Tenzro Testnet is live —request testnet TNZO
← Back to Tutorials
App DevelopmentAdvanced

Build a Gasless App with Paymaster

Build an application where users never see gas fees. The developer funds a master wallet with TNZO, and the AppClient sponsors all user operations -- transactions, inference, agent spawning, and bridging. This is the Stripe model for Web3: developers pay, users just use the app.

What We're Building

Architecture


// Developer deploys app with master wallet
//
// Master Wallet (funded with TNZO)
//     |
//     +-- User A wallet (auto-funded, spending limit: 10 TNZO/day)
//     |     +-- Session key: inference only, 24h expiry
//     |
//     +-- User B wallet (auto-funded, spending limit: 50 TNZO/day)
//     |     +-- Session key: full access, 1h expiry
//     |
//     +-- Agent C wallet (auto-funded, delegation scope)
//           +-- Allowed: inference, settlement
//           +-- Max per tx: 5 TNZO

Step 1: Install the SDK

TypeScript

npm install tenzro-sdk

Rust

cargo add tenzro-sdk

Step 2: Initialize AppClient with Master Wallet

import { AppClient } from 'tenzro-sdk';

// Create AppClient with master wallet private key
const app = await AppClient.new(
  'https://rpc.tenzro.network',
  process.env.MASTER_PRIVATE_KEY!
);

// Or use API key (recommended for production)
const app = await AppClient.fromApiKey(
  'https://rpc.tenzro.network',
  process.env.TENZRO_API_KEY!
);

console.log('Master balance:', await app.getMasterBalance());

Step 3: Register Your App

// Register app on the network (returns API key)
const registration = await app.client.rpc.call('tenzro_registerApp', {
  name: 'My Gasless DeFi App',
  master_wallet_address: app.masterWallet.address
});

console.log('App ID:', registration.app_id);
console.log('API Key:', registration.api_key);

Step 4: Create User Wallets

// Create wallet for a human user (funded with 1 TNZO from master)
const alice = await app.createUserWallet('alice', 1000000000000000000n);
console.log('Alice wallet:', alice.address);

// Create wallet for an agent user
const agent = await app.createUserWallet('research-bot', 500000000000000000n);
console.log('Agent wallet:', agent.address);

// List all user wallets
const users = await app.listUserWallets();
console.log(users.length, 'user wallets');

Step 5: Set Spending Limits

// Alice: max 10 TNZO/day, max 2 TNZO per transaction
await app.setUserLimits(
  alice.address,
  10000000000000000000n,  // 10 TNZO daily
  2000000000000000000n    // 2 TNZO per tx
);

// Agent: tighter limits
await app.setUserLimits(
  agent.address,
  5000000000000000000n,   // 5 TNZO daily
  1000000000000000000n    // 1 TNZO per tx
);

Step 6: Create Session Keys

// Give Alice a 24h session key for inference only
const aliceSession = await app.createSessionKey(
  alice.address,
  86400,  // 24 hours
  ['inference', 'balance_query']
);
console.log('Session:', aliceSession.session_id);

// Give the agent a 1h session key for full operations
const agentSession = await app.createSessionKey(
  agent.address,
  3600,  // 1 hour
  ['inference', 'settlement', 'bridge', 'transfer']
);

Step 7: Sponsor Operations

// Sponsor an inference request (master pays)
const result = await app.sponsorInference(
  alice.address,
  'gemma3-270m',
  'Explain how smart contracts work'
);
console.log('Response:', result.output);
console.log('Cost:', result.cost, 'TNZO (paid by master wallet)');

// Sponsor a transaction (master pays gas)
await app.sponsorTransaction(
  alice.address,
  '0xRecipientAddress...',
  100000000000000000n  // 0.1 TNZO
);

// Sponsor agent spawning (master pays)
const spawnedAgent = await app.sponsorAgent(
  alice.address,
  'alice-helper',
  ['nlp', 'code']
);

// Sponsor bridge (master pays bridge fees)
await app.sponsorBridge(
  alice.address,
  'TNZO', 'ethereum', 'arbitrum',
  '1000000000000000000', // 1 TNZO
  '0xArbitrumRecipient...'
);

Step 8: Monitor Usage

const stats = await app.getUsageStats();
console.log('Total gas spent:', stats.total_gas_spent);
console.log('Inference cost:', stats.total_inference_cost, 'TNZO');
console.log('Bridge fees:', stats.total_bridge_fees);
console.log('User count:', stats.user_count);
console.log('Transactions:', stats.transaction_count);

Step 9: Fund Master Wallet

// Check master balance
const balance = await app.getMasterBalance();
console.log('Master balance:', balance / 10n**18n, 'TNZO');

// On testnet, use faucet
await app.client.wallet.requestFaucet(app.masterWallet.address);

Production Considerations

Related