Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
258 changes: 221 additions & 37 deletions src/content/ccip/llms-full.txt

Large diffs are not rendered by default.

81 changes: 71 additions & 10 deletions src/content/ccip/v2/canton/concepts/explicit-disclosure.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ metadata:
description: "Explicit Disclosure Services for CCIP on Canton: global CCIP API, token pool operator APIs, CNS discovery, and reference EDS deployment."
excerpt: "CCIP Canton EDS, explicit disclosure, token pool API, Global CCIP API, CNS discovery, chainlink-canton"
datePublished: "2026-06-27"
lastModified: "2026-06-27"
lastModified: "2026-10-13"
difficulty: "intermediate"
estimatedTime: "10 minutes"
whatsnext:
Expand Down Expand Up @@ -38,7 +38,7 @@ curl --request POST \
--header 'content-type: application/json' \
--data '{
"addresses": [
"tokenadminregistry-lzrnd@ccipOwner::1220e382f4e57b0815e6be737006e381e6b7de448e06bd033ece6df498017879f551"
"tokenadminregistry-nbehb@ccipOwner::1220e382f4e57b0815e6be737006e381e6b7de448e06bd033ece6df498017879f551"
]
}'
```
Expand Down Expand Up @@ -80,17 +80,78 @@ Most issuers only need the `token_pool_api` block. Set `type = ""` or omit the b

### Configuration reference

| Field | Meaning |
| :--------------------------- | :-------------------------------------------------------------------------------------------- |
| `chain_selector` | Local Canton chain selector (distinct from remote selectors in `ApplyChainUpdates`). |
| `[node].url` | Participant gRPC Ledger API endpoint. EDS reads the Active Contract Set over this connection. |
| `[node.auth].type` | `static`, `insecureStatic`, `clientCredentials`, or `authorizationCode`. |
| `map key / instance_address` | Each pool keyed by instance address hex; map key **must** equal `instance_address`. |
| `type` | `burnMint` or `lockRelease`. |
| `pool_owner` | Pool owner party (should equal `instrumentId.admin`). |
| Field | Meaning |
| :--------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `chain_selector` | Local Canton chain selector (distinct from remote selectors in `ApplyChainUpdates`). |
| `[node].url` | Participant gRPC Ledger API endpoint. EDS reads the Active Contract Set over this connection. |
| `[node.auth].type` | `static`, `insecureStatic`, `clientCredentials`, or `authorizationCode`. |
| `map key / instance_address` | Each pool keyed by instance address hex; map key **must** equal `instance_address`. |
| `type` | `burnMint` or `lockRelease`. |
| `pool_owner` | Pool owner party (should equal `instrumentId.admin`). |
| `[factory].type` | BurnMint pools only: `address` (EDS reads the factory directly from the ACS — needs `template_id`, `party`, `instance_address`) or `url` (EDS calls the DA registry backend's `getBurnMintFactory` endpoint at serve time — needs `token_standard_url`). See the [BurnMint guide](/ccip/canton/tutorials/cross-chain-tokens/burn-mint-token-pool#serve-the-factory-from-your-eds). |

Operators using the provided token pool contracts can run the reference implementation without custom code. **Custom pool implementations** must implement the standardized API endpoints or adapt the reference.

### Example config (BurnMint pool, URL-mode factory)

A minimal EDS config for a single BurnMint pool whose factory is resolved via the DA registry backend. Secrets (`client_secret`, JWTs) do **not** go in this file — pass a second, secrets-only TOML via `CONFIG_FILE=config.toml,config_secrets.toml` (later files override earlier ones):

```toml filename="config.toml"
chain_selector = "9268731218649498074" # local Canton chain selector

[server]
host = "0.0.0.0"
port = 8088

[node]
url = "participant.grpc-ledger-api.example.com:443"
max_retries = 10

[node.auth]
type = "clientCredentials"
user_id = "user-eds"
auth_url = "https://auth.example.com" # OIDC issuer; EDS discovers the token endpoint via RFC 8414
client_id = "eds-client"
# client_secret is set in the layered secrets file (config_secrets.toml), not here

# ccip_api, ccv_api, and executor_api are not needed when serving only your own pool.
[ccip_api]
enabled = false

