diff --git a/tools/rosetta/CHANGELOG.md b/tools/rosetta/CHANGELOG.md index 254759f5d134..788db8861dc3 100644 --- a/tools/rosetta/CHANGELOG.md +++ b/tools/rosetta/CHANGELOG.md @@ -37,8 +37,8 @@ Ref: https://keepachangelog.com/en/1.0.0/ ## [Unreleased] ### Improvements - -* [#13832](https://github.com/cosmos/cosmos-sdk/pull/13832) Correctly populates rosetta's `/network/status` endpoint response. Roseta data api is divided into its own go files (account, block, mempool, network). +* [#14061](https://github.com/cosmos/cosmos-sdk/pull/14061) Adds openapi specification. +* [#13832](https://github.com/cosmos/cosmos-sdk/pull/13832) Correctly populates rosetta's `/network/status` endpoint response. Rosetta's data api is divided into its own go files (account, block, mempool, network). ### Bug Fixes diff --git a/tools/rosetta/lib/internal/service/account.go b/tools/rosetta/lib/internal/service/account.go index 5c3ff3eb59c9..5636a35b0261 100644 --- a/tools/rosetta/lib/internal/service/account.go +++ b/tools/rosetta/lib/internal/service/account.go @@ -55,6 +55,6 @@ func (on OnlineNetwork) AccountBalance(ctx context.Context, request *types.Accou // AccountsCoins - relevant only for UTXO based chain // see https://www.rosetta-api.org/docs/AccountApi.html#accountcoins -func (o OnlineNetwork) AccountCoins(_ context.Context, _ *types.AccountCoinsRequest) (*types.AccountCoinsResponse, *types.Error) { +func (on OnlineNetwork) AccountCoins(_ context.Context, _ *types.AccountCoinsRequest) (*types.AccountCoinsResponse, *types.Error) { return nil, errors.ToRosetta(errors.ErrOffline) } diff --git a/tools/rosetta/openapi/index.html b/tools/rosetta/openapi/index.html new file mode 100644 index 000000000000..c21b2f41f2d4 --- /dev/null +++ b/tools/rosetta/openapi/index.html @@ -0,0 +1,27 @@ + + + + + + + Rosetta API + + + + + + +
+ + + + diff --git a/tools/rosetta/openapi/openapi.yaml b/tools/rosetta/openapi/openapi.yaml new file mode 100644 index 000000000000..57e39563dea6 --- /dev/null +++ b/tools/rosetta/openapi/openapi.yaml @@ -0,0 +1,1227 @@ +openapi: 3.0.0 +info: + title: Rosetta API + description: | + version: "main" + license: + name: Apache 2.0 + url: https://github.com/cosmos/cosmos-sdk/blob/main/LICENSE +servers: + - url: http://localhost:8080 + description: Interact with the rosetta API locally on your device +tags: + - name: Account + description: Account endpoints are used to fetch the state of an account. + - name: Block + description: Block endpoints are used to access any data stored in a block + - name: Construction + description: Construction endpoints are used to create and broadcast transactions. + - name: Mempool + description: Mempool endpoints are used to fetch any data stored in the mempool. + - name: Network + description: Network endpoints are used when first connecting to a Rosetta endpoint to determine which network and sub-networks are supported. +paths: + /account/balance: + post: + summary: Get an array of all AccountBalances for an AccountIdentifier and the BlockIdentifier at which the balance lookup was performed. + tags: + - Account + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/AccountBalanceRequest" + responses: + "200": + description: Empty + content: + application/json: + schema: + $ref: "#/components/schemas/AccountBalanceResponse" + "500": + description: Error + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + /account/coins: + post: + summary: Get an array of all unspent coins for an AccountIdentifier and the BlockIdentifier at which the lookup was performed. + tags: + - Account + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/AccountCoinsRequest" + responses: + "200": + description: Empty + content: + application/json: + schema: + $ref: "#/components/schemas/AccountCoinsRequest" + "500": + description: Error + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + /block: + post: + summary: Get a block by its Block Identifier. + tags: + - Block + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/BlockRequest" + responses: + "200": + description: Empty + content: + application/json: + schema: + $ref: "#/components/schemas/BlockResponse" + "500": + description: Error + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + /block/transaction: + post: + summary: Get a transaction in a block by its Transaction Identifier. + tags: + - Block + requestBody: + content: + application/json: + schema: + $ref: "#/components/schemas/BlockTransactionRequest" + responses: + "200": + description: Empty + content: + application/json: + schema: + $ref: "#/components/schemas/BlockTransactionResponse" + "500": + description: Error + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + /mempool: + post: + summary: Get all Transaction Identifiers in the mempool + tags: + - Mempool + requestBody: + content: + application/json: + schema: + $ref: "#/components/schemas/MempoolRequest" + responses: + "200": + description: Empty + content: + application/json: + schema: + $ref: "#/components/schemas/MempoolResponse" + "500": + description: Error + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + /mempool/transaction: + post: + summary: Get a transaction in the mempool by its Transaction Identifier. + tags: + - Mempool + requestBody: + content: + application/json: + schema: + $ref: "#/components/schemas/MempoolTransactionRequest" + responses: + "200": + description: Empty + content: + application/json: + schema: + $ref: "#/components/schemas/MempoolTransactionResponse" + "500": + description: Error + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + /network/list: + post: + summary: Returns a list of NetworkIdentifiers that the Rosetta server supports. + tags: + - Network + requestBody: + content: + application/json: + schema: + $ref: "#/components/schemas/NetworkListRequest" + responses: + "200": + description: Empty + content: + application/json: + schema: + $ref: "#/components/schemas/NetworkListResponse" + "500": + description: Error + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + /network/options: + post: + summary: Returns the version information and allowed network-specific types for a NetworkIdentifier. + tags: + - Network + requestBody: + content: + application/json: + schema: + $ref: "#/components/schemas/NetworkOptionsRequest" + responses: + "200": + description: Empty + content: + application/json: + schema: + $ref: "#/components/schemas/NetworkOptionsResponse" + "500": + description: Error + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + /network/status: + post: + summary: Returns the current status of the network requested. + tags: + - Network + requestBody: + content: + application/json: + schema: + $ref: "#/components/schemas/NetworkStatusRequest" + responses: + "200": + description: Empty + content: + application/json: + schema: + $ref: "#/components/schemas/NetworkStatusResponse" + "500": + description: Error + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + /construction/combine: + post: + summary: Combine creates a network-specific transaction from an unsigned transaction and an array of provided signatures. + tags: + - Construction + requestBody: + content: + application/json: + schema: + $ref: "#/components/schemas/ConstructionCombineRequest" + responses: + "200": + description: Empty + content: + application/json: + schema: + $ref: "#/components/schemas/ConstructionCombineResponse" + "500": + description: Error + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + /construction/derive: + post: + summary: Derive returns the AccountIdentifier associated with a public key. + tags: + - Construction + requestBody: + content: + application/json: + schema: + $ref: "#/components/schemas/ConstructionDeriveRequest" + responses: + "200": + description: Empty + content: + application/json: + schema: + $ref: "#/components/schemas/ConstructionDeriveResponse" + "500": + description: Error + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + /construction/hash: + post: + summary: Derive returns the AccountIdentifier associated with a public key. + tags: + - Construction + requestBody: + content: + application/json: + schema: + $ref: "#/components/schemas/ConstructionHashRequest" + responses: + "200": + description: Empty + content: + application/json: + schema: + $ref: "#/components/schemas/ConstructionHashResponse" + "500": + description: Error + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + /construction/metadata: + post: + summary: Get any information required to construct a transaction for a specific network. + tags: + - Construction + requestBody: + content: + application/json: + schema: + $ref: "#/components/schemas/ConstructionMetadataRequest" + responses: + "200": + description: Empty + content: + application/json: + schema: + $ref: "#/components/schemas/ConstructionMetadataResponse" + "500": + description: Error + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + /construction/parse: + post: + summary: Parse is called on both unsigned and signed transactions to understand the intent of the formulated transaction. + tags: + - Construction + requestBody: + content: + application/json: + schema: + $ref: "#/components/schemas/ConstructionParseRequest" + responses: + "200": + description: Empty + content: + application/json: + schema: + $ref: "#/components/schemas/ConstructionParseResponse" + "500": + description: Error + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + /construction/payloads: + post: + summary: Payloads is called with an array of operations and the response from `/construction/metadata`. + tags: + - Construction + requestBody: + content: + application/json: + schema: + $ref: "#/components/schemas/ConstructionPayloadsRequest" + responses: + "200": + description: Empty + content: + application/json: + schema: + $ref: "#/components/schemas/ConstructionPayloadsResponse" + "500": + description: Error + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + /construction/preprocess: + post: + summary: Preprocess is called prior to /construction/payloads to construct a request for any metadata that is needed for transaction construction given. + tags: + - Construction + requestBody: + content: + application/json: + schema: + $ref: "#/components/schemas/ConstructionPreprocessRequest" + responses: + "200": + description: Empty + content: + application/json: + schema: + $ref: "#/components/schemas/ConstructionPreprocessResponse" + "500": + description: Error + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + /construction/submit: + post: + summary: Submit a pre-signed transaction to the node. This call should not block on the transaction being included in a block. + tags: + - Construction + requestBody: + content: + application/json: + schema: + $ref: "#/components/schemas/ConstructionSubmitRequest" + responses: + "200": + description: Empty + content: + application/json: + schema: + $ref: "#/components/schemas/ConstructionSubmitResponse" + "500": + description: Error + content: + application/json: + schema: + $ref: "#/components/schemas/Error" +components: + schemas: + Error: + type: object + required: + - code + - message + - retriable + properties: + code: + type: integer + example: 12 + message: + type: string + example: "" + description: + type: string + example: "" + retriable: + type: boolean + example: true + details: + type: object + + BlockIdentifier: + type: object + required: + - index + - hash + properties: + index: + type: integer + example: 13342095 + hash: + type: string + example: "F7EB233A45FCB1B42457F1ACF50C2574AE14731D0B31BBD5D6B199868023119D" + PartialBlockIdentifier: + type: object + properties: + index: + type: integer + example: 13342095 + hash: + type: string + example: "F7EB233A45FCB1B42457F1ACF50C2574AE14731D0B31BBD5D6B199868023119D" + Block: + type: object + required: + - block_identifier + - parent_block_identifier + - timestamp + - transactions + properties: + block_identifier: + $ref: "#/components/schemas/BlockIdentifier" + parent_block_identifier: + $ref: "#/components/schemas/BlockIdentifier" + timestamp: + type: integer + transactions: + type: array + items: + $ref: "#/components/schemas/Transaction" + metadata: + type: object + + OperationStatus: + type: object + required: + - status + - successful + properties: + status: + type: string + successful: + type: boolean + OperationIdentifier: + type: object + required: + - index + properties: + index: + type: integer + network_index: + type: integer + Operation: + type: object + required: + - operation_identifier + - type + properties: + operation_identifier: + $ref: "#/components/schemas/OperationIdentifier" + related_operations: + type: array + items: + $ref: "#/components/schemas/OperationIdentifier" + type: + type: string + status: + type: string + account: + $ref: "#/components/schemas/AccountIdentifier" + amount: + $ref: "#/components/schemas/Amount" + coin_change: + $ref: "#/components/schemas/CoinChange" + metadata: + type: object + + Direction: + type: string + enum: + - forward + - backward + TransactionIdentifier: + type: object + required: + - hash + properties: + hash: + type: string + RelatedTransaction: + type: object + required: + - transaction_identifier + - direction + properties: + network_identifier: + $ref: "#/components/schemas/NetworkIdentifier" + transaction_identifier: + $ref: "#/components/schemas/TransactionIdentifier" + direction: + $ref: "#/components/schemas/Direction" + + Transaction: + type: object + required: + - transaction_identifier + - operations + properties: + transaction_identifier: + $ref: "#/components/schemas/TransactionIdentifier" + operations: + type: array + items: + $ref: "#/components/schemas/Operation" + related_transactions: + type: array + items: + $ref: "#/components/schemas/RelatedTransaction" + metadata: + type: object + + ExemptionType: + type: string + enum: + - greater_or_equal + - less_or_equal + - dynamic + BalanceExemption: + type: object + properties: + sub_account_address: + type: string + currency: + $ref: "#/components/schemas/Currency" + exemption_type: + $ref: "#/components/schemas/ExemptionType" + Currency: + type: object + required: + - symbol + - decimals + properties: + symbol: + type: string + example: "ATOM" + decimals: + type: integer + example: 8 + metadata: + type: object + Amount: + type: object + required: + - value + - currency + properties: + value: + type: string + currency: + $ref: "#/components/schemas/Currency" + metadata: + type: object + + SubNetworkIdentifier: + type: object + required: + - network + properties: + network: + type: string + metadata: + type: object + NetworkIdentifier: + type: object + required: + - blockchain + - network + properties: + blockchain: + type: string + example: "Cosmos" + network: + type: string + example: "cosmoshub-4" + sub_network_identifier: + $ref: "#/components/schemas/SubNetworkIdentifier" + + SubAccount: + type: object + required: + - address + properties: + address: + type: string + example: "cosmos149hrsy9sze6635a29p7tp33sep35zxqfaknypj" + metadata: + type: object + AccountIdentifier: + type: object + required: + - address + properties: + address: + type: string + sub_account: + $ref: "#/components/schemas/SubAccount" + metadata: + type: object + + CoinAction: + type: string + enum: + - coin_created + - coin_spent + CoinChange: + type: object + required: + - coin_action + - coin_identifier + properties: + coin_identifier: + $ref: "#/components/schemas/CoinIdentifier" + coin_action: + $ref: "#/components/schemas/CoinAction" + CoinIdentifier: + type: object + required: + - identifier + properties: + identifier: + type: string + Coin: + type: object + properties: + coin_identifier: + $ref: "#/components/schemas/CoinIdentifier" + amount: + $ref: "#/components/schemas/Amount" + + Case: + type: string + enum: + - upper_case + - lower_case + - case_sensitive + - null + Version: + type: object + required: + - rosetta_version + - node_version + properties: + rosetta_version: + type: string + node_version: + type: string + middleware_version: + type: string + metadata: + type: object + Allow: + type: object + required: + - operation_statuses + - operation_types + - errors + - historical_balance_lookup + - call_methods + - balance_exemptions + - mempool_coins + properties: + operation_statuses: + type: array + items: + $ref: "#/components/schemas/OperationStatus" + operation_types: + type: array + items: + type: string + errors: + type: array + items: + $ref: "#/components/schemas/Error" + historical_balance_lookup: + type: boolean + timestamp_start_index: + type: integer + call_methods: + type: array + items: + type: string + balance_exemptions: + $ref: "#/components/schemas/BalanceExemption" + mempool_coins: + type: boolean + block_hash_case: + $ref: "#/components/schemas/Case" + transaction_hash_case: + $ref: "#/components/schemas/Case" + + SyncStatus: + type: object + properties: + current_index: + type: integer + target_index: + type: integer + stage: + type: string + synced: + type: boolean + + Peer: + type: object + required: + - peer_id + properties: + peer_id: + type: string + metadata: + type: object + + CurveType: + type: string + enum: + - secp256k1 + - secp256r1 + - edwards25519 + - tweedle + - pallas + PublicKey: + type: object + required: + - hex_bytes + - curve_type + properties: + hex_bytes: + type: string + curve_type: + $ref: "#/components/schemas/CurveType" + SignatureType: + type: string + enum: + - ecdsa + - ecdsa_recovery + - ed25519 + - schnorr_1 + - schnorr_poseidon + SigningPayload: + type: object + required: + - hex_bytes + properties: + address: + type: string + account_identifier: + $ref: "#/components/schemas/AccountIdentifier" + hex_bytes: + type: string + signature_type: + $ref: "#/components/schemas/SignatureType" + Signature: + type: object + required: + - signing_payload + - public_key + - signature_type + - hex_bytes + properties: + signing_payload: + $ref: "#/components/schemas/SigningPayload" + public_key: + $ref: "#/components/schemas/PublicKey" + signature_type: + $ref: "#/components/schemas/SignatureType" + hex_bytes: + type: string + + + AccountBalanceRequest: + type: object + required: + - network_identifier + - account_identifier + properties: + network_identifier: + $ref: "#/components/schemas/NetworkIdentifier" + account_identifier: + $ref: "#/components/schemas/AccountIdentifier" + block_identifier: + $ref: "#/components/schemas/PartialBlockIdentifier" + currency: + $ref: "#/components/schemas/Currency" + AccountBalanceResponse: + type: object + required: + - block_identifier + - balances + properties: + block_identifier: + $ref: "#/components/schemas/BlockIdentifier" + balances: + type: array + items: + $ref: "#/components/schemas/Amount" + metadata: + type: object + AccountCoinsRequest: + type: object + required: + - network_identifier + - account_identifier + - include_mempool + properties: + network_identifier: + $ref: "#/components/schemas/NetworkIdentifier" + account_identifier: + $ref: "#/components/schemas/AccountIdentifier" + include_mempool: + type: boolean + currencies: + type: array + items: + $ref: "#/components/schemas/Currency" + AccountCoinsResponse: + type: object + required: + - block_identifier + - coins + properties: + block_identifier: + $ref: "#/components/schemas/BlockIdentifier" + coins: + type: array + items: + $ref: "#/components/schemas/Coin" + metadata: + type: object + + BlockRequest: + type: object + required: + - network_identifier + - block_identifier + properties: + network_identifier: + $ref: "#/components/schemas/NetworkIdentifier" + block_identifier: + $ref: "#/components/schemas/PartialBlockIdentifier" + BlockResponse: + type: object + properties: + block: + $ref: "#/components/schemas/Block" + other_transactions: + type: array + items: + $ref: "#/components/schemas/TransactionIdentifier" + BlockTransactionRequest: + type: object + required: + - network_identifier + - block_identifier + - transaction_identifier + properties: + network_identifier: + $ref: "#/components/schemas/NetworkIdentifier" + block_identifier: + $ref: "#/components/schemas/BlockIdentifier" + transaction_identifier: + $ref: "#/components/schemas/TransactionIdentifier" + BlockTransactionResponse: + type: object + required: + - transaction + properties: + transaction: + $ref: "#/components/schemas/Transaction" + + MempoolRequest: + type: object + required: + - network_identifier + properties: + network_identifier: + $ref: "#/components/schemas/NetworkIdentifier" + metadata: + type: object + MempoolResponse: + type: object + required: + - transaction_identifiers + properties: + transaction_identifiers: + type: array + items: + $ref: "#/components/schemas/TransactionIdentifier" + MempoolTransactionRequest: + type: object + required: + - network_identifier + - transaction_identifier + properties: + network_identifier: + $ref: "#/components/schemas/NetworkIdentifier" + transaction_identifier: + $ref: "#/components/schemas/TransactionIdentifier" + MempoolTransactionResponse: + type: object + required: + - transaction + properties: + transaction: + $ref: "#/components/schemas/TransactionIdentifier" + metadata: + type: object + + NetworkListRequest: + type: object + properties: + metadata: + type: object + NetworkListResponse: + type: object + required: + - network_identifiers + properties: + network_identifiers: + type: array + items: + $ref: "#/components/schemas/NetworkIdentifier" + NetworkOptionsRequest: + type: object + required: + - network_identifier + properties: + network_identifier: + $ref: "#/components/schemas/NetworkIdentifier" + metadata: + type: object + NetworkOptionsResponse: + type: object + required: + - version + - allow + properties: + version: + $ref: "#/components/schemas/Version" + allow: + $ref: "#/components/schemas/Allow" + NetworkStatusRequest: + type: object + required: + - network_identifier + properties: + network_identifier: + $ref: "#/components/schemas/NetworkIdentifier" + metadata: + type: object + NetworkStatusResponse: + type: object + required: + - current_block_identifier + - current_block_timestamp + - genesis_block_identifier + properties: + current_block_identifier: + $ref: "#/components/schemas/BlockIdentifier" + current_block_timestamp: + type: integer + genesis_block_identifier: + $ref: "#/components/schemas/BlockIdentifier" + oldest_block_identifier: + $ref: "#/components/schemas/BlockIdentifier" + sync_status: + $ref: "#/components/schemas/SyncStatus" + peers: + type: array + items: + $ref: "#/components/schemas/Peer" + ConstructionCombineRequest: + type: object + required: + - network_identifier + - unsigned_transaction + - signatures + properties: + network_identifier: + $ref: "#/components/schemas/NetworkIdentifier" + unsigned_transaction: + type: string + signatures: + type: array + items: + $ref: "#/components/schemas/Signature" + ConstructionCombineResponse: + type: object + required: + - signed_transaction + properties: + signed_transaction: + type: string + ConstructionDeriveRequest: + type: object + required: + - network_identifier + - public_key + properties: + network_identifier: + $ref: "#/components/schemas/NetworkIdentifier" + public_key: + $ref: "#/components/schemas/PublicKey" + metadata: + type: object + ConstructionDeriveResponse: + type: object + properties: + address: + type: string + account_identifier: + $ref: "#/components/schemas/AccountIdentifier" + metadata: + type: object + ConstructionHashRequest: + type: object + required: + - network_identifier + - signed_transaction + properties: + network_identifier: + $ref: "#/components/schemas/NetworkIdentifier" + signed_transaction: + type: string + ConstructionHashResponse: + type: object + required: + - transaction_identifier + properties: + transaction_identifier: + $ref: "#/components/schemas/TransactionIdentifier" + metadata: + type: object + ConstructionMetadataRequest: + type: object + required: + - network_identifier + properties: + network_identifier: + $ref: "#/components/schemas/NetworkIdentifier" + options: + type: object + public_keys: + type: array + items: + $ref: "#/components/schemas/PublicKey" + ConstructionMetadataResponse: + type: object + properties: + metadata: + type: object + suggested_fee: + type: array + items: + $ref: "#/components/schemas/Amount" + ConstructionParseRequest: + type: object + required: + - network_identifier + - signed + - transaction + properties: + network_identifier: + $ref: "#/components/schemas/NetworkIdentifier" + signed: + type: boolean + transaction: + type: string + ConstructionParseResponse: + type: object + required: + - operations + properties: + operations: + type: array + items: + $ref: "#/components/schemas/Operation" + signers: + type: array + items: + type: string + account_identifier_signers: + type: array + items: + $ref: "#/components/schemas/AccountIdentifier" + metadata: + type: object + ConstructionPayloadsRequest: + type: object + required: + - network_identifier + - operations + properties: + network_identifier: + $ref: "#/components/schemas/NetworkIdentifier" + operations: + type: array + items: + $ref: "#/components/schemas/Operation" + metadata.: + type: object + public_keys: + type: array + items: + $ref: "#/components/schemas/PublicKey" + ConstructionPayloadsResponse: + type: object + required: + - unsigned_transaction + - payloads + properties: + unsigned_transaction: + type: string + payloads: + type: array + items: + $ref: "#/components/schemas/SigningPayload" + ConstructionPreprocessRequest: + type: object + required: + - network_identifier + - operations + properties: + network_identifier: + $ref: "#/components/schemas/NetworkIdentifier" + operations: + type: array + items: + $ref: "#/components/schemas/Operation" + metadata: + type: object + ConstructionPreprocessResponse: + type: object + properties: + options: + type: object + required_public_keys: + type: array + items: + $ref: "#/components/schemas/AccountIdentifier" + ConstructionSubmitRequest: + type: object + required: + - network_identifier + - signed_transaction + properties: + network_identifier: + $ref: "#/components/schemas/NetworkIdentifier" + signed_transaction: + type: string + + ConstructionSubmitResponse: + type: object + required: + - transaction_identifier + properties: + transaction_identifier: + $ref: "#/components/schemas/TransactionIdentifier" + metadata: + type: object + + + + + + + +