Skip to content

Commit

Permalink
fix: support floating values (#141)
Browse files Browse the repository at this point in the history
* fix: support floating values
  • Loading branch information
troykessler committed Jul 3, 2024
1 parent 97d8b54 commit bb184ca
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 43 deletions.
8 changes: 4 additions & 4 deletions common/coins/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@kyvejs/coins",
"version": "1.0.1",
"version": "1.0.2",
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
"files": [
Expand All @@ -23,13 +23,13 @@
},
"dependencies": {
"@cosmjs/amino": "^0.32.3",
"bn.js": "^5.2.1"
"bignumber.js": "^9.1.2"
},
"devDependencies": {
"jest": "^29.7.0",
"@types/jest": "^29.5.12",
"jest": "^29.7.0",
"rimraf": "^3.0.2",
"typescript": "^4.5.5",
"@types/bn.js": "^5.1.5"
"@types/bignumber.js": "^5.0.0"
}
}
68 changes: 37 additions & 31 deletions common/coins/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,22 @@
import { parseCoins, Coin } from "@cosmjs/amino";
import BN from "bn.js";
import BigNumber from "bignumber.js";

BigNumber.set({
ROUNDING_MODE: 3,
});

type CoinArgs = String[] | Coin[] | Coins[];

export class Coins {
private coinMap: Map<string, BN> = new Map();
private coinMap: Map<string, BigNumber> = new Map();

private get coins(): Coin[] {
return this.sortCoins(
Array.from(this.coinMap.entries()).map(([denom, amount]) => ({
denom,
amount: amount.toString(),
amount: amount.toFixed(0),
}))
).filter((coin) => !new BN(coin.amount).isZero());
).filter((coin) => !new BigNumber(coin.amount).isZero());
}

/**
Expand Down Expand Up @@ -179,7 +183,9 @@ export class Coins {
* @return {boolean}
*/
public isAnyNegative(): boolean {
return Array.from(this.coinMap.values()).some((amount) => amount.isNeg());
return Array.from(this.coinMap.values()).some((amount) =>
amount.isNegative()
);
}

