Overview
identiPay uses the Sui blockchain for:
- Identity Registry: On-chain storage of identity commitments and public keys
- Trust Registry: Issuer certificate verification
- Payment Settlement: Atomic transaction settlement with ZK proofs
- Shielded Pool: Privacy-preserving asset pool
- Stealth Addresses: One-time payment addresses
Prerequisites
- Sui CLI installed (
sui command)
- Sui wallet with testnet SUI tokens
- Git
Installation
Install Sui CLI
cargo install --locked --git https://github.com/MystenLabs/sui.git --branch testnet sui
Verify installation:Create Sui Wallet
sui client new-address ed25519
This creates a new Ed25519 keypair and address.Configure Network
Switch to testnet:sui client switch --env testnet
Verify configuration:
Contract Deployment
Package Structure
The identiPay Move package contains:
contracts/
├── Move.toml # Package manifest
├── Published.toml # Deployment records
└── sources/
├── intent.move # Payment intent structures
├── settlement.move # Settlement logic and ZK verification
├── trust_registry.move # Issuer certificate registry
├── meta_address_registry.move # Identity commitment registry
├── announcements.move # Stealth address announcements
├── shielded_pool.move # Privacy-preserving pool
├── zk_verifier.move # ZK proof verification
├── receipt.move # Receipt NFTs
└── warranty.move # Product warranty NFTs
Move.toml Configuration
[package]
name = "identipay"
edition = "2024.beta"
[dependencies]
Sui = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework/packages/sui-framework", rev = "framework/testnet" }
[addresses]
identipay = "0x0"
Deploy Package
Clone Repository
git clone https://github.com/your-org/identipay.git
cd identipay/contracts
Build Package
This compiles the Move modules and checks for errors. Publish to Testnet
sui client publish --gas-budget 500000000
Gas budget is in MIST (1 SUI = 1,000,000,000 MIST). Adjust as needed.
Save Deployment Information
After publishing, save the following from the output:
- Package ID: The published package object ID
- Trust Registry ID: Shared object for trust registry
- Meta Registry ID: Shared object for identity commitments
- Settlement State ID: Shared object for settlement tracking
- Verification Key ID: Object containing ZK verification keys
- Shielded Pool ID: Shared object for the privacy pool
Example output:----- Transaction Effects ----
Status : Success
Created Objects:
- ID: 0x1d78444dc29300d7ef1fda1cc292b154cba7dce8de68e12371f89179c3fdaf19 , Owner: Immutable
- ID: 0x2a1b3c4d..., Owner: Shared
- ID: 0x3b2c4d5e..., Owner: Shared
...
Published Package
The testnet deployment is recorded in Published.toml:
# Generated by Move
# This file contains metadata about published versions
[published.testnet]
chain-id = "4c78adac"
published-at = "0x1d78444dc29300d7ef1fda1cc292b154cba7dce8de68e12371f89179c3fdaf19"
original-id = "0x1d78444dc29300d7ef1fda1cc292b154cba7dce8de68e12371f89179c3fdaf19"
version = 1
toolchain-version = "1.66.1"
build-config = { flavor = "sui", edition = "2024" }
upgrade-capability = "0x0da172fd0feec73746e6b7f814f1cb1e8ce4a01f98b43abe5ccb2965ec725e40"
RPC Configuration
Network Endpoints
SUI_RPC_URL=https://fullnode.testnet.sui.io:443
RPC Methods Used
The backend uses the following Sui RPC methods:
sui_getObject: Fetch shared objects (registries, pool)
sui_executeTransactionBlock: Submit settlement transactions
sui_getTransactionBlock: Query transaction status
suix_queryEvents: Poll for settlement and announcement events
suix_getDynamicFieldObject: Query identity commitments by name
Object IDs
After deployment, configure these object IDs in your backend .env:
# Package ID (immutable)
PACKAGE_ID=0x1d78444dc29300d7ef1fda1cc292b154cba7dce8de68e12371f89179c3fdaf19
# Shared Objects
TRUST_REGISTRY_ID=0x...
META_REGISTRY_ID=0x...
SETTLEMENT_STATE_ID=0x...
SHIELDED_POOL_ID=0x...
# Verification Keys
VERIFICATION_KEY_ID=0x...
AGE_CHECK_VK_ID=0x...
POOL_SPEND_VK_ID=0x...
Finding Object IDs
If you need to find object IDs after deployment:
# List all objects owned by your address
sui client objects
# Get object details
sui client object <OBJECT_ID>
Verification Keys
ZK verification keys must be uploaded to the chain:
Generate Verification Keys
Use your ZK circuit compiler (Circom, Noir, etc.) to generate verification keys:cd circuits/identity_registration
npx snarkjs groth16 setup ...
Upload to Sui
Call the upload_verification_key function:sui client call \
--package $PACKAGE_ID \
--module zk_verifier \
--function upload_verification_key \
--args "$VK_BYTES" \
--gas-budget 50000000
Save Verification Key ID
Note the created object ID and add to .env:VERIFICATION_KEY_ID=0x...
Admin Keypair
The backend needs an admin keypair to submit transactions:
Export Private Key
sui keytool export --key-identity <ADDRESS>
This outputs a private key in format: suiprivkey1q...Add to Environment
ADMIN_SECRET_KEY=suiprivkey1q...
Never commit this private key to version control. Keep it secure.
Sui Client Integration
The backend uses the Sui TypeScript SDK:
import { SuiClient } from "@mysten/sui/client";
import { Transaction } from "@mysten/sui/transactions";
import { Ed25519Keypair } from "@mysten/sui/keypairs/ed25519";
const client = new SuiClient({ url: config.suiRpcUrl });
const keypair = Ed25519Keypair.fromSecretKey(
decodeSuiPrivateKey(config.adminSecretKey).secretKey
);
Query Events
const events = await client.queryEvents({
query: {
MoveEventType: `${packageId}::settlement::SettlementEvent`,
},
cursor: lastCursor,
limit: 50,
});
Submit Transaction
const tx = new Transaction();
tx.moveCall({
target: `${packageId}::settlement::settle_payment`,
arguments: [
tx.object(settlementStateId),
tx.pure.vector("u8", intentHash),
tx.pure.vector("u8", proof),
tx.pure.vector("u8", publicInputs),
],
});
const result = await client.signAndExecuteTransaction({
signer: keypair,
transaction: tx,
});
Event Indexing
The backend polls for events from the Sui blockchain:
Settlement Events
type: `${packageId}::settlement::SettlementEvent`
fields: {
intentHash: string,
merchantAddress: string,
amount: string,
timestamp: string,
}
Announcement Events
type: `${packageId}::announcements::StealthAnnouncement`
fields: {
ephemeralPubkey: string,
viewTag: number,
stealthAddress: string,
metadata: string,
timestamp: string,
}
Upgrade Capability
The deployment includes an upgrade capability object:
upgrade-capability = "0x0da172fd0feec73746e6b7f814f1cb1e8ce4a01f98b43abe5ccb2965ec725e40"
To upgrade the package:
sui client upgrade \
--upgrade-capability 0x0da172fd0feec73746e6b7f814f1cb1e8ce4a01f98b43abe5ccb2965ec725e40 \
--gas-budget 500000000
Upgrading contracts can break compatibility. Test thoroughly on devnet first.
Testing on Devnet
Before deploying to testnet or mainnet:
Switch to Devnet
sui client switch --env devnet
sui client faucet
Deploy Package
sui client publish --gas-budget 500000000
Test Transactions
Run integration tests against devnet deployment:DEVNET=true deno task test
Gas Estimation
Typical gas costs for identiPay operations:
- Register Name: ~5,000,000 MIST (~0.005 SUI)
- Create Proposal: ~1,000,000 MIST (~0.001 SUI)
- Settle Payment: ~10,000,000 MIST (~0.01 SUI)
- Stealth Announcement: ~2,000,000 MIST (~0.002 SUI)
Gas costs may vary based on network congestion and transaction complexity.
Monitoring
Sui Explorer
View transactions and objects on Sui Explorer:
Query Package Info
sui client object $PACKAGE_ID
Check Shared Object State
sui client object $META_REGISTRY_ID --json
Troubleshooting
Insufficient Gas
Solution: Request more SUI from faucet or increase gas budget.
Package Publish Failed
Error: Package verification failed
Solution: Check for compilation errors:
Object Not Found
Error: Object 0x... not found
Solution: Verify object ID is correct and exists on the current network:
Security Considerations
Private Key Management
- Store admin private key in secure environment variables
- Use hardware wallets for mainnet deployments
- Rotate keys periodically
Shared Object Access
- Trust registry: Only admin can add issuers
- Meta registry: Anyone can register names (with valid ZK proof)
- Settlement state: Only admin can settle payments
Upgrade Policy
- Test upgrades on devnet first
- Announce upgrades to users in advance
- Maintain backward compatibility when possible
Next Steps
Backend Setup
Configure the backend with deployed contract IDs
Smart Contracts
Learn about the Move contract architecture