From b9f87cffe7ecb53a5a21ef1ba29013fdad4e60ef Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Mon, 21 Dec 2020 09:57:22 +0100 Subject: [PATCH] Add SigningCosmosClient.sign --- CHANGELOG.md | 2 + .../launchpad/src/signingcosmosclient.spec.ts | 51 ++++++++++++++++++- packages/launchpad/src/signingcosmosclient.ts | 14 +++-- .../launchpad/types/signingcosmosclient.d.ts | 6 +++ 4 files changed, 68 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dd866eac..87fcd394 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,8 @@ - @cosmjs/launchpad: `Secp256k1HdWallet.sign` method renamed `signAmino`. - @cosmjs/launchpad: Add `CosmosClient.getTx` method for searching by ID and remove such functionality from `CosmosClient.searchTx`. +- @cosmjs/launchpad: Add `SigningCosmosClient.sign` method for signing without + broadcasting. - @cosmjs/launchpad-ledger: `LedgerSigner.sign` method renamed `signAmino`. - @cosmjs/proto-signing: Add new package for handling transaction signing with protobuf encoding. diff --git a/packages/launchpad/src/signingcosmosclient.spec.ts b/packages/launchpad/src/signingcosmosclient.spec.ts index f3a54e45..3a670d0c 100644 --- a/packages/launchpad/src/signingcosmosclient.spec.ts +++ b/packages/launchpad/src/signingcosmosclient.spec.ts @@ -4,10 +4,10 @@ import { assert } from "@cosmjs/utils"; import { Coin, coin, coins } from "./coins"; import { assertIsBroadcastTxSuccess, PrivateCosmosClient } from "./cosmosclient"; import { GasPrice } from "./gas"; -import { MsgDelegate } from "./msgs"; +import { MsgDelegate, MsgSend } from "./msgs"; import { Secp256k1HdWallet } from "./secp256k1hdwallet"; import { PrivateSigningCosmosClient, SigningCosmosClient } from "./signingcosmosclient"; -import { launchpad, makeRandomAddress, pendingWithoutLaunchpad } from "./testutils.spec"; +import { base64Matcher, launchpad, makeRandomAddress, pendingWithoutLaunchpad } from "./testutils.spec"; const httpUrl = "http://localhost:1317"; @@ -172,4 +172,51 @@ describe("SigningCosmosClient", () => { assertIsBroadcastTxSuccess(result); }); }); + + describe("sign", () => { + it("works", async () => { + pendingWithoutLaunchpad(); + const wallet = await Secp256k1HdWallet.fromMnemonic(faucet.mnemonic); + const client = new SigningCosmosClient(httpUrl, faucet.address, wallet); + + const msg1: MsgDelegate = { + type: "cosmos-sdk/MsgDelegate", + value: { + delegator_address: faucet.address, + validator_address: launchpad.validator.address, + amount: coin(1234, "ustake"), + }, + }; + const msg2: MsgSend = { + type: "cosmos-sdk/MsgSend", + value: { + from_address: faucet.address, + to_address: makeRandomAddress(), + amount: coins(1234567, "ucosm"), + }, + }; + const fee = { + amount: coins(2000, "ucosm"), + gas: "180000", // 180k + }; + const memo = "Use your power wisely"; + + const signed = await client.sign([msg1, msg2], fee, memo); + expect(signed.msg).toEqual([msg1, msg2]); + expect(signed.fee).toEqual(fee); + expect(signed.memo).toEqual(memo); + expect(signed.signatures).toEqual([ + { + pub_key: { + type: "tendermint/PubKeySecp256k1", + value: jasmine.stringMatching(base64Matcher), + }, + signature: jasmine.stringMatching(base64Matcher), + }, + ]); + + const broadcastResult = await client.broadcastTx(signed); + assertIsBroadcastTxSuccess(broadcastResult); + }); + }); }); diff --git a/packages/launchpad/src/signingcosmosclient.ts b/packages/launchpad/src/signingcosmosclient.ts index 5a1cb373..bd1a33a6 100644 --- a/packages/launchpad/src/signingcosmosclient.ts +++ b/packages/launchpad/src/signingcosmosclient.ts @@ -6,7 +6,7 @@ import { buildFeeTable, FeeTable, GasLimits, GasPrice } from "./gas"; import { BroadcastMode } from "./lcdapi"; import { Msg, MsgSend } from "./msgs"; import { OfflineSigner } from "./signer"; -import { makeStdTx } from "./tx"; +import { makeStdTx, StdTx } from "./tx"; import { StdFee } from "./types"; /** @@ -87,11 +87,19 @@ export class SigningCosmosClient extends CosmosClient { * creates a single signature, assembles the signed transaction and broadcasts it. */ public async signAndBroadcast(msgs: readonly Msg[], fee: StdFee, memo = ""): Promise { + const signedTx = await this.sign(msgs, fee, memo); + return this.broadcastTx(signedTx); + } + + /** + * Gets account number and sequence from the API, creates a sign doc, + * creates a single signature and assembles the signed transaction. + */ + public async sign(msgs: readonly Msg[], fee: StdFee, memo = ""): Promise { const { accountNumber, sequence } = await this.getSequence(); const chainId = await this.getChainId(); const signDoc = makeSignDoc(msgs, fee, chainId, memo, accountNumber, sequence); const { signed, signature } = await this.signer.signAmino(this.senderAddress, signDoc); - const signedTx = makeStdTx(signed, signature); - return this.broadcastTx(signedTx); + return makeStdTx(signed, signature); } } diff --git a/packages/launchpad/types/signingcosmosclient.d.ts b/packages/launchpad/types/signingcosmosclient.d.ts index 839ad665..36e88181 100644 --- a/packages/launchpad/types/signingcosmosclient.d.ts +++ b/packages/launchpad/types/signingcosmosclient.d.ts @@ -4,6 +4,7 @@ import { FeeTable, GasLimits, GasPrice } from "./gas"; import { BroadcastMode } from "./lcdapi"; import { Msg } from "./msgs"; import { OfflineSigner } from "./signer"; +import { StdTx } from "./tx"; import { StdFee } from "./types"; /** * These fees are used by the higher level methods of SigningCosmosClient @@ -52,4 +53,9 @@ export declare class SigningCosmosClient extends CosmosClient { * creates a single signature, assembles the signed transaction and broadcasts it. */ signAndBroadcast(msgs: readonly Msg[], fee: StdFee, memo?: string): Promise; + /** + * Gets account number and sequence from the API, creates a sign doc, + * creates a single signature and assembles the signed transaction. + */ + sign(msgs: readonly Msg[], fee: StdFee, memo?: string): Promise; }