Skip to content

Commit

Permalink
Merge pull request #4526 from EdgeApp/jon/display-txinfo
Browse files Browse the repository at this point in the history
Show EdgeTxAction Info in Transaction List
  • Loading branch information
Jon-edge authored Oct 25, 2023
2 parents 05bc90d + c310a22 commit 4cb9dd9
Show file tree
Hide file tree
Showing 9 changed files with 200 additions and 19 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
## Unreleased

- added: Paybis buy/sell in Brazil, Columbia, and Mexico
- added: EdgeTxAction information to Transaction List
- added: "Paused Wallet" visual indicator on wallet list
- added: Paybis sell to debit card
- added: Signup captcha experiment.
Expand Down
100 changes: 99 additions & 1 deletion src/actions/CategoriesActions.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { EdgeAccount } from 'edge-core-js'
import { EdgeAccount, EdgeAssetAmount, EdgeCurrencyWallet, EdgeTransaction } from 'edge-core-js'
import { sprintf } from 'sprintf-js'

import { showError } from '../components/services/AirshipInstance'
import { lstrings } from '../locales/strings'
import { ThunkAction } from '../types/reduxTypes'
import { getCurrencyCode } from '../util/CurrencyInfoHelpers'

export type Category = 'transfer' | 'exchange' | 'expense' | 'income'

Expand Down Expand Up @@ -255,3 +257,99 @@ export const defaultCategories = [
'Transfer:Mycelium',
'Transfer:Dark Wallet'
]

/**
* Given an EdgeTxAction, returns the display value for pre-filling the
* 'Category' and 'Notes' tiles, if they are not already user-modified.
*/
export const getTxActionDisplayInfo = (
tx: EdgeTransaction,
wallet: EdgeCurrencyWallet,
tokenId?: string
): { splitCategory: SplitCategory; notes?: string } | undefined => {
const { action } = tx
if (action == null) return
const { type } = action

const getCurrencyCodes = (assets: EdgeAssetAmount[]) => assets.map(asset => getCurrencyCode(wallet, asset.tokenId))

switch (type) {
case 'swap':
case 'swapOrderFill': {
// Determine if the swap destination was to a different asset or if the
// swap source was from a different asset.
const txSrcSameAsset = action.sourceAsset.tokenId === tokenId && action.sourceAsset.pluginId === wallet.currencyInfo.pluginId
const toFromStr = txSrcSameAsset ? lstrings.transaction_details_swap_to_subcat_1s : lstrings.transaction_details_swap_from_subcat_1s
const otherAsset = txSrcSameAsset ? action.destAsset : action.sourceAsset

return {
splitCategory: {
category: 'exchange',
subcategory: sprintf(toFromStr, getCurrencyCode(wallet, otherAsset.tokenId))
}
}
}
case 'swapOrderPost':
return {
splitCategory: {
category: 'expense',
subcategory: sprintf(lstrings.transaction_details_swap_order_post)
}
}
case 'swapOrderCancel':
return {
splitCategory: {
category: 'expense',
subcategory: sprintf(lstrings.transaction_details_swap_order_cancel)
}
}
case 'stake': {
let subcategory
if (action.stakeAssets.length === 1) subcategory = sprintf(lstrings.transaction_details_stake_subcat_1s, ...getCurrencyCodes(action.stakeAssets))
else if (action.stakeAssets.length === 2) subcategory = sprintf(lstrings.transaction_details_stake_subcat_2s, ...getCurrencyCodes(action.stakeAssets))
else {
console.warn(`Unsupported number of assets for '${type}' EdgeTxActionSwapType`)
return
}
return { splitCategory: { category: 'transfer', subcategory } }
}
case 'stakeOrder': {
let notes
if (action.stakeAssets.length === 1) notes = sprintf(lstrings.transaction_details_unstake_order_notes_1s, ...getCurrencyCodes(action.stakeAssets))
else if (action.stakeAssets.length === 2) notes = sprintf(lstrings.transaction_details_unstake_order_notes_2s, ...getCurrencyCodes(action.stakeAssets))
else {
console.error(`Unsupported number of assets for '${type}' EdgeTxActionSwapType`)
return
}
return {
splitCategory: { category: 'expense', subcategory: lstrings.transaction_details_stake_order_subcat },
notes
}
}
case 'unstake': {
let subcategory
if (action.stakeAssets.length === 1) subcategory = sprintf(lstrings.transaction_details_unstake_subcat_1s, ...getCurrencyCodes(action.stakeAssets))
else if (action.stakeAssets.length === 2) subcategory = sprintf(lstrings.transaction_details_unstake_subcat_2s, ...getCurrencyCodes(action.stakeAssets))
else {
console.error(`Unsupported number of assets for '${type}' EdgeTxActionSwapType`)
return
}
return { splitCategory: { category: 'transfer', subcategory } }
}
case 'unstakeOrder': {
let notes
if (action.stakeAssets.length === 1) notes = sprintf(lstrings.transaction_details_unstake_order_notes_1s, ...getCurrencyCodes(action.stakeAssets))
else if (action.stakeAssets.length === 2) notes = sprintf(lstrings.transaction_details_unstake_order_notes_2s, ...getCurrencyCodes(action.stakeAssets))
else {
console.error(`Unsupported number of assets for '${type}' EdgeTxActionSwapType`)
return
}
return {
splitCategory: { category: 'expense', subcategory: lstrings.transaction_details_unstake_order },
notes
}
}
default:
console.error(`Unsupported EdgeTxAction type: '${type}'`)
}
}
41 changes: 27 additions & 14 deletions src/components/scenes/TransactionDetailsScene.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ import FastImage from 'react-native-fast-image'
import IonIcon from 'react-native-vector-icons/Ionicons'
import { sprintf } from 'sprintf-js'

