Add QueryClient.queryAbci and deprecate QueryClient.queryUnverified

This commit is contained in:
Simon Warta 2022-11-24 15:27:03 +01:00
parent 7a5cebaab5
commit 503e94996f
4 changed files with 138 additions and 3 deletions

View File

@ -6,6 +6,11 @@ and this project adheres to
## [Unreleased]
### Deprecated
- @cosmjs/stargate: Deprecate `QueryClient.queryUnverified` in favour of newly
added `QueryClient.queryAbci`.
## [0.29.4] - 2022-11-15
### Added

View File

@ -166,4 +166,95 @@ describe("QueryClient", () => {
tmClient.disconnect();
});
});
describe("queryAbci", () => {
it("works via WebSockets", async () => {
pendingWithoutSimapp();
const [client, tmClient] = await makeClient(simapp.tendermintUrlWs);
const requestData = Uint8Array.from(
QueryAllBalancesRequest.encode({ address: unused.address }).finish(),
);
const { value } = await client.queryAbci(`/cosmos.bank.v1beta1.Query/AllBalances`, requestData);
const response = QueryAllBalancesResponse.decode(value);
expect(response.balances.length).toEqual(2);
tmClient.disconnect();
});
it("works via http", async () => {
pendingWithoutSimapp();
const [client, tmClient] = await makeClient(simapp.tendermintUrlHttp);
const requestData = Uint8Array.from(
QueryAllBalancesRequest.encode({ address: unused.address }).finish(),
);
const { value } = await client.queryAbci(`/cosmos.bank.v1beta1.Query/AllBalances`, requestData);
const response = QueryAllBalancesResponse.decode(value);
expect(response.balances.length).toEqual(2);
tmClient.disconnect();
});
it("works for height", async () => {
pendingWithoutSimapp();
const [queryClient, tmClient] = await makeClient(simapp.tendermintUrlHttp);
const joe = makeRandomAddress();
const h1 = (await tmClient.status()).syncInfo.latestBlockHeight;
// Send tokens to `recipient`
const wallet = await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic);
const client = await SigningStargateClient.connectWithSigner(
simapp.tendermintUrlHttp,
wallet,
defaultSigningClientOptions,
);
const amount = coin(332211, simapp.denomFee);
await client.sendTokens(faucet.address0, joe, [amount], "auto");
const h2 = (await tmClient.status()).syncInfo.latestBlockHeight;
assert(h1 < h2);
// Query with no height
{
const requestData = QueryBalanceRequest.encode({ address: joe, denom: simapp.denomFee }).finish();
const { value, height } = await queryClient.queryAbci(
`/cosmos.bank.v1beta1.Query/Balance`,
requestData,
);
const response = QueryBalanceResponse.decode(value);
expect(response.balance).toEqual(amount);
expect(height).toEqual(h2);
}
// Query at h2 (after send)
{
const requestData = QueryBalanceRequest.encode({ address: joe, denom: simapp.denomFee }).finish();
const { value, height } = await queryClient.queryAbci(
`/cosmos.bank.v1beta1.Query/Balance`,
requestData,
h2,
);
const response = QueryBalanceResponse.decode(value);
expect(response.balance).toEqual(amount);
expect(height).toEqual(h2);
}
// Query at h1 (before send)
{
const requestData = QueryBalanceRequest.encode({ address: joe, denom: simapp.denomFee }).finish();
const { value, height } = await queryClient.queryAbci(
`/cosmos.bank.v1beta1.Query/Balance`,
requestData,
h1,
);
const response = QueryBalanceResponse.decode(value);
expect(response.balance).toEqual({ amount: "0", denom: simapp.denomFee });
expect(height).toEqual(h1);
}
tmClient.disconnect();
});
});
});

View File

@ -26,6 +26,16 @@ export interface ProvenQuery {
readonly height: number;
}
/**
* The response of an ABCI query to Tendermint.
* This is a subset of `tendermint34.AbciQueryResponse` in order
* to abstract away Tendermint versions.
*/
export interface QueryAbciResponse {
readonly value: Uint8Array;
readonly height: number;
}
export class QueryClient {
/** Constructs a QueryClient with 0 extensions */
public static withExtensions(tmClient: Tendermint34Client): QueryClient;
@ -570,11 +580,32 @@ export class QueryClient {
};
}
/**
* Performs an ABCI query to Tendermint without requesting a proof.
*
* @deprecated use queryAbci instead
*/
public async queryUnverified(
path: string,
request: Uint8Array,
desiredHeight?: number,
): Promise<Uint8Array> {
const response = await this.queryAbci(path, request, desiredHeight);
return response.value;
}
/**
* Performs an ABCI query to Tendermint without requesting a proof.
*
* If the `desiredHeight` is set, a particular height is requested. Otherwise
* the latest height is requested. The response contains the actual height of
* the query.
*/
public async queryAbci(
path: string,
request: Uint8Array,
desiredHeight?: number,
): Promise<QueryAbciResponse> {
const response = await this.tmClient.abciQuery({
path: path,
data: request,
@ -586,7 +617,14 @@ export class QueryClient {
throw new Error(`Query failed with (${response.code}): ${response.log}`);
}
return response.value;
if (!response.height) {
throw new Error("No query height returned");
}
return {
value: response.value,
height: response.height,
};
}
// this must return the header for height+1

View File

@ -31,9 +31,10 @@ export interface ProtobufRpcClient {
export function createProtobufRpcClient(base: QueryClient): ProtobufRpcClient {
return {
request: (service: string, method: string, data: Uint8Array): Promise<Uint8Array> => {
request: async (service: string, method: string, data: Uint8Array): Promise<Uint8Array> => {
const path = `/${service}/${method}`;
return base.queryUnverified(path, data);
const response = await base.queryAbci(path, data, undefined);
return response.value;
},
};
}