Integrate Zoza Shield
Wallet-drain protection for your users, in 5 minutes. Browser extension, TypeScript SDK, REST API, and an on-chain guard — pick what fits your stack.
Quick Start
The fastest path: install the SDK, assess a transaction before your user signs, show a warning if risky.
import { ShieldClient } from '@zoza/shield';
const shield = new ShieldClient(); // free tier, no key needed for checkOrigin
// Before the user signs anything:
const risk = await shield.assessTransaction({
chain: 'eth',
tx: { to: '0x...', data: '0x095ea7b3...', value: '0x0' },
origin: 'https://my-exchange.com'
});
if (risk.risk === 'critical') {
// block the signature, show a warning, require typed acknowledgement
showBlockingModal(risk.summary);
}
That's it — your users are now protected against Permit2 drainers, infinite approvals, phishing origins, and the other 8 attack classes Shield decodes. Keep reading for authenticated endpoints, the browser extension, and the on-chain guard.
Pick Your Integration
Zoza Shield ships four integration surfaces. Use as many as make sense for your product.
Browser Extension
Chrome/Brave/Edge extension. Blocks phishing dApps before your user's wallet loads them. Zero integration — your users install it themselves.
TypeScript SDK
Drop-in risk assessment for any wallet UI. Decodes calldata locally, checks origins against the signed registry, flags Permit2 and approval drainers.
REST API
HTTP/JSON endpoints for everything the SDK does. Call from Go, Python, Rust, mobile, backends — whatever runs your stack.
On-Chain Safe Guard
Gnosis Safe / account-abstraction module. Enforces Shield's allowlist on-chain — drain transactions revert at the contract level, not just the UI.
Apply for an API Key
Most endpoints are free and keyless — /v1/check, /v1/registry, /v1/report, and the audit log are open to anyone. You only need an API key for the B2B decode and assess-signature endpoints (which count toward your daily quota).
Fill the form below — we review within 24 hours and email your zsk_live_... key on approval. Keys are shown once at issuance — store yours somewhere safe.
Authentication
Pass your key as a Bearer token:
Authorization: Bearer zsk_live_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Every authenticated response includes rate-limit headers:
X-RateLimit-Limit: 100000 # your daily quota
X-RateLimit-Remaining: 99872 # calls left today
X-RateLimit-Reset-UTC: 00:00 # quota resets at UTC midnight
If a key is invalid, revoked, or over quota, the response is 401 with an X-Zoza-Auth-Error header explaining which of those it was.
Base URL
https://shield-api.zoza.world
All API paths below are relative to that base. The default in the TypeScript SDK already points at this host — override via new ShieldClient({ apiURL: '...' }) if you proxy through your own infra.
TypeScript SDK — Installation
npm install @zoza/shield
pnpm add @zoza/shield
yarn add @zoza/shield
Zero runtime dependencies. Ships ESM + CJS + TypeScript types. Works in browsers, Node ≥18, Deno, Bun, React Native (with a fetch polyfill).
import { ShieldClient } from '@zoza/shield';
const shield = new ShieldClient({
apiKey: process.env.SHIELD_KEY, // optional for free endpoints
apiURL: 'https://shield-api.zoza.world', // default
offline: false, // if true, skips network calls
});
Assess a Transaction
Call before the user signs. Returns a ThreatAssessment with a risk level (low | medium | high | critical) and a human-readable summary.
const assessment = await shield.assessTransaction({
chain: 'eth', // 'eth' | 'sol' | 'tron' | 'btc'
tx: {
to: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
data: '0x095ea7b3...ffff', // approve(spender, amount) calldata
value: '0x0'
},
origin: 'https://app.some-dapp.com',
method: 'eth_sendTransaction'
});
// assessment shape:
// { risk: 'critical', title: 'Token approval',
// summary: 'Unlimited approval to 0x...',
// decoded: {...}, siteStatus: {...}, requireTypedAck: true }
if (assessment.requireTypedAck) {
// Force the user to type "I UNDERSTAND" to proceed.
}
Assess a Signature (EIP-712 / Permit2)
The #1 drainer technique in 2024 was off-chain signatures, not on-chain approvals. Catch them:
const typedData = { /* EIP-712 struct the user is about to sign */ };
const assessment = await shield.assessSignature({
chain: 'eth',
typedData,
origin: 'https://random-airdrop.xyz'
});
// Catches: Permit, Permit2, PermitForAll, Seaport orders with drainer patterns,
// domain/origin mismatches, infinite-amount permits, attacker-controlled spenders.
if (assessment.domainMismatch) {
// Signature domain (e.g. "app.uniswap.org") doesn't match page origin.
// Classic phishing setup — block it.
}
Check an Origin Against the Registry
const site = await shield.checkOrigin('https://app.uniswap.org');
// { status: 'verified', dapp: { name: 'Uniswap', category: 'dex' } }
const bad = await shield.checkOrigin('https://uniswap-app.com');
// { status: 'phishing', threat: { type: 'phishing', target_dapp: 'Uniswap' } }
Offline Mode — Local Decoding Only
For wallets that can't afford a network round-trip per transaction, or need to work in air-gapped environments. Skips the registry check but still decodes the calldata.
const shield = new ShieldClient({ offline: true });
const decoded = shield.decodeCalldataLocal('0x095ea7b3...ffff');
// { name: 'approve', risk: 'critical', summary: 'Unlimited ERC-20 approval' }
const sigRisk = shield.detectSignatureRiskLocal(typedData, 'app.dapp.com');
// { kind: 'permit2', risk: 'high', summary: '...', domainOriginMismatch: false }
REST API — Public Endpoints
curl -X POST https://shield-api.zoza.world/v1/check \
-H "Content-Type: application/json" \
-d '{"url":"https://app.uniswap.org"}'
{
"status": "verified",
"dapp": { "name": "Uniswap", "category": "dex", "chains": ["ethereum"] },
"action": "allow"
}
// Possible status values:
// "verified" — registered dApp, safe
// "known" — seen before, not flagged (neutral)
// "suspicious" — partial match or heuristic warning
// "phishing" — actively flagged as malicious
// "unknown" — first time we've seen it
GET /v1/registry
Cache-Control: max-age=300.{
"version": 1247,
"dapps": [ { "name": "Uniswap", "domains": [...], "category": "dex" }, ... ],
"threats": [ { "domain": "uniswap-app.com", "type": "phishing" }, ... ],
"signature": "base64-ed25519-signature",
"signed_at": "2026-04-17T10:32:05Z",
"pubkey": "34b83458d85068871ccac6bd9efe93303acb6df2d0d6ee5a818224ba3265f9b9"
}
Verify the signature with the published pubkey (see Shield Canary). Any integrator can prove the registry hasn't been tampered with.
POST /v1/report
curl -X POST https://shield-api.zoza.world/v1/report \
-H "Content-Type: application/json" \
-d '{"domain":"uniswap-app.com","target_dapp":"Uniswap","type":"phishing","reported_by":"user@example.com"}'
GET /v1/stats
dapps_count, threats_count, registry version.REST API — B2B Endpoints (require API key, count toward quota)
POST /v1/decode
curl -X POST https://shield-api.zoza.world/v1/decode \
-H "Content-Type: application/json" \
-H "Authorization: Bearer zsk_live_YOURKEY" \
-d '{"calldata":"0x095ea7b3000000000000000000000000...ffff","origin":"https://app.uniswap.org","chain":"eth"}'
{
"decoded": {
"name": "approve",
"summary": "Unlimited approval of USDC to 0x...",
"risk": "critical",
"params": { "spender": "0x...", "amount": "MAX_UINT256" }
},
"site_status": { "status": "verified", "dapp": {...} },
"chain": "eth"
}
POST /v1/assess-signature
shield.assessSignature(). Useful for backend risk-scoring, fraud detection, logged signatures.{
"typed_data": { /* full EIP-712 struct */ },
"origin": "https://sketchy-airdrop.xyz",
"chain": "eth"
}
GET /v1/key-info
Audit Log
{valid: true, length: N} or the index of the first broken link.See the Shield Audit page for the web UI + independent verifier.
Browser Extension
The Zoza Shield extension is a drop-in protection layer for your users. No integration required on your side — your users install it themselves from the Chrome Web Store.
Partner with Us
If you're a wallet, exchange, or dApp and want to surface the Shield warning inside your own UI (instead of relying on users to install the extension), use the SDK. If you want your users nudged to install the extension, we provide:
- Co-branded install flow (
zoza.world/shield?from=yourdapp) - Extension-detection snippet (detects if Shield is installed, shows an install banner if not)
- Attribution pixel for measuring protection rates
Email hello@zoza.world for the partnership kit.
On-Chain Safe Guard
ZozaSafeGuard.sol is a Gnosis Safe Transaction Guard that enforces Shield's signed allowlist on-chain. Even if a UI is compromised, drain transactions revert at the contract level.
The contract has 18 Foundry tests + formal property checks, but has not been through a third-party audit yet (Trail of Bits / Spearbit queued, ~4-8 weeks). Use on testnet and small-value mainnet Safes until the audit lands. Treasuries — wait for the audit.
Architecture
- Root: Ed25519 pubkey pinned in the guard. Same key that signs the API registry.
- Allowlist: Signed (root_pubkey, target, selector, expires_at) tuples. Guard verifies the sig on every Safe transaction.
- Rotation: 6-step ceremony, documented in
products/zoza-shield/OPS.md. - Emergency: Safe owners can disable the guard via a separate multisig threshold — no lock-out risk.
Signed Allowlist Flow (concept)
- Off-chain: Shield signs an allowance tuple
(target, selector, expires_at)with the root Ed25519 key. - On-chain: Your Safe transaction includes the signature as part of its payload.
- Guard check:
ZozaSafeGuard.checkTransaction()verifies the signature against the pinned root pubkey before allowing execution. No signature → revert.
The REST endpoint that serves these signatures and a reference integration are being finalised for the audit freeze. Ask for early-access access above if you want to integrate on testnet now.
Safe Guard is pre-release — contract source, deployment scripts, and the signed-allowlist flow will be published alongside the third-party audit. For early-access integration on testnet, email hello@zoza.world. Read the Safe Guard walkthrough for the threat model in plain English.
Error Codes
| HTTP | Meaning | When It Happens |
|---|---|---|
| 200 | OK | Request succeeded. |
| 201 | Created | Report / dApp / threat registered. |
| 400 | Bad Request | Missing required field, malformed JSON, invalid chain, calldata not hex. |
| 401 | Unauthorized | Missing Bearer token, invalid key, revoked key, or quota exceeded. Check X-Zoza-Auth-Error for the specific cause. |
| 404 | Not Found | Unknown path or resource. |
| 500 | Server Error | Bug on our side — report to hello@zoza.world with the request ID. |
Rate Limits & Plans
Free endpoints (/v1/check, /v1/registry, /v1/report, audit log) are unlimited and keyless. B2B endpoints (/v1/decode, /v1/assess-signature) count against your daily quota.
Free
- Calldata decoder
- Signature risk assessment
- Community support
Pro
- Everything in Free
- Email support (24h SLA)
- Usage dashboard
- Custom integration help
Enterprise
- Everything in Pro
- Dedicated infrastructure
- SLA + on-call
- Private Safe Guard deployment
- On-prem / VPC option
Quota resets at UTC midnight. If you hit your limit, requests return 401 with X-Zoza-Auth-Error: quota exceeded. Upgrade inline by emailing us — no downtime.
CORS
All endpoints allow all origins (Access-Control-Allow-Origin: *) for the v0.2 release. This lets browser SDKs work without a proxy. If you need origin-pinned CORS for your own compliance — or a dedicated instance running in your VPC — email hello@zoza.world.
Going-Live Checklist
Support
| hello@zoza.world — fastest for integration questions, API key requests, partnership | |
| Status | shield-api.zoza.world/health — live uptime |
| Audit | Audit log · Canary · Retention |
| @zoza_world — launches, incidents, roadmap | |
| Source | Public repo + open-source licence planned. Until then, integration is via SDK + hosted API. Email for source access under NDA. |
© Zoza · zoza.world · Source-available open-sourcing planned — the hosted API, SDK, and extension are live today.