Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(swap): Metadata labels #2782

Merged
merged 8 commits into from
Oct 17, 2023
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
442 changes: 221 additions & 221 deletions apps/wallet-mobile/ios/Podfile.lock

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ const supportedProviders: ReadonlyArray<Swap.SupportedProvider> = [
'sundaeswap',
'muesliswap',
'vyfi',
// 'muesliswap_v2', // TODO: enable after more clarification - right now user is not receiving tokens back when choosing this pool
'muesliswap_v2',
] as const

const LiquidityDexList = () => {
Expand Down
34 changes: 33 additions & 1 deletion apps/wallet-mobile/src/features/Swap/common/helpers.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import {createTypeGuardFromSchema, parseSafe} from '@yoroi/common'
import {Swap} from '@yoroi/types'
import {SwapApi} from '@yoroi/types/src/swap/api'
import {useMutation, UseMutationOptions} from 'react-query'
import {z} from 'zod'

import {useSelectedWallet} from '../../../SelectedWallet'
import {
Expand All @@ -11,6 +13,7 @@ import {YoroiWallet} from '../../../yoroi-wallets/cardano/types'
import {generateCIP30UtxoCbor} from '../../../yoroi-wallets/cardano/utils'
import {YoroiEntry} from '../../../yoroi-wallets/types'
import {Quantities} from '../../../yoroi-wallets/utils'

export const createYoroiEntry = (
createOrder: Swap.CreateOrderData,
address: string,
Expand All @@ -19,7 +22,7 @@ export const createYoroiEntry = (
const amountEntry = {}

const sellTokenId = createOrder.amounts.sell.tokenId
// summing fees is missing the frontend fee
// TODO Frontend Fee is not added. Once will be defined needs to be added here
if (sellTokenId === wallet.primaryTokenInfo.id) {
amountEntry[sellTokenId] = Quantities.sum([
createOrder.selectedPool.deposit.quantity,
Expand Down Expand Up @@ -66,3 +69,32 @@ export const useCancelOrderWithHw = (
cancelOrder: mutation.mutate,
}
}

export type OrderTxMetadata = {
sellTokenId: string
buyTokenId: string
sellQuantity: string
buyQuantity: string
provider: string
}

const OrderTxMetadataSchema: z.ZodSchema<OrderTxMetadata> = z.object({
sellTokenId: z.string(),
buyTokenId: z.string(),
sellQuantity: z.string(),
buyQuantity: z.string(),
provider: z.string(),
})

const isOrderTxMetadata = createTypeGuardFromSchema(OrderTxMetadataSchema)

/**
* Parses and validates a JSON metadata string, transforming it into a structure compliant with MappedRawOrder['metadata'].
*
* @param metadataJson - The JSON string representation of metadata.
* @returns The parsed metadata object or null if parsing fails or validation fails.
*/
export const parseOrderTxMetadata = (metadataJson: string): OrderTxMetadata | null => {
const parsedMetadata = parseSafe(metadataJson)
return isOrderTxMetadata(parsedMetadata) ? parsedMetadata : null
}
1 change: 0 additions & 1 deletion apps/wallet-mobile/src/features/Swap/common/useSwapTx.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ export const useSwapTx = (options?: UseMutationOptions<YoroiUnsignedTx, Error, {
sellQuantity: orderData.amounts.sell.quantity,
buyTokenId: orderData.amounts.buy.tokenId,
buyQuantity: orderData.amounts.buy.quantity,
feeTokenId: pool?.deposit.tokenId,
}),
),
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ export const CreateOrder = () => {
const orderResult: Swap.CreateOrderData | undefined = makePossibleMarketOrder(
orderDetails.sell,
orderDetails.buy,
orderDetails.pools,
orderDetails.selectedPool,
orderDetails.slippage,
orderDetails.address,
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import _ from 'lodash'
import {capitalize} from 'lodash'
import React from 'react'
import {useIntl} from 'react-intl'
import {Alert, StyleSheet, TouchableOpacity, View} from 'react-native'
import {StyleSheet, TouchableOpacity, View} from 'react-native'
import {FlatList} from 'react-native-gesture-handler'

import {
Expand All @@ -25,6 +25,7 @@ import {useSync, useTokenInfo, useTransactionInfos} from '../../../../../yoroi-w
import {TransactionInfo, TxMetadataInfo} from '../../../../../yoroi-wallets/types'
import {asQuantity, openInExplorer, Quantities} from '../../../../../yoroi-wallets/utils'
import {Counter} from '../../../common/Counter/Counter'
import {parseOrderTxMetadata} from '../../../common/helpers'
import {PoolIcon} from '../../../common/PoolIcon/PoolIcon'
import {useStrings} from '../../../common/strings'

Expand All @@ -46,35 +47,30 @@ const compareByDate = (a: MappedRawOrder, b: MappedRawOrder) => {
return new Date(b.date).getTime() - new Date(a.date).getTime()
}

const findCompletedOrderTx = (transactions: TransactionInfo[], onError: (err: Error) => void): MappedRawOrder[] => {
const findCompletedOrderTx = (transactions: TransactionInfo[]): MappedRawOrder[] => {
const sentTransactions = transactions.filter((tx) => tx.direction === 'SENT')
const receivedTransactions = transactions.filter((tx) => tx.direction === 'RECEIVED')

const filteredTx = sentTransactions
.reduce((acc, sentTx) => {
const result: {id?: string; metadata?: TxMetadataInfo; date?: string} = {}
const result: TxMetadataInfo = {}
receivedTransactions.forEach((receivedTx) => {
receivedTx.inputs.forEach((input) => {
if (Boolean(input.id) && input?.id?.slice(0, -1) === sentTx?.id && receivedTx.metadata !== null) {
if (Boolean(input.id) && input?.id?.slice(0, -1) === sentTx?.id && receivedTx.metadata?.['674'] !== null) {
result['id'] = sentTx?.id
result['metadata'] = sentTx?.metadata
result['date'] = receivedTx?.lastUpdatedAt
const metadata = parseOrderTxMetadata(sentTx?.metadata?.['674'])
if (metadata) {
result['metadata'] = metadata
return acc.push(result as MappedRawOrder)
}
}
})
})

if (result['id'] !== undefined && result['metadata'] !== undefined) {
try {
const metadata = JSON.parse(result.metadata as string)
result['metadata'] = metadata
return acc.concat(result as MappedRawOrder)
} catch (error) {
onError(error as Error)
}
}
return acc
}, [] as Array<MappedRawOrder>)
.sort(compareByDate)

return filteredTx.filter((tx) => tx.metadata !== null).sort(compareByDate)
}

Expand All @@ -85,9 +81,7 @@ export const CompletedOrders = () => {

const transactionsInfos = useTransactionInfos(wallet)

const completeOrders = findCompletedOrderTx(Object.values(transactionsInfos), (error: Error) => {
Alert.alert(strings.generalErrorTitle, strings.generalErrorMessage(error))
})
const completeOrders = findCompletedOrderTx(Object.values(transactionsInfos))

const {track} = useMetrics()

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import {isArray, isString} from '@yoroi/common'
import assert from 'assert'
import {BigNumber} from 'bignumber.js'

Expand Down Expand Up @@ -90,7 +91,21 @@ export const processTxHistoryData = (
memo: string | null,
defaultAsset: DefaultAsset,
): TransactionInfo => {
const metadata = tx.metadata?.[0]?.map_json.msg?.join('') ?? null
const metadata = tx.metadata?.reduce<TransactionInfo['metadata']>(
(metadatas: TransactionInfo['metadata'], metadata) => {
if (metadata?.label && metadatas != null) {
if (isArray(metadata?.map_json?.msg)) {
metadatas[metadata.label] = metadata.map_json.msg.join('')
}
if (isString(metadata?.map_json?.msg)) {
metadatas[metadata.label] = metadata.map_json.msg
}
}
return metadatas
},
{},
)

const _strToDefaultMultiAsset = (amount: string) => strToDefaultMultiAsset(amount, networkId, defaultAsset)
// collateral
const collateral = tx.collateralInputs || []
Expand Down Expand Up @@ -268,6 +283,6 @@ export const processTxHistoryData = (
tokens,
blockNumber: tx.blockNum ?? 0,
memo,
metadata: metadata ?? null,
metadata,
}
}
4 changes: 4 additions & 0 deletions apps/wallet-mobile/src/yoroi-wallets/mocks/transaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ export const mockTransactionInfos: Record<string, TransactionInfo> = {
},
},
memo: null,
metadata: {},
},
'5e7eff1b687f538066ea08938e91ba562c88dc817782816a1fc6f1560d8905e8': {
id: '5e7eff1b687f538066ea08938e91ba562c88dc817782816a1fc6f1560d8905e8',
Expand Down Expand Up @@ -193,6 +194,7 @@ export const mockTransactionInfos: Record<string, TransactionInfo> = {
},
},
memo: null,
metadata: {},
},
'0953a5e90889ed0b2ea1e3230cccde871d90c17868aea22300716ecaeec93096': {
id: '0953a5e90889ed0b2ea1e3230cccde871d90c17868aea22300716ecaeec93096',
Expand Down Expand Up @@ -289,6 +291,7 @@ export const mockTransactionInfos: Record<string, TransactionInfo> = {
},
},
memo: null,
metadata: {},
},
}

Expand Down Expand Up @@ -388,6 +391,7 @@ export const mockTransactionInfo = (transaction?: Partial<TransactionInfo>): Tra
},
},
memo: null,
metadata: {},
...transaction,
}
}
Expand Down
6 changes: 3 additions & 3 deletions apps/wallet-mobile/src/yoroi-wallets/types/other.ts
Original file line number Diff line number Diff line change
Expand Up @@ -398,8 +398,8 @@ export const TRANSACTION_STATUS = {
}
export type TransactionStatus = (typeof TRANSACTION_STATUS)[keyof typeof TRANSACTION_STATUS]

export type TxMetadata = Array<{label: string; map_json: {msg: Array<string>}}>
export type TxMetadataInfo = unknown
export type TxMetadata = Array<{label: string; map_json?: any; text_scalar?: string | null}>
export type TxMetadataInfo = Record<string, any>

export type TransactionInfo = {
id: string
Expand All @@ -417,7 +417,7 @@ export type TransactionInfo = {
tokens: Record<string, Token>
blockNumber: number
memo: null | string
metadata?: TxMetadataInfo
metadata: TxMetadataInfo | undefined
stackchain marked this conversation as resolved.
Show resolved Hide resolved
}

export type IOData = {
Expand Down
2 changes: 1 addition & 1 deletion packages/openswap/src/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,5 +119,5 @@ export const supportedProviders: ReadonlyArray<Provider> = [
'sundaeswap',
'vyfi',
'wingriders',
// 'muesliswap_v2' // TODO: enable after more clarification - right now user is not receiving tokens back when choosing this pool
'muesliswap_v2',
] as const
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {Balance, Swap} from '@yoroi/types'
import {Swap} from '@yoroi/types'

import {makePossibleMarketOrder} from './makePossibleMarketOrder'

Expand All @@ -12,7 +12,7 @@ describe('makePossibleMarketOrder', () => {
quantity: '177' as const, // the expected buy quantity becsause makePossibleMarketOrder will ignore the buy quantity
tokenId: 'tokenB',
}
const pool1: Swap.Pool = {
const bestPool1: Swap.Pool = {
tokenA: {quantity: '4500000', tokenId: 'tokenA'},
tokenB: {quantity: '9000000', tokenId: 'tokenB'},
ptPriceTokenA: '0',
Expand All @@ -27,47 +27,21 @@ describe('makePossibleMarketOrder', () => {
tokenId: '0',
},
}
const pool2: Swap.Pool = {
tokenA: {quantity: '5500000', tokenId: 'tokenA'},
tokenB: {quantity: '9000000', tokenId: 'tokenB'},
ptPriceTokenA: '0',
ptPriceTokenB: '0',
fee: '0.3',
provider: 'sundaeswap',
batcherFee: {quantity: '10', tokenId: ''},
deposit: {quantity: '1', tokenId: ''},
poolId: '0',
lpToken: {
quantity: '0',
tokenId: '0',
},
}
const pools = [pool1, pool2]

const slippage = 10
const address = '0xAddressHere'

const result = makePossibleMarketOrder(sell, buy, pools, slippage, address)
const result = makePossibleMarketOrder(
sell,
buy,
bestPool1,
slippage,
address,
)

expect(result?.selectedPool).toEqual(pool1)
expect(result?.selectedPool).toEqual(bestPool1)
expect(result?.slippage).toEqual(slippage)
expect(result?.address).toEqual(address)
expect(result?.amounts.buy.quantity).toEqual(buy.quantity)
})

it('should return undefined if no pools are provided', () => {
const sell = {
quantity: '100' as Balance.Quantity,
tokenId: 'tokenA',
}
const buy = {
quantity: '200' as Balance.Quantity,
tokenId: 'tokenB',
}
const pools: Swap.Pool[] = []
const slippage = 10
const address = '0xAddressHere'

const result = makePossibleMarketOrder(sell, buy, pools, slippage, address)
expect(result).toBeUndefined()
})
})
Loading
Loading