diff --git a/packages/launchpad/src/lcdapi/distribution.spec.ts b/packages/launchpad/src/lcdapi/distribution.spec.ts index 38562109..66e7cd9b 100644 --- a/packages/launchpad/src/lcdapi/distribution.spec.ts +++ b/packages/launchpad/src/lcdapi/distribution.spec.ts @@ -33,7 +33,7 @@ describe("DistributionExtension", () => { beforeAll(async () => { if (wasmdEnabled()) { const wallet = await Secp256k1Wallet.fromMnemonic(faucet.mnemonic); - const client = new SigningCosmosClient(wasmd.endpoint, faucet.address, wallet, {}); + const client = new SigningCosmosClient(wasmd.endpoint, faucet.address, wallet); const chainId = await client.getChainId(); const msg: MsgDelegate = { diff --git a/packages/launchpad/src/lcdapi/gov.spec.ts b/packages/launchpad/src/lcdapi/gov.spec.ts index 44f79889..c6cd10d1 100644 --- a/packages/launchpad/src/lcdapi/gov.spec.ts +++ b/packages/launchpad/src/lcdapi/gov.spec.ts @@ -31,7 +31,7 @@ describe("GovExtension", () => { beforeAll(async () => { if (wasmdEnabled()) { const wallet = await Secp256k1Wallet.fromMnemonic(faucet.mnemonic); - const client = new SigningCosmosClient(wasmd.endpoint, faucet.address, wallet, {}); + const client = new SigningCosmosClient(wasmd.endpoint, faucet.address, wallet); const chainId = await client.getChainId(); const proposalMsg = { diff --git a/packages/launchpad/src/lcdapi/staking.spec.ts b/packages/launchpad/src/lcdapi/staking.spec.ts index 4580bf17..5127f65e 100644 --- a/packages/launchpad/src/lcdapi/staking.spec.ts +++ b/packages/launchpad/src/lcdapi/staking.spec.ts @@ -34,7 +34,7 @@ describe("StakingExtension", () => { beforeAll(async () => { if (wasmdEnabled()) { const wallet = await Secp256k1Wallet.fromMnemonic(faucet.mnemonic); - const client = new SigningCosmosClient(wasmd.endpoint, faucet.address, wallet, {}); + const client = new SigningCosmosClient(wasmd.endpoint, faucet.address, wallet); const chainId = await client.getChainId(); { diff --git a/packages/launchpad/src/signingcosmosclient.ts b/packages/launchpad/src/signingcosmosclient.ts index ea9a79e6..5160160b 100644 --- a/packages/launchpad/src/signingcosmosclient.ts +++ b/packages/launchpad/src/signingcosmosclient.ts @@ -8,19 +8,49 @@ import { StdFee, StdTx } from "./types"; import { OfflineSigner } from "./wallet"; /** - * Those fees are used by the higher level methods of SigningCosmosClient + * These fees are used by the higher level methods of SigningCosmosClient */ export interface FeeTable { readonly send: StdFee; } -const defaultFees: FeeTable = { - send: { - amount: coins(2000, "ucosm"), - gas: "80000", // 80k - }, +export class GasPrice { + readonly amount: number; + readonly denom: string; + + constructor(amount: number, denom: string) { + this.amount = amount; + this.denom = denom; + } +} + +export type GasLimits = { + readonly [key in keyof FeeTable]: number; }; +function calculateFee(gasLimit: number, denom: string, price: number): StdFee { + const amount = Math.ceil(price * gasLimit); + return { + amount: coins(amount, denom), + gas: gasLimit.toString(), + }; +} + +function buildFeeTable({ denom, amount }: GasPrice, gasLimits: GasLimits): FeeTable { + return Object.entries(gasLimits).reduce((feeTable, [type, gasLimit]) => { + if (gasLimit === undefined) { + return feeTable; + } + return { + ...feeTable, + [type]: calculateFee(gasLimit, denom, amount), + }; + }, {} as FeeTable); +} + +const defaultGasPrice: GasPrice = new GasPrice(0.025, "ucosm"); +const defaultGasLimits: GasLimits = { send: 80000 }; + export class SigningCosmosClient extends CosmosClient { public readonly senderAddress: string; @@ -36,14 +66,16 @@ export class SigningCosmosClient extends CosmosClient { * @param apiUrl The URL of a Cosmos SDK light client daemon API (sometimes called REST server or REST API) * @param senderAddress The address that will sign and send transactions using this instance * @param signer An implementation of OfflineSigner which can provide signatures for transactions, potentially requiring user input. - * @param customFees The fees that are paid for transactions + * @param gasPrice The price paid per unit of gas + * @param gasLimits Custom overrides for gas limits related to specific transaction types * @param broadcastMode Defines at which point of the transaction processing the broadcastTx method returns */ public constructor( apiUrl: string, senderAddress: string, signer: OfflineSigner, - customFees?: Partial, + gasPrice: GasPrice = defaultGasPrice, + gasLimits?: Partial, broadcastMode = BroadcastMode.Block, ) { super(apiUrl, broadcastMode); @@ -51,7 +83,12 @@ export class SigningCosmosClient extends CosmosClient { this.senderAddress = senderAddress; this.signer = signer; - this.fees = { ...defaultFees, ...(customFees || {}) }; + + const mergedGasLimits = { + ...defaultGasLimits, + ...gasLimits, + }; + this.fees = buildFeeTable(gasPrice, mergedGasLimits); } public async getSequence(address?: string): Promise { diff --git a/packages/launchpad/types/signingcosmosclient.d.ts b/packages/launchpad/types/signingcosmosclient.d.ts index 9e6062a2..d8974309 100644 --- a/packages/launchpad/types/signingcosmosclient.d.ts +++ b/packages/launchpad/types/signingcosmosclient.d.ts @@ -5,11 +5,19 @@ import { Msg } from "./msgs"; import { StdFee } from "./types"; import { OfflineSigner } from "./wallet"; /** - * Those fees are used by the higher level methods of SigningCosmosClient + * These fees are used by the higher level methods of SigningCosmosClient */ export interface FeeTable { readonly send: StdFee; } +export declare class GasPrice { + readonly amount: number; + readonly denom: string; + constructor(amount: number, denom: string); +} +export declare type GasLimits = { + readonly [key in keyof FeeTable]: number; +}; export declare class SigningCosmosClient extends CosmosClient { readonly senderAddress: string; private readonly signer; @@ -23,14 +31,16 @@ export declare class SigningCosmosClient extends CosmosClient { * @param apiUrl The URL of a Cosmos SDK light client daemon API (sometimes called REST server or REST API) * @param senderAddress The address that will sign and send transactions using this instance * @param signer An implementation of OfflineSigner which can provide signatures for transactions, potentially requiring user input. - * @param customFees The fees that are paid for transactions + * @param gasPrice The price paid per unit of gas + * @param gasLimits Custom overrides for gas limits related to specific transaction types * @param broadcastMode Defines at which point of the transaction processing the broadcastTx method returns */ constructor( apiUrl: string, senderAddress: string, signer: OfflineSigner, - customFees?: Partial, + gasPrice?: GasPrice, + gasLimits?: Partial, broadcastMode?: BroadcastMode, ); getSequence(address?: string): Promise;