-
Notifications
You must be signed in to change notification settings - Fork 50
simpleXRPL docs #224
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
simpleXRPL docs #224
Changes from 4 commits
c451979
d4dae48
ad216a9
35e8fc2
b618289
94d618b
ec18829
e9065b1
803aebe
8da9406
1f2ecb3
acb62d3
9d92240
354f7dd
5dd9f99
caddbf4
52bc4b4
a965b59
5e385d6
bf2a67c
3d7c499
dc449f4
65a8008
ecfaa75
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| Every simpleXRPL write resolves to a `SubmissionResult<T>` — a union tagged by `source`, with the backend's raw response preserved verbatim. Its common fields are: | ||
|
|
||
| | Field | Type | Description | | ||
| | --- | --- | --- | | ||
| | `intent` | `T` | The method-specific output. See the method's response values below. | | ||
| | `source` | `'rippled' \| 'custody' \| 'palisade'` | Which backend produced the result; discriminates `response`. | | ||
| | `response` | `TxResponse` \| custody record \| Palisade record | The backend's raw response, preserved verbatim. | | ||
| | `txHash` | `string` _(optional)_ | The XRPL transaction hash, once the transaction is on-ledger. | | ||
| | `intentId` | `string` _(optional)_ | The custodian intent id, when the path produced one. | | ||
| | `idempotencyKey` | `string` _(optional)_ | The UUIDv7 this submission carried. Pass it back as a later call's `idempotencyKey` to retry to the same intent. | |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| `options` is an optional second argument that sets the source account and overrides the fee. | ||
|
|
||
| | Option | Type | Required | Description | | ||
| | --- | --- | --- | --- | | ||
| | `from` | `AccountSelector` | No | The account to act as. Defaults to the primary signer's primary account. (For IOU verbs, this is the issuer.) | | ||
| | `fee` | `FeeIntent` | No | Fee override. | | ||
| | `idempotencyKey` | `string` | No | A prior submission's `idempotencyKey`, to retry to the same intent instead of creating a duplicate. Auto-generated when omitted. | |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,130 @@ | ||
| --- | ||
| seo: | ||
| description: Install simpleXRPL, initialize the client, connect a custodian, and run your first XRP Ledger operation. | ||
| labels: | ||
| - simpleXRPL | ||
| - SDK | ||
| --- | ||
|
|
||
| # Get Started | ||
|
|
||
| This guide takes you from install to your first on-ledger operation in three steps: **initialize the client**, **set up a custodian**, and **run a vertical operation**. The examples target the XRPL Testnet with a local signer so you can run them as-is, then swap in a production custodian when you're ready. | ||
|
|
||
| ## Prerequisites | ||
|
|
||
| - **Node.js >= 20.19.** simpleXRPL is Node-targeted and not intended to run in the browser. | ||
| - Install the package: | ||
|
|
||
| ```sh | ||
| npm install simplexrpl | ||
| ``` | ||
|
|
||
| ## 1. Initialize the client | ||
|
|
||
| `SimpleXRPL.init(...)` is the single entry point — you never construct the client with `new`. It binds one or more already-authenticated signing backends (the **connectors**) to a network and builds the account index. | ||
|
|
||
| ```ts | ||
| import { LocalSigner, SimpleXRPL } from 'simplexrpl' | ||
|
|
||
| const client = await SimpleXRPL.init({ | ||
| // Point at a rippled endpoint. `faucetUrl` is only used on test networks | ||
| // (by `client.account.fund`). | ||
| rippledUrl: 'wss://s.altnet.rippletest.net:51233', | ||
| faucetUrl: 'https://faucet.altnet.rippletest.net/accounts', | ||
|
|
||
| // Bind one or more connectors. Here, a single local-signing backend that | ||
| // reads its seeds from the environment (`XRPL_*_SEED`). | ||
| signers: [LocalSigner.fromEnv()], | ||
| }) | ||
|
|
||
| // ... use the client ... | ||
|
|
||
| await client.disconnect() | ||
| ``` | ||
|
|
||
| - **`primarySigner`** is the default backend for verbs called without an explicit account. It defaults to `signers[0]`, so you only set it when you bind more than one connector. | ||
| - With **no `signers`**, the client is read-only: reads work, but write verbs throw `NoSignerError` until a signer is added. | ||
| - Bind an account at runtime (for example, a freshly created wallet) with `client.registerLocalAccount(seed)`. | ||
|
|
||
| See [Initialize the client](tutorials/inititialize-clients.md) for the full walkthrough, and [Client and initialization](references/index.md#client-and-initialization) for the configuration reference. | ||
|
|
||
| ## 2. Set up a custodian | ||
|
|
||
| The **connector** determines how operations run and who holds the keys. simpleXRPL ships three, each constructed and authenticated on its own, then handed to `init`: | ||
|
|
||
| - **`LocalSigner`** — self-custody; keys held in-process. For development and testing. | ||
| - **`RippleCustody`** — routes through Ripple Custody. For production. | ||
| - **`PalisadeCustody`** — routes through Palisade. For production. | ||
|
|
||
| The local signer in Step 1 is enough for development. For production, construct a custodian connector and bind it instead of (or alongside) the local one: | ||
|
|
||
| ```ts | ||
| import { | ||
| LocalSigner, | ||
| PalisadeCustody, | ||
| RippleCustody, | ||
| SimpleXRPL, | ||
| } from 'simplexrpl' | ||
|
|
||
| // Ripple Custody — authenticates with an intent-author key and operates within | ||
| // one Custody domain. `fromEnv` reads the `RIPPLE_CUSTODY_*` variables. | ||
| const rippleCustody = await RippleCustody.fromEnv({ | ||
| primary: process.env.RIPPLE_CUSTODY_PRIMARY ?? '', | ||
| }) | ||
|
|
||
| // Palisade — authenticates via OAuth client credentials and acts on a | ||
| // specific vault/wallet. | ||
| const palisade = await PalisadeCustody.create({ | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. just confirming that it's correct that we have no url for ripple custody but we do for palisade? @pdp2121 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes that's correct afaik. Cant tag Cybele here to confirm
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just added her to review team, tagging @cybele-ripple |
||
| baseUrl: 'https://api.sandbox.palisade.co', | ||
| clientId: process.env.PALISADE_CLIENT_ID ?? '', | ||
| clientSecret: process.env.PALISADE_CLIENT_SECRET ?? '', | ||
| primary: { | ||
| vaultId: process.env.PALISADE_VAULT_ID ?? '', | ||
| walletId: process.env.PALISADE_WALLET_ID ?? '', | ||
| }, | ||
| // Enable the raw sign-only fallback for transactors the custodian has no | ||
| // native operation for. Off by default. | ||
| allowRawSigning: false, | ||
| }) | ||
|
|
||
| const client = await SimpleXRPL.init({ | ||
| rippledUrl: 'wss://s.altnet.rippletest.net:51233', | ||
| signers: [rippleCustody, palisade, LocalSigner.fromEnv()], | ||
| primarySigner: rippleCustody, | ||
| }) | ||
| ``` | ||
|
|
||
| Read credentials from your environment or secrets manager — never hard-code keys. Once bound, every vertical verb works the same regardless of which connector owns the account: the SDK routes each write to the custodian that holds it. | ||
|
oeggert marked this conversation as resolved.
Outdated
|
||
|
|
||
| {% admonition type="info" name="Note" %} | ||
| Whether an operation runs through a custodian's **native** path or the **raw-signing fallback** is decided per operation; the fallback is off by default and enabled per connector via `allowRawSigning`. See [Operation Execution](index.md#operation-execution) and the [Connector Routing](references/connector-routing.md) table. | ||
| {% /admonition %} | ||
|
|
||
| See [Connect to custodians](tutorials/connect-custodians.md) for the full per-connector setup. | ||
|
|
||
| ## 3. Run a vertical operation | ||
|
|
||
| Operations are grouped into domain-specific **verticals** — `xrp`, `token`, `iou`, `credential`, `domain`, and `account` — reached off the client. Each verb reads as business intent rather than protocol mechanics. Here's the simplest one, a native XRP payment: | ||
|
oeggert marked this conversation as resolved.
Outdated
|
||
|
|
||
| ```ts | ||
| const result = await client.xrp.transfer({ | ||
| to: 'rDestination...', | ||
| amount: '10', | ||
| }) | ||
|
|
||
| console.log(result.txHash) | ||
| ``` | ||
|
|
||
| - A write verb uses the **primary account** by default; target a different bound account by passing `from` in the options. | ||
| - Every write resolves to a `SubmissionResult` carrying the transaction hash, the backend's response, and a typed `intent` output. See [Results and handles](references/index.md#results-and-handles). | ||
| - **Reads** (such as `client.account.retrieve()`) need no signer and submit nothing. | ||
|
|
||
| {% admonition type="success" name="Tip" %} | ||
| On a test network, create and fund an account first with [`account.create()`](references/verticals/account/create.md) and [`account.fund()`](references/verticals/account/fund.md), then use its address as the source or destination. | ||
| {% /admonition %} | ||
|
|
||
| ## Next steps | ||
|
|
||
| - **Tutorials** — end-to-end workflows: [Issue an RWA as an MPT](tutorials/issue-rwa-as-mpt.md), [Issue and distribute an IOU](tutorials/issue-and-distribute-iou.md), [Place a DEX order](tutorials/place-dex-order.md), and more. | ||
| - **Reference** — every vertical, method, connector, and type: [Reference](references/index.md). | ||
| - **Concepts** — what simpleXRPL is and why: [What is simpleXRPL](index.md). | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,47 @@ | ||
| --- | ||
| seo: | ||
| description: simpleXRPL is an opinionated TypeScript SDK that lets institutional developers express XRP Ledger operations as business intent and route them through the custodians they already use. | ||
| labels: | ||
| - simpleXRPL | ||
| - SDK | ||
| --- | ||
|
|
||
| # simpleXRPL | ||
| [Source](https://github.com/ripple/simpleXRPL) | ||
|
|
||
| The `simpleXRPL` is an opinionated TypeScript SDK for the XRP Ledger, built for institutional developers who interact with the ledger through a custodian. It raises the level of your code from XRPL protocol mechanics to business operations that the SDK routes through your institutional custodians. Concretely, this means: | ||
|
oeggert marked this conversation as resolved.
Outdated
|
||
|
|
||
| - `simpleXRPL` defines the shape of business operations, handling the underlying XRPL transactions and custodian API calls. | ||
| - Your code doesn't change even if you switch custodians or operate across several at once. | ||
|
|
||
| {% admonition type="warning" name="Caution" %} | ||
| `simpleXRPL` is pre-1.0. The public API may change between releases and no sandbox exists yet to test native custodian operations. | ||
| {% /admonition %} | ||
|
|
||
|
|
||
| ## How It Works | ||
|
|
||
| `simpleXRPL` is built around four concepts: | ||
|
|
||
| - **Clients**: Establishes the network connection and the connector configuration. Both are immutable for the client's lifetime; to change either, you create a new client. | ||
| - **Connectors**: The execution model that determines *how* operations run and *who* holds account keys. Each connector exposes a uniform interface to the rest of the SDK, so the same code runs across all of them. | ||
| - **Accounts**: An XRPL [account](https://xrpl.org/docs/concepts/accounts) paired with the connector that signs for it. | ||
|
oeggert marked this conversation as resolved.
Outdated
|
||
| - **Verticals**: Domain-specific classes and methods that group related business operations. | ||
|
|
||
|
|
||
| ## Operation Execution | ||
|
|
||
| For every operation, on every connector, `simpleXRPL` has a statically defined routing decision that it reports at initialization: | ||
|
|
||
| - **Native**: Maps onto an endpoint a custodian exposes and natively handles. | ||
| - **Raw Signing**: For an operation the custodian exposes no native support for, the SDK builds the underlying XRPL transactions, the custodian signs the raw bytes, then the SDK submits them to the XRPL directly. Raw signing is off by default and enabled per connector; once on, it covers every operation that connector can't handle natively. | ||
| - **Unavailable**: The custodian doesn't expose a native endpoint and raw signing isn't enabled on the connector, so this operation is rejected. | ||
|
|
||
| {% admonition type="info" name="Note" %} | ||
| For a complete list of supported operations by connector, see [Connector Routing](./references/connector-routing.md) | ||
| {% /admonition %} | ||
|
|
||
|
|
||
| ## See Also | ||
|
|
||
| - [Get Started](./get-started.md) | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,61 @@ | ||
| --- | ||
| seo: | ||
| description: The connector routing table — per XRPL transactor and per custodian, whether an operation routes native, requires the raw-signing fallback, or is unavailable. | ||
| labels: | ||
| - simpleXRPL | ||
| - SDK | ||
| --- | ||
|
|
||
| # Connector Routing | ||
|
|
||
| [Source](https://github.com/ripple/simpleXRPL/blob/50619258cf753008e8a185eaeb3ceca489e5998a/docs/connector-routing.md) | ||
|
|
||
| How simpleXRPL dispatches each XRPL transactor per connector. Derived directly from each custodian's native-operation set and the transactors the verticals build, so it always matches the code. | ||
|
|
||
| {% admonition type="info" name="Note" %} | ||
| This page is generated from the SDK source by `scripts/gen-connector-routing.mjs` — do not edit by hand. Regenerate with `npm run docgen:routing`. | ||
| {% /admonition %} | ||
|
|
||
| ## Transactor → connector path | ||
|
|
||
| The pipeline routes by transactor type: **Local** signs everything in-process; a custodian uses its **native** operation when the transactor is in its capability set, otherwise the **raw** sign-only fallback, otherwise the write is rejected. | ||
|
|
||
| | Transactor | Local | Ripple Custody | Palisade | | ||
| | --- | --- | --- | --- | | ||
| | `AccountSet` | signs locally | **native** | **native** | | ||
| | `Clawback` | signs locally | **native** | **native** | | ||
| | `CredentialAccept` | signs locally | raw fallback¹ | raw fallback¹ | | ||
| | `CredentialCreate` | signs locally | raw fallback¹ | raw fallback¹ | | ||
| | `CredentialDelete` | signs locally | raw fallback¹ | raw fallback¹ | | ||
| | `DepositPreauth` | signs locally | **native** | raw fallback¹ | | ||
| | `EscrowFinish` | signs locally | **native** | raw fallback¹ | | ||
| | `MPTokenAuthorize` | signs locally | **native** | raw fallback¹ | | ||
| | `MPTokenIssuanceCreate` | signs locally | **native** | raw fallback¹ | | ||
| | `MPTokenIssuanceDestroy` | signs locally | **native** | raw fallback¹ | | ||
| | `MPTokenIssuanceSet` | signs locally | **native** | raw fallback¹ | | ||
| | `OfferCancel` | signs locally | raw fallback¹ | **native** | | ||
| | `OfferCreate` | signs locally | **native** | **native** | | ||
| | `Payment` | signs locally | **native** | **native** | | ||
| | `PermissionedDomainDelete` | signs locally | raw fallback¹ | raw fallback¹ | | ||
| | `PermissionedDomainSet` | signs locally | raw fallback¹ | raw fallback¹ | | ||
| | `SetRegularKey` | signs locally | raw fallback¹ | raw fallback¹ | | ||
| | `TrustSet` | signs locally | **native** | **native** | | ||
|
|
||
| ¹ **raw fallback** applies only when raw signing is enabled on that custodian (`allowRawSigning`). With raw signing disabled, a non-native transactor is rejected with `SignerCapabilityError` — use a Local account or a custodian that natively supports it. The raw path signs the encoded transaction and submits it through the shared XRPL connection. | ||
|
|
||
| ## Vertical → transactors | ||
|
|
||
| Which XRPL transactors each vertical builds. Cross-reference with the table above to see how a given method routes on each connector. | ||
|
|
||
| | Vertical | Transactors emitted | | ||
| | --- | --- | | ||
| | `account` | `AccountSet`, `DepositPreauth`, `Payment`, `SetRegularKey` | | ||
| | `credential` | `CredentialAccept`, `CredentialCreate`, `CredentialDelete` | | ||
| | `domain` | `PermissionedDomainDelete`, `PermissionedDomainSet` | | ||
| | `iou` | `AccountSet`, `Clawback`, `OfferCancel`, `OfferCreate`, `Payment`, `TrustSet` | | ||
| | `token` | `MPTokenAuthorize`, `MPTokenIssuanceCreate`, `MPTokenIssuanceDestroy`, `MPTokenIssuanceSet`, `OfferCancel`, `OfferCreate`, `Payment` | | ||
| | `xrp` | `Payment` | | ||
|
|
||
| --- | ||
|
|
||
| _Native-ops sets: `NATIVE_XRPL_TRANSACTORS` (Ripple Custody), `PALISADE_NATIVE_TRANSACTORS` (Palisade). Local signs all transactors._ |
|
oeggert marked this conversation as resolved.
Outdated
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,94 @@ | ||
| --- | ||
| seo: | ||
| description: Reference index for the simpleXRPL SDK — its verticals, connectors, the amount and asset model, submission results, and the error hierarchy. | ||
| labels: | ||
| - simpleXRPL | ||
| - SDK | ||
| --- | ||
|
|
||
| # Reference | ||
|
|
||
| This section is the map of simpleXRPL's public API surface: the client entry point, the business-intent verticals, the custodian connectors, the amount and asset model, submission results, and the error hierarchy. Complete type-level signatures for every symbol are generated from the source with TypeDoc; the tables below are the curated index of what you actually build against. | ||
|
|
||
| New to simpleXRPL? Start with [What is simpleXRPL](../index.md) for the concepts, then [Get Started](../get-started.md) to install and connect a custodian. | ||
|
|
||
| {% admonition type="info" name="Note" %} | ||
| This index covers the public surface only. Internal and testing seams (the dispatch pipeline, injected I/O ports, and the production ledger port) are intentionally omitted — you don't call them directly. | ||
| {% /admonition %} | ||
|
|
||
| ## Client and initialization | ||
|
|
||
| The client owns the network connection and the connector configuration, both immutable for its lifetime. | ||
|
|
||
| | Symbol | Description | | ||
| | --- | --- | | ||
| | `SimpleXRPL` | The entry point. `SimpleXRPL.init(...)` establishes the network, connector, and account bindings. | | ||
| | `SimpleXRPLClient` | The runtime client returned by `init`; exposes the verticals. | | ||
| | `SimpleXRPLConfig` | The initialization configuration shape (network, connector, accounts). | | ||
| | `NetworkInfo` | Resolved network details for the connected client. | | ||
|
|
||
| ## Verticals | ||
|
|
||
| Operations are grouped into domain-specific **verticals**, one per area of XRPL functionality and reached off the client. See [Verticals](verticals/index.md) for what a vertical is and the full list of verticals and their methods. | ||
|
|
||
| ## Connectors | ||
|
|
||
| The connector is the execution model — it determines how operations run and who holds the keys. See [Operation Execution](../index.md#operation-execution) for how each operation routes. | ||
|
|
||
| | Connector | Use | Key configuration types | | ||
| | --- | --- | --- | | ||
| | `LocalSigner` | Development and testing; holds `xrpl` wallets in-process. | `LocalSignerCreateOptions`, `LocalSignerFromEnvOptions` | | ||
| | `RippleCustody` | Production; routes through Ripple Custody. | `RippleCustodyOptions`, `RippleCustodyAuthOptions`, `RippleCustodyFromEnvOptions` | | ||
| | `PalisadeCustody` | Production; routes through Palisade. | `PalisadeCustodyConfig`, `PalisadeWalletRef` | | ||
|
|
||
| ## Amounts and assets | ||
|
|
||
| The amount model represents XRP, IOU, and MPT values and handles decimal/scale conversion. | ||
|
|
||
| | Symbol | Description | | ||
| | --- | --- | | ||
| | `Amount` | A value paired with the asset it denominates. | | ||
|
oeggert marked this conversation as resolved.
Outdated
|
||
| | `Asset` | The asset an amount is in (XRP, IOU, or MPT). | | ||
| | `XRP_ASSET` | The canonical XRP asset constant. | | ||
| | `iou(currency, issuer)` | Construct an issued-currency asset. | | ||
| | `mpt(mptIssuanceId, scale?)` | Construct an MPT asset; `scale` is the decimal places between display value and on-ledger base units. | | ||
| | `toLedgerAmount` / `fromLedgerAmount` | Convert between display amounts and on-ledger base units. | | ||
| | `LedgerAmount` | The on-ledger (base-unit) amount representation. | | ||
|
|
||
| ## Results and handles | ||
|
|
||
| | Symbol | Description | | ||
| | --- | --- | | ||
| | `SubmissionResult<T>` | The terminal result of an operation; carries the discriminated `source`/`response` pairing and the vertical's typed `intent` output. | | ||
| | `SubmissionResultFields` | The common fields present on every submission result. | | ||
| | `SubmissionPath` | Which path the operation took (native vs. raw-signing). | | ||
| | `SubmissionHandle` | Handle over an asynchronously-submitted operation, for flows that resolve later. | | ||
| | `CustodyTransactionResult` / `PalisadeTransactionResult` | The connector-specific transaction record inside the result. | | ||
|
|
||
| The `*Intent` types (`XrpTransferIntent`, `MptIssueIntent`, `IOUIssueIntent`, `DomainIntent`, and the rest) are the typed `intent` payloads attached to each result. | ||
|
|
||
| ## Errors | ||
|
|
||
| All errors extend `SimpleXRPLError`, so you can catch the base class or narrow to a specific type. | ||
|
|
||
| | Error | Raised when | | ||
| | --- | --- | | ||
| | `SimpleXRPLError` | Base class for every SDK error. | | ||
| | `NoSignerError` | No signer/connector owns the target account. | | ||
| | `SignerCapabilityError` | The operation can't be signed on this connector (native path missing, or raw signing not enabled). | | ||
| | `AccountNotFoundError` | The referenced account is not bound to the client. | | ||
| | `AmbiguousAccountError` | The account reference matches more than one bound account. | | ||
| | `RippledSubmitError` | The transaction reached a terminal on-ledger failure (non-`tesSUCCESS`). | | ||
| | `IntentPendingError` | A custodian intent is still awaiting approval when a terminal result was expected. | | ||
| | `IntentValidationError` | A custodian rejected the intent as invalid. | | ||
| | `MultiStepFailureError` | A multi-step operation failed partway through. | | ||
| | `CustodyApiError` / `CustodyAuthError` | Ripple Custody API or authentication failure. | | ||
| | `PalisadeApiError` / `PalisadeAuthError` | Palisade API or authentication failure. | | ||
|
|
||
| ## Related reference | ||
|
|
||
| Companion reference pages that live alongside this index: | ||
|
|
||
| - **Function-to-transactor mapping** — the underlying XRPL transactor(s) each method expands into (also shown inline on each method page). | ||
| - [**Connector routing table**](connector-routing.md) — per operation and per connector, whether it routes native, requires raw-signing fallback, or is unavailable. | ||
| - **Institutional defaults** — the full set of defaults the SDK applies unless overridden. | ||
Uh oh!
There was an error while loading. Please reload this page.