You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The public API assumes one chain. Responses carry Stellar-shaped fields (stellar_account_g, muxed_address, memo_id, stellar_tx_hash), amounts are numbers, and there is no way for a
client to say which chain it wants. Payment links
(crates/api/src/routes/payment_links.rs) resolve a
single hard-coded asset. Webhook payloads (octo-webhooks) carry
no chain identity, so a consumer receiving deposit.confirmed cannot tell which chain it came from.
Expose multi-chain support coherently across the API, the OpenAPI spec, and webhooks, without
breaking existing Stellar integrations.
Requirements and context
Existing Stellar clients must keep working. Choose and document a compatibility strategy:
default chain_id to Stellar when the field is absent, and/or version the API. Amount-as-string
(feat(store): Arbitrary-precision amounts — replace i64 stroops with NUMERIC(78,0) #215) is already breaking — bundle the breaks into one clearly-communicated version rather than
dribbling them out.
Every resource that is chain-scoped must expose chain_id in responses, and accept it on creation.
Chain-specific fields must be nested, not flattened. A flat response with memo_id: null on
EVM and derivation_index: null on Stellar teaches clients to guess. Nest under a chain_details
discriminated union keyed on chain kind.
drift_tests.rs enforces spec/implementation agreement — every change here needs a matching docs/openapi.yaml change or CI fails.
Security: authorisation is per wallet and must remain per wallet. Adding a chain_id
parameter must not create a path where a client passes a chain id to reach another tenant's
resources. Extend crates/api/tests/authz_matrix_tests.rs
with chain-scoped cases.
Suggested execution
Branch: feat/multi-chain-api-surface
Implement changes
Add chain_id to wallet/address/transaction/payment-link request and response schemas, with the
documented default for absent values, and nest chain-specific fields under a discriminated union.
Add GET /v1/chains — supported chains, their tokens (feat(store): ERC-20 token registry #223), confirmation depths, and enabled
status, so clients can discover capability rather than hard-code it.
Extend payment links to multi-chain: chain selection at creation, per-chain deposit address at
checkout, chain_id recorded on payment rows.
Add chain_id to every webhook payload and document the new deposit lifecycle events.
Extend crates/api/tests/drift_tests.rs to cover the new
and modified endpoints. Note: this file currently has a compile error on main
(statusN at line 47) — fix it as part of this PR.
Backward-compatibility tests: a request with no chain_id behaves exactly as it does today,
asserted against the current response shapes.
Authorization tests: a client cannot reach another tenant's wallet by varying chain_id.
Webhook tests: every event carries a correct chain_id; existing signature verification is
unchanged.
Multi-chain payment-link end-to-end test covering creation, chain selection, and per-chain address
issuance.
Write a migration guide for API consumers documenting every breaking change and how to adapt.
Example commit message
feat(api): multi-chain API surface, OpenAPI, and webhooks
Adds chain_id across chain-scoped resources with Stellar as the default
for absent values, nests chain-specific fields under a discriminated
union so clients stop guessing at null columns, and adds GET /v1/chains
for capability discovery.
Payment links gain chain selection with per-chain deposit addresses,
and every webhook payload now carries chain_id.
Also fixes a pre-existing compile error in drift_tests.rs.
BREAKING CHANGE: amount fields are strings; chain-specific fields moved
under chain_details.
Refs #227
Guidelines
Last issue in the epic and the one users actually see. Write the migration guide as if you were the
integrator receiving it.
Depends on: #215, #216, #220, #225. Blocks: nothing (terminal).
Description
The public API assumes one chain. Responses carry Stellar-shaped fields (
stellar_account_g,muxed_address,memo_id,stellar_tx_hash), amounts are numbers, and there is no way for aclient to say which chain it wants. Payment links
(
crates/api/src/routes/payment_links.rs) resolve asingle hard-coded asset. Webhook payloads (
octo-webhooks) carryno chain identity, so a consumer receiving
deposit.confirmedcannot tell which chain it came from.Expose multi-chain support coherently across the API, the OpenAPI spec, and webhooks, without
breaking existing Stellar integrations.
Requirements and context
default
chain_idto Stellar when the field is absent, and/or version the API. Amount-as-string(feat(store): Arbitrary-precision amounts — replace i64 stroops with NUMERIC(78,0) #215) is already breaking — bundle the breaks into one clearly-communicated version rather than
dribbling them out.
chain_idin responses, and accept it on creation.memo_id: nullonEVM and
derivation_index: nullon Stellar teaches clients to guess. Nest under achain_detailsdiscriminated union keyed on chain kind.
choosing at checkout and each choice yielding a chain-appropriate deposit address (feat(store): EVM per-customer deposit addresses via HD derivation #220).
chain_idin every event, and new events from this epic(
deposit.confirmed,deposit.orphanedfrom feat(ingest): Confirmation depth and reorg handling for EVM deposits #222) need documented payloads. Webhook signing(
crates/webhooks/src/sign.rs) is unchanged.drift_tests.rsenforces spec/implementation agreement — every change here needs a matchingdocs/openapi.yamlchange or CI fails.chain_idparameter must not create a path where a client passes a chain id to reach another tenant's
resources. Extend
crates/api/tests/authz_matrix_tests.rswith chain-scoped cases.
Suggested execution
Branch:
feat/multi-chain-api-surfaceImplement changes
chain_idto wallet/address/transaction/payment-link request and response schemas, with thedocumented default for absent values, and nest chain-specific fields under a discriminated union.
GET /v1/chains— supported chains, their tokens (feat(store): ERC-20 token registry #223), confirmation depths, and enabledstatus, so clients can discover capability rather than hard-code it.
checkout,
chain_idrecorded on payment rows.chain_idto every webhook payload and document the new deposit lifecycle events.docs/openapi.yaml,docs/api.md, and the Bruno collectionin
api-tests/added in4cd1bd2.Test and commit
crates/api/tests/drift_tests.rsto cover the newand modified endpoints. Note: this file currently has a compile error on
main(
statusNat line 47) — fix it as part of this PR.chain_idbehaves exactly as it does today,asserted against the current response shapes.
chain_id.chain_id; existing signature verification isunchanged.
issuance.
Example commit message
Guidelines
Last issue in the epic and the one users actually see. Write the migration guide as if you were the
integrator receiving it.