USC SDK
Getting Started with the USC SDK
Section titled “Getting Started with the USC SDK ”The @gluwa/usc-sdk is a TypeScript/JavaScript SDK for verifying cross-chain transactions on the Creditcoin network. It lets you generate inclusion proofs for transactions on supported source chains (e.g. Ethereum Sepolia) and verify them on-chain via Creditcoin’s precompile contracts.
Installation
Section titled “Installation ”npm install @gluwa/usc-sdk# oryarn add @gluwa/usc-sdkThe SDK requires ethers.js v6 as a peer dependency.
Core concepts
Section titled “Core concepts ”A transaction inclusion proof answers the question: “Did this transaction really happen on chain X?” It is made of two parts:
| Part | What it proves |
|---|---|
| Merkle proof | The transaction is included in a specific block’s transaction tree |
| Continuity proof | That block is part of a sequence of blocks anchored to an attestation point on Creditcoin |
The SDK provides three main components you will work with:
ProverAPIProofGenerator— fetches pre-computed proofs from a hosted API (recommended starting point)PrecompileChainInfoProvider— queries attestation state from CreditcoinPrecompileBlockProver— submits proofs to Creditcoin’s on-chain verifier
Setting up providers
Section titled “Setting up providers ”You need two JSON-RPC providers: one for the source chain (where the transaction happened) and one for Creditcoin (where proofs are verified).
import { JsonRpcProvider } from 'ethers';import { chainInfo, blockProver, proofGenerator } from '@gluwa/usc-sdk';
// Source chain (e.g. Ethereum Sepolia)const sourceProvider = new JsonRpcProvider('https://sepolia.infura.io/v3/<api_key>'); //or other providers
// Creditcoin USC v2 Testnet, or CC3 Testnetconst creditcoinProvider = new JsonRpcProvider('https://rpc.usc-testnet.creditcoin.network'); //or CC3 Tesnet RPC, https://rpc.cc3-testnet.creditcoin.networkStep 1: Query supported chains
Section titled “Step 1: Query supported chains ”Use PrecompileChainInfoProvider to see which source chains are currently supported and find the chainKey for the chain you want to prove transactions from.
const chainInfoProvider = new chainInfo.PrecompileChainInfoProvider(creditcoinProvider);
const supportedChains = await chainInfoProvider.getSupportedChains();console.log(supportedChains);// [{ chainKey: 1, chainId: 11155111, chainName: 'Ethereum Sepolia', chainEncoding: 1 }, ...]The chainKey is a Creditcoin-internal identifier for a source chain — it is not the same as the chain’s EVM chainId. You will need it in every subsequent call.
Step 2: Wait for attestation
Section titled “Step 2: Wait for attestation ”Before a proof can be generated, the block containing your transaction must be attested on Creditcoin. Attestation happens periodically and automatically; you just need to wait for it.
const txHash = '0x6fe777442b70a5511f3c443176ae860e50445bd93b663711717996a70c5022ab';const chainKey = 1; // from Step 1
// Find which block the transaction is inconst tx = await sourceProvider.getTransaction(txHash);const blockNumber = tx!.blockNumber!;
// We create a connection to the proof generation server. We listen// for new attestations to be cached here rather than listening for// them directly on-chain. This prevents request timing issues.const proofGenApi = new proofGenerator.api.ProverAPIProofGenerator( chainKey, 'https://prover.usc-testnet.creditcoin.network', 5000, // request timeout in ms (optional, default: 5000));
// Wait until Creditcoin has attested that blockawait proofGenApi.waitUntilHeightAttested(chainKey, blockNumber);console.log(`Block ${blockNumber} is attested — ready to generate proof`);waitUntilHeightAttested polls the proofGenerationApi server at a configurable interval (default: 15 s) and resolves once the necessary attestation is present in the prover cache. It will throw after a configurable timeout (default: 15 m).
Step 3: Generate a proof with the Prover
Section titled “Step 3: Generate a proof with the Prover ”ProverAPIProofGenerator is the simplest way to get a proof. It calls a hosted API that computes and caches proofs on your behalf — no RPC-heavy local computation required.
const result = await proofGenApi.generateProof(txHash);
if (!result.success) { throw new Error(`Proof generation failed: ${result.error}`);}
const proofData = result.data!;console.log('Block number:', proofData.headerNumber);console.log('Transaction bytes:', proofData.txBytes);The returned proofData object contains everything needed for on-chain verification:
| Field | Type | Description |
|---|---|---|
chainKey |
number |
Source chain identifier |
headerNumber |
number |
Block number the transaction was in |
txHash |
string |
Transaction hash |
txBytes |
string |
ABI-encoded transaction |
merkleProof |
TransactionMerkleProof |
Siblings in the block’s transaction Merkle tree |
continuityProof |
ContinuityProof |
Chain of Merkle roots linking the block to an attestation |
cached |
boolean |
Whether the proof was served from cache |
Batch proof generation
Section titled “Batch proof generation ”If you need proofs for multiple transactions at once, use generateBatchProof. All transactions in a batch share a single continuity proof, which makes on-chain batch verification more efficient. The current MAX_BATCH_SIZE is 10 proofs, and these must be within a MAX_BATCH_RANGE of 1000 blocks.
const batchResult = await proofGenApi.generateBatchProof([txHash1, txHash2]);
if (!batchResult.success) { throw new Error(`Batch proof generation failed: ${batchResult.error}`);}
const batchData = batchResult.data!;Step 4: Verify the proof on-chain
Section titled “Step 4: Verify the proof on-chain ”PrecompileBlockProver submits proofs to Creditcoin’s verifier precompile.
Single transaction
Section titled “Single transaction ”const prover = new blockProver.PrecompileBlockProver(creditcoinProvider);
const verified = await prover.verifySingle( proofData.chainKey, proofData.headerNumber, proofData.txBytes, proofData.merkleProof, proofData.continuityProof,);
console.log('Verification result:', verified ? 'SUCCESS' : 'FAILED');Batch of transactions
Section titled “Batch of transactions ”When using batch proofs, you need to flatten the proof data into parallel arrays:
const headers: number[] = [];const txBytesArr: string[] = [];const merkleProofs = [];
for (const [headerNumber, proofsMap] of batchData.merkleProofs.entries()) { for (const [, proofEntry] of proofsMap.entries()) { headers.push(headerNumber); txBytesArr.push(proofEntry.txBytes); merkleProofs.push(proofEntry.merkleProof); }}
const batchVerified = await prover.verifyBatch( batchData.chainKey, headers, txBytesArr, merkleProofs, batchData.continuityProof,);
console.log('Batch verification result:', batchVerified ? 'SUCCESS' : 'FAILED');Complete end-to-end example
Section titled “Complete end-to-end example ”import { JsonRpcProvider } from 'ethers';
import { chainInfo, blockProver, proofGenerator } from '@gluwa/usc-sdk';
async function proveTransaction(txHash: string) {
// Resolve chain key
const chainKey = 1; // Ethereum Sepolia on USC Testnet2 and CC3 Testnet
// Providers
const sourceProvider = new JsonRpcProvider('https://sepolia.infura.io/v3/<api_key>'); //or other providers
const creditcoinProvider = new JsonRpcProvider('https://rpc.usc-testnet2.creditcoin.network'); //or CC3 Tesnet RPC, https://rpc.cc3-testnet.creditcoin.network
const chainInfoProvider = new chainInfo.PrecompileChainInfoProvider(creditcoinProvider);
const prover = new blockProver.PrecompileBlockProver(creditcoinProvider);
const proofGenApi = new proofGenerator.api.ProverAPIProofGenerator(
chainKey,
'https://prover.usc-testnet.creditcoin.network',
);
// Find block and wait for attestation
const tx = await sourceProvider.getTransaction(txHash);
await proofGenApi.waitUntilHeightAttested(chainKey, tx!.blockNumber!);
// Generate proof via API
const result = await proofGenApi.generateProof(txHash);
if (!result.success || !result.data) {
throw new Error(`Proof generation failed: ${result.error}`);
}
const { chainKey: ck, headerNumber, txBytes, merkleProof, continuityProof } = result.data;
// Verify on-chain
const verified = await prover.verifySingle(ck, headerNumber, txBytes, merkleProof, continuityProof);
console.log('Proof verification:', verified ? 'SUCCESS' : 'FAILED');
return verified;
}
Alternative: Raw proof generator
Section titled “Alternative: Raw proof generator ”For advanced use cases where you need full control (e.g. running your own indexer, offline proof computation, or custom block providers), the SDK also ships a RawProofGenerator that computes proofs locally by fetching data directly from source chain RPCs.
import { EncodingVersion } from '@gluwa/usc-sdk/encoding';
const blockProvider = new proofGenerator.raw.blockProvider.SimpleBlockProvider(sourceProvider);const rawGenerator = new proofGenerator.raw.RawProofGenerator( chainKey, blockProvider, chainInfoProvider, EncodingVersion.V1,);
const result = await rawGenerator.generateProof(txHash);Both RawProofGenerator and ProverAPIProofGenerator implement the same ProofGenerator interface and produce identical output, so you can swap between them without changing any downstream code.