Skip to content

feat: add Stellar chain support with Soroban auth signing and x402 payments#198

Open
oceans404 wants to merge 6 commits intoopen-wallet-standard:mainfrom
oceans404:main
Open

feat: add Stellar chain support with Soroban auth signing and x402 payments#198
oceans404 wants to merge 6 commits intoopen-wallet-standard:mainfrom
oceans404:main

Conversation

@oceans404
Copy link
Copy Markdown

@oceans404 oceans404 commented Apr 8, 2026

Summary

Adds full Stellar support to OWS: wallet creation (G-address derivation), message signing (SEP-53), transaction signing, Soroban smart contract authorization, x402 USDC payments on Stellar, and pre-wired MoonPay funding.

  • Stellar as supported chain — Ed25519 signing, BIP-44 m/44'/148'/{index}' derivation, three networks (pubnet, testnet, futurenet)
  • Soroban auth entry signing — new sign_inner_authorizations trait method on ChainSigner with default no-op (zero impact on other chains). Stellar override transparently detects InvokeHostFunction ops and signs matching auth entries inside transaction envelopes
  • x402 USDC payments on Stellar — Soroban invokeHostFunction calling transfer(from, to, amount) on USDC contract, with simulation, auth signing, and fee estimation
  • Shared Soroban auth helperssoroban_auth module with build_auth_preimage_xdr and format_auth_signature for reuse
  • MoonPay pre-wiredstellar added to MOONPAY_CHAINS; will work with zero code changes when MoonPay Agents API adds Stellar
  • x402 v2 extensions forwarding — payment payloads now include extensions.bazaar for Bazaar discovery indexing

Stellar on OWS

Supported Networks

Network Chain ID CLI shorthand Passphrase
Mainnet stellar:pubnet stellar Public Global Stellar Network ; September 2015
Testnet stellar:testnet stellar-testnet Test SDF Network ; September 2015
Futurenet stellar:futurenet stellar-futurenet Test SDF Future Network ; October 2022

CLI Usage

# Create wallet (derives G-address alongside all chains)
ows wallet create --name my-wallet

# Sign a message (SEP-53)
ows sign message --chain stellar --wallet my-wallet --message "hello"

# Sign and broadcast a transaction
ows sign send-tx --chain stellar-testnet --wallet my-wallet --tx <hex-xdr>

# x402 payment on Stellar
ows pay request --wallet my-wallet --network stellar:pubnet https://api.example.com/data

# Agent access
OWS_PASSPHRASE=ows_key_xxx ows pay request --wallet agent-wallet https://api.example.com

How Soroban Auth Signing Works

When sign send-tx receives a transaction containing InvokeHostFunction:

  1. Detects Soroban auth entries inside the envelope
  2. For each SorobanAuthorizationEntry with Address credentials matching the wallet's pubkey and unsigned (Void) signature:
    • Builds HashIdPreimage::SorobanAuthorization (network ID, nonce, expiration, invocation)
    • SHA-256 hashes the preimage XDR, Ed25519 signs the hash
    • Formats signature as ScVal::Vec([ScVal::Map({public_key, signature})]) (standard __check_auth format)
  3. Skips entries for other signers, already-signed entries, contract addresses, and SourceAccount credentials
  4. Signs the outer transaction envelope normally

This is transparent — no Soroban-specific CLI flags needed. The caller builds and simulates the transaction externally, passes the envelope to OWS.

x402 Payment Flow on Stellar

ows pay request handles Stellar x402 payments end-to-end:

  1. Sends HTTP request, gets 402 with Stellar payment requirements
  2. Builds Soroban InvokeHostFunction tx calling transfer(from, to, amount) on the USDC contract
  3. Simulates via Soroban RPC (twice — once to get auth entries, once with signed auth for accurate fees)
  4. Signs auth entries with Ed25519 (keys never leave Rust)
  5. Retries request with signed payment payload

Architecture

