@subwallet/extension-base 1.3.25-0 → 1.3.27-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/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/constants.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 +3 -3
- 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/constants.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 +3 -3
- package/types/service-base.d.ts +6 -2
- package/types/swap/index.d.ts +34 -6
- package/types/transaction/process.d.ts +0 -6
|
@@ -4,14 +4,15 @@
|
|
|
4
4
|
import { SwapError } from '@subwallet/extension-base/background/errors/SwapError';
|
|
5
5
|
import { TransactionError } from '@subwallet/extension-base/background/errors/TransactionError';
|
|
6
6
|
import { ServiceStatus } from '@subwallet/extension-base/services/base/types';
|
|
7
|
+
import { _getAssetOriginChain, _getChainSubstrateAddressPrefix } from '@subwallet/extension-base/services/chain-service/utils';
|
|
7
8
|
import { AssetHubSwapHandler } from '@subwallet/extension-base/services/swap-service/handler/asset-hub';
|
|
8
9
|
import { ChainflipSwapHandler } from '@subwallet/extension-base/services/swap-service/handler/chainflip-handler';
|
|
9
10
|
import { HydradxHandler } from '@subwallet/extension-base/services/swap-service/handler/hydradx-handler';
|
|
10
|
-
import { _PROVIDER_TO_SUPPORTED_PAIR_MAP, getSwapAltToken, SWAP_QUOTE_TIMEOUT_MAP } from '@subwallet/extension-base/services/swap-service/utils';
|
|
11
|
+
import { _PROVIDER_TO_SUPPORTED_PAIR_MAP, findXcmDestination, getBridgeStep, getSwapAltToken, getSwapStep, isChainsHasSameProvider, SWAP_QUOTE_TIMEOUT_MAP } from '@subwallet/extension-base/services/swap-service/utils';
|
|
11
12
|
import { BasicTxErrorType } from '@subwallet/extension-base/types';
|
|
12
13
|
import { DEFAULT_FIRST_STEP, MOCK_STEP_FEE } from '@subwallet/extension-base/types/service-base';
|
|
13
14
|
import { _SUPPORTED_SWAP_PROVIDERS, SwapErrorType, SwapProviderId, SwapStepType } from '@subwallet/extension-base/types/swap';
|
|
14
|
-
import { createPromiseHandler } from '@subwallet/extension-base/utils';
|
|
15
|
+
import { createPromiseHandler, reformatAddress } from '@subwallet/extension-base/utils';
|
|
15
16
|
import subwalletApiSdk from '@subwallet/subwallet-api-sdk';
|
|
16
17
|
import { BehaviorSubject } from 'rxjs';
|
|
17
18
|
import { SimpleSwapHandler } from "./handler/simpleswap-handler.js";
|
|
@@ -63,7 +64,8 @@ export class SwapService {
|
|
|
63
64
|
getDefaultProcess(params) {
|
|
64
65
|
const result = {
|
|
65
66
|
totalFee: [MOCK_STEP_FEE],
|
|
66
|
-
steps: [DEFAULT_FIRST_STEP]
|
|
67
|
+
steps: [DEFAULT_FIRST_STEP],
|
|
68
|
+
path: []
|
|
67
69
|
};
|
|
68
70
|
result.totalFee.push({
|
|
69
71
|
feeComponent: [],
|
|
@@ -77,6 +79,33 @@ export class SwapService {
|
|
|
77
79
|
});
|
|
78
80
|
return result;
|
|
79
81
|
}
|
|
82
|
+
getDefaultProcessV2(params) {
|
|
83
|
+
const result = {
|
|
84
|
+
totalFee: [MOCK_STEP_FEE],
|
|
85
|
+
steps: [DEFAULT_FIRST_STEP],
|
|
86
|
+
path: []
|
|
87
|
+
};
|
|
88
|
+
const swapPairInfo = params.path[0].pair; // todo: improve for Round 2
|
|
89
|
+
|
|
90
|
+
result.totalFee.push({
|
|
91
|
+
feeComponent: [],
|
|
92
|
+
feeOptions: [params.request.pair.from],
|
|
93
|
+
defaultFeeToken: params.request.pair.from
|
|
94
|
+
});
|
|
95
|
+
result.steps.push({
|
|
96
|
+
id: result.steps.length,
|
|
97
|
+
name: 'Swap',
|
|
98
|
+
type: SwapStepType.SWAP,
|
|
99
|
+
metadata: {
|
|
100
|
+
sendingValue: params.request.fromAmount.toString(),
|
|
101
|
+
originTokenInfo: this.chainService.getAssetBySlug(swapPairInfo.from),
|
|
102
|
+
destinationTokenInfo: this.chainService.getAssetBySlug(swapPairInfo.to)
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
return result;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// deprecated
|
|
80
109
|
async generateOptimalProcess(params) {
|
|
81
110
|
if (!params.selectedQuote) {
|
|
82
111
|
return this.getDefaultProcess(params);
|
|
@@ -91,24 +120,153 @@ export class SwapService {
|
|
|
91
120
|
}
|
|
92
121
|
}
|
|
93
122
|
}
|
|
123
|
+
async generateOptimalProcessV2(params) {
|
|
124
|
+
if (!params.selectedQuote) {
|
|
125
|
+
return this.getDefaultProcessV2(params);
|
|
126
|
+
} else {
|
|
127
|
+
var _params$request$curre2;
|
|
128
|
+
const providerId = ((_params$request$curre2 = params.request.currentQuote) === null || _params$request$curre2 === void 0 ? void 0 : _params$request$curre2.id) || params.selectedQuote.provider.id;
|
|
129
|
+
const handler = this.handlers[providerId];
|
|
130
|
+
if (handler) {
|
|
131
|
+
return handler.generateOptimalProcessV2(params);
|
|
132
|
+
} else {
|
|
133
|
+
return this.getDefaultProcessV2(params);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
async generateOptimalProcessWithoutPath(params) {
|
|
138
|
+
var _params$request$curre3;
|
|
139
|
+
if (!params.selectedQuote || params.path.length > 0) {
|
|
140
|
+
return this.getDefaultProcessV2(params);
|
|
141
|
+
}
|
|
142
|
+
const [path, directSwapRequest] = this.getAvailablePath(params.request);
|
|
143
|
+
if (!directSwapRequest) {
|
|
144
|
+
return this.getDefaultProcessV2(params);
|
|
145
|
+
}
|
|
146
|
+
params.path = path;
|
|
147
|
+
const providerId = ((_params$request$curre3 = params.request.currentQuote) === null || _params$request$curre3 === void 0 ? void 0 : _params$request$curre3.id) || params.selectedQuote.provider.id;
|
|
148
|
+
const handler = this.handlers[providerId];
|
|
149
|
+
if (handler) {
|
|
150
|
+
return handler.generateOptimalProcessV2(params);
|
|
151
|
+
} else {
|
|
152
|
+
return this.getDefaultProcessV2(params);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// deprecated
|
|
157
|
+
// eslint-disable-next-line @typescript-eslint/require-await
|
|
94
158
|
async handleSwapRequest(request) {
|
|
95
|
-
/*
|
|
96
|
-
* 1. Ask swap quotes from providers
|
|
97
|
-
* 2. Select the best quote
|
|
98
|
-
* 3. Generate optimal process for that quote
|
|
159
|
+
/*
|
|
160
|
+
* 1. Ask swap quotes from providers
|
|
161
|
+
* 2. Select the best quote
|
|
162
|
+
* 3. Generate optimal process for that quote
|
|
99
163
|
* */
|
|
100
|
-
|
|
101
|
-
const
|
|
164
|
+
|
|
165
|
+
// const swapQuoteResponse = await this.getLatestDirectQuotes(request);
|
|
166
|
+
|
|
167
|
+
// const optimalProcess = await this.generateOptimalProcess({
|
|
168
|
+
// request,
|
|
169
|
+
// selectedQuote: swapQuoteResponse.optimalQuote
|
|
170
|
+
// });
|
|
171
|
+
|
|
172
|
+
return {
|
|
173
|
+
// @ts-ignore
|
|
174
|
+
process: null,
|
|
175
|
+
// @ts-ignore
|
|
176
|
+
quote: null
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
async handleSwapRequestV2(request) {
|
|
180
|
+
/*
|
|
181
|
+
* 1. Find available path
|
|
182
|
+
* 2. Ask swap quotes from providers
|
|
183
|
+
* 3. Select the best quote
|
|
184
|
+
* 4. Generate optimal process for that quote
|
|
185
|
+
* */
|
|
186
|
+
|
|
187
|
+
// todo: path will become a list of path in Round 2
|
|
188
|
+
// const [path, directSwapRequest] = this.getAvailablePath(request);
|
|
189
|
+
//
|
|
190
|
+
// if (!directSwapRequest) {
|
|
191
|
+
// throw Error('Swap pair not found');
|
|
192
|
+
// }
|
|
193
|
+
|
|
194
|
+
// const swapQuoteResponse = await this.getLatestDirectQuotes(directSwapRequest);
|
|
195
|
+
const {
|
|
196
|
+
path,
|
|
197
|
+
swapQuoteResponse
|
|
198
|
+
} = await this.getLatestQuoteFromSwapRequest(request);
|
|
199
|
+
const optimalProcess = await this.generateOptimalProcessV2({
|
|
102
200
|
request,
|
|
103
|
-
selectedQuote: swapQuoteResponse.optimalQuote
|
|
201
|
+
selectedQuote: swapQuoteResponse.optimalQuote,
|
|
202
|
+
path
|
|
104
203
|
});
|
|
105
204
|
return {
|
|
106
205
|
process: optimalProcess,
|
|
107
206
|
quote: swapQuoteResponse
|
|
108
207
|
};
|
|
109
208
|
}
|
|
110
|
-
|
|
111
|
-
|
|
209
|
+
getAvailablePath(request) {
|
|
210
|
+
const {
|
|
211
|
+
pair
|
|
212
|
+
} = request;
|
|
213
|
+
// todo: control provider tighter
|
|
214
|
+
const allSupportedChainsBySwapProvider = [...new Set(Object.values(_PROVIDER_TO_SUPPORTED_PAIR_MAP).flat())];
|
|
215
|
+
const fromToken = this.chainService.getAssetBySlug(pair.from);
|
|
216
|
+
const toToken = this.chainService.getAssetBySlug(pair.to);
|
|
217
|
+
const fromChain = _getAssetOriginChain(fromToken);
|
|
218
|
+
const toChain = _getAssetOriginChain(toToken);
|
|
219
|
+
const toChainInfo = this.chainService.getChainInfoByKey(toChain);
|
|
220
|
+
const process = [];
|
|
221
|
+
if (!fromToken || !toToken) {
|
|
222
|
+
throw Error('Token not found');
|
|
223
|
+
}
|
|
224
|
+
if (!fromChain || !toChain) {
|
|
225
|
+
throw Error('Token metadata error');
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// SWAP: 2 tokens in the same chain and chain has dex
|
|
229
|
+
if (isChainsHasSameProvider(fromChain, toChain)) {
|
|
230
|
+
// there's a dex that can support direct swapping
|
|
231
|
+
const swapStep = getSwapStep(fromToken.slug, toToken.slug);
|
|
232
|
+
process.push(swapStep);
|
|
233
|
+
return [process, {
|
|
234
|
+
...request,
|
|
235
|
+
pair: swapStep.pair
|
|
236
|
+
}];
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
// BRIDGE -> SWAP: Try to find a token in dest chain that can bridge from fromToken
|
|
240
|
+
const bridgeDestination = findXcmDestination(this.chainService.getAssetRefMap(), fromToken, toChain);
|
|
241
|
+
if (bridgeDestination && allSupportedChainsBySwapProvider.includes(toChain)) {
|
|
242
|
+
const bridgeStep = getBridgeStep(fromToken.slug, bridgeDestination);
|
|
243
|
+
const swapStep = getSwapStep(bridgeDestination, toToken.slug);
|
|
244
|
+
process.push(bridgeStep);
|
|
245
|
+
process.push(swapStep);
|
|
246
|
+
return [process, {
|
|
247
|
+
...request,
|
|
248
|
+
address: reformatAddress(request.address, _getChainSubstrateAddressPrefix(toChainInfo)),
|
|
249
|
+
pair: swapStep.pair
|
|
250
|
+
}];
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
// todo: improve to support SWAP -> BRIDGE and BRIDGE -> SWAP -> BRIDGE
|
|
254
|
+
|
|
255
|
+
return [[], undefined];
|
|
256
|
+
}
|
|
257
|
+
async getLatestQuoteFromSwapRequest(request) {
|
|
258
|
+
const [path, directSwapRequest] = this.getAvailablePath(request);
|
|
259
|
+
if (!directSwapRequest) {
|
|
260
|
+
throw Error('Swap pair not found');
|
|
261
|
+
}
|
|
262
|
+
const swapQuoteResponse = await this.getLatestDirectQuotes(directSwapRequest);
|
|
263
|
+
return {
|
|
264
|
+
path,
|
|
265
|
+
swapQuoteResponse
|
|
266
|
+
};
|
|
267
|
+
}
|
|
268
|
+
async getLatestDirectQuotes(request) {
|
|
269
|
+
// request.pair.metadata = this.getSwapPairMetadata(request.pair.slug); // deprecated
|
|
112
270
|
const quoteAskResponses = await this.askProvidersForQuote(request);
|
|
113
271
|
|
|
114
272
|
// todo: handle error to return back to UI
|
|
@@ -129,7 +287,7 @@ export class SwapService {
|
|
|
129
287
|
selectedQuote = availableQuotes.find(quote => {
|
|
130
288
|
var _request$currentQuote;
|
|
131
289
|
return quote.provider.id === ((_request$currentQuote = request.currentQuote) === null || _request$currentQuote === void 0 ? void 0 : _request$currentQuote.id);
|
|
132
|
-
}) || availableQuotes[0];
|
|
290
|
+
}) || availableQuotes[0]; // todo: choose best quote based on rate
|
|
133
291
|
aliveUntil = ((_selectedQuote = selectedQuote) === null || _selectedQuote === void 0 ? void 0 : _selectedQuote.aliveUntil) || +Date.now() + SWAP_QUOTE_TIMEOUT_MAP.default;
|
|
134
292
|
}
|
|
135
293
|
return {
|
|
@@ -235,15 +393,20 @@ export class SwapService {
|
|
|
235
393
|
};
|
|
236
394
|
});
|
|
237
395
|
}
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
}
|
|
396
|
+
|
|
397
|
+
// private getSwapPairMetadata (slug: string): Record<string, any> | undefined {
|
|
398
|
+
// return this.getSwapPairs().find((pair) => pair.slug === slug)?.metadata;
|
|
399
|
+
// }
|
|
400
|
+
|
|
242
401
|
async validateSwapProcess(params) {
|
|
243
402
|
const providerId = params.selectedQuote.provider.id;
|
|
244
403
|
const handler = this.handlers[providerId];
|
|
404
|
+
if (params.currentStep > 1) {
|
|
405
|
+
// only validate from the first step
|
|
406
|
+
return [];
|
|
407
|
+
}
|
|
245
408
|
if (handler) {
|
|
246
|
-
return handler.
|
|
409
|
+
return handler.validateSwapProcessV2(params);
|
|
247
410
|
} else {
|
|
248
411
|
return [new TransactionError(BasicTxErrorType.INTERNAL_ERROR)];
|
|
249
412
|
}
|
|
@@ -254,6 +417,7 @@ export class SwapService {
|
|
|
254
417
|
// todo: do better to handle error generating steps
|
|
255
418
|
return Promise.reject(new TransactionError(BasicTxErrorType.INTERNAL_ERROR, 'Please check your network and try again'));
|
|
256
419
|
}
|
|
420
|
+
console.log('handling swap process: ', params.process);
|
|
257
421
|
if (handler) {
|
|
258
422
|
return handler.handleSwapProcess(params);
|
|
259
423
|
} else {
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
// Copyright 2019-2022 @subwallet/extension-base
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
export let DynamicSwapType;
|
|
5
|
+
(function (DynamicSwapType) {
|
|
6
|
+
DynamicSwapType["SWAP"] = "SWAP";
|
|
7
|
+
DynamicSwapType["BRIDGE"] = "BRIDGE";
|
|
8
|
+
})(DynamicSwapType || (DynamicSwapType = {}));
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import { _ChainAsset } from '@subwallet/chain-list/types';
|
|
1
|
+
import { _AssetRef, _ChainAsset } from '@subwallet/chain-list/types';
|
|
2
|
+
import { DynamicSwapAction } from '@subwallet/extension-base/services/swap-service/interface';
|
|
3
|
+
import { CommonStepDetail } from '@subwallet/extension-base/types';
|
|
2
4
|
import { SwapPair } from '@subwallet/extension-base/types/swap';
|
|
3
5
|
export declare const CHAIN_FLIP_TESTNET_EXPLORER = "https://blocks-perseverance.chainflip.io";
|
|
4
6
|
export declare const CHAIN_FLIP_MAINNET_EXPLORER = "https://scan.chainflip.io";
|
|
@@ -6,6 +8,7 @@ export declare const SIMPLE_SWAP_EXPLORER = "https://simpleswap.io";
|
|
|
6
8
|
export declare const SIMPLE_SWAP_SUPPORTED_TESTNET_ASSET_MAPPING: Record<string, string>;
|
|
7
9
|
export declare const SWAP_QUOTE_TIMEOUT_MAP: Record<string, number>;
|
|
8
10
|
export declare const _PROVIDER_TO_SUPPORTED_PAIR_MAP: Record<string, string[]>;
|
|
11
|
+
export declare const FEE_RATE_MULTIPLIER: Record<string, number>;
|
|
9
12
|
export declare function getSwapAlternativeAsset(swapPair: SwapPair): string | undefined;
|
|
10
13
|
export declare function getSwapAltToken(chainAsset: _ChainAsset): string | undefined;
|
|
11
14
|
export declare function calculateSwapRate(fromAmount: string, toAmount: string, fromAsset: _ChainAsset, toAsset: _ChainAsset): number;
|
|
@@ -23,3 +26,8 @@ export declare function getChainflipBroker(isTestnet: boolean): {
|
|
|
23
26
|
url: string;
|
|
24
27
|
};
|
|
25
28
|
export declare function getChainflipSwap(isTestnet: boolean): string;
|
|
29
|
+
export declare function getBridgeStep(from: string, to: string): DynamicSwapAction;
|
|
30
|
+
export declare function getSwapStep(from: string, to: string): DynamicSwapAction;
|
|
31
|
+
export declare function findXcmDestination(assetRefMap: Record<string, _AssetRef>, chainAsset: _ChainAsset, destChain: string): string | undefined;
|
|
32
|
+
export declare function isChainsHasSameProvider(fromChain: string, toChain: string): boolean;
|
|
33
|
+
export declare function getTokenPairFromStep(steps: CommonStepDetail[]): SwapPair | undefined;
|
|
@@ -2,8 +2,11 @@
|
|
|
2
2
|
// SPDX-License-Identifier: Apache-2.0
|
|
3
3
|
|
|
4
4
|
import { COMMON_ASSETS, COMMON_CHAIN_SLUGS } from '@subwallet/chain-list';
|
|
5
|
+
import { _AssetRefPath } from '@subwallet/chain-list/types';
|
|
5
6
|
import { _getAssetDecimals } from '@subwallet/extension-base/services/chain-service/utils';
|
|
6
7
|
import { CHAINFLIP_BROKER_API } from '@subwallet/extension-base/services/swap-service/handler/chainflip-handler';
|
|
8
|
+
import { DynamicSwapType } from '@subwallet/extension-base/services/swap-service/interface';
|
|
9
|
+
import { CommonStepType } from '@subwallet/extension-base/types';
|
|
7
10
|
import { SwapProviderId } from '@subwallet/extension-base/types/swap';
|
|
8
11
|
import BigN from 'bignumber.js';
|
|
9
12
|
export const CHAIN_FLIP_TESTNET_EXPLORER = 'https://blocks-perseverance.chainflip.io';
|
|
@@ -24,14 +27,21 @@ export const SWAP_QUOTE_TIMEOUT_MAP = {
|
|
|
24
27
|
};
|
|
25
28
|
export const _PROVIDER_TO_SUPPORTED_PAIR_MAP = {
|
|
26
29
|
[SwapProviderId.HYDRADX_MAINNET]: [COMMON_CHAIN_SLUGS.HYDRADX],
|
|
27
|
-
[SwapProviderId.HYDRADX_TESTNET]: [COMMON_CHAIN_SLUGS.HYDRADX_TESTNET],
|
|
28
30
|
[SwapProviderId.CHAIN_FLIP_MAINNET]: [COMMON_CHAIN_SLUGS.POLKADOT, COMMON_CHAIN_SLUGS.ETHEREUM, COMMON_CHAIN_SLUGS.ARBITRUM],
|
|
29
|
-
[SwapProviderId.CHAIN_FLIP_TESTNET]: [COMMON_CHAIN_SLUGS.CHAINFLIP_POLKADOT, COMMON_CHAIN_SLUGS.ETHEREUM_SEPOLIA],
|
|
30
31
|
[SwapProviderId.POLKADOT_ASSET_HUB]: [COMMON_CHAIN_SLUGS.POLKADOT_ASSET_HUB],
|
|
31
32
|
[SwapProviderId.KUSAMA_ASSET_HUB]: [COMMON_CHAIN_SLUGS.KUSAMA_ASSET_HUB],
|
|
33
|
+
[SwapProviderId.SIMPLE_SWAP]: ['bittensor', COMMON_CHAIN_SLUGS.ETHEREUM, COMMON_CHAIN_SLUGS.POLKADOT],
|
|
34
|
+
[SwapProviderId.UNISWAP]: [COMMON_CHAIN_SLUGS.ETHEREUM, COMMON_CHAIN_SLUGS.ARBITRUM],
|
|
35
|
+
// testnet
|
|
36
|
+
[SwapProviderId.CHAIN_FLIP_TESTNET]: [COMMON_CHAIN_SLUGS.CHAINFLIP_POLKADOT, COMMON_CHAIN_SLUGS.ETHEREUM_SEPOLIA],
|
|
37
|
+
[SwapProviderId.HYDRADX_TESTNET]: [COMMON_CHAIN_SLUGS.HYDRADX_TESTNET],
|
|
32
38
|
[SwapProviderId.ROCOCO_ASSET_HUB]: [COMMON_CHAIN_SLUGS.ROCOCO_ASSET_HUB],
|
|
33
|
-
[SwapProviderId.WESTEND_ASSET_HUB]: ['westend_assethub']
|
|
34
|
-
|
|
39
|
+
[SwapProviderId.WESTEND_ASSET_HUB]: ['westend_assethub']
|
|
40
|
+
};
|
|
41
|
+
export const FEE_RATE_MULTIPLIER = {
|
|
42
|
+
default: 1,
|
|
43
|
+
medium: 1.2,
|
|
44
|
+
high: 2
|
|
35
45
|
};
|
|
36
46
|
export function getSwapAlternativeAsset(swapPair) {
|
|
37
47
|
var _swapPair$metadata;
|
|
@@ -85,4 +95,64 @@ export function getChainflipSwap(isTestnet) {
|
|
|
85
95
|
} else {
|
|
86
96
|
return `https://chainflip-broker.io/swap?apikey=${CHAINFLIP_BROKER_API}`;
|
|
87
97
|
}
|
|
98
|
+
}
|
|
99
|
+
export function getBridgeStep(from, to) {
|
|
100
|
+
return {
|
|
101
|
+
action: DynamicSwapType.BRIDGE,
|
|
102
|
+
pair: {
|
|
103
|
+
slug: `${from}___${to}`,
|
|
104
|
+
from,
|
|
105
|
+
to
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
export function getSwapStep(from, to) {
|
|
110
|
+
return {
|
|
111
|
+
action: DynamicSwapType.SWAP,
|
|
112
|
+
pair: {
|
|
113
|
+
slug: `${from}___${to}`,
|
|
114
|
+
from,
|
|
115
|
+
to
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
export function findXcmDestination(assetRefMap, chainAsset, destChain) {
|
|
120
|
+
const foundAssetRef = Object.values(assetRefMap).find(assetRef => assetRef.srcAsset === chainAsset.slug && assetRef.destChain === destChain && assetRef.path === _AssetRefPath.XCM);
|
|
121
|
+
if (foundAssetRef) {
|
|
122
|
+
return foundAssetRef.destAsset;
|
|
123
|
+
}
|
|
124
|
+
return undefined;
|
|
125
|
+
}
|
|
126
|
+
export function isChainsHasSameProvider(fromChain, toChain) {
|
|
127
|
+
// todo: a provider may support multiple chains but not cross-chain swaps
|
|
128
|
+
for (const group of Object.values(_PROVIDER_TO_SUPPORTED_PAIR_MAP)) {
|
|
129
|
+
if (group.includes(fromChain) && group.includes(toChain)) {
|
|
130
|
+
return true;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
return false;
|
|
134
|
+
}
|
|
135
|
+
export function getTokenPairFromStep(steps) {
|
|
136
|
+
const mainSteps = steps.filter(step => step.type !== CommonStepType.DEFAULT);
|
|
137
|
+
if (!mainSteps.length) {
|
|
138
|
+
return undefined;
|
|
139
|
+
}
|
|
140
|
+
if (mainSteps.length === 1) {
|
|
141
|
+
const metadata = mainSteps[0].metadata; // todo: temp for round 1, the exact interface is handle in round 2
|
|
142
|
+
|
|
143
|
+
return {
|
|
144
|
+
from: metadata.originTokenInfo.slug,
|
|
145
|
+
to: metadata.destinationTokenInfo.slug,
|
|
146
|
+
slug: `${metadata.originTokenInfo.slug}___${metadata.destinationTokenInfo.slug}`
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
const firstStep = mainSteps[0];
|
|
150
|
+
const lastStep = mainSteps[mainSteps.length - 1];
|
|
151
|
+
const firstMetadata = firstStep.metadata;
|
|
152
|
+
const lastMetadata = lastStep.metadata;
|
|
153
|
+
return {
|
|
154
|
+
from: firstMetadata.originTokenInfo.slug,
|
|
155
|
+
to: lastMetadata.destinationTokenInfo.slug,
|
|
156
|
+
slug: `${firstMetadata.originTokenInfo.slug}___${lastMetadata.destinationTokenInfo.slug}`
|
|
157
|
+
};
|
|
88
158
|
}
|
|
@@ -42,6 +42,9 @@ function getBlockExplorerAccountRoute(explorerLink) {
|
|
|
42
42
|
if (explorerLink.includes('astral.autonomys')) {
|
|
43
43
|
return 'accounts';
|
|
44
44
|
}
|
|
45
|
+
if (explorerLink.includes('taostats.io')) {
|
|
46
|
+
return 'account';
|
|
47
|
+
}
|
|
45
48
|
return 'address';
|
|
46
49
|
}
|
|
47
50
|
function getBlockExplorerTxRoute(chainInfo) {
|
|
@@ -66,9 +69,6 @@ export function getExplorerLink(chainInfo, value, type) {
|
|
|
66
69
|
return `${explorerLink}${explorerLink.endsWith('/') ? '' : '/'}${route}/${value}`;
|
|
67
70
|
}
|
|
68
71
|
if (explorerLink && isHex(hexAddPrefix(value))) {
|
|
69
|
-
if (chainInfo.slug === 'bittensor') {
|
|
70
|
-
return undefined;
|
|
71
|
-
}
|
|
72
72
|
const route = getBlockExplorerTxRoute(chainInfo);
|
|
73
73
|
if (chainInfo.slug === 'tangle') {
|
|
74
74
|
return `${explorerLink}${explorerLink.endsWith('/') ? '' : '/'}extrinsic/${value}${route}/${value}`;
|
package/types/service-base.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
import { DynamicSwapAction } from '@subwallet/extension-base/services/swap-service/interface';
|
|
1
2
|
import { OptimalSwapPathParams, SwapFeeType, SwapStepType } from '@subwallet/extension-base/types/swap';
|
|
2
3
|
import { OptimalYieldPath, OptimalYieldPathParams, YieldStepType } from '@subwallet/extension-base/types/yield';
|
|
3
4
|
export declare type OptimalProcessParams = OptimalYieldPathParams | OptimalSwapPathParams;
|
|
4
|
-
export declare type OptimalProcessResult = OptimalYieldPath |
|
|
5
|
+
export declare type OptimalProcessResult = OptimalYieldPath | CommonOptimalSwapPath;
|
|
5
6
|
export declare enum CommonStepType {
|
|
6
7
|
DEFAULT = "DEFAULT",
|
|
7
8
|
XCM = "XCM",
|
|
@@ -30,7 +31,10 @@ export interface CommonStepFeeInfo {
|
|
|
30
31
|
export interface CommonStepDetail extends BaseStepDetail {
|
|
31
32
|
id: number;
|
|
32
33
|
}
|
|
33
|
-
export interface
|
|
34
|
+
export interface CommonOptimalSwapPath extends CommonOptimalTransferPath {
|
|
35
|
+
path: DynamicSwapAction[];
|
|
36
|
+
}
|
|
37
|
+
export interface CommonOptimalTransferPath {
|
|
34
38
|
totalFee: CommonStepFeeInfo[];
|
|
35
39
|
steps: CommonStepDetail[];
|
|
36
40
|
}
|
package/types/swap/index.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { _ChainInfo } from '@subwallet/chain-list/types';
|
|
1
|
+
import { _ChainAsset, _ChainInfo } from '@subwallet/chain-list/types';
|
|
2
2
|
import { SwapError } from '@subwallet/extension-base/background/errors/SwapError';
|
|
3
3
|
import { AmountData, ChainType, ExtrinsicType } from '@subwallet/extension-base/background/KoniTypes';
|
|
4
|
-
import {
|
|
4
|
+
import { DynamicSwapAction } from '@subwallet/extension-base/services/swap-service/interface';
|
|
5
|
+
import { BaseStepDetail, BaseStepType, CommonOptimalSwapPath, CommonStepFeeInfo } from '@subwallet/extension-base/types/service-base';
|
|
5
6
|
import BigN from 'bignumber.js';
|
|
6
7
|
import { BaseProcessRequestSign, TransactionData } from '../transaction';
|
|
7
8
|
export declare type SwapRate = number;
|
|
@@ -11,6 +12,11 @@ export interface SwapPair {
|
|
|
11
12
|
to: string;
|
|
12
13
|
metadata?: Record<string, any>;
|
|
13
14
|
}
|
|
15
|
+
export interface ActionPair {
|
|
16
|
+
slug: string;
|
|
17
|
+
from: string;
|
|
18
|
+
to: string;
|
|
19
|
+
}
|
|
14
20
|
export interface SwapQuote {
|
|
15
21
|
pair: SwapPair;
|
|
16
22
|
fromAmount: string;
|
|
@@ -77,7 +83,7 @@ export interface SwapBaseTxData {
|
|
|
77
83
|
address: string;
|
|
78
84
|
slippage: number;
|
|
79
85
|
recipient?: string;
|
|
80
|
-
process:
|
|
86
|
+
process: CommonOptimalSwapPath;
|
|
81
87
|
}
|
|
82
88
|
export interface ChainflipSwapTxData extends SwapBaseTxData {
|
|
83
89
|
depositChannelId: string;
|
|
@@ -91,6 +97,7 @@ export interface HydradxSwapTxData extends SwapBaseTxData {
|
|
|
91
97
|
txHex: string;
|
|
92
98
|
}
|
|
93
99
|
export declare type GenSwapStepFunc = (params: OptimalSwapPathParams) => Promise<[BaseStepDetail, CommonStepFeeInfo] | undefined>;
|
|
100
|
+
export declare type GenSwapStepFuncV2 = (params: OptimalSwapPathParamsV2) => Promise<[BaseStepDetail, CommonStepFeeInfo] | undefined>;
|
|
94
101
|
export interface ChainflipPreValidationMetadata {
|
|
95
102
|
minSwap: AmountData;
|
|
96
103
|
maxSwap?: AmountData;
|
|
@@ -125,7 +132,7 @@ export interface SwapRequest {
|
|
|
125
132
|
currentQuote?: SwapProvider;
|
|
126
133
|
}
|
|
127
134
|
export interface SwapRequestResult {
|
|
128
|
-
process:
|
|
135
|
+
process: CommonOptimalSwapPath;
|
|
129
136
|
quote: SwapQuoteResponse;
|
|
130
137
|
}
|
|
131
138
|
export interface SwapQuoteResponse {
|
|
@@ -135,7 +142,7 @@ export interface SwapQuoteResponse {
|
|
|
135
142
|
error?: SwapError;
|
|
136
143
|
}
|
|
137
144
|
export interface SwapSubmitParams extends BaseProcessRequestSign {
|
|
138
|
-
process:
|
|
145
|
+
process: CommonOptimalSwapPath;
|
|
139
146
|
currentStep: number;
|
|
140
147
|
quote: SwapQuote;
|
|
141
148
|
address: string;
|
|
@@ -156,6 +163,11 @@ export interface OptimalSwapPathParams {
|
|
|
156
163
|
request: SwapRequest;
|
|
157
164
|
selectedQuote?: SwapQuote;
|
|
158
165
|
}
|
|
166
|
+
export interface OptimalSwapPathParamsV2 {
|
|
167
|
+
request: SwapRequest;
|
|
168
|
+
selectedQuote?: SwapQuote;
|
|
169
|
+
path: DynamicSwapAction[];
|
|
170
|
+
}
|
|
159
171
|
export interface SwapEarlyValidation {
|
|
160
172
|
error?: SwapErrorType;
|
|
161
173
|
metadata?: ChainflipPreValidationMetadata | HydradxPreValidationMetadata | AssetHubPreValidationMetadata;
|
|
@@ -165,9 +177,10 @@ export interface AssetHubSwapEarlyValidation extends SwapEarlyValidation {
|
|
|
165
177
|
}
|
|
166
178
|
export interface ValidateSwapProcessParams {
|
|
167
179
|
address: string;
|
|
168
|
-
process:
|
|
180
|
+
process: CommonOptimalSwapPath;
|
|
169
181
|
selectedQuote: SwapQuote;
|
|
170
182
|
recipient?: string;
|
|
183
|
+
currentStep: number;
|
|
171
184
|
}
|
|
172
185
|
export interface SlippageType {
|
|
173
186
|
slippage: BigN;
|
|
@@ -179,3 +192,18 @@ export interface PermitSwapData {
|
|
|
179
192
|
}
|
|
180
193
|
export declare const CHAINFLIP_SLIPPAGE = 0.02;
|
|
181
194
|
export declare const SIMPLE_SWAP_SLIPPAGE = 0.05;
|
|
195
|
+
export interface BaseSwapStepMetadata {
|
|
196
|
+
sendingValue: string;
|
|
197
|
+
originTokenInfo: _ChainAsset;
|
|
198
|
+
destinationTokenInfo: _ChainAsset;
|
|
199
|
+
}
|
|
200
|
+
export interface BriefXCMStep extends BaseSwapStepMetadata {
|
|
201
|
+
expectedReceive?: string;
|
|
202
|
+
}
|
|
203
|
+
export interface HydrationSwapStepMetadata extends BaseSwapStepMetadata {
|
|
204
|
+
txHex: `0x${string}`;
|
|
205
|
+
}
|
|
206
|
+
export interface ChainFlipSwapStepMetadata extends BaseSwapStepMetadata {
|
|
207
|
+
srcChain: string;
|
|
208
|
+
destChain: string;
|
|
209
|
+
}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { _ChainAsset } from '@subwallet/chain-list/types';
|
|
2
1
|
import { TransactionEventResponse } from '@subwallet/extension-base/services/transaction-service/types';
|
|
3
2
|
import { CommonStepDetail, CommonStepFeeInfo } from '../service-base';
|
|
4
3
|
import { SwapPair, SwapProvider, SwapRate, SwapRoute, SwapSubmitParams } from '../swap';
|
|
@@ -52,11 +51,6 @@ export interface BriefProcessStep {
|
|
|
52
51
|
processId: string;
|
|
53
52
|
stepId: number;
|
|
54
53
|
}
|
|
55
|
-
export interface BriefXCMStep {
|
|
56
|
-
sendingValue: string;
|
|
57
|
-
originTokenInfo: _ChainAsset;
|
|
58
|
-
destinationTokenInfo: _ChainAsset;
|
|
59
|
-
}
|
|
60
54
|
export interface BriefSwapStep {
|
|
61
55
|
pair: SwapPair;
|
|
62
56
|
fromAmount: string;
|