Skip to content

feat(canton): add CCIP bridge disclosures and client examples - #10002

Closed
ralph-bitgo[bot] wants to merge 5 commits into
masterfrom
SCAAS-11643-ccip-bridge-examples
Closed

ralph-bitgo[bot] wants to merge 5 commits into
masterfrom
SCAAS-11643-ccip-bridge-examples

Conversation

@ralph-bitgo

@ralph-bitgo ralph-bitgo Bot commented Oct 19, 2026 •

Copy link
Copy Markdown

Description

Add Canton CCIP bridge request support and USD1 EVM↔Canton client examples:

  • sdk-core: optional CantonCommandParams.disclosedContracts and payload-aware resolveContracts.createArgumentFilter; export the EDS disclosure shape.
  • sdk-coin-canton: serialize disclosures through CantonCommandBuilder / CantonCommandRequest.
  • Inbound Execute and outbound Send examples collect global/CCV/token-pool/executor disclosures, avoid ACS lookup of the cross-party router factory, and select receivers by finality or explicit CID.
  • Custodial wallets need no passphrase/unlock. Outbound requests pass tokenName. Setup halts on pending approval and supports router-only resume. Dry runs read the actual wallet party but never submit. Conflicting finality overrides fail early.
  • Production requires --laneConfig with independently verified identities/URLs; the draft production constants are not treated as verified.
  • README documents onboarding prerequisites and deferred operational acceptance.

Why: external clients cannot prepare custodial CCIP Execute/Send without cross-party disclosures and correct receiver finality. The examples expose the existing sendMany flow while avoiding validator credentials and preventing dependent setup steps from racing pending approval.

Issue Number

SCAAS-11643

Type of change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • This change requires a documentation update

How Has This Been Tested?

  • CantonCommandBuilder suite: 32 passing (cd modules/sdk-coin-canton && npx mocha --grep CantonCommandBuilder). Scoped SDK builds completed/current after workspace installation; ESLint passed for sdk-core and sdk-coin-canton, and sdk-coin-canton formatting passed.
  • Both example scripts pass node --check. Seven offline CLI scenarios exercised dry-run party handling, finality filtering, approval halting, router-only resume, outbound disclosures/tokenName, production gating and conflicting-finality rejection. External responses were fixtures; no live signing or ledger execution was exercised.
  • The broader Canton suite has pre-existing BITGOJS_TEST_PASSWORD-gated setup; those suites were not locally verified.
  • Cross-repo validation note: type-check deferred to CI (sandbox OOM, exit 137 at concurrency 1) — wallet-platform follow-up only; IMS type-check ran locally. This does not describe an SDK type-check failure. Wallet-platform Biome/DB checks are also deferred with engineer approval. If sandbox resources become available, rerun deferred checks before leaving draft; no further environment workarounds are planned.
  • Reviewer priority in the related wallet-platform change: runtime disclosure codec validation replaces a cast and now rejects malformed input; instrument↔intent-token binding and decimal-precision checks are additional client-input validations.

Checklist:

  • My code follows the style guidelines of this project
  • I have performed a self-review of my own code
  • My code compiles correctly for both Node and Browser environments — scoped Node builds checked; browser build not exercised
  • I have commented my code, particularly in hard-to-understand areas
  • My commits follow Conventional Commits and I have properly described any BREAKING CHANGES — none
  • The ticket or github issue was included in the commit message as a reference
  • I have made corresponding changes to the documentation and on any new/updated functions and/or methods — JSDoc and examples README
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes — builder suite passes; broader secret-gated suites deferred

Related delivery and remaining acceptance

The IMS draft provides server-side disclosure/factory resolution and pending-input metadata. Wallet-platform provides Send locks and validation. Live custodial lane execution, production constants verification, validator onboarding and the party-preflight API product ask remain outstanding; this draft does not close operational acceptance.

Pre-PR ACI gate skipped: no .github/ai-checks/pr-risk on the base branch.

Cross-repository drafts

Add CantonDisclosedContract and an optional disclosedContracts array to
CantonCommandParams so clients can pass the CCIP OffRamp/CCV/token-pool
disclosure blobs (fetched from the public EDS endpoints) through to the
platform, and an optional createArgumentFilter on
CantonCommandResolveContractSpec so contract resolution can select a
CCIPReceiver payload-aware by receiverFinalityConfig.

Why: CCIP Execute/Send require cross-party disclosures at ledger prepare
time and finality-specific receivers; without these fields external
clients cannot assemble the commands for custodial Canton wallets.

Ticket: SCAAS-11643
Session-Id: c64486c0-8dba-415e-ab0a-1e7c4a99b35e
Task-Id: ce366653-12a0-4f96-bb86-02993a4d1b4c
Requested-By: Zeeshan Amjad <zeeshanamjad@bitgo.com>
Add a disclosedContracts setter to CantonCommandBuilder and include the
disclosures in CantonCommandBuilder.toRequestObject()/CantonCommandRequest
when present, forwarding them to IMS alongside the existing
resolveContracts specs.

