# Ripple Custody

[[Source]](https://github.com/ripple/simpleXRPL/blob/95b977b15f8950c5bc076b25165217869c0b06d3/src/custodians/ripple/construction.ts#L35)

Ripple Custody authenticates with an intent-author key exchanged for a token. A Custody deployment is per-tenant, so its gateway and token URLs point at the instance provisioned for you. See: [Generate a key pair and register a public key](https://docs.ripple.com/products/custody/identity-and-access/authentication/generate-api-keys-and-register) for instructions on creating API credentials to fill in this constructor.

## RippleCustody.create()

Construct with every value passed explicitly.

### Signature

```ts
RippleCustody.create(options: RippleCustodyOptions): Promise<RippleCustody>
```

### Options

| Field | Type | Required | Description |
|  --- | --- | --- | --- |
| `gatewayUrl` | `string` | Yes | The Custody gateway base URL. |
| `auth` | `RippleCustodyAuthOptions` | Yes | Intent-author credentials and token endpoint. |
| `auth.signingKey` | `string` | Yes | Intent-author private key, as PEM contents. |
| `auth.tokenUrl` | `string` | Yes | The Custody token endpoint URL. |
| `auth.clientId` | `string` | No | The OIDC client id to authenticate as. Defaults to `customer_api`. |
| `domainId` | `string` | Yes | The Custody domain this custodian operates in. |
| `primary` | `string` | Yes | The primary account's r-address; validated against the discovered set. |
| `allowRawSigning` | `boolean` | No | Enable the raw-signing fallback. Defaults to `false`. |
| `defaultFee` | [`FeeIntent`](/docs/simplexrpl/references/types#feeintent) | No | House fee intent — a priority tier and/or a `maxFeeDrops` cap. Backends that can't honor the tier auto-price and warn. Defaults to `low`. |
| `defaultDryRun` | `boolean` | No | Pre-flight every write through Custody's dry-run. Defaults to `false`. |
| `defaultTimeoutMs` | `number` | No | How long `submitAndWait` polls before throwing `IntentPendingError`. |
| `http` | `CustodyHttpPort` | No | Advanced: a custom HTTP transport, shape `{ send: (request) => Promise<response> }`. Defaults to the production fetch port; most callers omit it. |


Caution
Enabling `allowRawSigning` weakens the custodian's controls. On the raw path the custodian signs an opaque payload rather than a structured operation, so its transaction-level controls (transfer policies, allow-lists, and approval rules keyed to operation semantics) cannot inspect what is being signed. Ripple Custody types this payload `Unsafe`. `xrpl.js` protocol validation still runs on every path, so malformed transactions are still rejected; what is lost is the custodian's ability to reason about the transaction's intent.

Leave it off unless a specific transactor requires it, and prefer routing those operations through a signer that models them natively.

## RippleCustody.fromEnv()

Reads the endpoints, credentials, and domain from environment variables.

The `env` requires these keys:

- `RIPPLE_CUSTODY_GATEWAY_URL`
- `RIPPLE_CUSTODY_AUTH_SIGNING_KEY`
- `RIPPLE_CUSTODY_AUTH_TOKEN_URL`
- `RIPPLE_CUSTODY_AUTH_CLIENT_ID` (optional)
- `RIPPLE_CUSTODY_DOMAIN_ID`


### Signature

```ts
RippleCustody.fromEnv(options: RippleCustodyFromEnvOptions): Promise<RippleCustody>
```

### Options

| Field | Type | Required | Description |
|  --- | --- | --- | --- |
| `primary` | `string` | Yes | The primary account's r-address; validated against the discovered set. |
| `allowRawSigning` | `boolean` | No | Enable the raw-signing fallback. Defaults to `false`. |
| `defaultFee` | [`FeeIntent`](/docs/simplexrpl/references/types#feeintent) | No | House fee intent — a priority tier and/or a `maxFeeDrops` cap. Backends that can't honor the tier auto-price and warn. Defaults to `low`. |
| `defaultDryRun` | `boolean` | No | Pre-flight every write through Custody's dry-run. Defaults to `false`. |
| `defaultTimeoutMs` | `number` | No | How long `submitAndWait` polls before throwing `IntentPendingError`. |
| `env` | `object` | No | The source the `RIPPLE_CUSTODY_*` environment variables are read from, as a map of names to values. Defaults to `process.env`. |
| `http` | `object` | No | A custom HTTP transport (implements `CustodyHttpPort`). Defaults to the production fetch port; most callers omit it. |


Caution
Enabling `allowRawSigning` weakens the custodian's controls. On the raw path the custodian signs an opaque payload rather than a structured operation, so its transaction-level controls (transfer policies, allow-lists, and approval rules keyed to operation semantics) cannot inspect what is being signed. Ripple Custody types this payload `Unsafe`. `xrpl.js` protocol validation still runs on every path, so malformed transactions are still rejected; what is lost is the custodian's ability to reason about the transaction's intent.

Leave it off unless a specific transactor requires it, and prefer routing those operations through a signer that models them natively.

### Resolving the signing key

`fromEnv()` accepts `RIPPLE_CUSTODY_AUTH_SIGNING_KEY` in three forms, chosen by what the value starts with:

| Value starts with | Resolved as |
|  --- | --- |
| `-----BEGIN` | Literal PEM contents. |
| `arn:aws:secretsmanager:` | An AWS Secrets Manager secret ARN — the secret is fetched and parsed. |
| anything else | A path to a `.pem` file on disk, read at startup. |


For the Secrets Manager path, the secret's value must be a JSON object (not a raw PEM string) with these fields:

| Field | Required | Description |
|  --- | --- | --- |
| `private_key` | Yes | The intent-author private key, PEM contents. |
| `user_alias` | Yes | The Custody user this keypair belongs to. Validated as present so an incomplete secret fails fast. |


The AWS client is constructed with no explicit credentials, so it uses the default AWS SDK credential provider chain: environment variables, a shared profile, or the runtime's IAM role. Resolution throws `SimpleXRPLError` if the secret is empty, isn't valid JSON, or is missing `private_key` or `user_alias`.

## Example

```ts
const rippleCustody = await RippleCustody.fromEnv({
  primary: process.env.RIPPLE_CUSTODY_PRIMARY ?? '',
})
```