@gearbox-protocol/sdk 15.1.0-next.11 → 15.1.0-next.13

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 (53) hide show
  1. package/dist/cjs/dev/mode-parity/compareOpportunities.js +105 -0
  2. package/dist/cjs/dev/{comparePositions.js → mode-parity/comparePositions.js} +23 -46
  3. package/dist/cjs/dev/mode-parity/compareRules.js +93 -0
  4. package/dist/cjs/dev/{fieldDiff.js → mode-parity/fieldDiff.js} +49 -2
  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/new-sdk/index.js +3 -3
  13. package/dist/cjs/new-sdk/opportunities/OpportunitiesNamespace.js +8 -8
  14. package/dist/cjs/new-sdk/{simulate/SimulateApi.js → prepare/PrepareApi.js} +21 -49
  15. package/dist/cjs/new-sdk/prepare/index.js +4 -0
  16. package/dist/esm/dev/{compareOpportunities.js → mode-parity/compareOpportunities.js} +14 -46
  17. package/dist/esm/dev/{comparePositions.js → mode-parity/comparePositions.js} +16 -39
  18. package/dist/esm/dev/mode-parity/compareRules.js +91 -0
  19. package/dist/esm/dev/{fieldDiff.js → mode-parity/fieldDiff.js} +49 -3
  20. package/dist/esm/dev/mode-parity/scriptUtils.js +121 -0
  21. package/dist/esm/model/compare.schema.js +29 -0
  22. package/dist/esm/model/curators.schema.js +2 -1
  23. package/dist/esm/model/index.js +2 -1
  24. package/dist/esm/model/opportunities.schema.js +13 -12
  25. package/dist/esm/model/positions.schema.js +15 -14
  26. package/dist/esm/model/primitives.schema.js +2 -1
  27. package/dist/esm/new-sdk/index.js +3 -3
  28. package/dist/esm/new-sdk/opportunities/OpportunitiesNamespace.js +8 -8
  29. package/dist/esm/new-sdk/{simulate/SimulateApi.js → prepare/PrepareApi.js} +21 -49
  30. package/dist/esm/new-sdk/prepare/index.js +3 -0
  31. package/dist/types/dev/{compareOpportunities.d.ts → mode-parity/compareOpportunities.d.ts} +5 -5
  32. package/dist/types/dev/{comparePositions.d.ts → mode-parity/comparePositions.d.ts} +5 -5
  33. package/dist/types/dev/mode-parity/compareRules.d.ts +33 -0
  34. package/dist/types/dev/{fieldDiff.d.ts → mode-parity/fieldDiff.d.ts} +47 -5
  35. package/dist/types/dev/mode-parity/scriptUtils.d.ts +47 -0
  36. package/dist/types/model/compare.schema.d.ts +47 -0
  37. package/dist/types/model/index.d.ts +2 -1
  38. package/dist/types/new-sdk/execute/ExecuteApi.d.ts +9 -9
  39. package/dist/types/new-sdk/index.d.ts +4 -4
  40. package/dist/types/new-sdk/opportunities/OpportunitiesNamespace.d.ts +4 -4
  41. package/dist/types/new-sdk/opportunities/types.d.ts +5 -5
  42. package/dist/types/new-sdk/{simulate/SimulateApi.d.ts → prepare/PrepareApi.d.ts} +19 -19
  43. package/dist/types/new-sdk/prepare/index.d.ts +3 -0
  44. package/dist/types/new-sdk/{simulate → prepare}/types.d.ts +35 -61
  45. package/dist/types/sdk/accounts/intents/testing/sdk-mock.d.ts +1 -1
  46. package/dist/types/sdk/accounts/intents/types.d.ts +12 -12
  47. package/package.json +1 -1
  48. package/dist/cjs/dev/compareOpportunities.js +0 -137
  49. package/dist/cjs/new-sdk/simulate/index.js +0 -4
  50. package/dist/esm/new-sdk/simulate/index.js +0 -3
  51. package/dist/types/new-sdk/simulate/index.d.ts +0 -3
  52. /package/dist/cjs/new-sdk/{simulate → prepare}/types.js +0 -0
  53. /package/dist/esm/new-sdk/{simulate → prepare}/types.js +0 -0
