@shapeshiftoss/utils 1.0.5 → 1.1.0

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.
Files changed (42) hide show
  1. package/LICENSE.md +21 -0
  2. package/dist/cjs/.tsbuildinfo +1 -1
  3. package/dist/cjs/assetData/baseAssets.d.ts +24 -1
  4. package/dist/cjs/assetData/baseAssets.js +383 -17
  5. package/dist/cjs/assetData/decodeAssetData.js +2 -2
  6. package/dist/cjs/assetData/getBaseAsset.js +48 -2
  7. package/dist/cjs/bigAmount/bigAmount.d.ts +82 -0
  8. package/dist/cjs/bigAmount/bigAmount.js +276 -0
  9. package/dist/cjs/bigAmount/bigAmount.test.d.ts +1 -0
  10. package/dist/cjs/bigAmount/bigAmount.test.js +1194 -0
  11. package/dist/cjs/chainIdToFeeAssetId.js +48 -2
  12. package/dist/cjs/encoding.d.ts +2 -0
  13. package/dist/cjs/encoding.js +13 -0
  14. package/dist/cjs/getAssetNamespaceFromChainId.js +25 -1
  15. package/dist/cjs/getChainShortName.d.ts +1 -1
  16. package/dist/cjs/getChainShortName.js +48 -2
  17. package/dist/cjs/getNativeFeeAssetReference.js +53 -2
  18. package/dist/cjs/index.d.ts +3 -0
  19. package/dist/cjs/index.js +7 -3
  20. package/dist/cjs/treasury.d.ts +10 -6
  21. package/dist/cjs/treasury.js +13 -6
  22. package/dist/esm/.tsbuildinfo +1 -1
  23. package/dist/esm/assetData/baseAssets.d.ts +24 -1
  24. package/dist/esm/assetData/baseAssets.js +381 -16
  25. package/dist/esm/assetData/decodeAssetData.js +1 -1
  26. package/dist/esm/assetData/getBaseAsset.js +49 -3
  27. package/dist/esm/bigAmount/bigAmount.d.ts +82 -0
  28. package/dist/esm/bigAmount/bigAmount.js +272 -0
  29. package/dist/esm/bigAmount/bigAmount.test.d.ts +1 -0
  30. package/dist/esm/bigAmount/bigAmount.test.js +1192 -0
  31. package/dist/esm/chainIdToFeeAssetId.js +49 -3
  32. package/dist/esm/encoding.d.ts +2 -0
  33. package/dist/esm/encoding.js +8 -0
  34. package/dist/esm/getAssetNamespaceFromChainId.js +25 -1
  35. package/dist/esm/getChainShortName.d.ts +1 -1
  36. package/dist/esm/getChainShortName.js +48 -2
  37. package/dist/esm/getNativeFeeAssetReference.js +53 -2
  38. package/dist/esm/index.d.ts +3 -0
  39. package/dist/esm/index.js +4 -1
  40. package/dist/esm/treasury.d.ts +10 -6
  41. package/dist/esm/treasury.js +12 -5
  42. package/package.json +15 -16
