Skip to Content
Zh CnDocs
交易 API
Nogas 功能

Nogas 功能

什么是 Nogas?

当用户没有主链币(如 ETH、BNB、SOL)支付 gas 费时,Bitget Wallet 可以代替用户发起交易并支付 gas 费用,然后从用户的交易 token 中扣除一部分作为抵扣费用。

这使得用户仅使用稳定币即可完成 swap 交易,无需持有任何主链币余额。


Nogas 实现原理

EVM 链

EVM 链上的 Nogas 利用 EIP-7702 能力实现:

  1. Bitget Wallet 通过 SetCode 交易向用户地址挂载合约代码,将用户的 EOA(外部拥有账户)升级为具有智能合约功能的地址。
  2. 然后使用内部地址发起对用户升级后 EOA 地址的合约调用交易。
  3. 用户只需签署一条 EIP-712 类型化数据消息,无需签署链上交易。

Solana 链

Solana 链上的实现更为简单:

  • Bitget Wallet 将内部地址设置为 feePayer,代替用户支付 gas 费用。
  • 返回的交易数据格式与普通模式相同,用户正常签署交易即可。

如何使用 Nogas

Nogas 目前仅在**订单模式(Order Mode)**下可用。启用步骤:

  1. 调用 getSwapPrice 接口,检查响应中的 features 数组是否包含 "no_gas"
  2. 调用 makeSwapOrder 接口时,将 feature 参数设置为 "no_gas"

响应差异

Solana 链:响应与普通模式完全相同,返回 txs 数组。

EVM 链:响应中包含 signatures 数组,取代普通模式的 txs 数组。每个签名项包含:

字段类型说明
kindstring固定为 "signature"
chainNamestring链名称
chainIdstring链标识
hashstringEIP-712 类型化数据的 hash 值,使用 eth_sign 签名此值
dataobjectEIP-712 结构化数据,用于展示
data.signTypestring固定为 "eip712"
data.typesobjectEIP-712 类型定义
data.domainobjectEIP-712 域分隔符
data.messageobjectEIP-712 消息内容

签名与提交(EVM)

  1. signatures 数组的每个项中提取 hash 字段。
  2. 使用 eth_sign 对 hash 进行签名(原始 hash 签名,非 personal_sign)。
  3. 通过 submitSwapOrder 接口提交签名数据,放入 signedTxs 数组中。

使用限制

条件要求
支持的 token仅限稳定币(USDT、USDC 等)
最低订单价值≥ 5 USD(Morph 链为 1 USD)
可用模式仅订单模式

完整的各链最低订单金额请参阅订单模式文档中的支持链列表


EVM Nogas 示例(Node.js)

以下示例演示了 EVM 链上完整的 Nogas 流程:创建订单、签名 EIP-712 hash、提交签名数据。

