@gearbox-protocol/sdk 13.0.0-beta.3 → 13.0.0-beta.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (106) hide show
  1. package/dist/cjs/abi/iPriceFeed.js +84 -0
  2. package/dist/cjs/common-utils/index.js +22 -0
  3. package/dist/cjs/common-utils/package.json +1 -0
  4. package/dist/cjs/{sdk → common-utils}/utils/assetsMath.js +88 -21
  5. package/dist/cjs/common-utils/utils/bigintMath.js +65 -0
  6. package/dist/cjs/common-utils/utils/creditAccount/calcHealthFactor.js +76 -0
  7. package/dist/cjs/common-utils/utils/creditAccount/calcOverallAPY.js +81 -0
  8. package/dist/cjs/{sdk/utils/priceMath.js → common-utils/utils/creditAccount/calcQuotaBorrowRate.js} +19 -12
  9. package/dist/cjs/{sdk/utils/bigintMath.js → common-utils/utils/creditAccount/calcRelativeBaseBorrowRate.js} +11 -10
  10. package/dist/cjs/common-utils/utils/creditAccount/debt.js +64 -0
  11. package/dist/cjs/common-utils/utils/creditAccount/getTimeToLiquidation.js +38 -0
  12. package/dist/cjs/common-utils/utils/creditAccount/index.js +38 -0
  13. package/dist/cjs/common-utils/utils/creditAccount/liquidationPrice.js +47 -0
  14. package/dist/cjs/common-utils/utils/creditAccount/quotaUtils.js +149 -0
  15. package/dist/cjs/common-utils/utils/creditAccount/sort.js +95 -0
  16. package/dist/cjs/common-utils/utils/creditAccount/types.js +16 -0
  17. package/dist/cjs/{sdk → common-utils}/utils/endpoints.js +11 -17
  18. package/dist/cjs/common-utils/utils/index.js +30 -0
  19. package/dist/cjs/common-utils/utils/priceMath.js +66 -0
  20. package/dist/cjs/permissionless/bindings/cross-chain-multisig.js +3 -3
  21. package/dist/cjs/permissionless/bindings/instance-manager.js +2 -2
  22. package/dist/cjs/plugins/adapters/contracts/MellowDepositQueueAdapterContract.js +0 -6
  23. package/dist/cjs/plugins/adapters/contracts/MellowRedeemQueueAdapterContract.js +0 -6
  24. package/dist/cjs/sdk/GearboxSDK.js +0 -2
  25. package/dist/cjs/sdk/base/BaseContract.js +5 -2
  26. package/dist/cjs/sdk/base/ChainContractsRegister.js +2 -10
  27. package/dist/cjs/sdk/base/Construct.js +25 -19
  28. package/dist/cjs/sdk/base/SDKConstruct.js +1 -1
  29. package/dist/cjs/sdk/market/adapters/PlaceholderAdapterContracts.js +16 -0
  30. package/dist/cjs/sdk/market/pricefeeds/updates/PriceUpdatesCache.js +0 -17
  31. package/dist/cjs/sdk/market/pricefeeds/updates/PythUpdater.js +1 -1
  32. package/dist/cjs/sdk/market/pricefeeds/updates/RedstoneUpdater.js +1 -1
  33. package/dist/cjs/sdk/market/pricefeeds/updates/fetchPythPayloads.js +2 -2
  34. package/dist/cjs/sdk/utils/formatter.js +3 -3
  35. package/dist/cjs/sdk/utils/index.js +0 -10
  36. package/dist/esm/abi/iPriceFeed.js +60 -0
  37. package/dist/esm/common-utils/index.js +1 -0
  38. package/dist/esm/common-utils/package.json +1 -0
  39. package/dist/esm/{sdk → common-utils}/utils/assetsMath.js +80 -13
  40. package/dist/esm/common-utils/utils/bigintMath.js +41 -0
  41. package/dist/esm/common-utils/utils/creditAccount/calcHealthFactor.js +55 -0
  42. package/dist/esm/common-utils/utils/creditAccount/calcOverallAPY.js +60 -0
  43. package/dist/esm/common-utils/utils/creditAccount/calcQuotaBorrowRate.js +18 -0
  44. package/dist/esm/common-utils/utils/creditAccount/calcRelativeBaseBorrowRate.js +10 -0
  45. package/dist/esm/common-utils/utils/creditAccount/debt.js +43 -0
  46. package/dist/esm/common-utils/utils/creditAccount/getTimeToLiquidation.js +18 -0
  47. package/dist/esm/common-utils/utils/creditAccount/index.js +9 -0
  48. package/dist/esm/common-utils/utils/creditAccount/liquidationPrice.js +23 -0
  49. package/dist/esm/common-utils/utils/creditAccount/quotaUtils.js +125 -0
  50. package/dist/esm/common-utils/utils/creditAccount/sort.js +67 -0
  51. package/dist/esm/common-utils/utils/creditAccount/types.js +0 -0
  52. package/dist/esm/{sdk → common-utils}/utils/endpoints.js +9 -14
  53. package/dist/esm/common-utils/utils/index.js +5 -0
  54. package/dist/esm/common-utils/utils/priceMath.js +42 -0
  55. package/dist/esm/permissionless/bindings/cross-chain-multisig.js +3 -3
  56. package/dist/esm/permissionless/bindings/instance-manager.js +2 -2
  57. package/dist/esm/plugins/adapters/contracts/MellowDepositQueueAdapterContract.js +0 -6
  58. package/dist/esm/plugins/adapters/contracts/MellowRedeemQueueAdapterContract.js +0 -6
  59. package/dist/esm/sdk/GearboxSDK.js +0 -2
  60. package/dist/esm/sdk/base/BaseContract.js +5 -2
  61. package/dist/esm/sdk/base/ChainContractsRegister.js +2 -10
  62. package/dist/esm/sdk/base/Construct.js +25 -19
  63. package/dist/esm/sdk/base/SDKConstruct.js +1 -1
  64. package/dist/esm/sdk/market/adapters/PlaceholderAdapterContracts.js +16 -0
  65. package/dist/esm/sdk/market/pricefeeds/updates/PriceUpdatesCache.js +0 -17
  66. package/dist/esm/sdk/market/pricefeeds/updates/PythUpdater.js +1 -1
  67. package/dist/esm/sdk/market/pricefeeds/updates/RedstoneUpdater.js +1 -1
  68. package/dist/esm/sdk/market/pricefeeds/updates/fetchPythPayloads.js +2 -2
  69. package/dist/esm/sdk/utils/formatter.js +1 -1
  70. package/dist/esm/sdk/utils/index.js +0 -5
  71. package/dist/types/abi/iPriceFeed.d.ts +87 -0
  72. package/dist/types/common-utils/index.d.ts +1 -0
  73. package/dist/types/common-utils/utils/assetsMath.d.ts +114 -0
  74. package/dist/types/common-utils/utils/bigintMath.d.ts +43 -0
  75. package/dist/types/common-utils/utils/creditAccount/calcHealthFactor.d.ts +25 -0
  76. package/dist/types/common-utils/utils/creditAccount/calcOverallAPY.d.ts +37 -0
  77. package/dist/types/common-utils/utils/creditAccount/calcQuotaBorrowRate.d.ts +18 -0
  78. package/dist/types/common-utils/utils/creditAccount/calcRelativeBaseBorrowRate.d.ts +15 -0
  79. package/dist/types/common-utils/utils/creditAccount/debt.d.ts +35 -0
  80. package/dist/types/common-utils/utils/creditAccount/getTimeToLiquidation.d.ts +16 -0
  81. package/dist/types/common-utils/utils/creditAccount/index.d.ts +9 -0
  82. package/dist/types/common-utils/utils/creditAccount/liquidationPrice.d.ts +25 -0
  83. package/dist/types/common-utils/utils/creditAccount/quotaUtils.d.ts +81 -0
  84. package/dist/types/common-utils/utils/creditAccount/sort.d.ts +55 -0
  85. package/dist/types/common-utils/utils/creditAccount/types.d.ts +18 -0
  86. package/dist/types/{sdk → common-utils}/utils/endpoints.d.ts +13 -5
  87. package/dist/types/common-utils/utils/index.d.ts +5 -0
  88. package/dist/types/common-utils/utils/priceMath.d.ts +47 -0
  89. package/dist/types/permissionless/bindings/cross-chain-multisig.d.ts +3 -3
  90. package/dist/types/permissionless/bindings/instance-manager.d.ts +3 -3
  91. package/dist/types/plugins/adapters/contracts/MellowDepositQueueAdapterContract.d.ts +1 -4
  92. package/dist/types/plugins/adapters/contracts/MellowRedeemQueueAdapterContract.d.ts +1 -4
  93. package/dist/types/sdk/base/ChainContractsRegister.d.ts +0 -2
  94. package/dist/types/sdk/base/Construct.d.ts +7 -10
  95. package/dist/types/sdk/market/adapters/PlaceholderAdapterContracts.d.ts +2 -1
  96. package/dist/types/sdk/market/pricefeeds/updates/PriceUpdatesCache.d.ts +1 -8
  97. package/dist/types/sdk/utils/index.d.ts +0 -5
  98. package/package.json +11 -2
  99. package/dist/cjs/sdk/utils/creditAccount.js +0 -409
  100. package/dist/esm/sdk/utils/bigintMath.js +0 -9
  101. package/dist/esm/sdk/utils/creditAccount.js +0 -396
  102. package/dist/esm/sdk/utils/priceMath.js +0 -11
  103. package/dist/types/sdk/utils/assetsMath.d.ts +0 -42
  104. package/dist/types/sdk/utils/bigintMath.d.ts +0 -6
  105. package/dist/types/sdk/utils/creditAccount.d.ts +0 -128
  106. package/dist/types/sdk/utils/priceMath.d.ts +0 -9
