@subwallet/extension-base 1.1.54-0 → 1.1.56-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.
Files changed (112) hide show
  1. package/background/KoniTypes.d.ts +30 -2
  2. package/background/KoniTypes.js +6 -0
  3. package/background/errors/SwapError.d.ts +6 -0
  4. package/background/errors/SwapError.js +57 -0
  5. package/background/errors/TransactionError.js +9 -0
  6. package/background/types.d.ts +2 -0
  7. package/cjs/background/KoniTypes.js +8 -1
  8. package/cjs/background/errors/SwapError.js +64 -0
  9. package/cjs/background/errors/TransactionError.js +9 -0
  10. package/cjs/koni/api/nft/{statemint_nft → assethub_nft}/index.js +5 -3
  11. package/cjs/koni/api/nft/{statemine_nft → assethub_unique}/index.js +5 -3
  12. package/cjs/koni/api/nft/index.js +13 -13
  13. package/cjs/koni/api/nft/nft.js +1 -1
  14. package/cjs/koni/api/nft/transfer.js +11 -15
  15. package/cjs/koni/api/staking/bonding/utils.js +35 -6
  16. package/cjs/koni/background/handlers/Extension.js +214 -102
  17. package/cjs/koni/background/handlers/State.js +5 -2
  18. package/cjs/packageInfo.js +1 -1
  19. package/cjs/services/balance-service/index.js +6 -3
  20. package/cjs/services/chain-service/constants.js +18 -4
  21. package/cjs/services/chain-service/index.js +39 -18
  22. package/cjs/services/chain-service/utils/index.js +15 -4
  23. package/cjs/services/chain-service/utils/patch.js +1 -1
  24. package/cjs/services/earning-service/constants/chains.js +4 -2
  25. package/cjs/services/earning-service/handlers/native-staking/amplitude.js +7 -9
  26. package/cjs/services/earning-service/handlers/native-staking/astar.js +4 -3
  27. package/cjs/services/earning-service/handlers/native-staking/para-chain.js +11 -8
  28. package/cjs/services/earning-service/handlers/native-staking/relay-chain.js +22 -3
  29. package/cjs/services/earning-service/handlers/nomination-pool/index.js +19 -5
  30. package/cjs/services/earning-service/service.js +0 -1
  31. package/cjs/services/migration-service/scripts/MigrateTransactionHistoryBySymbol.js +4 -17
  32. package/cjs/services/migration-service/scripts/databases/MigrateAssetSetting.js +4 -17
  33. package/cjs/services/migration-service/scripts/index.js +3 -3
  34. package/cjs/services/swap-service/handler/base-handler.js +189 -0
  35. package/cjs/services/swap-service/handler/chainflip-handler.js +407 -0
  36. package/cjs/services/swap-service/handler/hydradx-handler.js +531 -0
  37. package/cjs/services/swap-service/index.js +250 -0
  38. package/cjs/services/swap-service/utils.js +126 -0
  39. package/cjs/services/transaction-service/index.js +20 -0
  40. package/cjs/services/transaction-service/utils.js +6 -0
  41. package/cjs/types/fee/evm.js +1 -0
  42. package/cjs/types/fee/fee.js +70 -0
  43. package/cjs/types/fee/index.js +27 -1
  44. package/cjs/types/service-base.js +1 -0
  45. package/cjs/types/swap/index.js +50 -0
  46. package/cjs/utils/index.js +12 -0
  47. package/cjs/utils/swap.js +78 -0
  48. package/koni/api/nft/{statemint_nft → assethub_nft}/index.d.ts +1 -1
  49. package/koni/api/nft/{statemint_nft → assethub_nft}/index.js +4 -2
  50. package/koni/api/nft/{statemine_nft → assethub_unique}/index.d.ts +1 -1
  51. package/koni/api/nft/{statemine_nft → assethub_unique}/index.js +4 -2
  52. package/koni/api/nft/index.js +13 -13
  53. package/koni/api/nft/nft.js +1 -1
  54. package/koni/api/nft/transfer.d.ts +1 -2
  55. package/koni/api/nft/transfer.js +10 -13
  56. package/koni/api/staking/bonding/utils.d.ts +3 -1
  57. package/koni/api/staking/bonding/utils.js +32 -6
  58. package/koni/background/handlers/Extension.d.ts +6 -0
  59. package/koni/background/handlers/Extension.js +111 -0
  60. package/koni/background/handlers/State.d.ts +2 -0
  61. package/koni/background/handlers/State.js +5 -2
  62. package/package.json +85 -28
  63. package/packageInfo.js +1 -1
  64. package/services/balance-service/index.js +6 -3
  65. package/services/base/types.d.ts +4 -0
  66. package/services/chain-service/constants.js +18 -4
  67. package/services/chain-service/index.d.ts +4 -0
  68. package/services/chain-service/index.js +21 -1
  69. package/services/chain-service/utils/index.d.ts +7 -5
  70. package/services/chain-service/utils/index.js +9 -2
  71. package/services/chain-service/utils/patch.js +1 -1
  72. package/services/earning-service/constants/chains.d.ts +1 -0
  73. package/services/earning-service/constants/chains.js +1 -0
  74. package/services/earning-service/handlers/native-staking/amplitude.js +7 -9
  75. package/services/earning-service/handlers/native-staking/astar.js +4 -3
  76. package/services/earning-service/handlers/native-staking/para-chain.js +12 -9
  77. package/services/earning-service/handlers/native-staking/relay-chain.js +24 -5
  78. package/services/earning-service/handlers/nomination-pool/index.js +19 -5
  79. package/services/earning-service/service.js +0 -1
  80. package/services/event-service/types.d.ts +1 -0
  81. package/services/migration-service/scripts/MigrateTransactionHistoryBySymbol.js +4 -17
  82. package/services/migration-service/scripts/databases/MigrateAssetSetting.js +4 -17
  83. package/services/migration-service/scripts/index.js +3 -3
  84. package/services/swap-service/handler/base-handler.d.ts +38 -0
  85. package/services/swap-service/handler/base-handler.js +180 -0
  86. package/services/swap-service/handler/chainflip-handler.d.ts +30 -0
  87. package/services/swap-service/handler/chainflip-handler.js +399 -0
  88. package/services/swap-service/handler/hydradx-handler.d.ts +36 -0
  89. package/services/swap-service/handler/hydradx-handler.js +522 -0
  90. package/services/swap-service/index.d.ts +32 -0
  91. package/services/swap-service/index.js +241 -0
  92. package/services/swap-service/utils.d.ts +18 -0
  93. package/services/swap-service/utils.js +105 -0
  94. package/services/transaction-service/index.js +20 -0
  95. package/services/transaction-service/utils.d.ts +2 -0
  96. package/services/transaction-service/utils.js +6 -2
  97. package/types/fee/evm.d.ts +49 -0
  98. package/types/fee/evm.js +1 -0
  99. package/types/fee/fee.d.ts +32 -0
  100. package/types/fee/fee.js +63 -0
  101. package/types/fee/index.d.ts +2 -49
  102. package/types/fee/index.js +5 -1
  103. package/types/service-base.d.ts +10 -0
  104. package/types/service-base.js +1 -0
  105. package/types/swap/index.d.ts +168 -0
  106. package/types/swap/index.js +41 -0
  107. package/types/yield/info/chain/target.d.ts +2 -0
  108. package/types/yield/info/pallet.d.ts +8 -0
  109. package/utils/index.d.ts +1 -0
  110. package/utils/index.js +2 -1
  111. package/utils/swap.d.ts +3 -0
  112. package/utils/swap.js +70 -0
