Merge pull request #833 from cosmos/827-restructure-fees

Remove default fees
This commit is contained in:
Will Clark 2021-06-16 12:09:00 +02:00 committed by GitHub
commit 06fbc34f72
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 273 additions and 586 deletions

View File

@ -24,6 +24,12 @@ and this project adheres to
- @cosmjs/cosmwasm-stargate: The `transferAmount` property on
`InstantiateOptions` (accepted as a parameter to
`SigningCosmWasmClient.instantiate`) has been renamed to `funds`.
- @cosmjs/cosmwasm-stargate: Default fee/gas values have been removed. Fees now
need to be calculated and passed to `SigningCosmWasmClient` when calling any
methods which submit transactions to the blockchain.
- @cosmjs/stargate: Default fee/gas values have been removed. Fees now need to
be calculated and passed to `SigningStargateClient` when calling any methods
which submit transactions to the blockchain.
- @cosmjs/tendermint-rpc: Make `tendermint34.Header.lastBlockId` and
`tendermint34.Block.lastCommit` optional to better handle the case of height 1
where there is no previous block.
@ -31,6 +37,11 @@ and this project adheres to
### Removed
- Node.js v10 is no longer supported. Please use v12 or later.
- @cosmjs/cosmwasm-stargate: Remove `CosmWasmFeeTable` type and
`defaultGasLimits` object.
- @cosmjs/stargate: Remove types, objects and functions to do with default fees:
`CosmosFeeTable`, `FeeTable`, `GasLimits`, `defaultGasLimits`,
`defaultGasPrice` and `buildFeeTable`.
- @cosmjs/tendermint-rpc: `Client` has been removed. Please use
`Tendermint33Client` or `Tendermint34Client`, depending on your needs.

View File

