oz-policy-builder
Wallet adapter

Overview

TypeScript SEP-43 adapter that closes the record → synthesize → simulate → sign → install loop.

The wallet adapter is the TypeScript layer that signs and installs a generated policy on a real Stellar smart account, then verifies the on-chain rule matches the synthesized spec.

It ships two adapter implementations and three orchestration helpers.

Adapters

AdapterUse
FreighterWalletBrowser-extension wallet via @stellar/freighter-api.
PasskeyWalletTwo paths: a headless Keypair.fromSecret for testnet automation, and a passkey-kit hook for WebAuthn-backed signing.

Both implement the same WalletAdapter interface, which conforms to SEP-43:

interface WalletAdapter {
  isAvailable(): Promise<boolean>;
  getAddress(): Promise<string>;
  signTransaction(envelopeXdr: string, params: SignTransactionParams): Promise<SignTransactionResult>;
  signAuthEntry(authEntryXdr: string, params: SignAuthEntryParams): Promise<SignAuthEntryResult>;
}

SignTransactionParams.submit is restricted to false — submission is owned by installPolicy, never the wallet, so the simulate → sign → submit sequence stays auditable.

Orchestration helpers

  • installPolicy — sign the install envelope, submit it, poll until landed, extract the assigned context_rule_id.
  • verifyInstall — spawn the oz-policy-mcp subprocess and call verify_install. Returns drift items if the on-chain rule does not match the expected spec.
  • makeOzSmartAccountAuthEncoder — produces the encoder callback that installPolicy uses to construct the OZ AuthPayload and bind context-rule ids into the signature.

Pinned versions

DepPin
@stellar/freighter-api=6.0.1
passkey-kit=0.12.0
@stellar/stellar-sdk=12.3.0 (dev)
typescript=5.6.3 (dev)
vitest=2.1.9 (dev)

Errors

All adapter and orchestration errors implement a discriminated code: string field plus a detail: string. The codes are stable and documented per function.

CodeFunctionMeaning
E_WALLET_REJECTEDadapterUser rejected the sign request.
E_INSTALL_SUBMIT_FAILEDinstallPolicyThe submit RPC call failed.
E_INSTALL_POLL_TIMEOUTinstallPolicyThe poll timed out before the transaction left NOT_FOUND.
E_INSTALL_RESULT_DECODE_FAILEDinstallPolicyThe context_rule_id could not be extracted from the result.
E_MAINNET_REQUIRES_CONSENTinstallPolicyCalled against mainnet without confirmMainnet: true.
E_VERIFY_SUBPROCESS_SPAWN_FAILEDverifyInstallThe MCP subprocess could not be spawned.
E_VERIFY_SUBPROCESS_TIMEOUTverifyInstallThe MCP subprocess did not reply within the timeout.
E_VERIFY_SUBPROCESS_CRASHEDverifyInstallThe MCP subprocess exited before replying.
E_VERIFY_PROTOCOL_ERRORverifyInstallThe JSON-RPC handshake or response shape was malformed.
E_VERIFY_TOOL_ERRORverifyInstallThe verify_install tool itself returned a typed error.

On this page