You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
MetaMask-compatible middleware for Canton Network, enabling ERC-20 style interactions with Splice-compliant CIP-56 tokens.
Overview
This project provides:
API Server -- Ethereum JSON-RPC facade that translates MetaMask transactions to Canton CIP-56 operations
Relayer -- Bridges PROMPT tokens between Ethereum and Canton
Interoperability -- Native Canton users (e.g. Canton Loop) and MetaMask users can seamlessly transfer tokens to each other
Splice Token Standard (CIP-0056) -- All tokens implement the Splice HoldingV1, TransferFactory, and Metadata interfaces
Splice Registry API -- External wallets discover TransferFactory contracts for explicit disclosure during transfers
External Parties -- All users are allocated as external parties using the Interactive Submission API (no ~200 internal party limit)
Quick Start (Local Development)
# 1. Bootstrap: starts Docker, registers users, mints tokens
./scripts/testing/bootstrap-local.sh --clean
# 2. Test: runs all 8 interop + bridge test steps
go run scripts/testing/interop-demo.go
Both scripts auto-detect all dynamic configuration (domain IDs, party IDs, contract addresses) from the running Docker containers. See the Local Interop Testing Guide for full details.
All users are external parties on Canton. They hold their own signing keys and use the Interactive Submission API (prepare/sign/execute) instead of the standard CommandService.
MetaMask / cast send / Canton Loop
│
▼
/eth endpoint (JSON-RPC) or Interactive Submission (gRPC)
│
▼
Resolve Canton signing key from encrypted DB store
│
▼
PrepareSubmission → sign with user's key → ExecuteSubmission
│
▼
Canton Ledger: TransferFactory_Transfer (Splice-compliant CIP-56)
Tokens
Token
Type
Description
DEMO
Native Canton (CIP-56)
Minted directly on Canton via CIP56Manager, implements Splice HoldingV1
PROMPT
Bridged ERC-20
Bridged from Ethereum via the Wayfinder bridge, also uses Splice HoldingV1
Both tokens carry Splice-standard metadata (TextMap Text) with DNS-prefixed keys (e.g. splice.chainsafe.io/symbol). Metadata is propagated through all transfers via the TransferFactory.
Display Canton token activity (holdings, configs, events)
canton-transfer-demo.go
Demo transfers and reconciliation
register-native-user.go
Register a native Canton user
register-user.go
Register an EVM user
e2e-local.go
End-to-end local tests
test-reconcile.go
Test balance reconciliation
test-whitelist.go
Test whitelist functionality
Setup (scripts/setup/)
Script
Description
bootstrap-all.sh
Full automated setup (alternative to bootstrap-local.sh)
bootstrap-bridge.go
Bootstrap bridge contracts on Canton
bootstrap-demo.go
Mint DEMO tokens to users
docker-bootstrap.sh
Docker-specific bootstrap
setup-local.sh
Local environment setup
setup-devnet.sh
DevNet setup
build-dars.sh
Build DAML archives
generate-protos.sh
Regenerate protobuf Go code
Bridge (scripts/bridge/)
Script
Description
bridge-activity.go
Display recent bridge activity
bridge-deposit.go
Deposit ERC-20 to Canton
get-holding-cid.go
Get holding contract ID for withdrawals
initiate-withdrawal.go
Initiate Canton → Ethereum withdrawal
cleanup-withdrawals.go
Clean up processed withdrawals
Utilities (scripts/utils/)
Script
Description
check-user-holdings.go
Check user holdings on Canton
verify-canton-holdings.go
Verify/compare holdings (DB vs Canton)
list-parties.go
List known parties
list-users.go
List registered users
check-mappings.go
Check fingerprint mappings
reconcile.go
Manual balance reconciliation
reset-demo-state.go
Reset demo state
query-canton-holdings.sh
Query Canton holdings (bash)
metamask-info.sh
Show MetaMask config
mock-oauth2-server.go
Local OAuth2 mock server
Development
Build
go mod download
go build ./...
Lint
golangci-lint run ./...
Manual Setup
export CANTON_MASTER_KEY=$(openssl rand -base64 32)export SKIP_CANTON_SIG_VERIFY=true
docker compose up -d
# Wait for healthy status, then bootstrap
go run scripts/setup/bootstrap-bridge.go -config config.e2e-local.yaml
go run scripts/setup/bootstrap-demo.go -config config.e2e-local.yaml
Verify Setup
curl http://localhost:8081/health
curl -X POST http://localhost:8081/registry/transfer-instruction/v1/transfer-factory
go run scripts/utils/check-user-holdings.go -config config.e2e-local.yaml
Configuration
Environment
Config File
Local testing
config.e2e-local.yaml
Docker
config.docker.yaml
API server (Docker)
config.api-server.docker.yaml
Local devnet
config.local-devnet.yaml
Example
config.example.yaml
Key Canton-specific fields (auto-detected by bootstrap):