Skip to content
This repository has been archived by the owner on Aug 21, 2024. It is now read-only.

Commit

Permalink
API documentation for Soroban-RPC (#253)
Browse files Browse the repository at this point in the history
* 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 <[email protected]>

* Adding content for the `getAccount` method

Stubbing in basic file structure for all other methods.

Signed-off-by: Elliot Voris <[email protected]>

* Expanding the methods in the sidebar by default

Signed-off-by: Elliot Voris <[email protected]>

* Adding content for `getHealth` method

Signed-off-by: Elliot Voris <[email protected]>

* Adding content for the `getHealth` method

Signed-off-by: Elliot Voris <[email protected]>

* Adding content for the `getLatestLedger` method

Signed-off-by: Elliot Voris <[email protected]>

* Adding content for the `getLedgerEntry` method

Signed-off-by: Elliot Voris <[email protected]>

* Adding content for the `getContractData` method

Signed-off-by: Elliot Voris <[email protected]>

* Adding content for the `getEvents` method

Signed-off-by: Elliot Voris <[email protected]>

* Un-commenting a TODO item

Signed-off-by: Elliot Voris <[email protected]>

* Adding content for the `getNetwork` method

Signed-off-by: Elliot Voris <[email protected]>

* Adding content for the `getTransactionStatus` method

Signed-off-by: Elliot Voris <[email protected]>

* Adding content for the `requestAirdrop` method

Signed-off-by: Elliot Voris <[email protected]>

* Adding content for the `sendTransaction` method

Signed-off-by: Elliot Voris <[email protected]>

* Adding content for `simulateTransaction` method

Signed-off-by: Elliot Voris <[email protected]>

* Changing the appearance of a WIP note

Signed-off-by: Elliot Voris <[email protected]>

* Breaking each of the intro sections into their own pages

Signed-off-by: Elliot Voris <[email protected]>

* 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 <[email protected]>

* Adding a "description" field to the intro category

Signed-off-by: Elliot Voris <[email protected]>

* Fixing a link reference to `pagination`

Signed-off-by: Elliot Voris <[email protected]>

* Capitalizing `Stellar` more consistently

Signed-off-by: Elliot Voris <[email protected]>

* Update api/methods/getEvents.mdx

Soroban-RPC supports querying up to 24 hours of recent ledgers.

Co-authored-by: Paul Bellamy <[email protected]>

* Update api/methods/getTransactionStatus.mdx

Co-authored-by: Paul Bellamy <[email protected]>

* `sendTransaction` *does* support all Stellar transactions.

Signed-off-by: Elliot Voris <[email protected]>

* Removing the question about auto-calculating footprints

Signed-off-by: Elliot Voris <[email protected]>

* All questions have been answered. Sweet!!

Signed-off-by: Elliot Voris <[email protected]>

* Update api/pagination.mdx

Co-authored-by: Paul Bellamy <[email protected]>

* Removing the "Outstanding Questions" page from the sidebar

Signed-off-by: Elliot Voris <[email protected]>

* denoting `getNetwork` as a work-in-progress

Signed-off-by: Elliot Voris <[email protected]>

* Moving the (WIP) methods to their own sidebar section

Signed-off-by: Elliot Voris <[email protected]>

* Adding example request/response to the `getAccount` method

Signed-off-by: Elliot Voris <[email protected]>

* Adding example request/response for the `getHealth` method

Signed-off-by: Elliot Voris <[email protected]>

* Adding example request/response for the `sendTransaction` method

Signed-off-by: Elliot Voris <[email protected]>

* Adding example request/response for the `getTransactionStatus` method

Signed-off-by: Elliot Voris <[email protected]>

* Adding example request/response for the `getContractData` method

Signed-off-by: Elliot Voris <[email protected]>

* Adding example request/response for the `getLedgerEntry` method

Signed-off-by: Elliot Voris <[email protected]>

* Changing the `balance` field into a "TODO"

Signed-off-by: Elliot Voris <[email protected]>

* Adding example request/response for the `getEvents` method

Signed-off-by: Elliot Voris <[email protected]>

* Adding a note about the events that are returned

Signed-off-by: Elliot Voris <[email protected]>

* Adding example request/response for the `simulateTransaction` method.

Signed-off-by: Elliot Voris <[email protected]>

* Adding a pending example to the `getTransactionStatus` method

Signed-off-by: Elliot Voris <[email protected]>

* Adding a more useful success example to `getTransactionStatus`

Signed-off-by: Elliot Voris <[email protected]>

* Using a soroban transaction in the `sendTransaction` method

Don't forget the footprint, friends!

Signed-off-by: Elliot Voris <[email protected]>

* Removing the `getContractData` method

This method is being deprecated. See stellar/stellar-cli#316 for
more details.

Please use the `getLedgerEntry` method instead.

Signed-off-by: Elliot Voris <[email protected]>

Signed-off-by: Elliot Voris <[email protected]>
Co-authored-by: Paul Bellamy <[email protected]>
  • Loading branch information
ElliotFriend and paulbellamy authored Jan 24, 2023
1 parent 40a7719 commit 9d79c37
Show file tree
Hide file tree
Showing 16 changed files with 774 additions and 9 deletions.
14 changes: 14 additions & 0 deletions api/anti-goals.mdx
Original file line number Diff line number Diff line change
@@ -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...
:::
17 changes: 17 additions & 0 deletions api/goals.mdx
Original file line number Diff line number Diff line change
@@ -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.
16 changes: 16 additions & 0 deletions api/json-rpc.mdx
Original file line number Diff line number Diff line change
@@ -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]: <https://www.jsonrpc.org/specification>
[jsonrpc error object]: <https://www.jsonrpc.org/specification#error_object>
[js-soroban-client]: <https://github.com/stellar/js-soroban-client>
47 changes: 47 additions & 0 deletions api/methods/getAccount.mdx
Original file line number Diff line number Diff line change
@@ -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>` - Address of the account to lookup

## Returns

- `<object>`
- `id`: `<address>`
- `sequence`: `<string>` - 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"
}
}
```
134 changes: 134 additions & 0 deletions api/methods/getEvents.mdx
Original file line number Diff line number Diff line change
@@ -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`: `<string>` - Stringified ledger sequence number to fetch events after (inclusive).
- `endLedger`: `<string>` - 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`: `<object[]>` - 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`: `<string[]>` - (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`: `<TopicFilter[]>` - (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`: `<PaginationOptions>` - See "[Pagination](../pagination)"

## Returns

- `<object>`
- `events`: `<object[]>`
- `ledger`: `<string>` - String-ified sequence number of the ledger.
- `ledgerClosedAt`: `<string>` - ISO8601 timestamp of the ledger closing time.
- `contractId`: `<string>` - ID of the emitting contract.
- `id`: `<string>` - 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) + `<hyphen>` + number for the event within the operation.
- For example:
- 1234-1
- `pagingToken`: `<string>` - Duplicate of `id` field, but in the standard place for pagination tokens.
- `topic`: `<xdr.ScVal[]>` - List containing the topic this event was emitted with.
- `value`: `<object>` - List containing the topic this event was emitted with.
- `xdr`: `<xdr.ScVal>` - 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]: <https://github.com/stellar/rs-soroban-env/blob/924d86cacd58b8a162344bfe0ab37d9668f5d629/soroban-env-host/src/native_contract/token/event.rs#L21-L33>
[`toid` from Horizon]: <https://github.com/stellar/go/blob/master/toid/main.go>
38 changes: 38 additions & 0 deletions api/methods/getHealth.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
---
sidebar_position: 2
---

General node health check.

## Parameters

- None

## Returns

- `<object>`
- `status`: "healthy"

## Examples

### Request

```json
{
"jsonrpc": "2.0",
"id": 8675309,
"method": "getHealth"
}
```

### Response

```json
{
"jsonrpc": "2.0",
"id": 8675309,
"result": {
"status": "healthy"
}
}
```
20 changes: 20 additions & 0 deletions api/methods/getLatestLedger.mdx
Original file line number Diff line number Diff line change
@@ -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

- `<object>`
- `id`: `<hash>` - hash of the latest ledger
- `protocolVersion`: `<number>`
- `sequence`: `<number>`
103 changes: 103 additions & 0 deletions api/methods/getLedgerEntry.mdx
Original file line number Diff line number Diff line change
@@ -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`: `<xdr.LedgerKey>` - The key of the ledger entry you wish to retrieve (serialized in a base64 string)

## Return

- `<object>`
- `xdr`: `<xdr.LedgerEntryData>` - The current value of the given ledger entry (serialized in a base64 string)
- `lastModifiedLedgerSeq`: `<number>` - The ledger number of the last time this entry was updated (optional)
- `latestLedger`: `<number>` - 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]: </docs/examples/storing-data>
Loading

0 comments on commit 9d79c37

Please sign in to comment.