Skip to content

feat: add instrument_id to token config and splice_holding_package_id#227

Merged
salindne merged 11 commits intomainfrom
feat/212-instrument-id-config
Apr 28, 2026
Merged

feat: add instrument_id to token config and splice_holding_package_id#227
salindne merged 11 commits intomainfrom
feat/212-instrument-id-config

Conversation

@salindne
Copy link
Copy Markdown
Contributor

Summary

  • Add InstrumentID (required) and InstrumentAdmin (optional, defaults to IssuerParty) fields to ERC20Token config struct
  • Add SpliceHoldingPackageID (required) to cantonsdk/token.Config for Splice HoldingV1 interface queries
  • Update all config YAML files with instrument_id per token and splice_holding_package_id

This is the foundation for #218 (unified balance query) and #214 (transfer factory). Every token now specifies its Canton instrument ID, and the SDK config knows the Splice HoldingV1 package ID for interface-based ACS queries.

Closes #212

Test plan

  • go build ./... passes
  • All 19 test packages pass
  • Config validation tests pass (all default/test YAML files load correctly)
  • Token erc20 tests updated with InstrumentID field
  • E2E system tests updated with InstrumentID field

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
@codecov-commenter
Copy link
Copy Markdown

codecov-commenter commented Apr 18, 2026

Codecov Report

❌ Patch coverage is 0% with 172 lines in your changes missing coverage. Please review.
⚠️ Please upload report for BASE (main@268108f). Learn more about missing BASE report.

Files with missing lines Patch % Lines
pkg/cantonsdk/token/client.go 0.00% 102 Missing ⚠️
pkg/cantonsdk/token/registry_client.go 0.00% 54 Missing ⚠️
pkg/cantonsdk/values/meta.go 0.00% 7 Missing ⚠️
pkg/cantonsdk/client/client.go 0.00% 4 Missing ⚠️
pkg/cantonsdk/token/config.go 0.00% 2 Missing ⚠️
pkg/cantonsdk/token/options.go 0.00% 2 Missing ⚠️
pkg/cantonsdk/token/encode.go 0.00% 1 Missing ⚠️

❌ 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

Impacted file tree graph

@@           Coverage Diff           @@
##             main     #227   +/-   ##
=======================================
  Coverage        ?   32.20%           
=======================================
  Files           ?      126           
  Lines           ?     8791           
  Branches        ?        0           
=======================================
  Hits            ?     2831           
  Misses          ?     5710           
  Partials        ?      250           
Flag Coverage Δ
unittests 32.20% <0.00%> (?)

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
pkg/token/config.go 84.61% <ø> (ø)
pkg/cantonsdk/token/encode.go 0.00% <0.00%> (ø)
pkg/cantonsdk/token/config.go 0.00% <0.00%> (ø)
pkg/cantonsdk/token/options.go 0.00% <0.00%> (ø)
pkg/cantonsdk/client/client.go 0.00% <0.00%> (ø)
pkg/cantonsdk/values/meta.go 0.00% <0.00%> (ø)
pkg/cantonsdk/token/registry_client.go 0.00% <0.00%> (ø)
pkg/cantonsdk/token/client.go 0.00% <0.00%> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces configuration for Canton instrument mapping and holding package IDs across various environment and test configuration files. Key changes include adding splice_holding_package_id to the Canton token configuration and instrument_id to the ERC-20 token metadata. Feedback highlights that the promised default logic for InstrumentAdmin is missing, and the new SpliceHoldingPackageID is currently unused in the client implementation. Additionally, the mainnet configuration files should use environment variables for the new package ID to maintain consistency with existing settings.

Comment thread pkg/token/config.go Outdated
Comment thread pkg/cantonsdk/token/config.go
Comment thread pkg/config/defaults/config.api-server.mainnet.yaml Outdated
Comment thread pkg/config/defaults/config.relayer.mainnet.yaml Outdated
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
Comment thread pkg/token/config.go Outdated
* 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
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.
Resolve conflict in tests/e2e/tests/bridge/withdrawal_test.go: keep the
*stack.Token pointer signature from this branch and the receiver.Address
account from main (the test withdraws from receiver, not User1).
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.
@salindne salindne merged commit 6a8b4a9 into main Apr 28, 2026
4 checks passed
@salindne salindne deleted the feat/212-instrument-id-config branch April 28, 2026 19:36
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.

Add instrument_id to token config

4 participants