@@ -0,0 +1,121 @@
1
+ import { getAlchemyUrl } from "../providers.js";
2
+ import { pino } from "pino";
3
+ //#region src/dev/mode-parity/scriptUtils.ts
4
+ const NETWORKS = [
5
+ "Mainnet",
6
+ "Monad",
7
+ "Plasma",
8
+ "Somnia",
9
+ "Etherlink"
10
+ ];
11
+ const BACKEND_URL = process.env.BACKEND_URL ?? "https://api.gear-dev.dev";
12
+ const TIMEOUT = 48e4;
13
+ function requireEnv(name) {
14
+ const value = process.env[name];
15
+ if (!value) throw new Error(`${name} is required to reach the chains this script reads`);
16
+ return value;
17
+ }
18
+ function rpcUrls() {
19
+ const alchemyKey = requireEnv("ALCHEMY_KEY");
20
+ const alchemy = (network) => {
21
+ const url = getAlchemyUrl(network, alchemyKey);
22
+ if (!url) throw new Error(`Alchemy serves no URL for ${network}`);
23
+ return url;
24
+ };
25
+ return {
26
+ Mainnet: alchemy("Mainnet"),
27
+ Monad: alchemy("Monad"),
28
+ Plasma: alchemy("Plasma"),
29
+ Somnia: requireEnv("SOMNIA_PROVIDER"),
30
+ Etherlink: requireEnv("ETHERLINK_PROVIDER")
31
+ };
32
+ }
33
+ function createLogger() {
34
+ return pino({
35
+ level: process.env.LOG_LEVEL ?? "info",
36
+ formatters: {
37
+ bindings: () => ({}),
38
+ level: (label) => ({ level: label })
39
+ }
40
+ });
41
+ }
42
+ function errorMessage(error) {
43
+ return error instanceof Error ? error.message : String(error);
44
+ }
45
+ /**
46
+ * Runs `fn` over `items` with at most `concurrency` in flight.
47
+ **/
48
+ async function mapPool(items, concurrency, fn) {
49
+ let next = 0;
50
+ const workers = Array.from({ length: Math.min(concurrency, items.length) }, async () => {
51
+ while (true) {
52
+ const index = next;
53
+ next += 1;
54
+ if (index >= items.length) return;
55
+ await fn(items[index]);
56
+ }
57
+ });
58
+ await Promise.all(workers);
59
+ }
60
+ /**
61
+ * Formats a relative difference in bps as a percent, e.g. 12.5 → `"0.125%"`.
62
+ **/
63
+ function formatBpsAsPercent(bps) {
64
+ if (!Number.isFinite(bps)) return "";
65
+ const percent = bps / 100;
66
+ if (percent === 0) return "0%";
67
+ return `${Math.abs(percent) >= 1 ? trimTrailingZeros(percent.toFixed(3)) : trimTrailingZeros(percent.toPrecision(4))}%`;
68
+ }
69
+ function trimTrailingZeros(value) {
70
+ return value.includes(".") ? value.replace(/\.?0+$/, "") : value;
71
+ }
72
+ function worstColumns(worst) {
73
+ return {
74
+ "max diff": worst ? formatBpsAsPercent(worst.bps) : "",
75
+ "worst entity": worst?.id ?? ""
76
+ };
77
+ }
78
+ /**
79
+ * Prints the shared membership table, the fields that differed most often,
80
+ * and any chain that failed to answer.
81
+ **/
82
+ function printCompareSummary(noun, report, extraLines = []) {
83
+ const { summary } = report;
84
+ console.log(`\n${noun} from ${report.backendUrl} vs the chain`);
85
+ console.table(summary.byChain.map((chain) => ({
86
+ chain: chain.chainId,
87
+ onchain: chain.onchainRows,
88
+ offchain: chain.offchainRows,
89
+ matched: chain.matched,
90
+ identical: chain.identical,
91
+ clean: chain.clean,
92
+ differing: chain.differing,
93
+ "only onchain": chain.onlyOnchain,
94
+ "only offchain": chain.onlyOffchain
95
+ })));
96
+ for (const line of extraLines) console.log(line);
97
+ const unexpected = summary.diffsByPath.filter((entry) => entry.unexpected > 0);
98
+ const expected = summary.diffsByPath.filter((entry) => entry.unexpected === 0 && entry.expected > 0);
99
+ if (unexpected.length) {
100
+ console.log("\nunexpected fields that differed most often:");
101
+ console.table(unexpected.slice(0, 25).map((entry) => ({
102
+ field: entry.path,
103
+ unexpected: entry.unexpected,
104
+ expected: entry.expected,
105
+ kinds: entry.kinds.join(", "),
106
+ ...worstColumns(entry.worstUnexpected)
107
+ })));
108
+ }
109
+ if (expected.length) {
110
+ console.log("\nexpected fields (mode-scoped or within tolerance):");
111
+ console.table(expected.slice(0, 25).map((entry) => ({
112
+ field: entry.path,
113
+ rows: entry.expected,
114
+ kinds: entry.kinds.join(", "),
115
+ ...worstColumns(entry.worstExpected)
116
+ })));
117
+ }
118
+ for (const chain of [...report.onchainChains, ...report.offchainChains]) if (chain.status === "error") console.log(`chain ${chain.chainId} failed on ${chain.source}:`, chain.error);
119
+ }
120
+ //#endregion
121
+ export { BACKEND_URL, NETWORKS, TIMEOUT, createLogger, errorMessage, formatBpsAsPercent, mapPool, printCompareSummary, requireEnv, rpcUrls };
@@ -0,0 +1,29 @@
1
+ //#region src/model/compare.schema.ts
2
+ /**
3
+ * Marks a field that only the backend fills.
4
+ **/
5
+ function offchainOnly(schema) {
6
+ return schema.meta({ compare: "offchainOnly" });
7
+ }
8
+ /**
9
+ * Marks a field that only the chain fills.
10
+ **/
11
+ function onchainOnly(schema) {
12
+ return schema.meta({ compare: "onchainOnly" });
13
+ }
14
+ /**
15
+ * Marks a numeric field whose two sources may drift within {@link kind}.
16
+ **/
17
+ function tolerance(schema, kind) {
18
+ return schema.meta({ compare: { tolerance: kind } });
19
+ }
20
+ /**
21
+ * The compare tag registered on a schema, if any.
22
+ **/
23
+ function compareTagOf(schema) {
24
+ const meta = schema.meta();
25
+ if (!meta || !("compare" in meta)) return;
26
+ return meta.compare;
27
+ }
28
+ //#endregion
29
+ export { compareTagOf, offchainOnly, onchainOnly, tolerance };
@@ -1,4 +1,5 @@
1
1
  import { ZodAddress } from "../sdk/utils/zod.js";
2
+ import { offchainOnly } from "./compare.schema.js";
2
3
  import { z } from "zod/v4";
3
4
  //#region src/model/curators.schema.ts
4
5
  /**
@@ -30,7 +31,7 @@ const curatorNameSchema = z.enum([
30
31
  const curatorSchema = z.object({
31
32
  address: ZodAddress(),
32
33
  name: curatorNameSchema.optional(),
33
- url: z.string().nullable()
34
+ url: offchainOnly(z.string().nullable())
34
35
  });
35
36
  //#endregion
36
37
  export { curatorNameSchema, curatorSchema };
@@ -1,4 +1,5 @@
1
1
  import { CHART_METRIC_UNITS, CHART_RANGES, CHART_UNAVAILABLE_CODES, POOL_OPPORTUNITY_CHART_METRICS, POOL_POSITION_CHART_METRICS, STRATEGY_OPPORTUNITY_CHART_METRICS, STRATEGY_POSITION_CHART_METRICS } from "./charts.js";
2
+ import { compareTagOf, offchainOnly, onchainOnly, tolerance } from "./compare.schema.js";
2
3
  import { amountSchema, assetTypeSchema, bpsSchema, chainIdSchema, leverageSchema, timestampSchema, tokenAmountSchema, tokenSchema, txCallSchema } from "./primitives.schema.js";
3
4
  import { chartBundleSchemaFor, chartDenominationSchema, chartMetricSchema, chartQueryCodec, chartQueryParamsSchema, chartQuerySchema, chartRangeSchema, chartSeriesSchema, chartValueSchema, chartWindowSchema, poolOpportunityChartMetricSchema, poolPositionChartMetricSchema, strategyOpportunityChartMetricSchema, strategyPositionChartMetricSchema } from "./charts.schema.js";
4
5
  import "./curators.js";
@@ -16,4 +17,4 @@ import { borrowRateBreakdownSchema, pnlBreakdownSchema, pointsProgramPnLSchema,
16
17
  import "./primitives.js";
17
18
  import "./response.js";
18
19
  import { chainFailedSchema, chainMetadataSchema, chainSucceededSchema, dataSourceSchema, responseMetadataSchema, responseSchema } from "./response.schema.js";
19
- export { CHART_METRIC_UNITS, CHART_RANGES, CHART_UNAVAILABLE_CODES, FILTER_ALL, POOL_OPPORTUNITY_CHART_METRICS, POOL_POSITION_CHART_METRICS, STRATEGY_OPPORTUNITY_CHART_METRICS, STRATEGY_POSITION_CHART_METRICS, amountSchema, apyBreakdownSchema, assetTypeSchema, booleanParamSchema, borrowRateBreakdownSchema, bpsSchema, chainFailedSchema, chainIdSchema, chainMetadataSchema, chainSucceededSchema, chartBundleSchemaFor, chartDenominationSchema, chartMetricSchema, chartQueryCodec, chartQueryParamsSchema, chartQuerySchema, chartRangeSchema, chartSeriesSchema, chartValueSchema, chartWindowSchema, curatorNameSchema, curatorSchema, dataSourceSchema, delayedReceivedAssetSchema, encodeFlag, filterAllSchema, filterable, instantReceivedAssetSchema, isFilterSet, leverageSchema, liquidatableAccountFilterSchema, liquidatableAccountSchema, liquidationApprovalSchema, liquidationDetailsSchema, liquidationPositionId, liquidationPositionSchema, matchesLiquidatableAccountFilter, matchesOpportunityFilter, matchesPositionFilter, noticeKindSchema, noticeSchema, opportunityBaseSchema, opportunityDetailSchema, opportunityFilterQueryParamsSchema, opportunityFilterQuerySchema, opportunityFilterSchema, opportunityId, opportunityKeySchema, opportunityKindSchema, opportunitySchema, pnlBreakdownSchema, pointRewardsSchema, pointsProgramPnLSchema, pointsProgramSchema, pointsRewardsPnLSchema, poolOpportunityChartMetricSchema, poolOpportunityDetailSchema, poolOpportunityId, poolOpportunityKeySchema, poolOpportunitySchema, poolPositionChartMetricSchema, poolPositionId, poolPositionKeySchema, poolPositionSchema, positionCollateralSchema, positionFilterQueryParamsSchema, positionFilterQuerySchema, positionFilterSchema, positionId, positionKeySchema, positionKindSchema, positionSchema, positionTransactionKindSchema, positionTransactionSchema, positionsTotalsSchema, priceFeedDataSchema, priceFeedSummarySchema, quotaAssetSchema, rateCurvePointSchema, rateCurveSchema, receivedAssetSchema, responseMetadataSchema, responseSchema, rewardsPnLSchema, rewardsSchema, strategyOpportunityChartMetricSchema, strategyOpportunityDetailSchema, strategyOpportunityId, strategyOpportunityKeySchema, strategyOpportunitySchema, strategyPositionChartMetricSchema, strategyPositionId, strategyPositionKeySchema, strategyPositionSchema, timestampSchema, tokenAmountSchema, tokenRewardsPnLSchema, tokenRewardsSchema, tokenSchema, txCallSchema };
20
+ export { CHART_METRIC_UNITS, CHART_RANGES, CHART_UNAVAILABLE_CODES, FILTER_ALL, POOL_OPPORTUNITY_CHART_METRICS, POOL_POSITION_CHART_METRICS, STRATEGY_OPPORTUNITY_CHART_METRICS, STRATEGY_POSITION_CHART_METRICS, amountSchema, apyBreakdownSchema, assetTypeSchema, booleanParamSchema, borrowRateBreakdownSchema, bpsSchema, chainFailedSchema, chainIdSchema, chainMetadataSchema, chainSucceededSchema, chartBundleSchemaFor, chartDenominationSchema, chartMetricSchema, chartQueryCodec, chartQueryParamsSchema, chartQuerySchema, chartRangeSchema, chartSeriesSchema, chartValueSchema, chartWindowSchema, compareTagOf, curatorNameSchema, curatorSchema, dataSourceSchema, delayedReceivedAssetSchema, encodeFlag, filterAllSchema, filterable, instantReceivedAssetSchema, isFilterSet, leverageSchema, liquidatableAccountFilterSchema, liquidatableAccountSchema, liquidationApprovalSchema, liquidationDetailsSchema, liquidationPositionId, liquidationPositionSchema, matchesLiquidatableAccountFilter, matchesOpportunityFilter, matchesPositionFilter, noticeKindSchema, noticeSchema, offchainOnly, onchainOnly, opportunityBaseSchema, opportunityDetailSchema, opportunityFilterQueryParamsSchema, opportunityFilterQuerySchema, opportunityFilterSchema, opportunityId, opportunityKeySchema, opportunityKindSchema, opportunitySchema, pnlBreakdownSchema, pointRewardsSchema, pointsProgramPnLSchema, pointsProgramSchema, pointsRewardsPnLSchema, poolOpportunityChartMetricSchema, poolOpportunityDetailSchema, poolOpportunityId, poolOpportunityKeySchema, poolOpportunitySchema, poolPositionChartMetricSchema, poolPositionId, poolPositionKeySchema, poolPositionSchema, positionCollateralSchema, positionFilterQueryParamsSchema, positionFilterQuerySchema, positionFilterSchema, positionId, positionKeySchema, positionKindSchema, positionSchema, positionTransactionKindSchema, positionTransactionSchema, positionsTotalsSchema, priceFeedDataSchema, priceFeedSummarySchema, quotaAssetSchema, rateCurvePointSchema, rateCurveSchema, receivedAssetSchema, responseMetadataSchema, responseSchema, rewardsPnLSchema, rewardsSchema, strategyOpportunityChartMetricSchema, strategyOpportunityDetailSchema, strategyOpportunityId, strategyOpportunityKeySchema, strategyOpportunitySchema, strategyPositionChartMetricSchema, strategyPositionId, strategyPositionKeySchema, strategyPositionSchema, timestampSchema, tokenAmountSchema, tokenRewardsPnLSchema, tokenRewardsSchema, tokenSchema, tolerance, txCallSchema };
@@ -1,4 +1,5 @@
1
1
  import { ZodAddress } from "../sdk/utils/zod.js";
2
+ import { offchainOnly, tolerance } from "./compare.schema.js";
2
3
  import { amountSchema, assetTypeSchema, bpsSchema, chainIdSchema, leverageSchema, timestampSchema, tokenSchema } from "./primitives.schema.js";
3
4
  import { curatorSchema } from "./curators.schema.js";
4
5
  import { isFilterSet } from "./filters.js";
@@ -45,9 +46,9 @@ const rewardsSchema = z.discriminatedUnion("kind", [tokenRewardsSchema, pointRew
45
46
  * {@link ApyBreakdown}
46
47
  **/
