@subwallet/extension-base 1.3.73-0 → 1.3.74-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 (108) hide show
  1. package/background/KoniTypes.d.ts +42 -5
  2. package/background/KoniTypes.js +14 -1
  3. package/cjs/background/KoniTypes.js +16 -2
  4. package/cjs/core/logic-validation/transfer.js +35 -57
  5. package/cjs/koni/background/handlers/Extension.js +599 -144
  6. package/cjs/koni/background/handlers/State.js +5 -2
  7. package/cjs/koni/background/handlers/Tabs.js +3 -2
  8. package/cjs/packageInfo.js +1 -1
  9. package/cjs/services/balance-service/helpers/subscribe/substrate/index.js +0 -2
  10. package/cjs/services/chain-service/handler/SubstrateApi.js +6 -1
  11. package/cjs/services/chain-service/index.js +1 -0
  12. package/cjs/services/chain-service/utils/index.js +4 -0
  13. package/cjs/services/event-service/index.js +1 -0
  14. package/cjs/services/fee-service/utils/index.js +4 -4
  15. package/cjs/services/inapp-notification-service/consts.js +4 -2
  16. package/cjs/services/inapp-notification-service/index.js +51 -6
  17. package/cjs/services/inapp-notification-service/interfaces.js +2 -0
  18. package/cjs/services/inapp-notification-service/utils/common.js +4 -0
  19. package/cjs/services/keyring-service/context/account-context.js +44 -0
  20. package/cjs/services/keyring-service/context/handlers/Multisig.js +186 -0
  21. package/cjs/services/keyring-service/context/state.js +12 -0
  22. package/cjs/services/multisig-service/index.js +627 -0
  23. package/cjs/services/multisig-service/utils.js +242 -0
  24. package/cjs/services/request-service/handler/SubstrateRequestHandler.js +25 -0
  25. package/cjs/services/request-service/index.js +5 -1
  26. package/cjs/services/storage-service/DatabaseService.js +5 -2
  27. package/cjs/services/storage-service/db-stores/InappNotification.js +20 -2
  28. package/cjs/services/substrate-proxy-service/index.js +22 -7
  29. package/cjs/services/transaction-service/helpers/index.js +8 -0
  30. package/cjs/services/transaction-service/index.js +348 -147
  31. package/cjs/services/transaction-service/types.js +18 -1
  32. package/cjs/types/account/info/keyring.js +5 -0
  33. package/cjs/types/account/info/proxy.js +1 -0
  34. package/cjs/types/multisig/index.js +14 -0
  35. package/cjs/types/transaction/error.js +9 -2
  36. package/cjs/utils/account/transform.js +28 -4
  37. package/cjs/utils/logger/Logger.js +294 -0
  38. package/cjs/utils/logger/index.js +42 -0
  39. package/cjs/utils/logger/types.js +1 -0
  40. package/core/logic-validation/transfer.d.ts +2 -2
  41. package/core/logic-validation/transfer.js +10 -32
  42. package/koni/background/handlers/Extension.d.ts +7 -0
  43. package/koni/background/handlers/Extension.js +498 -43
  44. package/koni/background/handlers/State.d.ts +2 -0
  45. package/koni/background/handlers/State.js +5 -2
  46. package/koni/background/handlers/Tabs.js +3 -2
  47. package/package.json +42 -6
  48. package/packageInfo.js +1 -1
  49. package/services/balance-service/helpers/subscribe/substrate/index.js +0 -2
  50. package/services/chain-service/handler/SubstrateApi.js +7 -2
  51. package/services/chain-service/index.js +1 -0
  52. package/services/chain-service/types.d.ts +1 -1
  53. package/services/chain-service/utils/index.js +4 -0
  54. package/services/event-service/index.d.ts +1 -0
  55. package/services/event-service/index.js +1 -0
  56. package/services/event-service/types.d.ts +1 -0
  57. package/services/fee-service/utils/index.js +4 -4
  58. package/services/inapp-notification-service/consts.d.ts +3 -1
  59. package/services/inapp-notification-service/consts.js +5 -3
  60. package/services/inapp-notification-service/index.d.ts +3 -2
  61. package/services/inapp-notification-service/index.js +51 -6
  62. package/services/inapp-notification-service/interfaces.d.ts +18 -2
  63. package/services/inapp-notification-service/interfaces.js +2 -0
  64. package/services/inapp-notification-service/utils/common.d.ts +1 -0
  65. package/services/inapp-notification-service/utils/common.js +3 -0
  66. package/services/keyring-service/context/account-context.d.ts +9 -1
  67. package/services/keyring-service/context/account-context.js +44 -0
  68. package/services/keyring-service/context/handlers/Multisig.d.ts +18 -0
  69. package/services/keyring-service/context/handlers/Multisig.js +180 -0
  70. package/services/keyring-service/context/state.d.ts +2 -0
  71. package/services/keyring-service/context/state.js +12 -0
  72. package/services/multisig-service/index.d.ts +245 -0
  73. package/services/multisig-service/index.js +620 -0
  74. package/services/multisig-service/utils.d.ts +95 -0
  75. package/services/multisig-service/utils.js +227 -0
  76. package/services/request-service/handler/SubstrateRequestHandler.d.ts +1 -0
  77. package/services/request-service/handler/SubstrateRequestHandler.js +25 -0
  78. package/services/request-service/index.d.ts +2 -1
  79. package/services/request-service/index.js +5 -1
  80. package/services/storage-service/DatabaseService.d.ts +3 -2
  81. package/services/storage-service/DatabaseService.js +5 -2
  82. package/services/storage-service/db-stores/InappNotification.d.ts +3 -2
  83. package/services/storage-service/db-stores/InappNotification.js +20 -2
  84. package/services/substrate-proxy-service/index.d.ts +4 -1
  85. package/services/substrate-proxy-service/index.js +22 -8
  86. package/services/transaction-service/helpers/index.js +8 -0
  87. package/services/transaction-service/index.d.ts +31 -0
  88. package/services/transaction-service/index.js +270 -69
  89. package/services/transaction-service/types.d.ts +28 -3
  90. package/services/transaction-service/types.js +12 -1
  91. package/types/account/info/keyring.d.ts +14 -1
  92. package/types/account/info/keyring.js +6 -0
  93. package/types/account/info/proxy.d.ts +1 -0
  94. package/types/account/info/proxy.js +1 -0
  95. package/types/multisig/index.d.ts +76 -0
  96. package/types/multisig/index.js +8 -0
  97. package/types/notification/index.d.ts +8 -0
  98. package/types/substrateProxyAccount/index.d.ts +26 -1
  99. package/types/transaction/error.d.ts +6 -1
  100. package/types/transaction/error.js +7 -1
  101. package/types/transaction/request.d.ts +0 -1
  102. package/utils/account/transform.js +28 -4
  103. package/utils/logger/Logger.d.ts +31 -0
  104. package/utils/logger/Logger.js +267 -0
  105. package/utils/logger/index.d.ts +15 -0
  106. package/utils/logger/index.js +29 -0
  107. package/utils/logger/types.d.ts +23 -0
  108. package/utils/logger/types.js +1 -0