/**
Expand All @@ -192,7 +198,7 @@ export class Coins {
public isAllPositive(): boolean {
return (
!this.empty() &&
Array.from(this.coinMap.values()).every((amount) => amount.gtn(0))
Array.from(this.coinMap.values()).every((amount) => amount.gt(0))
);
}

Expand All @@ -211,7 +217,7 @@ export class Coins {
this.coinArgsToCoins(...coinsB).forEach((coin) => {
this.coinMap.set(
coin.denom,
(this.coinMap.get(coin.denom) || new BN(0)).add(new BN(coin.amount))
(this.coinMap.get(coin.denom) || new BigNumber(0)).plus(coin.amount)
);
});

Expand All @@ -235,7 +241,7 @@ export class Coins {
this.coinArgsToCoins(...coinsB).forEach((coin) => {
this.coinMap.set(
coin.denom,
(this.coinMap.get(coin.denom) || new BN(0)).sub(new BN(coin.amount))
(this.coinMap.get(coin.denom) || new BigNumber(0)).minus(coin.amount)
);
});

Expand All @@ -257,7 +263,10 @@ export class Coins {
*/
public mul(value: number | string): Coins {
this.coinMap.forEach((amount, denom) => {
this.coinMap.set(denom, amount.mul(new BN(value)));
this.coinMap.set(
denom,
new BigNumber(amount.multipliedBy(value).toFixed(0))
);
});

return new Coins(this);
Expand All @@ -280,7 +289,7 @@ export class Coins {
*/
public quo(value: number | string): Coins {
this.coinMap.forEach((amount, denom) => {
this.coinMap.set(denom, new BN(amount.div(new BN(value)).toString()));
this.coinMap.set(denom, amount.idiv(value));
});

return new Coins(this);
Expand All @@ -304,9 +313,9 @@ export class Coins {
return new Coins(
...this.coinArgsToCoins(...coinsB).map((coin) => ({
denom: coin.denom,
amount: BN.min(
this.coinMap.get(coin.denom) || new BN(0),
new BN(coin.amount)
amount: BigNumber.min(
this.coinMap.get(coin.denom) || new BigNumber(0),
coin.amount
).toString(),
}))
);
Expand All @@ -330,7 +339,10 @@ export class Coins {
this.coinArgsToCoins(...coinsB).forEach((coin) => {
this.coinMap.set(
coin.denom,
BN.max(this.coinMap.get(coin.denom) || new BN(0), new BN(coin.amount))
BigNumber.max(
this.coinMap.get(coin.denom) || new BigNumber(0),
coin.amount
)
);
});

Expand All @@ -357,7 +369,7 @@ export class Coins {
return this.coinArgsToCoins(...coinsB).every(
(coin) =>
this.coinMap.has(coin.denom) &&
this.coinMap.get(coin.denom)!.gte(new BN(coin.amount))
this.coinMap.get(coin.denom)!.gte(coin.amount)
);
}

Expand All @@ -381,7 +393,7 @@ export class Coins {
return this.coinArgsToCoins(...coinsB).every(
(coin) =>
this.coinMap.has(coin.denom) &&
this.coinMap.get(coin.denom)!.gt(new BN(coin.amount))
this.coinMap.get(coin.denom)!.gt(coin.amount)
);
}

Expand All @@ -406,8 +418,7 @@ export class Coins {

return Array.from(this.coinMap.keys()).every(
(denom) =>
coins.has(denom) &&
this.coinMap.get(denom)!.lte(new BN(coins.get(denom)!))
coins.has(denom) && this.coinMap.get(denom)!.lte(coins.get(denom)!)
);
}

Expand All @@ -432,8 +443,7 @@ export class Coins {

return Array.from(this.coinMap.keys()).every(
(denom) =>
coins.has(denom) &&
this.coinMap.get(denom)!.lt(new BN(coins.get(denom)!))
coins.has(denom) && this.coinMap.get(denom)!.lt(coins.get(denom)!)
);
}

Expand All @@ -458,8 +468,7 @@ export class Coins {

return Array.from(this.coinMap.keys()).some(
(denom) =>
coins.has(denom) &&
this.coinMap.get(denom)!.gte(new BN(coins.get(denom)!))
coins.has(denom) && this.coinMap.get(denom)!.gte(coins.get(denom)!)
);
}

Expand All @@ -484,8 +493,7 @@ export class Coins {

return Array.from(this.coinMap.keys()).some(
(denom) =>
coins.has(denom) &&
this.coinMap.get(denom)!.gt(new BN(coins.get(denom)!))
coins.has(denom) && this.coinMap.get(denom)!.gt(coins.get(denom)!)
);
}

Expand All @@ -510,8 +518,7 @@ export class Coins {

return Array.from(this.coinMap.keys()).some(
(denom) =>
coins.has(denom) &&
this.coinMap.get(denom)!.lte(new BN(coins.get(denom)!))
coins.has(denom) && this.coinMap.get(denom)!.lte(coins.get(denom)!)
);
}

Expand All @@ -536,8 +543,7 @@ export class Coins {

return Array.from(this.coinMap.keys()).some(
(denom) =>
coins.has(denom) &&
this.coinMap.get(denom)!.lt(new BN(coins.get(denom)!))
coins.has(denom) && this.coinMap.get(denom)!.lt(coins.get(denom)!)
);
}

Expand Down Expand Up @@ -565,11 +571,11 @@ export class Coins {
return coins;
}

private coinArgsToMap(...coinArgs: CoinArgs): Map<string, BN> {
const map: Map<string, BN> = new Map();
private coinArgsToMap(...coinArgs: CoinArgs): Map<string, BigNumber> {
const map: Map<string, BigNumber> = new Map();

this.coinArgsToCoins(...coinArgs).forEach((coin) => {
map.set(coin.denom, new BN(coin.amount));
map.set(coin.denom, new BigNumber(coin.amount));
});

return map;
Expand Down
16 changes: 14 additions & 2 deletions common/coins/test/coins.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ describe("coins.ts", () => {
expect(() => new Coins("10acoin,30B")).toThrow(
new Error("Got an invalid coin string")
);
// float values
expect(() => new Coins("10acoin,0.2bcoin")).toThrow(
new Error("Got an invalid coin string")
);

// --- Coin ---

Expand Down Expand Up @@ -319,9 +323,13 @@ describe("coins.ts", () => {
""
);

expect(new Coins("10acoin,20bcoin,30ccoin").mul("3").toString()).toEqual(
expect(new Coins("10acoin,20bcoin,30ccoin").mul(3).toString()).toEqual(
"30acoin,60bcoin,90ccoin"
);

expect(new Coins("10acoin,20bcoin,17ccoin").mul("0.1").toString()).toEqual(
"1acoin,2bcoin,1ccoin"
);
});

test("quo", () => {
Expand All @@ -337,8 +345,12 @@ describe("coins.ts", () => {

expect(new Coins("4acoin").quo(8).toString()).toEqual("");

expect(new Coins("10acoin,20bcoin,30ccoin").quo(0.2).toString()).toEqual(
"50acoin,100bcoin,150ccoin"
);

expect(() => new Coins("10acoin,20bcoin,30ccoin").quo(0)).toThrow(
new Error("Assertion failed")
new Error("Got an invalid coin string")
);
});

Expand Down
12 changes: 6 additions & 6 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2093,12 +2093,12 @@
dependencies:
"@babel/types" "^7.20.7"

"@types/bn.js@^5.1.5":
version "5.1.5"
resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-5.1.5.tgz#2e0dacdcce2c0f16b905d20ff87aedbc6f7b4bf0"
integrity sha512-V46N0zwKRF5Q00AZ6hWtN0T8gGmDUaUzLWQvHFo5yThtVwK/VCenFY3wXVbOvNfajEpsTfQM4IN9k/d6gUVX3A==
"@types/bignumber.js@^5.0.0":
version "5.0.0"
resolved "https://registry.yarnpkg.com/@types/bignumber.js/-/bignumber.js-5.0.0.tgz#d9f1a378509f3010a3255e9cc822ad0eeb4ab969"
integrity sha512-0DH7aPGCClywOFaxxjE6UwpN2kQYe9LwuDQMv+zYA97j5GkOMo8e66LYT+a8JYU7jfmUFRZLa9KycxHDsKXJCA==
dependencies:
"@types/node" "*"
bignumber.js "*"

"@types/clone@^2.1.1":
version "2.1.4"
Expand Down Expand Up @@ -2934,7 +2934,7 @@ bigint-buffer@^1.1.5:
dependencies:
bindings "^1.3.0"

[email protected], bignumber.js@^9.0.0, bignumber.js@^9.0.1, bignumber.js@^9.0.2, bignumber.js@^9.1.0, bignumber.js@^9.1.2:
bignumber.js@*, bignumber.js@9.1.2, bignumber.js@^9.0.0, bignumber.js@^9.0.1, bignumber.js@^9.0.2, bignumber.js@^9.1.0, bignumber.js@^9.1.2:
version "9.1.2"
resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.1.2.tgz#b7c4242259c008903b13707983b5f4bbd31eda0c"
integrity sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug==
Expand Down

0 comments on commit bb184ca

Please sign in to comment.