@subwallet/extension-base 1.0.2-2 → 1.0.2-3

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 (134) hide show
  1. package/background/KoniTypes.d.ts +46 -38
  2. package/background/KoniTypes.js +8 -8
  3. package/background/errors/TransactionError.js +25 -1
  4. package/background/types.d.ts +10 -5
  5. package/cjs/background/KoniTypes.js +8 -8
  6. package/cjs/background/errors/TransactionError.js +24 -0
  7. package/cjs/constants/index.js +8 -26
  8. package/cjs/koni/api/dotsama/balance.js +49 -224
  9. package/cjs/koni/api/dotsama/transfer.js +34 -39
  10. package/cjs/koni/api/nft/acala_nft/index.js +7 -7
  11. package/cjs/koni/api/nft/bit.country/index.js +7 -6
  12. package/cjs/koni/api/nft/evm_nft/index.js +8 -3
  13. package/cjs/koni/api/nft/index.js +3 -6
  14. package/cjs/koni/api/nft/karura_nft/index.js +7 -6
  15. package/cjs/koni/api/nft/rmrk_nft/index.js +11 -1
  16. package/cjs/koni/api/nft/statemine_nft/index.js +7 -6
  17. package/cjs/koni/api/nft/unique_nft/index.js +5 -1
  18. package/cjs/koni/api/nft/wasm_nft/index.js +170 -111
  19. package/cjs/koni/api/nft/wasm_nft/utils.js +11 -7
  20. package/cjs/koni/api/staking/bonding/amplitude.js +13 -9
  21. package/cjs/koni/api/staking/bonding/astar.js +15 -13
  22. package/cjs/koni/api/staking/bonding/index.js +22 -10
  23. package/cjs/koni/api/staking/bonding/paraChain.js +85 -2
  24. package/cjs/koni/api/staking/bonding/relayChain.js +122 -16
  25. package/cjs/koni/api/staking/bonding/utils.js +27 -8
  26. package/cjs/koni/api/tokens/wasm/index.js +5 -4
  27. package/cjs/koni/api/tokens/wasm/utils.js +63 -0
  28. package/cjs/koni/api/xcm/polkadotXcm.js +1 -1
  29. package/cjs/koni/api/xcm/utils.js +18 -13
  30. package/cjs/koni/api/xcm/xTokens.js +1 -1
  31. package/cjs/koni/api/xcm/xcmPallet.js +9 -6
  32. package/cjs/koni/background/cron.js +171 -61
  33. package/cjs/koni/background/handlers/Extension.js +382 -207
  34. package/cjs/koni/background/handlers/State.js +41 -33
  35. package/cjs/koni/background/handlers/Tabs.js +50 -17
  36. package/cjs/koni/background/subscription.js +32 -29
  37. package/cjs/packageInfo.js +1 -1
  38. package/cjs/services/chain-service/handler/SubstrateChainHandler.js +13 -8
  39. package/cjs/services/chain-service/index.js +59 -45
  40. package/cjs/services/event-service/index.js +5 -1
  41. package/cjs/services/event-service/types.js +11 -1
  42. package/cjs/services/history-service/index.js +19 -13
  43. package/cjs/services/history-service/subsquid-multi-chain-history.js +13 -10
  44. package/cjs/services/keyring-service/index.js +11 -13
  45. package/cjs/services/price-service/coingecko.js +0 -1
  46. package/cjs/services/price-service/index.js +2 -3
  47. package/cjs/services/request-service/handler/AuthRequestHandler.js +13 -7
  48. package/cjs/services/request-service/handler/EvmRequestHandler.js +8 -12
  49. package/cjs/services/request-service/index.js +14 -5
  50. package/cjs/services/storage-service/DatabaseService.js +56 -34
  51. package/cjs/services/storage-service/db-stores/Nft.js +7 -15
  52. package/cjs/services/transaction-service/event-parser/index.js +20 -48
  53. package/cjs/services/transaction-service/index.js +26 -15
  54. package/cjs/utils/address.js +10 -1
  55. package/cjs/utils/index.js +9 -15
  56. package/constants/index.d.ts +7 -13
  57. package/constants/index.js +7 -13
  58. package/koni/api/dotsama/balance.d.ts +0 -1
  59. package/koni/api/dotsama/balance.js +22 -197
  60. package/koni/api/dotsama/transfer.js +11 -16
  61. package/koni/api/nft/acala_nft/index.js +7 -7
  62. package/koni/api/nft/bit.country/index.js +7 -6
  63. package/koni/api/nft/evm_nft/index.js +7 -3
  64. package/koni/api/nft/index.d.ts +1 -2
  65. package/koni/api/nft/index.js +3 -6
  66. package/koni/api/nft/karura_nft/index.js +7 -6
  67. package/koni/api/nft/nft.d.ts +1 -0
  68. package/koni/api/nft/rmrk_nft/index.js +11 -1
  69. package/koni/api/nft/statemine_nft/index.js +7 -6
  70. package/koni/api/nft/unique_nft/index.js +5 -1
  71. package/koni/api/nft/wasm_nft/index.d.ts +0 -2
  72. package/koni/api/nft/wasm_nft/index.js +168 -109
  73. package/koni/api/nft/wasm_nft/utils.d.ts +7 -5
  74. package/koni/api/nft/wasm_nft/utils.js +7 -5
  75. package/koni/api/staking/bonding/amplitude.d.ts +0 -1
  76. package/koni/api/staking/bonding/amplitude.js +15 -10
  77. package/koni/api/staking/bonding/astar.js +8 -6
  78. package/koni/api/staking/bonding/index.d.ts +4 -1
  79. package/koni/api/staking/bonding/index.js +23 -13
  80. package/koni/api/staking/bonding/paraChain.d.ts +3 -0
  81. package/koni/api/staking/bonding/paraChain.js +86 -5
  82. package/koni/api/staking/bonding/relayChain.d.ts +5 -1
  83. package/koni/api/staking/bonding/relayChain.js +121 -18
  84. package/koni/api/staking/bonding/utils.d.ts +3 -2
  85. package/koni/api/staking/bonding/utils.js +27 -9
  86. package/koni/api/tokens/wasm/index.js +5 -4
  87. package/koni/api/tokens/wasm/utils.d.ts +6 -0
  88. package/koni/api/tokens/wasm/utils.js +54 -0
  89. package/koni/api/xcm/polkadotXcm.js +2 -2
  90. package/koni/api/xcm/utils.d.ts +5 -6
  91. package/koni/api/xcm/utils.js +15 -10
  92. package/koni/api/xcm/xTokens.js +2 -2
  93. package/koni/api/xcm/xcmPallet.js +10 -9
  94. package/koni/background/cron.d.ts +6 -1
  95. package/koni/background/cron.js +172 -62
  96. package/koni/background/handlers/Extension.d.ts +8 -3
  97. package/koni/background/handlers/Extension.js +297 -126
  98. package/koni/background/handlers/State.d.ts +5 -6
  99. package/koni/background/handlers/State.js +43 -33
  100. package/koni/background/handlers/Tabs.js +50 -17
  101. package/koni/background/subscription.js +31 -30
  102. package/package.json +18 -13
  103. package/packageInfo.js +1 -1
  104. package/services/chain-service/handler/SubstrateChainHandler.js +14 -9
  105. package/services/chain-service/helper/psp22_abi.json +1041 -881
  106. package/services/chain-service/helper/psp34_abi.json +2963 -1807
  107. package/services/chain-service/index.d.ts +3 -2
  108. package/services/chain-service/index.js +53 -40
  109. package/services/chain-service/types.d.ts +1 -0
  110. package/services/event-service/index.js +5 -1
  111. package/services/event-service/types.d.ts +5 -9
  112. package/services/event-service/types.js +4 -1
  113. package/services/history-service/index.d.ts +4 -2
  114. package/services/history-service/index.js +19 -13
  115. package/services/history-service/subsquid-multi-chain-history.js +16 -12
  116. package/services/keyring-service/index.d.ts +4 -2
  117. package/services/keyring-service/index.js +11 -13
  118. package/services/price-service/coingecko.js +0 -1
  119. package/services/price-service/index.js +2 -3
  120. package/services/request-service/handler/AuthRequestHandler.d.ts +3 -1
  121. package/services/request-service/handler/AuthRequestHandler.js +13 -7
  122. package/services/request-service/handler/EvmRequestHandler.js +8 -12
  123. package/services/request-service/index.d.ts +3 -1
  124. package/services/request-service/index.js +14 -5
  125. package/services/storage-service/DatabaseService.d.ts +1 -0
  126. package/services/storage-service/DatabaseService.js +56 -34
  127. package/services/storage-service/db-stores/Nft.d.ts +2 -2
  128. package/services/storage-service/db-stores/Nft.js +7 -14
  129. package/services/transaction-service/event-parser/index.js +21 -49
  130. package/services/transaction-service/index.js +26 -15
  131. package/utils/address.d.ts +3 -0
  132. package/utils/address.js +8 -1
  133. package/utils/index.d.ts +2 -2
  134. package/utils/index.js +7 -13
