Wallet SDK — @insureco/wallet

The @insureco/wallet TypeScript client for iec-wallet. Check balances, charge gas, credit tokens, query the ledger, and validate deploy reserves — with full type safety and built-in retry logic.

Installation

npm install @insureco/wallet
// Production
import { WalletClient, WalletError, deriveWalletId } from '@insureco/wallet'

// Testing
import { MockWalletClient } from '@insureco/wallet/testing'

Zero external dependencies — uses only native Node.js fetch, crypto, and AbortSignal.

Quick Start

import { WalletClient } from '@insureco/wallet'

// From explicit config
const wallet = new WalletClient({
  baseUrl: process.env.IEC_WALLET_URL || 'http://localhost:3002',
  serviceKey: process.env.INTERNAL_SERVICE_KEY,
})

// Or from environment variables
const wallet = WalletClient.fromEnv()

// Ensure a wallet exists (idempotent)
const { wallet: w } = await wallet.ensureWallet({
  ownerId: 'my-org',
  ownerType: 'organization',
  ownerName: 'My Organization',
})
// w.id === 'wallet-my-org'
// w.totalBalance === 50000  (org gets 50K intro tokens)

Wallet Operations

// Check balance
const balance = await wallet.getBalance('wallet-my-org')
// { walletId, totalBalance, balances: [{ tokenType, balance }] }

// Credit tokens
await wallet.credit('wallet-my-org', {
  amount: 10000,
  tokenType: 'purchased',
  reason: 'Token purchase',
  referenceId: 'purchase-123',
})

// Query ledger
const ledger = await wallet.getLedger('wallet-my-org', {
  page: 1,
  limit: 20,
  serviceId: 'my-api',  // optional filter
})

Charging Gas

Gas TypeWhat It Pays ForUses Intro Tokens?
hostingPod uptime (charged hourly)Yes
transactionAPI calls through JanusNo — automatically skipped
// Hosting gas (uses intro tokens)
await wallet.debit('wallet-my-org', {
  amount: 5,
  reason: 'hosting_gas',
  gasType: 'hosting',
  serviceId: 'my-api',
})

// Transaction gas (purchased/earned only)
await wallet.debit('wallet-my-org', {
  amount: 1,
  reason: 'api_call',
  gasType: 'transaction',
  serviceId: 'my-api',
})

Deploy Gate Check

const { sufficient, balance, required } = await wallet.checkReserve({
  walletId: 'wallet-my-org',
  podTier: 'nano',  // nano | small | medium | large | xlarge
  months: 3,
})

if (!sufficient) {
  throw new Error(`Insufficient reserve: ${balance} < ${required}`)
}

Testing with MockWalletClient

import { MockWalletClient } from '@insureco/wallet/testing'

const mockWallet = new MockWalletClient()

// Pre-seed a wallet balance
mockWallet.seed('wallet-test-org', 50000)

// Inject into your service
const service = new MyService({ wallet: mockWallet })
await service.processPayment('wallet-test-org', 100)

// Assert
expect(mockWallet.getBalance('wallet-test-org').totalBalance).toBe(49900)
expect(mockWallet.transactions).toHaveLength(1)

Error Handling

import { WalletError } from '@insureco/wallet'

try {
  await wallet.debit('wallet-my-org', { amount: 100, gasType: 'hosting' })
} catch (err) {
  if (err instanceof WalletError) {
    if (err.code === 'INSUFFICIENT_BALANCE') {
      // handle low balance
    }
  }
}

Environment Variables

VariableRequiredDescription
IEC_WALLET_URLYes*Base URL of the wallet service
WALLET_URLFallbackAlternative if IEC_WALLET_URL is not set
INTERNAL_SERVICE_KEYNoService-to-service auth key

Declare iec-wallet in internalDependencies to have IEC_WALLET_URL auto-injected:

spec:
  internalDependencies:
    - service: iec-wallet   # injects IEC_WALLET_URL

Last updated: February 28, 2026