Appearance
FAQ
Questions that come up repeatedly, from both users and engineers new to the codebase.
Product
Does Blazpay ever hold my funds?
No. Swaps and bridges are single transactions you send from your own wallet. CSIP and Autopilot put funds in a vault contract you own — the platform's executor key can trade within limits you set on-chain, but cannot withdraw to itself. Full detail in custody & trust model.
What does it cost?
0.1% of the input amount on swaps and bridges, 0.2% of the output on Autopilot trades, and an optional 0.00003 ETH per CSIP auto-claim. Nothing else. Fiat ramps and perpetuals carry the third-party provider's own fees, which the UI shows before you commit. See fees.
How many chains and providers, exactly?
The honest answer is "30+ chains, 21 live providers", and the reason it is a range is that both drift:
swap-sdk'sChainIdenum lists 38 chains.RELAYER_DEPLOYED_CHAINScurrently contains 22 — those are the ones where a swap can settle. Ethereum and Etherlink are deliberately excluded (gas cost and no bridged liquidity respectively).- 26 aggregators are implemented; the
TradeManagerconstructor comments out any whose upstream API is down. At the time of writing 21 are registered.
Authoritative sources: chains and providers.
Why can I bridge to a chain but not swap on it?
Because bridging into a chain only needs a destination address, while swapping on it needs a BlazpayRelayer deployment. A chain can be seeded in the database (Network + Token records) before its relayer exists. assertRelayerDeployed(chainId) fails fast in that case rather than sending funds to an address with no code.
Is BlazAI actually executing, or just advising?
Executing. The agent produces a structured intent; the backend turns it into a real quote and a signable transaction; the chat renders a confirmation card you sign. The one thing the LLM never does is originate a trade on its own — every parameter it extracts is re-resolved against real chain and token data server-side first.
Why did BlazAI move to its own domain?
A product decision on 2026-07-26: defi.blazpay.com becomes trading-only, ai.blazpay.com owns the whole conversational product, and blazpay.com is the brand hub. The split is by product, not by interface — so the per-chain SEO pages stay on defi, because they carry trading intent. See domains.
Which products are not finished?
Liquidity (pools UI exists, launch pending), lend/borrow (not started), and copy trading (the engine exists in a separate repo and needs productising). Autopilot is code-complete and deployed to mainnet but has open items before promotion to users — see the status matrix.
Engineering
Which repo owns what?
Four repos, all siblings in defi-set. bz-agent classifies intent. bz-backend does everything server-side, including the entire ecosystem layer. defi-dex is both frontends. swap-sdk is the aggregation engine, consumed by the backend and the frontend. See repositories.
Why is swap-sdk a git dependency rather than an npm package?
It is published as github:blazpay/swap-sdk#vX.Y.Z and consumed by both bz-backend and defi-dex.
Bumping the pin in package.json is not enough
package-lock.json pins swap-sdk by resolved commit, and npm install obeys the lock even after rm -rf node_modules/swap-sdk. You must also run npm install github:blazpay/swap-sdk#vX.Y.Z --package-lock-only and commit both files. This has burned a production deploy — it installed 1.9.1 despite a v1.12.0 pin. See swap-sdk releases.
Why does the same quote need two round-trips?
Because provider APIs separate quoting from transaction building, and the raw provider response is far too large to ship to the browser. GET /defi/quotes streams small meta objects over SSE and caches the full { data, meta, restProps } in Redis under meta.id for five minutes. GET /defi/swap/:id rehydrates that and calls the provider's build endpoint. See quote → settle pipeline.
Why does the backend sign the meta-transaction instead of the user?
The signature attests to the route, not the spend. Without it, anyone could use BlazpayRelayer as a generic call-forwarder. The user's authority comes from being msg.sender — funds are pulled from them by transferFrom, and they pay the gas. Both signatures are required. See custody.
Why do some providers need a backend proxy and others do not?
Only the ones requiring a secret: 1inch, OpenOcean, Unizen, Squid, OKX, Uniswap, ChangeNow, Changelly and the fiat ramps use an API key or a registered referrer that must not ship in a browser bundle. LiFi, Butter, KyberSwap, Symbiosis, Across, Relay, deBridge, Rango, XY Finance and others are called directly. See provider proxies.
What is the difference between routes/ and v1/routes/ in the backend?
routes/ is the original API surface, mounted at /api. v1/routes/ is a newer, cleaner surface mounted at /api/v1 and holds BlazAI, the dApp builder, audit, safety, wallet cards, training data, feedback and notifications. Both are live. New AI-adjacent work goes in v1.
Why is defi-dex 7+ MB?
Because the AI shell genuinely needs the trading core — every chat action that quotes, signs or executes pulls in the same wallet, ethers and aggregator code the trading app uses. A separate repo would not help. Marketing pages avoid the cost through a dual-entry code split: src/index.tsx is a 3 KB dispatcher that dynamic-imports a light MarketingApp tree (~234 KB) for marketing routes and the full app for everything else. See frontend architecture.
npx tsc --noEmit shows thousands of errors. Is the build broken?
No. There are roughly 3,300 pre-existing errors originating in node_modules type definitions. vite build is the real gate. Do not try to get tsc --noEmit to zero as part of an unrelated change.
Why do CSIP orders run at the wrong cadence if I am not careful?
Because the contract's interval field is the total window in seconds, not the gap between orders, and frequency is the order count. Next-due is depositTime + (interval × processed / frequency). The CSIP form must therefore send duration = perOrderGap × orders. Sending the gap as the total window makes buys run orders× too fast — a bug that shipped once. See DCA contract.
Why does an Autopilot agent never trade?
Most likely the router allow-list is empty on that chain. The vault is fail-safe: setRouters([...], true) must be called by the owner before any trade can execute. Run contract-deployment/scripts/probe-autopilot-routers.cjs to find which aggregator routers actually deliver in-transaction output on that chain, then allow-list those. This is the current state on Robinhood Chain.
Why do some providers get rejected during route probing?
Solver- and intent-based providers (Relay, Nordstern) do not deliver output inside the transaction — they fill asynchronously. The vault's minimum-output check correctly reverts on them. Route probing simulates each candidate with estimateGas before selection so those get filtered out rather than wasting a real transaction. See execution engine.
Where do I add a new AI capability?
Nine files across three repos, in order. There is a checklist: add an AI intent.
How do I make a token show up in the picker?
Token visibility is driven by the order field on the Token model, and the frontend slices the top 200. "USDT is missing on chain X" is almost always a ranking problem, not a missing record. scripts/curate-token-order.js fixes it by ranking canonical majors. See token curation.
Which branch deploys where?
| Target | Branch | Trigger |
|---|---|---|
bz-backend on the GCP VM | bishtNew | ./scripts/deploy.gcp.sh deploy bz-backend |
bz-agent on the GCP VM | main | ./scripts/deploy.gcp.sh deploy bz-agent |
defi-dex on Netlify | optimized | Push (auto-build) |
defi-dex's main is roughly 80 commits behind and effectively stale. See deployment.
The backend deploy is rsync mode, not git mode
deploy.gcp.sh checks whether the VM's app directory is a git repo. bz-backend on the VM is not, so it uses rsync — which copies your entire local working tree (excluding only .git/, node_modules/, .env, dist/, build/, logs/, *.log, and without --delete). Uncommitted local work goes to production too. See deploy backend.
Do I need to commit a Co-Authored-By trailer?
No. Do not add a Co-Authored-By: or AI-generated trailer to commits in this project.