@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
|
@@ -8,49 +8,152 @@ 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
|
+
const waitForEvmTxConfirmation_1 = require("../../../internal/waitForEvmTxConfirmation");
|
|
24
|
+
const lifi_1 = require("../lifi");
|
|
25
|
+
const LOG_PREFIX = '[ZeroX]';
|
|
26
|
+
function mergeZeroXOptions(instance, perCall) {
|
|
27
|
+
return Object.assign(Object.assign({}, instance), perCall);
|
|
28
|
+
}
|
|
12
29
|
class ZeroX {
|
|
13
|
-
constructor(
|
|
30
|
+
constructor(_a) {
|
|
31
|
+
var { mpc } = _a, defaults = __rest(_a, ["mpc"]);
|
|
14
32
|
this.mpc = mpc;
|
|
33
|
+
this.defaults = defaults;
|
|
15
34
|
}
|
|
16
|
-
/**
|
|
17
|
-
* Get a quote from the Swaps API.
|
|
18
|
-
*
|
|
19
|
-
* @param apiKey - The API key for the Swaps API.
|
|
20
|
-
* @param args - The arguments for the quote.
|
|
21
|
-
* @param chainId - The chain ID for the quote.
|
|
22
|
-
* @returns The quote response.
|
|
23
|
-
*/
|
|
24
35
|
getQuote(args, options) {
|
|
25
36
|
var _a;
|
|
26
37
|
return __awaiter(this, void 0, void 0, function* () {
|
|
27
|
-
|
|
38
|
+
const merged = Object.assign(Object.assign({}, this.defaults), options);
|
|
39
|
+
const key = merged.zeroXApiKey;
|
|
40
|
+
return (_a = this.mpc) === null || _a === void 0 ? void 0 : _a.getSwapsQuoteV2(args, key != null && key !== '' ? { zeroXApiKey: key } : undefined);
|
|
28
41
|
});
|
|
29
42
|
}
|
|
30
|
-
/**
|
|
31
|
-
* Get the valid, swappable token sources that can be used with your Portal MPC Wallet.
|
|
32
|
-
*
|
|
33
|
-
* @param apiKey - The API key for the Swaps API.
|
|
34
|
-
* @param chainId - The chain ID for the sources.
|
|
35
|
-
* @returns The sources response.
|
|
36
|
-
*/
|
|
37
43
|
getSources(chainId, options) {
|
|
38
44
|
var _a;
|
|
39
45
|
return __awaiter(this, void 0, void 0, function* () {
|
|
40
|
-
|
|
46
|
+
const merged = Object.assign(Object.assign({}, this.defaults), options);
|
|
47
|
+
const key = merged.zeroXApiKey;
|
|
48
|
+
return (_a = this.mpc) === null || _a === void 0 ? void 0 : _a.getSwapsSourcesV2({ chainId }, key != null && key !== '' ? { zeroXApiKey: key } : undefined);
|
|
41
49
|
});
|
|
42
50
|
}
|
|
43
|
-
/**
|
|
44
|
-
* Get the price of a token from the Swaps API.
|
|
45
|
-
*
|
|
46
|
-
* @param args - The arguments for the price.
|
|
47
|
-
* @param options - The options for the price.
|
|
48
|
-
* @returns The price response.
|
|
49
|
-
*/
|
|
50
51
|
getPrice(args, options) {
|
|
51
52
|
var _a;
|
|
52
53
|
return __awaiter(this, void 0, void 0, function* () {
|
|
53
|
-
|
|
54
|
+
const merged = Object.assign(Object.assign({}, this.defaults), options);
|
|
55
|
+
const key = merged.zeroXApiKey;
|
|
56
|
+
return (_a = this.mpc) === null || _a === void 0 ? void 0 : _a.getSwapsPrice(args, key != null && key !== '' ? { zeroXApiKey: key } : undefined);
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
tradeAsset(params, options) {
|
|
60
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w;
|
|
61
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
62
|
+
const o = mergeZeroXOptions(this.defaults, options);
|
|
63
|
+
const signAndSend = o.signAndSendTransaction;
|
|
64
|
+
if (!signAndSend) {
|
|
65
|
+
throw new Error(`${LOG_PREFIX} tradeAsset requires signAndSendTransaction`);
|
|
66
|
+
}
|
|
67
|
+
if (!o.waitForConfirmation && !o.evmRequestFn) {
|
|
68
|
+
throw new Error(`${LOG_PREFIX} tradeAsset requires waitForConfirmation (instance default or per-call option), or evmRequestFn fallback.`);
|
|
69
|
+
}
|
|
70
|
+
const apiOpts = { zeroXApiKey: (_a = o.zeroXApiKey) !== null && _a !== void 0 ? _a : params.zeroXApiKey };
|
|
71
|
+
(_b = params.onProgress) === null || _b === void 0 ? void 0 : _b.call(params, 'fetching_quote');
|
|
72
|
+
const quoteReq = {
|
|
73
|
+
chainId: params.chainId,
|
|
74
|
+
buyToken: params.buyToken,
|
|
75
|
+
sellToken: params.sellToken,
|
|
76
|
+
sellAmount: params.sellAmount,
|
|
77
|
+
txOrigin: params.fromAddress,
|
|
78
|
+
swapFeeRecipient: params.swapFeeRecipient,
|
|
79
|
+
swapFeeBps: params.swapFeeBps,
|
|
80
|
+
swapFeeToken: params.swapFeeToken,
|
|
81
|
+
tradeSurplusRecipient: params.tradeSurplusRecipient,
|
|
82
|
+
gasPrice: params.gasPrice,
|
|
83
|
+
slippageBps: params.slippageBps,
|
|
84
|
+
excludedSources: params.excludedSources,
|
|
85
|
+
sellEntireBalance: params.sellEntireBalance,
|
|
86
|
+
};
|
|
87
|
+
const quote = yield this.mpc.getSwapsQuoteV2(quoteReq, apiOpts);
|
|
88
|
+
const err = (_c = quote.error) === null || _c === void 0 ? void 0 : _c.trim();
|
|
89
|
+
if (err) {
|
|
90
|
+
throw new Error(`${LOG_PREFIX} Quote error: ${err}`);
|
|
91
|
+
}
|
|
92
|
+
const raw = (_d = quote.data) === null || _d === void 0 ? void 0 : _d.rawResponse;
|
|
93
|
+
if (!raw) {
|
|
94
|
+
const msg = 'Quote response missing data.rawResponse';
|
|
95
|
+
(_e = params.onProgress) === null || _e === void 0 ? void 0 : _e.call(params, 'failed', { errorMessage: msg });
|
|
96
|
+
throw new Error(`${LOG_PREFIX} ${msg}`);
|
|
97
|
+
}
|
|
98
|
+
const transaction = raw.transaction;
|
|
99
|
+
const to = transaction !== null &&
|
|
100
|
+
transaction !== undefined &&
|
|
101
|
+
typeof transaction === 'object' &&
|
|
102
|
+
'to' in transaction
|
|
103
|
+
? transaction.to
|
|
104
|
+
: undefined;
|
|
105
|
+
if (typeof to !== 'string' ||
|
|
106
|
+
to.trim() === '' ||
|
|
107
|
+
transaction === null ||
|
|
108
|
+
transaction === undefined ||
|
|
109
|
+
typeof transaction !== 'object') {
|
|
110
|
+
const msg = 'Quote response missing valid transaction (expected object with non-empty string "to")';
|
|
111
|
+
(_f = params.onProgress) === null || _f === void 0 ? void 0 : _f.call(params, 'failed', { errorMessage: msg });
|
|
112
|
+
throw new Error(`${LOG_PREFIX} ${msg}`);
|
|
113
|
+
}
|
|
114
|
+
const tx = transaction;
|
|
115
|
+
const network = (0, lifi_1.normalizeChainToNetwork)(params.chainId);
|
|
116
|
+
(_g = params.onProgress) === null || _g === void 0 ? void 0 : _g.call(params, 'signing', {
|
|
117
|
+
buyAmount: (_j = (_h = quote.data) === null || _h === void 0 ? void 0 : _h.rawResponse) === null || _j === void 0 ? void 0 : _j.buyAmount,
|
|
118
|
+
sellAmount: (_l = (_k = quote.data) === null || _k === void 0 ? void 0 : _k.rawResponse) === null || _l === void 0 ? void 0 : _l.sellAmount,
|
|
119
|
+
transaction: tx,
|
|
120
|
+
});
|
|
121
|
+
let txHash;
|
|
122
|
+
try {
|
|
123
|
+
txHash = yield signAndSend(tx, network);
|
|
124
|
+
}
|
|
125
|
+
catch (e) {
|
|
126
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
127
|
+
(_m = params.onProgress) === null || _m === void 0 ? void 0 : _m.call(params, 'failed', { errorMessage: msg });
|
|
128
|
+
throw e;
|
|
129
|
+
}
|
|
130
|
+
if (typeof txHash !== 'string' || txHash.trim() === '') {
|
|
131
|
+
const msg = 'signAndSendTransaction returned empty or invalid transaction hash';
|
|
132
|
+
(_o = params.onProgress) === null || _o === void 0 ? void 0 : _o.call(params, 'failed', { errorMessage: msg });
|
|
133
|
+
throw new Error(`${LOG_PREFIX} ${msg}`);
|
|
134
|
+
}
|
|
135
|
+
(_p = params.onProgress) === null || _p === void 0 ? void 0 : _p.call(params, 'submitted', { txHash });
|
|
136
|
+
if (o.waitForConfirmation) {
|
|
137
|
+
(_q = params.onProgress) === null || _q === void 0 ? void 0 : _q.call(params, 'confirming', { txHash });
|
|
138
|
+
const waiterResult = yield o.waitForConfirmation(txHash, network);
|
|
139
|
+
const ok = waiterResult === true;
|
|
140
|
+
if (!ok) {
|
|
141
|
+
const msg = `${LOG_PREFIX} on-chain confirmation did not complete (waitForConfirmation did not return true) for ${txHash} on ${network}`;
|
|
142
|
+
(_r = params.onProgress) === null || _r === void 0 ? void 0 : _r.call(params, 'failed', { errorMessage: msg, txHash });
|
|
143
|
+
throw new Error(msg);
|
|
144
|
+
}
|
|
145
|
+
(_s = params.onProgress) === null || _s === void 0 ? void 0 : _s.call(params, 'confirmed', { txHash });
|
|
146
|
+
}
|
|
147
|
+
else if (o.evmRequestFn) {
|
|
148
|
+
(_t = params.onProgress) === null || _t === void 0 ? void 0 : _t.call(params, 'confirming', { txHash });
|
|
149
|
+
yield (0, waitForEvmTxConfirmation_1.waitForEvmTxConfirmation)(txHash, network, o.evmRequestFn, {
|
|
150
|
+
pollIntervalMs: (_u = o.evmPollerOptions) === null || _u === void 0 ? void 0 : _u.pollIntervalMs,
|
|
151
|
+
timeoutMs: (_v = o.evmPollerOptions) === null || _v === void 0 ? void 0 : _v.timeoutMs,
|
|
152
|
+
onTimeout: 'throw',
|
|
153
|
+
});
|
|
154
|
+
(_w = params.onProgress) === null || _w === void 0 ? void 0 : _w.call(params, 'confirmed', { txHash });
|
|
155
|
+
}
|
|
156
|
+
return { hashes: [txHash] };
|
|
54
157
|
});
|
|
55
158
|
}
|
|
56
159
|
}
|
|
@@ -2,6 +2,29 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* @jest-environment jsdom
|
|
4
4
|
*/
|
|
5
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
6
|
+
if (k2 === undefined) k2 = k;
|
|
7
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
8
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
9
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
10
|
+
}
|
|
11
|
+
Object.defineProperty(o, k2, desc);
|
|
12
|
+
}) : (function(o, m, k, k2) {
|
|
13
|
+
if (k2 === undefined) k2 = k;
|
|
14
|
+
o[k2] = m[k];
|
|
15
|
+
}));
|
|
16
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
17
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
18
|
+
}) : function(o, v) {
|
|
19
|
+
o["default"] = v;
|
|
20
|
+
});
|
|
21
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
22
|
+
if (mod && mod.__esModule) return mod;
|
|
23
|
+
var result = {};
|
|
24
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
25
|
+
__setModuleDefault(result, mod);
|
|
26
|
+
return result;
|
|
27
|
+
};
|
|
5
28
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
6
29
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
7
30
|
return new (P || (P = Promise))(function (resolve, reject) {
|
|
@@ -18,6 +41,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
18
41
|
const _1 = __importDefault(require("."));
|
|
19
42
|
const mpc_1 = __importDefault(require("../../../mpc"));
|
|
20
43
|
const portal_1 = __importDefault(require("../../../__mocks/portal/portal"));
|
|
44
|
+
const waitEvm = __importStar(require("../../../internal/waitForEvmTxConfirmation"));
|
|
21
45
|
const constants_1 = require("../../../__mocks/constants");
|
|
22
46
|
describe('ZeroX', () => {
|
|
23
47
|
let zeroX;
|
|
@@ -63,7 +87,6 @@ describe('ZeroX', () => {
|
|
|
63
87
|
const result = yield zeroX.getSources('eip155:1', {
|
|
64
88
|
zeroXApiKey: 'test-api-key',
|
|
65
89
|
});
|
|
66
|
-
console.log(`Result:`, result);
|
|
67
90
|
expect(spy).toHaveBeenCalledTimes(1);
|
|
68
91
|
expect(spy).toHaveBeenCalledWith({ chainId: 'eip155:1' }, { zeroXApiKey: 'test-api-key' });
|
|
69
92
|
expect(result).toEqual(constants_1.mockSourcesRes);
|
|
@@ -108,4 +131,143 @@ describe('ZeroX', () => {
|
|
|
108
131
|
yield expect(zeroX.getPrice(constants_1.mockZeroExPriceRequest)).rejects.toThrow('Test error');
|
|
109
132
|
}));
|
|
110
133
|
});
|
|
134
|
+
describe('tradeAsset', () => {
|
|
135
|
+
it('throws when waitForConfirmation returns false and emits failed, not confirmed', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
136
|
+
const onProgress = jest.fn();
|
|
137
|
+
jest
|
|
138
|
+
.spyOn(mpc, 'getSwapsQuoteV2')
|
|
139
|
+
.mockResolvedValue(constants_1.mockZeroExQuoteV2Response);
|
|
140
|
+
yield expect(zeroX.tradeAsset(Object.assign(Object.assign({}, constants_1.mockZeroExQuoteV2Request), { fromAddress: constants_1.mockEip155Address, onProgress }), {
|
|
141
|
+
signAndSendTransaction: () => __awaiter(void 0, void 0, void 0, function* () { return '0xabc'; }),
|
|
142
|
+
waitForConfirmation: () => __awaiter(void 0, void 0, void 0, function* () { return false; }),
|
|
143
|
+
})).rejects.toThrow(/on-chain confirmation/);
|
|
144
|
+
const statuses = onProgress.mock.calls.map((c) => c[0]);
|
|
145
|
+
expect(statuses).toContain('failed');
|
|
146
|
+
expect(statuses).not.toContain('confirmed');
|
|
147
|
+
}));
|
|
148
|
+
it('emits confirmed after waitForConfirmation succeeds', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
149
|
+
const onProgress = jest.fn();
|
|
150
|
+
jest
|
|
151
|
+
.spyOn(mpc, 'getSwapsQuoteV2')
|
|
152
|
+
.mockResolvedValue(constants_1.mockZeroExQuoteV2Response);
|
|
153
|
+
yield zeroX.tradeAsset(Object.assign(Object.assign({}, constants_1.mockZeroExQuoteV2Request), { fromAddress: constants_1.mockEip155Address, onProgress }), {
|
|
154
|
+
signAndSendTransaction: () => __awaiter(void 0, void 0, void 0, function* () { return '0xabc'; }),
|
|
155
|
+
waitForConfirmation: () => __awaiter(void 0, void 0, void 0, function* () { return true; }),
|
|
156
|
+
});
|
|
157
|
+
expect(onProgress).toHaveBeenCalledWith('confirmed', { txHash: '0xabc' });
|
|
158
|
+
}));
|
|
159
|
+
it('throws before signing when quote has error string', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
160
|
+
jest.spyOn(mpc, 'getSwapsQuoteV2').mockResolvedValue({
|
|
161
|
+
error: 'insufficient liquidity',
|
|
162
|
+
});
|
|
163
|
+
yield expect(zeroX.tradeAsset(Object.assign(Object.assign({}, constants_1.mockZeroExQuoteV2Request), { fromAddress: constants_1.mockEip155Address }), {
|
|
164
|
+
signAndSendTransaction: () => __awaiter(void 0, void 0, void 0, function* () { return '0x'; }),
|
|
165
|
+
waitForConfirmation: () => __awaiter(void 0, void 0, void 0, function* () { return true; }),
|
|
166
|
+
})).rejects.toThrow(/Quote error: insufficient liquidity/);
|
|
167
|
+
}));
|
|
168
|
+
it('throws before signing when neither waitForConfirmation nor evmRequestFn', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
169
|
+
const quoteSpy = jest
|
|
170
|
+
.spyOn(mpc, 'getSwapsQuoteV2')
|
|
171
|
+
.mockResolvedValue(constants_1.mockZeroExQuoteV2Response);
|
|
172
|
+
yield expect(zeroX.tradeAsset(Object.assign(Object.assign({}, constants_1.mockZeroExQuoteV2Request), { fromAddress: constants_1.mockEip155Address }), {
|
|
173
|
+
signAndSendTransaction: () => __awaiter(void 0, void 0, void 0, function* () { return '0xshouldnotrun'; }),
|
|
174
|
+
})).rejects.toThrow(/requires waitForConfirmation.*or evmRequestFn/);
|
|
175
|
+
expect(quoteSpy).not.toHaveBeenCalled();
|
|
176
|
+
}));
|
|
177
|
+
it('throws before signing when rawResponse is missing', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
178
|
+
jest.spyOn(mpc, 'getSwapsQuoteV2').mockResolvedValue({
|
|
179
|
+
data: {},
|
|
180
|
+
});
|
|
181
|
+
yield expect(zeroX.tradeAsset(Object.assign(Object.assign({}, constants_1.mockZeroExQuoteV2Request), { fromAddress: constants_1.mockEip155Address }), {
|
|
182
|
+
signAndSendTransaction: () => __awaiter(void 0, void 0, void 0, function* () { return '0x'; }),
|
|
183
|
+
waitForConfirmation: () => __awaiter(void 0, void 0, void 0, function* () { return true; }),
|
|
184
|
+
})).rejects.toThrow(/missing data.rawResponse/);
|
|
185
|
+
}));
|
|
186
|
+
it('throws before signing when transaction.to is invalid', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
187
|
+
jest.spyOn(mpc, 'getSwapsQuoteV2').mockResolvedValue({
|
|
188
|
+
data: {
|
|
189
|
+
rawResponse: Object.assign(Object.assign({}, constants_1.mockZeroExQuoteV2Response.data.rawResponse), { transaction: { to: '' } }),
|
|
190
|
+
},
|
|
191
|
+
});
|
|
192
|
+
const onProgress = jest.fn();
|
|
193
|
+
yield expect(zeroX.tradeAsset(Object.assign(Object.assign({}, constants_1.mockZeroExQuoteV2Request), { fromAddress: constants_1.mockEip155Address, onProgress }), {
|
|
194
|
+
signAndSendTransaction: () => __awaiter(void 0, void 0, void 0, function* () { return '0x'; }),
|
|
195
|
+
waitForConfirmation: () => __awaiter(void 0, void 0, void 0, function* () { return true; }),
|
|
196
|
+
})).rejects.toThrow(/missing valid transaction/);
|
|
197
|
+
expect(onProgress).toHaveBeenCalledWith('failed', expect.objectContaining({
|
|
198
|
+
errorMessage: expect.stringContaining('valid transaction'),
|
|
199
|
+
}));
|
|
200
|
+
}));
|
|
201
|
+
it('signer throws: rethrows and emits failed', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
202
|
+
const onProgress = jest.fn();
|
|
203
|
+
jest
|
|
204
|
+
.spyOn(mpc, 'getSwapsQuoteV2')
|
|
205
|
+
.mockResolvedValue(constants_1.mockZeroExQuoteV2Response);
|
|
206
|
+
yield expect(zeroX.tradeAsset(Object.assign(Object.assign({}, constants_1.mockZeroExQuoteV2Request), { fromAddress: constants_1.mockEip155Address, onProgress }), {
|
|
207
|
+
signAndSendTransaction: () => __awaiter(void 0, void 0, void 0, function* () {
|
|
208
|
+
throw new Error('user rejected');
|
|
209
|
+
}),
|
|
210
|
+
waitForConfirmation: () => __awaiter(void 0, void 0, void 0, function* () { return true; }),
|
|
211
|
+
})).rejects.toThrow('user rejected');
|
|
212
|
+
expect(onProgress).toHaveBeenCalledWith('failed', expect.objectContaining({ errorMessage: 'user rejected' }));
|
|
213
|
+
}));
|
|
214
|
+
it('empty hash after sign: throws and emits failed', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
215
|
+
const onProgress = jest.fn();
|
|
216
|
+
jest
|
|
217
|
+
.spyOn(mpc, 'getSwapsQuoteV2')
|
|
218
|
+
.mockResolvedValue(constants_1.mockZeroExQuoteV2Response);
|
|
219
|
+
yield expect(zeroX.tradeAsset(Object.assign(Object.assign({}, constants_1.mockZeroExQuoteV2Request), { fromAddress: constants_1.mockEip155Address, onProgress }), {
|
|
220
|
+
signAndSendTransaction: () => __awaiter(void 0, void 0, void 0, function* () { return ' '; }),
|
|
221
|
+
waitForConfirmation: () => __awaiter(void 0, void 0, void 0, function* () { return true; }),
|
|
222
|
+
})).rejects.toThrow(/empty or invalid transaction hash/);
|
|
223
|
+
expect(onProgress).toHaveBeenCalledWith('failed', expect.objectContaining({ errorMessage: expect.any(String) }));
|
|
224
|
+
}));
|
|
225
|
+
it('evmRequestFn path: waits for receipt with onTimeout throw', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
226
|
+
const waitSpy = jest
|
|
227
|
+
.spyOn(waitEvm, 'waitForEvmTxConfirmation')
|
|
228
|
+
.mockResolvedValue(true);
|
|
229
|
+
jest
|
|
230
|
+
.spyOn(mpc, 'getSwapsQuoteV2')
|
|
231
|
+
.mockResolvedValue(constants_1.mockZeroExQuoteV2Response);
|
|
232
|
+
yield zeroX.tradeAsset(Object.assign(Object.assign({}, constants_1.mockZeroExQuoteV2Request), { fromAddress: constants_1.mockEip155Address }), {
|
|
233
|
+
signAndSendTransaction: () => __awaiter(void 0, void 0, void 0, function* () { return '0xhash'; }),
|
|
234
|
+
evmRequestFn: () => __awaiter(void 0, void 0, void 0, function* () { return ({}); }),
|
|
235
|
+
});
|
|
236
|
+
expect(waitSpy).toHaveBeenCalledWith('0xhash', 'eip155:1', expect.any(Function), expect.objectContaining({ onTimeout: 'throw' }));
|
|
237
|
+
waitSpy.mockRestore();
|
|
238
|
+
}));
|
|
239
|
+
it('instance zeroXApiKey wins over params.zeroXApiKey when both set', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
240
|
+
const spy = jest
|
|
241
|
+
.spyOn(mpc, 'getSwapsQuoteV2')
|
|
242
|
+
.mockResolvedValue(constants_1.mockZeroExQuoteV2Response);
|
|
243
|
+
const z = new _1.default({
|
|
244
|
+
mpc,
|
|
245
|
+
zeroXApiKey: 'from-instance',
|
|
246
|
+
});
|
|
247
|
+
yield z.tradeAsset(Object.assign(Object.assign({}, constants_1.mockZeroExQuoteV2Request), { fromAddress: constants_1.mockEip155Address, zeroXApiKey: 'from-params' }), {
|
|
248
|
+
signAndSendTransaction: () => __awaiter(void 0, void 0, void 0, function* () { return '0xh'; }),
|
|
249
|
+
waitForConfirmation: () => __awaiter(void 0, void 0, void 0, function* () { return true; }),
|
|
250
|
+
});
|
|
251
|
+
expect(spy).toHaveBeenCalledWith(expect.any(Object), expect.objectContaining({ zeroXApiKey: 'from-instance' }));
|
|
252
|
+
}));
|
|
253
|
+
it('uses params.zeroXApiKey when instance has no key', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
254
|
+
const spy = jest
|
|
255
|
+
.spyOn(mpc, 'getSwapsQuoteV2')
|
|
256
|
+
.mockResolvedValue(constants_1.mockZeroExQuoteV2Response);
|
|
257
|
+
yield zeroX.tradeAsset(Object.assign(Object.assign({}, constants_1.mockZeroExQuoteV2Request), { fromAddress: constants_1.mockEip155Address, zeroXApiKey: 'params-only' }), {
|
|
258
|
+
signAndSendTransaction: () => __awaiter(void 0, void 0, void 0, function* () { return '0xh'; }),
|
|
259
|
+
waitForConfirmation: () => __awaiter(void 0, void 0, void 0, function* () { return true; }),
|
|
260
|
+
});
|
|
261
|
+
expect(spy).toHaveBeenCalledWith(expect.any(Object), expect.objectContaining({ zeroXApiKey: 'params-only' }));
|
|
262
|
+
}));
|
|
263
|
+
it('normalizes numeric chainId to eip155 for signer', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
264
|
+
const sign = jest.fn().mockResolvedValue('0xh');
|
|
265
|
+
jest.spyOn(mpc, 'getSwapsQuoteV2').mockResolvedValue(Object.assign({}, constants_1.mockZeroExQuoteV2Response));
|
|
266
|
+
yield zeroX.tradeAsset(Object.assign(Object.assign({}, constants_1.mockZeroExQuoteV2Request), { chainId: '1', fromAddress: constants_1.mockEip155Address }), {
|
|
267
|
+
signAndSendTransaction: sign,
|
|
268
|
+
waitForConfirmation: () => __awaiter(void 0, void 0, void 0, function* () { return true; }),
|
|
269
|
+
});
|
|
270
|
+
expect(sign).toHaveBeenCalledWith(expect.anything(), 'eip155:1');
|
|
271
|
+
}));
|
|
272
|
+
});
|
|
111
273
|
});
|
|
@@ -1,16 +1,30 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
3
|
+
var t = {};
|
|
4
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
5
|
+
t[p] = s[p];
|
|
6
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
7
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
8
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
9
|
+
t[p[i]] = s[p[i]];
|
|
10
|
+
}
|
|
11
|
+
return t;
|
|
12
|
+
};
|
|
2
13
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
14
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
15
|
};
|
|
5
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
17
|
const yieldxyz_1 = __importDefault(require("./yieldxyz"));
|
|
7
18
|
/**
|
|
8
|
-
*
|
|
9
|
-
* In the future, Yield domain logic should be here.
|
|
19
|
+
* Yield integrations (Yield.xyz, etc.).
|
|
10
20
|
*/
|
|
11
21
|
class Yield {
|
|
12
|
-
constructor(
|
|
13
|
-
|
|
22
|
+
constructor(_a) {
|
|
23
|
+
var { mpc } = _a, rest = __rest(_a, ["mpc"]);
|
|
24
|
+
this.yieldXyz = new yieldxyz_1.default(Object.assign({ mpc }, rest));
|
|
25
|
+
}
|
|
26
|
+
getValidators(yieldId) {
|
|
27
|
+
return this.yieldXyz.getValidators(yieldId);
|
|
14
28
|
}
|
|
15
29
|
}
|
|
16
30
|
exports.default = Yield;
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @jest-environment jsdom
|
|
4
|
+
*/
|
|
5
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
6
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
7
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
8
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
9
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
10
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
11
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
12
|
+
});
|
|
13
|
+
};
|
|
14
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
15
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
16
|
+
};
|
|
17
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
+
const yieldxyz_1 = __importDefault(require("./yieldxyz"));
|
|
19
|
+
const mpc_1 = __importDefault(require("../../mpc"));
|
|
20
|
+
const portal_1 = __importDefault(require("../../__mocks/portal/portal"));
|
|
21
|
+
const constants_1 = require("../../__mocks/constants");
|
|
22
|
+
describe('YieldXyz getValidators', () => {
|
|
23
|
+
let mpc;
|
|
24
|
+
let yieldXyz;
|
|
25
|
+
beforeEach(() => {
|
|
26
|
+
jest.clearAllMocks();
|
|
27
|
+
portal_1.default.host = constants_1.mockHost;
|
|
28
|
+
mpc = new mpc_1.default({ portal: portal_1.default });
|
|
29
|
+
yieldXyz = new yieldxyz_1.default({ mpc });
|
|
30
|
+
});
|
|
31
|
+
it('returns validators from data.validators', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
32
|
+
const v = [{ address: '0x1', name: 'v1' }];
|
|
33
|
+
jest.spyOn(mpc, 'getYieldXyzValidators').mockResolvedValue({
|
|
34
|
+
data: { validators: v },
|
|
35
|
+
});
|
|
36
|
+
yield expect(yieldXyz.getValidators('y1')).resolves.toEqual(v);
|
|
37
|
+
}));
|
|
38
|
+
it('falls back to data.rawResponse.validators', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
39
|
+
const v = [{ address: '0x2' }];
|
|
40
|
+
jest.spyOn(mpc, 'getYieldXyzValidators').mockResolvedValue({
|
|
41
|
+
data: { rawResponse: { validators: v } },
|
|
42
|
+
});
|
|
43
|
+
yield expect(yieldXyz.getValidators('y1')).resolves.toEqual(v);
|
|
44
|
+
}));
|
|
45
|
+
it('falls back to data.rawResponse.items', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
46
|
+
const v = [{ address: '0x3' }];
|
|
47
|
+
jest.spyOn(mpc, 'getYieldXyzValidators').mockResolvedValue({
|
|
48
|
+
data: { rawResponse: { items: v, total: 1 } },
|
|
49
|
+
});
|
|
50
|
+
yield expect(yieldXyz.getValidators('y1')).resolves.toEqual(v);
|
|
51
|
+
}));
|
|
52
|
+
it('returns empty array when validators is empty (valid)', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
53
|
+
jest.spyOn(mpc, 'getYieldXyzValidators').mockResolvedValue({
|
|
54
|
+
data: { validators: [] },
|
|
55
|
+
});
|
|
56
|
+
yield expect(yieldXyz.getValidators('y1')).resolves.toEqual([]);
|
|
57
|
+
}));
|
|
58
|
+
it('throws on res.error', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
59
|
+
jest.spyOn(mpc, 'getYieldXyzValidators').mockResolvedValue({
|
|
60
|
+
error: 'not found',
|
|
61
|
+
data: { validators: [{ address: 'x' }] },
|
|
62
|
+
});
|
|
63
|
+
yield expect(yieldXyz.getValidators('y1')).rejects.toThrow('[YieldXyz] getValidators failed: not found');
|
|
64
|
+
}));
|
|
65
|
+
it('throws when no validators array in response', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
66
|
+
jest.spyOn(mpc, 'getYieldXyzValidators').mockResolvedValue({
|
|
67
|
+
data: { rawResponse: {} },
|
|
68
|
+
});
|
|
69
|
+
yield expect(yieldXyz.getValidators('y1')).rejects.toThrow('No validators in response');
|
|
70
|
+
}));
|
|
71
|
+
});
|