Add CosmWasmClient.searchTx
This commit is contained in:
parent
737d5570b9
commit
1e122a7546
@ -1,3 +1,5 @@
|
||||
import { assert } from "@iov/utils";
|
||||
|
||||
import { CosmWasmClient } from "./cosmwasmclient";
|
||||
import { makeSignBytes, marshalTx } from "./encoding";
|
||||
import { findAttribute } from "./logs";
|
||||
@ -5,7 +7,7 @@ import { Secp256k1Pen } from "./pen";
|
||||
import { RestClient } from "./restclient";
|
||||
import cosmoshub from "./testdata/cosmoshub.json";
|
||||
import { getRandomizedHackatom, makeRandomAddress } from "./testutils.spec";
|
||||
import { Coin, MsgSend, StdFee } from "./types";
|
||||
import { Coin, CosmosSdkTx, MsgSend, StdFee } from "./types";
|
||||
|
||||
const httpUrl = "http://localhost:1317";
|
||||
|
||||
@ -118,6 +120,134 @@ describe("CosmWasmClient", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("searchTx", () => {
|
||||
let posted:
|
||||
| {
|
||||
readonly sender: string;
|
||||
readonly recipient: string;
|
||||
readonly hash: string;
|
||||
readonly height: number;
|
||||
readonly tx: CosmosSdkTx;
|
||||
}
|
||||
| undefined;
|
||||
|
||||
beforeAll(async () => {
|
||||
if (cosmosEnabled()) {
|
||||
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 = await pen.sign(signBytes);
|
||||
const signedTx = {
|
||||
msg: [sendMsg],
|
||||
fee: fee,
|
||||
memo: memo,
|
||||
signatures: [signature],
|
||||
};
|
||||
|
||||
const result = await client.postTx(marshalTx(signedTx));
|
||||
const txDetails = await new RestClient(httpUrl).txsById(result.transactionHash);
|
||||
posted = {
|
||||
sender: sendMsg.value.from_address,
|
||||
recipient: sendMsg.value.to_address,
|
||||
hash: result.transactionHash,
|
||||
height: Number.parseInt(txDetails.height, 10),
|
||||
tx: txDetails.tx,
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
it("can search by ID", async () => {
|
||||
pendingWithoutCosmos();
|
||||
assert(posted, "value must be set in beforeAll()");
|
||||
const client = CosmWasmClient.makeReadOnly(httpUrl);
|
||||
const result = await client.searchTx({ id: posted.hash });
|
||||
expect(result.length).toEqual(1);
|
||||
expect(result[0]).toEqual(
|
||||
jasmine.objectContaining({
|
||||
height: posted.height.toString(),
|
||||
txhash: posted.hash,
|
||||
tx: posted.tx,
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
it("can search by height", async () => {
|
||||
pendingWithoutCosmos();
|
||||
assert(posted, "value must be set in beforeAll()");
|
||||
const client = CosmWasmClient.makeReadOnly(httpUrl);
|
||||
const result = await client.searchTx({ height: posted.height });
|
||||
expect(result.length).toEqual(1);
|
||||
expect(result[0]).toEqual(
|
||||
jasmine.objectContaining({
|
||||
height: posted.height.toString(),
|
||||
txhash: posted.hash,
|
||||
tx: posted.tx,
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
it("can search by sender", async () => {
|
||||
pendingWithoutCosmos();
|
||||
assert(posted, "value must be set in beforeAll()");
|
||||
const client = CosmWasmClient.makeReadOnly(httpUrl);
|
||||
const result = await client.searchTx({ sentFromOrTo: posted.sender });
|
||||
expect(result.length).toBeGreaterThanOrEqual(1);
|
||||
expect(result[result.length - 1]).toEqual(
|
||||
jasmine.objectContaining({
|
||||
height: posted.height.toString(),
|
||||
txhash: posted.hash,
|
||||
tx: posted.tx,
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
it("can search by recipient", async () => {
|
||||
pendingWithoutCosmos();
|
||||
assert(posted, "value must be set in beforeAll()");
|
||||
const client = CosmWasmClient.makeReadOnly(httpUrl);
|
||||
const result = await client.searchTx({ sentFromOrTo: posted.recipient });
|
||||
expect(result.length).toBeGreaterThanOrEqual(1);
|
||||
expect(result[result.length - 1]).toEqual(
|
||||
jasmine.objectContaining({
|
||||
height: posted.height.toString(),
|
||||
txhash: posted.hash,
|
||||
tx: posted.tx,
|
||||
}),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("upload", () => {
|
||||
it("works", async () => {
|
||||
pendingWithoutCosmos();
|
||||
|
||||
@ -3,7 +3,7 @@ import { Encoding } from "@iov/encoding";
|
||||
|
||||
import { makeSignBytes, marshalTx } from "./encoding";
|
||||
import { findAttribute, Log, parseLogs } from "./logs";
|
||||
import { RestClient } from "./restclient";
|
||||
import { RestClient, TxsResponse } from "./restclient";
|
||||
import {
|
||||
Coin,
|
||||
CosmosSdkTx,
|
||||
@ -65,6 +65,32 @@ export interface PostTxResult {
|
||||
readonly transactionHash: string;
|
||||
}
|
||||
|
||||
export interface SearchByIdQuery {
|
||||
readonly id: string;
|
||||
}
|
||||
|
||||
export interface SearchByHeightQuery {
|
||||
readonly height: number;
|
||||
}
|
||||
|
||||
export interface SearchBySentFromOrToQuery {
|
||||
readonly sentFromOrTo: string;
|
||||
}
|
||||
|
||||
export type SearchTxQuery = SearchByIdQuery | SearchByHeightQuery | SearchBySentFromOrToQuery;
|
||||
|
||||
function isSearchByIdQuery(query: SearchTxQuery): query is SearchByIdQuery {
|
||||
return (query as SearchByIdQuery).id !== undefined;
|
||||
}
|
||||
|
||||
function isSearchByHeightQuery(query: SearchTxQuery): query is SearchByHeightQuery {
|
||||
return (query as SearchByHeightQuery).height !== undefined;
|
||||
}
|
||||
|
||||
function isSearchBySentFromOrToQuery(query: SearchTxQuery): query is SearchBySentFromOrToQuery {
|
||||
return (query as SearchBySentFromOrToQuery).sentFromOrTo !== undefined;
|
||||
}
|
||||
|
||||
export interface ExecuteResult {
|
||||
readonly logs: readonly Log[];
|
||||
}
|
||||
@ -131,6 +157,26 @@ export class CosmWasmClient {
|
||||
};
|
||||
}
|
||||
|
||||
public async searchTx(query: SearchTxQuery): Promise<readonly TxsResponse[]> {
|
||||
// TODO: we need proper pagination support
|
||||
function limited(originalQuery: string): string {
|
||||
return `${originalQuery}&limit=75`;
|
||||
}
|
||||
|
||||
if (isSearchByIdQuery(query)) {
|
||||
return [await this.restClient.txsById(query.id)];
|
||||
} else if (isSearchByHeightQuery(query)) {
|
||||
return (await this.restClient.txs(`tx.height=${query.height}`)).txs;
|
||||
} else if (isSearchBySentFromOrToQuery(query)) {
|
||||
const sent = (await this.restClient.txs(limited(`message.sender=${query.sentFromOrTo}`))).txs;
|
||||
const sentHashes = sent.map(t => t.txhash);
|
||||
const received = (await this.restClient.txs(limited(`transfer.recipient=${query.sentFromOrTo}`))).txs;
|
||||
return [...sent, ...received.filter(t => !sentHashes.includes(t.txhash))];
|
||||
} else {
|
||||
throw new Error("Unknown query type");
|
||||
}
|
||||
}
|
||||
|
||||
public async postTx(tx: Uint8Array): Promise<PostTxResult> {
|
||||
const result = await this.restClient.postTx(tx);
|
||||
if (result.code) {
|
||||
|
||||
@ -7,7 +7,16 @@ export { unmarshalTx } from "./decoding";
|
||||
export { makeSignBytes, marshalTx } from "./encoding";
|
||||
export { RestClient, TxsResponse } from "./restclient";
|
||||
export { encodeSecp256k1Signature } from "./signature";
|
||||
export { CosmWasmClient, ExecuteResult, GetNonceResult, PostTxResult } from "./cosmwasmclient";
|
||||
export {
|
||||
CosmWasmClient,
|
||||
ExecuteResult,
|
||||
GetNonceResult,
|
||||
PostTxResult,
|
||||
SearchByHeightQuery,
|
||||
SearchByIdQuery,
|
||||
SearchBySentFromOrToQuery,
|
||||
SearchTxQuery,
|
||||
} from "./cosmwasmclient";
|
||||
export { makeCosmoshubPath, Pen, PrehashType, Secp256k1Pen } from "./pen";
|
||||
export {
|
||||
CosmosPubkeyBech32Prefix,
|
||||
|
||||
12
packages/sdk/types/cosmwasmclient.d.ts
vendored
12
packages/sdk/types/cosmwasmclient.d.ts
vendored
@ -1,4 +1,5 @@
|
||||
import { Log } from "./logs";
|
||||
import { TxsResponse } from "./restclient";
|
||||
import { Coin, CosmosSdkTx, StdSignature } from "./types";
|
||||
export interface SigningCallback {
|
||||
(signBytes: Uint8Array): Promise<StdSignature>;
|
||||
@ -13,6 +14,16 @@ export interface PostTxResult {
|
||||
/** Transaction hash (might be used as transaction ID). Guaranteed to be non-exmpty upper-case hex */
|
||||
readonly transactionHash: string;
|
||||
}
|
||||
export interface SearchByIdQuery {
|
||||
readonly id: string;
|
||||
}
|
||||
export interface SearchByHeightQuery {
|
||||
readonly height: number;
|
||||
}
|
||||
export interface SearchBySentFromOrToQuery {
|
||||
readonly sentFromOrTo: string;
|
||||
}
|
||||
export declare type SearchTxQuery = SearchByIdQuery | SearchByHeightQuery | SearchBySentFromOrToQuery;
|
||||
export interface ExecuteResult {
|
||||
readonly logs: readonly Log[];
|
||||
}
|
||||
@ -35,6 +46,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<GetNonceResult>;
|
||||
searchTx(query: SearchTxQuery): Promise<readonly TxsResponse[]>;
|
||||
postTx(tx: Uint8Array): Promise<PostTxResult>;
|
||||
/** Uploads code and returns a code ID */
|
||||
upload(wasmCode: Uint8Array, memo?: string): Promise<number>;
|
||||
|
||||
11
packages/sdk/types/index.d.ts
vendored
11
packages/sdk/types/index.d.ts
vendored
@ -6,7 +6,16 @@ export { unmarshalTx } from "./decoding";
|
||||
export { makeSignBytes, marshalTx } from "./encoding";
|
||||
export { RestClient, TxsResponse } from "./restclient";
|
||||
export { encodeSecp256k1Signature } from "./signature";
|
||||
export { CosmWasmClient, ExecuteResult, GetNonceResult, PostTxResult } from "./cosmwasmclient";
|
||||
export {
|
||||
CosmWasmClient,
|
||||
ExecuteResult,
|
||||
GetNonceResult,
|
||||
PostTxResult,
|
||||
SearchByHeightQuery,
|
||||
SearchByIdQuery,
|
||||
SearchBySentFromOrToQuery,
|
||||
SearchTxQuery,
|
||||
} from "./cosmwasmclient";
|
||||
export { makeCosmoshubPath, Pen, PrehashType, Secp256k1Pen } from "./pen";
|
||||
export {
|
||||
CosmosPubkeyBech32Prefix,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user