@@ -6,30 +6,31 @@ import { TransactionError } from '@subwallet/extension-base/background/errors/Tr
6
6
  import { isJsonPayload, SEED_DEFAULT_LENGTH, SEED_LENGTHS } from '@subwallet/extension-base/background/handlers/Extension';
7
7
  import { withErrorLog } from '@subwallet/extension-base/background/handlers/helpers';
8
8
  import { createSubscription } from '@subwallet/extension-base/background/handlers/subscriptions';
9
- import { AccountExternalErrorCode, BasicTxErrorType, ChainType, ExternalRequestPromiseStatus, ExtrinsicType, TransferTxErrorType } from '@subwallet/extension-base/background/KoniTypes';
9
+ import { AccountExternalErrorCode, BasicTxErrorType, ChainType, ExternalRequestPromiseStatus, ExtrinsicType, StakingType, TransferTxErrorType } from '@subwallet/extension-base/background/KoniTypes';
10
10
  import { ALL_ACCOUNT_KEY, ALL_GENESIS_HASH, DEFAULT_TIME_AUTO_LOCK } from '@subwallet/extension-base/constants';
11
11
  import { ALLOWED_PATH } from '@subwallet/extension-base/defaults';
12
12
  import { parseSubstrateTransaction } from '@subwallet/extension-base/koni/api/dotsama/parseTransaction';
13
13
  import { checkReferenceCount, checkSupportTransfer, createTransferExtrinsic } from '@subwallet/extension-base/koni/api/dotsama/transfer';
14
14
  import { getNftTransferExtrinsic, isRecipientSelf } from '@subwallet/extension-base/koni/api/nft/transfer';
15
- import { getBondingExtrinsic, getCancelWithdrawalExtrinsic, getClaimRewardExtrinsic, getNominationPoolsInfo, getUnbondingExtrinsic, getValidatorsInfo, getWithdrawalExtrinsic } from '@subwallet/extension-base/koni/api/staking/bonding';
15
+ import { getBondingExtrinsic, getCancelWithdrawalExtrinsic, getClaimRewardExtrinsic, getNominationPoolsInfo, getUnbondingExtrinsic, getValidatorsInfo, getWithdrawalExtrinsic, validateBondingCondition, validateUnbondingCondition } from '@subwallet/extension-base/koni/api/staking/bonding';
16
16
  import { getTuringCancelCompoundingExtrinsic, getTuringCompoundExtrinsic } from '@subwallet/extension-base/koni/api/staking/bonding/paraChain';
17
- import { getPoolingBondingExtrinsic, getPoolingUnbondingExtrinsic } from '@subwallet/extension-base/koni/api/staking/bonding/relayChain';
17
+ import { getPoolingBondingExtrinsic, getPoolingUnbondingExtrinsic, validatePoolBondingCondition, validateRelayUnbondingCondition } from '@subwallet/extension-base/koni/api/staking/bonding/relayChain';
18
18
  import { getERC20TransactionObject, getERC721Transaction, getEVMTransactionObject } from '@subwallet/extension-base/koni/api/tokens/evm/transfer';
19
19
  import { getPSP34TransferExtrinsic } from '@subwallet/extension-base/koni/api/tokens/wasm';
20
20
  import { createXcmExtrinsic } from '@subwallet/extension-base/koni/api/xcm';
