@gearbox-protocol/sdk 15.1.0-next.10 → 15.1.0-next.12

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 (42) hide show
  1. package/dist/cjs/dev/mode-parity/compareOpportunities.js +105 -0
  2. package/dist/cjs/dev/mode-parity/comparePositions.js +160 -0
  3. package/dist/cjs/dev/mode-parity/compareRules.js +93 -0
  4. package/dist/cjs/dev/mode-parity/fieldDiff.js +288 -0
  5. package/dist/cjs/dev/mode-parity/scriptUtils.js +131 -0
  6. package/dist/cjs/model/compare.schema.js +33 -0
  7. package/dist/cjs/model/curators.schema.js +2 -1
  8. package/dist/cjs/model/index.js +5 -0
  9. package/dist/cjs/model/opportunities.schema.js +13 -12
  10. package/dist/cjs/model/positions.schema.js +15 -14
  11. package/dist/cjs/model/primitives.schema.js +2 -1
  12. package/dist/cjs/sdk/market/math.js +8 -1
  13. package/dist/cjs/sdk/pools/PoolService.js +1 -1
  14. package/dist/cjs/sdk/positions/PositionsService.js +6 -1
  15. package/dist/esm/common-utils/index.js +3 -3
  16. package/dist/esm/common-utils/utils/index.js +1 -1
  17. package/dist/esm/dev/mode-parity/compareOpportunities.js +103 -0
  18. package/dist/esm/dev/mode-parity/comparePositions.js +158 -0
  19. package/dist/esm/dev/mode-parity/compareRules.js +91 -0
  20. package/dist/esm/dev/mode-parity/fieldDiff.js +270 -0
  21. package/dist/esm/dev/mode-parity/scriptUtils.js +121 -0
  22. package/dist/esm/model/compare.schema.js +29 -0
  23. package/dist/esm/model/curators.schema.js +2 -1
  24. package/dist/esm/model/index.js +2 -1
  25. package/dist/esm/model/opportunities.schema.js +13 -12
  26. package/dist/esm/model/positions.schema.js +15 -14
  27. package/dist/esm/model/primitives.schema.js +2 -1
  28. package/dist/esm/plugins/apy/ApyPlugin.js +2 -2
  29. package/dist/esm/sdk/market/math.js +8 -1
  30. package/dist/esm/sdk/pools/PoolService.js +1 -1
  31. package/dist/esm/sdk/positions/PositionsService.js +6 -1
  32. package/dist/types/dev/{compareOpportunities.d.ts → mode-parity/compareOpportunities.d.ts} +18 -66
  33. package/dist/types/dev/mode-parity/comparePositions.d.ts +149 -0
  34. package/dist/types/dev/mode-parity/compareRules.d.ts +33 -0
  35. package/dist/types/dev/mode-parity/fieldDiff.d.ts +209 -0
  36. package/dist/types/dev/mode-parity/scriptUtils.d.ts +47 -0
  37. package/dist/types/model/compare.schema.d.ts +47 -0
  38. package/dist/types/model/index.d.ts +2 -1
  39. package/dist/types/sdk/market/math.d.ts +2 -0
  40. package/package.json +1 -1
  41. package/dist/cjs/dev/compareOpportunities.js +0 -218
  42. package/dist/esm/dev/compareOpportunities.js +0 -216