@@ -42,13 +42,16 @@ import { _ChainConnectionStatus } from '@subwallet/extension-base/services/chain
42
42
  import { _getAssetDecimals, _getAssetSymbol, _getChainNativeTokenBasicInfo, _getContractAddressOfToken, _getEvmChainId, _isAssetSmartContractNft, _isChainBitcoinCompatible, _isChainCompatibleLedgerEvm, _isChainEnabled, _isChainEvmCompatible, _isChainSubstrateCompatible, _isCustomAsset, _isLocalToken, _isMantaZkAsset, _isNativeToken, _isNativeTokenBySlug, _isPureEvmChain, _isTokenEvmSmartContract, _isTokenTransferredByBitcoin, _isTokenTransferredByCardano, _isTokenTransferredByEvm, _isTokenTransferredByTon } from '@subwallet/extension-base/services/chain-service/utils';
43
43
  import { calculateToAmountByReservePool } from '@subwallet/extension-base/services/fee-service/utils';
44
44
  import { batchExtrinsicSetFeeHydration, getAssetHubTokensCanPayFee, getHydrationTokensCanPayFee } from '@subwallet/extension-base/services/fee-service/utils/tokenPayFee';
45
+ import { calcDepositAmount, createInitMultisigExtrinsic, decodeCallData, DEFAULT_MAX_WEIGHT } from '@subwallet/extension-base/services/multisig-service/utils';
45
46
  import { EXTENSION_REQUEST_URL } from '@subwallet/extension-base/services/request-service/constants';
46
47
  import { DEFAULT_AUTO_LOCK_TIME } from '@subwallet/extension-base/services/setting-service/constants';
48
+ import { createInitSubstrateProxyExtrinsic } from '@subwallet/extension-base/services/substrate-proxy-service';
49
+ import { SubstrateTransactionWrappingStatus } from '@subwallet/extension-base/services/transaction-service/types';
47
50
  import { isProposalExpired, isSupportWalletConnectChain, isSupportWalletConnectNamespace } from '@subwallet/extension-base/services/wallet-connect-service/helpers';
48
51
  import { SWStorage } from '@subwallet/extension-base/storage';
49
52
  import { AccountsStore } from '@subwallet/extension-base/stores';
50
- import { AccountChainType, AccountSignMode, BalanceType, BasicTxErrorType, BasicTxWarningCode, CommonStepType, EarningProcessType, ProcessType, StakingTxErrorType, StepStatus, SwapFeeType, YieldPoolType, YieldStepType } from '@subwallet/extension-base/types';
51
- import { _analyzeAddress, calculateMaxTransferable, combineAllAccountProxy, combineBitcoinFee, createPromiseHandler, createTransactionFromRLP, detectTransferTxType, filterUneconomicalUtxos, getAccountSignMode, getSizeInfo, getTransferableBitcoinUtxos, isSameAddress, isSubstrateEcdsaLedgerAssetSupported, MODULE_SUPPORT, reformatAddress, signatureToHex, transformAccounts, transformAddresses, uniqueStringArray } from '@subwallet/extension-base/utils';
53
+ import { AccountChainType, AccountSignMode, BalanceType, BasicTxErrorType, BasicTxWarningCode, CommonStepType, EarningProcessType, MultisigTxErrorType, ProcessType, StakingTxErrorType, StepStatus, SwapFeeType, YieldPoolType, YieldStepType } from '@subwallet/extension-base/types';
54
+ import { _analyzeAddress, calculateMaxTransferable, combineAllAccountProxy, combineBitcoinFee, createPromiseHandler, createTransactionFromRLP, detectTransferTxType, filterUneconomicalUtxos, getAccountJsonByAddress, getAccountSignMode, getSizeInfo, getTransferableBitcoinUtxos, isSameAddress, isSubstrateEcdsaLedgerAssetSupported, MODULE_SUPPORT, reformatAddress, signatureToHex, transformAccounts, transformAddresses, uniqueStringArray } from '@subwallet/extension-base/utils';
52
55
  import { parseContractInput, parseEvmRlp } from '@subwallet/extension-base/utils/eth/parseTransaction';
53
56
  import { getId } from '@subwallet/extension-base/utils/getId';
54
57
  import { getKeypairTypeByAddress, isAddress, isCardanoAddress, isSubstrateAddress, isTonAddress } from '@subwallet/keyring';
@@ -63,7 +66,7 @@ import { t } from 'i18next';
63
66
  import { combineLatest, Subject } from 'rxjs';
64
67
  import { TypeRegistry } from '@polkadot/types';
65
68
  import { assert, hexStripPrefix, hexToU8a, isAscii, isHex, noop, u8aToHex } from '@polkadot/util';
66
- import { decodeAddress, isEthereumAddress } from '@polkadot/util-crypto';
69
+ import { decodeAddress, isEthereumAddress, sortAddresses } from '@polkadot/util-crypto';
67
70
  import { getSuitableRegistry, setupApiRegistry, setupDappRegistry, setupDatabaseRegistry } from "../utils.js";