21
21
  import { _getChainNativeTokenBasicInfo, _getContractAddressOfToken, _getEvmChainId, _getSubstrateGenesisHash, _getTokenMinAmount, _isAssetSmartContractNft, _isChainEvmCompatible, _isCustomAsset, _isLocalToken, _isNativeToken, _isTokenEvmSmartContract } from '@subwallet/extension-base/services/chain-service/utils';
22
22
  import { EXTENSION_REQUEST_URL } from '@subwallet/extension-base/services/request-service/constants';
23
+ import { reformatAddress } from '@subwallet/extension-base/utils';
24
+ import { convertSubjectInfoToAddresses } from '@subwallet/extension-base/utils/address';
23
25
  import { createTransactionFromRLP, signatureToHex } from '@subwallet/extension-base/utils/eth';
24
26
  import { parseContractInput, parseEvmRlp } from '@subwallet/extension-base/utils/eth/parseTransaction';
25
27
  import { createPair } from '@subwallet/keyring';
26
28
  import { keyring } from '@subwallet/ui-keyring';
27
- import { accounts as accountsObservable } from '@subwallet/ui-keyring/observable/accounts';
28
29
  import BigN from 'bignumber.js';
29
30
  import { Transaction } from 'ethereumjs-tx';
30
31
  import { TypeRegistry } from '@polkadot/types';
31
- import { assert, BN, hexStripPrefix, hexToU8a, isAscii, isHex, u8aToHex, u8aToString } from '@polkadot/util';
32
- import { base64Decode, isEthereumAddress, jsonDecrypt, keyExtractSuri, mnemonicGenerate, mnemonicValidate } from '@polkadot/util-crypto';
32
+ import { assert, BN, BN_ZERO, hexStripPrefix, hexToU8a, isAscii, isHex, u8aToHex, u8aToString } from '@polkadot/util';
33
+ import { base64Decode, decodeAddress, isAddress, isEthereumAddress, jsonDecrypt, keyExtractSuri, mnemonicGenerate, mnemonicValidate } from '@polkadot/util-crypto';
33
34
  const ETH_DERIVE_DEFAULT = '/m/44\'/60\'/0\'/0/0';
