Compare commits

..
Author SHA1 Message Date
github-actions[bot]GitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>
4e5eb13b82 Version Packages (#1266)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-06-29 19:11:03 -07:00
2b11353909 [SDK] remove ethers/lib/utils dependency (#1277)
Co-authored-by: Jonas Daniels <[email protected]>
2023-06-30 01:10:47 +00:00
Manan TankandGitHub 5882091eab [chains] Fix RPC override issue (#1276) 2023-06-29 22:27:59 +00:00
Mariano FuentesandGitHub 8fc5f204b0 Fix bugs with cli deploy (#1274) 2023-06-29 18:11:25 +00:00
nkrishangandGitHub c953571588 mass rename smart-wallet -> account (#1271) 2023-06-29 12:26:48 +00:00
Manan TankandGitHub edcd22d612 [react-core] Add autoConnectTimeout (#1273) 2023-06-29 12:19:43 +00:00
iketwandGitHub 0d5503aae9 [RN] Only handle link if coinbase in supportedWallets (#1270) 2023-06-28 21:56:12 +00:00
Manan TankandGitHub 998e521733 [wallets, react] expose advancedOptions in paper (#1269) 2023-06-28 21:08:34 +00:00
FirekeeperandGitHub be606dd3c9 [paper] set signer null on disconnect (#1267) 2023-06-28 17:26:35 +00:00
d794b8f9f4 update: Add zerion to useInstalledWallets (#1210)
Co-authored-by: Jonas Daniels <[email protected]>
2023-06-28 16:50:36 +00:00
YashandGitHub 21b29490d4 [SDK] Tests for new publish+deploy flow (#1244) 2023-06-28 16:23:36 +00:00
github-actions[bot]GitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>
7b1d62b323 Version Packages (#1262)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-06-28 08:07:57 -07:00
Manan TankandGitHub e78da6b36c [wallets] Wallet connect v2 corrections (#1265) 2023-06-28 13:34:42 +00:00
ed711c8cb2 [Wallets] Use min number of chains if user passes more than 50 chains (#1263)
Co-authored-by: Manan Tank <[email protected]>
2023-06-28 12:04:28 +00:00
05a7495a13 [Wallets] handle passing RPC urls to SmartWallet config (#1255)
Co-authored-by: Jonas Daniels <[email protected]>
2023-06-28 07:20:04 +00:00
github-actions[bot]GitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>
11bb053246 Version Packages (#1261)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-06-27 22:16:09 -07:00
efb3546ec8 [Wallets] Fix. Respect dev passed chains. (#1259)
Co-authored-by: Manan Tank <[email protected]>
2023-06-28 05:07:24 +00:00
github-actions[bot]GitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>
0a5d2b5bdd Version Packages (#1247)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-06-27 17:36:21 -07:00
FirekeeperandGitHub ac3e019cd1 [unity-js-bridge] wcv2 and paper support (#1256) 2023-06-28 00:28:16 +00:00
3c5dc4804a Migration to WalletConnectV2 (#1215)
Co-authored-by: Manan Tank <[email protected]>
2023-06-28 00:04:07 +00:00
Joaquim VergesandGitHub 30ac3aef84 [SDK] Handle base64 encoded NFTs (#1254) 2023-06-27 23:31:52 +00:00
YashandGitHub ef4cb09219 [SDK] Any EVM deployments: update EIP155 error substrings (#1249) 2023-06-27 22:55:16 +00:00
ad7dae3b16 [React] Stop using useActiveChain deprecated hook (#1253)
Co-authored-by: Nacho Iacovino <[email protected]>
2023-06-27 21:50:28 +00:00
0fd8aa04a9 fix(chains): Celo Alfajores Explorer URL (#1243)
Co-authored-by: Joaquim Verges <[email protected]>
Co-authored-by: Jonas Daniels <[email protected]>
2023-06-27 19:37:23 +00:00
620e89dc25 [React] Export smart wallet hooks (#1248)
Co-authored-by: Jonas Daniels <[email protected]>
2023-06-27 19:01:45 +00:00
Nacho IacovinoandGitHub 86d33c4b3e [React] Fix marketplace v3 cache keys (#1251) 2023-06-27 18:06:30 +00:00
Adam MajmudarandGitHub d43f6171d9 Allow setting login payload duration (#1250) 2023-06-27 18:04:33 +00:00
06ca1c407d [SDK] Add tests for SmartWallet and SmartWalletFactory; add smartWallet.setAccess and smartWallet.isAdmin (#1227)
Co-authored-by: Nacho Iacovino <[email protected]>
Co-authored-by: Nacho Iacovino <[email protected]>
2023-06-27 01:57:33 +00:00
github-actions[bot]GitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>
c578a437cc Version Packages (#1234)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-06-26 18:42:04 -07:00
Danny FridayandGitHub 0c5b03b8d6 Remove ipfs-2 gateway (#1246) 2023-06-27 00:31:06 +00:00
nkrishangandGitHub 9af346eead [SDK][React] SmartWalletFactory: use getAllAccounts instead of event logs of AccountCreated to get accounts of a factory (#1241) 2023-06-26 17:51:22 +00:00
iketwandGitHub d9fb134ad4 [RN] better design for custom details button (#1245) 2023-06-26 15:25:19 +00:00
Mariano FuentesandGitHub 1c7264b403 Fix install bug (#1240) 2023-06-24 00:59:52 +00:00
Joaquim VergesandGitHub a140ee99b2 add zora extension in auto docs (#1239) 2023-06-24 00:23:07 +00:00
iketwandGitHub 6e1fe6e582 [React] Add Rainbow and Trust wallets connection hooks (#1238) 2023-06-23 23:06:59 +00:00
iketwandGitHub 536b0f1240 [React] Add Rainbow Wallet (#1237) 2023-06-23 22:11:40 +00:00
b626782b0e [React/Wallets] Add Trust Wallet (#1236)
Co-authored-by: Manan Tank <[email protected]>
2023-06-23 21:23:13 +00:00
Nacho IacovinoandGitHub 1d76334dd3 [React] Fix required type for address on useSmartWalletsForAddress (#1235) 2023-06-23 18:44:00 +00:00
nkrishangandGitHub d498c79a91 [SDK] Fix smartWalletFactory.getAllWallets (#1233) 2023-06-23 18:20:03 +00:00
162 changed files with 41562 additions and 5173 deletions
+37
View File
@@ -1,5 +1,42 @@
# @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
- [#1250](https://github.com/thirdweb-dev/js/pull/1250) [`d43f6171`](https://github.com/thirdweb-dev/js/commit/d43f6171d910e31b748b171b012174390aac3fff) Thanks [@adam-maj](https://github.com/adam-maj)! - Allow setting login payload validity duration
- Updated dependencies [[`ac3e019c`](https://github.com/thirdweb-dev/js/commit/ac3e019cd1776dbdb0d06b213420ad17586f678e), [`3c5dc480`](https://github.com/thirdweb-dev/js/commit/3c5dc4804abc56b933ec45e9e1da11eb182296cc)]:
- @thirdweb-dev/wallets@1.0.0
## 3.2.3
### Patch Changes
- Updated dependencies [[`536b0f12`](https://github.com/thirdweb-dev/js/commit/536b0f1240ab446aac22cf547a4e09e73ee6bf7b), [`b626782b`](https://github.com/thirdweb-dev/js/commit/b626782b0e8c6b76673472d3aee1c802dfb11b5f)]:
- @thirdweb-dev/wallets@0.3.3
## 3.2.2
### Patch Changes
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@thirdweb-dev/auth",
"version": "3.2.2",
"version": "3.2.7",
"main": "dist/thirdweb-dev-auth.cjs.js",
"module": "dist/thirdweb-dev-auth.esm.js",
"browser": {
@@ -25,6 +25,11 @@ export default async function handler(
version: ctx.authOptions?.version,
chainId: parsedPayload.data.chainId || ctx.authOptions?.chainId,
resources: ctx.authOptions?.resources,
expirationTime: ctx.authOptions?.loginPayloadDurationInSeconds
? new Date(
Date.now() + 1000 * ctx.authOptions.loginPayloadDurationInSeconds,
)
: undefined,
});
return res.status(200).json({ payload });
+1
View File
@@ -44,6 +44,7 @@ export type ThirdwebAuthConfig<
validateTokenId?:
| ((tokenId: string) => void)
| ((tokenId: string) => Promise<void>);
loginPayloadDurationInSeconds?: number;
tokenDurationInSeconds?: number;
refreshIntervalInSeconds?: number;
};
+5
View File
@@ -25,6 +25,11 @@ export default async function handler(
version: ctx.authOptions?.version,
chainId: parsedPayload.data.chainId || ctx.authOptions?.chainId,
resources: ctx.authOptions?.resources,
expirationTime: ctx.authOptions?.loginPayloadDurationInSeconds
? new Date(
Date.now() + 1000 * ctx.authOptions.loginPayloadDurationInSeconds,
)
: undefined,
});
return res.status(200).json({ payload });
+1
View File
@@ -55,6 +55,7 @@ export type ThirdwebAuthConfig<
validateTokenId?:
| ((tokenId: string) => void)
| ((tokenId: string) => Promise<void>);
loginPayloadDurationInSeconds?: number;
tokenDurationInSeconds?: number;
refreshIntervalInSeconds?: number;
};
+20
View File
@@ -1,5 +1,25 @@
# @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
- [#1248](https://github.com/thirdweb-dev/js/pull/1248) [`620e89dc`](https://github.com/thirdweb-dev/js/commit/620e89dc25c91557e2164a602c7aedd733525087) Thanks [@nachoiacovino](https://github.com/nachoiacovino)! - update chains
- [#1243](https://github.com/thirdweb-dev/js/pull/1243) [`0fd8aa04`](https://github.com/thirdweb-dev/js/commit/0fd8aa04a9424497758d13a51a72363edcc30e19) Thanks [@therealharpaljadeja](https://github.com/therealharpaljadeja)! - update chains
## 0.1.24
### Patch Changes
- [#1241](https://github.com/thirdweb-dev/js/pull/1241) [`9af346ee`](https://github.com/thirdweb-dev/js/commit/9af346eeada1037be27c8d3c9e1777f7be11a8ea) Thanks [@nkrishang](https://github.com/nkrishang)! - Use fn getAllAccounts instead of event logs AccountCreated
## 0.1.23
### Patch Changes
+1 -1
View File
@@ -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"
+2 -2
View File
@@ -1,11 +1,11 @@
import type { Chain } from "../src/types";
export default {
"name": "Optimism",
"name": "OP Mainnet",
"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": [],
+1 -1
View File
@@ -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",
-51
View File
@@ -1,51 +0,0 @@
import type { Chain } from "../src/types";
export default {
"name": "Horizen Yuma Testnet",
"shortName": "Yuma",
"chain": "Yuma",
"icon": {
"url": "ipfs://QmSFMBk3rMyu45Sy9KQHjgArFj4HdywANNYrSosLMUdcti",
"width": 1213,
"height": 1213,
"format": "png"
},
"rpc": [
"https://horizen-yuma-testnet.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://yuma-testnet.horizenlabs.io/ethv1"
],
"features": [
{
"name": "EIP155"
},
{
"name": "EIP1559"
}
],
"faucets": [
"https://yuma-testnet-faucet.horizen.io"
],
"nativeCurrency": {
"name": "Testnet Zen",
"symbol": "tZEN",
"decimals": 18
},
"infoURL": "https://horizen.io/",
"chainId": 1662,
"networkId": 1662,
"slip44": 121,
"explorers": [
{
"name": "Yuma Testnet Block Explorer",
"url": "https://yuma-explorer.horizen.io",
"icon": {
"url": "ipfs://QmSFMBk3rMyu45Sy9KQHjgArFj4HdywANNYrSosLMUdcti",
"width": 1213,
"height": 1213,
"format": "png"
},
"standard": "EIP3091"
}
],
"testnet": true,
"slug": "horizen-yuma-testnet"
} as const satisfies Chain;
+37
View File
@@ -0,0 +1,37 @@
import type { Chain } from "../src/types";
export default {
"name": "Pego Network",
"chain": "PEGO",
"rpc": [
"https://pego-network.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://pegorpc.com",
"https://node1.pegorpc.com",
"https://node2.pegorpc.com",
"https://node3.pegorpc.com"
],
"faucets": [],
"nativeCurrency": {
"name": "Pego Native Token",
"symbol": "PG",
"decimals": 18
},
"infoURL": "https://pego.network",
"shortName": "pg",
"chainId": 20201022,
"networkId": 20201022,
"icon": {
"url": "ipfs://QmVf1afskRHuZjFSLCZH8397KrVNAoYgyAePX9VMBrPVtx",
"width": 246,
"height": 247,
"format": "png"
},
"explorers": [
{
"name": "Pego Network Explorer",
"url": "https://scan.pego.network",
"standard": "EIP3091"
}
],
"testnet": false,
"slug": "pego-network"
} as const satisfies Chain;
+40
View File
@@ -0,0 +1,40 @@
import type { Chain } from "../src/types";
export default {
"name": "Peperium Chain Testnet",
"chain": "PERIUM",
"rpc": [
"https://peperium-chain-testnet.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://rpc-testnet.peperium.io"
],
"faucets": [],
"nativeCurrency": {
"name": "Peperium Chain Testnet",
"symbol": "PERIUM",
"decimals": 18
},
"infoURL": "https://peperium.io",
"shortName": "PERIUM",
"chainId": 4001,
"networkId": 4001,
"icon": {
"url": "ipfs://Qmag2hr5DQghRzKPN3oUFBkjWzqd5CndQzZeb5LfoiMCXf",
"width": 160,
"height": 160,
"format": "png"
},
"explorers": [
{
"name": "Peperium Chain Explorer",
"url": "https://scan-testnet.peperium.io",
"icon": {
"url": "ipfs://Qmag2hr5DQghRzKPN3oUFBkjWzqd5CndQzZeb5LfoiMCXf",
"width": 160,
"height": 160,
"format": "png"
},
"standard": "EIP3091"
}
],
"testnet": true,
"slug": "peperium-chain-testnet"
} as const satisfies Chain;
+1 -1
View File
@@ -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": [
+1 -1
View File
@@ -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": [],
+9 -4
View File
@@ -12,15 +12,20 @@ export default {
},
"rpc": [
"https://celo-alfajores-testnet.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://alfajores-forno.celo-testnet.org",
"wss://alfajores-forno.celo-testnet.org/ws"
"wss://alfajores-forno.celo-testnet.org/ws",
"https://alfajores-forno.celo-testnet.org"
],
"faucets": [
"https://celo.org/developers/faucet",
"https://cauldron.pretoriaresearchlab.io/alfajores-faucet"
"https://cauldron.pretoriaresearchlab.io/alfajores-faucet",
"https://celo.org/developers/faucet"
],
"infoURL": "https://docs.celo.org/",
"explorers": [
{
"name": "Celoscan",
"url": "https://alfajores.celoscan.io/",
"standard": "EIP3091"
},
{
"name": "Celoscan",
"url": "https://celoscan.io",
+1 -1
View File
@@ -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"
],
+2 -1
View File
@@ -5,7 +5,8 @@ export default {
"rpc": [
"https://rollux.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://rpc.rollux.com",
"wss://rpc.rollux.com/wss"
"wss://rpc.rollux.com/wss",
"https://rpc.ankr.com/rollux/${ANKR_API_KEY}"
],
"faucets": [
"https://rollux.id/faucetapp"
+3 -3
View File
@@ -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"
+1 -1
View File
@@ -4,7 +4,7 @@ export default {
"chain": "ETC",
"rpc": [
"https://ethereum-classic.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://www.ethercluster.com/etc"
"https://etc.rivet.link"
],
"faucets": [
"https://free-online-app.com/faucet-for-eth-evm-chains/?"
+1 -1
View File
@@ -4,7 +4,7 @@ export default {
"chain": "ETC",
"rpc": [
"https://ethereum-classic-testnet-mordor.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://www.ethercluster.com/mordor"
"https://rpc.mordor.etccooperative.org"
],
"faucets": [],
"nativeCurrency": {
+1 -1
View File
@@ -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",
+13
View File
@@ -0,0 +1,13 @@
// @ts-check
/** @typedef { import("../../src/types").Chain } Chain */
/** @type {Partial<Chain>} */
export default {
explorers: [
{
name: "Celoscan",
url: "https://alfajores.celoscan.io/",
standard: "EIP3091",
},
],
};
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@thirdweb-dev/chains",
"version": "0.1.23",
"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 = [];
@@ -146,6 +173,10 @@ function findSlug(chain) {
if (slug === "base-goerli-testnet") {
slug = "base-goerli";
}
// optimisim rename handling
if (slug === "op") {
slug = "optimism";
}
// end special cases
takenSlugs[slug] = true;
File diff suppressed because one or more lines are too long
+30 -44
View File
@@ -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;
}
/**
+29
View File
@@ -1,5 +1,34 @@
# 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
- Updated dependencies [[`ef4cb092`](https://github.com/thirdweb-dev/js/commit/ef4cb092192c58c9b292b29590b888f45f9fd23d), [`30ac3aef`](https://github.com/thirdweb-dev/js/commit/30ac3aef840bde51a61acf786c709cffd3c47354), [`620e89dc`](https://github.com/thirdweb-dev/js/commit/620e89dc25c91557e2164a602c7aedd733525087), [`0fd8aa04`](https://github.com/thirdweb-dev/js/commit/0fd8aa04a9424497758d13a51a72363edcc30e19)]:
- @thirdweb-dev/sdk@3.10.26
- @thirdweb-dev/chains@0.1.25
## 0.10.26
### Patch Changes
- [#1240](https://github.com/thirdweb-dev/js/pull/1240) [`1c7264b4`](https://github.com/thirdweb-dev/js/commit/1c7264b40330d068ece67df537a0f5db0f6aedca) Thanks [@Marfuen](https://github.com/Marfuen)! - Small bug fix for updating packages using --nightly
- Updated dependencies [[`d498c79a`](https://github.com/thirdweb-dev/js/commit/d498c79a911d478077dfb8a2490eb1bf91523186), [`0c5b03b8`](https://github.com/thirdweb-dev/js/commit/0c5b03b8d6cc6a4e69bb2a4647d3626e69f1283c), [`9af346ee`](https://github.com/thirdweb-dev/js/commit/9af346eeada1037be27c8d3c9e1777f7be11a8ea)]:
- @thirdweb-dev/sdk@3.10.25
- @thirdweb-dev/storage@1.1.5
- @thirdweb-dev/chains@0.1.24
## 0.10.25
### Patch Changes
+1 -1
View File
@@ -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 -1
View File
@@ -1,7 +1,7 @@
{
"name": "thirdweb",
"main": "dist/cli/index.js",
"version": "0.10.25",
"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(),
];
@@ -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"
+46 -19
View File
@@ -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");
}
}
+5 -5
View File
@@ -1,8 +1,8 @@
import * as toml from "@iarna/toml";
import { PackageManagerType } from "../core/types/ProjectType";
import { existsSync, readFileSync } from "fs";
import { runCommand } from "../create/helpers/run-command";
import path from "path";
import { PackageManagerType } from "../core/types/ProjectType";
import { runCommand } from "../create/helpers/run-command";
import { IProcessAppTypeArgs, IProcessContractAppTypeArgs } from "./types";
export function convertDependenciesToStringFormat(dependenciesObject: object) {
@@ -174,7 +174,7 @@ export const installOrUpdate = async (packageManager: PackageManagerType, depend
case "npm":
runner = "npm";
installCommand = ["install"];
updateCommand = ["update"]
updateCommand = ["install", "--legacy-peer-deps"]
break;
case "yarn":
runner = "yarn";
@@ -223,7 +223,7 @@ export const installOrUpdate = async (packageManager: PackageManagerType, depend
}
if (typeOfAction === "install") {
if (!dependenciesToAdd.length) {return;}
if (!dependenciesToAdd.length) { return; }
const commands = [...installCommand, ...dependenciesToAdd];
await runCommand(runner, commands, printLogs);
@@ -233,7 +233,7 @@ export const installOrUpdate = async (packageManager: PackageManagerType, depend
}
}
if (typeOfAction === "update") {
if (!dependenciesToUpdate.length) {return;}
if (!dependenciesToUpdate.length) { return; }
const commands = [...updateCommand, ...dependenciesToUpdate];
await runCommand(runner, commands, printLogs);
}
+1 -1
View File
@@ -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,
+6
View File
@@ -1,5 +1,11 @@
# @thirdweb-dev/contracts-js
## 1.3.7
### Patch Changes
- [#1241](https://github.com/thirdweb-dev/js/pull/1241) [`9af346ee`](https://github.com/thirdweb-dev/js/commit/9af346eeada1037be27c8d3c9e1777f7be11a8ea) Thanks [@nkrishang](https://github.com/nkrishang)! - Use fn getAllAccounts instead of event logs AccountCreated
## 1.3.6
### Patch Changes
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@thirdweb-dev/contracts-js",
"version": "1.3.6",
"version": "1.3.7",
"main": "dist/thirdweb-dev-contracts-js.cjs.js",
"module": "dist/thirdweb-dev-contracts-js.esm.js",
"browser": {
@@ -10,7 +10,7 @@
"license": "Apache-2.0",
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/contracts-js",
"dependencies": {
"@thirdweb-dev/contracts": "3.5.8"
"@thirdweb-dev/contracts": "3.5.9"
},
"devDependencies": {
"@babel/preset-env": "^7.18.10",
+56
View File
@@ -1,5 +1,61 @@
# @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
- [#1227](https://github.com/thirdweb-dev/js/pull/1227) [`06ca1c40`](https://github.com/thirdweb-dev/js/commit/06ca1c407dfee9d3d1fdaed1b6223ad0f9b8857b) Thanks [@nkrishang](https://github.com/nkrishang)! - Add react hooks for smart wallet
- [#1248](https://github.com/thirdweb-dev/js/pull/1248) [`620e89dc`](https://github.com/thirdweb-dev/js/commit/620e89dc25c91557e2164a602c7aedd733525087) Thanks [@nachoiacovino](https://github.com/nachoiacovino)! - Export account hooks
- [#1253](https://github.com/thirdweb-dev/js/pull/1253) [`ad7dae3b`](https://github.com/thirdweb-dev/js/commit/ad7dae3b163e61c7a6eb57f654885a7fdaa4cbb6) Thanks [@rattrayd11](https://github.com/rattrayd11)! - Stop using useActiveChain deprecated hook
- Updated dependencies [[`ef4cb092`](https://github.com/thirdweb-dev/js/commit/ef4cb092192c58c9b292b29590b888f45f9fd23d), [`ac3e019c`](https://github.com/thirdweb-dev/js/commit/ac3e019cd1776dbdb0d06b213420ad17586f678e), [`30ac3aef`](https://github.com/thirdweb-dev/js/commit/30ac3aef840bde51a61acf786c709cffd3c47354), [`3c5dc480`](https://github.com/thirdweb-dev/js/commit/3c5dc4804abc56b933ec45e9e1da11eb182296cc), [`620e89dc`](https://github.com/thirdweb-dev/js/commit/620e89dc25c91557e2164a602c7aedd733525087), [`0fd8aa04`](https://github.com/thirdweb-dev/js/commit/0fd8aa04a9424497758d13a51a72363edcc30e19)]:
- @thirdweb-dev/sdk@3.10.26
- @thirdweb-dev/wallets@1.0.0
- @thirdweb-dev/chains@0.1.25
## 3.14.3
### Patch Changes
- [#1235](https://github.com/thirdweb-dev/js/pull/1235) [`1d76334d`](https://github.com/thirdweb-dev/js/commit/1d76334dd3884703629835422f241d2825128f6f) Thanks [@nachoiacovino](https://github.com/nachoiacovino)! - Fix required type for address on useSmartWalletsForAddress
- [#1241](https://github.com/thirdweb-dev/js/pull/1241) [`9af346ee`](https://github.com/thirdweb-dev/js/commit/9af346eeada1037be27c8d3c9e1777f7be11a8ea) Thanks [@nkrishang](https://github.com/nkrishang)! - Use fn getAllAccounts instead of event logs AccountCreated
- Updated dependencies [[`536b0f12`](https://github.com/thirdweb-dev/js/commit/536b0f1240ab446aac22cf547a4e09e73ee6bf7b), [`b626782b`](https://github.com/thirdweb-dev/js/commit/b626782b0e8c6b76673472d3aee1c802dfb11b5f), [`d498c79a`](https://github.com/thirdweb-dev/js/commit/d498c79a911d478077dfb8a2490eb1bf91523186), [`0c5b03b8`](https://github.com/thirdweb-dev/js/commit/0c5b03b8d6cc6a4e69bb2a4647d3626e69f1283c), [`9af346ee`](https://github.com/thirdweb-dev/js/commit/9af346eeada1037be27c8d3c9e1777f7be11a8ea)]:
- @thirdweb-dev/wallets@0.3.3
- @thirdweb-dev/sdk@3.10.25
- @thirdweb-dev/storage@1.1.5
- @thirdweb-dev/chains@0.1.24
## 3.14.2
### Patch Changes
+1 -5
View File
@@ -1,6 +1,6 @@
{
"name": "@thirdweb-dev/react-core",
"version": "3.14.2",
"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",
@@ -113,10 +113,6 @@
"ethers": ">=5.5.1",
"react": ">=18.0.0"
},
"resolutions": {
"ansi-regex": "^6.0.1",
"typescript": "^4.6.2"
},
"peerDependenciesMeta": {
"@solana/web3.js": {
"optional": true
@@ -1,6 +1,6 @@
import { Chain, defaultChains } from "@thirdweb-dev/chains";
import { useCallback, useState } from "react";
import { useActiveChain, useChainId } from "../../evm/hooks/wallet";
import { useChain, useChainId } from "../../evm/hooks/wallet";
import { useSupportedChains } from "../../evm/hooks/useSupportedChains";
import { useSwitchChain, useWallet } from "./wallet-hooks";
import { assertWindowEthereum, walletIds } from "@thirdweb-dev/wallets";
@@ -29,7 +29,7 @@ type NetworkMetadata = {
/**
*
* @deprecated - use `useActiveChain`, `useSwitchChain`, `useChainId` instead
* @deprecated - use `useChain`, `useSwitchChain`, `useChainId` instead
*
* Hook for getting metadata about the network the current wallet is connected to and switching networks
*
@@ -55,7 +55,7 @@ type NetworkMetadata = {
* @public
*/
export function useNetwork(): [NetworkMetadata, SwitchNetwork | undefined] {
const chain = useActiveChain();
const chain = useChain();
const chainId = useChainId();
const switchChain = useSwitchChain();
const supportedChains = useSupportedChains();
@@ -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,
),
},
);
}
@@ -0,0 +1,125 @@
import type { providers } from "ethers";
import {
RequiredParam,
requiredParamInvariant,
} from "../../../core/query-utils/required-param";
import { useSDKChainId } from "../../providers/thirdweb-sdk-provider";
import {
cacheKeys,
invalidateContractAndBalances,
} from "../../utils/cache-keys";
import { useQueryWithNetwork } from "../query-utils/useQueryWithNetwork";
import {
useMutation,
UseMutationResult,
useQueryClient,
UseQueryResult,
} from "@tanstack/react-query";
import type {
SignerWithRestrictions,
SignerWithRestrictionsBatchInput,
SmartContract,
} from "@thirdweb-dev/sdk";
import invariant from "tiny-invariant";
/** **********************/
/** READ HOOKS **/
/** **********************/
/**
* Get all accounts
*
* @example
* ```javascript
* const { data: accounts, isLoading, error } = useAccountSigners(contract);
* ```
*
* @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 useAccountSigners(
contract: RequiredParam<SmartContract>,
): UseQueryResult<SignerWithRestrictions[]> {
const contractAddress = contract?.getAddress();
return useQueryWithNetwork(
cacheKeys.contract.account.signers(contractAddress),
() => {
requiredParamInvariant(contract, "No Contract instance provided");
invariant(
contract.account.getSignersWithRestrictions,
"Contract instance does not support contract.account.getSignersWithRestrictions",
);
return contract.account.getSignersWithRestrictions();
},
{ enabled: !!contract },
);
}
/** **********************/
/** WRITE HOOKS **/
/** **********************/
/**
* Set the account's entire snapshot of permissions
*
* @example
* ```jsx
* const Component = () => {
* const { contract } = useContract("{{contract_address}}");
* const {
* mutate: setAccountSigners,
* isLoading,
* error,
* } = useSetAccountSigners(contract);
*
* if (error) {
* console.error("failed to set account signers", error);
* }
*
* return (
* <button
* disabled={isLoading}
* onClick={() => setAccountSigners("0x...")}
* >
* Set Account Signers
* </button>
* );
* };
* ```
*
* @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 useSetAccountSigners(
contract: RequiredParam<SmartContract>,
): UseMutationResult<
{ receipt: providers.TransactionReceipt },
unknown,
SignerWithRestrictionsBatchInput,
unknown
> {
const activeChainId = useSDKChainId();
const contractAddress = contract?.getAddress();
const queryClient = useQueryClient();
return useMutation(
async (permissionsSnapshot: SignerWithRestrictionsBatchInput) => {
requiredParamInvariant(contract, "contract is undefined");
return contract.account.setAccess(permissionsSnapshot);
},
{
onSettled: () =>
invalidateContractAndBalances(
queryClient,
contractAddress,
activeChainId,
),
},
);
}
@@ -504,7 +504,7 @@ export function useEnglishAuctionWinningBid(
) {
const contractAddress = contract?.getAddress();
return useQueryWithNetwork(
cacheKeys.contract.marketplace.auction.getWinningBid(
cacheKeys.contract.marketplace.englishAuctions.getWinningBid(
contractAddress,
auctionId,
),
@@ -596,7 +596,7 @@ export function useBidBuffer(
) {
const contractAddress = contract?.getAddress();
return useQueryWithNetwork(
cacheKeys.contract.marketplace.getBidBufferBps(contractAddress),
cacheKeys.contract.marketplace.auction.getBidBufferBps(contractAddress, listingId),
() => {
requiredParamInvariant(contract, "No Contract instance provided");
@@ -647,7 +647,7 @@ export function useMinimumNextBid(
) {
const contractAddress = contract?.getAddress();
return useQueryWithNetwork(
cacheKeys.contract.marketplace.auction.getWinner(
cacheKeys.contract.marketplace.auction.getMinimumNextBid(
contractAddress,
listingId,
),
@@ -1,191 +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, AddressOrEns, 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.getAllWallets,
"Contract instance does not support contract.smartWalletFactory.getAllWallets",
);
return contract.smartWalletFactory.getAllWallets();
},
{ 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: AddressOrEns,
): 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,
),
},
);
}
+9 -6
View File
@@ -194,13 +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";
// account
export { useAccountSigners, useSetAccountSigners } from "./hooks/async/account";
// thirdweb hooks (work as long as at least `<ThirdwebSdkProvider>` is used)
+50 -24
View File
@@ -118,15 +118,25 @@ 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]),
},
account: {
signers: (contractAddress: RequiredParam<ContractAddress>) =>
createContractCacheKey(contractAddress, ["account", "signers"]),
},
app: {
get: (contractAddress: RequiredParam<ContractAddress>) =>
createContractCacheKey(contractAddress, ["appURI"]),
@@ -193,12 +203,8 @@ export const cacheKeys = {
},
},
sharedMetadata: {
get: (
contractAddress: RequiredParam<ContractAddress>,
) =>
createContractCacheKey(
contractAddress
),
get: (contractAddress: RequiredParam<ContractAddress>) =>
createContractCacheKey(contractAddress),
},
drop: {
getAllUnclaimed: (
@@ -273,10 +279,16 @@ export const cacheKeys = {
contractAddress,
params ? ["getActiveListings", params] : ["getActiveListings"],
),
getBidBufferBps: (contractAddress: RequiredParam<ContractAddress>) =>
createContractCacheKey(contractAddress, ["getBidBufferBps"]),
auction: {
getBidBufferBps: (
contractAddress: RequiredParam<ContractAddress>,
listingId: RequiredParam<BigNumberish>,
) =>
createContractCacheKey(contractAddress, [
"auction",
"getBidBufferBps",
{ listingId },
]),
getWinningBid: (
contractAddress: RequiredParam<ContractAddress>,
listingId: RequiredParam<BigNumberish>,
@@ -286,6 +298,15 @@ export const cacheKeys = {
"getWinningBid",
{ listingId },
]),
getMinimumNextBid: (
contractAddress: RequiredParam<ContractAddress>,
listingId: RequiredParam<BigNumberish>,
) =>
createContractCacheKey(contractAddress, [
"auction",
"getMinimumNextBid",
{ listingId },
]),
getWinner: (
contractAddress: RequiredParam<ContractAddress>,
listingId: RequiredParam<BigNumberish>,
@@ -305,8 +326,8 @@ export const cacheKeys = {
createContractCacheKey(
contractAddress,
params
? ["getAllDirectListings", params]
: ["getAllDirectListings"],
? ["directListings", "getAll", params]
: ["directListings", "getAll"],
),
getAllValid: (
contractAddress: RequiredParam<ContractAddress>,
@@ -315,20 +336,22 @@ export const cacheKeys = {
createContractCacheKey(
contractAddress,
params
? ["getAllValidDirectListings", params]
: ["getAllValidDirectListings"],
? ["directListings", "getAllValid", params]
: ["directListings", "getAllValid"],
),
getListing: (
contractAddress: RequiredParam<ContractAddress>,
listingId: RequiredParam<BigNumberish>,
) =>
createContractCacheKey(contractAddress, [
"directListings",
"getListing",
{ listingId },
]),
getTotalCount: (contractAddress: RequiredParam<ContractAddress>) =>
createContractCacheKey(contractAddress, [
"getTotalDirectListingsCount",
"directListings",
"getTotalCount",
]),
},
@@ -340,8 +363,8 @@ export const cacheKeys = {
createContractCacheKey(
contractAddress,
params
? ["getAllEnglishAuctions", params]
: ["getAllEnglishAuctions"],
? ["englishAuctions", "getAll", params]
: ["englishAuctions", "getAll"],
),
getAllValid: (
contractAddress: RequiredParam<ContractAddress>,
@@ -350,14 +373,15 @@ export const cacheKeys = {
createContractCacheKey(
contractAddress,
params
? ["getAllEValidEnglishAuctions", params]
: ["getAllEValidEnglishAuctions"],
? ["englishAuctions", "getAllValid", params]
: ["englishAuctions", "getAllValid"],
),
getAuction: (
contractAddress: RequiredParam<ContractAddress>,
auctionId: RequiredParam<BigNumberish>,
) =>
createContractCacheKey(contractAddress, [
"englishAuctions",
"getAuction",
{ auctionId },
]),
@@ -366,12 +390,14 @@ export const cacheKeys = {
auctionId: RequiredParam<BigNumberish>,
) =>
createContractCacheKey(contractAddress, [
"englishAuctions",
"getWinningBid",
{ auctionId },
]),
getTotalCount: (contractAddress: RequiredParam<ContractAddress>) =>
createContractCacheKey(contractAddress, [
"getTotalEnglishAuctionsCount",
"englishAuctions",
"getTotalCount",
]),
},
},
+10
View File
@@ -1,5 +1,15 @@
# @thirdweb-dev/react-native-compat
## 0.2.26
## 0.2.25
## 0.2.24
## 0.2.23
## 0.2.22
## 0.2.21
## 0.2.20
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "@thirdweb-dev/react-native-compat",
"description": "Shims for Thirdweb in React Native Projects",
"version": "0.2.21",
"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",
+87
View File
@@ -1,5 +1,92 @@
# @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
- [#1215](https://github.com/thirdweb-dev/js/pull/1215) [`3c5dc480`](https://github.com/thirdweb-dev/js/commit/3c5dc4804abc56b933ec45e9e1da11eb182296cc) Thanks [@iketw](https://github.com/iketw)! - Migrate wallets to WCV2 and remove WCV1 support.
Please, check our changelogs for more info: https://blog.thirdweb.com/changelog/
- Updated dependencies [[`ef4cb092`](https://github.com/thirdweb-dev/js/commit/ef4cb092192c58c9b292b29590b888f45f9fd23d), [`06ca1c40`](https://github.com/thirdweb-dev/js/commit/06ca1c407dfee9d3d1fdaed1b6223ad0f9b8857b), [`620e89dc`](https://github.com/thirdweb-dev/js/commit/620e89dc25c91557e2164a602c7aedd733525087), [`ac3e019c`](https://github.com/thirdweb-dev/js/commit/ac3e019cd1776dbdb0d06b213420ad17586f678e), [`30ac3aef`](https://github.com/thirdweb-dev/js/commit/30ac3aef840bde51a61acf786c709cffd3c47354), [`3c5dc480`](https://github.com/thirdweb-dev/js/commit/3c5dc4804abc56b933ec45e9e1da11eb182296cc), [`ad7dae3b`](https://github.com/thirdweb-dev/js/commit/ad7dae3b163e61c7a6eb57f654885a7fdaa4cbb6), [`620e89dc`](https://github.com/thirdweb-dev/js/commit/620e89dc25c91557e2164a602c7aedd733525087), [`0fd8aa04`](https://github.com/thirdweb-dev/js/commit/0fd8aa04a9424497758d13a51a72363edcc30e19)]:
- @thirdweb-dev/sdk@3.10.26
- @thirdweb-dev/react-core@3.14.4
- @thirdweb-dev/wallets@1.0.0
- @thirdweb-dev/chains@0.1.25
## 0.2.22
### Patch Changes
- [#1245](https://github.com/thirdweb-dev/js/pull/1245) [`d9fb134a`](https://github.com/thirdweb-dev/js/commit/d9fb134ad40ae067416625eb43cf3708f87db7b5) Thanks [@iketw](https://github.com/iketw)! - [RN]
- Added the option to import a new wallet in guest mode
- Added a "Request Testnet Funds" option when on testnets
- [#1245](https://github.com/thirdweb-dev/js/pull/1245) [`d9fb134a`](https://github.com/thirdweb-dev/js/commit/d9fb134ad40ae067416625eb43cf3708f87db7b5) Thanks [@iketw](https://github.com/iketw)! - [ReactNative] Export more components for easy development
- IconTextButton
Component that renders an icon and a text inside a button with border:
```javascript
<IconTextButton
mt="xs"
text="Switch Accounts"
icon={<SwitchIcon height={10} width={10} />}
onPress={() => {}}
/>
```
- NetworkButton: Used to render a Network
```javascript
<NetworkButton
chainIconUrl={chain?.icon?.url || ""}
chainName={chain?.name || "Unknown Network"}
onPress={onChangeNetworkPress}
/>
```
- Exported all icons from the assets folder for external use
- Updated dependencies [[`536b0f12`](https://github.com/thirdweb-dev/js/commit/536b0f1240ab446aac22cf547a4e09e73ee6bf7b), [`1d76334d`](https://github.com/thirdweb-dev/js/commit/1d76334dd3884703629835422f241d2825128f6f), [`b626782b`](https://github.com/thirdweb-dev/js/commit/b626782b0e8c6b76673472d3aee1c802dfb11b5f), [`d498c79a`](https://github.com/thirdweb-dev/js/commit/d498c79a911d478077dfb8a2490eb1bf91523186), [`0c5b03b8`](https://github.com/thirdweb-dev/js/commit/0c5b03b8d6cc6a4e69bb2a4647d3626e69f1283c), [`9af346ee`](https://github.com/thirdweb-dev/js/commit/9af346eeada1037be27c8d3c9e1777f7be11a8ea)]:
- @thirdweb-dev/[email protected]
- @thirdweb-dev/[email protected]
- @thirdweb-dev/[email protected]
- @thirdweb-dev/[email protected]
- @thirdweb-dev/[email protected]
## 0.2.21
### Patch Changes
+1 -5
View File
@@ -1,6 +1,6 @@
{
"name": "@thirdweb-dev/react-native",
"version": "0.2.21",
"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",
@@ -44,10 +44,6 @@
"react-native-svg": "^13.8.0",
"tiny-invariant": "^1.2.0"
},
"resolutions": {
"react-native-mmkv": "2.5.1",
"@magic-sdk/provider": "17.2.0"
},
"devDependencies": {
"@babel/core": "^7.19.3",
"@babel/preset-env": "^7.1.6",
@@ -1,7 +1,10 @@
import { ThemeProvider } from "../styles/ThemeProvider";
import { WalletDetailsButton } from "./ConnectWalletDetails/WalletDetailsButton";
import {
ConnectWalletDetailsProps,
WalletDetailsButton,
} from "./ConnectWalletDetails/WalletDetailsButton";
import { useAddress } from "@thirdweb-dev/react-core";
import React, { useEffect, useRef } from "react";
import { useEffect, useRef } from "react";
import { Animated } from "react-native";
import { ConnectWalletButton } from "./ConnectWalletFlow/ConnectWalletButton";
import { ConnectWalletButtonProps } from "./ConnectWalletFlow/ConnectWalletButton";
@@ -10,7 +13,7 @@ export type ConnectWalletProps = {
/**
* render a custom button to display the connected wallet details instead of the default button
*/
detailsButton?: React.ReactElement;
detailsButton?: ConnectWalletDetailsProps["detailsButton"];
} & ConnectWalletButtonProps;
export const ConnectWallet = ({
@@ -1,4 +1,4 @@
import { StyleSheet, View } from "react-native";
import { Linking, StyleSheet, View } from "react-native";
import Box from "../base/Box";
import { Toast } from "../base/Toast";
import { ExportLocalWalletModal } from "./ExportLocalWalletModal";
@@ -22,6 +22,8 @@ import { useModalState } from "../../providers/ui-context-provider";
import { CLOSE_MODAL_STATE, WalletDetailsModal } from "../../utils/modalTypes";
import { useAppTheme } from "../../styles/hooks";
import { LocalWalletImportModal } from "../ConnectWalletFlow/LocalWalletImportModal";
import { IconTextButton } from "../base/IconTextButton";
import MoneyIcon from "../../assets/money";
export const ConnectWalletDetailsModal = () => {
const theme = useAppTheme();
@@ -192,6 +194,18 @@ export const ConnectWalletDetailsModal = () => {
chainName={chain?.name || "Unknown Network"}
onPress={onChangeNetworkPress}
/>
{chain?.testnet && chain?.faucets?.length ? (
<IconTextButton
mt="xs"
text="Request Testnet Funds"
icon={<MoneyIcon height={10} width={10} />}
onPress={() => {
if (chain?.faucets?.[0]) {
Linking.openURL(chain.faucets[0]);
}
}}
/>
) : null}
{getAdditionalActions()}
{addressCopied === true ? (
<Toast text={"Address copied to clipboard"} />
@@ -3,8 +3,7 @@ import BaseButton from "../base/BaseButton";
import { ChainIcon } from "../base/ChainIcon";
import Text from "../base/Text";
import { WalletIcon } from "../base/WalletIcon";
import { useWallet, useBalance } from "@thirdweb-dev/react-core";
import { useActiveChain } from "@thirdweb-dev/react-core/evm";
import { useWallet, useBalance, useChain } from "@thirdweb-dev/react-core";
import { StyleSheet } from "react-native";
import { LocalWallet } from "@thirdweb-dev/wallets";
import { useModalState } from "../../providers/ui-context-provider";
@@ -12,7 +11,7 @@ import Box from "../base/Box";
export type ConnectWalletDetailsProps = {
address: string;
detailsButton?: React.ReactElement;
detailsButton?: React.FC<{ onPress: () => void }>;
};
export const WalletDetailsButton = ({
@@ -20,7 +19,7 @@ export const WalletDetailsButton = ({
detailsButton,
}: ConnectWalletDetailsProps) => {
const activeWallet = useWallet();
const chain = useActiveChain();
const chain = useChain();
const balanceQuery = useBalance();
const { setModalState } = useModalState();
@@ -38,15 +37,15 @@ export const WalletDetailsButton = ({
return (
<>
<BaseButton
backgroundColor="background"
borderColor="border"
style={styles.walletDetails}
onPress={onPress}
>
{detailsButton ? (
detailsButton
) : (
{detailsButton ? (
detailsButton({ onPress })
) : (
<BaseButton
backgroundColor="background"
borderColor="border"
style={styles.walletDetails}
onPress={onPress}
>
<Box flex={1} flexDirection="row" justifyContent="space-between">
<ChainIcon size={32} chainIconUrl={chain?.icon?.url} />
<Box justifyContent="center" alignItems="flex-start">
@@ -70,8 +69,8 @@ export const WalletDetailsButton = ({
iconUri={activeWallet?.getMeta().iconURL || ""}
/>
</Box>
)}
</BaseButton>
</BaseButton>
)}
</>
);
};
-1
View File
@@ -17,7 +17,6 @@ export { localWallet } from "./wallets/wallets/local-wallet";
export { LocalWallet } from "./wallets/wallets/LocalWallet";
export { magicWallet } from "./wallets/wallets/magic-wallet";
export { MagicWallet } from "./wallets/wallets/MagicWallet";
export * from "./wallets/wallets/WalletConnectV1";
export * from "./wallets/wallets/WalletConnectV2";
export type { WCMeta } from "./wallets/types/wc";
@@ -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,52 +0,0 @@
import {
WalletOptions,
WalletConnectV1Options,
WalletConnectV1 as WalletConnectV1Wallets,
} from "@thirdweb-dev/wallets";
import { formatWalletConnectDisplayUri } from "../../utils/uri";
import { Linking } from "react-native";
import { ExtraCoreWalletOptions } from "@thirdweb-dev/react-core";
import { WCMeta } from "../types/wc";
import { createAsyncLocalStorage } from "../../../core/AsyncStorage";
export type WC1Options = Omit<
WalletOptions<WalletConnectV1Options>,
"qrcode" | "walletId"
> &
ExtraCoreWalletOptions & {
walletId: NonNullable<WalletOptions["walletId"]>;
};
export abstract class WalletConnectV1 extends WalletConnectV1Wallets {
constructor(options: WC1Options) {
super({
...options,
walletId: options.walletId,
walletStorage:
options.walletStorage || createAsyncLocalStorage(options.walletId),
qrcode: false,
});
this.on("open_wallet", this._onWCOpenWallet);
this.on("disconnect", () => {
this.removeListener("open_wallet", this._onWCOpenWallet);
});
}
abstract getMeta(): WCMeta;
_onWCOpenWallet(uri?: string) {
const links = this.getMeta().links;
if (uri) {
const fullUrl = formatWalletConnectDisplayUri(uri, links);
Linking.openURL(fullUrl);
} else {
const fullUrl = formatWalletConnectDisplayUri("", links);
Linking.openURL(fullUrl);
}
}
}
@@ -1,9 +1,9 @@
import { walletIds } from "@thirdweb-dev/wallets";
import { WalletOptions, WalletConfig } from "@thirdweb-dev/react-core";
import { WalletConnectV1 } from "./WalletConnectV1";
import { WalletConnectV2 } from "./WalletConnectV2";
import { WCMeta } from "../types/wc";
export class MetaMaskWallet extends WalletConnectV1 {
export class MetaMaskWallet extends WalletConnectV2 {
static id = walletIds.metamask;
static meta = {
name: "MetaMask",
@@ -20,11 +20,17 @@ export class MetaMaskWallet extends WalletConnectV1 {
}
}
export const metamaskWallet = () => {
type MetaMaskWalletConfig = { projectId?: string };
export const metamaskWallet = (config?: MetaMaskWalletConfig) => {
return {
id: MetaMaskWallet.id,
meta: MetaMaskWallet.meta,
create: (options: WalletOptions) =>
new MetaMaskWallet({ ...options, walletId: walletIds.metamask }),
new MetaMaskWallet({
...options,
walletId: walletIds.metamask,
projectId: config?.projectId,
}),
} satisfies WalletConfig;
};
@@ -2,9 +2,9 @@ import {
WalletOptions as WalletOptionsRC,
WalletConfig,
} from "@thirdweb-dev/react-core";
import { WalletConnectV1 } from "./WalletConnectV1";
import { WalletConnectV2 } from "./WalletConnectV2";
export class RainbowWallet extends WalletConnectV1 {
export class RainbowWallet extends WalletConnectV2 {
static id = "rainbow" as const;
static meta = {
name: "Rainbow",
@@ -21,11 +21,17 @@ export class RainbowWallet extends WalletConnectV1 {
}
}
export const rainbowWallet = () => {
type RainbowWalletConfig = { projectId?: string };
export const rainbowWallet = (config?: RainbowWalletConfig) => {
return {
id: RainbowWallet.id,
meta: RainbowWallet.meta,
create: (options: WalletOptionsRC) =>
new RainbowWallet({ ...options, walletId: RainbowWallet.id }),
new RainbowWallet({
...options,
walletId: RainbowWallet.id,
projectId: config?.projectId,
}),
} satisfies WalletConfig;
};
@@ -1,5 +1,5 @@
import { WalletOptions, WalletConfig } from "@thirdweb-dev/react-core";
import { WC2Options, WalletConnectV2 } from "./WalletConnectV2";
import { WalletConnectV2 } from "./WalletConnectV2";
import { WCMeta } from "../types/wc";
export class TrustWallet extends WalletConnectV2 {
@@ -14,10 +14,6 @@ export class TrustWallet extends WalletConnectV2 {
},
};
constructor(options: WC2Options) {
super(options);
}
getMeta(): WCMeta {
return TrustWallet.meta;
}
+97
View File
@@ -1,5 +1,102 @@
# @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
- [#1215](https://github.com/thirdweb-dev/js/pull/1215) [`3c5dc480`](https://github.com/thirdweb-dev/js/commit/3c5dc4804abc56b933ec45e9e1da11eb182296cc) Thanks [@iketw](https://github.com/iketw)! - Migrate wallets to WCV2 and remove WCV1 support.
Please, check our changelogs for more info: https://blog.thirdweb.com/changelog/
- Updated dependencies [[`ef4cb092`](https://github.com/thirdweb-dev/js/commit/ef4cb092192c58c9b292b29590b888f45f9fd23d), [`06ca1c40`](https://github.com/thirdweb-dev/js/commit/06ca1c407dfee9d3d1fdaed1b6223ad0f9b8857b), [`620e89dc`](https://github.com/thirdweb-dev/js/commit/620e89dc25c91557e2164a602c7aedd733525087), [`ac3e019c`](https://github.com/thirdweb-dev/js/commit/ac3e019cd1776dbdb0d06b213420ad17586f678e), [`30ac3aef`](https://github.com/thirdweb-dev/js/commit/30ac3aef840bde51a61acf786c709cffd3c47354), [`3c5dc480`](https://github.com/thirdweb-dev/js/commit/3c5dc4804abc56b933ec45e9e1da11eb182296cc), [`ad7dae3b`](https://github.com/thirdweb-dev/js/commit/ad7dae3b163e61c7a6eb57f654885a7fdaa4cbb6), [`620e89dc`](https://github.com/thirdweb-dev/js/commit/620e89dc25c91557e2164a602c7aedd733525087), [`0fd8aa04`](https://github.com/thirdweb-dev/js/commit/0fd8aa04a9424497758d13a51a72363edcc30e19)]:
- @thirdweb-dev/sdk@3.10.26
- @thirdweb-dev/react-core@3.14.4
- @thirdweb-dev/wallets@1.0.0
- @thirdweb-dev/chains@0.1.25
## 3.14.3
### Patch Changes
- [#1238](https://github.com/thirdweb-dev/js/pull/1238) [`6e1fe6e5`](https://github.com/thirdweb-dev/js/commit/6e1fe6e582d4178884fc1793b330a9e477df5b4d) Thanks [@iketw](https://github.com/iketw)! - '[React] Adds Rainbow and Trust wallets hooks'
```javascript
import { useRainbowWallet, useTrustWallet } from "@thirdweb-dev/react";
const connectWithRainbow = useRainbowWallet();
const connectWithTrust = useTrustWallet();
```
- [#1237](https://github.com/thirdweb-dev/js/pull/1237) [`536b0f12`](https://github.com/thirdweb-dev/js/commit/536b0f1240ab446aac22cf547a4e09e73ee6bf7b) Thanks [@iketw](https://github.com/iketw)! - [React] Add Rainbow Wallet (implementing the WalletConnect wallet)
```javascript
import { ThirdwebProvider, rainbowWallet } from "@thirdweb-dev/react";
const activeChain = "ethereum";
<ThirdwebProvider
activeChain={activeChain}
supportedWallets={[rainbowWallet()]}
>
<App />
</ThirdwebProvider>;
```
- [#1236](https://github.com/thirdweb-dev/js/pull/1236) [`b626782b`](https://github.com/thirdweb-dev/js/commit/b626782b0e8c6b76673472d3aee1c802dfb11b5f) Thanks [@iketw](https://github.com/iketw)! - [Wallets/React] Add Trust Wallet
```javascript
import { ThirdwebProvider, trustWallet } from "@thirdweb-dev/react";
const activeChain = "mumbai";
<ThirdwebProvider
activeChain={activeChain}
autoSwitch={true}
supportedWallets={[trustWallet()]}
>
<App />
</ThirdwebProvider>;
```
- Updated dependencies [[`536b0f12`](https://github.com/thirdweb-dev/js/commit/536b0f1240ab446aac22cf547a4e09e73ee6bf7b), [`1d76334d`](https://github.com/thirdweb-dev/js/commit/1d76334dd3884703629835422f241d2825128f6f), [`b626782b`](https://github.com/thirdweb-dev/js/commit/b626782b0e8c6b76673472d3aee1c802dfb11b5f), [`d498c79a`](https://github.com/thirdweb-dev/js/commit/d498c79a911d478077dfb8a2490eb1bf91523186), [`9af346ee`](https://github.com/thirdweb-dev/js/commit/9af346eeada1037be27c8d3c9e1777f7be11a8ea)]:
- @thirdweb-dev/[email protected]
- @thirdweb-dev/[email protected]
- @thirdweb-dev/[email protected]
- @thirdweb-dev/[email protected]
## 3.14.2
### Patch Changes
+1 -5
View File
@@ -1,6 +1,6 @@
{
"name": "@thirdweb-dev/react",
"version": "3.14.2",
"version": "3.14.7",
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/react",
"author": "thirdweb eng <[email protected]>",
"license": "Apache-2.0",
@@ -153,10 +153,6 @@
"react": ">=18.0.0",
"react-dom": ">=18.0.0"
},
"resolutions": {
"ansi-regex": "^6.0.1",
"typescript": "^4.6.2"
},
"peerDependenciesMeta": {
"@solana/wallet-adapter-base": {
"optional": true
@@ -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"
);
@@ -0,0 +1,15 @@
import { useConnect } from "@thirdweb-dev/react-core";
import { useCallback } from "react";
export function useRainbowWallet() {
const connect = useConnect();
return useCallback(
async (connectOptions?: { chainId?: number }) => {
const { rainbowWallet } = await import(
"../../../wallet/wallets/rainbow/RainbowWallet"
);
return connect(rainbowWallet(), connectOptions);
},
[connect],
);
}
@@ -0,0 +1,15 @@
import { useConnect } from "@thirdweb-dev/react-core";
import { useCallback } from "react";
export function useTrustWallet() {
const connect = useConnect();
return useCallback(
async (connectOptions?: { chainId?: number }) => {
const { trustWallet } = await import(
"../../../wallet/wallets/trustWallet/TrustWallet"
);
return connect(trustWallet(), connectOptions);
},
[connect],
);
}
+2
View File
@@ -20,6 +20,8 @@ export { ThirdwebProvider } from "./providers/thirdweb-provider";
export { useInstalledWallets } from "../wallet/hooks/useInstalledWallets";
// wallet connection hooks
export { useRainbowWallet } from "./hooks/wallets/useRainbowWallet";
export { useTrustWallet } from "./hooks/wallets/useTrustWallet";
export { useMetamask } from "./hooks/wallets/useMetamask";
export { useCoinbaseWallet } from "./hooks/wallets/useCoinbaseWallet";
export { useFrameWallet } from "./hooks/wallets/useFrame";
@@ -18,15 +18,15 @@ interface ThirdwebProviderProps<TChains extends Chain[]>
"createWalletStorage" | "supportedWallets"
> {
/**
* Wallets that will be supported by the dApp
* @defaultValue [metamaskWallet(), coinbaseWallet(), walletConnectV1()]
* Wallets supported by the dApp
* @defaultValue `[ metamaskWallet(), coinbaseWallet(), walletConnect() ]`
*
* @example
* ```jsx
* import { metamaskWallet, coinbaseWallet, walletConnectV1 } from "@thirdweb-dev/react";
* import { metamaskWallet, coinbaseWallet, walletConnect } from "@thirdweb-dev/react";
*
* <ThirdwebProvider
* supportedWallets={[metamaskWallet(), coinbaseWallet(), walletConnectV1()]}
* supportedWallets={[metamaskWallet(), coinbaseWallet(), walletConnect()]}
* />
* ```
*/
+2
View File
@@ -4,7 +4,9 @@ export { coinbaseWallet } from "./wallet/wallets/coinbase/coinbaseWallet";
export { frameWallet } from "./wallet/wallets/frame/frameWallet";
export { metamaskWallet } from "./wallet/wallets/metamask/metamaskWallet";
export { paperWallet } from "./wallet/wallets/paperWallet";
export { rainbowWallet } from "./wallet/wallets/rainbow/RainbowWallet";
export { safeWallet } from "./wallet/wallets/safe/safeWallet";
export { trustWallet } from "./wallet/wallets/trustWallet/TrustWallet";
export { walletConnect } from "./wallet/wallets/walletConnect";
export { walletConnectV1 } from "./wallet/wallets/walletConnectV1";
export { smartWallet } from "./wallet/wallets/smartWallet/smartWallet";
@@ -385,6 +385,17 @@ const NetworkList = /* @__PURE__ */ memo(function NetworkList(props: {
const [switchingChainId, setSwitchingChainId] = useState(-1);
const [errorSwitchingChainId, setErrorSwitchingChainId] = useState(-1);
const close = props.close;
useEffect(() => {
// if switching and switched successfully - close modal
if (switchingChainId !== -1 && activeChainId === switchingChainId) {
if (close) {
close();
}
}
}, [switchingChainId, close, activeChainId]);
const handleSwitch = async (chain: Chain) => {
setErrorSwitchingChainId(-1);
setSwitchingChainId(chain.chainId);
@@ -3,19 +3,22 @@ import { assertWindowEthereum } from "@thirdweb-dev/wallets";
export function useInstalledWallets() {
let isMetamaskInstalled = false;
let isCoinbaseWalletInstalled = 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;
!!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,
return {
metamask: isMetamaskInstalled,
coinbaseWallet: isCoinbaseWalletInstalled,
trustWallet: isTrustWalletInstalled,
zerionWallet: isZerionWalletInstalled,
};
return installedWallets;
}
@@ -1,10 +1,10 @@
import { WalletConfig } from "@thirdweb-dev/react-core";
import { coinbaseWallet } from "./coinbase/coinbaseWallet";
import { metamaskWallet } from "./metamask/metamaskWallet";
import { walletConnectV1 } from "./walletConnectV1";
import { walletConnect } from "./walletConnect";
export const defaultWallets: WalletConfig<any>[] = /* @__PURE__ */ (() => [
metamaskWallet(),
coinbaseWallet(),
walletConnectV1(),
walletConnect(),
])();
@@ -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";
}
@@ -2,12 +2,28 @@ import type { WalletOptions, WalletConfig } from "@thirdweb-dev/react-core";
import { MetaMaskWallet, assertWindowEthereum } from "@thirdweb-dev/wallets";
import { MetamaskConnectUI } from "./MetamaskConnectUI";
export const metamaskWallet = (): WalletConfig<MetaMaskWallet> => {
type MetamaskWalletOptions = {
/**
* When connecting MetaMask using the QR Code - Wallet Connect connector is used which requires a project id.
* This project id is Your project’s unique identifier for wallet connect that can be obtained at cloud.walletconnect.com.
*
* https://docs.walletconnect.com/2.0/web3modal/options#projectid-required
*/
projectId?: string;
};
export const metamaskWallet = (
options?: MetamaskWalletOptions,
): WalletConfig<MetaMaskWallet> => {
return {
id: MetaMaskWallet.id,
meta: MetaMaskWallet.meta,
create: (options: WalletOptions) => {
return new MetaMaskWallet({ ...options, qrcode: false });
create: (walletOptions: WalletOptions) => {
return new MetaMaskWallet({
...walletOptions,
projectId: options?.projectId,
qrcode: false,
});
},
connectUI: MetamaskConnectUI,
isInstalled() {
@@ -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) {
@@ -0,0 +1,74 @@
import { ConnectUIProps, useConnect } from "@thirdweb-dev/react-core";
import { WalletConnect } from "@thirdweb-dev/wallets";
import { useEffect, useRef, useState } from "react";
import { isMobile } from "../../../evm/utils/isMobile";
import { ConnectingScreen } from "../../ConnectWallet/screens/ConnectingScreen";
import { GetStartedScreen } from "../../ConnectWallet/screens/GetStartedScreen";
import { RainbowScan } from "./RainbowScan";
export const RainbowConnectUI = (props: ConnectUIProps<WalletConnect>) => {
const [screen, setScreen] = useState<
"connecting" | "scanning" | "get-started"
>("connecting");
const { walletConfig, close } = props;
const connect = useConnect();
const { goBack } = props;
const connectPrompted = useRef(false);
useEffect(() => {
if (connectPrompted.current) {
return;
}
// if loading
(async () => {
// on mobile, open rainbow app link
if (isMobile()) {
window.open("https://rnbwapp.com");
} else {
// on desktop, show the rainbow scan qr code
setScreen("scanning");
}
})();
}, [walletConfig, close, connect, goBack]);
if (screen === "connecting") {
return (
<ConnectingScreen
onBack={props.goBack}
walletName={walletConfig.meta.name}
walletIconURL={walletConfig.meta.iconURL}
supportLink="https://rainbow.me/"
/>
);
}
if (screen === "get-started") {
return (
<GetStartedScreen
walletIconURL={walletConfig.meta.iconURL}
walletName={walletConfig.meta.name}
chromeExtensionLink={walletConfig.meta.urls?.chrome}
googlePlayStoreLink={walletConfig.meta.urls?.android}
appleStoreLink={walletConfig.meta.urls?.ios}
onBack={props.goBack}
/>
);
}
if (screen === "scanning") {
return (
<RainbowScan
onBack={props.goBack}
onConnected={close}
onGetStarted={() => {
setScreen("get-started");
}}
walletConfig={walletConfig}
/>
);
}
return null;
};
@@ -0,0 +1,59 @@
import { ScanScreen } from "../../ConnectWallet/screens/ScanScreen";
import {
useCreateWalletInstance,
useWalletContext,
} from "@thirdweb-dev/react-core";
import { useEffect, useRef, useState } from "react";
import type { WalletConnect } from "@thirdweb-dev/wallets";
import type { WalletConfig } from "@thirdweb-dev/react-core";
export const RainbowScan: React.FC<{
onBack: () => void;
onGetStarted: () => void;
onConnected: () => void;
walletConfig: WalletConfig<WalletConnect>;
}> = ({ onBack, onConnected, onGetStarted, walletConfig }) => {
const createInstance = useCreateWalletInstance();
const [qrCodeUri, setQrCodeUri] = useState<string | undefined>();
const { setConnectedWallet, chainToConnect, setConnectionStatus } =
useWalletContext();
const scanStarted = useRef(false);
useEffect(() => {
if (scanStarted.current) {
return;
}
scanStarted.current = true;
const rainbow = createInstance(walletConfig);
setConnectionStatus("connecting");
rainbow.connectWithQrCode({
chainId: chainToConnect?.chainId,
onQrCodeUri(uri) {
setQrCodeUri(uri);
},
onConnected() {
setConnectedWallet(rainbow);
onConnected();
},
});
}, [
createInstance,
setConnectedWallet,
chainToConnect,
onConnected,
walletConfig,
setConnectionStatus,
]);
return (
<ScanScreen
onBack={onBack}
onGetStarted={onGetStarted}
qrCodeUri={qrCodeUri}
walletName={walletConfig.meta.name}
walletIconURL={walletConfig.meta.iconURL}
/>
);
};
@@ -0,0 +1,38 @@
import type { WalletOptions, WalletConfig } from "@thirdweb-dev/react-core";
import { WalletConnect } from "@thirdweb-dev/wallets";
import { RainbowConnectUI } from "./RainbowConnectUI";
type RainbowWalletOptions = {
/**
* When connecting Rainbow using the QR Code - Wallet Connect connector is used which requires a project id.
* This project id is Your project’s unique identifier for wallet connect that can be obtained at cloud.walletconnect.com.
*
* https://docs.walletconnect.com/2.0/web3modal/options#projectid-required
*/
projectId?: string;
};
export const rainbowWallet = (
options?: RainbowWalletOptions,
): WalletConfig<WalletConnect> => {
return {
id: "rainbow",
meta: {
name: "Rainbow Wallet",
iconURL:
"ipfs://QmSZn47p4DVVBfzvg9BAX2EqwnPxkT1YAE7rUnrtd9CybQ/rainbow-logo.png",
},
create: (walletOptions: WalletOptions) => {
return new WalletConnect({
...walletOptions,
walletId: "rainbow",
projectId: options?.projectId,
qrcode: false,
});
},
connectUI: RainbowConnectUI,
isInstalled() {
return false;
},
};
};
@@ -0,0 +1,92 @@
import { ConnectUIProps, useConnect } from "@thirdweb-dev/react-core";
import { TrustWallet } from "@thirdweb-dev/wallets";
import { useEffect, useRef, useState } from "react";
import { isMobile } from "../../../evm/utils/isMobile";
import { ConnectingScreen } from "../../ConnectWallet/screens/ConnectingScreen";
import { GetStartedScreen } from "../../ConnectWallet/screens/GetStartedScreen";
import { TrustScan } from "./TrustScan";
export const TrustConnectUI = (props: ConnectUIProps<TrustWallet>) => {
const [screen, setScreen] = useState<
"connecting" | "scanning" | "get-started"
>("connecting");
const { walletConfig, close } = props;
const connect = useConnect();
const { goBack } = props;
const connectPrompted = useRef(false);
useEffect(() => {
if (connectPrompted.current) {
return;
}
const isInstalled = walletConfig.isInstalled
? walletConfig.isInstalled()
: false;
// if loading
(async () => {
if (isInstalled) {
try {
connectPrompted.current = true;
setScreen("connecting");
await connect(walletConfig);
close();
} catch (e) {
goBack();
}
}
// if trust is not injected
else {
// on mobile, open trust app link
if (isMobile()) {
window.open("https://link.trustwallet.com");
} else {
// on desktop, show the trust scan qr code
setScreen("scanning");
}
}
})();
}, [walletConfig, close, connect, goBack]);
if (screen === "connecting") {
return (
<ConnectingScreen
onBack={props.goBack}
walletName={walletConfig.meta.name}
walletIconURL={walletConfig.meta.iconURL}
supportLink="https://community.trustwallet.com/c/helpcenter/8"
/>
);
}
if (screen === "get-started") {
return (
<GetStartedScreen
walletIconURL={walletConfig.meta.iconURL}
walletName={walletConfig.meta.name}
chromeExtensionLink={walletConfig.meta.urls?.chrome}
googlePlayStoreLink={walletConfig.meta.urls?.android}
appleStoreLink={walletConfig.meta.urls?.ios}
onBack={props.goBack}
/>
);
}
if (screen === "scanning") {
return (
<TrustScan
onBack={props.goBack}
onConnected={close}
onGetStarted={() => {
setScreen("get-started");
}}
walletConfig={walletConfig}
/>
);
}
return null;
};
@@ -0,0 +1,59 @@
import { ScanScreen } from "../../ConnectWallet/screens/ScanScreen";
import {
useCreateWalletInstance,
useWalletContext,
} from "@thirdweb-dev/react-core";
import { useEffect, useRef, useState } from "react";
import type { TrustWallet } from "@thirdweb-dev/wallets";
import type { WalletConfig } from "@thirdweb-dev/react-core";
export const TrustScan: React.FC<{
onBack: () => void;
onGetStarted: () => void;
onConnected: () => void;
walletConfig: WalletConfig<TrustWallet>;
}> = ({ onBack, onConnected, onGetStarted, walletConfig }) => {
const createInstance = useCreateWalletInstance();
const [qrCodeUri, setQrCodeUri] = useState<string | undefined>();
const { setConnectedWallet, chainToConnect, setConnectionStatus } =
useWalletContext();
const scanStarted = useRef(false);
useEffect(() => {
if (scanStarted.current) {
return;
}
scanStarted.current = true;
const trust = createInstance(walletConfig);
setConnectionStatus("connecting");
trust.connectWithQrCode({
chainId: chainToConnect?.chainId,
onQrCodeUri(uri) {
setQrCodeUri(uri);
},
onConnected() {
setConnectedWallet(trust);
onConnected();
},
});
}, [
createInstance,
setConnectedWallet,
chainToConnect,
onConnected,
walletConfig,
setConnectionStatus,
]);
return (
<ScanScreen
onBack={onBack}
onGetStarted={onGetStarted}
qrCodeUri={qrCodeUri}
walletName={walletConfig.meta.name}
walletIconURL={walletConfig.meta.iconURL}
/>
);
};
@@ -0,0 +1,36 @@
import type { WalletOptions, WalletConfig } from "@thirdweb-dev/react-core";
import { TrustWallet, assertWindowEthereum } from "@thirdweb-dev/wallets";
import { TrustConnectUI } from "./TrustConnectUI";
type TrustWalletOptions = {
/**
* When connecting Trust using the QR Code - Wallet Connect connector is used which requires a project id.
* This project id is Your project’s unique identifier for wallet connect that can be obtained at cloud.walletconnect.com.
*
* https://docs.walletconnect.com/2.0/web3modal/options#projectid-required
*/
projectId?: string;
};
export const trustWallet = (
options?: TrustWalletOptions,
): WalletConfig<TrustWallet> => {
return {
id: TrustWallet.id,
meta: TrustWallet.meta,
create: (walletOptions: WalletOptions) => {
return new TrustWallet({
...walletOptions,
projectId: options?.projectId,
qrcode: false,
});
},
connectUI: TrustConnectUI,
isInstalled() {
if (assertWindowEthereum(globalThis.window)) {
return !!globalThis.window.ethereum.isTrust;
}
return false;
},
};
};
@@ -1,12 +1,9 @@
import { WalletConnectV1 } from "@thirdweb-dev/wallets";
import { WalletConfig, WalletOptions } from "@thirdweb-dev/react-core";
import { walletConnect } from "./walletConnect";
export const walletConnectV1 = (): WalletConfig<WalletConnectV1> => {
return {
id: WalletConnectV1.id,
meta: WalletConnectV1.meta,
create(options: WalletOptions) {
return new WalletConnectV1({ ...options, qrcode: true });
},
};
};
/**
* @deprecated Use `walletConnect` instead
*
* The WalletConnect v1.0 protocol has been shut down and no longer works.
* To avoid breaking change, `walletConnectV1` is still available but is an alias of `walletConnect`.
*/
export const walletConnectV1 = walletConnect;
@@ -2,12 +2,28 @@ import type { WalletOptions, WalletConfig } from "@thirdweb-dev/react-core";
import { ZerionWallet, assertWindowEthereum } from "@thirdweb-dev/wallets";
import { ZerionConnectUI } from "./ZerionConnectUI";
export const zerionWallet = (): WalletConfig<ZerionWallet> => {
type ZerionkWalletOptions = {
/**
* When connecting MetaMask using the QR Code - Wallet Connect connector is used which requires a project id.
* This project id is Your project’s unique identifier for wallet connect that can be obtained at cloud.walletconnect.com.
*
* https://docs.walletconnect.com/2.0/web3modal/options#projectid-required
*/
projectId?: string;
};
export const zerionWallet = (
options?: ZerionkWalletOptions,
): WalletConfig<ZerionWallet> => {
return {
id: ZerionWallet.id,
meta: ZerionWallet.meta,
create: (options: WalletOptions) => {
return new ZerionWallet(options);
create: (walletOptions: WalletOptions) => {
return new ZerionWallet({
...walletOptions,
projectId: options?.projectId,
qrcode: false,
});
},
connectUI: ZerionConnectUI,
isInstalled() {
+1
View File
@@ -24,6 +24,7 @@ module.exports = {
files: "./test/**/*",
rules: {
"@typescript-eslint/no-restricted-imports": "off",
"better-tree-shaking/no-top-level-side-effects": "off",
},
},
],
+35
View File
@@ -1,5 +1,40 @@
# @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
- [#1249](https://github.com/thirdweb-dev/js/pull/1249) [`ef4cb092`](https://github.com/thirdweb-dev/js/commit/ef4cb092192c58c9b292b29590b888f45f9fd23d) Thanks [@kumaryash90](https://github.com/kumaryash90)! - Update EIP155 error substrings for any evm deployments
- [#1254](https://github.com/thirdweb-dev/js/pull/1254) [`30ac3aef`](https://github.com/thirdweb-dev/js/commit/30ac3aef840bde51a61acf786c709cffd3c47354) Thanks [@joaquim-verges](https://github.com/joaquim-verges)! - Fetch base64 NFTs
- Updated dependencies [[`620e89dc`](https://github.com/thirdweb-dev/js/commit/620e89dc25c91557e2164a602c7aedd733525087), [`0fd8aa04`](https://github.com/thirdweb-dev/js/commit/0fd8aa04a9424497758d13a51a72363edcc30e19)]:
- @thirdweb-dev/chains@0.1.25
## 3.10.25
### Patch Changes
- [#1233](https://github.com/thirdweb-dev/js/pull/1233) [`d498c79a`](https://github.com/thirdweb-dev/js/commit/d498c79a911d478077dfb8a2490eb1bf91523186) Thanks [@nkrishang](https://github.com/nkrishang)! - Fix smartWalletFactory.getAllEvents
- [#1241](https://github.com/thirdweb-dev/js/pull/1241) [`9af346ee`](https://github.com/thirdweb-dev/js/commit/9af346eeada1037be27c8d3c9e1777f7be11a8ea) Thanks [@nkrishang](https://github.com/nkrishang)! - Use fn getAllAccounts instead of event logs AccountCreated
- Updated dependencies [[`0c5b03b8`](https://github.com/thirdweb-dev/js/commit/0c5b03b8d6cc6a4e69bb2a4647d3626e69f1283c), [`9af346ee`](https://github.com/thirdweb-dev/js/commit/9af346eeada1037be27c8d3c9e1777f7be11a8ea)]:
- @thirdweb-dev/storage@1.1.5
- @thirdweb-dev/contracts-js@1.3.7
- @thirdweb-dev/chains@0.1.24
## 3.10.24
### Patch Changes
+1 -7
View File
@@ -1,6 +1,6 @@
{
"name": "@thirdweb-dev/sdk",
"version": "3.10.24",
"version": "3.10.27",
"description": "The main thirdweb SDK.",
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/sdk",
"license": "Apache-2.0",
@@ -197,12 +197,6 @@
"yaml": "^2.1.1",
"zod": "^3.20.2"
},
"resolutions": {
"bn.js": "^5.2.1",
"nanoid": "^3.1.31",
"typescript": "^4.6.2",
"@microsoft/tsdoc": "^0.14.1"
},
"bugs": {
"url": "https://github.com/thirdweb-dev/js/issues"
},
@@ -10,6 +10,8 @@ export const ERROR_SUBSTRINGS = [
"recovered sender mismatch",
"transaction hash mismatch",
"chainid no support",
"chainid (0)",
"chainid(0)",
];
export const ERROR_SUBSTRINGS_COMPOSITE = [
@@ -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(
+16
View File
@@ -46,6 +46,22 @@ export async function fetchTokenMetadata(
tokenUri: string,
storage: ThirdwebStorage,
): Promise<NFTMetadata> {
// check for base64 encoded JSON
if (
tokenUri.startsWith("data:application/json;base64") &&
typeof Buffer !== "undefined"
) {
const base64 = tokenUri.split(",")[1];
const jsonMetadata = JSON.parse(
Buffer.from(base64, "base64").toString("utf-8"),
);
return CommonNFTOutput.parse({
...jsonMetadata,
id: BigNumber.from(tokenId).toString(),
uri: tokenUri,
});
}
// handle dynamic id URIs (2 possible formats)
const parsedUri = tokenUri.replace(
"{id}",
utils.hexZeroPad(BigNumber.from(tokenId).toHexString(), 32).slice(2),
@@ -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;
}
@@ -0,0 +1,191 @@
import type { IAccountFactory } from "@thirdweb-dev/contracts-js";
import { DetectableFeature } from "../interfaces/DetectableFeature";
import { FEATURE_ACCOUNT_FACTORY } from "../../constants/thirdweb-features";
import { ContractEvents } from "./contract-events";
import { ContractWrapper } from "./contract-wrapper";
import { buildTransactionFunction } from "../../common/transactions";
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/account";
import { isContractDeployed } from "../../common/any-evm-utils/isContractDeployed";
export class AccountFactory<TContract extends IAccountFactory>
implements DetectableFeature
{
featureName = FEATURE_ACCOUNT_FACTORY.name;
private contractWrapper: ContractWrapper<IAccountFactory>;
// utilities
public events: ContractEvents<IAccountFactory>;
constructor(contractWrapper: ContractWrapper<TContract>) {
this.contractWrapper = contractWrapper;
this.events = new ContractEvents(this.contractWrapper);
}
getAddress(): string {
return this.contractWrapper.readContract.address;
}
/*********************************
* READ FUNCTIONS
*******************************/
/**
* Get the deterministic address of the account that will be created
*
* @example
* ```javascript
* const accountAddress = await contract.accountFactory.predictAccountAddress(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 AccountFactory
*/
public async predictAccountAddress(
admin: string,
extraData?: BytesLike,
): Promise<string> {
let data: BytesLike = utils.toUtf8Bytes("");
if (extraData) {
data = extraData;
}
return this.contractWrapper.readContract.getAddress(admin, data);
}
/**
* Get all signers who have authority on the given account
*
* @example
* ```javascript
* const allSigners = await contract.accountFactory.getAssociatedSigners(admin);
* ```
* @param account - The account address.
* @returns all signers who have authority on the given account.
*
* @twfeature AccountFactory
*/
public async getAssociatedSigners(account: string): Promise<string[]> {
return this.contractWrapper.readContract.getSignersOfAccount(account);
}
/**
* Get all accounts on which the given signer has authority
*
* @example
* ```javascript
* const allAccounts = await contract.accountFactory.getAssociatedAccounts(admin);
* ```
* @param signer - The account address.
* @returns all accounts on which the given signer has authority.
*
* @twfeature AccountFactory
*/
public async getAssociatedAccounts(signer: string): Promise<string[]> {
return this.contractWrapper.readContract.getAccountsOfSigner(signer);
}
/**
* Get all accounts
*
* @example
* ```javascript
* const allAccounts = await contract.accountFactory.getAllAccounts();
* ```
*
* @returns all accounts created via the account factory.
*
* @twfeature AccountFactory
*/
public async getAllAccounts(): Promise<AccountEvent[]> {
const allAccounts =
await this.contractWrapper.readContract.getAllAccounts();
/**
* Note: an account can have multiple admins. In this function, we only return the first signer associated with
* the account. This should be the admin that created the account, unless this admin has lost their admin status.
*/
return await Promise.all(
allAccounts.map(async (account) => {
const assosiatedSigners = await this.getAssociatedSigners(account);
const admin = assosiatedSigners[0];
return { account, admin };
}),
);
}
/**
* Check if a account 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 isAccountDeployed(
admin: string,
extraData?: BytesLike,
): Promise<boolean> {
const addr = await this.predictAccountAddress(admin, extraData);
return isContractDeployed(addr, this.contractWrapper.getProvider());
}
/*********************************
* WRITE FUNCTIONS
*******************************/
/**
* Create a account
*
* @remarks Create a account for an admin. The admin will have complete authority over the account.
*
* @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.accountFactory.createAccount(admin, extraData);
* const receipt = tx.receipt();
* const accountAddress = tx.address;
* ```
*
* @twfeature AccountFactory
*/
createAccount = /* @__PURE__ */ buildTransactionFunction(
async (
accountAdmin: string,
extraData?: BytesLike,
): Promise<Transaction<TransactionResultWithAddress>> => {
if (await this.isAccountDeployed(accountAdmin, extraData)) {
throw new Error(`Account already deployed for admin: ${accountAdmin}`);
}
let data: BytesLike = utils.toUtf8Bytes("");
if (extraData) {
data = extraData;
}
return Transaction.fromContractWrapper({
contractWrapper: this.contractWrapper,
method: "createAccount",
args: [accountAdmin, data],
parse: (receipt) => {
const event = this.contractWrapper.parseLogs<AccountCreatedEvent>(
"AccountCreated",
receipt?.logs,
);
return {
address: event[0].args.account,
receipt,
};
},
});
},
);
}
@@ -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";
@@ -18,18 +18,19 @@ import {
SignerWithRestrictions,
AccessRestrictionsInput,
AccessRestrictionsSchema,
SignerWithRestrictionsBatchInput,
} from "../../types";
import invariant from "tiny-invariant";
import { buildTransactionFunction } from "../../common/transactions";
import { SmartWalletFactory } from "./smart-wallet-factory";
import { resolveOrGenerateId } from "../../common/signature-minting";
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 =
@@ -47,6 +48,20 @@ export class SmartWallet<TContract extends IAccountCore>
* HELPER FUNCTIONS
********************************/
private hasDuplicateSigners(
signers: SignerWithRestrictionsBatchInput,
): boolean {
const encounteredSigners = new Set();
return signers
.map((item) => item.signer)
.some((signer) => {
const isDuplicate = encounteredSigners.has(signer);
encounteredSigners.add(signer);
return isDuplicate;
});
}
/**
* Format the access restrictions for a given role
*
@@ -72,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
@@ -122,12 +137,12 @@ 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
*
*/
private async getFactory(): Promise<SmartWalletFactory<IAccountFactory>> {
private async getFactory(): Promise<ContractWrapper<IAccountFactory>> {
// Get factory.
const chainId = await this.contractWrapper.getChainID();
const factoryAddress = await this.getFactoryAddress();
@@ -137,7 +152,8 @@ export class SmartWallet<TContract extends IAccountCore>
IAccountFactoryAbi,
this.contractWrapper.options,
);
return new SmartWalletFactory(wrapper);
wrapper.updateSignerOrProvider(this.contractWrapper.getSigner() as Signer);
return wrapper;
}
/*********************************
@@ -145,16 +161,35 @@ export class SmartWallet<TContract extends IAccountCore>
********************************/
/**
* Get the restrictions under which a given signer can use the smart wallet.
* Get whether a signer is an admin on the account.
*
* @example
* ```javascript
* const restrictionsForSigner = await contract.smartWallet.getAccessRestrictions(signer);
* const isAdmin = await contract.account.isAdmin(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 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);
return await this.contractWrapper.readContract.isAdmin(
resolvedSignerAddress,
);
}
/**
* Get the restrictions under which a given signer can use the account.
*
* @example
* ```javascript
* const restrictionsForSigner = await contract.account.getAccessRestrictions(signer);
* ```
* @param signer - The address of a signer of the account.
* @returns the restrictions under which a given signer can use the account.
*
* @twfeature Account
*/
public async getAccessRestrictions(
signerAddress: AddressOrEns,
@@ -168,35 +203,36 @@ export class SmartWallet<TContract extends IAccountCore>
}
/**
* 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();
}
/**
* Get all signers (admin or non-admin) of the smart wallet, along with their access restrictions.
* Get all signers with their access restrictions
*
* @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.
const factory = await this.getFactory();
const signers: string[] = await factory.getAssociatedSigners(
const contract = await this.getFactory();
const signers: string[] = await contract.readContract.getSignersOfAccount(
this.getAddress(),
);
@@ -214,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> => {
@@ -240,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> => {
@@ -266,20 +302,20 @@ export class SmartWallet<TContract extends IAccountCore>
);
/**
* Grant an address access to the smart wallet with certain 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 (
@@ -312,8 +348,9 @@ export class SmartWallet<TContract extends IAccountCore>
const roleRestrictions: IAccountPermissions.RoleRestrictionsStruct = {
role,
approvedTargets: parsedRestrictions.approvedCallTargets,
maxValuePerTransaction:
maxValuePerTransaction: utils.parseEther(
parsedRestrictions.nativeTokenLimitPerTransaction,
),
startTimestamp: parsedRestrictions.startDate,
endTimestamp: parsedRestrictions.expirationDate,
};
@@ -358,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 (
@@ -407,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 (
@@ -459,20 +496,20 @@ export class SmartWallet<TContract extends IAccountCore>
);
/**
* Update an address' access to 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 (
@@ -497,8 +534,9 @@ export class SmartWallet<TContract extends IAccountCore>
const roleRestrictions: IAccountPermissions.RoleRestrictionsStruct = {
role: currentRole,
approvedTargets: parsedRestrictions.approvedCallTargets,
maxValuePerTransaction:
maxValuePerTransaction: utils.parseEther(
parsedRestrictions.nativeTokenLimitPerTransaction,
),
startTimestamp: parsedRestrictions.startDate,
endTimestamp: parsedRestrictions.expirationDate,
};
@@ -512,19 +550,19 @@ export class SmartWallet<TContract extends IAccountCore>
);
/**
* Revoke an address' access 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> => {
@@ -560,4 +598,204 @@ export class SmartWallet<TContract extends IAccountCore>
});
},
);
/**
* Set the account's entire snapshot of permissions
*
* @remarks Sets the account's entire snapshot of permissions.
*
* @param permissionsSnapshot - the snapshot to set as the account's entire permission snapshot.
*
* @example
* ```javascript
* const tx = await contract.account.setAccess(permissionsSnapshot);
* const receipt = tx.receipt();
* ```
*
* @twfeature Account
*/
setAccess = /* @__PURE__ */ buildTransactionFunction(
async (
permissionsSnapshot: SignerWithRestrictionsBatchInput,
): Promise<Transaction> => {
/**
* All cases
*
* - Add new admin :check:
* - Remove current admin :check:
* - Add new scoped :check:
* - Remove current scoped :check:
* - Update current scoped :check:
* - Current admin -> new scoped :check:
* - Current scoped -> new admin :check:
**/
// No duplicate signers in input!
if (this.hasDuplicateSigners(permissionsSnapshot)) {
throw new Error("Duplicate signers found in input.");
}
const currentPermissionsSnapshot =
await this.getSignersWithRestrictions();
// Performing a multicall.
const encoded: string[] = [];
// First make all calls related to admin access.
const allCurrentAdmins = currentPermissionsSnapshot
.filter((result) => result.isAdmin)
.map((result) => result.signer);
const allNewAdmins = permissionsSnapshot
.filter((result) => result.isAdmin)
.map((result) => result.signer);
// All remove-admin actions.
for (const currentAdmin of allCurrentAdmins) {
if (!allNewAdmins.includes(currentAdmin)) {
encoded.push(
this.contractWrapper.readContract.interface.encodeFunctionData(
"setAdmin",
[currentAdmin, false],
),
);
}
}
// All add-admin actions.
const toRemoveAsScoped: Record<string, string> = {};
for (const newAdmin of allNewAdmins) {
if (!allCurrentAdmins.includes(newAdmin)) {
const data =
this.contractWrapper.readContract.interface.encodeFunctionData(
"setAdmin",
[newAdmin, true],
);
// If the new admin is already a scoped account, we need to remove them as a scoped account first.
const currentRole = (
await this.contractWrapper.readContract.getRoleRestrictionsForAccount(
newAdmin,
)
).role;
if (currentRole === this.emptyRole) {
encoded.push(data);
} else {
toRemoveAsScoped[newAdmin] = data;
}
}
}
// All scoped actions.
const allCurrentScoped = currentPermissionsSnapshot
.filter((result) => !result.isAdmin)
.map((result) => result.signer);
const allNewScoped = permissionsSnapshot
.filter((result) => !result.isAdmin)
.map((result) => result.signer);
// All remove-scoped actions.
const newAdminsToRemoveAsScoped = Object.keys(toRemoveAsScoped);
for (const currentScoped of allCurrentScoped) {
if (!allNewScoped.includes(currentScoped)) {
const { payload, signature } = await this.generatePayload(
currentScoped,
RoleAction.REVOKE,
);
encoded.push(
this.contractWrapper.readContract.interface.encodeFunctionData(
"changeRole",
[payload, signature],
),
);
if (newAdminsToRemoveAsScoped.includes(currentScoped)) {
encoded.push(toRemoveAsScoped[currentScoped]);
}
}
}
// All add-scoped actions.
for (const newScoped of allNewScoped) {
if (!allCurrentScoped.includes(newScoped)) {
// Derive role for target signer.
const role = utils.solidityKeccak256(["string"], [newScoped]);
const parsedRestrictions = await AccessRestrictionsSchema.parseAsync(
permissionsSnapshot.find((result) => result.signer === newScoped)
?.restrictions,
);
// Get role restrictions struct.
const roleRestrictions: IAccountPermissions.RoleRestrictionsStruct = {
role,
approvedTargets: parsedRestrictions.approvedCallTargets,
maxValuePerTransaction: utils.parseEther(
parsedRestrictions.nativeTokenLimitPerTransaction,
),
startTimestamp: parsedRestrictions.startDate,
endTimestamp: parsedRestrictions.expirationDate,
};
encoded.push(
this.contractWrapper.readContract.interface.encodeFunctionData(
"setRoleRestrictions",
[roleRestrictions],
),
);
const { payload, signature } = await this.generatePayload(
newScoped,
RoleAction.GRANT,
);
encoded.push(
this.contractWrapper.readContract.interface.encodeFunctionData(
"changeRole",
[payload, signature],
),
);
}
}
// All update-scoped actions.
for (const currentScoped of allCurrentScoped) {
if (allNewScoped.includes(currentScoped)) {
// Derive role for target signer.
const role = utils.solidityKeccak256(["string"], [currentScoped]);
const parsedRestrictions = await AccessRestrictionsSchema.parseAsync(
permissionsSnapshot.find(
(result) => result.signer === currentScoped,
)?.restrictions,
);
// Get role restrictions struct.
const roleRestrictions: IAccountPermissions.RoleRestrictionsStruct = {
role,
approvedTargets: parsedRestrictions.approvedCallTargets,
maxValuePerTransaction: utils.parseEther(
parsedRestrictions.nativeTokenLimitPerTransaction,
),
startTimestamp: parsedRestrictions.startDate,
endTimestamp: parsedRestrictions.expirationDate,
};
encoded.push(
this.contractWrapper.readContract.interface.encodeFunctionData(
"setRoleRestrictions",
[roleRestrictions],
),
);
}
}
// Perform multicall
return Transaction.fromContractWrapper({
contractWrapper: this.contractWrapper,
method: "multicall",
args: [encoded],
});
},
);
}
@@ -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> {

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