Compare commits

...
Author SHA1 Message Date
github-actions[bot]GitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>
4df0c2ee10 Version Packages (#1542)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-08-28 17:36:13 -07:00
Mariano FuentesandGitHub 48a8f9385e [CLI] - Update cors restrictions on login (#1552) 2023-08-29 00:20:07 +00:00
Joaquim VergesandGitHub a91776e121 [all] fix changesets (#1553) 2023-08-28 17:12:24 -07:00
Joaquim VergesandGitHub f5aed34d3c update chains + fix opbnb-testnet (#1551) 2023-08-29 00:02:20 +00:00
0f02706906 Use auth token for CLI (#1422)
Co-authored-by: Adam Majmudar <[email protected]>
2023-08-28 16:42:07 +00:00
iketwandGitHub eb463735e2 [React/Wallets] Adds a new RainbowWallet that supports Rainbow browser extension (#1544) 2023-08-28 13:00:31 +00:00
Joaquim VergesandGitHub adec589ead [SDK] Expose joinAbis() utility function (#1545) 2023-08-28 03:30:51 +00:00
saminaandGitHub e5246f2667 Update README.md (#1531) 2023-08-26 00:53:32 +00:00
b29ec675f9 [react] export ConnectModalInline component for ConnectWallet playground (#1532)
Co-authored-by: Joaquim Verges <[email protected]>
2023-08-26 00:27:56 +00:00
Joaquim VergesandGitHub b30566c684 [Chains] updated chains (#1540) 2023-08-26 00:15:47 +00:00
github-actions[bot]GitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>
182a4e7e8f Version Packages (#1528)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-08-25 09:03:36 -07:00
iketwandGitHub 8b82f3c59c [CLI] Adds support for PWA Vite template (#1538) 2023-08-25 15:38:21 +00:00
YashandGitHub f59b729f8b [SDK] Fix auto-factory deployment: correct bytecode format (#1537) 2023-08-25 14:19:39 +00:00
iketwandGitHub 387dddbd87 [RN] Adds switchToActiveChain to the ConnectWallet button (#1536) 2023-08-25 13:10:17 +00:00
YashandGitHub 911e14fcac [Chains] Add Chiliz Spicy testnet (#1530) 2023-08-24 18:35:05 +00:00
cd6b07b591 feat(sdk): centralize contract reads (#1520)
Co-authored-by: Joaquim Verges <[email protected]>
2023-08-24 04:29:26 +00:00
YashandGitHub 154c55add5 Contracts version 3.9.3-0 (#1527) 2023-08-24 03:33:49 +00:00
github-actions[bot]GitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>
f202f597ca Version Packages (#1517)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-08-23 20:25:07 -07:00
YashandGitHub 91f0245be7 [SDK] Fix getChainProvider (#1526) 2023-08-24 00:00:03 +00:00
Joaquim VergesandGitHub ae74b8ef62 [SDK] separate ERC1155Supply extension from ERC1155 (#1523) 2023-08-23 22:23:17 +00:00
YashandGitHub 5a373a7509 [SDK] Correct polygon rpc for fetching published contract (#1525) 2023-08-23 19:22:16 +00:00
Manan TankandGitHub 088547f763 [react] various ConnectWallet improvements (#1522) 2023-08-23 17:48:04 +00:00
586e91dbe6 [SDK] Publish dynamic contract (#1488)
Co-authored-by: Nacho Iacovino <[email protected]>
2023-08-23 14:27:40 +00:00
Joaquim VergesandGitHub f65578d637 [SDK] Optimize contract resolution + Fallback to bytecode extension detection for un-imported contracts (#1498) 2023-08-23 00:03:52 +00:00
447d984653 [SDK] Airdrops (#1288)
Co-authored-by: Atharva Deosthale <[email protected]>
2023-08-22 13:26:31 +00:00
nkrishangandGitHub 34a3bb8ae3 [SDK][REACT] Update contracts release (#1518) 2023-08-22 04:31:36 +00:00
Joaquim VergesandGitHub bc003c2fef [SDK] Return early for claim checks when possible (#1516) 2023-08-22 00:01:06 +00:00
github-actions[bot]GitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>
c88fa57591 Version Packages (#1509)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-08-21 12:17:36 -07:00
Jonas DanielsandGitHub c12f0874b4 feat(chains): add new chains (#1513) 2023-08-21 18:20:53 +00:00
Jonas DanielsandGitHub 184c325ab2 fix(chains): Update icon URL for chains 37 and 47 (#1508) 2023-08-19 02:19:31 +00:00
046c9ad604 moved res.json() to avoid getting JSON error in console (#1501)
Co-authored-by: Jonas Daniels <[email protected]>
2023-08-19 02:09:58 +00:00
github-actions[bot]GitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>
2a7bbf8665 Version Packages (#1507)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-08-18 18:18:39 -07:00
Jonas DanielsandGitHub f97ddf4c7f [chains] - add xpla chains & update chains (#1506) 2023-08-19 01:01:08 +00:00
228 changed files with 5849 additions and 1306 deletions
+35
View File
@@ -1,5 +1,40 @@
# @thirdweb-dev/auth
## 3.2.38
### Patch Changes
- Updated dependencies [[`eb463735`](https://github.com/thirdweb-dev/js/commit/eb463735e2f784cd1d212a982835af95cf60766b), [`0f027069`](https://github.com/thirdweb-dev/js/commit/0f027069064bebe647f9235fa86ef7f165ffc7b3)]:
- @thirdweb-dev/wallets@1.1.21
## 3.2.37
### Patch Changes
- Updated dependencies []:
- @thirdweb-dev/wallets@1.1.20
## 3.2.36
### Patch Changes
- Updated dependencies []:
- @thirdweb-dev/wallets@1.1.19
## 3.2.35
### Patch Changes
- Updated dependencies []:
- @thirdweb-dev/wallets@1.1.18
## 3.2.34
### Patch Changes
- Updated dependencies []:
- @thirdweb-dev/wallets@1.1.17
## 3.2.33
### Patch Changes
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@thirdweb-dev/auth",
"version": "3.2.33",
"version": "3.2.38",
"main": "dist/thirdweb-dev-auth.cjs.js",
"module": "dist/thirdweb-dev-auth.esm.js",
"browser": {
+37
View File
@@ -1,5 +1,42 @@
# @thirdweb-dev/chains
## 0.1.49
### Patch Changes
- [#1540](https://github.com/thirdweb-dev/js/pull/1540) [`b30566c6`](https://github.com/thirdweb-dev/js/commit/b30566c68436ad94ddc938a380eccc13a8a7147d) Thanks [@joaquim-verges](https://github.com/joaquim-verges)! - updated chains
- [#1422](https://github.com/thirdweb-dev/js/pull/1422) [`0f027069`](https://github.com/thirdweb-dev/js/commit/0f027069064bebe647f9235fa86ef7f165ffc7b3) Thanks [@Marfuen](https://github.com/Marfuen)! - CLI will now use an OAuth like login flow to authenticate the device with the wallet on the dashboard.
Any actions performed by the CLI will be linked to your account / wallet on the dashboard, including but not limited to tracking your usage, and billing as needed.
- [#1551](https://github.com/thirdweb-dev/js/pull/1551) [`f5aed34d`](https://github.com/thirdweb-dev/js/commit/f5aed34d3c71065c3f45df2c1eb84ba9c36162d5) Thanks [@joaquim-verges](https://github.com/joaquim-verges)! - Update chains
## 0.1.48
### Patch Changes
- [#1530](https://github.com/thirdweb-dev/js/pull/1530) [`911e14fc`](https://github.com/thirdweb-dev/js/commit/911e14fcac743b07fa1a66440c72d662c08e971c) Thanks [@kumaryash90](https://github.com/kumaryash90)! - Add Chiliz Spicy testnet
## 0.1.47
### Patch Changes
- [#1518](https://github.com/thirdweb-dev/js/pull/1518) [`34a3bb8a`](https://github.com/thirdweb-dev/js/commit/34a3bb8ae3c1d7a506e5568a9e79ab7e469557a8) Thanks [@nkrishang](https://github.com/nkrishang)! - Update contracts package
## 0.1.46
### Patch Changes
- [#1508](https://github.com/thirdweb-dev/js/pull/1508) [`184c325a`](https://github.com/thirdweb-dev/js/commit/184c325ab2ef028022a050c4274f2ab12b1a3a7f) Thanks [@jnsdls](https://github.com/jnsdls)! - update xpla chain icons
- [#1513](https://github.com/thirdweb-dev/js/pull/1513) [`c12f0874`](https://github.com/thirdweb-dev/js/commit/c12f0874b4dac43c263c7edb20d0343c16381c34) Thanks [@jnsdls](https://github.com/jnsdls)! - add additonal chains
## 0.1.45
### Patch Changes
- [#1506](https://github.com/thirdweb-dev/js/pull/1506) [`f97ddf4c`](https://github.com/thirdweb-dev/js/commit/f97ddf4c7f14854f3b204ad9741b52ddb8dac736) Thanks [@jnsdls](https://github.com/jnsdls)! - add xpla chains & update chains
## 0.1.44
### Patch Changes
+3 -1
View File
@@ -15,7 +15,9 @@ export default {
"https://eth-mainnet.g.alchemy.com/v2/${ALCHEMY_API_KEY}",
"https://api.mycryptoapi.com/eth",
"https://cloudflare-eth.com",
"https://ethereum.publicnode.com"
"https://ethereum.publicnode.com",
"https://mainnet.gateway.tenderly.co",
"wss://mainnet.gateway.tenderly.co"
],
"features": [
{
+3 -1
View File
@@ -7,7 +7,9 @@ export default {
"https://optimism-mainnet.infura.io/v3/${INFURA_API_KEY}",
"https://opt-mainnet.g.alchemy.com/v2/${ALCHEMY_API_KEY}",
"https://mainnet.optimism.io",
"https://optimism.publicnode.com"
"https://optimism.publicnode.com",
"https://optimism.gateway.tenderly.co",
"wss://optimism.gateway.tenderly.co"
],
"faucets": [],
"nativeCurrency": {
+1
View File
@@ -18,6 +18,7 @@ export default {
"https://gnosis.api.onfinality.io/public",
"https://gnosis.blockpi.network/v1/rpc/public",
"https://web3endpoints.com/gnosischain-mainnet",
"https://gnosis.oat.farm",
"wss://rpc.gnosischain.com/wss"
],
"faucets": [
+3 -1
View File
@@ -10,7 +10,9 @@ export default {
"https://rpc.sepolia.org",
"https://rpc2.sepolia.org",
"https://rpc-sepolia.rockx.com",
"https://rpc.sepolia.ethpandaops.io"
"https://rpc.sepolia.ethpandaops.io",
"https://sepolia.gateway.tenderly.co",
"wss://sepolia.gateway.tenderly.co"
],
"faucets": [
"http://fauceth.komputing.org?chain=11155111&address=${ADDRESS}"
-25
View File
@@ -1,25 +0,0 @@
import type { Chain } from "../src/types";
export default {
"name": "DeBank Testnet",
"chain": "DeBank",
"rpc": [],
"faucets": [],
"icon": {
"url": "ipfs://QmW9pBps8WHRRWmyXhjLZrjZJUe8F48hUu7z98bu2RVsjN",
"width": 400,
"height": 400,
"format": "png"
},
"nativeCurrency": {
"name": "Ether",
"symbol": "ETH",
"decimals": 18
},
"infoURL": "https://debank.com",
"shortName": "debank-testnet",
"chainId": 115,
"networkId": 115,
"explorers": [],
"testnet": true,
"slug": "debank-testnet"
} as const satisfies Chain;
-25
View File
@@ -1,25 +0,0 @@
import type { Chain } from "../src/types";
export default {
"name": "DeBank Mainnet",
"chain": "DeBank",
"rpc": [],
"faucets": [],
"icon": {
"url": "ipfs://QmW9pBps8WHRRWmyXhjLZrjZJUe8F48hUu7z98bu2RVsjN",
"width": 400,
"height": 400,
"format": "png"
},
"nativeCurrency": {
"name": "Ether",
"symbol": "ETH",
"decimals": 18
},
"infoURL": "https://debank.com",
"shortName": "debank-mainnet",
"chainId": 116,
"networkId": 116,
"explorers": [],
"testnet": false,
"slug": "debank"
} as const satisfies Chain;
+8 -2
View File
@@ -17,8 +17,14 @@ export default {
"symbol": "MC",
"decimals": 18
},
"infoURL": "https://gaming.meritcircle.io",
"shortName": "BEAM",
"infoURL": "https://www.onbeam.com",
"shortName": "beam-testnet",
"icon": {
"url": "ipfs://QmQJ21NWyGGDraicVEzS1Uqq1yXahM9NCuNZgnfYvtspdt",
"width": 512,
"height": 512,
"format": "png"
},
"chainId": 13337,
"networkId": 13337,
"explorers": [
+3 -1
View File
@@ -18,7 +18,9 @@ export default {
"https://rpc-mainnet.maticvigil.com",
"https://rpc-mainnet.matic.quiknode.pro",
"https://matic-mainnet-full-rpc.bwarelabs.com",
"https://polygon-bor.publicnode.com"
"https://polygon-bor.publicnode.com",
"https://polygon.gateway.tenderly.co",
"wss://polygon.gateway.tenderly.co"
],
"faucets": [],
"nativeCurrency": {
+2 -2
View File
@@ -10,8 +10,8 @@ export default {
"https://t.me/HumanodeTestnet5FaucetBot"
],
"nativeCurrency": {
"name": "HMND",
"symbol": "HMND",
"name": "eHMND",
"symbol": "eHMND",
"decimals": 18
},
"infoURL": "https://humanode.io",
+19
View File
@@ -0,0 +1,19 @@
import type { Chain } from "../src/types";
export default {
"name": "Redbelly Network Mainnet",
"shortName": "rbn",
"chain": "RBN",
"chainId": 151,
"networkId": 151,
"rpc": [],
"faucets": [],
"infoURL": "https://redbelly.network",
"nativeCurrency": {
"name": "Redbelly Network Coin",
"symbol": "RBNT",
"decimals": 18
},
"status": "incubating",
"testnet": false,
"slug": "redbelly-network"
} as const satisfies Chain;
+19
View File
@@ -0,0 +1,19 @@
import type { Chain } from "../src/types";
export default {
"name": "Redbelly Network Devnet",
"shortName": "rbn-devnet",
"chain": "RBN",
"chainId": 152,
"networkId": 152,
"rpc": [],
"faucets": [],
"infoURL": "https://redbelly.network",
"nativeCurrency": {
"name": "Redbelly Network Coin",
"symbol": "RBNT",
"decimals": 18
},
"status": "incubating",
"testnet": false,
"slug": "redbelly-network-devnet"
} as const satisfies Chain;
+19
View File
@@ -0,0 +1,19 @@
import type { Chain } from "../src/types";
export default {
"name": "Redbelly Network Testnet",
"shortName": "rbn-testnet",
"chain": "RBN",
"chainId": 153,
"networkId": 153,
"rpc": [],
"faucets": [],
"infoURL": "https://redbelly.network",
"nativeCurrency": {
"name": "Redbelly Network Coin",
"symbol": "RBNT",
"decimals": 18
},
"status": "incubating",
"testnet": true,
"slug": "redbelly-network-testnet"
} as const satisfies Chain;
+18
View File
@@ -0,0 +1,18 @@
import type { Chain } from "../src/types";
export default {
"name": "Redbelly Network TGE",
"shortName": "rbn-tge",
"chain": "RBN",
"chainId": 154,
"networkId": 154,
"rpc": [],
"faucets": [],
"infoURL": "https://redbelly.network",
"nativeCurrency": {
"name": "Redbelly Network Coin",
"symbol": "RBNT",
"decimals": 18
},
"testnet": false,
"slug": "redbelly-network-tge"
} as const satisfies Chain;
+5 -5
View File
@@ -1,10 +1,10 @@
import type { Chain } from "../src/types";
export default {
"name": "Omni Testnet 1",
"name": "Omni Testnet",
"chain": "Omni",
"rpc": [
"https://omni-testnet-1.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://testnet-1.omni.network"
"https://omni-testnet.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://testnet.omni.network"
],
"features": [
{
@@ -24,10 +24,10 @@ export default {
"explorers": [
{
"name": "Omni Explorer",
"url": "https://testnet-1.explorer.omni.network",
"url": "https://testnet.explorer.omni.network",
"standard": "EIP3091"
}
],
"testnet": true,
"slug": "omni-testnet-1"
"slug": "omni-testnet"
} as const satisfies Chain;
+2 -2
View File
@@ -11,8 +11,8 @@ export default {
},
"rpc": [
"https://horizen-gobi-testnet.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://gobi-testnet.horizenlabs.io/ethv1",
"https://rpc.ankr.com/horizen_testnet_evm"
"https://gobi-rpc.horizenlabs.io/ethv1",
"https://rpc.ankr.com/horizen_gobi_testnet"
],
"features": [
{
+28
View File
@@ -0,0 +1,28 @@
import type { Chain } from "../src/types";
export default {
"name": "Bitchain Mainnet",
"chain": "Bit",
"rpc": [
"https://bitchain.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://rpc.bitchain.biz/"
],
"faucets": [],
"nativeCurrency": {
"name": "Bitcoin",
"symbol": "BTC",
"decimals": 18
},
"infoURL": "https://www.bitchain.biz/",
"shortName": "bit",
"chainId": 198,
"networkId": 198,
"explorers": [
{
"name": "Bitchain Scan",
"url": "https://explorer.bitchain.biz",
"standard": "EIP3091"
}
],
"testnet": false,
"slug": "bitchain"
} as const satisfies Chain;
+34
View File
@@ -0,0 +1,34 @@
import type { Chain } from "../src/types";
export default {
"name": "DeBank Testnet",
"chain": "DeBank",
"rpc": [
"https://debank-testnet.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"http://rpc.testnet.debank.com"
],
"faucets": [],
"icon": {
"url": "ipfs://QmW9pBps8WHRRWmyXhjLZrjZJUe8F48hUu7z98bu2RVsjN",
"width": 400,
"height": 400,
"format": "png"
},
"nativeCurrency": {
"name": "DeBank USD",
"symbol": "USD",
"decimals": 18
},
"infoURL": "https://debank.com",
"shortName": "dbk",
"chainId": 2021398,
"networkId": 2021398,
"explorers": [
{
"name": "DeBank Chain Explorer",
"url": "https://explorer.testnet.debank.com",
"standard": "EIP3091"
}
],
"testnet": true,
"slug": "debank-testnet"
} as const satisfies Chain;
+31
View File
@@ -0,0 +1,31 @@
import type { Chain } from "../src/types";
export default {
"name": "opBNB Mainnet",
"chain": "opBNB",
"rpc": [
"https://opbnb.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://opbnb-mainnet-rpc.bnbchain.org"
],
"faucets": [
"https://free-online-app.com/faucet-for-eth-evm-chains"
],
"nativeCurrency": {
"name": "BNB Chain Native Token",
"symbol": "BNB",
"decimals": 18
},
"infoURL": "https://opbnb.bnbchain.org/en",
"shortName": "obnb",
"chainId": 204,
"networkId": 204,
"slip44": 714,
"explorers": [
{
"name": "opbnbscan",
"url": "http://mainnet.opbnbscan.com",
"standard": "EIP3091"
}
],
"testnet": false,
"slug": "opbnb"
} as const satisfies Chain;
+5 -4
View File
@@ -1,10 +1,11 @@
import type { Chain } from "../src/types";
export default {
"name": "Kava EVM Testnet",
"name": "Kava Testnet",
"chain": "KAVA",
"rpc": [
"https://kava-evm-testnet.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://kava-testnet.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://evm.testnet.kava.io",
"https://kava-evm-testnet.rpc.thirdweb.com",
"wss://wevm.testnet.kava.io"
],
"faucets": [
@@ -28,7 +29,7 @@ export default {
"explorers": [
{
"name": "Kava Testnet Explorer",
"url": "https://explorer.testnet.kava.io",
"url": "http://testnet.kavascan.com",
"standard": "EIP3091",
"icon": {
"url": "ipfs://QmdpRTk6oL1HRW9xC6cAc4Rnf9gs6zgdAcr4Z3HcLztusm",
@@ -39,5 +40,5 @@ export default {
}
],
"testnet": true,
"slug": "kava-evm-testnet"
"slug": "kava-testnet"
} as const satisfies Chain;
+6 -4
View File
@@ -1,11 +1,13 @@
import type { Chain } from "../src/types";
export default {
"name": "Kava EVM",
"name": "Kava",
"chain": "KAVA",
"rpc": [
"https://kava-evm.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://kava.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://evm.kava.io",
"https://evm2.kava.io",
"https://kava-rpc.gateway.pokt.network",
"https://kava-evm.rpc.thirdweb.com",
"wss://wevm.kava.io",
"wss://wevm2.kava.io",
"https://kava-evm.publicnode.com"
@@ -29,7 +31,7 @@ export default {
"explorers": [
{
"name": "Kava EVM Explorer",
"url": "https://explorer.kava.io",
"url": "https://kavascan.com",
"standard": "EIP3091",
"icon": {
"url": "ipfs://QmdpRTk6oL1HRW9xC6cAc4Rnf9gs6zgdAcr4Z3HcLztusm",
@@ -40,5 +42,5 @@ export default {
}
],
"testnet": false,
"slug": "kava-evm"
"slug": "kava"
} as const satisfies Chain;
+5 -1
View File
@@ -4,7 +4,11 @@ export default {
"chain": "SOMA",
"rpc": [
"https://soma-network-testnet.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://data-testnet-v1.somanetwork.io/"
"https://data-testnet-v1.somanetwork.io/",
"https://testnet-au-server-2.somanetwork.io",
"https://testnet-au-server-1.somanetwork.io",
"https://testnet-sg-server-1.somanetwork.io",
"https://testnet-sg-server-2.somanetwork.io"
],
"faucets": [
"https://faucet.somanetwork.io"
+4 -1
View File
@@ -4,7 +4,10 @@ export default {
"chain": "SOMA",
"rpc": [
"https://soma-network.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://data-mainnet-v1.somanetwork.io/"
"https://data-mainnet-v1.somanetwork.io/",
"https://id-mainnet.somanetwork.io",
"https://hk-mainnet.somanetwork.io",
"https://sg-mainnet.somanetwork.io"
],
"faucets": [
"https://airdrop.somanetwork.io"
+34
View File
@@ -0,0 +1,34 @@
import type { Chain } from "../src/types";
export default {
"name": "Ancient8 Testnet",
"chain": "Ancient8",
"icon": {
"url": "ipfs://QmSX8sHToRzyFupT8BvPQjVsegRWFYz2mdnLkVnqBFKohY",
"width": 901,
"height": 901,
"format": "png"
},
"rpc": [
"https://ancient8-testnet.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://rpc-testnet.ancient8.gg"
],
"faucets": [],
"nativeCurrency": {
"name": "Ether",
"symbol": "ETH",
"decimals": 18
},
"infoURL": "https://ancient8.gg/",
"shortName": "a8",
"chainId": 2863311531,
"networkId": 2863311531,
"explorers": [
{
"name": "a8scan-testnet",
"url": "https://testnet.a8scan.io",
"standard": "EIP3091"
}
],
"testnet": true,
"slug": "ancient8-testnet"
} as const satisfies Chain;
+2 -2
View File
@@ -6,8 +6,8 @@ export default {
"https://boba-network.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://mainnet.boba.network",
"https://replica.boba.network",
"http://boba-ethereum.gateway.tenderly.co",
"http://gateway.tenderly.co/public/boba-ethereum",
"https://boba-ethereum.gateway.tenderly.co",
"https://gateway.tenderly.co/public/boba-ethereum",
"wss://boba-ethereum.gateway.tenderly.co/",
"wss://gateway.tenderly.co/public/boba-ethereum"
],
+21
View File
@@ -0,0 +1,21 @@
import type { Chain } from "../src/types";
export default {
"name": "Dubxcoin network",
"chain": "DUBX",
"rpc": [
"https://dubxcoin-network.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://rpcmain.arabianchain.org"
],
"faucets": [],
"nativeCurrency": {
"name": "Dubxcoin mainnet",
"symbol": "DUBX",
"decimals": 18
},
"infoURL": "https://arabianchain.org",
"shortName": "dubx",
"chainId": 3269,
"networkId": 3269,
"testnet": false,
"slug": "dubxcoin-network"
} as const satisfies Chain;
+23
View File
@@ -0,0 +1,23 @@
import type { Chain } from "../src/types";
export default {
"name": "Dubxcoin testnet",
"chain": "TESTDUBX",
"rpc": [
"https://dubxcoin-testnet.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://rpctestnet.arabianchain.org"
],
"faucets": [
"https://faucet.arabianchain.org/"
],
"nativeCurrency": {
"name": "Dubxcoin testnet",
"symbol": "TDUBX",
"decimals": 18
},
"infoURL": "https://arabianchain.org",
"shortName": "testdubx",
"chainId": 3270,
"networkId": 3270,
"testnet": true,
"slug": "dubxcoin-testnet"
} as const satisfies Chain;
+6
View File
@@ -5,6 +5,12 @@ export default {
"shortName": "POPTestnet",
"chainId": 331769,
"testnet": true,
"icon": {
"format": "png",
"url": "ipfs://QmP8rYvcc7aJB3c2YZxjxaySvHapHnoK8MnxuSuDT4PtF2",
"height": 400,
"width": 400
},
"rpc": [
"https://proofofpepe-testnet.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://testnet01.proofofpepe.tech"
+33
View File
@@ -0,0 +1,33 @@
import type { Chain } from "../src/types";
export default {
"name": "POP Mainnet",
"chain": "POP",
"shortName": "POP",
"chainId": 331771,
"testnet": false,
"icon": {
"format": "png",
"url": "ipfs://QmP8rYvcc7aJB3c2YZxjxaySvHapHnoK8MnxuSuDT4PtF2",
"height": 400,
"width": 400
},
"rpc": [
"https://pop.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://rpc00.proofofpepe.tech",
"https://rpc01.proofofpepe.tech",
"https://rpc02.proofofpepe.tech"
],
"nativeCurrency": {
"name": "Pepe",
"symbol": "PEPE",
"decimals": 18
},
"explorers": [
{
"name": "Pepescan",
"url": "https://pepescan.app",
"standard": "none"
}
],
"slug": "pop"
} as const satisfies Chain;
+23 -15
View File
@@ -1,27 +1,35 @@
import type { Chain } from "../src/types";
export default {
"name": "SeedCoin-Network",
"chain": "SeedCoin-Network",
"name": "Xpla Mainnet",
"chain": "XPLA",
"rpc": [
"https://seedcoin-network.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://node.seedcoin.network"
"https://xpla-xpla.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://dimension-evm-rpc.xpla.dev"
],
"faucets": [],
"nativeCurrency": {
"name": "SeedCoin",
"symbol": "SEED",
"name": "XPLA",
"symbol": "XPLA",
"decimals": 18
},
"infoURL": "https://www.seedcoin.network/",
"shortName": "SEED",
"infoURL": "https://xpla.io/",
"shortName": "xpla",
"chainId": 37,
"icon": {
"url": "ipfs://QmSchLvCCZjBzcv5n22v1oFDAc2yHJ42NERyjZeL9hBgrh",
"width": 64,
"height": 64,
"url": "ipfs://QmbvEAKZfgJckEziU3mpCwz6jqMeWRcLgd8TNsWA7g8sD9/xpla.png",
"width": 512,
"height": 512,
"format": "png"
},
"chainId": 37,
"networkId": 37,
"explorers": [
{
"name": "XPLA Explorer",
"url": "https://explorer.xpla.io",
"standard": "none"
}
],
"testnet": false,
"slug": "seedcoin-network"
"redFlags": [
"reusedChainId"
],
"slug": "xpla-xpla"
} as const satisfies Chain;
+36
View File
@@ -0,0 +1,36 @@
import type { Chain } from "../src/types";
export default {
"name": "Xpla Mainnet",
"chain": "XPLA",
"rpc": [
"https://xpla.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://dimension-rpc.xpla.dev"
],
"faucets": [
"https://faucet.xpla.io/"
],
"nativeCurrency": {
"name": "XPLA",
"symbol": "XPLA",
"decimals": 18
},
"infoURL": "https://xpla.io/",
"shortName": "xpla",
"chainId": 3701,
"networkId": 3701,
"icon": {
"url": "ipfs://Qmf4GoxfpeA5VGqu7KP5eyv1WKaCpNDbvMxq1MjQBwFWxq",
"width": 512,
"height": 512,
"format": "png"
},
"explorers": [
{
"name": "XPLA Explorer",
"url": "https://explorer.xpla.io",
"standard": "none"
}
],
"testnet": false,
"slug": "xpla"
} as const satisfies Chain;
+42
View File
@@ -0,0 +1,42 @@
import type { Chain } from "../src/types";
export default {
"name": "KalyChain Mainnet",
"chain": "KLC",
"icon": {
"url": "ipfs://QmUaXcPewLuQtY5a7xPTzJyVdjkH487VfV7gSR8UXrbxQ3",
"width": 512,
"height": 512,
"format": "png"
},
"rpc": [
"https://kalychain.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://rpc.kalychain.io/rpc"
],
"features": [
{
"name": "EIP155"
},
{
"name": "EIP1559"
}
],
"faucets": [],
"nativeCurrency": {
"name": "KalyCoin",
"symbol": "KLC",
"decimals": 18
},
"infoURL": "https://kalychain.io",
"shortName": "kalymainnet",
"chainId": 3888,
"networkId": 3888,
"explorers": [
{
"name": "KalyScan",
"url": "https://kalyscan.io",
"standard": "EIP3091"
}
],
"testnet": false,
"slug": "kalychain"
} as const satisfies Chain;
+42
View File
@@ -0,0 +1,42 @@
import type { Chain } from "../src/types";
export default {
"name": "KalyChain Testnet",
"chain": "KLC",
"icon": {
"url": "ipfs://QmUaXcPewLuQtY5a7xPTzJyVdjkH487VfV7gSR8UXrbxQ3",
"width": 512,
"height": 512,
"format": "png"
},
"rpc": [
"https://kalychain-testnet.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://testnetrpc.kalychain.io/rpc"
],
"features": [
{
"name": "EIP155"
},
{
"name": "EIP1559"
}
],
"faucets": [],
"nativeCurrency": {
"name": "KalyCoin",
"symbol": "KLC",
"decimals": 18
},
"infoURL": "https://kalychain.io",
"shortName": "kalytestnet",
"chainId": 3889,
"networkId": 3889,
"explorers": [
{
"name": "KalyScan",
"url": "https://testnet.kalyscan.io",
"standard": "EIP3091"
}
],
"testnet": true,
"slug": "kalychain-testnet"
} as const satisfies Chain;
+7 -9
View File
@@ -1,14 +1,12 @@
import type { Chain } from "../src/types";
export default {
"name": "Unicorn Ultra Testnet",
"name": "U2U Solaris Mainnet",
"chain": "u2u",
"rpc": [
"https://unicorn-ultra-testnet.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://rpc-testnet.uniultra.xyz"
],
"faucets": [
"https://faucet.uniultra.xyz"
"https://u2u-solaris.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://rpc-mainnet.uniultra.xyz"
],
"faucets": [],
"nativeCurrency": {
"name": "Unicorn Ultra",
"symbol": "U2U",
@@ -33,10 +31,10 @@ export default {
"format": "png"
},
"name": "U2U Explorer",
"url": "https://testnet.uniultra.xyz",
"url": "https://u2uscan.xyz",
"standard": "EIP3091"
}
],
"testnet": true,
"slug": "unicorn-ultra-testnet"
"testnet": false,
"slug": "u2u-solaris"
} as const satisfies Chain;
+3 -1
View File
@@ -7,7 +7,9 @@ export default {
"https://optimism-goerli.infura.io/v3/${INFURA_API_KEY}",
"https://opt-goerli.g.alchemy.com/v2/${ALCHEMY_API_KEY}",
"https://goerli.optimism.io",
"https://optimism-goerli.publicnode.com"
"https://optimism-goerli.publicnode.com",
"https://optimism-goerli.gateway.tenderly.co",
"wss://optimism-goerli.gateway.tenderly.co"
],
"faucets": [
"https://coinbase.com/faucets/optimism-goerli-faucet"
+39
View File
@@ -0,0 +1,39 @@
import type { Chain } from "../src/types";
export default {
"name": "Beam",
"chain": "BEAM",
"rpc": [
"https://beam.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://subnets.avax.network/beam/mainnet/rpc"
],
"features": [
{
"name": "EIP1559"
}
],
"faucets": [],
"nativeCurrency": {
"name": "Merit Circle",
"symbol": "MC",
"decimals": 18
},
"infoURL": "https://www.onbeam.com",
"shortName": "beam",
"icon": {
"url": "ipfs://QmQJ21NWyGGDraicVEzS1Uqq1yXahM9NCuNZgnfYvtspdt",
"width": 512,
"height": 512,
"format": "png"
},
"chainId": 4337,
"networkId": 4337,
"explorers": [
{
"name": "Beam Explorer",
"url": "https://subnets.avax.network/beam",
"standard": "EIP3091"
}
],
"testnet": false,
"slug": "beam"
} as const satisfies Chain;
+24 -22
View File
@@ -1,36 +1,38 @@
import type { Chain } from "../src/types";
export default {
"name": "Acria IntelliChain",
"chain": "AIC",
"name": "Xpla Testnet",
"chain": "XPLA",
"rpc": [
"https://acria-intellichain.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://aic.acria.ai"
"https://xpla-testnet.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://cube-evm-rpc.xpla.dev"
],
"faucets": [],
"nativeCurrency": {
"name": "ACRIA",
"symbol": "ACRIA",
"name": "XPLA",
"symbol": "XPLA",
"decimals": 18
},
"features": [
{
"name": "EIP155"
},
{
"name": "EIP1559"
}
"faucets": [
"https://faucet.xpla.io/"
],
"infoURL": "https://acria.ai",
"shortName": "aic",
"infoURL": "https://xpla.io/",
"shortName": "xpla-test",
"chainId": 47,
"networkId": 47,
"icon": {
"url": "ipfs://QmbvEAKZfgJckEziU3mpCwz6jqMeWRcLgd8TNsWA7g8sD9/xpla.png",
"width": 512,
"height": 512,
"format": "png"
},
"explorers": [
{
"name": "Acria IntelliChain-Explorer",
"url": "https://explorer.acria.ai",
"standard": "EIP3091"
"name": "XPLA Explorer",
"url": "https://explorer.xpla.io/testnet",
"standard": "none"
}
],
"testnet": false,
"slug": "acria-intellichain"
"testnet": true,
"redFlags": [
"reusedChainId"
],
"slug": "xpla-testnet"
} as const satisfies Chain;
+3 -1
View File
@@ -9,7 +9,9 @@ export default {
"wss://goerli.infura.io/v3/${INFURA_API_KEY}",
"https://eth-goerli.g.alchemy.com/v2/${ALCHEMY_API_KEY}",
"https://rpc.goerli.mudit.blog/",
"https://ethereum-goerli.publicnode.com"
"https://ethereum-goerli.publicnode.com",
"https://goerli.gateway.tenderly.co",
"wss://goerli.gateway.tenderly.co"
],
"faucets": [
"https://faucet.paradigm.xyz/",
+2 -2
View File
@@ -8,8 +8,8 @@ export default {
],
"faucets": [],
"nativeCurrency": {
"name": "HMND",
"symbol": "HMND",
"name": "eHMND",
"symbol": "eHMND",
"decimals": 18
},
"infoURL": "https://humanode.io",
+3 -3
View File
@@ -1,6 +1,6 @@
import type { Chain } from "../src/types";
export default {
"name": "opBNB",
"name": "Opbnb Testnet",
"chain": "opBNB",
"shortName": "opBNB",
"chainId": 5611,
@@ -11,7 +11,7 @@ export default {
"decimals": 18
},
"rpc": [
"https://opbnb.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://opbnb-testnet.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://opbnb-testnet-rpc.bnbchain.org"
],
"explorers": [
@@ -31,5 +31,5 @@ export default {
"width": 512,
"format": "svg"
},
"slug": "opbnb"
"slug": "opbnb-testnet"
} as const satisfies Chain;
+2 -2
View File
@@ -5,8 +5,8 @@ export default {
"rpc": [
"https://boba-bnb.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://bnb.boba.network",
"http://boba-bnb.gateway.tenderly.co/",
"http://gateway.tenderly.co/public/boba-bnb",
"https://boba-bnb.gateway.tenderly.co/",
"https://gateway.tenderly.co/public/boba-bnb",
"https://replica.bnb.boba.network",
"wss://boba-bnb.gateway.tenderly.co/",
"wss://gateway.tenderly.co/public/boba-bnb"
+23
View File
@@ -0,0 +1,23 @@
import type { Chain } from "../src/types";
export default {
"name": "Tanssi EVM ContainerChain",
"chain": "EVMCC",
"rpc": [
"https://tanssi-evm-containerchain.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://fraa-dancebox-3001-rpc.a.dancebox.tanssi.network",
"wss://fraa-dancebox-3001-rpc.a.dancebox.tanssi.network"
],
"faucets": [],
"nativeCurrency": {
"name": "Unit",
"symbol": "Unit",
"decimals": 18
},
"infoURL": "https://tanssi.network",
"shortName": "TanssiCC",
"chainId": 5678,
"networkId": 5678,
"explorers": [],
"testnet": false,
"slug": "tanssi-evm-containerchain"
} as const satisfies Chain;
+36
View File
@@ -0,0 +1,36 @@
import type { Chain } from "../src/types";
export default {
"name": "VELO Labs Mainnet",
"chain": "NOVA chain",
"rpc": [
"https://velo-labs.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://nova.velo.org"
],
"faucets": [
"https://nova-faucet.velo.org"
],
"nativeCurrency": {
"name": "Nova",
"symbol": "NOVA",
"decimals": 18
},
"infoURL": "https://velo.org",
"shortName": "VELO",
"chainId": 56789,
"networkId": 56789,
"icon": {
"url": "ipfs://QmYqvnW2jwPEKUv8BdaV4sbL8Audcwosat6SPn4GqYtKxc",
"width": 225,
"height": 225,
"format": "png"
},
"explorers": [
{
"name": "novascan",
"url": "https://novascan.velo.org",
"standard": "EIP3091"
}
],
"testnet": false,
"slug": "velo-labs"
} as const satisfies Chain;
+5 -1
View File
@@ -4,7 +4,11 @@ export default {
"chain": "DSC",
"rpc": [
"https://decimal-smart-chain.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://node.decimalchain.com/web3/"
"https://node.decimalchain.com/web3/",
"https://node1-mainnet.decimalchain.com/web3/",
"https://node2-mainnet.decimalchain.com/web3/",
"https://node3-mainnet.decimalchain.com/web3/",
"https://node4-mainnet.decimalchain.com/web3/"
],
"faucets": [],
"nativeCurrency": {
+33
View File
@@ -0,0 +1,33 @@
import type { Chain } from "../src/types";
export default {
"name": "Amplify Subnet",
"chain": "AMPLIFY",
"rpc": [
"https://amplify-subnet.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://subnets.avax.network/amplify/testnet/rpc"
],
"features": [
{
"name": "EIP1559"
}
],
"faucets": [],
"nativeCurrency": {
"name": "AMP",
"symbol": "AMP",
"decimals": 18
},
"infoURL": "https://www.avax.network",
"shortName": "amplify",
"chainId": 78430,
"networkId": 78430,
"explorers": [
{
"name": "AMPLIFY Explorer",
"url": "https://subnets-test.avax.network/amplify",
"standard": "EIP3091"
}
],
"testnet": true,
"slug": "amplify-subnet"
} as const satisfies Chain;
+33
View File
@@ -0,0 +1,33 @@
import type { Chain } from "../src/types";
export default {
"name": "Bulletin Subnet",
"chain": "BULLETIN",
"rpc": [
"https://bulletin-subnet.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://subnets.avax.network/bulletin/testnet/rpc"
],
"features": [
{
"name": "EIP1559"
}
],
"faucets": [],
"nativeCurrency": {
"name": "BLT",
"symbol": "BLT",
"decimals": 18
},
"infoURL": "https://www.avax.network",
"shortName": "bulletin",
"chainId": 78431,
"networkId": 78431,
"explorers": [
{
"name": "BULLETIN Explorer",
"url": "https://subnets-test.avax.network/bulletin",
"standard": "EIP3091"
}
],
"testnet": true,
"slug": "bulletin-subnet"
} as const satisfies Chain;
+33
View File
@@ -0,0 +1,33 @@
import type { Chain } from "../src/types";
export default {
"name": "Conduit Subnet",
"chain": "CONDUIT",
"rpc": [
"https://conduit-subnet.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://subnets.avax.network/conduit/testnet/rpc"
],
"features": [
{
"name": "EIP1559"
}
],
"faucets": [],
"nativeCurrency": {
"name": "CON",
"symbol": "CON",
"decimals": 18
},
"infoURL": "https://www.avax.network",
"shortName": "conduit",
"chainId": 78432,
"networkId": 78432,
"explorers": [
{
"name": "CONDUIT Explorer",
"url": "https://subnets-test.avax.network/conduit",
"standard": "EIP3091"
}
],
"testnet": true,
"slug": "conduit-subnet"
} as const satisfies Chain;
+3 -1
View File
@@ -16,7 +16,9 @@ export default {
"https://matic-mumbai.chainstacklabs.com",
"https://rpc-mumbai.maticvigil.com",
"https://matic-testnet-archive-rpc.bwarelabs.com",
"https://polygon-mumbai-bor.publicnode.com"
"https://polygon-mumbai-bor.publicnode.com",
"https://polygon-mumbai.gateway.tenderly.co",
"wss://polygon-mumbai.gateway.tenderly.co"
],
"faucets": [
"https://faucet.polygon.technology/"
+8 -10
View File
@@ -1,19 +1,17 @@
import type { Chain } from "../src/types";
export default {
"name": "BeOne Chain Testnet",
"chain": "BOC",
"name": "Testnet BeOne Chain",
"chain": "tBOC",
"rpc": [
"https://beone-chain-testnet.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://pre-boc1.beonechain.com",
"https://pre-boc2.beonechain.com",
"https://pre-boc3.beonechain.com"
"https://testnet-beone-chain.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://pre-boc1.beonechain.com"
],
"faucets": [
"https://testnet.beonescan.com/faucet"
],
"nativeCurrency": {
"name": "BeOne Chain Testnet",
"symbol": "BOC",
"name": "Testnet BeOne Chain",
"symbol": "tBOC",
"decimals": 18
},
"infoURL": "https://testnet.beonescan.com",
@@ -28,7 +26,7 @@ export default {
},
"explorers": [
{
"name": "BeOne Chain Testnet",
"name": "Testnet BeOne Chain",
"url": "https://testnet.beonescan.com",
"icon": {
"url": "ipfs://QmbVLQnaMDu86bPyKgCvTGhFBeYwjr15hQnrCcsp1EkAGL",
@@ -40,5 +38,5 @@ export default {
}
],
"testnet": true,
"slug": "beone-chain-testnet"
"slug": "testnet-beone-chain"
} as const satisfies Chain;
+5 -1
View File
@@ -4,7 +4,11 @@ export default {
"chain": "ETH",
"rpc": [
"https://base.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://mainnet.base.org/"
"https://mainnet.base.org/",
"https://developer-access-mainnet.base.org/",
"https://base.gateway.tenderly.co",
"wss://base.gateway.tenderly.co",
"https://base.publicnode.com"
],
"faucets": [],
"nativeCurrency": {
+3
View File
@@ -4,6 +4,9 @@ export default {
"chain": "ETH",
"rpc": [
"https://base-goerli.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://base-goerli.publicnode.com",
"wss://base-goerli.gateway.tenderly.co",
"https://base-goerli.gateway.tenderly.co",
"https://goerli.base.org"
],
"faucets": [
+40
View File
@@ -0,0 +1,40 @@
import type { Chain } from "../src/types";
export default {
"name": "Aerie Network",
"chain": "Aerie",
"rpc": [
"https://aerie-network.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://mainnet.aerielab.io"
],
"faucets": [],
"nativeCurrency": {
"name": "Aerie",
"symbol": "AER",
"decimals": 18
},
"infoURL": "https://aerielab.io/",
"shortName": "Aerie",
"chainId": 84886,
"networkId": 84886,
"icon": {
"url": "ipfs://bafkreig54jss26xllpjbclmfgwvot72m4ku7qxignhlqei6mijvwi2m4pu",
"width": 1062,
"height": 1069,
"format": "png"
},
"explorers": [
{
"name": "Aerie Explorer",
"url": "https://explorer.aerielab.io",
"icon": {
"url": "ipfs://bafkreig54jss26xllpjbclmfgwvot72m4ku7qxignhlqei6mijvwi2m4pu",
"width": 1062,
"height": 1069,
"format": "png"
},
"standard": "EIP3091"
}
],
"testnet": false,
"slug": "aerie-network"
} as const satisfies Chain;
+36
View File
@@ -0,0 +1,36 @@
import type { Chain } from "../src/types";
export default {
"name": "Spicy Chain",
"chain": "Spicy",
"rpc": [
"https://spicy-chain.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://spicy-rpc.chiliz.com/"
],
"faucets": [
"https://spicy-faucet.chiliz.com/"
],
"nativeCurrency": {
"name": "Chiliz",
"symbol": "CHZ",
"decimals": 18
},
"infoURL": "https://chiliz.com/",
"shortName": "Spicy",
"chainId": 88882,
"networkId": 88882,
"explorers": [
{
"name": "Spicy Explorer",
"url": "http://spicy-explorer.chiliz.com/",
"standard": "none"
}
],
"icon": {
"url": "ipfs://QmTGYofJ8VLkeNY4J69AvXi8e126kmbHmf34wLFoJ1FKAK",
"width": 400,
"height": 400,
"format": "png"
},
"testnet": true,
"slug": "spicy-chain"
} as const satisfies Chain;
+21
View File
@@ -0,0 +1,21 @@
import type { Chain } from "../src/types";
export default {
"name": "Worlds Appchain",
"chain": "WRLDS",
"shortName": "WRLDS",
"chainId": 91003,
"testnet": true,
"rpc": [
"https://worlds-appchain.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://api.evm.worlds.dev.eclipsenetwork.xyz/"
],
"nativeCurrency": {
"name": "WRLDS",
"symbol": "WRLDS",
"decimals": 18
},
"faucets": [
"https://faucet.evm.worlds.dev.eclipsenetwork.xyz/request_neon"
],
"slug": "worlds-appchain"
} as const satisfies Chain;
+3 -1
View File
@@ -7,7 +7,9 @@ export default {
"https://testnet.bnb.boba.network",
"wss://wss.testnet.bnb.boba.network",
"https://replica.testnet.bnb.boba.network",
"wss://replica-wss.testnet.bnb.boba.network"
"wss://replica-wss.testnet.bnb.boba.network",
"https://boba-bnb-testnet.gateway.tenderly.co",
"wss://boba-bnb-testnet.gateway.tenderly.co"
],
"faucets": [],
"nativeCurrency": {
+2 -1
View File
@@ -10,7 +10,8 @@ export default {
},
"rpc": [
"https://mind-smart-chain-testnet.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
"https://testnet-msc.mindchain.info/"
"https://testnet-msc.mindchain.info/",
"wss://testnet-msc.mindchain.info/ws"
],
"faucets": [
"https://faucet.mindchain.info/"
@@ -8,6 +8,12 @@ export default {
shortName: "POPTestnet",
chainId: 331769,
testnet: true,
icon: {
format: "png",
url: "ipfs://QmP8rYvcc7aJB3c2YZxjxaySvHapHnoK8MnxuSuDT4PtF2",
height: 400,
width: 400,
},
rpc: ["https://testnet01.proofofpepe.tech"],
nativeCurrency: {
name: "POP",
@@ -0,0 +1,30 @@
// @ts-check
/** @typedef { import("../../src/types").Chain } Chain */
/** @type {Omit<Chain, "slug">} */
export default {
name: "POP Mainnet",
chain: "POP",
shortName: "POP",
chainId: 331771,
testnet: false,
icon: {
format: "png",
url: "ipfs://QmP8rYvcc7aJB3c2YZxjxaySvHapHnoK8MnxuSuDT4PtF2",
height: 400,
width: 400,
},
rpc: [
"https://rpc00.proofofpepe.tech",
"https://rpc01.proofofpepe.tech",
"https://rpc02.proofofpepe.tech",
],
nativeCurrency: {
name: "Pepe",
symbol: "PEPE",
decimals: 18,
},
explorers: [
{ name: "Pepescan", url: "https://pepescan.app", standard: "none" },
],
};
+32
View File
@@ -0,0 +1,32 @@
// @ts-check
/** @typedef { import("../../src/types").Chain } Chain */
/** @type {Omit<Chain, "slug">} */
export default {
name: "Xpla Mainnet",
chain: "XPLA",
rpc: ["https://dimension-evm-rpc.xpla.dev"],
nativeCurrency: {
name: "XPLA",
symbol: "XPLA",
decimals: 18,
},
infoURL: "https://xpla.io/",
shortName: "xpla",
chainId: 37,
icon: {
url: "ipfs://QmbvEAKZfgJckEziU3mpCwz6jqMeWRcLgd8TNsWA7g8sD9/xpla.png",
width: 512,
height: 512,
format: "png",
},
explorers: [
{
name: "XPLA Explorer",
url: "https://explorer.xpla.io",
standard: "none",
},
],
testnet: false,
redFlags: ["reusedChainId"],
};
+33
View File
@@ -0,0 +1,33 @@
// @ts-check
/** @typedef { import("../../src/types").Chain } Chain */
/** @type {Omit<Chain, "slug">} */
export default {
name: "Xpla Testnet",
chain: "XPLA",
rpc: ["https://cube-evm-rpc.xpla.dev"],
nativeCurrency: {
name: "XPLA",
symbol: "XPLA",
decimals: 18,
},
faucets: ["https://faucet.xpla.io/"],
infoURL: "https://xpla.io/",
shortName: "xpla-test",
chainId: 47,
icon: {
url: "ipfs://QmbvEAKZfgJckEziU3mpCwz6jqMeWRcLgd8TNsWA7g8sD9/xpla.png",
width: 512,
height: 512,
format: "png",
},
explorers: [
{
name: "XPLA Explorer",
url: "https://explorer.xpla.io/testnet",
standard: "none",
},
],
testnet: true,
redFlags: ["reusedChainId"],
};
+33
View File
@@ -0,0 +1,33 @@
// @ts-check
/** @typedef { import("../../src/types").Chain } Chain */
/** @type {Omit<Chain, "slug">} */
export default {
name: "Spicy Chain",
chain: "Spicy",
rpc: ["https://spicy-rpc.chiliz.com/"],
faucets: ["https://spicy-faucet.chiliz.com/"],
nativeCurrency: {
name: "Chiliz",
symbol: "CHZ",
decimals: 18,
},
infoURL: "https://chiliz.com/",
shortName: "Spicy",
chainId: 88882,
networkId: 88882,
explorers: [
{
name: "Spicy Explorer",
url: "http://spicy-explorer.chiliz.com/",
standard: "none",
},
],
icon: {
url: "ipfs://QmTGYofJ8VLkeNY4J69AvXi8e126kmbHmf34wLFoJ1FKAK",
width: 400,
height: 400,
format: "png",
},
testnet: true,
};
+18
View File
@@ -0,0 +1,18 @@
// @ts-check
/** @typedef { import("../../src/types").Chain } Chain */
/** @type {Omit<Chain, "slug">} */
export default {
name: "Worlds Appchain",
chain: "WRLDS",
shortName: "WRLDS",
chainId: 91003,
testnet: true,
rpc: ["https://api.evm.worlds.dev.eclipsenetwork.xyz/"],
nativeCurrency: {
name: "WRLDS",
symbol: "WRLDS",
decimals: 18,
},
faucets: ["https://faucet.evm.worlds.dev.eclipsenetwork.xyz/request_neon"],
};
+8
View File
@@ -0,0 +1,8 @@
// @ts-check
/** @typedef { import("../../src/types").Chain } Chain */
/** @type {Partial<Chain>} */
export default {
name: "Opbnb Testnet",
slug: "opbnb-testnet",
};
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@thirdweb-dev/chains",
"version": "0.1.44",
"version": "0.1.49",
"main": "dist/thirdweb-dev-chains.cjs.js",
"module": "dist/thirdweb-dev-chains.esm.js",
"browser": {
@@ -344,6 +344,7 @@ ${exports.join("\n")}
export * from "./types";
export * from "./utils";
export const defaultChains = [c1, c5, c8453, c84531, c137, c80001, c42161, c421613, c10, c420, c56, c97, c250, c4002, c43114, c43113, c1337];
// @ts-expect-error - TODO: fix this later
export const allChains: Chain[] = [${exportNames.join(", ")}];
type ChainsById = {
File diff suppressed because one or more lines are too long
-1
View File
@@ -75,7 +75,6 @@ export function getChainRPCs(
*
* @param chain - The chain config to assemble RPC URLs from
* @param clientId - The client id to use for the RPC URL
* @param secretKey - The secret key to use for the RPC URL
* @returns The first valid RPC URL for the chain
*/
export function getValidChainRPCs(
+19 -19
View File
@@ -18,6 +18,7 @@ const CHAIN_RPC_TEST_CASES: [ChainRPCOptions, string[]][] = [
"https://api.mycryptoapi.com/eth",
"https://cloudflare-eth.com",
"https://ethereum.publicnode.com",
"https://mainnet.gateway.tenderly.co",
],
],
[
@@ -27,6 +28,7 @@ const CHAIN_RPC_TEST_CASES: [ChainRPCOptions, string[]][] = [
"https://api.mycryptoapi.com/eth",
"https://cloudflare-eth.com",
"https://ethereum.publicnode.com",
"https://mainnet.gateway.tenderly.co",
],
],
[
@@ -36,12 +38,16 @@ const CHAIN_RPC_TEST_CASES: [ChainRPCOptions, string[]][] = [
"https://api.mycryptoapi.com/eth",
"https://cloudflare-eth.com",
"https://ethereum.publicnode.com",
"https://mainnet.gateway.tenderly.co",
],
],
// infura is supported for both http and ws
[
{ mode: "ws", infuraApiKey: "SAMPLE_KEY" },
["wss://mainnet.infura.io/ws/v3/SAMPLE_KEY"],
[
"wss://mainnet.infura.io/ws/v3/SAMPLE_KEY",
"wss://mainnet.gateway.tenderly.co",
],
],
];
@@ -53,12 +59,6 @@ describe("chains/utils", () => {
},
);
test("Should throw error if no processedRPCs (getChainRPCs(%p))", () => {
expect(() => {
getChainRPCs(Ethereum, { mode: "ws" });
}).toThrowError('No RPC available for chainId "1" with mode ws');
});
test.each([
[
undefined,
@@ -68,6 +68,7 @@ describe("chains/utils", () => {
"https://api.mycryptoapi.com/eth",
"https://cloudflare-eth.com",
"https://ethereum.publicnode.com",
"https://mainnet.gateway.tenderly.co",
],
],
[
@@ -78,6 +79,7 @@ describe("chains/utils", () => {
"https://api.mycryptoapi.com/eth",
"https://cloudflare-eth.com",
"https://ethereum.publicnode.com",
"https://mainnet.gateway.tenderly.co",
],
],
[
@@ -88,6 +90,7 @@ describe("chains/utils", () => {
"https://api.mycryptoapi.com/eth",
"https://cloudflare-eth.com",
"https://ethereum.publicnode.com",
"https://mainnet.gateway.tenderly.co",
],
],
[
@@ -98,24 +101,13 @@ describe("chains/utils", () => {
"https://api.mycryptoapi.com/eth",
"https://cloudflare-eth.com",
"https://ethereum.publicnode.com",
"https://mainnet.gateway.tenderly.co",
],
],
])("getValidChainRPCs(Ethereum, %s, %s) = %p", (clientId, mode, expected) => {
expect(getValidChainRPCs(Ethereum, clientId, mode)).toEqual(expected);
});
test.each([
[undefined, "ws"],
["SAMPLE_CLIENT_KEY", "ws"],
])(
"Should throw error if no processedRPCs (getValidChainRPCs(Ethereum, %s, %s))",
(clientId, mode) => {
expect(() => {
getValidChainRPCs(Ethereum, clientId, mode);
}).toThrowError('No RPC available for chainId "1" with mode ws');
},
);
test.each(CHAIN_RPC_TEST_CASES)(
"getChainRPC(%p) = %p",
(options, expected) => {
@@ -174,6 +166,7 @@ describe("chains/utils", () => {
"https://api.mycryptoapi.com/eth",
"https://cloudflare-eth.com",
"https://ethereum.publicnode.com",
"https://mainnet.gateway.tenderly.co",
],
},
],
@@ -187,6 +180,7 @@ describe("chains/utils", () => {
"https://api.mycryptoapi.com/eth",
"https://cloudflare-eth.com",
"https://ethereum.publicnode.com",
"https://mainnet.gateway.tenderly.co",
],
},
],
@@ -210,6 +204,7 @@ describe("chains/utils with APP_BUNDLE_ID", () => {
"https://api.mycryptoapi.com/eth",
"https://cloudflare-eth.com",
"https://ethereum.publicnode.com",
"https://mainnet.gateway.tenderly.co",
],
],
[
@@ -220,6 +215,7 @@ describe("chains/utils with APP_BUNDLE_ID", () => {
"https://api.mycryptoapi.com/eth",
"https://cloudflare-eth.com",
"https://ethereum.publicnode.com",
"https://mainnet.gateway.tenderly.co",
],
],
[
@@ -230,6 +226,7 @@ describe("chains/utils with APP_BUNDLE_ID", () => {
"https://api.mycryptoapi.com/eth",
"https://cloudflare-eth.com",
"https://ethereum.publicnode.com",
"https://mainnet.gateway.tenderly.co",
],
],
[
@@ -240,6 +237,7 @@ describe("chains/utils with APP_BUNDLE_ID", () => {
"https://api.mycryptoapi.com/eth",
"https://cloudflare-eth.com",
"https://ethereum.publicnode.com",
"https://mainnet.gateway.tenderly.co",
],
],
])("getValidChainRPCs(Ethereum, %s, %s) = %p", (clientId, mode, expected) => {
@@ -257,6 +255,7 @@ describe("chains/utils with APP_BUNDLE_ID", () => {
"https://api.mycryptoapi.com/eth",
"https://cloudflare-eth.com",
"https://ethereum.publicnode.com",
"https://mainnet.gateway.tenderly.co",
],
},
],
@@ -270,6 +269,7 @@ describe("chains/utils with APP_BUNDLE_ID", () => {
"https://api.mycryptoapi.com/eth",
"https://cloudflare-eth.com",
"https://ethereum.publicnode.com",
"https://mainnet.gateway.tenderly.co",
],
},
],
+58
View File
@@ -1,5 +1,63 @@
# thirdweb
## 0.12.0
### Minor Changes
- [#1422](https://github.com/thirdweb-dev/js/pull/1422) [`0f027069`](https://github.com/thirdweb-dev/js/commit/0f027069064bebe647f9235fa86ef7f165ffc7b3) Thanks [@Marfuen](https://github.com/Marfuen)! - CLI will now use an OAuth like login flow to authenticate the device with the wallet on the dashboard.
Any actions performed by the CLI will be linked to your account / wallet on the dashboard, including but not limited to tracking your usage, and billing as needed.
### Patch Changes
- Updated dependencies [[`eb463735`](https://github.com/thirdweb-dev/js/commit/eb463735e2f784cd1d212a982835af95cf60766b), [`adec589e`](https://github.com/thirdweb-dev/js/commit/adec589ead8ceff1b57169e05a3e6733b4652cc7), [`b30566c6`](https://github.com/thirdweb-dev/js/commit/b30566c68436ad94ddc938a380eccc13a8a7147d), [`0f027069`](https://github.com/thirdweb-dev/js/commit/0f027069064bebe647f9235fa86ef7f165ffc7b3), [`f5aed34d`](https://github.com/thirdweb-dev/js/commit/f5aed34d3c71065c3f45df2c1eb84ba9c36162d5)]:
- @thirdweb-dev/wallets@1.1.21
- @thirdweb-dev/sdk@3.10.57
- @thirdweb-dev/chains@0.1.49
- @thirdweb-dev/storage@1.2.9
- @thirdweb-dev/auth@3.2.38
## 0.11.20
### Patch Changes
- [#1538](https://github.com/thirdweb-dev/js/pull/1538) [`8b82f3c5`](https://github.com/thirdweb-dev/js/commit/8b82f3c59cad6bd1167c13cb0b8a1cdc36475ab8) Thanks [@iketw](https://github.com/iketw)! - Adds support for creating PWA Vite apps
You can now run:
```bash
npx thirdweb@nightly create --template pwa-vite-typescript-starter
```
- Updated dependencies [[`f59b729f`](https://github.com/thirdweb-dev/js/commit/f59b729f8b09aa86655b8e8a70fba644fc52009b), [`911e14fc`](https://github.com/thirdweb-dev/js/commit/911e14fcac743b07fa1a66440c72d662c08e971c), [`cd6b07b5`](https://github.com/thirdweb-dev/js/commit/cd6b07b591606d2671794cebebf8edcb59076c32)]:
- @thirdweb-dev/[email protected]
- @thirdweb-dev/[email protected]
## 0.11.19
### Patch Changes
- Updated dependencies [[`586e91db`](https://github.com/thirdweb-dev/js/commit/586e91dbe610588cc7b24fade59172fed6481074), [`34a3bb8a`](https://github.com/thirdweb-dev/js/commit/34a3bb8ae3c1d7a506e5568a9e79ab7e469557a8), [`91f0245b`](https://github.com/thirdweb-dev/js/commit/91f0245be78ae523e1faea26b1032bfb283467d9), [`f65578d6`](https://github.com/thirdweb-dev/js/commit/f65578d637decc8b87cada5b5b0c8c504064d9d5), [`5a373a75`](https://github.com/thirdweb-dev/js/commit/5a373a75090da7e1e05724ed1a3a3a6aa9f7fd21), [`ae74b8ef`](https://github.com/thirdweb-dev/js/commit/ae74b8ef6200dba8affa8b52e7d834c5552350d0), [`bc003c2f`](https://github.com/thirdweb-dev/js/commit/bc003c2fef33fcf7ce5981d8634911ac4bcaa927), [`447d9846`](https://github.com/thirdweb-dev/js/commit/447d984653f77af6860ae907072e768b584b263d), [`f65578d6`](https://github.com/thirdweb-dev/js/commit/f65578d637decc8b87cada5b5b0c8c504064d9d5)]:
- @thirdweb-dev/[email protected]
- @thirdweb-dev/[email protected]
- @thirdweb-dev/[email protected]
## 0.11.18
### Patch Changes
- Updated dependencies [[`184c325a`](https://github.com/thirdweb-dev/js/commit/184c325ab2ef028022a050c4274f2ab12b1a3a7f), [`046c9ad6`](https://github.com/thirdweb-dev/js/commit/046c9ad604587ff79bf028c4fe7b1f9c94f4ea54), [`c12f0874`](https://github.com/thirdweb-dev/js/commit/c12f0874b4dac43c263c7edb20d0343c16381c34)]:
- @thirdweb-dev/[email protected]
- @thirdweb-dev/[email protected]
- @thirdweb-dev/[email protected]
## 0.11.17
### Patch Changes
- Updated dependencies [[`f97ddf4c`](https://github.com/thirdweb-dev/js/commit/f97ddf4c7f14854f3b204ad9741b52ddb8dac736)]:
- @thirdweb-dev/[email protected]
- @thirdweb-dev/[email protected]
## 0.11.16
### Patch Changes
+4 -2
View File
@@ -1,7 +1,7 @@
{
"name": "thirdweb",
"main": "dist/cli/index.js",
"version": "0.11.16",
"version": "0.12.0",
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/cli",
"author": "thirdweb eng <[email protected]>",
"license": "Apache-2.0",
@@ -37,9 +37,11 @@
},
"dependencies": {
"@iarna/toml": "^2.2.5",
"@thirdweb-dev/auth": "workspace:*",
"@thirdweb-dev/chains": "workspace:*",
"@thirdweb-dev/sdk": "workspace:*",
"@thirdweb-dev/storage": "workspace:*",
"@thirdweb-dev/wallets": "workspace:*",
"async-retry": "^1.3.3",
"commander": "^9.1.0",
"detect-package-manager": "^2.0.1",
@@ -53,10 +55,10 @@
"prompts": "^2.4.2",
"rimraf": "^3.0.2",
"solc": "0.8.17",
"sync-disk-cache": "^2.1.0",
"tar": "^6.1.15",
"update-notifier": "^6.0.2",
"validate-npm-package-name": "^4.0.0",
"xdg-app-paths": "^8.3.0",
"yaml": "^2.3.1"
},
"bin": {
+254 -65
View File
@@ -1,105 +1,294 @@
import { LocalWallet } from "@thirdweb-dev/wallets";
import assert from "assert";
import chalk from "chalk";
import prompts from "prompts";
import Cache, { CacheEntry } from "sync-disk-cache";
import { ApiResponse } from "../lib/types";
import os from "os";
import fs from "fs";
import http from "http";
import open from "open";
import ora from "ora";
import url from "url";
import { logger, spinner } from "../core/helpers/logger";
import { ThirdwebAuth } from "@thirdweb-dev/auth";
import { ICredsConfig } from "../lib/types";
import { generateStateParameter } from "../lib/utils";
import crypto from "node:crypto";
type LoginProps = {
browser: boolean;
configPaths: ConfigPaths;
};
const defaultLoginProps = {
browser: true,
configPaths: {
credsConfigPath: "",
cliWalletPath: "",
tokenPath: "",
},
};
type ConfigPaths = {
credsConfigPath: string;
cliWalletPath: string;
tokenPath: string;
}
export async function loginUser(
cache: Cache,
configPaths: ConfigPaths,
options?: { new: boolean },
showLogs?: boolean,
) {
const keyFound = getSession(cache);
if (keyFound && !options?.new) {
const { credsConfigPath, tokenPath } = configPaths;
const authToken = await getSession(tokenPath, credsConfigPath);
if (authToken && !options?.new) {
if (showLogs) {
console.log(chalk.green("You are already logged in"));
}
return keyFound;
globalThis["TW_AUTH_TOKEN"] = authToken;
return authToken;
} else {
const apiKey = await createSession(cache);
return apiKey;
const token = await authenticateUser({ browser: true, configPaths });
if (!token) {
throw new Error("Failed to login");
}
globalThis["TW_AUTH_TOKEN"] = token;
return token;
}
}
export async function logoutUser(cache: Cache) {
export async function logoutUser(credsConfigPath: string, tokenPath: string, cliWalletPath: string) {
try {
cache.remove("api-secret-key");
console.log(chalk.green("You have been logged out"));
ora("Logging out...").start();
const dirExists = fs.existsSync(credsConfigPath) && fs.existsSync(tokenPath);
if (!dirExists) {
ora().warn(chalk.yellow("You are already logged out, did you mean to login?"));
return;
}
fs.unlinkSync(credsConfigPath);
fs.unlinkSync(tokenPath);
// TODO: We can consider not removing this on logout later, once we want to implement teams. For now this wallet will be ephemeral.
fs.unlinkSync(cliWalletPath);
ora().succeed(chalk.green("You have been logged out"));
} catch (error) {
console.log(chalk.red("Something went wrong", error));
}
}
export function getSession(cache: Cache) {
export async function getSession(tokenPath: string, configCredsPath: string) {
if (!fs.existsSync(tokenPath) || !fs.existsSync(configCredsPath)) {
return null;
}
try {
const apiKey: CacheEntry = cache.get("api-secret-key");
return apiKey.value;
return fs.readFileSync(tokenPath, "utf8");
} catch (error) {
console.log(error);
console.error(error);
}
}
export async function createSession(cache: Cache) {
try {
const isWindows = os.type() === "Windows_NT";
if (isWindows) {
console.log(chalk.yellow("Windows detected: if you are using powershell, there are some known issues with it that we are actively working on, please use git bash or the command prompt. Thank you for your understanding."));
}
const response = await prompts({
type: "invisible",
name: "apiSecretKey",
message: `Please enter your API secret key, you can find or create it on ${chalk.blue(
"https://thirdweb.com/create-api-key",
)}`,
export const authenticateUser = async (
props: LoginProps = defaultLoginProps,
) => {
const { credsConfigPath, cliWalletPath, tokenPath } = props.configPaths;
const waitForDashboard = spinner("Waiting for a response from the dashboard").clear();
// Get or generate a localwallet.
const wallet = await getOrGenerateLocalWallet(credsConfigPath, cliWalletPath);
const walletAddress = await wallet.getAddress();
const domain = "thirdweb.com";
const auth = new ThirdwebAuth(wallet, domain);
// Generate the login payload to pass to the dashboard.
const loggedIn = await auth.login({
domain: domain,
address: walletAddress,
});
// In this case the state is the loggedIn object.
const ourState = generateStateParameter(32);
const payload = encodeURIComponent(JSON.stringify(loggedIn));
const urlToOpen = `https://thirdweb.com/cli/login?payload=${payload}&#${ourState}`;
let server: http.Server;
let loginTimeoutHandle: NodeJS.Timeout;
const timerPromise = new Promise<void>((resolve, reject) => {
loginTimeoutHandle = setTimeout(() => {
logger.error("Login session timed out, server didn't receive a response in 5 minutes. Please try again.");
server.close();
clearTimeout(loginTimeoutHandle);
reject(new Error("Login session timed out, server didn't receive a response in 5 minutes. Please try again."));
}, 300000);
});
const loginPromise = new Promise<string>((resolve, reject) => {
server = http.createServer(async (req, res) => {
function finish(error?: Error) {
clearTimeout(loginTimeoutHandle);
server.close((closeErr?: Error) => {
if (error || closeErr) {
reject(error || closeErr);
}
});
}
res.setHeader('Access-Control-Allow-Credentials', 'true');
res.setHeader('Access-Control-Allow-Origin', "https://thirdweb.com");
res.setHeader('Access-Control-Allow-Methods', 'POST');
if (req.method === 'OPTIONS') {
res.setHeader('Access-Control-Allow-Headers', 'content-type, baggage, sentry-trace');
res.writeHead(200);
res.end();
return;
}
assert(req.url, "This request doesn't have a URL");
const { pathname, query } = url.parse(req.url, true);
switch (pathname) {
case "/auth/callback": {
if (query.failed) {
res.writeHead(500, "Unable to authenticate with the dashboard!");
res.end("Unable to authenticate with the dashboard!", () => {
finish(new Error("Unable to authenticate with the dashboard!"));
})
reject(chalk.red("Something went wrong! Unable to authenticate with the dashboard."));
waitForDashboard.stop();
}
if (query.token) {
const token = Array.isArray(query.token) ? query.token[0] : query.token;
const theirState = Array.isArray(query.state)
? query.state[0]
: query.state;
// Check if the state sent back is the same as the one we sent.
if (theirState !== ourState) {
res.writeHead(400, { "Content-Type": "text/plain" }); // send a 400 response
res.end("Unauthorized request, state mismatch", () => {
finish(new Error("Unauthorized request, state mismatch"));
});
reject(
new Error(chalk.red("\nUnauthorized request, state mismatch")),
);
waitForDashboard.stop();
} else {
// Save the token to the config file.
// eslint-disable-next-line no-unused-expressions
fs.writeFileSync(tokenPath, token), {
encoding: "utf8",
mode: 0o600,
};
res.end(() => {
waitForDashboard.clear();
console.log(chalk.green(`Successfully linked your account to this device`));
finish();
});
logger.info(chalk.green(`\nSuccessfully logged in.`));
resolve(token); // resolve promise with secretKey
}
} else {
res.writeHead(400, { "Content-Type": "text/plain" });
res.end("No authToken received", () => {
finish(new Error("No authToken received"));
});
reject(new Error(chalk.red("\nNo authToken received")));
waitForDashboard.stop();
}
}
}
});
const keyPassed = response.apiSecretKey;
if (!keyPassed) {
console.log(chalk.red("You need to pass an API secret key"));
process.exit(1);
}
server.listen(8976);
});
if (props?.browser) {
console.log(chalk.yellow(`Automatically opening a link to authenticate with our dashboard...\n`))
waitForDashboard.start();
// Adding this timeout since it feels weird for the browser to open before the spinner.
setTimeout(async () => {
await open(urlToOpen);
}, 2000);
} else {
logger.info(`Visit this link to authenticate: ${urlToOpen}`);
}
if (keyPassed.length === 32) {
console.log(chalk.red(`This is not a valid secret key. To get your secret key
1. Create an API key at https://thirdweb.com/create-api-key
2. Store and copy your Secret Key. This will be shown only once.
3. Paste it in the CLI when prompted`));
process.exit(1);
}
return Promise.race([timerPromise, loginPromise]);
};
async function getOrCreatePassword(configCredsPath: string): Promise<string> {
const passwordFileExists = fs.existsSync(configCredsPath);
if (!passwordFileExists) {
// Generate a random password for the CLI to be able to import / export the wallet.
return crypto.randomUUID();
} else {
const file = fs.readFileSync(configCredsPath, "utf8");
try {
await validateKey(response.apiSecretKey);
} catch (error) {
console.log(error);
process.exit(1);
JSON.parse(file);
} catch (e) {
// If it fails to parse the password we should just delete the file and generate a new password, since this password is not shown to the user.
fs.unlinkSync(configCredsPath);
return getOrCreatePassword(configCredsPath);
}
cache.set("api-secret-key", response.apiSecretKey);
return response.apiSecretKey;
} catch (error) {
console.log(error);
const { password } = JSON.parse(file) as ICredsConfig;
return password;
}
}
export async function validateKey(apiSecretKey: string) {
const fetch = (await import("node-fetch")).default;
// TODO: CHANGE THIS TO PROD BEFORE MERGING!!!
const response = await fetch(
`https://api.thirdweb.com/v1/keys/use?scope=storage`,
{
async function getOrGenerateLocalWallet(configCredsPath: string, cliWalletPath: string) {
// Get or prompt for password.
const password = await getOrCreatePassword(configCredsPath);
const wallet = new LocalWallet();
const foundWallet = fs.existsSync(cliWalletPath);
if (foundWallet) {
const walletJson = fs.readFileSync(cliWalletPath, "utf8");
try {
// See if file is valid before proceeding.
JSON.parse(walletJson);
await wallet.import({
encryptedJson: walletJson,
password,
});
return wallet;
} catch (e) {
// Wallet file is not valid json, create a new one.
}
}
// Otherwise, generate a new wallet.
wallet.generate();
const walletExported = await wallet.export({
strategy: "encryptedJson",
password,
});
// write wallet
fs.writeFileSync(cliWalletPath, walletExported, {
encoding: "utf8",
mode: 0o600,
});
// write password
fs.writeFileSync(configCredsPath, JSON.stringify({
password: password,
}), "utf8");
return wallet;
}
export const validateKey = async (apiSecretKey: string) => {
const apiUrl = "https://api.thirdweb.com/v1/keys/use";
try {
const response = await fetch(`${apiUrl}?scope=storage`, {
method: "GET",
headers: {
"Content-Type": "application/json",
"x-secret-key": apiSecretKey,
},
},
);
}
})
const apiResponse = (await response.json()) as ApiResponse;
if (response.status !== 200) {
throw new Error("Unauthorized key");
}
if (!response.ok) {
const { error } = apiResponse;
throw new Error(chalk.red(error.message));
} else {
return apiSecretKey;
} catch (error) {
throw new Error(chalk.red("Unauthorized key"));
}
}
};
+104 -39
View File
@@ -3,11 +3,11 @@ import { ThirdwebStorage } from "@thirdweb-dev/storage";
import chalk from "chalk";
import { exec, spawn } from "child_process";
import { Command } from "commander";
import fs from "fs";
import open from "open";
import os from "os";
import path from "path";
import prompts from "prompts";
import Cache, { CacheEntry } from "sync-disk-cache";
import xdgAppPaths from "xdg-app-paths";
import { loginUser, logoutUser, validateKey } from "../auth";
import { detectExtensions } from "../common/feature-detector";
import { processProject } from "../common/processor";
@@ -24,11 +24,17 @@ import { upload } from "../storage/command";
const main = async () => {
// eslint-disable-next-line turbo/no-undeclared-env-vars
const skipIntro = process.env.THIRDWEB_CLI_SKIP_INTRO === "true";
const configDir = xdgAppPaths(".thirdweb").config();
const cacheDir = xdgAppPaths(".thirdweb").cache();
const lastVersionCheckCachePath = path.join(
cacheDir,
"last-version-check.txt",
);
const credsConfigPath = path.join(configDir, "creds.json");
const cliWalletPath = path.join(configDir, "wallet.json");
const tokenPath = path.join(configDir, "auth-token.txt");
const program = new Command();
const cache = new Cache("thirdweb-cli", {
location: path.join(os.homedir(), ".thirdweb", "creds"),
});
// yes this has to look like this, eliminates whitespace
if (!skipIntro) {
@@ -50,16 +56,32 @@ const main = async () => {
.version(cliVersion, "-v, --version")
.option("--skip-update-check", "Skip check for auto updates")
.hook("preAction", async () => {
const regenerateConfig = !fs.existsSync(configDir);
const regenerateCache = !fs.existsSync(cacheDir);
// Create config directory if it doesn't exist
if (regenerateConfig) {
fs.mkdirSync(configDir, { recursive: true });
}
// Create cache directory if it doesn't exist
if (regenerateCache) {
fs.mkdirSync(cacheDir, { recursive: true });
}
if (skipIntro || program.opts().skipUpdateCheck) {
return;
}
let shouldCheckVersion = true;
try {
const lastCheckCache: CacheEntry = cache.get("last-version-check");
const lastVersionCheckCache = fs.readFileSync(
lastVersionCheckCachePath,
"utf-8",
);
if (lastCheckCache.isCached) {
const lastVersionCheck = new Date(lastCheckCache.value);
if (lastVersionCheckCache) {
const lastVersionCheck = new Date(lastVersionCheckCache);
// Don't check for updates if already checked within past 24 hours
if (Date.now() - lastVersionCheck.getTime() < 1000 * 60 * 60 * 24) {
shouldCheckVersion = false;
@@ -88,7 +110,14 @@ const main = async () => {
try {
// Set cache to prevent checking for updates again for 24 hours
cache.set("last-version-check", new Date().toISOString());
fs.writeFileSync(
lastVersionCheckCachePath,
new Date().toISOString(),
{
encoding: "utf-8",
mode: 0o600,
},
);
} catch {
// no-op
}
@@ -300,17 +329,22 @@ const main = async () => {
"Deploy a dynamic smart contract made up of extensions to blockchains",
)
.option("--zksync", "Deploy on ZKSync")
.option("-k, --key <key>", "API key to authorize usage")
.option("-k, --key <key>", "API secret key to authorize usage")
.action(async (options) => {
let apiSecretKey = "";
let secretKey = "";
// If no key is passed in, prompt the user to login. If it is passed in, use it.
if (!options.key) {
apiSecretKey = await loginUser(cache);
await loginUser({
credsConfigPath,
cliWalletPath,
tokenPath,
});
} else {
// Don't need to validate anymore? Also, should probably rely on the underlying service to throw that error.
await validateKey(options.key);
apiSecretKey = options.key;
secretKey = options.key;
}
const url = await deploy(options, apiSecretKey);
const url = await deploy(options, secretKey);
if (url && !options.ci) {
await open(url);
}
@@ -332,20 +366,25 @@ const main = async () => {
.option("--dry-run", "dry run (skip actually publishing)")
.option("-d, --debug", "show debug logs")
.option("--ci", "Continuous Integration mode")
.option("-k, --key <key>", "API key to authorize usage")
.option("-k, --key <key>", "API secret key to authorize usage")
.action(async (options) => {
let apiSecretKey = "";
let secretKey = "";
// If no key is passed in, prompt the user to login. If it is passed in, use it.
if (!options.key) {
apiSecretKey = await loginUser(cache);
await loginUser({
credsConfigPath,
cliWalletPath,
tokenPath,
});
} else {
// Don't need to validate anymore? Also, should probably rely on the underlying service to throw that error.
await validateKey(options.key);
apiSecretKey = options.key;
secretKey = options.key;
}
logger.warn(
"'release' is deprecated and will be removed in a future update. Please use 'publish' instead.",
);
const url = await processProject(options, "publish", apiSecretKey);
const url = await processProject(options, "publish", secretKey);
info(
`Open this link to publish your contracts: ${chalk.blueBright(
url.toString(),
@@ -374,17 +413,22 @@ const main = async () => {
.option("--dry-run", "dry run (skip actually publishing)")
.option("-d, --debug", "show debug logs")
.option("--ci", "Continuous Integration mode")
.option("-k, --key <key>", "API key to authorize usage")
.option("-k, --key <key>", "API secret key to authorize usage")
.action(async (options) => {
let apiSecretKey = "";
let secretKey = "";
// If no key is passed in, prompt the user to login. If it is passed in, use it.
if (!options.key) {
apiSecretKey = await loginUser(cache);
await loginUser({
credsConfigPath,
cliWalletPath,
tokenPath,
});
} else {
// Don't need to validate anymore? Also, should probably rely on the underlying service to throw that error.
await validateKey(options.key);
apiSecretKey = options.key;
secretKey = options.key;
}
const url = await processProject(options, "publish", apiSecretKey);
const url = await processProject(options, "publish", secretKey);
info(
`Open this link to publish your contracts: ${chalk.blueBright(
url.toString(),
@@ -399,19 +443,31 @@ const main = async () => {
.command("upload")
.description("Upload any file or directory to decentralized storage (IPFS)")
.argument("[upload]", "path to file or directory to upload")
.option("-k, --key <key>", "API key to authorize usage")
.option("-k, --key <key>", "API secret key to authorize usage")
.action(async (_path, options) => {
let apiSecretKey = "";
let secretKey = "";
let storage: ThirdwebStorage;
// If no key is passed in, prompt the user to login. If it is passed in, use it.
if (!options.key) {
apiSecretKey = await loginUser(cache);
await loginUser({
credsConfigPath,
cliWalletPath,
tokenPath,
});
} else {
// Don't need to validate anymore? Also, should probably rely on the underlying service to throw that error.
await validateKey(options.key);
apiSecretKey = options.key;
secretKey = options.key;
}
const storage = new ThirdwebStorage({
secretKey: apiSecretKey,
});
if (secretKey) {
storage = new ThirdwebStorage({
secretKey,
});
} else {
storage = new ThirdwebStorage();
}
try {
const uri = await upload(storage, _path);
info(
@@ -438,7 +494,7 @@ const main = async () => {
),
);
} else {
logger.error(chalk.redBright("Failed to upload files"), err);
logger.error(chalk.redBright(err.message ? err.message : err));
}
}
});
@@ -460,17 +516,22 @@ const main = async () => {
"Preload ABIs and generate types for your smart contract to strongly type the thirdweb SDK",
)
.option("-p, --path <project-path>", "path to project", ".")
.option("-k, --key <key>", "API key to authorize usage")
.option("-k, --key <key>", "API secret key to authorize usage")
.action(async (options) => {
let apiSecretKey = "";
let secretKey = "";
// If no key is passed in, prompt the user to login. If it is passed in, use it.
if (!options.key) {
apiSecretKey = await loginUser(cache);
await loginUser({
credsConfigPath,
cliWalletPath,
tokenPath,
});
} else {
// Don't need to validate anymore? Also, should probably rely on the underlying service to throw that error.
await validateKey(options.key);
apiSecretKey = options.key;
secretKey = options.key;
}
await generate(options, apiSecretKey);
await generate(options, secretKey);
});
program
@@ -480,7 +541,11 @@ const main = async () => {
)
.option("-n, --new", "Login with a new API secret key", false)
.action(async (options) => {
await loginUser(cache, options, true);
await loginUser({
credsConfigPath,
cliWalletPath,
tokenPath,
}, options, true);
});
program
@@ -489,7 +554,7 @@ const main = async () => {
"Logout of the thirdweb CLI, effectively removing your API secret key from your machine",
)
.action(async () => {
await logoutUser(cache);
await logoutUser(credsConfigPath, tokenPath, cliWalletPath);
});
await program.parseAsync();
+25 -13
View File
@@ -32,12 +32,18 @@ import {
export async function processProject(
options: any,
command: "deploy" | "publish",
apiSecretKey: string,
secretKey: string,
) {
// TODO: allow overriding the default storage
const storage = new ThirdwebStorage({
secretKey: apiSecretKey,
});
let storage: ThirdwebStorage;
if (secretKey) {
storage = new ThirdwebStorage({
secretKey,
});
} else {
// Since the auth key is being set in the global context, we don't need to pass anything here.
storage = new ThirdwebStorage();
}
logger.setSettings({
minLevel: options.debug ? "debug" : "info",
@@ -240,7 +246,7 @@ export async function processProject(
} else {
const deployArgs: RouterParams = await formatToExtensions(
selectedContracts,
apiSecretKey,
secretKey,
);
const outputDeployArgs = JSON.stringify(deployArgs, undefined, 2);
@@ -345,9 +351,9 @@ export async function processProject(
loader.succeed("Upload successful");
return getUrl(combinedURIs, command);
} catch (e) {
} catch (err: any) {
loader.fail("Error uploading metadata");
throw e;
throw new Error(err.message ? err.message : err);
}
}
@@ -356,8 +362,8 @@ export function getUrl(hashes: string[], command: string) {
if (hashes.length === 1) {
url = new URL(
THIRDWEB_URL +
`/contracts/${command}/` +
encodeURIComponent(hashes[0].replace("ipfs://", "")),
`/contracts/${command}/` +
encodeURIComponent(hashes[0].replace("ipfs://", "")),
);
} else {
url = new URL(THIRDWEB_URL + "/contracts/" + command);
@@ -370,14 +376,20 @@ export function getUrl(hashes: string[], command: string) {
async function formatToExtensions(
contracts: ContractPayload[],
apiSecretKey: string,
secretKey: string,
): Promise<{
extensions: Extension[];
extensionDeployArgs: ExtensionDeployArgs[];
}> {
const storage = new ThirdwebStorage({
secretKey: apiSecretKey,
});
let storage: ThirdwebStorage;
if (secretKey) {
storage = new ThirdwebStorage({
secretKey,
});
} else {
// Since the auth key is being set in the global context, we don't need to pass anything here.
storage = new ThirdwebStorage();
}
const extensions: Extension[] = [];
const extensionDeployArgs: ExtensionDeployArgs[] = [];
+6
View File
@@ -69,6 +69,9 @@ export async function twCreate(
if (options.reactNative) {
framework = "react-native";
}
if (options.pwaVite) {
framework = "pwa-vite";
}
if (options.solana) {
chain = "solana";
@@ -239,6 +242,7 @@ export async function twCreate(
{ title: "Next.js", value: "next" },
{ title: "Create React App", value: "cra" },
{ title: "Vite", value: "vite" },
{ title: "PWA Vite", value: "pwa-vite" },
{ title: "React Native", value: "react-native" },
{ title: "Node.js", value: "node" },
{ title: "Express", value: "express" },
@@ -265,6 +269,8 @@ export async function twCreate(
if (typeof res.project === "string") {
language = res.project.trim();
}
} else if (framework === "pwa-vite" || framework === "pwa-next") {
language = "typescript";
} else {
const res = await prompts({
type: "select",
@@ -220,7 +220,7 @@ export async function createApp({
}
let startOrDev: string | undefined;
if (framework && (framework === "next" || framework === "vite")) {
if (framework && (framework.includes("next") || framework.includes("vite"))) {
startOrDev = "dev";
} else if (template) {
startOrDev = await getStartOrDev(template);
+12 -6
View File
@@ -8,11 +8,17 @@ import { upload } from "../storage/command";
export async function deployApp(
distPath = "dist",
projectPath = ".",
apiSecretKey: string,
secretKey: string,
) {
const storage = new ThirdwebStorage({
secretKey: apiSecretKey,
});
let storage: ThirdwebStorage;
if (secretKey) {
storage = new ThirdwebStorage({
secretKey,
});
} else {
// Since the auth key is being set in the global context, we don't need to pass anything here.
storage = new ThirdwebStorage();
}
const detectedPackageManager = await detectPackageManager(projectPath, {});
const detectedFramework = await detectFramework(
projectPath,
@@ -74,8 +80,8 @@ export async function deployApp(
"ipfs://",
"https://cf-ipfs.com/ipfs/",
)}`;
} catch (err) {
console.error("Can't upload project", err);
} catch (err: any) {
console.error(err.message ? err.message : err);
return Promise.reject("Can't upload project");
}
}
+3 -3
View File
@@ -12,7 +12,7 @@ type DeployOptions = {
distPath?: string;
};
export async function deploy(options: DeployOptions, apiSecretKey: string) {
export async function deploy(options: DeployOptions, secretKey: string) {
if (options.name) {
const url = generateDashboardUrl(options.name, options.contractVersion);
@@ -33,7 +33,7 @@ export async function deploy(options: DeployOptions, apiSecretKey: string) {
if (options.app) {
try {
const url = await deployApp(options.distPath, options.path, apiSecretKey);
const url = await deployApp(options.distPath, options.path, secretKey);
info(`Here is the link to your app: ${chalk.blueBright(url.toString())}`);
return url.toString();
} catch (err) {
@@ -44,7 +44,7 @@ export async function deploy(options: DeployOptions, apiSecretKey: string) {
}
}
const url = await processProject(options, "deploy", apiSecretKey);
const url = await processProject(options, "deploy", secretKey);
info(
`Open this link to deploy your contracts: ${chalk.blueBright(
url.toString(),
+13 -12
View File
@@ -14,7 +14,7 @@ import { info } from "../core/helpers/logger";
import { GenerateOptions, ThirdwebConfig } from "./types";
import { CHAIN_OPTIONS, getContractsForAddresses } from "./utils";
export async function generate(options: GenerateOptions, apiSecretKey: string) {
export async function generate(options: GenerateOptions, secretKey: string) {
const projectPath: string = options.path?.replace(/\/$/, "") || ".";
let contracts: DeployedContract[] = [];
@@ -55,8 +55,7 @@ export async function generate(options: GenerateOptions, apiSecretKey: string) {
const numberOfNewContracts =
contracts.length - thirdwebConfig.contracts.length;
info(
`Updated thirdweb.json with ${numberOfNewContracts} new contract${
numberOfNewContracts === 1 ? "" : "s"
`Updated thirdweb.json with ${numberOfNewContracts} new contract${numberOfNewContracts === 1 ? "" : "s"
}`,
);
}
@@ -86,19 +85,22 @@ export async function generate(options: GenerateOptions, apiSecretKey: string) {
);
info(
`Created a thirdweb.json file with configuration for ${
contracts.length
} contract${
contracts.length === 1 ? "" : "s"
`Created a thirdweb.json file with configuration for ${contracts.length
} contract${contracts.length === 1 ? "" : "s"
} detected in your project.\n\n - You can also update this configuration manually by editing the file.\n`,
);
}
// Attempt to download the ABI for each contract
ora(`Downloading ABIs for contracts configured in 'thirdweb.json'`).info();
const storage = new ThirdwebStorage({
secretKey: apiSecretKey,
});
let storage: ThirdwebStorage;
if (secretKey) {
storage = new ThirdwebStorage({
secretKey,
});
} else {
storage = new ThirdwebStorage();
}
const metadata: {
address: string;
metadata: Awaited<ReturnType<typeof fetchContractMetadataFromAddress>>;
@@ -187,8 +189,7 @@ export async function generate(options: GenerateOptions, apiSecretKey: string) {
}
ora(
`Downloaded and cached ABIs for ${metadata.length} smart contract${
metadata.length === 1 ? "" : "s"
`Downloaded and cached ABIs for ${metadata.length} smart contract${metadata.length === 1 ? "" : "s"
}`,
).succeed();
+5
View File
@@ -1,5 +1,10 @@
import { DeployedContract } from "@thirdweb-dev/sdk";
export type AuthConfig = {
secretKey?: string;
authToken?: string;
}
export type ThirdwebConfig = {
chainIds: number[];
contracts: DeployedContract[];
+4
View File
@@ -0,0 +1,4 @@
declare module globalThis {
// eslint-disable-next-line no-var
var TW_AUTH_TOKEN: string;
}
+6 -1
View File
@@ -4,6 +4,11 @@ import {
PackageManagerType,
} from "../core/types/ProjectType";
export type ICredsConfig = {
password: string;
expiration: number;
}
export type IProcessContractAppTypeArgs = {
detectedPackageManager: PackageManagerType;
thirdwebDepsToUpdate: Set<string>;
@@ -43,4 +48,4 @@ export type ApiResponse = {
statusCode: number;
message: string;
};
};
};
+5
View File
@@ -4,6 +4,11 @@ import path from "path";
import { PackageManagerType } from "../core/types/ProjectType";
import { runCommand } from "../create/helpers/run-command";
import { IProcessAppTypeArgs, IProcessContractAppTypeArgs } from "./types";
import crypto from "crypto";
export function generateStateParameter(length: number) {
return crypto.randomBytes(length).toString("hex");
}
export function convertDependenciesToStringFormat(dependenciesObject: object) {
return Object.entries(dependenciesObject).map(([pkg, versionDetails]) => {
+2 -2
View File
@@ -69,9 +69,9 @@ export async function upload(
);
try {
uri = await storage.upload(file, { uploadWithoutDirectory: true });
} catch (err) {
} catch (err: any) {
spin.fail("Failed to upload file to IPFS.");
return Promise.reject(err);
return Promise.reject(err.message ? err.message : err);
}
spin.succeed("Successfully uploaded file to IPFS.");
} else {
+6
View File
@@ -1,5 +1,11 @@
# @thirdweb-dev/contracts-js
## 1.3.12
### Patch Changes
- [#1518](https://github.com/thirdweb-dev/js/pull/1518) [`34a3bb8a`](https://github.com/thirdweb-dev/js/commit/34a3bb8ae3c1d7a506e5568a9e79ab7e469557a8) Thanks [@nkrishang](https://github.com/nkrishang)! - Update contracts package
## 1.3.11
### Patch Changes
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@thirdweb-dev/contracts-js",
"version": "1.3.11",
"version": "1.3.12",
"main": "dist/thirdweb-dev-contracts-js.cjs.js",
"module": "dist/thirdweb-dev-contracts-js.esm.js",
"browser": {
@@ -10,7 +10,7 @@
"license": "Apache-2.0",
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/contracts-js",
"dependencies": {
"@thirdweb-dev/contracts": "3.8.3"
"@thirdweb-dev/contracts": "3.9.3-0"
},
"devDependencies": {
"@babel/preset-env": "^7.22.9",
+56
View File
@@ -1,5 +1,61 @@
# @thirdweb-dev/react-core
## 3.14.38
### Patch Changes
- Updated dependencies [[`eb463735`](https://github.com/thirdweb-dev/js/commit/eb463735e2f784cd1d212a982835af95cf60766b), [`adec589e`](https://github.com/thirdweb-dev/js/commit/adec589ead8ceff1b57169e05a3e6733b4652cc7), [`b30566c6`](https://github.com/thirdweb-dev/js/commit/b30566c68436ad94ddc938a380eccc13a8a7147d), [`0f027069`](https://github.com/thirdweb-dev/js/commit/0f027069064bebe647f9235fa86ef7f165ffc7b3), [`f5aed34d`](https://github.com/thirdweb-dev/js/commit/f5aed34d3c71065c3f45df2c1eb84ba9c36162d5)]:
- @thirdweb-dev/wallets@1.1.21
- @thirdweb-dev/sdk@3.10.57
- @thirdweb-dev/chains@0.1.49
- @thirdweb-dev/storage@1.2.9
- @thirdweb-dev/auth@3.2.38
## 3.14.37
### Patch Changes
- Updated dependencies [[`f59b729f`](https://github.com/thirdweb-dev/js/commit/f59b729f8b09aa86655b8e8a70fba644fc52009b), [`911e14fc`](https://github.com/thirdweb-dev/js/commit/911e14fcac743b07fa1a66440c72d662c08e971c), [`cd6b07b5`](https://github.com/thirdweb-dev/js/commit/cd6b07b591606d2671794cebebf8edcb59076c32)]:
- @thirdweb-dev/sdk@3.10.56
- @thirdweb-dev/chains@0.1.48
- @thirdweb-dev/wallets@1.1.20
- @thirdweb-dev/auth@3.2.37
## 3.14.36
### Patch Changes
- [#1522](https://github.com/thirdweb-dev/js/pull/1522) [`088547f7`](https://github.com/thirdweb-dev/js/commit/088547f763294f1641c01ffe1aabac585f255dc0) Thanks [@MananTank](https://github.com/MananTank)! - - New prop `switchToActiveChain` added to `ConnectWallet`` component to show "Switch Network" button if wallet is not connected to the `activeChain`passed to the`ThirdwebProvider`
- Add max-height on `ConnectWallet` modal
- Local Wallet UI adjustments
- Updated dependencies [[`586e91db`](https://github.com/thirdweb-dev/js/commit/586e91dbe610588cc7b24fade59172fed6481074), [`34a3bb8a`](https://github.com/thirdweb-dev/js/commit/34a3bb8ae3c1d7a506e5568a9e79ab7e469557a8), [`91f0245b`](https://github.com/thirdweb-dev/js/commit/91f0245be78ae523e1faea26b1032bfb283467d9), [`f65578d6`](https://github.com/thirdweb-dev/js/commit/f65578d637decc8b87cada5b5b0c8c504064d9d5), [`5a373a75`](https://github.com/thirdweb-dev/js/commit/5a373a75090da7e1e05724ed1a3a3a6aa9f7fd21), [`ae74b8ef`](https://github.com/thirdweb-dev/js/commit/ae74b8ef6200dba8affa8b52e7d834c5552350d0), [`bc003c2f`](https://github.com/thirdweb-dev/js/commit/bc003c2fef33fcf7ce5981d8634911ac4bcaa927), [`447d9846`](https://github.com/thirdweb-dev/js/commit/447d984653f77af6860ae907072e768b584b263d), [`f65578d6`](https://github.com/thirdweb-dev/js/commit/f65578d637decc8b87cada5b5b0c8c504064d9d5)]:
- @thirdweb-dev/sdk@3.10.55
- @thirdweb-dev/chains@0.1.47
- @thirdweb-dev/storage@1.2.8
- @thirdweb-dev/wallets@1.1.19
- @thirdweb-dev/auth@3.2.36
## 3.14.35
### Patch Changes
- Updated dependencies [[`184c325a`](https://github.com/thirdweb-dev/js/commit/184c325ab2ef028022a050c4274f2ab12b1a3a7f), [`046c9ad6`](https://github.com/thirdweb-dev/js/commit/046c9ad604587ff79bf028c4fe7b1f9c94f4ea54), [`c12f0874`](https://github.com/thirdweb-dev/js/commit/c12f0874b4dac43c263c7edb20d0343c16381c34)]:
- @thirdweb-dev/chains@0.1.46
- @thirdweb-dev/storage@1.2.7
- @thirdweb-dev/sdk@3.10.54
- @thirdweb-dev/wallets@1.1.18
- @thirdweb-dev/auth@3.2.35
## 3.14.34
### Patch Changes
- Updated dependencies [[`f97ddf4c`](https://github.com/thirdweb-dev/js/commit/f97ddf4c7f14854f3b204ad9741b52ddb8dac736)]:
- @thirdweb-dev/chains@0.1.45
- @thirdweb-dev/sdk@3.10.53
- @thirdweb-dev/wallets@1.1.17
- @thirdweb-dev/auth@3.2.34
## 3.14.33
### Patch Changes
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@thirdweb-dev/react-core",
"version": "3.14.33",
"version": "3.14.38",
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/react-core",
"author": "thirdweb eng <[email protected]>",
"license": "Apache-2.0",
@@ -98,7 +98,7 @@
"typescript": "^5.1.6"
},
"dependencies": {
"@tanstack/react-query": "^4.32.0",
"@tanstack/react-query": "^4.33.0",
"@thirdweb-dev/chains": "workspace:*",
"@thirdweb-dev/generated-abis": "workspace:^",
"@thirdweb-dev/sdk": "workspace:*",
@@ -152,6 +152,7 @@ export const ThirdwebProviderCore = <TChains extends Chain[]>({
autoSwitch={props.autoSwitch}
autoConnectTimeout={props.autoConnectTimeout}
clientId={props.clientId}
activeChainSetExplicitly={!!props.activeChain}
>
<ThirdwebSDKProviderWrapper
queryClient={props.queryClient}
@@ -89,6 +89,7 @@ type ThirdwebWalletContextData = {
* Get wallet config object from wallet instance
*/
getWalletConfig: (walletInstance: WalletInstance) => WalletConfig | undefined;
activeChainSetExplicitly: boolean;
};
const ThirdwebWalletContext = /* @__PURE__ */ createContext<
@@ -106,6 +107,7 @@ export function ThirdwebWalletProvider(
autoSwitch?: boolean;
autoConnectTimeout?: number;
clientId?: string;
activeChainSetExplicitly: boolean;
}>,
) {
const [signer, setSigner] = useState<Signer | undefined>(undefined);
@@ -480,6 +482,7 @@ export function ThirdwebWalletProvider(
getWalletConfig: (walletInstance: WalletInstance) => {
return walletInstanceToConfig.get(walletInstance);
},
activeChainSetExplicitly: props.activeChainSetExplicitly,
}}
>
{props.children}
@@ -21,7 +21,6 @@ import {
} from "@tanstack/react-query";
import { getCachedAbiForContract, TransactionResult } from "@thirdweb-dev/sdk";
import type {
Abi,
CommonContractSchemaInput,
ContractEvent,
ContractForPrebuiltContractType,
@@ -33,6 +32,7 @@ import type {
ThirdwebSDK,
ValidContractInstance,
BaseContractForAddress,
PublishedMetadata,
} from "@thirdweb-dev/sdk";
import type { CallOverrides, ContractInterface, providers } from "ethers";
import { useEffect, useMemo } from "react";
@@ -88,19 +88,11 @@ export const contractType = {
// end contract type
type FetchCompilerMetadataReturnType = {
name: string;
metadata: Record<string, any>;
abi: Abi;
info: Record<string, any>;
licenses: string[];
};
// contract compiler metadata
function fetchCompilerMetadata(
contractAddress: RequiredParam<ContractAddress>,
sdk: RequiredParam<ThirdwebSDK>,
): Promise<FetchCompilerMetadataReturnType> | null {
): Promise<PublishedMetadata> | null {
if (!contractAddress || !sdk) {
return null;
}
@@ -114,7 +106,7 @@ function fetchCompilerMetadata(
export function useCompilerMetadata(
contractAddress: RequiredParam<ContractAddress>,
): UseQueryResult<FetchCompilerMetadataReturnType | null> {
): UseQueryResult<PublishedMetadata | null> {
const sdk = useSDK();
return useQueryWithNetwork(
+3
View File
@@ -251,6 +251,9 @@ export { ThirdwebSDKProvider } from "./providers/thirdweb-sdk-provider";
export { useSDK, useSDKChainId } from "./hooks/useSDK";
export type { ThirdwebSDKProviderProps } from "./providers/types";
// utils
export { invalidateContractAndBalances } from "./utils/cache-keys";
// types
export type {
Chain,
+10
View File
@@ -1,5 +1,15 @@
# @thirdweb-dev/react-native-compat
## 0.2.57
## 0.2.56
## 0.2.55
## 0.2.54
## 0.2.53
## 0.2.52
## 0.2.51
+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.52",
"version": "0.2.57",
"author": "thirdweb eng <[email protected]>",
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/react-native-compat",
"license": "Apache-2.0",
+67
View File
@@ -1,5 +1,72 @@
# @thirdweb-dev/react-native
## 0.2.57
### Patch Changes
- Updated dependencies [[`eb463735`](https://github.com/thirdweb-dev/js/commit/eb463735e2f784cd1d212a982835af95cf60766b), [`adec589e`](https://github.com/thirdweb-dev/js/commit/adec589ead8ceff1b57169e05a3e6733b4652cc7), [`b30566c6`](https://github.com/thirdweb-dev/js/commit/b30566c68436ad94ddc938a380eccc13a8a7147d), [`0f027069`](https://github.com/thirdweb-dev/js/commit/0f027069064bebe647f9235fa86ef7f165ffc7b3), [`f5aed34d`](https://github.com/thirdweb-dev/js/commit/f5aed34d3c71065c3f45df2c1eb84ba9c36162d5)]:
- @thirdweb-dev/wallets@1.1.21
- @thirdweb-dev/sdk@3.10.57
- @thirdweb-dev/chains@0.1.49
- @thirdweb-dev/storage@1.2.9
- @thirdweb-dev/react-core@3.14.38
## 0.2.56
### Patch Changes
- [#1536](https://github.com/thirdweb-dev/js/pull/1536) [`387dddbd`](https://github.com/thirdweb-dev/js/commit/387dddbd87ff6c1a53ffaf663564a44b89a3a2a5) Thanks [@iketw](https://github.com/iketw)! - Adds switchToActiveChain prop to the ConnectWallet button.
When set to true it will show a "Switch Network" button if the wallet
is connected to a different chain than the `activeChain` provided in `ThirdwebProvider`
**Note:** IF you support multiple networks in your app this prop should
be set to `false` to allow users to switch between networks.
Usage:
```javascript
<ConnectWallet switchToActiveChain={true} />
```
- Updated dependencies [[`f59b729f`](https://github.com/thirdweb-dev/js/commit/f59b729f8b09aa86655b8e8a70fba644fc52009b), [`911e14fc`](https://github.com/thirdweb-dev/js/commit/911e14fcac743b07fa1a66440c72d662c08e971c), [`cd6b07b5`](https://github.com/thirdweb-dev/js/commit/cd6b07b591606d2671794cebebf8edcb59076c32)]:
- @thirdweb-dev/[email protected]
- @thirdweb-dev/[email protected]
- @thirdweb-dev/[email protected]
- @thirdweb-dev/[email protected]
## 0.2.55
### Patch Changes
- Updated dependencies [[`586e91db`](https://github.com/thirdweb-dev/js/commit/586e91dbe610588cc7b24fade59172fed6481074), [`34a3bb8a`](https://github.com/thirdweb-dev/js/commit/34a3bb8ae3c1d7a506e5568a9e79ab7e469557a8), [`91f0245b`](https://github.com/thirdweb-dev/js/commit/91f0245be78ae523e1faea26b1032bfb283467d9), [`f65578d6`](https://github.com/thirdweb-dev/js/commit/f65578d637decc8b87cada5b5b0c8c504064d9d5), [`5a373a75`](https://github.com/thirdweb-dev/js/commit/5a373a75090da7e1e05724ed1a3a3a6aa9f7fd21), [`ae74b8ef`](https://github.com/thirdweb-dev/js/commit/ae74b8ef6200dba8affa8b52e7d834c5552350d0), [`bc003c2f`](https://github.com/thirdweb-dev/js/commit/bc003c2fef33fcf7ce5981d8634911ac4bcaa927), [`447d9846`](https://github.com/thirdweb-dev/js/commit/447d984653f77af6860ae907072e768b584b263d), [`f65578d6`](https://github.com/thirdweb-dev/js/commit/f65578d637decc8b87cada5b5b0c8c504064d9d5), [`088547f7`](https://github.com/thirdweb-dev/js/commit/088547f763294f1641c01ffe1aabac585f255dc0)]:
- @thirdweb-dev/[email protected]
- @thirdweb-dev/[email protected]
- @thirdweb-dev/[email protected]
- @thirdweb-dev/[email protected]
- @thirdweb-dev/[email protected]
## 0.2.54
### Patch Changes
- Updated dependencies [[`184c325a`](https://github.com/thirdweb-dev/js/commit/184c325ab2ef028022a050c4274f2ab12b1a3a7f), [`046c9ad6`](https://github.com/thirdweb-dev/js/commit/046c9ad604587ff79bf028c4fe7b1f9c94f4ea54), [`c12f0874`](https://github.com/thirdweb-dev/js/commit/c12f0874b4dac43c263c7edb20d0343c16381c34)]:
- @thirdweb-dev/[email protected]
- @thirdweb-dev/[email protected]
- @thirdweb-dev/[email protected]
- @thirdweb-dev/[email protected]
- @thirdweb-dev/[email protected]
## 0.2.53
### Patch Changes
- Updated dependencies [[`f97ddf4c`](https://github.com/thirdweb-dev/js/commit/f97ddf4c7f14854f3b204ad9741b52ddb8dac736)]:
- @thirdweb-dev/[email protected]
- @thirdweb-dev/[email protected]
- @thirdweb-dev/[email protected]
- @thirdweb-dev/[email protected]
## 0.2.52
### Patch Changes
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@thirdweb-dev/react-native",
"version": "0.2.52",
"version": "0.2.57",
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/react-native",
"author": "thirdweb eng <[email protected]>",
"license": "Apache-2.0",
@@ -28,7 +28,7 @@
"@magic-sdk/provider": "17.2.0",
"@magic-sdk/react-native-bare": "^18.5.0",
"@shopify/restyle": "^2.4.2",
"@tanstack/react-query": "^4.32.0",
"@tanstack/react-query": "^4.33.0",
"@thirdweb-dev/chains": "workspace:*",
"@thirdweb-dev/react-core": "workspace:*",
"@thirdweb-dev/sdk": "workspace:*",
@@ -3,11 +3,18 @@ import {
ConnectWalletDetailsProps,
WalletDetailsButton,
} from "./ConnectWalletDetails/WalletDetailsButton";
import { useAddress } from "@thirdweb-dev/react-core";
import { useEffect, useRef } from "react";
import { Animated } from "react-native";
import {
useAddress,
useNetworkMismatch,
useSwitchChain,
useWalletContext,
} from "@thirdweb-dev/react-core";
import { useEffect, useRef, useState } from "react";
import { ActivityIndicator, Animated, StyleSheet } from "react-native";
import { ConnectWalletButton } from "./ConnectWalletFlow/ConnectWalletButton";
import { ConnectWalletButtonProps } from "./ConnectWalletFlow/ConnectWalletButton";
import BaseButton from "./base/BaseButton";
import Text from "./base/Text";
export type ConnectWalletProps = {
/**
@@ -26,6 +33,17 @@ export type ConnectWalletProps = {
* @default false
*/
hideTestnetFaucet?: boolean;
/**
* Whether to show "Switch Network" button if the wallet is connected,
* but it is not connected to the `activeChain` provided in `ThirdwebProvider`
*
* Please, note that if you support multiple networks in your app this prop should
* be set to `false` to allow users to switch between networks.
*
* @default false
*/
switchToActiveChain?: boolean;
} & ConnectWalletButtonProps;
export const ConnectWallet = ({
@@ -35,9 +53,15 @@ export const ConnectWallet = ({
modalTitle,
extraRows,
hideTestnetFaucet,
switchToActiveChain,
}: ConnectWalletProps) => {
const fadeAnim = useRef(new Animated.Value(0)).current;
const address = useAddress();
const isNetworkMismatch = useNetworkMismatch();
const { activeChainSetExplicitly } = useWalletContext();
const { activeChain } = useWalletContext();
const switchChain = useSwitchChain();
const [switching, setSwitching] = useState(false);
useEffect(() => {
Animated.timing(fadeAnim, {
@@ -51,12 +75,38 @@ export const ConnectWallet = ({
<ThemeProvider theme={theme}>
<Animated.View style={{ opacity: fadeAnim }}>
{address ? (
<WalletDetailsButton
address={address}
detailsButton={detailsButton}
extraRows={extraRows}
hideTestnetFaucet={hideTestnetFaucet}
/>
switchToActiveChain &&
isNetworkMismatch &&
activeChainSetExplicitly ? (
<BaseButton
backgroundColor="buttonBackgroundColor"
onPress={async () => {
setSwitching(true);
try {
await switchChain(activeChain.chainId);
} catch {
// ignore
}
setSwitching(false);
}}
style={styles.connectWalletButton}
>
{switching ? (
<ActivityIndicator size="small" color="buttonTextColor" />
) : (
<Text variant="bodyLarge" color="buttonTextColor">
Switch Network
</Text>
)}
</BaseButton>
) : (
<WalletDetailsButton
address={address}
detailsButton={detailsButton}
extraRows={extraRows}
hideTestnetFaucet={hideTestnetFaucet}
/>
)
) : (
<ConnectWalletButton
modalTitle={modalTitle}
@@ -68,3 +118,17 @@ export const ConnectWallet = ({
</ThemeProvider>
);
};
const styles = StyleSheet.create({
connectWalletButton: {
display: "flex",
flexDirection: "row",
alignContent: "center",
alignItems: "center",
justifyContent: "center",
borderRadius: 8,
paddingHorizontal: 10,
paddingVertical: 10,
minWidth: 150,
},
});
+57
View File
@@ -1,5 +1,62 @@
# @thirdweb-dev/react
## 3.14.38
### Patch Changes
- [#1532](https://github.com/thirdweb-dev/js/pull/1532) [`b29ec675`](https://github.com/thirdweb-dev/js/commit/b29ec675f9c41c49c015af2427d5402367c06c73) Thanks [@MananTank](https://github.com/MananTank)! - Export ConnectModalInline component
- [#1544](https://github.com/thirdweb-dev/js/pull/1544) [`eb463735`](https://github.com/thirdweb-dev/js/commit/eb463735e2f784cd1d212a982835af95cf60766b) Thanks [@iketw](https://github.com/iketw)! - Adds support for Rainbow's new browser extension
- Updated dependencies [[`eb463735`](https://github.com/thirdweb-dev/js/commit/eb463735e2f784cd1d212a982835af95cf60766b), [`adec589e`](https://github.com/thirdweb-dev/js/commit/adec589ead8ceff1b57169e05a3e6733b4652cc7), [`b30566c6`](https://github.com/thirdweb-dev/js/commit/b30566c68436ad94ddc938a380eccc13a8a7147d), [`0f027069`](https://github.com/thirdweb-dev/js/commit/0f027069064bebe647f9235fa86ef7f165ffc7b3), [`f5aed34d`](https://github.com/thirdweb-dev/js/commit/f5aed34d3c71065c3f45df2c1eb84ba9c36162d5)]:
- @thirdweb-dev/wallets@1.1.21
- @thirdweb-dev/sdk@3.10.57
- @thirdweb-dev/chains@0.1.49
- @thirdweb-dev/react-core@3.14.38
## 3.14.37
### Patch Changes
- Updated dependencies [[`f59b729f`](https://github.com/thirdweb-dev/js/commit/f59b729f8b09aa86655b8e8a70fba644fc52009b), [`911e14fc`](https://github.com/thirdweb-dev/js/commit/911e14fcac743b07fa1a66440c72d662c08e971c), [`cd6b07b5`](https://github.com/thirdweb-dev/js/commit/cd6b07b591606d2671794cebebf8edcb59076c32)]:
- @thirdweb-dev/sdk@3.10.56
- @thirdweb-dev/chains@0.1.48
- @thirdweb-dev/react-core@3.14.37
- @thirdweb-dev/wallets@1.1.20
## 3.14.36
### Patch Changes
- [#1522](https://github.com/thirdweb-dev/js/pull/1522) [`088547f7`](https://github.com/thirdweb-dev/js/commit/088547f763294f1641c01ffe1aabac585f255dc0) Thanks [@MananTank](https://github.com/MananTank)! - - New prop `switchToActiveChain` added to `ConnectWallet`` component to show "Switch Network" button if wallet is not connected to the `activeChain`passed to the`ThirdwebProvider`
- Add max-height on `ConnectWallet` modal
- Local Wallet UI adjustments
- Updated dependencies [[`586e91db`](https://github.com/thirdweb-dev/js/commit/586e91dbe610588cc7b24fade59172fed6481074), [`34a3bb8a`](https://github.com/thirdweb-dev/js/commit/34a3bb8ae3c1d7a506e5568a9e79ab7e469557a8), [`91f0245b`](https://github.com/thirdweb-dev/js/commit/91f0245be78ae523e1faea26b1032bfb283467d9), [`5a373a75`](https://github.com/thirdweb-dev/js/commit/5a373a75090da7e1e05724ed1a3a3a6aa9f7fd21), [`ae74b8ef`](https://github.com/thirdweb-dev/js/commit/ae74b8ef6200dba8affa8b52e7d834c5552350d0), [`bc003c2f`](https://github.com/thirdweb-dev/js/commit/bc003c2fef33fcf7ce5981d8634911ac4bcaa927), [`447d9846`](https://github.com/thirdweb-dev/js/commit/447d984653f77af6860ae907072e768b584b263d), [`f65578d6`](https://github.com/thirdweb-dev/js/commit/f65578d637decc8b87cada5b5b0c8c504064d9d5), [`088547f7`](https://github.com/thirdweb-dev/js/commit/088547f763294f1641c01ffe1aabac585f255dc0)]:
- @thirdweb-dev/sdk@3.10.55
- @thirdweb-dev/chains@0.1.47
- @thirdweb-dev/react-core@3.14.36
- @thirdweb-dev/wallets@1.1.19
## 3.14.35
### Patch Changes
- Updated dependencies [[`184c325a`](https://github.com/thirdweb-dev/js/commit/184c325ab2ef028022a050c4274f2ab12b1a3a7f), [`c12f0874`](https://github.com/thirdweb-dev/js/commit/c12f0874b4dac43c263c7edb20d0343c16381c34)]:
- @thirdweb-dev/chains@0.1.46
- @thirdweb-dev/react-core@3.14.35
- @thirdweb-dev/sdk@3.10.54
- @thirdweb-dev/wallets@1.1.18
## 3.14.34
### Patch Changes
- Updated dependencies [[`f97ddf4c`](https://github.com/thirdweb-dev/js/commit/f97ddf4c7f14854f3b204ad9741b52ddb8dac736)]:
- @thirdweb-dev/chains@0.1.45
- @thirdweb-dev/react-core@3.14.34
- @thirdweb-dev/sdk@3.10.53
- @thirdweb-dev/wallets@1.1.17
## 3.14.33
### Patch Changes
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@thirdweb-dev/react",
"version": "3.14.33",
"version": "3.14.38",
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/react",
"author": "thirdweb eng <[email protected]>",
"license": "Apache-2.0",
@@ -131,7 +131,7 @@
"@radix-ui/react-tabs": "^1.0.4",
"@radix-ui/react-tooltip": "^1.0.6",
"@react-icons/all-files": "^4.1.0",
"@tanstack/react-query": "^4.32.0",
"@tanstack/react-query": "^4.33.0",
"@thirdweb-dev/chains": "workspace:*",
"@thirdweb-dev/react-core": "workspace:*",
"@thirdweb-dev/wallets": "workspace:*",

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