@@ -0,0 +1,272 @@
1
+ import { bn, bnOrZero } from '../bignumber/bignumber.js';
2
+ const ROUND_DOWN = 1;
3
+ const ROUND_HALF_UP = 4;
4
+ const TEN = bn(10);
5
+ const THOR_PRECISION = 8;
6
+ export class BigAmount {
7
+ // Internal value is ALWAYS in base units (raw blockchain integer scale).
8
+ value;
9
+ precision;
10
+ assetId;
11
+ static config;
12
+ constructor(value, precision, assetId) {
13
+ this.value = value;
14
+ this.precision = precision;
15
+ this.assetId = assetId;
16
+ }
17
+ // ── Configuration ───────────────────────────────
18
+ static configure(config) {
19
+ BigAmount.config = config;
20
+ }
21
+ static getConfig() {
22
+ return BigAmount.config;
23
+ }
24
+ static resetConfig() {
25
+ BigAmount.config = undefined;
26
+ }
27
+ // ── Construction (all nullish-safe) ───────────────
28
+ static fromBaseUnit(args) {
29
+ if ('assetId' in args && args.assetId !== undefined) {
30
+ const precision = BigAmount.resolveConfigPrecision(args.assetId);
31
+ return new BigAmount(bnOrZero(args.value), precision, args.assetId);
32
+ }
33
+ return new BigAmount(bnOrZero(args.value), args.precision);
34
+ }
35
+ static fromPrecision(args) {
36
+ if ('assetId' in args && args.assetId !== undefined) {
37
+ const precision = BigAmount.resolveConfigPrecision(args.assetId);
38
+ return new BigAmount(bnOrZero(args.value).times(TEN.pow(precision)), precision, args.assetId);
39
+ }
40
+ return new BigAmount(bnOrZero(args.value).times(TEN.pow(args.precision)), args.precision);
41
+ }
42
+ static zero({ precision, assetId }) {
43
+ return new BigAmount(bn(0), precision, assetId);
44
+ }
45
+ static fromBN({ value, precision, assetId, }) {
46
+ const safeValue = value.isFinite() ? value : bn(0);
47
+ return new BigAmount(safeValue.times(TEN.pow(precision)), precision, assetId);
48
+ }
49
+ static fromJSON({ value, precision, assetId, }) {
50
+ return new BigAmount(bn(value), precision, assetId);
51
+ }
52
+ static min(...amounts) {
53
+ if (amounts.length === 0)
54
+ throw new Error('BigAmount.min requires at least one argument');
55
+ return amounts.reduce((acc, cur) => {
56
+ assertSamePrecision(acc, cur);
57
+ return acc.value.lte(cur.value) ? acc : cur;
58
+ });
59
+ }
60
+ static max(...amounts) {
61
+ if (amounts.length === 0)
62
+ throw new Error('BigAmount.max requires at least one argument');
63
+ return amounts.reduce((acc, cur) => {
64
+ assertSamePrecision(acc, cur);
65
+ return acc.value.gte(cur.value) ? acc : cur;
66
+ });
67
+ }
68
+ static isBigAmount(value) {
69
+ return value instanceof BigAmount;
70
+ }
71
+ // ── Arithmetic (chainable → BigAmount) ────────────
72
+ plus(other) {
73
+ if (other instanceof BigAmount) {
74
+ assertSamePrecision(this, other);
75
+ return new BigAmount(this.value.plus(other.value), this.precision, this.assetId);
76
+ }
77
+ return new BigAmount(this.value.plus(bnOrZero(other).times(TEN.pow(this.precision))), this.precision, this.assetId);
78
+ }
79
+ minus(other) {
80
+ if (other instanceof BigAmount) {
81
+ assertSamePrecision(this, other);
82
+ return new BigAmount(this.value.minus(other.value), this.precision, this.assetId);
83
+ }
84
+ return new BigAmount(this.value.minus(bnOrZero(other).times(TEN.pow(this.precision))), this.precision, this.assetId);
85
+ }
86
+ times(scalar) {
87
+ assertNotBigAmount(scalar, 'times');
88
+ return new BigAmount(this.value.times(bnOrZero(scalar)), this.precision, this.assetId);
89
+ }
90
+ div(scalar) {
91
+ assertNotBigAmount(scalar, 'div');
92
+ const divisor = bnOrZero(scalar);
93
+ if (divisor.isZero()) {
94
+ return BigAmount.zero({ precision: this.precision, assetId: this.assetId });
95
+ }
96
+ return new BigAmount(this.value.div(divisor), this.precision, this.assetId);
97
+ }
98
+ abs() {
99
+ return new BigAmount(this.value.abs(), this.precision, this.assetId);
100
+ }
101
+ negated() {
102
+ return new BigAmount(this.value.negated(), this.precision, this.assetId);
103
+ }
104
+ positiveOrZero() {
105
+ return this.value.isPositive()
106
+ ? this
107
+ : BigAmount.zero({ precision: this.precision, assetId: this.assetId });
108
+ }
109
+ decimalPlaces(n, rm) {
110
+ const precisionValue = this.value.div(TEN.pow(this.precision));
111
+ const truncated = precisionValue.decimalPlaces(n, rm);
112
+ return new BigAmount(truncated.times(TEN.pow(this.precision)), this.precision, this.assetId);
113
+ }
114
+ // ── Comparison (terminal → boolean) ───────────────
115
+ gt(other) {
116
+ if (other instanceof BigAmount) {
117
+ assertSamePrecision(this, other);
118
+ return this.value.gt(other.value);
119
+ }
120
+ return this.value.gt(bnOrZero(other).times(TEN.pow(this.precision)));
121
+ }
122
+ gte(other) {
123
+ if (other instanceof BigAmount) {
124
+ assertSamePrecision(this, other);
125
+ return this.value.gte(other.value);
126
+ }
127
+ return this.value.gte(bnOrZero(other).times(TEN.pow(this.precision)));
128
+ }
129
+ lt(other) {
130
+ if (other instanceof BigAmount) {
131
+ assertSamePrecision(this, other);
132
+ return this.value.lt(other.value);
133
+ }
134
+ return this.value.lt(bnOrZero(other).times(TEN.pow(this.precision)));
135
+ }
136
+ lte(other) {
137
+ if (other instanceof BigAmount) {
138
+ assertSamePrecision(this, other);
139
+ return this.value.lte(other.value);
140
+ }
141
+ return this.value.lte(bnOrZero(other).times(TEN.pow(this.precision)));
142
+ }
143
+ eq(other) {
144
+ if (other instanceof BigAmount) {
145
+ assertSamePrecision(this, other);
146
+ return this.value.eq(other.value);
147
+ }
148
+ return this.value.eq(bnOrZero(other).times(TEN.pow(this.precision)));
149
+ }
150
+ isZero() {
151
+ return this.value.isZero();
152
+ }
153
+ isPositive() {
154
+ return this.value.isPositive();
155
+ }
156
+ isNegative() {
157
+ return this.value.isNegative();
158
+ }
159
+ isFinite() {
160
+ return this.value.isFinite();
161
+ }
162
+ // ── Output ────────────────────────────────────────
163
+ toBaseUnit() {
164
+ return this.value.toFixed(0, ROUND_HALF_UP);
165
+ }
166
+ toPrecision() {
167
+ return this.value.div(TEN.pow(this.precision)).toFixed();
168
+ }
169
+ toBN() {
170
+ return this.value.div(TEN.pow(this.precision));
171
+ }
172
+ toFixed(decimals) {
173
+ const precisionValue = this.value.div(TEN.pow(this.precision));
174
+ if (typeof decimals === 'number') {
175
+ return precisionValue.toFixed(decimals, ROUND_DOWN);
176
+ }
177
+ return precisionValue.toFixed();
178
+ }
179
+ toString() {
180
+ return this.toPrecision();
181
+ }
182
+ toNumber() {
183
+ return this.value.div(TEN.pow(this.precision)).toNumber();
184
+ }
185
+ toSignificant(digits) {
186
+ const precisionValue = this.value.div(TEN.pow(this.precision));
187
+ if (precisionValue.isZero())
188
+ return '0';
189
+ const fixed = precisionValue.toFixed();
190
+ const isNeg = fixed.startsWith('-');
191
+ const abs = isNeg ? fixed.slice(1) : fixed;
192
+ const dotIndex = abs.indexOf('.');
193
+ if (dotIndex === -1)
194
+ return fixed;
195
+ const intPart = abs.slice(0, dotIndex);
196
+ const decPart = abs.slice(dotIndex + 1);
197
+ if (intPart !== '0') {
198
+ const intDigits = intPart.length;
199
+ if (intDigits >= digits)
200
+ return (isNeg ? '-' : '') + intPart;
201
+ const trimmed = decPart.slice(0, digits - intDigits);
202
+ const result = `${intPart}.${trimmed}`.replace(/\.?0+$/, '');
203
+ return (isNeg ? '-' : '') + result;
204
+ }
205
+ let firstNonZero = 0;
206
+ while (firstNonZero < decPart.length && decPart[firstNonZero] === '0') {
207
+ firstNonZero++;
208
+ }
209
+ const significantPart = decPart.slice(firstNonZero, firstNonZero + digits);
210
+ const leadingZeros = decPart.slice(0, firstNonZero);
211
+ const result = `0.${leadingZeros}${significantPart}`.replace(/0+$/, '');
212
+ return (isNeg ? '-' : '') + result;
213
+ }
214
+ // ── Fiat conversion ────────────────────────────────
215
+ toUserCurrency(decimals = 2) {
216
+ if (!this.assetId)
217
+ throw new Error('BigAmount: toUserCurrency() requires assetId');
218
+ if (!BigAmount.config?.resolvePrice)
219
+ throw new Error('BigAmount: not configured');
220
+ const price = BigAmount.config.resolvePrice(this.assetId);
221
+ return this.value
222
+ .div(TEN.pow(this.precision))
223
+ .times(bnOrZero(price))
224
+ .toFixed(decimals, ROUND_HALF_UP);
225
+ }
226
+ toUSD(decimals = 2) {
227
+ if (!this.assetId)
228
+ throw new Error('BigAmount: toUSD() requires assetId');
229
+ if (!BigAmount.config?.resolvePriceUsd)
230
+ throw new Error('BigAmount: not configured');
231
+ const priceUsd = BigAmount.config.resolvePriceUsd(this.assetId);
232
+ return this.value
233
+ .div(TEN.pow(this.precision))
234
+ .times(bnOrZero(priceUsd))
235
+ .toFixed(decimals, ROUND_HALF_UP);
236
+ }
237
+ // ── THORChain precision ──────────────────────────
238
+ static fromThorBaseUnit(value) {
239
+ return BigAmount.fromBaseUnit({ value, precision: THOR_PRECISION });
240
+ }
241
+ toThorBaseUnit() {
242
+ return this.value
243
+ .times(TEN.pow(THOR_PRECISION))
244
+ .div(TEN.pow(this.precision))
245
+ .toFixed(0, ROUND_HALF_UP);
246
+ }
247
+ // ── Interop ───────────────────────────────────────
248
+ toJSON() {
249
+ return {
250
+ value: this.value.toFixed(0, ROUND_HALF_UP),
251
+ precision: this.precision,
252
+ assetId: this.assetId,
253
+ };
254
+ }
255
+ // ── Private helpers ────────────────────────────────
256
+ static resolveConfigPrecision(assetId) {
257
+ if (!BigAmount.config?.resolvePrecision) {
258
+ throw new Error('BigAmount: not configured — call BigAmount.configure() first');
259
+ }
260
+ return BigAmount.config.resolvePrecision(assetId);
261
+ }
262
+ }
263
+ function assertSamePrecision(a, b) {
264
+ if (a.precision !== b.precision) {
265
+ throw new Error(`Cannot operate on amounts with different precisions: ${a.precision} vs ${b.precision}`);
266
+ }
267
+ }
268
+ function assertNotBigAmount(value, method) {
269
+ if (value instanceof BigAmount) {
270
+ throw new TypeError(`BigAmount.${method} does not accept BigAmount as argument (dimensionally invalid). Use .toPrecision() or .toBaseUnit() to extract the scalar first.`);
271
+ }
272
+ }
@@ -0,0 +1 @@
1
+ export {};