export interface ParseBigIntOptions { /** * The number of digits starting from the right of the returned bigint to consider as decimal * places. * * @default 18n */ precision?: bigint | undefined /** * If true, requires exact match (no commas, no extra whitespace) * * @default false */ strict?: boolean | undefined } /** * Like `parseNumber()`, but returns a bigint instead of a number. Decimals to the right of * `precision` are truncated. * * @param value - The string to parse as a bigint. * @param options - Parsing options. * @returns The bigint representation of `value`, or `null` if we failed to parse it. */ export function parseBigInt(value: string, options?: ParseBigIntOptions) { const { precision = 18n, strict = false } = options ?? {} if (precision < 0n) { throw new Error(`[parseBigInt] \`precision\` must be positive, got ${precision}`) } const originalValue = value const cleanedValue = value.replace(/,/g, '').trim() if (strict && cleanedValue !== originalValue) return null if (cleanedValue === '' || cleanedValue === '-' || cleanedValue === '.' || cleanedValue === '-.') return null const [integerPart, decimalPart = '', somethingAfterDecimalPart] = cleanedValue.split('.') if (integerPart!.trim() !== integerPart) return null if (decimalPart.trim() !== decimalPart) return null if (somethingAfterDecimalPart !== undefined) return null try { const precisionNumber = Number(precision) return BigInt( `${integerPart}${decimalPart.slice(0, precisionNumber).padEnd(precisionNumber, '0')}`, ) } catch { return null } }