Connect modules in properties

This commit is contained in:
Simon Warta 2020-07-07 23:38:28 +02:00
parent ad07231bf3
commit e42620bf70
15 changed files with 202 additions and 186 deletions

View File

@ -70,7 +70,7 @@ async function uploadContract(
gas: "89000000",
};
const { account_number, sequence } = (await client.authAccounts(alice.address0)).result.value;
const { account_number, sequence } = (await client.auth.account(alice.address0)).result.value;
const signBytes = makeSignBytes([theMsg], fee, wasmd.chainId, memo, account_number, sequence);
const signature = await pen.sign(signBytes);
const signedTx = makeSignedTx(theMsg, fee, memo, signature);
@ -108,7 +108,7 @@ async function instantiateContract(
gas: "89000000",
};
const { account_number, sequence } = (await client.authAccounts(alice.address0)).result.value;
const { account_number, sequence } = (await client.auth.account(alice.address0)).result.value;
const signBytes = makeSignBytes([theMsg], fee, wasmd.chainId, memo, account_number, sequence);
const signature = await pen.sign(signBytes);
const signedTx = makeSignedTx(theMsg, fee, memo, signature);
@ -136,7 +136,7 @@ async function executeContract(
gas: "89000000",
};
const { account_number, sequence } = (await client.authAccounts(alice.address0)).result.value;
const { account_number, sequence } = (await client.auth.account(alice.address0)).result.value;
const signBytes = makeSignBytes([theMsg], fee, wasmd.chainId, memo, account_number, sequence);
const signature = await pen.sign(signBytes);
const signedTx = makeSignedTx(theMsg, fee, memo, signature);
@ -291,7 +291,7 @@ describe("wasm", () => {
expect(amountAttr.value).toEqual("1234ucosm,321ustake");
expect(result.data).toEqual(toHex(Bech32.decode(contractAddress).data).toUpperCase());
const balance = (await client.authAccounts(contractAddress)).result.value.coins;
const balance = (await client.auth.account(contractAddress)).result.value.coins;
expect(balance).toEqual(transferAmount);
}
@ -311,9 +311,9 @@ describe("wasm", () => {
});
// Verify token transfer from contract to beneficiary
const beneficiaryBalance = (await client.authAccounts(beneficiaryAddress)).result.value.coins;
const beneficiaryBalance = (await client.auth.account(beneficiaryAddress)).result.value.coins;
expect(beneficiaryBalance).toEqual(transferAmount);
const contractBalance = (await client.authAccounts(contractAddress)).result.value.coins;
const contractBalance = (await client.auth.account(contractAddress)).result.value.coins;
expect(contractBalance).toEqual([]);
}
});
@ -328,7 +328,7 @@ describe("wasm", () => {
const client = makeWasmClient(wasmd.endpoint);
// check with contracts were here first to compare
const existingInfos = await client.listCodeInfo();
const existingInfos = await client.wasm.listCodeInfo();
existingInfos.forEach((val, idx) => expect(val.id).toEqual(idx + 1));
const numExisting = existingInfos.length;
@ -341,7 +341,7 @@ describe("wasm", () => {
const codeId = Number.parseInt(codeIdAttr.value, 10);
// ensure we were added to the end of the list
const newInfos = await client.listCodeInfo();
const newInfos = await client.wasm.listCodeInfo();
expect(newInfos.length).toEqual(numExisting + 1);
const lastInfo = newInfos[newInfos.length - 1];
expect(lastInfo.id).toEqual(codeId);
@ -356,7 +356,7 @@ describe("wasm", () => {
expect(lastInfo.data_hash.toLowerCase()).toEqual(toHex(wasmHash));
// download code and check against auto-gen
const { data } = await client.getCode(codeId);
const { data } = await client.wasm.getCode(codeId);
expect(fromBase64(data)).toEqual(hackatom.data);
});
@ -374,7 +374,7 @@ describe("wasm", () => {
// reuse an existing contract, or upload if needed
let codeId: number;
const existingInfos = await client.listCodeInfo();
const existingInfos = await client.wasm.listCodeInfo();
if (existingInfos.length > 0) {
codeId = existingInfos[existingInfos.length - 1].id;
} else {
@ -386,7 +386,7 @@ describe("wasm", () => {
}
// create new instance and compare before and after
const existingContractsByCode = await client.listContractsByCodeId(codeId);
const existingContractsByCode = await client.wasm.listContractsByCodeId(codeId);
for (const contract of existingContractsByCode) {
expect(contract.address).toMatch(bech32AddressMatcher);
expect(contract.code_id).toEqual(codeId);
@ -400,7 +400,7 @@ describe("wasm", () => {
const contractAddressAttr = findAttribute(logs, "message", "contract_address");
const myAddress = contractAddressAttr.value;
const newContractsByCode = await client.listContractsByCodeId(codeId);
const newContractsByCode = await client.wasm.listContractsByCodeId(codeId);
expect(newContractsByCode.length).toEqual(existingContractsByCode.length + 1);
const newContract = newContractsByCode[newContractsByCode.length - 1];
expect(newContract).toEqual(
@ -412,7 +412,7 @@ describe("wasm", () => {
);
// check out info
const myInfo = await client.getContractInfo(myAddress);
const myInfo = await client.wasm.getContractInfo(myAddress);
assert(myInfo);
expect(myInfo).toEqual(
jasmine.objectContaining({
@ -427,7 +427,7 @@ describe("wasm", () => {
// make sure random addresses don't give useful info
const nonExistentAddress = makeRandomAddress();
expect(await client.getContractInfo(nonExistentAddress)).toBeNull();
expect(await client.wasm.getContractInfo(nonExistentAddress)).toBeNull();
});
describe("contract state", () => {
@ -455,7 +455,7 @@ describe("wasm", () => {
pendingWithoutWasmd();
// get contract state
const state = await client.getAllContractState(contractAddress!);
const state = await client.wasm.getAllContractState(contractAddress!);
expect(state.length).toEqual(1);
const data = state[0];
expect(data.key).toEqual(expectedKey);
@ -464,7 +464,7 @@ describe("wasm", () => {
expect(value.beneficiary).toBeDefined();
// bad address is empty array
const noContractState = await client.getAllContractState(noContract);
const noContractState = await client.wasm.getAllContractState(noContract);
expect(noContractState).toEqual([]);
});
@ -472,18 +472,18 @@ describe("wasm", () => {
pendingWithoutWasmd();
// query by one key
const raw = await client.queryContractRaw(contractAddress!, expectedKey);
const raw = await client.wasm.queryContractRaw(contractAddress!, expectedKey);
assert(raw, "must get result");
const model = JSON.parse(fromAscii(raw));
expect(model.verifier).toBeDefined();
expect(model.beneficiary).toBeDefined();
// missing key is null
const missing = await client.queryContractRaw(contractAddress!, fromHex("cafe0dad"));
const missing = await client.wasm.queryContractRaw(contractAddress!, fromHex("cafe0dad"));
expect(missing).toBeNull();
// bad address is null
const noContractModel = await client.queryContractRaw(noContract, expectedKey);
const noContractModel = await client.wasm.queryContractRaw(noContract, expectedKey);
expect(noContractModel).toBeNull();
});
@ -491,18 +491,18 @@ describe("wasm", () => {
pendingWithoutWasmd();
// we can query the verifier properly
const resultDocument = await client.queryContractSmart(contractAddress!, { verifier: {} });
const resultDocument = await client.wasm.queryContractSmart(contractAddress!, { verifier: {} });
expect(resultDocument).toEqual({ verifier: alice.address0 });
// invalid query syntax throws an error
await client.queryContractSmart(contractAddress!, { nosuchkey: {} }).then(
await client.wasm.queryContractSmart(contractAddress!, { nosuchkey: {} }).then(
() => fail("shouldn't succeed"),
(error) =>
expect(error).toMatch(/query wasm contract failed: parsing hackatom::contract::QueryMsg/),
);
// invalid address throws an error
await client.queryContractSmart(noContract, { verifier: {} }).then(
await client.wasm.queryContractSmart(noContract, { verifier: {} }).then(
() => fail("shouldn't succeed"),
(error) => expect(error).toMatch("not found"),
);

View File

@ -76,82 +76,86 @@ function unwrapWasmResponse<T>(response: WasmResponse<T>): T {
* @see https://github.com/cosmwasm/wasmd/blob/master/x/wasm/client/rest/query.go#L19-L27
*/
export interface WasmModule extends LcdModule {
readonly listCodeInfo: () => Promise<readonly CodeInfo[]>;
readonly wasm: {
readonly listCodeInfo: () => Promise<readonly CodeInfo[]>;
/**
* Downloads the original wasm bytecode by code ID.
*
* Throws an error if no code with this id
*/
readonly getCode: (id: number) => Promise<CodeDetails>;
/**
* Downloads the original wasm bytecode by code ID.
*
* Throws an error if no code with this id
*/
readonly getCode: (id: number) => Promise<CodeDetails>;
readonly listContractsByCodeId: (id: number) => Promise<readonly ContractInfo[]>;
readonly listContractsByCodeId: (id: number) => Promise<readonly ContractInfo[]>;
/**
* Returns null when contract was not found at this address.
*/
readonly getContractInfo: (address: string) => Promise<ContractDetails | null>;
/**
* Returns null when contract was not found at this address.
*/
readonly getContractInfo: (address: string) => Promise<ContractDetails | null>;
/**
* Returns all contract state.
* This is an empty array if no such contract, or contract has no data.
*/
readonly getAllContractState: (address: string) => Promise<readonly Model[]>;
/**
* Returns all contract state.
* This is an empty array if no such contract, or contract has no data.
*/
readonly getAllContractState: (address: string) => Promise<readonly Model[]>;
/**
* Returns the data at the key if present (unknown decoded json),
* or null if no data at this (contract address, key) pair
*/
readonly queryContractRaw: (address: string, key: Uint8Array) => Promise<Uint8Array | null>;
/**
* Returns the data at the key if present (unknown decoded json),
* or null if no data at this (contract address, key) pair
*/
readonly queryContractRaw: (address: string, key: Uint8Array) => Promise<Uint8Array | null>;
/**
* Makes a smart query on the contract and parses the reponse as JSON.
* Throws error if no such contract exists, the query format is invalid or the response is invalid.
*/
readonly queryContractSmart: (address: string, query: object) => Promise<JsonObject>;
/**
* Makes a smart query on the contract and parses the reponse as JSON.
* Throws error if no such contract exists, the query format is invalid or the response is invalid.
*/
readonly queryContractSmart: (address: string, query: object) => Promise<JsonObject>;
};
}
export function setupWasmModule(base: LcdClient): WasmModule {
return {
listCodeInfo: async () => {
const path = `/wasm/code`;
const responseData = (await base.get(path)) as WasmResponse<LcdApiArray<CodeInfo>>;
return normalizeLcdApiArray(unwrapWasmResponse(responseData));
},
getCode: async (id: number) => {
const path = `/wasm/code/${id}`;
const responseData = (await base.get(path)) as WasmResponse<CodeDetails>;
return unwrapWasmResponse(responseData);
},
listContractsByCodeId: async (id: number) => {
const path = `/wasm/code/${id}/contracts`;
const responseData = (await base.get(path)) as WasmResponse<LcdApiArray<ContractInfo>>;
return normalizeLcdApiArray(unwrapWasmResponse(responseData));
},
getContractInfo: async (address: string) => {
const path = `/wasm/contract/${address}`;
const response = (await base.get(path)) as WasmResponse<ContractDetails | null>;
return unwrapWasmResponse(response);
},
getAllContractState: async (address: string) => {
const path = `/wasm/contract/${address}/state`;
const responseData = (await base.get(path)) as WasmResponse<LcdApiArray<WasmData>>;
return normalizeLcdApiArray(unwrapWasmResponse(responseData)).map(parseWasmData);
},
queryContractRaw: async (address: string, key: Uint8Array) => {
const hexKey = toHex(key);
const path = `/wasm/contract/${address}/raw/${hexKey}?encoding=hex`;
const responseData = (await base.get(path)) as WasmResponse<WasmData[]>;
const data = unwrapWasmResponse(responseData);
return data.length === 0 ? null : fromBase64(data[0].val);
},
queryContractSmart: async (address: string, query: object) => {
const encoded = toHex(toUtf8(JSON.stringify(query)));
const path = `/wasm/contract/${address}/smart/${encoded}?encoding=hex`;
const responseData = (await base.get(path)) as WasmResponse<SmartQueryResponse>;
const result = unwrapWasmResponse(responseData);
// By convention, smart queries must return a valid JSON document (see https://github.com/CosmWasm/cosmwasm/issues/144)
return JSON.parse(fromUtf8(fromBase64(result.smart)));
wasm: {
listCodeInfo: async () => {
const path = `/wasm/code`;
const responseData = (await base.get(path)) as WasmResponse<LcdApiArray<CodeInfo>>;
return normalizeLcdApiArray(unwrapWasmResponse(responseData));
},
getCode: async (id: number) => {
const path = `/wasm/code/${id}`;
const responseData = (await base.get(path)) as WasmResponse<CodeDetails>;
return unwrapWasmResponse(responseData);
},
listContractsByCodeId: async (id: number) => {
const path = `/wasm/code/${id}/contracts`;
const responseData = (await base.get(path)) as WasmResponse<LcdApiArray<ContractInfo>>;
return normalizeLcdApiArray(unwrapWasmResponse(responseData));
},
getContractInfo: async (address: string) => {
const path = `/wasm/contract/${address}`;
const response = (await base.get(path)) as WasmResponse<ContractDetails | null>;
return unwrapWasmResponse(response);
},
getAllContractState: async (address: string) => {
const path = `/wasm/contract/${address}/state`;
const responseData = (await base.get(path)) as WasmResponse<LcdApiArray<WasmData>>;
return normalizeLcdApiArray(unwrapWasmResponse(responseData)).map(parseWasmData);
},
queryContractRaw: async (address: string, key: Uint8Array) => {
const hexKey = toHex(key);
const path = `/wasm/contract/${address}/raw/${hexKey}?encoding=hex`;
const responseData = (await base.get(path)) as WasmResponse<WasmData[]>;
const data = unwrapWasmResponse(responseData);
return data.length === 0 ? null : fromBase64(data[0].val);
},
queryContractSmart: async (address: string, query: object) => {
const encoded = toHex(toUtf8(JSON.stringify(query)));
const path = `/wasm/contract/${address}/smart/${encoded}?encoding=hex`;
const responseData = (await base.get(path)) as WasmResponse<SmartQueryResponse>;
const result = unwrapWasmResponse(responseData);
// By convention, smart queries must return a valid JSON document (see https://github.com/CosmWasm/cosmwasm/issues/144)
return JSON.parse(fromUtf8(fromBase64(result.smart)));
},
},
};
}

View File

@ -41,32 +41,34 @@ export interface ContractDetails extends ContractInfo {
* @see https://github.com/cosmwasm/wasmd/blob/master/x/wasm/client/rest/query.go#L19-L27
*/
export interface WasmModule extends LcdModule {
readonly listCodeInfo: () => Promise<readonly CodeInfo[]>;
/**
* Downloads the original wasm bytecode by code ID.
*
* Throws an error if no code with this id
*/
readonly getCode: (id: number) => Promise<CodeDetails>;
readonly listContractsByCodeId: (id: number) => Promise<readonly ContractInfo[]>;
/**
* Returns null when contract was not found at this address.
*/
readonly getContractInfo: (address: string) => Promise<ContractDetails | null>;
/**
* Returns all contract state.
* This is an empty array if no such contract, or contract has no data.
*/
readonly getAllContractState: (address: string) => Promise<readonly Model[]>;
/**
* Returns the data at the key if present (unknown decoded json),
* or null if no data at this (contract address, key) pair
*/
readonly queryContractRaw: (address: string, key: Uint8Array) => Promise<Uint8Array | null>;
/**
* Makes a smart query on the contract and parses the reponse as JSON.
* Throws error if no such contract exists, the query format is invalid or the response is invalid.
*/
readonly queryContractSmart: (address: string, query: object) => Promise<JsonObject>;
readonly wasm: {
readonly listCodeInfo: () => Promise<readonly CodeInfo[]>;
/**
* Downloads the original wasm bytecode by code ID.
*
* Throws an error if no code with this id
*/
readonly getCode: (id: number) => Promise<CodeDetails>;
readonly listContractsByCodeId: (id: number) => Promise<readonly ContractInfo[]>;
/**
* Returns null when contract was not found at this address.
*/
readonly getContractInfo: (address: string) => Promise<ContractDetails | null>;
/**
* Returns all contract state.
* This is an empty array if no such contract, or contract has no data.
*/
readonly getAllContractState: (address: string) => Promise<readonly Model[]>;
/**
* Returns the data at the key if present (unknown decoded json),
* or null if no data at this (contract address, key) pair
*/
readonly queryContractRaw: (address: string, key: Uint8Array) => Promise<Uint8Array | null>;
/**
* Makes a smart query on the contract and parses the reponse as JSON.
* Throws error if no such contract exists, the query format is invalid or the response is invalid.
*/
readonly queryContractSmart: (address: string, query: object) => Promise<JsonObject>;
};
}
export declare function setupWasmModule(base: LcdClient): WasmModule;

View File

@ -75,7 +75,7 @@ describe("CosmosClient", () => {
const openedClient = (client as unknown) as PrivateCosmWasmClient;
const blockLatestSpy = spyOn(openedClient.lcdClient, "blocksLatest").and.callThrough();
const authAccountsSpy = spyOn(openedClient.lcdClient, "authAccounts").and.callThrough();
const authAccountsSpy = spyOn(openedClient.lcdClient.auth, "account").and.callThrough();
const height1 = await client.getHeight();
expect(height1).toBeGreaterThan(0);

View File

@ -166,7 +166,7 @@ export class CosmosClient {
public async getHeight(): Promise<number> {
if (this.anyValidAddress) {
const { height } = await this.lcdClient.authAccounts(this.anyValidAddress);
const { height } = await this.lcdClient.auth.account(this.anyValidAddress);
return parseInt(height, 10);
} else {
// Note: this gets inefficient when blocks contain a lot of transactions since it
@ -207,7 +207,7 @@ export class CosmosClient {
}
public async getAccount(address: string): Promise<Account | undefined> {
const account = await this.lcdClient.authAccounts(address);
const account = await this.lcdClient.auth.account(address);
const value = account.result.value;
if (value.address === "") {
return undefined;

View File

@ -19,7 +19,7 @@ describe("auth", () => {
it("works for unused account without pubkey", async () => {
pendingWithoutWasmd();
const client = makeAuthClient(wasmd.endpoint);
const { height, result } = await client.authAccounts(unused.address);
const { height, result } = await client.auth.account(unused.address);
expect(height).toMatch(nonNegativeIntegerMatcher);
expect(result).toEqual({
type: "cosmos-sdk/Account",
@ -46,7 +46,7 @@ describe("auth", () => {
it("has correct pubkey for faucet", async () => {
pendingWithoutWasmd();
const client = makeAuthClient(wasmd.endpoint);
const { result } = await client.authAccounts(faucet.address);
const { result } = await client.auth.account(faucet.address);
expect(result.value).toEqual(
jasmine.objectContaining({
public_key: encodeBech32Pubkey(faucet.pubkey, "cosmospub"),
@ -59,7 +59,7 @@ describe("auth", () => {
pendingWithoutWasmd();
const client = makeAuthClient(wasmd.endpoint);
const nonExistentAccount = makeRandomAddress();
const { result } = await client.authAccounts(nonExistentAccount);
const { result } = await client.auth.account(nonExistentAccount);
expect(result).toEqual({
type: "cosmos-sdk/Account",
value: jasmine.objectContaining({ address: "" }),

View File

@ -20,18 +20,22 @@ export interface AuthAccountsResponse {
}
export interface AuthModule extends LcdModule {
readonly authAccounts: (address: string) => Promise<AuthAccountsResponse>;
readonly auth: {
readonly account: (address: string) => Promise<AuthAccountsResponse>;
};
}
export function setupAuthModule(base: LcdClient): AuthModule {
return {
authAccounts: async (address: string) => {
const path = `/auth/accounts/${address}`;
const responseData = await base.get(path);
if (responseData.result.type !== "cosmos-sdk/Account") {
throw new Error("Unexpected response data format");
}
return responseData as AuthAccountsResponse;
auth: {
account: async (address: string) => {
const path = `/auth/accounts/${address}`;
const responseData = await base.get(path);
if (responseData.result.type !== "cosmos-sdk/Account") {
throw new Error("Unexpected response data format");
}
return responseData as AuthAccountsResponse;
},
},
};
}

View File

@ -23,7 +23,7 @@ import {
import { StdFee } from "../types";
import { setupAuthModule } from "./auth";
import { TxsResponse } from "./base";
import { LcdApiArray, LcdClient, normalizeLcdApiArray } from "./lcdclient";
import { LcdApiArray, LcdClient, LcdModule, normalizeLcdApiArray } from "./lcdclient";
/** Deployed as part of scripts/wasmd/init.sh */
export const deployedErc20 = {
@ -79,8 +79,22 @@ describe("LcdClient", () => {
return response.result;
}
interface WasmModule extends Record<string, () => any> {
listCodeInfo: () => Promise<readonly CodeInfo[]>;
interface WasmModule extends LcdModule {
wasm: {
listCodeInfo: () => Promise<readonly CodeInfo[]>;
};
}
function setupWasmModule(base: LcdClient): WasmModule {
return {
wasm: {
listCodeInfo: async (): Promise<readonly CodeInfo[]> => {
const path = `/wasm/code`;
const responseData = (await base.get(path)) as WasmResponse<LcdApiArray<CodeInfo>>;
return normalizeLcdApiArray(unwrapWasmResponse(responseData));
},
},
};
}
it("works for no modules", async () => {
@ -90,18 +104,9 @@ describe("LcdClient", () => {
it("works for one module", async () => {
pendingWithoutWasmd();
function wasmClientRegisterer(base: LcdClient): WasmModule {
return {
listCodeInfo: async (): Promise<readonly CodeInfo[]> => {
const path = `/wasm/code`;
const responseData = (await base.get(path)) as WasmResponse<LcdApiArray<CodeInfo>>;
return normalizeLcdApiArray(unwrapWasmResponse(responseData));
},
};
}
const client = LcdClient.withModules({ apiUrl: wasmd.endpoint }, wasmClientRegisterer);
const codes = await client.listCodeInfo();
const client = LcdClient.withModules({ apiUrl: wasmd.endpoint }, setupWasmModule);
const codes = await client.wasm.listCodeInfo();
expect(codes.length).toBeGreaterThanOrEqual(3);
expect(codes[0].id).toEqual(deployedErc20.codeId);
expect(codes[0].data_hash).toEqual(deployedErc20.checksum.toUpperCase());
@ -111,15 +116,6 @@ describe("LcdClient", () => {
it("works for two modules", async () => {
pendingWithoutWasmd();
function registerWasmModule(base: LcdClient): WasmModule {
return {
listCodeInfo: async (): Promise<readonly CodeInfo[]> => {
const path = `/wasm/code`;
const responseData = (await base.get(path)) as WasmResponse<LcdApiArray<CodeInfo>>;
return normalizeLcdApiArray(unwrapWasmResponse(responseData));
},
};
}
interface TotalSupplyAllReponse {
readonly height: string;
@ -129,21 +125,23 @@ describe("LcdClient", () => {
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
function setupSupplyModule(base: LcdClient) {
return {
totalSupplyAll: async (): Promise<TotalSupplyAllReponse> => {
const path = `/supply/total`;
return (await base.get(path)) as TotalSupplyAllReponse;
supply: {
totalAll: async (): Promise<TotalSupplyAllReponse> => {
const path = `/supply/total`;
return (await base.get(path)) as TotalSupplyAllReponse;
},
},
};
}
const client = LcdClient.withModules({ apiUrl: wasmd.endpoint }, registerWasmModule, setupSupplyModule);
const codes = await client.listCodeInfo();
const client = LcdClient.withModules({ apiUrl: wasmd.endpoint }, setupWasmModule, setupSupplyModule);
const codes = await client.wasm.listCodeInfo();
expect(codes.length).toBeGreaterThanOrEqual(3);
expect(codes[0].id).toEqual(deployedErc20.codeId);
expect(codes[0].data_hash).toEqual(deployedErc20.checksum.toUpperCase());
expect(codes[0].builder).toEqual(deployedErc20.builder);
expect(codes[0].source).toEqual(deployedErc20.source);
const supply = await client.totalSupplyAll();
const supply = await client.supply.totalAll();
expect(supply).toEqual({
height: jasmine.stringMatching(/^[0-9]+$/),
result: [
@ -525,7 +523,7 @@ describe("LcdClient", () => {
};
const client = LcdClient.withModules({ apiUrl: wasmd.endpoint }, setupAuthModule);
const { account_number, sequence } = (await client.authAccounts(faucet.address)).result.value;
const { account_number, sequence } = (await client.auth.account(faucet.address)).result.value;
const signBytes = makeSignBytes([theMsg], fee, wasmd.chainId, memo, account_number, sequence);
const signature = await pen.sign(signBytes);
@ -578,9 +576,9 @@ describe("LcdClient", () => {
};
const client = LcdClient.withModules({ apiUrl: wasmd.endpoint }, setupAuthModule);
const { account_number: an1, sequence: sequence1 } = (await client.authAccounts(address1)).result.value;
const { account_number: an2, sequence: sequence2 } = (await client.authAccounts(address2)).result.value;
const { account_number: an3, sequence: sequence3 } = (await client.authAccounts(address3)).result.value;
const { account_number: an1, sequence: sequence1 } = (await client.auth.account(address1)).result.value;
const { account_number: an2, sequence: sequence2 } = (await client.auth.account(address2)).result.value;
const { account_number: an3, sequence: sequence3 } = (await client.auth.account(address3)).result.value;
const signBytes1 = makeSignBytes([theMsg], fee, wasmd.chainId, memo, an1, sequence1);
const signBytes2 = makeSignBytes([theMsg], fee, wasmd.chainId, memo, an2, sequence2);
@ -643,7 +641,7 @@ describe("LcdClient", () => {
};
const client = LcdClient.withModules({ apiUrl: wasmd.endpoint }, setupAuthModule);
const { account_number, sequence } = (await client.authAccounts(address1)).result.value;
const { account_number, sequence } = (await client.auth.account(address1)).result.value;
const signBytes = makeSignBytes([msg1, msg2], fee, wasmd.chainId, memo, account_number, sequence);
const signature1 = await account1.sign(signBytes);
@ -703,8 +701,8 @@ describe("LcdClient", () => {
};
const client = LcdClient.withModules({ apiUrl: wasmd.endpoint }, setupAuthModule);
const { account_number: an1, sequence: sequence1 } = (await client.authAccounts(address1)).result.value;
const { account_number: an2, sequence: sequence2 } = (await client.authAccounts(address2)).result.value;
const { account_number: an1, sequence: sequence1 } = (await client.auth.account(address1)).result.value;
const { account_number: an2, sequence: sequence2 } = (await client.auth.account(address2)).result.value;
const signBytes1 = makeSignBytes([msg2, msg1], fee, wasmd.chainId, memo, an1, sequence1);
const signBytes2 = makeSignBytes([msg2, msg1], fee, wasmd.chainId, memo, an2, sequence2);
@ -771,8 +769,8 @@ describe("LcdClient", () => {
};
const client = LcdClient.withModules({ apiUrl: wasmd.endpoint }, setupAuthModule);
const { account_number: an1, sequence: sequence1 } = (await client.authAccounts(address1)).result.value;
const { account_number: an2, sequence: sequence2 } = (await client.authAccounts(address2)).result.value;
const { account_number: an1, sequence: sequence1 } = (await client.auth.account(address1)).result.value;
const { account_number: an2, sequence: sequence2 } = (await client.auth.account(address2)).result.value;
const signBytes1 = makeSignBytes([msg1, msg2], fee, wasmd.chainId, memo, an1, sequence1);
const signBytes2 = makeSignBytes([msg1, msg2], fee, wasmd.chainId, memo, an2, sequence2);
@ -834,8 +832,8 @@ describe("LcdClient", () => {
};
const client = LcdClient.withModules({ apiUrl: wasmd.endpoint }, setupAuthModule);
const { account_number: an1, sequence: sequence1 } = (await client.authAccounts(address1)).result.value;
const { account_number: an2, sequence: sequence2 } = (await client.authAccounts(address2)).result.value;
const { account_number: an1, sequence: sequence1 } = (await client.auth.account(address1)).result.value;
const { account_number: an2, sequence: sequence2 } = (await client.auth.account(address2)).result.value;
const signBytes1 = makeSignBytes([msg2, msg1], fee, wasmd.chainId, memo, an1, sequence1);
const signBytes2 = makeSignBytes([msg2, msg1], fee, wasmd.chainId, memo, an2, sequence2);

View File

@ -20,7 +20,7 @@ export function normalizeLcdApiArray<T>(backend: LcdApiArray<T>): readonly T[] {
return backend || [];
}
export type LcdModule = Record<string, (...args: any[]) => any>;
export type LcdModule = Record<string, Record<string, (...args: any[]) => any>>;
type LcdModuleSetup<M extends LcdModule> = (base: LcdClient) => M;

View File

@ -3,12 +3,12 @@ import { LcdClient } from "./lcdclient";
import { setupSupplyModule } from "./supply";
describe("supply", () => {
describe("totalSupplyAll", () => {
describe("totalAll", () => {
it("works", async () => {
pendingWithoutWasmd();
const client = LcdClient.withModules({ apiUrl: wasmd.endpoint }, setupSupplyModule);
const supply = await client.totalSupplyAll();
const supply = await client.supply.totalAll();
expect(supply).toEqual({
height: jasmine.stringMatching(/^[0-9]+$/),
result: [
@ -25,12 +25,12 @@ describe("supply", () => {
});
});
describe("totalSupply", () => {
describe("total", () => {
it("works", async () => {
pendingWithoutWasmd();
const client = LcdClient.withModules({ apiUrl: wasmd.endpoint }, setupSupplyModule);
const supply = await client.totalSupply("ucosm");
const supply = await client.supply.total("ucosm");
expect(supply).toEqual({
height: jasmine.stringMatching(/^[0-9]+$/),
result: jasmine.stringMatching(/^[0-9]+$/),

View File

@ -13,17 +13,21 @@ export interface TotalSupplyReponse {
}
export interface SupplyModule extends LcdModule {
readonly totalSupplyAll: () => Promise<TotalSupplyAllReponse>;
readonly totalSupply: (denom: string) => Promise<TotalSupplyReponse>;
readonly supply: {
readonly totalAll: () => Promise<TotalSupplyAllReponse>;
readonly total: (denom: string) => Promise<TotalSupplyReponse>;
};
}
export function setupSupplyModule(base: LcdClient): SupplyModule {
return {
totalSupplyAll: async () => {
return base.get(`/supply/total`);
},
totalSupply: async (denom: string) => {
return base.get(`/supply/total/${denom}`);
supply: {
totalAll: async () => {
return base.get(`/supply/total`);
},
total: async (denom: string) => {
return base.get(`/supply/total/${denom}`);
},
},
};
}

View File

@ -35,7 +35,7 @@ describe("SigningCosmosClient", () => {
const openedClient = (client as unknown) as PrivateCosmWasmClient;
const blockLatestSpy = spyOn(openedClient.lcdClient, "blocksLatest").and.callThrough();
const authAccountsSpy = spyOn(openedClient.lcdClient, "authAccounts").and.callThrough();
const authAccountsSpy = spyOn(openedClient.lcdClient.auth, "account").and.callThrough();
const height = await client.getHeight();
expect(height).toBeGreaterThan(0);

View File

@ -17,6 +17,8 @@ export interface AuthAccountsResponse {
};
}
export interface AuthModule extends LcdModule {
readonly authAccounts: (address: string) => Promise<AuthAccountsResponse>;
readonly auth: {
readonly account: (address: string) => Promise<AuthAccountsResponse>;
};
}
export declare function setupAuthModule(base: LcdClient): AuthModule;

View File

@ -11,7 +11,7 @@ import {
/** Unfortunately, Cosmos SDK encodes empty arrays as null */
export declare type LcdApiArray<T> = readonly T[] | null;
export declare function normalizeLcdApiArray<T>(backend: LcdApiArray<T>): readonly T[];
export declare type LcdModule = Record<string, (...args: any[]) => any>;
export declare type LcdModule = Record<string, Record<string, (...args: any[]) => any>>;
declare type LcdModuleSetup<M extends LcdModule> = (base: LcdClient) => M;
export interface LcdClientBaseOptions {
readonly apiUrl: string;

View File

@ -10,7 +10,9 @@ export interface TotalSupplyReponse {
readonly result: string;
}
export interface SupplyModule extends LcdModule {
readonly totalSupplyAll: () => Promise<TotalSupplyAllReponse>;
readonly totalSupply: (denom: string) => Promise<TotalSupplyReponse>;
readonly supply: {
readonly totalAll: () => Promise<TotalSupplyAllReponse>;
readonly total: (denom: string) => Promise<TotalSupplyReponse>;
};
}
export declare function setupSupplyModule(base: LcdClient): SupplyModule;