@gearbox-protocol/sdk 14.12.0-next.80 → 14.12.0-next.82

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 (221) hide show
  1. package/dist/cjs/model/filters.js +0 -4
  2. package/dist/cjs/model/filters.schema.js +10 -1
  3. package/dist/cjs/model/index.js +11 -0
  4. package/dist/cjs/model/liquidations.js +1 -1
  5. package/dist/cjs/model/liquidations.schema.js +1 -1
  6. package/dist/cjs/model/opportunities.js +1 -1
  7. package/dist/cjs/model/opportunities.schema.js +6 -13
  8. package/dist/cjs/model/positions.js +1 -1
  9. package/dist/cjs/model/positions.schema.js +33 -1
  10. package/dist/cjs/model/response.js +1 -0
  11. package/dist/cjs/model/response.schema.js +64 -0
  12. package/dist/cjs/new-sdk/AbstractNamespace.js +46 -128
  13. package/dist/cjs/new-sdk/GearboxSDK.js +55 -42
  14. package/dist/cjs/new-sdk/errors/AllSourcesFailedError.js +20 -0
  15. package/dist/cjs/new-sdk/errors/MissingSourceError.js +25 -0
  16. package/dist/cjs/new-sdk/errors/NoSourceServedError.js +20 -0
  17. package/dist/cjs/new-sdk/errors/SourceChainMismatchError.js +34 -0
  18. package/dist/cjs/new-sdk/errors/SourceUnavailableError.js +25 -0
  19. package/dist/cjs/new-sdk/errors/assertSameChains.js +12 -0
  20. package/dist/cjs/new-sdk/errors/everyChainFailed.js +11 -0
  21. package/dist/cjs/new-sdk/errors/index.js +15 -0
  22. package/dist/cjs/new-sdk/index.js +23 -3
  23. package/dist/cjs/new-sdk/opportunities/OpportunitiesNamespace.js +37 -89
  24. package/dist/cjs/new-sdk/positions/PositionsNamespace.js +27 -94
  25. package/dist/cjs/new-sdk/types.js +0 -21
  26. package/dist/cjs/new-sdk/utils/filterResponse.js +21 -0
  27. package/dist/cjs/new-sdk/utils/index.js +6 -0
  28. package/dist/cjs/new-sdk/utils/mergeChains.js +81 -0
  29. package/dist/cjs/new-sdk/utils/types.js +1 -0
  30. package/dist/cjs/offchain/AbstractOffchainNamespace.js +42 -65
  31. package/dist/cjs/offchain/GearboxAPI.js +12 -8
  32. package/dist/cjs/offchain/errors/OffchainInvalidJsonError.js +19 -0
  33. package/dist/cjs/offchain/errors/OffchainNotConfiguredError.js +20 -0
  34. package/dist/cjs/offchain/errors/OffchainNotImplementedError.js +19 -0
  35. package/dist/cjs/offchain/errors/OffchainRequestFailedError.js +24 -0
  36. package/dist/cjs/offchain/errors/OffchainStatusError.js +20 -0
  37. package/dist/cjs/offchain/errors/OffchainTransportError.js +31 -0
  38. package/dist/cjs/offchain/errors/OffchainValidationError.js +26 -0
  39. package/dist/cjs/offchain/errors/backendMessage.js +28 -0
  40. package/dist/cjs/offchain/errors/errorCause.js +12 -0
  41. package/dist/cjs/offchain/errors/index.js +21 -0
  42. package/dist/cjs/offchain/errors/readResponseBody.js +15 -0
  43. package/dist/cjs/offchain/index.js +22 -5
  44. package/dist/cjs/offchain/opportunities/OffchainOpportunities.js +6 -3
  45. package/dist/cjs/offchain/positions/OffchainPositions.js +15 -21
  46. package/dist/cjs/offchain/types.js +0 -75
  47. package/dist/cjs/sdk/MultichainSDK.js +1 -1
  48. package/dist/cjs/sdk/OnchainSDK.js +1 -1
  49. package/dist/cjs/sdk/accounts/credit-account-compressor/CreditAccountCompressor.js +6 -6
  50. package/dist/cjs/sdk/accounts/liquidations/LiquidationsService.js +26 -20
  51. package/dist/cjs/sdk/accounts/liquidations/MultichainLiquidationsService.js +38 -14
  52. package/dist/cjs/sdk/accounts/withdrawal-compressor/AbstractWithdrawalCompressorContract.js +7 -5
  53. package/dist/cjs/sdk/accounts/withdrawal-compressor/WithdrawalCompressorV313Contract.js +3 -2
  54. package/dist/cjs/sdk/base/MultichainConstruct.js +73 -34
  55. package/dist/cjs/sdk/chain/chains.js +11 -0
  56. package/dist/cjs/sdk/chain/index.js +1 -0
  57. package/dist/cjs/sdk/core/index.js +1 -1
  58. package/dist/cjs/sdk/index.js +2 -1
  59. package/dist/cjs/sdk/market/rwa/RWARegistry.js +4 -2
  60. package/dist/cjs/sdk/opportunities/MultichainOpportunitiesService.js +18 -32
  61. package/dist/cjs/sdk/opportunities/OpportunitiesService.js +1 -4
  62. package/dist/cjs/sdk/pools/PoolService.js +2 -1
  63. package/dist/cjs/sdk/positions/MultichainPositionsService.js +6 -29
  64. package/dist/cjs/sdk/positions/PositionsService.js +12 -6
  65. package/dist/esm/dev/AccountOpener.js +1 -1
  66. package/dist/esm/dev/withdrawalUtils.js +1 -1
  67. package/dist/esm/model/filters.js +0 -4
  68. package/dist/esm/model/filters.schema.js +10 -2
  69. package/dist/esm/model/index.js +5 -3
  70. package/dist/esm/model/liquidations.js +1 -1
  71. package/dist/esm/model/liquidations.schema.js +1 -1
  72. package/dist/esm/model/opportunities.js +1 -1
  73. package/dist/esm/model/opportunities.schema.js +4 -11
  74. package/dist/esm/model/positions.js +1 -1
  75. package/dist/esm/model/positions.schema.js +33 -3
  76. package/dist/esm/model/response.js +1 -0
  77. package/dist/esm/model/response.schema.js +58 -0
  78. package/dist/esm/new-sdk/AbstractNamespace.js +46 -128
  79. package/dist/esm/new-sdk/GearboxSDK.js +55 -42
  80. package/dist/esm/new-sdk/errors/AllSourcesFailedError.js +19 -0
  81. package/dist/esm/new-sdk/errors/MissingSourceError.js +24 -0
  82. package/dist/esm/new-sdk/errors/NoSourceServedError.js +19 -0
  83. package/dist/esm/new-sdk/errors/SourceChainMismatchError.js +33 -0
  84. package/dist/esm/new-sdk/errors/SourceUnavailableError.js +24 -0
  85. package/dist/esm/new-sdk/errors/assertSameChains.js +11 -0
  86. package/dist/esm/new-sdk/errors/everyChainFailed.js +10 -0
  87. package/dist/esm/new-sdk/errors/index.js +8 -0
  88. package/dist/esm/new-sdk/index.js +13 -3
  89. package/dist/esm/new-sdk/opportunities/OpportunitiesNamespace.js +38 -90
  90. package/dist/esm/new-sdk/positions/PositionsNamespace.js +28 -95
  91. package/dist/esm/new-sdk/types.js +1 -21
  92. package/dist/esm/new-sdk/utils/filterResponse.js +20 -0
  93. package/dist/esm/new-sdk/utils/index.js +3 -1
  94. package/dist/esm/new-sdk/utils/mergeChains.js +78 -0
  95. package/dist/esm/new-sdk/utils/types.js +1 -0
  96. package/dist/esm/offchain/AbstractOffchainNamespace.js +41 -64
  97. package/dist/esm/offchain/GearboxAPI.js +12 -8
  98. package/dist/esm/offchain/errors/OffchainInvalidJsonError.js +18 -0
  99. package/dist/esm/offchain/errors/OffchainNotConfiguredError.js +19 -0
  100. package/dist/esm/offchain/errors/OffchainNotImplementedError.js +18 -0
  101. package/dist/esm/offchain/errors/OffchainRequestFailedError.js +23 -0
  102. package/dist/esm/offchain/errors/OffchainStatusError.js +19 -0
  103. package/dist/esm/offchain/errors/OffchainTransportError.js +30 -0
  104. package/dist/esm/offchain/errors/OffchainValidationError.js +25 -0
  105. package/dist/esm/offchain/errors/backendMessage.js +27 -0
  106. package/dist/esm/offchain/errors/errorCause.js +11 -0
  107. package/dist/esm/offchain/errors/index.js +11 -0
  108. package/dist/esm/offchain/errors/readResponseBody.js +14 -0
  109. package/dist/esm/offchain/index.js +13 -2
  110. package/dist/esm/offchain/opportunities/OffchainOpportunities.js +6 -3
  111. package/dist/esm/offchain/positions/OffchainPositions.js +15 -21
  112. package/dist/esm/offchain/types.js +1 -72
  113. package/dist/esm/plugins/adapters/contracts/ERC4626AdapterContract.js +1 -1
  114. package/dist/esm/preview/simulate/simulatePoolOperation.js +1 -1
  115. package/dist/esm/preview/trace/extractTransfers.js +1 -1
  116. package/dist/esm/sdk/MultichainSDK.js +1 -1
  117. package/dist/esm/sdk/OnchainSDK.js +1 -1
  118. package/dist/esm/sdk/accounts/CreditAccountsServiceV310.js +2 -2
  119. package/dist/esm/sdk/accounts/credit-account-compressor/CreditAccountCompressor.js +6 -6
  120. package/dist/esm/sdk/accounts/liquidations/LiquidationsService.js +27 -21
  121. package/dist/esm/sdk/accounts/liquidations/MultichainLiquidationsService.js +38 -14
  122. package/dist/esm/sdk/accounts/withdrawal-compressor/AbstractWithdrawalCompressorContract.js +7 -5
  123. package/dist/esm/sdk/accounts/withdrawal-compressor/RedemptionLoggerV310Contract.js +1 -1
  124. package/dist/esm/sdk/accounts/withdrawal-compressor/WithdrawalCompressorV310Contract.js +1 -1
  125. package/dist/esm/sdk/accounts/withdrawal-compressor/WithdrawalCompressorV311Contract.js +1 -1
  126. package/dist/esm/sdk/accounts/withdrawal-compressor/WithdrawalCompressorV313Contract.js +4 -3
  127. package/dist/esm/sdk/base/MultichainConstruct.js +73 -34
  128. package/dist/esm/sdk/base/TokensMeta.js +2 -2
  129. package/dist/esm/sdk/chain/chains.js +11 -1
  130. package/dist/esm/sdk/chain/detectNetwork.js +1 -1
  131. package/dist/esm/sdk/chain/index.js +2 -2
  132. package/dist/esm/sdk/core/createAddressProvider.js +1 -1
  133. package/dist/esm/sdk/core/index.js +1 -1
  134. package/dist/esm/sdk/index.js +3 -3
  135. package/dist/esm/sdk/market/credit/CreditFacadeV310BaseContract.js +1 -1
  136. package/dist/esm/sdk/market/pool/PoolV310Contract.js +1 -1
  137. package/dist/esm/sdk/market/rwa/RWARegistry.js +4 -2
  138. package/dist/esm/sdk/market/zapper/IETHZapperContract.js +1 -1
  139. package/dist/esm/sdk/market/zapper/ZapperContract.js +1 -1
  140. package/dist/esm/sdk/opportunities/MultichainOpportunitiesService.js +18 -32
  141. package/dist/esm/sdk/opportunities/OpportunitiesService.js +1 -4
  142. package/dist/esm/sdk/pools/PoolService.js +3 -2
  143. package/dist/esm/sdk/positions/MultichainPositionsService.js +6 -29
  144. package/dist/esm/sdk/positions/PositionsService.js +12 -6
  145. package/dist/esm/sdk/utils/viem/simulateWithPriceUpdates.js +1 -1
  146. package/dist/types/model/filters.d.ts +9 -3
  147. package/dist/types/model/filters.schema.d.ts +7 -1
  148. package/dist/types/model/index.d.ts +7 -5
  149. package/dist/types/model/liquidations.d.ts +2 -6
  150. package/dist/types/model/liquidations.schema.d.ts +1 -1
  151. package/dist/types/model/opportunities.d.ts +3 -7
  152. package/dist/types/model/opportunities.schema.d.ts +2 -2
  153. package/dist/types/model/positions.d.ts +2 -6
  154. package/dist/types/model/positions.schema.d.ts +32 -2
  155. package/dist/types/model/response.d.ts +105 -0
  156. package/dist/types/model/response.schema.d.ts +98 -0
  157. package/dist/types/new-sdk/AbstractNamespace.d.ts +33 -98
  158. package/dist/types/new-sdk/GearboxSDK.d.ts +10 -25
  159. package/dist/types/new-sdk/errors/AllSourcesFailedError.d.ts +11 -0
  160. package/dist/types/new-sdk/errors/MissingSourceError.d.ts +23 -0
  161. package/dist/types/new-sdk/errors/NoSourceServedError.d.ts +17 -0
  162. package/dist/types/new-sdk/errors/SourceChainMismatchError.d.ts +35 -0
  163. package/dist/types/new-sdk/errors/SourceUnavailableError.d.ts +22 -0
  164. package/dist/types/new-sdk/errors/assertSameChains.d.ts +11 -0
  165. package/dist/types/new-sdk/errors/everyChainFailed.d.ts +10 -0
  166. package/dist/types/new-sdk/errors/index.d.ts +8 -0
  167. package/dist/types/new-sdk/index.d.ts +17 -6
  168. package/dist/types/new-sdk/opportunities/OpportunitiesNamespace.d.ts +19 -40
  169. package/dist/types/new-sdk/opportunities/index.d.ts +2 -2
  170. package/dist/types/new-sdk/opportunities/types.d.ts +80 -26
  171. package/dist/types/new-sdk/positions/PositionsNamespace.d.ts +17 -38
  172. package/dist/types/new-sdk/positions/index.d.ts +2 -2
  173. package/dist/types/new-sdk/positions/types.d.ts +74 -24
  174. package/dist/types/new-sdk/types.d.ts +24 -77
  175. package/dist/types/new-sdk/utils/filterResponse.d.ts +16 -0
  176. package/dist/types/new-sdk/utils/history.d.ts +6 -36
  177. package/dist/types/new-sdk/utils/index.d.ts +5 -2
  178. package/dist/types/new-sdk/utils/mergeChains.d.ts +20 -0
  179. package/dist/types/new-sdk/utils/types.d.ts +11 -0
  180. package/dist/types/offchain/AbstractOffchainNamespace.d.ts +21 -28
  181. package/dist/types/offchain/GearboxAPI.d.ts +13 -9
  182. package/dist/types/offchain/errors/OffchainInvalidJsonError.d.ts +16 -0
  183. package/dist/types/offchain/errors/OffchainNotConfiguredError.d.ts +16 -0
  184. package/dist/types/offchain/errors/OffchainNotImplementedError.d.ts +15 -0
  185. package/dist/types/offchain/errors/OffchainRequestFailedError.d.ts +12 -0
  186. package/dist/types/offchain/errors/OffchainStatusError.d.ts +16 -0
  187. package/dist/types/offchain/errors/OffchainTransportError.d.ts +43 -0
  188. package/dist/types/offchain/errors/OffchainValidationError.d.ts +21 -0
  189. package/dist/types/offchain/errors/backendMessage.d.ts +9 -0
  190. package/dist/types/offchain/errors/errorCause.d.ts +22 -0
  191. package/dist/types/offchain/errors/index.d.ts +11 -0
  192. package/dist/types/offchain/errors/readResponseBody.d.ts +8 -0
  193. package/dist/types/offchain/index.d.ts +13 -2
  194. package/dist/types/offchain/opportunities/OffchainOpportunities.d.ts +9 -8
  195. package/dist/types/offchain/positions/OffchainPositions.d.ts +9 -15
  196. package/dist/types/offchain/types.d.ts +7 -88
  197. package/dist/types/sdk/accounts/credit-account-compressor/types.d.ts +4 -0
  198. package/dist/types/sdk/accounts/index.d.ts +3 -3
  199. package/dist/types/sdk/accounts/liquidations/LiquidationsService.d.ts +2 -2
  200. package/dist/types/sdk/accounts/liquidations/MultichainLiquidationsService.d.ts +15 -14
  201. package/dist/types/sdk/accounts/liquidations/index.d.ts +2 -2
  202. package/dist/types/sdk/accounts/liquidations/types.d.ts +32 -16
  203. package/dist/types/sdk/accounts/withdrawal-compressor/AbstractWithdrawalCompressorContract.d.ts +4 -4
  204. package/dist/types/sdk/accounts/withdrawal-compressor/WithdrawalCompressorV313Contract.d.ts +2 -2
  205. package/dist/types/sdk/accounts/withdrawal-compressor/index.d.ts +2 -2
  206. package/dist/types/sdk/accounts/withdrawal-compressor/types.d.ts +26 -4
  207. package/dist/types/sdk/base/MultichainConstruct.d.ts +63 -14
  208. package/dist/types/sdk/base/index.d.ts +2 -2
  209. package/dist/types/sdk/chain/chains.d.ts +10 -2
  210. package/dist/types/sdk/chain/index.d.ts +2 -2
  211. package/dist/types/sdk/index.d.ts +7 -7
  212. package/dist/types/sdk/market/MarketSuite.d.ts +1 -1
  213. package/dist/types/sdk/market/rwa/RWARegistry.d.ts +2 -1
  214. package/dist/types/sdk/opportunities/MultichainOpportunitiesService.d.ts +13 -16
  215. package/dist/types/sdk/pools/types.d.ts +4 -0
  216. package/dist/types/sdk/positions/MultichainPositionsService.d.ts +2 -12
  217. package/dist/types/sdk/positions/index.d.ts +2 -2
  218. package/dist/types/sdk/positions/types.d.ts +14 -5
  219. package/dist/types/sdk/types/index.d.ts +2 -2
  220. package/dist/types/sdk/types/multichain.d.ts +16 -36
  221. package/package.json +1 -1