@@ -3,10 +3,10 @@
3
3
 
4
4
  import { TransactionError } from '@subwallet/extension-base/background/errors/TransactionError';
5
5
  import { BasicTxErrorType, ExtrinsicType, StakingTxErrorType } from '@subwallet/extension-base/background/KoniTypes';
6
- import { calculateAlephZeroValidatorReturn, calculateChainStakedReturnV2, calculateInflation, calculateTernoaValidatorReturn, calculateValidatorStakedReturn, getAvgValidatorEraReward, getCommission, getMaxValidatorErrorMessage, getMinStakeErrorMessage, getSupportedDaysByHistoryDepth } from '@subwallet/extension-base/koni/api/staking/bonding/utils';
6
+ import { calculateAlephZeroValidatorReturn, calculateChainStakedReturnV2, calculateInflation, calculateTernoaValidatorReturn, calculateValidatorStakedReturn, getAvgValidatorEraReward, getCommission, getMaxValidatorErrorMessage, getMinStakeErrorMessage, getSupportedDaysByHistoryDepth, getTopValidatorByPoints, getValidatorPointsMap } from '@subwallet/extension-base/koni/api/staking/bonding/utils';
7
7
  import { _STAKING_ERA_LENGTH_MAP } from '@subwallet/extension-base/services/chain-service/constants';
8
8
  import { _getChainSubstrateAddressPrefix } from '@subwallet/extension-base/services/chain-service/utils';
9
- import { _STAKING_CHAIN_GROUP } from '@subwallet/extension-base/services/earning-service/constants';
9
+ import { _STAKING_CHAIN_GROUP, MaxEraRewardPointsEras } from '@subwallet/extension-base/services/earning-service/constants';
10
10
  import { parseIdentity } from '@subwallet/extension-base/services/earning-service/utils';
11
11
  import { EarningStatus, UnstakingStatus } from '@subwallet/extension-base/types';
12
12
  import { balanceFormatter, formatNumber, reformatAddress } from '@subwallet/extension-base/utils';
@@ -274,11 +274,23 @@ export default class RelayNativeStakingPoolHandler extends BaseNativeStakingPool
274
274
  if (!poolInfo || !poolInfo.statistic) {
275
275
  return Promise.reject(new TransactionError(BasicTxErrorType.INTERNAL_ERROR));
276
276
  }
277
- const _era = await chainApi.api.query.staking.currentEra();
277
+ const [_era, _activeEraInfo] = await Promise.all([chainApi.api.query.staking.currentEra(), chainApi.api.query.staking.activeEra()]);
278
278
  const currentEra = _era.toString();
279
+ const activeEraInfo = _activeEraInfo.toPrimitive();
280
+ const activeEra = activeEraInfo.index;
279
281
  const allValidators = [];
280
282
  const validatorInfoList = [];
