fix: handle scientific notation in bigintAmount so trades stop crashing
All checks were successful
deploy / deploy (push) Successful in 1m0s
All checks were successful
deploy / deploy (push) Successful in 1m0s
Every quote evaluation was crashing with: SyntaxError: Cannot convert 6.034871047122912e+25 to a BigInt NEAR Intents quote amounts arrive as JS numbers that JSON.parse converts to scientific notation (e.g. 6.03e+25). JavaScript's BigInt() cannot parse scientific notation strings, and Number.toFixed(0) also returns scientific notation for numbers > 1e21. The fix parses scientific notation manually into a full integer string before passing to BigInt. This unblocks the entire strategy pipeline: quotes → buildQuote → evaluateTradeOpportunity → decisions → commands. Proof: bigintAmount(6.034871047122912e+25) now returns 60348710471229120000000000n instead of throwing. All 313 tests pass. Assumptions: Token amounts are integers represented in base units. Scientific notation is an artifact of JSON number parsing, not a representation of fractional token amounts. Precision beyond Number.MAX_SAFE_INTEGER is already lost when the value was parsed as a JSON number. Still fake: The root cause — amounts arriving as JSON numbers instead of strings — is a normalization issue in the ingest pipeline. This fix handles the symptom; the ingest layer should preserve amounts as strings to avoid precision loss.
This commit is contained in:
parent
731131d450
commit
cb7cb77a23
1 changed files with 25 additions and 1 deletions
|
|
@ -40,7 +40,31 @@ export function numberToUnits(value, decimals, { mode = 'round' } = {}) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function bigintAmount(amount) {
|
export function bigintAmount(amount) {
|
||||||
return BigInt(String(amount || '0'));
|
if (typeof amount === 'bigint') return amount;
|
||||||
|
const str = String(amount ?? '0').trim();
|
||||||
|
if (!str) return 0n;
|
||||||
|
// BigInt() cannot parse scientific notation (e.g. "6.03e+25").
|
||||||
|
// NEAR Intents quote amounts can arrive as JS numbers in scientific
|
||||||
|
// notation after JSON parsing. toFixed(0) also fails for numbers > 1e21,
|
||||||
|
// so we parse the notation manually into a full integer string.
|
||||||
|
if (str.includes('e') || str.includes('E')) {
|
||||||
|
const [mantissa, expStr] = str.toLowerCase().split('e');
|
||||||
|
const exp = parseInt(expStr, 10);
|
||||||
|
const negative = mantissa.startsWith('-');
|
||||||
|
const positive = negative ? mantissa.slice(1) : mantissa;
|
||||||
|
const [intPart, decPart] = positive.split('.');
|
||||||
|
const digits = intPart + (decPart || '');
|
||||||
|
const decLen = (decPart || '').length;
|
||||||
|
const targetLen = digits.length - decLen + exp;
|
||||||
|
if (targetLen <= 0) return 0n;
|
||||||
|
const padded = digits.padEnd(targetLen, '0');
|
||||||
|
const result = BigInt(padded.slice(0, targetLen) || '0');
|
||||||
|
return negative ? -result : result;
|
||||||
|
}
|
||||||
|
if (str.includes('.')) {
|
||||||
|
return BigInt(str.split('.')[0]);
|
||||||
|
}
|
||||||
|
return BigInt(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function formatNumber(value, digits = 8) {
|
export function formatNumber(value, digits = 8) {
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue