我无法同时向多个地址发送令牌。据我所知,Cosmos 不支持批量发送,所以我必须为每个收件人做一个 tx,并确保每个 tx 的帐户序列(nonce)正确。
因此,如果我手动指定账户序列,我可以一次创建多个发送交易——但我仍然需要等待节点确认一笔交易并在发送下一笔交易之前更新账户序列。
在这种情况下可以做什么?
我无法同时向多个地址发送令牌。据我所知,Cosmos 不支持批量发送,所以我必须为每个收件人做一个 tx,并确保每个 tx 的帐户序列(nonce)正确。
因此,如果我手动指定账户序列,我可以一次创建多个发送交易——但我仍然需要等待节点确认一笔交易并在发送下一笔交易之前更新账户序列。
在这种情况下可以做什么?
Cosmos 实际上支持银行模块上的 MultiSend 操作,不幸的是,它通常不会连接到客户端以获得支持,但它被 Coinbase 等交易所广泛用于优化转账。
此后我被提醒,单个 Cosmos 交易可以包含多个消息,其中每个消息都是发送给银行模块的消息,用于将代币发送到一个帐户。这就是 Cosmos 中批量发送的工作原理。
不幸的是,这不能通过命令行获得,因此必须使用 SDK 来进行这样的交易。
这是CosmJS演示的链接,该演示在此处的 Cosmos SDK 的 v0.39.x LTS 版本上发送带有两条消息和两个签名的交易(来自Confio的提示 Ethan Frey指出了这一点)
万一链接在任何时候发生变化,这里的代码:
describe("appendSignature", () => {
it("works", async () => {
pendingWithoutLaunchpad();
const wallet0 = await Secp256k1HdWallet.fromMnemonic(faucet.mnemonic, makeCosmoshubPath(0));
const wallet1 = await Secp256k1HdWallet.fromMnemonic(faucet.mnemonic, makeCosmoshubPath(1));
const client0 = new SigningCosmosClient(launchpad.endpoint, faucet.address0, wallet0);
const client1 = new SigningCosmosClient(launchpad.endpoint, faucet.address1, wallet1);
const msg1: MsgSend = {
type: "cosmos-sdk/MsgSend",
value: {
from_address: faucet.address0,
to_address: makeRandomAddress(),
amount: coins(1234567, "ucosm"),
},
};
const msg2: MsgSend = {
type: "cosmos-sdk/MsgSend",
value: {
from_address: faucet.address1,
to_address: makeRandomAddress(),
amount: coins(1234567, "ucosm"),
},
};
const fee = {
amount: coins(2000, "ucosm"),
gas: "160000", // 2*80k
};
const memo = "This must be authorized by the two of us";
const signed = await client0.sign([msg1, msg2], fee, memo);
const cosigned = await client1.appendSignature(signed);
expect(cosigned.msg).toEqual([msg1, msg2]);
expect(cosigned.fee).toEqual(fee);
expect(cosigned.memo).toEqual(memo);
expect(cosigned.signatures).toEqual([
{
pub_key: faucet.pubkey0,
signature: jasmine.stringMatching(base64Matcher),
},
{
pub_key: faucet.pubkey1,
signature: jasmine.stringMatching(base64Matcher),
},
]);
// Ensure signed transaction is valid
const broadcastResult = await client0.broadcastTx(cosigned);
assertIsBroadcastTxSuccess(broadcastResult);
});
});
在 Golang 中做这种事情,比如使用 Cosmos SDK 客户端 CLI,你可以以distribution
模块为例:https ://github.com/cosmos/cosmos-sdk/blob/master/x/distribution/client/ cli/tx.go#L165-L180
msgs := make([]sdk.Msg, 0, len(validators))
for _, valAddr := range validators {
val, err := sdk.ValAddressFromBech32(valAddr)
if err != nil {
return err
}
msg := types.NewMsgWithdrawDelegatorReward(delAddr, val)
if err := msg.ValidateBasic(); err != nil {
return err
}
msgs = append(msgs, msg)
}
chunkSize, _ := cmd.Flags().GetInt(FlagMaxMessagesPerTx)
return newSplitAndApply(tx.GenerateOrBroadcastTxCLI, clientCtx, cmd.Flags(), msgs, chunkSize)