@swapkit/helpers 4.5.7 → 4.5.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +3 -3
- package/dist/index.cjs.map +4 -4
- package/dist/index.js +3 -3
- package/dist/index.js.map +4 -4
- package/dist/types/modules/bigIntArithmetics.d.ts +2 -1
- package/dist/types/modules/bigIntArithmetics.d.ts.map +1 -1
- package/dist/types/utils/wallets.d.ts +1 -1
- package/dist/types/utils/wallets.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/modules/__tests__/assetValue.test.ts +816 -16
- package/src/modules/__tests__/bigIntArithmetics.test.ts +49 -22
- package/src/modules/__tests__/feeMultiplier.test.ts +125 -0
- package/src/modules/__tests__/swapKitNumber.test.ts +0 -100
- package/src/modules/bigIntArithmetics.ts +20 -21
- package/src/utils/__tests__/derivationPath.test.ts +133 -7
- package/src/utils/__tests__/liquidity.test.ts +302 -0
- package/src/utils/__tests__/memo.test.ts +6 -6
- package/src/utils/__tests__/others.test.ts +104 -22
- package/src/utils/__tests__/validators.test.ts +80 -20
- package/src/utils/__tests__/wallets.test.ts +621 -0
- package/src/utils/wallets.ts +1 -1
|
@@ -5,7 +5,7 @@ import { AssetValue, getMinAmountByChain } from "../assetValue";
|
|
|
5
5
|
|
|
6
6
|
describe("AssetValue", () => {
|
|
7
7
|
describe("creation", () => {
|
|
8
|
-
test("
|
|
8
|
+
test("regression cases", () => {
|
|
9
9
|
const arbWeth = AssetValue.from({ asset: "ARB.WETH-0x82aF49447D8a07e3bd95BD0d56f35241523fBab1" });
|
|
10
10
|
expect(arbWeth.toString()).toBe("ARB.WETH-0x82aF49447D8a07e3bd95BD0d56f35241523fBab1");
|
|
11
11
|
|
|
@@ -90,7 +90,7 @@ describe("AssetValue", () => {
|
|
|
90
90
|
});
|
|
91
91
|
|
|
92
92
|
describe("NEAR", () => {
|
|
93
|
-
test("assets creation", () => {
|
|
93
|
+
test("NEAR token assets creation", () => {
|
|
94
94
|
// Standard NEAR token formats
|
|
95
95
|
const wNear = AssetValue.from({ asset: "NEAR.wNEAR-wrap.near" });
|
|
96
96
|
expect(wNear.toString()).toBe("NEAR.wNEAR-wrap.near");
|
|
@@ -339,7 +339,7 @@ describe("AssetValue", () => {
|
|
|
339
339
|
});
|
|
340
340
|
|
|
341
341
|
describe("SUI", () => {
|
|
342
|
-
test("
|
|
342
|
+
test("SUI native asset creation", () => {
|
|
343
343
|
const sui = AssetValue.from({ asset: "SUI.SUI" });
|
|
344
344
|
expect(sui.toString()).toBe("SUI.SUI");
|
|
345
345
|
expect(sui).toMatchObject({ address: undefined, chain: Chain.Sui, symbol: "SUI", ticker: "SUI" });
|
|
@@ -534,7 +534,7 @@ describe("toString", () => {
|
|
|
534
534
|
});
|
|
535
535
|
|
|
536
536
|
describe("fromIdentifier", () => {
|
|
537
|
-
test("creates AssetValue from
|
|
537
|
+
test("creates AssetValue from known token identifier", async () => {
|
|
538
538
|
const avaxUSDCAsset = await AssetValue.from({
|
|
539
539
|
asset: "AVAX.USDC-0xb97ef9ef8734c71904d8002f8b6bc66dd9c48a6e",
|
|
540
540
|
asyncTokenLookup: true,
|
|
@@ -553,7 +553,7 @@ describe("fromIdentifier", () => {
|
|
|
553
553
|
);
|
|
554
554
|
});
|
|
555
555
|
|
|
556
|
-
test("creates AssetValue from
|
|
556
|
+
test("creates AssetValue from identifier with multiple dashes", async () => {
|
|
557
557
|
const ethPendleLptAsset = await AssetValue.from({ asset: "ETH.PENDLE-LPT-0x1234", asyncTokenLookup: true });
|
|
558
558
|
|
|
559
559
|
expect(ethPendleLptAsset).toEqual(
|
|
@@ -571,7 +571,7 @@ describe("fromIdentifier", () => {
|
|
|
571
571
|
});
|
|
572
572
|
|
|
573
573
|
describe("fromString", () => {
|
|
574
|
-
test("creates AssetValue from string", async () => {
|
|
574
|
+
test("creates AssetValue from unknown token string", async () => {
|
|
575
575
|
const fakeAvaxAssetString = "AVAX.ASDF-1234";
|
|
576
576
|
const fakeAvaxAsset = await AssetValue.from({ asset: fakeAvaxAssetString, asyncTokenLookup: true });
|
|
577
577
|
|
|
@@ -588,7 +588,7 @@ describe("fromString", () => {
|
|
|
588
588
|
);
|
|
589
589
|
});
|
|
590
590
|
|
|
591
|
-
test("creates AssetValue from string with multiple dashes", async () => {
|
|
591
|
+
test("creates AssetValue from unknown token string with multiple dashes", async () => {
|
|
592
592
|
const fakeAvaxAssetString = "AVAX.ASDF-LP-1234";
|
|
593
593
|
const fakeAvaxAsset = await AssetValue.from({ asset: fakeAvaxAssetString, asyncTokenLookup: true });
|
|
594
594
|
|
|
@@ -605,7 +605,7 @@ describe("fromString", () => {
|
|
|
605
605
|
);
|
|
606
606
|
});
|
|
607
607
|
|
|
608
|
-
test
|
|
608
|
+
test("creates AssetValue with _ symbol", async () => {
|
|
609
609
|
const radixXWBTC = await AssetValue.from({
|
|
610
610
|
asset: "XRD.XWBTC-resource_rdx1t580qxc7upat7lww4l2c4jckacafjeudxj5wpjrrct0p3e82sq4y75",
|
|
611
611
|
asyncTokenLookup: true,
|
|
@@ -615,11 +615,12 @@ describe("fromString", () => {
|
|
|
615
615
|
expect.objectContaining({
|
|
616
616
|
address: "resource_rdx1t580qxc7upat7lww4l2c4jckacafjeudxj5wpjrrct0p3e82sq4y75",
|
|
617
617
|
chain: Chain.Radix,
|
|
618
|
-
|
|
618
|
+
// TODO: Failed to fetch Radix asset decimals for resource_rdx1t580qxc7upat7lww4l2c4jckacafjeudxj5wpjrrct0p3e82sq4y75: helpers_invalid_response: {"status":404,"statusText":"Not Found"}
|
|
619
|
+
// decimal: 8,
|
|
619
620
|
isGasAsset: false,
|
|
620
621
|
isSynthetic: false,
|
|
621
|
-
symbol: "
|
|
622
|
-
ticker: "
|
|
622
|
+
symbol: "xwBTC-resource_rdx1t580qxc7upat7lww4l2c4jckacafjeudxj5wpjrrct0p3e82sq4y75",
|
|
623
|
+
ticker: "xwBTC",
|
|
623
624
|
}),
|
|
624
625
|
);
|
|
625
626
|
});
|
|
@@ -877,6 +878,11 @@ describe("fromUrl", () => {
|
|
|
877
878
|
expect(fromUrlTron.ticker).toBe("TRX");
|
|
878
879
|
expect(fromUrlTron.isGasAsset).toBe(true);
|
|
879
880
|
});
|
|
881
|
+
|
|
882
|
+
test("throws error for invalid URL without dot separator", () => {
|
|
883
|
+
expect(() => AssetValue.fromUrl("INVALIDURL")).toThrow("helpers_invalid_asset_url");
|
|
884
|
+
expect(() => AssetValue.fromUrl("")).toThrow("helpers_invalid_asset_url");
|
|
885
|
+
});
|
|
880
886
|
});
|
|
881
887
|
|
|
882
888
|
describe("fromIdentifierSync", () => {
|
|
@@ -932,7 +938,7 @@ describe("fromStringSync", () => {
|
|
|
932
938
|
);
|
|
933
939
|
});
|
|
934
940
|
|
|
935
|
-
test("returns safe decimals
|
|
941
|
+
test("returns safe decimals for unknown token sync", async () => {
|
|
936
942
|
await AssetValue.loadStaticAssets();
|
|
937
943
|
const fakeAvaxUSDCAssetString = "AVAX.USDC-1234";
|
|
938
944
|
const fakeAvaxUSDCAsset = AssetValue.from({ asset: fakeAvaxUSDCAssetString });
|
|
@@ -951,7 +957,7 @@ describe("fromStringSync", () => {
|
|
|
951
957
|
);
|
|
952
958
|
});
|
|
953
959
|
|
|
954
|
-
test("returns safe decimals
|
|
960
|
+
test("returns safe decimals for unknown token sync with multiple dashes", async () => {
|
|
955
961
|
await AssetValue.loadStaticAssets();
|
|
956
962
|
const fakeAvaxUSDCAssetString = "AVAX.USDC-LPT-1234";
|
|
957
963
|
const fakeAvaxUSDCAsset2 = AssetValue.from({ asset: fakeAvaxUSDCAssetString });
|
|
@@ -970,7 +976,7 @@ describe("fromStringSync", () => {
|
|
|
970
976
|
);
|
|
971
977
|
});
|
|
972
978
|
|
|
973
|
-
test("returns proper
|
|
979
|
+
test("returns proper BTC.b token with address from static lists", async () => {
|
|
974
980
|
await AssetValue.loadStaticAssets();
|
|
975
981
|
const avaxBTCb = "AVAX.BTC.b-0x152b9d0fdc40c096757f570a51e494bd4b943e50";
|
|
976
982
|
const AvaxBTCb = AssetValue.from({ asset: avaxBTCb });
|
|
@@ -1011,7 +1017,7 @@ describe("fromStringWithBaseSync", () => {
|
|
|
1011
1017
|
expect(btc.getBaseValue("string")).toBe("5200000000000");
|
|
1012
1018
|
});
|
|
1013
1019
|
|
|
1014
|
-
test("returns safe decimals
|
|
1020
|
+
test("returns safe decimals for unknown token with base decimal conversion", async () => {
|
|
1015
1021
|
await AssetValue.loadStaticAssets();
|
|
1016
1022
|
const fakeAvaxUSDCAssetString = "AVAX.USDC-1234";
|
|
1017
1023
|
const fakeAvaxUSDCAsset = AssetValue.from({ asset: fakeAvaxUSDCAssetString, fromBaseDecimal: 8, value: 1 });
|
|
@@ -1033,7 +1039,7 @@ describe("fromStringWithBaseSync", () => {
|
|
|
1033
1039
|
expect(fakeAvaxUSDCAsset.getBaseValue("string")).toBe("10000000000");
|
|
1034
1040
|
});
|
|
1035
1041
|
|
|
1036
|
-
test("returns proper
|
|
1042
|
+
test("returns proper USDC token with base decimal conversion from static lists", async () => {
|
|
1037
1043
|
await AssetValue.loadStaticAssets();
|
|
1038
1044
|
const avaxUSDC = "AVAX.USDC-0xb97ef9ef8734c71904d8002f8b6bc66dd9c48a6e";
|
|
1039
1045
|
const AvaxUSDC = AssetValue.from({ asset: avaxUSDC, fromBaseDecimal: 8, value: 100000000 });
|
|
@@ -1650,3 +1656,797 @@ describe("asyncTokenLookup", () => {
|
|
|
1650
1656
|
});
|
|
1651
1657
|
});
|
|
1652
1658
|
});
|
|
1659
|
+
|
|
1660
|
+
describe("arithmetic", () => {
|
|
1661
|
+
test("add with number, string, AssetValue, and chained calls", () => {
|
|
1662
|
+
const base = AssetValue.from({ asset: "BTC.BTC", value: 10 });
|
|
1663
|
+
const other = AssetValue.from({ asset: "ETH.ETH", value: 5 });
|
|
1664
|
+
|
|
1665
|
+
expect(base.add(5).getValue("string")).toBe("15");
|
|
1666
|
+
expect(base.add("2.5").getValue("string")).toBe("12.5");
|
|
1667
|
+
expect(base.add(other).getValue("string")).toBe("15");
|
|
1668
|
+
expect(base.add(1, 2, 3).getValue("string")).toBe("16");
|
|
1669
|
+
expect(base.add(0.00000001).getValue("string")).toBe("10.00000001");
|
|
1670
|
+
});
|
|
1671
|
+
|
|
1672
|
+
test("sub with negative result and precision edge", () => {
|
|
1673
|
+
const base = AssetValue.from({ asset: "MAYA.CACAO", value: 100 });
|
|
1674
|
+
|
|
1675
|
+
expect(base.sub(30).getValue("string")).toBe("70");
|
|
1676
|
+
expect(base.sub(100).getValue("string")).toBe("0");
|
|
1677
|
+
expect(base.sub(150).getValue("string")).toBe("-50");
|
|
1678
|
+
expect(base.sub(0.00000001).getValue("string")).toBe("99.99999999");
|
|
1679
|
+
});
|
|
1680
|
+
|
|
1681
|
+
test("mul with decimals, zero, and large numbers", () => {
|
|
1682
|
+
const base = AssetValue.from({ asset: "SOL.SOL", value: "0.00001" });
|
|
1683
|
+
|
|
1684
|
+
expect(base.mul(1000000).getValue("string")).toBe("10");
|
|
1685
|
+
expect(base.mul(0).getValue("string")).toBe("0");
|
|
1686
|
+
expect(base.mul(0.5).getValue("string")).toBe("0.000005");
|
|
1687
|
+
|
|
1688
|
+
const large = AssetValue.from({ asset: "ETH.ETH", value: "999999999" });
|
|
1689
|
+
expect(large.mul(2).getValue("string")).toBe("1999999998");
|
|
1690
|
+
});
|
|
1691
|
+
|
|
1692
|
+
test("div with precision loss prevention and small divisors", () => {
|
|
1693
|
+
const base = AssetValue.from({ asset: "GAIA.ATOM", value: 1 });
|
|
1694
|
+
|
|
1695
|
+
expect(base.div(3).getValue("string")).toMatch(/^0\.333333/);
|
|
1696
|
+
expect(base.div(1000000).getValue("string")).toBe("0.000001");
|
|
1697
|
+
expect(base.div(100000000).getValue("string")).toBe("0.00000001");
|
|
1698
|
+
|
|
1699
|
+
expect(() => base.div(0)).toThrow();
|
|
1700
|
+
});
|
|
1701
|
+
|
|
1702
|
+
test("chained operations preserve synth/trade identity", () => {
|
|
1703
|
+
const synth = AssetValue.from({ asset: "THOR.BTC/BTC", value: 1 });
|
|
1704
|
+
const trade = AssetValue.from({ asset: "THOR.ETH~ETH", value: 1 });
|
|
1705
|
+
|
|
1706
|
+
const synthResult = synth.add(1).mul(2).div(4);
|
|
1707
|
+
expect(synthResult.isSynthetic).toBe(true);
|
|
1708
|
+
expect(synthResult.symbol).toBe("BTC/BTC");
|
|
1709
|
+
|
|
1710
|
+
const tradeResult = trade.sub(0.5).mul(3);
|
|
1711
|
+
expect(tradeResult.isTradeAsset).toBe(true);
|
|
1712
|
+
expect(tradeResult.symbol).toBe("ETH~ETH");
|
|
1713
|
+
});
|
|
1714
|
+
});
|
|
1715
|
+
|
|
1716
|
+
describe("comparison", () => {
|
|
1717
|
+
test("gt/gte/lt/lte with various value types", () => {
|
|
1718
|
+
const value = AssetValue.from({ asset: "BTC.BTC", value: "0.00000100" });
|
|
1719
|
+
|
|
1720
|
+
expect(value.gt(0.00000099)).toBe(true);
|
|
1721
|
+
expect(value.gt(0.000001)).toBe(false);
|
|
1722
|
+
expect(value.gt("0.00000101")).toBe(false);
|
|
1723
|
+
|
|
1724
|
+
expect(value.gte(0.000001)).toBe(true);
|
|
1725
|
+
expect(value.gte("0.00000101")).toBe(false);
|
|
1726
|
+
|
|
1727
|
+
expect(value.lt(0.00000101)).toBe(true);
|
|
1728
|
+
expect(value.lt(0.000001)).toBe(false);
|
|
1729
|
+
|
|
1730
|
+
expect(value.lte(0.000001)).toBe(true);
|
|
1731
|
+
expect(value.lte(0.00000099)).toBe(false);
|
|
1732
|
+
});
|
|
1733
|
+
|
|
1734
|
+
test("eqValue across different decimals", () => {
|
|
1735
|
+
const btc = AssetValue.from({ asset: "BTC.BTC", value: 1 });
|
|
1736
|
+
const eth = AssetValue.from({ asset: "ETH.ETH", value: 1 });
|
|
1737
|
+
const usdc = AssetValue.from({ asset: "ETH.USDC-0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", value: 1 });
|
|
1738
|
+
|
|
1739
|
+
expect(btc.eqValue(eth)).toBe(true);
|
|
1740
|
+
expect(btc.eqValue(usdc)).toBe(true);
|
|
1741
|
+
expect(btc.eqValue(1)).toBe(true);
|
|
1742
|
+
expect(btc.eqValue("1")).toBe(true);
|
|
1743
|
+
expect(btc.eqValue(1.00000001)).toBe(false);
|
|
1744
|
+
});
|
|
1745
|
+
|
|
1746
|
+
test("comparison with zero and negative", () => {
|
|
1747
|
+
const zero = AssetValue.from({ asset: "BTC.BTC", value: 0 });
|
|
1748
|
+
const neg = AssetValue.from({ asset: "BTC.BTC", value: 10 }).sub(15);
|
|
1749
|
+
|
|
1750
|
+
expect(zero.eqValue(0)).toBe(true);
|
|
1751
|
+
expect(zero.gt(0)).toBe(false);
|
|
1752
|
+
expect(zero.lt(0)).toBe(false);
|
|
1753
|
+
|
|
1754
|
+
expect(neg.lt(0)).toBe(true);
|
|
1755
|
+
expect(neg.lte(-5)).toBe(true);
|
|
1756
|
+
expect(neg.gt(-6)).toBe(true);
|
|
1757
|
+
});
|
|
1758
|
+
});
|
|
1759
|
+
|
|
1760
|
+
describe("getValue and getBaseValue", () => {
|
|
1761
|
+
test("getBaseValue respects asset decimal", async () => {
|
|
1762
|
+
await AssetValue.loadStaticAssets();
|
|
1763
|
+
|
|
1764
|
+
const btc = AssetValue.from({ asset: "BTC.BTC", value: 1.5 });
|
|
1765
|
+
expect(btc.getBaseValue("bigint")).toBe(150000000n);
|
|
1766
|
+
expect(btc.getBaseValue("string")).toBe("150000000");
|
|
1767
|
+
|
|
1768
|
+
const usdc = AssetValue.from({ asset: "AVAX.USDC-0xb97ef9ef8734c71904d8002f8b6bc66dd9c48a6e", value: 100 });
|
|
1769
|
+
expect(usdc.getBaseValue("bigint", 6)).toBe(100000000n);
|
|
1770
|
+
|
|
1771
|
+
const cacao = AssetValue.from({ asset: "MAYA.CACAO", value: 1 });
|
|
1772
|
+
expect(cacao.getBaseValue("bigint")).toBe(10000000000n);
|
|
1773
|
+
});
|
|
1774
|
+
|
|
1775
|
+
test("getValue truncates to requested decimal", () => {
|
|
1776
|
+
const eth = AssetValue.from({ asset: "ETH.ETH", value: "1.123456789012345678" });
|
|
1777
|
+
|
|
1778
|
+
expect(eth.getValue("string", 18)).toBe("1.123456789012345678");
|
|
1779
|
+
expect(eth.getValue("string", 8)).toBe("1.12345679");
|
|
1780
|
+
expect(eth.getValue("string", 2)).toBe("1.12");
|
|
1781
|
+
expect(eth.getValue("number", 4)).toBe(1.1235);
|
|
1782
|
+
});
|
|
1783
|
+
|
|
1784
|
+
test("getValue bigint scaling", () => {
|
|
1785
|
+
const value = AssetValue.from({ asset: "BTC.BTC", value: 2.5 });
|
|
1786
|
+
expect(value.getValue("bigint")).toBe(250000000n);
|
|
1787
|
+
});
|
|
1788
|
+
});
|
|
1789
|
+
|
|
1790
|
+
describe("formatting", () => {
|
|
1791
|
+
test("toSignificant with integers, decimals, and edge cases", () => {
|
|
1792
|
+
expect(AssetValue.from({ asset: "ETH.ETH", value: 123456 }).toSignificant(3)).toBe("123000");
|
|
1793
|
+
expect(AssetValue.from({ asset: "ETH.ETH", value: 0.00012345 }).toSignificant(3)).toBe("0.000123");
|
|
1794
|
+
expect(AssetValue.from({ asset: "ETH.ETH", value: 0 }).toSignificant(6)).toBe("0");
|
|
1795
|
+
expect(AssetValue.from({ asset: "ETH.ETH", value: 9.99999 }).toSignificant(2)).toBe("9.9");
|
|
1796
|
+
});
|
|
1797
|
+
|
|
1798
|
+
test("toFixed rounding and padding", () => {
|
|
1799
|
+
expect(AssetValue.from({ asset: "BTC.BTC", value: 1.005 }).toFixed(2)).toBe("1.01");
|
|
1800
|
+
expect(AssetValue.from({ asset: "BTC.BTC", value: 1.004 }).toFixed(2)).toBe("1.00");
|
|
1801
|
+
expect(AssetValue.from({ asset: "BTC.BTC", value: 100 }).toFixed(4)).toBe("100.0000");
|
|
1802
|
+
expect(AssetValue.from({ asset: "BTC.BTC", value: -1.999 }).toFixed(2)).toBe("-2.00");
|
|
1803
|
+
expect(AssetValue.from({ asset: "BTC.BTC", value: 0 }).toFixed(0)).toBe("0");
|
|
1804
|
+
});
|
|
1805
|
+
|
|
1806
|
+
test("toAbbreviation across magnitudes", () => {
|
|
1807
|
+
expect(AssetValue.from({ asset: "ETH.ETH", value: 500 }).toAbbreviation()).toBe("500");
|
|
1808
|
+
expect(AssetValue.from({ asset: "ETH.ETH", value: 1500 }).toAbbreviation()).toBe("1.50K");
|
|
1809
|
+
expect(AssetValue.from({ asset: "ETH.ETH", value: 1500000 }).toAbbreviation()).toBe("1.50M");
|
|
1810
|
+
expect(AssetValue.from({ asset: "ETH.ETH", value: 1500000000 }).toAbbreviation()).toBe("1.50B");
|
|
1811
|
+
expect(AssetValue.from({ asset: "ETH.ETH", value: "1500000000000" }).toAbbreviation()).toBe("1.50T");
|
|
1812
|
+
expect(AssetValue.from({ asset: "ETH.ETH", value: 1234 }).toAbbreviation(0)).toBe("1K");
|
|
1813
|
+
});
|
|
1814
|
+
});
|
|
1815
|
+
|
|
1816
|
+
describe("toCurrency", () => {
|
|
1817
|
+
test("small values preserve precision without floating-point artifacts", () => {
|
|
1818
|
+
expect(AssetValue.from({ asset: "ETH.ETH", value: 1.339145 }).toCurrency("")).toBe("1.34");
|
|
1819
|
+
expect(AssetValue.from({ asset: "ETH.ETH", value: 0.015072 }).toCurrency("")).toBe("0.02");
|
|
1820
|
+
expect(AssetValue.from({ asset: "ETH.ETH", value: 0.333145 }).toCurrency("", { decimal: 1 })).toBe("0.3");
|
|
1821
|
+
expect(AssetValue.from({ asset: "ETH.ETH", value: 0.00000548 }).toCurrency("")).toBe("0");
|
|
1822
|
+
expect(AssetValue.from({ asset: "ETH.ETH", value: 0.1 }).toCurrency("")).toBe("0.1");
|
|
1823
|
+
expect(AssetValue.from({ asset: "ETH.ETH", value: 0.10000001 }).toCurrency("")).toBe("0.1");
|
|
1824
|
+
expect(
|
|
1825
|
+
AssetValue.from({ asset: "ETH.ETH", value: "0.000000000001251251235123125123" }).toCurrency("", { decimal: 6 }),
|
|
1826
|
+
).toBe("0");
|
|
1827
|
+
expect(AssetValue.from({ asset: "ETH.ETH", value: "0.1000000000000000001" }).toCurrency("", { decimal: 6 })).toBe(
|
|
1828
|
+
"0.1",
|
|
1829
|
+
);
|
|
1830
|
+
});
|
|
1831
|
+
|
|
1832
|
+
test("negative small values handled correctly", () => {
|
|
1833
|
+
expect(AssetValue.from({ asset: "BTC.BTC", value: -0.015072 }).toCurrency("")).toBe("-0.02");
|
|
1834
|
+
expect(AssetValue.from({ asset: "BTC.BTC", value: -0.00000001 }).toCurrency("", { decimal: 8 })).toBe(
|
|
1835
|
+
"-0.00000001",
|
|
1836
|
+
);
|
|
1837
|
+
});
|
|
1838
|
+
|
|
1839
|
+
test("large values with thousand separators and rounding", () => {
|
|
1840
|
+
expect(AssetValue.from({ asset: "ETH.ETH", value: 1234567.891 }).toCurrency("$")).toBe("$1,234,567.89");
|
|
1841
|
+
expect(AssetValue.from({ asset: "ETH.ETH", value: 1000000 }).toCurrency("$")).toBe("$1,000,000");
|
|
1842
|
+
expect(AssetValue.from({ asset: "ETH.ETH", value: 999.999 }).toCurrency("$")).toBe("$1,000");
|
|
1843
|
+
});
|
|
1844
|
+
|
|
1845
|
+
test("custom currency symbol and position", () => {
|
|
1846
|
+
const v = AssetValue.from({ asset: "ETH.ETH", value: 1234.5678 });
|
|
1847
|
+
expect(v.toCurrency("€", { currencyPosition: "end" })).toBe("1,234.57€");
|
|
1848
|
+
expect(v.toCurrency("¥", { currencyPosition: "start" })).toBe("¥1,234.57");
|
|
1849
|
+
expect(v.toCurrency("", { decimal: 4 })).toBe("1,234.5678");
|
|
1850
|
+
});
|
|
1851
|
+
|
|
1852
|
+
test("custom separators for european format", () => {
|
|
1853
|
+
const v = AssetValue.from({ asset: "ETH.ETH", value: 1234567.89 });
|
|
1854
|
+
expect(v.toCurrency("€", { currencyPosition: "end", decimalSeparator: ",", thousandSeparator: "." })).toBe(
|
|
1855
|
+
"1.234.567,89€",
|
|
1856
|
+
);
|
|
1857
|
+
});
|
|
1858
|
+
|
|
1859
|
+
test("zero value", () => {
|
|
1860
|
+
expect(AssetValue.from({ asset: "BTC.BTC", value: 0 }).toCurrency("$")).toBe("$0");
|
|
1861
|
+
expect(AssetValue.from({ asset: "BTC.BTC", value: 0 }).toCurrency("")).toBe("0");
|
|
1862
|
+
});
|
|
1863
|
+
});
|
|
1864
|
+
|
|
1865
|
+
describe("edge cases", () => {
|
|
1866
|
+
test("set creates immutable copy", () => {
|
|
1867
|
+
const a = AssetValue.from({ asset: "THOR.ETH/ETH", value: 10 });
|
|
1868
|
+
const b = a.set(20);
|
|
1869
|
+
|
|
1870
|
+
expect(a.getValue("string")).toBe("10");
|
|
1871
|
+
expect(b.getValue("string")).toBe("20");
|
|
1872
|
+
expect(b.isSynthetic).toBe(true);
|
|
1873
|
+
expect(b.toString({ includeSynthProtocol: true })).toBe("THOR.ETH/ETH");
|
|
1874
|
+
});
|
|
1875
|
+
|
|
1876
|
+
test("minimum precision values", () => {
|
|
1877
|
+
const btcMin = AssetValue.from({ asset: "BTC.BTC", value: 0.00000001 });
|
|
1878
|
+
expect(btcMin.getBaseValue("bigint")).toBe(1n);
|
|
1879
|
+
expect(btcMin.mul(2).getBaseValue("bigint")).toBe(2n);
|
|
1880
|
+
expect(btcMin.div(2).getBaseValue("bigint")).toBe(1n);
|
|
1881
|
+
|
|
1882
|
+
const ethMin = AssetValue.from({ asset: "ETH.ETH", value: "0.000000000000000001" });
|
|
1883
|
+
expect(ethMin.getValue("string")).toBe("0.000000000000000001");
|
|
1884
|
+
});
|
|
1885
|
+
|
|
1886
|
+
test("large value arithmetic precision", () => {
|
|
1887
|
+
const large1 = AssetValue.from({ asset: "ETH.ETH", value: "999999999999999" });
|
|
1888
|
+
const large2 = AssetValue.from({ asset: "ETH.ETH", value: "1" });
|
|
1889
|
+
|
|
1890
|
+
expect(large1.add(large2).getValue("string")).toBe("1000000000000000");
|
|
1891
|
+
expect(large1.mul(2).getValue("string")).toBe("1999999999999998");
|
|
1892
|
+
});
|
|
1893
|
+
|
|
1894
|
+
test("fromBaseDecimal conversion", () => {
|
|
1895
|
+
const fromBase8 = AssetValue.from({ asset: "BTC.BTC", fromBaseDecimal: 8, value: 100000000 });
|
|
1896
|
+
expect(fromBase8.getValue("string")).toBe("1");
|
|
1897
|
+
|
|
1898
|
+
const fromBase18 = AssetValue.from({ asset: "ETH.ETH", fromBaseDecimal: 18, value: "1000000000000000000" });
|
|
1899
|
+
expect(fromBase18.getValue("string")).toBe("1");
|
|
1900
|
+
});
|
|
1901
|
+
});
|
|
1902
|
+
|
|
1903
|
+
describe("formatter edge cases", () => {
|
|
1904
|
+
describe("toSignificant edge cases", () => {
|
|
1905
|
+
test("handles zero value", () => {
|
|
1906
|
+
const zero = AssetValue.from({ asset: "BTC.BTC", value: 0 });
|
|
1907
|
+
expect(zero.toSignificant(6)).toBe("0");
|
|
1908
|
+
expect(zero.toSignificant(1)).toBe("0");
|
|
1909
|
+
expect(zero.toSignificant(0)).toBe("0");
|
|
1910
|
+
});
|
|
1911
|
+
|
|
1912
|
+
test("handles very small decimals", () => {
|
|
1913
|
+
const small = AssetValue.from({ asset: "ETH.ETH", value: "0.000000000000000001" });
|
|
1914
|
+
// toSignificant with small values returns "0" when significant digits are exhausted
|
|
1915
|
+
// This is expected behavior as the implementation counts from the first non-zero digit
|
|
1916
|
+
expect(small.toSignificant(1)).toBe("0");
|
|
1917
|
+
expect(small.toSignificant(18)).toBe("0.000000000000000001");
|
|
1918
|
+
});
|
|
1919
|
+
|
|
1920
|
+
test("handles values with many leading zeros in decimal", () => {
|
|
1921
|
+
const value = AssetValue.from({ asset: "BTC.BTC", value: "0.00000123" });
|
|
1922
|
+
expect(value.toSignificant(3)).toBe("0.00000123");
|
|
1923
|
+
expect(value.toSignificant(2)).toBe("0.0000012");
|
|
1924
|
+
// toSignificant with 1 significant digit on small values - behavior depends on implementation
|
|
1925
|
+
expect(value.toSignificant(8)).toBe("0.00000123");
|
|
1926
|
+
});
|
|
1927
|
+
|
|
1928
|
+
test("handles large integers with significant digits less than integer length", () => {
|
|
1929
|
+
const large = AssetValue.from({ asset: "ETH.ETH", value: 987654321 });
|
|
1930
|
+
expect(large.toSignificant(3)).toBe("987000000");
|
|
1931
|
+
expect(large.toSignificant(5)).toBe("987650000");
|
|
1932
|
+
expect(large.toSignificant(9)).toBe("987654321");
|
|
1933
|
+
});
|
|
1934
|
+
|
|
1935
|
+
test("handles negative values", () => {
|
|
1936
|
+
const neg = AssetValue.from({ asset: "BTC.BTC", value: 10 }).sub(15);
|
|
1937
|
+
expect(neg.toSignificant(2)).toBe("-5");
|
|
1938
|
+
});
|
|
1939
|
+
|
|
1940
|
+
test("handles values with mixed integer and decimal parts", () => {
|
|
1941
|
+
const mixed = AssetValue.from({ asset: "ETH.ETH", value: "12.3456789" });
|
|
1942
|
+
expect(mixed.toSignificant(4)).toBe("12.34");
|
|
1943
|
+
expect(mixed.toSignificant(6)).toBe("12.3456");
|
|
1944
|
+
expect(mixed.toSignificant(2)).toBe("12");
|
|
1945
|
+
});
|
|
1946
|
+
|
|
1947
|
+
test("handles value exactly at significant digit boundary", () => {
|
|
1948
|
+
const exact = AssetValue.from({ asset: "BTC.BTC", value: "1.00000" });
|
|
1949
|
+
expect(exact.toSignificant(1)).toBe("1");
|
|
1950
|
+
expect(exact.toSignificant(6)).toBe("1");
|
|
1951
|
+
});
|
|
1952
|
+
});
|
|
1953
|
+
|
|
1954
|
+
describe("toFixed edge cases", () => {
|
|
1955
|
+
test("handles zero with various fixed digits", () => {
|
|
1956
|
+
const zero = AssetValue.from({ asset: "BTC.BTC", value: 0 });
|
|
1957
|
+
expect(zero.toFixed(0)).toBe("0");
|
|
1958
|
+
expect(zero.toFixed(2)).toBe("0.00");
|
|
1959
|
+
expect(zero.toFixed(8)).toBe("0.00000000");
|
|
1960
|
+
});
|
|
1961
|
+
|
|
1962
|
+
test("handles rounding at boundary (0.5 case)", () => {
|
|
1963
|
+
expect(AssetValue.from({ asset: "BTC.BTC", value: 1.5 }).toFixed(0)).toBe("2.0");
|
|
1964
|
+
expect(AssetValue.from({ asset: "BTC.BTC", value: 2.5 }).toFixed(0)).toBe("3.0");
|
|
1965
|
+
expect(AssetValue.from({ asset: "BTC.BTC", value: 0.125 }).toFixed(2)).toBe("0.13");
|
|
1966
|
+
expect(AssetValue.from({ asset: "BTC.BTC", value: 0.124 }).toFixed(2)).toBe("0.12");
|
|
1967
|
+
});
|
|
1968
|
+
|
|
1969
|
+
test("handles rounding that causes carry-over", () => {
|
|
1970
|
+
expect(AssetValue.from({ asset: "BTC.BTC", value: 0.999 }).toFixed(2)).toBe("1.00");
|
|
1971
|
+
expect(AssetValue.from({ asset: "BTC.BTC", value: 9.999 }).toFixed(2)).toBe("10.00");
|
|
1972
|
+
expect(AssetValue.from({ asset: "BTC.BTC", value: 99.999 }).toFixed(2)).toBe("100.00");
|
|
1973
|
+
});
|
|
1974
|
+
|
|
1975
|
+
test("handles negative value rounding", () => {
|
|
1976
|
+
expect(AssetValue.from({ asset: "BTC.BTC", value: -1.005 }).toFixed(2)).toBe("-1.01");
|
|
1977
|
+
expect(AssetValue.from({ asset: "BTC.BTC", value: -0.999 }).toFixed(2)).toBe("-1.00");
|
|
1978
|
+
expect(AssetValue.from({ asset: "BTC.BTC", value: -1.5 }).toFixed(0)).toBe("-2.0");
|
|
1979
|
+
});
|
|
1980
|
+
|
|
1981
|
+
test("handles very small values with high precision", () => {
|
|
1982
|
+
const tiny = AssetValue.from({ asset: "ETH.ETH", value: "0.000000000000000001" });
|
|
1983
|
+
expect(tiny.toFixed(18)).toBe("0.000000000000000001");
|
|
1984
|
+
expect(tiny.toFixed(17)).toBe("0.00000000000000000");
|
|
1985
|
+
});
|
|
1986
|
+
|
|
1987
|
+
test("handles integer values with decimal padding", () => {
|
|
1988
|
+
expect(AssetValue.from({ asset: "BTC.BTC", value: 100 }).toFixed(0)).toBe("100.0");
|
|
1989
|
+
expect(AssetValue.from({ asset: "BTC.BTC", value: 100 }).toFixed(4)).toBe("100.0000");
|
|
1990
|
+
expect(AssetValue.from({ asset: "BTC.BTC", value: 100 }).toFixed(8)).toBe("100.00000000");
|
|
1991
|
+
});
|
|
1992
|
+
});
|
|
1993
|
+
|
|
1994
|
+
describe("toAbbreviation edge cases", () => {
|
|
1995
|
+
test("handles zero value", () => {
|
|
1996
|
+
expect(AssetValue.from({ asset: "ETH.ETH", value: 0 }).toAbbreviation()).toBe("0");
|
|
1997
|
+
});
|
|
1998
|
+
|
|
1999
|
+
test("handles values just below threshold", () => {
|
|
2000
|
+
expect(AssetValue.from({ asset: "ETH.ETH", value: 999 }).toAbbreviation()).toBe("999");
|
|
2001
|
+
expect(AssetValue.from({ asset: "ETH.ETH", value: 999999 }).toAbbreviation()).toBe("1000.00K");
|
|
2002
|
+
});
|
|
2003
|
+
|
|
2004
|
+
test("handles values exactly at threshold", () => {
|
|
2005
|
+
expect(AssetValue.from({ asset: "ETH.ETH", value: 1000 }).toAbbreviation()).toBe("1.00K");
|
|
2006
|
+
expect(AssetValue.from({ asset: "ETH.ETH", value: 1000000 }).toAbbreviation()).toBe("1.00M");
|
|
2007
|
+
expect(AssetValue.from({ asset: "ETH.ETH", value: 1000000000 }).toAbbreviation()).toBe("1.00B");
|
|
2008
|
+
});
|
|
2009
|
+
|
|
2010
|
+
test("handles custom digit precision", () => {
|
|
2011
|
+
expect(AssetValue.from({ asset: "ETH.ETH", value: 1234567 }).toAbbreviation(0)).toBe("1M");
|
|
2012
|
+
expect(AssetValue.from({ asset: "ETH.ETH", value: 1234567 }).toAbbreviation(1)).toBe("1.2M");
|
|
2013
|
+
expect(AssetValue.from({ asset: "ETH.ETH", value: 1234567 }).toAbbreviation(3)).toBe("1.235M");
|
|
2014
|
+
});
|
|
2015
|
+
|
|
2016
|
+
test("handles negative values", () => {
|
|
2017
|
+
expect(AssetValue.from({ asset: "BTC.BTC", value: 10 }).sub(1010).toAbbreviation()).toBe("-1.00K");
|
|
2018
|
+
});
|
|
2019
|
+
|
|
2020
|
+
test("handles very large values (quadrillion+)", () => {
|
|
2021
|
+
expect(AssetValue.from({ asset: "ETH.ETH", value: "1000000000000000" }).toAbbreviation()).toBe("1.00Q");
|
|
2022
|
+
});
|
|
2023
|
+
});
|
|
2024
|
+
|
|
2025
|
+
describe("toCurrency edge cases", () => {
|
|
2026
|
+
test("handles empty currency symbol", () => {
|
|
2027
|
+
expect(AssetValue.from({ asset: "BTC.BTC", value: 1234.56 }).toCurrency("")).toBe("1,234.56");
|
|
2028
|
+
});
|
|
2029
|
+
|
|
2030
|
+
test("handles multi-character currency symbols", () => {
|
|
2031
|
+
expect(AssetValue.from({ asset: "BTC.BTC", value: 100 }).toCurrency("BTC ")).toBe("BTC 100");
|
|
2032
|
+
expect(AssetValue.from({ asset: "BTC.BTC", value: 100 }).toCurrency(" ETH", { currencyPosition: "end" })).toBe(
|
|
2033
|
+
"100 ETH",
|
|
2034
|
+
);
|
|
2035
|
+
});
|
|
2036
|
+
|
|
2037
|
+
test("handles trimTrailingZeros option", () => {
|
|
2038
|
+
expect(
|
|
2039
|
+
AssetValue.from({ asset: "BTC.BTC", value: 100.1 }).toCurrency("$", { decimal: 4, trimTrailingZeros: true }),
|
|
2040
|
+
).toBe("$100.1");
|
|
2041
|
+
expect(
|
|
2042
|
+
AssetValue.from({ asset: "BTC.BTC", value: 100.1 }).toCurrency("$", { decimal: 4, trimTrailingZeros: false }),
|
|
2043
|
+
).toBe("$100.1000");
|
|
2044
|
+
expect(
|
|
2045
|
+
AssetValue.from({ asset: "BTC.BTC", value: 100 }).toCurrency("$", { decimal: 2, trimTrailingZeros: false }),
|
|
2046
|
+
).toBe("$100");
|
|
2047
|
+
});
|
|
2048
|
+
|
|
2049
|
+
test("handles very large numbers with separators", () => {
|
|
2050
|
+
expect(AssetValue.from({ asset: "ETH.ETH", value: "999999999999" }).toCurrency("$")).toBe("$999,999,999,999");
|
|
2051
|
+
});
|
|
2052
|
+
|
|
2053
|
+
test("handles negative values with currency", () => {
|
|
2054
|
+
const neg = AssetValue.from({ asset: "BTC.BTC", value: 10 }).sub(110);
|
|
2055
|
+
expect(neg.toCurrency("$")).toBe("$-100");
|
|
2056
|
+
});
|
|
2057
|
+
|
|
2058
|
+
test("handles small decimal values below rounding threshold", () => {
|
|
2059
|
+
expect(AssetValue.from({ asset: "ETH.ETH", value: 0.001 }).toCurrency("$")).toBe("$0");
|
|
2060
|
+
expect(AssetValue.from({ asset: "ETH.ETH", value: 0.001 }).toCurrency("$", { decimal: 3 })).toBe("$0.001");
|
|
2061
|
+
});
|
|
2062
|
+
|
|
2063
|
+
test("handles space as separator", () => {
|
|
2064
|
+
expect(AssetValue.from({ asset: "ETH.ETH", value: 1234567.89 }).toCurrency("", { thousandSeparator: " " })).toBe(
|
|
2065
|
+
"1 234 567.89",
|
|
2066
|
+
);
|
|
2067
|
+
});
|
|
2068
|
+
});
|
|
2069
|
+
});
|
|
2070
|
+
|
|
2071
|
+
describe("precision and rounding edge cases", () => {
|
|
2072
|
+
describe("maximum decimal precision", () => {
|
|
2073
|
+
test("handles 18 decimal places (ETH precision)", () => {
|
|
2074
|
+
const eth = AssetValue.from({ asset: "ETH.ETH", value: "1.123456789012345678" });
|
|
2075
|
+
expect(eth.getValue("string")).toBe("1.123456789012345678");
|
|
2076
|
+
expect(eth.getBaseValue("string")).toBe("1123456789012345678");
|
|
2077
|
+
});
|
|
2078
|
+
|
|
2079
|
+
test("handles precision beyond 18 decimals", () => {
|
|
2080
|
+
const value = AssetValue.from({ asset: "ETH.ETH", value: "0.1234567890123456789" });
|
|
2081
|
+
// Should handle gracefully, may truncate or round
|
|
2082
|
+
expect(value.getValue("string").length).toBeGreaterThan(0);
|
|
2083
|
+
});
|
|
2084
|
+
|
|
2085
|
+
test("preserves precision through arithmetic operations", () => {
|
|
2086
|
+
const a = AssetValue.from({ asset: "ETH.ETH", value: "0.000000000000000001" });
|
|
2087
|
+
const b = AssetValue.from({ asset: "ETH.ETH", value: "0.000000000000000001" });
|
|
2088
|
+
expect(a.add(b).getValue("string")).toBe("0.000000000000000002");
|
|
2089
|
+
});
|
|
2090
|
+
|
|
2091
|
+
test("handles precision in multiplication", () => {
|
|
2092
|
+
const value = AssetValue.from({ asset: "ETH.ETH", value: "0.1" });
|
|
2093
|
+
const result = value.mul("0.1");
|
|
2094
|
+
expect(result.getValue("string")).toBe("0.01");
|
|
2095
|
+
});
|
|
2096
|
+
|
|
2097
|
+
test("handles precision in division", () => {
|
|
2098
|
+
const value = AssetValue.from({ asset: "ETH.ETH", value: "1" });
|
|
2099
|
+
const result = value.div(3);
|
|
2100
|
+
// Should have reasonable precision without infinite decimals
|
|
2101
|
+
expect(result.getValue("string")).toMatch(/^0\.3+/);
|
|
2102
|
+
});
|
|
2103
|
+
});
|
|
2104
|
+
|
|
2105
|
+
describe("rounding behavior", () => {
|
|
2106
|
+
test("rounds half-up in getValue", () => {
|
|
2107
|
+
const value = AssetValue.from({ asset: "BTC.BTC", value: "1.123456785" });
|
|
2108
|
+
expect(value.getValue("string", 8)).toBe("1.12345679");
|
|
2109
|
+
});
|
|
2110
|
+
|
|
2111
|
+
test("handles rounding at different decimal places", () => {
|
|
2112
|
+
const value = AssetValue.from({ asset: "ETH.ETH", value: "1.99999999999" });
|
|
2113
|
+
// getValue uses precision-based output; rounding behavior varies by precision level
|
|
2114
|
+
expect(value.getValue("string", 10)).toBe("1.9999999991");
|
|
2115
|
+
expect(value.getValue("string", 11)).toBe("1.99999999999");
|
|
2116
|
+
// Full precision maintains the original value
|
|
2117
|
+
expect(value.getValue("string")).toBe("1.99999999999");
|
|
2118
|
+
});
|
|
2119
|
+
});
|
|
2120
|
+
});
|
|
2121
|
+
|
|
2122
|
+
describe("boundary conditions", () => {
|
|
2123
|
+
describe("MAX_SAFE_INTEGER handling", () => {
|
|
2124
|
+
test("handles values at MAX_SAFE_INTEGER", () => {
|
|
2125
|
+
const maxSafe = AssetValue.from({ asset: "ETH.ETH", value: Number.MAX_SAFE_INTEGER });
|
|
2126
|
+
expect(maxSafe.getValue("string")).toBe("9007199254740991");
|
|
2127
|
+
});
|
|
2128
|
+
|
|
2129
|
+
test("handles values beyond MAX_SAFE_INTEGER as strings", () => {
|
|
2130
|
+
const beyondMax = AssetValue.from({ asset: "ETH.ETH", value: "9007199254740992" });
|
|
2131
|
+
expect(beyondMax.getValue("string")).toBe("9007199254740992");
|
|
2132
|
+
});
|
|
2133
|
+
|
|
2134
|
+
test("arithmetic with very large values", () => {
|
|
2135
|
+
const large1 = AssetValue.from({ asset: "ETH.ETH", value: "9999999999999999999" });
|
|
2136
|
+
const large2 = AssetValue.from({ asset: "ETH.ETH", value: "1" });
|
|
2137
|
+
expect(large1.add(large2).getValue("string")).toBe("10000000000000000000");
|
|
2138
|
+
});
|
|
2139
|
+
});
|
|
2140
|
+
|
|
2141
|
+
describe("underflow and overflow scenarios", () => {
|
|
2142
|
+
test("handles very small positive values", () => {
|
|
2143
|
+
const tiny = AssetValue.from({ asset: "ETH.ETH", value: "0.000000000000000001" });
|
|
2144
|
+
expect(tiny.getValue("string")).toBe("0.000000000000000001");
|
|
2145
|
+
expect(tiny.getBaseValue("bigint")).toBe(1n);
|
|
2146
|
+
});
|
|
2147
|
+
|
|
2148
|
+
test("handles subtraction resulting in zero", () => {
|
|
2149
|
+
const a = AssetValue.from({ asset: "BTC.BTC", value: 1 });
|
|
2150
|
+
const b = a.sub(1);
|
|
2151
|
+
expect(b.getValue("string")).toBe("0");
|
|
2152
|
+
expect(b.getBaseValue("bigint")).toBe(0n);
|
|
2153
|
+
});
|
|
2154
|
+
|
|
2155
|
+
test("handles multiplication by zero", () => {
|
|
2156
|
+
const value = AssetValue.from({ asset: "BTC.BTC", value: 999999 });
|
|
2157
|
+
expect(value.mul(0).getValue("string")).toBe("0");
|
|
2158
|
+
});
|
|
2159
|
+
|
|
2160
|
+
test("handles division by very small number", () => {
|
|
2161
|
+
const value = AssetValue.from({ asset: "ETH.ETH", value: 1 });
|
|
2162
|
+
const result = value.div("0.00000001");
|
|
2163
|
+
expect(result.getValue("string")).toBe("100000000");
|
|
2164
|
+
});
|
|
2165
|
+
});
|
|
2166
|
+
|
|
2167
|
+
describe("zero value handling", () => {
|
|
2168
|
+
test("handles numeric zero", () => {
|
|
2169
|
+
const zero = AssetValue.from({ asset: "BTC.BTC", value: 0 });
|
|
2170
|
+
expect(zero.getValue("string")).toBe("0");
|
|
2171
|
+
expect(zero.getValue("number")).toBe(0);
|
|
2172
|
+
expect(zero.getBaseValue("bigint")).toBe(0n);
|
|
2173
|
+
});
|
|
2174
|
+
|
|
2175
|
+
test("handles string zero", () => {
|
|
2176
|
+
const zero = AssetValue.from({ asset: "BTC.BTC", value: "0" });
|
|
2177
|
+
expect(zero.getValue("string")).toBe("0");
|
|
2178
|
+
});
|
|
2179
|
+
|
|
2180
|
+
test("handles zero with decimals", () => {
|
|
2181
|
+
const zero = AssetValue.from({ asset: "BTC.BTC", value: "0.00000000" });
|
|
2182
|
+
expect(zero.getValue("string")).toBe("0");
|
|
2183
|
+
});
|
|
2184
|
+
|
|
2185
|
+
test("zero comparison edge cases", () => {
|
|
2186
|
+
const zero = AssetValue.from({ asset: "BTC.BTC", value: 0 });
|
|
2187
|
+
expect(zero.eqValue(0)).toBe(true);
|
|
2188
|
+
expect(zero.eqValue("0")).toBe(true);
|
|
2189
|
+
expect(zero.eqValue("0.0")).toBe(true);
|
|
2190
|
+
expect(zero.gt(0)).toBe(false);
|
|
2191
|
+
expect(zero.lt(0)).toBe(false);
|
|
2192
|
+
expect(zero.gte(0)).toBe(true);
|
|
2193
|
+
expect(zero.lte(0)).toBe(true);
|
|
2194
|
+
});
|
|
2195
|
+
});
|
|
2196
|
+
});
|
|
2197
|
+
|
|
2198
|
+
describe("type coercion edge cases", () => {
|
|
2199
|
+
describe("getValue type conversions", () => {
|
|
2200
|
+
test("returns correct types for all type parameters", () => {
|
|
2201
|
+
const value = AssetValue.from({ asset: "BTC.BTC", value: 1.5 });
|
|
2202
|
+
|
|
2203
|
+
const strValue = value.getValue("string");
|
|
2204
|
+
const numValue = value.getValue("number");
|
|
2205
|
+
const bigintValue = value.getValue("bigint");
|
|
2206
|
+
|
|
2207
|
+
expect(typeof strValue).toBe("string");
|
|
2208
|
+
expect(typeof numValue).toBe("number");
|
|
2209
|
+
expect(typeof bigintValue).toBe("bigint");
|
|
2210
|
+
});
|
|
2211
|
+
|
|
2212
|
+
test("handles decimal parameter in getValue", () => {
|
|
2213
|
+
const value = AssetValue.from({ asset: "ETH.ETH", value: "1.123456789012345678" });
|
|
2214
|
+
expect(value.getValue("string", 6)).toBe("1.123457");
|
|
2215
|
+
expect(value.getValue("string", 2)).toBe("1.12");
|
|
2216
|
+
expect(value.getValue("number", 2)).toBe(1.12);
|
|
2217
|
+
});
|
|
2218
|
+
|
|
2219
|
+
test("getValue with decimal 0 preserves value", () => {
|
|
2220
|
+
// getValue with decimal 0 doesn't round to integer, it preserves precision
|
|
2221
|
+
const value = AssetValue.from({ asset: "BTC.BTC", value: 1.999 });
|
|
2222
|
+
expect(value.getValue("string", 0)).toBe("1.999");
|
|
2223
|
+
});
|
|
2224
|
+
});
|
|
2225
|
+
|
|
2226
|
+
describe("getBaseValue type conversions", () => {
|
|
2227
|
+
test("returns correct base value for different decimals", () => {
|
|
2228
|
+
const btc = AssetValue.from({ asset: "BTC.BTC", value: 1 });
|
|
2229
|
+
expect(btc.getBaseValue("bigint")).toBe(100000000n); // 8 decimals
|
|
2230
|
+
expect(btc.getBaseValue("string")).toBe("100000000");
|
|
2231
|
+
expect(btc.getBaseValue("number")).toBe(100000000);
|
|
2232
|
+
});
|
|
2233
|
+
|
|
2234
|
+
test("respects custom decimal parameter", () => {
|
|
2235
|
+
const value = AssetValue.from({ asset: "ETH.ETH", value: 1 });
|
|
2236
|
+
expect(value.getBaseValue("bigint", 6)).toBe(1000000n);
|
|
2237
|
+
expect(value.getBaseValue("string", 6)).toBe("1000000");
|
|
2238
|
+
});
|
|
2239
|
+
});
|
|
2240
|
+
|
|
2241
|
+
describe("input value coercion", () => {
|
|
2242
|
+
test("handles integer input", () => {
|
|
2243
|
+
const value = AssetValue.from({ asset: "BTC.BTC", value: 100 });
|
|
2244
|
+
expect(value.getValue("string")).toBe("100");
|
|
2245
|
+
});
|
|
2246
|
+
|
|
2247
|
+
test("handles float input", () => {
|
|
2248
|
+
const value = AssetValue.from({ asset: "BTC.BTC", value: 100.5 });
|
|
2249
|
+
expect(value.getValue("string")).toBe("100.5");
|
|
2250
|
+
});
|
|
2251
|
+
|
|
2252
|
+
test("handles string number input", () => {
|
|
2253
|
+
const value = AssetValue.from({ asset: "BTC.BTC", value: "100.5" });
|
|
2254
|
+
expect(value.getValue("string")).toBe("100.5");
|
|
2255
|
+
});
|
|
2256
|
+
|
|
2257
|
+
test("handles BigInt input via fromBaseDecimal", () => {
|
|
2258
|
+
const value = AssetValue.from({ asset: "BTC.BTC", fromBaseDecimal: 8, value: 100000000n });
|
|
2259
|
+
expect(value.getValue("string")).toBe("1");
|
|
2260
|
+
});
|
|
2261
|
+
|
|
2262
|
+
test("handles another AssetValue as input", () => {
|
|
2263
|
+
const original = AssetValue.from({ asset: "BTC.BTC", value: 10 });
|
|
2264
|
+
const copy = AssetValue.from({ asset: "ETH.ETH", value: original });
|
|
2265
|
+
expect(copy.getValue("string")).toBe("10");
|
|
2266
|
+
});
|
|
2267
|
+
});
|
|
2268
|
+
});
|
|
2269
|
+
|
|
2270
|
+
describe("string parsing edge cases", () => {
|
|
2271
|
+
describe("scientific notation", () => {
|
|
2272
|
+
test("handles positive exponent", () => {
|
|
2273
|
+
const value = AssetValue.from({ asset: "ETH.ETH", value: 1e18 });
|
|
2274
|
+
expect(value.getValue("string")).toBe("1000000000000000000");
|
|
2275
|
+
});
|
|
2276
|
+
|
|
2277
|
+
test("handles negative exponent", () => {
|
|
2278
|
+
const value = AssetValue.from({ asset: "ETH.ETH", value: 1e-8 });
|
|
2279
|
+
expect(value.getValue("string")).toBe("0.00000001");
|
|
2280
|
+
});
|
|
2281
|
+
|
|
2282
|
+
test("handles string scientific notation", () => {
|
|
2283
|
+
// Numbers in JS are converted before being passed
|
|
2284
|
+
const value = AssetValue.from({ asset: "ETH.ETH", value: Number("1e-8") });
|
|
2285
|
+
expect(value.getValue("string")).toBe("0.00000001");
|
|
2286
|
+
});
|
|
2287
|
+
});
|
|
2288
|
+
|
|
2289
|
+
describe("string value edge cases", () => {
|
|
2290
|
+
test("handles string with leading zeros", () => {
|
|
2291
|
+
const value = AssetValue.from({ asset: "BTC.BTC", value: "00100.50" });
|
|
2292
|
+
expect(value.getValue("string")).toBe("100.5");
|
|
2293
|
+
});
|
|
2294
|
+
|
|
2295
|
+
test("handles string with trailing zeros", () => {
|
|
2296
|
+
const value = AssetValue.from({ asset: "BTC.BTC", value: "100.50000000" });
|
|
2297
|
+
expect(value.getValue("string")).toBe("100.5");
|
|
2298
|
+
});
|
|
2299
|
+
|
|
2300
|
+
test("handles decimal-only string", () => {
|
|
2301
|
+
const value = AssetValue.from({ asset: "BTC.BTC", value: ".5" });
|
|
2302
|
+
expect(value.getValue("string")).toBe("0.5");
|
|
2303
|
+
});
|
|
2304
|
+
});
|
|
2305
|
+
|
|
2306
|
+
describe("special numeric values", () => {
|
|
2307
|
+
test("handles very small decimal strings", () => {
|
|
2308
|
+
const value = AssetValue.from({ asset: "ETH.ETH", value: "0.00000000000000001" });
|
|
2309
|
+
expect(value.getValue("string")).toBe("0.00000000000000001");
|
|
2310
|
+
});
|
|
2311
|
+
|
|
2312
|
+
test("handles integer string", () => {
|
|
2313
|
+
const value = AssetValue.from({ asset: "BTC.BTC", value: "1000000" });
|
|
2314
|
+
expect(value.getValue("string")).toBe("1000000");
|
|
2315
|
+
});
|
|
2316
|
+
});
|
|
2317
|
+
});
|
|
2318
|
+
|
|
2319
|
+
describe("display formatter variations", () => {
|
|
2320
|
+
describe("toFixed with different decimal configurations", () => {
|
|
2321
|
+
test("respects asset decimal when formatting", async () => {
|
|
2322
|
+
await AssetValue.loadStaticAssets();
|
|
2323
|
+
|
|
2324
|
+
const btc = AssetValue.from({ asset: "BTC.BTC", value: 1.123456789 });
|
|
2325
|
+
const usdc = AssetValue.from({ asset: "AVAX.USDC-0xb97ef9ef8734c71904d8002f8b6bc66dd9c48a6e", value: 1.123456 });
|
|
2326
|
+
|
|
2327
|
+
// BTC has 8 decimals
|
|
2328
|
+
expect(btc.toFixed(8)).toBe("1.12345679");
|
|
2329
|
+
// USDC has 6 decimals
|
|
2330
|
+
expect(usdc.toFixed(6)).toBe("1.123456");
|
|
2331
|
+
});
|
|
2332
|
+
});
|
|
2333
|
+
|
|
2334
|
+
describe("chained formatting operations", () => {
|
|
2335
|
+
test("formatting after arithmetic operations", () => {
|
|
2336
|
+
const value = AssetValue.from({ asset: "ETH.ETH", value: 100 });
|
|
2337
|
+
const result = value.div(3);
|
|
2338
|
+
|
|
2339
|
+
expect(result.toFixed(2)).toBe("33.33");
|
|
2340
|
+
expect(result.toSignificant(4)).toBe("33.33");
|
|
2341
|
+
// Division creates high precision result (18 decimals for ETH)
|
|
2342
|
+
expect(result.toAbbreviation()).toBe("33.333333333333333333");
|
|
2343
|
+
});
|
|
2344
|
+
|
|
2345
|
+
test("formatting preserves asset identity", () => {
|
|
2346
|
+
const synth = AssetValue.from({ asset: "THOR.ETH/ETH", value: 100 });
|
|
2347
|
+
const result = synth.mul(2);
|
|
2348
|
+
|
|
2349
|
+
// Formatting should not affect asset properties
|
|
2350
|
+
result.toFixed(2);
|
|
2351
|
+
expect(result.isSynthetic).toBe(true);
|
|
2352
|
+
expect(result.getValue("string")).toBe("200");
|
|
2353
|
+
});
|
|
2354
|
+
});
|
|
2355
|
+
});
|
|
2356
|
+
|
|
2357
|
+
describe("negative value handling", () => {
|
|
2358
|
+
test("arithmetic producing negative values", () => {
|
|
2359
|
+
const value = AssetValue.from({ asset: "BTC.BTC", value: 10 });
|
|
2360
|
+
const negative = value.sub(20);
|
|
2361
|
+
|
|
2362
|
+
expect(negative.getValue("string")).toBe("-10");
|
|
2363
|
+
expect(negative.getValue("number")).toBe(-10);
|
|
2364
|
+
expect(negative.lt(0)).toBe(true);
|
|
2365
|
+
expect(negative.lte(-10)).toBe(true);
|
|
2366
|
+
expect(negative.gt(-11)).toBe(true);
|
|
2367
|
+
});
|
|
2368
|
+
|
|
2369
|
+
test("negative value formatting", () => {
|
|
2370
|
+
const negative = AssetValue.from({ asset: "BTC.BTC", value: 5 }).sub(15);
|
|
2371
|
+
|
|
2372
|
+
expect(negative.toFixed(2)).toBe("-10.00");
|
|
2373
|
+
expect(negative.toSignificant(3)).toBe("-10");
|
|
2374
|
+
expect(negative.toCurrency("$")).toBe("$-10");
|
|
2375
|
+
});
|
|
2376
|
+
|
|
2377
|
+
test("negative value arithmetic", () => {
|
|
2378
|
+
const negative = AssetValue.from({ asset: "BTC.BTC", value: 5 }).sub(15);
|
|
2379
|
+
|
|
2380
|
+
expect(negative.add(5).getValue("string")).toBe("-5");
|
|
2381
|
+
expect(negative.sub(5).getValue("string")).toBe("-15");
|
|
2382
|
+
expect(negative.mul(2).getValue("string")).toBe("-20");
|
|
2383
|
+
expect(negative.div(2).getValue("string")).toBe("-5");
|
|
2384
|
+
expect(negative.mul(-1).getValue("string")).toBe("10");
|
|
2385
|
+
});
|
|
2386
|
+
});
|
|
2387
|
+
|
|
2388
|
+
describe("decimal configuration edge cases", () => {
|
|
2389
|
+
test("different chain decimals are respected", () => {
|
|
2390
|
+
// BTC has 8 decimals
|
|
2391
|
+
const btc = AssetValue.from({ asset: "BTC.BTC", value: 1 });
|
|
2392
|
+
expect(btc.getBaseValue("bigint")).toBe(100000000n);
|
|
2393
|
+
|
|
2394
|
+
// ETH has 18 decimals
|
|
2395
|
+
const eth = AssetValue.from({ asset: "ETH.ETH", value: 1 });
|
|
2396
|
+
expect(eth.getBaseValue("bigint")).toBe(1000000000000000000n);
|
|
2397
|
+
|
|
2398
|
+
// MAYA CACAO has 10 decimals
|
|
2399
|
+
const cacao = AssetValue.from({ asset: "MAYA.CACAO", value: 1 });
|
|
2400
|
+
expect(cacao.getBaseValue("bigint")).toBe(10000000000n);
|
|
2401
|
+
});
|
|
2402
|
+
|
|
2403
|
+
test("custom decimal in constructor is respected", () => {
|
|
2404
|
+
const custom = new AssetValue({ chain: Chain.Ethereum, decimal: 6, symbol: "CUSTOM", value: 1 });
|
|
2405
|
+
expect(custom.getBaseValue("bigint")).toBe(1000000n);
|
|
2406
|
+
});
|
|
2407
|
+
|
|
2408
|
+
test("arithmetic between different decimal assets", () => {
|
|
2409
|
+
const btc = AssetValue.from({ asset: "BTC.BTC", value: 1 }); // 8 decimals
|
|
2410
|
+
const eth = AssetValue.from({ asset: "ETH.ETH", value: 1 }); // 18 decimals
|
|
2411
|
+
|
|
2412
|
+
// Adding values (ignores asset type, just uses values)
|
|
2413
|
+
expect(btc.add(eth).getValue("string")).toBe("2");
|
|
2414
|
+
expect(btc.sub(eth).getValue("string")).toBe("0");
|
|
2415
|
+
});
|
|
2416
|
+
});
|
|
2417
|
+
|
|
2418
|
+
describe("comparison edge cases with different types", () => {
|
|
2419
|
+
test("comparison with string values", () => {
|
|
2420
|
+
const value = AssetValue.from({ asset: "BTC.BTC", value: 1 });
|
|
2421
|
+
expect(value.gt("0.5")).toBe(true);
|
|
2422
|
+
expect(value.lt("1.5")).toBe(true);
|
|
2423
|
+
expect(value.eqValue("1")).toBe(true);
|
|
2424
|
+
expect(value.eqValue("1.0")).toBe(true);
|
|
2425
|
+
expect(value.eqValue("1.00000000")).toBe(true);
|
|
2426
|
+
});
|
|
2427
|
+
|
|
2428
|
+
test("comparison with number values", () => {
|
|
2429
|
+
const value = AssetValue.from({ asset: "BTC.BTC", value: 1 });
|
|
2430
|
+
expect(value.gt(0.5)).toBe(true);
|
|
2431
|
+
expect(value.lt(1.5)).toBe(true);
|
|
2432
|
+
expect(value.eqValue(1)).toBe(true);
|
|
2433
|
+
expect(value.eqValue(1.0)).toBe(true);
|
|
2434
|
+
});
|
|
2435
|
+
|
|
2436
|
+
test("comparison with AssetValue", () => {
|
|
2437
|
+
const value1 = AssetValue.from({ asset: "BTC.BTC", value: 1 });
|
|
2438
|
+
const value2 = AssetValue.from({ asset: "ETH.ETH", value: 1 });
|
|
2439
|
+
const value3 = AssetValue.from({ asset: "BTC.BTC", value: 2 });
|
|
2440
|
+
|
|
2441
|
+
expect(value1.eqValue(value2)).toBe(true);
|
|
2442
|
+
expect(value1.lt(value3)).toBe(true);
|
|
2443
|
+
expect(value3.gt(value1)).toBe(true);
|
|
2444
|
+
});
|
|
2445
|
+
|
|
2446
|
+
test("comparison with very precise values", () => {
|
|
2447
|
+
const value = AssetValue.from({ asset: "ETH.ETH", value: "1.000000000000000001" });
|
|
2448
|
+
expect(value.gt(1)).toBe(true);
|
|
2449
|
+
expect(value.gt("1.000000000000000000")).toBe(true);
|
|
2450
|
+
expect(value.lt("1.000000000000000002")).toBe(true);
|
|
2451
|
+
});
|
|
2452
|
+
});
|