Crate Stellar additions
ows-core Network passphrases, chain IDs, RPC defaults
ows-signer StellarSigner, soroban_auth helpers, sign_inner_authorizations
ows-lib sign_and_send pipeline, sign_stellar_auth_entry, policy enforcement
ows-pay Soroban tx building, simulation, x402 auth signing via WalletAccess

Design Decisions

  • sign_inner_authorizations is a trait method with default no-op — only Stellar overrides it; all other chains are unaffected
  • Shared helpers live in ows-signer/soroban_auth — used by sign_inner_authorizations; x402 keeps its own inline copy to avoid adding ows-signer as a dependency of ows-pay
  • G-addresses only — smart wallet (C-address) support deferred until demand materializes; infrastructure is in place for later
  • MoonPay pre-wiredows fund deposit --chain stellar returns MoonPay's 400 today but will work with zero changes when they add Stellar to the Agents API

Test plan

  • cargo check passes cleanly
  • cargo test -p ows-signer — 291 passed, 0 failed (13 new sign_inner_authorizations tests + 2 soroban_auth tests + fixed pre-existing test_sign_soroban_auth_equivalence)
  • cargo test -p ows-lib — 148 passed, 0 failed
  • Non-Soroban transactions pass through sign_inner_authorizations unchanged
  • Auth entries for non-matching keys are never signed
  • Already-signed entries are preserved (idempotent)
  • Different networks produce different signatures (replay protection)
  • Signature cryptographically verifies against the correct preimage
  • Manual test: ows sign send-tx --chain stellar-testnet with a real Soroban envelope
  • Manual test: ows pay request against an x402 endpoint accepting Stellar USDC

🤖 Generated with Claude Code


Note

High Risk
High risk: introduces a new chain family (Stellar) and modifies core signing/broadcast and payment flows, including inner-authorization signing and new network/RPC handling.

