diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml index c2c03891e..b00528bfe 100644 --- a/.github/workflows/docker-publish.yml +++ b/.github/workflows/docker-publish.yml @@ -22,7 +22,7 @@ jobs: (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository) steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Build and push Fuel Explorer Graphql image uses: ./.github/actions/docker-publish @@ -31,27 +31,5 @@ jobs: username: ${{ github.repository_owner }} password: ${{ secrets.GITHUB_TOKEN }} image: ghcr.io/fuellabs/fuel-explorer - dockerfile: deployment/Dockerfile + dockerfile: ./deployment/Dockerfile context: ./packages/graphql - - # Temporary publish a new version of the graphql-new - # until the graphql removed to use only the new version - build-and-publish-image-v2: - runs-on: buildjet-4vcpu-ubuntu-2204 - if: | - (github.event_name == 'release' && github.event.action == 'published') || - github.ref == 'refs/heads/main' || - (github.event_name == 'pull_request' && - github.event.pull_request.head.repo.full_name == github.repository) - steps: - - uses: actions/checkout@v3 - - - name: Build and push Fuel Explorer Graphql image V2 - uses: ./.github/actions/docker-publish - id: publish - with: - username: ${{ github.repository_owner }} - password: ${{ secrets.GITHUB_TOKEN }} - image: ghcr.io/fuellabs/fuel-explorer - dockerfile: deployment/Dockerfile.v2 - context: ./packages/graphql-new diff --git a/.github/workflows/helm-publish.yml b/.github/workflows/helm-publish.yml index d82c865a5..aeadba07b 100644 --- a/.github/workflows/helm-publish.yml +++ b/.github/workflows/helm-publish.yml @@ -23,7 +23,7 @@ jobs: steps: - name: Check out code - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Package and Push Charts uses: bsord/helm-push@v4.1.0 diff --git a/.github/workflows/pr-tests.yml b/.github/workflows/pr-tests.yml index 134d02c28..a00628b9c 100644 --- a/.github/workflows/pr-tests.yml +++ b/.github/workflows/pr-tests.yml @@ -15,14 +15,11 @@ jobs: runs-on: buildjet-4vcpu-ubuntu-2204 steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Create .env file graphql run: cp packages/graphql/.env.example packages/graphql/.env - - - name: Create .env file graphql-new - run: cp packages/graphql-new/.env.example packages/graphql-new/.env - + - name: Create .env file explorer run: cp packages/app-explorer/.env.example packages/app-explorer/.env diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml index 5321c4f69..6ba8bb72f 100644 --- a/.github/workflows/pr.yaml +++ b/.github/workflows/pr.yaml @@ -28,7 +28,7 @@ jobs: if: ${{ github.head_ref != 'changeset-release/master' }} runs-on: buildjet-4vcpu-ubuntu-2204 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: FuelLabs/github-actions/setups/node@master with: node-version: 20.11.0 @@ -43,7 +43,7 @@ jobs: if: ${{ github.head_ref != 'changeset-release/master' }} runs-on: buildjet-4vcpu-ubuntu-2204 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: FuelLabs/github-actions/setups/node@master with: node-version: 20.11.0 diff --git a/.gitignore b/.gitignore index 8068acaa0..c4b398b2d 100644 --- a/.gitignore +++ b/.gitignore @@ -89,4 +89,6 @@ act-actions **/**/generated # playwright report -**/**/playwright-report/* \ No newline at end of file +**/**/playwright-report/* +**/**/mnt/db +**/**/db diff --git a/.lintstagedrc.mjs b/.lintstagedrc.mjs index ebf10c5a7..368288e18 100644 --- a/.lintstagedrc.mjs +++ b/.lintstagedrc.mjs @@ -1,5 +1,5 @@ export default { - '**/*.(js|jsx|ts|tsx|md|json|mdx|html|css)': [ - 'biome check --apply-unsafe --diagnostic-level=error --max-diagnostics=1000', + '*.{js,ts,cjs,mjs,d.cts,d.mts,jsx,tsx,json,jsonc}': [ + 'biome check --apply-unsafe --no-errors-on-unmatched', ], }; diff --git a/biome.json b/biome.json index bfe634bb3..2ed291084 100644 --- a/biome.json +++ b/biome.json @@ -15,7 +15,8 @@ "rules": { "recommended": true, "style": { - "noNonNullAssertion": "off" + "noNonNullAssertion": "off", + "useImportType": "error" }, "suspicious": { "noExplicitAny": "warn", diff --git a/contracts/predicate/package.json b/contracts/predicate/package.json index 4336fc0d2..3c296f32e 100644 --- a/contracts/predicate/package.json +++ b/contracts/predicate/package.json @@ -15,9 +15,9 @@ "app-commons": "workspace:*" }, "devDependencies": { - "dotenv": "16.4.1", + "dotenv": "16.4.5", "fuels": "0.74.0", - "vitest": "1.2.2", - "tsx": "4.7.1" + "vitest": "1.5.0", + "tsx": "4.7.2" } } diff --git a/contracts/predicate/scripts/process.env.d.ts b/contracts/predicate/scripts/process.env.d.ts index 828912e8c..2f182d632 100644 --- a/contracts/predicate/scripts/process.env.d.ts +++ b/contracts/predicate/scripts/process.env.d.ts @@ -7,4 +7,4 @@ declare global { } } -export {}; +export type {}; diff --git a/deployment/Dockerfile b/deployment/Dockerfile index 16158472c..cc3b6685a 100644 --- a/deployment/Dockerfile +++ b/deployment/Dockerfile @@ -3,11 +3,20 @@ FROM node:20-slim AS base # Expose the ENVs to the env of the container -ENV PORT="${PORT}" -ENV FUEL_PROVIDER="${FUEL_PROVIDER:-https://beta-5.fuel.network/graphql}" ENV PNPM_HOME="/pnpm" ENV PATH="$PNPM_HOME:$PATH" -ENV SERVER_BUILD=true + +ENV SERVER_PORT="${SERVER_PORT:-3004}" +ENV FUEL_PROVIDER="${FUEL_PROVIDER:-https://beta-5.fuel.network/graphql}" +ENV SERVER_BUILD="${SERVER_BUILD}" +ENV SYNC_MISSING="${SYNC_MISSING}" + +# Database config +ENV DB_HOST="${DB_HOST}" +ENV DB_PORT="${DB_PORT}" +ENV DB_USER="${DB_USER}" +ENV DB_PASS="${DB_PASS}" +ENV DB_NAME="${DB_NAME}" # Enable pnpm using corepack form node.js RUN corepack enable @@ -15,13 +24,13 @@ RUN corepack enable # Install dependencies for the entire monorepo COPY . /app-explorer WORKDIR /app-explorer +ENV PM2_HOME=/tmp/.pm2 # Install dependencies for the entire monorepo RUN pnpm install +RUN pnpm add -g pm2 tsx # Expose the specified port -EXPOSE ${PORT} - -# Start GraphQL server +EXPOSE ${SERVER_PORT} WORKDIR /app-explorer -CMD ["pnpm", "server:start"] +CMD ["./scripts/run.sh"] diff --git a/deployment/Dockerfile.v2 b/deployment/Dockerfile.v2 deleted file mode 100644 index f7d1ae500..000000000 --- a/deployment/Dockerfile.v2 +++ /dev/null @@ -1,38 +0,0 @@ -# This image contains the graphql server -# built for the fuel-explorer -FROM node:20-slim AS base - -# Expose the ENVs to the env of the container -ENV PORT="${PORT}" -ENV FUEL_PROVIDER="${FUEL_PROVIDER:-https://beta-5.fuel.network/graphql}" -ENV PNPM_HOME="/pnpm" -ENV PATH="$PNPM_HOME:$PATH" -ENV SERVER_BUILD=true -ENV SYNC_MISSING=false -ENV DB_MIGRATE=false - -# Database config -ENV DB_HOST="${DB_HOST}" -ENV DB_PORT="${DB_PORT}" -ENV DB_USER="${DB_USER}" -ENV DB_PASS="${DB_PASS}" -ENV DB_NAME="${DB_NAME}" - -# Enable pnpm using corepack form node.js -RUN corepack enable - -# Install dependencies for the entire monorepo -COPY . /app-explorer -WORKDIR /app-explorer - -# Install dependencies for the entire monorepo -RUN pnpm install -RUN pnpm db:setup - -# Expose the specified port -EXPOSE ${PORT} - -# Start GraphQL server -WORKDIR /app-explorer - -CMD ["pnpm", "server:start"] diff --git a/docker/Makefile b/docker/Makefile index fd3673c3d..add0bbf56 100644 --- a/docker/Makefile +++ b/docker/Makefile @@ -13,3 +13,8 @@ clean: logs: docker compose logs -f +dump-db: + docker compose exec fuel-explorer-pgsql pg_dump -U postgres -d postgres > ../packages/graphql/db/dev_dump.sql + +restore-db: + docker compose exec fuel-explorer-pgsql psql -U postgres -d postgres < ../packages/graphql/db/dev_dump.sql diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index 381566616..a01bc565a 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -21,6 +21,8 @@ services: context: ./fuel-core/ env_file: - ./envs/fuel_core.env + volumes: + - ./fuel-core/mnt/db:/fuel/mnt/db environment: L1_CHAIN_HTTP: http://l1_chain:9545/ DEPLOYMENTS_HTTP: http://l1_chain:8081/deployments.local.json @@ -88,5 +90,29 @@ services: timeout: 5s retries: 5 + fuel-rabbitmq: + image: rabbitmq:3-management + ports: + - "5672:5672" # AMQP protocol port + - "15672:15672" # Management UI port + environment: + RABBITMQ_DEFAULT_USER: guest + RABBITMQ_DEFAULT_PASS: guest + networks: + - app-network + + # env_file: + # - ./envs/graphql.env + # ports: + # - "3004:${SERVER_PORT:-3004}" + # environment: + # - DB_HOST=fuel-explorer-pgsql + # - DB_PORT=5432 + # volumes: + # - ../packages/graphql:/app + volumes: fuel-explorer-pgsql-db: +networks: + app-network: + driver: bridge diff --git a/docker/envs/graphql.env b/docker/envs/graphql.env new file mode 100644 index 000000000..74c5b27da --- /dev/null +++ b/docker/envs/graphql.env @@ -0,0 +1,9 @@ +PORT=3004 +FUEL_PROVIDER=https://beta-5.fuel.network/graphql +SERVER_BUILD=false +SYNC_MISSING=false +DB_HOST=127.0.0.1 +DB_PORT=5432 +DB_USER=postgres +DB_PASS=postgres +DB_NAME=postgres diff --git a/docker/erc20-deployer/Dockerfile b/docker/erc20-deployer/Dockerfile index 16bb8d1a5..0b4ff34a4 100644 --- a/docker/erc20-deployer/Dockerfile +++ b/docker/erc20-deployer/Dockerfile @@ -4,7 +4,7 @@ FROM node:20-alpine WORKDIR /ecr20-deployer # Copy deployer project -ADD ./deployer /erc20-deployer/deployer +COPY ./deployer /erc20-deployer/deployer # Run install inside the depdencies WORKDIR /erc20-deployer/deployer @@ -26,4 +26,4 @@ ENV PK_ETH_WALLET="${PK_ETH_WALLET}" EXPOSE ${PORT} # copy over script and run -CMD ["pnpm", "start"] \ No newline at end of file +CMD ["pnpm", "start"] diff --git a/docker/erc20-deployer/deployer/package.json b/docker/erc20-deployer/deployer/package.json index 0b0291143..f25f55518 100644 --- a/docker/erc20-deployer/deployer/package.json +++ b/docker/erc20-deployer/deployer/package.json @@ -5,10 +5,10 @@ }, "dependencies": { "@fuel-bridge/test-utils": "0.5.0", - "ethers": "6.11.0", + "ethers": "6.12.0", "fuels": "0.74.0" }, "devDependencies": { "ts-node": "^10.9.2" } -} \ No newline at end of file +} diff --git a/docker/erc20-deployer/deployer/src/index.ts b/docker/erc20-deployer/deployer/src/index.ts index 734f38bcc..8d2dd0118 100644 --- a/docker/erc20-deployer/deployer/src/index.ts +++ b/docker/erc20-deployer/deployer/src/index.ts @@ -1,4 +1,4 @@ -import { createServer } from 'http'; +import { createServer } from 'node:http'; import { getOrDeployECR20Contract, getOrDeployFuelTokenContract, diff --git a/docker/fuel-core/chainConfig.json b/docker/fuel-core/chainConfig.json index 7ea3de242..cb71a0500 100644 --- a/docker/fuel-core/chainConfig.json +++ b/docker/fuel-core/chainConfig.json @@ -1,119 +1,49 @@ { - "chain_name": "local_testnet", - "consensus": { - "PoA": { - "signing_key": "0xc8e615a4089466174459ef19cfd257d2e17adfabff3b8f219dbb5fb4eca87c50" - } - }, - "block_gas_limit": 5000000000, + "chain_name": "Testnet Beta 5", + "block_gas_limit": 30000000, "initial_state": { "coins": [ { - "owner": "0xc8e615a4089466174459ef19cfd257d2e17adfabff3b8f219dbb5fb4eca87c50", - "amount": "0x000000e8d4a51000", - "asset_id": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "owner": "0x92dffc873b56f219329ed03bb69bebe8c3d8b041088574882f7a6404f02e2f28", - "amount": "0x000000e8d4a51000", - "asset_id": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "owner": "0x456bdaffaf74fe03521754ac445d148033c0c6acf7d593132c43f92fdbc7324c", - "amount": "0x000000e8d4a51000", - "asset_id": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "owner": "0x639880ece7753a32e09164d14dad7436c57737e567f18b98f6ee30fec6b247ec", - "amount": "0x000000e8d4a51000", - "asset_id": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "owner": "0xfd8c520ef8caff0ad3289aa64acecd4ef86ac8f643fd9b76bf2d163a86a66716", - "amount": "0x000000e8d4a51000", - "asset_id": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "owner": "0x8247104854dd733cb475901d55047f57cb3c8cafe3a9f7233de3325b8bf56a5c", - "amount": "0x000000e8d4a51000", - "asset_id": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "owner": "0x53de37ae51fcfecb17ee3589f68904ac75bf5ec109edeb1065ccb63145287da6", - "amount": "0x000000e8d4a51000", - "asset_id": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "owner": "0x17f4bef51f63f0c28af20d4223a3bf5cf1735a3b7ec52b4fcfbdbb5f30582a6b", - "amount": "0x000000e8d4a51000", - "asset_id": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "owner": "0x95725e9083d8ed1cb52dcf6429d0cfce00cc375eeac5b620b5c36f5b1e734b31", - "amount": "0x000000e8d4a51000", - "asset_id": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "owner": "0x08792a75d5714165aa117fd75450f9efcfb7124d034ef271f2919e4cc287046c", - "amount": "0x000000e8d4a51000", - "asset_id": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "owner": "0x6a16fba49dbdf7689c52b7a22951a54dc164076d27bdc6042b5d8377d68ca10b", - "amount": "0x000000e8d4a51000", + "owner": "0xa1184d77d0d08a064e03b2bd9f50863e88faddea4693a05ca1ee9b1732ea99b7", + "amount": "0x1000000000000000", "asset_id": "0x0000000000000000000000000000000000000000000000000000000000000000" }, { - "owner": "0x6494a55c0e3da212fdd0515507d00ae99151c7966e1448079c76bc447b577254", - "amount": "0x000000e8d4a51000", + "owner": "0xb5566df884bee4e458151c2fe4082c8af38095cc442c61e0dc83a371d70d88fd", + "amount": "0x1000000000000000", "asset_id": "0x0000000000000000000000000000000000000000000000000000000000000000" }, { - "owner": "0xe0e1c94a9f9e02454772813ba6a6261b5228db1fabde3a68b23c0e9744ce22fc", - "amount": "0x000000e8d4a51000", + "owner": "0x9da7247e1d63d30d69f136f0f8654ee8340362c785b50f0a60513c7edbf5bb7c", + "amount": "0x1000000000000000", "asset_id": "0x0000000000000000000000000000000000000000000000000000000000000000" }, { - "owner": "0x425f3e91aedff36e72ae60a8a1d328e625d66d39fcc98d5fcd1ba7df65a9f878", - "amount": "0x000000e8d4a51000", + "owner": "0x4b2ca966aad1a9d66994731db5138933cf61679107c3cde2a10d9594e47c084e", + "amount": "0x1000000000000000", "asset_id": "0x0000000000000000000000000000000000000000000000000000000000000000" }, { - "owner": "0xe2242f2e4971c34bc6fe5e1c0043b1aba717cb6a51f31f0dc0708cca73df905a", - "amount": "0x000000e8d4a51000", + "owner": "0x26183fbe7375045250865947695dfc12500dcc43efb9102b4e8c4d3c20009dcb", + "amount": "0x1000000000000000", "asset_id": "0x0000000000000000000000000000000000000000000000000000000000000000" }, { - "owner": "0x6aa67cb316f329111dc708bb766360f5026a614edb11882e14d4cc04f26e0a08", - "amount": "0x000000e8d4a51000", + "owner": "0x81f3a10b61828580d06cc4c7b0ed8f59b9fb618be856c55d33decd95489a1e23", + "amount": "0x1000000000000000", "asset_id": "0x0000000000000000000000000000000000000000000000000000000000000000" }, { - "owner": "0xef5c2b712c4f3a10a37d6371cab2b03a6afd12e4ffcc9567d45d8c4b6e217e5c", - "amount": "0x000000e8d4a51000", - "asset_id": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "owner": "0xa82f66642de54993b32036eef7914f2dbaa217aa3209707b64d0b90187456a1f", - "amount": "0x000000e8d4a51000", - "asset_id": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "owner": "0x9c9c1f3346b54fe6cb379fa27f338464592515fd865656089c4a23ac34390e6f", - "amount": "0x000000e8d4a51000", - "asset_id": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "owner": "0x8a332bc33f4c10ad36392a9ca958a5ddf56081cc764f61613ea119e42ced6ac5", - "amount": "0x000000e8d4a51000", + "owner": "0x587aa0482482efea0234752d1ad9a9c438d1f34d2859b8bef2d56a432cb68e33", + "amount": "0x1000000000000000", "asset_id": "0x0000000000000000000000000000000000000000000000000000000000000000" } ], "contracts": [ { - "contract_id": "0x1111111111111111111111111111111111111111111111111111111111111111", - "code": "0x2222222222222222222222222222222222222222222222222222222222222222", - "salt": "0x0000000000000000000000000000000000000000000000000000000000000001" + "contract_id": "0x7777777777777777777777777777777777777777777777777777777777777777", + "code": "0x9000000994318e6e453f30e85bf6088f7161d44e57b86a6af0c955d22b353f91b2465f5e6140000a504d00205d4d30001a4860004945048076440001240400005050c0043d51345024040000", + "salt": "0x1bfd51cb31b8d0bc7d93d38f97ab771267d8786ab87073e0c2b8f9ddc44b274e" } ] }, @@ -122,14 +52,14 @@ "max_inputs": 255, "max_outputs": 255, "max_witnesses": 255, - "max_gas_per_tx": 10000000, + "max_gas_per_tx": 30000000, "max_size": 17825792 }, "predicate_params": { "max_predicate_length": 1048576, "max_predicate_data_length": 1048576, - "max_gas_per_predicate": 10000000, - "max_message_data_length": 1048576 + "max_message_data_length": 1048576, + "max_gas_per_predicate": 30000000 }, "script_params": { "max_script_length": 1048576, @@ -137,11 +67,230 @@ }, "contract_params": { "contract_max_size": 16777216, - "max_storage_slots": 255 + "max_storage_slots": 65536 }, "fee_params": { "gas_price_factor": 92, - "gas_per_byte": 4 + "gas_per_byte": 63 + }, + "chain_id": 0, + "gas_costs": { + "add": 2, + "addi": 2, + "aloc": 1, + "and": 2, + "andi": 2, + "bal": 366, + "bhei": 2, + "bhsh": 2, + "burn": 33949, + "cb": 2, + "cfei": 2, + "cfsi": 2, + "croo": 40, + "div": 2, + "divi": 2, + "eck1": 3347, + "ecr1": 46165, + "ed19": 4210, + "eq": 2, + "exp": 2, + "expi": 2, + "flag": 1, + "gm": 2, + "gt": 2, + "gtf": 16, + "ji": 2, + "jmp": 2, + "jne": 2, + "jnei": 2, + "jnzi": 2, + "jmpf": 2, + "jmpb": 2, + "jnzf": 2, + "jnzb": 2, + "jnef": 2, + "jneb": 2, + "lb": 2, + "log": 754, + "lt": 2, + "lw": 2, + "mint": 35718, + "mlog": 2, + "mod": 2, + "modi": 2, + "move": 2, + "movi": 2, + "mroo": 5, + "mul": 2, + "muli": 2, + "mldv": 4, + "noop": 1, + "not": 2, + "or": 2, + "ori": 2, + "poph": 3, + "popl": 3, + "pshh": 4, + "pshl": 4, + "ret_contract": 733, + "rvrt_contract": 722, + "sb": 2, + "sll": 2, + "slli": 2, + "srl": 2, + "srli": 2, + "srw": 253, + "sub": 2, + "subi": 2, + "sw": 2, + "sww": 29053, + "time": 79, + "tr": 46242, + "tro": 33251, + "wdcm": 3, + "wqcm": 3, + "wdop": 3, + "wqop": 3, + "wdml": 3, + "wqml": 4, + "wddv": 5, + "wqdv": 7, + "wdmd": 11, + "wqmd": 18, + "wdam": 9, + "wqam": 12, + "wdmm": 11, + "wqmm": 11, + "xor": 2, + "xori": 2, + "call": { + "LightOperation": { + "base": 21687, + "units_per_gas": 4 + } + }, + "ccp": { + "LightOperation": { + "base": 59, + "units_per_gas": 20 + } + }, + "csiz": { + "LightOperation": { + "base": 59, + "units_per_gas": 195 + } + }, + "k256": { + "LightOperation": { + "base": 282, + "units_per_gas": 3 + } + }, + "ldc": { + "LightOperation": { + "base": 45, + "units_per_gas": 65 + } + }, + "logd": { + "LightOperation": { + "base": 1134, + "units_per_gas": 2 + } + }, + "mcl": { + "LightOperation": { + "base": 3, + "units_per_gas": 523 + } + }, + "mcli": { + "LightOperation": { + "base": 3, + "units_per_gas": 526 + } + }, + "mcp": { + "LightOperation": { + "base": 3, + "units_per_gas": 448 + } + }, + "mcpi": { + "LightOperation": { + "base": 7, + "units_per_gas": 585 + } + }, + "meq": { + "LightOperation": { + "base": 11, + "units_per_gas": 1097 + } + }, + "retd_contract": { + "LightOperation": { + "base": 1086, + "units_per_gas": 2 + } + }, + "s256": { + "LightOperation": { + "base": 45, + "units_per_gas": 3 + } + }, + "scwq": { + "HeavyOperation": { + "base": 30375, + "gas_per_unit": 28628 + } + }, + "smo": { + "LightOperation": { + "base": 64196, + "units_per_gas": 1 + } + }, + "srwq": { + "HeavyOperation": { + "base": 262, + "gas_per_unit": 249 + } + }, + "swwq": { + "HeavyOperation": { + "base": 28484, + "gas_per_unit": 26613 + } + }, + "contract_root": { + "LightOperation": { + "base": 45, + "units_per_gas": 1 + } + }, + "state_root": { + "HeavyOperation": { + "base": 350, + "gas_per_unit": 176 + } + }, + "new_storage_per_byte": 63, + "vm_initialization": { + "LightOperation": { + "base": 1645, + "units_per_gas": 14 + } + } + }, + "base_asset_id": "0000000000000000000000000000000000000000000000000000000000000000" + }, + "consensus": { + "PoA": { + "signing_key": "0xc8e615a4089466174459ef19cfd257d2e17adfabff3b8f219dbb5fb4eca87c50" } } } diff --git a/docker/fuel-core/fuel_core.sh b/docker/fuel-core/fuel_core.sh index 5a562bcf3..c9b5ede2c 100644 --- a/docker/fuel-core/fuel_core.sh +++ b/docker/fuel-core/fuel_core.sh @@ -6,40 +6,40 @@ JSON='{"jsonrpc":"2.0","id":0,"method":"net_version","params":[]}' FUEL_DB_PATH=./mnt/db/ if [ -z "$L1_CHAIN_HTTP" ]; then - echo "Must specify \$L1_CHAIN_HTTP." - exit 1 + echo "Must specify \$L1_CHAIN_HTTP." + exit 1 fi if [ -z "$DEPLOYMENTS_HTTP" ]; then - echo "Must specify \$DEPLOYMENTS_HTTP." - exit 1 + echo "Must specify \$DEPLOYMENTS_HTTP." + exit 1 fi # wait for the base layer to be up echo "Waiting for l1 chain." curl \ - --fail \ - --show-error \ - --silent \ - -H "Content-Type: application/json" \ - --retry-connrefused \ - --retry $RETRIES \ - --retry-delay 1 \ - -d $JSON \ - $L1_CHAIN_HTTP > /dev/null + --fail \ + --show-error \ + --silent \ + -H "Content-Type: application/json" \ + --retry-connrefused \ + --retry $RETRIES \ + --retry-delay 1 \ + -d $JSON \ + $L1_CHAIN_HTTP >/dev/null echo "Connected to l1 chain." # get the deployments file from the deployer echo "Waiting for l1 chain deployment data." curl \ - --fail \ - --show-error \ - --silent \ - --retry-connrefused \ - --retry-all-errors \ - --retry $RETRIES \ - --retry-delay 5 \ - $DEPLOYMENTS_HTTP \ - -o addresses.json + --fail \ + --show-error \ + --silent \ + --retry-connrefused \ + --retry-all-errors \ + --retry $RETRIES \ + --retry-delay 5 \ + $DEPLOYMENTS_HTTP \ + -o addresses.json echo "Got l1 chain deployment data." # pull data from deployer dump @@ -48,19 +48,18 @@ echo "FUEL_MESSAGE_PORTAL_CONTRACT_ADDRESS: $FUEL_MESSAGE_PORTAL_CONTRACT_ADDRES echo "L1_CHAIN_HTTP: $L1_CHAIN_HTTP" # start the Fuel client -#--db-path ${FUEL_DB_PATH} echo "Starting fuel node." exec /root/fuel-core run \ - --ip $FUEL_IP \ - --port $FUEL_PORT \ - --db-type in-memory \ - --utxo-validation \ - --vm-backtrace \ - --enable-relayer \ - --relayer $L1_CHAIN_HTTP \ - --relayer-v2-listening-contracts $FUEL_MESSAGE_PORTAL_CONTRACT_ADDRESS \ - --coinbase-recipient 0x1111111111111111111111111111111111111111111111111111111111111111 \ - --poa-interval-period 1s \ - --min-gas-price 1 \ - --chain ./chainConfig.json \ - --debug + --ip $FUEL_IP \ + --port $FUEL_PORT \ + --db-path ${FUEL_DB_PATH} \ + --utxo-validation \ + --vm-backtrace \ + --enable-relayer \ + --relayer $L1_CHAIN_HTTP \ + --relayer-v2-listening-contracts $FUEL_MESSAGE_PORTAL_CONTRACT_ADDRESS \ + --coinbase-recipient 0x7777777777777777777777777777777777777777777777777777777777777777 \ + --poa-interval-period 1s \ + --min-gas-price 1 \ + --chain ./chainConfig.json \ + --debug diff --git a/package.json b/package.json index 719254e92..2f198fe07 100644 --- a/package.json +++ b/package.json @@ -22,17 +22,18 @@ "docker/erc20-deployer/deployer" ], "scripts": { - "build:preview": "pnpm turbo:run build:preview", "build:lib": "pnpm turbo:run build:lib", + "build:preview": "pnpm turbo:run build:preview", + "db:dev-dump": "make -C ./docker dump-db", + "db:dev-restore": "make -C ./docker restore-db", "deps:update": "updates -gu && pnpm -r exec updates -gu", "dev": "./scripts/dev.sh", "dev:explorer": "pnpm --filter=app-explorer dev", - "dev:portal": "pnpm --filter=app-portal dev", "dev:graphql": "pnpm --filter=graphql dev", - "dev:notification": "pnpm --filter=notification-service dev:notification", - "lint": "biome check --apply-unsafe .", - "lint:ci": "biome lint --max-diagnostics=1000 --diagnostic-level=error .", + "dev:portal": "pnpm --filter=app-portal dev", "format": "biome format --write .", + "lint": "biome check --apply-unsafe .", + "lint:ci": "biome ci --max-diagnostics=1000 --diagnostic-level=error .", "node:clean": "make -C ./docker clean", "node:logs": "make -C ./docker logs", "node:reset": "run-s node:stop node:clean node:start", @@ -43,55 +44,54 @@ "storybook:portal": "pnpm turbo:run storybook --filter=app-portal", "test": "pnpm turbo:run test", "test:all": "run-p test test:e2e", - "test:e2e": "playwright test --config=packages/e2e-tests/playwright.config.ts", "test:ci": "pnpm turbo:run test -- --ci --testLocationInResults --json --coverage", "test:clear": "pnpm turbo:run test -- --clearCache", - "test:coverage": " pnpm turbo:run test -- --coverage", + "test:coverage": "pnpm turbo:run test -- --coverage", + "test:e2e": "playwright test --config=packages/e2e-tests/playwright.config.ts", "test:watch": "pnpm turbo:run test -- --watch", "ts:check": "pnpm turbo:run ts:check", "turbo:run": "./scripts/turbo.sh" }, "dependencies": { - "ethers": "^6.7.1", "fuels": "0.74.0", - "jest": "29.7.0", - "lint-staged": "15.2.2" + "ethers": "^6.12.0", + "jest": "29.7.0" }, "devDependencies": { - "@babel/core": "^7.23.9", - "@biomejs/biome": "1.5.3", - "@fuels/jest": "^0.18.0", - "@fuels/ts-config": "^0.18.0", - "@fuels/tsup-config": "^0.18.0", + "@babel/core": "^7.24.4", + "@biomejs/biome": "1.7.0", + "@fuels/jest": "^0.18.1", + "@fuels/ts-config": "^0.18.1", + "@fuels/tsup-config": "^0.18.1", "@jest/types": "29.6.3", - "@next/eslint-plugin-next": "^14.1.0", + "@next/eslint-plugin-next": "^14.2.2", "@nomiclabs/hardhat-etherscan": "^3.1.8", - "@openzeppelin/hardhat-upgrades": "^3.0.3", - "@playwright/test": "^1.41.2", - "@swc/core": "1.4.1", + "@openzeppelin/hardhat-upgrades": "^3.0.5", + "@playwright/test": "^1.43.1", + "@swc/core": "1.4.16", "@swc/jest": "0.2.36", "@types/jest": "29.5.12", - "@typescript-eslint/eslint-plugin": "^7.0.1", - "@typescript-eslint/parser": "^7.0.1", + "@typescript-eslint/eslint-plugin": "^7.7.0", + "@typescript-eslint/parser": "^7.7.0", "@xstate/cli": "^0.5.17", - "dotenv": "^16.4.4", - "get-tsconfig": "4.7.2", + "dotenv": "^16.4.5", + "get-tsconfig": "4.7.3", "hardhat-typechain": "^0.3.5", "husky": "^9.0.11", "jest": "29.7.0", "jest-environment-jsdom": "29.7.0", "jest-transform-stub": "^2.0.0", "lint-staged": "^15.2.2", - "next": "14.1.0", + "next": "14.2.2", "npm-run-all": "^4.1.5", "ts-jest": "^29.1.2", "ts-node": "10.9.2", "tsup": "8.0.2", - "tsx": "4.7.1", - "turbo": "^1.12.4", - "typescript": "5.3.3", - "updates": "^15.1.2", - "vitest": "1.2.2" + "tsx": "4.7.2", + "turbo": "^1.13.2", + "typescript": "5.4.5", + "updates": "^16.0.1", + "vitest": "1.5.0" }, "pnpm": { "peerDependencyRules": { diff --git a/packages/app-commons/package.json b/packages/app-commons/package.json index 31c50be7a..5623e553a 100644 --- a/packages/app-commons/package.json +++ b/packages/app-commons/package.json @@ -15,11 +15,11 @@ "dependencies": { "@fuels/ui": "workspace:*", "react": "18.2.0", - "tailwind-variants": "0.1.20" + "tailwind-variants": "0.2.1" }, "devDependencies": { - "@types/react": "18.2.54", - "@types/react-dom": "18.2.22", - "typescript": "5.3.3" + "@types/react": "18.2.79", + "@types/react-dom": "18.2.25", + "typescript": "5.4.5" } } diff --git a/packages/app-commons/src/process.env.d.ts b/packages/app-commons/src/process.env.d.ts index 20ecca6cf..ddfdcb613 100644 --- a/packages/app-commons/src/process.env.d.ts +++ b/packages/app-commons/src/process.env.d.ts @@ -19,4 +19,4 @@ declare global { } } -export {}; +export type {}; diff --git a/packages/app-explorer/.env.example b/packages/app-explorer/.env.example index e23970db2..d35407b73 100644 --- a/packages/app-explorer/.env.example +++ b/packages/app-explorer/.env.example @@ -10,5 +10,5 @@ NEXT_PUBLIC_WALLET_INSTALL=https://chrome.google.com/webstore/detail/fuel-wallet NEXT_PUBLIC_WALLET_INSTALL_NEXT=https://next-wallet.fuel.network/docs/install/#install-from-source-code # Explorer API URL -FUEL_EXPLORER_API= +FUEL_EXPLORER_API=http://localhost:3004/graphql FUEL_EXPLORER_API_KEY= diff --git a/packages/app-explorer/.gitignore b/packages/app-explorer/.gitignore index 95f9674ea..ea2a85458 100644 --- a/packages/app-explorer/.gitignore +++ b/packages/app-explorer/.gitignore @@ -2,4 +2,3 @@ public/storybook public/ui public/portal public/portal-storybook -src/graphql/generated diff --git a/packages/app-explorer/.storybook/main.ts b/packages/app-explorer/.storybook/main.ts index 450b4d2b0..706a07f85 100644 --- a/packages/app-explorer/.storybook/main.ts +++ b/packages/app-explorer/.storybook/main.ts @@ -30,12 +30,6 @@ const config: StorybookConfig = { }, }), webpack: (config: any) => { - config.module.rules.push({ - test: /\.(graphql|gql)/, - exclude: /node_modules/, - loader: 'graphql-tag/loader', - }); - config.module.rules.push({ test: /\.svg$/i, issuer: /\.[jt]sx?$/, diff --git a/packages/app-explorer/.storybook/preview.tsx b/packages/app-explorer/.storybook/preview.tsx index a51c613c0..7a27de3a5 100644 --- a/packages/app-explorer/.storybook/preview.tsx +++ b/packages/app-explorer/.storybook/preview.tsx @@ -3,11 +3,11 @@ import '../src/app/globals.css'; import './fonts.css'; import { INITIAL_VIEWPORTS } from '@storybook/addon-viewport'; -import { Preview } from '@storybook/react'; +import type { Preview } from '@storybook/react'; import React from 'react'; import { withThemeDecorator } from 'storybook-addon-theme'; -import { ReactNode } from 'react'; +import type { ReactNode } from 'react'; import { Provider } from '../src/systems/Core/components/Provider'; function ThemeWrapper({ children }: { children: ReactNode }) { diff --git a/packages/app-explorer/next.config.mjs b/packages/app-explorer/next.config.mjs index 9dd4261c6..2458024f0 100644 --- a/packages/app-explorer/next.config.mjs +++ b/packages/app-explorer/next.config.mjs @@ -1,19 +1,6 @@ import { redirects } from './src/redirects.mjs'; -const externals = [ - 'bcryptjs', - 'ws', - 'isomorphic-ws', - 'node-fetch', - '@whatwg/node-fetch', - 'graphql', - '@graphql-tools/delegate', - '@graphql-tools/load', - '@graphql-tools/schema', - '@graphql-tools/stitch', - '@graphql-tools/url-loader', - '@graphql-tools/utils', -]; +const externals = []; /** @type {import('next').NextConfig} */ const config = { @@ -75,12 +62,6 @@ const config = { 'tls', ); - config.module.rules.push({ - test: /\.(graphql|gql)/, - exclude: /node_modules/, - loader: 'graphql-tag/loader', - }); - // Grab the existing rule that handles SVG imports const fileLoaderRule = config.module.rules.find((rule) => rule.test?.test?.('.svg'), diff --git a/packages/app-explorer/package.json b/packages/app-explorer/package.json index b99293933..e5521a77a 100644 --- a/packages/app-explorer/package.json +++ b/packages/app-explorer/package.json @@ -13,40 +13,39 @@ "ts:check": "tsc --noEmit" }, "dependencies": { - "@faker-js/faker": "8.4.0", + "@faker-js/faker": "8.4.1", "@fuel-explorer/graphql": "workspace:*", "@fuel-ts/math": "0.76.0", - "@fuels/assets": "^0.18.0", + "@fuels/assets": "^0.18.1", "@fuels/ui": "workspace:*", "@tabler/icons-react": "2.46.0", - "@vercel/analytics": "1.1.3", + "@vercel/analytics": "1.2.2", "app-commons": "workspace:*", "app-portal": "workspace:*", "clsx": "2.1.0", "csstype": "3.1.3", "dayjs": "1.11.10", - "framer-motion": "11.0.3", + "framer-motion": "11.1.7", "fuels": "0.74.0", - "geist": "1.2.1", - "graphql": ">=16.8.1", - "graphql-request": ">=6.1.0", + "geist": "1.3.0", + "graphql": "16.8.1", + "graphql-request": "6.1.0", "graphql-tag": "2.12.6", - "graphql-yoga": "5.1.1", "js-cookies": "1.0.4", - "next": "14.1.0", - "next-themes": "0.2.1", + "next": "14.2.2", + "next-themes": "0.3.0", "react": "18.2.0", "react-dom": "18.2.0", - "react-json-view-lite": "1.2.1", + "react-json-view-lite": "1.3.0", "react-use": "17.5.0", "react-window": "1.8.10", "tai64": "1.0.0", - "tailwind-variants": "0.1.20", - "zod": "3.22.4", - "zod-validation-error": "3.0.0" + "tailwind-variants": "0.2.1", + "zod": "3.22.5", + "zod-validation-error": "3.1.0" }, "devDependencies": { - "@babel/core": "^7.23.9", + "@babel/core": "^7.24.4", "@storybook/addon-a11y": "^8.0.8", "@storybook/addon-actions": "^8.0.8", "@storybook/addon-essentials": "^8.0.8", @@ -60,27 +59,27 @@ "@storybook/testing-library": "^0.2.2", "@storybook/types": "^8.0.8", "@svgr/webpack": "8.1.0", - "@testing-library/dom": "9.3.4", + "@testing-library/dom": "10.0.0", "@testing-library/jest-dom": "6.4.2", - "@types/node": "20.11.6", - "@types/react": "18.2.54", - "@types/react-dom": "18.2.22", + "@types/node": "20.12.7", + "@types/react": "18.2.79", + "@types/react-dom": "18.2.25", "@types/react-window": "1.8.8", "@xstate/cli": "^0.5.17", - "autoprefixer": "10.4.17", - "postcss": "8.4.35", - "postcss-import": "16.0.1", + "autoprefixer": "10.4.19", + "postcss": "8.4.38", + "postcss-import": "16.1.0", "radix-ui-themes-with-tailwind": "1.2.6", "storybook": "^8.0.8", "storybook-addon-theme": "workspace:*", - "tailwindcss": "3.4.1", + "tailwindcss": "3.4.3", "tailwindcss-animate": "1.0.7", - "tailwindcss-radix": "2.8.0", + "tailwindcss-radix": "3.0.3", "tsconfig-paths-webpack-plugin": "^4.1.0", - "tsup": "8.0.1", - "typescript": "5.3.3", - "vite": "^5.1.3", - "vite-tsconfig-paths": "^4.3.1" + "tsup": "8.0.2", + "typescript": "5.4.5", + "vite": "^5.2.9", + "vite-tsconfig-paths": "^4.3.2" }, "browser": { "fs": false, diff --git a/packages/app-explorer/src/app/account/[id]/layout.tsx b/packages/app-explorer/src/app/account/[id]/layout.tsx index fa8a64ae9..9501377ec 100644 --- a/packages/app-explorer/src/app/account/[id]/layout.tsx +++ b/packages/app-explorer/src/app/account/[id]/layout.tsx @@ -17,4 +17,4 @@ export default function Layout({ } export const dynamic = 'force-static'; -export const revalidate = Infinity; +export const revalidate = Number.POSITIVE_INFINITY; diff --git a/packages/app-explorer/src/app/account/[id]/predicate/page.tsx b/packages/app-explorer/src/app/account/[id]/predicate/page.tsx index 1a74faecf..2ce7399d5 100644 --- a/packages/app-explorer/src/app/account/[id]/predicate/page.tsx +++ b/packages/app-explorer/src/app/account/[id]/predicate/page.tsx @@ -12,4 +12,4 @@ export default async function Account({ params: { id } }: AccountRouteProps) { } export const dynamic = 'force-static'; -export const revalidate = Infinity; +export const revalidate = Number.POSITIVE_INFINITY; diff --git a/packages/app-explorer/src/app/api/graphql/route.ts b/packages/app-explorer/src/app/api/graphql/route.ts deleted file mode 100644 index 659f0eca5..000000000 --- a/packages/app-explorer/src/app/api/graphql/route.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { createExecutor, createSchema } from '@fuel-explorer/graphql'; -import { ContextDomain } from '@fuel-explorer/graphql/src/domains/Context'; -import { FUEL_CHAIN } from 'app-commons'; -import { createYoga } from 'graphql-yoga'; -import { NextResponse } from 'next/server'; - -const { providerUrl: url } = FUEL_CHAIN; - -const executor = createExecutor(async ({ body }) => { - return fetch(url, { - body, - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - }).then((res) => res.json()); -}); - -const schema = createSchema(executor); -const { handleRequest } = createYoga({ - schema, - batching: true, - graphqlEndpoint: '/api/graphql', - fetchAPI: { - Response, - Request, - }, - context: async () => { - return ContextDomain.createContext(url); - }, -}); - -const authenticatiohMiddleware = async (request: Request, ctx: Object) => { - if (process.env.FUEL_EXPLORER_API) { - return new NextResponse('Unauthorized', { - status: 401, - }); - } - return handleRequest(request, ctx); -}; - -export { - authenticatiohMiddleware as GET, - authenticatiohMiddleware as POST, - authenticatiohMiddleware as OPTIONS, -}; diff --git a/packages/app-explorer/src/app/block/[id]/[mode]/page.tsx b/packages/app-explorer/src/app/block/[id]/[mode]/page.tsx index 93417df70..147bf28e7 100644 --- a/packages/app-explorer/src/app/block/[id]/[mode]/page.tsx +++ b/packages/app-explorer/src/app/block/[id]/[mode]/page.tsx @@ -27,4 +27,4 @@ export default async function Block({ params: { id, mode } }: BlockRouteProps) { } export const dynamic = 'force-static'; -export const invalidate = Infinity; +export const invalidate = Number.POSITIVE_INFINITY; diff --git a/packages/app-explorer/src/app/block/[id]/layout.tsx b/packages/app-explorer/src/app/block/[id]/layout.tsx index 2464175dc..dba77dce3 100644 --- a/packages/app-explorer/src/app/block/[id]/layout.tsx +++ b/packages/app-explorer/src/app/block/[id]/layout.tsx @@ -18,4 +18,4 @@ export default function BlockLayout({ } export const dynamic = 'force-static'; -export const invalidate = Infinity; +export const invalidate = Number.POSITIVE_INFINITY; diff --git a/packages/app-explorer/src/app/bridge/layout.tsx b/packages/app-explorer/src/app/bridge/layout.tsx index 5a475d0fa..27efc6e4e 100644 --- a/packages/app-explorer/src/app/bridge/layout.tsx +++ b/packages/app-explorer/src/app/bridge/layout.tsx @@ -1,5 +1,5 @@ import { OverlayDialog, Providers } from 'app-portal'; -import { Metadata } from 'next'; +import type { Metadata } from 'next'; export const metadata: Metadata = { title: 'Fuel Bridge', diff --git a/packages/app-explorer/src/app/contract/[id]/code/page.tsx b/packages/app-explorer/src/app/contract/[id]/code/page.tsx index d3ddb3e29..4f593b2ef 100644 --- a/packages/app-explorer/src/app/contract/[id]/code/page.tsx +++ b/packages/app-explorer/src/app/contract/[id]/code/page.tsx @@ -14,4 +14,4 @@ export default async function ContractPage({ } export const dynamic = 'force-static'; -export const revalidate = Infinity; +export const revalidate = Number.POSITIVE_INFINITY; diff --git a/packages/app-explorer/src/app/contract/[id]/layout.tsx b/packages/app-explorer/src/app/contract/[id]/layout.tsx index 23b1f1176..fd8dbf219 100644 --- a/packages/app-explorer/src/app/contract/[id]/layout.tsx +++ b/packages/app-explorer/src/app/contract/[id]/layout.tsx @@ -17,4 +17,4 @@ export default function Layout({ } export const dynamic = 'force-static'; -export const revalidate = Infinity; +export const revalidate = Number.POSITIVE_INFINITY; diff --git a/packages/app-explorer/src/app/ecosystem/layout.tsx b/packages/app-explorer/src/app/ecosystem/layout.tsx index cb640645a..77a2ca5ea 100644 --- a/packages/app-explorer/src/app/ecosystem/layout.tsx +++ b/packages/app-explorer/src/app/ecosystem/layout.tsx @@ -1,5 +1,5 @@ import { OverlayDialog, Providers } from 'app-portal'; -import { Metadata } from 'next'; +import type { Metadata } from 'next'; export const metadata: Metadata = { title: 'Fuel Ecosystem', diff --git a/packages/app-explorer/src/app/page.tsx b/packages/app-explorer/src/app/page.tsx index 7f07ea4a1..aae1997a4 100644 --- a/packages/app-explorer/src/app/page.tsx +++ b/packages/app-explorer/src/app/page.tsx @@ -5,16 +5,16 @@ import { TxsScreenSync } from '~/systems/Transactions/pages/TxsScreenSync'; import type { TxsRouteProps } from '~/systems/Transactions/types'; export default async function Home({ - searchParams: { page = '1' }, + searchParams: { after, before }, }: TxsRouteProps) { return ( <> } + key={after || before} + fallback={} > - + ); diff --git a/packages/app-explorer/src/app/tx/[id]/[mode]/page.tsx b/packages/app-explorer/src/app/tx/[id]/[mode]/page.tsx index b8bf8466e..cbf4f7979 100644 --- a/packages/app-explorer/src/app/tx/[id]/[mode]/page.tsx +++ b/packages/app-explorer/src/app/tx/[id]/[mode]/page.tsx @@ -29,4 +29,4 @@ export default async function Transaction({ } export const fetchCache = 'force-cache'; -export const revalidate = Infinity; +export const revalidate = Number.POSITIVE_INFINITY; diff --git a/packages/app-explorer/src/app/tx/[id]/layout.tsx b/packages/app-explorer/src/app/tx/[id]/layout.tsx index ce27babc3..d7b8e4296 100644 --- a/packages/app-explorer/src/app/tx/[id]/layout.tsx +++ b/packages/app-explorer/src/app/tx/[id]/layout.tsx @@ -17,4 +17,4 @@ export default function TxLayout({ } export const dynamic = 'force-static'; -export const revalidate = Infinity; +export const revalidate = Number.POSITIVE_INFINITY; diff --git a/packages/app-explorer/src/graphql.d.ts b/packages/app-explorer/src/graphql.d.ts deleted file mode 100644 index a7eac6db2..000000000 --- a/packages/app-explorer/src/graphql.d.ts +++ /dev/null @@ -1,5 +0,0 @@ -declare module '*.graphql' { - import type { DocumentNode } from 'graphql'; - const Schema: DocumentNode; - export = Schema; -} diff --git a/packages/app-explorer/src/routes.ts b/packages/app-explorer/src/routes.ts index 1d69f39d1..bb52aa0b1 100644 --- a/packages/app-explorer/src/routes.ts +++ b/packages/app-explorer/src/routes.ts @@ -1,7 +1,10 @@ import { route } from 'app-commons'; export const Routes = { - home: route<[page: string]>('/?page=:page'), + home: { + after: route<[after: string]>('/?after=:after'), + before: route<[before: string]>('/?before=:before'), + }, txSimple: route<[id: string]>('/tx/:id/simple'), txAdvanced: route<[id: string]>('/tx/:id/advanced'), blockSimple: route<[id: string]>('/block/:id/simple'), diff --git a/packages/app-explorer/src/systems/Account/actions/get-account-transactions.ts b/packages/app-explorer/src/systems/Account/actions/get-account-transactions.ts index b0fb3307d..a284c6a2d 100644 --- a/packages/app-explorer/src/systems/Account/actions/get-account-transactions.ts +++ b/packages/app-explorer/src/systems/Account/actions/get-account-transactions.ts @@ -11,6 +11,6 @@ const schema = z.object({ export const getAccountTransactions = act(schema, async (input) => { const owner = parseAddressParam(input.owner); - const { data } = await sdk.getAccountTransactions({ owner }); - return data.transactions; + const { data } = await sdk.transactionsByOwner({ owner }); + return data.transactionsByOwner; }); diff --git a/packages/app-explorer/src/systems/Account/actions/get-balances.ts b/packages/app-explorer/src/systems/Account/actions/get-balances.ts index 01ab6865f..eefc10b01 100644 --- a/packages/app-explorer/src/systems/Account/actions/get-balances.ts +++ b/packages/app-explorer/src/systems/Account/actions/get-balances.ts @@ -11,8 +11,6 @@ const schema = z.object({ export const getBalances = act(schema, async (input) => { const owner = parseAddressParam(input.owner); - const { data } = await sdk.getBalances({ owner }).catch((_) => { - return { data: { balances: { nodes: [] } } }; - }); + const { data } = await sdk.balances({ first: 50, filter: { owner } }); return data.balances.nodes; }); diff --git a/packages/app-explorer/src/systems/Account/actions/get-predicate.ts b/packages/app-explorer/src/systems/Account/actions/get-predicate.ts index 3ecc46167..934bc0066 100644 --- a/packages/app-explorer/src/systems/Account/actions/get-predicate.ts +++ b/packages/app-explorer/src/systems/Account/actions/get-predicate.ts @@ -11,6 +11,6 @@ const schema = z.object({ export const getPredicate = act(schema, async (input) => { if (!input.owner) return null; - const { data } = await sdk.getPredicate({ address: input.owner }); + const { data } = await sdk.predicate({ address: input.owner }); return data.predicate; }); diff --git a/packages/app-explorer/src/systems/Account/components/AccountAssets/AccountAssets.tsx b/packages/app-explorer/src/systems/Account/components/AccountAssets/AccountAssets.tsx index 0fcc1ac78..86fcca58f 100644 --- a/packages/app-explorer/src/systems/Account/components/AccountAssets/AccountAssets.tsx +++ b/packages/app-explorer/src/systems/Account/components/AccountAssets/AccountAssets.tsx @@ -1,10 +1,10 @@ -import type { AccountBalanceFragment } from '@fuel-explorer/graphql'; +import type { GQLBalanceFragment } from '@fuel-explorer/graphql'; import { VStack } from '@fuels/ui'; import { BalanceItem } from '~/systems/Core/components/BalanceItem/BalanceItem'; import { EmptyAssets } from '~/systems/Core/components/EmptyBlocks/EmptyAsset'; export type AccountAssetsProps = { - balances: AccountBalanceFragment[]; + balances: GQLBalanceFragment[]; id: string; isLoading?: boolean; }; diff --git a/packages/app-explorer/src/systems/Account/components/AccountPredicate/AccountPredicate.tsx b/packages/app-explorer/src/systems/Account/components/AccountPredicate/AccountPredicate.tsx index 9550b019b..9e21389c3 100644 --- a/packages/app-explorer/src/systems/Account/components/AccountPredicate/AccountPredicate.tsx +++ b/packages/app-explorer/src/systems/Account/components/AccountPredicate/AccountPredicate.tsx @@ -1,11 +1,11 @@ 'use client'; -import type { Predicate } from '@fuel-explorer/graphql'; +import type { GQLPredicateItem, Maybe } from '@fuel-explorer/graphql'; import { VStack } from '@fuels/ui'; import { CodeBlock } from '~/systems/Core/components/CodeBlock/CodeBlock'; export type AccountPredicateProps = { - predicate?: Predicate; + predicate?: Maybe; id: string; isLoading?: boolean; }; diff --git a/packages/app-explorer/src/systems/Account/components/AccountTabs/AccountTabsSync.tsx b/packages/app-explorer/src/systems/Account/components/AccountTabs/AccountTabsSync.tsx index ba4978931..1c86b3532 100644 --- a/packages/app-explorer/src/systems/Account/components/AccountTabs/AccountTabsSync.tsx +++ b/packages/app-explorer/src/systems/Account/components/AccountTabs/AccountTabsSync.tsx @@ -4,5 +4,10 @@ import { AccountTabs } from './AccountTabs'; export async function AccountsTabsSync({ id }: { id: string }) { const predicate = await getPredicate({ owner: id }); - return ; + return ( + + ); } diff --git a/packages/app-explorer/src/systems/Account/screens/AccountPredicateSync.tsx b/packages/app-explorer/src/systems/Account/screens/AccountPredicateSync.tsx index 090054827..66291aa87 100644 --- a/packages/app-explorer/src/systems/Account/screens/AccountPredicateSync.tsx +++ b/packages/app-explorer/src/systems/Account/screens/AccountPredicateSync.tsx @@ -4,5 +4,5 @@ import { AccountPredicate } from '../components/AccountPredicate/AccountPredicat export async function AccountPredicateSync({ id }: { id: string }) { const predicate = await getPredicate({ owner: id }); - return ; + return ; } diff --git a/packages/app-explorer/src/systems/Account/screens/AccountTransactionsSync.tsx b/packages/app-explorer/src/systems/Account/screens/AccountTransactionsSync.tsx index 28a83dd1b..72627ea90 100644 --- a/packages/app-explorer/src/systems/Account/screens/AccountTransactionsSync.tsx +++ b/packages/app-explorer/src/systems/Account/screens/AccountTransactionsSync.tsx @@ -5,7 +5,7 @@ import { getAccountTransactions } from '../actions/get-account-transactions'; export async function AccountTransactionsSync({ id }: { id: string }) { const txs = await getAccountTransactions({ owner: id }); - const transactions = txs.edges; + const transactions = txs.nodes; if (!transactions.length) { return ; } diff --git a/packages/app-explorer/src/systems/Block/actions/get-block.ts b/packages/app-explorer/src/systems/Block/actions/get-block.ts index 22b1bf120..256030cd7 100644 --- a/packages/app-explorer/src/systems/Block/actions/get-block.ts +++ b/packages/app-explorer/src/systems/Block/actions/get-block.ts @@ -1,6 +1,6 @@ 'use server'; -import type { GetBlockByHeightQuery } from '@fuel-explorer/graphql'; +import type { GQLBlockFragment } from '@fuel-explorer/graphql'; import { Signer } from 'fuels'; import { z } from 'zod'; import { act } from '~/systems/Core/utils/act-server'; @@ -20,28 +20,22 @@ export const getBlock = act(schema, async (input) => { } if (isAddressValid) { - const { data } = await sdk.getBlockById({ id }); - const producer = getProducer(data); + const { data } = await sdk.block({ id }); + const producer = getProducer(data?.block); return { block: data.block, producer }; } - const { data } = await sdk.getBlockByHeight({ height: id }); - const producer = getProducer(data); + const { data } = await sdk.block({ height: id }); + const producer = getProducer(data?.block); return { block: data.block, producer }; }); -const getProducer = ( - data: - | GetBlockByHeightQuery - | { - block: null; - }, -) => { +const getProducer = (block?: GQLBlockFragment | null) => { // TODO use custom resolver once a fix is found let producer: string | null = null; - if (data.block && data.block.consensus.__typename === 'PoAConsensus') { - const signature = data?.block?.consensus.signature; - producer = Signer.recoverAddress(data.block.id, signature).toAddress(); + if (block && block.consensus.__typename === 'PoAConsensus') { + const signature = block?.consensus.signature; + producer = Signer.recoverAddress(block.id, signature).toAddress(); } return producer; diff --git a/packages/app-explorer/src/systems/Block/components/Block.tsx b/packages/app-explorer/src/systems/Block/components/Block.tsx index 516a8fdab..6c7a27990 100644 --- a/packages/app-explorer/src/systems/Block/components/Block.tsx +++ b/packages/app-explorer/src/systems/Block/components/Block.tsx @@ -1,6 +1,6 @@ 'use client'; -import type { BlockItemFragment, Maybe } from '@fuel-explorer/graphql'; +import type { GQLBlockFragment, Maybe } from '@fuel-explorer/graphql'; import { ViewModes } from '~/systems/Core/components/ViewMode/ViewMode'; import { BlockHeader } from './BlockHeader'; @@ -10,7 +10,7 @@ import { BlockScreenSimple } from './BlockScreenSimple'; type BlockScreenProps = { id: string; viewMode: ViewModes; - block?: Maybe; + block?: Maybe; producer: Maybe; isLoading?: boolean; }; diff --git a/packages/app-explorer/src/systems/Block/components/BlockHeader.tsx b/packages/app-explorer/src/systems/Block/components/BlockHeader.tsx index 17610ba70..fa2ca6072 100644 --- a/packages/app-explorer/src/systems/Block/components/BlockHeader.tsx +++ b/packages/app-explorer/src/systems/Block/components/BlockHeader.tsx @@ -2,8 +2,12 @@ import { Address, LoadingBox, LoadingWrapper } from '@fuels/ui'; import { IconCube } from '@tabler/icons-react'; import { PageTitle } from 'app-commons'; +import { useParams } from 'next/navigation'; import { PageSubtitle } from '~/systems/Core/components/PageSubtitle/PageSubtitle'; -import { ViewMode } from '~/systems/Core/components/ViewMode/ViewMode'; +import { + ViewMode, + type ViewModes, +} from '~/systems/Core/components/ViewMode/ViewMode'; import { isValidAddress } from '~/systems/Core/utils/address'; export function BlockHeader({ @@ -13,10 +17,11 @@ export function BlockHeader({ id: string; isLoading?: boolean; }) { + const { mode } = useParams<{ mode: ViewModes }>(); return ( } - rightElement={!isLoading && } + rightElement={!isLoading && } > Block }>; + block?: Maybe }>; }; export function BlockScreenAdvanced({ block }: BlockScreenAdvancedProps) { if (!block) { return null; } + return ( diff --git a/packages/app-explorer/src/systems/Block/components/BlockScreenSimple.tsx b/packages/app-explorer/src/systems/Block/components/BlockScreenSimple.tsx index c3e9ccdb5..bccc70303 100644 --- a/packages/app-explorer/src/systems/Block/components/BlockScreenSimple.tsx +++ b/packages/app-explorer/src/systems/Block/components/BlockScreenSimple.tsx @@ -1,7 +1,6 @@ -/* eslint-disable @typescript-eslint/no-explicit-any */ 'use client'; -import type { BlockItemFragment, Maybe } from '@fuel-explorer/graphql'; +import type { GQLBlockFragment, Maybe } from '@fuel-explorer/graphql'; import { Address, Grid, @@ -19,7 +18,7 @@ import { TxList } from '~/systems/Transactions/components/TxList/TxList'; import { TxListLoader } from '~/systems/Transactions/components/TxList/TxListLoader'; type BlockScreenSimpleProps = { - block?: Maybe; + block?: Maybe; producer?: Maybe; isLoading?: boolean; }; @@ -29,7 +28,8 @@ export function BlockScreenSimple({ producer, isLoading, }: BlockScreenSimpleProps) { - const txList = (block?.transactions.map((v) => ({ node: v })) as any) || []; + const txList = block?.transactions ?? []; + return ( diff --git a/packages/app-explorer/src/systems/Block/screens/BlockScreenSimpleSync.tsx b/packages/app-explorer/src/systems/Block/screens/BlockScreenSimpleSync.tsx index 56829914a..8a6cf420f 100644 --- a/packages/app-explorer/src/systems/Block/screens/BlockScreenSimpleSync.tsx +++ b/packages/app-explorer/src/systems/Block/screens/BlockScreenSimpleSync.tsx @@ -4,5 +4,6 @@ import type { BlockRouteParams } from '../types'; export async function BlockScreenSimpleSync({ id }: BlockRouteParams) { const { block, producer } = await getBlock({ id }); + return ; } diff --git a/packages/app-explorer/src/systems/Contract/actions/get-contract.ts b/packages/app-explorer/src/systems/Contract/actions/get-contract.ts index 2b16b6366..4b7feed42 100644 --- a/packages/app-explorer/src/systems/Contract/actions/get-contract.ts +++ b/packages/app-explorer/src/systems/Contract/actions/get-contract.ts @@ -11,12 +11,15 @@ const schema = z.object({ export const getContract = act(schema, async (input) => { const id = parseAddressParam(input.id); - const { data } = await sdk.getContract({ id }); + const { data } = await sdk.contract({ id }); return data.contract; }); export const getContractBalances = act(schema, async (input) => { const id = parseAddressParam(input.id); - const { data } = await sdk.getContractBalances({ id }); + const { data } = await sdk.contractBalances({ + first: 1000, + filter: { contract: id }, + }); return data.contractBalances; }); diff --git a/packages/app-explorer/src/systems/Contract/components/ContractAssetList.tsx b/packages/app-explorer/src/systems/Contract/components/ContractAssetList.tsx index 07d13c834..29a455bdf 100644 --- a/packages/app-explorer/src/systems/Contract/components/ContractAssetList.tsx +++ b/packages/app-explorer/src/systems/Contract/components/ContractAssetList.tsx @@ -1,6 +1,6 @@ 'use client'; import type { - ContractBalanceConnectionItemFragment, + GQLContractBalanceConnectionNodeFragment, Maybe, } from '@fuel-explorer/graphql'; import { VStack } from '@fuels/ui'; @@ -10,7 +10,7 @@ import { EmptyCard } from '~/systems/Core/components/EmptyCard/EmptyCard'; import { ContractBalanceItem } from './ContractBalanceItem'; type TabAssetsProps = { - balances?: Maybe; + balances?: Maybe; }; export function ContractAssetList({ balances }: TabAssetsProps) { @@ -34,7 +34,8 @@ export function ContractAssetList({ balances }: TabAssetsProps) { return ( ); })} diff --git a/packages/app-explorer/src/systems/Core/actions/search.ts b/packages/app-explorer/src/systems/Core/actions/search.ts index f96d0fa4d..dcdcc2086 100644 --- a/packages/app-explorer/src/systems/Core/actions/search.ts +++ b/packages/app-explorer/src/systems/Core/actions/search.ts @@ -9,8 +9,6 @@ const schema = z.object({ }); export const search = act(schema, async ({ query }) => { - const { data } = await sdk.searchQuery({ search: query }).catch((_) => { - return { data: { search: null } }; - }); - return data?.search ?? null; + const { data } = await sdk.search({ query }); + return data; }); diff --git a/packages/app-explorer/src/systems/Core/components/BalanceItem/BalanceItem.tsx b/packages/app-explorer/src/systems/Core/components/BalanceItem/BalanceItem.tsx index 2d2e390d4..2761d0f93 100644 --- a/packages/app-explorer/src/systems/Core/components/BalanceItem/BalanceItem.tsx +++ b/packages/app-explorer/src/systems/Core/components/BalanceItem/BalanceItem.tsx @@ -1,5 +1,5 @@ 'use client'; -import type { AccountBalanceFragment } from '@fuel-explorer/graphql'; +import type { GQLBalanceFragment } from '@fuel-explorer/graphql'; import type { BaseProps } from '@fuels/ui'; import { Address, @@ -17,7 +17,7 @@ import type { UtxoItem } from '../Utxos/Utxos'; import { Utxos } from '../Utxos/Utxos'; type BalanceItemProps = BaseProps<{ - item: Omit; + item: Omit; isLoading?: boolean; }>; diff --git a/packages/app-explorer/src/systems/Core/components/Pagination/Pagination.tsx b/packages/app-explorer/src/systems/Core/components/Pagination/Pagination.tsx index b74020995..62ac08373 100644 --- a/packages/app-explorer/src/systems/Core/components/Pagination/Pagination.tsx +++ b/packages/app-explorer/src/systems/Core/components/Pagination/Pagination.tsx @@ -1,23 +1,27 @@ -import type { BaseProps } from '@fuels/ui'; import { Button, HStack, cx } from '@fuels/ui'; import { IconArrowLeft, IconArrowRight } from '@tabler/icons-react'; -type PaginationProps = BaseProps<{ - page: number; - onChange?: (page: number) => void; -}>; - -export function Pagination({ page, onChange, ...props }: PaginationProps) { - const hasPrev = page > 1; - const hasNext = page < 10; +type PaginationProps = { + hasPrev?: boolean; + hasNext?: boolean; + onPrev: () => void; + onNext: () => void; + className?: string; +}; +export function Pagination({ + hasPrev, + hasNext, + onPrev, + onNext, + className, +}: PaginationProps) { return ( - diff --git a/packages/app-explorer/src/systems/Core/components/Search/SearchForm.tsx b/packages/app-explorer/src/systems/Core/components/Search/SearchForm.tsx index 62615ca68..899df0095 100644 --- a/packages/app-explorer/src/systems/Core/components/Search/SearchForm.tsx +++ b/packages/app-explorer/src/systems/Core/components/Search/SearchForm.tsx @@ -1,4 +1,4 @@ -import type { SearchResult } from '@fuel-explorer/graphql'; +import type { GQLSearchQuery } from '@fuel-explorer/graphql'; import { useContext } from 'react'; import { useFormState } from 'react-dom'; import { search } from '~/systems/Core/actions/search'; @@ -19,8 +19,8 @@ export function SearchForm({ expandOnFocus, }: SearchFormProps) { const classes = styles(); - const [results, action] = useFormState( - (_: SearchResult | null, formData: FormData) => { + const [data, action] = useFormState( + (_: GQLSearchQuery | null, formData: FormData) => { return search({ query: formData.get('query')?.toString() || '' }); }, null, @@ -31,7 +31,7 @@ export function SearchForm({
; + searchResult?: Maybe; openDropdown: boolean; onOpenChange: () => void; searchValue: string; @@ -208,7 +208,7 @@ const SearchResultDropdown = forwardRef( type SearchInputProps = BaseProps & { onSubmit?: (value: string) => void; onClear?: (value: string) => void; - searchResult?: Maybe; + searchResult?: Maybe; alwaysDisplayActionButtons?: boolean; expandOnFocus?: boolean; }; diff --git a/packages/app-explorer/src/systems/Core/components/Utxos/Utxos.tsx b/packages/app-explorer/src/systems/Core/components/Utxos/Utxos.tsx index 22e05a5a9..9ba88dd0e 100644 --- a/packages/app-explorer/src/systems/Core/components/Utxos/Utxos.tsx +++ b/packages/app-explorer/src/systems/Core/components/Utxos/Utxos.tsx @@ -1,4 +1,4 @@ -import type { UtxoItem as TUtxoItem } from '@fuel-explorer/graphql'; +import type { GQLUtxoItem as TUtxoItem } from '@fuel-explorer/graphql'; import { Address, Box, Collapsible, useBreakpoints } from '@fuels/ui'; import type { BoxProps } from '@fuels/ui'; import { IconCoins } from '@tabler/icons-react'; diff --git a/packages/app-explorer/src/systems/Core/components/ViewMode/ViewMode.tsx b/packages/app-explorer/src/systems/Core/components/ViewMode/ViewMode.tsx index 58f1d27b7..089ee17c7 100644 --- a/packages/app-explorer/src/systems/Core/components/ViewMode/ViewMode.tsx +++ b/packages/app-explorer/src/systems/Core/components/ViewMode/ViewMode.tsx @@ -1,15 +1,12 @@ import { ToggleGroup } from '@fuels/ui'; import Link from 'next/link'; -import { useParams } from 'next/navigation'; export enum ViewModes { Simple = 'simple', Advanced = 'advanced', } -export function ViewMode() { - const { mode } = useParams<{ mode: ViewModes }>(); - +export function ViewMode({ mode }: { mode: ViewModes }) { return ( diff --git a/packages/app-explorer/src/systems/Core/utils/sdk.ts b/packages/app-explorer/src/systems/Core/utils/sdk.ts index 072aaffe0..592f2ece1 100644 --- a/packages/app-explorer/src/systems/Core/utils/sdk.ts +++ b/packages/app-explorer/src/systems/Core/utils/sdk.ts @@ -1,27 +1,21 @@ -import { resolve } from 'url'; -import { getSdk } from '@fuel-explorer/graphql/src/sdk'; +import { getSdk } from '@fuel-explorer/graphql/sdk'; import { GraphQLClient } from 'graphql-request'; const { FUEL_EXPLORER_API, FUEL_EXPLORER_API_KEY } = process.env; -const VERCEL_URL = process.env.VERCEL_URL || process.env.NEXT_PUBLIC_VERCEL_URL; -const VERCEL_ENV = - process.env.VERCEL_ENV || process.env.NEXT_PUBLIC_VERCEL_ENV || 'development'; -const getBaseUrl = () => { - if (FUEL_EXPLORER_API && FUEL_EXPLORER_API_KEY) return FUEL_EXPLORER_API; - if (VERCEL_ENV !== 'development') - return resolve(`https://${VERCEL_URL}`, '/api/graphql'); - return 'http://localhost:3000/api/graphql'; -}; +if (!FUEL_EXPLORER_API) { + throw new Error('FUEL_EXPLORER_API is required'); +} + const getHeaders = () => { - if (FUEL_EXPLORER_API_KEY) { - return { Authorization: `Bearer ${FUEL_EXPLORER_API_KEY}` }; - } - return undefined; + return FUEL_EXPLORER_API_KEY + ? { Authorization: `Bearer ${FUEL_EXPLORER_API_KEY}` } + : undefined; }; -const client = new GraphQLClient(getBaseUrl(), { +const client = new GraphQLClient(FUEL_EXPLORER_API, { fetch, headers: getHeaders(), }); + export const sdk = getSdk(client); diff --git a/packages/app-explorer/src/systems/Transaction/__mocks__/tx.ts b/packages/app-explorer/src/systems/Transaction/__mocks__/tx.ts index cd72319d7..4c74d4b2c 100644 --- a/packages/app-explorer/src/systems/Transaction/__mocks__/tx.ts +++ b/packages/app-explorer/src/systems/Transaction/__mocks__/tx.ts @@ -1,9 +1,4 @@ -/* eslint-disable @typescript-eslint/no-explicit-any */ -import { - GroupedInputType, - GroupedOutputType, - mocks, -} from '@fuel-explorer/graphql'; +import { GQLGroupedInputType, mocks } from '@fuel-explorer/graphql'; import { dayjs } from '~/systems/Core/utils/dayjs'; const date = dayjs().subtract(1, 'day'); @@ -14,7 +9,7 @@ const status = mocks.aSuccessStatus({ }), }); -function input(typename: any) { +function input(typename?: 'InputCoin') { return mocks.anInputCoin({ __typename: typename }); } @@ -26,62 +21,58 @@ const ADDRS = { contractId: 'fuel1f347fmtxk7pl2hjy5mfk9y9889c2v946xvjkvdk0zkk4ehkj9rvs8a3c9m', }; -export const GROUPED_INPUT_ASSET = mocks.aGroupedInput({ - ...ADDRS, - type: GroupedInputType.InputCoin, +export const GROUPED_INPUT_ASSET = mocks.aGroupedInputCoin({ + owner: ADDRS.owner, + type: GQLGroupedInputType.InputCoin, assetId: '0x0000000000000000000000000000000000000000', inputs: [input('InputCoin'), input('InputCoin'), input('InputCoin')], }); -export const GROUPED_INPUT_ASSET_UNKNOWN = mocks.aGroupedInput({ - ...ADDRS, - type: GroupedInputType.InputCoin, +export const GROUPED_INPUT_ASSET_UNKNOWN = mocks.aGroupedInputCoin({ + owner: ADDRS.owner, + type: GQLGroupedInputType.InputCoin, + assetId: undefined, inputs: [input('InputCoin'), input('InputCoin'), input('InputCoin')], }); -export const GROUPED_INPUT_MESSAGE = mocks.aGroupedInput({ - ...ADDRS, - type: GroupedInputType.InputMessage, +export const GROUPED_INPUT_MESSAGE = mocks.aGroupedInputMessage({ + recipient: ADDRS.recipient, + sender: ADDRS.sender, + type: GQLGroupedInputType.InputMessage, }); -function output(typename: any) { +function output(typename?: 'CoinOutput') { return mocks.aCoinOutput({ __typename: typename }); } -export const GROUPED_OUTPUT_ASSET = mocks.aGroupedOutput({ - ...ADDRS, - type: GroupedOutputType.CoinOutput, - outputs: [output('OutputCoin'), output('OutputCoin'), output('OutputCoin')], +export const GROUPED_OUTPUT_ASSET = mocks.aGroupedOutputCoin({ + to: ADDRS.to, assetId: '0x0000000000000000000000000000000000000000', + outputs: [output('CoinOutput'), output('CoinOutput'), output('CoinOutput')], }); -export const GROUPED_OUTPUT_ASSET_UNKNOWN = mocks.aGroupedOutput({ - ...ADDRS, - type: GroupedOutputType.CoinOutput, - outputs: [output('outputCoin'), output('outputCoin'), output('outputCoin')], -}); -export const GROUPED_OUTPUT_CHANGE_OUTPUT = mocks.aGroupedOutput({ - ...ADDRS, - type: GroupedOutputType.ChangeOutput, - outputs: [output('outputCoin'), output('outputCoin'), output('outputCoin')], - assetId: '0x0000000000000000000000000000000000000000', +export const GROUPED_OUTPUT_ASSET_UNKNOWN = mocks.aGroupedOutputCoin({ + to: ADDRS.to, + assetId: undefined, + outputs: [output('CoinOutput'), output('CoinOutput'), output('CoinOutput')], }); -export const GROUPED_OUTPUT_CHANGE_OUTPUT_UNKNOWN = mocks.aGroupedOutput({ - ...ADDRS, - type: GroupedOutputType.ChangeOutput, - outputs: [output('outputCoin'), output('outputCoin'), output('outputCoin')], +export const GROUPED_OUTPUT_CHANGE_OUTPUT = mocks.aGroupedOutputChanged({ + to: ADDRS.to, + assetId: '0x0000000000000000000000000000000000000000', + outputs: [output('CoinOutput'), output('CoinOutput'), output('CoinOutput')], }); -export const GROUPED_OUTPUT_CONTRACT_CREATED = mocks.aGroupedOutput({ - ...ADDRS, - type: GroupedOutputType.ContractCreated, -}); +export const GROUPED_OUTPUT_CHANGE_OUTPUT_UNKNOWN = mocks.aGroupedOutputChanged( + { + to: ADDRS.to, + assetId: undefined, + outputs: [output('CoinOutput'), output('CoinOutput'), output('CoinOutput')], + }, +); -export const GROUPED_OUTPUT_MESSAGE = mocks.aGroupedOutput({ - ...ADDRS, - type: GroupedOutputType.MessageOutput, -}); +export const GROUPED_OUTPUT_CONTRACT_CREATED = + mocks.aGroupedOutputContractCreated({}); export const TX_MOCK = mocks.aTransaction({ title: 'ContractCall', @@ -90,9 +81,6 @@ export const TX_MOCK = mocks.aTransaction({ fromNow: date.fromNow(), full: dayjs().format('DD MMM YYYY - HH:mm:ss A'), }, - totalAccounts: 2, - totalAssets: 3, - totalOperations: 4, status, groupedInputs: [ GROUPED_INPUT_ASSET, @@ -104,6 +92,5 @@ export const TX_MOCK = mocks.aTransaction({ GROUPED_OUTPUT_ASSET, GROUPED_OUTPUT_ASSET_UNKNOWN, GROUPED_OUTPUT_CONTRACT_CREATED, - GROUPED_OUTPUT_MESSAGE, ], }); diff --git a/packages/app-explorer/src/systems/Transaction/actions/get-tx.ts b/packages/app-explorer/src/systems/Transaction/actions/get-tx.ts index 1208ec168..46b21d6be 100644 --- a/packages/app-explorer/src/systems/Transaction/actions/get-tx.ts +++ b/packages/app-explorer/src/systems/Transaction/actions/get-tx.ts @@ -13,7 +13,7 @@ const schema = z.object({ export const getTx = act(schema, async (input) => { try { const id = parseAddressParam(input.id); - const { data } = await sdk.getTransaction({ id }); + const { data } = await sdk.transactionDetails({ id }); return data.transaction; } catch (e) { console.error(e); diff --git a/packages/app-explorer/src/systems/Transaction/component/TxHeader/TxHeader.tsx b/packages/app-explorer/src/systems/Transaction/component/TxHeader/TxHeader.tsx index b88a60e8f..bd99361ac 100644 --- a/packages/app-explorer/src/systems/Transaction/component/TxHeader/TxHeader.tsx +++ b/packages/app-explorer/src/systems/Transaction/component/TxHeader/TxHeader.tsx @@ -2,7 +2,11 @@ import { Address, useBreakpoints } from '@fuels/ui'; import { IconChecklist } from '@tabler/icons-react'; import { PageTitle } from 'app-commons'; -import { ViewMode } from '~/systems/Core/components/ViewMode/ViewMode'; +import { useParams } from 'next/navigation'; +import { + ViewMode, + type ViewModes, +} from '~/systems/Core/components/ViewMode/ViewMode'; export function TxHeader({ id, @@ -12,10 +16,11 @@ export function TxHeader({ isLoading?: boolean; }) { const { isLaptop } = useBreakpoints(); + const { mode } = useParams<{ mode: ViewModes }>(); return ( } - rightElement={!isLoading && } + rightElement={!isLoading && } > Transaction
diff --git a/packages/app-explorer/src/systems/Transaction/component/TxInput/TxInput.tsx b/packages/app-explorer/src/systems/Transaction/component/TxInput/TxInput.tsx index bc3ca649f..906dfa0c7 100644 --- a/packages/app-explorer/src/systems/Transaction/component/TxInput/TxInput.tsx +++ b/packages/app-explorer/src/systems/Transaction/component/TxInput/TxInput.tsx @@ -1,4 +1,9 @@ -import type { GroupedInput, InputCoin } from '@fuel-explorer/graphql'; +import type { + GQLInputCoin, + GQLTxDetailsGroupedInputCoinFragment, + GQLTxDetailsGroupedInputContractFragment, + GQLTxDetailsGroupedInputMessageFragment, +} from '@fuel-explorer/graphql'; import { Address, Box, @@ -20,18 +25,30 @@ import { Utxos } from '~/systems/Core/components/Utxos/Utxos'; import { TxIcon } from '../TxIcon/TxIcon'; -export type TxInputProps = CardProps & { - input: GroupedInput; +type Inputs = + | GQLTxDetailsGroupedInputCoinFragment + | GQLTxDetailsGroupedInputMessageFragment + | GQLTxDetailsGroupedInputContractFragment; + +export type TxInputProps = CardProps & { + input: T; }; -const TxInputCoin = createComponent({ +const TxInputCoin = createComponent< + TxInputProps, + typeof Collapsible +>({ id: 'TxInputCoin', render: (_, { input, ...props }) => { + if (!input) { + return null; + } + if (!input.assetId) return null; const assetId = input.assetId; const amount = input.totalAmount; - const inputs = input.inputs as InputCoin[]; + const inputs = input.inputs as GQLInputCoin[]; const { isMobile } = useBreakpoints(); return ( @@ -66,7 +83,10 @@ const TxInputCoin = createComponent({ }, }); -const TxInputMessage = createComponent({ +const TxInputMessage = createComponent< + TxInputProps, + typeof Collapsible +>({ id: 'TxInputMessage', render: (_, { input, ...props }) => { const { sender, recipient, data } = input; @@ -83,7 +103,10 @@ const TxInputMessage = createComponent({
({ }); export function TxInput({ input, ...props }: TxInputProps) { - if (input.type === 'InputCoin') { + if (!input) { + return null; + } + + if (input.__typename === 'GroupedInputCoin') { return ; } - if (input.type === 'InputMessage') { + + if (input.__typename === 'GroupedInputMessage') { return ; } + + return null; } diff --git a/packages/app-explorer/src/systems/Transaction/component/TxOutput/TxOutput.stories.tsx b/packages/app-explorer/src/systems/Transaction/component/TxOutput/TxOutput.stories.tsx index ae496696f..e4cfa7d06 100644 --- a/packages/app-explorer/src/systems/Transaction/component/TxOutput/TxOutput.stories.tsx +++ b/packages/app-explorer/src/systems/Transaction/component/TxOutput/TxOutput.stories.tsx @@ -5,7 +5,6 @@ import { GROUPED_OUTPUT_ASSET, GROUPED_OUTPUT_ASSET_UNKNOWN, GROUPED_OUTPUT_CONTRACT_CREATED, - GROUPED_OUTPUT_MESSAGE, TX_MOCK, } from '../../__mocks__/tx'; @@ -45,13 +44,3 @@ export const ContractCreated: Story = { /> ), }; - -export const Message: Story = { - render: () => ( - - ), -}; diff --git a/packages/app-explorer/src/systems/Transaction/component/TxOutput/TxOutput.tsx b/packages/app-explorer/src/systems/Transaction/component/TxOutput/TxOutput.tsx index 74ac1ad49..3e6fb552d 100644 --- a/packages/app-explorer/src/systems/Transaction/component/TxOutput/TxOutput.tsx +++ b/packages/app-explorer/src/systems/Transaction/component/TxOutput/TxOutput.tsx @@ -1,7 +1,8 @@ -import { GroupedOutputType } from '@fuel-explorer/graphql'; import type { - GroupedOutput, - TransactionItemFragment, + GQLTransactionDetailsFragment, + GQLTxDetailsGroupedOutputChangedFragment, + GQLTxDetailsGroupedOutputCoinFragment, + GQLTxDetailsGroupedOutputContractCreatedFragment, } from '@fuel-explorer/graphql'; import { Address, @@ -25,22 +26,33 @@ import { Amount } from '~/systems/Core/components/Amount/Amount'; import { TxIcon } from '../TxIcon/TxIcon'; -function getTooltipText(tx: TransactionItemFragment, output: GroupedOutput) { +type Outputs = + | GQLTxDetailsGroupedOutputChangedFragment + | GQLTxDetailsGroupedOutputCoinFragment + | GQLTxDetailsGroupedOutputContractCreatedFragment; + +function getTooltipText(tx: GQLTransactionDetailsFragment, output: Outputs) { if (tx.isMint) { return 'This is the amount minted in the transaction'; } - if (output.type === GroupedOutputType.ChangeOutput) { + if (output.__typename === 'GroupedOutputChanged') { return 'This is the amount remaining after transaction'; } return 'This is the amount spent in the transaction'; } -export type TxOutputProps = CardProps & { - tx: TransactionItemFragment; - output: GroupedOutput; +export type TxOutputProps = CardProps & { + tx: GQLTransactionDetailsFragment; + output: T; }; -const TxOutputCoin = createComponent({ +const TxOutputCoin = createComponent< + TxOutputProps< + | GQLTxDetailsGroupedOutputCoinFragment + | GQLTxDetailsGroupedOutputChangedFragment + >, + typeof Card +>({ id: 'TxOutputCoin', render: (_, { tx, output, ...props }) => { const classes = styles(); @@ -48,7 +60,7 @@ const TxOutputCoin = createComponent({ const assetId = output.assetId; const amount = output.totalAmount; const isReceiving = - output.type === GroupedOutputType.ChangeOutput || + output.__typename === 'GroupedOutputChanged' || (output.outputs?.length === 1 && output.outputs[0]?.__typename === 'CoinOutput'); @@ -90,30 +102,10 @@ const TxOutputCoin = createComponent({ }, }); -const TxOutputContract = createComponent({ - id: 'TxOutputContract', - render: (_, { output, ...props }) => { - const classes = styles(); - - return ( - - - - - - Contract Output - - Input Index: {output.inputIndex} - - - - - - ); - }, -}); - -const TxOutputContractCreated = createComponent({ +const TxOutputContractCreated = createComponent< + TxOutputProps, + typeof Card +>({ id: 'TxOutputContractCreated', render: (_, { output, ...props }) => { const classes = styles(); @@ -142,59 +134,24 @@ const TxOutputContractCreated = createComponent({ }, }); -const TxOutputMessage = createComponent({ - id: 'TxOutputMessage', - render: (_, { output, ...props }) => { - const classes = styles(); - const { recipient } = output; - - return ( - - - - - Message - -
-
- - - - - ); - }, -}); - export function TxOutput({ output, ...props }: TxOutputProps) { if ( - output.type === GroupedOutputType.CoinOutput || - output.type === GroupedOutputType.ChangeOutput + output.__typename === 'GroupedOutputCoin' || + output.__typename === 'GroupedOutputChanged' ) { return ; } - if (output.type === GroupedOutputType.ContractOutput) { - return ; - } - if (output.type === GroupedOutputType.ContractCreated) { - return ; - } - if (output.type === GroupedOutputType.MessageOutput) { - return ; - } + // @TODO: Indexer is not returning this grouped output + // if (output.type === GroupedOutputType.ContractOutput) { + // return ; + // } + + // @TODO: Indexer is not returning this grouped output + // if (output.type === GroupedOutputType.MessageOutput) { + // return ; + // } + + return ; } const styles = tv({ diff --git a/packages/app-explorer/src/systems/Transaction/component/TxScreen/TxScreenAdvanced.tsx b/packages/app-explorer/src/systems/Transaction/component/TxScreen/TxScreenAdvanced.tsx index b6d369b3b..061a3bfe9 100644 --- a/packages/app-explorer/src/systems/Transaction/component/TxScreen/TxScreenAdvanced.tsx +++ b/packages/app-explorer/src/systems/Transaction/component/TxScreen/TxScreenAdvanced.tsx @@ -1,12 +1,10 @@ 'use client'; -import type { Maybe } from '@fuel-explorer/graphql'; +import type { GQLTransactionDetailsFragment } from '@fuel-explorer/graphql'; import { CodeBlock } from '~/systems/Core/components/CodeBlock/CodeBlock'; -import type { TransactionNode } from '../../types'; - type TxScreenProps = { - transaction?: Maybe; + transaction?: GQLTransactionDetailsFragment; }; export function TxScreenAdvanced({ transaction: tx }: TxScreenProps) { diff --git a/packages/app-explorer/src/systems/Transaction/component/TxScreen/TxScreenSimple.tsx b/packages/app-explorer/src/systems/Transaction/component/TxScreen/TxScreenSimple.tsx index 46cfd2ff2..9243c1aa6 100644 --- a/packages/app-explorer/src/systems/Transaction/component/TxScreen/TxScreenSimple.tsx +++ b/packages/app-explorer/src/systems/Transaction/component/TxScreen/TxScreenSimple.tsx @@ -1,7 +1,6 @@ -/* eslint-disable @typescript-eslint/no-explicit-any */ 'use client'; -import type { GroupedInput, GroupedOutput } from '@fuel-explorer/graphql'; +import type { GQLTransactionDetailsFragment } from '@fuel-explorer/graphql'; import { Address, Badge, @@ -33,12 +32,12 @@ import { AssetItem } from '~/systems/Asset/components/AssetItem/AssetItem'; import { CardInfo } from '../../../Core/components/CardInfo/CardInfo'; import { TxInput } from '../../component/TxInput/TxInput'; import { TxOutput } from '../../component/TxOutput/TxOutput'; -import type { TransactionNode, TxStatus } from '../../types'; +import type { TxStatus } from '../../types'; import { TX_INTENT_MAP, TxIcon } from '../TxIcon/TxIcon'; import { TxScripts } from '../TxScripts/TxScripts'; type TxScreenProps = { - transaction: TransactionNode; + transaction: GQLTransactionDetailsFragment; isLoading?: boolean; }; @@ -58,24 +57,22 @@ export function TxScreenSimple({ transaction: tx, isLoading }: TxScreenProps) { } /> } - regularEl={title} - /> - ) as any + } + regularEl={title} + /> } > - {tx.isPredicate && ( + {tx.hasPredicate && ( Predicate @@ -98,7 +95,7 @@ export function TxScreenSimple({ transaction: tx, isLoading }: TxScreenProps) { , , (tx.blockHeight || isLoading) && ( - + } @@ -131,12 +128,14 @@ export function TxScreenSimple({ transaction: tx, isLoading }: TxScreenProps) { ), Gas used: {formatZeroUnits(tx.gasUsed || '')}} + regularEl={ + <>Gas used: {formatZeroUnits(tx.gasCosts?.gasUsed || '')} + } loadingEl={ <> @@ -149,7 +148,7 @@ export function TxScreenSimple({ transaction: tx, isLoading }: TxScreenProps) { } - regularEl={`${bn(tx.fee).format()} ETH`} + regularEl={`${bn(tx.gasCosts?.fee).format()} ETH`} /> , ]; @@ -166,7 +165,7 @@ function ContentMain({ tx, isLoading, }: { - tx: TransactionNode; + tx: GQLTransactionDetailsFragment; isLoading?: boolean; }) { const hasInputs = tx.groupedInputs?.length ?? 0 > 0; @@ -192,7 +191,7 @@ function ContentMain({ {tx.groupedInputs?.map((input, i) => ( // here we use only index as key because this component will not change - + ))} } @@ -237,7 +236,7 @@ function ContentMain({ // here we use only index as key because this component will not change key={i} tx={tx} - output={output as GroupedOutput} + output={output} /> ))} @@ -261,7 +260,7 @@ function MintOutputs({ tx, isLoading, }: { - tx: TransactionNode; + tx: GQLTransactionDetailsFragment; isLoading: boolean; }) { const classes = styles(); diff --git a/packages/app-explorer/src/systems/Transaction/component/TxScripts/TxScripts.tsx b/packages/app-explorer/src/systems/Transaction/component/TxScripts/TxScripts.tsx index a1ad25945..a5c3d2555 100644 --- a/packages/app-explorer/src/systems/Transaction/component/TxScripts/TxScripts.tsx +++ b/packages/app-explorer/src/systems/Transaction/component/TxScripts/TxScripts.tsx @@ -1,9 +1,10 @@ -import { ReceiptType } from '@fuel-explorer/graphql/src/sdk'; -import type { - Maybe, - OperationReceipt, - TransactionReceiptFragment, -} from '@fuel-explorer/graphql/src/sdk'; +import { + GQLReceiptType, + type GQLTransactionDetailsFragment, + type GQLTxDetailsOperationReceiptFragment, + type GQLTxDetailsReceiptItemFragment, + type Maybe, +} from '@fuel-explorer/graphql'; import type { BaseProps } from '@fuels/ui'; import { Address, @@ -31,7 +32,6 @@ import { import { bn } from 'fuels'; import NextLink from 'next/link'; import { createContext, useContext, useState } from 'react'; -/* eslint-disable @typescript-eslint/no-explicit-any */ import 'react-json-view-lite/dist/index.css'; import { useMeasure } from 'react-use'; import { tv } from 'tailwind-variants'; @@ -39,16 +39,15 @@ import { Amount } from '~/systems/Core/components/Amount/Amount'; import { EmptyCard } from '~/systems/Core/components/EmptyCard/EmptyCard'; import { JsonViewer } from '~/systems/Core/components/JsonViewer/JsonViewer'; -import type { TransactionNode } from '../../types'; - export type TxScriptsProps = BaseProps<{ - tx: TransactionNode; + tx: GQLTransactionDetailsFragment; isLoading?: boolean; }>; export function TxScripts({ tx, isLoading, ...props }: TxScriptsProps) { const [opened, setOpened] = useState(false); const hasOperations = tx.operations?.length ?? 0 > 0; + return ( >; }>; @@ -125,20 +124,21 @@ function ScriptsContent({ tx, opened, setOpened }: ScriptsContent) { const hasPanic = operations?.some((o) => o?.receipts?.some( (r) => - r?.item?.receiptType === ReceiptType.Panic || - r?.item?.receiptType === ReceiptType.Revert, + r?.item?.receiptType === GQLReceiptType.Panic || + r?.item?.receiptType === GQLReceiptType.Revert, ), ); if (!opened && receipts.length > 3) { return ( <> - +