Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions packages/wallet-management/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,9 @@
"@mysten/wallet-standard": "^0.16.11",
"@solana/wallet-adapter-base": "^0.9.27",
"@solana/web3.js": "^1.98.4",
"@tronweb3/tronwallet-abstract-adapter": "^1.1.9",
"@tronweb3/tronwallet-adapter-react-hooks": "^1.1.10",
"@tronweb3/tronwallet-adapters": "^1.2.12",
"i18next": "^25.3.6",
"mitt": "^3.0.1",
"react-i18next": "^15.6.1",
Expand Down
78 changes: 78 additions & 0 deletions packages/wallet-management/src/components/TronListItemButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import type { ChainType } from '@lifi/sdk'
import type { Adapter as TronWalletAdapter } from '@tronweb3/tronwallet-abstract-adapter'
import { useWallet as useTronWallet } from '@tronweb3/tronwallet-adapter-react-hooks'
import { useLastConnectedAccount } from '../hooks/useAccount.js'
import { useWalletManagementEvents } from '../hooks/useWalletManagementEvents.js'
import { getChainTypeIcon } from '../icons.js'
import { WalletManagementEvent } from '../types/events.js'
import { WalletTagType } from '../types/walletTagType.js'
import { CardListItemButton } from './CardListItemButton.js'
import type { WalletListItemButtonProps } from './types.js'

interface TronListItemButtonProps extends WalletListItemButtonProps {
connector: TronWalletAdapter
}