Overview
Stellar is now a supported chain family across the CLI, core registry, and docs (CAIP-2 stellar:*, BIP-44 coin type 148, derivation path m/44'/148'/0', and default RPC endpoints for testnet/futurenet).

Core signing flow is extended to support chain-specific inner authorization signing via ChainSigner::sign_inner_authorizations (default no-op), and the main sign→encode→broadcast pipeline now invokes this hook before signing the outer transaction; Stellar broadcasting is added using Soroban RPC JSON-RPC sendTransaction with base64-encoded XDR plus improved error enrichment.

x402 payments gain Stellar support: ows-pay can now build/simulate Soroban USDC transfer transactions, sign Soroban auth preimages via a new WalletAccess::sign_stellar_auth hook, re-simulate for accurate fees, and forward extensions in x402 v2 payloads; the CLI adds a --network override for payment requests and MoonPay funding adds stellar as a target chain.

Reviewed by Cursor Bugbot for commit b143241. Bugbot is set up for automated code reviews on this repo. Configure here.

@oceans404 oceans404 requested a review from njdawn as a code owner April 8, 2026 00:28
@vercel
Copy link
Copy Markdown

vercel bot commented Apr 8, 2026

@oceans404 is attempting to deploy a commit to the MoonPay Team on Vercel.

A member of the Team first needs to authorize it.

@socket-security
Copy link
Copy Markdown

socket-security bot commented Apr 8, 2026

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Addedcargo/​tokio@​1.51.15910093100100
Addedcargo/​libc@​0.2.1848010093100100
Addedcargo/​signal-hook@​0.4.48210093100100
Addedcargo/​stellar-strkey@​0.0.1389100100100100
Addedcargo/​stellar-xdr@​26.0.093100100100100

View full report

oceans404 and others added 6 commits April 10, 2026 12:31
- ChainType::Stellar with Ed25519 curve, coin type 148, SEP-0005 derivation (m/44'/148'/{index}')
- StellarSigner with network-aware passphrase dispatch (pubnet, testnet, futurenet)
- Full signing pipeline: XDR envelope parsing, TransactionSignaturePayload construction, DecoratedSignature assembly via stellar-xdr
- SEP-53 message signing
- Soroban JSON-RPC broadcasting with enriched error messages (stellar_errors.rs)
- Backward-compatible signer_for_chain_type(ChainType) wrapper
- Pre-wired MoonPay funding + dynamic find_account_for_chain fix
- Updated docs, skills, website-docs, and README for 10 supported chains
Implement end-to-end x402 payments on Stellar (Soroban) alongside the
existing EVM path. The client now builds a Soroban transfer transaction,
simulates it, signs the auth entries, and sends the assembled XDR to the
facilitator for settlement.

Key changes:
- ows-pay: Stellar exact payment flow (simulate, sign auth, assemble tx,
  double-simulate for accurate fees)
- ows-signer: ed25519 signing for Soroban authorization preimages
- ows-cli: --network flag on `pay request` to select a specific chain
  when the server offers multiple payment options
- Fix ledger close time estimate (5s -> 6s) to prevent facilitator
  rejection of signature expiration on Stellar

Tested against anypay-test server with x402.org facilitator on both
Base Sepolia (eip155:84532) and Stellar testnet.
Same fix as the PR (open-wallet-standard#197), applied on top of the Stellar support
commits on main.

Fixes open-wallet-standard#196

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds sign_inner_authorizations to the ChainSigner trait so that
ows sign send-tx transparently signs Soroban authorization entries
inside Stellar transaction envelopes. This enables agents to call
arbitrary Soroban contracts through OWS without chain-specific CLI
commands — just pass a pre-simulated envelope and OWS handles both
the inner auth signing and outer envelope signing.

- New trait method with default no-op (zero impact on other chains)
- StellarSigner override: detects InvokeHostFunction ops, signs
  matching auth entries, skips others/already-signed/contracts
- Shared helpers in soroban_auth module (preimage + signature formatting)
- Fix pre-existing test_sign_soroban_auth_equivalence test bug
- 13 new tests covering all edge cases + security scenarios

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Fix All in Cursor

Bugbot Autofix is kicking off a free cloud agent to fix these issues. This run is complimentary, but you can enable autofix for all future PRs in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit b143241. Configure here.

ChainType::Sui,
ChainType::Xrpl,
ChainType::Nano,
ChainType::Stellar,
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Spark accidentally added to ALL_CHAIN_TYPES array

High Severity

ChainType::Spark was added to ALL_CHAIN_TYPES alongside Stellar, but the PR only intends to add Stellar support. Previously, ALL_CHAIN_TYPES had 10 entries (without Spark); now it has 12. Since derive_all_accounts iterates over ALL_CHAIN_TYPES to create wallet addresses, every wallet creation will now produce an extra Spark account. Spark shares Bitcoin's derivation path (m/84'/0'/0'/0/0), so this creates a redundant account from the same key material. The documentation was updated from "9" to "10" accounts (not 12), confirming only Stellar was intended.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit b143241. Configure here.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bugbot Autofix determined this is a false positive.

ALL_CHAIN_TYPES currently contains 10 entries and does not include ChainType::Spark, so the reported regression is not present.

This Bugbot Autofix run was free. To enable autofix for future PRs, go to the Cursor dashboard.

"expected account ledger entry",
)),
}
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused function soroban_rpc_get_account is dead code

Low Severity

The soroban_rpc_get_account function is defined but never called anywhere in the codebase. It appears to have been written for sequence number fetching but the build_stellar_exact flow uses a null source account with sequence 0 instead. This is ~80 lines of dead code that will produce a compiler warning.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit b143241. Configure here.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bugbot Autofix determined this is a false positive.

There is no soroban_rpc_get_account definition in the current codebase, so this dead-code warning does not apply.

This Bugbot Autofix run was free. To enable autofix for future PRs, go to the Cursor dashboard.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant