diff --git a/.circleci/config.yml b/.circleci/config.yml deleted file mode 100644 index ac0f9788..00000000 --- a/.circleci/config.yml +++ /dev/null @@ -1,95 +0,0 @@ -version: 2.1 - -orbs: - aws-ecr: circleci/aws-ecr@8.2.1 - kubernetes: circleci/kubernetes@1.3.1 - helm: circleci/helm@2.0.1 - node: circleci/node@5.2.0 - -jobs: - build: - machine: - image: ubuntu-2204:2024.01.1 - resource_class: large - steps: - - checkout - - node/install: - node-version: "22.3" - - run: - name: Install dependencies - command: | - npm install - - run: - name: Run tests - command: | - npm run test - - run: - name: Build project - command: | - npm run build - - build_docker: - machine: - image: ubuntu-2204:2024.01.1 - resource_class: large - steps: - - checkout - - aws-ecr/build-image: - push-image: false - dockerfile: Dockerfile - path: ./ - build-path: ./ - tag: "$CIRCLE_SHA1,$CIRCLE_TAG" - repo: "simple-staking" - - run: - name: Save Docker image to export it to workspace - command: | - docker save $(docker image ls --format '{{.Repository}}:{{.Tag}}') > /tmp/simple-staking.tar - - persist_to_workspace: - root: /tmp - paths: - - simple-staking.tar - - push_docker: - machine: - image: ubuntu-2204:2024.01.1 - resource_class: large - steps: - - attach_workspace: - at: /tmp - - run: - name: Load Docker image from workspace - command: | - docker load -i /tmp/simple-staking.tar - - aws-ecr/ecr-login: - aws-access-key-id: AWS_ACCESS_KEY_ID - aws-secret-access-key: AWS_SECRET_ACCESS_KEY - region: "$AWS_REGION" - - aws-ecr/push-image: - registry-id: AWS_ECR_REGISTRY_ID - region: "$AWS_REGION" - repo: "simple-staking" - tag: "$CIRCLE_SHA1,$CIRCLE_TAG" - -workflows: - CICD: - jobs: - - build - - build_docker: - filters: - tags: - only: /.*/ - branches: - only: - - dev - - main - - push_docker: - requires: - - build_docker - filters: - tags: - only: /.*/ - branches: - only: - - dev - - main diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 00000000..7083d434 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,13 @@ +name: ci + +on: + pull_request: + branches: + - '**' + +jobs: + lint_test: + uses: babylonlabs-io/.github/.github/workflows/reusable_node_lint_test.yml@v0.3.0 + with: + run-build: true + run-unit-tests: true \ No newline at end of file diff --git a/.github/workflows/publish.yaml b/.github/workflows/publish.yaml new file mode 100644 index 00000000..96ed64c2 --- /dev/null +++ b/.github/workflows/publish.yaml @@ -0,0 +1,118 @@ +name: docker_publish + +on: + push: + branches: + - 'main' + - 'dev' + tags: + - '*' + +jobs: + lint_test: + uses: babylonlabs-io/.github/.github/workflows/reusable_node_lint_test.yml@v0.3.0 + with: + run-build: true + run-unit-tests: true + + docker_build: + needs: [lint_test] + runs-on: ubuntu-22.04 + strategy: + matrix: + environment: [devnet, staging, testnet, mainnet-private, mainnet] + environment: ${{ matrix.environment }} + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Build Docker image + uses: docker/build-push-action@v6 + with: + tags: simple-staking:${{ github.sha }} + outputs: type=docker,dest=/tmp/simple-staking-${{ matrix.environment }}.tar + build-args: | + NEXT_PUBLIC_MEMPOOL_API=${{ vars.NEXT_PUBLIC_MEMPOOL_API }} + NEXT_PUBLIC_API_URL=${{ vars.NEXT_PUBLIC_API_URL }} + NEXT_PUBLIC_NETWORK=${{ vars.NEXT_PUBLIC_NETWORK }} + NEXT_PUBLIC_DISPLAY_TESTING_MESSAGES=${{ vars.NEXT_PUBLIC_DISPLAY_TESTING_MESSAGES }} + + - name: Upload Docker image to workspace + uses: actions/upload-artifact@v4 + with: + name: simple-staking-${{ matrix.environment }} + path: /tmp/simple-staking-${{ matrix.environment }}.tar + + dockerhub_publish: + runs-on: ubuntu-22.04 + strategy: + matrix: + environment: [devnet, staging, testnet, mainnet-private, mainnet] + needs: ["docker_build"] + steps: + - name: Download Docker image from workspace + uses: actions/download-artifact@v4 + with: + name: simple-staking-${{ matrix.environment }} + path: /tmp/ + + - name: Load Docker image + run: docker load -i /tmp/simple-staking-${{ matrix.environment }}.tar + + - name: Login to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Push Docker image with SHA + run: | + docker tag simple-staking:${{ github.sha }} ${{ vars.DOCKERHUB_REGISTRY_ID }}/simple-staking:${{ github.sha }}-${{ matrix.environment }} + docker push ${{ vars.DOCKERHUB_REGISTRY_ID }}/simple-staking:${{ github.sha }}-${{ matrix.environment }} + + - name: Push Docker image with Tag + if: startsWith(github.ref, 'refs/tags/') + run: | + docker tag simple-staking:${{ github.sha }} ${{ vars.DOCKERHUB_REGISTRY_ID }}/simple-staking:${{ github.ref_name }}-${{ matrix.environment }} + docker push ${{ vars.DOCKERHUB_REGISTRY_ID }}/simple-staking:${{ github.ref_name }}-${{ matrix.environment }} + + ecr_publish: + runs-on: ubuntu-22.04 + strategy: + matrix: + environment: [devnet, staging, testnet, mainnet-private, mainnet] + needs: ["docker_build"] + steps: + - name: Download Docker image from workspace + uses: actions/download-artifact@v4 + with: + name: simple-staking-${{ matrix.environment }} + path: /tmp/ + + - name: Load Docker image + run: docker load -i /tmp/simple-staking-${{ matrix.environment }}.tar + + - name: Configure AWS credentials + uses: aws-actions/configure-aws-credentials@v4 + with: + aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} + aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + aws-region: ${{ vars.AWS_ECR_REGION }} + + - name: Login to Amazon ECR Private + id: login-ecr + uses: aws-actions/amazon-ecr-login@v2 + + - name: Push Docker image with SHA + run: | + docker tag simple-staking:${{ github.sha }} ${{ vars.AWS_ECR_REGISTRY_ID }}/simple-staking:${{ github.sha }}-${{ matrix.environment }} + docker push ${{ vars.AWS_ECR_REGISTRY_ID }}/simple-staking:${{ github.sha }}-${{ matrix.environment }} + + - name: Push Docker image with Tag + if: startsWith(github.ref, 'refs/tags/') + run: | + docker tag simple-staking:${{ github.sha }} ${{ vars.AWS_ECR_REGISTRY_ID }}/simple-staking:${{ github.ref_name }}-${{ matrix.environment }} + docker push ${{ vars.AWS_ECR_REGISTRY_ID }}/simple-staking:${{ github.ref_name }}-${{ matrix.environment }} diff --git a/Dockerfile b/Dockerfile index 08973a98..c13ce121 100644 --- a/Dockerfile +++ b/Dockerfile @@ -13,17 +13,20 @@ COPY next.config.mjs . COPY tsconfig.json . COPY tailwind.config.ts . COPY postcss.config.js . -COPY docker-entrypoint.sh . - -# We replace NEXT_PUBLIC_* variables here with placeholders -# as next.js automatically replaces those during building -# Later the docker-entrypoint.sh script finds such variables and replaces them -# with the docker environment variables we have set -RUN NEXT_PUBLIC_MEMPOOL_API=APP_NEXT_PUBLIC_MEMPOOL_API \ - NEXT_PUBLIC_API_URL=APP_NEXT_PUBLIC_API_URL \ - NEXT_PUBLIC_NETWORK=APP_NEXT_PUBLIC_NETWORK \ - NEXT_PUBLIC_DISPLAY_TESTING_MESSAGES=APP_NEXT_PUBLIC_DISPLAY_TESTING_MESSAGES \ - npm run build + +ARG NEXT_PUBLIC_MEMPOOL_API +ENV NEXT_PUBLIC_MEMPOOL_API=${NEXT_PUBLIC_MEMPOOL_API} + +ARG NEXT_PUBLIC_API_URL +ENV NEXT_PUBLIC_API_URL=${NEXT_PUBLIC_API_URL} + +ARG NEXT_PUBLIC_NETWORK +ENV NEXT_PUBLIC_NETWORK=${NEXT_PUBLIC_NETWORK} + +ARG NEXT_PUBLIC_DISPLAY_TESTING_MESSAGES +ENV NEXT_PUBLIC_DISPLAY_TESTING_MESSAGES=${NEXT_PUBLIC_DISPLAY_TESTING_MESSAGES} + +RUN npm run build # Step 2. Production image, copy all the files and run next FROM node:22-alpine3.19 AS runner @@ -35,7 +38,6 @@ RUN addgroup --system --gid 1001 nodejs RUN adduser --system --uid 1001 nextjs USER nextjs -COPY --from=builder --chown=nextjs:nodejs /app/docker-entrypoint.sh ./docker-entrypoint.sh COPY --from=builder /app/public ./public # Automatically leverage output traces to reduce image size @@ -46,6 +48,5 @@ COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static # Uncomment the following line to disable telemetry at run time ENV NEXT_TELEMETRY_DISABLED 1 -ENTRYPOINT ["/app/docker-entrypoint.sh"] CMD ["node", "server.js"] STOPSIGNAL SIGTERM diff --git a/docker-entrypoint.sh b/docker-entrypoint.sh deleted file mode 100755 index f1fc77dd..00000000 --- a/docker-entrypoint.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/usr/bin/env sh -set -Ex - -# This method has been inspired by the comment here: -# https://github.com/vercel/next.js/discussions/17641#discussioncomment-339555 -function apply_path { - find /app/.next \( -type d -name .git -prune \) -o -type f -print0 | xargs -0 sed -i "s#APP_NEXT_PUBLIC_MEMPOOL_API#$MEMPOOL_API#g" - find /app/.next \( -type d -name .git -prune \) -o -type f -print0 | xargs -0 sed -i "s#APP_NEXT_PUBLIC_API_URL#$API_URL#g" - find /app/.next \( -type d -name .git -prune \) -o -type f -print0 | xargs -0 sed -i "s#APP_NEXT_PUBLIC_NETWORK#$NETWORK#g" - find /app/.next \( -type d -name .git -prune \) -o -type f -print0 | xargs -0 sed -i "s#APP_NEXT_PUBLIC_DISPLAY_TESTING_MESSAGES#$DISPLAY_TESTING_MESSAGES#g" -} - -apply_path -echo "Starting Nextjs" -exec "$@" diff --git a/package-lock.json b/package-lock.json index 17e1df1f..e5027773 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "simple-staking", - "version": "0.2.30", + "version": "0.2.31", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "simple-staking", - "version": "0.2.30", + "version": "0.2.31", "dependencies": { "@bitcoinerlab/secp256k1": "^1.1.1", "@keystonehq/animated-qr": "^0.8.6", diff --git a/package.json b/package.json index e3df98c8..b9087f41 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "simple-staking", - "version": "0.2.30", + "version": "0.2.31", "private": true, "scripts": { "dev": "next dev", diff --git a/src/app/components/Connect/ConnectSmall.tsx b/src/app/components/Connect/ConnectSmall.tsx index 906e6b38..21d33c78 100644 --- a/src/app/components/Connect/ConnectSmall.tsx +++ b/src/app/components/Connect/ConnectSmall.tsx @@ -54,7 +54,7 @@ export const ConnectSmall: React.FC = ({ > - + ); }; diff --git a/src/app/components/Delegations/Delegation.tsx b/src/app/components/Delegations/Delegation.tsx index 65109f9b..b3ff0dd0 100644 --- a/src/app/components/Delegations/Delegation.tsx +++ b/src/app/components/Delegations/Delegation.tsx @@ -152,7 +152,7 @@ export const Delegation: React.FC = ({ > - + {generateActionButton()} diff --git a/src/app/components/FinalityProviders/FinalityProvider.tsx b/src/app/components/FinalityProviders/FinalityProvider.tsx index ae38488d..ef88076a 100644 --- a/src/app/components/FinalityProviders/FinalityProvider.tsx +++ b/src/app/components/FinalityProviders/FinalityProvider.tsx @@ -95,7 +95,7 @@ export const FinalityProvider: React.FC = ({ 0 )} - + ); }; diff --git a/src/app/components/FinalityProviders/FinalityProviders.tsx b/src/app/components/FinalityProviders/FinalityProviders.tsx index 0ac6da29..9d8668f1 100644 --- a/src/app/components/FinalityProviders/FinalityProviders.tsx +++ b/src/app/components/FinalityProviders/FinalityProviders.tsx @@ -82,8 +82,8 @@ export const FinalityProviders: React.FC = ({ )} - - + + ); }; diff --git a/src/app/components/Modals/ConnectModal.tsx b/src/app/components/Modals/ConnectModal.tsx index 9c7fefd0..7ff42c9f 100644 --- a/src/app/components/Modals/ConnectModal.tsx +++ b/src/app/components/Modals/ConnectModal.tsx @@ -224,7 +224,7 @@ export const ConnectModal: React.FC = ({ > - + )} diff --git a/src/app/components/Modals/Terms/data/terms.tsx b/src/app/components/Modals/Terms/data/terms.tsx index 8b012dfc..c75c045a 100644 --- a/src/app/components/Modals/Terms/data/terms.tsx +++ b/src/app/components/Modals/Terms/data/terms.tsx @@ -1,14 +1,15 @@ +import { getNetworkAppUrl } from "@/config"; + export const Terms = () => { + const url = getNetworkAppUrl(); + return (