@@ -2,117 +2,50 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_model_positions = require("../../model/positions.js");
3
3
  require("../../model/index.js");
4
4
  const require_new_sdk_AbstractNamespace = require("../AbstractNamespace.js");
5
+ const require_new_sdk_utils_filterResponse = require("../utils/filterResponse.js");
6
+ const require_new_sdk_utils_mergeChains = require("../utils/mergeChains.js");
7
+ require("../utils/index.js");
5
8
  //#region src/new-sdk/positions/PositionsNamespace.ts
6
9
  /**
7
- * Fields the backend owns even when the chain also fills them.
8
- *
9
- * The yield and PnL groups are derived from a position's history and from
10
- * incentive programs, neither of which the chain has. `targetCollateral` is
11
- * there for a subtler reason: the read model defines it as the collateral the
12
- * position was opened into, which only the backend can know, while the chain
13
- * approximates it with the dominant collateral held right now.
14
- **/
15
- const OFFCHAIN_OWNED_FIELDS = /* @__PURE__ */ new Set([
16
- "apy",
17
- "netApy",
18
- "pnl",
19
- "targetCollateral"
20
- ]);
21
- /**
22
- * The `positions` namespace of the combined SDK.
23
- *
24
- * A stateless router over the two sources, see {@link AbstractNamespace} for the
25
- * routing itself. What is specific to positions is the reads below and the merge
26
- * policy at the bottom of the class.
27
- *
28
- * The class implements the methods of every mode; {@link GearboxSDK} exposes it
29
- * as its mode's slice of {@link PositionsByMode}, so calling a method the mode
30
- * does not have is a compile error rather than a runtime one.
10
+ * The `positions` namespace of a {@link GearboxSDK}, see
11
+ * {@link PositionsByMode} for what each mode offers.
31
12
  **/
