{"version":3,"file":"util.mjs","sources":["../src/util.ts"],"sourcesContent":["import { ABIArrayDynamicType, ABIArrayStaticType, ABIByteType, ABIReturnType, ABITupleType, ABIType, ABIUintType, ABIValue } from 'algosdk'\nimport { APP_PAGE_MAX_SIZE } from './types/app'\n\n/**\n * Converts a value which might be a number or a bigint into a number to be used with apis that don't support bigint.\n *\n * Throws an UnsafeConversionError if the conversion would result in an unsafe integer for the Number type\n * @param value\n */\nexport const toNumber = (value: number | bigint) => {\n  if (typeof value === 'number') return value\n\n  if (value > BigInt(Number.MAX_SAFE_INTEGER)) {\n    throw new UnsafeConversionError(\n      `Cannot convert ${value} to a Number as it is larger than the maximum safe integer the Number type can hold.`,\n    )\n  } else if (value < BigInt(Number.MIN_SAFE_INTEGER)) {\n    throw new UnsafeConversionError(\n      `Cannot convert ${value} to a Number as it is smaller than the minimum safe integer the Number type can hold.`,\n    )\n  }\n  return Number(value)\n}\n\nexport class UnsafeConversionError extends Error {}\n\n/**\n * Calculates the amount of funds to add to a wallet to bring it up to the minimum spending balance.\n * @param minSpendingBalance The minimum spending balance for the wallet\n * @param currentSpendingBalance The current spending balance for the wallet\n * @param minFundingIncrement The minimum amount of funds that can be added to the wallet\n * @returns The amount of funds to add to the wallet or null if the wallet is already above the minimum spending balance\n */\nexport const calculateFundAmount = (\n  minSpendingBalance: bigint,\n  currentSpendingBalance: bigint,\n  minFundingIncrement: bigint,\n): bigint | null => {\n  if (minSpendingBalance > currentSpendingBalance) {\n    const minFundAmount = minSpendingBalance - currentSpendingBalance\n    return BigInt(Math.max(Number(minFundAmount), Number(minFundingIncrement)))\n  } else {\n    return null\n  }\n}\n\n/**\n * Checks if the current environment is Node.js\n *\n * @returns A boolean indicating whether the current environment is Node.js\n */\nexport const isNode = () => {\n  return typeof process !== 'undefined' && process.versions != null && process.versions.node != null\n}\n\n/**\n * Returns the given array split into chunks of `batchSize` batches.\n * @param array The array to chunk\n * @param batchSize The size of batches to split the array into\n * @returns A generator that yields the array split into chunks of `batchSize` batches\n */\nexport function* chunkArray<T>(array: T[], batchSize: number): Generator<T[], void> {\n  for (let i = 0; i < array.length; i += batchSize) yield array.slice(i, i + batchSize)\n}\n\n/**\n * Memoize calls to the given function in an in-memory map.\n * @param fn The function to memoize\n * @returns The memoized function\n */\nexport const memoize = <T = unknown, R = unknown>(fn: (val: T) => R) => {\n  const cache = new Map()\n  const cached = function (this: unknown, val: T) {\n    return cache.has(val) ? cache.get(val) : cache.set(val, fn.call(this, val)) && cache.get(val)\n  }\n  cached.cache = cache\n  return cached as (val: T) => R\n}\n\nexport const binaryStartsWith = (base: Uint8Array, startsWith: Uint8Array): boolean => {\n  if (startsWith.length > base.length) return false\n  for (let i = 0; i < startsWith.length; i++) {\n    if (base[i] !== startsWith[i]) return false\n  }\n  return true\n}\n\nexport const defaultJsonValueReplacer = (key: string, value: unknown) => {\n  if (typeof value === 'bigint') {\n    try {\n      return toNumber(value)\n    } catch {\n      return value.toString()\n    }\n  }\n  return value\n}\nexport const asJson = (\n  value: unknown,\n  replacer: (key: string, value: unknown) => unknown = defaultJsonValueReplacer,\n  space?: string | number,\n) => {\n  return JSON.stringify(value, replacer, space)\n}\n\n/** Calculate minimum number of extra program pages required for provided approval and clear state programs */\nexport const calculateExtraProgramPages = (approvalProgram: Uint8Array, clearStateProgram?: Uint8Array): number => {\n  return Math.floor((approvalProgram.length + (clearStateProgram?.length ?? 0) - 1) / APP_PAGE_MAX_SIZE)\n}\n\n/** Take a decoded ABI value and convert all byte arrays (including nested ones) from number[] to Uint8Arrays */\nexport function convertAbiByteArrays(value: ABIValue, type: ABIReturnType): ABIValue {\n  // Return value as is if the type doesn't have any bytes or if it's already an Uint8Array\n  if (!type.toString().includes('byte') || value instanceof Uint8Array) {\n    return value\n  }\n\n  // Handle byte arrays (byte[N] or byte[])\n  if (\n    (type instanceof ABIArrayStaticType || type instanceof ABIArrayDynamicType) &&\n    type.childType instanceof ABIByteType &&\n    Array.isArray(value)\n  ) {\n    return new Uint8Array(value as number[])\n  }\n\n  // Handle other arrays (for nested structures)\n  if ((type instanceof ABIArrayStaticType || type instanceof ABIArrayDynamicType) && Array.isArray(value)) {\n    const result = []\n    for (let i = 0; i < value.length; i++) {\n      result.push(convertAbiByteArrays(value[i], type.childType))\n    }\n    return result\n  }\n\n  // Handle tuples (for nested structures)\n  if (type instanceof ABITupleType && Array.isArray(value)) {\n    const result = []\n    for (let i = 0; i < value.length && i < type.childTypes.length; i++) {\n      result.push(convertAbiByteArrays(value[i], type.childTypes[i]))\n    }\n    return result\n  }\n\n  // For other types, return the value as is\n  return value\n}\n\n/**\n * Convert bigint values to numbers for uint types with bit size < 53\n */\nexport const convertABIDecodedBigIntToNumber = (value: ABIValue, type: ABIType): ABIValue => {\n  if (typeof value === 'bigint') {\n    if (type instanceof ABIUintType) {\n      return type.bitSize < 53 ? Number(value) : value\n    } else {\n      return value\n    }\n  } else if (Array.isArray(value) && (type instanceof ABIArrayStaticType || type instanceof ABIArrayDynamicType)) {\n    return value.map((v) => convertABIDecodedBigIntToNumber(v, type.childType))\n  } else if (Array.isArray(value) && type instanceof ABITupleType) {\n    return value.map((v, i) => convertABIDecodedBigIntToNumber(v, type.childTypes[i]))\n  } else {\n    return value\n  }\n}\n"],"names":[],"mappings":";;;AAGA;;;;;AAKG;AACU,MAAA,QAAQ,GAAG,CAAC,KAAsB,KAAI;IACjD,IAAI,OAAO,KAAK,KAAK,QAAQ;AAAE,QAAA,OAAO,KAAK;IAE3C,IAAI,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC,EAAE;AAC3C,QAAA,MAAM,IAAI,qBAAqB,CAC7B,kBAAkB,KAAK,CAAA,oFAAA,CAAsF,CAC9G;;SACI,IAAI,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC,EAAE;AAClD,QAAA,MAAM,IAAI,qBAAqB,CAC7B,kBAAkB,KAAK,CAAA,qFAAA,CAAuF,CAC/G;;AAEH,IAAA,OAAO,MAAM,CAAC,KAAK,CAAC;AACtB;AAEM,MAAO,qBAAsB,SAAQ,KAAK,CAAA;AAAG;AAEnD;;;;;;AAMG;AACU,MAAA,mBAAmB,GAAG,CACjC,kBAA0B,EAC1B,sBAA8B,EAC9B,mBAA2B,KACV;AACjB,IAAA,IAAI,kBAAkB,GAAG,sBAAsB,EAAE;AAC/C,QAAA,MAAM,aAAa,GAAG,kBAAkB,GAAG,sBAAsB;AACjE,QAAA,OAAO,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC,mBAAmB,CAAC,CAAC,CAAC;;SACtE;AACL,QAAA,OAAO,IAAI;;AAEf;AAWA;;;;;AAKG;UACc,UAAU,CAAI,KAAU,EAAE,SAAiB,EAAA;AAC1D,IAAA,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,IAAI,SAAS;QAAE,MAAM,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC;AACvF;AAEA;;;;AAIG;AACU,MAAA,OAAO,GAAG,CAA2B,EAAiB,KAAI;AACrE,IAAA,MAAM,KAAK,GAAG,IAAI,GAAG,EAAE;IACvB,MAAM,MAAM,GAAG,UAAyB,GAAM,EAAA;AAC5C,QAAA,OAAO,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,IAAI,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC;AAC/F,KAAC;AACD,IAAA,MAAM,CAAC,KAAK,GAAG,KAAK;AACpB,IAAA,OAAO,MAAuB;AAChC;MAEa,gBAAgB,GAAG,CAAC,IAAgB,EAAE,UAAsB,KAAa;AACpF,IAAA,IAAI,UAAU,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM;AAAE,QAAA,OAAO,KAAK;AACjD,IAAA,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,UAAU,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;QAC1C,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,UAAU,CAAC,CAAC,CAAC;AAAE,YAAA,OAAO,KAAK;;AAE7C,IAAA,OAAO,IAAI;AACb;MAEa,wBAAwB,GAAG,CAAC,GAAW,EAAE,KAAc,KAAI;AACtE,IAAA,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE;AAC7B,QAAA,IAAI;AACF,YAAA,OAAO,QAAQ,CAAC,KAAK,CAAC;;AACtB,QAAA,MAAM;AACN,YAAA,OAAO,KAAK,CAAC,QAAQ,EAAE;;;AAG3B,IAAA,OAAO,KAAK;AACd;AACO,MAAM,MAAM,GAAG,CACpB,KAAc,EACd,QAAA,GAAqD,wBAAwB,EAC7E,KAAuB,KACrB;IACF,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,QAAQ,EAAE,KAAK,CAAC;AAC/C;AAEA;MACa,0BAA0B,GAAG,CAAC,eAA2B,EAAE,iBAA8B,KAAY;IAChH,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,eAAe,CAAC,MAAM,IAAI,iBAAiB,EAAE,MAAM,IAAI,CAAC,CAAC,GAAG,CAAC,IAAI,iBAAiB,CAAC;AACxG;AAEA;AACgB,SAAA,oBAAoB,CAAC,KAAe,EAAE,IAAmB,EAAA;;AAEvE,IAAA,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,KAAK,YAAY,UAAU,EAAE;AACpE,QAAA,OAAO,KAAK;;;IAId,IACE,CAAC,IAAI,YAAY,kBAAkB,IAAI,IAAI,YAAY,mBAAmB;QAC1E,IAAI,CAAC,SAAS,YAAY,WAAW;AACrC,QAAA,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EACpB;AACA,QAAA,OAAO,IAAI,UAAU,CAAC,KAAiB,CAAC;;;AAI1C,IAAA,IAAI,CAAC,IAAI,YAAY,kBAAkB,IAAI,IAAI,YAAY,mBAAmB,KAAK,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE;QACvG,MAAM,MAAM,GAAG,EAAE;AACjB,QAAA,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;AACrC,YAAA,MAAM,CAAC,IAAI,CAAC,oBAAoB,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;;AAE7D,QAAA,OAAO,MAAM;;;IAIf,IAAI,IAAI,YAAY,YAAY,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE;QACxD,MAAM,MAAM,GAAG,EAAE;QACjB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,IAAI,CAAC,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;AACnE,YAAA,MAAM,CAAC,IAAI,CAAC,oBAAoB,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;;AAEjE,QAAA,OAAO,MAAM;;;AAIf,IAAA,OAAO,KAAK;AACd;AAEA;;AAEG;MACU,+BAA+B,GAAG,CAAC,KAAe,EAAE,IAAa,KAAc;AAC1F,IAAA,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE;AAC7B,QAAA,IAAI,IAAI,YAAY,WAAW,EAAE;AAC/B,YAAA,OAAO,IAAI,CAAC,OAAO,GAAG,EAAE,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,KAAK;;aAC3C;AACL,YAAA,OAAO,KAAK;;;AAET,SAAA,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,IAAI,YAAY,kBAAkB,IAAI,IAAI,YAAY,mBAAmB,CAAC,EAAE;AAC9G,QAAA,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,+BAA+B,CAAC,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;;SACtE,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,IAAI,YAAY,YAAY,EAAE;QAC/D,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,+BAA+B,CAAC,CAAC,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;;SAC7E;AACL,QAAA,OAAO,KAAK;;AAEhB;;;;"}