From 9d79c3701e11dc0b562ae4eacd790a95ca61359f Mon Sep 17 00:00:00 2001 From: Elliot Voris Date: Tue, 24 Jan 2023 06:39:26 -0600 Subject: [PATCH] API documentation for Soroban-RPC (#253) * Adding the `/api` route to the config, and basic intro content For the moment, I'm essentially copying from the Google Doc. Signed-off-by: Elliot Voris * Adding content for the `getAccount` method Stubbing in basic file structure for all other methods. Signed-off-by: Elliot Voris * Expanding the methods in the sidebar by default Signed-off-by: Elliot Voris * Adding content for `getHealth` method Signed-off-by: Elliot Voris * Adding content for the `getHealth` method Signed-off-by: Elliot Voris * Adding content for the `getLatestLedger` method Signed-off-by: Elliot Voris * Adding content for the `getLedgerEntry` method Signed-off-by: Elliot Voris * Adding content for the `getContractData` method Signed-off-by: Elliot Voris * Adding content for the `getEvents` method Signed-off-by: Elliot Voris * Un-commenting a TODO item Signed-off-by: Elliot Voris * Adding content for the `getNetwork` method Signed-off-by: Elliot Voris * Adding content for the `getTransactionStatus` method Signed-off-by: Elliot Voris * Adding content for the `requestAirdrop` method Signed-off-by: Elliot Voris * Adding content for the `sendTransaction` method Signed-off-by: Elliot Voris * Adding content for `simulateTransaction` method Signed-off-by: Elliot Voris * Changing the appearance of a WIP note Signed-off-by: Elliot Voris * Breaking each of the intro sections into their own pages Signed-off-by: Elliot Voris * Hand-writing (most) of the sidebar It's easier to accomplish what I'm after this way. Or, at least, I figured out how to accomplish it this way first. Signed-off-by: Elliot Voris * Adding a "description" field to the intro category Signed-off-by: Elliot Voris * Fixing a link reference to `pagination` Signed-off-by: Elliot Voris * Capitalizing `Stellar` more consistently Signed-off-by: Elliot Voris * Update api/methods/getEvents.mdx Soroban-RPC supports querying up to 24 hours of recent ledgers. Co-authored-by: Paul Bellamy * Update api/methods/getTransactionStatus.mdx Co-authored-by: Paul Bellamy * `sendTransaction` *does* support all Stellar transactions. Signed-off-by: Elliot Voris * Removing the question about auto-calculating footprints Signed-off-by: Elliot Voris * All questions have been answered. Sweet!! Signed-off-by: Elliot Voris * Update api/pagination.mdx Co-authored-by: Paul Bellamy * Removing the "Outstanding Questions" page from the sidebar Signed-off-by: Elliot Voris * denoting `getNetwork` as a work-in-progress Signed-off-by: Elliot Voris * Moving the (WIP) methods to their own sidebar section Signed-off-by: Elliot Voris * Adding example request/response to the `getAccount` method Signed-off-by: Elliot Voris * Adding example request/response for the `getHealth` method Signed-off-by: Elliot Voris * Adding example request/response for the `sendTransaction` method Signed-off-by: Elliot Voris * Adding example request/response for the `getTransactionStatus` method Signed-off-by: Elliot Voris * Adding example request/response for the `getContractData` method Signed-off-by: Elliot Voris * Adding example request/response for the `getLedgerEntry` method Signed-off-by: Elliot Voris * Changing the `balance` field into a "TODO" Signed-off-by: Elliot Voris * Adding example request/response for the `getEvents` method Signed-off-by: Elliot Voris * Adding a note about the events that are returned Signed-off-by: Elliot Voris * Adding example request/response for the `simulateTransaction` method. Signed-off-by: Elliot Voris * Adding a pending example to the `getTransactionStatus` method Signed-off-by: Elliot Voris * Adding a more useful success example to `getTransactionStatus` Signed-off-by: Elliot Voris * Using a soroban transaction in the `sendTransaction` method Don't forget the footprint, friends! Signed-off-by: Elliot Voris * Removing the `getContractData` method This method is being deprecated. See stellar/soroban-tools#316 for more details. Please use the `getLedgerEntry` method instead. Signed-off-by: Elliot Voris Signed-off-by: Elliot Voris Co-authored-by: Paul Bellamy --- api/anti-goals.mdx | 14 +++ api/goals.mdx | 17 ++++ api/json-rpc.mdx | 16 ++++ api/methods/getAccount.mdx | 47 ++++++++++ api/methods/getEvents.mdx | 134 +++++++++++++++++++++++++++ api/methods/getHealth.mdx | 38 ++++++++ api/methods/getLatestLedger.mdx | 20 ++++ api/methods/getLedgerEntry.mdx | 103 ++++++++++++++++++++ api/methods/getNetwork.mdx | 19 ++++ api/methods/getTransactionStatus.mdx | 107 +++++++++++++++++++++ api/methods/requestAirdrop.mdx | 26 ++++++ api/methods/sendTransaction.mdx | 63 +++++++++++++ api/methods/simulateTransaction.mdx | 62 +++++++++++++ api/pagination.mdx | 26 ++++++ docusaurus.config.js | 33 +++++-- sidebarsApi.js | 58 ++++++++++++ 16 files changed, 774 insertions(+), 9 deletions(-) create mode 100644 api/anti-goals.mdx create mode 100644 api/goals.mdx create mode 100644 api/json-rpc.mdx create mode 100644 api/methods/getAccount.mdx create mode 100644 api/methods/getEvents.mdx create mode 100644 api/methods/getHealth.mdx create mode 100644 api/methods/getLatestLedger.mdx create mode 100644 api/methods/getLedgerEntry.mdx create mode 100644 api/methods/getNetwork.mdx create mode 100644 api/methods/getTransactionStatus.mdx create mode 100644 api/methods/requestAirdrop.mdx create mode 100644 api/methods/sendTransaction.mdx create mode 100644 api/methods/simulateTransaction.mdx create mode 100644 api/pagination.mdx create mode 100644 sidebarsApi.js diff --git a/api/anti-goals.mdx b/api/anti-goals.mdx new file mode 100644 index 00000000..d60010cd --- /dev/null +++ b/api/anti-goals.mdx @@ -0,0 +1,14 @@ +--- +sidebar_position: 1 +title: Anti-Goals +--- + +- Soroban-RPC is not a Horizon replacement. Horizon is better suited for historical reporting and analytics queries. Horizon is more concerned with Stellar Vanilla data. +- Soroban-RPC should not depend on Horizon. Horizon is expensive and difficult to run, so if Soroban-RPC depended on Horizon, it would inherit that. +- Soroban-RPC should also provide an API basis for infrastructure providers to implement, but not necessarily be an off-the-shelf solution for them. +- Soroban-RPC is not a reporting/analytics tool and does not provide thorough historical data querying. It does not provide any data aggregation, compilations, or multi-server coordination requests. +- Soroban-RPC does not target ultra-low latency. The latency should be low enough to build and submit successful soroban transactions, but supporting high-frequency traders is not the goal. + +:::note todo +TODO: Decide on direct exposure support (i.e. should we support exposing soroban-rpc directly to the internet?). People will do it regardless, so it might be best to... +::: diff --git a/api/goals.mdx b/api/goals.mdx new file mode 100644 index 00000000..95f02bab --- /dev/null +++ b/api/goals.mdx @@ -0,0 +1,17 @@ +--- +sidebar_position: 0 +title: Goals +--- + +Soroban-RPC can be simply described as a "live network gateway for Soroban." It provides information that the network currently has in its view (i.e. current state). It also has the ability to send a transaction to the network, and query the network for the status of previously sent transactions. It is meant to be simple, minimal, scalable, and familiar to blockchain developers from other ecosystems. + +Soroban-RPC should provide all the basic data that a dapp developer would need, provided they are: + +- Only interested in current state data, or are willing to ingest events into their own infrastructure to support reporting/analytics queries. + - Caveat: Soroban-RPC should provide enough data-retention to support reliable ingestion of events. +- Only interested in building and submitting Soroban transactions (not Stellar Vanilla). + +Soroban-RPC should support the developer from local testing (via the quickstart image), all the way through to production deployments. + +- This implies it should be easy to deploy, and easy to maintain; with low cost, and little "admin" needed. +- The developer should be able to simply run the quickstart docker image, and quickly be ready to serve requests without needing to set up or maintain dependent infrastructure. \ No newline at end of file diff --git a/api/json-rpc.mdx b/api/json-rpc.mdx new file mode 100644 index 00000000..e1e52184 --- /dev/null +++ b/api/json-rpc.mdx @@ -0,0 +1,16 @@ +--- +sidebar_position: 2 +title: JSON-RPC +--- + +Soroban-RPC will accept HTTP POST requests using the [JSON-RPC 2.0] specification. Errors are returned via the [jsonrpc error object] wherever possible (and makes sense). + +For production and other publicly-accessible instances, the JSON-RPC endpoint should be served over SSL on port 443, where possible, for security and ease of use. Though, soroban-rpc does not terminate ssl by itself, so will need a load-balancer or other service to terminate SSL for it. + +To interact with soroban-rpc from inside a JavaScript application, use the [js-soroban-client] library, which gives a convenient interface for the RPC methods. + +When XDR is passed as a parameter or returned, it is always a string encoded using standard base64. + +[JSON-RPC 2.0]: +[jsonrpc error object]: +[js-soroban-client]: diff --git a/api/methods/getAccount.mdx b/api/methods/getAccount.mdx new file mode 100644 index 00000000..2bf84831 --- /dev/null +++ b/api/methods/getAccount.mdx @@ -0,0 +1,47 @@ +--- +sidebar_position: 1 +--- + +Fetch a minimal set of current info about a Stellar account. + +Needed to get the current sequence number, and balance for the account so you can build a successful transaction. + +## Parameters + +- `
` - Address of the account to lookup + +## Returns + +- `` + - `id`: `
` + - `sequence`: `` - Current sequence number of the account + - TODO: Balances for the account (same format as in horizon) should be displayed + - TODO: signers/flags/thresholds/etc? + +## Examples + +### Request + +```json +{ + "jsonrpc": "2.0", + "id": 8675309, + "method": "getAccount", + "params": { + "address": "GAO2X2IGYZQEN7RJCA25MB2DM7AQA354AL77DJ2WL46Z6V5XRWVWV44Z" + } +} +``` + +### Response + +```json +{ + "jsonrpc": "2.0", + "id": 8675309, + "result": { + "id": "GAO2X2IGYZQEN7RJCA25MB2DM7AQA354AL77DJ2WL46Z6V5XRWVWV44Z", + "sequence": "703867830403072" + } +} +``` diff --git a/api/methods/getEvents.mdx b/api/methods/getEvents.mdx new file mode 100644 index 00000000..3b09c6d4 --- /dev/null +++ b/api/methods/getEvents.mdx @@ -0,0 +1,134 @@ +--- +sidebar_position: 6 +--- + +Clients can request a filtered list of events emitted by a given ledger range. Soroban-RPC will support querying within a maximum 24 hours of recent ledgers. + +Note, this could be used by the client to only prompt a refresh when there is a new ledger with relevant events. It should also be used by backend Dapp components to "ingest" events into their own database for querying and serving. + +If making multiple requests, clients should deduplicate any events received, based on the event's unique id field. This prevents double-processing in the case of duplicate events being received. + +By default soroban-rpc retains the most recent 24 hours of events. + +## Parameters + +- `startLedger`: `` - Stringified ledger sequence number to fetch events after (inclusive). +- `endLedger`: `` - Stringified ledger sequence number to fetch events before (inclusive). endLedger must be less than or equal to startLedger + 4320 (about 6 hours of ledgers). +- `filters`: `` - List of filters for the returned events. Events matching any of the filters are included. To match a filter, an event must match both a contractId and a topic. Maximum 5 filters are allowed per request. + - `type`: `<"system"|"contract">` - (optional) Filter to only system or only contract type events. If omitted, return all. + - `contractIds`: `` - (optional) List of contract ids to query for events. If omitted, return events for all contracts. Maximum 5 contract IDs are allowed per request. + - `topics`: `` - (optional) List of topic filters. If omitted, query for all events. If multiple filters are specified, events will be included if they match any of the filters. Maximum 5 filters are allowed per request. + - A `TopicFilter` is `SegmentMatcher[]` + - The list can be 1-4 `SegmentMatcher`s long. + - A `SegmentMatcher` is one of the following: + - For an exact segment match, a string containing base64-encoded ScVal + - For a wildcard single-segment match, the string "*", matches exactly one segment. + - Examples of matching token transfer events. Events are emitted here: [rs-soroban-env/event.rs at 924d86cacd58b8a162344bfe0ab37d9668f5d629]. I've decoded the base64-encoded ScVals for easier reading (both the symbols and addresses). In real usage, the `ScSymbol("transfer").toXdr().toString("base64")`, and `ScBinary(pubkeyBytes).toXdr().toString("base64")`, would be base64 encoded strings for exact matches. For example: + - `[ScSymbol("transfer"), "*", "*"]` + - Matches any token transfer events + - `[ScSymbol("transfer"), "*", "GABC...123"]` + - Matches any token transfer events to recipient: GABC...123 + - `[ScSymbol("transfer"), "GDEF...456", "GABC...123"]` + - Matches only token transfers from GDEF...456 to GABC...123. +- `pagination`: `` - See "[Pagination](../pagination)" + +## Returns + +- `` + - `events`: `` + - `ledger`: `` - String-ified sequence number of the ledger. + - `ledgerClosedAt`: `` - ISO8601 timestamp of the ledger closing time. + - `contractId`: `` - ID of the emitting contract. + - `id`: `` - Unique identifier for this event. + - The event's unique id field is based on a [`toid` from Horizon] as used in Horizon's /effects endpoint. + - https://github.com/stellar/go/blob/master/services/horizon/internal/db2/history/effect.go#L58 + - Specifically, it is a string containing: + - bigint(32 bit ledger sequence + 20 bit txn number + 12 bit operation) + `` + number for the event within the operation. + - For example: + - 1234-1 + - `pagingToken`: `` - Duplicate of `id` field, but in the standard place for pagination tokens. + - `topic`: `` - List containing the topic this event was emitted with. + - `value`: `` - List containing the topic this event was emitted with. + - `xdr`: `` - The emitted body value of the event (serialized in a base64 string). + +## Examples + +The following examples query the asset contract for the `native` token, searching for any transfers that take place (up to 100 results). + +:::note +The examples below only returns two transfer events that took place to/from the same account. In the real-world, you would expect far more results. +::: + +### Request + +```json +{ + "jsonrpc": "2.0", + "id": 8675309, + "method": "getEvents", + "params": { + "startLedger": "227000", + "endLedger": "230200", + "filters": [ + { + "type": "contract", + "contractIds": [ + "d93f5c7bb0ebc4a9c8f727c5cebc4e41194d38257e1d0d910356b43bfc528813" + ], + "topics": [ + ["AAAABQAAAAh0cmFuc2Zlcg==", "*", "*"] + ] + } + ], + "pagination": { + "limit": 100 + } + } +} +``` + +### Response + +```json +{ + "jsonrpc": "2.0", + "id": 8675309, + "result": [ + { + "type": "contract", + "ledger": "230010", + "ledgerClosedAt": "2023-01-23T18:54:41Z", + "contractId": "d93f5c7bb0ebc4a9c8f727c5cebc4e41194d38257e1d0d910356b43bfc528813", + "id": "0000987885427757056-0000000001", + "pagingToken": "0000987885427757056-0000000001", + "topic": [ + "AAAABQAAAAh0cmFuc2Zlcg==", + "AAAABAAAAAEAAAAAAAAAAgAAAAUAAAAHQWNjb3VudAAAAAAEAAAAAQAAAAgAAAAAHavpBsZgRv4pEDXWB0NnwQBvvAL/8adWXz2fV7eNq2o=", + "AAAABAAAAAEAAAAAAAAAAgAAAAUAAAAHQWNjb3VudAAAAAAEAAAAAQAAAAgAAAAAHavpBsZgRv4pEDXWB0NnwQBvvAL/8adWXz2fV7eNq2o=" + ], + "value": { + "xdr": "AAAABAAAAAEAAAAFAAAAAAABhqAAAAAAAAAAAA==" + } + }, + { + "type": "contract", + "ledger": "230170", + "ledgerClosedAt": "2023-01-23T19:08:37Z", + "contractId": "d93f5c7bb0ebc4a9c8f727c5cebc4e41194d38257e1d0d910356b43bfc528813", + "id": "0000988572622524416-0000000001", + "pagingToken": "0000988572622524416-0000000001", + "topic": [ + "AAAABQAAAAh0cmFuc2Zlcg==", + "AAAABAAAAAEAAAAAAAAAAgAAAAUAAAAHQWNjb3VudAAAAAAEAAAAAQAAAAgAAAAAHavpBsZgRv4pEDXWB0NnwQBvvAL/8adWXz2fV7eNq2o=", + "AAAABAAAAAEAAAAAAAAAAgAAAAUAAAAHQWNjb3VudAAAAAAEAAAAAQAAAAgAAAAAHavpBsZgRv4pEDXWB0NnwQBvvAL/8adWXz2fV7eNq2o=" + ], + "value": { + "xdr": "AAAABAAAAAEAAAAFAAAAAAAHoSAAAAAAAAAAAA==" + } + } + ] +} +``` + +[rs-soroban-env/event.rs at 924d86cacd58b8a162344bfe0ab37d9668f5d629]: +[`toid` from Horizon]: diff --git a/api/methods/getHealth.mdx b/api/methods/getHealth.mdx new file mode 100644 index 00000000..06a958d2 --- /dev/null +++ b/api/methods/getHealth.mdx @@ -0,0 +1,38 @@ +--- +sidebar_position: 2 +--- + +General node health check. + +## Parameters + +- None + +## Returns + +- `` + - `status`: "healthy" + +## Examples + +### Request + +```json +{ + "jsonrpc": "2.0", + "id": 8675309, + "method": "getHealth" +} +``` + +### Response + +```json +{ + "jsonrpc": "2.0", + "id": 8675309, + "result": { + "status": "healthy" + } +} +``` diff --git a/api/methods/getLatestLedger.mdx b/api/methods/getLatestLedger.mdx new file mode 100644 index 00000000..636f391e --- /dev/null +++ b/api/methods/getLatestLedger.mdx @@ -0,0 +1,20 @@ +--- +sidebar_position: 3 +--- + +:::note +The `getLatestLedger` method is still a work-in-progress. +::: + +For finding out the current latest known ledger of this node. This is a subset of the ledger info from Horizon. + +## Parameters + +- None + +## Returns + +- `` + - `id`: `` - hash of the latest ledger + - `protocolVersion`: `` + - `sequence`: `` diff --git a/api/methods/getLedgerEntry.mdx b/api/methods/getLedgerEntry.mdx new file mode 100644 index 00000000..f625ab92 --- /dev/null +++ b/api/methods/getLedgerEntry.mdx @@ -0,0 +1,103 @@ +--- +sidebar_position: 4 +--- + +For reading the current value of ledger entries directly. Allows you to directly inspect the _current state_ of a contract, a contract's code, or any other ledger entry. This is a backup way to access your contract data which may not be available via events or `simulateTransaction`. + +To fetch contract wasm byte-code, use the ContractCode ledger entry key. + +## Parameters + +- `key`: `` - The key of the ledger entry you wish to retrieve (serialized in a base64 string) + +## Return + +- `` + - `xdr`: `` - The current value of the given ledger entry (serialized in a base64 string) + - `lastModifiedLedgerSeq`: `` - The ledger number of the last time this entry was updated (optional) + - `latestLedger`: `` - The current latest ledger observed by the node when this response was generated. + +## Examples + +### Request + +```json +{ + "jsonrpc": "2.0", + "id": 8675309, + "method": "getLedgerEntry", + "params": { + "key": "AAAABhv6ziOnWcVRdGMZjtFKSWnLSndMp9JPVLLXxQqAvKqJAAAABQAAAAdDT1VOVEVSAA==" + } +} +``` + +### Response + +```json +{ + "jsonrpc": "2.0", + "id": 8675309, + "result": { + "xdr": "AAAABhv6ziOnWcVRdGMZjtFKSWnLSndMp9JPVLLXxQqAvKqJAAAABQAAAAdDT1VOVEVSAAAAAAEAAAAD", + "lastModifiedLedgerSeq": "164986", + "latestLedger": "179436" + } +} +``` + +### Generating `key` Parameters + +The example above is querying a deployment of the [`increment` example contract] to find out what value is stored in the `COUNTER` ledger entry. This value can be derived using the following code snippets. You should be able to extrapolate from the provided examples how to get `key` parameters for other types and values. + +#### Python + +:::note +If you are using the Python `stellar_sdk` to generate these keys, you will need to install the latest version of the `soroban` branch of the SDK. This can be done like so: + +```bash +pip install git+https://github.com/StellarCN/py-stellar-base.git@soroban +``` +::: + +```python +import stellar_sdk.xdr as xdr, stellar_sdk.soroban_types as soroban_types + +def get_ledger_key_symbol(contract_id, symbol_text): + ledger_key = xdr.ledger_key.LedgerKey( + type=xdr.ledger_entry_type.LedgerEntryType.CONTRACT_DATA, + contract_data=xdr.ledger_key_contract_data.LedgerKeyContractData( + contract_id=xdr.hash.Hash(bytes.fromhex(contract_id)), + key=soroban_types.Symbol(symbol_text)._to_xdr_sc_val() + ) + ) + return ledger_key.to_xdr() + +print(get_ledger_key_symbol( + "1bface23a759c5517463198ed14a4969cb4a774ca7d24f54b2d7c50a80bcaa89", + "COUNTER" +)) +``` + +#### JavaScript + +```js +const SorobanClient = require('soroban-client') +const xdr = SorobanClient.xdr + +const getLedgerKeySymbol = (contractId, symbolText) => { + const ledgerKey = xdr.LedgerKey.contractData( + new xdr.LedgerKeyContractData({ + contractId: Buffer.from(contractId, 'hex'), + key: xdr.ScVal.scvSymbol(symbolText) + }) + ) + return ledgerKey.toXDR('base64') +} +console.log(getLedgerKeySymbol( + '1bface23a759c5517463198ed14a4969cb4a774ca7d24f54b2d7c50a80bcaa89', + 'COUNTER' +)) +``` + +[`increment` example contract]: \ No newline at end of file diff --git a/api/methods/getNetwork.mdx b/api/methods/getNetwork.mdx new file mode 100644 index 00000000..5e997243 --- /dev/null +++ b/api/methods/getNetwork.mdx @@ -0,0 +1,19 @@ +--- +sidebar_position: 7 +--- + +:::note +The `getNetwork` method is still a work-in-progress. +::: + +General info about the currently configured network. + +## Parameters + +- None + +## Returns + +- `` + - `passphrase`: `` - Network passphrase configured + - `protocolVersion`: `` - Protocol version of the latest ledger diff --git a/api/methods/getTransactionStatus.mdx b/api/methods/getTransactionStatus.mdx new file mode 100644 index 00000000..bef1e68a --- /dev/null +++ b/api/methods/getTransactionStatus.mdx @@ -0,0 +1,107 @@ +--- +sidebar_position: 8 +--- + +:::note +The `getTransactionStatus` method is still a work-in-progress. +::: + +Clients will poll this to tell when the transaction has been completed. + +- TODO: Figure out result/error and how that fits into the jsonrpc response object +- TODO: Figure out return values for non-contract-invocation transactions + +## Parameters + +- `` - transaction hash to query + +## Returns + +- `` + - `id`: `` - hash of the transaction as a hex-encoded string + - `status`: `` - the current status of the transaction by hash, one of: + - pending + - success + - error + - `results`: `` - (optional) Will be present on completed successful transactions. + - xdr: ` - xdr-encoded return value of the contract call + - TODO: Anything else we should include? Gas spent? + - `envelopeXdr`: `` - (optional) A base64 encoded string of the raw TransactionEnvelope XDR struct for this transaction. + - `resultXdr`: `` - (optional) A base64 encoded string of the raw TransactionResult XDR struct for this transaction. + - `resultMetaXdr`: `` - (optional) A base64 encoded string of the raw TransactionResultMeta XDR struct for this transaction. + - `error`: `` - (optional) Will be present on failed transactions. + - `code`: `` - Short unique string representing the type of error + - `message`: `` - Human friendly summary of the error + - `data`: `` - (optional) More data related to the error if available + +## Examples + +### Request + +```json +{ + "jsonrpc": "2.0", + "id": 8675309, + "method": "getTransactionStatus", + "params": { + "hash": "97eb77da26e21d6a032fc0c311831d94a702ba336037da7c8a5ec51b3e39c485" + } +} +``` + +### Response + +#### Pending + +```json +{ + "jsonrpc": "2.0", + "id": 8675309, + "result": { + "id": "d70916f8b8aa55c13d5974a38e32a3efe440ef6870c0f0a07075d1c128d23698", + "status": "pending" + } +} +``` + +#### Success + +```json +{ + "jsonrpc": "2.0", + "id": 8675309, + "result": { + "id": "d70916f8b8aa55c13d5974a38e32a3efe440ef6870c0f0a07075d1c128d23698", + "status": "success", + "results": [ + { + "xdr": "AAAAAQAAAAY=" + } + ] + } +} +``` + +#### Error + +```json +{ + "jsonrpc": "2.0", + "id": 8675309, + "result": { + "id": "48dd243d4683745b7efa9f4fe6182f944b03cfd169135657e39c974e9b1fc50d", + "status": "error", + "error": { + "code": "tx_submission_failed", + "message": "Transaction submission failed", + "data": { + "envelope_xdr": "AAAAAgAAAAAdq+kGxmBG/ikQNdYHQ2fBAG+8Av/xp1ZfPZ9Xt42ragAAAGQAAoAp/////gAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAACgAAAAVoZWxsbwAAAAAAAAEAAAAHc29yb2JhbgAAAAAAAAAAAbeNq2oAAABAc6zcO/sTKyF26B1iJygLVrhhcVfK05rNW9gyeNwqSVeMFkHXpZ6D/6mqSB0KtvacxK4/VoiwWPrBQGPelnktBQ==", + "result_codes": { + "transaction": "tx_bad_seq" + }, + "result_xdr": "AAAAAAAAAAD////7AAAAAA==" + } + } + } +} +``` \ No newline at end of file diff --git a/api/methods/requestAirdrop.mdx b/api/methods/requestAirdrop.mdx new file mode 100644 index 00000000..a9c718c6 --- /dev/null +++ b/api/methods/requestAirdrop.mdx @@ -0,0 +1,26 @@ +--- +sidebar_position: 9 +--- + +:::note +The `requestAirdrop` method is still a work-in-progress. +::: + +Used outside pubnet to request some lumens from friendbot for a particular account. + +:::note +Maybe we could replace this with a 'friendbotUrl' field in `getNetwork` method? +::: + +## Parameters + +- `` - Account pubkey to fund + +## Returns + +- `` + - `transactionId`: `` - Transaction id of the transfer. + +## Errors + +- If this is pubnet (or friendbot is otherwise unavailable). diff --git a/api/methods/sendTransaction.mdx b/api/methods/sendTransaction.mdx new file mode 100644 index 00000000..cf968e4a --- /dev/null +++ b/api/methods/sendTransaction.mdx @@ -0,0 +1,63 @@ +--- +sidebar_position: 10 +--- + +Submit a real transaction to the Stellar network. This is the only way to make changes "on-chain". + +Unlike Horizon, this does not wait for transaction completion. It simply validates and enqueues the transaction. Clients should call getTransactionStatus to learn about transaction success/failure. + +This supports all transactions, not only smart contract-related transactions. + +- TODO: Decide on submit-vs-send for naming +- TODO: Add a return value that would represent the minimal amount of time the client would need to wait before calling getTransactionStatus + +## Parameters + +- `` - The signed transaction to broadcast (serialized in base64) + +## Returns + +- `` + - `id`: `` The transaction hash (in an hex-encoded string), and the initial transaction status, ("pending" or something), unless we can reject it immediately. + - `status`: `` - the current status of the transaction by hash, one of: + - `pending` + - `success` + - `error` + - `error`: `` - (optional) If the transaction was rejected immediately, this will be an error object. See [`getTransactionStatus`](getTransactionStatus) for format. + +## Possible Errors + +- TODO: Fewer than existing txsub as not waiting for completion + +## Examples + +### Request + +The following example request uses a transaction to invoke the `increment` method of the [`increment` example contract]. + +```json +{ + "jsonrpc": "2.0", + "id": 8675309, + "method": "sendTransaction", + "params": { + "transaction": "AAAAAgAAAAAdq+kGxmBG/ikQNdYHQ2fBAG+8Av/xp1ZfPZ9Xt42ragAAJxAAAoAqAAAAEAAAAAEAAAAAAAAAAAAAAABjzuUjAAAAAAAAAAEAAAAAAAAAGAAAAAAAAAACAAAABAAAAAEAAAAGAAAAIBv6ziOnWcVRdGMZjtFKSWnLSndMp9JPVLLXxQqAvKqJAAAABQAAAAlpbmNyZW1lbnQAAAAAAAACAAAABhv6ziOnWcVRdGMZjtFKSWnLSndMp9JPVLLXxQqAvKqJAAAAAwAAAAMAAAAH1CpZRz0BSN27PmqtsmBhv+AAJJwHgmrvJNPrHRAl9l8AAAABAAAABhv6ziOnWcVRdGMZjtFKSWnLSndMp9JPVLLXxQqAvKqJAAAABQAAAAdDT1VOVEVSAAAAAAAAAAABt42ragAAAECMEuou2IDSTtqTu62ZOBkJZJc3aYL10ZlsRg9CMXXYwk1Lv6c23Iy3HawBPKOE2DQKhbi49cdPkMI5n/QtnkgE" + } +} +``` + +### Response + +```json +{ + "jsonrpc": "2.0", + "id": 8675309, + "result": { + "id": "d70916f8b8aa55c13d5974a38e32a3efe440ef6870c0f0a07075d1c128d23698", + "status": "pending", + "error": null + } +} +``` + +[`increment` example contract]: \ No newline at end of file diff --git a/api/methods/simulateTransaction.mdx b/api/methods/simulateTransaction.mdx new file mode 100644 index 00000000..38d73f4c --- /dev/null +++ b/api/methods/simulateTransaction.mdx @@ -0,0 +1,62 @@ +--- +sidebar_position: 11 +--- + +Submit a trial contract invocation to get back return values, expected ledger footprint, and expected costs. + +## Parameters + +- `` - The transaction to be simulated (serialized in base64) + +## Returns + +- `` + - `cost`: `` - Information about the fees expected, instructions used, etc. + - `cpuInsns`: `` - Stringified-number of the total cpu instructions consumed by this transaction + - `memBytes`: `` - Stringified-number of the total memory bytes allocated by this transaction + - `footprint`: `` -Array of ledger keys expected to be written by this transaction. (serialized in base64) + - `results`: `` - If error is present then results will not be in the response + - `xdr`: `` - (optional) Only present on success. xdr-encoded return value of the contract call + - `latestLedger`: `` - Stringified-number of the current latest ledger observed by the node when this response was generated. + - `error`: `` - (optional) only present if the transaction failed. This field will include more details from `stellar-core` about why the invoke host function call failed. + +## Examples + +The example transaction below invokes the `increment` function from the [`increment` example contract]. + +### Request + +```json +{ + "jsonrpc": "2.0", + "id": 8675309, + "method": "simulateTransaction", + "params": { + "transaction": "AAAAAgAAAAAdq+kGxmBG/ikQNdYHQ2fBAG+8Av/xp1ZfPZ9Xt42ragAAJxAAAAAAAAAAAgAAAAEAAAAAAAAAAAAAAABjzuFcAAAAAAAAAAEAAAAAAAAAGAAAAAAAAAACAAAABAAAAAEAAAAGAAAAIBv6ziOnWcVRdGMZjtFKSWnLSndMp9JPVLLXxQqAvKqJAAAABQAAAAlpbmNyZW1lbnQAAAAAAAAAAAAAAAAAAAAAAAAA" + } +} +``` + +### Response + +```json +{ + "jsonrpc": "2.0", + "id": 8675309, + "result": { + "results": [ + { + "xdr": "AAAAAQAAAAY=" + } + ], + "footprint": "AAAAAgAAAAYb+s4jp1nFUXRjGY7RSklpy0p3TKfST1Sy18UKgLyqiQAAAAMAAAADAAAAB9QqWUc9AUjduz5qrbJgYb/gACScB4Jq7yTT6x0QJfZfAAAAAQAAAAYb+s4jp1nFUXRjGY7RSklpy0p3TKfST1Sy18UKgLyqiQAAAAUAAAAHQ09VTlRFUgA=", + "cost": { + "cpuInsns": "163642", + "memBytes": "1506" + }, + "latestLedger": "230473" + } +} +``` + +[`increment` example contract]: \ No newline at end of file diff --git a/api/pagination.mdx b/api/pagination.mdx new file mode 100644 index 00000000..c6b3026f --- /dev/null +++ b/api/pagination.mdx @@ -0,0 +1,26 @@ +--- +sidebar_position: 3 +title: Pagination +--- + +Pagination in soroban-rpc is similar to pagination in Horizon. + +For methods which support it, the pagination arguments are passed as a final object argument with two values: + +- `cursor`: string - (optional) A string ID that points to a specific location in a collection of responses and is pulled from the paging_token value of a record. +- `limit`: number - (optional) The maximum number of records returned. The limit can range from 1 to 200 - an upper limit that is hardcoded in Soroban-RPC for performance reasons. If this argument isn't designated, it defaults to 10. + +For example, calling a method with pagination parameter set: + +```json +{ + "jsonrpc": "2.0", + "Id": "1", + "method": "exampleMethod", + "params": [ + "other", + "arguments", + { "cursor": "1234-1", "limit": 100 } + ] +} +``` diff --git a/docusaurus.config.js b/docusaurus.config.js index 001b9686..a113f44d 100644 --- a/docusaurus.config.js +++ b/docusaurus.config.js @@ -28,6 +28,15 @@ const config = { anonymizeIP: true, }, ], + [ + '@docusaurus/plugin-content-docs', + { + id: 'api', + path: 'api', + routeBasePath: 'api', + sidebarPath: require.resolve('./sidebarsApi.js'), + }, + ], require('./src/dev-server-plugin'), require('./src/analytics-module') ], @@ -53,10 +62,10 @@ const config = { /** @type {import('@docusaurus/preset-classic').ThemeConfig} */ ({ image: 'img/meta.png', - docs: { - sidebar: { - autoCollapseCategories: false - } + docs: { + sidebar: { + autoCollapseCategories: false + } }, navbar: { logo: { @@ -67,18 +76,24 @@ const config = { }, items: [ { - to: '/docs', - label: 'Docs', + to: '/docs', + label: 'Docs', position: 'left' }, + { + to: '/api', + label: 'API', + position: 'left', + docsPluginId: 'api' + }, { href: 'https://quest.stellar.org/live', label: 'Stellar Quest', position: 'left', }, // { - // href: 'https://github.com/stellar/sorobanathon', - // label: 'Sorobanathon', + // href: 'https://github.com/stellar/sorobanathon', + // label: 'Sorobanathon', // position: 'left' // }, { @@ -122,7 +137,7 @@ const config = { }, // { // label: 'Sorobanathon', - // href: 'https://github.com/stellar/sorobanathon', + // href: 'https://github.com/stellar/sorobanathon', // }, ], }, diff --git a/sidebarsApi.js b/sidebarsApi.js new file mode 100644 index 00000000..c419cb69 --- /dev/null +++ b/sidebarsApi.js @@ -0,0 +1,58 @@ +module.exports = { + apiSidebar: [ + { + type: 'category', + label: 'Introduction', + collapsible: true, + collapsed: false, + link: { + type: 'generated-index', + title: 'Introduction', + description: 'A public discussion about the design of soroban-rpc.', + slug: '/', + }, + items: [ + 'goals', + 'anti-goals', + 'json-rpc', + 'pagination', + ], + }, + { + type: 'category', + label: 'Request/Response Methods', + collapsible: true, + collapsed: false, + link: { + type: 'generated-index', + title: 'Request/Response Methods', + slug: 'methods', + }, + items: [ + 'methods/getAccount', + 'methods/getHealth', + 'methods/getLedgerEntry', + 'methods/getEvents', + 'methods/getTransactionStatus', + 'methods/sendTransaction', + 'methods/simulateTransaction', + ], + }, + { + type: 'category', + label: 'Incomplete Methods', + collapsible: true, + collapsed: false, + link: { + type: 'generated-index', + title: 'Incomplete Methods', + slug: 'incomplete-methods', + }, + items: [ + 'methods/getLatestLedger', + 'methods/getNetwork', + 'methods/requestAirdrop', + ], + }, + ], +}; \ No newline at end of file