Skip to content

About

Unbound Stellar gateway service and Soroban redemption escrow (Testnet)

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

Unbound logo

Unbound-stellar

The Stellar-native layer of Unbound: trustline and issuer checks, strict-send path quotes, unsigned transaction builders, submission, ledger reconciliation, and the one Soroban contract (the redemption escrow).

CI License: MIT Network: Stellar Testnet Status: pre-release

Part of Unbound - turn stranded value into something usable.

What is Unbound?

Store credit is usually stuck inside one retailer. Unbound lets a person exchange store credit that a retailer has genuinely issued and agreed to honor for other Stellar assets, at a real order-book quote that they sign on their own device, or redeem it with the issuer.

  • Issuer-authorized only. A verified merchant signs a redemption policy with its Stellar issuer key and must authorize every holder's trustline. No issuer, no usable credit; arbitrary gift cards are out of scope.
  • No fake liquidity. Quotes come from real Stellar path payments, expire and carry a minimum-output floor. No route means no quote. Unbound never promises a price, liquidity or fiat cash-out.
  • Ledger-truthful. Nothing is shown as settled until the ledger confirms it; unknown outcomes reconcile by hash.
  • Testnet only today. Mainnet needs an external security review and legal/compliance work that has not happened.

This repository

Unbound-stellar owns everything that touches the ledger: verifying issuer accounts and flags, checking trustlines and authorization, finding strict-send paths with a slippage cap and expiry, building unsigned transactions (settlement, trustline authorization, issuance, redemption return), classifying submissions, and indexing confirmations into versioned reconciliation events for Unbound-core. It ships as a TypeScript SDK plus a gateway HTTP service and a chain worker. Only the Testnet passphrase is accepted.

It also owns Unbound's only smart contract, contracts/redemption-escrow (Rust, soroban-sdk 29.0.1): returned credit is held until the issuer confirms (released to the issuer), rejects (refunded), or the deadline passes (anyone can trigger the refund). Why this is the one place Soroban is used: ADR 0002. The TypeScript side (SorobanRedemptionEscrow) builds unsigned, simulated invocations and decodes records and events, tested against golden XDR produced by the Rust tests.

Architecture

Unbound is four independently tested repositories with one owner per boundary. This one is highlighted.

flowchart LR
  M["Unbound-mobile<br/>Flutter wallet"]
  S["Unbound-site<br/>landing + merchant console"]
  C["Unbound-core<br/>HTTP API v1, policy, intents, audit"]
  G["Unbound-stellar<br/>SDK, gateway service, chain worker"]
  N[("Stellar Testnet<br/>assets, trustlines, DEX,<br/>Soroban redemption escrow")]
  M -- "quotes, intents, signed XDR" --> C
  S -- "merchant auth, redemption queue" --> C
  C -- "quote / build / submit" --> G
  G -- "Horizon + Soroban RPC" --> N
  G -- "reconciliation events" --> C
  style G fill:#7537F5,stroke:#10092E,color:#ffffff
Loading

Clients never build Stellar transactions, and core never reimplements ledger logic. Details: docs/ARCHITECTURE.md and docs/STELLAR_PROTOCOL.md.

Quickstart

Requires Node 22+.

npm ci
npm run check                      # lint + typecheck + tests + build
npx tsx scripts/m1-demo.ts         # offline demo: issue, quote, settle, and a refused no-trustline route

# the Soroban contract (Rust stable + wasm32v1-none)
cd contracts
cargo fmt --check && cargo clippy --all-targets -- -D warnings && cargo test
SOROBAN_SDK_BUILD_SYSTEM_SUPPORTS_SPEC_SHAKING_V2=1 cargo build --release --target wasm32v1-none
DRY_RUN=1 ../scripts/deploy-testnet.sh   # prints the stellar-cli deploy steps (the real run is recorded in docs/DEPLOYMENT.md)

The demo runs on SimulatedLedger, an in-memory test adapter that verifies real XDR signatures, sequence numbers and time bounds; its hashes are not Testnet hashes. The gateway (npm run gateway, needs GATEWAY_TOKEN) and worker (npm run worker, needs CORE_URL + CORE_TOKEN) are written and tested over HTTP but have never been run against Horizon (see .env.example).

Project status

Legend: Built = implemented and covered by automated tests in this repo. Not yet = not started or not verified.