68
71
  export function isJsonPayload(value) {
69
72
  return value.genesisHash !== undefined;
@@ -1255,7 +1258,6 @@ export default class KoniExtension {
1255
1258
  feeCustom,
1256
1259
  feeOption,
1257
1260
  from,
1258
- signerSubstrateProxyAddress,
1259
1261
  to,
1260
1262
  tokenPayFeeSlug,
1261
1263
  tokenSlug,
@@ -1489,7 +1491,6 @@ export default class KoniExtension {
1489
1491
  isTransferAll: isTransferNativeToken ? transferAll : false,
1490
1492
  isTransferLocalTokenAndPayThatTokenAsFee,
1491
1493
  edAsWarning: isTransferNativeToken,
1492
- signerSubstrateProxyAddress,
1493
1494
  additionalValidator: additionalValidator
1494
1495
  });
1495
1496
  }
@@ -1501,7 +1502,6 @@ export default class KoniExtension {
1501
1502
  from,
1502
1503
  isPassConfirmation,
1503
1504
  originNetworkKey,
1504
- signerSubstrateProxyAddress,
1505
1505
  to,
1506
1506
  tokenPayFeeSlug,
1507
1507
  tokenSlug,
@@ -1697,8 +1697,7 @@ export default class KoniExtension {
1697
1697
  xcmFeeDryRun,
1698
1698
  errors,
1699
1699
  additionalValidator: additionalValidator,
1700
- eventsHandler: eventsHandler,
1701
- signerSubstrateProxyAddress
1700
+ eventsHandler: eventsHandler
1702
1701
  });
1703
1702
  }
1704
1703
  async makeBitcoinDappTransferConfirmation(inputData) {
@@ -2423,8 +2422,7 @@ export default class KoniExtension {
2423
2422
  const {
2424
2423
  params,
2425
2424
  recipientAddress,
2426
- senderAddress,
2427
- signerSubstrateProxyAddress
2425
+ senderAddress
2428
2426
  } = inputData;
2429
2427
  const isSendingSelf = isRecipientSelf(senderAddress, recipientAddress);
2430
2428
 
@@ -2445,8 +2443,7 @@ export default class KoniExtension {
2445
2443
  isSendingSelf
2446
2444
  },
2447
2445
  extrinsicType: ExtrinsicType.SEND_NFT,
2448
- chainType: ChainType.SUBSTRATE,
2449
- signerSubstrateProxyAddress
2446
+ chainType: ChainType.SUBSTRATE
2450
2447
  });
2451
2448
  return {
2452
2449
  ...rs,
@@ -2483,6 +2480,9 @@ export default class KoniExtension {
2483
2480
  }
2484
2481
  return result;
2485
2482
  }
2483
+ async accountsCreateMultisig(request) {
2484
+ return this.#koniState.keyringService.context.accountsCreateMultisig(request);
2485
+ }
2486
2486
 
2487
2487
  /// External account
2488
2488
 
@@ -2918,6 +2918,439 @@ export default class KoniExtension {
2918
2918
  });
2919
2919
  }
2920
2920
 
