From 83bb1021aaa928acf2bf258c94bc82208389ba19 Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Tue, 11 Feb 2020 10:48:50 +0100 Subject: [PATCH] Add CosmWasmClient.postTx --- packages/sdk/src/cosmwasmclient.spec.ts | 54 ++++++++++++++++++++++++- packages/sdk/src/cosmwasmclient.ts | 43 ++++++++++++-------- packages/sdk/src/index.ts | 2 +- packages/sdk/types/cosmwasmclient.d.ts | 6 +++ packages/sdk/types/index.d.ts | 2 +- 5 files changed, 86 insertions(+), 21 deletions(-) diff --git a/packages/sdk/src/cosmwasmclient.spec.ts b/packages/sdk/src/cosmwasmclient.spec.ts index 9c6e0b5c..5aa92931 100644 --- a/packages/sdk/src/cosmwasmclient.spec.ts +++ b/packages/sdk/src/cosmwasmclient.spec.ts @@ -1,9 +1,10 @@ import { CosmWasmClient } from "./cosmwasmclient"; -import { encodeSecp256k1Signature } from "./encoding"; +import { encodeSecp256k1Signature, makeSignBytes, marshalTx } from "./encoding"; +import { findAttribute } from "./logs"; import { Secp256k1Pen } from "./pen"; import { RestClient } from "./restclient"; import { getRandomizedHackatom, makeRandomAddress } from "./testutils.spec"; -import { Coin } from "./types"; +import { Coin, MsgSend, StdFee } from "./types"; const httpUrl = "http://localhost:1317"; @@ -58,6 +59,55 @@ describe("CosmWasmClient", () => { }); }); + describe("postTx", () => { + it("works", async () => { + pendingWithoutCosmos(); + const pen = await Secp256k1Pen.fromMnemonic(faucet.mnemonic); + const client = CosmWasmClient.makeReadOnly(httpUrl); + + const memo = "My first contract on chain"; + const sendMsg: MsgSend = { + type: "cosmos-sdk/MsgSend", + value: { + // eslint-disable-next-line @typescript-eslint/camelcase + from_address: faucet.address, + // eslint-disable-next-line @typescript-eslint/camelcase + to_address: makeRandomAddress(), + amount: [ + { + denom: "ucosm", + amount: "1234567", + }, + ], + }, + }; + + const fee: StdFee = { + amount: [ + { + amount: "5000", + denom: "ucosm", + }, + ], + gas: "890000", + }; + + const chainId = await client.chainId(); + const { accountNumber, sequence } = await client.getNonce(faucet.address); + const signBytes = makeSignBytes([sendMsg], fee, chainId, memo, accountNumber, sequence); + const signature = encodeSecp256k1Signature(pen.pubkey, await pen.createSignature(signBytes)); + const signedTx = { + msg: [sendMsg], + fee: fee, + memo: memo, + signatures: [signature], + }; + const { logs } = await client.postTx(marshalTx(signedTx)); + const amountAttr = findAttribute(logs, "transfer", "amount"); + expect(amountAttr.value).toEqual("1234567ucosm"); + }); + }); + describe("upload", () => { it("works", async () => { pendingWithoutCosmos(); diff --git a/packages/sdk/src/cosmwasmclient.ts b/packages/sdk/src/cosmwasmclient.ts index 2e32ddea..941d341e 100644 --- a/packages/sdk/src/cosmwasmclient.ts +++ b/packages/sdk/src/cosmwasmclient.ts @@ -26,6 +26,12 @@ export interface GetNonceResult { readonly sequence: number; } +export interface PostTxResult { + readonly logs: readonly Log[]; + readonly rawLog: string; + readonly transactionHash: string; +} + export class CosmWasmClient { public static makeReadOnly(url: string): CosmWasmClient { return new CosmWasmClient(url); @@ -78,6 +84,18 @@ export class CosmWasmClient { }; } + public async postTx(tx: Uint8Array): Promise { + const result = await this.restClient.postTx(tx); + if (result.code) { + throw new Error(`Error when posting tx. Code: ${result.code}; Raw log: ${result.raw_log}`); + } + return { + logs: parseLogs(result.logs) || [], + rawLog: result.raw_log || "", + transactionHash: result.txhash, + }; + } + /** Uploads code and returns a code ID */ public async upload(wasmCode: Uint8Array, memo = ""): Promise { const storeCodeMsg: MsgStoreCode = { @@ -111,12 +129,8 @@ export class CosmWasmClient { signatures: [signature], }; - const result = await this.restClient.postTx(marshalTx(signedTx)); - if (result.code) { - throw new Error(`Error uploading contract. Code: ${result.code}; Raw log: ${result.raw_log}`); - } - const logs = parseLogs(result.logs); - const codeIdAttr = findAttribute(logs, "message", "code_id"); + const result = await this.postTx(marshalTx(signedTx)); + const codeIdAttr = findAttribute(result.logs, "message", "code_id"); const codeId = Number.parseInt(codeIdAttr.value, 10); return codeId; } @@ -160,12 +174,9 @@ export class CosmWasmClient { memo: memo, signatures: [signature], }; - const result = await this.restClient.postTx(marshalTx(signedTx)); - if (result.code) { - throw new Error(`Error instantiating contract. Code: ${result.code}; Raw log: ${result.raw_log}`); - } - const logs = parseLogs(result.logs); - const contractAddressAttr = findAttribute(logs, "message", "contract_address"); + + const result = await this.postTx(marshalTx(signedTx)); + const contractAddressAttr = findAttribute(result.logs, "message", "contract_address"); return contractAddressAttr.value; } @@ -205,12 +216,10 @@ export class CosmWasmClient { memo: memo, signatures: [signature], }; - const result = await this.restClient.postTx(marshalTx(signedTx)); - if (result.code) { - throw new Error(`Error when posting tx. Code: ${result.code}; Raw log: ${result.raw_log}`); - } + + const result = await this.postTx(marshalTx(signedTx)); return { - logs: parseLogs(result.logs), + logs: result.logs, }; } } diff --git a/packages/sdk/src/index.ts b/packages/sdk/src/index.ts index abfadd1a..b574af12 100644 --- a/packages/sdk/src/index.ts +++ b/packages/sdk/src/index.ts @@ -6,7 +6,7 @@ export { CosmosAddressBech32Prefix, encodeAddress, isValidAddress } from "./addr export { unmarshalTx } from "./decoding"; export { encodeSecp256k1Signature, makeSignBytes, marshalTx } from "./encoding"; export { RestClient, TxsResponse } from "./restclient"; -export { CosmWasmClient, GetNonceResult } from "./cosmwasmclient"; +export { CosmWasmClient, GetNonceResult, PostTxResult } from "./cosmwasmclient"; export { makeCosmoshubPath, Pen, PrehashType, Secp256k1Pen } from "./pen"; export { CosmosPubkeyBech32Prefix, diff --git a/packages/sdk/types/cosmwasmclient.d.ts b/packages/sdk/types/cosmwasmclient.d.ts index dac30039..be4c4222 100644 --- a/packages/sdk/types/cosmwasmclient.d.ts +++ b/packages/sdk/types/cosmwasmclient.d.ts @@ -7,6 +7,11 @@ export interface GetNonceResult { readonly accountNumber: number; readonly sequence: number; } +export interface PostTxResult { + readonly logs: readonly Log[]; + readonly rawLog: string; + readonly transactionHash: string; +} export declare class CosmWasmClient { static makeReadOnly(url: string): CosmWasmClient; static makeWritable(url: string, senderAddress: string, signCallback: SigningCallback): CosmWasmClient; @@ -22,6 +27,7 @@ export declare class CosmWasmClient { * @param address returns data for this address. When unset, the client's sender adddress is used. */ getNonce(address?: string): Promise; + postTx(tx: Uint8Array): Promise; /** Uploads code and returns a code ID */ upload(wasmCode: Uint8Array, memo?: string): Promise; instantiate( diff --git a/packages/sdk/types/index.d.ts b/packages/sdk/types/index.d.ts index 67cdb1c0..7e9834b8 100644 --- a/packages/sdk/types/index.d.ts +++ b/packages/sdk/types/index.d.ts @@ -5,7 +5,7 @@ export { CosmosAddressBech32Prefix, encodeAddress, isValidAddress } from "./addr export { unmarshalTx } from "./decoding"; export { encodeSecp256k1Signature, makeSignBytes, marshalTx } from "./encoding"; export { RestClient, TxsResponse } from "./restclient"; -export { CosmWasmClient, GetNonceResult } from "./cosmwasmclient"; +export { CosmWasmClient, GetNonceResult, PostTxResult } from "./cosmwasmclient"; export { makeCosmoshubPath, Pen, PrehashType, Secp256k1Pen } from "./pen"; export { CosmosPubkeyBech32Prefix,