@ -20,6 +20,8 @@ import { CosmWasmClient, PrivateCosmWasmClient } from "./cosmwasmclient";
import { SigningCosmWasmClient } from "./signingcosmwasmclient";
import {
alice,
defaultInstantiateFee,
defaultUploadFee,
deployedHackatom,
getHackatom,
makeRandomAddress,
@ -31,7 +33,7 @@ import {
} from "./testutils.spec";
interface HackatomInstance {
readonly initMsg: {
readonly instantiateMsg: {
readonly verifier: string;
readonly beneficiary: string;
};
@ -318,15 +320,17 @@ describe("CosmWasmClient", () => {
if (wasmdEnabled()) {
const wallet = await DirectSecp256k1HdWallet.fromMnemonic(alice.mnemonic, { prefix: wasmd.prefix });
const client = await SigningCosmWasmClient.connectWithSigner(wasmd.endpoint, wallet);
const { codeId } = await client.upload(alice.address0, getHackatom().data);
const initMsg = { verifier: makeRandomAddress(), beneficiary: makeRandomAddress() };
const { codeId } = await client.upload(alice.address0, getHackatom().data, defaultUploadFee);
const instantiateMsg = { verifier: makeRandomAddress(), beneficiary: makeRandomAddress() };
const label = "random hackatom";
const { contractAddress } = await client.instantiate(
alice.address0,
codeId,
initMsg,
"random hackatom",
instantiateMsg,
label,
defaultInstantiateFee,
);
contract = { initMsg: initMsg, address: contractAddress };
contract = { instantiateMsg: instantiateMsg, address: contractAddress };
}
});
@ -338,8 +342,8 @@ describe("CosmWasmClient", () => {
const raw = await client.queryContractRaw(contract.address, configKey);
assert(raw, "must get result");
expect(JSON.parse(fromAscii(raw))).toEqual({
verifier: contract.initMsg.verifier,
beneficiary: contract.initMsg.beneficiary,
verifier: contract.instantiateMsg.verifier,
beneficiary: contract.instantiateMsg.beneficiary,
funder: alice.address0,
});
});
@ -372,15 +376,17 @@ describe("CosmWasmClient", () => {
if (wasmdEnabled()) {
const wallet = await DirectSecp256k1HdWallet.fromMnemonic(alice.mnemonic, { prefix: wasmd.prefix });
const client = await SigningCosmWasmClient.connectWithSigner(wasmd.endpoint, wallet);
const { codeId } = await client.upload(alice.address0, getHackatom().data);
const initMsg = { verifier: makeRandomAddress(), beneficiary: makeRandomAddress() };
const { codeId } = await client.upload(alice.address0, getHackatom().data, defaultUploadFee);
const instantiateMsg = { verifier: makeRandomAddress(), beneficiary: makeRandomAddress() };
const label = "a different hackatom";
const { contractAddress } = await client.instantiate(
alice.address0,
codeId,
initMsg,
"a different hackatom",
instantiateMsg,
label,
defaultInstantiateFee,
);
contract = { initMsg: initMsg, address: contractAddress };
contract = { instantiateMsg: instantiateMsg, address: contractAddress };
}
});
@ -390,7 +396,7 @@ describe("CosmWasmClient", () => {
const client = await CosmWasmClient.connect(wasmd.endpoint);
const result = await client.queryContractSmart(contract.address, { verifier: {} });
expect(result).toEqual({ verifier: contract.initMsg.verifier });
expect(result).toEqual({ verifier: contract.instantiateMsg.verifier });
});
it("errors for malformed query message", async () => {

View File

@ -22,9 +22,7 @@ export {
MsgUpdateAdminEncodeObject,
} from "./encodeobjects";
export {
defaultGasLimits,
ChangeAdminResult,
CosmWasmFeeTable, // part of SigningCosmWasmClientOptions
ExecuteResult,
InstantiateOptions,
InstantiateResult,

View File

@ -9,7 +9,6 @@ import {
assertIsBroadcastTxSuccess,
coin,
coins,
GasPrice,
MsgDelegateEncodeObject,
MsgSendEncodeObject,
} from "@cosmjs/stargate";
@ -27,6 +26,13 @@ import { MsgStoreCodeEncodeObject } from "./encodeobjects";
import { SigningCosmWasmClient, UploadMeta } from "./signingcosmwasmclient";
import {
alice,
defaultClearAdminFee,
defaultExecuteFee,
defaultInstantiateFee,
defaultMigrateFee,
defaultSendFee,
defaultUpdateAdminFee,
defaultUploadFee,
getHackatom,
makeRandomAddress,
makeWasmClient,
@ -57,167 +63,6 @@ describe("SigningCosmWasmClient", () => {
const client = await SigningCosmWasmClient.connectWithSigner(wasmd.endpoint, wallet, options);
expect(client.registry.lookupType("/custom.MsgCustom")).toEqual(MsgSend);
});
it("can be constructed with custom gas price", async () => {
pendingWithoutWasmd();
const wallet = await DirectSecp256k1HdWallet.fromMnemonic(alice.mnemonic, { prefix: wasmd.prefix });
const options = {
prefix: wasmd.prefix,
gasPrice: GasPrice.fromString("3.14utest"),
};
const client = await SigningCosmWasmClient.connectWithSigner(wasmd.endpoint, wallet, options);
expect(client.fees).toEqual({
upload: {
amount: coins(4710000, "utest"),
gas: "1500000",
},
init: {
amount: coins(1570000, "utest"),
gas: "500000",
},
migrate: {
amount: coins(628000, "utest"),
gas: "200000",
},
exec: {
amount: coins(628000, "utest"),
gas: "200000",
},
send: {
amount: coins(251200, "utest"),
gas: "80000",
},
changeAdmin: {
amount: coins(251200, "utest"),
gas: "80000",
},
delegate: {
amount: coins(502400, "utest"),
gas: "160000",
},
transfer: {
amount: coins(502400, "utest"),
gas: "160000",
},
undelegate: {
amount: coins(502400, "utest"),
gas: "160000",
},
withdraw: {
amount: coins(502400, "utest"),
gas: "160000",
},
});
});
it("can be constructed with custom gas limits", async () => {
pendingWithoutWasmd();
const wallet = await DirectSecp256k1HdWallet.fromMnemonic(alice.mnemonic, { prefix: wasmd.prefix });
const options = {
prefix: wasmd.prefix,
gasLimits: {
send: 160000,
},
};
const client = await SigningCosmWasmClient.connectWithSigner(wasmd.endpoint, wallet, options);
expect(client.fees).toEqual({
upload: {
amount: coins(37500, "ucosm"),
gas: "1500000",
},
init: {
amount: coins(12500, "ucosm"),
gas: "500000",
},
migrate: {
amount: coins(5000, "ucosm"),
gas: "200000",
},
exec: {
amount: coins(5000, "ucosm"),
gas: "200000",
},
send: {
amount: coins(4000, "ucosm"),
gas: "160000",
},
changeAdmin: {
amount: coins(2000, "ucosm"),
gas: "80000",
},
delegate: {
amount: coins(4000, "ucosm"),
gas: "160000",
},
transfer: {
amount: coins(4000, "ucosm"),
gas: "160000",
},
undelegate: {
amount: coins(4000, "ucosm"),
gas: "160000",
},
withdraw: {
amount: coins(4000, "ucosm"),
gas: "160000",
},
});
});
it("can be constructed with custom gas price and gas limits", async () => {
pendingWithoutWasmd();
const wallet = await DirectSecp256k1HdWallet.fromMnemonic(alice.mnemonic, { prefix: wasmd.prefix });
const options = {
prefix: wasmd.prefix,
gasPrice: GasPrice.fromString("3.14utest"),
gasLimits: {
send: 160000,
},
};
const client = await SigningCosmWasmClient.connectWithSigner(wasmd.endpoint, wallet, options);
expect(client.fees).toEqual({
upload: {
amount: coins(4710000, "utest"),
gas: "1500000",
},
init: {
amount: coins(1570000, "utest"),
gas: "500000",
},
migrate: {
amount: coins(628000, "utest"),
gas: "200000",
},
exec: {
amount: coins(628000, "utest"),
gas: "200000",
},
send: {
amount: coins(502400, "utest"),
gas: "160000",
},
changeAdmin: {
amount: coins(251200, "utest"),
gas: "80000",
},
delegate: {
amount: coins(502400, "utest"),
gas: "160000",
},
transfer: {
amount: coins(502400, "utest"),
gas: "160000",
},
undelegate: {
amount: coins(502400, "utest"),
gas: "160000",
},
withdraw: {
amount: coins(502400, "utest"),
gas: "160000",
},
});
});
});
describe("upload", () => {
@ -228,7 +73,7 @@ describe("SigningCosmWasmClient", () => {
const client = await SigningCosmWasmClient.connectWithSigner(wasmd.endpoint, wallet, options);
const wasm = getHackatom().data;
const { codeId, originalChecksum, originalSize, compressedChecksum, compressedSize } =
await client.upload(alice.address0, wasm);
await client.upload(alice.address0, wasm, defaultUploadFee);
expect(originalChecksum).toEqual(toHex(sha256(wasm)));
expect(originalSize).toEqual(wasm.length);
expect(compressedChecksum).toMatch(/^[0-9a-f]{64}$/);
@ -246,7 +91,7 @@ describe("SigningCosmWasmClient", () => {
source: "https://crates.io/api/v1/crates/cw-nameservice/0.1.0/download",
builder: "confio/cosmwasm-opt:0.6.2",
};
const { codeId } = await client.upload(alice.address0, hackatom.data, meta);
const { codeId } = await client.upload(alice.address0, hackatom.data, defaultUploadFee, meta);
const codeDetails = await client.getCodeDetails(codeId);
expect(codeDetails.source).toEqual(meta.source);
expect(codeDetails.builder).toEqual(meta.builder);
@ -259,7 +104,7 @@ describe("SigningCosmWasmClient", () => {
const wallet = await DirectSecp256k1HdWallet.fromMnemonic(alice.mnemonic, { prefix: wasmd.prefix });
const options = { prefix: wasmd.prefix };
const client = await SigningCosmWasmClient.connectWithSigner(wasmd.endpoint, wallet, options);
const { codeId } = await client.upload(alice.address0, getHackatom().data);
const { codeId } = await client.upload(alice.address0, getHackatom().data, defaultUploadFee);
const funds = [coin(1234, "ucosm"), coin(321, "ustake")];
const beneficiaryAddress = makeRandomAddress();
const { contractAddress } = await client.instantiate(
@ -270,6 +115,7 @@ describe("SigningCosmWasmClient", () => {
beneficiary: beneficiaryAddress,
},
"My cool label",
defaultInstantiateFee,
{
memo: "Let's see if the memo is used",
funds: funds,
@ -287,7 +133,7 @@ describe("SigningCosmWasmClient", () => {
const wallet = await DirectSecp256k1HdWallet.fromMnemonic(alice.mnemonic, { prefix: wasmd.prefix });
const options = { prefix: wasmd.prefix };
const client = await SigningCosmWasmClient.connectWithSigner(wasmd.endpoint, wallet, options);
const { codeId } = await client.upload(alice.address0, getHackatom().data);
const { codeId } = await client.upload(alice.address0, getHackatom().data, defaultUploadFee);
const beneficiaryAddress = makeRandomAddress();
const { contractAddress } = await client.instantiate(
alice.address0,
@ -297,6 +143,7 @@ describe("SigningCosmWasmClient", () => {
beneficiary: beneficiaryAddress,
},
"My cool label",
defaultInstantiateFee,
{ admin: unused.address },
);
const wasmClient = await makeWasmClient(wasmd.endpoint);
@ -310,7 +157,7 @@ describe("SigningCosmWasmClient", () => {
const wallet = await DirectSecp256k1HdWallet.fromMnemonic(alice.mnemonic, { prefix: wasmd.prefix });
const options = { prefix: wasmd.prefix };
const client = await SigningCosmWasmClient.connectWithSigner(wasmd.endpoint, wallet, options);
const { codeId } = await client.upload(alice.address0, getHackatom().data);
const { codeId } = await client.upload(alice.address0, getHackatom().data, defaultUploadFee);
const contractAddress1 = await client.instantiate(
alice.address0,
codeId,
@ -319,6 +166,7 @@ describe("SigningCosmWasmClient", () => {
beneficiary: makeRandomAddress(),
},
"contract 1",
defaultInstantiateFee,
);
const contractAddress2 = await client.instantiate(
alice.address0,
@ -328,6 +176,7 @@ describe("SigningCosmWasmClient", () => {
beneficiary: makeRandomAddress(),
},
"contract 2",
defaultInstantiateFee,
);
expect(contractAddress1).not.toEqual(contractAddress2);
});
@ -339,7 +188,7 @@ describe("SigningCosmWasmClient", () => {
const wallet = await DirectSecp256k1HdWallet.fromMnemonic(alice.mnemonic, { prefix: wasmd.prefix });
const options = { prefix: wasmd.prefix };
const client = await SigningCosmWasmClient.connectWithSigner(wasmd.endpoint, wallet, options);
const { codeId } = await client.upload(alice.address0, getHackatom().data);
const { codeId } = await client.upload(alice.address0, getHackatom().data, defaultUploadFee);
const beneficiaryAddress = makeRandomAddress();
const { contractAddress } = await client.instantiate(
alice.address0,
@ -349,6 +198,8 @@ describe("SigningCosmWasmClient", () => {
beneficiary: beneficiaryAddress,
},
"My cool label",
defaultInstantiateFee,
{
admin: alice.address0,
},
@ -358,7 +209,7 @@ describe("SigningCosmWasmClient", () => {
assert(contractInfo1);
expect(contractInfo1.admin).toEqual(alice.address0);
await client.updateAdmin(alice.address0, contractAddress, unused.address);
await client.updateAdmin(alice.address0, contractAddress, unused.address, defaultUpdateAdminFee);
const { contractInfo: contractInfo2 } = await wasmClient.wasm.getContractInfo(contractAddress);
assert(contractInfo2);
expect(contractInfo2.admin).toEqual(unused.address);
@ -371,7 +222,7 @@ describe("SigningCosmWasmClient", () => {
const wallet = await DirectSecp256k1HdWallet.fromMnemonic(alice.mnemonic, { prefix: wasmd.prefix });
const options = { prefix: wasmd.prefix };
const client = await SigningCosmWasmClient.connectWithSigner(wasmd.endpoint, wallet, options);
const { codeId } = await client.upload(alice.address0, getHackatom().data);
const { codeId } = await client.upload(alice.address0, getHackatom().data, defaultUploadFee);
const beneficiaryAddress = makeRandomAddress();
const { contractAddress } = await client.instantiate(
alice.address0,
@ -381,6 +232,7 @@ describe("SigningCosmWasmClient", () => {
beneficiary: beneficiaryAddress,
},
"My cool label",
defaultInstantiateFee,
{
admin: alice.address0,
},
@ -390,7 +242,7 @@ describe("SigningCosmWasmClient", () => {
assert(contractInfo1);
expect(contractInfo1.admin).toEqual(alice.address0);
await client.clearAdmin(alice.address0, contractAddress);
await client.clearAdmin(alice.address0, contractAddress, defaultClearAdminFee);
const { contractInfo: contractInfo2 } = await wasmClient.wasm.getContractInfo(contractAddress);
assert(contractInfo2);
expect(contractInfo2.admin).toEqual("");
@ -403,8 +255,8 @@ describe("SigningCosmWasmClient", () => {
const wallet = await DirectSecp256k1HdWallet.fromMnemonic(alice.mnemonic, { prefix: wasmd.prefix });
const options = { prefix: wasmd.prefix };
const client = await SigningCosmWasmClient.connectWithSigner(wasmd.endpoint, wallet, options);
const { codeId: codeId1 } = await client.upload(alice.address0, getHackatom().data);
const { codeId: codeId2 } = await client.upload(alice.address0, getHackatom().data);
const { codeId: codeId1 } = await client.upload(alice.address0, getHackatom().data, defaultUploadFee);
const { codeId: codeId2 } = await client.upload(alice.address0, getHackatom().data, defaultUploadFee);
const beneficiaryAddress = makeRandomAddress();
const { contractAddress } = await client.instantiate(
alice.address0,
@ -414,6 +266,7 @@ describe("SigningCosmWasmClient", () => {
beneficiary: beneficiaryAddress,
},
"My cool label",
defaultInstantiateFee,
{
admin: alice.address0,
},
@ -424,7 +277,13 @@ describe("SigningCosmWasmClient", () => {
expect(contractInfo1.admin).toEqual(alice.address0);
const newVerifier = makeRandomAddress();
await client.migrate(alice.address0, contractAddress, codeId2, { verifier: newVerifier });
await client.migrate(
alice.address0,
contractAddress,
codeId2,
{ verifier: newVerifier },
defaultMigrateFee,
);
const { contractInfo: contractInfo2 } = await wasmClient.wasm.getContractInfo(contractAddress);
assert(contractInfo2);
expect({ ...contractInfo2 }).toEqual({
@ -440,7 +299,7 @@ describe("SigningCosmWasmClient", () => {
const wallet = await DirectSecp256k1HdWallet.fromMnemonic(alice.mnemonic, { prefix: wasmd.prefix });
const options = { prefix: wasmd.prefix };
const client = await SigningCosmWasmClient.connectWithSigner(wasmd.endpoint, wallet, options);
const { codeId } = await client.upload(alice.address0, getHackatom().data);
const { codeId } = await client.upload(alice.address0, getHackatom().data, defaultUploadFee);
// instantiate
const funds = [coin(233444, "ucosm"), coin(5454, "ustake")];
const beneficiaryAddress = makeRandomAddress();
@ -452,12 +311,18 @@ describe("SigningCosmWasmClient", () => {
beneficiary: beneficiaryAddress,
},
"amazing random contract",
defaultInstantiateFee,
{
funds: funds,
},
);
// execute
const result = await client.execute(alice.address0, contractAddress, { release: {} }, undefined);
const result = await client.execute(
alice.address0,
contractAddress,
{ release: {} },
defaultExecuteFee,
);
const wasmEvent = result.logs[0].events.find((e) => e.type === "wasm");
assert(wasmEvent, "Event of type wasm expected");
expect(wasmEvent.attributes).toContain({ key: "action", value: "release" });
@ -497,7 +362,13 @@ describe("SigningCosmWasmClient", () => {
});
// send
const result = await client.sendTokens(alice.address0, beneficiaryAddress, amount, memo);
const result = await client.sendTokens(
alice.address0,
beneficiaryAddress,
amount,
defaultSendFee,
memo,
);
assertIsBroadcastTxSuccess(result);
expect(result.rawLog).toBeTruthy();
@ -525,7 +396,13 @@ describe("SigningCosmWasmClient", () => {
});
// send
const result = await client.sendTokens(alice.address0, beneficiaryAddress, amount, memo);
const result = await client.sendTokens(
alice.address0,
beneficiaryAddress,
amount,
defaultSendFee,
memo,
);
assertIsBroadcastTxSuccess(result);
expect(result.rawLog).toBeTruthy();

View File

@ -18,14 +18,8 @@ import {
AminoTypes,
BroadcastTxFailure,
BroadcastTxResponse,
buildFeeTable,
Coin,
CosmosFeeTable,
defaultGasLimits as defaultStargateGasLimits,
defaultGasPrice,
defaultRegistryTypes,
GasLimits,
GasPrice,
isBroadcastTxFailure,
logs,
MsgDelegateEncodeObject,
@ -63,18 +57,6 @@ import {
MsgUpdateAdminEncodeObject,
} from "./encodeobjects";
/**
* These fees are used by the higher level methods of SigningCosmWasmClient
*/
export interface CosmWasmFeeTable extends CosmosFeeTable {
readonly upload: StdFee;
readonly init: StdFee;
readonly exec: StdFee;
readonly migrate: StdFee;
/** Paid when setting the contract admin to a new address or unsetting it */
readonly changeAdmin: StdFee;
}
function prepareBuilder(builder: string | undefined): string {
if (builder === undefined) {
return ""; // normalization needed by backend
@ -84,15 +66,6 @@ function prepareBuilder(builder: string | undefined): string {
}
}
export const defaultGasLimits: GasLimits<CosmWasmFeeTable> = {
...defaultStargateGasLimits,
upload: 1_500_000,
init: 500_000,
migrate: 200_000,
exec: 200_000,
changeAdmin: 80_000,
};
export interface UploadMeta {
/**
* An URL to a .tar.gz archive of the source code of the contract, which can be used to reproducibly build the Wasm bytecode.
@ -195,14 +168,11 @@ export interface SigningCosmWasmClientOptions {
readonly registry?: Registry;
readonly aminoTypes?: AminoTypes;
readonly prefix?: string;
readonly gasPrice?: GasPrice;
readonly gasLimits?: Partial<GasLimits<CosmWasmFeeTable>>;
readonly broadcastTimeoutMs?: number;
readonly broadcastPollIntervalMs?: number;
}
export class SigningCosmWasmClient extends CosmWasmClient {
public readonly fees: CosmWasmFeeTable;
public readonly registry: Registry;
public readonly broadcastTimeoutMs: number | undefined;
public readonly broadcastPollIntervalMs: number | undefined;
@ -244,10 +214,7 @@ export class SigningCosmWasmClient extends CosmWasmClient {
const {
registry = createDefaultRegistry(),
aminoTypes = new AminoTypes({ additions: cosmWasmTypes, prefix: options.prefix }),
gasPrice = defaultGasPrice,
gasLimits = {},
} = options;
this.fees = buildFeeTable<CosmWasmFeeTable>(gasPrice, defaultGasLimits, gasLimits);
this.registry = registry;
this.aminoTypes = aminoTypes;
this.signer = signer;
@ -259,6 +226,7 @@ export class SigningCosmWasmClient extends CosmWasmClient {
public async upload(
senderAddress: string,
wasmCode: Uint8Array,
fee: StdFee,
meta: UploadMeta = {},
memo = "",
): Promise<UploadResult> {
@ -275,7 +243,7 @@ export class SigningCosmWasmClient extends CosmWasmClient {
}),
};
const result = await this.signAndBroadcast(senderAddress, [storeCodeMsg], this.fees.upload, memo);
const result = await this.signAndBroadcast(senderAddress, [storeCodeMsg], fee, memo);
if (isBroadcastTxFailure(result)) {
throw new Error(createBroadcastTxErrorMessage(result));
}
@ -297,6 +265,7 @@ export class SigningCosmWasmClient extends CosmWasmClient {
codeId: number,
msg: Record<string, unknown>,
label: string,
fee: StdFee,
options: InstantiateOptions = {},
): Promise<InstantiateResult> {
const instantiateContractMsg: MsgInstantiateContractEncodeObject = {
@ -310,12 +279,7 @@ export class SigningCosmWasmClient extends CosmWasmClient {
admin: options.admin,
}),
};
const result = await this.signAndBroadcast(
senderAddress,
[instantiateContractMsg],
this.fees.init,
options.memo,
);
const result = await this.signAndBroadcast(senderAddress, [instantiateContractMsg], fee, options.memo);
if (isBroadcastTxFailure(result)) {
throw new Error(createBroadcastTxErrorMessage(result));
}
@ -332,6 +296,7 @@ export class SigningCosmWasmClient extends CosmWasmClient {
senderAddress: string,
contractAddress: string,
newAdmin: string,
fee: StdFee,
memo = "",
): Promise<ChangeAdminResult> {
const updateAdminMsg: MsgUpdateAdminEncodeObject = {
@ -342,7 +307,7 @@ export class SigningCosmWasmClient extends CosmWasmClient {
newAdmin: newAdmin,
}),
};
const result = await this.signAndBroadcast(senderAddress, [updateAdminMsg], this.fees.changeAdmin, memo);
const result = await this.signAndBroadcast(senderAddress, [updateAdminMsg], fee, memo);
if (isBroadcastTxFailure(result)) {
throw new Error(createBroadcastTxErrorMessage(result));
}
@ -355,6 +320,7 @@ export class SigningCosmWasmClient extends CosmWasmClient {
public async clearAdmin(
senderAddress: string,
contractAddress: string,
fee: StdFee,
memo = "",
): Promise<ChangeAdminResult> {
const clearAdminMsg: MsgClearAdminEncodeObject = {
@ -364,7 +330,7 @@ export class SigningCosmWasmClient extends CosmWasmClient {
contract: contractAddress,
}),
};
const result = await this.signAndBroadcast(senderAddress, [clearAdminMsg], this.fees.changeAdmin, memo);
const result = await this.signAndBroadcast(senderAddress, [clearAdminMsg], fee, memo);
if (isBroadcastTxFailure(result)) {
throw new Error(createBroadcastTxErrorMessage(result));
}
@ -379,6 +345,7 @@ export class SigningCosmWasmClient extends CosmWasmClient {
contractAddress: string,
codeId: number,
migrateMsg: Record<string, unknown>,
fee: StdFee,
memo = "",
): Promise<MigrateResult> {
const migrateContractMsg: MsgMigrateContractEncodeObject = {
@ -390,7 +357,7 @@ export class SigningCosmWasmClient extends CosmWasmClient {
migrateMsg: toUtf8(JSON.stringify(migrateMsg)),
}),
};
const result = await this.signAndBroadcast(senderAddress, [migrateContractMsg], this.fees.migrate, memo);
const result = await this.signAndBroadcast(senderAddress, [migrateContractMsg], fee, memo);
if (isBroadcastTxFailure(result)) {
throw new Error(createBroadcastTxErrorMessage(result));
}
@ -404,6 +371,7 @@ export class SigningCosmWasmClient extends CosmWasmClient {
senderAddress: string,
contractAddress: string,
msg: Record<string, unknown>,
fee: StdFee,
memo = "",
funds?: readonly Coin[],
): Promise<ExecuteResult> {
@ -416,7 +384,7 @@ export class SigningCosmWasmClient extends CosmWasmClient {
funds: [...(funds || [])],
}),
};
const result = await this.signAndBroadcast(senderAddress, [executeContractMsg], this.fees.exec, memo);
const result = await this.signAndBroadcast(senderAddress, [executeContractMsg], fee, memo);
if (isBroadcastTxFailure(result)) {
throw new Error(createBroadcastTxErrorMessage(result));
}
@ -430,6 +398,7 @@ export class SigningCosmWasmClient extends CosmWasmClient {
senderAddress: string,
recipientAddress: string,
amount: readonly Coin[],
fee: StdFee,
memo = "",
): Promise<BroadcastTxResponse> {
const sendMsg: MsgSendEncodeObject = {
@ -440,45 +409,48 @@ export class SigningCosmWasmClient extends CosmWasmClient {
amount: [...amount],
},
};
return this.signAndBroadcast(senderAddress, [sendMsg], this.fees.send, memo);
return this.signAndBroadcast(senderAddress, [sendMsg], fee, memo);
}
public async delegateTokens(
delegatorAddress: string,
validatorAddress: string,
amount: Coin,
fee: StdFee,
memo = "",
): Promise<BroadcastTxResponse> {
const delegateMsg: MsgDelegateEncodeObject = {
typeUrl: "/cosmos.staking.v1beta1.MsgDelegate",
value: MsgDelegate.fromPartial({ delegatorAddress: delegatorAddress, validatorAddress, amount }),
};
return this.signAndBroadcast(delegatorAddress, [delegateMsg], this.fees.delegate, memo);
return this.signAndBroadcast(delegatorAddress, [delegateMsg], fee, memo);
}
public async undelegateTokens(
delegatorAddress: string,
validatorAddress: string,
amount: Coin,
fee: StdFee,
memo = "",
): Promise<BroadcastTxResponse> {
const undelegateMsg: MsgUndelegateEncodeObject = {
typeUrl: "/cosmos.staking.v1beta1.MsgUndelegate",
value: MsgUndelegate.fromPartial({ delegatorAddress: delegatorAddress, validatorAddress, amount }),
};
return this.signAndBroadcast(delegatorAddress, [undelegateMsg], this.fees.undelegate, memo);
return this.signAndBroadcast(delegatorAddress, [undelegateMsg], fee, memo);
}
public async withdrawRewards(
delegatorAddress: string,
validatorAddress: string,
fee: StdFee,
memo = "",
): Promise<BroadcastTxResponse> {
const withdrawDelegatorRewardMsg: MsgWithdrawDelegatorRewardEncodeObject = {
typeUrl: "/cosmos.distribution.v1beta1.MsgWithdrawDelegatorReward",
value: MsgWithdrawDelegatorReward.fromPartial({ delegatorAddress: delegatorAddress, validatorAddress }),
};
return this.signAndBroadcast(delegatorAddress, [withdrawDelegatorRewardMsg], this.fees.withdraw, memo);
return this.signAndBroadcast(delegatorAddress, [withdrawDelegatorRewardMsg], fee, memo);
}
/**

View File

@ -11,7 +11,9 @@ import {
import {
AuthExtension,
BankExtension,
calculateFee,
coins,
GasPrice,
QueryClient,
setupAuthExtension,
setupBankExtension,
@ -23,6 +25,15 @@ import { AuthInfo, SignDoc, TxBody } from "cosmjs-types/cosmos/tx/v1beta1/tx";
import { setupWasmExtension, WasmExtension } from "./queries";
import hackatom from "./testdata/contract.json";
export const defaultGasPrice = GasPrice.fromString("0.025ucosm");
export const defaultSendFee = calculateFee(80_000, defaultGasPrice);
export const defaultUploadFee = calculateFee(1_500_000, defaultGasPrice);
export const defaultInstantiateFee = calculateFee(500_000, defaultGasPrice);
export const defaultExecuteFee = calculateFee(200_000, defaultGasPrice);
export const defaultMigrateFee = calculateFee(200_000, defaultGasPrice);
export const defaultUpdateAdminFee = calculateFee(80_000, defaultGasPrice);
export const defaultClearAdminFee = calculateFee(80_000, defaultGasPrice);
/** An internal testing type. SigningCosmWasmClient has a similar but different interface */
export interface ContractUploadInstructions {
/** The wasm bytecode */

View File

@ -5,6 +5,7 @@ import {
} from "@cosmjs/launchpad";
import {
assertIsBroadcastTxSuccess as assertIsBroadcastTxSuccessStargate,
calculateFee,
SigningStargateClient,
StargateClient,
} from "@cosmjs/stargate";
@ -88,7 +89,8 @@ export class Faucet {
const result = await client.sendTokens(job.recipient, [job.amount], constants.memo);
return assertIsBroadcastTxSuccessLaunchpad(result);
}
const result = await client.sendTokens(job.sender, job.recipient, [job.amount], constants.memo);
const fee = calculateFee(constants.gasLimits.send, constants.gasPrice);
const result = await client.sendTokens(job.sender, job.recipient, [job.amount], fee, constants.memo);
assertIsBroadcastTxSuccessStargate(result);
}

View File

@ -43,10 +43,7 @@ export async function createClients(
> => [
senderAddress,
isOfflineDirectSigner(wallet)
? await SigningStargateClient.connectWithSigner(apiUrl, wallet, {
gasLimits: constants.gasLimits,
gasPrice: constants.gasPrice,
})
? await SigningStargateClient.connectWithSigner(apiUrl, wallet)
: new SigningCosmosClient(apiUrl, senderAddress, wallet, constants.gasPrice, constants.gasLimits),
],
),

View File

@ -6,7 +6,6 @@ import {
makeSignDoc,
Secp256k1HdWallet,
serializeSignDoc,
StdFee,
} from "@cosmjs/amino";
import { Secp256k1, Secp256k1Signature, sha256 } from "@cosmjs/crypto";
import { fromBase64 } from "@cosmjs/encoding";
@ -16,6 +15,7 @@ import {
} from "@cosmjs/launchpad";
import {
assertIsBroadcastTxSuccess as assertIsBroadcastTxSuccessStargate,
calculateFee,
SigningStargateClient,
} from "@cosmjs/stargate";
import { sleep } from "@cosmjs/utils";
@ -53,10 +53,7 @@ async function createTransport(): Promise<Transport> {
describe("LedgerSigner", () => {
const defaultChainId = "testing";
const defaultFee: StdFee = {
amount: coins(100, "ucosm"),
gas: "250",
};
const defaultFee = calculateFee(80_000, "0.025ucosm");
const defaultMemo = "Some memo";
const defaultSequence = "0";
const defaultAccountNumber = "42";
@ -69,7 +66,13 @@ describe("LedgerSigner", () => {
const client = await SigningStargateClient.connectWithSigner(simapp.endpoint, wallet);
const amount = coins(226644, "ucosm");
const memo = "Ensure chain has my pubkey";
const sendResult = await client.sendTokens(faucet.address, defaultLedgerAddress, amount, memo);
const sendResult = await client.sendTokens(
faucet.address,
defaultLedgerAddress,
amount,
defaultFee,
memo,
);
assertIsBroadcastTxSuccessStargate(sendResult);
}
});
@ -197,6 +200,7 @@ describe("LedgerSigner", () => {
firstAccount.address,
defaultLedgerAddress,
coins(1234, "ucosm"),
defaultFee,
);
assertIsBroadcastTxSuccessStargate(result);
},

View File

@ -1,6 +1,6 @@
import { Decimal } from "@cosmjs/math";
import { GasPrice } from "./fee";
import { calculateFee, GasPrice } from "./fee";
describe("GasPrice", () => {
it("can be constructed", () => {
@ -59,3 +59,25 @@ describe("GasPrice", () => {
});
});
});
describe("calculateFee", () => {
it("multiplies the gas price by the gas limit", () => {
const gasLimit = 80000;
const gasPrice = GasPrice.fromString("0.025ucosm");
const fee = calculateFee(gasLimit, gasPrice);
expect(fee).toEqual({
amount: [{ amount: "2000", denom: "ucosm" }],
gas: "80000",
});
});
it("accepts a string gas price", () => {
const gasLimit = 80000;
const gasPrice = "0.025ucosm";
const fee = calculateFee(gasLimit, gasPrice);
expect(fee).toEqual({
amount: [{ amount: "2000", denom: "ucosm" }],
gas: "80000",
});
});
});

View File

@ -2,11 +2,6 @@ import { StdFee } from "@cosmjs/amino";
import { Decimal, Uint53 } from "@cosmjs/math";
import { coins } from "@cosmjs/proto-signing";
/**
* This is the same as FeeTable from @cosmjs/launchpad but those might diverge in the future.
*/
export type FeeTable = Record<string, StdFee>;
/**
* Denom checker for the Cosmos SDK 0.42 denom pattern
* (https://github.com/cosmos/cosmos-sdk/blob/v0.42.4/types/coin.go#L599-L601).
@ -56,37 +51,12 @@ export class GasPrice {
}
}
/**
* This is the same as GasLimits from @cosmjs/launchpad but those might diverge in the future.
*/
export type GasLimits<T extends Record<string, StdFee>> = {
readonly [key in keyof T]: number;
};
/**
* This is the same as calculateFee from @cosmjs/launchpad but those might diverge in the future.
*/
function calculateFee(gasLimit: number, { denom, amount: gasPriceAmount }: GasPrice): StdFee {
export function calculateFee(gasLimit: number, gasPrice: GasPrice | string): StdFee {
const processedGasPrice = typeof gasPrice === "string" ? GasPrice.fromString(gasPrice) : gasPrice;
const { denom, amount: gasPriceAmount } = processedGasPrice;
const amount = Math.ceil(gasPriceAmount.multiply(new Uint53(gasLimit)).toFloatApproximation());
return {
amount: coins(amount, denom),
gas: gasLimit.toString(),
};
}
/**
* This is the same as buildFeeTable from @cosmjs/launchpad but those might diverge in the future.
*/
export function buildFeeTable<T extends Record<string, StdFee>>(
gasPrice: GasPrice,
defaultGasLimits: GasLimits<T>,
gasLimits: Partial<GasLimits<T>>,
): T {
return Object.entries(defaultGasLimits).reduce(
(feeTable, [type, defaultGasLimit]) => ({
...feeTable,
[type]: calculateFee(gasLimits[type] || defaultGasLimit, gasPrice),
}),
{} as T,
);
}

View File

@ -51,7 +51,7 @@ export {
MsgUndelegateEncodeObject,
MsgWithdrawDelegatorRewardEncodeObject,
} from "./encodeobjects";
export { buildFeeTable, FeeTable, GasLimits, GasPrice } from "./fee";
export { calculateFee, GasPrice } from "./fee";
export * as logs from "./logs";
export { makeMultisignedTx } from "./multisignature";
export {
@ -95,9 +95,6 @@ export {
TimeoutError,
} from "./stargateclient";
export {
CosmosFeeTable,
defaultGasLimits,
defaultGasPrice,
defaultRegistryTypes,
SignerData,
SigningStargateClient,

View File

@ -12,10 +12,10 @@ import { decodeTxRaw } from "../../proto-signing/build";
import { AminoMsgDelegate } from "./aminomsgs";
import { AminoTypes } from "./aminotypes";
import { MsgDelegateEncodeObject, MsgSendEncodeObject } from "./encodeobjects";
import { GasPrice } from "./fee";
import { PrivateSigningStargateClient, SigningStargateClient } from "./signingstargateclient";
import { assertIsBroadcastTxSuccess } from "./stargateclient";
import {
defaultSendFee,
faucet,
makeRandomAddress,
ModifyingDirectSecp256k1HdWallet,
@ -27,60 +27,6 @@ import {
describe("SigningStargateClient", () => {
describe("constructor", () => {
it("can be constructed with default fees", async () => {
pendingWithoutSimapp();
const wallet = await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic);
const client = await SigningStargateClient.connectWithSigner(simapp.tendermintUrl, wallet);
const openedClient = client as unknown as PrivateSigningStargateClient;
expect(openedClient.fees).toEqual({
send: {
amount: [
{
amount: "2000",
denom: "ucosm",
},
],
gas: "80000",
},
delegate: {
amount: [
{
amount: "4000",
denom: "ucosm",
},
],
gas: "160000",
},
transfer: {
amount: [
{
amount: "4000",
denom: "ucosm",
},
],
gas: "160000",
},
undelegate: {
amount: [
{
amount: "4000",
denom: "ucosm",
},
],
gas: "160000",
},
withdraw: {
amount: [
{
amount: "4000",
denom: "ucosm",
},
],
gas: "160000",
},
});
});
it("can be constructed with custom registry", async () => {
pendingWithoutSimapp();
const wallet = await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic);
@ -91,180 +37,6 @@ describe("SigningStargateClient", () => {
const openedClient = client as unknown as PrivateSigningStargateClient;
expect(openedClient.registry.lookupType("/custom.MsgCustom")).toEqual(MsgSend);
});
it("can be constructed with custom gas price", async () => {
pendingWithoutSimapp();
const wallet = await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic);
const gasPrice = GasPrice.fromString("3.14utest");
const options = { gasPrice: gasPrice };
const client = await SigningStargateClient.connectWithSigner(simapp.tendermintUrl, wallet, options);
const openedClient = client as unknown as PrivateSigningStargateClient;
expect(openedClient.fees).toEqual({
send: {
amount: [
{
amount: "251200", // 3.14 * 80_000
denom: "utest",
},
],
gas: "80000",
},
delegate: {
amount: [
{
amount: "502400", // 3.14 * 160_000
denom: "utest",
},
],
gas: "160000",
},
transfer: {
amount: [
{
amount: "502400",
denom: "utest",
},
],
gas: "160000",
},
undelegate: {
amount: [
{
amount: "502400",
denom: "utest",
},
],
gas: "160000",
},
withdraw: {
amount: [
{
amount: "502400",
denom: "utest",
},
],
gas: "160000",
},
});
});
it("can be constructed with custom gas limits", async () => {
pendingWithoutSimapp();
const wallet = await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic);
const gasLimits = {
send: 160000,
delegate: 120000,
};
const options = { gasLimits: gasLimits };
const client = await SigningStargateClient.connectWithSigner(simapp.tendermintUrl, wallet, options);
const openedClient = client as unknown as PrivateSigningStargateClient;
expect(openedClient.fees).toEqual({
send: {
amount: [
{
amount: "4000", // 0.025 * 160_000
denom: "ucosm",
},
],
gas: "160000",
},
delegate: {
amount: [
{
amount: "3000", // 0.025 * 120_000
denom: "ucosm",
},
],
gas: "120000",
},
transfer: {
amount: [
{
amount: "4000",
denom: "ucosm",
},
],
gas: "160000",
},
undelegate: {
amount: [
{
amount: "4000",
denom: "ucosm",
},
],
gas: "160000",
},
withdraw: {
amount: [
{
amount: "4000",
denom: "ucosm",
},
],
gas: "160000",
},
});
});
it("can be constructed with custom gas price and gas limits", async () => {
pendingWithoutSimapp();
const wallet = await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic);
const gasPrice = GasPrice.fromString("3.14utest");
const gasLimits = {
send: 160000,
};
const options = { gasPrice: gasPrice, gasLimits: gasLimits };
const client = await SigningStargateClient.connectWithSigner(simapp.tendermintUrl, wallet, options);
const openedClient = client as unknown as PrivateSigningStargateClient;
expect(openedClient.fees).toEqual({
send: {
amount: [
{
amount: "502400", // 3.14 * 160_000
denom: "utest",
},
],
gas: "160000",
},
delegate: {
amount: [
{
amount: "502400", // 3.14 * 160_000
denom: "utest",
},
],
gas: "160000",
},
transfer: {
amount: [
{
amount: "502400",
denom: "utest",
},
],
gas: "160000",
},
undelegate: {
amount: [
{
amount: "502400",
denom: "utest",
},
],
gas: "160000",
},
withdraw: {
amount: [
{
amount: "502400",
denom: "utest",
},
],
gas: "160000",
},
});
});
});
describe("sendTokens", () => {
@ -285,7 +57,13 @@ describe("SigningStargateClient", () => {
});
// send
const result = await client.sendTokens(faucet.address0, beneficiaryAddress, amount, memo);
const result = await client.sendTokens(
faucet.address0,
beneficiaryAddress,
amount,
defaultSendFee,
memo,
);
assertIsBroadcastTxSuccess(result);
expect(result.rawLog).toBeTruthy();
@ -311,7 +89,13 @@ describe("SigningStargateClient", () => {
});
// send
const result = await client.sendTokens(faucet.address0, beneficiaryAddress, amount, memo);
const result = await client.sendTokens(
faucet.address0,
beneficiaryAddress,
amount,
defaultSendFee,
memo,
);
assertIsBroadcastTxSuccess(result);
expect(result.rawLog).toBeTruthy();

View File

@ -67,31 +67,8 @@ import {
MsgUndelegateEncodeObject,
MsgWithdrawDelegatorRewardEncodeObject,
} from "./encodeobjects";
import { buildFeeTable, FeeTable, GasLimits, GasPrice } from "./fee";
import { BroadcastTxResponse, StargateClient } from "./stargateclient";
/**
* These fees are used by the higher level methods of SigningCosmosClient
*
* This is the same as CosmosFeeTable from @cosmjs/launchpad but those might diverge in the future.
*/
export interface CosmosFeeTable extends FeeTable {
readonly send: StdFee;
readonly delegate: StdFee;
readonly transfer: StdFee;
readonly undelegate: StdFee;
readonly withdraw: StdFee;
}
export const defaultGasPrice = GasPrice.fromString("0.025ucosm");
export const defaultGasLimits: GasLimits<CosmosFeeTable> = {
send: 80_000,
delegate: 160_000,
transfer: 160_000,
undelegate: 160_000,
withdraw: 160_000,
};
export const defaultRegistryTypes: ReadonlyArray<[string, GeneratedType]> = [
["/cosmos.bank.v1beta1.MsgMultiSend", MsgMultiSend],
["/cosmos.distribution.v1beta1.MsgFundCommunityPool", MsgFundCommunityPool],
@ -141,7 +118,6 @@ export interface SignerData {
/** Use for testing only */
export interface PrivateSigningStargateClient {
readonly fees: CosmosFeeTable;
readonly registry: Registry;
}
@ -149,14 +125,11 @@ export interface SigningStargateClientOptions {
readonly registry?: Registry;
readonly aminoTypes?: AminoTypes;
readonly prefix?: string;
readonly gasPrice?: GasPrice;
readonly gasLimits?: Partial<GasLimits<CosmosFeeTable>>;
readonly broadcastTimeoutMs?: number;
readonly broadcastPollIntervalMs?: number;
}
export class SigningStargateClient extends StargateClient {
public readonly fees: CosmosFeeTable;
public readonly registry: Registry;
public readonly broadcastTimeoutMs: number | undefined;
public readonly broadcastPollIntervalMs: number | undefined;
@ -195,13 +168,8 @@ export class SigningStargateClient extends StargateClient {
options: SigningStargateClientOptions,
) {
super(tmClient);
const {
registry = createDefaultRegistry(),
aminoTypes = new AminoTypes({ prefix: options.prefix }),
gasPrice = defaultGasPrice,
gasLimits = {},
} = options;
this.fees = buildFeeTable<CosmosFeeTable>(gasPrice, defaultGasLimits, gasLimits);
const { registry = createDefaultRegistry(), aminoTypes = new AminoTypes({ prefix: options.prefix }) } =
options;
this.registry = registry;
this.aminoTypes = aminoTypes;
this.signer = signer;
@ -213,6 +181,7 @@ export class SigningStargateClient extends StargateClient {
senderAddress: string,
recipientAddress: string,
amount: readonly Coin[],
fee: StdFee,
memo = "",
): Promise<BroadcastTxResponse> {
const sendMsg: MsgSendEncodeObject = {
@ -223,13 +192,14 @@ export class SigningStargateClient extends StargateClient {
amount: [...amount],
},
};
return this.signAndBroadcast(senderAddress, [sendMsg], this.fees.send, memo);
return this.signAndBroadcast(senderAddress, [sendMsg], fee, memo);
}
public async delegateTokens(
delegatorAddress: string,
validatorAddress: string,
amount: Coin,
fee: StdFee,
memo = "",
): Promise<BroadcastTxResponse> {
const delegateMsg: MsgDelegateEncodeObject = {
@ -240,13 +210,14 @@ export class SigningStargateClient extends StargateClient {
amount: amount,
}),
};
return this.signAndBroadcast(delegatorAddress, [delegateMsg], this.fees.delegate, memo);
return this.signAndBroadcast(delegatorAddress, [delegateMsg], fee, memo);
}
public async undelegateTokens(
delegatorAddress: string,
validatorAddress: string,
amount: Coin,
fee: StdFee,
memo = "",
): Promise<BroadcastTxResponse> {
const undelegateMsg: MsgUndelegateEncodeObject = {
@ -257,12 +228,13 @@ export class SigningStargateClient extends StargateClient {
amount: amount,
}),
};
return this.signAndBroadcast(delegatorAddress, [undelegateMsg], this.fees.undelegate, memo);
return this.signAndBroadcast(delegatorAddress, [undelegateMsg], fee, memo);
}
public async withdrawRewards(
delegatorAddress: string,
validatorAddress: string,
fee: StdFee,
memo = "",
): Promise<BroadcastTxResponse> {
const withdrawMsg: MsgWithdrawDelegatorRewardEncodeObject = {
@ -272,7 +244,7 @@ export class SigningStargateClient extends StargateClient {
validatorAddress: validatorAddress,
}),
};
return this.signAndBroadcast(delegatorAddress, [withdrawMsg], this.fees.withdraw, memo);
return this.signAndBroadcast(delegatorAddress, [withdrawMsg], fee, memo);
}
public async sendIbcTokens(
@ -284,6 +256,7 @@ export class SigningStargateClient extends StargateClient {
timeoutHeight: Height | undefined,
/** timeout in seconds */
timeoutTimestamp: number | undefined,
fee: StdFee,
memo = "",
): Promise<BroadcastTxResponse> {
const timeoutTimestampNanoseconds = timeoutTimestamp
@ -301,7 +274,7 @@ export class SigningStargateClient extends StargateClient {
timeoutTimestamp: timeoutTimestampNanoseconds,
}),
};
return this.signAndBroadcast(senderAddress, [transferMsg], this.fees.transfer, memo);
return this.signAndBroadcast(senderAddress, [transferMsg], fee, memo);
}
public async signAndBroadcast(

View File

@ -12,6 +12,8 @@ import {
import { SignMode } from "cosmjs-types/cosmos/tx/signing/v1beta1/signing";
import { AuthInfo, SignDoc, TxBody } from "cosmjs-types/cosmos/tx/v1beta1/tx";
import { calculateFee, GasPrice } from "./fee";
export function simappEnabled(): boolean {
return !!process.env.SIMAPP_ENABLED;
}
@ -46,6 +48,9 @@ export function fromOneElementArray<T>(elements: ArrayLike<T>): T {
return elements[0];
}
export const defaultGasPrice = GasPrice.fromString("0.025ucosm");
export const defaultSendFee = calculateFee(80_000, defaultGasPrice);
export const simapp = {
tendermintUrl: "localhost:26658",
tendermintUrlWs: "ws://localhost:26658",

View File

@ -1,8 +1,9 @@
#!/usr/bin/env -S yarn node
/* eslint-disable @typescript-eslint/naming-convention */
const { DirectSecp256k1HdWallet } = require("@cosmjs/proto-signing");
const { SigningCosmWasmClient } = require("@cosmjs/cosmwasm-stargate");
const { DirectSecp256k1HdWallet } = require("@cosmjs/proto-signing");
const { GasPrice, calculateFee } = require("@cosmjs/stargate");
const fs = require("fs");
const endpoint = "http://localhost:26659";
@ -21,11 +22,19 @@ const codeMeta = {
};
async function main() {
const gasPrice = GasPrice.fromString("0.025ucosm");
const wallet = await DirectSecp256k1HdWallet.fromMnemonic(alice.mnemonic, { prefix: "wasm" });
const client = await SigningCosmWasmClient.connectWithSigner(endpoint, wallet);
const wasm = fs.readFileSync(__dirname + "/contracts/cw1_subkeys.wasm");
const uploadReceipt = await client.upload(alice.address0, wasm, codeMeta, "Upload CW1 subkeys contract");
const uploadFee = calculateFee(1_500_000, gasPrice);
const uploadReceipt = await client.upload(
alice.address0,
wasm,
uploadFee,
codeMeta,
"Upload CW1 subkeys contract",
);
console.info(`Upload succeeded. Receipt: ${JSON.stringify(uploadReceipt)}`);
const initMsg = {
@ -33,16 +42,30 @@ async function main() {
mutable: true,
};
const label = "Subkey test";
const { contractAddress } = await client.instantiate(alice.address0, uploadReceipt.codeId, initMsg, label, {
memo: `Create a CW1 instance for ${alice.address0}`,
admin: alice.address0,
});
await client.sendTokens(alice.address0, contractAddress, [
const instantiateFee = calculateFee(500_000, gasPrice);
const { contractAddress } = await client.instantiate(
alice.address0,
uploadReceipt.codeId,
initMsg,
label,
instantiateFee,
{
amount: "1000",
denom: "ucosm",
memo: `Create a CW1 instance for ${alice.address0}`,
admin: alice.address0,
},
]);
);
const sendFee = calculateFee(80_000, gasPrice);
await client.sendTokens(
alice.address0,
contractAddress,
[
{
amount: "1000",
denom: "ucosm",
},
],
sendFee,
);
console.info(`Contract instantiated for ${alice.address0} subkey at ${contractAddress}`);
}

View File

@ -1,8 +1,9 @@
#!/usr/bin/env -S yarn node
/* eslint-disable @typescript-eslint/naming-convention */
const { DirectSecp256k1HdWallet } = require("@cosmjs/proto-signing");
const { SigningCosmWasmClient } = require("@cosmjs/cosmwasm-stargate");
const { DirectSecp256k1HdWallet } = require("@cosmjs/proto-signing");
const { GasPrice, calculateFee } = require("@cosmjs/stargate");
const fs = require("fs");
const endpoint = "http://localhost:26659";
@ -63,35 +64,46 @@ const initData = [
];
async function main() {
const gasPrice = GasPrice.fromString("0.025ucosm");
const wallet = await DirectSecp256k1HdWallet.fromMnemonic(alice.mnemonic, { prefix: "wasm" });
const client = await SigningCosmWasmClient.connectWithSigner(endpoint, wallet);
const wasm = fs.readFileSync(__dirname + "/contracts/cw3_fixed_multisig.wasm");
const uploadFee = calculateFee(1_500_000, gasPrice);
const uploadReceipt = await client.upload(
alice.address0,
wasm,
uploadFee,
codeMeta,
"Upload CW3 fixed multisig contract",
);
console.info(`Upload succeeded. Receipt: ${JSON.stringify(uploadReceipt)}`);
const instantiateFee = calculateFee(500_000, gasPrice);
const sendFee = calculateFee(80_000, gasPrice);
for (const { admin, initMsg, label } of initData) {
const { contractAddress } = await client.instantiate(
alice.address0,
uploadReceipt.codeId,
initMsg,
label,
instantiateFee,
{
memo: `Create a CW3 instance for ${initMsg.symbol}`,
admin: admin,
},
);
await client.sendTokens(alice.address0, contractAddress, [
{
amount: "1000",
denom: "ucosm",
},
]);
await client.sendTokens(
alice.address0,
contractAddress,
[
{
amount: "1000",
denom: "ucosm",
},
],
sendFee,
);
console.info(`Contract instantiated for ${label} at ${contractAddress}`);
}
}

View File

@ -1,8 +1,9 @@
#!/usr/bin/env -S yarn node
/* eslint-disable @typescript-eslint/naming-convention */
const { DirectSecp256k1HdWallet } = require("@cosmjs/proto-signing");
const { SigningCosmWasmClient } = require("@cosmjs/cosmwasm-stargate");
const { DirectSecp256k1HdWallet } = require("@cosmjs/proto-signing");
const { calculateFee, GasPrice } = require("@cosmjs/stargate");
const fs = require("fs");
const endpoint = "http://localhost:26659";
@ -48,18 +49,34 @@ const inits = [
];
async function main() {
const gasPrice = GasPrice.fromString("0.025ucosm");
const wallet = await DirectSecp256k1HdWallet.fromMnemonic(alice.mnemonic, { prefix: "wasm" });
const client = await SigningCosmWasmClient.connectWithSigner(endpoint, wallet);
const wasm = fs.readFileSync(__dirname + "/contracts/hackatom.wasm");
const uploadReceipt = await client.upload(alice.address0, wasm, codeMeta, "Upload hackatom contract");
const uploadFee = calculateFee(1_500_000, gasPrice);
const uploadReceipt = await client.upload(
alice.address0,
wasm,
uploadFee,
codeMeta,
"Upload hackatom contract",
);
console.info(`Upload succeeded. Receipt: ${JSON.stringify(uploadReceipt)}`);
const instantiateFee = calculateFee(500_000, gasPrice);
for (const { label, msg, admin } of inits) {
const { contractAddress } = await client.instantiate(alice.address0, uploadReceipt.codeId, msg, label, {
memo: `Create a hackatom instance in deploy_hackatom.js`,
admin: admin,
});
const { contractAddress } = await client.instantiate(
alice.address0,
uploadReceipt.codeId,
msg,
label,
instantiateFee,
{
memo: `Create a hackatom instance in deploy_hackatom.js`,
admin: admin,
},
);
console.info(`Contract instantiated at ${contractAddress}`);
}
}

View File

@ -5,7 +5,12 @@ const { coins } = require("@cosmjs/amino");
const { Random } = require("@cosmjs/crypto");
const { Bech32 } = require("@cosmjs/encoding");
const { DirectSecp256k1HdWallet } = require("@cosmjs/proto-signing");
const { assertIsBroadcastTxSuccess, SigningStargateClient } = require("@cosmjs/stargate");
const {
assertIsBroadcastTxSuccess,
SigningStargateClient,
calculateFee,
GasPrice,
} = require("@cosmjs/stargate");
const rpcUrl = "http://localhost:26659";
const prefix = "wasm";
@ -20,8 +25,9 @@ async function main() {
const client = await SigningStargateClient.connectWithSigner(rpcUrl, wallet, { prefix: prefix });
const recipient = Bech32.encode(prefix, Random.getBytes(20));
const amount = coins(226644, "ucosm");
const fee = calculateFee(80_000, "0.025ucosm");
const memo = "Ensure chain has my pubkey";
const sendResult = await client.sendTokens(faucet.address0, recipient, amount, memo);
const sendResult = await client.sendTokens(faucet.address0, recipient, amount, fee, memo);
assertIsBroadcastTxSuccess(sendResult);
}