281
- const [_totalEraStake, _eraStakers, _minBond, _stakingRewards, _validators] = await Promise.all([chainApi.api.query.staking.erasTotalStake(parseInt(currentEra)), chainApi.api.query.staking.erasStakers.entries(parseInt(currentEra)), chainApi.api.query.staking.minNominatorBond(), ((_chainApi$api$query$s = chainApi.api.query.stakingRewards) === null || _chainApi$api$query$s === void 0 ? void 0 : _chainApi$api$query$s.data) && chainApi.api.query.stakingRewards.data(), chainApi.api.query.staking.validators.entries()]);
283
+ const maxEraRewardPointsEras = MaxEraRewardPointsEras;
284
+ const endEraForPoints = parseInt(activeEra) - 1;
285
+ let startEraForPoints = endEraForPoints - maxEraRewardPointsEras + 1;
286
+ const [_totalEraStake, _eraStakers, _minBond, _stakingRewards, _validators, ..._eraRewardPoints] = await Promise.all([chainApi.api.query.staking.erasTotalStake(parseInt(currentEra)), chainApi.api.query.staking.erasStakers.entries(parseInt(currentEra)), chainApi.api.query.staking.minNominatorBond(), ((_chainApi$api$query$s = chainApi.api.query.stakingRewards) === null || _chainApi$api$query$s === void 0 ? void 0 : _chainApi$api$query$s.data) && chainApi.api.query.stakingRewards.data(), chainApi.api.query.staking.validators.entries(), chainApi.api.query.staking.erasRewardPoints.multi([...Array(maxEraRewardPointsEras).keys()].map(i => i + startEraForPoints))]);
287
+ const eraRewardMap = {};
288
+ for (const item of _eraRewardPoints[0]) {
289
+ eraRewardMap[startEraForPoints] = item.toHuman();
290
+ startEraForPoints++;
291
+ }
292
+ const validatorPointsMap = getValidatorPointsMap(eraRewardMap);
293
+ const topValidatorList = getTopValidatorByPoints(validatorPointsMap);
282
294
 
283
295
  // filter blocked validators
284
296
  const validators = _validators;
@@ -309,6 +321,11 @@ export default class RelayNativeStakingPoolHandler extends BaseNativeStakingPool
309
321
  const rawValidatorStat = item[1].toHuman();
310
322
  const validatorAddress = rawValidatorInfo[1];
311
323
  if (!blockValidatorList.includes(validatorAddress)) {
324
+ var _validatorPointsMap$v;
325
+ let isTopQuartile = false;
326
+ if (topValidatorList.includes(validatorAddress)) {
327
+ isTopQuartile = true;
328
+ }
312
329
  const rawTotalStake = rawValidatorStat.total;
313
330
  const rawOwnStake = rawValidatorStat.own;
314
331
  const bnTotalStake = new BN(rawTotalStake.replaceAll(',', ''));
@@ -333,7 +350,9 @@ export default class RelayNativeStakingPoolHandler extends BaseNativeStakingPool
333
350
  blocked: false,
334
351
  isVerified: false,
335
352
  minBond,
336
- isCrowded: unlimitedNominatorRewarded ? false : nominatorCount > parseInt(maxNominatorRewarded)
353
+ isCrowded: unlimitedNominatorRewarded ? false : nominatorCount > parseInt(maxNominatorRewarded),
354
+ eraRewardPoint: ((_validatorPointsMap$v = validatorPointsMap[validatorAddress]) !== null && _validatorPointsMap$v !== void 0 ? _validatorPointsMap$v : BN_ZERO).toString(),
355
+ topQuartile: isTopQuartile
337
356
  });
338
357
  }
339
358
  }
