diff --git a/packages/launchpad/src/gas.spec.ts b/packages/launchpad/src/gas.spec.ts index bb29902a..a92e4e08 100644 --- a/packages/launchpad/src/gas.spec.ts +++ b/packages/launchpad/src/gas.spec.ts @@ -1,9 +1,23 @@ +import { Decimal } from "@cosmjs/math"; + import { GasPrice } from "./gas"; describe("GasPrice", () => { it("can be constructed", () => { - const gasPrice = new GasPrice(3.14, "utest"); - expect(gasPrice.amount).toEqual(3.14); - expect(gasPrice.denom).toEqual("utest"); + const inputs = ["3.14", "3", "0.14"]; + inputs.forEach((input) => { + const gasPrice = new GasPrice(Decimal.fromUserInput(input, 18), "utest"); + expect(gasPrice.amount.toString()).toEqual(input); + expect(gasPrice.denom).toEqual("utest"); + }); + }); + + it("can be constructed from a config string", () => { + const inputs = ["3.14", "3", "0.14"]; + inputs.forEach((input) => { + const gasPrice = GasPrice.fromString(`${input}utest`); + expect(gasPrice.amount.toString()).toEqual(input); + expect(gasPrice.denom).toEqual("utest"); + }); }); }); diff --git a/packages/launchpad/src/gas.ts b/packages/launchpad/src/gas.ts index 7f0fabe4..cc48d5c6 100644 --- a/packages/launchpad/src/gas.ts +++ b/packages/launchpad/src/gas.ts @@ -1,14 +1,30 @@ +import { Decimal } from "@cosmjs/math"; + import { coins } from "./coins"; import { StdFee } from "./types"; export class GasPrice { - public readonly amount: number; + public readonly amount: Decimal; public readonly denom: string; - constructor(amount: number, denom: string) { + constructor(amount: Decimal, denom: string) { this.amount = amount; this.denom = denom; } + + public static fromString(gasPrice: string): GasPrice { + const matchResult = gasPrice.match(/^(?.+?)(?[a-z]+)$/); + if (!matchResult) { + throw new Error("Invalid gas price string"); + } + const { amount, denom } = matchResult.groups as { readonly amount: string; readonly denom: string }; + if (denom.length < 3 || denom.length > 127) { + throw new Error("Gas price denomination must be between 3 and 127 characters"); + } + const fractionalDigits = 18; + const decimalAmount = Decimal.fromUserInput(amount, fractionalDigits); + return new GasPrice(decimalAmount, denom); + } } export type GasLimits> = { @@ -16,7 +32,8 @@ export type GasLimits> = { }; function calculateFee(gasLimit: number, { denom, amount: gasPriceAmount }: GasPrice): StdFee { - const amount = Math.ceil(gasPriceAmount * gasLimit); + const gasLimitDecimal = Decimal.fromUserInput(gasLimit.toString(), gasPriceAmount.fractionalDigits); + const amount = Math.ceil(gasPriceAmount.multiply(gasLimitDecimal).toFloatApproximation()); return { amount: coins(amount, denom), gas: gasLimit.toString(), diff --git a/packages/launchpad/types/gas.d.ts b/packages/launchpad/types/gas.d.ts index b4070f3e..b20b96e2 100644 --- a/packages/launchpad/types/gas.d.ts +++ b/packages/launchpad/types/gas.d.ts @@ -1,8 +1,10 @@ +import { Decimal } from "@cosmjs/math"; import { StdFee } from "./types"; export declare class GasPrice { - readonly amount: number; + readonly amount: Decimal; readonly denom: string; - constructor(amount: number, denom: string); + constructor(amount: Decimal, denom: string); + static fromString(gasPrice: string): GasPrice; } export declare type GasLimits> = { readonly [key in keyof T]: number;