diff --git a/.changeset/config.json b/.changeset/config.json index 83c584af40b..78276722d50 100644 --- a/.changeset/config.json +++ b/.changeset/config.json @@ -12,7 +12,6 @@ "iota-wallet", "iota-explorer", "wallet-dashboard", - "@iota/apps-ui-kit", "apps-backend", "@iota/core", "@iota/apps-ui-kit", diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index f9e3cf04ffa..8be2aa0d12b 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -15,7 +15,9 @@ /docker/ @iotaledger/l1-core-infra @iotaledger/core-node @iotaledger/devops-admin /crates/iota-json-rpc*/ @iotaledger/l1-core-infra /crates/iota-graphql*/ @iotaledger/l1-core-infra -/crates/iota-indexer/ @iotaledger/l1-core-infra +/crates/iota-indexer*/ @iotaledger/l1-core-infra +/crates/iota-data-ingestion*/ @iotaledger/l1-core-infra +/crates/iota-analytics-indexer/ @iotaledger/l1-core-infra # core-node team /crates/iota-archival/ @iotaledger/core-node @@ -75,6 +77,8 @@ vercel.json @iotaledger/boxfish @iotaledger/tooling # Scripts /scripts/dependency_graphs/ @muXxer +/scripts/cargo_sort/ @muXxer +/scripts/generate_files/ @muXxer /scripts/codesearch/ @muXxer /scripts/slipstream/ @muXxer diff --git a/.github/actions/diffs/action.yml b/.github/actions/diffs/action.yml index df411e36cb8..13e34f24df5 100644 --- a/.github/actions/diffs/action.yml +++ b/.github/actions/diffs/action.yml @@ -37,6 +37,7 @@ runs: - ".github/workflows/_rust_lints.yml" - ".github/workflows/_external_rust_tests.yml" - ".github/workflows/_cargo_deny.yml" + - "scripts/cargo_sort/cargo_sort.py" - "Cargo.toml" - "Cargo.lock" - ".config/nextest.toml" diff --git a/.github/workflows/_ledgernano.yml b/.github/workflows/_ledgernano.yml new file mode 100644 index 00000000000..0d9484caf47 --- /dev/null +++ b/.github/workflows/_ledgernano.yml @@ -0,0 +1,45 @@ +name: Ledgernano End-to-end Tests + +on: workflow_call + +concurrency: + group: ledgernano-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +jobs: + ledgernano: + name: Ledgernano + runs-on: self-hosted + steps: + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # Pin v4.1.1 + - uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # pin@v4.0.0 + + - name: Install Nodejs + uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # pin@v4.0.2 + with: + node-version: "20" + cache: "pnpm" + + - name: Install dependencies + run: pnpm install --frozen-lockfile + + - name: Install ledgernano dependencies + run: | + sudo apt-get install -y qemu-user-static + sudo apt-get install -y libxcb-xinerama0 + sudo pip install speculos --break-system-packages + + - name: Download ledgernano bin + run: | + sudo apt-get install -y gh + echo ${{ secrets.LEDGER_APP_TOKEN }} | gh auth login --with-token + gh release list --repo https://github.com/iotaledger/ledger-app-iota + gh release download --repo https://github.com/iotaledger/ledger-app-iota -p nanos.tar.gz untagged-a706a550379839d8db15 + tar -xvf nanos.tar.gz + mv nanos/iota sdk/ledgerjs-hw-app-iota/tests/iota + + - name: Start speculos simulator + run: speculos --api-port 5000 --display headless ./sdk/ledgerjs-hw-app-iota/tests/iota & + + - name: Run TS SDK ledgernano tests + run: pnpm --filter @iota/ledgerjs-hw-app-iota test diff --git a/.github/workflows/_rust_lints.yml b/.github/workflows/_rust_lints.yml index 5b6628cf44f..fb7e75eb51b 100644 --- a/.github/workflows/_rust_lints.yml +++ b/.github/workflows/_rust_lints.yml @@ -27,6 +27,24 @@ jobs: - name: Check Rust formatting run: cargo +nightly ci-fmt + cargo-sort: + if: (!cancelled() && inputs.isRust) + runs-on: [self-hosted] + steps: + - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # pin@v4 + - name: Check Cargo.toml format and sorting + run: | + pushd "scripts/cargo_sort" + ./run.sh --skip-dprint + popd + - name: Check Cargo.toml diffs after formatting + run: | + if git status --porcelain | grep -q "Cargo.toml"; then + echo "Cargo.toml files not formatted and/or sorted properly! Please run the 'scripts/cargo_sort/run.sh' script." + git diff # Show the actual diffs + exit 1 # Fail the workflow + fi + clippy: if: (!cancelled() && !failure() && inputs.isRust) needs: diff --git a/.github/workflows/_turborepo.yml b/.github/workflows/_turborepo.yml index a2a02a18ef9..f1de036a17c 100644 --- a/.github/workflows/_turborepo.yml +++ b/.github/workflows/_turborepo.yml @@ -52,12 +52,6 @@ jobs: - name: (debug-before) Check SDK dist folder continue-on-error: true run: tree ./sdk/typescript/dist - - name: (debug) Lint - continue-on-error: true - run: pnpm turbo lint - - name: (debug-after) Check SDK dist folder - continue-on-error: true - run: tree ./sdk/typescript/dist - name: Lint run: pnpm turbo lint - name: Install wasm-pack for mbf package @@ -73,7 +67,8 @@ jobs: - name: Build run: pnpm turbo build - name: Test - run: pnpm turbo test + # @iota/ledgerjs-hw-app-iota is tested separately + run: pnpm turbo test --filter '!@iota/ledgerjs-hw-app-iota' # Pack wallet extension and upload it as an artifact for easy developer use: - name: Wallet Extension Has Changes? id: wallet-diff diff --git a/.github/workflows/_vercel_deploy.yml b/.github/workflows/_vercel_deploy.yml new file mode 100644 index 00000000000..47f9d854598 --- /dev/null +++ b/.github/workflows/_vercel_deploy.yml @@ -0,0 +1,98 @@ +name: Vercel Deploys + +on: + workflow_call: + inputs: + isExplorer: + type: boolean + required: true + isTypescriptSDK: + type: boolean + required: true + isAppsBackend: + type: boolean + required: true + isAppsUiKit: + type: boolean + required: true + isWalletDashboard: + type: boolean + required: true + shouldDeployPreview: + type: boolean + required: true + isDevelop: + type: boolean + required: true + githubRef: + type: string + required: true + +concurrency: + group: ${{ github.workflow }}-${{ inputs.githubRef }} + cancel-in-progress: true + +jobs: + explorer-preview: + name: Vercel Explorer Preview + if: inputs.shouldDeployPreview && inputs.isExplorer + uses: ./.github/workflows/apps-explorer.deploy.yml + secrets: inherit + with: + isProd: false + + explorer-prod: + name: Vercel Explorer Production + if: inputs.isDevelop + uses: ./.github/workflows/apps-explorer.deploy.yml + secrets: inherit + with: + isProd: true + + ui-kit-preview: + name: Vercel UI Kit Preview + if: inputs.shouldDeployPreview && inputs.isAppsUiKit + uses: ./.github/workflows/apps-ui-kit.deploy.yml + secrets: inherit + with: + isProd: false + + ui-kit-prod: + name: Vercel UI Kit Preview + if: inputs.isDevelop + uses: ./.github/workflows/apps-ui-kit.deploy.yml + secrets: inherit + with: + isProd: true + + wallet-dashboard-preview: + name: Vercel Wallet Dashboard Preview + if: inputs.shouldDeployPreview && inputs.isWalletDashboard + uses: ./.github/workflows/apps-wallet-dashboard.deploy.yml + secrets: inherit + with: + isProd: false + + wallet-dashboard-prod: + name: Vercel Wallet Dashboard Production + if: inputs.isDevelop + uses: ./.github/workflows/apps-wallet-dashboard.deploy.yml + secrets: inherit + with: + isProd: true + + apps-backend-preview: + name: Vercel apps-backend Preview + if: inputs.shouldDeployPreview && inputs.isAppsBackend + uses: ./.github/workflows/apps-backend.deploy.yml + secrets: inherit + with: + isProd: false + + apps-backend-prod: + name: Vercel apps-backend Production + if: inputs.isDevelop + uses: ./.github/workflows/apps-backend.deploy.yml + secrets: inherit + with: + isProd: true diff --git a/.github/workflows/apps-backend-production.deploy.yml b/.github/workflows/apps-backend-production.deploy.yml deleted file mode 100644 index 2e014786e91..00000000000 --- a/.github/workflows/apps-backend-production.deploy.yml +++ /dev/null @@ -1,48 +0,0 @@ -name: Production Deploy for Apps Backend - -env: - VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }} - VERCEL_PROJECT_ID: ${{ secrets.APPS_BACKEND_VERCEL_PROJECT_ID }} - -on: - push: - branches: - - develop - paths: - - "apps/apps-backend/**" - - ".github/workflows/apps-backend-production.deploy.yml" - -jobs: - deploy-production: - permissions: - contents: read - pull-requests: write - runs-on: [self-hosted] - steps: - - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # pin@v4 - - uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # pin@v4 - - name: Install Nodejs - uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # pin@v4 - with: - node-version: "20" - cache: "pnpm" - - name: Install dependencies - run: pnpm install --frozen-lockfile - - name: Turbo Cache - id: turbo-cache - uses: actions/cache@3624ceb22c1c5a301c8db4169662070a689d9ea8 # pin@v4 - with: - path: node_modules/.cache/turbo - key: turbo-${{ runner.os }}-${{ github.sha }} - restore-keys: | - turbo-${{ runner.os }}- - - name: Install Vercel CLI - run: pnpm add --global vercel@canary - - name: Pull Vercel Prod Environment - run: vercel pull --yes --environment=production --token=${{ secrets.VERCEL_TOKEN }} - - name: Build the Apps Backend - run: pnpm apps-backend build - - name: Build Project Artifacts - run: vercel build --prod --token=${{ secrets.VERCEL_TOKEN }} - - name: Deploy Project Artifacts to Vercel - run: vercel deploy --prod --prebuilt --token=${{ secrets.VERCEL_TOKEN }} diff --git a/.github/workflows/apps-backend-preview.deploy.yml b/.github/workflows/apps-backend.deploy.yml similarity index 61% rename from .github/workflows/apps-backend-preview.deploy.yml rename to .github/workflows/apps-backend.deploy.yml index 7c3981195f4..38c919e73f5 100644 --- a/.github/workflows/apps-backend-preview.deploy.yml +++ b/.github/workflows/apps-backend.deploy.yml @@ -1,17 +1,19 @@ -name: Preview Deploy for Apps Backend +name: Deploy for Apps Backend env: VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }} VERCEL_PROJECT_ID: ${{ secrets.APPS_BACKEND_VERCEL_PROJECT_ID }} on: - pull_request: - paths: - - "apps/apps-backend/**" - - ".github/workflows/apps-backend-preview.deploy.yml" + workflow_dispatch: + workflow_call: + inputs: + isProd: + type: boolean + required: true jobs: - deploy-preview: + deploy: permissions: contents: read pull-requests: write @@ -26,6 +28,18 @@ jobs: cache: "pnpm" - name: Install dependencies run: pnpm install --frozen-lockfile + - name: Setup Prod Flag + id: setup_prod_flags + run: | + if [[ "${{ inputs.isProd }}" = "true" ]]; then + echo "PROD_FLAG=--prod" >> $GITHUB_OUTPUT + echo "ENVIRONMENT=production" >> $GITHUB_OUTPUT + echo "VERCEL_OUTPUT=" >> $GITHUB_OUTPUT + else + echo "PROD_FLAG=" >> $GITHUB_OUTPUT + echo "ENVIRONMENT=preview" >> $GITHUB_OUTPUT + echo "VERCEL_OUTPUT=> vercel_output.txt" >> $GITHUB_OUTPUT + fi - name: Turbo Cache id: turbo-cache uses: actions/cache@3624ceb22c1c5a301c8db4169662070a689d9ea8 # pin@v4 @@ -36,18 +50,20 @@ jobs: turbo-${{ runner.os }}- - name: Install Vercel CLI run: pnpm add --global vercel@canary + - name: Pull Vercel Env variables (network configs) + run: vercel pull --yes --environment=${{steps.setup_prod_flags.outputs.ENVIRONMENT}} --token=${{ secrets.VERCEL_TOKEN }} - name: Build the Apps Backend run: pnpm apps-backend build - - name: Pull Vercel Environment - run: vercel pull --yes --environment=preview --token=${{ secrets.VERCEL_TOKEN }} - - name: Build Project Artifacts - run: vercel build --token=${{ secrets.VERCEL_TOKEN }} + - name: Build Vercel Project Artifacts + run: vercel build ${{steps.setup_prod_flags.outputs.PROD_FLAG}} --token=${{ secrets.VERCEL_TOKEN }} - name: Deploy Project Artifacts to Vercel - run: vercel deploy --prebuilt --token=${{ secrets.VERCEL_TOKEN }} > vercel_output.txt + run: vercel deploy ${{steps.setup_prod_flags.outputs.PROD_FLAG}} --prebuilt --token=${{ secrets.VERCEL_TOKEN }} ${{ steps.setup_prod_flags.outputs.VERCEL_OUTPUT }} - name: Extract Deploy URL id: deploy_url + if: ${{ inputs.isProd == false }} run: echo "DEPLOY_URL=$(cat vercel_output.txt | awk 'END{print}')" >> $GITHUB_OUTPUT - name: Comment on pull request + if: ${{ inputs.isProd == false }} uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # pin@v7 with: github-token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/apps-explorer-production.deploy.yml b/.github/workflows/apps-explorer-production.deploy.yml deleted file mode 100644 index 41bd81f1595..00000000000 --- a/.github/workflows/apps-explorer-production.deploy.yml +++ /dev/null @@ -1,50 +0,0 @@ -name: Deploy Explorer Prod - -env: - VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }} - VERCEL_PROJECT_ID: ${{ secrets.EXPLORER_VERCEL_PROJECT_ID }} - -on: - push: - branches: - - develop - paths: - - "apps/explorer/**" - - ".github/workflows/apps-explorer-production.deploy.yml" - -jobs: - deploy-production: - permissions: - contents: read - pull-requests: write - runs-on: [self-hosted] - steps: - - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # pin@v4 - - uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # pin@v4 - - name: Install Nodejs - uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # pin@v4 - with: - node-version: "20" - cache: "pnpm" - - name: Install dependencies - run: pnpm install --frozen-lockfile - - name: Turbo Cache - id: turbo-cache - uses: actions/cache@3624ceb22c1c5a301c8db4169662070a689d9ea8 # pin@v4 - with: - path: node_modules/.cache/turbo - key: turbo-${{ runner.os }}-${{ github.sha }} - restore-keys: | - turbo-${{ runner.os }}- - - name: Install Vercel CLI - run: pnpm add --global vercel@canary - - name: Pull Vercel Env variables (network configs) - run: vercel pull --yes --environment=production --token=${{ secrets.VERCEL_TOKEN }} - - name: Copy the .env file - run: cp ./.vercel/.env.production.local ./sdk/.env - - name: Build Explorer - run: pnpm explorer build - - name: Build Project Artifacts - run: vercel build --prod --token=${{ secrets.VERCEL_TOKEN }} - - name: Deploy Project Artifacts to Vercel - run: vercel deploy --prod --prebuilt --token=${{ secrets.VERCEL_TOKEN }} diff --git a/.github/workflows/apps-explorer-preview.deploy.yml b/.github/workflows/apps-explorer.deploy.yml similarity index 62% rename from .github/workflows/apps-explorer-preview.deploy.yml rename to .github/workflows/apps-explorer.deploy.yml index b4b70604832..fe482d68102 100644 --- a/.github/workflows/apps-explorer-preview.deploy.yml +++ b/.github/workflows/apps-explorer.deploy.yml @@ -1,4 +1,4 @@ -name: Preview Deploy for Explorer +name: Deploy for Explorer env: VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }} @@ -6,19 +6,14 @@ env: on: workflow_dispatch: - pull_request: - types: [opened, synchronize, reopened, ready_for_review] - paths: - - "apps/explorer/**" - - ".github/workflows/apps-explorer-preview.deploy.yml" - -concurrency: - group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} - cancel-in-progress: true + workflow_call: + inputs: + isProd: + type: boolean + required: true jobs: - deploy-preview: - if: github.event.pull_request.draft == false + deploy: permissions: contents: read pull-requests: write @@ -33,6 +28,18 @@ jobs: cache: "pnpm" - name: Install dependencies run: pnpm install --frozen-lockfile + - name: Setup Prod Flag + id: setup_prod_flags + run: | + if [[ "${{ inputs.isProd }}" = "true" ]]; then + echo "PROD_FLAG=--prod" >> $GITHUB_OUTPUT + echo "ENVIRONMENT=production" >> $GITHUB_OUTPUT + echo "VERCEL_OUTPUT=" >> $GITHUB_OUTPUT + else + echo "PROD_FLAG=" >> $GITHUB_OUTPUT + echo "ENVIRONMENT=preview" >> $GITHUB_OUTPUT + echo "VERCEL_OUTPUT=> vercel_output.txt" >> $GITHUB_OUTPUT + fi - name: Turbo Cache id: turbo-cache uses: actions/cache@3624ceb22c1c5a301c8db4169662070a689d9ea8 # pin@v4 @@ -44,21 +51,22 @@ jobs: - name: Install Vercel CLI run: pnpm add --global vercel@canary - name: Pull Vercel Env variables (network configs) - run: vercel pull --yes --environment=preview --token=${{ secrets.VERCEL_TOKEN }} + run: vercel pull --yes --environment=${{steps.setup_prod_flags.outputs.ENVIRONMENT}} --token=${{ secrets.VERCEL_TOKEN }} - name: Copy the .env file - run: cp ./.vercel/.env.preview.local ./sdk/.env + run: cp ./.vercel/.env.${{steps.setup_prod_flags.outputs.ENVIRONMENT}}.local ./sdk/.env - name: Build Explorer run: pnpm explorer build - - name: Build Project Artifacts - run: vercel build --token=${{ secrets.VERCEL_TOKEN }} + - name: Build Vercel Project Artifacts + run: vercel build ${{steps.setup_prod_flags.outputs.PROD_FLAG}} --token=${{ secrets.VERCEL_TOKEN }} - name: Deploy Project Artifacts to Vercel - run: vercel deploy --prebuilt --token=${{ secrets.VERCEL_TOKEN }} > vercel_output.txt + run: vercel deploy ${{steps.setup_prod_flags.outputs.PROD_FLAG}} --prebuilt --token=${{ secrets.VERCEL_TOKEN }} ${{ steps.setup_prod_flags.outputs.VERCEL_OUTPUT }} - name: Extract Deploy URL id: deploy_url + if: ${{ inputs.isProd == false }} run: echo "DEPLOY_URL=$(cat vercel_output.txt | awk 'END{print}')" >> $GITHUB_OUTPUT - name: Comment on pull request + if: ${{ inputs.isProd == false }} uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # pin@v7 - if: github.event_name == 'pull_request' with: github-token: ${{ secrets.GITHUB_TOKEN }} script: | diff --git a/.github/workflows/apps-ui-kit-production.deploy.yml b/.github/workflows/apps-ui-kit-production.deploy.yml deleted file mode 100644 index 6e300bafee2..00000000000 --- a/.github/workflows/apps-ui-kit-production.deploy.yml +++ /dev/null @@ -1,37 +0,0 @@ -name: Production Deploy for Apps UI Kit Storybook - -env: - VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }} - VERCEL_PROJECT_ID: ${{ secrets.APPS_UI_KIT_VERCEL_PROJECT_ID }} - -on: - push: - branches: - - develop - paths: - - "apps/ui-kit/**" - - "apps/ui-icons/**" - - ".github/workflows/apps-ui-kit-production.deploy.yml" - -jobs: - deploy-production: - permissions: - contents: read - pull-requests: write - runs-on: [self-hosted] - steps: - - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # pin@v4 - - uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # pin@v4 - - name: Install Nodejs - uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # pin@v4 - with: - node-version: "20" - cache: "pnpm" - - name: Install Vercel CLI - run: pnpm add --global vercel@canary - - name: Pull Vercel Environment Information - run: vercel pull --cwd ./apps/ui-kit --yes --environment=production --token=${{ secrets.VERCEL_TOKEN }} - - name: Build Project Artifacts - run: vercel build --prod --cwd ./apps/ui-kit --token=${{ secrets.VERCEL_TOKEN }} - - name: Deploy Project Artifacts to Vercel - run: vercel deploy --cwd ./apps/ui-kit --prod --prebuilt --token=${{ secrets.VERCEL_TOKEN }} diff --git a/.github/workflows/apps-ui-kit-preview.deploy.yml b/.github/workflows/apps-ui-kit.deploy.yml similarity index 58% rename from .github/workflows/apps-ui-kit-preview.deploy.yml rename to .github/workflows/apps-ui-kit.deploy.yml index fb76af6f4fb..bbb003fb875 100644 --- a/.github/workflows/apps-ui-kit-preview.deploy.yml +++ b/.github/workflows/apps-ui-kit.deploy.yml @@ -1,4 +1,4 @@ -name: Preview Deploy for Apps UI Kit Storybook +name: Deploy for Apps UI Kit Storybook env: VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }} @@ -6,20 +6,14 @@ env: on: workflow_dispatch: - pull_request: - types: [opened, synchronize, reopened, ready_for_review] - paths: - - "apps/ui-kit/**" - - "apps/ui-icons/**" - - ".github/workflows/apps-ui-kit-preview.deploy.yml" - -concurrency: - group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} - cancel-in-progress: true + workflow_call: + inputs: + isProd: + type: boolean + required: true jobs: - deploy-preview: - if: github.event.pull_request.draft == false + deploy: permissions: contents: read pull-requests: write @@ -32,20 +26,35 @@ jobs: with: node-version: "20" cache: "pnpm" + - name: Install dependencies + run: pnpm install --frozen-lockfile + - name: Setup Prod Flag + id: setup_prod_flags + run: | + if [[ "${{ inputs.isProd }}" = "true" ]]; then + echo "PROD_FLAG=--prod" >> $GITHUB_OUTPUT + echo "ENVIRONMENT=production" >> $GITHUB_OUTPUT + echo "VERCEL_OUTPUT=" >> $GITHUB_OUTPUT + else + echo "PROD_FLAG=" >> $GITHUB_OUTPUT + echo "ENVIRONMENT=preview" >> $GITHUB_OUTPUT + echo "VERCEL_OUTPUT=> vercel_output.txt" >> $GITHUB_OUTPUT + fi - name: Install Vercel CLI run: pnpm add --global vercel@canary - name: Pull Vercel Environment Information - run: vercel pull --cwd ./apps/ui-kit --yes --environment=preview --token=${{ secrets.VERCEL_TOKEN }} + run: vercel pull --cwd ./apps/ui-kit --yes --environment=${{steps.setup_prod_flags.outputs.ENVIRONMENT}} --token=${{ secrets.VERCEL_TOKEN }} - name: Build Project Artifacts - run: vercel build --cwd ./apps/ui-kit --token=${{ secrets.VERCEL_TOKEN }} + run: vercel build ${{steps.setup_prod_flags.outputs.PROD_FLAG}} --cwd ./apps/ui-kit --token=${{ secrets.VERCEL_TOKEN }} - name: Deploy Project Artifacts to Vercel - run: vercel deploy --cwd ./apps/ui-kit --prebuilt --token=${{ secrets.VERCEL_TOKEN }} > vercel_output.txt + run: vercel deploy --cwd ./apps/ui-kit ${{steps.setup_prod_flags.outputs.PROD_FLAG}} --prebuilt --token=${{ secrets.VERCEL_TOKEN }} ${{ steps.setup_prod_flags.outputs.VERCEL_OUTPUT }} - name: Extract Deploy URL id: deploy_url + if: ${{ inputs.isProd == false }} run: echo "DEPLOY_URL=$(cat vercel_output.txt | awk 'END{print}')" >> $GITHUB_OUTPUT - name: Comment on pull request + if: ${{ inputs.isProd == false }} uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # pin@v7 - if: github.event_name == 'pull_request' with: github-token: ${{ secrets.GITHUB_TOKEN }} script: | diff --git a/.github/workflows/apps-wallet-dashboard-production.deploy.yml b/.github/workflows/apps-wallet-dashboard-production.deploy.yml deleted file mode 100644 index 411aac1f7ef..00000000000 --- a/.github/workflows/apps-wallet-dashboard-production.deploy.yml +++ /dev/null @@ -1,50 +0,0 @@ -name: Production Deploy for Wallet Dashboard - -env: - VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }} - VERCEL_PROJECT_ID: ${{ secrets.WALLET_DASHBOARD_VERCEL_PROJECT_ID }} - -on: - push: - branches: - - develop - paths: - - "apps/wallet-dashboard/**" - - ".github/workflows/apps-wallet-dashboard-production.deploy.yml" - -jobs: - deploy-production: - permissions: - contents: read - pull-requests: write - runs-on: [self-hosted] - steps: - - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # pin@v4 - - uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # pin@v4 - - name: Install Nodejs - uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # pin@v4 - with: - node-version: "20" - cache: "pnpm" - - name: Install dependencies - run: pnpm install --frozen-lockfile - - name: Turbo Cache - id: turbo-cache - uses: actions/cache@3624ceb22c1c5a301c8db4169662070a689d9ea8 # pin@v4 - with: - path: node_modules/.cache/turbo - key: turbo-${{ runner.os }}-${{ github.sha }} - restore-keys: | - turbo-${{ runner.os }}- - - name: Install Vercel CLI - run: pnpm add --global vercel@canary - - name: Pull Vercel Env variables (network configs) - run: vercel pull --yes --environment=production --token=${{ secrets.VERCEL_TOKEN }} - - name: Copy the .env file - run: cp ./.vercel/.env.production.local ./sdk/.env - - name: Build Wallet Dashboard Local - run: pnpm wallet-dashboard build - - name: Build Vercel Project Artifacts - run: vercel build --prod --token=${{ secrets.VERCEL_TOKEN }} - - name: Deploy Project Artifacts to Vercel - run: vercel deploy --prod --prebuilt --token=${{ secrets.VERCEL_TOKEN }} diff --git a/.github/workflows/apps-wallet-dashboard-preview.deploy.yml b/.github/workflows/apps-wallet-dashboard.deploy.yml similarity index 62% rename from .github/workflows/apps-wallet-dashboard-preview.deploy.yml rename to .github/workflows/apps-wallet-dashboard.deploy.yml index e7d6b8f0041..97bd8ae6670 100644 --- a/.github/workflows/apps-wallet-dashboard-preview.deploy.yml +++ b/.github/workflows/apps-wallet-dashboard.deploy.yml @@ -1,4 +1,4 @@ -name: Preview Deploy for Wallet Dashboard +name: Deploy for Wallet Dashboard env: VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }} @@ -6,19 +6,14 @@ env: on: workflow_dispatch: - pull_request: - types: [opened, synchronize, reopened, ready_for_review] - paths: - - "apps/wallet-dashboard/**" - - ".github/workflows/apps-wallet-dashboard-preview.deploy.yml" - -concurrency: - group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} - cancel-in-progress: true + workflow_call: + inputs: + isProd: + type: boolean + required: true jobs: - deploy-preview: - if: github.event.pull_request.draft == false + deploy: permissions: contents: read pull-requests: write @@ -33,6 +28,18 @@ jobs: cache: "pnpm" - name: Install dependencies run: pnpm install --frozen-lockfile + - name: Setup Prod Flag + id: setup_prod_flags + run: | + if [[ "${{ inputs.isProd }}" = "true" ]]; then + echo "PROD_FLAG=--prod" >> $GITHUB_OUTPUT + echo "ENVIRONMENT=production" >> $GITHUB_OUTPUT + echo "VERCEL_OUTPUT=" >> $GITHUB_OUTPUT + else + echo "PROD_FLAG=" >> $GITHUB_OUTPUT + echo "ENVIRONMENT=preview" >> $GITHUB_OUTPUT + echo "VERCEL_OUTPUT=> vercel_output.txt" >> $GITHUB_OUTPUT + fi - name: Turbo Cache id: turbo-cache uses: actions/cache@3624ceb22c1c5a301c8db4169662070a689d9ea8 # pin@v4 @@ -44,21 +51,22 @@ jobs: - name: Install Vercel CLI run: pnpm add --global vercel@canary - name: Pull Vercel Env variables (network configs) - run: vercel pull --yes --environment=preview --token=${{ secrets.VERCEL_TOKEN }} + run: vercel pull --yes --environment=${{steps.setup_prod_flags.outputs.ENVIRONMENT}} --token=${{ secrets.VERCEL_TOKEN }} - name: Copy the .env file - run: cp ./.vercel/.env.preview.local ./sdk/.env + run: cp ./.vercel/.env.${{steps.setup_prod_flags.outputs.ENVIRONMENT}}.local ./sdk/.env - name: Build Wallet Dashboard run: pnpm wallet-dashboard build - - name: Build Project Artifacts - run: vercel build --token=${{ secrets.VERCEL_TOKEN }} + - name: Build Vercel Project Artifacts + run: vercel build ${{steps.setup_prod_flags.outputs.PROD_FLAG}} --token=${{ secrets.VERCEL_TOKEN }} - name: Deploy Project Artifacts to Vercel - run: vercel deploy --prebuilt --token=${{ secrets.VERCEL_TOKEN }} > vercel_output.txt + run: vercel deploy ${{steps.setup_prod_flags.outputs.PROD_FLAG}} --prebuilt --token=${{ secrets.VERCEL_TOKEN }} ${{ steps.setup_prod_flags.outputs.VERCEL_OUTPUT }} - name: Extract Deploy URL id: deploy_url + if: ${{ inputs.isProd == false }} run: echo "DEPLOY_URL=$(cat vercel_output.txt | awk 'END{print}')" >> $GITHUB_OUTPUT - name: Comment on pull request + if: ${{ inputs.isProd == false }} uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # pin@v7 - if: github.event_name == 'pull_request' with: github-token: ${{ secrets.GITHUB_TOKEN }} script: | diff --git a/.github/workflows/hierarchy.yml b/.github/workflows/hierarchy.yml index f028b93b236..47d92c4ce92 100644 --- a/.github/workflows/hierarchy.yml +++ b/.github/workflows/hierarchy.yml @@ -25,7 +25,11 @@ jobs: isWallet: ${{ (steps.turbo.outputs.packages && contains(fromJson(steps.turbo.outputs.packages), 'iota-wallet')) }} isExplorer: ${{ (steps.turbo.outputs.packages && contains(fromJson(steps.turbo.outputs.packages), 'iota-explorer')) }} isTypescriptSDK: ${{ (steps.turbo.outputs.packages && contains(fromJson(steps.turbo.outputs.packages), '@iota/iota-sdk')) }} + isAppsBackend: ${{ (steps.turbo.outputs.packages && contains(fromJson(steps.turbo.outputs.packages), 'apps-backend')) }} + isAppsUiKit: ${{ (steps.turbo.outputs.packages && contains(fromJson(steps.turbo.outputs.packages), '@iota/apps-ui-kit')) }} + isWalletDashboard: ${{ (steps.turbo.outputs.packages && contains(fromJson(steps.turbo.outputs.packages), 'wallet-dashboard')) }} isGraphQlTransport: ${{ (steps.turbo.outputs.packages && contains(fromJson(steps.turbo.outputs.packages), '@iota/graphql-transport')) }} + isLedgerjs: ${{ (steps.turbo.outputs.packages && contains(fromJson(steps.turbo.outputs.packages), '@iota/ledgerjs-hw-app-iota')) }} steps: - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # pin@v4 - name: Detect Changes (turbo) @@ -144,3 +148,32 @@ jobs: isTypescriptSDK: ${{ needs.diff.outputs.isTypescriptSDK == 'true' }} isGraphQlTransport: ${{ needs.diff.outputs.isGraphQlTransport == 'true' }} isDevelop: ${{ github.ref_name == 'develop' }} + + vercel-deploy: + if: (!cancelled() && !failure()) + needs: + - diff + - dprint-format + - license-check + - typos + uses: ./.github/workflows/_vercel_deploy.yml + secrets: inherit + with: + shouldDeployPreview: ${{github.event_name == 'pull_request' && github.event.pull_request.draft == false}} + isExplorer: ${{ needs.diff.outputs.isExplorer == 'true' }} + isTypescriptSDK: ${{ needs.diff.outputs.isTypescriptSDK == 'true' }} + isAppsBackend: ${{ needs.diff.outputs.isAppsBackend == 'true' }} + isAppsUiKit: ${{ needs.diff.outputs.isAppsUiKit == 'true' }} + isWalletDashboard: ${{ needs.diff.outputs.isWalletDashboard == 'true' }} + isDevelop: ${{ github.ref_name == 'develop' }} + githubRef: ${{ github.event.pull_request.number || github.ref }} + + ledgernano: + if: (!cancelled() && !failure()) && needs.diff.outputs.isLedgerjs == 'true' && github.event.pull_request.draft == false + needs: + - diff + - dprint-format + - license-check + - typos + uses: ./.github/workflows/_ledgernano.yml + secrets: inherit diff --git a/Cargo.toml b/Cargo.toml index 6fd5380358f..141904a44f1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,5 @@ [workspace] resolver = "2" - exclude = [ "external-crates/move/crates/bytecode-interpreter-crypto", "external-crates/move/crates/bytecode-verifier-libfuzzer", @@ -61,7 +60,6 @@ exclude = [ "external-crates/move/move-execution/v0/crates/move-vm-runtime", "sdk/move-bytecode-template", ] - members = [ "consensus/config", "consensus/core", diff --git a/apps/apps-backend/src/restricted/restricted.controller.ts b/apps/apps-backend/src/restricted/restricted.controller.ts index 03f77358e06..4ba61ddd045 100644 --- a/apps/apps-backend/src/restricted/restricted.controller.ts +++ b/apps/apps-backend/src/restricted/restricted.controller.ts @@ -9,7 +9,7 @@ export class RestrictedController { @Post('/') @Header('Cache-Control', 'max-age=0, must-revalidate') checkRestrictions(@Res() res: Response) { - // No restrictions implemented yet + // No restrictions implemented yet. res.status(HttpStatus.OK).send(); } } diff --git a/apps/explorer/README.md b/apps/explorer/README.md index 0da36c73bf5..db68127e02e 100644 --- a/apps/explorer/README.md +++ b/apps/explorer/README.md @@ -1,6 +1,6 @@ # IOTA Explorer -[IOTA Explorer](https://explorer.iota.io/) is a network explorer for the IOTA network, similar in functionality to [Etherscan](https://etherscan.io/) or [Solana Explorer](https://explorer.solana.com/). Use IOTA Explorer to see the latest transactions and objects. +[IOTA Explorer](https://explorer.iota.org/) is a network explorer for the IOTA network, similar in functionality to [Etherscan](https://etherscan.io/) or [Solana Explorer](https://explorer.solana.com/). Use IOTA Explorer to see the latest transactions and objects. # Set Up diff --git a/apps/explorer/src/components/IotaTokenCard.tsx b/apps/explorer/src/components/IotaTokenCard.tsx index 7b40e74a859..05720a0bd28 100644 --- a/apps/explorer/src/components/IotaTokenCard.tsx +++ b/apps/explorer/src/components/IotaTokenCard.tsx @@ -2,9 +2,10 @@ // Modifications Copyright (c) 2024 IOTA Stiftung // SPDX-License-Identifier: Apache-2.0 +import { Panel } from '@iota/apps-ui-kit'; import { COIN_GECKO_IOTA_URL, useIotaCoinData } from '@iota/core'; import { IotaLogoMark } from '@iota/ui-icons'; -import { ButtonOrLink, Card } from '~/components/ui'; +import { ButtonOrLink } from '~/components/ui'; export function IotaTokenCard(): JSX.Element { const { data } = useIotaCoinData(); @@ -19,12 +20,12 @@ export function IotaTokenCard(): JSX.Element { return ( - -
+ +
-
+
1 IOTA = {formattedPrice} @@ -33,7 +34,7 @@ export function IotaTokenCard(): JSX.Element {
- + ); } diff --git a/apps/explorer/src/components/home-metrics/OnTheNetwork.tsx b/apps/explorer/src/components/home-metrics/OnTheNetwork.tsx index 703c712550c..d98dc4b126f 100644 --- a/apps/explorer/src/components/home-metrics/OnTheNetwork.tsx +++ b/apps/explorer/src/components/home-metrics/OnTheNetwork.tsx @@ -100,8 +100,7 @@ export function OnTheNetwork(): JSX.Element { text={gasPriceFormatted ?? '-'} supportingLabel={gasPriceFormatted !== null ? 'IOTA' : undefined} tooltipPosition={TooltipPosition.Top} - tooltipText=" -The reference gas price in the current epoch." + tooltipText="The reference gas price in the current epoch." />
diff --git a/apps/explorer/src/components/layout/PageLayout.tsx b/apps/explorer/src/components/layout/PageLayout.tsx index dcd7ca952c8..9602bad3c85 100644 --- a/apps/explorer/src/components/layout/PageLayout.tsx +++ b/apps/explorer/src/components/layout/PageLayout.tsx @@ -29,7 +29,7 @@ export function PageLayout({ content, loading }: PageLayoutProps): JSX.Element { request<{ degraded: boolean }>('monitor-network', { project: 'EXPLORER', }), - // Keep cached for 2 minutes: + // Keep cached for 2 minutes staleTime: 2 * 60 * 1000, retry: false, enabled: network === Network.Mainnet, diff --git a/apps/explorer/src/components/ui/Card.tsx b/apps/explorer/src/components/ui/Card.tsx deleted file mode 100644 index f2d5746b5a1..00000000000 --- a/apps/explorer/src/components/ui/Card.tsx +++ /dev/null @@ -1,84 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// Modifications Copyright (c) 2024 IOTA Stiftung -// SPDX-License-Identifier: Apache-2.0 - -import { cva, type VariantProps } from 'class-variance-authority'; -import { type ReactNode } from 'react'; - -const cardStyles = cva('overflow-hidden', { - variants: { - bg: { - default: 'bg-gray-40', - highlight: 'bg-success-light', - lightBlue: 'bg-iota/10', - white: 'bg-white', - 'white/80': 'bg-white/80', - }, - height: { - full: 'h-full', - }, - width: { - full: 'w-full', - }, - rounded: { - lg: 'rounded-lg', - xl: 'rounded-xl', - '2xl': 'rounded-2xl', - }, - spacing: { - none: '', - sm: 'px-5 py-4', - md: 'p-5', - lg: 'p-6', - lgGraph: 'p-6 pb-4', - }, - border: { - gray45: 'border border-gray-45', - steel: 'border border-steel', - }, - shadow: { - true: 'shadow-md', - }, - growOnHover: { - true: 'hover:scale-101 ease-in-out duration-200', - }, - }, - defaultVariants: { - bg: 'default', - spacing: 'md', - rounded: 'xl', - }, -}); - -export interface CardProps extends VariantProps { - children?: ReactNode; -} - -export function Card({ - spacing, - rounded, - bg, - border, - shadow, - children, - height, - width, - growOnHover, -}: CardProps): JSX.Element { - return ( -
- {children} -
- ); -} diff --git a/apps/explorer/src/components/ui/Tooltip.tsx b/apps/explorer/src/components/ui/Tooltip.tsx deleted file mode 100644 index 5eb6cc61e26..00000000000 --- a/apps/explorer/src/components/ui/Tooltip.tsx +++ /dev/null @@ -1,155 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// Modifications Copyright (c) 2024 IOTA Stiftung -// SPDX-License-Identifier: Apache-2.0 - -import { - useFloating, - autoUpdate, - offset, - flip, - shift, - useHover, - useFocus, - useDismiss, - useRole, - useInteractions, - FloatingPortal, - arrow, -} from '@floating-ui/react'; -import { AnimatePresence, motion } from 'framer-motion'; -import { useRef, useState } from 'react'; -import type { Placement } from '@floating-ui/react'; -import type { ReactNode, CSSProperties } from 'react'; -import { Info } from '@iota/ui-icons'; - -const TOOLTIP_DELAY = 150; - -interface TooltipProps { - tip: ReactNode; - children: ReactNode; - onOpen?: () => void; - placement?: Placement; -} - -export function Tooltip({ tip, children, onOpen, placement = 'top' }: TooltipProps): JSX.Element { - const [open, setOpen] = useState(false); - const arrowRef = useRef(null); - - const { - x, - y, - refs, - strategy, - context, - middlewareData, - placement: finalPlacement, - } = useFloating({ - placement, - open, - onOpenChange: (updatedIsOpen) => { - if (open !== updatedIsOpen && updatedIsOpen && onOpen) { - onOpen(); - } - setOpen(updatedIsOpen); - }, - whileElementsMounted: autoUpdate, - middleware: [offset(5), flip(), shift(), arrow({ element: arrowRef, padding: 6 })], - }); - - const { getReferenceProps, getFloatingProps } = useInteractions([ - useHover(context, { move: true, delay: TOOLTIP_DELAY }), - useFocus(context), - useRole(context, { role: 'tooltip' }), - useDismiss(context), - ]); - - const animateProperty = - finalPlacement.startsWith('top') || finalPlacement.startsWith('bottom') ? 'y' : 'x'; - - const animateValue = - finalPlacement.startsWith('bottom') || finalPlacement.startsWith('right') - ? 'calc(-50% - 15px)' - : 'calc(50% + 15px)'; - - const arrowStyle: CSSProperties = { - left: middlewareData.arrow?.x, - top: middlewareData.arrow?.y, - }; - - const staticSide = ( - { - top: 'bottom', - right: 'left', - bottom: 'top', - left: 'right', - } as const - )[finalPlacement.split('-')[0]]; - - if (staticSide) { - arrowStyle[staticSide] = '-3px'; - } - - return ( - <> -
- {children} -
- - - {open ? ( - -
- {tip} -
-
- - ) : null} - - - - ); -} - -export type IconTooltipProps = Omit; - -export function IconTooltip(props: IconTooltipProps) { - return ( - - - - ); -} diff --git a/apps/explorer/src/components/ui/index.ts b/apps/explorer/src/components/ui/index.ts index 8db90fc04a6..6cf3f4c845d 100644 --- a/apps/explorer/src/components/ui/index.ts +++ b/apps/explorer/src/components/ui/index.ts @@ -7,7 +7,6 @@ export * from './image'; export * from './modal'; export * from './ButtonOrLink'; -export * from './Card'; export * from './ExpandableList'; export * from './FilterList'; export * from './ImageIcon'; @@ -24,5 +23,4 @@ export * from './ProgressCircle'; export * from './RingChart'; export * from './SplitPanes'; export * from './TableCard'; -export * from './Tooltip'; export * from './VerticalList'; diff --git a/apps/explorer/src/lib/utils/sentry.ts b/apps/explorer/src/lib/utils/sentry.ts index c9456beeb7c..95320908fca 100644 --- a/apps/explorer/src/lib/utils/sentry.ts +++ b/apps/explorer/src/lib/utils/sentry.ts @@ -57,7 +57,7 @@ export function initSentry() { //, ], allowUrls: [ - /.*\.iota\.io/i, + /.*\.iota\.org/i, /.*-iota-foundation\.vercel\.app/i, 'explorer-topaz.vercel.app', ], diff --git a/apps/explorer/tailwind.config.ts b/apps/explorer/tailwind.config.ts index 224711dc95e..5532fa8c156 100644 --- a/apps/explorer/tailwind.config.ts +++ b/apps/explorer/tailwind.config.ts @@ -5,11 +5,12 @@ import preset from '@iota/core/tailwind.config'; import colors from 'tailwindcss/colors'; import { type Config } from 'tailwindcss'; -import { uiKitResponsivePreset } from '@iota/apps-ui-kit'; +// Note: exception for the tailwind preset import +import uiKitResponsivePreset from '../../apps/ui-kit/src/lib/tailwind/responsive.preset'; export default { presets: [preset, uiKitResponsivePreset], - content: ['./src/**/*.{js,jsx,ts,tsx}', './node_modules/@iota/apps-ui-kit/dist/**/*.js'], + content: ['./src/**/*.{js,jsx,ts,tsx}', './../ui-kit/src/lib/**/*.{js,jsx,ts,tsx}'], theme: { // This COLOR are duplicated from @iota/core tailwind.config.ts!!! // They are repeated here cause uiKitResponsivePreset overwrites the colors, and they are still used throughout Explorer diff --git a/apps/explorer/tsconfig.json b/apps/explorer/tsconfig.json index bea45c24203..623178a72a9 100644 --- a/apps/explorer/tsconfig.json +++ b/apps/explorer/tsconfig.json @@ -24,6 +24,7 @@ "references": [ { "path": "../../sdk/typescript/" }, { "path": "../../sdk/kiosk/" }, - { "path": "../../sdk/dapp-kit/" } + { "path": "../../sdk/dapp-kit/" }, + { "path": "../ui-kit" } ] } diff --git a/apps/ui-kit/src/lib/components/atoms/divider/Divider.tsx b/apps/ui-kit/src/lib/components/atoms/divider/Divider.tsx index afdae876ae3..a9391cfe151 100644 --- a/apps/ui-kit/src/lib/components/atoms/divider/Divider.tsx +++ b/apps/ui-kit/src/lib/components/atoms/divider/Divider.tsx @@ -33,7 +33,7 @@ export function Divider({ height, lineHeight = DEFAULT_LINE_HEIGHT, }: DividerProps): React.JSX.Element { - // Set width and height of divider line based on type + // Set height and width of divider line based on type const lineStyle = { ...(type === DividerType.Horizontal ? { height: lineHeight } : { width: lineHeight }), }; diff --git a/apps/ui-kit/tsconfig.base.json b/apps/ui-kit/tsconfig.base.json index 76fac5f8526..187384cd91e 100644 --- a/apps/ui-kit/tsconfig.base.json +++ b/apps/ui-kit/tsconfig.base.json @@ -10,10 +10,14 @@ "noFallthroughCasesInSwitch": true, "moduleResolution": "node", "resolveJsonModule": true, - "noEmit": true, "isolatedModules": true, "sourceMap": true, "jsx": "react-jsx", + "composite": true, + "declaration": true, + "declarationMap": true, + "outDir": "dist", + "emitDeclarationOnly": true, "paths": { "@/*": ["./src/*"], "@/components": ["./src/lib/components"], diff --git a/apps/wallet-dashboard/app/dashboard/layout.tsx b/apps/wallet-dashboard/app/dashboard/layout.tsx index ac56873f2b4..69c6a6da46a 100644 --- a/apps/wallet-dashboard/app/dashboard/layout.tsx +++ b/apps/wallet-dashboard/app/dashboard/layout.tsx @@ -2,9 +2,10 @@ // SPDX-License-Identifier: Apache-2.0 'use client'; -import { Button, Notifications, RouteLink } from '@/components/index'; +import { Notifications, RouteLink } from '@/components/index'; import React, { useState, type PropsWithChildren } from 'react'; import { ConnectButton } from '@iota/dapp-kit'; +import { Button } from '@iota/apps-ui-kit'; const routes = [ { title: 'Home', path: '/dashboard/home' }, @@ -36,7 +37,7 @@ function DashboardLayout({ children }: PropsWithChildren): JSX.Element { {routes.map((route) => { return ; })} - +
-
+
{touchedFields.recoveryPhrase && errors.recoveryPhrase && ( - ampli.clickedBullsharkQuestsCta({ sourceFlow: 'Banner - Apps tab' }) - } + onClick={() => ampli.clickedAppsBannerCta({ sourceFlow: 'Banner - Apps tab' })} > .line-1 { - top: calc(50% - ($line-height / 2)); - transform: rotate(45deg); - } - - > .line-2 { - transform: rotate(-45deg); - } - - > .line-3 { - opacity: 0; - } -} diff --git a/apps/wallet/src/ui/app/components/menu/button/WalletSettingsButton.tsx b/apps/wallet/src/ui/app/components/menu/button/WalletSettingsButton.tsx index bb875f73ac5..9607f08c8dd 100644 --- a/apps/wallet/src/ui/app/components/menu/button/WalletSettingsButton.tsx +++ b/apps/wallet/src/ui/app/components/menu/button/WalletSettingsButton.tsx @@ -2,9 +2,10 @@ // Modifications Copyright (c) 2024 IOTA Stiftung // SPDX-License-Identifier: Apache-2.0 +import { Button, ButtonSize, ButtonType } from '@iota/apps-ui-kit'; import { Close, Settings } from '@iota/ui-icons'; import { useMenuIsOpen, useNextMenuUrl } from '_components'; -import { ButtonOrLink } from '_src/ui/app/shared/utils/ButtonOrLink'; +import { Link } from 'react-router-dom'; import { cx } from 'class-variance-authority'; export function WalletSettingsButton() { @@ -13,15 +14,16 @@ export function WalletSettingsButton() { const IconComponent = isOpen ? Close : Settings; return ( - - - +
)} diff --git a/apps/wallet/src/ui/app/pages/home/interstitial/index.tsx b/apps/wallet/src/ui/app/pages/home/interstitial/index.tsx index ca575d1f81d..b435f4d650e 100644 --- a/apps/wallet/src/ui/app/pages/home/interstitial/index.tsx +++ b/apps/wallet/src/ui/app/pages/home/interstitial/index.tsx @@ -50,7 +50,7 @@ function Interstitial({ enabled, dismissKey, imageUrl, bannerUrl, onClose }: Int { - ampli.clickedBullsharkQuestsCta({ sourceFlow: 'Interstitial' }); + ampli.clickedAppsBannerCta({ sourceFlow: 'Interstitial' }); closeInterstitial(); }} className="h-full w-full" @@ -59,7 +59,6 @@ function Interstitial({ enabled, dismissKey, imageUrl, bannerUrl, onClose }: Int )} - - ); - }, -); diff --git a/apps/wallet/tailwind.config.ts b/apps/wallet/tailwind.config.ts index 19ef6350361..f1935832df5 100644 --- a/apps/wallet/tailwind.config.ts +++ b/apps/wallet/tailwind.config.ts @@ -5,11 +5,12 @@ import preset from '@iota/core/tailwind.config'; import { type Config } from 'tailwindcss'; import animatePlugin from 'tailwindcss-animate'; -import { uiKitStaticPreset } from '@iota/apps-ui-kit'; +// Note: exception for the tailwind preset import +import uiKitStaticPreset from '../../apps/ui-kit/src/lib/tailwind/static.preset'; export default { presets: [preset, uiKitStaticPreset], - content: ['./src/**/*.{js,jsx,ts,tsx}', './node_modules/@iota/apps-ui-kit/dist/**/*.js'], + content: ['./src/**/*.{js,jsx,ts,tsx}', './../ui-kit/src/lib/**/*.{js,jsx,ts,tsx}'], theme: { extend: { colors: { diff --git a/crates/iota-core/src/traffic_controller/mod.rs b/crates/iota-core/src/traffic_controller/mod.rs index 592f15adf96..47fb47c8efc 100644 --- a/crates/iota-core/src/traffic_controller/mod.rs +++ b/crates/iota-core/src/traffic_controller/mod.rs @@ -22,7 +22,10 @@ use iota_metrics::spawn_monitored_task; use iota_types::traffic_control::{PolicyConfig, RemoteFirewallConfig, Weight}; use prometheus::IntGauge; use rand::Rng; -use tokio::sync::{mpsc, mpsc::error::TrySendError}; +use tokio::{ + sync::{mpsc, mpsc::error::TrySendError}, + time, +}; use tracing::{debug, error, info, trace, warn}; use self::metrics::TrafficControllerMetrics; @@ -687,6 +690,10 @@ impl TrafficSim { let mut time_blocked_start = Instant::now(); let start = Instant::now(); + // we use ticker instead of sleep to be as close to the target TPS as possible, + let sleep_time = Duration::from_micros(1_000_000 / per_client_tps as u64); + let mut interval_ticker = time::interval(sleep_time); + while start.elapsed() < duration { let client = Some(IpAddr::V4(Ipv4Addr::new(127, 0, 0, task_num))); let allowed = controller.check(&client, &None).await; @@ -715,7 +722,8 @@ impl TrafficSim { num_blocked += 1; } num_requests += 1; - tokio::time::sleep(Duration::from_micros(1_000_000 / per_client_tps as u64)).await; + + interval_ticker.tick().await; } TrafficSimMetrics { num_requests, diff --git a/crates/iota-e2e-tests/tests/traffic_control_tests.rs b/crates/iota-e2e-tests/tests/traffic_control_tests.rs index 22ad1477f5d..93104798017 100644 --- a/crates/iota-e2e-tests/tests/traffic_control_tests.rs +++ b/crates/iota-e2e-tests/tests/traffic_control_tests.rs @@ -78,7 +78,14 @@ async fn test_validator_traffic_control_ok() -> Result<(), anyhow::Error> { let policy_config = PolicyConfig { connection_blocklist_ttl_sec: 1, proxy_blocklist_ttl_sec: 5, - spam_policy_type: PolicyType::TestNConnIP(5), + // In this test, the validator gRPC API is receiving some requests that don't count towards + // the policy and two requests that do (/iota.validator.Validator/CertifiedTransactionV2 for + // an already executed transaction). However, the counter is updated only after the response + // is generated, but the limit is checked before we handle the request, so at the end we end + // up with 2 handled requests even if the limit is set to 1 and only the subsequent request + // would be rejected. Set the limit to the actual number of requests, so that it's + // not flaky on slower runners. + spam_policy_type: PolicyType::TestNConnIP(2), // This should never be invoked when set as an error policy // as we are not sending requests that error error_policy_type: PolicyType::TestPanicOnInvocation, @@ -102,7 +109,13 @@ async fn test_fullnode_traffic_control_ok() -> Result<(), anyhow::Error> { let policy_config = PolicyConfig { connection_blocklist_ttl_sec: 1, proxy_blocklist_ttl_sec: 5, - spam_policy_type: PolicyType::TestNConnIP(10), + // The following JSON API requests are counted towards this limit: + // 2 x rpc.discover - those are not sent by the test scenario + // 5 x iotax_getOwnedObjects + // 1 x iotax_getReferenceGasPrice + // 2 x iota_executeTransactionBlock + // 1 x iota_getTransactionBlock + spam_policy_type: PolicyType::TestNConnIP(11), // This should never be invoked when set as an error policy // as we are not sending requests that error error_policy_type: PolicyType::TestPanicOnInvocation, @@ -210,7 +223,9 @@ async fn test_validator_traffic_control_error_blocked() -> Result<(), anyhow::Er let n = 5; let policy_config = PolicyConfig { connection_blocklist_ttl_sec: 1, - // Test that any N requests will cause an IP to be added to the blocklist. + // Test that any N requests to the gRPC API of the validator will cause an IP to be added to + // the blocklist. In this test we're directly calling + // `/iota.validator.Validator/Transaction` gRPC method to go above the limit. error_policy_type: PolicyType::TestNConnIP(n - 1), dry_run: false, ..Default::default() @@ -253,7 +268,10 @@ async fn test_fullnode_traffic_control_spam_blocked() -> Result<(), anyhow::Erro let txn_count = 15; let policy_config = PolicyConfig { connection_blocklist_ttl_sec: 3, - // Test that any N requests will cause an IP to be added to the blocklist. + // Test that any N requests will cause an IP to be added to the blocklist. In the test we + // are performing `txn_count` `iota_getTransactionBlock` calls to the fullnode's JSON API, + // but additionally before that, we're performing other requests, but using `txn_count - 1` + // as the limit is enough to test the blocking functionality. spam_policy_type: PolicyType::TestNConnIP(txn_count - 1), spam_sample_rate: Weight::one(), dry_run: false, @@ -591,8 +609,8 @@ async fn test_traffic_control_manual_set_dead_mans_switch() -> Result<(), anyhow #[sim_test] async fn test_traffic_sketch_no_blocks() { let sketch_config = FreqThresholdConfig { - client_threshold: 10_100, - proxied_client_threshold: 10_100, + client_threshold: 5_050, + proxied_client_threshold: 5_050, window_size_secs: 4, update_interval_secs: 1, ..Default::default() @@ -602,21 +620,24 @@ async fn test_traffic_sketch_no_blocks() { proxy_blocklist_ttl_sec: 1, spam_policy_type: PolicyType::NoOp, error_policy_type: PolicyType::FreqThreshold(sketch_config), - channel_capacity: 100, + // keeping channel capacity small results in less errors in test metrics, + // in case of congestion (due to running on slower hardware) requests are dropped + // and do not influence the rate and do not make the spam rate inconsistent + channel_capacity: 10, dry_run: false, ..Default::default() }; let metrics = TrafficSim::run( policy, - 10, // num_clients - 10_000, // per_client_tps + 10, // num_clients + 5_000, // per_client_tps Duration::from_secs(20), true, // report ) .await; - let expected_requests = 10_000 * 10 * 20; - assert!(metrics.num_blocked < 10_010); + let expected_requests = 5_000 * 10 * 20; + assert!(metrics.num_blocked < 5_005); assert!(metrics.num_requests > expected_requests - 1_000); assert!(metrics.num_requests < expected_requests + 200); assert!(metrics.num_blocklist_adds <= 1); @@ -670,8 +691,8 @@ async fn test_traffic_sketch_with_slow_blocks() { #[sim_test] async fn test_traffic_sketch_with_sampled_spam() { let sketch_config = FreqThresholdConfig { - client_threshold: 4_500, - proxied_client_threshold: 4_500, + client_threshold: 450, + proxied_client_threshold: 450, window_size_secs: 4, update_interval_secs: 1, ..Default::default() @@ -682,26 +703,30 @@ async fn test_traffic_sketch_with_sampled_spam() { spam_policy_type: PolicyType::FreqThreshold(sketch_config), spam_sample_rate: Weight::new(0.5).unwrap(), dry_run: false, + // keeping channel capacity small results in less errors in test metrics, + // in case of congestion (due to running on slower hardware) requests are dropped + // and do not influence the rate and do not make the spam rate inconsistent + channel_capacity: 10, ..Default::default() }; let metrics = TrafficSim::run( policy, - 1, // num_clients - 10_000, // per_client_tps + 1, // num_clients + 1000, // per_client_tps Duration::from_secs(20), true, // report ) .await; - let expected_requests = 10_000 * 20; - assert!(metrics.num_requests > expected_requests - 1_000); - assert!(metrics.num_requests < expected_requests + 200); + let expected_requests = 1000 * 20; + assert!(metrics.num_requests > expected_requests - 100); + assert!(metrics.num_requests < expected_requests + 20); // number of blocked requests should be nearly the same // as before, as we have half the single client TPS, // but the threshould is also halved. However, divide by // 5 instead of 4 as a buffer due in case we're unlucky with // the sampling - assert!(metrics.num_blocked > (expected_requests / 5) - 1000); + assert!(metrics.num_blocked > (expected_requests / 5) - 100); } async fn assert_traffic_control_ok(mut test_cluster: TestCluster) -> Result<(), anyhow::Error> { diff --git a/crates/iota-metrics/src/metered_channel.rs b/crates/iota-metrics/src/metered_channel.rs index f7220c643ce..39b875a8a62 100644 --- a/crates/iota-metrics/src/metered_channel.rs +++ b/crates/iota-metrics/src/metered_channel.rs @@ -117,12 +117,11 @@ impl Receiver { /// Attempts to receive the next value for this receiver. /// Decrements the gauge in case of a successful `try_recv`. pub fn try_recv(&mut self) -> Result { - self.inner.try_recv().map(|val| { + self.inner.try_recv().inspect(|_| { self.gauge.dec(); if let Some(total_gauge) = &self.total { total_gauge.inc(); } - val }) } @@ -132,12 +131,11 @@ impl Receiver { /// keep track of the total number of received items. Returns the received /// value if successful, or `None` if the channel is closed. pub fn blocking_recv(&mut self) -> Option { - self.inner.blocking_recv().map(|val| { + self.inner.blocking_recv().inspect(|_| { self.gauge.dec(); if let Some(total_gauge) = &self.total { total_gauge.inc(); } - val }) } @@ -230,9 +228,8 @@ impl Sender { self.inner .try_send(message) // remove this unsightly hack once https://github.com/rust-lang/rust/issues/91345 is resolved - .map(|val| { + .inspect(|_| { self.gauge.inc(); - val }) } diff --git a/crates/iota-metrics/src/monitored_mpsc.rs b/crates/iota-metrics/src/monitored_mpsc.rs index 2429c163b11..8c8ce92c931 100644 --- a/crates/iota-metrics/src/monitored_mpsc.rs +++ b/crates/iota-metrics/src/monitored_mpsc.rs @@ -289,14 +289,13 @@ impl Receiver { /// Attempts to receive the next value for this receiver. /// Decrements the gauge in case of a successful `try_recv`. pub fn try_recv(&mut self) -> Result { - self.inner.try_recv().map(|val| { + self.inner.try_recv().inspect(|_| { if let Some(inflight) = &self.inflight { inflight.dec(); } if let Some(received) = &self.received { received.inc(); } - val }) } @@ -306,14 +305,13 @@ impl Receiver { /// received gauge (if available) to track the total number of received /// items. pub fn blocking_recv(&mut self) -> Option { - self.inner.blocking_recv().map(|val| { + self.inner.blocking_recv().inspect(|_| { if let Some(inflight) = &self.inflight { inflight.dec(); } if let Some(received) = &self.received { received.inc(); } - val }) } @@ -503,14 +501,13 @@ impl UnboundedReceiver { /// Attempts to receive the next value for this receiver. /// Decrements the gauge in case of a successful `try_recv`. pub fn try_recv(&mut self) -> Result { - self.inner.try_recv().map(|val| { + self.inner.try_recv().inspect(|_| { if let Some(inflight) = &self.inflight { inflight.dec(); } if let Some(received) = &self.received { received.inc(); } - val }) } @@ -519,14 +516,13 @@ impl UnboundedReceiver { /// has been processed, and the received gauge (if available) /// is incremented to track the total number of items received. pub fn blocking_recv(&mut self) -> Option { - self.inner.blocking_recv().map(|val| { + self.inner.blocking_recv().inspect(|_| { if let Some(inflight) = &self.inflight { inflight.dec(); } if let Some(received) = &self.received { received.inc(); } - val }) } diff --git a/crates/iota-rosetta/tests/gas_budget_tests.rs b/crates/iota-rosetta/tests/gas_budget_tests.rs index f71eb48018d..b3b79359a5d 100644 --- a/crates/iota-rosetta/tests/gas_budget_tests.rs +++ b/crates/iota-rosetta/tests/gas_budget_tests.rs @@ -167,7 +167,7 @@ async fn test_pay_with_gas_budget_fail() { TransactionIdentifierResponseResult::Error(rosetta_submit_gas_error) => { assert_eq!(rosetta_submit_gas_error, RosettaSubmitGasError { code: 11, - message: "Transaction dry run error".to_string(), + message: "Transaction dry run".to_string(), description: None, retriable: false, details: RosettaSubmitGasErrorDetails { diff --git a/crates/iota-types/Cargo.toml b/crates/iota-types/Cargo.toml index 5f7d713c009..6527f245153 100644 --- a/crates/iota-types/Cargo.toml +++ b/crates/iota-types/Cargo.toml @@ -101,7 +101,6 @@ harness = false [features] default = [] test-utils = [] - gas-profiler = [ "move-vm-profiler/gas-profiler", "move-vm-test-utils/gas-profiler", diff --git a/crates/typed-store/src/traits.rs b/crates/typed-store/src/traits.rs index 108d8de0280..b9e9b97a4dd 100644 --- a/crates/typed-store/src/traits.rs +++ b/crates/typed-store/src/traits.rs @@ -11,7 +11,7 @@ use crate::TypedStoreError; pub trait Map<'a, K, V> where - K: Serialize + DeserializeOwned + ?Sized, + K: Serialize + DeserializeOwned, V: Serialize + DeserializeOwned, { type Error: Error; @@ -156,7 +156,7 @@ where #[async_trait] pub trait AsyncMap<'a, K, V> where - K: Serialize + DeserializeOwned + ?Sized + std::marker::Sync, + K: Serialize + DeserializeOwned + std::marker::Sync, V: Serialize + DeserializeOwned + std::marker::Sync + std::marker::Send, { type Error: Error; diff --git a/dapps/kiosk-cli/index.js b/dapps/kiosk-cli/index.js index b7f972f2973..a54976a9a9a 100644 --- a/dapps/kiosk-cli/index.js +++ b/dapps/kiosk-cli/index.js @@ -42,10 +42,7 @@ import { Transaction } from '@iota/iota-sdk/transactions'; /** * List of known types for shorthand search in the `search` command. */ -const KNOWN_TYPES = { - iotafren: - '0x80d7de9c4a56194087e0ba0bf59492aa8e6a5ee881606226930827085ddf2332::iotafrens::IotaFren<0x80d7de9c4a56194087e0ba0bf59492aa8e6a5ee881606226930827085ddf2332::capy::Capy>', -}; +const KNOWN_TYPES = {}; /** JsonRpcProvider for the Testnet */ const client = new IotaClient({ url: getFullnodeUrl('testnet') }); @@ -140,13 +137,13 @@ program program .command('search') .description('search open listings in Kiosks') - .argument('', 'The type of the item to search for. \nAvailable aliases: "iotafren", "test"') + .argument('', 'The type of the item to search for. \nAvailable aliases: "test"') .action(searchType); program .command('policy') .description('search for a TransferPolicy for the specified type') - .argument('', 'The type of the item to search for. \nAvailable aliases: "iotafren", "test"') + .argument('', 'The type of the item to search for. \nAvailable aliases: "test"') .action(searchPolicy); program diff --git a/iota-execution/Cargo.toml b/iota-execution/Cargo.toml index c6b1c4f9c78..8d1bf2e2543 100644 --- a/iota-execution/Cargo.toml +++ b/iota-execution/Cargo.toml @@ -35,7 +35,6 @@ petgraph = "0.6" [features] default = [] - gas-profiler = [ "iota-adapter-latest/gas-profiler", "move-vm-config/gas-profiler", diff --git a/iota-execution/cut/src/plan.rs b/iota-execution/cut/src/plan.rs index e697cfb8ae7..3f3588f6289 100644 --- a/iota-execution/cut/src/plan.rs +++ b/iota-execution/cut/src/plan.rs @@ -277,9 +277,8 @@ impl CutPlan { /// will be copied to their destinations, and their dependencies will be /// fixed up. On failure, pending changes are rolled back. pub(crate) fn execute(&self) -> Result<()> { - self.execute_().map_err(|e| { + self.execute_().inspect_err(|_| { self.rollback(); - e }) } fn execute_(&self) -> Result<()> { diff --git a/iota-execution/latest/iota-adapter/src/temporary_store.rs b/iota-execution/latest/iota-adapter/src/temporary_store.rs index 15f85440119..8f2f6b1da22 100644 --- a/iota-execution/latest/iota-adapter/src/temporary_store.rs +++ b/iota-execution/latest/iota-adapter/src/temporary_store.rs @@ -1082,9 +1082,9 @@ impl<'backing> BackingPackageStore for TemporaryStore<'backing> { if let Some(obj) = self.execution_results.written_objects.get(package_id) { Ok(Some(PackageObject::new(obj.clone()))) } else { - self.store.get_package_object(package_id).map(|obj| { + self.store.get_package_object(package_id).inspect(|obj| { // Track object but leave unchanged - if let Some(v) = &obj { + if let Some(v) = obj { if !self .runtime_packages_loaded_from_db .read() @@ -1099,7 +1099,6 @@ impl<'backing> BackingPackageStore for TemporaryStore<'backing> { .insert(*package_id, v.clone()); } } - obj }) } } diff --git a/iota-execution/latest/iota-move-natives/src/dynamic_field.rs b/iota-execution/latest/iota-move-natives/src/dynamic_field.rs index 631c31b5099..e087c44b1a7 100644 --- a/iota-execution/latest/iota-move-natives/src/dynamic_field.rs +++ b/iota-execution/latest/iota-move-natives/src/dynamic_field.rs @@ -327,9 +327,8 @@ pub fn borrow_child_object( if !global_value.exists()? { return Ok(NativeResult::err(context.gas_used(), E_KEY_DOES_NOT_EXIST)); } - let child_ref = global_value.borrow_global().map_err(|err| { + let child_ref = global_value.borrow_global().inspect_err(|err| { assert!(err.major_status() != StatusCode::MISSING_DATA); - err })?; native_charge_gas_early_exit!( @@ -403,9 +402,8 @@ pub fn remove_child_object( if !global_value.exists()? { return Ok(NativeResult::err(context.gas_used(), E_KEY_DOES_NOT_EXIST)); } - let child = global_value.move_from().map_err(|err| { + let child = global_value.move_from().inspect_err(|err| { assert!(err.major_status() != StatusCode::MISSING_DATA); - err })?; native_charge_gas_early_exit!( diff --git a/iota-execution/latest/iota-verifier/src/verifier.rs b/iota-execution/latest/iota-verifier/src/verifier.rs index 3e43cf51941..0644392062a 100644 --- a/iota-execution/latest/iota-verifier/src/verifier.rs +++ b/iota-execution/latest/iota-verifier/src/verifier.rs @@ -52,7 +52,7 @@ pub fn iota_verify_module_unmetered( module: &CompiledModule, fn_info_map: &FnInfoMap, ) -> Result<(), ExecutionError> { - iota_verify_module_metered(module, fn_info_map, &mut DummyMeter).map_err(|err| { + iota_verify_module_metered(module, fn_info_map, &mut DummyMeter).inspect_err(|err| { // We must never see timeout error in execution debug_assert!( !matches!( @@ -61,6 +61,5 @@ pub fn iota_verify_module_unmetered( ), "Unexpected timeout error in execution" ); - err }) } diff --git a/iota-execution/v0/iota-adapter/src/temporary_store.rs b/iota-execution/v0/iota-adapter/src/temporary_store.rs index 15f85440119..8f2f6b1da22 100644 --- a/iota-execution/v0/iota-adapter/src/temporary_store.rs +++ b/iota-execution/v0/iota-adapter/src/temporary_store.rs @@ -1082,9 +1082,9 @@ impl<'backing> BackingPackageStore for TemporaryStore<'backing> { if let Some(obj) = self.execution_results.written_objects.get(package_id) { Ok(Some(PackageObject::new(obj.clone()))) } else { - self.store.get_package_object(package_id).map(|obj| { + self.store.get_package_object(package_id).inspect(|obj| { // Track object but leave unchanged - if let Some(v) = &obj { + if let Some(v) = obj { if !self .runtime_packages_loaded_from_db .read() @@ -1099,7 +1099,6 @@ impl<'backing> BackingPackageStore for TemporaryStore<'backing> { .insert(*package_id, v.clone()); } } - obj }) } } diff --git a/iota-execution/v0/iota-move-natives/src/dynamic_field.rs b/iota-execution/v0/iota-move-natives/src/dynamic_field.rs index 631c31b5099..e087c44b1a7 100644 --- a/iota-execution/v0/iota-move-natives/src/dynamic_field.rs +++ b/iota-execution/v0/iota-move-natives/src/dynamic_field.rs @@ -327,9 +327,8 @@ pub fn borrow_child_object( if !global_value.exists()? { return Ok(NativeResult::err(context.gas_used(), E_KEY_DOES_NOT_EXIST)); } - let child_ref = global_value.borrow_global().map_err(|err| { + let child_ref = global_value.borrow_global().inspect_err(|err| { assert!(err.major_status() != StatusCode::MISSING_DATA); - err })?; native_charge_gas_early_exit!( @@ -403,9 +402,8 @@ pub fn remove_child_object( if !global_value.exists()? { return Ok(NativeResult::err(context.gas_used(), E_KEY_DOES_NOT_EXIST)); } - let child = global_value.move_from().map_err(|err| { + let child = global_value.move_from().inspect_err(|err| { assert!(err.major_status() != StatusCode::MISSING_DATA); - err })?; native_charge_gas_early_exit!( diff --git a/iota-execution/v0/iota-verifier/src/verifier.rs b/iota-execution/v0/iota-verifier/src/verifier.rs index 3e43cf51941..0644392062a 100644 --- a/iota-execution/v0/iota-verifier/src/verifier.rs +++ b/iota-execution/v0/iota-verifier/src/verifier.rs @@ -52,7 +52,7 @@ pub fn iota_verify_module_unmetered( module: &CompiledModule, fn_info_map: &FnInfoMap, ) -> Result<(), ExecutionError> { - iota_verify_module_metered(module, fn_info_map, &mut DummyMeter).map_err(|err| { + iota_verify_module_metered(module, fn_info_map, &mut DummyMeter).inspect_err(|err| { // We must never see timeout error in execution debug_assert!( !matches!( @@ -61,6 +61,5 @@ pub fn iota_verify_module_unmetered( ), "Unexpected timeout error in execution" ); - err }) } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6f7ca430524..edecb0e30ae 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -991,6 +991,9 @@ importers: apps/wallet-dashboard: dependencies: + '@iota/apps-ui-kit': + specifier: workspace:* + version: link:../ui-kit '@iota/core': specifier: workspace:* version: link:../core @@ -1818,12 +1821,18 @@ importers: '@ledgerhq/hw-transport-mocker': specifier: ^6.29.0 version: 6.29.4 + '@ledgerhq/hw-transport-node-speculos-http': + specifier: ^6.29.2 + version: 6.29.4 '@size-limit/preset-small-lib': specifier: ^11.1.4 version: 11.1.5(size-limit@11.1.5) '@types/node': specifier: ^20.14.10 version: 20.16.9 + axios: + specifier: ^1.7.4 + version: 1.7.7(debug@4.3.7) size-limit: specifier: ^11.1.4 version: 11.1.5 @@ -4539,6 +4548,9 @@ packages: '@ledgerhq/hw-transport-mocker@6.29.4': resolution: {integrity: sha512-CLDIpQ/eqU8qrCYGY9MyHa+oMgqs6PuNkWtqbcaS4AzNx8L/9bv7y8CZwCjxX6oB/2ZEq42RlL6oZ6Ou3oHnoQ==} + '@ledgerhq/hw-transport-node-speculos-http@6.29.4': + resolution: {integrity: sha512-UTIqSxf1jH2aVGsg6VnQXDj9fpzn/q/cf9eNwg87QSTNvJ8wbomNBy+x+fgjXt4pZpv9lbFzIyGhE6qsh9QvMQ==} + '@ledgerhq/hw-transport-webhid@6.29.4': resolution: {integrity: sha512-XkF37lcuyg9zVExMyfDQathWly8rRcGac13wgZATBa3nZ+hUzzWr5QVKg1pKCw10izVHGErW/9a4tbb72rUEmQ==} @@ -15425,10 +15437,6 @@ packages: resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==} engines: {node: '>=6'} - tough-cookie@2.5.0: - resolution: {integrity: sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==} - engines: {node: '>=0.8'} - tough-cookie@4.1.4: resolution: {integrity: sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==} engines: {node: '>=6'} @@ -20759,6 +20767,16 @@ snapshots: '@ledgerhq/logs': 6.12.0 rxjs: 7.8.1 + '@ledgerhq/hw-transport-node-speculos-http@6.29.4': + dependencies: + '@ledgerhq/errors': 6.19.1 + '@ledgerhq/hw-transport': 6.31.4 + '@ledgerhq/logs': 6.12.0 + axios: 1.7.7(debug@4.3.7) + rxjs: 7.8.1 + transitivePeerDependencies: + - debug + '@ledgerhq/hw-transport-webhid@6.29.4': dependencies: '@ledgerhq/devices': 8.4.4 @@ -33335,7 +33353,7 @@ snapshots: performance-now: 2.1.0 qs: 6.5.3 safe-buffer: 5.2.1 - tough-cookie: 2.5.0 + tough-cookie: 4.1.4 tunnel-agent: 0.6.0 uuid: 3.4.0 @@ -34490,11 +34508,6 @@ snapshots: totalist@3.0.1: {} - tough-cookie@2.5.0: - dependencies: - psl: 1.9.0 - punycode: 2.3.1 - tough-cookie@4.1.4: dependencies: psl: 1.9.0 diff --git a/scripts/cargo_sort/README.md b/scripts/cargo_sort/README.md new file mode 100644 index 00000000000..ac111895610 --- /dev/null +++ b/scripts/cargo_sort/README.md @@ -0,0 +1,17 @@ +# Cargo Sort + +This python script sorts all dependencies in all `Cargo.toml` files in the repository (except `external-crates`) by internal and external dependencies. + +## Usage + +```bash +usage: run.sh [-h] [--target TARGET] [--skip-dprint] [--debug] + +Format the Cargo.toml files and sort internal and external dependencies. + +options: + -h, --help show this help message and exit + --target TARGET Target directory to search in. + --skip-dprint Skip running dprint fmt. + --debug Show debug prints. +``` diff --git a/scripts/cargo_sort/cargo_sort.py b/scripts/cargo_sort/cargo_sort.py new file mode 100644 index 00000000000..af358a3a769 --- /dev/null +++ b/scripts/cargo_sort/cargo_sort.py @@ -0,0 +1,355 @@ +import os, re, argparse, subprocess + +COMMENT_DEPENDENCIES_START_EXTERNAL = "# external dependencies" +COMMENT_DEPENDENCIES_START_INTERNAL = "# internal dependencies" + +def get_package_name_from_cargo_toml(file_path): + # search for the [package] section in the Cargo.toml file + section_regex = re.compile(r'^\[([a-zA-Z0-9_-]+)\]$') + package_section_regex = re.compile(r'^\[package\]$') + package_name_regex = re.compile(r'^name\s*=\s*"(.*)"$') + + with open(file_path, 'r') as file: + lines = file.readlines() + + in_package_section = False + for line in lines: + stripped_line = line.strip() + + if not in_package_section and package_section_regex.match(stripped_line): + in_package_section = True + continue + + if in_package_section: + package_name_match = package_name_regex.match(stripped_line) + if package_name_match: + return package_name_match.group(1) + + if section_regex.match(stripped_line): + # we are done with the package section + return None + + # no package section found + return None + +def get_package_names_from_cargo_tomls(directory): + print("Getting \"internal\" crates from 'Cargo.toml' files...") + + package_names = {} + + # find all Cargo.toml files in the target folder + for root, _, files in os.walk(directory): + for file in files: + if file == 'Cargo.toml': + file_path = os.path.join(root, file) + package_name = get_package_name_from_cargo_toml(file_path) + if package_name: + package_names[package_name] = None + + return package_names + +def process_cargo_toml(file_path, internal_crates_dict, debug): + with open(file_path, 'r') as file: + lines = file.readlines() + + array_start_regex = re.compile(r'^([a-zA-Z0-9_-]+)\s*=\s*\[$') + crates_line_regex = re.compile(r'^([a-zA-Z0-9_-]+)(?:\.workspace)?\s*=\s*(?:{[^}]*\bpackage\s*=\s*"(.*?)"[^}]*}|.*)$') + + class Section(object): + def __init__(self, line): + self.line = line + self.unknown_lines_start = [] + self.external_crates = {} + self.internal_crates = {} + self.unknown_lines_end = [] + + def add_node(self, node): + if not node.name in internal_crates_dict: + self.external_crates[node.alias] = node + else: + self.internal_crates[node.alias] = node + + def add_unknown_line(self, line): + if not self.external_crates and not self.internal_crates: + self.unknown_lines_start.append(line) + else: + self.unknown_lines_end.append(line) + + def get_processed_lines(self): + # check if the nodes in the section should be sorted + sort_nodes = any(word in self.line for word in ['dependencies', 'profile']) + + processed_lines = [] + + # add potential unprocessed lines (comments at the start of the section) + if self.unknown_lines_start: + processed_lines.extend(self.unknown_lines_start) + + # add the section header + processed_lines.append(self.line) + + both_dependency_groups_exist = self.external_crates and self.internal_crates + if both_dependency_groups_exist: + processed_lines.append(COMMENT_DEPENDENCIES_START_EXTERNAL) + + # add the external crates + external_crates = self.external_crates + if sort_nodes: + # sort the external crates by alias + external_crates = {key: self.external_crates[key] for key in sorted(self.external_crates)} + for crate_alias in external_crates: + processed_lines.extend(external_crates[crate_alias].get_processed_lines()) + + if both_dependency_groups_exist: + # add a newline between external and internal crates + processed_lines.append('') + + if both_dependency_groups_exist: + processed_lines.append(COMMENT_DEPENDENCIES_START_INTERNAL) + + # add the internal crates + internal_crates = self.internal_crates + if sort_nodes: + # sort the internal crates by alias + internal_crates = {key: self.internal_crates[key] for key in sorted(self.internal_crates)} + for crate_alias in internal_crates: + processed_lines.extend(internal_crates[crate_alias].get_processed_lines()) + + # add potential unprocessed lines (comments at the end of the section) + if self.unknown_lines_end: + processed_lines.extend(self.unknown_lines_end) + return processed_lines + + class Node(object): + def __init__(self, name, alias, start, is_multiline, comments): + self.name = name + self.alias = alias + self.lines = [start] + self.is_multiline = is_multiline + self.comments = comments + + def add_line(self, line): + if not self.is_multiline: + raise Exception(f"Node {self.name} is not multiline") + self.lines.append(line) + + def get_processed_lines(self): + if self.is_multiline and len(self.lines) > 2: + # sort all the lines except the first and the last one + self.lines = [self.lines[0]] + sorted(self.lines[1:-1]) + [self.lines[-1]] + + processed_lines = [] + for comment in self.comments: + if not comment.strip(): + # skip empty lines + continue + processed_lines.append(comment) + for line in self.lines: + processed_lines.append(line) + return processed_lines + + processed_lines = [] + current_section = None + current_node = None + unprocessed_lines = [] + + def print_debug_info(msg): + if debug: + print(msg) + + def finish_node(): + nonlocal current_node + if current_node: + # if we have a current node, finish it + current_node = None + + def finish_section(): + nonlocal current_node, current_section, processed_lines, unprocessed_lines + + finish_node() + + if current_section: + # if we have a current section, finish it + # We need to check were the unprocessed lines belong to by scanning in reverse. + # If there is a newline between the next section and the remaining unprocessed lines, + # the unprocessed lines belong to the current section. + if unprocessed_lines: + unprocessed_lines_current_section = [] + unprocessed_lines_next_section = [] + + newline_found = False + for line in reversed(unprocessed_lines): + if not line.strip(): + # found a newline, the unprocessed lines belong to the current section + newline_found = True + # skip the newline + continue + + if newline_found: + unprocessed_lines_current_section.insert(0, line) + else: + unprocessed_lines_next_section.insert(0, line) + + for unprocessed_line in unprocessed_lines_current_section: + current_section.add_unknown_line(unprocessed_line) + + # set the unprocessed lines to contain the comments for the next section + # this will be picked up while creating the next section + unprocessed_lines = unprocessed_lines_next_section + + processed_lines.extend(current_section.get_processed_lines()) + current_section = None + + # add a newline between sections + processed_lines.append('') + + for line in lines: + # strip the line of leading/trailing whitespace + stripped_line = line.strip() + + if stripped_line in [COMMENT_DEPENDENCIES_START_EXTERNAL, COMMENT_DEPENDENCIES_START_INTERNAL]: + # skip the line if it is the start of the external or internal crates + continue + + print_debug_info(f"Processing line: '{stripped_line}'") + + # check if the line is a section header + is_section_header = stripped_line.startswith('[') and stripped_line.endswith(']') + if is_section_header: + print_debug_info(f" -> Section header: {stripped_line}") + + finish_section() + + # create a new section + current_section = Section(stripped_line) + for unprocessed_line in unprocessed_lines: + if not unprocessed_line.strip(): + # skip empty lines + continue + current_section.add_unknown_line(unprocessed_line) + unprocessed_lines = [] + continue + + # check if the line is an array start + array_start_regex_search = array_start_regex.search(stripped_line) + if array_start_regex_search: + print_debug_info(f" -> Array start: {array_start_regex_search.group(1)}") + + finish_node() + + array_name = array_start_regex_search.group(1) + + # create a new node + if not current_section: + raise Exception(f"Node {array_name.name} without section") + current_node = Node(name=array_name, alias=array_name, start=stripped_line, is_multiline=True, comments=unprocessed_lines) + current_section.add_node(current_node) + unprocessed_lines = [] + + continue + + # check if the line is an array end + is_array_end = "[" not in stripped_line and stripped_line.endswith(']') + if is_array_end: + print_debug_info(f" -> Array end: {stripped_line}") + + if not current_node: + raise Exception(f"Array end {stripped_line} without start") + + # add the unprocessed lines to the current node + for unprocessed_line in unprocessed_lines: + if not unprocessed_line.strip(): + # skip empty lines + continue + current_node.add_line(unprocessed_line) + unprocessed_lines = [] + + # add the end line to the current node + current_node.add_line(line.rstrip()) + + finish_node() + continue + + # check if the line is a crate line + crate_regex_search = crates_line_regex.search(stripped_line) + if crate_regex_search: + print_debug_info(f" -> Crate: {crate_regex_search.group(1)}") + + crate_alias = crate_regex_search.group(1) + crate_name = crate_regex_search.group(1) + if crate_regex_search.group(2): + crate_name = crate_regex_search.group(2) + + # create a new node + if not current_section: + raise Exception(f"Node {crate_name} without section") + + current_section.add_node(Node(name=crate_name, alias=crate_alias, start=stripped_line, is_multiline=False, comments=unprocessed_lines)) + unprocessed_lines = [] + continue + + # unknown line type, add it to the unprocessed lines + print_debug_info(f" -> Unknown line: {stripped_line}") + unprocessed_lines.append(line.rstrip()) + + finish_section() + + # Rewrite the file with the processed lines + with open(file_path, 'w') as file: + # write a newline for every entry in the processed lines list except the last one, + # it is a newline anyway (added by finish_section) + for line in processed_lines[:-1]: + file.write(f"{line}\n") + +def find_and_process_toml_files(directory, internal_crates_dict, ignored_folders, debug): + print("Processing Cargo.toml files...") + + # Compile the regex patterns for ignored folders + ignored_folders = [re.compile(pattern) for pattern in ignored_folders] + + for root, dirs, files in os.walk(directory): + # Skip the entire directory if the root matches any ignored folder pattern + if any(pattern.search(root) for pattern in ignored_folders): + print(f" Skipping directory (regex): {root}") + dirs.clear() # Don't walk into the directory if it should be ignored + continue + + for file in files: + if file == 'Cargo.toml': + file_path = os.path.join(root, file) + print(f'Processing {file_path}') + process_cargo_toml(file_path, internal_crates_dict, debug) + +# Run dprint fmt +def run_dprint_fmt(directory): + cwd = os.getcwd() + + print("Running dprint fmt...") + try: + os.chdir(directory) + subprocess.run(["dprint", "fmt"], check=True) + finally: + os.chdir(cwd) + +if __name__ == '__main__': + parser = argparse.ArgumentParser(description='Format the Cargo.toml files and sort internal and external dependencies.') + parser.add_argument('--target', default="../../", help='Target directory to search in.') + parser.add_argument('--skip-dprint', action='store_true', help='Skip running dprint fmt.') + parser.add_argument('--debug', action='store_true', help='Show debug prints.') + + args = parser.parse_args() + + internal_crates_dict = get_package_names_from_cargo_tomls(args.target) + + # add special cases + internal_crates_dict["iota-rust-sdk"] = None + + # ignored folders + ignored_folders = [ + "external-crates", + ] + + find_and_process_toml_files(args.target, internal_crates_dict, ignored_folders, args.debug) + + if not args.skip_dprint: + run_dprint_fmt(args.target) diff --git a/scripts/cargo_sort/run.sh b/scripts/cargo_sort/run.sh new file mode 100755 index 00000000000..e78faa38843 --- /dev/null +++ b/scripts/cargo_sort/run.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +# Check if either "python" or "python3" exists and use it +if command -v python3 &>/dev/null; then + PYTHON_CMD="python3" +elif command -v python &>/dev/null; then + PYTHON_CMD="python" +else + echo "Neither python nor python3 binary is installed. Please install Python." + exit 1 +fi + +$PYTHON_CMD cargo_sort.py "$@" \ No newline at end of file diff --git a/scripts/generate_files/Dockerfile b/scripts/generate_files/Dockerfile new file mode 100644 index 00000000000..14f2589e983 --- /dev/null +++ b/scripts/generate_files/Dockerfile @@ -0,0 +1,32 @@ +FROM node:20-bookworm + +# Accept a build argument for the Rust version +ARG RUST_VERSION=1.80.1 + +# Get USER_ID from build-args +ARG USER_ID=1000 + +# Check if the USER_ID needs to be updated, and adjust permissions accordingly +RUN if [ $USER_ID -ne 1000 ]; then \ + usermod -u $USER_ID node; \ + chown -R $USER_ID /home/node; \ +fi + +# Install pnpm +RUN npm install -g pnpm + +USER node +WORKDIR /home/node + +# Set the safe.directory to /app +RUN git config --global --add safe.directory /app + +# Install the specific Rust version +RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- --default-toolchain ${RUST_VERSION} -y + +# Add .cargo/bin to PATH +ENV PATH="/home/node/.cargo/bin:${PATH}" + +RUN mkdir -p /home/node/app + +WORKDIR /home/node/app \ No newline at end of file diff --git a/scripts/generate_files/README.md b/scripts/generate_files/README.md new file mode 100644 index 00000000000..c2583591f01 --- /dev/null +++ b/scripts/generate_files/README.md @@ -0,0 +1,3 @@ +# Generate files + +Run the script `./update_generated_files.sh` to update the `openrpc` and `graphql` specs, and the autogenerated typescript code that is based on both specs. diff --git a/scripts/generate_files/update_generated_files.sh b/scripts/generate_files/update_generated_files.sh new file mode 100755 index 00000000000..127ac45a414 --- /dev/null +++ b/scripts/generate_files/update_generated_files.sh @@ -0,0 +1,113 @@ +#!/bin/bash +TARGET_FOLDER="../.." +SKIP_SPEC_GENERATION=false +CHECK_BUILDS=false + +# Parse command line arguments +# Usage: +# --target-folder - the target folder of the repository +# --skip-spec-generation - skip the generation of the open rpc and graphql schema +# --check-builds - run a build check after the generation of the files +while [ $# -gt 0 ]; do + if [[ $1 == *"--target-folder"* ]]; then + TARGET_FOLDER=$2 + fi + + if [[ $1 == *"--skip-spec-generation"* ]]; then + SKIP_SPEC_GENERATION=true + fi + + if [[ $1 == *"--check-builds"* ]]; then + CHECK_BUILDS=true + fi + + shift +done + +# Resolve the target folder +TARGET_FOLDER=$(realpath ${TARGET_FOLDER}) + +function print_step { + echo -e "\e[32m$1\e[0m" +} + +function print_error { + echo -e "\e[31m$1\e[0m" +} + +function check_error { + if [ $? -ne 0 ]; then + print_error "$1" + exit 1 + fi +} + +function docker_run { + docker run --rm --name pnpm-cargo-image -v ${TARGET_FOLDER}:/home/node/app:rw --user $(id -u):$(id -g) pnpm-cargo-image sh -c "$1" +} + +print_step "Parse the rust toolchain version from 'rust-toolchain.toml'..." +RUST_VERSION=$(grep -oE 'channel = "[^"]+' ./../../rust-toolchain.toml | sed 's/channel = "//') +if [ -z "$RUST_VERSION" ]; then + print_error "Failed to parse the rust toolchain version" + exit 1 +fi + +print_step "Building pnpm-cargo docker image with rust version ${RUST_VERSION}..." +docker build --build-arg RUST_VERSION=${RUST_VERSION} --build-arg USER_ID=$(id -u) -t pnpm-cargo-image -f ./Dockerfile . +check_error "Failed to build pnpm-cargo docker image" + +print_step "Changing directory to ${TARGET_FOLDER}" +pushd ${TARGET_FOLDER} + +# add cleanup hook to return to original folder +function cleanup { + popd +} + +trap cleanup EXIT + +# if the spec generation is not skipped, generate the spec +if [ "$SKIP_SPEC_GENERATION" = false ]; then + print_step "Generating open rpc schema..." + cargo run --package iota-open-rpc --example generate-json-rpc-spec -- record + check_error "Failed to generate open rpc schema" + + echo -e "\e[32mGenerating graphql schema..." + cargo run --package iota-graphql-rpc generate-schema --file ./crates/iota-graphql-rpc/schema.graphql + check_error "Failed to generate graphql schema" +fi + +print_step "Installing typescript sdk dependencies..." +docker_run "cd sdk/typescript && pnpm i" +check_error "Failed to install typescript sdk dependencies" + +print_step "Installing graphql-transport dependencies..." +docker_run "cd sdk/graphql-transport && pnpm i" +check_error "Failed to install graphql-transport dependencies" + +print_step "Updating open rpc client types..." +docker_run "cd sdk/typescript && pnpm update-open-rpc-client-types" +check_error "Failed to update open rpc client types" + +print_step "Create graphql schema in 'client/types/generated.ts'..." +docker_run "cd sdk/typescript && pnpm update-graphql-schemas" +check_error "Failed to create graphql schema" + +print_step "Generating graphql-transport typescript types..." +docker_run "cd sdk/graphql-transport && pnpm codegen" +check_error "Failed to generate graphql-transport typescript types" + +if [ "$CHECK_BUILDS" = true ]; then + print_step "Run a typescript sdk build to check if the generated files are correct..." + docker_run "cd sdk/typescript && pnpm run build" + check_error "Failed to build typescript sdk" + + print_step "Run a graphql-transport build to check if the generated files are correct..." + docker_run "cd sdk/graphql-transport && pnpm run build" + check_error "Failed to build graphql-transport" + + print_step "Run a complete turbo build to catch possible issues in other SDK modules or apps..." + docker_run "pnpm turbo build" + check_error "Failed to build the complete project" +fi \ No newline at end of file diff --git a/sdk/.env.defaults b/sdk/.env.defaults index 3b8d543a38e..a6d40f7a431 100644 --- a/sdk/.env.defaults +++ b/sdk/.env.defaults @@ -6,7 +6,7 @@ IOTA_NETWORKS = ' "mainnet": { "id": "mainnet", "name": "Mainnet", - "url": "https://fullnode.mainnet.iota.io:443", + "url": "https://fullnode.mainnet.iota.org:443", "chain": "iota:mainnet", "explorer": "https://explorer.iota.org", "kiosk": { @@ -19,10 +19,10 @@ IOTA_NETWORKS = ' "testnet": { "id": "testnet", "name": "Testnet", - "url": "https://fullnode.testnet.iota.io:443", + "url": "https://fullnode.testnet.iota.org:443", "explorer": "https://explorer.iota.org", "chain": "iota:testnet", - "faucet": "https://faucet.testnet.iota.io/gas", + "faucet": "https://faucet.testnet.iota.org/gas", "kiosk": { "royaltyRulePackageId": "bd8fc1947cf119350184107a3087e2dc27efefa0dd82e25a1f699069fe81a585", "kioskLockRulePackageId": "bd8fc1947cf119350184107a3087e2dc27efefa0dd82e25a1f699069fe81a585", @@ -33,10 +33,10 @@ IOTA_NETWORKS = ' "devnet": { "id": "devnet", "name": "Devnet", - "url": "https://fullnode.devnet.iota.io:443", + "url": "https://fullnode.devnet.iota.org:443", "explorer": "https://explorer.iota.org", "chain": "iota:devnet", - "faucet": "https://faucet.devnet.iota.io/gas" + "faucet": "https://faucet.devnet.iota.org/gas" }, "localnet": { "id": "localnet", diff --git a/sdk/create-dapp/templates/react-e2e-counter/README.md b/sdk/create-dapp/templates/react-e2e-counter/README.md index 6b502445f48..a222ee66d02 100644 --- a/sdk/create-dapp/templates/react-e2e-counter/README.md +++ b/sdk/create-dapp/templates/react-e2e-counter/README.md @@ -28,7 +28,7 @@ This template uses `testnet` by default, so we'll need to set up a testnet environment in the CLI: ```bash -iota client new-env --alias testnet --rpc https://fullnode.testnet.iota.io:443 +iota client new-env --alias testnet --rpc https://fullnode.testnet.iota.org:443 iota client switch --env testnet ``` @@ -51,7 +51,7 @@ We can ensure we have some IOTA in our new wallet by requesting IOTA from the faucet (make sure to replace the address with your address): ```bash -curl --location --request POST 'https://faucet.testnet.iota.io/gas' \ +curl --location --request POST 'https://faucet.testnet.iota.org/gas' \ --header 'Content-Type: application/json' \ --data-raw '{ "FixedAmountRequest": { diff --git a/sdk/graphql-transport/src/generated/queries.ts b/sdk/graphql-transport/src/generated/queries.ts index 5465b305677..ac36d66bdf4 100644 --- a/sdk/graphql-transport/src/generated/queries.ts +++ b/sdk/graphql-transport/src/generated/queries.ts @@ -5050,14 +5050,13 @@ export type ValidatorConnection = { /** The credentials related fields associated with a validator. */ export type ValidatorCredentials = { __typename?: 'ValidatorCredentials'; + authorityPubKey?: Maybe; netAddress?: Maybe; networkPubKey?: Maybe; p2PAddress?: Maybe; primaryAddress?: Maybe; proofOfPossession?: Maybe; protocolPubKey?: Maybe; - workerAddress?: Maybe; - workerPubKey?: Maybe; }; /** An edge in a connection. */ @@ -5255,12 +5254,12 @@ export type GetCommitteeInfoQueryVariables = Exact<{ }>; -export type GetCommitteeInfoQuery = { __typename?: 'Query', epoch?: { __typename?: 'Epoch', epochId: any, validatorSet?: { __typename?: 'ValidatorSet', activeValidators: { __typename?: 'ValidatorConnection', pageInfo: { __typename?: 'PageInfo', hasNextPage: boolean, endCursor?: string | null }, nodes: Array<{ __typename?: 'Validator', votingPower?: number | null, credentials?: { __typename?: 'ValidatorCredentials', protocolPubKey?: any | null } | null }> } } | null } | null }; +export type GetCommitteeInfoQuery = { __typename?: 'Query', epoch?: { __typename?: 'Epoch', epochId: any, validatorSet?: { __typename?: 'ValidatorSet', activeValidators: { __typename?: 'ValidatorConnection', pageInfo: { __typename?: 'PageInfo', hasNextPage: boolean, endCursor?: string | null }, nodes: Array<{ __typename?: 'Validator', votingPower?: number | null, credentials?: { __typename?: 'ValidatorCredentials', authorityPubKey?: any | null } | null }> } } | null } | null }; export type GetCurrentEpochQueryVariables = Exact<{ [key: string]: never; }>; -export type GetCurrentEpochQuery = { __typename?: 'Query', epoch?: { __typename?: 'Epoch', epochId: any, totalTransactions?: any | null, startTimestamp: any, endTimestamp?: any | null, referenceGasPrice?: any | null, validatorSet?: { __typename?: 'ValidatorSet', activeValidators: { __typename?: 'ValidatorConnection', pageInfo: { __typename?: 'PageInfo', hasNextPage: boolean, endCursor?: string | null }, nodes: Array<{ __typename?: 'Validator', atRisk?: any | null, commissionRate?: number | null, exchangeRatesSize?: any | null, description?: string | null, gasPrice?: any | null, imageUrl?: string | null, name?: string | null, nextEpochCommissionRate?: number | null, nextEpochGasPrice?: any | null, nextEpochStake?: any | null, pendingPoolTokenWithdraw?: any | null, pendingStake?: any | null, pendingTotalIotaWithdraw?: any | null, poolTokenBalance?: any | null, projectUrl?: string | null, rewardsPool?: any | null, stakingPoolActivationEpoch?: any | null, stakingPoolIotaBalance?: any | null, votingPower?: number | null, exchangeRates?: { __typename?: 'MoveObject', address: any, contents?: { __typename?: 'MoveValue', json: any } | null } | null, credentials?: { __typename?: 'ValidatorCredentials', netAddress?: string | null, networkPubKey?: any | null, p2PAddress?: string | null, primaryAddress?: string | null, workerPubKey?: any | null, workerAddress?: string | null, proofOfPossession?: any | null, protocolPubKey?: any | null } | null, nextEpochCredentials?: { __typename?: 'ValidatorCredentials', netAddress?: string | null, networkPubKey?: any | null, p2PAddress?: string | null, primaryAddress?: string | null, workerPubKey?: any | null, workerAddress?: string | null, proofOfPossession?: any | null, protocolPubKey?: any | null } | null, operationCap?: { __typename?: 'MoveObject', address: any } | null, stakingPool?: { __typename?: 'MoveObject', address: any } | null, address: { __typename?: 'Address', address: any } }> } } | null, firstCheckpoint: { __typename?: 'CheckpointConnection', nodes: Array<{ __typename?: 'Checkpoint', sequenceNumber: any }> } } | null }; +export type GetCurrentEpochQuery = { __typename?: 'Query', epoch?: { __typename?: 'Epoch', epochId: any, totalTransactions?: any | null, startTimestamp: any, endTimestamp?: any | null, referenceGasPrice?: any | null, validatorSet?: { __typename?: 'ValidatorSet', activeValidators: { __typename?: 'ValidatorConnection', pageInfo: { __typename?: 'PageInfo', hasNextPage: boolean, endCursor?: string | null }, nodes: Array<{ __typename?: 'Validator', atRisk?: any | null, commissionRate?: number | null, exchangeRatesSize?: any | null, description?: string | null, gasPrice?: any | null, imageUrl?: string | null, name?: string | null, nextEpochCommissionRate?: number | null, nextEpochGasPrice?: any | null, nextEpochStake?: any | null, pendingPoolTokenWithdraw?: any | null, pendingStake?: any | null, pendingTotalIotaWithdraw?: any | null, poolTokenBalance?: any | null, projectUrl?: string | null, rewardsPool?: any | null, stakingPoolActivationEpoch?: any | null, stakingPoolIotaBalance?: any | null, votingPower?: number | null, exchangeRates?: { __typename?: 'MoveObject', address: any, contents?: { __typename?: 'MoveValue', json: any } | null } | null, credentials?: { __typename?: 'ValidatorCredentials', netAddress?: string | null, networkPubKey?: any | null, p2PAddress?: string | null, primaryAddress?: string | null, authorityPubKey?: any | null, proofOfPossession?: any | null, protocolPubKey?: any | null } | null, nextEpochCredentials?: { __typename?: 'ValidatorCredentials', netAddress?: string | null, networkPubKey?: any | null, p2PAddress?: string | null, primaryAddress?: string | null, authorityPubKey?: any | null, proofOfPossession?: any | null, protocolPubKey?: any | null } | null, operationCap?: { __typename?: 'MoveObject', address: any } | null, stakingPool?: { __typename?: 'MoveObject', address: any } | null, address: { __typename?: 'Address', address: any } }> } } | null, firstCheckpoint: { __typename?: 'CheckpointConnection', nodes: Array<{ __typename?: 'Checkpoint', sequenceNumber: any }> } } | null }; export type PaginateEpochValidatorsQueryVariables = Exact<{ id: Scalars['UInt53']['input']; @@ -5268,11 +5267,11 @@ export type PaginateEpochValidatorsQueryVariables = Exact<{ }>; -export type PaginateEpochValidatorsQuery = { __typename?: 'Query', epoch?: { __typename?: 'Epoch', validatorSet?: { __typename?: 'ValidatorSet', activeValidators: { __typename?: 'ValidatorConnection', pageInfo: { __typename?: 'PageInfo', hasNextPage: boolean, endCursor?: string | null }, nodes: Array<{ __typename?: 'Validator', atRisk?: any | null, commissionRate?: number | null, exchangeRatesSize?: any | null, description?: string | null, gasPrice?: any | null, imageUrl?: string | null, name?: string | null, nextEpochCommissionRate?: number | null, nextEpochGasPrice?: any | null, nextEpochStake?: any | null, pendingPoolTokenWithdraw?: any | null, pendingStake?: any | null, pendingTotalIotaWithdraw?: any | null, poolTokenBalance?: any | null, projectUrl?: string | null, rewardsPool?: any | null, stakingPoolActivationEpoch?: any | null, stakingPoolIotaBalance?: any | null, votingPower?: number | null, exchangeRates?: { __typename?: 'MoveObject', address: any, contents?: { __typename?: 'MoveValue', json: any } | null } | null, credentials?: { __typename?: 'ValidatorCredentials', netAddress?: string | null, networkPubKey?: any | null, p2PAddress?: string | null, primaryAddress?: string | null, workerPubKey?: any | null, workerAddress?: string | null, proofOfPossession?: any | null, protocolPubKey?: any | null } | null, nextEpochCredentials?: { __typename?: 'ValidatorCredentials', netAddress?: string | null, networkPubKey?: any | null, p2PAddress?: string | null, primaryAddress?: string | null, workerPubKey?: any | null, workerAddress?: string | null, proofOfPossession?: any | null, protocolPubKey?: any | null } | null, operationCap?: { __typename?: 'MoveObject', address: any } | null, stakingPool?: { __typename?: 'MoveObject', address: any } | null, address: { __typename?: 'Address', address: any } }> } } | null } | null }; +export type PaginateEpochValidatorsQuery = { __typename?: 'Query', epoch?: { __typename?: 'Epoch', validatorSet?: { __typename?: 'ValidatorSet', activeValidators: { __typename?: 'ValidatorConnection', pageInfo: { __typename?: 'PageInfo', hasNextPage: boolean, endCursor?: string | null }, nodes: Array<{ __typename?: 'Validator', atRisk?: any | null, commissionRate?: number | null, exchangeRatesSize?: any | null, description?: string | null, gasPrice?: any | null, imageUrl?: string | null, name?: string | null, nextEpochCommissionRate?: number | null, nextEpochGasPrice?: any | null, nextEpochStake?: any | null, pendingPoolTokenWithdraw?: any | null, pendingStake?: any | null, pendingTotalIotaWithdraw?: any | null, poolTokenBalance?: any | null, projectUrl?: string | null, rewardsPool?: any | null, stakingPoolActivationEpoch?: any | null, stakingPoolIotaBalance?: any | null, votingPower?: number | null, exchangeRates?: { __typename?: 'MoveObject', address: any, contents?: { __typename?: 'MoveValue', json: any } | null } | null, credentials?: { __typename?: 'ValidatorCredentials', netAddress?: string | null, networkPubKey?: any | null, p2PAddress?: string | null, primaryAddress?: string | null, authorityPubKey?: any | null, proofOfPossession?: any | null, protocolPubKey?: any | null } | null, nextEpochCredentials?: { __typename?: 'ValidatorCredentials', netAddress?: string | null, networkPubKey?: any | null, p2PAddress?: string | null, primaryAddress?: string | null, authorityPubKey?: any | null, proofOfPossession?: any | null, protocolPubKey?: any | null } | null, operationCap?: { __typename?: 'MoveObject', address: any } | null, stakingPool?: { __typename?: 'MoveObject', address: any } | null, address: { __typename?: 'Address', address: any } }> } } | null } | null }; -export type Rpc_Validator_FieldsFragment = { __typename?: 'Validator', atRisk?: any | null, commissionRate?: number | null, exchangeRatesSize?: any | null, description?: string | null, gasPrice?: any | null, imageUrl?: string | null, name?: string | null, nextEpochCommissionRate?: number | null, nextEpochGasPrice?: any | null, nextEpochStake?: any | null, pendingPoolTokenWithdraw?: any | null, pendingStake?: any | null, pendingTotalIotaWithdraw?: any | null, poolTokenBalance?: any | null, projectUrl?: string | null, rewardsPool?: any | null, stakingPoolActivationEpoch?: any | null, stakingPoolIotaBalance?: any | null, votingPower?: number | null, exchangeRates?: { __typename?: 'MoveObject', address: any, contents?: { __typename?: 'MoveValue', json: any } | null } | null, credentials?: { __typename?: 'ValidatorCredentials', netAddress?: string | null, networkPubKey?: any | null, p2PAddress?: string | null, primaryAddress?: string | null, workerPubKey?: any | null, workerAddress?: string | null, proofOfPossession?: any | null, protocolPubKey?: any | null } | null, nextEpochCredentials?: { __typename?: 'ValidatorCredentials', netAddress?: string | null, networkPubKey?: any | null, p2PAddress?: string | null, primaryAddress?: string | null, workerPubKey?: any | null, workerAddress?: string | null, proofOfPossession?: any | null, protocolPubKey?: any | null } | null, operationCap?: { __typename?: 'MoveObject', address: any } | null, stakingPool?: { __typename?: 'MoveObject', address: any } | null, address: { __typename?: 'Address', address: any } }; +export type Rpc_Validator_FieldsFragment = { __typename?: 'Validator', atRisk?: any | null, commissionRate?: number | null, exchangeRatesSize?: any | null, description?: string | null, gasPrice?: any | null, imageUrl?: string | null, name?: string | null, nextEpochCommissionRate?: number | null, nextEpochGasPrice?: any | null, nextEpochStake?: any | null, pendingPoolTokenWithdraw?: any | null, pendingStake?: any | null, pendingTotalIotaWithdraw?: any | null, poolTokenBalance?: any | null, projectUrl?: string | null, rewardsPool?: any | null, stakingPoolActivationEpoch?: any | null, stakingPoolIotaBalance?: any | null, votingPower?: number | null, exchangeRates?: { __typename?: 'MoveObject', address: any, contents?: { __typename?: 'MoveValue', json: any } | null } | null, credentials?: { __typename?: 'ValidatorCredentials', netAddress?: string | null, networkPubKey?: any | null, p2PAddress?: string | null, primaryAddress?: string | null, authorityPubKey?: any | null, proofOfPossession?: any | null, protocolPubKey?: any | null } | null, nextEpochCredentials?: { __typename?: 'ValidatorCredentials', netAddress?: string | null, networkPubKey?: any | null, p2PAddress?: string | null, primaryAddress?: string | null, authorityPubKey?: any | null, proofOfPossession?: any | null, protocolPubKey?: any | null } | null, operationCap?: { __typename?: 'MoveObject', address: any } | null, stakingPool?: { __typename?: 'MoveObject', address: any } | null, address: { __typename?: 'Address', address: any } }; -export type Rpc_Credential_FieldsFragment = { __typename?: 'ValidatorCredentials', netAddress?: string | null, networkPubKey?: any | null, p2PAddress?: string | null, primaryAddress?: string | null, workerPubKey?: any | null, workerAddress?: string | null, proofOfPossession?: any | null, protocolPubKey?: any | null }; +export type Rpc_Credential_FieldsFragment = { __typename?: 'ValidatorCredentials', netAddress?: string | null, networkPubKey?: any | null, p2PAddress?: string | null, primaryAddress?: string | null, authorityPubKey?: any | null, proofOfPossession?: any | null, protocolPubKey?: any | null }; export type GetTypeLayoutQueryVariables = Exact<{ type: Scalars['String']['input']; @@ -5306,7 +5305,7 @@ export type GetLatestCheckpointSequenceNumberQuery = { __typename?: 'Query', che export type GetLatestIotaSystemStateQueryVariables = Exact<{ [key: string]: never; }>; -export type GetLatestIotaSystemStateQuery = { __typename?: 'Query', epoch?: { __typename?: 'Epoch', epochId: any, startTimestamp: any, endTimestamp?: any | null, referenceGasPrice?: any | null, systemStateVersion?: any | null, iotaTotalSupply?: number | null, iotaTreasuryCapId?: any | null, safeMode?: { __typename?: 'SafeMode', enabled?: boolean | null, gasSummary?: { __typename?: 'GasCostSummary', computationCost?: any | null, nonRefundableStorageFee?: any | null, storageCost?: any | null, storageRebate?: any | null } | null } | null, storageFund?: { __typename?: 'StorageFund', nonRefundableBalance?: any | null, totalObjectStorageRebates?: any | null } | null, systemParameters?: { __typename?: 'SystemParameters', minValidatorCount?: number | null, maxValidatorCount?: number | null, minValidatorJoiningStake?: any | null, durationMs?: any | null, validatorLowStakeThreshold?: any | null, validatorLowStakeGracePeriod?: any | null, validatorVeryLowStakeThreshold?: any | null } | null, protocolConfigs: { __typename?: 'ProtocolConfigs', protocolVersion: any }, validatorSet?: { __typename?: 'ValidatorSet', inactivePoolsSize?: number | null, pendingActiveValidatorsSize?: number | null, stakingPoolMappingsSize?: number | null, validatorCandidatesSize?: number | null, pendingRemovals?: Array | null, totalStake?: any | null, stakingPoolMappingsId?: any | null, pendingActiveValidatorsId?: any | null, validatorCandidatesId?: any | null, inactivePoolsId?: any | null, activeValidators: { __typename?: 'ValidatorConnection', pageInfo: { __typename?: 'PageInfo', hasNextPage: boolean, endCursor?: string | null }, nodes: Array<{ __typename?: 'Validator', atRisk?: any | null, commissionRate?: number | null, exchangeRatesSize?: any | null, description?: string | null, gasPrice?: any | null, imageUrl?: string | null, name?: string | null, nextEpochCommissionRate?: number | null, nextEpochGasPrice?: any | null, nextEpochStake?: any | null, pendingPoolTokenWithdraw?: any | null, pendingStake?: any | null, pendingTotalIotaWithdraw?: any | null, poolTokenBalance?: any | null, projectUrl?: string | null, rewardsPool?: any | null, stakingPoolActivationEpoch?: any | null, stakingPoolIotaBalance?: any | null, votingPower?: number | null, exchangeRates?: { __typename?: 'MoveObject', address: any, contents?: { __typename?: 'MoveValue', json: any } | null } | null, credentials?: { __typename?: 'ValidatorCredentials', netAddress?: string | null, networkPubKey?: any | null, p2PAddress?: string | null, primaryAddress?: string | null, workerPubKey?: any | null, workerAddress?: string | null, proofOfPossession?: any | null, protocolPubKey?: any | null } | null, nextEpochCredentials?: { __typename?: 'ValidatorCredentials', netAddress?: string | null, networkPubKey?: any | null, p2PAddress?: string | null, primaryAddress?: string | null, workerPubKey?: any | null, workerAddress?: string | null, proofOfPossession?: any | null, protocolPubKey?: any | null } | null, operationCap?: { __typename?: 'MoveObject', address: any } | null, stakingPool?: { __typename?: 'MoveObject', address: any } | null, address: { __typename?: 'Address', address: any } }> } } | null } | null }; +export type GetLatestIotaSystemStateQuery = { __typename?: 'Query', epoch?: { __typename?: 'Epoch', epochId: any, startTimestamp: any, endTimestamp?: any | null, referenceGasPrice?: any | null, systemStateVersion?: any | null, iotaTotalSupply?: number | null, iotaTreasuryCapId?: any | null, safeMode?: { __typename?: 'SafeMode', enabled?: boolean | null, gasSummary?: { __typename?: 'GasCostSummary', computationCost?: any | null, nonRefundableStorageFee?: any | null, storageCost?: any | null, storageRebate?: any | null } | null } | null, storageFund?: { __typename?: 'StorageFund', nonRefundableBalance?: any | null, totalObjectStorageRebates?: any | null } | null, systemParameters?: { __typename?: 'SystemParameters', minValidatorCount?: number | null, maxValidatorCount?: number | null, minValidatorJoiningStake?: any | null, durationMs?: any | null, validatorLowStakeThreshold?: any | null, validatorLowStakeGracePeriod?: any | null, validatorVeryLowStakeThreshold?: any | null } | null, protocolConfigs: { __typename?: 'ProtocolConfigs', protocolVersion: any }, validatorSet?: { __typename?: 'ValidatorSet', inactivePoolsSize?: number | null, pendingActiveValidatorsSize?: number | null, stakingPoolMappingsSize?: number | null, validatorCandidatesSize?: number | null, pendingRemovals?: Array | null, totalStake?: any | null, stakingPoolMappingsId?: any | null, pendingActiveValidatorsId?: any | null, validatorCandidatesId?: any | null, inactivePoolsId?: any | null, activeValidators: { __typename?: 'ValidatorConnection', pageInfo: { __typename?: 'PageInfo', hasNextPage: boolean, endCursor?: string | null }, nodes: Array<{ __typename?: 'Validator', atRisk?: any | null, commissionRate?: number | null, exchangeRatesSize?: any | null, description?: string | null, gasPrice?: any | null, imageUrl?: string | null, name?: string | null, nextEpochCommissionRate?: number | null, nextEpochGasPrice?: any | null, nextEpochStake?: any | null, pendingPoolTokenWithdraw?: any | null, pendingStake?: any | null, pendingTotalIotaWithdraw?: any | null, poolTokenBalance?: any | null, projectUrl?: string | null, rewardsPool?: any | null, stakingPoolActivationEpoch?: any | null, stakingPoolIotaBalance?: any | null, votingPower?: number | null, exchangeRates?: { __typename?: 'MoveObject', address: any, contents?: { __typename?: 'MoveValue', json: any } | null } | null, credentials?: { __typename?: 'ValidatorCredentials', netAddress?: string | null, networkPubKey?: any | null, p2PAddress?: string | null, primaryAddress?: string | null, authorityPubKey?: any | null, proofOfPossession?: any | null, protocolPubKey?: any | null } | null, nextEpochCredentials?: { __typename?: 'ValidatorCredentials', netAddress?: string | null, networkPubKey?: any | null, p2PAddress?: string | null, primaryAddress?: string | null, authorityPubKey?: any | null, proofOfPossession?: any | null, protocolPubKey?: any | null } | null, operationCap?: { __typename?: 'MoveObject', address: any } | null, stakingPool?: { __typename?: 'MoveObject', address: any } | null, address: { __typename?: 'Address', address: any } }> } } | null } | null }; export type GetMoveFunctionArgTypesQueryVariables = Exact<{ packageId: Scalars['IotaAddress']['input']; @@ -5658,8 +5657,7 @@ export const Rpc_Credential_FieldsFragmentDoc = new TypedDocumentString(` networkPubKey p2PAddress primaryAddress - workerPubKey - workerAddress + authorityPubKey proofOfPossession protocolPubKey } @@ -5713,8 +5711,7 @@ export const Rpc_Validator_FieldsFragmentDoc = new TypedDocumentString(` networkPubKey p2PAddress primaryAddress - workerPubKey - workerAddress + authorityPubKey proofOfPossession protocolPubKey }`, {"fragmentName":"RPC_VALIDATOR_FIELDS"}) as unknown as TypedDocumentString; @@ -6789,7 +6786,7 @@ export const GetCommitteeInfoDocument = new TypedDocumentString(` } nodes { credentials { - protocolPubKey + authorityPubKey } votingPower } @@ -6872,8 +6869,7 @@ fragment RPC_CREDENTIAL_FIELDS on ValidatorCredentials { networkPubKey p2PAddress primaryAddress - workerPubKey - workerAddress + authorityPubKey proofOfPossession protocolPubKey }`) as unknown as TypedDocumentString; @@ -6941,8 +6937,7 @@ fragment RPC_CREDENTIAL_FIELDS on ValidatorCredentials { networkPubKey p2PAddress primaryAddress - workerPubKey - workerAddress + authorityPubKey proofOfPossession protocolPubKey }`) as unknown as TypedDocumentString; @@ -7153,8 +7148,7 @@ fragment RPC_CREDENTIAL_FIELDS on ValidatorCredentials { networkPubKey p2PAddress primaryAddress - workerPubKey - workerAddress + authorityPubKey proofOfPossession protocolPubKey }`) as unknown as TypedDocumentString; diff --git a/sdk/graphql-transport/src/mappers/validator.ts b/sdk/graphql-transport/src/mappers/validator.ts index 879ab64538a..1ff80a361ab 100644 --- a/sdk/graphql-transport/src/mappers/validator.ts +++ b/sdk/graphql-transport/src/mappers/validator.ts @@ -26,10 +26,9 @@ export function mapGraphQlValidatorToRpcValidator( nextEpochP2pAddress: validator.nextEpochCredentials?.p2PAddress, nextEpochPrimaryAddress: validator.nextEpochCredentials?.primaryAddress, nextEpochProofOfPossession: validator.nextEpochCredentials?.proofOfPossession, - nextEpochProtocolPubkeyBytes: validator.nextEpochCredentials?.protocolPubKey, + nextEpochAuthorityPubkeyBytes: validator.nextEpochCredentials?.authorityPubKey, nextEpochStake: validator.nextEpochStake!, - nextEpochWorkerAddress: validator.nextEpochCredentials?.workerAddress, - nextEpochWorkerPubkeyBytes: validator.nextEpochCredentials?.workerPubKey, + nextEpochProtocolPubkeyBytes: validator.nextEpochCredentials?.protocolPubKey, operationCapId: validator.operationCap?.address!, p2pAddress: validator.credentials?.p2PAddress!, pendingTotalIotaWithdraw: validator.pendingTotalIotaWithdraw, @@ -39,6 +38,7 @@ export function mapGraphQlValidatorToRpcValidator( primaryAddress: validator.credentials?.primaryAddress!, projectUrl: validator.projectUrl!, proofOfPossessionBytes: validator.credentials?.proofOfPossession, + authorityPubkeyBytes: validator.credentials?.authorityPubKey, protocolPubkeyBytes: validator.credentials?.protocolPubKey, rewardsPool: validator.rewardsPool, stakingPoolId: validator.stakingPool?.address!, @@ -46,7 +46,5 @@ export function mapGraphQlValidatorToRpcValidator( stakingPoolIotaBalance: validator.stakingPoolIotaBalance, iotaAddress: validator.address.address, votingPower: validator.votingPower?.toString()!, - workerAddress: validator.credentials?.workerAddress!, - workerPubkeyBytes: validator.credentials?.workerPubKey, }; } diff --git a/sdk/graphql-transport/src/methods.ts b/sdk/graphql-transport/src/methods.ts index ff1b23be313..67d420b43ce 100644 --- a/sdk/graphql-transport/src/methods.ts +++ b/sdk/graphql-transport/src/methods.ts @@ -1235,7 +1235,7 @@ export const RPC_METHODS: { return { epoch: epochId.toString(), validators: validatorSet?.activeValidators?.nodes.map((val) => [ - val.credentials?.protocolPubKey!, + val.credentials?.authorityPubKey!, String(val.votingPower), ])!, }; diff --git a/sdk/graphql-transport/src/queries/getCommitteeInfo.graphql b/sdk/graphql-transport/src/queries/getCommitteeInfo.graphql index e76f555374e..c3b40da6f58 100644 --- a/sdk/graphql-transport/src/queries/getCommitteeInfo.graphql +++ b/sdk/graphql-transport/src/queries/getCommitteeInfo.graphql @@ -13,7 +13,7 @@ query getCommitteeInfo($epochId: UInt53, $after: String) { } nodes { credentials { - protocolPubKey + authorityPubKey } votingPower } diff --git a/sdk/graphql-transport/src/queries/getCurrentEpoch.graphql b/sdk/graphql-transport/src/queries/getCurrentEpoch.graphql index e094a7082be..ffeaf181bd7 100644 --- a/sdk/graphql-transport/src/queries/getCurrentEpoch.graphql +++ b/sdk/graphql-transport/src/queries/getCurrentEpoch.graphql @@ -93,8 +93,7 @@ fragment RPC_CREDENTIAL_FIELDS on ValidatorCredentials { networkPubKey p2PAddress primaryAddress - workerPubKey - workerAddress + authorityPubKey proofOfPossession protocolPubKey } diff --git a/sdk/kiosk/src/client/kiosk-transaction.ts b/sdk/kiosk/src/client/kiosk-transaction.ts index 22a23d04cbb..b8b12d3aa95 100644 --- a/sdk/kiosk/src/client/kiosk-transaction.ts +++ b/sdk/kiosk/src/client/kiosk-transaction.ts @@ -153,7 +153,6 @@ export class KioskTransaction { /** * A function to borrow an item from a kiosk & execute any function with it. - * Example: You could borrow a Fren out of a kiosk, attach an accessory (or mix), and return it. */ borrowTx({ itemType, itemId }: ItemId, callback: (item: TransactionArgument) => void) { this.#validateKioskIsSet(); diff --git a/sdk/ledgerjs-hw-app-iota/package.json b/sdk/ledgerjs-hw-app-iota/package.json index bd26fd273ec..7287f13b396 100644 --- a/sdk/ledgerjs-hw-app-iota/package.json +++ b/sdk/ledgerjs-hw-app-iota/package.json @@ -66,8 +66,10 @@ "devDependencies": { "@iota/build-scripts": "workspace:*", "@ledgerhq/hw-transport-mocker": "^6.29.0", + "@ledgerhq/hw-transport-node-speculos-http": "^6.29.2", "@size-limit/preset-small-lib": "^11.1.4", "@types/node": "^20.14.10", + "axios": "^1.7.4", "size-limit": "^11.1.4", "typescript": "^5.5.3", "vitest": "^2.0.1" diff --git a/sdk/ledgerjs-hw-app-iota/tests/Iota.test.ts b/sdk/ledgerjs-hw-app-iota/tests/Iota.test.ts index d4d6386244b..e21666cb704 100644 --- a/sdk/ledgerjs-hw-app-iota/tests/Iota.test.ts +++ b/sdk/ledgerjs-hw-app-iota/tests/Iota.test.ts @@ -3,12 +3,134 @@ // SPDX-License-Identifier: Apache-2.0 import { openTransportReplayer, RecordStore } from '@ledgerhq/hw-transport-mocker'; -import { expect, test } from 'vitest'; - +import { describe, expect, it } from 'vitest'; +import SpeculosHttpTransport from '@ledgerhq/hw-transport-node-speculos-http'; +import Axios from 'axios'; import Iota from '../src/Iota'; -test('Iota init', async () => { - const transport = await openTransportReplayer(RecordStore.fromString('')); - const pkt = new Iota(transport); - expect(pkt).not.toBe(undefined); +const API_PORT: number = 5000; +const SPECULOS_BASE_URL: string = `http://127.0.0.1:${API_PORT}`; + +// Before running the tests you need to install speculos and start the iota app with it. +// If the binary is not available, download it: +// gh release download --repo https://github.com/iotaledger/ledger-app-iota -p nanos.tar.gz untagged-a706a550379839d8db15 +// tar -xvf nanos.tar.gz +// sudo apt-get install qemu-user-static libxcb-xinerama0 // might be needed for speculos to work +// pip install speculos +// Finally to start the emulator: +// speculos --api-port 5000 --display headless ./sdk/ledgerjs-hw-app-iota/tests/iota +describe.sequential('Test ledgerjs-hw-app-iota', () => { + it('Iota init', async () => { + const transport = await openTransportReplayer(RecordStore.fromString('')); + const pkt = new Iota(transport); + expect(pkt).not.toBe(undefined); + }); + + it('Test address generation', async () => { + const transport = await SpeculosHttpTransport.open({}); + const ledgerClient = new Iota(transport); + + const { publicKey } = await ledgerClient.getPublicKey(`m/44'/4218'/0'/0'/0'`); + + // Default speculos mnemonic: glory promote mansion idle axis finger extra february uncover one trip resource lawn turtle enact monster seven myth punch hobby comfort wild raise skin + expect(Buffer.from(publicKey).toString('hex')).toBe( + 'f0a9c612b7e69f1a114aa9189c1f32997d395d09d183368ddfd6d5dc49e34647', + ); + }); + + it('Test address generation with display', async () => { + const transport = await SpeculosHttpTransport.open({}); + const ledgerClient = new Iota(transport); + + let addressReceived = false; + ledgerClient + .getPublicKey(`m/44'/4218'/0'/0'/0'`, true) + .then(({ publicKey }) => { + // Default speculos mnemonic: glory promote mansion idle axis finger extra february uncover one trip resource lawn turtle enact monster seven myth punch hobby comfort wild raise skin + expect(Buffer.from(publicKey).toString('hex')).toBe( + 'f0a9c612b7e69f1a114aa9189c1f32997d395d09d183368ddfd6d5dc49e34647', + ); + addressReceived = true; + }) + .catch((err) => { + throw new Error(err); + }); + await new Promise((resolve) => setTimeout(resolve, 1000)); + // Send requests to approve the shown address + for (let i = 0; i < 6; i++) { + await Axios.post(SPECULOS_BASE_URL + '/button/right', { action: 'press-and-release' }); + } + await Axios.post(SPECULOS_BASE_URL + '/button/both', { action: 'press-and-release' }); + if (!addressReceived) { + throw new Error(`Didn't receive address in time`); + } + }); + + it('Test signing', { timeout: 10000 }, async () => { + const transport = await SpeculosHttpTransport.open({}); + const ledgerClient = new Iota(transport); + let signatureReceived = false; + ledgerClient + .signTransaction( + `m/44'/4218'/0'/0'/0'`, + '0000000000020008e803000000000000002021c22f952c8742b3156dfca5fc8278bd3ba7b209c81e26c4f44a9944259b03b50202000101000001010200000101006fb21feead027da4873295affd6c4f3618fe176fa2fbf3e7b5ef1d9463b31e2101cad8ac9d85be1fcb1ec3f5870a50004549f4f892856b70499ed1654201c4399984470b000000000020ec2f226e6647a523608dc52ccb9976720c51d60ebfeadc524ee870cdfd1f6b8c6fb21feead027da4873295affd6c4f3618fe176fa2fbf3e7b5ef1d9463b31e21e803000000000000404b4c000000000000', + ) + .then(({ signature }) => { + expect(Buffer.from(signature).toString('hex')).toBe( + '9aaa0b45f0aeef61b055fe5c76a9184e6d6b7b361ff77387bd9c43873b07e349300ab7dce9602bf59c287600cdb9b4ade00257c683de65b51f18aee4ed402e0c', + ); + signatureReceived = true; + }) + .catch((err) => { + throw new Error(err); + }); + await new Promise((resolve) => setTimeout(resolve, 500)); + // Send requests to approve the tx + for (let i = 0; i < 14; i++) { + await Axios.post(SPECULOS_BASE_URL + '/button/right', { action: 'press-and-release' }); + } + await Axios.post(SPECULOS_BASE_URL + '/button/both', { action: 'press-and-release' }); + await new Promise((resolve) => setTimeout(resolve, 2000)); + if (!signatureReceived) { + throw new Error(`Didn't receive signature in time`); + } + }); + + it('Test blind signing', { timeout: 10000 }, async () => { + // Enable blind signing + await Axios.post(SPECULOS_BASE_URL + '/button/right', { action: 'press-and-release' }); + await Axios.post(SPECULOS_BASE_URL + '/button/right', { action: 'press-and-release' }); + await Axios.post(SPECULOS_BASE_URL + '/button/both', { action: 'press-and-release' }); + await Axios.post(SPECULOS_BASE_URL + '/button/both', { action: 'press-and-release' }); + await Axios.post(SPECULOS_BASE_URL + '/button/right', { action: 'press-and-release' }); + await Axios.post(SPECULOS_BASE_URL + '/button/both', { action: 'press-and-release' }); + + const transport = await SpeculosHttpTransport.open({}); + const ledgerClient = new Iota(transport); + let signatureReceived = false; + ledgerClient + .signTransaction( + `m/44'/4218'/0'/0'/0'`, + '0000000000000000000000000000000000000000000000000000000000000000', + ) + .then(({ signature }) => { + expect(Buffer.from(signature).toString('hex')).toBe( + 'c05235724452fd33c4df3558117f47ca807a9bd70750022d414f96790d3ec1c7e08a0c12b52972edd68f535f040357c20ea226d6d06f09e670f008916395c003', + ); + signatureReceived = true; + }) + .catch((err) => { + throw new Error(err); + }); + await new Promise((resolve) => setTimeout(resolve, 500)); + // Send requests to approve the tx + for (let i = 0; i < 8; i++) { + await Axios.post(SPECULOS_BASE_URL + '/button/right', { action: 'press-and-release' }); + } + await Axios.post(SPECULOS_BASE_URL + '/button/both', { action: 'press-and-release' }); + await new Promise((resolve) => setTimeout(resolve, 2000)); + if (!signatureReceived) { + throw new Error(`Didn't receive signature in time`); + } + }); }); diff --git a/sdk/move-bytecode-template/Cargo.lock b/sdk/move-bytecode-template/Cargo.lock index 4428821940d..2ecfe3668cb 100644 --- a/sdk/move-bytecode-template/Cargo.lock +++ b/sdk/move-bytecode-template/Cargo.lock @@ -32,9 +32,9 @@ dependencies = [ [[package]] name = "bitvec" -version = "1.0.1" +version = "0.20.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" +checksum = "7774144344a4faa177370406a7ff5f1da24303817368584c6206c8303eb07848" dependencies = [ "funty", "radium", @@ -93,9 +93,9 @@ checksum = "b90ca2580b73ab6a1f724b76ca11ab632df820fd6040c336200d2c1df7b3c82c" [[package]] name = "fixed-hash" -version = "0.8.0" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "835c052cb0c08c1acf6ffd71c022172e18723949c8282f2b9f27efbc51e64534" +checksum = "cfcf0ed7fe52a17a03854ec54a9f76d6d84508d1c0e66bc1793301c73fc8493c" dependencies = [ "byteorder", "rand", @@ -105,9 +105,9 @@ dependencies = [ [[package]] name = "funty" -version = "2.0.0" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" +checksum = "fed34cd105917e91daa4da6b3728c47b068749d6a62c59811f06ed2ac71d9da7" [[package]] name = "getrandom" @@ -122,6 +122,12 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + [[package]] name = "hashbrown" version = "0.14.5" @@ -136,18 +142,18 @@ checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" [[package]] name = "impl-codec" -version = "0.6.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba6a270039626615617f3f36d15fc827041df3b78c439da2cadfa47455a77f2f" +checksum = "161ebdfec3c8e3b52bf61c4f3550a1eea4f9579d10dc1b936f3171ebdcd6c443" dependencies = [ "parity-scale-codec", ] [[package]] name = "impl-serde" -version = "0.4.0" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebc88fc67028ae3db0c853baa36269d398d5f45b6982f95549ff5def78c935cd" +checksum = "4551f042f3438e64dbd6226b20527fc84a6e1fe65688b58746a2f53623f25f5c" dependencies = [ "serde", ] @@ -163,6 +169,16 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", +] + [[package]] name = "indexmap" version = "2.3.0" @@ -170,7 +186,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "de3fc2e30ba82dd1b3911c8de1ffc143c74a914a14e99514d7637e3099df5ea0" dependencies = [ "equivalent", - "hashbrown", + "hashbrown 0.14.5", ] [[package]] @@ -200,6 +216,12 @@ version = "0.2.155" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" +[[package]] +name = "linked-hash-map" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" + [[package]] name = "log" version = "0.4.22" @@ -350,9 +372,9 @@ checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "parity-scale-codec" -version = "3.6.12" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "306800abfa29c7f16596b5970a588435e3d5b3149683d00c12b699cc19f895ee" +checksum = "373b1a4c1338d9cd3d1fa53b3a11bdab5ab6bd80a20f7f7becd76953ae2be909" dependencies = [ "arrayvec", "bitvec", @@ -364,9 +386,9 @@ dependencies = [ [[package]] name = "parity-scale-codec-derive" -version = "3.6.12" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d830939c76d294956402033aee57a6da7b438f2294eb94864c37b0569053a42c" +checksum = "1557010476e0595c9b568d16dcfb81b93cdeb157612726f5170d31aa707bed27" dependencies = [ "proc-macro-crate", "proc-macro2", @@ -385,9 +407,9 @@ dependencies = [ [[package]] name = "primitive-types" -version = "0.12.2" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b34d9fd68ae0b74a41b21c03c2f62847aa0ffea044eee893b4c140b37e244e2" +checksum = "05e4722c697a58a99d5d06a08c30821d7c082a4632198de1eaa5a6c22ef42373" dependencies = [ "fixed-hash", "impl-codec", @@ -397,10 +419,11 @@ dependencies = [ [[package]] name = "proc-macro-crate" -version = "3.1.0" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284" +checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" dependencies = [ + "once_cell", "toml_edit", ] @@ -424,9 +447,9 @@ dependencies = [ [[package]] name = "radium" -version = "0.7.0" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" +checksum = "643f8f41a8ebc4c5dc4515c82bb8abd397b527fc20fd681b7c011c2aee5d44fb" [[package]] name = "rand" @@ -544,15 +567,14 @@ dependencies = [ [[package]] name = "serde_yaml" -version = "0.9.34+deprecated" +version = "0.8.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" +checksum = "578a7433b776b56a35785ed5ce9a7e777ac0598aac5a6dd1b4b18a307c7fc71b" dependencies = [ - "indexmap", - "itoa", + "indexmap 1.9.3", "ryu", "serde", - "unsafe-libyaml", + "yaml-rust", ] [[package]] @@ -617,11 +639,11 @@ checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" [[package]] name = "toml_edit" -version = "0.21.1" +version = "0.19.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" +checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" dependencies = [ - "indexmap", + "indexmap 2.3.0", "toml_datetime", "winnow", ] @@ -644,12 +666,6 @@ version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" -[[package]] -name = "unsafe-libyaml" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" - [[package]] name = "variant_count" version = "1.1.0" @@ -731,11 +747,17 @@ dependencies = [ [[package]] name = "wyz" -version = "0.5.1" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +checksum = "85e60b0d1b5f99db2556934e21937020776a5d31520bf169e851ac44e6420214" + +[[package]] +name = "yaml-rust" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85" dependencies = [ - "tap", + "linked-hash-map", ] [[package]] diff --git a/sdk/move-bytecode-template/README.md b/sdk/move-bytecode-template/README.md index 08d7d62a92f..030e17e0fed 100644 --- a/sdk/move-bytecode-template/README.md +++ b/sdk/move-bytecode-template/README.md @@ -18,9 +18,6 @@ This package is a perfect fit for the following applications: ## Example of a Template Module -The following code is a close-copy of the `Coin` example from the -[Move by Example](https://examples.iota.io/samples/coin.html) book. - ```move module 0x0::template { use std::option; diff --git a/sdk/move-bytecode-template/tests/universal.test.ts b/sdk/move-bytecode-template/tests/universal.test.ts index 05fc7197bf5..97e54ecd158 100644 --- a/sdk/move-bytecode-template/tests/universal.test.ts +++ b/sdk/move-bytecode-template/tests/universal.test.ts @@ -22,18 +22,12 @@ describe('move-binary-template', () => { it('should update identifiers', () => { const patched = template.update_identifiers(pokemonBytes(), { - Stats: 'PokeStats', - pokemon_v1: 'capymon', - new: 'capy_new', - speed: 'capy_speed', + Stats: 'IotaStats', }); const de = template.deserialize(patched); - expect(de.identifiers.includes('PokeStats')).toBeTruthy(); - expect(de.identifiers.includes('capymon')).toBeTruthy(); - expect(de.identifiers.includes('capy_new')).toBeTruthy(); - expect(de.identifiers.includes('capy_speed')).toBeTruthy(); + expect(de.identifiers.includes('IotaStats')).toBeTruthy(); }); it('should update constants', () => { diff --git a/sdk/typescript/README.md b/sdk/typescript/README.md index 6f2982f483b..e0c0ff6b387 100644 --- a/sdk/typescript/README.md +++ b/sdk/typescript/README.md @@ -101,7 +101,7 @@ https://stackoverflow.com/questions/52676244/node-version-not-updating-after-nvm To run E2E tests against Devnet ``` -VITE_FAUCET_URL='https://faucet.devnet.iota.io:443/gas' VITE_FULLNODE_URL='https://fullnode.devnet.iota.io' pnpm --filter @iota/iota-sdk exec vitest e2e +VITE_FAUCET_URL='https://faucet.devnet.iota.org:443/gas' VITE_FULLNODE_URL='https://fullnode.devnet.iota.org' pnpm --filter @iota/iota-sdk exec vitest e2e ``` ## Connecting to IOTA Network @@ -110,7 +110,7 @@ The `IotaClient` class provides a connection to the JSON-RPC Server and should b read-only operations. The default URLs to connect with the RPC server are: - local: http://127.0.0.1:9000 -- Devnet: https://fullnode.devnet.iota.io +- Devnet: https://fullnode.devnet.iota.org ```typescript import { getFullnodeUrl, IotaClient } from '@iota/iota-sdk/client'; @@ -147,7 +147,7 @@ import { getFullnodeUrl, IotaClient } from '@iota/iota-sdk/client'; // create a client connected to devnet const client = new IotaClient({ - url: 'https://fullnode.devnet.iota.io', + url: 'https://fullnode.devnet.iota.org', }); // get coins owned by an address diff --git a/sdk/typescript/package.json b/sdk/typescript/package.json index 6780c483cb1..369f083c220 100644 --- a/sdk/typescript/package.json +++ b/sdk/typescript/package.json @@ -102,9 +102,8 @@ "eslint:fix": "pnpm run eslint:check --fix", "lint": "pnpm run eslint:check && pnpm run prettier:check", "lint:fix": "pnpm run eslint:fix && pnpm run prettier:fix", - "update-graphql-schema": "pnpm run generate-schema -c src/graphql/generated/2024.10/tsconfig.tada.json", "update-graphql-schemas": "pnpm tsx scripts/update-graphql-schemas.ts", - "update-open-rpc-schema": "pnpm tsx scripts/generate.ts", + "update-open-rpc-client-types": "pnpm tsx scripts/generate.ts", "generate-schema": "gql.tada generate-output" }, "bugs": { diff --git a/sdk/typescript/scripts/generate-schema-lib.ts b/sdk/typescript/scripts/generate-schema-lib.ts new file mode 100644 index 00000000000..3920f25be5f --- /dev/null +++ b/sdk/typescript/scripts/generate-schema-lib.ts @@ -0,0 +1,77 @@ +// Copyright (c) Mysten Labs, Inc. +// Modifications Copyright (c) 2024 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +import { execSync } from 'child_process'; +import { readFile, writeFile } from 'node:fs/promises'; +import { resolve } from 'node:path'; + +// creates the schema tsconfig file in the respective target folder +export async function createSchemaTsConfigFile(targetFolder: string, minorVersion: string) { + // create tsconfig.tada.json + await writeFile( + resolve(targetFolder, 'tsconfig.tada.json'), + ` +{ + "compilerOptions": { + "plugins": [ + { + "name": "gql.tada/ts-plugin", + "schema": "./schema.graphql", + "tadaOutputLocation": "src/graphql/generated/${minorVersion}/tada-env.d.ts" + } + ] + } +}`.trimStart(), + ); +} + +// generates the schema in the respective target folder by running `pnpm run generate-schema` +export async function generateSchema(targetFolder: string) { + const filePath = resolve(targetFolder, 'tsconfig.tada.json'); + + execSync(`pnpm run generate-schema -c ${filePath}`); +} + +// creates the schema index file in the respective target folder +export async function createSchemaIndexFile(targetFolder: string, minorVersion: string) { + // create index.ts + await writeFile( + resolve(targetFolder, 'index.ts'), + ` +// Copyright (c) Mysten Labs, Inc. +// Modifications Copyright (c) 2024 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +import { initGraphQLTada } from 'gql.tada'; + +import type { introspection } from '../../generated/${minorVersion}/tada-env.js'; +import type { CustomScalars } from '../../types.js'; + +export * from '../../types.js'; + +export type { FragmentOf, ResultOf, VariablesOf, TadaDocumentNode } from 'gql.tada'; +export { readFragment, maskFragments } from 'gql.tada'; + +export const graphql = initGraphQLTada<{ + introspection: introspection; + scalars: CustomScalars; +}>(); +`.trimStart(), + ); +} + +// adds the exports to the package.json file +export async function addExportsToPackageJson(packageRoot: string, versions: string[]) { + const packageJsonPath = resolve(packageRoot, 'package.json'); + const packageJson = JSON.parse(await readFile(packageJsonPath, 'utf-8')); + + for (const version of versions) { + packageJson.exports[`./graphql/schemas/${version}`] = { + import: `./dist/esm/graphql/schemas/${version}/index.js`, + require: `./dist/cjs/graphql/schemas/${version}/index.js`, + }; + } + + await writeFile(packageJsonPath, `${JSON.stringify(packageJson, null, ' ')}\n`); +} diff --git a/sdk/typescript/scripts/update-graphql-schemas.ts b/sdk/typescript/scripts/update-graphql-schemas.ts index aad87c70ec0..32f39183f80 100644 --- a/sdk/typescript/scripts/update-graphql-schemas.ts +++ b/sdk/typescript/scripts/update-graphql-schemas.ts @@ -2,10 +2,15 @@ // Modifications Copyright (c) 2024 IOTA Stiftung // SPDX-License-Identifier: Apache-2.0 -import { execSync } from 'child_process'; -import { readFile } from 'fs/promises'; -import { mkdir, writeFile } from 'node:fs/promises'; +import { mkdir } from 'node:fs/promises'; +import { copyFile } from 'node:fs'; import path, { resolve } from 'node:path'; +import { + createSchemaTsConfigFile, + generateSchema, + createSchemaIndexFile, + addExportsToPackageJson, +} from './generate-schema-lib.js'; const BRANCH = 'develop'; const MAJOR = 2024; @@ -26,81 +31,37 @@ const releases = [ }, ]; -for (const { minorVersion } of releases.values()) { - const packageRoot = path.resolve(import.meta.url.slice(5), '../..'); - - const schema = await readFile( - path.resolve(packageRoot, '../../crates/iota-graphql-rpc/schema.graphql'), - 'utf-8', - ); - - const filePath = resolve( - import.meta.url.slice(5), - `../../src/graphql/generated/${minorVersion}/schema.graphql`, - ); +const packageRoot = path.resolve(import.meta.url.slice(5), '../..'); +const workspaceRoot = path.resolve(packageRoot, '../..'); +const schemaSourceFilePath = path.resolve( + workspaceRoot, + 'crates/iota-graphql-rpc', + 'schema.graphql', +); - await mkdir(resolve(filePath, '..'), { recursive: true }); - await writeFile(filePath, schema); - - await writeFile( - resolve(filePath, '..', 'tsconfig.tada.json'), - ` -{ - "compilerOptions": { - "plugins": [ - { - "name": "@0no-co/graphqlsp", - "schema": "./schema.graphql", - "tadaOutputLocation": "src/graphql/generated/${minorVersion}/tada-env.d.ts" - } - ] - } -} -`.trimStart(), +for (const { minorVersion } of releases.values()) { + const targetFolderGenerated = path.resolve( + packageRoot, + `src/graphql/generated/${minorVersion}/`, ); + const targetFolderSchemas = resolve(packageRoot, `src/graphql/schemas/${minorVersion}/`); - execSync(`pnpm run generate-schema -c ${resolve(filePath, '..', 'tsconfig.tada.json')}`); - - await mkdir(resolve(filePath, '../../../schemas', minorVersion), { recursive: true }); - await writeFile( - resolve(filePath, `../../../schemas/${minorVersion}/index.ts`), - ` -// Copyright (c) Mysten Labs, Inc. -// Modifications Copyright (c) 2024 IOTA Stiftung -// SPDX-License-Identifier: Apache-2.0 - -import { initGraphQLTada } from 'gql.tada'; - -import type { introspection } from '../../generated/${minorVersion}/tada-env.js'; -import type { CustomScalars } from '../../types.js'; - -export * from '../../types.js'; + // create target folders + await mkdir(targetFolderGenerated, { recursive: true }); + await mkdir(targetFolderSchemas, { recursive: true }); -export type { FragmentOf, ResultOf, VariablesOf, TadaDocumentNode } from 'gql.tada'; -export { readFragment, maskFragments } from 'gql.tada'; + // copy the schema file to the target folder + copyFile(schemaSourceFilePath, resolve(targetFolderGenerated, 'schema.graphql'), (err) => { + if (err) throw err; + }); -export const graphql = initGraphQLTada<{ - introspection: introspection; - scalars: CustomScalars; -}>(); -`.trimStart(), - ); + // create additional files per version + await createSchemaTsConfigFile(targetFolderGenerated, minorVersion); + await generateSchema(targetFolderGenerated); + await createSchemaIndexFile(targetFolderSchemas, minorVersion); } const releaseVersions = releases.map(({ minorVersion }) => minorVersion); -await addExportsToPackageJson(releaseVersions); - -async function addExportsToPackageJson(versions: string[]) { - const packageJsonPath = resolve(import.meta.url.slice(5), '../../package.json'); - const packageJson = JSON.parse(await readFile(packageJsonPath, 'utf-8')); - - for (const version of versions) { - packageJson.exports[`./graphql/schemas/${version}`] = { - import: `./dist/esm/graphql/schemas/${version}/index.js`, - require: `./dist/cjs/graphql/schemas/${version}/index.js`, - }; - } - - await writeFile(packageJsonPath, `${JSON.stringify(packageJson, null, ' ')}\n`); -} +// add exports to package.json +await addExportsToPackageJson(packageRoot, releaseVersions); diff --git a/sdk/typescript/src/client/types/generated.ts b/sdk/typescript/src/client/types/generated.ts index 002decccf4e..a8a48b0e2a6 100644 --- a/sdk/typescript/src/client/types/generated.ts +++ b/sdk/typescript/src/client/types/generated.ts @@ -800,6 +800,7 @@ export type IotaTransactionBlockBuilderMode = 'Commit' | 'DevInspect'; * fields so that they are decoupled from the internal definitions. */ export interface IotaValidatorSummary { + authorityPubkeyBytes: string; commissionRate: string; description: string; /** ID of the exchange rate table object. */ @@ -812,6 +813,7 @@ export interface IotaValidatorSummary { name: string; netAddress: string; networkPubkeyBytes: string; + nextEpochAuthorityPubkeyBytes?: string | null; nextEpochCommissionRate: string; nextEpochGasPrice: string; nextEpochNetAddress?: string | null; @@ -821,8 +823,6 @@ export interface IotaValidatorSummary { nextEpochProofOfPossession?: string | null; nextEpochProtocolPubkeyBytes?: string | null; nextEpochStake: string; - nextEpochWorkerAddress?: string | null; - nextEpochWorkerPubkeyBytes?: string | null; operationCapId: string; p2pAddress: string; /** Pending pool token withdrawn during the current epoch, emptied at epoch boundaries. */ @@ -848,8 +848,6 @@ export interface IotaValidatorSummary { /** The total number of IOTA tokens in this pool. */ stakingPoolIotaBalance: string; votingPower: string; - workerAddress: string; - workerPubkeyBytes: string; } export interface MoveCallMetrics { /** The count of calls of each function in the last 30 days. */ @@ -1114,7 +1112,7 @@ export type ObjectResponseError = code: 'unknown'; } | { - code: 'displayError'; + code: 'display'; error: string; }; export interface IotaObjectResponseQuery { diff --git a/sdk/typescript/src/graphql/generated/2024.10/schema.graphql b/sdk/typescript/src/graphql/generated/2024.10/schema.graphql index 4a94721baf3..fba63a69734 100644 --- a/sdk/typescript/src/graphql/generated/2024.10/schema.graphql +++ b/sdk/typescript/src/graphql/generated/2024.10/schema.graphql @@ -4511,14 +4511,13 @@ type ValidatorConnection { The credentials related fields associated with a validator. """ type ValidatorCredentials { - protocolPubKey: Base64 + authorityPubKey: Base64 networkPubKey: Base64 - workerPubKey: Base64 + protocolPubKey: Base64 proofOfPossession: Base64 netAddress: String p2PAddress: String primaryAddress: String - workerAddress: String } """ diff --git a/sdk/typescript/src/graphql/generated/2024.10/tada-env.d.ts b/sdk/typescript/src/graphql/generated/2024.10/tada-env.d.ts index aaa947644f0..4fd806a8aa2 100644 --- a/sdk/typescript/src/graphql/generated/2024.10/tada-env.d.ts +++ b/sdk/typescript/src/graphql/generated/2024.10/tada-env.d.ts @@ -179,7 +179,7 @@ export type introspection_types = { 'UpgradeTransaction': { kind: 'OBJECT'; name: 'UpgradeTransaction'; fields: { 'currentPackage': { name: 'currentPackage'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'IotaAddress'; ofType: null; }; } }; 'dependencies': { name: 'dependencies'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'LIST'; name: never; ofType: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'IotaAddress'; ofType: null; }; }; }; } }; 'modules': { name: 'modules'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'LIST'; name: never; ofType: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Base64'; ofType: null; }; }; }; } }; 'upgradeTicket': { name: 'upgradeTicket'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'UNION'; name: 'TransactionArgument'; ofType: null; }; } }; }; }; 'Validator': { kind: 'OBJECT'; name: 'Validator'; fields: { 'address': { name: 'address'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'Address'; ofType: null; }; } }; 'apy': { name: 'apy'; type: { kind: 'SCALAR'; name: 'Int'; ofType: null; } }; 'atRisk': { name: 'atRisk'; type: { kind: 'SCALAR'; name: 'UInt53'; ofType: null; } }; 'commissionRate': { name: 'commissionRate'; type: { kind: 'SCALAR'; name: 'Int'; ofType: null; } }; 'credentials': { name: 'credentials'; type: { kind: 'OBJECT'; name: 'ValidatorCredentials'; ofType: null; } }; 'description': { name: 'description'; type: { kind: 'SCALAR'; name: 'String'; ofType: null; } }; 'exchangeRates': { name: 'exchangeRates'; type: { kind: 'OBJECT'; name: 'MoveObject'; ofType: null; } }; 'exchangeRatesSize': { name: 'exchangeRatesSize'; type: { kind: 'SCALAR'; name: 'UInt53'; ofType: null; } }; 'exchangeRatesTable': { name: 'exchangeRatesTable'; type: { kind: 'OBJECT'; name: 'Owner'; ofType: null; } }; 'gasPrice': { name: 'gasPrice'; type: { kind: 'SCALAR'; name: 'BigInt'; ofType: null; } }; 'imageUrl': { name: 'imageUrl'; type: { kind: 'SCALAR'; name: 'String'; ofType: null; } }; 'name': { name: 'name'; type: { kind: 'SCALAR'; name: 'String'; ofType: null; } }; 'nextEpochCommissionRate': { name: 'nextEpochCommissionRate'; type: { kind: 'SCALAR'; name: 'Int'; ofType: null; } }; 'nextEpochCredentials': { name: 'nextEpochCredentials'; type: { kind: 'OBJECT'; name: 'ValidatorCredentials'; ofType: null; } }; 'nextEpochGasPrice': { name: 'nextEpochGasPrice'; type: { kind: 'SCALAR'; name: 'BigInt'; ofType: null; } }; 'nextEpochStake': { name: 'nextEpochStake'; type: { kind: 'SCALAR'; name: 'BigInt'; ofType: null; } }; 'operationCap': { name: 'operationCap'; type: { kind: 'OBJECT'; name: 'MoveObject'; ofType: null; } }; 'pendingPoolTokenWithdraw': { name: 'pendingPoolTokenWithdraw'; type: { kind: 'SCALAR'; name: 'BigInt'; ofType: null; } }; 'pendingStake': { name: 'pendingStake'; type: { kind: 'SCALAR'; name: 'BigInt'; ofType: null; } }; 'pendingTotalIotaWithdraw': { name: 'pendingTotalIotaWithdraw'; type: { kind: 'SCALAR'; name: 'BigInt'; ofType: null; } }; 'poolTokenBalance': { name: 'poolTokenBalance'; type: { kind: 'SCALAR'; name: 'BigInt'; ofType: null; } }; 'projectUrl': { name: 'projectUrl'; type: { kind: 'SCALAR'; name: 'String'; ofType: null; } }; 'reportRecords': { name: 'reportRecords'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'AddressConnection'; ofType: null; }; } }; 'rewardsPool': { name: 'rewardsPool'; type: { kind: 'SCALAR'; name: 'BigInt'; ofType: null; } }; 'stakingPool': { name: 'stakingPool'; type: { kind: 'OBJECT'; name: 'MoveObject'; ofType: null; } }; 'stakingPoolActivationEpoch': { name: 'stakingPoolActivationEpoch'; type: { kind: 'SCALAR'; name: 'UInt53'; ofType: null; } }; 'stakingPoolId': { name: 'stakingPoolId'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'IotaAddress'; ofType: null; }; } }; 'stakingPoolIotaBalance': { name: 'stakingPoolIotaBalance'; type: { kind: 'SCALAR'; name: 'BigInt'; ofType: null; } }; 'votingPower': { name: 'votingPower'; type: { kind: 'SCALAR'; name: 'Int'; ofType: null; } }; }; }; 'ValidatorConnection': { kind: 'OBJECT'; name: 'ValidatorConnection'; fields: { 'edges': { name: 'edges'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'LIST'; name: never; ofType: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'ValidatorEdge'; ofType: null; }; }; }; } }; 'nodes': { name: 'nodes'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'LIST'; name: never; ofType: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'Validator'; ofType: null; }; }; }; } }; 'pageInfo': { name: 'pageInfo'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'PageInfo'; ofType: null; }; } }; }; }; - 'ValidatorCredentials': { kind: 'OBJECT'; name: 'ValidatorCredentials'; fields: { 'netAddress': { name: 'netAddress'; type: { kind: 'SCALAR'; name: 'String'; ofType: null; } }; 'networkPubKey': { name: 'networkPubKey'; type: { kind: 'SCALAR'; name: 'Base64'; ofType: null; } }; 'p2PAddress': { name: 'p2PAddress'; type: { kind: 'SCALAR'; name: 'String'; ofType: null; } }; 'primaryAddress': { name: 'primaryAddress'; type: { kind: 'SCALAR'; name: 'String'; ofType: null; } }; 'proofOfPossession': { name: 'proofOfPossession'; type: { kind: 'SCALAR'; name: 'Base64'; ofType: null; } }; 'protocolPubKey': { name: 'protocolPubKey'; type: { kind: 'SCALAR'; name: 'Base64'; ofType: null; } }; 'workerAddress': { name: 'workerAddress'; type: { kind: 'SCALAR'; name: 'String'; ofType: null; } }; 'workerPubKey': { name: 'workerPubKey'; type: { kind: 'SCALAR'; name: 'Base64'; ofType: null; } }; }; }; + 'ValidatorCredentials': { kind: 'OBJECT'; name: 'ValidatorCredentials'; fields: { 'authorityPubKey': { name: 'authorityPubKey'; type: { kind: 'SCALAR'; name: 'Base64'; ofType: null; } }; 'netAddress': { name: 'netAddress'; type: { kind: 'SCALAR'; name: 'String'; ofType: null; } }; 'networkPubKey': { name: 'networkPubKey'; type: { kind: 'SCALAR'; name: 'Base64'; ofType: null; } }; 'p2PAddress': { name: 'p2PAddress'; type: { kind: 'SCALAR'; name: 'String'; ofType: null; } }; 'primaryAddress': { name: 'primaryAddress'; type: { kind: 'SCALAR'; name: 'String'; ofType: null; } }; 'proofOfPossession': { name: 'proofOfPossession'; type: { kind: 'SCALAR'; name: 'Base64'; ofType: null; } }; 'protocolPubKey': { name: 'protocolPubKey'; type: { kind: 'SCALAR'; name: 'Base64'; ofType: null; } }; }; }; 'ValidatorEdge': { kind: 'OBJECT'; name: 'ValidatorEdge'; fields: { 'cursor': { name: 'cursor'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'String'; ofType: null; }; } }; 'node': { name: 'node'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'Validator'; ofType: null; }; } }; }; }; 'ValidatorSet': { kind: 'OBJECT'; name: 'ValidatorSet'; fields: { 'activeValidators': { name: 'activeValidators'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'ValidatorConnection'; ofType: null; }; } }; 'inactivePoolsId': { name: 'inactivePoolsId'; type: { kind: 'SCALAR'; name: 'IotaAddress'; ofType: null; } }; 'inactivePoolsSize': { name: 'inactivePoolsSize'; type: { kind: 'SCALAR'; name: 'Int'; ofType: null; } }; 'pendingActiveValidatorsId': { name: 'pendingActiveValidatorsId'; type: { kind: 'SCALAR'; name: 'IotaAddress'; ofType: null; } }; 'pendingActiveValidatorsSize': { name: 'pendingActiveValidatorsSize'; type: { kind: 'SCALAR'; name: 'Int'; ofType: null; } }; 'pendingRemovals': { name: 'pendingRemovals'; type: { kind: 'LIST'; name: never; ofType: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Int'; ofType: null; }; }; } }; 'stakingPoolMappingsId': { name: 'stakingPoolMappingsId'; type: { kind: 'SCALAR'; name: 'IotaAddress'; ofType: null; } }; 'stakingPoolMappingsSize': { name: 'stakingPoolMappingsSize'; type: { kind: 'SCALAR'; name: 'Int'; ofType: null; } }; 'totalStake': { name: 'totalStake'; type: { kind: 'SCALAR'; name: 'BigInt'; ofType: null; } }; 'validatorCandidatesId': { name: 'validatorCandidatesId'; type: { kind: 'SCALAR'; name: 'IotaAddress'; ofType: null; } }; 'validatorCandidatesSize': { name: 'validatorCandidatesSize'; type: { kind: 'SCALAR'; name: 'Int'; ofType: null; } }; }; }; 'ZkLoginIntentScope': { name: 'ZkLoginIntentScope'; enumValues: 'TRANSACTION_DATA' | 'PERSONAL_MESSAGE'; }; diff --git a/sdk/typescript/src/transactions/__tests__/bcs.test.ts b/sdk/typescript/src/transactions/__tests__/bcs.test.ts index afb7c9570a0..b3cebb240da 100644 --- a/sdk/typescript/src/transactions/__tests__/bcs.test.ts +++ b/sdk/typescript/src/transactions/__tests__/bcs.test.ts @@ -14,7 +14,7 @@ it('can serialize simplified programmable call struct', () => { package: '0x2', module: 'display', function: 'new', - typeArguments: [normalizeStructTag('0x6::capy::Capy')], + typeArguments: [normalizeStructTag('0x6::iota::IOTA')], arguments: [ { $kind: 'GasCoin', @@ -104,9 +104,9 @@ it('can serialize transaction data with a programmable transaction', () => { bytes: bcs .vector(bcs.String) .serialize([ - 'Capy {name}', - 'A cute little creature', - 'https://api.capy.art/{id}/svg', + '{name}', + '{description}', + 'https://api.iota.org/{id}/svg', ]) .toBase64(), }, @@ -126,7 +126,7 @@ it('can serialize transaction data with a programmable transaction', () => { package: iota, module: 'display', function: 'new', - typeArguments: [`${iota}::capy::Capy`], + typeArguments: [`${iota}::iota::IOTA`], arguments: [ // publisher object { @@ -142,7 +142,7 @@ it('can serialize transaction data with a programmable transaction', () => { package: iota, module: 'display', function: 'add_multiple', - typeArguments: [`${iota}::capy::Capy`], + typeArguments: [`${iota}::iota::IOTA`], arguments: [ // result of the first transaction { @@ -168,7 +168,7 @@ it('can serialize transaction data with a programmable transaction', () => { package: iota, module: 'display', function: 'update_version', - typeArguments: [`${iota}::capy::Capy`], + typeArguments: [`${iota}::iota::IOTA`], arguments: [ // result of the first transaction again { diff --git a/sdk/typescript/test/e2e/coin-metadata.test.ts b/sdk/typescript/test/e2e/coin-metadata.test.ts index d0ac0fa3d80..fa9f69bd06a 100644 --- a/sdk/typescript/test/e2e/coin-metadata.test.ts +++ b/sdk/typescript/test/e2e/coin-metadata.test.ts @@ -24,6 +24,6 @@ describe('Test Coin Metadata', () => { expect(coinMetadata.decimals).to.equal(2); expect(coinMetadata.name).to.equal('Test Coin'); expect(coinMetadata.description).to.equal('Test coin metadata'); - expect(coinMetadata.iconUrl).to.equal('http://iota.io'); + expect(coinMetadata.iconUrl).to.equal('http://iota.org'); }); }); diff --git a/sdk/typescript/test/e2e/data/coin_metadata/sources/coin_metadata.move b/sdk/typescript/test/e2e/data/coin_metadata/sources/coin_metadata.move index bc1139196a1..e9668264600 100644 --- a/sdk/typescript/test/e2e/data/coin_metadata/sources/coin_metadata.move +++ b/sdk/typescript/test/e2e/data/coin_metadata/sources/coin_metadata.move @@ -17,7 +17,7 @@ module coin_metadata::test { b"TEST", b"Test Coin", b"Test coin metadata", - option::some(url::new_unsafe_from_bytes(b"http://iota.io")), + option::some(url::new_unsafe_from_bytes(b"http://iota.org")), ctx ); diff --git a/turbo.json b/turbo.json index abc4d0b6757..f73103f2c7e 100644 --- a/turbo.json +++ b/turbo.json @@ -2,9 +2,7 @@ "ui": "tui", "$schema": "https://turbo.build/schema.json", "tasks": { - "lint": { - "dependsOn": ["^build"] - }, + "lint": { }, "lint:fix": { "dependsOn": ["^build"] },