47
48
  const apyBreakdownSchema = z.object({
48
- totalApy: bpsSchema.optional(),
49
- organicApy: bpsSchema,
50
- rewards: z.array(rewardsSchema).optional()
49
+ totalApy: offchainOnly(bpsSchema).optional(),
50
+ organicApy: tolerance(bpsSchema, "bps"),
51
+ rewards: offchainOnly(z.array(rewardsSchema)).optional()
51
52
  });
52
53
  /**
53
54
  * {@link OpportunityBase}
@@ -70,9 +71,9 @@ const poolOpportunitySchema = z.object({
70
71
  ...opportunityBaseSchema.shape,
71
72
  kind: z.literal("pool"),
72
73
  pool: ZodAddress(),
73
- totalSupply: amountSchema,
74
- availableLiquidity: amountSchema,
75
- utilization: bpsSchema,
74
+ totalSupply: tolerance(amountSchema, "amount"),
75
+ availableLiquidity: tolerance(amountSchema, "amount"),
76
+ utilization: tolerance(bpsSchema, "bps"),
76
77
  supplyApy: apyBreakdownSchema
77
78
  });
78
79
  /**
@@ -87,12 +88,12 @@ const strategyOpportunitySchema = z.object({
87
88
  liquidationPremium: bpsSchema,
88
89
  liquidationFee: bpsSchema,
89
90
  expirationDate: timestampSchema.nullable(),
90
- collateralApy: apyBreakdownSchema.optional(),
91
- maxLeverageApy: apyBreakdownSchema.optional(),
92
- borrowApy: bpsSchema.optional(),
93
- additionalBorrowApy: bpsSchema.optional(),
94
- totalValue: amountSchema.optional(),
95
- utilization: bpsSchema.optional(),
91
+ collateralApy: offchainOnly(apyBreakdownSchema).optional(),
92
+ maxLeverageApy: offchainOnly(apyBreakdownSchema).optional(),
93
+ borrowApy: tolerance(bpsSchema, "bps").optional(),
94
+ additionalBorrowApy: tolerance(bpsSchema, "bps").optional(),
95
+ totalValue: offchainOnly(amountSchema).optional(),
96
+ utilization: offchainOnly(bpsSchema).optional(),
96
97
  maxBorrowAmount: amountSchema,
97
98
  maxLeverage: leverageSchema
98
99
  });
@@ -1,4 +1,5 @@
1
1
  import { ZodAddress, ZodBigInt, ZodHex } from "../sdk/utils/zod.js";
2
+ import { offchainOnly, onchainOnly, tolerance } from "./compare.schema.js";
2
3
  import { assetTypeSchema, bpsSchema, chainIdSchema, leverageSchema, timestampSchema, tokenAmountSchema, tokenSchema } from "./primitives.schema.js";
3
4
  import { isFilterSet } from "./filters.js";
4
5
  import { booleanParamSchema, encodeFlag, filterable } from "./filters.schema.js";
@@ -55,8 +56,8 @@ const pnlBreakdownSchema = z.object({
55
56
  * {@link PositionCollateral}
56
57
  **/
