@portal-hq/web 3.13.2 → 3.14.0-alpha.0

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 (96) hide show
  1. package/lib/commonjs/index.js +127 -9
  2. package/lib/commonjs/index.test.js +13 -0
  3. package/lib/commonjs/integrations/delegations/index.js +109 -2
  4. package/lib/commonjs/integrations/delegations/index.test.js +171 -0
  5. package/lib/commonjs/integrations/ramps/noah/index.test.js +18 -5
  6. package/lib/commonjs/integrations/trading/index.js +16 -5
  7. package/lib/commonjs/integrations/trading/lifi/index.js +297 -25
  8. package/lib/commonjs/integrations/trading/lifi/lifi.tradeAsset.test.js +360 -0
  9. package/lib/commonjs/integrations/trading/lifi/lifiStatusPoll.js +118 -0
  10. package/lib/commonjs/integrations/trading/lifi/lifiStatusPoll.test.js +66 -0
  11. package/lib/commonjs/integrations/trading/zero-x/index.js +129 -26
  12. package/lib/commonjs/integrations/trading/zero-x/index.test.js +163 -1
  13. package/lib/commonjs/integrations/yield/index.js +18 -4
  14. package/lib/commonjs/integrations/yield/yieldxyz.getValidators.test.js +71 -0
  15. package/lib/commonjs/integrations/yield/yieldxyz.highLevel.test.js +330 -0
  16. package/lib/commonjs/integrations/yield/yieldxyz.js +517 -1
  17. package/lib/commonjs/internal/pollLoop.js +64 -0
  18. package/lib/commonjs/internal/pollLoop.test.js +100 -0
  19. package/lib/commonjs/internal/stripStalePlanningNonce.js +65 -0
  20. package/lib/commonjs/internal/stripStalePlanningNonce.test.js +35 -0
  21. package/lib/commonjs/internal/waitForEvmOrUserOpConfirmation.js +155 -0
  22. package/lib/commonjs/internal/waitForEvmOrUserOpConfirmation.test.js +33 -0
  23. package/lib/commonjs/internal/waitForEvmTxConfirmation.js +104 -0
  24. package/lib/commonjs/internal/waitForSolanaTxConfirmation.js +106 -0
  25. package/lib/commonjs/internal/yieldEvmNetwork.js +60 -0
  26. package/lib/commonjs/mpc/index.js +116 -1
  27. package/lib/commonjs/provider/index.js +17 -0
  28. package/lib/commonjs/shared/trace/index.js +0 -1
  29. package/lib/esm/index.js +127 -9
  30. package/lib/esm/index.test.js +13 -0
  31. package/lib/esm/integrations/delegations/index.js +109 -2
  32. package/lib/esm/integrations/delegations/index.test.js +171 -0
  33. package/lib/esm/integrations/ramps/noah/index.test.js +18 -5
  34. package/lib/esm/integrations/trading/index.js +16 -5
  35. package/lib/esm/integrations/trading/lifi/index.js +292 -25
  36. package/lib/esm/integrations/trading/lifi/lifi.tradeAsset.test.js +332 -0
  37. package/lib/esm/integrations/trading/lifi/lifiStatusPoll.js +113 -0
  38. package/lib/esm/integrations/trading/lifi/lifiStatusPoll.test.js +64 -0
  39. package/lib/esm/integrations/trading/zero-x/index.js +129 -26
  40. package/lib/esm/integrations/trading/zero-x/index.test.js +141 -2
  41. package/lib/esm/integrations/yield/index.js +18 -4
  42. package/lib/esm/integrations/yield/yieldxyz.getValidators.test.js +66 -0
  43. package/lib/esm/integrations/yield/yieldxyz.highLevel.test.js +325 -0
  44. package/lib/esm/integrations/yield/yieldxyz.js +517 -1
  45. package/lib/esm/internal/pollLoop.js +59 -0
  46. package/lib/esm/internal/pollLoop.test.js +98 -0
  47. package/lib/esm/internal/stripStalePlanningNonce.js +61 -0
  48. package/lib/esm/internal/stripStalePlanningNonce.test.js +33 -0
  49. package/lib/esm/internal/waitForEvmOrUserOpConfirmation.js +151 -0
  50. package/lib/esm/internal/waitForEvmOrUserOpConfirmation.test.js +31 -0
  51. package/lib/esm/internal/waitForEvmTxConfirmation.js +100 -0
  52. package/lib/esm/internal/waitForSolanaTxConfirmation.js +102 -0
  53. package/lib/esm/internal/yieldEvmNetwork.js +55 -0
  54. package/lib/esm/mpc/index.js +116 -1
  55. package/lib/esm/provider/index.js +17 -0
  56. package/lib/esm/shared/trace/index.js +0 -1
  57. package/noah-types.d.ts +16 -2
  58. package/package.json +3 -2
  59. package/src/index.test.ts +15 -0
  60. package/src/index.ts +203 -14
  61. package/src/integrations/delegations/index.test.ts +251 -0
  62. package/src/integrations/delegations/index.ts +202 -4
  63. package/src/integrations/ramps/noah/index.test.ts +18 -5
  64. package/src/integrations/trading/index.ts +10 -7
  65. package/src/integrations/trading/lifi/index.ts +388 -28
  66. package/src/integrations/trading/lifi/lifi.tradeAsset.test.ts +436 -0
  67. package/src/integrations/trading/lifi/lifiStatusPoll.test.ts +74 -0
  68. package/src/integrations/trading/lifi/lifiStatusPoll.ts +158 -0
  69. package/src/integrations/trading/zero-x/index.test.ts +297 -1
  70. package/src/integrations/trading/zero-x/index.ts +181 -27
  71. package/src/integrations/yield/index.ts +24 -4
  72. package/src/integrations/yield/yieldxyz.getValidators.test.ts +70 -0
  73. package/src/integrations/yield/yieldxyz.highLevel.test.ts +403 -0
  74. package/src/integrations/yield/yieldxyz.ts +740 -8
  75. package/src/internal/pollLoop.test.ts +109 -0
  76. package/src/internal/pollLoop.ts +87 -0
  77. package/src/internal/stripStalePlanningNonce.test.ts +38 -0
  78. package/src/internal/stripStalePlanningNonce.ts +66 -0
  79. package/src/internal/waitForEvmOrUserOpConfirmation.test.ts +31 -0
  80. package/src/internal/waitForEvmOrUserOpConfirmation.ts +194 -0
  81. package/src/internal/waitForEvmTxConfirmation.ts +155 -0
  82. package/src/internal/waitForSolanaTxConfirmation.ts +135 -0
  83. package/src/internal/yieldEvmNetwork.ts +57 -0
  84. package/src/mpc/index.ts +142 -1
  85. package/src/provider/index.ts +25 -0
  86. package/src/shared/trace/index.ts +0 -1
  87. package/src/shared/types/README.md +6 -0
  88. package/src/shared/types/api.ts +12 -1
  89. package/src/shared/types/common.ts +332 -20
  90. package/src/shared/types/delegations.ts +10 -0
  91. package/src/shared/types/index.ts +1 -0
  92. package/src/shared/types/lifi.ts +82 -0
  93. package/src/shared/types/noah.ts +124 -33
  94. package/src/shared/types/yieldxyz.ts +186 -0
  95. package/src/shared/types/zero-x.ts +66 -0
  96. package/types.d.ts +6 -0
