Skip to main content

Gas API

Web3 (MPC-EOA) vaults pay their own gas — a vault holding tokens but no native coin (ETH/BNB/MATIC) can't broadcast a withdrawal. ZenVault manages this: you fund one gas wallet per workspace, and ZenVault automatically tops up your vaults from it on demand (and tells you when to refill). Asset vaults are unaffected — their gas is handled for you.

The split: you fund and watch the gas wallet; ZenVault distributes it to your vaults, audits the spend, and alerts you when it's low.

MethodPathScope
POST/v1/gas/walletaccounts:write
GET/v1/gasbalances:read
POST/v1/gas/ensuretransfers:write

Provision your gas wallet

POST /v1/gas/wallet is idempotent create-or-return — safe to call on every boot. It creates a web3 MPC-EOA (purpose: gas) if you don't have one and returns the address to fund. There is one gas wallet per workspace.

POST /v1/gas/wallet
→ {
"created": true,
"accountId": "…",
"label": "<workspace>-gas",
"chains": [
{ "chain": "ethereum", "address": "0x…", "balance": 0, "threshold": 0.03, "status": "empty" }
]
}

A web3 gas wallet is one EVM address that works on every EVM chain, so funding that one address covers gas on Ethereum, BSC, Polygon, etc.

Fund it, then watch it

Send native coin to the returned address — the only manual step. Then:

  • GET /v1/gas returns per-chain balance, threshold, status (healthy / low / empty), 24h top-up spend, and how many transfers are awaiting broadcast — render it in your dashboard with a "top up" prompt.
  • gas.low / gas.depleted webhooks fire when the wallet drops below threshold / can't fund top-ups, so you refill before withdrawals stall.

How top-ups work

When a web3-vault withdrawal can't pay gas, ZenVault sends a native top-up from your gas wallet to that vault, then the withdrawal broadcasts automatically on the next cycle — no retry needed on your side. Each top-up is a normal transfer tagged metadata.kind = "gas_topup", visible in GET /v1/transfers. Top-ups are sized to the tx's actual cost, so a small gas balance funds many sends.

Pre-gas before a time-sensitive op

The reactive top-up is fine for plain withdrawals, but for a swap whose quote expires in seconds the top-up latency can outlive the quote. Call ensure before you request the quote: it tops the vault up to minNative and blocks until the gas lands, so the signed swap broadcasts immediately.

POST /v1/gas/ensure
{
"accountId": "0536…", // the vault you'll swap from
"chain": "ethereum",
"minNative": "0.0015", // gas + native value the swap needs
"waitMs": 60000 // optional, default 60s, max 120s
}
→ {
"ready": true, // false → re-call to keep waiting
"chain": "ethereum",
"vaultAddress": "0xB322…",
"balance": 0.0021,
"required": 0.0015,
"topupTransferId": "…", // present when a top-up was kicked off
"waitedMs": 9000
}
  • Idempotent — if ready:false, just call again; it won't stack a second top-up within the cooldown, it keeps waiting.
  • If the vault already holds ≥ minNative, it returns ready:true instantly.
  • Set a generous client timeout (it can block up to waitMs).
  • Returns 400 if your gas wallet can't fund the top-up — fund the address from GET /v1/gas and retry.