Sui Gas Pool放弃到入门

本文已默认阅读者有一定基础知识

一、介绍

Sui Gas Pool是一个服务,它支持在Sui网络上进行大规模的赞助交易。它管理一个由赞助地址拥有的gas币的数据库,并提供API来预留gas币和使用它们来支付交易费用。通过管理池中的大量gas币对象,它实现了可伸缩性和高吞吐量,因此可以同时赞助大量交易。

二、安装与启动Sui Gas Pool服务

1. 环境配置

1)安装Rust和Redis环境

2)编译Sui Gas Pool

拉取Sui Gas Pool代码

git clone https://github.com/MystenLabs/sui-gas-pool.git

打包代码

cd sui-gas-pool
cargo build --release

3)生成与修改配置文件

./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: 用钱包私钥可以转,下面会给方法
  • rpc-host-ip: gas pool的rpc服务ip, 通常就是 0.0.0.0
  • rpc-port: rpc服务端口
  • metrics-port: 监控服务可以访问并获取指标数据和日志记录的端口
  • redis_url: redis服务地址
  • fullnode-url: gas pool所处sui环境的rpc地址
  • coin-init-config
    • target-init-balance: 每个gas的初始余额可以给 100000000
      也就是 0.1 SUI, gas pool 会在初始化的时候把赞助钱包的币按照这个进行分割


      image.png
    • refresh-interval-sec: 定时查看赞助钱包的所有gas币,看看是否有新增

  • daily-gas-usage-cap: 每天允许使用的gas总量,作为安全上限

生成keypair的方法:
首先,从钱包或者命令行获取primarykey

image.png

然后,通过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

4)配置rpc的鉴权token

在环境变量中加上export GAS_STATION_AUTH="你的token"即可,例如zsh就是修改~/.zshrc文件,修改完记得source ~/.zshrc

这块就是在http请求时,需要加载header里,例如Authorization: Bearer 你的token

2. 启动Sui Gas Pool

注意 使用一个新的钱包作为赞助钱包,这个钱包只用作赞助交易,不要进行其他操作

别忘了启动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
image.png

三、前端调用

示例代码: https://github.com/klren0312/sui-gas-pool-frontend-example

1. Sui Gas Pool 提供的 rpc 接口

三个,分别是检查服务状态,预留gas,赞助交易


image.png

我们要用的就是预留gas和赞助交易的接口,这两个接口是相关联的,在赞助交易之前,需要告诉Sui Gas Pool进行gas预留,随后使用预留gas接口返回的参数来配置赞助交易。

先看看两个接口的传参和返回值

1)预留gas接口(/v1/reserve_gas)

传参:

{
    "gas_budget": 1038456,
    "reserve_duration_secs": 600
}
  • gas_budget gas值
  • reserve_duration_secs 失效时间,最高600秒

返回参数:

{
    "result": {
        "sponsor_address": "0x0",
        "reservation_id": 2,
        "gas_coins": [
            {
                "objectId": "0x0",
                "version": 313000180,
                "digest": "fff"
            }
        ]
    },
    "error": null
}
  • sponsor_address 赞助交易的钱包地址
  • reservation_id 预留gas的id
  • gas_coins 用来给 setGasPayment 用的 gas币的数组

2)赞助交易接口(/v1/execute_tx)

传参:

{
    "reservation_id": 2,
    "tx_bytes": "eee",
    "user_sig": "eee"
}
  • reservation_id 上面预留gas的id
  • tx_bytes 交易字节
  • user_sig 用户签名

返回参数,关注"status": "success"即可,其他参数自己看

{
    "effects": {
        "messageVersion": "v1",
        "status": {
            "status": "success"
        },
    },
    "error": null
}

2. 实战

1)配代理

rpc接口有跨域问题,先在开发工具里配置接口代理

import { defineConfig } from '@farmfe/core';
export default defineConfig({
  server: {
    proxy: {
      '/v1': {
        target: 'http://localhost:9527',
        changeOrigin: true,
      }
    }
  }
});

2)封装两个请求方法

预留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>
  }

3)编写交易(测试网运行)

测试的合约是 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)
    }
  }
)

4)结果展示

可以查看测试用户钱包:0x00c46d25eb8612f783ad2f87e700f1c042629a0d0a31a59c0226ee80aa204718,Sui 为空。

image.png

执行交易时可以看到钱包显示


image.png

执行赞助交易的digest:Q5Y1UsRTE3j3q5HV4g21LQnuG6XndzxgStAau6YwEur
可以看到gas是由赞助钱包支付

image.png

四、总结

官方开源的Sui Gas Pool虽然文档写的很难用,但是毕竟自建可以更加的安全和免费使用。当然也可以使用收费的enoki(开发网和测试网有免费额度)。

image.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容