@@ -0,0 +1,131 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_dev_providers = require("../providers.js");
3
+ let pino = require("pino");
4
+ //#region src/dev/mode-parity/scriptUtils.ts
5
+ const NETWORKS = [
6
+ "Mainnet",
7
+ "Monad",
8
+ "Plasma",
9
+ "Somnia",
10
+ "Etherlink"
11
+ ];
12
+ const BACKEND_URL = process.env.BACKEND_URL ?? "https://api.gear-dev.dev";
13
+ const TIMEOUT = 48e4;
14
+ function requireEnv(name) {
15
+ const value = process.env[name];
16
+ if (!value) throw new Error(`${name} is required to reach the chains this script reads`);
17
+ return value;
18
+ }
19
+ function rpcUrls() {
20
+ const alchemyKey = requireEnv("ALCHEMY_KEY");
21
+ const alchemy = (network) => {
22
+ const url = require_dev_providers.getAlchemyUrl(network, alchemyKey);
23
+ if (!url) throw new Error(`Alchemy serves no URL for ${network}`);
24
+ return url;
25
+ };
26
+ return {
27
+ Mainnet: alchemy("Mainnet"),
28
+ Monad: alchemy("Monad"),
29
+ Plasma: alchemy("Plasma"),
30
+ Somnia: requireEnv("SOMNIA_PROVIDER"),
31
+ Etherlink: requireEnv("ETHERLINK_PROVIDER")
32
+ };
33
+ }
34
+ function createLogger() {
35
+ return (0, pino.pino)({
36
+ level: process.env.LOG_LEVEL ?? "info",
37
+ formatters: {
38
+ bindings: () => ({}),
39
+ level: (label) => ({ level: label })
40
+ }
41
+ });
42
+ }
43
+ function errorMessage(error) {
44
+ return error instanceof Error ? error.message : String(error);
45
+ }
46
+ /**
47
+ * Runs `fn` over `items` with at most `concurrency` in flight.
48
+ **/
49
+ async function mapPool(items, concurrency, fn) {
50
+ let next = 0;
51
+ const workers = Array.from({ length: Math.min(concurrency, items.length) }, async () => {
52
+ while (true) {
53
+ const index = next;
54
+ next += 1;
55
+ if (index >= items.length) return;
56
+ await fn(items[index]);
57
+ }
58
+ });
59
+ await Promise.all(workers);
60
+ }
61
+ /**
62
+ * Formats a relative difference in bps as a percent, e.g. 12.5 → `"0.125%"`.
63
+ **/
64
+ function formatBpsAsPercent(bps) {
65
+ if (!Number.isFinite(bps)) return "";
66
+ const percent = bps / 100;
67
+ if (percent === 0) return "0%";
68
+ return `${Math.abs(percent) >= 1 ? trimTrailingZeros(percent.toFixed(3)) : trimTrailingZeros(percent.toPrecision(4))}%`;
69
+ }
70
+ function trimTrailingZeros(value) {
71
+ return value.includes(".") ? value.replace(/\.?0+$/, "") : value;
72
+ }
73
+ function worstColumns(worst) {
74
+ return {
75
+ "max diff": worst ? formatBpsAsPercent(worst.bps) : "",
76
+ "worst entity": worst?.id ?? ""
77
+ };
78
+ }
79
+ /**
80
+ * Prints the shared membership table, the fields that differed most often,
81
+ * and any chain that failed to answer.
82
+ **/
83
+ function printCompareSummary(noun, report, extraLines = []) {
84
+ const { summary } = report;
85
+ console.log(`\n${noun} from ${report.backendUrl} vs the chain`);
86
+ console.table(summary.byChain.map((chain) => ({
87
+ chain: chain.chainId,
88
+ onchain: chain.onchainRows,
89
+ offchain: chain.offchainRows,
90
+ matched: chain.matched,
91
+ identical: chain.identical,
92
+ clean: chain.clean,
93
+ differing: chain.differing,
94
+ "only onchain": chain.onlyOnchain,
95
+ "only offchain": chain.onlyOffchain
96
+ })));
97
+ for (const line of extraLines) console.log(line);
98
+ const unexpected = summary.diffsByPath.filter((entry) => entry.unexpected > 0);
99
+ const expected = summary.diffsByPath.filter((entry) => entry.unexpected === 0 && entry.expected > 0);
100
+ if (unexpected.length) {
101
+ console.log("\nunexpected fields that differed most often:");
102
+ console.table(unexpected.slice(0, 25).map((entry) => ({
103
+ field: entry.path,
104
+ unexpected: entry.unexpected,
105
+ expected: entry.expected,
106
+ kinds: entry.kinds.join(", "),
107
+ ...worstColumns(entry.worstUnexpected)
108
+ })));
109
+ }
110
+ if (expected.length) {
111
+ console.log("\nexpected fields (mode-scoped or within tolerance):");
112
+ console.table(expected.slice(0, 25).map((entry) => ({
113
+ field: entry.path,
114
+ rows: entry.expected,
115
+ kinds: entry.kinds.join(", "),
116
+ ...worstColumns(entry.worstExpected)
117
+ })));
118
+ }
119
+ for (const chain of [...report.onchainChains, ...report.offchainChains]) if (chain.status === "error") console.log(`chain ${chain.chainId} failed on ${chain.source}:`, chain.error);
120
+ }
121
+ //#endregion
122
+ exports.BACKEND_URL = BACKEND_URL;
123
+ exports.NETWORKS = NETWORKS;
124
+ exports.TIMEOUT = TIMEOUT;
125
+ exports.createLogger = createLogger;
126
+ exports.errorMessage = errorMessage;
127
+ exports.formatBpsAsPercent = formatBpsAsPercent;
128
+ exports.mapPool = mapPool;
129
+ exports.printCompareSummary = printCompareSummary;
130
+ exports.requireEnv = requireEnv;
131
+ exports.rpcUrls = rpcUrls;
@@ -0,0 +1,33 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ //#region src/model/compare.schema.ts
3
+ /**
4
+ * Marks a field that only the backend fills.
5
+ **/
6
+ function offchainOnly(schema) {
7
+ return schema.meta({ compare: "offchainOnly" });
8
+ }
9
+ /**
10
+ * Marks a field that only the chain fills.
11
+ **/
12
+ function onchainOnly(schema) {
13
+ return schema.meta({ compare: "onchainOnly" });
14
+ }
15
+ /**
16
+ * Marks a numeric field whose two sources may drift within {@link kind}.
17
+ **/
18
+ function tolerance(schema, kind) {
19
+ return schema.meta({ compare: { tolerance: kind } });
20
+ }
21
+ /**
22
+ * The compare tag registered on a schema, if any.
23
+ **/
24
+ function compareTagOf(schema) {
25
+ const meta = schema.meta();
26
+ if (!meta || !("compare" in meta)) return;
27
+ return meta.compare;
28
+ }
29
+ //#endregion
30
+ exports.compareTagOf = compareTagOf;
31
+ exports.offchainOnly = offchainOnly;
32
+ exports.onchainOnly = onchainOnly;
33
+ exports.tolerance = tolerance;
@@ -1,5 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_sdk_utils_zod = require("../sdk/utils/zod.js");
3
+ const require_model_compare_schema = require("./compare.schema.js");
3
4
  let zod_v4 = require("zod/v4");
