Compare commits
36
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6cc38b0680 | ||
|
|
7abb36a7ec | ||
|
|
6832b19fc5 | ||
|
|
1c4cbedb6a | ||
|
|
8ff87be631 | ||
|
|
e43beec36a | ||
|
|
c5b7fef5ba | ||
|
|
4c5e40ae4e | ||
|
|
ab2dfd4f5c | ||
|
|
13029e3286 | ||
|
|
44c9ccd65d | ||
|
|
7912c26323 | ||
|
|
69d68f5a25 | ||
|
|
836be52724 | ||
|
|
9f993dcc1e | ||
|
|
61760a180f | ||
|
|
a3f3e160e0 | ||
|
|
b1190914a9 | ||
|
|
e79a952061 | ||
|
|
480ed721d1 | ||
|
|
42c7436827 | ||
|
|
16e9e8b64d | ||
|
|
23ab897e32 | ||
|
|
6fcdec7c12 | ||
|
|
b734f05525 | ||
|
|
30ea9c6bf7 | ||
|
|
6de3a19b86 | ||
|
|
06e59cf916 | ||
|
|
3f3a484a3a | ||
|
|
05e52114bf | ||
|
|
1a421d3b5d | ||
|
|
97fdbc8f64 | ||
|
|
ebf4025718 | ||
|
|
a81a5285b7 | ||
|
|
95c9d56ea4 | ||
|
|
18552f3a22 |
+11
-1
@@ -15,7 +15,17 @@
|
||||
"access": "public",
|
||||
"baseBranch": "main",
|
||||
"updateInternalDependencies": "patch",
|
||||
"ignore": ["e2e-cra-5", "e2e-next-13", "e2e-vite-3"],
|
||||
"ignore": [
|
||||
"e2e-cra-5",
|
||||
"e2e-next-13",
|
||||
"e2e-vite-3",
|
||||
"bundlers-esbuild",
|
||||
"bundlers-vite",
|
||||
"bundlers-webpack",
|
||||
"bundlers-swc",
|
||||
"runtimes-node-commonjs",
|
||||
"runtimes-node-module"
|
||||
],
|
||||
"___experimentalUnsafeOptions_WILL_CHANGE_IN_PATCH": {
|
||||
"updateInternalDependents": "always",
|
||||
"onlyUpdatePeerDependentsWhenOutOfRange": true
|
||||
|
||||
@@ -31,6 +31,11 @@ jobs:
|
||||
with:
|
||||
fetch-depth: 25
|
||||
|
||||
- name: Setup bun
|
||||
uses: oven-sh/setup-bun@v1
|
||||
with:
|
||||
bun-version: latest
|
||||
|
||||
- name: Install
|
||||
uses: ./.github/composite-actions/install
|
||||
|
||||
@@ -59,6 +64,11 @@ jobs:
|
||||
node-version: 20
|
||||
check-latest: true
|
||||
|
||||
- name: Setup bun
|
||||
uses: oven-sh/setup-bun@v1
|
||||
with:
|
||||
bun-version: latest
|
||||
|
||||
- uses: pnpm/action-setup@v2
|
||||
with:
|
||||
version: 8
|
||||
@@ -84,6 +94,12 @@ jobs:
|
||||
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: latest
|
||||
|
||||
- uses: pnpm/action-setup@v2
|
||||
with:
|
||||
version: 8
|
||||
@@ -114,6 +130,12 @@ jobs:
|
||||
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: latest
|
||||
|
||||
- uses: pnpm/action-setup@v2
|
||||
with:
|
||||
version: 8
|
||||
|
||||
@@ -26,6 +26,11 @@ jobs:
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Setup bun
|
||||
uses: oven-sh/setup-bun@v1
|
||||
with:
|
||||
bun-version: latest
|
||||
|
||||
- name: Install
|
||||
uses: ./.github/composite-actions/install
|
||||
|
||||
|
||||
@@ -67,6 +67,11 @@ jobs:
|
||||
repository: ${{ fromJson(steps.get_pull_request_ref.outputs.data).head.repo.full_name }}
|
||||
ref: ${{ fromJson(steps.get_pull_request_ref.outputs.data).head.ref }}
|
||||
|
||||
- name: Setup bun
|
||||
uses: oven-sh/setup-bun@v1
|
||||
with:
|
||||
bun-version: latest
|
||||
|
||||
- name: Install
|
||||
uses: ./.github/composite-actions/install
|
||||
|
||||
|
||||
@@ -26,6 +26,11 @@ jobs:
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Setup bun
|
||||
uses: oven-sh/setup-bun@v1
|
||||
with:
|
||||
bun-version: latest
|
||||
|
||||
- name: Install
|
||||
uses: ./.github/composite-actions/install
|
||||
|
||||
|
||||
@@ -1,5 +1,49 @@
|
||||
# @thirdweb-dev/auth
|
||||
|
||||
## 4.1.10
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`6832b19f`](https://github.com/thirdweb-dev/js/commit/6832b19fc5eedc7c17e69940a361840de0a84881), [`7abb36a7`](https://github.com/thirdweb-dev/js/commit/7abb36a7ec39766dd7da03015ccef401ef7a7863), [`1c4cbedb`](https://github.com/thirdweb-dev/js/commit/1c4cbedb6a3c9f9014ffbf83c02b998768958d96)]:
|
||||
- @thirdweb-dev/wallets@2.1.7
|
||||
|
||||
## 4.1.9
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`ab2dfd4f`](https://github.com/thirdweb-dev/js/commit/ab2dfd4f5cf4256fa62d76f84ca804992afab1e4)]:
|
||||
- @thirdweb-dev/wallets@2.1.6
|
||||
|
||||
## 4.1.8
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`69d68f5a`](https://github.com/thirdweb-dev/js/commit/69d68f5a25877bf5ea694719d2cf4ca8388f3091)]:
|
||||
- @thirdweb-dev/wallets@2.1.5
|
||||
|
||||
## 4.1.7
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`9f993dcc`](https://github.com/thirdweb-dev/js/commit/9f993dcc1e60cc087850b8fb9ce09524073ce0b5)]:
|
||||
- @thirdweb-dev/wallets@2.1.4
|
||||
|
||||
## 4.1.6
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`6fcdec7c`](https://github.com/thirdweb-dev/js/commit/6fcdec7c12e4a3c0d10f3a67771e19cfad5c8ab5), [`42c74368`](https://github.com/thirdweb-dev/js/commit/42c743682739de77c264c11cc1692ed752f929a6), [`480ed721`](https://github.com/thirdweb-dev/js/commit/480ed721d1c736049fa8b6ee4cbdbdf3cce18abd), [`16e9e8b6`](https://github.com/thirdweb-dev/js/commit/16e9e8b64d7d1a97a5b32fc855479e992b7ed3a8), [`b1190914`](https://github.com/thirdweb-dev/js/commit/b1190914a97a9c4d9019c4ce8ee49ad345aed18c)]:
|
||||
- @thirdweb-dev/wallets@2.1.3
|
||||
|
||||
## 4.1.5
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#1927](https://github.com/thirdweb-dev/js/pull/1927) [`05e52114`](https://github.com/thirdweb-dev/js/commit/05e52114bf4f0ee352f393ed20115a904a18c310) Thanks [@alecananian](https://github.com/alecananian)! - Update Fastify login route response to match Express/Next
|
||||
|
||||
- Updated dependencies [[`3f3a484a`](https://github.com/thirdweb-dev/js/commit/3f3a484a3aa6e9f784e4d44458461bac0d3d4c6b), [`a81a5285`](https://github.com/thirdweb-dev/js/commit/a81a5285b7ef4ddf47fd2779ab80ebbef4bd9e0e), [`30ea9c6b`](https://github.com/thirdweb-dev/js/commit/30ea9c6bf74b483a98592a1d8d64589b7f1b22a3), [`97fdbc8f`](https://github.com/thirdweb-dev/js/commit/97fdbc8f6443dcd08a7610e4437bd4c9d6b0e8c8)]:
|
||||
- @thirdweb-dev/wallets@2.1.2
|
||||
|
||||
## 4.1.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@thirdweb-dev/auth",
|
||||
"version": "4.1.4",
|
||||
"version": "4.1.10",
|
||||
"main": "dist/thirdweb-dev-auth.cjs.js",
|
||||
"module": "dist/thirdweb-dev-auth.esm.js",
|
||||
"browser": {
|
||||
@@ -58,7 +58,7 @@
|
||||
"scripts": {
|
||||
"build": "preconstruct build",
|
||||
"format": "prettier --write 'src/**/*'",
|
||||
"lint": "eslint src/",
|
||||
"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 30000 --parallel './test/**/*.test.ts'",
|
||||
|
||||
@@ -22,7 +22,9 @@ export const loginHandler = (
|
||||
schema: {
|
||||
body: LoginPayloadBodySchema,
|
||||
response: {
|
||||
200: z.any(),
|
||||
200: z.object({
|
||||
token: z.string(),
|
||||
}),
|
||||
},
|
||||
},
|
||||
handler: async (req, res) => {
|
||||
@@ -104,7 +106,8 @@ export const loginHandler = (
|
||||
},
|
||||
);
|
||||
|
||||
return res.status(200).send({ success: true });
|
||||
// Send token in body and as cookie for frontend and backend use cases
|
||||
return res.status(200).send({ token });
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
@@ -3,24 +3,13 @@
|
||||
"version": "0.1.58",
|
||||
"main": "dist/thirdweb-dev-chains.cjs.js",
|
||||
"module": "dist/thirdweb-dev-chains.esm.js",
|
||||
"browser": {
|
||||
"./dist/thirdweb-dev-chains.esm.js": "./dist/thirdweb-dev-chains.browser.esm.js"
|
||||
},
|
||||
"exports": {
|
||||
".": {
|
||||
"module": {
|
||||
"browser": "./dist/thirdweb-dev-chains.browser.esm.js",
|
||||
"default": "./dist/thirdweb-dev-chains.esm.js"
|
||||
},
|
||||
"module": "./dist/thirdweb-dev-chains.esm.js",
|
||||
"default": "./dist/thirdweb-dev-chains.cjs.js"
|
||||
},
|
||||
"./package.json": "./package.json"
|
||||
},
|
||||
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/chains",
|
||||
"license": "Apache-2.0",
|
||||
"bugs": {
|
||||
"url": "https://github.com/thirdweb-dev/js/issues"
|
||||
},
|
||||
"author": "thirdweb eng <[email protected]>",
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.22.9",
|
||||
@@ -29,11 +18,9 @@
|
||||
"@babel/runtime": "^7.22.6",
|
||||
"@preconstruct/cli": "2.7.0",
|
||||
"@thirdweb-dev/tsconfig": "workspace:*",
|
||||
"@types/jest": "^29.5.3",
|
||||
"axios": "^1.4.0",
|
||||
"deepmerge": "^4.3.1",
|
||||
"eslint-config-thirdweb": "workspace:*",
|
||||
"jest": "^29.6.2",
|
||||
"plop": "^3.1.2",
|
||||
"typescript": "^5.1.6"
|
||||
},
|
||||
@@ -41,11 +28,7 @@
|
||||
"entrypoints": [
|
||||
"index.ts"
|
||||
],
|
||||
"exports": {
|
||||
"envConditions": [
|
||||
"browser"
|
||||
]
|
||||
}
|
||||
"exports": true
|
||||
},
|
||||
"sideEffects": false,
|
||||
"scripts": {
|
||||
@@ -56,7 +39,7 @@
|
||||
"plop": "plop",
|
||||
"add-chain": "plop add-chain",
|
||||
"override-chain": "plop override-chain",
|
||||
"test": "jest"
|
||||
"test": "bun test"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
|
||||
@@ -1,5 +1,62 @@
|
||||
# thirdweb
|
||||
|
||||
## 0.13.18
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`6832b19f`](https://github.com/thirdweb-dev/js/commit/6832b19fc5eedc7c17e69940a361840de0a84881), [`7abb36a7`](https://github.com/thirdweb-dev/js/commit/7abb36a7ec39766dd7da03015ccef401ef7a7863), [`1c4cbedb`](https://github.com/thirdweb-dev/js/commit/1c4cbedb6a3c9f9014ffbf83c02b998768958d96), [`e43beec3`](https://github.com/thirdweb-dev/js/commit/e43beec36a569211b6fe708107aa7dc04bff08ec)]:
|
||||
- @thirdweb-dev/wallets@2.1.7
|
||||
- @thirdweb-dev/sdk@4.0.15
|
||||
- @thirdweb-dev/auth@4.1.10
|
||||
|
||||
## 0.13.17
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`ab2dfd4f`](https://github.com/thirdweb-dev/js/commit/ab2dfd4f5cf4256fa62d76f84ca804992afab1e4), [`ab2dfd4f`](https://github.com/thirdweb-dev/js/commit/ab2dfd4f5cf4256fa62d76f84ca804992afab1e4)]:
|
||||
- @thirdweb-dev/sdk@4.0.14
|
||||
- @thirdweb-dev/wallets@2.1.6
|
||||
- @thirdweb-dev/storage@2.0.5
|
||||
- @thirdweb-dev/auth@4.1.9
|
||||
|
||||
## 0.13.16
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`69d68f5a`](https://github.com/thirdweb-dev/js/commit/69d68f5a25877bf5ea694719d2cf4ca8388f3091)]:
|
||||
- @thirdweb-dev/wallets@2.1.5
|
||||
- @thirdweb-dev/auth@4.1.8
|
||||
|
||||
## 0.13.15
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`9f993dcc`](https://github.com/thirdweb-dev/js/commit/9f993dcc1e60cc087850b8fb9ce09524073ce0b5)]:
|
||||
- @thirdweb-dev/wallets@2.1.4
|
||||
- @thirdweb-dev/auth@4.1.7
|
||||
|
||||
## 0.13.14
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`23ab897e`](https://github.com/thirdweb-dev/js/commit/23ab897e329cdd5b316fbe554ea0f64add91f2b4), [`a3f3e160`](https://github.com/thirdweb-dev/js/commit/a3f3e160e07328655a4f0332f41f4edd210a1a8a), [`6fcdec7c`](https://github.com/thirdweb-dev/js/commit/6fcdec7c12e4a3c0d10f3a67771e19cfad5c8ab5), [`42c74368`](https://github.com/thirdweb-dev/js/commit/42c743682739de77c264c11cc1692ed752f929a6), [`6fcdec7c`](https://github.com/thirdweb-dev/js/commit/6fcdec7c12e4a3c0d10f3a67771e19cfad5c8ab5), [`480ed721`](https://github.com/thirdweb-dev/js/commit/480ed721d1c736049fa8b6ee4cbdbdf3cce18abd), [`16e9e8b6`](https://github.com/thirdweb-dev/js/commit/16e9e8b64d7d1a97a5b32fc855479e992b7ed3a8), [`b1190914`](https://github.com/thirdweb-dev/js/commit/b1190914a97a9c4d9019c4ce8ee49ad345aed18c)]:
|
||||
- @thirdweb-dev/sdk@4.0.13
|
||||
- @thirdweb-dev/storage@2.0.4
|
||||
- @thirdweb-dev/wallets@2.1.3
|
||||
- @thirdweb-dev/auth@4.1.6
|
||||
|
||||
## 0.13.13
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#1918](https://github.com/thirdweb-dev/js/pull/1918) [`95c9d56e`](https://github.com/thirdweb-dev/js/commit/95c9d56ea47ef57113679196efe8f9114c6fbb21) Thanks [@saminacodes](https://github.com/saminacodes)! - Fix url redirect for pre-built deploy command
|
||||
|
||||
- Updated dependencies [[`3f3a484a`](https://github.com/thirdweb-dev/js/commit/3f3a484a3aa6e9f784e4d44458461bac0d3d4c6b), [`05e52114`](https://github.com/thirdweb-dev/js/commit/05e52114bf4f0ee352f393ed20115a904a18c310), [`a81a5285`](https://github.com/thirdweb-dev/js/commit/a81a5285b7ef4ddf47fd2779ab80ebbef4bd9e0e), [`30ea9c6b`](https://github.com/thirdweb-dev/js/commit/30ea9c6bf74b483a98592a1d8d64589b7f1b22a3), [`97fdbc8f`](https://github.com/thirdweb-dev/js/commit/97fdbc8f6443dcd08a7610e4437bd4c9d6b0e8c8), [`3f3a484a`](https://github.com/thirdweb-dev/js/commit/3f3a484a3aa6e9f784e4d44458461bac0d3d4c6b)]:
|
||||
- @thirdweb-dev/wallets@2.1.2
|
||||
- @thirdweb-dev/auth@4.1.5
|
||||
- @thirdweb-dev/storage@2.0.3
|
||||
- @thirdweb-dev/sdk@4.0.12
|
||||
|
||||
## 0.13.12
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "thirdweb",
|
||||
"main": "dist/cli/index.js",
|
||||
"version": "0.13.12",
|
||||
"version": "0.13.18",
|
||||
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/cli",
|
||||
"author": "thirdweb eng <[email protected]>",
|
||||
"license": "Apache-2.0",
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { LocalWallet } from "@thirdweb-dev/wallets";
|
||||
import assert from "assert";
|
||||
import chalk from "chalk";
|
||||
import fs from "fs";
|
||||
@@ -30,7 +29,7 @@ type ConfigPaths = {
|
||||
credsConfigPath: string;
|
||||
cliWalletPath: string;
|
||||
tokenPath: string;
|
||||
}
|
||||
};
|
||||
|
||||
export async function loginUser(
|
||||
configPaths: ConfigPaths,
|
||||
@@ -56,12 +55,21 @@ export async function loginUser(
|
||||
}
|
||||
}
|
||||
|
||||
export async function logoutUser(credsConfigPath: string, tokenPath: string, cliWalletPath: string) {
|
||||
export async function logoutUser(
|
||||
credsConfigPath: string,
|
||||
tokenPath: string,
|
||||
cliWalletPath: string,
|
||||
) {
|
||||
try {
|
||||
ora("Logging out...").start();
|
||||
const dirExists = fs.existsSync(credsConfigPath) && fs.existsSync(tokenPath) && fs.existsSync(cliWalletPath);
|
||||
const dirExists =
|
||||
fs.existsSync(credsConfigPath) &&
|
||||
fs.existsSync(tokenPath) &&
|
||||
fs.existsSync(cliWalletPath);
|
||||
if (!dirExists) {
|
||||
ora().warn(chalk.yellow("You are already logged out, did you mean to login?"));
|
||||
ora().warn(
|
||||
chalk.yellow("You are already logged out, did you mean to login?"),
|
||||
);
|
||||
return;
|
||||
}
|
||||
fs.unlinkSync(credsConfigPath);
|
||||
@@ -89,7 +97,9 @@ export const authenticateUser = async (
|
||||
props: LoginProps = defaultLoginProps,
|
||||
) => {
|
||||
const { credsConfigPath, cliWalletPath, tokenPath } = props.configPaths;
|
||||
const waitForDashboard = spinner("Waiting for a response from the dashboard").clear();
|
||||
const waitForDashboard = spinner(
|
||||
"Waiting for a response from the dashboard",
|
||||
).clear();
|
||||
|
||||
// Get or generate a localwallet.
|
||||
const wallet = await getOrGenerateLocalWallet(credsConfigPath, cliWalletPath);
|
||||
@@ -112,10 +122,16 @@ export const authenticateUser = async (
|
||||
let loginTimeoutHandle: NodeJS.Timeout;
|
||||
const timerPromise = new Promise<void>((resolve, reject) => {
|
||||
loginTimeoutHandle = setTimeout(() => {
|
||||
logger.error("Login session timed out, server didn't receive a response in 5 minutes. Please try again.");
|
||||
logger.error(
|
||||
"Login session timed out, server didn't receive a response in 5 minutes. Please try again.",
|
||||
);
|
||||
server.close();
|
||||
clearTimeout(loginTimeoutHandle);
|
||||
reject(new Error("Login session timed out, server didn't receive a response in 5 minutes. Please try again."));
|
||||
reject(
|
||||
new Error(
|
||||
"Login session timed out, server didn't receive a response in 5 minutes. Please try again.",
|
||||
),
|
||||
);
|
||||
}, 300000);
|
||||
});
|
||||
|
||||
@@ -129,12 +145,15 @@ export const authenticateUser = async (
|
||||
}
|
||||
});
|
||||
}
|
||||
res.setHeader('Access-Control-Allow-Credentials', 'true');
|
||||
res.setHeader('Access-Control-Allow-Origin', "https://thirdweb.com");
|
||||
res.setHeader('Access-Control-Allow-Methods', 'POST');
|
||||
res.setHeader("Access-Control-Allow-Credentials", "true");
|
||||
res.setHeader("Access-Control-Allow-Origin", "https://thirdweb.com");
|
||||
res.setHeader("Access-Control-Allow-Methods", "POST");
|
||||
|
||||
if (req.method === 'OPTIONS') {
|
||||
res.setHeader('Access-Control-Allow-Headers', 'content-type, baggage, sentry-trace');
|
||||
if (req.method === "OPTIONS") {
|
||||
res.setHeader(
|
||||
"Access-Control-Allow-Headers",
|
||||
"content-type, baggage, sentry-trace",
|
||||
);
|
||||
res.writeHead(200);
|
||||
res.end();
|
||||
return;
|
||||
@@ -148,12 +167,18 @@ export const authenticateUser = async (
|
||||
res.writeHead(500, "Unable to authenticate with the dashboard!");
|
||||
res.end("Unable to authenticate with the dashboard!", () => {
|
||||
finish(new Error("Unable to authenticate with the dashboard!"));
|
||||
})
|
||||
reject(chalk.red("Something went wrong! Unable to authenticate with the dashboard."));
|
||||
});
|
||||
reject(
|
||||
chalk.red(
|
||||
"Something went wrong! Unable to authenticate with the dashboard.",
|
||||
),
|
||||
);
|
||||
waitForDashboard.stop();
|
||||
}
|
||||
if (query.token) {
|
||||
const token = Array.isArray(query.token) ? query.token[0] : query.token;
|
||||
const token = Array.isArray(query.token)
|
||||
? query.token[0]
|
||||
: query.token;
|
||||
const theirState = Array.isArray(query.state)
|
||||
? query.state[0]
|
||||
: query.state;
|
||||
@@ -171,13 +196,18 @@ export const authenticateUser = async (
|
||||
} else {
|
||||
// Save the token to the config file.
|
||||
// eslint-disable-next-line no-unused-expressions
|
||||
fs.writeFileSync(tokenPath, token), {
|
||||
encoding: "utf8",
|
||||
mode: 0o600,
|
||||
};
|
||||
fs.writeFileSync(tokenPath, token),
|
||||
{
|
||||
encoding: "utf8",
|
||||
mode: 0o600,
|
||||
};
|
||||
res.end(() => {
|
||||
waitForDashboard.clear();
|
||||
console.log(chalk.green(`Successfully linked your account to this device`));
|
||||
console.log(
|
||||
chalk.green(
|
||||
`Successfully linked your account to this device`,
|
||||
),
|
||||
);
|
||||
finish();
|
||||
});
|
||||
logger.info(chalk.green(`\nSuccessfully logged in.`));
|
||||
@@ -197,15 +227,21 @@ export const authenticateUser = async (
|
||||
|
||||
server.listen(8976);
|
||||
});
|
||||
console.log(`Automatically attempting to open a link to authenticate with our dashboard...\n`);
|
||||
console.log(
|
||||
`Automatically attempting to open a link to authenticate with our dashboard...\n`,
|
||||
);
|
||||
waitForDashboard.start();
|
||||
// Adding this timeout since it feels weird for the browser to open before the spinner.
|
||||
setTimeout(async () => {
|
||||
await open(urlToOpen);
|
||||
}, 2000);
|
||||
|
||||
console.log(chalk.yellow(`If the browser doesn't open, please use this link to authenticate:\n`));
|
||||
console.log(chalk.yellow(urlToOpen + '\n'));
|
||||
console.log(
|
||||
chalk.yellow(
|
||||
`If the browser doesn't open, please use this link to authenticate:\n`,
|
||||
),
|
||||
);
|
||||
console.log(chalk.yellow(urlToOpen + "\n"));
|
||||
|
||||
return Promise.race([timerPromise, loginPromise]);
|
||||
};
|
||||
@@ -229,9 +265,13 @@ async function getOrCreatePassword(configCredsPath: string): Promise<string> {
|
||||
}
|
||||
}
|
||||
|
||||
async function getOrGenerateLocalWallet(configCredsPath: string, cliWalletPath: string) {
|
||||
async function getOrGenerateLocalWallet(
|
||||
configCredsPath: string,
|
||||
cliWalletPath: string,
|
||||
) {
|
||||
// Get or prompt for password.
|
||||
const password = await getOrCreatePassword(configCredsPath);
|
||||
const { LocalWallet } = await import("@thirdweb-dev/wallets");
|
||||
const wallet = new LocalWallet();
|
||||
const foundWallet = fs.existsSync(cliWalletPath);
|
||||
|
||||
@@ -265,9 +305,13 @@ async function getOrGenerateLocalWallet(configCredsPath: string, cliWalletPath:
|
||||
});
|
||||
|
||||
// write password
|
||||
fs.writeFileSync(configCredsPath, JSON.stringify({
|
||||
password: password,
|
||||
}), "utf8");
|
||||
fs.writeFileSync(
|
||||
configCredsPath,
|
||||
JSON.stringify({
|
||||
password: password,
|
||||
}),
|
||||
"utf8",
|
||||
);
|
||||
|
||||
return wallet;
|
||||
}
|
||||
@@ -280,14 +324,13 @@ export const validateKey = async (apiSecretKey: string) => {
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"x-secret-key": apiSecretKey,
|
||||
}
|
||||
})
|
||||
},
|
||||
});
|
||||
|
||||
if (response.status !== 200) {
|
||||
throw new Error("Unauthorized key");
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
throw new Error(chalk.red("Unauthorized key"));
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import got from "got/dist/source";
|
||||
import got from "got";
|
||||
|
||||
export const getStartOrDev = async (name: string) => {
|
||||
try {
|
||||
|
||||
@@ -30,7 +30,7 @@ export default function generateDashboardUrl(
|
||||
const foundMapping = mapping[name as keyof typeof mapping];
|
||||
|
||||
return foundMapping
|
||||
? `https://thirdweb.com/dashboard/${foundMapping}`
|
||||
? `https://thirdweb.com/thirdweb.eth/${foundMapping}`
|
||||
: undefined;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,4 @@
|
||||
{
|
||||
"main": "dist/thirdweb-dev-contracts-js-factories-TWFactory__factory.cjs.js",
|
||||
"module": "dist/thirdweb-dev-contracts-js-factories-TWFactory__factory.esm.js",
|
||||
"browser": {
|
||||
"./dist/thirdweb-dev-contracts-js-factories-TWFactory__factory.cjs.js": "./dist/thirdweb-dev-contracts-js-factories-TWFactory__factory.browser.cjs.js",
|
||||
"./dist/thirdweb-dev-contracts-js-factories-TWFactory__factory.esm.js": "./dist/thirdweb-dev-contracts-js-factories-TWFactory__factory.browser.esm.js"
|
||||
}
|
||||
"module": "dist/thirdweb-dev-contracts-js-factories-TWFactory__factory.esm.js"
|
||||
}
|
||||
|
||||
@@ -1,8 +1,4 @@
|
||||
{
|
||||
"main": "dist/thirdweb-dev-contracts-js-factories-TWFee__factory.cjs.js",
|
||||
"module": "dist/thirdweb-dev-contracts-js-factories-TWFee__factory.esm.js",
|
||||
"browser": {
|
||||
"./dist/thirdweb-dev-contracts-js-factories-TWFee__factory.cjs.js": "./dist/thirdweb-dev-contracts-js-factories-TWFee__factory.browser.cjs.js",
|
||||
"./dist/thirdweb-dev-contracts-js-factories-TWFee__factory.esm.js": "./dist/thirdweb-dev-contracts-js-factories-TWFee__factory.browser.esm.js"
|
||||
}
|
||||
"module": "dist/thirdweb-dev-contracts-js-factories-TWFee__factory.esm.js"
|
||||
}
|
||||
|
||||
@@ -1,8 +1,4 @@
|
||||
{
|
||||
"main": "dist/thirdweb-dev-contracts-js-factories-TWMinimalFactory__factory.cjs.js",
|
||||
"module": "dist/thirdweb-dev-contracts-js-factories-TWMinimalFactory__factory.esm.js",
|
||||
"browser": {
|
||||
"./dist/thirdweb-dev-contracts-js-factories-TWMinimalFactory__factory.cjs.js": "./dist/thirdweb-dev-contracts-js-factories-TWMinimalFactory__factory.browser.cjs.js",
|
||||
"./dist/thirdweb-dev-contracts-js-factories-TWMinimalFactory__factory.esm.js": "./dist/thirdweb-dev-contracts-js-factories-TWMinimalFactory__factory.browser.esm.js"
|
||||
}
|
||||
"module": "dist/thirdweb-dev-contracts-js-factories-TWMinimalFactory__factory.esm.js"
|
||||
}
|
||||
|
||||
@@ -1,8 +1,4 @@
|
||||
{
|
||||
"main": "dist/thirdweb-dev-contracts-js-factories-TWMultichainRegistryLogic__factory.cjs.js",
|
||||
"module": "dist/thirdweb-dev-contracts-js-factories-TWMultichainRegistryLogic__factory.esm.js",
|
||||
"browser": {
|
||||
"./dist/thirdweb-dev-contracts-js-factories-TWMultichainRegistryLogic__factory.cjs.js": "./dist/thirdweb-dev-contracts-js-factories-TWMultichainRegistryLogic__factory.browser.cjs.js",
|
||||
"./dist/thirdweb-dev-contracts-js-factories-TWMultichainRegistryLogic__factory.esm.js": "./dist/thirdweb-dev-contracts-js-factories-TWMultichainRegistryLogic__factory.browser.esm.js"
|
||||
}
|
||||
"module": "dist/thirdweb-dev-contracts-js-factories-TWMultichainRegistryLogic__factory.esm.js"
|
||||
}
|
||||
|
||||
@@ -1,8 +1,4 @@
|
||||
{
|
||||
"main": "dist/thirdweb-dev-contracts-js-factories-TWMultichainRegistryRouter__factory.cjs.js",
|
||||
"module": "dist/thirdweb-dev-contracts-js-factories-TWMultichainRegistryRouter__factory.esm.js",
|
||||
"browser": {
|
||||
"./dist/thirdweb-dev-contracts-js-factories-TWMultichainRegistryRouter__factory.cjs.js": "./dist/thirdweb-dev-contracts-js-factories-TWMultichainRegistryRouter__factory.browser.cjs.js",
|
||||
"./dist/thirdweb-dev-contracts-js-factories-TWMultichainRegistryRouter__factory.esm.js": "./dist/thirdweb-dev-contracts-js-factories-TWMultichainRegistryRouter__factory.browser.esm.js"
|
||||
}
|
||||
"module": "dist/thirdweb-dev-contracts-js-factories-TWMultichainRegistryRouter__factory.esm.js"
|
||||
}
|
||||
|
||||
@@ -1,8 +1,4 @@
|
||||
{
|
||||
"main": "dist/thirdweb-dev-contracts-js-factories-TWMultichainRegistryStorage__factory.cjs.js",
|
||||
"module": "dist/thirdweb-dev-contracts-js-factories-TWMultichainRegistryStorage__factory.esm.js",
|
||||
"browser": {
|
||||
"./dist/thirdweb-dev-contracts-js-factories-TWMultichainRegistryStorage__factory.cjs.js": "./dist/thirdweb-dev-contracts-js-factories-TWMultichainRegistryStorage__factory.browser.cjs.js",
|
||||
"./dist/thirdweb-dev-contracts-js-factories-TWMultichainRegistryStorage__factory.esm.js": "./dist/thirdweb-dev-contracts-js-factories-TWMultichainRegistryStorage__factory.browser.esm.js"
|
||||
}
|
||||
"module": "dist/thirdweb-dev-contracts-js-factories-TWMultichainRegistryStorage__factory.esm.js"
|
||||
}
|
||||
|
||||
@@ -1,8 +1,4 @@
|
||||
{
|
||||
"main": "dist/thirdweb-dev-contracts-js-factories-TWMultichainRegistry__factory.cjs.js",
|
||||
"module": "dist/thirdweb-dev-contracts-js-factories-TWMultichainRegistry__factory.esm.js",
|
||||
"browser": {
|
||||
"./dist/thirdweb-dev-contracts-js-factories-TWMultichainRegistry__factory.cjs.js": "./dist/thirdweb-dev-contracts-js-factories-TWMultichainRegistry__factory.browser.cjs.js",
|
||||
"./dist/thirdweb-dev-contracts-js-factories-TWMultichainRegistry__factory.esm.js": "./dist/thirdweb-dev-contracts-js-factories-TWMultichainRegistry__factory.browser.esm.js"
|
||||
}
|
||||
"module": "dist/thirdweb-dev-contracts-js-factories-TWMultichainRegistry__factory.esm.js"
|
||||
}
|
||||
|
||||
@@ -1,8 +1,4 @@
|
||||
{
|
||||
"main": "dist/thirdweb-dev-contracts-js-factories-TWProxy__factory.cjs.js",
|
||||
"module": "dist/thirdweb-dev-contracts-js-factories-TWProxy__factory.esm.js",
|
||||
"browser": {
|
||||
"./dist/thirdweb-dev-contracts-js-factories-TWProxy__factory.cjs.js": "./dist/thirdweb-dev-contracts-js-factories-TWProxy__factory.browser.cjs.js",
|
||||
"./dist/thirdweb-dev-contracts-js-factories-TWProxy__factory.esm.js": "./dist/thirdweb-dev-contracts-js-factories-TWProxy__factory.browser.esm.js"
|
||||
}
|
||||
"module": "dist/thirdweb-dev-contracts-js-factories-TWProxy__factory.esm.js"
|
||||
}
|
||||
|
||||
@@ -1,8 +1,4 @@
|
||||
{
|
||||
"main": "dist/thirdweb-dev-contracts-js-factories-TWRegistry__factory.cjs.js",
|
||||
"module": "dist/thirdweb-dev-contracts-js-factories-TWRegistry__factory.esm.js",
|
||||
"browser": {
|
||||
"./dist/thirdweb-dev-contracts-js-factories-TWRegistry__factory.cjs.js": "./dist/thirdweb-dev-contracts-js-factories-TWRegistry__factory.browser.cjs.js",
|
||||
"./dist/thirdweb-dev-contracts-js-factories-TWRegistry__factory.esm.js": "./dist/thirdweb-dev-contracts-js-factories-TWRegistry__factory.browser.esm.js"
|
||||
}
|
||||
"module": "dist/thirdweb-dev-contracts-js-factories-TWRegistry__factory.esm.js"
|
||||
}
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
{
|
||||
"main": "dist/thirdweb-dev-contracts-js-factories-TWRouter__factory.cjs.js",
|
||||
"module": "dist/thirdweb-dev-contracts-js-factories-TWRouter__factory.esm.js",
|
||||
"browser": {
|
||||
"./dist/thirdweb-dev-contracts-js-factories-TWRouter__factory.cjs.js": "./dist/thirdweb-dev-contracts-js-factories-TWRouter__factory.browser.cjs.js",
|
||||
"./dist/thirdweb-dev-contracts-js-factories-TWRouter__factory.esm.js": "./dist/thirdweb-dev-contracts-js-factories-TWRouter__factory.browser.esm.js"
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,4 @@
|
||||
{
|
||||
"main": "dist/thirdweb-dev-contracts-js-factories-TWStatelessFactory__factory.cjs.js",
|
||||
"module": "dist/thirdweb-dev-contracts-js-factories-TWStatelessFactory__factory.esm.js",
|
||||
"browser": {
|
||||
"./dist/thirdweb-dev-contracts-js-factories-TWStatelessFactory__factory.cjs.js": "./dist/thirdweb-dev-contracts-js-factories-TWStatelessFactory__factory.browser.cjs.js",
|
||||
"./dist/thirdweb-dev-contracts-js-factories-TWStatelessFactory__factory.esm.js": "./dist/thirdweb-dev-contracts-js-factories-TWStatelessFactory__factory.browser.esm.js"
|
||||
}
|
||||
"module": "dist/thirdweb-dev-contracts-js-factories-TWStatelessFactory__factory.esm.js"
|
||||
}
|
||||
|
||||
@@ -3,9 +3,422 @@
|
||||
"version": "1.3.16",
|
||||
"main": "dist/thirdweb-dev-contracts-js.cjs.js",
|
||||
"module": "dist/thirdweb-dev-contracts-js.esm.js",
|
||||
"browser": {
|
||||
"./dist/thirdweb-dev-contracts-js.cjs.js": "./dist/thirdweb-dev-contracts-js.browser.cjs.js",
|
||||
"./dist/thirdweb-dev-contracts-js.esm.js": "./dist/thirdweb-dev-contracts-js.browser.esm.js"
|
||||
"exports": {
|
||||
".": {
|
||||
"module": "./dist/thirdweb-dev-contracts-js.esm.js",
|
||||
"default": "./dist/thirdweb-dev-contracts-js.cjs.js"
|
||||
},
|
||||
"./factories/TWFee__factory": {
|
||||
"module": "./factories/TWFee__factory/dist/thirdweb-dev-contracts-js-factories-TWFee__factory.esm.js",
|
||||
"default": "./factories/TWFee__factory/dist/thirdweb-dev-contracts-js-factories-TWFee__factory.cjs.js"
|
||||
},
|
||||
"./factories/TWProxy__factory": {
|
||||
"module": "./factories/TWProxy__factory/dist/thirdweb-dev-contracts-js-factories-TWProxy__factory.esm.js",
|
||||
"default": "./factories/TWProxy__factory/dist/thirdweb-dev-contracts-js-factories-TWProxy__factory.cjs.js"
|
||||
},
|
||||
"./factories/TWFactory__factory": {
|
||||
"module": "./factories/TWFactory__factory/dist/thirdweb-dev-contracts-js-factories-TWFactory__factory.esm.js",
|
||||
"default": "./factories/TWFactory__factory/dist/thirdweb-dev-contracts-js-factories-TWFactory__factory.cjs.js"
|
||||
},
|
||||
"./factories/TWRegistry__factory": {
|
||||
"module": "./factories/TWRegistry__factory/dist/thirdweb-dev-contracts-js-factories-TWRegistry__factory.esm.js",
|
||||
"default": "./factories/TWRegistry__factory/dist/thirdweb-dev-contracts-js-factories-TWRegistry__factory.cjs.js"
|
||||
},
|
||||
"./factories/TWMinimalFactory__factory": {
|
||||
"module": "./factories/TWMinimalFactory__factory/dist/thirdweb-dev-contracts-js-factories-TWMinimalFactory__factory.esm.js",
|
||||
"default": "./factories/TWMinimalFactory__factory/dist/thirdweb-dev-contracts-js-factories-TWMinimalFactory__factory.cjs.js"
|
||||
},
|
||||
"./factories/TWStatelessFactory__factory": {
|
||||
"module": "./factories/TWStatelessFactory__factory/dist/thirdweb-dev-contracts-js-factories-TWStatelessFactory__factory.esm.js",
|
||||
"default": "./factories/TWStatelessFactory__factory/dist/thirdweb-dev-contracts-js-factories-TWStatelessFactory__factory.cjs.js"
|
||||
},
|
||||
"./factories/TWMultichainRegistry__factory": {
|
||||
"module": "./factories/TWMultichainRegistry__factory/dist/thirdweb-dev-contracts-js-factories-TWMultichainRegistry__factory.esm.js",
|
||||
"default": "./factories/TWMultichainRegistry__factory/dist/thirdweb-dev-contracts-js-factories-TWMultichainRegistry__factory.cjs.js"
|
||||
},
|
||||
"./factories/TWMultichainRegistryLogic__factory": {
|
||||
"module": "./factories/TWMultichainRegistryLogic__factory/dist/thirdweb-dev-contracts-js-factories-TWMultichainRegistryLogic__factory.esm.js",
|
||||
"default": "./factories/TWMultichainRegistryLogic__factory/dist/thirdweb-dev-contracts-js-factories-TWMultichainRegistryLogic__factory.cjs.js"
|
||||
},
|
||||
"./factories/TWMultichainRegistryRouter__factory": {
|
||||
"module": "./factories/TWMultichainRegistryRouter__factory/dist/thirdweb-dev-contracts-js-factories-TWMultichainRegistryRouter__factory.esm.js",
|
||||
"default": "./factories/TWMultichainRegistryRouter__factory/dist/thirdweb-dev-contracts-js-factories-TWMultichainRegistryRouter__factory.cjs.js"
|
||||
},
|
||||
"./factories/TWMultichainRegistryStorage__factory": {
|
||||
"module": "./factories/TWMultichainRegistryStorage__factory/dist/thirdweb-dev-contracts-js-factories-TWMultichainRegistryStorage__factory.esm.js",
|
||||
"default": "./factories/TWMultichainRegistryStorage__factory/dist/thirdweb-dev-contracts-js-factories-TWMultichainRegistryStorage__factory.cjs.js"
|
||||
},
|
||||
"./package.json": "./package.json",
|
||||
"./dist/abis/SharedMetadataBatch.json": "./dist/abis/SharedMetadataBatch.json",
|
||||
"./dist/abis/Staking721Upgradeable.json": "./dist/abis/Staking721Upgradeable.json",
|
||||
"./dist/abis/Staking1155.json": "./dist/abis/Staking1155.json",
|
||||
"./dist/abis/IPluginMap.json": "./dist/abis/IPluginMap.json",
|
||||
"./dist/abis/SignatureAction.json": "./dist/abis/SignatureAction.json",
|
||||
"./dist/abis/IDirectListings.json": "./dist/abis/IDirectListings.json",
|
||||
"./dist/abis/Multiwrap.json": "./dist/abis/Multiwrap.json",
|
||||
"./dist/abis/ERC20Votes.json": "./dist/abis/ERC20Votes.json",
|
||||
"./dist/abis/ITWFee.json": "./dist/abis/ITWFee.json",
|
||||
"./dist/abis/Permissions.json": "./dist/abis/Permissions.json",
|
||||
"./dist/abis/Pack.json": "./dist/abis/Pack.json",
|
||||
"./dist/abis/RulesEngineExtension.json": "./dist/abis/RulesEngineExtension.json",
|
||||
"./dist/abis/PrimarySale.json": "./dist/abis/PrimarySale.json",
|
||||
"./dist/abis/EntryPoint.json": "./dist/abis/EntryPoint.json",
|
||||
"./dist/abis/DropSinglePhase1155.json": "./dist/abis/DropSinglePhase1155.json",
|
||||
"./dist/abis/IAirdropERC721.json": "./dist/abis/IAirdropERC721.json",
|
||||
"./dist/abis/TWFee.json": "./dist/abis/TWFee.json",
|
||||
"./dist/abis/IContractPublisher.json": "./dist/abis/IContractPublisher.json",
|
||||
"./dist/abis/IOwnable.json": "./dist/abis/IOwnable.json",
|
||||
"./dist/abis/SignatureDrop_V4.json": "./dist/abis/SignatureDrop_V4.json",
|
||||
"./dist/abis/ITokenERC20.json": "./dist/abis/ITokenERC20.json",
|
||||
"./dist/abis/OperatorFilterToggle.json": "./dist/abis/OperatorFilterToggle.json",
|
||||
"./dist/abis/EnumerableSet.json": "./dist/abis/EnumerableSet.json",
|
||||
"./dist/abis/ERC721A__IERC721ReceiverUpgradeable.json": "./dist/abis/ERC721A__IERC721ReceiverUpgradeable.json",
|
||||
"./dist/abis/AccountFactory.json": "./dist/abis/AccountFactory.json",
|
||||
"./dist/abis/MerkleProof.json": "./dist/abis/MerkleProof.json",
|
||||
"./dist/abis/SafeCast.json": "./dist/abis/SafeCast.json",
|
||||
"./dist/abis/Staking721.json": "./dist/abis/Staking721.json",
|
||||
"./dist/abis/ERC721A.json": "./dist/abis/ERC721A.json",
|
||||
"./dist/abis/UserOperationLib.json": "./dist/abis/UserOperationLib.json",
|
||||
"./dist/abis/ERC721Multiwrap.json": "./dist/abis/ERC721Multiwrap.json",
|
||||
"./dist/abis/SignatureDrop.json": "./dist/abis/SignatureDrop.json",
|
||||
"./dist/abis/IMintableERC721.json": "./dist/abis/IMintableERC721.json",
|
||||
"./dist/abis/IBurnToClaim.json": "./dist/abis/IBurnToClaim.json",
|
||||
"./dist/abis/AccountPermissions.json": "./dist/abis/AccountPermissions.json",
|
||||
"./dist/abis/IStakeManager.json": "./dist/abis/IStakeManager.json",
|
||||
"./dist/abis/IClaimConditionsSinglePhase.json": "./dist/abis/IClaimConditionsSinglePhase.json",
|
||||
"./dist/abis/PrimarySaleInit.json": "./dist/abis/PrimarySaleInit.json",
|
||||
"./dist/abis/IERC2771Context.json": "./dist/abis/IERC2771Context.json",
|
||||
"./dist/abis/IAccountCore.json": "./dist/abis/IAccountCore.json",
|
||||
"./dist/abis/IERC165.json": "./dist/abis/IERC165.json",
|
||||
"./dist/abis/BurnToClaimDrop721Logic.json": "./dist/abis/BurnToClaimDrop721Logic.json",
|
||||
"./dist/abis/ERC721DelayedReveal.json": "./dist/abis/ERC721DelayedReveal.json",
|
||||
"./dist/abis/IClaimCondition_V1.json": "./dist/abis/IClaimCondition_V1.json",
|
||||
"./dist/abis/IERC1155.json": "./dist/abis/IERC1155.json",
|
||||
"./dist/abis/IStaking1155.json": "./dist/abis/IStaking1155.json",
|
||||
"./dist/abis/Math.json": "./dist/abis/Math.json",
|
||||
"./dist/abis/IRoyaltyEngineV1.json": "./dist/abis/IRoyaltyEngineV1.json",
|
||||
"./dist/abis/DelayedRevealStorage.json": "./dist/abis/DelayedRevealStorage.json",
|
||||
"./dist/abis/ISignatureMintERC1155.json": "./dist/abis/ISignatureMintERC1155.json",
|
||||
"./dist/abis/IPack.json": "./dist/abis/IPack.json",
|
||||
"./dist/abis/SenderCreator.json": "./dist/abis/SenderCreator.json",
|
||||
"./dist/abis/IMintableERC1155.json": "./dist/abis/IMintableERC1155.json",
|
||||
"./dist/abis/ReentrancyGuardLogic.json": "./dist/abis/ReentrancyGuardLogic.json",
|
||||
"./dist/abis/IERC1155Receiver.json": "./dist/abis/IERC1155Receiver.json",
|
||||
"./dist/abis/IERC4906.json": "./dist/abis/IERC4906.json",
|
||||
"./dist/abis/ERC2771ContextLogic.json": "./dist/abis/ERC2771ContextLogic.json",
|
||||
"./dist/abis/TWBitMaps.json": "./dist/abis/TWBitMaps.json",
|
||||
"./dist/abis/IERC2981.json": "./dist/abis/IERC2981.json",
|
||||
"./dist/abis/ILazyMintWithTier.json": "./dist/abis/ILazyMintWithTier.json",
|
||||
"./dist/abis/ERC721SignatureMint.json": "./dist/abis/ERC721SignatureMint.json",
|
||||
"./dist/abis/LazyMintWithTier_V1.json": "./dist/abis/LazyMintWithTier_V1.json",
|
||||
"./dist/abis/EvolvingNFTLogic.json": "./dist/abis/EvolvingNFTLogic.json",
|
||||
"./dist/abis/IPrimarySale.json": "./dist/abis/IPrimarySale.json",
|
||||
"./dist/abis/IRouterState.json": "./dist/abis/IRouterState.json",
|
||||
"./dist/abis/NFTMetadataRenderer.json": "./dist/abis/NFTMetadataRenderer.json",
|
||||
"./dist/abis/SignatureActionUpgradeable.json": "./dist/abis/SignatureActionUpgradeable.json",
|
||||
"./dist/abis/IPermissions.json": "./dist/abis/IPermissions.json",
|
||||
"./dist/abis/EnglishAuctionsLogic.json": "./dist/abis/EnglishAuctionsLogic.json",
|
||||
"./dist/abis/IMulticall.json": "./dist/abis/IMulticall.json",
|
||||
"./dist/abis/Exec.json": "./dist/abis/Exec.json",
|
||||
"./dist/abis/IAccountFactory.json": "./dist/abis/IAccountFactory.json",
|
||||
"./dist/abis/ERC721LazyMint.json": "./dist/abis/ERC721LazyMint.json",
|
||||
"./dist/abis/IDropSinglePhase_V1.json": "./dist/abis/IDropSinglePhase_V1.json",
|
||||
"./dist/abis/ERC721AQueryableInit.json": "./dist/abis/ERC721AQueryableInit.json",
|
||||
"./dist/abis/ERC721AQueryableUpgradeable.json": "./dist/abis/ERC721AQueryableUpgradeable.json",
|
||||
"./dist/abis/DropERC721.json": "./dist/abis/DropERC721.json",
|
||||
"./dist/abis/AirdropERC721.json": "./dist/abis/AirdropERC721.json",
|
||||
"./dist/abis/IDropSinglePhase.json": "./dist/abis/IDropSinglePhase.json",
|
||||
"./dist/abis/zora_IERC721Drop.json": "./dist/abis/zora_IERC721Drop.json",
|
||||
"./dist/abis/TWStringSet.json": "./dist/abis/TWStringSet.json",
|
||||
"./dist/abis/InitStorage.json": "./dist/abis/InitStorage.json",
|
||||
"./dist/abis/IDropSinglePhase1155.json": "./dist/abis/IDropSinglePhase1155.json",
|
||||
"./dist/abis/AccountCore.json": "./dist/abis/AccountCore.json",
|
||||
"./dist/abis/TWStorageSlot.json": "./dist/abis/TWStorageSlot.json",
|
||||
"./dist/abis/TWMinimalFactory.json": "./dist/abis/TWMinimalFactory.json",
|
||||
"./dist/abis/TWRegistry.json": "./dist/abis/TWRegistry.json",
|
||||
"./dist/abis/OpenEditionERC721.json": "./dist/abis/OpenEditionERC721.json",
|
||||
"./dist/abis/ERC2771Context.json": "./dist/abis/ERC2771Context.json",
|
||||
"./dist/abis/IERC721Receiver.json": "./dist/abis/IERC721Receiver.json",
|
||||
"./dist/abis/ISharedMetadataBatch.json": "./dist/abis/ISharedMetadataBatch.json",
|
||||
"./dist/abis/ERC1155Holder.json": "./dist/abis/ERC1155Holder.json",
|
||||
"./dist/abis/BurnToClaim.json": "./dist/abis/BurnToClaim.json",
|
||||
"./dist/abis/Forwarder.json": "./dist/abis/Forwarder.json",
|
||||
"./dist/abis/ERC2771ContextInit.json": "./dist/abis/ERC2771ContextInit.json",
|
||||
"./dist/abis/SharedMetadataBatchStorage.json": "./dist/abis/SharedMetadataBatchStorage.json",
|
||||
"./dist/abis/PlatformFeeLogic.json": "./dist/abis/PlatformFeeLogic.json",
|
||||
"./dist/abis/Royalty.json": "./dist/abis/Royalty.json",
|
||||
"./dist/abis/IMintableERC20.json": "./dist/abis/IMintableERC20.json",
|
||||
"./dist/abis/PermissionsLogic.json": "./dist/abis/PermissionsLogic.json",
|
||||
"./dist/abis/Staking20Base.json": "./dist/abis/Staking20Base.json",
|
||||
"./dist/abis/IContext.json": "./dist/abis/IContext.json",
|
||||
"./dist/abis/Staking20Upgradeable.json": "./dist/abis/Staking20Upgradeable.json",
|
||||
"./dist/abis/Proxy.json": "./dist/abis/Proxy.json",
|
||||
"./dist/abis/ERC1967Proxy.json": "./dist/abis/ERC1967Proxy.json",
|
||||
"./dist/abis/IRoyaltyPayments.json": "./dist/abis/IRoyaltyPayments.json",
|
||||
"./dist/abis/BaseRouter.json": "./dist/abis/BaseRouter.json",
|
||||
"./dist/abis/TWAddress.json": "./dist/abis/TWAddress.json",
|
||||
"./dist/abis/EvolvingNFT.json": "./dist/abis/EvolvingNFT.json",
|
||||
"./dist/abis/ContractMetadata.json": "./dist/abis/ContractMetadata.json",
|
||||
"./dist/abis/IOffers.json": "./dist/abis/IOffers.json",
|
||||
"./dist/abis/Staking1155Base.json": "./dist/abis/Staking1155Base.json",
|
||||
"./dist/abis/PermissionsEnumerableImpl.json": "./dist/abis/PermissionsEnumerableImpl.json",
|
||||
"./dist/abis/TWFactory.json": "./dist/abis/TWFactory.json",
|
||||
"./dist/abis/IERC6551Account.json": "./dist/abis/IERC6551Account.json",
|
||||
"./dist/abis/ILoyaltyCard.json": "./dist/abis/ILoyaltyCard.json",
|
||||
"./dist/abis/SafeMath.json": "./dist/abis/SafeMath.json",
|
||||
"./dist/abis/MarketplaceV3.json": "./dist/abis/MarketplaceV3.json",
|
||||
"./dist/abis/ReentrancyGuardInit.json": "./dist/abis/ReentrancyGuardInit.json",
|
||||
"./dist/abis/DropERC721_V3.json": "./dist/abis/DropERC721_V3.json",
|
||||
"./dist/abis/PermissionOverrideCoreRouter.json": "./dist/abis/PermissionOverrideCoreRouter.json",
|
||||
"./dist/abis/OperatorFilterer.json": "./dist/abis/OperatorFilterer.json",
|
||||
"./dist/abis/IDelayedReveal.json": "./dist/abis/IDelayedReveal.json",
|
||||
"./dist/abis/TokenERC721.json": "./dist/abis/TokenERC721.json",
|
||||
"./dist/abis/PlatformFeeStorage.json": "./dist/abis/PlatformFeeStorage.json",
|
||||
"./dist/abis/ERC6551AccountLib.json": "./dist/abis/ERC6551AccountLib.json",
|
||||
"./dist/abis/ITWRegistry.json": "./dist/abis/ITWRegistry.json",
|
||||
"./dist/abis/DropERC20.json": "./dist/abis/DropERC20.json",
|
||||
"./dist/abis/TWStatelessFactory.json": "./dist/abis/TWStatelessFactory.json",
|
||||
"./dist/abis/IDropERC721.json": "./dist/abis/IDropERC721.json",
|
||||
"./dist/abis/IMarketplace.json": "./dist/abis/IMarketplace.json",
|
||||
"./dist/abis/IThirdwebContract.json": "./dist/abis/IThirdwebContract.json",
|
||||
"./dist/abis/LazyMint_V1.json": "./dist/abis/LazyMint_V1.json",
|
||||
"./dist/abis/PrimarySaleStorage.json": "./dist/abis/PrimarySaleStorage.json",
|
||||
"./dist/abis/IClaimConditionMultiPhase.json": "./dist/abis/IClaimConditionMultiPhase.json",
|
||||
"./dist/abis/ReentrancyGuardStorage.json": "./dist/abis/ReentrancyGuardStorage.json",
|
||||
"./dist/abis/LoyaltyPoints.json": "./dist/abis/LoyaltyPoints.json",
|
||||
"./dist/abis/IBurnableERC20.json": "./dist/abis/IBurnableERC20.json",
|
||||
"./dist/abis/Initializable.json": "./dist/abis/Initializable.json",
|
||||
"./dist/abis/IAirdropERC20Claimable.json": "./dist/abis/IAirdropERC20Claimable.json",
|
||||
"./dist/abis/AirdropERC1155.json": "./dist/abis/AirdropERC1155.json",
|
||||
"./dist/abis/ERC721AUpgradeable.json": "./dist/abis/ERC721AUpgradeable.json",
|
||||
"./dist/abis/RouterStorage.json": "./dist/abis/RouterStorage.json",
|
||||
"./dist/abis/ILoyaltyPoints.json": "./dist/abis/ILoyaltyPoints.json",
|
||||
"./dist/abis/TokenERC20.json": "./dist/abis/TokenERC20.json",
|
||||
"./dist/abis/AirdropERC20Claimable.json": "./dist/abis/AirdropERC20Claimable.json",
|
||||
"./dist/abis/SignatureMintERC20.json": "./dist/abis/SignatureMintERC20.json",
|
||||
"./dist/abis/Staking1155Upgradeable.json": "./dist/abis/Staking1155Upgradeable.json",
|
||||
"./dist/abis/IEntryPoint.json": "./dist/abis/IEntryPoint.json",
|
||||
"./dist/abis/EnglishAuctionsStorage.json": "./dist/abis/EnglishAuctionsStorage.json",
|
||||
"./dist/abis/IDropERC721_V3.json": "./dist/abis/IDropERC721_V3.json",
|
||||
"./dist/abis/EIP712.json": "./dist/abis/EIP712.json",
|
||||
"./dist/abis/DelayedReveal.json": "./dist/abis/DelayedReveal.json",
|
||||
"./dist/abis/IAccount.json": "./dist/abis/IAccount.json",
|
||||
"./dist/abis/OffersStorage.json": "./dist/abis/OffersStorage.json",
|
||||
"./dist/abis/IClaimableERC721.json": "./dist/abis/IClaimableERC721.json",
|
||||
"./dist/abis/IBurnableERC1155.json": "./dist/abis/IBurnableERC1155.json",
|
||||
"./dist/abis/ContractMetadataInit.json": "./dist/abis/ContractMetadataInit.json",
|
||||
"./dist/abis/ERC165.json": "./dist/abis/ERC165.json",
|
||||
"./dist/abis/RouterImmutable.json": "./dist/abis/RouterImmutable.json",
|
||||
"./dist/abis/IStaking20.json": "./dist/abis/IStaking20.json",
|
||||
"./dist/abis/IERC721Supply.json": "./dist/abis/IERC721Supply.json",
|
||||
"./dist/abis/ITokenERC721.json": "./dist/abis/ITokenERC721.json",
|
||||
"./dist/abis/ERC2771ContextUpgradeable.json": "./dist/abis/ERC2771ContextUpgradeable.json",
|
||||
"./dist/abis/IDropClaimCondition_V2.json": "./dist/abis/IDropClaimCondition_V2.json",
|
||||
"./dist/abis/Upgradeable.json": "./dist/abis/Upgradeable.json",
|
||||
"./dist/abis/DynamicAccount.json": "./dist/abis/DynamicAccount.json",
|
||||
"./dist/abis/LoyaltyCard.json": "./dist/abis/LoyaltyCard.json",
|
||||
"./dist/abis/IClaimCondition.json": "./dist/abis/IClaimCondition.json",
|
||||
"./dist/abis/IStaking721.json": "./dist/abis/IStaking721.json",
|
||||
"./dist/abis/IEnglishAuctions.json": "./dist/abis/IEnglishAuctions.json",
|
||||
"./dist/abis/TWMultichainRegistry.json": "./dist/abis/TWMultichainRegistry.json",
|
||||
"./dist/abis/StakeManager.json": "./dist/abis/StakeManager.json",
|
||||
"./dist/abis/BurnToClaimDropERC721.json": "./dist/abis/BurnToClaimDropERC721.json",
|
||||
"./dist/abis/ERC20SignatureMint.json": "./dist/abis/ERC20SignatureMint.json",
|
||||
"./dist/abis/ISignatureMintERC721_V1.json": "./dist/abis/ISignatureMintERC721_V1.json",
|
||||
"./dist/abis/ERC20DropVote.json": "./dist/abis/ERC20DropVote.json",
|
||||
"./dist/abis/ERC721AStorage.json": "./dist/abis/ERC721AStorage.json",
|
||||
"./dist/abis/BaseAccountFactory.json": "./dist/abis/BaseAccountFactory.json",
|
||||
"./dist/abis/ERC1155PresetUpgradeable.json": "./dist/abis/ERC1155PresetUpgradeable.json",
|
||||
"./dist/abis/PlatformFeeImpl.json": "./dist/abis/PlatformFeeImpl.json",
|
||||
"./dist/abis/SafeERC20.json": "./dist/abis/SafeERC20.json",
|
||||
"./dist/abis/IAirdropERC1155.json": "./dist/abis/IAirdropERC1155.json",
|
||||
"./dist/abis/OffersLogic.json": "./dist/abis/OffersLogic.json",
|
||||
"./dist/abis/Marketplace.json": "./dist/abis/Marketplace.json",
|
||||
"./dist/abis/TWStrings.json": "./dist/abis/TWStrings.json",
|
||||
"./dist/abis/DirectListingsStorage.json": "./dist/abis/DirectListingsStorage.json",
|
||||
"./dist/abis/TieredDrop.json": "./dist/abis/TieredDrop.json",
|
||||
"./dist/abis/ERC1155Receiver.json": "./dist/abis/ERC1155Receiver.json",
|
||||
"./dist/abis/AccountCoreStorage.json": "./dist/abis/AccountCoreStorage.json",
|
||||
"./dist/abis/Drop1155.json": "./dist/abis/Drop1155.json",
|
||||
"./dist/abis/IDelayedRevealDeprecated.json": "./dist/abis/IDelayedRevealDeprecated.json",
|
||||
"./dist/abis/DropERC1155.json": "./dist/abis/DropERC1155.json",
|
||||
"./dist/abis/PermissionsInit.json": "./dist/abis/PermissionsInit.json",
|
||||
"./dist/abis/Account.json": "./dist/abis/Account.json",
|
||||
"./dist/abis/ERC20Base.json": "./dist/abis/ERC20Base.json",
|
||||
"./dist/abis/INFTStake.json": "./dist/abis/INFTStake.json",
|
||||
"./dist/abis/BytesLib.json": "./dist/abis/BytesLib.json",
|
||||
"./dist/abis/LazyMintStorage.json": "./dist/abis/LazyMintStorage.json",
|
||||
"./dist/abis/IDropERC20_V2.json": "./dist/abis/IDropERC20_V2.json",
|
||||
"./dist/abis/ERC2771ContextUpgradeableStorage.json": "./dist/abis/ERC2771ContextUpgradeableStorage.json",
|
||||
"./dist/abis/IClaimableERC1155.json": "./dist/abis/IClaimableERC1155.json",
|
||||
"./dist/abis/ILazyMint.json": "./dist/abis/ILazyMint.json",
|
||||
"./dist/abis/IOperatorFilterToggle.json": "./dist/abis/IOperatorFilterToggle.json",
|
||||
"./dist/abis/IERC1155Metadata.json": "./dist/abis/IERC1155Metadata.json",
|
||||
"./dist/abis/IBeacon.json": "./dist/abis/IBeacon.json",
|
||||
"./dist/abis/BaseAccount.json": "./dist/abis/BaseAccount.json",
|
||||
"./dist/abis/ITokenBundle.json": "./dist/abis/ITokenBundle.json",
|
||||
"./dist/abis/ReentrancyGuard.json": "./dist/abis/ReentrancyGuard.json",
|
||||
"./dist/abis/AirdropERC20.json": "./dist/abis/AirdropERC20.json",
|
||||
"./dist/abis/ERC2771ContextStorage.json": "./dist/abis/ERC2771ContextStorage.json",
|
||||
"./dist/abis/SignatureMintERC1155Upgradeable.json": "./dist/abis/SignatureMintERC1155Upgradeable.json",
|
||||
"./dist/abis/IPackVRFDirect.json": "./dist/abis/IPackVRFDirect.json",
|
||||
"./dist/abis/MetaTx.json": "./dist/abis/MetaTx.json",
|
||||
"./dist/abis/IDropERC20.json": "./dist/abis/IDropERC20.json",
|
||||
"./dist/abis/ERC721A__Initializable.json": "./dist/abis/ERC721A__Initializable.json",
|
||||
"./dist/abis/TokenBoundAccount.json": "./dist/abis/TokenBoundAccount.json",
|
||||
"./dist/abis/ISharedMetadata.json": "./dist/abis/ISharedMetadata.json",
|
||||
"./dist/abis/IERC721Metadata.json": "./dist/abis/IERC721Metadata.json",
|
||||
"./dist/abis/DropSinglePhase_V1.json": "./dist/abis/DropSinglePhase_V1.json",
|
||||
"./dist/abis/PermissionsEnumerable.json": "./dist/abis/PermissionsEnumerable.json",
|
||||
"./dist/abis/IAccountFactoryCore.json": "./dist/abis/IAccountFactoryCore.json",
|
||||
"./dist/abis/TokenStake.json": "./dist/abis/TokenStake.json",
|
||||
"./dist/abis/AppURI.json": "./dist/abis/AppURI.json",
|
||||
"./dist/abis/AirdropERC721Claimable.json": "./dist/abis/AirdropERC721Claimable.json",
|
||||
"./dist/abis/DropSinglePhase.json": "./dist/abis/DropSinglePhase.json",
|
||||
"./dist/abis/OperatorFiltererUpgradeable.json": "./dist/abis/OperatorFiltererUpgradeable.json",
|
||||
"./dist/abis/IAirdropERC721Claimable.json": "./dist/abis/IAirdropERC721Claimable.json",
|
||||
"./dist/abis/IOperatorFilterRegistry.json": "./dist/abis/IOperatorFilterRegistry.json",
|
||||
"./dist/abis/IContractFactory.json": "./dist/abis/IContractFactory.json",
|
||||
"./dist/abis/ERC20Drop.json": "./dist/abis/ERC20Drop.json",
|
||||
"./dist/abis/LazyMintWithTier.json": "./dist/abis/LazyMintWithTier.json",
|
||||
"./dist/abis/ManagedAccount.json": "./dist/abis/ManagedAccount.json",
|
||||
"./dist/abis/EIP712ChainlessDomain.json": "./dist/abis/EIP712ChainlessDomain.json",
|
||||
"./dist/abis/IDropERC1155.json": "./dist/abis/IDropERC1155.json",
|
||||
"./dist/abis/IPermissionsEnumerable.json": "./dist/abis/IPermissionsEnumerable.json",
|
||||
"./dist/abis/SignatureMintERC1155.json": "./dist/abis/SignatureMintERC1155.json",
|
||||
"./dist/abis/ForwarderConsumer.json": "./dist/abis/ForwarderConsumer.json",
|
||||
"./dist/abis/IAggregator.json": "./dist/abis/IAggregator.json",
|
||||
"./dist/abis/PermissionsEnumerableStorage.json": "./dist/abis/PermissionsEnumerableStorage.json",
|
||||
"./dist/abis/IEditionStake.json": "./dist/abis/IEditionStake.json",
|
||||
"./dist/abis/ERC1155Drop.json": "./dist/abis/ERC1155Drop.json",
|
||||
"./dist/abis/DropStorage.json": "./dist/abis/DropStorage.json",
|
||||
"./dist/abis/PackVRFDirect.json": "./dist/abis/PackVRFDirect.json",
|
||||
"./dist/abis/AccountExtension.json": "./dist/abis/AccountExtension.json",
|
||||
"./dist/abis/SoulboundERC721A.json": "./dist/abis/SoulboundERC721A.json",
|
||||
"./dist/abis/ISignatureAction.json": "./dist/abis/ISignatureAction.json",
|
||||
"./dist/abis/ERC721AInit.json": "./dist/abis/ERC721AInit.json",
|
||||
"./dist/abis/IRoyalty.json": "./dist/abis/IRoyalty.json",
|
||||
"./dist/abis/IAccountPermissions_V1.json": "./dist/abis/IAccountPermissions_V1.json",
|
||||
"./dist/abis/CoreRouter.json": "./dist/abis/CoreRouter.json",
|
||||
"./dist/abis/ContractMetadataLogic.json": "./dist/abis/ContractMetadataLogic.json",
|
||||
"./dist/abis/ERC1155LazyMint.json": "./dist/abis/ERC1155LazyMint.json",
|
||||
"./dist/abis/TokenERC1155.json": "./dist/abis/TokenERC1155.json",
|
||||
"./dist/abis/IAccountPermissions.json": "./dist/abis/IAccountPermissions.json",
|
||||
"./dist/abis/Staking20.json": "./dist/abis/Staking20.json",
|
||||
"./dist/abis/RoyaltyStorage.json": "./dist/abis/RoyaltyStorage.json",
|
||||
"./dist/abis/ERC6551BytecodeLib.json": "./dist/abis/ERC6551BytecodeLib.json",
|
||||
"./dist/abis/TWMultichainRegistryStorage.json": "./dist/abis/TWMultichainRegistryStorage.json",
|
||||
"./dist/abis/ForwarderEOAOnly.json": "./dist/abis/ForwarderEOAOnly.json",
|
||||
"./dist/abis/TokenStore.json": "./dist/abis/TokenStore.json",
|
||||
"./dist/abis/TokenBundle.json": "./dist/abis/TokenBundle.json",
|
||||
"./dist/abis/IPaymaster.json": "./dist/abis/IPaymaster.json",
|
||||
"./dist/abis/RoyaltyInit.json": "./dist/abis/RoyaltyInit.json",
|
||||
"./dist/abis/SharedMetadata.json": "./dist/abis/SharedMetadata.json",
|
||||
"./dist/abis/ManagedAccountFactory.json": "./dist/abis/ManagedAccountFactory.json",
|
||||
"./dist/abis/IFeeTierPlacementExtension.json": "./dist/abis/IFeeTierPlacementExtension.json",
|
||||
"./dist/abis/TokenCallbackHandler.json": "./dist/abis/TokenCallbackHandler.json",
|
||||
"./dist/abis/PaymentSplitterUpgradeable.json": "./dist/abis/PaymentSplitterUpgradeable.json",
|
||||
"./dist/abis/ERC1155Base.json": "./dist/abis/ERC1155Base.json",
|
||||
"./dist/abis/ForwarderChainlessDomain.json": "./dist/abis/ForwarderChainlessDomain.json",
|
||||
"./dist/abis/ERC1967Upgrade.json": "./dist/abis/ERC1967Upgrade.json",
|
||||
"./dist/abis/ExtensionManager.json": "./dist/abis/ExtensionManager.json",
|
||||
"./dist/abis/NonceManager.json": "./dist/abis/NonceManager.json",
|
||||
"./dist/abis/IAirdropERC1155Claimable.json": "./dist/abis/IAirdropERC1155Claimable.json",
|
||||
"./dist/abis/IVotes.json": "./dist/abis/IVotes.json",
|
||||
"./dist/abis/PluginMap.json": "./dist/abis/PluginMap.json",
|
||||
"./dist/abis/PermissionsEnumerableLogic.json": "./dist/abis/PermissionsEnumerableLogic.json",
|
||||
"./dist/abis/IContractMetadata.json": "./dist/abis/IContractMetadata.json",
|
||||
"./dist/abis/IDropClaimCondition.json": "./dist/abis/IDropClaimCondition.json",
|
||||
"./dist/abis/SignatureMintERC20Upgradeable.json": "./dist/abis/SignatureMintERC20Upgradeable.json",
|
||||
"./dist/abis/DynamicAccountFactory.json": "./dist/abis/DynamicAccountFactory.json",
|
||||
"./dist/abis/OwnableInit.json": "./dist/abis/OwnableInit.json",
|
||||
"./dist/abis/VoteERC20.json": "./dist/abis/VoteERC20.json",
|
||||
"./dist/abis/IMultiwrap.json": "./dist/abis/IMultiwrap.json",
|
||||
"./dist/abis/BurnToClaimDrop721Storage.json": "./dist/abis/BurnToClaimDrop721Storage.json",
|
||||
"./dist/abis/IBurnableERC721.json": "./dist/abis/IBurnableERC721.json",
|
||||
"./dist/abis/AccountPermissionsStorage.json": "./dist/abis/AccountPermissionsStorage.json",
|
||||
"./dist/abis/FeeType.json": "./dist/abis/FeeType.json",
|
||||
"./dist/abis/Split.json": "./dist/abis/Split.json",
|
||||
"./dist/abis/IERC20Metadata.json": "./dist/abis/IERC20Metadata.json",
|
||||
"./dist/abis/EditionStake.json": "./dist/abis/EditionStake.json",
|
||||
"./dist/abis/ERC721A__InitializableStorage.json": "./dist/abis/ERC721A__InitializableStorage.json",
|
||||
"./dist/abis/TWMultichainRegistryLogic.json": "./dist/abis/TWMultichainRegistryLogic.json",
|
||||
"./dist/abis/IERC1155Enumerable.json": "./dist/abis/IERC1155Enumerable.json",
|
||||
"./dist/abis/SignatureMintERC721.json": "./dist/abis/SignatureMintERC721.json",
|
||||
"./dist/abis/IERC1155Supply.json": "./dist/abis/IERC1155Supply.json",
|
||||
"./dist/abis/AirdropERC1155Claimable.json": "./dist/abis/AirdropERC1155Claimable.json",
|
||||
"./dist/abis/ISignatureMintERC20.json": "./dist/abis/ISignatureMintERC20.json",
|
||||
"./dist/abis/ERC1155.json": "./dist/abis/ERC1155.json",
|
||||
"./dist/abis/IRulesEngine.json": "./dist/abis/IRulesEngine.json",
|
||||
"./dist/abis/Router.json": "./dist/abis/Router.json",
|
||||
"./dist/abis/IPlatformFee.json": "./dist/abis/IPlatformFee.json",
|
||||
"./dist/abis/Base64.json": "./dist/abis/Base64.json",
|
||||
"./dist/abis/ProxyForUpgradeable.json": "./dist/abis/ProxyForUpgradeable.json",
|
||||
"./dist/abis/Helpers.json": "./dist/abis/Helpers.json",
|
||||
"./dist/abis/VRFV2WrapperConsumerBase.json": "./dist/abis/VRFV2WrapperConsumerBase.json",
|
||||
"./dist/abis/ITokenERC1155.json": "./dist/abis/ITokenERC1155.json",
|
||||
"./dist/abis/BatchMintMetadata.json": "./dist/abis/BatchMintMetadata.json",
|
||||
"./dist/abis/NFTMetadata.json": "./dist/abis/NFTMetadata.json",
|
||||
"./dist/abis/ERC20Permit.json": "./dist/abis/ERC20Permit.json",
|
||||
"./dist/abis/IAppURI.json": "./dist/abis/IAppURI.json",
|
||||
"./dist/abis/ERC1155DelayedReveal.json": "./dist/abis/ERC1155DelayedReveal.json",
|
||||
"./dist/abis/BatchMintMetadata_V1.json": "./dist/abis/BatchMintMetadata_V1.json",
|
||||
"./dist/abis/ContractPublisher.json": "./dist/abis/ContractPublisher.json",
|
||||
"./dist/abis/Drop.json": "./dist/abis/Drop.json",
|
||||
"./dist/abis/MockContractPublisher.json": "./dist/abis/MockContractPublisher.json",
|
||||
"./dist/abis/ERC721Holder.json": "./dist/abis/ERC721Holder.json",
|
||||
"./dist/abis/IWETH.json": "./dist/abis/IWETH.json",
|
||||
"./dist/abis/ERC1155SignatureMint.json": "./dist/abis/ERC1155SignatureMint.json",
|
||||
"./dist/abis/TWProxy.json": "./dist/abis/TWProxy.json",
|
||||
"./dist/abis/CurrencyTransferLib.json": "./dist/abis/CurrencyTransferLib.json",
|
||||
"./dist/abis/MinimalForwarderEOAOnly.json": "./dist/abis/MinimalForwarderEOAOnly.json",
|
||||
"./dist/abis/PermissionsEnumerableInit.json": "./dist/abis/PermissionsEnumerableInit.json",
|
||||
"./dist/abis/INonceManager.json": "./dist/abis/INonceManager.json",
|
||||
"./dist/abis/IERC721.json": "./dist/abis/IERC721.json",
|
||||
"./dist/abis/IERC721AQueryableUpgradeable.json": "./dist/abis/IERC721AQueryableUpgradeable.json",
|
||||
"./dist/abis/DropERC1155_V2.json": "./dist/abis/DropERC1155_V2.json",
|
||||
"./dist/abis/PermissionsStorage.json": "./dist/abis/PermissionsStorage.json",
|
||||
"./dist/abis/IDrop1155.json": "./dist/abis/IDrop1155.json",
|
||||
"./dist/abis/IERC721Enumerable.json": "./dist/abis/IERC721Enumerable.json",
|
||||
"./dist/abis/IDropSinglePhase1155_V1.json": "./dist/abis/IDropSinglePhase1155_V1.json",
|
||||
"./dist/abis/ERC1271.json": "./dist/abis/ERC1271.json",
|
||||
"./dist/abis/DropSinglePhase1155_V1.json": "./dist/abis/DropSinglePhase1155_V1.json",
|
||||
"./dist/abis/Ownable.json": "./dist/abis/Ownable.json",
|
||||
"./dist/abis/ERC721Base.json": "./dist/abis/ERC721Base.json",
|
||||
"./dist/abis/OperatorFilterToggleStorage.json": "./dist/abis/OperatorFilterToggleStorage.json",
|
||||
"./dist/abis/NFTStake.json": "./dist/abis/NFTStake.json",
|
||||
"./dist/abis/ContractMetadataStorage.json": "./dist/abis/ContractMetadataStorage.json",
|
||||
"./dist/abis/DropERC20_V2.json": "./dist/abis/DropERC20_V2.json",
|
||||
"./dist/abis/PlatformFee.json": "./dist/abis/PlatformFee.json",
|
||||
"./dist/abis/IERC20.json": "./dist/abis/IERC20.json",
|
||||
"./dist/abis/Staking721Base.json": "./dist/abis/Staking721Base.json",
|
||||
"./dist/abis/RulesEngine.json": "./dist/abis/RulesEngine.json",
|
||||
"./dist/abis/LazyMint.json": "./dist/abis/LazyMint.json",
|
||||
"./dist/abis/BurnToClaimStorage.json": "./dist/abis/BurnToClaimStorage.json",
|
||||
"./dist/abis/Multicall.json": "./dist/abis/Multicall.json",
|
||||
"./dist/abis/PlatformFeeInit.json": "./dist/abis/PlatformFeeInit.json",
|
||||
"./dist/abis/TWMultichainRegistryRouter.json": "./dist/abis/TWMultichainRegistryRouter.json",
|
||||
"./dist/abis/OwnableStorage.json": "./dist/abis/OwnableStorage.json",
|
||||
"./dist/abis/IERC1822Proxiable.json": "./dist/abis/IERC1822Proxiable.json",
|
||||
"./dist/abis/ERC20Vote.json": "./dist/abis/ERC20Vote.json",
|
||||
"./dist/abis/IAirdropERC20.json": "./dist/abis/IAirdropERC20.json",
|
||||
"./dist/abis/DirectListingsLogic.json": "./dist/abis/DirectListingsLogic.json",
|
||||
"./dist/abis/IERC20Permit.json": "./dist/abis/IERC20Permit.json",
|
||||
"./dist/abis/INFTMetadata.json": "./dist/abis/INFTMetadata.json",
|
||||
"./dist/abis/IDrop.json": "./dist/abis/IDrop.json",
|
||||
"./dist/abis/ISignatureMintERC721.json": "./dist/abis/ISignatureMintERC721.json",
|
||||
"./dist/abis/RulesEngineStorage.json": "./dist/abis/RulesEngineStorage.json",
|
||||
"./dist/abis/ERC20SignatureMintVote.json": "./dist/abis/ERC20SignatureMintVote.json",
|
||||
"./dist/abis/BatchMintMetadataStorage.json": "./dist/abis/BatchMintMetadataStorage.json",
|
||||
"./dist/abis/ITokenStake.json": "./dist/abis/ITokenStake.json",
|
||||
"./dist/abis/ITWMultichainRegistry.json": "./dist/abis/ITWMultichainRegistry.json",
|
||||
"./dist/abis/SignatureMintERC721Upgradeable.json": "./dist/abis/SignatureMintERC721Upgradeable.json",
|
||||
"./dist/abis/IERC721A.json": "./dist/abis/IERC721A.json",
|
||||
"./dist/abis/IDropERC1155_V2.json": "./dist/abis/IDropERC1155_V2.json",
|
||||
"./dist/abis/IContractDeployer.json": "./dist/abis/IContractDeployer.json",
|
||||
"./dist/abis/ERC721Drop.json": "./dist/abis/ERC721Drop.json",
|
||||
"./dist/abis/ERC2771ContextUpgradeableLogic.json": "./dist/abis/ERC2771ContextUpgradeableLogic.json",
|
||||
"./dist/abis/ContractMetadataImpl.json": "./dist/abis/ContractMetadataImpl.json"
|
||||
},
|
||||
"license": "Apache-2.0",
|
||||
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/contracts-js",
|
||||
@@ -36,14 +449,17 @@
|
||||
"entrypoints": [
|
||||
"index.ts",
|
||||
"./factories/TW*.ts"
|
||||
]
|
||||
],
|
||||
"exports": {
|
||||
"extra": {}
|
||||
}
|
||||
},
|
||||
"sideEffects": false,
|
||||
"scripts": {
|
||||
"clean": "rm -rf dist/",
|
||||
"typechain": "rm -rf ./src && cp ./external_abis/*.json ./node_modules/@thirdweb-dev/contracts/abi && typechain --target ethers-v5 --out-dir src './node_modules/@thirdweb-dev/contracts/abi/*.json'",
|
||||
"extract-abi": "node ./scripts/extract-abis.mjs",
|
||||
"build": "pnpm typechain && tsc && pnpm preconstruct build && pnpm extract-abi",
|
||||
"extract-abi": "bun ./scripts/extract-abis.ts && bun ./scripts/write-exports.ts",
|
||||
"build": "bun ./scripts/revert-exports.ts && pnpm typechain && tsc && pnpm preconstruct build && pnpm extract-abi",
|
||||
"push": "yalc push"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
import { readFile, writeFile } from "node:fs/promises";
|
||||
|
||||
const pkgJson = JSON.parse(await readFile('./package.json', "utf-8"));
|
||||
|
||||
// for each path add to the `exports` field in `package.json`
|
||||
const pkgExports = pkgJson.exports || {};
|
||||
Object.keys(pkgExports).forEach(key => {
|
||||
if(key.endsWith(".json") && key !== './package.json'){
|
||||
delete pkgExports[key];
|
||||
}
|
||||
})
|
||||
pkgJson.exports = pkgExports;
|
||||
// write the updated `package.json` to disk
|
||||
|
||||
await writeFile('./package.json', JSON.stringify(pkgJson, null, 2), "utf-8");
|
||||
@@ -0,0 +1,28 @@
|
||||
|
||||
import {resolve} from "node:path";
|
||||
import { readdir, readFile, writeFile } from "node:fs/promises";
|
||||
|
||||
|
||||
// enumerate all files in `dist/abis/*.json`
|
||||
async function getPaths() {
|
||||
|
||||
const dir = resolve(__dirname, '../dist/abis');
|
||||
const paths = await readdir(dir);
|
||||
const jsonPaths = paths.filter(p => p.endsWith('.json'));
|
||||
return jsonPaths.map(p => `./dist/abis/${p}`);
|
||||
}
|
||||
|
||||
|
||||
const [paths, pkg] = await Promise.all([getPaths(), readFile('./package.json', "utf-8")]);
|
||||
|
||||
const pkgJson = JSON.parse(pkg);
|
||||
|
||||
// for each path add to the `exports` field in `package.json`
|
||||
const pkgExports = pkgJson.exports || {};
|
||||
for(const path of paths){
|
||||
pkgExports[path] = path;
|
||||
}
|
||||
pkgJson.exports = pkgExports;
|
||||
// write the updated `package.json` to disk
|
||||
|
||||
await writeFile('./package.json', JSON.stringify(pkgJson, null, 2), "utf-8");
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"extends": "@thirdweb-dev/tsconfig/base.json",
|
||||
"extends": "@thirdweb-dev/tsconfig/sdk.json",
|
||||
"include": ["."],
|
||||
"exclude": ["dist", "build", "node_modules"]
|
||||
}
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"presets": [
|
||||
"@babel/preset-typescript",
|
||||
["@babel/preset-env", { "targets": "defaults, not ie 11" }]
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
# folders
|
||||
dist/
|
||||
|
||||
# files
|
||||
@@ -0,0 +1,24 @@
|
||||
module.exports = {
|
||||
root: true,
|
||||
extends: ["thirdweb"],
|
||||
rules: {
|
||||
"no-restricted-globals": [
|
||||
"error",
|
||||
{
|
||||
name: "Buffer",
|
||||
message: "Use Uint8Array instead.",
|
||||
},
|
||||
],
|
||||
"no-restricted-imports": [
|
||||
"error",
|
||||
{
|
||||
name: "buffer",
|
||||
message: "Use Uint8Array instead.",
|
||||
},
|
||||
{
|
||||
name: "node:buffer",
|
||||
message: "Use Uint8Array instead.",
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,7 @@
|
||||
# @thirdweb-dev/crypto
|
||||
|
||||
## 0.2.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- [#1861](https://github.com/thirdweb-dev/js/pull/1861) [`ab2dfd4f`](https://github.com/thirdweb-dev/js/commit/ab2dfd4f5cf4256fa62d76f84ca804992afab1e4) Thanks [@jnsdls](https://github.com/jnsdls)! - initial release
|
||||
@@ -0,0 +1,94 @@
|
||||
<p align="center">
|
||||
<br />
|
||||
<a href="https://thirdweb.com"><img src="https://github.com/thirdweb-dev/js/blob/main/packages/sdk/logo.svg?raw=true" width="200" alt=""/></a>
|
||||
<br />
|
||||
</p>
|
||||
<h1 align="center">thirdweb crypto</h1>
|
||||
<p align="center">
|
||||
<a href="https://www.npmjs.com/package/@thirdweb-dev/crypto"><img src="https://img.shields.io/npm/v/@thirdweb-dev/crypto?color=red&label=npm&logo=npm" alt="npm version"/></a>
|
||||
<a href="https://github.com/thirdweb-dev/js/actions/workflows/build-test-lint.yml"><img alt="Build Status" src="https://github.com/thirdweb-dev/js/actions/workflows/build-test-lint.yml/badge.svg"/></a>
|
||||
<a href="https://discord.gg/thirdweb"><img alt="Join our Discord!" src="https://img.shields.io/discord/834227967404146718.svg?color=7289da&label=discord&logo=discord&style=flat"/></a>
|
||||
|
||||
</p>
|
||||
<p align="center"><strong>Secure, performant and cross-platform cryptography methods commonly used across other thirdweb packages.</strong></p>
|
||||
<br />
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
npm install @thirdweb-dev/crypto
|
||||
```
|
||||
|
||||
## Available methods
|
||||
|
||||
### Encryption
|
||||
|
||||
| method | use case | return type | underlying technology |
|
||||
| -------------------------------------------- | ----------------------------------------------------------------------------------------------------- | ----------------- | --------------------- |
|
||||
| `aesEncrypt(<plaintext>, <password>)` | Encrypts a string/Uint8Array with AES-GCM | `Promise<string>` | `WebCrypto` (AES-GCM) |
|
||||
| `aesDecrypt(<ciphertext>, <password>)` | Decrypts a value encrypted via `aesEncrypt` | `Promise<string>` | `WebCrypto` (AES-GCM) |
|
||||
| `aesDecryptCompat(<ciphertext>, <password>)` | Same as `aesDecrypt` but also supports values encrypted via `crypto-js` (for backwards compatibility) | `Promise<string>` | `WebCrypto` (AES-GCM) |
|
||||
|
||||
### Hashing
|
||||
|
||||
| method | use case | return type | underlying technology |
|
||||
| ----------------------------------- | --------------------------------------------------------------- | --------------------- | --------------------- |
|
||||
| `sha256(<value>)` | Hashes a string/Uint8Array with SHA256 | `Promise<Uint8Array>` | `WebCrypto` |
|
||||
| `sha256Hex(<value>)` | Same as `sha256` but reruns as hex string | `Promise<string>` | `WebCrypto` |
|
||||
| `sha256Sync(<value>)` | Same as `sha256` but synchronous | `Uint8Array` | `@noble/hashes` |
|
||||
| `sha256SyncHex(<value>)` | Same as `sha256Sync` but reruns as hex string | `string` | `@noble/hashes` |
|
||||
| `keccak256Sync(<value>)` | Hashes a string/Uint8Array with Keccak256 | `Uint8Array` | `js-sha3` |
|
||||
| `keccak256SyncHex(<value>)` | Same as `keccak256Sync` but returns as hex string | `string` | `js-sha3` |
|
||||
| `keccak256SyncHexPrefixed(<value>)` | Same as `keccak256Sync` but returns as `0x` prefixed hex string | `0x${string}` | `js-sha3` |
|
||||
|
||||
## Initial Benchmarks
|
||||
|
||||
#### sha256 -> Uint8Array
|
||||
|
||||
```bash
|
||||
┌──────────────────────────────┬─────────┬────────────────────┬────────┬─────────┐
|
||||
│ Task Name │ ops/sec │ Average Time (ns) │ Margin │ Samples │
|
||||
├──────────────────────────────┼─────────┼────────────────────┼────────┼─────────┤
|
||||
│ @thirdweb-dev/crypto (async) │ 112,929 │ 8855.08539999982 │ ±1.37% │ 100000 │
|
||||
│ @thirdweb-dev/crypto (sync) │ 55,004 │ 18180.482820000594 │ ±1.02% │ 100000 │
|
||||
│ crypto-js (sync) │ 19,213 │ 52047.35353999857 │ ±0.25% │ 100000 │
|
||||
└──────────────────────────────┴─────────┴────────────────────┴────────┴─────────┘
|
||||
```
|
||||
|
||||
#### sha256 -> hex
|
||||
|
||||
```bash
|
||||
┌──────────────────────────────┬─────────┬────────────────────┬────────┬─────────┐
|
||||
│ Task Name │ ops/sec │ Average Time (ns) │ Margin │ Samples │
|
||||
├──────────────────────────────┼─────────┼────────────────────┼────────┼─────────┤
|
||||
│ @thirdweb-dev/crypto (async) │ 100,845 │ 9916.125730001713 │ ±1.24% │ 100000 │
|
||||
│ @thirdweb-dev/crypto (sync) │ 53,751 │ 18604.047449997142 │ ±0.92% │ 100000 │
|
||||
│ crypto-js (sync) │ 19,077 │ 52419.03465000334 │ ±0.24% │ 100000 │
|
||||
└──────────────────────────────┴─────────┴────────────────────┴────────┴─────────┘
|
||||
```
|
||||
|
||||
#### keccack256 -> Uint8Array
|
||||
|
||||
```bash
|
||||
┌──────────────────────┬─────────┬────────────────────┬────────┬─────────┐
|
||||
│ Task Name │ ops/sec │ Average Time (ns) │ Margin │ Samples │
|
||||
├──────────────────────┼─────────┼────────────────────┼────────┼─────────┤
|
||||
│ @thirdweb-dev/crypto │ 72,533 │ 13786.719900000808 │ ±0.31% │ 100000 │
|
||||
│ ethers@v5 │ 71,891 │ 13909.94663000107 │ ±0.33% │ 100000 │
|
||||
│ @noble/hashes │ 27,244 │ 36704.73226000136 │ ±0.19% │ 100000 │
|
||||
│ viem │ 27,115 │ 36879.07953999698 │ ±0.26% │ 100000 │
|
||||
└──────────────────────┴─────────┴────────────────────┴────────┴─────────┘
|
||||
```
|
||||
|
||||
#### keccack256 -> hex
|
||||
|
||||
```bash
|
||||
┌──────────────────────┬─────────┬───────────────────┬────────┬─────────┐
|
||||
│ Task Name │ ops/sec │ Average Time (ns) │ Margin │ Samples │
|
||||
├──────────────────────┼─────────┼───────────────────┼────────┼─────────┤
|
||||
│ @thirdweb-dev/crypto │ 42,947 │ 23284.22780000266 │ ±0.23% │ 100000 │
|
||||
│ ethers@5 │ 35,568 │ 28114.98005000045 │ ±0.42% │ 100000 │
|
||||
│ @noble/hashes │ 15,149 │ 66009.80448000187 │ ±0.26% │ 100000 │
|
||||
│ viem │ 15,217 │ 65714.15843999518 │ ±0.25% │ 100000 │
|
||||
└──────────────────────┴─────────┴───────────────────┴────────┴─────────┘
|
||||
```
|
||||
@@ -0,0 +1,44 @@
|
||||
import { Bench } from "tinybench";
|
||||
import { aesDecrypt, aesDecryptCompat, aesEncrypt } from "../src";
|
||||
import { AES, enc } from "crypto-js";
|
||||
// @ts-expect-error - this function actually does exist
|
||||
import { consoleTable } from "js-awe";
|
||||
|
||||
const PLAINTEXT = "my secret text";
|
||||
const PASSWORD = "pw";
|
||||
|
||||
const encrypted = await aesEncrypt(PLAINTEXT, PASSWORD);
|
||||
const encryptedCryptoJs = AES.encrypt(PLAINTEXT, PASSWORD).toString();
|
||||
|
||||
const bench = new Bench({ iterations: 100_000 });
|
||||
|
||||
bench
|
||||
.add("aesDecrypt", async () => {
|
||||
const res = await aesDecrypt(encrypted, PASSWORD);
|
||||
if (res !== PLAINTEXT) {
|
||||
throw new Error("aesDecrypt failed");
|
||||
}
|
||||
})
|
||||
.add("aesDecryptCompat", async () => {
|
||||
const res = await aesDecryptCompat(encrypted, PASSWORD);
|
||||
if (res !== PLAINTEXT) {
|
||||
throw new Error("aesDecryptCompat (compat, modern) failed");
|
||||
}
|
||||
})
|
||||
.add("aesDecryptCompat (crypto-js)", async () => {
|
||||
const res = await aesDecryptCompat(encryptedCryptoJs, PASSWORD);
|
||||
if (res !== PLAINTEXT) {
|
||||
throw new Error("aesDecryptCompat (compat, legacy) failed");
|
||||
}
|
||||
})
|
||||
.add("crypto-js", async () => {
|
||||
const res = AES.decrypt(encryptedCryptoJs, PASSWORD).toString(enc.Utf8);
|
||||
if (res !== PLAINTEXT) {
|
||||
throw new Error("crypto-js failed");
|
||||
}
|
||||
});
|
||||
|
||||
await bench.warmup();
|
||||
await bench.run();
|
||||
|
||||
consoleTable(bench.table());
|
||||
@@ -0,0 +1,23 @@
|
||||
import { Bench } from "tinybench";
|
||||
import { aesEncrypt } from "../src";
|
||||
import { AES } from "crypto-js";
|
||||
// @ts-expect-error - this function actually does exist
|
||||
import { consoleTable } from "js-awe";
|
||||
|
||||
const PLAINTEXT = "my secret text";
|
||||
const PASSWORD = "pw";
|
||||
|
||||
const bench = new Bench({ iterations: 100_000 });
|
||||
|
||||
bench
|
||||
.add("aesEncrypt", async () => {
|
||||
await aesEncrypt(PLAINTEXT, PASSWORD);
|
||||
})
|
||||
.add("crypto-js", () => {
|
||||
AES.encrypt(PLAINTEXT, PASSWORD).toString();
|
||||
});
|
||||
|
||||
await bench.warmup();
|
||||
await bench.run();
|
||||
|
||||
consoleTable(bench.table());
|
||||
@@ -0,0 +1,63 @@
|
||||
import { Bench } from "tinybench";
|
||||
import { keccak256SyncHex } from "../src";
|
||||
import { utils } from "ethers";
|
||||
import {
|
||||
uint8ArrayToString,
|
||||
uint8ArrayToHex,
|
||||
} from "../src/utils/uint8array-extras";
|
||||
import { keccak_256 as noble } from "@noble/hashes/sha3";
|
||||
import { keccak256 as viem } from "viem";
|
||||
// @ts-expect-error - this function actually does exist
|
||||
import { consoleTable } from "js-awe";
|
||||
|
||||
const value = crypto.getRandomValues(new Uint8Array(1000));
|
||||
const stringValue = uint8ArrayToString(value);
|
||||
|
||||
const uint8Bench = new Bench({ iterations: 100_000 });
|
||||
|
||||
uint8Bench
|
||||
.add("@thirdweb-dev/crypto", async () => {
|
||||
keccak256SyncHex(value);
|
||||
})
|
||||
.add("ethers@v5", async () => {
|
||||
utils.keccak256(value);
|
||||
})
|
||||
.add("@noble/hashes", async () => {
|
||||
uint8ArrayToHex(noble(value));
|
||||
})
|
||||
.add("viem", async () => {
|
||||
viem(value);
|
||||
});
|
||||
|
||||
await uint8Bench.warmup();
|
||||
await uint8Bench.run();
|
||||
|
||||
console.log();
|
||||
console.log("keccak256(<Uint8Array>):");
|
||||
consoleTable(uint8Bench.table());
|
||||
console.log();
|
||||
|
||||
const stringBench = new Bench({ iterations: 100_000 });
|
||||
|
||||
stringBench
|
||||
.add("@thirdweb-dev/crypto", async () => {
|
||||
keccak256SyncHex(stringValue);
|
||||
})
|
||||
.add("ethers@5", async () => {
|
||||
// OK because this is benchmark code only
|
||||
// eslint-disable-next-line no-restricted-globals
|
||||
utils.keccak256(Buffer.from(stringValue));
|
||||
})
|
||||
.add("@noble/hashes", async () => {
|
||||
uint8ArrayToHex(noble(stringValue));
|
||||
})
|
||||
.add("viem", async () => {
|
||||
viem(stringValue as `0x${string}`);
|
||||
});
|
||||
|
||||
await stringBench.warmup();
|
||||
await stringBench.run();
|
||||
|
||||
console.log("keccak256(<string>):");
|
||||
consoleTable(stringBench.table());
|
||||
console.log();
|
||||
@@ -0,0 +1,51 @@
|
||||
import Bench from "tinybench";
|
||||
import { sha256, sha256Hex, sha256Sync, sha256HexSync } from "../src";
|
||||
import { SHA256, enc } from "crypto-js";
|
||||
import { uint8ArrayToString } from "../src/utils/uint8array-extras";
|
||||
// @ts-expect-error - this function actually does exist
|
||||
import { consoleTable } from "js-awe";
|
||||
|
||||
const STRING_TO_HASH = uint8ArrayToString(
|
||||
crypto.getRandomValues(new Uint8Array(1000)),
|
||||
);
|
||||
|
||||
const sha256Bench = new Bench({ iterations: 100_000 });
|
||||
|
||||
sha256Bench
|
||||
.add("@thirdweb-dev/crypto (async)", async () => {
|
||||
await sha256(STRING_TO_HASH);
|
||||
})
|
||||
.add("@thirdweb-dev/crypto (sync)", async () => {
|
||||
sha256Sync(STRING_TO_HASH);
|
||||
})
|
||||
.add("crypto-js (sync)", async () => {
|
||||
SHA256(STRING_TO_HASH).toString();
|
||||
});
|
||||
|
||||
await sha256Bench.warmup();
|
||||
await sha256Bench.run();
|
||||
|
||||
console.log();
|
||||
console.log("sha256:");
|
||||
consoleTable(sha256Bench.table());
|
||||
console.log();
|
||||
|
||||
const sha256HexBench = new Bench({ iterations: 100_000 });
|
||||
|
||||
sha256HexBench
|
||||
.add("@thirdweb-dev/crypto (async)", async () => {
|
||||
await sha256Hex(STRING_TO_HASH);
|
||||
})
|
||||
.add("@thirdweb-dev/crypto (sync)", async () => {
|
||||
sha256HexSync(STRING_TO_HASH);
|
||||
})
|
||||
.add("crypto-js (sync)", async () => {
|
||||
SHA256(STRING_TO_HASH).toString(enc.Hex);
|
||||
});
|
||||
|
||||
await sha256HexBench.warmup();
|
||||
await sha256HexBench.run();
|
||||
|
||||
console.log("sha256 -> hex:");
|
||||
consoleTable(sha256HexBench.table());
|
||||
console.log();
|
||||
@@ -0,0 +1,62 @@
|
||||
{
|
||||
"name": "@thirdweb-dev/crypto",
|
||||
"version": "0.2.0",
|
||||
"main": "dist/thirdweb-dev-crypto.cjs.js",
|
||||
"module": "dist/thirdweb-dev-crypto.esm.js",
|
||||
"exports": {
|
||||
".": {
|
||||
"module": "./dist/thirdweb-dev-crypto.esm.js",
|
||||
"default": "./dist/thirdweb-dev-crypto.cjs.js"
|
||||
},
|
||||
"./package.json": "./package.json"
|
||||
},
|
||||
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/utils",
|
||||
"license": "Apache-2.0",
|
||||
"bugs": {
|
||||
"url": "https://github.com/thirdweb-dev/js/issues"
|
||||
},
|
||||
"author": "thirdweb eng <[email protected]>",
|
||||
"files": [
|
||||
"dist/"
|
||||
],
|
||||
"preconstruct": {
|
||||
"entrypoints": [
|
||||
"index.ts"
|
||||
],
|
||||
"exports": true
|
||||
},
|
||||
"sideEffects": false,
|
||||
"dependencies": {
|
||||
"@noble/hashes": "^1.3.2",
|
||||
"js-sha3": "^0.9.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@preconstruct/cli": "2.7.0",
|
||||
"@thirdweb-dev/tsconfig": "workspace:*",
|
||||
"@types/crypto-js": "^4.1.3",
|
||||
"crypto-js": "^4.2.0",
|
||||
"eslint-config-thirdweb": "workspace:*",
|
||||
"ethers": "^5.7.2",
|
||||
"js-awe": "^1.0.62",
|
||||
"tinybench": "^2.5.1",
|
||||
"typescript": "^5.1.6",
|
||||
"viem": "^1.19.1"
|
||||
},
|
||||
"scripts": {
|
||||
"format": "prettier --write 'src/**/*'",
|
||||
"lint": "eslint src/ && bunx publint --strict --level warning",
|
||||
"fix": "eslint src/ --fix",
|
||||
"clean": "rm -rf dist/",
|
||||
"build": "tsc && preconstruct build",
|
||||
"push": "yalc push",
|
||||
"test": "bun test",
|
||||
"benchmark:aes-encrypt": "bun benchmark/aes-encrypt.ts",
|
||||
"benchmark:aes-decrypt": "bun benchmark/aes-decrypt.ts",
|
||||
"benchmark:sha256": "bun benchmark/sha256.ts",
|
||||
"benchmark:keccak256": "bun benchmark/keccak256.ts",
|
||||
"benchmark": "bun run benchmark:aes-encrypt && bun run benchmark:aes-decrypt && bun run benchmark:sha256 && bun run benchmark:keccak256"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
import { getCachedTextDecoder, getCachedTextEncoder } from "../utils/cache";
|
||||
import {
|
||||
decryptCryptoJSCipherBase64,
|
||||
parseCryptoJSCipherBase64,
|
||||
} from "./utils/crypto-js-compat";
|
||||
import { base64ToUint8Array } from "../utils/uint8array-extras";
|
||||
import { universalCrypto } from "../utils/universal-crypto";
|
||||
|
||||
/**
|
||||
* Decrypts ciphertext encrypted with aesEncrypt() using supplied password.
|
||||
*
|
||||
* @param ciphertext - Ciphertext to be decrypted.
|
||||
* @param password - Password to use to decrypt ciphertext.
|
||||
* @returns Decrypted plaintext.
|
||||
*
|
||||
* @example
|
||||
* const plaintext = await aesDecrypt(ciphertext, 'pw');
|
||||
*/
|
||||
export async function aesDecrypt(
|
||||
ciphertext: string,
|
||||
password: string,
|
||||
): Promise<string> {
|
||||
const crypto = await universalCrypto();
|
||||
// encode password as UTF-8
|
||||
const pwUtf8 = getCachedTextEncoder().encode(password);
|
||||
// hash the password
|
||||
const pwHash = await crypto.subtle.digest("SHA-256", pwUtf8);
|
||||
|
||||
const cipherUint8Array = base64ToUint8Array(ciphertext);
|
||||
|
||||
// iv
|
||||
const iv = cipherUint8Array.slice(0, 12);
|
||||
|
||||
// specify algorithm to use
|
||||
const alg = { name: "AES-GCM", iv };
|
||||
|
||||
// generate key from pw
|
||||
const key = await crypto.subtle.importKey("raw", pwHash, alg, false, [
|
||||
"decrypt",
|
||||
]);
|
||||
|
||||
// ciphertext
|
||||
const ctUint8 = cipherUint8Array.slice(12);
|
||||
|
||||
try {
|
||||
// decrypt ciphertext using key
|
||||
const plainBuffer = await crypto.subtle.decrypt(alg, key, ctUint8);
|
||||
// return the plaintext from ArrayBuffer
|
||||
return getCachedTextDecoder().decode(plainBuffer);
|
||||
} catch (e) {
|
||||
throw new Error("Decrypt failed");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypts ciphertext encrypted with aesEncrypt() OR "crypto-js".AES using supplied password.
|
||||
*
|
||||
* @param ciphertext - Ciphertext to be decrypted.
|
||||
* @param password - Password to use to decrypt ciphertext.
|
||||
* @returns Decrypted plaintext.
|
||||
*
|
||||
* @example
|
||||
* const plaintext = await aesDecryptCompat(ciphertext, 'pw');
|
||||
*/
|
||||
export async function aesDecryptCompat(
|
||||
ciphertext: string,
|
||||
password: string,
|
||||
): Promise<string> {
|
||||
// determine if we're dealing with a legacy (cryptojs) ciphertext
|
||||
const cryptoJs = parseCryptoJSCipherBase64(ciphertext);
|
||||
if (cryptoJs.salt && cryptoJs.ciphertext) {
|
||||
return decryptCryptoJSCipherBase64(
|
||||
cryptoJs.salt,
|
||||
cryptoJs.ciphertext,
|
||||
password,
|
||||
);
|
||||
}
|
||||
// otherwise assume it's a ciphertext generated by aesEncrypt()
|
||||
return aesDecrypt(ciphertext, password);
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
import {
|
||||
concatUint8Arrays,
|
||||
uint8ArrayToBase64,
|
||||
} from "../utils/uint8array-extras";
|
||||
import { getCachedTextEncoder } from "../utils/cache";
|
||||
import { universalCrypto } from "../utils/universal-crypto";
|
||||
|
||||
/**
|
||||
* Encrypts plaintext using AES-GCM with supplied password, for decryption with aesDecrypt().
|
||||
*
|
||||
* @param plaintext - Plaintext to be encrypted.
|
||||
* @param password - Password to use to encrypt plaintext.
|
||||
* @returns Encrypted ciphertext.
|
||||
*
|
||||
* @example
|
||||
* const ciphertext = await aesEncrypt('my secret text', 'pw');
|
||||
*/
|
||||
export async function aesEncrypt(
|
||||
plaintext: string,
|
||||
password: string,
|
||||
): Promise<string> {
|
||||
const crypto = await universalCrypto();
|
||||
const textEncoder = getCachedTextEncoder();
|
||||
// encode password as UTF-8
|
||||
const pwUtf8 = textEncoder.encode(password);
|
||||
// hash the password
|
||||
const pwHash = await crypto.subtle.digest("SHA-256", pwUtf8);
|
||||
|
||||
// get 96-bit random iv
|
||||
const iv = crypto.getRandomValues(new Uint8Array(12));
|
||||
|
||||
// specify algorithm to use
|
||||
const alg = { name: "AES-GCM", iv };
|
||||
|
||||
// generate key from pw
|
||||
const key = await crypto.subtle.importKey("raw", pwHash, alg, false, [
|
||||
"encrypt",
|
||||
]);
|
||||
|
||||
// encode plaintext as UTF-8
|
||||
const ptUint8 = textEncoder.encode(plaintext);
|
||||
// encrypt plaintext using key
|
||||
const ctBuffer = await crypto.subtle.encrypt(alg, key, ptUint8);
|
||||
|
||||
// iv+ciphertext base64-encoded
|
||||
return uint8ArrayToBase64(concatUint8Arrays([iv, new Uint8Array(ctBuffer)]));
|
||||
}
|
||||
@@ -0,0 +1,415 @@
|
||||
// stripped down version of `js-md5`
|
||||
// changes:
|
||||
// - we know we always have ArrayBuffer available
|
||||
// - we only care about `arrayBuffer` output
|
||||
// - we want to behave the same regardless of NODE or non NODE env
|
||||
// - transformed into class
|
||||
// - typescript
|
||||
|
||||
/**
|
||||
* [js-md5]{@link https://github.com/emn178/js-md5}
|
||||
*
|
||||
* @namespace md5
|
||||
* @version 0.8.3
|
||||
* @author Chen, Yi-Cyuan [[email protected]]
|
||||
* @copyright Chen, Yi-Cyuan 2014-2023
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
const INPUT_ERROR = "input is invalid type";
|
||||
const FINALIZE_ERROR = "finalize already called";
|
||||
|
||||
const EXTRA = [128, 32768, 8388608, -2147483648];
|
||||
|
||||
// [message: string, isString: bool]
|
||||
function formatMessage(
|
||||
message: string | any[] | ArrayBuffer | ArrayLike<number>,
|
||||
): [string | Uint8Array | Array<any> | ArrayBufferView, boolean] {
|
||||
const type = typeof message;
|
||||
if (typeof message === "string") {
|
||||
return [message, true];
|
||||
}
|
||||
if (type !== "object" || message === null) {
|
||||
throw new Error(INPUT_ERROR);
|
||||
}
|
||||
if (message instanceof ArrayBuffer) {
|
||||
return [new Uint8Array(message), false];
|
||||
}
|
||||
if (!Array.isArray(message) && !ArrayBuffer.isView(message)) {
|
||||
throw new Error(INPUT_ERROR);
|
||||
}
|
||||
return [message, false];
|
||||
}
|
||||
|
||||
/**
|
||||
* Md5 class
|
||||
* @class Md5
|
||||
* @description This is internal class.
|
||||
* @see {@link md5.create}
|
||||
*/
|
||||
class Md5 {
|
||||
buffer8: Uint8Array;
|
||||
blocks: Uint32Array;
|
||||
h0: number;
|
||||
h1: number;
|
||||
h2: number;
|
||||
h3: number;
|
||||
start: number;
|
||||
bytes: number;
|
||||
hBytes: number;
|
||||
finalized: boolean;
|
||||
hashed: boolean;
|
||||
first: boolean;
|
||||
lastByteIndex: number = 0;
|
||||
constructor() {
|
||||
// eslint-disable-next-line @typescript-eslint/no-shadow
|
||||
const buffer = new ArrayBuffer(68);
|
||||
this.buffer8 = new Uint8Array(buffer);
|
||||
this.blocks = new Uint32Array(buffer);
|
||||
|
||||
this.h0 =
|
||||
this.h1 =
|
||||
this.h2 =
|
||||
this.h3 =
|
||||
this.start =
|
||||
this.bytes =
|
||||
this.hBytes =
|
||||
0;
|
||||
this.finalized = this.hashed = false;
|
||||
this.first = true;
|
||||
}
|
||||
/**
|
||||
* @method update
|
||||
* @memberof Md5
|
||||
* @instance
|
||||
* @description Update hash
|
||||
* @param {String|Array|Uint8Array|ArrayBuffer} message message to hash
|
||||
* @returns {Md5} Md5 object.
|
||||
* @see {@link md5.update}
|
||||
*/
|
||||
update(inputMessage: string | any[] | ArrayBuffer | ArrayLike<number>): Md5 {
|
||||
if (this.finalized) {
|
||||
throw new Error(FINALIZE_ERROR);
|
||||
}
|
||||
|
||||
const [message, isString] = formatMessage(inputMessage);
|
||||
|
||||
const blocks = this.blocks;
|
||||
let length = 0;
|
||||
if (ArrayBuffer.isView(message)) {
|
||||
length = message.byteLength;
|
||||
} else {
|
||||
length = message.length;
|
||||
}
|
||||
let code,
|
||||
index = 0,
|
||||
i;
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-shadow
|
||||
const buffer8 = this.buffer8;
|
||||
|
||||
while (index < length) {
|
||||
if (this.hashed) {
|
||||
this.hashed = false;
|
||||
blocks[0] = blocks[16];
|
||||
blocks[16] =
|
||||
blocks[1] =
|
||||
blocks[2] =
|
||||
blocks[3] =
|
||||
blocks[4] =
|
||||
blocks[5] =
|
||||
blocks[6] =
|
||||
blocks[7] =
|
||||
blocks[8] =
|
||||
blocks[9] =
|
||||
blocks[10] =
|
||||
blocks[11] =
|
||||
blocks[12] =
|
||||
blocks[13] =
|
||||
blocks[14] =
|
||||
blocks[15] =
|
||||
0;
|
||||
}
|
||||
|
||||
if (isString) {
|
||||
for (i = this.start; index < length && i < 64; ++index) {
|
||||
code = (message as string).charCodeAt(index);
|
||||
if (code < 0x80) {
|
||||
buffer8[i++] = code;
|
||||
} else if (code < 0x800) {
|
||||
buffer8[i++] = 0xc0 | (code >>> 6);
|
||||
buffer8[i++] = 0x80 | (code & 0x3f);
|
||||
} else if (code < 0xd800 || code >= 0xe000) {
|
||||
buffer8[i++] = 0xe0 | (code >>> 12);
|
||||
buffer8[i++] = 0x80 | ((code >>> 6) & 0x3f);
|
||||
buffer8[i++] = 0x80 | (code & 0x3f);
|
||||
} else {
|
||||
code =
|
||||
0x10000 +
|
||||
(((code & 0x3ff) << 10) |
|
||||
((message as string).charCodeAt(++index) & 0x3ff));
|
||||
buffer8[i++] = 0xf0 | (code >>> 18);
|
||||
buffer8[i++] = 0x80 | ((code >>> 12) & 0x3f);
|
||||
buffer8[i++] = 0x80 | ((code >>> 6) & 0x3f);
|
||||
buffer8[i++] = 0x80 | (code & 0x3f);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (i = this.start; index < length && i < 64; ++index) {
|
||||
// at this point we know it's not a string
|
||||
buffer8[i++] = (message as any)[index];
|
||||
}
|
||||
}
|
||||
this.lastByteIndex = i;
|
||||
this.bytes += i - this.start;
|
||||
if (i >= 64) {
|
||||
this.start = i - 64;
|
||||
this.hash();
|
||||
this.hashed = true;
|
||||
} else {
|
||||
this.start = i;
|
||||
}
|
||||
}
|
||||
if (this.bytes > 4294967295) {
|
||||
this.hBytes += (this.bytes / 4294967296) << 0;
|
||||
this.bytes = this.bytes % 4294967296;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
finalize() {
|
||||
if (this.finalized) {
|
||||
return;
|
||||
}
|
||||
this.finalized = true;
|
||||
// eslint-disable-next-line @typescript-eslint/no-shadow
|
||||
const blocks = this.blocks,
|
||||
i = this.lastByteIndex;
|
||||
blocks[i >>> 2] |= EXTRA[i & 3];
|
||||
if (i >= 56) {
|
||||
if (!this.hashed) {
|
||||
this.hash();
|
||||
}
|
||||
blocks[0] = blocks[16];
|
||||
blocks[16] =
|
||||
blocks[1] =
|
||||
blocks[2] =
|
||||
blocks[3] =
|
||||
blocks[4] =
|
||||
blocks[5] =
|
||||
blocks[6] =
|
||||
blocks[7] =
|
||||
blocks[8] =
|
||||
blocks[9] =
|
||||
blocks[10] =
|
||||
blocks[11] =
|
||||
blocks[12] =
|
||||
blocks[13] =
|
||||
blocks[14] =
|
||||
blocks[15] =
|
||||
0;
|
||||
}
|
||||
blocks[14] = this.bytes << 3;
|
||||
blocks[15] = (this.hBytes << 3) | (this.bytes >>> 29);
|
||||
this.hash();
|
||||
}
|
||||
hash() {
|
||||
const blocks = this.blocks;
|
||||
let a, b, c, d, bc, da;
|
||||
|
||||
if (this.first) {
|
||||
a = blocks[0] - 680876937;
|
||||
a = (((a << 7) | (a >>> 25)) - 271733879) << 0;
|
||||
d = (-1732584194 ^ (a & 2004318071)) + blocks[1] - 117830708;
|
||||
d = (((d << 12) | (d >>> 20)) + a) << 0;
|
||||
c = (-271733879 ^ (d & (a ^ -271733879))) + blocks[2] - 1126478375;
|
||||
c = (((c << 17) | (c >>> 15)) + d) << 0;
|
||||
b = (a ^ (c & (d ^ a))) + blocks[3] - 1316259209;
|
||||
b = (((b << 22) | (b >>> 10)) + c) << 0;
|
||||
} else {
|
||||
a = this.h0;
|
||||
b = this.h1;
|
||||
c = this.h2;
|
||||
d = this.h3;
|
||||
a += (d ^ (b & (c ^ d))) + blocks[0] - 680876936;
|
||||
a = (((a << 7) | (a >>> 25)) + b) << 0;
|
||||
d += (c ^ (a & (b ^ c))) + blocks[1] - 389564586;
|
||||
d = (((d << 12) | (d >>> 20)) + a) << 0;
|
||||
c += (b ^ (d & (a ^ b))) + blocks[2] + 606105819;
|
||||
c = (((c << 17) | (c >>> 15)) + d) << 0;
|
||||
b += (a ^ (c & (d ^ a))) + blocks[3] - 1044525330;
|
||||
b = (((b << 22) | (b >>> 10)) + c) << 0;
|
||||
}
|
||||
|
||||
a += (d ^ (b & (c ^ d))) + blocks[4] - 176418897;
|
||||
a = (((a << 7) | (a >>> 25)) + b) << 0;
|
||||
d += (c ^ (a & (b ^ c))) + blocks[5] + 1200080426;
|
||||
d = (((d << 12) | (d >>> 20)) + a) << 0;
|
||||
c += (b ^ (d & (a ^ b))) + blocks[6] - 1473231341;
|
||||
c = (((c << 17) | (c >>> 15)) + d) << 0;
|
||||
b += (a ^ (c & (d ^ a))) + blocks[7] - 45705983;
|
||||
b = (((b << 22) | (b >>> 10)) + c) << 0;
|
||||
a += (d ^ (b & (c ^ d))) + blocks[8] + 1770035416;
|
||||
a = (((a << 7) | (a >>> 25)) + b) << 0;
|
||||
d += (c ^ (a & (b ^ c))) + blocks[9] - 1958414417;
|
||||
d = (((d << 12) | (d >>> 20)) + a) << 0;
|
||||
c += (b ^ (d & (a ^ b))) + blocks[10] - 42063;
|
||||
c = (((c << 17) | (c >>> 15)) + d) << 0;
|
||||
b += (a ^ (c & (d ^ a))) + blocks[11] - 1990404162;
|
||||
b = (((b << 22) | (b >>> 10)) + c) << 0;
|
||||
a += (d ^ (b & (c ^ d))) + blocks[12] + 1804603682;
|
||||
a = (((a << 7) | (a >>> 25)) + b) << 0;
|
||||
d += (c ^ (a & (b ^ c))) + blocks[13] - 40341101;
|
||||
d = (((d << 12) | (d >>> 20)) + a) << 0;
|
||||
c += (b ^ (d & (a ^ b))) + blocks[14] - 1502002290;
|
||||
c = (((c << 17) | (c >>> 15)) + d) << 0;
|
||||
b += (a ^ (c & (d ^ a))) + blocks[15] + 1236535329;
|
||||
b = (((b << 22) | (b >>> 10)) + c) << 0;
|
||||
a += (c ^ (d & (b ^ c))) + blocks[1] - 165796510;
|
||||
a = (((a << 5) | (a >>> 27)) + b) << 0;
|
||||
d += (b ^ (c & (a ^ b))) + blocks[6] - 1069501632;
|
||||
d = (((d << 9) | (d >>> 23)) + a) << 0;
|
||||
c += (a ^ (b & (d ^ a))) + blocks[11] + 643717713;
|
||||
c = (((c << 14) | (c >>> 18)) + d) << 0;
|
||||
b += (d ^ (a & (c ^ d))) + blocks[0] - 373897302;
|
||||
b = (((b << 20) | (b >>> 12)) + c) << 0;
|
||||
a += (c ^ (d & (b ^ c))) + blocks[5] - 701558691;
|
||||
a = (((a << 5) | (a >>> 27)) + b) << 0;
|
||||
d += (b ^ (c & (a ^ b))) + blocks[10] + 38016083;
|
||||
d = (((d << 9) | (d >>> 23)) + a) << 0;
|
||||
c += (a ^ (b & (d ^ a))) + blocks[15] - 660478335;
|
||||
c = (((c << 14) | (c >>> 18)) + d) << 0;
|
||||
b += (d ^ (a & (c ^ d))) + blocks[4] - 405537848;
|
||||
b = (((b << 20) | (b >>> 12)) + c) << 0;
|
||||
a += (c ^ (d & (b ^ c))) + blocks[9] + 568446438;
|
||||
a = (((a << 5) | (a >>> 27)) + b) << 0;
|
||||
d += (b ^ (c & (a ^ b))) + blocks[14] - 1019803690;
|
||||
d = (((d << 9) | (d >>> 23)) + a) << 0;
|
||||
c += (a ^ (b & (d ^ a))) + blocks[3] - 187363961;
|
||||
c = (((c << 14) | (c >>> 18)) + d) << 0;
|
||||
b += (d ^ (a & (c ^ d))) + blocks[8] + 1163531501;
|
||||
b = (((b << 20) | (b >>> 12)) + c) << 0;
|
||||
a += (c ^ (d & (b ^ c))) + blocks[13] - 1444681467;
|
||||
a = (((a << 5) | (a >>> 27)) + b) << 0;
|
||||
d += (b ^ (c & (a ^ b))) + blocks[2] - 51403784;
|
||||
d = (((d << 9) | (d >>> 23)) + a) << 0;
|
||||
c += (a ^ (b & (d ^ a))) + blocks[7] + 1735328473;
|
||||
c = (((c << 14) | (c >>> 18)) + d) << 0;
|
||||
b += (d ^ (a & (c ^ d))) + blocks[12] - 1926607734;
|
||||
b = (((b << 20) | (b >>> 12)) + c) << 0;
|
||||
bc = b ^ c;
|
||||
a += (bc ^ d) + blocks[5] - 378558;
|
||||
a = (((a << 4) | (a >>> 28)) + b) << 0;
|
||||
d += (bc ^ a) + blocks[8] - 2022574463;
|
||||
d = (((d << 11) | (d >>> 21)) + a) << 0;
|
||||
da = d ^ a;
|
||||
c += (da ^ b) + blocks[11] + 1839030562;
|
||||
c = (((c << 16) | (c >>> 16)) + d) << 0;
|
||||
b += (da ^ c) + blocks[14] - 35309556;
|
||||
b = (((b << 23) | (b >>> 9)) + c) << 0;
|
||||
bc = b ^ c;
|
||||
a += (bc ^ d) + blocks[1] - 1530992060;
|
||||
a = (((a << 4) | (a >>> 28)) + b) << 0;
|
||||
d += (bc ^ a) + blocks[4] + 1272893353;
|
||||
d = (((d << 11) | (d >>> 21)) + a) << 0;
|
||||
da = d ^ a;
|
||||
c += (da ^ b) + blocks[7] - 155497632;
|
||||
c = (((c << 16) | (c >>> 16)) + d) << 0;
|
||||
b += (da ^ c) + blocks[10] - 1094730640;
|
||||
b = (((b << 23) | (b >>> 9)) + c) << 0;
|
||||
bc = b ^ c;
|
||||
a += (bc ^ d) + blocks[13] + 681279174;
|
||||
a = (((a << 4) | (a >>> 28)) + b) << 0;
|
||||
d += (bc ^ a) + blocks[0] - 358537222;
|
||||
d = (((d << 11) | (d >>> 21)) + a) << 0;
|
||||
da = d ^ a;
|
||||
c += (da ^ b) + blocks[3] - 722521979;
|
||||
c = (((c << 16) | (c >>> 16)) + d) << 0;
|
||||
b += (da ^ c) + blocks[6] + 76029189;
|
||||
b = (((b << 23) | (b >>> 9)) + c) << 0;
|
||||
bc = b ^ c;
|
||||
a += (bc ^ d) + blocks[9] - 640364487;
|
||||
a = (((a << 4) | (a >>> 28)) + b) << 0;
|
||||
d += (bc ^ a) + blocks[12] - 421815835;
|
||||
d = (((d << 11) | (d >>> 21)) + a) << 0;
|
||||
da = d ^ a;
|
||||
c += (da ^ b) + blocks[15] + 530742520;
|
||||
c = (((c << 16) | (c >>> 16)) + d) << 0;
|
||||
b += (da ^ c) + blocks[2] - 995338651;
|
||||
b = (((b << 23) | (b >>> 9)) + c) << 0;
|
||||
a += (c ^ (b | ~d)) + blocks[0] - 198630844;
|
||||
a = (((a << 6) | (a >>> 26)) + b) << 0;
|
||||
d += (b ^ (a | ~c)) + blocks[7] + 1126891415;
|
||||
d = (((d << 10) | (d >>> 22)) + a) << 0;
|
||||
c += (a ^ (d | ~b)) + blocks[14] - 1416354905;
|
||||
c = (((c << 15) | (c >>> 17)) + d) << 0;
|
||||
b += (d ^ (c | ~a)) + blocks[5] - 57434055;
|
||||
b = (((b << 21) | (b >>> 11)) + c) << 0;
|
||||
a += (c ^ (b | ~d)) + blocks[12] + 1700485571;
|
||||
a = (((a << 6) | (a >>> 26)) + b) << 0;
|
||||
d += (b ^ (a | ~c)) + blocks[3] - 1894986606;
|
||||
d = (((d << 10) | (d >>> 22)) + a) << 0;
|
||||
c += (a ^ (d | ~b)) + blocks[10] - 1051523;
|
||||
c = (((c << 15) | (c >>> 17)) + d) << 0;
|
||||
b += (d ^ (c | ~a)) + blocks[1] - 2054922799;
|
||||
b = (((b << 21) | (b >>> 11)) + c) << 0;
|
||||
a += (c ^ (b | ~d)) + blocks[8] + 1873313359;
|
||||
a = (((a << 6) | (a >>> 26)) + b) << 0;
|
||||
d += (b ^ (a | ~c)) + blocks[15] - 30611744;
|
||||
d = (((d << 10) | (d >>> 22)) + a) << 0;
|
||||
c += (a ^ (d | ~b)) + blocks[6] - 1560198380;
|
||||
c = (((c << 15) | (c >>> 17)) + d) << 0;
|
||||
b += (d ^ (c | ~a)) + blocks[13] + 1309151649;
|
||||
b = (((b << 21) | (b >>> 11)) + c) << 0;
|
||||
a += (c ^ (b | ~d)) + blocks[4] - 145523070;
|
||||
a = (((a << 6) | (a >>> 26)) + b) << 0;
|
||||
d += (b ^ (a | ~c)) + blocks[11] - 1120210379;
|
||||
d = (((d << 10) | (d >>> 22)) + a) << 0;
|
||||
c += (a ^ (d | ~b)) + blocks[2] + 718787259;
|
||||
c = (((c << 15) | (c >>> 17)) + d) << 0;
|
||||
b += (d ^ (c | ~a)) + blocks[9] - 343485551;
|
||||
b = (((b << 21) | (b >>> 11)) + c) << 0;
|
||||
|
||||
if (this.first) {
|
||||
this.h0 = (a + 1732584193) << 0;
|
||||
this.h1 = (b - 271733879) << 0;
|
||||
this.h2 = (c - 1732584194) << 0;
|
||||
this.h3 = (d + 271733878) << 0;
|
||||
this.first = false;
|
||||
} else {
|
||||
this.h0 = (this.h0 + a) << 0;
|
||||
this.h1 = (this.h1 + b) << 0;
|
||||
this.h2 = (this.h2 + c) << 0;
|
||||
this.h3 = (this.h3 + d) << 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @method arrayBuffer
|
||||
* @memberof Md5
|
||||
* @instance
|
||||
* @description Output hash as ArrayBuffer
|
||||
* @returns {ArrayBuffer} ArrayBuffer
|
||||
* @see {@link md5.arrayBuffer}
|
||||
* @example
|
||||
* hash.arrayBuffer();
|
||||
*/
|
||||
arrayBuffer(): ArrayBuffer {
|
||||
this.finalize();
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-shadow
|
||||
const buffer = new ArrayBuffer(16);
|
||||
// eslint-disable-next-line @typescript-eslint/no-shadow
|
||||
const blocks = new Uint32Array(buffer);
|
||||
blocks[0] = this.h0;
|
||||
blocks[1] = this.h1;
|
||||
blocks[2] = this.h2;
|
||||
blocks[3] = this.h3;
|
||||
return buffer;
|
||||
}
|
||||
}
|
||||
|
||||
export function arrayBuffer(uint8Arr: Uint8Array) {
|
||||
const md5 = new Md5();
|
||||
md5.update(uint8Arr);
|
||||
return md5.arrayBuffer();
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
import { getCachedTextDecoder, getCachedTextEncoder } from "../../utils/cache";
|
||||
import { arrayBuffer } from "../lib/md5";
|
||||
import {
|
||||
base64ToUint8Array,
|
||||
concatUint8Arrays,
|
||||
} from "../../utils/uint8array-extras";
|
||||
import { universalCrypto } from "../../utils/universal-crypto";
|
||||
|
||||
/**
|
||||
* This is an implementation of the CryptoJS AES decryption scheme, without actually relying on crypto-js.
|
||||
*/
|
||||
|
||||
const HEAD_SIZE_DWORD = 2;
|
||||
const SALT_SIZE_DWORD = 2;
|
||||
|
||||
export async function decryptCryptoJSCipherBase64(
|
||||
salt: Uint8Array,
|
||||
ciphertext: Uint8Array,
|
||||
password: string,
|
||||
{ keySizeDWORD = 256 / 32, ivSizeDWORD = 128 / 32, iterations = 1 } = {},
|
||||
) {
|
||||
const crypto = await universalCrypto();
|
||||
const { key, iv } = await dangerouslyDeriveParameters(
|
||||
password,
|
||||
salt,
|
||||
keySizeDWORD,
|
||||
ivSizeDWORD,
|
||||
iterations,
|
||||
);
|
||||
|
||||
try {
|
||||
// decrypt ciphertext using key
|
||||
const plainBuffer = await crypto.subtle.decrypt(
|
||||
{ name: "AES-CBC", iv },
|
||||
key,
|
||||
ciphertext,
|
||||
);
|
||||
// return the plaintext from ArrayBuffer
|
||||
return getCachedTextDecoder().decode(plainBuffer);
|
||||
} catch (e) {
|
||||
throw new Error("Decrypt failed");
|
||||
}
|
||||
}
|
||||
|
||||
export function parseCryptoJSCipherBase64(cryptoJSCipherBase64: string) {
|
||||
let salt: Uint8Array | null = null;
|
||||
let ciphertext = base64ToUint8Array(cryptoJSCipherBase64);
|
||||
|
||||
const [head, body] = splitUint8Array(ciphertext, HEAD_SIZE_DWORD * 4);
|
||||
|
||||
// This effectively checks if the ciphertext starts with 'Salted__', which is the crypto-js convention.
|
||||
const headDataView = new DataView(head.buffer);
|
||||
if (
|
||||
headDataView.getInt32(0) === 0x53616c74 &&
|
||||
headDataView.getInt32(4) === 0x65645f5f
|
||||
) {
|
||||
[salt, ciphertext] = splitUint8Array(body, SALT_SIZE_DWORD * 4);
|
||||
}
|
||||
|
||||
return { ciphertext, salt };
|
||||
}
|
||||
|
||||
async function dangerouslyDeriveParameters(
|
||||
password: string,
|
||||
salt: Uint8Array,
|
||||
keySizeDWORD: number,
|
||||
ivSizeDWORD: number,
|
||||
iterations: number,
|
||||
) {
|
||||
const crypto = await universalCrypto();
|
||||
const passwordUint8Array = getCachedTextEncoder().encode(password);
|
||||
|
||||
const keyPlusIV = dangerousEVPKDF(
|
||||
passwordUint8Array,
|
||||
salt,
|
||||
keySizeDWORD + ivSizeDWORD,
|
||||
iterations,
|
||||
);
|
||||
const [rawKey, iv] = splitUint8Array(keyPlusIV, keySizeDWORD * 4);
|
||||
|
||||
const key = await crypto.subtle.importKey("raw", rawKey, "AES-CBC", false, [
|
||||
"decrypt",
|
||||
]);
|
||||
|
||||
return { key, iv };
|
||||
}
|
||||
|
||||
function dangerousEVPKDF(
|
||||
passwordUint8Array: Uint8Array,
|
||||
saltUint8Array: Uint8Array,
|
||||
keySizeDWORD: number,
|
||||
iterations: number,
|
||||
) {
|
||||
let derivedKey = new Uint8Array();
|
||||
let block = new Uint8Array();
|
||||
|
||||
while (derivedKey.byteLength < keySizeDWORD * 4) {
|
||||
block = new Uint8Array(
|
||||
arrayBuffer(
|
||||
concatUint8Arrays([block, passwordUint8Array, saltUint8Array]),
|
||||
),
|
||||
);
|
||||
|
||||
for (let i = 1; i < iterations; i++) {
|
||||
block = new Uint8Array(arrayBuffer(block));
|
||||
}
|
||||
|
||||
derivedKey = concatUint8Arrays([derivedKey, block]);
|
||||
}
|
||||
|
||||
return derivedKey;
|
||||
}
|
||||
|
||||
function splitUint8Array(a: Uint8Array, i: number) {
|
||||
return [a.subarray(0, i), a.subarray(i, a.length)];
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
export { aesDecrypt, aesDecryptCompat } from "./aes/decrypt";
|
||||
export { aesEncrypt } from "./aes/encrypt";
|
||||
export { sha256, sha256Hex, sha256Sync, sha256HexSync } from "./sha256";
|
||||
export {
|
||||
keccak256Sync,
|
||||
keccak256SyncHex,
|
||||
keccak256SyncHexPrefixed,
|
||||
} from "./keccak256";
|
||||
@@ -0,0 +1,31 @@
|
||||
import { keccak_256 } from "js-sha3";
|
||||
|
||||
/**
|
||||
* Hashes a string or Uint8Array using keccak256.
|
||||
* @param value - Value to be hashed.
|
||||
* @returns Hash of the value as Uint8Array.
|
||||
*/
|
||||
export function keccak256Sync(value: string | Uint8Array): Uint8Array {
|
||||
return new Uint8Array(keccak_256.arrayBuffer(value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Hashes a string or Uint8Array using keccak256 and returns the result as a hex string.
|
||||
* @param value - Value to be hashed.
|
||||
* @returns Hash of the value as a hex string.
|
||||
*/
|
||||
export function keccak256SyncHex(value: string | Uint8Array): string {
|
||||
return keccak_256(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Hashes a string or Uint8Array using keccak256 and returns the result as a hex string prefixed with "0x".
|
||||
* @param value - Value to be hashed.
|
||||
* @returns Hash of the value as a hex string prefixed with "0x".
|
||||
*/
|
||||
export function keccak256SyncHexPrefixed(
|
||||
value: string | Uint8Array,
|
||||
): `0x${string}` {
|
||||
// prefix with 0x (this is what ethers.utils.keccak256 does)
|
||||
return `0x${keccak256SyncHex(value)}`;
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
import { sha256 as sha256Noble } from "@noble/hashes/sha256";
|
||||
import { uint8ArrayToHex } from "./utils/uint8array-extras";
|
||||
import { getCachedTextEncoder } from "./utils/cache";
|
||||
import { universalCrypto } from "./utils/universal-crypto";
|
||||
|
||||
/**
|
||||
* Hash a string or Uint8Array using sha256.
|
||||
* @param value - Value to be hashed.
|
||||
* @returns A promise that resolves to the hash of the value as Uint8Array.
|
||||
*/
|
||||
export async function sha256(
|
||||
value: string | BufferSource,
|
||||
): Promise<Uint8Array> {
|
||||
let encodedValue;
|
||||
if (typeof value === "string") {
|
||||
// if we do not have a cahced TextEncoder instance, create one
|
||||
|
||||
encodedValue = getCachedTextEncoder().encode(value);
|
||||
} else {
|
||||
encodedValue = value;
|
||||
}
|
||||
|
||||
return new Uint8Array(
|
||||
await (await universalCrypto()).subtle.digest("SHA-256", encodedValue),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Hash a string or Uint8Array using sha256 and returns the result as a hex string.
|
||||
* @param value - Value to be hashed.
|
||||
* @returns A promise that resolves to the hash of the value as a hex string.
|
||||
*/
|
||||
export async function sha256Hex(value: string | BufferSource): Promise<string> {
|
||||
return uint8ArrayToHex(await sha256(value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Hash a string or Uint8Array using sha256.
|
||||
* @param value - Value to be hashed.
|
||||
* @returns The hash of the value as Uint8Array.
|
||||
*/
|
||||
export function sha256Sync(value: string | Uint8Array): Uint8Array {
|
||||
return sha256Noble(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Hash a string or Uint8Array using sha256.
|
||||
* @param value - Value to be hashed.
|
||||
* @returns The hash of the value as a hex string.
|
||||
*/
|
||||
export function sha256HexSync(value: string | Uint8Array): string {
|
||||
return uint8ArrayToHex(sha256Sync(value));
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
class TextProcessorCache {
|
||||
#encoder: TextEncoder | undefined;
|
||||
#decoder: TextDecoder | undefined;
|
||||
|
||||
get encoder(): TextEncoder {
|
||||
if (!this.#encoder) {
|
||||
this.#encoder = new TextEncoder();
|
||||
}
|
||||
return this.#encoder;
|
||||
}
|
||||
|
||||
get decoder(): TextDecoder {
|
||||
if (!this.#decoder) {
|
||||
this.#decoder = new TextDecoder();
|
||||
}
|
||||
return this.#decoder;
|
||||
}
|
||||
}
|
||||
|
||||
// create a singleton instance of the TextProcessorCache
|
||||
const textProcessorSingleton = new TextProcessorCache();
|
||||
|
||||
export function getCachedTextEncoder(): TextEncoder {
|
||||
return textProcessorSingleton.encoder;
|
||||
}
|
||||
|
||||
export function getCachedTextDecoder(): TextDecoder {
|
||||
return textProcessorSingleton.decoder;
|
||||
}
|
||||
+251
@@ -0,0 +1,251 @@
|
||||
export type TypedArray =
|
||||
| Int8Array
|
||||
| Uint8Array
|
||||
| Uint8ClampedArray
|
||||
| Int16Array
|
||||
| Uint16Array
|
||||
| Int32Array
|
||||
| Uint32Array
|
||||
| Float32Array
|
||||
| Float64Array
|
||||
| BigInt64Array
|
||||
| BigUint64Array;
|
||||
|
||||
/**
|
||||
Check if the given value is an instance of `Uint8Array`.
|
||||
|
||||
Replacement for [`Buffer.isBuffer()`](https://nodejs.org/api/buffer.html#static-method-bufferisbufferobj).
|
||||
|
||||
@example
|
||||
```
|
||||
import {isUint8Array} from 'uint8array-extras';
|
||||
|
||||
console.log(isUint8Array(new Uint8Array()));
|
||||
//=> true
|
||||
|
||||
console.log(isUint8Array(Buffer.from('x')));
|
||||
//=> true
|
||||
|
||||
console.log(isUint8Array(new ArrayBuffer(10)));
|
||||
//=> false
|
||||
```
|
||||
*/
|
||||
export function isUint8Array(value: unknown): value is Uint8Array;
|
||||
|
||||
/**
|
||||
Throw a `TypeError` if the given value is not an instance of `Uint8Array`.
|
||||
|
||||
@example
|
||||
```
|
||||
import {assertUint8Array} from 'uint8array-extras';
|
||||
|
||||
try {
|
||||
assertUint8Array(new ArrayBuffer(10)); // Throws a TypeError
|
||||
} catch (error) {
|
||||
console.error(error.message);
|
||||
}
|
||||
```
|
||||
*/
|
||||
export function assertUint8Array(value: unknown): asserts value is Uint8Array;
|
||||
|
||||
/**
|
||||
Convert a value to a `Uint8Array` without copying its data.
|
||||
|
||||
This can be useful for converting a `Buffer` to a pure `Uint8Array`. `Buffer` is already an `Uint8Array` subclass, but [`Buffer` alters some behavior](https://sindresorhus.com/blog/goodbye-nodejs-buffer), so it can be useful to cast it to a pure `Uint8Array` before returning it.
|
||||
|
||||
Tip: If you want a copy, just call `.slice()` on the return value.
|
||||
*/
|
||||
export function toUint8Array(value: TypedArray | ArrayBuffer | DataView): Uint8Array;
|
||||
|
||||
/**
|
||||
Concatenate the given arrays into a new array.
|
||||
|
||||
If `arrays` is empty, it will return a zero-sized `Uint8Array`.
|
||||
|
||||
If `totalLength` is not specified, it is calculated from summing the lengths of the given arrays.
|
||||
|
||||
Replacement for [`Buffer.concat()`](https://nodejs.org/api/buffer.html#static-method-bufferconcatlist-totallength).
|
||||
|
||||
@example
|
||||
```
|
||||
import {concatUint8Arrays} from 'uint8array-extras';
|
||||
|
||||
const a = new Uint8Array([1, 2, 3]);
|
||||
const b = new Uint8Array([4, 5, 6]);
|
||||
|
||||
console.log(concatUint8Arrays([a, b]));
|
||||
//=> Uint8Array [1, 2, 3, 4, 5, 6]
|
||||
```
|
||||
*/
|
||||
export function concatUint8Arrays(arrays: Uint8Array[], totalLength?: number): Uint8Array;
|
||||
|
||||
/**
|
||||
Check if two arrays are identical by verifying that they contain the same bytes in the same sequence.
|
||||
|
||||
Replacement for [`Buffer#equals()`](https://nodejs.org/api/buffer.html#bufequalsotherbuffer).
|
||||
|
||||
@example
|
||||
```
|
||||
import {areUint8ArraysEqual} from 'uint8array-extras';
|
||||
|
||||
const a = new Uint8Array([1, 2, 3]);
|
||||
const b = new Uint8Array([1, 2, 3]);
|
||||
const c = new Uint8Array([4, 5, 6]);
|
||||
|
||||
console.log(areUint8ArraysEqual(a, b));
|
||||
//=> true
|
||||
|
||||
console.log(areUint8ArraysEqual(a, c));
|
||||
//=> false
|
||||
```
|
||||
*/
|
||||
export function areUint8ArraysEqual(a: Uint8Array, b: Uint8Array): boolean;
|
||||
|
||||
/**
|
||||
Compare two arrays and indicate their relative order or equality. Useful for sorting.
|
||||
|
||||
Replacement for [`Buffer.compare()`](https://nodejs.org/api/buffer.html#static-method-buffercomparebuf1-buf2).
|
||||
|
||||
@example
|
||||
```
|
||||
import {compareUint8Arrays} from 'uint8array-extras';
|
||||
|
||||
const array1 = new Uint8Array([1, 2, 3]);
|
||||
const array2 = new Uint8Array([4, 5, 6]);
|
||||
const array3 = new Uint8Array([7, 8, 9]);
|
||||
|
||||
[array3, array1, array2].sort(compareUint8Arrays);
|
||||
//=> [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
|
||||
```
|
||||
*/
|
||||
export function compareUint8Arrays(a: Uint8Array, b: Uint8Array): 0 | 1 | -1;
|
||||
|
||||
/**
|
||||
Convert a `Uint8Array` (containing a UTF-8 string) to a string.
|
||||
|
||||
Replacement for [`Buffer#toString()`](https://nodejs.org/api/buffer.html#buftostringencoding-start-end).
|
||||
|
||||
@example
|
||||
```
|
||||
import {uint8ArrayToString} from 'uint8array-extras';
|
||||
|
||||
const byteArray = new Uint8Array([72, 101, 108, 108, 111]);
|
||||
|
||||
console.log(uint8ArrayToString(byteArray));
|
||||
//=> 'Hello'
|
||||
```
|
||||
*/
|
||||
export function uint8ArrayToString(array: Uint8Array): string;
|
||||
|
||||
/**
|
||||
Convert a string to a `Uint8Array` (using UTF-8 encoding).
|
||||
|
||||
Replacement for [`Buffer.from('Hello')`](https://nodejs.org/api/buffer.html#static-method-bufferfromstring-encoding).
|
||||
|
||||
@example
|
||||
```
|
||||
import {stringToUint8Array} from 'uint8array-extras';
|
||||
|
||||
console.log(stringToUint8Array('Hello'));
|
||||
//=> Uint8Array [72, 101, 108, 108, 111]
|
||||
```
|
||||
*/
|
||||
export function stringToUint8Array(string: string): Uint8Array;
|
||||
|
||||
/**
|
||||
Convert a `Uint8Array` to a Base64-encoded string.
|
||||
|
||||
Specify `{urlSafe: true}` to get a [Base64URL](https://base64.guru/standards/base64url)-encoded string.
|
||||
|
||||
Replacement for [`Buffer#toString('base64')`](https://nodejs.org/api/buffer.html#buftostringencoding-start-end).
|
||||
|
||||
@example
|
||||
```
|
||||
import {uint8ArrayToBase64} from 'uint8array-extras';
|
||||
|
||||
const byteArray = new Uint8Array([72, 101, 108, 108, 111]);
|
||||
|
||||
console.log(uint8ArrayToBase64(byteArray));
|
||||
//=> 'SGVsbG8='
|
||||
```
|
||||
*/
|
||||
export function uint8ArrayToBase64(array: Uint8Array, options?: {urlSafe: boolean}): string;
|
||||
|
||||
/**
|
||||
Convert a Base64-encoded or [Base64URL](https://base64.guru/standards/base64url)-encoded string to a `Uint8Array`.
|
||||
|
||||
Replacement for [`Buffer.from('SGVsbG8=', 'base64')`](https://nodejs.org/api/buffer.html#static-method-bufferfromstring-encoding).
|
||||
|
||||
@example
|
||||
```
|
||||
import {base64ToUint8Array} from 'uint8array-extras';
|
||||
|
||||
console.log(base64ToUint8Array('SGVsbG8='));
|
||||
//=> Uint8Array [72, 101, 108, 108, 111]
|
||||
```
|
||||
*/
|
||||
export function base64ToUint8Array(string: string): Uint8Array;
|
||||
|
||||
/**
|
||||
Encode a string to Base64-encoded string.
|
||||
|
||||
Specify `{urlSafe: true}` to get a [Base64URL](https://base64.guru/standards/base64url)-encoded string.
|
||||
|
||||
Replacement for `Buffer.from('Hello').toString('base64')` and [`btoa()`](https://developer.mozilla.org/en-US/docs/Web/API/btoa).
|
||||
|
||||
@example
|
||||
```
|
||||
import {stringToBase64} from 'uint8array-extras';
|
||||
|
||||
console.log(stringToBase64('Hello'));
|
||||
//=> 'SGVsbG8='
|
||||
```
|
||||
*/
|
||||
export function stringToBase64(string: string, options?: {urlSafe: boolean}): string;
|
||||
|
||||
/**
|
||||
Decode a Base64-encoded or [Base64URL](https://base64.guru/standards/base64url)-encoded string to a string.
|
||||
|
||||
Replacement for `Buffer.from('SGVsbG8=', 'base64').toString()` and [`atob()`](https://developer.mozilla.org/en-US/docs/Web/API/atob).
|
||||
|
||||
@example
|
||||
```
|
||||
import {base64ToString} from 'uint8array-extras';
|
||||
|
||||
console.log(base64ToString('SGVsbG8='));
|
||||
//=> 'Hello'
|
||||
```
|
||||
*/
|
||||
export function base64ToString(base64String: string): string;
|
||||
|
||||
/**
|
||||
Convert a `Uint8Array` to a Hex string.
|
||||
|
||||
Replacement for [`Buffer#toString('hex')`](https://nodejs.org/api/buffer.html#buftostringencoding-start-end).
|
||||
|
||||
@example
|
||||
```
|
||||
import {uint8ArrayToHex} from 'uint8array-extras';
|
||||
|
||||
const byteArray = new Uint8Array([72, 101, 108, 108, 111]);
|
||||
|
||||
console.log(uint8ArrayToHex(byteArray));
|
||||
//=> '48656c6c6f'
|
||||
```
|
||||
*/
|
||||
export function uint8ArrayToHex(array: Uint8Array): string;
|
||||
|
||||
/**
|
||||
Convert a Hex string to a `Uint8Array`.
|
||||
|
||||
Replacement for [`Buffer.from('48656c6c6f', 'hex')`](https://nodejs.org/api/buffer.html#static-method-bufferfromstring-encoding).
|
||||
|
||||
@example
|
||||
```
|
||||
import {hexToUint8Array} from 'uint8array-extras';
|
||||
|
||||
console.log(hexToUint8Array('48656c6c6f'));
|
||||
//=> Uint8Array [72, 101, 108, 108, 111]
|
||||
```
|
||||
*/
|
||||
export function hexToUint8Array(hexString: string): Uint8Array;
|
||||
@@ -0,0 +1,242 @@
|
||||
// taken from: https://github.com/sindresorhus/uint8array-extras
|
||||
// to make it work across CJS and ESM -> once we're fully ESM we can remove this and instead use the package directly
|
||||
|
||||
import { getCachedTextDecoder, getCachedTextEncoder } from "./cache";
|
||||
|
||||
const objectToString = Object.prototype.toString;
|
||||
const uint8ArrayStringified = "[object Uint8Array]";
|
||||
|
||||
export function isUint8Array(value) {
|
||||
if (!value) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (value.constructor === Uint8Array) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return objectToString.call(value) === uint8ArrayStringified;
|
||||
}
|
||||
|
||||
export function assertUint8Array(value) {
|
||||
if (!isUint8Array(value)) {
|
||||
throw new TypeError(`Expected \`Uint8Array\`, got \`${typeof value}\``);
|
||||
}
|
||||
}
|
||||
|
||||
export function toUint8Array(value) {
|
||||
if (value instanceof ArrayBuffer) {
|
||||
return new Uint8Array(value);
|
||||
}
|
||||
|
||||
if (ArrayBuffer.isView(value)) {
|
||||
return new Uint8Array(value.buffer, value.byteOffset, value.byteLength);
|
||||
}
|
||||
|
||||
throw new TypeError(`Unsupported value, got \`${typeof value}\`.`);
|
||||
}
|
||||
|
||||
export function concatUint8Arrays(arrays, totalLength) {
|
||||
if (arrays.length === 0) {
|
||||
return new Uint8Array(0);
|
||||
}
|
||||
|
||||
totalLength ??= arrays.reduce(
|
||||
(accumulator, currentValue) => accumulator + currentValue.length,
|
||||
0,
|
||||
);
|
||||
|
||||
const returnValue = new Uint8Array(totalLength);
|
||||
|
||||
let offset = 0;
|
||||
for (const array of arrays) {
|
||||
assertUint8Array(array);
|
||||
returnValue.set(array, offset);
|
||||
offset += array.length;
|
||||
}
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
export function areUint8ArraysEqual(a, b) {
|
||||
assertUint8Array(a);
|
||||
assertUint8Array(b);
|
||||
|
||||
if (a === b) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (a.length !== b.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (let index = 0; index < a.length; index++) {
|
||||
if (a[index] !== b[index]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
export function compareUint8Arrays(a, b) {
|
||||
assertUint8Array(a);
|
||||
assertUint8Array(b);
|
||||
|
||||
const length = Math.min(a.length, b.length);
|
||||
|
||||
for (let index = 0; index < length; index++) {
|
||||
if (a[index] < b[index]) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (a[index] > b[index]) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
// At this point, all the compared elements are equal.
|
||||
// The shorter array should come first if the arrays are of different lengths.
|
||||
if (a.length > b.length) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (a.length < b.length) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
export function uint8ArrayToString(array) {
|
||||
assertUint8Array(array);
|
||||
return getCachedTextDecoder().decode(array);
|
||||
}
|
||||
|
||||
function assertString(value) {
|
||||
if (typeof value !== "string") {
|
||||
throw new TypeError(`Expected \`string\`, got \`${typeof value}\``);
|
||||
}
|
||||
}
|
||||
|
||||
export function stringToUint8Array(string) {
|
||||
assertString(string);
|
||||
return getCachedTextEncoder().encode(string);
|
||||
}
|
||||
|
||||
function base64ToBase64Url(base64) {
|
||||
return base64.replaceAll("+", "-").replaceAll("/", "_").replace(/=+$/, "");
|
||||
}
|
||||
|
||||
function base64UrlToBase64(base64url) {
|
||||
return base64url.replaceAll("-", "+").replaceAll("_", "/");
|
||||
}
|
||||
|
||||
// Reference: https://phuoc.ng/collection/this-vs-that/concat-vs-push/
|
||||
const MAX_BLOCK_SIZE = 65_535;
|
||||
|
||||
export function uint8ArrayToBase64(array, { urlSafe = false } = {}) {
|
||||
assertUint8Array(array);
|
||||
|
||||
let base64;
|
||||
|
||||
if (array.length < MAX_BLOCK_SIZE) {
|
||||
// Required as `btoa` and `atob` don't properly support Unicode: https://developer.mozilla.org/en-US/docs/Glossary/Base64#the_unicode_problem
|
||||
base64 = globalThis.btoa(String.fromCodePoint.apply(this, array));
|
||||
} else {
|
||||
base64 = "";
|
||||
for (const value of array) {
|
||||
base64 += String.fromCodePoint(value);
|
||||
}
|
||||
|
||||
base64 = globalThis.btoa(base64);
|
||||
}
|
||||
|
||||
return urlSafe ? base64ToBase64Url(base64) : base64;
|
||||
}
|
||||
|
||||
export function base64ToUint8Array(base64String) {
|
||||
assertString(base64String);
|
||||
return Uint8Array.from(
|
||||
globalThis.atob(base64UrlToBase64(base64String)),
|
||||
(x) => x.codePointAt(0),
|
||||
);
|
||||
}
|
||||
|
||||
export function stringToBase64(string, { urlSafe = false } = {}) {
|
||||
assertString(string);
|
||||
return uint8ArrayToBase64(stringToUint8Array(string), { urlSafe });
|
||||
}
|
||||
|
||||
export function base64ToString(base64String) {
|
||||
assertString(base64String);
|
||||
return uint8ArrayToString(base64ToUint8Array(base64String));
|
||||
}
|
||||
|
||||
const byteToHexLookupTable = Array.from({ length: 256 }, (_, index) =>
|
||||
index.toString(16).padStart(2, "0"),
|
||||
);
|
||||
|
||||
export function uint8ArrayToHex(array) {
|
||||
assertUint8Array(array);
|
||||
|
||||
// Concatenating a string is faster than using an array.
|
||||
let hexString = "";
|
||||
|
||||
for (let index = 0; index < array.length; index++) {
|
||||
hexString += byteToHexLookupTable[array[index]];
|
||||
}
|
||||
|
||||
return hexString;
|
||||
}
|
||||
|
||||
const hexToDecimalLookupTable = {
|
||||
0: 0,
|
||||
1: 1,
|
||||
2: 2,
|
||||
3: 3,
|
||||
4: 4,
|
||||
5: 5,
|
||||
6: 6,
|
||||
7: 7,
|
||||
8: 8,
|
||||
9: 9,
|
||||
a: 10,
|
||||
b: 11,
|
||||
c: 12,
|
||||
d: 13,
|
||||
e: 14,
|
||||
f: 15,
|
||||
A: 10,
|
||||
B: 11,
|
||||
C: 12,
|
||||
D: 13,
|
||||
E: 14,
|
||||
F: 15,
|
||||
};
|
||||
|
||||
export function hexToUint8Array(hexString) {
|
||||
assertString(hexString);
|
||||
|
||||
if (hexString.length % 2 !== 0) {
|
||||
throw new Error("Invalid Hex string length.");
|
||||
}
|
||||
|
||||
const resultLength = hexString.length / 2;
|
||||
const bytes = new Uint8Array(resultLength);
|
||||
|
||||
for (let index = 0; index < resultLength; index++) {
|
||||
const highNibble = hexToDecimalLookupTable[hexString[index * 2]];
|
||||
const lowNibble = hexToDecimalLookupTable[hexString[index * 2 + 1]];
|
||||
|
||||
if (highNibble === undefined || lowNibble === undefined) {
|
||||
throw new Error(
|
||||
`Invalid Hex character encountered at position ${index * 2}`,
|
||||
);
|
||||
}
|
||||
|
||||
bytes[index] = (highNibble << 4) | lowNibble; // eslint-disable-line no-bitwise
|
||||
}
|
||||
|
||||
return bytes;
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
export async function universalCrypto(): Promise<Crypto> {
|
||||
if ("crypto" in globalThis) {
|
||||
return globalThis.crypto;
|
||||
}
|
||||
|
||||
// otherwise we are in node 18 so we can use `webcrypto` off of the "node:crypto" package and treat it as native
|
||||
// trick bundlers so that they leave this alone :)
|
||||
const pto = "pto";
|
||||
// this becomes `node:crypto` at runtime
|
||||
return (await import("node" + ":cry" + pto)).webcrypto as Crypto;
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
import { aesEncrypt, aesDecrypt, aesDecryptCompat } from "../src";
|
||||
|
||||
import { AES } from "crypto-js";
|
||||
|
||||
describe("AES", () => {
|
||||
describe("modern", () => {
|
||||
it("should properly encrypt and decrypt", async () => {
|
||||
const plaintext = "my secret text";
|
||||
const password = "pw";
|
||||
const ciphertext = await aesEncrypt(plaintext, password);
|
||||
const decrypted = await aesDecrypt(ciphertext, password);
|
||||
expect(decrypted).toEqual(plaintext);
|
||||
});
|
||||
|
||||
it("should not decypt if password is wrong", async () => {
|
||||
const plaintext = "my secret text";
|
||||
const password = "pw";
|
||||
const wrongPassword = "wrong";
|
||||
const ciphertext = await aesEncrypt(plaintext, password);
|
||||
let decrypted = "";
|
||||
try {
|
||||
decrypted = await aesDecrypt(ciphertext, wrongPassword);
|
||||
} catch (err) {
|
||||
expect(err.message).toEqual("Decrypt failed");
|
||||
}
|
||||
expect(decrypted).not.toEqual(plaintext);
|
||||
});
|
||||
|
||||
it("should not decrypt legacy crypto-js ciphertext using aesDecrypt", async () => {
|
||||
const plaintext = "my secret text";
|
||||
const password = "pw";
|
||||
const ciphertext = AES.encrypt(plaintext, password).toString();
|
||||
let decrypted = "";
|
||||
try {
|
||||
decrypted = await aesDecrypt(ciphertext, password);
|
||||
} catch (err) {
|
||||
expect(err.message).toEqual("Decrypt failed");
|
||||
}
|
||||
expect(decrypted).not.toEqual(plaintext);
|
||||
});
|
||||
});
|
||||
|
||||
describe("compat (crypto-js decrypt support)", () => {
|
||||
it("should properly decrypt legacy crypto-js ciphertext when using aesDecryptCompat", async () => {
|
||||
const plaintext = "my secret text";
|
||||
const password = "pw";
|
||||
const ciphertext = AES.encrypt(plaintext, password).toString();
|
||||
const decrypted = await aesDecryptCompat(ciphertext, password);
|
||||
expect(decrypted).toEqual(plaintext);
|
||||
});
|
||||
|
||||
it("should not decypt if password is wrong using decrypt legacy crypto-js ciphertext when using aesDecryptCompat", async () => {
|
||||
const plaintext = "my secret text";
|
||||
const password = "pw";
|
||||
const wrongPassword = "wrong";
|
||||
const ciphertext = AES.encrypt(plaintext, password).toString();
|
||||
let decrypted = "";
|
||||
try {
|
||||
decrypted = await aesDecryptCompat(ciphertext, wrongPassword);
|
||||
} catch (err) {
|
||||
expect(err.message).toEqual("Decrypt failed");
|
||||
}
|
||||
expect(decrypted).not.toEqual(plaintext);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,30 @@
|
||||
import {
|
||||
keccak256SyncHex,
|
||||
keccak256SyncHexPrefixed,
|
||||
keccak256Sync,
|
||||
} from "../src";
|
||||
import { utils } from "ethers";
|
||||
import { keccak_256 } from "@noble/hashes/sha3";
|
||||
import { uint8ArrayToHex } from "../src/utils/uint8array-extras";
|
||||
|
||||
const STRING_TO_HASH = "hello world";
|
||||
|
||||
describe("keccak256", () => {
|
||||
it("keccak256SyncHexPrefixed === ethers.utils.keccak256", async () => {
|
||||
const out = keccak256SyncHexPrefixed(STRING_TO_HASH);
|
||||
const ethersOut = utils.keccak256(Buffer.from(STRING_TO_HASH));
|
||||
|
||||
expect(out).toEqual(ethersOut);
|
||||
});
|
||||
it("keccak256SyncHex === @noble/hashes: keccak_256 -> hex", async () => {
|
||||
const out = keccak256SyncHex(STRING_TO_HASH);
|
||||
const nobleOut = uint8ArrayToHex(keccak_256(STRING_TO_HASH));
|
||||
expect(out).toEqual(nobleOut);
|
||||
});
|
||||
|
||||
it("keccak256Sync === @noble/hashes: keccak_256", async () => {
|
||||
const out = keccak256Sync(STRING_TO_HASH);
|
||||
const nobleOut = keccak_256(STRING_TO_HASH);
|
||||
expect(out).toEqual(nobleOut);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,30 @@
|
||||
import { sha256, sha256Hex, sha256Sync, sha256HexSync } from "../src";
|
||||
import { createHash } from "node:crypto";
|
||||
|
||||
const STRING_TO_HASH = "hello world";
|
||||
|
||||
describe("sha256", () => {
|
||||
it("sha256", async () => {
|
||||
const out = await sha256(STRING_TO_HASH);
|
||||
const hash = createHash("sha256").update(STRING_TO_HASH).digest();
|
||||
expect(out).toEqual(hash);
|
||||
});
|
||||
|
||||
it("sha256 -> hex", async () => {
|
||||
const out = await sha256Hex(STRING_TO_HASH);
|
||||
const hash = createHash("sha256").update(STRING_TO_HASH).digest("hex");
|
||||
expect(out).toEqual(hash);
|
||||
});
|
||||
|
||||
it("sha256Sync", async () => {
|
||||
const out = sha256Sync(STRING_TO_HASH);
|
||||
const hash = createHash("sha256").update(STRING_TO_HASH).digest();
|
||||
expect(out).toEqual(hash);
|
||||
});
|
||||
|
||||
it("sha256Sync -> hex", async () => {
|
||||
const out = sha256HexSync(STRING_TO_HASH);
|
||||
const hash = createHash("sha256").update(STRING_TO_HASH).digest("hex");
|
||||
expect(out).toEqual(hash);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"extends": "@thirdweb-dev/tsconfig/sdk.json",
|
||||
"include": ["src", "types"],
|
||||
"exclude": ["dist", "build", "node_modules"]
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"presets": [
|
||||
"@babel/preset-typescript",
|
||||
["@babel/preset-env", { "targets": "defaults, not ie 11" }]
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
# folders
|
||||
dist/
|
||||
|
||||
# files
|
||||
@@ -0,0 +1,4 @@
|
||||
module.exports = {
|
||||
root: true,
|
||||
extends: ["thirdweb"],
|
||||
};
|
||||
@@ -0,0 +1,12 @@
|
||||
# @thirdweb-dev/merkletree
|
||||
|
||||
## 0.2.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- [#1861](https://github.com/thirdweb-dev/js/pull/1861) [`ab2dfd4f`](https://github.com/thirdweb-dev/js/commit/ab2dfd4f5cf4256fa62d76f84ca804992afab1e4) Thanks [@jnsdls](https://github.com/jnsdls)! - initial release
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`ab2dfd4f`](https://github.com/thirdweb-dev/js/commit/ab2dfd4f5cf4256fa62d76f84ca804992afab1e4)]:
|
||||
- @thirdweb-dev/crypto@0.2.0
|
||||
@@ -0,0 +1,16 @@
|
||||
<p align="center">
|
||||
<br />
|
||||
<a href="https://thirdweb.com"><img src="https://github.com/thirdweb-dev/js/blob/main/packages/sdk/logo.svg?raw=true" width="200" alt=""/></a>
|
||||
<br />
|
||||
</p>
|
||||
<h1 align="center">thirdweb merkletree</h1>
|
||||
<p align="center">
|
||||
<a href="https://www.npmjs.com/package/@thirdweb-dev/merkletree"><img src="https://img.shields.io/npm/v/@thirdweb-dev/merkletree?color=red&label=npm&logo=npm" alt="npm version"/></a>
|
||||
<a href="https://github.com/thirdweb-dev/js/actions/workflows/build-test-lint.yml"><img alt="Build Status" src="https://github.com/thirdweb-dev/js/actions/workflows/build-test-lint.yml/badge.svg"/></a>
|
||||
<a href="https://discord.gg/thirdweb"><img alt="Join our Discord!" src="https://img.shields.io/discord/834227967404146718.svg?color=7289da&label=discord&logo=discord&style=flat"/></a>
|
||||
|
||||
</p>
|
||||
<!-- <p align="center"><strong>Best in class Web3 SDK for Browser, Node and Mobile apps</strong></p> -->
|
||||
<br />
|
||||
|
||||
### todo
|
||||
@@ -0,0 +1,60 @@
|
||||
{
|
||||
"name": "@thirdweb-dev/merkletree",
|
||||
"version": "0.2.0",
|
||||
"main": "dist/thirdweb-dev-merkletree.cjs.js",
|
||||
"module": "dist/thirdweb-dev-merkletree.esm.js",
|
||||
"exports": {
|
||||
".": {
|
||||
"module": "./dist/thirdweb-dev-merkletree.esm.js",
|
||||
"default": "./dist/thirdweb-dev-merkletree.cjs.js"
|
||||
},
|
||||
"./package.json": "./package.json"
|
||||
},
|
||||
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/utils",
|
||||
"license": "Apache-2.0",
|
||||
"bugs": {
|
||||
"url": "https://github.com/thirdweb-dev/js/issues"
|
||||
},
|
||||
"author": "thirdweb eng <[email protected]>",
|
||||
"files": [
|
||||
"dist/"
|
||||
],
|
||||
"preconstruct": {
|
||||
"entrypoints": [
|
||||
"index.ts"
|
||||
],
|
||||
"exports": true
|
||||
},
|
||||
"sideEffects": false,
|
||||
"dependencies": {
|
||||
"@thirdweb-dev/crypto": "workspace:*",
|
||||
"buffer": "^6.0.3",
|
||||
"buffer-reverse": "^1.0.1",
|
||||
"treeify": "^1.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@preconstruct/cli": "2.7.0",
|
||||
"@thirdweb-dev/tsconfig": "workspace:*",
|
||||
"@types/benchmark": "^2.1.4",
|
||||
"@types/treeify": "^1.0.2",
|
||||
"benchmark": "^2.1.4",
|
||||
"eslint-config-thirdweb": "workspace:*",
|
||||
"typescript": "^5.1.6"
|
||||
},
|
||||
"scripts": {
|
||||
"format": "prettier --write 'src/**/*'",
|
||||
"lint": "eslint src/ && bunx publint --strict --level warning",
|
||||
"fix": "eslint src/ --fix",
|
||||
"clean": "rm -rf dist/",
|
||||
"build": "tsc && preconstruct build",
|
||||
"push": "yalc push",
|
||||
"test": "bun test",
|
||||
"benchmark:aes-encrypt": "bun benchmark/aes-encrypt.ts",
|
||||
"benchmark:aes-decrypt": "bun benchmark/aes-decrypt.ts",
|
||||
"benchmark:sha256": "bun benchmark/sha256.ts",
|
||||
"benchmark": "bun run benchmark:aes-encrypt && bun run benchmark:aes-decrypt && bun run benchmark:sha256"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export { MerkleTree } from "./merkletree/MerkleTree";
|
||||
@@ -0,0 +1,441 @@
|
||||
// ADAPTED FROM https://github.com/merkletreejs/merkletreejs
|
||||
|
||||
import { Buffer } from "buffer";
|
||||
|
||||
export class Base {
|
||||
/**
|
||||
* print
|
||||
* @desc Prints out a visual representation of the merkle tree.
|
||||
* @example
|
||||
*```js
|
||||
*tree.print()
|
||||
*```
|
||||
*/
|
||||
print(): void {
|
||||
Base.print(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* bufferIndexOf
|
||||
* @desc Returns the first index of which given buffer is found in array.
|
||||
* @param {Buffer[]} haystack - Array of buffers.
|
||||
* @param {Buffer} needle - Buffer to find.
|
||||
* @return {Number} - Index number
|
||||
*
|
||||
* @example
|
||||
* ```js
|
||||
*const index = tree.bufferIndexOf(haystack, needle)
|
||||
*```
|
||||
*/
|
||||
protected bufferIndexOf(
|
||||
array: Buffer[],
|
||||
element: Buffer,
|
||||
isSorted: boolean = false,
|
||||
): number {
|
||||
if (isSorted) {
|
||||
return this.binarySearch(array, element, Buffer.compare);
|
||||
}
|
||||
|
||||
const eqChecker = (buffer1: Buffer, buffer2: Buffer) =>
|
||||
buffer1.equals(buffer2);
|
||||
return this.linearSearch(array, element, eqChecker);
|
||||
}
|
||||
|
||||
/**
|
||||
* binarySearch
|
||||
* @desc Returns the first index of which given item is found in array using binary search.
|
||||
* @param {Buffer[]} array - Array of items.
|
||||
* @param {Buffer} element - Item to find.
|
||||
* @param {Function} compareFunction
|
||||
* @return {Number} - Index number
|
||||
*
|
||||
* @example
|
||||
* ```js
|
||||
*const index = MerkleTree.binarySearch(array, element, Buffer.compare)
|
||||
*```
|
||||
*/
|
||||
static binarySearch(
|
||||
array: Buffer[],
|
||||
element: Buffer,
|
||||
compareFunction: (a: Buffer, b: Buffer) => number,
|
||||
): number {
|
||||
let start = 0;
|
||||
let end = array.length - 1;
|
||||
|
||||
// Iterate while start not meets end
|
||||
while (start <= end) {
|
||||
// Find the mid index
|
||||
const mid = Math.floor((start + end) / 2);
|
||||
|
||||
// Check if the mid value is greater than, equal to, or less than search element.
|
||||
const ordering = compareFunction(array[mid], element);
|
||||
|
||||
// If element is present at mid, start iterating for searching first appearance.
|
||||
if (ordering === 0) {
|
||||
// Linear reverse iteration until the first matching item index is found.
|
||||
for (let i = mid - 1; i >= 0; i--) {
|
||||
if (compareFunction(array[i], element) === 0) {
|
||||
continue;
|
||||
}
|
||||
return i + 1;
|
||||
}
|
||||
return 0;
|
||||
} /* Else look in left or right half accordingly */ else if (
|
||||
ordering < 0
|
||||
) {
|
||||
start = mid + 1;
|
||||
} else {
|
||||
end = mid - 1;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* binarySearch
|
||||
* @desc Returns the first index of which given item is found in array using binary search.
|
||||
* @param {Buffer[]} array - Array of items.
|
||||
* @param {Buffer} element - Item to find.
|
||||
* @param {Function} compareFunction
|
||||
* @return {Number} - Index number
|
||||
*
|
||||
* @example
|
||||
* ```js
|
||||
*const index = tree.binarySearch(array, element, Buffer.compare)
|
||||
*```
|
||||
*/
|
||||
binarySearch(
|
||||
array: Buffer[],
|
||||
element: Buffer,
|
||||
compareFunction: (a: Buffer, b: Buffer) => number,
|
||||
): number {
|
||||
return Base.binarySearch(array, element, compareFunction);
|
||||
}
|
||||
|
||||
/**
|
||||
* linearSearch
|
||||
* @desc Returns the first index of which given item is found in array using linear search.
|
||||
* @param {Buffer[]} array - Array of items.
|
||||
* @param {Buffer} element - Item to find.
|
||||
* @param {Function} eqChecker
|
||||
* @return {Number} - Index number
|
||||
*
|
||||
* @example
|
||||
* ```js
|
||||
*const index = MerkleTree.linearSearch(array, element, (a, b) => a === b)
|
||||
*```
|
||||
*/
|
||||
static linearSearch(
|
||||
array: Buffer[],
|
||||
element: Buffer,
|
||||
eqChecker: (a: Buffer, b: Buffer) => boolean,
|
||||
): number {
|
||||
for (let i = 0; i < array.length; i++) {
|
||||
if (eqChecker(array[i], element)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* linearSearch
|
||||
* @desc Returns the first index of which given item is found in array using linear search.
|
||||
* @param {Buffer[]} array - Array of items.
|
||||
* @param {Buffer} element - Item to find.
|
||||
* @param {Function} eqChecker
|
||||
* @return {Number} - Index number
|
||||
*
|
||||
* @example
|
||||
* ```js
|
||||
*const index = tree.linearSearch(array, element, (a, b) => a === b)
|
||||
*```
|
||||
*/
|
||||
linearSearch(
|
||||
array: Buffer[],
|
||||
element: Buffer,
|
||||
eqChecker: (a: Buffer, b: Buffer) => boolean,
|
||||
): number {
|
||||
return Base.linearSearch(array, element, eqChecker);
|
||||
}
|
||||
|
||||
/**
|
||||
* bufferify
|
||||
* @desc Returns a buffer type for the given value.
|
||||
* @param {String|Number|Object|Buffer|ArrayBuffer} value
|
||||
* @return {Buffer}
|
||||
*
|
||||
* @example
|
||||
* ```js
|
||||
*const buf = MerkleTree.bufferify('0x1234')
|
||||
*```
|
||||
*/
|
||||
static bufferify(value: any): Buffer {
|
||||
if (!Buffer.isBuffer(value)) {
|
||||
// crypto-js support
|
||||
if (typeof value === "object" && value.words) {
|
||||
return Buffer.from(value.toString(convertWordsToBuffer), "hex");
|
||||
} else if (Base.isHexString(value)) {
|
||||
return Buffer.from(value.replace(/^0x/, ""), "hex");
|
||||
} else if (typeof value === "string") {
|
||||
return Buffer.from(value);
|
||||
} else if (typeof value === "bigint") {
|
||||
return Buffer.from(value.toString(16), "hex");
|
||||
} else if (value instanceof Uint8Array) {
|
||||
return Buffer.from(value.buffer);
|
||||
} else if (typeof value === "number") {
|
||||
let s = value.toString();
|
||||
if (s.length % 2) {
|
||||
s = `0${s}`;
|
||||
}
|
||||
return Buffer.from(s, "hex");
|
||||
} else if (ArrayBuffer.isView(value)) {
|
||||
return Buffer.from(value.buffer, value.byteOffset, value.byteLength);
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
bigNumberify(value: any): bigint {
|
||||
return Base.bigNumberify(value);
|
||||
}
|
||||
|
||||
static bigNumberify(value: any): bigint {
|
||||
if (typeof value === "bigint") {
|
||||
return value;
|
||||
}
|
||||
|
||||
if (typeof value === "string") {
|
||||
if (value.startsWith("0x") && Base.isHexString(value)) {
|
||||
return BigInt("0x" + value.replace("0x", "").toString());
|
||||
}
|
||||
return BigInt(value);
|
||||
}
|
||||
|
||||
if (Buffer.isBuffer(value)) {
|
||||
return BigInt("0x" + value.toString("hex"));
|
||||
}
|
||||
|
||||
if (value instanceof Uint8Array) {
|
||||
return uint8ArrayToBigInt(value);
|
||||
}
|
||||
|
||||
if (typeof value === "number") {
|
||||
return BigInt(value);
|
||||
}
|
||||
|
||||
throw new Error("cannot bigNumberify");
|
||||
}
|
||||
|
||||
/**
|
||||
* isHexString
|
||||
* @desc Returns true if value is a hex string.
|
||||
* @param {String} value
|
||||
* @return {Boolean}
|
||||
*
|
||||
* @example
|
||||
* ```js
|
||||
*console.log(MerkleTree.isHexString('0x1234'))
|
||||
*```
|
||||
*/
|
||||
static isHexString(v: string): boolean {
|
||||
return typeof v === "string" && /^(0x)?[0-9A-Fa-f]*$/.test(v);
|
||||
}
|
||||
|
||||
/**
|
||||
* print
|
||||
* @desc Prints out a visual representation of the given merkle tree.
|
||||
* @param {Object} tree - Merkle tree instance.
|
||||
* @return {String}
|
||||
* @example
|
||||
*```js
|
||||
*MerkleTree.print(tree)
|
||||
*```
|
||||
*/
|
||||
static print(tree: any): void {
|
||||
console.log(tree.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* bufferToHex
|
||||
* @desc Returns a hex string with 0x prefix for given buffer.
|
||||
* @param {Buffer} value
|
||||
* @return {String}
|
||||
* @example
|
||||
*```js
|
||||
*const hexStr = tree.bufferToHex(Buffer.from('A'))
|
||||
*```
|
||||
*/
|
||||
bufferToHex(value: Buffer, withPrefix: boolean = true): string {
|
||||
return Base.bufferToHex(value, withPrefix);
|
||||
}
|
||||
|
||||
/**
|
||||
* bufferToHex
|
||||
* @desc Returns a hex string with 0x prefix for given buffer.
|
||||
* @param {Buffer} value
|
||||
* @return {String}
|
||||
* @example
|
||||
*```js
|
||||
*const hexStr = MerkleTree.bufferToHex(Buffer.from('A'))
|
||||
*```
|
||||
*/
|
||||
static bufferToHex(value: Buffer, withPrefix: boolean = true): string {
|
||||
return `${withPrefix ? "0x" : ""}${(value || Buffer.alloc(0)).toString(
|
||||
"hex",
|
||||
)}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* bufferify
|
||||
* @desc Returns a buffer type for the given value.
|
||||
* @param {String|Number|Object|Buffer} value
|
||||
* @return {Buffer}
|
||||
*
|
||||
* @example
|
||||
* ```js
|
||||
*const buf = tree.bufferify('0x1234')
|
||||
*```
|
||||
*/
|
||||
bufferify(value: any): Buffer {
|
||||
return Base.bufferify(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* bufferifyFn
|
||||
* @desc Returns a function that will bufferify the return value.
|
||||
* @param {Function}
|
||||
* @return {Function}
|
||||
*
|
||||
* @example
|
||||
* ```js
|
||||
*const fn = tree.bufferifyFn((value) => sha256(value))
|
||||
*```
|
||||
*/
|
||||
bufferifyFn(f: any): any {
|
||||
return (value: any): Buffer => {
|
||||
const v = f(value);
|
||||
if (Buffer.isBuffer(v)) {
|
||||
return v;
|
||||
}
|
||||
|
||||
if (this.isHexString(v)) {
|
||||
return Buffer.from(v.replace("0x", ""), "hex");
|
||||
}
|
||||
|
||||
if (typeof v === "string") {
|
||||
return Buffer.from(v);
|
||||
}
|
||||
|
||||
if (typeof v === "bigint") {
|
||||
return Buffer.from(value.toString(16), "hex");
|
||||
}
|
||||
|
||||
if (ArrayBuffer.isView(v)) {
|
||||
return Buffer.from(v.buffer, v.byteOffset, v.byteLength);
|
||||
}
|
||||
|
||||
// crypto-js support
|
||||
const arrayBuffer = hexStringToArrayBuffer(value.toString("hex"));
|
||||
// Assuming f now works with ArrayBuffers
|
||||
const processedBuffer = f(arrayBuffer);
|
||||
|
||||
const hexResult = arrayBufferToHexString(processedBuffer);
|
||||
|
||||
return Buffer.from(hexResult, "hex");
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* isHexString
|
||||
* @desc Returns true if value is a hex string.
|
||||
* @param {String} value
|
||||
* @return {Boolean}
|
||||
*
|
||||
* @example
|
||||
* ```js
|
||||
*console.log(MerkleTree.isHexString('0x1234'))
|
||||
*```
|
||||
*/
|
||||
protected isHexString(value: string): boolean {
|
||||
return Base.isHexString(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* log2
|
||||
* @desc Returns the log2 of number.
|
||||
* @param {Number} value
|
||||
* @return {Number}
|
||||
*/
|
||||
protected log2(n: number): number {
|
||||
return n === 1 ? 0 : 1 + this.log2((n / 2) | 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* zip
|
||||
* @desc Returns true if value is a hex string.
|
||||
* @param {String[]|Number[]|Buffer[]} a - first array
|
||||
* @param {String[]|Number[]|Buffer[]} b - second array
|
||||
* @return {String[][]|Number[][]|Buffer[][]}
|
||||
*
|
||||
* @example
|
||||
* ```js
|
||||
*const zipped = tree.zip(['a', 'b'],['A', 'B'])
|
||||
*console.log(zipped) // [ [ 'a', 'A' ], [ 'b', 'B' ] ]
|
||||
*```
|
||||
*/
|
||||
protected zip(a: any[], b: any[]): any[][] {
|
||||
return a.map((e, i) => [e, b[i]]);
|
||||
}
|
||||
|
||||
static hexZeroPad(hexStr: string, length: number) {
|
||||
return "0x" + hexStr.replace("0x", "").padStart(length, "0");
|
||||
}
|
||||
}
|
||||
|
||||
export default Base;
|
||||
|
||||
// UTILS
|
||||
|
||||
// replaces CryptoJS.enc.Hex
|
||||
function convertWordsToBuffer(value: { words: any }) {
|
||||
const wordArray = value.words;
|
||||
const arrayBuffer = new ArrayBuffer(wordArray.length * 4); // 4 bytes per word
|
||||
const uint8View = new Uint8Array(arrayBuffer);
|
||||
|
||||
for (let i = 0; i < wordArray.length; i++) {
|
||||
uint8View[i * 4] = (wordArray[i] >> 24) & 0xff;
|
||||
uint8View[i * 4 + 1] = (wordArray[i] >> 16) & 0xff;
|
||||
uint8View[i * 4 + 2] = (wordArray[i] >> 8) & 0xff;
|
||||
uint8View[i * 4 + 3] = wordArray[i] & 0xff;
|
||||
}
|
||||
|
||||
return arrayBuffer;
|
||||
}
|
||||
|
||||
function hexStringToArrayBuffer(hexString: string) {
|
||||
const buffer = new Uint8Array(hexString.length / 2);
|
||||
|
||||
for (let i = 0; i < hexString.length; i += 2) {
|
||||
buffer[i / 2] = parseInt(hexString.substring(i, i + 2), 16);
|
||||
}
|
||||
|
||||
return buffer.buffer;
|
||||
}
|
||||
|
||||
function arrayBufferToHexString(arrayBuffer: ArrayBuffer) {
|
||||
const uint8View = new Uint8Array(arrayBuffer);
|
||||
return Array.from(uint8View)
|
||||
.map((byte) => byte.toString(16).padStart(2, "0"))
|
||||
.join("");
|
||||
}
|
||||
|
||||
function uint8ArrayToBigInt(u8a: Uint8Array) {
|
||||
const hex = Array.from(u8a)
|
||||
.map((byte) => byte.toString(16).padStart(2, "0"))
|
||||
.join("");
|
||||
return BigInt(`0x${hex}`);
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,199 @@
|
||||
import { MerkleTree } from "../src/index";
|
||||
import { keccak256Sync, sha256Sync } from "@thirdweb-dev/crypto";
|
||||
|
||||
describe("MerkleTree", () => {
|
||||
it("sha256 with keccak256 leaves", () => {
|
||||
const leaves = ["a", "b", "c"].map(keccak256Sync);
|
||||
const tree = new MerkleTree(leaves, sha256Sync);
|
||||
|
||||
// check equality of the roots
|
||||
expect(tree.getHexRoot()).toMatchSnapshot();
|
||||
// check equality of the leaves
|
||||
expect(tree.getHexLeaves()).toMatchSnapshot();
|
||||
// check equality of the layers
|
||||
expect(tree.getHexLayers()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("sha256 with keccak256 leaves with duplicate odd option", () => {
|
||||
const leaves = ["a", "b", "c"].map(keccak256Sync);
|
||||
const tree = new MerkleTree(leaves, sha256Sync, { duplicateOdd: true });
|
||||
|
||||
// check equality of the roots
|
||||
expect(tree.getHexRoot()).toMatchSnapshot();
|
||||
// check equality of the leaves
|
||||
expect(tree.getHexLeaves()).toMatchSnapshot();
|
||||
// check equality of the layers
|
||||
expect(tree.getHexLayers()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("sha256 with sort pairs option", () => {
|
||||
const leaves = ["a", "b", "c", "d", "e", "f"].map(sha256Sync);
|
||||
const tree = new MerkleTree(leaves, sha256Sync, { sortPairs: true });
|
||||
|
||||
// check equality of the roots
|
||||
expect(tree.getHexRoot()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("sha256 verify with positional hex proof and no pairSort", () => {
|
||||
const leaves = ["a", "b", "c", "d", "e", "f"].map(sha256Sync);
|
||||
const tree = new MerkleTree(leaves, sha256Sync, { sortPairs: false });
|
||||
|
||||
expect(
|
||||
tree.verify(
|
||||
// TODO: accept Uint8Array as input
|
||||
tree.getProof(Buffer.from(leaves[1]), 1),
|
||||
// TODO: accept Uint8Array as input
|
||||
Buffer.from(leaves[1]),
|
||||
tree.getHexRoot(),
|
||||
),
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
test("sha256 verify with non-hex proof and no pairSort", () => {
|
||||
const leaves = ["a", "b", "c", "d", "e", "f"].map(sha256Sync);
|
||||
const tree = new MerkleTree(leaves, sha256Sync, { sortPairs: false });
|
||||
|
||||
expect(
|
||||
tree.verify(
|
||||
// TODO: accept Uint8Array as input
|
||||
tree.getProof(Buffer.from(leaves[1]), 1),
|
||||
// TODO: accept Uint8Array as input
|
||||
Buffer.from(leaves[1]),
|
||||
tree.getHexRoot(),
|
||||
),
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
it("sha256 verify with hex proof and pairSort", () => {
|
||||
const leaves = ["a", "b", "c", "d", "e", "f"].map(sha256Sync);
|
||||
const tree = new MerkleTree(leaves, sha256Sync, { sortPairs: true });
|
||||
|
||||
expect(
|
||||
tree.verify(
|
||||
// TODO: accept Uint8Array as input
|
||||
tree.getHexProof(Buffer.from(leaves[1]), 1),
|
||||
// TODO: accept Uint8Array as input
|
||||
Buffer.from(leaves[1]),
|
||||
tree.getHexRoot(),
|
||||
),
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
it("keccak256 with sort leaves and sort pairs option", () => {
|
||||
const leaves = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j"].map(
|
||||
keccak256Sync,
|
||||
);
|
||||
const tree = new MerkleTree(leaves, keccak256Sync, {
|
||||
sortLeaves: true,
|
||||
sortPairs: true,
|
||||
});
|
||||
|
||||
// check equality of the roots
|
||||
expect(tree.getHexRoot()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("keccak256 with sort option", () => {
|
||||
const leaves = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j"].map(
|
||||
keccak256Sync,
|
||||
);
|
||||
const tree = new MerkleTree(leaves, keccak256Sync, { sort: true });
|
||||
|
||||
// check equality of the roots
|
||||
expect(tree.getHexRoot()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("sha256 with sha256 leaves and sort pairs option and duplicate odd option", () => {
|
||||
const leaves = ["a", "b", "c", "d", "e", "f"].map(sha256Sync);
|
||||
const tree = new MerkleTree(leaves, sha256Sync, {
|
||||
sortPairs: true,
|
||||
duplicateOdd: true,
|
||||
});
|
||||
|
||||
// check equality of the roots
|
||||
expect(tree.getHexRoot()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("sha256 with hash leaves option", () => {
|
||||
const expectedRoot =
|
||||
"0x1f7379539707bcaea00564168d1d4d626b09b73f8a2a365234c62d763f854da2";
|
||||
|
||||
const leaves = ["a", "b", "c", "d", "e", "f"];
|
||||
const tree1 = new MerkleTree(leaves, sha256Sync, { hashLeaves: true });
|
||||
expect(tree1.getHexRoot()).toEqual(expectedRoot);
|
||||
|
||||
const hashedLeaves = ["a", "b", "c", "d", "e", "f"].map(sha256Sync);
|
||||
const tree2 = new MerkleTree(hashedLeaves, sha256Sync);
|
||||
expect(tree2.getHexRoot()).toEqual(expectedRoot);
|
||||
});
|
||||
|
||||
it("sha256 with hash leaves option and duplicate odd option", () => {
|
||||
const leaves = ["a", "b", "c", "d", "e", "f"];
|
||||
const tree = new MerkleTree(leaves, sha256Sync, {
|
||||
hashLeaves: true,
|
||||
duplicateOdd: true,
|
||||
});
|
||||
const root =
|
||||
"44205acec5156114821f1f71d87c72e0de395633cd1589def6d4444cc79f8103";
|
||||
|
||||
expect(tree.getRoot().toString("hex")).toEqual(root);
|
||||
});
|
||||
|
||||
it("solidity keccak256", () => {
|
||||
const leaves = ["a", "b", "c"].map(keccak256Sync);
|
||||
|
||||
const a_hash =
|
||||
"3ac225168df54212a25c1c01fd35bebfea408fdac2e31ddd6f80a4bbf9a5f1cb";
|
||||
const b_hash =
|
||||
"b5553de315e0edf504d9150af82dafa5c4667fa618ed0a6f19c69b41166c5510";
|
||||
const c_hash =
|
||||
"0b42b6393c1f53060fe3ddbfcd7aadcca894465a5a438f69c87d790b2299b9b2";
|
||||
|
||||
expect(leaves.map((l) => Buffer.from(l).toString("hex"))).toEqual([
|
||||
a_hash,
|
||||
b_hash,
|
||||
c_hash,
|
||||
]);
|
||||
|
||||
const tree = new MerkleTree(leaves, keccak256Sync);
|
||||
|
||||
const layers = tree.getLayers().slice(1); // no leaves
|
||||
|
||||
const layer_1 = Buffer.from(
|
||||
keccak256Sync(Buffer.concat([leaves[0], leaves[1]])),
|
||||
).toString("hex");
|
||||
|
||||
expect(layers[0][0].toString("hex")).toEqual(layer_1);
|
||||
expect(layers[0][1].toString("hex")).toEqual(c_hash);
|
||||
|
||||
const root = Buffer.from(
|
||||
"aff1208e69c9e8be9b584b07ebac4e48a1ee9d15ce3afe20b77a4d29e4175aa3",
|
||||
"hex",
|
||||
);
|
||||
expect(tree.getRoot().toString("hex")).toEqual(root.toString("hex"));
|
||||
|
||||
const proof_0 = tree.getProof(Buffer.from(leaves[0]));
|
||||
expect(proof_0.length).toEqual(2);
|
||||
expect(proof_0[0].position).toEqual("right");
|
||||
expect(proof_0[0].data.toString("hex")).toEqual(b_hash);
|
||||
expect(proof_0[1].position).toEqual("right");
|
||||
expect(proof_0[1].data.toString("hex")).toEqual(c_hash);
|
||||
|
||||
expect(tree.verify(proof_0, Buffer.from(leaves[0]), root)).toBe(true);
|
||||
|
||||
const proof_1 = tree.getProof(Buffer.from(leaves[1]));
|
||||
expect(proof_1.length).toEqual(2);
|
||||
expect(proof_1[0].position).toEqual("left");
|
||||
expect(proof_1[0].data.toString("hex")).toEqual(a_hash);
|
||||
expect(proof_1[1].position).toEqual("right");
|
||||
expect(proof_1[1].data.toString("hex")).toEqual(c_hash);
|
||||
|
||||
expect(tree.verify(proof_1, Buffer.from(leaves[1]), root)).toBe(true);
|
||||
|
||||
const proof_2 = tree.getProof(Buffer.from(leaves[2]));
|
||||
expect(proof_2.length).toEqual(1);
|
||||
expect(proof_2[0].position).toEqual("left");
|
||||
expect(proof_2[0].data.toString("hex")).toEqual(layer_1);
|
||||
|
||||
expect(tree.verify(proof_2, Buffer.from(leaves[2]), root)).toBe(true);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,63 @@
|
||||
// Bun Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`MerkleTree sha256 with keccak256 leaves 1`] = `"0x311d2e46f49b15fff8b746b74ad57f2cc9e0d9939fda94387141a2d3fdf187ae"`;
|
||||
|
||||
exports[`MerkleTree sha256 with keccak256 leaves 2`] = `
|
||||
[
|
||||
"0x3ac225168df54212a25c1c01fd35bebfea408fdac2e31ddd6f80a4bbf9a5f1cb",
|
||||
"0xb5553de315e0edf504d9150af82dafa5c4667fa618ed0a6f19c69b41166c5510",
|
||||
"0x0b42b6393c1f53060fe3ddbfcd7aadcca894465a5a438f69c87d790b2299b9b2",
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`MerkleTree sha256 with keccak256 leaves 3`] = `
|
||||
[
|
||||
[
|
||||
"0x3ac225168df54212a25c1c01fd35bebfea408fdac2e31ddd6f80a4bbf9a5f1cb",
|
||||
"0xb5553de315e0edf504d9150af82dafa5c4667fa618ed0a6f19c69b41166c5510",
|
||||
"0x0b42b6393c1f53060fe3ddbfcd7aadcca894465a5a438f69c87d790b2299b9b2",
|
||||
],
|
||||
[
|
||||
"0x176f0f307632fdd5831875eb709e2f68d770b102262998b214ddeb3f04164ae1",
|
||||
"0x0b42b6393c1f53060fe3ddbfcd7aadcca894465a5a438f69c87d790b2299b9b2",
|
||||
],
|
||||
[
|
||||
"0x311d2e46f49b15fff8b746b74ad57f2cc9e0d9939fda94387141a2d3fdf187ae",
|
||||
],
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`MerkleTree sha256 with keccak256 leaves with duplicate odd option 1`] = `"0xbcdd0f60308db788712205115fe4273bfda49fa0925611fee765a63df9ab96a1"`;
|
||||
|
||||
exports[`MerkleTree sha256 with keccak256 leaves with duplicate odd option 2`] = `
|
||||
[
|
||||
"0x3ac225168df54212a25c1c01fd35bebfea408fdac2e31ddd6f80a4bbf9a5f1cb",
|
||||
"0xb5553de315e0edf504d9150af82dafa5c4667fa618ed0a6f19c69b41166c5510",
|
||||
"0x0b42b6393c1f53060fe3ddbfcd7aadcca894465a5a438f69c87d790b2299b9b2",
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`MerkleTree sha256 with keccak256 leaves with duplicate odd option 3`] = `
|
||||
[
|
||||
[
|
||||
"0x3ac225168df54212a25c1c01fd35bebfea408fdac2e31ddd6f80a4bbf9a5f1cb",
|
||||
"0xb5553de315e0edf504d9150af82dafa5c4667fa618ed0a6f19c69b41166c5510",
|
||||
"0x0b42b6393c1f53060fe3ddbfcd7aadcca894465a5a438f69c87d790b2299b9b2",
|
||||
],
|
||||
[
|
||||
"0x176f0f307632fdd5831875eb709e2f68d770b102262998b214ddeb3f04164ae1",
|
||||
"0x43e061172b1177f25d0f156b2d2ed11728006fade8e167ff3d1b9dbc979a3358",
|
||||
],
|
||||
[
|
||||
"0xbcdd0f60308db788712205115fe4273bfda49fa0925611fee765a63df9ab96a1",
|
||||
],
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`MerkleTree sha256 with sort pairs option 1`] = `"0xa30ba95a1a5dc397fe45ea20105363b08d682b864a28f4940419a29349a28325"`;
|
||||
|
||||
exports[`MerkleTree keccak256 with sort option 1`] = `"0x60219f87561939610b484575e45c6e81156a53b86d7cd16640d930d14f21758e"`;
|
||||
|
||||
exports[`MerkleTree sha256 with sha256 leaves and sort pairs option and duplicate odd option 1`] = `"0xa5260b2a7ec31584e5d5689a5628c2b3d949e2397334fd71c107478e5f887eaf"`;
|
||||
|
||||
exports[`MerkleTree keccak256 with sort leaves and sort pairs option 1`] = `"0x60219f87561939610b484575e45c6e81156a53b86d7cd16640d930d14f21758e"`;
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"extends": "@thirdweb-dev/tsconfig/sdk.json",
|
||||
"include": ["src", "types"],
|
||||
"exclude": ["dist", "build", "node_modules"]
|
||||
}
|
||||
@@ -43,7 +43,7 @@
|
||||
},
|
||||
"scripts": {
|
||||
"format": "prettier --write 'src/**/*'",
|
||||
"lint": "eslint src/",
|
||||
"lint": "eslint src/ && bunx publint --strict --level warning",
|
||||
"fix": "eslint src/ --fix",
|
||||
"clean": "rm -rf dist/",
|
||||
"build": "tsc && preconstruct build",
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
module.exports = {
|
||||
root: true,
|
||||
extends: ["thirdweb"],
|
||||
plugins: ["better-tree-shaking"],
|
||||
plugins: ["better-tree-shaking", "eslint-plugin-tsdoc"],
|
||||
rules: {
|
||||
"tsdoc/syntax": "error",
|
||||
"better-tree-shaking/no-top-level-side-effects": "error",
|
||||
},
|
||||
};
|
||||
|
||||
@@ -1,5 +1,70 @@
|
||||
# @thirdweb-dev/react-core
|
||||
|
||||
## 4.1.8
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`6832b19f`](https://github.com/thirdweb-dev/js/commit/6832b19fc5eedc7c17e69940a361840de0a84881), [`7abb36a7`](https://github.com/thirdweb-dev/js/commit/7abb36a7ec39766dd7da03015ccef401ef7a7863), [`1c4cbedb`](https://github.com/thirdweb-dev/js/commit/1c4cbedb6a3c9f9014ffbf83c02b998768958d96), [`e43beec3`](https://github.com/thirdweb-dev/js/commit/e43beec36a569211b6fe708107aa7dc04bff08ec)]:
|
||||
- @thirdweb-dev/wallets@2.1.7
|
||||
- @thirdweb-dev/sdk@4.0.15
|
||||
- @thirdweb-dev/auth@4.1.10
|
||||
|
||||
## 4.1.7
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`ab2dfd4f`](https://github.com/thirdweb-dev/js/commit/ab2dfd4f5cf4256fa62d76f84ca804992afab1e4), [`ab2dfd4f`](https://github.com/thirdweb-dev/js/commit/ab2dfd4f5cf4256fa62d76f84ca804992afab1e4)]:
|
||||
- @thirdweb-dev/sdk@4.0.14
|
||||
- @thirdweb-dev/wallets@2.1.6
|
||||
- @thirdweb-dev/storage@2.0.5
|
||||
- @thirdweb-dev/auth@4.1.9
|
||||
|
||||
## 4.1.6
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`69d68f5a`](https://github.com/thirdweb-dev/js/commit/69d68f5a25877bf5ea694719d2cf4ca8388f3091)]:
|
||||
- @thirdweb-dev/wallets@2.1.5
|
||||
- @thirdweb-dev/auth@4.1.8
|
||||
|
||||
## 4.1.5
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`9f993dcc`](https://github.com/thirdweb-dev/js/commit/9f993dcc1e60cc087850b8fb9ce09524073ce0b5)]:
|
||||
- @thirdweb-dev/wallets@2.1.4
|
||||
- @thirdweb-dev/auth@4.1.7
|
||||
|
||||
## 4.1.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#1951](https://github.com/thirdweb-dev/js/pull/1951) [`e79a9520`](https://github.com/thirdweb-dev/js/commit/e79a95206116ea09de0126fdbe30fb4413fdff28) Thanks [@kien-ngo](https://github.com/kien-ngo)! - Fix caching issue with useTotalCirculatingSupply
|
||||
|
||||
- [#1944](https://github.com/thirdweb-dev/js/pull/1944) [`6fcdec7c`](https://github.com/thirdweb-dev/js/commit/6fcdec7c12e4a3c0d10f3a67771e19cfad5c8ab5) Thanks [@iketw](https://github.com/iketw)! - Adds tsdoc warnings to enforce a common comments format
|
||||
|
||||
- [#1950](https://github.com/thirdweb-dev/js/pull/1950) [`b1190914`](https://github.com/thirdweb-dev/js/commit/b1190914a97a9c4d9019c4ce8ee49ad345aed18c) Thanks [@joaquim-verges](https://github.com/joaquim-verges)! - Smart Wallet autoconnect fixes and performance improvements
|
||||
|
||||
- Updated dependencies [[`23ab897e`](https://github.com/thirdweb-dev/js/commit/23ab897e329cdd5b316fbe554ea0f64add91f2b4), [`a3f3e160`](https://github.com/thirdweb-dev/js/commit/a3f3e160e07328655a4f0332f41f4edd210a1a8a), [`6fcdec7c`](https://github.com/thirdweb-dev/js/commit/6fcdec7c12e4a3c0d10f3a67771e19cfad5c8ab5), [`42c74368`](https://github.com/thirdweb-dev/js/commit/42c743682739de77c264c11cc1692ed752f929a6), [`6fcdec7c`](https://github.com/thirdweb-dev/js/commit/6fcdec7c12e4a3c0d10f3a67771e19cfad5c8ab5), [`480ed721`](https://github.com/thirdweb-dev/js/commit/480ed721d1c736049fa8b6ee4cbdbdf3cce18abd), [`16e9e8b6`](https://github.com/thirdweb-dev/js/commit/16e9e8b64d7d1a97a5b32fc855479e992b7ed3a8), [`b1190914`](https://github.com/thirdweb-dev/js/commit/b1190914a97a9c4d9019c4ce8ee49ad345aed18c)]:
|
||||
- @thirdweb-dev/sdk@4.0.13
|
||||
- @thirdweb-dev/storage@2.0.4
|
||||
- @thirdweb-dev/wallets@2.1.3
|
||||
- @thirdweb-dev/auth@4.1.6
|
||||
|
||||
## 4.1.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#1943](https://github.com/thirdweb-dev/js/pull/1943) [`30ea9c6b`](https://github.com/thirdweb-dev/js/commit/30ea9c6bf74b483a98592a1d8d64589b7f1b22a3) Thanks [@iketw](https://github.com/iketw)! - Adds tsdoc warnings to enforce a common comments format
|
||||
|
||||
- [#1929](https://github.com/thirdweb-dev/js/pull/1929) [`06e59cf9`](https://github.com/thirdweb-dev/js/commit/06e59cf91647e4080829d49f8cb91a4d8fdc87f7) Thanks [@iketw](https://github.com/iketw)! - Move addresses' utils to the core package
|
||||
|
||||
- Updated dependencies [[`3f3a484a`](https://github.com/thirdweb-dev/js/commit/3f3a484a3aa6e9f784e4d44458461bac0d3d4c6b), [`05e52114`](https://github.com/thirdweb-dev/js/commit/05e52114bf4f0ee352f393ed20115a904a18c310), [`a81a5285`](https://github.com/thirdweb-dev/js/commit/a81a5285b7ef4ddf47fd2779ab80ebbef4bd9e0e), [`30ea9c6b`](https://github.com/thirdweb-dev/js/commit/30ea9c6bf74b483a98592a1d8d64589b7f1b22a3), [`97fdbc8f`](https://github.com/thirdweb-dev/js/commit/97fdbc8f6443dcd08a7610e4437bd4c9d6b0e8c8), [`3f3a484a`](https://github.com/thirdweb-dev/js/commit/3f3a484a3aa6e9f784e4d44458461bac0d3d4c6b)]:
|
||||
- @thirdweb-dev/wallets@2.1.2
|
||||
- @thirdweb-dev/auth@4.1.5
|
||||
- @thirdweb-dev/storage@2.0.3
|
||||
- @thirdweb-dev/sdk@4.0.12
|
||||
|
||||
## 4.1.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@thirdweb-dev/react-core",
|
||||
"version": "4.1.2",
|
||||
"version": "4.1.8",
|
||||
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/react-core",
|
||||
"author": "thirdweb eng <[email protected]>",
|
||||
"license": "Apache-2.0",
|
||||
@@ -45,7 +45,7 @@
|
||||
"private": false,
|
||||
"scripts": {
|
||||
"format": "prettier --write 'src/**/*'",
|
||||
"lint": "eslint src/",
|
||||
"lint": "eslint src/ && bunx publint --strict --level warning",
|
||||
"fix": "eslint src/ --fix",
|
||||
"clean": "rm -rf dist/",
|
||||
"generate-docs": "pnpm generate-docs:evm && pnpm generate-snippets",
|
||||
|
||||
@@ -335,7 +335,7 @@ export function ThirdwebWalletProvider(
|
||||
},
|
||||
);
|
||||
} catch (e) {
|
||||
console.error("Failed to auto connect wallet");
|
||||
console.error("Failed to auto connect personal wallet");
|
||||
console.error(e);
|
||||
setConnectionStatus("disconnected");
|
||||
return;
|
||||
@@ -366,9 +366,14 @@ export function ThirdwebWalletProvider(
|
||||
} catch (e) {
|
||||
console.error("Failed to auto connect wallet");
|
||||
console.error(e);
|
||||
lastConnectedWalletStorage.removeItem(
|
||||
LAST_CONNECTED_WALLET_STORAGE_KEY,
|
||||
);
|
||||
if (
|
||||
e instanceof Error &&
|
||||
e.message === autoConnectTimeoutErrorMessage
|
||||
) {
|
||||
lastConnectedWalletStorage.removeItem(
|
||||
LAST_CONNECTED_WALLET_STORAGE_KEY,
|
||||
);
|
||||
}
|
||||
setConnectionStatus("disconnected");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,13 +43,13 @@ export type WalletConfig<I extends WalletInstance = WalletInstance> = {
|
||||
|
||||
/**
|
||||
* If true, this wallet will be tagged as "recommended" in ConnectWallet Modal and will be shown at the top of the list
|
||||
* @default false
|
||||
* @defaultValue false
|
||||
*/
|
||||
recommended?: boolean;
|
||||
|
||||
/**
|
||||
* If the wallet can sign transactions without user interaction, set this to true.
|
||||
* @default false
|
||||
* @defaultValue false
|
||||
*/
|
||||
isHeadless?: boolean;
|
||||
};
|
||||
@@ -154,7 +154,7 @@ export type ConnectUIProps<I extends WalletInstance = WalletInstance> = {
|
||||
/**
|
||||
* Called when the wallet is connected but it's
|
||||
* part of another wallet's connection flow.
|
||||
* @param walleInstance the instance of the connected wallet
|
||||
* @param walleInstance - the instance of the connected wallet
|
||||
*/
|
||||
onLocallyConnected?: (walleInstance: WalletInstance) => void;
|
||||
};
|
||||
|
||||
@@ -28,7 +28,7 @@ import { constants, utils } from "ethers";
|
||||
import invariant from "tiny-invariant";
|
||||
|
||||
/**
|
||||
* The options to be passed as the second parameter to the {@link useClaimIneligibilityReasons}` hook.
|
||||
* The options to be passed as the second parameter to the {@link useClaimIneligibilityReasons} hook.
|
||||
*
|
||||
* @beta
|
||||
*/
|
||||
|
||||
@@ -193,7 +193,10 @@ export function useTotalCirculatingSupply(
|
||||
const { erc721, erc1155 } = getErcs(contract);
|
||||
|
||||
return useQueryWithNetwork<BigNumber>(
|
||||
cacheKeys.contract.nft.query.totalCirculatingSupply(contractAddress),
|
||||
cacheKeys.contract.nft.query.totalCirculatingSupply(
|
||||
contractAddress,
|
||||
tokenId ?? undefined,
|
||||
),
|
||||
async () => {
|
||||
requiredParamInvariant(contract, "No Contract instance provided");
|
||||
|
||||
@@ -718,7 +721,7 @@ export function useBurnNFT<TContract extends NFTContract>(
|
||||
/**
|
||||
* Set shared metadata
|
||||
* TODO add docs
|
||||
* @private
|
||||
* @internal
|
||||
*/
|
||||
export function useSetSharedMetadata<TContract extends NFTContract>(
|
||||
contract: RequiredParam<TContract>,
|
||||
|
||||
@@ -257,6 +257,13 @@ export type { ThirdwebSDKProviderProps } from "./providers/types";
|
||||
|
||||
// utils
|
||||
export { invalidateContractAndBalances } from "./utils/cache-keys";
|
||||
export {
|
||||
isEnsName,
|
||||
isPossibleEVMAddress,
|
||||
shortenAddress,
|
||||
shortenIfAddress,
|
||||
shortenString,
|
||||
} from "./utils/addresses";
|
||||
|
||||
// types
|
||||
export type {
|
||||
|
||||
@@ -1,12 +1,33 @@
|
||||
import { utils } from "ethers";
|
||||
|
||||
export function shortenString(str: string, extraShort?: true) {
|
||||
export function shortenString(str: string, extraShort: boolean = true) {
|
||||
return `${str.substring(0, extraShort ? 4 : 6)}...${str.substring(
|
||||
str.length - (extraShort ? 3 : 4),
|
||||
)}`;
|
||||
}
|
||||
|
||||
export function shortenAddress(address: string, extraShort?: true): string {
|
||||
/**
|
||||
* This function shortens an address if it is a valid EVM address.
|
||||
*
|
||||
* @param address - The address to shorten
|
||||
* @param extraShort - If true, show the first 4 and last 3 characters
|
||||
* @returns The shortened address
|
||||
*
|
||||
* @remarks
|
||||
* Note that this function will not check if the address is an ENS.
|
||||
*
|
||||
* @example Calling shortenAddress with extraShort set to true
|
||||
* ```ts
|
||||
* const address = shortenIfAddress("0x1234567890123456789012345678901234567890", true); // result will be "0x1234...890"
|
||||
* ```
|
||||
*/
|
||||
export function shortenAddress(
|
||||
address?: string,
|
||||
extraShort: boolean = true,
|
||||
): string {
|
||||
if (!address) {
|
||||
return "";
|
||||
}
|
||||
try {
|
||||
const formattedAddress = utils.getAddress(address);
|
||||
return shortenString(formattedAddress, extraShort);
|
||||
@@ -17,10 +38,24 @@ export function shortenAddress(address: string, extraShort?: true): string {
|
||||
|
||||
export function shortenIfAddress(
|
||||
address?: string | null | false,
|
||||
extraShort?: true,
|
||||
extraShort: boolean = true,
|
||||
): string {
|
||||
if (typeof address === "string" && address.length > 0) {
|
||||
if (address && utils.isAddress(address)) {
|
||||
return shortenAddress(address, extraShort);
|
||||
}
|
||||
return address || "";
|
||||
}
|
||||
|
||||
export function isEnsName(name: string): boolean {
|
||||
return name?.endsWith(".eth");
|
||||
}
|
||||
|
||||
export function isPossibleEVMAddress(address?: string, ignoreEns?: boolean) {
|
||||
if (!address) {
|
||||
return false;
|
||||
}
|
||||
if (isEnsName(address) && !ignoreEns) {
|
||||
return true;
|
||||
}
|
||||
return utils.isAddress(address);
|
||||
}
|
||||
|
||||
@@ -182,10 +182,12 @@ export const cacheKeys = {
|
||||
),
|
||||
totalCirculatingSupply: (
|
||||
contractAddress: RequiredParam<ContractAddress>,
|
||||
tokenId?: BigNumberish,
|
||||
) =>
|
||||
createContractCacheKey(contractAddress, [
|
||||
"query",
|
||||
"totalCirculatingSupply",
|
||||
tokenId ?? "0",
|
||||
]),
|
||||
totalCount: (contractAddress: RequiredParam<ContractAddress>) =>
|
||||
createContractCacheKey(contractAddress, ["query", "totalCount"]),
|
||||
|
||||
@@ -1,5 +1,17 @@
|
||||
# @thirdweb-dev/react-native-compat
|
||||
|
||||
## 0.4.8
|
||||
|
||||
## 0.4.7
|
||||
|
||||
## 0.4.6
|
||||
|
||||
## 0.4.5
|
||||
|
||||
## 0.4.4
|
||||
|
||||
## 0.4.3
|
||||
|
||||
## 0.4.2
|
||||
|
||||
## 0.4.1
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@thirdweb-dev/react-native-compat",
|
||||
"description": "Shims for Thirdweb in React Native Projects",
|
||||
"version": "0.4.2",
|
||||
"version": "0.4.8",
|
||||
"author": "thirdweb eng <[email protected]>",
|
||||
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/react-native-compat",
|
||||
"license": "Apache-2.0",
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
module.exports = {
|
||||
root: true,
|
||||
extends: ["thirdweb"],
|
||||
plugins: ["i18next"],
|
||||
plugins: ["i18next", "eslint-plugin-tsdoc"],
|
||||
rules: {
|
||||
"tsdoc/syntax": "error",
|
||||
"i18next/no-literal-string": 2,
|
||||
},
|
||||
settings: {
|
||||
|
||||
@@ -1,5 +1,131 @@
|
||||
# @thirdweb-dev/react-native
|
||||
|
||||
## 0.4.8
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`6832b19f`](https://github.com/thirdweb-dev/js/commit/6832b19fc5eedc7c17e69940a361840de0a84881), [`7abb36a7`](https://github.com/thirdweb-dev/js/commit/7abb36a7ec39766dd7da03015ccef401ef7a7863), [`1c4cbedb`](https://github.com/thirdweb-dev/js/commit/1c4cbedb6a3c9f9014ffbf83c02b998768958d96), [`e43beec3`](https://github.com/thirdweb-dev/js/commit/e43beec36a569211b6fe708107aa7dc04bff08ec)]:
|
||||
- @thirdweb-dev/wallets@2.1.7
|
||||
- @thirdweb-dev/sdk@4.0.15
|
||||
- @thirdweb-dev/react-core@4.1.8
|
||||
|
||||
## 0.4.7
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`ab2dfd4f`](https://github.com/thirdweb-dev/js/commit/ab2dfd4f5cf4256fa62d76f84ca804992afab1e4), [`ab2dfd4f`](https://github.com/thirdweb-dev/js/commit/ab2dfd4f5cf4256fa62d76f84ca804992afab1e4)]:
|
||||
- @thirdweb-dev/sdk@4.0.14
|
||||
- @thirdweb-dev/wallets@2.1.6
|
||||
- @thirdweb-dev/storage@2.0.5
|
||||
- @thirdweb-dev/react-core@4.1.7
|
||||
|
||||
## 0.4.6
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#1945](https://github.com/thirdweb-dev/js/pull/1945) [`69d68f5a`](https://github.com/thirdweb-dev/js/commit/69d68f5a25877bf5ea694719d2cf4ca8388f3091) Thanks [@iketw](https://github.com/iketw)! - Enable Facebook Sign In for embedded wallet
|
||||
|
||||
- Updated dependencies [[`69d68f5a`](https://github.com/thirdweb-dev/js/commit/69d68f5a25877bf5ea694719d2cf4ca8388f3091)]:
|
||||
- @thirdweb-dev/wallets@2.1.5
|
||||
- @thirdweb-dev/react-core@4.1.6
|
||||
|
||||
## 0.4.5
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`9f993dcc`](https://github.com/thirdweb-dev/js/commit/9f993dcc1e60cc087850b8fb9ce09524073ce0b5)]:
|
||||
- @thirdweb-dev/wallets@2.1.4
|
||||
- @thirdweb-dev/react-core@4.1.5
|
||||
|
||||
## 0.4.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#1944](https://github.com/thirdweb-dev/js/pull/1944) [`6fcdec7c`](https://github.com/thirdweb-dev/js/commit/6fcdec7c12e4a3c0d10f3a67771e19cfad5c8ab5) Thanks [@iketw](https://github.com/iketw)! - Adds tsdoc warnings to enforce a common comments format
|
||||
|
||||
- Updated dependencies [[`23ab897e`](https://github.com/thirdweb-dev/js/commit/23ab897e329cdd5b316fbe554ea0f64add91f2b4), [`a3f3e160`](https://github.com/thirdweb-dev/js/commit/a3f3e160e07328655a4f0332f41f4edd210a1a8a), [`e79a9520`](https://github.com/thirdweb-dev/js/commit/e79a95206116ea09de0126fdbe30fb4413fdff28), [`6fcdec7c`](https://github.com/thirdweb-dev/js/commit/6fcdec7c12e4a3c0d10f3a67771e19cfad5c8ab5), [`42c74368`](https://github.com/thirdweb-dev/js/commit/42c743682739de77c264c11cc1692ed752f929a6), [`6fcdec7c`](https://github.com/thirdweb-dev/js/commit/6fcdec7c12e4a3c0d10f3a67771e19cfad5c8ab5), [`480ed721`](https://github.com/thirdweb-dev/js/commit/480ed721d1c736049fa8b6ee4cbdbdf3cce18abd), [`16e9e8b6`](https://github.com/thirdweb-dev/js/commit/16e9e8b64d7d1a97a5b32fc855479e992b7ed3a8), [`b1190914`](https://github.com/thirdweb-dev/js/commit/b1190914a97a9c4d9019c4ce8ee49ad345aed18c)]:
|
||||
- @thirdweb-dev/sdk@4.0.13
|
||||
- @thirdweb-dev/react-core@4.1.4
|
||||
- @thirdweb-dev/storage@2.0.4
|
||||
- @thirdweb-dev/wallets@2.1.3
|
||||
|
||||
## 0.4.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#1908](https://github.com/thirdweb-dev/js/pull/1908) [`18552f3a`](https://github.com/thirdweb-dev/js/commit/18552f3a225d1c46f0ff19c2b1c9cc44f84e33ac) Thanks [@kien-ngo](https://github.com/kien-ngo)! - Add `hideSwitchToPersonalWallet` prop on `ConnectWallet` component to hide the "Switch to Personal wallet" option in the ConnectWallet modal which is shown when wallet is connected as a Smart Wallet
|
||||
|
||||
- [#1912](https://github.com/thirdweb-dev/js/pull/1912) [`1a421d3b`](https://github.com/thirdweb-dev/js/commit/1a421d3b5d837eade5b7344118a7148ddea35517) Thanks [@iketw](https://github.com/iketw)! - Adds Apple as a social sign in option for EmbeddedWallet
|
||||
|
||||
You can now do:
|
||||
|
||||
```typescript
|
||||
embeddedWallet({
|
||||
auth: {
|
||||
options: ['apple'],
|
||||
redirectUrl: 'your-apps-redirect-url://',
|
||||
},
|
||||
}),
|
||||
```
|
||||
|
||||
- [#1943](https://github.com/thirdweb-dev/js/pull/1943) [`30ea9c6b`](https://github.com/thirdweb-dev/js/commit/30ea9c6bf74b483a98592a1d8d64589b7f1b22a3) Thanks [@iketw](https://github.com/iketw)! - Adds tsdoc warnings to enforce a common comments format
|
||||
|
||||
- [#1929](https://github.com/thirdweb-dev/js/pull/1929) [`06e59cf9`](https://github.com/thirdweb-dev/js/commit/06e59cf91647e4080829d49f8cb91a4d8fdc87f7) Thanks [@iketw](https://github.com/iketw)! - Move addresses' utils to the core package
|
||||
|
||||
- [#1925](https://github.com/thirdweb-dev/js/pull/1925) [`97fdbc8f`](https://github.com/thirdweb-dev/js/commit/97fdbc8f6443dcd08a7610e4437bd4c9d6b0e8c8) Thanks [@iketw](https://github.com/iketw)! - [RN] Adds walletConnectReceiver prop to EmbeddedWallet and SmartWallet
|
||||
|
||||
You can pass your own WalletConnect projectId and metadata (highly recommended):
|
||||
|
||||
```typescript
|
||||
embeddedWallet({
|
||||
auth: {
|
||||
options: ['email', 'google'],
|
||||
redirectUrl: 'redirect-url',
|
||||
},
|
||||
walletConnectReceiver: {
|
||||
walletConnectWalletMetadata?: WCMetadata;
|
||||
walletConnectV2ProjectId?: string;
|
||||
walletConnectV2RelayUrl?: string;
|
||||
},
|
||||
}),
|
||||
|
||||
smartWallet(localWallet(), {
|
||||
factoryAddress: 'factory-address',
|
||||
gasless: true,
|
||||
walletConnectReceiver: {
|
||||
walletConnectWalletMetadata?: WCMetadata;
|
||||
walletConnectV2ProjectId?: string;
|
||||
walletConnectV2RelayUrl?: string;
|
||||
},
|
||||
}),
|
||||
```
|
||||
|
||||
You can just pass `true` to the prop and these props will default to our internal WalletConnect projectId and metadata.
|
||||
|
||||
```typescript
|
||||
embeddedWallet({
|
||||
auth: {
|
||||
options: ['email', 'google'],
|
||||
redirectUrl: 'redirect-url',
|
||||
},
|
||||
walletConnectReceiver: true
|
||||
}),
|
||||
|
||||
smartWallet(localWallet(), {
|
||||
factoryAddress: 'factory-address',
|
||||
gasless: true,
|
||||
walletConnectReceiver: true
|
||||
}),
|
||||
```
|
||||
|
||||
- [#1942](https://github.com/thirdweb-dev/js/pull/1942) [`6de3a19b`](https://github.com/thirdweb-dev/js/commit/6de3a19b86476cf5f7d67223a366379c4fdb9b74) Thanks [@iketw](https://github.com/iketw)! - Updated react-native-safe-area-context to 4.74
|
||||
|
||||
- Updated dependencies [[`3f3a484a`](https://github.com/thirdweb-dev/js/commit/3f3a484a3aa6e9f784e4d44458461bac0d3d4c6b), [`a81a5285`](https://github.com/thirdweb-dev/js/commit/a81a5285b7ef4ddf47fd2779ab80ebbef4bd9e0e), [`30ea9c6b`](https://github.com/thirdweb-dev/js/commit/30ea9c6bf74b483a98592a1d8d64589b7f1b22a3), [`06e59cf9`](https://github.com/thirdweb-dev/js/commit/06e59cf91647e4080829d49f8cb91a4d8fdc87f7), [`97fdbc8f`](https://github.com/thirdweb-dev/js/commit/97fdbc8f6443dcd08a7610e4437bd4c9d6b0e8c8), [`3f3a484a`](https://github.com/thirdweb-dev/js/commit/3f3a484a3aa6e9f784e4d44458461bac0d3d4c6b)]:
|
||||
- @thirdweb-dev/[email protected]
|
||||
- @thirdweb-dev/[email protected]
|
||||
- @thirdweb-dev/[email protected]
|
||||
- @thirdweb-dev/[email protected]
|
||||
|
||||
## 0.4.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@thirdweb-dev/react-native",
|
||||
"version": "0.4.2",
|
||||
"version": "0.4.8",
|
||||
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/react-native",
|
||||
"author": "thirdweb eng <[email protected]>",
|
||||
"license": "Apache-2.0",
|
||||
@@ -70,6 +70,7 @@
|
||||
"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",
|
||||
"ethers": "^5.7.2",
|
||||
"expo": "^47.0.14",
|
||||
"jest": "^29.6.2",
|
||||
@@ -79,7 +80,7 @@
|
||||
"react-native-camera": "^4.2.1",
|
||||
"react-native-device-info": "10.6.0",
|
||||
"react-native-mmkv": "2.5.1",
|
||||
"react-native-safe-area-context": "4.5.3",
|
||||
"react-native-safe-area-context": "4.7.4",
|
||||
"react-native-webview": "12.1.0",
|
||||
"rimraf": "^3.0.2",
|
||||
"typedoc": "^0.25.2",
|
||||
@@ -93,7 +94,7 @@
|
||||
"react-native-inappbrowser-reborn": "^3.7.0",
|
||||
"react-native-quick-base64": "^2.0.7",
|
||||
"react-native-quick-crypto": "^0.6.1",
|
||||
"react-native-safe-area-context": "4.5.3",
|
||||
"react-native-safe-area-context": "4.7.4",
|
||||
"react-native-webview": "12.1.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
|
||||
@@ -73,7 +73,7 @@ export class noopStorage implements IAsyncStorage {
|
||||
/**
|
||||
* Returns a new instance of AsyncLocalStorage
|
||||
*
|
||||
* @param name Name to namespace the storage with
|
||||
* @param name - Name to namespace the storage with
|
||||
* @returns A new instance of AsyncLocalStorage
|
||||
*/
|
||||
export function createAsyncLocalStorage(name: string) {
|
||||
@@ -83,7 +83,7 @@ export function createAsyncLocalStorage(name: string) {
|
||||
/**
|
||||
* Returns a new instance of LocalStorage
|
||||
*
|
||||
* @param name Name to namespace the storage with
|
||||
* @param name - Name to namespace the storage with
|
||||
* @returns A new instance of LocalStorage
|
||||
*/
|
||||
export function createSyncStorage(name: string) {
|
||||
|
||||
@@ -31,7 +31,7 @@ export class SecureStorage implements ISecureStorage {
|
||||
/**
|
||||
* Returns a new instance of SecureStorage implemented by Expo SecureStore
|
||||
*
|
||||
* @param name Name to namespace the storage with
|
||||
* @param name - Name to namespace the storage with
|
||||
* @returns A new instance of SecureStorage
|
||||
*/
|
||||
export function createSecureStorage(name: string) {
|
||||
|
||||
@@ -1,3 +1,14 @@
|
||||
export const APPLE_ICON = `<svg fill="#959CA0" height="40px" width="40px" version="1.1" id="Capa_1" viewBox="0 0 24 24" xml:space="preserve" stroke="#959CA0"><g id="SVGRepo_bgCarrier" stroke-width="0"></g><g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"></g><g id="SVGRepo_iconCarrier"> <g> <g> <path d="M15.769,0c0.053,0,0.106,0,0.162,0c0.13,1.606-0.483,2.806-1.228,3.675c-0.731,0.863-1.732,1.7-3.351,1.573 c-0.108-1.583,0.506-2.694,1.25-3.561C13.292,0.879,14.557,0.16,15.769,0z"></path> <path d="M20.67,16.716c0,0.016,0,0.03,0,0.045c-0.455,1.378-1.104,2.559-1.896,3.655c-0.723,0.995-1.609,2.334-3.191,2.334 c-1.367,0-2.275-0.879-3.676-0.903c-1.482-0.024-2.297,0.735-3.652,0.926c-0.155,0-0.31,0-0.462,0 c-0.995-0.144-1.798-0.932-2.383-1.642c-1.725-2.098-3.058-4.808-3.306-8.276c0-0.34,0-0.679,0-1.019 c0.105-2.482,1.311-4.5,2.914-5.478c0.846-0.52,2.009-0.963,3.304-0.765c0.555,0.086,1.122,0.276,1.619,0.464 c0.471,0.181,1.06,0.502,1.618,0.485c0.378-0.011,0.754-0.208,1.135-0.347c1.116-0.403,2.21-0.865,3.652-0.648 c1.733,0.262,2.963,1.032,3.723,2.22c-1.466,0.933-2.625,2.339-2.427,4.74C17.818,14.688,19.086,15.964,20.67,16.716z"></path> </g> <g> </g> <g> </g> <g> </g> <g> </g> <g> </g> <g> </g> <g> </g> <g> </g> <g> </g> <g> </g> <g> </g> <g> </g> <g> </g> <g> </g> <g> </g> </g> </g></svg>`;
|
||||
|
||||
export const FACEBOOK_ICON = `<svg xml:space="preserve" viewBox="0 0 40 40">
|
||||
<linearGradient id="a" x1="-277.375" x2="-277.375" y1="406.6018" y2="407.5726" gradientTransform="matrix(40 0 0 -39.7778 11115.001 16212.334)" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0" stop-color="#0062e0"/>
|
||||
<stop offset="1" stop-color="#19afff"/>
|
||||
</linearGradient>
|
||||
<path fill="url(#a)" d="M16.7 39.8C7.2 38.1 0 29.9 0 20 0 9 9 0 20 0s20 9 20 20c0 9.9-7.2 18.1-16.7 19.8l-1.1-.9h-4.4l-1.1.9z"/>
|
||||
<path fill="#fff" d="m27.8 25.6.9-5.6h-5.3v-3.9c0-1.6.6-2.8 3-2.8H29V8.2c-1.4-.2-3-.4-4.4-.4-4.6 0-7.8 2.8-7.8 7.8V20h-5v5.6h5v14.1c1.1.2 2.2.3 3.3.3 1.1 0 2.2-.1 3.3-.3V25.6h4.4z"/>
|
||||
</svg>`;
|
||||
|
||||
export const GOOGLE_ICON = `<svg height={height} viewBox="0 0 24 24" width={width}>
|
||||
<path
|
||||
d="M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09z"
|
||||
|
||||
@@ -36,7 +36,7 @@ export type ConnectWalletProps = {
|
||||
/**
|
||||
* Hide option to request testnet funds for testnets in dropdown
|
||||
*
|
||||
* @default false
|
||||
* @defaultValue false
|
||||
*/
|
||||
hideTestnetFaucet?: boolean;
|
||||
|
||||
@@ -47,7 +47,7 @@ export type ConnectWalletProps = {
|
||||
* Please, note that if you support multiple networks in your app this prop should
|
||||
* be set to `false` to allow users to switch between networks.
|
||||
*
|
||||
* @default false
|
||||
* @defaultValue false
|
||||
*/
|
||||
switchToActiveChain?: boolean;
|
||||
|
||||
@@ -69,6 +69,13 @@ export type ConnectWalletProps = {
|
||||
* ```
|
||||
*/
|
||||
displayBalanceToken?: Record<number, string>;
|
||||
|
||||
/**
|
||||
* Hide the "switch to Personal wallet" option in the wallet modal which is shown when wallet is connected to a Smart Wallet
|
||||
*
|
||||
* @defaultValue false
|
||||
*/
|
||||
hideSwitchToPersonalWallet?: boolean;
|
||||
} & ConnectWalletButtonProps;
|
||||
|
||||
export const ConnectWallet = ({
|
||||
@@ -84,6 +91,7 @@ export const ConnectWallet = ({
|
||||
termsOfServiceUrl,
|
||||
privacyPolicyUrl,
|
||||
supportedTokens,
|
||||
hideSwitchToPersonalWallet,
|
||||
}: ConnectWalletProps) => {
|
||||
const globalTheme = useGlobalTheme();
|
||||
const l = useLocale();
|
||||
@@ -163,6 +171,7 @@ export const ConnectWallet = ({
|
||||
hideTestnetFaucet={hideTestnetFaucet}
|
||||
supportedTokens={supportedTokensMemo}
|
||||
displayBalanceToken={displayBalanceToken}
|
||||
hideSwitchToPersonalWallet={hideSwitchToPersonalWallet}
|
||||
/>
|
||||
)
|
||||
) : (
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { useWallet } from "@thirdweb-dev/react-core";
|
||||
import { IWalletConnectReceiver } from "@thirdweb-dev/wallets";
|
||||
import { useCallback, useEffect, useRef, useState } from "react";
|
||||
import Box from "../base/Box";
|
||||
import BaseButton from "../base/BaseButton";
|
||||
@@ -14,8 +13,13 @@ import WalletConnectIcon from "../../assets/wallet-connect";
|
||||
import QrCodeIcon from "../../assets/qr-code";
|
||||
import { QRCodeScan } from "./QRCodeScan";
|
||||
import { useLocale } from "../../providers/ui-context-provider";
|
||||
import { useWalletConnectHandler } from "../../providers/context-provider";
|
||||
|
||||
const ConnectAppField = () => {
|
||||
const ConnectAppField = ({
|
||||
onConnectAppTriggered,
|
||||
}: {
|
||||
onConnectAppTriggered?: () => void;
|
||||
}) => {
|
||||
const theme = useTheme();
|
||||
const l = useLocale();
|
||||
const [showWCInput, setShowWCInput] = useState(false);
|
||||
@@ -24,22 +28,19 @@ const ConnectAppField = () => {
|
||||
const wallet = useWallet();
|
||||
const [showQRCodeScan, setShowQRCodeScan] = useState(false);
|
||||
const wcUriRef = useRef<string | undefined>();
|
||||
const walletConnectHandler = useWalletConnectHandler();
|
||||
|
||||
const getAppMeta = useCallback(() => {
|
||||
if (wallet && "isWCReceiverEnabled" in wallet) {
|
||||
const sessions = (
|
||||
wallet as unknown as IWalletConnectReceiver
|
||||
).getActiveSessions();
|
||||
if (Object.keys(sessions).length > 0) {
|
||||
setAppMeta({
|
||||
name: sessions[0].peer.metadata.name,
|
||||
iconUrl: sessions[0].peer.metadata.icons[0],
|
||||
});
|
||||
}
|
||||
const sessions = walletConnectHandler?.getActiveSessions();
|
||||
if (sessions && Object.keys(sessions).length > 0) {
|
||||
setAppMeta({
|
||||
name: sessions[0].peer.metadata.name,
|
||||
iconUrl: sessions[0].peer.metadata.icons[0],
|
||||
});
|
||||
}
|
||||
}, [wallet]);
|
||||
}, [walletConnectHandler]);
|
||||
|
||||
const onSmartWalletWCMessage = useCallback(
|
||||
const onWalletConnectMessage = useCallback(
|
||||
({ type }: { type: string }) => {
|
||||
if (type === "session_approved") {
|
||||
getAppMeta();
|
||||
@@ -52,22 +53,22 @@ const ConnectAppField = () => {
|
||||
|
||||
useEffect(() => {
|
||||
if (wallet) {
|
||||
wallet.addListener("message", onSmartWalletWCMessage);
|
||||
wallet.addListener("message", onWalletConnectMessage);
|
||||
|
||||
getAppMeta();
|
||||
}
|
||||
|
||||
return () => {
|
||||
if (wallet) {
|
||||
wallet.removeListener("message", onSmartWalletWCMessage);
|
||||
wallet.removeListener("message", onWalletConnectMessage);
|
||||
}
|
||||
};
|
||||
}, [getAppMeta, onSmartWalletWCMessage, wallet]);
|
||||
}, [getAppMeta, onWalletConnectMessage, wallet]);
|
||||
|
||||
const onConnectDappPress = () => {
|
||||
if (appMeta) {
|
||||
reset();
|
||||
(wallet as unknown as IWalletConnectReceiver).disconnectSession();
|
||||
walletConnectHandler?.disconnectSession();
|
||||
} else {
|
||||
setShowWCInput(true);
|
||||
}
|
||||
@@ -103,10 +104,14 @@ const ConnectAppField = () => {
|
||||
|
||||
const uriToUse = uri || wcUri;
|
||||
|
||||
if (uriToUse?.startsWith("wc:")) {
|
||||
(wallet as unknown as IWalletConnectReceiver).connectApp(uriToUse);
|
||||
if (!uriToUse?.startsWith("wc:")) {
|
||||
return;
|
||||
}
|
||||
|
||||
onConnectAppTriggered?.();
|
||||
|
||||
walletConnectHandler?.connectApp(uriToUse);
|
||||
|
||||
setWCUri(undefined);
|
||||
wcUriRef.current = undefined;
|
||||
};
|
||||
@@ -135,6 +140,7 @@ const ConnectAppField = () => {
|
||||
style: {
|
||||
color: theme.colors.textPrimary,
|
||||
fontFamily: theme.textVariants.defaults.fontFamily,
|
||||
flex: 1,
|
||||
},
|
||||
}}
|
||||
containerProps={{
|
||||
|
||||
+16
-4
@@ -30,6 +30,8 @@ import { SupportedTokens } from "../SendFunds/defaultTokens";
|
||||
import { ActiveDot } from "../base";
|
||||
import { EmbeddedWallet } from "../../wallets/wallets/embedded/EmbeddedWallet";
|
||||
import { useLocale } from "../../providers/ui-context-provider";
|
||||
import { isWalletConnectReceiverEnabled } from "../../wallets/utils";
|
||||
import ConnectAppField from "./ConnectAppField";
|
||||
|
||||
const MODAL_HEIGHT = Dimensions.get("window").height * 0.7;
|
||||
const DEVICE_WIDTH = Dimensions.get("window").width;
|
||||
@@ -42,6 +44,7 @@ export const ConnectWalletDetailsModal = ({
|
||||
hideTestnetFaucet,
|
||||
supportedTokens,
|
||||
displayBalanceToken,
|
||||
hideSwitchToPersonalWallet,
|
||||
}: {
|
||||
isVisible: boolean;
|
||||
onClosePress: () => void;
|
||||
@@ -50,6 +53,7 @@ export const ConnectWalletDetailsModal = ({
|
||||
hideTestnetFaucet?: boolean;
|
||||
supportedTokens: SupportedTokens;
|
||||
displayBalanceToken?: Record<number, string>;
|
||||
hideSwitchToPersonalWallet?: boolean;
|
||||
}) => {
|
||||
const l = useLocale();
|
||||
const [isExportModalVisible, setIsExportModalVisible] = useState(false);
|
||||
@@ -131,6 +135,7 @@ export const ConnectWalletDetailsModal = ({
|
||||
return (
|
||||
<SmartWalletAdditionalActions
|
||||
onExportPress={onExportLocalWalletPress}
|
||||
hideSwitchToPersonalWallet={hideSwitchToPersonalWallet}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@@ -203,11 +208,15 @@ export const ConnectWalletDetailsModal = ({
|
||||
return null;
|
||||
}, [
|
||||
activeWallet?.walletId,
|
||||
isImportModalVisible,
|
||||
onExportLocalWalletPress,
|
||||
onWalletImported,
|
||||
smartWallet,
|
||||
l,
|
||||
onExportLocalWalletPress,
|
||||
l.connect_wallet_details.additional_actions,
|
||||
l.connect_wallet_details.backup_wallet,
|
||||
l.connect_wallet_details.import_wallet,
|
||||
l.local_wallet.this_is_a_temporary_wallet,
|
||||
isImportModalVisible,
|
||||
onWalletImported,
|
||||
hideSwitchToPersonalWallet,
|
||||
]);
|
||||
|
||||
return (
|
||||
@@ -296,6 +305,9 @@ export const ConnectWalletDetailsModal = ({
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
{isWalletConnectReceiverEnabled(activeWallet) ? (
|
||||
<ConnectAppField onConnectAppTriggered={onClosePress} />
|
||||
) : null}
|
||||
{getAdditionalActions()}
|
||||
{extraRows ? extraRows({}) : null}
|
||||
{addressCopied === true ? (
|
||||
|
||||
+10
-6
@@ -10,12 +10,15 @@ import { useState } from "react";
|
||||
import BaseButton from "../base/BaseButton";
|
||||
import Box from "../base/Box";
|
||||
import { ModalHeaderTextClose } from "../base/modal/ModalHeaderTextClose";
|
||||
import { useAddress, useWallet } from "@thirdweb-dev/react-core";
|
||||
import {
|
||||
shortenAddress,
|
||||
useAddress,
|
||||
useWallet,
|
||||
} from "@thirdweb-dev/react-core";
|
||||
import { PasswordInput } from "../PasswordInput";
|
||||
import * as FileSystem from "expo-file-system";
|
||||
import { SmartWallet } from "@thirdweb-dev/wallets";
|
||||
import { usePersonalWalletAddress } from "../../wallets/hooks/usePersonalWalletAddress";
|
||||
import { shortenWalletAddress } from "../../utils/addresses";
|
||||
import { LocalWallet } from "../../wallets/wallets/LocalWallet";
|
||||
import { TWModal } from "../base/modal/TWModal";
|
||||
import { useLocale } from "../../providers/ui-context-provider";
|
||||
@@ -162,7 +165,7 @@ export const ExportLocalWalletModal = ({
|
||||
{l.local_wallet.wallet_address}
|
||||
</Text>
|
||||
<Text variant="bodySmallSecondary">
|
||||
{shortenWalletAddress(
|
||||
{shortenAddress(
|
||||
personalWalletAddress ? personalWalletAddress : address,
|
||||
)}
|
||||
</Text>
|
||||
@@ -173,16 +176,17 @@ export const ExportLocalWalletModal = ({
|
||||
<Text variant="bodySmall" color="red" mt="xs" textAlign="left">
|
||||
{error}
|
||||
</Text>
|
||||
<Box flexDirection="row" justifyContent="flex-end" mt="lg">
|
||||
<Box flexDirection="row" justifyContent="flex-end" mt="xs">
|
||||
<BaseButton
|
||||
backgroundColor="white"
|
||||
backgroundColor="accentButtonColor"
|
||||
borderColor="accentButtonColor"
|
||||
style={styles.modalButton}
|
||||
onPress={onContinuePress}
|
||||
>
|
||||
{isExporting ? (
|
||||
<ActivityIndicator size="small" color="black" />
|
||||
) : (
|
||||
<Text variant="bodySmall" color="black">
|
||||
<Text variant="bodySmall" color="accentButtonTextColor">
|
||||
{l.connect_wallet_details.backup}
|
||||
</Text>
|
||||
)}
|
||||
|
||||
+4
-5
@@ -2,18 +2,19 @@ import { useWallet } from "@thirdweb-dev/react-core";
|
||||
import Box from "../base/Box";
|
||||
import BaseButton from "../base/BaseButton";
|
||||
import Text from "../base/Text";
|
||||
import { IWalletConnectReceiver } from "@thirdweb-dev/wallets";
|
||||
import {
|
||||
CLOSE_MODAL_STATE,
|
||||
WalletConnectSessionProposalModal,
|
||||
} from "../../utils/modalTypes";
|
||||
import { useLocale, useModalState } from "../../providers/ui-context-provider";
|
||||
import { useWalletConnectHandler } from "../../providers/context-provider";
|
||||
|
||||
export const SessionProposalModal = () => {
|
||||
const l = useLocale();
|
||||
const { modalState, setModalState } = useModalState();
|
||||
const { data: proposalData } =
|
||||
modalState as WalletConnectSessionProposalModal;
|
||||
const walletConnectHandler = useWalletConnectHandler();
|
||||
|
||||
const wallet = useWallet();
|
||||
|
||||
@@ -41,7 +42,7 @@ export const SessionProposalModal = () => {
|
||||
minWidth={100}
|
||||
borderColor="border"
|
||||
onPress={async () => {
|
||||
(wallet as unknown as IWalletConnectReceiver).rejectSession();
|
||||
walletConnectHandler?.rejectSession();
|
||||
onClose();
|
||||
}}
|
||||
>
|
||||
@@ -61,9 +62,7 @@ export const SessionProposalModal = () => {
|
||||
if (!wallet) {
|
||||
throw new Error("Wallet not connected.");
|
||||
}
|
||||
await (
|
||||
wallet as unknown as IWalletConnectReceiver
|
||||
).approveSession();
|
||||
await walletConnectHandler?.approveSession();
|
||||
onClose();
|
||||
}}
|
||||
>
|
||||
|
||||
+11
-15
@@ -1,19 +1,16 @@
|
||||
import { useChain, useWallet } from "@thirdweb-dev/react-core";
|
||||
import { shortenAddress, useChain, useWallet } from "@thirdweb-dev/react-core";
|
||||
import Box from "../base/Box";
|
||||
import BaseButton from "../base/BaseButton";
|
||||
import Text from "../base/Text";
|
||||
import {
|
||||
EIP155_SIGNING_METHODS,
|
||||
IWalletConnectReceiver,
|
||||
} from "@thirdweb-dev/wallets";
|
||||
import { EIP155_SIGNING_METHODS } from "@thirdweb-dev/wallets";
|
||||
import { useLocale, useModalState } from "../../providers/ui-context-provider";
|
||||
import {
|
||||
CLOSE_MODAL_STATE,
|
||||
WalletConnectSessionRequestModal,
|
||||
} from "../../utils/modalTypes";
|
||||
import { ActivityIndicator, Dimensions } from "react-native";
|
||||
import { shortenWalletAddress } from "../../utils/addresses";
|
||||
import { useCallback, useState } from "react";
|
||||
import { useWalletConnectHandler } from "../../providers/context-provider";
|
||||
|
||||
const getTitle = (method: string) => {
|
||||
switch (method) {
|
||||
@@ -34,6 +31,7 @@ export const SessionRequestModal = () => {
|
||||
const { modalState, setModalState } = useModalState();
|
||||
const { data: requestData } = modalState as WalletConnectSessionRequestModal;
|
||||
const [approvingRequest, setApprovingRequest] = useState(false);
|
||||
const walletConnectHandler = useWalletConnectHandler();
|
||||
|
||||
const wallet = useWallet();
|
||||
const chain = useChain();
|
||||
@@ -48,12 +46,10 @@ export const SessionRequestModal = () => {
|
||||
}
|
||||
|
||||
setApprovingRequest(true);
|
||||
(wallet as unknown as IWalletConnectReceiver)
|
||||
.approveRequest()
|
||||
.finally(() => {
|
||||
setApprovingRequest(false);
|
||||
onClose();
|
||||
});
|
||||
walletConnectHandler?.approveEIP155Request().finally(() => {
|
||||
setApprovingRequest(false);
|
||||
onClose();
|
||||
});
|
||||
};
|
||||
|
||||
const getContent = useCallback(() => {
|
||||
@@ -86,10 +82,10 @@ export const SessionRequestModal = () => {
|
||||
return (
|
||||
<Box>
|
||||
<Text variant="bodySmall" textAlign="left">
|
||||
{`${l.common.from}: ${shortenWalletAddress(from)}`}
|
||||
{`${l.common.from}: ${shortenAddress(from)}`}
|
||||
</Text>
|
||||
<Text variant="bodySmall" textAlign="left" mt="sm">
|
||||
{`${l.common.to}: ${shortenWalletAddress(to)}`}
|
||||
{`${l.common.to}: ${shortenAddress(to)}`}
|
||||
</Text>
|
||||
</Box>
|
||||
);
|
||||
@@ -126,7 +122,7 @@ export const SessionRequestModal = () => {
|
||||
minWidth={100}
|
||||
borderColor="border"
|
||||
onPress={async () => {
|
||||
(wallet as unknown as IWalletConnectReceiver).rejectRequest();
|
||||
walletConnectHandler?.rejectEIP155Request();
|
||||
onClose();
|
||||
}}
|
||||
>
|
||||
|
||||
+20
-20
@@ -11,15 +11,16 @@ import { useWalletContext, useWallet } from "@thirdweb-dev/react-core";
|
||||
import { useEffect, useState } from "react";
|
||||
import { useSmartWallet } from "../../providers/context-provider";
|
||||
import RightArrowIcon from "../../assets/right-arrow";
|
||||
import ConnectAppField from "./ConnectAppField";
|
||||
import DisconnectIcon from "../../assets/disconnect";
|
||||
import { IconTextButton } from "../base/IconTextButton";
|
||||
import { useGlobalTheme, useLocale } from "../../providers/ui-context-provider";
|
||||
|
||||
export const SmartWalletAdditionalActions = ({
|
||||
onExportPress,
|
||||
hideSwitchToPersonalWallet,
|
||||
}: {
|
||||
onExportPress: () => void;
|
||||
hideSwitchToPersonalWallet?: boolean;
|
||||
}) => {
|
||||
const l = useLocale();
|
||||
const { setConnectedWallet } = useWalletContext();
|
||||
@@ -61,25 +62,24 @@ export const SmartWalletAdditionalActions = ({
|
||||
|
||||
return (
|
||||
<>
|
||||
<IconTextButton
|
||||
mt="xs"
|
||||
text={
|
||||
showSmartWallet
|
||||
? l.smart_wallet.switch_to_smart
|
||||
: l.smart_wallet.switch_to_personal
|
||||
}
|
||||
icon={
|
||||
<DisconnectIcon
|
||||
width={14}
|
||||
height={14}
|
||||
color={theme.colors.iconPrimary}
|
||||
/>
|
||||
}
|
||||
onPress={onWalletPress}
|
||||
/>
|
||||
{!showSmartWallet && smartWallet?.enableConnectApp ? (
|
||||
<ConnectAppField />
|
||||
) : null}
|
||||
{(showSmartWallet || !hideSwitchToPersonalWallet) && (
|
||||
<IconTextButton
|
||||
mt="xs"
|
||||
text={
|
||||
showSmartWallet
|
||||
? l.smart_wallet.switch_to_smart
|
||||
: l.smart_wallet.switch_to_personal
|
||||
}
|
||||
icon={
|
||||
<DisconnectIcon
|
||||
width={14}
|
||||
height={14}
|
||||
color={theme.colors.iconPrimary}
|
||||
/>
|
||||
}
|
||||
onPress={onWalletPress}
|
||||
/>
|
||||
)}
|
||||
{wallet?.walletId === walletIds.localWallet ||
|
||||
activeWallet?.walletId === walletIds.localWallet ? (
|
||||
<>
|
||||
|
||||
@@ -36,6 +36,12 @@ export type ConnectWalletDetailsProps = {
|
||||
* ```
|
||||
*/
|
||||
displayBalanceToken?: Record<number, string>;
|
||||
/**
|
||||
* Hide the "switch to Personal wallet" option in the dropdown which is shown when wallet is connected to a Smart Wallet
|
||||
*
|
||||
* @defaultValue false
|
||||
*/
|
||||
hideSwitchToPersonalWallet?: boolean;
|
||||
};
|
||||
|
||||
export const WalletDetailsButton = ({
|
||||
@@ -45,6 +51,7 @@ export const WalletDetailsButton = ({
|
||||
hideTestnetFaucet,
|
||||
supportedTokens,
|
||||
displayBalanceToken,
|
||||
hideSwitchToPersonalWallet,
|
||||
}: ConnectWalletDetailsProps) => {
|
||||
const l = useLocale();
|
||||
const activeWallet = useWallet();
|
||||
@@ -76,6 +83,7 @@ export const WalletDetailsButton = ({
|
||||
hideTestnetFaucet={hideTestnetFaucet}
|
||||
supportedTokens={supportedTokens}
|
||||
displayBalanceToken={displayBalanceToken}
|
||||
hideSwitchToPersonalWallet={hideSwitchToPersonalWallet}
|
||||
/>
|
||||
{detailsButton ? (
|
||||
detailsButton({ onPress })
|
||||
|
||||
+27
-20
@@ -1,7 +1,7 @@
|
||||
import { walletIds } from "@thirdweb-dev/wallets";
|
||||
import { ModalHeaderTextClose } from "../../base/modal/ModalHeaderTextClose";
|
||||
import { WalletConfig } from "@thirdweb-dev/react-core";
|
||||
import { ReactNode, useState } from "react";
|
||||
import { ReactNode, useMemo, useState } from "react";
|
||||
import Box from "../../base/Box";
|
||||
import Text from "../../base/Text";
|
||||
import ThirdwebLogo from "../../../assets/thirdweb-logo";
|
||||
@@ -33,7 +33,6 @@ export function ChooseWallet({
|
||||
onChooseWallet,
|
||||
modalTitleIconUrl,
|
||||
onClose,
|
||||
excludeWalletIds = [],
|
||||
termsOfServiceUrl,
|
||||
privacyPolicyUrl,
|
||||
}: ChooseWalletProps) {
|
||||
@@ -49,14 +48,25 @@ export function ChooseWallet({
|
||||
w.id === walletIds.magicLink ||
|
||||
(w.id === walletIds.embeddedWallet && w.selectUI),
|
||||
);
|
||||
const connectionWallets = wallets
|
||||
.filter(
|
||||
|
||||
const walletsToDisplay = useMemo(() => {
|
||||
const filteredWallets = wallets.filter(
|
||||
(wallet) =>
|
||||
wallet.id !== walletIds.magicLink &&
|
||||
wallet.id !== walletIds.embeddedWallet &&
|
||||
wallet.id !== walletIds.localWallet,
|
||||
)
|
||||
.slice(0, 2);
|
||||
);
|
||||
|
||||
const trueItems = filteredWallets.filter(
|
||||
(item) => item.recommended === true,
|
||||
);
|
||||
const falseItems = filteredWallets.filter(
|
||||
(item) => item.recommended !== true,
|
||||
);
|
||||
const sortedWallets = [...trueItems, ...falseItems];
|
||||
|
||||
return sortedWallets;
|
||||
}, [wallets]);
|
||||
|
||||
const showToSPrivacyPolicy = termsOfServiceUrl || privacyPolicyUrl;
|
||||
|
||||
@@ -74,7 +84,7 @@ export function ChooseWallet({
|
||||
};
|
||||
|
||||
const onSingleWalletPress = () => {
|
||||
onChooseWallet(connectionWallets[0]);
|
||||
onChooseWallet(walletsToDisplay[0]);
|
||||
};
|
||||
|
||||
const onBackPress = () => {
|
||||
@@ -135,13 +145,7 @@ export function ChooseWallet({
|
||||
{!emailWallet || isConnectAWalletEnabled ? (
|
||||
<>
|
||||
<ChooseWalletContent
|
||||
wallets={wallets}
|
||||
excludeWalletIds={[
|
||||
...excludeWalletIds,
|
||||
walletIds.localWallet,
|
||||
walletIds.magicLink,
|
||||
walletIds.embeddedWallet,
|
||||
]}
|
||||
wallets={walletsToDisplay}
|
||||
onChooseWallet={onChooseWallet}
|
||||
/>
|
||||
|
||||
@@ -176,7 +180,7 @@ export function ChooseWallet({
|
||||
) : null}
|
||||
{emailWallet &&
|
||||
!isConnectAWalletEnabled &&
|
||||
(guestWallet || connectionWallets.length > 0) ? (
|
||||
(guestWallet || walletsToDisplay.length > 0) ? (
|
||||
<Box
|
||||
mt="md"
|
||||
marginHorizontal="xl"
|
||||
@@ -193,15 +197,15 @@ export function ChooseWallet({
|
||||
) : null}
|
||||
{emailWallet &&
|
||||
!isConnectAWalletEnabled &&
|
||||
connectionWallets.length > 0 ? (
|
||||
connectionWallets.length === 1 ? (
|
||||
walletsToDisplay.length > 0 ? (
|
||||
walletsToDisplay.length === 1 ? (
|
||||
<WalletButton
|
||||
marginHorizontal="xl"
|
||||
paddingHorizontal="none"
|
||||
paddingVertical="none"
|
||||
mt="md"
|
||||
walletIconUrl={connectionWallets[0].meta.iconURL}
|
||||
name={connectionWallets[0].meta.name}
|
||||
walletIconUrl={walletsToDisplay[0].meta.iconURL}
|
||||
name={walletsToDisplay[0].meta.name}
|
||||
onPress={onSingleWalletPress}
|
||||
/>
|
||||
) : (
|
||||
@@ -217,7 +221,10 @@ export function ChooseWallet({
|
||||
borderWidth={1}
|
||||
onPress={onConnectAWalletPress}
|
||||
>
|
||||
{connectionWallets.map((wallet) => {
|
||||
{walletsToDisplay.map((wallet, index) => {
|
||||
if (index > 1) {
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
<Box key={wallet.meta.name} mr="xxs">
|
||||
<ImageSvgUri
|
||||
|
||||
+2
-22
@@ -1,4 +1,3 @@
|
||||
import { useMemo } from "react";
|
||||
import type { WalletConfig } from "@thirdweb-dev/react-core";
|
||||
import { Dimensions, ScrollView, View } from "react-native";
|
||||
import { WalletButton } from "../../base/WalletButton";
|
||||
@@ -7,7 +6,6 @@ import { useTheme } from "@shopify/restyle";
|
||||
|
||||
interface ChooseWalletContentProps {
|
||||
wallets: WalletConfig[];
|
||||
excludeWalletIds?: string[];
|
||||
onChooseWallet: (wallet: WalletConfig, data?: any) => void;
|
||||
}
|
||||
|
||||
@@ -15,27 +13,10 @@ const MAX_HEIGHT = Dimensions.get("window").height * 0.3;
|
||||
|
||||
export const ChooseWalletContent = ({
|
||||
wallets,
|
||||
excludeWalletIds,
|
||||
onChooseWallet,
|
||||
}: ChooseWalletContentProps) => {
|
||||
const theme = useTheme();
|
||||
|
||||
const walletsToDisplay = useMemo(() => {
|
||||
const filteredWallets = wallets.filter(
|
||||
(w) => !!!excludeWalletIds?.find((ewId) => ewId === w.id),
|
||||
);
|
||||
|
||||
const trueItems = filteredWallets.filter(
|
||||
(item) => item.recommended === true,
|
||||
);
|
||||
const falseItems = filteredWallets.filter(
|
||||
(item) => item.recommended !== true,
|
||||
);
|
||||
const sortedWallets = [...trueItems, ...falseItems];
|
||||
|
||||
return sortedWallets;
|
||||
}, [wallets, excludeWalletIds]);
|
||||
|
||||
return (
|
||||
<View style={{ flexDirection: "column", maxHeight: MAX_HEIGHT }}>
|
||||
<ScrollView
|
||||
@@ -45,9 +26,8 @@ export const ChooseWalletContent = ({
|
||||
paddingHorizontal: 16,
|
||||
}}
|
||||
>
|
||||
{walletsToDisplay.map((item, index) => {
|
||||
const marginBottom =
|
||||
index === walletsToDisplay.length - 1 ? "none" : "xxs";
|
||||
{wallets.map((item, index) => {
|
||||
const marginBottom = index === wallets.length - 1 ? "none" : "xxs";
|
||||
return (
|
||||
<Box key={item.id}>
|
||||
{item.selectUI ? (
|
||||
|
||||
@@ -13,12 +13,12 @@ export type ConnectWalletButtonProps = {
|
||||
theme?: ThemeProviderProps["theme"];
|
||||
/**
|
||||
* Set a custom title for the button
|
||||
* @default "Connect Wallet"
|
||||
* @defaultValue "Connect Wallet"
|
||||
*/
|
||||
buttonTitle?: string;
|
||||
/**
|
||||
* Set a custom title for the Connect Wallet modal
|
||||
* @default "Choose your wallet"
|
||||
* @defaultValue "Choose your wallet"
|
||||
*/
|
||||
modalTitle?: string;
|
||||
/**
|
||||
|
||||
+17
-14
@@ -188,14 +188,21 @@ export const LocalWalletImportModal = ({
|
||||
{l.common.password}
|
||||
</Text>
|
||||
<PasswordInput onChangeText={onChangeText} />
|
||||
<Text variant="bodySmall" color="red" mt="xs" textAlign="left">
|
||||
{error}
|
||||
</Text>
|
||||
{error ? (
|
||||
<Text
|
||||
variant="bodySmall"
|
||||
color="red"
|
||||
marginVertical="xxs"
|
||||
textAlign="left"
|
||||
>
|
||||
{error}
|
||||
</Text>
|
||||
) : null}
|
||||
<Box
|
||||
mb="xs"
|
||||
flexDirection="row"
|
||||
justifyContent="center"
|
||||
alignItems="center"
|
||||
mt="sm"
|
||||
>
|
||||
<Box height={1} flex={1} backgroundColor="border" />
|
||||
<Text variant="bodySmall" textAlign="center" marginHorizontal="xxs">
|
||||
@@ -214,23 +221,19 @@ export const LocalWalletImportModal = ({
|
||||
fontFamily: theme.textVariants.defaults.fontFamily,
|
||||
},
|
||||
}}
|
||||
containerProps={{ pl: "xxs" }}
|
||||
containerProps={{ pl: "xxs", mt: "sm" }}
|
||||
/>
|
||||
<Box
|
||||
flexDirection="row"
|
||||
justifyContent="center"
|
||||
paddingHorizontal="md"
|
||||
mt="lg"
|
||||
>
|
||||
<Box flexDirection="row" justifyContent="flex-end" mt="lg">
|
||||
<BaseButton
|
||||
backgroundColor="white"
|
||||
backgroundColor="accentButtonColor"
|
||||
borderColor="accentButtonColor"
|
||||
style={styles.modalButton}
|
||||
onPress={onImportPress}
|
||||
>
|
||||
{isImporting ? (
|
||||
<ActivityIndicator size="small" color="black" />
|
||||
<ActivityIndicator size="small" color="accentButtonTextColor" />
|
||||
) : (
|
||||
<Text variant="bodySmall" color="black">
|
||||
<Text variant="bodySmall" color="accentButtonTextColor">
|
||||
{l.common.import}
|
||||
</Text>
|
||||
)}
|
||||
|
||||
@@ -338,6 +338,7 @@ const SendFundsForm = ({
|
||||
<BaseButton
|
||||
mt="md"
|
||||
backgroundColor="accentButtonColor"
|
||||
borderColor="accentButtonColor"
|
||||
flexDirection="row"
|
||||
alignItems="center"
|
||||
justifyContent="center"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { shortenAddress } from "@thirdweb-dev/react-core";
|
||||
import { Theme } from "../../styles/theme";
|
||||
import { shortenWalletAddress } from "../../utils/addresses";
|
||||
import Text from "./Text";
|
||||
|
||||
type AddressProps = {
|
||||
@@ -16,7 +16,7 @@ export const AddressDisplay = ({
|
||||
}: AddressProps) => {
|
||||
return (
|
||||
<Text variant={variant} {...props}>
|
||||
{shortenWalletAddress(address, extraShort)}
|
||||
{shortenAddress(address, extraShort)}
|
||||
</Text>
|
||||
);
|
||||
};
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user