2921
+ // Multisig handlers
2922
+ async approvePendingTx(inputData) {
2923
+ const {
2924
+ address,
2925
+ callHash,
2926
+ chain,
2927
+ multisigMetadata,
2928
+ timepoint
2929
+ } = inputData;
2930
+ if (!address || !chain || !multisigMetadata || !callHash || !timepoint) {
2931
+ return this.#koniState.transactionService.generateBeforeHandleResponseErrors([new TransactionError(MultisigTxErrorType.INVALID_PARAMS)]);
2932
+ }
2933
+ const api = this.#koniState.getSubstrateApi(chain).api;
2934
+ if (!api || !api.tx || !api.tx.multisig) {
2935
+ return this.#koniState.transactionService.generateBeforeHandleResponseErrors([new TransactionError(MultisigTxErrorType.LACK_MULTISIG_PALLET)]);
2936
+ }
2937
+ const otherSignatories = multisigMetadata.signers.filter(s => !isSameAddress(s, address));
2938
+ const extrinsic = api.tx.multisig.approveAsMulti(multisigMetadata.threshold, sortAddresses(otherSignatories), timepoint, callHash, DEFAULT_MAX_WEIGHT);
2939
+ return await this.#koniState.transactionService.handleTransaction({
2940
+ address,
2941
+ chain,
2942
+ chainType: ChainType.SUBSTRATE,
2943
+ data: inputData,
2944
+ extrinsicType: ExtrinsicType.MULTISIG_APPROVE_TX,
2945
+ transaction: extrinsic,
2946
+ url: EXTENSION_REQUEST_URL
2947
+ });
2948
+ }
2949
+ async executePendingTx(inputData) {
2950
+ const {
2951
+ address,
2952
+ call,
2953
+ chain,
2954
+ decodedCallData,
2955
+ multisigMetadata,
2956
+ timepoint
2957
+ } = inputData;
2958
+ if (!address || !chain || !multisigMetadata || !timepoint || !call || !decodedCallData) {
2959
+ return this.#koniState.transactionService.generateBeforeHandleResponseErrors([new TransactionError(MultisigTxErrorType.INVALID_PARAMS)]);
2960
+ }
2961
+ try {
2962
+ const api = this.#koniState.getSubstrateApi(chain).api;
2963
+ if (!api || !api.tx || !api.tx.multisig) {
2964
+ return this.#koniState.transactionService.generateBeforeHandleResponseErrors([new TransactionError(MultisigTxErrorType.LACK_MULTISIG_PALLET)]);
2965
+ }
2966
+ const otherSignatories = multisigMetadata.signers.filter(s => !isSameAddress(s, address));
2967
+ const originalCall = api.createType('Call', call);
2968
+ const originalExtrinsic = api.tx(originalCall);
2969
+ const {
2970
+ weight
2971
+ } = await originalExtrinsic.paymentInfo(otherSignatories[0]); // estimate max weight for execute multisig tx
2972
+
2973
+ const extrinsic = api.tx.multisig.asMulti(multisigMetadata.threshold, sortAddresses(otherSignatories), timepoint, call, weight);
2974
+ return await this.#koniState.transactionService.handleTransaction({
2975
+ address,
2976
+ chain,
2977
+ chainType: ChainType.SUBSTRATE,
2978
+ data: inputData,
2979
+ extrinsicType: ExtrinsicType.MULTISIG_EXECUTE_TX,
2980
+ transaction: extrinsic,
2981
+ url: EXTENSION_REQUEST_URL
2982
+ });
2983
+ } catch (e) {
2984
+ const errMsg = e.message;
2985
+ return this.#koniState.transactionService.generateBeforeHandleResponseErrors([new TransactionError(MultisigTxErrorType.UNABLE_TO_CONSTRUCT_TX, errMsg)]);
2986
+ }
2987
+ }
2988
+ async cancelPendingTx(inputData) {
2989
+ const {
2990
+ address,
2991
+ callHash,
2992
+ chain,
2993
+ multisigMetadata,
2994
+ timepoint
2995
+ } = inputData;
2996
+ if (!address || !chain || !multisigMetadata || !callHash) {
2997
+ return this.#koniState.transactionService.generateBeforeHandleResponseErrors([new TransactionError(MultisigTxErrorType.INVALID_PARAMS)]);
2998
+ }
2999
+ const api = this.#koniState.getSubstrateApi(chain).api;
3000
+ if (!api || !api.tx || !api.tx.multisig) {
3001
+ return this.#koniState.transactionService.generateBeforeHandleResponseErrors([new TransactionError(MultisigTxErrorType.LACK_MULTISIG_PALLET)]);
3002
+ }
3003
+ const otherSignatories = multisigMetadata.signers.filter(s => !isSameAddress(s, address));
3004
+ const extrinsic = api.tx.multisig.cancelAsMulti(multisigMetadata.threshold, sortAddresses(otherSignatories), timepoint, callHash);
3005
+ return await this.#koniState.transactionService.handleTransaction({
3006
+ address,
3007
+ chain,
3008
+ chainType: ChainType.SUBSTRATE,
3009
+ data: inputData,
3010
+ extrinsicType: ExtrinsicType.MULTISIG_CANCEL_TX,
3011
+ transaction: extrinsic,
3012
+ url: EXTENSION_REQUEST_URL
3013
+ });
3014
+ }
3015
+
3016
+ // Multisig Account
3017
+ async initMultisigTx(request) {
3018
+ const {
3019
+ chain,
3020
+ multisigMetadata: {
3021
+ signers,
3022
+ threshold
3023
+ },
3024
+ signer,
3025
+ transactionId
3026
+ } = request;
3027
+
3028
+ /**
3029
+ * ─────────────────────────────
3030
+ * Prepare original transaction
3031
+ * ─────────────────────────────
3032
+ */
3033
+ const substrateApi = await this.#koniState.chainService.getSubstrateApi(chain).isReady;
3034
+ const originTransaction = this.#koniState.transactionService.getTransaction(transactionId);
3035
+ if (!(originTransaction !== null && originTransaction !== void 0 && originTransaction.transaction)) {
3036
+ throw new Error(`[initMultisigTx] Origin transaction not found: ${transactionId}`);
3037
+ }
3038
+ const extrinsicOriginTransaction = originTransaction.transaction;
3039
+ const callData = extrinsicOriginTransaction.method.toHex();
3040
+
3041
+ /**
3042
+ * ─────────────────────────────
3043
+ * Create multisig wrapped extrinsic
3044
+ * ─────────────────────────────
3045
+ */
3046
+ const multisigExtrinsic = createInitMultisigExtrinsic(substrateApi.api, threshold, signers, signer, extrinsicOriginTransaction);
3047
+ const decodedCallData = decodeCallData({
3048
+ api: substrateApi.api,
3049
+ callData
3050
+ });
3051
+
3052
+ /**
3053
+ * ─────────────────────────────
3054
+ * Fee & deposit calculation
3055
+ * ─────────────────────────────
3056
+ */
3057
+ const networkFee = (await multisigExtrinsic.paymentInfo(signer)).partialFee.toString();
3058
+ const depositBase = substrateApi.api.consts.multisig.depositBase.toString();
3059
+ const depositFactor = substrateApi.api.consts.multisig.depositFactor.toString();
3060
+ const depositAmount = calcDepositAmount(depositBase, threshold, depositFactor);
3061
+
3062
+ /**
3063
+ * ─────────────────────────────
3064
+ * Additional validation
3065
+ * ─────────────────────────────
3066
+ * Validate signer balance:
3067
+ * - multisig deposit
3068
+ * - network fee
3069
+ */
3070
+ const additionalValidator = async inputTransaction => {
3071
+ const signerBalance = await this.getAddressTransferableBalance({
3072
+ address: signer,
3073
+ networkKey: chain,
3074
+ token: this.#koniState.chainService.getNativeTokenInfo(chain).slug,
3075
+ extrinsicType: ExtrinsicType.TRANSFER_TOKEN
3076
+ });
3077
+
3078
+ // Hydration: token fee setting is not supported
3079
+ // todo: check and return better error for the case set token fee on hydration
3080
+ if (_SUPPORT_TOKEN_PAY_FEE_GROUP.hydration.includes(chain)) {
3081
+ var _substrateApi$api$que3;
3082
+ const setTokenPayFee = await ((_substrateApi$api$que3 = substrateApi.api.query.multiTransactionPayment) === null || _substrateApi$api$que3 === void 0 ? void 0 : _substrateApi$api$que3.accountCurrencyMap(signer));
3083
+ if (setTokenPayFee.toPrimitive()) {
3084
+ inputTransaction.errors.push(new TransactionError(BasicTxErrorType.NOT_ENOUGH_BALANCE, t('bg.koni.handler.Extension.notEnoughBalanceForMultisigDepositAndFee')));
3085
+ }
3086
+ }
3087
+ const requiredBalance = BigInt(depositAmount) + BigInt(networkFee);
3088
+ if (BigInt(signerBalance.value) < requiredBalance) {
3089
+ inputTransaction.errors.push(new TransactionError(BasicTxErrorType.NOT_ENOUGH_BALANCE, t('bg.koni.handler.Extension.notEnoughBalanceForMultisigDepositAndFee')));
3090
+ }
3091
+ };
3092
+
3093
+ /**
3094
+ * ─────────────────────────────
3095
+ * Event forwarding
3096
+ * ─────────────────────────────
3097
+ * Multisig INIT transaction:
3098
+ * - `signed` is forwarded to notify that the multisig initialization
3099
+ * has been successfully submitted.
3100
+ * - `error` / `timeout` are forwarded to propagate failures.
3101
+ *
3102
+ * Note:
3103
+ * Multisig execution requires collecting enough approvals,
3104
+ * so the transaction is not finalized at this stage.
3105
+ * These forwarded events are only used to resolve
3106
+ * the original wrapped transaction promise.
3107
+ */
3108
+ const eventsHandler = eventEmitter => {
3109
+ const originEmitter = originTransaction === null || originTransaction === void 0 ? void 0 : originTransaction.emitterTransaction;
3110
+ if (!originEmitter) {
3111
+ return;
3112
+ }
3113
+ eventEmitter.on('signed', data => {
3114
+ originEmitter.emit('signed', data);
3115
+ });
3116
+ eventEmitter.on('error', data => {
3117
+ if (data.errors.length > 0) {
3118
+ originEmitter.emit('error', data);
3119
+ }
3120
+ });
3121
+ eventEmitter.on('timeout', data => {
3122
+ if (data.errors.length > 0 && data.errors.some(e => e.errorType === BasicTxErrorType.TIMEOUT)) {
3123
+ originEmitter.emit('timeout', data);
3124
+ }
3125
+ });
3126
+ };
3127
+
3128
+ /**
3129
+ * ─────────────────────────────
3130
+ * Submit wrapped transaction
3131
+ * ─────────────────────────────
3132
+ */
3133
+ return this.#koniState.transactionService.handleWrappedTransaction({
3134
+ address: signer,
3135
+ chain,
3136
+ chainType: ChainType.SUBSTRATE,
3137
+ extrinsicType: ExtrinsicType.MULTISIG_INIT_TX,
3138
+ transaction: multisigExtrinsic,
3139
+ skipFeeValidation: true,
3140
+ wrappingStatus: SubstrateTransactionWrappingStatus.WRAP_RESULT,
3141
+ data: {
3142
+ // input
3143
+ ...request,
3144
+ // output
3145
+ submittedCallData: multisigExtrinsic.toHex(),
3146
+ callData,
3147
+ decodedCallData,
3148
+ depositAmount,
3149
+ networkFee
3150
+ },
3151
+ additionalValidator,
3152
+ eventsHandler
3153
+ });
3154
+ }
3155
+
3156
+ // Substrate Proxy Account
3157
+ async handleSubstrateProxyWrappedTx(request) {
3158
+ const {
3159
+ chain,
3160
+ proxyMetadata,
3161
+ signer,
3162
+ transactionId
3163
+ } = request;
3164
+ const {
3165
+ proxiedAddress
3166
+ } = proxyMetadata;
3167
+
3168
+ /**
3169
+ * ─────────────────────────────
3170
+ * Prepare original transaction
3171
+ * ─────────────────────────────
3172
+ */
3173
+ const substrateApi = await this.#koniState.chainService.getSubstrateApi(chain).isReady;
3174
+ const originTransaction = this.#koniState.transactionService.getTransaction(transactionId);
3175
+ const extrinsicOriginTransaction = originTransaction === null || originTransaction === void 0 ? void 0 : originTransaction.transaction;
3176
+ const callData = extrinsicOriginTransaction.method.toHex();
3177
+ const decodedCallData = decodeCallData({
3178
+ api: substrateApi.api,
3179
+ callData
3180
+ });
3181
+
3182
+ /**
3183
+ * ─────────────────────────────
3184
+ * Determine proxy execution
3185
+ * ─────────────────────────────
3186
+ * If signer is the proxied address itself,
3187
+ * a substrate proxy transaction is NOT required.
3188
+ */
3189
+ const isSignerProxiedAccount = isSameAddress(signer, proxiedAddress);
3190
+
3191
+ /**
3192
+ * ─────────────────────────────
3193
+ * Fee calculation
3194
+ * ─────────────────────────────
3195
+ */
3196
+
3197
+ const substrateProxyExtrinsic = isSignerProxiedAccount ? extrinsicOriginTransaction : createInitSubstrateProxyExtrinsic(substrateApi.api, proxiedAddress, extrinsicOriginTransaction);
3198
+ const networkFee = (await substrateProxyExtrinsic.paymentInfo(signer)).partialFee.toString();
3199
+
3200
+ /**
3201
+ * ─────────────────────────────
3202
+ * Additional validation
3203
+ * ─────────────────────────────
3204
+ * Validate signer balance for proxy execution fee.
3205
+ */
3206
+ const additionalValidator = async inputTransaction => {
3207
+ const signerBalance = await this.getAddressTransferableBalance({
3208
+ address: signer,
3209
+ networkKey: chain,
3210
+ token: this.#koniState.chainService.getNativeTokenInfo(chain).slug,
3211
+ extrinsicType: ExtrinsicType.TRANSFER_TOKEN
3212
+ });
3213
+
3214
+ // todo: check and return better error for the case set token fee on hydration
3215
+ if (_SUPPORT_TOKEN_PAY_FEE_GROUP.hydration.includes(chain)) {
3216
+ var _substrateApi$api$que4;
3217
+ const setTokenPayFee = await ((_substrateApi$api$que4 = substrateApi.api.query.multiTransactionPayment) === null || _substrateApi$api$que4 === void 0 ? void 0 : _substrateApi$api$que4.accountCurrencyMap(signer));
3218
+ if (setTokenPayFee.toPrimitive()) {
3219
+ const account = getAccountJsonByAddress(signer);
3220
+ inputTransaction.errors.push(new TransactionError(BasicTxErrorType.NOT_ENOUGH_BALANCE, t('bg.koni.handler.Extension.proxyAccountNotEnoughBalance', {
3221
+ replace: {
3222
+ accountName: account === null || account === void 0 ? void 0 : account.name
3223
+ }
3224
+ })));
3225
+ }
3226
+ }
3227
+ if (BigInt(signerBalance.value) < BigInt(networkFee)) {
3228
+ const account = getAccountJsonByAddress(signer);
3229
+ inputTransaction.errors.push(new TransactionError(BasicTxErrorType.NOT_ENOUGH_BALANCE, t('bg.koni.handler.Extension.proxyAccountNotEnoughBalance', {
3230
+ replace: {
3231
+ accountName: account === null || account === void 0 ? void 0 : account.name
3232
+ }
3233
+ })));
3234
+ }
3235
+ };
3236
+
3237
+ /**
3238
+ * ─────────────────────────────
3239
+ * Event forwarding
3240
+ * ─────────────────────────────
3241
+ * The substrate proxy transaction acts as a wrapper.
3242
+ * Its lifecycle events are forwarded to the original
3243
+ * transaction to resolve the wrapped transaction promise.
3244
+ * update history transaction accordingly.
3245
+ */
3246
+ const eventsHandler = eventEmitter => {
3247
+ if (!(originTransaction !== null && originTransaction !== void 0 && originTransaction.emitterTransaction)) {
3248
+ return;
3249
+ }
3250
+ const originEmitter = originTransaction.emitterTransaction;
3251
+ eventEmitter.on('send', data => {
3252
+ originEmitter.emit('send', {
3253
+ ...data,
3254
+ id: originTransaction.id
3255
+ });
3256
+ });
3257
+ eventEmitter.on('signed', data => {
3258
+ originEmitter.emit('signed', {
3259
+ ...data,
3260
+ id: originTransaction.id
3261
+ });
3262
+ });
3263
+ eventEmitter.on('extrinsicHash', data => {
3264
+ originEmitter.emit('extrinsicHash', {
3265
+ ...data,
3266
+ id: originTransaction.id
3267
+ });
3268
+ });
3269
+ eventEmitter.on('success', data => {
3270
+ originEmitter.emit('success', {
3271
+ ...data,
3272
+ id: originTransaction.id
3273
+ });
3274
+ });
3275
+ eventEmitter.on('error', data => {
3276
+ if (data.errors.length > 0) {
3277
+ originEmitter.emit('error', {
3278
+ ...data,
3279
+ id: originTransaction.id
3280
+ });
3281
+ }
3282
+ });
3283
+ eventEmitter.on('timeout', data => {
3284
+ if (data.errors.some(error => error.errorType === BasicTxErrorType.TIMEOUT)) {
3285
+ originEmitter.emit('timeout', {
3286
+ ...data,
3287
+ id: originTransaction.id
3288
+ });
3289
+ }
3290
+ });
3291
+ };
3292
+
3293
+ /**
3294
+ * ─────────────────────────────
3295
+ * Execute wrapped transaction
3296
+ * ─────────────────────────────
3297
+ */
3298
+
3299
+ // Case 1: signer === proxied address → handle original transaction
3300
+ if (isSignerProxiedAccount) {
3301
+ let callDataFinal = callData;
3302
+ let decodedCallDataFinal = decodedCallData;
3303
+ const pendingMultisigTxRequest = originTransaction.data;
3304
+ if (pendingMultisigTxRequest.call && pendingMultisigTxRequest.decodedCallData) {
3305
+ callDataFinal = pendingMultisigTxRequest.call;
3306
+ decodedCallDataFinal = pendingMultisigTxRequest.decodedCallData;
3307
+ }
3308
+ const response = await this.#koniState.transactionService.handleWrappedTransaction({
3309
+ ...originTransaction,
3310
+ skipFeeValidation: false,
3311
+ data: {
3312
+ ...originTransaction.data,
3313
+ // output
3314
+ decodedCallData: decodedCallDataFinal,
3315
+ submittedCallData: substrateProxyExtrinsic.toHex(),
3316
+ callData: callDataFinal,
3317
+ networkFee
3318
+ },
3319
+ errors: [],
3320
+ // Clear previous errors
3321
+ wrappingStatus: SubstrateTransactionWrappingStatus.WRAP_RESULT,
3322
+ eventsHandler
3323
+ });
3324
+
3325
+ // Clear wrappingStatus since no wrapping is needed
3326
+ delete response.wrappingStatus;
3327
+ return response;
3328
+ }
3329
+
3330
+ // Case 2: create and handle substrate proxy transaction
3331
+ return await this.#koniState.transactionService.handleWrappedTransaction({
3332
+ address: signer,
3333
+ chain,
3334
+ chainType: ChainType.SUBSTRATE,
3335
+ extrinsicType: ExtrinsicType.SUBSTRATE_PROXY_INIT_TX,
3336
+ transaction: substrateProxyExtrinsic,
3337
+ skipFeeValidation: true,
3338
+ transferNativeAmount: originTransaction.transferNativeAmount,
3339
+ data: {
3340
+ // input
3341
+ ...request,
3342
+ // output
3343
+ decodedCallData,
3344
+ submittedCallData: substrateProxyExtrinsic.toHex(),
3345
+ callData,
3346
+ networkFee
3347
+ },
3348
+ wrappingStatus: SubstrateTransactionWrappingStatus.WRAP_RESULT,
3349
+ additionalValidator,
3350
+ eventsHandler
3351
+ });
3352
+ }
3353
+
2921
3354
  // EVM Transaction