@@ -158,11 +158,25 @@ export default class NominationPoolHandler extends BasePoolHandler {
158
158
  if (nominations) {
159
159
  const validatorList = nominations.targets;
160
160
  await Promise.all(validatorList.map(async validatorAddress => {
161
- const _eraStaker = await substrateApi.api.query.staking.erasStakers(currentEra, validatorAddress);
162
- const eraStaker = _eraStaker.toPrimitive();
163
- const sortedNominators = eraStaker.others.sort((a, b) => {
164
- return new BigN(b.value).minus(a.value).toNumber();
165
- });
161
+ let sortedNominators = [];
162
+ if (['kusama'].includes(this.chain)) {
163
+ // todo: hot fix for kusama first, we'll review all relaychains later
164
+ const _eraStaker = await substrateApi.api.query.staking.erasStakersPaged.entries(currentEra, validatorAddress);
165
+ const eraStakerOtherList = [];
166
+ _eraStaker.forEach(paged => {
167
+ const pagedExposure = paged[1].toPrimitive();
168
+ eraStakerOtherList.push(...pagedExposure.others);
169
+ });
170
+ sortedNominators = eraStakerOtherList.sort((a, b) => {
171
+ return new BigN(b.value).minus(a.value).toNumber();
172
+ });
173
+ } else {
174
+ const _eraStaker = await substrateApi.api.query.staking.erasStakers(currentEra, validatorAddress);
175
+ const eraStaker = _eraStaker.toPrimitive();
176
+ sortedNominators = eraStaker.others.sort((a, b) => {
177
+ return new BigN(b.value).minus(a.value).toNumber();
178
+ });
179
+ }
166
180
  const topNominators = sortedNominators.map(nominator => {
167
181
  return nominator.who;
168
182
  }).slice(0, unlimitedNominatorRewarded ? undefined : maxNominatorRewardedPerValidator);
@@ -396,7 +396,6 @@ export default class EarningService {
396
396
  async removeYieldPositions(chains, addresses) {
397
397
  const removeKeys = [];
398
398
  chains && chains.length > 0 && Object.entries(this.yieldPositionSubject.getValue()).forEach(([key, value]) => {
399
- console.log('removeYieldPositions', key, value.chain, chains.indexOf(value.chain) > -1);
400
399
  if (chains.indexOf(value.chain) > -1 && !removeKeys.includes(key)) {
401
400
  removeKeys.push(key);
402
401
  }
@@ -38,6 +38,7 @@ export interface EventRegistry {
38
38
  'buy.tokens.ready': [boolean];
39
39
  'buy.services.ready': [boolean];
40
40
  'earning.ready': [boolean];
41
+ 'swap.ready': [boolean];
41
42
  }
42
43
  export declare type EventType = keyof EventRegistry;
43
44
  export declare const COMMON_RELOAD_EVENTS: EventType[];
@@ -7,23 +7,10 @@ export default class MigrateTransactionHistoryBySymbol extends BaseMigrationJob
7
7
  const state = this.state;
8
8
  try {
9
9
  const changeSlugsMap = {
10
- 'ethereum-ERC20-WFTM-0x4E15361FD6b4BB609Fa63C81A2be19d873717870': 'ethereum-ERC20-FTM-0x4E15361FD6b4BB609Fa63C81A2be19d873717870',
11
- 'moonbeam-ERC20-CSG-0x2Dfc76901bB2ac2A5fA5fc479590A490BBB10a5F': 'moonbeam-ERC20-CGS-0x2Dfc76901bB2ac2A5fA5fc479590A490BBB10a5F',
12
- 'astar-LOCAL-aUSD': 'astar-LOCAL-aSEED',
13
- 'astarEvm-ERC20-aUSD-0xfFFFFfFF00000000000000010000000000000001': 'astarEvm-ERC20-aSEED-0xfFFFFfFF00000000000000010000000000000001',
14
- 'moonriver-LOCAL-xcaUSD': 'moonriver-LOCAL-xcaSeed',
15
- 'moonriver-LOCAL-xckBTC': 'moonriver-LOCAL-xcKBTC',
16
- 'bifrost-LOCAL-aUSD': 'bifrost-LOCAL-KUSD',
17
- 'calamari-LOCAL-aUSD': 'calamari-LOCAL-AUSD',
18
- 'shiden-LOCAL-aUSD': 'shiden-LOCAL-aSEED',
19
- 'shidenEvm-ERC20-aUSD-0xfFFfFFfF00000000000000010000000000000000': 'shidenEvm-ERC20-aSEED-0xfFFfFFfF00000000000000010000000000000000',
20
- 'ethereum_goerli-NATIVE-GoerliETH': 'ethereum_goerli-NATIVE-ETH',
21
- 'binance_test-NATIVE-BNB': 'binance_test-NATIVE-tBNB',
22
- 'pangolin-LOCAL-CKTON': 'pangolin-LOCAL-PKTON',
23
- 'zeta_test-NATIVE-aZETA': 'zeta_test-NATIVE-ZETA',
24
- 'origintrail-NATIVE-OTP': 'origintrail-NATIVE-NEURO',
25
- 'moonbeam-LOCAL-xciBTC': 'moonbeam-LOCAL-xcIBTC',
26
- 'tomochain-NATIVE-TOMO': 'tomochain-NATIVE-VIC'
10
+ 'moonbeam-LOCAL-xcaUSD': 'moonbeam-LOCAL-xcaSEED',
11
+ 'calamari-LOCAL-AUSD': 'calamari-LOCAL-aSEED',
12
+ 'moonriver-LOCAL-xcaSeed': 'moonriver-LOCAL-xcaSEED',
13
+ 'bifrost-LOCAL-KUSD': 'bifrost-LOCAL-aSEED'
27
14
  };
28
15
  const allTxs = [];
29
16
  await Promise.all(Object.entries(changeSlugsMap).map(async ([oldSlug, newSlug], i) => {
@@ -6,23 +6,10 @@ export default class MigrateAssetSetting extends BaseMigrationJob {
6
6
  async run() {
7
7
  try {
8
8
  const changeSlugsMap = {
9
- 'ethereum-ERC20-WFTM-0x4E15361FD6b4BB609Fa63C81A2be19d873717870': 'ethereum-ERC20-FTM-0x4E15361FD6b4BB609Fa63C81A2be19d873717870',
10
- 'moonbeam-ERC20-CSG-0x2Dfc76901bB2ac2A5fA5fc479590A490BBB10a5F': 'moonbeam-ERC20-CGS-0x2Dfc76901bB2ac2A5fA5fc479590A490BBB10a5F',
11
- 'astar-LOCAL-aUSD': 'astar-LOCAL-aSEED',
12
- 'astarEvm-ERC20-aUSD-0xfFFFFfFF00000000000000010000000000000001': 'astarEvm-ERC20-aSEED-0xfFFFFfFF00000000000000010000000000000001',
13
- 'moonriver-LOCAL-xcaUSD': 'moonriver-LOCAL-xcaSeed',
14
- 'moonriver-LOCAL-xckBTC': 'moonriver-LOCAL-xcKBTC',
15
- 'bifrost-LOCAL-aUSD': 'bifrost-LOCAL-KUSD',
16
- 'calamari-LOCAL-aUSD': 'calamari-LOCAL-AUSD',
17
- 'shiden-LOCAL-aUSD': 'shiden-LOCAL-aSEED',
18
- 'shidenEvm-ERC20-aUSD-0xfFFfFFfF00000000000000010000000000000000': 'shidenEvm-ERC20-aSEED-0xfFFfFFfF00000000000000010000000000000000',
19
- 'ethereum_goerli-NATIVE-GoerliETH': 'ethereum_goerli-NATIVE-ETH',
20
- 'binance_test-NATIVE-BNB': 'binance_test-NATIVE-tBNB',
21
- 'pangolin-LOCAL-CKTON': 'pangolin-LOCAL-PKTON',
22
- 'zeta_test-NATIVE-aZETA': 'zeta_test-NATIVE-ZETA',
23
- 'origintrail-NATIVE-OTP': 'origintrail-NATIVE-NEURO',
24
- 'moonbeam-LOCAL-xciBTC': 'moonbeam-LOCAL-xcIBTC',
25
- 'tomochain-NATIVE-TOMO': 'tomochain-NATIVE-VIC'
9
+ 'moonbeam-LOCAL-xcaUSD': 'moonbeam-LOCAL-xcaSEED',
10
+ 'calamari-LOCAL-AUSD': 'calamari-LOCAL-aSEED',
11
+ 'moonriver-LOCAL-xcaSeed': 'moonriver-LOCAL-xcaSEED',
12
+ 'bifrost-LOCAL-KUSD': 'bifrost-LOCAL-aSEED'
26
13
  };
27
14
  const assetSetting = await this.state.chainService.getAssetSettings();
28
15
  const migratedAssetSetting = {};
@@ -47,9 +47,9 @@ export default {
47
47
  '1.1.26-01': MigratePolygonUSDCProvider,
48
48
  '1.1.28-01': MigrateEarningVersion,
49
49
  '1.1.41-01': DeleteChainStaking,
50
- '1.1.44-01': MigrateAssetSetting,
51
- '1.1.45-01': MigrateTransactionHistoryBySymbol,
52
- '1.1.46-01': AutoEnableSomeTokens
50
+ '1.1.46-01': AutoEnableSomeTokens,
51
+ '1.1.53-01': MigrateAssetSetting,
52
+ '1.1.53-02': MigrateTransactionHistoryBySymbol
53
53
  // [`${EVERYTIME}-1.1.42-02`]: MigrateTransactionHistoryBySymbol
54
54
  // [`${EVERYTIME}-1`]: AutoEnableChainsTokens
55
55
  };
@@ -0,0 +1,38 @@
1
+ import { SwapError } from '@subwallet/extension-base/background/errors/SwapError';
2
+ import { TransactionError } from '@subwallet/extension-base/background/errors/TransactionError';
3
+ import { BalanceService } from '@subwallet/extension-base/services/balance-service';
4
+ import { ChainService } from '@subwallet/extension-base/services/chain-service';
5
+ import { BaseStepDetail } from '@subwallet/extension-base/types/service-base';
6
+ import { GenSwapStepFunc, OptimalSwapPath, OptimalSwapPathParams, SwapEarlyValidation, SwapFeeInfo, SwapProvider, SwapQuote, SwapRequest, SwapSubmitParams, SwapSubmitStepData, ValidateSwapProcessParams } from '@subwallet/extension-base/types/swap';
7
+ export interface SwapBaseInterface {
8
+ getSwapQuote: (request: SwapRequest) => Promise<SwapQuote | SwapError>;
9
+ generateOptimalProcess: (params: OptimalSwapPathParams) => Promise<OptimalSwapPath>;
10
+ getSubmitStep: (params: OptimalSwapPathParams) => Promise<[BaseStepDetail, SwapFeeInfo] | undefined>;
11
+ validateSwapRequest: (request: SwapRequest) => Promise<SwapEarlyValidation>;
12
+ validateSwapProcess: (params: ValidateSwapProcessParams) => Promise<TransactionError[]>;
13
+ handleSwapProcess: (params: SwapSubmitParams) => Promise<SwapSubmitStepData>;
14
+ handleSubmitStep: (params: SwapSubmitParams) => Promise<SwapSubmitStepData>;
15
+ isReady?: boolean;
16
+ init?: () => Promise<void>;
17
+ }
18
+ export interface SwapBaseHandlerInitParams {
19
+ providerSlug: string;
20
+ providerName: string;
21
+ chainService: ChainService;
22
+ balanceService: BalanceService;
23
+ }
24
+ export declare class SwapBaseHandler {
25
+ private readonly providerSlug;
26
+ private readonly providerName;
27
+ chainService: ChainService;
28
+ balanceService: BalanceService;
29
+ constructor({ balanceService, chainService, providerName, providerSlug }: SwapBaseHandlerInitParams);
30
+ generateOptimalProcess(params: OptimalSwapPathParams, genStepFuncList: GenSwapStepFunc[]): Promise<OptimalSwapPath>;
31
+ validateXcmStep(params: ValidateSwapProcessParams, stepIndex: number): Promise<TransactionError[]>;
32
+ validateTokenApproveStep(params: ValidateSwapProcessParams, stepIndex: number): Promise<TransactionError[]>;
33
+ validateSetFeeTokenStep(params: ValidateSwapProcessParams, stepIndex: number): Promise<TransactionError[]>;
34
+ validateSwapStep(params: ValidateSwapProcessParams, isXcmOk: boolean, stepIndex: number): Promise<TransactionError[]>;
35
+ get name(): string;
36
+ get slug(): string;
37
+ get providerInfo(): SwapProvider;
38
+ }
@@ -0,0 +1,180 @@
1
+ // Copyright 2019-2022 @subwallet/extension-base
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ import { TransactionError } from '@subwallet/extension-base/background/errors/TransactionError';
5
+ import { BasicTxErrorType } from '@subwallet/extension-base/background/KoniTypes';
6
+ import { _getAssetDecimals, _getTokenMinAmount, _isChainEvmCompatible, _isNativeToken } from '@subwallet/extension-base/services/chain-service/utils';
7
+ import { DEFAULT_SWAP_FIRST_STEP, getSwapAlternativeAsset, MOCK_SWAP_FEE } from '@subwallet/extension-base/services/swap-service/utils';
8
+ import { SwapErrorType, SwapFeeType } from '@subwallet/extension-base/types/swap';
9
+ import { formatNumber } from '@subwallet/extension-base/utils';
10
+ import BigNumber from 'bignumber.js';
11
+ import { t } from 'i18next';
12
+ import { isEthereumAddress } from '@polkadot/util-crypto';
13
+ export class SwapBaseHandler {
14
+ constructor({
15
+ balanceService,
16
+ chainService,
17
+ providerName,
18
+ providerSlug
19
+ }) {
20
+ this.providerName = providerName;
21
+ this.providerSlug = providerSlug;
22
+ this.chainService = chainService;
23
+ this.balanceService = balanceService;
24
+ }
25
+
26
+ // public abstract getSwapQuote(request: SwapRequest): Promise<SwapQuote | SwapError>;
27
+ async generateOptimalProcess(params, genStepFuncList) {
28
+ const result = {
29
+ totalFee: [MOCK_SWAP_FEE],
30
+ steps: [DEFAULT_SWAP_FIRST_STEP]
31
+ };
32
+ try {
33
+ for (const genStepFunc of genStepFuncList) {
34
+ const step = await genStepFunc.bind(this, params)();
35
+ if (step) {
36
+ result.steps.push({
37
+ id: result.steps.length,
38
+ ...step[0]
39
+ });
40
+ result.totalFee.push(step[1]);
41
+ }
42
+ }
43
+ return result;
44
+ } catch (e) {
45
+ return result;
46
+ }
47
+ }
48
+ async validateXcmStep(params, stepIndex) {
49
+ const bnAmount = new BigNumber(params.selectedQuote.fromAmount);
50
+ const swapPair = params.selectedQuote.pair;
51
+ const alternativeAssetSlug = getSwapAlternativeAsset(swapPair);
52
+ if (!alternativeAssetSlug) {
53
+ return [new TransactionError(BasicTxErrorType.INTERNAL_ERROR)];
54
+ }
55
+ const alternativeAsset = this.chainService.getAssetBySlug(alternativeAssetSlug);
56
+ const fromAsset = this.chainService.getAssetBySlug(swapPair.from);
57
+ const [alternativeAssetBalance, fromAssetBalance] = await Promise.all([this.balanceService.getTokenFreeBalance(params.address, alternativeAsset.originChain, alternativeAssetSlug), this.balanceService.getTokenFreeBalance(params.address, fromAsset.originChain, fromAsset.slug)]);
58
+ const bnAlternativeAssetBalance = new BigNumber(alternativeAssetBalance.value);
59
+ const bnFromAssetBalance = new BigNumber(fromAssetBalance.value);
60
+ const xcmFeeComponent = params.process.totalFee[stepIndex].feeComponent[0]; // todo: can do better than indexing
61
+ const xcmFee = new BigNumber(xcmFeeComponent.amount || '0');
62
+ let xcmAmount = bnAmount.minus(bnFromAssetBalance);
63
+ if (_isNativeToken(alternativeAsset)) {
64
+ xcmAmount = xcmAmount.plus(xcmFee);
65
+ }
66
+ const alternativeTokenMinAmount = new BigNumber(alternativeAsset.minAmount || '0');
67
+ if (!bnAlternativeAssetBalance.minus(xcmAmount).gte(alternativeTokenMinAmount)) {
68
+ const maxBn = bnFromAssetBalance.plus(new BigNumber(alternativeAssetBalance.value)).minus(xcmFee).minus(alternativeTokenMinAmount);
69
+ const maxValue = formatNumber(maxBn.toString(), fromAsset.decimals || 0);
70
+ const altInputTokenInfo = this.chainService.getAssetBySlug(alternativeAssetSlug);
71
+ const symbol = altInputTokenInfo.symbol;
72
+ const alternativeChain = this.chainService.getChainInfoByKey(altInputTokenInfo.originChain);
73
+ const chain = this.chainService.getChainInfoByKey(fromAsset.originChain);
74
+ const inputNetworkName = chain.name;
75
+ const altNetworkName = alternativeChain.name;
76
+ const currentValue = formatNumber(bnFromAssetBalance.toString(), fromAsset.decimals || 0);
77
+ const bnMaxXCM = new BigNumber(alternativeAssetBalance.value).minus(xcmFee).minus(alternativeTokenMinAmount);
78
+ const maxXCMValue = formatNumber(bnMaxXCM.toString(), fromAsset.decimals || 0);
79
+ if (maxBn.lte(0) || bnFromAssetBalance.lte(0) || bnMaxXCM.lte(0)) {
80
+ return [new TransactionError(BasicTxErrorType.NOT_ENOUGH_BALANCE, t(`Insufficient balance. Deposit ${fromAsset.symbol} and try again.`))];
81
+ }
82
+ return [new TransactionError(BasicTxErrorType.NOT_ENOUGH_BALANCE, t('You can only enter a maximum of {{maxValue}} {{symbol}}, which is {{currentValue}} {{symbol}} ({{inputNetworkName}}) and {{maxXCMValue}} {{symbol}} ({{altNetworkName}}). Lower your amount and try again.', {
83
+ replace: {
84
+ symbol,
85
+ maxValue,
86
+ inputNetworkName,
87
+ altNetworkName,
88
+ currentValue,
89
+ maxXCMValue
90
+ }
91
+ }))];
92
+ }
93
+ return [];
94
+ }
95
+ async validateTokenApproveStep(params, stepIndex) {
96
+ return Promise.resolve([]);
97
+ }
98
+ async validateSetFeeTokenStep(params, stepIndex) {
99
+ if (!params.selectedQuote) {
100
+ return Promise.resolve([new TransactionError(BasicTxErrorType.INTERNAL_ERROR)]);
101
+ }
102
+ const feeInfo = params.process.totalFee[stepIndex];
103
+ const feeAmount = feeInfo.feeComponent[0];
104
+ const feeTokenInfo = this.chainService.getAssetBySlug(feeInfo.defaultFeeToken);
105
+ const feeTokenBalance = await this.balanceService.getTokenFreeBalance(params.address, feeTokenInfo.originChain, feeTokenInfo.slug);
106
+ const bnFeeTokenBalance = new BigNumber(feeTokenBalance.value);
107
+ const bnFeeAmount = new BigNumber(feeAmount.amount);
108
+ if (bnFeeAmount.gte(bnFeeTokenBalance)) {
109
+ return Promise.resolve([new TransactionError(BasicTxErrorType.NOT_ENOUGH_BALANCE)]);
110
+ }
111
+ return [];
112
+ }
113
+ async validateSwapStep(params, isXcmOk, stepIndex) {
114
+ if (!params.selectedQuote) {
115
+ return Promise.resolve([new TransactionError(BasicTxErrorType.INTERNAL_ERROR)]);
116
+ }
117
+ const selectedQuote = params.selectedQuote;
118
+ const currentTimestamp = +Date.now();
119
+ if (selectedQuote.aliveUntil <= currentTimestamp) {
120
+ return Promise.resolve([new TransactionError(SwapErrorType.QUOTE_TIMEOUT)]);
121
+ }
122
+ const bnAmount = new BigNumber(params.selectedQuote.fromAmount);
123
+ const fromAsset = this.chainService.getAssetBySlug(params.selectedQuote.pair.from);
124
+ const stepFee = params.process.totalFee[stepIndex].feeComponent;
125
+ const networkFee = stepFee.find(fee => fee.feeType === SwapFeeType.NETWORK_FEE);
126
+ if (!networkFee) {
127
+ return Promise.resolve([new TransactionError(BasicTxErrorType.INTERNAL_ERROR)]);
128
+ }
129
+ const feeTokenInfo = this.chainService.getAssetBySlug(networkFee.tokenSlug);
130
+ const feeTokenChain = this.chainService.getChainInfoByKey(feeTokenInfo.originChain);
131
+ const [feeTokenBalance, fromAssetBalance] = await Promise.all([this.balanceService.getTokenFreeBalance(params.address, feeTokenInfo.originChain, feeTokenInfo.slug), this.balanceService.getTokenFreeBalance(params.address, fromAsset.originChain, fromAsset.slug)]);
132
+ const bnFeeTokenBalance = new BigNumber(feeTokenBalance.value);
133
+ const bnFromAssetBalance = new BigNumber(fromAssetBalance.value);
134
+ const bnFeeAmount = new BigNumber(networkFee.amount);
135
+ if (bnFeeTokenBalance.lte(bnFeeAmount)) {
136
+ return Promise.resolve([new TransactionError(BasicTxErrorType.NOT_ENOUGH_BALANCE, `You don't have enough ${feeTokenInfo.symbol} (${feeTokenChain.name}) to pay transaction fee`)]);
137
+ }
138
+ if (fromAsset.slug === feeTokenInfo.slug) {
139
+ if (bnFromAssetBalance.lte(bnFeeAmount.plus(bnAmount))) {
140
+ return Promise.resolve([new TransactionError(BasicTxErrorType.NOT_ENOUGH_BALANCE, `Insufficient balance. Deposit ${fromAsset.symbol} and try again.`)]);
141
+ }
142
+ }
143
+ if (params.selectedQuote.minSwap) {
144
+ const minProtocolSwap = new BigNumber(params.selectedQuote.minSwap);
145
+ if (!isXcmOk && bnFromAssetBalance.lte(minProtocolSwap)) {
146
+ const parsedMinSwapValue = formatNumber(minProtocolSwap, _getAssetDecimals(fromAsset));
147
+ return Promise.resolve([new TransactionError(SwapErrorType.SWAP_NOT_ENOUGH_BALANCE, `Insufficient balance. You need more than ${parsedMinSwapValue} ${fromAsset.symbol} to start swapping. Deposit ${fromAsset.symbol} and try again.`)]); // todo: min swap or amount?
148
+ }
149
+ }
150
+
151
+ const bnSrcAssetMinAmount = new BigNumber(_getTokenMinAmount(fromAsset));
152
+ const bnMaxBalanceSwap = bnFromAssetBalance.minus(bnSrcAssetMinAmount);
153
+ if (!isXcmOk && bnAmount.gte(bnMaxBalanceSwap)) {
154
+ const parsedMaxBalanceSwap = formatNumber(bnMaxBalanceSwap, _getAssetDecimals(fromAsset));
155
+ return Promise.resolve([new TransactionError(SwapErrorType.SWAP_EXCEED_ALLOWANCE, `Amount too high. Lower your amount ${bnMaxBalanceSwap.gt(0) ? `below ${parsedMaxBalanceSwap} ${fromAsset.symbol}` : ''} and try again`)]);
156
+ }
157
+ if (params.recipient) {
158
+ const toAsset = this.chainService.getAssetBySlug(params.selectedQuote.pair.to);
159
+ const destChainInfo = this.chainService.getChainInfoByKey(toAsset.originChain);
160
+ const isEvmAddress = isEthereumAddress(params.recipient);
161
+ const isEvmDestChain = _isChainEvmCompatible(destChainInfo);
162
+ if (isEvmAddress && !isEvmDestChain || !isEvmAddress && isEvmDestChain) {
163
+ return Promise.resolve([new TransactionError(SwapErrorType.INVALID_RECIPIENT)]);
164
+ }
165
+ }
166
+ return Promise.resolve([]);
167
+ }
168
+ get name() {
169
+ return this.providerName;
170
+ }
171
+ get slug() {
172
+ return this.providerSlug;
173
+ }
174
+ get providerInfo() {
175
+ return {
176
+ id: this.providerSlug,
177
+ name: this.providerName
178
+ };
179
+ }
180
+ }
@@ -0,0 +1,30 @@
1
+ import { COMMON_ASSETS } from '@subwallet/chain-list';
2
+ import { SwapError } from '@subwallet/extension-base/background/errors/SwapError';
3
+ import { TransactionError } from '@subwallet/extension-base/background/errors/TransactionError';
4
+ import { BalanceService } from '@subwallet/extension-base/services/balance-service';
5
+ import { ChainService } from '@subwallet/extension-base/services/chain-service';
6
+ import { SwapBaseInterface } from '@subwallet/extension-base/services/swap-service/handler/base-handler';
7
+ import { BaseStepDetail } from '@subwallet/extension-base/types/service-base';
8
+ import { OptimalSwapPath, OptimalSwapPathParams, SwapEarlyValidation, SwapFeeInfo, SwapQuote, SwapRequest, SwapSubmitParams, SwapSubmitStepData, ValidateSwapProcessParams } from '@subwallet/extension-base/types/swap';
9
+ export declare class ChainflipSwapHandler implements SwapBaseInterface {
10
+ private swapSdk;
11
+ private readonly isTestnet;
12
+ private swapBaseHandler;
13
+ constructor(chainService: ChainService, balanceService: BalanceService, isTestnet?: boolean);
14
+ get chainService(): ChainService;
15
+ get balanceService(): BalanceService;
16
+ get providerInfo(): import("@subwallet/extension-base/types/swap").SwapProvider;
17
+ get name(): string;
18
+ get slug(): string;
19
+ get assetMapping(): Record<string, import("@chainflip/sdk/dist/contracts-b0BB7B5m").A>;
20
+ get chainMapping(): Record<string, import("@chainflip/sdk/dist/contracts-b0BB7B5m").C>;
21
+ get intermediaryAssetSlug(): COMMON_ASSETS.USDC_ETHEREUM | COMMON_ASSETS.USDC_SEPOLIA;
22
+ validateSwapRequest(request: SwapRequest): Promise<SwapEarlyValidation>;
23
+ private parseSwapPath;
24
+ getSwapQuote(request: SwapRequest): Promise<SwapQuote | SwapError>;
25
+ validateSwapProcess(params: ValidateSwapProcessParams): Promise<TransactionError[]>;
26
+ handleSubmitStep(params: SwapSubmitParams): Promise<SwapSubmitStepData>;
27
+ handleSwapProcess(params: SwapSubmitParams): Promise<SwapSubmitStepData>;
28
+ getSubmitStep(params: OptimalSwapPathParams): Promise<[BaseStepDetail, SwapFeeInfo] | undefined>;
29
+ generateOptimalProcess(params: OptimalSwapPathParams): Promise<OptimalSwapPath>;
30
+ }