You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在Python中使用TON区块链v5r1版本钱包发送交易并实现批量转账(Multi-send)

如何在Python中使用TON区块链v5r1版本钱包发送交易并实现批量转账(Multi-send)

嘿,我完全理解你现在的困扰——tonsdk确实还没原生支持v5r1钱包版本,不过别担心,咱们有几种可行的办法来实现你的需求,包括批量转账和SEQNO的正确处理,下面我一步步给你讲清楚:

一、替代方案:用支持v5r1的工具或库

如果你不想手动造轮子,可以试试这些选项:

  • toncli:这是TON官方的命令行工具,完全支持v5r1钱包,包括批量转账功能。你可以在Python里用subprocess模块调用它的命令来完成操作,不用自己处理底层的签名和消息构造。
  • tonpy:这是一个更偏向底层的TON Python库,已经支持v5r1钱包的所有操作,包括批量交易的构造和发送,用法和tonsdk类似,但对新版本的支持更及时。

二、手动实现v5r1交易(基于tonsdk的工具)

如果坚持要用tonsdk的现有工具来手动实现,咱们可以利用它的密钥生成、BOC处理工具,自己构造v5r1格式的交易,步骤如下:

1. 生成密钥对和钱包地址

首先,用tonsdk生成密钥对,然后手动计算v5r1钱包的地址(因为tonsdk没内置这个版本的地址生成):

from tonsdk.crypto import mnemonic_to_wallet_key
from tonsdk.boc import Cell, Slice
from tonsdk.utils import b64_to_bytes

# 从助记词生成密钥
mnemonics = "my seed phrase here".split(" ")
pub_k, priv_k = mnemonic_to_wallet_key(mnemonics)

# v5r1钱包合约的BOC(可以从TON官方合约仓库获取)
V5R1_CODE_B64 = "这里替换成v5r1合约代码的Base64字符串"
v5r1_code_cell = Cell.one_from_boc(b64_to_bytes(V5R1_CODE_B64))

# 构造状态初始化cell,生成钱包地址
wallet_data_cell = Cell().store_bytes(pub_k)
state_init_cell = Cell()
state_init_cell.store_ref(v5r1_code_cell)
state_init_cell.store_ref(wallet_data_cell)

# 生成主网工作链0的地址
wallet_address = state_init_cell.hash().to_address(workchain=0)
print(f"v5r1钱包地址:{wallet_address.to_string()}")

2. 获取当前SEQNO

SEQNO是钱包的交易序列号,必须用最新的值才能发送成功,我们可以通过TON Center API获取:

import requests

# 替换成你的TON Center API密钥
API_KEY = "your_toncenter_api_key"
API_URL = "https://toncenter.com/api/v2"

def get_current_seqno(address):
    resp = requests.get(
        f"{API_URL}/getWalletInfo",
        params={"address": address.to_string(), "api_key": API_KEY}
    )
    resp_data = resp.json()
    return resp_data["result"]["seqno"]

seqno = get_current_seqno(wallet_address)

3. 构造批量转账消息

v5r1支持把多个内部转账消息打包成一个交易,我们需要把每个转账的目标地址、金额、备注(可选)构造进cell:

from tonsdk.utils import to_nano
import time

# 构造批量转账的消息列表
batch_transfers = [
    {
        "dest": "EQABC...",  # 第一个目标地址
        "value": to_nano(0.1, "ton"),
        "comment": "批量转账第一笔"
    },
    {
        "dest": "EQXYZ...",  # 第二个目标地址
        "value": to_nano(0.2, "ton"),
        "comment": "批量转账第二笔"
    }
]

# 构造交易的核心数据cell
expire_at = int(time.time()) + 60  # 交易1分钟内过期
msg_inner_cell = Cell()
msg_inner_cell.store_uint(seqno, 32)  # 写入SEQNO
msg_inner_cell.store_uint(expire_at, 64)  # 写入过期时间
msg_inner_cell.store_uint(len(batch_transfers), 8)  # 写入消息数量

for transfer in batch_transfers:
    # 写入内部消息标记
    msg_inner_cell.store_uint(0, 1)
    # 写入目标地址
    msg_inner_cell.store_address(transfer["dest"])
    # 写入转账金额
    msg_inner_cell.store_coins(transfer["value"])
    # 写入不需要回复的标记
    msg_inner_cell.store_uint(0, 1)
    # 写入备注(可选)
    comment_cell = Cell().store_uint(0, 32).store_string(transfer["comment"])
    msg_inner_cell.store_ref(comment_cell)

4. 签名并构造外部消息

用私钥对交易数据签名,然后打包成可以发送到TON网络的外部消息:

from tonsdk.crypto import sign
from tonsdk.utils import bytes_to_b64

# 对交易数据hash签名
signing_hash = msg_inner_cell.hash()
signature = sign(signing_hash, priv_k)

# 构造外部消息cell
external_msg_cell = Cell()
external_msg_cell.store_uint(0, 32)  # 外部消息标记
external_msg_cell.store_address(wallet_address)
external_msg_cell.store_coins(0)
external_msg_cell.store_uint(0, 1)  # 不需要回复

# 写入签名和交易数据
sign_data_cell = Cell().store_bytes(signature).store_ref(msg_inner_cell)
external_msg_cell.store_ref(sign_data_cell)

5. 发送交易到TON网络

最后把外部消息的BOC发送到TON Center API:

def send_transaction(boc_cell):
    boc_b64 = bytes_to_b64(boc_cell.to_boc(False))
    resp = requests.post(
        f"{API_URL}/sendBoc",
        params={"api_key": API_KEY},
        json={"boc": boc_b64}
    )
    return resp.json()

send_result = send_transaction(external_msg_cell)
print(f"交易发送结果:{send_result}")

三、SEQNO的正确处理要点

v5r1的SEQNO处理和之前的钱包版本逻辑一致,但有几个关键注意事项:

  • 每次交易前必须获取最新SEQNO:SEQNO是递增的,用旧值发送的交易会被合约拒绝,建议在构造交易前10秒内获取最新值。
  • 实现重试机制:如果发送失败(比如返回seqno mismatch错误),不要直接重试,先重新获取最新的SEQNO,再构造新的交易发送。
  • 避免并发发送:同一钱包同时发送多笔交易会导致SEQNO冲突,必须保证交易串行处理。

备注:内容来源于stack exchange,提问作者koolaa12

火山引擎 最新活动