@@ -8,58 +8,330 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
8
8
  step((generator = generator.apply(thisArg, _arguments || [])).next());
9
9
  });
10
10
  };
11
+ var __rest = (this && this.__rest) || function (s, e) {
12
+ var t = {};
13
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
14
+ t[p] = s[p];
15
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
16
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
17
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
18
+ t[p[i]] = s[p[i]];
19
+ }
20
+ return t;
21
+ };
11
22
  Object.defineProperty(exports, "__esModule", { value: true });
23
+ exports.statusBridgeFromStepTool = exports.parseLifiTransactionRequestFromStep = exports.resolveLifiStepNetworkCaip2 = exports.normalizeChainToNetwork = void 0;
24
+ const logger_1 = require("../../../logger");
25
+ const waitForEvmTxConfirmation_1 = require("../../../internal/waitForEvmTxConfirmation");
26
+ const stripStalePlanningNonce_1 = require("../../../internal/stripStalePlanningNonce");
27
+ const lifiStatusPoll_1 = require("./lifiStatusPoll");
28
+ const LOG_PREFIX = '[LiFi]';
29
+ /**
30
+ * Internal sentinel error used to avoid emitting duplicate `failed` progress events.
31
+ */
32
+ class LifiReportedError extends Error {
33
+ constructor(message) {
34
+ super(message);
35
+ this.name = 'LifiReportedError';
36
+ }
37
+ }
38
+ /** Normalize LiFi chain key / id to CAIP-2 `eip155:*` for the Portal provider. */
39
+ function normalizeChainToNetwork(chain) {
40
+ const c = chain.trim();
41
+ if (c.startsWith('eip155:')) {
42
+ return c;
43
+ }
44
+ if (/^0x[0-9a-fA-F]+$/.test(c)) {
45
+ return `eip155:${parseInt(c, 16)}`;
46
+ }
47
+ if (/^\d+$/.test(c)) {
48
+ return `eip155:${c}`;
49
+ }
50
+ return c;
51
+ }
52
+ exports.normalizeChainToNetwork = normalizeChainToNetwork;
53
+ function resolveLifiStepNetworkCaip2(step) {
54
+ var _a;
55
+ const fromTx = (_a = step.transactionRequest) === null || _a === void 0 ? void 0 : _a.chainId;
56
+ if (fromTx) {
57
+ return normalizeChainToNetwork(fromTx);
58
+ }
59
+ return normalizeChainToNetwork(step.action.fromChainId);
60
+ }
61
+ exports.resolveLifiStepNetworkCaip2 = resolveLifiStepNetworkCaip2;
62
+ function parseLifiTransactionRequestFromStep(step) {
63
+ var _a;
64
+ const tr = step.transactionRequest;
65
+ if (!tr) {
66
+ throw new Error(`${LOG_PREFIX} Step has no transactionRequest; call getRouteStep first.`);
67
+ }
68
+ const base = {
69
+ data: tr.data,
70
+ to: tr.to,
71
+ from: tr.from,
72
+ value: (_a = tr.value) !== null && _a !== void 0 ? _a : '0x0',
73
+ gas: tr.gasLimit,
74
+ gasPrice: tr.gasPrice,
75
+ };
76
+ if (tr.maxFeePerGas != null) {
77
+ base.maxFeePerGas = tr.maxFeePerGas;
78
+ }
79
+ if (tr.maxPriorityFeePerGas != null) {
80
+ base.maxPriorityFeePerGas = tr.maxPriorityFeePerGas;
81
+ }
82
+ return base;
83
+ }
84
+ exports.parseLifiTransactionRequestFromStep = parseLifiTransactionRequestFromStep;
85
+ function statusBridgeFromStepTool(tool) {
86
+ if (!tool) {
87
+ return undefined;
88
+ }
89
+ return tool.toLowerCase();
90
+ }
91
+ exports.statusBridgeFromStepTool = statusBridgeFromStepTool;
92
+ function mergeLifiOptions(instance, perCall) {
93
+ return Object.assign(Object.assign({}, instance), perCall);
94
+ }
12
95
  class LiFi {
13
- constructor({ mpc }) {
96
+ constructor(_a) {
97
+ var { mpc } = _a, tradeDefaults = __rest(_a, ["mpc"]);
14
98
  this.mpc = mpc;
99
+ this.defaultTradeOptions = tradeDefaults;
15
100
  }
16
- /**
17
- * Retrieves routes from the Li.Fi integration.
18
- * @param data - The parameters for the routes request.
19
- * @returns A `LifiRoutesResponse` promise.
20
- * @throws An error if the operation fails.
21
- */
22
101
  getRoutes(data) {
23
102
  var _a;
24
103
  return __awaiter(this, void 0, void 0, function* () {
25
104
  return (_a = this.mpc) === null || _a === void 0 ? void 0 : _a.getLifiRoutes(data);
26
105
  });
27
106
  }
28
- /**
29
- * Retrieves a quote from the Li.Fi integration.
30
- * @param data - The parameters for the quote request.
31
- * @returns A `LifiQuoteResponse` promise.
32
- * @throws An error if the operation fails.
33
- */
34
107
  getQuote(data) {
35
108
  var _a;
36
109
  return __awaiter(this, void 0, void 0, function* () {
37
110
  return (_a = this.mpc) === null || _a === void 0 ? void 0 : _a.getLifiQuote(data);
38
111
  });
39
112
  }
40
- /**
41
- * Retrieves the status of a transaction from the Li.Fi integration.
42
- * @param data - The parameters for the status request.
43
- * @returns A `LifiStatusResponse` promise.
44
- * @throws An error if the operation fails.
45
- */
46
113
  getStatus(data) {
47
114
  var _a;
48
115
  return __awaiter(this, void 0, void 0, function* () {
49
116
  return (_a = this.mpc) === null || _a === void 0 ? void 0 : _a.getLifiStatus(data);
50
117
  });
51
118
  }
52
- /**
53
- * Retrieves an unsigned transaction from the Li.Fi integration that has yet to be signed/submitted.
54
- * @param data - The step transaction request containing the step details.
55
- * @returns A `LifiStepTransactionResponse` promise.
56
- * @throws An error if the operation fails.
57
- */
58
119
  getRouteStep(data) {
59
120
  var _a;
60
121
  return __awaiter(this, void 0, void 0, function* () {
61
122
  return (_a = this.mpc) === null || _a === void 0 ? void 0 : _a.getLifiRouteStep(data);
62
123
  });
63
124
  }
125
+ pollStatus(request, options) {
126
+ return __awaiter(this, void 0, void 0, function* () {
127
+ const { everyMs = 10000, initialDelayMs = 10000, timeoutMs = 600000, maxConsecutiveErrors = 10, backoff = { factor: 1.5, maxIntervalMs: 15000 }, onUpdate, } = options !== null && options !== void 0 ? options : {};
128
+ return (0, lifiStatusPoll_1.pollLifiStatusUntilTerminal)({
129
+ getStatus: (r) => this.mpc.getLifiStatus(r),
130
+ request,
131
+ onUpdate,
132
+ everyMs,
133
+ initialDelayMs,
134
+ timeoutMs,
135
+ maxConsecutiveErrors,
136
+ backoff,
137
+ });
138
+ });
139
+ }
140
+ tradeAsset(params, options) {
141
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t;
142
+ return __awaiter(this, void 0, void 0, function* () {
143
+ try {
144
+ const o = mergeLifiOptions(this.defaultTradeOptions, options);
145
+ const signAndSend = o.signAndSendTransaction;
146
+ if (!signAndSend) {
147
+ throw new Error(`${LOG_PREFIX} tradeAsset requires signAndSendTransaction`);
148
+ }
149
+ const effectiveWait = (txHash, network) => __awaiter(this, void 0, void 0, function* () {
150
+ var _u, _v;
151
+ if (o.waitForConfirmation) {
152
+ return o.waitForConfirmation(txHash, network);
153
+ }
154
+ if (o.evmRequestFn) {
155
+ if (!network.startsWith('eip155:')) {
156
+ logger_1.sdkLogger.warn(`${LOG_PREFIX} Cannot verify confirmation for non-EVM network ${network}. ` +
157
+ 'Provide waitForConfirmation or use Portal.waitForConfirmation.');
158
+ return Promise.resolve(false);
159
+ }
160
+ return (0, waitForEvmTxConfirmation_1.waitForEvmTxConfirmation)(txHash, network, o.evmRequestFn, {
161
+ pollIntervalMs: (_u = o.evmPollerOptions) === null || _u === void 0 ? void 0 : _u.pollIntervalMs,
162
+ timeoutMs: (_v = o.evmPollerOptions) === null || _v === void 0 ? void 0 : _v.timeoutMs,
163
+ // Intentionally differs from Yield's optimistic `resolve_false` timeout
164
+ // handling: LiFi must abort here so we do not continue into bridge-status
165
+ // polling after source-chain confirmation has already timed out.
166
+ onTimeout: 'throw',
167
+ });
168
+ }
169
+ throw new Error(`${LOG_PREFIX} tradeAsset requires waitForConfirmation or evmRequestFn fallback.`);
170
+ });
171
+ (_a = params.onProgress) === null || _a === void 0 ? void 0 : _a.call(params, 'fetching_routes');
172
+ const routesRes = yield this.getRoutes({
173
+ fromChainId: normalizeChainToNetwork(params.fromChain),
174
+ toChainId: normalizeChainToNetwork(params.toChain),
175
+ fromTokenAddress: params.fromToken,
176
+ toTokenAddress: params.toToken,
177
+ fromAmount: params.amount,
178
+ fromAddress: params.fromAddress,
179
+ toAddress: params.toAddress,
180
+ options: params.routeOptions,
181
+ });
182
+ if (routesRes.error) {
183
+ throw new Error(`${LOG_PREFIX} getRoutes: ${routesRes.error}`);
184
+ }
185
+ const routes = (_c = (_b = routesRes.data) === null || _b === void 0 ? void 0 : _b.rawResponse.routes) !== null && _c !== void 0 ? _c : [];
186
+ if (routes.length === 0) {
187
+ throw new Error(`${LOG_PREFIX} No routes returned from LiFi`);
188
+ }
189
+ const idx = (_d = params.routeIndex) !== null && _d !== void 0 ? _d : 0;
190
+ const route = routes[idx];
191
+ if (!route) {
192
+ throw new Error(`${LOG_PREFIX} no route available at index ${idx}`);
193
+ }
194
+ (_e = params.onProgress) === null || _e === void 0 ? void 0 : _e.call(params, 'route_selected', { route, routeIndex: idx });
195
+ const hashes = [];
196
+ const stepsOut = [];
197
+ const totalSteps = route.steps.length;
198
+ for (let stepIndex = 0; stepIndex < route.steps.length; stepIndex++) {
199
+ const step = route.steps[stepIndex];
200
+ // Validate step exists (defensive check for sparse arrays)
201
+ if (!step) {
202
+ throw new Error(`${LOG_PREFIX} Step at index ${stepIndex} is undefined or null. This indicates a malformed route response.`);
203
+ }
204
+ (_f = params.onProgress) === null || _f === void 0 ? void 0 : _f.call(params, 'preparing_step', {
205
+ route,
206
+ routeIndex: idx,
207
+ step,
208
+ stepIndex,
209
+ totalSteps,
210
+ });
211
+ const stepRes = yield this.getRouteStep(step);
212
+ if (stepRes.error) {
213
+ throw new Error(`${LOG_PREFIX} getRouteStep: ${stepRes.error}`);
214
+ }
215
+ const populated = (_g = stepRes.data) === null || _g === void 0 ? void 0 : _g.rawResponse;
216
+ if (!populated) {
217
+ throw new Error(`${LOG_PREFIX} getRouteStep returned no step data`);
218
+ }
219
+ const network = resolveLifiStepNetworkCaip2(populated);
220
+ let tx = parseLifiTransactionRequestFromStep(populated);
221
+ if (network.startsWith('eip155:')) {
222
+ const stripped = (0, stripStalePlanningNonce_1.stripStalePlanningNonceIfJsonObject)(tx);
223
+ // Validate stripped result is still an object
224
+ if (typeof stripped !== 'object' ||
225
+ stripped === null ||
226
+ Array.isArray(stripped)) {
227
+ throw new Error(`${LOG_PREFIX} stripStalePlanningNonce returned invalid type: ${typeof stripped}`);
228
+ }
229
+ tx = stripped;
230
+ }
231
+ (_h = params.onProgress) === null || _h === void 0 ? void 0 : _h.call(params, 'signing', {
232
+ route,
233
+ routeIndex: idx,
234
+ step: populated,
235
+ stepIndex,
236
+ totalSteps,
237
+ transaction: tx,
238
+ });
239
+ const txHash = yield signAndSend(tx, network);
240
+ if (typeof txHash !== 'string' || txHash.trim().length === 0) {
241
+ const msg = `Invalid transaction hash returned from signAndSendTransaction at step ${stepIndex} for network ${network}.`;
242
+ (_j = params.onProgress) === null || _j === void 0 ? void 0 : _j.call(params, 'failed', {
243
+ errorMessage: msg,
244
+ txHash,
245
+ routeIndex: idx,
246
+ stepIndex,
247
+ totalSteps,
248
+ step: populated,
249
+ });
250
+ throw new LifiReportedError(`${LOG_PREFIX} ${msg}`);
251
+ }
252
+ hashes.push(txHash);
253
+ (_k = params.onProgress) === null || _k === void 0 ? void 0 : _k.call(params, 'submitted', {
254
+ route,
255
+ routeIndex: idx,
256
+ step: populated,
257
+ stepIndex,
258
+ totalSteps,
259
+ txHash,
260
+ });
261
+ (_l = params.onProgress) === null || _l === void 0 ? void 0 : _l.call(params, 'confirming', {
262
+ route,
263
+ routeIndex: idx,
264
+ step: populated,
265
+ stepIndex,
266
+ totalSteps,
267
+ txHash,
268
+ });
269
+ const waiterResult = (yield effectiveWait(txHash, network));
270
+ const ok = waiterResult === true;
271
+ if (!ok) {
272
+ const msg = `${LOG_PREFIX} on-chain confirmation did not complete (waitForConfirmation did not return true) for ${txHash} on ${network}`;
273
+ (_m = params.onProgress) === null || _m === void 0 ? void 0 : _m.call(params, 'failed', {
274
+ errorMessage: msg,
275
+ txHash,
276
+ routeIndex: idx,
277
+ stepIndex,
278
+ totalSteps,
279
+ step: populated,
280
+ });
281
+ throw new LifiReportedError(msg);
282
+ }
283
+ const bridgeTool = statusBridgeFromStepTool(populated.tool);
284
+ const crossLike = populated.type === 'cross' ||
285
+ populated.action.fromChainId !== populated.action.toChainId;
286
+ if (crossLike && bridgeTool) {
287
+ (_o = params.onProgress) === null || _o === void 0 ? void 0 : _o.call(params, 'lifi_pending', {
288
+ route,
289
+ routeIndex: idx,
290
+ step: populated,
291
+ stepIndex,
292
+ totalSteps,
293
+ txHash,
294
+ });
295
+ const pollOpts = (_p = params.statusPoll) !== null && _p !== void 0 ? _p : {};
296
+ const terminal = yield this.pollStatus({
297
+ txHash,
298
+ fromChain: params.fromChain,
299
+ toChain: params.toChain,
300
+ bridge: bridgeTool,
301
+ }, pollOpts);
302
+ (_q = params.onProgress) === null || _q === void 0 ? void 0 : _q.call(params, 'step_done', {
303
+ route,
304
+ routeIndex: idx,
305
+ step: populated,
306
+ stepIndex,
307
+ totalSteps,
308
+ txHash,
309
+ lifiStatus: terminal,
310
+ });
311
+ }
312
+ else {
313
+ (_r = params.onProgress) === null || _r === void 0 ? void 0 : _r.call(params, 'step_done', {
314
+ route,
315
+ routeIndex: idx,
316
+ step: populated,
317
+ stepIndex,
318
+ totalSteps,
319
+ txHash,
320
+ });
321
+ }
322
+ stepsOut.push(populated);
323
+ }
324
+ (_s = params.onProgress) === null || _s === void 0 ? void 0 : _s.call(params, 'complete', { route, routeIndex: idx });
325
+ return { hashes, steps: stepsOut, route };
326
+ }
327
+ catch (error) {
328
+ if (!(error instanceof LifiReportedError)) {
329
+ const errorMessage = error instanceof Error ? error.message : String(error);
330
+ (_t = params.onProgress) === null || _t === void 0 ? void 0 : _t.call(params, 'failed', { errorMessage });
331
+ }
332
+ throw error;
333
+ }
334
+ });
335
+ }
64
336
  }
65
337
  exports.default = LiFi;