@subwallet/extension-base 1.3.39-0 → 1.3.40-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/cjs/koni/background/handlers/Extension.js +79 -69
- package/cjs/packageInfo.js +1 -1
- package/cjs/services/balance-service/transfer/xcm/index.js +19 -28
- package/cjs/services/balance-service/transfer/xcm/utils.js +47 -49
- package/cjs/services/chain-service/constants.js +2 -2
- package/cjs/services/chain-service/index.js +4 -0
- package/cjs/services/chain-service/utils/patch.js +1 -1
- package/cjs/services/earning-service/handlers/special.js +28 -36
- package/cjs/services/swap-service/handler/base-handler.js +58 -53
- package/cjs/services/swap-service/handler/kyber-handler.js +44 -28
- package/cjs/services/swap-service/handler/simpleswap-handler.js +79 -40
- package/cjs/services/swap-service/utils.js +2 -0
- package/cjs/utils/fee/transfer.js +41 -33
- package/koni/background/handlers/Extension.js +15 -5
- package/package.json +7 -7
- package/packageInfo.js +1 -1
- package/services/balance-service/transfer/xcm/index.d.ts +1 -2
- package/services/balance-service/transfer/xcm/index.js +16 -25
- package/services/balance-service/transfer/xcm/utils.d.ts +36 -6
- package/services/balance-service/transfer/xcm/utils.js +46 -48
- package/services/chain-service/constants.js +2 -2
- package/services/chain-service/index.js +4 -0
- package/services/chain-service/utils/patch.js +1 -1
- package/services/earning-service/handlers/special.js +12 -20
- package/services/swap-service/handler/base-handler.js +11 -6
- package/services/swap-service/handler/kyber-handler.js +44 -28
- package/services/swap-service/handler/simpleswap-handler.js +80 -41
- package/services/swap-service/utils.js +2 -0
- package/utils/fee/transfer.js +11 -3
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
// Copyright 2019-2022 @subwallet/extension-base
|
|
2
2
|
// SPDX-License-Identifier: Apache-2.0
|
|
3
3
|
|
|
4
|
-
import { XCM_MIN_AMOUNT_RATIO } from '@subwallet/extension-base/constants';
|
|
5
4
|
import { _isAcrossBridgeXcm, _isPolygonBridgeXcm, _isPosBridgeXcm, _isSnowBridgeXcm } from '@subwallet/extension-base/core/substrate/xcm-parser';
|
|
6
5
|
import { getAvailBridgeExtrinsicFromAvail, getAvailBridgeTxFromEth } from '@subwallet/extension-base/services/balance-service/transfer/xcm/availBridge';
|
|
7
6
|
import { getExtrinsicByPolkadotXcmPallet } from '@subwallet/extension-base/services/balance-service/transfer/xcm/polkadotXcm';
|
|
8
7
|
import { _createPolygonBridgeL1toL2Extrinsic, _createPolygonBridgeL2toL1Extrinsic } from '@subwallet/extension-base/services/balance-service/transfer/xcm/polygonBridge';
|
|
9
8
|
import { getSnowBridgeEvmTransfer } from '@subwallet/extension-base/services/balance-service/transfer/xcm/snowBridge';
|
|
10
|
-
import { buildXcm,
|
|
9
|
+
import { buildXcm, dryRunXcm, isChainNotSupportDryRun, isChainNotSupportPolkadotApi } from '@subwallet/extension-base/services/balance-service/transfer/xcm/utils';
|
|
11
10
|
import { getExtrinsicByXcmPalletPallet } from '@subwallet/extension-base/services/balance-service/transfer/xcm/xcmPallet';
|
|
12
11
|
import { getExtrinsicByXtokensPallet } from '@subwallet/extension-base/services/balance-service/transfer/xcm/xTokens';
|
|
13
12
|
import { _XCM_CHAIN_GROUP } from '@subwallet/extension-base/services/chain-service/constants';
|
|
@@ -39,6 +38,8 @@ export const createSnowBridgeExtrinsic = async ({
|
|
|
39
38
|
}
|
|
40
39
|
return getSnowBridgeEvmTransfer(originTokenInfo, originChain, destinationChain, sender, recipient, sendingValue, evmApi, feeInfo, feeCustom, feeOption);
|
|
41
40
|
};
|
|
41
|
+
|
|
42
|
+
// deprecated
|
|
42
43
|
export const createXcmExtrinsic = async ({
|
|
43
44
|
destinationChain,
|
|
44
45
|
originChain,
|
|
@@ -121,37 +122,27 @@ export const createXcmExtrinsicV2 = async request => {
|
|
|
121
122
|
return await buildXcm(request);
|
|
122
123
|
} catch (e) {
|
|
123
124
|
console.log('createXcmExtrinsicV2 error: ', e);
|
|
124
|
-
const errorMessage = e instanceof Error ? e.message : 'Unknown error occurred';
|
|
125
|
-
if (isChainNotSupportPolkadotApi(errorMessage)) {
|
|
126
|
-
return createXcmExtrinsic(request);
|
|
127
|
-
}
|
|
128
125
|
return undefined;
|
|
129
126
|
}
|
|
130
127
|
};
|
|
131
128
|
export const dryRunXcmExtrinsicV2 = async request => {
|
|
132
129
|
try {
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
return {
|
|
140
|
-
success: false
|
|
141
|
-
};
|
|
130
|
+
const dryRunResult = await dryRunXcm(request);
|
|
131
|
+
const originDryRunResult = dryRunResult.origin;
|
|
132
|
+
if (originDryRunResult.success) {
|
|
133
|
+
const destinationDryRunResult = dryRunResult.destination;
|
|
134
|
+
if (destinationDryRunResult.success) {
|
|
135
|
+
return true;
|
|
142
136
|
}
|
|
143
|
-
const _xcmFeeInfo = await xcmTransfer.paymentInfo(request.sender);
|
|
144
|
-
const xcmFeeInfo = _xcmFeeInfo.toPrimitive();
|
|
145
137
|
|
|
146
|
-
//
|
|
147
|
-
return
|
|
148
|
-
success: true,
|
|
149
|
-
fee: Math.round(xcmFeeInfo.partialFee * XCM_MIN_AMOUNT_RATIO).toString()
|
|
150
|
-
};
|
|
138
|
+
// pass dry-run in these cases
|
|
139
|
+
return isChainNotSupportDryRun(destinationDryRunResult.failureReason) || isChainNotSupportPolkadotApi(destinationDryRunResult.failureReason);
|
|
151
140
|
}
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
141
|
+
|
|
142
|
+
// pass dry-run in these cases
|
|
143
|
+
return isChainNotSupportDryRun(originDryRunResult.failureReason) || isChainNotSupportPolkadotApi(originDryRunResult.failureReason);
|
|
144
|
+
} catch (e) {
|
|
145
|
+
return false;
|
|
155
146
|
}
|
|
156
147
|
};
|
|
157
148
|
export const createAcrossBridgeExtrinsic = async ({
|
|
@@ -1,14 +1,44 @@
|
|
|
1
|
-
import { _ChainInfo } from '@subwallet/chain-list/types';
|
|
1
|
+
import { _ChainAsset, _ChainInfo } from '@subwallet/chain-list/types';
|
|
2
2
|
import { CreateXcmExtrinsicProps } from '@subwallet/extension-base/services/balance-service/transfer/xcm/index';
|
|
3
3
|
import { SubmittableExtrinsic } from '@polkadot/api/types';
|
|
4
|
-
export
|
|
5
|
-
success:
|
|
6
|
-
|
|
4
|
+
export declare type DryRunNodeFailure = {
|
|
5
|
+
success: false;
|
|
6
|
+
failureReason: string;
|
|
7
|
+
};
|
|
8
|
+
export declare type DryRunNodeSuccess = {
|
|
9
|
+
success: true;
|
|
10
|
+
fee: string;
|
|
11
|
+
forwardedXcms: any;
|
|
12
|
+
};
|
|
13
|
+
export declare type DryRunNodeResult = DryRunNodeSuccess | DryRunNodeFailure;
|
|
14
|
+
export declare type DryRunResult = {
|
|
15
|
+
origin: DryRunNodeResult;
|
|
16
|
+
destination?: DryRunNodeResult;
|
|
17
|
+
};
|
|
18
|
+
interface GetXcmFeeRequest {
|
|
19
|
+
sender: string;
|
|
20
|
+
recipient: string;
|
|
21
|
+
value: string;
|
|
22
|
+
fromChainInfo: _ChainInfo;
|
|
23
|
+
toChainInfo: _ChainInfo;
|
|
24
|
+
fromTokenInfo: _ChainAsset;
|
|
7
25
|
}
|
|
26
|
+
export declare type XcmFeeType = 'dryRun' | 'paymentInfo';
|
|
27
|
+
export interface XcmFeeDetail {
|
|
28
|
+
fee: string;
|
|
29
|
+
currency: string;
|
|
30
|
+
feeType: XcmFeeType;
|
|
31
|
+
dryRunError?: string;
|
|
32
|
+
}
|
|
33
|
+
export declare type GetXcmFeeResult = {
|
|
34
|
+
origin: XcmFeeDetail;
|
|
35
|
+
destination: XcmFeeDetail;
|
|
36
|
+
};
|
|
8
37
|
export declare function buildXcm(request: CreateXcmExtrinsicProps): Promise<SubmittableExtrinsic<"promise", import("@polkadot/types/types").ISubmittableResult>>;
|
|
9
|
-
export declare function dryRunXcm(request: CreateXcmExtrinsicProps): Promise<
|
|
10
|
-
export declare function
|
|
38
|
+
export declare function dryRunXcm(request: CreateXcmExtrinsicProps): Promise<DryRunResult>;
|
|
39
|
+
export declare function estimateXcmFee(request: GetXcmFeeRequest): Promise<GetXcmFeeResult | undefined>;
|
|
11
40
|
export declare function isChainNotSupportPolkadotApi(str: string): boolean;
|
|
12
41
|
export declare function isChainNotSupportDryRun(str: string): boolean;
|
|
13
42
|
export declare const STABLE_XCM_VERSION = 3;
|
|
14
43
|
export declare function isUseTeleportProtocol(originChainInfo: _ChainInfo, destChainInfo: _ChainInfo, tokenSlug?: string): boolean;
|
|
44
|
+
export {};
|
|
@@ -1,14 +1,13 @@
|
|
|
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
4
|
import { fetchParaSpellChainMap } from '@subwallet/extension-base/constants/paraspell-chain-map';
|
|
6
|
-
import { BasicTxErrorType } from '@subwallet/extension-base/types';
|
|
7
5
|
import { assert, compactToU8a, isHex, u8aConcat, u8aEq } from '@polkadot/util';
|
|
8
|
-
const paraSpellEndpoint = 'https://api.lightspell.xyz';
|
|
6
|
+
const paraSpellEndpoint = 'https://api.lightspell.xyz/v3';
|
|
9
7
|
const paraSpellApi = {
|
|
10
8
|
buildXcm: `${paraSpellEndpoint}/x-transfer`,
|
|
11
|
-
dryRunXcm: `${paraSpellEndpoint}/dry-run
|
|
9
|
+
dryRunXcm: `${paraSpellEndpoint}/dry-run`,
|
|
10
|
+
feeXcm: `${paraSpellEndpoint}/xcm-fee`
|
|
12
11
|
};
|
|
13
12
|
const paraSpellKey = process.env.PARASPELL_API_KEY || '';
|
|
14
13
|
function txHexToSubmittableExtrinsic(api, hex) {
|
|
@@ -73,7 +72,7 @@ export async function buildXcm(request) {
|
|
|
73
72
|
substrateApi
|
|
74
73
|
} = request;
|
|
75
74
|
if (!substrateApi) {
|
|
76
|
-
|
|
75
|
+
throw new Error('Substrate API is not available');
|
|
77
76
|
}
|
|
78
77
|
const psAssetType = (_originTokenInfo$meta = originTokenInfo.metadata) === null || _originTokenInfo$meta === void 0 ? void 0 : _originTokenInfo$meta.paraSpellAssetType;
|
|
79
78
|
const psAssetValue = (_originTokenInfo$meta2 = originTokenInfo.metadata) === null || _originTokenInfo$meta2 === void 0 ? void 0 : _originTokenInfo$meta2.paraSpellValue;
|
|
@@ -104,8 +103,6 @@ export async function buildXcm(request) {
|
|
|
104
103
|
const chainApi = await substrateApi.isReady;
|
|
105
104
|
return txHexToSubmittableExtrinsic(chainApi.api, extrinsicHex);
|
|
106
105
|
}
|
|
107
|
-
|
|
108
|
-
// dry run can fail due to sender address & amount token
|
|
109
106
|
export async function dryRunXcm(request) {
|
|
110
107
|
var _originTokenInfo$meta3, _originTokenInfo$meta4;
|
|
111
108
|
const {
|
|
@@ -120,60 +117,60 @@ export async function dryRunXcm(request) {
|
|
|
120
117
|
const psAssetType = (_originTokenInfo$meta3 = originTokenInfo.metadata) === null || _originTokenInfo$meta3 === void 0 ? void 0 : _originTokenInfo$meta3.paraSpellAssetType;
|
|
121
118
|
const psAssetValue = (_originTokenInfo$meta4 = originTokenInfo.metadata) === null || _originTokenInfo$meta4 === void 0 ? void 0 : _originTokenInfo$meta4.paraSpellValue;
|
|
122
119
|
if (!psAssetType || !psAssetValue) {
|
|
123
|
-
throw new Error('Token is not support XCM at this time');
|
|
120
|
+
throw new Error('Token is not support XCM at this time');
|
|
124
121
|
}
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
122
|
+
const bodyData = {
|
|
123
|
+
senderAddress: sender,
|
|
124
|
+
address: recipient,
|
|
125
|
+
from: paraSpellChainMap[originChain.slug],
|
|
126
|
+
to: paraSpellChainMap[destinationChain.slug],
|
|
127
|
+
currency: createParaSpellCurrency(psAssetType, psAssetValue, sendingValue)
|
|
128
|
+
};
|
|
129
|
+
const response = await fetch(paraSpellApi.dryRunXcm, {
|
|
130
|
+
method: 'POST',
|
|
131
|
+
body: JSON.stringify(bodyData),
|
|
132
|
+
headers: {
|
|
133
|
+
'Content-Type': 'application/json',
|
|
134
|
+
Accept: 'application/json',
|
|
135
|
+
'X-API-KEY': paraSpellKey
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
if (!response.ok) {
|
|
139
|
+
const error = await response.json();
|
|
140
|
+
return {
|
|
141
|
+
origin: {
|
|
142
|
+
success: false,
|
|
143
|
+
failureReason: error.message
|
|
142
144
|
}
|
|
143
|
-
}
|
|
144
|
-
dryRunInfo = await response.json();
|
|
145
|
-
} catch (e) {
|
|
146
|
-
console.error('Unable to dry run', e);
|
|
147
|
-
}
|
|
148
|
-
if (!dryRunInfo || !dryRunInfo.success) {
|
|
149
|
-
throw new TransactionError(BasicTxErrorType.UNABLE_TO_SEND, 'Unable to perform transaction. Select another token or destination chain and try again');
|
|
145
|
+
};
|
|
150
146
|
}
|
|
151
|
-
return
|
|
147
|
+
return await response.json();
|
|
152
148
|
}
|
|
153
|
-
export async function
|
|
154
|
-
var
|
|
149
|
+
export async function estimateXcmFee(request) {
|
|
150
|
+
var _fromTokenInfo$metada, _fromTokenInfo$metada2;
|
|
155
151
|
const {
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
originTokenInfo,
|
|
152
|
+
fromChainInfo,
|
|
153
|
+
fromTokenInfo,
|
|
159
154
|
recipient,
|
|
160
155
|
sender,
|
|
161
|
-
|
|
156
|
+
toChainInfo,
|
|
157
|
+
value
|
|
162
158
|
} = request;
|
|
163
159
|
const paraSpellChainMap = await fetchParaSpellChainMap();
|
|
164
|
-
const psAssetType = (
|
|
165
|
-
const psAssetValue = (
|
|
160
|
+
const psAssetType = (_fromTokenInfo$metada = fromTokenInfo.metadata) === null || _fromTokenInfo$metada === void 0 ? void 0 : _fromTokenInfo$metada.paraSpellAssetType;
|
|
161
|
+
const psAssetValue = (_fromTokenInfo$metada2 = fromTokenInfo.metadata) === null || _fromTokenInfo$metada2 === void 0 ? void 0 : _fromTokenInfo$metada2.paraSpellValue;
|
|
166
162
|
if (!psAssetType || !psAssetValue) {
|
|
167
|
-
|
|
163
|
+
console.error('Lack of paraspell metadata');
|
|
164
|
+
return undefined;
|
|
168
165
|
}
|
|
169
166
|
const bodyData = {
|
|
170
167
|
senderAddress: sender,
|
|
171
168
|
address: recipient,
|
|
172
|
-
from: paraSpellChainMap[
|
|
173
|
-
to: paraSpellChainMap[
|
|
174
|
-
currency: createParaSpellCurrency(psAssetType, psAssetValue,
|
|
169
|
+
from: paraSpellChainMap[fromChainInfo.slug],
|
|
170
|
+
to: paraSpellChainMap[toChainInfo.slug],
|
|
171
|
+
currency: createParaSpellCurrency(psAssetType, psAssetValue, value)
|
|
175
172
|
};
|
|
176
|
-
const response = await fetch(paraSpellApi.
|
|
173
|
+
const response = await fetch(paraSpellApi.feeXcm, {
|
|
177
174
|
method: 'POST',
|
|
178
175
|
body: JSON.stringify(bodyData),
|
|
179
176
|
headers: {
|
|
@@ -183,13 +180,14 @@ export async function dryRunXcmV2(request) {
|
|
|
183
180
|
}
|
|
184
181
|
});
|
|
185
182
|
if (!response.ok) {
|
|
186
|
-
|
|
187
|
-
|
|
183
|
+
console.error('Failed to request estimate fee');
|
|
184
|
+
return undefined;
|
|
188
185
|
}
|
|
189
186
|
return await response.json();
|
|
190
187
|
}
|
|
191
188
|
function createParaSpellCurrency(assetType, assetValue, amount) {
|
|
192
189
|
// todo: handle complex conditions for asset has same symbol in a chain: Id, Multi-location, ...
|
|
190
|
+
// todo: or update all asset to use multi-location
|
|
193
191
|
return {
|
|
194
192
|
[assetType]: assetValue,
|
|
195
193
|
amount
|
|
@@ -29,7 +29,7 @@ export const _BALANCE_CHAIN_GROUP = {
|
|
|
29
29
|
kintsugi: ['kintsugi', 'interlay', 'kintsugi_test', 'mangatax_para'],
|
|
30
30
|
genshiro: ['genshiro_testnet', 'genshiro'],
|
|
31
31
|
equilibrium_parachain: ['equilibrium_parachain'],
|
|
32
|
-
bifrost: ['bifrost', 'acala', 'karura', 'acala_testnet', 'pioneer', 'bitcountry', 'bifrost_dot', 'hydradx_main', 'hydradx_rococo', 'pendulum', 'amplitude', 'continuum_network', 'truth_network'],
|
|
32
|
+
bifrost: ['bifrost', 'acala', 'karura', 'acala_testnet', 'pioneer', 'bitcountry', 'bifrost_dot', 'hydradx_main', 'hydradx_rococo', 'pendulum', 'amplitude', 'continuum_network', 'truth_network', 'jamton'],
|
|
33
33
|
statemine: ['statemine', 'astar', 'shiden', 'statemint', 'moonbeam', 'moonbase', 'moonriver', 'crabParachain', 'darwinia2', 'parallel', 'calamari', 'manta_network', 'rococo_assethub', 'liberlandTest', 'liberland', 'dentnet', 'pangolin', 'crust', 'phala', 'shibuya', 'dbcchain', 'westend_assethub'],
|
|
34
34
|
kusama: ['kusama', 'kintsugi', 'kintsugi_test', 'interlay', 'acala', 'statemint', 'karura', 'bifrost'],
|
|
35
35
|
// perhaps there are some runtime updates
|
|
@@ -258,7 +258,7 @@ export const _TRANSFER_CHAIN_GROUP = {
|
|
|
258
258
|
riochain: ['riochain'],
|
|
259
259
|
sora_substrate: ['sora_substrate'],
|
|
260
260
|
avail: ['kate', 'goldberg_testnet'],
|
|
261
|
-
pendulum: ['pendulum', 'amplitude', 'amplitude_test', 'hydradx_main', 'bifrost', 'bifrost_dot'],
|
|
261
|
+
pendulum: ['pendulum', 'amplitude', 'amplitude_test', 'hydradx_main', 'bifrost', 'bifrost_dot', 'jamton'],
|
|
262
262
|
centrifuge: ['centrifuge'],
|
|
263
263
|
disable_transfer: ['crab', 'pangolin']
|
|
264
264
|
};
|
|
@@ -1233,6 +1233,10 @@ export class ChainService {
|
|
|
1233
1233
|
deprecated = true;
|
|
1234
1234
|
break;
|
|
1235
1235
|
}
|
|
1236
|
+
if (defaultChainAsset.slug === storedAssetInfo.slug) {
|
|
1237
|
+
duplicated = true;
|
|
1238
|
+
break;
|
|
1239
|
+
}
|
|
1236
1240
|
}
|
|
1237
1241
|
if (!duplicated && !deprecated) {
|
|
1238
1242
|
mergedAssetRegistry[storedAssetInfo.slug] = storedAssetInfo;
|
|
@@ -5,7 +5,7 @@ const PRODUCTION_BRANCHES = ['master', 'webapp', 'webapp-dev'];
|
|
|
5
5
|
const branchName = process.env.BRANCH_NAME || 'subwallet-dev';
|
|
6
6
|
const fetchDomain = PRODUCTION_BRANCHES.indexOf(branchName) > -1 ? 'https://chain-list-assets.subwallet.app' : 'https://dev.sw-chain-list-assets.pages.dev';
|
|
7
7
|
const fetchFile = PRODUCTION_BRANCHES.indexOf(branchName) > -1 ? 'list.json' : 'preview.json';
|
|
8
|
-
const ChainListVersion = '0.2.
|
|
8
|
+
const ChainListVersion = '0.2.105'; // update this when build chainlist
|
|
9
9
|
|
|
10
10
|
// todo: move this interface to chainlist
|
|
11
11
|
|
|
@@ -5,7 +5,8 @@ import { TransactionError } from '@subwallet/extension-base/background/errors/Tr
|
|
|
5
5
|
import { ChainType, ExtrinsicType } from '@subwallet/extension-base/background/KoniTypes';
|
|
6
6
|
import { ALL_ACCOUNT_KEY, XCM_FEE_RATIO, XCM_MIN_AMOUNT_RATIO } from '@subwallet/extension-base/constants';
|
|
7
7
|
import { YIELD_POOL_STAT_REFRESH_INTERVAL } from '@subwallet/extension-base/koni/api/yield/helper/utils';
|
|
8
|
-
import { createXcmExtrinsicV2
|
|
8
|
+
import { createXcmExtrinsicV2 } from '@subwallet/extension-base/services/balance-service/transfer/xcm';
|
|
9
|
+
import { estimateXcmFee } from '@subwallet/extension-base/services/balance-service/transfer/xcm/utils';
|
|
9
10
|
import { _getAssetDecimals, _getAssetExistentialDeposit, _getAssetName, _getAssetSymbol, _getChainNativeTokenSlug, _isNativeToken } from '@subwallet/extension-base/services/chain-service/utils';
|
|
10
11
|
import { BasicTxErrorType, YieldStepType, YieldValidationStatus } from '@subwallet/extension-base/types';
|
|
11
12
|
import { createPromiseHandler, formatNumber } from '@subwallet/extension-base/utils';
|
|
@@ -217,29 +218,20 @@ export default class BaseSpecialStakingPoolHandler extends BasePoolHandler {
|
|
|
217
218
|
const altChainInfo = this.state.getChainInfo(altInputTokenInfo.originChain);
|
|
218
219
|
const symbol = altInputTokenInfo.symbol;
|
|
219
220
|
const networkName = altChainInfo.name;
|
|
220
|
-
const xcmOriginSubstrateApi = await this.state.getSubstrateApi(altInputTokenInfo.originChain).isReady;
|
|
221
|
-
const id = getId();
|
|
222
|
-
const feeInfo = await this.state.feeService.subscribeChainFee(id, altChainInfo.slug, 'substrate');
|
|
223
|
-
const xcmRequest = {
|
|
224
|
-
sender: address,
|
|
225
|
-
originTokenInfo: altInputTokenInfo,
|
|
226
|
-
destinationTokenInfo: inputTokenInfo,
|
|
227
|
-
sendingValue: bnAmount.toString(),
|
|
228
|
-
recipient: address,
|
|
229
|
-
destinationChain: this.chainInfo,
|
|
230
|
-
originChain: altChainInfo,
|
|
231
|
-
substrateApi: xcmOriginSubstrateApi,
|
|
232
|
-
feeInfo
|
|
233
|
-
};
|
|
234
221
|
|
|
235
222
|
// TODO: calculate fee for destination chain
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
223
|
+
const xcmFeeInfo = await estimateXcmFee({
|
|
224
|
+
fromChainInfo: altChainInfo,
|
|
225
|
+
fromTokenInfo: altInputTokenInfo,
|
|
226
|
+
toChainInfo: this.chainInfo,
|
|
227
|
+
recipient: address,
|
|
228
|
+
sender: address,
|
|
229
|
+
value: bnAmount.toString()
|
|
230
|
+
});
|
|
231
|
+
if (!xcmFeeInfo) {
|
|
241
232
|
throw new Error('Error estimating XCM fee');
|
|
242
233
|
}
|
|
234
|
+
const xcmFee = BigN(xcmFeeInfo.origin.fee).multipliedBy(XCM_MIN_AMOUNT_RATIO).toFixed(0, 1);
|
|
243
235
|
const fee = {
|
|
244
236
|
slug: altInputTokenSlug,
|
|
245
237
|
amount: xcmFee
|
|
@@ -7,8 +7,9 @@ import { validateSpendingAndFeePayment } from '@subwallet/extension-base/core/lo
|
|
|
7
7
|
import { _isAccountActive } from '@subwallet/extension-base/core/substrate/system-pallet';
|
|
8
8
|
import { _isAcrossBridgeXcm, _isSnowBridgeXcm, _isXcmWithinSameConsensus } from '@subwallet/extension-base/core/substrate/xcm-parser';
|
|
9
9
|
import { _isSufficientToken } from '@subwallet/extension-base/core/utils';
|
|
10
|
-
import { createXcmExtrinsicV2
|
|
10
|
+
import { createXcmExtrinsicV2 } from '@subwallet/extension-base/services/balance-service/transfer/xcm';
|
|
11
11
|
import { _isAcrossChainBridge, AcrossErrorMsg } from '@subwallet/extension-base/services/balance-service/transfer/xcm/acrossBridge';
|
|
12
|
+
import { estimateXcmFee } from '@subwallet/extension-base/services/balance-service/transfer/xcm/utils';
|
|
12
13
|
import { _getAssetDecimals, _getAssetOriginChain, _getAssetSymbol, _getChainNativeTokenSlug, _getTokenMinAmount, _isChainEvmCompatible, _isNativeToken } from '@subwallet/extension-base/services/chain-service/utils';
|
|
13
14
|
import { DEFAULT_EXCESS_AMOUNT_WEIGHT, FEE_RATE_MULTIPLIER } from '@subwallet/extension-base/services/swap-service/utils';
|
|
14
15
|
import { BasicTxErrorType, SwapStepType, TransferTxErrorType } from '@subwallet/extension-base/types';
|
|
@@ -121,11 +122,15 @@ export class SwapBaseHandler {
|
|
|
121
122
|
};
|
|
122
123
|
|
|
123
124
|
// TODO: calculate fee for destination chain
|
|
124
|
-
const
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
125
|
+
const xcmFeeInfo = await estimateXcmFee({
|
|
126
|
+
fromChainInfo: xcmRequest.originChain,
|
|
127
|
+
fromTokenInfo: xcmRequest.originTokenInfo,
|
|
128
|
+
toChainInfo: xcmRequest.destinationChain,
|
|
129
|
+
recipient: xcmRequest.recipient,
|
|
130
|
+
sender: xcmRequest.sender,
|
|
131
|
+
value: xcmRequest.sendingValue
|
|
132
|
+
});
|
|
133
|
+
const estimatedBridgeFee = BigN((xcmFeeInfo === null || xcmFeeInfo === void 0 ? void 0 : xcmFeeInfo.origin.fee) || '0').multipliedBy(FEE_RATE_MULTIPLIER.medium).toFixed(0, 1);
|
|
129
134
|
const fee = {
|
|
130
135
|
feeComponent: [{
|
|
131
136
|
feeType: SwapFeeType.NETWORK_FEE,
|
|
@@ -14,44 +14,59 @@ import { calculateGasFeeParams } from "../../fee-service/utils/index.js";
|
|
|
14
14
|
import { SwapBaseHandler } from "./base-handler.js";
|
|
15
15
|
export const KYBER_CLIENT_ID = process.env.KYBER_CLIENT_ID || '';
|
|
16
16
|
const kyberUrl = 'https://aggregator-api.kyberswap.com';
|
|
17
|
-
async function
|
|
17
|
+
async function buildTxForKyberSwap(params, chain) {
|
|
18
18
|
const {
|
|
19
19
|
recipient,
|
|
20
20
|
sender,
|
|
21
21
|
slippageTolerance
|
|
22
22
|
} = params;
|
|
23
23
|
let routeSummary = params.routeSummary;
|
|
24
|
+
console.log('routeSummary1', routeSummary);
|
|
24
25
|
if (!routeSummary || !routeSummary.tokenIn || !routeSummary.tokenOut || !routeSummary.amountIn) {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
26
|
+
return {
|
|
27
|
+
error: new TransactionError(BasicTxErrorType.INTERNAL_ERROR, 'Invalid Route Summary')
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
const {
|
|
31
|
+
amountIn,
|
|
32
|
+
tokenIn,
|
|
33
|
+
tokenOut
|
|
34
|
+
} = routeSummary;
|
|
35
|
+
const queryParams = new URLSearchParams({
|
|
36
|
+
tokenIn,
|
|
37
|
+
tokenOut,
|
|
38
|
+
amountIn,
|
|
39
|
+
gasInclude: 'true'
|
|
40
|
+
});
|
|
41
|
+
const url = `${kyberUrl}/${chain}/api/v1/routes?${queryParams.toString()}`;
|
|
42
|
+
try {
|
|
43
|
+
var _routeData$data;
|
|
44
|
+
const res = await fetch(url, {
|
|
45
|
+
method: 'GET',
|
|
46
|
+
headers: {
|
|
47
|
+
'Content-Type': 'application/json',
|
|
48
|
+
'x-client-id': KYBER_CLIENT_ID,
|
|
49
|
+
accept: 'application/json'
|
|
47
50
|
}
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
+
});
|
|
52
|
+
if (!res.ok) {
|
|
53
|
+
const errorText = await res.text();
|
|
54
|
+
return {
|
|
55
|
+
error: new TransactionError(BasicTxErrorType.INTERNAL_ERROR, `Fetch Kyber routes failed: ${errorText}`)
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
const routeData = await res.json();
|
|
59
|
+
if (!((_routeData$data = routeData.data) !== null && _routeData$data !== void 0 && _routeData$data.routeSummary)) {
|
|
51
60
|
return {
|
|
52
|
-
error: new TransactionError(BasicTxErrorType.INTERNAL_ERROR)
|
|
61
|
+
error: new TransactionError(BasicTxErrorType.INTERNAL_ERROR, routeData.message)
|
|
53
62
|
};
|
|
54
63
|
}
|
|
64
|
+
routeSummary = routeData.data.routeSummary;
|
|
65
|
+
} catch (error) {
|
|
66
|
+
console.error('Error:', error);
|
|
67
|
+
return {
|
|
68
|
+
error: new TransactionError(BasicTxErrorType.INTERNAL_ERROR, 'Unable to build Kyber swap transaction')
|
|
69
|
+
};
|
|
55
70
|
}
|
|
56
71
|
const body = {
|
|
57
72
|
routeSummary,
|
|
@@ -61,6 +76,7 @@ async function buildTxForSwap(params, chain) {
|
|
|
61
76
|
ignoreCappedSlippage: true,
|
|
62
77
|
enableGasEstimation: true
|
|
63
78
|
};
|
|
79
|
+
console.log('routeSummary2', routeSummary);
|
|
64
80
|
try {
|
|
65
81
|
const res = await fetch(`${kyberUrl}/${chain}/api/v1/route/build`, {
|
|
66
82
|
method: 'POST',
|
|
@@ -272,7 +288,7 @@ export class KyberHandler {
|
|
|
272
288
|
const recipient = _reformatAddressWithChain((_params$recipient = params.recipient) !== null && _params$recipient !== void 0 ? _params$recipient : sender, toChainInfo);
|
|
273
289
|
const metadata = params.quote.metadata;
|
|
274
290
|
const slippageTolerance = params.slippage * 10000;
|
|
275
|
-
const rawTx = await
|
|
291
|
+
const rawTx = await buildTxForKyberSwap({
|
|
276
292
|
routeSummary: metadata.routeSummary,
|
|
277
293
|
sender: params.address,
|
|
278
294
|
recipient,
|