diff --git a/.123trigger b/.123trigger index 98ca5207a7..f5f9e0f6d5 100644 --- a/.123trigger +++ b/.123trigger @@ -176,4 +176,5 @@ 1.3.8 1.3.9 1.3.10 -1.3.11 \ No newline at end of file +1.3.11 +1.3.12 \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index b003316d23..b13e0255d4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,19 @@ # CHANGELOG +## 1.3.12 +Build date: Jan 06, 2025. + +Features & Update: +- Add referral code for Bifrost Liquid Staking (vDOT, vMANTA) +- Support bridge ETH <-> POS (#3893) +- Support Avail Recovery app (#3915) +- Set up SubWallet validators (#2533) +- Update chain-list (#3897) + +Bug fixed: +- Fix max transferable for Avail Bridge (#3911) + + ## 1.3.11 Build date: Dec 23, 2024. @@ -10,6 +24,7 @@ Features & Update: Bug fixed: - Fix errors when making transactions on Tangle mainnet (#3861) + ## 1.3.10 Build date: Dec 12, 2024. diff --git a/CONTRIBUTORS b/CONTRIBUTORS index cbfed0fc89..a55bfb946c 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -1,9 +1,9 @@ - 2914 AnhMTV Release version 1.3.11 + 2922 AnhMTV Release version 1.3.12 2552 Nam Phạm [Issue 3855] test: add log - 2380 S2kael [Issue-3855] Remove log + 2387 S2kael 869 lw-cdm [MasterAccount] Update logic to reorder account on select account modal 568 nguyentiendung [Issue-3553] [Issue-3553] Refactor code and add recipient to swap history. - 490 bluezdot [Issue-3888] build: update version @galacticcouncil/sdk to 5.1.0 + 492 bluezdot 465 Jaco 0.42.5 (#969) 354 Thiendekaco [Issue-3707] [fix] Unified account - fix dApp ui bug #4 186 dominhquang [Issue-3507] Fix UI bug for Notification @@ -12,12 +12,12 @@ 170 lw-cdm 160 Automation Bot [CI Skip] Auto increase webapp build number 104 khainh predefine metadata for Polkadot & Kusama chains + 99 PDTnhah [Issue-3897] Update chainlist 96 lw - 91 PDTnhah [Issue-3861] Fix: Update link navigate to explorer + 94 tunghp2002 [Update] Refactor code 83 Hieu Dao Update README.md 83 leewong 82 Thibaut Sardan Add account filtering feature (#832) - 77 tunghp2002 [update] Reformat sender address 74 bluedot [Issue-3888] build: upgrade version polkadot api 63 Roman fix ui issues 53 Dominhquangdev update Bridge code diff --git a/package.json b/package.json index 062aeef27c..fc9ee8ba77 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,7 @@ "url": "https://github.com/Koniverse/Subwallet-V2.git" }, "sideEffects": false, - "version": "1.3.11", + "version": "1.3.12", "workspaces": [ "packages/*" ], @@ -105,12 +105,12 @@ "@polkadot/types-support": "^15.0.1", "@polkadot/util": "^13.2.3", "@polkadot/util-crypto": "^13.2.3", - "@subwallet/chain-list": "0.2.96", + "@subwallet/chain-list": "0.2.97", "@subwallet/keyring": "^0.1.8-beta.0", "@subwallet/react-ui": "5.1.2-b79", "@subwallet/ui-keyring": "0.1.8-beta.0", "@types/bn.js": "^5.1.6", - "@zondax/ledger-substrate": "0.44.2", + "@zondax/ledger-substrate": "1.0.1", "babel-core": "^7.0.0-bridge.0", "babel-jest": "^29.3.1", "browserify-sign": "^4.2.2", diff --git a/packages/extension-base/package.json b/packages/extension-base/package.json index 6e1d0724c0..2d65f302c5 100644 --- a/packages/extension-base/package.json +++ b/packages/extension-base/package.json @@ -17,7 +17,7 @@ "./detectPackage.cjs" ], "type": "module", - "version": "1.3.11-0", + "version": "1.3.12-1", "main": "index.js", "dependencies": { "@acala-network/api": "^5.0.2", @@ -55,11 +55,11 @@ "@reduxjs/toolkit": "^1.9.1", "@sora-substrate/type-definitions": "^1.17.7", "@substrate/connect": "^0.8.9", - "@subwallet/chain-list": "0.2.96", - "@subwallet/extension-base": "^1.3.11-0", - "@subwallet/extension-chains": "^1.3.11-0", - "@subwallet/extension-dapp": "^1.3.11-0", - "@subwallet/extension-inject": "^1.3.11-0", + "@subwallet/chain-list": "0.2.97", + "@subwallet/extension-base": "^1.3.12-1", + "@subwallet/extension-chains": "^1.3.12-1", + "@subwallet/extension-dapp": "^1.3.12-1", + "@subwallet/extension-inject": "^1.3.12-1", "@subwallet/keyring": "^0.1.8-beta.0", "@subwallet/ui-keyring": "^0.1.8-beta.0", "@ton/core": "^0.56.3", @@ -105,7 +105,7 @@ "web3-utils": "^1.10.0" }, "devDependencies": { - "@subwallet/extension-mocks": "^1.3.11-0", + "@subwallet/extension-mocks": "^1.3.12-1", "@types/uuid": "^9.0.1" } } diff --git a/packages/extension-base/src/background/KoniTypes.ts b/packages/extension-base/src/background/KoniTypes.ts index ff96b76aeb..26778ad267 100644 --- a/packages/extension-base/src/background/KoniTypes.ts +++ b/packages/extension-base/src/background/KoniTypes.ts @@ -277,6 +277,17 @@ export interface MetadataItem { types: Record | string>; userExtensions?: ExtDef; hexV15?: HexString; + tokenInfo?: { + ss58Format: number; + tokenDecimals: number; + tokenSymbol: string; + }; +} + +export interface MetadataV15Item { + genesisHash: string; + specVersion: string; + hexV15?: HexString; } export interface CrowdloanItem { @@ -792,6 +803,7 @@ export interface CreateHardwareAccountItem { name: string; isEthereum: boolean; isGeneric: boolean; + isLedgerRecovery?: boolean; } export interface RequestAccountCreateHardwareV2 extends CreateHardwareAccountItem { @@ -1264,6 +1276,8 @@ export interface LedgerNetwork { isEthereum: boolean; /** Hide networks that are supported by the dot migration app */ isHide?: boolean; + /** Recovery app */ + isRecovery?: boolean; /** Slip44 in the derivation path */ slip44: number; } diff --git a/packages/extension-base/src/constants/staking.ts b/packages/extension-base/src/constants/staking.ts index 4882802bde..6c9c3c0a89 100644 --- a/packages/extension-base/src/constants/staking.ts +++ b/packages/extension-base/src/constants/staking.ts @@ -14,3 +14,8 @@ export const PREDEFINED_STAKING_POOL: Record = { export const MAX_NOMINATIONS = '16'; export const PREDEFINED_EARNING_POOL_PROMISE = fetchStaticData>('nomination-pool-recommendation'); + +export type ChainRecommendValidator = { + maxCount: number; + preSelectValidators: string; +}; diff --git a/packages/extension-base/src/core/substrate/xcm-parser.ts b/packages/extension-base/src/core/substrate/xcm-parser.ts index e3454f20d0..636d38a9f9 100644 --- a/packages/extension-base/src/core/substrate/xcm-parser.ts +++ b/packages/extension-base/src/core/substrate/xcm-parser.ts @@ -6,6 +6,7 @@ import { _ChainAsset, _ChainInfo } from '@subwallet/chain-list/types'; import { _Address } from '@subwallet/extension-base/background/KoniTypes'; import { isAvailChainBridge } from '@subwallet/extension-base/services/balance-service/transfer/xcm/availBridge'; import { _isPolygonChainBridge } from '@subwallet/extension-base/services/balance-service/transfer/xcm/polygonBridge'; +import { _isPosChainBridge } from '@subwallet/extension-base/services/balance-service/transfer/xcm/posBridge'; import { _getChainSubstrateAddressPrefix, _getEvmChainId, _getSubstrateParaId, _getSubstrateRelayParent, _getXcmAssetMultilocation, _isChainEvmCompatible, _isPureEvmChain, _isSubstrateParaChain } from '@subwallet/extension-base/services/chain-service/utils'; import { decodeAddress, evmToAddress } from '@polkadot/util-crypto'; @@ -63,7 +64,7 @@ export function _getXcmMultiLocation (originChainInfo: _ChainInfo, destChainInfo } export function _isXcmTransferUnstable (originChainInfo: _ChainInfo, destChainInfo: _ChainInfo, assetSlug: string): boolean { - return !_isXcmWithinSameConsensus(originChainInfo, destChainInfo) || _isMythosFromHydrationToMythos(originChainInfo, destChainInfo, assetSlug) || _isPolygonBridgeXcm(originChainInfo, destChainInfo); + return !_isXcmWithinSameConsensus(originChainInfo, destChainInfo) || _isMythosFromHydrationToMythos(originChainInfo, destChainInfo, assetSlug) || _isPolygonBridgeXcm(originChainInfo, destChainInfo) || _isPosBridgeXcm(originChainInfo, destChainInfo); } function getAssetHubBridgeUnstableWarning (originChainInfo: _ChainInfo): string { @@ -104,8 +105,18 @@ function getPolygonBridgeWarning (originChainInfo: _ChainInfo): string { } } +function getPosBridgeWarning (originChainInfo: _ChainInfo): string { + if (originChainInfo.slug === COMMON_CHAIN_SLUGS.ETHEREUM || originChainInfo.slug === COMMON_CHAIN_SLUGS.ETHEREUM_SEPOLIA) { + return 'Cross-chain transfer of this token may take up to 22 minutes. Do you still want to continue?'; + } else { + return 'Cross-chain transfer of this token may take up to 90 minutes, and you’ll need to manually claim the funds on the destination network to complete the transfer. Do you still want to continue?'; + } +} + export function _getXcmUnstableWarning (originChainInfo: _ChainInfo, destChainInfo: _ChainInfo, assetSlug: string): string { - if (_isPolygonBridgeXcm(originChainInfo, destChainInfo)) { + if (_isPosBridgeXcm(originChainInfo, destChainInfo)) { + return getPosBridgeWarning(originChainInfo); + } else if (_isPolygonBridgeXcm(originChainInfo, destChainInfo)) { return getPolygonBridgeWarning(originChainInfo); } else if (_isAvailBridgeXcm(originChainInfo, destChainInfo)) { return getAvailBridgeWarning(); @@ -141,6 +152,10 @@ export function _isPolygonBridgeXcm (originChainInfo: _ChainInfo, destChainInfo: return _isPolygonChainBridge(originChainInfo.slug, destChainInfo.slug); } +export function _isPosBridgeXcm (originChainInfo: _ChainInfo, destChainInfo: _ChainInfo): boolean { + return _isPosChainBridge(originChainInfo.slug, destChainInfo.slug); +} + // --------------------------------------------------------------------------------------------------------------------- function _getMultiLocationParent (originChainInfo: _ChainInfo, isWithinSameConsensus: boolean): number { diff --git a/packages/extension-base/src/koni/api/contract-handler/utils/index.ts b/packages/extension-base/src/koni/api/contract-handler/utils/index.ts index b4c24fbac1..85fdcbaf13 100644 --- a/packages/extension-base/src/koni/api/contract-handler/utils/index.ts +++ b/packages/extension-base/src/koni/api/contract-handler/utils/index.ts @@ -29,6 +29,10 @@ export const _AVAIL_BRIDGE_GATEWAY_ABI: Record = require('./avail_b export const _AVAIL_TEST_BRIDGE_GATEWAY_ABI: Record = require('./avail_test_bridge_abi.json'); // eslint-disable-next-line @typescript-eslint/no-var-requires,@typescript-eslint/no-unsafe-assignment export const _POLYGON_BRIDGE_ABI: Record = require('./polygon_bridge_abi.json'); +// eslint-disable-next-line @typescript-eslint/no-var-requires,@typescript-eslint/no-unsafe-assignment +export const _POS_BRIDGE_ABI: Record = require('./pos_bridge_abi.json'); +// eslint-disable-next-line @typescript-eslint/no-var-requires,@typescript-eslint/no-unsafe-assignment +export const _POS_BRIDGE_L2_ABI: Record = require('./pos_bridge_l2_abi.json'); const SNOWBRIDGE_GATEWAY_ETHEREUM_CONTRACT_ADDRESS = '0x27ca963C279c93801941e1eB8799c23f407d68e7'; const SNOWBRIDGE_GATEWAY_SEPOLIA_CONTRACT_ADDRESS = '0x5B4909cE6Ca82d2CE23BD46738953c7959E710Cd'; @@ -72,3 +76,29 @@ export function getPolygonBridgeContract (chain: string): string { throw new Error('Invalid chain'); } + +const POSBRIDGE_GATEWAY_AMOY_CONTRACT_ADDRESS = '0x52eF3d68BaB452a294342DC3e5f464d7f610f72E'; +const POSBRIDGE_GATEWAY_SEPOLIA_CONTRACT_ADDRESS = '0x34F5A25B627f50Bb3f5cAb72807c4D4F405a9232'; + +const POSBRIDGE_GATEWAY_CONTRACT_ADDRESS = '0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619'; +const POSBRIDGE_GATEWAY_ETHEREUM_CONTRACT_ADDRESS = '0xA0c68C638235ee32657e8f720a23ceC1bFc77C77'; + +export function getPosL2BridgeContract (chain: string): string { + if (chain === 'polygon_amoy' || chain === COMMON_CHAIN_SLUGS.ETHEREUM_SEPOLIA) { + return POSBRIDGE_GATEWAY_AMOY_CONTRACT_ADDRESS; + } else if (chain === 'polygon' || chain === COMMON_CHAIN_SLUGS.ETHEREUM) { + return POSBRIDGE_GATEWAY_CONTRACT_ADDRESS; + } + + throw new Error('Invalid chain'); +} + +export function getPosL1BridgeContract (chain: string): string { + if (chain === COMMON_CHAIN_SLUGS.ETHEREUM_SEPOLIA) { + return POSBRIDGE_GATEWAY_SEPOLIA_CONTRACT_ADDRESS; + } else if (chain === COMMON_CHAIN_SLUGS.ETHEREUM) { + return POSBRIDGE_GATEWAY_ETHEREUM_CONTRACT_ADDRESS; + } + + throw new Error('Invalid chain'); +} diff --git a/packages/extension-base/src/koni/api/contract-handler/utils/pos_bridge_abi.json b/packages/extension-base/src/koni/api/contract-handler/utils/pos_bridge_abi.json new file mode 100644 index 0000000000..6c65771703 --- /dev/null +++ b/packages/extension-base/src/koni/api/contract-handler/utils/pos_bridge_abi.json @@ -0,0 +1,783 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "userAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "address payable", + "name": "relayerAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "functionSignature", + "type": "bytes" + } + ], + "name": "MetaTransactionExecuted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "tokenType", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "predicateAddress", + "type": "address" + } + ], + "name": "PredicateRegistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "previousAdminRole", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "newAdminRole", + "type": "bytes32" + } + ], + "name": "RoleAdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "rootToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "childToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "tokenType", + "type": "bytes32" + } + ], + "name": "TokenMapped", + "type": "event" + }, + { + "inputs": [], + "name": "DEFAULT_ADMIN_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "DEPOSIT", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "ERC712_VERSION", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "ETHER_ADDRESS", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAPPER_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAP_TOKEN", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "checkpointManagerAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "childChainManagerAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "childToRootToken", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "rootToken", + "type": "address" + }, + { + "internalType": "address", + "name": "childToken", + "type": "address" + } + ], + "name": "cleanMapToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "depositEtherFor", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "internalType": "address", + "name": "rootToken", + "type": "address" + }, + { + "internalType": "bytes", + "name": "depositData", + "type": "bytes" + } + ], + "name": "depositFor", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "userAddress", + "type": "address" + }, + { + "internalType": "bytes", + "name": "functionSignature", + "type": "bytes" + }, + { + "internalType": "bytes32", + "name": "sigR", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "sigS", + "type": "bytes32" + }, + { + "internalType": "uint8", + "name": "sigV", + "type": "uint8" + } + ], + "name": "executeMetaTransaction", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "inputData", + "type": "bytes" + } + ], + "name": "exit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getChainId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "getDomainSeperator", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "getNonce", + "outputs": [ + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "getRoleAdmin", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + } + ], + "name": "getRoleMember", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "getRoleMemberCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "grantRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasRole", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_owner", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "initializeEIP712", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "rootToken", + "type": "address" + }, + { + "internalType": "address", + "name": "childToken", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "tokenType", + "type": "bytes32" + } + ], + "name": "mapToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "processedExits", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "tokenType", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "predicateAddress", + "type": "address" + } + ], + "name": "registerPredicate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "rootToken", + "type": "address" + }, + { + "internalType": "address", + "name": "childToken", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "tokenType", + "type": "bytes32" + } + ], + "name": "remapToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "renounceRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "revokeRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "rootToChildToken", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newCheckpointManager", + "type": "address" + } + ], + "name": "setCheckpointManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newChildChainManager", + "type": "address" + } + ], + "name": "setChildChainManagerAddress", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newStateSender", + "type": "address" + } + ], + "name": "setStateSender", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "setupContractId", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "stateSenderAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "tokenToType", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "typeToPredicate", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } +] \ No newline at end of file diff --git a/packages/extension-base/src/koni/api/contract-handler/utils/pos_bridge_l2_abi.json b/packages/extension-base/src/koni/api/contract-handler/utils/pos_bridge_l2_abi.json new file mode 100644 index 0000000000..40e62b445c --- /dev/null +++ b/packages/extension-base/src/koni/api/contract-handler/utils/pos_bridge_l2_abi.json @@ -0,0 +1,793 @@ +[ + { + "constant": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "name_", + "type": "string" + }, + { + "indexed": false, + "internalType": "string", + "name": "symbol_", + "type": "string" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "address", + "name": "childChainManager", + "type": "address" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "constant": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "payable": false, + "type": "event" + }, + { + "constant": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "userAddress", + "type": "address" + }, + { + "indexed": true, + "internalType": "address payable", + "name": "relayerAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "functionSignature", + "type": "bytes" + } + ], + "name": "MetaTransactionExecuted", + "payable": false, + "type": "event" + }, + { + "constant": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "previousAdminRole", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "newAdminRole", + "type": "bytes32" + } + ], + "name": "RoleAdminChanged", + "payable": false, + "type": "event" + }, + { + "constant": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleGranted", + "payable": false, + "type": "event" + }, + { + "constant": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleRevoked", + "payable": false, + "type": "event" + }, + { + "constant": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "payable": false, + "type": "event" + }, + { + "constant": false, + "inputs": [], + "name": "DEFAULT_ADMIN_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "DEPOSITOR_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "ERC712_VERSION", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "userAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "functionSignature", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "sigR", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "sigS", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "sigV", + "type": "uint8" + } + ], + "name": "executeMetaTransaction", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "payable": false, + "stateMutability": "payable", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "getChainId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "pure", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "getDomainSeperator", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "getNonce", + "outputs": [ + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "getRoleAdmin", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "index", + "type": "uint256" + } + ], + "name": "getRoleMember", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "getRoleMemberCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "grantRole", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasRole", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "addedValue", + "type": "uint256" + } + ], + "name": "increaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "renounceRole", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "revokeRole", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "depositData", + "type": "bytes" + } + ], + "name": "deposit", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "withdraw", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + } + ] \ No newline at end of file diff --git a/packages/extension-base/src/koni/background/handlers/Extension.ts b/packages/extension-base/src/koni/background/handlers/Extension.ts index 6a6b5485c5..273ce331bd 100644 --- a/packages/extension-base/src/koni/background/handlers/Extension.ts +++ b/packages/extension-base/src/koni/background/handlers/Extension.ts @@ -3,6 +3,7 @@ import { Common } from '@ethereumjs/common'; import { LegacyTransaction } from '@ethereumjs/tx'; +import { COMMON_CHAIN_SLUGS } from '@subwallet/chain-list'; import { _AssetRef, _AssetType, _ChainAsset, _ChainInfo, _MultiChainAsset } from '@subwallet/chain-list/types'; import { TransactionError } from '@subwallet/extension-base/background/errors/TransactionError'; import { withErrorLog } from '@subwallet/extension-base/background/handlers/helpers'; @@ -34,10 +35,11 @@ import { createTonTransaction } from '@subwallet/extension-base/services/balance import { createAvailBridgeExtrinsicFromAvail, createAvailBridgeTxFromEth, createPolygonBridgeExtrinsic, createSnowBridgeExtrinsic, createXcmExtrinsic, CreateXcmExtrinsicProps, FunctionCreateXcmExtrinsic, getXcmMockTxFee } from '@subwallet/extension-base/services/balance-service/transfer/xcm'; import { getClaimTxOnAvail, getClaimTxOnEthereum, isAvailChainBridge } from '@subwallet/extension-base/services/balance-service/transfer/xcm/availBridge'; import { _isPolygonChainBridge, getClaimPolygonBridge, isClaimedPolygonBridge } from '@subwallet/extension-base/services/balance-service/transfer/xcm/polygonBridge'; +import { _isPosChainBridge, getClaimPosBridge } from '@subwallet/extension-base/services/balance-service/transfer/xcm/posBridge'; import { _API_OPTIONS_CHAIN_GROUP, _DEFAULT_MANTA_ZK_CHAIN, _MANTA_ZK_CHAIN_GROUP, _ZK_ASSET_PREFIX, SUFFICIENT_CHAIN } from '@subwallet/extension-base/services/chain-service/constants'; import { _ChainApiStatus, _ChainConnectionStatus, _ChainState, _NetworkUpsertParams, _SubstrateAdapterQueryArgs, _SubstrateApi, _ValidateCustomAssetRequest, _ValidateCustomAssetResponse, EnableChainParams, EnableMultiChainParams } from '@subwallet/extension-base/services/chain-service/types'; -import { _getAssetDecimals, _getAssetSymbol, _getChainNativeTokenBasicInfo, _getContractAddressOfToken, _getEvmChainId, _getTokenOnChainAssetId, _getXcmAssetMultilocation, _isAssetSmartContractNft, _isBridgedToken, _isChainEvmCompatible, _isChainSubstrateCompatible, _isChainTonCompatible, _isCustomAsset, _isLocalToken, _isMantaZkAsset, _isNativeToken, _isPureEvmChain, _isTokenEvmSmartContract, _isTokenTransferredByEvm, _isTokenTransferredByTon } from '@subwallet/extension-base/services/chain-service/utils'; -import { _NotificationInfo, NotificationSetup } from '@subwallet/extension-base/services/inapp-notification-service/interfaces'; +import { _getAssetDecimals, _getAssetSymbol, _getChainNativeTokenBasicInfo, _getContractAddressOfToken, _getEvmChainId, _getTokenMinAmount, _getTokenOnChainAssetId, _getXcmAssetMultilocation, _isAssetSmartContractNft, _isBridgedToken, _isChainEvmCompatible, _isChainSubstrateCompatible, _isChainTonCompatible, _isCustomAsset, _isLocalToken, _isMantaZkAsset, _isNativeToken, _isPureEvmChain, _isTokenEvmSmartContract, _isTokenTransferredByEvm, _isTokenTransferredByTon } from '@subwallet/extension-base/services/chain-service/utils'; +import { ClaimPolygonBridgeNotificationMetadata, NotificationSetup } from '@subwallet/extension-base/services/inapp-notification-service/interfaces'; import { AppBannerData, AppConfirmationData, AppPopupData } from '@subwallet/extension-base/services/mkt-campaign-service/types'; import { EXTENSION_REQUEST_URL } from '@subwallet/extension-base/services/request-service/constants'; import { AuthUrls } from '@subwallet/extension-base/services/request-service/types'; @@ -53,9 +55,8 @@ import { RequestClaimBridge } from '@subwallet/extension-base/types/bridge'; import { GetNotificationParams, RequestIsClaimedPolygonBridge, RequestSwitchStatusParams } from '@subwallet/extension-base/types/notification'; import { CommonOptimalPath } from '@subwallet/extension-base/types/service-base'; import { SwapPair, SwapQuoteResponse, SwapRequest, SwapRequestResult, SwapSubmitParams, ValidateSwapProcessParams } from '@subwallet/extension-base/types/swap'; -import { _analyzeAddress, BN_ZERO, combineAllAccountProxy, createTransactionFromRLP, isSameAddress, MODULE_SUPPORT, reformatAddress, signatureToHex, Transaction as QrTransaction, transformAccounts, transformAddresses, uniqueStringArray } from '@subwallet/extension-base/utils'; +import { _analyzeAddress, BN_ZERO, combineAllAccountProxy, createTransactionFromRLP, isSameAddress, MODULE_SUPPORT, reformatAddress, signatureToHex, toBNString, Transaction as QrTransaction, transformAccounts, transformAddresses, uniqueStringArray } from '@subwallet/extension-base/utils'; import { parseContractInput, parseEvmRlp } from '@subwallet/extension-base/utils/eth/parseTransaction'; -import { metadataExpand } from '@subwallet/extension-chains'; import { MetadataDef } from '@subwallet/extension-inject/types'; import { getKeypairTypeByAddress, isAddress, isSubstrateAddress, isTonAddress } from '@subwallet/keyring'; import { EthereumKeypairTypes, SubstrateKeypairTypes, TonKeypairTypes } from '@subwallet/keyring/types'; @@ -71,12 +72,13 @@ import { combineLatest, Subject } from 'rxjs'; import { TransactionConfig } from 'web3-core'; import { SubmittableExtrinsic } from '@polkadot/api/types'; -import { Metadata, TypeRegistry } from '@polkadot/types'; -import { ChainProperties } from '@polkadot/types/interfaces'; +import { TypeRegistry } from '@polkadot/types'; import { AnyJson, Registry, SignerPayloadJSON, SignerPayloadRaw } from '@polkadot/types/types'; import { assert, hexStripPrefix, hexToU8a, isAscii, isHex, u8aToHex } from '@polkadot/util'; import { decodeAddress, isEthereumAddress } from '@polkadot/util-crypto'; +import { getSuitableRegistry, RegistrySource, setupApiRegistry, setupDappRegistry, setupDatabaseRegistry } from '../utils'; + export function isJsonPayload (value: SignerPayloadJSON | SignerPayloadRaw): value is SignerPayloadJSON { return (value as SignerPayloadJSON).genesisHash !== undefined; } @@ -1462,6 +1464,7 @@ export default class KoniExtension { const isAvailBridgeFromAvail = isAvailChainBridge(originNetworkKey) && _isPureEvmChain(chainInfoMap[destinationNetworkKey]); const isSnowBridgeEvmTransfer = _isPureEvmChain(chainInfoMap[originNetworkKey]) && _isSnowBridgeXcm(chainInfoMap[originNetworkKey], chainInfoMap[destinationNetworkKey]) && !isAvailBridgeFromEvm; const isPolygonBridgeTransfer = _isPolygonChainBridge(originNetworkKey, destinationNetworkKey); + const isPosBridgeTransfer = _isPosChainBridge(originNetworkKey, destinationNetworkKey); let additionalValidator: undefined | ((inputTransaction: SWTransactionResponse) => Promise); let eventsHandler: undefined | ((eventEmitter: TransactionEmitter) => void); @@ -1482,7 +1485,7 @@ export default class KoniExtension { let funcCreateExtrinsic: FunctionCreateXcmExtrinsic; - if (isPolygonBridgeTransfer) { + if (isPosBridgeTransfer || isPolygonBridgeTransfer) { funcCreateExtrinsic = createPolygonBridgeExtrinsic; } else if (isSnowBridgeEvmTransfer) { funcCreateExtrinsic = createSnowBridgeExtrinsic; @@ -1548,7 +1551,7 @@ export default class KoniExtension { transaction: extrinsic, data: inputData, extrinsicType: ExtrinsicType.TRANSFER_XCM, - chainType: !isSnowBridgeEvmTransfer && !isAvailBridgeFromEvm && !isPolygonBridgeTransfer ? ChainType.SUBSTRATE : ChainType.EVM, + chainType: !isSnowBridgeEvmTransfer && !isAvailBridgeFromEvm && !isPolygonBridgeTransfer && !isPosBridgeTransfer ? ChainType.SUBSTRATE : ChainType.EVM, transferNativeAmount: _isNativeToken(originTokenInfo) ? value : '0', ignoreWarnings, isTransferAll: transferAll, @@ -1780,6 +1783,10 @@ export default class KoniExtension { const chainInfoMap = this.#koniState.chainService.getChainInfoMap(); const destinationTokenInfo = this.#koniState.getXcmEqualAssetByChain(destChain, originTokenInfo.slug); + // todo: improve this case. Currently set 1 AVAIL for covering fee as default. + const isSpecialBridgeFromAvail = originTokenInfo.slug === 'avail_mainnet-NATIVE-AVAIL' && destChain === COMMON_CHAIN_SLUGS.ETHEREUM; + const specialBridgeFromAvailFee = new BigN(toBNString(1, _getAssetDecimals(originTokenInfo))).minus(new BigN(_getTokenMinAmount(originTokenInfo))); + if (destinationTokenInfo) { const [bnMockExecutionFee, { value }] = await Promise.all([ getXcmMockTxFee(substrateApi, chainInfoMap, originTokenInfo, destinationTokenInfo), @@ -1787,7 +1794,7 @@ export default class KoniExtension { ]); const bnMaxTransferable = new BigN(value); - const txFee = bnMockExecutionFee.multipliedBy(XCM_FEE_RATIO); + const txFee = isSpecialBridgeFromAvail ? specialBridgeFromAvailFee : bnMockExecutionFee.multipliedBy(XCM_FEE_RATIO); return bnMaxTransferable.minus(txFee); } @@ -2515,7 +2522,7 @@ export default class KoniExtension { } } - /// Signing substrate request + // Signing substrate request private async signingApprovePasswordV2 ({ id }: RequestSigningApprovePasswordV2): Promise { const queued = this.#koniState.getSignRequest(id); @@ -2526,7 +2533,7 @@ export default class KoniExtension { // unlike queued.account.address the following // address is encoded with the default prefix - // which what is used for password caching mapping + // which is used for password caching mapping const { address } = pair; if (!pair) { @@ -2541,77 +2548,29 @@ export default class KoniExtension { const { payload } = request; - let registry: Registry; + let registry: Registry = new TypeRegistry(); if (isJsonPayload(payload)) { const [, chainInfo] = this.#koniState.findNetworkKeyByGenesisHash(payload.genesisHash); - let metadata: MetadataDef | MetadataItem | undefined; - - /** - * Get the metadata for the genesisHash - * @todo: need to handle case metadata store in db - */ - metadata = this.#koniState.knownMetadata.find((meta: MetadataDef) => - meta.genesisHash === payload.genesisHash); - if (metadata) { - // we have metadata, expand it and extract the info/registry - const expanded = metadataExpand(metadata, false); - - registry = expanded.registry; - registry.setSignedExtensions(payload.signedExtensions, expanded.definition.userExtensions); + const allRegistry: RegistrySource[] = [ + setupApiRegistry(chainInfo, this.#koniState), + setupDatabaseRegistry( + await this.#koniState.chainService.getMetadataByHash(payload.genesisHash) as MetadataItem, + chainInfo, + payload + ), + setupDappRegistry( + this.#koniState.knownMetadata.find((meta: MetadataDef) => meta.genesisHash === payload.genesisHash) as MetadataDef, + payload + ) + ].filter((item): item is RegistrySource => item !== null && item.registry !== undefined); + + if (allRegistry.length === 0) { + registry.setSignedExtensions(payload.signedExtensions); } else { - metadata = await this.#koniState.chainService.getMetadataByHash(payload.genesisHash); - - if (metadata) { - registry = new TypeRegistry(); - - const _metadata = new Metadata(registry, metadata.hexValue); - - registry.register(metadata.types); - registry.setChainProperties(registry.createType('ChainProperties', { - ss58Format: chainInfo?.substrateInfo?.addressPrefix ?? 42, - tokenDecimals: chainInfo?.substrateInfo?.decimals, - tokenSymbol: chainInfo?.substrateInfo?.symbol - }) as unknown as ChainProperties); - registry.setMetadata(_metadata, payload.signedExtensions, metadata.userExtensions); - } else { - // we have no metadata, create a new registry - registry = new TypeRegistry(); - registry.setSignedExtensions(payload.signedExtensions); - } - } - - if (!metadata) { - /* - * Some networks must have metadata to signing, - * so if the chain not active (cannot use metadata from api), it must be rejected - * */ - if ( - chainInfo && - (_API_OPTIONS_CHAIN_GROUP.avail.includes(chainInfo.slug) || _API_OPTIONS_CHAIN_GROUP.goldberg.includes(chainInfo.slug)) // The special case for chains that need metadata to signing - ) { - // For case the chain does not have any provider - if (!Object.keys(chainInfo.providers).length) { - reject(new Error('{{chain}} network does not have any provider to connect, please update metadata from dApp'.replaceAll('{{chain}}', chainInfo.name))); - - return false; - } - - const isChainActive = this.#koniState.getChainStateByKey(chainInfo.slug).active; - - if (!isChainActive) { - reject(new Error('Please activate {{chain}} network before signing'.replaceAll('{{chain}}', chainInfo.name))); - - return false; - } - - registry = this.#koniState.getSubstrateApi(chainInfo.slug).api.registry as unknown as TypeRegistry; - } + registry = getSuitableRegistry(allRegistry, payload); } - } else { - // for non-payload, just create a registry to use - registry = new TypeRegistry(); } const result = request.sign(registry as unknown as TypeRegistry, pair); @@ -3898,8 +3857,14 @@ export default class KoniExtension { let transaction: SubmittableExtrinsic<'promise'> | TransactionConfig | null = null; const evmApi = this.#koniState.getEvmApi(chain); + const metadata = notification.metadata as ClaimPolygonBridgeNotificationMetadata; + + if (metadata.bridgeType === 'POS') { + transaction = await getClaimPosBridge(chain, notification, evmApi); + } else { + transaction = await getClaimPolygonBridge(chain, notification, evmApi); + } - transaction = await getClaimPolygonBridge(chain, notification, evmApi); const chainType: ChainType = ChainType.EVM; return await this.#koniState.transactionService.handleTransaction({ diff --git a/packages/extension-base/src/koni/background/utils.ts b/packages/extension-base/src/koni/background/utils.ts new file mode 100644 index 0000000000..3ad32601d2 --- /dev/null +++ b/packages/extension-base/src/koni/background/utils.ts @@ -0,0 +1,94 @@ +// Copyright 2019-2022 @subwallet/extension-koni authors & contributors +// SPDX-License-Identifier: Apache-2.0 + +import { _ChainInfo } from '@subwallet/chain-list/types'; +import { MetadataItem } from '@subwallet/extension-base/background/KoniTypes'; +import { metadataExpand } from '@subwallet/extension-chains/bundle'; +import { MetadataDef } from '@subwallet/extension-inject/types'; + +import { Metadata, TypeRegistry } from '@polkadot/types'; +import { ChainProperties } from '@polkadot/types/interfaces'; +import { Registry, SignerPayloadJSON } from '@polkadot/types/types'; + +import KoniState from './handlers/State'; + +export interface RegistrySource{ + registry: Registry, + specVersion: string | number, +} + +export function getSuitableRegistry (registries: RegistrySource[], payload: SignerPayloadJSON) { + const payloadSpecVersion = parseInt(payload.specVersion); + const sortedRegistries = registries + .filter((registrySource): registrySource is RegistrySource => registrySource.registry !== undefined) + .map((registrySource) => { + const specVersion = Number(registrySource.specVersion); + const distance = Math.abs(specVersion - payloadSpecVersion); + const isHigher = specVersion >= payloadSpecVersion; + + return { + registry: registrySource.registry, + specVersion, + distance, + isHigher + }; + }) + .sort((a, b) => { + if (a.distance !== b.distance) { + return a.distance - b.distance; + } + + return b.specVersion - a.specVersion; + }); + + return sortedRegistries[0].registry; +} + +export function setupApiRegistry (chainInfo: _ChainInfo | undefined, koniState: KoniState): RegistrySource | null { + if (!chainInfo) { + return null; + } + + const api = koniState.getSubstrateApi(chainInfo.slug).api; + const apiSpecVersion = api?.runtimeVersion.specVersion.toString(); + const registry = api?.registry as unknown as TypeRegistry; + + return { + registry, + specVersion: apiSpecVersion + }; +} + +export function setupDatabaseRegistry (metadata: MetadataItem, chainInfo: _ChainInfo | undefined, payload: SignerPayloadJSON): RegistrySource | null { + if (!metadata || !metadata.genesisHash || !chainInfo) { + return null; + } + + const registry = new TypeRegistry(); + const _metadata = new Metadata(registry, metadata.hexValue); + + registry.register(metadata.types); + registry.setChainProperties(registry.createType('ChainProperties', metadata.tokenInfo) as unknown as ChainProperties); + registry.setMetadata(_metadata, payload.signedExtensions, metadata.userExtensions); + + return { + registry, + specVersion: metadata.specVersion + }; +} + +export function setupDappRegistry (metadata: MetadataDef, payload: SignerPayloadJSON): RegistrySource | null { + if (!metadata || !metadata.genesisHash) { + return null; + } + + const expanded = metadataExpand(metadata, false); + const registry = expanded.registry; + + registry.setSignedExtensions(payload.signedExtensions, expanded.definition.userExtensions); + + return { + registry, + specVersion: metadata.specVersion + }; +} diff --git a/packages/extension-base/src/packageInfo.ts b/packages/extension-base/src/packageInfo.ts index c1541585d7..8356c1b69b 100644 --- a/packages/extension-base/src/packageInfo.ts +++ b/packages/extension-base/src/packageInfo.ts @@ -3,4 +3,4 @@ // Do not edit, auto-generated by @polkadot/dev -export const packageInfo = { name: '@subwallet/extension-base', path: 'auto', type: 'auto', version: '1.3.11-0' }; +export const packageInfo = { name: '@subwallet/extension-base', path: 'auto', type: 'auto', version: '1.3.12-1' }; diff --git a/packages/extension-base/src/services/balance-service/transfer/smart-contract.ts b/packages/extension-base/src/services/balance-service/transfer/smart-contract.ts index d0ea926e1b..c53d389292 100644 --- a/packages/extension-base/src/services/balance-service/transfer/smart-contract.ts +++ b/packages/extension-base/src/services/balance-service/transfer/smart-contract.ts @@ -90,7 +90,10 @@ export async function getERC20TransactionObject ( const transferData = generateTransferData(to, transferValue); const [gasLimit, priority] = await Promise.all([ // eslint-disable-next-line @typescript-eslint/no-unsafe-call,@typescript-eslint/no-unsafe-member-access - erc20Contract.methods.transfer(to, transferValue).estimateGas({ from }) as number, + erc20Contract.methods.transfer(to, transferValue).estimateGas({ from }) + .catch(() => { + throw Error('Unable to estimate fee for this transaction. Try again or contact support at agent@subwallet.app'); + }) as number, calculateGasFeeParams(evmApi, networkKey) ]); diff --git a/packages/extension-base/src/services/balance-service/transfer/xcm/index.ts b/packages/extension-base/src/services/balance-service/transfer/xcm/index.ts index 3f8af260c5..6f6407d265 100644 --- a/packages/extension-base/src/services/balance-service/transfer/xcm/index.ts +++ b/packages/extension-base/src/services/balance-service/transfer/xcm/index.ts @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 import { _ChainAsset, _ChainInfo } from '@subwallet/chain-list/types'; -import { _isPolygonBridgeXcm, _isSnowBridgeXcm } from '@subwallet/extension-base/core/substrate/xcm-parser'; +import { _isPolygonBridgeXcm, _isPosBridgeXcm, _isSnowBridgeXcm } from '@subwallet/extension-base/core/substrate/xcm-parser'; import { getAvailBridgeExtrinsicFromAvail, getAvailBridgeTxFromEth } from '@subwallet/extension-base/services/balance-service/transfer/xcm/availBridge'; import { getExtrinsicByPolkadotXcmPallet } from '@subwallet/extension-base/services/balance-service/transfer/xcm/polkadotXcm'; import { _createPolygonBridgeL1toL2Extrinsic, _createPolygonBridgeL2toL1Extrinsic } from '@subwallet/extension-base/services/balance-service/transfer/xcm/polygonBridge'; @@ -19,6 +19,8 @@ import { SubmittableExtrinsic } from '@polkadot/api/types'; import { u8aToHex } from '@polkadot/util'; import { addressToEvm } from '@polkadot/util-crypto'; +import { _createPosBridgeL1toL2Extrinsic, _createPosBridgeL2toL1Extrinsic, _isPosChainBridge } from './posBridge'; + export type CreateXcmExtrinsicProps = { originTokenInfo: _ChainAsset; destinationTokenInfo: _ChainAsset; @@ -122,8 +124,11 @@ export const createPolygonBridgeExtrinsic = async ({ chainInfoMap, sendingValue }: CreateXcmExtrinsicProps): Promise => { const originChainInfo = chainInfoMap[originTokenInfo.originChain]; const destinationChainInfo = chainInfoMap[destinationTokenInfo.originChain]; + const isPolygonBridgeXcm = _isPolygonBridgeXcm(originChainInfo, destinationChainInfo); + + const isValidBridge = isPolygonBridgeXcm || _isPosBridgeXcm(originChainInfo, destinationChainInfo); - if (!_isPolygonBridgeXcm(originChainInfo, destinationChainInfo)) { + if (!isValidBridge) { throw new Error('This is not a valid PolygonBridge transfer'); } @@ -137,11 +142,15 @@ export const createPolygonBridgeExtrinsic = async ({ chainInfoMap, const sourceChain = originChainInfo.slug; - if (sourceChain === 'polygonzkEvm_cardona' || sourceChain === 'polygonZkEvm') { - return _createPolygonBridgeL2toL1Extrinsic(originTokenInfo, originChainInfo, sender, recipient, sendingValue, evmApi); - } else { - return _createPolygonBridgeL1toL2Extrinsic(originTokenInfo, originChainInfo, sender, recipient, sendingValue, evmApi); - } + const createExtrinsic = isPolygonBridgeXcm + ? (sourceChain === 'polygonzkEvm_cardona' || sourceChain === 'polygonZkEvm') + ? _createPolygonBridgeL2toL1Extrinsic + : _createPolygonBridgeL1toL2Extrinsic + : (sourceChain === 'polygon_amoy' || sourceChain === 'polygon') + ? _createPosBridgeL2toL1Extrinsic + : _createPosBridgeL1toL2Extrinsic; + + return createExtrinsic(originTokenInfo, originChainInfo, sender, recipient, sendingValue, evmApi); }; export const getXcmMockTxFee = async (substrateApi: _SubstrateApi, chainInfoMap: Record, originTokenInfo: _ChainAsset, destinationTokenInfo: _ChainAsset): Promise => { diff --git a/packages/extension-base/src/services/balance-service/transfer/xcm/polygonBridge.ts b/packages/extension-base/src/services/balance-service/transfer/xcm/polygonBridge.ts index 7cd5b30c5a..e8d2fc5f92 100644 --- a/packages/extension-base/src/services/balance-service/transfer/xcm/polygonBridge.ts +++ b/packages/extension-base/src/services/balance-service/transfer/xcm/polygonBridge.ts @@ -93,7 +93,7 @@ export async function getClaimPolygonBridge (chainSlug: string, notification: _N const isTestnet = chainSlug === COMMON_CHAIN_SLUGS.ETHEREUM_SEPOLIA; const proofDomain = isTestnet ? POLYGON_PROOF_INDEXER.TESTNET : POLYGON_PROOF_INDEXER.MAINNET; - const proofResponse = await fetch(`${proofDomain}?networkId=${metadata.sourceNetwork}&depositCount=${metadata.counter}`) + const proofResponse = await fetch(`${proofDomain}?networkId=${metadata.sourceNetwork ?? ''}&depositCount=${metadata.counter ?? ''}`) .then((res) => res.json()) as ClaimNotification; const proof = proofResponse.proof; diff --git a/packages/extension-base/src/services/balance-service/transfer/xcm/posBridge.ts b/packages/extension-base/src/services/balance-service/transfer/xcm/posBridge.ts new file mode 100644 index 0000000000..4b64c45437 --- /dev/null +++ b/packages/extension-base/src/services/balance-service/transfer/xcm/posBridge.ts @@ -0,0 +1,180 @@ +// Copyright 2019-2022 @subwallet/extension-base +// SPDX-License-Identifier: Apache-2.0 + +import { COMMON_CHAIN_SLUGS } from '@subwallet/chain-list'; +import { _ChainAsset, _ChainInfo } from '@subwallet/chain-list/types'; +import { getWeb3Contract } from '@subwallet/extension-base/koni/api/contract-handler/evm/web3'; +import { _POS_BRIDGE_ABI, _POS_BRIDGE_L2_ABI, getPosL1BridgeContract, getPosL2BridgeContract } from '@subwallet/extension-base/koni/api/contract-handler/utils'; +import { _EvmApi } from '@subwallet/extension-base/services/chain-service/types'; +import { calculateGasFeeParams } from '@subwallet/extension-base/services/fee-service/utils'; +import { _NotificationInfo, ClaimPolygonBridgeNotificationMetadata } from '@subwallet/extension-base/services/inapp-notification-service/interfaces'; +import { fetchPolygonBridgeTransactions } from '@subwallet/extension-base/services/inapp-notification-service/utils'; +import { BasicTxErrorType } from '@subwallet/extension-base/types'; +import { TransactionConfig } from 'web3-core'; +import { ContractSendMethod } from 'web3-eth-contract'; + +interface inputData { + error?: string + message: string; + result?: string; +} + +interface EventArgument { + topics: string[]; +} + +interface Event { + arguments: EventArgument[]; +} + +export const POS_EXIT_PAYLOAD_INDEXER = { + MAINNET: 'https://proof-generator.polygon.technology/api/v1/matic/exit-payload', + TESTNET: 'https://proof-generator.polygon.technology/api/v1/amoy/exit-payload' +}; + +export async function _createPosBridgeL1toL2Extrinsic (tokenInfo: _ChainAsset, originChainInfo: _ChainInfo, sender: string, recipientAddress: string, value: string, evmApi: _EvmApi): Promise { + const posBridgeContractAddress = getPosL1BridgeContract(originChainInfo.slug); + const posBridgeContract = getWeb3Contract(posBridgeContractAddress, evmApi, _POS_BRIDGE_ABI); + + // eslint-disable-next-line @typescript-eslint/no-unsafe-call,@typescript-eslint/no-unsafe-member-access,@typescript-eslint/no-unsafe-assignment + const transferCall: ContractSendMethod = posBridgeContract.methods.depositEtherFor(recipientAddress); + const transferEncodedCall = transferCall.encodeABI(); + const priority = await calculateGasFeeParams(evmApi, evmApi.chainSlug); + + const transactionConfig: TransactionConfig = { + from: sender, + to: posBridgeContractAddress, + value: value, + data: transferEncodedCall, + gasPrice: priority.gasPrice, + maxFeePerGas: priority?.maxFeePerGas?.toString(), + maxPriorityFeePerGas: priority?.maxPriorityFeePerGas?.toString() + }; + + const gasLimit = await evmApi.api.eth.estimateGas(transactionConfig).catch(() => 200000); + + transactionConfig.gas = gasLimit.toString(); + + return transactionConfig; +} + +export async function _createPosBridgeL2toL1Extrinsic (tokenInfo: _ChainAsset, originChainInfo: _ChainInfo, sender: string, recipientAddress: string, value: string, evmApi: _EvmApi): Promise { + const posBridgeContractAddress = getPosL2BridgeContract(originChainInfo.slug); + const posBridgeContract = getWeb3Contract(posBridgeContractAddress, evmApi, _POS_BRIDGE_L2_ABI); + + // eslint-disable-next-line @typescript-eslint/no-unsafe-call,@typescript-eslint/no-unsafe-member-access,@typescript-eslint/no-unsafe-assignment + const transferCall: ContractSendMethod = posBridgeContract.methods.withdraw(value); + const transferEncodedCall = transferCall.encodeABI(); + const priority = await calculateGasFeeParams(evmApi, evmApi.chainSlug); + + const transactionConfig: TransactionConfig = { + from: sender, + to: posBridgeContractAddress, + value: undefined, + data: transferEncodedCall, + gasPrice: priority.gasPrice, + maxFeePerGas: priority?.maxFeePerGas?.toString(), + maxPriorityFeePerGas: priority?.maxPriorityFeePerGas?.toString() + }; + + const gasLimit = await evmApi.api.eth.estimateGas(transactionConfig).catch(() => 200000); + + transactionConfig.gas = gasLimit.toString(); + + return transactionConfig; +} + +export async function getClaimPosBridge (chainSlug: string, notification: _NotificationInfo, evmApi: _EvmApi) { + const posBridgeContractAddress = getPosL2BridgeContract(chainSlug); + const posBridgeContract = getWeb3Contract(posBridgeContractAddress, evmApi, _POS_BRIDGE_L2_ABI); + + const metadata = notification.metadata as ClaimPolygonBridgeNotificationMetadata; + + // eslint-disable-next-line @typescript-eslint/no-unsafe-call,@typescript-eslint/no-unsafe-member-access,@typescript-eslint/no-unsafe-assignment + const event = posBridgeContract.events.Transfer(metadata.userAddress, metadata.userAddress, metadata.amounts[0]) as Event; + + const isTestnet = chainSlug === COMMON_CHAIN_SLUGS.ETHEREUM_SEPOLIA; + const domain = isTestnet ? POS_EXIT_PAYLOAD_INDEXER.TESTNET : POS_EXIT_PAYLOAD_INDEXER.MAINNET; + + const eventSignature: string = event?.arguments?.[0]?.topics?.[0]; + + let inputData: inputData; + + try { + const res = await fetch(`${domain}/${metadata.transactionHash}?eventSignature=${eventSignature}`); + + inputData = await res.json() as inputData; + + if (inputData.error && inputData.message.includes('not been checkpointed yet')) { + throw new Error(`${inputData.message}. Please try again later.`); + } + } catch (err) { + console.error('Error:', err); + throw new Error(BasicTxErrorType.INTERNAL_ERROR); + } + + const posClaimContractAddress = getPosL1BridgeContract(chainSlug); + const posClaimContract = getWeb3Contract(posClaimContractAddress, evmApi, _POS_BRIDGE_ABI); + + // eslint-disable-next-line @typescript-eslint/no-unsafe-call,@typescript-eslint/no-unsafe-member-access,@typescript-eslint/no-unsafe-assignment + const transferCall: ContractSendMethod = posClaimContract.methods.exit(inputData.result); + const transferEncodedCall = transferCall.encodeABI(); + + const priority = await calculateGasFeeParams(evmApi, evmApi.chainSlug); + + const transactionConfig = { + from: metadata.userAddress, + to: posClaimContractAddress, + value: '0', + data: transferEncodedCall, + gasPrice: priority.gasPrice, + maxFeePerGas: priority.maxFeePerGas?.toString(), + maxPriorityFeePerGas: priority.maxPriorityFeePerGas?.toString() + } as TransactionConfig; + + const gasLimit = await evmApi.api.eth.estimateGas(transactionConfig).catch(() => 200000); + + transactionConfig.gas = gasLimit.toString(); + + return transactionConfig; +} + +export async function isClaimedPosBridge (id: string, address: string, isTestnet: boolean): Promise { + try { + const isClaimableBridge = await fetchPolygonBridgeTransactions(address, isTestnet); + + if (isClaimableBridge && isClaimableBridge.success) { + const isIdClaimable = isClaimableBridge.result.some((transaction) => transaction._id === id); + + return !isIdClaimable; + } + } catch (err) { + console.error('Error:', err); + } + + return false; +} + +export function _isPosChainBridge (srcChain: string, destChain: string): boolean { + if (srcChain === 'polygon_amoy' && destChain === COMMON_CHAIN_SLUGS.ETHEREUM_SEPOLIA) { + return true; + } else if (srcChain === COMMON_CHAIN_SLUGS.ETHEREUM_SEPOLIA && destChain === 'polygon_amoy') { + return true; + } else if (srcChain === 'polygon' && destChain === COMMON_CHAIN_SLUGS.ETHEREUM) { + return true; + } else if (srcChain === COMMON_CHAIN_SLUGS.ETHEREUM && destChain === 'polygon') { + return true; + } + + return false; +} + +export function _isPosChainL2Bridge (srcChain: string, destChain: string): boolean { + if (srcChain === 'polygon_amoy' && destChain === COMMON_CHAIN_SLUGS.ETHEREUM_SEPOLIA) { + return true; + } else if (srcChain === 'polygon' && destChain === COMMON_CHAIN_SLUGS.ETHEREUM) { + return true; + } + + return false; +} diff --git a/packages/extension-base/src/services/chain-service/index.ts b/packages/extension-base/src/services/chain-service/index.ts index 5d5e3f7562..accbad33e5 100644 --- a/packages/extension-base/src/services/chain-service/index.ts +++ b/packages/extension-base/src/services/chain-service/index.ts @@ -3,7 +3,7 @@ import { AssetLogoMap, AssetRefMap, ChainAssetMap, ChainInfoMap, ChainLogoMap, MultiChainAssetMap } from '@subwallet/chain-list'; import { _AssetRef, _AssetRefPath, _AssetType, _ChainAsset, _ChainInfo, _ChainStatus, _EvmInfo, _MultiChainAsset, _SubstrateChainType, _SubstrateInfo, _TonInfo } from '@subwallet/chain-list/types'; -import { AssetSetting, ValidateNetworkResponse } from '@subwallet/extension-base/background/KoniTypes'; +import { AssetSetting, MetadataItem, ValidateNetworkResponse } from '@subwallet/extension-base/background/KoniTypes'; import { _DEFAULT_ACTIVE_CHAINS, _ZK_ASSET_PREFIX, LATEST_CHAIN_DATA_FETCHING_INTERVAL } from '@subwallet/extension-base/services/chain-service/constants'; import { EvmChainHandler } from '@subwallet/extension-base/services/chain-service/handler/EvmChainHandler'; import { MantaPrivateHandler } from '@subwallet/extension-base/services/chain-service/handler/manta/MantaPrivateHandler'; @@ -13,7 +13,7 @@ import { _CHAIN_VALIDATION_ERROR } from '@subwallet/extension-base/services/chai import { _ChainApiStatus, _ChainConnectionStatus, _ChainState, _CUSTOM_PREFIX, _DataMap, _EvmApi, _NetworkUpsertParams, _NFT_CONTRACT_STANDARDS, _SMART_CONTRACT_STANDARDS, _SmartContractTokenInfo, _SubstrateApi, _ValidateCustomAssetRequest, _ValidateCustomAssetResponse } from '@subwallet/extension-base/services/chain-service/types'; import { _isAssetAutoEnable, _isAssetCanPayTxFee, _isAssetFungibleToken, _isChainEnabled, _isCustomAsset, _isCustomChain, _isCustomProvider, _isEqualContractAddress, _isEqualSmartContractAsset, _isLocalToken, _isMantaZkAsset, _isPureEvmChain, _isPureSubstrateChain, _parseAssetRefKey, randomizeProvider, updateLatestChainInfo } from '@subwallet/extension-base/services/chain-service/utils'; import { EventService } from '@subwallet/extension-base/services/event-service'; -import { IChain, IMetadataItem } from '@subwallet/extension-base/services/storage-service/databases'; +import { IChain, IMetadataItem, IMetadataV15Item } from '@subwallet/extension-base/services/storage-service/databases'; import DatabaseService from '@subwallet/extension-base/services/storage-service/DatabaseService'; import AssetSettingStore from '@subwallet/extension-base/stores/AssetSetting'; import { addLazy, calculateMetadataHash, fetchStaticData, filterAssetsByChainAndType, getShortMetadata, MODULE_SUPPORT } from '@subwallet/extension-base/utils'; @@ -2070,46 +2070,56 @@ export class ChainService { return this.dbService.stores.metadata.upsertMetadata(chain, metadata); } + getMetadataV15 (chain: string) { + return this.dbService.stores.metadataV15.getMetadata(chain); + } + + upsertMetadataV15 (chain: string, metadata: IMetadataV15Item) { + return this.dbService.stores.metadataV15.upsertMetadata(chain, metadata); + } + getMetadataByHash (hash: string) { return this.dbService.stores.metadata.getMetadataByGenesisHash(hash); } - getExtraInfo (chain: string): Omit { - const chainInfo = this.getChainInfoByKey(chain); + getExtraInfo (metadata: MetadataItem): Omit { + const tokenInfo = metadata.tokenInfo; return { - decimals: chainInfo.substrateInfo?.decimals ?? 0, - tokenSymbol: chainInfo.substrateInfo?.symbol ?? 'Unit', - base58Prefix: chainInfo.substrateInfo?.addressPrefix ?? 42 + decimals: tokenInfo?.tokenDecimals ?? 0, + tokenSymbol: tokenInfo?.tokenSymbol ?? 'Unit', + base58Prefix: tokenInfo?.ss58Format ?? 42 }; } async calculateMetadataHash (chain: string): Promise { const metadata = await this.getMetadata(chain); + const metadataV15 = await this.getMetadataV15(chain); - if (!metadata || !metadata.hexV15) { + if (!metadata || !metadataV15 || !metadataV15.hexV15) { return undefined; } - const extraInfo = this.getExtraInfo(chain); + const extraInfo = this.getExtraInfo(metadata); const specVersion = parseInt(metadata.specVersion); const specName = metadata.specName; - const hexV15 = metadata.hexV15; + const hexV15 = metadataV15.hexV15; return calculateMetadataHash({ ...extraInfo, specVersion, specName }, hexV15); } async shortenMetadata (chain: string, txBlob: string): Promise { const metadata = await this.getMetadata(chain); + const metadataV15 = await this.getMetadataV15(chain); - if (!metadata || !metadata.hexV15) { + if (!metadata || !metadataV15 || !metadataV15.hexV15) { return undefined; } - const extraInfo = this.getExtraInfo(chain); + const extraInfo = this.getExtraInfo(metadata); const specVersion = parseInt(metadata.specVersion); const specName = metadata.specName; - const hexV15 = metadata.hexV15; + const hexV15 = metadataV15.hexV15; return getShortMetadata(txBlob as HexString, { ...extraInfo, specVersion, specName }, hexV15); } diff --git a/packages/extension-base/src/services/chain-service/utils/patch.ts b/packages/extension-base/src/services/chain-service/utils/patch.ts index 2dc53844a5..9e8b6c3382 100644 --- a/packages/extension-base/src/services/chain-service/utils/patch.ts +++ b/packages/extension-base/src/services/chain-service/utils/patch.ts @@ -8,7 +8,7 @@ const branchName = process.env.BRANCH_NAME || 'subwallet-dev'; const fetchDomain = PRODUCTION_BRANCHES.indexOf(branchName) > -1 ? 'https://chain-list-assets.subwallet.app' : 'https://dev.sw-chain-list-assets.pages.dev'; const fetchFile = PRODUCTION_BRANCHES.indexOf(branchName) > -1 ? 'list.json' : 'preview.json'; -const ChainListVersion = '0.2.96'; // update this when build chainlist +const ChainListVersion = '0.2.97'; // update this when build chainlist // todo: move this interface to chainlist export interface PatchInfo { diff --git a/packages/extension-base/src/services/earning-service/constants/chains.ts b/packages/extension-base/src/services/earning-service/constants/chains.ts index 9c3d3666f7..8f5c77fee7 100644 --- a/packages/extension-base/src/services/earning-service/constants/chains.ts +++ b/packages/extension-base/src/services/earning-service/constants/chains.ts @@ -27,3 +27,5 @@ export const ST_LIQUID_TOKEN_ABI: Record = require('./abis/st_liqui export const MANTA_VALIDATOR_POINTS_PER_BLOCK = 20; export const MANTA_MIN_DELEGATION = 500; + +export const CHANNEL_ID = 7; diff --git a/packages/extension-base/src/services/earning-service/handlers/liquid-staking/bifrost-manta.ts b/packages/extension-base/src/services/earning-service/handlers/liquid-staking/bifrost-manta.ts index 8d49cb9a55..7a01ef831b 100644 --- a/packages/extension-base/src/services/earning-service/handlers/liquid-staking/bifrost-manta.ts +++ b/packages/extension-base/src/services/earning-service/handlers/liquid-staking/bifrost-manta.ts @@ -4,6 +4,7 @@ import { ChainType, ExtrinsicType } from '@subwallet/extension-base/background/KoniTypes'; import KoniState from '@subwallet/extension-base/koni/background/handlers/State'; import { _getAssetDecimals, _getTokenOnChainInfo } from '@subwallet/extension-base/services/chain-service/utils'; +import { CHANNEL_ID } from '@subwallet/extension-base/services/earning-service/constants'; import { BaseYieldStepDetail, HandleYieldStepData, LiquidYieldPoolInfo, OptimalYieldPath, SubmitYieldJoinData, TransactionData, YieldStepType } from '@subwallet/extension-base/types'; import BifrostLiquidStakingPoolHandler from './bifrost'; @@ -143,7 +144,7 @@ export default class BifrostMantaLiquidStakingPoolHandler extends BifrostLiquidS const substrateApi = await this.substrateApi.isReady; const inputTokenSlug = this.inputAsset; const inputTokenInfo = this.state.getAssetBySlug(inputTokenSlug); - const extrinsic = substrateApi.api.tx.vtokenMinting.mint(_getTokenOnChainInfo(inputTokenInfo), data.amount, undefined, undefined); + const extrinsic = substrateApi.api.tx.vtokenMinting.mint(_getTokenOnChainInfo(inputTokenInfo), data.amount, undefined, CHANNEL_ID); return { txChain: this.chain, diff --git a/packages/extension-base/src/services/earning-service/handlers/liquid-staking/bifrost.ts b/packages/extension-base/src/services/earning-service/handlers/liquid-staking/bifrost.ts index 02387d8fdd..94ea547781 100644 --- a/packages/extension-base/src/services/earning-service/handlers/liquid-staking/bifrost.ts +++ b/packages/extension-base/src/services/earning-service/handlers/liquid-staking/bifrost.ts @@ -5,7 +5,7 @@ import { ChainType, ExtrinsicType } from '@subwallet/extension-base/background/K import KoniState from '@subwallet/extension-base/koni/background/handlers/State'; import { _STAKING_ERA_LENGTH_MAP } from '@subwallet/extension-base/services/chain-service/constants'; import { _getAssetDecimals, _getTokenOnChainInfo } from '@subwallet/extension-base/services/chain-service/utils'; -import { fakeAddress } from '@subwallet/extension-base/services/earning-service/constants'; +import { CHANNEL_ID, fakeAddress } from '@subwallet/extension-base/services/earning-service/constants'; import { BaseYieldStepDetail, EarningStatus, HandleYieldStepData, LiquidYieldPoolInfo, LiquidYieldPositionInfo, OptimalYieldPath, OptimalYieldPathParams, RuntimeDispatchInfo, SubmitYieldJoinData, TokenBalanceRaw, TransactionData, UnstakingInfo, UnstakingStatus, YieldPoolMethodInfo, YieldPositionInfo, YieldStepType, YieldTokenBaseInfo } from '@subwallet/extension-base/types'; import { reformatAddress } from '@subwallet/extension-base/utils'; import BigNumber from 'bignumber.js'; @@ -337,7 +337,7 @@ export default class BifrostLiquidStakingPoolHandler extends BaseLiquidStakingPo const defaultFeeTokenSlug = this.feeAssets[0]; if (new BN(params.amount).gt(BN_ZERO)) { - const _mintFeeInfo = await poolOriginSubstrateApi.api.tx.vtokenMinting.mint(_getTokenOnChainInfo(inputTokenInfo), params.amount, undefined, undefined).paymentInfo(fakeAddress); + const _mintFeeInfo = await poolOriginSubstrateApi.api.tx.vtokenMinting.mint(_getTokenOnChainInfo(inputTokenInfo), params.amount, undefined, CHANNEL_ID).paymentInfo(fakeAddress); const mintFeeInfo = _mintFeeInfo.toPrimitive() as unknown as RuntimeDispatchInfo; return { @@ -356,7 +356,7 @@ export default class BifrostLiquidStakingPoolHandler extends BaseLiquidStakingPo const substrateApi = await this.substrateApi.isReady; const inputTokenSlug = this.inputAsset; const inputTokenInfo = this.state.getAssetBySlug(inputTokenSlug); - const extrinsic = substrateApi.api.tx.vtokenMinting.mint(_getTokenOnChainInfo(inputTokenInfo), data.amount, undefined, undefined); + const extrinsic = substrateApi.api.tx.vtokenMinting.mint(_getTokenOnChainInfo(inputTokenInfo), data.amount, undefined, CHANNEL_ID); return { txChain: this.chain, diff --git a/packages/extension-base/src/services/inapp-notification-service/index.ts b/packages/extension-base/src/services/inapp-notification-service/index.ts index cbe795c37e..dc8095d503 100644 --- a/packages/extension-base/src/services/inapp-notification-service/index.ts +++ b/packages/extension-base/src/services/inapp-notification-service/index.ts @@ -329,12 +329,13 @@ export class InappNotificationService implements CronServiceInterface { const symbol = token.symbol; const decimals = token.decimals ?? 0; const notifications: _BaseNotificationInfo[] = transactions.map((transaction) => { - const { _id, amounts, counter, destinationNetwork, originTokenAddress, originTokenNetwork, receiver, sourceNetwork, status, transactionHash, transactionInitiator, userAddress } = transaction; + const { _id, amounts, bridgeType, counter, destinationNetwork, originTokenAddress, originTokenNetwork, receiver, sourceNetwork, status, transactionHash, transactionInitiator, userAddress } = transaction; const metadata: ClaimPolygonBridgeNotificationMetadata = { chainSlug: token.originChain, tokenSlug: token.slug, _id, amounts, + bridgeType, counter, destinationNetwork, originTokenAddress, diff --git a/packages/extension-base/src/services/inapp-notification-service/interfaces.ts b/packages/extension-base/src/services/inapp-notification-service/interfaces.ts index e6fcc52389..c022cc91fd 100644 --- a/packages/extension-base/src/services/inapp-notification-service/interfaces.ts +++ b/packages/extension-base/src/services/inapp-notification-service/interfaces.ts @@ -70,15 +70,16 @@ export interface ClaimPolygonBridgeNotificationMetadata { tokenSlug: string; _id: string; amounts: string[]; - counter: number; + bridgeType: string; + counter?: number; destinationNetwork: number; - originTokenAddress: string; - originTokenNetwork: number; - receiver: string; - sourceNetwork: number; + originTokenAddress?: string; + originTokenNetwork?: number; + receiver?: string; + sourceNetwork?: number; status: BridgeTransactionStatus; transactionHash: string; - transactionInitiator: string; + transactionInitiator?: string; userAddress: string; } diff --git a/packages/extension-base/src/services/inapp-notification-service/utils/polygon.ts b/packages/extension-base/src/services/inapp-notification-service/utils/polygon.ts index 5bdc1476db..d904789d65 100644 --- a/packages/extension-base/src/services/inapp-notification-service/utils/polygon.ts +++ b/packages/extension-base/src/services/inapp-notification-service/utils/polygon.ts @@ -11,7 +11,7 @@ export const POLYGON_BRIDGE_INDEXER = { export interface PolygonTransaction { _id: string; transactionIndex?: number; - sourceNetwork: number; + sourceNetwork?: number; destinationNetwork: number; blockNumber: number; amounts: string[]; @@ -25,16 +25,16 @@ export interface PolygonTransaction { userAddress: string; wrappedTokenAddress?: string; wrappedTokenNetwork?: number; - counter: number; + counter?: number; bridgeContractAddress?: string; eventInitiatorAddress?: string; globalExitRootManager?: string; leaf?: string; mainnetExitRoot?: string; metadata?: string; - originTokenAddress: string; - originTokenNetwork: number; - receiver: string; // empty when not claimed + originTokenAddress?: string; + originTokenNetwork?: number; + receiver?: string; // empty when not claimed refuel: boolean; rollUpExitRoot?: string; nonce?: any; @@ -43,7 +43,7 @@ export interface PolygonTransaction { claimTransactionBlockNumber?: number; claimTransactionHash?: string; claimTransactionTimestamp?: string; - transactionInitiator: string; + transactionInitiator?: string; } interface PaginationData { @@ -87,7 +87,7 @@ export async function fetchPolygonBridgeTransactions (userAddress: string, isTes page: page.toString() }); - const networkIds = [0, 1]; + const networkIds = [0, 1, -1]; networkIds.forEach((networkId) => { params.append('destinationNetworkIds', networkId.toString()); diff --git a/packages/extension-base/src/services/keyring-service/context/handlers/Ledger.ts b/packages/extension-base/src/services/keyring-service/context/handlers/Ledger.ts index 439a0efd8a..f06654aca1 100644 --- a/packages/extension-base/src/services/keyring-service/context/handlers/Ledger.ts +++ b/packages/extension-base/src/services/keyring-service/context/handlers/Ledger.ts @@ -86,7 +86,7 @@ export class AccountLedgerHandler extends AccountBaseHandler { const pairs: KeyringPair[] = []; for (const account of accounts) { - const { accountIndex, address, addressOffset, genesisHash, hardwareType, isEthereum, isGeneric, name, originGenesisHash } = account; + const { accountIndex, address, addressOffset, genesisHash, hardwareType, isEthereum, isGeneric, isLedgerRecovery, name, originGenesisHash } = account; const baseMeta: KeyringPair$Meta = { name, @@ -95,7 +95,8 @@ export class AccountLedgerHandler extends AccountBaseHandler { addressOffset, genesisHash, originGenesisHash, - isGeneric + isGeneric, + isLedgerRecovery }; const type = isEthereum ? 'ethereum' : 'sr25519'; diff --git a/packages/extension-base/src/services/migration-service/scripts/index.ts b/packages/extension-base/src/services/migration-service/scripts/index.ts index 03be614d84..301b328477 100644 --- a/packages/extension-base/src/services/migration-service/scripts/index.ts +++ b/packages/extension-base/src/services/migration-service/scripts/index.ts @@ -62,9 +62,9 @@ export default >{ '1.2.28-02': MigrateTransactionHistoryBySymbol, '1.2.69-01': MigrateRemoveGenesisHash, '1.2.13-01': ReloadMetadata, - '1.2.14-01': ClearMetadataDatabase, '1.2.32-01': MigratePairData, - '1.3.6-01': MigrateTransactionHistoryBridge + '1.3.6-01': MigrateTransactionHistoryBridge, + '1.3.10-01': ClearMetadataDatabase // [`${EVERYTIME}-1.1.42-02`]: MigrateTransactionHistoryBySymbol // [`${EVERYTIME}-1`]: AutoEnableChainsTokens }; diff --git a/packages/extension-base/src/services/storage-service/DatabaseService.ts b/packages/extension-base/src/services/storage-service/DatabaseService.ts index b0db514b1f..a91949bf05 100644 --- a/packages/extension-base/src/services/storage-service/DatabaseService.ts +++ b/packages/extension-base/src/services/storage-service/DatabaseService.ts @@ -6,7 +6,7 @@ import { APIItemState, ChainStakingMetadata, CrowdloanItem, MantaPayConfig, NftC import { EventService } from '@subwallet/extension-base/services/event-service'; import { _NotificationInfo } from '@subwallet/extension-base/services/inapp-notification-service/interfaces'; import KoniDatabase, { IBalance, ICampaign, IChain, ICrowdloanItem, INft } from '@subwallet/extension-base/services/storage-service/databases'; -import { AssetStore, BalanceStore, ChainStore, CrowdloanStore, MetadataStore, MigrationStore, NftCollectionStore, NftStore, PriceStore, StakingStore, TransactionStore } from '@subwallet/extension-base/services/storage-service/db-stores'; +import { AssetStore, BalanceStore, ChainStore, CrowdloanStore, MetadataStore, MetadataV15Store, MigrationStore, NftCollectionStore, NftStore, PriceStore, StakingStore, TransactionStore } from '@subwallet/extension-base/services/storage-service/db-stores'; import BaseStore from '@subwallet/extension-base/services/storage-service/db-stores/BaseStore'; import CampaignStore from '@subwallet/extension-base/services/storage-service/db-stores/Campaign'; import ChainStakingMetadataStore from '@subwallet/extension-base/services/storage-service/db-stores/ChainStakingMetadata'; @@ -55,6 +55,8 @@ export default class DatabaseService { migration: new MigrationStore(this._db.migrations), metadata: new MetadataStore(this._db.metadata), + metadataV15: new MetadataV15Store(this._db.metadataV15), + chain: new ChainStore(this._db.chain), asset: new AssetStore(this._db.asset), diff --git a/packages/extension-base/src/services/storage-service/databases/index.ts b/packages/extension-base/src/services/storage-service/databases/index.ts index 1cda2f9af1..0b21de49fc 100644 --- a/packages/extension-base/src/services/storage-service/databases/index.ts +++ b/packages/extension-base/src/services/storage-service/databases/index.ts @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 import { _AssetRef, _ChainAsset, _ChainInfo } from '@subwallet/chain-list/types'; -import { CampaignData, ChainStakingMetadata, CrowdloanItem, MetadataItem, NftCollection, NftItem, NominatorMetadata, PriceJson, StakingItem, TransactionHistoryItem } from '@subwallet/extension-base/background/KoniTypes'; +import { CampaignData, ChainStakingMetadata, CrowdloanItem, MetadataItem, MetadataV15Item, NftCollection, NftItem, NominatorMetadata, PriceJson, StakingItem, TransactionHistoryItem } from '@subwallet/extension-base/background/KoniTypes'; import { _NotificationInfo } from '@subwallet/extension-base/services/inapp-notification-service/interfaces'; import { BalanceItem, YieldPoolInfo, YieldPositionInfo } from '@subwallet/extension-base/types'; import Dexie, { Table, Transaction } from 'dexie'; @@ -41,6 +41,7 @@ export interface IMigration { } export interface IMetadataItem extends MetadataItem, DefaultChainDoc {} +export interface IMetadataV15Item extends MetadataV15Item, DefaultChainDoc {} export type IMantaPayLedger = any; @@ -62,6 +63,8 @@ export default class KoniDatabase extends Dexie { public migrations!: Table; public metadata!: Table; + public metadataV15!: Table; + public chain!: Table; public asset!: Table<_ChainAsset, object>; @@ -126,6 +129,10 @@ export default class KoniDatabase extends Dexie { this.conditionalVersion(7, { inappNotification: 'id, address, proxyId, [proxyId+actionType], actionType' }); + + this.conditionalVersion(8, { + metadataV15: 'genesisHash, chain' + }); } private conditionalVersion ( diff --git a/packages/extension-base/src/services/storage-service/db-stores/MetadataV15.ts b/packages/extension-base/src/services/storage-service/db-stores/MetadataV15.ts new file mode 100644 index 0000000000..a985c2927e --- /dev/null +++ b/packages/extension-base/src/services/storage-service/db-stores/MetadataV15.ts @@ -0,0 +1,24 @@ +// Copyright 2019-2022 @subwallet/extension-base authors & contributors +// SPDX-License-Identifier: Apache-2.0 + +import BaseStoreWithChain from '@subwallet/extension-base/services/storage-service/db-stores/BaseStoreWithChain'; + +import { IMetadataV15Item } from '../databases'; + +export default class MetadataV15Store extends BaseStoreWithChain { + getMetadata (chain: string) { + return this.table.where('chain').equals(chain).first(); + } + + upsertMetadata (chain: string, metadata: IMetadataV15Item) { + return this.table.put(metadata, chain); + } + + getMetadataByGenesisHash (genesisHash: string) { + return this.table.get(genesisHash); + } + + updateMetadataByGenesisHash (genesisHash: string, metadata: IMetadataV15Item) { + return this.table.put(metadata, genesisHash); + } +} diff --git a/packages/extension-base/src/services/storage-service/db-stores/index.ts b/packages/extension-base/src/services/storage-service/db-stores/index.ts index f26e20b498..d3e465eaaf 100644 --- a/packages/extension-base/src/services/storage-service/db-stores/index.ts +++ b/packages/extension-base/src/services/storage-service/db-stores/index.ts @@ -11,5 +11,7 @@ export { default as TransactionStore } from './Transaction'; export { default as MigrationStore } from './Migration'; export { default as MetadataStore } from './Metadata'; +export { default as MetadataV15Store } from './MetadataV15'; + export { default as ChainStore } from './Chain'; export { default as AssetStore } from './Asset'; diff --git a/packages/extension-base/src/services/transaction-service/utils.ts b/packages/extension-base/src/services/transaction-service/utils.ts index 87247d9c02..a491b3a664 100644 --- a/packages/extension-base/src/services/transaction-service/utils.ts +++ b/packages/extension-base/src/services/transaction-service/utils.ts @@ -43,6 +43,10 @@ function getBlockExplorerAccountRoute (explorerLink: string) { return '#/accounts'; } + if (explorerLink.includes('laos.statescan.io')) { + return '#/accounts'; + } + if (explorerLink.includes('explorer.zkverify.io')) { return 'account'; } diff --git a/packages/extension-base/src/types/account/info/keyring.ts b/packages/extension-base/src/types/account/info/keyring.ts index ca66298e62..5891a41ca9 100644 --- a/packages/extension-base/src/types/account/info/keyring.ts +++ b/packages/extension-base/src/types/account/info/keyring.ts @@ -59,6 +59,8 @@ export interface AccountLedgerData { originGenesisHash?: string | null; /** Ledger's availableGenesisHashes */ availableGenesisHashes?: string[]; + /** Is Ledger recovery chain */ + isLedgerRecovery?: boolean; } /** diff --git a/packages/extension-base/src/utils/metadata.ts b/packages/extension-base/src/utils/metadata.ts index 41c6c47c2d..05e5555936 100644 --- a/packages/extension-base/src/utils/metadata.ts +++ b/packages/extension-base/src/utils/metadata.ts @@ -4,11 +4,27 @@ import { ChainService } from '@subwallet/extension-base/services/chain-service'; import { _SubstrateApi } from '@subwallet/extension-base/services/chain-service/types'; +import { ApiPromise } from '@polkadot/api'; +import { TypeRegistry } from '@polkadot/types'; import { getSpecExtensions, getSpecTypes } from '@polkadot/types-known'; -import { u8aToHex } from '@polkadot/util'; +import { formatBalance, isNumber, u8aToHex } from '@polkadot/util'; import { HexString } from '@polkadot/util/types'; +import { defaults as addressDefaults } from '@polkadot/util-crypto/address/defaults'; import { ExtraInfo, merkleizeMetadata } from '@polkadot-api/merkleize-metadata'; +interface Statics { + api: ApiPromise; + registry: TypeRegistry; +} + +export const statics = { + api: undefined, + registry: new TypeRegistry() +} as unknown as Statics; + +export const DEFAULT_DECIMALS = statics.registry.createType('u32', 12); +export const DEFAULT_SS58 = statics.registry.createType('u32', addressDefaults.prefix); + export const _isRuntimeUpdated = (signedExtensions?: string[]): boolean => { return signedExtensions ? signedExtensions.includes('CheckMetadataHash') : false; }; @@ -25,43 +41,86 @@ export const getShortMetadata = (blob: HexString, extraInfo: ExtraInfo, metadata return u8aToHex(_merkleizeMetadata.getProofForExtrinsicPayload(blob)); }; -export const cacheMetadata = ( - chain: string, - substrateApi: _SubstrateApi, - chainService?: ChainService -): void => { - // Update metadata to database with async methods - substrateApi.api.isReady.then(async (api) => { +const updateMetadataV15 = async (chain: string, api: ApiPromise, chainService?: ChainService): Promise => { + try { const currentSpecVersion = api.runtimeVersion.specVersion.toString(); - const specName = api.runtimeVersion.specName.toString(); const genesisHash = api.genesisHash.toHex(); - const metadata = await chainService?.getMetadata(chain); + const metadata = await chainService?.getMetadataV15(chain); // Avoid date existed metadata if (metadata && metadata.specVersion === currentSpecVersion && metadata.genesisHash === genesisHash) { return; } - const systemChain = await api.rpc.system.chain(); - // const _metadata: Option = await api.call.metadata.metadataAtVersion(15); - // const metadataHex = _metadata.isSome ? _metadata.unwrap().toHex().slice(2) : ''; // Need unwrap to create metadata object - let hexV15: HexString | undefined; + if (api.call.metadata.metadataAtVersion) { + const metadataV15 = await api.call.metadata.metadataAtVersion(15); - const metadataV15 = await api.call.metadata.metadataAtVersion(15); + if (!metadataV15.isEmpty) { + const hexV15 = metadataV15.unwrap().toHex(); + const updateMetadata = { + chain: chain, + genesisHash: genesisHash, + specVersion: currentSpecVersion, + hexV15 + }; - if (!metadataV15.isEmpty) { - hexV15 = metadataV15.unwrap().toHex(); + chainService?.upsertMetadataV15(chain, { ...updateMetadata }).catch(console.error); + } } + } catch (err) { + console.error('Error:', err); + } +}; + +const updateMetadata = async ( + chain: string, + api: ApiPromise, + chainService?: ChainService +) => { + const currentSpecVersion = api.runtimeVersion.specVersion.toString(); + const genesisHash = api.genesisHash.toHex(); + const specName = api.runtimeVersion.specName.toString(); + const metadata = await chainService?.getMetadata(chain); - chainService?.upsertMetadata(chain, { - chain: chain, - genesisHash: genesisHash, - specName: specName, - specVersion: currentSpecVersion, - hexValue: api.runtimeMetadata.toHex(), - types: getSpecTypes(api.registry, systemChain, api.runtimeVersion.specName, api.runtimeVersion.specVersion) as unknown as Record, - userExtensions: getSpecExtensions(api.registry, systemChain, api.runtimeVersion.specName), - hexV15 - }).catch(console.error); + // Avoid date existed metadata + if (metadata && metadata.specVersion === currentSpecVersion && metadata.genesisHash === genesisHash) { + return; + } + + const systemChain = api.runtimeChain; + const metadataHex = api.runtimeMetadata.toHex(); + const registry = api.registry; + + const tokenInfo = { + ss58Format: isNumber(registry.chainSS58) + ? registry.chainSS58 + : DEFAULT_SS58.toNumber(), + tokenDecimals: (registry.chainDecimals || [DEFAULT_DECIMALS.toNumber()])[0], + tokenSymbol: (registry.chainTokens || formatBalance.getDefaults().unit)[0] + }; + + const updateMetadata = { + chain: chain, + genesisHash: genesisHash, + specName: specName, + specVersion: currentSpecVersion, + hexValue: metadataHex, + types: getSpecTypes(api.registry, systemChain, api.runtimeVersion.specName, api.runtimeVersion.specVersion) as unknown as Record, + userExtensions: getSpecExtensions(api.registry, systemChain, api.runtimeVersion.specName), + tokenInfo + }; + + chainService?.upsertMetadata(chain, { ...updateMetadata }).catch(console.error); +}; + +export const cacheMetadata = ( + chain: string, + substrateApi: _SubstrateApi, + chainService?: ChainService +): void => { + // Update metadata to database with async methods + substrateApi.api.isReady.then((api) => { + updateMetadata(chain, api, chainService).catch(console.error); + updateMetadataV15(chain, api, chainService).catch(console.error); }).catch(console.error); }; diff --git a/packages/extension-base/src/utils/number.ts b/packages/extension-base/src/utils/number.ts index c442672412..9d95cb670e 100644 --- a/packages/extension-base/src/utils/number.ts +++ b/packages/extension-base/src/utils/number.ts @@ -234,6 +234,12 @@ export const PREDEFINED_FORMATTER: Record = { balance: balanceFormatter }; +export const toBNString = (input: string | number | BigNumber, decimal: number): string => { + const raw = new BigNumber(input); + + return raw.multipliedBy(BN_TEN.pow(decimal)).toFixed(); +}; + /** @function formatNumber * Convert number to a formatted string by dividing by 10^decimal * @param {string | number | BigNumber} input - Input number diff --git a/packages/extension-chains/package.json b/packages/extension-chains/package.json index cc6cec588f..0c6224b08e 100644 --- a/packages/extension-chains/package.json +++ b/packages/extension-chains/package.json @@ -17,14 +17,14 @@ "./detectPackage.cjs" ], "type": "module", - "version": "1.3.11-0", + "version": "1.3.12-1", "main": "index.js", "dependencies": { "@babel/runtime": "^7.20.6", "@polkadot/networks": "^12.6.2", "@polkadot/util": "^12.6.2", "@polkadot/util-crypto": "^12.6.2", - "@subwallet/extension-inject": "^1.3.11-0" + "@subwallet/extension-inject": "^1.3.12-1" }, "peerDependencies": { "@polkadot/api": "*", diff --git a/packages/extension-chains/src/packageInfo.ts b/packages/extension-chains/src/packageInfo.ts index 993a03b29b..5a51e9a997 100644 --- a/packages/extension-chains/src/packageInfo.ts +++ b/packages/extension-chains/src/packageInfo.ts @@ -3,4 +3,4 @@ // Do not edit, auto-generated by @polkadot/dev -export const packageInfo = { name: '@subwallet/extension-chains', path: 'auto', type: 'auto', version: '1.3.11-0' }; +export const packageInfo = { name: '@subwallet/extension-chains', path: 'auto', type: 'auto', version: '1.3.12-1' }; diff --git a/packages/extension-compat-metamask/package.json b/packages/extension-compat-metamask/package.json index 6325b6ef36..660d7f804a 100644 --- a/packages/extension-compat-metamask/package.json +++ b/packages/extension-compat-metamask/package.json @@ -17,14 +17,14 @@ "./detectPackage.cjs" ], "type": "module", - "version": "1.3.11-0", + "version": "1.3.12-1", "main": "index.js", "dependencies": { "@babel/runtime": "^7.20.6", "@metamask/detect-provider": "^1.2.0", "@polkadot/types": "^11.0.3", "@polkadot/util": "^12.6.2", - "@subwallet/extension-inject": "^1.3.11-0", + "@subwallet/extension-inject": "^1.3.12-1", "web3": "^1.10.0" }, "peerDependencies": { diff --git a/packages/extension-compat-metamask/src/packageInfo.ts b/packages/extension-compat-metamask/src/packageInfo.ts index 391d715c4e..96c478bcb5 100644 --- a/packages/extension-compat-metamask/src/packageInfo.ts +++ b/packages/extension-compat-metamask/src/packageInfo.ts @@ -3,4 +3,4 @@ // Do not edit, auto-generated by @polkadot/dev -export const packageInfo = { name: '@subwallet/extension-compat-metamask', path: 'auto', type: 'auto', version: '1.3.11-0' }; +export const packageInfo = { name: '@subwallet/extension-compat-metamask', path: 'auto', type: 'auto', version: '1.3.12-1' }; diff --git a/packages/extension-dapp/package.json b/packages/extension-dapp/package.json index 6c3d74eb27..0eb58b3796 100644 --- a/packages/extension-dapp/package.json +++ b/packages/extension-dapp/package.json @@ -17,13 +17,13 @@ "./detectPackage.cjs" ], "type": "module", - "version": "1.3.11-0", + "version": "1.3.12-1", "main": "index.js", "dependencies": { "@babel/runtime": "^7.20.6", "@polkadot/util": "^12.6.2", "@polkadot/util-crypto": "^12.6.2", - "@subwallet/extension-inject": "^1.3.11-0" + "@subwallet/extension-inject": "^1.3.12-1" }, "peerDependencies": { "@polkadot/api": "*", diff --git a/packages/extension-dapp/src/packageInfo.ts b/packages/extension-dapp/src/packageInfo.ts index ee400c85f0..6563e21530 100644 --- a/packages/extension-dapp/src/packageInfo.ts +++ b/packages/extension-dapp/src/packageInfo.ts @@ -3,4 +3,4 @@ // Do not edit, auto-generated by @polkadot/dev -export const packageInfo = { name: '@subwallet/extension-dapp', path: 'auto', type: 'auto', version: '1.3.11-0' }; +export const packageInfo = { name: '@subwallet/extension-dapp', path: 'auto', type: 'auto', version: '1.3.12-1' }; diff --git a/packages/extension-inject/package.json b/packages/extension-inject/package.json index 71f2cc1a78..b1d656da0d 100644 --- a/packages/extension-inject/package.json +++ b/packages/extension-inject/package.json @@ -14,7 +14,7 @@ }, "sideEffects": true, "type": "module", - "version": "1.3.11-0", + "version": "1.3.12-1", "main": "index.js", "dependencies": { "@babel/runtime": "^7.20.6", diff --git a/packages/extension-inject/src/packageInfo.ts b/packages/extension-inject/src/packageInfo.ts index 7a95154859..5ef8bd69af 100644 --- a/packages/extension-inject/src/packageInfo.ts +++ b/packages/extension-inject/src/packageInfo.ts @@ -3,4 +3,4 @@ // Do not edit, auto-generated by @polkadot/dev -export const packageInfo = { name: '@subwallet/extension-inject', path: 'auto', type: 'auto', version: '1.3.11-0' }; +export const packageInfo = { name: '@subwallet/extension-inject', path: 'auto', type: 'auto', version: '1.3.12-1' }; diff --git a/packages/extension-koni-ui/package.json b/packages/extension-koni-ui/package.json index 923a5f5a75..2530fe88cf 100644 --- a/packages/extension-koni-ui/package.json +++ b/packages/extension-koni-ui/package.json @@ -14,7 +14,7 @@ }, "sideEffects": true, "type": "module", - "version": "1.3.11-0", + "version": "1.3.12-1", "dependencies": { "@babel/runtime": "^7.20.6", "@coinbase/cbpay-js": "^1.7.0", @@ -34,11 +34,11 @@ "@polkadot/util-crypto": "^12.6.2", "@ramonak/react-progress-bar": "^5.0.3", "@reduxjs/toolkit": "^1.9.1", - "@subwallet/chain-list": "0.2.96", - "@subwallet/extension-base": "^1.3.11-0", - "@subwallet/extension-chains": "^1.3.11-0", - "@subwallet/extension-dapp": "^1.3.11-0", - "@subwallet/extension-inject": "^1.3.11-0", + "@subwallet/chain-list": "0.2.97", + "@subwallet/extension-base": "^1.3.12-1", + "@subwallet/extension-chains": "^1.3.12-1", + "@subwallet/extension-dapp": "^1.3.12-1", + "@subwallet/extension-inject": "^1.3.12-1", "@subwallet/keyring": "^0.1.8-beta.0", "@subwallet/react-ui": "5.1.2-b77", "@subwallet/ui-keyring": "^0.1.8-beta.0", @@ -87,7 +87,7 @@ "usehooks-ts": "^2.9.1" }, "devDependencies": { - "@subwallet/extension-mocks": "^1.3.11-0", + "@subwallet/extension-mocks": "^1.3.12-1", "@types/bn.js": "^5.1.6", "@types/enzyme": "^3.10.12", "@types/enzyme-adapter-react-16": "^1.0.6", diff --git a/packages/extension-koni-ui/src/Popup/Account/ConnectLedger.tsx b/packages/extension-koni-ui/src/Popup/Account/ConnectLedger.tsx index c303b72158..f2e0588060 100644 --- a/packages/extension-koni-ui/src/Popup/Account/ConnectLedger.tsx +++ b/packages/extension-koni-ui/src/Popup/Account/ConnectLedger.tsx @@ -4,11 +4,13 @@ import { LedgerNetwork, MigrationLedgerNetwork } from '@subwallet/extension-base/background/KoniTypes'; import { reformatAddress } from '@subwallet/extension-base/utils'; import { AccountItemWithName, AccountWithNameSkeleton, BasicOnChangeFunction, ChainSelector, DualLogo, InfoIcon, Layout, PageWrapper } from '@subwallet/extension-koni-ui/components'; +import { LedgerChainSelector, LedgerItemType } from '@subwallet/extension-koni-ui/components/Field/LedgerChainSelector'; import { ATTACH_ACCOUNT_MODAL, SUBSTRATE_MIGRATION_KEY, USER_GUIDE_URL } from '@subwallet/extension-koni-ui/constants'; import { useAutoNavigateToCreatePassword, useCompleteCreateAccount, useGetSupportedLedger, useGoBackFromCreateAccount, useLedger } from '@subwallet/extension-koni-ui/hooks'; import { createAccountHardwareMultiple } from '@subwallet/extension-koni-ui/messaging'; import { RootState } from '@subwallet/extension-koni-ui/stores'; import { ChainItemType, ThemeProps } from '@subwallet/extension-koni-ui/types'; +import { convertNetworkSlug } from '@subwallet/extension-koni-ui/utils'; import { BackgroundIcon, Button, Icon, Image, SwList } from '@subwallet/react-ui'; import CN from 'classnames'; import { CheckCircle, CircleNotch, Swatches } from 'phosphor-react'; @@ -54,11 +56,14 @@ const Component: React.FC = (props: Props) => { const { accounts } = useSelector((state: RootState) => state.accountState); - const networks = useMemo((): ChainItemType[] => supportedLedger + const networks = useMemo((): LedgerItemType[] => supportedLedger .filter(({ isHide }) => !isHide) .map((network) => ({ - name: !network.isGeneric ? network.networkName.replace(' network', '') : network.networkName, - slug: network.slug + name: !network.isGeneric + ? network.networkName.replace(' network', '').concat(network.isRecovery ? ' Recovery' : '') + : network.networkName, + chain: network.slug, + slug: convertNetworkSlug(network) })), [supportedLedger]); const networkMigrates = useMemo((): ChainItemType[] => migrateSupportLedger @@ -78,7 +83,7 @@ const Component: React.FC = (props: Props) => { const [isSubmitting, setIsSubmitting] = useState(false); const selectedChain = useMemo((): LedgerNetwork | undefined => { - return supportedLedger.find((n) => n.slug === chain); + return supportedLedger.find((n) => convertNetworkSlug(n) === chain); }, [chain, supportedLedger]); const selectedChainMigrateMode = useMemo((): MigrationLedgerNetwork | undefined => { @@ -93,7 +98,7 @@ const Component: React.FC = (props: Props) => { return chainMigrateMode && selectedChain ? `${selectedChain.accountName}` : ''; }, [chainMigrateMode, migrateSupportLedger]); - const { error, getAllAddress, isLoading, isLocked, ledger, refresh, warning } = useLedger(chain, true, false, false, selectedChainMigrateMode?.genesisHash); + const { error, getAllAddress, isLoading, isLocked, ledger, refresh, warning } = useLedger(selectedChain?.slug, true, false, false, selectedChainMigrateMode?.genesisHash, selectedChain?.isRecovery); const onPreviousStep = useCallback(() => { setFirstStep(true); @@ -248,7 +253,8 @@ const Component: React.FC = (props: Props) => { hardwareType: 'ledger', name: item.name, isEthereum: selectedChain.isEthereum, - isGeneric: selectedChain.isGeneric + isGeneric: selectedChain.isGeneric, + isLedgerRecovery: selectedChain?.isRecovery })) }) .then(() => { @@ -326,7 +332,7 @@ const Component: React.FC = (props: Props) => { sizeSquircleBorder={108} /> - = (props: Props) => { refresh: refreshLedger, signMessage: ledgerSignMessage, signTransaction: ledgerSignTransaction, - warning: ledgerWarning } = useLedger(chainSlug, activeLedger, true, forceUseMigrationApp, account?.originGenesisHash); + warning: ledgerWarning } = useLedger(chainSlug, activeLedger, true, forceUseMigrationApp, account?.originGenesisHash, account?.isLedgerRecovery); const isLedgerConnected = useMemo(() => !isLocked && !isLedgerLoading && !!ledger, [isLedgerLoading, isLocked, ledger]); diff --git a/packages/extension-koni-ui/src/Popup/Settings/Notifications/Notification.tsx b/packages/extension-koni-ui/src/Popup/Settings/Notifications/Notification.tsx index ca2b8d198e..4c66477246 100644 --- a/packages/extension-koni-ui/src/Popup/Settings/Notifications/Notification.tsx +++ b/packages/extension-koni-ui/src/Popup/Settings/Notifications/Notification.tsx @@ -1,9 +1,11 @@ // Copyright 2019-2022 @polkadot/extension-ui authors & contributors // SPDX-License-Identifier: Apache-2.0 +import { COMMON_CHAIN_SLUGS } from '@subwallet/chain-list'; import { NotificationType } from '@subwallet/extension-base/background/KoniTypes'; import { ALL_ACCOUNT_KEY } from '@subwallet/extension-base/constants'; import { _POLYGON_BRIDGE_ABI } from '@subwallet/extension-base/koni/api/contract-handler/utils'; +import { isClaimedPosBridge } from '@subwallet/extension-base/services/balance-service/transfer/xcm/posBridge'; import { _NotificationInfo, BridgeTransactionStatus, ClaimAvailBridgeNotificationMetadata, ClaimPolygonBridgeNotificationMetadata, NotificationActionType, NotificationSetup, NotificationTab, WithdrawClaimNotificationMetadata } from '@subwallet/extension-base/services/inapp-notification-service/interfaces'; import { GetNotificationParams, RequestSwitchStatusParams } from '@subwallet/extension-base/types/notification'; import { detectTranslate } from '@subwallet/extension-base/utils'; @@ -346,7 +348,15 @@ function Component ({ className = '' }: Props): React.ReactElement { const handleClaimPolygonBridge = async () => { try { const metadata = item.metadata as ClaimPolygonBridgeNotificationMetadata; - const isClaimed = await getIsClaimNotificationStatus({ chainslug: metadata.chainSlug, counter: metadata.counter, sourceNetwork: metadata.sourceNetwork }); + let isClaimed = false; + + if (metadata.bridgeType === 'POS') { + const isTestnet = metadata.chainSlug === COMMON_CHAIN_SLUGS.ETHEREUM_SEPOLIA; + + isClaimed = await isClaimedPosBridge(metadata._id, metadata.userAddress, isTestnet) || false; + } else { + isClaimed = await getIsClaimNotificationStatus({ chainslug: metadata.chainSlug, counter: metadata.counter ?? 0, sourceNetwork: metadata.sourceNetwork ?? 0 }); + } if (!isClaimed) { setClaimAvailBridgeStorage({ diff --git a/packages/extension-koni-ui/src/Popup/Transaction/variants/SendFund.tsx b/packages/extension-koni-ui/src/Popup/Transaction/variants/SendFund.tsx index 68928481df..4d6e3c8525 100644 --- a/packages/extension-koni-ui/src/Popup/Transaction/variants/SendFund.tsx +++ b/packages/extension-koni-ui/src/Popup/Transaction/variants/SendFund.tsx @@ -10,10 +10,11 @@ import { ActionType } from '@subwallet/extension-base/core/types'; import { getAvailBridgeGatewayContract, getSnowBridgeGatewayContract } from '@subwallet/extension-base/koni/api/contract-handler/utils'; import { isAvailChainBridge } from '@subwallet/extension-base/services/balance-service/transfer/xcm/availBridge'; import { _isPolygonChainBridge } from '@subwallet/extension-base/services/balance-service/transfer/xcm/polygonBridge'; +import { _isPosChainBridge, _isPosChainL2Bridge } from '@subwallet/extension-base/services/balance-service/transfer/xcm/posBridge'; import { _getAssetDecimals, _getAssetName, _getAssetOriginChain, _getAssetSymbol, _getContractAddressOfToken, _getMultiChainAsset, _getOriginChainOfAsset, _getTokenMinAmount, _isChainEvmCompatible, _isNativeToken, _isTokenTransferredByEvm } from '@subwallet/extension-base/services/chain-service/utils'; import { TON_CHAINS } from '@subwallet/extension-base/services/earning-service/constants'; import { SWTransactionResponse } from '@subwallet/extension-base/services/transaction-service/types'; -import { AccountChainType, AccountProxy, AccountProxyType, AccountSignMode, BasicTxWarningCode } from '@subwallet/extension-base/types'; +import { AccountChainType, AccountProxy, AccountProxyType, AccountSignMode, AnalyzedGroup, BasicTxWarningCode } from '@subwallet/extension-base/types'; import { CommonStepType } from '@subwallet/extension-base/types/service-base'; import { _reformatAddressWithChain, detectTranslate, isAccountAll } from '@subwallet/extension-base/utils'; import { AccountAddressSelector, AddressInputNew, AddressInputRef, AlertBox, AlertModal, AmountInput, ChainSelector, HiddenInput, TokenItemType, TokenSelector } from '@subwallet/extension-koni-ui/components'; @@ -172,13 +173,21 @@ const Component = ({ className = '', isAllAccount, targetAccountProxy }: Compone const hideMaxButton = useMemo(() => { const chainInfo = chainInfoMap[chainValue]; - if (_isPolygonChainBridge(chainValue, destChainValue)) { + if (_isPolygonChainBridge(chainValue, destChainValue) || _isPosChainBridge(chainValue, destChainValue)) { return true; } return !!chainInfo && !!assetInfo && _isChainEvmCompatible(chainInfo) && destChainValue === chainValue && _isNativeToken(assetInfo); }, [chainInfoMap, chainValue, destChainValue, assetInfo]); + const disabledToAddressInput = useMemo(() => { + if (_isPosChainL2Bridge(chainValue, destChainValue)) { + return true; + } + + return false; + }, [chainValue, destChainValue]); + const [loading, setLoading] = useState(false); const [isTransferAll, setIsTransferAll] = useState(false); @@ -289,10 +298,11 @@ const Component = ({ className = '', isAllAccount, targetAccountProxy }: Compone const isNotShowAccountSelector = !isAllAccount && accountAddressItems.length < 2; const addressInputRef = useRef(null); + const addressInputCurrent = addressInputRef.current; const updateAddressInputValue = useCallback((value: string) => { - addressInputRef.current?.setInputValue(value); - addressInputRef.current?.setSelectedOption((prev) => { + addressInputCurrent?.setInputValue(value); + addressInputCurrent?.setSelectedOption((prev) => { if (!prev) { return prev; } @@ -302,7 +312,7 @@ const Component = ({ className = '', isAllAccount, targetAccountProxy }: Compone formatedAddress: value }; }); - }, []); + }, [addressInputCurrent]); const validateRecipient = useCallback((rule: Rule, _recipientAddress: string): Promise => { const { chain, destChain, from } = form.getFieldsValue(); @@ -395,7 +405,7 @@ const Component = ({ className = '', isAllAccount, targetAccountProxy }: Compone persistData(form.getFieldsValue()); }, - [form, assetRegistry, isTransferAll, persistData] + [persistData, form, assetRegistry, isTransferAll] ); const isShowWarningOnSubmit = useCallback((values: TransferParams): boolean => { @@ -738,7 +748,7 @@ const Component = ({ className = '', isAllAccount, targetAccountProxy }: Compone }; updateFromValue(); - }, [accountAddressItems, form, fromValue]); + }, [accountAddressItems, disabledToAddressInput, form, fromValue]); // Get max transfer value useEffect(() => { @@ -813,6 +823,23 @@ const Component = ({ className = '', isAllAccount, targetAccountProxy }: Compone }); }, [assetValue, chainValue, destChainValue, fromValue, transferAmountValue]); + useEffect(() => { + if (disabledToAddressInput) { + const selectedItem = accountAddressItems.find((i) => i.address === fromValue); + const chainInfo = chainInfoMap[chainValue]; + const reformatedInputValue = _reformatAddressWithChain(fromValue, chainInfo); + + addressInputCurrent?.setInputValue?.(selectedItem?.address); + addressInputCurrent?.setSelectedOption?.({ + address: selectedItem?.address || '', + formatedAddress: reformatedInputValue, + analyzedGroup: AnalyzedGroup.RECENT, + displayName: selectedItem?.accountName + }); + form.setFieldValue('to', fromValue); + } + }, [accountAddressItems, addressInputCurrent, chainInfoMap, chainValue, disabledToAddressInput, form, fromValue]); + useRestoreTransaction(form); return ( @@ -882,6 +909,7 @@ const Component = ({ className = '', isAllAccount, targetAccountProxy }: Compone > ): React.Rea }, [autoFormatValue, chainInfo, inputValue, isShowAdvancedAddressDetection, onBlur, parseAndChangeValue, selectedOption]); // autoComplete - // "item: unknown" is hotfix for typescript error of AutoComplete const onSelectAutoComplete = useCallback((graftedValue: string, item: unknown) => { setInputValue(getInputValueFromGraftedValue(graftedValue)); @@ -402,6 +401,7 @@ function Component (props: Props, ref: ForwardedRef): React.Rea <>
): React.Rea showAddressBook && (
+ + ); + } + + return ( + + + )} + /> + ); + }, [messageTooltip, t, token.colorSuccess]); + + return ( + ('Network name')} + selected={value || ''} + statusHelp={statusHelp} + title={title || label || placeholder || t('Select network')} + tooltip={tooltip} + /> + ); +} + +export const LedgerChainSelector = styled(forwardRef(Component))(({ theme: { token } }: Props) => { + return ({ + '&.ant-select-modal-input-container .ant-select-modal-input-wrapper': { + paddingLeft: 12, + paddingRight: 12 + }, + + '&.chain-selector-input': { + '.__selected-item, .__loading-text': { + whiteSpace: 'nowrap', + overflow: 'hidden', + textOverflow: 'ellipsis' + }, + + '.__selected-item': { + color: token.colorText, + fontWeight: 500, + lineHeight: token.lineHeightHeading6 + }, + + '.__loading-text': { + color: token.colorTextLight4 + } + }, + + '.chain-logo': { + margin: '-1px 0' + }, + + '.ant-network-item .__check-icon': { + display: 'flex', + width: 40, + justifyContent: 'center' + }, + + '.ant-network-item.disabled': { + opacity: token.opacityDisable, + '.ant-network-item-content': { + cursor: 'not-allowed', + + '&:hover': { + backgroundColor: token.colorBgSecondary + } + } + } + }); +}); diff --git a/packages/extension-koni-ui/src/constants/ledger.ts b/packages/extension-koni-ui/src/constants/ledger.ts index 4a1d3635d3..61dd559cab 100644 --- a/packages/extension-koni-ui/src/constants/ledger.ts +++ b/packages/extension-koni-ui/src/constants/ledger.ts @@ -8,6 +8,7 @@ export const SUBSTRATE_GENERIC_KEY = 'substrate_generic'; export const SUBSTRATE_MIGRATION_KEY = 'substrate_migration'; export const POLKADOT_KEY = 'polkadot'; export const POLKADOT_SLIP_44 = 354; +export const RECOVERY_SLUG = '_recovery'; export const PredefinedLedgerNetwork: LedgerNetwork[] = [ { @@ -116,8 +117,23 @@ export const PredefinedLedgerNetwork: LedgerNetwork[] = [ isDevMode: false, isGeneric: false, isEthereum: false, + isRecovery: false, slip44: 709 }, + { + accountName: 'Avail Recovery', + appName: 'Avail Recovery', + networkName: 'Avail network', + genesisHash: ChainInfoMap.avail_mainnet.substrateInfo?.genesisHash || '0xb91746b45e0346cc2f815a520b9c6cb4d5c0902af848db0a80f85932d2e8276a', + icon: 'substrate', + network: 'availRecovery', + slug: ChainInfoMap.avail_mainnet.slug, + isDevMode: false, + isGeneric: false, + isEthereum: false, + isRecovery: true, + slip44: 354 + }, { accountName: 'Acala', appName: 'Acala', diff --git a/packages/extension-koni-ui/src/hooks/ledger/useLedger.ts b/packages/extension-koni-ui/src/hooks/ledger/useLedger.ts index 1158f9cff4..7cca4c9ffb 100644 --- a/packages/extension-koni-ui/src/hooks/ledger/useLedger.ts +++ b/packages/extension-koni-ui/src/hooks/ledger/useLedger.ts @@ -42,7 +42,11 @@ const baseState: StateBase = { // && uiSettings.ledgerConn !== 'none' }; -const getNetwork = (ledgerChains: LedgerNetwork[], slug: string, isEthereumNetwork: boolean): LedgerNetwork | undefined => { +const getNetwork = (ledgerChains: LedgerNetwork[], slug: string, isEthereumNetwork: boolean, isRecovery?: boolean): LedgerNetwork | undefined => { + if (isRecovery) { + return ledgerChains.find((network) => network.slug === slug && network.isRecovery); + } + return ledgerChains.find((network) => network.slug === slug || (network.isEthereum && isEthereumNetwork)); }; @@ -50,12 +54,12 @@ const getNetworkByGenesisHash = (ledgerChains: MigrationLedgerNetwork[], genesis return ledgerChains.find((network) => network.genesisHash === genesisHash); }; -const retrieveLedger = (chainSlug: string, ledgerChains: LedgerNetwork[], migrateLedgerChains: MigrationLedgerNetwork[], isEthereumNetwork: boolean, forceMigration: boolean, originGenesisHash?: string | null): Ledger => { +const retrieveLedger = (chainSlug: string, ledgerChains: LedgerNetwork[], migrateLedgerChains: MigrationLedgerNetwork[], isEthereumNetwork: boolean, forceMigration: boolean, originGenesisHash?: string | null, isRecovery?: boolean): Ledger => { const { isLedgerCapable } = baseState; assert(isLedgerCapable, ledgerIncompatible); - const def = getNetwork(ledgerChains, chainSlug, isEthereumNetwork); + const def = getNetwork(ledgerChains, chainSlug, isEthereumNetwork, isRecovery); assert(def, 'There is no known Ledger app available for this chain'); @@ -86,7 +90,7 @@ const retrieveLedger = (chainSlug: string, ledgerChains: LedgerNetwork[], migrat } }; -export function useLedger (chainSlug?: string, active = true, isSigning = false, forceMigration = false, originGenesisHash?: string | null): Result { +export function useLedger (chainSlug?: string, active = true, isSigning = false, forceMigration = false, originGenesisHash?: string | null, isRecovery?: boolean): Result { const { t } = useTranslation(); const [ledgerChains, migrateLedgerChains] = useGetSupportedLedger(); @@ -133,14 +137,14 @@ export function useLedger (chainSlug?: string, active = true, isSigning = false, } try { - return retrieveLedger(chainSlug, ledgerChains, migrateLedgerChains, isEvmNetwork, forceMigration, originGenesisHash); + return retrieveLedger(chainSlug, ledgerChains, migrateLedgerChains, isEvmNetwork, forceMigration, originGenesisHash, isRecovery); } catch (error) { setError((error as Error).message); } } return null; - }, [refreshLock, chainSlug, active, ledgerChains, migrateLedgerChains, isEvmNetwork, forceMigration, originGenesisHash]); + }, [refreshLock, chainSlug, active, ledgerChains, migrateLedgerChains, isEvmNetwork, forceMigration, originGenesisHash, isRecovery]); const appName = useMemo(() => { const unknownNetwork = 'unknown network'; @@ -151,7 +155,7 @@ export function useLedger (chainSlug?: string, active = true, isSigning = false, const chainInfo = chainInfoMap[chainSlug]; const isEthereumNetwork = chainInfo ? _isChainEvmCompatible(chainInfo) : false; - const { appName, isEthereum, isGeneric } = getNetwork(ledgerChains, chainSlug, isEthereumNetwork) || { appName: 'Polkadot Migration', isGeneric: true }; + const { appName, isEthereum, isGeneric } = getNetwork(ledgerChains, chainSlug, isEthereumNetwork, isRecovery) || { appName: 'Polkadot Migration', isGeneric: true }; if (!isGeneric && forceMigration && !isEthereum) { if (NotNeedMigrationGens.includes(chainInfo?.substrateInfo?.genesisHash || '')) { @@ -162,7 +166,7 @@ export function useLedger (chainSlug?: string, active = true, isSigning = false, } return appName; - }, [chainInfoMap, forceMigration, ledgerChains, chainSlug]); + }, [chainInfoMap, forceMigration, ledgerChains, chainSlug, isRecovery]); const refresh = useCallback(() => { setRefreshLock(true); diff --git a/packages/extension-koni-ui/src/utils/account/ledger.ts b/packages/extension-koni-ui/src/utils/account/ledger.ts index 9a44b3c6e6..8f7e6c00ed 100644 --- a/packages/extension-koni-ui/src/utils/account/ledger.ts +++ b/packages/extension-koni-ui/src/utils/account/ledger.ts @@ -5,7 +5,7 @@ import { _ChainInfo } from '@subwallet/chain-list/types'; import { LedgerNetwork } from '@subwallet/extension-base/background/KoniTypes'; import { _ChainState } from '@subwallet/extension-base/services/chain-service/types'; import { _isChainEvmCompatible } from '@subwallet/extension-base/services/chain-service/utils'; -import { PredefinedLedgerNetwork } from '@subwallet/extension-koni-ui/constants/ledger'; +import { PredefinedLedgerNetwork, RECOVERY_SLUG } from '@subwallet/extension-koni-ui/constants/ledger'; interface ChainItem extends _ChainState { isEthereum: boolean; @@ -25,3 +25,5 @@ export const getSupportedLedger = (networkInfoMap: Record, n return networkInfoItems.find((item) => ledgerNetwork.slug === item.slug || (ledgerNetwork.isEthereum && item.isEthereum)); }); }; + +export const convertNetworkSlug = (network: LedgerNetwork) => network.slug.concat(network.isRecovery ? RECOVERY_SLUG : ''); diff --git a/packages/extension-koni-ui/src/utils/connector/Ledger/index.ts b/packages/extension-koni-ui/src/utils/connector/Ledger/index.ts index a88dc0a337..b1b8d7e188 100644 --- a/packages/extension-koni-ui/src/utils/connector/Ledger/index.ts +++ b/packages/extension-koni-ui/src/utils/connector/Ledger/index.ts @@ -47,7 +47,7 @@ export const convertLedgerError = (err: Error, t: TFunction, network: string, is } if (message.includes('Data is invalid')) { - if (isGetAddress) { + if (!isGetAddress) { return { status: 'error', message: t('Unable to sign. Open “{{network}}” on Ledger, refresh and approve again', { replace: { network: network } }) diff --git a/packages/extension-koni-ui/src/utils/earning.ts b/packages/extension-koni-ui/src/utils/earning.ts index 69f5bcb0cb..2caa0900f2 100644 --- a/packages/extension-koni-ui/src/utils/earning.ts +++ b/packages/extension-koni-ui/src/utils/earning.ts @@ -82,7 +82,7 @@ export function autoSelectValidatorOptimally (validators: ValidatorInfo[], maxCo if (result.length >= maxCount) { shuffle(result); - return result.slice(0, maxCount - 1); + return result.slice(0, maxCount); } shuffle(notPreSelected); diff --git a/packages/extension-koni/package.json b/packages/extension-koni/package.json index d848a28212..306ca4c0fc 100644 --- a/packages/extension-koni/package.json +++ b/packages/extension-koni/package.json @@ -14,12 +14,12 @@ }, "sideEffects": false, "type": "module", - "version": "1.3.11-0", + "version": "1.3.12-1", "dependencies": { "@babel/runtime": "^7.20.6", - "@subwallet/extension-base": "^1.3.11-0", - "@subwallet/extension-inject": "^1.3.11-0", - "@subwallet/extension-koni-ui": "^1.3.11-0" + "@subwallet/extension-base": "^1.3.12-1", + "@subwallet/extension-inject": "^1.3.12-1", + "@subwallet/extension-koni-ui": "^1.3.12-1" }, "devDependencies": { "@polkadot/dev": "^0.65.23", diff --git a/packages/extension-koni/src/packageInfo.ts b/packages/extension-koni/src/packageInfo.ts index 45c90905a4..52f945435e 100644 --- a/packages/extension-koni/src/packageInfo.ts +++ b/packages/extension-koni/src/packageInfo.ts @@ -3,4 +3,4 @@ // Do not edit, auto-generated by @polkadot/dev -export const packageInfo = { name: '@subwallet/extension-koni', path: 'auto', type: 'auto', version: '1.3.11-0' }; +export const packageInfo = { name: '@subwallet/extension-koni', path: 'auto', type: 'auto', version: '1.3.12-1' }; diff --git a/packages/extension-mocks/package.json b/packages/extension-mocks/package.json index da787ac014..8e928ac961 100644 --- a/packages/extension-mocks/package.json +++ b/packages/extension-mocks/package.json @@ -14,7 +14,7 @@ }, "sideEffects": false, "type": "module", - "version": "1.3.11-0", + "version": "1.3.12-1", "main": "index.js", "dependencies": { "@babel/runtime": "^7.20.6", diff --git a/packages/extension-web-ui/package.json b/packages/extension-web-ui/package.json index d090aff69d..9d2c8114ca 100644 --- a/packages/extension-web-ui/package.json +++ b/packages/extension-web-ui/package.json @@ -14,7 +14,7 @@ }, "sideEffects": true, "type": "module", - "version": "1.3.11-0", + "version": "1.3.12-1", "dependencies": { "@babel/runtime": "^7.20.6", "@coinbase/cbpay-js": "^1.7.0", @@ -35,11 +35,11 @@ "@polkadot/util-crypto": "^12.6.2", "@ramonak/react-progress-bar": "^5.0.3", "@reduxjs/toolkit": "^1.9.1", - "@subwallet/chain-list": "0.2.96", - "@subwallet/extension-base": "^1.3.11-0", - "@subwallet/extension-chains": "^1.3.11-0", - "@subwallet/extension-dapp": "^1.3.11-0", - "@subwallet/extension-inject": "^1.3.11-0", + "@subwallet/chain-list": "0.2.97", + "@subwallet/extension-base": "^1.3.12-1", + "@subwallet/extension-chains": "^1.3.12-1", + "@subwallet/extension-dapp": "^1.3.12-1", + "@subwallet/extension-inject": "^1.3.12-1", "@subwallet/keyring": "^0.1.8-beta.0", "@subwallet/react-ui": "^5.1.2-b77", "@subwallet/ui-keyring": "^0.1.8-beta.0", @@ -88,7 +88,7 @@ "usehooks-ts": "^2.9.1" }, "devDependencies": { - "@subwallet/extension-mocks": "^1.3.11-0", + "@subwallet/extension-mocks": "^1.3.12-1", "@types/bn.js": "^5.1.6", "@types/enzyme": "^3.10.12", "@types/enzyme-adapter-react-16": "^1.0.6", diff --git a/packages/extension-web-ui/src/components/Field/Earning/EarningValidatorSelector.tsx b/packages/extension-web-ui/src/components/Field/Earning/EarningValidatorSelector.tsx index 5c8a68caa6..83e1fd1151 100644 --- a/packages/extension-web-ui/src/components/Field/Earning/EarningValidatorSelector.tsx +++ b/packages/extension-web-ui/src/components/Field/Earning/EarningValidatorSelector.tsx @@ -1,10 +1,11 @@ // Copyright 2019-2022 @subwallet/extension-web-ui authors & contributors // SPDX-License-Identifier: Apache-2.0 +import { ChainRecommendValidator } from '@subwallet/extension-base/constants'; import { getValidatorLabel } from '@subwallet/extension-base/koni/api/staking/bonding/utils'; import { _STAKING_CHAIN_GROUP } from '@subwallet/extension-base/services/earning-service/constants'; import { YieldPoolType } from '@subwallet/extension-base/types'; -import { detectTranslate } from '@subwallet/extension-base/utils'; +import { detectTranslate, fetchStaticData } from '@subwallet/extension-base/utils'; import { BaseModal, SelectValidatorInput, StakingValidatorItem } from '@subwallet/extension-web-ui/components'; import EmptyValidator from '@subwallet/extension-web-ui/components/Account/EmptyValidator'; import { BasicInputWrapper } from '@subwallet/extension-web-ui/components/Field/Base'; @@ -50,8 +51,6 @@ interface SortOption { const SORTING_MODAL_ID = 'nominated-sorting-modal'; const FILTER_MODAL_ID = 'nominated-filter-modal'; -const AVAIL_CHAIN = 'avail_mainnet'; -const AVAIL_VALIDATOR = '5FjdibsxmNFas5HWcT2i1AXbpfgiNfWqezzo88H2tskxWdt2'; const filterOptions = [ { @@ -104,6 +103,8 @@ const Component = (props: Props, ref: ForwardedRef) => { const isSingleSelect = useMemo(() => _isSingleSelect || !isRelayChain, [_isSingleSelect, isRelayChain]); const hasReturn = useMemo(() => items[0]?.expectedReturn !== undefined, [items]); + const [defaultPoolMap, setDefaultPoolMap] = useState>({}); + const maxPoolMembersValue = useMemo(() => { if (poolInfo.type === YieldPoolType.NATIVE_STAKING) { // todo: should also check chain group for pool return poolInfo.maxPoolMembers; @@ -314,12 +315,25 @@ const Component = (props: Props, ref: ForwardedRef) => { }, [activeModal, id]); useEffect(() => { - if (chain === AVAIL_CHAIN) { + fetchStaticData>('direct-nomination-validator').then((earningPoolRecommendation) => { + setDefaultPoolMap(earningPoolRecommendation); + }).catch(console.error); + }, []); + + useEffect(() => { + const recommendValidator = defaultPoolMap[chain]; + + if (recommendValidator) { setAutoValidator((old) => { if (old) { return old; } else { - const selectedValidator = autoSelectValidatorOptimally(items, 16, true, AVAIL_VALIDATOR); + const selectedValidator = autoSelectValidatorOptimally( + items, + recommendValidator.maxCount, + true, + recommendValidator.preSelectValidators + ); return selectedValidator.map((item) => getValidatorKey(item.address, item.identity)).join(','); } @@ -327,7 +341,7 @@ const Component = (props: Props, ref: ForwardedRef) => { } else { setAutoValidator(''); } - }, [items, chain]); + }, [items, chain, defaultPoolMap]); useEffect(() => { const _default = nominations?.map((item) => getValidatorKey(item.validatorAddress, item.validatorIdentity)).join(',') || autoValidator || ''; diff --git a/packages/web-runner/package.json b/packages/web-runner/package.json index 40a8c607c7..89abba8e24 100644 --- a/packages/web-runner/package.json +++ b/packages/web-runner/package.json @@ -14,12 +14,12 @@ }, "sideEffects": false, "type": "module", - "version": "1.3.11-0", + "version": "1.3.12-1", "dependencies": { "@babel/runtime": "^7.20.6", - "@subwallet/extension-base": "^1.3.11-0", - "@subwallet/extension-inject": "^1.3.11-0", - "@subwallet/extension-koni-ui": "^1.3.11-0" + "@subwallet/extension-base": "^1.3.12-1", + "@subwallet/extension-inject": "^1.3.12-1", + "@subwallet/extension-koni-ui": "^1.3.12-1" }, "devDependencies": { "@polkadot/dev": "^0.65.23", diff --git a/packages/webapp/package.json b/packages/webapp/package.json index c3b94df316..6fc33051d8 100644 --- a/packages/webapp/package.json +++ b/packages/webapp/package.json @@ -15,12 +15,12 @@ }, "sideEffects": false, "type": "module", - "version": "1.3.11-0", + "version": "1.3.12-1", "dependencies": { "@babel/runtime": "^7.20.6", - "@subwallet/extension-base": "^1.3.11-0", - "@subwallet/extension-inject": "^1.3.11-0", - "@subwallet/extension-web-ui": "^1.3.11-0" + "@subwallet/extension-base": "^1.3.12-1", + "@subwallet/extension-inject": "^1.3.12-1", + "@subwallet/extension-web-ui": "^1.3.12-1" }, "devDependencies": { "@polkadot/dev": "^0.65.23", diff --git a/patches/@polkadot+hw-ledger+12.6.2.patch b/patches/@polkadot+hw-ledger+12.6.2.patch index 9dbdf99e5c..6bd660f208 100644 --- a/patches/@polkadot+hw-ledger+12.6.2.patch +++ b/patches/@polkadot+hw-ledger+12.6.2.patch @@ -1,12 +1,13 @@ diff --git a/node_modules/@polkadot/hw-ledger/defaults.js b/node_modules/@polkadot/hw-ledger/defaults.js -index 9f06432..97efba8 100644 +index 9f06432..4daa29a 100644 --- a/node_modules/@polkadot/hw-ledger/defaults.js +++ b/node_modules/@polkadot/hw-ledger/defaults.js -@@ -37,5 +37,6 @@ export const ledgerApps = { +@@ -37,5 +37,7 @@ export const ledgerApps = { unique: 'Unique', vtb: 'VTB', xxnetwork: 'XXNetwork', - zeitgeist: 'Zeitgeist' + zeitgeist: 'Zeitgeist', -+ avail: 'Avail' ++ avail: 'Avail', ++ availRecovery: 'AvailRecovery', }; diff --git a/yarn.lock b/yarn.lock index 959639d302..39db93445c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6439,19 +6439,19 @@ __metadata: languageName: node linkType: hard -"@subwallet/chain-list@npm:0.2.96": - version: 0.2.96 - resolution: "@subwallet/chain-list@npm:0.2.96" +"@subwallet/chain-list@npm:0.2.97": + version: 0.2.97 + resolution: "@subwallet/chain-list@npm:0.2.97" dependencies: "@polkadot/dev": 0.67.167 "@polkadot/util": ^12.5.1 eventemitter3: ^5.0.1 ts-md5: ^1.3.1 - checksum: a7d9436d2e799f3ad0e976fea33ff2319a3a69fc45dda7915ebead94007c4de81069411bf30be27136ea6eb8a11aa77750e230c62747885d19d8f06cf2924f47 + checksum: 3271231e2c5b435dd2f4c502da5af8b547a5ac8aafe7089d09c9966fd74b233eb4077d04e0c960857d5b5e2fbd29f178f08aec473e6ec23d19bd07b6642af432 languageName: node linkType: hard -"@subwallet/extension-base@^1.3.11-0, @subwallet/extension-base@workspace:packages/extension-base": +"@subwallet/extension-base@^1.3.12-1, @subwallet/extension-base@workspace:packages/extension-base": version: 0.0.0-use.local resolution: "@subwallet/extension-base@workspace:packages/extension-base" dependencies: @@ -6490,12 +6490,12 @@ __metadata: "@reduxjs/toolkit": ^1.9.1 "@sora-substrate/type-definitions": ^1.17.7 "@substrate/connect": ^0.8.9 - "@subwallet/chain-list": 0.2.96 - "@subwallet/extension-base": ^1.3.11-0 - "@subwallet/extension-chains": ^1.3.11-0 - "@subwallet/extension-dapp": ^1.3.11-0 - "@subwallet/extension-inject": ^1.3.11-0 - "@subwallet/extension-mocks": ^1.3.11-0 + "@subwallet/chain-list": 0.2.97 + "@subwallet/extension-base": ^1.3.12-1 + "@subwallet/extension-chains": ^1.3.12-1 + "@subwallet/extension-dapp": ^1.3.12-1 + "@subwallet/extension-inject": ^1.3.12-1 + "@subwallet/extension-mocks": ^1.3.12-1 "@subwallet/keyring": ^0.1.8-beta.0 "@subwallet/ui-keyring": ^0.1.8-beta.0 "@ton/core": ^0.56.3 @@ -6543,7 +6543,7 @@ __metadata: languageName: unknown linkType: soft -"@subwallet/extension-chains@^1.3.11-0, @subwallet/extension-chains@workspace:packages/extension-chains": +"@subwallet/extension-chains@^1.3.12-1, @subwallet/extension-chains@workspace:packages/extension-chains": version: 0.0.0-use.local resolution: "@subwallet/extension-chains@workspace:packages/extension-chains" dependencies: @@ -6551,7 +6551,7 @@ __metadata: "@polkadot/networks": ^12.6.2 "@polkadot/util": ^12.6.2 "@polkadot/util-crypto": ^12.6.2 - "@subwallet/extension-inject": ^1.3.11-0 + "@subwallet/extension-inject": ^1.3.12-1 peerDependencies: "@polkadot/api": "*" "@polkadot/types": "*" @@ -6566,21 +6566,21 @@ __metadata: "@metamask/detect-provider": ^1.2.0 "@polkadot/types": ^11.0.3 "@polkadot/util": ^12.6.2 - "@subwallet/extension-inject": ^1.3.11-0 + "@subwallet/extension-inject": ^1.3.12-1 web3: ^1.10.0 peerDependencies: "@polkadot/util": "*" languageName: unknown linkType: soft -"@subwallet/extension-dapp@^1.3.11-0, @subwallet/extension-dapp@workspace:packages/extension-dapp": +"@subwallet/extension-dapp@^1.3.12-1, @subwallet/extension-dapp@workspace:packages/extension-dapp": version: 0.0.0-use.local resolution: "@subwallet/extension-dapp@workspace:packages/extension-dapp" dependencies: "@babel/runtime": ^7.20.6 "@polkadot/util": ^12.6.2 "@polkadot/util-crypto": ^12.6.2 - "@subwallet/extension-inject": ^1.3.11-0 + "@subwallet/extension-inject": ^1.3.12-1 peerDependencies: "@polkadot/api": "*" "@polkadot/util": "*" @@ -6588,7 +6588,7 @@ __metadata: languageName: unknown linkType: soft -"@subwallet/extension-inject@^1.3.11-0, @subwallet/extension-inject@workspace:packages/extension-inject": +"@subwallet/extension-inject@^1.3.12-1, @subwallet/extension-inject@workspace:packages/extension-inject": version: 0.0.0-use.local resolution: "@subwallet/extension-inject@workspace:packages/extension-inject" dependencies: @@ -6607,7 +6607,7 @@ __metadata: languageName: unknown linkType: soft -"@subwallet/extension-koni-ui@^1.3.11-0, @subwallet/extension-koni-ui@workspace:packages/extension-koni-ui": +"@subwallet/extension-koni-ui@^1.3.12-1, @subwallet/extension-koni-ui@workspace:packages/extension-koni-ui": version: 0.0.0-use.local resolution: "@subwallet/extension-koni-ui@workspace:packages/extension-koni-ui" dependencies: @@ -6629,12 +6629,12 @@ __metadata: "@polkadot/util-crypto": ^12.6.2 "@ramonak/react-progress-bar": ^5.0.3 "@reduxjs/toolkit": ^1.9.1 - "@subwallet/chain-list": 0.2.96 - "@subwallet/extension-base": ^1.3.11-0 - "@subwallet/extension-chains": ^1.3.11-0 - "@subwallet/extension-dapp": ^1.3.11-0 - "@subwallet/extension-inject": ^1.3.11-0 - "@subwallet/extension-mocks": ^1.3.11-0 + "@subwallet/chain-list": 0.2.97 + "@subwallet/extension-base": ^1.3.12-1 + "@subwallet/extension-chains": ^1.3.12-1 + "@subwallet/extension-dapp": ^1.3.12-1 + "@subwallet/extension-inject": ^1.3.12-1 + "@subwallet/extension-mocks": ^1.3.12-1 "@subwallet/keyring": ^0.1.8-beta.0 "@subwallet/react-ui": 5.1.2-b77 "@subwallet/ui-keyring": ^0.1.8-beta.0 @@ -6707,9 +6707,9 @@ __metadata: dependencies: "@babel/runtime": ^7.20.6 "@polkadot/dev": ^0.65.23 - "@subwallet/extension-base": ^1.3.11-0 - "@subwallet/extension-inject": ^1.3.11-0 - "@subwallet/extension-koni-ui": ^1.3.11-0 + "@subwallet/extension-base": ^1.3.12-1 + "@subwallet/extension-inject": ^1.3.12-1 + "@subwallet/extension-koni-ui": ^1.3.12-1 "@types/chrome": ^0.0.254 "@types/serviceworker": ^0.0.80 assert: ^2.0.0 @@ -6737,7 +6737,7 @@ __metadata: languageName: unknown linkType: soft -"@subwallet/extension-mocks@^1.3.11-0, @subwallet/extension-mocks@workspace:packages/extension-mocks": +"@subwallet/extension-mocks@^1.3.12-1, @subwallet/extension-mocks@workspace:packages/extension-mocks": version: 0.0.0-use.local resolution: "@subwallet/extension-mocks@workspace:packages/extension-mocks" dependencies: @@ -6746,7 +6746,7 @@ __metadata: languageName: unknown linkType: soft -"@subwallet/extension-web-ui@^1.3.11-0, @subwallet/extension-web-ui@workspace:packages/extension-web-ui": +"@subwallet/extension-web-ui@^1.3.12-1, @subwallet/extension-web-ui@workspace:packages/extension-web-ui": version: 0.0.0-use.local resolution: "@subwallet/extension-web-ui@workspace:packages/extension-web-ui" dependencies: @@ -6769,12 +6769,12 @@ __metadata: "@polkadot/util-crypto": ^12.6.2 "@ramonak/react-progress-bar": ^5.0.3 "@reduxjs/toolkit": ^1.9.1 - "@subwallet/chain-list": 0.2.96 - "@subwallet/extension-base": ^1.3.11-0 - "@subwallet/extension-chains": ^1.3.11-0 - "@subwallet/extension-dapp": ^1.3.11-0 - "@subwallet/extension-inject": ^1.3.11-0 - "@subwallet/extension-mocks": ^1.3.11-0 + "@subwallet/chain-list": 0.2.97 + "@subwallet/extension-base": ^1.3.12-1 + "@subwallet/extension-chains": ^1.3.12-1 + "@subwallet/extension-dapp": ^1.3.12-1 + "@subwallet/extension-inject": ^1.3.12-1 + "@subwallet/extension-mocks": ^1.3.12-1 "@subwallet/keyring": ^0.1.8-beta.0 "@subwallet/react-ui": ^5.1.2-b77 "@subwallet/ui-keyring": ^0.1.8-beta.0 @@ -6966,9 +6966,9 @@ __metadata: dependencies: "@babel/runtime": ^7.20.6 "@polkadot/dev": ^0.65.23 - "@subwallet/extension-base": ^1.3.11-0 - "@subwallet/extension-inject": ^1.3.11-0 - "@subwallet/extension-koni-ui": ^1.3.11-0 + "@subwallet/extension-base": ^1.3.12-1 + "@subwallet/extension-inject": ^1.3.12-1 + "@subwallet/extension-koni-ui": ^1.3.12-1 assert: ^2.0.0 babel-loader: ^9.1.3 browser-resolve: ^2.0.0 @@ -6999,9 +6999,9 @@ __metadata: dependencies: "@babel/runtime": ^7.20.6 "@polkadot/dev": ^0.65.23 - "@subwallet/extension-base": ^1.3.11-0 - "@subwallet/extension-inject": ^1.3.11-0 - "@subwallet/extension-web-ui": ^1.3.11-0 + "@subwallet/extension-base": ^1.3.12-1 + "@subwallet/extension-inject": ^1.3.12-1 + "@subwallet/extension-web-ui": ^1.3.12-1 assert: ^2.0.0 babel-loader: ^9.1.3 browser-resolve: ^2.0.0 @@ -9243,23 +9243,23 @@ __metadata: languageName: node linkType: hard -"@zondax/ledger-js@npm:^0.8.2": - version: 0.8.2 - resolution: "@zondax/ledger-js@npm:0.8.2" +"@zondax/ledger-js@npm:^0.11.0": + version: 0.11.0 + resolution: "@zondax/ledger-js@npm:0.11.0" dependencies: "@ledgerhq/hw-transport": 6.30.6 - checksum: 7b33cd87d8569732028a57e594a4674f9fa232155c227031a00985bf9b6af62774a5cdbed59a5754c998122862ded64060b042c97850a38e6b734455828b362d + checksum: 38743b887fceaeb13460d70a127cb385f5df034fe014f698d4f164f0d111add71dd01381c182ac71135c7fb43f38e7b21218d5df7d87d69ddaee17dd9c57d392 languageName: node linkType: hard -"@zondax/ledger-substrate@npm:0.44.2": - version: 0.44.2 - resolution: "@zondax/ledger-substrate@npm:0.44.2" +"@zondax/ledger-substrate@npm:1.0.1": + version: 1.0.1 + resolution: "@zondax/ledger-substrate@npm:1.0.1" dependencies: - "@ledgerhq/hw-transport": 6.30.6 - "@zondax/ledger-js": ^0.8.2 - axios: ^1.6.8 - checksum: 1f0035725c88335c8e1c234fc75ebdbc39666d8567bb3d77734ed861f85a49b87d358f520bef76287ff2e75914f790a5454cb27b7814489292100730023a9541 + "@ledgerhq/hw-transport": 6.31.2 + "@zondax/ledger-js": ^0.11.0 + axios: ^1.7.4 + checksum: e5fd0743bb6a5638c7a633131a0f4db84e9e8eec720fa659f6f116a8fe6629125b6d472184683c1a64a88fadf89bb54c6e3ffa4fa063470b4395df87d7be0bb0 languageName: node linkType: hard @@ -10133,14 +10133,14 @@ __metadata: languageName: node linkType: hard -"axios@npm:^1.6.8": - version: 1.6.8 - resolution: "axios@npm:1.6.8" +"axios@npm:^1.7.4": + version: 1.7.9 + resolution: "axios@npm:1.7.9" dependencies: follow-redirects: ^1.15.6 form-data: ^4.0.0 proxy-from-env: ^1.1.0 - checksum: bf007fa4b207d102459300698620b3b0873503c6d47bf5a8f6e43c0c64c90035a4f698b55027ca1958f61ab43723df2781c38a99711848d232cad7accbcdfcdd + checksum: cb8ce291818effda09240cb60f114d5625909b345e10f389a945320e06acf0bc949d0f8422d25720f5dd421362abee302c99f5e97edec4c156c8939814b23d19 languageName: node linkType: hard