Security / Audit·EVM · Solana · Multi-chain
Blowfish
Pre-signature transaction simulation and signature scanning for wallets and dApps. Renders a human-readable preview of every state change (token transfers, NFT moves, approvals) and labels malicious or suspicious patterns before the user clicks Confirm. Covers EVM chains and Solana via a single API + npm client.
- 01pre-signature transaction simulation
- 02signature/personal_sign warnings
- 03asset-diff previews (in/out, approvals)
- 04wallet UI security badges
- 05dApp connect-time scam warnings
- pnpm add @blowfishxyz/api-client
| Variable | Scope | Description |
|---|---|---|
| BLOWFISH_API_KEY | Server | Blowfish API key, sent in the `X-Api-Key` header. SERVER-SIDE ONLY — proxy from your backend; do not ship to the browser. |
Use Blowfish before any signature. Initialize `import { createClient } from '@blowfishxyz/api-client'; const client = createClient({ basePath: 'https://api.blowfish.xyz', apiKey: process.env.BLOWFISH_API_KEY });`. EVM tx scan: `client.scanTransactionsEvm({ chainNetwork: 'mainnet', chainFamily: 'ethereum', userAccount, txObjects: [{ from, to, value, data }], metadata: { origin } })` returns `{ action: 'NONE'|'WARN'|'BLOCK', warnings: [...], simulationResults: { aggregated: { expectedStateChanges, error } } }`. Personal-sign / typed-data scan: `client.scanMessageEvm({ chainNetwork, chainFamily, userAccount, message: { kind: 'TYPED_DATA'|'SIGN_MESSAGE', rawMessage } })`. Solana: `client.scanTransactionsSolana({ network, userAccount, transactions: [base64SerializedMessage] })`. Re-request the simulation every ~5s while the confirm modal is open so the preview stays fresh against pending state, and gate the signing button on `action !== 'BLOCK'`. Render `expectedStateChanges` as the user-facing 'You will send / You will receive' diff.
- ⚑Blowfish API keys MUST stay on the server — exposing one in the browser leaks rate-limit budget and is explicitly called out as a misuse in the docs. Always proxy through `/api/scan`.
- ⚑Solana scan expects base64-encoded serialized messages, NOT base58 transaction signatures or unsigned tx wire format — passing the wrong encoding silently returns `NONE`.
- ⚑Simulation results go stale within seconds for high-throughput chains and AMM swaps with tight slippage — re-request every 5s while the confirm modal is open or display a 'preview may be outdated' badge.
- ⚑False positives on novel-but-legit dApps and brand-new tokens (cold-start problem) are real; provide a 'proceed anyway' affordance with prominent risk copy rather than hard-blocking.
- ⚑EVM chain coverage is broad on majors (Ethereum, Polygon, BSC, Arbitrum, Optimism, Base, Avalanche) but partial on long-tail L2s — verify the (chain, product) pair before shipping a warning the user might not understand.
- ⚑Latency is typically 200–800ms but can spike for novel contracts requiring just-in-time fork simulation; run the scan in parallel with rendering the confirm modal and fail-open with a warning badge if it times out.