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
4 changes: 3 additions & 1 deletion src/app/actions/claimLinks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,8 @@ export async function getNextDepositIndex(contractVersion: string): Promise<numb
export async function claimSendLink(
pubKey: string,
recipient: string,
password: string
password: string,
waitForTx: boolean
): Promise<SendLink | { error: string }> {
const response = await fetchWithSentry(`${PEANUT_API_URL}/send-links/${pubKey}/claim`, {
method: 'POST',
Expand All @@ -97,6 +98,7 @@ export async function claimSendLink(
body: JSON.stringify({
recipient,
password,
waitForTx,
}),
})
if (!response.ok) {
Expand Down
2 changes: 1 addition & 1 deletion src/app/actions/history.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,6 @@ export async function getHistoryEntry(entryId: string, entryType: EHistoryEntryT
}

const data = await response.json()
const entry = completeHistoryEntry(data)
const entry = await completeHistoryEntry(data)
return entry
}
48 changes: 41 additions & 7 deletions src/components/Claim/Link/views/MantecaDetailsStep.view.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
'use client'

import { Button } from '@/components/0_Bruddle'
import BaseInput from '@/components/0_Bruddle/BaseInput'
import { Icon } from '@/components/Global/Icons/Icon'
import { MercadoPagoStep } from '@/types/manteca.types'
import { Dispatch, FC, SetStateAction } from 'react'
import { Dispatch, FC, SetStateAction, useState } from 'react'
import { MANTECA_COUNTRIES_CONFIG } from '@/constants'
import ValidatedInput from '@/components/Global/ValidatedInput'
import { validateCbuCvuAlias } from '@/utils/withdraw.utils'
import ErrorAlert from '@/components/Global/ErrorAlert'

interface MantecaDetailsStepProps {
setCurrentStep: Dispatch<SetStateAction<MercadoPagoStep>>
Expand All @@ -20,22 +23,53 @@ const MantecaDetailsStep: FC<MantecaDetailsStepProps> = ({
const handleOnClick = async () => {
setCurrentStep(MercadoPagoStep.REVIEW)
}
const [errorMessage, setErrorMessage] = useState<string | null>(null)
const [isDestinationAddressValid, setIsDestinationAddressValid] = useState(false)
const [isDestinationAddressChanging, setIsDestinationAddressChanging] = useState(false)

const countryConfig = MANTECA_COUNTRIES_CONFIG['AR']

const validateDestinationAddress = async (value: string) => {
value = value.trim()
if (!value) {
return false
}
const { valid, message } = validateCbuCvuAlias(value)
if (!valid) {
setErrorMessage(message!)
}
return valid
}

return (
<>
<p className="font-bold">Enter account details</p>

<BaseInput
<ValidatedInput
value={destinationAddress}
onChange={(e) => setDestinationAddress(e.target.value)}
placeholder="CVU or Alias"
onUpdate={(update) => {
setDestinationAddress(update.value)
setIsDestinationAddressValid(update.isValid)
setIsDestinationAddressChanging(update.isChanging)
if (update.isValid || update.value === '') {
setErrorMessage(null)
}
}}
placeholder={countryConfig.accountNumberLabel}
validate={validateDestinationAddress}
/>
<div className="flex items-center gap-2 text-xs text-grey-1">
<Icon name="info" width={16} height={16} />
<span>You can only withdraw to accounts under your name.</span>
</div>

<Button disabled={!destinationAddress} onClick={() => handleOnClick()} shadowSize="4">
{errorMessage && <ErrorAlert description={errorMessage} />}
<Button
disabled={
!destinationAddress || !isDestinationAddressValid || !!errorMessage || isDestinationAddressChanging
}
onClick={() => handleOnClick()}
shadowSize="4"
>
Review
</Button>
</>
Expand Down
9 changes: 5 additions & 4 deletions src/components/Claim/Link/views/MantecaReviewStep.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ const MantecaReviewStep: FC<MantecaReviewStepProps> = ({

const detailsCardRows: MantecaCardRow[] = [
{
key: 'alias',
label: 'Alias',
key: 'destinationAddress',
label: 'Destination Address',
value: destinationAddress,
allowCopy: true,
},
Expand All @@ -52,8 +52,9 @@ const MantecaReviewStep: FC<MantecaReviewStepProps> = ({
try {
setError(null)
setIsSubmitting(true)
const claimResponse = await sendLinksApi.claim(MANTECA_DEPOSIT_ADDRESS, claimLink)
const txHash = claimResponse?.claim?.txHash
const waitForTx = true
const claimResponse = await sendLinksApi.claim(MANTECA_DEPOSIT_ADDRESS, claimLink, waitForTx)
const txHash = claimResponse.claim?.txHash
if (!txHash) {
setError('Claim failed: missing transaction hash.')
return
Expand Down
4 changes: 2 additions & 2 deletions src/components/TransactionDetails/TransactionCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -89,9 +89,9 @@ const TransactionCard: React.FC<TransactionCardProps> = ({
const displayAmount = `${sign}$${formattedAmount}`

let currencyDisplayAmount: string | undefined
if (transaction.currency && transaction.currency.code !== 'USD') {
if (transaction.currency && transaction.currency.code.toUpperCase() !== 'USD') {
const formattedCurrencyAmount = formatNumberForDisplay(transaction.currency.amount, { maxDecimals: 2 })
currencyDisplayAmount = `≈ ${transaction.currency.code} ${formattedCurrencyAmount}`
currencyDisplayAmount = `≈ ${transaction.currency.code.toUpperCase()} ${formattedCurrencyAmount}`
}

return (
Expand Down
4 changes: 2 additions & 2 deletions src/services/sendLinks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -149,10 +149,10 @@ export const sendLinksApi = {
* @param destinationAddress - The destination address to claim the link to (for manteca claims)
* @returns The claim link data
*/
claim: async (recipient: string, link: string): Promise<SendLink> => {
claim: async (recipient: string, link: string, waitForTx: boolean = false): Promise<SendLink> => {
const params = getParamsFromLink(link)
const pubKey = generateKeysFromString(params.password).address
const response = await claimSendLink(pubKey, recipient, params.password)
const response = await claimSendLink(pubKey, recipient, params.password, waitForTx)
if ('error' in response) {
throw new Error(response.error)
}
Expand Down
28 changes: 24 additions & 4 deletions src/utils/history.utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { PEANUT_WALLET_TOKEN_DECIMALS, BASE_URL } from '@/constants'
import { formatUnits } from 'viem'
import { Hash } from 'viem'
import { getTokenDetails } from '@/utils'
import { getCurrencyPrice } from '@/app/actions/currency'

export enum EHistoryEntryType {
REQUEST = 'REQUEST',
Expand All @@ -19,6 +20,7 @@ export enum EHistoryEntryType {
MANTECA_QR_PAYMENT = 'MANTECA_QR_PAYMENT',
MANTECA_OFFRAMP = 'MANTECA_OFFRAMP',
MANTECA_ONRAMP = 'MANTECA_ONRAMP',
BRIDGE_GUEST_OFFRAMP = 'BRIDGE_GUEST_OFFRAMP',
}
export function historyTypeToNumber(type: EHistoryEntryType): number {
return Object.values(EHistoryEntryType).indexOf(type)
Expand Down Expand Up @@ -183,7 +185,7 @@ export function getTransactionSign(transaction: Pick<TransactionDetails, 'direct
}

/** Completes a history entry by adding additional data and formatting the amount. */
export function completeHistoryEntry(entry: HistoryEntry): HistoryEntry {
export async function completeHistoryEntry(entry: HistoryEntry): Promise<HistoryEntry> {
const extraData = entry.extraData ?? {}
let link: string = ''
let tokenSymbol: string = ''
Expand Down Expand Up @@ -230,12 +232,30 @@ export function completeHistoryEntry(entry: HistoryEntry): HistoryEntry {
}
break
}
case EHistoryEntryType.WITHDRAW:
case EHistoryEntryType.BRIDGE_ONRAMP: {
tokenSymbol = entry.tokenSymbol
usdAmount = entry.amount.toString()
if (entry.currency?.code) {
entry.currency.code = entry.currency.code.toUpperCase()
}
if (usdAmount === entry.currency?.amount && entry.currency?.code && entry.currency?.code !== 'USD') {
const price = await getCurrencyPrice(entry.currency.code)
usdAmount = (Number(entry.currency.amount) * price.sell).toString()
}
break
}
case EHistoryEntryType.BRIDGE_OFFRAMP:
case EHistoryEntryType.BRIDGE_ONRAMP:
case EHistoryEntryType.BRIDGE_GUEST_OFFRAMP:
case EHistoryEntryType.BANK_SEND_LINK_CLAIM: {
tokenSymbol = entry.tokenSymbol
usdAmount = entry.amount.toString()
usdAmount = entry.amount
if (entry.currency?.code) {
entry.currency.code = entry.currency.code.toUpperCase()
}
if (usdAmount === entry.currency?.amount && entry.currency?.code && entry.currency?.code !== 'USD') {
const price = await getCurrencyPrice(entry.currency.code)
entry.currency.amount = (Number(entry.amount) * price.buy).toString()
}
break
}
default: {
Expand Down
Loading