4
5
  //#region src/model/curators.schema.ts
5
6
  /**
@@ -31,7 +32,7 @@ const curatorNameSchema = zod_v4.z.enum([
31
32
  const curatorSchema = zod_v4.z.object({
32
33
  address: require_sdk_utils_zod.ZodAddress(),
33
34
  name: curatorNameSchema.optional(),
34
- url: zod_v4.z.string().nullable()
35
+ url: require_model_compare_schema.offchainOnly(zod_v4.z.string().nullable())
35
36
  });
36
37
  //#endregion
37
38
  exports.curatorNameSchema = curatorNameSchema;
@@ -1,5 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_model_charts = require("./charts.js");
3
+ const require_model_compare_schema = require("./compare.schema.js");
3
4
  const require_model_primitives_schema = require("./primitives.schema.js");
4
5
  const require_model_charts_schema = require("./charts.schema.js");
5
6
  require("./curators.js");
@@ -45,6 +46,7 @@ exports.chartRangeSchema = require_model_charts_schema.chartRangeSchema;
45
46
  exports.chartSeriesSchema = require_model_charts_schema.chartSeriesSchema;
46
47
  exports.chartValueSchema = require_model_charts_schema.chartValueSchema;
47
48
  exports.chartWindowSchema = require_model_charts_schema.chartWindowSchema;
49
+ exports.compareTagOf = require_model_compare_schema.compareTagOf;
48
50
  exports.curatorNameSchema = require_model_curators_schema.curatorNameSchema;
49
51
  exports.curatorSchema = require_model_curators_schema.curatorSchema;
50
52
  exports.dataSourceSchema = require_model_response_schema.dataSourceSchema;
@@ -66,6 +68,8 @@ exports.matchesOpportunityFilter = require_model_opportunities.matchesOpportunit
66
68
  exports.matchesPositionFilter = require_model_positions.matchesPositionFilter;
67
69
  exports.noticeKindSchema = require_model_notices_schema.noticeKindSchema;
68
70
  exports.noticeSchema = require_model_notices_schema.noticeSchema;
71
+ exports.offchainOnly = require_model_compare_schema.offchainOnly;
72
+ exports.onchainOnly = require_model_compare_schema.onchainOnly;
69
73
  exports.opportunityBaseSchema = require_model_opportunities_schema.opportunityBaseSchema;
70
74
  exports.opportunityDetailSchema = require_model_opportunities_schema.opportunityDetailSchema;
71
75
  exports.opportunityFilterQueryParamsSchema = require_model_opportunities_schema.opportunityFilterQueryParamsSchema;
@@ -124,4 +128,5 @@ exports.tokenAmountSchema = require_model_primitives_schema.tokenAmountSchema;
124
128
  exports.tokenRewardsPnLSchema = require_model_positions_schema.tokenRewardsPnLSchema;
125
129
  exports.tokenRewardsSchema = require_model_opportunities_schema.tokenRewardsSchema;
126
130
  exports.tokenSchema = require_model_primitives_schema.tokenSchema;
131
+ exports.tolerance = require_model_compare_schema.tolerance;
127
132
  exports.txCallSchema = require_model_primitives_schema.txCallSchema;
@@ -1,5 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_sdk_utils_zod = require("../sdk/utils/zod.js");
3
+ const require_model_compare_schema = require("./compare.schema.js");
3
4
  const require_model_primitives_schema = require("./primitives.schema.js");
4
5
  const require_model_curators_schema = require("./curators.schema.js");
5
6
  const require_model_filters = require("./filters.js");
@@ -46,9 +47,9 @@ const rewardsSchema = zod_v4.z.discriminatedUnion("kind", [tokenRewardsSchema, p
46
47
  * {@link ApyBreakdown}
47
48
  **/
48
49
  const apyBreakdownSchema = zod_v4.z.object({
49
- totalApy: require_model_primitives_schema.bpsSchema.optional(),
50
- organicApy: require_model_primitives_schema.bpsSchema,
51
- rewards: zod_v4.z.array(rewardsSchema).optional()
50
+ totalApy: require_model_compare_schema.offchainOnly(require_model_primitives_schema.bpsSchema).optional(),
51
+ organicApy: require_model_compare_schema.tolerance(require_model_primitives_schema.bpsSchema, "bps"),
52
+ rewards: require_model_compare_schema.offchainOnly(zod_v4.z.array(rewardsSchema)).optional()
52
53
  });
53
54
  /**
54
55
  * {@link OpportunityBase}
@@ -71,9 +72,9 @@ const poolOpportunitySchema = zod_v4.z.object({
71
72
  ...opportunityBaseSchema.shape,
72
73
  kind: zod_v4.z.literal("pool"),
73
74
  pool: require_sdk_utils_zod.ZodAddress(),
74
- totalSupply: require_model_primitives_schema.amountSchema,
75
- availableLiquidity: require_model_primitives_schema.amountSchema,
76
- utilization: require_model_primitives_schema.bpsSchema,
75
+ totalSupply: require_model_compare_schema.tolerance(require_model_primitives_schema.amountSchema, "amount"),
76
+ availableLiquidity: require_model_compare_schema.tolerance(require_model_primitives_schema.amountSchema, "amount"),
77
+ utilization: require_model_compare_schema.tolerance(require_model_primitives_schema.bpsSchema, "bps"),
77
78
  supplyApy: apyBreakdownSchema
78
79
  });
79
80
  /**
@@ -88,12 +89,12 @@ const strategyOpportunitySchema = zod_v4.z.object({
88
89
  liquidationPremium: require_model_primitives_schema.bpsSchema,
89
90
  liquidationFee: require_model_primitives_schema.bpsSchema,
90
91
  expirationDate: require_model_primitives_schema.timestampSchema.nullable(),
91
- collateralApy: apyBreakdownSchema.optional(),
92
- maxLeverageApy: apyBreakdownSchema.optional(),
93
- borrowApy: require_model_primitives_schema.bpsSchema.optional(),
94
- additionalBorrowApy: require_model_primitives_schema.bpsSchema.optional(),
95
- totalValue: require_model_primitives_schema.amountSchema.optional(),
96
- utilization: require_model_primitives_schema.bpsSchema.optional(),
92
+ collateralApy: require_model_compare_schema.offchainOnly(apyBreakdownSchema).optional(),
93
+ maxLeverageApy: require_model_compare_schema.offchainOnly(apyBreakdownSchema).optional(),
94
+ borrowApy: require_model_compare_schema.tolerance(require_model_primitives_schema.bpsSchema, "bps").optional(),
95
+ additionalBorrowApy: require_model_compare_schema.tolerance(require_model_primitives_schema.bpsSchema, "bps").optional(),
96
+ totalValue: require_model_compare_schema.offchainOnly(require_model_primitives_schema.amountSchema).optional(),
97
+ utilization: require_model_compare_schema.offchainOnly(require_model_primitives_schema.bpsSchema).optional(),
97
98
  maxBorrowAmount: require_model_primitives_schema.amountSchema,
98
99
  maxLeverage: require_model_primitives_schema.leverageSchema
99
100
  });
@@ -1,5 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_sdk_utils_zod = require("../sdk/utils/zod.js");
3
+ const require_model_compare_schema = require("./compare.schema.js");
3
4
  const require_model_primitives_schema = require("./primitives.schema.js");
4
5
  const require_model_filters = require("./filters.js");
5
6
  const require_model_filters_schema = require("./filters.schema.js");
@@ -56,8 +57,8 @@ const pnlBreakdownSchema = zod_v4.z.object({
56
57
  * {@link PositionCollateral}
57
58
  **/
58
59
  const positionCollateralSchema = zod_v4.z.object({
59
- collateral: require_model_primitives_schema.tokenAmountSchema,
60
- quota: require_model_primitives_schema.tokenAmountSchema,
60
+ collateral: require_model_compare_schema.tolerance(require_model_primitives_schema.tokenAmountSchema, "amount"),
61
+ quota: require_model_compare_schema.tolerance(require_model_primitives_schema.tokenAmountSchema, "amount"),
61
62
  withdrawals: zod_v4.z.array(require_model_liquidations_schema.delayedReceivedAssetSchema)
62
63
  });