const { ethers } = require("ethers"); const API_HOST = "https://bopenapi.bgwapi.io"; const PARTNER_CODE = "your_partner_code"; const PRIVATE_KEY = "0xYourPrivateKeyHere"; const wallet = new ethers.Wallet(PRIVATE_KEY); async function apiPost(path, body) { const res = await fetch(`${API_HOST}${path}`, { method: "POST", headers: { "Content-Type": "application/json", "Partner-Code": PARTNER_CODE, }, body: JSON.stringify(body), }); return res.json(); } // Step 1: 查询价格并检查 nogas 可用性 async function getQuote() { const res = await apiPost("/bgw-pro/swapx/order/getSwapPrice", { fromChain: "bnb", fromContract: "0x55d398326f99059ff775485246999027b3197955", // USDT fromAmount: "10", toChain: "bnb", toContract: "0x8ac76a51cc950d9822d68b83fe1ad97b32cd580d", // USDC fromAddress: wallet.address, }); if (res.status !== 0) throw new Error(`Quote failed: ${res.msg}`); const supportsNogas = res.data.features?.includes("no_gas"); console.log("Supports nogas:", supportsNogas); console.log("Market:", res.data.market); return res.data; } // Step 2: 创建 nogas 订单 async function createOrder(market) { const res = await apiPost("/bgw-pro/swapx/order/makeSwapOrder", { fromChain: "bnb", fromContract: "0x55d398326f99059ff775485246999027b3197955", fromAmount: "10", toChain: "bnb", toContract: "0x8ac76a51cc950d9822d68b83fe1ad97b32cd580d", fromAddress: wallet.address, toAddress: wallet.address, market, slippage: "3", feature: "no_gas", }); if (res.status !== 0) throw new Error(`Create order failed: ${res.msg}`); console.log("Order ID:", res.data.orderId); console.log("Response contains 'signatures':", !!res.data.signatures); return res.data; } // Step 3: 签名 EIP-712 hash async function signHash(orderData) { const signedTxs = []; for (const item of orderData.signatures) { const hash = item.hash; // 直接签名原始 hash 字节(非 personal_sign) const signature = wallet.signingKey.sign(hash).serialized; signedTxs.push(signature); } console.log("Signed transactions:", signedTxs); return signedTxs; } // Step 4: 提交签名后的订单 async function submitOrder(orderId, signedTxs) { const res = await apiPost("/bgw-pro/swapx/order/submitSwapOrder", { orderId, signedTxs, }); if (res.status !== 0) throw new Error(`Submit failed: ${res.msg}`); console.log("Order submitted successfully:", res.data.orderId); return res.data; } // Step 5: 轮询订单状态 async function pollOrderStatus(orderId) { while (true) { const res = await apiPost("/bgw-pro/swapx/order/getSwapOrder", { orderId }); if (res.status !== 0) throw new Error(`Query failed: ${res.msg}`); const status = res.data.status; console.log(`Order ${orderId} status: ${status}`); if (["success", "failed", "refunded"].includes(status)) { return res.data; } await new Promise((r) => setTimeout(r, 3000)); } } // 主流程 async function main() { const quote = await getQuote(); const orderData = await createOrder(quote.market); const signedTxs = await signHash(orderData); await submitOrder(orderData.orderId, signedTxs); await pollOrderStatus(orderData.orderId); } main().catch(console.error);

makeSwapOrder 响应示例(EVM Nogas)

{ "status": 0, "error_code": 0, "data": { "orderId": "316de20899804b75a4e88f9bfd8468f3", "signatures": [ { "kind": "signature", "chainName": "bnb", "chainId": "56", "hash": "0xa8c2faaf03806e3172cad40bed94e60d16a0e598747474f52ab7e0856f963f6f", "data": { "signType": "eip712", "types": { "Aggregator": [ { "name": "chainId", "type": "uint256" }, { "name": "msgSender", "type": "address" }, { "name": "deadline", "type": "uint256" }, { "name": "nonce", "type": "uint256" }, { "name": "adminContract", "type": "address" }, { "name": "calls", "type": "Call[]" } ], "Call": [ { "name": "target", "type": "address" }, { "name": "value", "type": "uint256" }, { "name": "callData", "type": "bytes" } ], "EIP712Domain": [ { "name": "name", "type": "string" }, { "name": "version", "type": "string" }, { "name": "chainId", "type": "uint256" }, { "name": "verifyingContract", "type": "address" } ] }, "primaryType": "Aggregator", "domain": { "chainId": "56", "name": "BW7702Admin", "verifyingContract": "0x8C80e4d123e1A9E787B74a150D3220Dabf327707", "version": "1" }, "message": { "adminContract": "0x8C80e4d123e1A9E787B74a150D3220Dabf327707", "calls": [ { "callData": "0xd984396a...", "target": "0xBc1D9760bd6ca468CA9fB5Ff2CFbEAC35d86c973", "value": "0" } ], "chainId": "56", "deadline": "1775121855", "msgSender": "0xe51346fbf6D8c3833cD28b3e49611B3f972b9276", "nonce": "5775121735994317608" } } } ], "toMinAmount": "9.416319243764614284" }, "msg": "success" }

submitSwapOrder 请求示例

{ "orderId": "316de20899804b75a4e88f9bfd8468f3", "signedTxs": [ "0x8f68bad504ca45f299b1843f736c069ee1e636fe50f5bef764ead661deddd4647dcf0ff2d83d69533ffe88568c514a47c59989e0c794138473a27da5feb9a7f41c" ] }
Last updated on