2922
3355
  async parseContractInput({
2923
3356
  chainId,
@@ -3747,8 +4180,7 @@ export default class KoniExtension {
3747
4180
  isPassConfirmation,
3748
4181
  onSend,
3749
4182
  path,
3750
- processId,
3751
- signerSubstrateProxyAddress
4183
+ processId
3752
4184
  } = inputData;
3753
4185
  const {
3754
4186
  address
@@ -3879,7 +4311,6 @@ export default class KoniExtension {
3879
4311
  // change this depends on step
3880
4312
  chainType,
3881
4313
  resolveOnDone: !isLastStep,
3882
- signerSubstrateProxyAddress,
3883
4314
  transferNativeAmount,
3884
4315
  balanceType: balanceTypeForPool,
3885
4316
  skipFeeValidation: isMintingStep && isPoolSupportAlternativeFee,
@@ -3892,7 +4323,6 @@ export default class KoniExtension {
3892
4323
  async handleYieldLeave(params) {
3893
4324
  const {
3894
4325
  address,
3895
- signerSubstrateProxyAddress,
3896
4326
  slug
3897
4327
  } = params;
3898
4328
  const leaveValidation = await this.#koniState.earningService.validateYieldLeave(params);
@@ -3908,7 +4338,6 @@ export default class KoniExtension {
3908
4338
  data: params,
3909
4339
  // TODO
3910
4340
  extrinsicType,
3911
- signerSubstrateProxyAddress,
3912
4341
  chainType: (handler === null || handler === void 0 ? void 0 : handler.transactionChainType) || ChainType.SUBSTRATE
3913
4342
  });
3914
4343
  }
@@ -3985,7 +4414,6 @@ export default class KoniExtension {
3985
4414
  async yieldSubmitWithdrawal(params) {
3986
4415
  const {
3987
4416
  address,
3988
- signerSubstrateProxyAddress,
3989
4417
  slug
3990
4418
  } = params;
3991
4419
  const poolHandler = this.#koniState.earningService.getPoolHandler(slug);
@@ -3999,7 +4427,6 @@ export default class KoniExtension {
3999
4427
  transaction: extrinsic,
4000
4428
  data: params,
4001
4429
  extrinsicType: ExtrinsicType.STAKING_WITHDRAW,
4002
- signerSubstrateProxyAddress,
4003
4430
  chainType: (poolHandler === null || poolHandler === void 0 ? void 0 : poolHandler.transactionChainType) || ChainType.SUBSTRATE
4004
4431
  });
4005
4432
  }
@@ -4007,7 +4434,6 @@ export default class KoniExtension {
4007
4434
  const {
4008
4435
  address,
4009
4436
  selectedUnstaking,
4010
- signerSubstrateProxyAddress,
4011
4437
  slug
4012
4438
  } = params;
4013
4439
  const poolHandler = this.#koniState.earningService.getPoolHandler(slug);
@@ -4022,14 +4448,12 @@ export default class KoniExtension {
4022
4448
  transaction: extrinsic,
4023
4449
  data: params,
4024
4450
  extrinsicType: ExtrinsicType.STAKING_CANCEL_UNSTAKE,
4025
- signerSubstrateProxyAddress,
4026
4451
  chainType: (poolHandler === null || poolHandler === void 0 ? void 0 : poolHandler.transactionChainType) || ChainType.SUBSTRATE
4027
4452
  });
4028
4453
  }
4029
4454
  async yieldSubmitClaimReward(params) {
4030
4455
  const {
4031
4456
  address,
4032
- signerSubstrateProxyAddress,
4033
4457
  slug
4034
4458
  } = params;
4035
4459
  const poolHandler = this.#koniState.earningService.getPoolHandler(slug);
@@ -4042,7 +4466,6 @@ export default class KoniExtension {
4042
4466
  chain: poolHandler.chain,
4043
4467
  transaction: extrinsic,
4044
4468
  data: params,
4045
- signerSubstrateProxyAddress,
4046
4469
  extrinsicType: ExtrinsicType.STAKING_CLAIM_REWARD,
4047
4470
  chainType: (poolHandler === null || poolHandler === void 0 ? void 0 : poolHandler.transactionChainType) || ChainType.SUBSTRATE
4048
4471
  });
@@ -4061,7 +4484,6 @@ export default class KoniExtension {
4061
4484
  async handleYieldChangeValidator(params) {
4062
4485
  const {
4063
4486
  address,
4064
- signerSubstrateProxyAddress,
4065
4487
  slug
4066
4488
  } = params;
4067
4489
  const poolHandler = this.#koniState.earningService.getPoolHandler(slug);
@@ -4074,7 +4496,6 @@ export default class KoniExtension {
4074
4496
  chain: poolHandler.chain,
4075
4497
  transaction: extrinsic,
4076
4498
  data: params,
4077
- signerSubstrateProxyAddress,
4078
4499
  extrinsicType: ExtrinsicType.CHANGE_EARNING_VALIDATOR,
4079
4500
  chainType: ChainType.SUBSTRATE
4080
4501
  });
@@ -4444,8 +4865,8 @@ export default class KoniExtension {
4444
4865
  });
4445
4866
  return await this.#koniState.inappNotificationService.getUnreadNotificationsCountMap();
4446
4867
  }
4447
- markAllReadNotification(proxyId) {
4448
- return this.#koniState.inappNotificationService.markAllRead(proxyId);
4868
+ markAllReadNotification(params) {
4869
+ return this.#koniState.inappNotificationService.markAllRead(params);
4449
4870
  }
4450
4871
  switchReadNotificationStatus(params) {
4451
4872
  return this.#koniState.inappNotificationService.switchReadStatus(params);
@@ -4762,10 +5183,9 @@ export default class KoniExtension {
4762
5183
  async handleAddSubstrateProxyAccount(params) {
4763
5184
  const {
4764
5185
  address,
4765
- chain,
4766
- signerSubstrateProxyAddress
5186
+ chain
4767
5187
  } = params;
4768
- const validationErrors = await this.#koniState.substrateProxyAccountService.validateAddSubstrateProxyAccount(params, signerSubstrateProxyAddress);
5188
+ const validationErrors = await this.#koniState.substrateProxyAccountService.validateAddSubstrateProxyAccount(params);
4769
5189
  if (validationErrors.length > 0) {
4770
5190
  return this.#koniState.transactionService.generateBeforeHandleResponseErrors(validationErrors);
4771
5191
  }
@@ -4776,15 +5196,13 @@ export default class KoniExtension {
4776
5196
  transaction: extrinsic,
4777
5197
  data: params,
4778
5198
  extrinsicType: ExtrinsicType.ADD_SUBSTRATE_PROXY_ACCOUNT,
4779
- chainType: ChainType.SUBSTRATE,
4780
- signerSubstrateProxyAddress
5199
+ chainType: ChainType.SUBSTRATE
4781
5200
  });
4782
5201
  }
4783
5202
  async handleRemoveSubstrateProxyAccount(params) {
4784
5203
  const {
4785
5204
  address,
4786
- chain,
4787
- signerSubstrateProxyAddress
5205
+ chain
4788
5206
  } = params;
4789
5207
  const extrinsic = await this.#koniState.substrateProxyAccountService.removeSubstrateProxyAccounts(params);
4790
5208
  return await this.#koniState.transactionService.handleTransaction({
@@ -4793,8 +5211,7 @@ export default class KoniExtension {
4793
5211
  transaction: extrinsic,
4794
5212
  data: params,
4795
5213
  extrinsicType: ExtrinsicType.REMOVE_SUBSTRATE_PROXY_ACCOUNT,
4796
- chainType: ChainType.SUBSTRATE,
4797
- signerSubstrateProxyAddress
5214
+ chainType: ChainType.SUBSTRATE
4798
5215
  });
4799
5216
  }
4800
5217
 
@@ -4810,8 +5227,7 @@ export default class KoniExtension {
4810
5227
  transaction: extrinsic,
4811
5228
  data: request,
4812
5229
  extrinsicType: ExtrinsicType.GOV_VOTE,
4813
- chainType: ChainType.SUBSTRATE,
4814
- signerSubstrateProxyAddress: request.signerSubstrateProxyAddress
5230
+ chainType: ChainType.SUBSTRATE
4815
5231
  });
4816
5232
  }
4817
5233
  async handleRemoveVote(request) {
@@ -4822,8 +5238,7 @@ export default class KoniExtension {
4822
5238
  transaction: extrinsic,
4823
5239
  data: request,
4824
5240
  extrinsicType: ExtrinsicType.GOV_UNVOTE,
4825
- chainType: ChainType.SUBSTRATE,
4826
- signerSubstrateProxyAddress: request.signerSubstrateProxyAddress
5241
+ chainType: ChainType.SUBSTRATE
4827
5242
  });
4828
5243
  }