@@ -26,27 +26,41 @@ var import_ChainContractsRegister = require("./ChainContractsRegister.js");
26
26
  class Construct {
27
27
  logger;
28
28
  client;
29
- register;
29
+ #register;
30
30
  /**
31
31
  * Indicates that contract state needs to be updated
32
32
  */
33
33
  #dirty = false;
34
34
  constructor(options) {
35
- const { logger } = options;
36
- if ("client" in options) {
37
- const { client } = options;
38
- this.client = client;
39
- this.register = import_ChainContractsRegister.ChainContractsRegister.for(client, logger);
35
+ if (options instanceof import_ChainContractsRegister.ChainContractsRegister) {
36
+ this.#register = options;
37
+ this.client = options.client;
38
+ } else if ("register" in options) {
39
+ this.#register = options.register;
40
+ this.client = options.register.client;
40
41
  } else {
41
- const { register } = options;
42
- this.register = register;
43
- this.client = register.client;
42
+ this.client = options.client;
44
43
  }
45
44
  this.logger = (0, import_utils.childLogger)(
46
45
  this.constructor.name,
47
- this.register.logger ?? logger
46
+ this.#register?.logger ?? options.logger
48
47
  );
49
48
  }
49
+ /**
50
+ * Throws if register was not provided in constructor options
51
+ * Ephemeral contracts that do not need to access other contracts may not need it
52
+ */
53
+ get register() {
54
+ if (!this.#register) {
55
+ throw new Error(
56
+ "contracts register not available, it must be provided if contract needs to access other contracts"
57
+ );
58
+ }
59
+ return this.#register;
60
+ }
61
+ safeGetRegister() {
62
+ return this.#register;
63
+ }
50
64
  get chain() {
51
65
  return this.client.chain;
52
66
  }
@@ -68,19 +82,11 @@ class Construct {
68
82
  set dirty(value) {
69
83
  this.#dirty = value;
70
84
  }
71
- /**
72
- * Syntax sugar for rgister.tokensMeta
73
- */
74
85
  get tokensMeta() {
75
86
  return this.register.tokensMeta;
76
87
  }
77
- /**
78
- * Syntax suggar for getting contract labels
79
- * @param address
80
- * @returns
81
- */
82
88
  labelAddress(address, omitAddress) {
83
- return this.register.labelAddress(address, omitAddress);
89
+ return this.#register?.labelAddress(address, omitAddress) ?? address;
84
90
  }
85
91
  /**
86
92
  * Returns list of addresses that should be watched for events to sync state
@@ -25,7 +25,7 @@ var import_Construct = require("./Construct.js");
25
25
  class SDKConstruct extends import_Construct.Construct {
26
26
  sdk;
27
27
  constructor(sdk) {
28
- super(sdk);
28
+ super({ register: sdk });
29
29
  this.sdk = sdk;
30
30
  }
31
31
  }
@@ -21,11 +21,21 @@ __export(PlaceholderAdapterContracts_exports, {
21
21
  PlaceholderAdapterContract: () => PlaceholderAdapterContract
22
22
  });
23
23
  module.exports = __toCommonJS(PlaceholderAdapterContracts_exports);
24
+ var import_viem = require("viem");
24
25
  var import_base = require("../../base/index.js");
25
26
  class PlaceholderAdapterContract extends import_base.PlaceholderContract {
26
27
  #targetContract;
28
+ #creditManager;
27
29
  constructor(options, args) {
28
30
  super(options, args.baseParams);
31
+ if (args.baseParams.serializedParams) {
32
+ const [cm, tc] = (0, import_viem.decodeAbiParameters)(
33
+ [{ type: "address" }, { type: "address" }],
34
+ args.baseParams.serializedParams
35
+ );
36
+ this.#creditManager = cm;
37
+ this.#targetContract = tc;
38
+ }
29
39
  }
30
40
  get targetContract() {
31
41
  if (!this.#targetContract) {
@@ -33,6 +43,12 @@ class PlaceholderAdapterContract extends import_base.PlaceholderContract {
33
43
  }
34
44
  return this.#targetContract;
35
45
  }
46
+ get creditManager() {
47
+ if (!this.#creditManager) {
48
+ throw new import_base.MissingSerializedParamsError("creditManager");
49
+ }
50
+ return this.#creditManager;
51
+ }
36
52
  }
37
53
  // Annotate the CommonJS export names for ESM import in node:
38
54
  0 && (module.exports = {
@@ -22,23 +22,6 @@ __export(PriceUpdatesCache_exports, {
22
22
  });
23
23
  module.exports = __toCommonJS(PriceUpdatesCache_exports);
24
24
  class PriceUpdatesCache {
25
- static #caches = /* @__PURE__ */ new Map();
26
- /**
27
- * Price update caches can be shared across networks
28
- * @param id - unique key to identify the cache
29
- * @param opts
30
- * @returns
31
- */
32
- static get(id, opts) {
33
- const key = `${id}:${opts.historical ? "historical" : "latest"}:${opts.ttl}`;
34
- const cache = PriceUpdatesCache.#caches.get(key);
35
- if (cache) {
36
- return cache;
37
- }
38
- const newCache = new PriceUpdatesCache(opts);
39
- PriceUpdatesCache.#caches.set(key, newCache);
40
- return newCache;
41
- }
42
25
  #cache = /* @__PURE__ */ new Map();
43
26
  #ttlMs;
44
27
  #historical;
@@ -68,7 +68,7 @@ class PythUpdater extends import_base.SDKConstruct {
68
68
  `using historical timestamp ${this.#historicalTimestamp}`
69
69
  );
70
70
  }
71
- this.#cache = import_PriceUpdatesCache.PriceUpdatesCache.get("pyth", {
71
+ this.#cache = new import_PriceUpdatesCache.PriceUpdatesCache({
72
72
  // currently staleness period is 240 seconds on all networks, add some buffer
73
73
  // this period of 4 minutes is selected based on time that is required for user to sign transaction with wallet
74
74
  // so it's unlikely to decrease
@@ -76,7 +76,7 @@ class RedstoneUpdater extends import_base.SDKConstruct {
76
76
  `using historical timestamp ${this.#historicalTimestampMs}`
77
77
  );
78
78
  }
79
- this.#cache = import_PriceUpdatesCache.PriceUpdatesCache.get("redstone", {
79
+ this.#cache = new import_PriceUpdatesCache.PriceUpdatesCache({
80
80
  // currently staleness period is 240 seconds on all networks, add some buffer
81
81
  // this period of 4 minutes is selected based on time that is required for user to sign transaction with wallet
82
82
  // so it's unlikely to decrease
@@ -35,7 +35,7 @@ async function fetchPythPayloads(options) {
35
35
  customFetch = fetch,
36
36
  returnPrices
37
37
  } = options;
38
- const ids = Array.from(new Set(dataFeedsIds));
38
+ const ids = Array.from(new Set(dataFeedsIds)).sort();
39
39
  if (ids.length === 0) {
40
40
  return [];
41
41
  }
@@ -46,7 +46,7 @@ async function fetchPythPayloads(options) {
46
46
  if (ignoreMissingFeeds) {
47
47
  url.searchParams.append("ignore_invalid_price_ids", "true");
48
48
  }
49
- for (const id of dataFeedsIds) {
49
+ for (const id of ids) {
50
50
  url.searchParams.append("ids[]", id);
51
51
  }
52
52
  const resp = await (0, import_utils.retry)(
@@ -48,7 +48,7 @@ __export(formatter_exports, {
48
48
  module.exports = __toCommonJS(formatter_exports);
49
49
  var import_date_fns = require("date-fns");
50
50
  var import_decimal = __toESM(require("decimal.js-light"));
51
- var import__ = require("../index.js");
51
+ var import_constants = require("../constants/index.js");
52
52
  const toBigInt = (v) => {
53
53
  const value = typeof v === "object" && v.type === "BigNumber" ? v.hex : v.toString();
54
54
  return BigInt(value);
@@ -170,10 +170,10 @@ function shortHash(address) {
170
170
  return address === void 0 ? "" : `${address.slice(0, 5)}...`;
171
171
  }
172
172
  function formatPercentage(healthFactor, decimals = 2) {
173
- return (healthFactor / Number(import__.PERCENTAGE_FACTOR)).toFixed(decimals);
173
+ return (healthFactor / Number(import_constants.PERCENTAGE_FACTOR)).toFixed(decimals);
174
174
  }
175
175
  function formatLeverage(leverage, decimals = 2) {
176
- return (leverage / Number(import__.LEVERAGE_DECIMALS)).toFixed(decimals);
176
+ return (leverage / Number(import_constants.LEVERAGE_DECIMALS)).toFixed(decimals);
177
177
  }
178
178
  // Annotate the CommonJS export names for ESM import in node:
179
179
  0 && (module.exports = {
@@ -18,13 +18,9 @@ module.exports = __toCommonJS(utils_exports);
18
18
  __reExport(utils_exports, require("./AddressMap.js"), module.exports);
19
19
  __reExport(utils_exports, require("./AddressSet.js"), module.exports);
20
20
  __reExport(utils_exports, require("./abi-decode.js"), module.exports);
21
- __reExport(utils_exports, require("./assetsMath.js"), module.exports);
22
- __reExport(utils_exports, require("./bigintMath.js"), module.exports);
23
21
  __reExport(utils_exports, require("./bytes32ToString.js"), module.exports);
24
22
  __reExport(utils_exports, require("./childLogger.js"), module.exports);
25
23
  __reExport(utils_exports, require("./createRawTx.js"), module.exports);
26
- __reExport(utils_exports, require("./creditAccount.js"), module.exports);
27
- __reExport(utils_exports, require("./endpoints.js"), module.exports);
28
24
  __reExport(utils_exports, require("./etherscan.js"), module.exports);
29
25
  __reExport(utils_exports, require("./filterDust.js"), module.exports);
30
26
  __reExport(utils_exports, require("./formatter.js"), module.exports);
@@ -32,7 +28,6 @@ __reExport(utils_exports, require("./hex.js"), module.exports);
32
28
  __reExport(utils_exports, require("./isDust.js"), module.exports);
33
29
  __reExport(utils_exports, require("./json.js"), module.exports);
34
30
  __reExport(utils_exports, require("./mappers.js"), module.exports);
35
- __reExport(utils_exports, require("./priceMath.js"), module.exports);
36
31
  __reExport(utils_exports, require("./retry.js"), module.exports);
37
32
  __reExport(utils_exports, require("./toAddress.js"), module.exports);
38
33
  __reExport(utils_exports, require("./type-utils.js"), module.exports);
@@ -42,13 +37,9 @@ __reExport(utils_exports, require("./zod.js"), module.exports);
42
37
  ...require("./AddressMap.js"),
43
38
  ...require("./AddressSet.js"),
44
39
  ...require("./abi-decode.js"),
45
- ...require("./assetsMath.js"),
46
- ...require("./bigintMath.js"),
47
40
  ...require("./bytes32ToString.js"),
48
41
  ...require("./childLogger.js"),
49
42
  ...require("./createRawTx.js"),
50
- ...require("./creditAccount.js"),
51
- ...require("./endpoints.js"),
52
43
  ...require("./etherscan.js"),
53
44
  ...require("./filterDust.js"),
54
45
  ...require("./formatter.js"),
@@ -56,7 +47,6 @@ __reExport(utils_exports, require("./zod.js"), module.exports);
56
47
  ...require("./isDust.js"),
57
48
  ...require("./json.js"),
58
49
  ...require("./mappers.js"),
59
- ...require("./priceMath.js"),
60
50
  ...require("./retry.js"),
61
51
  ...require("./toAddress.js"),
62
52
  ...require("./type-utils.js"),
@@ -0,0 +1,60 @@
1
+ const iPriceFeedAbi = [
2
+ {
3
+ type: "function",
4
+ name: "contractType",
5
+ inputs: [],
6
+ outputs: [{ name: "", type: "bytes32", internalType: "bytes32" }],
7
+ stateMutability: "view"
8
+ },
9
+ {
10
+ type: "function",
11
+ name: "decimals",
12
+ inputs: [],
13
+ outputs: [{ name: "", type: "uint8", internalType: "uint8" }],
14
+ stateMutability: "view"
15
+ },
16
+ {
17
+ type: "function",
18
+ name: "description",
19
+ inputs: [],
20
+ outputs: [{ name: "", type: "string", internalType: "string" }],
21
+ stateMutability: "view"
22
+ },
23
+ {
24
+ type: "function",
25
+ name: "latestRoundData",
26
+ inputs: [],
27
+ outputs: [
28
+ { name: "", type: "uint80", internalType: "uint80" },
29
+ { name: "answer", type: "int256", internalType: "int256" },
30
+ { name: "", type: "uint256", internalType: "uint256" },
31
+ { name: "updatedAt", type: "uint256", internalType: "uint256" },
32
+ { name: "", type: "uint80", internalType: "uint80" }
33
+ ],
34
+ stateMutability: "view"
35
+ },
36
+ {
37
+ type: "function",
38
+ name: "serialize",
39
+ inputs: [],
40
+ outputs: [{ name: "serializedData", type: "bytes", internalType: "bytes" }],
41
+ stateMutability: "view"
42
+ },
43
+ {
44
+ type: "function",
45
+ name: "skipPriceCheck",
46
+ inputs: [],
47
+ outputs: [{ name: "", type: "bool", internalType: "bool" }],
48
+ stateMutability: "view"
49
+ },
50
+ {
51
+ type: "function",
52
+ name: "version",
53
+ inputs: [],
54
+ outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
55
+ stateMutability: "view"
56
+ }
57
+ ];
58
+ export {
59
+ iPriceFeedAbi
60
+ };
@@ -0,0 +1 @@
1
+ export * from "./utils/index.js";
@@ -0,0 +1 @@
1
+ {"type": "module","sideEffects":false}
@@ -1,6 +1,22 @@
1
- import { BigIntMath, PriceUtils } from "../index.js";
2
- import { CreditAccountDataUtils } from "./creditAccount.js";
1
+ import { BigIntMath } from "./bigintMath.js";
2
+ import { sortBalances } from "./creditAccount/sort.js";
3
+ import { PriceUtils } from "./priceMath.js";
3
4
  class AssetUtils {
5
+ constructor() {
6
+ }
7
+ /**
8
+ * Selects the next candidate token to add to a selected-asset list.
9
+ *
10
+ * Flow:
11
+ * 1) Removes tokens already present in `selectedAssets`
12
+ * 2) Builds balances for the remaining allowed tokens
13
+ * 3) Sorts the balances using `CreditAccountDataUtils.sortBalances`
14
+ * 4) Returns the highest-priority token address, if any
15
+ *
16
+ * Addresses are normalized to lowercase for matching.
17
+ *
18
+ * @returns The next token address to select, or `undefined` if no candidates remain.
19
+ */
4
20
  static nextAsset({
5
21
  allowedTokens,
6
22
  selectedAssets,
@@ -19,7 +35,7 @@ class AssetUtils {
19
35
  const alreadySelected = selectedRecord[allowedToken.toLowerCase()];
20
36
  return !alreadySelected;
21
37
  });
22
- const sorted = CreditAccountDataUtils.sortBalances(
38
+ const sorted = sortBalances(
23
39
  AssetUtils.getBalances(notSelected, balances),
24
40
  prices,
25
41
  tokensList
@@ -27,15 +43,30 @@ class AssetUtils {
27
43
  const [address] = sorted[0] || [];
28
44
  return address;
29
45
  }
46
+ /**
47
+ * Builds a normalized balance record for a specific token subset.
48
+ *
49
+ * Missing balances are defaulted to `0n`.
50
+ *
51
+ * @param allowedTokens Tokens to include in the output record.
52
+ * @param externalBalances Source balances keyed by lowercase address.
53
+ * @returns A record that contains only `allowedTokens`.
54
+ */
30
55
  static getBalances(allowedTokens, externalBalances) {
31
56
  return allowedTokens.reduce((acc, address) => {
32
57
  const addressLc = address.toLowerCase();
33
- return {
34
- ...acc,
35
- [addressLc]: externalBalances[addressLc] || 0n
36
- };
58
+ acc[addressLc] = externalBalances[addressLc] || 0n;
59
+ return acc;
37
60
  }, {});
38
61
  }
62
+ /**
63
+ * Converts an asset array into a token-address keyed record.
64
+ *
65
+ * If duplicate token addresses are present, the last occurrence wins.
66
+ *
67
+ * @param a Source asset list.
68
+ * @returns Record keyed by `asset.token`.
69
+ */
39
70
  static constructAssetRecord(a) {
40
71
  const record = a.reduce((acc, asset) => {
41
72
  acc[asset.token] = asset;
@@ -43,6 +74,18 @@ class AssetUtils {
43
74
  }, {});
44
75
  return record;
45
76
  }
77
+ /**
78
+ * Creates a reusable wrapper function that merges "unwrapped" and "wrapped"
79
+ * token balances into the wrapped token representation.
80
+ *
81
+ * The returned function:
82
+ * - converts non-negative unwrapped balance into wrapped units by price
83
+ * - adds the converted amount to the wrapped token balance
84
+ * - removes the unwrapped token from the result list
85
+ * - leaves input untouched when no unwrapped token is present
86
+ *
87
+ * @returns A function producing `[assets, convertedUnwrapped, originalWrapped]`.
88
+ */
46
89
  static memoWrap = (unwrappedAddress, wrappedAddress, prices, tokensList) => function wrap(assets) {
47
90
  const assetsRecord = AssetUtils.constructAssetRecord(assets);
48
91
  const unwrapped = assetsRecord[unwrappedAddress];
@@ -75,8 +118,16 @@ class AssetUtils {
75
118
  return [Object.values(assetsRecord), 0n, wrappedAmount];
76
119
  };
77
120
  /**
78
- * Sums the the second assets list into the first assets list
79
- * Balances cant be negative; creates new assets.
121
+ * Adds balances from the second asset list into the first list.
122
+ *
123
+ * Behavior:
124
+ * - balances are clamped to non-negative before summation
125
+ * - tokens found only in `b` are created in the output
126
+ * - existing asset metadata is preserved from `a` when possible
127
+ *
128
+ * @param a Base asset list.
129
+ * @param b Asset deltas to add.
130
+ * @returns A merged list containing assets from both inputs.
80
131
  */
81
132
  static sumAssets(a, b) {
82
133
  const aRecord = AssetUtils.constructAssetRecord(a);
@@ -94,8 +145,16 @@ class AssetUtils {
94
145
  return Object.values(resRecord);
95
146
  }
96
147
  /**
97
- * Sums the the second assets list into the first assets list
98
- * Balances cant be negative; doesn't create new assets.
148
+ * Adds balances from the second list to matching assets in the first list.
149
+ *
150
+ * Behavior:
151
+ * - balances are clamped to non-negative before summation
152
+ * - only assets already present in `a` are returned
153
+ * - no new token entries are created
154
+ *
155
+ * @param a Base asset list.
156
+ * @param b Asset deltas keyed by token.
157
+ * @returns Updated version of `a` with adjusted balances.
99
158
  */
100
159
  static addBalances(a, b) {
101
160
  const bRecord = AssetUtils.constructAssetRecord(b);
@@ -107,8 +166,16 @@ class AssetUtils {
107
166
  });
108
167
  }
109
168
  /**
110
- * Subtracts the the second assets list from the first assets list
111
- * Balances cant be negative; doesn't create new assets.
169
+ * Subtracts balances in the second list from matching assets in the first list.
170
+ *
171
+ * Behavior:
172
+ * - both operands are clamped to non-negative before subtraction
173
+ * - output balances are clamped to non-negative after subtraction
174
+ * - only assets already present in `a` are returned
175
+ *
176
+ * @param a Base asset list.
177
+ * @param b Asset amounts to subtract by token.
178
+ * @returns Updated `a` list with non-negative post-subtraction balances.
112
179
  */
113
180
  static subAssets(a, b) {
114
181
  const bRecord = AssetUtils.constructAssetRecord(b);
@@ -0,0 +1,41 @@
1
+ class BigIntMath {
2
+ constructor() {
3
+ }
4
+ /**
5
+ * Returns the absolute (non-negative) value of a bigint.
6
+ *
7
+ * @param x Input value.
8
+ * @returns `x` when `x` is already non-negative, otherwise `-x`.
9
+ */
10
+ static abs = (x) => x < 0n ? -x : x;
11
+ /**
12
+ * Returns the greater of two bigint values.
13
+ *
14
+ * @param a First candidate value.
15
+ * @param b Second candidate value.
16
+ * @returns The larger value between `a` and `b`.
17
+ */
18
+ static max = (a, b) => a > b ? a : b;
19
+ /**
20
+ * Returns the smaller of two bigint values.
21
+ *
22
+ * @param a First candidate value.
23
+ * @param b Second candidate value.
24
+ * @returns The smaller value between `a` and `b`.
25
+ */
26
+ static min = (a, b) => a < b ? a : b;
27
+ /**
28
+ * Returns the negative form of a bigint if it is currently positive.
29
+ *
30
+ * Useful when a value should be represented as an outflow/debit:
31
+ * - positive values become negative
32
+ * - zero and negative values are returned unchanged
33
+ *
34
+ * @param a Input value.
35
+ * @returns A non-positive bigint representation of `a`.
36
+ */
37
+ static neg = (a) => a > 0 ? a * -1n : a;
38
+ }
39
+ export {
40
+ BigIntMath
41
+ };
@@ -0,0 +1,55 @@
1
+ import {
2
+ PERCENTAGE_FACTOR,
3
+ PRICE_DECIMALS
4
+ } from "../../../sdk/index.js";
5
+ import { BigIntMath } from "../bigintMath.js";
6
+ import { PriceUtils } from "../priceMath.js";
7
+ const MAX_UINT16 = 65535;
8
+ function calcHealthFactor({
9
+ assets,
10
+ quotas,
11
+ quotasInfo,
12
+ liquidationThresholds,
13
+ underlyingToken,
14
+ debt,
15
+ prices,
16
+ tokensList
17
+ }) {
18
+ if (debt === 0n) return MAX_UINT16;
19
+ const underlyingDecimals = tokensList[underlyingToken]?.decimals || 18;
20
+ const underlyingPrice = prices[underlyingToken] || 0n;
21
+ const assetMoney = assets.reduce(
22
+ (acc, { token: tokenAddress, balance: amount }) => {
23
+ const tokenDecimals = tokensList[tokenAddress]?.decimals || 18;
24
+ const lt = liquidationThresholds[tokenAddress] || 0n;
25
+ const price = prices[tokenAddress] || 0n;
26
+ const tokenMoney = PriceUtils.calcTotalPrice(
27
+ price,
28
+ amount,
29
+ tokenDecimals
30
+ );
31
+ const tokenLtMoney = tokenMoney * lt / PERCENTAGE_FACTOR;
32
+ const { isActive = false } = quotasInfo?.[tokenAddress] || {};
33
+ const quota = quotas[tokenAddress];
34
+ const quotaBalance = isActive ? quota?.balance || 0n : 0n;
35
+ const quotaMoney = PriceUtils.calcTotalPrice(
36
+ underlyingPrice,
37
+ quotaBalance,
38
+ underlyingDecimals
39
+ );
40
+ const money = quota ? BigIntMath.min(quotaMoney, tokenLtMoney) : tokenLtMoney;
41
+ return acc + money;
42
+ },
43
+ 0n
44
+ );
45
+ const borrowedMoney = PriceUtils.calcTotalPrice(
46
+ underlyingPrice || PRICE_DECIMALS,
47
+ debt,
48
+ underlyingDecimals
49
+ );
50
+ const hfInPercent = borrowedMoney > 0n ? assetMoney * PERCENTAGE_FACTOR / borrowedMoney : 0n;
51
+ return Number(hfInPercent);
52
+ }
53
+ export {
54
+ calcHealthFactor
55
+ };
@@ -0,0 +1,60 @@
1
+ import {
2
+ PERCENTAGE_FACTOR,
3
+ PRICE_DECIMALS
4
+ } from "../../../sdk/index.js";
5
+ import { PriceUtils } from "../priceMath.js";
6
+ function calcOverallAPY({
7
+ caAssets,
8
+ lpAPY,
9
+ prices,
10
+ quotas,
11
+ quotaRates,
12
+ feeInterest,
13
+ totalValue,
14
+ debt,
15
+ baseRateWithFee,
16
+ underlyingToken,
17
+ tokensList
18
+ }) {
19
+ if (!lpAPY || !totalValue || totalValue <= 0n || !debt || totalValue <= debt)
20
+ return void 0;
21
+ const underlyingTokenDecimals = tokensList[underlyingToken]?.decimals || 18;
22
+ const underlyingPrice = prices[underlyingToken];
23
+ const assetAPYMoney = caAssets.reduce(
24
+ (acc, { token: tokenAddress, balance: amount }) => {
25
+ const apy = lpAPY[tokenAddress] || 0;
26
+ const tokenDecimals = tokensList[tokenAddress]?.decimals || 18;
27
+ const price = prices[tokenAddress] || 0n;
28
+ const money = PriceUtils.calcTotalPrice(price, amount, tokenDecimals);
29
+ const apyMoney = money * BigInt(apy);
30
+ const { rate: quotaAPY = 0n, isActive = false } = quotaRates?.[tokenAddress] || {};
31
+ const { balance: quotaBalance = 0n } = quotas[tokenAddress] || {};
32
+ const quotaAmount = isActive ? quotaBalance : 0n;
33
+ const quotaMoney = PriceUtils.calcTotalPrice(
34
+ underlyingPrice || 0n,
35
+ quotaAmount,
36
+ underlyingTokenDecimals
37
+ );
38
+ const quotaRate = quotaAPY * (BigInt(feeInterest) + PERCENTAGE_FACTOR) / PERCENTAGE_FACTOR;
39
+ const quotaAPYMoney = quotaMoney * quotaRate;
40
+ return acc + apyMoney - quotaAPYMoney;
41
+ },
42
+ 0n
43
+ );
44
+ const debtMoney = PriceUtils.calcTotalPrice(
45
+ underlyingPrice || 0n,
46
+ debt,
47
+ underlyingTokenDecimals
48
+ );
49
+ const debtAPYMoney = debtMoney * BigInt(baseRateWithFee);
50
+ const yourAssetsMoney = PriceUtils.calcTotalPrice(
51
+ underlyingPrice || PRICE_DECIMALS,
52
+ totalValue - debt,
53
+ underlyingTokenDecimals
54
+ );
55
+ const apyInPercent = (assetAPYMoney - debtAPYMoney) / yourAssetsMoney;
56
+ return apyInPercent;
57
+ }
58
+ export {
59
+ calcOverallAPY
60
+ };
@@ -0,0 +1,18 @@
1
+ function calcQuotaBorrowRate({
2
+ quotas,
3
+ quotaRates
4
+ }) {
5
+ const totalRateBalance = Object.values(quotas).reduce(
6
+ (acc, { token, balance }) => {
7
+ const { rate = 0, isActive = false } = quotaRates?.[token] || {};
8
+ const quotaBalance = isActive ? balance : 0n;
9
+ const rateBalance = quotaBalance * BigInt(rate);
10
+ return acc + rateBalance;
11
+ },
12
+ 0n
13
+ );
14
+ return totalRateBalance;
15
+ }
16
+ export {
17
+ calcQuotaBorrowRate
18
+ };
@@ -0,0 +1,10 @@
1
+ function calcRelativeBaseBorrowRate({
2
+ debt,
3
+ baseRateWithFee,
4
+ assetAmountInUnderlying
5
+ }) {
6
+ return debt * BigInt(baseRateWithFee) * assetAmountInUnderlying;
7
+ }
8
+ export {
9
+ calcRelativeBaseBorrowRate
10
+ };