export const TronListItemButton = ({
ecosystemSelection,
connector,
tagType,
onConnected,
onConnecting,
onError,
}: TronListItemButtonProps) => {
const emitter = useWalletManagementEvents()
const { connected, connect, disconnect, select } = useTronWallet()
const connectorDisplayName = ecosystemSelection ? 'Tron' : connector.name
const { setLastConnectedAccount } = useLastConnectedAccount()

const connectWallet = async () => {
if (tagType === WalletTagType.Connected) {
onConnected?.()
return
}

try {
onConnecting?.()
if (connected) {
await disconnect()
}
select(connector.name)
// NB: select() and connect() cannot run in the same batched update
setTimeout(async () => {
await connect()
connector.once('connect', (address: string) => {
setLastConnectedAccount(connector)
emitter.emit(WalletManagementEvent.WalletConnected, {
address,
chainId: 728126428, // TODO: replace with chainId when ready
chainType: 'TVM' as unknown as ChainType, // TODO: replace with chainType when ready
connectorId: connector.name,
connectorName: connector.name,
})
})
onConnected?.()
}, 0)
} catch (error) {
onError?.(error)
}
}

return (
<CardListItemButton
key={connectorDisplayName}
icon={
ecosystemSelection
? getChainTypeIcon('TVM' as unknown as ChainType)
: (connector.icon ?? '')
}
onClick={connectWallet}
title={connectorDisplayName}
tagType={
ecosystemSelection && tagType !== WalletTagType.Connected
? undefined
: tagType
}
/>
)
}
18 changes: 17 additions & 1 deletion packages/wallet-management/src/components/WalletMenuContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
} from '@mui/material'
import type { WalletWithRequiredFeatures } from '@mysten/wallet-standard'
import type { WalletAdapter } from '@solana/wallet-adapter-base'
import type { Adapter as TronWalletAdapter } from '@tronweb3/tronwallet-abstract-adapter'
import { useMemo, useReducer, useRef } from 'react'
import { useTranslation } from 'react-i18next'
import type { Connector } from 'wagmi'
Expand All @@ -31,6 +32,7 @@ import { CardListItemButton } from './CardListItemButton.js'
import { EVMListItemButton } from './EVMListItemButton.js'
import { SuiListItemButton } from './SuiListItemButton.js'
import { SVMListItemButton } from './SVMListItemButton.js'
import { TronListItemButton } from './TronListItemButton.js'
import { UTXOListItemButton } from './UTXOListItemButton.js'
import { WalletInfoDisplay } from './WalletInfoDisplay.js'
import { WalletMenuContentEmpty } from './WalletMenuContentEmpty.js'
Expand Down Expand Up @@ -81,7 +83,9 @@ export const WalletMenuContent: React.FC<WalletMenuContentProps> = ({
const connectedConnectorIds: string[] = useMemo(() => {
return accounts
.filter((account) => account.isConnected)
.map((account) => getConnectorId(account.connector, account.chainType))
.map((account) =>
getConnectorId(account.connector, account.chainType as ChainType)
)
.filter(Boolean)
}, [accounts])

Expand Down Expand Up @@ -217,6 +221,18 @@ export const WalletMenuContent: React.FC<WalletMenuContentProps> = ({
onError={(error) => handleError(id, error)}
/>
)
case 'TVM' as unknown as ChainType: // TODO: update this type
return (
<TronListItemButton
key={key}
ecosystemSelection={ecosystemSelection}
tagType={tagType}
connector={connector as TronWalletAdapter}
onConnected={onClose}
onConnecting={() => handleConnecting(id)}
onError={(error) => handleError(id, error)}
/>
)
default:
return null
}
Expand Down
32 changes: 30 additions & 2 deletions packages/wallet-management/src/hooks/useAccount.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,16 @@ import { useCurrentWallet } from '@mysten/dapp-kit'
import type { WalletWithRequiredFeatures } from '@mysten/wallet-standard'
import type { WalletAdapter } from '@solana/wallet-adapter-base'
import { useWallet } from '@solana/wallet-adapter-react'
import type { Adapter as TronWalletAdapter } from '@tronweb3/tronwallet-abstract-adapter'
import { useWallet as useTronWallet } from '@tronweb3/tronwallet-adapter-react-hooks'
import { useMemo } from 'react'
import type { Connector } from 'wagmi'
import { useAccount as useAccountInternal } from 'wagmi'
import { create } from 'zustand'
import type { CreateConnectorFnExtended } from '../connectors/types.js'

export interface AccountBase<
CT extends ChainType,
CT extends ChainType | 'TVM', // TODO: update this type
WalletConnector = undefined,
> {
address?: string
Expand All @@ -31,13 +33,15 @@ export type EVMAccount = AccountBase<ChainType.EVM, Connector>
export type SVMAccount = AccountBase<ChainType.SVM, WalletAdapter>
export type UTXOAccount = AccountBase<ChainType.UTXO, BigmiConnector>
export type MVMAccount = AccountBase<ChainType.MVM, WalletWithRequiredFeatures>
export type TVMAccount = AccountBase<'TVM', TronWalletAdapter>
export type DefaultAccount = AccountBase<ChainType>

export type Account =
| EVMAccount
| SVMAccount
| UTXOAccount
| MVMAccount
| TVMAccount
| DefaultAccount

export interface AccountResult {
Expand Down Expand Up @@ -67,6 +71,7 @@ export type LastConnectedAccount =
| BigmiConnector
| CreateConnectorFnExtended
| WalletWithRequiredFeatures
| TronWalletAdapter
| null

interface LastConnectedAccountStore {
Expand All @@ -91,6 +96,7 @@ export const useAccount = (args?: UseAccountArgs): AccountResult => {
const wagmiAccount = useAccountInternal()
const { wallet } = useWallet()
const { currentWallet, connectionStatus } = useCurrentWallet()
const { wallet: tronWallet } = useTronWallet()
const { lastConnectedAccount } = useLastConnectedAccount()

// biome-ignore lint/correctness/useExhaustiveDependencies: run only when wallet changes
Expand Down Expand Up @@ -143,7 +149,27 @@ export const useAccount = (args?: UseAccountArgs): AccountResult => {
address: bigmiAccount.account?.address,
addresses: bigmiAccount.accounts?.map((account) => account.address),
}
const accounts = [evm, svm, utxo, sui]
const tron: TVMAccount = tronWallet?.adapter?.connected
? {
address: tronWallet.adapter.address || undefined,
chainId: 728126428,
chainType: 'TVM',
connector: tronWallet.adapter,
isConnected: Boolean(tronWallet.adapter.address),
isConnecting: false,
isReconnecting: false,
isDisconnected: !tronWallet?.adapter,
status: 'connected',
}
: {
chainType: 'TVM',
isConnected: false,
isConnecting: false,
isReconnecting: false,
isDisconnected: true,
status: 'disconnected',
}
const accounts = [evm, svm, utxo, sui, tron]
const connectedAccounts = accounts.filter(
(account) => account.isConnected && account.address
)
Expand Down Expand Up @@ -190,6 +216,8 @@ export const useAccount = (args?: UseAccountArgs): AccountResult => {
bigmiAccount.status,
bigmiAccount.account?.address,
bigmiAccount.chainId,
tronWallet?.adapter?.connected,
tronWallet?.adapter?.address,
args?.chainType,
lastConnectedAccount,
currentWallet?.accounts?.length,
Expand Down
5 changes: 5 additions & 0 deletions packages/wallet-management/src/hooks/useAccountDisconnect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { useConfig as useBigmiConfig } from '@bigmi/react'
import { ChainType } from '@lifi/sdk'
import { useDisconnectWallet } from '@mysten/dapp-kit'
import { useWallet } from '@solana/wallet-adapter-react'
import { useWallet as useTronWallet } from '@tronweb3/tronwallet-adapter-react-hooks'
import type { Config } from 'wagmi'
import { useConfig as useWagmiConfig } from 'wagmi'
import { disconnect, getAccount } from 'wagmi/actions'
Expand All @@ -17,6 +18,7 @@ export const useAccountDisconnect = () => {
const wagmiConfig = useWagmiConfig()
const { disconnect: solanaDisconnect } = useWallet()
const { mutateAsync: disconnectWallet } = useDisconnectWallet()
const { disconnect: tronDisconnect } = useTronWallet()

const handleDisconnectEVM = async (config: Config) => {
const connectedAccount = getAccount(config)
Expand Down Expand Up @@ -46,6 +48,9 @@ export const useAccountDisconnect = () => {
case ChainType.MVM:
await disconnectWallet()
break
case 'TVM' as unknown as ChainType: // TODO: update this type
await tronDisconnect()
break
}
}
}
55 changes: 47 additions & 8 deletions packages/wallet-management/src/hooks/useCombinedWallets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,16 @@ import { useConnect as useBigmiConnect } from '@bigmi/react'
import { ChainType } from '@lifi/sdk'
import type { Theme } from '@mui/material'
import { useMediaQuery } from '@mui/material'
import { useWallets } from '@mysten/dapp-kit'
import { useWallets as useSuiWallets } from '@mysten/dapp-kit'
import type { WalletWithRequiredFeatures } from '@mysten/wallet-standard'
import { WalletReadyState } from '@solana/wallet-adapter-base'
import type { Wallet } from '@solana/wallet-adapter-react'
import { useWallet } from '@solana/wallet-adapter-react'
import type { Wallet as SolanaWallet } from '@solana/wallet-adapter-react'
import { useWallet as useSolanaWallets } from '@solana/wallet-adapter-react'
import { AdapterState } from '@tronweb3/tronwallet-abstract-adapter'
import {
type Wallet as TronWallet,
useWallet as useTronWallets,
} from '@tronweb3/tronwallet-adapter-react-hooks'
import { useEffect, useState } from 'react'
import type { Connector } from 'wagmi'
import { useConnect } from 'wagmi'
Expand Down Expand Up @@ -48,8 +53,9 @@ const normalizeName = (name: string) => name.split(' ')[0].toLowerCase().trim()
const combineWalletLists = (
utxoConnectorList: BigmiConnector[],
evmConnectorList: (CreateConnectorFnExtended | Connector)[],
svmWalletList: Wallet[],
svmWalletList: SolanaWallet[],
suiWalletList: WalletWithRequiredFeatures[],
tronWalletList: TronWallet[],
walletEcosystemsOrder?: Record<string, ChainType[]>
): CombinedWallet[] => {
const walletMap = new Map<string, CombinedWallet>()
Expand Down Expand Up @@ -109,6 +115,21 @@ const combineWalletLists = (
walletMap.set(normalizedName, existing)
})

tronWalletList.forEach((tron) => {
const normalizedName = normalizeName(tron.adapter.name)
const existing = walletMap.get(normalizedName) || {
id: tron.adapter.name,
name: tron.adapter.name,
icon: tron.adapter.icon,
connectors: [] as CombinedWalletConnector[],
}
existing.connectors.push({
connector: tron.adapter,
chainType: 'TVM' as unknown as ChainType, // TODO: update this type
})
walletMap.set(normalizedName, existing)
})

let combinedWallets = Array.from(walletMap.values())
if (walletEcosystemsOrder) {
combinedWallets = combinedWallets.map((wallet) => {
Expand All @@ -133,8 +154,9 @@ export const useCombinedWallets = () => {
const walletConfig = useWalletManagementConfig()
const { connectors: wagmiConnectors } = useConnect()
const { connectors: bigmiConnectors } = useBigmiConnect()
const { wallets: solanaWallets } = useWallet()
const suiWallets = useWallets()
const { wallets: solanaWallets } = useSolanaWallets()
const suiWallets = useSuiWallets()
const { wallets: tronWallets } = useTronWallets()
const [combinedWallets, setCombinedWallets] = useState<CombinedWallets>(
() => {
return {
Expand Down Expand Up @@ -231,7 +253,7 @@ export const useCombinedWallets = () => {

const includeEcosystem = (chainType: ChainType) =>
!walletConfig.enabledChainTypes ||
walletConfig.enabledChainTypes.includes(chainType)
walletConfig.enabledChainTypes.includes(chainType as ChainType)

const installedUTXOConnectors = includeEcosystem(ChainType.UTXO)
? bigmiConnectors.filter((connector) => {
Expand Down Expand Up @@ -260,11 +282,22 @@ export const useCombinedWallets = () => {
? suiWallets
: []

// const installedTronWallets = includeEcosystem('TVM' as ChainType) // TODO: update this type
// ? tronWallets.filter((wallet) => {
// return wallet.state !== AdapterState.NotFound
// })
// : []

const installedTronWallets = tronWallets.filter((wallet) => {
return wallet.state !== AdapterState.NotFound
})

const installedCombinedWallets = combineWalletLists(
installedUTXOConnectors,
installedEVMConnectors,
installedSVMWallets,
installedSuiWallets,
installedTronWallets,
walletConfig.walletEcosystemsOrder
)

Expand All @@ -285,11 +318,16 @@ export const useCombinedWallets = () => {
return !isInstalled && isDesktopView
})

const notDetectedTRNWallets = tronWallets.filter((wallet) => {
return wallet.state === AdapterState.NotFound && isDesktopView
})

const notDetectedCombinedWallets = combineWalletLists(
notDetectedUTXOConnectors,
notDetectedEVMConnectors,
notDetectedSVMWallets,
[]
[],
notDetectedTRNWallets
)

installedCombinedWallets.sort(walletComparator)
Expand All @@ -305,6 +343,7 @@ export const useCombinedWallets = () => {
isDesktopView,
solanaWallets,
suiWallets,
tronWallets,
wagmiConnectors,
walletConfig,
])
Expand Down
4 changes: 4 additions & 0 deletions packages/wallet-management/src/icons.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ export const getChainTypeIcon = (chainType: ChainType) => {
return 'https://lifinance.github.io/types/src/assets/icons/chains/bitcoin.svg'
case ChainType.MVM:
return 'https://lifinance.github.io/types/src/assets/icons/chains/sui.svg'
case 'TVM' as unknown as ChainType: // TODO: update this type
return 'https://lifinance.github.io/types/src/assets/icons/chains/tron.svg'
default:
return ''
}
}

Expand Down
2 changes: 2 additions & 0 deletions packages/wallet-management/src/types/walletConnector.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { Connector as BigmiConnector } from '@bigmi/client'
import type { WalletWithRequiredFeatures } from '@mysten/wallet-standard'
import type { WalletAdapter } from '@solana/wallet-adapter-base'
import type { Adapter as TronWalletAdapter } from '@tronweb3/tronwallet-abstract-adapter'
import type { Connector } from 'wagmi'
import type { CreateConnectorFnExtended } from '../connectors/types.js'

Expand All @@ -10,3 +11,4 @@ export type WalletConnector =
| BigmiConnector
| CreateConnectorFnExtended
| WalletWithRequiredFeatures
| TronWalletAdapter
Loading