Skip to content
Merged
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
2 changes: 1 addition & 1 deletion src/components/scenes/Fio/FioRequestConfirmationScene.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,7 @@ export class FioRequestConfirmationConnected extends React.Component<
this.resetSlider()
showError(
`${lstrings.fio_request_error_header}: "${
error.json?.fields?.[0]?.error ?? ''
error.json?.fields?.[0]?.error ?? String(error)
}"`
)
}
Expand Down
137 changes: 48 additions & 89 deletions src/components/scenes/Fio/FioRequestListScene.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@ import { ActivityIndicator, SectionList, View } from 'react-native'
import { sprintf } from 'sprintf-js'

import { refreshAllFioAddresses } from '../../../actions/FioAddressActions'
import { FIO_ASSET_MAP } from '../../../constants/FioConstants'
import { SPECIAL_CURRENCY_INFO } from '../../../constants/WalletAndCurrencyConstants'
import { fioCodeToEdgeAsset } from '../../../constants/FioConstants'
import { formatDate, SHORT_DATE_FMT } from '../../../locales/intl'
import { lstrings } from '../../../locales/strings'
import { getExchangeDenomByCurrencyCode } from '../../../selectors/DenominationSelectors'
Expand All @@ -20,13 +19,11 @@ import {
import {
addToFioAddressCache,
cancelFioRequest,
convertFIOToEdgeCodes,
FIO_FAKE_RECORD_OBT_DATA_REQUEST,
FIO_NO_BUNDLED_ERR_CODE,
fioMakeSpend,
fioSignAndBroadcast
} from '../../../util/FioAddressUtils'
import { tokenIdsToCurrencyCodes } from '../../../util/utils'
import { SceneWrapper } from '../../common/SceneWrapper'
import { ButtonsModal } from '../../modals/ButtonsModal'
import { WalletListModal, WalletListResult } from '../../modals/WalletListModal'
Expand Down Expand Up @@ -383,47 +380,58 @@ class FioRequestList extends React.Component<Props, LocalState> {
return
}
const { account, onSelectWallet } = this.props
const availableWallets: Array<{ id: string; currencyCode: string }> = []
for (const walletId of Object.keys(account.currencyWallets)) {
const wallet = account.currencyWallets[walletId]
const { chainCode, tokenCode } = convertFIOToEdgeCodes(
account,
wallet.currencyInfo.pluginId,
fioRequest.content.chain_code.toUpperCase(),
fioRequest.content.token_code.toUpperCase()
)
const walletCurrencyCode = wallet.currencyInfo.currencyCode.toUpperCase()
if (walletCurrencyCode === tokenCode) {
availableWallets.push({ id: walletId, currencyCode: tokenCode })
if (availableWallets.length > 1) {
await this.renderDropUp(fioRequest)
return
const edgeAsset = fioCodeToEdgeAsset(
account,
fioRequest.content.chain_code.toUpperCase(),
fioRequest.content.token_code.toUpperCase()
)

// Find matching wallets:
if (edgeAsset != null) {
const { pluginId, tokenId } = edgeAsset
const walletIds = Object.keys(account.currencyWallets).filter(
walletId => {
const wallet = account.currencyWallets[walletId]
return (
wallet.currencyInfo.pluginId === pluginId &&
(tokenId == null || wallet.enabledTokenIds.includes(tokenId))
)
}
}
const enabledTokens = tokenIdsToCurrencyCodes(
wallet.currencyConfig,
wallet.enabledTokenIds
)
if (
walletCurrencyCode === chainCode &&
enabledTokens.includes(tokenCode)
) {
availableWallets.push({ id: walletId, currencyCode: tokenCode })
if (availableWallets.length > 1) {
await this.renderDropUp(fioRequest)
return

// Just do the send if we have one choice:
if (walletIds.length === 1) {
const [walletId] = walletIds
const wallet = account.currencyWallets[walletId]

const currencyCode = getCurrencyCode(wallet, tokenId)
onSelectWallet(walletId, currencyCode)
await this.sendCrypto(fioRequest, walletId, currencyCode)
return
}

// Show a modal if we have multiple choices:
if (walletIds.length > 1) {
const result = await Airship.show<WalletListResult>(bridge => (
<WalletListModal
bridge={bridge}
navigation={this.props.navigation as NavigationBase}
headerTitle={lstrings.fio_src_wallet}
allowedAssets={[edgeAsset]}
/>
))
if (result?.type === 'wallet') {
const { walletId, tokenId } = result
const wallet = account.currencyWallets[walletId]
const currencyCode = getCurrencyCode(wallet, tokenId)
onSelectWallet(walletId, currencyCode)
await this.sendCrypto(fioRequest, walletId, currencyCode)
}
return
}
}
if (availableWallets.length) {
onSelectWallet(availableWallets[0].id, availableWallets[0].currencyCode)
await this.sendCrypto(
fioRequest,
availableWallets[0].id,
availableWallets[0].currencyCode
)
return
}

// Nothing matched, so show an error:
await Airship.show<'ok' | undefined>(bridge => (
<ButtonsModal
bridge={bridge}
Expand All @@ -440,55 +448,6 @@ class FioRequestList extends React.Component<Props, LocalState> {
))
}

renderDropUp = async (selectedFioPendingRequest: FioRequest) => {
const { account, onSelectWallet } = this.props
const { content } = selectedFioPendingRequest
const pluginId =
Object.keys(FIO_ASSET_MAP).find(
pluginId =>
FIO_ASSET_MAP[pluginId].chainCode === content.chain_code.toUpperCase()
) ??
Object.keys(SPECIAL_CURRENCY_INFO).find(
pluginId =>
SPECIAL_CURRENCY_INFO[pluginId].chainCode ===
content.chain_code.toUpperCase()
)
if (pluginId == null) {
showError(
sprintf(
lstrings.fio_request_unknown_chain_code,
content.chain_code.toUpperCase()
)
)
return
}

const { tokenCode } = convertFIOToEdgeCodes(
account,
pluginId,
content.chain_code.toUpperCase(),
content.token_code.toUpperCase()
)
const tokenId = getTokenIdForced(account, pluginId, tokenCode)
const allowedAssets = [{ pluginId, tokenId }]

const result = await Airship.show<WalletListResult>(bridge => (
<WalletListModal
bridge={bridge}
navigation={this.props.navigation as NavigationBase}
headerTitle={lstrings.fio_src_wallet}
allowedAssets={allowedAssets}
/>
))
if (result?.type === 'wallet') {
const { walletId, tokenId } = result
const wallet = account.currencyWallets[walletId]
const currencyCode = getCurrencyCode(wallet, tokenId)
onSelectWallet(walletId, currencyCode)
await this.sendCrypto(selectedFioPendingRequest, walletId, currencyCode)
}
}

sendCrypto = async (
pendingRequest: FioRequest,
walletId: string,
Expand Down
61 changes: 56 additions & 5 deletions src/constants/FioConstants.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,27 @@
/**
* Special mapping that defines `chain_codes` and `token_codes` for FIO tx's
* that do not fit the typical pattern of using currency codes
*/
import { EdgeAccount } from 'edge-core-js'

import { EdgeAsset } from '../types/types'
import { getTokenId } from '../util/CurrencyInfoHelpers'
import { infoServerData } from '../util/network'

export interface FioAsset {
chainCode: string
tokenCodes: { [address: string]: string }
tokenCodes: { [tokenId: string]: string }
}

/**
* Special mapping that defines `chain_codes` and `token_codes` for FIO tx's
* that do not fit the typical pattern of using currency codes
*/
export const FIO_ASSET_MAP: { [pluginId: string]: FioAsset } = {
abstract: {
chainCode: 'ABSTRACT',
tokenCodes: {}
},
ethereum: {
chainCode: 'ETH', // Make this explicit so L2's don't take it
tokenCodes: {}
},
ethereumpo: {
chainCode: 'ETHEREUMPO',
tokenCodes: {}
Expand Down Expand Up @@ -47,3 +57,44 @@ export const FIO_ASSET_MAP: { [pluginId: string]: FioAsset } = {
}
}
}

export const fioCodeToEdgeAsset = (
account: EdgeAccount,
fioChainCode: string,
fioTokenCode: string
): EdgeAsset | undefined => {
const fioAssets = infoServerData.rollup?.fioAssets ?? FIO_ASSET_MAP

const pluginId =
// Check the table first:
Object.keys(fioAssets).find(
pluginId => fioAssets[pluginId].chainCode === fioChainCode
) ??
// Otherwise, just match the main currency code:
Object.keys(account.currencyConfig).find(
pluginId =>
account.currencyConfig[pluginId].currencyInfo.currencyCode ===
fioChainCode
)

// Bail out if we don't know about this chain:
if (pluginId == null) return

// Find the token being asked for:
const fioTokens = fioAssets[pluginId]?.tokenCodes ?? {}
const tokenId =
// If the token code matches the chain code, we want the main asset:
fioTokenCode === fioAssets[pluginId]?.chainCode
? null
: // Otherwise, check the special token mappings for this chain:
Object.keys(fioTokens).find(
tokenId => fioTokens[tokenId] === fioTokenCode
) ??
// Otherwise, do a normal token lookup:
getTokenId(account.currencyConfig[pluginId], fioTokenCode)

// Bail out if we couldn't find a matching token or main asset (null):
if (tokenId === undefined) return

return { pluginId, tokenId }
}
4 changes: 3 additions & 1 deletion src/util/CurrencyInfoHelpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,9 @@ export const getTokenIdForced = (
): EdgeTokenId => {
const tokenId = getTokenId(account.currencyConfig[pluginId], currencyCode)
if (tokenId === undefined)
throw new Error('getTokenIdForced: tokenId not found')
throw new Error(
`getTokenIdForced: tokenId not found for ${currencyCode} in ${pluginId}`
)
return tokenId
}

Expand Down
2 changes: 1 addition & 1 deletion src/util/FioAddressUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1333,7 +1333,7 @@ export const convertEdgeToFIOCodes = (
edgeTokenCode: string
) => {
const fioAssets = infoServerData.rollup?.fioAssets ?? FIO_ASSET_MAP
const fioChainCode = fioAssets[pluginId].chainCode ?? edgeChainCode
const fioChainCode = fioAssets[pluginId]?.chainCode ?? edgeChainCode
const fioTokenCode =
edgeTokenCode === edgeChainCode ? fioChainCode : edgeTokenCode

Expand Down
14 changes: 0 additions & 14 deletions src/util/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -633,20 +633,6 @@ export const getPluginIdFromChainCode = (
return pluginId
}

export function tokenIdsToCurrencyCodes(
currencyConfig: EdgeCurrencyConfig,
tokenIds: string[]
): string[] {
const { builtinTokens = {}, customTokens = {} } = currencyConfig

const out: string[] = []
for (const tokenId of tokenIds) {
const token = customTokens[tokenId] ?? builtinTokens[tokenId]
if (token != null) out.push(token.currencyCode)
}
return out
}

export interface MiniCurrencyConfig {
allTokens: EdgeTokenMap
currencyInfo: EdgeCurrencyInfo
Expand Down
Loading