4829
5244
  async handleUnlockVote(request) {
@@ -4834,8 +5249,7 @@ export default class KoniExtension {
4834
5249
  transaction: extrinsic,
4835
5250
  data: request,
4836
5251
  extrinsicType: ExtrinsicType.GOV_UNLOCK_VOTE,
4837
- chainType: ChainType.SUBSTRATE,
4838
- signerSubstrateProxyAddress: request.signerSubstrateProxyAddress
5252
+ chainType: ChainType.SUBSTRATE
4839
5253
  });
4840
5254
  }
4841
5255
  async subscribeGovLockedInfo(id, port) {
@@ -4855,6 +5269,25 @@ export default class KoniExtension {
4855
5269
 
4856
5270
  /* Open Gov */
4857
5271
 
5272
+ /* Multisig Acocunt */
5273
+
5274
+ async subscribePendingMultisigTx(id, port) {
5275
+ const cb = createSubscription(id, port);
5276
+ await this.#koniState.multisigService.waitForStarted();
5277
+ const pendingTxSubscription = this.#koniState.multisigService.subscribePendingMultisigTxMap().subscribe({
5278
+ next: rs => {
5279
+ cb(rs);
5280
+ }
5281
+ });
5282
+ this.createUnsubscriptionHandle(id, pendingTxSubscription.unsubscribe);
5283
+ port.onDisconnect.addListener(() => {
5284
+ this.cancelSubscription(id);
5285
+ });
5286
+ return this.#koniState.multisigService.getPendingMultisigTxMap();
5287
+ }
5288
+
5289
+ /* Multisig Acocunt */
5290
+
4858
5291
  // --------------------------------------------------------------
