diff --git a/Dockerfile b/Dockerfile index 9bb8990..423a89a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,3 +1,5 @@ + + FROM node:18-alpine AS deps WORKDIR /app COPY package.json package-lock.json ./ @@ -15,6 +17,8 @@ ARG BOT_API_TOKEN ARG BOT_API_URL ARG BOT_API_WAPP_ENABLED ARG BACKEND_API_URL +ARG BACKEND_API_TOKEN +ARG BACKEND_API_TOKEN_SECRET ARG NODE_PROVIDER_SEPOLIA_URL ARG NODE_PROVIDER_MUMBAI_URL ARG NODE_PROVIDER_SCROLL_URL @@ -29,7 +33,6 @@ ARG RECAPTCHA_API_KEY ARG NEXT_PUBLIC_RECAPTCHA_SITE_KEY ARG NEXT_PUBLIC_NFT_IMAGE_REPOSITORY ARG NEXT_PUBLIC_NFT_MARKETPLACE_URL - # # env ENV NODE_ENV production @@ -41,6 +44,8 @@ ENV BOT_API_TOKEN $BOT_API_TOKEN ENV BOT_API_URL $BOT_API_URL ENV BOT_API_WAPP_ENABLED $BOT_API_WAPP_ENABLED ENV BACKEND_API_URL $BACKEND_API_URL +ENV BACKEND_API_TOKEN $BACKEND_API_TOKEN +ENV BACKEND_API_TOKEN_SECRET $BACKEND_API_TOKEN_SECRET ENV NODE_PROVIDER_SEPOLIA_URL $NODE_PROVIDER_SEPOLIA_URL ENV NODE_PROVIDER_MUMBAI_URL $NODE_PROVIDER_MUMBAI_URL ENV NODE_PROVIDER_SCROLL_URL $NODE_PROVIDER_SCROLL_URL @@ -58,14 +63,19 @@ ENV NEXT_PUBLIC_NFT_MARKETPLACE_URL $NEXT_PUBLIC_NFT_MARKETPLACE_URL # COPY --from=deps /app/node_modules ./node_modules COPY . . + RUN echo "***********************" RUN env +RUN echo $BACKEND_API_TOKEN +RUN echo $BACKEND_API_TOKEN_SECRET RUN echo "***********************" + RUN npm run build # FROM node:18-alpine AS runner WORKDIR /app ENV NODE_ENV production + RUN addgroup --system --gid 1001 nodejs && adduser --system --uid 1001 nextjs COPY --from=builder /app/next.config.js ./ COPY --from=builder /app/public ./public diff --git a/cloudbuild.yaml b/cloudbuild.yaml index 4066480..7832743 100644 --- a/cloudbuild.yaml +++ b/cloudbuild.yaml @@ -1,9 +1,8 @@ steps: - # Para para generar un .env para que sea tomado por el step de build. - # Las variables serán tomadas de la definición del "trigger", - # "variables de sustitución", en Google Cloud Build. - # en gcp, se tiene que poner como nombre de cada variable, el unserscore - # como prefijo. Ejemplo: "_APP_ENV" + # + # This step is kept as a workaround, generating a .env file that is required by the + # library used with MongoDB. If it is removed, attempting to connect to the database + # throws an error indicating that the URI does not exist in the environment. # - name: 'gcr.io/cloud-builders/npm' id: CreateEnv @@ -17,6 +16,8 @@ steps: - BOT_API_URL=${_BOT_API_URL} - BOT_API_WAPP_ENABLED=${_BOT_API_WAPP_ENABLED} - BACKEND_API_URL=${_BACKEND_API_URL} + - BACKEND_API_TOKEN=${_BACKEND_API_TOKEN} + #- BACKEND_API_TOKEN_SECRET=$$BACKEND_API_TOKEN_SECRET - NODE_PROVIDER_SEPOLIA_URL=${_NODE_PROVIDER_SEPOLIA_URL} - NODE_PROVIDER_MUMBAI_URL=${_NODE_PROVIDER_MUMBAI_URL} - NODE_PROVIDER_SCROLL_URL=${_NODE_PROVIDER_SCROLL_URL} @@ -31,67 +32,97 @@ steps: - NEXT_PUBLIC_RECAPTCHA_SITE_KEY=${_NEXT_PUBLIC_RECAPTCHA_SITE_KEY} - NEXT_PUBLIC_NFT_IMAGE_REPOSITORY=${_NEXT_PUBLIC_NFT_IMAGE_REPOSITORY} - NEXT_PUBLIC_NFT_MARKETPLACE_URL=${_NEXT_PUBLIC_NFT_MARKETPLACE_URL} - - # build the container images - - name: "gcr.io/cloud-builders/docker" + secretEnv: [ + 'BACKEND_API_TOKEN_SECRET' + ] + # + # Build docker imagen. + # Variables with a prefix '_' are from Cloud Build 'substitution' (declared in the job). + # Variables with a prefix '$$' are from Secret Manager. + # + - name: 'gcr.io/cloud-builders/docker' id: Build args: [ - "build", - "--no-cache", - "-t", - "$_AR_HOSTNAME/$PROJECT_ID/cloud-run-source-deploy/$REPO_NAME/$_SERVICE_NAME:$COMMIT_SHA", - "--build-arg", "APP_ENV=${_APP_ENV}", - "--build-arg", "MONGODB=${_MONGODB}", - "--build-arg", "MONGODB_BOT=${_MONGODB_BOT}", - "--build-arg", "DB_CHATTERPAY_NAME=${_DB_CHATTERPAY_NAME}", - "--build-arg", "RECAPTCHA_API_KEY=${_RECAPTCHA_API_KEY}", - "--build-arg", "NEXT_PUBLIC_RECAPTCHA_SITE_KEY=${_NEXT_PUBLIC_RECAPTCHA_SITE_KEY}", - "--build-arg", "NEXT_PUBLIC_NFT_IMAGE_REPOSITORY=${_NEXT_PUBLIC_NFT_IMAGE_REPOSITORY}", - "--build-arg", "NEXT_PUBLIC_NFT_MARKETPLACE_URL=${_NEXT_PUBLIC_NFT_MARKETPLACE_URL}", - "--build-arg", "BOT_API_TOKEN=${_BOT_API_TOKEN}", - "--build-arg", "BOT_API_URL=${_BOT_API_URL}", - "--build-arg", "BOT_API_WAPP_ENABLED=${_BOT_API_WAPP_ENABLED}", - "--build-arg", "BACKEND_API_URL=${_BACKEND_API_URL}", - "--build-arg", "NODE_PROVIDER_SEPOLIA_URL=${_NODE_PROVIDER_SEPOLIA_URL}", - "--build-arg", "NODE_PROVIDER_MUMBAI_URL=${_NODE_PROVIDER_MUMBAI_URL}", - "--build-arg", "NODE_PROVIDER_SCROLL_URL=${_NODE_PROVIDER_SCROLL_URL}", - "--build-arg", "HANDLE_VERCEL_FREE_PLAN_TIMEOUT=${_HANDLE_VERCEL_FREE_PLAN_TIMEOUT}", - "--build-arg", "NEXT_PUBLIC_USE_MOCK=${_NEXT_PUBLIC_USE_MOCK}", - "--build-arg", "API3_ENABLED=${_API3_ENABLED}", - "--build-arg", "JWT_SECRET=${_JWT_SECRET}", - "--build-arg", "NEXT_PUBLIC_FROM_ICP=${_NEXT_PUBLIC_FROM_ICP}", - "--build-arg", "NEXT_PUBLIC_UI_URL=${_NEXT_PUBLIC_UI_URL}", - "--build-arg", "NEXT_PUBLIC_ALLOWED_ORIGINS=${_NEXT_PUBLIC_ALLOWED_ORIGINS}", - "." + 'build', + '--no-cache', + '-t', + '$_AR_HOSTNAME/$PROJECT_ID/cloud-run-source-deploy/$REPO_NAME/$_SERVICE_NAME:$COMMIT_SHA', + '--build-arg', 'APP_ENV=${_APP_ENV}', + '--build-arg', 'MONGODB=${_MONGODB}', + '--build-arg', 'MONGODB_BOT=${_MONGODB_BOT}', + '--build-arg', 'DB_CHATTERPAY_NAME=${_DB_CHATTERPAY_NAME}', + '--build-arg', 'RECAPTCHA_API_KEY=${_RECAPTCHA_API_KEY}', + '--build-arg', 'NEXT_PUBLIC_RECAPTCHA_SITE_KEY=${_NEXT_PUBLIC_RECAPTCHA_SITE_KEY}', + '--build-arg', 'NEXT_PUBLIC_NFT_IMAGE_REPOSITORY=${_NEXT_PUBLIC_NFT_IMAGE_REPOSITORY}', + '--build-arg', 'NEXT_PUBLIC_NFT_MARKETPLACE_URL=${_NEXT_PUBLIC_NFT_MARKETPLACE_URL}', + '--build-arg', 'BOT_API_TOKEN=${_BOT_API_TOKEN}', + '--build-arg', 'BOT_API_URL=${_BOT_API_URL}', + '--build-arg', 'BOT_API_WAPP_ENABLED=${_BOT_API_WAPP_ENABLED}', + '--build-arg', 'BACKEND_API_URL=${_BACKEND_API_URL}', + '--build-arg', 'BACKEND_API_TOKEN=${_BACKEND_API_TOKEN}', + '--build-arg', 'BACKEND_API_TOKEN_SECRET=$$BACKEND_API_TOKEN_SECRET', + '--build-arg', 'NODE_PROVIDER_SEPOLIA_URL=${_NODE_PROVIDER_SEPOLIA_URL}', + '--build-arg', 'NODE_PROVIDER_MUMBAI_URL=${_NODE_PROVIDER_MUMBAI_URL}', + '--build-arg', 'NODE_PROVIDER_SCROLL_URL=${_NODE_PROVIDER_SCROLL_URL}', + '--build-arg', 'HANDLE_VERCEL_FREE_PLAN_TIMEOUT=${_HANDLE_VERCEL_FREE_PLAN_TIMEOUT}', + '--build-arg', 'NEXT_PUBLIC_USE_MOCK=${_NEXT_PUBLIC_USE_MOCK}', + '--build-arg', 'API3_ENABLED=${_API3_ENABLED}', + '--build-arg', 'JWT_SECRET=${_JWT_SECRET}', + '--build-arg', 'NEXT_PUBLIC_FROM_ICP=${_NEXT_PUBLIC_FROM_ICP}', + '--build-arg', 'NEXT_PUBLIC_UI_URL=${_NEXT_PUBLIC_UI_URL}', + '--build-arg', 'NEXT_PUBLIC_ALLOWED_ORIGINS=${_NEXT_PUBLIC_ALLOWED_ORIGINS}', + '.' + ] + secretEnv: [ + 'BACKEND_API_TOKEN_SECRET' ] + # # push the container images to Container Registry - - name: "gcr.io/cloud-builders/docker" + # + - name: 'gcr.io/cloud-builders/docker' id: Push args: [ - "push", - "$_AR_HOSTNAME/$PROJECT_ID/cloud-run-source-deploy/$REPO_NAME/$_SERVICE_NAME:$COMMIT_SHA" + 'push', + '$_AR_HOSTNAME/$PROJECT_ID/cloud-run-source-deploy/$REPO_NAME/$_SERVICE_NAME:$COMMIT_SHA' ] - + # # Deploy container images to Cloud Run - - name: "gcr.io/cloud-builders/gcloud" + # + - name: 'gcr.io/cloud-builders/gcloud' id: Deploy entrypoint: gcloud args: [ - "run", - "deploy", - "$_SERVICE_NAME", - "--platform", - "managed", - "--region", - "$_DEPLOY_REGION", - "--image", - "$_AR_HOSTNAME/$PROJECT_ID/cloud-run-source-deploy/$REPO_NAME/$_SERVICE_NAME:$COMMIT_SHA", - "--labels", - "managed-by=gcp-cloud-build-deploy-cloud-run,commit-sha=$COMMIT_SHA,gcb-build-id=$BUILD_ID,gcb-trigger-id=$_TRIGGER_ID", - "--quiet", - "--allow-unauthenticated", + 'run', + 'deploy', + '$_SERVICE_NAME', + '--platform', + 'managed', + '--region', + '$_DEPLOY_REGION', + '--image', + '$_AR_HOSTNAME/$PROJECT_ID/cloud-run-source-deploy/$REPO_NAME/$_SERVICE_NAME:$COMMIT_SHA', + '--labels', + 'managed-by=gcp-cloud-build-deploy-cloud-run,commit-sha=$COMMIT_SHA,gcb-build-id=$BUILD_ID,gcb-trigger-id=$_TRIGGER_ID', + '--quiet', + '--allow-unauthenticated', ] + # + # print secret variables + # + - name: 'bash' + script: | + #!/usr/bin/env bash + echo 'BACKEND_API_TOKEN en cloudbuild.yaml 1: $BACKEND_API_TOKEN_SECRET' + secretEnv: [ + 'BACKEND_API_TOKEN_SECRET' + ] + +availableSecrets: + secretManager: + - versionName: 'projects/$PROJECT_ID/secrets/${_BACKEND_API_TOKEN_SECRET_NAME}/versions/latest' + env: 'BACKEND_API_TOKEN_SECRET' + images: - $_AR_HOSTNAME/$PROJECT_ID/cloud-run-source-deploy/$REPO_NAME/$_SERVICE_NAME:$COMMIT_SHA diff --git a/example_env b/example_env index cf6fed7..72fbd8f 100644 --- a/example_env +++ b/example_env @@ -8,6 +8,7 @@ APP_ENV='development' BOT_API_TOKEN={api token} BOT_API_URL=http://localhost:3000 BACKEND_API_URL=https://dev.back.chatterpay.net +BACKEND_API_TOKEN='backend token' BOT_API_WAPP_ENABLED=true MONGODB='mongodb://localhost:27017' MONGODB_BOT='BOT mongo db url' diff --git a/next.config.js b/next.config.js index e370b02..0b2a57b 100644 --- a/next.config.js +++ b/next.config.js @@ -19,6 +19,7 @@ module.exports = { 'storage.googleapis.com', 'cilxj-yiaaa-aaaag-alkxq-cai.icp0.io', 'gateway.pinata.cloud', + 'w.wallhaven.cc', 'img.freepik.com'], remotePatterns: [ { @@ -44,6 +45,12 @@ module.exports = { hostname: 'img.freepik.com', port: '', pathname: '/**', + }, + { + protocol: 'https', + hostname: 'w.wallhaven.cc', + port: '', + pathname: '/**', } ], }, diff --git a/scripts/docker-build.sh b/scripts/docker-build.sh index 99a8e8f..fe4b4ce 100644 --- a/scripts/docker-build.sh +++ b/scripts/docker-build.sh @@ -15,19 +15,23 @@ docker build \ --build-arg MONGODB="$MONGODB" \ --build-arg MONGODB_BOT="$MONGODB_BOT" \ --build-arg DB_CHATTERPAY_NAME="$DB_CHATTERPAY_NAME" \ + --build-arg RECAPTCHA_API_KEY="$RECAPTCHA_API_KEY" \ + --build-arg NEXT_PUBLIC_RECAPTCHA_SITE_KEY="$NEXT_PUBLIC_RECAPTCHA_SITE_KEY" \ + --build-arg NEXT_PUBLIC_NFT_IMAGE_REPOSITORY="$NEXT_PUBLIC_NFT_IMAGE_REPOSITORY" \ + --build-arg NEXT_PUBLIC_NFT_MARKETPLACE_URL="$NEXT_PUBLIC_NFT_MARKETPLACE_URL" \ --build-arg BOT_API_TOKEN="$BOT_API_TOKEN" \ --build-arg BOT_API_URL="$BOT_API_URL" \ + --build-arg BOT_API_WAPP_ENABLED="$BOT_API_WAPP_ENABLED" \ + --build-arg BACKEND_API_URL="$BACKEND_API_URL" \ + --build-arg BACKEND_API_TOKEN="$BACKEND_API_TOKEN" \ --build-arg NODE_PROVIDER_SEPOLIA_URL="$NODE_PROVIDER_SEPOLIA_URL" \ --build-arg NODE_PROVIDER_MUMBAI_URL="$NODE_PROVIDER_MUMBAI_URL" \ --build-arg NODE_PROVIDER_SCROLL_URL="$NODE_PROVIDER_SCROLL_URL" \ + --build-arg HANDLE_VERCEL_FREE_PLAN_TIMEOUT="$HANDLE_VERCEL_FREE_PLAN_TIMEOUT" \ + --build-arg NEXT_PUBLIC_USE_MOCK="$NEXT_PUBLIC_USE_MOCK" \ --build-arg API3_ENABLED="$API3_ENABLED" \ --build-arg JWT_SECRET="$JWT_SECRET" \ --build-arg NEXT_PUBLIC_FROM_ICP="$NEXT_PUBLIC_FROM_ICP" \ - --build-arg NEXT_PUBLIC_USE_MOCK="$NEXT_PUBLIC_USE_MOCK" \ --build-arg NEXT_PUBLIC_UI_URL="$NEXT_PUBLIC_UI_URL" \ --build-arg NEXT_PUBLIC_ALLOWED_ORIGINS="$NEXT_PUBLIC_ALLOWED_ORIGINS" \ - --build-arg RECAPTCHA_API_KEY="$RECAPTCHA_API_KEY" \ - --build-arg NEXT_PUBLIC_RECAPTCHA_SITE_KEY="$NEXT_PUBLIC_RECAPTCHA_SITE_KEY" \ - --build-arg NEXT_PUBLIC_NFT_IMAGE_REPOSITORY="$NEXT_PUBLIC_NFT_IMAGE_REPOSITORY" \ - --build-arg NEXT_PUBLIC_NFT_MARKETPLACE_URL="$NEXT_PUBLIC_NFT_MARKETPLACE_URL" \ -t my-nextjs-app .. diff --git a/src/app/api/_data/_mock/_countries.ts b/src/app/api/_data/_countries.ts similarity index 100% rename from src/app/api/_data/_mock/_countries.ts rename to src/app/api/_data/_countries.ts diff --git a/src/app/api/_data/_mock/_mock.ts b/src/app/api/_data/_mock/_mock.ts deleted file mode 100644 index b7b37c9..0000000 --- a/src/app/api/_data/_mock/_mock.ts +++ /dev/null @@ -1,65 +0,0 @@ -import { sub } from 'date-fns' - -import { - _id, - _ages, - _prices, - _emails, - _ratings, - _nativeS, - _nativeM, - _nativeL, - _percents, - _booleans, - _sentences, - _lastNames, - _fullNames, - _firstNames, - _descriptions, - _phoneNumbers -} from './assets' - -// ---------------------------------------------------------------------- - -export const _mock = { - id: (index: number) => _id[index], - time: (index: number) => sub(new Date(), { days: index, hours: index }), - boolean: (index: number) => _booleans[index], - // role: (index: number) => _roles[index], - // Text - // taskNames: (index: number) => _taskNames[index], - // postTitle: (index: number) => _postTitles[index], - // jobTitle: (index: number) => _jobTitles[index], - // tourName: (index: number) => _tourNames[index], - // productName: (index: number) => _productNames[index], - sentence: (index: number) => _sentences[index], - description: (index: number) => _descriptions[index], - // Contact - email: (index: number) => _emails[index], - phoneNumber: (index: number) => _phoneNumbers[index], - // fullAddress: (index: number) => _fullAddress[index], - // Name - firstName: (index: number) => _firstNames[index], - lastName: (index: number) => _lastNames[index], - fullName: (index: number) => _fullNames[index], - // companyName: (index: number) => _companyNames[index], - // Number - number: { - percent: (index: number) => _percents[index], - rating: (index: number) => _ratings[index], - age: (index: number) => _ages[index], - price: (index: number) => _prices[index], - nativeS: (index: number) => _nativeS[index], - nativeM: (index: number) => _nativeM[index], - nativeL: (index: number) => _nativeL[index] - }, - // Image - image: { - cover: (index: number) => `/assets/images/cover_1.jpg`, - avatar: (index: number) => `/assets/images/avatars/avatar_${index + 1}.jpg`, - travel: (index: number) => `/assets/images/travel_1.jpg`, - company: (index: number) => `/assets/images/company_1.png`, - product: (index: number) => `/assets/images/product_1.jpg`, - portrait: (index: number) => `/assets/images/portrait_1.jpg` - } -} diff --git a/src/app/api/_data/_mock/_others.ts b/src/app/api/_data/_mock/_others.ts deleted file mode 100644 index f66eced..0000000 --- a/src/app/api/_data/_mock/_others.ts +++ /dev/null @@ -1,52 +0,0 @@ -// ---------------------------------------------------------------------- - -export const _socials = [ - { - value: 'facebook', - name: 'FaceBook', - icon: 'eva:facebook-fill', - color: '#1877F2', - path: 'https://www.facebook.com/caitlyn.kerluke' - }, - { - value: 'instagram', - name: 'Instagram', - icon: 'ant-design:instagram-filled', - color: '#E02D69', - path: 'https://www.instagram.com/caitlyn.kerluke' - }, - { - value: 'linkedin', - name: 'Linkedin', - icon: 'eva:linkedin-fill', - color: '#007EBB', - path: 'https://www.linkedin.com/caitlyn.kerluke' - }, - { - value: 'twitter', - name: 'Twitter', - icon: 'eva:twitter-fill', - color: '#00AAEC', - path: 'https://www.twitter.com/caitlyn.kerluke' - } -] - -// ---------------------------------------------------------------------- - -export const _homePlans = [...Array(3)].map((_, index) => ({ - license: ['Standard', 'Standard Plus', 'Extended'][index], - commons: ['One end products', '12 months updates', '6 months of support'], - options: [ - 'JavaScript version', - 'TypeScript version', - 'Design Resources', - 'Commercial applications' - ], - icons: [ - '/assets/icons/platforms/ic_js.svg', - '/assets/icons/platforms/ic_ts.svg', - '/assets/icons/platforms/ic_figma.svg' - ] -})) - -// ---------------------------------------------------------------------- diff --git a/src/app/api/_data/_mock/_wallet.ts b/src/app/api/_data/_mock/_wallet.ts deleted file mode 100644 index 8e512e6..0000000 --- a/src/app/api/_data/_mock/_wallet.ts +++ /dev/null @@ -1,130 +0,0 @@ -import { IBalance, ITransaction } from 'src/types/wallet' - -import { _mock } from './_mock' - -export const _balances: IBalance[] = [ - { - network: 'sepolia', - balance: 23432.03, - token: 'USDC', - balance_conv: { - usd: 1, - ars: 1, - brl: 1, - uyu: 1 - } - }, - { - network: 'sepolia', - balance: 1.5, - token: 'ETH', - balance_conv: { - usd: 1, - ars: 1, - brl: 1, - uyu: 1 - } - }, - { - network: 'sepolia', - balance: 1, - token: 'BTC', - balance_conv: { - usd: 1, - ars: 1, - brl: 1, - uyu: 1 - } - } -] - -export const _transactions: ITransaction[] = [ - { - id: _mock.id(2), - trx_hash: '0x469c61b085335276861a90a7dc6809c6144317f9a811c95c923a1b3b35d85c29', - wallet_from: '0x35dad65F60c1A32c9895BE97f6bcE57D32792E83', - contact_from_phone: '5491153475555', - contact_from_name: _mock.fullName(2), - contact_from_avatar_url: _mock.fullName(2), - wallet_to: '0x117b706DEF40310eF5926aB57868dAcf46605b8d', - contact_to_phone: '5491131997779', - contact_to_name: _mock.fullName(10), - contact_to_avatar_url: _mock.image.avatar(10), - type: 'transfer', - date: _mock.time(2), - status: 'completed', - amount: _mock.number.price(2), - token: 'USDC' - }, - { - id: _mock.id(3), - trx_hash: '0x5832143b88fcd1727760bc656ee61219f74a1329eee401f2f9afc2e4802a0974', - wallet_from: '0x117b706DEF40310eF5926aB57868dAcf46605b8d', - contact_from_phone: '5491131997779', - contact_from_name: _mock.fullName(10), - contact_from_avatar_url: _mock.fullName(10), - wallet_to: '0x35dad65F60c1A32c9895BE97f6bcE57D32792E83', - contact_to_phone: '5491153475555', - contact_to_name: _mock.fullName(3), - contact_to_avatar_url: _mock.image.avatar(3), - type: 'transfer', - - date: _mock.time(3), - status: 'completed', - amount: _mock.number.price(3), - token: 'USDC' - }, - { - id: _mock.id(4), - wallet_from: '0x35dad65F60c1A32c9895BE97f6bcE57D32792E83', - trx_hash: '0x3eb9d217ff24604ad149c61487dd166296982849eb87d9992988f21ee22fdc17', - contact_from_phone: '5491153475555', - contact_from_name: _mock.fullName(4), - contact_from_avatar_url: _mock.fullName(4), - wallet_to: '0x117b706DEF40310eF5926aB57868dAcf46605b8d', - contact_to_phone: '5491131997779', - contact_to_name: _mock.fullName(10), - contact_to_avatar_url: _mock.image.avatar(10), - type: 'transfer', - - date: _mock.time(4), - status: 'failed', - amount: _mock.number.price(4), - token: 'USDC' - }, - { - id: _mock.id(5), - trx_hash: '0x4f6c005226909336066dd8f199bb0e0346175e53e1a53c50231b2395ba770b67', - wallet_from: '0x117b706DEF40310eF5926aB57868dAcf46605b8d', - contact_from_phone: '5491131997779', - contact_from_name: _mock.fullName(10), - contact_from_avatar_url: _mock.fullName(10), - wallet_to: '0x35dad65F60c1A32c9895BE97f6bcE57D32792E83', - contact_to_phone: '5491153475555', - contact_to_name: _mock.fullName(5), - contact_to_avatar_url: _mock.image.avatar(5), - type: 'transfer', - - date: _mock.time(5), - status: 'completed', - amount: _mock.number.price(5), - token: 'USDC' - }, - { - id: _mock.id(6), - trx_hash: '0x1fb00e771fdac89017694d22504a45568785c903c568fa6ffb40641f9ea59a2f', - wallet_from: '0x117b706DEF40310eF5926aB57868dAcf46605b8d', - contact_from_phone: '5491131997779', - contact_from_name: _mock.fullName(10), - contact_from_avatar_url: _mock.fullName(10), - wallet_to: '0x35dad65F60c1A32c9895BE97f6bcE57D32792E83', - contact_to_phone: '5491153475555', - contact_to_name: _mock.fullName(6), - contact_to_avatar_url: _mock.image.avatar(6), - type: 'transfer', - date: _mock.time(6), - status: 'failed', - amount: _mock.number.price(6), - token: 'USDC' - } -] diff --git a/src/app/api/_data/_mock/assets.ts b/src/app/api/_data/_mock/assets.ts deleted file mode 100644 index 6a244b6..0000000 --- a/src/app/api/_data/_mock/assets.ts +++ /dev/null @@ -1,268 +0,0 @@ -// ---------------------------------------------------------------------- - -export const _id = [...Array(40)].map( - (_, index) => `e99f09a7-dd88-49d5-b1c8-1daf80c2d7b${index + 1}` -) - -// ---------------------------------------------------------------------- - -export const _booleans = [ - true, - true, - true, - false, - false, - true, - false, - false, - false, - false, - true, - true, - true, - false, - false, - false, - true, - false, - false, - false, - true, - false, - false, - true -] - -// ---------------------------------------------------------------------- - -export const _emails = [ - 'nannie_abernathy70@yahoo.com', - 'ashlynn_ohara62@gmail.com', - 'milo.farrell@hotmail.com', - 'violet.ratke86@yahoo.com', - 'letha_lubowitz24@yahoo.com', - 'aditya_greenfelder31@gmail.com', - 'lenna_bergnaum27@hotmail.com', - 'luella.ryan33@gmail.com', - 'joana.simonis84@gmail.com', - 'marjolaine_white94@gmail.com', - 'vergie_block82@hotmail.com', - 'vito.hudson@hotmail.com', - 'tyrel_greenholt@gmail.com', - 'dwight.block85@yahoo.com', - 'mireya13@hotmail.com', - 'dasia_jenkins@hotmail.com', - 'benny89@yahoo.com', - 'dawn.goyette@gmail.com', - 'zella_hickle4@yahoo.com', - 'avery43@hotmail.com', - 'olen_legros@gmail.com', - 'jimmie.gerhold73@hotmail.com', - 'genevieve.powlowski@hotmail.com', - 'louie.kuphal39@gmail.com' -] - -// ---------------------------------------------------------------------- - -export const _fullNames = [ - 'Jayvion Simon', - 'Lucian Obrien', - 'Deja Brady', - 'Harrison Stein', - 'Reece Chung', - 'Lainey Davidson', - 'Cristopher Cardenas', - 'Melanie Noble', - 'Chase Day', - 'Shawn Manning', - 'Soren Durham', - 'Cortez Herring', - 'Brycen Jimenez', - 'Giana Brandt', - 'Aspen Schmitt', - 'Colten Aguilar', - 'Angelique Morse', - 'Selina Boyer', - 'Lawson Bass', - 'Ariana Lang', - 'Amiah Pruitt', - 'Harold Mcgrath', - 'Esperanza Mcintyre', - 'Mireya Conner' -] - -export const _firstNames = [ - 'Mossie', - 'David', - 'Ebba', - 'Chester', - 'Eula', - 'Jaren', - 'Boyd', - 'Brady', - 'Aida', - 'Anastasia', - 'Gregoria', - 'Julianne', - 'Ila', - 'Elyssa', - 'Lucio', - 'Lewis', - 'Jacinthe', - 'Molly', - 'Brown', - 'Fritz', - 'Keon', - 'Ella', - 'Ken', - 'Whitney' -] - -export const _lastNames = [ - 'Carroll', - 'Simonis', - 'Yost', - 'Hand', - 'Emmerich', - 'Wilderman', - 'Howell', - 'Sporer', - 'Boehm', - 'Morar', - 'Koch', - 'Reynolds', - 'Padberg', - 'Watsica', - 'Upton', - 'Yundt', - 'Pfeffer', - 'Parker', - 'Zulauf', - 'Treutel', - 'McDermott', - 'McDermott', - 'Cruickshank', - 'Parisian' -] - -// ---------------------------------------------------------------------- - -export const _prices = [ - 83.74, 97.14, 68.71, 85.21, 52.17, 25.18, 43.84, 60.98, 98.42, 53.37, 72.75, 56.61, 64.55, 77.32, - 60.62, 79.81, 93.68, 47.44, 76.24, 92.87, 72.91, 20.54, 94.25, 37.51 -] - -export const _ratings = [ - 4.2, 3.7, 4.5, 3.5, 0.5, 3.0, 2.5, 2.8, 4.9, 3.6, 2.5, 1.7, 3.9, 2.8, 4.1, 4.5, 2.2, 3.2, 0.6, - 1.3, 3.8, 3.8, 3.8, 2.0 -] - -export const _ages = [ - 30, 26, 59, 47, 29, 46, 18, 56, 39, 19, 45, 18, 46, 56, 38, 41, 44, 48, 32, 45, 42, 60, 33, 57 -] - -export const _percents = [ - 10.1, 13.6, 28.2, 42.1, 37.2, 18.5, 40.1, 94.8, 91.4, 53.0, 25.4, 62.9, 86.6, 62.4, 35.4, 17.6, - 52.0, 6.8, 95.3, 26.6, 69.9, 92.1, 46.2, 85.6 -] - -export const _nativeS = [ - 11, 10, 7, 10, 12, 5, 10, 1, 8, 8, 10, 11, 12, 8, 4, 11, 8, 9, 4, 9, 2, 6, 3, 7 -] - -export const _nativeM = [ - 497, 763, 684, 451, 433, 463, 951, 194, 425, 435, 807, 521, 538, 839, 394, 269, 453, 821, 364, - 849, 804, 776, 263, 239 -] - -export const _nativeL = [ - 9911, 1947, 9124, 6984, 8488, 2034, 3364, 8401, 8996, 5271, 8478, 1139, 8061, 3035, 6733, 3952, - 2405, 3127, 6843, 4672, 6995, 6053, 5192, 9686 -] - -// ---------------------------------------------------------------------- - -export const _phoneNumbers = [ - '365-374-4961', - '904-966-2836', - '399-757-9909', - '692-767-2903', - '990-588-5716', - '955-439-2578', - '226-924-4058', - '552-917-1454', - '285-840-9338', - '306-269-2446', - '883-373-6253', - '476-509-8866', - '201-465-1954', - '538-295-9408', - '531-492-6028', - '981-699-7588', - '500-268-4826', - '205-952-3828', - '222-255-5190', - '408-439-8033', - '272-940-8266', - '812-685-8057', - '353-801-5212', - '606-285-8928' -] - -// ---------------------------------------------------------------------- - -export const _sentences = [ - 'The sun slowly set over the horizon, painting the sky in vibrant hues of orange and pink.', - 'She eagerly opened the gift, her eyes sparkling with excitement.', - 'The old oak tree stood tall and majestic, its branches swaying gently in the breeze.', - 'The aroma of freshly brewed coffee filled the air, awakening my senses.', - 'The children giggled with joy as they ran through the sprinklers on a hot summer day.', - 'He carefully crafted a beautiful sculpture out of clay, his hands skillfully shaping the intricate details.', - 'The concert was a mesmerizing experience, with the music filling the venue and the crowd cheering in delight.', - 'The waves crashed against the shore, creating a soothing symphony of sound.', - 'The scent of blooming flowers wafted through the garden, creating a fragrant paradise.', - 'She gazed up at the night sky, marveling at the twinkling stars that dotted the darkness.', - 'The professor delivered a captivating lecture, engaging the students with thought-provoking ideas.', - 'The hiker trekked through the dense forest, guided by the soft glow of sunlight filtering through the trees.', - 'The delicate butterfly gracefully fluttered from flower to flower, sipping nectar with its slender proboscis.', - 'The aroma of freshly baked cookies filled the kitchen, tempting everyone with its irresistible scent.', - "The majestic waterfall cascaded down the rocks, creating a breathtaking display of nature's power.", - 'The actor delivered a powerful performance, moving the audience to tears with his emotional portrayal.', - 'The book transported me to a magical world, where imagination knew no bounds.', - 'The scent of rain filled the air as dark clouds gathered overhead, promising a refreshing downpour.', - 'The chef skillfully plated the dish, turning simple ingredients into a work of culinary art.', - 'The newborn baby let out a tiny cry, announcing its arrival to the world.', - 'The athlete sprinted across the finish line, arms raised in victory as the crowd erupted in applause.', - 'The ancient ruins stood as a testament to a civilization long gone, their grandeur still awe-inspiring.', - 'The artist dipped the brush into vibrant paint, bringing the canvas to life with bold strokes and vivid colors.', - 'The laughter of children echoed through the playground, filling the atmosphere with pure joy.' -] - -// ---------------------------------------------------------------------- - -export const _descriptions = [ - `Occaecati est et illo quibusdam accusamus qui. Incidunt aut et molestiae ut facere aut. Est quidem iusto praesentium excepturi harum nihil tenetur facilis. Ut omnis voluptates nihil accusantium doloribus eaque debitis.`, - `Atque eaque ducimus minima distinctio velit. Laborum et veniam officiis. Delectus ex saepe hic id laboriosam officia. Odit nostrum qui illum saepe debitis ullam. Laudantium beatae modi fugit ut. Dolores consequatur beatae nihil voluptates rem maiores.`, - `Rerum eius velit dolores. Explicabo ad nemo quibusdam. Voluptatem eum suscipit et ipsum et consequatur aperiam quia. Rerum nulla sequi recusandae illum velit quia quas. Et error laborum maiores cupiditate occaecati.`, - `Et non omnis qui. Qui sunt deserunt dolorem aut velit cumque adipisci aut enim. Nihil quis quisquam nesciunt dicta nobis ab aperiam dolorem repellat. Voluptates non blanditiis. Error et tenetur iste soluta cupiditate ratione perspiciatis et. Quibusdam aliquid nam sunt et quisquam non esse.`, - `Nihil ea sunt facilis praesentium atque. Ab animi alias sequi molestias aut velit ea. Sed possimus eos. Et est aliquid est voluptatem.`, - `Non rerum modi. Accusamus voluptatem odit nihil in. Quidem et iusto numquam veniam culpa aperiam odio aut enim. Quae vel dolores. Pariatur est culpa veritatis aut dolorem.`, - `Est enim et sit non impedit aperiam cumque animi. Aut eius impedit saepe blanditiis. Totam molestias magnam minima fugiat.`, - `Unde a inventore et. Sed esse ut. Atque ducimus quibusdam fuga quas id qui fuga.`, - `Eaque natus adipisci soluta nostrum dolorem. Nesciunt ipsum molestias ut aliquid natus ut omnis qui fugiat. Dolor et rem. Ut neque voluptatem blanditiis quasi ullam deleniti.`, - `Nam et error exercitationem qui voluptate optio. Officia omnis qui accusantium ipsam qui. Quia sequi nulla perspiciatis optio vero omnis maxime omnis ipsum. Perspiciatis consequuntur asperiores veniam dolores.`, - `Perspiciatis nulla ut ut ut voluptates totam consectetur eligendi qui. Optio ut cum. Dolorum sapiente qui laborum. Impedit temporibus totam delectus nihil. Voluptatem corrupti rem.`, - `Distinctio omnis similique omnis eos. Repellat cumque rerum nisi. Reiciendis soluta non ut veniam temporibus. Accusantium et dolorem voluptas harum. Nemo eius voluptate dicta et hic nemo. Dolorem assumenda et beatae molestias sit quo mollitia quis consequatur.`, - `Sed ut mollitia tempore ipsam et illum doloribus ut. Occaecati ratione veritatis explicabo. Omnis nam omnis sunt placeat tempore accusantium placeat distinctio velit.`, - `Eum illo dicta et perspiciatis ut blanditiis eos sequi. Ea veritatis aut et voluptas aut. Laborum eos quia tempore a culpa.`, - `Aut quos quae dolores repudiandae similique perferendis perferendis earum laudantium. Facere placeat natus nobis. Eius vitae ullam dolorem.`, - `Vero dolorem et voluptatem fugit tempore a quam iure. Fuga consequatur corrupti sunt asperiores vitae. Libero totam repellendus animi debitis illum et sunt officia.`, - `Cupiditate illum officiis id molestiae. Numquam non molestiae aliquid et natus sed hic. Alias quia explicabo sed corrupti sint. Natus in et odio qui unde facilis quia. Est sit eius laboriosam aliquid non aperiam quia quo corporis.`, - `Et a ab. Optio aspernatur minus tempora amet vitae consectetur inventore cumque. Sed et omnis. Aspernatur a magnam.`, - `Ipsum omnis et. Quia ea et autem tempore consequuntur veniam dolorem officiis. Ipsa dicta et ut quidem quia doloremque. Sequi vitae doloremque temporibus. Deserunt incidunt id aperiam itaque natus. Earum sit eaque quas incidunt nihil.`, - `Quae consequatur reiciendis. Consequatur non optio. Eaque id placeat. Commodi quo officia aut repudiandae reiciendis tempore voluptatem et. Ut accusamus qui itaque maxime aliquam. Fugit ut animi molestiae porro maiores.`, - `Modi hic asperiores ab cumque quam est aut. Voluptas atque quos molestias. Ut excepturi distinctio ipsam aspernatur sit.`, - `Sunt totam facilis. Quam commodi voluptatem veniam. Tempora deleniti itaque fugit nihil voluptas.`, - `Ipsam aliquam velit nobis repellendus officiis aut deserunt id et. Nihil sunt aut dolores aut. Dolores est ipsa quia et laborum quidem laborum accusamus id. Facilis odit quod hic laudantium saepe omnis nisi in sint. Sed cupiditate possimus id.`, - `Magnam non eveniet optio optio ut aliquid atque. Velit libero aspernatur quis laborum consequatur laudantium. Tempora facere optio fugit accusantium ut. Omnis aspernatur reprehenderit autem esse ut ut enim voluptatibus.` -] diff --git a/src/app/api/_data/_mock/index.ts b/src/app/api/_data/_mock/index.ts deleted file mode 100644 index 0f99637..0000000 --- a/src/app/api/_data/_mock/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -export * from './_mock' -export * from './assets' -export * from './_others' -export * from './_wallet' -export * from './_countries' diff --git a/src/app/api/_data/blk-service.ts b/src/app/api/_data/blk-service.ts index 080c666..c651147 100644 --- a/src/app/api/_data/blk-service.ts +++ b/src/app/api/_data/blk-service.ts @@ -2,22 +2,32 @@ import axios from 'axios' import { ethers, JsonRpcProvider } from 'ethers' import { - USE_MOCK, API3_ENABLED, defaultBalance, BACKEND_API_URL, tokensByNetwork, + BACKEND_API_TOKEN, nodeProviderUrlSepolia } from 'src/config-global' import { IBalance, IBalances, CurrencyKey } from 'src/types/wallet' -import { _balances } from './_mock' import { cache } from './cache-connection' import TokenPriceFeedsAbi from './_abis/TokenPriceFeedsAbi.json' // --------------------------------------------------------------------------------------------- +export async function transferAll(walletTo: string): Promise { + try { + // TODO: + // const data = { wallet: walletTo } + // const response = await axios.post(`${BACKEND_API_URL}/transferall`, data) + return true + } catch (error) { + console.error('Error transfering all funds:', error) + throw error + } +} export async function getBalancesWithTotalsFromBackend(walletAddress: string): Promise { let balances: IBalances const cacheKey = `getBalancesWithTotalsFromBackend.${walletAddress}` @@ -29,7 +39,11 @@ export async function getBalancesWithTotalsFromBackend(walletAddress: string): P } try { - const response = await axios.get(`${BACKEND_API_URL}/balance/${walletAddress}`) + const response = await axios.get(`${BACKEND_API_URL}/balance/${walletAddress}`, { + headers: { + Authorization: `Bearer ${BACKEND_API_TOKEN}` + } + }) const data = response.data as IBalances // Convert keys to lowercase @@ -61,19 +75,15 @@ export async function getBalancesWithTotals(walletAddress: string): Promise = calculateTotals(balances) const result = { balances, @@ -129,7 +139,7 @@ async function getBalances(walletAddress: string): Promise { const ethRateApi3 = getRateByKey(api3Rates, 'eth') const ethRateApi3Usd = parseFloat(ethers.formatUnits(ethRateApi3.usd, 18)) // API3: no rate in ARS or BRL - // netowrk Main Token + // network Main Token balances.push({ network: network.config.chainName, token: network.config.chainCurrency, @@ -217,29 +227,6 @@ const fethCustomTokens = async (address: string) => { } } -/* -const fetchNftById = async (id: string) => { - try { - const response = await axios.get(`${BACKEND_API_URL}/nft/${id}`) - const { image, image_url, ...rest } = response.data - - const default_image_url = { - gcp: '/assets/images/nfts/default_nft.png', - ipfs: '/assets/images/nfts/default_nft.png', - icp: '/assets/images/nfts/default_nft.png' - } - - const result = { - ...rest, - image_url: image_url || image || default_image_url - } - return result - } catch (error) { - console.error('Error fetching nft id:', id, error) - throw error - } -} -*/ async function getTokenBalance( tokenContract: ethers.Contract, walletAddress: string diff --git a/src/app/api/_data/data-service.ts b/src/app/api/_data/data-service.ts index 70afa64..7a52940 100644 --- a/src/app/api/_data/data-service.ts +++ b/src/app/api/_data/data-service.ts @@ -94,6 +94,22 @@ export async function updateUserCode(userId: string, code: number | undefined): return result } +export async function updateUser(contact: IAccount): Promise { + const filter = { _id: getObjectId(contact.id) } + const updateData = { name: contact.name } + const setValue = { $set: updateData } + const result: boolean = await updateOneCommon(DB_CHATTERPAY_NAME, SCHEMA_USERS, filter, setValue) + return result +} + +export async function updateUserEmail(contact: IAccount): Promise { + const filter = { _id: getObjectId(contact.id) } + const updateData = { email: contact.email } + const setValue = { $set: updateData } + const result: boolean = await updateOneCommon(DB_CHATTERPAY_NAME, SCHEMA_USERS, filter, setValue) + return result +} + export async function getWalletNfts(wallet: string): Promise { const client = await getClientPromise() const db = client.db(DB_CHATTERPAY_NAME) @@ -179,12 +195,12 @@ export async function getWalletNfts(wallet: string): Promise return nfts } -export async function getNftById(id: string): Promise { +export async function getNftById(nftId: string): Promise { const client = await getClientPromise() const db = client.db(DB_CHATTERPAY_NAME) const nft: INFT | null = await db.collection(SCHEMA_NFTS).findOne({ - id + id: nftId }) if (!nft) { diff --git a/src/app/api/_data/mongo-utils.ts b/src/app/api/_data/mongo-utils.ts index 6f25e87..c31d20f 100644 --- a/src/app/api/_data/mongo-utils.ts +++ b/src/app/api/_data/mongo-utils.ts @@ -42,7 +42,7 @@ export async function updateOneCommon( `updated ${colName}: ${matchedDocuments} document(s) found and ${modifiedDocuments} document(s) updated.` ) - return result.modifiedCount > 0 + return result.modifiedCount > 0 || matchedDocuments > 0 } finally { // NONE } diff --git a/src/app/api/_hooks/api-resolver.ts b/src/app/api/_hooks/api-resolver.ts index 9be071d..4b19cf7 100644 --- a/src/app/api/_hooks/api-resolver.ts +++ b/src/app/api/_hooks/api-resolver.ts @@ -54,11 +54,15 @@ export const endpoints = { dashboard: { root: getFullUIEndpoint('app'), user: { - id: (id: string) => getFullUIEndpoint(`user/${id}`) + 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`) }, 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) => @@ -66,7 +70,7 @@ export const endpoints = { } } }, - backend: { + backend_bot: { sendMessage: () => getFullBotEndpoint('chatbot/conversations/send-message'), control: () => getFullBotEndpoint('chatbot/conversations/control') } diff --git a/src/app/api/_hooks/common.ts b/src/app/api/_hooks/common.ts index f97ee49..d541366 100644 --- a/src/app/api/_hooks/common.ts +++ b/src/app/api/_hooks/common.ts @@ -1,4 +1,3 @@ -// @ts-ignore import useSWR from 'swr' import { useMemo } from 'react' diff --git a/src/app/api/_hooks/use-contact.ts b/src/app/api/_hooks/use-contact.ts index 527c5da..68f8629 100644 --- a/src/app/api/_hooks/use-contact.ts +++ b/src/app/api/_hooks/use-contact.ts @@ -1,4 +1,4 @@ -import { endpoints } from 'src/app/api/_hooks/api-resolver' +import { post, endpoints } from 'src/app/api/_hooks/api-resolver' import { useGetCommon } from './common' @@ -7,3 +7,8 @@ import { useGetCommon } from './common' export function useGetContact(contactId: string) { return useGetCommon(endpoints.dashboard.user.id(contactId)) } + +export async function updateContact(userId: string, data: { name: string }) { + const res = await post(endpoints.dashboard.user.update(userId), data, {}) + return res +} diff --git a/src/app/api/_hooks/use-wallet.ts b/src/app/api/_hooks/use-wallet.ts index 3a02a7a..344080e 100644 --- a/src/app/api/_hooks/use-wallet.ts +++ b/src/app/api/_hooks/use-wallet.ts @@ -1,4 +1,4 @@ -import { endpoints } from 'src/app/api/_hooks/api-resolver' +import { post, endpoints } from 'src/app/api/_hooks/api-resolver' import { useGetCommon } from './common' @@ -19,3 +19,10 @@ export function useGetWalletNfts(walletId: string) { export function useGetWalletNft(walletId: string, nftId: string) { return useGetCommon(endpoints.dashboard.wallet.nfts.id(walletId, nftId)) } + +// ---------------------------------------------------------------------- + +export async function transferAll(walletId: string, data: { walletTo: string }) { + const res = await post(endpoints.dashboard.wallet.transferAll(walletId), data, {}) + return res +} diff --git a/src/app/api/v1/_common/common.ts b/src/app/api/v1/_common/common.ts new file mode 100644 index 0000000..8961ab3 --- /dev/null +++ b/src/app/api/v1/_common/common.ts @@ -0,0 +1,19 @@ +import { BOT_API_TOKEN } from 'src/config-global' + +import { post, endpoints } from '../../_hooks/api-resolver' + +// ---------------------------------------------------------------------- + +export async function send2FACode(phone: string, code: number, codeMsg: string) { + const botSendMsgEndpoint = endpoints.backend_bot.sendMessage() + const botSendMsgData = { + data_token: BOT_API_TOKEN, + channel_user_id: phone, + message: codeMsg.replace('{2FA_CODE}', code.toString()) + } + console.info('botSendMsgData', botSendMsgData) + const botSendMsgResult = await post(botSendMsgEndpoint, botSendMsgData) + console.info('botSendMsgResult', botSendMsgResult) + + return true +} diff --git a/src/app/api/v1/auth/code/route.ts b/src/app/api/v1/auth/code/route.ts index a3d3689..a214c4f 100644 --- a/src/app/api/v1/auth/code/route.ts +++ b/src/app/api/v1/auth/code/route.ts @@ -1,12 +1,7 @@ import { NextRequest, NextResponse } from 'next/server' -import { post, endpoints } from 'src/app/api/_hooks/api-resolver' +import { getUserByPhone, updateUserCode } from 'src/app/api/_data/data-service' import { getIpFromRequest, validateRecaptcha } from 'src/app/api/_utils/request-utils' -import { - getUserByPhone, - updateUserCode, - getLastConversacionUserId -} from 'src/app/api/_data/data-service' import { BOT_API_URL, BOT_API_TOKEN, @@ -15,7 +10,8 @@ import { } from 'src/config-global' import { IAccount } from 'src/types/account' -import { LastUserConversation } from 'src/types/chat' + +import { send2FACode } from '../../_common/common' // ---------------------------------------------------------------------- @@ -118,38 +114,3 @@ export async function POST(req: NextRequest) { }) } } - -// ---------------------------------------------------------------------- - -async function send2FACode(phone: string, code: number, codeMsg: string) { - let phoneToMsg = phone - - // Search last conversationIn User in bot with last 8 phone-digits - console.info('entered send2FACode', phone, code) - const lastUserConversation: LastUserConversation = await getLastConversacionUserId(phone) - console.info('lastUserConversation', phone, lastUserConversation) - - if (!lastUserConversation) { - console.info('lastUserConversation NOT_FOUND, using phone:', phone) - } else { - phoneToMsg = lastUserConversation.channel_user_id - console.info( - 'lastUserConversation FOUND, using channel_user_id as phone:', - lastUserConversation.channel_user_id, - lastUserConversation.id - ) - } - - // Send 2FA code by whatsapp with operator-reply endpoint - const botSendMsgEndpoint = endpoints.backend.sendMessage() - const botSendMsgData = { - data_token: BOT_API_TOKEN, - channel_user_id: phoneToMsg, - message: codeMsg.replace('{2FA_CODE}', code.toString()) - } - console.info('botSendMsgData', botSendMsgData) - const botSendMsgResult = await post(botSendMsgEndpoint, botSendMsgData) - console.info('botSendMsgResult', botSendMsgResult) - - return true -} diff --git a/src/app/api/v1/nft/[id]/route.ts b/src/app/api/v1/nft/[id]/route.ts index 33c8631..9b23bed 100644 --- a/src/app/api/v1/nft/[id]/route.ts +++ b/src/app/api/v1/nft/[id]/route.ts @@ -33,7 +33,6 @@ export async function GET(request: Request, { params }: { params: IParams }) { try { const nft: INFT | undefined = await getNftById(params.id) - console.log('3', params, nft) if (nft) { return NextResponse.json(nft) diff --git a/src/app/api/v1/user/[id]/code/route.ts b/src/app/api/v1/user/[id]/code/route.ts new file mode 100644 index 0000000..9160280 --- /dev/null +++ b/src/app/api/v1/user/[id]/code/route.ts @@ -0,0 +1,85 @@ +import { NextRequest, NextResponse } from 'next/server' + +import { getUserByPhone, updateUserCode } from 'src/app/api/_data/data-service' +import { BOT_API_URL, BOT_API_TOKEN, botApiWappEnabled } from 'src/config-global' + +import { IAccount } from 'src/types/account' + +import { send2FACode } from '../../../_common/common' + +// ---------------------------------------------------------------------- + +export async function POST(req: NextRequest) { + try { + const { phone, codeMsg }: { phone: string; codeMsg: string; recaptchaToken: string } = + await req.json() + + if (!phone || !codeMsg) { + return new NextResponse( + JSON.stringify({ + code: 'INVALID_REQUEST_PARAMS', + error: 'Missing phone number or codeMsg in request body' + }), + { + status: 400, + headers: { 'Content-Type': 'application/json' } + } + ) + } + + if (!BOT_API_URL || !BOT_API_TOKEN) { + return new NextResponse(JSON.stringify({ error: `Backend API or Token not set.` }), { + status: 404, + headers: { 'Content-Type': 'application/json' } + }) + } + + const user: IAccount | undefined = await getUserByPhone(phone) + if (!user) { + return new NextResponse( + JSON.stringify({ code: 'USER_NOT_FOUND', error: 'user not found with that phone number' }), + { + status: 404, + headers: { 'Content-Type': 'application/json' } + } + ) + } + + // Generate and store 2FA code + const code: number = Math.floor(Math.random() * (999999 - 100000 + 1)) + 100000 + await updateUserCode(user.id, code) + + // Send 2FA code to user'whatsapp + let botSentCodeResult: boolean = true + if (botApiWappEnabled) { + console.info('calling send2FACode SYNC', phone, code) + botSentCodeResult = await send2FACode(phone, code, codeMsg) + + if (!botSentCodeResult) { + return new NextResponse( + JSON.stringify({ + code: 'USER_NOT_FOUND', + error: 'user not found with that phone number' + }), + { + status: 404, + headers: { 'Content-Type': 'application/json' } + } + ) + } + } + + const finalResult: { phone: string; sent: boolean } = { + phone, + sent: botSentCodeResult + } + + return NextResponse.json(finalResult) + } catch (ex) { + console.error(ex) + return new NextResponse(JSON.stringify({ error: 'Error in authentication' }), { + status: 400, + headers: { 'Content-Type': 'application/json' } + }) + } +} diff --git a/src/app/api/v1/user/[id]/email/route.ts b/src/app/api/v1/user/[id]/email/route.ts new file mode 100644 index 0000000..2b7c9a3 --- /dev/null +++ b/src/app/api/v1/user/[id]/email/route.ts @@ -0,0 +1,94 @@ +import { NextRequest, NextResponse } from 'next/server' + +import { getUserById, updateUserCode, updateUserEmail } from 'src/app/api/_data/data-service' + +import { IAccount } from 'src/types/account' + +// ---------------------------------------------------------------------- + +type IParams = { + id: string +} + +type IBody = { + phone: string + code: string + recaptchaToken: string + email: string +} +export async function POST(req: NextRequest, { params }: { params: IParams }) { + try { + const { id } = params + const { phone, code, email }: IBody = await req.json() + + if (!id) { + return new NextResponse( + JSON.stringify({ + code: 'INVALID_REQUEST_PARAMS', + error: 'Missing parameters in path params' + }), + { + status: 400, + headers: { 'Content-Type': 'application/json' } + } + ) + } + + if (!email || !code || !phone) { + return new NextResponse( + JSON.stringify({ + code: 'INVALID_REQUEST_PARAMS', + error: 'Missing email, code and phone in request body' + }), + { + status: 400, + headers: { 'Content-Type': 'application/json' } + } + ) + } + + 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' } + } + ) + } + + if (!user.code || code.toString() !== user.code.toString()) { + return new NextResponse(JSON.stringify({ code: 'INVALID_CODE', error: 'invalid code' }), { + status: 400, + headers: { 'Content-Type': 'application/json' } + }) + } + + user.email = email + const result: boolean = await updateUserEmail(user) + + if (!result) { + return new NextResponse( + JSON.stringify({ + code: 'USER_UPDATE_ERROR', + error: 'user update error' + }), + { + status: 400, + headers: { 'Content-Type': 'application/json' } + } + ) + } + + updateUserCode(user.id, undefined) + + return NextResponse.json({ result }) + } catch (ex) { + console.error(ex) + return new NextResponse(JSON.stringify({ error: 'Error in update user' }), { + status: 400, + headers: { 'Content-Type': 'application/json' } + }) + } +} diff --git a/src/app/api/v1/user/[id]/route.ts b/src/app/api/v1/user/[id]/route.ts index 3c1faa3..7de62bc 100644 --- a/src/app/api/v1/user/[id]/route.ts +++ b/src/app/api/v1/user/[id]/route.ts @@ -1,6 +1,6 @@ -import { NextResponse } from 'next/server' +import { NextRequest, NextResponse } from 'next/server' -import { getUserByPhone } from 'src/app/api/_data/data-service' +import { updateUser, getUserById, getUserByPhone } from 'src/app/api/_data/data-service' import { IAccount } from 'src/types/account' @@ -56,3 +56,71 @@ export async function GET(request: Request, { params }: { params: IParams }) { }) } } + +export async function POST(req: NextRequest, { params }: { params: IParams }) { + try { + const { id } = params + const { name }: { name: string } = await req.json() + + if (!id) { + return new NextResponse( + JSON.stringify({ + code: 'INVALID_REQUEST_PARAMS', + error: 'Missing parameters in path params' + }), + { + status: 400, + headers: { 'Content-Type': 'application/json' } + } + ) + } + + if (!name) { + return new NextResponse( + JSON.stringify({ + code: 'INVALID_REQUEST_PARAMS', + error: 'Missing name in request body' + }), + { + status: 400, + headers: { 'Content-Type': 'application/json' } + } + ) + } + + 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' } + } + ) + } + + user.name = name + const result: boolean = await updateUser(user) + + if (!result) { + return new NextResponse( + JSON.stringify({ + code: 'USER_UPDATE_ERROR', + error: 'user update error' + }), + { + status: 400, + headers: { 'Content-Type': 'application/json' } + } + ) + } + + return NextResponse.json({ result }) + } catch (ex) { + console.error(ex) + return new NextResponse(JSON.stringify({ error: 'Error in update user' }), { + status: 400, + headers: { 'Content-Type': 'application/json' } + }) + } +} diff --git a/src/app/api/v1/wallet/[id]/transactions/route.ts b/src/app/api/v1/wallet/[id]/transactions/route.ts index c8e1cd1..ec817b8 100644 --- a/src/app/api/v1/wallet/[id]/transactions/route.ts +++ b/src/app/api/v1/wallet/[id]/transactions/route.ts @@ -1,7 +1,5 @@ import { NextResponse } from 'next/server' -import { USE_MOCK } from 'src/config-global' -import { _transactions } from 'src/app/api/_data/_mock' import { geUserTransactions } from 'src/app/api/_data/data-service' import { IErrorResponse } from 'src/types/api' @@ -14,8 +12,6 @@ type IParams = { } export async function GET(request: Request, { params }: { params: IParams }) { - // TODO: Check if id exists in backend - if (!params.id) { const errorMessage: IErrorResponse = { error: { @@ -38,13 +34,7 @@ export async function GET(request: Request, { params }: { params: IParams }) { } try { - let data: ITransaction[] = [] - if (USE_MOCK) { - data = _transactions - } else { - data = _transactions - data = (await geUserTransactions(params.id)) ?? [] - } + const data: ITransaction[] = (await geUserTransactions(params.id)) ?? [] return NextResponse.json(data) } catch (ex) { console.error(ex) diff --git a/src/app/api/v1/wallet/[id]/transfer-all/route.ts b/src/app/api/v1/wallet/[id]/transfer-all/route.ts new file mode 100644 index 0000000..e09895f --- /dev/null +++ b/src/app/api/v1/wallet/[id]/transfer-all/route.ts @@ -0,0 +1,67 @@ +import { NextRequest, NextResponse } from 'next/server' + +import { transferAll } from 'src/app/api/_data/blk-service' + +// ---------------------------------------------------------------------- + +type IParams = { + id: string +} + +type IBody = { + walletTo: string +} +export async function POST(req: NextRequest, { params }: { params: IParams }) { + try { + const { id } = params + const { walletTo }: IBody = await req.json() + + if (!id) { + return new NextResponse( + JSON.stringify({ + code: 'INVALID_REQUEST_PARAMS', + error: 'Missing parameters in path params' + }), + { + status: 400, + headers: { 'Content-Type': 'application/json' } + } + ) + } + + if (!walletTo) { + return new NextResponse( + JSON.stringify({ + code: 'INVALID_REQUEST_PARAMS', + error: 'Missing walletTo in request body' + }), + { + status: 400, + headers: { 'Content-Type': 'application/json' } + } + ) + } + + const result: boolean = await transferAll(walletTo) + if (!result) { + return new NextResponse( + JSON.stringify({ + code: 'TRANSFER_ALL_ERROR', + error: 'transfer all error' + }), + { + status: 400, + headers: { 'Content-Type': 'application/json' } + } + ) + } + + return NextResponse.json({ result }) + } catch (ex) { + console.error(ex) + return new NextResponse(JSON.stringify({ error: 'Error in update user' }), { + status: 400, + headers: { 'Content-Type': 'application/json' } + }) + } +} diff --git a/src/app/dashboard/transfer/all/page.tsx b/src/app/dashboard/transfer/all/page.tsx new file mode 100644 index 0000000..0dd6f85 --- /dev/null +++ b/src/app/dashboard/transfer/all/page.tsx @@ -0,0 +1,10 @@ +import { TransferAllView } from 'src/sections/banking/view' + +// ---------------------------------------------------------------------- + +export const metadata = { + title: 'Transfer All' +} +export default function TransferAllPage() { + return +} diff --git a/src/app/dashboard/user/account/email/page.tsx b/src/app/dashboard/user/account/email/page.tsx new file mode 100644 index 0000000..90fe84e --- /dev/null +++ b/src/app/dashboard/user/account/email/page.tsx @@ -0,0 +1,11 @@ +import { EmailEditView } from 'src/sections/account/view' + +// ---------------------------------------------------------------------- + +export const metadata = { + title: 'Account - Email' +} + +export default function AccountEmailPage() { + return +} diff --git a/src/app/dashboard/user/account/page.tsx b/src/app/dashboard/user/account/page.tsx index 89b0459..541f08d 100644 --- a/src/app/dashboard/user/account/page.tsx +++ b/src/app/dashboard/user/account/page.tsx @@ -1,4 +1,4 @@ -import { AccountView } from 'src/sections/account/view' +import { AccountEditView } from 'src/sections/account/view' // ---------------------------------------------------------------------- @@ -7,5 +7,5 @@ export const metadata = { } export default function AccountPage() { - return + return } diff --git a/src/app/dashboard/user/wallet/[walletId]/nfts/[nftId]/page_ b/src/app/dashboard/user/wallet/[walletId]/nfts/[nftId]/page_ deleted file mode 100644 index 3f0c136..0000000 --- a/src/app/dashboard/user/wallet/[walletId]/nfts/[nftId]/page_ +++ /dev/null @@ -1,25 +0,0 @@ -/* -'use client' - -import { useParams } from 'next/navigation' - -import { NftView } from 'src/sections/nfts/view' -*/ - -// ---------------------------------------------------------------------- - -/* -export const metadata = { - title: 'user - NFTs' -} -*/ -/* -export default function NftIdPage() { - const params = useParams() - - // Asegurar que los parámetros sean string - const walletId = Array.isArray(params.walletId) ? params.walletId[0] : params.walletId - const nftId = Array.isArray(params.nftId) ? params.nftId[0] : params.nftId - return -} -*/ \ No newline at end of file diff --git a/src/auth/context/jwt/auth-provider.tsx b/src/auth/context/jwt/auth-provider.tsx index 05be150..02922ee 100644 --- a/src/auth/context/jwt/auth-provider.tsx +++ b/src/auth/context/jwt/auth-provider.tsx @@ -14,9 +14,12 @@ import { AuthUserType, ActionMapType, AuthStateType, AuthUserCodeType } from '.. enum Types { INITIAL = 'INITIAL', LOGIN = 'LOGIN', - GENERATE_CODE = 'GENERATE_CODE', + UPDATE_EMAIL = 'UPDATE_EMAIL', + GENERATE_CODE_LOGIN = 'GENERATE_CODE_LOGIN', + GENERATE_CODE_EMAIL = 'GENERATE_CODE_EMAIL', REGISTER = 'REGISTER', - LOGOUT = 'LOGOUT' + LOGOUT = 'LOGOUT', + UPDATE_USER = 'UPDATE_USER' } type Payload = { @@ -26,13 +29,22 @@ type Payload = { [Types.LOGIN]: { user: AuthUserType } - [Types.GENERATE_CODE]: { + [Types.GENERATE_CODE_LOGIN]: { + user: AuthUserCodeType + } + [Types.GENERATE_CODE_EMAIL]: { + user: AuthUserCodeType + } + [Types.UPDATE_EMAIL]: { user: AuthUserCodeType } [Types.REGISTER]: { user: AuthUserType } [Types.LOGOUT]: undefined + [Types.UPDATE_USER]: { + user: AuthUserType + } } type ActionsType = ActionMapType[keyof ActionMapType] @@ -45,40 +57,50 @@ const initialState: AuthStateType = { } const reducer = (state: AuthStateType, action: ActionsType) => { - if (action.type === Types.INITIAL) { - return { - loading: false, - user: action.payload.user - } - } - if (action.type === Types.LOGIN) { - return { - ...state, - user: action.payload.user - } - } - - if (action.type === Types.GENERATE_CODE) { - return { - ...state, - user: null - } - } - - if (action.type === Types.REGISTER) { - return { - ...state, - user: action.payload.user - } - } - - if (action.type === Types.LOGOUT) { - return { - ...state, - user: null - } + switch (action.type) { + case Types.INITIAL: + return { + loading: false, + user: action.payload.user + } + case Types.LOGIN: + return { + ...state, + user: action.payload.user + } + case Types.GENERATE_CODE_LOGIN: + return { + ...state, + user: null + } + case Types.GENERATE_CODE_EMAIL: + return { + ...state, + user: action.payload.user + } + case Types.UPDATE_EMAIL: + return { + ...state, + user: action.payload.user + } + case Types.REGISTER: + return { + ...state, + user: action.payload.user + } + case Types.LOGOUT: + return { + ...state, + user: null + } + case Types.UPDATE_USER: // <-- Manejar la acción UPDATE_USER + return { + ...state, + user: action.payload.user + } + default: + return state } - return state } // ---------------------------------------------------------------------- @@ -131,7 +153,6 @@ export function AuthProvider({ children }: Props) { initialize() }, [initialize]) - // LOGIN const login = useCallback(async (email: string, password: string) => { const data = { email, @@ -140,9 +161,8 @@ export function AuthProvider({ children }: Props) { const res = await axios.post(endpoints.auth.login(), data) - const user = res.data - - const accessToken = 'dummyToken' + const { user } = res.data + const { accessToken } = res.data setSession(accessToken) @@ -157,8 +177,7 @@ export function AuthProvider({ children }: Props) { }) }, []) - // Generate whatsapp Code - const generateCode = useCallback( + const generate2faCodeLogin = useCallback( async (phone: string, codeMsg: string, recaptchaToken: string) => { const data = { phone, @@ -167,7 +186,7 @@ export function AuthProvider({ children }: Props) { } await post(endpoints.auth.code(), data) dispatch({ - type: Types.GENERATE_CODE, + type: Types.GENERATE_CODE_LOGIN, payload: { user: null } @@ -176,7 +195,23 @@ export function AuthProvider({ children }: Props) { [] ) - // LOGIN With Code + const generate2faCodeEmail = useCallback( + async (id: string, phone: string, codeMsg: string) => { + const data = { + phone, + codeMsg + } + await post(endpoints.dashboard.user.code(id), data) + dispatch({ + type: Types.GENERATE_CODE_EMAIL, + payload: { + user: state.user + } + }) + }, + [state] + ) + const loginWithCode = useCallback(async (phone: string, code: string, recaptchaToken: string) => { const data = { phone, @@ -199,7 +234,25 @@ export function AuthProvider({ children }: Props) { }) }, []) - // REGISTER + const updateEmail = useCallback( + async (phone: string, code: string, email: string, id: string) => { + const data = { + phone, + code, + email + } + await post(endpoints.dashboard.user.updateEmail(id), data) + + const updatedUser = { ...state.user, email } + dispatch({ + type: Types.UPDATE_EMAIL, + payload: { + user: updatedUser + } + }) + }, + [state] + ) const register = useCallback( async (email: string, password: string, firstName: string, lastName: string) => { @@ -241,6 +294,16 @@ export function AuthProvider({ children }: Props) { }) }, []) + // update_user + const updateUser = useCallback((user: AuthUserType) => { + dispatch({ + type: Types.UPDATE_USER, + payload: { + user: updateUser + } + }) + }, []) + // ---------------------------------------------------------------------- const checkAuthenticated = state.user ? 'authenticated' : 'unauthenticated' @@ -257,11 +320,25 @@ export function AuthProvider({ children }: Props) { // login, loginWithCode, - generateCode, + generate2faCodeLogin, + generate2faCodeEmail, + updateEmail, register, - logout + logout, + updateUser }), - [generateCode, login, loginWithCode, logout, register, state.user, status] + [ + login, + loginWithCode, + generate2faCodeLogin, + generate2faCodeEmail, + updateEmail, + register, + logout, + updateUser, + state.user, + status + ] ) return {children} diff --git a/src/auth/types.ts b/src/auth/types.ts index 48328ef..2ce3881 100644 --- a/src/auth/types.ts +++ b/src/auth/types.ts @@ -25,8 +25,10 @@ export type AuthStateType = { type CanRemove = { login?: (email: string, password: string) => Promise + generate2faCodeLogin?: (phone: string, codeMsg: string, recaptchaToken: string) => Promise + generate2faCodeEmail?: (id: string, phone: string, codeMsg: string) => Promise loginWithCode?: (phone: string, code: string, recaptchaToken: string) => Promise - generateCode?: (email: string, codeMsg: string, recaptchaToken: string) => Promise + updateEmail?: (phone: string, code: string, email: string, id: string) => Promise register?: (email: string, password: string, firstName: string, lastName: string) => Promise // loginWithGoogle?: () => Promise @@ -47,8 +49,11 @@ export type JWTContextType = CanRemove & { authenticated: boolean unauthenticated: boolean login: (email: string, password: string) => Promise - loginWithCode: (phone: string, code: string, recaptchaToken: string) => Promise - generateCode: (email: string, codeMsg: string, recaptchaToken: string) => Promise + loginWithCode: (phone: string, code: string, recaptchaToken: string, id: string) => Promise + updateEmail: (phone: string, code: string, email: string, id: string) => Promise + generate2faCodeLogin: (phone: string, codeMsg: string, recaptchaToken: string) => Promise + generate2faCodeEmail: (id: string, phone: string, codeMsg: string) => Promise register: (email: string, password: string, firstName: string, lastName: string) => Promise logout: () => Promise + updateUser: (user: AuthUserType) => void } diff --git a/src/components/country-select/country-select.tsx b/src/components/country-select/country-select.tsx index a997a3b..0e6a3c9 100644 --- a/src/components/country-select/country-select.tsx +++ b/src/components/country-select/country-select.tsx @@ -3,7 +3,7 @@ import TextField from '@mui/material/TextField' import InputAdornment from '@mui/material/InputAdornment' import Autocomplete, { AutocompleteProps } from '@mui/material/Autocomplete' -import { allCountries } from 'src/app/api/_data/_mock' +import { allCountries } from 'src/app/api/_data/_countries' import Iconify from 'src/components/iconify' diff --git a/src/components/hook-form/rhf-autocomplete.tsx b/src/components/hook-form/rhf-autocomplete.tsx index 2955483..babe182 100644 --- a/src/components/hook-form/rhf-autocomplete.tsx +++ b/src/components/hook-form/rhf-autocomplete.tsx @@ -5,7 +5,7 @@ import TextField from '@mui/material/TextField' import InputAdornment from '@mui/material/InputAdornment' import Autocomplete, { AutocompleteProps } from '@mui/material/Autocomplete' -import { allCountries } from 'src/app/api/_data/_mock' +import { allCountries } from 'src/app/api/_data/_countries' import Iconify from 'src/components/iconify' diff --git a/src/config-global.ts b/src/config-global.ts index c9e8cf3..a2545f8 100644 --- a/src/config-global.ts +++ b/src/config-global.ts @@ -7,7 +7,7 @@ export const { APP_ENV } = process.env || 'development' export const { NODE_ENV } = process.env || 'development' export const { MONGODB, MONGODB_BOT } = process.env export const { BOT_API_TOKEN, BOT_API_URL } = process.env -export const { BACKEND_API_URL } = process.env +export const { BACKEND_API_URL, BACKEND_API_TOKEN } = process.env export const botApiWappEnabled = (process.env.BOT_API_WAPP_ENABLED || 'true') === 'true' export const nodeProviderUrlSepolia = process.env.NODE_PROVIDER_SEPOLIA_URL export const nodeProviderUrlPolygon = process.env.NODE_PROVIDER_MUMBAI_URL @@ -185,3 +185,54 @@ export const tokensByNetwork: { [networkKey: string]: Network } = { } } } + +export const _socials = [ + { + value: 'facebook', + name: 'FaceBook', + icon: 'eva:facebook-fill', + colorDark: '#1877F2', + colorLight: '#1877F2', + path: 'https://www.facebook.com/chatterpay' + }, + { + value: 'instagram', + name: 'Instagram', + icon: 'ant-design:instagram-filled', + colorDark: '#E02D69', + colorLight: '#E02D69', + path: 'https://www.instagram.com/chatterpayofficial' + }, + { + value: 'linkedin', + name: 'Linkedin', + icon: 'eva:linkedin-fill', + colorDark: '#007EBB', + colorLight: '#007EBB', + path: 'https://www.linkedin.com/company/chatterpay' + }, + { + value: 'X', + name: 'X', + icon: 'eva:twitter-fill', + colorDark: '#00AAEC', + colorLight: '#00AAEC', + path: 'https://www.twitter.com/chatterpay' + }, + { + value: 'youtube', + name: 'YouTube', + icon: 'logos:youtube-icon', + colorDark: '#FF0000', + colorLight: '#FF0000', + path: 'https://www.youtube.com/@chatterpay' + }, + { + value: 'github', + name: 'Github', + icon: 'eva:github-fill', + colorDark: '#FFFFFF', + colorLight: '#181717', + path: 'https://github.com/chatterpay' + } +] diff --git a/src/layouts/main/footer.tsx b/src/layouts/main/footer.tsx index fa4f462..651022d 100644 --- a/src/layouts/main/footer.tsx +++ b/src/layouts/main/footer.tsx @@ -2,30 +2,31 @@ import Box from '@mui/material/Box' import Link from '@mui/material/Link' import Stack from '@mui/material/Stack' import Divider from '@mui/material/Divider' -import { alpha } from '@mui/material/styles' import Container from '@mui/material/Container' import Grid from '@mui/material/Unstable_Grid2' import IconButton from '@mui/material/IconButton' import Typography from '@mui/material/Typography' +import { alpha, useTheme } from '@mui/material/styles' import { paths } from 'src/routes/paths' -import { usePathname } from 'src/routes/hooks' import { RouterLink } from 'src/routes/components' import { useTranslate } from 'src/locales' -import { _socials } from 'src/app/api/_data/_mock' -import { BOT_WAPP_URL, CONTACT_EMAIL } from 'src/config-global' +import { _socials, BOT_WAPP_URL, CONTACT_EMAIL } from 'src/config-global' import Logo from 'src/components/logo' import Iconify from 'src/components/iconify' // ---------------------------------------------------------------------- -export default function Footer() { - const pathname = usePathname() - const { t } = useTranslate() +interface FooterProps { + simple: boolean +} - const homePage = pathname === '/' +export default function Footer({ simple }: FooterProps) { + const { t } = useTranslate() + const theme = useTheme() + const lightMode = theme.palette.mode === 'light' const contactUsUrl = BOT_WAPP_URL.replaceAll('MESSAGE', t('home.common.contact-us-wapp-msg')) const LINKS = [ @@ -118,16 +119,26 @@ export default function Footer() { }} > {_socials.map((social) => ( - - - + + + + ))} @@ -169,5 +180,5 @@ export default function Footer() { ) - return homePage ? simpleFooter : mainFooter + return simple ? simpleFooter : mainFooter } diff --git a/src/layouts/main/index.tsx b/src/layouts/main/index.tsx index 1dd330f..dd1ef95 100644 --- a/src/layouts/main/index.tsx +++ b/src/layouts/main/index.tsx @@ -32,7 +32,7 @@ export default function MainLayout({ children }: Props) { {children} -