@portal-hq/web 3.13.1 → 3.13.2-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 +438 -0
  16. package/lib/commonjs/integrations/yield/yieldxyz.js +541 -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 +433 -0
  44. package/lib/esm/integrations/yield/yieldxyz.js +541 -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 +536 -0
  74. package/src/integrations/yield/yieldxyz.ts +762 -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 +193 -0
  95. package/src/shared/types/zero-x.ts +66 -0
  96. package/types.d.ts +6 -0
@@ -85,4 +85,175 @@ describe('Delegations', () => {
85
85
  yield expect(delegations.transferFrom(mockTransferFromRequest)).rejects.toThrow('Test error');
86
86
  }));
87
87
  });
88
+ describe('approveAndSubmit, revokeAndSubmit, transferAndSubmit', () => {
89
+ const mockSignAndSend = jest.fn();
90
+ beforeEach(() => {
91
+ mockSignAndSend.mockResolvedValue('0xtxhash');
92
+ });
93
+ it('throws when signAndSendTransaction is not configured', () => __awaiter(void 0, void 0, void 0, function* () {
94
+ const d = new Delegations({ mpc });
95
+ yield expect(d.approveAndSubmit(mockEVMApproveRequest)).rejects.toThrow('[Delegations] No signer configured. Call setSignAndSendTransaction() on the instance or pass signAndSendTransaction in options.');
96
+ yield expect(d.revokeAndSubmit(mockEVMRevokeRequest)).rejects.toThrow('[Delegations] No signer configured. Call setSignAndSendTransaction() on the instance or pass signAndSendTransaction in options.');
97
+ yield expect(d.transferAndSubmit(mockTransferFromRequest)).rejects.toThrow('[Delegations] No signer configured. Call setSignAndSendTransaction() on the instance or pass signAndSendTransaction in options.');
98
+ }));
99
+ it('approveAndSubmit calls MPC then signAndSend per transaction', () => __awaiter(void 0, void 0, void 0, function* () {
100
+ jest.spyOn(mpc, 'delegationsApprove').mockResolvedValue(mockEVMApproveResponse);
101
+ const d = new Delegations({
102
+ mpc,
103
+ signAndSendTransaction: mockSignAndSend,
104
+ });
105
+ const result = yield d.approveAndSubmit(mockEVMApproveRequest);
106
+ expect(mpc.delegationsApprove).toHaveBeenCalledWith(mockEVMApproveRequest);
107
+ expect(mockSignAndSend).toHaveBeenCalledTimes(1);
108
+ expect(mockSignAndSend).toHaveBeenCalledWith(mockEVMApproveResponse.transactions[0], mockEVMApproveRequest.chain);
109
+ expect(result).toEqual({ hashes: ['0xtxhash'] });
110
+ }));
111
+ it('revokeAndSubmit calls delegationsRevoke then signAndSend per transaction', () => __awaiter(void 0, void 0, void 0, function* () {
112
+ jest.spyOn(mpc, 'delegationsRevoke').mockResolvedValue(mockEVMRevokeResponse);
113
+ const d = new Delegations({
114
+ mpc,
115
+ signAndSendTransaction: mockSignAndSend,
116
+ });
117
+ const result = yield d.revokeAndSubmit(mockEVMRevokeRequest);
118
+ expect(mpc.delegationsRevoke).toHaveBeenCalledWith(mockEVMRevokeRequest);
119
+ expect(mockSignAndSend).toHaveBeenCalledTimes(1);
120
+ expect(mockSignAndSend).toHaveBeenCalledWith(mockEVMRevokeResponse.transactions[0], mockEVMRevokeRequest.chain);
121
+ expect(result).toEqual({ hashes: ['0xtxhash'] });
122
+ }));
123
+ it('transferAndSubmit calls delegationsTransferFrom then signAndSend per transaction', () => __awaiter(void 0, void 0, void 0, function* () {
124
+ jest
125
+ .spyOn(mpc, 'delegationsTransferFrom')
126
+ .mockResolvedValue(mockTransferFromResponse);
127
+ const d = new Delegations({
128
+ mpc,
129
+ signAndSendTransaction: mockSignAndSend,
130
+ });
131
+ const result = yield d.transferAndSubmit(mockTransferFromRequest);
132
+ expect(mpc.delegationsTransferFrom).toHaveBeenCalledWith(mockTransferFromRequest);
133
+ expect(mockSignAndSend).toHaveBeenCalledTimes(1);
134
+ expect(mockSignAndSend).toHaveBeenCalledWith(mockTransferFromResponse.transactions[0], mockTransferFromRequest.chain);
135
+ expect(result).toEqual({ hashes: ['0xtxhash'] });
136
+ }));
137
+ it('uses encodedTransactions when transactions is empty', () => __awaiter(void 0, void 0, void 0, function* () {
138
+ const response = {
139
+ transactions: [],
140
+ encodedTransactions: ['solTxPayload'],
141
+ metadata: mockEVMApproveResponse.metadata,
142
+ };
143
+ jest.spyOn(mpc, 'delegationsApprove').mockResolvedValue(response);
144
+ const d = new Delegations({
145
+ mpc,
146
+ signAndSendTransaction: mockSignAndSend,
147
+ });
148
+ yield d.approveAndSubmit(mockEVMApproveRequest);
149
+ expect(mockSignAndSend).toHaveBeenCalledWith('solTxPayload', mockEVMApproveRequest.chain);
150
+ }));
151
+ it('invokes onProgress for each transaction', () => __awaiter(void 0, void 0, void 0, function* () {
152
+ jest.spyOn(mpc, 'delegationsApprove').mockResolvedValue(mockEVMApproveResponse);
153
+ const onProgress = jest.fn();
154
+ const d = new Delegations({
155
+ mpc,
156
+ signAndSendTransaction: mockSignAndSend,
157
+ });
158
+ yield d.approveAndSubmit(mockEVMApproveRequest, { onProgress });
159
+ expect(onProgress).toHaveBeenCalledTimes(2);
160
+ expect(onProgress).toHaveBeenNthCalledWith(1, {
161
+ step: 'signing',
162
+ index: 0,
163
+ total: 1,
164
+ });
165
+ expect(onProgress).toHaveBeenNthCalledWith(2, {
166
+ step: 'submitted',
167
+ index: 0,
168
+ total: 1,
169
+ hash: '0xtxhash',
170
+ });
171
+ }));
172
+ it('throws when response has no transactions', () => __awaiter(void 0, void 0, void 0, function* () {
173
+ jest.spyOn(mpc, 'delegationsApprove').mockResolvedValue({
174
+ metadata: mockEVMApproveResponse.metadata,
175
+ });
176
+ const d = new Delegations({
177
+ mpc,
178
+ signAndSendTransaction: mockSignAndSend,
179
+ });
180
+ yield expect(d.approveAndSubmit(mockEVMApproveRequest)).rejects.toThrow('No transactions in delegation response.');
181
+ expect(mockSignAndSend).not.toHaveBeenCalled();
182
+ }));
183
+ it('submits multiple EVM transactions in order', () => __awaiter(void 0, void 0, void 0, function* () {
184
+ const txA = Object.assign({}, mockEVMApproveResponse.transactions[0]);
185
+ const txB = Object.assign(Object.assign({}, txA), { data: '0xbbbb' });
186
+ jest.spyOn(mpc, 'delegationsApprove').mockResolvedValue(Object.assign(Object.assign({}, mockEVMApproveResponse), { transactions: [txA, txB] }));
187
+ const d = new Delegations({
188
+ mpc,
189
+ signAndSendTransaction: mockSignAndSend,
190
+ });
191
+ mockSignAndSend.mockResolvedValueOnce('0xh1').mockResolvedValueOnce('0xh2');
192
+ const result = yield d.approveAndSubmit(mockEVMApproveRequest);
193
+ expect(mockSignAndSend).toHaveBeenCalledTimes(2);
194
+ expect(mockSignAndSend).toHaveBeenNthCalledWith(1, txA, mockEVMApproveRequest.chain);
195
+ expect(mockSignAndSend).toHaveBeenNthCalledWith(2, txB, mockEVMApproveRequest.chain);
196
+ expect(result.hashes).toEqual(['0xh1', '0xh2']);
197
+ }));
198
+ it('propagates error after first tx succeeds (partial submit)', () => __awaiter(void 0, void 0, void 0, function* () {
199
+ const txA = Object.assign({}, mockEVMApproveResponse.transactions[0]);
200
+ const txB = Object.assign(Object.assign({}, txA), { data: '0xbbbb' });
201
+ jest.spyOn(mpc, 'delegationsApprove').mockResolvedValue(Object.assign(Object.assign({}, mockEVMApproveResponse), { transactions: [txA, txB] }));
202
+ const d = new Delegations({
203
+ mpc,
204
+ signAndSendTransaction: mockSignAndSend,
205
+ });
206
+ mockSignAndSend
207
+ .mockResolvedValueOnce('0xh1')
208
+ .mockRejectedValueOnce(new Error('second tx failed'));
209
+ yield expect(d.approveAndSubmit(mockEVMApproveRequest)).rejects.toThrow('second tx failed');
210
+ expect(mockSignAndSend).toHaveBeenCalledTimes(2);
211
+ }));
212
+ it('per-call signAndSendTransaction overrides constructor signer', () => __awaiter(void 0, void 0, void 0, function* () {
213
+ jest.spyOn(mpc, 'delegationsApprove').mockResolvedValue(mockEVMApproveResponse);
214
+ const instanceSigner = jest.fn().mockResolvedValue('0xinstance');
215
+ const perCallSigner = jest.fn().mockResolvedValue('0xpercall');
216
+ const d = new Delegations({
217
+ mpc,
218
+ signAndSendTransaction: instanceSigner,
219
+ });
220
+ yield d.approveAndSubmit(mockEVMApproveRequest, {
221
+ signAndSendTransaction: perCallSigner,
222
+ });
223
+ expect(instanceSigner).not.toHaveBeenCalled();
224
+ expect(perCallSigner).toHaveBeenCalledTimes(1);
225
+ }));
226
+ it('throws on whitespace-only hash from signer', () => __awaiter(void 0, void 0, void 0, function* () {
227
+ jest.spyOn(mpc, 'delegationsApprove').mockResolvedValue(mockEVMApproveResponse);
228
+ mockSignAndSend.mockResolvedValue(' ');
229
+ const d = new Delegations({
230
+ mpc,
231
+ signAndSendTransaction: mockSignAndSend,
232
+ });
233
+ yield expect(d.approveAndSubmit(mockEVMApproveRequest)).rejects.toThrow('Invalid transaction hash');
234
+ }));
235
+ it('prefers transactions over encodedTransactions when both non-empty', () => __awaiter(void 0, void 0, void 0, function* () {
236
+ const evmTx = mockEVMApproveResponse.transactions[0];
237
+ jest.spyOn(mpc, 'delegationsApprove').mockResolvedValue({
238
+ transactions: [evmTx],
239
+ encodedTransactions: ['should-not-use'],
240
+ metadata: mockEVMApproveResponse.metadata,
241
+ });
242
+ const d = new Delegations({
243
+ mpc,
244
+ signAndSendTransaction: mockSignAndSend,
245
+ });
246
+ yield d.approveAndSubmit(mockEVMApproveRequest);
247
+ expect(mockSignAndSend).toHaveBeenCalledWith(evmTx, mockEVMApproveRequest.chain);
248
+ }));
249
+ it('setSignAndSendTransaction enables submit after construction', () => __awaiter(void 0, void 0, void 0, function* () {
250
+ jest.spyOn(mpc, 'delegationsApprove').mockResolvedValue(mockEVMApproveResponse);
251
+ const d = new Delegations({ mpc });
252
+ const late = jest.fn().mockResolvedValue('0xlate');
253
+ d.setSignAndSendTransaction(late);
254
+ const result = yield d.approveAndSubmit(mockEVMApproveRequest);
255
+ expect(late).toHaveBeenCalledTimes(1);
256
+ expect(result).toEqual({ hashes: ['0xlate'] });
257
+ }));
258
+ });
88
259
  });
