@subwallet/extension-base 1.2.3-0 → 1.2.3-1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. package/background/KoniTypes.d.ts +4 -0
  2. package/cjs/core/logic-validation/earning.js +47 -0
  3. package/cjs/core/logic-validation/swap.js +99 -0
  4. package/cjs/core/logic-validation/transfer.js +219 -0
  5. package/cjs/core/substrate/nominationpools-pallet.js +12 -0
  6. package/cjs/core/substrate/system-pallet.js +78 -0
  7. package/cjs/koni/api/dotsama/transfer.js +49 -4
  8. package/cjs/koni/api/staking/bonding/utils.js +1 -1
  9. package/cjs/koni/api/xcm/index.js +30 -2
  10. package/cjs/koni/background/handlers/Extension.js +135 -245
  11. package/cjs/packageInfo.js +1 -1
  12. package/cjs/services/balance-service/helpers/group.js +4 -27
  13. package/cjs/services/balance-service/helpers/subscribe/index.js +2 -30
  14. package/cjs/services/balance-service/helpers/subscribe/substrate/index.js +41 -80
  15. package/cjs/services/balance-service/index.js +11 -9
  16. package/cjs/services/chain-service/index.js +0 -1
  17. package/cjs/services/chain-service/utils/index.js +6 -0
  18. package/cjs/services/earning-service/handlers/base.js +1 -1
  19. package/cjs/services/earning-service/handlers/special.js +11 -12
  20. package/cjs/services/swap-service/handler/base-handler.js +28 -44
  21. package/cjs/services/swap-service/handler/chainflip-handler.js +23 -21
  22. package/cjs/services/swap-service/handler/hydradx-handler.js +40 -38
  23. package/cjs/services/swap-service/index.js +6 -0
  24. package/cjs/services/swap-service/utils.js +8 -49
  25. package/cjs/services/transaction-service/index.js +66 -155
  26. package/core/logic-validation/earning.d.ts +10 -0
  27. package/core/logic-validation/earning.js +37 -0
  28. package/core/logic-validation/swap.d.ts +8 -0
  29. package/core/logic-validation/swap.js +89 -0
  30. package/core/logic-validation/transfer.d.ts +16 -0
  31. package/core/logic-validation/transfer.js +206 -0
  32. package/core/substrate/nominationpools-pallet.d.ts +7 -0
  33. package/core/substrate/nominationpools-pallet.js +6 -0
  34. package/core/substrate/system-pallet.d.ts +27 -0
  35. package/core/substrate/system-pallet.js +71 -0
  36. package/koni/api/dotsama/transfer.d.ts +3 -1
  37. package/koni/api/dotsama/transfer.js +44 -1
  38. package/koni/api/staking/bonding/relayChain.d.ts +2 -1
  39. package/koni/api/staking/bonding/utils.js +1 -1
  40. package/koni/api/xcm/index.d.ts +2 -0
  41. package/koni/api/xcm/index.js +27 -1
  42. package/koni/background/handlers/Extension.d.ts +5 -5
  43. package/koni/background/handlers/Extension.js +111 -221
  44. package/package.json +34 -9
  45. package/packageInfo.js +1 -1
  46. package/services/balance-service/helpers/group.js +4 -27
  47. package/services/balance-service/helpers/subscribe/index.d.ts +2 -1
  48. package/services/balance-service/helpers/subscribe/index.js +2 -30
  49. package/services/balance-service/helpers/subscribe/substrate/index.d.ts +2 -1
  50. package/services/balance-service/helpers/subscribe/substrate/index.js +26 -64
  51. package/services/balance-service/index.d.ts +7 -6
  52. package/services/balance-service/index.js +12 -10
  53. package/services/chain-service/index.js +0 -1
  54. package/services/chain-service/utils/index.d.ts +1 -0
  55. package/services/chain-service/utils/index.js +4 -0
  56. package/services/earning-service/handlers/base.js +1 -1
  57. package/services/earning-service/handlers/nomination-pool/index.d.ts +2 -1
  58. package/services/earning-service/handlers/special.js +11 -12
  59. package/services/swap-service/handler/base-handler.d.ts +3 -2
  60. package/services/swap-service/handler/base-handler.js +26 -42
  61. package/services/swap-service/handler/chainflip-handler.d.ts +2 -1
  62. package/services/swap-service/handler/chainflip-handler.js +4 -2
  63. package/services/swap-service/handler/hydradx-handler.d.ts +2 -1
  64. package/services/swap-service/handler/hydradx-handler.js +7 -5
  65. package/services/swap-service/index.js +7 -1
  66. package/services/swap-service/utils.d.ts +2 -4
  67. package/services/swap-service/utils.js +7 -47
  68. package/services/transaction-service/index.d.ts +1 -1
  69. package/services/transaction-service/index.js +30 -119
  70. package/services/transaction-service/types.d.ts +1 -0
  71. package/types/balance/index.d.ts +6 -10
  72. package/types/yield/info/pallet.d.ts +0 -6
@@ -3,29 +3,27 @@
3
3
 
4
4
  import { Common } from '@ethereumjs/common';
5
5
  import { LegacyTransaction } from '@ethereumjs/tx';
6
- import { _AssetType } from '@subwallet/chain-list/types';
7
6
  import { TransactionError } from '@subwallet/extension-base/background/errors/TransactionError';
8
7
  import { withErrorLog } from '@subwallet/extension-base/background/handlers/helpers';
9
8
  import { createSubscription } from '@subwallet/extension-base/background/handlers/subscriptions';
10
- import { AccountExternalErrorCode, BasicTxErrorType, BasicTxWarningCode, CampaignDataType, ChainType, ExternalRequestPromiseStatus, ExtrinsicType, MantaPayEnableMessage, StakingTxErrorType, StakingType, TransferTxErrorType } from '@subwallet/extension-base/background/KoniTypes';
11
- import { TransactionWarning } from '@subwallet/extension-base/background/warnings/TransactionWarning';
12
- import { ALL_ACCOUNT_KEY, ALL_GENESIS_HASH, LATEST_SESSION, XCM_FEE_RATIO, XCM_MIN_AMOUNT_RATIO } from '@subwallet/extension-base/constants';
9
+ import { AccountExternalErrorCode, BasicTxErrorType, CampaignDataType, ChainType, ExternalRequestPromiseStatus, ExtrinsicType, MantaPayEnableMessage, StakingTxErrorType, StakingType } from '@subwallet/extension-base/background/KoniTypes';
10
+ import { ALL_ACCOUNT_KEY, ALL_GENESIS_HASH, LATEST_SESSION, XCM_FEE_RATIO } from '@subwallet/extension-base/constants';
11
+ import { additionalValidateTransfer, additionalValidateXcmTransfer, validateTransferRequest, validateXcmTransferRequest } from '@subwallet/extension-base/core/logic-validation/transfer';
13
12
  import { ALLOWED_PATH } from '@subwallet/extension-base/defaults';
14
13
  import { resolveAzeroAddressToDomain, resolveAzeroDomainToAddress } from '@subwallet/extension-base/koni/api/dotsama/domain';
15
14
  import { parseSubstrateTransaction } from '@subwallet/extension-base/koni/api/dotsama/parseTransaction';
16
- import { checkReferenceCount, checkSupportTransfer, createTransferExtrinsic } from '@subwallet/extension-base/koni/api/dotsama/transfer';
15
+ import { checkReferenceCount, checkSupportTransfer, createTransferExtrinsic, getTransferMockTxFee } from '@subwallet/extension-base/koni/api/dotsama/transfer';
17
16
  import { getNftTransferExtrinsic, isRecipientSelf } from '@subwallet/extension-base/koni/api/nft/transfer';
18
17
  import { getBondingExtrinsic, getCancelWithdrawalExtrinsic, getClaimRewardExtrinsic, getNominationPoolsInfo, getUnbondingExtrinsic, getValidatorsInfo, validateBondingCondition, validateUnbondingCondition } from '@subwallet/extension-base/koni/api/staking/bonding';
19
18
  import { getTuringCancelCompoundingExtrinsic, getTuringCompoundExtrinsic } from '@subwallet/extension-base/koni/api/staking/bonding/paraChain';
20
19
  import { getPoolingBondingExtrinsic, getPoolingUnbondingExtrinsic, validatePoolBondingCondition, validateRelayUnbondingCondition } from '@subwallet/extension-base/koni/api/staking/bonding/relayChain';
21
20
  import { getERC20TransactionObject, getERC721Transaction, getEVMTransactionObject } from '@subwallet/extension-base/koni/api/tokens/evm/transfer';
22
21
  import { getPSP34TransferExtrinsic } from '@subwallet/extension-base/koni/api/tokens/wasm';
23
- import { createXcmExtrinsic } from '@subwallet/extension-base/koni/api/xcm';
22
+ import { createXcmExtrinsic, getXcmMockTxFee } from '@subwallet/extension-base/koni/api/xcm';
24
23
  import { YIELD_EXTRINSIC_TYPES } from '@subwallet/extension-base/koni/api/yield/helper/utils';
25
24
  import { _API_OPTIONS_CHAIN_GROUP, _DEFAULT_MANTA_ZK_CHAIN, _MANTA_ZK_CHAIN_GROUP, _ZK_ASSET_PREFIX } from '@subwallet/extension-base/services/chain-service/constants';
26
25
  import { _ChainConnectionStatus } from '@subwallet/extension-base/services/chain-service/types';
27
- import { _getChainNativeTokenBasicInfo, _getContractAddressOfToken, _getEvmChainId, _getSubstrateGenesisHash, _getTokenMinAmount, _isAssetSmartContractNft, _isChainEvmCompatible, _isCustomAsset, _isLocalToken, _isMantaZkAsset, _isNativeToken, _isTokenEvmSmartContract, _isTokenTransferredByEvm } from '@subwallet/extension-base/services/chain-service/utils';
28
- import { calculateGasFeeParams } from '@subwallet/extension-base/services/fee-service/utils';
26
+ import { _getAssetDecimals, _getAssetSymbol, _getChainNativeTokenBasicInfo, _getContractAddressOfToken, _getEvmChainId, _getSubstrateGenesisHash, _getTokenMinAmount, _isAssetSmartContractNft, _isChainEvmCompatible, _isCustomAsset, _isLocalToken, _isMantaZkAsset, _isNativeToken, _isTokenEvmSmartContract, _isTokenTransferredByEvm } from '@subwallet/extension-base/services/chain-service/utils';
29
27
  import { EXTENSION_REQUEST_URL } from '@subwallet/extension-base/services/request-service/constants';
30
28
  import { DEFAULT_AUTO_LOCK_TIME } from '@subwallet/extension-base/services/setting-service/constants';
31
29
  import { WALLET_CONNECT_EIP155_NAMESPACE } from '@subwallet/extension-base/services/wallet-connect-service/constants';
@@ -35,15 +33,14 @@ import { AccountsStore } from '@subwallet/extension-base/stores';
35
33
  import { YieldPoolType } from '@subwallet/extension-base/types';
36
34
  import { BN_ZERO, convertSubjectInfoToAddresses, createTransactionFromRLP, isSameAddress, MODULE_SUPPORT, reformatAddress, signatureToHex, uniqueStringArray } from '@subwallet/extension-base/utils';
37
35
  import { parseContractInput, parseEvmRlp } from '@subwallet/extension-base/utils/eth/parseTransaction';
38
- import { balanceFormatter, formatNumber } from '@subwallet/extension-base/utils/number';
39
36
  import { createPair } from '@subwallet/keyring';
