Skip to main content

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

1

Install Sui CLI

cargo install --locked --git https://github.com/MystenLabs/sui.git --branch testnet sui
Verify installation:
sui --version
2

Create Sui Wallet

sui client new-address ed25519
This creates a new Ed25519 keypair and address.
3

Get Testnet Tokens

Request testnet SUI from the faucet:
sui client faucet
Or visit: https://faucet.testnet.sui.io/
4

Configure Network

Switch to testnet:
sui client switch --env testnet
Verify configuration:
sui client active-env

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

Move.toml
[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

1

Clone Repository

git clone https://github.com/your-org/identipay.git
cd identipay/contracts
2

Build Package

sui move build
This compiles the Move modules and checks for errors.
3

Publish to Testnet

sui client publish --gas-budget 500000000
Gas budget is in MIST (1 SUI = 1,000,000,000 MIST). Adjust as needed.
4

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:
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:
.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:
1

Generate Verification Keys

Use your ZK circuit compiler (Circom, Noir, etc.) to generate verification keys:
cd circuits/identity_registration
npx snarkjs groth16 setup ...
2

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
3

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:
1

Export Private Key

sui keytool export --key-identity <ADDRESS>
This outputs a private key in format: suiprivkey1q...
2

Add to Environment

.env
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:
1

Switch to Devnet

sui client switch --env devnet
sui client faucet
2

Deploy Package

sui client publish --gas-budget 500000000
3

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

Error: Insufficient gas
Solution: Request more SUI from faucet or increase gas budget.

Package Publish Failed

Error: Package verification failed
Solution: Check for compilation errors:
sui move build

Object Not Found

Error: Object 0x... not found
Solution: Verify object ID is correct and exists on the current network:
sui client object 0x...

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

Build docs developers (and LLMs) love