5 minute guide

Quick Start

Build your first compliant DeFi transaction in under 5 minutes.

Read this before you write a single line of code

ILAL's ComplianceHook rejects every on-chain transaction from a wallet without an active compliance session. The API will build and return a valid unsigned TX — but when you broadcast it, the chain will revert. Step 2 activates your session. Do it before calling any DeFi endpoint.

1

Get Your API Key

Register at ilal.tech/login, then go to the API Keys dashboard and click Create API Key.

Your key will look like:
ilal_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Copy and save your key immediately — it will only be shown once.
2

Activate Your Wallet (Required Before Any On-Chain TX)

One call. Handles registration + session activation in a single request. No ZK proof required on testnet. The relayer pays gas.

curl
curl -X POST https://ilal-mvp-production.up.railway.app/api/v1/testnet/activate \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"walletAddress": "YOUR_WALLET_ADDRESS"}'
Expected response:
json
{
  "success": true,
  "walletAddress": "0x...",
  "txHash": "0x...",
  "expiresAt": "2026-04-05T14:00:00.000Z",
  "note": "Testnet only — ZK proof bypassed."
}
Idempotent: safe to call multiple times. If already registered or active, returns existing state.
Session duration: 24 hours by default. Pass durationHours to extend up to 720h.
Multi-wallet: use POST /testnet/activate-batch with {"wallets": ["0x...", "0x..."]} for up to 20 wallets at once.
Session expires? Just call this endpoint again — no re-registration needed.

Verify your session is active:

curl
curl https://ilal-mvp-production.up.railway.app/api/v1/session/YOUR_WALLET_ADDRESS \
  -H "X-API-Key: YOUR_API_KEY"
# → { "isActive": true, "remainingSeconds": 86342 }
ProductionUses ZK proof instead of bypass
  1. Register → POST /onboarding/register
  2. Get attestation → GET /onboarding/attestation/:address
  3. Generate PLONK proof client-side
  4. Submit → POST /verify
3

Build a Swap Transaction

Call POST /defi/swap. Returns unsigned calldata plus a live preflight that simulates the TX on-chain before returning.

curl
curl -X POST https://ilal-mvp-production.up.railway.app/api/v1/defi/swap \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "tokenIn":     "0x4200000000000000000000000000000000000006",
    "tokenOut":    "0xa486Fb51ED09B970A23F7Fe910bc90089f78424D",
    "amount":      "1000000000000000",
    "userAddress": "YOUR_WALLET_ADDRESS"
  }'
Response:
json
{
  "success": true,
  "transaction": { "to": "0x...", "data": "0x...", "value": "0x0", "chainId": 84532, "gas": "0x1E8480" },
  "preflight": {
    "sessionActive": true,
    "canBroadcastSafely": true,
    "simulation": { "success": true }
  }
}
If canBroadcastSafely is false — do not broadcast. Check preflight.simulation.revertReason for the exact cause. Most common: session expired → re-run Step 2.
4

Sign & Broadcast

Take result.transaction and send it with your own signer.

TypeScript (viem)
import { createWalletClient, http } from 'viem';
import { privateKeyToAccount } from 'viem/accounts';
import { baseSepolia } from 'viem/chains';

const account = privateKeyToAccount(YOUR_PRIVATE_KEY);
const wallet  = createWalletClient({ account, chain: baseSepolia, transport: http() });

// Step 2: activate (if not already done)
await fetch('https://ilal-mvp-production.up.railway.app/api/v1/testnet/activate', {
  method: 'POST',
  headers: { 'X-API-Key': 'YOUR_API_KEY', 'Content-Type': 'application/json' },
  body: JSON.stringify({ walletAddress: account.address }),
});

// Step 3: build
const res = await fetch('https://ilal-mvp-production.up.railway.app/api/v1/defi/swap', {
  method: 'POST',
  headers: { 'X-API-Key': 'YOUR_API_KEY', 'Content-Type': 'application/json' },
  body: JSON.stringify({
    tokenIn:     '0x4200000000000000000000000000000000000006',
    tokenOut:    '0xa486Fb51ED09B970A23F7Fe910bc90089f78424D',
    amount:      '1000000000000000',
    userAddress: account.address,
  }),
});
const { transaction, preflight } = await res.json();

// Guard: never broadcast if simulation failed
if (!preflight.canBroadcastSafely) {
  throw new Error(`Cannot broadcast: ${preflight.simulation?.revertReason}`);
}

// Step 4: send
const hash = await wallet.sendTransaction({
  to:    transaction.to,
  data:  transaction.data,
  value: BigInt(transaction.value),
});
console.log('Confirmed:', hash);

Troubleshooting Checklist

If something isn't working, run through this in order:

1GET /health200 — API reachableWrong URL or network issue
2GET /usage/stats (X-API-Key)200 — key worksCheck error.code: API_KEY_FORMAT_INVALID / API_KEY_HASH_MISMATCH
3POST /testnet/activatetxHash — session active500 → check VERIFIER_PRIVATE_KEY on server side
4GET /session/:addressisActive: trueSession not yet on-chain — wait 1 block and retry
5GET /preflight/:addresscanSwap: trueCheck readiness.issues[] for missing allowances or balance
6POST /defi/swapcanBroadcastSafely: trueCheck simulation.revertReason — session / allowance / pool depth
7Sign + BroadcastOn-chain confirmedcanBroadcastSafely was false — never broadcast if false