[ccv_api]
enabled = false

[executor_api]
enabled = false

[token_pool_api]
enabled = true

# Map key must equal instance_address: the Keccak256 hash of "<pool_instance_id>@<pool_owner_party>"
[token_pool_api.token_pools."0x…"]
party_id = "<party with ACS visibility of the pool>" # stakeholder used for ACS reads; not necessarily the pool owner
instance_address = "0x…"
type = "burnMint"
pool_owner = "<pool owner party>"

# Factory resolution via the DA registry backend (registry instruments only).
[token_pool_api.token_pools."0x…".factory]
type = "url"
token_standard_url = "https://api.utilities.digitalasset.com" # mainnet; testnet: https://api.utilities.digitalasset-staging.com
# token_standard_auth is omitted — the DA endpoint is public
```

```toml filename="config_secrets.toml"
[node.auth]
client_secret = "<injected from your secret manager>"
```

<Aside type="note" title="Auth discovery">

`clientCredentials` auth requires `auth_url` and discovers the token endpoint via RFC 8414 (`.well-known/oauth-authorization-server`). If your authorization server only serves the OIDC `openid-configuration` document, ask Chainlink ops — an explicit token-endpoint override is not yet exposed in the config.

</Aside>

## Operator responsibilities

- **Availability** — EDS must stay reachable; users cannot send or execute token transfers involving your pool if it is down.
Expand Down
8 changes: 4 additions & 4 deletions src/content/ccip/v2/canton/concepts/manual-execution.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -82,12 +82,12 @@ Using the [CCIP CLI](https://github.com/smartcontractkit/ccip-tools-ts/blob/main

The SDK **finds or creates** a compatible `CCIPReceiver` on the default path — see [Canton as Destination](/ccip/canton/tutorials/destination) tutorials.

### 4. Token transfers — accept holdings
### 4. Token transfers — holdings arrive with execution

If the message included a token transfer:
If the message included a token transfer, the token release runs **inside the same Execute transaction** as the manual-exec command — you do not submit a separate accept step on the CCIP path:

1. The token pool creates a **`TransferInstruction`** to the receiver party.
2. The receiver party must **accept** the `TransferInstruction` to take custody — this is separate from the CCIP execute step.
- **BurnMint pools** (the default testnet TEST ↔ LINK lane): the pool's `BurnMintFactory` mints holdings directly to the receiver party within the execution transaction. Tokens are in the receiver's holdings as soon as it commits — there is no `TransferInstruction` to accept.
- **LockRelease pools**: the pool transfers from the pool owner's holdings within the same transaction. When the receiver's transfer preapproval is included in the EDS-supplied execute context, the transfer completes immediately. Without a preapproval, the transaction instead leaves a **pending `TransferInstruction`** that the receiver must accept separately via their token's transfer-instruction API or wallet — the manual-exec command does not accept pending instructions.

For programmable token transfers, your receiver logic runs after tokens are available.

Expand Down
6 changes: 3 additions & 3 deletions src/content/ccip/v2/canton/concepts/overview.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -83,10 +83,10 @@ To execute, the user interacts with the [`CCIPReceiver` contract](https://github
- On success, the OffRamp/TokenPool consumes tickets and, for token transfers, issues a `TokenReceiveTicket`.
- `PerPartyRouter` marks the message executed to prevent double execution.

If the message contained a token transfer, the receiver uses the `TokenReceiveTicket` to call the token pool:
If the message contained a token transfer, the receiver uses the `TokenReceiveTicket` to call the token pool — the release runs inside the same execution transaction:

1. The token pool verifies the ticket was issued by the CCIP owner and creates an outgoing `TransferInstruction` to the token receiver party.
2. The receiver party accepts the `TransferInstruction` to gain access to the transferred tokens.
1. **BurnMint pools** mint holdings directly to the token receiver party — no `TransferInstruction` is created.
2. **LockRelease pools** transfer from the pool owner's holdings via the token's `TransferFactory` — the transfer completes immediately when the receiver's preapproval is included in the EDS-supplied context; otherwise a pending `TransferInstruction` is left for the receiver party to accept separately.

## Canton → Public chain

Expand Down
Loading
Loading