32
13
  var PositionsNamespace = class extends require_new_sdk_AbstractNamespace.AbstractNamespace {
33
- constructor(onchain, offchain, logger) {
34
- super("Positions", onchain, offchain, logger);
14
+ /**
15
+ * {@inheritDoc PositionsBase.merge}
16
+ **/
17
+ merge = { list: (onchain, offchain) => require_new_sdk_utils_mergeChains.mergeChainList(onchain, offchain, this.maxOffchainLagSeconds) };
18
+ constructor(onchain, offchain, options) {
19
+ super("Positions", onchain?.positions, offchain?.positions, options);
35
20
  }
36
21
  /**
37
22
  * {@inheritDoc PositionsBase.list}
38
23
  **/
39
24
  async list(wallet, filter) {
40
- return this.readList("list positions", async (sdk) => {
41
- const { result, meta } = await sdk.positions.list({
25
+ return this.merged("list positions", {
26
+ fromChain: (source) => source.list({
42
27
  wallet,
43
28
  filter
44
- });
45
- return {
46
- value: result,
47
- chains: meta
48
- };
49
- }, (api) => api.positions.list(wallet, filter));
50
- }
51
- history(key) {
52
- return { chart: (metric, range) => this.#chart(key, metric, range) };
29
+ }),
30
+ fromBackend: (source) => source.list({
31
+ wallet,
32
+ filter
33
+ }),
34
+ merge: this.merge.list
35
+ });
53
36
  }
54
37
  /**
55
- * Reads one chart of one position from the backend.
56
- *
57
- * The metric a caller may name is gated by the reader's type, so the kind of
58
- * the key is not re-checked here.
38
+ * {@inheritDoc PositionsBase.filter}
59
39
  **/
60
- async #chart(key, metric, range) {
61
- const { result, meta } = await this.readOffchain(`get ${metric} history`, (api) => api.positions.getHistory({
40
+ filter(response, filter) {
41
+ return require_new_sdk_utils_filterResponse.filterResponse(response, filter, require_model_positions.matchesPositionFilter);
42
+ }
43
+ history(key) {
44
+ return { chart: (metric, range) => this.offchain.getHistory({
62
45
  position: key,
63
46
  range,
64
47
  metric
65
- }), {
66
- metric,
67
- points: [],
68
- metadata: {}
69
- });
70
- return {
71
- data: result.points,
72
- metadata: {
73
- ...result.metadata,
74
- source: meta
75
- }
76
- };
77
- }
78
- /**
79
- * Merges the two versions of one position.
80
- *
81
- * The chain wins every field it fills; the backend fills the rest and owns
82
- * {@link OFFCHAIN_OWNED_FIELDS}.
83
- *
84
- * The rule is onchain-first, field-wise, and never deeper than one level: a
85
- * group like `totalValue` or `apy` is taken whole from one source, so a row
86
- * never mixes an on-chain token amount with a backend dollar value derived
87
- * from a different block.
88
- **/
89
- mergeOne(onchain, offchain) {
90
- const merged = { ...onchain };
91
- for (const [field, value] of Object.entries(offchain)) {
92
- if (value === void 0) continue;
93
- if (OFFCHAIN_OWNED_FIELDS.has(field) || merged[field] === void 0) merged[field] = value;
94
- }
95
- return merged;
96
- }
97
- /**
98
- * Unions the two lists by canonical position id.
99
- *
100
- * Rows present in both are merged by {@link PositionsNamespace.mergeOne}.
101
- * Rows only the backend knows are appended: a chain the SDK does not cover,
102
- * or a market it has not loaded, must not hide a position the wallet actually
103
- * holds.
104
- **/
105
- mergeList(onchain, offchain) {
106
- const byId = /* @__PURE__ */ new Map();
107
- for (const row of onchain) byId.set(require_model_positions.positionId(row), row);
108
- const extra = [];
109
- for (const row of offchain) {
110
- const id = require_model_positions.positionId(row);
111
- const existing = byId.get(id);
112
- if (existing) byId.set(id, this.mergeOne(existing, row));
113
- else extra.push(row);
114
- }
115
- return [...byId.values(), ...extra];
48
+ }) };
116
49
  }
117
50
  };
118
51
  //#endregion
@@ -1,22 +1 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- //#region src/new-sdk/types.ts
3
- /**
4
- * Thrown when a read had sources to ask and none of them answered.
5
- *
6
- * A read that partially succeeded never throws: it returns what it has and
7
- * reports the rest in {@link SourceMeta}.
8
- **/
9
- var AllSourcesFailedError = class extends Error {
10
- /**
11
- * Outcome of every source the failed read asked.
12
- **/
13
- meta;
14
- constructor(action, meta) {
15
- const reasons = [...meta.chains.filter((c) => c.status === "error").map((c) => `${c.network}: ${c.error}`), ...meta.offchain?.status === "error" ? [`offchain: ${meta.offchain.error}`] : []];
16
- super(`cannot ${action}, every source failed (${reasons.join("; ")})`);
17
- this.name = "AllSourcesFailedError";
18
- this.meta = meta;
19
- }
20
- };
21
- //#endregion
22
- exports.AllSourcesFailedError = AllSourcesFailedError;
@@ -0,0 +1,21 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ //#region src/new-sdk/utils/filterResponse.ts
3
+ /**
4
+ * Narrows an already-read list, rows and metadata alike. `undefined` passes
5
+ * through, so a read still in flight stays that way.
6
+ *
7
+ * @typeParam T - Row type.
8
+ * @typeParam F - Filter type.
9
+ * @param matches - Whether one row satisfies the filter, e.g.
10
+ * `matchesOpportunityFilter`.
11
+ **/
12
+ function filterResponse(response, filter, matches) {
13
+ if (!response) return;
14
+ const chainIds = filter?.chainIds;
15
+ return {
16
+ data: response.data.filter((row) => matches(row, filter)),
17
+ meta: { chains: chainIds ? response.meta.chains.filter((chain) => chainIds.includes(chain.chainId)) : response.meta.chains }
18
+ };
19
+ }
20
+ //#endregion
21
+ exports.filterResponse = filterResponse;
@@ -1,2 +1,8 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_new_sdk_utils_filterResponse = require("./filterResponse.js");
2
3
  require("./history.js");
4
+ const require_new_sdk_utils_mergeChains = require("./mergeChains.js");
5
+ exports.DEFAULT_MAX_OFFCHAIN_LAG = require_new_sdk_utils_mergeChains.DEFAULT_MAX_OFFCHAIN_LAG;
6
+ exports.filterResponse = require_new_sdk_utils_filterResponse.filterResponse;
7
+ exports.mergeChainList = require_new_sdk_utils_mergeChains.mergeChainList;
8
+ exports.mergeChainOne = require_new_sdk_utils_mergeChains.mergeChainOne;
@@ -0,0 +1,81 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_new_sdk_errors_NoSourceServedError = require("../errors/NoSourceServedError.js");
3
+ require("../errors/index.js");
4
+ //#region src/new-sdk/utils/mergeChains.ts
5
+ /**
6
+ * How many seconds the backend may lag the chain and still be used.
7
+ **/
8
+ const DEFAULT_MAX_OFFCHAIN_LAG = 120;
9
+ /**
10
+ * Merges two lists chain by chain: a chain is served by the backend when it is
11
+ * within `maxLagSeconds` of the chain, by the chain otherwise, and reported as
12
+ * an error when neither source succeeded.
13
+ **/
14
+ function mergeChainList(onchain, offchain, maxLagSeconds = 120) {
15
+ if (!onchain && !offchain) return;
16
+ const fromOnchain = /* @__PURE__ */ new Map();
17
+ for (const chain of onchain?.meta.chains ?? []) fromOnchain.set(chain.chainId, chain);
18
+ const fromOffchain = /* @__PURE__ */ new Map();
19
+ for (const chain of offchain?.meta.chains ?? []) fromOffchain.set(chain.chainId, chain);
20
+ const data = [];
21
+ const chains = [];
22
+ for (const chainId of /* @__PURE__ */ new Set([...fromOnchain.keys(), ...fromOffchain.keys()])) {
23
+ const onchainMeta = fromOnchain.get(chainId);
24
+ const offchainMeta = fromOffchain.get(chainId);
25
+ const winner = pickSource(onchainMeta, offchainMeta, maxLagSeconds);
26
+ if (winner === "onchain" && onchain && onchainMeta) {
27
+ data.push(...onchain.data.filter((row) => row.chainId === chainId));
28
+ chains.push(onchainMeta);
29
+ } else if (winner === "offchain" && offchain && offchainMeta) {
30
+ data.push(...offchain.data.filter((row) => row.chainId === chainId));
31
+ chains.push(offchainMeta);
32
+ } else chains.push(failedChain(chainId, onchainMeta, offchainMeta));
33
+ }
34
+ return {
35
+ data,
36
+ meta: { chains }
37
+ };
38
+ }
39
+ /**
40
+ * Merges two versions of one entity under the same freshness rule as
41
+ * {@link mergeChainList}, returning the winning response whole.
42
+ **/
43
+ function mergeChainOne(onchain, offchain, maxLagSeconds = 120) {
44
+ switch (pickSource(onchain?.meta.chains[0], offchain?.meta.chains[0], maxLagSeconds)) {
45
+ case "onchain": return onchain;
46
+ case "offchain": return offchain;
47
+ default: return;
48
+ }
49
+ }
50
+ /**
51
+ * Which side serves one chain, or `undefined` when neither can.
52
+ **/
53
+ function pickSource(onchain, offchain, maxLagSeconds) {
54
+ const onchainOk = onchain?.status === "success" ? onchain : void 0;
55
+ const offchainOk = offchain?.status === "success" ? offchain : void 0;
56
+ if (onchainOk && offchainOk) return isFresh(onchainOk, offchainOk, maxLagSeconds) ? "offchain" : "onchain";
57
+ if (onchainOk) return "onchain";
58
+ if (offchainOk) return "offchain";
59
+ }
60
+ /**
61
+ * Whether the backend is close enough behind the chain to be preferred.
62
+ **/
63
+ function isFresh(onchain, offchain, maxLagSeconds) {
64
+ return offchain.timestamp >= onchain.timestamp - maxLagSeconds;
65
+ }
66
+ /**
67
+ * Metadata for a chain neither source served.
68
+ **/
69
+ function failedChain(chainId, onchain, offchain) {
70
+ if (!onchain || !offchain) return onchain ?? offchain;
71
+ const reasons = [onchain, offchain].map((chain) => chain.status === "error" ? chain.error : void 0).filter((reason) => !!reason);
72
+ return {
73
+ chainId,
74
+ status: "error",
75
+ error: reasons.length === 1 ? reasons[0] : new require_new_sdk_errors_NoSourceServedError.NoSourceServedError(chainId, reasons)
76
+ };
77
+ }
78
+ //#endregion
79
+ exports.DEFAULT_MAX_OFFCHAIN_LAG = DEFAULT_MAX_OFFCHAIN_LAG;
80
+ exports.mergeChainList = mergeChainList;
81
+ exports.mergeChainOne = mergeChainOne;
@@ -0,0 +1 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
@@ -1,26 +1,31 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_model_history_schema = require("../model/history.schema.js");
3
- const require_offchain_types = require("./types.js");
3
+ const require_model_response_schema = require("../model/response.schema.js");
4
+ const require_offchain_errors_OffchainInvalidJsonError = require("./errors/OffchainInvalidJsonError.js");
5
+ const require_offchain_errors_OffchainNotConfiguredError = require("./errors/OffchainNotConfiguredError.js");
6
+ const require_offchain_errors_OffchainRequestFailedError = require("./errors/OffchainRequestFailedError.js");
7
+ const require_offchain_errors_OffchainStatusError = require("./errors/OffchainStatusError.js");
8
+ const require_offchain_errors_OffchainValidationError = require("./errors/OffchainValidationError.js");
9
+ const require_offchain_errors_readResponseBody = require("./errors/readResponseBody.js");
10
+ require("./errors/index.js");
4
11
  let zod_v4 = require("zod/v4");
5
12
  //#region src/offchain/AbstractOffchainNamespace.ts
6
13
  const DEFAULT_TIMEOUT = 3e4;
7
14
  /**
8
- * Common logic of every {@link GearboxAPI} namespace.
9
- *
10
- * A namespace is a set of routes: it knows which path answers which read and
11
- * which schema describes the payload. Everything under that — where the
12
- * backend is, how long a request may take, how a failure is reported and how a
13
- * response becomes read model values — lives here, so a namespace holds
15
+ * Base class of every {@link GearboxAPI} namespace: issues the requests,
16
+ * decodes the responses and reports the failures, so that a namespace holds
14
17
  * nothing but its routes.
15
18
  **/
16
19
  var AbstractOffchainNamespace = class {
17
20
  logger;
18
21
  #baseUrl;
22
+ #chainIds;
19
23
  #timeout;
20
24
  constructor(name, options) {
21
- this.#baseUrl = options?.baseUrl?.replace(/\/+$/, "");
22
- this.#timeout = options?.timeout ?? DEFAULT_TIMEOUT;
23
- this.logger = options?.logger?.child?.({ name }) ?? options?.logger;
25
+ this.#baseUrl = options.baseUrl?.replace(/\/+$/, "");
26
+ this.#chainIds = [...options.chainIds];
27
+ this.#timeout = options.timeout ?? DEFAULT_TIMEOUT;
28
+ this.logger = options.logger?.child?.({ name }) ?? options.logger;
24
29
  }
25
30
  /**
26
31
  * Base URL every read of this namespace is issued against.
@@ -29,36 +34,39 @@ var AbstractOffchainNamespace = class {
29
34
  return this.#baseUrl;
30
35
  }
31
36
  /**
32
- * Reads one endpoint and decodes its payload.
33
- *
34
- * The envelope is built here rather than by the caller: the status is
35
- * `"success"` whenever this returns at all, because anything else has
36
- * already thrown.
37
+ * Chains one read covers: the configured ones, narrowed by the filter when it
38
+ * names any. A filter naming a chain this client does not cover narrows
39
+ * nothing.
40
+ **/
41
+ scopedChainIds(filter) {
42
+ const wanted = filter?.chainIds;
43
+ return wanted ? this.#chainIds.filter((chainId) => wanted.includes(chainId)) : [...this.#chainIds];
44
+ }
45
+ /**
46
+ * Reads one endpoint and decodes its payload. Timeouts, non-2xx answers and
47
+ * schema skew throw, since none of them is a {@link DataResponse}.
37
48
  **/
38
49
  async get(request) {
39
50
  const url = this.#url(request.path, request.query);
40
- this.logger?.debug(`reading ${url}`);
41
51
  const payload = await this.#fetchJson(url);
42
- const parsed = request.schema.safeParse(payload);
52
+ const parsed = require_model_response_schema.responseSchema(request.schema).safeParse(payload);
43
53
  if (!parsed.success) {
44
- this.logger?.error({
45
- url,
46
- issues: parsed.error.issues
47
- }, "offchain response does not match the read model");
48
- throw new require_offchain_types.OffchainValidationError(url, parsed.error.issues);
54
+ const error = new require_offchain_errors_OffchainValidationError.OffchainValidationError(url, parsed.error);
55
+ this.logger?.error(error, "offchain response does not match the read model");
56
+ throw error;
49
57
  }
58
+ const { data, meta } = parsed.data;
50
59
  return {
51
- result: parsed.data,
52
- meta: { status: "success" }
60
+ data,
61
+ meta: { chains: meta.chains.map((chain) => ({
62
+ ...chain,
63
+ source: "offchain"
64
+ })) }
53
65
  };
54
66
  }
55
67
  /**
56
- * Reads one historical series.
57
- *
58
- * The requested metric is pinned in the schema, which is what upholds the
59
- * `HistorySeries<M>` a caller gets back: a response carrying a different
60
- * metric is version skew and fails validation like any other mismatch,
61
- * rather than being cast into the requested shape.
68
+ * Reads one historical series. A response carrying a metric other than the
69
+ * requested one fails validation.
62
70
  **/
63
71
  async readHistory(request) {
64
72
  return this.get({
@@ -71,7 +79,7 @@ var AbstractOffchainNamespace = class {
71
79
  * Full URL of a read, with the conditions that do not narrow left out.
72
80
  **/
73
81
  #url(path, query) {
74
- if (!this.#baseUrl) throw new require_offchain_types.OffchainNotConfiguredError(path);
82
+ if (!this.#baseUrl) throw new require_offchain_errors_OffchainNotConfiguredError.OffchainNotConfiguredError(path);
75
83
  const url = new URL(`${this.#baseUrl}${path}`);
76
84
  for (const [key, value] of Object.entries(query ?? {})) if (value !== void 0) url.searchParams.set(key, value);
77
85
  return url.toString();
@@ -87,46 +95,15 @@ var AbstractOffchainNamespace = class {
87
95
  signal: AbortSignal.timeout(this.#timeout)
88
96
  });
89
97
  } catch (error) {
90
- throw new require_offchain_types.OffchainTransportError(url, describe(error));
98
+ throw new require_offchain_errors_OffchainRequestFailedError.OffchainRequestFailedError(url, error);
91
99
  }
92
- if (!response.ok) throw new require_offchain_types.OffchainTransportError(url, await failureReason(response), response.status);
100
+ if (!response.ok) throw new require_offchain_errors_OffchainStatusError.OffchainStatusError(url, response.status, await require_offchain_errors_readResponseBody.readResponseBody(response));
93
101
  try {
94
102
  return await response.json();
95
103
  } catch (error) {
96
- throw new require_offchain_types.OffchainTransportError(url, `the body is not JSON (${describe(error)})`, response.status);
104
+ throw new require_offchain_errors_OffchainInvalidJsonError.OffchainInvalidJsonError(url, response.status, error);
97
105
  }
98
106
  }
99
107
  };
100
- /**
101
- * Why a non-2xx response failed, in the backend's own words when it said.
102
- **/
103
- async function failureReason(response) {
104
- const status = `the backend answered ${response.status}`;
105
- let body;
106
- try {
107
- body = await response.text();
108
- } catch {
109
- return status;
110
- }
111
- const message = backendMessage(body) ?? body.trim();
112
- return message ? `${status}: ${truncate(message)}` : status;
113
- }
114
- /**
115
- * The `message` of a Gearbox backend error body, or nothing when the body is
116
- * not one.
117
- **/
118
- function backendMessage(body) {
119
- try {
120
- const parsed = JSON.parse(body);
121
- if (typeof parsed === "object" && parsed !== null && "message" in parsed && typeof parsed.message === "string") return parsed.message;
122
- } catch {}
123
- }
124
- function describe(error) {
125
- if (error instanceof Error) return error.name === "TimeoutError" ? "the request timed out" : error.message;
126
- return String(error);
127
- }
128
- function truncate(text) {
129
- return text.length > 200 ? `${text.slice(0, 200)}…` : text;
130
- }
131
108
  //#endregion
132
109
  exports.AbstractOffchainNamespace = AbstractOffchainNamespace;
@@ -11,18 +11,21 @@ require("./positions/index.js");
11
11
  * call reads the same way against either source:
12
12
  *
13
13
  * ```ts
14
- * const api = new GearboxAPI({ baseUrl: "https://api.gearbox.fi" });
15
- * const { result } = await api.opportunities.list({ kind: "strategy" });
14
+ * const api = new GearboxAPI({
15
+ * baseUrl: "https://api.gearbox.fi",
16
+ * chainIds: [1, 42161],
17
+ * });
18
+ * const { data } = await api.opportunities.list({ kind: "strategy" });
16
19
  * ```
17
20
  *
18
- * The backend imports the read model from this package and its endpoints
19
- * return those types directly, so there is no wire DTO layer here only
20
- * transport and schema validation.
21
- *
22
- * The transport is not implemented yet; see {@link OffchainOpportunities} and
23
- * {@link OffchainPositions} for what each stubbed endpoint currently answers.
21
+ * Every read is scoped to {@link GearboxAPIOptions.chainIds}, so a client only
22
+ * ever sees the chains it was built for even though the backend knows more.
24
23
  **/
25
24
  var GearboxAPI = class {
25
+ /**
26
+ * Chains every read of this client is scoped to.
27
+ **/
28
+ chainIds;
26
29
  /**
27
30
  * Namespace for pool and strategy opportunities.
28
31
  **/
@@ -32,6 +35,7 @@ var GearboxAPI = class {
32
35
  **/
33
36
  positions;
34
37
  constructor(options) {
38
+ this.chainIds = [...options.chainIds];
35
39
  this.opportunities = new require_offchain_opportunities_OffchainOpportunities.OffchainOpportunities(options);
36
40
  this.positions = new require_offchain_positions_OffchainPositions.OffchainPositions(options);
37
41
  }
@@ -0,0 +1,19 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_offchain_errors_OffchainTransportError = require("./OffchainTransportError.js");
3
+ //#region src/offchain/errors/OffchainInvalidJsonError.ts
4
+ /**
5
+ * Thrown when the backend answered in the 2xx range with a body that is not
6
+ * JSON, so there is nothing to validate against the read model.
7
+ **/
8
+ var OffchainInvalidJsonError = class extends require_offchain_errors_OffchainTransportError.OffchainTransportError {
9
+ name = "OffchainInvalidJsonError";
10
+ constructor(url, status, cause) {
11
+ super("The Gearbox backend answered with a body that is not JSON.", {
12
+ url,
13
+ status,
14
+ cause
15
+ });
16
+ }
17
+ };
18
+ //#endregion
19
+ exports.OffchainInvalidJsonError = OffchainInvalidJsonError;
@@ -0,0 +1,20 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ let viem = require("viem");
3
+ //#region src/offchain/errors/OffchainNotConfiguredError.ts
4
+ /**
5
+ * Thrown when a read is issued against a client that was never told where the
6
+ * backend is.
7
+ **/
8
+ var OffchainNotConfiguredError = class extends viem.BaseError {
9
+ name = "OffchainNotConfiguredError";
10
+ /**
11
+ * Path that was read, below the base URL that is missing.
12
+ **/
13
+ path;
14
+ constructor(path) {
15
+ super("No baseUrl was configured for the Gearbox backend.", { metaMessages: [`Path: ${path}`] });
16
+ this.path = path;
17
+ }
18
+ };
19
+ //#endregion
20
+ exports.OffchainNotConfiguredError = OffchainNotConfiguredError;
@@ -0,0 +1,19 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ let viem = require("viem");
3
+ //#region src/offchain/errors/OffchainNotImplementedError.ts
4
+ /**
5
+ * Thrown by the endpoints that are not implemented yet.
6
+ **/
7
+ var OffchainNotImplementedError = class extends viem.BaseError {
8
+ name = "OffchainNotImplementedError";
9
+ /**
10
+ * Endpoint that was asked for.
11
+ **/
12
+ endpoint;
13
+ constructor(endpoint) {
14
+ super("This Gearbox backend endpoint is not implemented yet.", { metaMessages: [`Endpoint: ${endpoint}`] });
15
+ this.endpoint = endpoint;
16
+ }
17
+ };
18
+ //#endregion
19
+ exports.OffchainNotImplementedError = OffchainNotImplementedError;
@@ -0,0 +1,24 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_offchain_errors_OffchainTransportError = require("./OffchainTransportError.js");
3
+ //#region src/offchain/errors/OffchainRequestFailedError.ts
4
+ /**
5
+ * Thrown when a request to the backend never completed: the network was down,
6
+ * or it took longer than {@link GearboxAPIOptions.timeout}.
7
+ **/
8
+ var OffchainRequestFailedError = class extends require_offchain_errors_OffchainTransportError.OffchainTransportError {
9
+ name = "OffchainRequestFailedError";
10
+ constructor(url, cause) {
11
+ super(timedOut(cause) ? "The request to the Gearbox backend timed out." : "The request to the Gearbox backend failed.", {
12
+ url,
13
+ cause
14
+ });
15
+ }
16
+ };
17
+ /**
18
+ * Whether a caught value is the rejection `AbortSignal.timeout` produces.
19
+ **/
20
+ function timedOut(error) {
21
+ return error instanceof Error && error.name === "TimeoutError";
22
+ }
23
+ //#endregion
24
+ exports.OffchainRequestFailedError = OffchainRequestFailedError;
@@ -0,0 +1,20 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_offchain_errors_backendMessage = require("./backendMessage.js");
3
+ const require_offchain_errors_OffchainTransportError = require("./OffchainTransportError.js");
4
+ //#region src/offchain/errors/OffchainStatusError.ts
5
+ /**
6
+ * Thrown when the backend answered with a status outside the 2xx range. What it
7
+ * said about it, when it said anything, is the `details` of the error.
8
+ **/
9
+ var OffchainStatusError = class extends require_offchain_errors_OffchainTransportError.OffchainTransportError {
10
+ name = "OffchainStatusError";
11
+ constructor(url, status, body) {
12
+ super(`The Gearbox backend answered ${status}.`, {
13
+ url,
14
+ status,
15
+ details: require_offchain_errors_backendMessage.backendMessage(body)
16
+ });
17
+ }
18
+ };
19
+ //#endregion
20
+ exports.OffchainStatusError = OffchainStatusError;
@@ -0,0 +1,31 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_offchain_errors_errorCause = require("./errorCause.js");
3
+ let viem = require("viem");
4
+ //#region src/offchain/errors/OffchainTransportError.ts
5
+ /**
6
+ * Thrown when the backend could not be reached, or answered with something
7
+ * other than a JSON body in the 2xx range. Its subclasses say which of the
8
+ * three it was; catch this one to catch all of them.
9
+ **/
10
+ var OffchainTransportError = class extends viem.BaseError {
11
+ /**
12
+ * URL that was requested, query included.
13
+ **/
14
+ url;
15
+ /**
16
+ * Status the backend answered with, absent when the request never completed.
17
+ **/
18
+ status;
19
+ constructor(shortMessage, params) {
20
+ const caught = require_offchain_errors_errorCause.errorCause(params.cause);
21
+ super(shortMessage, {
22
+ cause: caught.cause,
23
+ details: caught.details ?? params.details,
24
+ metaMessages: [`URL: ${params.url}`, ...params.status === void 0 ? [] : [`Status: ${params.status}`]]
25
+ });
26
+ this.url = params.url;
27
+ this.status = params.status;
28
+ }
29
+ };
30
+ //#endregion
31
+ exports.OffchainTransportError = OffchainTransportError;
@@ -0,0 +1,26 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ let viem = require("viem");
3
+ let zod_v4 = require("zod/v4");
4
+ //#region src/offchain/errors/OffchainValidationError.ts
5
+ /**
6
+ * Thrown when the backend answered, but with a payload the read model does not
7
+ * describe, i.e. the two are of different versions.
8
+ **/
9
+ var OffchainValidationError = class extends viem.BaseError {
10
+ name = "OffchainValidationError";
11
+ /**
12
+ * URL whose payload failed to validate.
13
+ **/
14
+ url;
15
+ /**
16
+ * The zod failure itself, e.g. for `z.treeifyError(error.zodError)`.
17
+ **/
18
+ zodError;
19
+ constructor(url, zodError) {
20
+ super("The Gearbox backend response does not match the read model.", { metaMessages: [`URL: ${url}`, ...zod_v4.z.prettifyError(zodError).split("\n")] });
21
+ this.url = url;
22
+ this.zodError = zodError;
23
+ }
24
+ };
25
+ //#endregion
26
+ exports.OffchainValidationError = OffchainValidationError;