57
58
  const positionCollateralSchema = z.object({
58
- collateral: tokenAmountSchema,
59
- quota: tokenAmountSchema,
59
+ collateral: tolerance(tokenAmountSchema, "amount"),
60
+ quota: tolerance(tokenAmountSchema, "amount"),
60
61
  withdrawals: z.array(delayedReceivedAssetSchema)
61
62
  });
62
63
  /**
@@ -67,9 +68,9 @@ const poolPositionSchema = z.object({
67
68
  name: z.string(),
68
69
  chainId: chainIdSchema,
69
70
  pool: ZodAddress(),
70
- netValue: tokenAmountSchema,
71
+ netValue: tolerance(tokenAmountSchema, "amount"),
71
72
  apy: apyBreakdownSchema,
72
- pnl: pnlBreakdownSchema.optional()
73
+ pnl: offchainOnly(pnlBreakdownSchema).optional()
73
74
  });
74
75
  /**
75
76
  * {@link BorrowRateBreakdown}
@@ -90,16 +91,16 @@ const strategyPositionSchema = z.object({
90
91
  creditManager: ZodAddress(),
91
92
  creditAccount: ZodAddress(),
92
93
  targetCollateral: tokenSchema.nullable(),
93
- leverage: leverageSchema,
94
- borrowApy: bpsSchema,
95
- netApy: apyBreakdownSchema.optional(),
96
- totalDebt: tokenAmountSchema,
97
- totalValue: tokenAmountSchema,
98
- healthFactor: bpsSchema,
99
- borrowRate: borrowRateBreakdownSchema.optional(),
100
- timeToLiquidation: ZodBigInt().nullable().optional(),
101
- liquidationPrice: ZodBigInt().nullable().optional(),
102
- pnl: pnlBreakdownSchema.optional(),
94
+ leverage: tolerance(leverageSchema, "float"),
95
+ borrowApy: tolerance(bpsSchema, "bps"),
96
+ netApy: offchainOnly(apyBreakdownSchema).optional(),
97
+ totalDebt: tolerance(tokenAmountSchema, "amount"),
98
+ totalValue: tolerance(tokenAmountSchema, "amount"),
99
+ healthFactor: tolerance(bpsSchema, "bps"),
100
+ borrowRate: onchainOnly(borrowRateBreakdownSchema).optional(),
101
+ timeToLiquidation: onchainOnly(ZodBigInt().nullable()).optional(),
102
+ liquidationPrice: onchainOnly(ZodBigInt().nullable()).optional(),
103
+ pnl: offchainOnly(pnlBreakdownSchema).optional(),
103
104
  collaterals: z.array(positionCollateralSchema)
104
105
  });
105
106
  /**
@@ -1,4 +1,5 @@
1
1
  import { ZodAddress, ZodBigInt, ZodHex } from "../sdk/utils/zod.js";
2
+ import { tolerance } from "./compare.schema.js";
2
3
  import { z } from "zod/v4";
3
4
  //#region src/model/primitives.schema.ts
4
5
  /**
@@ -39,7 +40,7 @@ const leverageSchema = z.number().nonnegative();
39
40
  **/
40
41
  const amountSchema = z.object({
41
42
  value: ZodBigInt(),
42
- valueUsd: z.number().nullable()
43
+ valueUsd: tolerance(z.number().nullable(), "usd")
43
44
  });
