diff --git a/CHANGELOG.md b/CHANGELOG.md index 720d38c5..6231d1ba 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,3 +13,5 @@ `OfflineSigner` instead of a `SigningCallback`. - @cosmjs/math: Add missing integer check to `Uint64.fromNumber`. Before `Uint64.fromNumber(1.1)` produced some result. +- @cosmjs/sdk38: Add `SigningCosmosClient.signAndPost` as a mid-level + abstraction between `SigningCosmosClient.sendTokens` and `.postTx`. diff --git a/packages/sdk38/src/signingcosmosclient.spec.ts b/packages/sdk38/src/signingcosmosclient.spec.ts index ac5c6e5f..f1cb66c6 100644 --- a/packages/sdk38/src/signingcosmosclient.spec.ts +++ b/packages/sdk38/src/signingcosmosclient.spec.ts @@ -1,9 +1,11 @@ +/* eslint-disable @typescript-eslint/naming-convention */ import { assert } from "@cosmjs/utils"; -import { Coin } from "./coins"; +import { Coin, coin, coins } from "./coins"; import { isPostTxFailure, PrivateCosmWasmClient } from "./cosmosclient"; +import { MsgDelegate } from "./msgs"; import { SigningCosmosClient } from "./signingcosmosclient"; -import { makeRandomAddress, pendingWithoutWasmd } from "./testutils.spec"; +import { makeRandomAddress, pendingWithoutWasmd, validatorAddress } from "./testutils.spec"; import { Secp256k1Wallet } from "./wallet"; const httpUrl = "http://localhost:1317"; @@ -76,4 +78,27 @@ describe("SigningCosmosClient", () => { expect(after.balance).toEqual(transferAmount); }); }); + + describe("signAndPost", () => { + it("works", async () => { + pendingWithoutWasmd(); + const wallet = await Secp256k1Wallet.fromMnemonic(faucet.mnemonic); + const client = new SigningCosmosClient(httpUrl, faucet.address, wallet); + + const msg: MsgDelegate = { + type: "cosmos-sdk/MsgDelegate", + value: { + delegator_address: faucet.address, + validator_address: validatorAddress, + amount: coin(1234, "ustake"), + }, + }; + const fee = { + amount: coins(2000, "ucosm"), + gas: "120000", // 120k + }; + const result = await client.signAndPost([msg], fee, "Use your power wisely"); + assert(!isPostTxFailure(result)); + }); + }); }); diff --git a/packages/sdk38/src/signingcosmosclient.ts b/packages/sdk38/src/signingcosmosclient.ts index 23f0013b..d901425a 100644 --- a/packages/sdk38/src/signingcosmosclient.ts +++ b/packages/sdk38/src/signingcosmosclient.ts @@ -3,7 +3,7 @@ import { Coin, coins } from "./coins"; import { Account, CosmosClient, GetSequenceResult, PostTxResult } from "./cosmosclient"; import { makeSignBytes } from "./encoding"; import { BroadcastMode } from "./lcdapi"; -import { MsgSend } from "./msgs"; +import { Msg, MsgSend } from "./msgs"; import { StdFee, StdTx } from "./types"; import { OfflineSigner } from "./wallet"; @@ -87,18 +87,24 @@ export class SigningCosmosClient extends CosmosClient { amount: transferAmount, }, }; - const fee = this.fees.send; + return this.signAndPost([sendMsg], this.fees.send, memo); + } + + /** + * Gets account number and sequence from the API, creates a sign doc, + * creates a single signature, assembles the signed transaction and broadcasts it. + */ + public async signAndPost(msgs: readonly Msg[], fee: StdFee, memo = ""): Promise { const { accountNumber, sequence } = await this.getSequence(); const chainId = await this.getChainId(); - const signBytes = makeSignBytes([sendMsg], fee, chainId, memo, accountNumber, sequence); + const signBytes = makeSignBytes(msgs, fee, chainId, memo, accountNumber, sequence); const signature = await this.signer.sign(this.senderAddress, signBytes); const signedTx: StdTx = { - msg: [sendMsg], + msg: msgs, fee: fee, memo: memo, signatures: [signature], }; - return this.postTx(signedTx); } } diff --git a/packages/sdk38/types/signingcosmosclient.d.ts b/packages/sdk38/types/signingcosmosclient.d.ts index 410e12db..d9947075 100644 --- a/packages/sdk38/types/signingcosmosclient.d.ts +++ b/packages/sdk38/types/signingcosmosclient.d.ts @@ -1,6 +1,7 @@ import { Coin } from "./coins"; import { Account, CosmosClient, GetSequenceResult, PostTxResult } from "./cosmosclient"; import { BroadcastMode } from "./lcdapi"; +import { Msg } from "./msgs"; import { StdFee } from "./types"; import { OfflineSigner } from "./wallet"; export interface FeeTable { @@ -35,4 +36,9 @@ export declare class SigningCosmosClient extends CosmosClient { getSequence(address?: string): Promise; getAccount(address?: string): Promise; sendTokens(recipientAddress: string, transferAmount: readonly Coin[], memo?: string): Promise; + /** + * Gets account number and sequence from the API, creates a sign doc, + * creates a single signature, assembles the signed transaction and broadcasts it. + */ + signAndPost(msgs: readonly Msg[], fee: StdFee, memo?: string): Promise; }