# Choose your path Source: https://cantor8.mintlify.app/choose-your-path Pick the right Cantor8 product for your team in 30 seconds. Three products, three jobs. Pick the one that matches what you're building. **You're building a dApp** that needs Canton wallet connectivity. **You're an institution** holding and moving Canton assets at scale. **You're an issuer** launching a token, stablecoin, or RWA on Canton. ## Not sure which fits? Start by role Building a DeFi, payments, or trading application that needs wallet connectivity. **Start here if you want to:** * Let users connect a Canton wallet * Request approvals and submit transfers * Skip building auth, signing, or ledger plumbing Bank, fund, custodian, broker, or treasury team operating on Canton. **Start here if you want to:** * Hold and move multi-asset balances at scale * Apply role-based controls and approval policies * Maintain audit-ready logging and reporting Issuing a stablecoin, security, RWA, or loyalty asset on Canton. **Start here if you want to:** * Define and configure a Canton-native asset * Control mint, burn, transfer, and registry * Skip writing DAML or running issuance infrastructure Evaluating Cantor8 for an enterprise use case. **Start here if you need to:** * Understand how the products fit together * Map a workflow to one or more products * Compare options before committing *** ## Decide product by product Still on the fence? Here's a closer look at each product — when it's the right fit, and when you should pick a different one. ## Wallet SDK * You're a DeFi, payments, or trading dApp * You need users to connect a wallet and approve actions * You don't want to build auth, signing, or ledger plumbing * You need to **issue** assets → Token Factory * You need **institutional custody** → Enterprise Wallet ## Enterprise Wallet * You're a bank, fund, custodian, or treasury team * You need role-based controls and approval policies * You hold multi-asset balances at scale * You're an end-user dApp → Wallet SDK * You're creating a new token → Token Factory ## Token Factory * You're issuing a stablecoin, security, or RWA * You need mint, burn, transfer, and registry controls * You don't want to write DAML or maintain a token registry * You only need to **hold** existing assets → Enterprise Wallet * You only need to **connect** users to a wallet → Wallet SDK ## By goal Looking for a specific outcome? Jump straight to the right starting page. | I want to… | Start here | | ----------------------------------------------- | --------------------------------------------------------------------------- | | Connect users to a Canton wallet from my dApp | [Wallet SDK — Introduction](/wallet-sdk/introduction) | | Let users approve and sign Canton transfers | [Wallet SDK — Quick start](/wallet-sdk/quick-start) | | Hold and operate institutional Canton balances | [Enterprise Wallet — Common use cases](/enterprise-wallet/common-use-cases) | | Apply approval policies and role-based controls | [Enterprise Wallet — Common use cases](/enterprise-wallet/common-use-cases) | | Launch a new stablecoin, security, or RWA | [Token Factory — Common use cases](/token-factory/common-use-cases) | | Manage mint, burn, and registry for a token | [Token Factory — Common use cases](/token-factory/common-use-cases) | | Combine issuance, custody, and end-user access | See [Combining products](#combining-products) | ## Combining products Most teams use **more than one** Cantor8 product. Common combinations: **Token Factory** to issue → **Enterprise Wallet** to hold treasury → **Wallet SDK** to give end users access. **Wallet SDK** for the user experience → **Enterprise Wallet** as the custody backend for institutional accounts. **Enterprise Wallet** for custody → **Token Factory** to issue fund units or share classes. **Enterprise Wallet** for settlement balances → **Wallet SDK** for the merchant or partner UI. ## Getting help Reach out at [**integrations@cantor8.io**](mailto:integrations@cantor8.io) to discuss your use case, get credentials, or scope a custom integration. # Authentication Source: https://cantor8.mintlify.app/enterprise-wallet/authentication OIDC-compliant security layer with dual-layer in-memory caching. The service implements a configurable, **OIDC-compliant security layer** designed for Zero-Trust environments. ## Operational modes Authentication is treated as a toggleable effect. The mode is determined strictly by the `AUTH_TYPE` environment variable. `auth0` · `keycloak` · `custom` The service acts as a gatekeeper. All protected endpoints require a valid `Bearer` token in the `Authorization` header. `noop` The security layer defaults to a no-op provider, permitting all requests without validation. All authentication checks are skipped. ## Performance and caching To maintain sub-millisecond overhead, the validation logic avoids synchronous round-trips to the Identity Provider on every request. Instead, it uses a **dual-layer in-memory strategy**. Once a JWT is cryptographically verified, its valid state is cached until the token's natural expiration (`exp` claim). Subsequent requests with the same token **bypass signature verification entirely**. Public keys (JSON Web Key Set) needed for verification are cached long-term and refreshed only if a token references an unknown Key ID (`kid`) — handling key rotation automatically. ## Request flow ```mermaid theme={null} sequenceDiagram participant Client participant Gatekeeper participant L1 as L1 Cache
(JWT, Sessions) participant L2 as L2 Cache
(JWKS) participant IdP as Identity Provider Client->>Gatekeeper: HTTP GET (Bearer Token) Note right of Gatekeeper: Layer 1: Session Check Gatekeeper->>L1: Get(Token) alt Cache Hit (Fast Path) L1-->>Gatekeeper: Valid Session else Cache Miss (Slow Path) Note right of Gatekeeper: Layer 2: Key Lookup Gatekeeper->>Gatekeeper: Verify Header Gatekeeper->>L2: GetKey(kid) opt Key Missing (Rotation) L2->>IdP: Fetch JWKS IdP-->>L2: Public Keys end L2-->>Gatekeeper: Public Key Gatekeeper->>Gatekeeper: Verify Signature & Claims Gatekeeper->>L1: Put(Token, Session, TTL=exp) L1-->>Gatekeeper: Valid Session end Gatekeeper-->>Client: 200 OK ``` # Auto-Batch Source: https://cantor8.mintlify.app/enterprise-wallet/auto-batch Optional background engine that aggregates transfers into batched ledger submissions for high throughput. Auto-Batch is an optional background feature that automatically aggregates pending transfer orders into batched ledger submissions. Instead of one interactive transaction per transfer, up to `AUTO_BATCH_MAX_SIZE` transfers for the same party are collapsed into a single submission — significantly improving throughput under load. ## Enabling Auto-Batch is **disabled by default** (`AUTO_BATCH_SWITCH=false`). When disabled, no background loops run and the HTTP server behaves exactly as before this feature was introduced. ```bash theme={null} AUTO_BATCH_SWITCH=true ``` ## Database The feature persists batch state in a relational store. Two backends are supported: An H2 database in PostgreSQL-compatibility mode. No extra infrastructure required. **State does not survive a restart.** A PostgreSQL instance for persistent, production-grade storage. Set `AUTO_BATCH_DB_TYPE=psql`. The default is `in-memory` for **backward compatibility**. Existing deployments can opt into auto-batching without provisioning a PostgreSQL instance. The database is initialised on every startup (schema migrations apply automatically). In `in-memory` mode the store is empty after each restart — any in-flight batches from a prior run are not recovered. ## Batch lifecycle An `Order` (a single transfer request submitted via the HTTP API) moves through two independent state machines: | Entity | Terminal success | Terminal failure | | --------- | -------------------------------- | ----------------------------------------------------- | | **Order** | `Dequeue` (picked up by a batch) | (released back to `Queued` if batch fails terminally) | | **Batch** | `Confirmed` | `Failed` with `attempts ≥ maxAttempts` | ```mermaid theme={null} stateDiagram-v2 direction LR [*] --> Prepared : prepareBatch Prepared --> Submitted : submitBatch (batching / recovery) Prepared --> Failed : submitBatch (sync error) Submitted --> Accepted : ledger ack Submitted --> Failed : ledger rejects Accepted --> Confirmed : ledger confirms Accepted --> Failed : ledger rejects Failed --> Submitted : retry (attempts < maxAttempts) Failed --> [*] : terminal (attempts ≥ maxAttempts) Confirmed --> [*] ``` ### Key invariants * `attempts` is incremented **before** each submission attempt (atomically). Both synchronous errors (network, SDK) and asynchronous ledger rejections consume exactly one credit — no silent infinite retries. * Every `update()` uses **optimistic locking** (keyed on `batch.updatedAt`) so the three concurrent loops never corrupt each other's state. ## Background loops `BatchOrdersJob` spawns three loops in parallel. All loops share the same **exponential-backoff wrapper** (1 s → 60 s, with jitter) that activates on unhandled errors, preventing cascading failures from hammering downstream services. Prepares and submits one new batch per idle party per cycle. Also recovers `Prepared` batches with `attempts = 0` that were created before a restart. ```mermaid theme={null} sequenceDiagram participant batchingLoop participant BatchOrdersWorker participant BatchStore participant OrdersStore participant WalletService loop every batchInterval batchingLoop->>BatchOrdersWorker: recoverPreparedBatches() BatchOrdersWorker->>BatchStore: searchByStatus(Prepared) note over BatchOrdersWorker: submit any stuck batches (attempts = 0, never flew) batchingLoop->>BatchOrdersWorker: prepareBatch() BatchOrdersWorker->>BatchStore: searchActives() note over BatchOrdersWorker,OrdersStore: exclude parties with any active batch BatchOrdersWorker->>OrdersStore: searchNextAvailables(excludedParties, limit) alt orders found for an idle party BatchOrdersWorker->>BatchStore: create(Batch, orderIds) note over BatchOrdersWorker,BatchStore: atomic: Batch(Prepared) + Order status → Dequeue batchingLoop->>BatchOrdersWorker: submitBatch(batchId) BatchOrdersWorker->>BatchStore: incrementAttempts(batchId) BatchOrdersWorker->>WalletService: batchSend(from, transfers) BatchOrdersWorker->>BatchStore: update(Submitted) else no idle orders batchingLoop->>batchingLoop: sleep(batchInterval) end end ``` Polls the ledger for every in-flight batch (`Submitted` or `Accepted`) and advances its state. Terminal outcomes (`Confirmed`, `Failed`) are written back; the retry loop handles `Failed`. ```mermaid theme={null} sequenceDiagram participant monitoringLoop participant BatchOrdersMonitor participant BatchStore participant WalletService loop every monitorInterval monitoringLoop->>BatchStore: searchMonitoreables() note over BatchStore: Submitted + Accepted only loop each in-flight batch monitoringLoop->>BatchOrdersMonitor: monitorBatch(batchId) BatchOrdersMonitor->>WalletService: commandStatus(partyId, commandId) alt confirmed BatchOrdersMonitor->>BatchStore: update(Confirmed) else failed BatchOrdersMonitor->>BatchStore: update(Failed) note over BatchOrdersMonitor: attempts already counted retryingLoop will handle retry else in-flight BatchOrdersMonitor->>BatchStore: update(Accepted) end end monitoringLoop->>monitoringLoop: sleep(monitorInterval) end ``` Separates failed batches into two groups: those still within the retry budget are re-submitted; those that have exhausted `maxAttempts` are marked terminal and their orders are released back to `Queued`. ```mermaid theme={null} sequenceDiagram participant retryingLoop participant BatchOrdersWorker participant BatchStore participant BatchOrdersStore loop every retryInterval retryingLoop->>BatchStore: searchFailed() loop terminal batches (attempts ≥ maxAttempts) retryingLoop->>BatchOrdersStore: searchIn(batchId) retryingLoop->>BatchStore: markAsFailedAndReleaseOrders(batchId, orderIds) note over BatchStore: atomic: status → Failed + orders → Queued end loop retriable batches (0 < attempts < maxAttempts) retryingLoop->>BatchOrdersWorker: submitBatch(batchId) retryingLoop->>retryingLoop: sleep(recoveryInterval) end retryingLoop->>retryingLoop: sleep(retryInterval) end ``` Tune batch and retry timings via the `AUTO_BATCH_*` environment variables. See [Configuration](/enterprise-wallet/configuration#auto-batch). # Common use cases Source: https://cantor8.mintlify.app/enterprise-wallet/common-use-cases How partners apply C8 Enterprise Wallet — what it is, who it's for, and the business value it delivers. ## What it is C8 Enterprise Wallet is a ready-made custody and operations layer that allows institutions to hold, transfer, and govern Canton-native assets across multiple parties and entities. It gives enterprise teams a compliant and operationally robust way to manage on-ledger assets at scale — with role-based controls, approval policies, and high-throughput execution — without building custody infrastructure from scratch. ## Why it matters For most institutions, operating a wallet at enterprise scale is complex and operationally sensitive. It requires: * Multi-party key management * Role-based access and approval policies * High-throughput transaction execution * Multi-asset balance and reporting C8 Enterprise Wallet removes that complexity. Institutions can focus on their treasury and product operations while C8 handles the custody and execution layer. ## Why it stands out Even teams with no prior ledger experience can easily adopt C8 Enterprise Wallet. It abstracts away the hardest parts of working with ledgers — key management, UTXO handling, party orchestration, ledger communication — so institutions don't need in-house DLT expertise to go live. Partners simply integrate the service and immediately gain capabilities that legacy, centralized payment infrastructure cannot match: * **Private transactions** — sub-transaction privacy at the ledger level, not bolted-on at the application layer. * **Fast settlement** — operations execute in seconds, not the hours or days typical of legacy rails. * **Self-custody by default** — institutions stay in full control of their own funds and keys, instead of trusting a centralized operator. * **Operational simplicity** — C8 takes on the heavy technical lifting; partners focus on their own product and treasury workflows. * **Lower transaction processing costs** — significantly cheaper per-transaction economics compared to traditional fiat infrastructure. The result: enterprises move from outdated, slow, opaque infrastructure to a modern, private, self-custodial layer — without taking on the engineering burden that usually comes with it. ## Who it is for C8 Enterprise Wallet is designed for institutions and operations teams that need to manage Canton-native assets at scale. ## How partners can use it Partners and institutions can embed C8 Enterprise Wallet into their own operational workflows. A typical lifecycle: — all while staying inside the partner operational journey. C8 Enterprise Wallet is the right fit when an institution needs compliant, multi-party custody on Canton but does **not** want to own private key management, policy engines, or direct ledger communication. ## Business value C8 Enterprise Wallet helps institutions **operate Canton-enabled treasury and custody faster**, **reduce operational and compliance risk**, and **provide stakeholders with a trusted enterprise-grade wallet experience** backed by Cantor8 infrastructure. In short: it turns C8 Enterprise Wallet into a plug-in institutional custody layer for partner applications and treasury operations. # Configuration Source: https://cantor8.mintlify.app/enterprise-wallet/configuration Environment variables for bootstrap, authentication, Auto-Batch, and database. The bootstrap logic is fully driven by environment variables. Group them as below. ## Core bootstrap Overrides the default validator endpoint. Used as the app-name fallback during transfer submission. Initializes the wallet with this BIP39 phrase. Effectively "logs in" to wallets derived from this mnemonic. Used as the **BIP39 salt**. Defaults to an empty string for compatibility with standard BIP39 wallets (Trust Wallet, Ledger, etc.) that don't use a passphrase by default. ## Authentication Selected Identity Provider. Supported values: `auth0`, `keycloak`, `custom`, `noop`. Use `noop` to disable the authentication layer. Expected `aud` claim in the JWT. Comma-separated whitelist of accepted JWS asymmetric algorithms. Supported: `RS256`, `RS384`, `RS512`, `ES256`, `ES384`, `ES512`, `EdDSA`, `Ed25519`. ### Identity Provider URLs The set of variables used to derive the JWKS URL depends on `AUTH_TYPE`. The base URL of your IdP. The base URL of your IdP. The OIDC realm used for discovery paths. Custom URL of your IdP — for non-standard paths. ## Auto-Batch Enables the background batching engine. Storage backend for batch state. Accepted: `in-memory`, `psql`. Use `psql` for production. Maximum number of orders per batch. How long the batching loop waits between batch preparation cycles. How long the monitoring loop waits between polling cycles for in-flight batches. Pause between individual submissions during a recovery pass (prevents ledger spikes). How long the retry loop waits between retry cycles for failed batches. Hard ceiling on submission attempts per batch. Once reached, the batch is marked terminal and its orders are released back to the queue. ## PostgreSQL connection Applies only when `AUTO_BATCH_DB_TYPE=psql`. Database server hostname. Database server port. Database name. Database user. Database password. ## Connection pool Applies to both `in-memory` and `psql` backends. Thread pool size for database operations. Maximum pool connections. Minimum idle connections kept alive. Milliseconds to wait for a connection before timing out. Milliseconds before an idle connection is evicted. # Setup & deployment Source: https://cantor8.mintlify.app/enterprise-wallet/docker-compose-deployment Everything you need to set up and run C8 Enterprise Wallet with Docker Compose. This guide walks you through the technical onboarding for C8 Enterprise Wallet — what to share with the C8 team, what you'll receive in return, and how to bring the service up with Docker Compose. ## Before you begin To get started, share the following with the C8 team: * Your DockerHub username The C8 team will then provide: * Access to the C8 DockerHub repository * Integration credentials: * `client_id` * `access_key_id` * `secret_access_key` * A coupon code for MainNet registration You will also need the following on the deployment host: * Docker Compose * A 24-word BIP39 mnemonic phrase that you generate yourself (see [Generate a BIP39 mnemonic](#1-generate-a-bip39-mnemonic) below) **Self-custody notice.** C8 Enterprise Wallet is self-custodial. You must generate and securely store the wallet mnemonic phrase during deployment. If the mnemonic phrase is lost, C8 cannot recover accounts or funds. ## Deployment flow The full deployment is a five-step sequence. Each step is described in detail below. Create the 24-word phrase that backs the self-custodial wallet. Define `WALLET_MNEMONIC`, `CLIENT_ID`, backend URLs, and auth/batch settings in `.env`. Fill in the C8-provided image in `docker-compose-client.yml`. Start the container with the CloudWatch logging parameters. Open Swagger UI and confirm the API is reachable. ## 1. Generate a BIP39 mnemonic Generate a random 24-word BIP39 mnemonic phrase. Using `bip39`: ```bash theme={null} npm install -g bip39 bip39 generate --words=24 ``` Or using `bitcoin-cli`: ```bash theme={null} brew install bitcoin bitcoin-cli mnemonic new 24 ``` Store the mnemonic securely. Do not commit it to source control. ## 2. Create the environment file Create a `.env` file next to `docker-compose-client.yml`: ```bash .env theme={null} WALLET_MNEMONIC= CLIENT_ID= BACKEND_URL=https://wallet-backend.main.digik.cantor8.tech/api IDENTITY_SERVICE_URL=https://id.cantor8.tech SCANNER_API_BASE_URL=https://scanner-ledger-history-server.main.digik.cantor8.tech AUTH_TYPE=noop AUTO_BATCH_SWITCH=false AUTO_BATCH_DB_TYPE=in-memory ``` `AUTH_TYPE=noop` disables authentication for the wallet API. With this setting, all API endpoints are exposed without authentication. For production deployments, C8 can provide Keycloak or Auth0 configuration. When identity-provider authentication is enabled, all C8 Enterprise Wallet API endpoints expect a valid JWT token from the configured IdP. ## 3. Prepare Docker Compose Use the provided `docker-compose-client.yml` template and set the `image` value to the DockerHub image shared by C8: ```yaml docker-compose-client.yml theme={null} services: enterprise-wallet: image: "/:" container_name: c8-enterprise-wallet restart: unless-stopped env_file: - .env ports: - "8080:8080" logging: driver: awslogs options: awslogs-region: ${AWS_REGION} awslogs-group: ${CLOUDWATCH_LOG_GROUP} awslogs-stream: ${CLOUDWATCH_LOG_STREAM} awslogs-endpoint: ${CLOUDWATCH_ENDPOINT} ``` ## 4. Deploy Run Docker Compose with the CloudWatch logging parameters provided during integration: ```bash theme={null} AWS_REGION=eu-west-1 \ CLOUDWATCH_LOG_GROUP=enterprise-wallet \ CLOUDWATCH_LOG_STREAM= \ CLOUDWATCH_ENDPOINT=https://logs.eu-west-1.amazonaws.com \ AWS_ACCESS_KEY_ID= \ AWS_SECRET_ACCESS_KEY= \ docker compose -f docker-compose-client.yml up --force-recreate ``` To run the wallet in the background, add `-d`: ```bash theme={null} AWS_REGION=eu-west-1 \ CLOUDWATCH_LOG_GROUP=enterprise-wallet \ CLOUDWATCH_LOG_STREAM= \ CLOUDWATCH_ENDPOINT=https://logs.eu-west-1.amazonaws.com \ AWS_ACCESS_KEY_ID= \ AWS_SECRET_ACCESS_KEY= \ docker compose -f docker-compose-client.yml up -d --force-recreate ``` ## 5. Verify the deployment After deployment, open Swagger UI: ```text theme={null} http://:8080/docs ``` The public API documentation is also available at: ```text theme={null} https://cantor8.github.io/wallet-api/ ``` ## API account creation When creating new accounts through the API, include the `coupon` parameter: ```json theme={null} { "coupon": "" } ``` The exact value will be provided during integration. ## Configuration reference | Parameter | Description | | ----------------------- | -------------------------------------------------------- | | `WALLET_MNEMONIC` | 24-word BIP39 mnemonic used by the self-custodial wallet | | `CLIENT_ID` | Client identifier provided by C8 | | `BACKEND_URL` | C8 wallet backend API URL | | `IDENTITY_SERVICE_URL` | C8 identity service URL | | `SCANNER_API_BASE_URL` | C8 scanner / ledger history server URL | | `AUTH_TYPE` | API authentication mode. `noop` disables authentication | | `AUTO_BATCH_SWITCH` | Enables or disables auto-batching | | `AUTO_BATCH_DB_TYPE` | Auto-batching storage type, for example `in-memory` | | `AWS_REGION` | AWS region used for CloudWatch logs | | `CLOUDWATCH_LOG_GROUP` | CloudWatch log group name | | `CLOUDWATCH_LOG_STREAM` | CloudWatch log stream name, usually the client ID | | `CLOUDWATCH_ENDPOINT` | CloudWatch Logs endpoint | | `AWS_ACCESS_KEY_ID` | AWS access key ID provided during integration | | `AWS_SECRET_ACCESS_KEY` | AWS secret access key provided during integration | ## Security notes * Keep `.env`, mnemonic phrases, and AWS credentials out of source control. * Use `AUTH_TYPE=noop` only in controlled environments. * Prefer IdP-backed API authentication for production deployments. * Rotate integration credentials according to your organization security policy. ## Try it on DevNet Want to try the wallet before going to production? You can point it at the C8 DevNet environment. 1. In your `.env`, set the following URLs: ```bash .env theme={null} BACKEND_URL=https://wallet-backend.dev.digik.cantor8.tech/api IDENTITY_SERVICE_URL=https://id.dev.digik.cantor8.tech ``` 2. On DevNet, you don't need a signup coupon to register new accounts — just omit the `coupon` parameter when creating accounts through the API. # Getting started Source: https://cantor8.mintlify.app/enterprise-wallet/introduction High-level HTTP API for wallet operations on the Canton Network, designed for institutional workflows. Cantor8 Enterprise Wallet is a **Scala-based service** that provides a high-level HTTP API designed for wallet operations and secure communications with the Canton Ledger. It is built for institutions that need a hardened, OIDC-secured, high-throughput wallet service backing their treasury, settlement, or custody workflows — without owning the underlying ledger plumbing. ## Overview C8 Enterprise Wallet provides: * Support for any token standard enabled on the C8 backend * Pre-approval for incoming token-standard transactions with 1-step transfer * Automated UTXO management * Auto-batching with in-memory or PostgreSQL storage * USDC Bridge support * Optional API authentication through Keycloak or Auth0 * Self-custodial wallet operation ## What you'll find here How partners apply C8 Enterprise Wallet and the value it delivers. OIDC-compliant security layer with dual-layer caching. Optional background engine that aggregates transfers for high throughput. Environment variables, IdP setup, and database tuning. Build and run the service in containers. # About Cantor8 Source: https://cantor8.mintlify.app/index Enterprise-grade infrastructure for the Canton Network — developer documentation. **Cantor8** delivers a unified infrastructure layer for institutions operating on the [Canton Network](https://www.canton.network/) — combining asset issuance, custody, and execution within a single configurable system. Each component is modular and built for control, letting institutions define their own workflows, permissions, and execution logic while integrating with existing financial systems. This site is the **developer documentation** for the three building blocks you can integrate directly today: Embed Canton wallet connectivity into your dApp. Self-custody wallet service for institutional operations. Compliant token issuance, registry, and lifecycle controls. ## Where it fits Cantor8 is built for real-world financial workflows. The same infrastructure powers: * **Tokenised assets** — issuance and lifecycle of digital securities and RWAs with compliance baked into the smart contract layer. * **Treasury operations** — private movement of funds across systems, counterparties, and jurisdictions. * **Payments & payroll** — automated distribution of digital assets across employees, partners, and entities. * **Trading & settlement** — high-performance asset exchange with deterministic execution and final settlement. ## Next steps Pick the fastest path for your role and get to the right docs. Compare the three products and decide which one (or combination) fits. # Quickstart Source: https://cantor8.mintlify.app/quickstart Begin with a guide on the fastest path to a successful outcome This page is the **fastest path into the product docs**. Pick the section that matches what you're building — each one is a self-contained guide. If you're not sure which product fits, start with [Choose your path](/choose-your-path). ## Pick your starting point Connect a Canton wallet and submit your first transfer from a dApp. **Best for:** dApp developers integrating wallet connectivity. Run the self-custodial wallet service with Docker Compose. **Best for:** institutions standing up custody and settlement infrastructure. Scope and onboard a new tokenised asset with the C8 team. **Best for:** issuers launching a stablecoin, security, or RWA. ## Get help Reach out at [**integrations@cantor8.io**](mailto:integrations@cantor8.io) to discuss your use case, get credentials, or scope a custom integration. # API reference Source: https://cantor8.mintlify.app/token-factory/api-reference Token App REST API — admin operations, data queries, status, and health checks. The Token App exposes a REST API for administering tokens (mint, burn), querying historical data (mints, burns, holdings), and inspecting service status and health. All secured endpoints require an HTTP `Bearer` token in the `Authorization` header: ```http theme={null} Authorization: Bearer ``` The code examples below assume two environment variables: ```bash theme={null} export BASE_URL="https://" export TOKEN="" ``` ## Admin Write operations against the ledger. Both endpoints accept an idempotent `command_id` — repeating the same `command_id` won't submit twice. ### `POST /api/admin/mint` Mint new units of an instrument to a recipient party. Client-supplied idempotency key for the ledger submit. Instrument to mint. Recipient party id. Amount to mint. Accepts a number or a decimal string. ```bash cURL theme={null} curl -X POST "$BASE_URL/api/admin/mint" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "command_id": "mint-2025-01-01-001", "instrument_id": "rCC", "party_id": "alice::122...", "amount": "100.0" }' ``` ```ts TypeScript theme={null} const res = await fetch(`${baseUrl}/api/admin/mint`, { method: "POST", headers: { Authorization: `Bearer ${token}`, "Content-Type": "application/json", }, body: JSON.stringify({ command_id: "mint-2025-01-01-001", instrument_id: "rCC", party_id: "alice::122...", amount: "100.0", }), }); const data = await res.json(); ``` ```python Python theme={null} import requests res = requests.post( f"{base_url}/api/admin/mint", headers={"Authorization": f"Bearer {token}"}, json={ "command_id": "mint-2025-01-01-001", "instrument_id": "rCC", "party_id": "alice::122...", "amount": "100.0", }, ) data = res.json() ``` ```json 200 OK theme={null} { "command_id": "mint-2025-01-01-001", "status": "submitted" } ``` ```json 422 Validation Error theme={null} { "detail": [ { "loc": ["body", "amount"], "msg": "value is not a valid decimal", "type": "value_error" } ] } ``` ### `POST /api/admin/burn` Burn units of an instrument held by a party. Client- or system-assigned id for the ledger submit. Instrument to burn. Party whose tokens will be burned (holder or subject). Amount to burn. ```bash cURL theme={null} curl -X POST "$BASE_URL/api/admin/burn" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "command_id": "burn-2025-01-01-001", "instrument_id": "rCC", "party_id": "alice::122...", "amount": "10.0" }' ``` ```ts TypeScript theme={null} const res = await fetch(`${baseUrl}/api/admin/burn`, { method: "POST", headers: { Authorization: `Bearer ${token}`, "Content-Type": "application/json", }, body: JSON.stringify({ command_id: "burn-2025-01-01-001", instrument_id: "rCC", party_id: "alice::122...", amount: "10.0", }), }); const data = await res.json(); ``` ```python Python theme={null} import requests res = requests.post( f"{base_url}/api/admin/burn", headers={"Authorization": f"Bearer {token}"}, json={ "command_id": "burn-2025-01-01-001", "instrument_id": "rCC", "party_id": "alice::122...", "amount": "10.0", }, ) data = res.json() ``` ```json 200 OK theme={null} { "command_id": "burn-2025-01-01-001", "status": "submitted" } ``` ## Data Read-only queries against the confirmed history captured by the token monitor. All endpoints support pagination via `limit` and `offset` query parameters and optional filtering by `party_id` and `instrument_id`. ### `GET /data/admin/mints` List confirmed mint records. Filter by recipient party id. Filter by instrument id. Page size. Range: 1–1000. Pagination offset (≥0). ```bash cURL theme={null} curl -G "$BASE_URL/data/admin/mints" \ -H "Authorization: Bearer $TOKEN" \ --data-urlencode "instrument_id=rCC" \ --data-urlencode "limit=100" ``` ```ts TypeScript theme={null} const params = new URLSearchParams({ instrument_id: "rCC", limit: "100" }); const res = await fetch(`${baseUrl}/data/admin/mints?${params}`, { headers: { Authorization: `Bearer ${token}` }, }); const data = await res.json(); ``` ```python Python theme={null} import requests res = requests.get( f"{base_url}/data/admin/mints", headers={"Authorization": f"Bearer {token}"}, params={"instrument_id": "rCC", "limit": 100}, ) data = res.json() ``` ```json 200 OK theme={null} [ { "command_id": "mint-2025-01-01-001", "created_at": "2025-01-01T00:00:00Z", "party_id": "alice::122...", "instrument_id": "rCC", "update_id": "1220abc...", "amount": "100.0" } ] ``` ### `GET /data/admin/burns` List confirmed burn records. Same query parameters as `/data/admin/mints`. ```bash cURL theme={null} curl -G "$BASE_URL/data/admin/burns" \ -H "Authorization: Bearer $TOKEN" \ --data-urlencode "instrument_id=rCC" \ --data-urlencode "limit=100" ``` ```ts TypeScript theme={null} const params = new URLSearchParams({ instrument_id: "rCC", limit: "100" }); const res = await fetch(`${baseUrl}/data/admin/burns?${params}`, { headers: { Authorization: `Bearer ${token}` }, }); const data = await res.json(); ``` ```python Python theme={null} import requests res = requests.get( f"{base_url}/data/admin/burns", headers={"Authorization": f"Bearer {token}"}, params={"instrument_id": "rCC", "limit": 100}, ) data = res.json() ``` ```json 200 OK theme={null} [ { "command_id": "burn-2025-01-01-001", "created_at": "2025-01-01T00:00:00Z", "party_id": "alice::122...", "instrument_id": "rCC", "update_id": "1220def...", "amount": "10.0" } ] ``` ### `GET /data/admin/holdings` Return a snapshot of on-ledger holdings from the latest monitor scan. Filter by owner party id. Filter by instrument id. Page size. Range: 1–100000. Pagination offset (≥0). ```bash cURL theme={null} curl -G "$BASE_URL/data/admin/holdings" \ -H "Authorization: Bearer $TOKEN" \ --data-urlencode "instrument_id=rCC" ``` ```ts TypeScript theme={null} const params = new URLSearchParams({ instrument_id: "rCC" }); const res = await fetch(`${baseUrl}/data/admin/holdings?${params}`, { headers: { Authorization: `Bearer ${token}` }, }); const data = await res.json(); ``` ```python Python theme={null} import requests res = requests.get( f"{base_url}/data/admin/holdings", headers={"Authorization": f"Bearer {token}"}, params={"instrument_id": "rCC"}, ) data = res.json() ``` ```json 200 OK theme={null} { "scan": { "scanned_at": "2025-01-01T00:00:00Z" }, "total": 1, "holdings": [ { "holding_cid": "0042...", "party_id": "alice::122...", "instrument_id": "rCC", "amount": "90.0", "locked": false } ] } ``` The `locked` flag is `true` when a non-expired lock blocks spending (for example, an in-flight transfer). ## Status ### `GET /status` Return the latest cached snapshot from the token-monitor loop (no live ledger query). Includes per-token stats (supply, holders, concentration, module-specific fields) and monitor/queue operational stats. Each section carries the time it was last refreshed; `updated_at` is the overall freshness. Fields that don't apply to a token — or aren't available yet — are omitted. The snapshot is only populated while monitoring is enabled; otherwise `tokens` is empty. ```bash cURL theme={null} curl "$BASE_URL/status" \ -H "Authorization: Bearer $TOKEN" ``` ```ts TypeScript theme={null} const res = await fetch(`${baseUrl}/status`, { headers: { Authorization: `Bearer ${token}` }, }); const data = await res.json(); ``` ```python Python theme={null} import requests res = requests.get( f"{base_url}/status", headers={"Authorization": f"Bearer {token}"}, ) data = res.json() ``` ```json 200 OK theme={null} { "updated_at": "2025-01-01T00:00:00Z", "tokens": { "rCC": { "total_supply": "1000.0", "total_locked_supply": "10.0", "unique_holders": 42, "top_holder_share": "0.18", "supply_concentration_hhi": "0.07", "updated_at": "2025-01-01T00:00:00Z" } }, "operational": { "updated_at": "2025-01-01T00:00:00Z", "monitor": { "last_success_at": "2025-01-01T00:00:00Z", "age_seconds": 2.1, "last_scan_duration_seconds": 0.4, "poll_interval_seconds": 5, "last_scan_holdings": 42, "cycles_total": 12345, "cycle_errors_total": 0, "monitoring_enabled": true }, "subscriptions": [ { "name": "self-redeem", "queue_depth": 0, "queue_maxsize": 1024, "dropped_batches_total": 0 } ], "modules": {} } } ``` Key per-token fields: | Field | Description | | -------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- | | `total_supply` | Total amount in circulation across all active holdings (spendable + locked), summed from the latest on-ledger scan. | | `total_locked_supply` | Portion of `total_supply` currently locked (e.g. in-flight transfer) and not spendable. | | `unique_holders` | Number of distinct owner parties holding at least one active holding. | | `top_holder_share` | Fraction of `total_supply` held by the single largest holder (0–1). | | `supply_concentration_hhi` | Herfindahl–Hirschman Index of supply across holders. `1.0` = one holder owns everything; `~1/unique_holders` = evenly distributed. | ## Health and metrics Unauthenticated operational endpoints for orchestration and monitoring. ### `GET /healthz` Liveness probe. Returns `200 OK` when the service is up. ```bash cURL theme={null} curl "$BASE_URL/healthz" ``` ### `GET /metrics` Returns service metrics in JSON. ```bash cURL theme={null} curl "$BASE_URL/metrics" ``` ## Error responses Validation errors are returned as `422 Unprocessable Entity`: ```json theme={null} { "detail": [ { "loc": ["body", "amount"], "msg": "value is not a valid number", "type": "value_error" } ] } ``` # Common use cases Source: https://cantor8.mintlify.app/token-factory/common-use-cases How partners apply C8 Token Factory — what it is, who it's for, and the business value it delivers. Token Factory helps companies create and move digital assets on Canton. In simple terms: **issue a token, define who can hold it, move it between parties, pause it if needed, and keep a clear record of what happened.** It combines two parts: Creates and manages tokens. Moves tokens privately between approved parties. ## At a glance *** ## Tokenized Asset Issuance A way to create a digital version of an asset on Canton — fund unit, deposit, security, commodity balance, payment balance, reward, rebate, or any other value a company wants to track and move. **Why it matters.** Creating a token is not enough. A company also needs rules: who can issue it, who can receive it, when it can move, and what happens if something goes wrong. Token Factory puts those rules into the token workflow. * Banks * Asset managers * Fintechs * Payment companies * Tokenized RWA issuers Create a new token from existing templates, set name and decimal precision, deploy, and add it to the registry. Wallets and apps can then discover it and use the registry API to prepare transfers. Faster token launch · less custom smart contract work · built-in controls for mint, burn, freeze, and transfers · easier wallet and partner integration. *** ## Bridged Assets A way to represent assets like BTC or ETH inside Canton. **Why it matters.** Some companies want to use assets like BTC or ETH in private Canton workflows, without exposing all activity on a public chain. * Custodians * Wallet providers * Treasury teams * Settlement platforms * Crypto asset operators Mint a Canton token when the original asset is deposited, and burn it when the asset is withdrawn. The token then moves privately inside Canton. Brings external assets into Canton workflows · keeps transfers private · supports deposit and withdrawal flows · gives operators controls if something needs to be paused or corrected. *** ## Wallet and Payment Flows A way for wallets and apps to support Token Factory assets without knowing every contract detail. The registry API tells the wallet what tokens exist and how to prepare a transfer. **Why it matters.** Wallets need a simple integration path — they should not need to understand every DAML package or token version. * Wallet apps * Payment apps * Partner portals * Internal treasury tools A wallet lists tokens via the registry, then requests transfer context before submitting on Canton. With auto-accept the transfer completes directly; otherwise the receiver gets an offer to accept or reject. Simpler wallet integration · multi-token support through one API pattern · direct transfers when both sides are ready · offer-based transfers when approval is needed. *** ## Private Transfers A way to move assets between parties while keeping transaction details visible only to the right participants. **Why it matters.** In many financial workflows it is not acceptable for everyone to see who is transacting, how much is moving, or what asset is involved. Canton gives privacy at the ledger level — Token Factory uses that for token transfers. * Financial institutions * Trading desks * Payment networks * Treasury teams * Partner ecosystems Build apps where approved users send tokens to each other, while only involved parties and approved observers see the details. Keeps sensitive activity private · supports controlled data sharing · makes token movement usable for real financial workflows · reduces the need for manual off-chain coordination. *** ## Atomic Settlement A way to lock assets before settlement and only move them when the required steps are complete. Useful for DvP, swaps, collateral movement, and other workflows where both sides need confidence. **Why it matters.** Settlement risk happens when one side of a transaction completes and the other does not. Token Factory supports allocation flows that reserve assets and then execute, cancel, or withdraw them. * Settlement venues * OTC desks * Treasury teams * Collateral platforms * Swap and exchange products Create an allocation, have the receiver accept the settlement, and let an executor complete or cancel the transfer. Reduces settlement risk · safer multi-step transactions · clear state for pending, completed, cancelled, or withdrawn flows · works well for private financial transfers. *** ## Compliance Controls Controls for pausing or correcting token activity: global freeze, party freeze, admin burn, migration, and force-burn for locked funds. **Why it matters.** Real asset systems need a way to react to mistakes, fraud, legal orders, sanctions checks, or operational issues. * Issuers * Compliance teams * Custodians * Regulated platforms * Internal operations teams Freeze all activity, freeze one party, burn tokens, or migrate holdings to a newer contract version. Actions are controlled by admin workflows and can include reasons for audit. Safer token operations · better control after launch · easier incident response · compliance controls built into the asset lifecycle. *** ## Partner-Branded Tokens A way for partners to launch their own token using the same Token Factory structure. **Why it matters.** Many partners need a token for their own product, but they should not have to build the full system from zero. * Banks * Fintechs * Payment companies * Loyalty platforms * Enterprise partners Copy the token templates, change name and settings, deploy, and add to the registry. The token reuses the same transfer, wallet, freeze, and settlement patterns. Faster partner launches · reusable token setup · same operating model across many tokens · easier support and maintenance. *** ## Rewards, Rebates, and Redemption A way to issue credits, rewards, or rebate balances that can later be transferred or redeemed. `rCC` in the repo shows this pattern. **Why it matters.** Reward and rebate systems often live in normal databases. Token Factory can make them ledger-based, auditable, and transferable. * Loyalty programs * Merchant networks * Rebate programs * Mobile money partners * Ecosystem operators Mint reward or rebate tokens, allow users to transfer them, and redeem them through controlled flows. Clear record of issued and redeemed value · easier reconciliation · transferable reward balances · better control over redemption. *** ## Multi-Asset Treasury A way to manage several tokenized assets with the same tools and rules. **Why it matters.** Treasury teams often deal with many asset types. A common system makes it easier to move, reserve, burn, freeze, and reconcile them. * Treasury teams * Custodians * Asset platforms * Payment networks * Crypto operations teams Add several tokens to the registry and use the same API and CLI patterns for each one. One model for many assets · less operational complexity · easier reporting and reconciliation · better control over asset movement. *** ## Summary Token Factory is useful when a company wants to **create a digital asset and actually operate it**. It helps issue the asset, move it privately, connect it to wallets, reserve it for settlement, and keep control if something needs to be paused, fixed, or upgraded. # Integration Source: https://cantor8.mintlify.app/token-factory/integration How to integrate Cantor8 Token Factory into your platform. Interested in integrating Cantor8 Token Factory into your product or operations? The C8 team will guide you through the integration end-to-end — scoping the right token setup, provisioning access, and walking through technical onboarding. Reach out to [**integrations@cantor8.io**](mailto:integrations@cantor8.io) and we'll get back to you with next steps. ## What to include in your message To speed things up, share a short note covering: * Your company and the product you're building * What you want to tokenize (asset type, jurisdiction, scale) * Expected go-live timeline * Any specific compliance or operational requirements Once we have that, the C8 team will schedule a kickoff call and share the technical onboarding materials. # Cantor8 Token Factory Source: https://cantor8.mintlify.app/token-factory/introduction Multi-token platform for the Canton Network — issue, transfer, freeze, burn, migrate, and settle tokenized assets. Cantor8 Token Factory is a multi-token platform for the Canton Network. It provides typed DAML token packages, a token registry API, and operational tooling for issuing, transferring, freezing, burning, migrating, and settling tokenized assets. It is designed for **regulated and operationally controlled asset workflows**: token ownership and lifecycle logic stay on ledger, while registry endpoints let wallets and backend services discover instruments and prepare Canton choice contexts. ## What you'll find here How partners apply C8 Token Factory — what it is, who it's for, and the value it delivers. How to scope and onboard a new tokenised asset with the C8 team. REST API for admin operations, data queries, status, and health checks. Reach out at [**integrations@cantor8.io**](mailto:integrations@cantor8.io) to discuss your use case. # Common use cases Source: https://cantor8.mintlify.app/validator-as-a-service/common-use-cases How partners apply C8 Validator as a Service — what it is, who it is for, and the business value it delivers. ## What it is C8 Validator as a Service is a managed operational service for running Canton validator nodes on behalf of institutions and partners. It gives teams a production-ready path into the Canton Network without requiring them to build a dedicated validator operations function internally. C8 can support registration, deploy the validator in an isolated environment, coordinate required allowlisting steps, and maintain the node after launch. ## Why it matters Running a Canton validator node requires more than infrastructure. Teams need reliable DevOps, weekly updates, monitoring, incident response, network access coordination, and traffic management. For many partners, that is not the core product they are trying to build. C8 Validator as a Service lets partners participate in Canton-based workflows while C8 handles the operational responsibility of validator setup and maintenance. ## Who it is for C8 Validator as a Service is designed for institutions and product teams that need access to Canton validator infrastructure but want a managed operating model. ## Common use cases ### Launching a MainNet validator Partners that need a MainNet Canton validator can use C8 to manage the full technical setup path. C8 prepares the isolated environment, supports registration, submits the required IP details for allowlisting, and brings the validator into production once the network access requirements are satisfied. ### Supporting wallet and treasury workflows Institutional wallet and treasury products often depend on reliable Canton connectivity. C8 Validator as a Service gives those products a managed validator layer, so the partner can focus on balances, transfers, approvals, reconciliation, and user-facing operations instead of validator reliability. ### Enabling token issuance and lifecycle operations Tokenized asset workflows require dependable ledger access for issuance, transfer, freeze, burn, settlement, and lifecycle events. By operating the validator layer, C8 helps asset issuers and platforms keep the infrastructure side stable while they build regulated asset workflows on top. ### Reducing internal DevOps burden Some institutions can run their own validator, but do not want to allocate an internal team to weekly updates, monitoring, release handling, or network traffic management. C8 provides the operational capacity and Canton-specific experience required to keep the validator healthy after deployment. ### Accelerating partner onboarding For new partners, validator setup can become a gating step before the product can move to production. C8 reduces that friction by coordinating the technical onboarding sequence, preparing the environment, and guiding the partner through the Canton network access requirements. ## Business value C8 Validator as a Service helps partners launch Canton validator infrastructure faster, reduce operational risk, and avoid building a dedicated validator DevOps function before going live. C8 Validator as a Service turns validator operations into a managed infrastructure layer for Canton-based products and institutional workflows. # C8 Validator as a Service Source: https://cantor8.mintlify.app/validator-as-a-service/introduction Fully managed Canton validator nodes for institutions — C8 handles setup, registration, and operations. C8 Validator as a Service gives institutions a managed way to run a validator node on the Canton Network without taking on the full infrastructure and operations burden internally. There is always an option to run a Canton validator node in your own infrastructure. For most teams, however, this requires dedicated DevOps capacity, weekly updates, active monitoring, traffic management, and a clear process for operating inside a permissioned network. C8 provides this as a managed service. As an official Canton Node Operator, C8 can prepare the validator environment, support the required registration flow, submit network access details for allowlisting, deploy the node, and continue operating it after launch. ## What it is C8 Validator as a Service is an operational layer for institutions that need validator connectivity to Canton but do not want to build and maintain the node operations stack from scratch. The service covers the practical work required to get a validator node production-ready: * Isolated infrastructure environment for the partner validator * Canton node deployment and configuration * Network registration support * IP submission and allowlisting coordination * DevOps setup and release management * Monitoring, alerting, and traffic management * Ongoing operational support after go-live C8 handles the infrastructure path from registration to production operations, so partners can focus on their Canton-enabled product, treasury, wallet, or asset workflow. ## Why it matters Canton is a permissioned network. Operating a validator is not only a matter of starting infrastructure; it also requires the correct network setup, access coordination, and ongoing operational discipline. For institutions, the hard parts are usually not the first deployment command. The hard parts are keeping the node healthy, updated, observable, reachable, and aligned with network requirements over time. C8 Validator as a Service is designed to remove that operating burden while preserving the partner's ability to participate in Canton-based workflows. ## What C8 manages C8 prepares the isolated environment, configures the validator node, and manages the technical deployment path. C8 supports the partner through the required onboarding steps and coordinates the technical details needed for Canton access. C8 submits the required IP information to the Foundation for whitelist approval as part of the permissioned network process. C8 manages updates, monitoring, alerts, traffic handling, and day-to-day infrastructure reliability. ## When to use it C8 Validator as a Service is a good fit when your team needs a validator node for MainNet or production-facing Canton workflows, but does not want to own the full operational lifecycle internally. It is especially useful when the validator is a dependency for another C8 product or partner workflow, such as Enterprise Wallet, Token Factory, asset issuance, institutional settlement, or treasury operations. ## Next steps See where managed validator operations fit into partner workflows. Understand the path from registration to live node operations. # Onboarding and operations Source: https://cantor8.mintlify.app/validator-as-a-service/onboarding-and-operations The managed path from Canton validator registration to production operations with C8. C8 Validator as a Service is built around a simple operating model: C8 handles the validator infrastructure lifecycle while the partner focuses on the business workflow that depends on Canton connectivity. The exact sequence may vary by partner, network requirements, and deployment scope, but the process generally follows the stages below. ## Operating model Partners can always choose to run their own Canton validator node in their own infrastructure. That path gives maximum internal control, but it also requires the partner to own DevOps, monitoring, weekly release updates, traffic management, and operational support. With C8 Validator as a Service, C8 takes responsibility for the technical setup and ongoing operation of the validator environment. The partner runs the validator in its own infrastructure and owns updates, monitoring, traffic, and incident response. C8 prepares, deploys, monitors, updates, and operates the validator as part of the managed service. ## Onboarding flow C8 and the partner confirm operating requirements, expected usage, and whether the validator supports a wallet, token, settlement, or custom workflow. C8 creates an isolated infrastructure environment for the partner validator and configures the required deployment baseline. C8 supports the registration process and collects the technical details required for network access. Because Canton is a permissioned network, C8 submits the required IP information to the Foundation for whitelist approval. C8 deploys the validator, verifies connectivity, checks service health, and confirms the node is ready for partner workflows. After launch, C8 manages monitoring, alerts, updates, traffic handling, and ongoing infrastructure support. ## Operational responsibilities The managed service is designed to cover the validator responsibilities that usually require a dedicated infrastructure team. * **Release management** — applying required regular updates and keeping the validator aligned with network expectations. * **Monitoring and alerting** — tracking node health, service availability, and operational signals. * **Traffic management** — ensuring the validator can handle expected network and partner traffic patterns. * **Environment isolation** — separating partner validator infrastructure from other operational environments. * **Production support** — responding to issues and coordinating follow-up where network or infrastructure dependencies are involved. ## Partner responsibilities The partner remains responsible for the business and product workflows that use the validator. This typically includes: * Defining the product or institutional workflow that depends on Canton * Providing required business and registration information * Confirming expected usage patterns and operational requirements * Integrating applications, wallets, token services, or back-office systems with the C8 stack * Managing end-user, compliance, and business process requirements outside the validator infrastructure layer ## Production readiness Before a validator is considered ready for production use, C8 verifies the core operational requirements. The node should be deployed in the isolated environment, registered for the network, allowlisted where required, monitored, and connected to the partner workflow that depends on it. The final go-live timing depends on infrastructure readiness, partner inputs, and completion of external network access steps such as allowlisting. ## When to contact C8 Contact the C8 team when your product or institution needs Canton validator connectivity and you want C8 to manage the setup and operation path. Reach out to discuss your requirements, product workflow, and expected launch timeline — we'll guide you through the next steps. Coordinate registration, allowlisting, infrastructure setup, and operational readiness. Interested in Validator as a Service or have any other questions? Drop us a line at [**integrations@cantor8.io**](mailto:integrations@cantor8.io) — we're happy to help. # API reference Source: https://cantor8.mintlify.app/wallet-sdk/api-reference ## Public API: `C8WalletProvider` | Method | Parameters | Return Type | | --------------------- | ------------------------------------------ | --------------------------------------------------------- | | `connect()` | None | `Promise` | | `disconnect()` | None | `Promise` | | `status()` | None | `Promise<{ connected: boolean; walletVersion?: string }>` | | `getInstruments()` | None | `Promise` | | `getAccounts()` | `instrumentId?: string` | `Promise` | | `send()` | `input: SendInput` | `Promise` | | `signAndExecute()` | `input: SignAndExecuteInput` | `Promise` | | `checkTxStatusById()` | `input: { txId: string }` | `Promise` | | `on()` | `event: T, cb: Listener>` | `() => boolean` | *** ## Constructor Creates a new wallet provider instance. ```ts theme={null} new C8WalletProvider(config) ``` URL of the dApp initiating the connection. Defaults to the current page URL. Name of the dApp. Must match the name registered with the wallet. Canton network to connect to. One of `"devnet"` or `"mainnet"`. *** ## connect Opens the C8 Wallet popup and establishes the `postMessage` channel. The user sees a connection approval screen in the wallet. ```ts theme={null} connect(): Promise ``` Resolves when the user approves the connection. Must be called from a user gesture (e.g. button click) to avoid `POPUP_BLOCKED` errors. *** ## disconnect Closes the wallet popup and tears down the `postMessage` channel. Emits the `disconnected` event. ```ts theme={null} disconnect(): Promise ``` *** ## status Returns the current connection state. ```ts theme={null} status(): Promise<{ connected: boolean, walletVersion?: string }> ``` Whether the wallet is currently connected. Version of the connected wallet (only present when connected). *** ## getInstruments Returns the list of Canton instruments available in the connected wallet. ```ts theme={null} getInstruments(): Promise type InstrumentListPayload = { instruments: Array<{ instrumentId: string name: string symbol: string }> } ``` *** ## getAccounts Returns accounts and their holdings. If `instrumentId` is provided, filters to accounts holding that instrument. ```ts theme={null} getAccounts(instrumentId?: string): Promise type AccountListPayload = { accounts: Array<{ partyId: string holdings: Array<{ instrumentId: string balance: number balanceUsd: number }> }> } ``` Optional. Filters accounts to those holding this instrument. *** ## send Submits a transfer on the Canton ledger. Opens an approval screen in the wallet popup. ```ts theme={null} send(input): Promise ``` Canton `partyId` of the sender. Asset to transfer. Transfer amount. Canton `partyId` of the recipient. Optional text memo attached to the transfer. Optional arbitrary key-value metadata. Transaction ID assigned by the Canton ledger. Use it with `checkTxStatusById`. *** ## signAndExecute Signs and executes an arbitrary DAML command via the connected wallet. Use this for custom templates and choices beyond standard transfers. See [Transfer types](/wallet-sdk/transfer-types) for the full example. ```ts theme={null} signAndExecute(input): Promise ``` Human-readable note shown to the user in the wallet UI. The party submitting the command. Unique idempotency key for this submission (e.g. a UUID). JSON-serialized array of DAML commands (`CreateCommand`, `ExerciseCommand`, etc.). JSON-serialized array of contracts disclosed to the participant to authorize the command. *** ## on Subscribes to a wallet event. Returns an unsubscribe function. See [Events](/wallet-sdk/events) for the full event reference. ```ts theme={null} on(event: T, cb: Listener>): () => boolean ``` Event type to subscribe to (e.g. `"connected"`, `"txChanged"`). Callback invoked with the typed event payload. Unsubscribe function. Call it to remove the listener. *** ## checkTxStatusById Polls the Canton ledger for the current status of a previously submitted transaction. ```ts theme={null} checkTxStatusById(input): Promise ``` Transaction ID returned by `send()`. Current ledger status for the given transaction. # Common use cases Source: https://cantor8.mintlify.app/wallet-sdk/common-use-cases How partners apply C8 Wallet SDK — what it is, who it's for, and the business value it delivers. ## What it is C8 Wallet SDK is a ready-made integration layer that allows third-party applications to connect their users to **C8 Wallet** on the Canton network. It gives partner applications a secure and familiar way to work with wallet-based user approvals, Canton assets, and transaction flows — without building wallet infrastructure from scratch. ## Why it matters For most teams, building a wallet layer is expensive and operationally sensitive. It requires: * Authentication flows * User approval screens * Transaction signing * Wallet state handling * Network-specific logic C8 Wallet SDK removes that complexity. Partners can focus on their product experience while C8 Wallet handles the wallet interaction layer. ## Who it is for The SDK is designed for development teams building applications that need Canton wallet connectivity. ## How partners can use it Partners can embed C8 Wallet connectivity directly into their own application experience. A user can: — all while staying inside the partner product journey. The SDK is the right fit when an application needs to support wallet-based actions but does **not** want to own private key management, transaction signing, or direct Canton ledger communication. ## Business value C8 Wallet SDK helps partners **launch Canton-enabled products faster**, **reduce integration risk**, and **provide users with a trusted wallet experience** backed by Cantor8 infrastructure. C8 Wallet acts as a plug-in wallet layer for partner applications. # Core concepts Source: https://cantor8.mintlify.app/wallet-sdk/core-concepts ## Canton network C8 Wallet is built on [Canton](https://www.canton.network/), a privacy-enabled blockchain designed for institutional finance. Rather than Ethereum-style addresses, Canton uses: * **`partyId`** — string identifier for a participant (account) * **`instrumentId`** — string identifier for a tokenized asset Your dApp works with these identifiers throughout the SDK. ## Popup + postMessage architecture The SDK uses two channels to talk to the wallet, depending on the request type: **Interactive actions** that require user consent, auth, or cryptographic signatures — e.g. connecting an account or signing a transaction. **Read-only data** retrieval that does not require user intervention — e.g. fetching instruments or balances. ## Instruments and holdings An **instrument** is a Canton asset type (e.g. a tokenized currency or security). A **holding** is a specific account's balance of that instrument. The typical flow: `getInstruments()` — pick an `instrumentId`. `getAccounts(instrumentId)` — pick a `partyId` and holding. `send({ senderPartyId, instrumentId, amount, receiverPartyId })`. # Error handling Source: https://cantor8.mintlify.app/wallet-sdk/error-handling SDK methods reject with an error object that includes a stable `code` field. Switch on `err.code` to handle each case. ```js theme={null} try { const { txId } = await c8.send({ /* ... */ }); } catch (err) { switch (err.code) { case 'USER_REJECTED': /* ... */ break; case 'INSUFFICIENT_FUNDS': /* ... */ break; case 'POPUP_BLOCKED': /* ... */ break; case 'NOT_CONNECTED': /* ... */ break; // ... } } ``` ## Error codes The user dismissed the approval popup. Prompt them to retry the action. The selected holding's balance is too low for the requested transfer. Surface a clear "not enough balance" message to the user. The browser blocked the wallet popup. Make sure `connect()` and `send()` are called from a user gesture (e.g. a button click). The method was called before `connect()`. Call `await c8.connect()` first. The provider failed to initialize. Verify your `C8WalletProvider` config (`dappName`, `network`). The wallet could not prepare the transfer. Often indicates invalid `senderPartyId`, `instrumentId`, or `amount`. The transfer was submitted but failed to execute on the Canton ledger. Could not retrieve transfer status. Retry, or check connectivity to the Canton network. `getInstruments()` failed. Verify the wallet is connected and reachable. `getAccounts()` failed. Verify the wallet is connected and reachable. `checkTxStatusById()` failed. The `txId` may be invalid or the ledger may be temporarily unreachable. # Events Source: https://cantor8.mintlify.app/wallet-sdk/events Subscribe to wallet and transaction lifecycle events with `c8.on(event, handler)`. ```js theme={null} c8.on('connected', (e) => { /* ... */ }); c8.on('txChanged', (e) => { /* ... */ }); ``` ## Event reference Fires when the user approves the connection in the popup. Payload: `{ meta?: Json }`. Fires when `disconnect()` is called or the popup is closed. Payload: `{ reason?: string, meta?: Json }`. Fires when balances or holdings change. Payload: `{ accounts: AccountInfoPayload[], meta?: Json }`. Fires when a transaction request is initiated. Payload: `{ txId?: string, meta?: Json }`. Fires when a transaction's completion status updates. Payload: `{ txId: string, status: "pending" | "confirmed" | "failed" | string, meta?: Json }`. Fires when the wallet interface changes its UI display theme. Payload: `{ theme: "dark" | "light", meta?: Json }`. Fires when an action or modal interface is explicitly rejected by the user. Payload: `{ reason: string, meta?: Json }`. Always register listeners **before** calling `connect()` to ensure you don't miss the initial `connected` event. ## Unsubscribing from events The `on()` method returns an unsubscribe function. Call it to remove the listener. ```js theme={null} const unsubscribe = c8.on("connected", (event) => { console.log("Connected", event); }); unsubscribe(); ``` # Installation Source: https://cantor8.mintlify.app/wallet-sdk/installation Install the SDK from the distributed tarball: ```bash npm theme={null} npm i @cantor8/wallet-connect-sdk ``` ```bash yarn theme={null} yarn add @cantor8/wallet-connect-sdk ``` ```bash pnpm theme={null} pnpm add @cantor8/wallet-connect-sdk ``` The SDK is currently distributed as a `.tgz` package. Place the file in your project root (or reference it by path) before installing. ## Requirements * Modern browser with `window.postMessage` support * A dApp served over HTTPS (or `localhost` for development) # Cantor8 Wallet SDK Source: https://cantor8.mintlify.app/wallet-sdk/introduction Lightweight SDK for integrating the C8 Wallet into dApps on Canton. C8 Wallet SDK is built for DeFi applications running on the Canton network that need a ready-made wallet layer. It connects your dApp to the C8 Wallet through a secure popup and `postMessage` channel, handling auth, account resolution, transfer submission, and status polling out of the box. ## How it works At the core of the SDK is `C8WalletProvider`. It owns the full wallet lifecycle — connection, instrument and account resolution, transfer submission, and status polling — so dApp developers don't have to deal with Canton-specific cryptography or direct ledger communication. All wallet interaction happens in a separate, secure popup window and communicates with your dApp through the browser's native `postMessage` API, keeping signing keys isolated from the application context. Connect a wallet and submit your first transfer in 3 steps. Learn about parties, instruments, and the popup architecture. Full reference for C8WalletProvider methods. Subscribe to wallet and transaction lifecycle events. # Networks available Source: https://cantor8.mintlify.app/wallet-sdk/networks Pass the target network to `C8WalletProvider` via the `network` option. Local development and integration testing. Use for all non-production work. Production Canton network. Real assets — use only for live deployments. ```js theme={null} const c8 = new C8WalletProvider({ dappUrl: window.location.href, dappName: "My DeFi App", network: "devnet", // or "mainnet" }); ``` Always verify you are pointing at the correct network before signing transactions in production. # Quick start Source: https://cantor8.mintlify.app/wallet-sdk/quick-start Get from zero to a signed Canton transfer in three steps. Create a `C8WalletProvider` instance with your dApp metadata and target network. ```js theme={null} const c8 = new C8WalletProvider({ dappUrl: window.location.href, dappName: "My DeFi App", network: "devnet" // "devnet" | "mainnet" }); ``` `dappName` must match the name your dApp is registered under in the wallet. Listen for connection and transaction lifecycle events. ```js theme={null} c8.on('connected', (e) => console.log('Connected', e)); c8.on('disconnected', (e) => console.log('Disconnected', e)); c8.on('accountChanged', (e) => console.log('Balance changed', e)); c8.on('txInitiated', (e) => console.log('TX initiated', e)); c8.on('txChanged', (e) => console.log('TX changed', e)); ``` See the [Events reference](/wallet-sdk/events) for the full list. Open the wallet popup, pick an instrument and account, then submit a transfer. ```js theme={null} await c8.connect(); // Fetch available instruments (Canton tokens / assets) const { instruments } = await c8.getInstruments(); const instrumentId = instruments[0]?.instrumentId; // Fetch accounts for that instrument const { accounts } = await c8.getAccounts(instrumentId); const senderPartyId = accounts[0]?.partyId; const senderHoldingInstrId = accounts[0]?.holdings[0]?.instrumentId ?? instrumentId; // Submit a transfer const { txId } = await c8.send({ senderPartyId, instrumentId: senderHoldingInstrId, amount: 1.23, receiverPartyId: 'Party::Receiver', // memo and metadata are optional — see API reference }); console.log('Transaction submitted:', txId); ``` You received a `txId` — the transfer is now on the Canton ledger. Use [`checkTxStatusById`](/wallet-sdk/api-reference#checktxstatusbyid-input-promise-transferstatusresponsepayload) to poll its status. # Transfer types Source: https://cantor8.mintlify.app/wallet-sdk/transfer-types Standard transfers supported out of the box and custom transaction types via C8. ## Standard transfers Out of the box, the SDK supports connecting a Canton wallet, resolving instruments and accounts, and submitting transfers between parties. This covers the majority of DeFi use cases: payments, settlements, and asset movement across Canton participants. ## Custom transaction types Canton's smart contract model (DAML) allows for arbitrarily complex workflows — multi-party agreements, conditional transfers, bespoke financial instruments. If your application requires transaction types beyond standard transfers, the SDK can be extended to support them. This involves aligning on your contract and workflow requirements with the Cantor8 team, who will implement the corresponding support on the C8 backend. ### `signAndExecute` — arbitrary contracts The SDK exposes a low-level method that lets your dApp sign and execute any DAML command supported by the connected wallet — including custom templates and choices defined for your integration. ```ts theme={null} signAndExecute(input: { note: string; partyId: string; commandId: string; commandsJson: string; disclosedContracts: string; }): Promise; ``` **Parameters** | Field | Description | | -------------------- | ----------------------------------------------------------------------------------------- | | `note` | Human-readable note shown to the user in the wallet UI. | | `partyId` | The party submitting the command. | | `commandId` | Unique idempotency key for this submission (e.g. a UUID). | | `commandsJson` | JSON-serialized array of DAML commands (`CreateCommand`, `ExerciseCommand`, etc.). | | `disclosedContracts` | JSON-serialized array of Contracts disclosed to the participant to authorize the command. | ### Example Submitting a `CreateCommand` for a custom template: ```ts theme={null} const onSignAndExecuteClick = async () => { const input = { note: signAndExecuteMessage ?? "Hello from Cantor8 Wallet Connect SDK Demo", partyId: selectedAccount, commandId: crypto.randomUUID(), commandsJson: JSON.stringify([ { CreateCommand: { templateId: "#splice-wallet:Splice.Wall..pprovalProposal", createArguments: { receiver: "9acf24..49ce9d", provider: "cantor8-digik-1::122..77f", expectedDso: "DSO::122..1a", }, }, }, ]), disclosedContracts: "", }; c8.signAndExecute(input).catch((e) => console.log("error signing and executing", e, e.data) ); }; ``` Example of `disclosed_contracts` payload: ```json theme={null} "disclosed_contracts": [ { "templateId": "167da4910b0..c93056f2f3bcd", "contractId": "0060.77887563880cd00", "createdEventBlob": "CgMyLjES7wY..Wk/eLGNgpQNGrdDxjiLIpmGdEB4=", "synchronizerId": "global-domain::1220be58..881bb471a" } ], ``` Contact the C8 team at [**integrations@cantor8.io**](mailto:integrations@cantor8.io) to scope custom transaction support for your application.