@@ -62,7 +62,15 @@ describe('Noah', () => {
62
62
  destinationAddress: 'SoLAddr1111111111111111111111111111111111111',
63
63
  };
64
64
  const spy = jest.spyOn(mpc, 'initiatePayin').mockResolvedValue({
65
- data: { payinId: 'p1', bankDetails: {} },
65
+ data: {
66
+ payinId: 'p1',
67
+ bankDetails: {
68
+ paymentMethodId: 'pm-123',
69
+ paymentMethodType: 'bank_account',
70
+ accountNumber: '1234567890',
71
+ network: 'solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1',
72
+ },
73
+ },
66
74
  });
67
75
  yield noah.initiatePayin(req);
68
76
  expect(spy).toHaveBeenCalledWith(req);
@@ -74,14 +82,14 @@ describe('Noah', () => {
74
82
  fiatCurrency: 'USD',
75
83
  };
76
84
  const spy = jest.spyOn(mpc, 'simulatePayin').mockResolvedValue({
77
- data: {},
85
+ data: { fiatDepositId: 'deposit-123' },
78
86
  });
79
87
  yield noah.simulatePayin(sim);
80
88
  expect(spy).toHaveBeenCalledWith(sim);
81
89
  }));
82
90
  it('should call mpc.getPayoutCountries', () => __awaiter(void 0, void 0, void 0, function* () {
83
91
  const spy = jest.spyOn(mpc, 'getPayoutCountries').mockResolvedValue({
84
- data: { countries: [] },
92
+ data: { countries: { US: ['USD'], MX: ['MXN', 'USD'] } },
85
93
  });
86
94
  yield noah.getPayoutCountries();
87
95
  expect(spy).toHaveBeenCalled();
@@ -94,7 +102,7 @@ describe('Noah', () => {
94
102
  fiatAmount: '10',
95
103
  };
96
104
  const spy = jest.spyOn(mpc, 'getPayoutChannels').mockResolvedValue({
97
- data: [],
105
+ data: { items: [] },
98
106
  });
99
107
  yield noah.getPayoutChannels(req);
100
108
  expect(spy).toHaveBeenCalledWith(req);
@@ -102,7 +110,12 @@ describe('Noah', () => {
102
110
  it('should call mpc.getPayoutChannelForm', () => __awaiter(void 0, void 0, void 0, function* () {
103
111
  const spy = jest
104
112
  .spyOn(mpc, 'getPayoutChannelForm')
105
- .mockResolvedValue({ data: {} });
113
+ .mockResolvedValue({
114
+ data: {
115
+ formSchema: { type: 'object', properties: {} },
116
+ formMetadata: { contentHash: 'abc123' },
117
+ },
118
+ });
106
119
  yield noah.getPayoutChannelForm('ch-1');
107
120
  expect(spy).toHaveBeenCalledWith('ch-1');
108
121
  }));
@@ -1,12 +1,23 @@
1
+ var __rest = (this && this.__rest) || function (s, e) {
2
+ var t = {};
3
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
4
+ t[p] = s[p];
5
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
6
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
7
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
8
+ t[p[i]] = s[p[i]];
9
+ }
10
+ return t;
11
+ };
1
12
  import ZeroX from './zero-x';
2
13
  import LiFi from './lifi';
3
14
  /**
4
- * This class is a container for the LiFi class.
5
- * In the future, Trading domain logic should be here.
15
+ * Trading integrations (LiFi, 0x).
6
16
  */
7
17
  export default class Trading {
8
- constructor({ mpc }) {
9
- this.lifi = new LiFi({ mpc });
10
- this.zeroX = new ZeroX({ mpc });
18
+ constructor(_a) {
19
+ var { mpc } = _a, defaults = __rest(_a, ["mpc"]);
20
+ this.lifi = new LiFi(Object.assign({ mpc }, defaults));
21
+ this.zeroX = new ZeroX(Object.assign({ mpc }, defaults));
11
22
  }
12
23
  }
@@ -7,56 +7,323 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
7
7
  step((generator = generator.apply(thisArg, _arguments || [])).next());
8
8
  });
9
9
  };
10
+ var __rest = (this && this.__rest) || function (s, e) {
11
+ var t = {};
12
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
13
+ t[p] = s[p];
14
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
15
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
16
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
17
+ t[p[i]] = s[p[i]];
18
+ }
19
+ return t;
20
+ };
21
+ import { sdkLogger } from '../../../logger';
22
+ import { waitForEvmTxConfirmation } from '../../../internal/waitForEvmTxConfirmation';
23
+ import { stripStalePlanningNonceIfJsonObject } from '../../../internal/stripStalePlanningNonce';
24
+ import { pollLifiStatusUntilTerminal, } from './lifiStatusPoll';
25
+ const LOG_PREFIX = '[LiFi]';
26
+ /**
27
+ * Internal sentinel error used to avoid emitting duplicate `failed` progress events.
28
+ */
29
+ class LifiReportedError extends Error {
30
+ constructor(message) {
31
+ super(message);
32
+ this.name = 'LifiReportedError';
33
+ }
34
+ }
35
+ /** Normalize LiFi chain key / id to CAIP-2 `eip155:*` for the Portal provider. */
36
+ export function normalizeChainToNetwork(chain) {
37
+ const c = chain.trim();
38
+ if (c.startsWith('eip155:')) {
39
+ return c;
40
+ }
41
+ if (/^0x[0-9a-fA-F]+$/.test(c)) {
42
+ return `eip155:${parseInt(c, 16)}`;
43
+ }
44
+ if (/^\d+$/.test(c)) {
45
+ return `eip155:${c}`;
46
+ }
47
+ return c;
48
+ }
49
+ export function resolveLifiStepNetworkCaip2(step) {
50
+ var _a;
51
+ const fromTx = (_a = step.transactionRequest) === null || _a === void 0 ? void 0 : _a.chainId;
52
+ if (fromTx) {
53
+ return normalizeChainToNetwork(fromTx);
54
+ }
55
+ return normalizeChainToNetwork(step.action.fromChainId);
56
+ }
57
+ export function parseLifiTransactionRequestFromStep(step) {
58
+ var _a;
59
+ const tr = step.transactionRequest;
60
+ if (!tr) {
61
+ throw new Error(`${LOG_PREFIX} Step has no transactionRequest; call getRouteStep first.`);
62
+ }
63
+ const base = {
64
+ data: tr.data,
65
+ to: tr.to,
66
+ from: tr.from,
67
+ value: (_a = tr.value) !== null && _a !== void 0 ? _a : '0x0',
68
+ gas: tr.gasLimit,
69
+ gasPrice: tr.gasPrice,
70
+ };
71
+ if (tr.maxFeePerGas != null) {
72
+ base.maxFeePerGas = tr.maxFeePerGas;
73
+ }
74
+ if (tr.maxPriorityFeePerGas != null) {
75
+ base.maxPriorityFeePerGas = tr.maxPriorityFeePerGas;
76
+ }
77
+ return base;
78
+ }
79
+ export function statusBridgeFromStepTool(tool) {
80
+ if (!tool) {
81
+ return undefined;
82
+ }
83
+ return tool.toLowerCase();
84
+ }
85
+ function mergeLifiOptions(instance, perCall) {
86
+ return Object.assign(Object.assign({}, instance), perCall);
87
+ }
10
88
  export default class LiFi {
11
- constructor({ mpc }) {
89
+ constructor(_a) {
90
+ var { mpc } = _a, tradeDefaults = __rest(_a, ["mpc"]);
12
91
  this.mpc = mpc;
92
+ this.defaultTradeOptions = tradeDefaults;
13
93
  }
14
- /**
15
- * Retrieves routes from the Li.Fi integration.
16
- * @param data - The parameters for the routes request.
17
- * @returns A `LifiRoutesResponse` promise.
18
- * @throws An error if the operation fails.
19
- */
20
94
  getRoutes(data) {
21
95
  var _a;
22
96
  return __awaiter(this, void 0, void 0, function* () {
23
97
  return (_a = this.mpc) === null || _a === void 0 ? void 0 : _a.getLifiRoutes(data);
24
98
  });
25
99
  }
26
- /**
27
- * Retrieves a quote from the Li.Fi integration.
28
- * @param data - The parameters for the quote request.
29
- * @returns A `LifiQuoteResponse` promise.
30
- * @throws An error if the operation fails.
31
- */
32
100
  getQuote(data) {
33
101
  var _a;
34
102
  return __awaiter(this, void 0, void 0, function* () {
35
103
  return (_a = this.mpc) === null || _a === void 0 ? void 0 : _a.getLifiQuote(data);
36
104
  });
37
105
  }
38
- /**
39
- * Retrieves the status of a transaction from the Li.Fi integration.
40
- * @param data - The parameters for the status request.
41
- * @returns A `LifiStatusResponse` promise.
42
- * @throws An error if the operation fails.
43
- */
44
106
  getStatus(data) {
45
107
  var _a;
46
108
  return __awaiter(this, void 0, void 0, function* () {
47
109
  return (_a = this.mpc) === null || _a === void 0 ? void 0 : _a.getLifiStatus(data);
48
110
  });
49
111
  }
50
- /**
51
- * Retrieves an unsigned transaction from the Li.Fi integration that has yet to be signed/submitted.
52
- * @param data - The step transaction request containing the step details.
53
- * @returns A `LifiStepTransactionResponse` promise.
54
- * @throws An error if the operation fails.
55
- */
56
112
  getRouteStep(data) {
57
113
  var _a;
58
114
  return __awaiter(this, void 0, void 0, function* () {
59
115
  return (_a = this.mpc) === null || _a === void 0 ? void 0 : _a.getLifiRouteStep(data);
60
116
  });
61
117
  }
118
+ pollStatus(request, options) {
119
+ return __awaiter(this, void 0, void 0, function* () {
120
+ const { everyMs = 10000, initialDelayMs = 10000, timeoutMs = 600000, maxConsecutiveErrors = 10, backoff = { factor: 1.5, maxIntervalMs: 15000 }, onUpdate, } = options !== null && options !== void 0 ? options : {};
121
+ return pollLifiStatusUntilTerminal({
122
+ getStatus: (r) => this.mpc.getLifiStatus(r),
123
+ request,
124
+ onUpdate,
125
+ everyMs,
126
+ initialDelayMs,
127
+ timeoutMs,
128
+ maxConsecutiveErrors,
129
+ backoff,
130
+ });
131
+ });
132
+ }
133
+ tradeAsset(params, options) {
134
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t;
135
+ return __awaiter(this, void 0, void 0, function* () {
136
+ try {
137
+ const o = mergeLifiOptions(this.defaultTradeOptions, options);
138
+ const signAndSend = o.signAndSendTransaction;
139
+ if (!signAndSend) {
140
+ throw new Error(`${LOG_PREFIX} tradeAsset requires signAndSendTransaction`);
141
+ }
142
+ const effectiveWait = (txHash, network) => __awaiter(this, void 0, void 0, function* () {
143
+ var _u, _v;
144
+ if (o.waitForConfirmation) {
145
+ return o.waitForConfirmation(txHash, network);
146
+ }
147
+ if (o.evmRequestFn) {
148
+ if (!network.startsWith('eip155:')) {
149
+ sdkLogger.warn(`${LOG_PREFIX} Cannot verify confirmation for non-EVM network ${network}. ` +
150
+ 'Provide waitForConfirmation or use Portal.waitForConfirmation.');
151
+ return Promise.resolve(false);
152
+ }
153
+ return waitForEvmTxConfirmation(txHash, network, o.evmRequestFn, {
154
+ pollIntervalMs: (_u = o.evmPollerOptions) === null || _u === void 0 ? void 0 : _u.pollIntervalMs,
155
+ timeoutMs: (_v = o.evmPollerOptions) === null || _v === void 0 ? void 0 : _v.timeoutMs,
156
+ // Intentionally differs from Yield's optimistic `resolve_false` timeout
157
+ // handling: LiFi must abort here so we do not continue into bridge-status
158
+ // polling after source-chain confirmation has already timed out.
159
+ onTimeout: 'throw',
160
+ });
161
+ }
162
+ throw new Error(`${LOG_PREFIX} tradeAsset requires waitForConfirmation or evmRequestFn fallback.`);
163
+ });
164
+ (_a = params.onProgress) === null || _a === void 0 ? void 0 : _a.call(params, 'fetching_routes');
165
+ const routesRes = yield this.getRoutes({
166
+ fromChainId: normalizeChainToNetwork(params.fromChain),
167
+ toChainId: normalizeChainToNetwork(params.toChain),
168
+ fromTokenAddress: params.fromToken,
169
+ toTokenAddress: params.toToken,
170
+ fromAmount: params.amount,
171
+ fromAddress: params.fromAddress,
172
+ toAddress: params.toAddress,
173
+ options: params.routeOptions,
174
+ });
175
+ if (routesRes.error) {
176
+ throw new Error(`${LOG_PREFIX} getRoutes: ${routesRes.error}`);
177
+ }
178
+ const routes = (_c = (_b = routesRes.data) === null || _b === void 0 ? void 0 : _b.rawResponse.routes) !== null && _c !== void 0 ? _c : [];
179
+ if (routes.length === 0) {
180
+ throw new Error(`${LOG_PREFIX} No routes returned from LiFi`);
181
+ }
182
+ const idx = (_d = params.routeIndex) !== null && _d !== void 0 ? _d : 0;
183
+ const route = routes[idx];
184
+ if (!route) {
185
+ throw new Error(`${LOG_PREFIX} no route available at index ${idx}`);
186
+ }
187
+ (_e = params.onProgress) === null || _e === void 0 ? void 0 : _e.call(params, 'route_selected', { route, routeIndex: idx });
188
+ const hashes = [];
189
+ const stepsOut = [];
190
+ const totalSteps = route.steps.length;
191
+ for (let stepIndex = 0; stepIndex < route.steps.length; stepIndex++) {
192
+ const step = route.steps[stepIndex];
193
+ // Validate step exists (defensive check for sparse arrays)
194
+ if (!step) {
195
+ throw new Error(`${LOG_PREFIX} Step at index ${stepIndex} is undefined or null. This indicates a malformed route response.`);
196
+ }
197
+ (_f = params.onProgress) === null || _f === void 0 ? void 0 : _f.call(params, 'preparing_step', {
198
+ route,
199
+ routeIndex: idx,
200
+ step,
201
+ stepIndex,
202
+ totalSteps,
203
+ });
204
+ const stepRes = yield this.getRouteStep(step);
205
+ if (stepRes.error) {
206
+ throw new Error(`${LOG_PREFIX} getRouteStep: ${stepRes.error}`);
207
+ }
208
+ const populated = (_g = stepRes.data) === null || _g === void 0 ? void 0 : _g.rawResponse;
209
+ if (!populated) {
210
+ throw new Error(`${LOG_PREFIX} getRouteStep returned no step data`);
211
+ }
212
+ const network = resolveLifiStepNetworkCaip2(populated);
213
+ let tx = parseLifiTransactionRequestFromStep(populated);
214
+ if (network.startsWith('eip155:')) {
215
+ const stripped = stripStalePlanningNonceIfJsonObject(tx);
216
+ // Validate stripped result is still an object
217
+ if (typeof stripped !== 'object' ||
218
+ stripped === null ||
219
+ Array.isArray(stripped)) {
220
+ throw new Error(`${LOG_PREFIX} stripStalePlanningNonce returned invalid type: ${typeof stripped}`);
221
+ }
222
+ tx = stripped;
223
+ }
224
+ (_h = params.onProgress) === null || _h === void 0 ? void 0 : _h.call(params, 'signing', {
225
+ route,
226
+ routeIndex: idx,
227
+ step: populated,
228
+ stepIndex,
229
+ totalSteps,
230
+ transaction: tx,
231
+ });
232
+ const txHash = yield signAndSend(tx, network);
233
+ if (typeof txHash !== 'string' || txHash.trim().length === 0) {
234
+ const msg = `Invalid transaction hash returned from signAndSendTransaction at step ${stepIndex} for network ${network}.`;
235
+ (_j = params.onProgress) === null || _j === void 0 ? void 0 : _j.call(params, 'failed', {
236
+ errorMessage: msg,
237
+ txHash,
238
+ routeIndex: idx,
239
+ stepIndex,
240
+ totalSteps,
241
+ step: populated,
242
+ });
243
+ throw new LifiReportedError(`${LOG_PREFIX} ${msg}`);
244
+ }
245
+ hashes.push(txHash);
246
+ (_k = params.onProgress) === null || _k === void 0 ? void 0 : _k.call(params, 'submitted', {
247
+ route,
248
+ routeIndex: idx,
249
+ step: populated,
250
+ stepIndex,
251
+ totalSteps,
252
+ txHash,
253
+ });
254
+ (_l = params.onProgress) === null || _l === void 0 ? void 0 : _l.call(params, 'confirming', {
255
+ route,
256
+ routeIndex: idx,
257
+ step: populated,
258
+ stepIndex,
259
+ totalSteps,
260
+ txHash,
261
+ });
262
+ const waiterResult = (yield effectiveWait(txHash, network));
263
+ const ok = waiterResult === true;
264
+ if (!ok) {
265
+ const msg = `${LOG_PREFIX} on-chain confirmation did not complete (waitForConfirmation did not return true) for ${txHash} on ${network}`;
266
+ (_m = params.onProgress) === null || _m === void 0 ? void 0 : _m.call(params, 'failed', {
267
+ errorMessage: msg,
268
+ txHash,
269
+ routeIndex: idx,
270
+ stepIndex,
271
+ totalSteps,
272
+ step: populated,
273
+ });
274
+ throw new LifiReportedError(msg);
275
+ }
276
+ const bridgeTool = statusBridgeFromStepTool(populated.tool);
277
+ const crossLike = populated.type === 'cross' ||
278
+ populated.action.fromChainId !== populated.action.toChainId;
279
+ if (crossLike && bridgeTool) {
280
+ (_o = params.onProgress) === null || _o === void 0 ? void 0 : _o.call(params, 'lifi_pending', {
281
+ route,
282
+ routeIndex: idx,
283
+ step: populated,
284
+ stepIndex,
285
+ totalSteps,
286
+ txHash,
287
+ });
288
+ const pollOpts = (_p = params.statusPoll) !== null && _p !== void 0 ? _p : {};
289
+ const terminal = yield this.pollStatus({
290
+ txHash,
291
+ fromChain: params.fromChain,
292
+ toChain: params.toChain,
293
+ bridge: bridgeTool,
294
+ }, pollOpts);
295
+ (_q = params.onProgress) === null || _q === void 0 ? void 0 : _q.call(params, 'step_done', {
296
+ route,
297
+ routeIndex: idx,
298
+ step: populated,
299
+ stepIndex,
300
+ totalSteps,
301
+ txHash,
302
+ lifiStatus: terminal,
303
+ });
304
+ }
305
+ else {
306
+ (_r = params.onProgress) === null || _r === void 0 ? void 0 : _r.call(params, 'step_done', {
307
+ route,
308
+ routeIndex: idx,
309
+ step: populated,
310
+ stepIndex,
311
+ totalSteps,
312
+ txHash,
313
+ });
314
+ }
315
+ stepsOut.push(populated);
316
+ }
317
+ (_s = params.onProgress) === null || _s === void 0 ? void 0 : _s.call(params, 'complete', { route, routeIndex: idx });
318
+ return { hashes, steps: stepsOut, route };
319
+ }
320
+ catch (error) {
321
+ if (!(error instanceof LifiReportedError)) {
322
+ const errorMessage = error instanceof Error ? error.message : String(error);
323
+ (_t = params.onProgress) === null || _t === void 0 ? void 0 : _t.call(params, 'failed', { errorMessage });
324
+ }
325
+ throw error;
326
+ }
327
+ });
328
+ }
62
329
  }