{"ast":null,"code":"var __assign = this && this.__assign || function () {\n  __assign = Object.assign || function (t) {\n    for (var s, i = 1, n = arguments.length; i < n; i++) {\n      s = arguments[i];\n      for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];\n    }\n    return t;\n  };\n  return __assign.apply(this, arguments);\n};\nimport { encodeBase64ToJson, encodeBase64toUint8, encodeJsonToBase64, encodeUint8toBase64Url } from './base64.js';\nimport { TOKEN_PREFIX, TOKEN_VERSION } from './utils/Constants.js';\nimport { bytesToHex, hexToBytes } from '@noble/curves/abstract/utils';\nimport { sha256 } from '@noble/hashes/sha256';\nimport { decodeCBOR, encodeCBOR } from './cbor.js';\nimport { PaymentRequest } from './model/PaymentRequest.js';\nimport { pointFromHex } from '@cashu/crypto/modules/common';\nimport { verifyDLEQProof_reblind } from '@cashu/crypto/modules/client/NUT12';\n/**\n * Splits the amount into denominations of the provided @param keyset\n * @param value amount to split\n * @param keyset keys to look up split amounts\n * @param split? optional custom split amounts\n * @param order? optional order for split amounts (default: \"asc\")\n * @returns Array of split amounts\n * @throws Error if @param split amount is greater than @param value amount\n */\nexport function splitAmount(value, keyset, split, order) {\n  if (split) {\n    if (split.reduce(function (a, b) {\n      return a + b;\n    }, 0) > value) {\n      throw new Error(\"Split is greater than total amount: \".concat(split.reduce(function (a, b) {\n        return a + b;\n      }, 0), \" > \").concat(value));\n    }\n    split.forEach(function (amt) {\n      if (!hasCorrespondingKey(amt, keyset)) {\n        throw new Error('Provided amount preferences do not match the amounts of the mint keyset.');\n      }\n    });\n    value = value - split.reduce(function (curr, acc) {\n      return curr + acc;\n    }, 0);\n  } else {\n    split = [];\n  }\n  var sortedKeyAmounts = getKeysetAmounts(keyset);\n  sortedKeyAmounts.forEach(function (amt) {\n    var q = Math.floor(value / amt);\n    for (var i = 0; i < q; ++i) split === null || split === void 0 ? void 0 : split.push(amt);\n    value %= amt;\n  });\n  return split.sort(function (a, b) {\n    return order === 'desc' ? b - a : a - b;\n  });\n}\n/**\n * Creates a list of amounts to keep based on the proofs we have and the proofs we want to reach.\n * @param proofsWeHave complete set of proofs stored (from current mint)\n * @param amountToKeep amount to keep\n * @param keys keys of current keyset\n * @param targetCount the target number of proofs to reach\n * @returns an array of amounts to keep\n */\nexport function getKeepAmounts(proofsWeHave, amountToKeep, keys, targetCount) {\n  // determines amounts we need to reach the targetCount for each amount based on the amounts of the proofs we have\n  // it tries to select amounts so that the proofs we have and the proofs we want reach the targetCount\n  var amountsWeWant = [];\n  var amountsWeHave = proofsWeHave.map(function (p) {\n    return p.amount;\n  });\n  var sortedKeyAmounts = getKeysetAmounts(keys, 'asc');\n  sortedKeyAmounts.forEach(function (amt) {\n    var countWeHave = amountsWeHave.filter(function (a) {\n      return a === amt;\n    }).length;\n    var countWeWant = Math.max(targetCount - countWeHave, 0);\n    for (var i = 0; i < countWeWant; ++i) {\n      if (amountsWeWant.reduce(function (a, b) {\n        return a + b;\n      }, 0) + amt > amountToKeep) {\n        break;\n      }\n      amountsWeWant.push(amt);\n    }\n  });\n  // use splitAmount to fill the rest between the sum of amountsWeHave and amountToKeep\n  var amountDiff = amountToKeep - amountsWeWant.reduce(function (a, b) {\n    return a + b;\n  }, 0);\n  if (amountDiff) {\n    var remainingAmounts = splitAmount(amountDiff, keys);\n    remainingAmounts.forEach(function (amt) {\n      amountsWeWant.push(amt);\n    });\n  }\n  var sortedAmountsWeWant = amountsWeWant.sort(function (a, b) {\n    return a - b;\n  });\n  return sortedAmountsWeWant;\n}\n/**\n * returns the amounts in the keyset sorted by the order specified\n * @param keyset to search in\n * @param order order to sort the amounts in\n * @returns the amounts in the keyset sorted by the order specified\n */\nexport function getKeysetAmounts(keyset, order) {\n  if (order === void 0) {\n    order = 'desc';\n  }\n  if (order == 'desc') {\n    return Object.keys(keyset).map(function (k) {\n      return parseInt(k);\n    }).sort(function (a, b) {\n      return b - a;\n    });\n  }\n  return Object.keys(keyset).map(function (k) {\n    return parseInt(k);\n  }).sort(function (a, b) {\n    return a - b;\n  });\n}\n/**\n * Checks if the provided amount is in the keyset.\n * @param amount amount to check\n * @param keyset to search in\n * @returns true if the amount is in the keyset, false otherwise\n */\nexport function hasCorrespondingKey(amount, keyset) {\n  return amount in keyset;\n}\n/**\n * Converts a bytes array to a number.\n * @param bytes to convert to number\n * @returns  number\n */\nexport function bytesToNumber(bytes) {\n  return hexToNumber(bytesToHex(bytes));\n}\n/**\n * Converts a hex string to a number.\n * @param hex to convert to number\n * @returns number\n */\nexport function hexToNumber(hex) {\n  return BigInt(\"0x\".concat(hex));\n}\n/**\n * Converts a number to a hex string of 64 characters.\n * @param number (bigint) to conver to hex\n * @returns hex string start-padded to 64 characters\n */\nexport function numberToHexPadded64(number) {\n  return number.toString(16).padStart(64, '0');\n}\nfunction isValidHex(str) {\n  return /^[a-f0-9]*$/i.test(str);\n}\n/**\n * Checks wether a proof or a list of proofs contains a non-hex id\n * @param p Proof or list of proofs\n * @returns boolean\n */\nexport function hasNonHexId(p) {\n  if (Array.isArray(p)) {\n    return p.some(function (proof) {\n      return !isValidHex(proof.id);\n    });\n  }\n  return isValidHex(p.id);\n}\n//used for json serialization\nexport function bigIntStringify(_key, value) {\n  return typeof value === 'bigint' ? value.toString() : value;\n}\n/**\n * Helper function to encode a v3 cashu token\n * @param token to encode\n * @returns encoded token\n */\nexport function getEncodedTokenV3(token) {\n  var v3TokenObj = {\n    token: [{\n      mint: token.mint,\n      proofs: token.proofs\n    }]\n  };\n  if (token.unit) {\n    v3TokenObj.unit = token.unit;\n  }\n  if (token.memo) {\n    v3TokenObj.memo = token.memo;\n  }\n  return TOKEN_PREFIX + TOKEN_VERSION + encodeJsonToBase64(v3TokenObj);\n}\n/**\n * Helper function to encode a cashu token (defaults to v4 if keyset id allows it)\n * @param token\n * @param [opts]\n */\nexport function getEncodedToken(token, opts) {\n  var nonHex = hasNonHexId(token.proofs);\n  if (nonHex || (opts === null || opts === void 0 ? void 0 : opts.version) === 3) {\n    if ((opts === null || opts === void 0 ? void 0 : opts.version) === 4) {\n      throw new Error('can not encode to v4 token if proofs contain non-hex keyset id');\n    }\n    return getEncodedTokenV3(token);\n  }\n  return getEncodedTokenV4(token);\n}\nexport function getEncodedTokenV4(token) {\n  // Make sure each DLEQ has its blinding factor\n  token.proofs.forEach(function (p) {\n    if (p.dleq && p.dleq.r == undefined) {\n      throw new Error('Missing blinding factor in included DLEQ proof');\n    }\n  });\n  var nonHex = hasNonHexId(token.proofs);\n  if (nonHex) {\n    throw new Error('can not encode to v4 token if proofs contain non-hex keyset id');\n  }\n  var idMap = {};\n  var mint = token.mint;\n  for (var i = 0; i < token.proofs.length; i++) {\n    var proof = token.proofs[i];\n    if (idMap[proof.id]) {\n      idMap[proof.id].push(proof);\n    } else {\n      idMap[proof.id] = [proof];\n    }\n  }\n  var tokenTemplate = {\n    m: mint,\n    u: token.unit || 'sat',\n    t: Object.keys(idMap).map(function (id) {\n      return {\n        i: hexToBytes(id),\n        p: idMap[id].map(function (p) {\n          var _a;\n          return __assign({\n            a: p.amount,\n            s: p.secret,\n            c: hexToBytes(p.C)\n          }, p.dleq && {\n            d: {\n              e: hexToBytes(p.dleq.e),\n              s: hexToBytes(p.dleq.s),\n              r: hexToBytes((_a = p.dleq.r) !== null && _a !== void 0 ? _a : '00')\n            }\n          });\n        })\n      };\n    })\n  };\n  if (token.memo) {\n    tokenTemplate.d = token.memo;\n  }\n  var encodedData = encodeCBOR(tokenTemplate);\n  var prefix = 'cashu';\n  var version = 'B';\n  var base64Data = encodeUint8toBase64Url(encodedData);\n  return prefix + version + base64Data;\n}\n/**\n * Helper function to decode cashu tokens into object\n * @param token an encoded cashu token (cashuAey...)\n * @returns cashu token object\n */\nexport function getDecodedToken(token) {\n  // remove prefixes\n  var uriPrefixes = ['web+cashu://', 'cashu://', 'cashu:', 'cashu'];\n  uriPrefixes.forEach(function (prefix) {\n    if (!token.startsWith(prefix)) {\n      return;\n    }\n    token = token.slice(prefix.length);\n  });\n  return handleTokens(token);\n}\n/**\n * Helper function to decode different versions of cashu tokens into an object\n * @param token an encoded cashu token (cashuAey...)\n * @returns cashu Token object\n */\nexport function handleTokens(token) {\n  var version = token.slice(0, 1);\n  var encodedToken = token.slice(1);\n  if (version === 'A') {\n    var parsedV3Token = encodeBase64ToJson(encodedToken);\n    if (parsedV3Token.token.length > 1) {\n      throw new Error('Multi entry token are not supported');\n    }\n    var entry = parsedV3Token.token[0];\n    var tokenObj = {\n      mint: entry.mint,\n      proofs: entry.proofs,\n      unit: parsedV3Token.unit || 'sat'\n    };\n    if (parsedV3Token.memo) {\n      tokenObj.memo = parsedV3Token.memo;\n    }\n    return tokenObj;\n  } else if (version === 'B') {\n    var uInt8Token = encodeBase64toUint8(encodedToken);\n    var tokenData = decodeCBOR(uInt8Token);\n    var proofs_1 = [];\n    tokenData.t.forEach(function (t) {\n      return t.p.forEach(function (p) {\n        proofs_1.push(__assign({\n          secret: p.s,\n          C: bytesToHex(p.c),\n          amount: p.a,\n          id: bytesToHex(t.i)\n        }, p.d && {\n          dleq: {\n            r: bytesToHex(p.d.r),\n            s: bytesToHex(p.d.s),\n            e: bytesToHex(p.d.e)\n          }\n        }));\n      });\n    });\n    var decodedToken = {\n      mint: tokenData.m,\n      proofs: proofs_1,\n      unit: tokenData.u || 'sat'\n    };\n    if (tokenData.d) {\n      decodedToken.memo = tokenData.d;\n    }\n    return decodedToken;\n  }\n  throw new Error('Token version is not supported');\n}\n/**\n * Returns the keyset id of a set of keys\n * @param keys keys object to derive keyset id from\n * @returns\n */\nexport function deriveKeysetId(keys) {\n  var pubkeysConcat = Object.entries(keys).sort(function (a, b) {\n    return +a[0] - +b[0];\n  }).map(function (_a) {\n    var pubKey = _a[1];\n    return hexToBytes(pubKey);\n  }).reduce(function (prev, curr) {\n    return mergeUInt8Arrays(prev, curr);\n  }, new Uint8Array());\n  var hash = sha256(pubkeysConcat);\n  var hashHex = Buffer.from(hash).toString('hex').slice(0, 14);\n  return '00' + hashHex;\n}\nexport function mergeUInt8Arrays(a1, a2) {\n  // sum of individual array lengths\n  var mergedArray = new Uint8Array(a1.length + a2.length);\n  mergedArray.set(a1);\n  mergedArray.set(a2, a1.length);\n  return mergedArray;\n}\nexport function sortProofsById(proofs) {\n  return proofs.sort(function (a, b) {\n    return a.id.localeCompare(b.id);\n  });\n}\nexport function isObj(v) {\n  return typeof v === 'object';\n}\nexport function checkResponse(data) {\n  if (!isObj(data)) return;\n  if ('error' in data && data.error) {\n    throw new Error(data.error);\n  }\n  if ('detail' in data && data.detail) {\n    throw new Error(data.detail);\n  }\n}\nexport function joinUrls() {\n  var parts = [];\n  for (var _i = 0; _i < arguments.length; _i++) {\n    parts[_i] = arguments[_i];\n  }\n  return parts.map(function (part) {\n    return part.replace(/(^\\/+|\\/+$)/g, '');\n  }).join('/');\n}\nexport function sanitizeUrl(url) {\n  return url.replace(/\\/$/, '');\n}\nexport function sumProofs(proofs) {\n  return proofs.reduce(function (acc, proof) {\n    return acc + proof.amount;\n  }, 0);\n}\nexport function decodePaymentRequest(paymentRequest) {\n  return PaymentRequest.fromEncodedRequest(paymentRequest);\n}\nvar MessageNode = /** @class */function () {\n  function MessageNode(message) {\n    this._value = message;\n    this._next = null;\n  }\n  Object.defineProperty(MessageNode.prototype, \"value\", {\n    get: function () {\n      return this._value;\n    },\n    set: function (message) {\n      this._value = message;\n    },\n    enumerable: false,\n    configurable: true\n  });\n  Object.defineProperty(MessageNode.prototype, \"next\", {\n    get: function () {\n      return this._next;\n    },\n    set: function (node) {\n      this._next = node;\n    },\n    enumerable: false,\n    configurable: true\n  });\n  return MessageNode;\n}();\nexport { MessageNode };\nvar MessageQueue = /** @class */function () {\n  function MessageQueue() {\n    this._first = null;\n    this._last = null;\n    this._size = 0;\n  }\n  Object.defineProperty(MessageQueue.prototype, \"first\", {\n    get: function () {\n      return this._first;\n    },\n    set: function (messageNode) {\n      this._first = messageNode;\n    },\n    enumerable: false,\n    configurable: true\n  });\n  Object.defineProperty(MessageQueue.prototype, \"last\", {\n    get: function () {\n      return this._last;\n    },\n    set: function (messageNode) {\n      this._last = messageNode;\n    },\n    enumerable: false,\n    configurable: true\n  });\n  Object.defineProperty(MessageQueue.prototype, \"size\", {\n    get: function () {\n      return this._size;\n    },\n    set: function (v) {\n      this._size = v;\n    },\n    enumerable: false,\n    configurable: true\n  });\n  MessageQueue.prototype.enqueue = function (message) {\n    var newNode = new MessageNode(message);\n    if (this._size === 0 || !this._last) {\n      this._first = newNode;\n      this._last = newNode;\n    } else {\n      this._last.next = newNode;\n      this._last = newNode;\n    }\n    this._size++;\n    return true;\n  };\n  MessageQueue.prototype.dequeue = function () {\n    if (this._size === 0 || !this._first) return null;\n    var prev = this._first;\n    this._first = prev.next;\n    prev.next = null;\n    this._size--;\n    return prev.value;\n  };\n  return MessageQueue;\n}();\nexport { MessageQueue };\n/**\n * Removes all traces of DLEQs from a list of proofs\n * @param proofs The list of proofs that dleq should be stripped from\n */\nexport function stripDleq(proofs) {\n  return proofs.map(function (p) {\n    var newP = __assign({}, p);\n    delete newP['dleq'];\n    delete newP['dleqValid'];\n    return newP;\n  });\n}\n/**\n * Checks that the proof has a valid DLEQ proof according to\n * keyset `keys`\n * @param proof The proof subject to verification\n * @param keyset The Mint's keyset to be used for verification\n * @returns true if verification succeeded, false otherwise\n * @throws Error if @param proof does not match any key in @param keyset\n */\nexport function hasValidDleq(proof, keyset) {\n  var _a;\n  if (proof.dleq == undefined) {\n    return false;\n  }\n  var dleq = {\n    e: hexToBytes(proof.dleq.e),\n    s: hexToBytes(proof.dleq.s),\n    r: hexToNumber((_a = proof.dleq.r) !== null && _a !== void 0 ? _a : '00')\n  };\n  if (!hasCorrespondingKey(proof.amount, keyset.keys)) {\n    throw new Error(\"undefined key for amount \".concat(proof.amount));\n  }\n  var key = keyset.keys[proof.amount];\n  if (!verifyDLEQProof_reblind(new TextEncoder().encode(proof.secret), dleq, pointFromHex(proof.C), pointFromHex(key))) {\n    return false;\n  }\n  return true;\n}\n//# sourceMappingURL=utils.js.map","map":null,"metadata":{},"sourceType":"module","externalDependencies":[]}