@subwallet/extension-base 1.2.3-0 → 1.2.4-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 (94) hide show
  1. package/background/KoniTypes.d.ts +4 -153
  2. package/background/KoniTypes.js +0 -21
  3. package/cjs/background/KoniTypes.js +1 -22
  4. package/cjs/core/logic-validation/earning.js +47 -0
  5. package/cjs/core/logic-validation/swap.js +99 -0
  6. package/cjs/core/logic-validation/transfer.js +212 -0
  7. package/cjs/core/substrate/nominationpools-pallet.js +22 -0
  8. package/cjs/core/substrate/system-pallet.js +77 -0
  9. package/cjs/core/substrate/xcm-parser.js +190 -0
  10. package/cjs/koni/api/dotsama/transfer.js +58 -122
  11. package/cjs/koni/api/staking/bonding/utils.js +1 -1
  12. package/cjs/koni/api/xcm/index.js +30 -2
  13. package/cjs/koni/api/xcm/polkadotXcm.js +12 -20
  14. package/cjs/koni/api/xcm/utils.js +8 -126
  15. package/cjs/koni/api/xcm/xTokens.js +10 -8
  16. package/cjs/koni/api/xcm/xcmPallet.js +6 -6
  17. package/cjs/koni/background/handlers/Extension.js +223 -356
  18. package/cjs/packageInfo.js +1 -1
  19. package/cjs/services/balance-service/helpers/group.js +4 -27
  20. package/cjs/services/balance-service/helpers/subscribe/index.js +2 -30
  21. package/cjs/services/balance-service/helpers/subscribe/substrate/index.js +46 -82
  22. package/cjs/services/balance-service/index.js +11 -9
  23. package/cjs/services/chain-service/constants.js +2 -2
  24. package/cjs/services/chain-service/index.js +0 -1
  25. package/cjs/services/chain-service/utils/index.js +13 -2
  26. package/cjs/services/earning-service/handlers/base.js +1 -1
  27. package/cjs/services/earning-service/handlers/special.js +11 -12
  28. package/cjs/services/migration-service/scripts/MigrateTransactionHistoryBySymbol.js +2 -1
  29. package/cjs/services/migration-service/scripts/databases/MigrateAssetSetting.js +2 -1
  30. package/cjs/services/migration-service/scripts/index.js +2 -2
  31. package/cjs/services/swap-service/handler/base-handler.js +30 -44
  32. package/cjs/services/swap-service/handler/chainflip-handler.js +23 -21
  33. package/cjs/services/swap-service/handler/hydradx-handler.js +41 -39
  34. package/cjs/services/swap-service/index.js +6 -0
  35. package/cjs/services/swap-service/utils.js +8 -49
  36. package/cjs/services/transaction-service/index.js +66 -155
  37. package/core/logic-validation/earning.d.ts +10 -0
  38. package/core/logic-validation/earning.js +37 -0
  39. package/core/logic-validation/swap.d.ts +8 -0
  40. package/core/logic-validation/swap.js +89 -0
  41. package/core/logic-validation/transfer.d.ts +16 -0
  42. package/core/logic-validation/transfer.js +199 -0
  43. package/core/substrate/nominationpools-pallet.d.ts +10 -0
  44. package/core/substrate/nominationpools-pallet.js +13 -0
  45. package/core/substrate/system-pallet.d.ts +27 -0
  46. package/core/substrate/system-pallet.js +70 -0
  47. package/core/substrate/xcm-parser.d.ts +49 -0
  48. package/core/substrate/xcm-parser.js +181 -0
  49. package/koni/api/dotsama/transfer.d.ts +3 -4
  50. package/koni/api/dotsama/transfer.js +54 -118
  51. package/koni/api/staking/bonding/relayChain.d.ts +2 -1
  52. package/koni/api/staking/bonding/utils.js +1 -1
  53. package/koni/api/xcm/index.d.ts +2 -0
  54. package/koni/api/xcm/index.js +27 -1
  55. package/koni/api/xcm/polkadotXcm.js +14 -22
  56. package/koni/api/xcm/utils.d.ts +3 -48
  57. package/koni/api/xcm/utils.js +5 -114
  58. package/koni/api/xcm/xTokens.js +12 -10
  59. package/koni/api/xcm/xcmPallet.js +7 -7
  60. package/koni/background/handlers/Extension.d.ts +6 -8
  61. package/koni/background/handlers/Extension.js +117 -247
  62. package/package.json +39 -9
  63. package/packageInfo.js +1 -1
  64. package/services/balance-service/helpers/group.js +4 -27
  65. package/services/balance-service/helpers/subscribe/index.d.ts +2 -1
  66. package/services/balance-service/helpers/subscribe/index.js +2 -30
  67. package/services/balance-service/helpers/subscribe/substrate/index.d.ts +2 -1
  68. package/services/balance-service/helpers/subscribe/substrate/index.js +31 -66
  69. package/services/balance-service/index.d.ts +7 -6
  70. package/services/balance-service/index.js +12 -10
  71. package/services/chain-service/constants.js +2 -2
  72. package/services/chain-service/index.js +0 -1
  73. package/services/chain-service/utils/index.d.ts +4 -2
  74. package/services/chain-service/utils/index.js +9 -2
  75. package/services/earning-service/handlers/base.js +1 -1
  76. package/services/earning-service/handlers/nomination-pool/index.d.ts +2 -1
  77. package/services/earning-service/handlers/special.js +11 -12
  78. package/services/migration-service/scripts/MigrateTransactionHistoryBySymbol.js +2 -1
  79. package/services/migration-service/scripts/databases/MigrateAssetSetting.js +2 -1
  80. package/services/migration-service/scripts/index.js +2 -2
  81. package/services/swap-service/handler/base-handler.d.ts +3 -2
  82. package/services/swap-service/handler/base-handler.js +28 -42
  83. package/services/swap-service/handler/chainflip-handler.d.ts +2 -1
  84. package/services/swap-service/handler/chainflip-handler.js +4 -2
  85. package/services/swap-service/handler/hydradx-handler.d.ts +2 -1
  86. package/services/swap-service/handler/hydradx-handler.js +8 -6
  87. package/services/swap-service/index.js +7 -1
  88. package/services/swap-service/utils.d.ts +2 -4
  89. package/services/swap-service/utils.js +7 -47
  90. package/services/transaction-service/index.d.ts +1 -1
  91. package/services/transaction-service/index.js +30 -119
  92. package/services/transaction-service/types.d.ts +1 -0
  93. package/types/balance/index.d.ts +6 -10
  94. package/types/yield/info/pallet.d.ts +0 -6
