本文已默认阅读者有一定基础知识
Sui Gas Pool是一个服务,它支持在Sui网络上进行大规模的赞助交易。它管理一个由赞助地址拥有的gas币的数据库,并提供API来预留gas币和使用它们来支付交易费用。通过管理池中的大量gas币对象,它实现了可伸缩性和高吞吐量,因此可以同时赞助大量交易。
拉取Sui Gas Pool代码
git clone https://github.com/MystenLabs/sui-gas-pool.git
打包代码
cd sui-gas-pool
cargo build --release
./target/release/tool generate-sample-config --config-path sample.yaml
可以看到sample.yaml
文件内容,官方readme有个sidecar,太麻烦不用了,直接用内存私钥干
---
signer-config:
local:
keypair:
rpc-host-ip: 0.0.0.0
rpc-port: 9527
metrics-port: 9184
gas-pool-config:
redis:
redis_url: "redis://127.0.0.1"
fullnode-url: "https://fullnode.testnet.sui.io:443"
coin-init-config:
target-init-balance: 100000000
refresh-interval-sec: 86400
daily-gas-usage-cap: 1500000000000
参数解释:
生成keypair的方法:
首先,从钱包或者命令行获取primarykey
然后,通过tssdk,生成keypair
import { decodeSuiPrivateKey } from "@mysten/sui/cryptography"
import { toBase64 } from "@mysten/sui/utils"
const sui_key_to_gas_station = (sui_priv_key: string) => {
const { schema, secretKey } = decodeSuiPrivateKey(sui_priv_key)
const flag =
schema === 'ED25519' ? 0x00 : schema === 'Secp256k1' ? 0x01 : 0x02
return toBase64(Uint8Array.from([flag, ...secretKey]))
}
const keypair = sui_key_to_gas_station('your private key')
console.log(keypair)
最后,将生成的keypair填入sample.yaml
中
在环境变量中加上export GAS_STATION_AUTH="你的token"
即可,例如zsh就是修改~/.zshrc
文件,修改完记得source ~/.zshrc
这块就是在http请求时,需要加载header里,例如Authorization: Bearer 你的token
注意 使用一个新的钱包作为赞助钱包,这个钱包只用作赞助交易,不要进行其他操作
别忘了启动redis
redis-server
启动sui-gas-station
./target/release/sui-gas-station --config-path ./sample.yaml
pm2部署执行
pm2 start /root/sui-gas-pool/target/release/sui-gas-station -- --config-path /root/sui-gas-pool/sample.yaml
示例代码: https://github.com/klren0312/sui-gas-pool-frontend-example
三个,分别是检查服务状态,预留gas,赞助交易
我们要用的就是预留gas和赞助交易的接口,这两个接口是相关联的,在赞助交易之前,需要告诉Sui Gas Pool进行gas预留,随后使用预留gas接口返回的参数来配置赞助交易。
先看看两个接口的传参和返回值
传参:
{
"gas_budget": 1038456,
"reserve_duration_secs": 600
}
返回参数:
{
"result": {
"sponsor_address": "0x0",
"reservation_id": 2,
"gas_coins": [
{
"objectId": "0x0",
"version": 313000180,
"digest": "fff"
}
]
},
"error": null
}
setGasPayment
用的 gas币的数组传参:
{
"reservation_id": 2,
"tx_bytes": "eee",
"user_sig": "eee"
}
返回参数,关注"status": "success"
即可,其他参数自己看
{
"effects": {
"messageVersion": "v1",
"status": {
"status": "success"
},
},
"error": null
}
rpc接口有跨域问题,先在开发工具里配置接口代理
import { defineConfig } from '@farmfe/core';
export default defineConfig({
server: {
proxy: {
'/v1': {
target: 'http://localhost:9527',
changeOrigin: true,
}
}
}
});
预留gas的请求方法,入参就是gas值
const doReserveGas = (gasUsed: string) => {
const requestOptions = {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer zzespooltoken`
},
body: JSON.stringify({
'gas_budget': parseInt(gasUsed),
'reserve_duration_secs': 300
})
}
return fetch('/v1/reserve_gas', requestOptions).then((res) => res.json()).catch((error) => {
console.error(error)
return null
}) as Promise<ReserveGasResponse>
}
执行赞助交易的请求方法,入参就是上面预留gas的id、交易字节和用户签名,交易字节和用户签名可以通过useSignTransaction
的签名方法获取
const executeTx = (reservationId: number, txBytes: string, userSig: string) => {
const requestOptions = {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer zzespooltoken`
},
body: JSON.stringify({
'reservation_id': reservationId,
'tx_bytes': txBytes,
'user_sig': userSig
})
}
return fetch('/v1/execute_tx', requestOptions).then((response) => response.json()).catch((error) => {
console.error(error)
return null
}) as Promise<ExecuteTxResponse>
}
测试的合约是 0x485e975299a5d5df56967462a9e585faeb1687ed79b11704ace090b5ac84f5af
server对象是0x8443d3ada68fd36b894e9e91019f8045ca6bd1f9a8db1ec5d1681c534b54d602
先构建交易,然后通过client.devInspectTransactionBlock
预估gas值
const txb = new Transaction()
txb.moveCall({
target: `${packageId}::week_one::create_profile`,
arguments: [
txb.pure.string('test' + Date.now()),
txb.pure.string('test' + Date.now()),
txb.object(server),
],
})
const result = await client.devInspectTransactionBlock({
transactionBlock: txb,
sender: account?.address || '0x0',
})
const gasUsed = result.effects.gasUsed.storageRebate
然后将预估的gas值传入sui gas pool,获得需要的赞助交易地址,gas币数组以及预留gas的id
// 预留gas
const reserveGasRes = await doReserveGas(gasUsed)
if (reserveGasRes?.error) {
message.error('预留gas失败')
return
}
const reservationId = reserveGasRes.result.reservation_id
const gasCoins = reserveGasRes.result.gas_coins
const sponsorAddress = reserveGasRes.result.sponsor_address
然后按照文档: https://sdk.mystenlabs.com/typescript/transaction-building/sponsored-transactions
设置一些赞助交易的参数
// 设置赞助交易参数
txb.setSender(account?.address || '0x0')
txb.setGasPayment(gasCoins)
txb.setGasOwner(sponsorAddress)
对交易进行签名,签名结果的 bytes, signature 加上上面获取的gas预留id,可以传入rpc的赞助交易接口,完成赞助交易
// 签名
signTransaction(
{
transaction: txb,
},
{
onSuccess: async ({ bytes, signature }) => {
// 执行赞助交易
const executeTxRes = await executeTx(reservationId, bytes, signature).finally(() => {
setLoading(false)
})
if (executeTxRes?.error) {
messageApi.error('执行交易失败')
return
}
setTxDigest(executeTxRes.effects.transactionDigest)
messageApi.success('赞助交易成功')
},
onError: (error) => {
setLoading(false)
messageApi.error('交易签名失败' + error.message)
}
}
)
可以查看测试用户钱包:0x00c46d25eb8612f783ad2f87e700f1c042629a0d0a31a59c0226ee80aa204718,Sui 为空。
执行交易时可以看到钱包显示
执行赞助交易的digest:Q5Y1UsRTE3j3q5HV4g21LQnuG6XndzxgStAau6YwEur
可以看到gas是由赞助钱包支付
官方开源的Sui Gas Pool虽然文档写的很难用,但是毕竟自建可以更加的安全和免费使用。当然也可以使用收费的enoki(开发网和测试网有免费额度)。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。