40
37
  import { keyring } from '@subwallet/ui-keyring';
41
38
  import { getSdkError } from '@walletconnect/utils';
42
39
  import BigN from 'bignumber.js';
43
40
  import { t } from 'i18next';
44
41
  import { TypeRegistry } from '@polkadot/types';
45
- import { assert, BN, hexStripPrefix, hexToU8a, isAscii, isHex, u8aToHex, u8aToString } from '@polkadot/util';
46
- import { addressToEvm, base64Decode, decodeAddress, isAddress, isEthereumAddress, jsonDecrypt, keyExtractSuri, mnemonicGenerate, mnemonicValidate } from '@polkadot/util-crypto';
42
+ import { assert, hexStripPrefix, hexToU8a, isAscii, isHex, u8aToHex, u8aToString } from '@polkadot/util';
43
+ import { base64Decode, decodeAddress, isAddress, isEthereumAddress, jsonDecrypt, keyExtractSuri, mnemonicGenerate, mnemonicValidate } from '@polkadot/util-crypto';
47
44
  const ETH_DERIVE_DEFAULT = '/m/44\'/60\'/0\'/0/0';
48
45
  function getSuri(seed, type) {
49
46
  return type === 'ethereum' ? `${seed}${ETH_DERIVE_DEFAULT}` : seed;
@@ -1542,39 +1539,6 @@ export default class KoniExtension {
1542
1539
  items: subscribeHistoriesResponse.value
1543
1540
  };
1544
1541
  }