@@ -0,0 +1,199 @@
1
+ // Copyright 2019-2022 @subwallet/extension-base authors & contributors
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ import { TransactionError } from '@subwallet/extension-base/background/errors/TransactionError';
5
+ import { BasicTxErrorType, BasicTxWarningCode, ExtrinsicType, TransferTxErrorType } from '@subwallet/extension-base/background/KoniTypes';
6
+ import { TransactionWarning } from '@subwallet/extension-base/background/warnings/TransactionWarning';
7
+ import { XCM_MIN_AMOUNT_RATIO } from '@subwallet/extension-base/constants';
8
+ import { _canAccountBeReaped } from '@subwallet/extension-base/core/substrate/system-pallet';
9
+ import { _TRANSFER_CHAIN_GROUP } from '@subwallet/extension-base/services/chain-service/constants';
10
+ import { _getChainNativeTokenBasicInfo, _getContractAddressOfToken, _getTokenMinAmount, _isNativeToken, _isTokenEvmSmartContract } from '@subwallet/extension-base/services/chain-service/utils';
11
+ import { calculateGasFeeParams } from '@subwallet/extension-base/services/fee-service/utils';
12
+ import { isSubstrateTransaction } from '@subwallet/extension-base/services/transaction-service/helpers';
13
+ import { balanceFormatter, formatNumber } from '@subwallet/extension-base/utils';
14
+ import { keyring } from '@subwallet/ui-keyring';
15
+ import BigN from 'bignumber.js';
16
+ import { t } from 'i18next';
17
+ import { isEthereumAddress } from '@polkadot/util-crypto';
18
+
19
+ // normal transfer
20
+ export function validateTransferRequest(tokenInfo, from, to, value, transferAll) {
21
+ const errors = [];
22
+ const keypair = keyring.getPair(from);
23
+ let transferValue;
24
+ if (!transferAll) {
25
+ if (value === undefined) {
26
+ errors.push(new TransactionError(BasicTxErrorType.INVALID_PARAMS, t('Transfer amount is required')));
27
+ }
28
+ if (value) {
29
+ transferValue = new BigN(value);
30
+ }
31
+ }
32
+ if (!tokenInfo) {
33
+ errors.push(new TransactionError(BasicTxErrorType.INVALID_PARAMS, t('Not found token from registry')));
34
+ }
35
+ if (isEthereumAddress(from) && isEthereumAddress(to) && _isTokenEvmSmartContract(tokenInfo) && _getContractAddressOfToken(tokenInfo).length === 0) {
36
+ errors.push(new TransactionError(BasicTxErrorType.INVALID_PARAMS, t('Not found ERC20 address for this token')));
37
+ }
38
+ return [errors, keypair, transferValue];
39
+ }
40
+ export function additionalValidateTransfer(tokenInfo, extrinsicType, receiverTransferTokenFreeBalance, transferAmount, senderTransferTokenTransferable) {
41
+ const minAmount = _getTokenMinAmount(tokenInfo);
42
+ let warning;
43
+ let error;
44
+
45
+ // Check ed of not native token for sender
46
+ if (extrinsicType === ExtrinsicType.TRANSFER_TOKEN && senderTransferTokenTransferable) {
47
+ if (new BigN(senderTransferTokenTransferable).minus(transferAmount).lt(minAmount)) {
48
+ warning = new TransactionWarning(BasicTxWarningCode.NOT_ENOUGH_EXISTENTIAL_DEPOSIT);
49
+ }
50
+ }
51
+
52
+ // Check ed for receiver
53
+ if (new BigN(receiverTransferTokenFreeBalance).plus(transferAmount).lt(minAmount)) {
54
+ const atLeast = new BigN(minAmount).minus(receiverTransferTokenFreeBalance).plus((tokenInfo.decimals || 0) === 0 ? 0 : 1);
55
+ const atLeastStr = formatNumber(atLeast, tokenInfo.decimals || 0, balanceFormatter, {
56
+ maxNumberFormat: tokenInfo.decimals || 6
57
+ });
58
+ error = new TransactionError(TransferTxErrorType.RECEIVER_NOT_ENOUGH_EXISTENTIAL_DEPOSIT, t('You must transfer at least {{amount}} {{symbol}} to keep the destination account alive', {
59
+ replace: {
60
+ amount: atLeastStr,
61
+ symbol: tokenInfo.symbol
62
+ }
63
+ }));
64
+ }
65
+ return [warning, error];
66
+ }
67
+
68
+ // xcm transfer
69
+ export function validateXcmTransferRequest(destTokenInfo, sender, sendingValue) {
70
+ const errors = [];
71
+ const keypair = keyring.getPair(sender);
72
+ const transferValue = new BigN(sendingValue);
73
+ if (!destTokenInfo) {
74
+ errors.push(new TransactionError(TransferTxErrorType.INVALID_TOKEN, t('Not found token from registry')));
75
+ }
76
+ return [errors, keypair, transferValue];
77
+ }
78
+ export function additionalValidateXcmTransfer(originTokenInfo, destinationTokenInfo, sendingAmount, senderTransferable) {
79
+ const destMinAmount = _getTokenMinAmount(destinationTokenInfo);
80
+ const minSendingRequired = new BigN(destMinAmount).multipliedBy(XCM_MIN_AMOUNT_RATIO);
81
+ let error;
82
+ let warning;
83
+
84
+ // Check ed for receiver
85
+ if (new BigN(sendingAmount).lt(minSendingRequired)) {
86
+ const atLeastStr = formatNumber(minSendingRequired, destinationTokenInfo.decimals || 0, balanceFormatter, {
87
+ maxNumberFormat: destinationTokenInfo.decimals || 6
88
+ });
89
+ error = new TransactionError(TransferTxErrorType.RECEIVER_NOT_ENOUGH_EXISTENTIAL_DEPOSIT, t('You must transfer at least {{amount}} {{symbol}} to keep the destination account alive', {
90
+ replace: {
91
+ amount: atLeastStr,
92
+ symbol: originTokenInfo.symbol
93
+ }
94
+ }));
95
+ }
96
+
97
+ // Check ed for sender
98
+ if (!_isNativeToken(originTokenInfo)) {
99
+ if (new BigN(senderTransferable).minus(sendingAmount).lt(_getTokenMinAmount(originTokenInfo))) {
100
+ warning = new TransactionWarning(BasicTxWarningCode.NOT_ENOUGH_EXISTENTIAL_DEPOSIT);
101
+ }
102
+ }
103
+ return [warning, error];
104
+ }
105
+
106
+ // general validations
107
+ export function checkSupportForTransaction(validationResponse, transaction) {
108
+ const {
109
+ extrinsicType
110
+ } = validationResponse;
111
+ if (!transaction) {
112
+ if (extrinsicType === ExtrinsicType.SEND_NFT) {
113
+ validationResponse.errors.push(new TransactionError(BasicTxErrorType.UNSUPPORTED, t('This feature is not yet available for this NFT')));
114
+ } else {
115
+ validationResponse.errors.push(new TransactionError(BasicTxErrorType.UNSUPPORTED));
116
+ }
117
+ }
118
+ }
119
+ export async function estimateFeeForTransaction(validationResponse, transaction, chainInfo, evmApi) {
120
+ const estimateFee = {
121
+ symbol: '',
122
+ decimals: 0,
123
+ value: '0',
124
+ tooHigh: false
125
+ };
126
+ const {
127
+ decimals,
128
+ symbol
129
+ } = _getChainNativeTokenBasicInfo(chainInfo);
130
+ estimateFee.decimals = decimals;
131
+ estimateFee.symbol = symbol;
132
+ if (transaction) {
133
+ try {
134
+ if (isSubstrateTransaction(transaction)) {
135
+ estimateFee.value = (await transaction.paymentInfo(validationResponse.address)).partialFee.toString();
136
+ } else {
137
+ const gasLimit = await evmApi.api.eth.estimateGas(transaction);
138
+ const priority = await calculateGasFeeParams(evmApi, chainInfo.slug);
139
+ if (priority.baseGasFee) {
140
+ const maxFee = priority.maxFeePerGas; // TODO: Need review
141
+
142
+ estimateFee.value = maxFee.multipliedBy(gasLimit).toFixed(0);
143
+ } else {
144
+ estimateFee.value = new BigN(priority.gasPrice).multipliedBy(gasLimit).toFixed(0);
145
+ }
146
+ estimateFee.tooHigh = priority.busyNetwork;
147
+ }
148
+ } catch (e) {
149
+ const error = e;
150
+ if (error.message.includes('gas required exceeds allowance') && error.message.includes('insufficient funds')) {
151
+ validationResponse.errors.push(new TransactionError(BasicTxErrorType.NOT_ENOUGH_BALANCE));
152
+ }
153
+ }
154
+ }
155
+ return estimateFee;
156
+ }
157
+ export function checkSigningAccountForTransaction(validationResponse) {
158
+ const pair = keyring.getPair(validationResponse.address);
159
+ if (!pair) {
160
+ validationResponse.errors.push(new TransactionError(BasicTxErrorType.INTERNAL_ERROR, t('Unable to find account')));
161
+ } else {
162
+ var _pair$meta;
163
+ if ((_pair$meta = pair.meta) !== null && _pair$meta !== void 0 && _pair$meta.isReadOnly) {
164
+ validationResponse.errors.push(new TransactionError(BasicTxErrorType.INTERNAL_ERROR, t('This account is watch-only')));
165
+ }
166
+ }
167
+ }
168
+ export function checkBalanceWithTransactionFee(validationResponse, transactionInput, nativeTokenInfo, nativeTokenAvailable) {
169
+ if (!validationResponse.estimateFee) {
170
+ // todo: estimateFee should be must-have, need to refactor interface
171
+ return;
172
+ }
173
+ const {
174
+ edAsWarning,
175
+ extrinsicType,
176
+ isTransferAll,
177
+ skipFeeValidation
178
+ } = transactionInput;
179
+ if (skipFeeValidation) {
180
+ return;
181
+ }
182
+ const bnFee = new BigN(validationResponse.estimateFee.value);
183
+ const bnNativeTokenAvailable = new BigN(nativeTokenAvailable.value);
184
+ const bnNativeTokenTransferAmount = new BigN(validationResponse.transferNativeAmount || '0');
185
+ if (!bnNativeTokenAvailable.gt(0)) {
186
+ validationResponse.errors.push(new TransactionError(BasicTxErrorType.NOT_ENOUGH_BALANCE));
187
+ }
188
+ const isChainNotSupportTransferAll = [..._TRANSFER_CHAIN_GROUP.acala, ..._TRANSFER_CHAIN_GROUP.genshiro, ..._TRANSFER_CHAIN_GROUP.bitcountry, ..._TRANSFER_CHAIN_GROUP.statemine].includes(nativeTokenInfo.originChain);
189
+ if (bnNativeTokenTransferAmount.plus(bnFee).gt(bnNativeTokenAvailable) && (!isTransferAll || isChainNotSupportTransferAll)) {
190
+ validationResponse.errors.push(new TransactionError(BasicTxErrorType.NOT_ENOUGH_BALANCE)); // todo: should be generalized and reused in all features
191
+ }
192
+
193
+ // todo: only system.pallet has metadata, we should add for other pallets and mechanisms as well
194
+ const isNeedCheckRemainingBalance = !isTransferAll && extrinsicType === ExtrinsicType.TRANSFER_BALANCE && nativeTokenAvailable.metadata && _canAccountBeReaped(nativeTokenAvailable.metadata);
195
+ const isRemainingBalanceValid = bnNativeTokenAvailable.minus(bnNativeTokenTransferAmount).minus(bnFee).lt(_getTokenMinAmount(nativeTokenInfo));
196
+ if (isNeedCheckRemainingBalance && isRemainingBalanceValid) {
197
+ edAsWarning ? validationResponse.warnings.push(new TransactionWarning(BasicTxWarningCode.NOT_ENOUGH_EXISTENTIAL_DEPOSIT)) : validationResponse.errors.push(new TransactionError(BasicTxErrorType.NOT_ENOUGH_EXISTENTIAL_DEPOSIT));
198
+ }
199
+ }
@@ -0,0 +1,10 @@
1
+ import BigN from 'bignumber.js';
2
+ export declare type PalletNominationPoolsPoolMember = {
3
+ poolId: number;
4
+ points: number;
5
+ lastRecordedRewardCounter: number;
6
+ unbondingEras: Record<string, number>;
7
+ };
8
+ export declare function _getActiveStakeInNominationPool(memberInfo: PalletNominationPoolsPoolMember): BigN;
9
+ export declare function _getUnbondingStakeInNominationPool(memberInfo: PalletNominationPoolsPoolMember): BigN;
10
+ export declare function _getTotalStakeInNominationPool(memberInfo: PalletNominationPoolsPoolMember): BigN;
@@ -0,0 +1,13 @@
1
+ // Copyright 2019-2022 @subwallet/extension-base
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ import BigN from 'bignumber.js';
5
+ export function _getActiveStakeInNominationPool(memberInfo) {
6
+ return new BigN(memberInfo.points.toString());
7
+ }
8
+ export function _getUnbondingStakeInNominationPool(memberInfo) {
9
+ return new BigN(Object.values(memberInfo.unbondingEras).reduce((a, b) => a + b, 0));
10
+ }
11
+ export function _getTotalStakeInNominationPool(memberInfo) {
12
+ return _getActiveStakeInNominationPool(memberInfo).plus(_getUnbondingStakeInNominationPool(memberInfo));
13
+ }
@@ -0,0 +1,27 @@
1
+ import { ExtrinsicType } from '@subwallet/extension-base/background/KoniTypes';
2
+ export declare type FrameSystemAccountInfoV2 = Omit<FrameSystemAccountInfoV1, 'data'> & {
3
+ data: {
4
+ free: number;
5
+ reserved: number;
6
+ frozen: number;
7
+ flags: number;
8
+ };
9
+ };
10
+ export declare type FrameSystemAccountInfoV1 = {
11
+ nonce: number;
12
+ consumers: number;
13
+ providers: number;
14
+ sufficients: number;
15
+ data: {
16
+ free: number | string;
17
+ reserved: number;
18
+ miscFrozen: number;
19
+ feeFrozen: number;
20
+ };
21
+ };
22
+ export declare type FrameSystemAccountInfo = FrameSystemAccountInfoV1 | FrameSystemAccountInfoV2;
23
+ export declare function _getSystemPalletTransferable(accountInfo: FrameSystemAccountInfo, existentialDeposit: string, extrinsicType?: ExtrinsicType): string;
24
+ export declare function _canAccountBeReaped(accountInfo: FrameSystemAccountInfo): boolean;
25
+ export declare function _isAccountActive(accountInfo: FrameSystemAccountInfo): boolean;
26
+ export declare function _getSystemPalletTotalBalance(accountInfo: FrameSystemAccountInfo): string;
27
+ export declare function _getAppliedExistentialDepositWithExtrinsicType(accountInfo: FrameSystemAccountInfo, existentialDeposit: string, extrinsicType?: ExtrinsicType): string;
@@ -0,0 +1,70 @@
1
+ // Copyright 2019-2022 @subwallet/extension-base
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ import { ExtrinsicType } from '@subwallet/extension-base/background/KoniTypes';
5
+ import BigN from 'bignumber.js';
6
+
7
+ // https://crates.parity.io/frame_system/struct.AccountInfo.html
8
+ // https://wiki.polkadot.network/docs/learn-account-balances
9
+
10
+ function isV1(accountInfo) {
11
+ return accountInfo.data.miscFrozen !== undefined && accountInfo.data.feeFrozen !== undefined;
12
+ }
13
+ export function _getSystemPalletTransferable(accountInfo, existentialDeposit, extrinsicType) {
14
+ const strictMode = !extrinsicType || ![ExtrinsicType.TRANSFER_BALANCE].includes(extrinsicType); // always apply strict mode to keep account alive unless explicitly specified otherwise
15
+
16
+ if (isV1(accountInfo)) {
17
+ return _getSystemPalletTransferableV1(accountInfo, existentialDeposit, strictMode);
18
+ } else {
19
+ return _getSystemPalletTransferableV2(accountInfo, existentialDeposit, strictMode);
20
+ }
21
+ }
22
+ export function _canAccountBeReaped(accountInfo) {
23
+ return accountInfo.consumers === 0; // might need to check refCount
24
+ }
25
+
26
+ export function _isAccountActive(accountInfo) {
27
+ return accountInfo.providers === 0 && accountInfo.consumers === 0;
28
+ }
29
+ export function _getSystemPalletTotalBalance(accountInfo) {
30
+ if (isV1(accountInfo)) {
31
+ return _getSystemPalletTotalBalanceV1(accountInfo);
32
+ } else {
33
+ return _getSystemPalletTotalBalanceV2(accountInfo);
34
+ }
35
+ }
36
+ export function _getAppliedExistentialDepositWithExtrinsicType(accountInfo, existentialDeposit, extrinsicType) {
37
+ const strictMode = !extrinsicType || ![ExtrinsicType.TRANSFER_BALANCE].includes(extrinsicType); // always apply strict mode to keep account alive unless explicitly specified otherwise
38
+
39
+ return _getAppliedExistentialDeposit(accountInfo, existentialDeposit, strictMode);
40
+ }
41
+
42
+ // ----------------------------------------------------------------------
43
+
44
+ function _getAppliedExistentialDeposit(accountInfo, existentialDeposit, strictMode) {
45
+ // strict mode will always apply existential deposit to keep account alive
46
+ if (strictMode) {
47
+ return existentialDeposit;
48
+ }
49
+ return _canAccountBeReaped(accountInfo) ? '0' : existentialDeposit; // account for ED here will go better with max transfer logic
50
+ }
51
+
52
+ function _getSystemPalletTransferableV2(accountInfo, existentialDeposit, strictMode) {
53
+ const bnFree = new BigN(accountInfo.data.free);
54
+ const bnLocked = new BigN(accountInfo.data.frozen).minus(accountInfo.data.reserved); // locked can go below 0 but this shouldn't matter
55
+ const bnAppliedExistentialDeposit = new BigN(_getAppliedExistentialDeposit(accountInfo, existentialDeposit, strictMode));
56
+ const bnTransferableBalance = bnFree.minus(BigN.max(bnLocked, bnAppliedExistentialDeposit));
57
+ return BigN.max(bnTransferableBalance, 0).toFixed();
58
+ }
59
+ function _getSystemPalletTotalBalanceV2(accountInfo) {
60
+ return new BigN(accountInfo.data.free).plus(accountInfo.data.reserved).toFixed();
61
+ }
62
+ function _getSystemPalletTransferableV1(accountInfo, existentialDeposit, strictMode) {
63
+ const bnAppliedExistentialDeposit = new BigN(_getAppliedExistentialDeposit(accountInfo, existentialDeposit, strictMode));
64
+ const bnAppliedFrozen = BigN.max(accountInfo.data.feeFrozen, accountInfo.data.miscFrozen);
65
+ const bnTransferableBalance = new BigN(accountInfo.data.free).minus(BigN.max(bnAppliedFrozen, bnAppliedExistentialDeposit));
66
+ return BigN.max(bnTransferableBalance, 0).toFixed();
67
+ }
68
+ function _getSystemPalletTotalBalanceV1(accountInfo) {
69
+ return new BigN(accountInfo.data.free).plus(accountInfo.data.reserved).toFixed();
70
+ }
@@ -0,0 +1,49 @@
1
+ import { _ChainAsset, _ChainInfo } from '@subwallet/chain-list/types';
2
+ import { _Address } from '@subwallet/extension-base/background/KoniTypes';
3
+ export declare function _getXcmDestWeight(originChainInfo: _ChainInfo): "Unlimited" | 5000000000;
4
+ export declare function _getXcmBeneficiary(destChainInfo: _ChainInfo, recipient: _Address, version: number): {
5
+ [x: string]: {
6
+ parents: number;
7
+ interior: {
8
+ X1: {
9
+ AccountId32: {
10
+ network: string | undefined;
11
+ id: Uint8Array;
12
+ };
13
+ AccountKey20?: undefined;
14
+ } | {
15
+ AccountKey20: {
16
+ network: string | undefined;
17
+ key: string;
18
+ };
19
+ AccountId32?: undefined;
20
+ } | ({
21
+ AccountId32: {
22
+ network: string | undefined;
23
+ id: Uint8Array;
24
+ };
25
+ AccountKey20?: undefined;
26
+ } | {
27
+ AccountKey20: {
28
+ network: string | undefined;
29
+ key: string;
30
+ };
31
+ AccountId32?: undefined;
32
+ })[];
33
+ };
34
+ };
35
+ };
36
+ export declare function _getXcmMultiAssets(tokenInfo: _ChainAsset, value: string, version: number): {
37
+ [x: string]: {
38
+ id: Record<string, any>;
39
+ fun: {
40
+ Fungible: string;
41
+ };
42
+ }[];
43
+ };
44
+ export declare function _getXcmMultiLocation(originChainInfo: _ChainInfo, destChainInfo: _ChainInfo, version: number, recipient?: _Address): {
45
+ [x: string]: {
46
+ parents: number;
47
+ interior: unknown;
48
+ };
49
+ };
@@ -0,0 +1,181 @@
1
+ // Copyright 2019-2022 @subwallet/extension-base
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ import { COMMON_CHAIN_SLUGS } from '@subwallet/chain-list';
5
+ import { _getChainSubstrateAddressPrefix, _getEvmChainId, _getSubstrateParaId, _getSubstrateRelayParent, _getXcmAssetMultilocation, _isChainEvmCompatible, _isSubstrateParaChain } from '@subwallet/extension-base/services/chain-service/utils';
6
+ import { decodeAddress, evmToAddress } from '@polkadot/util-crypto';
7
+ const FOUR_INSTRUCTIONS_WEIGHT = 5000000000;
8
+ const UNLIMITED_WEIGHT = 'Unlimited';
9
+ export function _getXcmDestWeight(originChainInfo) {
10
+ if (['pioneer'].includes(originChainInfo.slug)) {
11
+ return FOUR_INSTRUCTIONS_WEIGHT;
12
+ }
13
+ return UNLIMITED_WEIGHT;
14
+ }
15
+ export function _getXcmBeneficiary(destChainInfo, recipient, version) {
16
+ const receiverLocation = version < 4 // from V4, X1 is also an array
17
+ ? _getRecipientLocation(destChainInfo, recipient, version) : [_getRecipientLocation(destChainInfo, recipient, version)];
18
+ return {
19
+ [`V${version}`]: {
20
+ parents: 0,
21
+ interior: {
22
+ X1: receiverLocation
23
+ }
24
+ }
25
+ };
26
+ }
27
+ export function _getXcmMultiAssets(tokenInfo, value, version) {
28
+ const assetId = _getAssetIdentifier(tokenInfo, version);
29
+ return {
30
+ [`V${version}`]: [{
31
+ id: assetId,
32
+ fun: {
33
+ Fungible: value
34
+ }
35
+ }]
36
+ };
37
+ }
38
+ export function _getXcmMultiLocation(originChainInfo, destChainInfo, version, recipient) {
39
+ const isWithinSameConsensus = _isXcmWithinSameConsensus(originChainInfo, destChainInfo);
40
+ const parents = _getMultiLocationParent(originChainInfo, isWithinSameConsensus);
41
+ const interior = _getMultiLocationInterior(destChainInfo, isWithinSameConsensus, version, recipient);
42
+ return {
43
+ [`V${version}`]: {
44
+ parents,
45
+ interior
46
+ }
47
+ };
48
+ }
49
+
50
+ // ---------------------------------------------------------------------------------------------------------------------
51
+
52
+ function _isXcmWithinSameConsensus(originChainInfo, destChainInfo) {
53
+ return _getSubstrateRelayParent(originChainInfo) === destChainInfo.slug || _getSubstrateRelayParent(destChainInfo) === originChainInfo.slug || _getSubstrateRelayParent(originChainInfo) === _getSubstrateRelayParent(destChainInfo);
54
+ }
55
+ function _getMultiLocationParent(originChainInfo, isWithinSameConsensus) {
56
+ let parent = 0; // how many hops up the hierarchy
57
+
58
+ if (_isSubstrateParaChain(originChainInfo)) {
59
+ parent += 1;
60
+ }
61
+ if (!isWithinSameConsensus) {
62
+ parent += 1;
63
+ }
64
+ return parent;
65
+ }
66
+ function _getMultiLocationInterior(destChainInfo, isWithinSameConsensus, version, recipient) {
67
+ const junctions = [];
68
+ if (isWithinSameConsensus) {
69
+ if (_isSubstrateParaChain(destChainInfo)) {
70
+ junctions.push({
71
+ Parachain: _getSubstrateParaId(destChainInfo)
72
+ });
73
+ }
74
+ } else {
75
+ junctions.push({
76
+ GlobalConsensus: _getGlobalConsensusJunction(destChainInfo, version)
77
+ });
78
+ if (_isSubstrateParaChain(destChainInfo)) {
79
+ junctions.push({
80
+ Parachain: _getSubstrateParaId(destChainInfo)
81
+ });
82
+ }
83
+ }
84
+ if (recipient) {
85
+ junctions.push(_getRecipientLocation(destChainInfo, recipient, version));
86
+ }
87
+ if (junctions.length === 0 && !recipient) {
88
+ return 'Here';
89
+ }
90
+ if (version < 4 && junctions.length === 1) {
91
+ return {
92
+ X1: junctions[0]
93
+ };
94
+ }
95
+ return {
96
+ [`X${junctions.length}`]: junctions
97
+ };
98
+ }
99
+ function _getGlobalConsensusJunction(destChainInfo, version) {
100
+ let chainSlug = destChainInfo.slug;
101
+ let evmChainId;
102
+ if (_isSubstrateParaChain(destChainInfo)) {
103
+ const relaySlug = _getSubstrateRelayParent(destChainInfo);
104
+ if (!relaySlug) {
105
+ throw Error('Parachain must have a parent chainSlug');
106
+ }
107
+ chainSlug = relaySlug;
108
+ } else {
109
+ evmChainId = _getEvmChainId(destChainInfo);
110
+ }
111
+ if (evmChainId) {
112
+ return {
113
+ Ethereum: {
114
+ chainId: evmChainId
115
+ }
116
+ };
117
+ }
118
+ switch (chainSlug) {
119
+ case COMMON_CHAIN_SLUGS.POLKADOT:
120
+ return version < 4 ? {
121
+ Polkadot: null
122
+ } : 'Polkadot';
123
+ case COMMON_CHAIN_SLUGS.KUSAMA:
124
+ return version < 4 ? {
125
+ Kusama: null
126
+ } : 'Kusama';
127
+ default:
128
+ return version < 4 ? {
129
+ Rococo: null
130
+ } : 'Rococo';
131
+ }
132
+ }
133
+ function _getRecipientLocation(destChainInfo, recipient, version) {
134
+ const network = _getNetworkByVersion(version);
135
+ if (destChainInfo.slug === COMMON_CHAIN_SLUGS.ASTAR_EVM) {
136
+ const ss58Address = evmToAddress(recipient, _getChainSubstrateAddressPrefix(destChainInfo)); // TODO: shouldn't pass addressPrefix directly
137
+
138
+ return {
139
+ AccountId32: {
140
+ network,
141
+ id: decodeAddress(ss58Address)
142
+ }
143
+ };
144
+ }
145
+ if (_isChainEvmCompatible(destChainInfo)) {
146
+ return {
147
+ AccountKey20: {
148
+ network,
149
+ key: recipient
150
+ }
151
+ };
152
+ }
153
+ return {
154
+ AccountId32: {
155
+ network,
156
+ id: decodeAddress(recipient)
157
+ }
158
+ };
159
+ }
160
+ function _getAssetIdentifier(tokenInfo, version) {
161
+ const assetIdentifier = _getXcmAssetMultilocation(tokenInfo);
162
+ if (!assetIdentifier) {
163
+ throw new Error('Asset must have multilocation');
164
+ }
165
+ return version >= 4 // from V4, Concrete is removed
166
+ ? assetIdentifier : {
167
+ Concrete: assetIdentifier
168
+ };
169
+ }
170
+ function _getNetworkByVersion(version) {
171
+ switch (version) {
172
+ case 1:
173
+ case 2:
174
+ return 'Any';
175
+ case 3:
176
+ case 4:
177
+ return undefined;
178
+ default:
179
+ return undefined;
180
+ }
181
+ }
@@ -1,9 +1,7 @@
1
1
  import { _ChainAsset, _ChainInfo } from '@subwallet/chain-list/types';
2
- import { SupportTransferResponse } from '@subwallet/extension-base/background/KoniTypes';
3
- import { _SubstrateApi } from '@subwallet/extension-base/services/chain-service/types';
2
+ import { _EvmApi, _SubstrateApi } from '@subwallet/extension-base/services/chain-service/types';
3
+ import BigN from 'bignumber.js';
4
4
  import { SubmittableExtrinsic } from '@polkadot/api/promise/types';
5
- export declare function checkReferenceCount(networkKey: string, address: string, substrateApiMap: Record<string, _SubstrateApi>, chainInfo: _ChainInfo): Promise<boolean>;
6
- export declare function checkSupportTransfer(networkKey: string, tokenInfo: _ChainAsset, substrateApiMap: Record<string, _SubstrateApi>, chainInfo: _ChainInfo): Promise<SupportTransferResponse>;
7
5
  interface CreateTransferExtrinsicProps {
8
6
  substrateApi: _SubstrateApi;
9
7
  networkKey: string;
@@ -14,4 +12,5 @@ interface CreateTransferExtrinsicProps {
14
12
  tokenInfo: _ChainAsset;
15
13
  }
16
14
  export declare const createTransferExtrinsic: ({ from, networkKey, substrateApi, to, tokenInfo, transferAll, value }: CreateTransferExtrinsicProps) => Promise<[SubmittableExtrinsic | null, string]>;
15
+ export declare const getTransferMockTxFee: (address: string, chainInfo: _ChainInfo, tokenInfo: _ChainAsset, api: _SubstrateApi | _EvmApi) => Promise<BigN>;
17
16
  export {};