From 01758aadb293e6fec8442bed4e622519ea235d00 Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Mon, 2 Mar 2020 13:24:28 +0100 Subject: [PATCH 01/10] Standardize ExecuteResult, InstantiateResult, UploadResult --- packages/sdk/src/cosmwasmclient.spec.ts | 4 +-- packages/sdk/src/index.ts | 5 ++-- .../sdk/src/signingcosmwasmclient.spec.ts | 4 +-- packages/sdk/src/signingcosmwasmclient.ts | 25 ++++++++++++++++--- packages/sdk/types/index.d.ts | 5 ++-- packages/sdk/types/signingcosmwasmclient.d.ts | 16 +++++++++--- scripts/wasmd/deploy_erc20.js | 2 +- scripts/wasmd/deploy_nameservice.js | 2 +- 8 files changed, 46 insertions(+), 17 deletions(-) diff --git a/packages/sdk/src/cosmwasmclient.spec.ts b/packages/sdk/src/cosmwasmclient.spec.ts index 773816a3..1953b3c2 100644 --- a/packages/sdk/src/cosmwasmclient.spec.ts +++ b/packages/sdk/src/cosmwasmclient.spec.ts @@ -313,7 +313,7 @@ describe("CosmWasmClient", () => { ); const { codeId } = await client.upload(getRandomizedHackatom()); const initMsg = { verifier: makeRandomAddress(), beneficiary: makeRandomAddress() }; - const contractAddress = await client.instantiate(codeId, initMsg, "random hackatom"); + const { contractAddress } = await client.instantiate(codeId, initMsg, "random hackatom"); contract = { initMsg: initMsg, address: contractAddress }; } }); @@ -366,7 +366,7 @@ describe("CosmWasmClient", () => { ); const { codeId } = await client.upload(getRandomizedHackatom()); const initMsg = { verifier: makeRandomAddress(), beneficiary: makeRandomAddress() }; - const contractAddress = await client.instantiate(codeId, initMsg, "a different hackatom"); + const { contractAddress } = await client.instantiate(codeId, initMsg, "a different hackatom"); contract = { initMsg: initMsg, address: contractAddress }; } }); diff --git a/packages/sdk/src/index.ts b/packages/sdk/src/index.ts index 425cad66..d6d5d2ef 100644 --- a/packages/sdk/src/index.ts +++ b/packages/sdk/src/index.ts @@ -29,9 +29,10 @@ export { export { findSequenceForSignedTx } from "./sequence"; export { encodeSecp256k1Signature, decodeSignature } from "./signature"; export { + ExecuteResult, + InstantiateResult, SigningCallback, SigningCosmWasmClient, - ExecuteResult, UploadMeta, - UploadReceipt, + UploadResult, } from "./signingcosmwasmclient"; diff --git a/packages/sdk/src/signingcosmwasmclient.spec.ts b/packages/sdk/src/signingcosmwasmclient.spec.ts index 56cb6171..096008d0 100644 --- a/packages/sdk/src/signingcosmwasmclient.spec.ts +++ b/packages/sdk/src/signingcosmwasmclient.spec.ts @@ -87,7 +87,7 @@ describe("SigningCosmWasmClient", () => { }, ]; const beneficiaryAddress = makeRandomAddress(); - const contractAddress = await client.instantiate( + const { contractAddress } = await client.instantiate( codeId, { verifier: faucet.address, @@ -148,7 +148,7 @@ describe("SigningCosmWasmClient", () => { }, ]; const beneficiaryAddress = makeRandomAddress(); - const contractAddress = await client.instantiate( + const { contractAddress } = await client.instantiate( codeId, { verifier: faucet.address, diff --git a/packages/sdk/src/signingcosmwasmclient.ts b/packages/sdk/src/signingcosmwasmclient.ts index 8a2616a5..67d38752 100644 --- a/packages/sdk/src/signingcosmwasmclient.ts +++ b/packages/sdk/src/signingcosmwasmclient.ts @@ -68,7 +68,7 @@ export interface UploadMeta { readonly builder?: string; } -export interface UploadReceipt { +export interface UploadResult { /** Size of the original wasm code in bytes */ readonly originalSize: number; /** A hex encoded sha256 checksum of the original wasm code (that is stored on chain) */ @@ -79,6 +79,17 @@ export interface UploadReceipt { readonly compressedChecksum: string; /** The ID of the code asigned by the chain */ readonly codeId: number; + readonly logs: readonly Log[]; + /** Transaction hash (might be used as transaction ID). Guaranteed to be non-empty upper-case hex */ + readonly transactionHash: string; +} + +export interface InstantiateResult { + /** The address of the newly instantiated contract */ + readonly contractAddress: string; + readonly logs: readonly Log[]; + /** Transaction hash (might be used as transaction ID). Guaranteed to be non-empty upper-case hex */ + readonly transactionHash: string; } export interface ExecuteResult { @@ -115,7 +126,7 @@ export class SigningCosmWasmClient extends CosmWasmClient { } /** Uploads code and returns a receipt, including the code ID */ - public async upload(wasmCode: Uint8Array, meta: UploadMeta = {}, memo = ""): Promise { + public async upload(wasmCode: Uint8Array, meta: UploadMeta = {}, memo = ""): Promise { const source = meta.source || ""; const builder = prepareBuilder(meta.builder); @@ -150,6 +161,8 @@ export class SigningCosmWasmClient extends CosmWasmClient { compressedSize: compressed.length, compressedChecksum: Encoding.toHex(new Sha256(compressed).digest()), codeId: Number.parseInt(codeIdAttr.value, 10), + logs: result.logs, + transactionHash: result.transactionHash, }; } @@ -159,7 +172,7 @@ export class SigningCosmWasmClient extends CosmWasmClient { label: string, memo = "", transferAmount?: readonly Coin[], - ): Promise { + ): Promise { const instantiateMsg: MsgInstantiateContract = { type: "wasm/instantiate", value: { @@ -188,7 +201,11 @@ export class SigningCosmWasmClient extends CosmWasmClient { const result = await this.postTx(signedTx); const contractAddressAttr = findAttribute(result.logs, "message", "contract_address"); - return contractAddressAttr.value; + return { + contractAddress: contractAddressAttr.value, + logs: result.logs, + transactionHash: result.transactionHash, + }; } public async execute( diff --git a/packages/sdk/types/index.d.ts b/packages/sdk/types/index.d.ts index b1cd5985..a96ec335 100644 --- a/packages/sdk/types/index.d.ts +++ b/packages/sdk/types/index.d.ts @@ -28,9 +28,10 @@ export { export { findSequenceForSignedTx } from "./sequence"; export { encodeSecp256k1Signature, decodeSignature } from "./signature"; export { + ExecuteResult, + InstantiateResult, SigningCallback, SigningCosmWasmClient, - ExecuteResult, UploadMeta, - UploadReceipt, + UploadResult, } from "./signingcosmwasmclient"; diff --git a/packages/sdk/types/signingcosmwasmclient.d.ts b/packages/sdk/types/signingcosmwasmclient.d.ts index 318a387a..8b169172 100644 --- a/packages/sdk/types/signingcosmwasmclient.d.ts +++ b/packages/sdk/types/signingcosmwasmclient.d.ts @@ -17,7 +17,7 @@ export interface UploadMeta { /** The builder tag */ readonly builder?: string; } -export interface UploadReceipt { +export interface UploadResult { /** Size of the original wasm code in bytes */ readonly originalSize: number; /** A hex encoded sha256 checksum of the original wasm code (that is stored on chain) */ @@ -28,6 +28,16 @@ export interface UploadReceipt { readonly compressedChecksum: string; /** The ID of the code asigned by the chain */ readonly codeId: number; + readonly logs: readonly Log[]; + /** Transaction hash (might be used as transaction ID). Guaranteed to be non-empty upper-case hex */ + readonly transactionHash: string; +} +export interface InstantiateResult { + /** The address of the newly instantiated contract */ + readonly contractAddress: string; + readonly logs: readonly Log[]; + /** Transaction hash (might be used as transaction ID). Guaranteed to be non-empty upper-case hex */ + readonly transactionHash: string; } export interface ExecuteResult { readonly logs: readonly Log[]; @@ -48,14 +58,14 @@ export declare class SigningCosmWasmClient extends CosmWasmClient { getNonce(address?: string): Promise; getAccount(address?: string): Promise; /** Uploads code and returns a receipt, including the code ID */ - upload(wasmCode: Uint8Array, meta?: UploadMeta, memo?: string): Promise; + upload(wasmCode: Uint8Array, meta?: UploadMeta, memo?: string): Promise; instantiate( codeId: number, initMsg: object, label: string, memo?: string, transferAmount?: readonly Coin[], - ): Promise; + ): Promise; execute( contractAddress: string, handleMsg: object, diff --git a/scripts/wasmd/deploy_erc20.js b/scripts/wasmd/deploy_erc20.js index 63af5032..0e513945 100755 --- a/scripts/wasmd/deploy_erc20.js +++ b/scripts/wasmd/deploy_erc20.js @@ -82,7 +82,7 @@ async function main() { for (const initMsg of [initMsgHash, initMsgIsa, initMsgJade]) { const memo = `Create an ERC20 instance for ${initMsg.symbol}`; - const contractAddress = await client.instantiate(uploadReceipt.codeId, initMsg, initMsg.symbol, memo); + const { contractAddress } = await client.instantiate(uploadReceipt.codeId, initMsg, initMsg.symbol, memo); console.info(`Contract instantiated for ${initMsg.symbol} at ${contractAddress}`); } } diff --git a/scripts/wasmd/deploy_nameservice.js b/scripts/wasmd/deploy_nameservice.js index 9b689420..e835d4e4 100755 --- a/scripts/wasmd/deploy_nameservice.js +++ b/scripts/wasmd/deploy_nameservice.js @@ -45,7 +45,7 @@ async function main() { for (const { label, initMsg } of [free, luxury]) { const memo = `Create an nameservice instance "${label}"`; - const contractAddress = await client.instantiate(uploadReceipt.codeId, initMsg, label, memo); + const { contractAddress } = await client.instantiate(uploadReceipt.codeId, initMsg, label, memo); console.info(`Contract "${label}" instantiated at ${contractAddress}`); } } From 5bf3a191b3b0faa7a8f888eaa98756a0e79129be Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Mon, 2 Mar 2020 13:46:35 +0100 Subject: [PATCH 02/10] Create higher level IndexedTx --- packages/bcp/src/cosmwasmconnection.ts | 28 ++++++------- packages/bcp/src/decode.spec.ts | 20 +++++---- packages/bcp/src/decode.ts | 24 +++++------ packages/bcp/types/decode.d.ts | 6 +-- .../sdk/src/cosmwasmclient.searchtx.spec.ts | 38 ++++++++--------- packages/sdk/src/cosmwasmclient.ts | 42 ++++++++++++++----- packages/sdk/src/index.ts | 1 + packages/sdk/types/cosmwasmclient.d.ts | 17 +++++++- packages/sdk/types/index.d.ts | 1 + 9 files changed, 106 insertions(+), 71 deletions(-) diff --git a/packages/bcp/src/cosmwasmconnection.ts b/packages/bcp/src/cosmwasmconnection.ts index 648ea7a0..54d039b2 100644 --- a/packages/bcp/src/cosmwasmconnection.ts +++ b/packages/bcp/src/cosmwasmconnection.ts @@ -1,5 +1,4 @@ -/* eslint-disable @typescript-eslint/camelcase */ -import { CosmWasmClient, findSequenceForSignedTx, SearchTxFilter, TxsResponse, types } from "@cosmwasm/sdk"; +import { CosmWasmClient, findSequenceForSignedTx, IndexedTx, SearchTxFilter, types } from "@cosmwasm/sdk"; import { Account, AccountQuery, @@ -71,11 +70,11 @@ function deduplicate(input: ReadonlyArray, comparator: (a: T, b: T) => num } /** Compares transaxtion by height. If the height is equal, compare by hash to ensure deterministic order */ -function compareByHeightAndHash(a: TxsResponse, b: TxsResponse): number { +function compareByHeightAndHash(a: IndexedTx, b: IndexedTx): number { if (a.height === b.height) { - return a.txhash.localeCompare(b.txhash); + return a.hash.localeCompare(b.hash); } else { - return parseInt(a.height, 10) - parseInt(b.height, 10); + return a.height - b.height; } } @@ -248,9 +247,10 @@ export class CosmWasmConnection implements BlockchainConnection { } public async getBlockHeader(height: number): Promise { - const { block_id, block } = await this.cosmWasmClient.getBlock(height); + // eslint-disable-next-line @typescript-eslint/camelcase + const { block_id: blockId, block } = await this.cosmWasmClient.getBlock(height); return { - id: block_id.hash as BlockId, + id: blockId.hash as BlockId, height: parseInt(block.header.height, 10), time: new ReadonlyDate(block.header.time), transactionCount: block.data.txs?.length || 0, @@ -337,13 +337,13 @@ export class CosmWasmConnection implements BlockchainConnection { const filter: SearchTxFilter = { minHeight: minHeight, maxHeight: maxHeight }; - let txs: readonly TxsResponse[]; + let txs: readonly IndexedTx[]; if (id) { txs = await this.cosmWasmClient.searchTx({ id: id }, filter); } else if (height) { txs = await this.cosmWasmClient.searchTx({ height: height }, filter); } else if (sentFromOrTo) { - const pendingRequests = new Array>(); + const pendingRequests = new Array>(); pendingRequests.push(this.cosmWasmClient.searchTx({ sentFromOrTo: sentFromOrTo }, filter)); for (const contract of this.erc20Tokens.map(token => token.contractAddress)) { const searchBySender = [ @@ -371,7 +371,7 @@ export class CosmWasmConnection implements BlockchainConnection { } const responses = await Promise.all(pendingRequests); const allResults = responses.reduce((accumulator, results) => accumulator.concat(results), []); - txs = deduplicate(allResults, (a, b) => a.txhash.localeCompare(b.txhash)).sort(compareByHeightAndHash); + txs = deduplicate(allResults, (a, b) => a.hash.localeCompare(b.hash)).sort(compareByHeightAndHash); } else { throw new Error("Unsupported query"); } @@ -460,11 +460,11 @@ export class CosmWasmConnection implements BlockchainConnection { } private parseAndPopulateTxResponseUnsigned( - response: TxsResponse, + response: IndexedTx, ): ConfirmedTransaction | FailedTransaction { return parseTxsResponseUnsigned( this.chainId, - parseInt(response.height, 10), + response.height, response, this.bankTokens, this.erc20Tokens, @@ -472,7 +472,7 @@ export class CosmWasmConnection implements BlockchainConnection { } private async parseAndPopulateTxResponseSigned( - response: TxsResponse, + response: IndexedTx, ): Promise | FailedTransaction> { const firstMsg = response.tx.value.msg.find(() => true); if (!firstMsg) throw new Error("Got transaction without a first message. What is going on here?"); @@ -503,7 +503,7 @@ export class CosmWasmConnection implements BlockchainConnection { return parseTxsResponseSigned( this.chainId, - parseInt(response.height, 10), + response.height, nonce, response, this.bankTokens, diff --git a/packages/bcp/src/decode.spec.ts b/packages/bcp/src/decode.spec.ts index 49e5df0d..7ec8c142 100644 --- a/packages/bcp/src/decode.spec.ts +++ b/packages/bcp/src/decode.spec.ts @@ -1,5 +1,5 @@ /* eslint-disable @typescript-eslint/camelcase */ -import { types } from "@cosmwasm/sdk"; +import { IndexedTx, types } from "@cosmwasm/sdk"; import { Address, Algorithm, isSendTransaction, SendTransaction, TokenTicker } from "@iov/bcp"; import { Encoding } from "@iov/encoding"; import { assert } from "@iov/utils"; @@ -281,10 +281,11 @@ describe("decode", () => { describe("parseTxsResponseUnsigned", () => { it("works", () => { const currentHeight = 2923; - const txsResponse = { - height: "2823", - txhash: testdata.txId, - raw_log: '[{"msg_index":0,"success":true,"log":""}]', + const txsResponse: IndexedTx = { + height: 2823, + hash: testdata.txId, + rawLog: '[{"msg_index":0,"success":true,"log":""}]', + logs: [], tx: cosmoshub.tx, timestamp: "2020-02-14T11:35:41Z", }; @@ -310,10 +311,11 @@ describe("decode", () => { describe("parseTxsResponseSigned", () => { it("works", () => { const currentHeight = 2923; - const txsResponse = { - height: "2823", - txhash: testdata.txId, - raw_log: '[{"msg_index":0,"success":true,"log":""}]', + const txsResponse: IndexedTx = { + height: 2823, + hash: testdata.txId, + rawLog: '[{"msg_index":0,"success":true,"log":""}]', + logs: [], tx: cosmoshub.tx, timestamp: "2020-02-14T11:35:41Z", }; diff --git a/packages/bcp/src/decode.ts b/packages/bcp/src/decode.ts index 3279c9d9..aa4edb9c 100644 --- a/packages/bcp/src/decode.ts +++ b/packages/bcp/src/decode.ts @@ -1,4 +1,4 @@ -import { TxsResponse, types } from "@cosmwasm/sdk"; +import { IndexedTx, types } from "@cosmwasm/sdk"; import { Address, Algorithm, @@ -180,17 +180,16 @@ export function parseSignedTx( export function parseTxsResponseUnsigned( chainId: ChainId, currentHeight: number, - response: TxsResponse, + response: IndexedTx, tokens: BankTokens, erc20Tokens: readonly Erc20Token[], ): ConfirmedTransaction { - const height = parseInt(response.height, 10); return { transaction: parseUnsignedTx(response.tx.value, chainId, tokens, erc20Tokens), - height: height, - confirmations: currentHeight - height + 1, - transactionId: response.txhash as TransactionId, - log: response.raw_log, + height: response.height, + confirmations: currentHeight - response.height + 1, + transactionId: response.hash as TransactionId, + log: response.rawLog, }; } @@ -198,16 +197,15 @@ export function parseTxsResponseSigned( chainId: ChainId, currentHeight: number, nonce: Nonce, - response: TxsResponse, + response: IndexedTx, tokens: BankTokens, erc20Tokens: readonly Erc20Token[], ): ConfirmedAndSignedTransaction { - const height = parseInt(response.height, 10); return { ...parseSignedTx(response.tx.value, chainId, nonce, tokens, erc20Tokens), - height: height, - confirmations: currentHeight - height + 1, - transactionId: response.txhash as TransactionId, - log: response.raw_log, + height: response.height, + confirmations: currentHeight - response.height + 1, + transactionId: response.hash as TransactionId, + log: response.rawLog, }; } diff --git a/packages/bcp/types/decode.d.ts b/packages/bcp/types/decode.d.ts index b2fac2c7..906d4862 100644 --- a/packages/bcp/types/decode.d.ts +++ b/packages/bcp/types/decode.d.ts @@ -1,4 +1,4 @@ -import { TxsResponse, types } from "@cosmwasm/sdk"; +import { IndexedTx, types } from "@cosmwasm/sdk"; import { Amount, ChainId, @@ -43,7 +43,7 @@ export declare function parseSignedTx( export declare function parseTxsResponseUnsigned( chainId: ChainId, currentHeight: number, - response: TxsResponse, + response: IndexedTx, tokens: BankTokens, erc20Tokens: readonly Erc20Token[], ): ConfirmedTransaction; @@ -51,7 +51,7 @@ export declare function parseTxsResponseSigned( chainId: ChainId, currentHeight: number, nonce: Nonce, - response: TxsResponse, + response: IndexedTx, tokens: BankTokens, erc20Tokens: readonly Erc20Token[], ): ConfirmedAndSignedTransaction; diff --git a/packages/sdk/src/cosmwasmclient.searchtx.spec.ts b/packages/sdk/src/cosmwasmclient.searchtx.spec.ts index 5079a6bd..799684da 100644 --- a/packages/sdk/src/cosmwasmclient.searchtx.spec.ts +++ b/packages/sdk/src/cosmwasmclient.searchtx.spec.ts @@ -92,8 +92,8 @@ describe("CosmWasmClient.searchTx", () => { expect(result.length).toEqual(1); expect(result[0]).toEqual( jasmine.objectContaining({ - height: postedSend.height.toString(), - txhash: postedSend.hash, + height: postedSend.height, + hash: postedSend.hash, tx: postedSend.tx, }), ); @@ -144,8 +144,8 @@ describe("CosmWasmClient.searchTx", () => { expect(result.length).toEqual(1); expect(result[0]).toEqual( jasmine.objectContaining({ - height: postedSend.height.toString(), - txhash: postedSend.hash, + height: postedSend.height, + hash: postedSend.hash, tx: postedSend.tx, }), ); @@ -163,7 +163,7 @@ describe("CosmWasmClient.searchTx", () => { // Check basic structure of all results for (const result of results) { const msg = fromOneElementArray(result.tx.value.msg); - assert(isMsgSend(msg), `${result.txhash} (height ${result.height}) is not a bank send transaction`); + assert(isMsgSend(msg), `${result.hash} (height ${result.height}) is not a bank send transaction`); expect( msg.value.to_address === postedSend.sender || msg.value.from_address == postedSend.sender, ).toEqual(true); @@ -172,8 +172,8 @@ describe("CosmWasmClient.searchTx", () => { // Check details of most recent result expect(results[results.length - 1]).toEqual( jasmine.objectContaining({ - height: postedSend.height.toString(), - txhash: postedSend.hash, + height: postedSend.height, + hash: postedSend.hash, tx: postedSend.tx, }), ); @@ -189,7 +189,7 @@ describe("CosmWasmClient.searchTx", () => { // Check basic structure of all results for (const result of results) { const msg = fromOneElementArray(result.tx.value.msg); - assert(isMsgSend(msg), `${result.txhash} (height ${result.height}) is not a bank send transaction`); + assert(isMsgSend(msg), `${result.hash} (height ${result.height}) is not a bank send transaction`); expect( msg.value.to_address === postedSend.recipient || msg.value.from_address == postedSend.recipient, ).toEqual(true); @@ -198,8 +198,8 @@ describe("CosmWasmClient.searchTx", () => { // Check details of most recent result expect(results[results.length - 1]).toEqual( jasmine.objectContaining({ - height: postedSend.height.toString(), - txhash: postedSend.hash, + height: postedSend.height, + hash: postedSend.hash, tx: postedSend.tx, }), ); @@ -273,15 +273,15 @@ describe("CosmWasmClient.searchTx", () => { // Check basic structure of all results for (const result of results) { const msg = fromOneElementArray(result.tx.value.msg); - assert(isMsgSend(msg), `${result.txhash} (height ${result.height}) is not a bank send transaction`); + assert(isMsgSend(msg), `${result.hash} (height ${result.height}) is not a bank send transaction`); expect(msg.value.to_address).toEqual(postedSend.recipient); } // Check details of most recent result expect(results[results.length - 1]).toEqual( jasmine.objectContaining({ - height: postedSend.height.toString(), - txhash: postedSend.hash, + height: postedSend.height, + hash: postedSend.hash, tx: postedSend.tx, }), ); @@ -301,7 +301,7 @@ describe("CosmWasmClient.searchTx", () => { const msg = fromOneElementArray(result.tx.value.msg); assert( isMsgExecuteContract(msg) || isMsgInstantiateContract(msg), - `${result.txhash} (at ${result.height}) not an execute or instantiate msg`, + `${result.hash} (at ${result.height}) not an execute or instantiate msg`, ); } @@ -322,8 +322,8 @@ describe("CosmWasmClient.searchTx", () => { // Check details of most recent result expect(results[results.length - 1]).toEqual( jasmine.objectContaining({ - height: postedExecute.height.toString(), - txhash: postedExecute.hash, + height: postedExecute.height, + hash: postedExecute.hash, tx: postedExecute.tx, }), ); @@ -344,15 +344,15 @@ describe("CosmWasmClient.searchTx", () => { // Check basic structure of all results for (const result of results) { const msg = fromOneElementArray(result.tx.value.msg); - assert(isMsgExecuteContract(msg), `${result.txhash} (at ${result.height}) not an execute msg`); + assert(isMsgExecuteContract(msg), `${result.hash} (at ${result.height}) not an execute msg`); expect(msg.value.contract).toEqual(postedExecute.contract); } // Check details of most recent result expect(results[results.length - 1]).toEqual( jasmine.objectContaining({ - height: postedExecute.height.toString(), - txhash: postedExecute.hash, + height: postedExecute.height, + hash: postedExecute.hash, tx: postedExecute.tx, }), ); diff --git a/packages/sdk/src/cosmwasmclient.ts b/packages/sdk/src/cosmwasmclient.ts index 5ce22c5f..0ac9cb4b 100644 --- a/packages/sdk/src/cosmwasmclient.ts +++ b/packages/sdk/src/cosmwasmclient.ts @@ -2,7 +2,7 @@ import { Sha256 } from "@iov/crypto"; import { Encoding } from "@iov/encoding"; import { Log, parseLogs } from "./logs"; -import { BlockResponse, BroadcastMode, RestClient, TxsResponse } from "./restclient"; +import { BlockResponse, BroadcastMode, RestClient } from "./restclient"; import { CosmosSdkAccount, CosmosSdkTx, StdTx } from "./types"; export interface GetNonceResult { @@ -92,6 +92,20 @@ export interface ContractDetails extends Contract { readonly initMsg: object; } +/** A transaction that is indexed as part of the transaction history */ +export interface IndexedTx { + readonly height: number; + readonly hash: string; + readonly rawLog: string; + readonly logs: readonly Log[]; + readonly tx: CosmosSdkTx; + /** The gas limit as set by the user */ + readonly gasWanted?: number; + /** The gas used by the execution */ + readonly gasUsed?: number; + readonly timestamp: string; +} + export class CosmWasmClient { protected readonly restClient: RestClient; @@ -153,7 +167,7 @@ export class CosmWasmClient { } } - public async searchTx(query: SearchTxQuery, filter: SearchTxFilter = {}): Promise { + public async searchTx(query: SearchTxQuery, filter: SearchTxFilter = {}): Promise { const minHeight = filter.minHeight || 0; const maxHeight = filter.maxHeight || Number.MAX_SAFE_INTEGER; @@ -163,7 +177,7 @@ export class CosmWasmClient { return `${originalQuery}&tx.minheight=${minHeight}&tx.maxheight=${maxHeight}`; } - let txs: readonly TxsResponse[]; + let txs: readonly IndexedTx[]; if (isSearchByIdQuery(query)) { txs = await this.txsQuery(`tx.hash=${query.id}`); } else if (isSearchByHeightQuery(query)) { @@ -180,8 +194,8 @@ export class CosmWasmClient { const sent = await this.txsQuery(sentQuery); const received = await this.txsQuery(receivedQuery); - const sentHashes = sent.map(t => t.txhash); - txs = [...sent, ...received.filter(t => !sentHashes.includes(t.txhash))]; + const sentHashes = sent.map(t => t.hash); + txs = [...sent, ...received.filter(t => !sentHashes.includes(t.hash))]; } else if (isSearchByTagsQuery(query)) { const rawQuery = withFilters(query.tags.map(t => `${t.key}=${t.value}`).join("&")); txs = await this.txsQuery(rawQuery); @@ -190,10 +204,7 @@ export class CosmWasmClient { } // backend sometimes messes up with min/max height filtering - const filtered = txs.filter(tx => { - const txHeight = parseInt(tx.height, 10); - return txHeight >= minHeight && txHeight <= maxHeight; - }); + const filtered = txs.filter(tx => tx.height >= minHeight && tx.height <= maxHeight); return filtered; } @@ -303,7 +314,7 @@ export class CosmWasmClient { } } - private async txsQuery(query: string): Promise { + private async txsQuery(query: string): Promise { // TODO: we need proper pagination support const limit = 100; const result = await this.restClient.txsQuery(`${query}&limit=${limit}`); @@ -313,6 +324,15 @@ export class CosmWasmClient { `Found more results on the backend than we can process currently. Results: ${result.total_count}, supported: ${limit}`, ); } - return result.txs; + return result.txs.map( + (restItem): IndexedTx => ({ + height: parseInt(restItem.height, 10), + hash: restItem.txhash, + rawLog: restItem.raw_log, + logs: parseLogs(restItem.logs || []), + tx: restItem.tx, + timestamp: restItem.timestamp, + }), + ); } } diff --git a/packages/sdk/src/index.ts b/packages/sdk/src/index.ts index d6d5d2ef..28400ecf 100644 --- a/packages/sdk/src/index.ts +++ b/packages/sdk/src/index.ts @@ -12,6 +12,7 @@ export { Contract, CosmWasmClient, GetNonceResult, + IndexedTx, PostTxResult, SearchByHeightQuery, SearchByIdQuery, diff --git a/packages/sdk/types/cosmwasmclient.d.ts b/packages/sdk/types/cosmwasmclient.d.ts index f544e060..a35d3839 100644 --- a/packages/sdk/types/cosmwasmclient.d.ts +++ b/packages/sdk/types/cosmwasmclient.d.ts @@ -1,5 +1,5 @@ import { Log } from "./logs"; -import { BlockResponse, BroadcastMode, RestClient, TxsResponse } from "./restclient"; +import { BlockResponse, BroadcastMode, RestClient } from "./restclient"; import { CosmosSdkAccount, CosmosSdkTx, StdTx } from "./types"; export interface GetNonceResult { readonly accountNumber: number; @@ -63,6 +63,19 @@ export interface ContractDetails extends Contract { /** Argument passed on initialization of the contract */ readonly initMsg: object; } +/** A transaction that is indexed as part of the transaction history */ +export interface IndexedTx { + readonly height: number; + readonly hash: string; + readonly rawLog: string; + readonly logs: readonly Log[]; + readonly tx: CosmosSdkTx; + /** The gas limit as set by the user */ + readonly gasWanted?: number; + /** The gas used by the execution */ + readonly gasUsed?: number; + readonly timestamp: string; +} export declare class CosmWasmClient { protected readonly restClient: RestClient; constructor(url: string, broadcastMode?: BroadcastMode); @@ -86,7 +99,7 @@ export declare class CosmWasmClient { * @param height The height of the block. If undefined, the latest height is used. */ getBlock(height?: number): Promise; - searchTx(query: SearchTxQuery, filter?: SearchTxFilter): Promise; + searchTx(query: SearchTxQuery, filter?: SearchTxFilter): Promise; postTx(tx: StdTx): Promise; getCodes(): Promise; getCodeDetails(codeId: number): Promise; diff --git a/packages/sdk/types/index.d.ts b/packages/sdk/types/index.d.ts index a96ec335..6c1aecba 100644 --- a/packages/sdk/types/index.d.ts +++ b/packages/sdk/types/index.d.ts @@ -11,6 +11,7 @@ export { Contract, CosmWasmClient, GetNonceResult, + IndexedTx, PostTxResult, SearchByHeightQuery, SearchByIdQuery, From 911c9f06494afafe2f44d54131d126b3c53b8f91 Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Mon, 2 Mar 2020 14:07:37 +0100 Subject: [PATCH 03/10] Create higher level types Block, BlockHeader --- packages/bcp/src/cosmwasmconnection.ts | 15 +++++---- packages/sdk/src/cosmwasmclient.spec.ts | 30 +++++++++--------- packages/sdk/src/cosmwasmclient.ts | 41 ++++++++++++++++++++----- packages/sdk/src/index.ts | 2 ++ packages/sdk/types/cosmwasmclient.d.ts | 21 +++++++++++-- packages/sdk/types/index.d.ts | 2 ++ 6 files changed, 79 insertions(+), 32 deletions(-) diff --git a/packages/bcp/src/cosmwasmconnection.ts b/packages/bcp/src/cosmwasmconnection.ts index 54d039b2..6c5b16c9 100644 --- a/packages/bcp/src/cosmwasmconnection.ts +++ b/packages/bcp/src/cosmwasmconnection.ts @@ -138,8 +138,8 @@ export class CosmWasmConnection implements BlockchainConnection { } public async height(): Promise { - const { block } = await this.cosmWasmClient.getBlock(); - return parseInt(block.header.height, 10); + const { header } = await this.cosmWasmClient.getBlock(); + return header.height; } public async getToken(searchTicker: TokenTicker): Promise { @@ -247,13 +247,12 @@ export class CosmWasmConnection implements BlockchainConnection { } public async getBlockHeader(height: number): Promise { - // eslint-disable-next-line @typescript-eslint/camelcase - const { block_id: blockId, block } = await this.cosmWasmClient.getBlock(height); + const { id, header, txs } = await this.cosmWasmClient.getBlock(height); return { - id: blockId.hash as BlockId, - height: parseInt(block.header.height, 10), - time: new ReadonlyDate(block.header.time), - transactionCount: block.data.txs?.length || 0, + id: id as BlockId, + height: header.height, + time: new ReadonlyDate(header.time), + transactionCount: txs.length, }; } diff --git a/packages/sdk/src/cosmwasmclient.spec.ts b/packages/sdk/src/cosmwasmclient.spec.ts index 1953b3c2..88d65dc8 100644 --- a/packages/sdk/src/cosmwasmclient.spec.ts +++ b/packages/sdk/src/cosmwasmclient.spec.ts @@ -108,39 +108,39 @@ describe("CosmWasmClient", () => { const response = await client.getBlock(); // id - expect(response.block_id.hash).toMatch(tendermintIdMatcher); + expect(response.id).toMatch(tendermintIdMatcher); // header - expect(parseInt(response.block.header.height, 10)).toBeGreaterThanOrEqual(1); - expect(response.block.header.chain_id).toEqual(await client.chainId()); - expect(new ReadonlyDate(response.block.header.time).getTime()).toBeLessThan(ReadonlyDate.now()); - expect(new ReadonlyDate(response.block.header.time).getTime()).toBeGreaterThanOrEqual( + expect(response.header.height).toBeGreaterThanOrEqual(1); + expect(response.header.chainId).toEqual(await client.chainId()); + expect(new ReadonlyDate(response.header.time).getTime()).toBeLessThan(ReadonlyDate.now()); + expect(new ReadonlyDate(response.header.time).getTime()).toBeGreaterThanOrEqual( ReadonlyDate.now() - 5_000, ); - // data - expect(response.block.data.txs === null || Array.isArray(response.block.data.txs)).toEqual(true); + // txs + expect(Array.isArray(response.txs)).toEqual(true); }); it("works for block by height", async () => { pendingWithoutWasmd(); const client = new CosmWasmClient(wasmdEndpoint); - const height = parseInt((await client.getBlock()).block.header.height, 10); + const height = (await client.getBlock()).header.height; const response = await client.getBlock(height - 1); // id - expect(response.block_id.hash).toMatch(tendermintIdMatcher); + expect(response.id).toMatch(tendermintIdMatcher); // header - expect(response.block.header.height).toEqual(`${height - 1}`); - expect(response.block.header.chain_id).toEqual(await client.chainId()); - expect(new ReadonlyDate(response.block.header.time).getTime()).toBeLessThan(ReadonlyDate.now()); - expect(new ReadonlyDate(response.block.header.time).getTime()).toBeGreaterThanOrEqual( + expect(response.header.height).toEqual(height - 1); + expect(response.header.chainId).toEqual(await client.chainId()); + expect(new ReadonlyDate(response.header.time).getTime()).toBeLessThan(ReadonlyDate.now()); + expect(new ReadonlyDate(response.header.time).getTime()).toBeGreaterThanOrEqual( ReadonlyDate.now() - 5_000, ); - // data - expect(response.block.data.txs === null || Array.isArray(response.block.data.txs)).toEqual(true); + // txs + expect(Array.isArray(response.txs)).toEqual(true); }); }); diff --git a/packages/sdk/src/cosmwasmclient.ts b/packages/sdk/src/cosmwasmclient.ts index 0ac9cb4b..26b9e590 100644 --- a/packages/sdk/src/cosmwasmclient.ts +++ b/packages/sdk/src/cosmwasmclient.ts @@ -2,7 +2,7 @@ import { Sha256 } from "@iov/crypto"; import { Encoding } from "@iov/encoding"; import { Log, parseLogs } from "./logs"; -import { BlockResponse, BroadcastMode, RestClient } from "./restclient"; +import { BroadcastMode, RestClient } from "./restclient"; import { CosmosSdkAccount, CosmosSdkTx, StdTx } from "./types"; export interface GetNonceResult { @@ -106,6 +106,25 @@ export interface IndexedTx { readonly timestamp: string; } +export interface BlockHeader { + readonly version: { + readonly block: string; + readonly app: string; + }; + readonly height: number; + readonly chainId: string; + /** An RFC 3339 time string like e.g. '2020-02-15T10:39:10.4696305Z' */ + readonly time: string; +} + +export interface Block { + /** The ID is a hash of the block header (uppercase hex) */ + readonly id: string; + readonly header: BlockHeader; + /** Array of raw transactions */ + readonly txs: ReadonlyArray; +} + export class CosmWasmClient { protected readonly restClient: RestClient; @@ -159,12 +178,20 @@ export class CosmWasmClient { * * @param height The height of the block. If undefined, the latest height is used. */ - public async getBlock(height?: number): Promise { - if (height !== undefined) { - return this.restClient.blocks(height); - } else { - return this.restClient.blocksLatest(); - } + public async getBlock(height?: number): Promise { + const response = + height !== undefined ? await this.restClient.blocks(height) : await this.restClient.blocksLatest(); + + return { + id: response.block_id.hash, + header: { + version: response.block.header.version, + time: response.block.header.time, + height: parseInt(response.block.header.height, 10), + chainId: response.block.header.chain_id, + }, + txs: (response.block.data.txs || []).map(encoded => Encoding.fromBase64(encoded)), + }; } public async searchTx(query: SearchTxQuery, filter: SearchTxFilter = {}): Promise { diff --git a/packages/sdk/src/index.ts b/packages/sdk/src/index.ts index 28400ecf..bf7704fd 100644 --- a/packages/sdk/src/index.ts +++ b/packages/sdk/src/index.ts @@ -7,6 +7,8 @@ export { unmarshalTx } from "./decoding"; export { makeSignBytes, marshalTx } from "./encoding"; export { BroadcastMode, RestClient, TxsResponse } from "./restclient"; export { + Block, + BlockHeader, Code, CodeDetails, Contract, diff --git a/packages/sdk/types/cosmwasmclient.d.ts b/packages/sdk/types/cosmwasmclient.d.ts index a35d3839..54fa2749 100644 --- a/packages/sdk/types/cosmwasmclient.d.ts +++ b/packages/sdk/types/cosmwasmclient.d.ts @@ -1,5 +1,5 @@ import { Log } from "./logs"; -import { BlockResponse, BroadcastMode, RestClient } from "./restclient"; +import { BroadcastMode, RestClient } from "./restclient"; import { CosmosSdkAccount, CosmosSdkTx, StdTx } from "./types"; export interface GetNonceResult { readonly accountNumber: number; @@ -76,6 +76,23 @@ export interface IndexedTx { readonly gasUsed?: number; readonly timestamp: string; } +export interface BlockHeader { + readonly version: { + readonly block: string; + readonly app: string; + }; + readonly height: number; + readonly chainId: string; + /** An RFC 3339 time string like e.g. '2020-02-15T10:39:10.4696305Z' */ + readonly time: string; +} +export interface Block { + /** The ID is a hash of the block header (uppercase hex) */ + readonly id: string; + readonly header: BlockHeader; + /** Array of raw transactions */ + readonly txs: ReadonlyArray; +} export declare class CosmWasmClient { protected readonly restClient: RestClient; constructor(url: string, broadcastMode?: BroadcastMode); @@ -98,7 +115,7 @@ export declare class CosmWasmClient { * * @param height The height of the block. If undefined, the latest height is used. */ - getBlock(height?: number): Promise; + getBlock(height?: number): Promise; searchTx(query: SearchTxQuery, filter?: SearchTxFilter): Promise; postTx(tx: StdTx): Promise; getCodes(): Promise; diff --git a/packages/sdk/types/index.d.ts b/packages/sdk/types/index.d.ts index 6c1aecba..54934860 100644 --- a/packages/sdk/types/index.d.ts +++ b/packages/sdk/types/index.d.ts @@ -6,6 +6,8 @@ export { unmarshalTx } from "./decoding"; export { makeSignBytes, marshalTx } from "./encoding"; export { BroadcastMode, RestClient, TxsResponse } from "./restclient"; export { + Block, + BlockHeader, Code, CodeDetails, Contract, From ed79897cdeac27f4baf1f5b5cc013c1969f30ba3 Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Mon, 2 Mar 2020 14:21:06 +0100 Subject: [PATCH 04/10] Create higher level Account type --- packages/bcp/src/cosmwasmconnection.ts | 4 +-- packages/sdk/src/cosmwasmclient.spec.ts | 6 ++--- packages/sdk/src/cosmwasmclient.ts | 26 ++++++++++++++++--- packages/sdk/src/index.ts | 1 + packages/sdk/src/pubkey.ts | 8 +++--- packages/sdk/src/restclient.ts | 12 ++++++++- .../sdk/src/signingcosmwasmclient.spec.ts | 2 +- packages/sdk/src/signingcosmwasmclient.ts | 5 ++-- packages/sdk/src/types.ts | 12 --------- packages/sdk/types/cosmwasmclient.d.ts | 13 ++++++++-- packages/sdk/types/index.d.ts | 1 + packages/sdk/types/pubkey.d.ts | 6 ++--- packages/sdk/types/restclient.d.ts | 11 +++++++- packages/sdk/types/signingcosmwasmclient.d.ts | 6 ++--- packages/sdk/types/types.d.ts | 9 ------- 15 files changed, 74 insertions(+), 48 deletions(-) diff --git a/packages/bcp/src/cosmwasmconnection.ts b/packages/bcp/src/cosmwasmconnection.ts index 6c5b16c9..c57510b2 100644 --- a/packages/bcp/src/cosmwasmconnection.ts +++ b/packages/bcp/src/cosmwasmconnection.ts @@ -164,7 +164,7 @@ export class CosmWasmConnection implements BlockchainConnection { const address = isPubkeyQuery(query) ? pubkeyToAddress(query.pubkey, this.addressPrefix) : query.address; const bankAccount = await this.cosmWasmClient.getAccount(address); - const supportedBankCoins = (bankAccount?.coins || []).filter(({ denom }) => + const supportedBankCoins = (bankAccount?.balance || []).filter(({ denom }) => this.bankTokens.find(token => token.denom === denom), ); const erc20Amounts = await Promise.all( @@ -191,7 +191,7 @@ export class CosmWasmConnection implements BlockchainConnection { ...supportedBankCoins.map(coin => decodeAmount(this.bankTokens, coin)), ...nonZeroErc20Amounts, ].sort((a, b) => a.tokenTicker.localeCompare(b.tokenTicker)); - const pubkey = bankAccount?.public_key ? decodeCosmosPubkey(bankAccount.public_key) : undefined; + const pubkey = bankAccount?.pubkey ? decodeCosmosPubkey(bankAccount.pubkey) : undefined; return { address: address, balance: balance, diff --git a/packages/sdk/src/cosmwasmclient.spec.ts b/packages/sdk/src/cosmwasmclient.spec.ts index 88d65dc8..660c9e23 100644 --- a/packages/sdk/src/cosmwasmclient.spec.ts +++ b/packages/sdk/src/cosmwasmclient.spec.ts @@ -83,10 +83,10 @@ describe("CosmWasmClient", () => { const client = new CosmWasmClient(wasmdEndpoint); expect(await client.getAccount(unused.address)).toEqual({ address: unused.address, - account_number: 5, + accountNumber: 5, sequence: 0, - public_key: "", - coins: [ + pubkey: undefined, + balance: [ { denom: "ucosm", amount: "1000000000" }, { denom: "ustake", amount: "1000000000" }, ], diff --git a/packages/sdk/src/cosmwasmclient.ts b/packages/sdk/src/cosmwasmclient.ts index 26b9e590..79d5b4cb 100644 --- a/packages/sdk/src/cosmwasmclient.ts +++ b/packages/sdk/src/cosmwasmclient.ts @@ -3,13 +3,23 @@ import { Encoding } from "@iov/encoding"; import { Log, parseLogs } from "./logs"; import { BroadcastMode, RestClient } from "./restclient"; -import { CosmosSdkAccount, CosmosSdkTx, StdTx } from "./types"; +import { Coin, CosmosSdkTx, StdTx } from "./types"; export interface GetNonceResult { readonly accountNumber: number; readonly sequence: number; } +export interface Account { + /** Bech32 account address */ + readonly address: string; + readonly balance: ReadonlyArray; + /** Bech32 encoded pubkey */ + readonly pubkey: string | undefined; + readonly accountNumber: number; + readonly sequence: number; +} + export interface PostTxResult { readonly logs: readonly Log[]; readonly rawLog: string; @@ -162,15 +172,23 @@ export class CosmWasmClient { ); } return { - accountNumber: account.account_number, + accountNumber: account.accountNumber, sequence: account.sequence, }; } - public async getAccount(address: string): Promise { + public async getAccount(address: string): Promise { const account = await this.restClient.authAccounts(address); const value = account.result.value; - return value.address === "" ? undefined : value; + return value.address === "" + ? undefined + : { + address: value.address, + balance: value.coins, + pubkey: value.public_key || undefined, + accountNumber: value.account_number, + sequence: value.sequence, + }; } /** diff --git a/packages/sdk/src/index.ts b/packages/sdk/src/index.ts index bf7704fd..0b5e47b2 100644 --- a/packages/sdk/src/index.ts +++ b/packages/sdk/src/index.ts @@ -7,6 +7,7 @@ export { unmarshalTx } from "./decoding"; export { makeSignBytes, marshalTx } from "./encoding"; export { BroadcastMode, RestClient, TxsResponse } from "./restclient"; export { + Account, Block, BlockHeader, Code, diff --git a/packages/sdk/src/pubkey.ts b/packages/sdk/src/pubkey.ts index 5da2e0a5..b9c8b1ba 100644 --- a/packages/sdk/src/pubkey.ts +++ b/packages/sdk/src/pubkey.ts @@ -1,7 +1,7 @@ import { Bech32, Encoding } from "@iov/encoding"; import equal from "fast-deep-equal"; -import { Bech32PubKey, PubKey, pubkeyType } from "./types"; +import { PubKey, pubkeyType } from "./types"; export function encodeSecp256k1Pubkey(pubkey: Uint8Array): PubKey { if (pubkey.length !== 33 || (pubkey[0] !== 0x02 && pubkey[0] !== 0x03)) { @@ -28,8 +28,8 @@ const pubkeyAminoPrefixEd25519 = Encoding.fromHex("1624de6420"); const pubkeyAminoPrefixSr25519 = Encoding.fromHex("0dfb1005"); const pubkeyAminoPrefixLength = pubkeyAminoPrefixSecp256k1.length; -export function decodeBech32Pubkey(bech: Bech32PubKey): PubKey { - const { prefix, data } = Bech32.decode(bech); +export function decodeBech32Pubkey(bechEncoded: string): PubKey { + const { prefix, data } = Bech32.decode(bechEncoded); if (!isCosmosPubkeyBech32Prefix(prefix)) { throw new Error(`Invalid bech32 prefix. Must be one of ${validPubkeyPrefixes.join(", ")}.`); } @@ -65,7 +65,7 @@ export function decodeBech32Pubkey(bech: Bech32PubKey): PubKey { } } -export function encodeBech32Pubkey(pubkey: PubKey, prefix: CosmosPubkeyBech32Prefix): Bech32PubKey { +export function encodeBech32Pubkey(pubkey: PubKey, prefix: CosmosPubkeyBech32Prefix): string { let aminoPrefix: Uint8Array; switch (pubkey.type) { // Note: please don't add cases here without writing additional unit tests diff --git a/packages/sdk/src/restclient.ts b/packages/sdk/src/restclient.ts index 4e064fdc..ac5fd3cb 100644 --- a/packages/sdk/src/restclient.ts +++ b/packages/sdk/src/restclient.ts @@ -1,10 +1,20 @@ import { Encoding } from "@iov/encoding"; import axios, { AxiosError, AxiosInstance } from "axios"; -import { CosmosSdkAccount, CosmosSdkTx, Model, parseWasmData, StdTx, WasmData } from "./types"; +import { Coin, CosmosSdkTx, Model, parseWasmData, StdTx, WasmData } from "./types"; const { fromBase64, toHex, toUtf8 } = Encoding; +export interface CosmosSdkAccount { + /** Bech32 account address */ + readonly address: string; + readonly coins: ReadonlyArray; + /** Bech32 encoded pubkey */ + readonly public_key: string; + readonly account_number: number; + readonly sequence: number; +} + interface NodeInfo { readonly network: string; } diff --git a/packages/sdk/src/signingcosmwasmclient.spec.ts b/packages/sdk/src/signingcosmwasmclient.spec.ts index 096008d0..79c74fc1 100644 --- a/packages/sdk/src/signingcosmwasmclient.spec.ts +++ b/packages/sdk/src/signingcosmwasmclient.spec.ts @@ -205,7 +205,7 @@ describe("SigningCosmWasmClient", () => { // got tokens const after = await client.getAccount(beneficiaryAddress); assert(after); - expect(after.coins).toEqual(transferAmount); + expect(after.balance).toEqual(transferAmount); }); }); }); diff --git a/packages/sdk/src/signingcosmwasmclient.ts b/packages/sdk/src/signingcosmwasmclient.ts index 67d38752..db5933f1 100644 --- a/packages/sdk/src/signingcosmwasmclient.ts +++ b/packages/sdk/src/signingcosmwasmclient.ts @@ -3,13 +3,12 @@ import { Encoding } from "@iov/encoding"; import pako from "pako"; import { isValidBuilder } from "./builder"; -import { CosmWasmClient, GetNonceResult, PostTxResult } from "./cosmwasmclient"; +import { Account, CosmWasmClient, GetNonceResult, PostTxResult } from "./cosmwasmclient"; import { makeSignBytes } from "./encoding"; import { findAttribute, Log } from "./logs"; import { BroadcastMode } from "./restclient"; import { Coin, - CosmosSdkAccount, MsgExecuteContract, MsgInstantiateContract, MsgSend, @@ -121,7 +120,7 @@ export class SigningCosmWasmClient extends CosmWasmClient { return super.getNonce(address || this.senderAddress); } - public async getAccount(address?: string): Promise { + public async getAccount(address?: string): Promise { return super.getAccount(address || this.senderAddress); } diff --git a/packages/sdk/src/types.ts b/packages/sdk/src/types.ts index c902cc4b..1a354ade 100644 --- a/packages/sdk/src/types.ts +++ b/packages/sdk/src/types.ts @@ -150,18 +150,6 @@ export const pubkeyType = { export const pubkeyTypes: readonly string[] = [pubkeyType.secp256k1, pubkeyType.ed25519, pubkeyType.sr25519]; -// bech32-encoded amino-binary encoded PubKey interface. oof. -export type Bech32PubKey = string; - -export interface CosmosSdkAccount { - /** Bech32 account address */ - readonly address: string; - readonly coins: ReadonlyArray; - readonly public_key: Bech32PubKey; - readonly account_number: number; - readonly sequence: number; -} - export interface WasmData { // key is hex-encoded readonly key: string; diff --git a/packages/sdk/types/cosmwasmclient.d.ts b/packages/sdk/types/cosmwasmclient.d.ts index 54fa2749..89f5f45e 100644 --- a/packages/sdk/types/cosmwasmclient.d.ts +++ b/packages/sdk/types/cosmwasmclient.d.ts @@ -1,10 +1,19 @@ import { Log } from "./logs"; import { BroadcastMode, RestClient } from "./restclient"; -import { CosmosSdkAccount, CosmosSdkTx, StdTx } from "./types"; +import { Coin, CosmosSdkTx, StdTx } from "./types"; export interface GetNonceResult { readonly accountNumber: number; readonly sequence: number; } +export interface Account { + /** Bech32 account address */ + readonly address: string; + readonly balance: ReadonlyArray; + /** Bech32 encoded pubkey */ + readonly pubkey: string | undefined; + readonly accountNumber: number; + readonly sequence: number; +} export interface PostTxResult { readonly logs: readonly Log[]; readonly rawLog: string; @@ -109,7 +118,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; - getAccount(address: string): Promise; + getAccount(address: string): Promise; /** * Gets block header and meta * diff --git a/packages/sdk/types/index.d.ts b/packages/sdk/types/index.d.ts index 54934860..f77304d1 100644 --- a/packages/sdk/types/index.d.ts +++ b/packages/sdk/types/index.d.ts @@ -6,6 +6,7 @@ export { unmarshalTx } from "./decoding"; export { makeSignBytes, marshalTx } from "./encoding"; export { BroadcastMode, RestClient, TxsResponse } from "./restclient"; export { + Account, Block, BlockHeader, Code, diff --git a/packages/sdk/types/pubkey.d.ts b/packages/sdk/types/pubkey.d.ts index a7dddae8..8715588b 100644 --- a/packages/sdk/types/pubkey.d.ts +++ b/packages/sdk/types/pubkey.d.ts @@ -1,5 +1,5 @@ -import { Bech32PubKey, PubKey } from "./types"; +import { PubKey } from "./types"; export declare function encodeSecp256k1Pubkey(pubkey: Uint8Array): PubKey; export declare type CosmosPubkeyBech32Prefix = "cosmospub" | "cosmosvalconspub" | "cosmosvaloperpub"; -export declare function decodeBech32Pubkey(bech: Bech32PubKey): PubKey; -export declare function encodeBech32Pubkey(pubkey: PubKey, prefix: CosmosPubkeyBech32Prefix): Bech32PubKey; +export declare function decodeBech32Pubkey(bechEncoded: string): PubKey; +export declare function encodeBech32Pubkey(pubkey: PubKey, prefix: CosmosPubkeyBech32Prefix): string; diff --git a/packages/sdk/types/restclient.d.ts b/packages/sdk/types/restclient.d.ts index eaa59c0f..3e8a00d1 100644 --- a/packages/sdk/types/restclient.d.ts +++ b/packages/sdk/types/restclient.d.ts @@ -1,4 +1,13 @@ -import { CosmosSdkAccount, CosmosSdkTx, Model, StdTx } from "./types"; +import { Coin, CosmosSdkTx, Model, StdTx } from "./types"; +export interface CosmosSdkAccount { + /** Bech32 account address */ + readonly address: string; + readonly coins: ReadonlyArray; + /** Bech32 encoded pubkey */ + readonly public_key: string; + readonly account_number: number; + readonly sequence: number; +} interface NodeInfo { readonly network: string; } diff --git a/packages/sdk/types/signingcosmwasmclient.d.ts b/packages/sdk/types/signingcosmwasmclient.d.ts index 8b169172..9c8f5b0a 100644 --- a/packages/sdk/types/signingcosmwasmclient.d.ts +++ b/packages/sdk/types/signingcosmwasmclient.d.ts @@ -1,7 +1,7 @@ -import { CosmWasmClient, GetNonceResult, PostTxResult } from "./cosmwasmclient"; +import { Account, CosmWasmClient, GetNonceResult, PostTxResult } from "./cosmwasmclient"; import { Log } from "./logs"; import { BroadcastMode } from "./restclient"; -import { Coin, CosmosSdkAccount, StdFee, StdSignature } from "./types"; +import { Coin, StdFee, StdSignature } from "./types"; export interface SigningCallback { (signBytes: Uint8Array): Promise; } @@ -56,7 +56,7 @@ export declare class SigningCosmWasmClient extends CosmWasmClient { broadcastMode?: BroadcastMode, ); getNonce(address?: string): Promise; - getAccount(address?: string): Promise; + getAccount(address?: string): Promise; /** Uploads code and returns a receipt, including the code ID */ upload(wasmCode: Uint8Array, meta?: UploadMeta, memo?: string): Promise; instantiate( diff --git a/packages/sdk/types/types.d.ts b/packages/sdk/types/types.d.ts index d7f1bdf8..1a62733a 100644 --- a/packages/sdk/types/types.d.ts +++ b/packages/sdk/types/types.d.ts @@ -109,15 +109,6 @@ export declare const pubkeyType: { sr25519: "tendermint/PubKeySr25519"; }; export declare const pubkeyTypes: readonly string[]; -export declare type Bech32PubKey = string; -export interface CosmosSdkAccount { - /** Bech32 account address */ - readonly address: string; - readonly coins: ReadonlyArray; - readonly public_key: Bech32PubKey; - readonly account_number: number; - readonly sequence: number; -} export interface WasmData { readonly key: string; readonly val: string; From dc2b21c8f564981f7e2f993e079893ce85928a87 Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Mon, 2 Mar 2020 14:32:45 +0100 Subject: [PATCH 05/10] v0.7.0-alpha.3 --- lerna.json | 2 +- packages/bcp/package.json | 4 ++-- packages/cli/package.json | 4 ++-- packages/faucet/package.json | 4 ++-- packages/sdk/package.json | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/lerna.json b/lerna.json index 25c5ae3e..d3c57c6f 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { - "version": "0.7.0-alpha.2", + "version": "0.7.0-alpha.3", "useWorkspaces": true, "npmClient": "yarn" } diff --git a/packages/bcp/package.json b/packages/bcp/package.json index 71be60a2..7ce2ae92 100644 --- a/packages/bcp/package.json +++ b/packages/bcp/package.json @@ -1,6 +1,6 @@ { "name": "@cosmwasm/bcp", - "version": "0.7.0-alpha.2", + "version": "0.7.0-alpha.3", "description": "Transaction codec and client to communicate with any wasmd blockchain", "author": "Ethan Frey ", "license": "Apache-2.0", @@ -38,7 +38,7 @@ "pack-web": "yarn build-or-skip && webpack --mode development --config webpack.web.config.js" }, "dependencies": { - "@cosmwasm/sdk": "^0.7.0-alpha.2", + "@cosmwasm/sdk": "^0.7.0-alpha.3", "@iov/bcp": "^2.1.0", "@iov/crypto": "^2.1.0", "@iov/encoding": "^2.1.0", diff --git a/packages/cli/package.json b/packages/cli/package.json index 7aa0f7c5..009d2759 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,6 +1,6 @@ { "name": "@cosmwasm/cli", - "version": "0.7.0-alpha.2", + "version": "0.7.0-alpha.3", "description": "Command line interface", "contributors": [ "IOV SAS ", @@ -36,7 +36,7 @@ "!**/testdata/" ], "dependencies": { - "@cosmwasm/sdk": "^0.7.0-alpha.2", + "@cosmwasm/sdk": "^0.7.0-alpha.3", "@iov/crypto": "^2.1.0", "@iov/encoding": "^2.1.0", "@iov/utils": "^2.0.2", diff --git a/packages/faucet/package.json b/packages/faucet/package.json index 08604ac3..aa35b11a 100644 --- a/packages/faucet/package.json +++ b/packages/faucet/package.json @@ -1,6 +1,6 @@ { "name": "@cosmwasm/faucet", - "version": "0.7.0-alpha.2", + "version": "0.7.0-alpha.3", "description": "The faucet", "author": "Ethan Frey ", "license": "Apache-2.0", @@ -35,7 +35,7 @@ "test": "yarn build-or-skip && yarn test-node" }, "dependencies": { - "@cosmwasm/bcp": "^0.7.0-alpha.2", + "@cosmwasm/bcp": "^0.7.0-alpha.3", "@iov/bcp": "^2.1.0", "@iov/crypto": "^2.1.0", "@iov/encoding": "^2.1.0", diff --git a/packages/sdk/package.json b/packages/sdk/package.json index dfbdcff0..1df1724b 100644 --- a/packages/sdk/package.json +++ b/packages/sdk/package.json @@ -1,6 +1,6 @@ { "name": "@cosmwasm/sdk", - "version": "0.7.0-alpha.2", + "version": "0.7.0-alpha.3", "description": "CosmWasm SDK", "author": "Ethan Frey ", "license": "Apache-2.0", From 4bde976280220c88c8a1819ccfc97f17da22791d Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Mon, 2 Mar 2020 15:34:04 +0100 Subject: [PATCH 06/10] Add missing export ContractDetails --- packages/sdk/src/index.ts | 1 + packages/sdk/types/index.d.ts | 1 + 2 files changed, 2 insertions(+) diff --git a/packages/sdk/src/index.ts b/packages/sdk/src/index.ts index 0b5e47b2..56214227 100644 --- a/packages/sdk/src/index.ts +++ b/packages/sdk/src/index.ts @@ -13,6 +13,7 @@ export { Code, CodeDetails, Contract, + ContractDetails, CosmWasmClient, GetNonceResult, IndexedTx, diff --git a/packages/sdk/types/index.d.ts b/packages/sdk/types/index.d.ts index f77304d1..ddb6b5f1 100644 --- a/packages/sdk/types/index.d.ts +++ b/packages/sdk/types/index.d.ts @@ -12,6 +12,7 @@ export { Code, CodeDetails, Contract, + ContractDetails, CosmWasmClient, GetNonceResult, IndexedTx, From 8cbbb58417151f6cd913c417c4b9a1e1b4d12a61 Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Mon, 2 Mar 2020 15:36:49 +0100 Subject: [PATCH 07/10] v0.7.0-alpha.4 --- lerna.json | 2 +- packages/bcp/package.json | 4 ++-- packages/cli/package.json | 4 ++-- packages/faucet/package.json | 4 ++-- packages/sdk/package.json | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/lerna.json b/lerna.json index d3c57c6f..b9922acb 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { - "version": "0.7.0-alpha.3", + "version": "0.7.0-alpha.4", "useWorkspaces": true, "npmClient": "yarn" } diff --git a/packages/bcp/package.json b/packages/bcp/package.json index 7ce2ae92..7ac982ad 100644 --- a/packages/bcp/package.json +++ b/packages/bcp/package.json @@ -1,6 +1,6 @@ { "name": "@cosmwasm/bcp", - "version": "0.7.0-alpha.3", + "version": "0.7.0-alpha.4", "description": "Transaction codec and client to communicate with any wasmd blockchain", "author": "Ethan Frey ", "license": "Apache-2.0", @@ -38,7 +38,7 @@ "pack-web": "yarn build-or-skip && webpack --mode development --config webpack.web.config.js" }, "dependencies": { - "@cosmwasm/sdk": "^0.7.0-alpha.3", + "@cosmwasm/sdk": "^0.7.0-alpha.4", "@iov/bcp": "^2.1.0", "@iov/crypto": "^2.1.0", "@iov/encoding": "^2.1.0", diff --git a/packages/cli/package.json b/packages/cli/package.json index 009d2759..d7355414 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,6 +1,6 @@ { "name": "@cosmwasm/cli", - "version": "0.7.0-alpha.3", + "version": "0.7.0-alpha.4", "description": "Command line interface", "contributors": [ "IOV SAS ", @@ -36,7 +36,7 @@ "!**/testdata/" ], "dependencies": { - "@cosmwasm/sdk": "^0.7.0-alpha.3", + "@cosmwasm/sdk": "^0.7.0-alpha.4", "@iov/crypto": "^2.1.0", "@iov/encoding": "^2.1.0", "@iov/utils": "^2.0.2", diff --git a/packages/faucet/package.json b/packages/faucet/package.json index aa35b11a..a759711f 100644 --- a/packages/faucet/package.json +++ b/packages/faucet/package.json @@ -1,6 +1,6 @@ { "name": "@cosmwasm/faucet", - "version": "0.7.0-alpha.3", + "version": "0.7.0-alpha.4", "description": "The faucet", "author": "Ethan Frey ", "license": "Apache-2.0", @@ -35,7 +35,7 @@ "test": "yarn build-or-skip && yarn test-node" }, "dependencies": { - "@cosmwasm/bcp": "^0.7.0-alpha.3", + "@cosmwasm/bcp": "^0.7.0-alpha.4", "@iov/bcp": "^2.1.0", "@iov/crypto": "^2.1.0", "@iov/encoding": "^2.1.0", diff --git a/packages/sdk/package.json b/packages/sdk/package.json index 1df1724b..b9261ea3 100644 --- a/packages/sdk/package.json +++ b/packages/sdk/package.json @@ -1,6 +1,6 @@ { "name": "@cosmwasm/sdk", - "version": "0.7.0-alpha.3", + "version": "0.7.0-alpha.4", "description": "CosmWasm SDK", "author": "Ethan Frey ", "license": "Apache-2.0", From 27f27d31e36453bdf0fe88fa52a4e98fa134ccba Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Mon, 2 Mar 2020 17:34:22 +0100 Subject: [PATCH 08/10] Let Account use type types.PubKey --- packages/bcp/src/address.spec.ts | 13 +------------ packages/bcp/src/address.ts | 18 +++--------------- packages/bcp/src/cosmwasmconnection.ts | 6 +++--- packages/bcp/types/address.d.ts | 1 - packages/sdk/src/cosmwasmclient.ts | 8 ++++---- packages/sdk/types/cosmwasmclient.d.ts | 5 ++--- 6 files changed, 13 insertions(+), 38 deletions(-) diff --git a/packages/bcp/src/address.spec.ts b/packages/bcp/src/address.spec.ts index 0b52e387..459007dc 100644 --- a/packages/bcp/src/address.spec.ts +++ b/packages/bcp/src/address.spec.ts @@ -1,22 +1,11 @@ import { Algorithm, PubkeyBytes } from "@iov/bcp"; import { Encoding } from "@iov/encoding"; -import { decodeCosmosPubkey, pubkeyToAddress } from "./address"; +import { pubkeyToAddress } from "./address"; const { fromBase64, fromHex } = Encoding; describe("address", () => { - describe("decodeCosmosPubkey", () => { - it("works", () => { - expect( - decodeCosmosPubkey("cosmospub1addwnpepqd8sgxq7aw348ydctp3n5ajufgxp395hksxjzc6565yfp56scupfqhlgyg5"), - ).toEqual({ - data: fromBase64("A08EGB7ro1ORuFhjOnZcSgwYlpe0DSFjVNUIkNNQxwKQ"), - algo: Algorithm.Secp256k1, - }); - }); - }); - describe("pubkeyToAddress", () => { it("works for Secp256k1 compressed", () => { const prefix = "cosmos"; diff --git a/packages/bcp/src/address.ts b/packages/bcp/src/address.ts index 11afa609..e26cf556 100644 --- a/packages/bcp/src/address.ts +++ b/packages/bcp/src/address.ts @@ -1,21 +1,9 @@ -import { decodeBech32Pubkey, pubkeyToAddress as sdkPubkeyToAddress, types } from "@cosmwasm/sdk"; -import { Address, Algorithm, PubkeyBundle, PubkeyBytes } from "@iov/bcp"; +import { pubkeyToAddress as sdkPubkeyToAddress, types } from "@cosmwasm/sdk"; +import { Address, Algorithm, PubkeyBundle } from "@iov/bcp"; import { Secp256k1 } from "@iov/crypto"; import { Encoding } from "@iov/encoding"; -const { fromBase64, toBase64 } = Encoding; - -export function decodeCosmosPubkey(encodedPubkey: string): PubkeyBundle { - const sdkPubKey = decodeBech32Pubkey(encodedPubkey); - switch (sdkPubKey.type) { - case types.pubkeyType.secp256k1: - return { algo: Algorithm.Secp256k1, data: fromBase64(sdkPubKey.value) as PubkeyBytes }; - case types.pubkeyType.ed25519: - return { algo: Algorithm.Ed25519, data: fromBase64(sdkPubKey.value) as PubkeyBytes }; - default: - throw new Error("Unsupported Pubkey type: " + sdkPubKey.type); - } -} +const { toBase64 } = Encoding; // See https://github.com/tendermint/tendermint/blob/f2ada0a604b4c0763bda2f64fac53d506d3beca7/docs/spec/blockchain/encoding.md#public-key-cryptography export function pubkeyToAddress(pubkey: PubkeyBundle, prefix: string): Address { diff --git a/packages/bcp/src/cosmwasmconnection.ts b/packages/bcp/src/cosmwasmconnection.ts index c57510b2..275bd81b 100644 --- a/packages/bcp/src/cosmwasmconnection.ts +++ b/packages/bcp/src/cosmwasmconnection.ts @@ -36,10 +36,10 @@ import equal from "fast-deep-equal"; import { ReadonlyDate } from "readonly-date"; import { Producer, Stream } from "xstream"; -import { decodeCosmosPubkey, pubkeyToAddress } from "./address"; +import { pubkeyToAddress } from "./address"; import { Caip5 } from "./caip5"; import { CosmWasmCodec } from "./cosmwasmcodec"; -import { decodeAmount, parseTxsResponseSigned, parseTxsResponseUnsigned } from "./decode"; +import { decodeAmount, decodePubkey, parseTxsResponseSigned, parseTxsResponseUnsigned } from "./decode"; import { buildSignedTx } from "./encode"; import { accountToNonce, BankToken, Erc20Token } from "./types"; @@ -191,7 +191,7 @@ export class CosmWasmConnection implements BlockchainConnection { ...supportedBankCoins.map(coin => decodeAmount(this.bankTokens, coin)), ...nonZeroErc20Amounts, ].sort((a, b) => a.tokenTicker.localeCompare(b.tokenTicker)); - const pubkey = bankAccount?.pubkey ? decodeCosmosPubkey(bankAccount.pubkey) : undefined; + const pubkey = bankAccount?.pubkey ? decodePubkey(bankAccount.pubkey) : undefined; return { address: address, balance: balance, diff --git a/packages/bcp/types/address.d.ts b/packages/bcp/types/address.d.ts index aa49f713..98fa0ca9 100644 --- a/packages/bcp/types/address.d.ts +++ b/packages/bcp/types/address.d.ts @@ -1,3 +1,2 @@ import { Address, PubkeyBundle } from "@iov/bcp"; -export declare function decodeCosmosPubkey(encodedPubkey: string): PubkeyBundle; export declare function pubkeyToAddress(pubkey: PubkeyBundle, prefix: string): Address; diff --git a/packages/sdk/src/cosmwasmclient.ts b/packages/sdk/src/cosmwasmclient.ts index cb87bd5d..0f7a51b2 100644 --- a/packages/sdk/src/cosmwasmclient.ts +++ b/packages/sdk/src/cosmwasmclient.ts @@ -2,8 +2,9 @@ import { Sha256 } from "@iov/crypto"; import { Encoding } from "@iov/encoding"; import { Log, parseLogs } from "./logs"; +import { decodeBech32Pubkey } from "./pubkey"; import { BroadcastMode, RestClient } from "./restclient"; -import { Coin, CosmosSdkTx, StdTx } from "./types"; +import { Coin, CosmosSdkTx, PubKey, StdTx } from "./types"; export interface GetNonceResult { readonly accountNumber: number; @@ -14,8 +15,7 @@ export interface Account { /** Bech32 account address */ readonly address: string; readonly balance: ReadonlyArray; - /** Bech32 encoded pubkey */ - readonly pubkey: string | undefined; + readonly pubkey: PubKey | undefined; readonly accountNumber: number; readonly sequence: number; } @@ -185,7 +185,7 @@ export class CosmWasmClient { : { address: value.address, balance: value.coins, - pubkey: value.public_key || undefined, + pubkey: value.public_key ? decodeBech32Pubkey(value.public_key) : undefined, accountNumber: value.account_number, sequence: value.sequence, }; diff --git a/packages/sdk/types/cosmwasmclient.d.ts b/packages/sdk/types/cosmwasmclient.d.ts index 89f5f45e..e7ffa3d4 100644 --- a/packages/sdk/types/cosmwasmclient.d.ts +++ b/packages/sdk/types/cosmwasmclient.d.ts @@ -1,6 +1,6 @@ import { Log } from "./logs"; import { BroadcastMode, RestClient } from "./restclient"; -import { Coin, CosmosSdkTx, StdTx } from "./types"; +import { Coin, CosmosSdkTx, PubKey, StdTx } from "./types"; export interface GetNonceResult { readonly accountNumber: number; readonly sequence: number; @@ -9,8 +9,7 @@ export interface Account { /** Bech32 account address */ readonly address: string; readonly balance: ReadonlyArray; - /** Bech32 encoded pubkey */ - readonly pubkey: string | undefined; + readonly pubkey: PubKey | undefined; readonly accountNumber: number; readonly sequence: number; } From 23f88564e5df7ec092b9caf76708cb26d1cd12bc Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Mon, 2 Mar 2020 17:36:33 +0100 Subject: [PATCH 09/10] Add comment on IndexedTx.hash --- packages/sdk/src/cosmwasmclient.ts | 1 + packages/sdk/types/cosmwasmclient.d.ts | 1 + 2 files changed, 2 insertions(+) diff --git a/packages/sdk/src/cosmwasmclient.ts b/packages/sdk/src/cosmwasmclient.ts index 0f7a51b2..126e3b69 100644 --- a/packages/sdk/src/cosmwasmclient.ts +++ b/packages/sdk/src/cosmwasmclient.ts @@ -105,6 +105,7 @@ export interface ContractDetails extends Contract { /** A transaction that is indexed as part of the transaction history */ export interface IndexedTx { readonly height: number; + /** Transaction hash (might be used as transaction ID). Guaranteed to be non-empty upper-case hex */ readonly hash: string; readonly rawLog: string; readonly logs: readonly Log[]; diff --git a/packages/sdk/types/cosmwasmclient.d.ts b/packages/sdk/types/cosmwasmclient.d.ts index e7ffa3d4..4b92801b 100644 --- a/packages/sdk/types/cosmwasmclient.d.ts +++ b/packages/sdk/types/cosmwasmclient.d.ts @@ -74,6 +74,7 @@ export interface ContractDetails extends Contract { /** A transaction that is indexed as part of the transaction history */ export interface IndexedTx { readonly height: number; + /** Transaction hash (might be used as transaction ID). Guaranteed to be non-empty upper-case hex */ readonly hash: string; readonly rawLog: string; readonly logs: readonly Log[]; From d0ddcd8ea4bf78288c3dcee8487300c94ff6165d Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Mon, 2 Mar 2020 17:38:21 +0100 Subject: [PATCH 10/10] Document IndexedTx.timestamp --- packages/sdk/src/cosmwasmclient.ts | 1 + packages/sdk/types/cosmwasmclient.d.ts | 1 + 2 files changed, 2 insertions(+) diff --git a/packages/sdk/src/cosmwasmclient.ts b/packages/sdk/src/cosmwasmclient.ts index 126e3b69..370ce332 100644 --- a/packages/sdk/src/cosmwasmclient.ts +++ b/packages/sdk/src/cosmwasmclient.ts @@ -114,6 +114,7 @@ export interface IndexedTx { readonly gasWanted?: number; /** The gas used by the execution */ readonly gasUsed?: number; + /** An RFC 3339 time string like e.g. '2020-02-15T10:39:10.4696305Z' */ readonly timestamp: string; } diff --git a/packages/sdk/types/cosmwasmclient.d.ts b/packages/sdk/types/cosmwasmclient.d.ts index 4b92801b..83afe61f 100644 --- a/packages/sdk/types/cosmwasmclient.d.ts +++ b/packages/sdk/types/cosmwasmclient.d.ts @@ -83,6 +83,7 @@ export interface IndexedTx { readonly gasWanted?: number; /** The gas used by the execution */ readonly gasUsed?: number; + /** An RFC 3339 time string like e.g. '2020-02-15T10:39:10.4696305Z' */ readonly timestamp: string; } export interface BlockHeader {