Why: CantonCommandRequest had no disclosedContracts field, so the
platform could not pass client-fetched CCIP disclosures through to the
ledger prepare call — a hard blocker for custodial Execute/Send.

Ticket: SCAAS-11643
Session-Id: c64486c0-8dba-415e-ab0a-1e7c4a99b35e
Task-Id: ce366653-12a0-4f96-bb86-02993a4d1b4c
Requested-By: Zeeshan Amjad <zeeshanamjad@bitgo.com>
Add executeCcipMessage.js and sendCcipMessage.js (inbound and outbound
USD1 CCIP lanes) plus a README covering platform vs client
responsibilities and the wallet-party onboarding prerequisites (domain
hosting, CCIP package vetting, JSON-API rights). The scripts attach the
EDS disclosure blobs via cantonCommandParams.disclosedContracts, select
the receiver finality-aware (createArgumentFilter, or --receiverCid),
halt dependent setup steps on pending approvals, and pass tokenName so
the platform can lock and validate Send holdings.

Why: external clients need a working reference for bridging USD1 between
EVM and Canton on BitGo custodial wallets; each onboarding prerequisite
missing today surfaces as a cryptic mid-flow ledger error.

Ticket: SCAAS-11643
Session-Id: c64486c0-8dba-415e-ab0a-1e7c4a99b35e
Task-Id: ce366653-12a0-4f96-bb86-02993a4d1b4c
Requested-By: Zeeshan Amjad <zeeshanamjad@bitgo.com>
Read the actual wallet party during Execute dry runs, permit router-only
setup resume, reject conflicting finality overrides, and require a
verified lane configuration for production execution.

Blank-party disclosures and skipped receiver setup make the draft flow
fail; unverified production identities must not silently route funds.
Seven offline CLI scenarios exercise these paths without ledger calls.

Ticket: SCAAS-11643
Session-Id: c64486c0-8dba-415e-ab0a-1e7c4a99b35e
Task-Id: ce366653-12a0-4f96-bb86-02993a4d1b4c
Requested-By: Zeeshan Amjad <zeeshanamjad@bitgo.com>
@linear-code

linear-code Bot commented Oct 19, 2026

Copy link
Copy Markdown
Contributor

SCAAS-11643

@github-actions

github-actions Bot commented Oct 19, 2026 •

Copy link
Copy Markdown
Contributor

⚠️ Unit tests are failing on Node 26.x (Current release line, non-blocking). This is not an LTS version yet, so it does not block merge, but it signals an incompatibility to fix before Node 26.x becomes LTS.

View run

…sures server-side

- Remove the disclosedContracts() builder setter, the CantonCommandRequest
  field, and the CantonDisclosedContract type from sdk-core baseTypes
  (createArgumentFilter stays — used by the payload-aware receiver
  resolution).
- executeCcipMessage.js: the client now supplies only the encoded message
  and the raw CCV verifier results ({ destAddress, verifierResults });
  IMS resolves and injects the receiver exercise target, choice context,
  CCV contract ids/contexts, token transfer, and all ledger disclosures —
  all EDS calls removed from the example.
- sendCcipMessage.js: the client supplies only the message, instruments,
  and holding ids; IMS resolves the token pool (TAR), fee token config,
  pool/global/CCV/executor contexts and contract ids, and all ledger
  disclosures — TAR/pool/global/CCV/executor EDS calls removed.
- README updated to reflect the new responsibility split.

SCAAS-11643
@zeeshanamjad-eng
zeeshanamjad-eng force-pushed the SCAAS-11643-ccip-bridge-examples branch from 65e4fca to 772df0b Compare October 19, 2026 12:36
@zeeshanamjad-eng

Copy link
Copy Markdown
Contributor

Closing without merging — per review, no BitGoJS changes are needed for the CCIP Canton flow:

  • The released SDK already supports everything the client scripts need: the cantonCommand intent (sdk-core mpcUtils / recipientUtils) and the CantonCommandBuilder with command/actAs/resolveContracts/token were shipped before this PR. The one field this PR added to the SDK types (createArgumentFilter) reaches IMS at runtime without an SDK change (spec objects pass through the builder into the IMS request JSON, and indexerdb-microservice#2372 decodes it server-side).
  • All ledger disclosures are now resolved server-side: indexerdb-microservice#2372 resolves the Execute/Send disclosure blobs (global/CCV/token-pool/executor) from the EDS and injects the derived contexts, contract ids, fee token config, and token transfer into the choice argument. Clients pass no disclosedContracts — which is why the SDK disclosedContracts() surface added here is being dropped.
  • The two example scripts were relocated out of BitGoJS (they are standalone client tooling, not SDK code) — preserved on the local working branch SCAAS-11590-ccip-wallet-scripts in ccip-starter-kit-canton (bitgo/ethers deps added there), adapted to the server-side disclosure resolution.

Companion changes: indexerdb-microservice#2372 + bitgo-microservices#63639 carry the IMS/wallet-platform side. This branch stays as a reference for the scripts' history.

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.

2 participants