Last updated [27 May 2024]


- - https://btcstaking.testnet.babylonchain.io/ + + {url} {" "} is a website-hosted user interface (the{" "} “Interface”).{" "} diff --git a/src/app/components/Stakers/Stakers.tsx b/src/app/components/Stakers/Stakers.tsx index 8ff9954e..d4068422 100644 --- a/src/app/components/Stakers/Stakers.tsx +++ b/src/app/components/Stakers/Stakers.tsx @@ -89,8 +89,8 @@ export const Stakers: React.FC = () => { )}

- - + + ); }; diff --git a/src/app/components/Staking/FinalityProviders/FinalityProvider.tsx b/src/app/components/Staking/FinalityProviders/FinalityProvider.tsx index 11b3837c..b576eec5 100644 --- a/src/app/components/Staking/FinalityProviders/FinalityProvider.tsx +++ b/src/app/components/Staking/FinalityProviders/FinalityProvider.tsx @@ -79,7 +79,7 @@ export const FinalityProvider: React.FC = ({ > - + No data provided )} @@ -100,7 +100,10 @@ export const FinalityProvider: React.FC = ({ > - +

Commission:

@@ -115,7 +118,10 @@ export const FinalityProvider: React.FC = ({ > - +
diff --git a/src/app/components/Staking/Staking.tsx b/src/app/components/Staking/Staking.tsx index 50e2e09a..fbab9a12 100644 --- a/src/app/components/Staking/Staking.tsx +++ b/src/app/components/Staking/Staking.tsx @@ -629,7 +629,7 @@ export const Staking: React.FC = ({ > Preview - + {previewReady && ( { > - + )} diff --git a/src/app/globals.css b/src/app/globals.css index 8e50c77b..3810a469 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -110,3 +110,9 @@ input[type="number"] { body.modal-open { overflow: hidden; } + +.tooltip-wrap { + max-width: 20rem; + white-space: normal; + word-wrap: break-word; +} diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 3273667a..1883f113 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -3,6 +3,8 @@ import { Inter } from "next/font/google"; import "react-responsive-modal/styles.css"; import "react-tooltip/dist/react-tooltip.css"; +import { getNetworkAppUrl } from "@/config"; + import "./globals.css"; import Providers from "./providers"; @@ -27,17 +29,11 @@ export default function RootLayout({ - + - + diff --git a/src/config/index.ts b/src/config/index.ts index 99ae96e0..88fc21ef 100644 --- a/src/config/index.ts +++ b/src/config/index.ts @@ -5,3 +5,10 @@ export const shouldDisplayTestingMsg = (): boolean => { process.env.NEXT_PUBLIC_DISPLAY_TESTING_MESSAGES?.toString() !== "false" ); }; + +// getNetworkAppUrl function is used to get the network app url based on the environment +export const getNetworkAppUrl = (): string => { + return shouldDisplayTestingMsg() + ? "https://btcstaking.testnet.babylonchain.io" + : "https://btcstaking.babylonchain.io"; +};