@subwallet/extension-base 1.3.75-2 → 1.3.77-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 (63) hide show
  1. package/background/KoniTypes.d.ts +6 -2
  2. package/background/KoniTypes.js +1 -0
  3. package/cjs/background/KoniTypes.js +1 -0
  4. package/cjs/core/substrate/xcm-parser.js +8 -11
  5. package/cjs/koni/background/handlers/Extension.js +279 -64
  6. package/cjs/koni/background/handlers/Tabs.js +2 -3
  7. package/cjs/packageInfo.js +1 -1
  8. package/cjs/services/balance-service/index.js +6 -1
  9. package/cjs/services/chain-service/index.js +1 -1
  10. package/cjs/services/chain-service/utils/patch.js +1 -1
  11. package/cjs/services/earning-service/constants/chains.js +4 -1
  12. package/cjs/services/earning-service/handlers/liquid-staking/stella-swap.js +8 -5
  13. package/cjs/services/earning-service/handlers/native-staking/dtao.js +85 -113
  14. package/cjs/services/earning-service/handlers/native-staking/tanssi.js +2 -1
  15. package/cjs/services/earning-service/handlers/native-staking/tao.js +85 -100
  16. package/cjs/services/earning-service/service.js +35 -4
  17. package/cjs/services/multisig-service/index.js +1 -1
  18. package/cjs/services/request-service/handler/SubstrateRequestHandler.js +12 -0
  19. package/cjs/services/request-service/index.js +3 -0
  20. package/cjs/services/setting-service/constants.js +2 -1
  21. package/cjs/services/storage-service/db-stores/InappNotification.js +1 -1
  22. package/cjs/services/substrate-proxy-service/constant.js +1 -1
  23. package/cjs/services/transaction-service/index.js +9 -0
  24. package/cjs/utils/account/transform.js +3 -3
  25. package/core/substrate/xcm-parser.d.ts +1 -0
  26. package/core/substrate/xcm-parser.js +7 -11
  27. package/koni/background/handlers/Extension.d.ts +20 -0
  28. package/koni/background/handlers/Extension.js +218 -6
  29. package/koni/background/handlers/Tabs.js +2 -3
  30. package/package.json +6 -6
  31. package/packageInfo.js +1 -1
  32. package/services/balance-service/index.js +6 -1
  33. package/services/chain-service/index.js +1 -1
  34. package/services/chain-service/utils/patch.d.ts +1 -1
  35. package/services/chain-service/utils/patch.js +1 -1
  36. package/services/earning-service/constants/chains.d.ts +1 -0
  37. package/services/earning-service/constants/chains.js +2 -0
  38. package/services/earning-service/handlers/liquid-staking/stella-swap.d.ts +1 -0
  39. package/services/earning-service/handlers/liquid-staking/stella-swap.js +6 -4
  40. package/services/earning-service/handlers/native-staking/dtao.d.ts +2 -10
  41. package/services/earning-service/handlers/native-staking/dtao.js +86 -116
  42. package/services/earning-service/handlers/native-staking/tanssi.js +2 -1
  43. package/services/earning-service/handlers/native-staking/tao.d.ts +4 -3
  44. package/services/earning-service/handlers/native-staking/tao.js +84 -101
  45. package/services/earning-service/service.d.ts +2 -1
  46. package/services/earning-service/service.js +37 -6
  47. package/services/inapp-notification-service/interfaces.d.ts +1 -0
  48. package/services/multisig-service/index.js +1 -1
  49. package/services/request-service/handler/SubstrateRequestHandler.d.ts +1 -0
  50. package/services/request-service/handler/SubstrateRequestHandler.js +12 -0
  51. package/services/request-service/index.d.ts +1 -0
  52. package/services/request-service/index.js +3 -0
  53. package/services/request-service/types.d.ts +1 -0
  54. package/services/setting-service/constants.js +2 -1
  55. package/services/storage-service/db-stores/InappNotification.js +1 -1
  56. package/services/substrate-proxy-service/constant.js +1 -1
  57. package/services/transaction-service/index.d.ts +1 -1
  58. package/services/transaction-service/index.js +9 -0
  59. package/types/balance/transfer.d.ts +2 -0
  60. package/types/multisig/index.d.ts +12 -0
  61. package/types/yield/actions/join/submit.d.ts +8 -1
  62. package/types/yield/info/account/info.d.ts +11 -5
  63. package/utils/account/transform.js +3 -3
@@ -98,8 +98,6 @@ class EarningService {
98
98
  handlers.push(new _handlers.AmplitudeNativeStakingPoolHandler(this.state, chain));
99
99
  }
100
100
  if (_constants2._STAKING_CHAIN_GROUP.bittensor.includes(chain)) {
101
- // todo: check support for testnet
102
- // Mainnet only
103
101
  handlers.push(new _handlers.TaoNativeStakingPoolHandler(this.state, chain));
104
102
  handlers.push(new _handlers.SubnetTaoStakingPoolHandler(this.state, chain));
105
103
  }
@@ -443,6 +441,14 @@ class EarningService {
443
441
  }
444
442
  const updatedItem = structuredClone(item);
445
443
  updatedItem.metadata.availableMethod = handler.availableMethod;
444
+
445
+ // Disable staking for sunsetted pools
446
+ if (_constants2.SUNSETTED_YIELD_POOL_SLUGS.includes(item.slug)) {
447
+ updatedItem.metadata.availableMethod = {
448
+ ...updatedItem.metadata.availableMethod,
449
+ join: false
450
+ };
451
+ }
446
452
  this.updateYieldPoolInfo(updatedItem);
447
453
  });
448
454
  return onlineData;
@@ -537,7 +543,11 @@ class EarningService {
537
543
  const yieldPositionInfo = this.yieldPositionSubject.getValue();
538
544
  existedYieldPosition.forEach(item => {
539
545
  if (!this.inactivePoolSlug.has(item.slug)) {
540
- yieldPositionInfo[this._getYieldPositionKey(item.slug, item.address)] = item;
546
+ const normalizedItem = _constants2.SUNSETTED_YIELD_POOL_SLUGS.includes(item.slug) ? {
547
+ ...item,
548
+ status: _types2.EarningStatus.NOT_EARNING
549
+ } : item;
550
+ yieldPositionInfo[this._getYieldPositionKey(item.slug, item.address)] = normalizedItem;
541
551
  }
542
552
  });
543
553
  this.yieldPositionSubject.next(yieldPositionInfo);
@@ -560,7 +570,11 @@ class EarningService {
560
570
  return `${slug}---${address}`;
561
571
  }
562
572
  updateYieldPosition(data) {
563
- this.yieldPositionPersistQueue.push(data);
573
+ const normalizedData = _constants2.SUNSETTED_YIELD_POOL_SLUGS.includes(data.slug) ? {
574
+ ...data,
575
+ status: _types2.EarningStatus.NOT_EARNING
576
+ } : data;
577
+ this.yieldPositionPersistQueue.push(normalizedData);
564
578
  (0, _utils2.addLazy)('persistYieldPositionInfo', () => {
565
579
  const yieldPositionInfo = this.yieldPositionSubject.getValue();
566
580
  const queue = [...this.yieldPositionPersistQueue];
@@ -994,6 +1008,23 @@ class EarningService {
994
1008
  return Promise.reject(new _TransactionError.TransactionError(_types2.BasicTxErrorType.INTERNAL_ERROR));
995
1009
  }
996
1010
  }
1011
+ async handleChangeRootClaimType(params) {
1012
+ await this.eventService.waitChainReady;
1013
+ const {
1014
+ bittensorRootClaimType,
1015
+ chain,
1016
+ slug
1017
+ } = params;
1018
+ if (!_constants2._STAKING_CHAIN_GROUP.bittensor.includes(chain)) {
1019
+ return Promise.reject(new _TransactionError.TransactionError(_types2.BasicTxErrorType.UNSUPPORTED));
1020
+ }
1021
+ const handler = this.getPoolHandler(slug);
1022
+ if (handler) {
1023
+ return handler.handleChangeRootClaimType(bittensorRootClaimType);
1024
+ } else {
1025
+ return Promise.reject(new _TransactionError.TransactionError(_types2.BasicTxErrorType.INTERNAL_ERROR));
1026
+ }
1027
+ }
997
1028
 
998
1029
  /* Other */
999
1030
 
@@ -212,7 +212,7 @@ class MultisigService {
212
212
  */
213
213
  handleEvents(events, eventTypes) {
214
214
  let needReload = false;
215
- if (eventTypes.includes('account.add') || eventTypes.includes('account.remove')) {
215
+ if (eventTypes.includes('account.add') || eventTypes.includes('account.remove') || eventTypes.includes('account.updateCurrent')) {
216
216
  needReload = true;
217
217
  }
218
218
  if (eventTypes.includes('chain.updateState') || eventTypes.includes('transaction.done')) {
@@ -44,6 +44,18 @@ class SubstrateRequestHandler {
44
44
  };
45
45
  });
46
46
  }
47
+ updateSignRequest(id, request, signerAddress) {
48
+ const current = this.getSignRequest(id);
49
+ if (!current) {
50
+ throw new _TransactionError.TransactionError(_types.BasicTxErrorType.INVALID_PARAMS, 'Sign request not found');
51
+ }
52
+ this.#substrateRequests[id] = {
53
+ ...current,
54
+ request,
55
+ signerAddress: signerAddress || current.signerAddress
56
+ };
57
+ this.updateIconSign();
58
+ }
47
59
  updateIconSign(shouldClose) {
48
60
  this.signSubject.next(this.allSubstrateRequests);
49
61
  this.#requestService.updateIconV2(shouldClose);
@@ -175,6 +175,9 @@ class RequestService {
175
175
  getSignRequest(id) {
176
176
  return this.#substrateRequestHandler.getSignRequest(id);
177
177
  }
178
+ updateSignRequest(id, request, signerAddress) {
179
+ this.#substrateRequestHandler.updateSignRequest(id, request, signerAddress);
180
+ }
178
181
  async signInternalTransaction(id, address, url, payload, onSign, isWrappedTx) {
179
182
  if (isWrappedTx === _types.SubstrateTransactionWrappingStatus.WRAP_RESULT) {
180
183
  return this.#substrateRequestHandler.signWrappedTransaction(id, address, url, payload, onSign);
@@ -41,7 +41,8 @@ const DEFAULT_NOTIFICATION_SETUP = {
41
41
  earningClaim: true,
42
42
  earningWithdraw: true,
43
43
  availBridgeClaim: true,
44
- polygonBridgeClaim: true
44
+ polygonBridgeClaim: true,
45
+ pendingMultisigApprovals: true
45
46
  // isHideWithdraw: false, // todo: just for test, remove later
46
47
  // isHideMarketing: false,
47
48
  // isHideAnnouncement: false
@@ -89,7 +89,7 @@ class InappNotificationStore extends _BaseStore.default {
89
89
  isRead: true
90
90
  });
91
91
  }
92
- return this.table.where('proxyId').equalsIgnoreCase(proxyId).modify({
92
+ return this.table.where('proxyId').equalsIgnoreCase(proxyId).filter(notification => !excludeNotificationIds.includes(notification.id)).modify({
93
93
  isRead: true
94
94
  });
95
95
  }
@@ -9,7 +9,7 @@ var _KoniTypes = require("@subwallet/extension-base/background/KoniTypes");
9
9
  // SPDX-License-Identifier: Apache-2.0
10
10
 
11
11
  const SUBSTRATE_PROXY_ACCOUNT_EXTRINSIC_GROUPS = {
12
- STAKING: [_KoniTypes.ExtrinsicType.STAKING_BOND, _KoniTypes.ExtrinsicType.STAKING_UNBOND, _KoniTypes.ExtrinsicType.STAKING_WITHDRAW, _KoniTypes.ExtrinsicType.STAKING_JOIN_POOL, _KoniTypes.ExtrinsicType.STAKING_LEAVE_POOL, _KoniTypes.ExtrinsicType.CHANGE_EARNING_VALIDATOR, _KoniTypes.ExtrinsicType.STAKING_CANCEL_UNSTAKE, _KoniTypes.ExtrinsicType.STAKING_CLAIM_REWARD],
12
+ STAKING: [_KoniTypes.ExtrinsicType.STAKING_BOND, _KoniTypes.ExtrinsicType.STAKING_UNBOND, _KoniTypes.ExtrinsicType.STAKING_WITHDRAW, _KoniTypes.ExtrinsicType.STAKING_JOIN_POOL, _KoniTypes.ExtrinsicType.STAKING_LEAVE_POOL, _KoniTypes.ExtrinsicType.CHANGE_EARNING_VALIDATOR, _KoniTypes.ExtrinsicType.STAKING_CANCEL_UNSTAKE, _KoniTypes.ExtrinsicType.STAKING_CLAIM_REWARD, _KoniTypes.ExtrinsicType.CHANGE_BITTENSOR_ROOT_CLAIM_TYPE],
13
13
  GOV: [_KoniTypes.ExtrinsicType.GOV_VOTE, _KoniTypes.ExtrinsicType.GOV_UNVOTE, _KoniTypes.ExtrinsicType.GOV_UNLOCK_VOTE],
14
14
  PROXY: [
15
15
  // only type any can add proxy
@@ -1378,6 +1378,15 @@ class TransactionService {
1378
1378
  case _KoniTypes.ExtrinsicType.UNKNOWN:
1379
1379
  break;
1380
1380
  }
1381
+ const txData = transaction.data;
1382
+ const signer = txData === null || txData === void 0 ? void 0 : txData.signer;
1383
+ if (signer) {
1384
+ const currentAdditionalInfo = historyItem.additionalInfo ? historyItem.additionalInfo : {};
1385
+ historyItem.additionalInfo = {
1386
+ ...currentAdditionalInfo,
1387
+ signer
1388
+ };
1389
+ }
1381
1390
  try {
1382
1391
  // Return one more history record if transaction send to account in the wallets
1383
1392
  const toAccount = (historyItem === null || historyItem === void 0 ? void 0 : historyItem.to) && _uiKeyring.default.getPair(historyItem.to);
@@ -177,7 +177,7 @@ const getAccountTransactionActions = (signMode, networkType, type, _meta, _speci
177
177
  if ([_types2.AccountSignMode.PASSWORD, _types2.AccountSignMode.INJECTED].includes(signMode)) {
178
178
  switch (networkType) {
179
179
  case _types2.AccountChainType.SUBSTRATE:
180
- return [...BASE_TRANSFER_ACTIONS, ...NATIVE_STAKE_ACTIONS, ...POOL_STAKE_ACTIONS, ...EARN_VDOT_ACTIONS, ...EARN_LDOT_ACTIONS, ...EARN_SDOT_ACTIONS, ...EARN_QDOT_ACTIONS, ...EARN_VMANTA_ACTIONS, ...CLAIM_AVAIL_BRIDGE, ...OPEN_GOV_ACTIONS, ...MULTISIG_ACTIONS, ...SUBSTRATE_PROXY_ACTION, ...OTHER_ACTIONS];
180
+ return [...BASE_TRANSFER_ACTIONS, ...NATIVE_STAKE_ACTIONS, ...POOL_STAKE_ACTIONS, ...EARN_VDOT_ACTIONS, ...EARN_LDOT_ACTIONS, ...EARN_SDOT_ACTIONS, ...EARN_QDOT_ACTIONS, ...EARN_VMANTA_ACTIONS, ...CLAIM_AVAIL_BRIDGE, ...OPEN_GOV_ACTIONS, _KoniTypes.ExtrinsicType.CHANGE_BITTENSOR_ROOT_CLAIM_TYPE, ...MULTISIG_ACTIONS, ...SUBSTRATE_PROXY_ACTION, ...OTHER_ACTIONS];
181
181
  case _types2.AccountChainType.ETHEREUM:
182
182
  return [...BASE_TRANSFER_ACTIONS, ...NATIVE_STAKE_ACTIONS, ...POOL_STAKE_ACTIONS, ...EARN_STDOT_ACTIONS, ...OTHER_ACTIONS, ...CLAIM_AVAIL_BRIDGE, ...SUBSTRATE_PROXY_ACTION, ...EVM_ACTIONS];
183
183
  case _types2.AccountChainType.TON:
@@ -190,7 +190,7 @@ const getAccountTransactionActions = (signMode, networkType, type, _meta, _speci
190
190
  } else if (signMode === _types2.AccountSignMode.QR) {
191
191
  switch (networkType) {
192
192
  case _types2.AccountChainType.SUBSTRATE:
193
- return [...BASE_TRANSFER_ACTIONS, ...NATIVE_STAKE_ACTIONS, ...POOL_STAKE_ACTIONS, ...EARN_VDOT_ACTIONS, ...EARN_LDOT_ACTIONS, ...EARN_SDOT_ACTIONS, ...EARN_QDOT_ACTIONS, ...EARN_VMANTA_ACTIONS, ...CLAIM_AVAIL_BRIDGE, ...OPEN_GOV_ACTIONS, ...MULTISIG_ACTIONS, ...SUBSTRATE_PROXY_ACTION, ...OTHER_ACTIONS];
193
+ return [...BASE_TRANSFER_ACTIONS, ...NATIVE_STAKE_ACTIONS, ...POOL_STAKE_ACTIONS, ...EARN_VDOT_ACTIONS, ...EARN_LDOT_ACTIONS, ...EARN_SDOT_ACTIONS, ...EARN_QDOT_ACTIONS, ...EARN_VMANTA_ACTIONS, ...CLAIM_AVAIL_BRIDGE, ...OPEN_GOV_ACTIONS, _KoniTypes.ExtrinsicType.CHANGE_BITTENSOR_ROOT_CLAIM_TYPE, ...MULTISIG_ACTIONS, ...SUBSTRATE_PROXY_ACTION, ...OTHER_ACTIONS];
194
194
  case _types2.AccountChainType.ETHEREUM:
195
195
  return [...(_constants.isProductionMode ? [] : [...BASE_TRANSFER_ACTIONS, ...NATIVE_STAKE_ACTIONS, ...POOL_STAKE_ACTIONS, ...EARN_STDOT_ACTIONS, ...CLAIM_AVAIL_BRIDGE, ...OTHER_ACTIONS, ...EVM_ACTIONS])];
196
196
  case _types2.AccountChainType.TON:
@@ -224,7 +224,7 @@ const getAccountTransactionActions = (signMode, networkType, type, _meta, _speci
224
224
  case _types2.AccountChainType.SUBSTRATE:
225
225
  return [...BASE_TRANSFER_ACTIONS, ...NATIVE_STAKE_ACTIONS, ...POOL_STAKE_ACTIONS, ...EARN_VDOT_ACTIONS, ...EARN_VMANTA_ACTIONS, ...EARN_LDOT_ACTIONS, ...EARN_SDOT_ACTIONS,
226
226
  // ...EARN_QDOT_ACTIONS,
227
- ...OPEN_GOV_ACTIONS, ...MULTISIG_ACTIONS, ...SUBSTRATE_PROXY_ACTION, ...OTHER_ACTIONS];
227
+ ...OPEN_GOV_ACTIONS, _KoniTypes.ExtrinsicType.CHANGE_BITTENSOR_ROOT_CLAIM_TYPE, ...MULTISIG_ACTIONS, ...SUBSTRATE_PROXY_ACTION, ...OTHER_ACTIONS];
228
228
  case _types2.AccountChainType.ETHEREUM:
229
229
  return [...BASE_TRANSFER_ACTIONS, ...EARN_STDOT_ACTIONS, ...EVM_ACTIONS, ...CLAIM_AVAIL_BRIDGE, _KoniTypes.ExtrinsicType.STAKING_WITHDRAW,
230
230
  // For liquid staking
@@ -8,4 +8,5 @@ export declare function _isMythosFromHydrationToMythos(originChainInfo: _ChainIn
8
8
  export declare function _isPolygonBridgeXcm(originChainInfo: _ChainInfo, destChainInfo: _ChainInfo): boolean;
9
9
  export declare function _isPosBridgeXcm(originChainInfo: _ChainInfo, destChainInfo: _ChainInfo): boolean;
10
10
  export declare function _isAcrossBridgeXcm(originChainInfo: _ChainInfo, destChainInfo: _ChainInfo): boolean;
11
+ export declare function _isAssetHubBridgeXcm(originChainInfo: _ChainInfo, destChainInfo: _ChainInfo): boolean;
11
12
  export declare function _adaptX1Interior(_assetIdentifier: Record<string, any>, version: number): Record<string, any>;
@@ -8,17 +8,10 @@ import { _isPolygonChainBridge } from '@subwallet/extension-base/services/balanc
8
8
  import { _isPosChainBridge } from '@subwallet/extension-base/services/balance-service/transfer/xcm/posBridge';
9
9
  import { _getSubstrateRelayParent, _isPureEvmChain } from '@subwallet/extension-base/services/chain-service/utils';
10
10
  export function _isXcmTransferUnstable(originChainInfo, destChainInfo, assetSlug) {
11
- return !_isXcmWithinSameConsensus(originChainInfo, destChainInfo) || _isMythosFromHydrationToMythos(originChainInfo, destChainInfo, assetSlug) || _isPolygonBridgeXcm(originChainInfo, destChainInfo) || _isPosBridgeXcm(originChainInfo, destChainInfo);
11
+ return !_isXcmWithinSameConsensus(originChainInfo, destChainInfo) && !_isAssetHubBridgeXcm || _isMythosFromHydrationToMythos(originChainInfo, destChainInfo, assetSlug) || _isPolygonBridgeXcm(originChainInfo, destChainInfo) || _isPosBridgeXcm(originChainInfo, destChainInfo);
12
12
  }
13
- function getAssetHubBridgeUnstableWarning(originChainInfo) {
14
- switch (originChainInfo.slug) {
15
- case COMMON_CHAIN_SLUGS.POLKADOT_ASSET_HUB:
16
- return 'Cross-chain transfer of this token is not recommended as it is in beta and incurs a transaction fee of 2 DOT. Continue at your own risk';
17
- case COMMON_CHAIN_SLUGS.KUSAMA_ASSET_HUB:
18
- return 'Cross-chain transfer of this token is not recommended as it is in beta and incurs a transaction fee of 0.4 KSM. Continue at your own risk';
19
- default:
20
- return 'Cross-chain transfer of this token is not recommended as it is in beta and incurs a large transaction fee. Continue at your own risk';
21
- }
13
+ function getDefaultUnstableWarning() {
14
+ return 'Cross-chain transfer of this token is not recommended as it is in beta and incurs a large transaction fee. Continue at your own risk';
22
15
  }
23
16
  function getSnowBridgeUnstableWarning(originChainInfo) {
24
17
  switch (originChainInfo.slug) {
@@ -62,7 +55,7 @@ export function _getXcmUnstableWarning(originChainInfo, destChainInfo, assetSlug
62
55
  } else if (_isMythosFromHydrationToMythos(originChainInfo, destChainInfo, assetSlug)) {
63
56
  return getMythosFromHydrationToMythosWarning();
64
57
  } else {
65
- return getAssetHubBridgeUnstableWarning(originChainInfo);
58
+ return getDefaultUnstableWarning();
66
59
  }
67
60
  }
68
61
  export function _isXcmWithinSameConsensus(originChainInfo, destChainInfo) {
@@ -88,6 +81,9 @@ export function _isPosBridgeXcm(originChainInfo, destChainInfo) {
88
81
  export function _isAcrossBridgeXcm(originChainInfo, destChainInfo) {
89
82
  return _isAcrossChainBridge(originChainInfo.slug, destChainInfo.slug);
90
83
  }
84
+ export function _isAssetHubBridgeXcm(originChainInfo, destChainInfo) {
85
+ return originChainInfo.slug === 'statemint' && destChainInfo.slug === 'statemine' || originChainInfo.slug === 'statemine' && destChainInfo.slug === 'statemint';
86
+ }
91
87
  // ---------------------------------------------------------------------------------------------------------------------
92
88
 
93
89
  export function _adaptX1Interior(_assetIdentifier, version) {
@@ -188,6 +188,25 @@ export default class KoniExtension {
188
188
  private executePendingTx;
189
189
  private cancelPendingTx;
190
190
  private initMultisigTx;
191
+ private buildExtrinsicFromPayload;
192
+ /**
193
+ * ─────────────────────────────────────────────────────────────
194
+ * prepareMultisigSignRequest
195
+ * ─────────────────────────────────────────────────────────────
196
+ * Called when a dApp sends a signing request to a multisig account.
197
+ * This method wraps the original extrinsic into a multisig.asMulti call so that it can be submitted by one of the signers on behalf of the multisig account.
198
+ *
199
+ * Important:
200
+ * - The original sign request is MUTATED in-place via updateSignRequest.
201
+ * After this method returns, the UI will prompt the signer to sign
202
+ * the wrapped multisig extrinsic, not the original one.
203
+ * - Errors are collected (not thrown) and returned in the response
204
+ * so the UI can display them without crashing.
205
+ * - This method does NOT submit the transaction; it only prepares
206
+ * the payload for signing.
207
+ * ─────────────────────────────────────────────────────────────
208
+ */
209
+ private prepareMultisigSignRequest;
191
210
  private handleSubstrateProxyWrappedTx;
192
211
  private parseContractInput;
193
212
  private submitTuringStakeCompounding;
@@ -265,6 +284,7 @@ export default class KoniExtension {
265
284
  private yieldSubmitClaimReward;
266
285
  private yieldGetEarningImpact;
267
286
  private handleYieldChangeValidator;
287
+ private handleChangeBittensorRootClaimType;
268
288
  private unlockDotCheckCanMint;
269
289
  private unlockDotSubscribeMintedData;
270
290
  private subscribeProcessingBanner;
@@ -8,6 +8,7 @@ import { TransactionError } from '@subwallet/extension-base/background/errors/Tr
8
8
  import { withErrorLog } from '@subwallet/extension-base/background/handlers/helpers';
9
9
  import { createSubscription } from '@subwallet/extension-base/background/handlers/subscriptions';
10
10
  import { CampaignDataType, ChainType, ExternalRequestPromiseStatus, ExtrinsicType, MantaPayEnableMessage, StakingType } from '@subwallet/extension-base/background/KoniTypes';
11
+ import RequestExtrinsicSign from '@subwallet/extension-base/background/RequestExtrinsicSign';
11
12
  import { _SUPPORT_TOKEN_PAY_FEE_GROUP, ALL_ACCOUNT_KEY, BTC_DUST_AMOUNT, LATEST_SESSION } from '@subwallet/extension-base/constants';
12
13
  import { additionalValidateTransferForRecipient, validateTransferRequest, validateXcmMinAmountToMythos, validateXcmTransferRequest } from '@subwallet/extension-base/core/logic-validation/transfer';
13
14
  import { _isSnowBridgeXcm } from '@subwallet/extension-base/core/substrate/xcm-parser';
@@ -3153,8 +3154,134 @@ export default class KoniExtension {
3153
3154
  });
3154
3155
  }
3155
3156
 
3157
+ // Helper for prepareMultisigSignRequest: reconstruct the original extrinsic from the payload's method & args
3158
+ async buildExtrinsicFromPayload(chain, payload) {
3159
+ const substrateApi = await this.#koniState.chainService.getSubstrateApi(chain).isReady;
3160
+ const call = substrateApi.api.createType('Call', payload.method);
3161
+ const {
3162
+ method,
3163
+ section
3164
+ } = substrateApi.api.registry.findMetaCall(call.callIndex);
3165
+ const extrinsic = substrateApi.api.tx[section][method](...call.args);
3166
+ return {
3167
+ substrateApi,
3168
+ extrinsic,
3169
+ call
3170
+ };
3171
+ }
3172
+
3173
+ /**
3174
+ * ─────────────────────────────────────────────────────────────
3175
+ * prepareMultisigSignRequest
3176
+ * ─────────────────────────────────────────────────────────────
3177
+ * Called when a dApp sends a signing request to a multisig account.
3178
+ * This method wraps the original extrinsic into a multisig.asMulti call so that it can be submitted by one of the signers on behalf of the multisig account.
3179
+ *
3180
+ * Important:
3181
+ * - The original sign request is MUTATED in-place via updateSignRequest.
3182
+ * After this method returns, the UI will prompt the signer to sign
3183
+ * the wrapped multisig extrinsic, not the original one.
3184
+ * - Errors are collected (not thrown) and returned in the response
3185
+ * so the UI can display them without crashing.
3186
+ * - This method does NOT submit the transaction; it only prepares
3187
+ * the payload for signing.
3188
+ * ─────────────────────────────────────────────────────────────
3189
+ */
3190
+ async prepareMultisigSignRequest(request) {
3191
+ const {
3192
+ id,
3193
+ signer
3194
+ } = request;
3195
+
3196
+ // ── Step 1: Retrieve the pending sign request from the queue ──
3197
+ const queued = this.#koniState.getSignRequest(id);
3198
+ assert(queued, t('bg.koni.handler.Extension.unableToProceed'));
3199
+ const errors = [];
3200
+ let submittedCallData = '';
3201
+ let callData = '';
3202
+ let depositAmount = '';
3203
+ let networkFee = '';
3204
+ const payload = queued.request.payload;
3205
+
3206
+ // ── Step 2: Validate payload format ──
3207
+ // Only JSON payloads (SignerPayloadJSON) contain the structured fields
3208
+ // (genesisHash, method, etc.) needed to reconstruct the extrinsic.
3209
+ // Raw (bytes) payloads cannot be wrapped into a multisig call.
3210
+ if (!isJsonPayload(payload)) {
3211
+ errors.push(new TransactionError(BasicTxErrorType.INVALID_PARAMS, t('bg.koni.handler.Extension.unableToProceed')));
3212
+ } else {
3213
+ var _chainInfo$substrateI;
3214
+ // ── Step 3: Resolve chain from genesisHash & check multisig support ──
3215
+ callData = payload.method;
3216
+ const [chain, chainInfo] = this.#koniState.findNetworkKeyByGenesisHash(payload.genesisHash);
3217
+ if (!chain || !(chainInfo !== null && chainInfo !== void 0 && (_chainInfo$substrateI = chainInfo.substrateInfo) !== null && _chainInfo$substrateI !== void 0 && _chainInfo$substrateI.supportMultisig)) {
3218
+ errors.push(new TransactionError(BasicTxErrorType.UNSUPPORTED, t('bg.koni.handler.Extension.unableToProceed')));
3219
+ } else {
3220
+ // ── Step 4: Look up multisig account configuration ──
3221
+ // queued.address is the multisig account address (the "from" in the original request).
3222
+ // We need its threshold and signers list to construct the asMulti call.
3223
+ const accountProxy = this.#koniState.keyringService.context.getMultisigAccountByAddress(queued.address);
3224
+ if (!accountProxy) {
3225
+ errors.push(new TransactionError(BasicTxErrorType.INTERNAL_ERROR, t('bg.koni.handler.Extension.unableToProceed')));
3226
+ } else {
3227
+ const threshold = accountProxy.accounts[0].threshold;
3228
+ const signers = accountProxy.accounts[0].signers;
3229
+
3230
+ // ── Step 5: Rebuild the original extrinsic from payload call data ──
3231
+ const {
3232
+ extrinsic: originExtrinsic,
3233
+ substrateApi
3234
+ } = await this.buildExtrinsicFromPayload(chain, payload);
3235
+
3236
+ // ── Step 6: Wrap into multisig initiation extrinsic ──
3237
+ const multisigExtrinsic = createInitMultisigExtrinsic(substrateApi.api, threshold, signers, signer, originExtrinsic);
3238
+
3239
+ // ── Step 7: Estimate fee & calculate multisig deposit ──
3240
+ submittedCallData = multisigExtrinsic.method.toHex();
3241
+ networkFee = (await multisigExtrinsic.paymentInfo(signer)).partialFee.toString();
3242
+ const depositBase = substrateApi.api.consts.multisig.depositBase.toString();
3243
+ const depositFactor = substrateApi.api.consts.multisig.depositFactor.toString();
3244
+ depositAmount = calcDepositAmount(depositBase, threshold, depositFactor);
3245
+
3246
+ // ── Step 8: Validate signer has sufficient balance ──
3247
+ const signerBalance = await this.getAddressTransferableBalance({
3248
+ address: signer,
3249
+ networkKey: chain,
3250
+ token: this.#koniState.chainService.getNativeTokenInfo(chain).slug,
3251
+ extrinsicType: ExtrinsicType.TRANSFER_TOKEN
3252
+ });
3253
+ const requiredBalance = new BigN(depositAmount).plus(networkFee);
3254
+ if (new BigN(signerBalance.value).lt(requiredBalance)) {
3255
+ errors.push(new TransactionError(BasicTxErrorType.NOT_ENOUGH_BALANCE, t('bg.koni.handler.Extension.notEnoughBalanceForMultisigDepositAndFee')));
3256
+ }
3257
+
3258
+ // ── Step 9: Replace the original sign request with the wrapped payload ──
3259
+ // After this, the signing UI will show the multisig extrinsic instead of
3260
+ // the original one. The signer's address and fresh nonce are used so
3261
+ // the transaction is submitted from the signer (not the multisig account).
3262
+ const nonce = await substrateApi.api.rpc.system.accountNextIndex(signer);
3263
+ const wrappedPayload = {
3264
+ ...payload,
3265
+ address: signer,
3266
+ nonce: nonce.toHex(),
3267
+ method: multisigExtrinsic.method.toHex()
3268
+ };
3269
+ this.#koniState.requestService.updateSignRequest(id, new RequestExtrinsicSign(wrappedPayload), signer);
3270
+ }
3271
+ }
3272
+ }
3273
+ return {
3274
+ submittedCallData: submittedCallData,
3275
+ callData: callData,
3276
+ depositAmount,
3277
+ networkFee,
3278
+ errors
3279
+ };
3280
+ }
3281
+
3156
3282
  // Substrate Proxy Account
3157
3283
  async handleSubstrateProxyWrappedTx(request) {
3284
+ var _originTransaction;
3158
3285
  const {
3159
3286
  chain,
3160
3287
  proxyMetadata,
@@ -3171,8 +3298,8 @@ export default class KoniExtension {
3171
3298
  * ─────────────────────────────
3172
3299
  */
3173
3300
  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;
3301
+ let originTransaction = this.#koniState.transactionService.getTransaction(transactionId);
3302
+ const extrinsicOriginTransaction = (_originTransaction = originTransaction) === null || _originTransaction === void 0 ? void 0 : _originTransaction.transaction;
3176
3303
  const callData = extrinsicOriginTransaction.method.toHex();
3177
3304
  const decodedCallData = decodeCallData({
3178
3305
  api: substrateApi.api,
@@ -3244,7 +3371,8 @@ export default class KoniExtension {
3244
3371
  * update history transaction accordingly.
3245
3372
  */
3246
3373
  const eventsHandler = eventEmitter => {
3247
- if (!(originTransaction !== null && originTransaction !== void 0 && originTransaction.emitterTransaction)) {
3374
+ var _originTransaction2;
3375
+ if (!((_originTransaction2 = originTransaction) !== null && _originTransaction2 !== void 0 && _originTransaction2.emitterTransaction)) {
3248
3376
  return;
3249
3377
  }
3250
3378
  const originEmitter = originTransaction.emitterTransaction;
@@ -3296,6 +3424,49 @@ export default class KoniExtension {
3296
3424
  * ─────────────────────────────
3297
3425
  */
3298
3426
 
3427
+ const originTransferData = originTransaction.data;
3428
+ const isTransferAllBalance = originTransaction.extrinsicType === ExtrinsicType.TRANSFER_BALANCE && !!(originTransferData !== null && originTransferData !== void 0 && originTransferData.transferAll);
3429
+ const maxTransferableWithoutFee = originTransferData === null || originTransferData === void 0 ? void 0 : originTransferData.maxTransferableWithoutFee;
3430
+ const maxTransferable = originTransferData === null || originTransferData === void 0 ? void 0 : originTransferData.maxTransferable;
3431
+ if (isTransferAllBalance && !!maxTransferableWithoutFee && !!maxTransferable) {
3432
+ if (isSignerProxiedAccount) {
3433
+ this.#koniState.transactionService.updateTransaction(transactionId, {
3434
+ data: {
3435
+ ...originTransferData,
3436
+ value: maxTransferable,
3437
+ transferNativeAmount: maxTransferable
3438
+ }
3439
+ });
3440
+ } else {
3441
+ this.#koniState.transactionService.updateTransaction(transactionId, {
3442
+ data: {
3443
+ ...originTransferData,
3444
+ value: maxTransferableWithoutFee,
3445
+ transferNativeAmount: maxTransferableWithoutFee
3446
+ }
3447
+ });
3448
+ }
3449
+
3450
+ // Refresh originTransaction after update
3451
+ originTransaction = this.#koniState.transactionService.getTransaction(transactionId);
3452
+ }
3453
+
3454
+ // If signer is the proxied account itself, the original transaction will be signed and sent directly without proxy execution.
3455
+ if (isSignerProxiedAccount) {
3456
+ const restData = Object.fromEntries(Object.entries(originTransaction.data || {}).filter(([key]) => key !== 'signer'));
3457
+ this.#koniState.transactionService.updateTransaction(transactionId, {
3458
+ data: restData
3459
+ });
3460
+ } else {
3461
+ this.#koniState.transactionService.updateTransaction(transactionId, {
3462
+ data: {
3463
+ ...originTransaction.data,
3464
+ signer
3465
+ }
3466
+ });
3467
+ }
3468
+ originTransaction = this.#koniState.transactionService.getTransaction(transactionId);
3469
+
3299
3470
  // Case 1: signer === proxied address → handle original transaction
3300
3471
  if (isSignerProxiedAccount) {
3301
3472
  let callDataFinal = callData;
@@ -3343,6 +3514,8 @@ export default class KoniExtension {
3343
3514
  decodedCallData,
3344
3515
  submittedCallData: substrateProxyExtrinsic.toHex(),
3345
3516
  callData,
3517
+ signer,
3518
+ signerAddress: signer,
3346
3519
  networkFee
3347
3520
  },
3348
3521
  wrappingStatus: SubstrateTransactionWrappingStatus.WRAP_RESULT,
@@ -3530,7 +3703,8 @@ export default class KoniExtension {
3530
3703
  request,
3531
3704
  resolve
3532
3705
  } = queued;
3533
- const pair = keyring.getPair(queued.address);
3706
+ const signingAddress = queued.signerAddress || queued.address;
3707
+ const pair = keyring.getPair(signingAddress);
3534
3708
 
3535
3709
  // unlike queued.account.address the following
3536
3710
  // address is encoded with the default prefix
@@ -3560,10 +3734,26 @@ export default class KoniExtension {
3560
3734
  }
3561
3735
  }
3562
3736
  const result = request.sign(registry, pair);
3737
+ let signedTransaction;
3738
+ if (queued.signerAddress && isJsonPayload(payload)) {
3739
+ try {
3740
+ const [chain] = this.#koniState.findNetworkKeyByGenesisHash(payload.genesisHash);
3741
+ if (chain) {
3742
+ const {
3743
+ extrinsic
3744
+ } = await this.buildExtrinsicFromPayload(chain, payload);
3745
+ extrinsic.addSignature(payload.address, result.signature, payload);
3746
+ signedTransaction = extrinsic.toHex();
3747
+ }
3748
+ } catch (e) {
3749
+ console.error('Failed to build signed transaction for wrapped multisig signing', e);
3750
+ }
3751
+ }
3563
3752
  resolve({
3564
3753
  id,
3565
3754
  // In case evm chain, must be cut 2 character after 0x
3566
- signature: result.signature
3755
+ signature: result.signature,
3756
+ signedTransaction
3567
3757
  });
3568
3758
  if (this.#alwaysLock) {
3569
3759
  this.keyringLock();
@@ -4508,7 +4698,25 @@ export default class KoniExtension {
4508
4698
  chainType: ChainType.SUBSTRATE
4509
4699
  });
4510
4700
  }
4511
-
4701
+ async handleChangeBittensorRootClaimType(params) {
4702
+ const {
4703
+ address,
4704
+ slug
4705
+ } = params;
4706
+ const poolHandler = this.#koniState.earningService.getPoolHandler(slug);
4707
+ if (!poolHandler) {
4708
+ return this.#koniState.transactionService.generateBeforeHandleResponseErrors([new TransactionError(BasicTxErrorType.INVALID_PARAMS)]);
4709
+ }
4710
+ const extrinsic = await this.#koniState.earningService.handleChangeRootClaimType(params);
4711
+ return await this.#koniState.transactionService.handleTransaction({
4712
+ address,
4713
+ chain: poolHandler.chain,
4714
+ transaction: extrinsic,
4715
+ data: params,
4716
+ extrinsicType: ExtrinsicType.CHANGE_BITTENSOR_ROOT_CLAIM_TYPE,
4717
+ chainType: ChainType.SUBSTRATE
4718
+ });
4719
+ }
4512
4720
  /* Campaign */
4513
4721
 
4514
4722
  unlockDotCheckCanMint({
@@ -5490,6 +5698,8 @@ export default class KoniExtension {
5490
5698
  return await this.yieldGetEarningImpact(request);
5491
5699
  case 'pri(yield.changeValidator.submit)':
5492
5700
  return await this.handleYieldChangeValidator(request);
5701
+ case 'pri(yield.changeBittensorRootClaimType.submit)':
5702
+ return await this.handleChangeBittensorRootClaimType(request);
5493
5703
  /* Others */
5494
5704
 
5495
5705
  /* Actions */
@@ -5986,6 +6196,8 @@ export default class KoniExtension {
5986
6196
  return await this.cancelPendingTx(request);
5987
6197
  case 'pri(multisig.initMultisigTx)':
5988
6198
  return await this.initMultisigTx(request);
6199
+ case 'pri(multisig.prepareSignRequest)':
6200
+ return await this.prepareMultisigSignRequest(request);
5989
6201
  case 'pri(multisig.getSignableAccountInfos)':
5990
6202
  return this.#koniState.keyringService.context.getSignableAccountInfos(request);
5991
6203
  /* Multisig Account */
@@ -69,11 +69,10 @@ function transformAccountsV2(accounts, anyType = false, authInfo, accountAuthTyp
69
69
  const injectedAccounts = Object.values(accounts).filter(({
70
70
  json: {
71
71
  meta: {
72
- isHidden,
73
- isMultisig
72
+ isHidden
74
73
  }
75
74
  }
76
- }) => !isHidden && !isMultisig).filter(authTypeFilter).filter(({
75
+ }) => !isHidden).filter(authTypeFilter).filter(({
77
76
  json: {
78
77
  address
79
78
  }
package/package.json CHANGED
@@ -17,7 +17,7 @@
17
17
  "./cjs/detectPackage.js"
18
18
  ],
19
19
  "type": "module",
20
- "version": "1.3.75-2",
20
+ "version": "1.3.77-0",
21
21
  "main": "./cjs/index.js",
22
22
  "module": "./index.js",
23
23
  "types": "./index.d.ts",
@@ -3008,11 +3008,11 @@
3008
3008
  "@sora-substrate/type-definitions": "^1.17.7",
3009
3009
  "@substrate/connect": "^0.8.9",
3010
3010
  "@subwallet-monorepos/subwallet-services-sdk": "0.1.16",
3011
- "@subwallet/chain-list": "0.2.124",
3012
- "@subwallet/extension-base": "^1.3.75-2",
3013
- "@subwallet/extension-chains": "^1.3.75-2",
3014
- "@subwallet/extension-dapp": "^1.3.75-2",
3015
- "@subwallet/extension-inject": "^1.3.75-2",
3011
+ "@subwallet/chain-list": "0.2.126",
3012
+ "@subwallet/extension-base": "^1.3.77-0",
3013
+ "@subwallet/extension-chains": "^1.3.77-0",
3014
+ "@subwallet/extension-dapp": "^1.3.77-0",
3015
+ "@subwallet/extension-inject": "^1.3.77-0",
3016
3016
  "@subwallet/keyring": "^0.1.14",
3017
3017
  "@subwallet/ui-keyring": "^0.1.14",
3018
3018
  "@ton/core": "^0.56.3",
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.3.75-2'
10
+ version: '1.3.77-0'
11
11
  };
@@ -795,7 +795,12 @@ export class BalanceService {
795
795
  /** Return token slugs with balance in substrate chain - only work with substrate chains that have subscanSlug **/
796
796
  async getSubstrateTokensBalanceByChain(address, chainSlug, assetsByChain) {
797
797
  const tokenBalanceSlugs = [];
798
- const balanceData = await this.state.subscanService.getMultiChainBalance(address);
798
+
799
+ // Do not block chain enabling flow when balance detection fails.
800
+ const balanceData = await this.state.subscanService.getMultiChainBalance(address).catch(e => {
801
+ console.error(e);
802
+ return [];
803
+ });
799
804
  if (!balanceData) {
800
805
  return [];
801
806
  }
@@ -1418,10 +1418,10 @@ export class ChainService {
1418
1418
  paraId: params.chainSpec.paraId,
1419
1419
  symbol: params.chainEditInfo.symbol,
1420
1420
  genesisHash: params.chainSpec.genesisHash,
1421
+ supportProxy: false,
1421
1422
  relaySlug: null,
1422
1423
  hasNativeNft: false,
1423
1424
  supportStaking: params.chainSpec.paraId === null,
1424
- supportProxy: false,
1425
1425
  supportMultisig: false,
1426
1426
  supportSmartContract: null
1427
1427
  };