import { type BytesLike } from 'ethers'; import { type BlockInfo, type ChainContext, type ChainStatic, type GetBalanceOpts, type LogFilter, type RegistryTokenConfig, type TokenInfo, type TokenPoolConfig, type TokenPoolRemote, Chain } from '../chain.ts'; import type { ExtraArgs } from '../extra-args.ts'; import type { LeafHasher } from '../hasher/common.ts'; import { type NetworkInfo, ChainFamily } from '../networks.ts'; import { type CCIPExecution, type CCIPMessage, type CCIPRequest, type CCIPVerifications, type ChainLog, type ChainTransaction, type CommitReport, type ExecutionReceipt, type Lane, type LeanNumbers, type OffchainTokenData, type WithLogger } from '../types.ts'; import { type CantonClient } from './client/index.ts'; import { AcsDisclosureProvider } from './explicit-disclosures/acs.ts'; import { EdsDisclosureProvider } from './explicit-disclosures/eds.ts'; import { type TokenMetadataClient } from './token-metadata/client.ts'; import { type TransferInstructionClient } from './transfer-instruction/client.ts'; import { type UnsignedCantonTx } from './types.ts'; export type { CantonClient, CantonClientConfig, HashingSchemeVersion, PartySignatures, Signature, SinglePartySignatures, } from './client/index.ts'; export type { CantonCCVSendInput, CantonExtraArgsV1, CantonInstrumentId, CantonTokenExtraArgs, CantonTokenInput, CantonWallet, TransactionSigner, UnsignedCantonTx, } from './types.ts'; export { isCantonWallet, parseInstrumentId } from './types.ts'; /** * Canton chain implementation supporting Canton Ledger networks. * */ export declare class CantonChain extends Chain { static readonly family: "CANTON"; /** Canton uses 10 decimals (lf-coin micro-units) */ static readonly decimals = 10; readonly network: NetworkInfo; readonly provider: CantonClient; readonly acsDisclosureProvider: AcsDisclosureProvider; readonly edsDisclosureProvider: EdsDisclosureProvider; readonly transferInstructionClient: TransferInstructionClient; readonly tokenMetadataClient: TokenMetadataClient; readonly indexerUrl: string; readonly ccipParty: string; /** Custom fetch function supplied via ctx, used for indexer requests. Falls back to globalThis.fetch. */ private readonly fetchFn; /** * Creates a new CantonChain instance. * @param client - Canton Ledger API client. * @param acsDisclosureProvider - ACS-based disclosure provider. * @param edsDisclosureProvider - EDS-based disclosure provider. * @param transferInstructionClient - Transfer Instruction API client. * @param tokenMetadataClient - Token Metadata API client. * @param ccipParty - The party ID to use for CCIP operations * @param indexerUrl - Base URL of the CCV indexer service. * @param network - Network information for this chain. * @param ctx - Context containing logger. */ constructor(client: CantonClient, acsDisclosureProvider: AcsDisclosureProvider, edsDisclosureProvider: EdsDisclosureProvider, transferInstructionClient: TransferInstructionClient, tokenMetadataClient: TokenMetadataClient, ccipParty: string, indexerUrl: string, network: NetworkInfo, ctx?: ChainContext); /** * Mapping from lower-cased synchronizer alias variants to their canonical Canton chain ID * as it appears in selectors.ts (e.g. `canton:MainNet`). */ private static readonly SYNCHRONIZER_ALIAS_TO_CHAIN_ID; /** * Default Canton chain ID to use when the synchronizer alias is ambiguous * (e.g. the generic "global" alias used across all Canton environments). */ private static readonly DEFAULT_CANTON_CHAIN_ID; /** * Detect the Canton network and instantiate a CantonChain. * * Network detection works by querying the connected synchronizers via * `/v2/state/connected-synchronizers` and matching the `synchronizerAlias` of the * first recognised synchronizer against the known Canton chain names. * * @throws {@link CCIPChainNotFoundError} if no connected synchronizer alias maps to a known Canton chain */ static fromClient(client: CantonClient, acsDisclosureProvider: AcsDisclosureProvider, edsDisclosureProvider: EdsDisclosureProvider, transferInstructionClient: TransferInstructionClient, tokenMetadataClient: TokenMetadataClient, ccipParty: string, indexerUrl?: string, ctx?: ChainContext): Promise; /** * Creates a CantonChain instance from a Canton Ledger JSON API URL. * Verifies the connection and detects the network. * * @param url - Base URL for the Canton Ledger JSON API (e.g., http://localhost:7575). * @param ctx - Context containing logger. * @returns A new CantonChain instance. * @throws {@link CCIPHttpError} if connection to the Canton Ledger JSON API fails * @throws {@link CCIPNotImplementedError} if Canton network detection is not yet implemented */ static fromUrl(url: string, ctx?: ChainContext): Promise; /** * {@inheritDoc Chain.getBlockInfo} * @throws {@link CCIPNotImplementedError} Canton ledger uses offsets, not block numbers */ getBlockInfo(block: number | 'finalized' | 'latest'): Promise; /** * Fetches a Canton transaction (update) by its update ID. * * The ledger is queried via `/v2/updates/transaction-by-id` with a wildcard * party filter so that all visible events are returned without requiring a * known party ID. * * Canton concepts are mapped to {@link ChainTransaction} fields as follows: * - `hash` — the Canton `updateId` * - `blockNumber` — the ledger `offset` * - `timestamp` — `effectiveAt` parsed to Unix seconds * - `from` — first `actingParties` entry of the first exercised event * - `logs` — one {@link ChainLog} per transaction event * * @param hash - The Canton update ID (transaction hash) to look up. * @returns A {@link ChainTransaction} with events mapped to logs. */ getTransaction(hash: string): Promise; /** * {@inheritDoc Chain.getLogs} * @throws {@link CCIPNotImplementedError} always (not yet implemented for Canton) */ getLogs(_opts: LeanNumbers): AsyncIterableIterator; /** * {@inheritDoc Chain.typeAndVersion} * @throws {@link CCIPNotImplementedError} always (not yet implemented for Canton) */ typeAndVersion(_address: string): Promise<[type: string, version: string, typeAndVersion: string, suffix?: string]>; /** {@inheritDoc Chain.getOnRampConfig} */ getOnRampConfig(_onRamp: string, _destChainSelector: bigint): ReturnType; /** {@inheritDoc Chain.getOffRampConfig} */ getOffRampConfig(_offRamp: string, _sourceChainSelector: bigint): ReturnType; /** * Returns Canton's default fee token. * * Canton's default fee token is registry-level (not router-level): the * Amulet instrument exposed by the token-metadata registry. */ getNativeTokenForRouter(_router: string): Promise; /** * {@inheritDoc Chain.getOffRampsForRouter} * @throws {@link CCIPNotImplementedError} always (not yet implemented for Canton) */ getOffRampsForRouter(_router: string, _sourceChainSelector: bigint): Promise; /** * {@inheritDoc Chain.getOnRampForRouter} * @throws {@link CCIPNotImplementedError} always (not yet implemented for Canton) */ getOnRampForRouter(_router: string, _destChainSelector: bigint): Promise; /** * Returns token symbol and decimals for the given Canton fee token. * * Looks up the instrument in the Canton token-metadata registry. `token` is * the full Canton fee-token string (`"admin::id"`); the registry is keyed by * the local `id` portion. */ getTokenInfo(token: string): Promise<{ symbol: string; decimals: number; }>; /** * {@inheritDoc Chain.getBalance} * @throws {@link CCIPNotImplementedError} always (not yet implemented for Canton) */ getBalance(_opts: GetBalanceOpts): Promise; /** * {@inheritDoc Chain.getTokenAdminRegistryFor} * @throws {@link CCIPNotImplementedError} always (not yet implemented for Canton) */ getTokenAdminRegistryFor(_address: string): Promise; /** * Returns the CCIP fee for sending a message. * * Canton has no scalar upfront CCIP fee — the cost is computed inside the * on-chain command at send time. Returns `0n` so `--only-get-fee` and the * balance check both pass cleanly. */ getFee(_opts: Parameters[0]): Promise; /** {@inheritDoc Chain.generateUnsignedSendMessage} */ generateUnsignedSendMessage(opts: Parameters[0]): Promise; /** * {@inheritDoc Chain.sendMessage} */ sendMessage(opts: Parameters[0]): Promise; /** * {@inheritDoc Chain.getOffchainTokenData} */ getOffchainTokenData(request: CCIPRequest): Promise; /** * Builds a Canton `JsCommands` payload that exercises the `Execute` choice on * the caller's `CCIPReceiver` contract. The command includes: * * 1. **ACS disclosures** – same-party contracts (`PerPartyRouter`, * `CCIPReceiver`) fetched via {@link AcsDisclosureProvider}. * 2. **EDS disclosures** – cross-party contracts (OffRamp, GlobalConfig, * TokenAdminRegistry, RMNRemote, CCVs) fetched via * {@link EdsDisclosureProvider}. * 3. **Choice argument** – assembled from the encoded CCIP message, * verification data, and the opaque `contextData` returned by the EDS. * * @param opts - Must use the `offRamp` + `input` variant of {@link ExecuteOpts}. * `input` must contain `encodedMessage` and `verifications` (CCIP v2.0). * `payer` is the Daml party ID used for `actAs`. * @returns An {@link UnsignedCantonTx} wrapping the ready-to-submit * `JsCommands`. */ generateUnsignedExecute(opts: Parameters[0]): Promise; /** * Executes a CCIP message on Canton by: * 1. Validating the wallet as a {@link CantonWallet}. * 2. Building the unsigned command via {@link generateUnsignedExecute}. * 3. Submitting the command to the Canton Ledger API. * 4. Parsing the resulting transaction into a {@link CCIPExecution}. * * @throws {@link CCIPWalletInvalidError} if wallet is not a valid {@link CantonWallet} * @throws {@link CCIPError} if the Ledger API submission or result parsing fails */ execute(opts: Parameters[0]): Promise; /** * Submit a command to the ledger, using external signing when a * {@link TransactionSigner} is provided. * * - **No signer**: delegates to `submitAndWaitForTransaction` (direct submit). * - **With signer**: uses the interactive submission API: * 1. Prepare the transaction (`/v2/interactive-submission/prepare`). * 2. Decode the hash and call `signer.sign(hashBytes)`. * 3. Execute the signed transaction (`/v2/interactive-submission/executeAndWaitForTransaction`). */ private submitCommands; /** * Find or create a `CCIPReceiver` contract whose `minBlockConfirmations` equals `finality`. * * The `OffRamp.PrepareExecute` Daml choice rejects messages whose `finality` field does not * match the receiver's `minBlockConfirmations`, so each distinct finality value needs its own * receiver instance. This method first searches the ACS; if no match is found it creates a * fresh contract (mirroring the Go `deployReceiver` helper in the staging script). */ private createReceiverForFinality; /** * Fetches CCV verification results for a CCIP message from the Canton indexer. * @param opts - Options that should only include the CCIP request with the message ID to query. * @returns CCIPVerifications with verification policy and individual verifier results. */ getVerifications(opts: Parameters[0]): Promise; /** * {@inheritDoc Chain.getSupportedTokens} * @throws {@link CCIPNotImplementedError} always (not yet implemented for Canton) */ getSupportedTokens(_address: string, _opts?: { page?: number; }): Promise; /** * {@inheritDoc Chain.getRegistryTokenConfig} * @throws {@link CCIPNotImplementedError} always (not yet implemented for Canton) */ getRegistryTokenConfig(_registry: string, _token: string): Promise; /** * {@inheritDoc Chain.getTokenPoolConfig} * @throws {@link CCIPNotImplementedError} always (not yet implemented for Canton) */ getTokenPoolConfig(_tokenPool: string): Promise; /** * {@inheritDoc Chain.getTokenPoolRemotes} * @throws {@link CCIPNotImplementedError} always (not yet implemented for Canton) */ getTokenPoolRemotes(_tokenPool: string, _remoteChainSelector?: bigint): Promise>; /** * {@inheritDoc Chain.getFeeTokens} * @throws {@link CCIPNotImplementedError} always (not yet implemented for Canton) */ getFeeTokens(_router: string): Promise>; /** * Fetch a fresh Transfer Factory and choice context for a specific Canton instrument. */ private getTransferFactoryForInstrument; /** * Resolve token-transfer sender holdings, optionally constrained to caller-supplied CIDs. */ private resolveTokenTransferHoldings; /** * Resolve the registry-default fee token (Amulet) for this Canton chain. * * The fee token is registry-level, not router- or party-dependent: a single * metadata lookup yields `"::Amulet"`, where `adminId` is itself a * Daml party ID (`name::fingerprint`). */ private getDefaultFeeToken; /** * Fill in Canton-specific fields that {@link generateUnsignedSendMessage} * requires but the generic `sendMessage` caller (e.g. the CLI) does not * know how to populate: a default `feeToken` if missing, and at least one * `feeTokenHoldingCids` entry discovered from `party`'s holdings. */ private fillCantonSendDefaults; /** * Try to decode a CCIP message from a Canton log/event. * @returns undefined (Canton message format not yet supported) */ static decodeMessage(_log: Pick): CCIPMessage | undefined; /** * Try to decode extra args serialized for Canton. * @returns undefined (Canton extra args format not yet supported) */ static decodeExtraArgs(_extraArgs: BytesLike): undefined; /** * Encode extraArgs for Canton. * @throws {@link CCIPNotImplementedError} always (not yet implemented for Canton) */ static encodeExtraArgs(_extraArgs: ExtraArgs): string; /** * Try to decode a commit report from a Canton log. * @returns undefined (Canton commit format not yet supported) */ static decodeCommits(_log: Pick, _lane?: Lane): CommitReport[] | undefined; /** * Try to decode an execution receipt from a Canton log. * @returns undefined (Canton receipt format not yet supported) */ static decodeReceipt(_log: Pick): ExecutionReceipt | undefined; /** * Receive bytes and try to decode as a Canton address (Daml party ID or contract ID). * * @param bytes - Bytes or string to convert. * @returns Canton address string. * @throws {@link CCIPNotImplementedError} if bytes cannot be decoded as a Canton address */ static getAddress(bytes: BytesLike): string; /** * Validates a transaction (update) ID format for Canton. * Canton update IDs are base64-encoded strings. */ static isTxHash(v: unknown): v is string; /** * Gets the leaf hasher for Canton destination chains. * @throws {@link CCIPNotImplementedError} always (not yet implemented for Canton) */ static getDestLeafHasher(_lane: Lane, _ctx?: WithLogger): LeafHasher; /** * Build a message targeted at this Canton destination chain, populating missing fields. */ static buildMessageForDest(message: Parameters[0]): import("../types.ts").AnyMessage; } //# sourceMappingURL=index.d.ts.map