Compare commits

...
Author SHA1 Message Date
github-actions[bot]GitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>
7faab1c09b Version Packages (#994)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-05-18 11:15:53 -07:00
8bb0a6d874 fix: set ethers@^5 version in peerDeps of @thirdweb/contracts-js (#921)
Co-authored-by: Joaquim Verges <[email protected]>
2023-05-18 04:06:46 +00:00
b1ede491fb [REACT] Add React hook useBuyDirectListing() (#993)
Co-authored-by: Fran Ros <[email protected]>
Co-authored-by: Jarrod Watts <[email protected]>
Co-authored-by: Joaquim Verges <[email protected]>
2023-05-18 04:00:01 +00:00
f674da7b44 Add sepolia as a supported chain for WETH (#987)
Co-authored-by: Nacho Iacovino <[email protected]>
Co-authored-by: Jarrod Watts <[email protected]>
Co-authored-by: Joaquim Verges <[email protected]>
2023-05-18 03:49:27 +00:00
iketwandGitHub 748e3e7856 [RN] clear unusued fields (#1026) 2023-05-17 23:40:59 +00:00
738c0ec6c4 [wallets] Update paper sdk and add new supported chains (#1022)
Co-authored-by: Manan Tank <[email protected]>
2023-05-17 22:35:09 +00:00
Joaquim VergesandGitHub e4356e76d1 [SDK] Update error message when contracts ABIs cannot be resolved, with url to import contract (#1021) 2023-05-17 17:27:38 +00:00
iketwandGitHub 8a0dd070d4 [RN] Adds modalTitle, buttonTitle and detailsButton props to the ConnectWallet component (#1019) 2023-05-17 00:06:39 +00:00
Manan TankandGitHub 39bd963015 Render input for magic and paper wallet using selectUI API (#1015) 2023-05-16 22:41:48 +00:00
84fc3b6fab Add detect-project command to CLI (#926)
Co-authored-by: Jonas Daniels <[email protected]>
2023-05-16 20:05:59 +00:00
Adam MajmudarandGitHub 49ec2d171e [SDK] Add a prepareGaslessRequest function (#983) 2023-05-15 21:27:57 +00:00
Adam MajmudarandGitHub b92aabe450 [Auth] Expose request on user hook (#1013) 2023-05-15 21:21:40 +00:00
Manan TankandGitHub 470e0a144d [react-core] rename ConfiguredWallet -> WalletConfig (#1011) 2023-05-15 19:29:22 +00:00
Manan TankandGitHub b6bb73b34c [react, react-core] Various connect Wallet changes (#1006) 2023-05-15 18:20:45 +00:00
YashandGitHub 9886c858d9 [SDK] Add support for ZKSync Era Testnet (#988) 2023-05-12 22:24:31 +00:00
iketwandGitHub 25de32d45d [RN] Update wcv2 props (#1005) 2023-05-12 15:35:55 +00:00
Manan TankandGitHub d495a4b8a6 [react, wallets] Expose Web3Modal QRModalOptions in WalletConnect v2 (#1002) 2023-05-12 14:53:06 +00:00
Manan TankandGitHub 2b0fb9d22f [react] Fix flaky Coinbase QR code scan (#1001) 2023-05-11 15:12:39 +00:00
e9b69300d1 [SDK] Display plugins on router release page (#713)
Co-authored-by: Jonas Daniels <[email protected]>
2023-05-10 23:18:40 +00:00
Manan TankandGitHub 4f8438335e [react] Connect Wallet improvements (#998) 2023-05-10 22:42:45 +00:00
Manan TankandGitHub c3645c451b Various Connect Wallet changes (#996) 2023-05-10 18:49:58 +00:00
iketwandGitHub 482f6d1b58 [ReactNative] update export wallet modal UI (#995) 2023-05-10 18:05:05 +00:00
Joaquim VergesandGitHub 799d98e862 [SDK] switch type of abi in SmartContract to Abi (#997) 2023-05-10 17:51:01 +00:00
iketwandGitHub 8db78299ea [React/RN] rename useThirdwebWallet to useProviderContext (#989) 2023-05-10 11:44:04 +00:00
github-actions[bot]GitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>
1119f63a47 Version Packages (#991)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-05-09 23:23:42 -07:00
Joaquim VergesandGitHub 32908b7683 [SDK] rename extension detection functions (#992) 2023-05-10 06:03:26 +00:00
Joaquim VergesandGitHub 6a4aab0b8a [Wallets] LocalWalletNode fix + cleanup SmartWallet logs (#990) 2023-05-10 05:15:22 +00:00
217 changed files with 5421 additions and 1733 deletions
+4 -1
View File
@@ -16,4 +16,7 @@ public/dist
yalc.lock
build/
playwright-report/
.vscode/
.vscode/
# Artifacts
packages/cli/artifacts/
+16
View File
@@ -1,5 +1,21 @@
# @thirdweb-dev/auth
## 3.0.19
### Patch Changes
- [#1013](https://github.com/thirdweb-dev/js/pull/1013) [`b92aabe4`](https://github.com/thirdweb-dev/js/commit/b92aabe450f40b248fd1b7533f1d3bc7f8f25288) Thanks [@adam-maj](https://github.com/adam-maj)! - Expose request on onUser hook
- Updated dependencies [[`738c0ec6`](https://github.com/thirdweb-dev/js/commit/738c0ec6c4190aa2252233c1382aed5d982cc7b8), [`d495a4b8`](https://github.com/thirdweb-dev/js/commit/d495a4b8a6e0599e5b4611620f3fded80a411173), [`4f843833`](https://github.com/thirdweb-dev/js/commit/4f8438335e3e3731b67ae271cb34c383832242a0)]:
- @thirdweb-dev/wallets@0.2.20
## 3.0.18
### Patch Changes
- Updated dependencies [[`6a4aab0b`](https://github.com/thirdweb-dev/js/commit/6a4aab0b8a2e0f6ff1b47992a3c1e5426a74f7ff)]:
- @thirdweb-dev/wallets@0.2.19
## 3.0.17
### Patch Changes
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@thirdweb-dev/auth",
"version": "3.0.17",
"version": "3.0.19",
"main": "dist/thirdweb-dev-auth.cjs.js",
"module": "dist/thirdweb-dev-auth.esm.js",
"browser": {
+1 -1
View File
@@ -51,7 +51,7 @@ export async function getUser<
return authenticatedUser;
}
const data = await ctx.callbacks.onUser(authenticatedUser);
const data = await ctx.callbacks.onUser(authenticatedUser, req);
if (!data) {
return authenticatedUser;
}
+1 -1
View File
@@ -56,7 +56,7 @@ export async function getUser<
return authenticatedUser;
}
const data = await ctx.callbacks.onUser(authenticatedUser);
const data = await ctx.callbacks.onUser(authenticatedUser, req);
if (!data) {
return authenticatedUser;
}
+31
View File
@@ -1,5 +1,36 @@
# @thirdweb-dev/chains
## 0.1.16
### Patch Changes
- [#996](https://github.com/thirdweb-dev/js/pull/996) [`c3645c45`](https://github.com/thirdweb-dev/js/commit/c3645c451b5e9a0fcf651fa07eb0e31ebf1882ca) Thanks [@MananTank](https://github.com/MananTank)! - - add `theme` in `ConfiguredWallet.connectUI`'s props - to use theme aware UI for wallets
- add `useWalletConfig` hook to get the `ConfiguredWallet` object for active wallet
- add hooks `useSetConnectedWallet`, `useSetConnectionStatus`
- rename `useActiveChain` to `useChain` - keep the `useActiveChain` also with deprecated tag
- make `useSafe` hook await-able by returning the promise of connect() call
- add hook `useSmartWallet`
- allow rendering custom wallet details button via `<ConnectWallet detailsButton={} />` prop
- Rename "Export" to "Backup" in local wallet UI
- [#1011](https://github.com/thirdweb-dev/js/pull/1011) [`470e0a14`](https://github.com/thirdweb-dev/js/commit/470e0a144db6aa03e7789e231bbdfae43144f0e0) Thanks [@MananTank](https://github.com/MananTank)! - rename ConfiguredWallet to WalletConfig
```diff
- import { ConfiguredWallet } from '@thirdweb-dev/react';
+ import { WalletConfig } from '@thirdweb-dev/react';
```
- [#995](https://github.com/thirdweb-dev/js/pull/995) [`482f6d1b`](https://github.com/thirdweb-dev/js/commit/482f6d1b58ac99b331fc750d3eeb6082556fd526) Thanks [@iketw](https://github.com/iketw)! - [Chains] Update chains
- [#989](https://github.com/thirdweb-dev/js/pull/989) [`8db78299`](https://github.com/thirdweb-dev/js/commit/8db78299ea6cfb51d93b91bb1a351644a83c73d2) Thanks [@iketw](https://github.com/iketw)! - [React/ReactNative] Updated useThirdwebWallet to useWalletContext
## 0.1.15
### Patch Changes
- [#990](https://github.com/thirdweb-dev/js/pull/990) [`6a4aab0b`](https://github.com/thirdweb-dev/js/commit/6a4aab0b8a2e0f6ff1b47992a3c1e5426a74f7ff) Thanks [@joaquim-verges](https://github.com/joaquim-verges)! - updated chains
## 0.1.14
### Patch Changes
+34
View File
@@ -0,0 +1,34 @@
import type { Chain } from "../src/types";
export default {
"name": "Joseon Mainnet",
"chain": "Joseon",
"icon": {
"url": "ipfs://QmQjwcNRCLXU8JBtSkPLUnbWVrpoqbnZVffpJ9Bu8rG34e",
"width": 148,
"height": 148,
"format": "svg"
},
"rpc": [
"https://joseon.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://rpc.modchain.net/blockchain.joseon.com/rpc"
],
"faucets": [],
"nativeCurrency": {
"name": "Joseon Mun",
"symbol": "JSM",
"decimals": 18
},
"infoURL": "https://www.joseon.com/",
"shortName": "mun",
"chainId": 1392,
"networkId": 1392,
"explorers": [
{
"name": "BlockExplorer",
"url": "https://www.blockexplorer.com",
"standard": "EIP3091"
}
],
"testnet": false,
"slug": "joseon"
} as const satisfies Chain;
+34
View File
@@ -0,0 +1,34 @@
import type { Chain } from "../src/types";
export default {
"name": "Genesys Mainnet",
"chain": "Genesys",
"icon": {
"url": "ipfs://bafkreie6nai3yhykcdlsyshn5lbcbyba5y7zwsqg6owcfek2urhoucr6rm",
"width": 800,
"height": 800,
"format": "png"
},
"rpc": [
"https://genesys.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://rpc.genesys.network"
],
"faucets": [],
"nativeCurrency": {
"name": "Genesys",
"symbol": "GSYS",
"decimals": 18
},
"infoURL": "https://www.genesys.network/",
"shortName": "Genesys",
"chainId": 16507,
"networkId": 16507,
"explorers": [
{
"name": "GchainExplorer",
"url": "https://gchainexplorer.genesys.network",
"standard": "EIP3091"
}
],
"testnet": false,
"slug": "genesys"
} as const satisfies Chain;
+1 -1
View File
@@ -4,7 +4,7 @@ export default {
"chain": "IRIShub",
"rpc": [
"https://irishub-testnet.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"http://34.80.202.172:8545"
"https://evmrpc.nyancat.irisnet.org"
],
"features": [
{
+21
View File
@@ -0,0 +1,21 @@
import type { Chain } from "../src/types";
export default {
"name": "Structx Mainnet",
"chain": "utx",
"rpc": [
"https://structx.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://mainnet.structx.io"
],
"faucets": [],
"nativeCurrency": {
"name": "Notes",
"symbol": "utx",
"decimals": 18
},
"infoURL": "https://structx.io",
"shortName": "utx",
"chainId": 208,
"networkId": 208,
"testnet": false,
"slug": "structx"
} as const satisfies Chain;
+42
View File
@@ -0,0 +1,42 @@
import type { Chain } from "../src/types";
export default {
"name": "SOMA Network Testnet",
"chain": "SOMA",
"rpc": [
"https://soma-network-testnet.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://data-testnet-v1.somanetwork.io/"
],
"faucets": [
"https://faucet.somanetwork.io"
],
"nativeCurrency": {
"name": "SMA",
"symbol": "tSMA",
"decimals": 18
},
"infoURL": "https://somanetwork.io",
"shortName": "sma",
"chainId": 2323,
"networkId": 2323,
"icon": {
"url": "ipfs://QmadSU2tcyvuzssDYGJ4rVLag43QLnKwcBerZR2zKLVU2N",
"width": 500,
"height": 500,
"format": "png"
},
"explorers": [
{
"name": "SOMA Testnet Explorer",
"icon": {
"url": "ipfs://QmadSU2tcyvuzssDYGJ4rVLag43QLnKwcBerZR2zKLVU2N",
"width": 500,
"height": 500,
"format": "png"
},
"url": "https://testnet.somascan.io",
"standard": "none"
}
],
"testnet": true,
"slug": "soma-network-testnet"
} as const satisfies Chain;
+34
View File
@@ -0,0 +1,34 @@
import type { Chain } from "../src/types";
export default {
"name": "LaChain",
"chain": "LaChain",
"rpc": [
"https://lachain-lachain.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://rpc1.mainnet.lachain.network",
"https://rpc2.mainnet.lachain.network"
],
"faucets": [],
"nativeCurrency": {
"name": "LaCoin",
"symbol": "LAC",
"decimals": 18
},
"features": [
{
"name": "EIP155"
}
],
"infoURL": "",
"shortName": "lachain",
"chainId": 274,
"networkId": 274,
"explorers": [
{
"name": "LaChain Explorer",
"url": "https://explorer.lachain.network",
"standard": "EIP3091"
}
],
"testnet": false,
"slug": "lachain-lachain"
} as const satisfies Chain;
+36
View File
@@ -0,0 +1,36 @@
import type { Chain } from "../src/types";
export default {
"name": "Razor Skale Chain",
"chain": "Razor Schain",
"icon": {
"url": "ipfs://QmUdwAZJfyKGZnfPGDsCnNvGu123mdd57kTGj1Y3EWVuWK",
"width": 900,
"height": 900,
"format": "png"
},
"rpc": [
"https://razor-skale-chain.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://mainnet.skalenodes.com/v1/turbulent-unique-scheat"
],
"faucets": [
"https://faucet.razorscan.io/"
],
"nativeCurrency": {
"name": "sFuel",
"symbol": "SFUEL",
"decimals": 18
},
"infoURL": "https://razor.network",
"shortName": "razor",
"chainId": 278611351,
"networkId": 278611351,
"explorers": [
{
"name": "turbulent-unique-scheat",
"url": "https://turbulent-unique-scheat.explorer.mainnet.skalenodes.com",
"standard": "EIP3091"
}
],
"testnet": false,
"slug": "razor-skale-chain"
} as const satisfies Chain;
+45
View File
@@ -0,0 +1,45 @@
import type { Chain } from "../src/types";
export default {
"name": "Fastex Chain (Bahamut) Oasis Testnet",
"title": "Bahamut testnet Oasis",
"icon": {
"url": "ipfs://QmSemioP83RXnDWwTZbet8VpwJxcFRboX4B3pcdhLZGodP",
"width": 200,
"height": 200,
"format": "png"
},
"chain": "Fastex Chain (Bahamut)",
"rpc": [
"https://fastex-chain-bahamut-oasis-testnet.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://rpc1.oasis.bahamutchain.com"
],
"features": [
{
"name": "EIP155"
},
{
"name": "EIP1559"
}
],
"faucets": [
"https://faucet.oasis.fastexchain.com"
],
"nativeCurrency": {
"name": "FTN",
"symbol": "FTN",
"decimals": 18
},
"infoURL": "https://fastexchain.com",
"shortName": "Oasis",
"chainId": 4090,
"networkId": 4090,
"explorers": [
{
"name": "blockscout",
"url": "https://oasis.ftnscan.com",
"standard": "none"
}
],
"testnet": true,
"slug": "fastex-chain-bahamut-oasis-testnet"
} as const satisfies Chain;
+1 -1
View File
@@ -22,7 +22,7 @@ export default {
"decimals": 18
},
"infoURL": "https://fastex.com",
"shortName": "ftn",
"shortName": "fastexTestnet",
"chainId": 424242,
"networkId": 424242,
"explorers": [
+36
View File
@@ -0,0 +1,36 @@
import type { Chain } from "../src/types";
export default {
"name": "Worlds Caldera",
"chain": "WCal",
"rpc": [
"https://worlds-caldera.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://worlds-test.calderachain.xyz/http"
],
"faucets": [],
"nativeCurrency": {
"name": "Ether",
"symbol": "ETH",
"decimals": 18
},
"features": [
{
"name": "EIP155"
},
{
"name": "EIP1559"
}
],
"infoURL": "https://caldera.xyz/",
"shortName": "worldscal",
"chainId": 4281033,
"networkId": 4281033,
"icon": {
"url": "ipfs://QmdwQDr6vmBtXmK2TmknkEuZNoaDqTasFdZdu3DRw8b2wt",
"width": 1000,
"height": 1628,
"format": "png"
},
"explorers": [],
"testnet": true,
"slug": "worlds-caldera"
} as const satisfies Chain;
+34
View File
@@ -0,0 +1,34 @@
import type { Chain } from "../src/types";
export default {
"name": "ARZIO Chain",
"chain": "ARZIO",
"icon": {
"url": "ipfs://QmUwqGWGjjQweTprn5LBirAwRjYnteTiFLCVpSNHrfMmSL",
"width": 150,
"height": 150,
"format": "png"
},
"rpc": [
"https://arzio-chain.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://chain-rpc.arzio.co"
],
"faucets": [],
"nativeCurrency": {
"name": "ARZIO",
"symbol": "AZO",
"decimals": 18
},
"infoURL": "https://chain.arzio.co",
"shortName": "arzio",
"chainId": 456,
"networkId": 456,
"explorers": [
{
"name": "ARZIO Scan",
"url": "https://scan.arzio.co",
"standard": "EIP3091"
}
],
"testnet": false,
"slug": "arzio-chain"
} as const satisfies Chain;
+5 -2
View File
@@ -2,7 +2,10 @@ import type { Chain } from "../src/types";
export default {
"name": "Camino C-Chain",
"chain": "CAM",
"rpc": [],
"rpc": [
"https://camino-c-chain.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://api.camino.network/ext/bc/C/rpc"
],
"faucets": [],
"nativeCurrency": {
"name": "Camino",
@@ -22,7 +25,7 @@ export default {
"explorers": [
{
"name": "blockexplorer",
"url": "https://explorer.camino.foundation/mainnet",
"url": "https://suite.camino.network/explorer",
"standard": "none"
}
],
+1 -1
View File
@@ -25,7 +25,7 @@ export default {
"explorers": [
{
"name": "blockexplorer",
"url": "https://explorer.camino.foundation",
"url": "https://suite.camino.network/explorer",
"standard": "none"
}
],
+49
View File
@@ -0,0 +1,49 @@
import type { Chain } from "../src/types";
export default {
"name": "Opside Testnet Pre-Alpha",
"chain": "ETH",
"rpc": [
"https://opside-testnet-pre-alpha.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://pre-alpha-us-http-geth.opside.network",
"https://pre-alpha-hk-http-geth.opside.network"
],
"faucets": [],
"nativeCurrency": {
"name": "IDE Test Token",
"symbol": "IDE",
"decimals": 18
},
"features": [
{
"name": "EIP155"
},
{
"name": "EIP1559"
}
],
"infoURL": "https://opsi.de/",
"shortName": "Opside-Testnet",
"chainId": 51178,
"networkId": 51178,
"icon": {
"url": "ipfs://QmZnE2ygPL2ZGuzHGvFCHmrqxwdurrhz3K1yPnwLzKbgay",
"width": 401,
"height": 400,
"format": "png"
},
"explorers": [
{
"name": "OpsideTestnetInfo",
"url": "https://pre-alpha.opside.info",
"icon": {
"url": "ipfs://QmZnE2ygPL2ZGuzHGvFCHmrqxwdurrhz3K1yPnwLzKbgay",
"width": 401,
"height": 400,
"format": "png"
},
"standard": "EIP3091"
}
],
"testnet": true,
"slug": "opside-testnet-pre-alpha"
} as const satisfies Chain;
+44
View File
@@ -0,0 +1,44 @@
import type { Chain } from "../src/types";
export default {
"name": "Sahara",
"title": "Bahamut mainnet Sahara",
"chain": "Bahamut",
"icon": {
"url": "ipfs://QmSemioP83RXnDWwTZbet8VpwJxcFRboX4B3pcdhLZGodP",
"width": 200,
"height": 200,
"format": "png"
},
"rpc": [
"https://sahara.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://rpc1.sahara.bahamutchain.com",
"https://rpc2.sahara.bahamutchain.com"
],
"features": [
{
"name": "EIP155"
},
{
"name": "EIP1559"
}
],
"faucets": [],
"nativeCurrency": {
"name": "FTN",
"symbol": "FTN",
"decimals": 18
},
"shortName": "ftn",
"infoURL": "https://fastexchain.com",
"chainId": 5165,
"networkId": 5165,
"explorers": [
{
"name": "blockscout",
"url": "https://ftnscan.com",
"standard": "none"
}
],
"testnet": false,
"slug": "sahara"
} as const satisfies Chain;
+42
View File
@@ -0,0 +1,42 @@
import type { Chain } from "../src/types";
export default {
"name": "GuapcoinX",
"chain": "GuapcoinX",
"rpc": [
"https://guapcoinx.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://rpc-mainnet.guapcoinx.com/",
"https://rpc-mainnet-1.guapcoinx.com/",
"https://rpc-mainnet-2.guapcoinx.com/"
],
"faucets": [],
"nativeCurrency": {
"name": "GuapcoinX",
"symbol": "GuapX",
"decimals": 18
},
"infoURL": "https://guapcoin.org/",
"shortName": "GuapX",
"chainId": 71111,
"networkId": 71111,
"icon": {
"url": "ipfs://QmcDTR7982VQKDDz2Mh4fZbnE9hn67MuFPWQv1MimCqPvB",
"width": 800,
"height": 800,
"format": "png"
},
"explorers": [
{
"name": "GuapcoinX Explorer",
"url": "http://explorer.guapcoinx.com",
"standard": "none",
"icon": {
"url": "ipfs://QmcDTR7982VQKDDz2Mh4fZbnE9hn67MuFPWQv1MimCqPvB",
"width": 800,
"height": 800,
"format": "png"
}
}
],
"testnet": false,
"slug": "guapcoinx"
} as const satisfies Chain;
+35
View File
@@ -0,0 +1,35 @@
import type { Chain } from "../src/types";
export default {
"name": "Raba Network Mainnet",
"chain": "Raba",
"icon": {
"url": "ipfs://QmatP9qMHEYoXqRDyHMTyjYRQa6j6Gk7pmv1QLxQkvpGRP",
"width": 787,
"height": 750,
"format": "png"
},
"rpc": [
"https://raba-network.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://rpc.x.raba.app/",
"wss://rpc.x.raba.app/ws/"
],
"faucets": [],
"nativeCurrency": {
"name": "Raba",
"symbol": "RABA",
"decimals": 18
},
"infoURL": "https://x.raba.app/",
"shortName": "raba",
"chainId": 7484,
"networkId": 7484,
"explorers": [
{
"name": "raba",
"url": "https://x.raba.app/explorer",
"standard": "none"
}
],
"testnet": false,
"slug": "raba-network"
} as const satisfies Chain;
+22
View File
@@ -0,0 +1,22 @@
import type { Chain } from "../src/types";
export default {
"name": "BitEth",
"chain": "BTE",
"rpc": [
"https://biteth.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://rpc.biteth.org"
],
"faucets": [],
"nativeCurrency": {
"name": "BitEth",
"symbol": "BTE",
"decimals": 18
},
"infoURL": "https://biteth.org",
"shortName": "BitEth",
"chainId": 8086,
"networkId": 8086,
"explorers": [],
"testnet": false,
"slug": "biteth"
} as const satisfies Chain;
+34
View File
@@ -0,0 +1,34 @@
import type { Chain } from "../src/types";
export default {
"name": "CURVE Mainnet",
"chain": "CURVE",
"icon": {
"url": "ipfs://QmTjV3TTR5aLb7fi7tjx8gcDvYtqBpusqhCSaznVxJ7NJg",
"width": 150,
"height": 150,
"format": "png"
},
"rpc": [
"https://curve.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://mainnet-rpc.curvescan.io"
],
"faucets": [],
"nativeCurrency": {
"name": "Curve",
"symbol": "CURVE",
"decimals": 18
},
"infoURL": "https://curvescan.io",
"shortName": "CURVEm",
"chainId": 827431,
"networkId": 827431,
"explorers": [
{
"name": "CURVE Mainnet",
"url": "https://curvescan.io",
"standard": "EIP3091"
}
],
"testnet": false,
"slug": "curve"
} as const satisfies Chain;
+48
View File
@@ -0,0 +1,48 @@
import type { Chain } from "../src/types";
export default {
"name": "AltLayer Testnet",
"chain": "ETH",
"rpc": [
"https://altlayer-testnet.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://testnet-rollup-api.altlayer.io"
],
"faucets": [],
"nativeCurrency": {
"name": "Ether",
"symbol": "ETH",
"decimals": 18
},
"features": [
{
"name": "EIP155"
},
{
"name": "EIP1559"
}
],
"infoURL": "https://altlayer.io",
"shortName": "alt-testnet",
"chainId": 9997,
"networkId": 9997,
"icon": {
"url": "ipfs://QmcEfZJU7NMn9ycTAcEooQgGNfa2nYBToSUZHdFCFadcjb",
"width": 1080,
"height": 1025,
"format": "png"
},
"explorers": [
{
"name": "blockscout",
"url": "https://testnet-rollup-explorer.altlayer.io",
"icon": {
"url": "ipfs://bafybeifu5tpui7dk5cjoo54kde7pmuthvnl7sdykobuarsxgu7t2izurnq",
"width": 512,
"height": 512,
"format": "png"
},
"standard": "EIP3091"
}
],
"testnet": true,
"slug": "altlayer-testnet"
} as const satisfies Chain;
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@thirdweb-dev/chains",
"version": "0.1.14",
"version": "0.1.16",
"main": "dist/thirdweb-dev-chains.cjs.js",
"module": "dist/thirdweb-dev-chains.esm.js",
"browser": {
+20
View File
@@ -1,5 +1,25 @@
# thirdweb
## 0.10.16
### Patch Changes
- [#926](https://github.com/thirdweb-dev/js/pull/926) [`84fc3b6f`](https://github.com/thirdweb-dev/js/commit/84fc3b6fab112b91563348f1a88820bd49a2f9b3) Thanks [@Marfuen](https://github.com/Marfuen)! - Added detect-project command, reorganized folder structure for detecting, added many more detections.
- [#926](https://github.com/thirdweb-dev/js/pull/926) [`84fc3b6f`](https://github.com/thirdweb-dev/js/commit/84fc3b6fab112b91563348f1a88820bd49a2f9b3) Thanks [@Marfuen](https://github.com/Marfuen)! - Added log to see detected app type to the "detect-project" command
- Updated dependencies [[`e9b69300`](https://github.com/thirdweb-dev/js/commit/e9b69300d15b233609f1ed897256ec9a1eef3e28), [`49ec2d17`](https://github.com/thirdweb-dev/js/commit/49ec2d171ecb1c9240398b7b486a452eb9429979), [`799d98e8`](https://github.com/thirdweb-dev/js/commit/799d98e86258677ab72931fa8397aee653fe8b34), [`c3645c45`](https://github.com/thirdweb-dev/js/commit/c3645c451b5e9a0fcf651fa07eb0e31ebf1882ca), [`470e0a14`](https://github.com/thirdweb-dev/js/commit/470e0a144db6aa03e7789e231bbdfae43144f0e0), [`482f6d1b`](https://github.com/thirdweb-dev/js/commit/482f6d1b58ac99b331fc750d3eeb6082556fd526), [`e4356e76`](https://github.com/thirdweb-dev/js/commit/e4356e76d1506624afe2eb6feeaf57dc376f372f), [`9886c858`](https://github.com/thirdweb-dev/js/commit/9886c858d9c8d0f677aba6572dbf5cc6c876edf2), [`8db78299`](https://github.com/thirdweb-dev/js/commit/8db78299ea6cfb51d93b91bb1a351644a83c73d2)]:
- @thirdweb-dev/sdk@3.10.15
- @thirdweb-dev/chains@0.1.16
## 0.10.15
### Patch Changes
- Updated dependencies [[`32908b76`](https://github.com/thirdweb-dev/js/commit/32908b76832c60e91a0a6e40dbdb1c8f56e9e5be), [`6a4aab0b`](https://github.com/thirdweb-dev/js/commit/6a4aab0b8a2e0f6ff1b47992a3c1e5426a74f7ff)]:
- @thirdweb-dev/sdk@3.10.14
- @thirdweb-dev/chains@0.1.15
## 0.10.14
### Patch Changes
+4 -1
View File
@@ -1,7 +1,7 @@
{
"name": "thirdweb",
"main": "dist/cli/index.js",
"version": "0.10.14",
"version": "0.10.16",
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/cli",
"author": "thirdweb eng <[email protected]>",
"license": "Apache-2.0",
@@ -15,6 +15,7 @@
"@types/cross-spawn": "^6.0.2",
"@types/inquirer": "^8.2.1",
"@types/jest": "^29.2.1",
"@types/js-yaml": "^4.0.5",
"@types/node": "^18.0.0",
"@types/prompts": "^2.0.14",
"@types/rimraf": "^3.0.0",
@@ -34,6 +35,7 @@
"typescript": "^4.7.4"
},
"dependencies": {
"@iarna/toml": "^2.2.5",
"@thirdweb-dev/chains": "workspace:*",
"@thirdweb-dev/sdk": "workspace:*",
"@thirdweb-dev/storage": "workspace:*",
@@ -44,6 +46,7 @@
"ethers": "^5.7.2",
"got": "11.8.5",
"inquirer": "^8.2.3",
"js-yaml": "^4.1.0",
"open": "^8.4.0",
"prompts": "^2.4.2",
"rimraf": "^3.0.2",
+12
View File
@@ -1,5 +1,6 @@
#!/usr/bin/env node
import { detectExtensions } from "../common/feature-detector";
import { detectProjectV2 } from "../common/project-detector-v2";
import { processProject } from "../common/processor";
import { cliVersion, pkg } from "../constants/urls";
import { info, logger, spinner } from "../core/helpers/logger";
@@ -406,6 +407,17 @@ const main = async () => {
await detectExtensions(options);
});
program
.command("detect-project")
.description(
"Detect the type of project your are running and let you know what it is.",
)
.option("-p, --path <project-path>", "path to project", ".")
.option("-d, --debug", "show debug logs")
.action(async (options) => {
await detectProjectV2(options);
});
program
.command("generate")
.description(
@@ -0,0 +1,48 @@
import detectPackageManager from "../core/detection/detectPackageManager";
import detectFramework from "../core/detection/detectFramework";
import detectLibrary from "../core/detection/detectLibrary";
import detectLanguage from "../core/detection/detectLanguage";
import { logger } from "../core/helpers/logger";
import path from "path";
import { ContractLibrariesType, contractLibraries } from "../core/types/ProjectType";
export async function detectProjectV2(options: any) {
logger.setSettings({
minLevel: options.debug ? "debug" : "info",
});
let projectPath = process.cwd();
if (options.path) {
logger.debug("Overriding project path to " + options.path);
const resolvedPath = (options.path as string).startsWith("/")
? options.path
: path.resolve(`${projectPath}/${options.path}`);
projectPath = resolvedPath;
}
logger.debug("Processing project at path " + projectPath);
const detectedPackageManager = await detectPackageManager(
projectPath,
options,
);
const detectedLanguage = await detectLanguage(projectPath, options);
const detectedLibrary = await detectLibrary(
projectPath,
options,
detectedPackageManager,
);
const detectedFramework = await detectFramework(
projectPath,
options,
detectedPackageManager,
);
const detectedAppType = contractLibraries.includes(detectedFramework as ContractLibrariesType) ? "contract" : "app";
logger.debug("Detected package manager: " + detectedPackageManager);
logger.debug("Detected library: " + detectedLibrary);
logger.debug("Detected language: " + detectedLanguage);
logger.debug("Detected framework: " + detectedFramework);
logger.debug("Detected app type: " + detectedAppType);
}
+182
View File
@@ -0,0 +1,182 @@
import { ALWAYS_SUGGESTED } from "../constants/features";
import build from "../core/builder/build";
import detect from "../core/detection/detect";
import detectPackageManager from "../core/detection/detectPackageManager";
import { logger, spinner } from "../core/helpers/logger";
import { createContractsPrompt } from "../core/helpers/selector";
import { ContractFeatures, Feature } from "../core/interfaces/ContractFeatures";
import { ContractPayload } from "../core/interfaces/ContractPayload";
import { getPkgManager } from "../create/helpers/get-pkg-manager";
import { detectFeatures, FeatureWithEnabled } from "@thirdweb-dev/sdk";
import chalk from "chalk";
import { existsSync, readFileSync } from "fs";
import ora from "ora";
import path from "path";
export async function detectProject(options: any) {
logger.setSettings({
minLevel: options.debug ? "debug" : "info",
});
let projectPath = process.cwd();
if (options.path) {
logger.debug("Overriding project path to " + options.path);
const resolvedPath = (options.path as string).startsWith("/")
? options.path
: path.resolve(`${projectPath}/${options.path}`);
projectPath = resolvedPath;
}
logger.debug("Processing project at path " + projectPath);
const packageManagerType = await detectPackageManager(projectPath, options);
console.log(packageManagerType);
const projectType = await detect(projectPath, options);
let compiledResult;
const compileLoader = spinner("Compiling project...");
try {
compiledResult = await build(projectPath, projectType, options);
} catch (e) {
compileLoader.fail("Compilation failed");
logger.error(e);
process.exit(1);
}
compileLoader.succeed("Compilation successful");
let selectedContracts: ContractPayload[] = [];
if (compiledResult.contracts.length === 1) {
selectedContracts = [compiledResult.contracts[0]];
} else {
if (options.all) {
selectedContracts = compiledResult.contracts;
} else {
const choices = compiledResult.contracts.map((c) => ({
name: c.name,
value: c,
}));
const prompt = createContractsPrompt(
choices,
"Choose which contracts to run detection on",
);
const selection: Record<string, ContractPayload> = await prompt.run();
selectedContracts = Object.keys(selection).map((key) => selection[key]);
}
}
let contractsWithFeatures: ContractFeatures[] = selectedContracts.map(
(contract) => {
const abi: Parameters<typeof detectFeatures>[0] = JSON.parse(
contract.metadata,
)["output"]["abi"];
const features = extractFeatures(detectFeatures(abi));
const enabledFeatures: Feature[] = features.enabledFeatures.map(
(feature) => ({
name: feature.name,
reference: `https://portal.thirdweb.com/interfaces/${feature.name.toLowerCase()}`,
}),
);
const suggestedFeatures: Feature[] = features.suggestedFeatures.map(
(feature) => ({
name: feature.name,
reference: `https://portal.thirdweb.com/interfaces/${feature.name.toLowerCase()}`,
}),
);
return {
name: contract.name,
enabledFeatures,
suggestedFeatures,
};
},
);
contractsWithFeatures.map((contractWithFeatures) => {
logger.info(`\n`);
if (contractWithFeatures.enabledFeatures.length === 0) {
ora(
`No extensions detected on ${chalk.blueBright(
contractWithFeatures.name,
)}`,
).stopAndPersist({ symbol: "🔎" });
} else {
ora(
`Detected extension on ${chalk.blueBright(contractWithFeatures.name)}`,
).stopAndPersist({ symbol: "🔎" });
contractWithFeatures.enabledFeatures.map((feature) => {
logger.info(`✔️ ${chalk.green(feature.name)}`);
});
}
logger.info(``);
ora(`Suggested extensions`).info();
contractWithFeatures.suggestedFeatures.map((feature) => {
logger.info(
`${chalk.dim(chalk.gray(`-`))} ${chalk.gray(
feature.name,
)} - ${chalk.dim(chalk.gray(feature.reference))}`,
);
});
let deployCmd = `npx thirdweb@latest deploy`;
if (existsSync(projectPath + "/package.json")) {
const packageManager = getPkgManager();
const useYarn = packageManager === "yarn";
const pkgJson = JSON.parse(
readFileSync(projectPath + "/package.json", "utf-8"),
);
if (pkgJson?.scripts?.deploy === deployCmd) {
deployCmd = `${packageManager}${useYarn ? "" : " run"} deploy`;
}
}
logger.info(``);
ora(
`Once you're done writing your contracts, you can run the following command to deploy them:`,
).info();
logger.info(``);
logger.info(` ${chalk.cyan(deployCmd)}`);
logger.info(``);
});
}
function extractFeatures(
input: ReturnType<typeof detectFeatures>,
enabledFeatures: FeatureWithEnabled[] = [],
suggestedFeatures: FeatureWithEnabled[] = [],
parent = "__ROOT__",
) {
if (!input) {
return {
enabledFeatures,
suggestedFeatures,
};
}
for (const featureKey in input) {
const feature = input[featureKey];
// if feature is enabled, then add it to enabledFeatures
if (feature.enabled) {
enabledFeatures.push(feature);
}
// otherwise if it is disabled, but it's parent is enabled or suggested, then add it to suggestedFeatures
else if (
enabledFeatures.findIndex((f) => f.name === parent) > -1 ||
ALWAYS_SUGGESTED.includes(feature.name)
) {
suggestedFeatures.push(feature);
}
// recurse
extractFeatures(
feature.features,
enabledFeatures,
suggestedFeatures,
feature.name,
);
}
return {
enabledFeatures,
suggestedFeatures,
};
}
@@ -0,0 +1,88 @@
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 EchoDetector from "./frameworks/echo";
import FiberDetector from "./frameworks/fiber";
import GinDetector from "./frameworks/gin";
import RevelDetector from "./frameworks/revel";
import ZenjectDetector from "./frameworks/zenject";
export default async function detect(
path: string,
options: any,
detectedPackageManager: PackageManagerType,
): Promise<FrameworkType> {
// We could optimize further if we want, by only running the detectors that match the package manager.
const frameworkDetectors: FrameworkDetector[] = [
new BrownieDetector(),
new CRADetector(),
new DjangoDetector(),
new EchoDetector(),
new ExpoDetector(),
new FastAPIDetector(),
new FastifyDetector(),
new FiberDetector(),
new FlaskDetector(),
new FoundryDetector(),
new GatsbyDetector(),
new GinDetector(),
new HardhatDetector(),
new NextDetector(),
new PopulusDetector(),
new ReactNativeCLIDetector(),
new RemixDetector(),
new RevelDetector(),
new TruffleDetector(),
new VueDetector(),
new ZenjectDetector(),
];
const possibleFrameworks = frameworkDetectors
.filter((detector) => detector.matches(path, detectedPackageManager))
.map((detector) => detector.frameworkType);
if (!possibleFrameworks.length) {
return "none";
}
if (possibleFrameworks.length === 1) {
return possibleFrameworks[0];
}
info(
`Detected multiple possible frameworks: ${possibleFrameworks
.map((s) => `"${s}"`)
.join(", ")}`,
);
const question =
"We detected multiple possible frameworks which one do you want to use?";
if (options.ci) {
return possibleFrameworks[0];
} else {
const answer = await inquirer.prompt({
type: "list",
choices: possibleFrameworks,
name: question,
});
return answer[question];
}
}
@@ -0,0 +1,52 @@
import { info } from "../helpers/logger";
import { LanguageType } from "../types/ProjectType";
import { LanguageDetector } from "./detector";
import inquirer from "inquirer";
import JavascriptDetector from "./languages/javascript";
import TypescriptDetector from "./languages/typescript";
import PythonDetector from "./languages/python";
import GoDetector from "./languages/go";
export default async function detect(
path: string,
options: any,
): Promise<LanguageType> {
const languageDetectors: LanguageDetector[] = [
new JavascriptDetector(),
new TypescriptDetector(),
new PythonDetector(),
new GoDetector(),
];
const possibleLanguages = languageDetectors
.filter((detector) => detector.matches(path))
.map((detector) => detector.languageType);
if (!possibleLanguages.length) {
return "none";
}
if (possibleLanguages.length === 1) {
return possibleLanguages[0];
}
info(
`Detected multiple possible languages: ${possibleLanguages
.map((s) => `"${s}"`)
.join(", ")}`,
);
const question =
"We detected multiple possible languages which one do you want to use?";
if (options.ci) {
return possibleLanguages[0];
} else {
const answer = await inquirer.prompt({
type: "list",
choices: possibleLanguages,
name: question,
});
return answer[question];
}
}
@@ -0,0 +1,58 @@
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";
export default async function detect(
path: string,
options: any,
detectedPackageManager: PackageManagerType,
): Promise<LibraryType> {
// We could optimize further if we want, by only running the detectors that match the package manager.
const libraryDetectors: LibraryDetector[] = [
new ExpressDetector(),
new ReactDetector(),
new ReactNativeDetector(),
new ViteDetector(),
new Web3PyDetector(),
new PlayMakerDetector(),
];
const possibleLibraries = libraryDetectors
.filter((detector) => detector.matches(path, detectedPackageManager))
.map((detector) => detector.libraryType);
if (!possibleLibraries.length) {
return "none";
}
if (possibleLibraries.length === 1) {
return possibleLibraries[0];
}
info(
`Detected multiple possible libraries: ${possibleLibraries
.map((s) => `"${s}"`)
.join(", ")}`,
);
const question =
"We detected multiple possible libraries which one do you want to use?";
if (options.ci) {
return possibleLibraries[0];
} else {
const answer = await inquirer.prompt({
type: "list",
choices: possibleLibraries,
name: question,
});
return answer[question];
}
}
@@ -0,0 +1,58 @@
import { info } from "../helpers/logger";
import { PackageManagerType } from "../types/ProjectType";
import { PackageManagerDetector } from "./detector";
import inquirer from "inquirer";
import NPMDetector from "./packageManagers/npm";
import YarnDetector from "./packageManagers/yarn";
import PnpmDetector from "./packageManagers/pnpm";
import CondaDetector from "./packageManagers/conda";
import PipDetector from "./packageManagers/pip";
import PipEnvDetector from "./packageManagers/pipenv";
import PoetryDetector from "./packageManagers/poetry";
export default async function detect(
path: string,
options: any,
): Promise<PackageManagerType> {
const packageManagerDetectors: PackageManagerDetector[] = [
new NPMDetector(),
new YarnDetector(),
new PnpmDetector(),
new CondaDetector(),
new PipDetector(),
new PipEnvDetector(),
new PoetryDetector(),
];
const possiblePackageManagers = packageManagerDetectors
.filter((detector) => detector.matches(path))
.map((detector) => detector.packageManagerType);
if (!possiblePackageManagers.length) {
return "none";
}
if (possiblePackageManagers.length === 1) {
return possiblePackageManagers[0];
}
info(
`Detected multiple possible package managers: ${possiblePackageManagers
.map((s) => `"${s}"`)
.join(", ")}`,
);
const question =
"We detected multiple possible package managers, which one do you want to use?";
if (options.ci) {
return possiblePackageManagers[0];
} else {
const answer = await inquirer.prompt({
type: "list",
choices: possiblePackageManagers,
name: question,
});
return answer[question];
}
}
+38 -1
View File
@@ -1,7 +1,44 @@
import { ProjectType } from "../types/ProjectType";
import {
ProjectType,
LanguageType,
PackageManagerType,
AppType,
FrameworkType,
LibraryType,
} from "../types/ProjectType";
export interface Detector {
projectType: ProjectType;
matches(path: string): boolean;
}
export interface PackageManagerDetector {
packageManagerType: PackageManagerType;
matches(path: string): boolean;
}
export interface FrameworkDetector {
frameworkType: FrameworkType;
matches(path: string, PackageManager?: PackageManagerType): boolean;
}
export interface LibraryDetector {
libraryType: LibraryType;
matches(path: string, PackageManager?: PackageManagerType): boolean;
}
export interface LanguageDetector {
languageType: LanguageType;
matches(path: string): boolean;
}
export interface AppTypeDetector {
appType: AppType;
matches(path: string): boolean;
}
@@ -0,0 +1,30 @@
import { FrameworkDetector } from "../detector";
import { existsSync } from "fs";
import { FrameworkType, PackageManagerType } from "../../types/ProjectType";
import { getDependenciesForPython } from "../../../lib/utils";
export default class BrownieDetector implements FrameworkDetector {
public frameworkType: FrameworkType = "brownie";
public matches(path: string, packageManager: PackageManagerType): boolean {
const { dependencies, devDependencies } = getDependenciesForPython(
path,
packageManager,
);
const additionalFilesToCheck = [
"/brownie-config.yaml",
"/brownie-config.json",
];
const additionalFilesExist = additionalFilesToCheck.some((file) =>
existsSync(path + file),
);
return (
dependencies.includes("brownie") ||
devDependencies.includes("brownie") ||
additionalFilesExist ||
false
);
}
}
@@ -0,0 +1,25 @@
import { FrameworkDetector } from "../detector";
import { existsSync, readFileSync } from "fs";
import { FrameworkType } from "../../types/ProjectType";
import { parsePackageJson } from "../../../lib/utils";
export default class CRADetector implements FrameworkDetector {
public frameworkType: FrameworkType = "cra";
public matches(path: string): boolean {
const packageJsonPath = path + "/package.json";
if (!existsSync(packageJsonPath)) {
return false;
}
const packageJson = readFileSync(packageJsonPath);
const { dependencies, devDependencies } = parsePackageJson(packageJson);
const craDependencyExists =
dependencies["react-scripts"] ||
devDependencies["react-scripts"] ||
false;
return craDependencyExists;
}
}
@@ -0,0 +1,27 @@
import { FrameworkDetector } from "../detector";
import { existsSync } from "fs";
import { FrameworkType, PackageManagerType } from "../../types/ProjectType";
import { getDependenciesForPython } from "../../../lib/utils";
export default class DjangoDetector implements FrameworkDetector {
public frameworkType: FrameworkType = "django";
public matches(path: string, packageManager: PackageManagerType): boolean {
const { dependencies, devDependencies } = getDependenciesForPython(
path,
packageManager,
);
const additionalFilesToCheck = ["/manage.py"];
const additionalFilesExist = additionalFilesToCheck.some((file) =>
existsSync(path + file),
);
return (
dependencies.includes("django") ||
devDependencies.includes("django") ||
additionalFilesExist ||
false
);
}
}
@@ -0,0 +1,36 @@
import { FrameworkDetector } from "../detector";
import { existsSync, readFileSync } from "fs";
import { FrameworkType } from "../../types/ProjectType";
import { fileContainsImport, parseGoMod } from "../../../lib/utils";
export default class EchoDetector implements FrameworkDetector {
public frameworkType: FrameworkType = "echo";
public matches(path: string): boolean {
const goModFilePath = path + "/go.mod";
const mainGoFilePath = path + "/main.go";
let dependenciesExist = false;
if (!existsSync(goModFilePath) && !existsSync(mainGoFilePath)) {
return false;
}
if (existsSync(goModFilePath)) {
const goModFile = readFileSync(goModFilePath, "utf-8");
const { dependencies } = parseGoMod(goModFile);
const dependenciesToCheck = ["github.com/labstack/echo"];
dependenciesExist = dependenciesToCheck.some((dependency) =>
dependencies.some((importstr) => importstr.name === dependency),
);
}
const mainGoFile = readFileSync(mainGoFilePath, "utf-8");
const fileImportExists = fileContainsImport(
mainGoFile,
"github.com/labstack/echo",
);
return dependenciesExist || fileImportExists || false;
}
}
@@ -0,0 +1,32 @@
import { FrameworkDetector } from "../detector";
import { existsSync, readFileSync } from "fs";
import { FrameworkType } from "../../types/ProjectType";
import { parsePackageJson } from "../../../lib/utils";
export default class ExpoDetector implements FrameworkDetector {
public frameworkType: FrameworkType = "expo";
public matches(path: string): boolean {
const packageJsonPath = path + "/package.json";
if (!existsSync(packageJsonPath)) {
return false;
}
const packageJson = readFileSync(packageJsonPath);
const { dependencies, devDependencies } = parsePackageJson(packageJson);
const additionalFilesToCheck = ["/app.json", "/app.config.js", "/assets"];
const additionalFilesExist = additionalFilesToCheck.some((file) =>
existsSync(path + file),
);
const expoDependencyExists =
dependencies["expo"] ||
devDependencies["expo"] ||
additionalFilesExist ||
false;
return expoDependencyExists;
}
}
@@ -0,0 +1,27 @@
import { FrameworkDetector } from "../detector";
import { existsSync } from "fs";
import { FrameworkType, PackageManagerType } from "../../types/ProjectType";
import { getDependenciesForPython } from "../../../lib/utils";
export default class FastAPIDetector implements FrameworkDetector {
public frameworkType: FrameworkType = "fastapi";
public matches(path: string, packageManager: PackageManagerType): boolean {
const { dependencies, devDependencies } = getDependenciesForPython(
path,
packageManager,
);
const additionalFilesToCheck = ["/app.py", "/main.py"];
const additionalFilesExist = additionalFilesToCheck.some((file) =>
existsSync(path + file),
);
return (
dependencies.includes("fastapi") ||
devDependencies.includes("fastapi") ||
additionalFilesExist ||
false
);
}
}
@@ -0,0 +1,37 @@
import { FrameworkDetector } from "../detector";
import { existsSync, readFileSync } from "fs";
import { FrameworkType } from "../../types/ProjectType";
import { parsePackageJson } from "../../../lib/utils";
export default class FastifyDetector implements FrameworkDetector {
public frameworkType: FrameworkType = "fastify";
public matches(path: string): boolean {
const packageJsonPath = path + "/package.json";
if (!existsSync(packageJsonPath)) {
return false;
}
const packageJson = readFileSync(packageJsonPath);
const { dependencies, devDependencies } = parsePackageJson(packageJson);
const additionalFilesToCheck = [
"/server.js",
"/app.js",
"/server.ts",
"/app.ts",
];
const additionalFilesExist = additionalFilesToCheck.some((file) =>
existsSync(path + file),
);
const fastifyDependencyExists =
dependencies["fastify"] ||
devDependencies["fastify"] ||
additionalFilesExist ||
false;
return fastifyDependencyExists;
}
}
@@ -0,0 +1,36 @@
import { FrameworkDetector } from "../detector";
import { existsSync, readFileSync } from "fs";
import { FrameworkType } from "../../types/ProjectType";
import { fileContainsImport, parseGoMod } from "../../../lib/utils";
export default class FiberDetector implements FrameworkDetector {
public frameworkType: FrameworkType = "fiber";
public matches(path: string): boolean {
const goModFilePath = path + "/go.mod";
const mainGoFilePath = path + "/main.go";
let dependenciesExist = false;
if (!existsSync(goModFilePath) && !existsSync(mainGoFilePath)) {
return false;
}
if (existsSync(goModFilePath)) {
const goModFile = readFileSync(goModFilePath, "utf-8");
const { dependencies } = parseGoMod(goModFile);
const dependenciesToCheck = ["github.com/gofiber/fiber"];
dependenciesExist = dependenciesToCheck.some((dependency) =>
dependencies.some((importstr) => importstr.name === dependency),
);
}
const mainGoFile = readFileSync(mainGoFilePath, "utf-8");
const fileImportExists = fileContainsImport(
mainGoFile,
"github.com/gofiber/fiber",
);
return dependenciesExist || fileImportExists || false;
}
}
@@ -0,0 +1,27 @@
import { FrameworkDetector } from "../detector";
import { existsSync } from "fs";
import { FrameworkType, PackageManagerType } from "../../types/ProjectType";
import { getDependenciesForPython } from "../../../lib/utils";
export default class FlaskDetector implements FrameworkDetector {
public frameworkType: FrameworkType = "flask";
public matches(path: string, packageManager: PackageManagerType): boolean {
const { dependencies, devDependencies } = getDependenciesForPython(
path,
packageManager,
);
const additionalFilesToCheck = ["/app.py", "/application.py"];
const additionalFilesExist = additionalFilesToCheck.some((file) =>
existsSync(path + file),
);
return (
dependencies.includes("flask") ||
devDependencies.includes("flask") ||
additionalFilesExist ||
false
);
}
}
@@ -0,0 +1,16 @@
import { FrameworkDetector } from "../detector";
import { existsSync } from "fs";
import { FrameworkType } from "../../types/ProjectType";
export default class FoundryDetector implements FrameworkDetector {
public frameworkType: FrameworkType = "foundry";
public matches(path: string): boolean {
const additionalFilesToCheck = ["/foundry.toml", "/lib/forge-std/"];
const additionalFilesExist = additionalFilesToCheck.some((file) =>
existsSync(path + file),
);
return additionalFilesExist || false;
}
}
@@ -0,0 +1,32 @@
import { FrameworkDetector } from "../detector";
import { existsSync, readFileSync } from "fs";
import { FrameworkType } from "../../types/ProjectType";
import { parsePackageJson } from "../../../lib/utils";
export default class GatsbyDetector implements FrameworkDetector {
public frameworkType: FrameworkType = "gatsby";
public matches(path: string): boolean {
const packageJsonPath = path + "/package.json";
if (!existsSync(packageJsonPath)) {
return false;
}
const packageJson = readFileSync(packageJsonPath);
const { dependencies, devDependencies } = parsePackageJson(packageJson);
const additionalFilesToCheck = ["/gatsby.config.js", "/gatsby-config.ts"];
const additionalFilesExist = additionalFilesToCheck.some((file) =>
existsSync(path + file),
);
const gatsbyDependencyExists =
dependencies["gatsby"] ||
devDependencies["gatsby"] ||
additionalFilesExist ||
false;
return gatsbyDependencyExists;
}
}
@@ -0,0 +1,36 @@
import { FrameworkDetector } from "../detector";
import { existsSync, readFileSync } from "fs";
import { FrameworkType } from "../../types/ProjectType";
import { fileContainsImport, parseGoMod } from "../../../lib/utils";
export default class GinDetector implements FrameworkDetector {
public frameworkType: FrameworkType = "gin";
public matches(path: string): boolean {
const goModFilePath = path + "/go.mod";
const mainGoFilePath = path + "/main.go";
let dependenciesExist = false;
if (!existsSync(goModFilePath) && !existsSync(mainGoFilePath)) {
return false;
}
if (existsSync(goModFilePath)) {
const goModFile = readFileSync(goModFilePath, "utf-8");
const { dependencies } = parseGoMod(goModFile);
const dependenciesToCheck = ["github.com/gin-gonic/gin"];
dependenciesExist = dependenciesToCheck.some((dependency) =>
dependencies.some((importstr) => importstr.name === dependency),
);
}
const mainGoFile = readFileSync(mainGoFilePath, "utf-8");
const fileImportExists = fileContainsImport(
mainGoFile,
"github.com/gin-gonic/gin",
);
return dependenciesExist || fileImportExists || false;
}
}
@@ -0,0 +1,32 @@
import { FrameworkDetector } from "../detector";
import { existsSync, readFileSync } from "fs";
import { FrameworkType } from "../../types/ProjectType";
import { parsePackageJson } from "../../../lib/utils";
export default class HardhatDetector implements FrameworkDetector {
public frameworkType: FrameworkType = "hardhat";
public matches(path: string): boolean {
const packageJsonPath = path + "/package.json";
if (!existsSync(packageJsonPath)) {
return false;
}
const packageJson = readFileSync(packageJsonPath);
const { dependencies, devDependencies } = parsePackageJson(packageJson);
const additionalFilesToCheck = ["/hardhat.config.js", "/contracts/"];
const additionalFilesExist = additionalFilesToCheck.some((file) =>
existsSync(path + file),
);
const hardhatDependencyExists =
dependencies["hardhat"] ||
devDependencies["hardhat"] ||
additionalFilesExist ||
false;
return hardhatDependencyExists;
}
}
@@ -0,0 +1,32 @@
import { FrameworkDetector } from "../detector";
import { existsSync, readFileSync } from "fs";
import { FrameworkType } from "../../types/ProjectType";
import { parsePackageJson } from "../../../lib/utils";
export default class NextDetector implements FrameworkDetector {
public frameworkType: FrameworkType = "next";
public matches(path: string): boolean {
const packageJsonPath = path + "/package.json";
if (!existsSync(packageJsonPath)) {
return false;
}
const packageJson = readFileSync(packageJsonPath);
const { dependencies, devDependencies } = parsePackageJson(packageJson);
const additionalFilesToCheck = ["/next.config.js", "/next-config.ts"];
const additionalFilesExist = additionalFilesToCheck.some((file) =>
existsSync(path + file),
);
const nextDependencyExists =
dependencies["next"] ||
devDependencies["next"] ||
additionalFilesExist ||
false;
return nextDependencyExists;
}
}
@@ -0,0 +1,27 @@
import { FrameworkDetector } from "../detector";
import { existsSync } from "fs";
import { FrameworkType, PackageManagerType } from "../../types/ProjectType";
import { getDependenciesForPython } from "../../../lib/utils";
export default class PopulusDetector implements FrameworkDetector {
public frameworkType: FrameworkType = "populus";
public matches(path: string, packageManager: PackageManagerType): boolean {
const { dependencies, devDependencies } = getDependenciesForPython(
path,
packageManager,
);
const additionalFilesToCheck = ["/populus.json", "/populus.yaml"];
const additionalFilesExist = additionalFilesToCheck.some((file) =>
existsSync(path + file),
);
return (
dependencies.includes("populus") ||
devDependencies.includes("populus") ||
additionalFilesExist ||
false
);
}
}
@@ -0,0 +1,31 @@
import { FrameworkDetector } from "../detector";
import { existsSync, readFileSync } from "fs";
import { FrameworkType } from "../../types/ProjectType";
import { parsePackageJson } from "../../../lib/utils";
export default class ReactNativeCLIDetector implements FrameworkDetector {
public frameworkType: FrameworkType = "react-native-cli";
public matches(path: string): boolean {
const packageJsonPath = path + "/package.json";
if (!existsSync(packageJsonPath)) {
return false;
}
const packageJson = readFileSync(packageJsonPath);
const { dependencies, devDependencies } = parsePackageJson(packageJson);
const additionalFilesToCheck = ["/android", "/ios"];
const additionalFilesExist = additionalFilesToCheck.some((file) =>
existsSync(path + file),
);
return (
dependencies["react-native"] ||
devDependencies["react-native"] ||
additionalFilesExist ||
false
);
}
}
@@ -0,0 +1,30 @@
import { FrameworkDetector } from "../detector";
import { existsSync, readFileSync } from "fs";
import { FrameworkType } from "../../types/ProjectType";
import { parsePackageJson } from "../../../lib/utils";
export default class CRADetector implements FrameworkDetector {
public frameworkType: FrameworkType = "remix";
public matches(path: string): boolean {
const packageJsonPath = path + "/package.json";
if (!existsSync(packageJsonPath)) {
return false;
}
const packageJson = readFileSync(packageJsonPath);
const { dependencies, devDependencies } = parsePackageJson(packageJson);
const additionalFilesToCheck = ["/remix.config.js", "/remix-config.ts"];
const additionalFilesExist = additionalFilesToCheck.some((file) =>
existsSync(path + file),
);
const remixDependencies = Object.keys(dependencies)
.concat(Object.keys(devDependencies))
.filter((dep) => dep.startsWith("@remix-run/"));
return remixDependencies.length > 0 || additionalFilesExist || false;
}
}
@@ -0,0 +1,36 @@
import { FrameworkDetector } from "../detector";
import { existsSync, readFileSync } from "fs";
import { FrameworkType } from "../../types/ProjectType";
import { fileContainsImport, parseGoMod } from "../../../lib/utils";
export default class RevelDetector implements FrameworkDetector {
public frameworkType: FrameworkType = "revel";
public matches(path: string): boolean {
const goModFilePath = path + "/go.mod";
const mainGoFilePath = path + "/main.go";
let dependenciesExist = false;
if (!existsSync(goModFilePath) && !existsSync(mainGoFilePath)) {
return false;
}
if (existsSync(goModFilePath)) {
const goModFile = readFileSync(goModFilePath, "utf-8");
const { dependencies } = parseGoMod(goModFile);
const dependenciesToCheck = ["github.com/revel/revel"];
dependenciesExist = dependenciesToCheck.some((dependency) =>
dependencies.some((importstr) => importstr.name === dependency),
);
}
const mainGoFile = readFileSync(mainGoFilePath, "utf-8");
const fileImportExists = fileContainsImport(
mainGoFile,
"github.com/revel/revel",
);
return dependenciesExist || fileImportExists || false;
}
}
@@ -0,0 +1,35 @@
import { FrameworkDetector } from "../detector";
import { existsSync, readFileSync } from "fs";
import { FrameworkType } from "../../types/ProjectType";
import { parsePackageJson } from "../../../lib/utils";
export default class TruffleDetector implements FrameworkDetector {
public frameworkType: FrameworkType = "truffle";
public matches(path: string): boolean {
const packageJsonPath = path + "/package.json";
if (!existsSync(packageJsonPath)) {
return false;
}
const packageJson = readFileSync(packageJsonPath);
const { dependencies, devDependencies } = parsePackageJson(packageJson);
const additionalFilesToCheck = [
"/truffle.config.js",
"/truffle.js",
"/contracts/",
];
const additionalFilesExist = additionalFilesToCheck.some((file) =>
existsSync(path + file),
);
return (
dependencies["truffle"] ||
devDependencies["truffle"] ||
additionalFilesExist ||
false
);
}
}
@@ -0,0 +1,31 @@
import { FrameworkDetector } from "../detector";
import { existsSync, readFileSync } from "fs";
import { FrameworkType } from "../../types/ProjectType";
import { parsePackageJson } from "../../../lib/utils";
export default class VueDetector implements FrameworkDetector {
public frameworkType: FrameworkType = "vue";
public matches(path: string): boolean {
const packageJsonPath = path + "/package.json";
if (!existsSync(packageJsonPath)) {
return false;
}
const packageJson = readFileSync(packageJsonPath);
const { dependencies, devDependencies } = parsePackageJson(packageJson);
const additionalFilesToCheck = ["/vue.config.js"];
const additionalFilesExist = additionalFilesToCheck.some((file) =>
existsSync(path + file),
);
return (
dependencies["vue"] ||
devDependencies["vue"] ||
additionalFilesExist ||
false
);
}
}
@@ -0,0 +1,17 @@
import { FrameworkDetector } from "../detector";
import { existsSync } from "fs";
import { FrameworkType } from "../../types/ProjectType";
export default class ZenjectDetector implements FrameworkDetector {
public frameworkType: FrameworkType = "zenject";
public matches(path: string): boolean {
const foundZenject = existsSync(path + "/Assets/Zenject");
const foundZenjectDLL = existsSync(
path + "/Assets/Zenject/OptionalExtras/Zenject.dll",
);
const foundScript = existsSync(path + "/Assets/Scripts/ProjectContext.cs");
return foundZenject || foundZenjectDLL || foundScript || false;
}
}
@@ -0,0 +1,14 @@
import { LanguageDetector } from "../detector";
import { readdirSync } from "fs";
import { LanguageType } from "../../types/ProjectType";
export default class GoDetector implements LanguageDetector {
public languageType: LanguageType = "go";
public matches(path: string): boolean {
// Check if some of these files are written in Go.
const goFileExtensionRegex = /\.go$/;
const dirFiles = readdirSync(path);
return dirFiles.some((file) => file.match(goFileExtensionRegex));
}
}
@@ -0,0 +1,14 @@
import { LanguageDetector } from "../detector";
import { readdirSync } from "fs";
import { LanguageType } from "../../types/ProjectType";
export default class JavascriptDetector implements LanguageDetector {
public languageType: LanguageType = "javascript";
public matches(path: string): boolean {
// Check if some of these files are written in Go.
const javascriptFileExtensionRegex = /\.js$/;
const dirFiles = readdirSync(path);
return dirFiles.some((file) => file.match(javascriptFileExtensionRegex));
}
}
@@ -0,0 +1,14 @@
import { LanguageDetector } from "../detector";
import { readdirSync } from "fs";
import { LanguageType } from "../../types/ProjectType";
export default class PythonDetector implements LanguageDetector {
public languageType: LanguageType = "python";
public matches(path: string): boolean {
// Check if some of these files are written in Go.
const pythonFileExtensionRegex = /\.py$/;
const dirFiles = readdirSync(path);
return dirFiles.some((file) => file.match(pythonFileExtensionRegex));
}
}
@@ -0,0 +1,14 @@
import { LanguageDetector } from "../detector";
import { readdirSync } from "fs";
import { LanguageType } from "../../types/ProjectType";
export default class TypescriptDetector implements LanguageDetector {
public languageType: LanguageType = "typescript";
public matches(path: string): boolean {
// Check if some of these files are written in Go.
const typescriptFileExtensionRegex = /\.ts$/;
const dirFiles = readdirSync(path);
return dirFiles.some((file) => file.match(typescriptFileExtensionRegex));
}
}
@@ -0,0 +1,23 @@
import { LibraryDetector } from "../detector";
import { existsSync, readFileSync } from "fs";
import { LibraryType } from "../../types/ProjectType";
import { parsePackageJson } from "../../../lib/utils";
export default class ExpressDetector implements LibraryDetector {
public libraryType: LibraryType = "express";
public matches(path: string): boolean {
const packageJsonPath = path + "/package.json";
if (!existsSync(packageJsonPath)) {
return false;
}
const packageJson = readFileSync(packageJsonPath);
const { dependencies, devDependencies } = parsePackageJson(packageJson);
const expressDependencyExists =
dependencies["express"] || devDependencies["express"] || false;
return expressDependencyExists;
}
}
@@ -0,0 +1,14 @@
import { LibraryDetector } from "../detector";
import { existsSync } from "fs";
import { LibraryType } from "../../types/ProjectType";
export default class PlayMakerDetector implements LibraryDetector {
public libraryType: LibraryType = "playmaker";
public matches(path: string): boolean {
const foundPlayMaker = existsSync(path + "/Assets/PlayMaker");
const foundPlayMakerDLL = existsSync(path + "/Editor/PlayMaker.dll");
return foundPlayMaker || foundPlayMakerDLL || false;
}
}
@@ -0,0 +1,23 @@
import { LibraryDetector } from "../detector";
import { existsSync, readFileSync } from "fs";
import { LibraryType } from "../../types/ProjectType";
import { parsePackageJson } from "../../../lib/utils";
export default class ReactDetector implements LibraryDetector {
public libraryType: LibraryType = "react";
public matches(path: string): boolean {
const packageJsonPath = path + "/package.json";
if (!existsSync(packageJsonPath)) {
return false;
}
const packageJson = readFileSync(packageJsonPath);
const { dependencies, devDependencies } = parsePackageJson(packageJson);
const reactDependencyExists =
dependencies["react"] || devDependencies["react"] || false;
return reactDependencyExists;
}
}
@@ -0,0 +1,23 @@
import { LibraryDetector } from "../detector";
import { existsSync, readFileSync } from "fs";
import { LibraryType } from "../../types/ProjectType";
import { parsePackageJson } from "../../../lib/utils";
export default class ReactNativeDetector implements LibraryDetector {
public libraryType: LibraryType = "react-native";
public matches(path: string): boolean {
const packageJsonPath = path + "/package.json";
if (!existsSync(packageJsonPath)) {
return false;
}
const packageJson = readFileSync(packageJsonPath);
const { dependencies, devDependencies } = parsePackageJson(packageJson);
const reactNativeDependencyExists =
dependencies["react-native"] || devDependencies["react-native"] || false;
return reactNativeDependencyExists;
}
}
@@ -0,0 +1,23 @@
import { LibraryDetector } from "../detector";
import { existsSync, readFileSync } from "fs";
import { LibraryType } from "../../types/ProjectType";
import { parsePackageJson } from "../../../lib/utils";
export default class ViteDetector implements LibraryDetector {
public libraryType: LibraryType = "vite";
public matches(path: string): boolean {
const packageJsonPath = path + "/package.json";
if (!existsSync(packageJsonPath)) {
return false;
}
const packageJson = readFileSync(packageJsonPath);
const { dependencies, devDependencies } = parsePackageJson(packageJson);
const viteDependencyExists =
dependencies["vite"] || devDependencies["vite"] || false;
return viteDependencyExists;
}
}
@@ -0,0 +1,18 @@
import { LibraryDetector } from "../detector";
import { LibraryType, PackageManagerType } from "../../types/ProjectType";
import { getDependenciesForPython } from "../../../lib/utils";
export default class Web3PyDetector implements LibraryDetector {
public libraryType: LibraryType = "web3py";
public matches(path: string, packageManager: PackageManagerType): boolean {
const { dependencies, devDependencies } = getDependenciesForPython(
path,
packageManager,
);
return (
dependencies.includes("web3") || devDependencies.includes("web3") || false
);
}
}
@@ -0,0 +1,20 @@
import { PackageManagerDetector } from "../detector";
import { existsSync } from "fs";
import { PackageManagerType } from "../../types/ProjectType";
export default class CondaDetector implements PackageManagerDetector {
public packageManagerType: PackageManagerType = "conda";
public matches(path: string): boolean {
const files = [
"/environment.yml",
"/environment.yaml",
"/conda-requirements.txt",
"/.conda",
"/.condarc",
];
// Check if at least one of these files exists in the current path.
return files.some((file) => existsSync(path + file));
}
}
@@ -0,0 +1,11 @@
import { PackageManagerDetector } from "../detector";
import { existsSync } from "fs";
import { PackageManagerType } from "../../types/ProjectType";
export default class GoModulesDetector implements PackageManagerDetector {
public packageManagerType: PackageManagerType = "go-modules";
public matches(path: string): boolean {
return existsSync(path + "/go.mod");
}
}
@@ -0,0 +1,11 @@
import { PackageManagerDetector } from "../detector";
import { existsSync } from "fs";
import { PackageManagerType } from "../../types/ProjectType";
export default class NPMDetector implements PackageManagerDetector {
public packageManagerType: PackageManagerType = "npm";
public matches(path: string): boolean {
return existsSync(path + "/package-lock.json");
}
}
@@ -0,0 +1,11 @@
import { PackageManagerDetector } from "../detector";
import { existsSync } from "fs";
import { PackageManagerType } from "../../types/ProjectType";
export default class PipDetector implements PackageManagerDetector {
public packageManagerType: PackageManagerType = "pip";
public matches(path: string): boolean {
return existsSync(path + "/requirements.txt");
}
}
@@ -0,0 +1,14 @@
import { PackageManagerDetector } from "../detector";
import { existsSync } from "fs";
import { PackageManagerType } from "../../types/ProjectType";
export default class PipEnvDetector implements PackageManagerDetector {
public packageManagerType: PackageManagerType = "pipenv";
public matches(path: string): boolean {
const files = ["/Pipfile", "/Pipfile.lock"];
// Check if at least one of these files exists in the current path.
return files.some((file) => existsSync(path + file));
}
}
@@ -0,0 +1,14 @@
import { PackageManagerDetector } from "../detector";
import { existsSync } from "fs";
import { PackageManagerType } from "../../types/ProjectType";
export default class PnpmDetector implements PackageManagerDetector {
public packageManagerType: PackageManagerType = "pnpm";
public matches(path: string): boolean {
const files = ["/pnpm-lock.yaml", "/pnpm-workspace.yaml", "/.pnpm"];
// Check if at least one of these files exists in the current path.
return files.some((file) => existsSync(path + file));
}
}
@@ -0,0 +1,14 @@
import { PackageManagerDetector } from "../detector";
import { existsSync } from "fs";
import { PackageManagerType } from "../../types/ProjectType";
export default class PoetryDetector implements PackageManagerDetector {
public packageManagerType: PackageManagerType = "poetry";
public matches(path: string): boolean {
const files = ["/pyproject.toml", "/poetry.lock"];
// Check if at least one of these files exists in the current path.
return files.some((file) => existsSync(path + file));
}
}
@@ -0,0 +1,11 @@
import { PackageManagerDetector } from "../detector";
import { existsSync } from "fs";
import { PackageManagerType } from "../../types/ProjectType";
export default class YarnDetector implements PackageManagerDetector {
public packageManagerType: PackageManagerType = "yarn";
public matches(path: string): boolean {
return existsSync(path + "/yarn.lock");
}
}
@@ -10,4 +10,77 @@ export type ProjectType =
| "spa-webapp"
| "yarn"
| "npm"
| "none"
| "pnpm";
export type PackageManagerType =
| "yarn"
| "npm"
| "pnpm"
| "pip"
| "conda"
| "pipenv"
| "poetry"
| "go-modules"
| "none";
export type LanguageType =
| "javascript"
| "typescript"
| "python"
| "go"
| "c#"
| "solidity"
| "none";
export type FrameworkType =
| "next"
| "gatsby"
| "remix"
| "cra"
| "vue"
| "expo"
| "react-native-cli"
| "express"
| "hardhat"
| "truffle"
| "foundry"
| "brownie"
| "solc"
| "django"
| "flask"
| "fastapi"
| "populus"
| "fastify"
| "gin"
| "echo"
| "revel"
| "fiber"
| "zenject"
| "none";
export type LibraryType =
| "react"
| "react-native"
| "vue"
| "svelte"
| "vite"
| "express"
| "web3py"
| "playmaker"
| "none";
export type AppType = "app" | "contract" | "library" | "none";
export type ContractLibrariesType =
| "brownie"
| "foundry"
| "hardhat"
| "truffle"
| "solc"
| "none";
export const contractLibraries: readonly ContractLibrariesType[] = [
"brownie",
"foundry",
"hardhat",
"truffle",
"solc",
"none",
] as const;
+1 -1
View File
@@ -1,2 +1,2 @@
declare module 'sync-disk-cache';
declare module "sync-disk-cache";
declare module "solc";
+131
View File
@@ -0,0 +1,131 @@
import * as toml from "@iarna/toml";
import * as yaml from "js-yaml";
import { PackageManagerType } from "../core/types/ProjectType";
import { existsSync, readFileSync } from "fs";
export const parsePackageJson = (packageJson: Buffer) => {
const packageJsonContent = JSON.parse(packageJson.toString());
const dependencies = packageJsonContent.dependencies || {};
const devDependencies = packageJsonContent.devDependencies || {};
return { dependencies, devDependencies };
};
export const parseRequirementsTxt = (requirementsTxt: Buffer) => {
const requirementsTxtContent = requirementsTxt.toString();
const dependencies = requirementsTxtContent.split("\n");
return { dependencies };
};
export const parsePipFile = (PipFile: string) => {
const pipfile = toml.parse(PipFile);
const dependencies = (pipfile.packages as string[]) || [];
const devDependencies = (pipfile["dev-packages"] as string[]) || [];
return {
dependencies,
devDependencies,
};
};
export const parsePyProjectToml = (pyProjectToml: string) => {
const pyProjectFile = toml.parse(pyProjectToml) as any;
const dependencies =
(pyProjectFile["tool"]["poetry"]["dependencies"] as string[]) || [];
const devDependencies =
(pyProjectFile["tool"]["poetry"]["dev-dependencies"] as string[]) || [];
return {
dependencies,
devDependencies,
};
};
export const parseCondaYml = (condaYml: string) => {
const conda = yaml.load(condaYml) as any;
const dependencies = (conda.dependencies as string[]) || [];
return {
dependencies,
};
};
export const parseGoMod = (goModContent: string) => {
const dependencies: { name: string; version: string }[] = [];
const lines: string[] = goModContent.split("\n");
lines.forEach((line) => {
line = line.trim();
if (line.startsWith("require (")) {
let i = lines.indexOf(line) + 1;
while (i < lines.length && lines[i].trim() !== ")") {
const dependencyLine = lines[i].trim();
const [name, version] = dependencyLine.split(" ");
dependencies.push({ name, version });
i++;
}
}
});
return {
dependencies,
};
};
export const fileContainsImport = (file: string, importToCheck: string) => {
const lines = file.split("\n");
lines.forEach(() => {
if (lines.includes(importToCheck)) {
return true;
}
});
return false;
};
export const getDependenciesForPython = (
path: string,
packageManager: PackageManagerType,
) => {
let dependencies: string[] = [];
let devDependencies: string[] = [];
switch (packageManager) {
case "pip" || "pipenv":
const foundPipFile = existsSync(path + "Pipfile");
if (foundPipFile) {
const pipFile = readFileSync(path + "Pipfile", "utf-8");
const parsedPipFile = parsePipFile(pipFile);
dependencies = parsedPipFile.dependencies;
devDependencies = parsedPipFile.devDependencies;
break;
}
const foundRequirementsTxt = existsSync(path + "/requirements.txt");
if (!foundRequirementsTxt) {
break;
}
const requirementsTxt = readFileSync(path + "/requirements.txt");
dependencies = parseRequirementsTxt(requirementsTxt).dependencies;
break;
case "poetry":
const foundPyProjectToml = existsSync(path + "/pyproject.toml");
if (!foundPyProjectToml) {
break;
}
const pyProjectFile = readFileSync(path + "/pyproject.toml", "utf-8");
dependencies = parsePyProjectToml(pyProjectFile).dependencies;
break;
case "conda":
const foundCondaYml = existsSync(path + "/environment.yml");
if (!foundCondaYml) {
break;
}
const condaYml = readFileSync(path + "/environment.yml", "utf-8");
dependencies = parseCondaYml(condaYml).dependencies;
default:
break;
}
return {
dependencies,
devDependencies,
};
};
+1 -1
View File
@@ -26,7 +26,7 @@
"typescript": "^4.7.4"
},
"peerDependencies": {
"ethers": "^5.7.0"
"ethers": "^5"
},
"files": [
"dist/",
+47
View File
@@ -1,5 +1,52 @@
# @thirdweb-dev/react-core
## 3.12.0
### Minor Changes
- [#993](https://github.com/thirdweb-dev/js/pull/993) [`b1ede491`](https://github.com/thirdweb-dev/js/commit/b1ede491fbfbeca0ff3d6f5a6162546671bf8b99) Thanks [@0xfrosty](https://github.com/0xfrosty)! - Add React hook useBuyDirectListing() to buy a direct listing in a MarketplaceV3 contract
### Patch Changes
- [#1015](https://github.com/thirdweb-dev/js/pull/1015) [`39bd9630`](https://github.com/thirdweb-dev/js/commit/39bd963015ac00a1e4da2d0b4c9d85b334c7ad46) Thanks [@MananTank](https://github.com/MananTank)! - - add `selectUI` api in `WalletConfig` to allow rendering a custom UI for selecting a wallet
- Render an input for paper wallet and magic link using `selectUI` api
- add prop `modalTitle` on `ConnectWallet` to configure a custom title for the modal
- add props `selectionData`, `setSelectionData` and `supportedWallets` on `connectUI`
- [#996](https://github.com/thirdweb-dev/js/pull/996) [`c3645c45`](https://github.com/thirdweb-dev/js/commit/c3645c451b5e9a0fcf651fa07eb0e31ebf1882ca) Thanks [@MananTank](https://github.com/MananTank)! - - add `theme` in `ConfiguredWallet.connectUI`'s props - to use theme aware UI for wallets
- add `useWalletConfig` hook to get the `ConfiguredWallet` object for active wallet
- add hooks `useSetConnectedWallet`, `useSetConnectionStatus`
- rename `useActiveChain` to `useChain` - keep the `useActiveChain` also with deprecated tag
- make `useSafe` hook await-able by returning the promise of connect() call
- add hook `useSmartWallet`
- allow rendering custom wallet details button via `<ConnectWallet detailsButton={} />` prop
- Rename "Export" to "Backup" in local wallet UI
- [#1011](https://github.com/thirdweb-dev/js/pull/1011) [`470e0a14`](https://github.com/thirdweb-dev/js/commit/470e0a144db6aa03e7789e231bbdfae43144f0e0) Thanks [@MananTank](https://github.com/MananTank)! - rename ConfiguredWallet to WalletConfig
```diff
- import { ConfiguredWallet } from '@thirdweb-dev/react';
+ import { WalletConfig } from '@thirdweb-dev/react';
```
- [#989](https://github.com/thirdweb-dev/js/pull/989) [`8db78299`](https://github.com/thirdweb-dev/js/commit/8db78299ea6cfb51d93b91bb1a351644a83c73d2) Thanks [@iketw](https://github.com/iketw)! - [React/ReactNative] Updated useThirdwebWallet to useWalletContext
- Updated dependencies [[`e9b69300`](https://github.com/thirdweb-dev/js/commit/e9b69300d15b233609f1ed897256ec9a1eef3e28), [`49ec2d17`](https://github.com/thirdweb-dev/js/commit/49ec2d171ecb1c9240398b7b486a452eb9429979), [`799d98e8`](https://github.com/thirdweb-dev/js/commit/799d98e86258677ab72931fa8397aee653fe8b34), [`c3645c45`](https://github.com/thirdweb-dev/js/commit/c3645c451b5e9a0fcf651fa07eb0e31ebf1882ca), [`470e0a14`](https://github.com/thirdweb-dev/js/commit/470e0a144db6aa03e7789e231bbdfae43144f0e0), [`738c0ec6`](https://github.com/thirdweb-dev/js/commit/738c0ec6c4190aa2252233c1382aed5d982cc7b8), [`d495a4b8`](https://github.com/thirdweb-dev/js/commit/d495a4b8a6e0599e5b4611620f3fded80a411173), [`482f6d1b`](https://github.com/thirdweb-dev/js/commit/482f6d1b58ac99b331fc750d3eeb6082556fd526), [`e4356e76`](https://github.com/thirdweb-dev/js/commit/e4356e76d1506624afe2eb6feeaf57dc376f372f), [`9886c858`](https://github.com/thirdweb-dev/js/commit/9886c858d9c8d0f677aba6572dbf5cc6c876edf2), [`8db78299`](https://github.com/thirdweb-dev/js/commit/8db78299ea6cfb51d93b91bb1a351644a83c73d2), [`4f843833`](https://github.com/thirdweb-dev/js/commit/4f8438335e3e3731b67ae271cb34c383832242a0)]:
- @thirdweb-dev/[email protected]
- @thirdweb-dev/[email protected]
- @thirdweb-dev/[email protected]
## 3.11.11
### Patch Changes
- Updated dependencies [[`32908b76`](https://github.com/thirdweb-dev/js/commit/32908b76832c60e91a0a6e40dbdb1c8f56e9e5be), [`6a4aab0b`](https://github.com/thirdweb-dev/js/commit/6a4aab0b8a2e0f6ff1b47992a3c1e5426a74f7ff), [`6a4aab0b`](https://github.com/thirdweb-dev/js/commit/6a4aab0b8a2e0f6ff1b47992a3c1e5426a74f7ff)]:
- @thirdweb-dev/[email protected]
- @thirdweb-dev/[email protected]
- @thirdweb-dev/[email protected]
## 3.11.10
### Patch Changes
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@thirdweb-dev/react-core",
"version": "3.11.10",
"version": "3.12.0",
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/react-core",
"author": "thirdweb eng <[email protected]>",
"license": "Apache-2.0",
@@ -49,6 +49,7 @@ const MARKETPLACE_HOOKS = [
"useCreateAuctionListing",
"useMakeBid",
"useBuyNow",
"useBuyDirectListing",
];
const DROP_HOOKS = [
@@ -1,11 +1,11 @@
import { useThirdwebWallet } from "../providers/thirdweb-wallet-provider";
import { useWalletContext } from "../providers/thirdweb-wallet-provider";
import invariant from "tiny-invariant";
/**
* @returns the current active wallet instance
*/
export function useWallet() {
const context = useThirdwebWallet();
const context = useWalletContext();
invariant(
context,
"useWallet() hook must be used within a <ThirdwebProvider/>",
@@ -13,12 +13,24 @@ export function useWallet() {
return context.activeWallet;
}
/**
* @returns the current active wallet's configuration object
*/
export function useWalletConfig() {
const context = useWalletContext();
invariant(
context,
"useWallet() hook must be used within a <ThirdwebProvider/>",
);
return context.activeWalletConfig;
}
/**
*
* @returns `supportedWallets` configured in the `<ThirdwebProvider/>`
*/
export function useWallets() {
const context = useThirdwebWallet();
const context = useWalletContext();
invariant(
context,
"useWallets() hook must be used within a <ThirdwebProvider/>",
@@ -31,7 +43,7 @@ export function useWallets() {
* @returns a method to connect to a wallet class
*/
export function useConnect() {
const context = useThirdwebWallet();
const context = useWalletContext();
invariant(
context,
"useConnect() hook must be used within a <ThirdwebProvider/>",
@@ -44,7 +56,7 @@ export function useConnect() {
* @returns a method to disconnect from the current active wallet
*/
export function useDisconnect() {
const context = useThirdwebWallet();
const context = useWalletContext();
invariant(
context,
"useDisconnect() hook must be used within a <ThirdwebProvider/>",
@@ -64,7 +76,7 @@ export function useDisconnect() {
*
*/
export function useConnectionStatus() {
const context = useThirdwebWallet();
const context = useWalletContext();
invariant(
context,
"useConnectionStatus() must be used within a <ThirdwebProvider/>",
@@ -74,19 +86,15 @@ export function useConnectionStatus() {
/**
*
* @returns if the wallet is currently connecting
*
* @returns a method to create an instance of given wallet class
*/
export function useIsConnecting() {
const context = useThirdwebWallet();
export function useSetConnectionStatus() {
const context = useWalletContext();
invariant(
context,
"useConnectionStatus() must be used within a <ThirdwebProvider/>",
);
return (
context.connectionStatus === "connecting" ||
context.connectionStatus === "unknown"
"useSetConnectionStatus() must be used within a <ThirdwebProvider/>",
);
return context.setConnectionStatus;
}
/**
@@ -94,7 +102,7 @@ export function useIsConnecting() {
* @returns a method to create an instance of given wallet class
*/
export function useCreateWalletInstance() {
const context = useThirdwebWallet();
const context = useWalletContext();
invariant(
context,
"useCreateWalletInstance() must be used within a <ThirdwebProvider/>",
@@ -107,10 +115,23 @@ export function useCreateWalletInstance() {
* @returns a method to connect the wallet to network/chain with given chainId
*/
export function useSwitchChain() {
const context = useThirdwebWallet();
const context = useWalletContext();
invariant(
context,
"useSwitchChain() must be used within a <ThirdwebProvider/>",
);
return context.switchChain;
}
/**
*
* @returns a method to set a connected wallet instance
*/
export function useSetConnectedWallet() {
const context = useWalletContext();
invariant(
context,
"useSwitchChain() must be used within a <ThirdwebProvider/>",
);
return context.setConnectedWallet;
}
@@ -2,11 +2,11 @@ import { ThirdwebAuthProvider } from "../../evm/contexts/thirdweb-auth";
import { useUpdateChainsWithApiKeys } from "../../evm/hooks/chain-hooks";
import { ThirdwebSDKProvider } from "../../evm/providers/thirdweb-sdk-provider";
import { ThirdwebSDKProviderProps } from "../../evm/providers/types";
import { ConfiguredWallet } from "../types/wallet";
import { WalletConfig } from "../types/wallet";
import { ThirdwebThemeContext } from "./theme-context";
import {
ThirdwebWalletProvider,
useThirdwebWallet,
useWalletContext,
} from "./thirdweb-wallet-provider";
import { Chain, defaultChains } from "@thirdweb-dev/chains";
import {
@@ -40,7 +40,7 @@ export interface ThirdwebProviderCoreProps<TChains extends Chain[]>
* };
* ```
*/
supportedWallets: ConfiguredWallet[];
supportedWallets: WalletConfig[];
/**
* Metadata to pass to wallet connect and walletlink wallet connect. (Used to show *which* dApp is being connected to in mobile wallets that support it)
@@ -172,7 +172,7 @@ const ThirdwebSDKProviderWrapper = <TChains extends Chain[]>({
}: React.PropsWithChildren<
Omit<ThirdwebSDKProviderProps<TChains>, "signer">
>) => {
const signer = useThirdwebWallet()?.signer;
const signer = useWalletContext()?.signer;
return (
<ThirdwebSDKProvider signer={signer} {...props}>
@@ -1,5 +1,5 @@
import { DAppMetaData } from "../types/dAppMeta";
import type { ConfiguredWallet, WalletInstance } from "../types/wallet";
import type { WalletConfig, WalletInstance } from "../types/wallet";
import { ThirdwebThemeContext } from "./theme-context";
import { Chain } from "@thirdweb-dev/chains";
import {
@@ -41,41 +41,60 @@ type WalletConnectParams<I extends WalletInstance> = Parameters<
type ConnectionStatus = "unknown" | "connected" | "disconnected" | "connecting";
type ConnectFnArgs<I extends WalletInstance> =
type ConnectFnArgs<
I extends WalletInstance,
Config extends Record<string, any> | undefined,
> =
// if second argument is optional
undefined extends WalletConnectParams<I>
? [
wallet: ConfiguredWallet<I>,
wallet: WalletConfig<I, Config>,
connectParams?: NonNullable<WalletConnectParams<I>>,
]
: // if second argument is required
[
wallet: ConfiguredWallet<I>,
wallet: WalletConfig<I, Config>,
connectParams: NonNullable<WalletConnectParams<I>>,
];
// maps wallet instance to it's wallet config
const walletInstanceToConfig: Map<
WalletInstance,
WalletConfig<any, any>
> = new Map();
type ThirdwebWalletContextData = {
wallets: ConfiguredWallet[];
wallets: WalletConfig[];
signer?: Signer;
activeWallet?: WalletInstance;
activeWalletConfig?: ConfiguredWallet;
connect: <I extends WalletInstance>(
...args: ConnectFnArgs<I>
activeWalletConfig?: WalletConfig;
connect: <
I extends WalletInstance,
Config extends Record<string, any> | undefined = undefined,
>(
...args: ConnectFnArgs<I, Config>
) => Promise<void>;
disconnect: () => Promise<void>;
connectionStatus: ConnectionStatus;
setConnectionStatus: (status: ConnectionStatus) => void;
createWalletInstance: <I extends WalletInstance>(
Wallet: ConfiguredWallet<I>,
createWalletInstance: <
I extends WalletInstance,
Config extends Record<string, any> | undefined,
>(
Wallet: WalletConfig<I, Config>,
) => I;
createWalletStorage: CreateAsyncStorage;
switchChain: (chain: number) => Promise<void>;
chainToConnect?: Chain;
activeChain: Chain;
handleWalletConnect: (
setConnectedWallet: (
wallet: WalletInstance,
params?: ConnectParams<Record<string, any>>,
) => void;
/**
* Get wallet config object from wallet instance
*/
getWalletConfig: (walletInstance: WalletInstance) => WalletConfig | undefined;
};
const ThirdwebWalletContext = createContext<
@@ -85,7 +104,7 @@ const ThirdwebWalletContext = createContext<
export function ThirdwebWalletProvider(
props: PropsWithChildren<{
activeChain: Chain;
supportedWallets: ConfiguredWallet[];
supportedWallets: WalletConfig[];
shouldAutoConnect?: boolean;
createWalletStorage: CreateAsyncStorage;
dAppMeta?: DAppMetaData;
@@ -101,8 +120,8 @@ export function ThirdwebWalletProvider(
WalletInstance | undefined
>();
const [activeWalletConfig, setActiveConfig] = useState<
ConfiguredWallet | undefined
const [activeWalletConfig, setActiveWalletConfig] = useState<
WalletConfig | undefined
>();
if (!lastConnectedWalletStorage) {
@@ -130,8 +149,12 @@ export function ThirdwebWalletProvider(
}, [props.chains, props.dAppMeta, props.activeChain, theme]);
const createWalletInstance = useCallback(
<I extends WalletInstance>(wallet: ConfiguredWallet<I>): I => {
return wallet.create(walletParams);
<I extends WalletInstance, Config extends Record<string, any> | undefined>(
walletConfig: WalletConfig<I, Config>,
): I => {
const walletInstance = walletConfig.create(walletParams);
walletInstanceToConfig.set(walletInstance, walletConfig);
return walletInstance;
},
[walletParams],
);
@@ -143,35 +166,20 @@ export function ThirdwebWalletProvider(
}
}, [activeWallet, props.chains]);
const getWalletConfig = useCallback(
(wallet: WalletInstance) => {
const id = wallet.walletId;
// find in personal wallets if wrapper wallet
if (
activeWalletConfig &&
"config" in activeWalletConfig &&
(activeWalletConfig.config as any).personalWallets
) {
// find in personal wallets
return (activeWalletConfig.config as any).personalWallets.find(
(w: ConfiguredWallet) => w.id === id,
);
}
return props.supportedWallets.find((w) => w.id === id);
},
[activeWalletConfig, props.supportedWallets],
);
const handleWalletConnect = useCallback(
const setConnectedWallet = useCallback(
async (
wallet: WalletInstance,
connectParams?: ConnectParams<Record<string, any>>,
isAutoConnect = false,
) => {
setActiveWallet(wallet);
setActiveConfig(getWalletConfig(wallet));
const walletConfig = walletInstanceToConfig.get(wallet);
if (!walletConfig) {
throw new Error(
"Wallet config not found for given wallet instance. Do not create a wallet instance manually - use the useCreateWalletInstance() hook instead",
);
}
setActiveWalletConfig(walletConfig);
setConnectionStatus("connected");
const _signer = await wallet.getSigner();
setSigner(_signer);
@@ -182,19 +190,21 @@ export function ThirdwebWalletProvider(
}
// save to storage
const walletInfo: LastConnectedWalletInfo = {
walletId: wallet.walletId,
walletId: walletConfig.id,
connectParams,
};
// if personal wallet exists, we need to replace the connectParams.personalWallet to a stringifiable version
const personalWallet = wallet.getPersonalWallet() as AbstractClientWallet;
const personalWalletConfig = walletInstanceToConfig.get(personalWallet);
if (personalWallet) {
if (personalWallet && personalWalletConfig) {
walletInfo.connectParams = {
...walletInfo.connectParams,
personalWallet: {
walletId: personalWallet.walletId,
walletId: personalWalletConfig.id,
connectParams: personalWallet.getConnectParams(),
},
};
@@ -204,7 +214,7 @@ export function ThirdwebWalletProvider(
saveLastConnectedWalletInfo(walletInfo);
}
},
[getWalletConfig],
[],
);
const storeLastActiveChainId = useCallback(async (chainId: number) => {
@@ -291,7 +301,7 @@ export function ThirdwebWalletProvider(
if (personalWalletInfo) {
type Config = {
personalWallets: ConfiguredWallet[];
personalWallets: WalletConfig[];
};
const personalWallets =
@@ -334,7 +344,7 @@ export function ThirdwebWalletProvider(
try {
setConnectionStatus("connecting");
await wallet.autoConnect(walletInfo.connectParams);
handleWalletConnect(wallet, walletInfo.connectParams, true);
setConnectedWallet(wallet, walletInfo.connectParams, true);
} catch (e) {
lastConnectedWalletStorage.removeItem(
LAST_CONNECTED_WALLET_STORAGE_KEY,
@@ -348,14 +358,19 @@ export function ThirdwebWalletProvider(
}, [
createWalletInstance,
props.supportedWallets,
handleWalletConnect,
setConnectedWallet,
props.shouldAutoConnect,
activeWallet,
connectionStatus,
]);
const connectWallet = useCallback(
async <I extends WalletInstance>(...args: ConnectFnArgs<I>) => {
async <
I extends WalletInstance,
Config extends Record<string, any> | undefined = undefined,
>(
...args: ConnectFnArgs<I, Config>
) => {
const [WalletObj, connectParams] = args;
const _connectedParams = {
@@ -367,14 +382,14 @@ export function ThirdwebWalletProvider(
setConnectionStatus("connecting");
try {
await wallet.connect(_connectedParams);
handleWalletConnect(wallet, _connectedParams);
setConnectedWallet(wallet, _connectedParams);
} catch (e: any) {
console.error(`Error connecting to wallet: ${e}`);
setConnectionStatus("disconnected");
throw e;
}
},
[createWalletInstance, handleWalletConnect, chainToConnect],
[createWalletInstance, setConnectedWallet, chainToConnect],
);
const onWalletDisconnect = useCallback(async () => {
@@ -384,7 +399,7 @@ export function ThirdwebWalletProvider(
setConnectionStatus("disconnected");
setSigner(undefined);
setActiveWallet(undefined);
setActiveConfig(undefined);
setActiveWalletConfig(undefined);
}, []);
const disconnectWallet = useCallback(async () => {
@@ -443,9 +458,12 @@ export function ThirdwebWalletProvider(
createWalletInstance: createWalletInstance,
createWalletStorage: props.createWalletStorage,
switchChain,
handleWalletConnect,
setConnectedWallet: setConnectedWallet,
activeChain: props.activeChain,
chainToConnect,
getWalletConfig: (walletInstance: WalletInstance) => {
return walletInstanceToConfig.get(walletInstance);
},
}}
>
{props.children}
@@ -453,11 +471,11 @@ export function ThirdwebWalletProvider(
);
}
export function useThirdwebWallet() {
export function useWalletContext() {
const ctx = useContext(ThirdwebWalletContext);
if (!ctx) {
throw new Error(
`useThirdwebWallet() can only be used inside <ThirdwebProvider />`,
`useWalletContext() can only be used inside <ThirdwebProvider />`,
);
}
return ctx;
+104 -4
View File
@@ -15,7 +15,7 @@ export type WalletOptions = {
dappMetadata?: DAppMetaData;
} & ExtraCoreWalletOptions;
export type WalletInstance = InstanceType<typeof AbstractClientWallet>;
export type WalletInstance = AbstractClientWallet;
export type WalletClass<I extends WalletInstance = WalletInstance> = {
id: string;
@@ -23,14 +23,21 @@ export type WalletClass<I extends WalletInstance = WalletInstance> = {
meta: (typeof AbstractClientWallet)["meta"];
};
export type ConfiguredWallet<
export type WalletConfig<
I extends WalletInstance = WalletInstance,
Config extends Record<string, any> | undefined = undefined,
> = {
id: string;
meta: (typeof AbstractClientWallet)["meta"];
create: (options: WalletOptions) => I;
connectUI?: React.FC<ConnectUIProps>;
/**
* UI for connecting wallet
*/
connectUI?: React.FC<ConnectUIProps<I, Config>>;
/**
* UI for selecting wallet - this UI is rendered in the wallet selection screen
*/
selectUI?: React.FC<SelectUIProps<I, Config>>;
isInstalled?: () => boolean;
} & (Config extends undefined
? {}
@@ -38,7 +45,10 @@ export type ConfiguredWallet<
config: Config;
});
export type ConnectUIProps = {
export type ConnectUIProps<
I extends WalletInstance = WalletInstance,
Config extends Record<string, any> | undefined = undefined,
> = {
/**
* close the connect wallet modal
* @param reset reset Connect Wallet Modal to initial state, so that if it's opened again, it will start from the wallet-selection screen
@@ -61,4 +71,94 @@ export type ConnectUIProps = {
* go back to the wallet selector screen in connect wallet modal
*/
goBack: () => void;
/**
* theme of the connect wallet modal
*/
theme: "dark" | "light";
/**
* `WalletConfig` object of your wallet
*
* you can use this to connect to your wallet
*
* ### 1. Using `useConnect` hook
* ```ts
* const connect = useConnect();
*
* // call this function to connect to your wallet
* async function handleConnect() {
* await connect(walletConfig, options);
* }
*
* ```
*
* OR
*
* ### 2. Manually creating wallet instance and connecting
* ```ts
* const createWalletInstance = useCreateWalletInstance();
* const setConnectedWallet = useSetConnectedWallet();
* const setConnectionStatus = useSetConnectionStatus();
*
* // call this function to connect to your wallet
* async function handleConnect() {
* // create instance
* const walletInstance = createWalletInstance(walletConfig);
* // connect wallet
* setConnectionStatus('connecting);
* try {
* await walletInstance.connect(options);
* // set connected wallet
* setConnectedWallet(walletInstance);
* } catch {
* setConnectionStatus('disconnected');
* }
* }
* ```
*/
walletConfig: WalletConfig<I, Config>;
/**
* selectionData passed from `selectUI`'s `onSelect` function
*/
selectionData: any;
/**
* set selectionData
* @returns
*/
setSelectionData: (data: any) => void;
/**
* List of all supported wallets including your wallet.
*/
supportedWallets: WalletConfig[];
};
export type SelectUIProps<
I extends WalletInstance = WalletInstance,
Config extends Record<string, any> | undefined = undefined,
> = {
/**
* Call this function to "select" your wallet and render the screen for connecting the wallet
* @param selectionData - selectionData to be passed to `connectUI`'s `selectionData` prop
* @returns
*/
onSelect: (selectionData: any) => void;
/**
* `WalletConfig` object of your wallet
*
* you can use this get metadata of your wallet by doing `walletConfig.meta`
*/
walletConfig: WalletConfig<I, Config>;
/**
* List of all supported wallets including your wallet.
*
* You can use this to conditionally render UI based on how many wallets are supported.
* For example: You can render a larger UI if only one wallet (your wallet) is supported.
*/
supportedWallets: WalletConfig[];
};
@@ -5,6 +5,7 @@ import {
import { useSDKChainId } from "../../providers/thirdweb-sdk-provider";
import {
AcceptDirectOffer,
BuyFromListingParams,
BuyNowParams,
ExecuteAuctionSale,
MakeBidParams,
@@ -1380,6 +1381,71 @@ export function useBuyNow(contract: RequiredParam<Marketplace>) {
);
}
/**
* Buy a direct listing
*
* @example
* ```jsx
* const Component = () => {
* const { contract } = useContract("{{contract_address}}", "marketplace-v3");
* const {
* mutate: buyNow,
* isLoading,
* error,
* } = useBuyDirectListing(contract);
*
* if (error) {
* console.error("failed to buy direct listing", error);
* }
*
* return (
* <button
* disabled={isLoading}
* onClick={() => buyNow({listingId: 1, quantity: 1, buyer: "{{address}}"})}
* >
* Buy listing!
* </button>
* );
* };
* ```
*
* @param contract - an instance of a MarketplaceV3 contract
* @returns a mutation object that can be used to buy out a direct listing
* @see {@link https://portal.thirdweb.com/react/react.useBuyDirectListing?utm_source=sdk | Documentation}
* @beta
*/
export function useBuyDirectListing(contract: RequiredParam<MarketplaceV3>) {
const activeChainId = useSDKChainId();
const contractAddress = contract?.getAddress();
const queryClient = useQueryClient();
const walletAddress = useAddress();
return useMutation(
async (data: BuyFromListingParams) => {
invariant(walletAddress, "no wallet connected, cannot buy from listing");
requiredParamInvariant(contract, "No Contract instance provided");
invariant(
contract.directListings.buyFromListing,
"contract does not support directListings.buyFromListing"
);
return await contract.directListings.buyFromListing(
data.listingId,
data.quantity,
data.buyer
);
},
{
onSettled: () =>
invalidateContractAndBalances(
queryClient,
contractAddress,
activeChainId,
),
},
);
}
function isMarketplaceV1(
contract: RequiredParam<Marketplace | MarketplaceV3>,
): contract is Marketplace {
@@ -1,7 +1,7 @@
import { useThirdwebWallet } from "../../core/providers/thirdweb-wallet-provider";
import { useWalletContext } from "../../core/providers/thirdweb-wallet-provider";
export function useSupportedWallet(id: string) {
const context = useThirdwebWallet();
const context = useWalletContext();
const wallet = context?.wallets.find((_wallet) => _wallet.id === id);
if (!wallet) {
throw new Error(`Wallet with id "${id}" is not supported`);
+15 -4
View File
@@ -103,16 +103,16 @@ export function useChainId(): number | undefined {
* Hook for accessing the active Chain the current wallet is connected to
*
* ```javascript
* import { useActiveChain } from "@thirdweb-dev/react-core"
* import { useChain } from "@thirdweb-dev/react-core"
* ```
*
* @example
* You can get the chain of the connected wallet by using the hook as follows:
* ```javascript
* import { useActiveChain } from "@thirdweb-dev/react-core"
* import { useChain } from "@thirdweb-dev/react-core"
*
* const App = () => {
* const chain = useActiveChain()
* const chain = useChain()
*
* return <div>{chain.chainId}</div>
* }
@@ -120,7 +120,7 @@ export function useChainId(): number | undefined {
* @see {@link https://portal.thirdweb.com/react/react.useActiveChain?utm_source=sdk | Documentation}
* @public
*/
export function useActiveChain(): Chain | undefined {
export function useChain(): Chain | undefined {
const chainId = useChainId();
const chains = useSupportedChains();
@@ -137,3 +137,14 @@ export function useActiveChain(): Chain | undefined {
return chain || unknownChain;
}
/**
* @deprecated
*
* This hook is renamed to `useChain`
*
* use the `useChain` hook instead
*/
export function useActiveChain() {
return useChain();
}
+8 -3
View File
@@ -16,10 +16,12 @@ export {
useDisconnect,
useSwitchChain,
useWallets,
useIsConnecting,
useWalletConfig,
useSetConnectionStatus,
useSetConnectedWallet,
} from "../core/hooks/wallet-hooks";
export { useNetwork } from "../core/hooks/useNetwork";
export { useThirdwebWallet } from "../core/providers/thirdweb-wallet-provider";
export { useWalletContext } from "../core/providers/thirdweb-wallet-provider";
// connected wallet hooks
export {
@@ -28,14 +30,16 @@ export {
useAddress,
useChainId,
useActiveChain,
useChain,
} from "./hooks/wallet";
// Utilities and Others
export { shouldNeverPersistQuery } from "../core/query-utils/query-key";
export type { RequiredParam } from "../core/query-utils/required-param";
export type {
ConfiguredWallet,
WalletConfig,
ConnectUIProps,
SelectUIProps,
WalletClass,
WalletInstance,
ExtraCoreWalletOptions,
@@ -149,6 +153,7 @@ export {
useExecuteAuctionSale,
useOffers,
useBuyNow,
useBuyDirectListing,
} from "./hooks/async/marketplace";
// nft
+6
View File
@@ -268,6 +268,12 @@ export type BuyNowParams<TListingType = ListingType> =
type: ListingType.Auction;
};
export type BuyFromListingParams = {
listingId: string;
quantity: Amount;
buyer: WalletAddress;
};
// TOKEN DROP //
export type ClaimTokenParams = {
@@ -1,5 +1,9 @@
# @thirdweb-dev/react-native-compat
## 0.2.12
## 0.2.11
## 0.2.10
## 0.2.9
+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.10",
"version": "0.2.12",
"author": "thirdweb eng <[email protected]>",
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/react-native-compat",
"license": "Apache-2.0",
+95
View File
@@ -1,5 +1,100 @@
# @thirdweb-dev/react-native
## 0.2.12
### Patch Changes
- [#995](https://github.com/thirdweb-dev/js/pull/995) [`482f6d1b`](https://github.com/thirdweb-dev/js/commit/482f6d1b58ac99b331fc750d3eeb6082556fd526) Thanks [@iketw](https://github.com/iketw)! - [ReactNative] update export local wallet modal UI
- [#996](https://github.com/thirdweb-dev/js/pull/996) [`c3645c45`](https://github.com/thirdweb-dev/js/commit/c3645c451b5e9a0fcf651fa07eb0e31ebf1882ca) Thanks [@MananTank](https://github.com/MananTank)! - - add `theme` in `ConfiguredWallet.connectUI`'s props - to use theme aware UI for wallets
- add `useWalletConfig` hook to get the `ConfiguredWallet` object for active wallet
- add hooks `useSetConnectedWallet`, `useSetConnectionStatus`
- rename `useActiveChain` to `useChain` - keep the `useActiveChain` also with deprecated tag
- make `useSafe` hook await-able by returning the promise of connect() call
- add hook `useSmartWallet`
- allow rendering custom wallet details button via `<ConnectWallet detailsButton={} />` prop
- Rename "Export" to "Backup" in local wallet UI
- [#1011](https://github.com/thirdweb-dev/js/pull/1011) [`470e0a14`](https://github.com/thirdweb-dev/js/commit/470e0a144db6aa03e7789e231bbdfae43144f0e0) Thanks [@MananTank](https://github.com/MananTank)! - rename ConfiguredWallet to WalletConfig
```diff
- import { ConfiguredWallet } from '@thirdweb-dev/react';
+ import { WalletConfig } from '@thirdweb-dev/react';
```
- [#1019](https://github.com/thirdweb-dev/js/pull/1019) [`8a0dd070`](https://github.com/thirdweb-dev/js/commit/8a0dd070d4f4cb4d30b313e72827abf6f91f3f17) Thanks [@iketw](https://github.com/iketw)! - ## [ReactNative] Adds modalTitle, buttonTitle and detailsButton props to the ConnectWallet component
You can now customize the following props:
1. `buttonTitle`
The title of the ConnectWallet button which defaults to: "Connect Wallet":
```javascript
<ConnectWallet buttonTitle="Connect to claim" />
```
2. `modalTitle`
The title of the ConnectWallet modal which defaults to: "Choose your wallet":
```javascript
<ConnectWallet modalTitle="Select a wallet" />
```
3. `detailsButton`
The button that shows the details of the connected wallet. By default it shows
the chain icon, wallet balance, account address and wallet icon:
```javascript
const customDetailsButton = (
<View>
<Text>Connected button details</Text>
<Text>{shortenWalletAddress(address)}</Text>
</View>
);
<ConnectWallet detailsButton={customDetailsButton} />;
```
### Web3Button
The `buttonTitle` and `modalTitle` props are also available in the `Web3Button` config since we show a `ConnectWallet` button
if you don't have a connected wallet:
```javascript
<Web3Button
connectWalletProps={{
buttonTitle: "Connect to claim",
modalTitle: "Pick a wallet",
}}
contractAddress="contract-address"
action={(contract) => contract?.erc1155.claim(0, 1)}
>
Claim Factory
</Web3Button>
```
- [#989](https://github.com/thirdweb-dev/js/pull/989) [`8db78299`](https://github.com/thirdweb-dev/js/commit/8db78299ea6cfb51d93b91bb1a351644a83c73d2) Thanks [@iketw](https://github.com/iketw)! - [React/ReactNative] Updated useThirdwebWallet to useWalletContext
- Updated dependencies [[`e9b69300`](https://github.com/thirdweb-dev/js/commit/e9b69300d15b233609f1ed897256ec9a1eef3e28), [`39bd9630`](https://github.com/thirdweb-dev/js/commit/39bd963015ac00a1e4da2d0b4c9d85b334c7ad46), [`49ec2d17`](https://github.com/thirdweb-dev/js/commit/49ec2d171ecb1c9240398b7b486a452eb9429979), [`799d98e8`](https://github.com/thirdweb-dev/js/commit/799d98e86258677ab72931fa8397aee653fe8b34), [`c3645c45`](https://github.com/thirdweb-dev/js/commit/c3645c451b5e9a0fcf651fa07eb0e31ebf1882ca), [`470e0a14`](https://github.com/thirdweb-dev/js/commit/470e0a144db6aa03e7789e231bbdfae43144f0e0), [`b1ede491`](https://github.com/thirdweb-dev/js/commit/b1ede491fbfbeca0ff3d6f5a6162546671bf8b99), [`738c0ec6`](https://github.com/thirdweb-dev/js/commit/738c0ec6c4190aa2252233c1382aed5d982cc7b8), [`d495a4b8`](https://github.com/thirdweb-dev/js/commit/d495a4b8a6e0599e5b4611620f3fded80a411173), [`482f6d1b`](https://github.com/thirdweb-dev/js/commit/482f6d1b58ac99b331fc750d3eeb6082556fd526), [`e4356e76`](https://github.com/thirdweb-dev/js/commit/e4356e76d1506624afe2eb6feeaf57dc376f372f), [`9886c858`](https://github.com/thirdweb-dev/js/commit/9886c858d9c8d0f677aba6572dbf5cc6c876edf2), [`8db78299`](https://github.com/thirdweb-dev/js/commit/8db78299ea6cfb51d93b91bb1a351644a83c73d2), [`4f843833`](https://github.com/thirdweb-dev/js/commit/4f8438335e3e3731b67ae271cb34c383832242a0)]:
- @thirdweb-dev/[email protected]
- @thirdweb-dev/[email protected]
- @thirdweb-dev/[email protected]
- @thirdweb-dev/[email protected]
## 0.2.11
### Patch Changes
- Updated dependencies [[`32908b76`](https://github.com/thirdweb-dev/js/commit/32908b76832c60e91a0a6e40dbdb1c8f56e9e5be), [`6a4aab0b`](https://github.com/thirdweb-dev/js/commit/6a4aab0b8a2e0f6ff1b47992a3c1e5426a74f7ff), [`6a4aab0b`](https://github.com/thirdweb-dev/js/commit/6a4aab0b8a2e0f6ff1b47992a3c1e5426a74f7ff)]:
- @thirdweb-dev/[email protected]
- @thirdweb-dev/[email protected]
- @thirdweb-dev/[email protected]
- @thirdweb-dev/[email protected]
## 0.2.10
### Patch Changes
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@thirdweb-dev/react-native",
"version": "0.2.10",
"version": "0.2.12",
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/react-native",
"author": "thirdweb eng <[email protected]>",
"license": "Apache-2.0",
@@ -2,14 +2,33 @@ import { ThemeProvider, ThemeProviderProps } from "../styles/ThemeProvider";
import { ConnectWalletDetails } from "./ConnectWalletDetails/ConnectWalletDetails";
import { ConnectWalletFlow } from "./ConnectWalletFlow/ConnectWalletFlow";
import { useAddress } from "@thirdweb-dev/react-core";
import { useEffect, useRef } from "react";
import React, { useEffect, useRef } from "react";
import { Animated } from "react-native";
export type ConnectWalletProps = {
theme?: ThemeProviderProps["theme"];
/**
* Set a custom title for the button
* @default "Connect Wallet"
*/
buttonTitle?: string;
/**
* Set a custom title for the Connect Wallet modal
* @default "Choose your wallet"
*/
modalTitle?: string;
/**
* render a custom button to display the connected wallet details instead of the default button
*/
detailsButton?: React.ReactElement;
};
export const ConnectWallet = ({ theme }: ConnectWalletProps) => {
export const ConnectWallet = ({
buttonTitle,
detailsButton,
modalTitle,
theme,
}: ConnectWalletProps) => {
const fadeAnim = useRef(new Animated.Value(0)).current;
const address = useAddress();
@@ -26,9 +45,15 @@ export const ConnectWallet = ({ theme }: ConnectWalletProps) => {
<ThemeProvider theme={theme}>
<Animated.View style={{ opacity: fadeAnim }}>
{address ? (
<ConnectWalletDetails address={address} />
<ConnectWalletDetails
address={address}
detailsButton={detailsButton}
/>
) : (
<ConnectWalletFlow />
<ConnectWalletFlow
buttonTitle={buttonTitle}
modalTitle={modalTitle}
/>
)}
</Animated.View>
</ThemeProvider>
@@ -17,14 +17,19 @@ import { Toast } from "../base/Toast";
import { LocalWallet, SmartWallet, walletIds } from "@thirdweb-dev/wallets";
import { SmartWalletAdditionalActions } from "./SmartWalletAdditionalActions";
import { useSmartWallet } from "../../providers/context-provider";
import RightArrowIcon from "../../assets/right-arrow";
import { useTheme } from "@shopify/restyle";
export type ConnectWalletDetailsProps = {
address: string;
detailsButton?: React.ReactElement;
};
export const ConnectWalletDetails = ({
address,
detailsButton,
}: ConnectWalletDetailsProps) => {
const theme = useTheme();
const [isDetailsModalVisible, setIsDetailsModalVisible] = useState(false);
const [isExportModalVisible, setIsExportModalVisible] = useState(false);
const [isNetworkSelectorModalVisible, setIsNetworkSelectorModalVisible] =
@@ -105,13 +110,21 @@ export const ConnectWalletDetails = ({
backgroundColor="background"
borderColor="border"
mb="sm"
justifyContent="space-between"
style={styles.exportWallet}
onPress={onExportLocalWalletPress}
>
<PocketWalletIcon size={16} />
<View style={styles.exportWalletInfo}>
<Text variant="bodySmall">Backup wallet</Text>
</View>
<>
<PocketWalletIcon size={16} />
<View style={styles.exportWalletInfo}>
<Text variant="bodySmall">Backup wallet</Text>
</View>
</>
<RightArrowIcon
height={10}
width={10}
color={theme.colors.iconPrimary}
/>
</BaseButton>
{activeWallet?.walletId === LocalWallet.id ? (
@@ -126,7 +139,12 @@ export const ConnectWalletDetails = ({
}
return null;
}, [activeWallet?.walletId, onExportLocalWalletPress, smartWallet]);
}, [
activeWallet?.walletId,
onExportLocalWalletPress,
smartWallet,
theme.colors.iconPrimary,
]);
return (
<>
@@ -168,19 +186,28 @@ export const ConnectWalletDetails = ({
style={styles.walletDetails}
onPress={onPress}
>
<ChainIcon size={32} chainIconUrl={chain?.icon?.url} />
<View style={styles.walletInfo}>
<Text variant="bodySmall">
{balanceQuery.data?.displayValue.slice(0, 5)}{" "}
{balanceQuery.data?.symbol}
</Text>
{activeWallet?.walletId === LocalWallet.id ? (
<Text variant="error">Guest</Text>
) : (
<Address variant="bodySmallSecondary" address={address} />
)}
</View>
<WalletIcon size={32} iconUri={activeWallet?.getMeta().iconURL || ""} />
{detailsButton ? (
detailsButton
) : (
<>
<ChainIcon size={32} chainIconUrl={chain?.icon?.url} />
<View style={styles.walletInfo}>
<Text variant="bodySmall">
{balanceQuery.data?.displayValue.slice(0, 5)}{" "}
{balanceQuery.data?.symbol}
</Text>
{activeWallet?.walletId === LocalWallet.id ? (
<Text variant="error">Guest</Text>
) : (
<Address variant="bodySmallSecondary" address={address} />
)}
</View>
<WalletIcon
size={32}
iconUri={activeWallet?.getMeta().iconURL || ""}
/>
</>
)}
</BaseButton>
</>
);
@@ -14,9 +14,11 @@ import { ModalHeaderTextClose } from "../base/modal/ModalHeaderTextClose";
import { useAddress, useWallet } from "@thirdweb-dev/react-core";
import { PasswordInput } from "../PasswordInput";
import * as FileSystem from "expo-file-system";
import { LocalWallet } from "../../wallets/wallets/local-wallet";
import { SmartWallet } from "@thirdweb-dev/wallets";
import { usePersonalWalletAddress } from "../../wallets/hooks/usePersonalWalletAddress";
import { shortenWalletAddress } from "../../utils/addresses";
import { WalletIcon } from "../base/WalletIcon";
import { LocalWallet } from "../../wallets/wallets/LocalWallet";
export type ExportLocalWalletModalProps = {
isVisible: boolean;
@@ -148,11 +150,14 @@ export const ExportLocalWalletModal = ({
borderRadius="md"
p="lg"
>
<ModalHeaderTextClose headerText={""} onClose={onCloseInternal} />
<Text variant="header" textAlign="center">
Export your Wallet
<Box flexDirection="row" justifyContent="space-between" mb="sm">
<WalletIcon size={32} iconUri={LocalWallet.meta.iconURL} />
<ModalHeaderTextClose flex={1} onClose={onCloseInternal} />
</Box>
<Text variant="header" textAlign="left">
Backup your Wallet
</Text>
<Text variant="subHeader" mt="md" textAlign="center">
<Text variant="subHeader" mt="md" textAlign="left">
{
"This will download a JSON file containing your wallet information onto your device encrypted with the password."
}
@@ -161,7 +166,9 @@ export const ExportLocalWalletModal = ({
Wallet Address
</Text>
<Text variant="bodySmallSecondary">
{personalWalletAddress ? personalWalletAddress : address}
{shortenWalletAddress(
personalWalletAddress ? personalWalletAddress : address,
)}
</Text>
<Text variant="bodySmall" textAlign="left" mt="lg" mb="xxs">
Password
@@ -170,12 +177,7 @@ export const ExportLocalWalletModal = ({
<Text variant="bodySmall" color="red" mt="xs" textAlign="left">
{error}
</Text>
<Box
flexDirection="row"
justifyContent="center"
paddingHorizontal="md"
mt="lg"
>
<Box flexDirection="row" justifyContent="flex-end" mt="lg">
<BaseButton
backgroundColor="white"
style={styles.modalButton}
@@ -185,7 +187,7 @@ export const ExportLocalWalletModal = ({
<ActivityIndicator size="small" color="buttonTextColor" />
) : (
<Text variant="bodySmall" color="black">
Export
Backup
</Text>
)}
</BaseButton>
@@ -2,12 +2,15 @@ import { StyleSheet, View } from "react-native";
import PocketWalletIcon from "../../assets/wallet";
import BaseButton from "../base/BaseButton";
import { WalletIcon } from "../base/WalletIcon";
import { AbstractClientWallet, SmartWallet } from "@thirdweb-dev/wallets";
import {
AbstractClientWallet,
SmartWallet,
walletIds,
} from "@thirdweb-dev/wallets";
import { Address } from "../base/Address";
import Text from "../base/Text";
import { usePersonalWalletAddress } from "../../wallets/hooks/usePersonalWalletAddress";
import { LocalWallet } from "../../wallets/wallets/local-wallet";
import { useThirdwebWallet, useWallet } from "@thirdweb-dev/react-core";
import { useWalletContext, useWallet } from "@thirdweb-dev/react-core";
import { useEffect, useState } from "react";
import { useSmartWallet } from "../../providers/context-provider";
import RightArrowIcon from "../../assets/right-arrow";
@@ -19,7 +22,7 @@ export const SmartWalletAdditionalActions = ({
onExportPress: () => void;
}) => {
const personalWalletAddress = usePersonalWalletAddress();
const handleWalletConnect = useThirdwebWallet().handleWalletConnect;
const { setConnectedWallet } = useWalletContext();
const [smartWallet, setSmartWallet] = useSmartWallet();
const [smartWalletAddress, setSmartWalletAddress] = useState<string>("");
const [showSmartWallet, setShowSmartWallet] = useState(false);
@@ -53,7 +56,7 @@ export const SmartWalletAdditionalActions = ({
return;
}
handleWalletConnect(wallet);
setConnectedWallet(wallet);
};
return (
@@ -90,24 +93,32 @@ export const SmartWalletAdditionalActions = ({
color={theme.colors.iconPrimary}
/>
</BaseButton>
{wallet?.walletId === LocalWallet.id ||
activeWallet?.walletId === LocalWallet.id ? (
{wallet?.walletId === walletIds.localWallet ||
activeWallet?.walletId === walletIds.localWallet ? (
<>
<BaseButton
backgroundColor="background"
borderColor="border"
mb="sm"
justifyContent="space-between"
style={styles.exportWallet}
onPress={onExportPress}
>
<PocketWalletIcon size={16} />
<View style={styles.exportWalletInfo}>
<Text variant="bodySmall">
{wallet?.walletId === LocalWallet.id
? "Backup personal wallet"
: "Backup wallet"}
</Text>
</View>
<>
<PocketWalletIcon size={16} />
<View style={styles.exportWalletInfo}>
<Text variant="bodySmall">
{wallet?.walletId === walletIds.localWallet
? "Backup personal wallet"
: "Backup wallet"}
</Text>
</View>
</>
<RightArrowIcon
height={10}
width={10}
color={theme.colors.iconPrimary}
/>
</BaseButton>
<Text variant="error">
{

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