@subwallet/extension-base 1.3.26-0 → 1.3.27-1
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/background/KoniTypes.d.ts +4 -3
- package/background/warnings/TransactionWarning.d.ts +2 -0
- package/background/warnings/TransactionWarning.js +16 -1
- package/cjs/background/warnings/TransactionWarning.js +15 -0
- package/cjs/core/logic-validation/index.js +32 -1
- package/cjs/core/utils.js +25 -3
- package/cjs/koni/background/handlers/Extension.js +86 -94
- package/cjs/packageInfo.js +1 -1
- package/cjs/services/chain-service/utils/patch.js +1 -1
- package/cjs/services/swap-service/handler/asset-hub/handler.js +182 -40
- package/cjs/services/swap-service/handler/asset-hub/utils.js +3 -0
- package/cjs/services/swap-service/handler/base-handler.js +326 -12
- package/cjs/services/swap-service/handler/chainflip-handler.js +80 -16
- package/cjs/services/swap-service/handler/hydradx-handler.js +174 -30
- package/cjs/services/swap-service/handler/simpleswap-handler.js +50 -1
- package/cjs/services/swap-service/handler/uniswap-handler.js +47 -1
- package/cjs/services/swap-service/index.js +191 -27
- package/cjs/services/swap-service/interface.js +14 -0
- package/cjs/services/swap-service/utils.js +81 -5
- package/cjs/services/transaction-service/utils.js +4 -1
- package/core/logic-validation/index.d.ts +4 -0
- package/core/logic-validation/index.js +22 -1
- package/core/utils.d.ts +3 -0
- package/core/utils.js +22 -2
- package/koni/background/handlers/Extension.d.ts +2 -2
- package/koni/background/handlers/Extension.js +20 -28
- package/package.json +12 -7
- package/packageInfo.js +1 -1
- package/services/balance-service/helpers/process.d.ts +3 -3
- package/services/balance-service/index.d.ts +2 -3
- package/services/chain-service/utils/patch.js +1 -1
- package/services/swap-service/handler/asset-hub/handler.d.ts +6 -3
- package/services/swap-service/handler/asset-hub/handler.js +170 -28
- package/services/swap-service/handler/asset-hub/utils.js +3 -0
- package/services/swap-service/handler/base-handler.d.ts +12 -3
- package/services/swap-service/handler/base-handler.js +329 -15
- package/services/swap-service/handler/chainflip-handler.d.ts +4 -3
- package/services/swap-service/handler/chainflip-handler.js +74 -10
- package/services/swap-service/handler/hydradx-handler.d.ts +8 -3
- package/services/swap-service/handler/hydradx-handler.js +176 -32
- package/services/swap-service/handler/simpleswap-handler.d.ts +4 -2
- package/services/swap-service/handler/simpleswap-handler.js +50 -1
- package/services/swap-service/handler/uniswap-handler.d.ts +4 -2
- package/services/swap-service/handler/uniswap-handler.js +47 -1
- package/services/swap-service/index.d.ts +15 -5
- package/services/swap-service/index.js +182 -18
- package/services/swap-service/interface.d.ts +9 -0
- package/services/swap-service/interface.js +8 -0
- package/services/swap-service/utils.d.ts +9 -1
- package/services/swap-service/utils.js +74 -4
- package/services/transaction-service/utils.js +4 -1
- package/types/service-base.d.ts +6 -2
- package/types/swap/index.d.ts +34 -6
- package/types/transaction/process.d.ts +0 -6
|
@@ -8,14 +8,15 @@ exports._isChainSupportedByProvider = exports.SwapService = void 0;
|
|
|
8
8
|
var _SwapError = require("@subwallet/extension-base/background/errors/SwapError");
|
|
9
9
|
var _TransactionError = require("@subwallet/extension-base/background/errors/TransactionError");
|
|
10
10
|
var _types = require("@subwallet/extension-base/services/base/types");
|
|
11
|
+
var _utils = require("@subwallet/extension-base/services/chain-service/utils");
|
|
11
12
|
var _assetHub = require("@subwallet/extension-base/services/swap-service/handler/asset-hub");
|
|
12
13
|
var _chainflipHandler = require("@subwallet/extension-base/services/swap-service/handler/chainflip-handler");
|
|
13
14
|
var _hydradxHandler = require("@subwallet/extension-base/services/swap-service/handler/hydradx-handler");
|
|
14
|
-
var
|
|
15
|
+
var _utils2 = require("@subwallet/extension-base/services/swap-service/utils");
|
|
15
16
|
var _types2 = require("@subwallet/extension-base/types");
|
|
16
17
|
var _serviceBase = require("@subwallet/extension-base/types/service-base");
|
|
17
18
|
var _swap = require("@subwallet/extension-base/types/swap");
|
|
18
|
-
var
|
|
19
|
+
var _utils3 = require("@subwallet/extension-base/utils");
|
|
19
20
|
var _subwalletApiSdk = _interopRequireDefault(require("@subwallet/subwallet-api-sdk"));
|
|
20
21
|
var _rxjs = require("rxjs");
|
|
21
22
|
var _simpleswapHandler = require("./handler/simpleswap-handler");
|
|
@@ -24,15 +25,15 @@ var _uniswapHandler = require("./handler/uniswap-handler");
|
|
|
24
25
|
// SPDX-License-Identifier: Apache-2.0
|
|
25
26
|
|
|
26
27
|
const _isChainSupportedByProvider = (providerSlug, chain) => {
|
|
27
|
-
const supportedChains =
|
|
28
|
+
const supportedChains = _utils2._PROVIDER_TO_SUPPORTED_PAIR_MAP[providerSlug];
|
|
28
29
|
return supportedChains ? supportedChains.includes(chain) : false;
|
|
29
30
|
};
|
|
30
31
|
exports._isChainSupportedByProvider = _isChainSupportedByProvider;
|
|
31
32
|
class SwapService {
|
|
32
33
|
swapPairSubject = new _rxjs.BehaviorSubject([]);
|
|
33
34
|
handlers = {};
|
|
34
|
-
startPromiseHandler = (0,
|
|
35
|
-
stopPromiseHandler = (0,
|
|
35
|
+
startPromiseHandler = (0, _utils3.createPromiseHandler)();
|
|
36
|
+
stopPromiseHandler = (0, _utils3.createPromiseHandler)();
|
|
36
37
|
status = _types.ServiceStatus.NOT_INITIALIZED;
|
|
37
38
|
constructor(state) {
|
|
38
39
|
this.state = state;
|
|
@@ -71,7 +72,8 @@ class SwapService {
|
|
|
71
72
|
getDefaultProcess(params) {
|
|
72
73
|
const result = {
|
|
73
74
|
totalFee: [_serviceBase.MOCK_STEP_FEE],
|
|
74
|
-
steps: [_serviceBase.DEFAULT_FIRST_STEP]
|
|
75
|
+
steps: [_serviceBase.DEFAULT_FIRST_STEP],
|
|
76
|
+
path: []
|
|
75
77
|
};
|
|
76
78
|
result.totalFee.push({
|
|
77
79
|
feeComponent: [],
|
|
@@ -85,6 +87,33 @@ class SwapService {
|
|
|
85
87
|
});
|
|
86
88
|
return result;
|
|
87
89
|
}
|
|
90
|
+
getDefaultProcessV2(params) {
|
|
91
|
+
const result = {
|
|
92
|
+
totalFee: [_serviceBase.MOCK_STEP_FEE],
|
|
93
|
+
steps: [_serviceBase.DEFAULT_FIRST_STEP],
|
|
94
|
+
path: []
|
|
95
|
+
};
|
|
96
|
+
const swapPairInfo = params.path[0].pair; // todo: improve for Round 2
|
|
97
|
+
|
|
98
|
+
result.totalFee.push({
|
|
99
|
+
feeComponent: [],
|
|
100
|
+
feeOptions: [params.request.pair.from],
|
|
101
|
+
defaultFeeToken: params.request.pair.from
|
|
102
|
+
});
|
|
103
|
+
result.steps.push({
|
|
104
|
+
id: result.steps.length,
|
|
105
|
+
name: 'Swap',
|
|
106
|
+
type: _swap.SwapStepType.SWAP,
|
|
107
|
+
metadata: {
|
|
108
|
+
sendingValue: params.request.fromAmount.toString(),
|
|
109
|
+
originTokenInfo: this.chainService.getAssetBySlug(swapPairInfo.from),
|
|
110
|
+
destinationTokenInfo: this.chainService.getAssetBySlug(swapPairInfo.to)
|
|
111
|
+
}
|
|
112
|
+
});
|
|
113
|
+
return result;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// deprecated
|
|
88
117
|
async generateOptimalProcess(params) {
|
|
89
118
|
if (!params.selectedQuote) {
|
|
90
119
|
return this.getDefaultProcess(params);
|
|
@@ -99,24 +128,153 @@ class SwapService {
|
|
|
99
128
|
}
|
|
100
129
|
}
|
|
101
130
|
}
|
|
131
|
+
async generateOptimalProcessV2(params) {
|
|
132
|
+
if (!params.selectedQuote) {
|
|
133
|
+
return this.getDefaultProcessV2(params);
|
|
134
|
+
} else {
|
|
135
|
+
var _params$request$curre2;
|
|
136
|
+
const providerId = ((_params$request$curre2 = params.request.currentQuote) === null || _params$request$curre2 === void 0 ? void 0 : _params$request$curre2.id) || params.selectedQuote.provider.id;
|
|
137
|
+
const handler = this.handlers[providerId];
|
|
138
|
+
if (handler) {
|
|
139
|
+
return handler.generateOptimalProcessV2(params);
|
|
140
|
+
} else {
|
|
141
|
+
return this.getDefaultProcessV2(params);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
async generateOptimalProcessWithoutPath(params) {
|
|
146
|
+
var _params$request$curre3;
|
|
147
|
+
if (!params.selectedQuote || params.path.length > 0) {
|
|
148
|
+
return this.getDefaultProcessV2(params);
|
|
149
|
+
}
|
|
150
|
+
const [path, directSwapRequest] = this.getAvailablePath(params.request);
|
|
151
|
+
if (!directSwapRequest) {
|
|
152
|
+
return this.getDefaultProcessV2(params);
|
|
153
|
+
}
|
|
154
|
+
params.path = path;
|
|
155
|
+
const providerId = ((_params$request$curre3 = params.request.currentQuote) === null || _params$request$curre3 === void 0 ? void 0 : _params$request$curre3.id) || params.selectedQuote.provider.id;
|
|
156
|
+
const handler = this.handlers[providerId];
|
|
157
|
+
if (handler) {
|
|
158
|
+
return handler.generateOptimalProcessV2(params);
|
|
159
|
+
} else {
|
|
160
|
+
return this.getDefaultProcessV2(params);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// deprecated
|
|
165
|
+
// eslint-disable-next-line @typescript-eslint/require-await
|
|
102
166
|
async handleSwapRequest(request) {
|
|
103
|
-
/*
|
|
104
|
-
* 1. Ask swap quotes from providers
|
|
105
|
-
* 2. Select the best quote
|
|
106
|
-
* 3. Generate optimal process for that quote
|
|
167
|
+
/*
|
|
168
|
+
* 1. Ask swap quotes from providers
|
|
169
|
+
* 2. Select the best quote
|
|
170
|
+
* 3. Generate optimal process for that quote
|
|
107
171
|
* */
|
|
108
|
-
|
|
109
|
-
const
|
|
172
|
+
|
|
173
|
+
// const swapQuoteResponse = await this.getLatestDirectQuotes(request);
|
|
174
|
+
|
|
175
|
+
// const optimalProcess = await this.generateOptimalProcess({
|
|
176
|
+
// request,
|
|
177
|
+
// selectedQuote: swapQuoteResponse.optimalQuote
|
|
178
|
+
// });
|
|
179
|
+
|
|
180
|
+
return {
|
|
181
|
+
// @ts-ignore
|
|
182
|
+
process: null,
|
|
183
|
+
// @ts-ignore
|
|
184
|
+
quote: null
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
async handleSwapRequestV2(request) {
|
|
188
|
+
/*
|
|
189
|
+
* 1. Find available path
|
|
190
|
+
* 2. Ask swap quotes from providers
|
|
191
|
+
* 3. Select the best quote
|
|
192
|
+
* 4. Generate optimal process for that quote
|
|
193
|
+
* */
|
|
194
|
+
|
|
195
|
+
// todo: path will become a list of path in Round 2
|
|
196
|
+
// const [path, directSwapRequest] = this.getAvailablePath(request);
|
|
197
|
+
//
|
|
198
|
+
// if (!directSwapRequest) {
|
|
199
|
+
// throw Error('Swap pair not found');
|
|
200
|
+
// }
|
|
201
|
+
|
|
202
|
+
// const swapQuoteResponse = await this.getLatestDirectQuotes(directSwapRequest);
|
|
203
|
+
const {
|
|
204
|
+
path,
|
|
205
|
+
swapQuoteResponse
|
|
206
|
+
} = await this.getLatestQuoteFromSwapRequest(request);
|
|
207
|
+
const optimalProcess = await this.generateOptimalProcessV2({
|
|
110
208
|
request,
|
|
111
|
-
selectedQuote: swapQuoteResponse.optimalQuote
|
|
209
|
+
selectedQuote: swapQuoteResponse.optimalQuote,
|
|
210
|
+
path
|
|
112
211
|
});
|
|
113
212
|
return {
|
|
114
213
|
process: optimalProcess,
|
|
115
214
|
quote: swapQuoteResponse
|
|
116
215
|
};
|
|
117
216
|
}
|
|
118
|
-
|
|
119
|
-
|
|
217
|
+
getAvailablePath(request) {
|
|
218
|
+
const {
|
|
219
|
+
pair
|
|
220
|
+
} = request;
|
|
221
|
+
// todo: control provider tighter
|
|
222
|
+
const allSupportedChainsBySwapProvider = [...new Set(Object.values(_utils2._PROVIDER_TO_SUPPORTED_PAIR_MAP).flat())];
|
|
223
|
+
const fromToken = this.chainService.getAssetBySlug(pair.from);
|
|
224
|
+
const toToken = this.chainService.getAssetBySlug(pair.to);
|
|
225
|
+
const fromChain = (0, _utils._getAssetOriginChain)(fromToken);
|
|
226
|
+
const toChain = (0, _utils._getAssetOriginChain)(toToken);
|
|
227
|
+
const toChainInfo = this.chainService.getChainInfoByKey(toChain);
|
|
228
|
+
const process = [];
|
|
229
|
+
if (!fromToken || !toToken) {
|
|
230
|
+
throw Error('Token not found');
|
|
231
|
+
}
|
|
232
|
+
if (!fromChain || !toChain) {
|
|
233
|
+
throw Error('Token metadata error');
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// SWAP: 2 tokens in the same chain and chain has dex
|
|
237
|
+
if ((0, _utils2.isChainsHasSameProvider)(fromChain, toChain)) {
|
|
238
|
+
// there's a dex that can support direct swapping
|
|
239
|
+
const swapStep = (0, _utils2.getSwapStep)(fromToken.slug, toToken.slug);
|
|
240
|
+
process.push(swapStep);
|
|
241
|
+
return [process, {
|
|
242
|
+
...request,
|
|
243
|
+
pair: swapStep.pair
|
|
244
|
+
}];
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// BRIDGE -> SWAP: Try to find a token in dest chain that can bridge from fromToken
|
|
248
|
+
const bridgeDestination = (0, _utils2.findXcmDestination)(this.chainService.getAssetRefMap(), fromToken, toChain);
|
|
249
|
+
if (bridgeDestination && allSupportedChainsBySwapProvider.includes(toChain)) {
|
|
250
|
+
const bridgeStep = (0, _utils2.getBridgeStep)(fromToken.slug, bridgeDestination);
|
|
251
|
+
const swapStep = (0, _utils2.getSwapStep)(bridgeDestination, toToken.slug);
|
|
252
|
+
process.push(bridgeStep);
|
|
253
|
+
process.push(swapStep);
|
|
254
|
+
return [process, {
|
|
255
|
+
...request,
|
|
256
|
+
address: (0, _utils3.reformatAddress)(request.address, (0, _utils._getChainSubstrateAddressPrefix)(toChainInfo)),
|
|
257
|
+
pair: swapStep.pair
|
|
258
|
+
}];
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
// todo: improve to support SWAP -> BRIDGE and BRIDGE -> SWAP -> BRIDGE
|
|
262
|
+
|
|
263
|
+
return [[], undefined];
|
|
264
|
+
}
|
|
265
|
+
async getLatestQuoteFromSwapRequest(request) {
|
|
266
|
+
const [path, directSwapRequest] = this.getAvailablePath(request);
|
|
267
|
+
if (!directSwapRequest) {
|
|
268
|
+
throw Error('Swap pair not found');
|
|
269
|
+
}
|
|
270
|
+
const swapQuoteResponse = await this.getLatestDirectQuotes(directSwapRequest);
|
|
271
|
+
return {
|
|
272
|
+
path,
|
|
273
|
+
swapQuoteResponse
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
async getLatestDirectQuotes(request) {
|
|
277
|
+
// request.pair.metadata = this.getSwapPairMetadata(request.pair.slug); // deprecated
|
|
120
278
|
const quoteAskResponses = await this.askProvidersForQuote(request);
|
|
121
279
|
|
|
122
280
|
// todo: handle error to return back to UI
|
|
@@ -125,7 +283,7 @@ class SwapService {
|
|
|
125
283
|
const availableQuotes = quoteAskResponses.filter(quote => !quote.error).map(quote => quote.quote);
|
|
126
284
|
let quoteError;
|
|
127
285
|
let selectedQuote;
|
|
128
|
-
let aliveUntil = +Date.now() +
|
|
286
|
+
let aliveUntil = +Date.now() + _utils2.SWAP_QUOTE_TIMEOUT_MAP.default;
|
|
129
287
|
if (availableQuotes.length === 0) {
|
|
130
288
|
const preferredErrorResp = quoteAskResponses.find(quote => {
|
|
131
289
|
return !!quote.error && ![_swap.SwapErrorType.UNKNOWN, _swap.SwapErrorType.ASSET_NOT_SUPPORTED].includes(quote.error.errorType);
|
|
@@ -137,8 +295,8 @@ class SwapService {
|
|
|
137
295
|
selectedQuote = availableQuotes.find(quote => {
|
|
138
296
|
var _request$currentQuote;
|
|
139
297
|
return quote.provider.id === ((_request$currentQuote = request.currentQuote) === null || _request$currentQuote === void 0 ? void 0 : _request$currentQuote.id);
|
|
140
|
-
}) || availableQuotes[0];
|
|
141
|
-
aliveUntil = ((_selectedQuote = selectedQuote) === null || _selectedQuote === void 0 ? void 0 : _selectedQuote.aliveUntil) || +Date.now() +
|
|
298
|
+
}) || availableQuotes[0]; // todo: choose best quote based on rate
|
|
299
|
+
aliveUntil = ((_selectedQuote = selectedQuote) === null || _selectedQuote === void 0 ? void 0 : _selectedQuote.aliveUntil) || +Date.now() + _utils2.SWAP_QUOTE_TIMEOUT_MAP.default;
|
|
142
300
|
}
|
|
143
301
|
return {
|
|
144
302
|
optimalQuote: selectedQuote,
|
|
@@ -207,7 +365,7 @@ class SwapService {
|
|
|
207
365
|
|
|
208
366
|
// Update promise handler
|
|
209
367
|
this.startPromiseHandler.resolve();
|
|
210
|
-
this.stopPromiseHandler = (0,
|
|
368
|
+
this.stopPromiseHandler = (0, _utils3.createPromiseHandler)();
|
|
211
369
|
this.status = _types.ServiceStatus.STARTED;
|
|
212
370
|
}
|
|
213
371
|
async stop() {
|
|
@@ -221,7 +379,7 @@ class SwapService {
|
|
|
221
379
|
// todo: unsub, persist data,...
|
|
222
380
|
|
|
223
381
|
this.stopPromiseHandler.resolve();
|
|
224
|
-
this.startPromiseHandler = (0,
|
|
382
|
+
this.startPromiseHandler = (0, _utils3.createPromiseHandler)();
|
|
225
383
|
this.status = _types.ServiceStatus.STOPPED;
|
|
226
384
|
}
|
|
227
385
|
waitForStarted() {
|
|
@@ -239,20 +397,25 @@ class SwapService {
|
|
|
239
397
|
from: assetRef.srcAsset,
|
|
240
398
|
to: assetRef.destAsset,
|
|
241
399
|
metadata: {
|
|
242
|
-
alternativeAsset: (0,
|
|
400
|
+
alternativeAsset: (0, _utils2.getSwapAltToken)(fromAsset)
|
|
243
401
|
}
|
|
244
402
|
};
|
|
245
403
|
});
|
|
246
404
|
}
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
}
|
|
405
|
+
|
|
406
|
+
// private getSwapPairMetadata (slug: string): Record<string, any> | undefined {
|
|
407
|
+
// return this.getSwapPairs().find((pair) => pair.slug === slug)?.metadata;
|
|
408
|
+
// }
|
|
409
|
+
|
|
251
410
|
async validateSwapProcess(params) {
|
|
252
411
|
const providerId = params.selectedQuote.provider.id;
|
|
253
412
|
const handler = this.handlers[providerId];
|
|
413
|
+
if (params.currentStep > 1) {
|
|
414
|
+
// only validate from the first step
|
|
415
|
+
return [];
|
|
416
|
+
}
|
|
254
417
|
if (handler) {
|
|
255
|
-
return handler.
|
|
418
|
+
return handler.validateSwapProcessV2(params);
|
|
256
419
|
} else {
|
|
257
420
|
return [new _TransactionError.TransactionError(_types2.BasicTxErrorType.INTERNAL_ERROR)];
|
|
258
421
|
}
|
|
@@ -263,6 +426,7 @@ class SwapService {
|
|
|
263
426
|
// todo: do better to handle error generating steps
|
|
264
427
|
return Promise.reject(new _TransactionError.TransactionError(_types2.BasicTxErrorType.INTERNAL_ERROR, 'Please check your network and try again'));
|
|
265
428
|
}
|
|
429
|
+
console.log('handling swap process: ', params.process);
|
|
266
430
|
if (handler) {
|
|
267
431
|
return handler.handleSwapProcess(params);
|
|
268
432
|
} else {
|
|
@@ -279,7 +443,7 @@ class SwapService {
|
|
|
279
443
|
from: assetRef.srcAsset,
|
|
280
444
|
to: assetRef.destAsset,
|
|
281
445
|
metadata: {
|
|
282
|
-
alternativeAsset: (0,
|
|
446
|
+
alternativeAsset: (0, _utils2.getSwapAltToken)(fromAsset)
|
|
283
447
|
}
|
|
284
448
|
};
|
|
285
449
|
});
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.DynamicSwapType = void 0;
|
|
7
|
+
// Copyright 2019-2022 @subwallet/extension-base
|
|
8
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
9
|
+
let DynamicSwapType;
|
|
10
|
+
exports.DynamicSwapType = DynamicSwapType;
|
|
11
|
+
(function (DynamicSwapType) {
|
|
12
|
+
DynamicSwapType["SWAP"] = "SWAP";
|
|
13
|
+
DynamicSwapType["BRIDGE"] = "BRIDGE";
|
|
14
|
+
})(DynamicSwapType || (exports.DynamicSwapType = DynamicSwapType = {}));
|
|
@@ -4,17 +4,25 @@ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefau
|
|
|
4
4
|
Object.defineProperty(exports, "__esModule", {
|
|
5
5
|
value: true
|
|
6
6
|
});
|
|
7
|
-
exports._PROVIDER_TO_SUPPORTED_PAIR_MAP = exports.SWAP_QUOTE_TIMEOUT_MAP = exports.SIMPLE_SWAP_SUPPORTED_TESTNET_ASSET_MAPPING = exports.SIMPLE_SWAP_EXPLORER = exports.CHAIN_FLIP_TESTNET_EXPLORER = exports.CHAIN_FLIP_MAINNET_EXPLORER = void 0;
|
|
7
|
+
exports._PROVIDER_TO_SUPPORTED_PAIR_MAP = exports.SWAP_QUOTE_TIMEOUT_MAP = exports.SIMPLE_SWAP_SUPPORTED_TESTNET_ASSET_MAPPING = exports.SIMPLE_SWAP_EXPLORER = exports.FEE_RATE_MULTIPLIER = exports.CHAIN_FLIP_TESTNET_EXPLORER = exports.CHAIN_FLIP_MAINNET_EXPLORER = void 0;
|
|
8
8
|
exports.calculateSwapRate = calculateSwapRate;
|
|
9
9
|
exports.convertSwapRate = convertSwapRate;
|
|
10
|
+
exports.findXcmDestination = findXcmDestination;
|
|
11
|
+
exports.getBridgeStep = getBridgeStep;
|
|
10
12
|
exports.getChainflipBroker = getChainflipBroker;
|
|
11
13
|
exports.getChainflipOptions = getChainflipOptions;
|
|
12
14
|
exports.getChainflipSwap = getChainflipSwap;
|
|
13
15
|
exports.getSwapAltToken = getSwapAltToken;
|
|
14
16
|
exports.getSwapAlternativeAsset = getSwapAlternativeAsset;
|
|
17
|
+
exports.getSwapStep = getSwapStep;
|
|
18
|
+
exports.getTokenPairFromStep = getTokenPairFromStep;
|
|
19
|
+
exports.isChainsHasSameProvider = isChainsHasSameProvider;
|
|
15
20
|
var _chainList = require("@subwallet/chain-list");
|
|
21
|
+
var _types = require("@subwallet/chain-list/types");
|
|
16
22
|
var _utils = require("@subwallet/extension-base/services/chain-service/utils");
|
|
17
23
|
var _chainflipHandler = require("@subwallet/extension-base/services/swap-service/handler/chainflip-handler");
|
|
24
|
+
var _interface = require("@subwallet/extension-base/services/swap-service/interface");
|
|
25
|
+
var _types2 = require("@subwallet/extension-base/types");
|
|
18
26
|
var _swap = require("@subwallet/extension-base/types/swap");
|
|
19
27
|
var _bignumber = _interopRequireDefault(require("bignumber.js"));
|
|
20
28
|
// Copyright 2019-2022 @subwallet/extension-base
|
|
@@ -43,16 +51,24 @@ const SWAP_QUOTE_TIMEOUT_MAP = {
|
|
|
43
51
|
exports.SWAP_QUOTE_TIMEOUT_MAP = SWAP_QUOTE_TIMEOUT_MAP;
|
|
44
52
|
const _PROVIDER_TO_SUPPORTED_PAIR_MAP = {
|
|
45
53
|
[_swap.SwapProviderId.HYDRADX_MAINNET]: [_chainList.COMMON_CHAIN_SLUGS.HYDRADX],
|
|
46
|
-
[_swap.SwapProviderId.HYDRADX_TESTNET]: [_chainList.COMMON_CHAIN_SLUGS.HYDRADX_TESTNET],
|
|
47
54
|
[_swap.SwapProviderId.CHAIN_FLIP_MAINNET]: [_chainList.COMMON_CHAIN_SLUGS.POLKADOT, _chainList.COMMON_CHAIN_SLUGS.ETHEREUM, _chainList.COMMON_CHAIN_SLUGS.ARBITRUM],
|
|
48
|
-
[_swap.SwapProviderId.CHAIN_FLIP_TESTNET]: [_chainList.COMMON_CHAIN_SLUGS.CHAINFLIP_POLKADOT, _chainList.COMMON_CHAIN_SLUGS.ETHEREUM_SEPOLIA],
|
|
49
55
|
[_swap.SwapProviderId.POLKADOT_ASSET_HUB]: [_chainList.COMMON_CHAIN_SLUGS.POLKADOT_ASSET_HUB],
|
|
50
56
|
[_swap.SwapProviderId.KUSAMA_ASSET_HUB]: [_chainList.COMMON_CHAIN_SLUGS.KUSAMA_ASSET_HUB],
|
|
57
|
+
[_swap.SwapProviderId.SIMPLE_SWAP]: ['bittensor', _chainList.COMMON_CHAIN_SLUGS.ETHEREUM, _chainList.COMMON_CHAIN_SLUGS.POLKADOT],
|
|
58
|
+
[_swap.SwapProviderId.UNISWAP]: [_chainList.COMMON_CHAIN_SLUGS.ETHEREUM, _chainList.COMMON_CHAIN_SLUGS.ARBITRUM],
|
|
59
|
+
// testnet
|
|
60
|
+
[_swap.SwapProviderId.CHAIN_FLIP_TESTNET]: [_chainList.COMMON_CHAIN_SLUGS.CHAINFLIP_POLKADOT, _chainList.COMMON_CHAIN_SLUGS.ETHEREUM_SEPOLIA],
|
|
61
|
+
[_swap.SwapProviderId.HYDRADX_TESTNET]: [_chainList.COMMON_CHAIN_SLUGS.HYDRADX_TESTNET],
|
|
51
62
|
[_swap.SwapProviderId.ROCOCO_ASSET_HUB]: [_chainList.COMMON_CHAIN_SLUGS.ROCOCO_ASSET_HUB],
|
|
52
|
-
[_swap.SwapProviderId.WESTEND_ASSET_HUB]: ['westend_assethub']
|
|
53
|
-
[_swap.SwapProviderId.SIMPLE_SWAP]: ['bittensor', _chainList.COMMON_CHAIN_SLUGS.ETHEREUM, _chainList.COMMON_CHAIN_SLUGS.POLKADOT]
|
|
63
|
+
[_swap.SwapProviderId.WESTEND_ASSET_HUB]: ['westend_assethub']
|
|
54
64
|
};
|
|
55
65
|
exports._PROVIDER_TO_SUPPORTED_PAIR_MAP = _PROVIDER_TO_SUPPORTED_PAIR_MAP;
|
|
66
|
+
const FEE_RATE_MULTIPLIER = {
|
|
67
|
+
default: 1,
|
|
68
|
+
medium: 1.2,
|
|
69
|
+
high: 2
|
|
70
|
+
};
|
|
71
|
+
exports.FEE_RATE_MULTIPLIER = FEE_RATE_MULTIPLIER;
|
|
56
72
|
function getSwapAlternativeAsset(swapPair) {
|
|
57
73
|
var _swapPair$metadata;
|
|
58
74
|
return swapPair === null || swapPair === void 0 ? void 0 : (_swapPair$metadata = swapPair.metadata) === null || _swapPair$metadata === void 0 ? void 0 : _swapPair$metadata.alternativeAsset;
|
|
@@ -105,4 +121,64 @@ function getChainflipSwap(isTestnet) {
|
|
|
105
121
|
} else {
|
|
106
122
|
return `https://chainflip-broker.io/swap?apikey=${_chainflipHandler.CHAINFLIP_BROKER_API}`;
|
|
107
123
|
}
|
|
124
|
+
}
|
|
125
|
+
function getBridgeStep(from, to) {
|
|
126
|
+
return {
|
|
127
|
+
action: _interface.DynamicSwapType.BRIDGE,
|
|
128
|
+
pair: {
|
|
129
|
+
slug: `${from}___${to}`,
|
|
130
|
+
from,
|
|
131
|
+
to
|
|
132
|
+
}
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
function getSwapStep(from, to) {
|
|
136
|
+
return {
|
|
137
|
+
action: _interface.DynamicSwapType.SWAP,
|
|
138
|
+
pair: {
|
|
139
|
+
slug: `${from}___${to}`,
|
|
140
|
+
from,
|
|
141
|
+
to
|
|
142
|
+
}
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
function findXcmDestination(assetRefMap, chainAsset, destChain) {
|
|
146
|
+
const foundAssetRef = Object.values(assetRefMap).find(assetRef => assetRef.srcAsset === chainAsset.slug && assetRef.destChain === destChain && assetRef.path === _types._AssetRefPath.XCM);
|
|
147
|
+
if (foundAssetRef) {
|
|
148
|
+
return foundAssetRef.destAsset;
|
|
149
|
+
}
|
|
150
|
+
return undefined;
|
|
151
|
+
}
|
|
152
|
+
function isChainsHasSameProvider(fromChain, toChain) {
|
|
153
|
+
// todo: a provider may support multiple chains but not cross-chain swaps
|
|
154
|
+
for (const group of Object.values(_PROVIDER_TO_SUPPORTED_PAIR_MAP)) {
|
|
155
|
+
if (group.includes(fromChain) && group.includes(toChain)) {
|
|
156
|
+
return true;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
return false;
|
|
160
|
+
}
|
|
161
|
+
function getTokenPairFromStep(steps) {
|
|
162
|
+
const mainSteps = steps.filter(step => step.type !== _types2.CommonStepType.DEFAULT);
|
|
163
|
+
if (!mainSteps.length) {
|
|
164
|
+
return undefined;
|
|
165
|
+
}
|
|
166
|
+
if (mainSteps.length === 1) {
|
|
167
|
+
const metadata = mainSteps[0].metadata; // todo: temp for round 1, the exact interface is handle in round 2
|
|
168
|
+
|
|
169
|
+
return {
|
|
170
|
+
from: metadata.originTokenInfo.slug,
|
|
171
|
+
to: metadata.destinationTokenInfo.slug,
|
|
172
|
+
slug: `${metadata.originTokenInfo.slug}___${metadata.destinationTokenInfo.slug}`
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
const firstStep = mainSteps[0];
|
|
176
|
+
const lastStep = mainSteps[mainSteps.length - 1];
|
|
177
|
+
const firstMetadata = firstStep.metadata;
|
|
178
|
+
const lastMetadata = lastStep.metadata;
|
|
179
|
+
return {
|
|
180
|
+
from: firstMetadata.originTokenInfo.slug,
|
|
181
|
+
to: lastMetadata.destinationTokenInfo.slug,
|
|
182
|
+
slug: `${firstMetadata.originTokenInfo.slug}___${lastMetadata.destinationTokenInfo.slug}`
|
|
183
|
+
};
|
|
108
184
|
}
|
|
@@ -44,6 +44,9 @@ function getBlockExplorerAccountRoute(explorerLink) {
|
|
|
44
44
|
if (explorerLink.includes('laos.statescan.io')) {
|
|
45
45
|
return '#/accounts';
|
|
46
46
|
}
|
|
47
|
+
if (explorerLink.includes('polimec.statescan.io')) {
|
|
48
|
+
return '#/accounts';
|
|
49
|
+
}
|
|
47
50
|
if (explorerLink.includes('explorer.zkverify.io')) {
|
|
48
51
|
return 'account';
|
|
49
52
|
}
|
|
@@ -65,7 +68,7 @@ function getBlockExplorerTxRoute(chainInfo) {
|
|
|
65
68
|
if (['aventus', 'deeper_network'].includes(chainInfo.slug)) {
|
|
66
69
|
return 'transaction';
|
|
67
70
|
}
|
|
68
|
-
if (['invarch', 'tangle'].includes(chainInfo.slug)) {
|
|
71
|
+
if (['invarch', 'tangle', 'polimec'].includes(chainInfo.slug)) {
|
|
69
72
|
return '#/extrinsics';
|
|
70
73
|
}
|
|
71
74
|
return 'extrinsic';
|
|
@@ -1,4 +1,8 @@
|
|
|
1
|
+
import { _ChainAsset } from '@subwallet/chain-list/types';
|
|
2
|
+
import { TransactionError } from '@subwallet/extension-base/background/errors/TransactionError';
|
|
3
|
+
import BigN from 'bignumber.js';
|
|
1
4
|
export * from './swap';
|
|
2
5
|
export * from './request';
|
|
3
6
|
export * from './earning';
|
|
4
7
|
export * from './transfer';
|
|
8
|
+
export declare function validateSpendingAndFeePayment(spendingToken: _ChainAsset, feeToken: _ChainAsset, bnSpendingAmount: BigN, bnFromTokenBalance: BigN, bnFeeAmount: BigN, bnFeeTokenBalance: BigN): TransactionError[];
|
|
@@ -1,7 +1,28 @@
|
|
|
1
1
|
// Copyright 2019-2022 @subwallet/extension-base
|
|
2
2
|
// SPDX-License-Identifier: Apache-2.0
|
|
3
3
|
|
|
4
|
+
import { TransactionError } from '@subwallet/extension-base/background/errors/TransactionError';
|
|
5
|
+
import { _getTokenMinAmount, _isNativeToken } from '@subwallet/extension-base/services/chain-service/utils';
|
|
6
|
+
import { BasicTxErrorType } from '@subwallet/extension-base/types';
|
|
7
|
+
import { t } from 'i18next';
|
|
4
8
|
export * from "./swap.js";
|
|
5
9
|
export * from "./request.js";
|
|
6
10
|
export * from "./earning.js";
|
|
7
|
-
export * from "./transfer.js";
|
|
11
|
+
export * from "./transfer.js";
|
|
12
|
+
|
|
13
|
+
// apply for all tx: transfer, xcm, swap, earning
|
|
14
|
+
export function validateSpendingAndFeePayment(spendingToken, feeToken, bnSpendingAmount, bnFromTokenBalance, bnFeeAmount, bnFeeTokenBalance) {
|
|
15
|
+
if (spendingToken.slug === feeToken.slug) {
|
|
16
|
+
if (bnFromTokenBalance.lte(bnSpendingAmount.plus(bnFeeAmount).plus(_isNativeToken(spendingToken) ? '0' : _getTokenMinAmount(spendingToken)))) {
|
|
17
|
+
return [new TransactionError(BasicTxErrorType.NOT_ENOUGH_BALANCE, t(`Insufficient balance. Deposit ${spendingToken.symbol} and try again.`))];
|
|
18
|
+
}
|
|
19
|
+
} else {
|
|
20
|
+
if (bnFromTokenBalance.lte(bnSpendingAmount.plus(_isNativeToken(spendingToken) ? '0' : _getTokenMinAmount(spendingToken)))) {
|
|
21
|
+
return [new TransactionError(BasicTxErrorType.NOT_ENOUGH_BALANCE, t(`Insufficient balance. Deposit ${spendingToken.symbol} and try again.`))];
|
|
22
|
+
}
|
|
23
|
+
if (bnFeeTokenBalance.lte(bnFeeAmount.plus(_isNativeToken(feeToken) ? '0' : _getTokenMinAmount(feeToken)))) {
|
|
24
|
+
return [new TransactionError(BasicTxErrorType.NOT_ENOUGH_BALANCE, t(`Insufficient balance. Deposit ${feeToken.symbol} and try again.`))];
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
return [];
|
|
28
|
+
}
|
package/core/utils.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
import { _ChainAsset } from '@subwallet/chain-list/types';
|
|
1
2
|
import { ExtrinsicType } from '@subwallet/extension-base/background/KoniTypes';
|
|
2
3
|
import { LedgerMustCheckType, ValidateRecipientParams } from '@subwallet/extension-base/core/types';
|
|
4
|
+
import { _SubstrateApi } from '@subwallet/extension-base/services/chain-service/types';
|
|
3
5
|
import { AccountJson } from '@subwallet/extension-base/types';
|
|
4
6
|
export declare function getStrictMode(type: string, extrinsicType?: ExtrinsicType): boolean;
|
|
5
7
|
export declare function _getAppliedExistentialDeposit(existentialDeposit: string, strictMode?: boolean): bigint;
|
|
@@ -13,3 +15,4 @@ export declare function _isValidTonAddressFormat(validateRecipientParams: Valida
|
|
|
13
15
|
export declare function _isValidCardanoAddressFormat(validateRecipientParams: ValidateRecipientParams): string;
|
|
14
16
|
export declare function _isNotDuplicateAddress(validateRecipientParams: ValidateRecipientParams): string;
|
|
15
17
|
export declare function _isSupportLedgerAccount(validateRecipientParams: ValidateRecipientParams): string;
|
|
18
|
+
export declare const _isSufficientToken: (tokenInfo: _ChainAsset, substrateApi: _SubstrateApi) => Promise<boolean>;
|
package/core/utils.js
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
// Copyright 2019-2022 @subwallet/extension-base
|
|
2
2
|
// SPDX-License-Identifier: Apache-2.0
|
|
3
3
|
|
|
4
|
+
import { _AssetType } from '@subwallet/chain-list/types';
|
|
4
5
|
import { ExtrinsicType } from '@subwallet/extension-base/background/KoniTypes';
|
|
5
6
|
import { BalanceAccountType } from '@subwallet/extension-base/core/substrate/types';
|
|
6
7
|
import { tonAddressInfo } from '@subwallet/extension-base/services/balance-service/helpers/subscribe/ton/utils';
|
|
7
|
-
import {
|
|
8
|
+
import { SUFFICIENT_CHAIN } from '@subwallet/extension-base/services/chain-service/constants';
|
|
9
|
+
import { _getTokenOnChainAssetId, _getXcmAssetMultilocation, _isBridgedToken, _isChainCardanoCompatible, _isChainEvmCompatible, _isChainSubstrateCompatible, _isChainTonCompatible } from '@subwallet/extension-base/services/chain-service/utils';
|
|
8
10
|
import { isAddressAndChainCompatible, isSameAddress, reformatAddress } from '@subwallet/extension-base/utils';
|
|
9
11
|
import { isAddress, isCardanoTestnetAddress, isTonAddress } from '@subwallet/keyring';
|
|
10
12
|
import { isEthereumAddress } from '@polkadot/util-crypto';
|
|
@@ -129,4 +131,22 @@ export function _isSupportLedgerAccount(validateRecipientParams) {
|
|
|
129
131
|
}
|
|
130
132
|
}
|
|
131
133
|
return '';
|
|
132
|
-
}
|
|
134
|
+
}
|
|
135
|
+
export const _isSufficientToken = async (tokenInfo, substrateApi) => {
|
|
136
|
+
if (SUFFICIENT_CHAIN.includes(tokenInfo.originChain) && tokenInfo.assetType !== _AssetType.NATIVE) {
|
|
137
|
+
const assetId = _isBridgedToken(tokenInfo) ? _getXcmAssetMultilocation(tokenInfo) : _getTokenOnChainAssetId(tokenInfo);
|
|
138
|
+
const queryParams = {
|
|
139
|
+
section: 'query',
|
|
140
|
+
module: 'foreignAssets',
|
|
141
|
+
method: 'asset',
|
|
142
|
+
args: [assetId]
|
|
143
|
+
};
|
|
144
|
+
if (!_isBridgedToken(tokenInfo)) {
|
|
145
|
+
queryParams.module = 'assets';
|
|
146
|
+
}
|
|
147
|
+
const metadata = await substrateApi.makeRpcQuery(queryParams);
|
|
148
|
+
return metadata.isSufficient;
|
|
149
|
+
} else {
|
|
150
|
+
return false;
|
|
151
|
+
}
|
|
152
|
+
};
|
|
@@ -135,7 +135,6 @@ export default class KoniExtension {
|
|
|
135
135
|
private recoverDotSamaApi;
|
|
136
136
|
private validateERC721Token;
|
|
137
137
|
private upsertCustomToken;
|
|
138
|
-
private isSufficientToken;
|
|
139
138
|
private deleteCustomAsset;
|
|
140
139
|
private validateCustomAsset;
|
|
141
140
|
private getAddressTransferableBalance;
|
|
@@ -255,8 +254,9 @@ export default class KoniExtension {
|
|
|
255
254
|
private subscribeBuyTokens;
|
|
256
255
|
private subscribeBuyServices;
|
|
257
256
|
private subscribeSwapPairs;
|
|
258
|
-
private
|
|
257
|
+
private getOptimalSwapProcessOnSelectQuote;
|
|
259
258
|
private handleSwapRequest;
|
|
259
|
+
private handleSwapRequestV2;
|
|
260
260
|
private getLatestSwapQuote;
|
|
261
261
|
private validateSwapProcess;
|
|
262
262
|
private handleSwapStep;
|