Compare commits
67
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2108af7cf3 | ||
|
|
e4d243ef34 | ||
|
|
421ffa024c | ||
|
|
286b9f1e0b | ||
|
|
46e880d9e2 | ||
|
|
7116ae0ce6 | ||
|
|
1042b5538a | ||
|
|
9d319f462c | ||
|
|
ed19f73fae | ||
|
|
8718354e69 | ||
|
|
945ea1d9ad | ||
|
|
02c8d51b84 | ||
|
|
47f7b4df39 | ||
|
|
891fde539d | ||
|
|
9666940fed | ||
|
|
b7b5ad2c11 | ||
|
|
5de549c5d2 | ||
|
|
1de78fb2f3 | ||
|
|
603ea56c54 | ||
|
|
7365634c0a | ||
|
|
b76d89dbb2 | ||
|
|
de7f7d701c | ||
|
|
32fa0c6aa8 | ||
|
|
c508751f38 | ||
|
|
fbf4556d48 | ||
|
|
c9f290a1d4 | ||
|
|
5fb92c0a98 | ||
|
|
9af8561284 | ||
|
|
2e12c769f9 | ||
|
|
d89f009f14 | ||
|
|
1c29556f14 | ||
|
|
15697ae741 | ||
|
|
d2ffb82071 | ||
|
|
e8063936c9 | ||
|
|
0394eb22bf | ||
|
+2 |
7234e6bc10 | ||
|
|
26a50b1e05 | ||
|
|
00be583b89 | ||
|
|
8c9def769c | ||
|
|
213f313034 | ||
|
|
3aaad1e9bf | ||
|
|
55848db4ea | ||
|
|
0c83897f62 | ||
|
|
b6a6eae3cc | ||
|
|
f7b45fa04e | ||
|
|
82e5f53bc4 | ||
|
|
13c3083ac4 | ||
|
|
755cffe590 | ||
|
|
dd1141f9af | ||
|
|
968fdc3ebe | ||
|
|
2ef20589b7 | ||
|
|
6d63920c0a | ||
|
|
3ef378659e | ||
|
|
eba8f1c198 | ||
|
|
52f827e8f2 | ||
|
|
6063f40f87 | ||
|
|
6bd1b82a58 | ||
|
|
052892b396 | ||
|
|
3b12c5c926 | ||
|
|
02d2377ca5 | ||
|
|
9545005908 | ||
|
|
d93286bc1f | ||
|
|
50e7dbaa9d | ||
|
|
04961f0e9a | ||
|
|
37f8433c7c | ||
|
|
c81bb882c5 | ||
|
|
701cd880df |
+37
-17
@@ -2,28 +2,48 @@
|
||||
|
||||
# Platform team owns everything by default
|
||||
|
||||
* @thirdweb-dev/platform
|
||||
* @jnsdls @joaquim @MananTank
|
||||
|
||||
# Devrel owns all markdown files (README etc.)
|
||||
# legacy packages
|
||||
legacy_packages/auth/ @jnsdls
|
||||
legacy_packages/chains/ @jnsdls
|
||||
legacy_packages/cli/ @jnsdls
|
||||
legacy_packages/contracts-js/ @jnsdls
|
||||
legacy_packages/crypto/ @jnsdls
|
||||
legacy_packages/generated-abis/ @jnsdls
|
||||
legacy_packages/merkletree/ @jnsdls
|
||||
legacy_packages/pay/ @jnsdls
|
||||
legacy_packages/payments/ @jnsdls
|
||||
legacy_packages/react/ @MananTank @jnsdls
|
||||
legacy_packages/react-core/ @MananTank @jnsdls
|
||||
legacy_packages/react-native/ @jnsdls
|
||||
legacy_packages/react-native-compat/ @jnsdls
|
||||
legacy_packages/sdk/ @joaquim @jnsdls
|
||||
legacy_packages/storage/ @jnsdls
|
||||
legacy_packages/wallets/ @MananTank @jnsdls
|
||||
|
||||
*.md @thirdweb-dev/devrel
|
||||
.changeset/
|
||||
|
||||
# Shared ownership of the react and react-core packages
|
||||
# legacy e2e
|
||||
legacy_e2e/ @jnsdls
|
||||
|
||||
packages/react/ @thirdweb-dev/product @thirdweb-dev/platform
|
||||
packages/react-core/ @thirdweb-dev/product @thirdweb-dev/platform
|
||||
# packages
|
||||
|
||||
# Shared ownership of the CLI
|
||||
## specific thirdweb pieces
|
||||
packages/thirdweb/src/react/ @MananTank
|
||||
packages/thirdweb/src/reactive/ @MananTank
|
||||
packages/thirdweb/src/gas/ @joaquim
|
||||
packages/thirdweb/src/pay/ @MananTank @IDubuque
|
||||
|
||||
packages/cli/ @thirdweb-dev/product @thirdweb-dev/platform
|
||||
packages/typedoc-gen/ @MananTank
|
||||
# owned by phil for now
|
||||
packages/service-utils/ @arcoraven
|
||||
packages/eslint-config-thirdweb/ @jnsdls
|
||||
packages/tw-tsconfig/ @jnsdls
|
||||
packages/unity-js-bridge/ @joaquim @0xFirekeeper
|
||||
|
||||
# Chains is owned specifically by jonas for now
|
||||
|
||||
packages/chains/ @jnsdls
|
||||
|
||||
# .github folder + .changeset + turbo config is owned by joaquim and jonas for now
|
||||
|
||||
.github/ @jnsdls @joaquim-verges
|
||||
.changeset/config.json @jnsdls @joaquim-verges
|
||||
turbo.json @joaquim-verges @jnsdls
|
||||
# .github folder + .changeset + turbo config is owned by jonas for now
|
||||
scripts/ @jnsdls
|
||||
.github/ @jnsdls
|
||||
.changeset/config.json @jnsdls
|
||||
turbo.json @jnsdls
|
||||
|
||||
@@ -4,13 +4,20 @@ description: "Sets up Node.js and runs install"
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- uses: pnpm/action-setup@v2
|
||||
# we use bun for some test suites
|
||||
- name: Setup bun
|
||||
uses: oven-sh/setup-bun@v1
|
||||
with:
|
||||
bun-version: 1.0.35
|
||||
# pnpm for our dependencies
|
||||
- uses: pnpm/action-setup@v3
|
||||
with:
|
||||
version: 8
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v3
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
check-latest: true
|
||||
registry-url: "https://registry.npmjs.org"
|
||||
cache: "pnpm"
|
||||
|
||||
|
||||
@@ -9,3 +9,8 @@ updates:
|
||||
directory: "/" # Location of package manifests
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
schedule:
|
||||
# Check for updates to GitHub Actions every week
|
||||
interval: "weekly"
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
name: CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: ["main"]
|
||||
paths:
|
||||
- "packages/**"
|
||||
- "package.json"
|
||||
pull_request:
|
||||
types: [opened, synchronize]
|
||||
paths:
|
||||
- "packages/**"
|
||||
- "package.json"
|
||||
# trigger on merge group as well (merge queue)
|
||||
merge_group:
|
||||
types: [checks_requested]
|
||||
branches: ["main"]
|
||||
workflow_dispatch:
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
# To use Remote Caching, uncomment the next lines and follow the steps below.
|
||||
env:
|
||||
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
|
||||
TURBO_TEAM: ${{ secrets.TURBO_TEAM }}
|
||||
TW_SECRET_KEY: ${{ secrets.TW_SECRET_KEY }}
|
||||
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest-16
|
||||
name: Build Packages
|
||||
steps:
|
||||
- name: Check out the code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup & Install
|
||||
uses: ./.github/composite-actions/install
|
||||
|
||||
- name: Build Packages
|
||||
run: pnpm build:packages
|
||||
|
||||
lint:
|
||||
timeout-minutes: 15
|
||||
name: Lint Packages
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check out the code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup & Install
|
||||
uses: ./.github/composite-actions/install
|
||||
|
||||
- run: pnpm lint
|
||||
|
||||
test:
|
||||
timeout-minutes: 15
|
||||
name: Unit Tests
|
||||
runs-on: ubuntu-latest-16
|
||||
steps:
|
||||
- name: Check out the code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup & Install
|
||||
uses: ./.github/composite-actions/install
|
||||
|
||||
- name: Set up foundry
|
||||
uses: foundry-rs/foundry-toolchain@v1
|
||||
|
||||
- run: pnpm test
|
||||
|
||||
- name: Upload coverage reports to Codecov
|
||||
uses: codecov/codecov-action@v4
|
||||
with:
|
||||
directory: ./packages
|
||||
|
||||
e2e:
|
||||
timeout-minutes: 15
|
||||
name: E2E Tests
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check out the code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup & Install
|
||||
uses: ./.github/composite-actions/install
|
||||
|
||||
# TODO actually run e2e tests
|
||||
|
||||
benchmark:
|
||||
# cannot run benchmarks on merge group
|
||||
if: github.event_name != 'merge_group'
|
||||
timeout-minutes: 15
|
||||
name: "Benchmarks"
|
||||
runs-on: ubuntu-latest-16
|
||||
steps:
|
||||
- name: Check out the code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup & Install
|
||||
uses: ./.github/composite-actions/install
|
||||
|
||||
- name: Run benchmarks
|
||||
uses: CodSpeedHQ/action@v2
|
||||
with:
|
||||
token: ${{ secrets.CODSPEED_TOKEN }}
|
||||
run: "pnpm bench"
|
||||
@@ -0,0 +1,96 @@
|
||||
name: CI (Legacy Packages)
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: ["main"]
|
||||
paths:
|
||||
- "legacy_packages/**"
|
||||
- "legacy_e2e/**"
|
||||
- "package.json"
|
||||
pull_request:
|
||||
types: [opened, synchronize]
|
||||
paths:
|
||||
- "legacy_packages/**"
|
||||
- "legacy_e2e/**"
|
||||
- "package.json"
|
||||
# trigger on merge group as well (merge queue)
|
||||
merge_group:
|
||||
types: [checks_requested]
|
||||
branches: ["main"]
|
||||
workflow_dispatch:
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
# To use Remote Caching, uncomment the next lines and follow the steps below.
|
||||
env:
|
||||
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
|
||||
TURBO_TEAM: ${{ secrets.TURBO_TEAM }}
|
||||
TW_SECRET_KEY: ${{ secrets.TW_SECRET_KEY }}
|
||||
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest-16
|
||||
name: Build Packages
|
||||
steps:
|
||||
- name: Check out the code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup & Install
|
||||
uses: ./.github/composite-actions/install
|
||||
|
||||
- name: Build Packages
|
||||
run: pnpm build:legacy_packages
|
||||
|
||||
lint:
|
||||
timeout-minutes: 15
|
||||
name: Lint Packages
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check out the code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup & Install
|
||||
uses: ./.github/composite-actions/install
|
||||
|
||||
- run: pnpm lint:legacy
|
||||
|
||||
test:
|
||||
timeout-minutes: 15
|
||||
name: Unit Tests
|
||||
runs-on: ubuntu-latest-16
|
||||
steps:
|
||||
- name: Check out the code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup & Install
|
||||
uses: ./.github/composite-actions/install
|
||||
|
||||
- run: pnpm test:legacy
|
||||
|
||||
- name: Upload coverage reports to Codecov
|
||||
uses: codecov/codecov-action@v4
|
||||
with:
|
||||
directory: ./legacy_packages
|
||||
|
||||
e2e:
|
||||
timeout-minutes: 15
|
||||
name: E2E Tests
|
||||
runs-on: ubuntu-latest-16
|
||||
steps:
|
||||
- name: Check out the code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup & Install
|
||||
uses: ./.github/composite-actions/install
|
||||
|
||||
- name: Install Playwright
|
||||
run: npx playwright install --with-deps
|
||||
|
||||
- name: Run e2e tests
|
||||
run: pnpm e2e:legacy
|
||||
env:
|
||||
NODE_OPTIONS: "--max_old_space_size=4096"
|
||||
CLI_E2E_API_KEY: ${{ secrets.CLI_E2E_API_KEY }}
|
||||
@@ -1,193 +0,0 @@
|
||||
name: Build, Lint & Test & Benchmark
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: ["main"]
|
||||
pull_request:
|
||||
types: [opened, synchronize]
|
||||
# trigger on merge group as well (merge queue)
|
||||
merge_group:
|
||||
types: [checks_requested]
|
||||
workflow_dispatch:
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
# To use Remote Caching, uncomment the next lines and follow the steps below.
|
||||
env:
|
||||
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
|
||||
TURBO_TEAM: ${{ secrets.TURBO_TEAM }}
|
||||
TW_SECRET_KEY: ${{ secrets.TW_SECRET_KEY }}
|
||||
|
||||
jobs:
|
||||
build:
|
||||
timeout-minutes: 15
|
||||
name: Build
|
||||
runs-on: ubuntu-latest-16
|
||||
|
||||
steps:
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 25
|
||||
|
||||
- name: Setup bun
|
||||
uses: oven-sh/setup-bun@v1
|
||||
with:
|
||||
bun-version: 1.0.21
|
||||
|
||||
- name: Install
|
||||
uses: ./.github/composite-actions/install
|
||||
|
||||
- run: pnpm build
|
||||
|
||||
# We use week in the turbo cache key to keep the cache from infinitely growing
|
||||
- id: get-week
|
||||
run: echo "WEEK=$(date +%U)" >> $GITHUB_OUTPUT
|
||||
|
||||
- uses: actions/cache@v3
|
||||
timeout-minutes: 5
|
||||
id: cache-build
|
||||
with:
|
||||
path: ./*
|
||||
key: ${{ github.sha }}-${{ github.run_number }}
|
||||
|
||||
lint:
|
||||
timeout-minutes: 15
|
||||
name: Lint Packages
|
||||
runs-on: ubuntu-latest
|
||||
needs: build
|
||||
steps:
|
||||
- name: Setup node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 20
|
||||
check-latest: true
|
||||
|
||||
- name: Setup bun
|
||||
uses: oven-sh/setup-bun@v1
|
||||
with:
|
||||
bun-version: 1.0.21
|
||||
|
||||
- uses: pnpm/action-setup@v2
|
||||
with:
|
||||
version: 8
|
||||
|
||||
- uses: actions/cache@v3
|
||||
timeout-minutes: 5
|
||||
id: restore-build
|
||||
with:
|
||||
path: ./*
|
||||
key: ${{ github.sha }}-${{ github.run_number }}
|
||||
|
||||
- run: pnpm lint
|
||||
|
||||
test:
|
||||
timeout-minutes: 15
|
||||
name: Unit Tests
|
||||
runs-on: ubuntu-latest-16
|
||||
needs: build
|
||||
steps:
|
||||
- name: Setup node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 20
|
||||
check-latest: true
|
||||
|
||||
# we use bun for some test suites
|
||||
- name: Setup bun
|
||||
uses: oven-sh/setup-bun@v1
|
||||
with:
|
||||
bun-version: 1.0.21
|
||||
|
||||
- uses: pnpm/action-setup@v2
|
||||
with:
|
||||
version: 8
|
||||
|
||||
- uses: actions/cache@v3
|
||||
timeout-minutes: 5
|
||||
id: restore-build
|
||||
with:
|
||||
path: ./*
|
||||
key: ${{ github.sha }}-${{ github.run_number }}
|
||||
|
||||
- name: Set up foundry
|
||||
uses: foundry-rs/foundry-toolchain@v1
|
||||
|
||||
- run: pnpm test
|
||||
|
||||
- name: Upload coverage reports to Codecov
|
||||
uses: codecov/codecov-action@v3
|
||||
with:
|
||||
files: ./legacy_packages/sdk/coverage/evm/lcov.info,./packages/thirdweb/coverage/lcov.info
|
||||
|
||||
e2e:
|
||||
timeout-minutes: 15
|
||||
name: E2E Tests
|
||||
runs-on: ubuntu-latest-16
|
||||
needs: build
|
||||
steps:
|
||||
- name: Setup node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 20
|
||||
check-latest: true
|
||||
|
||||
# we use bun for some test suites
|
||||
- name: Setup bun
|
||||
uses: oven-sh/setup-bun@v1
|
||||
with:
|
||||
bun-version: 1.0.21
|
||||
|
||||
- uses: pnpm/action-setup@v2
|
||||
with:
|
||||
version: 8
|
||||
|
||||
- uses: actions/cache@v3
|
||||
timeout-minutes: 5
|
||||
id: restore-build
|
||||
with:
|
||||
path: ./*
|
||||
key: ${{ github.sha }}-${{ github.run_number }}
|
||||
|
||||
- name: Install Playwright
|
||||
run: npx playwright install --with-deps
|
||||
|
||||
- name: Run e2e tests
|
||||
run: pnpm e2e
|
||||
env:
|
||||
NODE_OPTIONS: "--max_old_space_size=4096"
|
||||
CLI_E2E_API_KEY: ${{ secrets.CLI_E2E_API_KEY }}
|
||||
|
||||
benchmark:
|
||||
timeout-minutes: 15
|
||||
name: "Benchmark"
|
||||
runs-on: ubuntu-latest-16
|
||||
needs: build
|
||||
steps:
|
||||
- name: Setup node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 20
|
||||
check-latest: true
|
||||
|
||||
- uses: pnpm/action-setup@v2
|
||||
with:
|
||||
version: 8
|
||||
|
||||
- uses: actions/cache@v3
|
||||
timeout-minutes: 5
|
||||
id: restore-build
|
||||
with:
|
||||
path: ./*
|
||||
key: ${{ github.sha }}-${{ github.run_number }}
|
||||
|
||||
- name: Set up foundry
|
||||
uses: foundry-rs/foundry-toolchain@v1
|
||||
|
||||
- name: Run benchmarks
|
||||
uses: CodSpeedHQ/action@v2
|
||||
with:
|
||||
token: ${{ secrets.CODSPEED_TOKEN }}
|
||||
run: "pnpm bench"
|
||||
@@ -13,12 +13,16 @@ name: "CodeQL"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "main" ]
|
||||
branches: ["main"]
|
||||
pull_request:
|
||||
# The branches below must be a subset of the branches above
|
||||
branches: [ "main" ]
|
||||
branches: ["main"]
|
||||
schedule:
|
||||
- cron: '37 9 * * 3'
|
||||
- cron: "37 9 * * 3"
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
analyze:
|
||||
@@ -32,41 +36,40 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
language: [ 'javascript' ]
|
||||
language: ["javascript"]
|
||||
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
|
||||
# Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v2
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||
# By default, queries listed here will override any specified in a config file.
|
||||
# Prefix the list here with "+" to use these queries and those in the config file.
|
||||
|
||||
# Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
|
||||
# queries: security-extended,security-and-quality
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v3
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||
# By default, queries listed here will override any specified in a config file.
|
||||
# Prefix the list here with "+" to use these queries and those in the config file.
|
||||
|
||||
|
||||
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||
# If this step fails, then you should remove it and run the build manually (see below)
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@v2
|
||||
# Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
|
||||
# queries: security-extended,security-and-quality
|
||||
|
||||
# ℹ️ Command-line programs to run using the OS shell.
|
||||
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
|
||||
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||
# If this step fails, then you should remove it and run the build manually (see below)
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@v3
|
||||
|
||||
# If the Autobuild fails above, remove it and uncomment the following three lines.
|
||||
# modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.
|
||||
# ℹ️ Command-line programs to run using the OS shell.
|
||||
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
|
||||
|
||||
# - run: |
|
||||
# echo "Run, Build Application using script"
|
||||
# ./location_of_script_within_repo/buildscript.sh
|
||||
# If the Autobuild fails above, remove it and uncomment the following three lines.
|
||||
# modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v2
|
||||
# - run: |
|
||||
# echo "Run, Build Application using script"
|
||||
# ./location_of_script_within_repo/buildscript.sh
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v3
|
||||
|
||||
@@ -24,13 +24,13 @@ jobs:
|
||||
runs-on: ubuntu-latest-16
|
||||
steps:
|
||||
- name: Checkout branch
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
# bun setup is required, because pnpm typdoc will run pnpm build and some packages uses bun for build
|
||||
- name: Setup bun
|
||||
uses: oven-sh/setup-bun@v1
|
||||
with:
|
||||
bun-version: 1.0.21
|
||||
bun-version: 1.0.35
|
||||
|
||||
- name: Install
|
||||
uses: ./.github/composite-actions/install
|
||||
|
||||
@@ -51,7 +51,7 @@ jobs:
|
||||
steps:
|
||||
- name: get pull request ref
|
||||
id: get_pull_request_ref
|
||||
uses: octokit/request-action@v2.1.0
|
||||
uses: octokit/request-action@v2.2.0
|
||||
with:
|
||||
route: GET /repos/{owner}/{repository}/pulls/{issue_id}
|
||||
owner: ${{ github.repository_owner }}
|
||||
@@ -61,7 +61,7 @@ jobs:
|
||||
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
|
||||
|
||||
- name: pull the repo.
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
persist-credentials: true
|
||||
repository: ${{ fromJson(steps.get_pull_request_ref.outputs.data).head.repo.full_name }}
|
||||
@@ -70,7 +70,7 @@ jobs:
|
||||
- name: Setup bun
|
||||
uses: oven-sh/setup-bun@v1
|
||||
with:
|
||||
bun-version: 1.0.21
|
||||
bun-version: 1.0.35
|
||||
|
||||
- name: Install
|
||||
uses: ./.github/composite-actions/install
|
||||
|
||||
@@ -26,7 +26,7 @@ jobs:
|
||||
runs-on: ubuntu-latest-16
|
||||
steps:
|
||||
- name: Checkout branch
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
# Do not use the GITHUB_TOKEN by default
|
||||
@@ -35,7 +35,7 @@ jobs:
|
||||
- name: Setup bun
|
||||
uses: oven-sh/setup-bun@v1
|
||||
with:
|
||||
bun-version: 1.0.21
|
||||
bun-version: 1.0.35
|
||||
|
||||
- name: Install
|
||||
uses: ./.github/composite-actions/install
|
||||
|
||||
@@ -10,12 +10,12 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install bun
|
||||
uses: oven-sh/setup-bun@v1
|
||||
with:
|
||||
bun-version: 1.0.21
|
||||
bun-version: 1.0.35
|
||||
|
||||
- name: Run chains sync
|
||||
run: bun run db:sync
|
||||
@@ -49,7 +49,7 @@ jobs:
|
||||
|
||||
- name: Create or Update Pull Request
|
||||
if: env.CHANGES_FOUND == 'true'
|
||||
uses: peter-evans/create-pull-request@v3
|
||||
uses: peter-evans/create-pull-request@v6
|
||||
with:
|
||||
title: "chore(chains): update chains"
|
||||
branch: "sync-chains"
|
||||
|
||||
@@ -18,9 +18,6 @@
|
||||
|
||||
<p align="center"><strong>All-in-one web3 SDK for Browser, Node and Mobile apps</strong></p>
|
||||
|
||||
> [!IMPORTANT]
|
||||
> We rewrote the thirdweb SDK from scratch for performance! Head over to the [v5 SDK](https://github.com/thirdweb-dev/js/tree/main/packages/thirdweb).
|
||||
|
||||
## Features
|
||||
|
||||
- Support for React & React-Native
|
||||
@@ -53,19 +50,6 @@
|
||||
| React Native Hooks | ✅ | ❌ | ❌ | ❌ |
|
||||
| React Native UI Components | ✅ | ❌ | ❌ | ❌ |
|
||||
|
||||
## Packages
|
||||
|
||||
| Package | Description |
|
||||
| ----------------------------------------------- | --------------------------------------------------------------------------- |
|
||||
| [/sdk](./legacy_packages/sdk) | Best in class web3 SDK for Browser, Node and Mobile apps |
|
||||
| [/wallets](./legacy_packages/wallets) | Unified web3 Wallet library to integrate any wallet into your applications. |
|
||||
| [/react](./legacy_packages/react) | Ultimate collection of React hooks for your web3 apps |
|
||||
| [/react-native](./legacy_packages/react-native) | Ultimate collection of React hooks for your native mobile web3 apps |
|
||||
| [/auth](./legacy_packages/auth) | Best in class wallet authentication for Node backends |
|
||||
| [/storage](./legacy_packages/storage) | Best in class decentralized storage SDK for Browser and Node |
|
||||
| [/cli](./legacy_packages/cli) | Publish and deploy smart contracts without dealing with private keys |
|
||||
| [/chains](./legacy_packages/chains) | All EVM chain information as JS objects for easy handling |
|
||||
|
||||
## Contributing
|
||||
|
||||
We welcome contributions from all developers regardless of experience level. If you are interested in contributing, please read our [Contributing Guide](.github/contributing.md) to learn how the repo works, how to test your changes, and how to submit a pull request.
|
||||
@@ -74,9 +58,9 @@ See our [open source page](https://thirdweb.com/open-source) for more informatio
|
||||
|
||||
## Additional Resources
|
||||
|
||||
- [SDK Documentation](https://portal.thirdweb.com/typescript/v5)
|
||||
- [Documentation](https://portal.thirdweb.com/typescript/v5)
|
||||
- [Templates](https://thirdweb.com/templates)
|
||||
- [YouTube](https://www.youtube.com/c/thirdweb_)
|
||||
- [YouTube](https://www.youtube.com/c/thirdweb)
|
||||
|
||||
## Support
|
||||
|
||||
|
||||
@@ -14,8 +14,7 @@
|
||||
"e2e": "bun run.ts"
|
||||
},
|
||||
"devDependencies": {
|
||||
"esbuild": "0.15.17",
|
||||
"execa": "^8.0.1",
|
||||
"esbuild": "0.20.2",
|
||||
"ora": "^6.3.1"
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import { execa } from "execa";
|
||||
import { $ } from "bun";
|
||||
import fs from "node:fs/promises";
|
||||
import ora from "ora";
|
||||
|
||||
@@ -9,7 +9,7 @@ const spinner = ora("Running fixtures: ").start();
|
||||
for (const fixture of fixtures) {
|
||||
spinner.suffixText = fixture;
|
||||
try {
|
||||
await execa("bunx", ["swc", "fixtures/" + fixture]);
|
||||
await $`esbuild fixtures/${fixture} --bundle`.text();
|
||||
} catch (error) {
|
||||
if (error.exitCode !== 0) {
|
||||
console.error(error);
|
||||
@@ -14,9 +14,8 @@
|
||||
"e2e": "bun run.ts"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@swc/cli": "^0.1.63",
|
||||
"@swc/core": "^1.3.71",
|
||||
"execa": "^8.0.1",
|
||||
"@swc/cli": "0.3.10",
|
||||
"@swc/core": "^1.4.11",
|
||||
"ora": "^6.3.1"
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import { execa } from "execa";
|
||||
import { $ } from "bun";
|
||||
import fs from "node:fs/promises";
|
||||
import ora from "ora";
|
||||
|
||||
@@ -9,7 +9,7 @@ const spinner = ora("Running fixtures: ").start();
|
||||
for (const fixture of fixtures) {
|
||||
spinner.suffixText = fixture;
|
||||
try {
|
||||
await execa("esbuild", ["fixtures/" + fixture, "--bundle"]);
|
||||
await $`bunx swc fixtures/${fixture}`.text();
|
||||
} catch (error) {
|
||||
if (error.exitCode !== 0) {
|
||||
console.error(error);
|
||||
@@ -14,8 +14,7 @@
|
||||
"e2e": "bun run.ts"
|
||||
},
|
||||
"devDependencies": {
|
||||
"execa": "^8.0.1",
|
||||
"ora": "^6.3.1",
|
||||
"vite": "^5.1.4"
|
||||
"vite": "^5.2.7"
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import { execa } from "execa";
|
||||
import { $ } from "bun";
|
||||
import fs from "node:fs/promises";
|
||||
import ora from "ora";
|
||||
|
||||
@@ -20,7 +20,7 @@ for (const fixture of fixtures) {
|
||||
`,
|
||||
);
|
||||
|
||||
await execa("vite", ["build", "fixtures/"]);
|
||||
await $`vite build fixtures/`.text();
|
||||
} catch (error) {
|
||||
if (error.exitCode !== 0) {
|
||||
console.error(error);
|
||||
@@ -14,9 +14,8 @@
|
||||
"e2e": "bun run.ts"
|
||||
},
|
||||
"devDependencies": {
|
||||
"execa": "^8.0.1",
|
||||
"ora": "^6.3.1",
|
||||
"webpack": "^5.89.0",
|
||||
"webpack": "^5.91.0",
|
||||
"webpack-cli": "^5.1.4"
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import { execa } from "execa";
|
||||
import { $ } from "bun";
|
||||
import fs from "node:fs/promises";
|
||||
import ora from "ora";
|
||||
|
||||
@@ -9,7 +9,7 @@ const spinner = ora("Running fixtures: ").start();
|
||||
for (const fixture of fixtures) {
|
||||
spinner.suffixText = fixture;
|
||||
try {
|
||||
await execa("webpack", ["build", "./fixtures/" + fixture]);
|
||||
await $`webpack build ./fixtures/${fixture} --mode=production`.text();
|
||||
} catch (error) {
|
||||
if (error.exitCode !== 0) {
|
||||
console.error(error);
|
||||
-1
@@ -15,7 +15,6 @@
|
||||
"e2e": "bun run.ts"
|
||||
},
|
||||
"devDependencies": {
|
||||
"execa": "^8.0.1",
|
||||
"ora": "^6.3.1"
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import { execa } from "execa";
|
||||
import { $ } from "bun";
|
||||
import fs from "node:fs/promises";
|
||||
import ora from "ora";
|
||||
|
||||
@@ -9,7 +9,7 @@ const spinner = ora("Running fixtures: ").start();
|
||||
for (const fixture of fixtures) {
|
||||
spinner.suffixText = fixture;
|
||||
try {
|
||||
await execa("node", ["fixtures/" + fixture]);
|
||||
await $`node fixtures/${fixture}`.text();
|
||||
} catch (error) {
|
||||
if (error.exitCode !== 0) {
|
||||
console.error(error);
|
||||
@@ -15,7 +15,6 @@
|
||||
"e2e": "bun run.ts"
|
||||
},
|
||||
"devDependencies": {
|
||||
"execa": "^8.0.1",
|
||||
"ora": "^6.3.1"
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import { execa } from "execa";
|
||||
import { $ } from "bun";
|
||||
import fs from "node:fs/promises";
|
||||
import ora from "ora";
|
||||
|
||||
@@ -9,7 +9,7 @@ const spinner = ora("Running fixtures: ").start();
|
||||
for (const fixture of fixtures) {
|
||||
spinner.suffixText = fixture;
|
||||
try {
|
||||
await execa("node", ["fixtures/" + fixture]);
|
||||
await $`node fixtures/${fixture}`.text();
|
||||
} catch (error) {
|
||||
if (error.exitCode !== 0) {
|
||||
console.error(error);
|
||||
@@ -1,5 +1,42 @@
|
||||
# @thirdweb-dev/auth
|
||||
|
||||
## 4.1.54
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies []:
|
||||
- @thirdweb-dev/wallets@2.4.32
|
||||
|
||||
## 4.1.53
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`00be583`](https://github.com/thirdweb-dev/js/commit/00be583b8902a1a0e5382ffdaafa6b9e31316075)]:
|
||||
- @thirdweb-dev/wallets@2.4.31
|
||||
|
||||
## 4.1.52
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies []:
|
||||
- @thirdweb-dev/wallets@2.4.30
|
||||
|
||||
## 4.1.51
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies []:
|
||||
- @thirdweb-dev/wallets@2.4.29
|
||||
|
||||
## 4.1.50
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#2577](https://github.com/thirdweb-dev/js/pull/2577) [`d93286b`](https://github.com/thirdweb-dev/js/commit/d93286bc1f8224d055b50ce3ffa4f302869cb2b1) Thanks [@jnsdls](https://github.com/jnsdls)! - update dependencies
|
||||
|
||||
- Updated dependencies [[`d93286b`](https://github.com/thirdweb-dev/js/commit/d93286bc1f8224d055b50ce3ffa4f302869cb2b1)]:
|
||||
- @thirdweb-dev/wallets@2.4.28
|
||||
|
||||
## 4.1.49
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@thirdweb-dev/auth",
|
||||
"version": "4.1.49",
|
||||
"version": "4.1.54",
|
||||
"main": "dist/thirdweb-dev-auth.cjs.js",
|
||||
"module": "dist/thirdweb-dev-auth.esm.js",
|
||||
"browser": {
|
||||
@@ -58,10 +58,10 @@
|
||||
"scripts": {
|
||||
"build": "preconstruct build",
|
||||
"format": "prettier --write 'src/**/*'",
|
||||
"lint": "eslint src/ && bunx publint --strict --level warning",
|
||||
"lint": "eslint src/",
|
||||
"fix": "eslint src/ --fix",
|
||||
"clean": "rm -rf dist/ && rm -rf node_modules/",
|
||||
"test": "mocha --config './test/.mocharc.json' --timeout 240000 --parallel './test/**/*.test.ts'",
|
||||
"test": "vitest",
|
||||
"push": "yalc push"
|
||||
},
|
||||
"preconstruct": {
|
||||
@@ -80,44 +80,37 @@
|
||||
}
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.23.7",
|
||||
"@babel/preset-env": "^7.23.8",
|
||||
"@babel/preset-typescript": "^7.23.3",
|
||||
"@microsoft/api-documenter": "^7.22.30",
|
||||
"@microsoft/api-extractor": "^7.36.3",
|
||||
"@microsoft/tsdoc": "^0.14.1",
|
||||
"@microsoft/api-documenter": "^7.24.1",
|
||||
"@microsoft/api-extractor": "^7.43.0",
|
||||
"@microsoft/tsdoc": "^0.14.2",
|
||||
"@preconstruct/cli": "2.7.0",
|
||||
"@swc-node/register": "^1.6.8",
|
||||
"@swc/core": "^1.3.71",
|
||||
"@swc-node/register": "^1.9.0",
|
||||
"@swc/core": "^1.4.11",
|
||||
"@thirdweb-dev/tsconfig": "workspace:*",
|
||||
"@types/chai": "^4.3.5",
|
||||
"@types/cookie": "^0.5.1",
|
||||
"@types/cookie-parser": "^1.4.3",
|
||||
"@types/express": "^4.17.13",
|
||||
"@types/mocha": "^10.0.0",
|
||||
"@types/uuid": "^9.0.5",
|
||||
"chai": "^4.3.6",
|
||||
"@types/cookie": "^0.6.0",
|
||||
"@types/cookie-parser": "^1.4.7",
|
||||
"@types/express": "^4.17.21",
|
||||
"@types/uuid": "^9.0.8",
|
||||
"cookie-parser": "^1.4.6",
|
||||
"eslint": "^8.56.0",
|
||||
"eslint": "^8.57.0",
|
||||
"eslint-config-thirdweb": "workspace:*",
|
||||
"eslint-plugin-import": "^2.26.0",
|
||||
"eslint-plugin-inclusive-language": "^2.2.0",
|
||||
"eslint-plugin-prettier": "^5.0.0",
|
||||
"eslint-plugin-tsdoc": "^0.2.16",
|
||||
"eslint-plugin-import": "^2.29.1",
|
||||
"eslint-plugin-inclusive-language": "^2.2.1",
|
||||
"eslint-plugin-prettier": "^5.1.3",
|
||||
"eslint-plugin-tsdoc": "^0.2.17",
|
||||
"ethers": "^5.7.2",
|
||||
"express": "^4.18.1",
|
||||
"fastify": "^4.25.2",
|
||||
"mocha": "10.4.0",
|
||||
"next": "^13.4",
|
||||
"next-auth": "^4.22.3",
|
||||
"typescript": "^5.3.3"
|
||||
"express": "^4.19.2",
|
||||
"fastify": "^4.26.2",
|
||||
"next": "^13.5.6",
|
||||
"next-auth": "^4.24.7",
|
||||
"typescript": "5.4.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"cookie-parser": "^1.4.6",
|
||||
"ethers": "^5",
|
||||
"express": "^4",
|
||||
"fastify": "^4.25.2",
|
||||
"next": "^12 || ^13 || ^14",
|
||||
"next": "^13.4 || ^14",
|
||||
"next-auth": "^4"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
@@ -141,12 +134,12 @@
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"@fastify/cookie": "^9.1.0",
|
||||
"@fastify/cookie": "^9.3.1",
|
||||
"@thirdweb-dev/wallets": "workspace:*",
|
||||
"cookie": "^0.5.0",
|
||||
"cookie": "^0.6.0",
|
||||
"fastify-type-provider-zod": "^1.1.9",
|
||||
"uuid": "^9.0.1",
|
||||
"zod": "^3.22.3"
|
||||
"zod": "^3.22.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
{
|
||||
"extension": [
|
||||
"ts"
|
||||
],
|
||||
"require": [
|
||||
"@swc-node/register"
|
||||
]
|
||||
}
|
||||
@@ -1,377 +1,384 @@
|
||||
import { ThirdwebAuth } from "../src/core";
|
||||
import { EthersWallet } from "@thirdweb-dev/wallets/evm/wallets/ethers";
|
||||
import { expect } from "chai";
|
||||
import { Wallet } from "ethers";
|
||||
import { describe, it, beforeAll, beforeEach, expect } from "vitest";
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
require("dotenv-mono").load();
|
||||
|
||||
describe("Wallet Authentication - EVM", async () => {
|
||||
let adminWallet: any, signerWallet: any, attackerWallet: any;
|
||||
let auth: ThirdwebAuth;
|
||||
describe.runIf(process.env.TW_SECRET_KEY)(
|
||||
"Wallet Authentication - EVM",
|
||||
{
|
||||
timeout: 60000,
|
||||
},
|
||||
async () => {
|
||||
let adminWallet: any, signerWallet: any, attackerWallet: any;
|
||||
let auth: ThirdwebAuth;
|
||||
|
||||
before(async () => {
|
||||
const [adminSigner, signerSigner, attackerSigner] = [
|
||||
Wallet.createRandom(),
|
||||
Wallet.createRandom(),
|
||||
Wallet.createRandom(),
|
||||
];
|
||||
beforeAll(async () => {
|
||||
const [adminSigner, signerSigner, attackerSigner] = [
|
||||
Wallet.createRandom(),
|
||||
Wallet.createRandom(),
|
||||
Wallet.createRandom(),
|
||||
];
|
||||
|
||||
adminWallet = new EthersWallet(adminSigner);
|
||||
signerWallet = new EthersWallet(signerSigner);
|
||||
attackerWallet = new EthersWallet(attackerSigner);
|
||||
adminWallet = new EthersWallet(adminSigner);
|
||||
signerWallet = new EthersWallet(signerSigner);
|
||||
attackerWallet = new EthersWallet(attackerSigner);
|
||||
|
||||
auth = new ThirdwebAuth(signerWallet, "thirdweb.com", {
|
||||
secretKey: process.env.TW_SECRET_KEY,
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
auth.updateWallet(signerWallet);
|
||||
});
|
||||
|
||||
it("Should verify logged in wallet", async () => {
|
||||
const payload = await auth.login();
|
||||
|
||||
auth.updateWallet(adminWallet);
|
||||
const address = await auth.verify(payload);
|
||||
|
||||
expect(address).to.equal(await signerWallet.getAddress());
|
||||
});
|
||||
|
||||
it("Should verify logged in wallet with chain ID and expiration", async () => {
|
||||
const payload = await auth.login({
|
||||
expirationTime: new Date(Date.now() + 1000 * 60 * 5),
|
||||
chainId: "137",
|
||||
});
|
||||
|
||||
auth.updateWallet(adminWallet);
|
||||
const address = await auth.verify(payload, {
|
||||
chainId: "137",
|
||||
});
|
||||
|
||||
expect(address).to.equal(await signerWallet.getAddress());
|
||||
});
|
||||
|
||||
it("Should verify payload with resources", async () => {
|
||||
const payload = await auth.login({
|
||||
resources: ["https://example.com", "https://test.com"],
|
||||
});
|
||||
|
||||
auth.updateWallet(adminWallet);
|
||||
const address = await auth.verify(payload, {
|
||||
resources: ["https://example.com", "https://test.com"],
|
||||
});
|
||||
|
||||
expect(address).to.equal(await signerWallet.getAddress());
|
||||
});
|
||||
|
||||
it("Should reject payload without necessary resources", async () => {
|
||||
const payload = await auth.login({
|
||||
resources: ["https://example.com"],
|
||||
});
|
||||
|
||||
auth.updateWallet(adminWallet);
|
||||
try {
|
||||
await auth.verify(payload, {
|
||||
resources: ["https://example.com", "https://test.com"],
|
||||
auth = new ThirdwebAuth(signerWallet, "thirdweb.com", {
|
||||
secretKey: process.env.TW_SECRET_KEY,
|
||||
});
|
||||
expect.fail();
|
||||
} catch (err: any) {
|
||||
expect(err.message).to.equal(
|
||||
"Login request is missing required resources: https://test.com",
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
it("Should verify payload with customized statement", async () => {
|
||||
const payload = await auth.login({
|
||||
statement: "Please sign!",
|
||||
});
|
||||
|
||||
auth.updateWallet(adminWallet);
|
||||
const address = await auth.verify(payload, {
|
||||
statement: "Please sign!",
|
||||
beforeEach(async () => {
|
||||
auth.updateWallet(signerWallet);
|
||||
});
|
||||
|
||||
expect(address).to.equal(await signerWallet.getAddress());
|
||||
});
|
||||
it("Should verify logged in wallet", async () => {
|
||||
const payload = await auth.login();
|
||||
|
||||
it("Should reject payload with incorrect statement", async () => {
|
||||
const payload = await auth.login({
|
||||
statement: "Please sign!",
|
||||
auth.updateWallet(adminWallet);
|
||||
const address = await auth.verify(payload);
|
||||
|
||||
expect(address).to.equal(await signerWallet.getAddress());
|
||||
});
|
||||
|
||||
auth.updateWallet(adminWallet);
|
||||
try {
|
||||
await auth.verify(payload, {
|
||||
statement: "Please sign again!",
|
||||
});
|
||||
expect.fail();
|
||||
} catch (err: any) {
|
||||
expect(err.message).to.include(
|
||||
"Expected statement 'Please sign again!' does not match statement on payload",
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
it("Should reject invalid nonce", async () => {
|
||||
const payload = await auth.login();
|
||||
|
||||
auth.updateWallet(adminWallet);
|
||||
try {
|
||||
await auth.verify(payload, {
|
||||
validateNonce: (nonce: string) => {
|
||||
if (nonce === payload.payload.nonce) {
|
||||
throw new Error();
|
||||
}
|
||||
},
|
||||
});
|
||||
expect.fail();
|
||||
} catch (err: any) {
|
||||
expect(err.message).to.equal("Login request nonce is invalid");
|
||||
}
|
||||
});
|
||||
|
||||
it("Should accept valid nonce", async () => {
|
||||
const payload = await auth.login();
|
||||
|
||||
auth.updateWallet(adminWallet);
|
||||
const address = await auth.verify(payload, {
|
||||
validateNonce: (nonce: string) => {
|
||||
if (nonce !== payload.payload.nonce) {
|
||||
throw new Error();
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
expect(address).to.equal(await signerWallet.getAddress());
|
||||
});
|
||||
|
||||
it("Should reject payload with incorrect domain", async () => {
|
||||
const payload = await auth.login();
|
||||
|
||||
auth.updateWallet(adminWallet);
|
||||
try {
|
||||
await auth.verify(payload, { domain: "test.thirdweb.com" });
|
||||
expect.fail();
|
||||
} catch (err: any) {
|
||||
expect(err.message).to.equal(
|
||||
"Expected domain 'test.thirdweb.com' does not match domain on payload 'thirdweb.com'",
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
it("Should reject expired login payload", async () => {
|
||||
const payload = await auth.login({
|
||||
expirationTime: new Date(Date.now() - 1000 * 60 * 5),
|
||||
});
|
||||
|
||||
auth.updateWallet(adminWallet);
|
||||
try {
|
||||
await auth.verify(payload);
|
||||
expect.fail();
|
||||
} catch (err: any) {
|
||||
expect(err.message).to.equal("Login request has expired");
|
||||
}
|
||||
});
|
||||
|
||||
it("Should reject payload with incorrect chain ID", async () => {
|
||||
const payload = await auth.login({
|
||||
chainId: "1",
|
||||
});
|
||||
|
||||
auth.updateWallet(adminWallet);
|
||||
try {
|
||||
await auth.verify(payload, {
|
||||
it("Should verify logged in wallet with chain ID and expiration", async () => {
|
||||
const payload = await auth.login({
|
||||
expirationTime: new Date(Date.now() + 1000 * 60 * 5),
|
||||
chainId: "137",
|
||||
});
|
||||
expect.fail();
|
||||
} catch (err: any) {
|
||||
expect(err.message).to.equal(
|
||||
"Expected chain ID '137' does not match chain ID on payload '1'",
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
it("Should reject payload with incorrect signer", async () => {
|
||||
const payload = await auth.login();
|
||||
payload.payload.address = await attackerWallet.getAddress();
|
||||
auth.updateWallet(adminWallet);
|
||||
const address = await auth.verify(payload, {
|
||||
chainId: "137",
|
||||
});
|
||||
|
||||
auth.updateWallet(adminWallet);
|
||||
try {
|
||||
await auth.verify(payload);
|
||||
expect.fail();
|
||||
} catch (err: any) {
|
||||
expect(err.message).to.contain("does not match payload address");
|
||||
}
|
||||
});
|
||||
|
||||
it("Should generate valid authentication token", async () => {
|
||||
const payload = await auth.login();
|
||||
|
||||
auth.updateWallet(adminWallet);
|
||||
const token = await auth.generate(payload);
|
||||
const user = await auth.authenticate(token);
|
||||
|
||||
expect(user.address).to.equal(await signerWallet.getAddress());
|
||||
});
|
||||
|
||||
it("Should reject token with incorrect domain", async () => {
|
||||
const payload = await auth.login();
|
||||
|
||||
auth.updateWallet(adminWallet);
|
||||
const token = await auth.generate(payload);
|
||||
|
||||
try {
|
||||
await auth.authenticate(token, { domain: "test.thirdweb.com" });
|
||||
expect.fail();
|
||||
} catch (err: any) {
|
||||
expect(err.message).to.contain(
|
||||
"Expected token to be for the domain 'test.thirdweb.com', but found token with domain 'thirdweb.com'",
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
it("Should reject token before invalid before", async () => {
|
||||
const payload = await auth.login();
|
||||
|
||||
auth.updateWallet(adminWallet);
|
||||
const token = await auth.generate(payload, {
|
||||
invalidBefore: new Date(Date.now() + 1000 * 60 * 5),
|
||||
expect(address).to.equal(await signerWallet.getAddress());
|
||||
});
|
||||
|
||||
try {
|
||||
await auth.authenticate(token);
|
||||
expect.fail();
|
||||
} catch (err: any) {
|
||||
expect(err.message).to.contain("This token is invalid before");
|
||||
}
|
||||
});
|
||||
it("Should verify payload with resources", async () => {
|
||||
const payload = await auth.login({
|
||||
resources: ["https://example.com", "https://test.com"],
|
||||
});
|
||||
|
||||
it("Should reject expired authentication token", async () => {
|
||||
const payload = await auth.login();
|
||||
auth.updateWallet(adminWallet);
|
||||
const address = await auth.verify(payload, {
|
||||
resources: ["https://example.com", "https://test.com"],
|
||||
});
|
||||
|
||||
auth.updateWallet(adminWallet);
|
||||
const token = await auth.generate(payload, {
|
||||
expirationTime: new Date(Date.now() - 1000 * 60 * 5),
|
||||
expect(address).to.equal(await signerWallet.getAddress());
|
||||
});
|
||||
|
||||
try {
|
||||
await auth.authenticate(token);
|
||||
expect.fail();
|
||||
} catch (err: any) {
|
||||
expect(err.message).to.contain("This token expired");
|
||||
}
|
||||
});
|
||||
it("Should reject payload without necessary resources", async () => {
|
||||
const payload = await auth.login({
|
||||
resources: ["https://example.com"],
|
||||
});
|
||||
|
||||
it("Should reject if admin address is not connected wallet address", async () => {
|
||||
const payload = await auth.login();
|
||||
|
||||
auth.updateWallet(adminWallet);
|
||||
const token = await auth.generate(payload);
|
||||
|
||||
auth.updateWallet(signerWallet);
|
||||
try {
|
||||
await auth.authenticate(token);
|
||||
expect.fail();
|
||||
} catch (err: any) {
|
||||
expect(err.message).to.contain(
|
||||
`The expected issuer address '${await signerWallet.getAddress()}' did not match the token issuer address '${await adminWallet.getAddress()}'`,
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
it("Should accept token with valid token ID", async () => {
|
||||
const payload = await auth.login();
|
||||
|
||||
auth.updateWallet(adminWallet);
|
||||
const token = await auth.generate(payload, {
|
||||
tokenId: "test",
|
||||
auth.updateWallet(adminWallet);
|
||||
try {
|
||||
await auth.verify(payload, {
|
||||
resources: ["https://example.com", "https://test.com"],
|
||||
});
|
||||
expect.fail();
|
||||
} catch (err: any) {
|
||||
expect(err.message).to.equal(
|
||||
"Login request is missing required resources: https://test.com",
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
const user = await auth.authenticate(token, {
|
||||
validateTokenId: (tokenId: string) => {
|
||||
if (tokenId !== "test") {
|
||||
throw new Error();
|
||||
}
|
||||
},
|
||||
it("Should verify payload with customized statement", async () => {
|
||||
const payload = await auth.login({
|
||||
statement: "Please sign!",
|
||||
});
|
||||
|
||||
auth.updateWallet(adminWallet);
|
||||
const address = await auth.verify(payload, {
|
||||
statement: "Please sign!",
|
||||
});
|
||||
|
||||
expect(address).to.equal(await signerWallet.getAddress());
|
||||
});
|
||||
|
||||
expect(user.address).to.equal(await signerWallet.getAddress());
|
||||
});
|
||||
it("Should reject payload with incorrect statement", async () => {
|
||||
const payload = await auth.login({
|
||||
statement: "Please sign!",
|
||||
});
|
||||
|
||||
it("Should reject token with invalid token ID", async () => {
|
||||
const payload = await auth.login();
|
||||
|
||||
auth.updateWallet(adminWallet);
|
||||
const token = await auth.generate(payload, {
|
||||
tokenId: "test",
|
||||
auth.updateWallet(adminWallet);
|
||||
try {
|
||||
await auth.verify(payload, {
|
||||
statement: "Please sign again!",
|
||||
});
|
||||
expect.fail();
|
||||
} catch (err: any) {
|
||||
expect(err.message).to.include(
|
||||
"Expected statement 'Please sign again!' does not match statement on payload",
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
try {
|
||||
await auth.authenticate(token, {
|
||||
validateTokenId: (tokenId: string) => {
|
||||
if (tokenId !== "invalid") {
|
||||
it("Should reject invalid nonce", async () => {
|
||||
const payload = await auth.login();
|
||||
|
||||
auth.updateWallet(adminWallet);
|
||||
try {
|
||||
await auth.verify(payload, {
|
||||
validateNonce: (nonce: string) => {
|
||||
if (nonce === payload.payload.nonce) {
|
||||
throw new Error();
|
||||
}
|
||||
},
|
||||
});
|
||||
expect.fail();
|
||||
} catch (err: any) {
|
||||
expect(err.message).to.equal("Login request nonce is invalid");
|
||||
}
|
||||
});
|
||||
|
||||
it("Should accept valid nonce", async () => {
|
||||
const payload = await auth.login();
|
||||
|
||||
auth.updateWallet(adminWallet);
|
||||
const address = await auth.verify(payload, {
|
||||
validateNonce: (nonce: string) => {
|
||||
if (nonce !== payload.payload.nonce) {
|
||||
throw new Error();
|
||||
}
|
||||
},
|
||||
});
|
||||
expect.fail();
|
||||
} catch (err: any) {
|
||||
expect(err.message).to.contain("Token ID is invalid");
|
||||
}
|
||||
});
|
||||
|
||||
it("Should propagate session on token", async () => {
|
||||
const payload = await auth.login();
|
||||
|
||||
auth.updateWallet(adminWallet);
|
||||
const token = await auth.generate(payload, {
|
||||
session: { role: "admin" },
|
||||
expect(address).to.equal(await signerWallet.getAddress());
|
||||
});
|
||||
|
||||
const user = await auth.authenticate(token);
|
||||
it("Should reject payload with incorrect domain", async () => {
|
||||
const payload = await auth.login();
|
||||
|
||||
expect(user.address).to.equal(await signerWallet.getAddress());
|
||||
expect(user.session).to.deep.equal({ role: "admin" });
|
||||
});
|
||||
|
||||
it("Should call session callback function", async () => {
|
||||
const payload = await auth.login();
|
||||
|
||||
auth.updateWallet(adminWallet);
|
||||
const token = await auth.generate(payload, {
|
||||
session: (address: string) => {
|
||||
return { address, role: "admin" };
|
||||
},
|
||||
auth.updateWallet(adminWallet);
|
||||
try {
|
||||
await auth.verify(payload, { domain: "test.thirdweb.com" });
|
||||
expect.fail();
|
||||
} catch (err: any) {
|
||||
expect(err.message).to.equal(
|
||||
"Expected domain 'test.thirdweb.com' does not match domain on payload 'thirdweb.com'",
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
const user = await auth.authenticate(token);
|
||||
it("Should reject expired login payload", async () => {
|
||||
const payload = await auth.login({
|
||||
expirationTime: new Date(Date.now() - 1000 * 60 * 5),
|
||||
});
|
||||
|
||||
expect(user.address).to.equal(await signerWallet.getAddress());
|
||||
expect(user.session).to.deep.equal({
|
||||
address: await signerWallet.getAddress(),
|
||||
role: "admin",
|
||||
auth.updateWallet(adminWallet);
|
||||
try {
|
||||
await auth.verify(payload);
|
||||
expect.fail();
|
||||
} catch (err: any) {
|
||||
expect(err.message).to.equal("Login request has expired");
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it("Should authenticate with issuer address", async () => {
|
||||
const payload = await auth.login();
|
||||
it("Should reject payload with incorrect chain ID", async () => {
|
||||
const payload = await auth.login({
|
||||
chainId: "1",
|
||||
});
|
||||
|
||||
auth.updateWallet(adminWallet);
|
||||
const token = await auth.generate(payload);
|
||||
|
||||
auth.updateWallet(attackerWallet);
|
||||
try {
|
||||
await auth.authenticate(token);
|
||||
expect.fail();
|
||||
} catch (err: any) {
|
||||
expect(err.message).to.contain("The expected issuer address");
|
||||
}
|
||||
|
||||
const user = await auth.authenticate(token, {
|
||||
issuerAddress: await adminWallet.getAddress(),
|
||||
auth.updateWallet(adminWallet);
|
||||
try {
|
||||
await auth.verify(payload, {
|
||||
chainId: "137",
|
||||
});
|
||||
expect.fail();
|
||||
} catch (err: any) {
|
||||
expect(err.message).to.equal(
|
||||
"Expected chain ID '137' does not match chain ID on payload '1'",
|
||||
);
|
||||
}
|
||||
});
|
||||
expect(user.address).to.equal(await signerWallet.getAddress());
|
||||
});
|
||||
});
|
||||
|
||||
it("Should reject payload with incorrect signer", async () => {
|
||||
const payload = await auth.login();
|
||||
payload.payload.address = await attackerWallet.getAddress();
|
||||
|
||||
auth.updateWallet(adminWallet);
|
||||
try {
|
||||
await auth.verify(payload);
|
||||
expect.fail();
|
||||
} catch (err: any) {
|
||||
expect(err.message).to.contain("does not match payload address");
|
||||
}
|
||||
});
|
||||
|
||||
it("Should generate valid authentication token", async () => {
|
||||
const payload = await auth.login();
|
||||
|
||||
auth.updateWallet(adminWallet);
|
||||
const token = await auth.generate(payload);
|
||||
const user = await auth.authenticate(token);
|
||||
|
||||
expect(user.address).to.equal(await signerWallet.getAddress());
|
||||
});
|
||||
|
||||
it("Should reject token with incorrect domain", async () => {
|
||||
const payload = await auth.login();
|
||||
|
||||
auth.updateWallet(adminWallet);
|
||||
const token = await auth.generate(payload);
|
||||
|
||||
try {
|
||||
await auth.authenticate(token, { domain: "test.thirdweb.com" });
|
||||
expect.fail();
|
||||
} catch (err: any) {
|
||||
expect(err.message).to.contain(
|
||||
"Expected token to be for the domain 'test.thirdweb.com', but found token with domain 'thirdweb.com'",
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
it("Should reject token before invalid before", async () => {
|
||||
const payload = await auth.login();
|
||||
|
||||
auth.updateWallet(adminWallet);
|
||||
const token = await auth.generate(payload, {
|
||||
invalidBefore: new Date(Date.now() + 1000 * 60 * 5),
|
||||
});
|
||||
|
||||
try {
|
||||
await auth.authenticate(token);
|
||||
expect.fail();
|
||||
} catch (err: any) {
|
||||
expect(err.message).to.contain("This token is invalid before");
|
||||
}
|
||||
});
|
||||
|
||||
it("Should reject expired authentication token", async () => {
|
||||
const payload = await auth.login();
|
||||
|
||||
auth.updateWallet(adminWallet);
|
||||
const token = await auth.generate(payload, {
|
||||
expirationTime: new Date(Date.now() - 1000 * 60 * 5),
|
||||
});
|
||||
|
||||
try {
|
||||
await auth.authenticate(token);
|
||||
expect.fail();
|
||||
} catch (err: any) {
|
||||
expect(err.message).to.contain("This token expired");
|
||||
}
|
||||
});
|
||||
|
||||
it("Should reject if admin address is not connected wallet address", async () => {
|
||||
const payload = await auth.login();
|
||||
|
||||
auth.updateWallet(adminWallet);
|
||||
const token = await auth.generate(payload);
|
||||
|
||||
auth.updateWallet(signerWallet);
|
||||
try {
|
||||
await auth.authenticate(token);
|
||||
expect.fail();
|
||||
} catch (err: any) {
|
||||
expect(err.message).to.contain(
|
||||
`The expected issuer address '${await signerWallet.getAddress()}' did not match the token issuer address '${await adminWallet.getAddress()}'`,
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
it("Should accept token with valid token ID", async () => {
|
||||
const payload = await auth.login();
|
||||
|
||||
auth.updateWallet(adminWallet);
|
||||
const token = await auth.generate(payload, {
|
||||
tokenId: "test",
|
||||
});
|
||||
|
||||
const user = await auth.authenticate(token, {
|
||||
validateTokenId: (tokenId: string) => {
|
||||
if (tokenId !== "test") {
|
||||
throw new Error();
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
expect(user.address).to.equal(await signerWallet.getAddress());
|
||||
});
|
||||
|
||||
it("Should reject token with invalid token ID", async () => {
|
||||
const payload = await auth.login();
|
||||
|
||||
auth.updateWallet(adminWallet);
|
||||
const token = await auth.generate(payload, {
|
||||
tokenId: "test",
|
||||
});
|
||||
|
||||
try {
|
||||
await auth.authenticate(token, {
|
||||
validateTokenId: (tokenId: string) => {
|
||||
if (tokenId !== "invalid") {
|
||||
throw new Error();
|
||||
}
|
||||
},
|
||||
});
|
||||
expect.fail();
|
||||
} catch (err: any) {
|
||||
expect(err.message).to.contain("Token ID is invalid");
|
||||
}
|
||||
});
|
||||
|
||||
it("Should propagate session on token", async () => {
|
||||
const payload = await auth.login();
|
||||
|
||||
auth.updateWallet(adminWallet);
|
||||
const token = await auth.generate(payload, {
|
||||
session: { role: "admin" },
|
||||
});
|
||||
|
||||
const user = await auth.authenticate(token);
|
||||
|
||||
expect(user.address).to.equal(await signerWallet.getAddress());
|
||||
expect(user.session).to.deep.equal({ role: "admin" });
|
||||
});
|
||||
|
||||
it("Should call session callback function", async () => {
|
||||
const payload = await auth.login();
|
||||
|
||||
auth.updateWallet(adminWallet);
|
||||
const token = await auth.generate(payload, {
|
||||
session: (address: string) => {
|
||||
return { address, role: "admin" };
|
||||
},
|
||||
});
|
||||
|
||||
const user = await auth.authenticate(token);
|
||||
|
||||
expect(user.address).to.equal(await signerWallet.getAddress());
|
||||
expect(user.session).to.deep.equal({
|
||||
address: await signerWallet.getAddress(),
|
||||
role: "admin",
|
||||
});
|
||||
});
|
||||
|
||||
it("Should authenticate with issuer address", async () => {
|
||||
const payload = await auth.login();
|
||||
|
||||
auth.updateWallet(adminWallet);
|
||||
const token = await auth.generate(payload);
|
||||
|
||||
auth.updateWallet(attackerWallet);
|
||||
try {
|
||||
await auth.authenticate(token);
|
||||
expect.fail();
|
||||
} catch (err: any) {
|
||||
expect(err.message).to.contain("The expected issuer address");
|
||||
}
|
||||
|
||||
const user = await auth.authenticate(token, {
|
||||
issuerAddress: await adminWallet.getAddress(),
|
||||
});
|
||||
expect(user.address).to.equal(await signerWallet.getAddress());
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
@@ -1,384 +1,391 @@
|
||||
import { LocalWallet, SmartWallet } from "@thirdweb-dev/wallets";
|
||||
import { ThirdwebAuth } from "../src/core";
|
||||
import { EthersWallet } from "@thirdweb-dev/wallets/evm/wallets/ethers";
|
||||
import { expect } from "chai";
|
||||
import { Wallet } from "ethers";
|
||||
import { describe, it, beforeEach, beforeAll, expect } from "vitest";
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
require("dotenv-mono").load();
|
||||
|
||||
describe("Wallet Authentication - EVM - Smart Wallet", async () => {
|
||||
let adminWallet: any, signerWallet: any, attackerWallet: any;
|
||||
let auth: ThirdwebAuth;
|
||||
describe.runIf(process.env.TW_SECRET_KEY)(
|
||||
"Wallet Authentication - EVM - Smart Wallet",
|
||||
{
|
||||
timeout: 60000,
|
||||
},
|
||||
async () => {
|
||||
let adminWallet: any, signerWallet: any, attackerWallet: any;
|
||||
let auth: ThirdwebAuth;
|
||||
|
||||
before(async () => {
|
||||
const factoryAddress = "0xbf1C9aA4B1A085f7DA890a44E82B0A1289A40052";
|
||||
const chain = 421614;
|
||||
const localWallet = new LocalWallet();
|
||||
await localWallet.generate();
|
||||
const smartWallet = new SmartWallet({
|
||||
chain: chain,
|
||||
factoryAddress: factoryAddress,
|
||||
gasless: true,
|
||||
secretKey: process.env.TW_SECRET_KEY,
|
||||
});
|
||||
await smartWallet.connect({ personalWallet: localWallet });
|
||||
beforeAll(async () => {
|
||||
const factoryAddress = "0xbf1C9aA4B1A085f7DA890a44E82B0A1289A40052";
|
||||
const chain = 421614;
|
||||
const localWallet = new LocalWallet();
|
||||
await localWallet.generate();
|
||||
const smartWallet = new SmartWallet({
|
||||
chain: chain,
|
||||
factoryAddress: factoryAddress,
|
||||
gasless: true,
|
||||
secretKey: process.env.TW_SECRET_KEY,
|
||||
});
|
||||
await smartWallet.connect({ personalWallet: localWallet });
|
||||
|
||||
adminWallet = new EthersWallet(Wallet.createRandom());
|
||||
signerWallet = smartWallet;
|
||||
attackerWallet = new EthersWallet(Wallet.createRandom());
|
||||
adminWallet = new EthersWallet(Wallet.createRandom());
|
||||
signerWallet = smartWallet;
|
||||
attackerWallet = new EthersWallet(Wallet.createRandom());
|
||||
|
||||
auth = new ThirdwebAuth(signerWallet, "thirdweb.com", {
|
||||
secretKey: process.env.TW_SECRET_KEY,
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
auth.updateWallet(signerWallet);
|
||||
});
|
||||
|
||||
it("Should verify logged in wallet", async () => {
|
||||
const payload = await auth.login();
|
||||
|
||||
auth.updateWallet(adminWallet);
|
||||
const address = await auth.verify(payload);
|
||||
|
||||
expect(address).to.equal(await signerWallet.getAddress());
|
||||
});
|
||||
|
||||
it("Should verify logged in wallet with chain ID and expiration", async () => {
|
||||
const payload = await auth.login({
|
||||
expirationTime: new Date(Date.now() + 1000 * 60 * 5),
|
||||
chainId: "421614",
|
||||
auth = new ThirdwebAuth(signerWallet, "thirdweb.com", {
|
||||
secretKey: process.env.TW_SECRET_KEY,
|
||||
});
|
||||
});
|
||||
|
||||
auth.updateWallet(adminWallet);
|
||||
const address = await auth.verify(payload, {
|
||||
chainId: "421614",
|
||||
beforeEach(async () => {
|
||||
auth.updateWallet(signerWallet);
|
||||
});
|
||||
|
||||
expect(address).to.equal(await signerWallet.getAddress());
|
||||
});
|
||||
it("Should verify logged in wallet", async () => {
|
||||
const payload = await auth.login();
|
||||
|
||||
it("Should verify payload with resources", async () => {
|
||||
const payload = await auth.login({
|
||||
resources: ["https://example.com", "https://test.com"],
|
||||
auth.updateWallet(adminWallet);
|
||||
const address = await auth.verify(payload);
|
||||
|
||||
expect(address).to.equal(await signerWallet.getAddress());
|
||||
});
|
||||
|
||||
auth.updateWallet(adminWallet);
|
||||
const address = await auth.verify(payload, {
|
||||
resources: ["https://example.com", "https://test.com"],
|
||||
it("Should verify logged in wallet with chain ID and expiration", async () => {
|
||||
const payload = await auth.login({
|
||||
expirationTime: new Date(Date.now() + 1000 * 60 * 5),
|
||||
chainId: "421614",
|
||||
});
|
||||
|
||||
auth.updateWallet(adminWallet);
|
||||
const address = await auth.verify(payload, {
|
||||
chainId: "421614",
|
||||
});
|
||||
|
||||
expect(address).to.equal(await signerWallet.getAddress());
|
||||
});
|
||||
|
||||
expect(address).to.equal(await signerWallet.getAddress());
|
||||
});
|
||||
|
||||
it("Should reject payload without necessary resources", async () => {
|
||||
const payload = await auth.login({
|
||||
resources: ["https://example.com"],
|
||||
});
|
||||
|
||||
auth.updateWallet(adminWallet);
|
||||
try {
|
||||
await auth.verify(payload, {
|
||||
it("Should verify payload with resources", async () => {
|
||||
const payload = await auth.login({
|
||||
resources: ["https://example.com", "https://test.com"],
|
||||
});
|
||||
expect.fail();
|
||||
} catch (err: any) {
|
||||
expect(err.message).to.equal(
|
||||
"Login request is missing required resources: https://test.com",
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
it("Should verify payload with customized statement", async () => {
|
||||
const payload = await auth.login({
|
||||
statement: "Please sign!",
|
||||
});
|
||||
|
||||
auth.updateWallet(adminWallet);
|
||||
const address = await auth.verify(payload, {
|
||||
statement: "Please sign!",
|
||||
});
|
||||
|
||||
expect(address).to.equal(await signerWallet.getAddress());
|
||||
});
|
||||
|
||||
it("Should reject payload with incorrect statement", async () => {
|
||||
const payload = await auth.login({
|
||||
statement: "Please sign!",
|
||||
});
|
||||
|
||||
auth.updateWallet(adminWallet);
|
||||
try {
|
||||
await auth.verify(payload, {
|
||||
statement: "Please sign again!",
|
||||
auth.updateWallet(adminWallet);
|
||||
const address = await auth.verify(payload, {
|
||||
resources: ["https://example.com", "https://test.com"],
|
||||
});
|
||||
expect.fail();
|
||||
} catch (err: any) {
|
||||
expect(err.message).to.include(
|
||||
"Expected statement 'Please sign again!' does not match statement on payload",
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
it("Should reject invalid nonce", async () => {
|
||||
const payload = await auth.login();
|
||||
expect(address).to.equal(await signerWallet.getAddress());
|
||||
});
|
||||
|
||||
auth.updateWallet(adminWallet);
|
||||
try {
|
||||
await auth.verify(payload, {
|
||||
it("Should reject payload without necessary resources", async () => {
|
||||
const payload = await auth.login({
|
||||
resources: ["https://example.com"],
|
||||
});
|
||||
|
||||
auth.updateWallet(adminWallet);
|
||||
try {
|
||||
await auth.verify(payload, {
|
||||
resources: ["https://example.com", "https://test.com"],
|
||||
});
|
||||
expect.fail();
|
||||
} catch (err: any) {
|
||||
expect(err.message).to.equal(
|
||||
"Login request is missing required resources: https://test.com",
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
it("Should verify payload with customized statement", async () => {
|
||||
const payload = await auth.login({
|
||||
statement: "Please sign!",
|
||||
});
|
||||
|
||||
auth.updateWallet(adminWallet);
|
||||
const address = await auth.verify(payload, {
|
||||
statement: "Please sign!",
|
||||
});
|
||||
|
||||
expect(address).to.equal(await signerWallet.getAddress());
|
||||
});
|
||||
|
||||
it("Should reject payload with incorrect statement", async () => {
|
||||
const payload = await auth.login({
|
||||
statement: "Please sign!",
|
||||
});
|
||||
|
||||
auth.updateWallet(adminWallet);
|
||||
try {
|
||||
await auth.verify(payload, {
|
||||
statement: "Please sign again!",
|
||||
});
|
||||
expect.fail();
|
||||
} catch (err: any) {
|
||||
expect(err.message).to.include(
|
||||
"Expected statement 'Please sign again!' does not match statement on payload",
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
it("Should reject invalid nonce", async () => {
|
||||
const payload = await auth.login();
|
||||
|
||||
auth.updateWallet(adminWallet);
|
||||
try {
|
||||
await auth.verify(payload, {
|
||||
validateNonce: (nonce: string) => {
|
||||
if (nonce === payload.payload.nonce) {
|
||||
throw new Error();
|
||||
}
|
||||
},
|
||||
});
|
||||
expect.fail();
|
||||
} catch (err: any) {
|
||||
expect(err.message).to.equal("Login request nonce is invalid");
|
||||
}
|
||||
});
|
||||
|
||||
it("Should accept valid nonce", async () => {
|
||||
const payload = await auth.login();
|
||||
|
||||
auth.updateWallet(adminWallet);
|
||||
const address = await auth.verify(payload, {
|
||||
validateNonce: (nonce: string) => {
|
||||
if (nonce === payload.payload.nonce) {
|
||||
if (nonce !== payload.payload.nonce) {
|
||||
throw new Error();
|
||||
}
|
||||
},
|
||||
});
|
||||
expect.fail();
|
||||
} catch (err: any) {
|
||||
expect(err.message).to.equal("Login request nonce is invalid");
|
||||
}
|
||||
});
|
||||
|
||||
it("Should accept valid nonce", async () => {
|
||||
const payload = await auth.login();
|
||||
|
||||
auth.updateWallet(adminWallet);
|
||||
const address = await auth.verify(payload, {
|
||||
validateNonce: (nonce: string) => {
|
||||
if (nonce !== payload.payload.nonce) {
|
||||
throw new Error();
|
||||
}
|
||||
},
|
||||
expect(address).to.equal(await signerWallet.getAddress());
|
||||
});
|
||||
|
||||
expect(address).to.equal(await signerWallet.getAddress());
|
||||
});
|
||||
it("Should reject payload with incorrect domain", async () => {
|
||||
const payload = await auth.login();
|
||||
|
||||
it("Should reject payload with incorrect domain", async () => {
|
||||
const payload = await auth.login();
|
||||
|
||||
auth.updateWallet(adminWallet);
|
||||
try {
|
||||
await auth.verify(payload, { domain: "test.thirdweb.com" });
|
||||
expect.fail();
|
||||
} catch (err: any) {
|
||||
expect(err.message).to.equal(
|
||||
"Expected domain 'test.thirdweb.com' does not match domain on payload 'thirdweb.com'",
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
it("Should reject expired login payload", async () => {
|
||||
const payload = await auth.login({
|
||||
expirationTime: new Date(Date.now() - 1000 * 60 * 5),
|
||||
auth.updateWallet(adminWallet);
|
||||
try {
|
||||
await auth.verify(payload, { domain: "test.thirdweb.com" });
|
||||
expect.fail();
|
||||
} catch (err: any) {
|
||||
expect(err.message).to.equal(
|
||||
"Expected domain 'test.thirdweb.com' does not match domain on payload 'thirdweb.com'",
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
auth.updateWallet(adminWallet);
|
||||
try {
|
||||
await auth.verify(payload);
|
||||
expect.fail();
|
||||
} catch (err: any) {
|
||||
expect(err.message).to.equal("Login request has expired");
|
||||
}
|
||||
});
|
||||
|
||||
it("Should reject payload with incorrect chain ID", async () => {
|
||||
const payload = await auth.login({
|
||||
chainId: "1",
|
||||
});
|
||||
|
||||
auth.updateWallet(adminWallet);
|
||||
try {
|
||||
await auth.verify(payload, {
|
||||
chainId: "137",
|
||||
it("Should reject expired login payload", async () => {
|
||||
const payload = await auth.login({
|
||||
expirationTime: new Date(Date.now() - 1000 * 60 * 5),
|
||||
});
|
||||
expect.fail();
|
||||
} catch (err: any) {
|
||||
expect(err.message).to.equal(
|
||||
"Expected chain ID '137' does not match chain ID on payload '1'",
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
it("Should reject payload with incorrect signer", async () => {
|
||||
const payload = await auth.login();
|
||||
payload.payload.address = await attackerWallet.getAddress();
|
||||
|
||||
auth.updateWallet(adminWallet);
|
||||
try {
|
||||
await auth.verify(payload);
|
||||
expect.fail();
|
||||
} catch (err: any) {
|
||||
expect(err.message).to.contain("does not match payload address");
|
||||
}
|
||||
});
|
||||
|
||||
it("Should generate valid authentication token", async () => {
|
||||
const payload = await auth.login();
|
||||
|
||||
auth.updateWallet(adminWallet);
|
||||
const token = await auth.generate(payload);
|
||||
const user = await auth.authenticate(token);
|
||||
|
||||
expect(user.address).to.equal(await signerWallet.getAddress());
|
||||
});
|
||||
|
||||
it("Should reject token with incorrect domain", async () => {
|
||||
const payload = await auth.login();
|
||||
|
||||
auth.updateWallet(adminWallet);
|
||||
const token = await auth.generate(payload);
|
||||
|
||||
try {
|
||||
await auth.authenticate(token, { domain: "test.thirdweb.com" });
|
||||
expect.fail();
|
||||
} catch (err: any) {
|
||||
expect(err.message).to.contain(
|
||||
"Expected token to be for the domain 'test.thirdweb.com', but found token with domain 'thirdweb.com'",
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
it("Should reject token before invalid before", async () => {
|
||||
const payload = await auth.login();
|
||||
|
||||
auth.updateWallet(adminWallet);
|
||||
const token = await auth.generate(payload, {
|
||||
invalidBefore: new Date(Date.now() + 1000 * 60 * 5),
|
||||
auth.updateWallet(adminWallet);
|
||||
try {
|
||||
await auth.verify(payload);
|
||||
expect.fail();
|
||||
} catch (err: any) {
|
||||
expect(err.message).to.equal("Login request has expired");
|
||||
}
|
||||
});
|
||||
|
||||
try {
|
||||
await auth.authenticate(token);
|
||||
expect.fail();
|
||||
} catch (err: any) {
|
||||
expect(err.message).to.contain("This token is invalid before");
|
||||
}
|
||||
});
|
||||
it("Should reject payload with incorrect chain ID", async () => {
|
||||
const payload = await auth.login({
|
||||
chainId: "1",
|
||||
});
|
||||
|
||||
it("Should reject expired authentication token", async () => {
|
||||
const payload = await auth.login();
|
||||
|
||||
auth.updateWallet(adminWallet);
|
||||
const token = await auth.generate(payload, {
|
||||
expirationTime: new Date(Date.now() - 1000 * 60 * 5),
|
||||
auth.updateWallet(adminWallet);
|
||||
try {
|
||||
await auth.verify(payload, {
|
||||
chainId: "137",
|
||||
});
|
||||
expect.fail();
|
||||
} catch (err: any) {
|
||||
expect(err.message).to.equal(
|
||||
"Expected chain ID '137' does not match chain ID on payload '1'",
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
try {
|
||||
await auth.authenticate(token);
|
||||
expect.fail();
|
||||
} catch (err: any) {
|
||||
expect(err.message).to.contain("This token expired");
|
||||
}
|
||||
});
|
||||
it("Should reject payload with incorrect signer", async () => {
|
||||
const payload = await auth.login();
|
||||
payload.payload.address = await attackerWallet.getAddress();
|
||||
|
||||
it("Should reject if admin address is not connected wallet address", async () => {
|
||||
const payload = await auth.login();
|
||||
|
||||
auth.updateWallet(adminWallet);
|
||||
const token = await auth.generate(payload);
|
||||
|
||||
auth.updateWallet(signerWallet);
|
||||
try {
|
||||
await auth.authenticate(token);
|
||||
expect.fail();
|
||||
} catch (err: any) {
|
||||
expect(err.message).to.contain(
|
||||
`The expected issuer address '${await signerWallet.getAddress()}' did not match the token issuer address '${await adminWallet.getAddress()}'`,
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
it("Should accept token with valid token ID", async () => {
|
||||
const payload = await auth.login();
|
||||
|
||||
auth.updateWallet(adminWallet);
|
||||
const token = await auth.generate(payload, {
|
||||
tokenId: "test",
|
||||
auth.updateWallet(adminWallet);
|
||||
try {
|
||||
await auth.verify(payload);
|
||||
expect.fail();
|
||||
} catch (err: any) {
|
||||
expect(err.message).to.contain("does not match payload address");
|
||||
}
|
||||
});
|
||||
|
||||
const user = await auth.authenticate(token, {
|
||||
validateTokenId: (tokenId: string) => {
|
||||
if (tokenId !== "test") {
|
||||
throw new Error();
|
||||
}
|
||||
},
|
||||
it("Should generate valid authentication token", async () => {
|
||||
const payload = await auth.login();
|
||||
|
||||
auth.updateWallet(adminWallet);
|
||||
const token = await auth.generate(payload);
|
||||
const user = await auth.authenticate(token);
|
||||
|
||||
expect(user.address).to.equal(await signerWallet.getAddress());
|
||||
});
|
||||
|
||||
expect(user.address).to.equal(await signerWallet.getAddress());
|
||||
});
|
||||
it("Should reject token with incorrect domain", async () => {
|
||||
const payload = await auth.login();
|
||||
|
||||
it("Should reject token with invalid token ID", async () => {
|
||||
const payload = await auth.login();
|
||||
auth.updateWallet(adminWallet);
|
||||
const token = await auth.generate(payload);
|
||||
|
||||
auth.updateWallet(adminWallet);
|
||||
const token = await auth.generate(payload, {
|
||||
tokenId: "test",
|
||||
try {
|
||||
await auth.authenticate(token, { domain: "test.thirdweb.com" });
|
||||
expect.fail();
|
||||
} catch (err: any) {
|
||||
expect(err.message).to.contain(
|
||||
"Expected token to be for the domain 'test.thirdweb.com', but found token with domain 'thirdweb.com'",
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
try {
|
||||
await auth.authenticate(token, {
|
||||
it("Should reject token before invalid before", async () => {
|
||||
const payload = await auth.login();
|
||||
|
||||
auth.updateWallet(adminWallet);
|
||||
const token = await auth.generate(payload, {
|
||||
invalidBefore: new Date(Date.now() + 1000 * 60 * 5),
|
||||
});
|
||||
|
||||
try {
|
||||
await auth.authenticate(token);
|
||||
expect.fail();
|
||||
} catch (err: any) {
|
||||
expect(err.message).to.contain("This token is invalid before");
|
||||
}
|
||||
});
|
||||
|
||||
it("Should reject expired authentication token", async () => {
|
||||
const payload = await auth.login();
|
||||
|
||||
auth.updateWallet(adminWallet);
|
||||
const token = await auth.generate(payload, {
|
||||
expirationTime: new Date(Date.now() - 1000 * 60 * 5),
|
||||
});
|
||||
|
||||
try {
|
||||
await auth.authenticate(token);
|
||||
expect.fail();
|
||||
} catch (err: any) {
|
||||
expect(err.message).to.contain("This token expired");
|
||||
}
|
||||
});
|
||||
|
||||
it("Should reject if admin address is not connected wallet address", async () => {
|
||||
const payload = await auth.login();
|
||||
|
||||
auth.updateWallet(adminWallet);
|
||||
const token = await auth.generate(payload);
|
||||
|
||||
auth.updateWallet(signerWallet);
|
||||
try {
|
||||
await auth.authenticate(token);
|
||||
expect.fail();
|
||||
} catch (err: any) {
|
||||
expect(err.message).to.contain(
|
||||
`The expected issuer address '${await signerWallet.getAddress()}' did not match the token issuer address '${await adminWallet.getAddress()}'`,
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
it("Should accept token with valid token ID", async () => {
|
||||
const payload = await auth.login();
|
||||
|
||||
auth.updateWallet(adminWallet);
|
||||
const token = await auth.generate(payload, {
|
||||
tokenId: "test",
|
||||
});
|
||||
|
||||
const user = await auth.authenticate(token, {
|
||||
validateTokenId: (tokenId: string) => {
|
||||
if (tokenId !== "invalid") {
|
||||
if (tokenId !== "test") {
|
||||
throw new Error();
|
||||
}
|
||||
},
|
||||
});
|
||||
expect.fail();
|
||||
} catch (err: any) {
|
||||
expect(err.message).to.contain("Token ID is invalid");
|
||||
}
|
||||
});
|
||||
|
||||
it("Should propagate session on token", async () => {
|
||||
const payload = await auth.login();
|
||||
|
||||
auth.updateWallet(adminWallet);
|
||||
const token = await auth.generate(payload, {
|
||||
session: { role: "admin" },
|
||||
expect(user.address).to.equal(await signerWallet.getAddress());
|
||||
});
|
||||
|
||||
const user = await auth.authenticate(token);
|
||||
it("Should reject token with invalid token ID", async () => {
|
||||
const payload = await auth.login();
|
||||
|
||||
expect(user.address).to.equal(await signerWallet.getAddress());
|
||||
expect(user.session).to.deep.equal({ role: "admin" });
|
||||
});
|
||||
auth.updateWallet(adminWallet);
|
||||
const token = await auth.generate(payload, {
|
||||
tokenId: "test",
|
||||
});
|
||||
|
||||
it("Should call session callback function", async () => {
|
||||
const payload = await auth.login();
|
||||
|
||||
auth.updateWallet(adminWallet);
|
||||
const token = await auth.generate(payload, {
|
||||
session: (address: string) => {
|
||||
return { address, role: "admin" };
|
||||
},
|
||||
try {
|
||||
await auth.authenticate(token, {
|
||||
validateTokenId: (tokenId: string) => {
|
||||
if (tokenId !== "invalid") {
|
||||
throw new Error();
|
||||
}
|
||||
},
|
||||
});
|
||||
expect.fail();
|
||||
} catch (err: any) {
|
||||
expect(err.message).to.contain("Token ID is invalid");
|
||||
}
|
||||
});
|
||||
|
||||
const user = await auth.authenticate(token);
|
||||
it("Should propagate session on token", async () => {
|
||||
const payload = await auth.login();
|
||||
|
||||
expect(user.address).to.equal(await signerWallet.getAddress());
|
||||
expect(user.session).to.deep.equal({
|
||||
address: await signerWallet.getAddress(),
|
||||
role: "admin",
|
||||
auth.updateWallet(adminWallet);
|
||||
const token = await auth.generate(payload, {
|
||||
session: { role: "admin" },
|
||||
});
|
||||
|
||||
const user = await auth.authenticate(token);
|
||||
|
||||
expect(user.address).to.equal(await signerWallet.getAddress());
|
||||
expect(user.session).to.deep.equal({ role: "admin" });
|
||||
});
|
||||
});
|
||||
|
||||
it("Should authenticate with issuer address", async () => {
|
||||
const payload = await auth.login();
|
||||
it("Should call session callback function", async () => {
|
||||
const payload = await auth.login();
|
||||
|
||||
auth.updateWallet(adminWallet);
|
||||
const token = await auth.generate(payload);
|
||||
auth.updateWallet(adminWallet);
|
||||
const token = await auth.generate(payload, {
|
||||
session: (address: string) => {
|
||||
return { address, role: "admin" };
|
||||
},
|
||||
});
|
||||
|
||||
auth.updateWallet(attackerWallet);
|
||||
try {
|
||||
await auth.authenticate(token);
|
||||
expect.fail();
|
||||
} catch (err: any) {
|
||||
expect(err.message).to.contain("The expected issuer address");
|
||||
}
|
||||
const user = await auth.authenticate(token);
|
||||
|
||||
const user = await auth.authenticate(token, {
|
||||
issuerAddress: await adminWallet.getAddress(),
|
||||
expect(user.address).to.equal(await signerWallet.getAddress());
|
||||
expect(user.session).to.deep.equal({
|
||||
address: await signerWallet.getAddress(),
|
||||
role: "admin",
|
||||
});
|
||||
});
|
||||
expect(user.address).to.equal(await signerWallet.getAddress());
|
||||
});
|
||||
});
|
||||
|
||||
it("Should authenticate with issuer address", async () => {
|
||||
const payload = await auth.login();
|
||||
|
||||
auth.updateWallet(adminWallet);
|
||||
const token = await auth.generate(payload);
|
||||
|
||||
auth.updateWallet(attackerWallet);
|
||||
try {
|
||||
await auth.authenticate(token);
|
||||
expect.fail();
|
||||
} catch (err: any) {
|
||||
expect(err.message).to.contain("The expected issuer address");
|
||||
}
|
||||
|
||||
const user = await auth.authenticate(token, {
|
||||
issuerAddress: await adminWallet.getAddress(),
|
||||
});
|
||||
expect(user.address).to.equal(await signerWallet.getAddress());
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
@@ -1,5 +1,31 @@
|
||||
# @thirdweb-dev/chains
|
||||
|
||||
## 0.1.87
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#2635](https://github.com/thirdweb-dev/js/pull/2635) [`fbf4556`](https://github.com/thirdweb-dev/js/commit/fbf4556d489b3be7c0c0ff85736e803573f55228) Thanks [@github-actions](https://github.com/apps/github-actions)! - Synced Chains Package
|
||||
|
||||
## 0.1.86
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#2597](https://github.com/thirdweb-dev/js/pull/2597) [`82e5f53`](https://github.com/thirdweb-dev/js/commit/82e5f53bc49208cbc43ef3eb64e3a4b6ef6c7cf6) Thanks [@github-actions](https://github.com/apps/github-actions)! - Synced Chains Package
|
||||
|
||||
## 0.1.85
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#2590](https://github.com/thirdweb-dev/js/pull/2590) [`3ef3786`](https://github.com/thirdweb-dev/js/commit/3ef378659e83341663dfaded417e33b5af29bbbc) Thanks [@github-actions](https://github.com/apps/github-actions)! - Synced Chains Package
|
||||
|
||||
## 0.1.84
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#2577](https://github.com/thirdweb-dev/js/pull/2577) [`d93286b`](https://github.com/thirdweb-dev/js/commit/d93286bc1f8224d055b50ce3ffa4f302869cb2b1) Thanks [@jnsdls](https://github.com/jnsdls)! - update dependencies
|
||||
|
||||
- [#2580](https://github.com/thirdweb-dev/js/pull/2580) [`50e7dba`](https://github.com/thirdweb-dev/js/commit/50e7dbaa9dae77cb8cd865405c322495e2498c65) Thanks [@github-actions](https://github.com/apps/github-actions)! - Synced Chains Package
|
||||
|
||||
## 0.1.83
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -46,7 +46,8 @@ export default {
|
||||
"https://evm.humans.stakepool.dev.br",
|
||||
"https://mainnet-humans-evm.konsortech.xyz",
|
||||
"https://evm-rpc.mainnet.humans.zone",
|
||||
"https://json-rpc.humans.bh.rocks"
|
||||
"https://json-rpc.humans.bh.rocks",
|
||||
"https://evm-rpc.humans.huginn.tech"
|
||||
],
|
||||
"shortName": "humans",
|
||||
"slug": "humans-ai",
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
import type { Chain } from "../src/types";
|
||||
export default {
|
||||
"chain": "NetMind",
|
||||
"chainId": 1100789,
|
||||
"explorers": [
|
||||
{
|
||||
"name": "NetMind Testnet Explorer",
|
||||
"url": "https://testbrower.protago-dev.com",
|
||||
"standard": "EIP3091",
|
||||
"icon": {
|
||||
"url": "ipfs://QmQNipd6uen7sm7HZXGbqhcSVkUXxu3Tp6c3BoeFpvmywp",
|
||||
"width": 500,
|
||||
"height": 500,
|
||||
"format": "png"
|
||||
}
|
||||
}
|
||||
],
|
||||
"faucets": [],
|
||||
"icon": {
|
||||
"url": "ipfs://QmQNipd6uen7sm7HZXGbqhcSVkUXxu3Tp6c3BoeFpvmywp",
|
||||
"width": 500,
|
||||
"height": 500,
|
||||
"format": "png"
|
||||
},
|
||||
"infoURL": "https://netmind.ai",
|
||||
"name": "Netmind Chain Testnet",
|
||||
"nativeCurrency": {
|
||||
"name": "NMT",
|
||||
"symbol": "NMT",
|
||||
"decimals": 18
|
||||
},
|
||||
"networkId": 1100789,
|
||||
"rpc": [
|
||||
"https://1100789.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
|
||||
"https://testblock.protago-dev.com"
|
||||
],
|
||||
"shortName": "nmtTest",
|
||||
"slug": "netmind-chain-testnet",
|
||||
"testnet": true,
|
||||
"title": "NetMind Chain Testnet"
|
||||
} as const satisfies Chain;
|
||||
@@ -0,0 +1,40 @@
|
||||
import type { Chain } from "../src/types";
|
||||
export default {
|
||||
"chain": "SC20",
|
||||
"chainId": 11221,
|
||||
"explorers": [
|
||||
{
|
||||
"name": "shinescan",
|
||||
"url": "https://shinescan.io",
|
||||
"standard": "none",
|
||||
"icon": {
|
||||
"url": "ipfs://QmUBkpY3prCTZHpx1fjrYLAJ6dPaGvNVTj97iy6p3NPUi1",
|
||||
"width": 161,
|
||||
"height": 161,
|
||||
"format": "png"
|
||||
}
|
||||
}
|
||||
],
|
||||
"faucets": [],
|
||||
"icon": {
|
||||
"url": "ipfs://QmUBkpY3prCTZHpx1fjrYLAJ6dPaGvNVTj97iy6p3NPUi1",
|
||||
"width": 161,
|
||||
"height": 161,
|
||||
"format": "png"
|
||||
},
|
||||
"infoURL": "https://shinechain.tech",
|
||||
"name": "Shine Chain",
|
||||
"nativeCurrency": {
|
||||
"name": "Shine",
|
||||
"symbol": "SC20",
|
||||
"decimals": 18
|
||||
},
|
||||
"networkId": 11221,
|
||||
"rpc": [
|
||||
"https://11221.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
|
||||
"https://rpc.shinescan.io"
|
||||
],
|
||||
"shortName": "SC20",
|
||||
"slug": "shine-chain",
|
||||
"testnet": false
|
||||
} as const satisfies Chain;
|
||||
@@ -0,0 +1,30 @@
|
||||
import type { Chain } from "../src/types";
|
||||
export default {
|
||||
"chain": "Avalanche",
|
||||
"chainId": 11227,
|
||||
"explorers": [],
|
||||
"faucets": [],
|
||||
"features": [],
|
||||
"icon": {
|
||||
"url": "https://images.ctfassets.net/9bazykntljf6/62CceHSYsRS4D9fgDSkLRB/877cb8f26954e1743ff535fd7fdaf78f/avacloud-placeholder.svg",
|
||||
"width": 256,
|
||||
"height": 256,
|
||||
"format": "svg"
|
||||
},
|
||||
"infoURL": "https://avacloud.io",
|
||||
"name": "Jiritsu Testnet",
|
||||
"nativeCurrency": {
|
||||
"name": "Jiritsu Testnet Token",
|
||||
"symbol": "TZW",
|
||||
"decimals": 18
|
||||
},
|
||||
"networkId": 11227,
|
||||
"redFlags": [],
|
||||
"rpc": [
|
||||
"https://11227.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
|
||||
"https://subnets.avax.network/jiritsutes/testnet/rpc"
|
||||
],
|
||||
"shortName": "Jiritsu Testnet",
|
||||
"slug": "jiritsu-testnet",
|
||||
"testnet": true
|
||||
} as const satisfies Chain;
|
||||
@@ -11,8 +11,8 @@ export default {
|
||||
"height": 300,
|
||||
"format": "png"
|
||||
},
|
||||
"infoURL": "https://raas.gelato.network/rollups/details/public/op-celestia-testnet",
|
||||
"name": "Gelato OP Celestia",
|
||||
"infoURL": "https://raas.gelato.network/rollups/details/public/opcelestia-raspberry",
|
||||
"name": "OP Celestia Rasberry",
|
||||
"nativeCurrency": {
|
||||
"name": "Ether",
|
||||
"symbol": "ETH",
|
||||
@@ -21,8 +21,8 @@ export default {
|
||||
"networkId": 123420111,
|
||||
"redFlags": [],
|
||||
"rpc": [],
|
||||
"shortName": "opcelestia",
|
||||
"slug": "gelato-op-celestia",
|
||||
"shortName": "opcelestia-rasberry",
|
||||
"slug": "op-celestia-rasberry",
|
||||
"testnet": true,
|
||||
"title": "Gelato OP Celestia Testnet"
|
||||
"title": "OP Celestia Rasberry"
|
||||
} as const satisfies Chain;
|
||||
@@ -0,0 +1,30 @@
|
||||
import type { Chain } from "../src/types";
|
||||
export default {
|
||||
"chain": "Avalanche",
|
||||
"chainId": 12781,
|
||||
"explorers": [],
|
||||
"faucets": [],
|
||||
"features": [],
|
||||
"icon": {
|
||||
"url": "https://images.ctfassets.net/9bazykntljf6/62CceHSYsRS4D9fgDSkLRB/877cb8f26954e1743ff535fd7fdaf78f/avacloud-placeholder.svg",
|
||||
"width": 256,
|
||||
"height": 256,
|
||||
"format": "svg"
|
||||
},
|
||||
"infoURL": "https://avacloud.io",
|
||||
"name": "playdapp Testnet",
|
||||
"nativeCurrency": {
|
||||
"name": "playdapp Testnet Token",
|
||||
"symbol": "PDA",
|
||||
"decimals": 18
|
||||
},
|
||||
"networkId": 12781,
|
||||
"redFlags": [],
|
||||
"rpc": [
|
||||
"https://12781.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
|
||||
"https://subnets.avax.network/playdappte/testnet/rpc"
|
||||
],
|
||||
"shortName": "playdapp Testnet",
|
||||
"slug": "playdapp-testnet",
|
||||
"testnet": true
|
||||
} as const satisfies Chain;
|
||||
@@ -2,9 +2,19 @@ import type { Chain } from "../src/types";
|
||||
export default {
|
||||
"chain": "Avalanche",
|
||||
"chainId": 13396,
|
||||
"explorers": [],
|
||||
"explorers": [
|
||||
{
|
||||
"name": "Masa Explorer",
|
||||
"url": "https://subnets.avax.network/masa",
|
||||
"standard": "EIP3091"
|
||||
}
|
||||
],
|
||||
"faucets": [],
|
||||
"features": [],
|
||||
"features": [
|
||||
{
|
||||
"name": "EIP1559"
|
||||
}
|
||||
],
|
||||
"icon": {
|
||||
"url": "https://images.ctfassets.net/9bazykntljf6/62CceHSYsRS4D9fgDSkLRB/877cb8f26954e1743ff535fd7fdaf78f/avacloud-placeholder.svg",
|
||||
"width": 256,
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
import type { Chain } from "../src/types";
|
||||
export default {
|
||||
"chain": "Avalanche",
|
||||
"chainId": 18109,
|
||||
"explorers": [],
|
||||
"faucets": [],
|
||||
"features": [],
|
||||
"icon": {
|
||||
"url": "https://images.ctfassets.net/9bazykntljf6/62CceHSYsRS4D9fgDSkLRB/877cb8f26954e1743ff535fd7fdaf78f/avacloud-placeholder.svg",
|
||||
"width": 256,
|
||||
"height": 256,
|
||||
"format": "svg"
|
||||
},
|
||||
"infoURL": "https://avacloud.io",
|
||||
"name": "QaUser7737 Testnet",
|
||||
"nativeCurrency": {
|
||||
"name": "QaUser7737 Testnet Token",
|
||||
"symbol": "XSP",
|
||||
"decimals": 18
|
||||
},
|
||||
"networkId": 18109,
|
||||
"redFlags": [],
|
||||
"rpc": [
|
||||
"https://18109.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
|
||||
"https://subnets.avax.network/defi-kingdoms/dfk-chain/rpc"
|
||||
],
|
||||
"shortName": "QaUser7737 Testnet",
|
||||
"slug": "qauser7737-testnet",
|
||||
"testnet": true
|
||||
} as const satisfies Chain;
|
||||
@@ -0,0 +1,30 @@
|
||||
import type { Chain } from "../src/types";
|
||||
export default {
|
||||
"chain": "Avalanche",
|
||||
"chainId": 24545,
|
||||
"explorers": [],
|
||||
"faucets": [],
|
||||
"features": [],
|
||||
"icon": {
|
||||
"url": "https://images.ctfassets.net/9bazykntljf6/62CceHSYsRS4D9fgDSkLRB/877cb8f26954e1743ff535fd7fdaf78f/avacloud-placeholder.svg",
|
||||
"width": 256,
|
||||
"height": 256,
|
||||
"format": "svg"
|
||||
},
|
||||
"infoURL": "https://avacloud.io",
|
||||
"name": "QaUser9167 Testnet",
|
||||
"nativeCurrency": {
|
||||
"name": "QaUser9167 Testnet Token",
|
||||
"symbol": "HBG",
|
||||
"decimals": 18
|
||||
},
|
||||
"networkId": 24545,
|
||||
"redFlags": [],
|
||||
"rpc": [
|
||||
"https://24545.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
|
||||
"https://subnets.avax.network/defi-kingdoms/dfk-chain/rpc"
|
||||
],
|
||||
"shortName": "QaUser9167 Testnet",
|
||||
"slug": "qauser9167-testnet",
|
||||
"testnet": true
|
||||
} as const satisfies Chain;
|
||||
@@ -0,0 +1,30 @@
|
||||
import type { Chain } from "../src/types";
|
||||
export default {
|
||||
"chain": "Avalanche",
|
||||
"chainId": 26031,
|
||||
"explorers": [],
|
||||
"faucets": [],
|
||||
"features": [],
|
||||
"icon": {
|
||||
"url": "https://images.ctfassets.net/9bazykntljf6/62CceHSYsRS4D9fgDSkLRB/877cb8f26954e1743ff535fd7fdaf78f/avacloud-placeholder.svg",
|
||||
"width": 256,
|
||||
"height": 256,
|
||||
"format": "svg"
|
||||
},
|
||||
"infoURL": "https://avacloud.io",
|
||||
"name": "QaUser7894 Testnet",
|
||||
"nativeCurrency": {
|
||||
"name": "QaUser7894 Testnet Token",
|
||||
"symbol": "YUT",
|
||||
"decimals": 18
|
||||
},
|
||||
"networkId": 26031,
|
||||
"redFlags": [],
|
||||
"rpc": [
|
||||
"https://26031.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
|
||||
"https://subnets.avax.network/defi-kingdoms/dfk-chain/rpc"
|
||||
],
|
||||
"shortName": "QaUser7894 Testnet",
|
||||
"slug": "qauser7894-testnet",
|
||||
"testnet": true
|
||||
} as const satisfies Chain;
|
||||
@@ -0,0 +1,46 @@
|
||||
import type { Chain } from "../src/types";
|
||||
export default {
|
||||
"chain": "ETH",
|
||||
"chainId": 282828,
|
||||
"explorers": [
|
||||
{
|
||||
"name": "zillscout",
|
||||
"url": "https://sepolia.zillnet.io",
|
||||
"standard": "EIP3091",
|
||||
"icon": {
|
||||
"url": "ipfs://QmfVmjLNiBh8KyCr9mwDZh34aEhhQ2LAjuP87DFxhfd9nn",
|
||||
"width": 264,
|
||||
"height": 264,
|
||||
"format": "png"
|
||||
}
|
||||
}
|
||||
],
|
||||
"faucets": [],
|
||||
"icon": {
|
||||
"url": "ipfs://QmfVmjLNiBh8KyCr9mwDZh34aEhhQ2LAjuP87DFxhfd9nn",
|
||||
"width": 264,
|
||||
"height": 264,
|
||||
"format": "png"
|
||||
},
|
||||
"infoURL": "https://zillnet.io",
|
||||
"name": "Zillion Sepolia Testnet",
|
||||
"nativeCurrency": {
|
||||
"name": "Sepolia Ether",
|
||||
"symbol": "ETH",
|
||||
"decimals": 18
|
||||
},
|
||||
"networkId": 282828,
|
||||
"parent": {
|
||||
"type": "L2",
|
||||
"chain": "eip155-11155111"
|
||||
},
|
||||
"rpc": [
|
||||
"https://282828.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
|
||||
"https://sepolia.zillnet.io/rpc"
|
||||
],
|
||||
"shortName": "zillsep",
|
||||
"slip44": 1,
|
||||
"slug": "zillion-sepolia-testnet",
|
||||
"status": "active",
|
||||
"testnet": true
|
||||
} as const satisfies Chain;
|
||||
@@ -0,0 +1,30 @@
|
||||
import type { Chain } from "../src/types";
|
||||
export default {
|
||||
"chain": "Avalanche",
|
||||
"chainId": 29830,
|
||||
"explorers": [],
|
||||
"faucets": [],
|
||||
"features": [],
|
||||
"icon": {
|
||||
"url": "https://images.ctfassets.net/9bazykntljf6/62CceHSYsRS4D9fgDSkLRB/877cb8f26954e1743ff535fd7fdaf78f/avacloud-placeholder.svg",
|
||||
"width": 256,
|
||||
"height": 256,
|
||||
"format": "svg"
|
||||
},
|
||||
"infoURL": "https://avacloud.io",
|
||||
"name": "QaUser6165 Testnet",
|
||||
"nativeCurrency": {
|
||||
"name": "QaUser6165 Testnet Token",
|
||||
"symbol": "TGQ",
|
||||
"decimals": 18
|
||||
},
|
||||
"networkId": 29830,
|
||||
"redFlags": [],
|
||||
"rpc": [
|
||||
"https://29830.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
|
||||
"https://subnets.avax.network/defi-kingdoms/dfk-chain/rpc"
|
||||
],
|
||||
"shortName": "QaUser6165 Testnet",
|
||||
"slug": "qauser6165-testnet",
|
||||
"testnet": true
|
||||
} as const satisfies Chain;
|
||||
@@ -0,0 +1,30 @@
|
||||
import type { Chain } from "../src/types";
|
||||
export default {
|
||||
"chain": "Avalanche",
|
||||
"chainId": 3084,
|
||||
"explorers": [],
|
||||
"faucets": [],
|
||||
"features": [],
|
||||
"icon": {
|
||||
"url": "https://images.ctfassets.net/9bazykntljf6/62CceHSYsRS4D9fgDSkLRB/877cb8f26954e1743ff535fd7fdaf78f/avacloud-placeholder.svg",
|
||||
"width": 256,
|
||||
"height": 256,
|
||||
"format": "svg"
|
||||
},
|
||||
"infoURL": "https://avacloud.io",
|
||||
"name": "XL Network Testnet",
|
||||
"nativeCurrency": {
|
||||
"name": "XL Network Testnet Token",
|
||||
"symbol": "XLN",
|
||||
"decimals": 18
|
||||
},
|
||||
"networkId": 3084,
|
||||
"redFlags": [],
|
||||
"rpc": [
|
||||
"https://3084.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
|
||||
"https://subnets.avax.network/xlnetworkt/testnet/rpc"
|
||||
],
|
||||
"shortName": "XL Network Testnet",
|
||||
"slug": "xl-network-testnet",
|
||||
"testnet": true
|
||||
} as const satisfies Chain;
|
||||
@@ -0,0 +1,30 @@
|
||||
import type { Chain } from "../src/types";
|
||||
export default {
|
||||
"chain": "Avalanche",
|
||||
"chainId": 31646,
|
||||
"explorers": [],
|
||||
"faucets": [],
|
||||
"features": [],
|
||||
"icon": {
|
||||
"url": "https://images.ctfassets.net/9bazykntljf6/62CceHSYsRS4D9fgDSkLRB/877cb8f26954e1743ff535fd7fdaf78f/avacloud-placeholder.svg",
|
||||
"width": 256,
|
||||
"height": 256,
|
||||
"format": "svg"
|
||||
},
|
||||
"infoURL": "https://avacloud.io",
|
||||
"name": "QaUser9492 Testnet",
|
||||
"nativeCurrency": {
|
||||
"name": "QaUser9492 Testnet Token",
|
||||
"symbol": "UVI",
|
||||
"decimals": 18
|
||||
},
|
||||
"networkId": 31646,
|
||||
"redFlags": [],
|
||||
"rpc": [
|
||||
"https://31646.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
|
||||
"https://subnets.avax.network/defi-kingdoms/dfk-chain/rpc"
|
||||
],
|
||||
"shortName": "QaUser9492 Testnet",
|
||||
"slug": "qauser9492-testnet",
|
||||
"testnet": true
|
||||
} as const satisfies Chain;
|
||||
@@ -0,0 +1,30 @@
|
||||
import type { Chain } from "../src/types";
|
||||
export default {
|
||||
"chain": "Avalanche",
|
||||
"chainId": 40868,
|
||||
"explorers": [],
|
||||
"faucets": [],
|
||||
"features": [],
|
||||
"icon": {
|
||||
"url": "https://images.ctfassets.net/9bazykntljf6/62CceHSYsRS4D9fgDSkLRB/877cb8f26954e1743ff535fd7fdaf78f/avacloud-placeholder.svg",
|
||||
"width": 256,
|
||||
"height": 256,
|
||||
"format": "svg"
|
||||
},
|
||||
"infoURL": "https://avacloud.io",
|
||||
"name": "QaUser5110 Testnet",
|
||||
"nativeCurrency": {
|
||||
"name": "QaUser5110 Testnet Token",
|
||||
"symbol": "CRL",
|
||||
"decimals": 18
|
||||
},
|
||||
"networkId": 40868,
|
||||
"redFlags": [],
|
||||
"rpc": [
|
||||
"https://40868.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
|
||||
"https://subnets.avax.network/defi-kingdoms/dfk-chain/rpc"
|
||||
],
|
||||
"shortName": "QaUser5110 Testnet",
|
||||
"slug": "qauser5110-testnet",
|
||||
"testnet": true
|
||||
} as const satisfies Chain;
|
||||
@@ -0,0 +1,30 @@
|
||||
import type { Chain } from "../src/types";
|
||||
export default {
|
||||
"chain": "Avalanche",
|
||||
"chainId": 48137,
|
||||
"explorers": [],
|
||||
"faucets": [],
|
||||
"features": [],
|
||||
"icon": {
|
||||
"url": "https://images.ctfassets.net/9bazykntljf6/62CceHSYsRS4D9fgDSkLRB/877cb8f26954e1743ff535fd7fdaf78f/avacloud-placeholder.svg",
|
||||
"width": 256,
|
||||
"height": 256,
|
||||
"format": "svg"
|
||||
},
|
||||
"infoURL": "https://avacloud.io",
|
||||
"name": "QaUser9608 Testnet",
|
||||
"nativeCurrency": {
|
||||
"name": "QaUser9608 Testnet Token",
|
||||
"symbol": "ASI",
|
||||
"decimals": 18
|
||||
},
|
||||
"networkId": 48137,
|
||||
"redFlags": [],
|
||||
"rpc": [
|
||||
"https://48137.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
|
||||
"https://subnets.avax.network/defi-kingdoms/dfk-chain/rpc"
|
||||
],
|
||||
"shortName": "QaUser9608 Testnet",
|
||||
"slug": "qauser9608-testnet",
|
||||
"testnet": true
|
||||
} as const satisfies Chain;
|
||||
@@ -0,0 +1,28 @@
|
||||
import type { Chain } from "../src/types";
|
||||
export default {
|
||||
"chain": "Azra Testnet",
|
||||
"chainId": 5106,
|
||||
"explorers": [
|
||||
{
|
||||
"name": "blockscout",
|
||||
"url": "https://explorerl2new-azra-testnet-6hz86owb1n.t.conduit.xyz",
|
||||
"standard": "EIP3091"
|
||||
}
|
||||
],
|
||||
"faucets": [],
|
||||
"infoURL": "https://azragames.com",
|
||||
"name": "Azra Testnet",
|
||||
"nativeCurrency": {
|
||||
"name": "ETH",
|
||||
"symbol": "ETH",
|
||||
"decimals": 18
|
||||
},
|
||||
"networkId": 5106,
|
||||
"rpc": [
|
||||
"https://5106.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
|
||||
"https://rpc-azra-testnet-6hz86owb1n.t.conduit.xyz"
|
||||
],
|
||||
"shortName": "azra-testnet",
|
||||
"slug": "azra-testnet",
|
||||
"testnet": true
|
||||
} as const satisfies Chain;
|
||||
@@ -0,0 +1,30 @@
|
||||
import type { Chain } from "../src/types";
|
||||
export default {
|
||||
"chain": "Avalanche",
|
||||
"chainId": 54763,
|
||||
"explorers": [],
|
||||
"faucets": [],
|
||||
"features": [],
|
||||
"icon": {
|
||||
"url": "https://images.ctfassets.net/9bazykntljf6/62CceHSYsRS4D9fgDSkLRB/877cb8f26954e1743ff535fd7fdaf78f/avacloud-placeholder.svg",
|
||||
"width": 256,
|
||||
"height": 256,
|
||||
"format": "svg"
|
||||
},
|
||||
"infoURL": "https://avacloud.io",
|
||||
"name": "QaUser3051 Testnet",
|
||||
"nativeCurrency": {
|
||||
"name": "QaUser3051 Testnet Token",
|
||||
"symbol": "DSX",
|
||||
"decimals": 18
|
||||
},
|
||||
"networkId": 54763,
|
||||
"redFlags": [],
|
||||
"rpc": [
|
||||
"https://54763.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
|
||||
"https://subnets.avax.network/defi-kingdoms/dfk-chain/rpc"
|
||||
],
|
||||
"shortName": "QaUser3051 Testnet",
|
||||
"slug": "qauser3051-testnet",
|
||||
"testnet": true
|
||||
} as const satisfies Chain;
|
||||
@@ -0,0 +1,30 @@
|
||||
import type { Chain } from "../src/types";
|
||||
export default {
|
||||
"chain": "Avalanche",
|
||||
"chainId": 555666,
|
||||
"explorers": [],
|
||||
"faucets": [],
|
||||
"features": [],
|
||||
"icon": {
|
||||
"url": "https://images.ctfassets.net/9bazykntljf6/62CceHSYsRS4D9fgDSkLRB/877cb8f26954e1743ff535fd7fdaf78f/avacloud-placeholder.svg",
|
||||
"width": 256,
|
||||
"height": 256,
|
||||
"format": "svg"
|
||||
},
|
||||
"infoURL": "https://avacloud.io",
|
||||
"name": "EclipseChain Testnet",
|
||||
"nativeCurrency": {
|
||||
"name": "EclipseChain Testnet Token",
|
||||
"symbol": "ECLPS",
|
||||
"decimals": 18
|
||||
},
|
||||
"networkId": 555666,
|
||||
"redFlags": [],
|
||||
"rpc": [
|
||||
"https://555666.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
|
||||
"https://subnets.avax.network/eclipsecha/testnet/rpc"
|
||||
],
|
||||
"shortName": "EclipseChain Testnet",
|
||||
"slug": "eclipsechain-testnet",
|
||||
"testnet": true
|
||||
} as const satisfies Chain;
|
||||
@@ -0,0 +1,30 @@
|
||||
import type { Chain } from "../src/types";
|
||||
export default {
|
||||
"chain": "Avalanche",
|
||||
"chainId": 57973,
|
||||
"explorers": [],
|
||||
"faucets": [],
|
||||
"features": [],
|
||||
"icon": {
|
||||
"url": "https://images.ctfassets.net/9bazykntljf6/62CceHSYsRS4D9fgDSkLRB/877cb8f26954e1743ff535fd7fdaf78f/avacloud-placeholder.svg",
|
||||
"width": 256,
|
||||
"height": 256,
|
||||
"format": "svg"
|
||||
},
|
||||
"infoURL": "https://avacloud.io",
|
||||
"name": "QaUser5524 Testnet",
|
||||
"nativeCurrency": {
|
||||
"name": "QaUser5524 Testnet Token",
|
||||
"symbol": "ADN",
|
||||
"decimals": 18
|
||||
},
|
||||
"networkId": 57973,
|
||||
"redFlags": [],
|
||||
"rpc": [
|
||||
"https://57973.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
|
||||
"https://subnets.avax.network/defi-kingdoms/dfk-chain/rpc"
|
||||
],
|
||||
"shortName": "QaUser5524 Testnet",
|
||||
"slug": "qauser5524-testnet",
|
||||
"testnet": true
|
||||
} as const satisfies Chain;
|
||||
@@ -0,0 +1,28 @@
|
||||
import type { Chain } from "../src/types";
|
||||
export default {
|
||||
"chain": "BounceBit",
|
||||
"chainId": 6000,
|
||||
"explorers": [
|
||||
{
|
||||
"name": "BBScan Testnet Explorer",
|
||||
"url": "https://bbscan.io",
|
||||
"standard": "none"
|
||||
}
|
||||
],
|
||||
"faucets": [],
|
||||
"infoURL": "https://bouncebit.io",
|
||||
"name": "BounceBit Testnet",
|
||||
"nativeCurrency": {
|
||||
"name": "BounceBit",
|
||||
"symbol": "BB",
|
||||
"decimals": 18
|
||||
},
|
||||
"networkId": 6000,
|
||||
"rpc": [
|
||||
"https://6000.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
|
||||
"https://fullnode-testnet.bouncebitapi.com/"
|
||||
],
|
||||
"shortName": "bouncebit-testnet",
|
||||
"slug": "bouncebit-testnet",
|
||||
"testnet": true
|
||||
} as const satisfies Chain;
|
||||
@@ -10,7 +10,7 @@ export default {
|
||||
},
|
||||
{
|
||||
"name": "Astar zkEVM Testnet zKyoto",
|
||||
"url": "hhttps://zkyoto.explorer.startale.com/",
|
||||
"url": "https://zkyoto.explorer.startale.com",
|
||||
"standard": "EIP3091"
|
||||
}
|
||||
],
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
import type { Chain } from "../src/types";
|
||||
export default {
|
||||
"chain": "ETH",
|
||||
"chainId": 70700,
|
||||
"explorers": [
|
||||
{
|
||||
"name": "Proof of Play Apex Explorer",
|
||||
"url": "https://explorer.apex.proofofplay.com",
|
||||
"standard": "EIP3091",
|
||||
"icon": {
|
||||
"url": "ipfs://QmW3NPDe6WRqucrWbe8pg3GqSMPi8V6Qa1fAiaQuqjxSJC",
|
||||
"width": 1256,
|
||||
"height": 1256,
|
||||
"format": "png"
|
||||
}
|
||||
}
|
||||
],
|
||||
"faucets": [],
|
||||
"icon": {
|
||||
"url": "ipfs://QmW3NPDe6WRqucrWbe8pg3GqSMPi8V6Qa1fAiaQuqjxSJC",
|
||||
"width": 1256,
|
||||
"height": 1256,
|
||||
"format": "png"
|
||||
},
|
||||
"infoURL": "https://proofofplay.com",
|
||||
"name": "Proof of Play - Apex",
|
||||
"nativeCurrency": {
|
||||
"name": "Ether",
|
||||
"symbol": "ETH",
|
||||
"decimals": 18
|
||||
},
|
||||
"networkId": 70700,
|
||||
"parent": {
|
||||
"type": "L2",
|
||||
"chain": "eip155-42161",
|
||||
"bridges": [
|
||||
{
|
||||
"url": "https://bridge.arbitrum.io"
|
||||
},
|
||||
{
|
||||
"url": "https://relay.link/bridge/apex/"
|
||||
}
|
||||
]
|
||||
},
|
||||
"rpc": [
|
||||
"https://70700.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
|
||||
"https://rpc.apex.proofofplay.com"
|
||||
],
|
||||
"shortName": "pop-apex",
|
||||
"slug": "proof-of-play-apex",
|
||||
"testnet": false
|
||||
} as const satisfies Chain;
|
||||
@@ -0,0 +1,35 @@
|
||||
import type { Chain } from "../src/types";
|
||||
export default {
|
||||
"chain": "Ankara",
|
||||
"chainId": 72778,
|
||||
"explorers": [
|
||||
{
|
||||
"name": "ankara",
|
||||
"url": "https://explorer.ankara-cagacrypto.com",
|
||||
"standard": "EIP3091"
|
||||
}
|
||||
],
|
||||
"faucets": [],
|
||||
"icon": {
|
||||
"url": "ipfs://Qmeiop9gSdzU4NNJ6GCuPk6AeYwD9pbhEFVfRdk4dXs3kJ",
|
||||
"width": 640,
|
||||
"height": 640,
|
||||
"format": "png"
|
||||
},
|
||||
"infoURL": "https://www.cagacrypto.com/",
|
||||
"name": "CAGA crypto Ankara testnet",
|
||||
"nativeCurrency": {
|
||||
"name": "Caga",
|
||||
"symbol": "CAGA",
|
||||
"decimals": 18
|
||||
},
|
||||
"networkId": 72778,
|
||||
"rpc": [
|
||||
"https://72778.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
|
||||
"https://www.ankara-cagacrypto.com",
|
||||
"wss://wss.ankara-cagacrypto.com"
|
||||
],
|
||||
"shortName": "caga",
|
||||
"slug": "caga-crypto-ankara-testnet",
|
||||
"testnet": true
|
||||
} as const satisfies Chain;
|
||||
@@ -0,0 +1,30 @@
|
||||
import type { Chain } from "../src/types";
|
||||
export default {
|
||||
"chain": "Avalanche",
|
||||
"chainId": 7317,
|
||||
"explorers": [],
|
||||
"faucets": [],
|
||||
"features": [],
|
||||
"icon": {
|
||||
"url": "https://images.ctfassets.net/9bazykntljf6/62CceHSYsRS4D9fgDSkLRB/877cb8f26954e1743ff535fd7fdaf78f/avacloud-placeholder.svg",
|
||||
"width": 256,
|
||||
"height": 256,
|
||||
"format": "svg"
|
||||
},
|
||||
"infoURL": "https://avacloud.io",
|
||||
"name": "QaUser5017 Testnet",
|
||||
"nativeCurrency": {
|
||||
"name": "QaUser5017 Testnet Token",
|
||||
"symbol": "IHS",
|
||||
"decimals": 18
|
||||
},
|
||||
"networkId": 7317,
|
||||
"redFlags": [],
|
||||
"rpc": [
|
||||
"https://7317.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
|
||||
"https://subnets.avax.network/defi-kingdoms/dfk-chain/rpc"
|
||||
],
|
||||
"shortName": "QaUser5017 Testnet",
|
||||
"slug": "qauser5017-testnet",
|
||||
"testnet": true
|
||||
} as const satisfies Chain;
|
||||
@@ -0,0 +1,30 @@
|
||||
import type { Chain } from "../src/types";
|
||||
export default {
|
||||
"chain": "Avalanche",
|
||||
"chainId": 7507,
|
||||
"explorers": [],
|
||||
"faucets": [],
|
||||
"features": [],
|
||||
"icon": {
|
||||
"url": "https://images.ctfassets.net/9bazykntljf6/62CceHSYsRS4D9fgDSkLRB/877cb8f26954e1743ff535fd7fdaf78f/avacloud-placeholder.svg",
|
||||
"width": 256,
|
||||
"height": 256,
|
||||
"format": "svg"
|
||||
},
|
||||
"infoURL": "https://avacloud.io",
|
||||
"name": "QaUser7740 Testnet",
|
||||
"nativeCurrency": {
|
||||
"name": "QaUser7740 Testnet Token",
|
||||
"symbol": "RUI",
|
||||
"decimals": 18
|
||||
},
|
||||
"networkId": 7507,
|
||||
"redFlags": [],
|
||||
"rpc": [
|
||||
"https://7507.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
|
||||
"https://subnets.avax.network/defi-kingdoms/dfk-chain/rpc"
|
||||
],
|
||||
"shortName": "QaUser7740 Testnet",
|
||||
"slug": "qauser7740-testnet",
|
||||
"testnet": true
|
||||
} as const satisfies Chain;
|
||||
@@ -0,0 +1,30 @@
|
||||
import type { Chain } from "../src/types";
|
||||
export default {
|
||||
"chain": "Avalanche",
|
||||
"chainId": 764984,
|
||||
"explorers": [],
|
||||
"faucets": [],
|
||||
"features": [],
|
||||
"icon": {
|
||||
"url": "https://images.ctfassets.net/9bazykntljf6/62CceHSYsRS4D9fgDSkLRB/877cb8f26954e1743ff535fd7fdaf78f/avacloud-placeholder.svg",
|
||||
"width": 256,
|
||||
"height": 256,
|
||||
"format": "svg"
|
||||
},
|
||||
"infoURL": "https://avacloud.io",
|
||||
"name": "Lamina1 Testnet",
|
||||
"nativeCurrency": {
|
||||
"name": "Lamina1 Testnet Token",
|
||||
"symbol": "L1T",
|
||||
"decimals": 18
|
||||
},
|
||||
"networkId": 764984,
|
||||
"redFlags": [],
|
||||
"rpc": [
|
||||
"https://764984.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
|
||||
"https://subnets.avax.network/lamina1tes/testnet/rpc"
|
||||
],
|
||||
"shortName": "Lamina1 Testnet",
|
||||
"slug": "lamina1-testnet",
|
||||
"testnet": true
|
||||
} as const satisfies Chain;
|
||||
@@ -0,0 +1,44 @@
|
||||
import type { Chain } from "../src/types";
|
||||
export default {
|
||||
"chain": "OEX",
|
||||
"chainId": 7798,
|
||||
"explorers": [
|
||||
{
|
||||
"name": "OpenEX Long Testnet Explorer",
|
||||
"url": "https://scan.long.openex.network",
|
||||
"standard": "EIP3091",
|
||||
"icon": {
|
||||
"url": "ipfs://bafkreidnu6p6vmmplerzvkboq7fz73ygkomzpnnokuxstrqv2fvxgmgg7i",
|
||||
"width": 512,
|
||||
"height": 512,
|
||||
"format": "png"
|
||||
}
|
||||
}
|
||||
],
|
||||
"faucets": [
|
||||
"https://long.hub.openex.network/faucet"
|
||||
],
|
||||
"icon": {
|
||||
"url": "ipfs://bafkreidnu6p6vmmplerzvkboq7fz73ygkomzpnnokuxstrqv2fvxgmgg7i",
|
||||
"width": 512,
|
||||
"height": 512,
|
||||
"format": "png"
|
||||
},
|
||||
"infoURL": "https://openex.network",
|
||||
"name": "OpenEX LONG Testnet",
|
||||
"nativeCurrency": {
|
||||
"name": "USDT Testnet",
|
||||
"symbol": "USDT",
|
||||
"decimals": 18
|
||||
},
|
||||
"networkId": 7798,
|
||||
"rpc": [
|
||||
"https://7798.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
|
||||
"https://long.rpc.openex.network/"
|
||||
],
|
||||
"shortName": "oex",
|
||||
"slip44": 1,
|
||||
"slug": "openex-long-testnet",
|
||||
"testnet": true,
|
||||
"title": "OpenEX LONG Testnet"
|
||||
} as const satisfies Chain;
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user