Capability Status
Exact amount math (integer base units, 7 dp, no floats) Built
Verified-issuer registry, fail-closed on untrusted or malformed assets; issuer flag and trustline checks Built (on the simulator)
Unsigned builders: issuer setup, authorize trustline, issue credit, change trust, redemption return Built (on the simulator)
Strict-send quotes: expiry, slippage cap (<= 10%), min-output floor, tamper-evident id, approved-route filter Built
Settlement builder re-validating freshness, balances, authorization and destination trustline Built
Submit classification (CONFIRMED / FAILED / RECONCILING), reconcile by hash, cursor indexer with replay Built
Gateway service for core (quote, settlement, redemption return, submit, balances) with bearer auth Built, tested over HTTP on the simulator
Chain worker (pending-hash watcher, event sink with retry and dead-letter file) Built, tested with a stub core
Horizon adapters (HorizonClient) Mapping-tested, and run against live Testnet on 2026-11-04 (paths, submit, transaction lookup); that run found and fixed the SDK ledger link-function bug
Soroban redemption escrow contract: open / confirm / reject / expire_refund, single-use ids, bounded deadlines, issuer = SAC admin, pause for new returns only, events Built: 22 behaviour and failure-path tests, a seeded invariant test (escrow balance == locked == open returns) and a golden-fixture test; wasm builds in CI
SorobanRedemptionEscrow adapter, gateway /gateway/v1/escrow/* endpoints, golden Rust -> TypeScript XDR fixtures Built (on FixtureSorobanRpc); StellarRpcSorobanPort run live against Soroban RPC: prepared open_return / confirm / reject / expire_refund landed on Testnet
scripts/deploy-testnet.sh (stellar-cli build, deploy, init, admin check, issuer authorize) Run for real on 2026-11-04: contract CC4ETHM44IUJ4GDRT57VH4OSNEMPEGUKQHQJCUQDIU2LKIAKZYIYOP6C (see docs/DEPLOYMENT.md)
Real Testnet hashes: deploy, escrow smoke (scripts/testnet-smoke.ts), core-driven escrow flows, DEX exchange Recorded in contracts/deployments/*.json and docs/DEPLOYMENT.md
Network-anchored gateway clock (LedgerClock): a host clock 95 s slow made every settlement tx_too_late Built; found live
Account-stream indexing, escrow event indexing from RPC, liquidity pools, reserves/liabilities Not yet
Published npm package, Docker image, metrics endpoint, fee sponsorship, external audit of the contract Not yet

Public boundary

  • TypeScript API exported from src/index.ts.
  • schemas/reconciliation-event.v1.json (generated from zod with npm run schemas, snapshot-tested) and fixtures/reconciliation-event.confirmed.v1.json - consumed by Unbound-core.
  • fixtures/gateway/*.json - gateway contract (incl. escrow endpoints), byte-identical to core's copy; deterministic XDR fixtures for the mobile decoder (now incl. escrow open_return / expire_refund).
  • fixtures/soroban/redemption-escrow.v1.json - golden contract records and events generated by the Rust tests.

The four repositories

Repository Owns Stack CI
Unbound-core Backend API: issuers, policies, intents, redemptions, audit TypeScript, Node 22, SQLite CI
Unbound-stellar (this repo) Stellar SDK, gateway service, chain worker, Soroban redemption escrow TypeScript, @stellar/stellar-sdk, Rust/Soroban CI
Unbound-site Landing page, partner docs and merchant console Next.js 16, React 19, Tailwind 4 CI
Unbound-mobile Flutter consumer wallet Flutter, Dart, Riverpod CI

Contributing and Drips Wave

Contributions are welcome. Start with CONTRIBUTING.md, then pick from the scoped, testable ideas in docs/CONTRIBUTOR_ISSUES.md. Unbound intends to take part in Drips Wave; that is subject to Drips' review and limits, and no rewards are promised. Wave issues are opened only once their dependencies and acceptance tests are ready. Everyone agrees to the Code of Conduct.

Security

Please report vulnerabilities privately (Security tab, Report a vulnerability) as described in SECURITY.md. The threat model is in docs/SECURITY.md. Testnet only: never use real funds, real customer data or Mainnet keys with this code.

Documentation

docs/PRD.md (product) · docs/SRD.md (requirements, API, states) · docs/ARCHITECTURE.md · docs/TECHNICAL_BUILD.md · docs/ROADMAP.md · docs/BRAND.md · AGENTS.md (rules for coding agents). The canonical copy of the shared docs lives in Unbound-core.

License

MIT. The Unbound logo in brand/ is the project's approved identity and is shared by all four repositories; it has not been trademark-cleared.

About

Unbound Stellar gateway service and Soroban redemption escrow (Testnet)

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages