Compare commits

...
Author SHA1 Message Date
Jonas DanielsGitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>GitHub Action
755cffe590 Version Packages (#2589)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: GitHub Action <[email protected]>
2024-03-29 16:17:16 -07:00
Manan TankandGitHub dd1141f9af fix: Do not open wallet uri when connected using official WC modal (#2595) 2024-03-29 23:00:55 +00:00
Joaquim VergesandGitHub 968fdc3ebe chore: add smart wallet exports for user op types (#2594) 2024-03-29 22:29:21 +00:00
2ef20589b7 chore(chains): update chains (#2593)
Co-authored-by: GitHub Action <[email protected]>
2024-03-29 15:07:03 -07:00
Manan TankandGitHub 6d63920c0a feat: add walletConnect, Fix WC connection issues (#2591) 2024-03-29 21:58:03 +00:00
3ef378659e chore(chains): update chains (#2590)
Co-authored-by: GitHub Action <[email protected]>
2024-03-29 14:24:29 -07:00
Joaquim VergesandGitHub eba8f1c198 fix: 721/1155 claimTo with custom currency (#2588) 2024-03-29 19:45:02 +00:00
Jonas DanielsGitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>GitHub Action
52f827e8f2 Version Packages (#2586)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: GitHub Action <[email protected]>
2024-03-29 11:37:16 -07:00
Jonas DanielsandGitHub 6063f40f87 fix(cli): fix execution on windows and when prettier is not installed (#2587) 2024-03-29 18:16:38 +00:00
YashandGitHub 6bd1b82a58 [CLI] Publish and deploy updates for ZKSync (#2584) 2024-03-29 17:12:50 +00:00
Manan TankandGitHub 052892b396 [v5] Fix WC session request (#2585) 2024-03-29 17:09:06 +00:00
Jonas DanielsGitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>GitHub Action
3b12c5c926 Version Packages (#2574)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: GitHub Action <[email protected]>
2024-03-29 03:59:31 -07:00
Jonas DanielsandGitHub 02d2377ca5 build: Update dependencies in package.json (#2582) 2024-03-29 03:44:43 -07:00
9545005908 chore(chains): update chains (#2581)
Co-authored-by: GitHub Action <[email protected]>
2024-03-29 03:43:37 -07:00
Jonas DanielsandGitHub d93286bc1f chore: Update devDependencies versions (#2577) 2024-03-29 10:29:33 +00:00
50e7dbaa9d chore(chains): update chains (#2580)
Co-authored-by: GitHub Action <[email protected]>
2024-03-28 21:05:46 -07:00
Joaquim VergesandGitHub 04961f0e9a feat: change getWalletBalance prop from account to address (#2576) 2024-03-28 23:45:15 +00:00
Jonas DanielsandGitHub 37f8433c7c chore: Skip benchmark step for merge groups (#2575) 2024-03-28 22:29:33 +00:00
Jonas DanielsandGitHub c81bb882c5 fix(evm): fix CWE-1333 (#2573) 2024-03-28 22:22:51 +00:00
Jonas DanielsandGitHub 701cd880df chore: point CLI backwards compatibility @latest instead of @beta (#2572) 2024-03-28 22:10:17 +00:00
194 changed files with 8281 additions and 10556 deletions
+2 -2
View File
@@ -4,11 +4,11 @@ description: "Sets up Node.js and runs install"
runs:
using: composite
steps:
- uses: pnpm/action-setup@v2
- 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
registry-url: "https://registry.npmjs.org"
+59 -21
View File
@@ -28,14 +28,14 @@ jobs:
steps:
- name: Check out code
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
fetch-depth: 25
- 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
@@ -46,7 +46,7 @@ jobs:
- id: get-week
run: echo "WEEK=$(date +%U)" >> $GITHUB_OUTPUT
- uses: actions/cache@v3
- uses: actions/cache@v4
timeout-minutes: 5
id: cache-build
with:
@@ -60,7 +60,7 @@ jobs:
needs: build
steps:
- name: Setup node
uses: actions/setup-node@v3
uses: actions/setup-node@v4
with:
node-version: 20
check-latest: true
@@ -68,13 +68,13 @@ jobs:
- name: Setup bun
uses: oven-sh/setup-bun@v1
with:
bun-version: 1.0.21
bun-version: 1.0.35
- uses: pnpm/action-setup@v2
- uses: pnpm/action-setup@v3
with:
version: 8
- uses: actions/cache@v3
- uses: actions/cache@v4
timeout-minutes: 5
id: restore-build
with:
@@ -90,7 +90,7 @@ jobs:
needs: build
steps:
- name: Setup node
uses: actions/setup-node@v3
uses: actions/setup-node@v4
with:
node-version: 20
check-latest: true
@@ -99,13 +99,13 @@ jobs:
- name: Setup bun
uses: oven-sh/setup-bun@v1
with:
bun-version: 1.0.21
bun-version: 1.0.35
- uses: pnpm/action-setup@v2
- uses: pnpm/action-setup@v3
with:
version: 8
- uses: actions/cache@v3
- uses: actions/cache@v4
timeout-minutes: 5
id: restore-build
with:
@@ -120,16 +120,16 @@ jobs:
- 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
files: ./packages/thirdweb/coverage/lcov.info
e2e:
test_legacy:
timeout-minutes: 15
name: E2E Tests
name: Unit Tests (Legacy)
runs-on: ubuntu-latest-16
needs: build
steps:
- name: Setup node
uses: actions/setup-node@v3
uses: actions/setup-node@v4
with:
node-version: 20
check-latest: true
@@ -138,13 +138,49 @@ jobs:
- name: Setup bun
uses: oven-sh/setup-bun@v1
with:
bun-version: 1.0.21
bun-version: 1.0.35
- uses: pnpm/action-setup@v2
- uses: pnpm/action-setup@v3
with:
version: 8
- uses: actions/cache@v3
- uses: actions/cache@v4
timeout-minutes: 5
id: restore-build
with:
path: ./*
key: ${{ github.sha }}-${{ github.run_number }}
- run: pnpm test:legacy
- name: Upload coverage reports to Codecov
uses: codecov/codecov-action@v3
with:
files: ./legacy_packages/sdk/coverage/evm/lcov.info
e2e:
timeout-minutes: 15
name: E2E Tests
runs-on: ubuntu-latest-16
needs: build
steps:
- name: Setup node
uses: actions/setup-node@v4
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.35
- uses: pnpm/action-setup@v3
with:
version: 8
- uses: actions/cache@v4
timeout-minutes: 5
id: restore-build
with:
@@ -161,22 +197,24 @@ jobs:
CLI_E2E_API_KEY: ${{ secrets.CLI_E2E_API_KEY }}
benchmark:
# only run if is not merge_group
if: github.event_name != 'merge_group'
timeout-minutes: 15
name: "Benchmark"
runs-on: ubuntu-latest-16
needs: build
steps:
- name: Setup node
uses: actions/setup-node@v3
uses: actions/setup-node@v4
with:
node-version: 20
check-latest: true
- uses: pnpm/action-setup@v2
- uses: pnpm/action-setup@v3
with:
version: 8
- uses: actions/cache@v3
- uses: actions/cache@v4
timeout-minutes: 5
id: restore-build
with:
+30 -31
View File
@@ -13,12 +13,12 @@ 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"
jobs:
analyze:
@@ -32,41 +32,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@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.
# 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@v2
# 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@v2
+2 -2
View File
@@ -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
+2 -2
View File
@@ -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
+2 -2
View File
@@ -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
+1 -1
View File
@@ -15,7 +15,7 @@ jobs:
- 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
+23
View File
@@ -1,5 +1,28 @@
# @thirdweb-dev/auth
## 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
+25 -32
View File
@@ -1,6 +1,6 @@
{
"name": "@thirdweb-dev/auth",
"version": "4.1.49",
"version": "4.1.52",
"main": "dist/thirdweb-dev-auth.cjs.js",
"module": "dist/thirdweb-dev-auth.esm.js",
"browser": {
@@ -61,7 +61,7 @@
"lint": "eslint src/ && bunx publint --strict --level warning",
"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"
-8
View File
@@ -1,8 +0,0 @@
{
"extension": [
"ts"
],
"require": [
"@swc-node/register"
]
}
+334 -327
View File
@@ -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(
"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());
});
},
);
+320 -313
View File
@@ -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(
"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());
});
},
);
+14
View File
@@ -1,5 +1,19 @@
# @thirdweb-dev/chains
## 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
+41
View File
@@ -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;
+28
View File
@@ -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;
+35
View File
@@ -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;
+1
View File
@@ -39,6 +39,7 @@ export default {
"shortName": "maticmum",
"slip44": 1,
"slug": "mumbai",
"status": "active",
"testnet": true,
"title": "Polygon Testnet Mumbai"
} as const satisfies Chain;
+40
View File
@@ -0,0 +1,40 @@
import type { Chain } from "../src/types";
export default {
"chain": "SPENT",
"chainId": 9911,
"explorers": [
{
"name": "escscan",
"url": "https://escscan.com",
"standard": "EIP3091",
"icon": {
"url": "ipfs://QmVvQdmAj6GNQjP1dsxQKbA7xgzqsciooGTQtQ2RsJ37Lf",
"width": 335,
"height": 335,
"format": "svg"
}
}
],
"faucets": [],
"icon": {
"url": "ipfs://QmVvQdmAj6GNQjP1dsxQKbA7xgzqsciooGTQtQ2RsJ37Lf",
"width": 335,
"height": 335,
"format": "svg"
},
"infoURL": "https://espento.network",
"name": "Espento Mainnet",
"nativeCurrency": {
"name": "ESPENTO",
"symbol": "SPENT",
"decimals": 18
},
"networkId": 9911,
"rpc": [
"https://9911.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://rpc.escscan.com/"
],
"shortName": "spent",
"slug": "espento",
"testnet": false
} as const satisfies Chain;
+30
View File
@@ -0,0 +1,30 @@
import type { Chain } from "../src/types";
export default {
"chain": "Avalanche",
"chainId": 99308,
"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": "Borne Gaming Testnet",
"nativeCurrency": {
"name": "Borne Gaming Testnet Token",
"symbol": "BORNE",
"decimals": 18
},
"networkId": 99308,
"redFlags": [],
"rpc": [
"https://99308.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://subnets.avax.network/bornegamin/testnet/rpc"
],
"shortName": "Borne Gaming Testnet",
"slug": "borne-gaming-testnet",
"testnet": true
} as const satisfies Chain;
+3 -10
View File
@@ -1,6 +1,6 @@
{
"name": "@thirdweb-dev/chains",
"version": "0.1.83",
"version": "0.1.85",
"main": "dist/thirdweb-dev-chains.cjs.js",
"module": "dist/thirdweb-dev-chains.esm.js",
"exports": {
@@ -12,15 +12,11 @@
},
"author": "thirdweb eng <[email protected]>",
"devDependencies": {
"@babel/core": "^7.23.7",
"@babel/preset-env": "^7.23.8",
"@babel/preset-typescript": "^7.23.3",
"@babel/runtime": "^7.23.8",
"@babel/runtime": "^7.24.1",
"@preconstruct/cli": "2.7.0",
"@thirdweb-dev/tsconfig": "workspace:*",
"eslint-config-thirdweb": "workspace:*",
"plop": "^3.1.2",
"typescript": "^5.3.3"
"typescript": "5.4.3"
},
"preconstruct": {
"entrypoints": [
@@ -34,9 +30,6 @@
"db:sync": "bun scripts/sync-db.ts",
"build": "tsc && preconstruct build",
"push": "yalc push",
"plop": "plop",
"add-chain": "plop add-chain",
"override-chain": "plop override-chain",
"test": "bun test"
},
"engines": {
-80
View File
@@ -1,80 +0,0 @@
const chainIdPrompt = {
type: "number",
name: "chainId",
message: "Chain ID",
validate: (value) => {
if (value.length === 0) {
return "ChainId is required";
}
if (!/^\d+$/.test(value)) {
return "ChainId must be a number";
}
return true;
},
};
const stringPrompt = (id, title, isRequired) => ({
type: "input",
name: id,
message: title,
validate: (value) => {
if (isRequired && value.length === 0) {
return `${title} is required`;
}
return true;
},
});
const testnetPrompt = {
type: "confirm",
name: "isTestnet",
message: "Is this a testnet?",
};
export default function (
/** @type {import('plop').NodePlopAPI} */
plop,
) {
// add partials
plop.setPartial("chainIdPartial", "chainId: {{chainId}},\n");
plop.setPartial("namePartial", `name: "{{name}}",\n`);
plop.setPartial("chainPartial", `chain: "{{chain}}",\n`);
plop.setPartial("shortNamePartial", `shortName: "{{shortName}}",\n`);
plop.setPartial("isTestnetPartial", `testnet: {{isTestnet}},\n`);
plop.setGenerator("add-chain", {
description: "add a new chain",
prompts: [
chainIdPrompt,
stringPrompt("name", "Name", true),
stringPrompt("chain", "Chain", true),
stringPrompt("shortName", "Short Name", true),
testnetPrompt,
],
actions: [
{
type: "add",
path: "data/additional/{{chainId}}.mjs",
templateFile: "plop-templates/add-chain.hbs",
},
],
});
plop.setGenerator("override-chain", {
description: "add an override for a chain",
prompts: [
chainIdPrompt,
stringPrompt("name", "Name"),
stringPrompt("chain", "Chain"),
stringPrompt("shortName", "Short Name"),
testnetPrompt,
],
actions: [
{
type: "add",
path: "data/overrides/{{chainId}}.mjs",
templateFile: "plop-templates/chain-override.hbs",
},
],
});
}
File diff suppressed because one or more lines are too long
+34
View File
@@ -1,5 +1,39 @@
# thirdweb
## 0.13.60
### Patch Changes
- Updated dependencies [[`3ef3786`](https://github.com/thirdweb-dev/js/commit/3ef378659e83341663dfaded417e33b5af29bbbc)]:
- @thirdweb-dev/chains@0.1.85
- @thirdweb-dev/sdk@4.0.54
- @thirdweb-dev/wallets@2.4.30
- @thirdweb-dev/auth@4.1.52
## 0.13.59
### Patch Changes
- [#2584](https://github.com/thirdweb-dev/js/pull/2584) [`6bd1b82`](https://github.com/thirdweb-dev/js/commit/6bd1b82a58505ec3af3a12ceeab51d78ee3b8bc0) Thanks [@kumaryash90](https://github.com/kumaryash90)! - cli changes for zksync publish
- Updated dependencies [[`6bd1b82`](https://github.com/thirdweb-dev/js/commit/6bd1b82a58505ec3af3a12ceeab51d78ee3b8bc0)]:
- @thirdweb-dev/sdk@4.0.53
- @thirdweb-dev/wallets@2.4.29
- @thirdweb-dev/auth@4.1.51
## 0.13.58
### 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 [[`c81bb88`](https://github.com/thirdweb-dev/js/commit/c81bb882c505a5f1feb8f627377e76a771cce3f4), [`d93286b`](https://github.com/thirdweb-dev/js/commit/d93286bc1f8224d055b50ce3ffa4f302869cb2b1), [`50e7dba`](https://github.com/thirdweb-dev/js/commit/50e7dbaa9dae77cb8cd865405c322495e2498c65)]:
- @thirdweb-dev/sdk@4.0.52
- @thirdweb-dev/storage@2.0.12
- @thirdweb-dev/wallets@2.4.28
- @thirdweb-dev/chains@0.1.84
- @thirdweb-dev/auth@4.1.50
## 0.13.57
### Patch Changes
+32 -26
View File
@@ -2,6 +2,7 @@ import { prepareEnvironment } from "@gmrchk/cli-testing-library";
import { copyFile } from "fs/promises";
import { resolve } from "path";
import { ERROR_MESSAGES } from "../constants/constants";
import { describe, it, expect } from "vitest";
// load env variables
require("dotenv-mono").load();
@@ -12,38 +13,43 @@ const apiSecretKey = process.env.TW_SECRET_KEY as string;
const itif = (condition: boolean) => (condition ? it : it.skip);
// this creates an app, can take some time that's fine
jest.setTimeout(120_000);
describe("npx thirdweb deploy", () => {
itif(!!apiSecretKey)("should return deploy page url", async () => {
const { spawn, cleanup, exists, path } = await prepareEnvironment();
describe(
"npx thirdweb deploy",
{
timeout: 120_000,
},
() => {
itif(!!apiSecretKey)("should return deploy page url", async () => {
const { spawn, cleanup, exists, path } = await prepareEnvironment();
await copyFile(
resolve("./e2e/files/BasicContract.sol"),
`${path}/BasicContract.sol`,
);
const { waitForText, waitForFinish, getExitCode, writeText, getStderr } =
await spawn(
"node",
`./dist/cli/index.js deploy --contract -k ${apiSecretKey}`,
await copyFile(
resolve("./e2e/files/BasicContract.sol"),
`${path}/BasicContract.sol`,
);
expect(await exists("BasicContract.sol")).toEqual(true);
const { waitForText, waitForFinish, getExitCode, writeText, getStderr } =
await spawn(
"node",
`./dist/cli/index.js deploy --contract -k ${apiSecretKey}`,
);
await waitForText(ERROR_MESSAGES.noConfiguration);
await writeText("y");
expect(await exists("BasicContract.sol")).toEqual(true);
// wait for program to finish
await waitForFinish();
await waitForText(ERROR_MESSAGES.noConfiguration);
await writeText("y");
expect(getStderr().at(-1)).toContain(
"https://thirdweb.com/contracts/deploy/",
);
// wait for program to finish
await waitForFinish();
// the process should exit with code 0
expect(getExitCode()).toEqual(0);
expect(getStderr().at(-1)).toContain(
"https://thirdweb.com/contracts/deploy/",
);
await cleanup(); // cleanup after test
});
});
// the process should exit with code 0
expect(getExitCode()).toEqual(0);
await cleanup(); // cleanup after test
});
},
);
+80 -74
View File
@@ -1,92 +1,98 @@
import { CREATE_MESSAGES } from "../constants/constants";
import { prepareEnvironment } from "@gmrchk/cli-testing-library";
import { describe, it, expect } from "vitest";
// load env variables
require("dotenv-mono").load();
// this creates an app, can take some time that's fine
jest.setTimeout(240_000);
describe(
"npx thirdweb detect",
{
timeout: 240_000,
},
() => {
it("should detect ERC721Base extensions", async () => {
const { spawn, cleanup, exists } = await prepareEnvironment();
const create = await spawn("node", "./dist/cli/index.js create");
describe("npx thirdweb detect", () => {
it("should detect ERC721Base extensions", async () => {
const { spawn, cleanup, exists } = await prepareEnvironment();
const create = await spawn("node", "./dist/cli/index.js create");
await create.waitForText(CREATE_MESSAGES.typeOfProject);
// select contract
await create.pressKey("arrowDown");
await create.pressKey("enter");
await create.waitForText(CREATE_MESSAGES.projectName);
// use default name
await create.pressKey("enter");
await create.waitForText(CREATE_MESSAGES.framework);
// select hardhat
await create.pressKey("enter");
await create.waitForText(CREATE_MESSAGES.contractName);
// set contract name
await create.writeText("Contract");
await create.pressKey("enter");
await create.waitForText(CREATE_MESSAGES.contract);
// select ERC721
await create.pressKey("arrowDown");
await create.pressKey("enter");
await create.waitForText(CREATE_MESSAGES.extensions);
// select no extra extensions
await create.pressKey("enter");
await create.waitForText(CREATE_MESSAGES.typeOfProject);
// select contract
await create.pressKey("arrowDown");
await create.pressKey("enter");
await create.waitForText(CREATE_MESSAGES.projectName);
// use default name
await create.pressKey("enter");
await create.waitForText(CREATE_MESSAGES.framework);
// select hardhat
await create.pressKey("enter");
await create.waitForText(CREATE_MESSAGES.contractName);
// set contract name
await create.writeText("Contract");
await create.pressKey("enter");
await create.waitForText(CREATE_MESSAGES.contract);
// select ERC721
await create.pressKey("arrowDown");
await create.pressKey("enter");
await create.waitForText(CREATE_MESSAGES.extensions);
// select no extra extensions
await create.pressKey("enter");
// wait for program to finish
await create.waitForFinish();
// wait for program to finish
await create.waitForFinish();
// check if the contract was created
expect(await exists("thirdweb-contracts/contracts/Contract.sol")).toEqual(
true,
);
// check if the contract was created
expect(await exists("thirdweb-contracts/contracts/Contract.sol")).toEqual(
true,
);
// check that hardhat config exists
expect(await exists("thirdweb-contracts/hardhat.config.js")).toEqual(
true,
);
// check that hardhat config exists
expect(await exists("thirdweb-contracts/hardhat.config.js")).toEqual(true);
await create.writeText("cd thirdweb-contracts");
await create.pressKey("enter");
await create.writeText("npm install");
await create.pressKey("enter");
await create.writeText("cd thirdweb-contracts");
await create.pressKey("enter");
await create.writeText("npm install");
await create.pressKey("enter");
const detect = await spawn(
"node",
"./dist/cli/index.js detect",
"./thirdweb-contracts",
);
const detect = await spawn(
"node",
"./dist/cli/index.js detect",
"./thirdweb-contracts",
);
// Select pnpm as package manager.
await detect.pressKey("arrowDown");
await detect.pressKey("enter");
// Select pnpm as package manager.
await detect.pressKey("arrowDown");
await detect.pressKey("enter");
// wait for program to finish
await detect.waitForFinish();
// wait for program to finish
await detect.waitForFinish();
const lines = detect.getStdout();
const lines = detect.getStdout();
// Detected extensions
expect(
lines.findIndex((line) => line.includes("ERC721")),
).toBeGreaterThan(-1);
expect(
lines.findIndex((line) => line.includes("ERC721Burnable")),
).toBeGreaterThan(-1);
expect(
lines.findIndex((line) => line.includes("ERC721Mintable")),
).toBeGreaterThan(-1);
// Detected extensions
expect(lines.findIndex((line) => line.includes("ERC721"))).toBeGreaterThan(
-1,
);
expect(
lines.findIndex((line) => line.includes("ERC721Burnable")),
).toBeGreaterThan(-1);
expect(
lines.findIndex((line) => line.includes("ERC721Mintable")),
).toBeGreaterThan(-1);
// Suggested extensions
expect(
lines.findIndex((line) => line.includes("- ERC721Enumerable")),
).toBeGreaterThan(-1);
expect(
lines.findIndex((line) => line.includes("- ERC721LazyMintable")),
).toBeGreaterThan(-1);
expect(
lines.findIndex((line) => line.includes("- ERC721SignatureMint")),
).toBeGreaterThan(-1);
// Suggested extensions
expect(
lines.findIndex((line) => line.includes("- ERC721Enumerable")),
).toBeGreaterThan(-1);
expect(
lines.findIndex((line) => line.includes("- ERC721LazyMintable")),
).toBeGreaterThan(-1);
expect(
lines.findIndex((line) => line.includes("- ERC721SignatureMint")),
).toBeGreaterThan(-1);
await cleanup(); // cleanup after test
});
});
await cleanup(); // cleanup after test
});
},
);
+30 -26
View File
@@ -2,6 +2,7 @@ import { prepareEnvironment } from "@gmrchk/cli-testing-library";
import { copyFile } from "fs/promises";
import { resolve } from "path";
import { ERROR_MESSAGES } from "../constants/constants";
import { describe, it, expect } from "vitest";
// load env variables
require("dotenv-mono").load();
@@ -12,37 +13,40 @@ const apiSecretKey = process.env.TW_SECRET_KEY as string;
// function to skip tests based on condition
const itif = (condition: boolean) => (condition ? it : it.skip);
// this creates an app, can take some time that's fine
jest.setTimeout(120_000);
describe(
"npx thirdweb publish",
{
timeout: 120_000,
},
() => {
// conditionally skip test if there's no api key
itif(!!apiSecretKey)("should return publish page url", async () => {
const { spawn, cleanup, exists, path } = await prepareEnvironment();
describe("npx thirdweb publish", () => {
// conditionally skip test if there's no api key
itif(!!apiSecretKey)("should return publish page url", async () => {
const { spawn, cleanup, exists, path } = await prepareEnvironment();
await copyFile(
resolve("./e2e/files/BasicContract.sol"),
`${path}/BasicContract.sol`,
);
await copyFile(
resolve("./e2e/files/BasicContract.sol"),
`${path}/BasicContract.sol`,
);
const { waitForText, waitForFinish, getExitCode, writeText, getStderr } =
await spawn("node", `./dist/cli/index.js publish -k ${apiSecretKey}`);
const { waitForText, waitForFinish, getExitCode, writeText, getStderr } =
await spawn("node", `./dist/cli/index.js publish -k ${apiSecretKey}`);
expect(await exists("BasicContract.sol")).toEqual(true);
expect(await exists("BasicContract.sol")).toEqual(true);
await waitForText(ERROR_MESSAGES.noConfiguration);
await writeText("y");
await waitForText(ERROR_MESSAGES.noConfiguration);
await writeText("y");
// wait for program to finish
await waitForFinish();
// wait for program to finish
await waitForFinish();
expect(getStderr().at(-1)).toContain(
"https://thirdweb.com/contracts/publish/",
);
expect(getStderr().at(-1)).toContain(
"https://thirdweb.com/contracts/publish/",
);
// the process should exit with code 0
expect(getExitCode()).toEqual(0);
// the process should exit with code 0
expect(getExitCode()).toEqual(0);
await cleanup(); // cleanup after test
});
});
await cleanup(); // cleanup after test
});
},
);
-5
View File
@@ -1,5 +0,0 @@
/** @type {import('ts-jest/dist/types').InitialOptionsTsJest} */
module.exports = {
preset: "ts-jest",
testEnvironment: "node",
};
+23 -29
View File
@@ -1,7 +1,7 @@
{
"name": "@thirdweb-dev/cli",
"main": "dist/cli/index.js",
"version": "0.13.57",
"version": "0.13.60",
"repository": "https://github.com/thirdweb-dev/js/tree/main/legacy_packages/cli",
"author": "thirdweb eng <[email protected]>",
"license": "Apache-2.0",
@@ -11,28 +11,23 @@
"devDependencies": {
"@gmrchk/cli-testing-library": "^0.1.2",
"@thirdweb-dev/tsconfig": "workspace:*",
"@types/async-retry": "^1.3.0",
"@types/cross-spawn": "^6.0.2",
"@types/inquirer": "^8.2.1",
"@types/jest": "^29.5.3",
"@types/js-yaml": "^4.0.5",
"@types/node": "^18.17.1",
"@types/prompts": "^2.4.4",
"@types/rimraf": "^3.0.0",
"@types/tar": "^6.1.5",
"@types/update-notifier": "^6.0.4",
"@types/validate-npm-package-name": "^4.0.0",
"@types/async-retry": "^1.4.8",
"@types/cross-spawn": "^6.0.6",
"@types/inquirer": "^8.2.10",
"@types/js-yaml": "^4.0.9",
"@types/node": "20.11.30",
"@types/prompts": "^2.4.9",
"@types/tar": "^6.1.11",
"@types/update-notifier": "^6.0.8",
"@types/validate-npm-package-name": "^4.0.2",
"chalk": "^5.3.0",
"cross-spawn": "^7.0.3",
"dotenv-mono": "^1.3.10",
"dotenv-mono": "^1.3.14",
"eslint-config-thirdweb": "workspace:*",
"hardhat": "^2.17.0",
"jest": "^29.6.2",
"hardhat": "^2.22.2",
"ora": "^6.3.1",
"ts-jest": "^29.1.1",
"ts-node": "^10.7.0",
"tsup": "^6.7.0",
"typescript": "^5.3.3"
"tsup": "8.0.2",
"typescript": "5.4.3"
},
"dependencies": {
"@iarna/toml": "^2.2.5",
@@ -42,22 +37,22 @@
"@thirdweb-dev/storage": "workspace:*",
"@thirdweb-dev/wallets": "workspace:*",
"async-retry": "^1.3.3",
"commander": "^9.1.0",
"commander": "^9.5.0",
"detect-package-manager": "^2.0.1",
"enquirer": "^2.3.6",
"enquirer": "^2.4.1",
"ethers": "^5.7.2",
"got": "11.8.5",
"inquirer": "^8.2.3",
"inquirer": "^8.2.6",
"js-yaml": "^4.1.0",
"open": "^8.4.0",
"open": "^8.4.2",
"prompts": "^2.4.2",
"rimraf": "^3.0.2",
"solc": "0.8.17",
"tar": "^6.1.15",
"rimraf": "5.0.5",
"solc": "0.8.25",
"tar": "^6.2.1",
"update-notifier": "^6.0.2",
"validate-npm-package-name": "^4.0.0",
"xdg-app-paths": "^8.3.0",
"yaml": "^2.3.4"
"yaml": "^2.4.1"
},
"bin": {
"thirdweb": "./dist/cli/index.js"
@@ -67,11 +62,10 @@
"lint": "eslint src/",
"fix": "eslint src/ --fix",
"clean": "rm -rf dist/",
"cli": "node -r ts-node/register src/cli/index.ts",
"build": "pnpm clean && tsup --env.NODE_ENV production --minify --format cjs --external hardhat --dts-resolve",
"build:watch": "pnpm run build --watch",
"generate-thirdweb-package": "node scripts/generate-thirdweb-package.js",
"e2e": "jest",
"e2e": "vitest",
"push": "yalc push"
},
"files": [
+1
View File
@@ -377,6 +377,7 @@ const main = async () => {
.option("--dry-run", "dry run (skip actually publishing)")
.option("-d, --debug", "show debug logs")
.option("--ci", "Continuous Integration mode")
.option("--zksync", "Publish with ZKSync settings")
.option(
"--link-lib <library:address...>",
"Specify library names and addresses",
+111 -5
View File
@@ -61,9 +61,7 @@ export async function processProject(
logger.debug("Processing project at path " + projectPath);
const projectType = options.zksync
? "hardhat"
: await detect(projectPath, options);
const projectType = await detect(projectPath, options);
if (projectType === "none") {
if (command === "deploy") {
@@ -106,9 +104,25 @@ export async function processProject(
}
let compiledResult: { contracts: ContractPayload[] };
let zkCompiledResult: { contracts: ContractPayload[] };
const compileLoader = spinner("Compiling project...");
try {
compiledResult = await build(projectPath, projectType, options);
if (options.zksync) {
zkCompiledResult = await build(projectPath, "zk-hardhat", options);
if (
compiledResult.contracts.length !== zkCompiledResult.contracts.length
) {
logger.error(
"Length mismatch: zksolc and solc compiled contracts differ.",
);
process.exit(1);
}
} else {
zkCompiledResult = { contracts: [] };
}
} catch (e) {
compileLoader.fail("Compilation failed");
logger.error(e);
@@ -223,6 +237,23 @@ export async function processProject(
process.exit(1);
}
let zkSelectedContracts: ContractPayload[] = [];
if (options.zksync) {
const fileNames = selectedContracts.map((selected) => selected.fileName);
zkSelectedContracts = zkCompiledResult.contracts.filter((contract) => {
const index = fileNames.indexOf(contract.fileName);
return index !== -1;
});
if (zkSelectedContracts.length !== selectedContracts.length) {
info(
"Selected contract not present in zksolc compiled contracts. Aborting.",
);
process.exit(1);
}
}
if (options.dryRun) {
info("Dry run, skipping deployment");
process.exit(0);
@@ -332,6 +363,81 @@ export async function processProject(
metadataUri: metadataURIs[i],
bytecodeUri: bytecodeURIs[i],
analytics,
compilers: {
solc: [
{
compilerVersion: compiledResult.contracts[0].compilerVersion,
evmVersion: compiledResult.contracts[0].evmVersion,
metadataUri: metadataURIs[i],
bytecodeUri: bytecodeURIs[i],
},
],
},
};
});
}
// upload zk-contracts if present
if (zkSelectedContracts.length > 0) {
for (let i = 0; i < zkSelectedContracts.length; i++) {
const contract = zkSelectedContracts[i];
if (contract.sources) {
// upload sources in batches to avoid getting rate limited (needs to be single uploads)
const batchSize = 3;
for (let j = 0; j < contract.sources.length; j = j + batchSize) {
const batch = contract.sources.slice(j, j + batchSize);
logger.debug(`Uploading Sources:\n${batch.join("\n")}\n`);
await Promise.all(
batch.map(async (c) => {
const file = readFileSync(c, "utf-8");
if (file.includes(soliditySDKPackage)) {
usesSoliditySDK = true;
}
return await storage.upload(file, {
uploadWithoutDirectory: true,
});
}),
);
}
}
}
// Upload build output metadatas (need to be single uploads)
const zkMetadataURIs = await Promise.all(
zkSelectedContracts.map(async (c) => {
logger.debug(`Uploading ${c.name}...`);
return await storage.upload(JSON.parse(JSON.stringify(c.metadata)), {
uploadWithoutDirectory: true,
});
}),
);
// Upload batch all bytecodes
const zkBytecodes = zkSelectedContracts.map((c) => c.bytecode);
const zkBytecodeURIs = await storage.uploadBatch(zkBytecodes);
combinedContents = combinedContents.map((c, i) => {
return {
...c,
compilers: {
zksolc: [
{
compilerVersion: zkCompiledResult.contracts[0].compilerVersion,
evmVersion: zkCompiledResult.contracts[0].evmVersion,
metadataUri: zkMetadataURIs[i],
bytecodeUri: zkBytecodeURIs[i],
},
],
solc: [
{
compilerVersion: compiledResult.contracts[0].compilerVersion,
evmVersion: compiledResult.contracts[0].evmVersion,
metadataUri: metadataURIs[i],
bytecodeUri: bytecodeURIs[i],
},
],
},
};
});
}
@@ -362,8 +468,8 @@ export function getUrl(hashes: string[], command: string) {
if (hashes.length === 1) {
url = new URL(
THIRDWEB_URL +
`/contracts/${command}/` +
encodeURIComponent(hashes[0].replace("ipfs://", "")),
`/contracts/${command}/` +
encodeURIComponent(hashes[0].replace("ipfs://", "")),
);
} else {
url = new URL(THIRDWEB_URL + "/contracts/" + command);
@@ -56,6 +56,8 @@ export class BrownieBuilder extends BaseBuilder {
sources: [], // TODO
fileName: "", // TODO
name: contractName,
compilerVersion: "",
evmVersion: "",
});
break;
}
@@ -5,6 +5,7 @@ import { FoundryBuilder } from "./foundry";
import { HardhatBuilder } from "./hardhat";
import { SolcBuilder } from "./solc";
import { TruffleBuilder } from "./truffle";
import { ZKHardhatBuilder } from "./zkHardhat";
export default async function build(
path: string,
@@ -19,6 +20,10 @@ export default async function build(
builder = new HardhatBuilder();
break;
}
case "zk-hardhat": {
builder = new ZKHardhatBuilder();
break;
}
case "foundry": {
builder = new FoundryBuilder();
break;
@@ -107,6 +107,9 @@ export class FoundryBuilder extends BaseBuilder {
contractInfo.rawMetadata ||
this.sanitizeParsedMetadata(parsedMetadata, contractInfo.abi);
const evmVersion = metadata.settings?.evmVersion || "";
const compilerVersion = metadata.compiler?.version || "";
const sources = Object.keys(parsedMetadata.sources)
.map((path) => {
if (path.startsWith("/") && existsSync(path)) {
@@ -146,6 +149,8 @@ export class FoundryBuilder extends BaseBuilder {
bytecode,
fileName,
sources,
compilerVersion,
evmVersion,
});
}
}
+10 -29
View File
@@ -36,22 +36,7 @@ export class HardhatBuilder extends BaseBuilder {
logger.debug("successfully extracted hardhat config", actualHardhatConfig);
await execute("npx hardhat clean", options.projectPath);
let ignoreIpfsHash = false;
if (options.zksync) {
const zkNetwork = Object.entries(actualHardhatConfig.networks).find(
(network) => {
return (network[1] as any).zksync;
},
);
ignoreIpfsHash = (zkNetwork?.[1] as any).zksync; // IPFS hash can't be recovered from ZKSync bytecode
await execute(
`npx hardhat compile --network ${zkNetwork?.[0]}`,
options.projectPath,
);
} else {
await execute(`npx hardhat compile`, options.projectPath);
}
await execute(`npx hardhat compile`, options.projectPath);
const solcConfigs = actualHardhatConfig.solidity.compilers;
if (solcConfigs) {
@@ -127,7 +112,7 @@ export class HardhatBuilder extends BaseBuilder {
}
let bytecode = info.evm.bytecode.object;
let deployedBytecode = info.evm.deployedBytecode?.object || bytecode;
let deployedBytecode = info.evm.deployedBytecode.object;
// link external libraries if any
bytecode = linkLibrary(bytecode, libraries);
@@ -135,9 +120,10 @@ export class HardhatBuilder extends BaseBuilder {
const { metadata, abi } = info;
const meta = metadata.solc_metadata
? JSON.parse(metadata.solc_metadata)
: JSON.parse(metadata);
const meta = JSON.parse(metadata);
const evmVersion = meta.settings?.evmVersion || "";
const compilerVersion = meta.compiler?.version || "";
const sources = Object.keys(meta.sources)
.map((path) => {
const directPath = join(options.projectPath, path);
@@ -165,20 +151,15 @@ export class HardhatBuilder extends BaseBuilder {
);
const fileName = fileNames.length > 0 ? fileNames[0] : "";
if (
this.shouldProcessContract(
abi,
deployedBytecode,
contractName,
ignoreIpfsHash,
)
) {
if (this.shouldProcessContract(abi, deployedBytecode, contractName)) {
contracts.push({
metadata: JSON.stringify(meta),
metadata,
bytecode,
name: contractName,
fileName,
sources,
compilerVersion,
evmVersion,
});
}
}
@@ -116,6 +116,9 @@ export class SolcBuilder extends BaseBuilder {
const parsedMetadata = JSON.parse(metadata);
const abi = parsedMetadata.output.abi;
const evmVersion = parsedMetadata.settings?.evmVersion || "";
const compilerVersion = parsedMetadata.compiler?.version || "";
const target = parsedMetadata.settings.compilationTarget;
if (
Object.keys(target).length === 0 ||
@@ -156,6 +159,8 @@ export class SolcBuilder extends BaseBuilder {
name: contractName,
fileName,
sources: _sources,
compilerVersion,
evmVersion,
});
}
}
@@ -13,10 +13,9 @@ export class TruffleBuilder extends BaseBuilder {
}> {
// get the current config first
// eslint-disable-next-line @typescript-eslint/no-var-requires
const truffleConfig = require(join(
options.projectPath,
"truffle-config.js",
));
const truffleConfig = require(
join(options.projectPath, "truffle-config.js"),
);
const buildPath = join(
options.projectPath,
@@ -42,6 +41,9 @@ export class TruffleBuilder extends BaseBuilder {
const meta = JSON.parse(metadata);
const abi = meta.output.abi;
const evmVersion = meta.settings?.evmVersion || "";
const compilerVersion = meta.compiler?.version || "";
const target = meta.settings.compilationTarget;
if (
Object.keys(target).length === 0 ||
@@ -81,6 +83,8 @@ export class TruffleBuilder extends BaseBuilder {
name: contractName,
fileName,
sources,
compilerVersion,
evmVersion,
});
}
}
@@ -0,0 +1,171 @@
import { findFiles } from "../../common/file-helper";
import { execute } from "../helpers/exec";
import { logger } from "../helpers/logger";
import { ContractPayload } from "../interfaces/ContractPayload";
import { BaseBuilder } from "./builder-base";
import { existsSync, readFileSync } from "fs";
import { HardhatConfig } from "hardhat/types";
import { join, resolve } from "path";
export class ZKHardhatBuilder extends BaseBuilder {
public async compile(options: any): Promise<{
contracts: ContractPayload[];
}> {
//we get our very own extractor script from the dir that we're in during execution
// this is `./dist/cli` (for all purposes of the CLI)
// then we look up the hardhat config extractor file path from there
const configExtractorScriptPath = resolve(
__dirname,
"../helpers/hardhat-config-extractor.js",
);
//the hardhat extractor **logs out** the runtime config of hardhat, we take that stdout and parse it
const stringifiedConfig = (
await execute(
`npx hardhat run "${configExtractorScriptPath}" --no-compile`,
options.projectPath,
)
).stdout;
//voila the hardhat config
const actualHardhatConfig = JSON.parse(
stringifiedConfig.split("__tw__")[1],
) as HardhatConfig;
logger.debug("successfully extracted hardhat config", actualHardhatConfig);
await execute("npx hardhat clean", options.projectPath);
let ignoreIpfsHash = false;
const zkNetwork = Object.entries(actualHardhatConfig.networks).find(
(network) => {
return (network[1] as any).zksync;
},
);
if (!(zkNetwork?.[1] as any).zksync) {
logger.warn("ZKSync settings not found. Aborting.");
process.exit(1);
}
ignoreIpfsHash = (zkNetwork?.[1] as any).zksync; // IPFS hash can't be recovered from ZKSync bytecode
await execute(
`npx hardhat compile --network ${zkNetwork?.[0]}`,
options.projectPath,
);
const artifactsPath = actualHardhatConfig.paths.artifacts;
const sourcesDir = actualHardhatConfig.paths.sources.replace(
options.projectPath,
"",
);
const contractsPath = join(artifactsPath, sourcesDir);
const contracts: ContractPayload[] = [];
const files: string[] = [];
findFiles(contractsPath, /^.*(?<!dbg)\.json$/, files);
const buildOutputPath = join(artifactsPath, "build-info");
const buildFiles: string[] = [];
findFiles(buildOutputPath, /^.*(?<!dbg)\.json$/, buildFiles);
for (const buildFile of buildFiles) {
const buildJsonFile = readFileSync(buildFile, "utf-8");
const buildJson = JSON.parse(buildJsonFile);
const contractBuildOutputs = buildJson.output.contracts;
for (const [contractPath, contractInfos] of Object.entries(
contractBuildOutputs,
)) {
if (contractPath.includes("@")) {
// skip library contracts
logger.debug("Skipping", contractPath, "(not a source target)");
continue;
}
for (const [contractName, contractInfo] of Object.entries(
contractInfos as any,
)) {
const info = contractInfo as any;
if (
!info.evm ||
!info.evm.bytecode ||
!info.evm.bytecode.object ||
!info.metadata ||
!info.abi
) {
logger.debug("Skipping", contractPath, "(no bytecode or metadata)");
continue;
}
const bytecode = info.evm.bytecode.object;
const deployedBytecode =
info.evm.deployedBytecode?.object || bytecode;
const { metadata, abi } = info;
const meta = metadata.solc_metadata
? JSON.parse(metadata.solc_metadata)
: JSON.parse(metadata);
// Find and add zk_version to solc_metadata settings - needed for verification
// TODO: it's a workaround. remove it (e.g. when ipfs hash issue is resolved)
const zkVersion = metadata.zk_version;
meta.settings["zkVersion"] = zkVersion;
const evmVersion = meta.settings?.evmVersion || "";
const compilerVersion = zkVersion || "";
const sources = Object.keys(meta.sources)
.map((path) => {
const directPath = join(options.projectPath, path);
if (existsSync(directPath)) {
return directPath;
}
const sourcePath = join(options.projectPath, sourcesDir, path);
if (existsSync(sourcePath)) {
return sourcePath;
}
const nodeModulesPath = join(
options.projectPath,
"node_modules",
path,
);
if (existsSync(nodeModulesPath)) {
return nodeModulesPath;
}
return undefined;
})
.filter((path) => path !== undefined) as string[];
const fileNames = Object.keys(
meta?.settings?.compilationTarget || {},
);
const fileName = fileNames.length > 0 ? fileNames[0] : "";
if (
this.shouldProcessContract(
abi,
deployedBytecode,
contractName,
ignoreIpfsHash,
)
) {
contracts.push({
metadata: JSON.stringify(meta),
bytecode,
name: contractName,
fileName,
sources,
compilerVersion,
evmVersion,
});
}
}
}
}
return {
contracts,
};
}
}
@@ -27,6 +27,17 @@ export default async function detect(
.filter((detector) => detector.matches(path))
.map((detector) => detector.projectType);
if (options.zksync) {
const hardhatProject = possibleProjectTypes.filter(
(projectType) => projectType === "hardhat",
);
if (hardhatProject.length === 0) {
logger.warn("ZKSync compilation requires hardhat plugins. Aborting.");
process.exit(1);
}
}
//if there is no project returned at all then just return unknown}
if (!possibleProjectTypes.length) {
const canCompile = hasContracts(path);
@@ -51,15 +62,28 @@ export default async function detect(
}
//if there is only one possible option just return it
if (possibleProjectTypes.length === 1) {
info(`Detected project type: ${possibleProjectTypes[0]}`);
if (options.zksync) {
info("ZKSync compilation will use hardhat");
} else {
info(`Detected project type: ${possibleProjectTypes[0]}`);
}
return possibleProjectTypes[0];
}
info(
`Detected multiple possible build tools: ${possibleProjectTypes
.map((s) => `"${s}"`)
.join(", ")}`,
);
if (options.zksync) {
info("ZKSync compilation will use hardhat");
info(
`For regular solc compilation, these are the available options: ${possibleProjectTypes
.map((s) => `"${s}"`)
.join(", ")}`,
);
} else {
info(
`Detected multiple possible build tools: ${possibleProjectTypes
.map((s) => `"${s}"`)
.join(", ")}`,
);
}
const question = "How would you like to compile your contracts";
@@ -26,4 +26,8 @@ export interface ContractPayload {
* The source file paths
*/
sources: string[];
compilerVersion: string;
evmVersion: string;
}
@@ -2,6 +2,7 @@ export type ProjectType =
| "brownie"
| "foundry"
| "hardhat"
| "zk-hardhat"
| "truffle"
| "solc"
| "vite"
@@ -1,5 +1,11 @@
# @thirdweb-dev/contracts-js
## 1.3.19
### 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
## 1.3.18
### Patch Changes
+4 -6
View File
@@ -1,6 +1,6 @@
{
"name": "@thirdweb-dev/contracts-js",
"version": "1.3.18",
"version": "1.3.19",
"main": "dist/thirdweb-dev-contracts-js.cjs.js",
"module": "dist/thirdweb-dev-contracts-js.esm.js",
"exports": {
@@ -428,17 +428,15 @@
"@thirdweb-dev/contracts": "3.12.1"
},
"devDependencies": {
"@babel/preset-env": "^7.23.8",
"@babel/preset-typescript": "^7.23.3",
"@ethersproject/abi": "^5.7.0",
"@ethersproject/providers": "^5.7.2",
"@preconstruct/cli": "^2.8.1",
"@preconstruct/cli": "2.7.0",
"@thirdweb-dev/tsconfig": "workspace:*",
"@typechain/ethers-v5": "10.0.0",
"eslint-config-thirdweb": "workspace:*",
"ethers": "^5.7.2",
"typechain": "^8.3.1",
"typescript": "^5.3.3"
"typechain": "^8.3.2",
"typescript": "5.4.3"
},
"peerDependencies": {
"ethers": "^5"
+6
View File
@@ -1,5 +1,11 @@
# @thirdweb-dev/crypto
## 0.2.3
### 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
## 0.2.2
### Patch Changes
+7 -7
View File
@@ -1,6 +1,6 @@
{
"name": "@thirdweb-dev/crypto",
"version": "0.2.2",
"version": "0.2.3",
"main": "dist/thirdweb-dev-crypto.cjs.js",
"module": "dist/thirdweb-dev-crypto.esm.js",
"exports": {
@@ -27,8 +27,8 @@
},
"sideEffects": false,
"dependencies": {
"@noble/hashes": "^1.3.2",
"js-sha3": "^0.9.2"
"@noble/hashes": "^1.4.0",
"js-sha3": "^0.9.3"
},
"devDependencies": {
"@preconstruct/cli": "2.7.0",
@@ -37,10 +37,10 @@
"crypto-js": "^4.2.0",
"eslint-config-thirdweb": "workspace:*",
"ethers": "^5.7.2",
"js-awe": "^1.0.62",
"tinybench": "^2.5.1",
"typescript": "^5.3.3",
"viem": "^1.19.1"
"js-awe": "^1.0.64",
"tinybench": "^2.6.0",
"typescript": "5.4.3",
"viem": "2.9.5"
},
"scripts": {
"format": "prettier --write 'src/**/*'",
+9
View File
@@ -1,5 +1,14 @@
# @thirdweb-dev/merkletree
## 0.2.3
### 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/crypto@0.2.3
## 0.2.2
### Patch Changes
+7 -7
View File
@@ -1,6 +1,6 @@
{
"name": "@thirdweb-dev/merkletree",
"version": "0.2.2",
"version": "0.2.3",
"main": "dist/thirdweb-dev-merkletree.cjs.js",
"module": "dist/thirdweb-dev-merkletree.esm.js",
"exports": {
@@ -35,17 +35,17 @@
"devDependencies": {
"@preconstruct/cli": "2.7.0",
"@thirdweb-dev/tsconfig": "workspace:*",
"@types/benchmark": "^2.1.4",
"@types/treeify": "^1.0.2",
"@types/benchmark": "^2.1.5",
"@types/treeify": "^1.0.3",
"benchmark": "^2.1.4",
"circomlibjs": "^0.1.7",
"eslint-config-thirdweb": "workspace:*",
"ethereum-cryptography": "^1.0.3",
"ethereumjs-util": "^7.0.9",
"ethereum-cryptography": "^1.2.0",
"ethereumjs-util": "^7.1.5",
"keccak256": "^1.0.6",
"sha1": "^1.1.1",
"tape": "^4.9.2",
"typescript": "^5.3.3"
"tape": "^4.17.0",
"typescript": "5.4.3"
},
"scripts": {
"format": "prettier --write 'src/**/*'",
+6
View File
@@ -1,5 +1,11 @@
# @thirdweb-dev/pay
## 0.1.6
### 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
## 0.1.5
### Patch Changes
+3 -3
View File
@@ -1,6 +1,6 @@
{
"name": "@thirdweb-dev/pay",
"version": "0.1.5",
"version": "0.1.6",
"main": "dist/thirdweb-dev-pay.cjs.js",
"module": "dist/thirdweb-dev-pay.esm.js",
"exports": {
@@ -33,13 +33,13 @@
},
"sideEffects": false,
"dependencies": {
"@coinbase/cbpay-js": "^1.7.0"
"@coinbase/cbpay-js": "^1.10.0"
},
"devDependencies": {
"@preconstruct/cli": "2.7.0",
"@thirdweb-dev/tsconfig": "workspace:*",
"eslint-config-thirdweb": "workspace:*",
"typescript": "^5.3.3"
"typescript": "5.4.3"
},
"scripts": {
"format": "prettier --write 'src/**/*'",
+6
View File
@@ -1,5 +1,11 @@
# @thirdweb-dev/payments
## 1.0.3
### 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
## 1.0.2
### Patch Changes
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@thirdweb-dev/payments",
"version": "1.0.2",
"version": "1.0.3",
"main": "dist/thirdweb-dev-payments.cjs.js",
"module": "dist/thirdweb-dev-payments.esm.js",
"types": "dist/thirdweb-dev-payments.cjs.d.ts",
@@ -44,7 +44,7 @@
"@preconstruct/cli": "2.7.0",
"@thirdweb-dev/tsconfig": "workspace:*",
"eslint-config-thirdweb": "workspace:*",
"typescript": "^5.3.3"
"typescript": "5.4.3"
},
"scripts": {
"format": "prettier --write 'src/**/*'",
+32
View File
@@ -1,5 +1,37 @@
# @thirdweb-dev/react-core
## 4.4.28
### Patch Changes
- Updated dependencies [[`3ef3786`](https://github.com/thirdweb-dev/js/commit/3ef378659e83341663dfaded417e33b5af29bbbc)]:
- @thirdweb-dev/chains@0.1.85
- @thirdweb-dev/sdk@4.0.54
- @thirdweb-dev/wallets@2.4.30
- @thirdweb-dev/auth@4.1.52
## 4.4.27
### Patch Changes
- Updated dependencies [[`6bd1b82`](https://github.com/thirdweb-dev/js/commit/6bd1b82a58505ec3af3a12ceeab51d78ee3b8bc0)]:
- @thirdweb-dev/sdk@4.0.53
- @thirdweb-dev/wallets@2.4.29
- @thirdweb-dev/auth@4.1.51
## 4.4.26
### 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 [[`c81bb88`](https://github.com/thirdweb-dev/js/commit/c81bb882c505a5f1feb8f627377e76a771cce3f4), [`d93286b`](https://github.com/thirdweb-dev/js/commit/d93286bc1f8224d055b50ce3ffa4f302869cb2b1), [`50e7dba`](https://github.com/thirdweb-dev/js/commit/50e7dbaa9dae77cb8cd865405c322495e2498c65)]:
- @thirdweb-dev/sdk@4.0.52
- @thirdweb-dev/storage@2.0.12
- @thirdweb-dev/wallets@2.4.28
- @thirdweb-dev/chains@0.1.84
- @thirdweb-dev/auth@4.1.50
## 4.4.25
### Patch Changes
+16 -19
View File
@@ -1,6 +1,6 @@
{
"name": "@thirdweb-dev/react-core",
"version": "4.4.25",
"version": "4.4.28",
"repository": "https://github.com/thirdweb-dev/js/tree/main/legacy_packages/react-core",
"author": "thirdweb eng <[email protected]>",
"license": "Apache-2.0",
@@ -57,34 +57,31 @@
},
"sideEffects:": false,
"devDependencies": {
"@babel/core": "^7.23.7",
"@babel/preset-env": "^7.23.8",
"@babel/preset-react": "^7.23.3",
"@babel/preset-typescript": "^7.23.3",
"@babel/runtime": "^7.23.8",
"@microsoft/api-documenter": "^7.22.30",
"@microsoft/api-extractor": "^7.36.3",
"@microsoft/tsdoc": "^0.14.1",
"@babel/preset-react": "^7.24.1",
"@babel/runtime": "^7.24.1",
"@microsoft/api-documenter": "^7.24.1",
"@microsoft/api-extractor": "^7.43.0",
"@microsoft/tsdoc": "^0.14.2",
"@preconstruct/cli": "2.7.0",
"@thirdweb-dev/auth": "workspace:*",
"@thirdweb-dev/tsconfig": "workspace:*",
"@types/js-cookie": "^3.0.6",
"@types/mime": "3.0.0",
"@types/react": "^18.2.17",
"eslint": "^8.56.0",
"@types/react": "18.2.17",
"eslint": "^8.57.0",
"eslint-config-thirdweb": "workspace:*",
"eslint-plugin-better-tree-shaking": "0.0.4",
"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",
"react": "^18.2.0",
"react": "18.2.0",
"typedoc-gen": "workspace:*",
"typescript": "^5.3.3"
"typescript": "5.4.3"
},
"dependencies": {
"@tanstack/react-query": "^4.33.0",
"@tanstack/react-query": "^4.36.1",
"@thirdweb-dev/auth": "workspace:*",
"@thirdweb-dev/chains": "workspace:*",
"@thirdweb-dev/generated-abis": "workspace:^",
@@ -92,7 +89,7 @@
"@thirdweb-dev/storage": "workspace:*",
"@thirdweb-dev/wallets": "workspace:*",
"mime": "3.0.0",
"tiny-invariant": "^1.2.0"
"tiny-invariant": "^1.3.3"
},
"peerDependencies": {
"ethers": ">=5.5.1",
@@ -15,7 +15,7 @@ import {
DAppMetaData,
SignerWallet,
} from "@thirdweb-dev/wallets";
import React, { useMemo } from "react";
import { useMemo } from "react";
/**
* The possible props for the ThirdwebProvider.
@@ -1,5 +1,15 @@
# @thirdweb-dev/react-native-compat
## 0.7.25
## 0.7.24
## 0.7.23
### 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
## 0.7.22
## 0.7.21
@@ -1,7 +1,7 @@
{
"name": "@thirdweb-dev/react-native-compat",
"description": "Shims for Thirdweb in React Native Projects",
"version": "0.7.22",
"version": "0.7.25",
"author": "thirdweb eng <[email protected]>",
"repository": "https://github.com/thirdweb-dev/js/tree/main/legacy_packages/react-native-compat",
"license": "Apache-2.0",
@@ -24,8 +24,8 @@
"@ethersproject/shims": "^5.7.0",
"@walletconnect/react-native-compat": "2.9.2",
"base-64": "^1.0.0",
"big-integer": "^1.6.51",
"react-native-get-random-values": "^1.10.0",
"big-integer": "^1.6.52",
"react-native-get-random-values": "^1.11.0",
"react-native-url-polyfill": "^2.0.0"
},
"peerDependencies": {
@@ -34,14 +34,13 @@
"react-native": ">=0.70.0"
},
"devDependencies": {
"@babel/preset-env": "^7.23.8",
"@thirdweb-dev/tsconfig": "workspace:*",
"@types/node": "^18.17.1",
"@types/node": "20.11.30",
"babel-plugin-module-resolver": "^5.0.0",
"eslint-config-thirdweb": "workspace:*",
"ethers": "^5.7.2",
"react": "^18.2.0",
"react-native": "^0.71.11",
"typescript": "^5.3.3"
"react": "18.2.0",
"react-native": "^0.71.17",
"typescript": "5.4.3"
}
}
+32
View File
@@ -1,5 +1,37 @@
# @thirdweb-dev/react-native
## 0.7.25
### Patch Changes
- Updated dependencies [[`3ef3786`](https://github.com/thirdweb-dev/js/commit/3ef378659e83341663dfaded417e33b5af29bbbc)]:
- @thirdweb-dev/chains@0.1.85
- @thirdweb-dev/react-core@4.4.28
- @thirdweb-dev/sdk@4.0.54
- @thirdweb-dev/wallets@2.4.30
## 0.7.24
### Patch Changes
- Updated dependencies [[`6bd1b82`](https://github.com/thirdweb-dev/js/commit/6bd1b82a58505ec3af3a12ceeab51d78ee3b8bc0)]:
- @thirdweb-dev/sdk@4.0.53
- @thirdweb-dev/react-core@4.4.27
- @thirdweb-dev/wallets@2.4.29
## 0.7.23
### 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 [[`c81bb88`](https://github.com/thirdweb-dev/js/commit/c81bb882c505a5f1feb8f627377e76a771cce3f4), [`d93286b`](https://github.com/thirdweb-dev/js/commit/d93286bc1f8224d055b50ce3ffa4f302869cb2b1), [`50e7dba`](https://github.com/thirdweb-dev/js/commit/50e7dbaa9dae77cb8cd865405c322495e2498c65)]:
- @thirdweb-dev/sdk@4.0.52
- @thirdweb-dev/react-core@4.4.26
- @thirdweb-dev/storage@2.0.12
- @thirdweb-dev/wallets@2.4.28
- @thirdweb-dev/chains@0.1.84
## 0.7.22
### Patch Changes
+26 -31
View File
@@ -1,6 +1,6 @@
{
"name": "@thirdweb-dev/react-native",
"version": "0.7.22",
"version": "0.7.25",
"repository": "https://github.com/thirdweb-dev/js/tree/main/legacy_packages/react-native",
"author": "thirdweb eng <[email protected]>",
"license": "Apache-2.0",
@@ -28,59 +28,54 @@
"@aws-sdk/client-lambda": "3.350.0",
"@aws-sdk/credential-providers": "3.350.0",
"@coinbase/wallet-mobile-sdk": "1.0.13",
"@paperxyz/embedded-wallet-service-sdk": "^1.2.4",
"@paperxyz/embedded-wallet-service-sdk": "^1.2.5",
"@shopify/restyle": "^2.4.2",
"@tanstack/react-query": "^4.33.0",
"@tanstack/react-query": "^4.36.1",
"@thirdweb-dev/chains": "workspace:*",
"@thirdweb-dev/react-core": "workspace:*",
"@thirdweb-dev/sdk": "workspace:*",
"@thirdweb-dev/storage": "workspace:*",
"@thirdweb-dev/wallets": "workspace:*",
"abitype": "^0.2.5",
"aws-amplify": "^5.3.8",
"abitype": "1.0.0",
"aws-amplify": "^5.3.18",
"expo-application": "5.7.0",
"expo-clipboard": "^4.5.0",
"expo-document-picker": "^11.2.2",
"expo-file-system": "^15.2.2",
"expo-secure-store": "^12.1.1",
"expo-clipboard": "^4.8.0",
"expo-document-picker": "^11.10.1",
"expo-file-system": "^15.9.0",
"expo-secure-store": "^12.8.1",
"react-native-modal": "^13.0.1",
"react-native-qrcode-svg": "6.2.0",
"react-native-svg": "^13.9.0",
"react-native-svg": "^13.14.0",
"secrets.js-34r7h": "^2.0.2",
"tiny-invariant": "^1.2.0"
"tiny-invariant": "^1.3.3"
},
"devDependencies": {
"@babel/core": "^7.23.7",
"@babel/preset-env": "^7.23.8",
"@react-native-async-storage/async-storage": "^1.18.2",
"@react-native-community/eslint-config": "^3.0.2",
"@react-native-async-storage/async-storage": "^1.23.1",
"@react-native-community/eslint-config": "^3.2.0",
"@thirdweb-dev/tsconfig": "workspace:*",
"@types/jest": "^29.5.3",
"@types/react": "^18.2.17",
"@types/react-native": "^0.71.8",
"babel-jest": "^29.6.2",
"eslint": "^8.56.0",
"@types/react": "18.2.17",
"@types/react-native": "^0.71.13",
"eslint": "^8.57.0",
"eslint-config-thirdweb": "workspace:*",
"eslint-plugin-i18next": "^6.0.3",
"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",
"jest": "^29.6.2",
"react": "^18.2.0",
"react-native": "^0.71.11",
"react": "18.2.0",
"react-native": "^0.71.17",
"react-native-camera": "^4.2.1",
"rimraf": "^3.0.2",
"rimraf": "5.0.5",
"typedoc-gen": "workspace:*",
"typescript": "^5.3.3"
"typescript": "5.4.3"
},
"optionalDependencies": {
"amazon-cognito-identity-js": "^6.3.3",
"amazon-cognito-identity-js": "^6.3.12",
"react-native-aes-gcm-crypto": "^0.2.2",
"react-native-camera": "^4.2.1",
"react-native-inappbrowser-reborn": "^3.7.0",
"react-native-quick-base64": "^2.0.7",
"react-native-quick-base64": "^2.0.8",
"react-native-quick-crypto": "^0.6.1"
},
"peerDependencies": {
@@ -24,11 +24,11 @@ export type LocalWalletImportModalProps = {
onWalletImported: (wallet: LocalWalletInstance) => void;
};
export const LocalWalletImportModal = ({
export const LocalWalletImportModal: React.FC<LocalWalletImportModalProps> = ({
isVisible,
onClose,
onWalletImported,
}: LocalWalletImportModalProps) => {
}) => {
const l = useLocale();
const [password, setPassword] = useState<string | undefined>();
const [privateKeyOrMnemonic, setPrivateKeyOrMnemonic] = useState<
@@ -140,12 +140,12 @@ export const LocalWalletImportModal = ({
const onPickFilePress = async () => {
const result = await DocumentPicker.getDocumentAsync({
copyToCacheDirectory: true,
type: "application/json",
multiple: false,
});
if (result.type === "success") {
setJsonFile(result.uri);
if (!result.canceled && result.assets.length > 0) {
setJsonFile(result.assets[0].uri);
setError(undefined);
} else {
setError(l.local_wallet.error_accessing_file);
+32
View File
@@ -1,5 +1,37 @@
# @thirdweb-dev/react
## 4.4.28
### Patch Changes
- Updated dependencies [[`3ef3786`](https://github.com/thirdweb-dev/js/commit/3ef378659e83341663dfaded417e33b5af29bbbc)]:
- @thirdweb-dev/chains@0.1.85
- @thirdweb-dev/react-core@4.4.28
- @thirdweb-dev/sdk@4.0.54
- @thirdweb-dev/wallets@2.4.30
## 4.4.27
### Patch Changes
- Updated dependencies [[`6bd1b82`](https://github.com/thirdweb-dev/js/commit/6bd1b82a58505ec3af3a12ceeab51d78ee3b8bc0)]:
- @thirdweb-dev/sdk@4.0.53
- @thirdweb-dev/react-core@4.4.27
- @thirdweb-dev/wallets@2.4.29
## 4.4.26
### 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 [[`c81bb88`](https://github.com/thirdweb-dev/js/commit/c81bb882c505a5f1feb8f627377e76a771cce3f4), [`d93286b`](https://github.com/thirdweb-dev/js/commit/d93286bc1f8224d055b50ce3ffa4f302869cb2b1), [`50e7dba`](https://github.com/thirdweb-dev/js/commit/50e7dbaa9dae77cb8cd865405c322495e2498c65)]:
- @thirdweb-dev/sdk@4.0.52
- @thirdweb-dev/react-core@4.4.26
- @thirdweb-dev/payments@1.0.3
- @thirdweb-dev/wallets@2.4.28
- @thirdweb-dev/chains@0.1.84
## 4.4.25
### Patch Changes
+22 -26
View File
@@ -1,6 +1,6 @@
{
"name": "@thirdweb-dev/react",
"version": "4.4.25",
"version": "4.4.28",
"repository": "https://github.com/thirdweb-dev/js/tree/main/legacy_packages/react",
"author": "thirdweb eng <[email protected]>",
"license": "Apache-2.0",
@@ -72,40 +72,36 @@
},
"sideEffects:": false,
"devDependencies": {
"@babel/core": "^7.23.7",
"@babel/preset-env": "^7.23.8",
"@babel/preset-react": "^7.23.3",
"@babel/preset-typescript": "^7.23.3",
"@babel/runtime": "^7.23.8",
"@microsoft/api-documenter": "^7.22.30",
"@microsoft/api-extractor": "^7.36.3",
"@microsoft/tsdoc": "^0.14.1",
"@babel/runtime": "^7.24.1",
"@microsoft/api-documenter": "^7.24.1",
"@microsoft/api-extractor": "^7.43.0",
"@microsoft/tsdoc": "^0.14.2",
"@preconstruct/cli": "2.7.0",
"@thirdweb-dev/auth": "workspace:*",
"@thirdweb-dev/sdk": "workspace:*",
"@thirdweb-dev/tsconfig": "workspace:*",
"@types/qrcode": "^1.5.2",
"@types/react": "^18.2.17",
"@types/react-dom": "^18.2.7",
"@types/uuid": "^9.0.5",
"eslint": "^8.56.0",
"@types/qrcode": "^1.5.5",
"@types/react": "18.2.17",
"@types/react-dom": "^18.2.23",
"@types/uuid": "^9.0.8",
"eslint": "^8.57.0",
"eslint-config-thirdweb": "workspace:*",
"eslint-plugin-better-tree-shaking": "0.0.4",
"eslint-plugin-import": "^2.26.0",
"eslint-plugin-inclusive-language": "^2.2.0",
"eslint-plugin-prettier": "^5.0.0",
"eslint-plugin-svg-jsx": "^1.2.2",
"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-svg-jsx": "^1.2.4",
"eslint-plugin-tsdoc": "^0.2.17",
"ethers": "^5.7.2",
"react": "^18.2.0",
"react": "18.2.0",
"react-dom": "^18.2.0",
"stream": "npm:stream-browserify@^3.0.0",
"typedoc-gen": "workspace:*",
"typescript": "^5.3.3"
"typescript": "5.4.3"
},
"dependencies": {
"@emotion/css": "11.10.5",
"@emotion/react": "^11.11.1",
"@emotion/react": "^11.11.4",
"@emotion/styled": "^11.11.0",
"@google/model-viewer": "^2.1.1",
"@headlessui/react": "1.7.6",
@@ -113,21 +109,21 @@
"@radix-ui/react-dialog": "^1.0.5",
"@radix-ui/react-focus-scope": "^1.0.4",
"@radix-ui/react-icons": "^1.3.0",
"@radix-ui/react-popover": "^1.0.6",
"@radix-ui/react-popover": "^1.0.7",
"@radix-ui/react-tabs": "^1.0.4",
"@radix-ui/react-tooltip": "^1.0.7",
"@tanstack/react-query": "^4.33.0",
"@tanstack/react-query": "^4.36.1",
"@thirdweb-dev/chains": "workspace:*",
"@thirdweb-dev/payments": "workspace:*",
"@thirdweb-dev/react-core": "workspace:*",
"@thirdweb-dev/sdk": "workspace:*",
"@thirdweb-dev/wallets": "workspace:*",
"buffer": "^6.0.3",
"copy-to-clipboard": "^3.3.2",
"copy-to-clipboard": "^3.3.3",
"detect-browser": "^5.3.0",
"fuse.js": "^7.0.0",
"qrcode": "^1.5.3",
"tiny-invariant": "^1.2.0"
"tiny-invariant": "^1.3.3"
},
"peerDependencies": {
"@thirdweb-dev/sdk": "workspace:*",
Binary file not shown.
+28
View File
@@ -1,5 +1,33 @@
# @thirdweb-dev/sdk
## 4.0.54
### Patch Changes
- Updated dependencies [[`3ef3786`](https://github.com/thirdweb-dev/js/commit/3ef378659e83341663dfaded417e33b5af29bbbc)]:
- @thirdweb-dev/chains@0.1.85
## 4.0.53
### Patch Changes
- [#2584](https://github.com/thirdweb-dev/js/pull/2584) [`6bd1b82`](https://github.com/thirdweb-dev/js/commit/6bd1b82a58505ec3af3a12ceeab51d78ee3b8bc0) Thanks [@kumaryash90](https://github.com/kumaryash90)! - cli changes for zksync publish
## 4.0.52
### Patch Changes
- [#2573](https://github.com/thirdweb-dev/js/pull/2573) [`c81bb88`](https://github.com/thirdweb-dev/js/commit/c81bb882c505a5f1feb8f627377e76a771cce3f4) Thanks [@jnsdls](https://github.com/jnsdls)! - fix CWE-1333
- [#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), [`50e7dba`](https://github.com/thirdweb-dev/js/commit/50e7dbaa9dae77cb8cd865405c322495e2498c65)]:
- @thirdweb-dev/contracts-js@1.3.19
- @thirdweb-dev/merkletree@0.2.3
- @thirdweb-dev/storage@2.0.12
- @thirdweb-dev/chains@0.1.84
- @thirdweb-dev/crypto@0.2.3
## 4.0.51
### Patch Changes
-3
View File
@@ -8,7 +8,4 @@ test-evm: FORCE
./scripts/waitForHardhatNode.sh
pnpm run test:all
test-sol: FORCE
./scripts/run_tests.sh
FORCE: ;
+30 -31
View File
@@ -1,6 +1,6 @@
{
"name": "@thirdweb-dev/sdk",
"version": "4.0.51",
"version": "4.0.54",
"description": "The main thirdweb SDK.",
"repository": "https://github.com/thirdweb-dev/js/tree/main/legacy_packages/sdk",
"license": "Apache-2.0",
@@ -75,42 +75,41 @@
"typedoc": "node scripts/typedoc.mjs"
},
"devDependencies": {
"@aws-sdk/client-secrets-manager": "^3.378.0",
"@aws-sdk/client-secrets-manager": "^3.543.0",
"@ethersproject/abstract-provider": "^5.7.0",
"@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",
"@nomiclabs/hardhat-ethers": "^2.2.3",
"@preconstruct/cli": "2.7.0",
"@project-serum/anchor": "^0.25.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/bn.js": "^5.1.1",
"@types/chai": "^4.3.5",
"@types/deep-equal-in-any-order": "^1.0.1",
"@types/mocha": "^10.0.0",
"@types/node": "^18.17.1",
"@types/uuid": "^9.0.5",
"chai": "^4.3.6",
"deep-equal-in-any-order": "^1.1.18",
"dotenv-mono": "^1.3.10",
"eslint": "^8.56.0",
"@types/bn.js": "^5.1.5",
"@types/chai": "^4.3.14",
"@types/deep-equal-in-any-order": "^1.0.3",
"@types/mocha": "^10.0.6",
"@types/node": "20.11.30",
"@types/uuid": "^9.0.8",
"chai": "^4.4.1",
"deep-equal-in-any-order": "^1.1.20",
"dotenv-mono": "^1.3.14",
"eslint": "^8.57.0",
"eslint-config-thirdweb": "workspace:*",
"eslint-plugin-better-tree-shaking": "0.0.4",
"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",
"ethers-aws-kms-signer": "^1.3.2",
"hardhat": "^2.17.0",
"hardhat": "^2.22.2",
"mocha": "10.4.0",
"nyc": "^15.1.0",
"rimraf": "^3.0.2",
"rimraf": "5.0.5",
"typedoc-gen": "workspace:*",
"typescript": "^5.3.3",
"zksync-web3": "^0.14.3"
"typescript": "5.4.3",
"zksync-web3": "^0.14.4"
},
"peerDependencies": {
"@aws-sdk/client-secrets-manager": "^3.215.0",
@@ -137,17 +136,17 @@
"@thirdweb-dev/generated-abis": "workspace:*",
"@thirdweb-dev/merkletree": "workspace:*",
"@thirdweb-dev/storage": "workspace:*",
"abitype": "^0.2.5",
"bn.js": "^5.2.1",
"abitype": "1.0.0",
"bn.js": "5.2.1",
"bs58": "^5.0.0",
"buffer": "^6.0.3",
"eventemitter3": "^5.0.1",
"fast-deep-equal": "^3.1.3",
"tiny-invariant": "^1.2.0",
"tiny-invariant": "^1.3.3",
"tweetnacl": "^1.0.3",
"uuid": "^9.0.1",
"yaml": "^2.3.4",
"zod": "^3.22.3"
"yaml": "^2.4.1",
"zod": "^3.22.4"
},
"bugs": {
"url": "https://github.com/thirdweb-dev/js/issues"
@@ -404,6 +404,12 @@ export function parseRevertReason(error: any): string {
errorString = error.toString();
}
// if the error is just too long, just return the message to limit Regexp processing time
// see: https://cwe.mitre.org/data/definitions/1333.html
if (errorString.length > 5000) {
return error.message || "";
}
return (
parseMessageParts(/.*?"message":"([^"\\]*).*?/, errorString) ||
parseMessageParts(/.*?"reason":"([^"\\]*).*?/, errorString) ||
@@ -487,6 +487,7 @@ export class ContractPublisher extends RPCConnectionHandler {
bytecodeUri: predeployMetadata.bytecodeUri,
name: predeployMetadata.name,
analytics: predeployMetadata.analytics,
compilers: predeployMetadata.compilers,
publisher,
});
const fullMetadataUri = await this.storage.upload(fullMetadata);
@@ -112,6 +112,14 @@ export type Abi = z.output<typeof AbiSchema>;
*/
export type AbiInput = z.input<typeof AbiSchema>;
/**
* @internal
*/
export const CompilerTypeInput = /* @__PURE__ */ (() =>
z.union([z.literal("solc"), z.literal("zksolc")]))();
export type CompilerType = z.input<typeof CompilerTypeInput>;
/**
* @internal
*/
@@ -122,6 +130,21 @@ export const PreDeployMetadata = /* @__PURE__ */ (() =>
metadataUri: z.string(),
bytecodeUri: z.string(),
analytics: z.any().optional(),
compilers: z
.record(
CompilerTypeInput,
// z.record(
z.array(
z.object({
compilerVersion: z.string().optional(),
evmVersion: z.string().optional(),
metadataUri: z.string(),
bytecodeUri: z.string(),
}),
),
// ),
)
.optional(),
})
.catchall(z.any()))();
@@ -65,7 +65,6 @@ export type ExtractFunctionType<
TAbi extends Abi,
TFunctionName extends TAbiFunctionNames<TAbi>,
> = (
// @ts-expect-error - TODO: fix this
...args: ExtractFunctionInputsType<TAbi, TFunctionName>
) => ExtractFunctionOutputsType<TAbi, TFunctionName>;
@@ -6,9 +6,9 @@ import { getChainProvider } from "../constants/urls";
import { Abi } from "../schema/contracts/custom";
import { twProxyArtifactZK } from "./temp-artifact/TWProxy";
import { fetchSourceFilesFromMetadata } from "../common/fetchSourceFilesFromMetadata";
import { fetchRawPredeployMetadata } from "../common/feature-detection/fetchRawPredeployMetadata";
import { fetchContractMetadata } from "../common/fetchContractMetadata";
import { checkVerificationStatus } from "../common/verification";
import { ThirdwebSDK } from "../core/sdk";
const RequestStatus = {
OK: "1",
@@ -27,7 +27,8 @@ export async function zkVerify(
explorerAPIUrl: string,
explorerAPIKey: string,
storage: ThirdwebStorage,
contractUri?: string,
metadataUri?: string,
zkVersion?: string,
encodedConstructorArgs?: string,
) {
try {
@@ -43,18 +44,24 @@ export async function zkVerify(
};
compilerMetadata.metadata.sources = twProxyArtifactZK.sources;
} else {
invariant(contractUri, "No contract URI provided");
const rawMeta = await fetchRawPredeployMetadata(contractUri, storage);
const metadataUri = rawMeta.compilers?.zksolc?.metadataUri;
if (!metadataUri || metadataUri.length === 0) {
metadataUri = await fetchFromMultiChainRegistry(
contractAddress,
chainId,
);
}
invariant(metadataUri && metadataUri.length > 0, "No contract URI found");
invariant(metadataUri, "ZkSolc metadata not found");
const parsedMetadata = await fetchContractMetadata(metadataUri, storage);
const zk_version =
parsedMetadata.metadata.settings.zk_version || zkVersion;
invariant(zk_version, "zk version not found");
compilerMetadata = {
name: parsedMetadata.name,
abi: parsedMetadata.abi,
metadata: parsedMetadata.metadata,
zk_version: rawMeta.zk_version,
zk_version,
};
}
@@ -172,13 +179,28 @@ async function zkFetchConstructorParams(
utils.hexDataSlice(transaction.data, 4),
);
return decoded[2];
return decoded[2].startsWith("0x") ? decoded[2] : `0x${decoded[2]}`;
} else {
// TODO: decode for create2 deployments via factory
return "";
return "0x";
}
} else {
// Could not retrieve constructor parameters, using empty parameters as fallback
return "";
return "0x";
}
}
async function fetchFromMultiChainRegistry(
address: string,
chainId: number,
): Promise<string | undefined> {
try {
// random wallet is fine here, we're doing gasless calls
const sdk = new ThirdwebSDK("polygon");
const uri = await sdk.multiChainRegistry.getContractMetadataURI(
chainId,
address,
);
return uri;
} catch (e) {}
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 104 KiB

+1 -1
View File
@@ -20,7 +20,7 @@ describe("Error Handling", async () => {
});
expect.fail();
} catch (err) {
expectError(err, "sender doesn't have enough funds to send tx");
expectError(err, "Sender doesn't have enough funds to send tx");
}
});
Binary file not shown.
Binary file not shown.
+9
View File
@@ -1,5 +1,14 @@
# @thirdweb-dev/storage
## 2.0.12
### 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/crypto@0.2.3
## 2.0.11
### Patch Changes
+11 -19
View File
@@ -1,6 +1,6 @@
{
"name": "@thirdweb-dev/storage",
"version": "2.0.11",
"version": "2.0.12",
"main": "dist/thirdweb-dev-storage.cjs.js",
"module": "dist/thirdweb-dev-storage.esm.js",
"exports": {
@@ -20,9 +20,7 @@
"fix": "eslint src/ --fix",
"clean": "rm -rf dist/",
"build": "tsc && preconstruct build",
"test:all": "NODE_ENV=test SWC_NODE_PROJECT=./tsconfig.test.json mocha --timeout 30000 --parallel './test/**/*.test.ts'",
"test": "pnpm test:all",
"test:single": "NODE_ENV=test SWC_NODE_PROJECT=./tsconfig.test.json mocha --timeout 30000",
"test": "vitest",
"push": "yalc push",
"typedoc": "node scripts/typedoc.mjs"
},
@@ -33,26 +31,20 @@
"exports": true
},
"devDependencies": {
"@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-node/register": "^1.9.0",
"@thirdweb-dev/tsconfig": "workspace:*",
"@types/chai": "^4.3.5",
"@types/mocha": "^10.0.0",
"@types/uuid": "^9.0.5",
"chai": "^4.3.6",
"eslint": "^8.56.0",
"@types/uuid": "^9.0.8",
"eslint": "^8.57.0",
"eslint-config-thirdweb": "workspace:*",
"eslint-plugin-tsdoc": "^0.2.16",
"eslint-plugin-tsdoc": "^0.2.17",
"esm": "^3.2.25",
"mocha": "10.4.0",
"rimraf": "^3.0.2",
"rimraf": "5.0.5",
"typedoc-gen": "workspace:*",
"typescript": "^5.3.3"
"typescript": "5.4.3"
},
"dependencies": {
"@thirdweb-dev/crypto": "workspace:*",
+4 -5
View File
@@ -1,17 +1,16 @@
/* eslint-disable no-unused-expressions */
import { expect } from "chai";
import { readFileSync } from "fs";
import { getGatewayUrlForCid, IpfsUploader, ThirdwebStorage } from "../src";
import { DEFAULT_GATEWAY_URLS, prepareGatewayUrls } from "../src/common/urls";
import { describe, it, expect } from "vitest";
// load env variables
// eslint-disable-next-line @typescript-eslint/no-var-requires
require("dotenv-mono").load();
const secretKey = process.env.TW_SECRET_KEY as string;
const itIfCI = process.env.CI ? it : it.skip;
describe("IPFS", async () => {
describe("IPFS", { timeout: 30000 }, async () => {
if (!secretKey) {
throw new Error("TW_SECRET_KEY is not set in the environment variables");
}
@@ -413,7 +412,7 @@ describe("IPFS", async () => {
});
// only run this in CI because on local it will always be different (different api key)
itIfCI(
it.runIf(process.env.CI)(
"Should return URIs with gateway URLs if specified on function",
async () => {
const uri = await storage.upload(
+27
View File
@@ -1,5 +1,32 @@
# @thirdweb-dev/wallets
## 2.4.30
### Patch Changes
- Updated dependencies [[`3ef3786`](https://github.com/thirdweb-dev/js/commit/3ef378659e83341663dfaded417e33b5af29bbbc)]:
- @thirdweb-dev/chains@0.1.85
- @thirdweb-dev/sdk@4.0.54
## 2.4.29
### Patch Changes
- Updated dependencies [[`6bd1b82`](https://github.com/thirdweb-dev/js/commit/6bd1b82a58505ec3af3a12ceeab51d78ee3b8bc0)]:
- @thirdweb-dev/sdk@4.0.53
## 2.4.28
### 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 [[`c81bb88`](https://github.com/thirdweb-dev/js/commit/c81bb882c505a5f1feb8f627377e76a771cce3f4), [`d93286b`](https://github.com/thirdweb-dev/js/commit/d93286bc1f8224d055b50ce3ffa4f302869cb2b1), [`50e7dba`](https://github.com/thirdweb-dev/js/commit/50e7dbaa9dae77cb8cd865405c322495e2498c65)]:
- @thirdweb-dev/sdk@4.0.52
- @thirdweb-dev/contracts-js@1.3.19
- @thirdweb-dev/chains@0.1.84
- @thirdweb-dev/crypto@0.2.3
## 2.4.27
### Patch Changes
+27 -33
View File
@@ -1,6 +1,6 @@
{
"name": "@thirdweb-dev/wallets",
"version": "2.4.27",
"version": "2.4.30",
"main": "dist/thirdweb-dev-wallets.cjs.js",
"module": "dist/thirdweb-dev-wallets.esm.js",
"browser": {
@@ -520,34 +520,34 @@
"sideEffects": false,
"dependencies": {
"@account-abstraction/contracts": "^0.5.0",
"@blocto/sdk": "^0.5.4",
"@coinbase/wallet-sdk": "^3.7.1",
"@blocto/sdk": "0.5.5",
"@coinbase/wallet-sdk": "^3.7.2",
"@google-cloud/kms": "3.0.1",
"@magic-ext/connect": "^6.7.2",
"@magic-ext/oauth": "^7.6.2",
"@magic-sdk/provider": "^13.6.2",
"@metamask/eth-sig-util": "^4.0.0",
"@metamask/eth-sig-util": "^4.0.1",
"@paperxyz/embedded-wallet-service-sdk": "^1.2.5",
"@paperxyz/sdk-common-utilities": "^0.1.0",
"@safe-global/safe-core-sdk": "^3.3.4",
"@paperxyz/sdk-common-utilities": "^0.1.1",
"@safe-global/safe-core-sdk": "^3.3.5",
"@safe-global/safe-ethers-adapters": "0.1.0-alpha.17",
"@safe-global/safe-ethers-lib": "^1.9.4",
"@thirdweb-dev/chains": "workspace:*",
"@thirdweb-dev/contracts-js": "workspace:*",
"@thirdweb-dev/crypto": "workspace:*",
"@thirdweb-dev/sdk": "workspace:*",
"@walletconnect/core": "^2.9.1",
"@walletconnect/ethereum-provider": "^2.9.1",
"@walletconnect/core": "^2.11.3",
"@walletconnect/ethereum-provider": "^2.11.3",
"@walletconnect/jsonrpc-utils": "^1.0.8",
"@walletconnect/modal": "^2.6.1",
"@walletconnect/types": "^2.9.1",
"@walletconnect/utils": "^2.10.2",
"@walletconnect/web3wallet": "^1.8.7",
"@walletconnect/modal": "^2.6.2",
"@walletconnect/types": "^2.11.3",
"@walletconnect/utils": "^2.11.3",
"@walletconnect/web3wallet": "^1.10.3",
"asn1.js": "5.4.1",
"bn.js": "5.2.0",
"bn.js": "5.2.1",
"buffer": "^6.0.3",
"eth-provider": "^0.13.6",
"ethereumjs-util": "^7.1.3",
"ethereumjs-util": "^7.1.5",
"eventemitter3": "^5.0.1",
"key-encoder": "2.0.3",
"magic-sdk": "^13.6.2",
@@ -582,34 +582,31 @@
}
},
"devDependencies": {
"@aws-sdk/client-secrets-manager": "^3.378.0",
"@babel/plugin-transform-class-properties": "^7.23.3",
"@babel/plugin-transform-flow-strip-types": "^7.23.3",
"@babel/plugin-transform-private-methods": "^7.23.3",
"@microsoft/api-extractor": "^7.36.3",
"@noble/ed25519": "^1.7.1",
"@aws-sdk/client-secrets-manager": "^3.543.0",
"@babel/plugin-transform-class-properties": "^7.24.1",
"@babel/plugin-transform-flow-strip-types": "^7.24.1",
"@babel/plugin-transform-private-methods": "^7.24.1",
"@microsoft/api-extractor": "^7.43.0",
"@noble/ed25519": "^1.7.3",
"@nomiclabs/hardhat-ethers": "^2.2.3",
"@preconstruct/cli": "2.7.0",
"@thirdweb-dev/tsconfig": "workspace:*",
"@types/bn.js": "^5.1.1",
"@types/jest": "^29.5.3",
"abitype": "^0.2.5",
"@types/bn.js": "^5.1.5",
"abitype": "1.0.0",
"babel-plugin-transform-inline-environment-variables": "^0.4.4",
"bs58": "^5.0.0",
"cross-env": "^7.0.3",
"eslint-config-thirdweb": "workspace:*",
"eslint-plugin-better-tree-shaking": "0.0.4",
"eslint-plugin-tsdoc": "^0.2.16",
"eslint-plugin-tsdoc": "^0.2.17",
"ethereum-provider": "^0.7.7",
"ethers": "^5.7.2",
"ethers-aws-kms-signer": "^1.3.2",
"hardhat": "^2.17.0",
"jest": "^29.6.2",
"rimraf": "^3.0.2",
"ts-jest": "^29.1.1",
"hardhat": "^2.22.2",
"rimraf": "5.0.5",
"tweetnacl": "^1.0.3",
"typedoc-gen": "workspace:*",
"typescript": "^5.3.3"
"typescript": "5.4.3"
},
"scripts": {
"format": "prettier --write 'src/**/*'",
@@ -620,12 +617,9 @@
"preconstruct:fix": "preconstruct fix",
"push": "yalc push",
"typedoc": "node scripts/typedoc.mjs",
"test": "jest"
"test": "vitest"
},
"engines": {
"node": ">=18"
},
"jest": {
"testTimeout": 30000
}
}
@@ -4,11 +4,10 @@ import { LocalWallet } from "../src/evm/wallets/local-wallet";
import { BaseSepoliaTestnet } from "@thirdweb-dev/chains";
import { ThirdwebSDK, SmartContract } from "@thirdweb-dev/sdk";
import { BigNumber, ethers } from "ethers";
import { describe, it, expect, beforeAll } from "vitest";
require("dotenv-mono").load();
jest.setTimeout(240_000);
let smartWallet: SmartWallet;
let smartWalletAddress: string;
let personalWallet: LocalWallet;
@@ -42,66 +41,75 @@ beforeAll(async () => {
);
});
describeIf(!!process.env.TW_SECRET_KEY)("ERC20Paymaster core tests", () => {
it("can connect", async () => {
expect(smartWalletAddress).toHaveLength(42);
});
it("should deploy+approve (gasless) and execute a tx", async () => {
const tokenContract = await sdk.getContract(erc20TokenAddress);
// initial checks
let approvedAmount = (
await tokenContract.erc20.allowanceOf(
smartWalletAddress,
erc20PaymasterAddress,
)
).value;
expect(approvedAmount.toNumber()).toEqual(0);
let isDeployed = await smartWallet.isDeployed();
expect(isDeployed).toEqual(false);
let balance = (await contract.erc20.balance()).value;
expect(balance.toNumber()).toEqual(0);
// airdrop tokens for payment
const tempLocalWallet = new LocalWallet();
await tempLocalWallet.generate();
const tempSmartWallet = new SmartWallet({
chain,
factoryAddress,
gasless: true,
secretKey: process.env.TW_SECRET_KEY,
describeIf(!!process.env.TW_SECRET_KEY)(
"ERC20Paymaster core tests",
{
timeout: 240_000,
},
() => {
it("can connect", async () => {
expect(smartWalletAddress).toHaveLength(42);
});
await tempSmartWallet.connect({
personalWallet: tempLocalWallet,
});
const claimTx = await contract.erc20.claimTo.prepare(smartWalletAddress, 1); // tx costs 1
const claimReceipt = await tempSmartWallet.execute(claimTx);
expect(claimReceipt.receipt.transactionHash).toHaveLength(66);
balance = (await contract.erc20.balance()).value;
expect(balance).toEqual(ethers.utils.parseEther("1"));
// transact with newly funded smart wallet using erc20 exclusively
const preparedTx = await contract.erc20.claim.prepare(1);
const tx = await smartWallet.execute(preparedTx);
expect(tx.receipt.transactionHash).toHaveLength(66);
it("should deploy+approve (gasless) and execute a tx", async () => {
const tokenContract = await sdk.getContract(erc20TokenAddress);
approvedAmount = (
await tokenContract.erc20.allowanceOf(
// initial checks
let approvedAmount = (
await tokenContract.erc20.allowanceOf(
smartWalletAddress,
erc20PaymasterAddress,
)
).value;
expect(approvedAmount.toNumber()).toEqual(0);
let isDeployed = await smartWallet.isDeployed();
expect(isDeployed).toEqual(false);
let balance = (await contract.erc20.balance()).value;
expect(balance.toNumber()).toEqual(0);
// airdrop tokens for payment
const tempLocalWallet = new LocalWallet();
await tempLocalWallet.generate();
const tempSmartWallet = new SmartWallet({
chain,
factoryAddress,
gasless: true,
secretKey: process.env.TW_SECRET_KEY,
});
await tempSmartWallet.connect({
personalWallet: tempLocalWallet,
});
const claimTx = await contract.erc20.claimTo.prepare(
smartWalletAddress,
erc20PaymasterAddress,
)
).value;
expect(approvedAmount).toEqual(
BigNumber.from(2).pow(96).sub(1).sub(ethers.utils.parseEther("1")), // 2^96 - 1 - 1^18 <- 1^18 is the tx cost removed from allowance
);
1,
); // tx costs 1
const claimReceipt = await tempSmartWallet.execute(claimTx);
expect(claimReceipt.receipt.transactionHash).toHaveLength(66);
balance = (await contract.erc20.balance()).value;
expect(balance).toEqual(ethers.utils.parseEther("1"));
isDeployed = await smartWallet.isDeployed();
expect(isDeployed).toEqual(true);
// transact with newly funded smart wallet using erc20 exclusively
const preparedTx = await contract.erc20.claim.prepare(1);
const tx = await smartWallet.execute(preparedTx);
expect(tx.receipt.transactionHash).toHaveLength(66);
balance = (await contract.erc20.balance()).value;
expect(balance).toEqual(ethers.utils.parseEther("1")); // we spent 1 token to claim 1 token
});
});
approvedAmount = (
await tokenContract.erc20.allowanceOf(
smartWalletAddress,
erc20PaymasterAddress,
)
).value;
expect(approvedAmount).toEqual(
BigNumber.from(2).pow(96).sub(1).sub(ethers.utils.parseEther("1")), // 2^96 - 1 - 1^18 <- 1^18 is the tx cost removed from allowance
);
isDeployed = await smartWallet.isDeployed();
expect(isDeployed).toEqual(true);
balance = (await contract.erc20.balance()).value;
expect(balance).toEqual(ethers.utils.parseEther("1")); // we spent 1 token to claim 1 token
});
},
);
@@ -4,11 +4,10 @@ import { LocalWallet } from "../src/evm/wallets/local-wallet";
import { ArbitrumSepolia } from "@thirdweb-dev/chains";
import { ThirdwebSDK, SmartContract } from "@thirdweb-dev/sdk";
import { checkContractWalletSignature } from "../src/evm/connectors/smart-wallet/lib/check-contract-wallet-signature";
import { describe, it, expect, beforeAll } from "vitest";
require("dotenv-mono").load();
jest.setTimeout(240_000);
let smartWallet: SmartWallet;
let smartWalletAddress: string;
let personalWallet: LocalWallet;
@@ -39,116 +38,122 @@ beforeAll(async () => {
);
});
describeIf(!!SECRET_KEY)("SmartWallet core tests", () => {
it("can connect", async () => {
expect(smartWalletAddress).toHaveLength(42);
});
it("can execute a tx via SDK", async () => {
const tx = await contract.erc1155.claim(0, 1);
expect(tx.receipt.transactionHash).toHaveLength(66);
const isDeployed = await smartWallet.isDeployed();
expect(isDeployed).toEqual(true);
const balance = await contract.erc1155.balance(0);
expect(balance.toNumber()).toEqual(1);
});
it("can estimate a tx", async () => {
const preparedTx = await contract.erc1155.claim.prepare(0, 1);
const estimates = await smartWallet.estimate(preparedTx);
expect(estimates.wei.toString()).not.toBe("0");
});
it("can execute a tx", async () => {
const preparedTx = await contract.erc1155.claim.prepare(0, 1);
const tx = await smartWallet.execute(preparedTx);
expect(tx.receipt.transactionHash).toHaveLength(66);
const balance = await contract.erc1155.balance(0);
expect(balance.toNumber()).toEqual(2);
});
it("can execute a batched tx", async () => {
const preparedTx = await contract.erc1155.claim.prepare(0, 1);
const tx = await smartWallet.executeBatch([preparedTx, preparedTx]);
expect(tx.receipt.transactionHash).toHaveLength(66);
const balance = await contract.erc1155.balance(0);
expect(balance.toNumber()).toEqual(4);
});
it("can execute a raw tx", async () => {
const preparedTx = await contract.erc1155.claim.prepare(0, 1);
const tx = await smartWallet.executeRaw({
to: preparedTx.getTarget(),
data: preparedTx.encode(),
describeIf(!!SECRET_KEY)(
"SmartWallet core tests",
{
timeout: 240_000,
},
() => {
it("can connect", async () => {
expect(smartWalletAddress).toHaveLength(42);
});
expect(tx.receipt.transactionHash).toHaveLength(66);
const balance = await contract.erc1155.balance(0);
expect(balance.toNumber()).toEqual(5);
});
it("can execute a batched raw tx", async () => {
const preparedTx = await contract.erc1155.claim.prepare(0, 1);
const tx = await smartWallet.executeBatchRaw([
{
it("can execute a tx via SDK", async () => {
const tx = await contract.erc1155.claim(0, 1);
expect(tx.receipt.transactionHash).toHaveLength(66);
const isDeployed = await smartWallet.isDeployed();
expect(isDeployed).toEqual(true);
const balance = await contract.erc1155.balance(0);
expect(balance.toNumber()).toEqual(1);
});
it("can estimate a tx", async () => {
const preparedTx = await contract.erc1155.claim.prepare(0, 1);
const estimates = await smartWallet.estimate(preparedTx);
expect(estimates.wei.toString()).not.toBe("0");
});
it("can execute a tx", async () => {
const preparedTx = await contract.erc1155.claim.prepare(0, 1);
const tx = await smartWallet.execute(preparedTx);
expect(tx.receipt.transactionHash).toHaveLength(66);
const balance = await contract.erc1155.balance(0);
expect(balance.toNumber()).toEqual(2);
});
it("can execute a batched tx", async () => {
const preparedTx = await contract.erc1155.claim.prepare(0, 1);
const tx = await smartWallet.executeBatch([preparedTx, preparedTx]);
expect(tx.receipt.transactionHash).toHaveLength(66);
const balance = await contract.erc1155.balance(0);
expect(balance.toNumber()).toEqual(4);
});
it("can execute a raw tx", async () => {
const preparedTx = await contract.erc1155.claim.prepare(0, 1);
const tx = await smartWallet.executeRaw({
to: preparedTx.getTarget(),
data: preparedTx.encode(),
},
{
to: preparedTx.getTarget(),
data: preparedTx.encode(),
},
]);
expect(tx.receipt.transactionHash).toHaveLength(66);
const balance = await contract.erc1155.balance(0);
expect(balance.toNumber()).toEqual(7);
});
it("can sign and verify 1271 old factory", async () => {
const message = "0x1234";
const sig = await smartWallet.signMessage(message);
const isValidV1 = await smartWallet.verifySignature(
message,
sig,
smartWalletAddress,
chain.chainId,
);
expect(isValidV1).toEqual(true);
const isValidV2 = await checkContractWalletSignature(
message,
sig,
smartWalletAddress,
chain.chainId,
undefined,
SECRET_KEY,
);
expect(isValidV2).toEqual(true);
});
it("can sign and verify 1271 new factory", async () => {
smartWallet = new SmartWallet({
chain,
factoryAddress: factoryAddressV2,
gasless: true,
secretKey: process.env.TW_SECRET_KEY,
});
expect(tx.receipt.transactionHash).toHaveLength(66);
const balance = await contract.erc1155.balance(0);
expect(balance.toNumber()).toEqual(5);
});
smartWalletAddress = await smartWallet.connect({ personalWallet });
const message = "0x1234";
const sig = await smartWallet.signMessage(message);
const isValidV1 = await smartWallet.verifySignature(
message,
sig,
smartWalletAddress,
chain.chainId,
);
expect(isValidV1).toEqual(true);
const isValidV2 = await checkContractWalletSignature(
message,
sig,
smartWalletAddress,
chain.chainId,
undefined,
SECRET_KEY,
);
expect(isValidV2).toEqual(true);
});
});
it("can execute a batched raw tx", async () => {
const preparedTx = await contract.erc1155.claim.prepare(0, 1);
const tx = await smartWallet.executeBatchRaw([
{
to: preparedTx.getTarget(),
data: preparedTx.encode(),
},
{
to: preparedTx.getTarget(),
data: preparedTx.encode(),
},
]);
expect(tx.receipt.transactionHash).toHaveLength(66);
const balance = await contract.erc1155.balance(0);
expect(balance.toNumber()).toEqual(7);
});
it("can sign and verify 1271 old factory", async () => {
const message = "0x1234";
const sig = await smartWallet.signMessage(message);
const isValidV1 = await smartWallet.verifySignature(
message,
sig,
smartWalletAddress,
chain.chainId,
);
expect(isValidV1).toEqual(true);
const isValidV2 = await checkContractWalletSignature(
message,
sig,
smartWalletAddress,
chain.chainId,
undefined,
SECRET_KEY,
);
expect(isValidV2).toEqual(true);
});
it("can sign and verify 1271 new factory", async () => {
smartWallet = new SmartWallet({
chain,
factoryAddress: factoryAddressV2,
gasless: true,
secretKey: process.env.TW_SECRET_KEY,
});
smartWalletAddress = await smartWallet.connect({ personalWallet });
const message = "0x1234";
const sig = await smartWallet.signMessage(message);
const isValidV1 = await smartWallet.verifySignature(
message,
sig,
smartWalletAddress,
chain.chainId,
);
expect(isValidV1).toEqual(true);
const isValidV2 = await checkContractWalletSignature(
message,
sig,
smartWalletAddress,
chain.chainId,
undefined,
SECRET_KEY,
);
expect(isValidV2).toEqual(true);
});
},
);
@@ -5,6 +5,7 @@ import { SmartWallet } from "../src/evm/wallets/smart-wallet";
import { EthersWallet } from "../src/evm/wallets/ethers";
import { EntryPoint__factory } from "@account-abstraction/contracts";
import { AbstractWallet } from "../src";
import { describe, it, beforeAll } from "vitest";
// TODO make this work with a mock bundler/paymaster
+7 -4
View File
@@ -11,7 +11,8 @@
},
"scripts": {
"preinstall": "npx only-allow pnpm",
"test": "turbo run test --filter=./packages/* --filter=./legacy_packages/*",
"test": "turbo run test --filter=./packages/*",
"test:legacy": "turbo run test --filter=./legacy_packages/*",
"e2e": "turbo run e2e",
"build": "turbo run build --filter=./packages/* --filter=./legacy_packages/*",
"bench": "turbo run bench",
@@ -77,7 +78,7 @@
"sharp": "^0.33.3",
"size-limit": "11.1.2",
"typedoc-gen": "workspace:*",
"typescript": "5.3.3",
"typescript": "5.4.3",
"vitest": "1.4.0"
},
"manypkg": {
@@ -89,7 +90,7 @@
"glob-parent@<5.1.2": ">=5.1.2",
"nth-check@<2.0.1": ">=2.0.1",
"socket.io-parser@>=4.0.4 <4.2.3": ">=4.2.3",
"fast-xml-parser@<4.2.4": ">=4.2.4",
"fast-xml-parser@<=4.2.4": ">4.2.4",
"@openzeppelin/contracts@>=4.3.0 <4.9.1": ">=4.9.1",
"@openzeppelin/contracts@>=4.7.0 <4.9.2": ">=4.9.2",
"xml2js@<0.5.0": ">=0.5.0",
@@ -97,7 +98,9 @@
"semver@<7.5.2": ">=7.5.2",
"json5@<1.0.2": ">=1.0.2",
"protobufjs@>=6.10.0 <7.2.4": ">=7.2.4",
"tough-cookie@<4.1.3": ">=4.1.3"
"tough-cookie@<4.1.3": ">=4.1.3",
"@ethereumjs/util@<9.0.0": ">=9.0.0",
"axios@<0.28.0": ">=0.28.0"
}
}
}
+6
View File
@@ -1,5 +1,11 @@
# @thirdweb-dev/service-utils
## 0.4.24
### 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
## 0.4.23
### Patch Changes
+4 -7
View File
@@ -1,6 +1,6 @@
{
"name": "@thirdweb-dev/service-utils",
"version": "0.4.23",
"version": "0.4.24",
"main": "dist/thirdweb-dev-service-utils.cjs.js",
"module": "dist/thirdweb-dev-service-utils.esm.js",
"exports": {
@@ -46,13 +46,10 @@
"@cloudflare/workers-types": "4.20240320.1",
"@preconstruct/cli": "2.7.0",
"@thirdweb-dev/tsconfig": "workspace:*",
"@types/jest": "^29.5.3",
"@types/node": "^20.11.30",
"@types/node": "20.11.30",
"eslint": "8.57.0",
"eslint-config-thirdweb": "workspace:*",
"jest": "^29.6.2",
"ts-jest": "^29.1.1",
"typescript": "^5.3.3"
"typescript": "5.4.3"
},
"scripts": {
"format": "prettier --write 'src/**/*'",
@@ -61,6 +58,6 @@
"clean": "rm -rf dist/",
"build": "tsc && preconstruct build",
"push": "yalc push",
"test": "jest"
"test": "vitest"
}
}
@@ -1,5 +1,6 @@
import { authorize } from ".";
import { CoreServiceConfig } from "../api";
import { describe, it, expect } from "vitest";
const validServiceConfig: CoreServiceConfig = {
apiUrl: "https://api.example.com",
@@ -1,5 +1,6 @@
import { validApiKeyMeta } from "../../mocks";
import { ClientAuthorizationPayload, authorizeClient } from "./client";
import { describe, it, expect } from "vitest";
describe("authorizeClient", () => {
const validAuthOptions: ClientAuthorizationPayload = {
@@ -5,6 +5,7 @@ import {
} from "../../mocks";
import { CoreServiceConfig } from "../api";
import { ServiceAuthorizationPayload, authorizeService } from "./service";
import { describe, it, expect } from "vitest";
describe("authorizeService", () => {
it("should authorize service with valid service scope and action", () => {
@@ -2,15 +2,16 @@ import { rateLimit } from ".";
import { validApiKeyMeta, validServiceConfig } from "../../mocks";
import { updateRateLimitedAt } from "../api";
import { AuthorizationResult } from "../authorize/types";
import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
const mockRedis = {
incr: jest.fn(),
expire: jest.fn(),
incr: vi.fn(),
expire: vi.fn(),
};
// Mocking the updateRateLimitedAt function
jest.mock("../../../src/core/api", () => ({
updateRateLimitedAt: jest.fn(),
vi.mock("../../../src/core/api", () => ({
updateRateLimitedAt: vi.fn(),
}));
const DEFAULT_AUTHZ_RESULT: AuthorizationResult = {
@@ -25,13 +26,13 @@ const DEFAULT_AUTHZ_RESULT: AuthorizationResult = {
describe("rateLimit", () => {
beforeEach(() => {
// Clear mock function calls and reset any necessary state.
jest.clearAllMocks();
vi.clearAllMocks();
mockRedis.incr.mockReset();
mockRedis.expire.mockReset();
});
afterEach(() => {
jest.spyOn(global.Math, "random").mockRestore();
vi.spyOn(global.Math, "random").mockRestore();
});
it("should not rate limit if service scope is not in rate limits", async () => {
@@ -128,7 +129,7 @@ describe("rateLimit", () => {
it("enforces rate limit if sampled (hit)", async () => {
mockRedis.incr.mockResolvedValue(10);
jest.spyOn(global.Math, "random").mockReturnValue(0.08);
vi.spyOn(global.Math, "random").mockReturnValue(0.08);
const result = await rateLimit({
authzResult: DEFAULT_AUTHZ_RESULT,
@@ -146,7 +147,7 @@ describe("rateLimit", () => {
it("does not enforce rate limit if sampled (miss)", async () => {
mockRedis.incr.mockResolvedValue(10);
jest.spyOn(global.Math, "random").mockReturnValue(0.15);
vi.spyOn(global.Math, "random").mockReturnValue(0.15);
const result = await rateLimit({
authzResult: DEFAULT_AUTHZ_RESULT,
@@ -1,5 +1,6 @@
import { usageLimit } from ".";
import { validApiKeyMeta, validServiceConfig } from "../../mocks";
import { describe, it, expect } from "vitest";
describe("usageLimit", () => {
it("should not usage limit if service scope is not in limits", async () => {
+28
View File
@@ -1,5 +1,33 @@
# thirdweb
## 5.0.3
### Patch Changes
- [#2595](https://github.com/thirdweb-dev/js/pull/2595) [`dd1141f`](https://github.com/thirdweb-dev/js/commit/dd1141f9af002817fb4fd4c002f5d77fde4ac950) Thanks [@MananTank](https://github.com/MananTank)! - Do not subscribe to `session_request_sent` event when using `walletConnect` because that is already handled when connecting with official Modal
- [#2591](https://github.com/thirdweb-dev/js/pull/2591) [`6d63920`](https://github.com/thirdweb-dev/js/commit/6d63920c0a25a395fed091f749e6e5438dce0b5d) Thanks [@MananTank](https://github.com/MananTank)! - Add `walletConnect`, fix WC connection issues
- [#2588](https://github.com/thirdweb-dev/js/pull/2588) [`eba8f1c`](https://github.com/thirdweb-dev/js/commit/eba8f1c19839ad89391d03271ef96b51d5f515ed) Thanks [@joaquim-verges](https://github.com/joaquim-verges)! - Fix 721/1155 claimTo
## 5.0.2
### Patch Changes
- [#2585](https://github.com/thirdweb-dev/js/pull/2585) [`052892b`](https://github.com/thirdweb-dev/js/commit/052892b39677755b3167da7520d48446a5ce7c59) Thanks [@MananTank](https://github.com/MananTank)! - Fix wallet not opened on WC sessions request event on page reload on mobile
- [#2587](https://github.com/thirdweb-dev/js/pull/2587) [`6063f40`](https://github.com/thirdweb-dev/js/commit/6063f40f87b2a108840cb08e1e9025542931b7e0) Thanks [@jnsdls](https://github.com/jnsdls)! - [CLI] - fix execution on windows and when prettier is not installed
## 5.0.1
### Patch Changes
- [#2572](https://github.com/thirdweb-dev/js/pull/2572) [`701cd88`](https://github.com/thirdweb-dev/js/commit/701cd880dfc81cf294bb48a23996b2dc737c3d4b) Thanks [@jnsdls](https://github.com/jnsdls)! - point CLI backwards compatibility @latest instead of @beta
- [#2576](https://github.com/thirdweb-dev/js/pull/2576) [`04961f0`](https://github.com/thirdweb-dev/js/commit/04961f0e9a333f9626519d726006def9fb67d7db) Thanks [@joaquim-verges](https://github.com/joaquim-verges)! - Change getWalletBalance prop from account to address
- [#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
## 5.0.0
### Major Changes
+1 -1
View File
@@ -14,7 +14,7 @@
## Installation
```bash
npm install thirdweb@beta
npm install thirdweb
```
## Features
+3 -3
View File
@@ -1,6 +1,6 @@
{
"name": "thirdweb",
"version": "5.0.0",
"version": "5.0.3",
"repository": {
"type": "git",
"url": "git+https://github.com/thirdweb-dev/js.git#main"
@@ -191,7 +191,7 @@
"mipd": "0.0.7",
"node-libs-browser": "2.2.1",
"uqr": "0.1.2",
"viem": "2.9.4"
"viem": "2.9.5"
},
"peerDependencies": {
"ethers": "^5 || ^6",
@@ -225,7 +225,7 @@
"push": "yalc push",
"size": "size-limit",
"test:watch": "vitest -c ./test/vitest.config.ts dev",
"test": "CI=true vitest -c ./test/vitest.config.ts --coverage --retry=3 --bail=1 --pool=forks",
"test": "CI=true vitest -c ./test/vitest.config.ts --coverage --bail=1",
"test:cov": "vitest dev -c ./test/vitest.config.ts --coverage",
"test:dev": "vitest dev -c ./test/vitest.config.ts",
"typedoc": "node scripts/typedoc.mjs",
+30 -1
View File
@@ -89,6 +89,21 @@ const walletInfos = allSupportedWallets.map((wallet) => {
return { id: wallet.id, name: wallet.name };
});
const customWalletInfos = [
{
id: "smart",
name: "Smart Wallet",
},
{
id: "embedded",
name: "Embedded Wallet",
},
{
id: "walletConnect",
name: "WalletConnect",
},
];
// clean the __geneated__ folder within `src/wallets/` directory
const OUT_PATH = join(__dirname, "../../src/wallets/__generated__");
@@ -141,7 +156,7 @@ export type MinimalWalletInfo = {
/**
* @internal
*/
const ALL_MINIMAL_WALLET_INFOS = <const>${JSON.stringify(walletInfos, null, 2)} satisfies MinimalWalletInfo[];
const ALL_MINIMAL_WALLET_INFOS = <const>${JSON.stringify([...walletInfos, ...customWalletInfos], null, 2)} satisfies MinimalWalletInfo[];
export default ALL_MINIMAL_WALLET_INFOS;
`,
@@ -222,6 +237,19 @@ const walletImports = allSupportedWallets
)
.join("\n");
const customWalletImports = ["smart", "embedded", "walletConnect"]
.map(
(walletId) =>
`case "${walletId}": {
return (
image
? import("../custom/${walletId}/image.js").then((img) => img.default)
: import("../custom/${walletId}/index.js").then((w) => w.wallet)
) as Promise<[TImage] extends [true] ? string : any>;
}`,
)
.join("\n");
await writeFile(
join(OUT_PATH, "getWalletInfo.ts"),
await format(
@@ -238,6 +266,7 @@ import type { WalletId } from "../wallet-types.js";
*/
export async function getWalletInfo<TImage extends boolean>(id: WalletId, image?: TImage): Promise<[TImage] extends [true] ? string : WalletInfo> {
switch (id) {
${customWalletImports}
${walletImports}
default: {
throw new Error(\`Wallet with id \${id} not found\`);
+18 -1
View File
@@ -6,7 +6,24 @@ const ANALYTICS_ENDPOINT = "https://c.thirdweb.com/event";
/**
* @internal
*/
export function track(client: ThirdwebClient, data: object) {
export function trackConnect(args: {
client: ThirdwebClient;
walletType: string;
walletAddress: string;
}) {
const { client, walletType, walletAddress } = args;
track(client, {
source: "connectWallet",
action: "connect",
walletType,
walletAddress,
});
}
/**
* @internal
*/
function track(client: ThirdwebClient, data: object) {
const fetch = getClientFetch(client);
fetch(ANALYTICS_ENDPOINT, {
+29 -11
View File
@@ -23,21 +23,39 @@ async function main() {
}
default: {
const isWindows = /^win/.test(process.platform);
let bunAvailable = false;
try {
const res = execSync("bun --version", {
stdio: "ignore",
encoding: "utf-8",
});
if (typeof res === "string" && res.indexOf(".") > -1) {
bunAvailable = true;
// bun has no windows support yet anyways
if (!isWindows) {
try {
const res = execSync("bun --version", {
stdio: "ignore",
encoding: "utf-8",
});
if (typeof res === "string" && res.indexOf(".") > -1) {
bunAvailable = true;
}
} catch {
bunAvailable = false;
}
} catch {
bunAvailable = false;
}
const runner = bunAvailable ? "bunx" : "npx";
let runner = "npx";
switch (true) {
case bunAvailable:
runner = "bun";
break;
case isWindows:
runner = "npx.cmd";
break;
}
const args = command
? ["--yes", "@thirdweb-dev/cli@latest", command, ...rest]
: ["--yes", "@thirdweb-dev/cli@latest", ...rest];
// eslint-disable-next-line better-tree-shaking/no-top-level-side-effects
spawn(runner, ["--yes", "@thirdweb-dev/cli@beta", command, ...rest], {
spawn(runner, args, {
stdio: "inherit",
});
}
@@ -12,12 +12,13 @@ import {
type AbiFunction,
formatAbiItem,
} from "abitype";
import { format } from "prettier";
import { prepareMethod } from "../../../utils/abi/prepare-method.js";
import { mkdir, writeFile } from "node:fs/promises";
import { packageDirectory } from "./utils.js";
import { join } from "node:path";
import { existsSync } from "node:fs";
import type { Options } from "prettier";
const client = createThirdwebClient({ clientId: "test" });
@@ -150,7 +151,7 @@ async function generateFromAbi(abi: Abi | string[]) {
);
}
const prettified = await format(body, {
const prettified = await prettifyCode(body, {
parser: "babel-ts",
});
return prettified;
@@ -330,3 +331,18 @@ function lowercaseFirstLetter(str: string) {
function eventNameToPreparedEventName(name: string) {
return `${lowercaseFirstLetter(name)}Event`;
}
const printedPrettierWarning = false;
async function prettifyCode(code: string, options: Options) {
try {
const { format } = await import("prettier/standalone.js");
return await format(code, options);
} catch (e) {
if (!printedPrettierWarning) {
console.info("Prettier not found, skipping code formatting.");
}
}
return code;
}

Some files were not shown because too many files have changed in this diff Show More