diff --git a/src/app/api/_data/blk-service.ts b/src/app/api/_data/blk-service.ts index c651147..1908544 100644 --- a/src/app/api/_data/blk-service.ts +++ b/src/app/api/_data/blk-service.ts @@ -17,11 +17,11 @@ import TokenPriceFeedsAbi from './_abis/TokenPriceFeedsAbi.json' // --------------------------------------------------------------------------------------------- -export async function transferAll(walletTo: string): Promise { +export async function transferAll(channelUserId: string, walletTo: string): Promise { try { // TODO: - // const data = { wallet: walletTo } - // const response = await axios.post(`${BACKEND_API_URL}/transferall`, data) + // const data = { channel_user_id: channelUserId, dst_address: walletTo } + // const response = await axios.post(`${BACKEND_API_URL}/withdraw_funds`, data) return true } catch (error) { console.error('Error transfering all funds:', error) diff --git a/src/app/api/_hooks/api-resolver.ts b/src/app/api/_hooks/api-resolver.ts index 4b19cf7..c599961 100644 --- a/src/app/api/_hooks/api-resolver.ts +++ b/src/app/api/_hooks/api-resolver.ts @@ -57,12 +57,12 @@ export const endpoints = { id: (id: string) => getFullUIEndpoint(`user/${id}`), update: (id: string) => getFullUIEndpoint(`user/${id}`), code: (id: string) => getFullUIEndpoint(`user/${id}/code`), - updateEmail: (id: string) => getFullUIEndpoint(`user/${id}/email`) + updateEmail: (id: string) => getFullUIEndpoint(`user/${id}/email`), + transferAll: (id: string) => getFullUIEndpoint(`user/${id}/transfer-all`) }, wallet: { balance: (id: string) => getFullUIEndpoint(`wallet/${id}/balance`), transactions: (id: string) => getFullUIEndpoint(`wallet/${id}/transactions`), - transferAll: (id: string) => getFullUIEndpoint(`wallet/${id}/transferAll`), nfts: { root: (id: string) => getFullUIEndpoint(`wallet/${id}/nfts`), id: (walletId: string, nftId: string) => diff --git a/src/app/api/_hooks/use-wallet.ts b/src/app/api/_hooks/use-wallet.ts index 344080e..b63be56 100644 --- a/src/app/api/_hooks/use-wallet.ts +++ b/src/app/api/_hooks/use-wallet.ts @@ -22,7 +22,9 @@ export function useGetWalletNft(walletId: string, nftId: string) { // ---------------------------------------------------------------------- -export async function transferAll(walletId: string, data: { walletTo: string }) { - const res = await post(endpoints.dashboard.wallet.transferAll(walletId), data, {}) +export async function transferAll(userId: string, data: { walletTo: string }) { + console.log('trasnfer all', userId, data) + const res = await post(endpoints.dashboard.user.transferAll(userId), data, {}) + console.log('x', res) return res } diff --git a/src/app/api/v1/wallet/[id]/transfer-all/route.ts b/src/app/api/v1/user/[id]/transfer-all/route.ts similarity index 76% rename from src/app/api/v1/wallet/[id]/transfer-all/route.ts rename to src/app/api/v1/user/[id]/transfer-all/route.ts index e09895f..0beade5 100644 --- a/src/app/api/v1/wallet/[id]/transfer-all/route.ts +++ b/src/app/api/v1/user/[id]/transfer-all/route.ts @@ -1,6 +1,9 @@ import { NextRequest, NextResponse } from 'next/server' import { transferAll } from 'src/app/api/_data/blk-service' +import { getUserById } from 'src/app/api/_data/data-service' + +import { IAccount } from 'src/types/account' // ---------------------------------------------------------------------- @@ -42,7 +45,18 @@ export async function POST(req: NextRequest, { params }: { params: IParams }) { ) } - const result: boolean = await transferAll(walletTo) + const user: IAccount | undefined = await getUserById(id) + if (!user) { + return new NextResponse( + JSON.stringify({ code: 'USER_NOT_FOUND', error: 'user not found with that id' }), + { + status: 404, + headers: { 'Content-Type': 'application/json' } + } + ) + } + + const result: boolean = await transferAll(user.id, walletTo) if (!result) { return new NextResponse( JSON.stringify({ diff --git a/src/components/hook-form/rhf-text-field.tsx b/src/components/hook-form/rhf-text-field.tsx index 8656d27..ca16036 100644 --- a/src/components/hook-form/rhf-text-field.tsx +++ b/src/components/hook-form/rhf-text-field.tsx @@ -19,11 +19,15 @@ export default function RHFTextField({ name, helperText, type, ...other }: Props { + let inputValue = event.target.value if (type === 'number') { - field.onChange(Number(event.target.value)) + field.onChange(Number(inputValue)) + } else if (type === 'wallet') { + inputValue = inputValue.replace(/[^a-zA-Z0-9]/g, '') + field.onChange(inputValue.startsWith('0x') ? inputValue : `0x${inputValue}`) } else { field.onChange(event.target.value) } diff --git a/src/layouts/common/account-popover.tsx b/src/layouts/common/account-popover.tsx index fe4be8a..b2f7097 100644 --- a/src/layouts/common/account-popover.tsx +++ b/src/layouts/common/account-popover.tsx @@ -28,7 +28,7 @@ export default function AccountPopover() { const OPTIONS = [ { label: t('menu.account'), - linkTo: paths.dashboard.user.account + linkTo: paths.dashboard.user.root } ] diff --git a/src/layouts/dashboard/config-navigation.tsx b/src/layouts/dashboard/config-navigation.tsx index 0e498db..3d89326 100644 --- a/src/layouts/dashboard/config-navigation.tsx +++ b/src/layouts/dashboard/config-navigation.tsx @@ -53,7 +53,7 @@ export function useNavData() { title: t('menu.user'), path: paths.dashboard.user.root, icon: ICONS.user, - children: [{ title: t('menu.account'), path: paths.dashboard.user.account }] + children: [{ title: t('menu.account'), path: paths.dashboard.user.root }] } ] } diff --git a/src/locales/langs/br.json b/src/locales/langs/br.json index d39d57b..527eb7a 100644 --- a/src/locales/langs/br.json +++ b/src/locales/langs/br.json @@ -33,7 +33,8 @@ "user": "Usuário", "account": "Conta", "logout": "Sair", - "email": "Alterar Email" + "email": "Alterar Email", + "transfer-all": "Transfer Tudo" }, "terms": { "title": "Termos e Condições", @@ -290,6 +291,7 @@ "title": "Saldo Estimado", "deposit": "Depositar", "send": "Enviar", + "transfer-all": "Transferir Tudo", "wapp-msg": "Olá!" }, "transactions": { @@ -305,6 +307,16 @@ "receive-from": "Recebido dinheiro de", "sent-to": "Enviado dinheiro para" }, + "transfer-all": { + "info": "Indica um endereço de carteira para onde serão enviados todos os fundos que você possui no Chatterpay.", + "msgs": { + "ok": "Os fundos foram transferidos. Você os verá na carteira indicada em breve.", + "error": "Houve um erro ao tentar transferir os fundos." + }, + "actions": { + "transfer": "Transferir Tudo" + } + }, "nfts": { "view-trx": "Ver detalhes da transação", "mint": "Ei, dá uma olhada no meu NFT:", diff --git a/src/locales/langs/en.json b/src/locales/langs/en.json index 14fd701..92815ce 100644 --- a/src/locales/langs/en.json +++ b/src/locales/langs/en.json @@ -33,7 +33,8 @@ "user": "User", "account": "Account", "logout": "Logout", - "email": "Email Change" + "email": "Email Change", + "transfer-all": "Transfer All" }, "home": { "header": { @@ -290,6 +291,7 @@ "title": "Estimated Balance", "deposit": "Deposit", "send": "Send", + "transfer-all": "Transfer All", "wapp-msg": "Hi!" }, "transactions": { @@ -305,6 +307,16 @@ "receive-from": "Received money from", "sent-to": "Sent money to" }, + "transfer-all": { + "info": "Indicates a wallet address where all funds in Chatterpay will be sent.", + "msgs": { + "ok": "The funds were transferred. You will see them in the indicated wallet shortly.", + "error": "There was an error attempting to transfer the funds." + }, + "actions": { + "transfer": "Transfer All" + } + }, "nfts": { "view-trx": "View Transacton Details", "mint": "Hey, check out my NFT:", diff --git a/src/locales/langs/es.json b/src/locales/langs/es.json index a9b06b4..3f6377e 100644 --- a/src/locales/langs/es.json +++ b/src/locales/langs/es.json @@ -33,7 +33,8 @@ "user": "Usuario", "account": "Cuenta", "logout": "Cerrar Sesión", - "email": "Cambiar Correo" + "email": "Cambiar Correo", + "transfer-all": "Transferir Todo" }, "terms": { "title": "Términos y Condiciones", @@ -290,6 +291,7 @@ "title": "Balance Estimado", "deposit": "Depositar", "send": "Enviar", + "transfer-all": "Transferir Todo", "wapp-msg": "Hola!" }, "transactions": { @@ -305,6 +307,16 @@ "receive-from": "Recibido dinero de", "sent-to": "Enviado dinero a" }, + "transfer-all": { + "info": "Indica una dirección de billetera en donde se enviarán todos los fondos que tengas en Chatterpay", + "msgs": { + "ok": "Los fondos fueron transferidos. Los verás en la billetera indicada en breve.", + "error": "Hubo un error al intentar transferir los fondos." + }, + "actions": { + "transfer": "Transferir Todo" + } + }, "nfts": { "view-trx": "Ver detalles de la transacción", "mint": "Hey, mira mi NFT:", diff --git a/src/routes/paths.ts b/src/routes/paths.ts index fb5ec8d..91ad342 100644 --- a/src/routes/paths.ts +++ b/src/routes/paths.ts @@ -23,18 +23,12 @@ export const paths = { root: `${ROOTS.DASHBOARD}/nfts`, content: (id: string) => `${ROOTS.DASHBOARD}/nfts` }, + transfer: { + all: `${ROOTS.DASHBOARD}/transfer/all` + }, user: { root: `${ROOTS.DASHBOARD}/user/account`, - account: `${ROOTS.DASHBOARD}/user/account`, - email: `${ROOTS.DASHBOARD}/user/account/email`, - wallet: { - root: (walletId: string) => `${ROOTS.DASHBOARD}/user/wallet/${walletId}`, - nfts: { - root: (walletId: string) => `${ROOTS.DASHBOARD}/user/wallet/${walletId}/nfts`, - item: (walletId: string, nftId: string) => - `${ROOTS.DASHBOARD}/user/wallet/${walletId}/nfts/${nftId}` - } - } + email: `${ROOTS.DASHBOARD}/user/account/email` } } } diff --git a/src/sections/account/change-email.tsx b/src/sections/account/change-email.tsx index 23cac85..69bd859 100644 --- a/src/sections/account/change-email.tsx +++ b/src/sections/account/change-email.tsx @@ -121,14 +121,14 @@ export default function ChangeEmail() { }, [startCountdown, contextUser, generate2faCodeEmail, t, setValue, enqueueSnackbar]) const handleCancel = () => { - router.push(paths.dashboard.user.account) + router.push(paths.dashboard.user.root) } const onSubmit = async (data: any) => { try { // @ts-ignore await updateEmail?.(contextUser!.phoneNumber, data.code || '', confirmEmail, contextUser!.id) - router.push(paths.dashboard.user.account) + router.push(paths.dashboard.user.root) setErrorMsg('') enqueueSnackbar(t('common.msg.update-success')) } catch (ex) { diff --git a/src/sections/banking/banking-balances.tsx b/src/sections/banking/banking-balances.tsx index 1d82205..fa2164b 100644 --- a/src/sections/banking/banking-balances.tsx +++ b/src/sections/banking/banking-balances.tsx @@ -14,6 +14,8 @@ import { SelectChangeEvent } from '@mui/material' +import { paths } from 'src/routes/paths' + import { useBoolean } from 'src/hooks/use-boolean' import { useResponsive } from 'src/hooks/use-responsive' @@ -40,7 +42,6 @@ export default function BankingBalances({ tableData, ...other }: Props) { - const walletLinkL1 = `${EXPLORER_L1}/address/${tableData?.wallet || ''}` const walletLinkL2 = `${EXPLORER_L2}/address/${tableData?.wallet || ''}` @@ -129,7 +130,6 @@ export default function BankingBalances({ > {t('balances.deposit')} - + ) diff --git a/src/sections/banking/transfer-all.tsx b/src/sections/banking/transfer-all.tsx index 2af7963..c7a1e4f 100644 --- a/src/sections/banking/transfer-all.tsx +++ b/src/sections/banking/transfer-all.tsx @@ -1,7 +1,7 @@ import * as Yup from 'yup' import { useForm } from 'react-hook-form' +import { useMemo, useState } from 'react' import { yupResolver } from '@hookform/resolvers/yup' -import { useMemo, useState, useEffect, useCallback } from 'react' import Box from '@mui/material/Box' import Card from '@mui/material/Card' @@ -14,140 +14,68 @@ import LoadingButton from '@mui/lab/LoadingButton' import { paths } from 'src/routes/paths' import { useRouter } from 'src/routes/hooks' -import { useCountdownSeconds } from 'src/hooks/use-countdown' - import { useTranslate } from 'src/locales' import { useAuthContext } from 'src/auth/hooks' +import { transferAll } from 'src/app/api/_hooks/use-wallet' import { useSnackbar } from 'src/components/snackbar' -import FormProvider, { RHFCode, RHFTextField } from 'src/components/hook-form' - -import { IAccount } from 'src/types/account' +import FormProvider, { RHFTextField } from 'src/components/hook-form' // ---------------------------------------------------------------------- export default function TransferAll() { const { enqueueSnackbar } = useSnackbar() const { t } = useTranslate() - const { generate2faCodeEmail, updateEmail } = useAuthContext() const { user } = useAuthContext() const router = useRouter() - - const [codeSent, setCodeSent] = useState(false) const [errorMsg, setErrorMsg] = useState('') - const [contextUser, setContextUser] = useState(null) - const { counting, countdown, startCountdown } = useCountdownSeconds(60) - - const ChangeEmailSchema = Yup.object().shape({ - oldEmail: Yup.string().email(t('common.must-be-valid-email')).required(t('common.required')), - newEmail: Yup.string().email(t('common.must-be-valid-email')).required(t('common.required')), - confirmEmail: Yup.string() - .oneOf([Yup.ref('newEmail')], t('common.emails-must-match')) - .required(t('common.required')), - // @ts-ignore - code: Yup.string().when('codeSent', { - is: true, - then: Yup.string() - .matches(/^[0-9]{6}$/, t('common.must-be-numeric')) - .required(t('common.required')) - }) + const TransferAllSchema = Yup.object().shape({ + wallet: Yup.string() + .matches(/^0x[a-zA-Z0-9]*$/, t('common.invalid-char')) + .required(t('common.required')) }) const defaultValues = useMemo( () => ({ - oldEmail: user?.email || '', - newEmail: '', - confirmEmail: '', - code: '' + wallet: '' }), - [user?.email] + [] ) const methods = useForm({ // @ts-ignore - resolver: yupResolver(ChangeEmailSchema), + resolver: yupResolver(TransferAllSchema), defaultValues }) const { watch, - setValue, handleSubmit, formState: { isSubmitting, isValid } } = methods - const newEmail = watch('newEmail') - const confirmEmail = watch('confirmEmail') - const codeValue = watch('code') + const wallet = watch('wallet') // ---------------------------------------------------------------------- - // guardar el telefono en estado, por cambios en el contexdto del user - useEffect(() => { - if (!user) return - // @ts-ignore - setContextUser(user) - }, [user]) - - const handleSendCode = useCallback(async () => { - try { - startCountdown() - setErrorMsg('') - - // @ts-ignore - await generate2faCodeEmail?.( - contextUser!.id, - // @ts-ignore - contextUser!.phoneNumber, - t('account.email.code-bot') - ) - - setCodeSent(true) - setValue('code', '') - enqueueSnackbar(`${t('account.email.code-sent')} ${contextUser}`, { - variant: 'info' - }) - } catch (ex) { - console.error(ex) - if (typeof ex === 'string') { - setErrorMsg(ex) - } else if (ex.code === 'USER_NOT_FOUND') { - setErrorMsg(t('login.msg.invalid-user')) - } else { - setErrorMsg(ex.error) - } - } - }, [startCountdown, contextUser, generate2faCodeEmail, t, setValue, enqueueSnackbar]) - const handleCancel = () => { - router.push(paths.dashboard.user.account) + router.push(paths.dashboard.root) } const onSubmit = async (data: any) => { try { - // @ts-ignore - await updateEmail?.(contextUser!.phoneNumber, data.code || '', confirmEmail, contextUser!.id) - router.push(paths.dashboard.user.account) + const walletTo = wallet.startsWith('0x') ? wallet : `0x${wallet}` + await transferAll(user!.id, { walletTo }) + router.push(paths.dashboard.root) setErrorMsg('') - enqueueSnackbar(t('common.msg.update-success')) + enqueueSnackbar(t('transfer-all.msgs.ok')) } catch (ex) { console.error(ex) - if (typeof ex === 'string') { - setErrorMsg(ex) - } else if (ex.code === 'USER_NOT_FOUND') { - setErrorMsg(t('login.msg.invalid-user')) - } else if (ex.code === 'INVALID_CODE') { - setErrorMsg(t('account.email.invalid-code')) - } else { - setErrorMsg(ex.error) - } + setErrorMsg(t('transfer-all.msgs.error')) } } - const isSendCodeDisabled = !newEmail || !confirmEmail || newEmail !== confirmEmail || counting - const isSaveDisabled = !codeSent || !codeValue || codeValue.length !== 6 || !isValid - // ---------------------------------------------------------------------- const renderForm = ( @@ -163,33 +91,15 @@ export default function TransferAll() { sm: 'repeat(1, 1fr)' }} > - - - - - {codeSent && ( - <> - {t('account.email.code-info')} - - - )} - + {t('transfer-all.info')} + {errorMsg && {errorMsg}} - - - - {counting - ? `${t('account.email.resend-code')} (${countdown}s)` - : t('account.email.send-code')} - - -