4859
5292
  // eslint-disable-next-line @typescript-eslint/require-await
4860
5293
  async handle(id, type, request, port) {
@@ -5061,6 +5494,8 @@ export default class KoniExtension {
5061
5494
  return this.accountsCreateSuriV2(request);
5062
5495
  case 'pri(accounts.create.externalV2)':
5063
5496
  return await this.accountsCreateExternalV2(request);
5497
+ case 'pri(accounts.create.multisig)':
5498
+ return await this.accountsCreateMultisig(request);
5064
5499
  case 'pri(accounts.create.hardwareV2)':
5065
5500
  return await this.accountsCreateHardwareV2(request);
5066
5501
  case 'pri(accounts.create.hardwareMultiple)':
@@ -5513,6 +5948,7 @@ export default class KoniExtension {
5513
5948
  return this.migrateSoloAccount(request);
5514
5949
  case 'pri(migrate.pingSession)':
5515
5950
  return this.pingSession(request);
5951
+ /* Migrate Unified Account */
5516
5952
 
5517
5953
  /* Gov */
5518
5954
  case 'pri(openGov.vote)':
@@ -5523,6 +5959,24 @@ export default class KoniExtension {
5523
5959
  return this.handleUnlockVote(request);
5524
5960
  case 'pri(openGov.subscribeGovLockedInfo)':
5525
5961
  return this.subscribeGovLockedInfo(id, port);
5962
+ /* Gov */
5963
+
5964
+ /* Multisig Account */
5965
+ case 'pri(multisig.subscribePendingMultisigTxs)':
5966
+ return await this.subscribePendingMultisigTx(id, port);
5967
+ case 'pri(multisig.getPendingMultisigTxs)':
5968
+ return this.#koniState.multisigService.getPendingTxsForMultisigAddress(request);
5969
+ case 'pri(multisig.approvePendingTx)':
5970
+ return await this.approvePendingTx(request);
5971
+ case 'pri(multisig.executePendingTx)':
5972
+ return await this.executePendingTx(request);
5973
+ case 'pri(multisig.cancelPendingTx)':
5974
+ return await this.cancelPendingTx(request);
5975
+ case 'pri(multisig.initMultisigTx)':
5976
+ return await this.initMultisigTx(request);
5977
+ case 'pri(multisig.getSignableAccountInfos)':
5978
+ return this.#koniState.keyringService.context.getSignableAccountInfos(request);
5979
+ /* Multisig Account */
5526
5980
 
5527
5981
  // Proxy
5528
5982
  case 'pri(substrateProxyAccount.getGroupInfo)':
@@ -5531,7 +5985,8 @@ export default class KoniExtension {
5531
5985
  return this.handleAddSubstrateProxyAccount(request);
5532
5986
  case 'pri(substrateProxyAccount.remove)':
5533
5987
  return this.handleRemoveSubstrateProxyAccount(request);
5534
-
5988
+ case 'pri(substrateProxyAccount.handleProxyWrappedTx)':
5989
+ return this.handleSubstrateProxyWrappedTx(request);
5535
5990
  // Default
5536
5991
  default:
5537
5992
  throw new Error(`Unable to handle message of type ${type}`);