44
45
  /**
45
46
  * {@link Token}
@@ -9,8 +9,8 @@ import "./errors/index.js";
9
9
  import { AbstractNamespace } from "./AbstractNamespace.js";
10
10
  import { ExecuteApi } from "./execute/ExecuteApi.js";
11
11
  import "./execute/index.js";
12
- import { SimulateApi } from "./simulate/SimulateApi.js";
13
- import "./simulate/index.js";
12
+ import { PrepareApi } from "./prepare/PrepareApi.js";
13
+ import "./prepare/index.js";
14
14
  import { filterResponse } from "./utils/filterResponse.js";
15
15
  import { DEFAULT_MAX_OFFCHAIN_LAG, mergeChainList, mergeChainOne } from "./utils/mergeChains.js";
16
16
  import "./utils/index.js";
@@ -20,4 +20,4 @@ import { PositionsNamespace } from "./positions/PositionsNamespace.js";
20
20
  import "./positions/index.js";
21
21
  import { DEFAULT_MAX_STATE_AGE, GearboxSDK } from "./GearboxSDK.js";
22
22
  import "./types.js";
23
- export { AbstractNamespace, AllSourcesFailedError, DEFAULT_MAX_OFFCHAIN_LAG, DEFAULT_MAX_STATE_AGE, ExecuteApi, GearboxSDK, MissingSourceError, NoSourceServedError, OpportunitiesNamespace, PositionsNamespace, SimulateApi, SourceChainMismatchError, SourceUnavailableError, assertSameChains, everyChainFailed, filterResponse, mergeChainList, mergeChainOne };
23
+ export { AbstractNamespace, AllSourcesFailedError, DEFAULT_MAX_OFFCHAIN_LAG, DEFAULT_MAX_STATE_AGE, ExecuteApi, GearboxSDK, MissingSourceError, NoSourceServedError, OpportunitiesNamespace, PositionsNamespace, PrepareApi, SourceChainMismatchError, SourceUnavailableError, assertSameChains, everyChainFailed, filterResponse, mergeChainList, mergeChainOne };
@@ -5,8 +5,8 @@ import "../errors/index.js";
5
5
  import { AbstractNamespace } from "../AbstractNamespace.js";
6
6
  import { ExecuteApi } from "../execute/ExecuteApi.js";
7
7
  import "../execute/index.js";
8
- import { SimulateApi } from "../simulate/SimulateApi.js";
9
- import "../simulate/index.js";
8
+ import { PrepareApi } from "../prepare/PrepareApi.js";
9
+ import "../prepare/index.js";
10
10
  import { filterResponse } from "../utils/filterResponse.js";
11
11
  import { mergeChainList, mergeChainOne } from "../utils/mergeChains.js";
12
12
  import "../utils/index.js";
@@ -24,19 +24,19 @@ var OpportunitiesNamespace = class extends AbstractNamespace {
24
24
  pool: (onchain, offchain) => mergeChainOne(onchain, offchain, this.maxOffchainLagSeconds),
25
25
  strategy: (onchain, offchain) => mergeChainOne(onchain, offchain, this.maxOffchainLagSeconds)
26
26
  };
27
- #simulate;
27
+ #prepare;
28
28
  #execute;
29
29
  constructor(onchain, offchain, options) {
30
30
  super("Opportunities", onchain?.opportunities, offchain?.opportunities, options);
31
- this.#simulate = onchain && new SimulateApi(onchain, options.ensureFresh);
31
+ this.#prepare = onchain && new PrepareApi(onchain, options.ensureFresh);
32
32
  this.#execute = onchain && new ExecuteApi((chainId) => onchain.chain(chainId));
33
33
  }
34
34
  /**
35
- * {@inheritDoc OpportunitiesOnchainOnly.simulate}
35
+ * {@inheritDoc OpportunitiesOnchainOnly.prepare}
36
36
  **/
