Skip to content
This repository has been archived by the owner on Oct 10, 2023. It is now read-only.

Commit

Permalink
[Wallet] Get history data depending on selected address using `Accoun…
Browse files Browse the repository at this point in the history
…tAddressSelector` (#1838)

- [x] Provide connected keystore / ledger addresses
- [x] Extend `Address` to `WalletAddress` to provide more data (chain + type)
- [x] Extract `WalletAddress` + `WalletType` to `shared/wallet/types`
- [x] Request history data depending on selected address
  • Loading branch information
veado authored Oct 8, 2021
1 parent 9388ba5 commit c5a9217
Show file tree
Hide file tree
Showing 77 changed files with 451 additions and 295 deletions.
6 changes: 3 additions & 3 deletions src/main/api/ledger/address.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
import TransportNodeHidSingleton from '@ledgerhq/hw-transport-node-hid-singleton'
import { Address } from '@xchainjs/xchain-client'
import { BNBChain, THORChain } from '@xchainjs/xchain-util'
import * as E from 'fp-ts/Either'

import { IPCLedgerAdddressParams, LedgerError, LedgerErrorId } from '../../../shared/api/types'
import { isError } from '../../../shared/utils/guard'
import { WalletAddress } from '../../../shared/wallet/types'
import { getAddress as getBNBAddress, verifyAddress as verifyBNBAddress } from './binance/address'
import { getAddress as getTHORAddress, verifyAddress as verifyTHORAddress } from './thorchain/address'

export const getAddress = async ({
chain,
network,
walletIndex = 0
}: IPCLedgerAdddressParams): Promise<E.Either<LedgerError, Address>> => {
}: IPCLedgerAdddressParams): Promise<E.Either<LedgerError, WalletAddress>> => {
try {
let res: E.Either<LedgerError, Address>
let res: E.Either<LedgerError, WalletAddress>
const transport = await TransportNodeHidSingleton.open()
switch (chain) {
case THORChain:
Expand Down
7 changes: 4 additions & 3 deletions src/main/api/ledger/binance/address.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,19 @@ import { crypto } from '@binance-chain/javascript-sdk'
import AppBNB from '@binance-chain/javascript-sdk/lib/ledger/ledger-app'
import type Transport from '@ledgerhq/hw-transport'
import { getDerivePath, getPrefix } from '@xchainjs/xchain-binance'
import { Address } from '@xchainjs/xchain-client'
import { BNBChain } from '@xchainjs/xchain-util'
import * as E from 'fp-ts/Either'

import { LedgerError, LedgerErrorId, Network } from '../../../../shared/api/types'
import { toClientNetwork } from '../../../../shared/utils/client'
import { isError } from '../../../../shared/utils/guard'
import { WalletAddress } from '../../../../shared/wallet/types'

export const getAddress = async (
transport: Transport,
network: Network,
walletIndex: number
): Promise<E.Either<LedgerError, Address>> => {
): Promise<E.Either<LedgerError, WalletAddress>> => {
try {
const app = new AppBNB(transport)
const derive_path = getDerivePath(walletIndex)
Expand All @@ -23,7 +24,7 @@ export const getAddress = async (
if (pk) {
// get address from pubkey
const address = crypto.getAddressFromPublicKey(pk.toString('hex'), prefix)
return E.right(address)
return E.right({ address, chain: BNBChain, type: 'ledger' })
} else {
return E.left({
errorId: LedgerErrorId.INVALID_PUBKEY,
Expand Down
10 changes: 7 additions & 3 deletions src/main/api/ledger/thorchain/address.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
import type Transport from '@ledgerhq/hw-transport'
import THORChainApp, { LedgerErrorType } from '@thorchain/ledger-thorchain'
import { Address } from '@xchainjs/xchain-client'
import { getPrefix } from '@xchainjs/xchain-thorchain'
import { THORChain } from '@xchainjs/xchain-util'
import * as E from 'fp-ts/Either'

import { LedgerError, LedgerErrorId, Network } from '../../../../shared/api/types'
import { toClientNetwork } from '../../../../shared/utils/client'
import { isError } from '../../../../shared/utils/guard'
import { WalletAddress } from '../../../../shared/wallet/types'
import { fromLedgerErrorType, PATH } from './common'

export const getAddress = async (transport: Transport, network: Network): Promise<E.Either<LedgerError, Address>> => {
export const getAddress = async (
transport: Transport,
network: Network
): Promise<E.Either<LedgerError, WalletAddress>> => {
try {
const app = new THORChainApp(transport)
const clientNetwork = toClientNetwork(network)
Expand All @@ -21,7 +25,7 @@ export const getAddress = async (transport: Transport, network: Network): Promis
msg: `Getting 'bech32Address' from Ledger's THORChain App failed`
})
}
return E.right(bech32Address)
return E.right({ address: bech32Address, chain: THORChain, type: 'ledger' })
} catch (error) {
return E.left({
errorId: LedgerErrorId.GET_ADDRESS_FAILED,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,33 +1,16 @@
import React from 'react'

import { Meta } from '@storybook/react'
import { BNBChain } from '@xchainjs/xchain-util'
import * as O from 'fp-ts/lib/Option'

import { AccountAddressSelector, WalletAddress } from './AccountAddressSelector'

const addresses: WalletAddress[] = [
{
walletAddress: 'bnb123123121',
walletType: 'ledger',
chain: BNBChain
},
{
walletAddress: 'bnb123123122',
walletType: 'ledger',
chain: BNBChain
},
{
walletAddress: 'bnb123123123',
walletType: 'keystore',
chain: BNBChain
}
]
import { MOCK_WALLET_ADDRESSES } from '../../../shared/mock/wallet'
import { AccountAddressSelector } from './AccountAddressSelector'

export const Default = () => (
<AccountAddressSelector
addresses={addresses}
addresses={MOCK_WALLET_ADDRESSES}
network={'testnet'}
selectedAddress={addresses[0]}
selectedAddress={O.some(MOCK_WALLET_ADDRESSES[0])}
onChangeAddress={() => console.log('change index')}
/>
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export const DropdownSelectorWrapper = styled.div`
border: 1px solid ${palette('primary', 0)};
border-radius: 5px;
padding-left: 7px;
cursor: pointer;
& .anticon-caret-down {
transition: transform 0.3s;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,75 +1,93 @@
import React, { useMemo } from 'react'

import { Address } from '@xchainjs/xchain-client'
import { Chain } from '@xchainjs/xchain-util'
import { Dropdown } from 'antd'
import * as A from 'fp-ts/lib/Array'
import * as FP from 'fp-ts/lib/function'
import * as O from 'fp-ts/lib/Option'
import { useIntl } from 'react-intl'

import { Network } from '../../../shared/api/types'
import { isLedgerWallet } from '../../../shared/utils/guard'
import { WalletAddress, WalletAddresses } from '../../../shared/wallet/types'
import { truncateAddress } from '../../helpers/addressHelper'
import { getChainAsset } from '../../helpers/chainHelper'
import { eqString } from '../../helpers/fp/eq'
import { WalletType } from '../../services/wallet/types'
import { eqWalletAddress } from '../../helpers/fp/eq'
import { walletTypeToI18n } from '../../services/wallet/util'
import { AssetIcon } from '../uielements/assets/assetIcon/AssetIcon'
import { Size as IconSize } from '../uielements/assets/assetIcon/AssetIcon.types'
import { WalletTypeLabel } from '../uielements/common/Common.styles'
import * as Styled from './AccountAddressSelector.styles'

export type WalletAddress = {
walletAddress: Address
walletType: WalletType
chain: Chain
}

type Props = {
selectedAddress: WalletAddress
addresses: WalletAddress[]
selectedAddress: O.Option<WalletAddress>
addresses: WalletAddresses
size?: IconSize
network: Network
onChangeAddress?: (address: Address) => void
onChangeAddress?: (address: WalletAddress) => void
}

export const AccountAddressSelector: React.FC<Props> = (props) => {
const { selectedAddress, addresses, size = 'small', network, onChangeAddress = FP.constVoid } = props
const {
selectedAddress: oSelectedAddress,
addresses,
size = 'small',
network,
onChangeAddress = FP.constVoid
} = props

const intl = useIntl()
const truncatedAddress = useMemo(
() => truncateAddress(selectedAddress.walletAddress, selectedAddress.chain, network),
[network, selectedAddress.chain, selectedAddress.walletAddress]
)

const menu = useMemo(
() => (
const menu = useMemo(() => {
const highlight = (address: WalletAddress) =>
FP.pipe(
oSelectedAddress,
O.fold(
() => false,
(selectedAddress) => eqWalletAddress.equals(address, selectedAddress)
)
)

return (
<Styled.Menu>
{addresses.map(({ walletAddress, walletType, chain }) => (
<Styled.MenuItem key={walletAddress} onClick={() => onChangeAddress(walletAddress)}>
<Styled.MenuItemWrapper highlighted={eqString.equals(selectedAddress.walletAddress, walletAddress)}>
<Styled.AssetIcon asset={getChainAsset(chain)} size={size} network={network} />
<Styled.WalletAddress>{walletAddress}</Styled.WalletAddress>
{isLedgerWallet(walletType) && (
<Styled.WalletTypeLabel>{walletTypeToI18n(walletType, intl)}</Styled.WalletTypeLabel>
)}
</Styled.MenuItemWrapper>
</Styled.MenuItem>
))}
{FP.pipe(
addresses,
A.map((walletAddress) => {
const { address, type, chain } = walletAddress
return (
<Styled.MenuItem key={address} onClick={() => onChangeAddress(walletAddress)}>
<Styled.MenuItemWrapper key={address} highlighted={highlight(walletAddress)}>
<Styled.AssetIcon asset={getChainAsset(chain)} size={size} network={network} />
<Styled.WalletAddress>{address}</Styled.WalletAddress>
{isLedgerWallet(type) && (
<Styled.WalletTypeLabel>{walletTypeToI18n(type, intl)}</Styled.WalletTypeLabel>
)}
</Styled.MenuItemWrapper>
</Styled.MenuItem>
)
})
)}
</Styled.Menu>
),
[addresses, intl, network, onChangeAddress, selectedAddress.walletAddress, size]
)
}, [addresses, intl, network, oSelectedAddress, onChangeAddress, size])

const renderSelectedAddress = FP.pipe(
oSelectedAddress,
O.fold(
() => <></>,
({ chain, type, address }) => (
<>
<AssetIcon asset={getChainAsset(chain)} size={'xsmall'} network={network} />
<Styled.TruncatedAddress>{truncateAddress(address, chain, network)}</Styled.TruncatedAddress>
{isLedgerWallet(type) && <WalletTypeLabel>{walletTypeToI18n(type, intl)}</WalletTypeLabel>}
<Styled.CaretDownOutlined />
</>
)
)
)

return (
<Dropdown overlay={menu} trigger={['click']}>
<Styled.DropdownSelectorWrapper>
<AssetIcon asset={getChainAsset(selectedAddress.chain)} size={'xsmall'} network={network} />
<Styled.TruncatedAddress>{truncatedAddress}</Styled.TruncatedAddress>
{isLedgerWallet(selectedAddress.walletType) && (
<WalletTypeLabel>{walletTypeToI18n(selectedAddress.walletType, intl)}</WalletTypeLabel>
)}
<Styled.CaretDownOutlined />
</Styled.DropdownSelectorWrapper>
<Styled.DropdownSelectorWrapper>{renderSelectedAddress}</Styled.DropdownSelectorWrapper>
</Dropdown>
)
}
2 changes: 1 addition & 1 deletion src/renderer/components/interact/Interact.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import React, { useMemo, useState } from 'react'
import { useIntl } from 'react-intl'

import { Network } from '../../../shared/api/types'
import { WalletType } from '../../services/wallet/types'
import { WalletType } from '../../../shared/wallet/types'
import * as Styled from './Interact.styles'

type Props = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@ import { useMemo, useState } from 'react'
import { Story } from '@storybook/react'
import { TxHash } from '@xchainjs/xchain-client'
import { assetAmount, AssetBNB, AssetBTC, AssetRuneNative, assetToBase } from '@xchainjs/xchain-util'
import * as O from 'fp-ts/lib/Option'

import { getMockRDValueFactory, RDStatus, rdStatusOptions } from '../../../shared/mock/rdByStatus'
import { MOCK_WALLET_ADDRESSES } from '../../../shared/mock/wallet'
import { WalletAddress } from '../../../shared/wallet/types'
import { PoolActions } from '../../services/midgard/types'
import { ErrorId } from '../../services/wallet/types'
import { PoolActionsHistory } from './PoolActionsHistory'
Expand Down Expand Up @@ -144,10 +147,15 @@ export const History: Story<{ dataStatus: RDStatus }> = ({ dataStatus }) => {
const [filter, setFilter] = useState<Filter>('ALL')
const HeaderContent = (
<WalletPoolActionsHistoryHeader
addresses={MOCK_WALLET_ADDRESSES}
selectedAddress={O.none}
network="testnet"
availableFilters={['ALL', 'SWITCH', 'DEPOSIT', 'SWAP', 'WITHDRAW', 'DONATE', 'REFUND']}
currentFilter={filter}
setFilter={setFilter}
onWalletAddressChanged={(address: WalletAddress) => {
console.log('selected address', address)
}}
openViewblockUrl={() => {
console.log('open viewblock')
return Promise.resolve(true)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,59 +1,38 @@
import React from 'react'
// TODO (@asgdx-team) Will be removed after #1810
// import { BCHChain, BNBChain, BTCChain, ETHChain, LTCChain, THORChain } from '@xchainjs/xchain-util'

import * as O from 'fp-ts/lib/Option'

import { Network } from '../../../shared/api/types'
// TODO (@asgdx-team) Will be implemented after #1810
// import { AccountAddressSelector, WalletAddress } from '../AccountAddressSelector'
import { WalletAddress, WalletAddresses } from '../../../shared/wallet/types'
import { AccountAddressSelector } from '../AccountAddressSelector'
import * as Styled from './PoolActionsHistory.styles'
import { PoolActionsHistoryFilter } from './PoolActionsHistoryFilter'
import { Filter } from './types'

// // TODO (@asgdx-team) Will be removed after #1810
// const addresses: WalletAddress[] = [
// {
// walletAddress: 'tbnb1ed04qgw3s69z90jskr3shpyn9mr0e59qdtsxqa',
// walletType: 'ledger',
// chain: BNBChain
// },
// {
// walletAddress: 'tthor13gym97tmw3axj3hpewdggy2cr288d3qffr8skg',
// walletType: 'ledger',
// chain: THORChain
// },
// {
// walletAddress: '0x33292c1d02c432d323fb62c57fb327da45e1bdde',
// walletType: 'keystore',
// chain: ETHChain
// },
// {
// walletAddress: 'tb1qtephp596jhpwrawlp67junuk347zl2cwc56xml',
// walletType: 'keystore',
// chain: BTCChain
// },
// {
// walletAddress: 'qr20g55jd7x3dalp4qxjfgfvda0nwr8cfccrgxd0dw',
// walletType: 'keystore',
// chain: BCHChain
// },
// {
// walletAddress: 'tltc1qtephp596jhpwrawlp67junuk347zl2cwpucctk',
// walletType: 'keystore',
// chain: LTCChain
// }
// ]

export type Props = {
network: Network
addresses: WalletAddresses
selectedAddress: O.Option<WalletAddress>
availableFilters: Filter[]
currentFilter: Filter
setFilter: (filter: Filter) => void
onWalletAddressChanged: (address: WalletAddress) => void
openViewblockUrl: () => Promise<boolean>
disabled?: boolean
}

export const WalletPoolActionsHistoryHeader: React.FC<Props> = (props) => {
const { availableFilters, currentFilter, setFilter, openViewblockUrl, disabled = false } = props
const {
network,
addresses,
selectedAddress,
availableFilters,
currentFilter,
setFilter,
openViewblockUrl,
onWalletAddressChanged,
disabled = false
} = props

return (
<>
Expand All @@ -64,10 +43,12 @@ export const WalletPoolActionsHistoryHeader: React.FC<Props> = (props) => {
onFilterChanged={setFilter}
disabled={disabled}
/>
{/*
TODO (@asgdx-team) Will be implemented after #1810
<AccountAddressSelector addresses={addresses} network={network} selectedAddress={addresses[0]} />
*/}
<AccountAddressSelector
addresses={addresses}
network={network}
selectedAddress={selectedAddress}
onChangeAddress={onWalletAddressChanged}
/>
</Styled.HeaderFilterContainer>
<Styled.HeaderLinkContainer>
<Styled.Headline onClick={openViewblockUrl}>
Expand Down
Loading

0 comments on commit c5a9217

Please sign in to comment.