63
64
  /**
@@ -68,9 +69,9 @@ const poolPositionSchema = zod_v4.z.object({
68
69
  name: zod_v4.z.string(),
69
70
  chainId: require_model_primitives_schema.chainIdSchema,
70
71
  pool: require_sdk_utils_zod.ZodAddress(),
71
- netValue: require_model_primitives_schema.tokenAmountSchema,
72
+ netValue: require_model_compare_schema.tolerance(require_model_primitives_schema.tokenAmountSchema, "amount"),
72
73
  apy: require_model_opportunities_schema.apyBreakdownSchema,
73
- pnl: pnlBreakdownSchema.optional()
74
+ pnl: require_model_compare_schema.offchainOnly(pnlBreakdownSchema).optional()
74
75
  });
75
76
  /**
76
77
  * {@link BorrowRateBreakdown}
@@ -91,16 +92,16 @@ const strategyPositionSchema = zod_v4.z.object({
91
92
  creditManager: require_sdk_utils_zod.ZodAddress(),
92
93
  creditAccount: require_sdk_utils_zod.ZodAddress(),
93
94
  targetCollateral: require_model_primitives_schema.tokenSchema.nullable(),
94
- leverage: require_model_primitives_schema.leverageSchema,
95
- borrowApy: require_model_primitives_schema.bpsSchema,
96
- netApy: require_model_opportunities_schema.apyBreakdownSchema.optional(),
97
- totalDebt: require_model_primitives_schema.tokenAmountSchema,
98
- totalValue: require_model_primitives_schema.tokenAmountSchema,
99
- healthFactor: require_model_primitives_schema.bpsSchema,
100
- borrowRate: borrowRateBreakdownSchema.optional(),
101
- timeToLiquidation: require_sdk_utils_zod.ZodBigInt().nullable().optional(),
102
- liquidationPrice: require_sdk_utils_zod.ZodBigInt().nullable().optional(),
103
- pnl: pnlBreakdownSchema.optional(),
95
+ leverage: require_model_compare_schema.tolerance(require_model_primitives_schema.leverageSchema, "float"),
96
+ borrowApy: require_model_compare_schema.tolerance(require_model_primitives_schema.bpsSchema, "bps"),
97
+ netApy: require_model_compare_schema.offchainOnly(require_model_opportunities_schema.apyBreakdownSchema).optional(),
98
+ totalDebt: require_model_compare_schema.tolerance(require_model_primitives_schema.tokenAmountSchema, "amount"),
99
+ totalValue: require_model_compare_schema.tolerance(require_model_primitives_schema.tokenAmountSchema, "amount"),
100
+ healthFactor: require_model_compare_schema.tolerance(require_model_primitives_schema.bpsSchema, "bps"),
101
+ borrowRate: require_model_compare_schema.onchainOnly(borrowRateBreakdownSchema).optional(),
102
+ timeToLiquidation: require_model_compare_schema.onchainOnly(require_sdk_utils_zod.ZodBigInt().nullable()).optional(),
103
+ liquidationPrice: require_model_compare_schema.onchainOnly(require_sdk_utils_zod.ZodBigInt().nullable()).optional(),
104
+ pnl: require_model_compare_schema.offchainOnly(pnlBreakdownSchema).optional(),
104
105
  collaterals: zod_v4.z.array(positionCollateralSchema)
105
106
  });
106
107
  /**
@@ -1,5 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_sdk_utils_zod = require("../sdk/utils/zod.js");
3
+ const require_model_compare_schema = require("./compare.schema.js");
3
4
  let zod_v4 = require("zod/v4");
4
5
  //#region src/model/primitives.schema.ts
5
6
  /**
@@ -40,7 +41,7 @@ const leverageSchema = zod_v4.z.number().nonnegative();
40
41
  **/
41
42
  const amountSchema = zod_v4.z.object({
42
43
  value: require_sdk_utils_zod.ZodBigInt(),
43
- valueUsd: zod_v4.z.number().nullable()
44
+ valueUsd: require_model_compare_schema.tolerance(zod_v4.z.number().nullable(), "usd")
44
45
  });
45
46
  /**
46
47
  * {@link Token}
@@ -24,8 +24,15 @@ function rayToBps(ray) {
24
24
  return Number(ray * require_sdk_constants_math.PERCENTAGE_FACTOR / require_sdk_constants_math.RAY);
25
25
  }
26
26
  /**
27
+ * Raw 8-decimal USD values below this are compressor leftover dust (typically
28
+ * 1-wei balances on empty accounts) and report as `0`.
29
+ **/
30
+ const USD_DUST_THRESHOLD = 1000n;
31
+ /**
27
32
  * Converts a USD value in the oracle's 8-decimal fixed point to a float.
28
33
  *
34
+ * Values below {@link USD_DUST_THRESHOLD} report as `0`.
35
+ *
29
36
  * @example
30
37
  * ```ts
31
38
  * // usd: $1500.50 in 8-decimal fixed point
@@ -33,7 +40,7 @@ function rayToBps(ray) {
33
40
  * ```
34
41
  **/
35
42
  function usdToNumber(usd) {
36
- return Number(usd) / Number(require_sdk_constants_math.PRICE_DECIMALS);
43
+ return usd < USD_DUST_THRESHOLD ? 0 : Number(usd) / Number(require_sdk_constants_math.PRICE_DECIMALS);
37
44
  }
