diff --git a/packages/sdk38/src/cosmosclient.spec.ts b/packages/sdk38/src/cosmosclient.spec.ts index 28d57a6a..b41ae6f2 100644 --- a/packages/sdk38/src/cosmosclient.spec.ts +++ b/packages/sdk38/src/cosmosclient.spec.ts @@ -76,7 +76,7 @@ describe("CosmosClient", () => { const height1 = await client.getHeight(); expect(height1).toBeGreaterThan(0); - await client.getCodes(); // warm up the client + await client.getAccount(guest.address); // warm up the client const height2 = await client.getHeight(); expect(height2).toBeGreaterThan(0); @@ -85,7 +85,7 @@ describe("CosmosClient", () => { expect(height3).toEqual(height2 + 1); expect(blockLatestSpy).toHaveBeenCalledTimes(1); - expect(authAccountsSpy).toHaveBeenCalledTimes(2); + expect(authAccountsSpy).toHaveBeenCalledTimes(3); }); }); @@ -232,65 +232,4 @@ describe("CosmosClient", () => { expect(transactionHash).toMatch(/^[0-9A-F]{64}$/); }); }); - - describe("getContracts", () => { - it("works", async () => { - pendingWithoutWasmd(); - const client = new CosmosClient(wasmd.endpoint); - const result = await client.getContracts(1); - expect(result.length).toBeGreaterThanOrEqual(3); - const [hash, isa, jade] = result; - expect(hash).toEqual({ - address: "cosmos18vd8fpwxzck93qlwghaj6arh4p7c5n89uzcee5", - codeId: 1, - creator: faucet.address, - label: "HASH", - }); - expect(isa).toEqual({ - address: "cosmos1hqrdl6wstt8qzshwc6mrumpjk9338k0lr4dqxd", - codeId: 1, - creator: faucet.address, - label: "ISA", - }); - expect(jade).toEqual({ - address: "cosmos18r5szma8hm93pvx6lwpjwyxruw27e0k5uw835c", - codeId: 1, - creator: faucet.address, - label: "JADE", - }); - }); - }); - - describe("getContract", () => { - it("works for HASH instance", async () => { - pendingWithoutWasmd(); - const client = new CosmosClient(wasmd.endpoint); - const hash = await client.getContract("cosmos18vd8fpwxzck93qlwghaj6arh4p7c5n89uzcee5"); - expect(hash).toEqual({ - address: "cosmos18vd8fpwxzck93qlwghaj6arh4p7c5n89uzcee5", - codeId: 1, - creator: faucet.address, - label: "HASH", - initMsg: { - decimals: 5, - name: "Hash token", - symbol: "HASH", - initial_balances: jasmine.arrayContaining([ - { - address: faucet.address, - amount: "11", - }, - { - address: unused.address, - amount: "12812345", - }, - { - address: guest.address, - amount: "22004000000", - }, - ]), - }, - }); - }); - }); }); diff --git a/packages/sdk38/src/cosmosclient.ts b/packages/sdk38/src/cosmosclient.ts index 7960c82d..5a020430 100644 --- a/packages/sdk38/src/cosmosclient.ts +++ b/packages/sdk38/src/cosmosclient.ts @@ -5,7 +5,7 @@ import { Coin } from "./coins"; import { Log, parseLogs } from "./logs"; import { decodeBech32Pubkey } from "./pubkey"; import { BroadcastMode, RestClient } from "./restclient"; -import { CosmosSdkTx, JsonObject, PubKey, StdTx } from "./types"; +import { CosmosSdkTx, PubKey, StdTx } from "./types"; export interface GetNonceResult { readonly accountNumber: number; @@ -75,34 +75,6 @@ export interface SearchTxFilter { readonly maxHeight?: number; } -export interface Code { - readonly id: number; - /** Bech32 account address */ - readonly creator: string; - /** Hex-encoded sha256 hash of the code stored here */ - readonly checksum: string; - readonly source?: string; - readonly builder?: string; -} - -export interface CodeDetails extends Code { - /** The original wasm bytes */ - readonly data: Uint8Array; -} - -export interface Contract { - readonly address: string; - readonly codeId: number; - /** Bech32 account address */ - readonly creator: string; - readonly label: string; -} - -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; @@ -150,7 +122,6 @@ export class CosmosClient { /** Any address the chain considers valid (valid bech32 with proper prefix) */ protected anyValidAddress: string | undefined; - private readonly codesCache = new Map(); private chainId: string | undefined; /** @@ -318,102 +289,6 @@ export class CosmosClient { }; } - public async getCodes(): Promise { - const result = await this.restClient.listCodeInfo(); - return result.map( - (entry): Code => { - this.anyValidAddress = entry.creator; - return { - id: entry.id, - creator: entry.creator, - checksum: Encoding.toHex(Encoding.fromHex(entry.data_hash)), - source: entry.source || undefined, - builder: entry.builder || undefined, - }; - }, - ); - } - - public async getCodeDetails(codeId: number): Promise { - const cached = this.codesCache.get(codeId); - if (cached) return cached; - - const getCodeResult = await this.restClient.getCode(codeId); - const codeDetails: CodeDetails = { - id: getCodeResult.id, - creator: getCodeResult.creator, - checksum: Encoding.toHex(Encoding.fromHex(getCodeResult.data_hash)), - source: getCodeResult.source || undefined, - builder: getCodeResult.builder || undefined, - data: Encoding.fromBase64(getCodeResult.data), - }; - this.codesCache.set(codeId, codeDetails); - return codeDetails; - } - - public async getContracts(codeId: number): Promise { - const result = await this.restClient.listContractsByCodeId(codeId); - return result.map( - (entry): Contract => ({ - address: entry.address, - codeId: entry.code_id, - creator: entry.creator, - label: entry.label, - }), - ); - } - - /** - * Throws an error if no contract was found at the address - */ - public async getContract(address: string): Promise { - const result = await this.restClient.getContractInfo(address); - if (!result) throw new Error(`No contract found at address "${address}"`); - return { - address: result.address, - codeId: result.code_id, - creator: result.creator, - label: result.label, - initMsg: result.init_msg, - }; - } - - /** - * Returns the data at the key if present (raw contract dependent storage data) - * or null if no data at this key. - * - * Promise is rejected when contract does not exist. - */ - public async queryContractRaw(address: string, key: Uint8Array): Promise { - // just test contract existence - const _info = await this.getContract(address); - - return this.restClient.queryContractRaw(address, key); - } - - /** - * Makes a smart query on the contract, returns the parsed JSON document. - * - * Promise is rejected when contract does not exist. - * Promise is rejected for invalid query format. - * Promise is rejected for invalid response format. - */ - public async queryContractSmart(address: string, queryMsg: object): Promise { - try { - return await this.restClient.queryContractSmart(address, queryMsg); - } catch (error) { - if (error instanceof Error) { - if (error.message.startsWith("not found: contract")) { - throw new Error(`No contract found at address "${address}"`); - } else { - throw error; - } - } else { - throw error; - } - } - } - private async txsQuery(query: string): Promise { // TODO: we need proper pagination support const limit = 100; diff --git a/packages/sdk38/src/index.ts b/packages/sdk38/src/index.ts index 57e3091b..7e86fdc9 100644 --- a/packages/sdk38/src/index.ts +++ b/packages/sdk38/src/index.ts @@ -8,10 +8,6 @@ export { Account, Block, BlockHeader, - Code, - CodeDetails, - Contract, - ContractDetails, CosmosClient, GetNonceResult, IndexedTx, diff --git a/packages/sdk38/src/restclient.ts b/packages/sdk38/src/restclient.ts index cb6316e9..a0d07624 100644 --- a/packages/sdk38/src/restclient.ts +++ b/packages/sdk38/src/restclient.ts @@ -2,9 +2,7 @@ import { Encoding, isNonNullObject } from "@iov/encoding"; import axios, { AxiosError, AxiosInstance } from "axios"; import { Coin } from "./coins"; -import { CosmosSdkTx, JsonObject, Model, parseWasmData, StdTx, WasmData } from "./types"; - -const { fromBase64, fromUtf8, toHex, toUtf8 } = Encoding; +import { CosmosSdkTx, StdTx } from "./types"; export interface CosmosSdkAccount { /** Bech32 account address */ @@ -210,13 +208,6 @@ type RestClientResponse = | WasmResponse | WasmResponse; -/** Unfortunately, Cosmos SDK encodes empty arrays as null */ -type CosmosSdkArray = ReadonlyArray | null; - -function normalizeArray(backend: CosmosSdkArray): ReadonlyArray { - return backend || []; -} - /** * The mode used to send transaction * @@ -231,17 +222,6 @@ export enum BroadcastMode { Async = "async", } -function isWasmError(resp: WasmResponse): resp is WasmError { - return (resp as WasmError).error !== undefined; -} - -function unwrapWasmResponse(response: WasmResponse): T { - if (isWasmError(response)) { - throw new Error(response.error); - } - return response.result; -} - // We want to get message data from 500 errors // https://stackoverflow.com/questions/56577124/how-to-handle-500-error-message-with-axios // this should be chained to catch one error and throw a more informative one @@ -391,67 +371,4 @@ export class RestClient { } return responseData as PostTxsResponse; } - - // The /wasm endpoints - - // wasm rest queries are listed here: https://github.com/cosmwasm/wasmd/blob/master/x/wasm/client/rest/query.go#L19-L27 - public async listCodeInfo(): Promise { - const path = `/wasm/code`; - const responseData = (await this.get(path)) as WasmResponse>; - return normalizeArray(unwrapWasmResponse(responseData)); - } - - // this will download the original wasm bytecode by code id - // throws error if no code with this id - public async getCode(id: number): Promise { - const path = `/wasm/code/${id}`; - const responseData = (await this.get(path)) as WasmResponse; - return unwrapWasmResponse(responseData); - } - - public async listContractsByCodeId(id: number): Promise { - const path = `/wasm/code/${id}/contracts`; - const responseData = (await this.get(path)) as WasmResponse>; - return normalizeArray(unwrapWasmResponse(responseData)); - } - - /** - * Returns null when contract was not found at this address. - */ - public async getContractInfo(address: string): Promise { - const path = `/wasm/contract/${address}`; - const response = (await this.get(path)) as WasmResponse; - return unwrapWasmResponse(response); - } - - // Returns all contract state. - // This is an empty array if no such contract, or contract has no data. - public async getAllContractState(address: string): Promise { - const path = `/wasm/contract/${address}/state`; - const responseData = (await this.get(path)) as WasmResponse>; - return normalizeArray(unwrapWasmResponse(responseData)).map(parseWasmData); - } - - // Returns the data at the key if present (unknown decoded json), - // or null if no data at this (contract address, key) pair - public async queryContractRaw(address: string, key: Uint8Array): Promise { - const hexKey = toHex(key); - const path = `/wasm/contract/${address}/raw/${hexKey}?encoding=hex`; - const responseData = (await this.get(path)) as WasmResponse; - const data = unwrapWasmResponse(responseData); - return data.length === 0 ? null : fromBase64(data[0].val); - } - - /** - * 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. - */ - public async queryContractSmart(address: string, query: object): Promise { - const encoded = toHex(toUtf8(JSON.stringify(query))); - const path = `/wasm/contract/${address}/smart/${encoded}?encoding=hex`; - const responseData = (await this.get(path)) as WasmResponse; - 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))); - } } diff --git a/packages/sdk38/src/types.ts b/packages/sdk38/src/types.ts index 0db122f9..476cb555 100644 --- a/packages/sdk38/src/types.ts +++ b/packages/sdk38/src/types.ts @@ -1,9 +1,5 @@ -import { Encoding } from "@iov/encoding"; - import { Coin } from "./coins"; -const { fromBase64, fromHex } = Encoding; - /** An Amino/Cosmos SDK StdTx */ export interface StdTx { readonly msg: ReadonlyArray; @@ -75,29 +71,3 @@ export const pubkeyType = { }; export const pubkeyTypes: readonly string[] = [pubkeyType.secp256k1, pubkeyType.ed25519, pubkeyType.sr25519]; - -export interface WasmData { - // key is hex-encoded - readonly key: string; - // value is base64 encoded - readonly val: string; -} - -// Model is a parsed WasmData object -export interface Model { - readonly key: Uint8Array; - readonly val: Uint8Array; -} - -export function parseWasmData({ key, val }: WasmData): Model { - return { - key: fromHex(key), - val: fromBase64(val), - }; -} - -/** - * An object containing a parsed JSON document. The result of JSON.parse(). - * This doen't privide any type safety over `any` but expresses intent in the code. - */ -export type JsonObject = any; diff --git a/packages/sdk38/types/cosmosclient.d.ts b/packages/sdk38/types/cosmosclient.d.ts index 0dcc72bb..0af6120a 100644 --- a/packages/sdk38/types/cosmosclient.d.ts +++ b/packages/sdk38/types/cosmosclient.d.ts @@ -1,7 +1,7 @@ import { Coin } from "./coins"; import { Log } from "./logs"; import { BroadcastMode, RestClient } from "./restclient"; -import { CosmosSdkTx, JsonObject, PubKey, StdTx } from "./types"; +import { CosmosSdkTx, PubKey, StdTx } from "./types"; export interface GetNonceResult { readonly accountNumber: number; readonly sequence: number; @@ -48,30 +48,6 @@ export interface SearchTxFilter { readonly minHeight?: number; readonly maxHeight?: number; } -export interface Code { - readonly id: number; - /** Bech32 account address */ - readonly creator: string; - /** Hex-encoded sha256 hash of the code stored here */ - readonly checksum: string; - readonly source?: string; - readonly builder?: string; -} -export interface CodeDetails extends Code { - /** The original wasm bytes */ - readonly data: Uint8Array; -} -export interface Contract { - readonly address: string; - readonly codeId: number; - /** Bech32 account address */ - readonly creator: string; - readonly label: string; -} -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; @@ -114,7 +90,6 @@ export declare class CosmosClient { protected readonly restClient: RestClient; /** Any address the chain considers valid (valid bech32 with proper prefix) */ protected anyValidAddress: string | undefined; - private readonly codesCache; private chainId; /** * Creates a new client to interact with a CosmWasm blockchain. @@ -149,27 +124,5 @@ export declare class CosmosClient { getBlock(height?: number): Promise; searchTx(query: SearchTxQuery, filter?: SearchTxFilter): Promise; postTx(tx: StdTx): Promise; - getCodes(): Promise; - getCodeDetails(codeId: number): Promise; - getContracts(codeId: number): Promise; - /** - * Throws an error if no contract was found at the address - */ - getContract(address: string): Promise; - /** - * Returns the data at the key if present (raw contract dependent storage data) - * or null if no data at this key. - * - * Promise is rejected when contract does not exist. - */ - queryContractRaw(address: string, key: Uint8Array): Promise; - /** - * Makes a smart query on the contract, returns the parsed JSON document. - * - * Promise is rejected when contract does not exist. - * Promise is rejected for invalid query format. - * Promise is rejected for invalid response format. - */ - queryContractSmart(address: string, queryMsg: object): Promise; private txsQuery; } diff --git a/packages/sdk38/types/index.d.ts b/packages/sdk38/types/index.d.ts index 829a4403..7e10a5ff 100644 --- a/packages/sdk38/types/index.d.ts +++ b/packages/sdk38/types/index.d.ts @@ -6,10 +6,6 @@ export { Account, Block, BlockHeader, - Code, - CodeDetails, - Contract, - ContractDetails, CosmosClient, GetNonceResult, IndexedTx, diff --git a/packages/sdk38/types/restclient.d.ts b/packages/sdk38/types/restclient.d.ts index 5d5deea4..b93175d3 100644 --- a/packages/sdk38/types/restclient.d.ts +++ b/packages/sdk38/types/restclient.d.ts @@ -1,5 +1,5 @@ import { Coin } from "./coins"; -import { CosmosSdkTx, JsonObject, Model, StdTx } from "./types"; +import { CosmosSdkTx, StdTx } from "./types"; export interface CosmosSdkAccount { /** Bech32 account address */ readonly address: string; @@ -213,19 +213,5 @@ export declare class RestClient { * @param tx a signed transaction as StdTx (i.e. not wrapped in type/value container) */ postTx(tx: StdTx): Promise; - listCodeInfo(): Promise; - getCode(id: number): Promise; - listContractsByCodeId(id: number): Promise; - /** - * Returns null when contract was not found at this address. - */ - getContractInfo(address: string): Promise; - getAllContractState(address: string): Promise; - queryContractRaw(address: string, key: Uint8Array): Promise; - /** - * 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. - */ - queryContractSmart(address: string, query: object): Promise; } export {}; diff --git a/packages/sdk38/types/types.d.ts b/packages/sdk38/types/types.d.ts index 8083027c..bb8390ed 100644 --- a/packages/sdk38/types/types.d.ts +++ b/packages/sdk38/types/types.d.ts @@ -48,17 +48,3 @@ export declare const pubkeyType: { sr25519: "tendermint/PubKeySr25519"; }; export declare const pubkeyTypes: readonly string[]; -export interface WasmData { - readonly key: string; - readonly val: string; -} -export interface Model { - readonly key: Uint8Array; - readonly val: Uint8Array; -} -export declare function parseWasmData({ key, val }: WasmData): Model; -/** - * An object containing a parsed JSON document. The result of JSON.parse(). - * This doen't privide any type safety over `any` but expresses intent in the code. - */ -export declare type JsonObject = any;