@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.
Files changed (54) hide show
  1. package/background/KoniTypes.d.ts +4 -3
  2. package/background/warnings/TransactionWarning.d.ts +2 -0
  3. package/background/warnings/TransactionWarning.js +16 -1
  4. package/cjs/background/warnings/TransactionWarning.js +15 -0
  5. package/cjs/core/logic-validation/index.js +32 -1
  6. package/cjs/core/utils.js +25 -3
  7. package/cjs/koni/background/handlers/Extension.js +86 -94
  8. package/cjs/packageInfo.js +1 -1
  9. package/cjs/services/chain-service/utils/patch.js +1 -1
  10. package/cjs/services/swap-service/handler/asset-hub/handler.js +182 -40
  11. package/cjs/services/swap-service/handler/asset-hub/utils.js +3 -0
  12. package/cjs/services/swap-service/handler/base-handler.js +326 -12
  13. package/cjs/services/swap-service/handler/chainflip-handler.js +80 -16
  14. package/cjs/services/swap-service/handler/hydradx-handler.js +174 -30
  15. package/cjs/services/swap-service/handler/simpleswap-handler.js +50 -1
  16. package/cjs/services/swap-service/handler/uniswap-handler.js +47 -1
  17. package/cjs/services/swap-service/index.js +191 -27
  18. package/cjs/services/swap-service/interface.js +14 -0
  19. package/cjs/services/swap-service/utils.js +81 -5
  20. package/cjs/services/transaction-service/utils.js +4 -1
  21. package/core/logic-validation/index.d.ts +4 -0
  22. package/core/logic-validation/index.js +22 -1
  23. package/core/utils.d.ts +3 -0
  24. package/core/utils.js +22 -2
  25. package/koni/background/handlers/Extension.d.ts +2 -2
  26. package/koni/background/handlers/Extension.js +20 -28
  27. package/package.json +12 -7
  28. package/packageInfo.js +1 -1
  29. package/services/balance-service/helpers/process.d.ts +3 -3
  30. package/services/balance-service/index.d.ts +2 -3
  31. package/services/chain-service/utils/patch.js +1 -1
  32. package/services/swap-service/handler/asset-hub/handler.d.ts +6 -3
  33. package/services/swap-service/handler/asset-hub/handler.js +170 -28
  34. package/services/swap-service/handler/asset-hub/utils.js +3 -0
  35. package/services/swap-service/handler/base-handler.d.ts +12 -3
  36. package/services/swap-service/handler/base-handler.js +329 -15
  37. package/services/swap-service/handler/chainflip-handler.d.ts +4 -3
  38. package/services/swap-service/handler/chainflip-handler.js +74 -10
  39. package/services/swap-service/handler/hydradx-handler.d.ts +8 -3
  40. package/services/swap-service/handler/hydradx-handler.js +176 -32
  41. package/services/swap-service/handler/simpleswap-handler.d.ts +4 -2
  42. package/services/swap-service/handler/simpleswap-handler.js +50 -1
  43. package/services/swap-service/handler/uniswap-handler.d.ts +4 -2
  44. package/services/swap-service/handler/uniswap-handler.js +47 -1
  45. package/services/swap-service/index.d.ts +15 -5
  46. package/services/swap-service/index.js +182 -18
  47. package/services/swap-service/interface.d.ts +9 -0
  48. package/services/swap-service/interface.js +8 -0
  49. package/services/swap-service/utils.d.ts +9 -1
  50. package/services/swap-service/utils.js +74 -4
  51. package/services/transaction-service/utils.js +4 -1
  52. package/types/service-base.d.ts +6 -2
  53. package/types/swap/index.d.ts +34 -6
  54. 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 _utils = require("@subwallet/extension-base/services/swap-service/utils");
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 _utils2 = require("@subwallet/extension-base/utils");
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 = _utils._PROVIDER_TO_SUPPORTED_PAIR_MAP[providerSlug];
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, _utils2.createPromiseHandler)();
35
- stopPromiseHandler = (0, _utils2.createPromiseHandler)();
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
- const swapQuoteResponse = await this.getLatestQuotes(request);
109
- const optimalProcess = await this.generateOptimalProcess({
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
- async getLatestQuotes(request) {
119
- request.pair.metadata = this.getSwapPairMetadata(request.pair.slug); // todo: improve this
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() + _utils.SWAP_QUOTE_TIMEOUT_MAP.default;
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() + _utils.SWAP_QUOTE_TIMEOUT_MAP.default;
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, _utils2.createPromiseHandler)();
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, _utils2.createPromiseHandler)();
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, _utils.getSwapAltToken)(fromAsset)
400
+ alternativeAsset: (0, _utils2.getSwapAltToken)(fromAsset)
243
401
  }
244
402
  };
245
403
  });
246
404
  }
247
- getSwapPairMetadata(slug) {
248
- var _this$getSwapPairs$fi;
249
- return (_this$getSwapPairs$fi = this.getSwapPairs().find(pair => pair.slug === slug)) === null || _this$getSwapPairs$fi === void 0 ? void 0 : _this$getSwapPairs$fi.metadata;
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.validateSwapProcess(params);
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, _utils.getSwapAltToken)(fromAsset)
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 { _isChainCardanoCompatible, _isChainEvmCompatible, _isChainSubstrateCompatible, _isChainTonCompatible } from '@subwallet/extension-base/services/chain-service/utils';
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 generateOptimalProcess;
257
+ private getOptimalSwapProcessOnSelectQuote;
259
258
  private handleSwapRequest;
259
+ private handleSwapRequestV2;
260
260
  private getLatestSwapQuote;
261
261
  private validateSwapProcess;
262
262
  private handleSwapStep;