38
45
  /**
39
46
  * Share of capital currently borrowed, in basis points. Returns `0` when there
@@ -415,7 +415,7 @@ var PoolService = class extends require_sdk_base_SDKConstruct.SDKConstruct {
415
415
  const { pool } = market.pool;
416
416
  return {
417
417
  kind: "pool",
418
- name: market.poolName,
418
+ name: this.sdk.tokensMeta.mustGetToken(pool.address).name,
419
419
  chainId: this.chainId,
420
420
  pool: pool.address,
421
421
  netValue: {
@@ -2,6 +2,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_sdk_utils_AddressMap = require("../utils/AddressMap.js");
3
3
  require("../constants/math.js");
4
4
  require("../constants/index.js");
5
+ const require_sdk_utils_hex = require("../utils/hex.js");
5
6
  require("../utils/index.js");
6
7
  const require_sdk_base_SDKConstruct = require("../base/SDKConstruct.js");
7
8
  require("../base/index.js");
@@ -147,7 +148,11 @@ var PositionsService = class extends require_sdk_base_SDKConstruct.SDKConstruct
147
148
  const { pool } = market.pool;
148
149
  const token = this.sdk.tokensMeta.mustGetToken(market.unwrappedUnderlying);
149
150
  const totalDebtValue = ca.debt + ca.accruedInterest + ca.accruedFees;
150
- const collateral = require_sdk_market_credit_dominantCollateral.dominantCollateral(ca, market);
151
+ let collateral = require_sdk_market_credit_dominantCollateral.dominantCollateral(ca, market);
152
+ if (collateral) {
153
+ const source = this.sdk.withdrawalCompressor?.getWithdrawalSourceToken(collateral);
154
+ if (source) collateral = require_sdk_utils_hex.hexEq(source, market.underlying) ? void 0 : source;
155
+ }
151
156
  const snapshot = require_sdk_positions_types.accountSnapshotFromCreditAccountData(ca);
152
157
  const borrowRate = this.borrowRate(snapshot);
153
158
  const timeToLiquidation = this.timeToLiquidation(snapshot);
@@ -1,7 +1,8 @@
1
- import { AxiosCache } from "./axios-cache/AxiosCache.js";
2
- import "./axios-cache/index.js";
3
1
  import { BigIntMath } from "../sdk/utils/bigint-math.js";
4
2
  import { calcDefaultQuota, calcQuotaUpdate, calcRecommendedQuota, roundUpQuota } from "./utils/creditAccount/quota-utils.js";
3
+ import { EXECUTE_BYTES_SELECTOR, collectTraces, findCallTo, findCallWithInput, findExecuteBytes, resolveProtocolCall } from "./utils/trace.js";
4
+ import { AxiosCache } from "./axios-cache/AxiosCache.js";
5
+ import "./axios-cache/index.js";
5
6
  import { ChartsCreditManagerData } from "./charts/credit-manager.js";
6
7
  import { CREDIT_SESSION_ID_BY_STATUS, CREDIT_SESSION_STATUS_BY_ID, CreditSession, CreditSessionFiltered, UserCreditSessionsBuilder } from "./charts/credit-session.js";
7
8
  import { ChartsPoolData, UserPoolData } from "./charts/pool.js";
@@ -91,6 +92,5 @@ import { getCMYouCanEarn } from "./utils/strategies/strategy-info/get-cm-you-can
91
92
  import { getStrategyInfoCore } from "./utils/strategies/strategy-info/get-strategy-info-core.js";
92
93
  import { getStrategyInfo } from "./utils/strategies/strategy-info/get-strategy-info.js";
93
94
  import { getStrategyYouCanEarn } from "./utils/strategies/strategy-info/get-strategy-you-can-earn.js";
94
- import { EXECUTE_BYTES_SELECTOR, collectTraces, findCallTo, findCallWithInput, findExecuteBytes, resolveProtocolCall } from "./utils/trace.js";
95
95
  import "./utils/index.js";
96
96
  export { AssetUtils, AxiosCache, BONUS_APY_FROM_POINTS, BigIntMath, CREDIT_SESSION_ID_BY_STATUS, CREDIT_SESSION_STATUS_BY_ID, ChartsCreditManagerData, ChartsPoolData, CreditSession, CreditSessionFiltered, EMPTY_ADDRESS, EMPTY_ARRAY, EMPTY_OBJECT, EXECUTE_BYTES_SELECTOR, MIN_HF_LIMITED, PriceUtils, RST_ETH_ADDRESS, TokenData, UserCreditSessionsBuilder, UserPoolData, addAmountInTarget, amountAbcComparator, assetComparator, calcDefaultQuota, calcHealthFactor, calcMaxDebtIncrease, calcMaxLendingDebt, calcOverallAPY, calcQuotaBorrowRate, calcQuotaUpdate, calcRecommendedQuota, calcRelativeBaseBorrowRate, calculateBorrowRateFromUtilization, calculateEarnings, calculateEffectiveBorrowRate, calculateLossCoefficient, calculateMaxLeverageFactor, calculateMaxStrategyDebt, calculateSafeBorrowRate, calculateTotalAPY, calculateTotalPoints, checkBoolean, checkDegenNFT, cmAvailabilityCondition, collectTraces, createLegacyStrategyDataSource, findCallTo, findCallWithInput, findExecuteBytes, getAvailableAndDisabledStrategies, getCMAllowedCollaterals, getCMYouCanEarn, getChainPhantomTokens, getCollateralByDebt, getComplexAPYList, getComplexPointsList, getDefaultAsset, getFactorFromLeverage, getLeverageFromFactor, getListWithAmountInTarget, getNativeTokenAddress, getPointsInfo, getPointsRates, getRateWithFee, getRecommendedDebt, getRecommendedLeverageFactor, getReleasedStrategiesList, getReleasedStrategiesListCore, getSafeBaseBorrowRate, getSingleQuotaBorrowRate, getStrategyCreditManagers, getStrategyCreditManagersList, getStrategyCreditManagersListCore, getStrategyInfo, getStrategyInfoCore, getStrategyMaxAPY, getStrategyPoints, getStrategyYouCanEarn, getTimeToLiquidation, getWalletBalancesAllowedOnCM, isActivatedToken, isApyWithPointsException, isCollateralToken, isCreditManagerUsable, isForbiddenToken, isObtainableToken, isStrategyCMDisabled, isStrategyDisabled, isStrategyEligible, isStrategyReleased, isUsableToken, isValidExtraCollateralToken, isZeroBalance, liquidationPrice, maxAPYFormula, maxLeverage, maxLeverageThreshold, resolveProtocolCall, roundUpQuota, sortAssets, sortBalances, sortStrategyCMsByAvailability, tokensAbcComparator, validateBalance, validateBalances, validateCreditManager, validateHF, validateOpenAccount, validateOpenAccountPoolQuotaStatus, validateOpenAccountPoolStatus, validateQuota, validateTokenToObtain, wrapTokenAddress };
@@ -1,5 +1,6 @@
1
1
  import { BigIntMath } from "../../sdk/utils/bigint-math.js";
2
2
  import { calcDefaultQuota, calcQuotaUpdate, calcRecommendedQuota, roundUpQuota } from "./creditAccount/quota-utils.js";
3
+ import { EXECUTE_BYTES_SELECTOR, collectTraces, findCallTo, findCallWithInput, findExecuteBytes, resolveProtocolCall } from "./trace.js";
3
4
  import { BONUS_APY_FROM_POINTS } from "./apy/bonus-apy-from-points.js";
4
5
  import { calculateBorrowRateFromUtilization } from "./apy/calculate-borrow-rate-from-utilization.js";
5
6
  import { PriceUtils } from "./price-math.js";
@@ -86,6 +87,5 @@ import { getStrategyInfoCore } from "./strategies/strategy-info/get-strategy-inf
86
87
  import { getStrategyInfo } from "./strategies/strategy-info/get-strategy-info.js";
87
88
  import { getStrategyYouCanEarn } from "./strategies/strategy-info/get-strategy-you-can-earn.js";
88
89
  import "./strategies/index.js";
89
- import { EXECUTE_BYTES_SELECTOR, collectTraces, findCallTo, findCallWithInput, findExecuteBytes, resolveProtocolCall } from "./trace.js";
90
90
  import "./validation/index.js";
91
91
  export { AssetUtils, BONUS_APY_FROM_POINTS, BigIntMath, EMPTY_ADDRESS, EMPTY_ARRAY, EMPTY_OBJECT, EXECUTE_BYTES_SELECTOR, MIN_HF_LIMITED, PriceUtils, RST_ETH_ADDRESS, addAmountInTarget, amountAbcComparator, assetComparator, calcDefaultQuota, calcHealthFactor, calcMaxDebtIncrease, calcMaxLendingDebt, calcOverallAPY, calcQuotaBorrowRate, calcQuotaUpdate, calcRecommendedQuota, calcRelativeBaseBorrowRate, calculateBorrowRateFromUtilization, calculateEarnings, calculateEffectiveBorrowRate, calculateLossCoefficient, calculateMaxLeverageFactor, calculateMaxStrategyDebt, calculateSafeBorrowRate, calculateTotalAPY, calculateTotalPoints, checkBoolean, checkDegenNFT, cmAvailabilityCondition, collectTraces, createLegacyStrategyDataSource, findCallTo, findCallWithInput, findExecuteBytes, getAvailableAndDisabledStrategies, getCMAllowedCollaterals, getCMYouCanEarn, getChainPhantomTokens, getCollateralByDebt, getComplexAPYList, getComplexPointsList, getDefaultAsset, getFactorFromLeverage, getLeverageFromFactor, getListWithAmountInTarget, getNativeTokenAddress, getPointsInfo, getPointsRates, getRateWithFee, getRecommendedDebt, getRecommendedLeverageFactor, getReleasedStrategiesList, getReleasedStrategiesListCore, getSafeBaseBorrowRate, getSingleQuotaBorrowRate, getStrategyCreditManagers, getStrategyCreditManagersList, getStrategyCreditManagersListCore, getStrategyInfo, getStrategyInfoCore, getStrategyMaxAPY, getStrategyPoints, getStrategyYouCanEarn, getTimeToLiquidation, getWalletBalancesAllowedOnCM, isActivatedToken, isApyWithPointsException, isCollateralToken, isCreditManagerUsable, isForbiddenToken, isObtainableToken, isStrategyCMDisabled, isStrategyDisabled, isStrategyEligible, isStrategyReleased, isUsableToken, isValidExtraCollateralToken, isZeroBalance, liquidationPrice, maxAPYFormula, maxLeverage, maxLeverageThreshold, resolveProtocolCall, roundUpQuota, sortAssets, sortBalances, sortStrategyCMsByAvailability, tokensAbcComparator, validateBalance, validateBalances, validateCreditManager, validateHF, validateOpenAccount, validateOpenAccountPoolQuotaStatus, validateOpenAccountPoolStatus, validateQuota, validateTokenToObtain, wrapTokenAddress };
@@ -0,0 +1,103 @@
1
+ import { opportunityId } from "../../model/opportunities.js";
2
+ import { poolOpportunitySchema, strategyOpportunitySchema } from "../../model/opportunities.schema.js";
3
+ import "../../model/index.js";
4
+ import { countPaths, diffObjects, toCompareCounts, union } from "./fieldDiff.js";
5
+ import { compileCompareRules, makeTagDiff } from "./compareRules.js";
6
+ //#region src/dev/mode-parity/compareOpportunities.ts
7
+ const tagDiff = makeTagDiff({
8
+ pool: compileCompareRules(poolOpportunitySchema),
9
+ strategy: compileCompareRules(strategyOpportunitySchema)
10
+ });
11
+ /**
12
+ * Matches two opportunity listings by {@link opportunityId} and reports every
13
+ * field the two sources disagree on.
14
+ *
15
+ * Nothing is filtered out. A field only the backend can fill, or a USD value
16
+ * that drifted within snapshot-lag noise, is still reported — tagged
17
+ * {@link FieldDiff.expected} so that {@link CompareCounts.clean} can ignore it
18
+ * while {@link CompareCounts.identical} stays strict.
19
+ **/
20
+ function compareOpportunities(input) {
21
+ const onchainRows = indexById(input.onchain.data);
22
+ const offchainRows = indexById(input.offchain.data);
23
+ const onlyOnchain = [];
24
+ const onlyOffchain = [];
25
+ const matched = [];
26
+ for (const [id, row] of onchainRows) {
27
+ const counterpart = offchainRows.get(id);
28
+ if (!counterpart) {
29
+ onlyOnchain.push(toRef(row));
30
+ continue;
31
+ }
32
+ const diffs = diffOpportunity(row, counterpart);
33
+ matched.push({
34
+ id,
35
+ kind: row.kind,
36
+ chainId: row.chainId,
37
+ onchainName: row.name,
38
+ offchainName: counterpart.name,
39
+ identical: diffs.length === 0,
40
+ clean: diffs.every((diff) => diff.expected),
41
+ diffs
42
+ });
43
+ }
44
+ for (const [id, row] of offchainRows) if (!onchainRows.has(id)) onlyOffchain.push(toRef(row));
45
+ byId(onlyOnchain);
46
+ byId(onlyOffchain);
47
+ matched.sort((a, b) => a.id.localeCompare(b.id));
48
+ return {
49
+ generatedAt: input.generatedAt ?? (/* @__PURE__ */ new Date()).toISOString(),
50
+ backendUrl: input.backendUrl,
51
+ networks: [...input.networks],
52
+ onchainChains: input.onchain.meta.chains,
53
+ offchainChains: input.offchain.meta.chains,
54
+ summary: summarize(input.onchain.data, input.offchain.data, onlyOnchain, onlyOffchain, matched),
55
+ onlyOnchain,
56
+ onlyOffchain,
57
+ matched
58
+ };
59
+ }
60
+ function indexById(rows) {
61
+ return new Map(rows.map((row) => [opportunityId(row), row]));
62
+ }
63
+ function byId(refs) {
64
+ refs.sort((a, b) => a.id.localeCompare(b.id));
65
+ }
66
+ function toRef(row) {
67
+ const base = {
68
+ id: opportunityId(row),
69
+ kind: row.kind,
70
+ chainId: row.chainId,
71
+ name: row.name
72
+ };
73
+ return row.kind === "pool" ? {
74
+ ...base,
75
+ pool: row.pool
76
+ } : {
77
+ ...base,
78
+ creditManager: row.creditManager,
79
+ targetCollateral: row.targetCollateral.address
80
+ };
81
+ }
82
+ /**
83
+ * Every field two versions of one opportunity disagree on.
84
+ **/
85
+ function diffOpportunity(onchain, offchain) {
86
+ return diffObjects(onchain, offchain).map((diff) => tagDiff(diff, onchain.kind));
87
+ }
88
+ function summarize(onchain, offchain, onlyOnchain, onlyOffchain, matched) {
89
+ const byChain = union(onchain.map((row) => String(row.chainId)), offchain.map((row) => String(row.chainId))).map((chainId) => ({
90
+ chainId: Number(chainId),
91
+ ...toCompareCounts(onchain.filter((row) => String(row.chainId) === chainId).length, offchain.filter((row) => String(row.chainId) === chainId).length, onlyOnchain.filter((ref) => String(ref.chainId) === chainId).length, onlyOffchain.filter((ref) => String(ref.chainId) === chainId).length, matched.filter((match) => String(match.chainId) === chainId))
92
+ })).sort((a, b) => a.chainId - b.chainId);
93
+ return {
94
+ ...toCompareCounts(onchain.length, offchain.length, onlyOnchain.length, onlyOffchain.length, matched),
95
+ byChain,
96
+ diffsByPath: countPaths(matched.flatMap((match) => match.diffs.map((diff) => ({
97
+ id: match.id,
98
+ diff
99
+ }))))
100
+ };
101
+ }
102
+ //#endregion
103
+ export { compareOpportunities, diffOpportunity };