1545
-
1546
- // Save address to contact
1547
- // private addContact (to: string) {
1548
- // const toAddress = reformatAddress(to);
1549
- // const account = keyring.getAccount(toAddress);
1550
- // const contact = keyring.getAddress(toAddress);
1551
- //
1552
- // if (!account && (!contact || contact.meta.isRecent)) {
1553
- // keyring.saveAddress(toAddress, {});
1554
- // }
1555
- // }
1556
-
1557
- validateTransfer(tokenSlug, from, to, value, transferAll) {
1558
- const errors = [];
1559
- const keypair = keyring.getPair(from);
1560
- let transferValue;
1561
- if (!transferAll) {
1562
- if (value === undefined) {
1563
- errors.push(new TransactionError(BasicTxErrorType.INVALID_PARAMS, t('Transfer amount is required')));
1564
- }
1565
- if (value) {
1566
- transferValue = new BN(value);
1567
- }
1568
- }
1569
- const tokenInfo = this.#koniState.getAssetBySlug(tokenSlug);
1570
- if (!tokenInfo) {
1571
- errors.push(new TransactionError(BasicTxErrorType.INVALID_PARAMS, t('Not found token from registry')));
1572
- }
1573
- if (isEthereumAddress(from) && isEthereumAddress(to) && _isTokenEvmSmartContract(tokenInfo) && _getContractAddressOfToken(tokenInfo).length === 0) {
1574
- errors.push(new TransactionError(BasicTxErrorType.INVALID_PARAMS, t('Not found ERC20 address for this token')));
1575
- }
1576
- return [errors, keypair, transferValue, tokenInfo];
1577
- }
1578
1542
  async makeTransfer(inputData) {
1579
1543
  const {
1580
1544
  from,
@@ -1584,45 +1548,41 @@ export default class KoniExtension {
1584
1548
  transferAll,
1585
1549
  value
1586
1550
  } = inputData;
1587
- const [errors,,, tokenInfo] = this.validateTransfer(tokenSlug, from, to, value, transferAll);
1551
+ const transferTokenInfo = this.#koniState.chainService.getAssetBySlug(tokenSlug);
1552
+ const [errors,,] = validateTransferRequest(transferTokenInfo, from, to, value, transferAll);
1588
1553
  const warnings = [];
1589
1554
  const evmApiMap = this.#koniState.getEvmApiMap();
1590
1555
  const chainInfo = this.#koniState.getChainInfo(networkKey);
1591
1556
  const nativeTokenInfo = this.#koniState.getNativeTokenInfo(networkKey);
1592
1557
  const nativeTokenSlug = nativeTokenInfo.slug;
1593
1558
  const isTransferNativeToken = nativeTokenSlug === tokenSlug;
1559
+ const extrinsicType = isTransferNativeToken ? ExtrinsicType.TRANSFER_BALANCE : ExtrinsicType.TRANSFER_TOKEN;
1594
1560
  let chainType = ChainType.SUBSTRATE;
1595
- const tokenBaseAmount = {
1596
- value: '0',
1597
- symbol: tokenInfo.symbol,
1598
- decimals: tokenInfo.decimals || 0
1599
- };
1600
1561
  const transferAmount = {
1601
- ...tokenBaseAmount
1562
+ value: '0',
1563
+ symbol: _getAssetSymbol(transferTokenInfo),
1564
+ decimals: _getAssetDecimals(transferTokenInfo)
1602
1565
  };
1603
1566
  let transaction;
1604
-
1605
- // Get native token amount
1606
- const freeBalance = await this.getAddressFreeBalance({
1567
+ const transferTokenAvailable = await this.getAddressTransferableBalance({
1607
1568
  address: from,
1608
1569
  networkKey,
1609
- token: tokenSlug
1570
+ token: tokenSlug,
1571
+ extrinsicType
1610
1572
  });
1611
1573
  try {
1612
- if (isEthereumAddress(from) && isEthereumAddress(to) && _isTokenTransferredByEvm(tokenInfo)) {
1613
- // TODO: review this
1574
+ if (isEthereumAddress(from) && isEthereumAddress(to) && _isTokenTransferredByEvm(transferTokenInfo)) {
1614
1575
  chainType = ChainType.EVM;
1615
- const txVal = transferAll ? freeBalance.value : value || '0';
1576
+ const txVal = transferAll ? transferTokenAvailable.value : value || '0';
1616
1577
  const evmApi = evmApiMap[networkKey];
1617
1578
 
1618
1579
  // Estimate with EVM API
1619
- if (_isTokenEvmSmartContract(tokenInfo) || _isLocalToken(tokenInfo)) {
1620
- [transaction, transferAmount.value] = await getERC20TransactionObject(_getContractAddressOfToken(tokenInfo), chainInfo, from, to, txVal, !!transferAll, evmApi);
1580
+ if (_isTokenEvmSmartContract(transferTokenInfo) || _isLocalToken(transferTokenInfo)) {
1581
+ [transaction, transferAmount.value] = await getERC20TransactionObject(_getContractAddressOfToken(transferTokenInfo), chainInfo, from, to, txVal, !!transferAll, evmApi);
1621
1582
  } else {
1622
1583
  [transaction, transferAmount.value] = await getEVMTransactionObject(chainInfo, from, to, txVal, !!transferAll, evmApi);
1623
1584
  }
1624
- } else if (_isMantaZkAsset(tokenInfo)) {
1625
- // TODO
1585
+ } else if (_isMantaZkAsset(transferTokenInfo)) {
1626
1586
  transaction = undefined;
1627
1587
  transferAmount.value = '0';
1628
1588
  } else {
@@ -1632,7 +1592,7 @@ export default class KoniExtension {
1632
1592
  value: value || '0',
1633
1593
  from: from,
1634
1594
  networkKey,
1635
- tokenInfo,
1595
+ tokenInfo: transferTokenInfo,
1636
1596
  to: to,
1637
1597
  substrateApi
1638
1598
  });
@@ -1645,46 +1605,33 @@ export default class KoniExtension {
1645
1605
  throw error;
1646
1606
  }
1647
1607
  const transferNativeAmount = isTransferNativeToken ? transferAmount.value : '0';
1648
-
1649
- // this.addContact(to);
1650
-
1651
1608
  const additionalValidator = async inputTransaction => {
1652
- const minAmount = tokenInfo.minAmount || '0';
1609
+ let senderTransferTokenTransferable;
1653
1610
 
1654
1611
  // Check ed for sender
1655
1612
  if (!isTransferNativeToken) {
1656
1613
  const {
1657
- value: balance
1658
- } = await this.getAddressFreeBalance({
1614
+ value
1615
+ } = await this.getAddressTransferableBalance({
1659
1616
  address: from,
1660
1617
  networkKey,
1661
- token: tokenSlug
1618
+ token: tokenSlug,
1619
+ extrinsicType
1662
1620
  });
1663
- if (new BigN(balance).minus(transferAmount.value).lt(minAmount)) {
1664
- inputTransaction.warnings.push(new TransactionWarning(BasicTxWarningCode.NOT_ENOUGH_EXISTENTIAL_DEPOSIT));
1665
- }
1621
+ senderTransferTokenTransferable = value;
1666
1622
  }
1667
1623
  const {
1668
- value: receiverBalance
1669
- } = await this.getAddressFreeBalance({
1624
+ value: receiverTransferTokenTransferable
1625
+ } = await this.getAddressTransferableBalance({
1670
1626
  address: to,
1671
1627
  networkKey,
1672
- token: tokenSlug
1673
- });
1628
+ token: tokenSlug,
1629
+ extrinsicType
1630
+ }); // todo: shouldn't be just transferable, locked also counts
1674
1631
 
1675
- // Check ed for receiver
1676
- if (new BigN(receiverBalance).plus(transferAmount.value).lt(minAmount)) {
1677
- const atLeast = new BigN(minAmount).minus(receiverBalance).plus((tokenInfo.decimals || 0) === 0 ? 0 : 1);
1678
- const atLeastStr = formatNumber(atLeast, tokenInfo.decimals || 0, balanceFormatter, {
1679
- maxNumberFormat: tokenInfo.decimals || 6
1680
- });
1681
- inputTransaction.errors.push(new TransactionError(TransferTxErrorType.RECEIVER_NOT_ENOUGH_EXISTENTIAL_DEPOSIT, t('You must transfer at least {{amount}} {{symbol}} to keep the destination account alive', {
1682
- replace: {
1683
- amount: atLeastStr,
1684
- symbol: tokenInfo.symbol
1685
- }
1686
- })));
1687
- }
1632
+ const [warning, error] = additionalValidateTransfer(transferTokenInfo, extrinsicType, receiverTransferTokenTransferable, transferAmount.value, senderTransferTokenTransferable);
1633
+ warning && inputTransaction.warnings.push(warning);
1634
+ error && inputTransaction.errors.push(error);
1688
1635
  };
1689
1636
  return this.#koniState.transactionService.handleTransaction({
1690
1637
  errors,
@@ -1695,24 +1642,13 @@ export default class KoniExtension {
1695
1642
  transferNativeAmount,
1696
1643
  transaction,
1697
1644
  data: inputData,
1698
- extrinsicType: isTransferNativeToken ? ExtrinsicType.TRANSFER_BALANCE : ExtrinsicType.TRANSFER_TOKEN,
1645
+ extrinsicType,
1699
1646
  ignoreWarnings: transferAll,
1700
1647
  isTransferAll: isTransferNativeToken ? transferAll : false,
1701
1648
  edAsWarning: isTransferNativeToken,
1702
1649
  additionalValidator: additionalValidator
1703
1650
  });
1704
1651
  }
1705
- validateCrossChainTransfer(destinationNetworkKey, sendingTokenSlug, sender, sendingValue) {
1706
- const errors = [];
1707
- const keypair = keyring.getPair(sender);
1708
- const transferValue = new BN(sendingValue);
1709
- const originTokenInfo = this.#koniState.getAssetBySlug(sendingTokenSlug);
1710
- const destinationTokenInfo = this.#koniState.getXcmEqualAssetByChain(destinationNetworkKey, sendingTokenSlug);
1711
- if (!destinationTokenInfo) {
1712
- errors.push(new TransactionError(TransferTxErrorType.INVALID_TOKEN, t('Not found token from registry')));
1713
- }
1714
- return [errors, keypair, transferValue, originTokenInfo, destinationTokenInfo];
1715
- }
1716
1652
  async makeCrossChainTransfer(inputData) {
1717
1653
  const {
1718
1654
  destinationNetworkKey,
@@ -1722,7 +1658,9 @@ export default class KoniExtension {
1722
1658
  tokenSlug,
1723
1659
  value
1724
1660
  } = inputData;
1725
- const [errors, fromKeyPair,, originTokenInfo, destinationTokenInfo] = this.validateCrossChainTransfer(destinationNetworkKey, tokenSlug, from, value);
1661
+ const originTokenInfo = this.#koniState.getAssetBySlug(tokenSlug);
1662
+ const destinationTokenInfo = this.#koniState.getXcmEqualAssetByChain(destinationNetworkKey, tokenSlug);
1663
+ const [errors, fromKeyPair] = validateXcmTransferRequest(destinationTokenInfo, from, value);
1726
1664
  let extrinsic = null;
1727
1665
  if (errors.length > 0) {
1728
1666
  return this.#koniState.transactionService.generateBeforeHandleResponseErrors(errors);
@@ -1741,37 +1679,16 @@ export default class KoniExtension {
1741
1679
  substrateApi
1742
1680
  });
1743
1681
  additionalValidator = async inputTransaction => {
1744
- const destMinAmount = destinationTokenInfo.minAmount || '0';
1745
- const atLeast = new BigN(destMinAmount).multipliedBy(XCM_MIN_AMOUNT_RATIO);
1746
-
1747
- // Check ed for receiver
1748
- if (new BigN(value).lt(atLeast)) {
1749
- const atLeastStr = formatNumber(atLeast, destinationTokenInfo.decimals || 0, balanceFormatter, {
1750
- maxNumberFormat: destinationTokenInfo.decimals || 6
1751
- });
1752
- inputTransaction.errors.push(new TransactionError(TransferTxErrorType.RECEIVER_NOT_ENOUGH_EXISTENTIAL_DEPOSIT, t('You must transfer at least {{amount}} {{symbol}} to keep the destination account alive', {
1753
- replace: {
1754
- amount: atLeastStr,
1755
- symbol: originTokenInfo.symbol
1756
- }
1757
- })));
1758
- }
1759
- const srcMinAmount = originTokenInfo.minAmount || '0';
1760
- const isTransferNativeToken = originTokenInfo.assetType === _AssetType.NATIVE;
1761
-
1762
- // Check ed for sender
1763
- if (!isTransferNativeToken) {
1764
- const {
1765
- value: balance
1766
- } = await this.getAddressFreeBalance({
1767
- address: from,
1768
- networkKey: originNetworkKey,
1769
- token: originTokenInfo.slug
1770
- });
1771
- if (new BigN(balance).minus(value).lt(srcMinAmount)) {
1772
- inputTransaction.warnings.push(new TransactionWarning(BasicTxWarningCode.NOT_ENOUGH_EXISTENTIAL_DEPOSIT));
1773
- }
1774
- }
1682
+ const {
1683
+ value: senderTransferable
1684
+ } = await this.getAddressTransferableBalance({
1685
+ address: from,
1686
+ networkKey: originNetworkKey,
1687
+ token: originTokenInfo.slug
1688
+ });
1689
+ const [warning, error] = additionalValidateXcmTransfer(originTokenInfo, destinationTokenInfo, value, senderTransferable);
1690
+ error && inputTransaction.errors.push(error);
1691
+ warning && inputTransaction.warnings.push(warning);
1775
1692
  };
1776
1693
  eventsHandler = eventEmitter => {
1777
1694
  eventEmitter.on('send', () => {
@@ -1790,9 +1707,6 @@ export default class KoniExtension {
1790
1707
  });
1791
1708
  };
1792
1709
  }
1793
-
1794
- // this.addContact(to);
1795
-
1796
1710
  return await this.#koniState.transactionService.handleTransaction({
1797
1711
  url: EXTENSION_REQUEST_URL,
1798
1712
  address: from,
@@ -1896,8 +1810,9 @@ export default class KoniExtension {
1896
1810
  async validateCustomAsset(data) {
1897
1811
  return await this.#koniState.validateCustomAsset(data);
1898
1812
  }
1899
- async getAddressFreeBalance({
1813
+ async getAddressTransferableBalance({
1900
1814
  address,
1815
+ extrinsicType,
1901
1816
  networkKey,
1902
1817
  token
1903
1818
  }) {
@@ -1907,100 +1822,75 @@ export default class KoniExtension {
1907
1822
  return await this.#koniState.getMantaPayZkBalance(address, tokenInfo);
1908
1823
  }
1909
1824
  }
1910
- return await this.#koniState.balanceService.getTokenFreeBalance(address, networkKey, token);
1825
+ return await this.#koniState.balanceService.getTransferableBalance(address, networkKey, token, extrinsicType);
1911
1826
  }
1912
- async transferGetMaxTransferable({
1827
+ async getMaxTransferable({
1913
1828
  address,
1914
1829
  destChain,
1915
1830
  isXcmTransfer,
1916
1831
  networkKey,
1917
1832
  token
1918
1833
  }) {
1919
- const freeBalance = await this.getAddressFreeBalance({
1920
- address,
1921
- networkKey,
1922
- token
1923
- });
1924
1834
  const tokenInfo = token ? this.#koniState.chainService.getAssetBySlug(token) : this.#koniState.chainService.getNativeTokenInfo(networkKey);
1925
1835
  if (!_isNativeToken(tokenInfo)) {
1926
- return freeBalance;
1836
+ return await this.getAddressTransferableBalance({
1837
+ extrinsicType: ExtrinsicType.TRANSFER_TOKEN,
1838
+ address,
1839
+ networkKey,
1840
+ token
1841
+ });
1927
1842
  } else {
1928
- const substrateApi = this.#koniState.chainService.getSubstrateApi(networkKey);
1929
- let estimatedFee;
1930
- let maxTransferable = new BigN(freeBalance.value);
1931
- try {
1932
- if (isXcmTransfer) {
1933
- const chainInfoMap = this.#koniState.chainService.getChainInfoMap();
1934
- const destinationTokenInfo = this.#koniState.getXcmEqualAssetByChain(destChain, tokenInfo.slug);
1935
- if (!destinationTokenInfo) {
1936
- estimatedFee = '0';
1937
- } else {
1938
- maxTransferable = maxTransferable.minus(new BigN(tokenInfo.minAmount || '0').multipliedBy(XCM_MIN_AMOUNT_RATIO));
1939
- const desChainInfo = chainInfoMap[destChain];
1940
- const orgChainInfo = chainInfoMap[networkKey];
1941
- const recipient = !isEthereumAddress(address) && _isChainEvmCompatible(desChainInfo) && !_isChainEvmCompatible(orgChainInfo) ? u8aToHex(addressToEvm(address)) : address;
1942
- const mockTx = await createXcmExtrinsic({
1943
- chainInfoMap,
1944
- destinationTokenInfo,
1945
- originTokenInfo: tokenInfo,
1946
- recipient: recipient,
1947
- sendingValue: '1000000000000000000',
1948
- substrateApi
1949
- });
1950
- try {
1951
- var _paymentInfo$partialF;
1952
- const paymentInfo = await mockTx.paymentInfo(address);
1953
- estimatedFee = (paymentInfo === null || paymentInfo === void 0 ? void 0 : (_paymentInfo$partialF = paymentInfo.partialFee) === null || _paymentInfo$partialF === void 0 ? void 0 : _paymentInfo$partialF.toString()) || '0';
1954
- } catch (e) {
1955
- estimatedFee = tokenInfo.minAmount || '0';
1956
- }
1957
- }
1958
- } else {
1959
- const chainInfo = this.#koniState.chainService.getChainInfoByKey(networkKey);
1960
- if (_isChainEvmCompatible(chainInfo) && _isTokenTransferredByEvm(tokenInfo)) {
1961
- const web3 = this.#koniState.chainService.getEvmApi(networkKey);
1962
- const transaction = {
1963
- value: 0,
1964
- to: '0x0000000000000000000000000000000000000000',
1965
- // null address
1966
- from: address
1967
- };
1968
- const gasLimit = await web3.api.eth.estimateGas(transaction);
1969
- const priority = await calculateGasFeeParams(web3, networkKey);
1970
- if (priority.baseGasFee) {
1971
- const maxFee = priority.maxFeePerGas;
1972
- estimatedFee = maxFee.multipliedBy(gasLimit).toFixed(0);
1973
- } else {
1974
- estimatedFee = new BigN(priority.gasPrice).multipliedBy(gasLimit).toFixed(0);
1975
- }
1976
- } else {
1977
- var _paymentInfo$partialF2;
1978
- const [mockTx] = await createTransferExtrinsic({
1979
- from: address,
1980
- networkKey,
1981
- substrateApi,
1982
- to: address,
1983
- tokenInfo,
1984
- transferAll: true,
1985
- value: '1000000000000000000'
1986
- });
1987
- const paymentInfo = await (mockTx === null || mockTx === void 0 ? void 0 : mockTx.paymentInfo(address));
1988
- estimatedFee = (paymentInfo === null || paymentInfo === void 0 ? void 0 : (_paymentInfo$partialF2 = paymentInfo.partialFee) === null || _paymentInfo$partialF2 === void 0 ? void 0 : _paymentInfo$partialF2.toString()) || '0';
1989
- }
1990
- }
1991
- } catch (e) {
1992
- estimatedFee = '0';
1993
- console.warn('Unable to estimate fee', e);
1843
+ let maxTransferable;
1844
+ if (isXcmTransfer) {
1845
+ maxTransferable = await this.getXcmMaxTransferable(tokenInfo, destChain, address);
1846
+ } else {
1847
+ // regular transfer with native token
1848
+ maxTransferable = await this.getNativeTokenMaxTransferable(tokenInfo, networkKey, address);
1994
1849
  }
1995
- maxTransferable = maxTransferable.minus(new BigN(estimatedFee).multipliedBy(isXcmTransfer ? XCM_FEE_RATIO : 1));
1996
1850
  return {
1997
- ...freeBalance,
1998
- value: maxTransferable.gt(BN_ZERO) ? maxTransferable.toFixed(0) || '0' : '0'
1851
+ value: maxTransferable.gt(BN_ZERO) ? maxTransferable.toFixed(0) || '0' : '0',
1852
+ decimals: tokenInfo.decimals,
1853
+ symbol: tokenInfo.symbol
1999
1854
  };
2000
1855
  }
2001
1856
  }
2002
- async subscribeAddressFreeBalance({
1857
+ async getXcmMaxTransferable(originTokenInfo, destChain, address) {
1858
+ const substrateApi = this.#koniState.chainService.getSubstrateApi(originTokenInfo.originChain);
1859
+ const chainInfoMap = this.#koniState.chainService.getChainInfoMap();
1860
+ const destinationTokenInfo = this.#koniState.getXcmEqualAssetByChain(destChain, originTokenInfo.slug);
1861
+ if (destinationTokenInfo) {
1862
+ const [bnMockFee, {
1863
+ value
1864
+ }] = await Promise.all([getXcmMockTxFee(substrateApi, chainInfoMap, address, originTokenInfo, destinationTokenInfo), this.getAddressTransferableBalance({
1865
+ extrinsicType: ExtrinsicType.TRANSFER_XCM,
1866
+ address,
1867
+ networkKey: originTokenInfo.originChain,
1868
+ token: originTokenInfo.slug
1869
+ })]);
1870
+ const bnMaxTransferable = new BigN(value);
1871
+ const estimatedFee = bnMockFee.multipliedBy(XCM_FEE_RATIO); // multiply by weight to account for destination chain fee
1872
+
1873
+ return bnMaxTransferable.minus(estimatedFee);
1874
+ }
1875
+ return new BigN(0);
1876
+ }
1877
+ async getNativeTokenMaxTransferable(tokenInfo, networkKey, address) {
1878
+ const chainInfo = this.#koniState.chainService.getChainInfoByKey(networkKey);
1879
+ const api = _isChainEvmCompatible(chainInfo) && _isTokenTransferredByEvm(tokenInfo) ? this.#koniState.chainService.getEvmApi(networkKey) : this.#koniState.chainService.getSubstrateApi(networkKey);
1880
+ const [mockTxFee, {
1881
+ value
1882
+ }] = await Promise.all([getTransferMockTxFee(address, chainInfo, tokenInfo, api), this.getAddressTransferableBalance({
1883
+ extrinsicType: ExtrinsicType.TRANSFER_BALANCE,
1884
+ address,
1885
+ networkKey,
1886
+ token: tokenInfo.slug
1887
+ })]);
1888
+ const bnMaxTransferable = new BigN(value);
1889
+ return bnMaxTransferable.minus(mockTxFee);
1890
+ }
1891
+ async subscribeAddressTransferableBalance({
2003
1892
  address,
1893
+ extrinsicType,
2004
1894
  networkKey,
2005
1895
  token
2006
1896
  }, id, port) {
@@ -2015,7 +1905,7 @@ export default class KoniExtension {
2015
1905
  // eslint-disable-next-line node/no-callback-literal
2016
1906
  cb(convertData(data));
2017
1907
  };
2018
- const [unsub, currentFreeBalance] = await this.#koniState.balanceService.subscribeTokenFreeBalance(address, networkKey, token, _cb);
1908
+ const [unsub, currentFreeBalance] = await this.#koniState.balanceService.subscribeTransferableBalance(address, networkKey, token, extrinsicType, _cb);
2019
1909
  this.createUnsubscriptionHandle(id, unsub);
2020
1910
  port.onDisconnect.addListener(() => {
2021
1911
  this.cancelSubscription(id);
@@ -4414,13 +4304,13 @@ export default class KoniExtension {
4414
4304
  case 'pri(transfer.getExistentialDeposit)':
4415
4305
  return this.transferGetExistentialDeposit(request);
4416
4306
  case 'pri(transfer.getMaxTransferable)':
4417
- return this.transferGetMaxTransferable(request);
4307
+ return this.getMaxTransferable(request);
4418
4308
  case 'pri(transfer.subscribeMaxTransferable)':
4419
- return this.transferGetMaxTransferable(request);
4309
+ return this.getMaxTransferable(request);
4420
4310
  case 'pri(freeBalance.get)':
4421
- return this.getAddressFreeBalance(request);
4311
+ return this.getAddressTransferableBalance(request);
4422
4312
  case 'pri(freeBalance.subscribe)':
4423
- return this.subscribeAddressFreeBalance(request, id, port);
4313
+ return this.subscribeAddressTransferableBalance(request, id, port);
4424
4314
  case 'pri(subscription.cancel)':
4425
4315
  return this.cancelSubscription(request);
4426
4316
  case 'pri(chainService.recoverSubstrateApi)':
package/package.json CHANGED
@@ -17,7 +17,7 @@
17
17
  "./cjs/detectPackage.js"
18
18
  ],
19
19
  "type": "module",
20
- "version": "1.2.3-0",
20
+ "version": "1.2.3-1",
21
21
  "main": "./cjs/index.js",
22
22
  "module": "./index.js",
23
23
  "types": "./index.d.ts",
@@ -129,6 +129,31 @@
129
129
  "require": "./cjs/constants/storage.js",
130
130
  "default": "./constants/storage.js"
131
131
  },
132
+ "./core/logic-validation/earning": {
133
+ "types": "./core/logic-validation/earning.d.ts",
134
+ "require": "./cjs/core/logic-validation/earning.js",
135
+ "default": "./core/logic-validation/earning.js"
136
+ },
137
+ "./core/logic-validation/swap": {
138
+ "types": "./core/logic-validation/swap.d.ts",
139
+ "require": "./cjs/core/logic-validation/swap.js",
140
+ "default": "./core/logic-validation/swap.js"
141
+ },
142
+ "./core/logic-validation/transfer": {
143
+ "types": "./core/logic-validation/transfer.d.ts",
144
+ "require": "./cjs/core/logic-validation/transfer.js",
145
+ "default": "./core/logic-validation/transfer.js"
146
+ },
147
+ "./core/substrate/nominationpools-pallet": {
148
+ "types": "./core/substrate/nominationpools-pallet.d.ts",
149
+ "require": "./cjs/core/substrate/nominationpools-pallet.js",
150
+ "default": "./core/substrate/nominationpools-pallet.js"
151
+ },
152
+ "./core/substrate/system-pallet": {
153
+ "types": "./core/substrate/system-pallet.d.ts",
154
+ "require": "./cjs/core/substrate/system-pallet.js",
155
+ "default": "./core/substrate/system-pallet.js"
156
+ },
132
157
  "./defaults": {
133
158
  "types": "./defaults.d.ts",
134
159
  "require": "./cjs/defaults.js",
@@ -1891,17 +1916,17 @@
1891
1916
  "@reduxjs/toolkit": "^1.9.1",
1892
1917
  "@sora-substrate/type-definitions": "^1.17.7",
1893
1918
  "@substrate/connect": "^0.8.9",
1894
- "@subwallet/chain-list": "0.2.65",
1895
- "@subwallet/extension-base": "^1.2.3-0",
1896
- "@subwallet/extension-chains": "^1.2.3-0",
1897
- "@subwallet/extension-dapp": "^1.2.3-0",
1898
- "@subwallet/extension-inject": "^1.2.3-0",
1919
+ "@subwallet/chain-list": "0.2.66",
1920
+ "@subwallet/extension-base": "^1.2.3-1",
1921
+ "@subwallet/extension-chains": "^1.2.3-1",
1922
+ "@subwallet/extension-dapp": "^1.2.3-1",
1923
+ "@subwallet/extension-inject": "^1.2.3-1",
1899
1924
  "@subwallet/keyring": "^0.1.5",
1900
1925
  "@subwallet/ui-keyring": "^0.1.5",
1901
1926
  "@walletconnect/keyvaluestorage": "^1.1.1",
1902
- "@walletconnect/sign-client": "^2.11.3",
1903
- "@walletconnect/types": "^2.11.3",
1904
- "@walletconnect/utils": "^2.11.3",
1927
+ "@walletconnect/sign-client": "^2.13.1",
1928
+ "@walletconnect/types": "^2.13.1",
1929
+ "@walletconnect/utils": "^2.13.1",
1905
1930
  "avail-js-sdk": "^0.2.12",
1906
1931
  "axios": "^1.6.2",
1907
1932
  "bignumber.js": "^9.1.1",
package/packageInfo.js CHANGED
@@ -7,5 +7,5 @@ export const packageInfo = {
7
7
  name: '@subwallet/extension-base',
8
8
  path: (import.meta && import.meta.url) ? new URL(import.meta.url).pathname.substring(0, new URL(import.meta.url).pathname.lastIndexOf('/') + 1) : 'auto',
9
9
  type: 'esm',
10
- version: '1.2.3-0'
10
+ version: '1.2.3-1'
11
11
  };
@@ -2,8 +2,7 @@
2
2
  // SPDX-License-Identifier: Apache-2.0
3
3
 
4
4
  import { APIItemState } from '@subwallet/extension-base/background/KoniTypes';
5
- import { sumBN } from '@subwallet/extension-base/utils';
6
- import BN from 'bn.js';
5
+ import BigN from 'bignumber.js';
7
6
 
8
7
  /**
9
8
  * Group the balance of {token} from {items} into {address}
@@ -14,33 +13,11 @@ import BN from 'bn.js';
14
13
  */
15
14
  export const groupBalance = (items, address, token) => {
16
15
  const states = items.map(item => item.state);
17
- const result = {
16
+ return {
18
17
  address,
19
18
  tokenSlug: token,
20
- free: sumBN(items.map(item => new BN(item.free))).toString(),
21
- locked: sumBN(items.map(item => new BN(item.locked))).toString(),
19
+ free: BigN.sum.apply(null, items.map(item => item.free)).toFixed(),
20
+ locked: BigN.sum.apply(null, items.map(item => item.locked)).toFixed(),
22
21
  state: states.every(item => item === APIItemState.NOT_SUPPORT) ? APIItemState.NOT_SUPPORT : states.some(item => item === APIItemState.READY) ? APIItemState.READY : APIItemState.PENDING
23
22
  };
24
- for (const item of items) {
25
- if (item.substrateInfo) {
26
- if (!result.substrateInfo) {
27
- result.substrateInfo = {
28
- ...item.substrateInfo
29
- };
30
- } else {
31
- const old = {
32
- ...result.substrateInfo
33
- };
34
- const _new = {
35
- ...item.substrateInfo
36
- };
37
- result.substrateInfo = {
38
- reserved: new BN(old.reserved || '0').add(new BN(_new.reserved || '0')).toString(),
39
- feeFrozen: new BN(old.feeFrozen || '0').add(new BN(_new.feeFrozen || '0')).toString(),
40
- miscFrozen: new BN(old.miscFrozen || '0').add(new BN(_new.miscFrozen || '0')).toString()
41
- };
42
- }
43
- }
44
- }
45
- return result;
46
23
  };
@@ -1,4 +1,5 @@
1
1
  import { _ChainAsset, _ChainInfo } from '@subwallet/chain-list/types';
2
+ import { ExtrinsicType } from '@subwallet/extension-base/background/KoniTypes';
2
3
  import { AccountJson } from '@subwallet/extension-base/background/types';
3
4
  import { _EvmApi, _SubstrateApi } from '@subwallet/extension-base/services/chain-service/types';
4
5
  import { BalanceItem } from '@subwallet/extension-base/types';
@@ -12,4 +13,4 @@ import { BalanceItem } from '@subwallet/extension-base/types';
12
13
  * @returns {AccountJson|null} - Account info or null if not found
13
14
  */
14
15
  export declare const getAccountJsonByAddress: (address: string) => AccountJson | null;
15
- export declare function subscribeBalance(addresses: string[], chains: string[], tokens: string[], _chainAssetMap: Record<string, _ChainAsset>, _chainInfoMap: Record<string, _ChainInfo>, substrateApiMap: Record<string, _SubstrateApi>, evmApiMap: Record<string, _EvmApi>, callback: (rs: BalanceItem[]) => void): () => void;
16
+ export declare function subscribeBalance(addresses: string[], chains: string[], tokens: string[], _chainAssetMap: Record<string, _ChainAsset>, _chainInfoMap: Record<string, _ChainInfo>, substrateApiMap: Record<string, _SubstrateApi>, evmApiMap: Record<string, _EvmApi>, callback: (rs: BalanceItem[]) => void, extrinsicType?: ExtrinsicType): () => void;