import { formatCategory, joinCategory, splitCategory } from '../../actions/CategoriesActions'
import { formatCategory, getTxActionDisplayInfo, joinCategory, splitCategory } from '../../actions/CategoriesActions'
import { playSendSound } from '../../actions/SoundActions'
import { TX_ACTION_LABEL_MAP } from '../../constants/txActionConstants'
import { useContactThumbnail } from '../../hooks/redux/useContactThumbnail'
import { lstrings } from '../../locales/strings'
import { EdgeSceneProps } from '../../types/routerTypes'
Expand Down Expand Up @@ -52,27 +53,38 @@ interface State {
class TransactionDetailsComponent extends React.Component<Props, State> {
constructor(props: Props) {
super(props)
const { edgeTransaction } = props.route.params
const { metadata = {} } = edgeTransaction
const { name = '', notes = '' } = metadata
const { wallet } = props
const { edgeTransaction, tokenId } = props.route.params
const { metadata } = edgeTransaction
const isSentTransaction = edgeTransaction.nativeAmount.startsWith('-') || (eq(edgeTransaction.nativeAmount, '0') && edgeTransaction.isSend)

const direction = isSentTransaction ? 'send' : 'receive'
const category = joinCategory(
splitCategory(
metadata.category,
// Pick the right default:
direction === 'receive' ? 'income' : 'expense'
)
)

// Choose a default category based on metadata or the txAction
const txActionInfo = getTxActionDisplayInfo(edgeTransaction, wallet, tokenId)
const txActionSplitCat = txActionInfo?.splitCategory
const txActionNotes = txActionInfo?.notes

const splitCat =
metadata?.category != null || txActionSplitCat == null
? splitCategory(
metadata?.category,
// Pick the right default:
direction === 'receive' ? 'income' : 'expense'
)
: txActionSplitCat

const category = joinCategory(splitCat)

const notes = metadata?.notes == null ? txActionNotes : metadata.notes

this.state = {
acceleratedTx: null,
bizId: 0,
category,
name,
name: metadata?.name ?? '',
direction,
notes
notes: notes ?? ''
}
}

Expand Down Expand Up @@ -189,11 +201,12 @@ class TransactionDetailsComponent extends React.Component<Props, State> {
render() {
const { navigation, route, theme, thumbnailPath, wallet } = this.props
const { edgeTransaction } = route.params
const { action } = edgeTransaction
const { direction, acceleratedTx, name, notes, category } = this.state
const styles = getStyles(theme)

const personLabel = direction === 'receive' ? lstrings.transaction_details_sender : lstrings.transaction_details_recipient
const personName = name !== '' ? name : personLabel
const personName = action != null ? TX_ACTION_LABEL_MAP[action.type] : name !== '' ? name : personLabel
const personHeader = sprintf(lstrings.transaction_details_person_name, personLabel)

// spendTargets recipient addresses format
Expand Down
6 changes: 4 additions & 2 deletions src/components/themed/TransactionListRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,13 @@ import { TransactionRow } from './TransactionRow'
interface Props {
navigation: NavigationBase
wallet: EdgeCurrencyWallet
tokenId?: string
currencyCode: string
transaction: EdgeTransaction
}

export function TransactionListRow(props: Props) {
const { navigation, currencyCode, wallet, transaction } = props
const { navigation, currencyCode, wallet, tokenId, transaction } = props
const { metadata } = transaction
const { name, amountFiat: defaultAmountFiat = 0 } = metadata ?? {}

Expand Down Expand Up @@ -84,7 +85,8 @@ export function TransactionListRow(props: Props) {
}
navigation.push('transactionDetails', {
edgeTransaction: transaction,
walletId: wallet.id
walletId: wallet.id,
tokenId
})
})

Expand Down
14 changes: 12 additions & 2 deletions src/components/themed/TransactionRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import Ionicons from 'react-native-vector-icons/Ionicons'
import { sprintf } from 'sprintf-js'

import { formatCategory, splitCategory } from '../../actions/CategoriesActions'
import { TX_ACTION_LABEL_MAP } from '../../constants/txActionConstants'
import { useHandler } from '../../hooks/useHandler'
import { lstrings } from '../../locales/strings'
import { triggerHaptic } from '../../util/haptic'
Expand Down Expand Up @@ -48,6 +49,7 @@ const TransactionRowComponent = (props: Props) => {
const styles = getStyles(theme)

const { canReplaceByFee = false } = wallet.currencyInfo
const { action } = transaction

const isSentTransaction = transaction.nativeAmount.startsWith('-') || (eq(transaction.nativeAmount, '0') && transaction.isSend)

Expand All @@ -58,12 +60,20 @@ const TransactionRowComponent = (props: Props) => {
let transactionText, transactionIcon, transactionStyle
if (isSentTransaction) {
transactionText =
transaction.metadata && transaction.metadata.name ? transaction.metadata.name : lstrings.fragment_transaction_list_sent_prefix + selectedCurrencyName
action != null
? TX_ACTION_LABEL_MAP[action.type]
: transaction.metadata && transaction.metadata.name
? transaction.metadata.name
: lstrings.fragment_transaction_list_sent_prefix + selectedCurrencyName
transactionIcon = <Ionicons name="arrow-up" size={theme.rem(1.25)} color={theme.negativeText} style={styles.iconArrows} />
transactionStyle = styles.iconSent
} else {
transactionText =
transaction.metadata && transaction.metadata.name ? transaction.metadata.name : lstrings.fragment_transaction_list_receive_prefix + selectedCurrencyName
action != null
? TX_ACTION_LABEL_MAP[action.type]
: transaction.metadata && transaction.metadata.name
? transaction.metadata.name
: lstrings.fragment_transaction_list_receive_prefix + selectedCurrencyName
transactionIcon = <Ionicons name="arrow-down" size={theme.rem(1.25)} color={theme.positiveText} style={styles.iconArrows} />
transactionStyle = styles.iconRequest
}
Expand Down
14 changes: 14 additions & 0 deletions src/constants/txActionConstants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { EdgeTxActionStakeType, EdgeTxActionSwapType } from 'edge-core-js'

import { lstrings } from '../locales/strings'

export const TX_ACTION_LABEL_MAP: Record<EdgeTxActionSwapType | EdgeTxActionStakeType, string> = {
swap: lstrings.transaction_details_swap,
swapOrderPost: lstrings.transaction_details_swap_order_post,
swapOrderFill: lstrings.transaction_details_swap_order_fill,
swapOrderCancel: lstrings.transaction_details_swap_order_cancel,
stake: lstrings.transaction_details_stake,
stakeOrder: lstrings.transaction_details_stake_order,
unstake: lstrings.transaction_details_unstake,
unstakeOrder: lstrings.transaction_details_unstake_order
}
22 changes: 22 additions & 0 deletions src/locales/en_US.ts
Original file line number Diff line number Diff line change
Expand Up @@ -677,6 +677,28 @@ const strings = {
transaction_details_exchange_support: 'Exchange Support',
transaction_details_exchange_support_request: '%s Support Request',
transaction_details_fee_warning: 'High Network Fees',
transaction_details_swap: 'Swap Funds',
transaction_details_swap_order_cancel: 'Swap Order Canceled',
transaction_details_swap_order_post: 'Swap Order Opened',
transaction_details_swap_order_fill: 'Swap Order Filled',
transaction_details_stake: 'Stake Funds',
transaction_details_stake_order: 'Stake Order',
transaction_details_unstake: 'Unstake Funds',
transaction_details_unstake_order: 'Unstake Order',

transaction_details_swap_to_subcat_1s: 'to %1$s',
transaction_details_swap_from_subcat_1s: 'from %1$s',
transaction_details_swap_order_notes_2s: '%1$s to %2$s',
transaction_details_stake_subcat_1s: 'Stake %1$s',
transaction_details_stake_subcat_2s: 'Stake %1$s and %2$s',
transaction_details_stake_order_notes_1s: 'Create Stake %1$s Order',
transaction_details_stake_order_notes_2s: 'Create Stake %1$s and %2$s Order',
transaction_details_stake_order_subcat: 'Create Stake Order',
transaction_details_unstake_subcat_1s: 'Unstake %1$s',
transaction_details_unstake_subcat_2s: 'Unstake %1$s and %2$s',
transaction_details_unstake_order_notes_1s: 'Create Unstake %1$s Order',
transaction_details_unstake_order_notes_2s: 'Create Unstake %1$s and %2$s Order',

my_receive_addresses_title: 'My Receive Addresses',

category_modal_title: 'Choose a Category',
Expand Down
20 changes: 20 additions & 0 deletions src/locales/strings/enUS.json
Original file line number Diff line number Diff line change
Expand Up @@ -608,6 +608,26 @@
"transaction_details_exchange_support": "Exchange Support",
"transaction_details_exchange_support_request": "%s Support Request",
"transaction_details_fee_warning": "High Network Fees",
"transaction_details_swap": "Swap Funds",
"transaction_details_swap_order_cancel": "Swap Order Canceled",
"transaction_details_swap_order_post": "Swap Order Opened",
"transaction_details_swap_order_fill": "Swap Order Filled",
"transaction_details_stake": "Stake Funds",
"transaction_details_stake_order": "Stake Order",
"transaction_details_unstake": "Unstake Funds",
"transaction_details_unstake_order": "Unstake Order",
"transaction_details_swap_to_subcat_1s": "to %1$s",
"transaction_details_swap_from_subcat_1s": "from %1$s",
"transaction_details_swap_order_notes_2s": "%1$s to %2$s",
"transaction_details_stake_subcat_1s": "Stake %1$s",
"transaction_details_stake_subcat_2s": "Stake %1$s and %2$s",
"transaction_details_stake_order_notes_1s": "Create Stake %1$s Order",
"transaction_details_stake_order_notes_2s": "Create Stake %1$s and %2$s Order",
"transaction_details_stake_order_subcat": "Create Stake Order",
"transaction_details_unstake_subcat_1s": "Unstake %1$s",
"transaction_details_unstake_subcat_2s": "Unstake %1$s and %2$s",
"transaction_details_unstake_order_notes_1s": "Create Unstake %1$s Order",
"transaction_details_unstake_order_notes_2s": "Create Unstake %1$s and %2$s Order",
"my_receive_addresses_title": "My Receive Addresses",
"category_modal_title": "Choose a Category",
"transaction_details_notes_title": "Notes",
Expand Down
1 change: 1 addition & 0 deletions src/types/routerTypes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,7 @@ export interface RouteParamList {
transactionDetails: {
edgeTransaction: EdgeTransaction
walletId: string
tokenId?: string
}
transactionList: TransactionListParams
transactionsExport: {
Expand Down

0 comments on commit 4cb9dd9

Please sign in to comment.