37
- get simulate() {
38
- if (!this.#simulate) throw new SourceUnavailableError("Opportunities", "onchain");
39
- return this.#simulate;
37
+ get prepare() {
38
+ if (!this.#prepare) throw new SourceUnavailableError("Opportunities", "onchain");
39
+ return this.#prepare;
40
40
  }
41
41
  /**
42
42
  * {@inheritDoc OpportunitiesOnchainOnly.execute}
@@ -3,9 +3,9 @@ import { MultichainConstruct } from "../../sdk/base/MultichainConstruct.js";
3
3
  import { fetchCreditAccountSlice } from "../../sdk/accounts/intents/utils/credit-account-slice.js";
4
4
  import { CreditAccountOperationsService } from "../../sdk/accounts/intents/index.js";
5
5
  import "../../sdk/index.js";
6
- //#region src/new-sdk/simulate/SimulateApi.ts
6
+ //#region src/new-sdk/prepare/PrepareApi.ts
7
7
  /**
8
- * {@inheritDoc OpportunitiesSimulate}
8
+ * {@inheritDoc OpportunitiesPrepare}
9
9
  *
10
10
  * Holds no state of its own: it owns the mapping from the public,
11
11
  * read-model-shaped request to the engine's intent, and nothing else. All
@@ -17,7 +17,7 @@ import "../../sdk/index.js";
17
17
  * to, hence a chain the SDK does not cover, or one that fails the read, throws
18
18
  * rather than answering with empty metadata.
19
19
  **/
20
- var SimulateApi = class extends MultichainConstruct {
20
+ var PrepareApi = class extends MultichainConstruct {
21
21
  #ensureFresh;
22
22
  constructor(sdk, ensureFresh) {
23
23
  super(sdk);
@@ -28,22 +28,10 @@ var SimulateApi = class extends MultichainConstruct {
28
28
  return super.queryChain(props);
29
29
  }
30
30
  /**
31
- * {@inheritDoc OpportunitiesSimulate.delayed}
31
+ * {@inheritDoc OpportunitiesPrepare.finalize}
32
32
  **/
33
- delayed = {
34
- withdrawStrategy: (position, params) => this.#startDelayedIntent(position, params, {
35
- type: "WITHDRAW",
36
- amount: params.amount,
37
- to: params.to,
38
- tokenOut: params.tokenOut,
39
- sourceToken: params.sourceToken
40
- }),
41
- adjustLeverage: (position, params) => this.#startDelayedIntent(position, params, {
42
- type: "ADJUST_LEVERAGE",
43
- targetLeverage: params.targetLeverage,
44
- token: params.token
45
- }),
46
- finish: (position, params) => this.queryChain({
33
+ async finalize(position, params) {
34
+ return this.queryChain({
47
35
  network: position.chainId,
48
36
  run: async (sdk) => {
49
37
  const intent = resumable(params.intent ?? params.claimable.intent);
@@ -60,10 +48,10 @@ var SimulateApi = class extends MultichainConstruct {
60
48
  quotaReserve: params.quotaReserve
61
49
  });
62
50
  }
63
- })
64
- };
51
+ });
52
+ }
65
53
  /**
66
- * {@inheritDoc OpportunitiesSimulate.deposit}
54
+ * {@inheritDoc OpportunitiesPrepare.deposit}
67
55
  **/
68
56
  deposit(pool, params) {
69
57
  const { marketRegister, pools } = this.sdk.chain(pool.chainId);
@@ -97,7 +85,7 @@ var SimulateApi = class extends MultichainConstruct {
97
85
  };
98
86
  }
99
87
  /**
100
- * {@inheritDoc OpportunitiesSimulate.withdraw}
88
+ * {@inheritDoc OpportunitiesPrepare.withdraw}
101
89
  **/
102
90
  withdraw(pool, params) {
103
91
  const { pools } = this.sdk.chain(pool.chainId);
@@ -129,7 +117,7 @@ var SimulateApi = class extends MultichainConstruct {
129
117
  };
130
118
  }
131
119
  /**
132
- * {@inheritDoc OpportunitiesSimulate.redeem}
120
+ * {@inheritDoc OpportunitiesPrepare.redeem}
133
121
  **/
134
122
  redeem(pool, params) {
135
123
  const { pools } = this.sdk.chain(pool.chainId);
@@ -161,7 +149,7 @@ var SimulateApi = class extends MultichainConstruct {
161
149
  };
162
150
  }
163
151
  /**
164
- * {@inheritDoc OpportunitiesSimulate.openNewStrategy}
152
+ * {@inheritDoc OpportunitiesPrepare.openNewStrategy}
165
153
  **/
166
154
  async openNewStrategy(strategy, params) {
167
155
  return this.queryChain({
@@ -179,7 +167,7 @@ var SimulateApi = class extends MultichainConstruct {
179
167
  });
180
168
  }
181
169
  /**
182
- * {@inheritDoc OpportunitiesSimulate.depositStrategy}
170
+ * {@inheritDoc OpportunitiesPrepare.depositStrategy}
183
171
  **/
184
172
  async depositStrategy(position, params) {
185
173
  return this.#startIntent(position, params, {
@@ -192,7 +180,7 @@ var SimulateApi = class extends MultichainConstruct {
192
180
  });
193
181
  }
194
182
  /**
195
- * {@inheritDoc OpportunitiesSimulate.withdrawStrategy}
183
+ * {@inheritDoc OpportunitiesPrepare.withdrawStrategy}
196
184
  **/
197
185
  async withdrawStrategy(position, params) {
198
186
  return this.#startRoutes(position, params, {
@@ -204,7 +192,7 @@ var SimulateApi = class extends MultichainConstruct {
204
192
  });
205
193
  }
206
194
  /**
207
- * {@inheritDoc OpportunitiesSimulate.maxWithdraw}
195
+ * {@inheritDoc OpportunitiesPrepare.maxWithdraw}
208
196
  **/
209
197
  async maxWithdraw(position) {
210
198
  return this.queryChain({
@@ -216,7 +204,7 @@ var SimulateApi = class extends MultichainConstruct {
216
204
  });
217
205
  }
218
206
  /**
219
- * {@inheritDoc OpportunitiesSimulate.repayStrategy}
207
+ * {@inheritDoc OpportunitiesPrepare.repayStrategy}
220
208
  **/
221
209
  async repayStrategy(position, params) {
222
210
  return this.#startIntent(position, params, {
@@ -227,7 +215,7 @@ var SimulateApi = class extends MultichainConstruct {
227
215
  });
228
216
  }
229
217
  /**
230
- * {@inheritDoc OpportunitiesSimulate.maxRepay}
218
+ * {@inheritDoc OpportunitiesPrepare.maxRepay}
231
219
  **/
232
220
  async maxRepay(position) {
233
221
  return this.queryChain({
@@ -239,7 +227,7 @@ var SimulateApi = class extends MultichainConstruct {
239
227
  });
240
228
  }
241
229
  /**
242
- * {@inheritDoc OpportunitiesSimulate.adjustLeverage}
230
+ * {@inheritDoc OpportunitiesPrepare.adjustLeverage}
243
231
  **/
244
232
  async adjustLeverage(position, params) {
245
233
  return this.#startRoutes(position, params, {
@@ -249,7 +237,7 @@ var SimulateApi = class extends MultichainConstruct {
249
237
  });
250
238
  }
251
239
  /**
252
- * {@inheritDoc OpportunitiesSimulate.addCollateral}
240
+ * {@inheritDoc OpportunitiesPrepare.addCollateral}
253
241
  **/
254
242
  async addCollateral(position, params) {
255
243
  return this.#startIntent(position, params, {
@@ -260,7 +248,7 @@ var SimulateApi = class extends MultichainConstruct {
260
248
  });
261
249
  }
