Full-codebase-audit 2026-05-30 outputs: - Audit report: 09 - Audits/Full Codebase Audit - 2026-05-30.md - 81 issue files ISSUE-055..135 (decisions + 1 skipped no-brainer). - Scanner docs from scratch (was zero): architecture, data model, API ref, payment flow, operations runbook + repo README. - Doc-sync updates across API reference, data models, flows, design system. - Secret Rotation Runbook (08 - Operations) for the exposed credentials. - Reusable workflow guide (07 - Development) + .claude/workflows/full-codebase-audit.js. Issues remain status:open intentionally — the code fixes are uncommitted-then-committed working-tree changes per repo and aren't "resolved" until merged/deployed. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
5.2 KiB
5.2 KiB
title, tags, created
| title | tags | created | |||
|---|---|---|---|---|---|
| ScannerIntent (Scanner DB model) |
|
2026-05-30 |
ScannerIntent
SQLite row in the AMN Pay Scanner's intents table. One row per payment intent registered by the backend. This is internal scanner state — it is not a Mongoose model and lives in a separate SQLite database (/data/scanner.db).
Schema
CREATE TABLE intents (
intent_id TEXT PRIMARY KEY,
chain_id INTEGER NOT NULL,
chain_type TEXT NOT NULL DEFAULT 'evm',
token_address TEXT NOT NULL,
destination TEXT NOT NULL,
amount TEXT NOT NULL,
payment_reference TEXT NOT NULL,
topic_ref TEXT,
status TEXT NOT NULL DEFAULT 'pending',
callback_url TEXT NOT NULL,
callback_secret TEXT NOT NULL,
confirmations_required INTEGER NOT NULL DEFAULT 12,
tx_hash TEXT,
log_index INTEGER,
block_number INTEGER,
confirmations INTEGER NOT NULL DEFAULT 0,
salt TEXT NOT NULL,
webhook_delivered_at TEXT,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
);
Fields
| Field | Type | Description |
|---|---|---|
intent_id |
TEXT PK | Caller-supplied unique ID (typically the backend Payment _id) |
chain_id |
INTEGER | Numeric chain ID. EVM standard (56, 137, 1, 42161, 8453), Tron (728126428), TON (1100) |
chain_type |
TEXT | evm / tron / ton. Determines which worker handles this intent |
token_address |
TEXT | ERC20 / TRC20 contract address. EVM/Tron: lowercase 0x hex. TON: exact base64url |
destination |
TEXT | Recipient wallet address. EVM/Tron: lowercase 0x hex. TON: base64url (case-sensitive) |
amount |
TEXT | Required amount in smallest token unit (wei / 10^decimals), stored as base-10 integer string |
payment_reference |
TEXT | 8-byte hex EVM payment reference (0x + 16 hex chars). Derived as last8(keccak256(intentId + salt + destination)) |
topic_ref |
TEXT | keccak256(paymentReferenceBytes) — matches Topics[1] in EVM logs. Pre-computed for indexed DB lookup. NULL for Tron/TON |
status |
TEXT | Intent lifecycle state (see below) |
callback_url |
TEXT | URL the scanner POSTs to on confirmation |
callback_secret |
TEXT | HMAC-SHA256 key for webhook signature. Never returned in API responses |
confirmations_required |
INTEGER | Number of blocks required before confirmation (EVM). Defaults to chain config |
tx_hash |
TEXT NULL | Transaction hash once a matching transfer is detected |
log_index |
INTEGER NULL | Log position within the transaction (EVM only; 0 for Tron/TON) |
block_number |
INTEGER NULL | Block number (EVM/Tron) or Unix timestamp seconds (TON) when the tx was seen |
confirmations |
INTEGER | Current confirmation depth. Incremented each scan cycle for confirming intents |
salt |
TEXT | 32-byte random hex. Combined with intent_id and destination to derive payment_reference. Prevents reference collisions across retried payments |
webhook_delivered_at |
TEXT NULL | RFC3339 timestamp when the webhook was successfully delivered. Used for startup crash recovery |
created_at / updated_at |
DATETIME | UTC timestamps |
Status values
| Status | Description |
|---|---|
pending |
Registered; scanner is watching for a matching on-chain transfer |
confirming |
EVM only — matching tx seen, waiting for confirmations_required blocks |
confirmed |
Payment confirmed; webhook delivery attempted |
expired |
TTL exceeded while still in pending or confirming |
webhook_failed |
All webhook delivery retries exhausted; manual retry or periodic auto-retry needed |
Indexes
CREATE INDEX idx_intents_status ON intents(status);
CREATE INDEX idx_intents_chain_status ON intents(chain_id, status);
CREATE INDEX idx_intents_payment_ref ON intents(payment_reference);
CREATE INDEX idx_intents_topic_ref ON intents(topic_ref);
CREATE UNIQUE INDEX idx_intents_tx_log ON intents(tx_hash, log_index)
WHERE tx_hash IS NOT NULL;
idx_intents_topic_ref is the performance-critical index — the EVM scanner's inner loop does a single indexed lookup per log entry.
The unique index on (tx_hash, log_index) prevents two intents being confirmed from the same on-chain event (double-spend protection).
Migrations
Three additive migrations run at startup (idempotent):
ADD COLUMN topic_ref TEXT— added after initial schemaADD COLUMN chain_type TEXT NOT NULL DEFAULT 'evm'— added for Tron/TON supportADD COLUMN webhook_delivered_at TEXT— added for crash recovery
A backfill pass recomputes topic_ref for existing EVM intents that had it as NULL.
Related
- Scanner Architecture
- Scanner API
- Payment Flow - Scanner
- Payment — the backend MongoDB model that triggers intent creation