Compare commits
17
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4e5eb13b82 | ||
|
|
2b11353909 | ||
|
|
5882091eab | ||
|
|
8fc5f204b0 | ||
|
|
c953571588 | ||
|
|
edcd22d612 | ||
|
|
0d5503aae9 | ||
|
|
998e521733 | ||
|
|
be606dd3c9 | ||
|
|
d794b8f9f4 | ||
|
|
21b29490d4 | ||
|
|
7b1d62b323 | ||
|
|
e78da6b36c | ||
|
|
ed711c8cb2 | ||
|
|
05a7495a13 | ||
|
|
11bb053246 | ||
|
|
efb3546ec8 |
@@ -1,5 +1,26 @@
|
||||
# @thirdweb-dev/auth
|
||||
|
||||
## 3.2.7
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`2b113539`](https://github.com/thirdweb-dev/js/commit/2b113539098384f910b3c4d54e1fde9d35a6f053), [`be606dd3`](https://github.com/thirdweb-dev/js/commit/be606dd3c93c1514834c1d970e864d7f949a07ab), [`998e5217`](https://github.com/thirdweb-dev/js/commit/998e521733efd6a67e42f9bf0beab5fbdccf08ae)]:
|
||||
- @thirdweb-dev/wallets@1.0.3
|
||||
|
||||
## 3.2.6
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`ed711c8c`](https://github.com/thirdweb-dev/js/commit/ed711c8cb2ed6a0deb1b2a5eeec06df1d4edc5e8), [`05a7495a`](https://github.com/thirdweb-dev/js/commit/05a7495a132aabab5f48abbdb80a468ff6f65df8), [`e78da6b3`](https://github.com/thirdweb-dev/js/commit/e78da6b36cfa6d954234820563201bf760186ed1)]:
|
||||
- @thirdweb-dev/wallets@1.0.2
|
||||
|
||||
## 3.2.5
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`efb3546e`](https://github.com/thirdweb-dev/js/commit/efb3546ec8268156be00301af28b9d83ecd5ab08)]:
|
||||
- @thirdweb-dev/wallets@1.0.1
|
||||
|
||||
## 3.2.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@thirdweb-dev/auth",
|
||||
"version": "3.2.4",
|
||||
"version": "3.2.7",
|
||||
"main": "dist/thirdweb-dev-auth.cjs.js",
|
||||
"module": "dist/thirdweb-dev-auth.esm.js",
|
||||
"browser": {
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
# @thirdweb-dev/chains
|
||||
|
||||
## 0.1.26
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#1276](https://github.com/thirdweb-dev/js/pull/1276) [`5882091e`](https://github.com/thirdweb-dev/js/commit/5882091eab65978009a5a5305701f121851b10ad) Thanks [@MananTank](https://github.com/MananTank)! - Do not change order or RPCs in `getChainRPCs` to Fix RPC override issue
|
||||
|
||||
## 0.1.25
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -10,9 +10,9 @@ export default {
|
||||
},
|
||||
"rpc": [
|
||||
"https://ethereum.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
|
||||
"https://eth-mainnet.g.alchemy.com/v2/${ALCHEMY_API_KEY}",
|
||||
"https://mainnet.infura.io/v3/${INFURA_API_KEY}",
|
||||
"wss://mainnet.infura.io/ws/v3/${INFURA_API_KEY}",
|
||||
"https://eth-mainnet.g.alchemy.com/v2/${ALCHEMY_API_KEY}",
|
||||
"https://api.mycryptoapi.com/eth",
|
||||
"https://cloudflare-eth.com",
|
||||
"https://ethereum.publicnode.com"
|
||||
|
||||
@@ -4,8 +4,8 @@ export default {
|
||||
"chain": "ETH",
|
||||
"rpc": [
|
||||
"https://optimism.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
|
||||
"https://opt-mainnet.g.alchemy.com/v2/${ALCHEMY_API_KEY}",
|
||||
"https://optimism-mainnet.infura.io/v3/${INFURA_API_KEY}",
|
||||
"https://opt-mainnet.g.alchemy.com/v2/${ALCHEMY_API_KEY}",
|
||||
"https://mainnet.optimism.io/"
|
||||
],
|
||||
"faucets": [],
|
||||
|
||||
@@ -10,8 +10,8 @@ export default {
|
||||
},
|
||||
"rpc": [
|
||||
"https://polygon.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
|
||||
"https://polygon-mainnet.g.alchemy.com/v2/${ALCHEMY_API_KEY}",
|
||||
"https://polygon-mainnet.infura.io/v3/${INFURA_API_KEY}",
|
||||
"https://polygon-mainnet.g.alchemy.com/v2/${ALCHEMY_API_KEY}",
|
||||
"https://polygon-rpc.com/",
|
||||
"https://rpc-mainnet.matic.network",
|
||||
"https://matic-mainnet.chainstacklabs.com",
|
||||
|
||||
@@ -4,8 +4,8 @@ export default {
|
||||
"chain": "ETH",
|
||||
"rpc": [
|
||||
"https://optimism-goerli.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
|
||||
"https://opt-goerli.g.alchemy.com/v2/${ALCHEMY_API_KEY}",
|
||||
"https://optimism-goerli.infura.io/v3/${INFURA_API_KEY}",
|
||||
"https://opt-goerli.g.alchemy.com/v2/${ALCHEMY_API_KEY}",
|
||||
"https://goerli.optimism.io/"
|
||||
],
|
||||
"faucets": [
|
||||
|
||||
@@ -13,8 +13,8 @@ export default {
|
||||
},
|
||||
"rpc": [
|
||||
"https://arbitrum-goerli.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
|
||||
"https://arb-goerli.g.alchemy.com/v2/${ALCHEMY_API_KEY}",
|
||||
"https://arbitrum-goerli.infura.io/v3/${INFURA_API_KEY}",
|
||||
"https://arb-goerli.g.alchemy.com/v2/${ALCHEMY_API_KEY}",
|
||||
"https://goerli-rollup.arbitrum.io/rpc/"
|
||||
],
|
||||
"faucets": [],
|
||||
|
||||
@@ -5,9 +5,9 @@ export default {
|
||||
"chain": "ETH",
|
||||
"rpc": [
|
||||
"https://goerli.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
|
||||
"https://eth-goerli.g.alchemy.com/v2/${ALCHEMY_API_KEY}",
|
||||
"https://goerli.infura.io/v3/${INFURA_API_KEY}",
|
||||
"wss://goerli.infura.io/v3/${INFURA_API_KEY}",
|
||||
"https://eth-goerli.g.alchemy.com/v2/${ALCHEMY_API_KEY}",
|
||||
"https://rpc.goerli.mudit.blog/",
|
||||
"https://ethereum-goerli.publicnode.com"
|
||||
],
|
||||
|
||||
@@ -5,10 +5,10 @@ export default {
|
||||
"chain": "ETH",
|
||||
"rpc": [
|
||||
"https://linea-testnet.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
|
||||
"https://rpc.goerli.linea.build",
|
||||
"wss://rpc.goerli.linea.build",
|
||||
"https://linea-goerli.infura.io/v3/${INFURA_API_KEY}",
|
||||
"wss://linea-goerli.infura.io/v3/${INFURA_API_KEY}"
|
||||
"wss://linea-goerli.infura.io/v3/${INFURA_API_KEY}",
|
||||
"https://rpc.goerli.linea.build",
|
||||
"wss://rpc.goerli.linea.build"
|
||||
],
|
||||
"faucets": [
|
||||
"https://faucetlink.to/goerli"
|
||||
|
||||
@@ -11,8 +11,8 @@ export default {
|
||||
},
|
||||
"rpc": [
|
||||
"https://mumbai.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
|
||||
"https://polygon-mumbai.g.alchemy.com/v2/${ALCHEMY_API_KEY}",
|
||||
"https://polygon-mumbai.infura.io/v3/${INFURA_API_KEY}",
|
||||
"https://polygon-mumbai.g.alchemy.com/v2/${ALCHEMY_API_KEY}",
|
||||
"https://matic-mumbai.chainstacklabs.com",
|
||||
"https://rpc-mumbai.maticvigil.com",
|
||||
"https://matic-testnet-archive-rpc.bwarelabs.com",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@thirdweb-dev/chains",
|
||||
"version": "0.1.25",
|
||||
"version": "0.1.26",
|
||||
"main": "dist/thirdweb-dev-chains.cjs.js",
|
||||
"module": "dist/thirdweb-dev-chains.esm.js",
|
||||
"browser": {
|
||||
|
||||
@@ -80,6 +80,33 @@ chains = chains
|
||||
};
|
||||
});
|
||||
|
||||
/**
|
||||
* Sort RPCs in chain
|
||||
* @param {Chain} chain
|
||||
*/
|
||||
function sortRPCs(chain) {
|
||||
const thirdwebRPCs = [];
|
||||
const alchemyRPCs = [];
|
||||
const infuraRPCs = [];
|
||||
const otherRPCs = [];
|
||||
|
||||
chain.rpc.forEach((rpc) => {
|
||||
if (rpc.includes("${THIRDWEB_API_KEY}")) {
|
||||
thirdwebRPCs.push(rpc);
|
||||
} else if (rpc.includes("${ALCHEMY_API_KEY}")) {
|
||||
alchemyRPCs.push(rpc);
|
||||
} else if (rpc.includes("${INFURA_API_KEY}")) {
|
||||
infuraRPCs.push(rpc);
|
||||
} else {
|
||||
otherRPCs.push(rpc);
|
||||
}
|
||||
});
|
||||
|
||||
chain.rpc = [...thirdwebRPCs, ...infuraRPCs, ...alchemyRPCs, ...otherRPCs];
|
||||
}
|
||||
|
||||
chains.forEach(sortRPCs);
|
||||
|
||||
const imports = [];
|
||||
const exports = [];
|
||||
const exportNames = [];
|
||||
|
||||
@@ -28,59 +28,45 @@ export function getChainRPCs(
|
||||
...options,
|
||||
};
|
||||
|
||||
const modeChains = chain.rpc.filter((rpc) => {
|
||||
if (rpc.startsWith("http") && mode === "http") {
|
||||
return true;
|
||||
}
|
||||
if (rpc.startsWith("ws") && mode === "ws") {
|
||||
return true;
|
||||
const processedRPCs: string[] = [];
|
||||
|
||||
chain.rpc.forEach((rpc) => {
|
||||
// exclude RPC if mode mismatch
|
||||
if (mode === "http" && !rpc.startsWith("http")) {
|
||||
return;
|
||||
}
|
||||
|
||||
return false;
|
||||
if (mode === "ws" && !rpc.startsWith("ws")) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Replace API_KEY placeholder with value
|
||||
if (thirdwebApiKey && rpc.includes("${THIRDWEB_API_KEY}")) {
|
||||
processedRPCs.push(rpc.replace("${THIRDWEB_API_KEY}", thirdwebApiKey));
|
||||
} else if (infuraApiKey && rpc.includes("${INFURA_API_KEY}")) {
|
||||
processedRPCs.push(rpc.replace("${INFURA_API_KEY}", infuraApiKey));
|
||||
} else if (alchemyApiKey && rpc.includes("${ALCHEMY_API_KEY}")) {
|
||||
processedRPCs.push(rpc.replace("${ALCHEMY_API_KEY}", alchemyApiKey));
|
||||
}
|
||||
|
||||
// exclude RPCs with unknown placeholder
|
||||
else if (rpc.includes("${")) {
|
||||
return;
|
||||
}
|
||||
|
||||
// add as is
|
||||
else {
|
||||
processedRPCs.push(rpc);
|
||||
}
|
||||
});
|
||||
|
||||
const thirdwebRPC = modeChains
|
||||
.filter((rpc) => {
|
||||
return rpc.includes("${THIRDWEB_API_KEY}") && thirdwebApiKey;
|
||||
})
|
||||
.map((rpc) =>
|
||||
thirdwebApiKey ? rpc.replace("${THIRDWEB_API_KEY}", thirdwebApiKey) : rpc,
|
||||
);
|
||||
|
||||
const alchemyRPC = modeChains
|
||||
.filter((rpc) => {
|
||||
return rpc.includes("${ALCHEMY_API_KEY}") && alchemyApiKey;
|
||||
})
|
||||
.map((rpc) =>
|
||||
alchemyApiKey ? rpc.replace("${ALCHEMY_API_KEY}", alchemyApiKey) : rpc,
|
||||
);
|
||||
|
||||
const infuraRPC = modeChains
|
||||
.filter((rpc) => {
|
||||
return rpc.includes("${INFURA_API_KEY}") && infuraApiKey;
|
||||
})
|
||||
.map((rpc) =>
|
||||
infuraApiKey ? rpc.replace("${INFURA_API_KEY}", infuraApiKey) : rpc,
|
||||
);
|
||||
|
||||
const allOtherRpcs = modeChains.filter((rpc) => {
|
||||
return !rpc.includes("${");
|
||||
});
|
||||
|
||||
const orderedRPCs = [
|
||||
...thirdwebRPC,
|
||||
...infuraRPC,
|
||||
...alchemyRPC,
|
||||
...allOtherRpcs,
|
||||
];
|
||||
|
||||
if (orderedRPCs.length === 0) {
|
||||
if (processedRPCs.length === 0) {
|
||||
throw new Error(
|
||||
`No RPC available for chainId "${chain.chainId}" with mode ${mode}`,
|
||||
);
|
||||
}
|
||||
|
||||
return orderedRPCs;
|
||||
return processedRPCs;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,15 @@
|
||||
# thirdweb
|
||||
|
||||
## 0.10.28
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#1274](https://github.com/thirdweb-dev/js/pull/1274) [`8fc5f204`](https://github.com/thirdweb-dev/js/commit/8fc5f204b00733089c02beee92c86b0f1fcac271) Thanks [@Marfuen](https://github.com/Marfuen)! - Added all detections for deploy command and some minor bug fixes
|
||||
|
||||
- Updated dependencies [[`2b113539`](https://github.com/thirdweb-dev/js/commit/2b113539098384f910b3c4d54e1fde9d35a6f053), [`c9535715`](https://github.com/thirdweb-dev/js/commit/c95357158819abd42d4b0900ecc2fa40fcb957f8), [`5882091e`](https://github.com/thirdweb-dev/js/commit/5882091eab65978009a5a5305701f121851b10ad)]:
|
||||
- @thirdweb-dev/sdk@3.10.27
|
||||
- @thirdweb-dev/chains@0.1.26
|
||||
|
||||
## 0.10.27
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -2,7 +2,7 @@ import { CREATE_MESSAGES } from "../constants/constants";
|
||||
import { prepareEnvironment } from "@gmrchk/cli-testing-library";
|
||||
|
||||
// this creates an app, can take some time that's fine
|
||||
jest.setTimeout(120_000);
|
||||
jest.setTimeout(240_000);
|
||||
|
||||
describe("npx thirdweb detect", () => {
|
||||
it("should detect ERC721Base extensions", async () => {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "thirdweb",
|
||||
"main": "dist/cli/index.js",
|
||||
"version": "0.10.27",
|
||||
"version": "0.10.28",
|
||||
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/cli",
|
||||
"author": "thirdweb eng <[email protected]>",
|
||||
"license": "Apache-2.0",
|
||||
|
||||
@@ -1,27 +1,28 @@
|
||||
import inquirer from "inquirer";
|
||||
import { info } from "../helpers/logger";
|
||||
import { FrameworkType, PackageManagerType } from "../types/ProjectType";
|
||||
import inquirer from "inquirer";
|
||||
import NextDetector from "./frameworks/next";
|
||||
import CRADetector from "./frameworks/cra";
|
||||
import RemixDetector from "./frameworks/remix";
|
||||
import GatsbyDetector from "./frameworks/gatsby";
|
||||
import VueDetector from "./frameworks/vue";
|
||||
import ReactNativeCLIDetector from "./frameworks/reactNativeCli";
|
||||
import DjangoDetector from "./frameworks/django";
|
||||
import ExpoDetector from "./frameworks/expo";
|
||||
import FoundryDetector from "./frameworks/foundry";
|
||||
import HardhatDetector from "./frameworks/hardhat";
|
||||
import { FrameworkDetector } from "./detector";
|
||||
import TruffleDetector from "./frameworks/truffle";
|
||||
import BrownieDetector from "./frameworks/brownie";
|
||||
import FastAPIDetector from "./frameworks/fastAPI";
|
||||
import FlaskDetector from "./frameworks/flask";
|
||||
import PopulusDetector from "./frameworks/populus";
|
||||
import FastifyDetector from "./frameworks/fastify";
|
||||
import CRADetector from "./frameworks/cra";
|
||||
import DjangoDetector from "./frameworks/django";
|
||||
import EchoDetector from "./frameworks/echo";
|
||||
import ExpoDetector from "./frameworks/expo";
|
||||
import FastAPIDetector from "./frameworks/fastAPI";
|
||||
import FastifyDetector from "./frameworks/fastify";
|
||||
import FiberDetector from "./frameworks/fiber";
|
||||
import FlaskDetector from "./frameworks/flask";
|
||||
import FoundryDetector from "./frameworks/foundry";
|
||||
import GatsbyDetector from "./frameworks/gatsby";
|
||||
import GinDetector from "./frameworks/gin";
|
||||
import HardhatDetector from "./frameworks/hardhat";
|
||||
import NextDetector from "./frameworks/next";
|
||||
import PopulusDetector from "./frameworks/populus";
|
||||
import ReactNativeCLIDetector from "./frameworks/reactNativeCli";
|
||||
import RemixDetector from "./frameworks/remix";
|
||||
import RevelDetector from "./frameworks/revel";
|
||||
import TruffleDetector from "./frameworks/truffle";
|
||||
import ViteDetector from "./frameworks/vite";
|
||||
import VueDetector from "./frameworks/vue";
|
||||
import ZenjectDetector from "./frameworks/zenject";
|
||||
|
||||
export default async function detect(
|
||||
@@ -50,6 +51,7 @@ export default async function detect(
|
||||
new RevelDetector(),
|
||||
new TruffleDetector(),
|
||||
new VueDetector(),
|
||||
new ViteDetector(),
|
||||
new ZenjectDetector(),
|
||||
];
|
||||
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
import inquirer from "inquirer";
|
||||
import { info } from "../helpers/logger";
|
||||
import { LibraryType, PackageManagerType } from "../types/ProjectType";
|
||||
import { LibraryDetector } from "./detector";
|
||||
import inquirer from "inquirer";
|
||||
import ReactDetector from "./libraries/react";
|
||||
import ExpressDetector from "./libraries/express";
|
||||
import ReactNativeDetector from "./libraries/reactNative";
|
||||
import ViteDetector from "./libraries/vite";
|
||||
import Web3PyDetector from "./libraries/web3py";
|
||||
import PlayMakerDetector from "./libraries/playmaker";
|
||||
import ReactDetector from "./libraries/react";
|
||||
import ReactNativeDetector from "./libraries/reactNative";
|
||||
import Web3PyDetector from "./libraries/web3py";
|
||||
|
||||
export default async function detect(
|
||||
path: string,
|
||||
@@ -19,7 +18,6 @@ export default async function detect(
|
||||
new ExpressDetector(),
|
||||
new ReactDetector(),
|
||||
new ReactNativeDetector(),
|
||||
new ViteDetector(),
|
||||
new Web3PyDetector(),
|
||||
new PlayMakerDetector(),
|
||||
];
|
||||
|
||||
+5
-5
@@ -1,10 +1,10 @@
|
||||
import { LibraryDetector } from "../detector";
|
||||
import { existsSync, readFileSync } from "fs";
|
||||
import { LibraryType } from "../../types/ProjectType";
|
||||
import { parsePackageJson } from "../../../lib/utils";
|
||||
import { FrameworkType } from "../../types/ProjectType";
|
||||
import { FrameworkDetector } from "../detector";
|
||||
|
||||
export default class ViteDetector implements LibraryDetector {
|
||||
public libraryType: LibraryType = "vite";
|
||||
export default class ViteDetector implements FrameworkDetector {
|
||||
public frameworkType: FrameworkType = "vite";
|
||||
|
||||
public matches(path: string): boolean {
|
||||
const packageJsonPath = path + "/package.json";
|
||||
@@ -16,7 +16,7 @@ export default class ViteDetector implements LibraryDetector {
|
||||
const packageJson = readFileSync(packageJsonPath);
|
||||
const { dependencies, devDependencies } = parsePackageJson(packageJson);
|
||||
const viteDependencyExists =
|
||||
dependencies["vite"] || devDependencies["vite"] || false;
|
||||
!!dependencies["vite"] || !!devDependencies["vite"] || false;
|
||||
|
||||
return viteDependencyExists;
|
||||
}
|
||||
@@ -56,6 +56,7 @@ export type FrameworkType =
|
||||
| "revel"
|
||||
| "fiber"
|
||||
| "zenject"
|
||||
| "vite"
|
||||
| "none";
|
||||
export type LibraryType =
|
||||
| "react"
|
||||
|
||||
@@ -1,30 +1,57 @@
|
||||
import NPMDetector from "../core/detection/npm";
|
||||
import ViteDetector from "../core/detection/vite";
|
||||
import YarnDetector from "../core/detection/yarn";
|
||||
import { ThirdwebStorage } from "@thirdweb-dev/storage";
|
||||
import detectFramework from "../core/detection/detectFramework";
|
||||
import detectPackageManager from "../core/detection/detectPackageManager";
|
||||
import { logger } from "../core/helpers/logger";
|
||||
import { runCommand } from "../create/helpers/run-command";
|
||||
import { upload } from "../storage/command";
|
||||
import { ThirdwebStorage } from "@thirdweb-dev/storage";
|
||||
|
||||
export async function deployApp(distPath = "dist", projectPath = ".") {
|
||||
const storage = new ThirdwebStorage();
|
||||
const supportedFrameworks = [new ViteDetector()];
|
||||
const detectedPackageManager = await detectPackageManager(projectPath, {});
|
||||
const detectedFramework = await detectFramework(projectPath, {}, detectedPackageManager);
|
||||
|
||||
const possibleProjects = supportedFrameworks
|
||||
.filter((detector) => detector.matches(projectPath))
|
||||
.map((detector) => detector.projectType);
|
||||
|
||||
const hasYarn = new YarnDetector().matches(".");
|
||||
const hasNPM = new NPMDetector().matches(".");
|
||||
|
||||
if (possibleProjects.length === 0) {
|
||||
if (detectedFramework === "none") {
|
||||
throw new Error("No supported project detected");
|
||||
}
|
||||
|
||||
switch (detectedFramework) {
|
||||
case "next":
|
||||
distPath = "out";
|
||||
break;
|
||||
case "cra":
|
||||
distPath = "build";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
logger.info(`Detected project type: ${detectedFramework}`);
|
||||
logger.info(`Detected package manager: ${detectedPackageManager}`);
|
||||
logger.info(`distPath: ${distPath}`);
|
||||
logger.info(`projectPath: ${projectPath}`);
|
||||
|
||||
try {
|
||||
if (hasYarn) {
|
||||
await runCommand("yarn", ["build"]);
|
||||
} else if (hasNPM) {
|
||||
await runCommand("npm", ["build"]);
|
||||
switch (detectedPackageManager) {
|
||||
case "yarn":
|
||||
await runCommand("yarn", ["build"], true);
|
||||
if (detectedFramework === "next") {
|
||||
await runCommand("yarn", ["export"], true);
|
||||
}
|
||||
break;
|
||||
case "npm":
|
||||
await runCommand("npm", ["run", "build"], true);
|
||||
if (detectedFramework === "next") {
|
||||
await runCommand("npm", ["run", "export"], true);
|
||||
}
|
||||
break;
|
||||
case "pnpm":
|
||||
await runCommand("pnpm", ["build"], true);
|
||||
if (detectedFramework === "next") {
|
||||
await runCommand("pnpm", ["export"], true);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new Error("No supported package manager detected");
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("Can't build project");
|
||||
@@ -33,9 +60,9 @@ export async function deployApp(distPath = "dist", projectPath = ".") {
|
||||
|
||||
try {
|
||||
const uri = await upload(storage, distPath);
|
||||
return `https://thirdweb.com/app/deploy/${uri.replace("ipfs://", "")}`;
|
||||
return `${uri.replace("ipfs://", "https://ipfs-public.thirdwebcdn.com/ipfs/")}`;
|
||||
} catch (err) {
|
||||
console.error("Can't upload project");
|
||||
console.error("Can't upload project", err);
|
||||
return Promise.reject("Can't upload project");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { spinner } from "../core/helpers/logger";
|
||||
import { BufferOrStringWithName, ThirdwebStorage } from "@thirdweb-dev/storage";
|
||||
import fs from "fs";
|
||||
import path from "path";
|
||||
import { spinner } from "../core/helpers/logger";
|
||||
|
||||
function recurseFiles(
|
||||
uploadPath: string,
|
||||
|
||||
@@ -1,5 +1,32 @@
|
||||
# @thirdweb-dev/react-core
|
||||
|
||||
## 3.14.7
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#1271](https://github.com/thirdweb-dev/js/pull/1271) [`c9535715`](https://github.com/thirdweb-dev/js/commit/c95357158819abd42d4b0900ecc2fa40fcb957f8) Thanks [@nkrishang](https://github.com/nkrishang)! - Rename smart wallets to account
|
||||
|
||||
- [#1273](https://github.com/thirdweb-dev/js/pull/1273) [`edcd22d6`](https://github.com/thirdweb-dev/js/commit/edcd22d61236edb2832f9b2f9796e891d58cb145) Thanks [@MananTank](https://github.com/MananTank)! - Add `autoConnectTimeout` to `ThirdwebProvider` to timeout wallet autoconnect
|
||||
|
||||
- Updated dependencies [[`2b113539`](https://github.com/thirdweb-dev/js/commit/2b113539098384f910b3c4d54e1fde9d35a6f053), [`c9535715`](https://github.com/thirdweb-dev/js/commit/c95357158819abd42d4b0900ecc2fa40fcb957f8), [`be606dd3`](https://github.com/thirdweb-dev/js/commit/be606dd3c93c1514834c1d970e864d7f949a07ab), [`5882091e`](https://github.com/thirdweb-dev/js/commit/5882091eab65978009a5a5305701f121851b10ad), [`998e5217`](https://github.com/thirdweb-dev/js/commit/998e521733efd6a67e42f9bf0beab5fbdccf08ae)]:
|
||||
- @thirdweb-dev/wallets@1.0.3
|
||||
- @thirdweb-dev/sdk@3.10.27
|
||||
- @thirdweb-dev/chains@0.1.26
|
||||
|
||||
## 3.14.6
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`ed711c8c`](https://github.com/thirdweb-dev/js/commit/ed711c8cb2ed6a0deb1b2a5eeec06df1d4edc5e8), [`05a7495a`](https://github.com/thirdweb-dev/js/commit/05a7495a132aabab5f48abbdb80a468ff6f65df8), [`e78da6b3`](https://github.com/thirdweb-dev/js/commit/e78da6b36cfa6d954234820563201bf760186ed1)]:
|
||||
- @thirdweb-dev/wallets@1.0.2
|
||||
|
||||
## 3.14.5
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`efb3546e`](https://github.com/thirdweb-dev/js/commit/efb3546ec8268156be00301af28b9d83ecd5ab08)]:
|
||||
- @thirdweb-dev/wallets@1.0.1
|
||||
|
||||
## 3.14.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@thirdweb-dev/react-core",
|
||||
"version": "3.14.4",
|
||||
"version": "3.14.7",
|
||||
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/react-core",
|
||||
"author": "thirdweb eng <[email protected]>",
|
||||
"license": "Apache-2.0",
|
||||
|
||||
@@ -61,6 +61,15 @@ export interface ThirdwebProviderCoreProps<TChains extends Chain[]>
|
||||
* Whether or not to automatically switch to wallet's network to active chain
|
||||
*/
|
||||
autoSwitch?: boolean;
|
||||
|
||||
/**
|
||||
* Timeout for auto-connecting wallet in milliseconds
|
||||
*
|
||||
* If wallet fails to connect in this time, it will stop trying to connect and user will have to manually connect
|
||||
*
|
||||
* @defaultValue 15000
|
||||
*/
|
||||
autoConnectTimeout?: number;
|
||||
}
|
||||
|
||||
export const ThirdwebProviderCore = <TChains extends Chain[]>({
|
||||
@@ -145,6 +154,7 @@ export const ThirdwebProviderCore = <TChains extends Chain[]>({
|
||||
dAppMeta={dAppMeta}
|
||||
activeChain={activeChainWithKey}
|
||||
autoSwitch={props.autoSwitch}
|
||||
autoConnectTimeout={props.autoConnectTimeout}
|
||||
>
|
||||
<ThirdwebSDKProviderWrapper
|
||||
queryClient={props.queryClient}
|
||||
|
||||
@@ -101,12 +101,15 @@ export function ThirdwebWalletProvider(
|
||||
dAppMeta?: DAppMetaData;
|
||||
chains: Chain[];
|
||||
autoSwitch?: boolean;
|
||||
autoConnectTimeout?: number;
|
||||
}>,
|
||||
) {
|
||||
const [signer, setSigner] = useState<Signer | undefined>(undefined);
|
||||
const [connectionStatus, setConnectionStatus] =
|
||||
useState<ConnectionStatus>("unknown");
|
||||
|
||||
const autoConnectTimeout = props.autoConnectTimeout || 15000;
|
||||
|
||||
const [activeWallet, setActiveWallet] = useState<
|
||||
WalletInstance | undefined
|
||||
>();
|
||||
@@ -311,8 +314,14 @@ export function ThirdwebWalletProvider(
|
||||
const personalWalletInstance = createWalletInstance(personalWalleObj);
|
||||
|
||||
try {
|
||||
await personalWalletInstance.autoConnect(
|
||||
personalWalletInfo.connectParams,
|
||||
await timeoutPromise(
|
||||
personalWalletInstance.autoConnect(
|
||||
personalWalletInfo.connectParams,
|
||||
),
|
||||
{
|
||||
ms: autoConnectTimeout,
|
||||
message: "Failed to Auto connect. Auto connect timed out.",
|
||||
},
|
||||
);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
@@ -337,7 +346,10 @@ export function ThirdwebWalletProvider(
|
||||
|
||||
try {
|
||||
setConnectionStatus("connecting");
|
||||
await wallet.autoConnect(walletInfo.connectParams);
|
||||
await timeoutPromise(wallet.autoConnect(walletInfo.connectParams), {
|
||||
ms: autoConnectTimeout,
|
||||
message: "Failed to Auto connect. Auto connect timed out.",
|
||||
});
|
||||
setConnectedWallet(wallet, walletInfo.connectParams, true);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
@@ -356,6 +368,7 @@ export function ThirdwebWalletProvider(
|
||||
props.shouldAutoConnect,
|
||||
activeWallet,
|
||||
connectionStatus,
|
||||
autoConnectTimeout,
|
||||
]);
|
||||
|
||||
const connectWallet = useCallback(
|
||||
@@ -496,3 +509,32 @@ async function saveLastConnectedWalletInfo(
|
||||
console.error("Error saving the last connected wallet info", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Timeout a promise with a given Error message if the promise does not resolve in given time
|
||||
*
|
||||
* @param promise - Promise to track for timeout
|
||||
* @param option - timeout options
|
||||
* @returns
|
||||
*/
|
||||
function timeoutPromise<T>(
|
||||
promise: Promise<T>,
|
||||
option: { ms: number; message: string },
|
||||
) {
|
||||
return new Promise<T>((resolve, reject) => {
|
||||
const timeoutId = setTimeout(() => {
|
||||
reject(new Error(option.message));
|
||||
}, option.ms);
|
||||
|
||||
promise.then(
|
||||
(res) => {
|
||||
clearTimeout(timeoutId);
|
||||
resolve(res);
|
||||
},
|
||||
(err) => {
|
||||
clearTimeout(timeoutId);
|
||||
reject(err);
|
||||
},
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -0,0 +1,185 @@
|
||||
import {
|
||||
RequiredParam,
|
||||
requiredParamInvariant,
|
||||
} from "../../../core/query-utils/required-param";
|
||||
import { useSDKChainId } from "../../providers/thirdweb-sdk-provider";
|
||||
import { WalletAddress } from "../../types";
|
||||
import {
|
||||
cacheKeys,
|
||||
invalidateContractAndBalances,
|
||||
} from "../../utils/cache-keys";
|
||||
import { useQueryWithNetwork } from "../query-utils/useQueryWithNetwork";
|
||||
import {
|
||||
useMutation,
|
||||
useQueryClient,
|
||||
UseQueryResult,
|
||||
} from "@tanstack/react-query";
|
||||
import type { AccountEvent, SmartContract } from "@thirdweb-dev/sdk";
|
||||
import type { BytesLike } from "ethers";
|
||||
import invariant from "tiny-invariant";
|
||||
|
||||
/** **********************/
|
||||
/** READ HOOKS **/
|
||||
/** **********************/
|
||||
|
||||
/**
|
||||
* Get all accounts
|
||||
*
|
||||
* @example
|
||||
* ```javascript
|
||||
* const { data: accounts, isLoading, error } = useAccounts(contract);
|
||||
* ```
|
||||
*
|
||||
* @param contract - an instance of a account factory contract
|
||||
* @returns a response object that includes an array of all accounts with their associated admin
|
||||
* @twfeature AccountFactory
|
||||
* @see {@link https://portal.thirdweb.com/react/react.useaccounts?utm_source=sdk | Documentation}
|
||||
* @beta
|
||||
*/
|
||||
export function useAccounts(
|
||||
contract: RequiredParam<SmartContract>,
|
||||
): UseQueryResult<AccountEvent[]> {
|
||||
const contractAddress = contract?.getAddress();
|
||||
return useQueryWithNetwork(
|
||||
cacheKeys.contract.accountFactory.getAll(contractAddress),
|
||||
() => {
|
||||
requiredParamInvariant(contract, "No Contract instance provided");
|
||||
invariant(
|
||||
contract.accountFactory.getAllAccounts,
|
||||
"Contract instance does not support contract.accountFactory.getAllAccounts",
|
||||
);
|
||||
return contract.accountFactory.getAllAccounts();
|
||||
},
|
||||
{ enabled: !!contract },
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all accounts associated with the provided address
|
||||
*
|
||||
* @example
|
||||
* ```javascript
|
||||
* const { data: accountsForAddress, isLoading, error } = useAccountsForAddress(contract, "{{account_address}}");
|
||||
* ```
|
||||
*
|
||||
* @param contract - an instance of a account factory contract
|
||||
* @returns a response object that includes an array of all accounts associated with the adress
|
||||
* @twfeature AccountFactory
|
||||
* @see {@link https://portal.thirdweb.com/react/react.useaccountsforaddress?utm_source=sdk | Documentation}
|
||||
* @beta
|
||||
*/
|
||||
export function useAccountsForAddress(
|
||||
contract: RequiredParam<SmartContract>,
|
||||
address: RequiredParam<WalletAddress>,
|
||||
): UseQueryResult<string[]> {
|
||||
const contractAddress = contract?.getAddress();
|
||||
return useQueryWithNetwork(
|
||||
cacheKeys.contract.accountFactory.getAllForAddress(
|
||||
contractAddress,
|
||||
address,
|
||||
),
|
||||
() => {
|
||||
requiredParamInvariant(contract, "No Contract instance provided");
|
||||
invariant(
|
||||
contract.accountFactory.getAssociatedAccounts,
|
||||
"Contract instance does not support contract.accountFactory.getAssociatedAccounts",
|
||||
);
|
||||
return contract.accountFactory.getAssociatedAccounts(address || "");
|
||||
},
|
||||
{ enabled: !!contract },
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a account has been deployed for the given admin
|
||||
*
|
||||
* @example
|
||||
* ```javascript
|
||||
* const { data: isAccountDeployed, isLoading, error } = useIsAccountDeployed(contract);
|
||||
* ```
|
||||
*
|
||||
* @param contract - an instance of a account factory contract
|
||||
* @returns a boolean indicating if a account has been deployed for the given admin
|
||||
* @twfeature AccountFactory
|
||||
* @see {@link https://portal.thirdweb.com/react/react.useisaccountdeployed?utm_source=sdk | Documentation}
|
||||
* @beta
|
||||
*/
|
||||
export function useIsAccountDeployed(
|
||||
contract: RequiredParam<SmartContract>,
|
||||
admin: RequiredParam<WalletAddress>,
|
||||
extraData?: BytesLike,
|
||||
): UseQueryResult<boolean> {
|
||||
const contractAddress = contract?.getAddress();
|
||||
return useQueryWithNetwork(
|
||||
cacheKeys.contract.accountFactory.isAccountDeployed(contractAddress, admin),
|
||||
() => {
|
||||
requiredParamInvariant(contract, "No Contract instance provided");
|
||||
invariant(
|
||||
contract.accountFactory.isAccountDeployed,
|
||||
"Contract instance does not support contract.accountFactory.getAllAccounts",
|
||||
);
|
||||
invariant(admin, "No account address provided");
|
||||
return contract.accountFactory.isAccountDeployed(admin, extraData);
|
||||
},
|
||||
{ enabled: !!contract },
|
||||
);
|
||||
}
|
||||
|
||||
/** **********************/
|
||||
/** WRITE HOOKS **/
|
||||
/** **********************/
|
||||
/**
|
||||
* Create a account
|
||||
*
|
||||
* @example
|
||||
* ```jsx
|
||||
* const Component = () => {
|
||||
* const { contract } = useContract("{{contract_address}}");
|
||||
* const {
|
||||
* mutate: createAccount,
|
||||
* isLoading,
|
||||
* error,
|
||||
* } = useCreateAccount(contract);
|
||||
*
|
||||
* if (error) {
|
||||
* console.error("failed to create account", error);
|
||||
* }
|
||||
*
|
||||
* return (
|
||||
* <button
|
||||
* disabled={isLoading}
|
||||
* onClick={() => createAccount("0x...")}
|
||||
* >
|
||||
* Create Account
|
||||
* </button>
|
||||
* );
|
||||
* };
|
||||
* ```
|
||||
*
|
||||
* @param contract - an instance of a account factory contract
|
||||
* @returns a mutation object that can be used to create a account
|
||||
* @twfeature AccountFactory
|
||||
* @see {@link https://portal.thirdweb.com/react/react.usecreateaccount?utm_source=sdk | Documentation}
|
||||
* @beta
|
||||
*/
|
||||
export function useCreateAccount(contract: RequiredParam<SmartContract>) {
|
||||
const activeChainId = useSDKChainId();
|
||||
const contractAddress = contract?.getAddress();
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
return useMutation(
|
||||
async (admin: string, extraData?: BytesLike) => {
|
||||
requiredParamInvariant(contract, "contract is undefined");
|
||||
|
||||
return contract.accountFactory.createAccount(admin, extraData);
|
||||
},
|
||||
{
|
||||
onSettled: () =>
|
||||
invalidateContractAndBalances(
|
||||
queryClient,
|
||||
contractAddress,
|
||||
activeChainId,
|
||||
),
|
||||
},
|
||||
);
|
||||
}
|
||||
+23
-23
@@ -27,32 +27,32 @@ import invariant from "tiny-invariant";
|
||||
/** **********************/
|
||||
|
||||
/**
|
||||
* Get all wallets
|
||||
* Get all accounts
|
||||
*
|
||||
* @example
|
||||
* ```javascript
|
||||
* const { data: smartWallets, isLoading, error } = useSmartWalletSigners(contract);
|
||||
* const { data: accounts, isLoading, error } = useAccountSigners(contract);
|
||||
* ```
|
||||
*
|
||||
* @param contract - an instance of a smart wallet
|
||||
* @returns a response object that includes an array of all signers of the provided smart wallet
|
||||
* @twfeature SmartWallet
|
||||
* @see {@link https://portal.thirdweb.com/react/react.usesmartwalletsigners?utm_source=sdk | Documentation}
|
||||
* @param contract - an instance of a account
|
||||
* @returns a response object that includes an array of all signers of the provided account
|
||||
* @twfeature Account
|
||||
* @see {@link https://portal.thirdweb.com/react/react.useaccountsigners?utm_source=sdk | Documentation}
|
||||
* @beta
|
||||
*/
|
||||
export function useSmartWalletSigners(
|
||||
export function useAccountSigners(
|
||||
contract: RequiredParam<SmartContract>,
|
||||
): UseQueryResult<SignerWithRestrictions[]> {
|
||||
const contractAddress = contract?.getAddress();
|
||||
return useQueryWithNetwork(
|
||||
cacheKeys.contract.smartWallet.signers(contractAddress),
|
||||
cacheKeys.contract.account.signers(contractAddress),
|
||||
() => {
|
||||
requiredParamInvariant(contract, "No Contract instance provided");
|
||||
invariant(
|
||||
contract.smartWallet.getSignersWithRestrictions,
|
||||
"Contract instance does not support contract.smartWallet.getSignersWithRestrictions",
|
||||
contract.account.getSignersWithRestrictions,
|
||||
"Contract instance does not support contract.account.getSignersWithRestrictions",
|
||||
);
|
||||
return contract.smartWallet.getSignersWithRestrictions();
|
||||
return contract.account.getSignersWithRestrictions();
|
||||
},
|
||||
{ enabled: !!contract },
|
||||
);
|
||||
@@ -62,40 +62,40 @@ export function useSmartWalletSigners(
|
||||
/** WRITE HOOKS **/
|
||||
/** **********************/
|
||||
/**
|
||||
* Set the wallet's entire snapshot of permissions
|
||||
* Set the account's entire snapshot of permissions
|
||||
*
|
||||
* @example
|
||||
* ```jsx
|
||||
* const Component = () => {
|
||||
* const { contract } = useContract("{{contract_address}}");
|
||||
* const {
|
||||
* mutate: setSmartWalletSigners,
|
||||
* mutate: setAccountSigners,
|
||||
* isLoading,
|
||||
* error,
|
||||
* } = useSetSmartWalletSigners(contract);
|
||||
* } = useSetAccountSigners(contract);
|
||||
*
|
||||
* if (error) {
|
||||
* console.error("failed to set smart wallet signers", error);
|
||||
* console.error("failed to set account signers", error);
|
||||
* }
|
||||
*
|
||||
* return (
|
||||
* <button
|
||||
* disabled={isLoading}
|
||||
* onClick={() => setSmartWalletSigners("0x...")}
|
||||
* onClick={() => setAccountSigners("0x...")}
|
||||
* >
|
||||
* Set Smart Wallet Signers
|
||||
* Set Account Signers
|
||||
* </button>
|
||||
* );
|
||||
* };
|
||||
* ```
|
||||
*
|
||||
* @param contract - an instance of a smart wallet contract
|
||||
* @returns a mutation object that can be used to set the smart wallet signers
|
||||
* @twfeature SmartWallet
|
||||
* @see {@link https://portal.thirdweb.com/react/react.usesetsmartwalletsigners?utm_source=sdk | Documentation}
|
||||
* @param contract - an instance of a account contract
|
||||
* @returns a mutation object that can be used to set the account signers
|
||||
* @twfeature Account
|
||||
* @see {@link https://portal.thirdweb.com/react/react.usesetaccountsigners?utm_source=sdk | Documentation}
|
||||
* @beta
|
||||
*/
|
||||
export function useSetSmartWalletSigners(
|
||||
export function useSetAccountSigners(
|
||||
contract: RequiredParam<SmartContract>,
|
||||
): UseMutationResult<
|
||||
{ receipt: providers.TransactionReceipt },
|
||||
@@ -111,7 +111,7 @@ export function useSetSmartWalletSigners(
|
||||
async (permissionsSnapshot: SignerWithRestrictionsBatchInput) => {
|
||||
requiredParamInvariant(contract, "contract is undefined");
|
||||
|
||||
return contract.smartWallet.setAccess(permissionsSnapshot);
|
||||
return contract.account.setAccess(permissionsSnapshot);
|
||||
},
|
||||
{
|
||||
onSettled: () =>
|
||||
@@ -1,188 +0,0 @@
|
||||
import {
|
||||
RequiredParam,
|
||||
requiredParamInvariant,
|
||||
} from "../../../core/query-utils/required-param";
|
||||
import { useSDKChainId } from "../../providers/thirdweb-sdk-provider";
|
||||
import { WalletAddress } from "../../types";
|
||||
import {
|
||||
cacheKeys,
|
||||
invalidateContractAndBalances,
|
||||
} from "../../utils/cache-keys";
|
||||
import { useQueryWithNetwork } from "../query-utils/useQueryWithNetwork";
|
||||
import {
|
||||
useMutation,
|
||||
useQueryClient,
|
||||
UseQueryResult,
|
||||
} from "@tanstack/react-query";
|
||||
import type { AccountEvent, SmartContract } from "@thirdweb-dev/sdk";
|
||||
import type { BytesLike } from "ethers";
|
||||
import invariant from "tiny-invariant";
|
||||
|
||||
/** **********************/
|
||||
/** READ HOOKS **/
|
||||
/** **********************/
|
||||
|
||||
/**
|
||||
* Get all wallets
|
||||
*
|
||||
* @example
|
||||
* ```javascript
|
||||
* const { data: smartWallets, isLoading, error } = useSmartWallets(contract);
|
||||
* ```
|
||||
*
|
||||
* @param contract - an instance of a smart wallet factory contract
|
||||
* @returns a response object that includes an array of all smart wallets with their associated admin
|
||||
* @twfeature SmartWalletFactory
|
||||
* @see {@link https://portal.thirdweb.com/react/react.usesmartwallets?utm_source=sdk | Documentation}
|
||||
* @beta
|
||||
*/
|
||||
export function useSmartWallets(
|
||||
contract: RequiredParam<SmartContract>,
|
||||
): UseQueryResult<AccountEvent[]> {
|
||||
const contractAddress = contract?.getAddress();
|
||||
return useQueryWithNetwork(
|
||||
cacheKeys.contract.smartWalletFactory.getAll(contractAddress),
|
||||
() => {
|
||||
requiredParamInvariant(contract, "No Contract instance provided");
|
||||
invariant(
|
||||
contract.smartWalletFactory.getAllAccounts,
|
||||
"Contract instance does not support contract.smartWalletFactory.getAllAccounts",
|
||||
);
|
||||
return contract.smartWalletFactory.getAllAccounts();
|
||||
},
|
||||
{ enabled: !!contract },
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all wallets associated with the provided address
|
||||
*
|
||||
* @example
|
||||
* ```javascript
|
||||
* const { data: smartWalletsForAddress, isLoading, error } = useSmartWalletsForAddress(contract, "{{wallet_address}}");
|
||||
* ```
|
||||
*
|
||||
* @param contract - an instance of a smart wallet factory contract
|
||||
* @returns a response object that includes an array of all smart wallets associated with the adress
|
||||
* @twfeature SmartWalletFactory
|
||||
* @see {@link https://portal.thirdweb.com/react/react.usesmartwalletsforaddress?utm_source=sdk | Documentation}
|
||||
* @beta
|
||||
*/
|
||||
export function useSmartWalletsForAddress(
|
||||
contract: RequiredParam<SmartContract>,
|
||||
address: RequiredParam<WalletAddress>,
|
||||
): UseQueryResult<string[]> {
|
||||
const contractAddress = contract?.getAddress();
|
||||
return useQueryWithNetwork(
|
||||
cacheKeys.contract.smartWalletFactory.getAllForAddress(
|
||||
contractAddress,
|
||||
address,
|
||||
),
|
||||
() => {
|
||||
requiredParamInvariant(contract, "No Contract instance provided");
|
||||
invariant(
|
||||
contract.smartWalletFactory.getAssociatedWallets,
|
||||
"Contract instance does not support contract.smartWalletFactory.getAssociatedWallets",
|
||||
);
|
||||
return contract.smartWalletFactory.getAssociatedWallets(address || "");
|
||||
},
|
||||
{ enabled: !!contract },
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a smart wallet has been deployed for the given admin
|
||||
*
|
||||
* @example
|
||||
* ```javascript
|
||||
* const { data: isSmartWalletDeployed, isLoading, error } = useIsSmartWalletDeployed(contract);
|
||||
* ```
|
||||
*
|
||||
* @param contract - an instance of a smart wallet factory contract
|
||||
* @returns a boolean indicating if a smart wallet has been deployed for the given admin
|
||||
* @twfeature SmartWalletFactory
|
||||
* @see {@link https://portal.thirdweb.com/react/react.useissmartwalletdeployed?utm_source=sdk | Documentation}
|
||||
* @beta
|
||||
*/
|
||||
export function useIsSmartWalletDeployed(
|
||||
contract: RequiredParam<SmartContract>,
|
||||
admin: RequiredParam<WalletAddress>,
|
||||
extraData?: BytesLike,
|
||||
): UseQueryResult<boolean> {
|
||||
const contractAddress = contract?.getAddress();
|
||||
return useQueryWithNetwork(
|
||||
cacheKeys.contract.smartWalletFactory.isSmartWalletDeployed(
|
||||
contractAddress,
|
||||
admin,
|
||||
),
|
||||
() => {
|
||||
requiredParamInvariant(contract, "No Contract instance provided");
|
||||
invariant(
|
||||
contract.smartWalletFactory.isWalletDeployed,
|
||||
"Contract instance does not support contract.smartWalletFactory.getAllWallets",
|
||||
);
|
||||
invariant(admin, "No wallet address provided");
|
||||
return contract.smartWalletFactory.isWalletDeployed(admin, extraData);
|
||||
},
|
||||
{ enabled: !!contract },
|
||||
);
|
||||
}
|
||||
|
||||
/** **********************/
|
||||
/** WRITE HOOKS **/
|
||||
/** **********************/
|
||||
/**
|
||||
* Create a smart wallet
|
||||
*
|
||||
* @example
|
||||
* ```jsx
|
||||
* const Component = () => {
|
||||
* const { contract } = useContract("{{contract_address}}");
|
||||
* const {
|
||||
* mutate: createSmartWallet,
|
||||
* isLoading,
|
||||
* error,
|
||||
* } = useCreateSmartWallet(contract);
|
||||
*
|
||||
* if (error) {
|
||||
* console.error("failed to create smart wallet", error);
|
||||
* }
|
||||
*
|
||||
* return (
|
||||
* <button
|
||||
* disabled={isLoading}
|
||||
* onClick={() => createSmartWallet("0x...")}
|
||||
* >
|
||||
* Create Smart Wallet
|
||||
* </button>
|
||||
* );
|
||||
* };
|
||||
* ```
|
||||
*
|
||||
* @param contract - an instance of a smart wallet factory contract
|
||||
* @returns a mutation object that can be used to create a smart wallet
|
||||
* @twfeature SmartWalletFactory
|
||||
* @see {@link https://portal.thirdweb.com/react/react.usecreatesmartwallet?utm_source=sdk | Documentation}
|
||||
* @beta
|
||||
*/
|
||||
export function useCreateSmartWallet(contract: RequiredParam<SmartContract>) {
|
||||
const activeChainId = useSDKChainId();
|
||||
const contractAddress = contract?.getAddress();
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
return useMutation(
|
||||
async (admin: string, extraData?: BytesLike) => {
|
||||
requiredParamInvariant(contract, "contract is undefined");
|
||||
|
||||
return contract.smartWalletFactory.createWallet(admin, extraData);
|
||||
},
|
||||
{
|
||||
onSettled: () =>
|
||||
invalidateContractAndBalances(
|
||||
queryClient,
|
||||
contractAddress,
|
||||
activeChainId,
|
||||
),
|
||||
},
|
||||
);
|
||||
}
|
||||
@@ -194,19 +194,16 @@ export {
|
||||
useBurnToken,
|
||||
} from "./hooks/async/token";
|
||||
|
||||
// smart wallet factory
|
||||
// account factory
|
||||
export {
|
||||
useIsSmartWalletDeployed,
|
||||
useSmartWallets,
|
||||
useCreateSmartWallet,
|
||||
useSmartWalletsForAddress,
|
||||
} from "./hooks/async/smart-wallet-factory";
|
||||
useIsAccountDeployed,
|
||||
useAccounts,
|
||||
useCreateAccount,
|
||||
useAccountsForAddress,
|
||||
} from "./hooks/async/account-factory";
|
||||
|
||||
// smart wallet
|
||||
export {
|
||||
useSmartWalletSigners,
|
||||
useSetSmartWalletSigners,
|
||||
} from "./hooks/async/smart-wallet";
|
||||
// account
|
||||
export { useAccountSigners, useSetAccountSigners } from "./hooks/async/account";
|
||||
|
||||
// thirdweb hooks (work as long as at least `<ThirdwebSdkProvider>` is used)
|
||||
|
||||
|
||||
@@ -118,18 +118,23 @@ export const cacheKeys = {
|
||||
overrides,
|
||||
]),
|
||||
|
||||
smartWalletFactory: {
|
||||
accountFactory: {
|
||||
getAll: (contractAddress: RequiredParam<ContractAddress>) =>
|
||||
createContractCacheKey(contractAddress, ["smartWalletFactory"]),
|
||||
isSmartWalletDeployed: (contractAdress: RequiredParam<ContractAddress>, admin: RequiredParam<string>) =>
|
||||
createContractCacheKey(contractAdress, ["isSmartWalletDeployed", admin]),
|
||||
getAllForAddress: (contractAdress: RequiredParam<ContractAddress>, address: RequiredParam<string>) =>
|
||||
createContractCacheKey(contractAddress, ["accountFactory"]),
|
||||
isAccountDeployed: (
|
||||
contractAdress: RequiredParam<ContractAddress>,
|
||||
admin: RequiredParam<string>,
|
||||
) => createContractCacheKey(contractAdress, ["isAccountDeployed", admin]),
|
||||
getAllForAddress: (
|
||||
contractAdress: RequiredParam<ContractAddress>,
|
||||
address: RequiredParam<string>,
|
||||
) =>
|
||||
createContractCacheKey(contractAdress, ["getAllForAddress", address]),
|
||||
},
|
||||
|
||||
smartWallet: {
|
||||
account: {
|
||||
signers: (contractAddress: RequiredParam<ContractAddress>) =>
|
||||
createContractCacheKey(contractAddress, ["smartWallet", "signers"]),
|
||||
createContractCacheKey(contractAddress, ["account", "signers"]),
|
||||
},
|
||||
|
||||
app: {
|
||||
@@ -198,12 +203,8 @@ export const cacheKeys = {
|
||||
},
|
||||
},
|
||||
sharedMetadata: {
|
||||
get: (
|
||||
contractAddress: RequiredParam<ContractAddress>,
|
||||
) =>
|
||||
createContractCacheKey(
|
||||
contractAddress
|
||||
),
|
||||
get: (contractAddress: RequiredParam<ContractAddress>) =>
|
||||
createContractCacheKey(contractAddress),
|
||||
},
|
||||
drop: {
|
||||
getAllUnclaimed: (
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
# @thirdweb-dev/react-native-compat
|
||||
|
||||
## 0.2.26
|
||||
|
||||
## 0.2.25
|
||||
|
||||
## 0.2.24
|
||||
|
||||
## 0.2.23
|
||||
|
||||
## 0.2.22
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@thirdweb-dev/react-native-compat",
|
||||
"description": "Shims for Thirdweb in React Native Projects",
|
||||
"version": "0.2.23",
|
||||
"version": "0.2.26",
|
||||
"author": "thirdweb eng <[email protected]>",
|
||||
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/react-native-compat",
|
||||
"license": "Apache-2.0",
|
||||
|
||||
@@ -1,5 +1,35 @@
|
||||
# @thirdweb-dev/react-native
|
||||
|
||||
## 0.2.26
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#1270](https://github.com/thirdweb-dev/js/pull/1270) [`0d5503aa`](https://github.com/thirdweb-dev/js/commit/0d5503aae90d9cd7a7adcabad19f7f45d9a37063) Thanks [@iketw](https://github.com/iketw)! - Only handle Coinbase callback URL if Coinbase is added as a supportedWallet
|
||||
|
||||
- [#1277](https://github.com/thirdweb-dev/js/pull/1277) [`2b113539`](https://github.com/thirdweb-dev/js/commit/2b113539098384f910b3c4d54e1fde9d35a6f053) Thanks [@joaquim-verges](https://github.com/joaquim-verges)! - remove ethers/lib/utils dependency
|
||||
|
||||
- Updated dependencies [[`2b113539`](https://github.com/thirdweb-dev/js/commit/2b113539098384f910b3c4d54e1fde9d35a6f053), [`c9535715`](https://github.com/thirdweb-dev/js/commit/c95357158819abd42d4b0900ecc2fa40fcb957f8), [`be606dd3`](https://github.com/thirdweb-dev/js/commit/be606dd3c93c1514834c1d970e864d7f949a07ab), [`edcd22d6`](https://github.com/thirdweb-dev/js/commit/edcd22d61236edb2832f9b2f9796e891d58cb145), [`5882091e`](https://github.com/thirdweb-dev/js/commit/5882091eab65978009a5a5305701f121851b10ad), [`998e5217`](https://github.com/thirdweb-dev/js/commit/998e521733efd6a67e42f9bf0beab5fbdccf08ae)]:
|
||||
- @thirdweb-dev/wallets@1.0.3
|
||||
- @thirdweb-dev/sdk@3.10.27
|
||||
- @thirdweb-dev/react-core@3.14.7
|
||||
- @thirdweb-dev/chains@0.1.26
|
||||
|
||||
## 0.2.25
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`ed711c8c`](https://github.com/thirdweb-dev/js/commit/ed711c8cb2ed6a0deb1b2a5eeec06df1d4edc5e8), [`05a7495a`](https://github.com/thirdweb-dev/js/commit/05a7495a132aabab5f48abbdb80a468ff6f65df8), [`e78da6b3`](https://github.com/thirdweb-dev/js/commit/e78da6b36cfa6d954234820563201bf760186ed1)]:
|
||||
- @thirdweb-dev/wallets@1.0.2
|
||||
- @thirdweb-dev/react-core@3.14.6
|
||||
|
||||
## 0.2.24
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`efb3546e`](https://github.com/thirdweb-dev/js/commit/efb3546ec8268156be00301af28b9d83ecd5ab08)]:
|
||||
- @thirdweb-dev/wallets@1.0.1
|
||||
- @thirdweb-dev/react-core@3.14.5
|
||||
|
||||
## 0.2.23
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@thirdweb-dev/react-native",
|
||||
"version": "0.2.23",
|
||||
"version": "0.2.26",
|
||||
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/react-native",
|
||||
"author": "thirdweb eng <[email protected]>",
|
||||
"license": "Apache-2.0",
|
||||
|
||||
@@ -65,7 +65,9 @@ export const ThirdwebProvider = <
|
||||
theme,
|
||||
...restProps
|
||||
}: PropsWithChildren<ThirdwebProviderProps<TChains>>) => {
|
||||
useCoinbaseWalletListener();
|
||||
useCoinbaseWalletListener(
|
||||
!!supportedWallets.find((w) => w.id === walletIds.coinbase),
|
||||
);
|
||||
|
||||
const hasMagicConfig = useMemo(
|
||||
() => !!supportedWallets.find((wc) => wc.id === walletIds.magicLink),
|
||||
|
||||
@@ -17,8 +17,7 @@ import {
|
||||
WagmiConnector,
|
||||
} from "@thirdweb-dev/wallets";
|
||||
import type { Address } from "abitype";
|
||||
import { providers } from "ethers";
|
||||
import { getAddress, hexValue } from "ethers/lib/utils.js";
|
||||
import { providers, utils } from "ethers";
|
||||
|
||||
export type CoinbaseWalletConnectorOptions = WalletMobileSDKProviderOptions &
|
||||
ConfigurationParams & {
|
||||
@@ -130,7 +129,7 @@ export class CoinbaseWalletConnector extends WagmiConnector<
|
||||
throw new Error("No accounts found");
|
||||
}
|
||||
// return checksum address
|
||||
return getAddress(accounts[0] as string);
|
||||
return utils.getAddress(accounts[0] as string);
|
||||
}
|
||||
|
||||
async getChainId() {
|
||||
@@ -193,7 +192,7 @@ export class CoinbaseWalletConnector extends WagmiConnector<
|
||||
|
||||
async switchChain(chainId: number): Promise<Chain> {
|
||||
const provider = await this.getProvider();
|
||||
const id = hexValue(chainId);
|
||||
const id = utils.hexValue(chainId);
|
||||
|
||||
try {
|
||||
await provider.request({
|
||||
@@ -279,7 +278,7 @@ export class CoinbaseWalletConnector extends WagmiConnector<
|
||||
if (accounts.length === 0) {
|
||||
this.emit("disconnect");
|
||||
} else {
|
||||
this.emit("change", { account: getAddress(accounts[0] as string) });
|
||||
this.emit("change", { account: utils.getAddress(accounts[0] as string) });
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ import { useCoinbaseWalletListener } from "./useCoinbaseWalletListener";
|
||||
*/
|
||||
export function useCoinbaseWallet(callbackURL: string) {
|
||||
const connect = useConnect();
|
||||
useCoinbaseWalletListener();
|
||||
useCoinbaseWalletListener(true);
|
||||
|
||||
return useCallback(
|
||||
async (connectOptions?: { chainId?: number; callbackURL: string }) => {
|
||||
|
||||
@@ -7,12 +7,16 @@ import { Linking } from "react-native";
|
||||
*
|
||||
* This hook sets up the UniversalLinks listener.
|
||||
*/
|
||||
export function useCoinbaseWalletListener() {
|
||||
export function useCoinbaseWalletListener(enable: boolean) {
|
||||
useEffect(() => {
|
||||
if (!enable) {
|
||||
return;
|
||||
}
|
||||
|
||||
const sub = Linking.addEventListener("url", ({ url }) => {
|
||||
// @ts-ignore - Passing a URL object to handleResponse crashes the function
|
||||
handleResponse(url);
|
||||
});
|
||||
return () => sub?.remove();
|
||||
}, []);
|
||||
}, [enable]);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,37 @@
|
||||
# @thirdweb-dev/react
|
||||
|
||||
## 3.14.7
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#1210](https://github.com/thirdweb-dev/js/pull/1210) [`d794b8f9`](https://github.com/thirdweb-dev/js/commit/d794b8f9f41dbd7e461ef07d0808c5b6d2f85515) Thanks [@konojunya](https://github.com/konojunya)! - Add zerion to useInstalledWallets
|
||||
|
||||
- [#1269](https://github.com/thirdweb-dev/js/pull/1269) [`998e5217`](https://github.com/thirdweb-dev/js/commit/998e521733efd6a67e42f9bf0beab5fbdccf08ae) Thanks [@MananTank](https://github.com/MananTank)! - - Expose `advancedOptions` and `styles` for paper wallet
|
||||
- Allow using "+" in paper email
|
||||
- Allow using "+" in magic email
|
||||
- Update Paper SDK version
|
||||
- Updated dependencies [[`2b113539`](https://github.com/thirdweb-dev/js/commit/2b113539098384f910b3c4d54e1fde9d35a6f053), [`c9535715`](https://github.com/thirdweb-dev/js/commit/c95357158819abd42d4b0900ecc2fa40fcb957f8), [`be606dd3`](https://github.com/thirdweb-dev/js/commit/be606dd3c93c1514834c1d970e864d7f949a07ab), [`edcd22d6`](https://github.com/thirdweb-dev/js/commit/edcd22d61236edb2832f9b2f9796e891d58cb145), [`5882091e`](https://github.com/thirdweb-dev/js/commit/5882091eab65978009a5a5305701f121851b10ad), [`998e5217`](https://github.com/thirdweb-dev/js/commit/998e521733efd6a67e42f9bf0beab5fbdccf08ae)]:
|
||||
- @thirdweb-dev/wallets@1.0.3
|
||||
- @thirdweb-dev/sdk@3.10.27
|
||||
- @thirdweb-dev/react-core@3.14.7
|
||||
- @thirdweb-dev/chains@0.1.26
|
||||
|
||||
## 3.14.6
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`ed711c8c`](https://github.com/thirdweb-dev/js/commit/ed711c8cb2ed6a0deb1b2a5eeec06df1d4edc5e8), [`05a7495a`](https://github.com/thirdweb-dev/js/commit/05a7495a132aabab5f48abbdb80a468ff6f65df8), [`e78da6b3`](https://github.com/thirdweb-dev/js/commit/e78da6b36cfa6d954234820563201bf760186ed1)]:
|
||||
- @thirdweb-dev/wallets@1.0.2
|
||||
- @thirdweb-dev/react-core@3.14.6
|
||||
|
||||
## 3.14.5
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`efb3546e`](https://github.com/thirdweb-dev/js/commit/efb3546ec8268156be00301af28b9d83ecd5ab08)]:
|
||||
- @thirdweb-dev/wallets@1.0.1
|
||||
- @thirdweb-dev/react-core@3.14.5
|
||||
|
||||
## 3.14.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@thirdweb-dev/react",
|
||||
"version": "3.14.4",
|
||||
"version": "3.14.7",
|
||||
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/react",
|
||||
"author": "thirdweb eng <[email protected]>",
|
||||
"license": "Apache-2.0",
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
import { useConnect, useWallet } from "@thirdweb-dev/react-core";
|
||||
import { PaperWallet, walletIds } from "@thirdweb-dev/wallets";
|
||||
import {
|
||||
PaperWallet,
|
||||
walletIds,
|
||||
PaperWalletAdditionalOptions,
|
||||
} from "@thirdweb-dev/wallets";
|
||||
import { useCallback, useEffect } from "react";
|
||||
import {
|
||||
useQuery,
|
||||
@@ -7,10 +11,12 @@ import {
|
||||
useQueryClient,
|
||||
} from "@tanstack/react-query";
|
||||
|
||||
type PaperConfig = Omit<PaperWalletAdditionalOptions, "chain" | "chains">;
|
||||
|
||||
export function usePaperWallet() {
|
||||
const connect = useConnect();
|
||||
return useCallback(
|
||||
async (options: { chainId?: number; clientId: string; email?: string }) => {
|
||||
async (options: { chainId?: number; email?: string } & PaperConfig) => {
|
||||
const { paperWallet } = await import(
|
||||
"../../../wallet/wallets/paperWallet"
|
||||
);
|
||||
|
||||
@@ -3,22 +3,22 @@ import { assertWindowEthereum } from "@thirdweb-dev/wallets";
|
||||
export function useInstalledWallets() {
|
||||
let isMetamaskInstalled = false;
|
||||
let isCoinbaseWalletInstalled = false;
|
||||
let isTrustWalletInstalled: boolean | undefined = false;
|
||||
let isZerionWalletInstalled = false;
|
||||
let isTrustWalletInstalled = false;
|
||||
|
||||
if (assertWindowEthereum(globalThis.window)) {
|
||||
isMetamaskInstalled = globalThis.window.ethereum?.isMetaMask;
|
||||
isMetamaskInstalled = !!globalThis.window.ethereum?.isMetaMask;
|
||||
isCoinbaseWalletInstalled =
|
||||
globalThis.window.ethereum?.isCoinbaseWallet ||
|
||||
globalThis.window.ethereum?.providers?.some((p) => p.isCoinbaseWallet) ||
|
||||
false;
|
||||
isTrustWalletInstalled = globalThis.window.ethereum?.isTrust;
|
||||
!!globalThis.window.ethereum?.isCoinbaseWallet ||
|
||||
!!globalThis.window.ethereum?.providers?.some((p) => p.isCoinbaseWallet);
|
||||
isZerionWalletInstalled = !!globalThis.window.ethereum?.isZerion;
|
||||
isTrustWalletInstalled = !!globalThis.window.ethereum?.isTrust;
|
||||
}
|
||||
|
||||
const installedWallets = {
|
||||
metamask: !!isMetamaskInstalled,
|
||||
coinbaseWallet: !!isCoinbaseWalletInstalled,
|
||||
trustWallet: !!isTrustWalletInstalled,
|
||||
return {
|
||||
metamask: isMetamaskInstalled,
|
||||
coinbaseWallet: isCoinbaseWalletInstalled,
|
||||
trustWallet: isTrustWalletInstalled,
|
||||
zerionWallet: isZerionWalletInstalled,
|
||||
};
|
||||
|
||||
return installedWallets;
|
||||
}
|
||||
|
||||
@@ -79,7 +79,7 @@ const MagicSelectionUI: React.FC<
|
||||
|
||||
if (isEmail && isEmailEnabled) {
|
||||
const emailRegex = /^([a-z0-9_\.-]+)@([\da-z\.-]+)\.([a-z\.]{2,})$/g;
|
||||
const isValidEmail = emailRegex.test(input);
|
||||
const isValidEmail = emailRegex.test(input.replace(/\+/g, ""));
|
||||
if (!isValidEmail) {
|
||||
return "Invalid email address";
|
||||
}
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
import { PaperWallet } from "@thirdweb-dev/wallets";
|
||||
import {
|
||||
PaperWallet,
|
||||
PaperWalletAdditionalOptions,
|
||||
} from "@thirdweb-dev/wallets";
|
||||
import {
|
||||
WalletConfig,
|
||||
WalletOptions,
|
||||
@@ -11,7 +14,7 @@ import { Spinner } from "../../components/Spinner";
|
||||
import { Flex } from "../../components/basic";
|
||||
import { InputSelectionUI } from "./InputSelectionUI";
|
||||
|
||||
type PaperConfig = { clientId: string };
|
||||
type PaperConfig = Omit<PaperWalletAdditionalOptions, "chain" | "chains">;
|
||||
|
||||
export const paperWallet = (config: PaperConfig): WalletConfig<PaperWallet> => {
|
||||
return {
|
||||
@@ -32,7 +35,8 @@ const PaperSelectionUI: React.FC<SelectUIProps<PaperWallet>> = (props) => {
|
||||
placeholder="Enter your email address"
|
||||
name="email"
|
||||
type="email"
|
||||
errorMessage={(input) => {
|
||||
errorMessage={(_input) => {
|
||||
const input = _input.replace(/\+/g, "");
|
||||
const emailRegex = /^([a-z0-9_\.-]+)@([\da-z\.-]+)\.([a-z\.]{2,})$/g;
|
||||
const isValidEmail = emailRegex.test(input);
|
||||
if (!isValidEmail) {
|
||||
|
||||
@@ -1,5 +1,16 @@
|
||||
# @thirdweb-dev/sdk
|
||||
|
||||
## 3.10.27
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#1277](https://github.com/thirdweb-dev/js/pull/1277) [`2b113539`](https://github.com/thirdweb-dev/js/commit/2b113539098384f910b3c4d54e1fde9d35a6f053) Thanks [@joaquim-verges](https://github.com/joaquim-verges)! - remove ethers/lib/utils dependency
|
||||
|
||||
- [#1271](https://github.com/thirdweb-dev/js/pull/1271) [`c9535715`](https://github.com/thirdweb-dev/js/commit/c95357158819abd42d4b0900ecc2fa40fcb957f8) Thanks [@nkrishang](https://github.com/nkrishang)! - Rename smart wallets to account
|
||||
|
||||
- Updated dependencies [[`5882091e`](https://github.com/thirdweb-dev/js/commit/5882091eab65978009a5a5305701f121851b10ad)]:
|
||||
- @thirdweb-dev/chains@0.1.26
|
||||
|
||||
## 3.10.26
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@thirdweb-dev/sdk",
|
||||
"version": "3.10.26",
|
||||
"version": "3.10.27",
|
||||
"description": "The main thirdweb SDK.",
|
||||
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/sdk",
|
||||
"license": "Apache-2.0",
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { BigNumber, providers, constants } from "ethers";
|
||||
import { isAddress } from "ethers/lib/utils";
|
||||
import { BigNumber, providers, constants, utils } from "ethers";
|
||||
import { extractIPFSHashFromBytecode } from "./extractIPFSHashFromBytecode";
|
||||
import { extractMinimalProxyImplementationAddress } from "./extractMinimalProxyImplementationAddress";
|
||||
|
||||
@@ -49,7 +48,7 @@ export async function resolveContractUriFromAddress(
|
||||
);
|
||||
const implementationAddress = `0x${proxyStorage.slice(-40)}`;
|
||||
if (
|
||||
isAddress(implementationAddress) &&
|
||||
utils.isAddress(implementationAddress) &&
|
||||
implementationAddress !== constants.AddressZero
|
||||
) {
|
||||
return await resolveContractUriFromAddress(
|
||||
|
||||
@@ -62,8 +62,8 @@ import {
|
||||
FEATURE_ENGLISH_AUCTIONS,
|
||||
FEATURE_OFFERS,
|
||||
FEATURE_EXTENSION_ROUTER,
|
||||
FEATURE_SMART_WALLET,
|
||||
FEATURE_SMART_WALLET_FACTORY,
|
||||
FEATURE_ACCOUNT,
|
||||
FEATURE_ACCOUNT_FACTORY,
|
||||
} from "./thirdweb-features";
|
||||
|
||||
/**
|
||||
@@ -127,8 +127,8 @@ export type Feature =
|
||||
| typeof FEATURE_DIRECT_LISTINGS
|
||||
| typeof FEATURE_ENGLISH_AUCTIONS
|
||||
| typeof FEATURE_OFFERS
|
||||
| typeof FEATURE_SMART_WALLET
|
||||
| typeof FEATURE_SMART_WALLET_FACTORY;
|
||||
| typeof FEATURE_ACCOUNT
|
||||
| typeof FEATURE_ACCOUNT_FACTORY;
|
||||
|
||||
export type Extension = Feature;
|
||||
|
||||
@@ -170,6 +170,6 @@ export const SUPPORTED_FEATURES: Record<string, Feature> = /* @__PURE__ */ {
|
||||
[FEATURE_DIRECT_LISTINGS.name]: FEATURE_DIRECT_LISTINGS,
|
||||
[FEATURE_ENGLISH_AUCTIONS.name]: FEATURE_ENGLISH_AUCTIONS,
|
||||
[FEATURE_OFFERS.name]: FEATURE_OFFERS,
|
||||
[FEATURE_SMART_WALLET_FACTORY.name]: FEATURE_SMART_WALLET_FACTORY,
|
||||
[FEATURE_SMART_WALLET.name]: FEATURE_SMART_WALLET,
|
||||
[FEATURE_ACCOUNT_FACTORY.name]: FEATURE_ACCOUNT_FACTORY,
|
||||
[FEATURE_ACCOUNT.name]: FEATURE_ACCOUNT,
|
||||
};
|
||||
|
||||
@@ -279,24 +279,24 @@ export const FEATURE_OFFERS = {
|
||||
features: {},
|
||||
} as const;
|
||||
|
||||
export const FEATURE_SMART_WALLET_FACTORY = {
|
||||
name: "SmartWalletFactory",
|
||||
namespace: "smartwallet.factory",
|
||||
export const FEATURE_ACCOUNT_FACTORY = {
|
||||
name: "AccountFactory",
|
||||
namespace: "accountFactory",
|
||||
docLinks: {
|
||||
// TODO
|
||||
sdk: "sdk.smartWalletFactory",
|
||||
contracts: "smartWalletFactory",
|
||||
sdk: "sdk.accountFactory",
|
||||
contracts: "",
|
||||
},
|
||||
abis: [IAccountFactory],
|
||||
features: {},
|
||||
} as const;
|
||||
|
||||
export const FEATURE_SMART_WALLET = {
|
||||
name: "SmartWallet",
|
||||
namespace: "smartwallet",
|
||||
export const FEATURE_ACCOUNT = {
|
||||
name: "Account",
|
||||
namespace: "account",
|
||||
docLinks: {
|
||||
// TODO
|
||||
sdk: "",
|
||||
sdk: "sdk.account",
|
||||
contracts: "",
|
||||
},
|
||||
abis: [IAccountCore],
|
||||
|
||||
@@ -14,8 +14,8 @@ import {
|
||||
FEATURE_PLATFORM_FEE,
|
||||
FEATURE_PRIMARY_SALE,
|
||||
FEATURE_ROYALTY,
|
||||
FEATURE_SMART_WALLET_FACTORY,
|
||||
FEATURE_SMART_WALLET,
|
||||
FEATURE_ACCOUNT_FACTORY,
|
||||
FEATURE_ACCOUNT,
|
||||
} from "../constants/thirdweb-features";
|
||||
import { Transaction } from "../core/classes/transactions";
|
||||
import { ContractAppURI } from "../core/classes/contract-appuri";
|
||||
@@ -54,7 +54,7 @@ import type {
|
||||
EnglishAuctionsLogic,
|
||||
OffersLogic,
|
||||
IAccountFactory,
|
||||
IAccountCore
|
||||
IAccountCore,
|
||||
} from "@thirdweb-dev/contracts-js";
|
||||
import { ThirdwebStorage } from "@thirdweb-dev/storage";
|
||||
import { BaseContract, CallOverrides } from "ethers";
|
||||
@@ -66,8 +66,8 @@ import { ContractOwner } from "../core/classes/contract-owner";
|
||||
import { MarketplaceV3DirectListings } from "../core/classes/marketplacev3-direct-listings";
|
||||
import { MarketplaceV3EnglishAuctions } from "../core/classes/marketplacev3-english-auction";
|
||||
import { MarketplaceV3Offers } from "../core/classes/marketplacev3-offers";
|
||||
import { SmartWalletFactory } from "../core/classes/smart-wallet-factory";
|
||||
import { SmartWallet } from "../core/classes/smart-wallet";
|
||||
import { AccountFactory } from "../core/classes/account-factory";
|
||||
import { Account } from "../core/classes/account";
|
||||
|
||||
/**
|
||||
* Custom contract dynamic class with feature detection
|
||||
@@ -299,46 +299,40 @@ export class SmartContract<
|
||||
}
|
||||
|
||||
/**
|
||||
* Smart Wallet Factory
|
||||
* Account Factory
|
||||
*
|
||||
* @remarks Create smart wallets and fetch data about them.
|
||||
* @remarks Create accounts and fetch data about them.
|
||||
* @example
|
||||
* ```javascript
|
||||
*
|
||||
* // Predict the address of the smart wallet that will be created for an admin.
|
||||
* const deterministicAddress = await contract.smartWalletFactory.predictWalletAddress(admin, extraData);
|
||||
* // Predict the address of the account that will be created for an admin.
|
||||
* const deterministicAddress = await contract.accountFactory.predictAccountAddress(admin, extraData);
|
||||
*
|
||||
* // Create smart wallets
|
||||
* const tx = await contract.smartWalletFactory.createWallet(admin, extraData);
|
||||
* // Create accounts
|
||||
* const tx = await contract.accountFactory.createAccount(admin, extraData);
|
||||
* // the same as `deterministicAddress`
|
||||
* const smartWalletAddress = tx.address;
|
||||
* const accountAddress = tx.address;
|
||||
*
|
||||
* // Get all smart wallets created by the factory
|
||||
* const allWallets = await contract.smartWalletFactory.getAllWallets();
|
||||
* // Get all accounts created by the factory
|
||||
* const allAccounts = await contract.accountFactory.getAllAccounts();
|
||||
*
|
||||
* // Get all smart wallets on which a signer has been given authority.
|
||||
* const associatedWallets = await contract.smartWalletFactory.getAssociatedWallets(signer);
|
||||
* // Get all accounts on which a signer has been given authority.
|
||||
* const associatedAccounts = await contract.accountFactory.getAssociatedAccounts(signer);
|
||||
*
|
||||
* // Get all signers who have been given authority on a smart wallet.
|
||||
* const associatedSigners = await contract.smartWalletFactory.getAssociatedSigners(smartWalletAddress);
|
||||
* // Get all signers who have been given authority on a account.
|
||||
* const associatedSigners = await contract.accountFactory.getAssociatedSigners(accountAddress);
|
||||
*
|
||||
* // Check whether a smart wallet has already been created for a given admin.
|
||||
* const isWalletDeployed = await contract.smartWalletFactory.isWalletDeployed(admin, extraData);
|
||||
* // Check whether a account has already been created for a given admin.
|
||||
* const isAccountDeployed = await contract.accountFactory.isAccountDeployed(admin, extraData);
|
||||
* ```
|
||||
*/
|
||||
get smartWalletFactory(): SmartWalletFactory<IAccountFactory> {
|
||||
return assertEnabled(
|
||||
this.detectSmartWalletFactory(),
|
||||
FEATURE_SMART_WALLET_FACTORY,
|
||||
);
|
||||
get accountFactory(): AccountFactory<IAccountFactory> {
|
||||
return assertEnabled(this.detectAccountFactory(), FEATURE_ACCOUNT_FACTORY);
|
||||
}
|
||||
|
||||
// TODO documentation
|
||||
get smartWallet(): SmartWallet<IAccountCore> {
|
||||
return assertEnabled(
|
||||
this.detectSmartWallet(),
|
||||
FEATURE_SMART_WALLET,
|
||||
)
|
||||
get account(): Account<IAccountCore> {
|
||||
return assertEnabled(this.detectAccount(), FEATURE_ACCOUNT);
|
||||
}
|
||||
|
||||
private _chainId: number;
|
||||
@@ -568,25 +562,28 @@ export class SmartContract<
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// ========== Smart account features ==========
|
||||
// ========== Account features ==========
|
||||
|
||||
private detectSmartWalletFactory() {
|
||||
private detectAccountFactory() {
|
||||
if (
|
||||
detectContractFeature<IAccountFactory>(
|
||||
this.contractWrapper,
|
||||
FEATURE_SMART_WALLET_FACTORY.name,
|
||||
FEATURE_ACCOUNT_FACTORY.name,
|
||||
)
|
||||
) {
|
||||
return new SmartWalletFactory(this.contractWrapper);
|
||||
return new AccountFactory(this.contractWrapper);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
private detectSmartWallet() {
|
||||
private detectAccount() {
|
||||
if (
|
||||
detectContractFeature<IAccountCore>(this.contractWrapper, FEATURE_SMART_WALLET.name)
|
||||
detectContractFeature<IAccountCore>(
|
||||
this.contractWrapper,
|
||||
FEATURE_ACCOUNT.name,
|
||||
)
|
||||
) {
|
||||
return new SmartWallet(this.contractWrapper);
|
||||
return new Account(this.contractWrapper);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
+46
-46
@@ -1,6 +1,6 @@
|
||||
import type { IAccountFactory } from "@thirdweb-dev/contracts-js";
|
||||
import { DetectableFeature } from "../interfaces/DetectableFeature";
|
||||
import { FEATURE_SMART_WALLET_FACTORY } from "../../constants/thirdweb-features";
|
||||
import { FEATURE_ACCOUNT_FACTORY } from "../../constants/thirdweb-features";
|
||||
|
||||
import { ContractEvents } from "./contract-events";
|
||||
import { ContractWrapper } from "./contract-wrapper";
|
||||
@@ -9,13 +9,13 @@ import { Transaction } from "./transactions";
|
||||
import { TransactionResultWithAddress } from "../types";
|
||||
import { type BytesLike, utils } from "ethers";
|
||||
import { AccountCreatedEvent } from "@thirdweb-dev/contracts-js/dist/declarations/src/AccountFactory";
|
||||
import type { AccountEvent } from "../../types/smart-wallet";
|
||||
import type { AccountEvent } from "../../types/account";
|
||||
import { isContractDeployed } from "../../common/any-evm-utils/isContractDeployed";
|
||||
|
||||
export class SmartWalletFactory<TContract extends IAccountFactory>
|
||||
export class AccountFactory<TContract extends IAccountFactory>
|
||||
implements DetectableFeature
|
||||
{
|
||||
featureName = FEATURE_SMART_WALLET_FACTORY.name;
|
||||
featureName = FEATURE_ACCOUNT_FACTORY.name;
|
||||
private contractWrapper: ContractWrapper<IAccountFactory>;
|
||||
|
||||
// utilities
|
||||
@@ -36,19 +36,19 @@ export class SmartWalletFactory<TContract extends IAccountFactory>
|
||||
*******************************/
|
||||
|
||||
/**
|
||||
* Get the deterministic address of the smart wallet that will be created
|
||||
* Get the deterministic address of the account that will be created
|
||||
*
|
||||
* @example
|
||||
* ```javascript
|
||||
* const walletAddress = await contract.smartWalletFactory.predictWalletAddress(admin);
|
||||
* const accountAddress = await contract.accountFactory.predictAccountAddress(admin);
|
||||
* ```
|
||||
* @param admin - The admin of the smart wallet.
|
||||
* @param extraData - (Optional) Extra data to be passed to the smart wallet on creation.
|
||||
* @returns the deterministic address of the smart wallet that will be created for the given admin.
|
||||
* @param admin - The admin of the account.
|
||||
* @param extraData - (Optional) Extra data to be passed to the account on creation.
|
||||
* @returns the deterministic address of the account that will be created for the given admin.
|
||||
*
|
||||
* @twfeature SmartWalletFactory
|
||||
* @twfeature AccountFactory
|
||||
*/
|
||||
public async predictWalletAddress(
|
||||
public async predictAccountAddress(
|
||||
admin: string,
|
||||
extraData?: BytesLike,
|
||||
): Promise<string> {
|
||||
@@ -60,48 +60,48 @@ export class SmartWalletFactory<TContract extends IAccountFactory>
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all signers who have authority on the given smart wallet
|
||||
* Get all signers who have authority on the given account
|
||||
*
|
||||
* @example
|
||||
* ```javascript
|
||||
* const allSigners = await contract.smartWalletFactory.getAssociatedSigners(admin);
|
||||
* const allSigners = await contract.accountFactory.getAssociatedSigners(admin);
|
||||
* ```
|
||||
* @param wallet - The smart wallet address.
|
||||
* @returns all signers who have authority on the given smart wallet.
|
||||
* @param account - The account address.
|
||||
* @returns all signers who have authority on the given account.
|
||||
*
|
||||
* @twfeature SmartWalletFactory
|
||||
* @twfeature AccountFactory
|
||||
*/
|
||||
public async getAssociatedSigners(wallet: string): Promise<string[]> {
|
||||
return this.contractWrapper.readContract.getSignersOfAccount(wallet);
|
||||
public async getAssociatedSigners(account: string): Promise<string[]> {
|
||||
return this.contractWrapper.readContract.getSignersOfAccount(account);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all wallets on which the given signer has authority
|
||||
* Get all accounts on which the given signer has authority
|
||||
*
|
||||
* @example
|
||||
* ```javascript
|
||||
* const allWallets = await contract.smartWalletFactory.getAssociatedWallets(admin);
|
||||
* const allAccounts = await contract.accountFactory.getAssociatedAccounts(admin);
|
||||
* ```
|
||||
* @param signer - The smart wallet address.
|
||||
* @returns all wallets on which the given signer has authority.
|
||||
* @param signer - The account address.
|
||||
* @returns all accounts on which the given signer has authority.
|
||||
*
|
||||
* @twfeature SmartWalletFactory
|
||||
* @twfeature AccountFactory
|
||||
*/
|
||||
public async getAssociatedWallets(signer: string): Promise<string[]> {
|
||||
public async getAssociatedAccounts(signer: string): Promise<string[]> {
|
||||
return this.contractWrapper.readContract.getAccountsOfSigner(signer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all wallets
|
||||
* Get all accounts
|
||||
*
|
||||
* @example
|
||||
* ```javascript
|
||||
* const allWallets = await contract.smartWalletFactory.getAllWallets();
|
||||
* const allAccounts = await contract.accountFactory.getAllAccounts();
|
||||
* ```
|
||||
*
|
||||
* @returns all wallets created via the smart wallet factory.
|
||||
* @returns all accounts created via the account factory.
|
||||
*
|
||||
* @twfeature SmartWalletFactory
|
||||
* @twfeature AccountFactory
|
||||
*/
|
||||
public async getAllAccounts(): Promise<AccountEvent[]> {
|
||||
const allAccounts =
|
||||
@@ -122,17 +122,17 @@ export class SmartWalletFactory<TContract extends IAccountFactory>
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a smart wallet has been deployed for the given admin
|
||||
* Check if a account has been deployed for the given admin
|
||||
*
|
||||
* @param admin - The admin of the smart wallet.
|
||||
* @param extraData - (Optional) Extra data to be passed to the smart wallet on creation.
|
||||
* @returns whether the smart wallet has been deployed for the given admin.
|
||||
* @param admin - The admin of the account.
|
||||
* @param extraData - (Optional) Extra data to be passed to the account on creation.
|
||||
* @returns whether the account has been deployed for the given admin.
|
||||
*/
|
||||
public async isWalletDeployed(
|
||||
public async isAccountDeployed(
|
||||
admin: string,
|
||||
extraData?: BytesLike,
|
||||
): Promise<boolean> {
|
||||
const addr = await this.predictWalletAddress(admin, extraData);
|
||||
const addr = await this.predictAccountAddress(admin, extraData);
|
||||
return isContractDeployed(addr, this.contractWrapper.getProvider());
|
||||
}
|
||||
|
||||
@@ -141,29 +141,29 @@ export class SmartWalletFactory<TContract extends IAccountFactory>
|
||||
*******************************/
|
||||
|
||||
/**
|
||||
* Create a smart wallet
|
||||
* Create a account
|
||||
*
|
||||
* @remarks Create a smart wallet for an admin. The admin will have complete authority over the smart wallet.
|
||||
* @remarks Create a account for an admin. The admin will have complete authority over the account.
|
||||
*
|
||||
* @param admin - The admin of the smart wallet.
|
||||
* @param extraData - (Optional) Extra data to be passed to the smart wallet on creation.
|
||||
* @param admin - The admin of the account.
|
||||
* @param extraData - (Optional) Extra data to be passed to the account on creation.
|
||||
*
|
||||
* @example
|
||||
* ```javascript
|
||||
* const tx = await contract.smartWalletFactory.createWallet(admin, extraData);
|
||||
* const tx = await contract.accountFactory.createAccount(admin, extraData);
|
||||
* const receipt = tx.receipt();
|
||||
* const smartWalletAddress = tx.address;
|
||||
* const accountAddress = tx.address;
|
||||
* ```
|
||||
*
|
||||
* @twfeature SmartWalletFactory
|
||||
* @twfeature AccountFactory
|
||||
*/
|
||||
createWallet = /* @__PURE__ */ buildTransactionFunction(
|
||||
createAccount = /* @__PURE__ */ buildTransactionFunction(
|
||||
async (
|
||||
walletAdmin: string,
|
||||
accountAdmin: string,
|
||||
extraData?: BytesLike,
|
||||
): Promise<Transaction<TransactionResultWithAddress>> => {
|
||||
if (await this.isWalletDeployed(walletAdmin, extraData)) {
|
||||
throw new Error(`Wallet already deployed for admin: ${walletAdmin}`);
|
||||
if (await this.isAccountDeployed(accountAdmin, extraData)) {
|
||||
throw new Error(`Account already deployed for admin: ${accountAdmin}`);
|
||||
}
|
||||
|
||||
let data: BytesLike = utils.toUtf8Bytes("");
|
||||
@@ -174,7 +174,7 @@ export class SmartWalletFactory<TContract extends IAccountFactory>
|
||||
return Transaction.fromContractWrapper({
|
||||
contractWrapper: this.contractWrapper,
|
||||
method: "createAccount",
|
||||
args: [walletAdmin, data],
|
||||
args: [accountAdmin, data],
|
||||
parse: (receipt) => {
|
||||
const event = this.contractWrapper.parseLogs<AccountCreatedEvent>(
|
||||
"AccountCreated",
|
||||
+65
-65
@@ -1,6 +1,6 @@
|
||||
import { DetectableFeature } from "../interfaces/DetectableFeature";
|
||||
import { ContractWrapper } from "./contract-wrapper";
|
||||
import { FEATURE_SMART_WALLET } from "../../constants/thirdweb-features";
|
||||
import { FEATURE_ACCOUNT } from "../../constants/thirdweb-features";
|
||||
import { utils, BigNumber } from "ethers";
|
||||
import { Transaction } from "./transactions";
|
||||
|
||||
@@ -27,10 +27,10 @@ import { AddressOrEns } from "../../schema";
|
||||
import { resolveAddress } from "../../common";
|
||||
import { Signer } from "ethers";
|
||||
|
||||
export class SmartWallet<TContract extends IAccountCore>
|
||||
export class Account<TContract extends IAccountCore>
|
||||
implements DetectableFeature
|
||||
{
|
||||
featureName = FEATURE_SMART_WALLET.name;
|
||||
featureName = FEATURE_ACCOUNT.name;
|
||||
private contractWrapper: ContractWrapper<IAccountCore>;
|
||||
|
||||
private emptyRole: string =
|
||||
@@ -87,7 +87,7 @@ export class SmartWallet<TContract extends IAccountCore>
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate and sign a payload to grant or revoke a signer's access to the smart wallet.
|
||||
* Generate and sign a payload to grant or revoke a signer's access to the account.
|
||||
*
|
||||
* @param signer - The address of the signer
|
||||
* @param roleAction - The address of the signer
|
||||
@@ -137,7 +137,7 @@ export class SmartWallet<TContract extends IAccountCore>
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the factory contract which deployed the smart wallet
|
||||
* Get the factory contract which deployed the account
|
||||
*
|
||||
* @returns Returns the address of the factory
|
||||
*
|
||||
@@ -161,16 +161,16 @@ export class SmartWallet<TContract extends IAccountCore>
|
||||
********************************/
|
||||
|
||||
/**
|
||||
* Get whether a signer is an admin on the smart wallet.
|
||||
* Get whether a signer is an admin on the account.
|
||||
*
|
||||
* @example
|
||||
* ```javascript
|
||||
* const isAdmin = await contract.smartWallet.isAdmin(signer);
|
||||
* const isAdmin = await contract.account.isAdmin(signer);
|
||||
* ```
|
||||
* @param signer - The address of a signer of the smart wallet.
|
||||
* @returns whether a signer is an admin on the smart wallet.
|
||||
* @param signer - The address of a signer of the account.
|
||||
* @returns whether a signer is an admin on the account.
|
||||
*
|
||||
* @twfeature SmartWallet
|
||||
* @twfeature Account
|
||||
*/
|
||||
public async isAdmin(signerAddress: AddressOrEns): Promise<boolean> {
|
||||
const resolvedSignerAddress = await resolveAddress(signerAddress);
|
||||
@@ -180,16 +180,16 @@ export class SmartWallet<TContract extends IAccountCore>
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the restrictions under which a given signer can use the smart wallet.
|
||||
* Get the restrictions under which a given signer can use the account.
|
||||
*
|
||||
* @example
|
||||
* ```javascript
|
||||
* const restrictionsForSigner = await contract.smartWallet.getAccessRestrictions(signer);
|
||||
* const restrictionsForSigner = await contract.account.getAccessRestrictions(signer);
|
||||
* ```
|
||||
* @param signer - The address of a signer of the smart wallet.
|
||||
* @returns the restrictions under which a given signer can use the smart wallet.
|
||||
* @param signer - The address of a signer of the account.
|
||||
* @returns the restrictions under which a given signer can use the account.
|
||||
*
|
||||
* @twfeature SmartWallet
|
||||
* @twfeature Account
|
||||
*/
|
||||
public async getAccessRestrictions(
|
||||
signerAddress: AddressOrEns,
|
||||
@@ -203,16 +203,16 @@ export class SmartWallet<TContract extends IAccountCore>
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the deployer of the smart wallet
|
||||
* @remarks Get the address of the EIP-4337 factory contract which deployed the smart wallet
|
||||
* Get the deployer of the account
|
||||
* @remarks Get the address of the EIP-4337 factory contract which deployed the account
|
||||
*
|
||||
* @example
|
||||
* ```javascript
|
||||
* const factoryAddress = await contract.smartWallet.getFactoryAddress();
|
||||
* const factoryAddress = await contract.account.getFactoryAddress();
|
||||
* ```
|
||||
* @returns the address of the factory which deployed the smart wallet.
|
||||
* @returns the address of the factory which deployed the account.
|
||||
*
|
||||
* @twfeature SmartWallet
|
||||
* @twfeature Account
|
||||
*/
|
||||
public async getFactoryAddress(): Promise<string> {
|
||||
return this.contractWrapper.readContract.factory();
|
||||
@@ -223,11 +223,11 @@ export class SmartWallet<TContract extends IAccountCore>
|
||||
*
|
||||
* @example
|
||||
* ```javascript
|
||||
* const allSigners = await contract.smartWallet.getSignersWithRestrictions();
|
||||
* const allSigners = await contract.account.getSignersWithRestrictions();
|
||||
* ```
|
||||
* @returns all signers (admin or non-admin) of the smart wallet, along with their access restrictions.
|
||||
* @returns all signers (admin or non-admin) of the account, along with their access restrictions.
|
||||
*
|
||||
* @twfeature SmartWallet
|
||||
* @twfeature Account
|
||||
*/
|
||||
public async getSignersWithRestrictions(): Promise<SignerWithRestrictions[]> {
|
||||
// Get all associated signers.
|
||||
@@ -250,19 +250,19 @@ export class SmartWallet<TContract extends IAccountCore>
|
||||
********************************/
|
||||
|
||||
/**
|
||||
* Grant an address admin access to the smart wallet
|
||||
* Grant an address admin access to the account
|
||||
*
|
||||
* @remarks Grants an address admin access to the smart wallet. The admin will have complete authority over the smart wallet.
|
||||
* @remarks Grants an address admin access to the account. The admin will have complete authority over the account.
|
||||
*
|
||||
* @param signer - The address to be granted admin access to the smart wallet.
|
||||
* @param signer - The address to be granted admin access to the account.
|
||||
*
|
||||
* @example
|
||||
* ```javascript
|
||||
* const tx = await contract.smartWallet.grantAdminAccess(signer);
|
||||
* const tx = await contract.account.grantAdminAccess(signer);
|
||||
* const receipt = tx.receipt();
|
||||
* ```
|
||||
*
|
||||
* @twfeature SmartWallet
|
||||
* @twfeature Account
|
||||
*/
|
||||
grantAdminAccess = /* @__PURE__ */ buildTransactionFunction(
|
||||
async (signerAddress: AddressOrEns): Promise<Transaction> => {
|
||||
@@ -276,19 +276,19 @@ export class SmartWallet<TContract extends IAccountCore>
|
||||
);
|
||||
|
||||
/**
|
||||
* Revoke an address' admin access to the smart wallet
|
||||
* Revoke an address' admin access to the account
|
||||
*
|
||||
* @remarks Revokes an address' admin access to the smart wallet.
|
||||
* @remarks Revokes an address' admin access to the account.
|
||||
*
|
||||
* @param signer - The address of an admin of the smart wallet.
|
||||
* @param signer - The address of an admin of the account.
|
||||
*
|
||||
* @example
|
||||
* ```javascript
|
||||
* const tx = await contract.smartWallet.revokeAdminAccess(signer);
|
||||
* const tx = await contract.account.revokeAdminAccess(signer);
|
||||
* const receipt = tx.receipt();
|
||||
* ```
|
||||
*
|
||||
* @twfeature SmartWallet
|
||||
* @twfeature Account
|
||||
*/
|
||||
revokeAdminAccess = /* @__PURE__ */ buildTransactionFunction(
|
||||
async (signerAddress: AddressOrEns): Promise<Transaction> => {
|
||||
@@ -302,20 +302,20 @@ export class SmartWallet<TContract extends IAccountCore>
|
||||
);
|
||||
|
||||
/**
|
||||
* Grant an address access to the smart wallet with restrictions
|
||||
* Grant an address access to the account with restrictions
|
||||
*
|
||||
* @remarks Grants an address access to the smart wallet with certain restrictions.
|
||||
* @remarks Grants an address access to the account with certain restrictions.
|
||||
*
|
||||
* @param signer - The address to be granted access to the smart wallet.
|
||||
* @param restrictions - The restrictions to be applied to the signer's use of the smart wallet.
|
||||
* @param signer - The address to be granted access to the account.
|
||||
* @param restrictions - The restrictions to be applied to the signer's use of the account.
|
||||
*
|
||||
* @example
|
||||
* ```javascript
|
||||
* const tx = await contract.smartWallet.grantAccess(signer, restrictions);
|
||||
* const tx = await contract.account.grantAccess(signer, restrictions);
|
||||
* const receipt = tx.receipt();
|
||||
* ```
|
||||
*
|
||||
* @twfeature SmartWallet
|
||||
* @twfeature Account
|
||||
*/
|
||||
grantAccess = /* @__PURE__ */ buildTransactionFunction(
|
||||
async (
|
||||
@@ -395,20 +395,20 @@ export class SmartWallet<TContract extends IAccountCore>
|
||||
);
|
||||
|
||||
/**
|
||||
* Approve an address as a call target for a given signer on the smart wallet
|
||||
* Approve an address as a call target for a given signer on the account
|
||||
*
|
||||
* @remarks Approves an address as a call target for a given signer on the smart wallet.
|
||||
* @remarks Approves an address as a call target for a given signer on the account.
|
||||
*
|
||||
* @param signer - A signer with restricted access to the smart wallet.
|
||||
* @param signer - A signer with restricted access to the account.
|
||||
* @param target - The address to approve as a call target for the signer.
|
||||
*
|
||||
* @example
|
||||
* ```javascript
|
||||
* const tx = await contract.smartWallet.approveTargetForSigner(signer, target);
|
||||
* const tx = await contract.account.approveTargetForSigner(signer, target);
|
||||
* const receipt = tx.receipt();
|
||||
* ```
|
||||
*
|
||||
* @twfeature SmartWallet
|
||||
* @twfeature Account
|
||||
*/
|
||||
approveTargetForSigner = /* @__PURE__ */ buildTransactionFunction(
|
||||
async (
|
||||
@@ -444,20 +444,20 @@ export class SmartWallet<TContract extends IAccountCore>
|
||||
);
|
||||
|
||||
/**
|
||||
* Disapprove an address as a call target for a given signer on the smart wallet
|
||||
* Disapprove an address as a call target for a given signer on the account
|
||||
*
|
||||
* @remarks Disapprove an address as a call target for a given signer on the smart wallet.
|
||||
* @remarks Disapprove an address as a call target for a given signer on the account.
|
||||
*
|
||||
* @param signer - A signer with restricted access to the smart wallet.
|
||||
* @param signer - A signer with restricted access to the account.
|
||||
* @param target - The address to disapprove as a call target for the signer.
|
||||
*
|
||||
* @example
|
||||
* ```javascript
|
||||
* const tx = await contract.smartWallet.disapproveTargetForSigner(signer, target);
|
||||
* const tx = await contract.account.disapproveTargetForSigner(signer, target);
|
||||
* const receipt = tx.receipt();
|
||||
* ```
|
||||
*
|
||||
* @twfeature SmartWallet
|
||||
* @twfeature Account
|
||||
*/
|
||||
disapproveTargetForSigner = /* @__PURE__ */ buildTransactionFunction(
|
||||
async (
|
||||
@@ -496,20 +496,20 @@ export class SmartWallet<TContract extends IAccountCore>
|
||||
);
|
||||
|
||||
/**
|
||||
* Update the restrictions of an address for using the smart wallet
|
||||
* Update the restrictions of an address for using the account
|
||||
*
|
||||
* @remarks Updates an address' access to the smart wallet.
|
||||
* @remarks Updates an address' access to the account.
|
||||
*
|
||||
* @param signer - The address whose access to the smart wallet is to be updated.
|
||||
* @param restrictions - The restrictions to be applied to the signer's use of the smart wallet.
|
||||
* @param signer - The address whose access to the account is to be updated.
|
||||
* @param restrictions - The restrictions to be applied to the signer's use of the account.
|
||||
*
|
||||
* @example
|
||||
* ```javascript
|
||||
* const tx = await contract.smartWallet.updateAccess(signer, restrictions);
|
||||
* const tx = await contract.account.updateAccess(signer, restrictions);
|
||||
* const receipt = tx.receipt();
|
||||
* ```
|
||||
*
|
||||
* @twfeature SmartWallet
|
||||
* @twfeature Account
|
||||
*/
|
||||
updateAccess = /* @__PURE__ */ buildTransactionFunction(
|
||||
async (
|
||||
@@ -550,19 +550,19 @@ export class SmartWallet<TContract extends IAccountCore>
|
||||
);
|
||||
|
||||
/**
|
||||
* Revoke a scoped access address to the smart wallet
|
||||
* Revoke a scoped access address to the account
|
||||
*
|
||||
* @remarks Revokes an address' access to the smart wallet.
|
||||
* @remarks Revokes an address' access to the account.
|
||||
*
|
||||
* @param signer - The address whose access to the smart wallet is to be revoked.
|
||||
* @param signer - The address whose access to the account is to be revoked.
|
||||
*
|
||||
* @example
|
||||
* ```javascript
|
||||
* const tx = await contract.smartWallet.revokeAccess(signer);
|
||||
* const tx = await contract.account.revokeAccess(signer);
|
||||
* const receipt = tx.receipt();
|
||||
* ```
|
||||
*
|
||||
* @twfeature SmartWallet
|
||||
* @twfeature Account
|
||||
*/
|
||||
revokeAccess = /* @__PURE__ */ buildTransactionFunction(
|
||||
async (signerAddress: AddressOrEns): Promise<Transaction> => {
|
||||
@@ -600,19 +600,19 @@ export class SmartWallet<TContract extends IAccountCore>
|
||||
);
|
||||
|
||||
/**
|
||||
* Set the wallet's entire snapshot of permissions
|
||||
* Set the account's entire snapshot of permissions
|
||||
*
|
||||
* @remarks Sets the wallet's entire snapshot of permissions.
|
||||
* @remarks Sets the account's entire snapshot of permissions.
|
||||
*
|
||||
* @param permissionsSnapshot - the snapshot to set as the wallet's entire permission snapshot.
|
||||
* @param permissionsSnapshot - the snapshot to set as the account's entire permission snapshot.
|
||||
*
|
||||
* @example
|
||||
* ```javascript
|
||||
* const tx = await contract.smartWallet.setAccess(permissionsSnapshot);
|
||||
* const tx = await contract.account.setAccess(permissionsSnapshot);
|
||||
* const receipt = tx.receipt();
|
||||
* ```
|
||||
*
|
||||
* @twfeature SmartWallet
|
||||
* @twfeature Account
|
||||
*/
|
||||
setAccess = /* @__PURE__ */ buildTransactionFunction(
|
||||
async (
|
||||
@@ -1,8 +1,7 @@
|
||||
import { EventType } from "../../constants/events";
|
||||
import type { ContractEvent, EventQueryOptions } from "../../types/events";
|
||||
import { ContractWrapper } from "./contract-wrapper";
|
||||
import type { BaseContract, Event, providers } from "ethers";
|
||||
import type { EventFragment } from "ethers/lib/utils.js";
|
||||
import type { BaseContract, Event, providers, utils } from "ethers";
|
||||
import type { EventEmitter } from "eventemitter3";
|
||||
|
||||
/**
|
||||
@@ -325,7 +324,7 @@ export class ContractEvents<TContract extends BaseContract> {
|
||||
}
|
||||
|
||||
private toContractEvent<TEvent extends Record<string, any>>(
|
||||
event: EventFragment,
|
||||
event: utils.EventFragment,
|
||||
args: ReadonlyArray<any>,
|
||||
rawLog: providers.Log,
|
||||
): ContractEvent<TEvent> {
|
||||
|
||||
@@ -44,7 +44,6 @@ import {
|
||||
type Signer,
|
||||
constants,
|
||||
} from "ethers";
|
||||
import { ConnectionInfo } from "ethers/lib/utils.js";
|
||||
import invariant from "tiny-invariant";
|
||||
import { CONTRACT_ADDRESSES } from "../../constants/addresses/CONTRACT_ADDRESSES";
|
||||
import { getContractAddressByChainId } from "../../constants/addresses/getContractAddressByChainId";
|
||||
@@ -471,7 +470,7 @@ export class ContractWrapper<
|
||||
callOverrides: CallOverrides,
|
||||
) {
|
||||
const provider = this.getProvider() as providers.Provider & {
|
||||
connection?: ConnectionInfo;
|
||||
connection?: utils.ConnectionInfo;
|
||||
};
|
||||
|
||||
// Get metadata for transaction to populate into error
|
||||
|
||||
@@ -50,5 +50,5 @@ export * from "./contract-published-metadata";
|
||||
export * from "./contract-owner";
|
||||
export * from "./transactions";
|
||||
export * from "./contract-appuri";
|
||||
export * from "./smart-wallet";
|
||||
export * from "./smart-wallet-factory";
|
||||
export * from "./account";
|
||||
export * from "./account-factory";
|
||||
|
||||
@@ -30,8 +30,6 @@ import {
|
||||
constants,
|
||||
} from "ethers";
|
||||
import { BigNumber } from "ethers";
|
||||
import { FormatTypes } from "ethers/lib/utils.js";
|
||||
import type { ConnectionInfo } from "ethers/lib/utils.js";
|
||||
import invariant from "tiny-invariant";
|
||||
import EventEmitter from "eventemitter3";
|
||||
import type { DeployEvents } from "../../types/deploy";
|
||||
@@ -494,7 +492,7 @@ export class Transaction<
|
||||
try {
|
||||
// for dynamic contracts, add 30% to the gas limit to account for multiple delegate calls
|
||||
const abi = JSON.parse(
|
||||
this.contract.interface.format(FormatTypes.json) as string,
|
||||
this.contract.interface.format("json") as string,
|
||||
);
|
||||
if (isRouterContract(abi)) {
|
||||
overrides.gasLimit = overrides.gasLimit.mul(110).div(100);
|
||||
@@ -663,7 +661,7 @@ export class Transaction<
|
||||
*/
|
||||
private async transactionError(error: any) {
|
||||
const provider = this.provider as providers.Provider & {
|
||||
connection?: ConnectionInfo;
|
||||
connection?: utils.ConnectionInfo;
|
||||
};
|
||||
|
||||
// Get metadata for transaction to populate into error
|
||||
@@ -849,7 +847,7 @@ export class DeployTransaction extends TransactionContext {
|
||||
*/
|
||||
private async deployError(error: any) {
|
||||
const provider = this.provider as providers.Provider & {
|
||||
connection?: ConnectionInfo;
|
||||
connection?: utils.ConnectionInfo;
|
||||
};
|
||||
|
||||
// Get metadata for transaction to populate into error
|
||||
|
||||
@@ -12,4 +12,4 @@ export * from "./multiwrap";
|
||||
export * from "./registry";
|
||||
export * from "./transactions";
|
||||
export * from "./contract";
|
||||
export * from "./smart-wallet";
|
||||
export * from "./account";
|
||||
|
||||
+147
-165
@@ -4,8 +4,8 @@ import { assert, expect } from "chai";
|
||||
import {
|
||||
SignerWithRestrictions,
|
||||
AccessRestrictions,
|
||||
SmartWallet,
|
||||
SmartWalletFactory,
|
||||
Account,
|
||||
AccountFactory,
|
||||
SignerWithRestrictionsInput,
|
||||
SignerWithRestrictionsBatchInput,
|
||||
} from "../../src/evm";
|
||||
@@ -23,9 +23,9 @@ import { IAccountCore, IAccountFactory } from "@thirdweb-dev/contracts-js";
|
||||
|
||||
global.fetch = /* @__PURE__ */ require("cross-fetch");
|
||||
|
||||
/* @__PURE__ */ describe("Smart wallets with wallet factory", function () {
|
||||
let smartWalletFactory: SmartWalletFactory<IAccountFactory>;
|
||||
let smartWallet: SmartWallet<IAccountCore>;
|
||||
/* @__PURE__ */ describe("Accounts with account factory", function () {
|
||||
let accountFactory: AccountFactory<IAccountFactory>;
|
||||
let account: Account<IAccountCore>;
|
||||
|
||||
let adminWallet: SignerWithAddress;
|
||||
|
||||
@@ -66,64 +66,63 @@ global.fetch = /* @__PURE__ */ require("cross-fetch");
|
||||
adminWallet,
|
||||
[entrypoint.address],
|
||||
);
|
||||
smartWalletFactory = (await sdk.getContract(factoryAddress))
|
||||
.smartWalletFactory;
|
||||
accountFactory = (await sdk.getContract(factoryAddress)).accountFactory;
|
||||
});
|
||||
|
||||
describe("Test: SmartWalletFactory actions", () => {
|
||||
it("Should create a new wallet for the admin", async () => {
|
||||
// Check before creating a smart wallet for `adminWallet`
|
||||
const isDeployed = await smartWalletFactory.isWalletDeployed(
|
||||
describe("Test: AccountFactory actions", () => {
|
||||
it("Should create a new account for the admin", async () => {
|
||||
// Check before creating a account for `adminWallet`
|
||||
const isDeployed = await accountFactory.isAccountDeployed(
|
||||
adminWallet.address,
|
||||
);
|
||||
assert.isFalse(
|
||||
isDeployed,
|
||||
"Smart wallet is should not be deployed for admin.",
|
||||
"Account is should not be deployed for admin.",
|
||||
);
|
||||
|
||||
const predictedAccountAddress: string =
|
||||
await smartWalletFactory.predictWalletAddress(adminWallet.address);
|
||||
await accountFactory.predictAccountAddress(adminWallet.address);
|
||||
|
||||
const allWalletsBefore = (await smartWalletFactory.getAllAccounts()).map(
|
||||
(wallet) => wallet.account,
|
||||
const allAccountsBefore = (await accountFactory.getAllAccounts()).map(
|
||||
(wallet) => account.account,
|
||||
);
|
||||
assert.isFalse(
|
||||
allWalletsBefore.includes(predictedAccountAddress),
|
||||
allAccountsBefore.includes(predictedAccountAddress),
|
||||
"Account should not be deployed for admin already.",
|
||||
);
|
||||
|
||||
assert.isTrue(
|
||||
(await smartWalletFactory.getAssociatedSigners(predictedAccountAddress))
|
||||
(await accountFactory.getAssociatedSigners(predictedAccountAddress))
|
||||
.length === 0,
|
||||
"Wallet should have no associated signers.",
|
||||
);
|
||||
assert.isTrue(
|
||||
(await smartWalletFactory.getAssociatedWallets(adminWallet.address))
|
||||
(await accountFactory.getAssociatedAccounts(adminWallet.address))
|
||||
.length === 0,
|
||||
"Signer should have no associated wallets.",
|
||||
"Signer should have no associated accounts.",
|
||||
);
|
||||
|
||||
// Create smart wallet for `adminWallet`
|
||||
const tx = await smartWalletFactory.createWallet(adminWallet.address);
|
||||
// Create account for `adminWallet`
|
||||
const tx = await accountFactory.createAccount(adminWallet.address);
|
||||
|
||||
// Checks after creating a smart wallet for `adminWallet`
|
||||
// Checks after creating a account for `adminWallet`
|
||||
assert.strictEqual(
|
||||
utils.getAddress(tx.address),
|
||||
utils.getAddress(predictedAccountAddress),
|
||||
"Smart wallet address should match predicted address.",
|
||||
"Account address should match predicted address.",
|
||||
);
|
||||
assert.isTrue(
|
||||
await smartWalletFactory.isWalletDeployed(adminWallet.address),
|
||||
"Smart wallet is should be deployed for admin.",
|
||||
await accountFactory.isAccountDeployed(adminWallet.address),
|
||||
"Account is should be deployed for admin.",
|
||||
);
|
||||
|
||||
const allWalletsAfter = await smartWalletFactory.getAllAccounts();
|
||||
const allAccountsAfter = await accountFactory.getAllAccounts();
|
||||
assert.isTrue(
|
||||
allWalletsAfter.length === 1,
|
||||
"Only one wallet should be created on the factory.",
|
||||
allAccountsAfter.length === 1,
|
||||
"Only one account should be created on the factory.",
|
||||
);
|
||||
|
||||
const { account, admin } = allWalletsAfter.filter(
|
||||
const { account, admin } = allAccountsAfter.filter(
|
||||
(wallet) =>
|
||||
utils.getAddress(wallet.account) ===
|
||||
utils.getAddress(predictedAccountAddress),
|
||||
@@ -136,165 +135,161 @@ global.fetch = /* @__PURE__ */ require("cross-fetch");
|
||||
assert.strictEqual(
|
||||
utils.getAddress(admin),
|
||||
utils.getAddress(adminWallet.address),
|
||||
"Correct admin for smart wallet.",
|
||||
"Correct admin for account.",
|
||||
);
|
||||
|
||||
const associatedWallets = await smartWalletFactory.getAssociatedWallets(
|
||||
const associatedAccounts = await accountFactory.getAssociatedAccounts(
|
||||
admin,
|
||||
);
|
||||
const associatedSigner = await smartWalletFactory.getAssociatedSigners(
|
||||
const associatedSigner = await accountFactory.getAssociatedSigners(
|
||||
account,
|
||||
);
|
||||
|
||||
assert.isTrue(
|
||||
associatedWallets.length === 1,
|
||||
associatedAccounts.length === 1,
|
||||
"Wallet should have only the admin as an associated signer.",
|
||||
);
|
||||
assert.strictEqual(
|
||||
utils.getAddress(account),
|
||||
utils.getAddress(associatedWallets[0]),
|
||||
utils.getAddress(associatedAccounts[0]),
|
||||
"Wallet should have only the admin as an associated signer.",
|
||||
);
|
||||
assert.isTrue(
|
||||
associatedSigner.length === 1,
|
||||
"Signer should have only the created wallet as an associated wallet.",
|
||||
"Signer should have only the created account as an associated account.",
|
||||
);
|
||||
assert.strictEqual(
|
||||
utils.getAddress(admin),
|
||||
utils.getAddress(associatedSigner[0]),
|
||||
"Signer should have only the created wallet as an associated wallet.",
|
||||
"Signer should have only the created account as an associated account.",
|
||||
);
|
||||
});
|
||||
|
||||
it("Should throw if creating wallet for an admin who already has one", async () => {
|
||||
// Create a wallet for admin
|
||||
await smartWalletFactory.createWallet(adminWallet.address);
|
||||
it("Should throw if creating account for an admin who already has one", async () => {
|
||||
// Create a account for admin
|
||||
await accountFactory.createAccount(adminWallet.address);
|
||||
|
||||
// Try creating another wallet for the same admin
|
||||
// Try creating another account for the same admin
|
||||
try {
|
||||
await smartWalletFactory.createWallet(adminWallet.address);
|
||||
await accountFactory.createAccount(adminWallet.address);
|
||||
expect.fail();
|
||||
} catch (err: any) {
|
||||
expect(err.message).to.equal(
|
||||
`Wallet already deployed for admin: ${adminWallet.address}`,
|
||||
`Account already deployed for admin: ${adminWallet.address}`,
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe("Test: SmartWallet actions", () => {
|
||||
describe("Test: Account actions", () => {
|
||||
beforeEach(async () => {
|
||||
// Create a wallet for admin
|
||||
const tx = await smartWalletFactory.createWallet(adminWallet.address);
|
||||
const smartWalletAddress = tx.address;
|
||||
// Create a account for admin
|
||||
const tx = await accountFactory.createAccount(adminWallet.address);
|
||||
const accountAddress = tx.address;
|
||||
|
||||
sdk.updateSignerOrProvider(adminWallet);
|
||||
await mockUploadContractMetadata(
|
||||
"smart-wallet",
|
||||
smartWalletAddress,
|
||||
accountAddress,
|
||||
IAccountCoreAbi,
|
||||
);
|
||||
|
||||
smartWallet = (await sdk.getContract(smartWalletAddress)).smartWallet;
|
||||
account = (await sdk.getContract(accountAddress)).account;
|
||||
});
|
||||
|
||||
it("Should be able to add another admin to the wallet.", async () => {
|
||||
it("Should be able to add another admin to the account.", async () => {
|
||||
assert.isFalse(
|
||||
await smartWallet.isAdmin(signer1Wallet.address),
|
||||
"New signer1 should not be an admin on the smart wallet.",
|
||||
await account.isAdmin(signer1Wallet.address),
|
||||
"New signer1 should not be an admin on the account.",
|
||||
);
|
||||
|
||||
await smartWallet.grantAdminAccess(signer1Wallet.address);
|
||||
await account.grantAdminAccess(signer1Wallet.address);
|
||||
|
||||
assert.isTrue(
|
||||
await smartWallet.isAdmin(signer1Wallet.address),
|
||||
"New signer1 should be an admin on the smart wallet.",
|
||||
await account.isAdmin(signer1Wallet.address),
|
||||
"New signer1 should be an admin on the account.",
|
||||
);
|
||||
|
||||
const isAdmin = (
|
||||
(await smartWallet.getSignersWithRestrictions()).find(
|
||||
(await account.getSignersWithRestrictions()).find(
|
||||
(result) =>
|
||||
utils.getAddress(result.signer) ===
|
||||
utils.getAddress(signer1Wallet.address),
|
||||
) as SignerWithRestrictions
|
||||
).isAdmin;
|
||||
assert.isTrue(isAdmin, "New signer1 should be an admin on the wallet.");
|
||||
assert.isTrue(isAdmin, "New signer1 should be an admin on the account.");
|
||||
|
||||
assert.isTrue(
|
||||
(
|
||||
await smartWalletFactory.getAssociatedSigners(
|
||||
smartWallet.getAddress(),
|
||||
)
|
||||
await accountFactory.getAssociatedSigners(account.getAddress())
|
||||
).includes(signer1Wallet.address),
|
||||
"New signer1 is an associated signer of the wallet.",
|
||||
"New signer1 is an associated signer of the account.",
|
||||
);
|
||||
assert.isTrue(
|
||||
(
|
||||
await smartWalletFactory.getAssociatedWallets(signer1Wallet.address)
|
||||
).includes(smartWallet.getAddress()),
|
||||
"Wallet is an associated wallet of the signer.",
|
||||
await accountFactory.getAssociatedAccounts(signer1Wallet.address)
|
||||
).includes(account.getAddress()),
|
||||
"Wallet is an associated account of the signer.",
|
||||
);
|
||||
});
|
||||
|
||||
it("Should be able to remove an admin from the wallet.", async () => {
|
||||
await smartWallet.grantAdminAccess(signer1Wallet.address);
|
||||
it("Should be able to remove an admin from the account.", async () => {
|
||||
await account.grantAdminAccess(signer1Wallet.address);
|
||||
assert.isTrue(
|
||||
await smartWallet.isAdmin(signer1Wallet.address),
|
||||
"New signer1 should be an admin on the smart wallet.",
|
||||
await account.isAdmin(signer1Wallet.address),
|
||||
"New signer1 should be an admin on the account.",
|
||||
);
|
||||
|
||||
await smartWallet.revokeAdminAccess(signer1Wallet.address);
|
||||
await account.revokeAdminAccess(signer1Wallet.address);
|
||||
|
||||
assert.isFalse(
|
||||
await smartWallet.isAdmin(signer1Wallet.address),
|
||||
"New signer1 should not be an admin on the smart wallet.",
|
||||
await account.isAdmin(signer1Wallet.address),
|
||||
"New signer1 should not be an admin on the account.",
|
||||
);
|
||||
|
||||
assert.isFalse(
|
||||
(await smartWallet.getSignersWithRestrictions())
|
||||
(await account.getSignersWithRestrictions())
|
||||
.map((result) => utils.getAddress(result.signer))
|
||||
.includes(signer1Wallet.address),
|
||||
"New signer1 should not be an admin on the wallet.",
|
||||
"New signer1 should not be an admin on the account.",
|
||||
);
|
||||
|
||||
assert.isFalse(
|
||||
(
|
||||
await smartWalletFactory.getAssociatedSigners(
|
||||
smartWallet.getAddress(),
|
||||
)
|
||||
await accountFactory.getAssociatedSigners(account.getAddress())
|
||||
).includes(signer1Wallet.address),
|
||||
"New signer1 is not an associated signer of the wallet.",
|
||||
"New signer1 is not an associated signer of the account.",
|
||||
);
|
||||
assert.isFalse(
|
||||
(
|
||||
await smartWalletFactory.getAssociatedWallets(signer1Wallet.address)
|
||||
).includes(smartWallet.getAddress()),
|
||||
"Wallet is not an associated wallet of the signer.",
|
||||
await accountFactory.getAssociatedAccounts(signer1Wallet.address)
|
||||
).includes(account.getAddress()),
|
||||
"Wallet is not an associated account of the signer.",
|
||||
);
|
||||
});
|
||||
|
||||
it("Should be able to grant restricted access to a new signer.", async () => {
|
||||
const signersWithRestrictions =
|
||||
await smartWallet.getSignersWithRestrictions();
|
||||
await account.getSignersWithRestrictions();
|
||||
assert.isFalse(
|
||||
signersWithRestrictions
|
||||
.map((result) => utils.getAddress(result.signer))
|
||||
.includes(signer1Wallet.address),
|
||||
"New signer should not already have access to the wallet.",
|
||||
"New signer should not already have access to the account.",
|
||||
);
|
||||
|
||||
// Grant access
|
||||
await smartWallet.grantAccess(signer1Wallet.address, {
|
||||
await account.grantAccess(signer1Wallet.address, {
|
||||
nativeTokenLimitPerTransaction: "1",
|
||||
approvedCallTargets: [adminWallet.address],
|
||||
});
|
||||
|
||||
assert.isFalse(
|
||||
await smartWallet.isAdmin(signer1Wallet.address),
|
||||
"New signer1 should not be an admin on the smart wallet.",
|
||||
await account.isAdmin(signer1Wallet.address),
|
||||
"New signer1 should not be an admin on the account.",
|
||||
);
|
||||
const newSignerWithRestrictions =
|
||||
await smartWallet.getSignersWithRestrictions();
|
||||
await account.getSignersWithRestrictions();
|
||||
const restrictions = newSignerWithRestrictions.find(
|
||||
(result) =>
|
||||
utils.getAddress(result.signer) ===
|
||||
@@ -304,7 +299,7 @@ global.fetch = /* @__PURE__ */ require("cross-fetch");
|
||||
newSignerWithRestrictions
|
||||
.map((result) => utils.getAddress(result.signer))
|
||||
.includes(signer1Wallet.address),
|
||||
"New signer1 should be a signer on the wallet.",
|
||||
"New signer1 should be a signer on the account.",
|
||||
);
|
||||
assert.strictEqual(
|
||||
restrictions.nativeTokenLimitPerTransaction.toString(),
|
||||
@@ -324,30 +319,28 @@ global.fetch = /* @__PURE__ */ require("cross-fetch");
|
||||
|
||||
assert.isTrue(
|
||||
(
|
||||
await smartWalletFactory.getAssociatedSigners(
|
||||
smartWallet.getAddress(),
|
||||
)
|
||||
await accountFactory.getAssociatedSigners(account.getAddress())
|
||||
).includes(signer1Wallet.address),
|
||||
"New signer1 is an associated signer of the wallet.",
|
||||
"New signer1 is an associated signer of the account.",
|
||||
);
|
||||
assert.isTrue(
|
||||
(
|
||||
await smartWalletFactory.getAssociatedWallets(signer1Wallet.address)
|
||||
).includes(smartWallet.getAddress()),
|
||||
"Wallet is an associated wallet of the signer.",
|
||||
await accountFactory.getAssociatedAccounts(signer1Wallet.address)
|
||||
).includes(account.getAddress()),
|
||||
"Wallet is an associated account of the signer.",
|
||||
);
|
||||
});
|
||||
|
||||
it("Should not be able to grant restricted access to a signer who already has access.", async () => {
|
||||
// Grant access to signer1
|
||||
await smartWallet.grantAccess(signer1Wallet.address, {
|
||||
await account.grantAccess(signer1Wallet.address, {
|
||||
nativeTokenLimitPerTransaction: "1",
|
||||
approvedCallTargets: [adminWallet.address],
|
||||
});
|
||||
|
||||
// Try granting access to signer1 again
|
||||
try {
|
||||
await smartWallet.grantAccess(signer1Wallet.address, {
|
||||
await account.grantAccess(signer1Wallet.address, {
|
||||
approvedCallTargets: [adminWallet.address],
|
||||
});
|
||||
expect.fail();
|
||||
@@ -358,57 +351,55 @@ global.fetch = /* @__PURE__ */ require("cross-fetch");
|
||||
|
||||
it("Should be able to revoke restricted access from an authorized signer.", async () => {
|
||||
// Grant access to signer1
|
||||
await smartWallet.grantAccess(signer1Wallet.address, {
|
||||
await account.grantAccess(signer1Wallet.address, {
|
||||
nativeTokenLimitPerTransaction: "1",
|
||||
approvedCallTargets: [adminWallet.address],
|
||||
});
|
||||
|
||||
// Revoke access
|
||||
await smartWallet.revokeAccess(signer1Wallet.address);
|
||||
await account.revokeAccess(signer1Wallet.address);
|
||||
|
||||
const signersWithRestrictions =
|
||||
await smartWallet.getSignersWithRestrictions();
|
||||
await account.getSignersWithRestrictions();
|
||||
assert.isFalse(
|
||||
signersWithRestrictions
|
||||
.map((result) => utils.getAddress(result.signer))
|
||||
.includes(signer1Wallet.address),
|
||||
"New signer should not have access to the wallet.",
|
||||
"New signer should not have access to the account.",
|
||||
);
|
||||
|
||||
assert.isFalse(
|
||||
await smartWallet.isAdmin(signer1Wallet.address),
|
||||
"New signer1 should not be an admin on the smart wallet.",
|
||||
await account.isAdmin(signer1Wallet.address),
|
||||
"New signer1 should not be an admin on the account.",
|
||||
);
|
||||
|
||||
assert.isFalse(
|
||||
(
|
||||
await smartWalletFactory.getAssociatedSigners(
|
||||
smartWallet.getAddress(),
|
||||
)
|
||||
await accountFactory.getAssociatedSigners(account.getAddress())
|
||||
).includes(signer1Wallet.address),
|
||||
"New signer1 is not an associated signer of the wallet.",
|
||||
"New signer1 is not an associated signer of the account.",
|
||||
);
|
||||
assert.isFalse(
|
||||
(
|
||||
await smartWalletFactory.getAssociatedWallets(signer1Wallet.address)
|
||||
).includes(smartWallet.getAddress()),
|
||||
"Wallet is not an associated wallet of the signer.",
|
||||
await accountFactory.getAssociatedAccounts(signer1Wallet.address)
|
||||
).includes(account.getAddress()),
|
||||
"Wallet is not an associated account of the signer.",
|
||||
);
|
||||
});
|
||||
|
||||
it("Should not be able to revoke restricted access from a signer who doesn't have access.", async () => {
|
||||
const signersWithRestrictions =
|
||||
await smartWallet.getSignersWithRestrictions();
|
||||
await account.getSignersWithRestrictions();
|
||||
assert.isFalse(
|
||||
signersWithRestrictions
|
||||
.map((result) => utils.getAddress(result.signer))
|
||||
.includes(signer1Wallet.address),
|
||||
"New signer should not already have access to the wallet.",
|
||||
"New signer should not already have access to the account.",
|
||||
);
|
||||
|
||||
// Try revoking access from signer1
|
||||
try {
|
||||
await smartWallet.revokeAccess(signer1Wallet.address);
|
||||
await account.revokeAccess(signer1Wallet.address);
|
||||
expect.fail();
|
||||
} catch (err: any) {
|
||||
expect(err.message).to.equal(`Signer does not have any access`);
|
||||
@@ -417,18 +408,17 @@ global.fetch = /* @__PURE__ */ require("cross-fetch");
|
||||
|
||||
it("Should be able to update access of an authorized signer.", async () => {
|
||||
// Grant access
|
||||
await smartWallet.grantAccess(signer1Wallet.address, {
|
||||
await account.grantAccess(signer1Wallet.address, {
|
||||
nativeTokenLimitPerTransaction: "1",
|
||||
approvedCallTargets: [adminWallet.address],
|
||||
});
|
||||
|
||||
assert.isFalse(
|
||||
await smartWallet.isAdmin(signer1Wallet.address),
|
||||
"New signer1 should not be an admin on the smart wallet.",
|
||||
await account.isAdmin(signer1Wallet.address),
|
||||
"New signer1 should not be an admin on the account.",
|
||||
);
|
||||
|
||||
const signerWithRestrictions =
|
||||
await smartWallet.getSignersWithRestrictions();
|
||||
const signerWithRestrictions = await account.getSignersWithRestrictions();
|
||||
const restrictions = signerWithRestrictions.find(
|
||||
(result) =>
|
||||
utils.getAddress(result.signer) ===
|
||||
@@ -438,7 +428,7 @@ global.fetch = /* @__PURE__ */ require("cross-fetch");
|
||||
signerWithRestrictions
|
||||
.map((result) => utils.getAddress(result.signer))
|
||||
.includes(signer1Wallet.address),
|
||||
"New signer1 should be a signer on the wallet.",
|
||||
"New signer1 should be a signer on the account.",
|
||||
);
|
||||
assert.strictEqual(
|
||||
restrictions.nativeTokenLimitPerTransaction.toString(),
|
||||
@@ -457,18 +447,18 @@ global.fetch = /* @__PURE__ */ require("cross-fetch");
|
||||
);
|
||||
|
||||
// Update access
|
||||
await smartWallet.updateAccess(signer1Wallet.address, {
|
||||
await account.updateAccess(signer1Wallet.address, {
|
||||
nativeTokenLimitPerTransaction: "3",
|
||||
approvedCallTargets: [signer2Wallet.address],
|
||||
});
|
||||
|
||||
assert.isFalse(
|
||||
await smartWallet.isAdmin(signer1Wallet.address),
|
||||
"New signer1 should not be an admin on the smart wallet.",
|
||||
await account.isAdmin(signer1Wallet.address),
|
||||
"New signer1 should not be an admin on the account.",
|
||||
);
|
||||
|
||||
const newSignerWithRestrictions =
|
||||
await smartWallet.getSignersWithRestrictions();
|
||||
await account.getSignersWithRestrictions();
|
||||
const newRestrictions = newSignerWithRestrictions.find(
|
||||
(result) =>
|
||||
utils.getAddress(result.signer) ===
|
||||
@@ -478,7 +468,7 @@ global.fetch = /* @__PURE__ */ require("cross-fetch");
|
||||
newSignerWithRestrictions
|
||||
.map((result) => utils.getAddress(result.signer))
|
||||
.includes(signer1Wallet.address),
|
||||
"New signer1 should be a signer on the wallet.",
|
||||
"New signer1 should be a signer on the account.",
|
||||
);
|
||||
assert.strictEqual(
|
||||
newRestrictions.nativeTokenLimitPerTransaction.toString(),
|
||||
@@ -499,17 +489,17 @@ global.fetch = /* @__PURE__ */ require("cross-fetch");
|
||||
|
||||
it("Should not be able to update access of a signer who doesn't have access.", async () => {
|
||||
const signersWithRestrictions =
|
||||
await smartWallet.getSignersWithRestrictions();
|
||||
await account.getSignersWithRestrictions();
|
||||
assert.isFalse(
|
||||
signersWithRestrictions
|
||||
.map((result) => utils.getAddress(result.signer))
|
||||
.includes(signer1Wallet.address),
|
||||
"New signer should not already have access to the wallet.",
|
||||
"New signer should not already have access to the account.",
|
||||
);
|
||||
|
||||
// Try updating access of signer1
|
||||
try {
|
||||
await smartWallet.updateAccess(signer1Wallet.address, {
|
||||
await account.updateAccess(signer1Wallet.address, {
|
||||
approvedCallTargets: [signer2Wallet.address],
|
||||
});
|
||||
expect.fail();
|
||||
@@ -520,14 +510,12 @@ global.fetch = /* @__PURE__ */ require("cross-fetch");
|
||||
|
||||
it("Should be able to append an approved target for an authorized signer.", async () => {
|
||||
// Grant access
|
||||
await smartWallet.grantAccess(signer1Wallet.address, {
|
||||
await account.grantAccess(signer1Wallet.address, {
|
||||
nativeTokenLimitPerTransaction: "1",
|
||||
approvedCallTargets: [adminWallet.address],
|
||||
});
|
||||
|
||||
const restrictions = (
|
||||
await smartWallet.getSignersWithRestrictions()
|
||||
).find(
|
||||
const restrictions = (await account.getSignersWithRestrictions()).find(
|
||||
(result) =>
|
||||
utils.getAddress(result.signer) ===
|
||||
utils.getAddress(signer1Wallet.address),
|
||||
@@ -544,14 +532,12 @@ global.fetch = /* @__PURE__ */ require("cross-fetch");
|
||||
);
|
||||
|
||||
// Append approved target
|
||||
await smartWallet.approveTargetForSigner(
|
||||
await account.approveTargetForSigner(
|
||||
signer1Wallet.address,
|
||||
signer2Wallet.address,
|
||||
);
|
||||
|
||||
const newRestrictions = (
|
||||
await smartWallet.getSignersWithRestrictions()
|
||||
).find(
|
||||
const newRestrictions = (await account.getSignersWithRestrictions()).find(
|
||||
(result) =>
|
||||
utils.getAddress(result.signer) ===
|
||||
utils.getAddress(signer1Wallet.address),
|
||||
@@ -575,14 +561,12 @@ global.fetch = /* @__PURE__ */ require("cross-fetch");
|
||||
|
||||
it("Should be able to remove an approved target for an authorized signer.", async () => {
|
||||
// Grant access
|
||||
await smartWallet.grantAccess(signer1Wallet.address, {
|
||||
await account.grantAccess(signer1Wallet.address, {
|
||||
nativeTokenLimitPerTransaction: "1",
|
||||
approvedCallTargets: [adminWallet.address, signer2Wallet.address],
|
||||
});
|
||||
|
||||
const restrictions = (
|
||||
await smartWallet.getSignersWithRestrictions()
|
||||
).find(
|
||||
const restrictions = (await account.getSignersWithRestrictions()).find(
|
||||
(result) =>
|
||||
utils.getAddress(result.signer) ===
|
||||
utils.getAddress(signer1Wallet.address),
|
||||
@@ -604,14 +588,12 @@ global.fetch = /* @__PURE__ */ require("cross-fetch");
|
||||
);
|
||||
|
||||
// Remove approved target
|
||||
await smartWallet.disapproveTargetForSigner(
|
||||
await account.disapproveTargetForSigner(
|
||||
signer1Wallet.address,
|
||||
signer2Wallet.address,
|
||||
);
|
||||
|
||||
const newRestrictions = (
|
||||
await smartWallet.getSignersWithRestrictions()
|
||||
).find(
|
||||
const newRestrictions = (await account.getSignersWithRestrictions()).find(
|
||||
(result) =>
|
||||
utils.getAddress(result.signer) ===
|
||||
utils.getAddress(signer1Wallet.address),
|
||||
@@ -628,7 +610,7 @@ global.fetch = /* @__PURE__ */ require("cross-fetch");
|
||||
);
|
||||
});
|
||||
|
||||
it("Should be able to set access for the smart wallet in a batch.", async () => {
|
||||
it("Should be able to set access for the account in a batch.", async () => {
|
||||
/**
|
||||
* All cases to test
|
||||
*
|
||||
@@ -661,7 +643,7 @@ global.fetch = /* @__PURE__ */ require("cross-fetch");
|
||||
signersWithRestrictions.push(restrictionsSigner3);
|
||||
|
||||
// Removing existing admin
|
||||
await smartWallet.grantAdminAccess(signer4Wallet.address);
|
||||
await account.grantAdminAccess(signer4Wallet.address);
|
||||
|
||||
const restrictionsSigner4: SignerWithRestrictionsInput = {
|
||||
signer: signer4Wallet.address,
|
||||
@@ -679,7 +661,7 @@ global.fetch = /* @__PURE__ */ require("cross-fetch");
|
||||
signersWithRestrictions.push(restrictionsSigner5);
|
||||
|
||||
// Removing an existing scoped signer
|
||||
await smartWallet.grantAccess(signer6Wallet.address, {
|
||||
await account.grantAccess(signer6Wallet.address, {
|
||||
approvedCallTargets: [adminWallet.address],
|
||||
});
|
||||
|
||||
@@ -692,7 +674,7 @@ global.fetch = /* @__PURE__ */ require("cross-fetch");
|
||||
|
||||
// Updating the restrictions of an existing scoped signer
|
||||
|
||||
await smartWallet.grantAccess(signer7Wallet.address, {
|
||||
await account.grantAccess(signer7Wallet.address, {
|
||||
approvedCallTargets: [adminWallet.address],
|
||||
});
|
||||
|
||||
@@ -704,7 +686,7 @@ global.fetch = /* @__PURE__ */ require("cross-fetch");
|
||||
signersWithRestrictions.push(restrictionsSigner7);
|
||||
|
||||
// Existing admin -> new scoped signer (demote)
|
||||
await smartWallet.grantAdminAccess(signer8Wallet.address);
|
||||
await account.grantAdminAccess(signer8Wallet.address);
|
||||
|
||||
const restrictionsSigner8: SignerWithRestrictionsInput = {
|
||||
signer: signer8Wallet.address,
|
||||
@@ -714,7 +696,7 @@ global.fetch = /* @__PURE__ */ require("cross-fetch");
|
||||
signersWithRestrictions.push(restrictionsSigner8);
|
||||
|
||||
// Existing scoped signer -> new admin (promote)
|
||||
await smartWallet.grantAccess(signer9Wallet.address, {
|
||||
await account.grantAccess(signer9Wallet.address, {
|
||||
approvedCallTargets: [adminWallet.address],
|
||||
});
|
||||
|
||||
@@ -726,11 +708,11 @@ global.fetch = /* @__PURE__ */ require("cross-fetch");
|
||||
signersWithRestrictions.push(restrictionsSigner9);
|
||||
|
||||
// Set access in batch
|
||||
await smartWallet.setAccess(signersWithRestrictions);
|
||||
await account.setAccess(signersWithRestrictions);
|
||||
|
||||
// Now checking if permissions are set correctly
|
||||
const signersWithRestrictionsAfter =
|
||||
await smartWallet.getSignersWithRestrictions();
|
||||
await account.getSignersWithRestrictions();
|
||||
|
||||
for (const restrictions of signersWithRestrictionsAfter) {
|
||||
switch (restrictions.signer) {
|
||||
@@ -738,96 +720,96 @@ global.fetch = /* @__PURE__ */ require("cross-fetch");
|
||||
case adminWallet.address:
|
||||
assert.isTrue(
|
||||
restrictions.isAdmin,
|
||||
"Admin wallet should be an admin.",
|
||||
"Admin account should be an admin.",
|
||||
);
|
||||
break;
|
||||
// `signer3Wallet` should be an admin
|
||||
case signer3Wallet.address:
|
||||
assert.isTrue(
|
||||
restrictions.isAdmin,
|
||||
"Signer3 wallet should be an admin.",
|
||||
"Signer3 account should be an admin.",
|
||||
);
|
||||
break;
|
||||
// `signer4Wallet` should not be admin or scoped signer
|
||||
case signer4Wallet.address:
|
||||
assert.isFalse(
|
||||
restrictions.isAdmin,
|
||||
"Signer4 wallet should not be an admin.",
|
||||
"Signer4 account should not be an admin.",
|
||||
);
|
||||
assert.strictEqual(
|
||||
restrictions.restrictions.approvedCallTargets.length,
|
||||
0,
|
||||
"Signer4 wallet should not have any approved call targets.",
|
||||
"Signer4 account should not have any approved call targets.",
|
||||
);
|
||||
break;
|
||||
// `signer5Wallet` should be a scoped signer
|
||||
case signer5Wallet.address:
|
||||
assert.isFalse(
|
||||
restrictions.isAdmin,
|
||||
"Signer5 wallet should not be an admin.",
|
||||
"Signer5 account should not be an admin.",
|
||||
);
|
||||
assert.strictEqual(
|
||||
restrictions.restrictions.approvedCallTargets.length,
|
||||
1,
|
||||
"Signer5 wallet should have one approved call target.",
|
||||
"Signer5 account should have one approved call target.",
|
||||
);
|
||||
assert.strictEqual(
|
||||
restrictions.restrictions.approvedCallTargets[0],
|
||||
adminWallet.address,
|
||||
"Signer5 wallet should have the expected approved call targets.",
|
||||
"Signer5 account should have the expected approved call targets.",
|
||||
);
|
||||
break;
|
||||
// `signer6Wallet` should not be admin or scoped signer
|
||||
case signer6Wallet.address:
|
||||
assert.isFalse(
|
||||
restrictions.isAdmin,
|
||||
"Signer6 wallet should not be an admin.",
|
||||
"Signer6 account should not be an admin.",
|
||||
);
|
||||
assert.strictEqual(
|
||||
restrictions.restrictions.approvedCallTargets.length,
|
||||
0,
|
||||
"Signer6 wallet should not have any approved call targets.",
|
||||
"Signer6 account should not have any approved call targets.",
|
||||
);
|
||||
break;
|
||||
// `signer7Wallet` should be a scoped signer with its updated restrictions
|
||||
case signer7Wallet.address:
|
||||
assert.isFalse(
|
||||
restrictions.isAdmin,
|
||||
"Signer7 wallet should not be an admin.",
|
||||
"Signer7 account should not be an admin.",
|
||||
);
|
||||
assert.strictEqual(
|
||||
restrictions.restrictions.approvedCallTargets.length,
|
||||
1,
|
||||
"Signer7 wallet should have one approved call target.",
|
||||
"Signer7 account should have one approved call target.",
|
||||
);
|
||||
assert.strictEqual(
|
||||
restrictions.restrictions.approvedCallTargets[0],
|
||||
signer1Wallet.address,
|
||||
"Signer7 wallet should have the expected approved call targets.",
|
||||
"Signer7 account should have the expected approved call targets.",
|
||||
);
|
||||
break;
|
||||
// `signer8Wallet` should be a scoped signer
|
||||
case signer8Wallet.address:
|
||||
assert.isFalse(
|
||||
restrictions.isAdmin,
|
||||
"Signer8 wallet should not be an admin.",
|
||||
"Signer8 account should not be an admin.",
|
||||
);
|
||||
assert.strictEqual(
|
||||
restrictions.restrictions.approvedCallTargets.length,
|
||||
1,
|
||||
"Signer8 wallet should have one approved call target.",
|
||||
"Signer8 account should have one approved call target.",
|
||||
);
|
||||
assert.strictEqual(
|
||||
restrictions.restrictions.approvedCallTargets[0],
|
||||
adminWallet.address,
|
||||
"Signer8 wallet should have the expected approved call targets.",
|
||||
"Signer8 account should have the expected approved call targets.",
|
||||
);
|
||||
break;
|
||||
// `signer9Wallet` should be an admin
|
||||
case signer9Wallet.address:
|
||||
assert.isTrue(
|
||||
restrictions.isAdmin,
|
||||
"Signer9 wallet should be an admin.",
|
||||
"Signer9 account should be an admin.",
|
||||
);
|
||||
break;
|
||||
default:
|
||||
@@ -82,6 +82,7 @@ let signers: SignerWithAddress[];
|
||||
let storage: ThirdwebStorage;
|
||||
let implementations: { [key in ContractType]?: string };
|
||||
let mock_weth_address: string;
|
||||
let thirdwebFactory: TWFactory;
|
||||
|
||||
const fastForwardTime = async (timeInSeconds: number): Promise<void> => {
|
||||
const now = Math.floor(Date.now() / 1000);
|
||||
@@ -133,6 +134,7 @@ export const mochaHooks = {
|
||||
.connect(signer)
|
||||
.deploy(trustedForwarderAddress, registry.address)) as TWFactory;
|
||||
|
||||
thirdwebFactory = await thirdwebFactoryDeployer.deployed();
|
||||
const deployTxFactory = thirdwebFactoryDeployer.deployTransaction;
|
||||
await deployTxFactory.wait();
|
||||
const thirdwebRegistryAddress = await thirdwebFactoryDeployer.registry();
|
||||
@@ -391,4 +393,5 @@ export {
|
||||
storage,
|
||||
implementations,
|
||||
hardhatEthers,
|
||||
thirdwebFactory,
|
||||
};
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import { ThirdwebSDK } from "../../src/evm";
|
||||
import { expectError, sdk } from "./before-setup";
|
||||
import { expect } from "chai";
|
||||
import { ethers } from "ethers";
|
||||
import { Wallet } from "ethers";
|
||||
|
||||
describe("Error Handling", async () => {
|
||||
it("should throw proper error on account with no balance", async () => {
|
||||
const newSdk = ThirdwebSDK.fromSigner(
|
||||
ethers.Wallet.createRandom().connect(sdk.getProvider()),
|
||||
Wallet.createRandom().connect(sdk.getProvider()),
|
||||
);
|
||||
|
||||
try {
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,85 @@
|
||||
// from SplitWallet published at: ipfs://Qmc5cQotuEnCo71ZztJk69wc8kuKbGmuCARL2FyAojoi9r/
|
||||
|
||||
const abi = [
|
||||
{
|
||||
inputs: [],
|
||||
stateMutability: "nonpayable",
|
||||
type: "constructor",
|
||||
},
|
||||
{
|
||||
inputs: [],
|
||||
name: "Unauthorized",
|
||||
type: "error",
|
||||
},
|
||||
{
|
||||
anonymous: false,
|
||||
inputs: [
|
||||
{
|
||||
indexed: true,
|
||||
internalType: "address",
|
||||
name: "split",
|
||||
type: "address",
|
||||
},
|
||||
{
|
||||
indexed: false,
|
||||
internalType: "uint256",
|
||||
name: "amount",
|
||||
type: "uint256",
|
||||
},
|
||||
],
|
||||
name: "ReceiveETH",
|
||||
type: "event",
|
||||
},
|
||||
{
|
||||
inputs: [
|
||||
{
|
||||
internalType: "contract ERC20",
|
||||
name: "token",
|
||||
type: "address",
|
||||
},
|
||||
{
|
||||
internalType: "uint256",
|
||||
name: "amount",
|
||||
type: "uint256",
|
||||
},
|
||||
],
|
||||
name: "sendERC20ToMain",
|
||||
outputs: [],
|
||||
stateMutability: "payable",
|
||||
type: "function",
|
||||
},
|
||||
{
|
||||
inputs: [
|
||||
{
|
||||
internalType: "uint256",
|
||||
name: "amount",
|
||||
type: "uint256",
|
||||
},
|
||||
],
|
||||
name: "sendETHToMain",
|
||||
outputs: [],
|
||||
stateMutability: "payable",
|
||||
type: "function",
|
||||
},
|
||||
{
|
||||
inputs: [],
|
||||
name: "splitMain",
|
||||
outputs: [
|
||||
{
|
||||
internalType: "contract ISplitMain",
|
||||
name: "",
|
||||
type: "address",
|
||||
},
|
||||
],
|
||||
stateMutability: "view",
|
||||
type: "function",
|
||||
},
|
||||
];
|
||||
|
||||
const bytecode =
|
||||
"0x60a060405234801561001057600080fd5b5033606081901b60805261035461004c60003960008181604b0152818160bc015281816101080152818161013c015261018601526103546000f3fe6080604052600436106100345760003560e01c80630e769b2b146100395780637c1f3ffe14610089578063ab0ebff41461009e575b600080fd5b34801561004557600080fd5b5061006d7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b03909116815260200160405180910390f35b61009c6100973660046102d0565b6100b1565b005b61009c6100ac366004610306565b610131565b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146100f9576040516282b42960e81b815260040160405180910390fd5b61012d6001600160a01b0383167f0000000000000000000000000000000000000000000000000000000000000000836101af565b5050565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610179576040516282b42960e81b815260040160405180910390fd5b6101ac6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001682610233565b50565b600060405163a9059cbb60e01b81526001600160a01b03841660048201528260248201526000806044836000895af19150506101ea81610289565b61022d5760405162461bcd60e51b815260206004820152600f60248201526e1514905394d1915497d19052531151608a1b60448201526064015b60405180910390fd5b50505050565b600080600080600085875af19050806102845760405162461bcd60e51b815260206004820152601360248201527211551217d514905394d1915497d19052531151606a1b6044820152606401610224565b505050565b60003d8261029b57806000803e806000fd5b80602081146102b35780156102c457600092506102c9565b816000803e600051151592506102c9565b600192505b5050919050565b600080604083850312156102e2578182fd5b82356001600160a01b03811681146102f8578283fd5b946020939093013593505050565b600060208284031215610317578081fd5b503591905056fea26469706673582212208e095a368bcb2efb2a8afd9b560ad94441e926086a4bc92edf16c33900df798e64736f6c63430008040033";
|
||||
|
||||
const deployedBytecode =
|
||||
"0x6080604052600436106100345760003560e01c80630e769b2b146100395780637c1f3ffe14610089578063ab0ebff41461009e575b600080fd5b34801561004557600080fd5b5061006d7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b03909116815260200160405180910390f35b61009c6100973660046102d0565b6100b1565b005b61009c6100ac366004610306565b610131565b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146100f9576040516282b42960e81b815260040160405180910390fd5b61012d6001600160a01b0383167f0000000000000000000000000000000000000000000000000000000000000000836101af565b5050565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610179576040516282b42960e81b815260040160405180910390fd5b6101ac6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001682610233565b50565b600060405163a9059cbb60e01b81526001600160a01b03841660048201528260248201526000806044836000895af19150506101ea81610289565b61022d5760405162461bcd60e51b815260206004820152600f60248201526e1514905394d1915497d19052531151608a1b60448201526064015b60405180910390fd5b50505050565b600080600080600085875af19050806102845760405162461bcd60e51b815260206004820152601360248201527211551217d514905394d1915497d19052531151606a1b6044820152606401610224565b505050565b60003d8261029b57806000803e806000fd5b80602081146102b35780156102c457600092506102c9565b816000803e600051151592506102c9565b600192505b5050919050565b600080604083850312156102e2578182fd5b82356001600160a01b03811681146102f8578283fd5b946020939093013593505050565b600060208284031215610317578081fd5b503591905056fea26469706673582212208e095a368bcb2efb2a8afd9b560ad94441e926086a4bc92edf16c33900df798e64736f6c63430008040033";
|
||||
|
||||
export { abi, bytecode, deployedBytecode };
|
||||
File diff suppressed because one or more lines are too long
@@ -20,5 +20,13 @@ export async function mockUploadWithCID(
|
||||
file: FileOrBufferOrString,
|
||||
options?: IpfsUploadBatchOptions | undefined,
|
||||
) {
|
||||
storage[cid] = file;
|
||||
const [cidMain, id] = cid.split("/");
|
||||
|
||||
if (id) {
|
||||
storage[cidMain] = {
|
||||
[id]: file,
|
||||
};
|
||||
} else {
|
||||
storage[cid] = file;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,360 @@
|
||||
import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers";
|
||||
import { jsonProvider, sdk, signers, thirdwebFactory } from "./before-setup";
|
||||
import { expect, assert } from "chai";
|
||||
import {
|
||||
Forwarder__factory,
|
||||
DropERC721__factory,
|
||||
ERC721Base__factory,
|
||||
} from "@thirdweb-dev/contracts-js";
|
||||
import {
|
||||
bytecode as SplitMainBytecode,
|
||||
deployedBytecode as SplitMainDeployedBytecode,
|
||||
abi as SplitMainAbi,
|
||||
} from "./metadata/SplitMain";
|
||||
import {
|
||||
bytecode as SplitWalletBytecode,
|
||||
deployedBytecode as SplitWalletDeployedBytecode,
|
||||
abi as SplitWalletAbi,
|
||||
} from "./metadata/SplitWallet";
|
||||
import {
|
||||
bytecode as TWCloneFactoryBytecode,
|
||||
abi as TWCloneFactoryAbi,
|
||||
} from "./metadata/TWCloneFactory";
|
||||
import { mockUploadMetadataWithBytecode } from "./utils";
|
||||
|
||||
const extendedMetadataMock = {
|
||||
name: "",
|
||||
metadataUri: "",
|
||||
bytecodeUri: "",
|
||||
analytics: {},
|
||||
version: "1.0.0",
|
||||
displayName: "",
|
||||
description: "",
|
||||
changelog: "",
|
||||
isDeployableViaFactory: false,
|
||||
isDeployableViaProxy: false,
|
||||
factoryDeploymentData: {
|
||||
implementationAddresses: {},
|
||||
implementationInitializerFunction: "initialize",
|
||||
factoryAddresses: {},
|
||||
},
|
||||
constructorParams: {},
|
||||
publisher: "",
|
||||
customFactoryInput: {
|
||||
factoryFunction: "",
|
||||
customFactoryAddresses: [],
|
||||
},
|
||||
};
|
||||
|
||||
describe("New Publish Flow", async () => {
|
||||
let adminWallet: SignerWithAddress,
|
||||
samWallet: SignerWithAddress,
|
||||
bobWallet: SignerWithAddress,
|
||||
w4: SignerWithAddress;
|
||||
|
||||
beforeEach(async () => {
|
||||
await jsonProvider.send("hardhat_reset", []);
|
||||
[adminWallet, samWallet, bobWallet, , , , , w4] = signers;
|
||||
});
|
||||
before("Mock upload infra contracts", async () => {
|
||||
// mock upload Forwarder
|
||||
await mockUploadMetadataWithBytecode(
|
||||
"Forwarder",
|
||||
Forwarder__factory.abi,
|
||||
Forwarder__factory.bytecode,
|
||||
"",
|
||||
{
|
||||
...extendedMetadataMock,
|
||||
deployType: "standard",
|
||||
networksForDeployment: {
|
||||
allNetworks: true,
|
||||
networksEnabled: [],
|
||||
},
|
||||
},
|
||||
"ipfs://Qmcu8FaqerUvQYb4qPg7PwkXa6dRtEe45LedLJPN42Jwqe/0",
|
||||
// ^ we use actual publish uri as mock uri here, because this contract's uri is fetched from publisher by contractName
|
||||
);
|
||||
|
||||
// mock upload TWCloneFactory
|
||||
await mockUploadMetadataWithBytecode(
|
||||
"Forwarder",
|
||||
TWCloneFactoryAbi,
|
||||
TWCloneFactoryBytecode,
|
||||
"",
|
||||
{
|
||||
...extendedMetadataMock,
|
||||
deployType: "standard",
|
||||
networksForDeployment: {
|
||||
allNetworks: true,
|
||||
networksEnabled: [],
|
||||
},
|
||||
},
|
||||
"ipfs://QmYfw13Zykqf9jAmJobNgYrEpatEF9waWcQPUHvJ7sctRb/0",
|
||||
// ^ we use actual publish uri as mock uri here, because this contract's uri is fetched from publisher by contractName
|
||||
);
|
||||
});
|
||||
|
||||
describe("Deploy newly published contract", async () => {
|
||||
it("should deploy regular contract", async () => {
|
||||
// mock publish as a standard-deploy contract
|
||||
const mockPublishUri = await mockUploadMetadataWithBytecode(
|
||||
"ERC721Base",
|
||||
ERC721Base__factory.abi,
|
||||
ERC721Base__factory.bytecode,
|
||||
"",
|
||||
{
|
||||
...extendedMetadataMock,
|
||||
deployType: "standard",
|
||||
networksForDeployment: {
|
||||
allNetworks: true,
|
||||
networksEnabled: [],
|
||||
},
|
||||
publisher: await adminWallet.getAddress(),
|
||||
},
|
||||
);
|
||||
|
||||
// deploy with mock uri
|
||||
const admin = await adminWallet.getAddress();
|
||||
const contractAddress = await sdk.deployer.deployContractFromUri(
|
||||
mockPublishUri,
|
||||
["Direct Deploy ERC721Base", "DDE", admin, 5],
|
||||
);
|
||||
const contract = await sdk.getContract(contractAddress);
|
||||
|
||||
const name = await contract.call("name");
|
||||
const owner = await contract.call("owner");
|
||||
|
||||
expect(name).to.equal("Direct Deploy ERC721Base");
|
||||
expect(owner).to.equal(admin);
|
||||
});
|
||||
|
||||
it("should deploy with custom factory", async () => {
|
||||
// mock publish SplitMain as a standard-deploy contract
|
||||
const splitMainMockUri = await mockUploadMetadataWithBytecode(
|
||||
"SplitMain",
|
||||
SplitMainAbi,
|
||||
SplitMainBytecode,
|
||||
SplitMainDeployedBytecode,
|
||||
{
|
||||
...extendedMetadataMock,
|
||||
deployType: "standard",
|
||||
networksForDeployment: {
|
||||
allNetworks: true,
|
||||
networksEnabled: [],
|
||||
},
|
||||
publisher: await adminWallet.getAddress(),
|
||||
},
|
||||
);
|
||||
|
||||
// deploy custom-factory `SplitMain`, with mock uri
|
||||
const splitMainAddress = await sdk.deployer.deployContractFromUri(
|
||||
splitMainMockUri,
|
||||
[],
|
||||
);
|
||||
|
||||
// mock publish SplitWallet as a custom-factory-deploy contract
|
||||
const splitWalletMockUri = await mockUploadMetadataWithBytecode(
|
||||
"SplitWallet",
|
||||
SplitWalletAbi,
|
||||
SplitWalletBytecode,
|
||||
SplitWalletDeployedBytecode,
|
||||
{
|
||||
...extendedMetadataMock,
|
||||
deployType: "customFactory",
|
||||
factoryDeploymentData: {
|
||||
...extendedMetadataMock.factoryDeploymentData,
|
||||
customFactoryInput: {
|
||||
factoryFunction: "createSplit",
|
||||
params: [],
|
||||
customFactoryAddresses: {
|
||||
"31337": splitMainAddress,
|
||||
},
|
||||
},
|
||||
},
|
||||
networksForDeployment: {
|
||||
allNetworks: true,
|
||||
networksEnabled: [],
|
||||
},
|
||||
publisher: await adminWallet.getAddress(),
|
||||
},
|
||||
);
|
||||
|
||||
// deploy contract via custom-factory, with mock uri
|
||||
const splitWalletAddress = await sdk.deployer.deployContractFromUri(
|
||||
splitWalletMockUri,
|
||||
[
|
||||
[await bobWallet.getAddress(), await adminWallet.getAddress()],
|
||||
[500000, 500000],
|
||||
0,
|
||||
await adminWallet.getAddress(),
|
||||
],
|
||||
);
|
||||
|
||||
const splitContract = await sdk.getContract(splitWalletAddress);
|
||||
const deployingAddress = await splitContract.call("splitMain");
|
||||
|
||||
expect(deployingAddress).to.equal(splitMainAddress);
|
||||
});
|
||||
});
|
||||
|
||||
describe("Deploy re-published contract", async () => {
|
||||
it("should deploy with auto factory", async () => {
|
||||
const mockPublisher = process.env.contractPublisherAddress;
|
||||
process.env.contractPublisherAddress =
|
||||
"0x664244560eBa21Bf82d7150C791bE1AbcD5B4cd7";
|
||||
const adminAddress = await adminWallet.getAddress();
|
||||
|
||||
// mock publish as a autoFactory-deploy contract
|
||||
const mockPublishUri = await mockUploadMetadataWithBytecode(
|
||||
"DropERC721",
|
||||
DropERC721__factory.abi,
|
||||
DropERC721__factory.bytecode,
|
||||
"",
|
||||
{
|
||||
...extendedMetadataMock,
|
||||
deployType: "autoFactory",
|
||||
networksForDeployment: {
|
||||
allNetworks: true,
|
||||
networksEnabled: [],
|
||||
},
|
||||
publisher: adminAddress,
|
||||
},
|
||||
);
|
||||
|
||||
// deploy via autoFactory, with mock uri
|
||||
const contractAddress = await sdk.deployer.deployContractFromUri(
|
||||
mockPublishUri,
|
||||
[
|
||||
adminAddress,
|
||||
"DropERC721 Minimal Proxy",
|
||||
"DME",
|
||||
"",
|
||||
[],
|
||||
adminAddress,
|
||||
adminAddress,
|
||||
5,
|
||||
5,
|
||||
adminAddress,
|
||||
],
|
||||
);
|
||||
const contract = await sdk.getContract(contractAddress);
|
||||
|
||||
const name = await contract.call("name");
|
||||
const owner = await contract.call("owner");
|
||||
const code = await sdk.getProvider().getCode(contractAddress);
|
||||
|
||||
expect(name).to.equal("DropERC721 Minimal Proxy");
|
||||
expect(owner).to.equal(adminAddress);
|
||||
assert(code.startsWith("0x363d3d373d3d3d363d73"));
|
||||
|
||||
process.env.contractPublisherAddress = mockPublisher;
|
||||
});
|
||||
});
|
||||
|
||||
describe("Deploy old contract without re-publishing", async () => {
|
||||
it("should deploy regular contract", async () => {
|
||||
// mock publish as old style -- omit deployType, networksForDeployment etc
|
||||
const mockPublishUri = await mockUploadMetadataWithBytecode(
|
||||
"ERC721Base",
|
||||
ERC721Base__factory.abi,
|
||||
ERC721Base__factory.bytecode,
|
||||
"",
|
||||
extendedMetadataMock,
|
||||
);
|
||||
|
||||
// deploy with mock uri
|
||||
const admin = await adminWallet.getAddress();
|
||||
const contractAddress = await sdk.deployer.deployContractFromUri(
|
||||
mockPublishUri,
|
||||
["Direct Deploy ERC721Base", "DDE", admin, 5],
|
||||
);
|
||||
const contract = await sdk.getContract(contractAddress);
|
||||
|
||||
const name = await contract.call("name");
|
||||
const owner = await contract.call("owner");
|
||||
|
||||
expect(name).to.equal("Direct Deploy ERC721Base");
|
||||
expect(owner).to.equal(admin);
|
||||
});
|
||||
|
||||
it("should deploy via old factory", async () => {
|
||||
const mockPublisher = process.env.contractPublisherAddress;
|
||||
process.env.contractPublisherAddress =
|
||||
"0x664244560eBa21Bf82d7150C791bE1AbcD5B4cd7";
|
||||
const adminAddress = await adminWallet.getAddress();
|
||||
|
||||
// mock publish as old-style factory deployable -- omit deployType, networksForDeployment etc
|
||||
const mockPublishUri = await mockUploadMetadataWithBytecode(
|
||||
"DropERC721",
|
||||
DropERC721__factory.abi,
|
||||
DropERC721__factory.bytecode,
|
||||
"",
|
||||
{
|
||||
...extendedMetadataMock,
|
||||
isDeployableViaFactory: true,
|
||||
publisher: adminAddress,
|
||||
},
|
||||
);
|
||||
|
||||
// deploy implementation
|
||||
const implementationAddress = await sdk.deployer.deployContractFromUri(
|
||||
mockPublishUri,
|
||||
[],
|
||||
{
|
||||
forceDirectDeploy: true,
|
||||
},
|
||||
);
|
||||
await (
|
||||
await thirdwebFactory.addImplementation(implementationAddress)
|
||||
).wait();
|
||||
|
||||
// re-upload, with implementation address
|
||||
const mockPublishUriUpdated = await mockUploadMetadataWithBytecode(
|
||||
"DropERC721",
|
||||
DropERC721__factory.abi,
|
||||
DropERC721__factory.bytecode,
|
||||
"",
|
||||
{
|
||||
...extendedMetadataMock,
|
||||
isDeployableViaFactory: true,
|
||||
factoryDeploymentData: {
|
||||
...extendedMetadataMock?.factoryDeploymentData,
|
||||
implementationAddresses: {
|
||||
"31337": implementationAddress,
|
||||
},
|
||||
factoryAddresses: {
|
||||
"31337": process.env.factoryAddress,
|
||||
},
|
||||
},
|
||||
publisher: adminAddress,
|
||||
},
|
||||
);
|
||||
|
||||
// Deploy proxy DropERC721
|
||||
const contractAddress = await sdk.deployer.deployContractFromUri(
|
||||
mockPublishUriUpdated,
|
||||
[
|
||||
adminAddress,
|
||||
"Drop Proxy Old",
|
||||
"DPA",
|
||||
"",
|
||||
[],
|
||||
adminAddress,
|
||||
adminAddress,
|
||||
5,
|
||||
5,
|
||||
adminAddress,
|
||||
],
|
||||
);
|
||||
|
||||
const drop = await sdk.getContract(contractAddress);
|
||||
const bytecode = await sdk.getProvider().getCode(contractAddress);
|
||||
const name = await drop.call("name");
|
||||
|
||||
expect(name).to.equal("Drop Proxy Old");
|
||||
assert(bytecode.startsWith("0x363d3d373d3d3d363d73"));
|
||||
});
|
||||
});
|
||||
|
||||
// TODO: test any-evm vs standard chain deploys with same publish-uri
|
||||
});
|
||||
@@ -1,4 +1,8 @@
|
||||
import { resolveContractUriFromAddress } from "../../src/evm";
|
||||
import {
|
||||
FullPublishMetadata,
|
||||
extractIPFSHashFromBytecode,
|
||||
resolveContractUriFromAddress,
|
||||
} from "../../src/evm";
|
||||
import { defaultProvider } from "./before-setup";
|
||||
import { mockUploadWithCID } from "./mock/MockStorage";
|
||||
import { ContractInterface, ethers } from "ethers";
|
||||
@@ -22,6 +26,8 @@ export const mockUploadContractMetadata = async (
|
||||
contractName: string,
|
||||
address: string,
|
||||
abi: any,
|
||||
extendedMetadata?: FullPublishMetadata | any,
|
||||
publishUri?: string,
|
||||
) => {
|
||||
const ipfsHash = (await resolveContractUriFromAddress(
|
||||
address,
|
||||
@@ -57,11 +63,68 @@ export const mockUploadContractMetadata = async (
|
||||
|
||||
// mock raw-metadata
|
||||
const rawMeta = {
|
||||
...extendedMetadata,
|
||||
name: contractName,
|
||||
metadataUri: ipfsHash,
|
||||
bytecodeUri: bytecodeUri,
|
||||
};
|
||||
const rawMetaUri = ipfsHash.concat("rawMeta");
|
||||
const rawMetaUri = publishUri || ipfsHash.concat("rawMeta");
|
||||
const rawMetaCID = rawMetaUri.replace("ipfs://", "");
|
||||
await mockUploadWithCID(rawMetaCID, JSON.stringify(rawMeta));
|
||||
|
||||
return rawMetaUri;
|
||||
};
|
||||
|
||||
export const mockUploadMetadataWithBytecode = async (
|
||||
contractName: string,
|
||||
abi: any,
|
||||
bytecode: string,
|
||||
deployedBytecode?: string,
|
||||
extendedMetadata?: FullPublishMetadata | any,
|
||||
publishUri?: string,
|
||||
): Promise<string> => {
|
||||
const ipfsHash =
|
||||
deployedBytecode && deployedBytecode.length > 0
|
||||
? (extractIPFSHashFromBytecode(deployedBytecode) as string)
|
||||
: (extractIPFSHashFromBytecode(bytecode) as string);
|
||||
|
||||
const metadata = {
|
||||
compiler: {},
|
||||
output: {
|
||||
abi,
|
||||
devdoc: {},
|
||||
userdoc: {},
|
||||
},
|
||||
settings: {
|
||||
compilationTarget: {
|
||||
contract: contractName,
|
||||
},
|
||||
evmVersion: {},
|
||||
metadata: {},
|
||||
optimizer: {},
|
||||
remappings: [],
|
||||
},
|
||||
sources: {},
|
||||
version: 1,
|
||||
};
|
||||
const metadataCID = ipfsHash.replace("ipfs://", "");
|
||||
await mockUploadWithCID(metadataCID, JSON.stringify(metadata));
|
||||
|
||||
// mock bytecode
|
||||
const bytecodeUri = ipfsHash.concat("bytecode");
|
||||
const bytecodeCID = bytecodeUri.replace("ipfs://", "");
|
||||
await mockUploadWithCID(bytecodeCID, bytecode);
|
||||
|
||||
// mock raw-metadata
|
||||
const rawMeta = {
|
||||
...extendedMetadata,
|
||||
name: contractName,
|
||||
metadataUri: ipfsHash,
|
||||
bytecodeUri: bytecodeUri,
|
||||
};
|
||||
const rawMetaUri = publishUri || ipfsHash.concat("rawMeta");
|
||||
const rawMetaCID = rawMetaUri.replace("ipfs://", "");
|
||||
await mockUploadWithCID(rawMetaCID, JSON.stringify(rawMeta));
|
||||
|
||||
return rawMetaUri;
|
||||
};
|
||||
|
||||
@@ -1,5 +1,31 @@
|
||||
# @thirdweb-dev/unity-js-bridge
|
||||
|
||||
## 0.2.44
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`2b113539`](https://github.com/thirdweb-dev/js/commit/2b113539098384f910b3c4d54e1fde9d35a6f053), [`c9535715`](https://github.com/thirdweb-dev/js/commit/c95357158819abd42d4b0900ecc2fa40fcb957f8), [`be606dd3`](https://github.com/thirdweb-dev/js/commit/be606dd3c93c1514834c1d970e864d7f949a07ab), [`5882091e`](https://github.com/thirdweb-dev/js/commit/5882091eab65978009a5a5305701f121851b10ad), [`998e5217`](https://github.com/thirdweb-dev/js/commit/998e521733efd6a67e42f9bf0beab5fbdccf08ae)]:
|
||||
- @thirdweb-dev/wallets@1.0.3
|
||||
- @thirdweb-dev/sdk@3.10.27
|
||||
- @thirdweb-dev/chains@0.1.26
|
||||
- @thirdweb-dev/auth@3.2.7
|
||||
|
||||
## 0.2.43
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`ed711c8c`](https://github.com/thirdweb-dev/js/commit/ed711c8cb2ed6a0deb1b2a5eeec06df1d4edc5e8), [`05a7495a`](https://github.com/thirdweb-dev/js/commit/05a7495a132aabab5f48abbdb80a468ff6f65df8), [`e78da6b3`](https://github.com/thirdweb-dev/js/commit/e78da6b36cfa6d954234820563201bf760186ed1)]:
|
||||
- @thirdweb-dev/wallets@1.0.2
|
||||
- @thirdweb-dev/auth@3.2.6
|
||||
|
||||
## 0.2.42
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`efb3546e`](https://github.com/thirdweb-dev/js/commit/efb3546ec8268156be00301af28b9d83ecd5ab08)]:
|
||||
- @thirdweb-dev/wallets@1.0.1
|
||||
- @thirdweb-dev/auth@3.2.5
|
||||
|
||||
## 0.2.41
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@thirdweb-dev/unity-js-bridge",
|
||||
"version": "0.2.41",
|
||||
"version": "0.2.44",
|
||||
"main": "dist/thirdweb-unity-bridge.js",
|
||||
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/unity-js-bridge",
|
||||
"license": "Apache-2.0",
|
||||
|
||||
@@ -1,5 +1,37 @@
|
||||
# @thirdweb-dev/wallets
|
||||
|
||||
## 1.0.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#1277](https://github.com/thirdweb-dev/js/pull/1277) [`2b113539`](https://github.com/thirdweb-dev/js/commit/2b113539098384f910b3c4d54e1fde9d35a6f053) Thanks [@joaquim-verges](https://github.com/joaquim-verges)! - remove ethers/lib/utils dependency
|
||||
|
||||
- [#1267](https://github.com/thirdweb-dev/js/pull/1267) [`be606dd3`](https://github.com/thirdweb-dev/js/commit/be606dd3c93c1514834c1d970e864d7f949a07ab) Thanks [@0xFirekeeper](https://github.com/0xFirekeeper)! - set signer null when disconnecting paper to avoid exceptions on event callbacks
|
||||
|
||||
- [#1269](https://github.com/thirdweb-dev/js/pull/1269) [`998e5217`](https://github.com/thirdweb-dev/js/commit/998e521733efd6a67e42f9bf0beab5fbdccf08ae) Thanks [@MananTank](https://github.com/MananTank)! - - Expose `advancedOptions` and `styles` for paper wallet
|
||||
- Allow using "+" in paper email
|
||||
- Allow using "+" in magic email
|
||||
- Update Paper SDK version
|
||||
- Updated dependencies [[`2b113539`](https://github.com/thirdweb-dev/js/commit/2b113539098384f910b3c4d54e1fde9d35a6f053), [`c9535715`](https://github.com/thirdweb-dev/js/commit/c95357158819abd42d4b0900ecc2fa40fcb957f8), [`5882091e`](https://github.com/thirdweb-dev/js/commit/5882091eab65978009a5a5305701f121851b10ad)]:
|
||||
- @thirdweb-dev/sdk@3.10.27
|
||||
- @thirdweb-dev/chains@0.1.26
|
||||
|
||||
## 1.0.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#1263](https://github.com/thirdweb-dev/js/pull/1263) [`ed711c8c`](https://github.com/thirdweb-dev/js/commit/ed711c8cb2ed6a0deb1b2a5eeec06df1d4edc5e8) Thanks [@iketw](https://github.com/iketw)! - Pass a min set of chains if user passes more than 50 chains. We'll rely on "adding chains" for new chains
|
||||
|
||||
- [#1255](https://github.com/thirdweb-dev/js/pull/1255) [`05a7495a`](https://github.com/thirdweb-dev/js/commit/05a7495a132aabab5f48abbdb80a468ff6f65df8) Thanks [@joaquim-verges](https://github.com/joaquim-verges)! - Handle passing RPC urls as chain in SmartWallet config
|
||||
|
||||
- [#1265](https://github.com/thirdweb-dev/js/pull/1265) [`e78da6b3`](https://github.com/thirdweb-dev/js/commit/e78da6b36cfa6d954234820563201bf760186ed1) Thanks [@MananTank](https://github.com/MananTank)! - Wallet Connect v2 Corrections
|
||||
|
||||
## 1.0.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#1259](https://github.com/thirdweb-dev/js/pull/1259) [`efb3546e`](https://github.com/thirdweb-dev/js/commit/efb3546ec8268156be00301af28b9d83ecd5ab08) Thanks [@iketw](https://github.com/iketw)! - Fix. Respecting passed wallets if less then 50, otherwhise use defaults chains.
|
||||
|
||||
## 1.0.0
|
||||
|
||||
### Major Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@thirdweb-dev/wallets",
|
||||
"version": "1.0.0",
|
||||
"version": "1.0.3",
|
||||
"main": "dist/thirdweb-dev-wallets.cjs.js",
|
||||
"module": "dist/thirdweb-dev-wallets.esm.js",
|
||||
"types": "dist/thirdweb-dev-wallets.cjs.d.ts",
|
||||
@@ -325,7 +325,7 @@
|
||||
"@magic-ext/connect": "^6.7.0",
|
||||
"@magic-ext/oauth": "^7.6.2",
|
||||
"@magic-sdk/provider": "^13.6.2",
|
||||
"@paperxyz/embedded-wallet-service-sdk": "^1.0.0",
|
||||
"@paperxyz/embedded-wallet-service-sdk": "^1.1.0",
|
||||
"@safe-global/safe-core-sdk": "^3.3.2",
|
||||
"@safe-global/safe-ethers-adapters": "^0.1.0-alpha.16",
|
||||
"@safe-global/safe-ethers-lib": "^1.9.2",
|
||||
|
||||
@@ -13,8 +13,7 @@ import type {
|
||||
} from "@coinbase/wallet-sdk";
|
||||
import type { CoinbaseWalletSDKOptions } from "@coinbase/wallet-sdk/dist/CoinbaseWalletSDK";
|
||||
import type { Chain } from "@thirdweb-dev/chains";
|
||||
import { providers } from "ethers";
|
||||
import { getAddress, hexValue } from "ethers/lib/utils.js";
|
||||
import { providers, utils } from "ethers";
|
||||
import { walletIds } from "../../constants/walletIds";
|
||||
|
||||
type Options = CoinbaseWalletSDKOptions & {
|
||||
@@ -61,7 +60,7 @@ export class CoinbaseWalletConnector extends WagmiConnector<
|
||||
this.emit("message", { type: "connecting" });
|
||||
|
||||
const accounts = await provider.enable();
|
||||
const account = getAddress(accounts[0] as string);
|
||||
const account = utils.getAddress(accounts[0] as string);
|
||||
// Switch to chain if provided
|
||||
let id = await this.getChainId();
|
||||
let unsupported = this.isChainUnsupported(id);
|
||||
@@ -120,7 +119,7 @@ export class CoinbaseWalletConnector extends WagmiConnector<
|
||||
throw new Error("No accounts found");
|
||||
}
|
||||
// return checksum address
|
||||
return getAddress(accounts[0] as string);
|
||||
return utils.getAddress(accounts[0] as string);
|
||||
}
|
||||
|
||||
async getChainId() {
|
||||
@@ -197,7 +196,7 @@ export class CoinbaseWalletConnector extends WagmiConnector<
|
||||
|
||||
async switchChain(chainId: number): Promise<Chain> {
|
||||
const provider = await this.getProvider();
|
||||
const id = hexValue(chainId);
|
||||
const id = utils.hexValue(chainId);
|
||||
|
||||
try {
|
||||
await provider.request({
|
||||
@@ -257,7 +256,7 @@ export class CoinbaseWalletConnector extends WagmiConnector<
|
||||
if (accounts.length === 0) {
|
||||
this.emit("disconnect");
|
||||
} else {
|
||||
this.emit("change", { account: getAddress(accounts[0] as string) });
|
||||
this.emit("change", { account: utils.getAddress(accounts[0] as string) });
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { providers } from "ethers";
|
||||
import { getAddress, hexValue } from "ethers/lib/utils.js";
|
||||
import { providers, utils } from "ethers";
|
||||
import type Provider from "ethereum-provider";
|
||||
import type { Address } from "abitype";
|
||||
import type { Chain } from "@thirdweb-dev/chains";
|
||||
@@ -76,7 +75,7 @@ export class FrameConnector extends WagmiConnector<
|
||||
const accounts: string[] = await provider.request({
|
||||
method: "eth_requestAccounts",
|
||||
});
|
||||
const account = getAddress(accounts[0] as string);
|
||||
const account = utils.getAddress(accounts[0] as string);
|
||||
// Switch to chain if provided
|
||||
let id = await this.getChainId();
|
||||
let unsupported = this.isChainUnsupported(id);
|
||||
@@ -132,7 +131,7 @@ export class FrameConnector extends WagmiConnector<
|
||||
method: "eth_accounts",
|
||||
})) as string[];
|
||||
// return checksum address
|
||||
return getAddress(accounts[0] as string);
|
||||
return utils.getAddress(accounts[0] as string);
|
||||
}
|
||||
|
||||
async getChainId() {
|
||||
@@ -195,7 +194,7 @@ export class FrameConnector extends WagmiConnector<
|
||||
if (!provider) {
|
||||
throw new ConnectorNotFoundError();
|
||||
}
|
||||
const chainIdHex = hexValue(chainId);
|
||||
const chainIdHex = utils.hexValue(chainId);
|
||||
|
||||
try {
|
||||
await Promise.all([
|
||||
@@ -320,7 +319,7 @@ export class FrameConnector extends WagmiConnector<
|
||||
this.emit("disconnect");
|
||||
} else {
|
||||
this.emit("change", {
|
||||
account: getAddress(accounts[0] as string),
|
||||
account: utils.getAddress(accounts[0] as string),
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
@@ -5,7 +5,7 @@ import {
|
||||
MagicOptions,
|
||||
} from "./types";
|
||||
import type { Chain } from "@thirdweb-dev/chains";
|
||||
import { ethers, Signer } from "ethers";
|
||||
import { ethers, Signer, utils } from "ethers";
|
||||
import {
|
||||
// OAuthProvider,
|
||||
OAuthExtension,
|
||||
@@ -17,7 +17,6 @@ import {
|
||||
SDKBase,
|
||||
} from "@magic-sdk/provider";
|
||||
import { Address } from "@thirdweb-dev/sdk";
|
||||
import { getAddress } from "ethers/lib/utils";
|
||||
import { Magic } from "magic-sdk";
|
||||
import type { AbstractProvider } from "web3-core";
|
||||
import { RPCProviderModule } from "@magic-sdk/provider/dist/types/modules/rpc-provider";
|
||||
@@ -102,7 +101,7 @@ export abstract class MagicBaseConnector extends WagmiConnector<
|
||||
if (accounts.length === 0) {
|
||||
this.emit("disconnect");
|
||||
} else {
|
||||
this.emit("change", { account: getAddress(accounts[0]) });
|
||||
this.emit("change", { account: utils.getAddress(accounts[0]) });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ import type {
|
||||
AuthLoginReturnType,
|
||||
InitializedUser,
|
||||
PaperEmbeddedWalletSdk,
|
||||
RecoveryShareManagement,
|
||||
} from "@paperxyz/embedded-wallet-service-sdk";
|
||||
import { UserStatus } from "@paperxyz/embedded-wallet-service-sdk";
|
||||
import type { Chain } from "@thirdweb-dev/chains";
|
||||
@@ -39,9 +40,15 @@ export class PaperWalletConnector extends Connector<PaperWalletConnectionArgs> {
|
||||
"@paperxyz/embedded-wallet-service-sdk"
|
||||
);
|
||||
resolve(
|
||||
new PaperEmbeddedWalletSdk({
|
||||
new PaperEmbeddedWalletSdk<RecoveryShareManagement.USER_MANAGED>({
|
||||
advancedOptions: {
|
||||
// @ts-expect-error - Allow passing string instead of forcing enum
|
||||
recoveryShareManagement:
|
||||
this.options.advancedOptions?.recoveryShareManagement,
|
||||
},
|
||||
clientId: this.options.clientId,
|
||||
chain: "Ethereum", // just pass Ethereum no matter what chain we are going to connect
|
||||
chain: "Ethereum",
|
||||
styles: this.options.styles,
|
||||
}),
|
||||
);
|
||||
} catch (err) {
|
||||
@@ -92,6 +99,7 @@ export class PaperWalletConnector extends Connector<PaperWalletConnectionArgs> {
|
||||
async disconnect(): Promise<void> {
|
||||
const paper = await this.#paper;
|
||||
await paper?.auth.logout();
|
||||
this.#signer = undefined;
|
||||
this.user = null;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,14 +1,26 @@
|
||||
import type { Chain } from "@thirdweb-dev/chains";
|
||||
import type {
|
||||
RecoveryShareManagement,
|
||||
PaperConstructorType,
|
||||
} from "@paperxyz/embedded-wallet-service-sdk";
|
||||
|
||||
type PaperAdvanceOptions = {
|
||||
recoveryShareManagement?: "USER_MANAGED" | "AWS_MANAGED";
|
||||
};
|
||||
|
||||
export type PaperWalletAdditionalOptions = {
|
||||
clientId: string;
|
||||
chain: Pick<Chain, "chainId" | "rpc">;
|
||||
advancedOptions?: PaperAdvanceOptions;
|
||||
styles?: PaperConstructorType<RecoveryShareManagement>["styles"];
|
||||
};
|
||||
|
||||
export interface PaperWalletConnectorOptions {
|
||||
clientId: string;
|
||||
chain: Pick<Chain, "chainId" | "rpc">;
|
||||
chains: Chain[];
|
||||
advancedOptions?: PaperAdvanceOptions;
|
||||
styles?: PaperConstructorType<RecoveryShareManagement>["styles"];
|
||||
}
|
||||
|
||||
export interface PaperWalletConnectionArgs {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Chain } from "@thirdweb-dev/chains";
|
||||
import { Chain, getChainByChainId } from "@thirdweb-dev/chains";
|
||||
import { ConnectParams, Connector } from "../../interfaces/connector";
|
||||
import { ERC4337EthersProvider } from "./lib/erc4337-provider";
|
||||
import { getVerifyingPaymaster } from "./lib/paymaster";
|
||||
@@ -15,6 +15,7 @@ import { EVMWallet } from "../../interfaces";
|
||||
import { ERC4337EthersSigner } from "./lib/erc4337-signer";
|
||||
import { BigNumber, ethers, providers } from "ethers";
|
||||
import {
|
||||
ChainOrRpcUrl,
|
||||
getChainProvider,
|
||||
SmartContract,
|
||||
Transaction,
|
||||
@@ -36,14 +37,14 @@ export class SmartWalletConnector extends Connector<SmartWalletConnectionArgs> {
|
||||
|
||||
async initialize(personalWallet: EVMWallet) {
|
||||
const config = this.config;
|
||||
const chain =
|
||||
typeof config.chain === "string"
|
||||
? config.chain
|
||||
: (config.chain as Chain).slug;
|
||||
const originalProvider = getChainProvider(config.chain, {
|
||||
thirdwebApiKey: config.thirdwebApiKey || DEFAULT_WALLET_API_KEY,
|
||||
}) as providers.BaseProvider;
|
||||
const chainSlug = await this.getChainSlug(config.chain, originalProvider);
|
||||
const bundlerUrl =
|
||||
this.config.bundlerUrl || `https://${chain}.bundler.thirdweb.com`;
|
||||
this.config.bundlerUrl || `https://${chainSlug}.bundler.thirdweb.com`;
|
||||
const paymasterUrl =
|
||||
this.config.paymasterUrl || `https://${chain}.bundler.thirdweb.com`;
|
||||
this.config.paymasterUrl || `https://${chainSlug}.bundler.thirdweb.com`;
|
||||
const entryPointAddress = config.entryPointAddress || ENTRYPOINT_ADDRESS;
|
||||
const localSigner = await personalWallet.getSigner();
|
||||
const providerConfig: ProviderConfig = {
|
||||
@@ -65,9 +66,6 @@ export class SmartWalletConnector extends Connector<SmartWalletConnectionArgs> {
|
||||
accountInfo: config.accountInfo || this.defaultAccountInfo(),
|
||||
thirdwebApiKey: config.thirdwebApiKey,
|
||||
};
|
||||
const originalProvider = getChainProvider(config.chain, {
|
||||
thirdwebApiKey: config.thirdwebApiKey || DEFAULT_WALLET_API_KEY,
|
||||
}) as providers.BaseProvider;
|
||||
this.personalWallet = personalWallet;
|
||||
const accountApi = new AccountAPI(providerConfig, originalProvider);
|
||||
this.aaProvider = await create4337Provider(
|
||||
@@ -251,4 +249,29 @@ export class SmartWalletConnector extends Connector<SmartWalletConnectionArgs> {
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
private async getChainSlug(
|
||||
chainOrRpc: ChainOrRpcUrl,
|
||||
provider: ethers.providers.Provider,
|
||||
): Promise<string> {
|
||||
if (typeof chainOrRpc === "object") {
|
||||
return chainOrRpc.slug;
|
||||
}
|
||||
if (typeof chainOrRpc === "number") {
|
||||
const chain = getChainByChainId(chainOrRpc);
|
||||
return chain.slug;
|
||||
}
|
||||
if (typeof chainOrRpc === "string") {
|
||||
if (chainOrRpc.startsWith("http") || chainOrRpc.startsWith("ws")) {
|
||||
// if it's a url, try to get the chain id from the provider
|
||||
const chainId = (await provider.getNetwork()).chainId;
|
||||
const chain = getChainByChainId(chainId);
|
||||
return chain.slug;
|
||||
}
|
||||
// otherwise its the network name
|
||||
return chainOrRpc;
|
||||
} else {
|
||||
throw new Error(`Invalid network: ${chainOrRpc}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { LOCAL_NODE_PKEY, SmartContract, ThirdwebSDK } from "@thirdweb-dev/sdk";
|
||||
import { BigNumberish, BigNumber, ethers } from "ethers";
|
||||
import { arrayify, hexConcat } from "ethers/lib/utils";
|
||||
import { BigNumberish, BigNumber, ethers, utils } from "ethers";
|
||||
import { AccountApiParams } from "../types";
|
||||
import { BaseAccountAPI } from "./base-api";
|
||||
import { MINIMAL_ACCOUNT_ABI } from "./constants";
|
||||
@@ -64,7 +63,7 @@ export class AccountAPI extends BaseAccountAPI {
|
||||
} catch (e) {
|
||||
console.error("Cost to deploy smart wallet: unknown", e);
|
||||
}
|
||||
return hexConcat([factory.getAddress(), tx.encode()]);
|
||||
return utils.hexConcat([factory.getAddress(), tx.encode()]);
|
||||
}
|
||||
|
||||
async getFactoryContract() {
|
||||
@@ -131,7 +130,9 @@ export class AccountAPI extends BaseAccountAPI {
|
||||
}
|
||||
|
||||
async signUserOpHash(userOpHash: string): Promise<string> {
|
||||
return await this.params.localSigner.signMessage(arrayify(userOpHash));
|
||||
return await this.params.localSigner.signMessage(
|
||||
utils.arrayify(userOpHash),
|
||||
);
|
||||
}
|
||||
|
||||
async isAcountDeployed() {
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
import { ethers, BigNumber, BigNumberish, providers } from "ethers";
|
||||
import { ethers, BigNumber, BigNumberish, providers, utils } from "ethers";
|
||||
import {
|
||||
EntryPoint,
|
||||
EntryPoint__factory,
|
||||
UserOperationStruct,
|
||||
} from "@account-abstraction/contracts";
|
||||
|
||||
import { resolveProperties } from "ethers/lib/utils";
|
||||
import { NotPromise, packUserOp } from "@account-abstraction/utils";
|
||||
import {
|
||||
GasOverheads,
|
||||
@@ -15,7 +14,11 @@ import {
|
||||
import { TransactionDetailsForUserOp } from "./transaction-details";
|
||||
import { getUserOpHashV06 } from "./utils";
|
||||
import { DUMMY_PAYMASTER_AND_DATA, SIG_SIZE } from "./paymaster";
|
||||
import { CeloAlfajoresTestnet, CeloBaklavaTestnet, Celo } from "@thirdweb-dev/chains"
|
||||
import {
|
||||
CeloAlfajoresTestnet,
|
||||
CeloBaklavaTestnet,
|
||||
Celo,
|
||||
} from "@thirdweb-dev/chains";
|
||||
|
||||
export interface BaseApiParams {
|
||||
provider: providers.Provider;
|
||||
@@ -169,7 +172,7 @@ export abstract class BaseAccountAPI {
|
||||
async getPreVerificationGas(
|
||||
userOp: Partial<UserOperationStruct>,
|
||||
): Promise<number> {
|
||||
const p = await resolveProperties(userOp);
|
||||
const p = await utils.resolveProperties(userOp);
|
||||
return calcPreVerificationGas(p, this.overheads);
|
||||
}
|
||||
|
||||
@@ -286,7 +289,11 @@ export abstract class BaseAccountAPI {
|
||||
const network = await this.provider.getNetwork();
|
||||
const chainId = network.chainId;
|
||||
|
||||
if (chainId === Celo.chainId || chainId === CeloAlfajoresTestnet.chainId || chainId === CeloBaklavaTestnet.chainId) {
|
||||
if (
|
||||
chainId === Celo.chainId ||
|
||||
chainId === CeloAlfajoresTestnet.chainId ||
|
||||
chainId === CeloBaklavaTestnet.chainId
|
||||
) {
|
||||
maxPriorityFeePerGas = maxFeePerGas;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
/* eslint-disable @typescript-eslint/no-parameter-properties */
|
||||
import { BigNumber, providers, Signer } from "ethers";
|
||||
import { hexValue, resolveProperties } from "ethers/lib/utils";
|
||||
import { BigNumber, providers, Signer, utils } from "ethers";
|
||||
|
||||
import {
|
||||
EntryPoint,
|
||||
@@ -134,7 +133,7 @@ export class ERC4337EthersProvider extends providers.BaseProvider {
|
||||
async constructUserOpTransactionResponse(
|
||||
userOp1: UserOperationStruct,
|
||||
): Promise<providers.TransactionResponse> {
|
||||
const userOp = await resolveProperties(userOp1);
|
||||
const userOp = await utils.resolveProperties(userOp1);
|
||||
const userOpHash = await this.smartAccountAPI.getUserOpHash(userOp);
|
||||
const waitForUserOp = async (): Promise<providers.TransactionReceipt> =>
|
||||
await new Promise((resolve, reject) => {
|
||||
@@ -154,7 +153,7 @@ export class ERC4337EthersProvider extends providers.BaseProvider {
|
||||
nonce: BigNumber.from(userOp.nonce).toNumber(),
|
||||
gasLimit: BigNumber.from(userOp.callGasLimit), // ??
|
||||
value: BigNumber.from(0),
|
||||
data: hexValue(userOp.callData), // should extract the actual called method from this "execFromEntryPoint()" call
|
||||
data: utils.hexValue(userOp.callData), // should extract the actual called method from this "execFromEntryPoint()" call
|
||||
chainId: this.chainId,
|
||||
wait: async (
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
import { ethers, providers } from "ethers";
|
||||
import { ethers, providers, utils } from "ethers";
|
||||
|
||||
import { Bytes, Signer } from "ethers";
|
||||
import { ClientConfig } from "@account-abstraction/sdk";
|
||||
import { BaseAccountAPI } from "./base-api";
|
||||
import type { ERC4337EthersProvider } from "./erc4337-provider";
|
||||
import { defineReadOnly, Deferrable } from "ethers/lib/utils";
|
||||
import { HttpRpcClient } from "./http-rpc-client";
|
||||
|
||||
export class ERC4337EthersSigner extends Signer {
|
||||
@@ -23,7 +22,7 @@ export class ERC4337EthersSigner extends Signer {
|
||||
smartAccountAPI: BaseAccountAPI,
|
||||
) {
|
||||
super();
|
||||
defineReadOnly(this, "provider", erc4337provider);
|
||||
utils.defineReadOnly(this, "provider", erc4337provider);
|
||||
this.config = config;
|
||||
this.originalSigner = originalSigner;
|
||||
this.erc4337provider = erc4337provider;
|
||||
@@ -35,7 +34,7 @@ export class ERC4337EthersSigner extends Signer {
|
||||
|
||||
// This one is called by Contract. It signs the request and passes in to Provider to be sent.
|
||||
async sendTransaction(
|
||||
transaction: Deferrable<providers.TransactionRequest>,
|
||||
transaction: utils.Deferrable<providers.TransactionRequest>,
|
||||
batched: boolean = false,
|
||||
): Promise<providers.TransactionResponse> {
|
||||
const tx = await ethers.utils.resolveProperties(transaction);
|
||||
@@ -138,7 +137,7 @@ export class ERC4337EthersSigner extends Signer {
|
||||
|
||||
async signTransaction(
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
transaction: Deferrable<providers.TransactionRequest>,
|
||||
transaction: utils.Deferrable<providers.TransactionRequest>,
|
||||
): Promise<string> {
|
||||
throw new Error("not implemented");
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { providers } from "ethers";
|
||||
import { resolveProperties } from "ethers/lib/utils";
|
||||
import { providers, utils } from "ethers";
|
||||
import { UserOperationStruct } from "@account-abstraction/contracts";
|
||||
import { deepHexlify } from "@account-abstraction/utils";
|
||||
|
||||
@@ -55,7 +54,7 @@ export class HttpRpcClient {
|
||||
*/
|
||||
async sendUserOpToBundler(userOp1: UserOperationStruct): Promise<string> {
|
||||
await this.initializing;
|
||||
const hexifiedUserOp = deepHexlify(await resolveProperties(userOp1));
|
||||
const hexifiedUserOp = deepHexlify(await utils.resolveProperties(userOp1));
|
||||
const jsonRequestData: [UserOperationStruct, string] = [
|
||||
hexifiedUserOp,
|
||||
this.entryPointAddress,
|
||||
@@ -71,7 +70,7 @@ export class HttpRpcClient {
|
||||
userOp1: Partial<UserOperationStruct>,
|
||||
): Promise<string> {
|
||||
await this.initializing;
|
||||
const hexifiedUserOp = deepHexlify(await resolveProperties(userOp1));
|
||||
const hexifiedUserOp = deepHexlify(await utils.resolveProperties(userOp1));
|
||||
const jsonRequestData: [UserOperationStruct, string] = [
|
||||
hexifiedUserOp,
|
||||
this.entryPointAddress,
|
||||
@@ -93,7 +92,7 @@ export class HttpRpcClient {
|
||||
if (!DEBUG) {
|
||||
return;
|
||||
}
|
||||
const userOp = await resolveProperties(userOp1);
|
||||
const userOp = await utils.resolveProperties(userOp1);
|
||||
console.debug(
|
||||
"sending",
|
||||
method,
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
/* eslint-disable @typescript-eslint/no-parameter-properties */
|
||||
import { BigNumberish, Event, providers } from "ethers";
|
||||
import { BigNumberish, Event, providers, utils } from "ethers";
|
||||
import { EntryPoint } from "@account-abstraction/contracts";
|
||||
import { defaultAbiCoder } from "ethers/lib/utils";
|
||||
|
||||
/**
|
||||
* This class encapsulates Ethers.js listener function and necessary UserOperation details to
|
||||
@@ -92,7 +91,7 @@ export class UserOperationEventListener {
|
||||
let message = revertReasonEvents[0].args.revertReason;
|
||||
if (message.startsWith("0x08c379a0")) {
|
||||
// Error(string)
|
||||
message = defaultAbiCoder
|
||||
message = utils.defaultAbiCoder
|
||||
.decode(["string"], "0x" + message.substring(10))
|
||||
.toString();
|
||||
}
|
||||
|
||||
@@ -1,10 +1,5 @@
|
||||
import { ethers } from "ethers";
|
||||
import { ethers, utils } from "ethers";
|
||||
import { UserOperationStruct } from "@account-abstraction/contracts";
|
||||
import {
|
||||
resolveProperties,
|
||||
keccak256,
|
||||
defaultAbiCoder,
|
||||
} from "ethers/lib/utils";
|
||||
|
||||
export function toJSON(op: Partial<UserOperationStruct>): Promise<any> {
|
||||
return ethers.utils.resolveProperties(op).then((userOp) =>
|
||||
@@ -38,18 +33,18 @@ export async function getUserOpHashV06(
|
||||
entryPoint: string,
|
||||
chainId: number,
|
||||
): Promise<Promise<string>> {
|
||||
const op = await resolveProperties(userOp);
|
||||
const op = await utils.resolveProperties(userOp);
|
||||
const hashedUserOp = {
|
||||
sender: op.sender,
|
||||
nonce: op.nonce,
|
||||
initCodeHash: keccak256(op.initCode),
|
||||
callDataHash: keccak256(op.callData),
|
||||
initCodeHash: utils.keccak256(op.initCode),
|
||||
callDataHash: utils.keccak256(op.callData),
|
||||
callGasLimit: op.callGasLimit,
|
||||
verificationGasLimit: op.verificationGasLimit,
|
||||
preVerificationGas: op.preVerificationGas,
|
||||
maxFeePerGas: op.maxFeePerGas,
|
||||
maxPriorityFeePerGas: op.maxPriorityFeePerGas,
|
||||
paymasterAndDataHash: keccak256(op.paymasterAndData),
|
||||
paymasterAndDataHash: utils.keccak256(op.paymasterAndData),
|
||||
};
|
||||
|
||||
const userOpType = {
|
||||
@@ -68,16 +63,16 @@ export async function getUserOpHashV06(
|
||||
name: "hashedUserOp",
|
||||
type: "tuple",
|
||||
};
|
||||
let encoded = defaultAbiCoder.encode(
|
||||
let encoded = utils.defaultAbiCoder.encode(
|
||||
[userOpType as any],
|
||||
[{ ...hashedUserOp }],
|
||||
);
|
||||
// remove leading word (total length) and trailing word (zero-length signature)
|
||||
|
||||
const userOpHash = keccak256(encoded);
|
||||
const enc = defaultAbiCoder.encode(
|
||||
const userOpHash = utils.keccak256(encoded);
|
||||
const enc = utils.defaultAbiCoder.encode(
|
||||
["bytes32", "address", "uint256"],
|
||||
[userOpHash, entryPoint, chainId],
|
||||
);
|
||||
return keccak256(enc);
|
||||
return utils.keccak256(enc);
|
||||
}
|
||||
|
||||
@@ -12,6 +12,8 @@ import { providers, utils } from "ethers";
|
||||
import { walletIds } from "../../constants/walletIds";
|
||||
import { QRModalOptions } from "./qrModalOptions";
|
||||
|
||||
const chainsToRequest = new Set([1, 137, 10, 42161, 56]);
|
||||
|
||||
type WalletConnectOptions = {
|
||||
qrModalOptions?: QRModalOptions;
|
||||
projectId: string;
|
||||
@@ -78,6 +80,7 @@ export class WalletConnectConnector extends WagmiConnector<
|
||||
#provider?: WalletConnectProvider;
|
||||
#initProviderPromise?: Promise<void>;
|
||||
#storage: AsyncStorage;
|
||||
filteredChains: Chain[];
|
||||
|
||||
constructor(config: { chains?: Chain[]; options: WalletConnectOptions }) {
|
||||
super({
|
||||
@@ -86,6 +89,13 @@ export class WalletConnectConnector extends WagmiConnector<
|
||||
});
|
||||
this.#storage = config.options.storage;
|
||||
this.#createProvider();
|
||||
|
||||
this.filteredChains =
|
||||
this.chains.length > 50
|
||||
? this.chains.filter((c) => {
|
||||
return chainsToRequest.has(c.chainId);
|
||||
})
|
||||
: this.chains;
|
||||
}
|
||||
|
||||
async connect({ chainId: chainIdP, pairingTopic }: ConnectConfig = {}) {
|
||||
@@ -101,7 +111,7 @@ export class WalletConnectConnector extends WagmiConnector<
|
||||
if (lastUsedChainId && !this.isChainUnsupported(lastUsedChainId)) {
|
||||
targetChainId = lastUsedChainId;
|
||||
} else {
|
||||
targetChainId = this.chains[0]?.chainId;
|
||||
targetChainId = this.filteredChains[0]?.chainId;
|
||||
}
|
||||
}
|
||||
if (!targetChainId) {
|
||||
@@ -120,11 +130,9 @@ export class WalletConnectConnector extends WagmiConnector<
|
||||
|
||||
// If there no active session, or the chains are stale, connect.
|
||||
if (!provider.session || isChainsStale) {
|
||||
// defaultChains, passing ALL CHAINS hangs the connector
|
||||
const optionalChains = [
|
||||
1, 5, 84531, 137, 80001, 42161, 421613, 10, 420, 56, 97, 250, 4002,
|
||||
43114, 43113, 1337,
|
||||
].filter((chainId) => chainId !== targetChainId);
|
||||
const optionalChains = this.filteredChains
|
||||
.filter((chain) => chain.chainId !== targetChainId)
|
||||
.map((optionalChain) => optionalChain.chainId);
|
||||
|
||||
this.emit("message", { type: "connecting" });
|
||||
|
||||
@@ -136,7 +144,7 @@ export class WalletConnectConnector extends WagmiConnector<
|
||||
});
|
||||
|
||||
await this.#setRequestedChainsIds(
|
||||
this.chains.map(({ chainId }) => chainId),
|
||||
this.filteredChains.map(({ chainId }) => chainId),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -305,7 +313,7 @@ export class WalletConnectConnector extends WagmiConnector<
|
||||
OPTIONAL_EVENTS,
|
||||
OPTIONAL_METHODS,
|
||||
} = await import("@walletconnect/ethereum-provider");
|
||||
const [defaultChain, ...optionalChains] = this.chains.map(
|
||||
const [defaultChain, ...optionalChains] = this.filteredChains.map(
|
||||
({ chainId }) => chainId,
|
||||
);
|
||||
|
||||
@@ -326,7 +334,7 @@ export class WalletConnectConnector extends WagmiConnector<
|
||||
icons: [this.options.dappMetadata.logoUrl || ""],
|
||||
},
|
||||
rpcMap: Object.fromEntries(
|
||||
this.chains.map((chain) => [chain.chainId, chain.rpc[0]]),
|
||||
this.filteredChains.map((chain) => [chain.chainId, chain.rpc[0]]),
|
||||
),
|
||||
|
||||
qrModalOptions: this.options.qrModalOptions,
|
||||
@@ -366,7 +374,7 @@ export class WalletConnectConnector extends WagmiConnector<
|
||||
}
|
||||
|
||||
const requestedChains = await this.#getRequestedChainsIds();
|
||||
const connectorChains = this.chains.map(({ chainId }) => chainId);
|
||||
const connectorChains = this.filteredChains.map(({ chainId }) => chainId);
|
||||
const namespaceChains = this.#getNamespaceChainsIds();
|
||||
|
||||
if (
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import {
|
||||
PaperWalletConnectionArgs,
|
||||
PaperWalletAdditionalOptions,
|
||||
PaperWalletAdditionalOptions as PaperWalletAdditionalOptions_,
|
||||
} from "../connectors/paper/types";
|
||||
import { Connector } from "../interfaces/connector";
|
||||
import { AbstractClientWallet, WalletOptions } from "./base";
|
||||
@@ -8,10 +8,12 @@ import type { Chain } from "@thirdweb-dev/chains";
|
||||
import type { PaperWalletConnector } from "../connectors/paper";
|
||||
import { walletIds } from "../constants/walletIds";
|
||||
|
||||
export type PaperWalletOptions = WalletOptions<PaperWalletAdditionalOptions>;
|
||||
export type { PaperWalletAdditionalOptions } from "../connectors/paper/types";
|
||||
|
||||
export type PaperWalletOptions = WalletOptions<PaperWalletAdditionalOptions_>;
|
||||
|
||||
export class PaperWallet extends AbstractClientWallet<
|
||||
PaperWalletAdditionalOptions,
|
||||
PaperWalletAdditionalOptions_,
|
||||
PaperWalletConnectionArgs
|
||||
> {
|
||||
connector?: Connector;
|
||||
@@ -28,8 +30,8 @@ export class PaperWallet extends AbstractClientWallet<
|
||||
return "Paper Wallet" as const;
|
||||
}
|
||||
|
||||
clientId: PaperWalletAdditionalOptions["clientId"];
|
||||
chain: PaperWalletAdditionalOptions["chain"];
|
||||
clientId: PaperWalletAdditionalOptions_["clientId"];
|
||||
chain: PaperWalletAdditionalOptions_["chain"];
|
||||
|
||||
constructor(options: PaperWalletOptions) {
|
||||
super(PaperWallet.id, {
|
||||
@@ -47,6 +49,11 @@ export class PaperWallet extends AbstractClientWallet<
|
||||
clientId: this.clientId,
|
||||
chain: this.chain,
|
||||
chains: this.chains,
|
||||
advancedOptions: {
|
||||
recoveryShareManagement:
|
||||
this.options?.advancedOptions?.recoveryShareManagement,
|
||||
},
|
||||
styles: this.options?.styles,
|
||||
});
|
||||
}
|
||||
return this.connector;
|
||||
|
||||
Generated
+236
-2352
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user