A reference implementation and testing suite for the Splice Token Standard using DAML smart contracts, Canton network, and TypeScript.
- Overview
- Project Structure
- Prerequisites
- Installation
- Execution
- Using This Project as a Template
- Development
- Reporting Issues
Canton Test Coin is a comprehensive test implementation demonstrating how to build a complete token system on the Canton network using the Splice Token Standard. It provides a working example of:
- Token Metadata: Manage token information and properties
- Token Allocation: Handle token allocation requests and track allocations
- Token Transfer: Execute secure token transfers between holders
- REST API: OpenAPI-compliant REST endpoints for all operations
- Smart Contract Layer: DAML-based smart contracts for token logic
This project combines:
- DAML (Digital Asset Modeling Language) for smart contract logic
- Canton Network for distributed ledger consensus
- TypeScript/Bun for the backend REST API
- Splice SDK for wallet integration and ledger communication
canton-test-coin/
├── daml/ # DAML smart contracts
│ ├── daml.yaml # DAML configuration
│ ├── src/
│ │ └── Coin/ # Token implementation modules
│ ├── test/ # Test DAML code and fixtures
│ │ ├── Index.daml # Core test templates
│ │ ├── Transfer.daml # Token transfer tests
│ │ ├── Allocation/ # Allocation-related tests
│ │ ├── Fixture/ # Test fixtures and setup
│ │ └── Util/ # Test utilities
│ └── token-standard-api/ # Splice Token Standard API dependencies
├── src/ # TypeScript backend application
│ ├── index.ts # Application entry point
│ ├── routes.ts # API route definitions
│ ├── api/ # API endpoint handlers
│ │ ├── metadata/ # Metadata endpoints
│ │ ├── transfer-instruction/ # Transfer orchestration
│ │ ├── allocation-instruction/ # Allocation operations
│ │ ├── allocation/ # Allocation queries
│ │ └── error.ts # Error handling utilities
│ ├── types/ # TypeScript type definitions
│ │ ├── daml-ts/ # Generated DAML TypeScript bindings
│ │ └── openapi-ts/ # Generated OpenAPI client types
│ └── util/ # Utility functions
│ ├── logger.ts # Logging setup
│ ├── init.ts # Application initialization
│ ├── walletSDK.ts # Splice Wallet SDK configuration
│ └── ... # Other utilities
├── scripts/ # Utility scripts
│ ├── generateOpenapi.ts # Generate OpenAPI types
│ └── helper/ # Helper scripts for manual operations
│ ├── createTransferInstruction.ts
│ ├── createAllocationInstruction.ts
│ └── createAllocation.ts
├── splice/ # Splice reference and submodule
├── splice-wallet-kernel/ # Wallet SDK reference (monorepo)
├── package.json # Node.js dependencies and scripts
├── tsconfig.json # TypeScript configuration
└── IMPROVEMENTS.md # Future improvements and notes
| Directory | Purpose |
|---|---|
daml/ |
DAML smart contracts defining token templates, transfer logic, and allocation mechanisms |
src/api/ |
Bun route handlers implementing the OpenAPI specification |
src/types/ |
Generated TypeScript types from DAML and OpenAPI specs |
src/util/ |
Shared utilities: logger, SDK configuration, initialization routines |
scripts/ |
One-off scripts for code generation and manual contract operations |
splice/ |
Git submodule containing Splice framework reference code |
splice-wallet-kernel/ |
Git submodule containing Splice Wallet Kernel framework reference code |
Before installing and running this project, ensure you have the following:
Required Software
- Bun (v1.2.19+) as runtime
- https://bun.com/docs/installation
- Verify:
bun --version
- DAML SDK: Version 3.4.9 or compatible
- Installation: https://docs.daml.com/getting-started/installation.html
- Set SDK version:
daml use 3.4.9 - Verify:
daml version
- Canton Network: Running instance accessible at configured endpoint
- Installation: see
start:localnetcommand in https://github.com/hyperledger-labs/splice-wallet-kernel/blob/main/package.json - See Development section for local setup
- Installation: see
Access & Credentials
- Canton Admin Credentials: Public/private key pair for signing transactions
- Ledger Access: Permission to submit and read from the connected Canton ledger
- Configure via environment variables (see Installation)
This project includes Splice framework code as submodules:
git submodule update --init --recursivebun installCreate a .env file in the project root based on .env.example:
cp .env.example .envEdit .env with your configuration:
# Server port
PORT=3001
# Canton admin authentication
ADMIN_PUBLIC_KEY=<your-admin-public-key>
ADMIN_PRIVATE_KEY=<your-admin-private-key>Where to get credentials?
You can search for and use createKeyPair() method in @canton-network/wallet-sdk project or create public/private key yourself based on any cryptographic algorithm.
To do a complete rebuild from scratch:
bun generate:allThis runs all code generation steps in sequence and does the following:
- Cleans previous builds
- Compiles main token contracts in
daml/ - Compiles token standard API in
daml/token-standard-api/ - Compiles test templates in
daml/test/for verification purposes - Generates:
- JavaScript/TypeScript bindings for all DAML templates
- Type definitions matching your contract structure
- Type-safe client classes corresponding to API endpoints based on OpenAPI specification
Once installation is complete, start the application:
bun devExpected output:
Server running at http://localhost:3001
The server will:
- Load Splice Wallet SDK configuration
- Authenticate with Canton network
- Initialize token templates
- Start HTTP server on configured port
After the server starts, you can interact with the token system. All API requests require bearer token authentication. Include the Authorization header with your bearer token in each request:
curl -H "Authorization: Bearer <your-bearer-token>" \
http://localhost:3001/registry/metadata/v1curl -X POST http://localhost:3001/registry/transfer-instruction/v1 \
-H "Authorization: Bearer <your-bearer-token>" \
-H "Content-Type: application/json" \
-d '{
"from": "<holder-party-id>",
"to": "<recipient-party-id>",
"amount": 1000
}'You can find the rest of the API endpoints in src/routes.ts or in the Token Standard API Specs.
For manual contract operations without the REST API, you can use helper scripts defined in scripts/helper/. All helper scripts are available via package.json scripts and use the helper: prefix. Their purpose is to obtain the id of contracts to pass as input when testing the API endpoints.
Creates a new token allocation on the ledger.
bun helper:createAllocationCreates an allocation instruction for token distribution.
bun helper:createAllocationInstructionCreates a transfer instruction to move tokens between holders.
bun helper:createTransferInstruction-
Fork or Clone: Use this repository as a starting point
git clone https://github.com/mateuszpiatkowski-da/canton-test-coin.git my-token
-
Customize DAML Contracts:
- Modify token logic in
daml/src/Coin/ - Define your own token templates and choices
- Update test fixtures in
daml/test/ - Rebuild with
bun daml:rebuild
- Modify token logic in
-
Extend API Handlers:
- Add new endpoints in
src/api/ - Implement handlers matching your token logic
- Export routes from
src/routes.ts
- Add new endpoints in
-
Update Configuration:
- Modify
.envfor your setup - Configure ledger connection details
- Set up your admin credentials
- Modify
-
Regenerate Types:
- Run
bun generate:allafter DAML changes - Commit generated types for reproducibility
- Run
-
Test Thoroughly:
- Add test cases in
daml/test/ - Run ledger integration tests
- Verify HTTP endpoints with
curlor Postman |
- Add test cases in
-
Make changes to DAML contracts or TypeScript code
-
Rebuild affected components:
bun daml:rebuild # After DAML changes bun generate:daml-ts # After DAML schema changes bun dev # Start development server with hot reload
-
Test against your Canton instance
-
Repeat until desired behavior achieved
DAML contracts include comprehensive test fixtures. To test them:
# Build test contracts
cd daml/test
daml build
# Run specific test template
daml script --dar .daml/dist/test-coin-test-1.0.0.dar --script-name <TestName>Start the local Canton network using the splice-wallet-kernel helper:
# from the project root
cd splice-wallet-kernel
yarn start:localhostThis command starts Canton and related services used by the wallet kernel. Wait for services to report healthy in the logs before proceeding.
Refer to splice-wallet-kernel repo for details.
TBD
TBD
Last Updated: February 2026 DAML SDK Version: 3.4.9+ Bun: 1.2.19+