From c1ed8c7f2ba057ad827f756e119018b5bbe233ab Mon Sep 17 00:00:00 2001 From: guanbinrui Date: Fri, 20 May 2022 19:59:08 +0800 Subject: [PATCH] refactor: hub state --- .i18n-codegen.json | 12 ++ .../background-script/BackupService.ts | 21 +- .../pages/Wallet/DeleteWallet/index.tsx | 4 +- .../Wallet/GasSetting/Prior1559GasSetting.tsx | 24 +-- .../pages/Wallet/Transfer/Transfer1559.tsx | 7 +- .../mask/src/plugins/Pets/hooks/useNfts.ts | 12 +- packages/mask/src/plugins/Pets/types.ts | 2 +- .../trader/GasPrior1559Settings.tsx | 31 +-- .../SNSAdaptor/trader/hooks/useGasConfig.ts | 19 +- .../plugins/Wallet/services/wallet/index.ts | 12 +- .../plugin-infra/src/web3-helpers/index.ts | 20 +- packages/plugin-infra/src/web3-state/Asset.ts | 52 ----- packages/plugin-infra/src/web3-state/Hub.ts | 39 ++++ .../plugin-infra/src/web3-state/Settings.ts | 14 +- .../plugin-infra/src/web3-state/TokenList.ts | 99 --------- packages/plugin-infra/src/web3-state/index.ts | 3 +- packages/plugin-infra/src/web3-types.ts | 14 +- packages/plugin-infra/src/web3/index.ts | 7 +- .../plugin-infra/src/web3/useFungibleAsset.ts | 23 ++ .../src/web3/useFungibleAssetSourceType.ts | 9 + .../src/web3/useFungibleAssets.ts | 11 +- .../src/web3/useFungibleTokenPrice.ts | 26 +-- .../web3/useFungibleTokensFromTokenList.ts | 27 +-- .../plugin-infra/src/web3/useGasOptions.ts | 16 +- .../src/web3/useNativeTokenPrice.ts | 23 +- .../src/web3/useNonFungibleAsset.ts | 26 +++ .../src/web3/useNonFungibleAssetSourceType.ts | 9 + .../src/web3/useNonFungibleAssets.ts | 10 +- .../src/web3/useNonFungibleTokenPrice.ts | 24 +-- .../web3/useNonFungibleTokensFromTokenList.ts | 27 ++- .../src/web3/useWeb3Connection.ts | 2 +- packages/plugin-infra/src/web3/useWeb3Hub.ts | 33 +++ packages/plugins/EVM/src/state/Asset.ts | 24 --- packages/plugins/EVM/src/state/GasOptions.ts | 18 -- packages/plugins/EVM/src/state/Hub.ts | 20 ++ .../TokenIconSpecialIconList.json | 0 packages/plugins/EVM/src/state/Hub/hub.ts | 182 ++++++++++++++++ packages/plugins/EVM/src/state/Hub/types.ts | 4 + .../state/Protocol/providers/MaskWallet.ts | 2 +- .../src/state/Protocol/translators/Base.ts | 5 +- packages/plugins/EVM/src/state/TokenIcon.ts | 28 --- packages/plugins/EVM/src/state/TokenList.ts | 43 ---- packages/plugins/EVM/src/state/TokenPrice.ts | 21 -- packages/plugins/EVM/src/state/index.ts | 24 +-- .../plugins/Flow/src/apis/fungibleAssets.ts | 4 +- packages/plugins/Flow/src/state/Asset.ts | 10 - packages/plugins/Flow/src/state/Hub.ts | 20 ++ packages/plugins/Flow/src/state/Hub/hub.ts | 171 +++++++++++++++ packages/plugins/Flow/src/state/Hub/types.ts | 4 + packages/plugins/Flow/src/state/TokenList.ts | 70 ------ packages/plugins/Flow/src/state/index.ts | 9 +- .../Solana/src/apis/getFungibleAssets.ts | 8 +- .../Solana/src/apis/getNonFungibleAssets.ts | 6 +- packages/plugins/Solana/src/state/Asset.ts | 14 -- packages/plugins/Solana/src/state/Hub.ts | 20 ++ packages/plugins/Solana/src/state/Hub/hub.ts | 143 +++++++++++++ .../plugins/Solana/src/state/Hub/types.ts | 4 + .../plugins/Solana/src/state/TokenList.ts | 33 --- packages/plugins/Solana/src/state/index.ts | 11 +- .../UI/components/FungibleTokenList/index.tsx | 3 +- .../src/UI/components/TokenIcon/index.tsx | 6 +- packages/web3-providers/src/NFTScan/index.ts | 4 +- packages/web3-providers/src/debank/index.ts | 6 +- packages/web3-providers/src/opensea/index.ts | 16 +- packages/web3-providers/src/rarible/index.ts | 10 +- .../web3-providers/src/token-list/index.ts | 2 +- packages/web3-providers/src/types.ts | 25 ++- packages/web3-providers/src/zerion/index.ts | 6 +- packages/web3-shared/base/src/specs/index.ts | 199 +++++++++++------- .../web3-shared/base/src/utils/resolver.ts | 2 +- packages/web3-shared/flow/types.ts | 1 - 71 files changed, 1098 insertions(+), 738 deletions(-) delete mode 100644 packages/plugin-infra/src/web3-state/Asset.ts create mode 100644 packages/plugin-infra/src/web3-state/Hub.ts delete mode 100644 packages/plugin-infra/src/web3-state/TokenList.ts create mode 100644 packages/plugin-infra/src/web3/useFungibleAsset.ts create mode 100644 packages/plugin-infra/src/web3/useFungibleAssetSourceType.ts create mode 100644 packages/plugin-infra/src/web3/useNonFungibleAsset.ts create mode 100644 packages/plugin-infra/src/web3/useNonFungibleAssetSourceType.ts create mode 100644 packages/plugin-infra/src/web3/useWeb3Hub.ts delete mode 100644 packages/plugins/EVM/src/state/Asset.ts delete mode 100644 packages/plugins/EVM/src/state/GasOptions.ts create mode 100644 packages/plugins/EVM/src/state/Hub.ts rename packages/plugins/EVM/src/state/{TokenIcon => Hub}/TokenIconSpecialIconList.json (100%) create mode 100644 packages/plugins/EVM/src/state/Hub/hub.ts create mode 100644 packages/plugins/EVM/src/state/Hub/types.ts delete mode 100644 packages/plugins/EVM/src/state/TokenIcon.ts delete mode 100644 packages/plugins/EVM/src/state/TokenList.ts delete mode 100644 packages/plugins/EVM/src/state/TokenPrice.ts delete mode 100644 packages/plugins/Flow/src/state/Asset.ts create mode 100644 packages/plugins/Flow/src/state/Hub.ts create mode 100644 packages/plugins/Flow/src/state/Hub/hub.ts create mode 100644 packages/plugins/Flow/src/state/Hub/types.ts delete mode 100644 packages/plugins/Flow/src/state/TokenList.ts delete mode 100644 packages/plugins/Solana/src/state/Asset.ts create mode 100644 packages/plugins/Solana/src/state/Hub.ts create mode 100644 packages/plugins/Solana/src/state/Hub/hub.ts create mode 100644 packages/plugins/Solana/src/state/Hub/types.ts delete mode 100644 packages/plugins/Solana/src/state/TokenList.ts diff --git a/.i18n-codegen.json b/.i18n-codegen.json index cfac4329fdbc..1cede9eab34e 100644 --- a/.i18n-codegen.json +++ b/.i18n-codegen.json @@ -122,6 +122,18 @@ "sourceMap": "inline" } }, + { + "input": "./packages/plugins/DAO/src/locales/en-US.json", + "output": "./packages/plugins/DAO/src/locales/i18n_generated", + "parser": { "type": "i18next", "contextSeparator": "$", "pluralSeparator": "_" }, + "generator": { + "type": "i18next/react-hooks", + "hooks": "useI18N", + "namespace": "money.juicebox", + "trans": "Translate", + "sourceMap": "inline" + } + }, { "input": "./packages/plugins/CyberConnect/src/locales/en-US.json", "output": "./packages/plugins/CyberConnect/src/locales/i18n_generated", diff --git a/packages/mask/src/extension/background-script/BackupService.ts b/packages/mask/src/extension/background-script/BackupService.ts index 41c0e7b61c58..f37fe9e67de7 100644 --- a/packages/mask/src/extension/background-script/BackupService.ts +++ b/packages/mask/src/extension/background-script/BackupService.ts @@ -3,7 +3,6 @@ export * from '../../../background/services/backup' import { assertEnvironment, Environment } from '@dimensiondev/holoflows-kit' assertEnvironment(Environment.ManifestBackground) -import { ProviderType } from '@masknet/web3-shared-evm' import { exportMnemonic, exportPrivateKey, @@ -97,14 +96,16 @@ delegateWalletRestore(async function (backup) { async function backupAllWallets(): Promise { const allSettled = await Promise.allSettled( ( - await getWallets(ProviderType.MaskWallet) - ).map(async (wallet) => { - return { - ...wallet, - mnemonic: wallet.derivationPath ? await exportMnemonic(wallet.address) : undefined, - privateKey: wallet.derivationPath ? undefined : await exportPrivateKey(wallet.address), - } - }), + await getWallets() + ) + .filter((x) => x.storedKeyInfo) + .map(async (wallet) => { + return { + ...wallet, + mnemonic: wallet.derivationPath ? await exportMnemonic(wallet.address) : undefined, + privateKey: wallet.derivationPath ? undefined : await exportPrivateKey(wallet.address), + } + }), ) const wallets_ = allSettled.map((x) => (x.status === 'fulfilled' ? WalletRecordToJSONFormat(x.value) : null)) if (wallets_.some((x) => !x)) throw new Error('Failed to backup wallets.') @@ -112,7 +113,7 @@ async function backupAllWallets(): Promise { } async function backupAllLegacyWallets(): Promise { - const x = await getLegacyWallets(ProviderType.MaskWallet) + const x = await getLegacyWallets() return x.map(LegacyWalletRecordToJSONFormat) } diff --git a/packages/mask/src/extension/popups/pages/Wallet/DeleteWallet/index.tsx b/packages/mask/src/extension/popups/pages/Wallet/DeleteWallet/index.tsx index 850c649683d7..4b66d6b5793a 100644 --- a/packages/mask/src/extension/popups/pages/Wallet/DeleteWallet/index.tsx +++ b/packages/mask/src/extension/popups/pages/Wallet/DeleteWallet/index.tsx @@ -3,7 +3,7 @@ import { Button, Typography } from '@mui/material' import { makeStyles } from '@masknet/theme' import { WalletIcon, WarningIcon } from '@masknet/icons' import { useNavigate } from 'react-router-dom' -import { ProviderType, formatEthereumAddress } from '@masknet/web3-shared-evm' +import { formatEthereumAddress } from '@masknet/web3-shared-evm' import { PopupRoutes } from '@masknet/shared-base' import { first } from 'lodash-unified' import { FormattedAddress } from '@masknet/shared' @@ -111,7 +111,7 @@ const DeleteWallet = memo(() => { if (wallet?.address) { try { await WalletRPC.removeWallet(wallet.address, password) - const wallets = await WalletRPC.getWallets(ProviderType.MaskWallet) + const wallets = await WalletRPC.getWallets() const otherWalletAddress = first(wallets)?.address diff --git a/packages/mask/src/extension/popups/pages/Wallet/GasSetting/Prior1559GasSetting.tsx b/packages/mask/src/extension/popups/pages/Wallet/GasSetting/Prior1559GasSetting.tsx index 6512664eb1cd..ff5f4bb7a794 100644 --- a/packages/mask/src/extension/popups/pages/Wallet/GasSetting/Prior1559GasSetting.tsx +++ b/packages/mask/src/extension/popups/pages/Wallet/GasSetting/Prior1559GasSetting.tsx @@ -1,5 +1,5 @@ import { makeStyles } from '@masknet/theme' -import { isLessThan, NetworkPluginID, pow10, TransactionDescriptorType } from '@masknet/web3-shared-base' +import { GasOptionType, isLessThan, NetworkPluginID, pow10, TransactionDescriptorType } from '@masknet/web3-shared-base' import { memo, useEffect, useMemo, useState } from 'react' import { useI18N } from '../../../../../utils' import { useAsync, useAsyncFn, useUpdateEffect } from 'react-use' @@ -23,7 +23,7 @@ import { isEmpty } from 'lodash-unified' import { useNavigate } from 'react-router-dom' import { PopupRoutes } from '@masknet/shared-base' import { toHex } from 'web3-utils' -import { useChainId, useNativeToken, useNativeTokenPrice, useWeb3, useWeb3State } from '@masknet/plugin-infra/web3' +import { useChainId, useGasOptions, useNativeToken, useNativeTokenPrice, useWeb3 } from '@masknet/plugin-infra/web3' const useStyles = makeStyles()((theme) => ({ options: { @@ -99,7 +99,7 @@ export const Prior1559GasSetting = memo(() => { const { t } = useI18N() const { classes } = useStyles() const web3 = useWeb3(NetworkPluginID.PLUGIN_EVM) - const { GasOptions } = useWeb3State(NetworkPluginID.PLUGIN_EVM) + const { value: gasOptions_ } = useGasOptions(NetworkPluginID.PLUGIN_EVM) const chainId = useChainId(NetworkPluginID.PLUGIN_EVM) const { value, loading: getValueLoading } = useUnconfirmedRequest() const [getGasLimitError, setGetGasLimitError] = useState(false) @@ -111,15 +111,13 @@ export const Prior1559GasSetting = memo(() => { }) // #region Get gas options from debank - const { value: gasOptions } = useAsync(async () => { - const gasOptions = await GasOptions?.getGasOptions?.(chainId) - if (!gasOptions) return null + const gasOptions = useMemo(() => { return { - slow: gasOptions.slow.suggestedMaxFeePerGas, - standard: gasOptions.normal.suggestedMaxFeePerGas, - fast: gasOptions.fast.suggestedMaxFeePerGas, + slow: gasOptions_?.[GasOptionType.SLOW].suggestedMaxFeePerGas ?? 0, + standard: gasOptions_?.[GasOptionType.NORMAL].suggestedMaxFeePerGas ?? 0, + fast: gasOptions_?.[GasOptionType.FAST].suggestedMaxFeePerGas ?? 0, } - }, [chainId]) + }, [chainId, gasOptions_]) // #endregion const options = useMemo( @@ -128,15 +126,15 @@ export const Prior1559GasSetting = memo(() => { ? [ { title: t('popups_wallet_gas_fee_settings_low'), - gasPrice: gasOptions?.slow ?? 0, + gasPrice: gasOptions.slow, }, { title: t('popups_wallet_gas_fee_settings_medium'), - gasPrice: gasOptions?.standard ?? 0, + gasPrice: gasOptions.standard, }, { title: t('popups_wallet_gas_fee_settings_high'), - gasPrice: gasOptions?.fast ?? 0, + gasPrice: gasOptions.fast, }, ] : null, diff --git a/packages/mask/src/extension/popups/pages/Wallet/Transfer/Transfer1559.tsx b/packages/mask/src/extension/popups/pages/Wallet/Transfer/Transfer1559.tsx index 8b2fc2079bda..47b218dc7bd1 100644 --- a/packages/mask/src/extension/popups/pages/Wallet/Transfer/Transfer1559.tsx +++ b/packages/mask/src/extension/popups/pages/Wallet/Transfer/Transfer1559.tsx @@ -50,6 +50,7 @@ import { useWallet, useWeb3State, useWeb3Connection, + useGasOptions, } from '@masknet/plugin-infra/web3' import { AccountItem } from './AccountItem' import { TransferAddressError } from '../type' @@ -194,7 +195,7 @@ export const Transfer1559 = memo(({ selectedAsset, openAssetM const chainId = useChainId(NetworkPluginID.PLUGIN_EVM) const network = useNetworkType(NetworkPluginID.PLUGIN_EVM) const connection = useWeb3Connection(NetworkPluginID.PLUGIN_EVM) - const { Others, GasOptions } = useWeb3State(NetworkPluginID.PLUGIN_EVM) + const { Others } = useWeb3State(NetworkPluginID.PLUGIN_EVM) const { value: nativeToken } = useFungibleToken(NetworkPluginID.PLUGIN_EVM) const navigate = useNavigate() @@ -206,7 +207,9 @@ export const Transfer1559 = memo(({ selectedAsset, openAssetM chainId: nativeToken?.chainId, }) - const { value: estimateGasFees } = useAsync(async () => GasOptions?.getGasOptions?.(chainId), [chainId]) + const { value: estimateGasFees } = useGasOptions(NetworkPluginID.PLUGIN_EVM, { + chainId, + }) const schema = useMemo(() => { return zod diff --git a/packages/mask/src/plugins/Pets/hooks/useNfts.ts b/packages/mask/src/plugins/Pets/hooks/useNfts.ts index 4832d52d1adf..55b06d0ed8cf 100644 --- a/packages/mask/src/plugins/Pets/hooks/useNfts.ts +++ b/packages/mask/src/plugins/Pets/hooks/useNfts.ts @@ -7,8 +7,10 @@ import { NonFungibleTokenContract, transform, NonFungibleAsset, + Constant, + Constants, } from '@masknet/web3-shared-base' -import { resolveIPFSLink, Constant, ChainId, SchemaType } from '@masknet/web3-shared-evm' +import { resolveIPFSLink, ChainId, SchemaType } from '@masknet/web3-shared-evm' import { cloneDeep, findLastIndex } from 'lodash-unified' import { delay } from '@dimensiondev/kit' import type { User, FilterContract } from '../types' @@ -41,7 +43,7 @@ export function useNFTs(user: User | undefined, configNFTs: Record isSameAddress(temp.contract, NFT.address)) if (!sameNFT) continue const isPunk = isSameAddress(NFT.address, Punk3D.contract) && NFT.tokenId === Punk3D.tokenId - if (isPunk) { + if (isPunk && NFT.metadata) { NFT.metadata.imageURL = Punk3D.url } const glbSupport = NFT.metadata?.imageURL?.endsWith('.glb') || isPunk @@ -63,7 +65,7 @@ export function useNFTs(user: User | undefined, configNFTs: Record | undefined) { +export function useNFTsExtra(configNFTs: Record | undefined) { const initContracts = useInitNFTs(configNFTs) const [retry, setRetry] = useState(0) const chainId = useChainId(NetworkPluginID.PLUGIN_EVM) @@ -73,7 +75,7 @@ export function useNFTsExtra(configNFTs: Record | undefined) { if (retry > 2) return let requests = [] if (!extra.length) { - requests = initContracts.map((nft) => OpenSea.getContract(nft.contract, chainId)) + requests = initContracts.map((nft) => OpenSea.getContract(nft.contract, { chainId })) } else { // openSea api request should not immediately await delay(3000) @@ -81,7 +83,7 @@ export function useNFTsExtra(configNFTs: Record | undefined) { if (nft.symbol && nft.name !== 'Unknown Token') { return Promise.resolve(nft) } - return OpenSea.getContract(initContracts[index].contract, chainId) + return OpenSea.getContract(initContracts[index].contract, { chainId }) }) } const lists: NonFungibleTokenContract[] = await Promise.all(requests) diff --git a/packages/mask/src/plugins/Pets/types.ts b/packages/mask/src/plugins/Pets/types.ts index 44759423b244..496f615dde2a 100644 --- a/packages/mask/src/plugins/Pets/types.ts +++ b/packages/mask/src/plugins/Pets/types.ts @@ -1,5 +1,5 @@ +import type { Constant } from '@masknet/web3-shared-base' import type { ERC721TokenInfo } from '@masknet/web3-shared-evm' -import type { Constant } from '@masknet/web3-shared-evm/constants/utils' export interface PetsDialogEvent { open: boolean diff --git a/packages/mask/src/plugins/Trader/SNSAdaptor/trader/GasPrior1559Settings.tsx b/packages/mask/src/plugins/Trader/SNSAdaptor/trader/GasPrior1559Settings.tsx index c75283f1bd4c..10d121fe62c1 100644 --- a/packages/mask/src/plugins/Trader/SNSAdaptor/trader/GasPrior1559Settings.tsx +++ b/packages/mask/src/plugins/Trader/SNSAdaptor/trader/GasPrior1559Settings.tsx @@ -10,8 +10,14 @@ import { toHex } from 'web3-utils' import BigNumber from 'bignumber.js' import ActionButton from '../../../../extension/options-page/DashboardComponents/ActionButton' import { isDashboardPage } from '@masknet/shared-base' -import { useChainId, useFungibleToken, useNativeTokenPrice, useWeb3State } from '@masknet/plugin-infra/web3' -import { NetworkPluginID } from '@masknet/web3-shared-base' +import { + useChainId, + useFungibleToken, + useGasOptions, + useNativeTokenPrice, + useWeb3State, +} from '@masknet/plugin-infra/web3' +import { GasOptionType, NetworkPluginID } from '@masknet/web3-shared-base' const useStyles = makeStyles<{ isDashboard: boolean }>()((theme, { isDashboard }) => ({ container: { @@ -111,7 +117,7 @@ interface GasPrior1559SettingsProps { export const GasPrior1559Settings = memo( ({ onCancel, onSave: onSave_, gasConfig, onSaveSlippage }) => { const chainId = useChainId(NetworkPluginID.PLUGIN_EVM) - const { GasOptions } = useWeb3State(NetworkPluginID.PLUGIN_EVM) + const { value: gasOptions_ } = useGasOptions(NetworkPluginID.PLUGIN_EVM) const isDashboard = isDashboardPage() const { classes } = useStyles({ isDashboard }) const { t } = useI18N() @@ -119,27 +125,24 @@ export const GasPrior1559Settings = memo( const [customGasPrice, setCustomGasPrice] = useState('0') // #region Get gas options from debank - const { value: gasOptions } = useAsync(async () => { - const response = await GasOptions?.getGasOptions?.(chainId) - if (!response) return { slow: 0, normal: 0, fast: 0 } - + const gasOptions = useMemo(() => { return { - slow: response.slow.suggestedMaxFeePerGas, - normal: response.normal.suggestedMaxFeePerGas, - fast: response.fast.suggestedMaxFeePerGas, + slow: gasOptions_?.[GasOptionType.SLOW].suggestedMaxFeePerGas ?? 0, + standard: gasOptions_?.[GasOptionType.NORMAL].suggestedMaxFeePerGas ?? 0, + fast: gasOptions_?.[GasOptionType.FAST].suggestedMaxFeePerGas ?? 0, } - }, [chainId]) + }, [chainId, gasOptions_]) // #endregion const options = useMemo( () => [ { title: t('plugin_trader_gas_setting_standard'), - gasPrice: gasOptions?.normal ?? 0, + gasPrice: gasOptions?.standard, }, { title: t('plugin_trader_gas_setting_fast'), - gasPrice: gasOptions?.fast ?? 0, + gasPrice: gasOptions?.fast, }, { title: t('plugin_trader_gas_setting_custom'), @@ -166,7 +169,7 @@ export const GasPrior1559Settings = memo( useUpdateEffect(() => { if (!(gasConfig?.gasPrice && gasOptions)) return const gasPrice = new BigNumber(gasConfig.gasPrice) - if (gasPrice.isEqualTo(gasOptions.normal)) setOption(0) + if (gasPrice.isEqualTo(gasOptions.standard)) setOption(0) else if (gasPrice.isEqualTo(gasOptions.fast)) setOption(1) else { setCustomGasPrice(formatWeiToGwei(gasPrice).toString()) diff --git a/packages/mask/src/plugins/Trader/SNSAdaptor/trader/hooks/useGasConfig.ts b/packages/mask/src/plugins/Trader/SNSAdaptor/trader/hooks/useGasConfig.ts index 25ed7950d0e6..b29116c95897 100644 --- a/packages/mask/src/plugins/Trader/SNSAdaptor/trader/hooks/useGasConfig.ts +++ b/packages/mask/src/plugins/Trader/SNSAdaptor/trader/hooks/useGasConfig.ts @@ -1,20 +1,21 @@ import { useState } from 'react' import { useAsync } from 'react-use' import { GasOptionConfig, formatGweiToWei, ChainId } from '@masknet/web3-shared-evm' -import { useWeb3State } from '@masknet/plugin-infra/web3' -import { NetworkPluginID } from '@masknet/web3-shared-base' +import { useGasOptions } from '@masknet/plugin-infra/web3' +import { GasOptionType, NetworkPluginID } from '@masknet/web3-shared-base' // TODO: support multiple chain export function useGasConfig(chainId: ChainId) { const [gasConfig, setGasConfig] = useState() - const { GasOptions } = useWeb3State(NetworkPluginID.PLUGIN_EVM) + const { value: gasOptions_ } = useGasOptions(NetworkPluginID.PLUGIN_EVM) const { value: gasPrice } = useAsync(async () => { try { - const response = await GasOptions?.getGasOptions?.(chainId) - const maxFeePerGas = formatGweiToWei(response?.normal?.suggestedMaxFeePerGas ?? 0).toFixed(0) - const maxPriorityFeePerGas = formatGweiToWei(response?.normal?.suggestedMaxPriorityFeePerGas ?? 0).toFixed( - 0, - ) + const maxFeePerGas = formatGweiToWei( + gasOptions_?.[GasOptionType.NORMAL]?.suggestedMaxFeePerGas ?? 0, + ).toFixed(0) + const maxPriorityFeePerGas = formatGweiToWei( + gasOptions_?.[GasOptionType.NORMAL]?.suggestedMaxPriorityFeePerGas ?? 0, + ).toFixed(0) setGasConfig({ maxFeePerGas, @@ -25,7 +26,7 @@ export function useGasConfig(chainId: ChainId) { setGasConfig(undefined) return } - }, [chainId]) + }, [chainId, gasOptions_]) return { gasPrice, gasConfig, setGasConfig } } diff --git a/packages/mask/src/plugins/Wallet/services/wallet/index.ts b/packages/mask/src/plugins/Wallet/services/wallet/index.ts index 65f268760a46..900bc2c2969d 100644 --- a/packages/mask/src/plugins/Wallet/services/wallet/index.ts +++ b/packages/mask/src/plugins/Wallet/services/wallet/index.ts @@ -5,7 +5,7 @@ import { toBuffer } from 'ethereumjs-util' import { personalSign, signTypedData as signTypedData_, SignTypedDataVersion } from '@metamask/eth-sig-util' import { encodeText } from '@dimensiondev/kit' import { isSameAddress } from '@masknet/web3-shared-base' -import { Transaction, formatEthereumAddress, ProviderType } from '@masknet/web3-shared-evm' +import type { Transaction, formatEthereumAddress, ProviderType } from '@masknet/web3-shared-evm' import { api } from '@dimensiondev/mask-wallet-core/proto' import { MAX_DERIVE_COUNT, HD_PATH_WITHOUT_INDEX_ETHEREUM } from '@masknet/plugin-wallet' import * as sdk from './maskwallet' @@ -32,13 +32,13 @@ export { isLocked, lockWallet, unlockWallet } from './locker' export async function getWallet(address?: string) { if (hasNativeAPI) { - const wallets = await getWallets(ProviderType.MaskWallet) + const wallets = await getWallets() return wallets.find((x) => isSameAddress(x.address, address)) } return database.getWallet(address) } -export async function getWallets(providerType?: ProviderType): Promise< +export async function getWallets(): Promise< (Omit & { configurable: boolean hasStoredKeyInfo: boolean @@ -46,8 +46,6 @@ export async function getWallets(providerType?: ProviderType): Promise< })[] > { // if (hasNativeAPI) { - // if (providerType && providerType !== ProviderType.MaskWallet) return [] - // // read wallet from rpc // const accounts = await EVM_RPC.getAccounts() // const address = first(accounts) ?? '' @@ -68,7 +66,7 @@ export async function getWallets(providerType?: ProviderType): Promise< // }, // ] // } - return database.getWallets(providerType) + return database.getWallets() } export function createMnemonicWords() { @@ -79,7 +77,7 @@ export async function getWalletPrimary() { if (hasNativeAPI) return null return ( first( - (await database.getWallets(ProviderType.MaskWallet)) + (await database.getWallets()) .filter((x) => x.storedKeyInfo?.type === api.StoredKeyType.Mnemonic) .sort((a, z) => a.createdAt.getTime() - z.createdAt.getTime()), ) ?? null diff --git a/packages/plugin-infra/src/web3-helpers/index.ts b/packages/plugin-infra/src/web3-helpers/index.ts index dd8d63c5b2fe..f73f4aa91848 100644 --- a/packages/plugin-infra/src/web3-helpers/index.ts +++ b/packages/plugin-infra/src/web3-helpers/index.ts @@ -1,6 +1,8 @@ import type { Connection, ConnectionOptions, + Hub, + HubOptions, NetworkDescriptor, NetworkPluginID, ProtocolState, @@ -106,7 +108,17 @@ export declare namespace Web3Helper { Definition[T]['TransactionSignature'], Definition[T]['Web3'] > - + export type Web3HubOptions = T extends never + ? never + : HubOptions + export type Web3Hub = T extends never + ? never + : Hub< + Definition[T]['ChainId'], + Definition[T]['SchemaType'], + Definition[T]['GasOption'], + Definition[T]['Transaction'] + > export type Web3State = T extends never ? never : Web3Plugin.ObjectCapabilities.Capabilities< @@ -162,6 +174,12 @@ export declare namespace Web3Helper { Definition[NetworkPluginID]['TransactionSignature'], Definition[NetworkPluginID]['Web3'] > + export type Web3HubAll = Hub< + Definition[NetworkPluginID]['ChainId'], + Definition[NetworkPluginID]['SchemaType'], + Definition[NetworkPluginID]['GasOption'], + Definition[NetworkPluginID]['Transaction'] + > export type Web3StateAll = Web3Plugin.ObjectCapabilities.Capabilities< Definition[NetworkPluginID]['ChainId'], diff --git a/packages/plugin-infra/src/web3-state/Asset.ts b/packages/plugin-infra/src/web3-state/Asset.ts deleted file mode 100644 index 466929ea1f92..000000000000 --- a/packages/plugin-infra/src/web3-state/Asset.ts +++ /dev/null @@ -1,52 +0,0 @@ -import type { - Pageable, - Pagination, - AssetState as Web3AssetState, - FungibleAsset, - NonFungibleAsset, -} from '@masknet/web3-shared-base' - -const PAGE_SIZE = 50 -const MAX_PAGE_SIZE = 25 - -export class AssetState implements Web3AssetState { - getFungibleAssets( - address: string, - pagination?: Pagination | undefined, - ): Promise>> { - throw new Error('Method not implemented.') - } - - getNonFungibleAssets( - address: string, - pagination?: Pagination | undefined, - ): Promise>> { - throw new Error('Method not implemented.') - } - - async *getAllFungibleAssets(address: string): AsyncIterableIterator> { - for (let i = 0; i < MAX_PAGE_SIZE; i += 1) { - const pageable = await this.getFungibleAssets(address, { - page: i, - size: PAGE_SIZE, - }) - - yield* pageable.data - - if (pageable.data.length === 0) return - } - } - - async *getAllNonFungibleAssets(address: string): AsyncIterableIterator> { - for (let i = 0; i < MAX_PAGE_SIZE; i += 1) { - const pageable = await this.getNonFungibleAssets(address, { - page: i, - size: PAGE_SIZE, - }) - - yield* pageable.data - - if (pageable.data.length === 0) return - } - } -} diff --git a/packages/plugin-infra/src/web3-state/Hub.ts b/packages/plugin-infra/src/web3-state/Hub.ts new file mode 100644 index 000000000000..9629fdde9fa5 --- /dev/null +++ b/packages/plugin-infra/src/web3-state/Hub.ts @@ -0,0 +1,39 @@ +import type { Subscription } from 'use-subscription' +import type { HubState as Web3HubState, Hub, HubOptions, SourceType, CurrencyType } from '@masknet/web3-shared-base' + +const SIZE_PER_PAGE = 50 +const MAX_PAGE_SIZE = 25 + +export class HubState + implements Web3HubState +{ + constructor( + protected createHub: ( + chainId?: ChainId, + account?: string, + sourceType?: SourceType, + currencyType?: CurrencyType, + sizePerPage?: number, + maxPageSize?: number, + ) => Hub, + protected subscription: { + account?: Subscription + chainId?: Subscription + sourceType?: Subscription + currencyType?: Subscription + }, + ) {} + + getHub(options?: HubOptions) { + return Promise.resolve( + this.createHub( + options?.chainId ?? this.subscription.chainId?.getCurrentValue(), + options?.account ?? this.subscription.account?.getCurrentValue(), + options?.sourceType ?? this.subscription.sourceType?.getCurrentValue(), + options?.currencyType ?? this.subscription.currencyType?.getCurrentValue(), + SIZE_PER_PAGE, + MAX_PAGE_SIZE, + ), + ) + } +} diff --git a/packages/plugin-infra/src/web3-state/Settings.ts b/packages/plugin-infra/src/web3-state/Settings.ts index dcf21b23bd86..1121fd6dfe71 100644 --- a/packages/plugin-infra/src/web3-state/Settings.ts +++ b/packages/plugin-infra/src/web3-state/Settings.ts @@ -1,10 +1,13 @@ import type { Subscription } from 'use-subscription' import { createConstantSubscription, StorageObject } from '@masknet/shared-base' -import { CurrencyType, SettingsState as Web3SettingsState } from '@masknet/web3-shared-base' +import { CurrencyType, GasOptionType, SourceType, SettingsState as Web3SettingsState } from '@masknet/web3-shared-base' import type { Plugin } from '../types' export interface SettingsStorage { currencyType: CurrencyType + gasOptionType: GasOptionType + fungibleAssetSourceType: SourceType + nonFungibleAssetSourceType: SourceType } export class SettingsState implements Web3SettingsState { @@ -12,14 +15,23 @@ export class SettingsState implements Web3SettingsState { public allowTestnet?: Subscription public currencyType?: Subscription + public gasOptionType?: Subscription + public fungibleAssetSourceType?: Subscription + public nonFungibleAssetSourceType?: Subscription constructor(context: Plugin.Shared.SharedContext) { const { storage } = context.createKVStorage('memory', 'Settings', { currencyType: CurrencyType.USD, + gasOptionType: GasOptionType.NORMAL, + fungibleAssetSourceType: SourceType.DeBank, + nonFungibleAssetSourceType: SourceType.OpenSea, }) this.storage = storage this.allowTestnet = createConstantSubscription(process.env.NODE_ENV === 'development') this.currencyType = this.storage.currencyType.subscription + this.gasOptionType = this.storage.gasOptionType.subscription + this.fungibleAssetSourceType = this.storage.fungibleAssetSourceType.subscription + this.nonFungibleAssetSourceType = this.storage.nonFungibleAssetSourceType.subscription } } diff --git a/packages/plugin-infra/src/web3-state/TokenList.ts b/packages/plugin-infra/src/web3-state/TokenList.ts deleted file mode 100644 index 663682d2724d..000000000000 --- a/packages/plugin-infra/src/web3-state/TokenList.ts +++ /dev/null @@ -1,99 +0,0 @@ -import type { Subscription } from 'use-subscription' -import { mapSubscription, mergeSubscription, StorageItem } from '@masknet/shared-base' -import type { - FungibleToken, - NonFungibleToken, - Token, - TokenListState as Web3TokenListState, -} from '@masknet/web3-shared-base' -import type { Plugin } from '../types' - -export class TokenListState< - ChainId extends number, - SchemaType extends string | number, - TokenLists extends Record< - 'fungibleTokens' | 'nonFungibleTokens', - Record[]> - > = Record<'fungibleTokens' | 'nonFungibleTokens', Record[]>>, -> implements Web3TokenListState -{ - protected storage: StorageItem = null! - - public fungibleTokens?: Subscription[]> - public nonFungibleTokens?: Subscription[]> - - constructor( - protected context: Plugin.Shared.SharedContext, - protected defaultValue: TokenLists, - protected subscriptions: { - chainId?: Subscription - }, - ) { - const { storage } = context.createKVStorage('memory', 'TokenList', { - value: defaultValue, - }) - this.storage = storage.value - - if (this.subscriptions.chainId) { - this.fungibleTokens = mapSubscription( - mergeSubscription<[ChainId, TokenLists]>(this.subscriptions.chainId, this.storage.subscription), - ([chainId, tokenLists]) => { - console.log({ - chainId, - tokenLists, - }) - return tokenLists.fungibleTokens[chainId] as FungibleToken[] - }, - ) - this.nonFungibleTokens = mapSubscription( - mergeSubscription<[ChainId, TokenLists]>(this.subscriptions.chainId, this.storage.subscription), - ([chainId, tokenLists]) => { - console.log({ - chainId, - tokenLists, - }) - return tokenLists.nonFungibleTokens[chainId] as NonFungibleToken[] - }, - ) - } - } - - async getTokens(type: 'fungible' | 'nonFungible', chainId: ChainId) { - if (type === 'fungible') - return this.storage.value.fungibleTokens[chainId] as FungibleToken[] - return this.storage.value.nonFungibleTokens[chainId] as NonFungibleToken[] - } - - getFungibleTokens(chainId: ChainId) { - return this.getTokens('fungible', chainId) as Promise[]> - } - - getNonFungibleTokens(chainId: ChainId) { - return this.getTokens('nonFungible', chainId) as Promise[]> - } - - protected setTokenList( - type: 'fungible' | 'nonFungible', - chainId: ChainId, - tokenList: Token[], - ) { - const all = this.storage.value - this.storage.setValue({ - ...all, - fungibleTokens: - type === 'fungible' - ? { - ...all.fungibleTokens, - [chainId]: tokenList, - } - : all.fungibleTokens, - nonFungibleTokens: - type === 'nonFungible' - ? { - ...all.nonFungibleTokens, - [chainId]: tokenList, - } - : all.nonFungibleTokens, - }) - } -} diff --git a/packages/plugin-infra/src/web3-state/index.ts b/packages/plugin-infra/src/web3-state/index.ts index add48383a8ac..a74cb13fc918 100644 --- a/packages/plugin-infra/src/web3-state/index.ts +++ b/packages/plugin-infra/src/web3-state/index.ts @@ -1,10 +1,9 @@ -export * from './Asset' export * from './AddressBook' export * from './NameService' export * from './RiskWarning' export * from './Settings' export * from './Token' -export * from './TokenList' +export * from './Hub' export * from './Transaction' export * from './TransactionFormatter' export * from './TransactionWatcher' diff --git a/packages/plugin-infra/src/web3-types.ts b/packages/plugin-infra/src/web3-types.ts index 23a50c3133a9..eaa4b3fe51ea 100644 --- a/packages/plugin-infra/src/web3-types.ts +++ b/packages/plugin-infra/src/web3-types.ts @@ -5,23 +5,18 @@ import type { NameServiceState, RiskWarningState, SettingsState, - GasOptionsState, TokenState, - TokenPriceState, - TokenListState, TransactionState, TransactionFormatterState, TransactionWatcherState, ProtocolState, ProviderState, - ExplorerState, WalletState, OthersState, IdentityServiceState, - TokenIconState, + HubState, } from '@masknet/web3-shared-base' import type { Plugin } from './types' -import type { AssetState } from './web3-state' export declare namespace Web3Plugin { export namespace ObjectCapabilities { @@ -40,16 +35,12 @@ export declare namespace Web3Plugin { Web3, > { AddressBook?: AddressBookState - Asset?: AssetState + Hub?: HubState IdentityService?: IdentityServiceState NameService?: NameServiceState RiskWarning?: RiskWarningState Settings?: SettingsState - GasOptions?: GasOptionsState Token?: TokenState - TokenIcon?: TokenIconState - TokenPrice?: TokenPriceState - TokenList?: TokenListState Transaction?: TransactionState TransactionFormatter?: TransactionFormatterState TransactionWatcher?: TransactionWatcherState @@ -65,7 +56,6 @@ export declare namespace Web3Plugin { Web3 > Provider?: ProviderState - Explorer?: ExplorerState Wallet?: WalletState Others?: OthersState } diff --git a/packages/plugin-infra/src/web3/index.ts b/packages/plugin-infra/src/web3/index.ts index 36d49caa749d..ea00626b9084 100644 --- a/packages/plugin-infra/src/web3/index.ts +++ b/packages/plugin-infra/src/web3/index.ts @@ -22,6 +22,8 @@ export * from './useClearTransactionsCallback' export * from './useCurrencyType' export * from './useDefaultChainId' export * from './useDefaultNetworkType' +export * from './useFungibleAsset' +export * from './useFungibleAssetSourceType' export * from './useFungibleAssets' export * from './useFungibleToken' export * from './useFungibleTokenBalance' @@ -30,8 +32,8 @@ export * from './useFungibleTokenWatched' export * from './useFungibleTokens' export * from './useFungibleTokensBalance' export * from './useFungibleTokensFromTokenList' -export * from './useGasOptions' export * from './useGasOptionType' +export * from './useGasOptions' export * from './useGasPrice' export * from './useImageChecker' export * from './useLookupAddress' @@ -42,6 +44,8 @@ export * from './useNativeTokenPrice' export * from './useNetworkDescriptor' export * from './useNetworkDescriptors' export * from './useNetworkType' +export * from './useNonFungibleAsset' +export * from './useNonFungibleAssetSourceType' export * from './useNonFungibleAssets' export * from './useNonFungibleTokenBalance' export * from './useNonFungibleTokenContract' @@ -67,6 +71,7 @@ export * from './useWalletPrimary' export * from './useWallets' export * from './useWeb3' export * from './useWeb3Connection' +export * from './useWeb3Hub' export * from './useWeb3State' export * from './useWeb3UI' export * from './useZeroAddress' diff --git a/packages/plugin-infra/src/web3/useFungibleAsset.ts b/packages/plugin-infra/src/web3/useFungibleAsset.ts new file mode 100644 index 000000000000..84e60fe69131 --- /dev/null +++ b/packages/plugin-infra/src/web3/useFungibleAsset.ts @@ -0,0 +1,23 @@ +import { useAsyncRetry } from 'react-use' +import { EMPTY_LIST } from '@masknet/shared-base' +import type { FungibleAsset, NetworkPluginID } from '@masknet/web3-shared-base' +import type { Web3Helper } from '../web3-helpers' +import { useWeb3Hub } from './useWeb3Hub' + +export function useFungibleAsset( + pluginID?: T, + address?: string, + options?: Web3Helper.Web3ConnectionOptions, +) { + type GetFungibleAsset = ( + address: string, + options?: Web3Helper.Web3ConnectionOptions, + ) => Promise> + + const hub = useWeb3Hub(pluginID, options) + + return useAsyncRetry(async () => { + if (!address) return EMPTY_LIST + return (hub?.getFungibleAsset as GetFungibleAsset | undefined)?.(address) + }, [address, hub?.getFungibleAsset]) +} diff --git a/packages/plugin-infra/src/web3/useFungibleAssetSourceType.ts b/packages/plugin-infra/src/web3/useFungibleAssetSourceType.ts new file mode 100644 index 000000000000..67f51ce05b52 --- /dev/null +++ b/packages/plugin-infra/src/web3/useFungibleAssetSourceType.ts @@ -0,0 +1,9 @@ +import { useSubscription } from 'use-subscription' +import type { NetworkPluginID } from '@masknet/web3-shared-base' +import { useWeb3State } from './useWeb3State' +import { UNDEIFNED } from '../utils/subscription' + +export function useFungibleAssetSourceType(pluginID?: T) { + const { Settings } = useWeb3State(pluginID) + return useSubscription(Settings?.fungibleAssetSourceType ?? UNDEIFNED) +} diff --git a/packages/plugin-infra/src/web3/useFungibleAssets.ts b/packages/plugin-infra/src/web3/useFungibleAssets.ts index c5774b9e89a5..84cefbacfb23 100644 --- a/packages/plugin-infra/src/web3/useFungibleAssets.ts +++ b/packages/plugin-infra/src/web3/useFungibleAssets.ts @@ -2,12 +2,13 @@ import { useAsyncRetry } from 'react-use' import { asyncIteratorToArray, EMPTY_LIST } from '@masknet/shared-base' import type { FungibleAsset, NetworkPluginID } from '@masknet/web3-shared-base' import type { Web3Helper } from '../web3-helpers' -import { useWeb3State } from './useWeb3State' import { useAccount } from './useAccount' +import { useWeb3Hub } from './useWeb3Hub' export function useFungibleAssets( pluginID?: T, schemaType?: Web3Helper.Definition[T]['SchemaType'], + options?: Web3Helper.Web3HubOptions, ) { type GetAllFungibleAssets = ( address: string, @@ -15,12 +16,12 @@ export function useFungibleAssets( FungibleAsset > - const { Asset } = useWeb3State(pluginID) const account = useAccount(pluginID) + const hub = useWeb3Hub(pluginID, options) return useAsyncRetry(async () => { - if (!account || !Asset) return EMPTY_LIST - const assets = await asyncIteratorToArray((Asset.getAllFungibleAssets as GetAllFungibleAssets)(account)) + if (!account || !hub) return EMPTY_LIST + const assets = await asyncIteratorToArray((hub?.getAllFungibleAssets as GetAllFungibleAssets)(account)) return assets.length && schemaType ? assets.filter((x) => x.schema === schemaType) : assets - }, [account, schemaType, Asset?.getAllFungibleAssets]) + }, [account, schemaType, hub]) } diff --git a/packages/plugin-infra/src/web3/useFungibleTokenPrice.ts b/packages/plugin-infra/src/web3/useFungibleTokenPrice.ts index a68c8e080b47..66e9741aaa98 100644 --- a/packages/plugin-infra/src/web3/useFungibleTokenPrice.ts +++ b/packages/plugin-infra/src/web3/useFungibleTokenPrice.ts @@ -1,31 +1,21 @@ import { useAsyncRetry } from 'react-use' -import type { CurrencyType, NetworkPluginID } from '@masknet/web3-shared-base' +import type { NetworkPluginID } from '@masknet/web3-shared-base' import type { Web3Helper } from '../web3-helpers' import { useChainId } from './useChainId' -import { useWeb3State } from './useWeb3State' +import { useWeb3Hub } from './useWeb3Hub' export function useFungibleTokenPrice( pluginID: T, address?: string, - options?: Web3Helper.Web3ConnectionOptions & { - currencyType?: CurrencyType - }, + options?: Web3Helper.Web3HubOptions, ) { - type GetFungibleTokenPrice = ( - chainId: Web3Helper.Definition[T]['ChainId'], - address: string, - currencyType?: CurrencyType, - ) => Promise + type GetFungibleTokenPrice = (chainId: Web3Helper.Definition[T]['ChainId'], address: string) => Promise const chainId = useChainId(pluginID, options?.chainId) - const { TokenPrice } = useWeb3State(pluginID) + const hub = useWeb3Hub(pluginID, options) return useAsyncRetry(async () => { - if (!chainId || !TokenPrice) return 0 - return (TokenPrice.getFungibleTokenPrice as GetFungibleTokenPrice)( - chainId, - address ?? '', - options?.currencyType, - ) - }, [chainId, address, options?.currencyType, TokenPrice]) + if (!chainId || !hub) return 0 + return (hub.getFungibleTokenPrice as GetFungibleTokenPrice)(chainId, address ?? '') + }, [chainId, address, hub]) } diff --git a/packages/plugin-infra/src/web3/useFungibleTokensFromTokenList.ts b/packages/plugin-infra/src/web3/useFungibleTokensFromTokenList.ts index a1c94f26aed2..4c9f441f0405 100644 --- a/packages/plugin-infra/src/web3/useFungibleTokensFromTokenList.ts +++ b/packages/plugin-infra/src/web3/useFungibleTokensFromTokenList.ts @@ -1,26 +1,21 @@ -import { Subscription, useSubscription } from 'use-subscription' +import { useAsyncRetry } from 'react-use' import type { FungibleToken, NetworkPluginID } from '@masknet/web3-shared-base' import type { Web3Helper } from '../web3-helpers' -import { useWeb3State } from './useWeb3State' -import { EMPTY_ARRAY } from '../utils/subscription' -import { useEffect } from 'react' import { useChainId } from './useChainId' +import { useWeb3Hub } from './useWeb3Hub' -export function useFungibleTokensFromTokenList(pluginID?: T) { +export function useFungibleTokensFromTokenList( + pluginID?: T, + options?: Web3Helper.Web3HubOptions, +) { type GetFungibleTokens = ( chainId: Web3Helper.Definition[T]['ChainId'], - ) => Promise> + ) => Promise[]> const chainId = useChainId(pluginID) - const { TokenList } = useWeb3State(pluginID) + const hub = useWeb3Hub(pluginID, options) - useEffect(() => { - ;(TokenList?.getFungibleTokens as GetFungibleTokens | undefined)?.(chainId) - }, [chainId, TokenList]) - - return useSubscription( - (TokenList?.fungibleTokens ?? EMPTY_ARRAY) as Subscription< - FungibleToken[] - >, - ) + return useAsyncRetry(async () => { + return (hub?.getFungibleTokensFromTokenList as GetFungibleTokens | undefined)?.(chainId) + }, [chainId, hub]) } diff --git a/packages/plugin-infra/src/web3/useGasOptions.ts b/packages/plugin-infra/src/web3/useGasOptions.ts index a78b5d9dd157..5a96e04ae9ca 100644 --- a/packages/plugin-infra/src/web3/useGasOptions.ts +++ b/packages/plugin-infra/src/web3/useGasOptions.ts @@ -1,20 +1,20 @@ import { useAsyncRetry } from 'react-use' -import { CurrencyType, GasOptionType, NetworkPluginID } from '@masknet/web3-shared-base' +import type { GasOptionType, NetworkPluginID } from '@masknet/web3-shared-base' import type { Web3Helper } from '../web3-helpers' import { useChainId } from './useChainId' -import { useWeb3State } from './useWeb3State' +import { useWeb3Hub } from './useWeb3Hub' -export function useGasOptions(pluginID?: T, currencyType = CurrencyType.USD) { +export function useGasOptions(pluginID?: T, options?: Web3Helper.Web3HubOptions) { type GetGasOptions = ( chainId: Web3Helper.Definition[T]['ChainId'], - currencyType: CurrencyType, + options?: Web3Helper.Web3HubOptions, ) => Promise> const chainId = useChainId(pluginID) - const { GasOptions } = useWeb3State(pluginID) + const hub = useWeb3Hub(pluginID, options) return useAsyncRetry(async () => { - if (!chainId || !GasOptions) return - return (GasOptions.getGasOptions as GetGasOptions)(chainId, currencyType) - }, [chainId, currencyType, GasOptions]) + if (!chainId || !hub) return + return (hub.getGasOptions as GetGasOptions)(chainId) + }, [chainId, hub]) } diff --git a/packages/plugin-infra/src/web3/useNativeTokenPrice.ts b/packages/plugin-infra/src/web3/useNativeTokenPrice.ts index 1519e7314bae..43cb6f96cd42 100644 --- a/packages/plugin-infra/src/web3/useNativeTokenPrice.ts +++ b/packages/plugin-infra/src/web3/useNativeTokenPrice.ts @@ -1,31 +1,22 @@ import { useAsyncRetry } from 'react-use' -import type { CurrencyType, NetworkPluginID } from '@masknet/web3-shared-base' +import type { NetworkPluginID } from '@masknet/web3-shared-base' import type { Web3Helper } from '../web3-helpers' -import { useWeb3State } from './useWeb3State' import { useNativeTokenAddress } from './useNativeTokenAddress' import { useChainId } from '../entry-web3' +import { useWeb3Hub } from './useWeb3Hub' -export function useNativeTokenPrice( - pluginID: T, - options?: Web3Helper.Web3ConnectionOptions & { - currencyType?: CurrencyType - }, -) { +export function useNativeTokenPrice(pluginID: T, options?: Web3Helper.Web3HubOptions) { type GetFungibleTokenPrice = ( chainId: Web3Helper.Definition[T]['ChainId'], address: string, - currencyType?: CurrencyType, + options?: Web3Helper.Web3HubOptions, ) => Promise const chainId = useChainId(pluginID) - const { TokenPrice } = useWeb3State(pluginID) + const hub = useWeb3Hub(pluginID, options) const nativeTokenAddress = useNativeTokenAddress(pluginID, options) return useAsyncRetry(async () => { - return (TokenPrice?.getFungibleTokenPrice as GetFungibleTokenPrice)( - chainId, - nativeTokenAddress, - options?.currencyType, - ) - }, [chainId, nativeTokenAddress, options?.currencyType, TokenPrice]) + return (hub?.getFungibleTokenPrice as GetFungibleTokenPrice)(chainId, nativeTokenAddress) + }, [chainId, nativeTokenAddress, hub]) } diff --git a/packages/plugin-infra/src/web3/useNonFungibleAsset.ts b/packages/plugin-infra/src/web3/useNonFungibleAsset.ts new file mode 100644 index 000000000000..d9bcf619fc08 --- /dev/null +++ b/packages/plugin-infra/src/web3/useNonFungibleAsset.ts @@ -0,0 +1,26 @@ +import { useAsyncRetry } from 'react-use' +import type { NonFungibleAsset, NetworkPluginID } from '@masknet/web3-shared-base' +import type { Web3Helper } from '../web3-helpers' +import { useAccount } from '../entry-web3' +import { useWeb3Hub } from './useWeb3Hub' +import { EMPTY_LIST } from '@masknet/shared-base' + +export function useNonFungibleAsset( + pluginID?: T, + address?: string, + id?: string, + options?: Web3Helper.Web3HubOptions, +) { + type GetNonFungibleAsset = ( + address: string, + id: string, + ) => Promise> + + const account = useAccount(pluginID) + const hub = useWeb3Hub(pluginID, options) + + return useAsyncRetry(async () => { + if (!address || !id || !hub) return EMPTY_LIST + return (hub.getNonFungibleAsset as GetNonFungibleAsset)(address, id) + }, [address, account, id, hub]) +} diff --git a/packages/plugin-infra/src/web3/useNonFungibleAssetSourceType.ts b/packages/plugin-infra/src/web3/useNonFungibleAssetSourceType.ts new file mode 100644 index 000000000000..4f0fd1d641ea --- /dev/null +++ b/packages/plugin-infra/src/web3/useNonFungibleAssetSourceType.ts @@ -0,0 +1,9 @@ +import { useSubscription } from 'use-subscription' +import type { NetworkPluginID } from '@masknet/web3-shared-base' +import { useWeb3State } from './useWeb3State' +import { UNDEIFNED } from '../utils/subscription' + +export function useNonFungibleAssetSourceType(pluginID?: T) { + const { Settings } = useWeb3State(pluginID) + return useSubscription(Settings?.nonFungibleAssetSourceType ?? UNDEIFNED) +} diff --git a/packages/plugin-infra/src/web3/useNonFungibleAssets.ts b/packages/plugin-infra/src/web3/useNonFungibleAssets.ts index 211209b86cb2..94316658872e 100644 --- a/packages/plugin-infra/src/web3/useNonFungibleAssets.ts +++ b/packages/plugin-infra/src/web3/useNonFungibleAssets.ts @@ -2,8 +2,8 @@ import { useAsyncRetry } from 'react-use' import { asyncIteratorToArray } from '@masknet/shared-base' import type { NonFungibleAsset, NetworkPluginID } from '@masknet/web3-shared-base' import type { Web3Helper } from '../web3-helpers' -import { useWeb3State } from './useWeb3State' import { useAccount } from './useAccount' +import { useWeb3Hub } from './useWeb3Hub' export function useNonFungibleAssets( pluginID?: T, @@ -15,12 +15,12 @@ export function useNonFungibleAssets( NonFungibleAsset > - const { Asset } = useWeb3State(pluginID) const account = useAccount(pluginID) + const hub = useWeb3Hub(pluginID) return useAsyncRetry(async () => { - if (!account || !Asset) return [] - const assets = await asyncIteratorToArray((Asset.getAllNonFungibleAssets as GetAllNonFungibleAssets)(account)) + if (!account || !hub) return [] + const assets = await asyncIteratorToArray((hub.getAllNonFungibleAssets as GetAllNonFungibleAssets)(account)) return assets.length && schemaType ? assets.filter((x) => x.schema === schemaType) : assets - }, [account, schemaType, Asset]) + }, [account, schemaType, hub]) } diff --git a/packages/plugin-infra/src/web3/useNonFungibleTokenPrice.ts b/packages/plugin-infra/src/web3/useNonFungibleTokenPrice.ts index 53b272b85748..abbfe8e35e4d 100644 --- a/packages/plugin-infra/src/web3/useNonFungibleTokenPrice.ts +++ b/packages/plugin-infra/src/web3/useNonFungibleTokenPrice.ts @@ -1,35 +1,27 @@ import { useAsyncRetry } from 'react-use' -import type { CurrencyType, NetworkPluginID } from '@masknet/web3-shared-base' +import type { NetworkPluginID } from '@masknet/web3-shared-base' import type { Web3Helper } from '../web3-helpers' import { useChainId } from './useChainId' -import { useWeb3State } from './useWeb3State' +import { useWeb3Hub } from './useWeb3Hub' export function useNonFungibleTokenPrice( pluginID: T, address?: string, tokenId?: string, - options?: Web3Helper.Web3ConnectionOptions & { - currencyType?: CurrencyType - }, + options?: Web3Helper.Web3HubOptions, ) { type GetNonFungibleTokenPrice = ( chainId: Web3Helper.Definition[T]['ChainId'], address: string, tokenId: string, - currencyType?: CurrencyType, + options?: Web3Helper.Web3HubOptions, ) => Promise const chainId = useChainId(pluginID, options?.chainId) - const { TokenPrice } = useWeb3State(pluginID) + const hub = useWeb3Hub(pluginID, options) return useAsyncRetry(async () => { - if (!chainId || !TokenPrice) return 0 - if (!address || !tokenId) return 0 - return (TokenPrice.getNonFungibleTokenPrice as GetNonFungibleTokenPrice)( - chainId, - address, - tokenId, - options?.currencyType, - ) - }, [chainId, address, tokenId, options?.currencyType, TokenPrice]) + if (!chainId || !address || !tokenId) return 0 + return (hub?.getNonFungibleTokenPrice as GetNonFungibleTokenPrice)(chainId, address, tokenId) + }, [chainId, address, tokenId, hub]) } diff --git a/packages/plugin-infra/src/web3/useNonFungibleTokensFromTokenList.ts b/packages/plugin-infra/src/web3/useNonFungibleTokensFromTokenList.ts index cb702158b40c..f7dcc9686ce0 100644 --- a/packages/plugin-infra/src/web3/useNonFungibleTokensFromTokenList.ts +++ b/packages/plugin-infra/src/web3/useNonFungibleTokensFromTokenList.ts @@ -1,14 +1,21 @@ -import { Subscription, useSubscription } from 'use-subscription' +import { useAsyncRetry } from 'react-use' import type { NetworkPluginID, NonFungibleToken } from '@masknet/web3-shared-base' import type { Web3Helper } from '../web3-helpers' -import { useWeb3State } from './useWeb3State' -import { EMPTY_ARRAY } from '../utils/subscription' +import { useWeb3Hub } from './useWeb3Hub' +import { useChainId } from './useChainId' -export function useNonFungibleTokensFromTokenList(pluginID?: T) { - const { TokenList } = useWeb3State(pluginID) - return useSubscription( - (TokenList?.nonFungibleTokens ?? EMPTY_ARRAY) as Subscription< - NonFungibleToken[] - >, - ) +export function useNonFungibleTokensFromTokenList( + pluginID?: T, + options?: Web3Helper.Web3HubOptions, +) { + type GetNonFungibleTokens = ( + chainId: Web3Helper.Definition[T]['ChainId'], + ) => Promise[]> + + const chainId = useChainId(pluginID) + const hub = useWeb3Hub(pluginID, options) + + return useAsyncRetry(async () => { + return (hub?.getNonFungibleTokensFromTokenList as GetNonFungibleTokens | undefined)?.(chainId) + }, [chainId, hub]) } diff --git a/packages/plugin-infra/src/web3/useWeb3Connection.ts b/packages/plugin-infra/src/web3/useWeb3Connection.ts index b3cebfe8ef81..e81b991dffae 100644 --- a/packages/plugin-infra/src/web3/useWeb3Connection.ts +++ b/packages/plugin-infra/src/web3/useWeb3Connection.ts @@ -19,7 +19,7 @@ export function useWeb3Connection( const { value: connection = null } = useAsyncRetry(async () => { if (!Protocol?.getConnection) return - return (Protocol.getConnection as GetConnection)({ + return (Protocol.getConnection as GetConnection)?.({ account, chainId, providerType, diff --git a/packages/plugin-infra/src/web3/useWeb3Hub.ts b/packages/plugin-infra/src/web3/useWeb3Hub.ts new file mode 100644 index 000000000000..04127b1d7759 --- /dev/null +++ b/packages/plugin-infra/src/web3/useWeb3Hub.ts @@ -0,0 +1,33 @@ +import { useAsyncRetry } from 'react-use' +import type { Hub, NetworkPluginID } from '@masknet/web3-shared-base' +import { useChainId, useAccount } from '../entry-web3' +import type { Web3Helper } from '../web3-helpers' +import { useWeb3State } from './useWeb3State' + +export function useWeb3Hub(pluginID?: T, options?: Web3Helper.Web3HubOptions) { + type GetHub = ( + options?: Web3Helper.Web3HubOptions, + ) => Promise< + Hub< + Web3Helper.Definition[T]['ChainId'], + Web3Helper.Definition[T]['SchemaType'], + Web3Helper.Definition[T]['GasOption'], + Web3Helper.Definition[T]['Transaction'] + > + > + + const { Hub } = useWeb3State(pluginID) + const chainId = useChainId(pluginID) + const account = useAccount(pluginID) + + const { value: hub = null } = useAsyncRetry(async () => { + if (!Hub?.getHub) return + return (Hub.getHub as GetHub)?.({ + account, + chainId, + ...options, + } as Web3Helper.Web3HubOptions) + }, [account, chainId, Hub, JSON.stringify(options)]) + + return hub +} diff --git a/packages/plugins/EVM/src/state/Asset.ts b/packages/plugins/EVM/src/state/Asset.ts deleted file mode 100644 index 1218551ba8ab..000000000000 --- a/packages/plugins/EVM/src/state/Asset.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { OpenSea, NFTScan, DeBank, Zerion } from '@masknet/web3-providers' -import { createPageable, Web3Pagination } from '@masknet/web3-shared-base' -import { AssetState } from '@masknet/plugin-infra/web3' -import type { ChainId, SchemaType } from '@masknet/web3-shared-evm' - -export class Asset extends AssetState { - override async getFungibleAssets(address: string, pagination?: Web3Pagination) { - // only the first page is available - if ((pagination?.page ?? 0) > 0) return createPageable([]) - try { - return DeBank.getAssets(address, pagination) - } catch { - return Zerion.getAssets(address, pagination) - } - } - - override async getNonFungibleAssets(address: string, pagination?: Web3Pagination) { - try { - return OpenSea.getTokens(address, pagination) - } catch { - return NFTScan.getTokens(address, pagination) - } - } -} diff --git a/packages/plugins/EVM/src/state/GasOptions.ts b/packages/plugins/EVM/src/state/GasOptions.ts deleted file mode 100644 index 0c53092a4c68..000000000000 --- a/packages/plugins/EVM/src/state/GasOptions.ts +++ /dev/null @@ -1,18 +0,0 @@ -import type { Plugin } from '@masknet/plugin-infra' -import { DeBank, MetaSwap } from '@masknet/web3-providers' -import type { CurrencyType, GasOptionsState as Web3GasOptionsState, GasOptionType } from '@masknet/web3-shared-base' -import { ChainId, chainResolver, GasOption } from '@masknet/web3-shared-evm' - -export class GasOptions implements Web3GasOptionsState { - constructor(protected context: Plugin.Shared.SharedContext) {} - - getGasOptions( - chainId: ChainId, - currencyType?: CurrencyType | undefined, - ): Promise> { - if (chainResolver.isSupport(chainId, 'EIP1559')) { - return MetaSwap.getGasOptions(chainId) - } - return DeBank.getGasOptions(chainId) - } -} diff --git a/packages/plugins/EVM/src/state/Hub.ts b/packages/plugins/EVM/src/state/Hub.ts new file mode 100644 index 000000000000..94068e7dbd4f --- /dev/null +++ b/packages/plugins/EVM/src/state/Hub.ts @@ -0,0 +1,20 @@ +import type { CurrencyType, SourceType } from '@masknet/web3-shared-base' +import { HubState } from '@masknet/plugin-infra/web3' +import type { ChainId, GasOption, SchemaType, Transaction } from '@masknet/web3-shared-evm' +import type { Plugin } from '@masknet/plugin-infra' +import type { Subscription } from 'use-subscription' +import { createHub } from './Hub/hub' + +export class Hub extends HubState { + constructor( + private context: Plugin.Shared.SharedContext, + subscription: { + account?: Subscription + chainId?: Subscription + sourceType?: Subscription + currencyType?: Subscription + }, + ) { + super(createHub, subscription) + } +} diff --git a/packages/plugins/EVM/src/state/TokenIcon/TokenIconSpecialIconList.json b/packages/plugins/EVM/src/state/Hub/TokenIconSpecialIconList.json similarity index 100% rename from packages/plugins/EVM/src/state/TokenIcon/TokenIconSpecialIconList.json rename to packages/plugins/EVM/src/state/Hub/TokenIconSpecialIconList.json diff --git a/packages/plugins/EVM/src/state/Hub/hub.ts b/packages/plugins/EVM/src/state/Hub/hub.ts new file mode 100644 index 000000000000..5ffe25de3369 --- /dev/null +++ b/packages/plugins/EVM/src/state/Hub/hub.ts @@ -0,0 +1,182 @@ +import { CoinGecko, DeBank, MetaSwap, NFTScan, OpenSea, TokenList, Zerion } from '@masknet/web3-providers' +import { + FungibleToken, + NonFungibleToken, + SourceType, + FungibleAsset, + HubOptions, + NonFungibleAsset, + Pageable, + GasOptionType, + createPageable, + isSameAddress, + currySameAddress, + CurrencyType, +} from '@masknet/web3-shared-base' +import { + ChainId, + chainResolver, + formatEthereumAddress, + GasOption, + getTokenAssetBaseURLConstants, + getTokenConstants, + getTokenListConstants, + SchemaType, + Transaction, +} from '@masknet/web3-shared-evm' +import SPECIAL_ICON_LIST from './TokenIconSpecialIconList.json' +import type { EVM_Hub } from './types' + +class Hub implements EVM_Hub { + constructor( + private chainId?: ChainId, + private account?: string, + private sourceType?: SourceType, + private currencyType?: CurrencyType, + private sizePerPage = 50, + private maxPageSize = 25, + ) {} + + async getFungibleTokensFromTokenList( + chainId: ChainId, + options?: HubOptions | undefined, + ): Promise[]> { + const { FUNGIBLE_TOKEN_LISTS = [] } = getTokenListConstants(chainId) + return TokenList.fetchFungibleTokensFromTokenLists(chainId, FUNGIBLE_TOKEN_LISTS) + } + async getNonFungibleTokensFromTokenList( + chainId: ChainId, + options?: HubOptions | undefined, + ): Promise[]> { + throw new Error('Method not implemented.') + } + getGasOptions( + chainId: ChainId, + options?: HubOptions | undefined, + ): Promise> { + if (chainResolver.isSupport(chainId, 'EIP1559')) { + return MetaSwap.getGasOptions(chainId) + } + return DeBank.getGasOptions(chainId) + } + getFungibleAsset( + address: string, + options?: HubOptions | undefined, + ): Promise> { + throw new Error('Method not implemented.') + } + async getFungibleAssets( + account: string, + options?: HubOptions | undefined, + ): Promise>> { + // only the first page is available + if ((options?.page ?? 0) > 0) return createPageable([]) + try { + return DeBank.getAssets(account, options) + } catch { + return Zerion.getAssets(account, options) + } + } + async getNonFungibleAsset( + address: string, + tokenId: string, + options?: HubOptions | undefined, + ): Promise | undefined> { + return OpenSea.getAsset(address, tokenId, options) + } + getNonFungibleAssets( + account: string, + options?: HubOptions | undefined, + ): Promise>> { + try { + return OpenSea.getTokens(account, options) + } catch { + return NFTScan.getTokens(account, options) + } + } + getFungibleTokenPrice( + chainId: ChainId, + address: string, + options?: HubOptions | undefined, + ): Promise { + return CoinGecko.getTokenPrice(address, options?.currencyType ?? this.currencyType) + } + getNonFungibleTokenPrice( + chainId: ChainId, + address: string, + tokenId: string, + options?: HubOptions | undefined, + ): Promise { + throw new Error('Method not implemented.') + } + async getFungibleTokenIconURLs( + chainId: ChainId, + address: string, + options?: HubOptions | undefined, + ): Promise { + const { TOKEN_ASSET_BASE_URI = [] } = getTokenAssetBaseURLConstants(chainId) + const checkSummedAddress = formatEthereumAddress(address) + + if (isSameAddress(getTokenConstants().NATIVE_TOKEN_ADDRESS, checkSummedAddress)) { + return TOKEN_ASSET_BASE_URI.map((x) => `${x}/info/logo.png`) + } + + const specialIcon = SPECIAL_ICON_LIST.find(currySameAddress(address)) + if (specialIcon) return [specialIcon.logo_url] + + // load from remote + return TOKEN_ASSET_BASE_URI.map((x) => `${x}/assets/${checkSummedAddress}/logo.png`) + } + getNonFungibleTokenIconURLs( + chainId: ChainId, + address: string, + tokenId?: string | undefined, + options?: HubOptions | undefined, + ): Promise { + throw new Error('Method not implemented.') + } + getLatestTransactions( + chainId: ChainId, + account: string, + options?: HubOptions | undefined, + ): Promise { + throw new Error('Method not implemented.') + } + + async *getAllFungibleAssets(address: string): AsyncIterableIterator> { + for (let i = 0; i < this.maxPageSize; i += 1) { + const pageable = await this.getFungibleAssets(address, { + page: i, + size: this.sizePerPage, + }) + + yield* pageable.data + + if (pageable.data.length === 0) return + } + } + + async *getAllNonFungibleAssets(address: string): AsyncIterableIterator> { + for (let i = 0; i < this.maxPageSize; i += 1) { + const pageable = await this.getNonFungibleAssets(address, { + page: i, + size: this.sizePerPage, + }) + + yield* pageable.data + + if (pageable.data.length === 0) return + } + } +} + +export function createHub( + chainId?: ChainId, + account?: string, + sourceType?: SourceType, + currencyType?: CurrencyType, + sizePerPage?: number, + maxPageSize?: number, +) { + return new Hub(chainId, account, sourceType, currencyType, sizePerPage, maxPageSize) +} diff --git a/packages/plugins/EVM/src/state/Hub/types.ts b/packages/plugins/EVM/src/state/Hub/types.ts new file mode 100644 index 000000000000..1b46d18057e3 --- /dev/null +++ b/packages/plugins/EVM/src/state/Hub/types.ts @@ -0,0 +1,4 @@ +import type { Web3Helper } from '@masknet/plugin-infra/web3' +import type { NetworkPluginID } from '@masknet/web3-shared-base' + +export interface EVM_Hub extends Web3Helper.Web3Hub {} diff --git a/packages/plugins/EVM/src/state/Protocol/providers/MaskWallet.ts b/packages/plugins/EVM/src/state/Protocol/providers/MaskWallet.ts index b4470c88d097..e9e7590b0726 100644 --- a/packages/plugins/EVM/src/state/Protocol/providers/MaskWallet.ts +++ b/packages/plugins/EVM/src/state/Protocol/providers/MaskWallet.ts @@ -7,7 +7,7 @@ import { BaseProvider } from './Base' import type { EVM_Provider } from '../types' import { SharedContextSettings, Web3StateSettings } from '../../../settings' -const { RPC_URLS = [], RPC_WEIGHTS = [] } = getRPCConstants(ChainId.Mainnet) +const { RPC_WEIGHTS = [] } = getRPCConstants(ChainId.Mainnet) export class MaskWalletProvider extends BaseProvider implements EVM_Provider { private id = 0 diff --git a/packages/plugins/EVM/src/state/Protocol/translators/Base.ts b/packages/plugins/EVM/src/state/Protocol/translators/Base.ts index eb02bff34af0..146efaf0d5f8 100644 --- a/packages/plugins/EVM/src/state/Protocol/translators/Base.ts +++ b/packages/plugins/EVM/src/state/Protocol/translators/Base.ts @@ -17,7 +17,10 @@ export class Base implements Translator { config.gas = BigNumber.max(toHex(addGasMargin(config.gas as string).toFixed()), 21000).toFixed() // add gas price - const options = await Web3StateSettings.value.GasOptions?.getGasOptions?.(context.chainId) + const hub = await Web3StateSettings.value.Hub?.getHub?.({ + chainId: context.chainId, + }) + const options = await hub?.getGasOptions?.(context.chainId) const { [GasOptionType.SLOW]: slowOption, [GasOptionType.NORMAL]: normalOption } = options ?? {} if (chainResolver.isSupport(context.chainId, 'EIP1559')) { diff --git a/packages/plugins/EVM/src/state/TokenIcon.ts b/packages/plugins/EVM/src/state/TokenIcon.ts deleted file mode 100644 index bcc378858038..000000000000 --- a/packages/plugins/EVM/src/state/TokenIcon.ts +++ /dev/null @@ -1,28 +0,0 @@ -import type { Plugin } from '@masknet/plugin-infra' -import SPECIAL_ICON_LIST from './TokenIcon/TokenIconSpecialIconList.json' -import { currySameAddress, isSameAddress, TokenIconState } from '@masknet/web3-shared-base' -import { - ChainId, - formatEthereumAddress, - getTokenAssetBaseURLConstants, - getTokenConstants, -} from '@masknet/web3-shared-evm' - -export class TokenIcon implements TokenIconState { - constructor(context: Plugin.Shared.SharedContext) {} - - async getFungibleTokenIconURLs(chainId: ChainId, address: string) { - const { TOKEN_ASSET_BASE_URI = [] } = getTokenAssetBaseURLConstants(chainId) - const checkSummedAddress = formatEthereumAddress(address) - - if (isSameAddress(getTokenConstants().NATIVE_TOKEN_ADDRESS, checkSummedAddress)) { - return TOKEN_ASSET_BASE_URI.map((x) => `${x}/info/logo.png`) - } - - const specialIcon = SPECIAL_ICON_LIST.find(currySameAddress(address)) - if (specialIcon) return [specialIcon.logo_url] - - // load from remote - return TOKEN_ASSET_BASE_URI.map((x) => `${x}/assets/${checkSummedAddress}/logo.png`) - } -} diff --git a/packages/plugins/EVM/src/state/TokenList.ts b/packages/plugins/EVM/src/state/TokenList.ts deleted file mode 100644 index e2f407809957..000000000000 --- a/packages/plugins/EVM/src/state/TokenList.ts +++ /dev/null @@ -1,43 +0,0 @@ -import type { Subscription } from 'use-subscription' -import { getEnumAsArray } from '@dimensiondev/kit' -import type { Plugin } from '@masknet/plugin-infra' -import { TokenListState } from '@masknet/plugin-infra/web3' -import { TokenList as TokenListAPI } from '@masknet/web3-providers' -import type { Token } from '@masknet/web3-shared-base' -import { ChainId, getTokenListConstants, SchemaType } from '@masknet/web3-shared-evm' - -export class TokenList extends TokenListState { - constructor( - context: Plugin.Shared.SharedContext, - subscriptions: { - chainId?: Subscription - }, - ) { - const defaultValue = getEnumAsArray(ChainId).reduce((accumualtor, chainId) => { - accumualtor.fungibleTokens = { - ...accumualtor.fungibleTokens, - [chainId.value]: [], - } - accumualtor.nonFungibleTokens = { - ...accumualtor.nonFungibleTokens, - [chainId.value]: [], - } - return accumualtor - }, {} as Record<'fungibleTokens' | 'nonFungibleTokens', Record[]>>) - - super(context, defaultValue, subscriptions) - } - - override async getTokens(type: 'fungible' | 'nonFungible', chainId: ChainId) { - const tokenListCached = await super.getTokens(type, chainId) - if (tokenListCached.length) return tokenListCached - - const { FUNGIBLE_TOKEN_LISTS = [] } = getTokenListConstants(chainId) - super.setTokenList( - type, - chainId, - await TokenListAPI.fetchFungibleTokensFromTokenLists(chainId, FUNGIBLE_TOKEN_LISTS), - ) - return super.getTokens(type, chainId) - } -} diff --git a/packages/plugins/EVM/src/state/TokenPrice.ts b/packages/plugins/EVM/src/state/TokenPrice.ts deleted file mode 100644 index 4c28f5c690f3..000000000000 --- a/packages/plugins/EVM/src/state/TokenPrice.ts +++ /dev/null @@ -1,21 +0,0 @@ -import type { Plugin } from '@masknet/plugin-infra' -import type { ChainId } from '@masknet/web3-shared-evm' -import type { CurrencyType, TokenPriceState } from '@masknet/web3-shared-base' -import { CoinGecko } from '@masknet/web3-providers' - -export class TokenPrice implements TokenPriceState { - constructor(protected context: Plugin.Shared.SharedContext) {} - - async getFungibleTokenPrice(chainId: ChainId, address: string, currencyType?: CurrencyType | undefined) { - return CoinGecko.getTokenPrice(address, currencyType) - } - - async getNonFungibleTokenPrice( - chainId: ChainId, - address: string, - tokenId: string, - currencyType?: CurrencyType | undefined, - ) { - return 0 - } -} diff --git a/packages/plugins/EVM/src/state/index.ts b/packages/plugins/EVM/src/state/index.ts index b859efd2b769..92616603d7c3 100644 --- a/packages/plugins/EVM/src/state/index.ts +++ b/packages/plugins/EVM/src/state/index.ts @@ -1,11 +1,8 @@ import type { Plugin } from '@masknet/plugin-infra' import { AddressBook } from './AddressBook' -import { Asset } from './Asset' +import { Hub } from './Hub' import { RiskWarning } from './RiskWarning' import { Token } from './Token' -import { TokenIcon } from './TokenIcon' -import { TokenList } from './TokenList' -import { TokenPrice } from './TokenPrice' import { Transaction } from './Transaction' import { NameService } from './NameService' import { Protocol } from './Protocol' @@ -17,16 +14,23 @@ import { TransactionFormatter } from './TransactionFormatter' import { TransactionWatcher } from './TransactionWatcher' import type { EVM_Web3State } from './Protocol/types' import { IdentityService } from './IdentityService' -import { GasOptions } from './GasOptions' export function createWeb3State(context: Plugin.Shared.SharedContext): EVM_Web3State { const Provider_ = new Provider(context) + const Settings_ = new Settings(context) return { + Settings: Settings_, + Provider: Provider_, + AddressBook: new AddressBook(context, { chainId: Provider_.chainId, }), - Asset: new Asset(), + Hub: new Hub(context, { + chainId: Provider_.chainId, + account: Provider_.account, + currencyType: Settings_.currencyType, + }), IdentityService: new IdentityService(context), NameService: new NameService(context, { chainId: Provider_.chainId, @@ -34,23 +38,15 @@ export function createWeb3State(context: Plugin.Shared.SharedContext): EVM_Web3S RiskWarning: new RiskWarning(context, { account: Provider_.account, }), - Settings: new Settings(context), - GasOptions: new GasOptions(context), Token: new Token(context, { account: Provider_.account, }), - TokenIcon: new TokenIcon(context), - TokenPrice: new TokenPrice(context), - TokenList: new TokenList(context, { - chainId: Provider_.chainId, - }), Transaction: new Transaction(context, { chainId: Provider_.chainId, account: Provider_.account, }), TransactionFormatter: new TransactionFormatter(context), TransactionWatcher: new TransactionWatcher(context), - Provider: Provider_, Protocol: new Protocol(context, { chainId: Provider_.chainId, account: Provider_.account, diff --git a/packages/plugins/Flow/src/apis/fungibleAssets.ts b/packages/plugins/Flow/src/apis/fungibleAssets.ts index 24423e9655c1..a6d9f25c82ab 100644 --- a/packages/plugins/Flow/src/apis/fungibleAssets.ts +++ b/packages/plugins/Flow/src/apis/fungibleAssets.ts @@ -1,6 +1,6 @@ import { ChainId, createClient, getTokenConstants, SchemaType } from '@masknet/web3-shared-flow' import { CoinGecko } from '@masknet/web3-providers' -import { FungibleAsset, Pagination, CurrencyType, Pageable, rightShift } from '@masknet/web3-shared-base' +import { FungibleAsset, CurrencyType, Pageable, rightShift, HubOptions } from '@masknet/web3-shared-base' import { createFungibleAsset, createFungibleToken } from '../helpers' async function getTokenBalance( @@ -124,7 +124,7 @@ async function getAssetTether(chainId: ChainId, account: string) { export async function getFungibleAssets( chainId: ChainId, address: string, - pagination?: Pagination, + options?: HubOptions, ): Promise>> { const allSettled = await Promise.allSettled([ getAssetFLOW(chainId, address), diff --git a/packages/plugins/Flow/src/state/Asset.ts b/packages/plugins/Flow/src/state/Asset.ts deleted file mode 100644 index 36b9cad5c663..000000000000 --- a/packages/plugins/Flow/src/state/Asset.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { AssetState } from '@masknet/plugin-infra/web3' -import type { Web3Pagination } from '@masknet/web3-shared-base' -import { ChainId, SchemaType } from '@masknet/web3-shared-flow' -import { FlowRPC } from '../messages' - -export class Asset extends AssetState { - override async getFungibleAssets(address: string, pagination?: Web3Pagination) { - return FlowRPC.getFungibleAssets(pagination?.chainId ?? ChainId.Mainnet, address) - } -} diff --git a/packages/plugins/Flow/src/state/Hub.ts b/packages/plugins/Flow/src/state/Hub.ts new file mode 100644 index 000000000000..54f7cd93df70 --- /dev/null +++ b/packages/plugins/Flow/src/state/Hub.ts @@ -0,0 +1,20 @@ +import type { Plugin } from '@masknet/plugin-infra' +import type { Subscription } from 'use-subscription' +import { HubState } from '@masknet/plugin-infra/web3' +import type { CurrencyType, SourceType } from '@masknet/web3-shared-base' +import type { ChainId, GasOption, SchemaType, Transaction } from '@masknet/web3-shared-flow' +import { createHub } from './Hub/hub' + +export class Hub extends HubState { + constructor( + private context: Plugin.Shared.SharedContext, + subscription: { + account?: Subscription + chainId?: Subscription + sourceType?: Subscription + currencyType?: Subscription + }, + ) { + super(createHub, subscription) + } +} diff --git a/packages/plugins/Flow/src/state/Hub/hub.ts b/packages/plugins/Flow/src/state/Hub/hub.ts new file mode 100644 index 000000000000..95ff8f455c6b --- /dev/null +++ b/packages/plugins/Flow/src/state/Hub/hub.ts @@ -0,0 +1,171 @@ +import { CoinGecko } from '@masknet/web3-providers' +import type { + FungibleToken, + NonFungibleToken, + SourceType, + CurrencyType, + FungibleAsset, + HubOptions, + NonFungibleAsset, + Pageable, + GasOptionType, +} from '@masknet/web3-shared-base' +import { ChainId, GasOption, getTokenConstants, SchemaType, Transaction } from '@masknet/web3-shared-flow' +import { createFungibleToken } from '../../helpers' +import { FlowRPC } from '../../messages' +import type { FlowHub } from './types' + +class Hub implements FlowHub { + constructor( + private chainId: ChainId, + private account: string, + private sourceType?: SourceType, + private currencyType?: CurrencyType, + private sizePerPage = 50, + private maxPageSize = 25, + ) {} + + async getFungibleTokensFromTokenList( + chainId: ChainId, + options?: HubOptions | undefined, + ): Promise[]> { + const { FLOW_ADDRESS = '', FUSD_ADDRESS = '', TETHER_ADDRESS = '' } = getTokenConstants(chainId) + return [ + createFungibleToken( + chainId, + FLOW_ADDRESS, + 'Flow', + 'FLOW', + 8, + new URL('../../assets/flow.png', import.meta.url).toString(), + ), + createFungibleToken( + chainId, + FUSD_ADDRESS, + 'Flow USD', + 'FUSD', + 8, + new URL('../../assets/FUSD.png', import.meta.url).toString(), + ), + createFungibleToken( + chainId, + TETHER_ADDRESS, + 'Tether USD', + 'tUSD', + 8, + new URL('../../assets/tUSD.png', import.meta.url).toString(), + ), + ] + } + async getNonFungibleTokensFromTokenList( + chainId: ChainId, + options?: HubOptions | undefined, + ): Promise[]> { + throw new Error('Method not implemented.') + } + getGasOptions( + chainId: ChainId, + options?: HubOptions | undefined, + ): Promise> { + throw new Error('Method not implemented.') + } + getFungibleAsset( + address: string, + options?: HubOptions | undefined, + ): Promise> { + throw new Error('Method not implemented.') + } + async getFungibleAssets( + account: string, + options?: HubOptions | undefined, + ): Promise>> { + return FlowRPC.getFungibleAssets(options?.chainId ?? this.chainId, account) + } + async getNonFungibleAsset( + address: string, + tokenId: string, + options?: HubOptions | undefined, + ): Promise | undefined> { + throw new Error('Method not implemented.') + } + getNonFungibleAssets( + account: string, + options?: HubOptions | undefined, + ): Promise>> { + throw new Error('Method not implemented.') + } + getFungibleTokenPrice( + chainId: ChainId, + address: string, + options?: HubOptions | undefined, + ): Promise { + return CoinGecko.getTokenPrice(address, options?.currencyType) + } + getNonFungibleTokenPrice( + chainId: ChainId, + address: string, + tokenId: string, + options?: HubOptions | undefined, + ): Promise { + throw new Error('Method not implemented.') + } + async getFungibleTokenIconURLs( + chainId: ChainId, + address: string, + options?: HubOptions | undefined, + ): Promise { + throw new Error('Method not implemented.') + } + getNonFungibleTokenIconURLs( + chainId: ChainId, + address: string, + tokenId?: string | undefined, + options?: HubOptions | undefined, + ): Promise { + throw new Error('Method not implemented.') + } + getLatestTransactions( + chainId: ChainId, + account: string, + options?: HubOptions | undefined, + ): Promise { + throw new Error('Method not implemented.') + } + + async *getAllFungibleAssets(address: string): AsyncIterableIterator> { + for (let i = 0; i < this.maxPageSize; i += 1) { + const pageable = await this.getFungibleAssets(address, { + page: i, + size: this.sizePerPage, + }) + + yield* pageable.data + + if (pageable.data.length === 0) return + } + } + + async *getAllNonFungibleAssets(address: string): AsyncIterableIterator> { + for (let i = 0; i < this.maxPageSize; i += 1) { + const pageable = await this.getNonFungibleAssets(address, { + page: i, + size: this.sizePerPage, + }) + + yield* pageable.data + + if (pageable.data.length === 0) return + } + } +} + +export function createHub( + chainId = ChainId.Mainnet, + account = '', + sourceType?: SourceType, + currencyType?: CurrencyType, + sizePerPage?: number, + maxPageSize?: number, +) { + return new Hub(chainId, account, sourceType, currencyType, sizePerPage, maxPageSize) +} diff --git a/packages/plugins/Flow/src/state/Hub/types.ts b/packages/plugins/Flow/src/state/Hub/types.ts new file mode 100644 index 000000000000..f3add4026716 --- /dev/null +++ b/packages/plugins/Flow/src/state/Hub/types.ts @@ -0,0 +1,4 @@ +import type { Web3Helper } from '@masknet/plugin-infra/web3' +import type { NetworkPluginID } from '@masknet/web3-shared-base' + +export interface FlowHub extends Web3Helper.Web3Hub {} diff --git a/packages/plugins/Flow/src/state/TokenList.ts b/packages/plugins/Flow/src/state/TokenList.ts deleted file mode 100644 index ccc88169727d..000000000000 --- a/packages/plugins/Flow/src/state/TokenList.ts +++ /dev/null @@ -1,70 +0,0 @@ -import type { Subscription } from 'use-subscription' -import { getEnumAsArray } from '@dimensiondev/kit' -import type { Plugin } from '@masknet/plugin-infra' -import { TokenListState } from '@masknet/plugin-infra/web3' -import type { FungibleToken, Token } from '@masknet/web3-shared-base' -import { ChainId, getTokenConstants, SchemaType } from '@masknet/web3-shared-flow' -import { createFungibleToken } from '../helpers' - -export class TokenList extends TokenListState { - constructor( - context: Plugin.Shared.SharedContext, - subscriptions: { - chainId?: Subscription - }, - ) { - const defaultValue = getEnumAsArray(ChainId).reduce((accumualtor, chainId) => { - accumualtor.fungibleTokens = { - ...accumualtor.fungibleTokens, - [chainId.value]: [], - } - accumualtor.nonFungibleTokens = { - ...accumualtor.nonFungibleTokens, - [chainId.value]: [], - } - return accumualtor - }, {} as Record<'fungibleTokens' | 'nonFungibleTokens', Record[]>>) - - super(context, defaultValue, subscriptions) - } - - private composeFungibleTokenList(chainId: ChainId): FungibleToken[] { - const { FLOW_ADDRESS = '', FUSD_ADDRESS = '', TETHER_ADDRESS = '' } = getTokenConstants(chainId) - return [ - createFungibleToken( - chainId, - FLOW_ADDRESS, - 'Flow', - 'FLOW', - 8, - new URL('../assets/flow.png', import.meta.url).toString(), - ), - createFungibleToken( - chainId, - FUSD_ADDRESS, - 'Flow USD', - 'FUSD', - 8, - new URL('../assets/FUSD.png', import.meta.url).toString(), - ), - createFungibleToken( - chainId, - TETHER_ADDRESS, - 'Tether USD', - 'tUSD', - 8, - new URL('../assets/tUSD.png', import.meta.url).toString(), - ), - ] - } - - override async getTokens(type: 'fungible' | 'nonFungible', chainId: ChainId) { - if (type === 'nonFungible') throw new Error('Not implmented yet.') - - const tokenListCached = await super.getTokens('fungible', chainId) - if (tokenListCached) return tokenListCached - - super.setTokenList('fungible', chainId, this.composeFungibleTokenList(chainId)) - return super.getTokens('fungible', chainId) - } -} diff --git a/packages/plugins/Flow/src/state/index.ts b/packages/plugins/Flow/src/state/index.ts index 4e0a94a120ca..7f4f16ac66de 100644 --- a/packages/plugins/Flow/src/state/index.ts +++ b/packages/plugins/Flow/src/state/index.ts @@ -1,10 +1,9 @@ import type { Plugin } from '@masknet/plugin-infra' import { AddressBook } from './AddressBook' -import { Asset } from './Asset' +import { Hub } from './Hub' import { Provider } from './Provider' import { Protocol } from './Protocol' import { Settings } from './Settings' -import { TokenList } from './TokenList' import { Transaction } from './Transaction' import { Wallet } from './Wallet' import { Others } from './Others' @@ -16,11 +15,11 @@ export function createWeb3State(context: Plugin.Shared.SharedContext): FlowWeb3S AddressBook: new AddressBook(context, { chainId: Provider_.chainId, }), - Asset: new Asset(), - Settings: new Settings(context), - TokenList: new TokenList(context, { + Hub: new Hub(context, { chainId: Provider_.chainId, + account: Provider_.account, }), + Settings: new Settings(context), Transaction: new Transaction(context, { chainId: Provider_.chainId, account: Provider_.account, diff --git a/packages/plugins/Solana/src/apis/getFungibleAssets.ts b/packages/plugins/Solana/src/apis/getFungibleAssets.ts index 33e2c715cfba..8fafd00817a6 100644 --- a/packages/plugins/Solana/src/apis/getFungibleAssets.ts +++ b/packages/plugins/Solana/src/apis/getFungibleAssets.ts @@ -1,4 +1,4 @@ -import { FungibleAsset, CurrencyType, Pageable, Web3Pagination } from '@masknet/web3-shared-base' +import { FungibleAsset, CurrencyType, Pageable, HubOptions } from '@masknet/web3-shared-base' import { ChainId, getTokenConstants, SchemaType } from '@masknet/web3-shared-solana' import { CoinGecko } from '@masknet/web3-providers' import { TokenListProvider } from '@solana/spl-token-registry' @@ -73,11 +73,11 @@ async function getSplTokenList(chainId: ChainId, account: string) { export async function getFungibleAssets( address: string, - pagination?: Web3Pagination, + options?: HubOptions, ): Promise>> { const allSettled = await Promise.allSettled([ - getSolanaBalance(pagination?.chainId ?? ChainId.Mainnet, address).then((x) => [x]), - getSplTokenList(pagination?.chainId ?? ChainId.Mainnet, address), + getSolanaBalance(options?.chainId ?? ChainId.Mainnet, address).then((x) => [x]), + getSplTokenList(options?.chainId ?? ChainId.Mainnet, address), ]) const assets = allSettled .map((x) => (x.status === 'fulfilled' ? x.value : null)) diff --git a/packages/plugins/Solana/src/apis/getNonFungibleAssets.ts b/packages/plugins/Solana/src/apis/getNonFungibleAssets.ts index 524be44b49d4..01ec8fa4cd81 100644 --- a/packages/plugins/Solana/src/apis/getNonFungibleAssets.ts +++ b/packages/plugins/Solana/src/apis/getNonFungibleAssets.ts @@ -1,5 +1,5 @@ import { Connection } from '@metaplex/js' -import { NonFungibleAsset, NonFungibleToken, Pageable, TokenType, Web3Pagination } from '@masknet/web3-shared-base' +import { HubOptions, NonFungibleAsset, NonFungibleToken, Pageable, TokenType } from '@masknet/web3-shared-base' import { ChainId, SchemaType } from '@masknet/web3-shared-solana' import { Metadata } from '@metaplex-foundation/mpl-token-metadata' import { fetchJSON, GetProgramAccountsResponse, requestRPC, SPL_TOKEN_PROGRAM_ID } from './shared' @@ -86,9 +86,9 @@ async function getNftList(chainId: ChainId, account: string): Promise, + options?: HubOptions, ): Promise>> { - const tokens = await getNftList(pagination?.chainId ?? ChainId.Mainnet, address) + const tokens = await getNftList(options?.chainId ?? ChainId.Mainnet, address) return { currentPage: 0, diff --git a/packages/plugins/Solana/src/state/Asset.ts b/packages/plugins/Solana/src/state/Asset.ts deleted file mode 100644 index 31f396e0289c..000000000000 --- a/packages/plugins/Solana/src/state/Asset.ts +++ /dev/null @@ -1,14 +0,0 @@ -import type { Web3Pagination } from '@masknet/web3-shared-base' -import { AssetState } from '@masknet/plugin-infra/web3' -import type { ChainId, SchemaType } from '@masknet/web3-shared-solana' -import { SolanaRPC } from '../messages' - -export class Asset extends AssetState { - override async getFungibleAssets(address: string, pagination?: Web3Pagination) { - return SolanaRPC.getFungibleAssets(address, pagination) - } - - override async getNonFungibleAssets(address: string, pagination?: Web3Pagination) { - return SolanaRPC.getNonFungibleAssets(address, pagination) - } -} diff --git a/packages/plugins/Solana/src/state/Hub.ts b/packages/plugins/Solana/src/state/Hub.ts new file mode 100644 index 000000000000..76f7c156be06 --- /dev/null +++ b/packages/plugins/Solana/src/state/Hub.ts @@ -0,0 +1,20 @@ +import type { CurrencyType, SourceType } from '@masknet/web3-shared-base' +import { HubState } from '@masknet/plugin-infra/web3' +import type { ChainId, GasOption, SchemaType, Transaction } from '@masknet/web3-shared-solana' +import type { Plugin } from '@masknet/plugin-infra' +import type { Subscription } from 'use-subscription' +import { createHub } from './Hub/hub' + +export class Hub extends HubState { + constructor( + private context: Plugin.Shared.SharedContext, + subscription: { + account?: Subscription + chainId?: Subscription + sourceType?: Subscription + currencyType?: Subscription + }, + ) { + super(createHub, subscription) + } +} diff --git a/packages/plugins/Solana/src/state/Hub/hub.ts b/packages/plugins/Solana/src/state/Hub/hub.ts new file mode 100644 index 000000000000..9bd70487b2de --- /dev/null +++ b/packages/plugins/Solana/src/state/Hub/hub.ts @@ -0,0 +1,143 @@ +import type { + FungibleToken, + NonFungibleToken, + SourceType, + FungibleAsset, + HubOptions, + NonFungibleAsset, + Pageable, + GasOptionType, + CurrencyType, +} from '@masknet/web3-shared-base' +import { ChainId, GasOption, SchemaType, Transaction } from '@masknet/web3-shared-solana' +import { SolanaRPC } from '../../messages' +import type { SolanaHub } from './types' + +class Hub implements SolanaHub { + constructor( + private chainId: ChainId, + private account: string, + private sourceType?: SourceType, + private currencyType?: CurrencyType, + private sizePerPage = 50, + private maxPageSize = 25, + ) {} + + async getFungibleTokensFromTokenList( + chainId: ChainId, + options?: HubOptions | undefined, + ): Promise[]> { + throw new Error('Method not implemented.') + } + async getNonFungibleTokensFromTokenList( + chainId: ChainId, + options?: HubOptions | undefined, + ): Promise[]> { + throw new Error('Method not implemented.') + } + getGasOptions( + chainId: ChainId, + options?: HubOptions | undefined, + ): Promise> { + throw new Error('Method not implemented.') + } + getFungibleAsset( + address: string, + options?: HubOptions | undefined, + ): Promise> { + throw new Error('Method not implemented.') + } + async getNonFungibleAsset( + address: string, + tokenId: string, + options?: HubOptions | undefined, + ): Promise | undefined> { + throw new Error('Method not implemented.') + } + async getFungibleAssets( + account: string, + options?: HubOptions | undefined, + ): Promise>> { + return SolanaRPC.getFungibleAssets(account, options) + } + getNonFungibleAssets( + account: string, + options?: HubOptions | undefined, + ): Promise>> { + return SolanaRPC.getNonFungibleAssets(account, options) + } + getFungibleTokenPrice( + chainId: ChainId, + address: string, + options?: HubOptions | undefined, + ): Promise { + throw new Error('Method not implemented.') + } + getNonFungibleTokenPrice( + chainId: ChainId, + address: string, + tokenId: string, + options?: HubOptions | undefined, + ): Promise { + throw new Error('Method not implemented.') + } + async getFungibleTokenIconURLs( + chainId: ChainId, + address: string, + options?: HubOptions | undefined, + ): Promise { + throw new Error('Method not implemented.') + } + getNonFungibleTokenIconURLs( + chainId: ChainId, + address: string, + tokenId?: string | undefined, + options?: HubOptions | undefined, + ): Promise { + throw new Error('Method not implemented.') + } + getLatestTransactions( + chainId: ChainId, + account: string, + options?: HubOptions | undefined, + ): Promise { + throw new Error('Method not implemented.') + } + + async *getAllFungibleAssets(address: string): AsyncIterableIterator> { + for (let i = 0; i < this.maxPageSize; i += 1) { + const pageable = await this.getFungibleAssets(address, { + page: i, + size: this.sizePerPage, + }) + + yield* pageable.data + + if (pageable.data.length === 0) return + } + } + + async *getAllNonFungibleAssets(address: string): AsyncIterableIterator> { + for (let i = 0; i < this.maxPageSize; i += 1) { + const pageable = await this.getNonFungibleAssets(address, { + page: i, + size: this.sizePerPage, + }) + + yield* pageable.data + + if (pageable.data.length === 0) return + } + } +} + +export function createHub( + chainId = ChainId.Mainnet, + account = '', + sourceType?: SourceType, + currencyType?: CurrencyType, + sizePerPage?: number, + maxPageSize?: number, +) { + return new Hub(chainId, account, sourceType, currencyType, sizePerPage, maxPageSize) +} diff --git a/packages/plugins/Solana/src/state/Hub/types.ts b/packages/plugins/Solana/src/state/Hub/types.ts new file mode 100644 index 000000000000..cd46aea54332 --- /dev/null +++ b/packages/plugins/Solana/src/state/Hub/types.ts @@ -0,0 +1,4 @@ +import type { Web3Helper } from '@masknet/plugin-infra/web3' +import type { NetworkPluginID } from '@masknet/web3-shared-base' + +export interface SolanaHub extends Web3Helper.Web3Hub {} diff --git a/packages/plugins/Solana/src/state/TokenList.ts b/packages/plugins/Solana/src/state/TokenList.ts deleted file mode 100644 index f2ff74506312..000000000000 --- a/packages/plugins/Solana/src/state/TokenList.ts +++ /dev/null @@ -1,33 +0,0 @@ -import type { Subscription } from 'use-subscription' -import { getEnumAsArray } from '@dimensiondev/kit' -import type { Plugin } from '@masknet/plugin-infra' -import { TokenListState } from '@masknet/plugin-infra/web3' -import type { Token } from '@masknet/web3-shared-base' -import { ChainId, SchemaType } from '@masknet/web3-shared-solana' - -export class TokenList extends TokenListState { - constructor( - protected override context: Plugin.Shared.SharedContext, - protected override subscriptions: { - chainId?: Subscription - }, - ) { - const defaultValue = getEnumAsArray(ChainId).reduce((accumualtor, chainId) => { - accumualtor.fungibleTokens = { - ...accumualtor.fungibleTokens, - [chainId.value]: [], - } - accumualtor.nonFungibleTokens = { - ...accumualtor.nonFungibleTokens, - [chainId.value]: [], - } - return accumualtor - }, {} as Record<'fungibleTokens' | 'nonFungibleTokens', Record[]>>) - - super(context, defaultValue, subscriptions) - } - - override async getFungibleTokens(chainId: ChainId) { - return [] - } -} diff --git a/packages/plugins/Solana/src/state/index.ts b/packages/plugins/Solana/src/state/index.ts index 99e69764d6b1..f8bf812946fe 100644 --- a/packages/plugins/Solana/src/state/index.ts +++ b/packages/plugins/Solana/src/state/index.ts @@ -1,10 +1,9 @@ import type { Plugin } from '@masknet/plugin-infra' import { Provider } from './Provider' import { AddressBook } from './AddressBook' -import { Asset } from './Asset' +import { Hub } from './Hub' import { Protocol } from './Protocol' import { Settings } from './Settings' -import { TokenList } from './TokenList' import { Transaction } from './Transaction' import { Wallet } from './Wallet' import { Others } from './Others' @@ -12,16 +11,18 @@ import type { SolanaWeb3State } from './Protocol/types' export function createWeb3State(context: Plugin.Shared.SharedContext): SolanaWeb3State { const Provider_ = new Provider(context) + const Settings_ = new Settings(context) return { AddressBook: new AddressBook(context, { chainId: Provider_.chainId, }), - Asset: new Asset(), - Settings: new Settings(context), - TokenList: new TokenList(context, { + Hub: new Hub(context, { chainId: Provider_.chainId, + account: Provider_.account, + currencyType: Settings_.currencyType, }), + Settings: Settings_, Transaction: new Transaction(context, { chainId: Provider_.chainId, account: Provider_.account, diff --git a/packages/shared/src/UI/components/FungibleTokenList/index.tsx b/packages/shared/src/UI/components/FungibleTokenList/index.tsx index 11909607f502..e0583e196084 100644 --- a/packages/shared/src/UI/components/FungibleTokenList/index.tsx +++ b/packages/shared/src/UI/components/FungibleTokenList/index.tsx @@ -26,6 +26,7 @@ import { NetworkPluginID, } from '@masknet/web3-shared-base' import { getFungibleTokenItem } from './FungibleTokenItem' +import { EMPTY_LIST } from '@masknet/shared-base' const DEFAULT_LIST_HEIGHT = 300 const SEARCH_KEYS = ['address', 'symbol', 'name'] @@ -68,7 +69,7 @@ export function FungibleTokenList(props: FungibleToke const account = useAccount() const chainId = useChainId(pluginID, props.chainId) const { Token, Others } = useWeb3State() as Web3Helper.Web3StateAll - const fungibleTokens = useFungibleTokensFromTokenList() + const { value: fungibleTokens = EMPTY_LIST } = useFungibleTokensFromTokenList() const trustedFungibleTokens = useTrustedFungibleTokens() const nativeToken = Others?.chainResolver.nativeCurrency(chainId) diff --git a/packages/shared/src/UI/components/TokenIcon/index.tsx b/packages/shared/src/UI/components/TokenIcon/index.tsx index a61c3e65f7dd..640a8a899307 100644 --- a/packages/shared/src/UI/components/TokenIcon/index.tsx +++ b/packages/shared/src/UI/components/TokenIcon/index.tsx @@ -2,7 +2,7 @@ import { memo } from 'react' import { Avatar, AvatarProps } from '@mui/material' import { makeStyles, useStylesExtends } from '@masknet/theme' import NO_IMAGE_COLOR from './constants' -import { useChainId, useWeb3State, Web3Helper } from '@masknet/plugin-infra/web3' +import { useChainId, useWeb3Hub, Web3Helper } from '@masknet/plugin-infra/web3' import type { NetworkPluginID } from '@masknet/web3-shared-base' import { useImageFailOver } from '../../../hooks' import { useAsyncRetry } from 'react-use' @@ -28,10 +28,10 @@ export function TokenIcon(props: TokenIconProps) { const { address, logoURL, name, AvatarProps, classes } = props const chainId = useChainId() as Web3Helper.ChainIdAll - const { TokenIcon } = useWeb3State(props.networkPluginID) as Web3Helper.Web3StateAll + const hub = useWeb3Hub(props.networkPluginID) as Web3Helper.Web3HubAll const { value: urls = EMPTY_LIST } = useAsyncRetry(async () => { - const logoURLs = await TokenIcon?.getFungibleTokenIconURLs?.(props.chainId ?? chainId, address) + const logoURLs = await hub?.getFungibleTokenIconURLs?.(props.chainId ?? chainId, address) return [logoURL, ...(logoURLs ?? [])].filter(Boolean) as string[] }, [chainId, props.chainId, address, logoURL, TokenIcon]) diff --git a/packages/web3-providers/src/NFTScan/index.ts b/packages/web3-providers/src/NFTScan/index.ts index 374ff23243d5..dab2e72d825b 100644 --- a/packages/web3-providers/src/NFTScan/index.ts +++ b/packages/web3-providers/src/NFTScan/index.ts @@ -1,5 +1,5 @@ import urlcat from 'urlcat' -import type { Web3Pagination } from '@masknet/web3-shared-base' +import type { HubOptions } from '@masknet/web3-shared-base' import { ChainId, createERC721Contract, @@ -96,7 +96,7 @@ export class NFTScanAPI implements NonFungibleTokenAPI.Provider = {}) { + async getTokens(from: string, { chainId = ChainId.Mainnet, page = 0, size = 50 }: HubOptions = {}) { const response = await fetchAsset<{ content: NFTScanAsset[] page_index: number diff --git a/packages/web3-providers/src/debank/index.ts b/packages/web3-providers/src/debank/index.ts index 1e281f7686a4..e91b9da77731 100644 --- a/packages/web3-providers/src/debank/index.ts +++ b/packages/web3-providers/src/debank/index.ts @@ -4,8 +4,8 @@ import { GasOptionType, Pageable, Transaction, - Web3Pagination, createPageable, + HubOptions, } from '@masknet/web3-shared-base' import { ChainId, formatGweiToWei, getDeBankConstants, SchemaType, GasOption } from '@masknet/web3-shared-evm' import { formatAssets, formatTransactions } from './format' @@ -66,7 +66,7 @@ export class DeBankAPI async getAssets( address: string, - pagination?: Web3Pagination, + options?: HubOptions, ): Promise>> { const response = await fetch( urlcat(DEBANK_OPEN_API, '/v1/user/token_list', { @@ -95,7 +95,7 @@ export class DeBankAPI async getTransactions( address: string, - { chainId = ChainId.Mainnet }: Web3Pagination = {}, + { chainId = ChainId.Mainnet }: HubOptions = {}, ): Promise>> { const { CHAIN_ID = '' } = getDeBankConstants(chainId) if (!CHAIN_ID) return createPageable() diff --git a/packages/web3-providers/src/opensea/index.ts b/packages/web3-providers/src/opensea/index.ts index a336b0a53d8e..89da991f36e7 100644 --- a/packages/web3-providers/src/opensea/index.ts +++ b/packages/web3-providers/src/opensea/index.ts @@ -14,7 +14,7 @@ import { OrderSide, scale10, TokenType, - Web3Pagination, + HubOptions, } from '@masknet/web3-shared-base' import { ChainId, @@ -292,7 +292,7 @@ export class OpenSeaAPI implements NonFungibleTokenAPI.Provider = {}) { const response = await fetchFromOpenSea( urlcat('/api/v1/asset/:address/:tokenId', { address, tokenId }), chainId, @@ -301,7 +301,7 @@ export class OpenSeaAPI implements NonFungibleTokenAPI.Provider = {}) { const assetContract = await fetchFromOpenSea( urlcat('/api/v1/asset_contract/:address', { address }), chainId, @@ -317,7 +317,7 @@ export class OpenSeaAPI implements NonFungibleTokenAPI.Provider = {}) { const response = await fetchFromOpenSea( urlcat('/api/v1/asset/:address/:tokenId', { address, tokenId }), chainId, @@ -326,7 +326,7 @@ export class OpenSeaAPI implements NonFungibleTokenAPI.Provider = {}) { const response = await fetchFromOpenSea<{ assets?: OpenSeaResponse[] }>( urlcat('/api/v1/assets', { owner: from, @@ -353,7 +353,7 @@ export class OpenSeaAPI implements NonFungibleTokenAPI.Provider = {}, + { chainId = ChainId.Mainnet, page, size }: HubOptions = {}, ) { const response = await fetchFromOpenSea<{ asset_events: OpenSeaAssetEvent[] @@ -373,7 +373,7 @@ export class OpenSeaAPI implements NonFungibleTokenAPI.Provider = {}, + { chainId = ChainId.Mainnet, page, size }: HubOptions = {}, ) { const response = await fetchFromOpenSea<{ orders: OpenSeaAssetOrder[] @@ -392,7 +392,7 @@ export class OpenSeaAPI implements NonFungibleTokenAPI.Provider = {}, + { chainId = ChainId.Mainnet, page = 0, size = 50 }: HubOptions = {}, ) { const response = await fetchFromOpenSea( urlcat('/api/v1/collections', { diff --git a/packages/web3-providers/src/rarible/index.ts b/packages/web3-providers/src/rarible/index.ts index 54c2243f2afc..4b7f30b698f0 100644 --- a/packages/web3-providers/src/rarible/index.ts +++ b/packages/web3-providers/src/rarible/index.ts @@ -3,10 +3,10 @@ import { first } from 'lodash-unified' import { createLookupTableResolver, CurrencyType, + HubOptions, NonFungibleAsset, NonFungibleToken, TokenType, - Web3Pagination, } from '@masknet/web3-shared-base' import { ChainId, @@ -156,7 +156,7 @@ export class RaribleAPI implements NonFungibleTokenAPI.Provider = {}) { + async getTokens(from: string, { page = 0, size = 50 }: HubOptions = {}) { const requestPath = urlcat('/protocol/v0.1/ethereum/nft/items/byOwner', { owner: from, size, @@ -188,7 +188,7 @@ export class RaribleAPI implements NonFungibleTokenAPI.Provider = {}, + // { chainId = ChainId.Mainnet }: HubOptions = {}, // ): Promise[]> { // const requestPath = urlcat('/items/:tokenAddress::tokenId/offers', { tokenAddress, tokenId }) // const orders = await fetchFromRarible(RaribleMainnetURL, requestPath, { @@ -223,7 +223,7 @@ export class RaribleAPI implements NonFungibleTokenAPI.Provider = {}, + // { chainId = ChainId.Mainnet }: HubOptions = {}, // ): Promise[]> { // const requestPath = urlcat('/items/:tokenAddress::tokenId/ownerships', { tokenAddress, tokenId }) // const assets = await fetchFromRarible(RaribleMainnetURL, requestPath) @@ -255,7 +255,7 @@ export class RaribleAPI implements NonFungibleTokenAPI.Provider = {}, + // opts: HubOptions = {}, // ) { // switch (side) { // case OrderSide.Buy: diff --git a/packages/web3-providers/src/token-list/index.ts b/packages/web3-providers/src/token-list/index.ts index 2e70e83b1d3e..c06764f9230e 100644 --- a/packages/web3-providers/src/token-list/index.ts +++ b/packages/web3-providers/src/token-list/index.ts @@ -1,4 +1,4 @@ -import { first, groupBy, uniqBy } from 'lodash-unified' +import { uniqBy } from 'lodash-unified' import { memoizePromise } from '@dimensiondev/kit' import { FungibleToken, TokenType } from '@masknet/web3-shared-base' import { ChainId, SchemaType, formatEthereumAddress, chainResolver } from '@masknet/web3-shared-evm' diff --git a/packages/web3-providers/src/types.ts b/packages/web3-providers/src/types.ts index be9fb59b2b48..fd50176e3886 100644 --- a/packages/web3-providers/src/types.ts +++ b/packages/web3-providers/src/types.ts @@ -11,14 +11,13 @@ import type { CurrencyType, Pageable, FungibleToken, - Pagination, - Web3Pagination, OrderSide, NonFungibleTokenCollection, NonFungibleTokenContract, NonFungibleTokenOrder, NonFungibleTokenEvent, GasOptionType, + HubOptions, } from '@masknet/web3-shared-base' export namespace ExplorerAPI { @@ -110,7 +109,7 @@ export namespace HistoryAPI { export interface Provider { getTransactions( address: string, - pagination?: Web3Pagination, + options?: HubOptions, ): Promise>> } } @@ -123,7 +122,7 @@ export namespace GasOptionAPI { export namespace FungibleTokenAPI { export interface Provider { - getAssets(address: string, pagination?: Pagination): Promise>> + getAssets(address: string, options?: HubOptions): Promise>> } } @@ -132,47 +131,47 @@ export namespace NonFungibleTokenAPI { getAsset?: ( address: string, tokenId: string, - pagination?: Web3Pagination, + options?: HubOptions, ) => Promise | undefined> getAssets?: (address: string) => Promise[]> getHistory?: ( address: string, tokenId: string, - pagination?: Web3Pagination, + options?: HubOptions, ) => Promise[]> getListings?: ( address: string, tokenId: string, - pagination?: Web3Pagination, + options?: HubOptions, ) => Promise[]> getOffers?: ( address: string, tokenId: string, - opts?: Web3Pagination, + opts?: HubOptions, ) => Promise[]> getOrders?: ( address: string, tokenId: string, side: OrderSide, - pagination?: Web3Pagination, + options?: HubOptions, ) => Promise[]> getToken?: ( address: string, tokenId: string, - pagination?: Web3Pagination, + options?: HubOptions, ) => Promise | undefined> getTokens?: ( from: string, - opts?: Web3Pagination, + opts?: HubOptions, ) => Promise>> getContract?: ( address: string, - opts?: Web3Pagination, + opts?: HubOptions, ) => Promise | undefined> getContractBalance?: (address: string) => Promise getCollections?: ( address: string, - pagination?: Web3Pagination, + options?: HubOptions, ) => Promise | undefined>> } } diff --git a/packages/web3-providers/src/zerion/index.ts b/packages/web3-providers/src/zerion/index.ts index 9b02197e0ef6..331df473d862 100644 --- a/packages/web3-providers/src/zerion/index.ts +++ b/packages/web3-providers/src/zerion/index.ts @@ -1,7 +1,7 @@ import io from 'socket.io-client' import { values } from 'lodash-unified' import { getEnumAsArray } from '@dimensiondev/kit' -import type { FungibleAsset, Pageable, Transaction, Web3Pagination } from '@masknet/web3-shared-base' +import type { FungibleAsset, Pageable, Transaction, HubOptions } from '@masknet/web3-shared-base' import { ChainId, getZerionConstants, SchemaType } from '@masknet/web3-shared-evm' import type { SocketRequestBody, @@ -103,7 +103,7 @@ const filterAssetType = ['compound', 'trash', 'uniswap', 'uniswap-v2', 'nft'] export class ZerionAPI implements FungibleTokenAPI.Provider, HistoryAPI.Provider { - async getAssets(address: string, pagination?: Web3Pagination) { + async getAssets(address: string, options?: HubOptions) { let result: FungibleAsset[] = [] const pairs = getEnumAsArray(ChainId).map( (x) => [x.value, getZerionConstants(x.value).ASSETS_SCOPE_NAME] as const, @@ -139,7 +139,7 @@ export class ZerionAPI async getTransactions( address: string, - pagination: Web3Pagination, + options?: HubOptions, ): Promise>> { let result: Transaction[] = [] // xdai-assets is not support diff --git a/packages/web3-shared/base/src/specs/index.ts b/packages/web3-shared/base/src/specs/index.ts index 36476ccc3c7c..461becdf308e 100644 --- a/packages/web3-shared/base/src/specs/index.ts +++ b/packages/web3-shared/base/src/specs/index.ts @@ -9,17 +9,6 @@ import type { createProviderResolver, } from '../utils' -export interface Pagination { - /** The item size of each page. */ - size?: number - /** The page index. */ - page?: number -} - -export type Web3Pagination = Pagination & { - chainId?: ChainId -} - export interface Pageable { currentPage: number hasNextPage: boolean @@ -61,6 +50,18 @@ export enum TokenType { NonFungible = 'NonFungible', } +export enum SourceType { + // FT assets + DeBank = 'DeBank', + Zerion = 'Zerion', + + // NFT assets + RSS3 = 'RSS3', + Zora = 'zora', + OpenSea = 'opensea', + NFTScan = 'NFTScan', +} + export enum TransactionStatusType { NOT_DEPEND = 1, SUCCEED = 2, @@ -349,18 +350,6 @@ export type Web3EnableRequirement = Partial< > > -export interface ConnectionOptions { - /** Designate the sub-network id of the transaction. */ - chainId?: ChainId - /** Designate the signer of the transaction. */ - account?: string - /** Designate the provider to handle the transaction. */ - providerType?: ProviderType - /** Handle on popups page. */ - popupsWindow?: boolean - /** Fragments to merge into the transaction. */ - overrides?: Partial -} export interface TransactionDescriptor { chainId: ChainId /** The transaction type */ @@ -515,7 +504,18 @@ export interface WalletProvider { export interface TransactionChecker { checkStatus(chainId: ChainId, id: string): Promise } - +export interface ConnectionOptions { + /** Designate the sub-network id of the transaction. */ + chainId?: ChainId + /** Designate the signer of the transaction. */ + account?: string + /** Designate the provider to handle the transaction. */ + providerType?: ProviderType + /** Handle on popups page. */ + popupsWindow?: boolean + /** Fragments to merge into the transaction. */ + overrides?: Partial +} export interface Connection< ChainId, SchemaType, @@ -639,6 +639,91 @@ export interface Connection< cancelRequest(hash: string, config: Transaction, options?: Web3ConnectionOptions): Promise } +export interface HubOptions { + /** The user account as the API parameter */ + account?: string + /** The chain id as the API parameter */ + chainId?: ChainId + /** The id of data provider */ + sourceType?: SourceType + /** The currency type of data */ + currencyType?: CurrencyType + /** The item size of each page. */ + size?: number + /** The page index. */ + page?: number +} + +export interface Hub> { + /** Get the fungible from built-in token list */ + getFungibleTokensFromTokenList?: (chainId: ChainId, options?: Web3HubOptions) => Promise[]> + /** Get the non-fungible from built-in token list */ + getNonFungibleTokensFromTokenList?: ( + chainId: ChainId, + options?: Web3HubOptions, + ) => Promise[]> + /** Get all gas options */ + getGasOptions?: ( + chainId: ChainId, + options?: Web3HubOptions, + ) => Promise> + /** Get a fungible asset */ + getFungibleAsset?: ( + address: string, + options?: Web3HubOptions, + ) => Promise | undefined> + /** Get an non-fungible asset */ + getNonFungibleAsset?: ( + address: string, + tokenId: string, + options?: Web3HubOptions, + ) => Promise | undefined> + /** Get fungible assets of given account with pagnaition supported. */ + getFungibleAssets?: ( + account: string, + options?: Web3HubOptions, + ) => Promise>> + /** Get non-fungible assets of given account with pagnaition supported. */ + getNonFungibleAssets?: ( + account: string, + options?: Web3HubOptions, + ) => Promise>> + /** Get all fungible assets of given account and ignore the pagnation options. */ + getAllFungibleAssets?: ( + address: string, + options?: Web3HubOptions, + ) => AsyncIterableIterator> + /** Get all non-fungible assets of given account and ignore the pagnation options. */ + getAllNonFungibleAssets?: ( + address: string, + options?: Web3HubOptions, + ) => AsyncIterableIterator> + /** Get price of a fungible token */ + getFungibleTokenPrice?: ( + chainId: ChainId, + address: string, + options?: Web3HubOptions, + ) => Promise + /** Get price of an non-fungible token */ + getNonFungibleTokenPrice?: ( + chainId: ChainId, + address: string, + tokenId: string, + options?: Web3HubOptions, + ) => Promise + /** Get token icon urls of a fungible token */ + getFungibleTokenIconURLs?: (chainId: ChainId, address: string, options?: Web3HubOptions) => Promise + /** Get token icon urls of an non-fungible token */ + getNonFungibleTokenIconURLs?: ( + chainId: ChainId, + address: string, + tokenId?: string, + options?: Web3HubOptions, + ) => Promise + /** Get the most recent transactions */ + getLatestTransactions: (chainId: ChainId, account: string, options?: Web3HubOptions) => Promise +} + export interface SettingsState { /** Is testnets valid */ allowTestnet?: Subscription @@ -646,6 +731,10 @@ export interface SettingsState { currencyType?: Subscription /** The gas options type */ gasOptionType?: Subscription + /** The source type of fungible assets */ + fungibleAssetSourceType?: Subscription + /** The source type of non-fungible assets */ + nonFungibleAssetSourceType?: Subscription } export interface AddressBookState { /** The tracked addresses of currently chosen sub-network */ @@ -667,22 +756,18 @@ export interface RiskWarningState { /** Revoke statement of designate account */ revoke?: (address: string, pluginID?: string) => Promise } -export interface AssetState { - /** Get fungible assets of given account. */ - getFungibleAssets?: ( - address: string, - pagination?: Web3Pagination, - ) => Promise>> - /** Get non-fungible assets of given account. */ - getNonFungibleAssets?: ( - address: string, - pagination?: Web3Pagination, - ) => Promise>> - /** Get all fungible assets of given account. */ - getAllFungibleAssets?: (address: string) => AsyncIterableIterator> - /** Get all non-fungible assets of given account. */ - getAllNonFungibleAssets?: (address: string) => AsyncIterableIterator> +export interface HubState< + ChainId, + SchemaType, + GasOption, + Transaction, + Web3HubOptions = HubOptions, + Web3Hub = Hub, +> { + /** Get external data hub */ + getHub?: (options: Web3HubOptions) => Promise } + export interface IdentityServiceState { /** Find all social addresses related to given social identity. */ lookup(identity: SocialIdentity): Promise @@ -693,10 +778,6 @@ export interface NameServiceState> /** get domain name of address */ reverse?: (chainId: ChainId, address: string) => Promise } -export interface GasOptionsState { - /** get all gas options */ - getGasOptions?: (chainId: ChainId, currencyType?: CurrencyType) => Promise> -} export interface TokenState { /** The user trusted fungible tokens. */ trustedFungibleTokens?: Subscription[]> @@ -716,34 +797,6 @@ export interface TokenState { /** Block a token */ blockToken?: (address: string, token: Token) => Promise } -export interface TokenPriceState { - /** get price of a fungible token */ - getFungibleTokenPrice?: (chainId: ChainId, address: string, currencyType?: CurrencyType) => Promise - /** get price of a non-fungible token */ - getNonFungibleTokenPrice?: ( - chainId: ChainId, - address: string, - tokenId: string, - currencyType?: CurrencyType, - ) => Promise -} -export interface TokenIconState { - /** get token icon urls of fungible token */ - getFungibleTokenIconURLs?: (chainId: ChainId, address: string) => Promise - /** get token icon urls of non-fungible token */ - getNonFungibleTokenIconURLs?: (chainId: ChainId, address: string, tokenId?: string) => Promise -} -export interface TokenListState { - /** The tracked fungible token list of currently chosen sub-network */ - fungibleTokens?: Subscription[]> - /** The tracked non-fungible token list of currently chosen sub-network */ - nonFungibleTokens?: Subscription[]> - - /** Get the fungible token list. */ - getFungibleTokens?: (chainId: ChainId) => Promise[]> - /** Get the non-fungible token list. */ - getNonFungibleTokens?: (chainId: ChainId) => Promise[]> -} export interface TransactionState { /** The tracked transactions of currently chosen sub-network */ transactions?: Subscription[]> @@ -795,10 +848,6 @@ export interface TransactionWatcherState { /** Update transaction status */ notifyTransaction: (id: string, status: TransactionStatusType) => void } -export interface ExplorerState { - /** Get the most recent transactions */ - getLatestTransactions: (chainId: ChainId, account: string) => Promise -} export interface ProviderState { /** The account of the currently visiting site. */ account?: Subscription diff --git a/packages/web3-shared/base/src/utils/resolver.ts b/packages/web3-shared/base/src/utils/resolver.ts index 3733c8b5d028..6101bf248b60 100644 --- a/packages/web3-shared/base/src/utils/resolver.ts +++ b/packages/web3-shared/base/src/utils/resolver.ts @@ -59,7 +59,7 @@ export function createExplorerResolver( transactionPathname = '/tx/:id', domainPathname = '/address/:domain', fungibleTokenPathname = '/address/:address', - nonFungibleTokenPathname = '/address/:address', + nonFungibleTokenPathname = '/nft/:address/:tokenId', }: ExplorerRoutes = {}, ) { const getExploroerURL = (chainId: ChainId) => { diff --git a/packages/web3-shared/flow/types.ts b/packages/web3-shared/flow/types.ts index accbfb591ca6..95a442dfe508 100644 --- a/packages/web3-shared/flow/types.ts +++ b/packages/web3-shared/flow/types.ts @@ -41,7 +41,6 @@ export enum TransactionStatusCode { } export type Web3 = typeof import('@blocto/fcl') -// export type Web3 = never export type Web3Provider = {} export type Signature = CompositeSignature[] export type GasOption = never