Implement min/max height filters in CosmWasmClient
This commit is contained in:
parent
798854b002
commit
dfe1cccadb
@ -1,5 +1,5 @@
|
||||
/* eslint-disable @typescript-eslint/camelcase */
|
||||
import { CosmWasmClient, findSequenceForSignedTx, TxsResponse, types } from "@cosmwasm/sdk";
|
||||
import { CosmWasmClient, findSequenceForSignedTx, SearchTxFilter, TxsResponse, types } from "@cosmwasm/sdk";
|
||||
import {
|
||||
Account,
|
||||
AccountQuery,
|
||||
@ -300,8 +300,8 @@ export class CosmWasmConnection implements BlockchainConnection {
|
||||
public async searchTx({
|
||||
height,
|
||||
id,
|
||||
maxHeight: maxHeightOptional,
|
||||
minHeight: minHeightOptional,
|
||||
maxHeight,
|
||||
minHeight,
|
||||
sentFromOrTo,
|
||||
signedBy,
|
||||
tags,
|
||||
@ -316,32 +316,20 @@ export class CosmWasmConnection implements BlockchainConnection {
|
||||
);
|
||||
}
|
||||
|
||||
const minHeight = minHeightOptional || 0;
|
||||
const maxHeight = maxHeightOptional || Number.MAX_SAFE_INTEGER;
|
||||
|
||||
if (maxHeight < minHeight) return []; // optional optimization
|
||||
const filter: SearchTxFilter = { minHeight: minHeight, maxHeight: maxHeight };
|
||||
|
||||
let txs: readonly TxsResponse[];
|
||||
if (id) {
|
||||
txs = await this.cosmWasmClient.searchTx({ id: id });
|
||||
txs = await this.cosmWasmClient.searchTx({ id: id }, filter);
|
||||
} else if (height) {
|
||||
if (height < minHeight) return []; // optional optimization
|
||||
if (height > maxHeight) return []; // optional optimization
|
||||
txs = await this.cosmWasmClient.searchTx({ height: height });
|
||||
txs = await this.cosmWasmClient.searchTx({ height: height }, filter);
|
||||
} else if (sentFromOrTo) {
|
||||
// TODO: pass minHeight/maxHeight to server once we have
|
||||
// https://github.com/cosmwasm/wasmd/issues/73
|
||||
txs = await this.cosmWasmClient.searchTx({ sentFromOrTo: sentFromOrTo });
|
||||
txs = await this.cosmWasmClient.searchTx({ sentFromOrTo: sentFromOrTo }, filter);
|
||||
} else {
|
||||
throw new Error("Unsupported query");
|
||||
}
|
||||
|
||||
const filtered = txs.filter(tx => {
|
||||
const txHeight = parseInt(tx.height, 10);
|
||||
return txHeight >= minHeight && txHeight <= maxHeight;
|
||||
});
|
||||
|
||||
return filtered.map(tx => this.parseAndPopulateTxResponseUnsigned(tx));
|
||||
return txs.map(tx => this.parseAndPopulateTxResponseUnsigned(tx));
|
||||
}
|
||||
|
||||
public listenTx(
|
||||
|
||||
4
packages/bcp/types/cosmwasmconnection.d.ts
vendored
4
packages/bcp/types/cosmwasmconnection.d.ts
vendored
@ -73,8 +73,8 @@ export declare class CosmWasmConnection implements BlockchainConnection {
|
||||
searchTx({
|
||||
height,
|
||||
id,
|
||||
maxHeight: maxHeightOptional,
|
||||
minHeight: minHeightOptional,
|
||||
maxHeight,
|
||||
minHeight,
|
||||
sentFromOrTo,
|
||||
signedBy,
|
||||
tags,
|
||||
|
||||
@ -309,6 +309,87 @@ describe("CosmWasmClient", () => {
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
it("can search by ID and filter by minHeight", async () => {
|
||||
pendingWithoutWasmd();
|
||||
assert(posted);
|
||||
const client = new CosmWasmClient(httpUrl);
|
||||
const query = { id: posted.hash };
|
||||
|
||||
{
|
||||
const result = await client.searchTx(query, { minHeight: 0 });
|
||||
expect(result.length).toEqual(1);
|
||||
}
|
||||
|
||||
{
|
||||
const result = await client.searchTx(query, { minHeight: posted.height - 1 });
|
||||
expect(result.length).toEqual(1);
|
||||
}
|
||||
|
||||
{
|
||||
const result = await client.searchTx(query, { minHeight: posted.height });
|
||||
expect(result.length).toEqual(1);
|
||||
}
|
||||
|
||||
{
|
||||
const result = await client.searchTx(query, { minHeight: posted.height + 1 });
|
||||
expect(result.length).toEqual(0);
|
||||
}
|
||||
});
|
||||
|
||||
it("can search by recipient and filter by minHeight", async () => {
|
||||
pendingWithoutWasmd();
|
||||
assert(posted);
|
||||
const client = new CosmWasmClient(httpUrl);
|
||||
const query = { sentFromOrTo: posted.recipient };
|
||||
|
||||
{
|
||||
const result = await client.searchTx(query, { minHeight: 0 });
|
||||
expect(result.length).toEqual(1);
|
||||
}
|
||||
|
||||
{
|
||||
const result = await client.searchTx(query, { minHeight: posted.height - 1 });
|
||||
expect(result.length).toEqual(1);
|
||||
}
|
||||
|
||||
{
|
||||
const result = await client.searchTx(query, { minHeight: posted.height });
|
||||
expect(result.length).toEqual(1);
|
||||
}
|
||||
|
||||
{
|
||||
const result = await client.searchTx(query, { minHeight: posted.height + 1 });
|
||||
expect(result.length).toEqual(0);
|
||||
}
|
||||
});
|
||||
|
||||
it("can search by recipient and filter by maxHeight", async () => {
|
||||
pendingWithoutWasmd();
|
||||
assert(posted);
|
||||
const client = new CosmWasmClient(httpUrl);
|
||||
const query = { sentFromOrTo: posted.recipient };
|
||||
|
||||
{
|
||||
const result = await client.searchTx(query, { maxHeight: 9999999999999 });
|
||||
expect(result.length).toEqual(1);
|
||||
}
|
||||
|
||||
{
|
||||
const result = await client.searchTx(query, { maxHeight: posted.height + 1 });
|
||||
expect(result.length).toEqual(1);
|
||||
}
|
||||
|
||||
{
|
||||
const result = await client.searchTx(query, { maxHeight: posted.height });
|
||||
expect(result.length).toEqual(1);
|
||||
}
|
||||
|
||||
{
|
||||
const result = await client.searchTx(query, { maxHeight: posted.height - 1 });
|
||||
expect(result.length).toEqual(0);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe("queryContractRaw", () => {
|
||||
|
||||
@ -43,6 +43,11 @@ function isSearchBySentFromOrToQuery(query: SearchTxQuery): query is SearchBySen
|
||||
return (query as SearchBySentFromOrToQuery).sentFromOrTo !== undefined;
|
||||
}
|
||||
|
||||
export interface SearchTxFilter {
|
||||
readonly minHeight?: number;
|
||||
readonly maxHeight?: number;
|
||||
}
|
||||
|
||||
export class CosmWasmClient {
|
||||
protected readonly restClient: RestClient;
|
||||
|
||||
@ -104,26 +109,51 @@ 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`;
|
||||
public async searchTx(query: SearchTxQuery, filter: SearchTxFilter = {}): Promise<readonly TxsResponse[]> {
|
||||
const minHeight = filter.minHeight || 0;
|
||||
const maxHeight = filter.maxHeight || Number.MAX_SAFE_INTEGER;
|
||||
|
||||
if (maxHeight < minHeight) return []; // optional optimization
|
||||
|
||||
function withFiltersAndLimits(originalQuery: string): string {
|
||||
const components = [
|
||||
"limit=75", // TODO: we need proper pagination support
|
||||
`tx.minheight=${minHeight}`,
|
||||
`tx.maxheight=${maxHeight}`,
|
||||
];
|
||||
return `${originalQuery}&${components.join("&")}`;
|
||||
}
|
||||
|
||||
let txs: readonly TxsResponse[];
|
||||
if (isSearchByIdQuery(query)) {
|
||||
return (await this.restClient.txsQuery(`tx.hash=${query.id}`)).txs;
|
||||
txs = (await this.restClient.txsQuery(`tx.hash=${query.id}`)).txs;
|
||||
} else if (isSearchByHeightQuery(query)) {
|
||||
return (await this.restClient.txsQuery(`tx.height=${query.height}`)).txs;
|
||||
// optional optimization to avoid network request
|
||||
if (query.height < minHeight || query.height > maxHeight) {
|
||||
txs = [];
|
||||
} else {
|
||||
txs = (await this.restClient.txsQuery(`tx.height=${query.height}`)).txs;
|
||||
}
|
||||
} else if (isSearchBySentFromOrToQuery(query)) {
|
||||
// We cannot get both in one request (see https://github.com/cosmos/gaia/issues/75)
|
||||
const sent = (await this.restClient.txsQuery(limited(`message.sender=${query.sentFromOrTo}`))).txs;
|
||||
const received = (await this.restClient.txsQuery(limited(`transfer.recipient=${query.sentFromOrTo}`)))
|
||||
.txs;
|
||||
const sentQuery = withFiltersAndLimits(`message.sender=${query.sentFromOrTo}`);
|
||||
const receivedQuery = withFiltersAndLimits(`transfer.recipient=${query.sentFromOrTo}`);
|
||||
const sent = (await this.restClient.txsQuery(sentQuery)).txs;
|
||||
const received = (await this.restClient.txsQuery(receivedQuery)).txs;
|
||||
|
||||
const sentHashes = sent.map(t => t.txhash);
|
||||
return [...sent, ...received.filter(t => !sentHashes.includes(t.txhash))];
|
||||
txs = [...sent, ...received.filter(t => !sentHashes.includes(t.txhash))];
|
||||
} else {
|
||||
throw new Error("Unknown query type");
|
||||
}
|
||||
|
||||
// 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;
|
||||
});
|
||||
|
||||
return filtered;
|
||||
}
|
||||
|
||||
public async postTx(tx: StdTx): Promise<PostTxResult> {
|
||||
|
||||
@ -14,6 +14,7 @@ export {
|
||||
SearchByIdQuery,
|
||||
SearchBySentFromOrToQuery,
|
||||
SearchTxQuery,
|
||||
SearchTxFilter,
|
||||
} from "./cosmwasmclient";
|
||||
export { makeCosmoshubPath, Pen, PrehashType, Secp256k1Pen } from "./pen";
|
||||
export {
|
||||
|
||||
6
packages/sdk/types/cosmwasmclient.d.ts
vendored
6
packages/sdk/types/cosmwasmclient.d.ts
vendored
@ -21,6 +21,10 @@ export interface SearchBySentFromOrToQuery {
|
||||
readonly sentFromOrTo: string;
|
||||
}
|
||||
export declare type SearchTxQuery = SearchByIdQuery | SearchByHeightQuery | SearchBySentFromOrToQuery;
|
||||
export interface SearchTxFilter {
|
||||
readonly minHeight?: number;
|
||||
readonly maxHeight?: number;
|
||||
}
|
||||
export declare class CosmWasmClient {
|
||||
protected readonly restClient: RestClient;
|
||||
constructor(url: string, broadcastMode?: BroadcastMode);
|
||||
@ -44,7 +48,7 @@ export declare class CosmWasmClient {
|
||||
* @param height The height of the block. If undefined, the latest height is used.
|
||||
*/
|
||||
getBlock(height?: number): Promise<BlockResponse>;
|
||||
searchTx(query: SearchTxQuery): Promise<readonly TxsResponse[]>;
|
||||
searchTx(query: SearchTxQuery, filter?: SearchTxFilter): Promise<readonly TxsResponse[]>;
|
||||
postTx(tx: StdTx): Promise<PostTxResult>;
|
||||
/**
|
||||
* Returns the data at the key if present (raw contract dependent storage data)
|
||||
|
||||
1
packages/sdk/types/index.d.ts
vendored
1
packages/sdk/types/index.d.ts
vendored
@ -13,6 +13,7 @@ export {
|
||||
SearchByIdQuery,
|
||||
SearchBySentFromOrToQuery,
|
||||
SearchTxQuery,
|
||||
SearchTxFilter,
|
||||
} from "./cosmwasmclient";
|
||||
export { makeCosmoshubPath, Pen, PrehashType, Secp256k1Pen } from "./pen";
|
||||
export {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user