feat: add USDCx to supported tokens config#229
feat: add USDCx to supported tokens config#229salindne merged 2 commits intofeat/218-unified-balance-queryfrom
Conversation
Add USDCx (USD Coin, 6 decimals) to supported_tokens in all config
YAML files. This enables MetaMask to query balanceOf, symbol, decimals,
and name for USDCx through the ERC-20 facade.
USDCx is automatically added to the non-custodial transfer allowlist
since it is derived from supported_tokens.
Mainnet config uses ${CANTON_USDCX_INSTRUMENT_ADMIN} env var for the
instrument admin (Circle's Bridge-Operator party).
Closes #213
There was a problem hiding this comment.
Code Review
This pull request adds configuration for the USDCx token across multiple environment and test configuration files, including the addition of the CANTON_USDCX_INSTRUMENT_ADMIN environment variable in tests. The review feedback suggests adding the instrument_admin field to config.e2e-local.yaml and config.api-server.docker.yaml to ensure consistency with other environment configurations where this field is explicitly defined.
Codecov Report❌ Patch coverage is ❌ Your patch status has failed because the patch coverage (0.00%) is below the target coverage (50.00%). You can increase the patch coverage or adjust the target coverage. Additional details and impacted files@@ Coverage Diff @@
## feat/218-unified-balance-query #229 +/- ##
==================================================================
- Coverage 32.90% 32.53% -0.38%
==================================================================
Files 123 124 +1
Lines 8551 8643 +92
==================================================================
- Hits 2814 2812 -2
- Misses 5489 5582 +93
- Partials 248 249 +1
Flags with carried forward coverage won't be shown. Click here to find out more.
🚀 New features to boost your workflow:
|
| symbol: "DEMO" | ||
| decimals: 18 | ||
| instrument_id: "DEMO" | ||
| "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48": |
There was a problem hiding this comment.
Are we able to test this on local yet?
…sfers (#230) Add support for transferring tokens issued by external parties (e.g., USDCx from Circle) by routing factory discovery based on InstrumentAdmin: - Local tokens (InstrumentAdmin == IssuerParty): existing ACS query - External tokens: POST to Transfer Factory Registry API Key changes: - New RegistryClient (HTTP POST) calls Splice Transfer Factory Registry and parses factoryId, choiceContext, disclosedContracts from response - resolveTransferFactory routes by InstrumentAdmin automatically - DisclosedContracts from registry response threaded through PrepareSubmissionRequest for both custodial and non-custodial paths - EncodeExtraArgs now accepts choiceContext from registry response - ReadAs conditionally set: IssuerParty for local, empty for external - ExternalTokens config maps InstrumentAdmin → registry URL - WithRegistryClient option on token client constructor No breaking changes to public API (TransferByPartyID, PrepareTransfer). Routing is internal based on holdings data. Closes #214
* feat: unified balance query via Splice HoldingV1 interface Add GetHoldingsByParty method that queries Canton using the Splice HoldingV1 interface as the user's own party, instead of querying CIP56Holding template as IssuerParty. This enables visibility of tokens issued by third parties (e.g., USDCx from Circle) where our IssuerParty is not a stakeholder on the holdings. GetHoldings now delegates to GetHoldingsByParty. GetAllHoldings retains the IssuerParty/template path for totalSupply and indexer use. Closes #218 * docs: clarify that CreateArguments is always populated for interface queries Canton Ledger API v2 proto marks create_arguments as Required on CreatedEvent, so decodeHolding works identically for both template-based and interface-based queries. Add comment to address review concern. * chore: add TODO for GetHoldingsByParty unit tests * feat: add USDCx to supported tokens config (#229) * feat: add USDCx to supported tokens config Add USDCx (USD Coin, 6 decimals) to supported_tokens in all config YAML files. This enables MetaMask to query balanceOf, symbol, decimals, and name for USDCx through the ERC-20 facade. USDCx is automatically added to the non-custodial transfer allowlist since it is derived from supported_tokens. Mainnet config uses ${CANTON_USDCX_INSTRUMENT_ADMIN} env var for the instrument admin (Circle's Bridge-Operator party). Closes #213 * feat: integrate Transfer Factory Registry API for external token transfers (#230) Add support for transferring tokens issued by external parties (e.g., USDCx from Circle) by routing factory discovery based on InstrumentAdmin: - Local tokens (InstrumentAdmin == IssuerParty): existing ACS query - External tokens: POST to Transfer Factory Registry API Key changes: - New RegistryClient (HTTP POST) calls Splice Transfer Factory Registry and parses factoryId, choiceContext, disclosedContracts from response - resolveTransferFactory routes by InstrumentAdmin automatically - DisclosedContracts from registry response threaded through PrepareSubmissionRequest for both custodial and non-custodial paths - EncodeExtraArgs now accepts choiceContext from registry response - ReadAs conditionally set: IssuerParty for local, empty for external - ExternalTokens config maps InstrumentAdmin → registry URL - WithRegistryClient option on token client constructor No breaking changes to public API (TransferByPartyID, PrepareTransfer). Routing is internal based on holdings data. Closes #214
…#227) * feat: add instrument_id to token config and splice_holding_package_id Add InstrumentID and InstrumentAdmin fields to ERC20Token struct for per-token Canton instrument mapping. InstrumentID is required; InstrumentAdmin defaults to IssuerParty when empty. Add SpliceHoldingPackageID to cantonsdk/token.Config for Splice HoldingV1 interface queries (needed by #218 unified balance query). Update all config YAML files (defaults, test fixtures, e2e-local, devnet) with instrument_id per token and splice_holding_package_id. Closes #212 * fix: pass stack.Token by pointer in WaitForAPIBalance to fix hugeParam lint * fix: use env vars for mainnet splice_holding_package_id, add test env Address review feedback: - Use ${CANTON_SPLICE_HOLDING_PACKAGE_ID} env var in mainnet configs (consistent with other package ID fields) - Add CANTON_SPLICE_HOLDING_PACKAGE_ID to setDefaultConfigEnv test helper * fix: update remaining WaitForAPIBalance callers to pass Token by pointer * feat: unified balance query via Splice HoldingV1 interface (#228) * feat: unified balance query via Splice HoldingV1 interface Add GetHoldingsByParty method that queries Canton using the Splice HoldingV1 interface as the user's own party, instead of querying CIP56Holding template as IssuerParty. This enables visibility of tokens issued by third parties (e.g., USDCx from Circle) where our IssuerParty is not a stakeholder on the holdings. GetHoldings now delegates to GetHoldingsByParty. GetAllHoldings retains the IssuerParty/template path for totalSupply and indexer use. Closes #218 * docs: clarify that CreateArguments is always populated for interface queries Canton Ledger API v2 proto marks create_arguments as Required on CreatedEvent, so decodeHolding works identically for both template-based and interface-based queries. Add comment to address review concern. * chore: add TODO for GetHoldingsByParty unit tests * feat: add USDCx to supported tokens config (#229) * feat: add USDCx to supported tokens config Add USDCx (USD Coin, 6 decimals) to supported_tokens in all config YAML files. This enables MetaMask to query balanceOf, symbol, decimals, and name for USDCx through the ERC-20 facade. USDCx is automatically added to the non-custodial transfer allowlist since it is derived from supported_tokens. Mainnet config uses ${CANTON_USDCX_INSTRUMENT_ADMIN} env var for the instrument admin (Circle's Bridge-Operator party). Closes #213 * feat: integrate Transfer Factory Registry API for external token transfers (#230) Add support for transferring tokens issued by external parties (e.g., USDCx from Circle) by routing factory discovery based on InstrumentAdmin: - Local tokens (InstrumentAdmin == IssuerParty): existing ACS query - External tokens: POST to Transfer Factory Registry API Key changes: - New RegistryClient (HTTP POST) calls Splice Transfer Factory Registry and parses factoryId, choiceContext, disclosedContracts from response - resolveTransferFactory routes by InstrumentAdmin automatically - DisclosedContracts from registry response threaded through PrepareSubmissionRequest for both custodial and non-custodial paths - EncodeExtraArgs now accepts choiceContext from registry response - ReadAs conditionally set: IssuerParty for local, empty for external - ExternalTokens config maps InstrumentAdmin → registry URL - WithRegistryClient option on token client constructor No breaking changes to public API (TransferByPartyID, PrepareTransfer). Routing is internal based on holdings data. Closes #214 * remove unused InstrumentAdmin field from ERC20Token The field was never read anywhere in the codebase. Transfer-factory routing uses InstrumentAdmin from the on-chain holding contract, not config. External tokens are handled via cantonsdk/token.Config.ExternalTokens keyed by admin party ID after #228. Removes the field, the instrument_admin yaml keys in local-devnet and mainnet configs, and the CANTON_USDCX_INSTRUMENT_ADMIN env var from config tests. * fix(e2e): set splice_holding_package_id in canton shim token configs PR 228 made SpliceHoldingPackageID required on cantonsdk/token.Config. The e2e canton shim was missing it on both the DEMO and PROMPT token clients, causing every test to fail with 'splice_holding_package_id is required' at api/full stack init. Adds the constant alongside the other devnet package IDs (matches the value in config.api-server.local-devnet.yaml) and wires it into both token.Config instances.
* feat: add instrument_id to token config and splice_holding_package_id Add InstrumentID and InstrumentAdmin fields to ERC20Token struct for per-token Canton instrument mapping. InstrumentID is required; InstrumentAdmin defaults to IssuerParty when empty. Add SpliceHoldingPackageID to cantonsdk/token.Config for Splice HoldingV1 interface queries (needed by #218 unified balance query). Update all config YAML files (defaults, test fixtures, e2e-local, devnet) with instrument_id per token and splice_holding_package_id. Closes #212 * fix: pass stack.Token by pointer in WaitForAPIBalance to fix hugeParam lint * fix: use env vars for mainnet splice_holding_package_id, add test env Address review feedback: - Use ${CANTON_SPLICE_HOLDING_PACKAGE_ID} env var in mainnet configs (consistent with other package ID fields) - Add CANTON_SPLICE_HOLDING_PACKAGE_ID to setDefaultConfigEnv test helper * fix: update remaining WaitForAPIBalance callers to pass Token by pointer * feat(indexer): support external token indexing * updated comment * review fixes * review fixes * feat: unified balance query via Splice HoldingV1 interface (#228) * feat: unified balance query via Splice HoldingV1 interface Add GetHoldingsByParty method that queries Canton using the Splice HoldingV1 interface as the user's own party, instead of querying CIP56Holding template as IssuerParty. This enables visibility of tokens issued by third parties (e.g., USDCx from Circle) where our IssuerParty is not a stakeholder on the holdings. GetHoldings now delegates to GetHoldingsByParty. GetAllHoldings retains the IssuerParty/template path for totalSupply and indexer use. Closes #218 * docs: clarify that CreateArguments is always populated for interface queries Canton Ledger API v2 proto marks create_arguments as Required on CreatedEvent, so decodeHolding works identically for both template-based and interface-based queries. Add comment to address review concern. * chore: add TODO for GetHoldingsByParty unit tests * feat: add USDCx to supported tokens config (#229) * feat: add USDCx to supported tokens config Add USDCx (USD Coin, 6 decimals) to supported_tokens in all config YAML files. This enables MetaMask to query balanceOf, symbol, decimals, and name for USDCx through the ERC-20 facade. USDCx is automatically added to the non-custodial transfer allowlist since it is derived from supported_tokens. Mainnet config uses ${CANTON_USDCX_INSTRUMENT_ADMIN} env var for the instrument admin (Circle's Bridge-Operator party). Closes #213 * feat: integrate Transfer Factory Registry API for external token transfers (#230) Add support for transferring tokens issued by external parties (e.g., USDCx from Circle) by routing factory discovery based on InstrumentAdmin: - Local tokens (InstrumentAdmin == IssuerParty): existing ACS query - External tokens: POST to Transfer Factory Registry API Key changes: - New RegistryClient (HTTP POST) calls Splice Transfer Factory Registry and parses factoryId, choiceContext, disclosedContracts from response - resolveTransferFactory routes by InstrumentAdmin automatically - DisclosedContracts from registry response threaded through PrepareSubmissionRequest for both custodial and non-custodial paths - EncodeExtraArgs now accepts choiceContext from registry response - ReadAs conditionally set: IssuerParty for local, empty for external - ExternalTokens config maps InstrumentAdmin → registry URL - WithRegistryClient option on token client constructor No breaking changes to public API (TransferByPartyID, PrepareTransfer). Routing is internal based on holdings data. Closes #214 * remove unused InstrumentAdmin field from ERC20Token The field was never read anywhere in the codebase. Transfer-factory routing uses InstrumentAdmin from the on-chain holding contract, not config. External tokens are handled via cantonsdk/token.Config.ExternalTokens keyed by admin party ID after #228. Removes the field, the instrument_admin yaml keys in local-devnet and mainnet configs, and the CANTON_USDCX_INSTRUMENT_ADMIN env var from config tests. * fix(e2e): set splice_holding_package_id in canton shim token configs PR 228 made SpliceHoldingPackageID required on cantonsdk/token.Config. The e2e canton shim was missing it on both the DEMO and PROMPT token clients, causing every test to fail with 'splice_holding_package_id is required' at api/full stack init. Adds the constant alongside the other devnet package IDs (matches the value in config.api-server.local-devnet.yaml) and wires it into both token.Config instances. * usdcx contracts deployments on local docker setup * usdcx contracts deployments on local docker setup * usdcx contracts deployments on local docker setup * feat(cantonsdk/token): add TransferInternalByPartyID for internal Canton party transfers Closes #247 * feat(e2e): add USDCx cross-participant transfer test and multi-participant devstack * fix(e2e): lint cleanup in Canton2Shim and types - gofmt canton2.go imports - drop unused-receiver names in stub methods - nosec annotation on USDCxTokenVirtualAddr (public EVM address, not a credential) * health check added for p2 * fix(ci): fix P2 package vetting race in USDCx bootstrap Use CMD-SHELL list form for canton healthcheck test to avoid YAML fold ambiguity, and add a 10s vetting propagation wait to the P2 bootstrap section — mirroring the equivalent wait already done for P1 — so that bootstrap-usdcx runs only after P2 packages are fully vetted on the synchronizer. --------- Co-authored-by: Sebastian Lindner <33971232+salindne@users.noreply.github.com> Co-authored-by: Arun Dhyani <dhyaniarun7@gmail.com>
Summary
Add USDCx (USD Coin, 6 decimals) to
supported_tokensin all config YAML files:This enables:
0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48)eth_callforsymbol(),decimals(),name()returns correct USDCx valuessupported_tokens)Mainnet uses
${CANTON_USDCX_INSTRUMENT_ADMIN}env var for Circle's Bridge-Operator party.Depends on #228 (unified balance query) and #227 (instrument_id config)
Closes #213
Test plan
go build ./...passes