Split CosmWasmClient and SigningCosmWasmClient
This commit is contained in:
parent
b6b29562cb
commit
6b522e5b4d
@ -73,7 +73,7 @@ export class CosmWasmConnection implements BlockchainConnection {
|
||||
addressPrefix: CosmosAddressBech32Prefix,
|
||||
tokens: TokenConfiguration,
|
||||
): Promise<CosmWasmConnection> {
|
||||
const cosmWasmClient = CosmWasmClient.makeReadOnly(url);
|
||||
const cosmWasmClient = new CosmWasmClient(url);
|
||||
const chainData = await this.initialize(cosmWasmClient);
|
||||
return new CosmWasmConnection(cosmWasmClient, chainData, addressPrefix, tokens);
|
||||
}
|
||||
|
||||
@ -8,24 +8,21 @@ import { makeSignBytes, marshalTx } from "./encoding";
|
||||
import { findAttribute } from "./logs";
|
||||
import { Secp256k1Pen } from "./pen";
|
||||
import { RestClient } from "./restclient";
|
||||
import { SigningCosmWasmClient } from "./signingcosmwasmclient";
|
||||
import cosmoshub from "./testdata/cosmoshub.json";
|
||||
import { getRandomizedHackatom, makeRandomAddress, tendermintIdMatcher } from "./testutils.spec";
|
||||
import { Coin, CosmosSdkTx, MsgSend, StdFee } from "./types";
|
||||
import {
|
||||
cosmosEnabled,
|
||||
getRandomizedHackatom,
|
||||
makeRandomAddress,
|
||||
pendingWithoutCosmos,
|
||||
tendermintIdMatcher,
|
||||
} from "./testutils.spec";
|
||||
import { CosmosSdkTx, MsgSend, StdFee } from "./types";
|
||||
|
||||
const { fromAscii, fromUtf8, toAscii } = Encoding;
|
||||
|
||||
const httpUrl = "http://localhost:1317";
|
||||
|
||||
function cosmosEnabled(): boolean {
|
||||
return !!process.env.COSMOS_ENABLED;
|
||||
}
|
||||
|
||||
function pendingWithoutCosmos(): void {
|
||||
if (!cosmosEnabled()) {
|
||||
return pending("Set COSMOS_ENABLED to enable Cosmos node-based tests");
|
||||
}
|
||||
}
|
||||
|
||||
const faucet = {
|
||||
mnemonic:
|
||||
"economy stock theory fatal elder harbor betray wasp final emotion task crumble siren bottom lizard educate guess current outdoor pair theory focus wife stone",
|
||||
@ -51,7 +48,7 @@ interface HackatomInstance {
|
||||
describe("CosmWasmClient", () => {
|
||||
describe("makeReadOnly", () => {
|
||||
it("can be constructed", () => {
|
||||
const client = CosmWasmClient.makeReadOnly(httpUrl);
|
||||
const client = new CosmWasmClient(httpUrl);
|
||||
expect(client).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@ -59,7 +56,7 @@ describe("CosmWasmClient", () => {
|
||||
describe("chainId", () => {
|
||||
it("works", async () => {
|
||||
pendingWithoutCosmos();
|
||||
const client = CosmWasmClient.makeReadOnly(httpUrl);
|
||||
const client = new CosmWasmClient(httpUrl);
|
||||
expect(await client.chainId()).toEqual("testing");
|
||||
});
|
||||
});
|
||||
@ -67,7 +64,7 @@ describe("CosmWasmClient", () => {
|
||||
describe("getNonce", () => {
|
||||
it("works", async () => {
|
||||
pendingWithoutCosmos();
|
||||
const client = CosmWasmClient.makeReadOnly(httpUrl);
|
||||
const client = new CosmWasmClient(httpUrl);
|
||||
expect(await client.getNonce(unusedAccount.address)).toEqual({
|
||||
accountNumber: 5,
|
||||
sequence: 0,
|
||||
@ -76,7 +73,7 @@ describe("CosmWasmClient", () => {
|
||||
|
||||
it("throws for missing accounts", async () => {
|
||||
pendingWithoutCosmos();
|
||||
const client = CosmWasmClient.makeReadOnly(httpUrl);
|
||||
const client = new CosmWasmClient(httpUrl);
|
||||
const missing = makeRandomAddress();
|
||||
await client.getNonce(missing).then(
|
||||
() => fail("this must not succeed"),
|
||||
@ -88,7 +85,7 @@ describe("CosmWasmClient", () => {
|
||||
describe("getAccount", () => {
|
||||
it("works", async () => {
|
||||
pendingWithoutCosmos();
|
||||
const client = CosmWasmClient.makeReadOnly(httpUrl);
|
||||
const client = new CosmWasmClient(httpUrl);
|
||||
expect(await client.getAccount(unusedAccount.address)).toEqual({
|
||||
address: unusedAccount.address,
|
||||
account_number: 5,
|
||||
@ -103,7 +100,7 @@ describe("CosmWasmClient", () => {
|
||||
|
||||
it("returns undefined for missing accounts", async () => {
|
||||
pendingWithoutCosmos();
|
||||
const client = CosmWasmClient.makeReadOnly(httpUrl);
|
||||
const client = new CosmWasmClient(httpUrl);
|
||||
const missing = makeRandomAddress();
|
||||
expect(await client.getAccount(missing)).toBeUndefined();
|
||||
});
|
||||
@ -112,7 +109,7 @@ describe("CosmWasmClient", () => {
|
||||
describe("getBlock", () => {
|
||||
it("works for latest block", async () => {
|
||||
pendingWithoutCosmos();
|
||||
const client = CosmWasmClient.makeReadOnly(httpUrl);
|
||||
const client = new CosmWasmClient(httpUrl);
|
||||
const response = await client.getBlock();
|
||||
|
||||
// id
|
||||
@ -132,7 +129,7 @@ describe("CosmWasmClient", () => {
|
||||
|
||||
it("works for block by height", async () => {
|
||||
pendingWithoutCosmos();
|
||||
const client = CosmWasmClient.makeReadOnly(httpUrl);
|
||||
const client = new CosmWasmClient(httpUrl);
|
||||
const height = parseInt((await client.getBlock()).block.header.height, 10);
|
||||
const response = await client.getBlock(height - 1);
|
||||
|
||||
@ -155,7 +152,7 @@ describe("CosmWasmClient", () => {
|
||||
describe("getIdentifier", () => {
|
||||
it("works", async () => {
|
||||
pendingWithoutCosmos();
|
||||
const client = CosmWasmClient.makeReadOnly(httpUrl);
|
||||
const client = new CosmWasmClient(httpUrl);
|
||||
expect(await client.getIdentifier(cosmoshub.tx)).toEqual(cosmoshub.id);
|
||||
});
|
||||
});
|
||||
@ -164,7 +161,7 @@ describe("CosmWasmClient", () => {
|
||||
it("works", async () => {
|
||||
pendingWithoutCosmos();
|
||||
const pen = await Secp256k1Pen.fromMnemonic(faucet.mnemonic);
|
||||
const client = CosmWasmClient.makeReadOnly(httpUrl);
|
||||
const client = new CosmWasmClient(httpUrl);
|
||||
|
||||
const memo = "My first contract on chain";
|
||||
const sendMsg: MsgSend = {
|
||||
@ -222,7 +219,7 @@ describe("CosmWasmClient", () => {
|
||||
beforeAll(async () => {
|
||||
if (cosmosEnabled()) {
|
||||
const pen = await Secp256k1Pen.fromMnemonic(faucet.mnemonic);
|
||||
const client = CosmWasmClient.makeWritable(httpUrl, faucet.address, signBytes => pen.sign(signBytes));
|
||||
const client = new SigningCosmWasmClient(httpUrl, faucet.address, signBytes => pen.sign(signBytes));
|
||||
|
||||
const recipient = makeRandomAddress();
|
||||
const transferAmount = [
|
||||
@ -248,7 +245,7 @@ describe("CosmWasmClient", () => {
|
||||
it("can search by ID", async () => {
|
||||
pendingWithoutCosmos();
|
||||
assert(posted, "value must be set in beforeAll()");
|
||||
const client = CosmWasmClient.makeReadOnly(httpUrl);
|
||||
const client = new CosmWasmClient(httpUrl);
|
||||
const result = await client.searchTx({ id: posted.hash });
|
||||
expect(result.length).toEqual(1);
|
||||
expect(result[0]).toEqual(
|
||||
@ -262,7 +259,7 @@ describe("CosmWasmClient", () => {
|
||||
|
||||
it("can search by ID (non existent)", async () => {
|
||||
pendingWithoutCosmos();
|
||||
const client = CosmWasmClient.makeReadOnly(httpUrl);
|
||||
const client = new CosmWasmClient(httpUrl);
|
||||
const nonExistentId = "0000000000000000000000000000000000000000000000000000000000000000";
|
||||
const result = await client.searchTx({ id: nonExistentId });
|
||||
expect(result.length).toEqual(0);
|
||||
@ -271,7 +268,7 @@ describe("CosmWasmClient", () => {
|
||||
it("can search by height", async () => {
|
||||
pendingWithoutCosmos();
|
||||
assert(posted, "value must be set in beforeAll()");
|
||||
const client = CosmWasmClient.makeReadOnly(httpUrl);
|
||||
const client = new CosmWasmClient(httpUrl);
|
||||
const result = await client.searchTx({ height: posted.height });
|
||||
expect(result.length).toEqual(1);
|
||||
expect(result[0]).toEqual(
|
||||
@ -286,7 +283,7 @@ describe("CosmWasmClient", () => {
|
||||
it("can search by sender", async () => {
|
||||
pendingWithoutCosmos();
|
||||
assert(posted, "value must be set in beforeAll()");
|
||||
const client = CosmWasmClient.makeReadOnly(httpUrl);
|
||||
const client = new CosmWasmClient(httpUrl);
|
||||
const result = await client.searchTx({ sentFromOrTo: posted.sender });
|
||||
expect(result.length).toBeGreaterThanOrEqual(1);
|
||||
expect(result[result.length - 1]).toEqual(
|
||||
@ -301,7 +298,7 @@ describe("CosmWasmClient", () => {
|
||||
it("can search by recipient", async () => {
|
||||
pendingWithoutCosmos();
|
||||
assert(posted, "value must be set in beforeAll()");
|
||||
const client = CosmWasmClient.makeReadOnly(httpUrl);
|
||||
const client = new CosmWasmClient(httpUrl);
|
||||
const result = await client.searchTx({ sentFromOrTo: posted.recipient });
|
||||
expect(result.length).toBeGreaterThanOrEqual(1);
|
||||
expect(result[result.length - 1]).toEqual(
|
||||
@ -314,141 +311,6 @@ describe("CosmWasmClient", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("upload", () => {
|
||||
it("works", async () => {
|
||||
pendingWithoutCosmos();
|
||||
const pen = await Secp256k1Pen.fromMnemonic(faucet.mnemonic);
|
||||
const client = CosmWasmClient.makeWritable(httpUrl, faucet.address, signBytes => pen.sign(signBytes));
|
||||
const codeId = await client.upload(getRandomizedHackatom());
|
||||
expect(codeId).toBeGreaterThanOrEqual(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe("instantiate", () => {
|
||||
it("works with transfer amount", async () => {
|
||||
pendingWithoutCosmos();
|
||||
const pen = await Secp256k1Pen.fromMnemonic(faucet.mnemonic);
|
||||
const client = CosmWasmClient.makeWritable(httpUrl, faucet.address, signBytes => pen.sign(signBytes));
|
||||
const codeId = await client.upload(getRandomizedHackatom());
|
||||
|
||||
const transferAmount: readonly Coin[] = [
|
||||
{
|
||||
amount: "1234",
|
||||
denom: "ucosm",
|
||||
},
|
||||
{
|
||||
amount: "321",
|
||||
denom: "ustake",
|
||||
},
|
||||
];
|
||||
const beneficiaryAddress = makeRandomAddress();
|
||||
const contractAddress = await client.instantiate(
|
||||
codeId,
|
||||
{
|
||||
verifier: faucet.address,
|
||||
beneficiary: beneficiaryAddress,
|
||||
},
|
||||
"Let's see",
|
||||
transferAmount,
|
||||
);
|
||||
|
||||
const rest = new RestClient(httpUrl);
|
||||
const balance = (await rest.authAccounts(contractAddress)).result.value.coins;
|
||||
expect(balance).toEqual(transferAmount);
|
||||
});
|
||||
|
||||
it("can instantiate one code multiple times", async () => {
|
||||
pendingWithoutCosmos();
|
||||
const pen = await Secp256k1Pen.fromMnemonic(faucet.mnemonic);
|
||||
const client = CosmWasmClient.makeWritable(httpUrl, faucet.address, signBytes => pen.sign(signBytes));
|
||||
const codeId = await client.upload(getRandomizedHackatom());
|
||||
|
||||
const contractAddress1 = await client.instantiate(codeId, {
|
||||
verifier: faucet.address,
|
||||
beneficiary: makeRandomAddress(),
|
||||
});
|
||||
const contractAddress2 = await client.instantiate(codeId, {
|
||||
verifier: faucet.address,
|
||||
beneficiary: makeRandomAddress(),
|
||||
});
|
||||
expect(contractAddress1).not.toEqual(contractAddress2);
|
||||
});
|
||||
});
|
||||
|
||||
describe("execute", () => {
|
||||
it("works", async () => {
|
||||
pendingWithoutCosmos();
|
||||
const pen = await Secp256k1Pen.fromMnemonic(faucet.mnemonic);
|
||||
const client = CosmWasmClient.makeWritable(httpUrl, faucet.address, signBytes => pen.sign(signBytes));
|
||||
const codeId = await client.upload(getRandomizedHackatom());
|
||||
|
||||
// instantiate
|
||||
const transferAmount: readonly Coin[] = [
|
||||
{
|
||||
amount: "233444",
|
||||
denom: "ucosm",
|
||||
},
|
||||
{
|
||||
amount: "5454",
|
||||
denom: "ustake",
|
||||
},
|
||||
];
|
||||
const beneficiaryAddress = makeRandomAddress();
|
||||
const contractAddress = await client.instantiate(
|
||||
codeId,
|
||||
{
|
||||
verifier: faucet.address,
|
||||
beneficiary: beneficiaryAddress,
|
||||
},
|
||||
undefined,
|
||||
transferAmount,
|
||||
);
|
||||
|
||||
// execute
|
||||
const result = await client.execute(contractAddress, {}, undefined);
|
||||
const [firstLog] = result.logs;
|
||||
expect(firstLog.log).toEqual(`released funds to ${beneficiaryAddress}`);
|
||||
|
||||
// Verify token transfer from contract to beneficiary
|
||||
const rest = new RestClient(httpUrl);
|
||||
const beneficiaryBalance = (await rest.authAccounts(beneficiaryAddress)).result.value.coins;
|
||||
expect(beneficiaryBalance).toEqual(transferAmount);
|
||||
const contractBalance = (await rest.authAccounts(contractAddress)).result.value.coins;
|
||||
expect(contractBalance).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("sendTokens", () => {
|
||||
it("works", async () => {
|
||||
pendingWithoutCosmos();
|
||||
const pen = await Secp256k1Pen.fromMnemonic(faucet.mnemonic);
|
||||
const client = CosmWasmClient.makeWritable(httpUrl, faucet.address, signBytes => pen.sign(signBytes));
|
||||
|
||||
// instantiate
|
||||
const transferAmount: readonly Coin[] = [
|
||||
{
|
||||
amount: "7890",
|
||||
denom: "ucosm",
|
||||
},
|
||||
];
|
||||
const beneficiaryAddress = makeRandomAddress();
|
||||
|
||||
// no tokens here
|
||||
const before = await client.getAccount(beneficiaryAddress);
|
||||
expect(before).toBeUndefined();
|
||||
|
||||
// send
|
||||
const result = await client.sendTokens(beneficiaryAddress, transferAmount, "for dinner");
|
||||
const [firstLog] = result.logs;
|
||||
expect(firstLog).toBeTruthy();
|
||||
|
||||
// got tokens
|
||||
const after = await client.getAccount(beneficiaryAddress);
|
||||
assert(after);
|
||||
expect(after.coins).toEqual(transferAmount);
|
||||
});
|
||||
});
|
||||
|
||||
describe("queryContractRaw", () => {
|
||||
const configKey = toAscii("config");
|
||||
const otherKey = toAscii("this_does_not_exist");
|
||||
@ -458,7 +320,7 @@ describe("CosmWasmClient", () => {
|
||||
if (cosmosEnabled()) {
|
||||
pendingWithoutCosmos();
|
||||
const pen = await Secp256k1Pen.fromMnemonic(faucet.mnemonic);
|
||||
const client = CosmWasmClient.makeWritable(httpUrl, faucet.address, signBytes => pen.sign(signBytes));
|
||||
const client = new SigningCosmWasmClient(httpUrl, faucet.address, signBytes => pen.sign(signBytes));
|
||||
const codeId = await client.upload(getRandomizedHackatom());
|
||||
const initMsg = { verifier: makeRandomAddress(), beneficiary: makeRandomAddress() };
|
||||
const contractAddress = await client.instantiate(codeId, initMsg);
|
||||
@ -470,7 +332,7 @@ describe("CosmWasmClient", () => {
|
||||
pendingWithoutCosmos();
|
||||
assert(contract);
|
||||
|
||||
const client = CosmWasmClient.makeReadOnly(httpUrl);
|
||||
const client = new CosmWasmClient(httpUrl);
|
||||
const raw = await client.queryContractRaw(contract.address, configKey);
|
||||
assert(raw, "must get result");
|
||||
expect(JSON.parse(fromUtf8(raw))).toEqual({
|
||||
@ -484,7 +346,7 @@ describe("CosmWasmClient", () => {
|
||||
pendingWithoutCosmos();
|
||||
assert(contract);
|
||||
|
||||
const client = CosmWasmClient.makeReadOnly(httpUrl);
|
||||
const client = new CosmWasmClient(httpUrl);
|
||||
const raw = await client.queryContractRaw(contract.address, otherKey);
|
||||
expect(raw).toBeNull();
|
||||
});
|
||||
@ -494,7 +356,7 @@ describe("CosmWasmClient", () => {
|
||||
assert(contract);
|
||||
|
||||
const nonExistentAddress = makeRandomAddress();
|
||||
const client = CosmWasmClient.makeReadOnly(httpUrl);
|
||||
const client = new CosmWasmClient(httpUrl);
|
||||
await client.queryContractRaw(nonExistentAddress, configKey).then(
|
||||
() => fail("must not succeed"),
|
||||
error => expect(error).toMatch(`No contract found at address "${nonExistentAddress}"`),
|
||||
@ -509,7 +371,7 @@ describe("CosmWasmClient", () => {
|
||||
if (cosmosEnabled()) {
|
||||
pendingWithoutCosmos();
|
||||
const pen = await Secp256k1Pen.fromMnemonic(faucet.mnemonic);
|
||||
const client = CosmWasmClient.makeWritable(httpUrl, faucet.address, signBytes => pen.sign(signBytes));
|
||||
const client = new SigningCosmWasmClient(httpUrl, faucet.address, signBytes => pen.sign(signBytes));
|
||||
const codeId = await client.upload(getRandomizedHackatom());
|
||||
const initMsg = { verifier: makeRandomAddress(), beneficiary: makeRandomAddress() };
|
||||
const contractAddress = await client.instantiate(codeId, initMsg);
|
||||
@ -521,7 +383,7 @@ describe("CosmWasmClient", () => {
|
||||
pendingWithoutCosmos();
|
||||
assert(contract);
|
||||
|
||||
const client = CosmWasmClient.makeReadOnly(httpUrl);
|
||||
const client = new CosmWasmClient(httpUrl);
|
||||
const verifier = await client.queryContractSmart(contract.address, { verifier: {} });
|
||||
expect(fromAscii(verifier)).toEqual(contract.initMsg.verifier);
|
||||
});
|
||||
@ -530,7 +392,7 @@ describe("CosmWasmClient", () => {
|
||||
pendingWithoutCosmos();
|
||||
assert(contract);
|
||||
|
||||
const client = CosmWasmClient.makeReadOnly(httpUrl);
|
||||
const client = new CosmWasmClient(httpUrl);
|
||||
await client.queryContractSmart(contract.address, { broken: {} }).then(
|
||||
() => fail("must not succeed"),
|
||||
error => expect(error).toMatch(/Error parsing QueryMsg/i),
|
||||
@ -541,7 +403,7 @@ describe("CosmWasmClient", () => {
|
||||
pendingWithoutCosmos();
|
||||
|
||||
const nonExistentAddress = makeRandomAddress();
|
||||
const client = CosmWasmClient.makeReadOnly(httpUrl);
|
||||
const client = new CosmWasmClient(httpUrl);
|
||||
await client.queryContractSmart(nonExistentAddress, { verifier: {} }).then(
|
||||
() => fail("must not succeed"),
|
||||
error => expect(error).toMatch(`No contract found at address "${nonExistentAddress}"`),
|
||||
|
||||
@ -1,59 +1,9 @@
|
||||
import { Sha256 } from "@iov/crypto";
|
||||
import { Encoding } from "@iov/encoding";
|
||||
|
||||
import { makeSignBytes, marshalTx } from "./encoding";
|
||||
import { findAttribute, Log, parseLogs } from "./logs";
|
||||
import { Log, parseLogs } from "./logs";
|
||||
import { BlockResponse, RestClient, TxsResponse } from "./restclient";
|
||||
import {
|
||||
Coin,
|
||||
CosmosSdkAccount,
|
||||
CosmosSdkTx,
|
||||
MsgExecuteContract,
|
||||
MsgInstantiateContract,
|
||||
MsgSend,
|
||||
MsgStoreCode,
|
||||
StdFee,
|
||||
StdSignature,
|
||||
} from "./types";
|
||||
|
||||
export interface FeeTable {
|
||||
readonly upload: StdFee;
|
||||
readonly init: StdFee;
|
||||
readonly exec: StdFee;
|
||||
readonly send: StdFee;
|
||||
}
|
||||
|
||||
function singleAmount(amount: number, denom: string): readonly Coin[] {
|
||||
return [{ amount: amount.toString(), denom: denom }];
|
||||
}
|
||||
|
||||
const defaultFees: FeeTable = {
|
||||
upload: {
|
||||
amount: singleAmount(25000, "ucosm"),
|
||||
gas: "1000000", // one million
|
||||
},
|
||||
init: {
|
||||
amount: singleAmount(12500, "ucosm"),
|
||||
gas: "500000", // 500k
|
||||
},
|
||||
exec: {
|
||||
amount: singleAmount(5000, "ucosm"),
|
||||
gas: "200000", // 200k
|
||||
},
|
||||
send: {
|
||||
amount: singleAmount(2000, "ucosm"),
|
||||
gas: "80000", // 80k
|
||||
},
|
||||
};
|
||||
|
||||
export interface SigningCallback {
|
||||
(signBytes: Uint8Array): Promise<StdSignature>;
|
||||
}
|
||||
|
||||
export interface SigningData {
|
||||
readonly senderAddress: string;
|
||||
readonly signCallback: SigningCallback;
|
||||
}
|
||||
import { CosmosSdkAccount, CosmosSdkTx } from "./types";
|
||||
|
||||
export interface GetNonceResult {
|
||||
readonly accountNumber: number;
|
||||
@ -93,44 +43,11 @@ function isSearchBySentFromOrToQuery(query: SearchTxQuery): query is SearchBySen
|
||||
return (query as SearchBySentFromOrToQuery).sentFromOrTo !== undefined;
|
||||
}
|
||||
|
||||
export interface ExecuteResult {
|
||||
readonly logs: readonly Log[];
|
||||
}
|
||||
|
||||
export class CosmWasmClient {
|
||||
public static makeReadOnly(url: string): CosmWasmClient {
|
||||
return new CosmWasmClient(url, undefined, {});
|
||||
}
|
||||
protected readonly restClient: RestClient;
|
||||
|
||||
public static makeWritable(
|
||||
url: string,
|
||||
senderAddress: string,
|
||||
signCallback: SigningCallback,
|
||||
feeTable?: Partial<FeeTable>,
|
||||
): CosmWasmClient {
|
||||
return new CosmWasmClient(
|
||||
url,
|
||||
{
|
||||
senderAddress: senderAddress,
|
||||
signCallback: signCallback,
|
||||
},
|
||||
feeTable || {},
|
||||
);
|
||||
}
|
||||
|
||||
private readonly restClient: RestClient;
|
||||
private readonly signingData: SigningData | undefined;
|
||||
private readonly fees: FeeTable;
|
||||
|
||||
private get signCallback(): SigningCallback {
|
||||
if (!this.signingData) throw new Error("Signing data not set in this client");
|
||||
return this.signingData.signCallback;
|
||||
}
|
||||
|
||||
private constructor(url: string, signingData: SigningData | undefined, customFees: Partial<FeeTable>) {
|
||||
public constructor(url: string) {
|
||||
this.restClient = new RestClient(url);
|
||||
this.signingData = signingData;
|
||||
this.fees = { ...defaultFees, ...customFees };
|
||||
}
|
||||
|
||||
public async chainId(): Promise<string> {
|
||||
@ -138,11 +55,6 @@ export class CosmWasmClient {
|
||||
return response.node_info.network;
|
||||
}
|
||||
|
||||
public get senderAddress(): string {
|
||||
if (!this.signingData) throw new Error("Signing data not set in this client");
|
||||
return this.signingData.senderAddress;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a 32 byte upper-case hex transaction hash (typically used as the transaction ID)
|
||||
*/
|
||||
@ -160,7 +72,7 @@ export class CosmWasmClient {
|
||||
*
|
||||
* @param address returns data for this address. When unset, the client's sender adddress is used.
|
||||
*/
|
||||
public async getNonce(address?: string): Promise<GetNonceResult> {
|
||||
public async getNonce(address: string): Promise<GetNonceResult> {
|
||||
const account = await this.getAccount(address);
|
||||
if (!account) {
|
||||
throw new Error(
|
||||
@ -173,8 +85,8 @@ export class CosmWasmClient {
|
||||
};
|
||||
}
|
||||
|
||||
public async getAccount(address?: string): Promise<CosmosSdkAccount | undefined> {
|
||||
const account = await this.restClient.authAccounts(address || this.senderAddress);
|
||||
public async getAccount(address: string): Promise<CosmosSdkAccount | undefined> {
|
||||
const account = await this.restClient.authAccounts(address);
|
||||
const value = account.result.value;
|
||||
return value.address === "" ? undefined : value;
|
||||
}
|
||||
@ -230,136 +142,6 @@ export class CosmWasmClient {
|
||||
};
|
||||
}
|
||||
|
||||
/** Uploads code and returns a code ID */
|
||||
public async upload(wasmCode: Uint8Array, memo = ""): Promise<number> {
|
||||
const storeCodeMsg: MsgStoreCode = {
|
||||
type: "wasm/store-code",
|
||||
value: {
|
||||
sender: this.senderAddress,
|
||||
// eslint-disable-next-line @typescript-eslint/camelcase
|
||||
wasm_byte_code: Encoding.toBase64(wasmCode),
|
||||
source: "",
|
||||
builder: "",
|
||||
},
|
||||
};
|
||||
const fee = this.fees.upload;
|
||||
const { accountNumber, sequence } = await this.getNonce();
|
||||
const chainId = await this.chainId();
|
||||
const signBytes = makeSignBytes([storeCodeMsg], fee, chainId, memo, accountNumber, sequence);
|
||||
const signature = await this.signCallback(signBytes);
|
||||
const signedTx = {
|
||||
msg: [storeCodeMsg],
|
||||
fee: fee,
|
||||
memo: memo,
|
||||
signatures: [signature],
|
||||
};
|
||||
|
||||
const result = await this.postTx(marshalTx(signedTx));
|
||||
const codeIdAttr = findAttribute(result.logs, "message", "code_id");
|
||||
const codeId = Number.parseInt(codeIdAttr.value, 10);
|
||||
return codeId;
|
||||
}
|
||||
|
||||
public async instantiate(
|
||||
codeId: number,
|
||||
initMsg: object,
|
||||
memo = "",
|
||||
transferAmount?: readonly Coin[],
|
||||
): Promise<string> {
|
||||
const instantiateMsg: MsgInstantiateContract = {
|
||||
type: "wasm/instantiate",
|
||||
value: {
|
||||
sender: this.senderAddress,
|
||||
// eslint-disable-next-line @typescript-eslint/camelcase
|
||||
code_id: codeId.toString(),
|
||||
// eslint-disable-next-line @typescript-eslint/camelcase
|
||||
init_msg: initMsg,
|
||||
// eslint-disable-next-line @typescript-eslint/camelcase
|
||||
init_funds: transferAmount || [],
|
||||
},
|
||||
};
|
||||
const fee = this.fees.init;
|
||||
const { accountNumber, sequence } = await this.getNonce();
|
||||
const chainId = await this.chainId();
|
||||
const signBytes = makeSignBytes([instantiateMsg], fee, chainId, memo, accountNumber, sequence);
|
||||
|
||||
const signature = await this.signCallback(signBytes);
|
||||
const signedTx = {
|
||||
msg: [instantiateMsg],
|
||||
fee: fee,
|
||||
memo: memo,
|
||||
signatures: [signature],
|
||||
};
|
||||
|
||||
const result = await this.postTx(marshalTx(signedTx));
|
||||
const contractAddressAttr = findAttribute(result.logs, "message", "contract_address");
|
||||
return contractAddressAttr.value;
|
||||
}
|
||||
|
||||
public async execute(
|
||||
contractAddress: string,
|
||||
handleMsg: object,
|
||||
memo = "",
|
||||
transferAmount?: readonly Coin[],
|
||||
): Promise<ExecuteResult> {
|
||||
const executeMsg: MsgExecuteContract = {
|
||||
type: "wasm/execute",
|
||||
value: {
|
||||
sender: this.senderAddress,
|
||||
contract: contractAddress,
|
||||
msg: handleMsg,
|
||||
// eslint-disable-next-line @typescript-eslint/camelcase
|
||||
sent_funds: transferAmount || [],
|
||||
},
|
||||
};
|
||||
const fee = this.fees.exec;
|
||||
const { accountNumber, sequence } = await this.getNonce();
|
||||
const chainId = await this.chainId();
|
||||
const signBytes = makeSignBytes([executeMsg], fee, chainId, memo, accountNumber, sequence);
|
||||
const signature = await this.signCallback(signBytes);
|
||||
const signedTx = {
|
||||
msg: [executeMsg],
|
||||
fee: fee,
|
||||
memo: memo,
|
||||
signatures: [signature],
|
||||
};
|
||||
|
||||
const result = await this.postTx(marshalTx(signedTx));
|
||||
return {
|
||||
logs: result.logs,
|
||||
};
|
||||
}
|
||||
|
||||
public async sendTokens(
|
||||
recipientAddress: string,
|
||||
transferAmount: readonly Coin[],
|
||||
memo = "",
|
||||
): Promise<PostTxResult> {
|
||||
const sendMsg: MsgSend = {
|
||||
type: "cosmos-sdk/MsgSend",
|
||||
value: {
|
||||
// eslint-disable-next-line @typescript-eslint/camelcase
|
||||
from_address: this.senderAddress,
|
||||
// eslint-disable-next-line @typescript-eslint/camelcase
|
||||
to_address: recipientAddress,
|
||||
amount: transferAmount,
|
||||
},
|
||||
};
|
||||
const fee = this.fees.send;
|
||||
const { accountNumber, sequence } = await this.getNonce();
|
||||
const chainId = await this.chainId();
|
||||
const signBytes = makeSignBytes([sendMsg], fee, chainId, memo, accountNumber, sequence);
|
||||
const signature = await this.signCallback(signBytes);
|
||||
const signedTx = {
|
||||
msg: [sendMsg],
|
||||
fee: fee,
|
||||
memo: memo,
|
||||
signatures: [signature],
|
||||
};
|
||||
|
||||
return this.postTx(marshalTx(signedTx));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the data at the key if present (raw contract dependent storage data)
|
||||
* or null if no data at this key.
|
||||
|
||||
@ -8,15 +8,12 @@ export { makeSignBytes, marshalTx } from "./encoding";
|
||||
export { RestClient, TxsResponse } from "./restclient";
|
||||
export {
|
||||
CosmWasmClient,
|
||||
ExecuteResult,
|
||||
GetNonceResult,
|
||||
PostTxResult,
|
||||
SearchByHeightQuery,
|
||||
SearchByIdQuery,
|
||||
SearchBySentFromOrToQuery,
|
||||
SearchTxQuery,
|
||||
SigningCallback,
|
||||
SigningData,
|
||||
} from "./cosmwasmclient";
|
||||
export { makeCosmoshubPath, Pen, PrehashType, Secp256k1Pen } from "./pen";
|
||||
export {
|
||||
@ -27,3 +24,4 @@ export {
|
||||
} from "./pubkey";
|
||||
export { findSequenceForSignedTx } from "./sequence";
|
||||
export { encodeSecp256k1Signature, decodeSignature } from "./signature";
|
||||
export { SigningCallback, SigningCosmWasmClient, ExecuteResult } from "./signingcosmwasmclient";
|
||||
|
||||
164
packages/sdk/src/signingcosmwasmclient.spec.ts
Normal file
164
packages/sdk/src/signingcosmwasmclient.spec.ts
Normal file
@ -0,0 +1,164 @@
|
||||
import { assert } from "@iov/utils";
|
||||
|
||||
import { Secp256k1Pen } from "./pen";
|
||||
import { RestClient } from "./restclient";
|
||||
import { SigningCosmWasmClient } from "./signingcosmwasmclient";
|
||||
import { getRandomizedHackatom, makeRandomAddress, pendingWithoutCosmos } from "./testutils.spec";
|
||||
import { Coin } from "./types";
|
||||
|
||||
const httpUrl = "http://localhost:1317";
|
||||
|
||||
const faucet = {
|
||||
mnemonic:
|
||||
"economy stock theory fatal elder harbor betray wasp final emotion task crumble siren bottom lizard educate guess current outdoor pair theory focus wife stone",
|
||||
pubkey: {
|
||||
type: "tendermint/PubKeySecp256k1",
|
||||
value: "A08EGB7ro1ORuFhjOnZcSgwYlpe0DSFjVNUIkNNQxwKQ",
|
||||
},
|
||||
address: "cosmos1pkptre7fdkl6gfrzlesjjvhxhlc3r4gmmk8rs6",
|
||||
};
|
||||
|
||||
describe("SigningCosmWasmClient", () => {
|
||||
describe("makeReadOnly", () => {
|
||||
it("can be constructed", async () => {
|
||||
const pen = await Secp256k1Pen.fromMnemonic(faucet.mnemonic);
|
||||
const client = new SigningCosmWasmClient(httpUrl, faucet.address, signBytes => pen.sign(signBytes));
|
||||
expect(client).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
describe("upload", () => {
|
||||
it("works", async () => {
|
||||
pendingWithoutCosmos();
|
||||
const pen = await Secp256k1Pen.fromMnemonic(faucet.mnemonic);
|
||||
const client = new SigningCosmWasmClient(httpUrl, faucet.address, signBytes => pen.sign(signBytes));
|
||||
const codeId = await client.upload(getRandomizedHackatom());
|
||||
expect(codeId).toBeGreaterThanOrEqual(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe("instantiate", () => {
|
||||
it("works with transfer amount", async () => {
|
||||
pendingWithoutCosmos();
|
||||
const pen = await Secp256k1Pen.fromMnemonic(faucet.mnemonic);
|
||||
const client = new SigningCosmWasmClient(httpUrl, faucet.address, signBytes => pen.sign(signBytes));
|
||||
const codeId = await client.upload(getRandomizedHackatom());
|
||||
|
||||
const transferAmount: readonly Coin[] = [
|
||||
{
|
||||
amount: "1234",
|
||||
denom: "ucosm",
|
||||
},
|
||||
{
|
||||
amount: "321",
|
||||
denom: "ustake",
|
||||
},
|
||||
];
|
||||
const beneficiaryAddress = makeRandomAddress();
|
||||
const contractAddress = await client.instantiate(
|
||||
codeId,
|
||||
{
|
||||
verifier: faucet.address,
|
||||
beneficiary: beneficiaryAddress,
|
||||
},
|
||||
"Let's see",
|
||||
transferAmount,
|
||||
);
|
||||
|
||||
const rest = new RestClient(httpUrl);
|
||||
const balance = (await rest.authAccounts(contractAddress)).result.value.coins;
|
||||
expect(balance).toEqual(transferAmount);
|
||||
});
|
||||
|
||||
it("can instantiate one code multiple times", async () => {
|
||||
pendingWithoutCosmos();
|
||||
const pen = await Secp256k1Pen.fromMnemonic(faucet.mnemonic);
|
||||
const client = new SigningCosmWasmClient(httpUrl, faucet.address, signBytes => pen.sign(signBytes));
|
||||
const codeId = await client.upload(getRandomizedHackatom());
|
||||
|
||||
const contractAddress1 = await client.instantiate(codeId, {
|
||||
verifier: faucet.address,
|
||||
beneficiary: makeRandomAddress(),
|
||||
});
|
||||
const contractAddress2 = await client.instantiate(codeId, {
|
||||
verifier: faucet.address,
|
||||
beneficiary: makeRandomAddress(),
|
||||
});
|
||||
expect(contractAddress1).not.toEqual(contractAddress2);
|
||||
});
|
||||
});
|
||||
|
||||
describe("execute", () => {
|
||||
it("works", async () => {
|
||||
pendingWithoutCosmos();
|
||||
const pen = await Secp256k1Pen.fromMnemonic(faucet.mnemonic);
|
||||
const client = new SigningCosmWasmClient(httpUrl, faucet.address, signBytes => pen.sign(signBytes));
|
||||
const codeId = await client.upload(getRandomizedHackatom());
|
||||
|
||||
// instantiate
|
||||
const transferAmount: readonly Coin[] = [
|
||||
{
|
||||
amount: "233444",
|
||||
denom: "ucosm",
|
||||
},
|
||||
{
|
||||
amount: "5454",
|
||||
denom: "ustake",
|
||||
},
|
||||
];
|
||||
const beneficiaryAddress = makeRandomAddress();
|
||||
const contractAddress = await client.instantiate(
|
||||
codeId,
|
||||
{
|
||||
verifier: faucet.address,
|
||||
beneficiary: beneficiaryAddress,
|
||||
},
|
||||
undefined,
|
||||
transferAmount,
|
||||
);
|
||||
|
||||
// execute
|
||||
const result = await client.execute(contractAddress, {}, undefined);
|
||||
const [firstLog] = result.logs;
|
||||
expect(firstLog.log).toEqual(`released funds to ${beneficiaryAddress}`);
|
||||
|
||||
// Verify token transfer from contract to beneficiary
|
||||
const rest = new RestClient(httpUrl);
|
||||
const beneficiaryBalance = (await rest.authAccounts(beneficiaryAddress)).result.value.coins;
|
||||
expect(beneficiaryBalance).toEqual(transferAmount);
|
||||
const contractBalance = (await rest.authAccounts(contractAddress)).result.value.coins;
|
||||
expect(contractBalance).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("sendTokens", () => {
|
||||
it("works", async () => {
|
||||
pendingWithoutCosmos();
|
||||
const pen = await Secp256k1Pen.fromMnemonic(faucet.mnemonic);
|
||||
const client = new SigningCosmWasmClient(httpUrl, faucet.address, signBytes => pen.sign(signBytes));
|
||||
|
||||
// instantiate
|
||||
const transferAmount: readonly Coin[] = [
|
||||
{
|
||||
amount: "7890",
|
||||
denom: "ucosm",
|
||||
},
|
||||
];
|
||||
const beneficiaryAddress = makeRandomAddress();
|
||||
|
||||
// no tokens here
|
||||
const before = await client.getAccount(beneficiaryAddress);
|
||||
expect(before).toBeUndefined();
|
||||
|
||||
// send
|
||||
const result = await client.sendTokens(beneficiaryAddress, transferAmount, "for dinner");
|
||||
const [firstLog] = result.logs;
|
||||
expect(firstLog).toBeTruthy();
|
||||
|
||||
// got tokens
|
||||
const after = await client.getAccount(beneficiaryAddress);
|
||||
assert(after);
|
||||
expect(after.coins).toEqual(transferAmount);
|
||||
});
|
||||
});
|
||||
});
|
||||
210
packages/sdk/src/signingcosmwasmclient.ts
Normal file
210
packages/sdk/src/signingcosmwasmclient.ts
Normal file
@ -0,0 +1,210 @@
|
||||
import { Encoding } from "@iov/encoding";
|
||||
|
||||
import { CosmWasmClient, GetNonceResult, PostTxResult } from "./cosmwasmclient";
|
||||
import { makeSignBytes, marshalTx } from "./encoding";
|
||||
import { findAttribute, Log } from "./logs";
|
||||
import {
|
||||
Coin,
|
||||
CosmosSdkAccount,
|
||||
MsgExecuteContract,
|
||||
MsgInstantiateContract,
|
||||
MsgSend,
|
||||
MsgStoreCode,
|
||||
StdFee,
|
||||
StdSignature,
|
||||
} from "./types";
|
||||
|
||||
export interface SigningCallback {
|
||||
(signBytes: Uint8Array): Promise<StdSignature>;
|
||||
}
|
||||
|
||||
export interface FeeTable {
|
||||
readonly upload: StdFee;
|
||||
readonly init: StdFee;
|
||||
readonly exec: StdFee;
|
||||
readonly send: StdFee;
|
||||
}
|
||||
|
||||
function singleAmount(amount: number, denom: string): readonly Coin[] {
|
||||
return [{ amount: amount.toString(), denom: denom }];
|
||||
}
|
||||
|
||||
const defaultFees: FeeTable = {
|
||||
upload: {
|
||||
amount: singleAmount(25000, "ucosm"),
|
||||
gas: "1000000", // one million
|
||||
},
|
||||
init: {
|
||||
amount: singleAmount(12500, "ucosm"),
|
||||
gas: "500000", // 500k
|
||||
},
|
||||
exec: {
|
||||
amount: singleAmount(5000, "ucosm"),
|
||||
gas: "200000", // 200k
|
||||
},
|
||||
send: {
|
||||
amount: singleAmount(2000, "ucosm"),
|
||||
gas: "80000", // 80k
|
||||
},
|
||||
};
|
||||
|
||||
export interface ExecuteResult {
|
||||
readonly logs: readonly Log[];
|
||||
}
|
||||
|
||||
export class SigningCosmWasmClient extends CosmWasmClient {
|
||||
public readonly senderAddress: string;
|
||||
|
||||
private readonly signCallback: SigningCallback;
|
||||
private readonly fees: FeeTable;
|
||||
|
||||
public constructor(
|
||||
url: string,
|
||||
senderAddress: string,
|
||||
signCallback: SigningCallback,
|
||||
customFees?: Partial<FeeTable>,
|
||||
) {
|
||||
super(url);
|
||||
this.senderAddress = senderAddress;
|
||||
this.signCallback = signCallback;
|
||||
this.fees = { ...defaultFees, ...(customFees || {}) };
|
||||
}
|
||||
|
||||
public async getNonce(address?: string): Promise<GetNonceResult> {
|
||||
return super.getNonce(address || this.senderAddress);
|
||||
}
|
||||
|
||||
public async getAccount(address?: string): Promise<CosmosSdkAccount | undefined> {
|
||||
return super.getAccount(address || this.senderAddress);
|
||||
}
|
||||
|
||||
/** Uploads code and returns a code ID */
|
||||
public async upload(wasmCode: Uint8Array, memo = ""): Promise<number> {
|
||||
const storeCodeMsg: MsgStoreCode = {
|
||||
type: "wasm/store-code",
|
||||
value: {
|
||||
sender: this.senderAddress,
|
||||
// eslint-disable-next-line @typescript-eslint/camelcase
|
||||
wasm_byte_code: Encoding.toBase64(wasmCode),
|
||||
source: "",
|
||||
builder: "",
|
||||
},
|
||||
};
|
||||
const fee = this.fees.upload;
|
||||
const { accountNumber, sequence } = await this.getNonce();
|
||||
const chainId = await this.chainId();
|
||||
const signBytes = makeSignBytes([storeCodeMsg], fee, chainId, memo, accountNumber, sequence);
|
||||
const signature = await this.signCallback(signBytes);
|
||||
const signedTx = {
|
||||
msg: [storeCodeMsg],
|
||||
fee: fee,
|
||||
memo: memo,
|
||||
signatures: [signature],
|
||||
};
|
||||
|
||||
const result = await this.postTx(marshalTx(signedTx));
|
||||
const codeIdAttr = findAttribute(result.logs, "message", "code_id");
|
||||
const codeId = Number.parseInt(codeIdAttr.value, 10);
|
||||
return codeId;
|
||||
}
|
||||
|
||||
public async instantiate(
|
||||
codeId: number,
|
||||
initMsg: object,
|
||||
memo = "",
|
||||
transferAmount?: readonly Coin[],
|
||||
): Promise<string> {
|
||||
const instantiateMsg: MsgInstantiateContract = {
|
||||
type: "wasm/instantiate",
|
||||
value: {
|
||||
sender: this.senderAddress,
|
||||
// eslint-disable-next-line @typescript-eslint/camelcase
|
||||
code_id: codeId.toString(),
|
||||
// eslint-disable-next-line @typescript-eslint/camelcase
|
||||
init_msg: initMsg,
|
||||
// eslint-disable-next-line @typescript-eslint/camelcase
|
||||
init_funds: transferAmount || [],
|
||||
},
|
||||
};
|
||||
const fee = this.fees.init;
|
||||
const { accountNumber, sequence } = await this.getNonce();
|
||||
const chainId = await this.chainId();
|
||||
const signBytes = makeSignBytes([instantiateMsg], fee, chainId, memo, accountNumber, sequence);
|
||||
|
||||
const signature = await this.signCallback(signBytes);
|
||||
const signedTx = {
|
||||
msg: [instantiateMsg],
|
||||
fee: fee,
|
||||
memo: memo,
|
||||
signatures: [signature],
|
||||
};
|
||||
|
||||
const result = await this.postTx(marshalTx(signedTx));
|
||||
const contractAddressAttr = findAttribute(result.logs, "message", "contract_address");
|
||||
return contractAddressAttr.value;
|
||||
}
|
||||
|
||||
public async execute(
|
||||
contractAddress: string,
|
||||
handleMsg: object,
|
||||
memo = "",
|
||||
transferAmount?: readonly Coin[],
|
||||
): Promise<ExecuteResult> {
|
||||
const executeMsg: MsgExecuteContract = {
|
||||
type: "wasm/execute",
|
||||
value: {
|
||||
sender: this.senderAddress,
|
||||
contract: contractAddress,
|
||||
msg: handleMsg,
|
||||
// eslint-disable-next-line @typescript-eslint/camelcase
|
||||
sent_funds: transferAmount || [],
|
||||
},
|
||||
};
|
||||
const fee = this.fees.exec;
|
||||
const { accountNumber, sequence } = await this.getNonce();
|
||||
const chainId = await this.chainId();
|
||||
const signBytes = makeSignBytes([executeMsg], fee, chainId, memo, accountNumber, sequence);
|
||||
const signature = await this.signCallback(signBytes);
|
||||
const signedTx = {
|
||||
msg: [executeMsg],
|
||||
fee: fee,
|
||||
memo: memo,
|
||||
signatures: [signature],
|
||||
};
|
||||
|
||||
const result = await this.postTx(marshalTx(signedTx));
|
||||
return {
|
||||
logs: result.logs,
|
||||
};
|
||||
}
|
||||
|
||||
public async sendTokens(
|
||||
recipientAddress: string,
|
||||
transferAmount: readonly Coin[],
|
||||
memo = "",
|
||||
): Promise<PostTxResult> {
|
||||
const sendMsg: MsgSend = {
|
||||
type: "cosmos-sdk/MsgSend",
|
||||
value: {
|
||||
// eslint-disable-next-line @typescript-eslint/camelcase
|
||||
from_address: this.senderAddress,
|
||||
// eslint-disable-next-line @typescript-eslint/camelcase
|
||||
to_address: recipientAddress,
|
||||
amount: transferAmount,
|
||||
},
|
||||
};
|
||||
const fee = this.fees.send;
|
||||
const { accountNumber, sequence } = await this.getNonce();
|
||||
const chainId = await this.chainId();
|
||||
const signBytes = makeSignBytes([sendMsg], fee, chainId, memo, accountNumber, sequence);
|
||||
const signature = await this.signCallback(signBytes);
|
||||
const signedTx = {
|
||||
msg: [sendMsg],
|
||||
fee: fee,
|
||||
memo: memo,
|
||||
signatures: [signature],
|
||||
};
|
||||
|
||||
return this.postTx(marshalTx(signedTx));
|
||||
}
|
||||
}
|
||||
@ -58,6 +58,16 @@ export const tendermintIdMatcher = /^[0-9A-F]{64}$/;
|
||||
export const tendermintOptionalIdMatcher = /^([0-9A-F]{64}|)$/;
|
||||
export const tendermintAddressMatcher = /^[0-9A-F]{40}$/;
|
||||
|
||||
export function cosmosEnabled(): boolean {
|
||||
return !!process.env.COSMOS_ENABLED;
|
||||
}
|
||||
|
||||
export function pendingWithoutCosmos(): void {
|
||||
if (!cosmosEnabled()) {
|
||||
return pending("Set COSMOS_ENABLED to enable Cosmos node-based tests");
|
||||
}
|
||||
}
|
||||
|
||||
describe("leb128", () => {
|
||||
describe("leb128Encode", () => {
|
||||
it("works for single byte values", () => {
|
||||
|
||||
54
packages/sdk/types/cosmwasmclient.d.ts
vendored
54
packages/sdk/types/cosmwasmclient.d.ts
vendored
@ -1,19 +1,6 @@
|
||||
import { Log } from "./logs";
|
||||
import { BlockResponse, TxsResponse } from "./restclient";
|
||||
import { Coin, CosmosSdkAccount, CosmosSdkTx, StdFee, StdSignature } from "./types";
|
||||
export interface FeeTable {
|
||||
readonly upload: StdFee;
|
||||
readonly init: StdFee;
|
||||
readonly exec: StdFee;
|
||||
readonly send: StdFee;
|
||||
}
|
||||
export interface SigningCallback {
|
||||
(signBytes: Uint8Array): Promise<StdSignature>;
|
||||
}
|
||||
export interface SigningData {
|
||||
readonly senderAddress: string;
|
||||
readonly signCallback: SigningCallback;
|
||||
}
|
||||
import { BlockResponse, RestClient, TxsResponse } from "./restclient";
|
||||
import { CosmosSdkAccount, CosmosSdkTx } from "./types";
|
||||
export interface GetNonceResult {
|
||||
readonly accountNumber: number;
|
||||
readonly sequence: number;
|
||||
@ -34,24 +21,10 @@ export interface SearchBySentFromOrToQuery {
|
||||
readonly sentFromOrTo: string;
|
||||
}
|
||||
export declare type SearchTxQuery = SearchByIdQuery | SearchByHeightQuery | SearchBySentFromOrToQuery;
|
||||
export interface ExecuteResult {
|
||||
readonly logs: readonly Log[];
|
||||
}
|
||||
export declare class CosmWasmClient {
|
||||
static makeReadOnly(url: string): CosmWasmClient;
|
||||
static makeWritable(
|
||||
url: string,
|
||||
senderAddress: string,
|
||||
signCallback: SigningCallback,
|
||||
feeTable?: Partial<FeeTable>,
|
||||
): CosmWasmClient;
|
||||
private readonly restClient;
|
||||
private readonly signingData;
|
||||
private readonly fees;
|
||||
private get signCallback();
|
||||
private constructor();
|
||||
protected readonly restClient: RestClient;
|
||||
constructor(url: string);
|
||||
chainId(): Promise<string>;
|
||||
get senderAddress(): string;
|
||||
/**
|
||||
* Returns a 32 byte upper-case hex transaction hash (typically used as the transaction ID)
|
||||
*/
|
||||
@ -63,8 +36,8 @@ 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>;
|
||||
getAccount(address?: string): Promise<CosmosSdkAccount | undefined>;
|
||||
getNonce(address: string): Promise<GetNonceResult>;
|
||||
getAccount(address: string): Promise<CosmosSdkAccount | undefined>;
|
||||
/**
|
||||
* Gets block header and meta
|
||||
*
|
||||
@ -73,21 +46,6 @@ export declare class CosmWasmClient {
|
||||
getBlock(height?: number): Promise<BlockResponse>;
|
||||
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>;
|
||||
instantiate(
|
||||
codeId: number,
|
||||
initMsg: object,
|
||||
memo?: string,
|
||||
transferAmount?: readonly Coin[],
|
||||
): Promise<string>;
|
||||
execute(
|
||||
contractAddress: string,
|
||||
handleMsg: object,
|
||||
memo?: string,
|
||||
transferAmount?: readonly Coin[],
|
||||
): Promise<ExecuteResult>;
|
||||
sendTokens(recipientAddress: string, transferAmount: readonly Coin[], memo?: string): Promise<PostTxResult>;
|
||||
/**
|
||||
* Returns the data at the key if present (raw contract dependent storage data)
|
||||
* or null if no data at this key.
|
||||
|
||||
4
packages/sdk/types/index.d.ts
vendored
4
packages/sdk/types/index.d.ts
vendored
@ -7,15 +7,12 @@ export { makeSignBytes, marshalTx } from "./encoding";
|
||||
export { RestClient, TxsResponse } from "./restclient";
|
||||
export {
|
||||
CosmWasmClient,
|
||||
ExecuteResult,
|
||||
GetNonceResult,
|
||||
PostTxResult,
|
||||
SearchByHeightQuery,
|
||||
SearchByIdQuery,
|
||||
SearchBySentFromOrToQuery,
|
||||
SearchTxQuery,
|
||||
SigningCallback,
|
||||
SigningData,
|
||||
} from "./cosmwasmclient";
|
||||
export { makeCosmoshubPath, Pen, PrehashType, Secp256k1Pen } from "./pen";
|
||||
export {
|
||||
@ -26,3 +23,4 @@ export {
|
||||
} from "./pubkey";
|
||||
export { findSequenceForSignedTx } from "./sequence";
|
||||
export { encodeSecp256k1Signature, decodeSignature } from "./signature";
|
||||
export { SigningCallback, SigningCosmWasmClient, ExecuteResult } from "./signingcosmwasmclient";
|
||||
|
||||
43
packages/sdk/types/signingcosmwasmclient.d.ts
vendored
Normal file
43
packages/sdk/types/signingcosmwasmclient.d.ts
vendored
Normal file
@ -0,0 +1,43 @@
|
||||
import { CosmWasmClient, GetNonceResult, PostTxResult } from "./cosmwasmclient";
|
||||
import { Log } from "./logs";
|
||||
import { Coin, CosmosSdkAccount, StdFee, StdSignature } from "./types";
|
||||
export interface SigningCallback {
|
||||
(signBytes: Uint8Array): Promise<StdSignature>;
|
||||
}
|
||||
export interface FeeTable {
|
||||
readonly upload: StdFee;
|
||||
readonly init: StdFee;
|
||||
readonly exec: StdFee;
|
||||
readonly send: StdFee;
|
||||
}
|
||||
export interface ExecuteResult {
|
||||
readonly logs: readonly Log[];
|
||||
}
|
||||
export declare class SigningCosmWasmClient extends CosmWasmClient {
|
||||
readonly senderAddress: string;
|
||||
private readonly signCallback;
|
||||
private readonly fees;
|
||||
constructor(
|
||||
url: string,
|
||||
senderAddress: string,
|
||||
signCallback: SigningCallback,
|
||||
customFees?: Partial<FeeTable>,
|
||||
);
|
||||
getNonce(address?: string): Promise<GetNonceResult>;
|
||||
getAccount(address?: string): Promise<CosmosSdkAccount | undefined>;
|
||||
/** Uploads code and returns a code ID */
|
||||
upload(wasmCode: Uint8Array, memo?: string): Promise<number>;
|
||||
instantiate(
|
||||
codeId: number,
|
||||
initMsg: object,
|
||||
memo?: string,
|
||||
transferAmount?: readonly Coin[],
|
||||
): Promise<string>;
|
||||
execute(
|
||||
contractAddress: string,
|
||||
handleMsg: object,
|
||||
memo?: string,
|
||||
transferAmount?: readonly Coin[],
|
||||
): Promise<ExecuteResult>;
|
||||
sendTokens(recipientAddress: string, transferAmount: readonly Coin[], memo?: string): Promise<PostTxResult>;
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user