@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.
- package/lib/commonjs/index.js +127 -9
- package/lib/commonjs/index.test.js +13 -0
- package/lib/commonjs/integrations/delegations/index.js +109 -2
- package/lib/commonjs/integrations/delegations/index.test.js +171 -0
- package/lib/commonjs/integrations/ramps/noah/index.test.js +18 -5
- package/lib/commonjs/integrations/trading/index.js +16 -5
- package/lib/commonjs/integrations/trading/lifi/index.js +297 -25
- package/lib/commonjs/integrations/trading/lifi/lifi.tradeAsset.test.js +360 -0
- package/lib/commonjs/integrations/trading/lifi/lifiStatusPoll.js +118 -0
- package/lib/commonjs/integrations/trading/lifi/lifiStatusPoll.test.js +66 -0
- package/lib/commonjs/integrations/trading/zero-x/index.js +129 -26
- package/lib/commonjs/integrations/trading/zero-x/index.test.js +163 -1
- package/lib/commonjs/integrations/yield/index.js +18 -4
- package/lib/commonjs/integrations/yield/yieldxyz.getValidators.test.js +71 -0
- package/lib/commonjs/integrations/yield/yieldxyz.highLevel.test.js +438 -0
- package/lib/commonjs/integrations/yield/yieldxyz.js +541 -1
- package/lib/commonjs/internal/pollLoop.js +64 -0
- package/lib/commonjs/internal/pollLoop.test.js +100 -0
- package/lib/commonjs/internal/stripStalePlanningNonce.js +65 -0
- package/lib/commonjs/internal/stripStalePlanningNonce.test.js +35 -0
- package/lib/commonjs/internal/waitForEvmOrUserOpConfirmation.js +155 -0
- package/lib/commonjs/internal/waitForEvmOrUserOpConfirmation.test.js +33 -0
- package/lib/commonjs/internal/waitForEvmTxConfirmation.js +104 -0
- package/lib/commonjs/internal/waitForSolanaTxConfirmation.js +106 -0
- package/lib/commonjs/internal/yieldEvmNetwork.js +60 -0
- package/lib/commonjs/mpc/index.js +116 -1
- package/lib/commonjs/provider/index.js +17 -0
- package/lib/commonjs/shared/trace/index.js +0 -1
- package/lib/esm/index.js +127 -9
- package/lib/esm/index.test.js +13 -0
- package/lib/esm/integrations/delegations/index.js +109 -2
- package/lib/esm/integrations/delegations/index.test.js +171 -0
- package/lib/esm/integrations/ramps/noah/index.test.js +18 -5
- package/lib/esm/integrations/trading/index.js +16 -5
- package/lib/esm/integrations/trading/lifi/index.js +292 -25
- package/lib/esm/integrations/trading/lifi/lifi.tradeAsset.test.js +332 -0
- package/lib/esm/integrations/trading/lifi/lifiStatusPoll.js +113 -0
- package/lib/esm/integrations/trading/lifi/lifiStatusPoll.test.js +64 -0
- package/lib/esm/integrations/trading/zero-x/index.js +129 -26
- package/lib/esm/integrations/trading/zero-x/index.test.js +141 -2
- package/lib/esm/integrations/yield/index.js +18 -4
- package/lib/esm/integrations/yield/yieldxyz.getValidators.test.js +66 -0
- package/lib/esm/integrations/yield/yieldxyz.highLevel.test.js +433 -0
- package/lib/esm/integrations/yield/yieldxyz.js +541 -1
- package/lib/esm/internal/pollLoop.js +59 -0
- package/lib/esm/internal/pollLoop.test.js +98 -0
- package/lib/esm/internal/stripStalePlanningNonce.js +61 -0
- package/lib/esm/internal/stripStalePlanningNonce.test.js +33 -0
- package/lib/esm/internal/waitForEvmOrUserOpConfirmation.js +151 -0
- package/lib/esm/internal/waitForEvmOrUserOpConfirmation.test.js +31 -0
- package/lib/esm/internal/waitForEvmTxConfirmation.js +100 -0
- package/lib/esm/internal/waitForSolanaTxConfirmation.js +102 -0
- package/lib/esm/internal/yieldEvmNetwork.js +55 -0
- package/lib/esm/mpc/index.js +116 -1
- package/lib/esm/provider/index.js +17 -0
- package/lib/esm/shared/trace/index.js +0 -1
- package/noah-types.d.ts +16 -2
- package/package.json +3 -2
- package/src/index.test.ts +15 -0
- package/src/index.ts +203 -14
- package/src/integrations/delegations/index.test.ts +251 -0
- package/src/integrations/delegations/index.ts +202 -4
- package/src/integrations/ramps/noah/index.test.ts +18 -5
- package/src/integrations/trading/index.ts +10 -7
- package/src/integrations/trading/lifi/index.ts +388 -28
- package/src/integrations/trading/lifi/lifi.tradeAsset.test.ts +436 -0
- package/src/integrations/trading/lifi/lifiStatusPoll.test.ts +74 -0
- package/src/integrations/trading/lifi/lifiStatusPoll.ts +158 -0
- package/src/integrations/trading/zero-x/index.test.ts +297 -1
- package/src/integrations/trading/zero-x/index.ts +181 -27
- package/src/integrations/yield/index.ts +24 -4
- package/src/integrations/yield/yieldxyz.getValidators.test.ts +70 -0
- package/src/integrations/yield/yieldxyz.highLevel.test.ts +536 -0
- package/src/integrations/yield/yieldxyz.ts +762 -8
- package/src/internal/pollLoop.test.ts +109 -0
- package/src/internal/pollLoop.ts +87 -0
- package/src/internal/stripStalePlanningNonce.test.ts +38 -0
- package/src/internal/stripStalePlanningNonce.ts +66 -0
- package/src/internal/waitForEvmOrUserOpConfirmation.test.ts +31 -0
- package/src/internal/waitForEvmOrUserOpConfirmation.ts +194 -0
- package/src/internal/waitForEvmTxConfirmation.ts +155 -0
- package/src/internal/waitForSolanaTxConfirmation.ts +135 -0
- package/src/internal/yieldEvmNetwork.ts +57 -0
- package/src/mpc/index.ts +142 -1
- package/src/provider/index.ts +25 -0
- package/src/shared/trace/index.ts +0 -1
- package/src/shared/types/README.md +6 -0
- package/src/shared/types/api.ts +12 -1
- package/src/shared/types/common.ts +332 -20
- package/src/shared/types/delegations.ts +10 -0
- package/src/shared/types/index.ts +1 -0
- package/src/shared/types/lifi.ts +82 -0
- package/src/shared/types/noah.ts +124 -33
- package/src/shared/types/yieldxyz.ts +193 -0
- package/src/shared/types/zero-x.ts +66 -0
- package/types.d.ts +6 -0
|
@@ -9,9 +9,29 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
9
9
|
});
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
const logger_1 = require("../../logger");
|
|
13
|
+
const waitForEvmTxConfirmation_1 = require("../../internal/waitForEvmTxConfirmation");
|
|
14
|
+
const stripStalePlanningNonce_1 = require("../../internal/stripStalePlanningNonce");
|
|
15
|
+
const yieldEvmNetwork_1 = require("../../internal/yieldEvmNetwork");
|
|
16
|
+
const LOG_PREFIX = '[YieldXyz]';
|
|
17
|
+
/** CAIP-2 chain ID format: namespace:reference (e.g. eip155:1, solana:5eykt...) */
|
|
18
|
+
const CAIP2_CHAIN_ID_REGEX = /^[a-z0-9-]+:[a-zA-Z0-9]+$/;
|
|
12
19
|
class YieldXyz {
|
|
13
|
-
constructor({ mpc }) {
|
|
20
|
+
constructor({ mpc, waitForConfirmation, evmRequestFn, evmPollerOptions, }) {
|
|
14
21
|
this.mpc = mpc;
|
|
22
|
+
this.waitForConfirmationFn = waitForConfirmation;
|
|
23
|
+
this.evmRequestFn = evmRequestFn;
|
|
24
|
+
this.evmPollerDefaults = evmPollerOptions;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Configures the signer used by deposit() and withdraw() when no per-call
|
|
28
|
+
* `signAndSendTransaction` option is provided. Typically called once after construction
|
|
29
|
+
* (e.g. Portal wires in its MPC signer via this method instead of the constructor).
|
|
30
|
+
*
|
|
31
|
+
* Per-call `signAndSendTransaction` in {@link YieldSubmitOptions} always takes precedence.
|
|
32
|
+
*/
|
|
33
|
+
setSignAndSendTransaction(fn) {
|
|
34
|
+
this.signAndSendTransactionFn = fn;
|
|
15
35
|
}
|
|
16
36
|
/**
|
|
17
37
|
* Retrieves yield balances for specified addresses and networks.
|
|
@@ -111,5 +131,525 @@ class YieldXyz {
|
|
|
111
131
|
return (_a = this.mpc) === null || _a === void 0 ? void 0 : _a.getYieldXyzTransaction(transactionId);
|
|
112
132
|
});
|
|
113
133
|
}
|
|
134
|
+
/**
|
|
135
|
+
* Resolve suggested defaults (amount, validators) from Portal yield defaults map.
|
|
136
|
+
* Calls the dedicated Yield.xyz defaults endpoint used in the deposit/withdraw flow.
|
|
137
|
+
*/
|
|
138
|
+
getYieldDefaults(req) {
|
|
139
|
+
var _a;
|
|
140
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
141
|
+
return (_a = this.mpc) === null || _a === void 0 ? void 0 : _a.getYieldXyzDefaults(req);
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
getValidators(yieldId) {
|
|
145
|
+
var _a, _b, _c, _d;
|
|
146
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
147
|
+
const res = yield this.mpc.getYieldXyzValidators(yieldId);
|
|
148
|
+
logger_1.sdkLogger.debug(`${LOG_PREFIX} getValidators raw response`, res);
|
|
149
|
+
if (res.error) {
|
|
150
|
+
logger_1.sdkLogger.error(`${LOG_PREFIX} getValidators error`, res.error);
|
|
151
|
+
throw new Error(`[YieldXyz] getValidators failed: ${res.error}`);
|
|
152
|
+
}
|
|
153
|
+
const d = res.data;
|
|
154
|
+
const validators = (_c = (_a = d === null || d === void 0 ? void 0 : d.validators) !== null && _a !== void 0 ? _a : (_b = d === null || d === void 0 ? void 0 : d.rawResponse) === null || _b === void 0 ? void 0 : _b.validators) !== null && _c !== void 0 ? _c : (_d = d === null || d === void 0 ? void 0 : d.rawResponse) === null || _d === void 0 ? void 0 : _d.items;
|
|
155
|
+
logger_1.sdkLogger.debug(`${LOG_PREFIX} getValidators processed`, { validators });
|
|
156
|
+
if (!validators || !Array.isArray(validators)) {
|
|
157
|
+
logger_1.sdkLogger.error(`${LOG_PREFIX} No validators found for yieldId="${yieldId}"`, { data: d });
|
|
158
|
+
throw new Error(`[YieldXyz] No validators in response for yieldId="${yieldId}"`);
|
|
159
|
+
}
|
|
160
|
+
return validators;
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* @internal Validates and trims `chain` to a full CAIP-2 id (no aliases or numeric shortcuts).
|
|
165
|
+
*/
|
|
166
|
+
requireFullCaip2Chain(chain) {
|
|
167
|
+
const c = chain.trim();
|
|
168
|
+
if (!c) {
|
|
169
|
+
throw new Error('[YieldXyz] chain is required.');
|
|
170
|
+
}
|
|
171
|
+
if (!CAIP2_CHAIN_ID_REGEX.test(c)) {
|
|
172
|
+
throw new Error(`[YieldXyz] chain must be a full CAIP-2 id (e.g. eip155:11155111). Received: "${chain}"`);
|
|
173
|
+
}
|
|
174
|
+
return c;
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* @internal When `params` includes a non-empty `yieldId`, returns it. Otherwise requires
|
|
178
|
+
* `chain` + `token`, validates CAIP-2, and resolves `yieldId` from Portal yield defaults.
|
|
179
|
+
*/
|
|
180
|
+
resolveYieldIdForHighLevelAction(params) {
|
|
181
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
182
|
+
const fromYieldId = 'yieldId' in params && params.yieldId != null
|
|
183
|
+
? String(params.yieldId).trim()
|
|
184
|
+
: '';
|
|
185
|
+
if (fromYieldId !== '') {
|
|
186
|
+
return { yieldId: fromYieldId };
|
|
187
|
+
}
|
|
188
|
+
if (!('chain' in params) || !('token' in params)) {
|
|
189
|
+
throw new Error('[YieldXyz] Provide either yieldId, or both chain (full CAIP-2) and token.');
|
|
190
|
+
}
|
|
191
|
+
const chainCaip2 = this.requireFullCaip2Chain(params.chain);
|
|
192
|
+
const token = params.token.trim();
|
|
193
|
+
const yieldId = yield this.resolveYieldIdFromPortalDefaults(chainCaip2, token);
|
|
194
|
+
return { yieldId, chain: chainCaip2, token };
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* @internal Loads Portal yield defaults and reads `yieldId` for the exact map key `{caip2}:{token}`.
|
|
199
|
+
*/
|
|
200
|
+
resolveYieldIdFromPortalDefaults(chainCaip2, tokenSymbol) {
|
|
201
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
202
|
+
const token = tokenSymbol.trim();
|
|
203
|
+
if (!token) {
|
|
204
|
+
throw new Error('[YieldXyz] token is required; use the exact symbol suffix from the yield defaults map.');
|
|
205
|
+
}
|
|
206
|
+
const key = `${chainCaip2}:${token}`;
|
|
207
|
+
const res = yield this.getYieldDefaults({
|
|
208
|
+
includeOpportunities: false,
|
|
209
|
+
});
|
|
210
|
+
if (res.error) {
|
|
211
|
+
throw new Error(`[YieldXyz] Failed to get yield defaults: ${res.error}`);
|
|
212
|
+
}
|
|
213
|
+
if (!res.data) {
|
|
214
|
+
throw new Error('[YieldXyz] No data returned from yield defaults endpoint');
|
|
215
|
+
}
|
|
216
|
+
const entry = res.data[key];
|
|
217
|
+
const yieldId = entry === null || entry === void 0 ? void 0 : entry.yieldId;
|
|
218
|
+
if (yieldId == null || yieldId === '') {
|
|
219
|
+
throw new Error(`[YieldXyz] No default yield for key "${key}". Use chain and token exactly as in the Portal yield defaults response.`);
|
|
220
|
+
}
|
|
221
|
+
return yieldId;
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* High-level deposit: build enter yield action, sign and submit each transaction, track hashes.
|
|
226
|
+
*
|
|
227
|
+
* The signer is resolved in priority order:
|
|
228
|
+
* 1. `options.signAndSendTransaction` — per-call override.
|
|
229
|
+
* 2. Instance setter — configured via {@link YieldXyz.setSignAndSendTransaction} (e.g. Portal).
|
|
230
|
+
* 3. Error — thrown if neither is available.
|
|
231
|
+
*
|
|
232
|
+
* Supply either **`yieldId`** + `amount` (optional `address` / `arguments`), or full **CAIP-2**
|
|
233
|
+
* **`chain`** + **`token`** + `amount` so the SDK can resolve `yieldId` from Portal yield defaults.
|
|
234
|
+
* Optional {@link YieldSubmitOptions.onProgress} fires the same steps regardless of input mode.
|
|
235
|
+
*/
|
|
236
|
+
deposit(params, options) {
|
|
237
|
+
var _a;
|
|
238
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
239
|
+
const signAndSend = (_a = options === null || options === void 0 ? void 0 : options.signAndSendTransaction) !== null && _a !== void 0 ? _a : this.signAndSendTransactionFn;
|
|
240
|
+
if (!signAndSend) {
|
|
241
|
+
throw new Error('[YieldXyz] No signer configured. Call setSignAndSendTransaction() on the instance or pass signAndSendTransaction in options.');
|
|
242
|
+
}
|
|
243
|
+
const { yieldId, chain: resolvedChain, token: resolvedToken } = yield this.resolveYieldIdForHighLevelAction(params);
|
|
244
|
+
logger_1.sdkLogger.info(`${LOG_PREFIX} deposit: entry`, {
|
|
245
|
+
amount: params.amount,
|
|
246
|
+
yieldId,
|
|
247
|
+
token: resolvedToken,
|
|
248
|
+
chain: resolvedChain,
|
|
249
|
+
usedExplicitYieldId: resolvedChain === undefined,
|
|
250
|
+
hasAddress: Boolean(params.address),
|
|
251
|
+
hasArguments: Boolean(params.arguments),
|
|
252
|
+
});
|
|
253
|
+
logger_1.sdkLogger.debug(`${LOG_PREFIX} deposit: resolved yieldId`, { yieldId });
|
|
254
|
+
const request = {
|
|
255
|
+
yieldId,
|
|
256
|
+
address: params.address,
|
|
257
|
+
arguments: Object.assign(Object.assign({}, params.arguments), { amount: params.amount }),
|
|
258
|
+
};
|
|
259
|
+
try {
|
|
260
|
+
const response = yield this.enter(request);
|
|
261
|
+
const effectiveWaitForConfirmation = this.resolveEffectiveWaitForConfirmation(options);
|
|
262
|
+
const base = yield this.executeAndTrack(response, signAndSend, options === null || options === void 0 ? void 0 : options.onProgress, effectiveWaitForConfirmation, 'deposit');
|
|
263
|
+
const result = Object.assign(Object.assign({}, base), (resolvedChain !== undefined && resolvedToken !== undefined
|
|
264
|
+
? { chain: resolvedChain, token: resolvedToken }
|
|
265
|
+
: {}));
|
|
266
|
+
logger_1.sdkLogger.info(`${LOG_PREFIX} deposit: complete`, {
|
|
267
|
+
hashes: result.hashes,
|
|
268
|
+
yieldId: result.yieldId,
|
|
269
|
+
status: result.status,
|
|
270
|
+
yieldOpportunityDetails: result.yieldOpportunityDetails,
|
|
271
|
+
});
|
|
272
|
+
return result;
|
|
273
|
+
}
|
|
274
|
+
catch (error) {
|
|
275
|
+
logger_1.sdkLogger.debug(`${LOG_PREFIX} deposit: failed, re-throwing`, error);
|
|
276
|
+
throw error;
|
|
277
|
+
}
|
|
278
|
+
});
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* High-level withdraw: same dual input modes, `yieldId` resolution, and signer fallback
|
|
282
|
+
* order as {@link YieldXyz.deposit}.
|
|
283
|
+
*/
|
|
284
|
+
withdraw(params, options) {
|
|
285
|
+
var _a;
|
|
286
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
287
|
+
const signAndSend = (_a = options === null || options === void 0 ? void 0 : options.signAndSendTransaction) !== null && _a !== void 0 ? _a : this.signAndSendTransactionFn;
|
|
288
|
+
if (!signAndSend) {
|
|
289
|
+
throw new Error('[YieldXyz] No signer configured. Call setSignAndSendTransaction() on the instance or pass signAndSendTransaction in options.');
|
|
290
|
+
}
|
|
291
|
+
const { yieldId, chain: resolvedChain, token: resolvedToken } = yield this.resolveYieldIdForHighLevelAction(params);
|
|
292
|
+
logger_1.sdkLogger.debug(`${LOG_PREFIX} withdraw: entry`, {
|
|
293
|
+
amount: params.amount,
|
|
294
|
+
yieldId,
|
|
295
|
+
token: resolvedToken,
|
|
296
|
+
chain: resolvedChain,
|
|
297
|
+
usedExplicitYieldId: resolvedChain === undefined,
|
|
298
|
+
hasAddress: Boolean(params.address),
|
|
299
|
+
hasArguments: Boolean(params.arguments),
|
|
300
|
+
});
|
|
301
|
+
logger_1.sdkLogger.debug(`${LOG_PREFIX} withdraw: resolved yieldId`, { yieldId });
|
|
302
|
+
const request = {
|
|
303
|
+
yieldId,
|
|
304
|
+
address: params.address,
|
|
305
|
+
arguments: Object.assign(Object.assign({}, params.arguments), { amount: params.amount }),
|
|
306
|
+
};
|
|
307
|
+
try {
|
|
308
|
+
const response = yield this.exit(request);
|
|
309
|
+
const effectiveWaitForConfirmation = this.resolveEffectiveWaitForConfirmation(options);
|
|
310
|
+
const base = yield this.executeAndTrack(response, signAndSend, options === null || options === void 0 ? void 0 : options.onProgress, effectiveWaitForConfirmation, 'withdraw');
|
|
311
|
+
const result = Object.assign(Object.assign({}, base), (resolvedChain !== undefined && resolvedToken !== undefined
|
|
312
|
+
? { chain: resolvedChain, token: resolvedToken }
|
|
313
|
+
: {}));
|
|
314
|
+
logger_1.sdkLogger.info(`${LOG_PREFIX} withdraw: complete`, {
|
|
315
|
+
hashes: result.hashes,
|
|
316
|
+
yieldId: result.yieldId,
|
|
317
|
+
status: result.status,
|
|
318
|
+
yieldOpportunityDetails: result.yieldOpportunityDetails,
|
|
319
|
+
});
|
|
320
|
+
return result;
|
|
321
|
+
}
|
|
322
|
+
catch (error) {
|
|
323
|
+
logger_1.sdkLogger.debug(`${LOG_PREFIX} withdraw: failed, re-throwing`, error);
|
|
324
|
+
throw error;
|
|
325
|
+
}
|
|
326
|
+
});
|
|
327
|
+
}
|
|
328
|
+
extractTransactions(response) {
|
|
329
|
+
var _a, _b;
|
|
330
|
+
const transactions = (_b = (_a = response.data) === null || _a === void 0 ? void 0 : _a.rawResponse) === null || _b === void 0 ? void 0 : _b.transactions;
|
|
331
|
+
if (transactions &&
|
|
332
|
+
Array.isArray(transactions) &&
|
|
333
|
+
transactions.length > 0) {
|
|
334
|
+
return transactions;
|
|
335
|
+
}
|
|
336
|
+
return [];
|
|
337
|
+
}
|
|
338
|
+
buildYieldOpportunityDetails(response) {
|
|
339
|
+
var _a;
|
|
340
|
+
const raw = (_a = response.data) === null || _a === void 0 ? void 0 : _a.rawResponse;
|
|
341
|
+
if (!raw) {
|
|
342
|
+
return { yieldId: '' };
|
|
343
|
+
}
|
|
344
|
+
return {
|
|
345
|
+
yieldId: raw.yieldId,
|
|
346
|
+
intent: raw.intent,
|
|
347
|
+
type: raw.type,
|
|
348
|
+
executionPattern: raw.executionPattern,
|
|
349
|
+
status: raw.status,
|
|
350
|
+
amount: raw.amount,
|
|
351
|
+
amountUsd: raw.amountUsd,
|
|
352
|
+
};
|
|
353
|
+
}
|
|
354
|
+
parseUnsignedToObject(unsigned) {
|
|
355
|
+
if (unsigned == null)
|
|
356
|
+
return {};
|
|
357
|
+
if (typeof unsigned === 'object')
|
|
358
|
+
return Object.assign({}, unsigned);
|
|
359
|
+
try {
|
|
360
|
+
const parsed = JSON.parse(unsigned);
|
|
361
|
+
// Validate parsed result is a plain object (not null, not array)
|
|
362
|
+
if (parsed != null &&
|
|
363
|
+
typeof parsed === 'object' &&
|
|
364
|
+
!Array.isArray(parsed)) {
|
|
365
|
+
return parsed;
|
|
366
|
+
}
|
|
367
|
+
logger_1.sdkLogger.warn(`${LOG_PREFIX} JSON.parse returned non-object type: ${typeof parsed}`);
|
|
368
|
+
return {};
|
|
369
|
+
}
|
|
370
|
+
catch (_a) {
|
|
371
|
+
return {};
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
getTransactionPayloadSummary(payload) {
|
|
375
|
+
var _a, _b, _c;
|
|
376
|
+
const obj = this.parseUnsignedToObject(typeof payload === 'string'
|
|
377
|
+
? payload
|
|
378
|
+
: payload);
|
|
379
|
+
const data = (_a = obj.data) !== null && _a !== void 0 ? _a : obj.input;
|
|
380
|
+
const dataStr = typeof data === 'string' ? data : JSON.stringify(data);
|
|
381
|
+
return {
|
|
382
|
+
from: obj.from,
|
|
383
|
+
to: obj.to,
|
|
384
|
+
dataLength: (_b = dataStr === null || dataStr === void 0 ? void 0 : dataStr.length) !== null && _b !== void 0 ? _b : 0,
|
|
385
|
+
value: obj.value,
|
|
386
|
+
gasLimit: (_c = obj.gas) !== null && _c !== void 0 ? _c : obj.gasLimit,
|
|
387
|
+
nonce: obj.nonce,
|
|
388
|
+
maxFeePerGas: obj.maxFeePerGas,
|
|
389
|
+
maxPriorityFeePerGas: obj.maxPriorityFeePerGas,
|
|
390
|
+
};
|
|
391
|
+
}
|
|
392
|
+
logError(context, error) {
|
|
393
|
+
const err = error;
|
|
394
|
+
logger_1.sdkLogger.error(`${LOG_PREFIX} ${context}:`, error);
|
|
395
|
+
if (err.response !== undefined) {
|
|
396
|
+
logger_1.sdkLogger.debug(`${LOG_PREFIX} ${context} HTTP response:`, err.response);
|
|
397
|
+
}
|
|
398
|
+
if (err.status !== undefined) {
|
|
399
|
+
logger_1.sdkLogger.debug(`${LOG_PREFIX} ${context} HTTP status:`, err.status);
|
|
400
|
+
}
|
|
401
|
+
if (err.data !== undefined) {
|
|
402
|
+
logger_1.sdkLogger.debug(`${LOG_PREFIX} ${context} HTTP response data:`, err.data);
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
resolveEffectiveWaitForConfirmation(options) {
|
|
406
|
+
var _a;
|
|
407
|
+
if (options === null || options === void 0 ? void 0 : options.waitForConfirmation) {
|
|
408
|
+
return options.waitForConfirmation;
|
|
409
|
+
}
|
|
410
|
+
if (this.waitForConfirmationFn) {
|
|
411
|
+
return this.waitForConfirmationFn;
|
|
412
|
+
}
|
|
413
|
+
const evmFn = (_a = options === null || options === void 0 ? void 0 : options.evmRequestFn) !== null && _a !== void 0 ? _a : this.evmRequestFn;
|
|
414
|
+
if (!evmFn) {
|
|
415
|
+
return undefined;
|
|
416
|
+
}
|
|
417
|
+
const pollerOpts = Object.assign(Object.assign({}, this.evmPollerDefaults), options === null || options === void 0 ? void 0 : options.evmPollerOptions);
|
|
418
|
+
return (txHash, network) => __awaiter(this, void 0, void 0, function* () {
|
|
419
|
+
var _b;
|
|
420
|
+
if (!(0, yieldEvmNetwork_1.isYieldEvmNetwork)(network)) {
|
|
421
|
+
logger_1.sdkLogger.warn(`${LOG_PREFIX} Cannot verify confirmation for non-EVM network ${network}. ` +
|
|
422
|
+
'Internal EVM poller fallback does not support non-EVM networks.');
|
|
423
|
+
return false;
|
|
424
|
+
}
|
|
425
|
+
const caip2 = network.startsWith('eip155:')
|
|
426
|
+
? network
|
|
427
|
+
: (_b = (0, yieldEvmNetwork_1.resolveYieldNetworkToCaip2)(network)) !== null && _b !== void 0 ? _b : network;
|
|
428
|
+
return (0, waitForEvmTxConfirmation_1.waitForEvmTxConfirmation)(txHash, caip2, evmFn, {
|
|
429
|
+
pollIntervalMs: pollerOpts.pollIntervalMs,
|
|
430
|
+
timeoutMs: pollerOpts.timeoutMs,
|
|
431
|
+
onTimeout: 'resolve_false',
|
|
432
|
+
});
|
|
433
|
+
});
|
|
434
|
+
}
|
|
435
|
+
executeAndTrack(response, signAndSend, onProgress, waitForConfirmation, method = 'deposit') {
|
|
436
|
+
var _a, _b, _c, _d, _e;
|
|
437
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
438
|
+
const transactions = this.extractTransactions(response);
|
|
439
|
+
logger_1.sdkLogger.debug(`${LOG_PREFIX} executeAndTrack: transaction count`, {
|
|
440
|
+
method,
|
|
441
|
+
transactionCount: transactions.length,
|
|
442
|
+
});
|
|
443
|
+
if (transactions.length === 0) {
|
|
444
|
+
throw new Error('No transactions in yield action response.');
|
|
445
|
+
}
|
|
446
|
+
const total = transactions.length;
|
|
447
|
+
const hashes = [];
|
|
448
|
+
let confirmationsReached = 0;
|
|
449
|
+
let confirmationsRequired = waitForConfirmation ? total : 0;
|
|
450
|
+
for (let index = 0; index < transactions.length; index++) {
|
|
451
|
+
const tx = transactions[index];
|
|
452
|
+
// Validate transaction exists (defensive check for sparse arrays)
|
|
453
|
+
if (!tx) {
|
|
454
|
+
throw new Error(`Transaction at index ${index} is undefined or null. This indicates a malformed API response.`);
|
|
455
|
+
}
|
|
456
|
+
try {
|
|
457
|
+
if (!tx.id) {
|
|
458
|
+
throw new Error(`Transaction at index ${index} is missing required field "id".`);
|
|
459
|
+
}
|
|
460
|
+
if (tx.network == null || tx.network === '') {
|
|
461
|
+
throw new Error(`Transaction ${tx.id} is missing required field "network".`);
|
|
462
|
+
}
|
|
463
|
+
if (tx.unsignedTransaction == null) {
|
|
464
|
+
throw new Error(`Transaction ${tx.id} has no unsignedTransaction to sign.`);
|
|
465
|
+
}
|
|
466
|
+
const rawUnsigned = tx.unsignedTransaction;
|
|
467
|
+
let payloadToSend = rawUnsigned;
|
|
468
|
+
const isEvm = typeof tx.network === 'string' && (0, yieldEvmNetwork_1.isYieldEvmNetwork)(tx.network);
|
|
469
|
+
const resolvedNetwork = isEvm
|
|
470
|
+
? ((_a = (0, yieldEvmNetwork_1.resolveYieldNetworkToCaip2)(tx.network)) !== null && _a !== void 0 ? _a : tx.network)
|
|
471
|
+
: tx.network;
|
|
472
|
+
if (isEvm) {
|
|
473
|
+
const canStripNonce = typeof rawUnsigned === 'string' ||
|
|
474
|
+
(typeof rawUnsigned === 'object' &&
|
|
475
|
+
rawUnsigned !== null &&
|
|
476
|
+
!Array.isArray(rawUnsigned));
|
|
477
|
+
if (canStripNonce) {
|
|
478
|
+
payloadToSend = (0, stripStalePlanningNonce_1.stripStalePlanningNonceIfJsonObject)(rawUnsigned);
|
|
479
|
+
}
|
|
480
|
+
logger_1.sdkLogger.debug(`${LOG_PREFIX} executeAndTrack: nonce stripped for EVM tx`, {
|
|
481
|
+
index,
|
|
482
|
+
transactionId: tx.id,
|
|
483
|
+
network: tx.network,
|
|
484
|
+
payloadKind: typeof payloadToSend,
|
|
485
|
+
});
|
|
486
|
+
}
|
|
487
|
+
const payloadSummary = this.getTransactionPayloadSummary(payloadToSend);
|
|
488
|
+
logger_1.sdkLogger.debug(`${LOG_PREFIX} executeAndTrack: transaction preparation`, {
|
|
489
|
+
method,
|
|
490
|
+
index,
|
|
491
|
+
total,
|
|
492
|
+
transactionId: tx.id,
|
|
493
|
+
network: tx.network,
|
|
494
|
+
type: tx.type,
|
|
495
|
+
payloadSummary,
|
|
496
|
+
});
|
|
497
|
+
const progressSigning = {
|
|
498
|
+
step: 'signing',
|
|
499
|
+
index,
|
|
500
|
+
total,
|
|
501
|
+
};
|
|
502
|
+
logger_1.sdkLogger.debug(`${LOG_PREFIX} executeAndTrack: signing start`, {
|
|
503
|
+
method,
|
|
504
|
+
index,
|
|
505
|
+
total,
|
|
506
|
+
transactionId: tx.id,
|
|
507
|
+
});
|
|
508
|
+
onProgress === null || onProgress === void 0 ? void 0 : onProgress(progressSigning);
|
|
509
|
+
const hash = yield signAndSend(payloadToSend, resolvedNetwork);
|
|
510
|
+
if (typeof hash !== 'string' || hash.trim() === '') {
|
|
511
|
+
throw new Error(`Transaction ${tx.id} signing returned an empty or invalid hash.`);
|
|
512
|
+
}
|
|
513
|
+
hashes.push(hash);
|
|
514
|
+
logger_1.sdkLogger.debug(`${LOG_PREFIX} executeAndTrack: signing complete`, {
|
|
515
|
+
method,
|
|
516
|
+
index,
|
|
517
|
+
total,
|
|
518
|
+
transactionId: tx.id,
|
|
519
|
+
hash,
|
|
520
|
+
});
|
|
521
|
+
logger_1.sdkLogger.info(`${LOG_PREFIX} ${method}: submitted tx`, {
|
|
522
|
+
index: index + 1,
|
|
523
|
+
total,
|
|
524
|
+
hash,
|
|
525
|
+
});
|
|
526
|
+
const progressSubmitted = {
|
|
527
|
+
step: 'submitted',
|
|
528
|
+
index,
|
|
529
|
+
total,
|
|
530
|
+
hash,
|
|
531
|
+
};
|
|
532
|
+
logger_1.sdkLogger.debug(`${LOG_PREFIX} executeAndTrack: onProgress`, {
|
|
533
|
+
step: progressSubmitted.step,
|
|
534
|
+
index: progressSubmitted.index,
|
|
535
|
+
total: progressSubmitted.total,
|
|
536
|
+
hash: progressSubmitted.hash,
|
|
537
|
+
});
|
|
538
|
+
onProgress === null || onProgress === void 0 ? void 0 : onProgress(progressSubmitted);
|
|
539
|
+
if (waitForConfirmation) {
|
|
540
|
+
const progressConfirming = {
|
|
541
|
+
step: 'confirming',
|
|
542
|
+
index,
|
|
543
|
+
total,
|
|
544
|
+
hash,
|
|
545
|
+
};
|
|
546
|
+
logger_1.sdkLogger.info(`${LOG_PREFIX} executeAndTrack: waiting for confirmation`, {
|
|
547
|
+
method,
|
|
548
|
+
index,
|
|
549
|
+
total,
|
|
550
|
+
hash,
|
|
551
|
+
network: tx.network,
|
|
552
|
+
strategy: 'waitForConfirmation',
|
|
553
|
+
});
|
|
554
|
+
onProgress === null || onProgress === void 0 ? void 0 : onProgress(progressConfirming);
|
|
555
|
+
const waiterResult = yield waitForConfirmation(hash, resolvedNetwork);
|
|
556
|
+
const isConfirmed = waiterResult === true;
|
|
557
|
+
if (isConfirmed) {
|
|
558
|
+
confirmationsReached += 1;
|
|
559
|
+
logger_1.sdkLogger.debug(`${LOG_PREFIX} executeAndTrack: confirmation received`, {
|
|
560
|
+
method,
|
|
561
|
+
hash,
|
|
562
|
+
confirmationsReached,
|
|
563
|
+
total,
|
|
564
|
+
});
|
|
565
|
+
onProgress === null || onProgress === void 0 ? void 0 : onProgress({ step: 'confirmed', index, total, hash });
|
|
566
|
+
}
|
|
567
|
+
else {
|
|
568
|
+
logger_1.sdkLogger.debug(`${LOG_PREFIX} executeAndTrack: confirmation not reached (waitForConfirmation did not return true)`, {
|
|
569
|
+
method,
|
|
570
|
+
hash,
|
|
571
|
+
confirmationsReached,
|
|
572
|
+
total,
|
|
573
|
+
waiterResult,
|
|
574
|
+
});
|
|
575
|
+
// Uncertain confirmation (timeout / false / no response): safe stop.
|
|
576
|
+
// Track the hash with backend before stopping, then return partial result.
|
|
577
|
+
logger_1.sdkLogger.debug(`${LOG_PREFIX} executeAndTrack: track (submitTransactionHash) call before break`, {
|
|
578
|
+
method,
|
|
579
|
+
transactionId: tx.id,
|
|
580
|
+
hash,
|
|
581
|
+
});
|
|
582
|
+
yield this.track({
|
|
583
|
+
transactionId: tx.id,
|
|
584
|
+
hash,
|
|
585
|
+
});
|
|
586
|
+
break;
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
logger_1.sdkLogger.debug(`${LOG_PREFIX} executeAndTrack: track (submitTransactionHash) call`, {
|
|
590
|
+
method,
|
|
591
|
+
transactionId: tx.id,
|
|
592
|
+
hash,
|
|
593
|
+
});
|
|
594
|
+
const trackResponse = yield this.track({
|
|
595
|
+
transactionId: tx.id,
|
|
596
|
+
hash,
|
|
597
|
+
});
|
|
598
|
+
logger_1.sdkLogger.debug(`${LOG_PREFIX} executeAndTrack: track response`, {
|
|
599
|
+
method,
|
|
600
|
+
transactionId: tx.id,
|
|
601
|
+
hash,
|
|
602
|
+
trackStatus: (_c = (_b = trackResponse === null || trackResponse === void 0 ? void 0 : trackResponse.data) === null || _b === void 0 ? void 0 : _b.rawResponse) === null || _c === void 0 ? void 0 : _c.status,
|
|
603
|
+
});
|
|
604
|
+
}
|
|
605
|
+
catch (error) {
|
|
606
|
+
this.logError(`executeAndTrack ${method} failed at index ${index}`, error);
|
|
607
|
+
logger_1.sdkLogger.debug(`${LOG_PREFIX} executeAndTrack: error context`, {
|
|
608
|
+
method,
|
|
609
|
+
index,
|
|
610
|
+
total,
|
|
611
|
+
transactionId: tx.id,
|
|
612
|
+
network: tx.network,
|
|
613
|
+
hashesSoFar: hashes.length,
|
|
614
|
+
});
|
|
615
|
+
throw error;
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
const rawResponse = (_d = response.data) === null || _d === void 0 ? void 0 : _d.rawResponse;
|
|
619
|
+
const yieldId = (_e = rawResponse === null || rawResponse === void 0 ? void 0 : rawResponse.yieldId) !== null && _e !== void 0 ? _e : '';
|
|
620
|
+
const yieldOpportunityDetails = this.buildYieldOpportunityDetails(response);
|
|
621
|
+
// Determine status based on confirmation semantics from docs:
|
|
622
|
+
// - If no confirmations required (no waitForConfirmation): SUCCESS
|
|
623
|
+
// - If all required confirmations reached: SUCCESS
|
|
624
|
+
// - If some confirmations reached but not all: PARTIAL_SUCCESS
|
|
625
|
+
// - If confirmations required but zero reached: FAILED
|
|
626
|
+
let status;
|
|
627
|
+
if (confirmationsRequired === 0) {
|
|
628
|
+
status = 'SUCCESS';
|
|
629
|
+
}
|
|
630
|
+
else if (confirmationsReached === confirmationsRequired) {
|
|
631
|
+
status = 'SUCCESS';
|
|
632
|
+
}
|
|
633
|
+
else if (confirmationsReached > 0) {
|
|
634
|
+
status = 'PARTIAL_SUCCESS';
|
|
635
|
+
}
|
|
636
|
+
else {
|
|
637
|
+
status = 'FAILED';
|
|
638
|
+
}
|
|
639
|
+
logger_1.sdkLogger.info(`${LOG_PREFIX} ${method}: executeAndTrack complete`, {
|
|
640
|
+
yieldId,
|
|
641
|
+
hashCount: hashes.length,
|
|
642
|
+
confirmationsReached,
|
|
643
|
+
confirmationsRequired,
|
|
644
|
+
status,
|
|
645
|
+
});
|
|
646
|
+
return {
|
|
647
|
+
hashes,
|
|
648
|
+
yieldId,
|
|
649
|
+
yieldOpportunityDetails,
|
|
650
|
+
status,
|
|
651
|
+
};
|
|
652
|
+
});
|
|
653
|
+
}
|
|
114
654
|
}
|
|
115
655
|
exports.default = YieldXyz;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Domain-agnostic poll loop (sleep + deadline + optional backoff).
|
|
4
|
+
* LiFi / other modules supply classification via `tick`.
|
|
5
|
+
*/
|
|
6
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
7
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
8
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
9
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
10
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
11
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
12
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
13
|
+
});
|
|
14
|
+
};
|
|
15
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
+
exports.pollLoop = exports.PollLoopTimeoutError = void 0;
|
|
17
|
+
class PollLoopTimeoutError extends Error {
|
|
18
|
+
constructor(message) {
|
|
19
|
+
super(message);
|
|
20
|
+
this.name = 'PollLoopTimeoutError';
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
exports.PollLoopTimeoutError = PollLoopTimeoutError;
|
|
24
|
+
function sleep(ms) {
|
|
25
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Repeatedly awaits `tick` until it returns `stop` (returns value), `throw` (propagates),
|
|
29
|
+
* or the deadline passes (throws {@link PollLoopTimeoutError}).
|
|
30
|
+
*/
|
|
31
|
+
function pollLoop(options) {
|
|
32
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
33
|
+
const { tick, intervalMs: baseIntervalMs, initialDelayMs = 0, backoff, timeoutMs, } = options;
|
|
34
|
+
const deadline = Date.now() + timeoutMs;
|
|
35
|
+
let interval = baseIntervalMs;
|
|
36
|
+
if (initialDelayMs > 0) {
|
|
37
|
+
yield sleep(initialDelayMs);
|
|
38
|
+
}
|
|
39
|
+
while (Date.now() < deadline) {
|
|
40
|
+
const result = yield tick();
|
|
41
|
+
// Check deadline again after tick completes (tick may have taken a long time)
|
|
42
|
+
if (Date.now() >= deadline && result.kind === 'continue') {
|
|
43
|
+
break;
|
|
44
|
+
}
|
|
45
|
+
if (result.kind === 'stop') {
|
|
46
|
+
return result.value;
|
|
47
|
+
}
|
|
48
|
+
if (result.kind === 'throw') {
|
|
49
|
+
throw result.error;
|
|
50
|
+
}
|
|
51
|
+
const remaining = deadline - Date.now();
|
|
52
|
+
if (remaining <= 0) {
|
|
53
|
+
break;
|
|
54
|
+
}
|
|
55
|
+
const sleepMs = Math.min(interval, Math.max(0, remaining));
|
|
56
|
+
yield sleep(sleepMs);
|
|
57
|
+
if (backoff) {
|
|
58
|
+
interval = Math.min(interval * backoff.factor, backoff.maxIntervalMs);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
throw new PollLoopTimeoutError(`pollLoop timed out after ${timeoutMs}ms`);
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
exports.pollLoop = pollLoop;
|