34
35
  function getSuri(seed, type) {
35
36
  return type === 'ethereum' ? `${seed}${ETH_DERIVE_DEFAULT}` : seed;
@@ -163,7 +164,8 @@ export default class KoniExtension {
163
164
  // FIXME This looks very much like what we have in Tabs
164
165
  accountsSubscribe(id, port) {
165
166
  const cb = createSubscription(id, port);
166
- const subscription = accountsObservable.subject.subscribe(accounts => cb(transformAccounts(accounts)));
167
+ const accountSubject = this.#koniState.keyringService.accountSubject;
168
+ const subscription = accountSubject.subscribe(accounts => cb(transformAccounts(accounts)));
167
169
  port.onDisconnect.addListener(() => {
168
170
  this.cancelSubscription(id);
169
171
  subscription.unsubscribe();
@@ -401,35 +403,37 @@ export default class KoniExtension {
401
403
  }
402
404
  async accountsGetAllWithCurrentAddress(id, port) {
403
405
  const cb = createSubscription(id, port);
404
- return await new Promise(resolve => {
405
- const subscription = accountsObservable.subject.subscribe(storedAccounts => {
406
- const transformedAccounts = transformAccounts(storedAccounts);
407
- const accounts = transformedAccounts && transformedAccounts.length ? [{
408
- ...ACCOUNT_ALL_JSON
409
- }, ...transformedAccounts] : [];
410
- const accountsWithCurrentAddress = {
411
- accounts
412
- };
413
- setTimeout(() => {
414
- const accountInfo = this.#koniState.keyringService.currentAccount;
415
- if (accountInfo) {
416
- accountsWithCurrentAddress.currentAddress = accountInfo.address;
417
- if (accountInfo.address === ALL_ACCOUNT_KEY) {
418
- accountsWithCurrentAddress.currentGenesisHash = accountInfo.currentGenesisHash;
419
- } else {
420
- const acc = accounts.find(a => a.address === accountInfo.address);
421
- accountsWithCurrentAddress.currentGenesisHash = (acc === null || acc === void 0 ? void 0 : acc.genesisHash) || ALL_GENESIS_HASH;
422
- }
423
- }
424
- resolve(accountsWithCurrentAddress);
425
- cb(accountsWithCurrentAddress);
426
- }, 300);
427
- });
428
- this.createUnsubscriptionHandle(id, subscription.unsubscribe);
429
- port.onDisconnect.addListener(() => {
430
- this.cancelSubscription(id);
431
- });
406
+ const keyringService = this.#koniState.keyringService;
407
+ await this.#koniState.eventService.waitAccountReady;
408
+ const currentAccount = keyringService.currentAccount;
409
+ const transformedAccounts = transformAccounts(keyringService.accounts);
410
+ const responseData = {
411
+ accounts: transformedAccounts !== null && transformedAccounts !== void 0 && transformedAccounts.length ? [{
412
+ ...ACCOUNT_ALL_JSON
413
+ }, ...transformedAccounts] : [],
414
+ currentAddress: currentAccount === null || currentAccount === void 0 ? void 0 : currentAccount.address,
415
+ currentGenesisHash: currentAccount === null || currentAccount === void 0 ? void 0 : currentAccount.currentGenesisHash
416
+ };
417
+ const subscriptionAccounts = keyringService.accountSubject.subscribe(storedAccounts => {
418
+ const transformedAccounts = transformAccounts(storedAccounts);
419
+ responseData.accounts = transformedAccounts !== null && transformedAccounts !== void 0 && transformedAccounts.length ? [{
420
+ ...ACCOUNT_ALL_JSON
421
+ }, ...transformedAccounts] : [];
422
+ cb(responseData);
423
+ });
424
+ const subscriptionCurrentAccount = keyringService.currentAccountSubject.subscribe(currentAccountData => {
425
+ responseData.currentAddress = currentAccountData.address;
426
+ responseData.currentGenesisHash = currentAccountData.currentGenesisHash;
427
+ cb(responseData);
428
+ });
429
+ this.createUnsubscriptionHandle(id, () => {
430
+ subscriptionAccounts.unsubscribe();
431
+ subscriptionCurrentAccount.unsubscribe();
432
+ });
433
+ port.onDisconnect.addListener(() => {
434
+ this.cancelSubscription(id);
432
435
  });
436
+ return responseData;
433
437
  }
434
438
  accountsGetAll(id, port) {
435
439
  const cb = createSubscription(id, port);
@@ -445,21 +449,66 @@ export default class KoniExtension {
445
449
  });
446
450
  return id;
447
451
  }
448
- saveRecentAccountId({
452
+ subscribeAddresses(id, port) {
453
+ const _cb = createSubscription(id, port);
454
+ const subscription = this.#koniState.keyringService.addressesSubject.subscribe(subjectInfo => {
455
+ const addresses = convertSubjectInfoToAddresses(subjectInfo);
456
+ _cb({
457
+ addresses: addresses
458
+ });
459
+ });
460
+ this.createUnsubscriptionHandle(id, subscription.unsubscribe);
461
+ port.onDisconnect.addListener(() => {
462
+ this.cancelSubscription(id);
463
+ });
464
+ const subjectInfo = this.#koniState.keyringService.addresses;
465
+ return {
466
+ addresses: convertSubjectInfoToAddresses(subjectInfo)
467
+ };
468
+ }
469
+ saveRecentAccount({
449
470
  accountId
450
471
  }) {
451
- return keyring.saveRecent(accountId);
472
+ if (isAddress(accountId)) {
473
+ const address = reformatAddress(accountId);
474
+ const account = keyring.getAccount(address);
475
+ const contact = keyring.getAddress(address);
476
+ return account || contact || {
477
+ ...keyring.saveRecent(accountId).json,
478
+ publicKey: decodeAddress(address)
479
+ };
480
+ } else {
481
+ throw Error('Invalid address');
482
+ }
483
+ }
484
+ editContactAccount({
485
+ address,
486
+ meta
487
+ }) {
488
+ if (isAddress(address)) {
489
+ const _address = reformatAddress(address);
490
+ keyring.saveAddress(_address, meta);
491
+ return true;
492
+ } else {
493
+ throw Error('Invalid address');
494
+ }
452
495
  }
453
- triggerAccountsSubscription() {
454
- const accountsSubject = accountsObservable.subject;
455
- accountsSubject.next(accountsSubject.getValue());
456
- return true;
496
+ deleteContactAccount({
497
+ address
498
+ }) {
499
+ if (isAddress(address)) {
500
+ const _address = reformatAddress(address);
501
+ keyring.forgetAddress(_address);
502
+ return true;
503
+ } else {
504
+ throw Error('Invalid address');
505
+ }
457
506
  }
458
507
  _getAuthListV2() {
508
+ const keyringService = this.#koniState.keyringService;
459
509
  return new Promise((resolve, reject) => {
460
510
  this.#koniState.getAuthorize(rs => {
461
- const accounts = accountsObservable.subject.getValue();
462
- const addressList = Object.keys(accounts);
511
+ const addressList = Object.keys(keyringService.accounts);
463
512
  const urlList = Object.keys(rs);
464
513
  if (Object.keys(rs[urlList[0]].isAllowedMap).toString() !== addressList.toString()) {
465
514
  urlList.forEach(url => {
@@ -573,7 +622,7 @@ export default class KoniExtension {
573
622
  return true;
574
623
  }
575
624
  getNonReadonlyAccounts() {
576
- const storedAccounts = accountsObservable.subject.getValue();
625
+ const storedAccounts = this.#koniState.keyringService.accounts;
577
626
  const transformedAccounts = transformAccounts(storedAccounts);
578
627
  return transformedAccounts.filter(a => !a.isReadOnly).map(a => a.address);
579
628
  }
@@ -806,8 +855,12 @@ export default class KoniExtension {
806
855
  } else {
807
856
  accountInfo.address = address;
808
857
  if (address !== ALL_ACCOUNT_KEY) {
809
- const currentKeyPair = keyring.getAccount(address);
810
- accountInfo.currentGenesisHash = (currentKeyPair === null || currentKeyPair === void 0 ? void 0 : currentKeyPair.meta.genesisHash) || ALL_GENESIS_HASH;
858
+ try {
859
+ const currentKeyPair = keyring.getPair(address);
860
+ accountInfo.currentGenesisHash = (currentKeyPair === null || currentKeyPair === void 0 ? void 0 : currentKeyPair.meta.genesisHash) || ALL_GENESIS_HASH;
861
+ } catch {
862
+ accountInfo.currentGenesisHash = ALL_GENESIS_HASH;
863
+ }
811
864
  } else {
812
865
  accountInfo.currentGenesisHash = accountInfo.allGenesisHash || ALL_GENESIS_HASH;
813
866
  }
@@ -817,18 +870,15 @@ export default class KoniExtension {
817
870
  });
818
871
  }
819
872
  updateCurrentAccountAddress(address) {
820
- this._saveCurrentAccountAddress(address, () => {
821
- this.triggerAccountsSubscription();
822
- });
873
+ this._saveCurrentAccountAddress(address);
823
874
  return true;
824
875
  }
825
- saveCurrentAccountAddress(data, id, port) {
826
- const cb = createSubscription(id, port);
827
- this._saveCurrentAccountAddress(data.address, cb);
828
- port.onDisconnect.addListener(() => {
829
- this.cancelSubscription(id);
876
+ async saveCurrentAccountAddress(data) {
877
+ return new Promise(resolve => {
878
+ this._saveCurrentAccountAddress(data.address, currentInfo => {
879
+ resolve(currentInfo);
880
+ });
830
881
  });
831
- return true;
832
882
  }
833
883
  async getAssetSetting() {
834
884
  return this.#koniState.chainService.getAssetSettings();
@@ -845,6 +895,7 @@ export default class KoniExtension {
845
895
  async updateAssetSetting(params) {
846
896
  try {
847
897
  await this.#koniState.chainService.updateAssetSetting(params.tokenSlug, params.assetSetting);
898
+ this.#koniState.eventService.emit('asset.updateState', params.tokenSlug);
848
899
  return true;
849
900
  } catch (e) {
850
901
  console.error('Error updating asset setting', e);
@@ -1272,6 +1323,14 @@ export default class KoniExtension {
1272
1323
  });
1273
1324
  return historySubject.getValue();
1274
1325
  }
1326
+ addContact(to) {
1327
+ const toAddress = reformatAddress(to);
1328
+ const account = keyring.getAccount(toAddress);
1329
+ const contact = keyring.getAddress(toAddress);
1330
+ if (!account && (!contact || contact.meta.isRecent)) {
1331
+ keyring.saveAddress(toAddress, {});
1332
+ }
1333
+ }
1275
1334
  validateTransfer(tokenSlug, from, to, value, transferAll) {
1276
1335
  const errors = [];
1277
1336
  const keypair = keyring.getPair(from);
@@ -1322,7 +1381,6 @@ export default class KoniExtension {
1322
1381
 
1323
1382
  // Get native token amount
1324
1383
  const freeBalance = await this.#koniState.balanceService.getTokenFreeBalance(from, networkKey, tokenSlug);
1325
- let edAsWarning = false;
1326
1384
  if (isEthereumAddress(from) && isEthereumAddress(to)) {
1327
1385
  chainType = ChainType.EVM;
1328
1386
  const txVal = transferAll ? freeBalance.value : value || '0';
@@ -1332,7 +1390,6 @@ export default class KoniExtension {
1332
1390
  [transaction, transferAmount.value] = await getERC20TransactionObject(_getContractAddressOfToken(tokenInfo), chainInfo, from, to, txVal, !!transferAll, evmApiMap);
1333
1391
  } else {
1334
1392
  [transaction, transferAmount.value] = await getEVMTransactionObject(chainInfo, to, txVal, !!transferAll, evmApiMap);
1335
- edAsWarning = true;
1336
1393
  }
1337
1394
  } else {
1338
1395
  const substrateApi = this.#koniState.getSubstrateApi(networkKey);
@@ -1345,9 +1402,9 @@ export default class KoniExtension {
1345
1402
  to: to,
1346
1403
  substrateApi
1347
1404
  });
1348
- edAsWarning = true;
1349
1405
  }
1350
1406
  const transferNativeAmount = isTransferNativeToken ? transferAmount.value : '0';
1407
+ this.addContact(to);
1351
1408
  return this.#koniState.transactionService.handleTransaction({
1352
1409
  errors,
1353
1410
  warnings,
@@ -1360,7 +1417,7 @@ export default class KoniExtension {
1360
1417
  extrinsicType: isTransferNativeToken ? ExtrinsicType.TRANSFER_BALANCE : ExtrinsicType.TRANSFER_TOKEN,
1361
1418
  ignoreWarnings: transferAll,
1362
1419
  isTransferAll: transferAll,
1363
- edAsWarning: edAsWarning
1420
+ edAsWarning: isTransferNativeToken
1364
1421
  });
1365
1422
  }
1366
1423
  validateCrossChainTransfer(destinationNetworkKey, sendingTokenSlug, sender, sendingValue) {
@@ -1400,6 +1457,7 @@ export default class KoniExtension {
1400
1457
  substrateApi
1401
1458
  });
1402
1459
  }
1460
+ this.addContact(to);
1403
1461
  return await this.#koniState.transactionService.handleTransaction({
1404
1462
  url: EXTENSION_REQUEST_URL,
1405
1463
  address: from,
@@ -1409,6 +1467,7 @@ export default class KoniExtension {
1409
1467
  extrinsicType: ExtrinsicType.TRANSFER_XCM,
1410
1468
  chainType: ChainType.SUBSTRATE,
1411
1469
  transferNativeAmount: _isNativeToken(originTokenInfo) ? value : '0',
1470
+ isTransferAll: inputData.transferAll,
1412
1471
  errors
1413
1472
  });
1414
1473
  }
@@ -1422,6 +1481,7 @@ export default class KoniExtension {
1422
1481
  const contractAddress = params.contractAddress;
1423
1482
  const tokenId = params.tokenId;
1424
1483
  const transaction = await getERC721Transaction(this.#koniState.getEvmApi(networkKey), contractAddress, senderAddress, recipientAddress, tokenId);
1484
+ this.addContact(recipientAddress);
1425
1485
  return await this.#koniState.transactionService.handleTransaction({
1426
1486
  address: senderAddress,
1427
1487
  chain: networkKey,
@@ -1497,6 +1557,71 @@ export default class KoniExtension {
1497
1557
  }) {
1498
1558
  return await this.#koniState.balanceService.getTokenFreeBalance(address, networkKey, token);
1499
1559
  }
1560
+ async transferGetMaxTransferable({
1561
+ address,
1562
+ destChain,
1563
+ isXcmTransfer,
1564
+ networkKey,
1565
+ token
1566
+ }) {
1567
+ const freeBalance = await this.#koniState.balanceService.getTokenFreeBalance(address, networkKey, token);
1568
+ const tokenInfo = token ? this.#koniState.chainService.getAssetBySlug(token) : this.#koniState.chainService.getNativeTokenInfo(networkKey);
1569
+ if (!_isNativeToken(tokenInfo)) {
1570
+ return freeBalance;
1571
+ } else {
1572
+ const substrateApi = this.#koniState.chainService.getSubstrateApi(networkKey);
1573
+ let estimatedFee;
1574
+ let maxTransferable = new BN(freeBalance.value);
1575
+ if (isXcmTransfer) {
1576
+ const chainInfoMap = this.#koniState.chainService.getChainInfoMap();
1577
+ const destinationTokenInfo = this.#koniState.getXcmEqualAssetByChain(destChain, tokenInfo.slug);
1578
+ if (!destinationTokenInfo) {
1579
+ estimatedFee = '0';
1580
+ } else {
1581
+ maxTransferable = maxTransferable.sub(new BN(tokenInfo.minAmount || '0'));
1582
+ const mockTx = await createXcmExtrinsic({
1583
+ chainInfoMap,
1584
+ destinationTokenInfo,
1585
+ originTokenInfo: tokenInfo,
1586
+ recipient: address,
1587
+ sendingValue: '0',
1588
+ substrateApi
1589
+ });
1590
+ try {
1591
+ var _paymentInfo$partialF;
1592
+ const paymentInfo = await mockTx.paymentInfo(address);
1593
+ estimatedFee = (paymentInfo === null || paymentInfo === void 0 ? void 0 : (_paymentInfo$partialF = paymentInfo.partialFee) === null || _paymentInfo$partialF === void 0 ? void 0 : _paymentInfo$partialF.toString()) || '0';
1594
+ } catch (e) {
1595
+ estimatedFee = '0';
1596
+ console.warn('Error estimating fee', e);
1597
+ }
1598
+ }
1599
+ } else {
1600
+ const [mockTx] = await createTransferExtrinsic({
1601
+ from: address,
1602
+ networkKey,
1603
+ substrateApi,
1604
+ to: address,
1605
+ tokenInfo,
1606
+ transferAll: true,
1607
+ value: '0'
1608
+ });
1609
+ try {
1610
+ var _paymentInfo$partialF2;
1611
+ const paymentInfo = await (mockTx === null || mockTx === void 0 ? void 0 : mockTx.paymentInfo(address));
1612
+ estimatedFee = (paymentInfo === null || paymentInfo === void 0 ? void 0 : (_paymentInfo$partialF2 = paymentInfo.partialFee) === null || _paymentInfo$partialF2 === void 0 ? void 0 : _paymentInfo$partialF2.toString()) || '0';
1613
+ } catch (e) {
1614
+ estimatedFee = '0';
1615
+ console.warn('Error estimating fee', e);
1616
+ }
1617
+ }
1618
+ maxTransferable = maxTransferable.sub(new BN(estimatedFee));
1619
+ return {
1620
+ ...freeBalance,
1621
+ value: maxTransferable.gt(BN_ZERO) ? maxTransferable.toString() || '0' : '0'
1622
+ };
1623
+ }
1624
+ }
1500
1625
  async subscribeAddressFreeBalance({
1501
1626
  address,
1502
1627
  networkKey,
@@ -1543,6 +1668,7 @@ export default class KoniExtension {
1543
1668
  const networkKey = params === null || params === void 0 ? void 0 : params.networkKey;
1544
1669
  const apiProps = this.#koniState.getSubstrateApi(networkKey);
1545
1670
  const extrinsic = !isPSP34 ? getNftTransferExtrinsic(networkKey, apiProps, senderAddress, recipientAddress, params || {}) : await getPSP34TransferExtrinsic(networkKey, apiProps, senderAddress, recipientAddress, params || {});
1671
+ this.addContact(recipientAddress);
1546
1672
  const rs = await this.#koniState.transactionService.handleTransaction({
1547
1673
  address: senderAddress,
1548
1674
  chain: networkKey,
@@ -1576,23 +1702,6 @@ export default class KoniExtension {
1576
1702
  meta: pair.meta
1577
1703
  };
1578
1704
  }
1579
-
1580
- // private async isInWalletAccount (address?: string) {
1581
- // return new Promise((resolve) => {
1582
- // if (address) {
1583
- // accountsObservable.subject.subscribe((storedAccounts: SubjectInfo): void => {
1584
- // if (storedAccounts[address]) {
1585
- // resolve(true);
1586
- // }
1587
- //
1588
- // resolve(false);
1589
- // });
1590
- // } else {
1591
- // resolve(false);
1592
- // }
1593
- // });
1594
- // }
1595
-
1596
1705
  accountsTie2({
1597
1706
  address,
1598
1707
  genesisHash
@@ -2038,6 +2147,7 @@ export default class KoniExtension {
2038
2147
  }
2039
2148
  async getNominationPoolOptions(chain) {
2040
2149
  const substrateApi = this.#koniState.getSubstrateApi(chain);
2150
+ console.log('chain', chain);
2041
2151
  return await getNominationPoolsInfo(chain, substrateApi);
2042
2152
  }
2043
2153
  async submitBonding(inputData) {
@@ -2048,12 +2158,15 @@ export default class KoniExtension {
2048
2158
  nominatorMetadata,
2049
2159
  selectedValidators
2050
2160
  } = inputData;
2051
- if (!amount || !selectedValidators) {
2052
- // Todo: Check and return error here
2053
-
2054
- return this.#koniState.transactionService.generateBeforeHandleResponseErrors([new TransactionError(BasicTxErrorType.INVALID_PARAMS)]);
2055
- }
2056
2161
  const chainInfo = this.#koniState.getChainInfo(chain);
2162
+ const chainStakingMetadata = await this.#koniState.getStakingMetadataByChain(chain, StakingType.NOMINATED);
2163
+ if (!chainStakingMetadata) {
2164
+ return this.#koniState.transactionService.generateBeforeHandleResponseErrors([new TransactionError(BasicTxErrorType.INTERNAL_ERROR)]);
2165
+ }
2166
+ const bondingValidation = validateBondingCondition(chainInfo, amount, selectedValidators, address, chainStakingMetadata, nominatorMetadata);
2167
+ if (!amount || !selectedValidators || bondingValidation.length > 0) {
2168
+ return this.#koniState.transactionService.generateBeforeHandleResponseErrors(bondingValidation);
2169
+ }
2057
2170
  const substrateApi = this.#koniState.getSubstrateApi(chain);
2058
2171
  const extrinsic = await getBondingExtrinsic(chainInfo, amount, selectedValidators, substrateApi, address, nominatorMetadata);
2059
2172
  console.log('Bonding extrinsic: ', chain, extrinsic.toHex());
@@ -2064,7 +2177,8 @@ export default class KoniExtension {
2064
2177
  data: inputData,
2065
2178
  extrinsicType: ExtrinsicType.STAKING_BOND,
2066
2179
  transaction: extrinsic,
2067
- url: EXTENSION_REQUEST_URL
2180
+ url: EXTENSION_REQUEST_URL,
2181
+ transferNativeAmount: amount
2068
2182
  });
2069
2183
  }
2070
2184
  async submitUnbonding(inputData) {
@@ -2074,12 +2188,17 @@ export default class KoniExtension {
2074
2188
  nominatorMetadata,
2075
2189
  validatorAddress
2076
2190
  } = inputData;
2077
- if (!amount || !nominatorMetadata) {
2078
- return this.#koniState.transactionService.generateBeforeHandleResponseErrors([new TransactionError(BasicTxErrorType.INVALID_PARAMS)]);
2191
+ const chainStakingMetadata = await this.#koniState.getStakingMetadataByChain(chain, StakingType.NOMINATED);
2192
+ if (!chainStakingMetadata || !nominatorMetadata) {
2193
+ return this.#koniState.transactionService.generateBeforeHandleResponseErrors([new TransactionError(BasicTxErrorType.INTERNAL_ERROR)]);
2194
+ }
2195
+ const unbondingValidation = validateUnbondingCondition(nominatorMetadata, amount, chain, chainStakingMetadata, validatorAddress);
2196
+ if (!amount || unbondingValidation.length > 0) {
2197
+ return this.#koniState.transactionService.generateBeforeHandleResponseErrors(unbondingValidation);
2079
2198
  }
2080
2199
  const substrateApi = this.#koniState.getSubstrateApi(chain);
2081
2200
  const extrinsic = await getUnbondingExtrinsic(nominatorMetadata, amount, chain, substrateApi, validatorAddress);
2082
- console.log('unbonding extrinsic: ', extrinsic.toHex());
2201
+ console.log('Unbonding extrinsic: ', extrinsic.toHex());
2083
2202
  return await this.#koniState.transactionService.handleTransaction({
2084
2203
  address: nominatorMetadata.address,
2085
2204
  chain: chain,
@@ -2153,7 +2272,7 @@ export default class KoniExtension {
2153
2272
  chainType: ChainType.SUBSTRATE
2154
2273
  });
2155
2274
  }
2156
- async submitPoolingBonding(inputData) {
2275
+ async submitPoolBonding(inputData) {
2157
2276
  const {
2158
2277
  address,
2159
2278
  amount,
@@ -2161,8 +2280,15 @@ export default class KoniExtension {
2161
2280
  nominatorMetadata,
2162
2281
  selectedPool
2163
2282
  } = inputData;
2164
-
2165
- // TODO: can't stake when unstake all
2283
+ const chainInfo = this.#koniState.getChainInfo(chain);
2284
+ const chainStakingMetadata = await this.#koniState.getStakingMetadataByChain(chain, StakingType.NOMINATED);
2285
+ if (!chainStakingMetadata) {
2286
+ return this.#koniState.transactionService.generateBeforeHandleResponseErrors([new TransactionError(BasicTxErrorType.INTERNAL_ERROR)]);
2287
+ }
2288
+ const bondingValidation = validatePoolBondingCondition(chainInfo, amount, selectedPool, address, chainStakingMetadata, nominatorMetadata);
2289
+ if (!amount || bondingValidation.length > 0) {
2290
+ return this.#koniState.transactionService.generateBeforeHandleResponseErrors(bondingValidation);
2291
+ }
2166
2292
  const substrateApi = this.#koniState.getSubstrateApi(chain);
2167
2293
  const extrinsic = await getPoolingBondingExtrinsic(substrateApi, amount, selectedPool.id, nominatorMetadata);
2168
2294
  console.log('Join nomination pool extrinsic', extrinsic.toHex());
@@ -2181,6 +2307,14 @@ export default class KoniExtension {
2181
2307
  chain,
2182
2308
  nominatorMetadata
2183
2309
  } = inputData;
2310
+ const chainStakingMetadata = await this.#koniState.getStakingMetadataByChain(chain, StakingType.NOMINATED);
2311
+ if (!chainStakingMetadata || !nominatorMetadata) {
2312
+ return this.#koniState.transactionService.generateBeforeHandleResponseErrors([new TransactionError(BasicTxErrorType.INTERNAL_ERROR)]);
2313
+ }
2314
+ const unbondingValidation = validateRelayUnbondingCondition(amount, chainStakingMetadata, nominatorMetadata);
2315
+ if (!amount || unbondingValidation.length > 0) {
2316
+ return this.#koniState.transactionService.generateBeforeHandleResponseErrors(unbondingValidation);
2317
+ }
2184
2318
  const substrateApi = this.#koniState.getSubstrateApi(chain);
2185
2319
  const extrinsic = await getPoolingUnbondingExtrinsic(substrateApi, amount, nominatorMetadata);
2186
2320
  console.log('Nomination pool unbond extrinsic', extrinsic.toHex());
@@ -2670,6 +2804,16 @@ export default class KoniExtension {
2670
2804
  });
2671
2805
  return notificationSubject.value;
2672
2806
  }
2807
+ async reloadCron({
2808
+ data
2809
+ }) {
2810
+ if (data === 'nft') {
2811
+ return await this.#koniState.reloadNft();
2812
+ } else if (data === 'staking') {
2813
+ return await this.#koniState.reloadStaking();
2814
+ }
2815
+ return Promise.resolve(false);
2816
+ }
2673
2817
 
2674
2818
  // --------------------------------------------------------------
2675
2819
  // eslint-disable-next-line @typescript-eslint/require-await
@@ -2688,8 +2832,6 @@ export default class KoniExtension {
2688
2832
  return this.accountsCreateSuri(request);
2689
2833
  case 'pri(accounts.changePassword)':
2690
2834
  return this.accountsChangePassword(request);
2691
- case 'pri(accounts.edit)':
2692
- return this.accountsEdit(request);
2693
2835
  case 'pri(accounts.export)':
2694
2836
  return this.accountsExport(request);
2695
2837
  case 'pri(accounts.show)':
@@ -2758,40 +2900,6 @@ export default class KoniExtension {
2758
2900
  return this.getAuthListV2();
2759
2901
  case 'pri(authorize.toggle)':
2760
2902
  return this.toggleAuthorization2(request);
2761
- case 'pri(accounts.create.suriV2)':
2762
- return await this.accountsCreateSuriV2(request);
2763
- case 'pri(accounts.forget)':
2764
- return await this.accountsForgetOverride(request);
2765
- case 'pri(accounts.create.externalV2)':
2766
- return await this.accountsCreateExternalV2(request);
2767
- case 'pri(accounts.create.hardwareV2)':
2768
- return await this.accountsCreateHardwareV2(request);
2769
- case 'pri(accounts.create.hardwareMultiple)':
2770
- return await this.accountsCreateHardwareMultiple(request);
2771
- case 'pri(accounts.create.withSecret)':
2772
- return await this.accountsCreateWithSecret(request);
2773
- case 'pri(seed.createV2)':
2774
- return this.seedCreateV2(request);
2775
- case 'pri(seed.validateV2)':
2776
- return this.seedValidateV2(request);
2777
- case 'pri(privateKey.validateV2)':
2778
- return this.metamaskPrivateKeyValidateV2(request);
2779
- case 'pri(accounts.exportPrivateKey)':
2780
- return this.accountExportPrivateKey(request);
2781
- case 'pri(accounts.checkPublicAndSecretKey)':
2782
- return this.checkPublicAndSecretKey(request);
2783
- case 'pri(accounts.subscribeWithCurrentAddress)':
2784
- return await this.accountsGetAllWithCurrentAddress(id, port);
2785
- case 'pri(accounts.subscribeAccountsInputAddress)':
2786
- return this.accountsGetAll(id, port);
2787
- case 'pri(accounts.saveRecent)':
2788
- return this.saveRecentAccountId(request);
2789
- case 'pri(accounts.triggerSubscription)':
2790
- return this.triggerAccountsSubscription();
2791
- case 'pri(currentAccount.saveAddress)':
2792
- return this.saveCurrentAccountAddress(request, id, port);
2793
- case 'pri(accounts.updateCurrentAddress)':
2794
- return this.updateCurrentAccountAddress(request);
2795
2903
  case 'pri(settings.changeBalancesVisibility)':
2796
2904
  return this.toggleBalancesVisibility(id, port);
2797
2905
  case 'pri(settings.subscribe)':
@@ -2841,6 +2949,65 @@ export default class KoniExtension {
2841
2949
  case 'pri(transaction.history.getSubscription)':
2842
2950
  return await this.subscribeHistory(id, port);
2843
2951
 
2952
+ /// Account management
2953
+ // Add account
2954
+ case 'pri(accounts.create.suriV2)':
2955
+ return await this.accountsCreateSuriV2(request);
2956
+ case 'pri(accounts.create.externalV2)':
2957
+ return await this.accountsCreateExternalV2(request);
2958
+ case 'pri(accounts.create.hardwareV2)':
2959
+ return await this.accountsCreateHardwareV2(request);
2960
+ case 'pri(accounts.create.hardwareMultiple)':
2961
+ return await this.accountsCreateHardwareMultiple(request);
2962
+ case 'pri(accounts.create.withSecret)':
2963
+ return await this.accountsCreateWithSecret(request);
2964
+ case 'pri(seed.createV2)':
2965
+ return this.seedCreateV2(request);
2966
+
2967
+ // Remove account
2968
+ case 'pri(accounts.forget)':
2969
+ return await this.accountsForgetOverride(request);
2970
+
2971
+ // Validate account
2972
+ case 'pri(seed.validateV2)':
2973
+ return this.seedValidateV2(request);
2974
+ case 'pri(privateKey.validateV2)':
2975
+ return this.metamaskPrivateKeyValidateV2(request);
2976
+ case 'pri(accounts.checkPublicAndSecretKey)':
2977
+ return this.checkPublicAndSecretKey(request);
2978
+
2979
+ // Export account
2980
+ case 'pri(accounts.exportPrivateKey)':
2981
+ return this.accountExportPrivateKey(request);
2982
+
2983
+ // Subscribe account
2984
+ case 'pri(accounts.subscribeWithCurrentAddress)':
2985
+ return await this.accountsGetAllWithCurrentAddress(id, port);
2986
+ case 'pri(accounts.subscribeAccountsInputAddress)':
2987
+ return this.accountsGetAll(id, port);
2988
+
2989
+ // Save current account
2990
+ case 'pri(currentAccount.saveAddress)':
2991
+ return await this.saveCurrentAccountAddress(request);
2992
+ case 'pri(accounts.updateCurrentAddress)':
2993
+ return this.updateCurrentAccountAddress(request);
2994
+
2995
+ // Edit account
2996
+ case 'pri(accounts.edit)':
2997
+ return this.accountsEdit(request);
2998
+
2999
+ // Save contact address
3000
+ case 'pri(accounts.saveRecent)':
3001
+ return this.saveRecentAccount(request);
3002
+ case 'pri(accounts.editContact)':
3003
+ return this.editContactAccount(request);
3004
+ case 'pri(accounts.deleteContact)':
3005
+ return this.deleteContactAccount(request);
3006
+
3007
+ // Subscribe address
3008
+ case 'pri(accounts.subscribeAddresses)':
3009
+ return this.subscribeAddresses(id, port);
3010
+
2844
3011
  // ChainService
2845
3012
  case 'pri(chainService.subscribeChainInfoMap)':
2846
3013
  return this.subscribeChainInfoMap(id, port);
@@ -2884,6 +3051,8 @@ export default class KoniExtension {
2884
3051
  return await this.transferCheckSupporting(request);
2885
3052
  case 'pri(transfer.getExistentialDeposit)':
2886
3053
  return this.transferGetExistentialDeposit(request);
3054
+ case 'pri(transfer.getMaxTransferable)':
3055
+ return this.transferGetMaxTransferable(request);
2887
3056
  case 'pri(freeBalance.get)':
2888
3057
  return this.getAddressFreeBalance(request);
2889
3058
  case 'pri(freeBalance.subscribe)':
@@ -2895,7 +3064,7 @@ export default class KoniExtension {
2895
3064
  case 'pri(accounts.get.meta)':
2896
3065
  return this.getAccountMeta(request);
2897
3066
 
2898
- // Send NFT
3067
+ /// Send NFT
2899
3068
  case 'pri(evmNft.submitTransaction)':
2900
3069
  return this.evmNftSubmitTransaction(request);
2901
3070
  case 'pri(substrateNft.submitTransaction)':
@@ -2953,7 +3122,7 @@ export default class KoniExtension {
2953
3122
  case 'pri(staking.submitTuringCancelCompound)':
2954
3123
  return await this.submitTuringCancelStakeCompound(request);
2955
3124
  case 'pri(bonding.nominationPool.submitBonding)':
2956
- return await this.submitPoolingBonding(request);
3125
+ return await this.submitPoolBonding(request);
2957
3126
  case 'pri(bonding.nominationPool.submitUnbonding)':
2958
3127
  return await this.submitPoolingUnbonding(request);
2959
3128
 
@@ -3002,6 +3171,8 @@ export default class KoniExtension {
3002
3171
  // Notification
3003
3172
  case 'pri(notifications.subscribe)':
3004
3173
  return this.subscribeNotifications(id, port);
3174
+ case 'pri(cron.reload)':
3175
+ return await this.reloadCron(request);
3005
3176
 
3006
3177
  // Default
3007
3178
  default: