@subwallet/extension-base 1.3.76-0 → 1.3.78-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 (96) hide show
  1. package/background/KoniTypes.d.ts +4 -1
  2. package/cjs/core/logic-validation/index.js +1 -1
  3. package/cjs/core/substrate/xcm-parser.js +17 -11
  4. package/cjs/koni/background/handlers/Extension.js +293 -71
  5. package/cjs/koni/background/handlers/State.js +20 -0
  6. package/cjs/koni/background/handlers/Tabs.js +2 -3
  7. package/cjs/packageInfo.js +1 -1
  8. package/cjs/services/balance-service/helpers/subscribe/evm.js +85 -6
  9. package/cjs/services/balance-service/helpers/subscribe/index.js +2 -1
  10. package/cjs/services/balance-service/index.js +6 -2
  11. package/cjs/services/balance-service/transfer/token.js +15 -0
  12. package/cjs/services/balance-service/transfer/xcm/bittensorBridge/index.js +27 -0
  13. package/cjs/services/balance-service/transfer/xcm/bittensorBridge/nativeTokenBridge.js +58 -0
  14. package/cjs/services/balance-service/transfer/xcm/bittensorBridge/utils.js +36 -0
  15. package/cjs/services/balance-service/transfer/xcm/index.js +61 -2
  16. package/cjs/services/balance-service/transfer/xcm/utils.js +94 -6
  17. package/cjs/services/chain-service/constants.js +4 -2
  18. package/cjs/services/chain-service/utils/patch.js +1 -1
  19. package/cjs/services/earning-service/constants/chains.js +7 -2
  20. package/cjs/services/earning-service/handlers/liquid-staking/stella-swap.js +8 -5
  21. package/cjs/services/earning-service/handlers/special.js +82 -65
  22. package/cjs/services/earning-service/service.js +19 -2
  23. package/cjs/services/multisig-service/index.js +1 -1
  24. package/cjs/services/request-service/handler/SubstrateRequestHandler.js +12 -0
  25. package/cjs/services/request-service/index.js +3 -0
  26. package/cjs/services/setting-service/constants.js +2 -1
  27. package/cjs/services/storage-service/db-stores/InappNotification.js +1 -1
  28. package/cjs/services/swap-service/handler/bittensor-handler.js +197 -0
  29. package/cjs/services/swap-service/index.js +7 -0
  30. package/cjs/services/transaction-service/index.js +10 -0
  31. package/cjs/types/balance/index.js +1 -0
  32. package/cjs/types/swap/index.js +3 -1
  33. package/cjs/utils/fee/transfer.js +20 -5
  34. package/core/logic-validation/index.js +1 -1
  35. package/core/substrate/xcm-parser.d.ts +3 -0
  36. package/core/substrate/xcm-parser.js +14 -11
  37. package/koni/background/handlers/Extension.d.ts +19 -0
  38. package/koni/background/handlers/Extension.js +233 -14
  39. package/koni/background/handlers/State.d.ts +1 -0
  40. package/koni/background/handlers/State.js +20 -0
  41. package/koni/background/handlers/Tabs.js +2 -3
  42. package/package.json +26 -6
  43. package/packageInfo.js +1 -1
  44. package/services/balance-service/helpers/subscribe/evm.d.ts +1 -0
  45. package/services/balance-service/helpers/subscribe/evm.js +76 -1
  46. package/services/balance-service/helpers/subscribe/index.js +2 -1
  47. package/services/balance-service/index.js +6 -2
  48. package/services/balance-service/transfer/token.d.ts +2 -1
  49. package/services/balance-service/transfer/token.js +15 -0
  50. package/services/balance-service/transfer/xcm/bittensorBridge/index.d.ts +2 -0
  51. package/services/balance-service/transfer/xcm/bittensorBridge/index.js +5 -0
  52. package/services/balance-service/transfer/xcm/bittensorBridge/nativeTokenBridge.d.ts +6 -0
  53. package/services/balance-service/transfer/xcm/bittensorBridge/nativeTokenBridge.js +50 -0
  54. package/services/balance-service/transfer/xcm/bittensorBridge/utils.d.ts +8 -0
  55. package/services/balance-service/transfer/xcm/bittensorBridge/utils.js +29 -0
  56. package/services/balance-service/transfer/xcm/index.d.ts +5 -0
  57. package/services/balance-service/transfer/xcm/index.js +57 -2
  58. package/services/balance-service/transfer/xcm/utils.d.ts +3 -2
  59. package/services/balance-service/transfer/xcm/utils.js +87 -1
  60. package/services/chain-service/constants.d.ts +2 -0
  61. package/services/chain-service/constants.js +4 -2
  62. package/services/chain-service/utils/patch.d.ts +1 -1
  63. package/services/chain-service/utils/patch.js +1 -1
  64. package/services/earning-service/constants/chains.d.ts +2 -0
  65. package/services/earning-service/constants/chains.js +4 -1
  66. package/services/earning-service/handlers/liquid-staking/stella-swap.d.ts +1 -0
  67. package/services/earning-service/handlers/liquid-staking/stella-swap.js +6 -4
  68. package/services/earning-service/handlers/special.d.ts +1 -1
  69. package/services/earning-service/handlers/special.js +85 -68
  70. package/services/earning-service/service.js +21 -4
  71. package/services/inapp-notification-service/interfaces.d.ts +1 -0
  72. package/services/multisig-service/index.js +1 -1
  73. package/services/request-service/handler/SubstrateRequestHandler.d.ts +1 -0
  74. package/services/request-service/handler/SubstrateRequestHandler.js +12 -0
  75. package/services/request-service/index.d.ts +1 -0
  76. package/services/request-service/index.js +3 -0
  77. package/services/request-service/types.d.ts +1 -0
  78. package/services/setting-service/constants.js +2 -1
  79. package/services/storage-service/db-stores/InappNotification.js +1 -1
  80. package/services/swap-service/handler/bittensor-handler.d.ts +21 -0
  81. package/services/swap-service/handler/bittensor-handler.js +189 -0
  82. package/services/swap-service/index.js +7 -0
  83. package/services/transaction-service/index.d.ts +1 -1
  84. package/services/transaction-service/index.js +10 -0
  85. package/services/transaction-service/types.d.ts +4 -3
  86. package/types/balance/index.d.ts +3 -1
  87. package/types/balance/index.js +1 -0
  88. package/types/balance/transfer.d.ts +9 -0
  89. package/types/fee/base.d.ts +1 -0
  90. package/types/multisig/index.d.ts +12 -0
  91. package/types/swap/index.d.ts +3 -1
  92. package/types/swap/index.js +3 -1
  93. package/types/yield/actions/join/step.d.ts +6 -0
  94. package/types/yield/actions/join/submit.d.ts +1 -0
  95. package/utils/fee/transfer.d.ts +1 -0
  96. package/utils/fee/transfer.js +21 -6
@@ -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';
@@ -31,9 +32,10 @@ import { createCardanoTransaction } from '@subwallet/extension-base/services/bal
31
32
  import { getERC20TransactionObject, getERC721Transaction, getEVMTransactionObject, getPSP34TransferExtrinsic } from '@subwallet/extension-base/services/balance-service/transfer/smart-contract';
32
33
  import { createSubstrateExtrinsic } from '@subwallet/extension-base/services/balance-service/transfer/token';
33
34
  import { createTonTransaction } from '@subwallet/extension-base/services/balance-service/transfer/ton-transfer';
34
- import { createAcrossBridgeExtrinsic, createAvailBridgeExtrinsicFromAvail, createAvailBridgeTxFromEth, createPolygonBridgeExtrinsic, createSnowBridgeExtrinsic, createXcmExtrinsicV2, dryRunXcmExtrinsicV2 } from '@subwallet/extension-base/services/balance-service/transfer/xcm';
35
+ import { createAcrossBridgeExtrinsic, createAvailBridgeExtrinsicFromAvail, createAvailBridgeTxFromEth, createBittensorToSubtensorEvmExtrinsic, createPolygonBridgeExtrinsic, createSnowBridgeExtrinsic, createSubtensorEvmToBittensorExtrinsic, createXcmExtrinsicV2, dryRunXcmExtrinsicV2 } from '@subwallet/extension-base/services/balance-service/transfer/xcm';
35
36
  import { _isAcrossChainBridge, getAcrossQuote } from '@subwallet/extension-base/services/balance-service/transfer/xcm/acrossBridge';
36
37
  import { getClaimTxOnAvail, getClaimTxOnEthereum, isAvailChainBridge } from '@subwallet/extension-base/services/balance-service/transfer/xcm/availBridge';
38
+ import { _isBittensorToSubtensorBridge, _isSubtensorToBittensorBridge } from '@subwallet/extension-base/services/balance-service/transfer/xcm/bittensorBridge/nativeTokenBridge';
37
39
  import { _isPolygonChainBridge, getClaimPolygonBridge, isClaimedPolygonBridge } from '@subwallet/extension-base/services/balance-service/transfer/xcm/polygonBridge';
38
40
  import { _isPosChainBridge, getClaimPosBridge } from '@subwallet/extension-base/services/balance-service/transfer/xcm/posBridge';
39
41
  import { estimateXcmFee } from '@subwallet/extension-base/services/balance-service/transfer/xcm/utils';
@@ -1258,6 +1260,7 @@ export default class KoniExtension {
1258
1260
  feeCustom,
1259
1261
  feeOption,
1260
1262
  from,
1263
+ metadata,
1261
1264
  to,
1262
1265
  tokenPayFeeSlug,
1263
1266
  tokenSlug,
@@ -1398,7 +1401,8 @@ export default class KoniExtension {
1398
1401
  networkKey: chain,
1399
1402
  tokenInfo: transferTokenInfo,
1400
1403
  to: to,
1401
- substrateApi
1404
+ substrateApi,
1405
+ metadata
1402
1406
  });
1403
1407
  if (_SUPPORT_TOKEN_PAY_FEE_GROUP.hydration.includes(chain)) {
1404
1408
  var _this$koniState$chain, _substrateApi$api$que;
@@ -1525,11 +1529,18 @@ export default class KoniExtension {
1525
1529
  const isPolygonBridgeTransfer = _isPolygonChainBridge(originNetworkKey, destinationNetworkKey);
1526
1530
  const isPosBridgeTransfer = _isPosChainBridge(originNetworkKey, destinationNetworkKey);
1527
1531
  const isAcrossBridgeTransfer = _isAcrossChainBridge(originNetworkKey, destinationNetworkKey);
1532
+ const isBittensorBridgeTransfer = _isBittensorToSubtensorBridge(originNetworkKey, destinationNetworkKey);
1533
+ const isSubtensorEvmBridgeTransfer = _isSubtensorToBittensorBridge(originNetworkKey, destinationNetworkKey);
1528
1534
  const extrinsicType = ExtrinsicType.TRANSFER_XCM;
1529
- const isSubstrateXcm = !(isAvailBridgeFromEvm || isAvailBridgeFromAvail || isSnowBridgeEvmTransfer || isPolygonBridgeTransfer || isPosBridgeTransfer || isAcrossBridgeTransfer);
1535
+ const isSubstrateParaspellXcm = !(isAvailBridgeFromEvm || isAvailBridgeFromAvail || isSnowBridgeEvmTransfer || isPolygonBridgeTransfer || isPosBridgeTransfer || isAcrossBridgeTransfer || isBittensorBridgeTransfer || isSubtensorEvmBridgeTransfer);
1530
1536
  const isTransferNative = this.#koniState.getNativeTokenInfo(originNetworkKey).slug === tokenSlug;
1531
1537
  const isTransferLocalTokenAndPayThatTokenAsFee = !isTransferNative && tokenSlug === tokenPayFeeSlug;
1532
1538
  let xcmFeeDryRun;
1539
+ const xcmDestinationFee = {
1540
+ symbol: (destinationTokenInfo === null || destinationTokenInfo === void 0 ? void 0 : destinationTokenInfo.symbol) || '',
1541
+ decimals: (destinationTokenInfo === null || destinationTokenInfo === void 0 ? void 0 : destinationTokenInfo.decimals) || 0,
1542
+ value: '0'
1543
+ };
1533
1544
  let additionalValidator;
1534
1545
  let eventsHandler;
1535
1546
  if (fromKeyPair && destinationTokenInfo) {
@@ -1540,6 +1551,9 @@ export default class KoniExtension {
1540
1551
  if (isPosBridgeTransfer || isPolygonBridgeTransfer) {
1541
1552
  funcCreateExtrinsic = createPolygonBridgeExtrinsic;
1542
1553
  type = 'evm';
1554
+ } else if (isSubtensorEvmBridgeTransfer) {
1555
+ funcCreateExtrinsic = createSubtensorEvmToBittensorExtrinsic;
1556
+ type = 'evm';
1543
1557
  } else if (isAcrossBridgeTransfer) {
1544
1558
  funcCreateExtrinsic = createAcrossBridgeExtrinsic;
1545
1559
  type = 'evm';
@@ -1549,6 +1563,9 @@ export default class KoniExtension {
1549
1563
  } else if (isAvailBridgeFromEvm) {
1550
1564
  funcCreateExtrinsic = createAvailBridgeTxFromEth;
1551
1565
  type = 'evm';
1566
+ } else if (isBittensorBridgeTransfer) {
1567
+ funcCreateExtrinsic = createBittensorToSubtensorEvmExtrinsic;
1568
+ type = 'substrate';
1552
1569
  } else if (isAvailBridgeFromAvail) {
1553
1570
  funcCreateExtrinsic = createAvailBridgeExtrinsicFromAvail;
1554
1571
  type = 'substrate';
@@ -1569,10 +1586,11 @@ export default class KoniExtension {
1569
1586
  evmApi,
1570
1587
  feeCustom,
1571
1588
  feeOption,
1572
- feeInfo
1589
+ feeInfo,
1590
+ transferAll
1573
1591
  };
1574
1592
  extrinsic = await funcCreateExtrinsic(params);
1575
- if (isSubstrateXcm) {
1593
+ if (isSubstrateParaspellXcm) {
1576
1594
  const xcmFeeInfo = await estimateXcmFee({
1577
1595
  fromChainInfo: params.originChain,
1578
1596
  fromTokenInfo: params.originTokenInfo,
@@ -1581,7 +1599,11 @@ export default class KoniExtension {
1581
1599
  sender: params.sender,
1582
1600
  value: params.sendingValue
1583
1601
  });
1602
+
1603
+ // todo: refactor name
1604
+ // todo: check to use full interface to has full AmountData, include symbol, decimal
1584
1605
  xcmFeeDryRun = (xcmFeeInfo === null || xcmFeeInfo === void 0 ? void 0 : xcmFeeInfo.origin.fee) || '0';
1606
+ xcmDestinationFee.value = (xcmFeeInfo === null || xcmFeeInfo === void 0 ? void 0 : xcmFeeInfo.destination.fee) || '0';
1585
1607
  }
1586
1608
  if (isAcrossBridgeTransfer) {
1587
1609
  const data = await getAcrossQuote(params);
@@ -1649,7 +1671,7 @@ export default class KoniExtension {
1649
1671
  warning.length && inputTransaction.warnings.push(...warning);
1650
1672
  error.length && inputTransaction.errors.push(...error);
1651
1673
  }
1652
- if (isSubstrateXcm) {
1674
+ if (isSubstrateParaspellXcm) {
1653
1675
  const isDryRunSuccess = await dryRunXcmExtrinsicV2(params, false);
1654
1676
  if (!isDryRunSuccess) {
1655
1677
  inputTransaction.errors.push(new TransactionError(BasicTxErrorType.UNABLE_TO_SEND, 'Unable to perform transaction. Select another token or destination chain and try again'));
@@ -1687,7 +1709,7 @@ export default class KoniExtension {
1687
1709
  transaction: extrinsic,
1688
1710
  data: inputData,
1689
1711
  extrinsicType,
1690
- chainType: !isSnowBridgeEvmTransfer && !isAvailBridgeFromEvm && !isPolygonBridgeTransfer && !isPosBridgeTransfer && !isAcrossBridgeTransfer ? ChainType.SUBSTRATE : ChainType.EVM,
1712
+ chainType: !isSnowBridgeEvmTransfer && !isAvailBridgeFromEvm && !isPolygonBridgeTransfer && !isPosBridgeTransfer && !isAcrossBridgeTransfer && !isSubtensorEvmBridgeTransfer ? ChainType.SUBSTRATE : ChainType.EVM,
1691
1713
  transferNativeAmount: _isNativeToken(originTokenInfo) ? value : '0',
1692
1714
  ignoreWarnings,
1693
1715
  tokenPayFeeSlug,
@@ -1695,6 +1717,7 @@ export default class KoniExtension {
1695
1717
  isTransferLocalTokenAndPayThatTokenAsFee,
1696
1718
  isPassConfirmation,
1697
1719
  xcmFeeDryRun,
1720
+ xcmDestinationFee,
1698
1721
  errors,
1699
1722
  additionalValidator: additionalValidator,
1700
1723
  eventsHandler: eventsHandler
@@ -2158,6 +2181,7 @@ export default class KoniExtension {
2158
2181
  destChain: _destChain,
2159
2182
  feeCustom,
2160
2183
  feeOption,
2184
+ metadata,
2161
2185
  to,
2162
2186
  token,
2163
2187
  tokenPayFeeSlug,
@@ -2199,7 +2223,8 @@ export default class KoniExtension {
2199
2223
  isTransferLocalTokenAndPayThatTokenAsFee,
2200
2224
  isTransferNativeTokenAndPayLocalTokenAsFee,
2201
2225
  nativeToken,
2202
- transferAll: transferAll
2226
+ transferAll,
2227
+ metadata
2203
2228
  };
2204
2229
  const subscription = combineLatest({
2205
2230
  freeBalance: freeBalanceSubject,
@@ -3153,8 +3178,134 @@ export default class KoniExtension {
3153
3178
  });
3154
3179
  }
3155
3180
 
3181
+ // Helper for prepareMultisigSignRequest: reconstruct the original extrinsic from the payload's method & args
3182
+ async buildExtrinsicFromPayload(chain, payload) {
3183
+ const substrateApi = await this.#koniState.chainService.getSubstrateApi(chain).isReady;
3184
+ const call = substrateApi.api.createType('Call', payload.method);
3185
+ const {
3186
+ method,
3187
+ section
3188
+ } = substrateApi.api.registry.findMetaCall(call.callIndex);
3189
+ const extrinsic = substrateApi.api.tx[section][method](...call.args);
3190
+ return {
3191
+ substrateApi,
3192
+ extrinsic,
3193
+ call
3194
+ };
3195
+ }
3196
+
3197
+ /**
3198
+ * ─────────────────────────────────────────────────────────────
3199
+ * prepareMultisigSignRequest
3200
+ * ─────────────────────────────────────────────────────────────
3201
+ * Called when a dApp sends a signing request to a multisig account.
3202
+ * 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.
3203
+ *
3204
+ * Important:
3205
+ * - The original sign request is MUTATED in-place via updateSignRequest.
3206
+ * After this method returns, the UI will prompt the signer to sign
3207
+ * the wrapped multisig extrinsic, not the original one.
3208
+ * - Errors are collected (not thrown) and returned in the response
3209
+ * so the UI can display them without crashing.
3210
+ * - This method does NOT submit the transaction; it only prepares
3211
+ * the payload for signing.
3212
+ * ─────────────────────────────────────────────────────────────
3213
+ */
3214
+ async prepareMultisigSignRequest(request) {
3215
+ const {
3216
+ id,
3217
+ signer
3218
+ } = request;
3219
+
3220
+ // ── Step 1: Retrieve the pending sign request from the queue ──
3221
+ const queued = this.#koniState.getSignRequest(id);
3222
+ assert(queued, t('bg.koni.handler.Extension.unableToProceed'));
3223
+ const errors = [];
3224
+ let submittedCallData = '';
3225
+ let callData = '';
3226
+ let depositAmount = '';
3227
+ let networkFee = '';
3228
+ const payload = queued.request.payload;
3229
+
3230
+ // ── Step 2: Validate payload format ──
3231
+ // Only JSON payloads (SignerPayloadJSON) contain the structured fields
3232
+ // (genesisHash, method, etc.) needed to reconstruct the extrinsic.
3233
+ // Raw (bytes) payloads cannot be wrapped into a multisig call.
3234
+ if (!isJsonPayload(payload)) {
3235
+ errors.push(new TransactionError(BasicTxErrorType.INVALID_PARAMS, t('bg.koni.handler.Extension.unableToProceed')));
3236
+ } else {
3237
+ var _chainInfo$substrateI;
3238
+ // ── Step 3: Resolve chain from genesisHash & check multisig support ──
3239
+ callData = payload.method;
3240
+ const [chain, chainInfo] = this.#koniState.findNetworkKeyByGenesisHash(payload.genesisHash);
3241
+ if (!chain || !(chainInfo !== null && chainInfo !== void 0 && (_chainInfo$substrateI = chainInfo.substrateInfo) !== null && _chainInfo$substrateI !== void 0 && _chainInfo$substrateI.supportMultisig)) {
3242
+ errors.push(new TransactionError(BasicTxErrorType.UNSUPPORTED, t('bg.koni.handler.Extension.unableToProceed')));
3243
+ } else {
3244
+ // ── Step 4: Look up multisig account configuration ──
3245
+ // queued.address is the multisig account address (the "from" in the original request).
3246
+ // We need its threshold and signers list to construct the asMulti call.
3247
+ const accountProxy = this.#koniState.keyringService.context.getMultisigAccountByAddress(queued.address);
3248
+ if (!accountProxy) {
3249
+ errors.push(new TransactionError(BasicTxErrorType.INTERNAL_ERROR, t('bg.koni.handler.Extension.unableToProceed')));
3250
+ } else {
3251
+ const threshold = accountProxy.accounts[0].threshold;
3252
+ const signers = accountProxy.accounts[0].signers;
3253
+
3254
+ // ── Step 5: Rebuild the original extrinsic from payload call data ──
3255
+ const {
3256
+ extrinsic: originExtrinsic,
3257
+ substrateApi
3258
+ } = await this.buildExtrinsicFromPayload(chain, payload);
3259
+
3260
+ // ── Step 6: Wrap into multisig initiation extrinsic ──
3261
+ const multisigExtrinsic = createInitMultisigExtrinsic(substrateApi.api, threshold, signers, signer, originExtrinsic);
3262
+
3263
+ // ── Step 7: Estimate fee & calculate multisig deposit ──
3264
+ submittedCallData = multisigExtrinsic.method.toHex();
3265
+ networkFee = (await multisigExtrinsic.paymentInfo(signer)).partialFee.toString();
3266
+ const depositBase = substrateApi.api.consts.multisig.depositBase.toString();
3267
+ const depositFactor = substrateApi.api.consts.multisig.depositFactor.toString();
3268
+ depositAmount = calcDepositAmount(depositBase, threshold, depositFactor);
3269
+
3270
+ // ── Step 8: Validate signer has sufficient balance ──
3271
+ const signerBalance = await this.getAddressTransferableBalance({
3272
+ address: signer,
3273
+ networkKey: chain,
3274
+ token: this.#koniState.chainService.getNativeTokenInfo(chain).slug,
3275
+ extrinsicType: ExtrinsicType.TRANSFER_TOKEN
3276
+ });
3277
+ const requiredBalance = new BigN(depositAmount).plus(networkFee);
3278
+ if (new BigN(signerBalance.value).lt(requiredBalance)) {
3279
+ errors.push(new TransactionError(BasicTxErrorType.NOT_ENOUGH_BALANCE, t('bg.koni.handler.Extension.notEnoughBalanceForMultisigDepositAndFee')));
3280
+ }
3281
+
3282
+ // ── Step 9: Replace the original sign request with the wrapped payload ──
3283
+ // After this, the signing UI will show the multisig extrinsic instead of
3284
+ // the original one. The signer's address and fresh nonce are used so
3285
+ // the transaction is submitted from the signer (not the multisig account).
3286
+ const nonce = await substrateApi.api.rpc.system.accountNextIndex(signer);
3287
+ const wrappedPayload = {
3288
+ ...payload,
3289
+ address: signer,
3290
+ nonce: nonce.toHex(),
3291
+ method: multisigExtrinsic.method.toHex()
3292
+ };
3293
+ this.#koniState.requestService.updateSignRequest(id, new RequestExtrinsicSign(wrappedPayload), signer);
3294
+ }
3295
+ }
3296
+ }
3297
+ return {
3298
+ submittedCallData: submittedCallData,
3299
+ callData: callData,
3300
+ depositAmount,
3301
+ networkFee,
3302
+ errors
3303
+ };
3304
+ }
3305
+
3156
3306
  // Substrate Proxy Account
3157
3307
  async handleSubstrateProxyWrappedTx(request) {
3308
+ var _originTransaction;
3158
3309
  const {
3159
3310
  chain,
3160
3311
  proxyMetadata,
@@ -3171,8 +3322,8 @@ export default class KoniExtension {
3171
3322
  * ─────────────────────────────
3172
3323
  */
3173
3324
  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;
3325
+ let originTransaction = this.#koniState.transactionService.getTransaction(transactionId);
3326
+ const extrinsicOriginTransaction = (_originTransaction = originTransaction) === null || _originTransaction === void 0 ? void 0 : _originTransaction.transaction;
3176
3327
  const callData = extrinsicOriginTransaction.method.toHex();
3177
3328
  const decodedCallData = decodeCallData({
3178
3329
  api: substrateApi.api,
@@ -3244,7 +3395,8 @@ export default class KoniExtension {
3244
3395
  * update history transaction accordingly.
3245
3396
  */
3246
3397
  const eventsHandler = eventEmitter => {
3247
- if (!(originTransaction !== null && originTransaction !== void 0 && originTransaction.emitterTransaction)) {
3398
+ var _originTransaction2;
3399
+ if (!((_originTransaction2 = originTransaction) !== null && _originTransaction2 !== void 0 && _originTransaction2.emitterTransaction)) {
3248
3400
  return;
3249
3401
  }
3250
3402
  const originEmitter = originTransaction.emitterTransaction;
@@ -3296,6 +3448,49 @@ export default class KoniExtension {
3296
3448
  * ─────────────────────────────
3297
3449
  */
3298
3450
 
3451
+ const originTransferData = originTransaction.data;
3452
+ const isTransferAllBalance = originTransaction.extrinsicType === ExtrinsicType.TRANSFER_BALANCE && !!(originTransferData !== null && originTransferData !== void 0 && originTransferData.transferAll);
3453
+ const maxTransferableWithoutFee = originTransferData === null || originTransferData === void 0 ? void 0 : originTransferData.maxTransferableWithoutFee;
3454
+ const maxTransferable = originTransferData === null || originTransferData === void 0 ? void 0 : originTransferData.maxTransferable;
3455
+ if (isTransferAllBalance && !!maxTransferableWithoutFee && !!maxTransferable) {
3456
+ if (isSignerProxiedAccount) {
3457
+ this.#koniState.transactionService.updateTransaction(transactionId, {
3458
+ data: {
3459
+ ...originTransferData,
3460
+ value: maxTransferable,
3461
+ transferNativeAmount: maxTransferable
3462
+ }
3463
+ });
3464
+ } else {
3465
+ this.#koniState.transactionService.updateTransaction(transactionId, {
3466
+ data: {
3467
+ ...originTransferData,
3468
+ value: maxTransferableWithoutFee,
3469
+ transferNativeAmount: maxTransferableWithoutFee
3470
+ }
3471
+ });
3472
+ }
3473
+
3474
+ // Refresh originTransaction after update
3475
+ originTransaction = this.#koniState.transactionService.getTransaction(transactionId);
3476
+ }
3477
+
3478
+ // If signer is the proxied account itself, the original transaction will be signed and sent directly without proxy execution.
3479
+ if (isSignerProxiedAccount) {
3480
+ const restData = Object.fromEntries(Object.entries(originTransaction.data || {}).filter(([key]) => key !== 'signer'));
3481
+ this.#koniState.transactionService.updateTransaction(transactionId, {
3482
+ data: restData
3483
+ });
3484
+ } else {
3485
+ this.#koniState.transactionService.updateTransaction(transactionId, {
3486
+ data: {
3487
+ ...originTransaction.data,
3488
+ signer
3489
+ }
3490
+ });
3491
+ }
3492
+ originTransaction = this.#koniState.transactionService.getTransaction(transactionId);
3493
+
3299
3494
  // Case 1: signer === proxied address → handle original transaction
3300
3495
  if (isSignerProxiedAccount) {
3301
3496
  let callDataFinal = callData;
@@ -3343,6 +3538,8 @@ export default class KoniExtension {
3343
3538
  decodedCallData,
3344
3539
  submittedCallData: substrateProxyExtrinsic.toHex(),
3345
3540
  callData,
3541
+ signer,
3542
+ signerAddress: signer,
3346
3543
  networkFee
3347
3544
  },
3348
3545
  wrappingStatus: SubstrateTransactionWrappingStatus.WRAP_RESULT,
@@ -3530,7 +3727,8 @@ export default class KoniExtension {
3530
3727
  request,
3531
3728
  resolve
3532
3729
  } = queued;
3533
- const pair = keyring.getPair(queued.address);
3730
+ const signingAddress = queued.signerAddress || queued.address;
3731
+ const pair = keyring.getPair(signingAddress);
3534
3732
 
3535
3733
  // unlike queued.account.address the following
3536
3734
  // address is encoded with the default prefix
@@ -3560,10 +3758,26 @@ export default class KoniExtension {
3560
3758
  }
3561
3759
  }
3562
3760
  const result = request.sign(registry, pair);
3761
+ let signedTransaction;
3762
+ if (queued.signerAddress && isJsonPayload(payload)) {
3763
+ try {
3764
+ const [chain] = this.#koniState.findNetworkKeyByGenesisHash(payload.genesisHash);
3765
+ if (chain) {
3766
+ const {
3767
+ extrinsic
3768
+ } = await this.buildExtrinsicFromPayload(chain, payload);
3769
+ extrinsic.addSignature(payload.address, result.signature, payload);
3770
+ signedTransaction = extrinsic.toHex();
3771
+ }
3772
+ } catch (e) {
3773
+ console.error('Failed to build signed transaction for wrapped multisig signing', e);
3774
+ }
3775
+ }
3563
3776
  resolve({
3564
3777
  id,
3565
3778
  // In case evm chain, must be cut 2 character after 0x
3566
- signature: result.signature
3779
+ signature: result.signature,
3780
+ signedTransaction
3567
3781
  });
3568
3782
  if (this.#alwaysLock) {
3569
3783
  this.keyringLock();
@@ -4325,7 +4539,8 @@ export default class KoniExtension {
4325
4539
  errorOnTimeOut,
4326
4540
  ...this.createPassConfirmationParams(isPassConfirmation),
4327
4541
  eventsHandler,
4328
- step
4542
+ step,
4543
+ xcmFeeDryRun: extrinsicType === ExtrinsicType.TRANSFER_XCM ? submitData.xcmStepFee : undefined
4329
4544
  });
4330
4545
  }
4331
4546
  async handleYieldLeave(params) {
@@ -5627,6 +5842,8 @@ export default class KoniExtension {
5627
5842
  return await this.reconnectChain(request);
5628
5843
  case 'pri(chainService.disableChain)':
5629
5844
  return await this.disableChain(request);
5845
+ case 'pri(chainService.disableAllChains)':
5846
+ return await this.#koniState.disableAllChains();
5630
5847
  case 'pri(chainService.removeChain)':
5631
5848
  return this.removeCustomChain(request);
5632
5849
  case 'pri(chainService.validateCustomChain)':
@@ -6006,6 +6223,8 @@ export default class KoniExtension {
6006
6223
  return await this.cancelPendingTx(request);
6007
6224
  case 'pri(multisig.initMultisigTx)':
6008
6225
  return await this.initMultisigTx(request);
6226
+ case 'pri(multisig.prepareSignRequest)':
6227
+ return await this.prepareMultisigSignRequest(request);
6009
6228
  case 'pri(multisig.getSignableAccountInfos)':
6010
6229
  return this.#koniState.keyringService.context.getSignableAccountInfos(request);
6011
6230
  /* Multisig Account */
@@ -196,6 +196,7 @@ export default class KoniState {
196
196
  forceRemoveChain(networkKey: string): void;
197
197
  private getDefaultNetworkKeys;
198
198
  disableChain(chainSlug: string): Promise<boolean>;
199
+ disableAllChains(): Promise<boolean>;
199
200
  enableChain(chainSlug: string, enableTokens?: boolean): Promise<boolean>;
200
201
  enableChainWithPriorityAssets(chainSlug: string, enableTokens?: boolean): Promise<boolean>;
201
202
  resetDefaultChains(): boolean;
@@ -749,6 +749,26 @@ export default class KoniState {
749
749
  }
750
750
  return this.chainService.disableChain(chainSlug);
751
751
  }
752
+ async disableAllChains() {
753
+ const chainStateMap = this.chainService.getChainStateMap();
754
+ const activeChainSlugs = Object.keys(chainStateMap).filter(slug => chainStateMap[slug].active);
755
+ const failedChainSlugs = [];
756
+ for (const chainSlug of activeChainSlugs) {
757
+ try {
758
+ const isDisabled = await this.disableChain(chainSlug);
759
+ if (!isDisabled) {
760
+ failedChainSlugs.push(chainSlug);
761
+ }
762
+ } catch (error) {
763
+ failedChainSlugs.push(chainSlug);
764
+ this.logger.error(`Failed to disable chain ${chainSlug}`, error);
765
+ }
766
+ }
767
+ if (failedChainSlugs.length) {
768
+ throw new Error('Unable to turn off all networks. Please try again later');
769
+ }
770
+ return true;
771
+ }
752
772
  async enableChain(chainSlug, enableTokens = true) {
753
773
  if (enableTokens) {
754
774
  await this.chainService.updateAssetSettingByChain(chainSlug, true);
@@ -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.76-0",
20
+ "version": "1.3.78-0",
21
21
  "main": "./cjs/index.js",
22
22
  "module": "./index.js",
23
23
  "types": "./index.d.ts",
@@ -804,6 +804,21 @@
804
804
  "require": "./cjs/services/balance-service/transfer/xcm/availBridge.js",
805
805
  "default": "./services/balance-service/transfer/xcm/availBridge.js"
806
806
  },
807
+ "./services/balance-service/transfer/xcm/bittensorBridge": {
808
+ "types": "./services/balance-service/transfer/xcm/bittensorBridge/index.d.ts",
809
+ "require": "./cjs/services/balance-service/transfer/xcm/bittensorBridge/index.js",
810
+ "default": "./services/balance-service/transfer/xcm/bittensorBridge/index.js"
811
+ },
812
+ "./services/balance-service/transfer/xcm/bittensorBridge/nativeTokenBridge": {
813
+ "types": "./services/balance-service/transfer/xcm/bittensorBridge/nativeTokenBridge.d.ts",
814
+ "require": "./cjs/services/balance-service/transfer/xcm/bittensorBridge/nativeTokenBridge.js",
815
+ "default": "./services/balance-service/transfer/xcm/bittensorBridge/nativeTokenBridge.js"
816
+ },
817
+ "./services/balance-service/transfer/xcm/bittensorBridge/utils": {
818
+ "types": "./services/balance-service/transfer/xcm/bittensorBridge/utils.d.ts",
819
+ "require": "./cjs/services/balance-service/transfer/xcm/bittensorBridge/utils.js",
820
+ "default": "./services/balance-service/transfer/xcm/bittensorBridge/utils.js"
821
+ },
807
822
  "./services/balance-service/transfer/xcm/polygonBridge": {
808
823
  "types": "./services/balance-service/transfer/xcm/polygonBridge.d.ts",
809
824
  "require": "./cjs/services/balance-service/transfer/xcm/polygonBridge.js",
@@ -2091,6 +2106,11 @@
2091
2106
  "require": "./cjs/services/swap-service/handler/base-handler.js",
2092
2107
  "default": "./services/swap-service/handler/base-handler.js"
2093
2108
  },
2109
+ "./services/swap-service/handler/bittensor-handler": {
2110
+ "types": "./services/swap-service/handler/bittensor-handler.d.ts",
2111
+ "require": "./cjs/services/swap-service/handler/bittensor-handler.js",
2112
+ "default": "./services/swap-service/handler/bittensor-handler.js"
2113
+ },
2094
2114
  "./services/swap-service/handler/chainflip-handler": {
2095
2115
  "types": "./services/swap-service/handler/chainflip-handler.d.ts",
2096
2116
  "require": "./cjs/services/swap-service/handler/chainflip-handler.js",
@@ -3008,11 +3028,11 @@
3008
3028
  "@sora-substrate/type-definitions": "^1.17.7",
3009
3029
  "@substrate/connect": "^0.8.9",
3010
3030
  "@subwallet-monorepos/subwallet-services-sdk": "0.1.16",
3011
- "@subwallet/chain-list": "0.2.125",
3012
- "@subwallet/extension-base": "^1.3.76-0",
3013
- "@subwallet/extension-chains": "^1.3.76-0",
3014
- "@subwallet/extension-dapp": "^1.3.76-0",
3015
- "@subwallet/extension-inject": "^1.3.76-0",
3031
+ "@subwallet/chain-list": "0.2.127",
3032
+ "@subwallet/extension-base": "^1.3.78-0",
3033
+ "@subwallet/extension-chains": "^1.3.78-0",
3034
+ "@subwallet/extension-dapp": "^1.3.78-0",
3035
+ "@subwallet/extension-inject": "^1.3.78-0",
3016
3036
  "@subwallet/keyring": "^0.1.14",
3017
3037
  "@subwallet/ui-keyring": "^0.1.14",
3018
3038
  "@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.76-0'
10
+ version: '1.3.78-0'
11
11
  };
@@ -1,3 +1,4 @@
1
1
  import { SubscribeEvmPalletBalance } from '@subwallet/extension-base/types';
2
2
  export declare function subscribeERC20Interval({ addresses, assetMap, callback, chainInfo, evmApi }: SubscribeEvmPalletBalance): () => void;
3
+ export declare function subscribeERC20IntervalForSubtensorEvm({ addresses, assetMap, callback, chainInfo, evmApi, substrateApiMap }: SubscribeEvmPalletBalance): () => void;
3
4
  export declare function subscribeEVMBalance(params: SubscribeEvmPalletBalance): () => void;
@@ -5,9 +5,11 @@ import { _AssetType } from '@subwallet/chain-list/types';
5
5
  import { APIItemState } from '@subwallet/extension-base/background/KoniTypes';
6
6
  import { ASTAR_REFRESH_BALANCE_INTERVAL, SUB_TOKEN_REFRESH_BALANCE_INTERVAL } from '@subwallet/extension-base/constants';
7
7
  import { getERC20Contract } from '@subwallet/extension-base/koni/api/contract-handler/evm/web3';
8
+ import { evmToSs58 } from '@subwallet/extension-base/services/balance-service/transfer/xcm/bittensorBridge/utils';
8
9
  import { _BALANCE_CHAIN_GROUP } from '@subwallet/extension-base/services/chain-service/constants';
9
- import { _getContractAddressOfToken } from '@subwallet/extension-base/services/chain-service/utils';
10
+ import { _getAssetNetuid, _getContractAddressOfToken } from '@subwallet/extension-base/services/chain-service/utils';
10
11
  import { filterAssetsByChainAndType } from '@subwallet/extension-base/utils';
12
+ import BigN from 'bignumber.js';
11
13
  import { BN } from '@polkadot/util';
12
14
  export function subscribeERC20Interval({
13
15
  addresses,
@@ -60,6 +62,77 @@ export function subscribeERC20Interval({
60
62
  clearInterval(interval);
61
63
  };
62
64
  }
65
+ export function subscribeERC20IntervalForSubtensorEvm({
66
+ addresses,
67
+ assetMap,
68
+ callback,
69
+ chainInfo,
70
+ evmApi,
71
+ substrateApiMap
72
+ }) {
73
+ const chain = chainInfo.slug;
74
+ const tokenList = filterAssetsByChainAndType(assetMap, chain, [_AssetType.ERC20]);
75
+ let cancel = false;
76
+ const getTokenBalances = () => {
77
+ Object.values(tokenList).map(async tokenInfo => {
78
+ try {
79
+ var _tokenInfo$metadata;
80
+ if ((_tokenInfo$metadata = tokenInfo.metadata) !== null && _tokenInfo$metadata !== void 0 && _tokenInfo$metadata.isAlphaToken && substrateApiMap) {
81
+ const ss58ToEvmMap = {};
82
+ const subtensorEvmSs58Address = [];
83
+ addresses.forEach(address => {
84
+ const ss58Address = evmToSs58(address);
85
+ subtensorEvmSs58Address.push(ss58Address);
86
+ ss58ToEvmMap[ss58Address] = address;
87
+ });
88
+ if (cancel) {
89
+ return;
90
+ }
91
+ const substrateApi = await substrateApiMap.bittensor.isReady;
92
+ const rawData = await substrateApi.api.call.stakeInfoRuntimeApi.getStakeInfoForColdkeys(subtensorEvmSs58Address);
93
+ const values = rawData.toPrimitive();
94
+ const converted = {};
95
+ for (let i = 0; i < values.length; i++) {
96
+ const [, stakes] = values[i];
97
+ const s58Address = subtensorEvmSs58Address[i];
98
+ const address = ss58ToEvmMap[s58Address];
99
+ converted[address] = {};
100
+ stakes.forEach(stakeInfo => {
101
+ const {
102
+ netuid,
103
+ stake
104
+ } = stakeInfo;
105
+ const currentValue = converted[address][netuid] || BigN(0);
106
+ converted[address][netuid] = currentValue.plus(stake);
107
+ });
108
+ }
109
+ const netuid = _getAssetNetuid(tokenInfo);
110
+ const items = Object.entries(converted).map(([address, stakeMap]) => {
111
+ const value = stakeMap[netuid] || BigN(0);
112
+ return {
113
+ address: address,
114
+ tokenSlug: tokenInfo.slug,
115
+ state: APIItemState.READY,
116
+ free: value.toFixed(0),
117
+ locked: '0'
118
+ };
119
+ });
120
+ if (!cancel) {
121
+ callback(items);
122
+ }
123
+ }
124
+ } catch (err) {
125
+ console.log(tokenInfo.slug, err);
126
+ }
127
+ });
128
+ };
129
+ getTokenBalances();
130
+ const interval = setInterval(getTokenBalances, SUB_TOKEN_REFRESH_BALANCE_INTERVAL);
131
+ return () => {
132
+ cancel = true;
133
+ clearInterval(interval);
134
+ };
135
+ }
63
136
  async function getEVMBalance(addresses, web3Api) {
64
137
  return await Promise.all(addresses.map(async address => {
65
138
  try {
@@ -110,8 +183,10 @@ export function subscribeEVMBalance(params) {
110
183
  getBalance();
111
184
  const interval = setInterval(getBalance, ASTAR_REFRESH_BALANCE_INTERVAL);
112
185
  const unsub2 = subscribeERC20Interval(params);
186
+ const unsub3 = subscribeERC20IntervalForSubtensorEvm(params);
113
187
  return () => {
114
188
  clearInterval(interval);
115
189
  unsub2 && unsub2();
190
+ unsub3 && unsub3();
116
191
  };
117
192
  }
@@ -46,7 +46,8 @@ export function subscribeBalance(addresses, chains, tokens, _chainAssetMap, _cha
46
46
  assetMap: chainAssetMap,
47
47
  callback,
48
48
  chainInfo,
49
- evmApi
49
+ evmApi,
50
+ substrateApiMap
50
51
  });
51
52
  }
52
53
  const tonApi = tonApiMap[chainSlug];