262
250
  /**
263
- * {@inheritDoc OpportunitiesSimulate.withdrawCollateral}
251
+ * {@inheritDoc OpportunitiesPrepare.withdrawCollateral}
264
252
  **/
265
253
  async withdrawCollateral(position, params) {
266
254
  return this.#startIntent(position, params, {
@@ -287,22 +275,6 @@ var SimulateApi = class extends MultichainConstruct {
287
275
  });
288
276
  }
289
277
  /**
290
- * Shared path of the same two flows when only the delayed route is asked for:
291
- * a planner that requests a redemption instead of swapping.
292
- **/
293
- async #startDelayedIntent(position, options, intent) {
294
- return this.queryChain({
295
- network: position.chainId,
296
- run: async (sdk) => service(sdk).startDelayedIntent({
297
- intent,
298
- creditAccount: await slice(sdk, position.creditAccount),
299
- sdk,
300
- slippage: options.slippage,
301
- quotaReserve: options.quotaReserve
302
- })
303
- });
304
- }
305
- /**
306
278
  * Shared path of the five flows that act on an existing account: read the
307
279
  * account, then run the intent through the engine.
308
280
  **/
@@ -357,4 +329,4 @@ function lpRoute(requested, routes) {
357
329
  return options.length === 1 ? options[0] : void 0;
358
330
  }
359
331
  //#endregion
360
- export { SimulateApi };
332
+ export { PrepareApi };
@@ -0,0 +1,3 @@
1
+ import { PrepareApi } from "./PrepareApi.js";
2
+ import "./types.js";
3
+ export { PrepareApi };
@@ -1,10 +1,10 @@
1
- import { ChainId } from "../model/primitives.js";
2
- import { Opportunity, OpportunityId, OpportunityKind } from "../model/opportunities.js";
3
- import { ChainMetadata, DataResponse } from "../model/response.js";
4
- import "../model/index.js";
1
+ import { ChainId } from "../../model/primitives.js";
2
+ import { Opportunity, OpportunityId, OpportunityKind } from "../../model/opportunities.js";
3
+ import { ChainMetadata, DataResponse } from "../../model/response.js";
4
+ import "../../model/index.js";
5
5
  import { ChainCompareCounts, CompareCounts, DiffKind, DiffPathCount, ExpectedDiffReason, FieldDiff } from "./fieldDiff.js";
6
6
  import { Address } from "viem";
7
- //#region src/dev/compareOpportunities.d.ts
7
+ //#region src/dev/mode-parity/compareOpportunities.d.ts
8
8
  /**
9
9
  * Enough of an opportunity to identify it in a report without carrying the
10
10
  * whole row.
@@ -1,10 +1,10 @@
1
- import { ChainId } from "../model/primitives.js";
2
- import { Position, PositionId, PositionKind } from "../model/positions.js";
3
- import { ChainMetadata, DataResponse } from "../model/response.js";
4
- import "../model/index.js";
1
+ import { ChainId } from "../../model/primitives.js";
2
+ import { Position, PositionId, PositionKind } from "../../model/positions.js";
3
+ import { ChainMetadata, DataResponse } from "../../model/response.js";
4
+ import "../../model/index.js";
5
5
  import { ChainCompareCounts, CompareCounts, DiffPathCount, FieldDiff } from "./fieldDiff.js";
6
6
  import { Address } from "viem";
7
- //#region src/dev/comparePositions.d.ts
7
+ //#region src/dev/mode-parity/comparePositions.d.ts
8
8
  /**
9
9
  * Enough of a position to identify it in a report without carrying the whole
10
10
  * row.
@@ -0,0 +1,33 @@
1
+ import { CompareTag } from "../../model/compare.schema.js";
2
+ import { FieldDiff } from "./fieldDiff.js";
3
+ import { z } from "zod/v4";
4
+ //#region src/dev/mode-parity/compareRules.d.ts
5
+ /**
6
+ * Collapsed-path → tag map compiled from a zod schema, e.g.
7
+ * `apy.totalApy` → `"offchainOnly"`, `totalDebt.value` → `{ tolerance: amount }`.
8
+ **/
9
+ type CompareRuleMap = Map<string, CompareTag>;
10
+ /**
11
+ * Walks a schema and records every field that carries compare metadata.
12
+ *
13
+ * `"amount"` on an object (an Amount / TokenAmount) is stored
14
+ * at `<path>.value`; every other tag is stored at the field's own path.
15
+ **/
16
+ declare function compileCompareRules(schema: z.ZodType): CompareRuleMap;
17
+ /**
18
+ * Rules compiled for each row kind, e.g. `"pool"` vs `"strategy"`.
19
+ **/
20
+ type CompareRulesByKind = Record<string, CompareRuleMap>;
21
+ /**
22
+ * Tags one field diff using the rules compiled for its row kind.
23
+ **/
24
+ type TagDiff = (diff: FieldDiff, kind: string) => FieldDiff;
25
+ /**
26
+ * Tags diffs using the rules compiled for each row kind.
27
+ *
28
+ * Mode tags match the path or anything nested under it. Tolerance tags match
29
+ * the path exactly and dispatch on {@link CompareTolerance}.
30
+ **/
31
+ declare function makeTagDiff(rulesByKind: CompareRulesByKind): TagDiff;
32
+ //#endregion
33
+ export { CompareRuleMap, CompareRulesByKind, TagDiff, compileCompareRules, makeTagDiff };