From cb7cb77a23b7cb26d8a50ae275353eee52de0bc3 Mon Sep 17 00:00:00 2001 From: philipp Date: Sun, 5 Jul 2026 02:01:32 +0200 Subject: [PATCH] fix: handle scientific notation in bigintAmount so trades stop crashing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- src/core/assets.mjs | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/src/core/assets.mjs b/src/core/assets.mjs index a959f80..f4d4627 100644 --- a/src/core/assets.mjs +++ b/src/core/assets.mjs @@ -40,7 +40,31 @@ export function numberToUnits(value, decimals, { mode = 'round' } = {}) { } 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) {