Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4df0c2ee10 | ||
|
|
48a8f9385e | ||
|
|
a91776e121 | ||
|
|
f5aed34d3c | ||
|
|
0f02706906 | ||
|
|
eb463735e2 | ||
|
|
adec589ead | ||
|
|
e5246f2667 | ||
|
|
b29ec675f9 | ||
|
|
b30566c684 |
@@ -1,5 +1,12 @@
|
||||
# @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
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@thirdweb-dev/auth",
|
||||
"version": "3.2.37",
|
||||
"version": "3.2.38",
|
||||
"main": "dist/thirdweb-dev-auth.cjs.js",
|
||||
"module": "dist/thirdweb-dev-auth.esm.js",
|
||||
"browser": {
|
||||
|
||||
@@ -1,5 +1,16 @@
|
||||
# @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
|
||||
|
||||
@@ -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": [
|
||||
{
|
||||
|
||||
@@ -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": {
|
||||
|
||||
@@ -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}"
|
||||
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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": [
|
||||
|
||||
@@ -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": {
|
||||
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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"
|
||||
],
|
||||
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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"
|
||||
|
||||
@@ -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/",
|
||||
|
||||
@@ -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;
|
||||
@@ -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"
|
||||
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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/"
|
||||
|
||||
@@ -5,7 +5,10 @@ export default {
|
||||
"rpc": [
|
||||
"https://base.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
|
||||
"https://mainnet.base.org/",
|
||||
"https://developer-access-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": {
|
||||
|
||||
@@ -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": [
|
||||
|
||||
@@ -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": {
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
// @ts-check
|
||||
/** @typedef { import("../../src/types").Chain } Chain */
|
||||
|
||||
/** @type {Partial<Chain>} */
|
||||
export default {
|
||||
name: "Opbnb Testnet",
|
||||
slug: "opbnb-testnet",
|
||||
};
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@thirdweb-dev/chains",
|
||||
"version": "0.1.48",
|
||||
"version": "0.1.49",
|
||||
"main": "dist/thirdweb-dev-chains.cjs.js",
|
||||
"module": "dist/thirdweb-dev-chains.esm.js",
|
||||
"browser": {
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -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(
|
||||
|
||||
@@ -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",
|
||||
],
|
||||
},
|
||||
],
|
||||
|
||||
@@ -1,5 +1,21 @@
|
||||
# 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
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "thirdweb",
|
||||
"main": "dist/cli/index.js",
|
||||
"version": "0.11.20",
|
||||
"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
@@ -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
@@ -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();
|
||||
|
||||
@@ -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[] = [];
|
||||
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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(),
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
import { DeployedContract } from "@thirdweb-dev/sdk";
|
||||
|
||||
export type AuthConfig = {
|
||||
secretKey?: string;
|
||||
authToken?: string;
|
||||
}
|
||||
|
||||
export type ThirdwebConfig = {
|
||||
chainIds: number[];
|
||||
contracts: DeployedContract[];
|
||||
|
||||
Vendored
+4
@@ -0,0 +1,4 @@
|
||||
declare module globalThis {
|
||||
// eslint-disable-next-line no-var
|
||||
var TW_AUTH_TOKEN: string;
|
||||
}
|
||||
@@ -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;
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -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]) => {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -1,5 +1,16 @@
|
||||
# @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
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@thirdweb-dev/react-core",
|
||||
"version": "3.14.37",
|
||||
"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",
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
# @thirdweb-dev/react-native-compat
|
||||
|
||||
## 0.2.57
|
||||
|
||||
## 0.2.56
|
||||
|
||||
## 0.2.55
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@thirdweb-dev/react-native-compat",
|
||||
"description": "Shims for Thirdweb in React Native Projects",
|
||||
"version": "0.2.56",
|
||||
"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",
|
||||
|
||||
@@ -1,5 +1,16 @@
|
||||
# @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
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@thirdweb-dev/react-native",
|
||||
"version": "0.2.56",
|
||||
"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",
|
||||
|
||||
@@ -1,5 +1,19 @@
|
||||
# @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
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@thirdweb-dev/react",
|
||||
"version": "3.14.37",
|
||||
"version": "3.14.38",
|
||||
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/react",
|
||||
"author": "thirdweb eng <[email protected]>",
|
||||
"license": "Apache-2.0",
|
||||
|
||||
@@ -152,7 +152,7 @@ const DialogContent = styled.div<{ theme?: Theme }>`
|
||||
}
|
||||
`;
|
||||
|
||||
const DialogTitle = /* @__PURE__ */ styled(/* @__PURE__ */ Dialog.Title)<{
|
||||
const DialogTitle = /* @__PURE__ */ styled.h2<{
|
||||
theme?: Theme;
|
||||
}>`
|
||||
margin: 0;
|
||||
|
||||
@@ -2,10 +2,9 @@ import { type Theme, fontSize, media } from "../design-system";
|
||||
import { iconSize } from "../design-system";
|
||||
import { IconButton } from "./buttons";
|
||||
import styled from "@emotion/styled";
|
||||
import { Title } from "@radix-ui/react-dialog";
|
||||
import { ChevronLeftIcon } from "@radix-ui/react-icons";
|
||||
|
||||
export const ModalTitle = /* @__PURE__ */ styled(Title)<{
|
||||
export const ModalTitle = /* @__PURE__ */ styled.h2<{
|
||||
theme?: Theme;
|
||||
centerOnMobile?: boolean;
|
||||
}>`
|
||||
|
||||
@@ -7,6 +7,8 @@ export { useSafe } from "./connectors/gnosis";
|
||||
export { useMagic } from "./connectors/magic";
|
||||
|
||||
export { ConnectWallet } from "../wallet/ConnectWallet/ConnectWallet";
|
||||
export { ConnectModalInline } from "../wallet/ConnectWallet/ConnectModal";
|
||||
|
||||
export { NetworkSelector } from "../wallet/ConnectWallet/NetworkSelector";
|
||||
export type { NetworkSelectorProps } from "../wallet/ConnectWallet/NetworkSelector";
|
||||
|
||||
|
||||
@@ -10,25 +10,41 @@ import {
|
||||
import {
|
||||
ModalConfigCtx,
|
||||
SetModalConfigCtx,
|
||||
WalletUIStatesProvider,
|
||||
useIsWalletModalOpen,
|
||||
useSetIsWalletModalOpen,
|
||||
} from "../../evm/providers/wallet-ui-states-provider";
|
||||
import { ThemeProvider } from "@emotion/react";
|
||||
import { darkTheme, lightTheme } from "../../design-system";
|
||||
import {
|
||||
Theme,
|
||||
darkTheme,
|
||||
lightTheme,
|
||||
radius,
|
||||
spacing,
|
||||
} from "../../design-system";
|
||||
import { useState, useCallback, useEffect, useRef, useContext } from "react";
|
||||
import { GetStartedWithWallets } from "./screens/GetStartedWithWallets";
|
||||
import { reservedScreens } from "./constants";
|
||||
import { HeadlessConnectUI } from "../wallets/headlessConnectUI";
|
||||
import styled from "@emotion/styled";
|
||||
import { scrollbar } from "../../design-system/styles";
|
||||
|
||||
export const ConnectModal = () => {
|
||||
const { theme, title } = useContext(ModalConfigCtx);
|
||||
export const ConnectModalContent = (props: {
|
||||
screen: string | WalletConfig;
|
||||
setScreen: (screen: string | WalletConfig) => void;
|
||||
theme?: "light" | "dark";
|
||||
title?: string;
|
||||
}) => {
|
||||
const { screen, setScreen } = props;
|
||||
const modalConfig = useContext(ModalConfigCtx);
|
||||
const title = props.title || modalConfig.title;
|
||||
const theme = props.theme || modalConfig.theme;
|
||||
const walletConfigs = useWallets();
|
||||
const initialScreen =
|
||||
walletConfigs.length === 1 && !walletConfigs[0].selectUI
|
||||
? walletConfigs[0]
|
||||
: reservedScreens.main;
|
||||
|
||||
const [screen, setScreen] = useState<string | WalletConfig>(initialScreen);
|
||||
const isWalletModalOpen = useIsWalletModalOpen();
|
||||
const setIsWalletModalOpen = useSetIsWalletModalOpen();
|
||||
const connectionStatus = useConnectionStatus();
|
||||
@@ -47,7 +63,13 @@ export const ConnectModal = () => {
|
||||
}
|
||||
setIsWalletModalOpen(false);
|
||||
},
|
||||
[setIsWalletModalOpen, initialScreen, connectionStatus, disconnect],
|
||||
[
|
||||
connectionStatus,
|
||||
setIsWalletModalOpen,
|
||||
setScreen,
|
||||
initialScreen,
|
||||
disconnect,
|
||||
],
|
||||
);
|
||||
|
||||
const handleBack = useCallback(() => {
|
||||
@@ -95,6 +117,55 @@ export const ConnectModal = () => {
|
||||
: darkTheme
|
||||
}
|
||||
>
|
||||
{screen === reservedScreens.main && (
|
||||
<WalletSelector
|
||||
title={title}
|
||||
walletConfigs={walletConfigs}
|
||||
onGetStarted={() => {
|
||||
setScreen(reservedScreens.getStarted);
|
||||
}}
|
||||
selectWallet={setScreen}
|
||||
/>
|
||||
)}
|
||||
|
||||
{screen === reservedScreens.getStarted && (
|
||||
<GetStartedWithWallets onBack={handleBack} />
|
||||
)}
|
||||
|
||||
{WalletConnectUI && (
|
||||
<WalletConnectUI
|
||||
supportedWallets={walletConfigs}
|
||||
theme={theme}
|
||||
goBack={handleBack}
|
||||
close={handleClose}
|
||||
isOpen={isWalletModalOpen}
|
||||
open={() => {
|
||||
setIsWalletModalOpen(true);
|
||||
}}
|
||||
walletConfig={screen}
|
||||
selectionData={walletModalConfig.data}
|
||||
setSelectionData={(data) => {
|
||||
setWalletModalConfig((config) => ({
|
||||
...config,
|
||||
data,
|
||||
}));
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</ThemeProvider>
|
||||
);
|
||||
};
|
||||
|
||||
export const ConnectModal = () => {
|
||||
const { theme } = useContext(ModalConfigCtx);
|
||||
const { screen, setScreen, initialScreen } = useScreen();
|
||||
const isWalletModalOpen = useIsWalletModalOpen();
|
||||
const setIsWalletModalOpen = useSetIsWalletModalOpen();
|
||||
const connectionStatus = useConnectionStatus();
|
||||
const disconnect = useDisconnect();
|
||||
|
||||
return (
|
||||
<ThemeProvider theme={theme === "light" ? lightTheme : darkTheme}>
|
||||
<Modal
|
||||
style={{
|
||||
maxWidth: "450px",
|
||||
@@ -111,42 +182,62 @@ export const ConnectModal = () => {
|
||||
}
|
||||
}}
|
||||
>
|
||||
{screen === reservedScreens.main && (
|
||||
<WalletSelector
|
||||
title={title}
|
||||
walletConfigs={walletConfigs}
|
||||
onGetStarted={() => {
|
||||
setScreen(reservedScreens.getStarted);
|
||||
}}
|
||||
selectWallet={setScreen}
|
||||
/>
|
||||
)}
|
||||
|
||||
{screen === reservedScreens.getStarted && (
|
||||
<GetStartedWithWallets onBack={handleBack} />
|
||||
)}
|
||||
|
||||
{WalletConnectUI && (
|
||||
<WalletConnectUI
|
||||
supportedWallets={walletConfigs}
|
||||
theme={theme}
|
||||
goBack={handleBack}
|
||||
close={handleClose}
|
||||
isOpen={isWalletModalOpen}
|
||||
open={() => {
|
||||
setIsWalletModalOpen(true);
|
||||
}}
|
||||
walletConfig={screen}
|
||||
selectionData={walletModalConfig.data}
|
||||
setSelectionData={(data) => {
|
||||
setWalletModalConfig((config) => ({
|
||||
...config,
|
||||
data,
|
||||
}));
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
<ConnectModalContent screen={screen} setScreen={setScreen} />
|
||||
</Modal>
|
||||
</ThemeProvider>
|
||||
);
|
||||
};
|
||||
|
||||
export const ConnectModalInline = (props: {
|
||||
theme?: "light" | "dark";
|
||||
title?: string;
|
||||
className?: string;
|
||||
}) => {
|
||||
const { screen, setScreen } = useScreen();
|
||||
return (
|
||||
<WalletUIStatesProvider theme={props.theme}>
|
||||
<ThemeProvider theme={props.theme === "light" ? lightTheme : darkTheme}>
|
||||
<ConnectModalInlineContainer className={props.className}>
|
||||
<ConnectModalContent
|
||||
screen={screen}
|
||||
setScreen={setScreen}
|
||||
theme={props.theme}
|
||||
title={props.title}
|
||||
/>
|
||||
</ConnectModalInlineContainer>
|
||||
</ThemeProvider>
|
||||
</WalletUIStatesProvider>
|
||||
);
|
||||
};
|
||||
|
||||
function useScreen() {
|
||||
const walletConfigs = useWallets();
|
||||
const initialScreen =
|
||||
walletConfigs.length === 1 && !walletConfigs[0].selectUI
|
||||
? walletConfigs[0]
|
||||
: reservedScreens.main;
|
||||
|
||||
const [screen, setScreen] = useState<string | WalletConfig>(initialScreen);
|
||||
return {
|
||||
screen,
|
||||
setScreen,
|
||||
initialScreen,
|
||||
};
|
||||
}
|
||||
|
||||
const ConnectModalInlineContainer = styled.div<{ theme?: Theme }>`
|
||||
background: ${(p) => p.theme.bg.base};
|
||||
padding: ${spacing.lg};
|
||||
border-radius: ${radius.xl};
|
||||
max-width: 450px;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
max-height: 70vh;
|
||||
overflow-y: auto;
|
||||
${(p) =>
|
||||
scrollbar({
|
||||
track: "transparent",
|
||||
thumb: p.theme.bg.elevated,
|
||||
hover: p.theme.bg.highlighted,
|
||||
})}
|
||||
`;
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
import { ConnectUIProps, useConnect } from "@thirdweb-dev/react-core";
|
||||
import { WalletConnect } from "@thirdweb-dev/wallets";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import { isMobile } from "../../../evm/utils/isMobile";
|
||||
import { ConnectingScreen } from "../../ConnectWallet/screens/ConnectingScreen";
|
||||
import { GetStartedScreen } from "../../ConnectWallet/screens/GetStartedScreen";
|
||||
import { isMobile } from "../../../evm/utils/isMobile";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import { RainbowScan } from "./RainbowScan";
|
||||
import { WCOpenURI } from "../../ConnectWallet/screens/WCOpenUri";
|
||||
import { GetStartedScreen } from "../../ConnectWallet/screens/GetStartedScreen";
|
||||
import { RainbowWallet } from "@thirdweb-dev/wallets";
|
||||
|
||||
export const RainbowConnectUI = (props: ConnectUIProps<WalletConnect>) => {
|
||||
export const RainbowConnectUI = (props: ConnectUIProps<RainbowWallet>) => {
|
||||
const [screen, setScreen] = useState<
|
||||
"connecting" | "scanning" | "get-started" | "open-wc-uri"
|
||||
"connecting" | "scanning" | "get-started"
|
||||
>("connecting");
|
||||
const { walletConfig, close } = props;
|
||||
const connect = useConnect();
|
||||
@@ -24,14 +23,34 @@ export const RainbowConnectUI = (props: ConnectUIProps<WalletConnect>) => {
|
||||
return;
|
||||
}
|
||||
|
||||
const isInstalled = walletConfig.isInstalled
|
||||
? walletConfig.isInstalled()
|
||||
: false;
|
||||
|
||||
// if loading
|
||||
(async () => {
|
||||
// on mobile, open rainbow app link
|
||||
if (isMobile()) {
|
||||
setScreen("open-wc-uri");
|
||||
} else {
|
||||
// on desktop, show the rainbow scan qr code
|
||||
setScreen("scanning");
|
||||
if (isInstalled) {
|
||||
try {
|
||||
connectPrompted.current = true;
|
||||
setScreen("connecting");
|
||||
await connect(walletConfig);
|
||||
close();
|
||||
} catch (e) {
|
||||
goBack();
|
||||
}
|
||||
}
|
||||
|
||||
// if rainbow is not injected
|
||||
else {
|
||||
// on mobile, open rainbow app link
|
||||
if (isMobile()) {
|
||||
window.open(
|
||||
`https://rainbow.app.link/dapp/${window.location.toString()}`,
|
||||
);
|
||||
} else {
|
||||
// on desktop, show the rainbow scan qr code
|
||||
setScreen("scanning");
|
||||
}
|
||||
}
|
||||
})();
|
||||
}, [walletConfig, close, connect, goBack]);
|
||||
@@ -43,24 +62,7 @@ export const RainbowConnectUI = (props: ConnectUIProps<WalletConnect>) => {
|
||||
onBack={props.goBack}
|
||||
walletName={walletConfig.meta.name}
|
||||
walletIconURL={walletConfig.meta.iconURL}
|
||||
supportLink="https://rainbow.me/"
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
if (screen === "open-wc-uri") {
|
||||
return (
|
||||
<WCOpenURI
|
||||
hideBackButton={hideBackButton}
|
||||
onBack={props.goBack}
|
||||
onConnected={close}
|
||||
walletConfig={walletConfig}
|
||||
supportLink="https://rainbow.me/"
|
||||
appUriPrefix={{
|
||||
ios: "rainbow://",
|
||||
android: "https://rnbwapp.com/",
|
||||
other: "https://rnbwapp.com/",
|
||||
}}
|
||||
supportLink="https://support.rainbow.io/hc/en-us/articles/4406430256539-User-Guide-Troubleshooting"
|
||||
/>
|
||||
);
|
||||
}
|
||||
@@ -83,7 +85,7 @@ export const RainbowConnectUI = (props: ConnectUIProps<WalletConnect>) => {
|
||||
if (screen === "scanning") {
|
||||
return (
|
||||
<RainbowScan
|
||||
onBack={props.goBack}
|
||||
onBack={goBack}
|
||||
onConnected={close}
|
||||
onGetStarted={() => {
|
||||
setScreen("get-started");
|
||||
|
||||
@@ -4,14 +4,14 @@ import {
|
||||
useWalletContext,
|
||||
} from "@thirdweb-dev/react-core";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import type { WalletConnect } from "@thirdweb-dev/wallets";
|
||||
import type { RainbowWallet } from "@thirdweb-dev/wallets";
|
||||
import type { WalletConfig } from "@thirdweb-dev/react-core";
|
||||
|
||||
export const RainbowScan: React.FC<{
|
||||
onBack: () => void;
|
||||
onGetStarted: () => void;
|
||||
onConnected: () => void;
|
||||
walletConfig: WalletConfig<WalletConnect>;
|
||||
walletConfig: WalletConfig<RainbowWallet>;
|
||||
hideBackButton: boolean;
|
||||
}> = ({ onBack, onConnected, onGetStarted, walletConfig, hideBackButton }) => {
|
||||
const createInstance = useCreateWalletInstance();
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import type { WalletOptions, WalletConfig } from "@thirdweb-dev/react-core";
|
||||
import { WalletConnect } from "@thirdweb-dev/wallets";
|
||||
import {
|
||||
RainbowWallet,
|
||||
getInjectedRainbowProvider,
|
||||
} from "@thirdweb-dev/wallets";
|
||||
import { RainbowConnectUI } from "./RainbowConnectUI";
|
||||
import { rainbowWalletUris } from "./rainbowWalletUris";
|
||||
import { handelWCSessionRequest } from "../handleWCSessionRequest";
|
||||
|
||||
type RainbowWalletOptions = {
|
||||
/**
|
||||
@@ -16,33 +17,22 @@ type RainbowWalletOptions = {
|
||||
|
||||
export const rainbowWallet = (
|
||||
options?: RainbowWalletOptions,
|
||||
): WalletConfig<WalletConnect> => {
|
||||
): WalletConfig<RainbowWallet> => {
|
||||
return {
|
||||
id: "rainbow",
|
||||
meta: {
|
||||
name: "Rainbow Wallet",
|
||||
iconURL:
|
||||
"ipfs://QmSZn47p4DVVBfzvg9BAX2EqwnPxkT1YAE7rUnrtd9CybQ/rainbow-logo.png",
|
||||
urls: {
|
||||
android: "https://rnbwapp.com/e/Va41HWS6Oxb",
|
||||
ios: "https://rnbwapp.com/e/OeMdmkJ6Oxb",
|
||||
},
|
||||
},
|
||||
id: RainbowWallet.id,
|
||||
meta: RainbowWallet.meta,
|
||||
create: (walletOptions: WalletOptions) => {
|
||||
const wallet = new WalletConnect({
|
||||
const wallet = new RainbowWallet({
|
||||
...walletOptions,
|
||||
walletId: "rainbow",
|
||||
projectId: options?.projectId,
|
||||
qrcode: false,
|
||||
});
|
||||
|
||||
handelWCSessionRequest(wallet, rainbowWalletUris);
|
||||
|
||||
return wallet;
|
||||
},
|
||||
connectUI: RainbowConnectUI,
|
||||
isInstalled() {
|
||||
return false;
|
||||
return !!getInjectedRainbowProvider();
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,5 +1,17 @@
|
||||
# @thirdweb-dev/sdk
|
||||
|
||||
## 3.10.57
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#1545](https://github.com/thirdweb-dev/js/pull/1545) [`adec589e`](https://github.com/thirdweb-dev/js/commit/adec589ead8ceff1b57169e05a3e6733b4652cc7) Thanks [@joaquim-verges](https://github.com/joaquim-verges)! - Expose joinAbis() utility function
|
||||
|
||||
- [#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.
|
||||
- Updated dependencies [[`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/chains@0.1.49
|
||||
- @thirdweb-dev/storage@1.2.9
|
||||
|
||||
## 3.10.56
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@thirdweb-dev/sdk",
|
||||
"version": "3.10.56",
|
||||
"version": "3.10.57",
|
||||
"description": "The main thirdweb SDK.",
|
||||
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/sdk",
|
||||
"license": "Apache-2.0",
|
||||
|
||||
@@ -28,6 +28,7 @@ export * from "./feature-detection/isFeatureEnabled";
|
||||
export * from "./feature-detection/assertEnabled";
|
||||
export * from "./feature-detection/detectContractFeature";
|
||||
export * from "./feature-detection/hasFunction";
|
||||
export * from "./plugin/joinABIs";
|
||||
|
||||
export * from "./version-checker";
|
||||
export * from "./fetchSourceFilesFromMetadata";
|
||||
|
||||
@@ -64,9 +64,8 @@ export function getChainProvider(
|
||||
|
||||
// if we still don't have an url fall back to just using the chainId or slug in the rpc and try that
|
||||
if (!rpcUrl) {
|
||||
rpcUrl = `https://${chainId || network}.rpc.thirdweb.com/${
|
||||
options.clientId || ""
|
||||
}`;
|
||||
rpcUrl = `https://${chainId || network}.rpc.thirdweb.com/${options.clientId || ""
|
||||
}`;
|
||||
}
|
||||
|
||||
if (!rpcUrl) {
|
||||
@@ -241,6 +240,7 @@ export function getProviderFromRpcUrl(
|
||||
headers["authorization"] = `Bearer ${
|
||||
(globalThis as any).TW_AUTH_TOKEN as string
|
||||
}`;
|
||||
headers["x-authorize-wallet"] = "true";
|
||||
authStrategy = "twAuthToken";
|
||||
}
|
||||
|
||||
@@ -278,18 +278,18 @@ export function getProviderFromRpcUrl(
|
||||
// Otherwise, create a new provider on the specific network
|
||||
const newProvider = chainId
|
||||
? // If we know the chainId we should use the StaticJsonRpcBatchProvider
|
||||
new StaticJsonRpcBatchProvider(
|
||||
{
|
||||
url: rpcUrl,
|
||||
headers,
|
||||
},
|
||||
chainId,
|
||||
)
|
||||
: // Otherwise fall back to the built in json rpc batch provider
|
||||
new providers.JsonRpcBatchProvider({
|
||||
new StaticJsonRpcBatchProvider(
|
||||
{
|
||||
url: rpcUrl,
|
||||
headers,
|
||||
});
|
||||
},
|
||||
chainId,
|
||||
)
|
||||
: // Otherwise fall back to the built in json rpc batch provider
|
||||
new providers.JsonRpcBatchProvider({
|
||||
url: rpcUrl,
|
||||
headers,
|
||||
});
|
||||
|
||||
// Save the provider in our cache
|
||||
RPC_PROVIDER_MAP.set(seralizedOpts, newProvider);
|
||||
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
declare module globalThis {
|
||||
// eslint-disable-next-line no-var
|
||||
var TW_AUTH_TOKEN: string;
|
||||
}
|
||||
@@ -1,5 +1,12 @@
|
||||
# @thirdweb-dev/service-utils
|
||||
|
||||
## 0.4.3
|
||||
|
||||
### Patch 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.
|
||||
|
||||
## 0.4.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@thirdweb-dev/service-utils",
|
||||
"version": "0.4.2",
|
||||
"version": "0.4.3",
|
||||
"main": "dist/thirdweb-dev-service-utils.cjs.js",
|
||||
"module": "dist/thirdweb-dev-service-utils.esm.js",
|
||||
"exports": {
|
||||
|
||||
@@ -6,6 +6,7 @@ export type CoreServiceConfig = {
|
||||
serviceScope: ServiceName;
|
||||
serviceApiKey: string;
|
||||
serviceAction?: string;
|
||||
useWalletAuth?: boolean;
|
||||
};
|
||||
|
||||
export type ApiKeyMetadata = {
|
||||
@@ -73,9 +74,10 @@ export async function fetchKeyMetadataFromApi(
|
||||
export async function fetchAccountFromApi(
|
||||
jwt: string,
|
||||
config: CoreServiceConfig,
|
||||
useWalletAuth: boolean,
|
||||
): Promise<ApiAccountResponse> {
|
||||
const { apiUrl, serviceApiKey } = config;
|
||||
const url = `${apiUrl}/v1/account/me`;
|
||||
const url = useWalletAuth ? `${apiUrl}/v1/wallet/me` : `${apiUrl}/v1/account/me`
|
||||
const response = await fetch(url, {
|
||||
method: "GET",
|
||||
headers: {
|
||||
|
||||
@@ -18,6 +18,8 @@ export type AuthorizationInput = {
|
||||
jwt: string | null;
|
||||
hashedJWT: string | null;
|
||||
targetAddress?: string | string[];
|
||||
// IMPORTANT: this is a stringified boolean! Only pass in true or false here. IK it's not ideal, but it's required to pass it in the headers.
|
||||
useWalletAuth?: string | null;
|
||||
};
|
||||
|
||||
type CacheOptions = {
|
||||
@@ -31,16 +33,16 @@ type CacheOptions = {
|
||||
|
||||
type ApiKeyCacheWithPossibleTTL =
|
||||
| {
|
||||
apiKeyMeta: ApiKeyMetadata;
|
||||
updatedAt: number;
|
||||
}
|
||||
apiKeyMeta: ApiKeyMetadata;
|
||||
updatedAt: number;
|
||||
}
|
||||
| ApiKeyMetadata;
|
||||
|
||||
type AccountCacheWithPossibleTTL =
|
||||
| {
|
||||
apiKeyMeta: AccountMetadata;
|
||||
updatedAt: number;
|
||||
}
|
||||
apiKeyMeta: AccountMetadata;
|
||||
updatedAt: number;
|
||||
}
|
||||
| AccountMetadata;
|
||||
|
||||
export async function authorize(
|
||||
@@ -48,7 +50,7 @@ export async function authorize(
|
||||
serviceConfig: CoreServiceConfig,
|
||||
cacheOptions?: CacheOptions,
|
||||
): Promise<AuthorizationResult> {
|
||||
const { clientId, targetAddress, secretKeyHash, jwt, hashedJWT } = authData;
|
||||
const { clientId, targetAddress, secretKeyHash, jwt, hashedJWT, useWalletAuth } = authData;
|
||||
const { enforceAuth } = serviceConfig;
|
||||
|
||||
// BACKWARDS COMPAT: if auth not enforced and we don't have auth credentials bypass
|
||||
@@ -89,7 +91,7 @@ export async function authorize(
|
||||
}
|
||||
if (!accountMeta) {
|
||||
try {
|
||||
const { data, error } = await fetchAccountFromApi(jwt, serviceConfig);
|
||||
const { data, error } = await fetchAccountFromApi(jwt, serviceConfig, useWalletAuth?.toLowerCase() === "true");
|
||||
if (error) {
|
||||
return {
|
||||
authorized: false,
|
||||
|
||||
@@ -20,7 +20,7 @@ export async function authorizeNode(
|
||||
authInput: AuthInput,
|
||||
serviceConfig: NodeServiceConfig,
|
||||
): Promise<AuthorizationResult> {
|
||||
let authData;
|
||||
let authData: AuthorizationInput;
|
||||
try {
|
||||
authData = extractAuthorizationData(authInput);
|
||||
} catch (e) {
|
||||
@@ -121,12 +121,18 @@ export function extractAuthorizationData(
|
||||
}
|
||||
|
||||
let jwt: null | string = null;
|
||||
let useWalletAuth: null | string = null;
|
||||
// check for authorization header on the request
|
||||
const authorizationHeader = getHeader(headers, "authorization");
|
||||
if (authorizationHeader) {
|
||||
const [type, token] = authorizationHeader.split(" ");
|
||||
if (type.toLowerCase() === "bearer" && !!token) {
|
||||
jwt = token;
|
||||
const walletAuthHeader = getHeader(headers, "x-authorize-wallet");
|
||||
// IK a stringified boolean is not ideal, but it's required to pass it in the headers.
|
||||
if (walletAuthHeader?.toLowerCase() === "true") {
|
||||
useWalletAuth = walletAuthHeader;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -139,6 +145,7 @@ export function extractAuthorizationData(
|
||||
origin,
|
||||
bundleId,
|
||||
targetAddress: authInput.targetAddress,
|
||||
useWalletAuth,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
# @thirdweb-dev/storage
|
||||
|
||||
## 1.2.9
|
||||
|
||||
### Patch 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.
|
||||
|
||||
## 1.2.8
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@thirdweb-dev/storage",
|
||||
"version": "1.2.8",
|
||||
"version": "1.2.9",
|
||||
"main": "dist/thirdweb-dev-storage.cjs.js",
|
||||
"module": "dist/thirdweb-dev-storage.esm.js",
|
||||
"browser": {
|
||||
|
||||
@@ -104,9 +104,8 @@ export class StorageDownloader implements IStorageDownloader {
|
||||
) {
|
||||
headers = {
|
||||
...headers,
|
||||
authorization: `Bearer ${
|
||||
(globalThis as any).TW_AUTH_TOKEN as string
|
||||
}`,
|
||||
authorization: `Bearer ${(globalThis as any).TW_AUTH_TOKEN as string}`,
|
||||
"x-authorize-wallet": 'true',
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -96,9 +96,8 @@ export class IpfsUploader implements IStorageUploader<IpfsUploadBatchOptions> {
|
||||
extensions = file.name.substring(extensionStartIndex);
|
||||
}
|
||||
}
|
||||
fileName = `${
|
||||
i + options.rewriteFileNames.fileStartNumber
|
||||
}${extensions}`;
|
||||
fileName = `${i + options.rewriteFileNames.fileStartNumber
|
||||
}${extensions}`;
|
||||
} else {
|
||||
fileName = `${file.name}`;
|
||||
}
|
||||
@@ -300,6 +299,10 @@ export class IpfsUploader implements IStorageUploader<IpfsUploadBatchOptions> {
|
||||
"authorization",
|
||||
`Bearer ${(globalThis as any).TW_AUTH_TOKEN as string}`,
|
||||
);
|
||||
xhr.setRequestHeader(
|
||||
"x-authorize-wallet",
|
||||
`true`,
|
||||
);
|
||||
}
|
||||
|
||||
xhr.send(form as any);
|
||||
@@ -316,6 +319,7 @@ export class IpfsUploader implements IStorageUploader<IpfsUploadBatchOptions> {
|
||||
}
|
||||
|
||||
const headers: HeadersInit = {};
|
||||
|
||||
if (this.secretKey) {
|
||||
headers["x-secret-key"] = this.secretKey;
|
||||
} else if (this.clientId) {
|
||||
@@ -333,9 +337,9 @@ export class IpfsUploader implements IStorageUploader<IpfsUploadBatchOptions> {
|
||||
"TW_AUTH_TOKEN" in globalThis &&
|
||||
typeof (globalThis as any).TW_AUTH_TOKEN === "string"
|
||||
) {
|
||||
headers["authorization"] = `Bearer ${
|
||||
(globalThis as any).TW_AUTH_TOKEN as string
|
||||
}`;
|
||||
headers["authorization"] = `Bearer ${(globalThis as any).TW_AUTH_TOKEN as string
|
||||
}`;
|
||||
headers["x-authorize-wallet"] = "true";
|
||||
}
|
||||
|
||||
const res = await fetch(`${this.uploadServerUrl}/ipfs/upload`, {
|
||||
@@ -346,8 +350,13 @@ export class IpfsUploader implements IStorageUploader<IpfsUploadBatchOptions> {
|
||||
},
|
||||
body: form.getBuffer(),
|
||||
});
|
||||
|
||||
if (!res.ok) {
|
||||
console.warn(await res.text());
|
||||
if (res.status === 401) {
|
||||
throw new Error(
|
||||
"Unauthorized - You don't have permission to use this service.",
|
||||
);
|
||||
}
|
||||
throw new Error("Failed to upload files to IPFS");
|
||||
}
|
||||
|
||||
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
declare module globalThis {
|
||||
// eslint-disable-next-line no-var
|
||||
var TW_AUTH_TOKEN: string;
|
||||
}
|
||||
@@ -426,7 +426,7 @@ describe("IPFS", async () => {
|
||||
getGatewayUrlForCid(
|
||||
authorizedUrls["ipfs://"][0],
|
||||
// CID changes based on file contents (prod gateway vs staging gateway since they get written)
|
||||
`bafybeie4otkctycxgas34kjsvapcbqspqfj2xzjvyaet26i3nvlxv56oxy/0`,
|
||||
`bafybeicn4fmtzb7kcg5idlzoo7ahomt5khqyz7lrpv2r5zz5n7sb4s2uvm/0`,
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
@@ -1,5 +1,16 @@
|
||||
# @thirdweb-dev/unity-js-bridge
|
||||
|
||||
## 0.2.75
|
||||
|
||||
### 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.2.74
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@thirdweb-dev/unity-js-bridge",
|
||||
"version": "0.2.74",
|
||||
"version": "0.2.75",
|
||||
"main": "dist/thirdweb-unity-bridge.js",
|
||||
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/unity-js-bridge",
|
||||
"license": "Apache-2.0",
|
||||
|
||||
@@ -1,5 +1,17 @@
|
||||
# @thirdweb-dev/wallets
|
||||
|
||||
## 1.1.21
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#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
|
||||
|
||||
- [#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.
|
||||
- Updated dependencies [[`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/sdk@3.10.57
|
||||
- @thirdweb-dev/chains@0.1.49
|
||||
|
||||
## 1.1.20
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -37,7 +37,7 @@ await wallet.connect();
|
||||
|
||||
- Private key
|
||||
- AWS KMs
|
||||
- AWS Sercret Manager
|
||||
- AWS Secret Manager
|
||||
|
||||
#### Documentation
|
||||
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"main": "dist/thirdweb-dev-wallets-evm-connectors-rainbow.cjs.js",
|
||||
"module": "dist/thirdweb-dev-wallets-evm-connectors-rainbow.esm.js",
|
||||
"browser": {
|
||||
"./dist/thirdweb-dev-wallets-evm-connectors-rainbow.esm.js": "./dist/thirdweb-dev-wallets-evm-connectors-rainbow.browser.esm.js"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"main": "dist/thirdweb-dev-wallets-evm-wallets-rainbow-wallet.cjs.js",
|
||||
"module": "dist/thirdweb-dev-wallets-evm-wallets-rainbow-wallet.esm.js",
|
||||
"browser": {
|
||||
"./dist/thirdweb-dev-wallets-evm-wallets-rainbow-wallet.esm.js": "./dist/thirdweb-dev-wallets-evm-wallets-rainbow-wallet.browser.esm.js"
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@thirdweb-dev/wallets",
|
||||
"version": "1.1.20",
|
||||
"version": "1.1.21",
|
||||
"main": "dist/thirdweb-dev-wallets.cjs.js",
|
||||
"module": "dist/thirdweb-dev-wallets.esm.js",
|
||||
"types": "dist/thirdweb-dev-wallets.cjs.d.ts",
|
||||
@@ -197,6 +197,13 @@
|
||||
},
|
||||
"default": "./evm/connectors/trust/dist/thirdweb-dev-wallets-evm-connectors-trust.cjs.js"
|
||||
},
|
||||
"./evm/wallets/rainbow-wallet": {
|
||||
"module": {
|
||||
"browser": "./evm/wallets/rainbow-wallet/dist/thirdweb-dev-wallets-evm-wallets-rainbow-wallet.browser.esm.js",
|
||||
"default": "./evm/wallets/rainbow-wallet/dist/thirdweb-dev-wallets-evm-wallets-rainbow-wallet.esm.js"
|
||||
},
|
||||
"default": "./evm/wallets/rainbow-wallet/dist/thirdweb-dev-wallets-evm-wallets-rainbow-wallet.cjs.js"
|
||||
},
|
||||
"./evm/wallets/wallet-connect": {
|
||||
"module": {
|
||||
"browser": "./evm/wallets/wallet-connect/dist/thirdweb-dev-wallets-evm-wallets-wallet-connect.browser.esm.js",
|
||||
@@ -232,6 +239,13 @@
|
||||
},
|
||||
"default": "./evm/wallets/coinbase-wallet/dist/thirdweb-dev-wallets-evm-wallets-coinbase-wallet.cjs.js"
|
||||
},
|
||||
"./evm/connectors/rainbow": {
|
||||
"module": {
|
||||
"browser": "./evm/connectors/rainbow/dist/thirdweb-dev-wallets-evm-connectors-rainbow.browser.esm.js",
|
||||
"default": "./evm/connectors/rainbow/dist/thirdweb-dev-wallets-evm-connectors-rainbow.esm.js"
|
||||
},
|
||||
"default": "./evm/connectors/rainbow/dist/thirdweb-dev-wallets-evm-connectors-rainbow.cjs.js"
|
||||
},
|
||||
"./evm/connectors/injected": {
|
||||
"module": {
|
||||
"browser": "./evm/connectors/injected/dist/thirdweb-dev-wallets-evm-connectors-injected.browser.esm.js",
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
import { Ethereum } from "../injected/types";
|
||||
import { assertWindowEthereum } from "../../utils/assertWindowEthereum";
|
||||
|
||||
export function getInjectedRainbowProvider(): Ethereum | undefined {
|
||||
if (typeof window === "undefined") {
|
||||
return;
|
||||
}
|
||||
|
||||
function getReady(ethereum?: Ethereum): Ethereum | undefined {
|
||||
const isRainbow = !!ethereum?.isRainbow;
|
||||
|
||||
if (!isRainbow) {
|
||||
return;
|
||||
}
|
||||
// Brave tries to make itself look like MetaMask
|
||||
// Could also try RPC `web3_clientVersion` if following is unreliable
|
||||
if (ethereum.isBraveWallet && !ethereum._events && !ethereum._state) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (ethereum.isPhantom) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (ethereum.isAvalanche) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (ethereum.isBitKeep) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (ethereum.isMathWallet) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (ethereum.isZerion) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (ethereum.isKuCoinWallet) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (ethereum.isPortal) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (ethereum.isTokenPocket) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (ethereum.isTokenary) {
|
||||
return;
|
||||
}
|
||||
|
||||
return ethereum;
|
||||
}
|
||||
|
||||
if (assertWindowEthereum(globalThis.window)) {
|
||||
if (globalThis.window.ethereum?.providers) {
|
||||
return globalThis.window.ethereum.providers.find(getReady);
|
||||
}
|
||||
|
||||
return getReady(globalThis.window.ethereum);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,156 @@
|
||||
import { AsyncStorage } from "../../../core/AsyncStorage";
|
||||
import {
|
||||
ConnectorNotFoundError,
|
||||
ResourceUnavailableError,
|
||||
RpcError,
|
||||
UserRejectedRequestError,
|
||||
} from "../../../lib/wagmi-core/errors";
|
||||
import { walletIds } from "../../constants/walletIds";
|
||||
import { InjectedConnector, InjectedConnectorOptions } from "../injected";
|
||||
import type { Chain } from "@thirdweb-dev/chains";
|
||||
import { utils } from "ethers";
|
||||
import { getInjectedRainbowProvider } from "./getInjectedRainbowProvider";
|
||||
|
||||
export type RainbowConnectorOptions = Pick<
|
||||
InjectedConnectorOptions,
|
||||
"shimDisconnect"
|
||||
> & {
|
||||
/**
|
||||
* While "disconnected" with `shimDisconnect`, allows user to select a different Rainbow account (than the currently connected account) when trying to connect.
|
||||
*/
|
||||
UNSTABLE_shimOnConnectSelectAccount?: boolean;
|
||||
};
|
||||
|
||||
type RainbowConnectorConstructorArg = {
|
||||
chains?: Chain[];
|
||||
connectorStorage: AsyncStorage;
|
||||
options?: RainbowConnectorOptions;
|
||||
};
|
||||
|
||||
export class RainbowConnector extends InjectedConnector {
|
||||
readonly id = walletIds.rainbow;
|
||||
#UNSTABLE_shimOnConnectSelectAccount: RainbowConnectorOptions["UNSTABLE_shimOnConnectSelectAccount"];
|
||||
|
||||
constructor(arg: RainbowConnectorConstructorArg) {
|
||||
const defaultOptions = {
|
||||
name: "Rainbow Wallet",
|
||||
shimDisconnect: true,
|
||||
shimChainChangedDisconnect: true,
|
||||
getProvider: getInjectedRainbowProvider,
|
||||
};
|
||||
|
||||
const options = {
|
||||
...defaultOptions,
|
||||
...arg.options,
|
||||
};
|
||||
|
||||
super({
|
||||
chains: arg.chains,
|
||||
options,
|
||||
connectorStorage: arg.connectorStorage,
|
||||
});
|
||||
|
||||
this.#UNSTABLE_shimOnConnectSelectAccount =
|
||||
options.UNSTABLE_shimOnConnectSelectAccount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Connect to injected Rainbow provider
|
||||
*/
|
||||
async connect(options: { chainId?: number } = {}) {
|
||||
try {
|
||||
const provider = await this.getProvider();
|
||||
if (!provider) {
|
||||
throw new ConnectorNotFoundError();
|
||||
}
|
||||
|
||||
this.setupListeners();
|
||||
|
||||
// emit "connecting" event
|
||||
this.emit("message", { type: "connecting" });
|
||||
|
||||
// Attempt to show wallet select prompt with `wallet_requestPermissions` when
|
||||
// `shimDisconnect` is active and account is in disconnected state (flag in storage)
|
||||
let account: string | null = null;
|
||||
if (
|
||||
this.#UNSTABLE_shimOnConnectSelectAccount &&
|
||||
this.options?.shimDisconnect &&
|
||||
!Boolean(this.connectorStorage.getItem(this.shimDisconnectKey))
|
||||
) {
|
||||
account = await this.getAccount().catch(() => null);
|
||||
const isConnected = !!account;
|
||||
if (isConnected) {
|
||||
// Attempt to show another prompt for selecting wallet if already connected
|
||||
try {
|
||||
await provider.request({
|
||||
method: "wallet_requestPermissions",
|
||||
params: [{ eth_accounts: {} }],
|
||||
});
|
||||
} catch (error) {
|
||||
// Not all Rainbow injected providers support `wallet_requestPermissions` (e.g. Rainbow iOS).
|
||||
// Only bubble up error if user rejects request
|
||||
if (this.isUserRejectedRequestError(error)) {
|
||||
throw new UserRejectedRequestError(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if account is not already set, request accounts and use the first account
|
||||
if (!account) {
|
||||
const accounts = await provider.request({
|
||||
method: "eth_requestAccounts",
|
||||
});
|
||||
account = utils.getAddress(accounts[0] as string);
|
||||
}
|
||||
|
||||
// get currently connected chainId
|
||||
let connectedChainId = await this.getChainId();
|
||||
// check if connected chain is unsupported
|
||||
let isUnsupported = this.isChainUnsupported(connectedChainId);
|
||||
|
||||
// if chainId is given, but does not match the currently connected chainId, switch to the given chainId
|
||||
if (options.chainId && connectedChainId !== options.chainId) {
|
||||
try {
|
||||
await this.switchChain(options.chainId);
|
||||
// recalculate the chainId and isUnsupported
|
||||
connectedChainId = options.chainId;
|
||||
isUnsupported = this.isChainUnsupported(options.chainId);
|
||||
} catch (e) {
|
||||
console.error(`Could not switch to chain id : ${options.chainId}`, e);
|
||||
}
|
||||
}
|
||||
|
||||
// if shimDisconnect is enabled
|
||||
if (this.options?.shimDisconnect) {
|
||||
// add shimDisconnectKey in storage - this signals that connector is "connected"
|
||||
await this.connectorStorage.setItem(this.shimDisconnectKey, "true");
|
||||
}
|
||||
|
||||
const connectionInfo = {
|
||||
chain: { id: connectedChainId, unsupported: isUnsupported },
|
||||
provider: provider,
|
||||
account,
|
||||
};
|
||||
|
||||
this.emit("connect", connectionInfo);
|
||||
return connectionInfo;
|
||||
} catch (error) {
|
||||
if (this.isUserRejectedRequestError(error)) {
|
||||
throw new UserRejectedRequestError(error);
|
||||
}
|
||||
if ((error as RpcError).code === -32002) {
|
||||
throw new ResourceUnavailableError(error);
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async switchAccount() {
|
||||
const provider = await this.getProvider();
|
||||
await provider.request({
|
||||
method: "wallet_requestPermissions",
|
||||
params: [{ eth_accounts: {} }],
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
declare module globalThis {
|
||||
// eslint-disable-next-line no-var
|
||||
var TW_AUTH_TOKEN: string;
|
||||
}
|
||||
@@ -54,6 +54,7 @@ export class HttpRpcClient {
|
||||
headers["authorization"] = `Bearer ${
|
||||
(globalThis as any).TW_AUTH_TOKEN as string
|
||||
}`;
|
||||
headers["x-authorize-wallet"] = "true";
|
||||
}
|
||||
|
||||
headers["x-sdk-version"] = pkg.version;
|
||||
|
||||
@@ -34,6 +34,12 @@ class VerifyingPaymasterAPI extends PaymasterAPI {
|
||||
};
|
||||
|
||||
if (isTwUrl(this.paymasterUrl)) {
|
||||
if (this.secretKey && this.clientId) {
|
||||
throw new Error(
|
||||
"Cannot use both secret key and client ID. Please use secretKey for server-side applications and clientId for client-side applications.",
|
||||
);
|
||||
}
|
||||
|
||||
if (this.secretKey) {
|
||||
headers["x-secret-key"] = this.secretKey;
|
||||
} else if (this.clientId) {
|
||||
@@ -51,9 +57,8 @@ class VerifyingPaymasterAPI extends PaymasterAPI {
|
||||
"TW_AUTH_TOKEN" in globalThis &&
|
||||
typeof (globalThis as any).TW_AUTH_TOKEN === "string"
|
||||
) {
|
||||
headers["authorization"] = `Bearer ${
|
||||
(globalThis as any).TW_AUTH_TOKEN as string
|
||||
}`;
|
||||
headers["authorization"] = `Bearer ${(globalThis as any).TW_AUTH_TOKEN as string}`;
|
||||
headers["x-authorize-wallet"] = "true";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
export const walletIds = {
|
||||
blocto: "blocto",
|
||||
coinbase: "coinbase",
|
||||
frame: "frame",
|
||||
metamask: "metamask",
|
||||
localWallet: "localWallet",
|
||||
magicLink: "magicLink",
|
||||
metamask: "metamask",
|
||||
paper: "paper",
|
||||
rainbow: "rainbowWallet",
|
||||
smartWallet: "smartWallet",
|
||||
safe: "safe",
|
||||
trust: "trust",
|
||||
walletConnectV1: "walletConnectV1",
|
||||
walletConnect: "walletConnect",
|
||||
magicLink: "magicLink",
|
||||
paper: "paper",
|
||||
blocto: "blocto",
|
||||
// add new ids sorted alphabetically
|
||||
};
|
||||
|
||||
@@ -30,6 +30,7 @@ export * from "./wallets/local-wallet";
|
||||
export * from "./wallets/frame";
|
||||
export * from "./wallets/injected";
|
||||
export * from "./wallets/metamask";
|
||||
export * from "./wallets/rainbow-wallet";
|
||||
export * from "./wallets/wallet-connect";
|
||||
export * from "./wallets/wallet-connect-v1";
|
||||
export * from "./wallets/safe";
|
||||
@@ -46,3 +47,4 @@ export type { Chain } from "@thirdweb-dev/chains";
|
||||
// export the window ethereum util
|
||||
export { assertWindowEthereum } from "./utils/assertWindowEthereum";
|
||||
export { getInjectedMetamaskProvider } from "./connectors/metamask/getInjectedMetamaskProvider";
|
||||
export { getInjectedRainbowProvider } from "./connectors/rainbow/getInjectedRainbowProvider";
|
||||
|
||||
@@ -380,85 +380,85 @@ export class LocalWallet extends AbstractClientWallet<
|
||||
|
||||
type DecryptOptions =
|
||||
| {
|
||||
decrypt?: (message: string, password: string) => Promise<string>;
|
||||
password: string;
|
||||
}
|
||||
decrypt?: (message: string, password: string) => Promise<string>;
|
||||
password: string;
|
||||
}
|
||||
| false;
|
||||
|
||||
type EncryptOptions =
|
||||
| {
|
||||
encrypt?: (message: string, password: string) => Promise<string>;
|
||||
password: string;
|
||||
}
|
||||
encrypt?: (message: string, password: string) => Promise<string>;
|
||||
password: string;
|
||||
}
|
||||
| false;
|
||||
|
||||
type ImportOptions =
|
||||
| {
|
||||
privateKey: string;
|
||||
encryption: DecryptOptions;
|
||||
}
|
||||
privateKey: string;
|
||||
encryption: DecryptOptions;
|
||||
}
|
||||
| {
|
||||
mnemonic: string;
|
||||
encryption: DecryptOptions;
|
||||
}
|
||||
mnemonic: string;
|
||||
encryption: DecryptOptions;
|
||||
}
|
||||
| {
|
||||
encryptedJson: string;
|
||||
password: string;
|
||||
};
|
||||
encryptedJson: string;
|
||||
password: string;
|
||||
};
|
||||
|
||||
type LoadOptions =
|
||||
| {
|
||||
strategy: "encryptedJson";
|
||||
password: string;
|
||||
storage?: AsyncStorage;
|
||||
}
|
||||
strategy: "encryptedJson";
|
||||
password: string;
|
||||
storage?: AsyncStorage;
|
||||
}
|
||||
| {
|
||||
strategy: "privateKey";
|
||||
storage?: AsyncStorage;
|
||||
encryption: DecryptOptions;
|
||||
}
|
||||
strategy: "privateKey";
|
||||
storage?: AsyncStorage;
|
||||
encryption: DecryptOptions;
|
||||
}
|
||||
| {
|
||||
strategy: "mnemonic";
|
||||
storage?: AsyncStorage;
|
||||
encryption: DecryptOptions;
|
||||
};
|
||||
strategy: "mnemonic";
|
||||
storage?: AsyncStorage;
|
||||
encryption: DecryptOptions;
|
||||
};
|
||||
|
||||
// omit the mnemonic strategy option from LoadOptions
|
||||
type LoadOrCreateOptions =
|
||||
| {
|
||||
strategy: "encryptedJson";
|
||||
password: string;
|
||||
storage?: AsyncStorage;
|
||||
}
|
||||
strategy: "encryptedJson";
|
||||
password: string;
|
||||
storage?: AsyncStorage;
|
||||
}
|
||||
| {
|
||||
strategy: "privateKey";
|
||||
storage?: AsyncStorage;
|
||||
encryption: DecryptOptions;
|
||||
};
|
||||
strategy: "privateKey";
|
||||
storage?: AsyncStorage;
|
||||
encryption: DecryptOptions;
|
||||
};
|
||||
|
||||
type SaveOptions =
|
||||
| { strategy: "encryptedJson"; password: string; storage?: AsyncStorage }
|
||||
| {
|
||||
strategy: "privateKey";
|
||||
encryption: EncryptOptions;
|
||||
storage?: AsyncStorage;
|
||||
}
|
||||
strategy: "privateKey";
|
||||
encryption: EncryptOptions;
|
||||
storage?: AsyncStorage;
|
||||
}
|
||||
| {
|
||||
strategy: "mnemonic";
|
||||
encryption: EncryptOptions;
|
||||
storage?: AsyncStorage;
|
||||
};
|
||||
strategy: "mnemonic";
|
||||
encryption: EncryptOptions;
|
||||
storage?: AsyncStorage;
|
||||
};
|
||||
|
||||
type ExportOptions =
|
||||
| { strategy: "encryptedJson"; password: string }
|
||||
| {
|
||||
strategy: "privateKey";
|
||||
encryption: EncryptOptions;
|
||||
}
|
||||
strategy: "privateKey";
|
||||
encryption: EncryptOptions;
|
||||
}
|
||||
| {
|
||||
strategy: "mnemonic";
|
||||
encryption: EncryptOptions;
|
||||
};
|
||||
strategy: "mnemonic";
|
||||
encryption: EncryptOptions;
|
||||
};
|
||||
|
||||
async function defaultEncrypt(message: string, password: string) {
|
||||
const cryptoJS = (await import("crypto-js")).default;
|
||||
@@ -481,7 +481,7 @@ function getDecryptor(encryption: DecryptOptions | undefined) {
|
||||
const noop = async (msg: string) => msg;
|
||||
return encryption
|
||||
? (msg: string) =>
|
||||
(encryption.decrypt || defaultDecrypt)(msg, encryption.password)
|
||||
(encryption.decrypt || defaultDecrypt)(msg, encryption.password)
|
||||
: noop;
|
||||
}
|
||||
|
||||
@@ -496,7 +496,7 @@ function getEncryptor(encryption: EncryptOptions | undefined) {
|
||||
const noop = async (msg: string) => msg;
|
||||
return encryption
|
||||
? (msg: string) =>
|
||||
(encryption.encrypt || defaultEncrypt)(msg, encryption.password)
|
||||
(encryption.encrypt || defaultEncrypt)(msg, encryption.password)
|
||||
: noop;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,161 @@
|
||||
import type { WalletConnectConnector as WalletConnectConnectorType } from "../connectors/wallet-connect";
|
||||
import type { QRModalOptions } from "../connectors/wallet-connect/qrModalOptions";
|
||||
import { Connector, WagmiAdapter } from "../interfaces/connector";
|
||||
import { AbstractClientWallet, WalletOptions } from "./base";
|
||||
import type { RainbowConnector as RainbowConnectorType } from "../connectors/rainbow";
|
||||
import { walletIds } from "../constants/walletIds";
|
||||
import { TW_WC_PROJECT_ID } from "../constants/wc";
|
||||
import { getInjectedRainbowProvider } from "../connectors/rainbow/getInjectedRainbowProvider";
|
||||
|
||||
type RainbowAdditionalOptions = {
|
||||
/**
|
||||
* Whether to open the default Wallet Connect QR code Modal for connecting to Zerion Wallet on mobile if Zerion is not injected when calling connect().
|
||||
*/
|
||||
qrcode?: boolean;
|
||||
|
||||
/**
|
||||
* When connecting Rainbow using the QR Code - Wallet Connect connector is used which requires a project id.
|
||||
* This project id is Your project’s unique identifier for wallet connect that can be obtained at cloud.walletconnect.com.
|
||||
*
|
||||
* https://docs.walletconnect.com/2.0/web3modal/options#projectid-required
|
||||
*/
|
||||
projectId?: string;
|
||||
|
||||
/**
|
||||
* options to customize the Wallet Connect QR Code Modal ( only relevant when qrcode is true )
|
||||
*
|
||||
* https://docs.walletconnect.com/2.0/web3modal/options
|
||||
*/
|
||||
qrModalOptions?: QRModalOptions;
|
||||
};
|
||||
|
||||
export type RainbowWalletOptions = WalletOptions<RainbowAdditionalOptions>;
|
||||
|
||||
type ConnectWithQrCodeArgs = {
|
||||
chainId?: number;
|
||||
onQrCodeUri: (uri: string) => void;
|
||||
onConnected: (accountAddress: string) => void;
|
||||
};
|
||||
|
||||
export class RainbowWallet extends AbstractClientWallet<RainbowAdditionalOptions> {
|
||||
connector?: Connector;
|
||||
walletConnectConnector?: WalletConnectConnectorType;
|
||||
rainbowConnector?: RainbowConnectorType;
|
||||
isInjected: boolean;
|
||||
|
||||
static meta = {
|
||||
name: "Rainbow Wallet",
|
||||
iconURL:
|
||||
"ipfs://QmSZn47p4DVVBfzvg9BAX2EqwnPxkT1YAE7rUnrtd9CybQ/rainbow-logo.png",
|
||||
urls: {
|
||||
chrome:
|
||||
"https://chrome.google.com/webstore/detail/rainbow/opfgelmcmbiajamepnmloijbpoleiama",
|
||||
android: "https://rnbwapp.com/e/Va41HWS6Oxb",
|
||||
ios: "https://rnbwapp.com/e/OeMdmkJ6Oxb",
|
||||
},
|
||||
};
|
||||
|
||||
static id = walletIds.rainbow;
|
||||
|
||||
public get walletName() {
|
||||
return "Rainbow Wallet" as const;
|
||||
}
|
||||
|
||||
constructor(options: RainbowWalletOptions) {
|
||||
super(RainbowWallet.id, options);
|
||||
this.isInjected = !!getInjectedRainbowProvider();
|
||||
}
|
||||
|
||||
protected async getConnector(): Promise<Connector> {
|
||||
if (!this.connector) {
|
||||
// if rainbow is injected, use the injected connector
|
||||
// otherwise, use the wallet connect connector for using the rainbow app on mobile via QR code scan
|
||||
|
||||
if (this.isInjected) {
|
||||
// import the connector dynamically
|
||||
const { RainbowConnector } = await import("../connectors/rainbow");
|
||||
const rainbowConnector = new RainbowConnector({
|
||||
chains: this.chains,
|
||||
connectorStorage: this.walletStorage,
|
||||
options: {
|
||||
shimDisconnect: true,
|
||||
},
|
||||
});
|
||||
|
||||
this.rainbowConnector = rainbowConnector;
|
||||
|
||||
this.connector = new WagmiAdapter(rainbowConnector);
|
||||
} else {
|
||||
const { WalletConnectConnector } = await import(
|
||||
"../connectors/wallet-connect"
|
||||
);
|
||||
|
||||
const walletConnectConnector = new WalletConnectConnector({
|
||||
chains: this.chains,
|
||||
options: {
|
||||
projectId: this.options?.projectId || TW_WC_PROJECT_ID, // TODO,
|
||||
storage: this.walletStorage,
|
||||
qrcode: this.options?.qrcode,
|
||||
dappMetadata: this.dappMetadata,
|
||||
qrModalOptions: this.options?.qrModalOptions,
|
||||
},
|
||||
});
|
||||
|
||||
walletConnectConnector.getProvider().then((provider) => {
|
||||
provider.signer.client.on("session_request_sent", () => {
|
||||
this.emit("wc_session_request_sent");
|
||||
});
|
||||
});
|
||||
|
||||
// need to save this for getting the QR code URI
|
||||
this.walletConnectConnector = walletConnectConnector;
|
||||
this.connector = new WagmiAdapter(walletConnectConnector);
|
||||
}
|
||||
}
|
||||
|
||||
return this.connector;
|
||||
}
|
||||
|
||||
/**
|
||||
* connect to wallet with QR code
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* rainbow.connectWithQrCode({
|
||||
* chainId: 1,
|
||||
* onQrCodeUri(qrCodeUri) {
|
||||
* // render the QR code with `qrCodeUri`
|
||||
* },
|
||||
* onConnected(accountAddress) {
|
||||
* // update UI to show connected state
|
||||
* },
|
||||
* })
|
||||
* ```
|
||||
*/
|
||||
async connectWithQrCode(options: ConnectWithQrCodeArgs) {
|
||||
await this.getConnector();
|
||||
const wcConnector = this.walletConnectConnector;
|
||||
|
||||
if (!wcConnector) {
|
||||
throw new Error("WalletConnect connector not found");
|
||||
}
|
||||
|
||||
const wcProvider = await wcConnector.getProvider();
|
||||
|
||||
// set a listener for display_uri event
|
||||
wcProvider.on("display_uri", (uri) => {
|
||||
options.onQrCodeUri(uri);
|
||||
});
|
||||
|
||||
// trigger connect flow
|
||||
this.connect({ chainId: options.chainId }).then(options.onConnected);
|
||||
}
|
||||
|
||||
async switchAccount() {
|
||||
if (!this.rainbowConnector) {
|
||||
throw new Error("Can not switch Account");
|
||||
}
|
||||
|
||||
await this.rainbowConnector.switchAccount();
|
||||
}
|
||||
}
|
||||
Generated
+62
-72
@@ -239,6 +239,9 @@ importers:
|
||||
'@iarna/toml':
|
||||
specifier: ^2.2.5
|
||||
version: 2.2.5
|
||||
'@thirdweb-dev/auth':
|
||||
specifier: workspace:*
|
||||
version: link:../auth
|
||||
'@thirdweb-dev/chains':
|
||||
specifier: workspace:*
|
||||
version: link:../chains
|
||||
@@ -248,6 +251,9 @@ importers:
|
||||
'@thirdweb-dev/storage':
|
||||
specifier: workspace:*
|
||||
version: link:../storage
|
||||
'@thirdweb-dev/wallets':
|
||||
specifier: workspace:*
|
||||
version: link:../wallets
|
||||
async-retry:
|
||||
specifier: ^1.3.3
|
||||
version: 1.3.3
|
||||
@@ -287,9 +293,6 @@ importers:
|
||||
solc:
|
||||
specifier: 0.8.17
|
||||
version: 0.8.17
|
||||
sync-disk-cache:
|
||||
specifier: ^2.1.0
|
||||
version: 2.1.0
|
||||
tar:
|
||||
specifier: ^6.1.15
|
||||
version: 6.1.15
|
||||
@@ -299,6 +302,9 @@ importers:
|
||||
validate-npm-package-name:
|
||||
specifier: ^4.0.0
|
||||
version: 4.0.0
|
||||
xdg-app-paths:
|
||||
specifier: ^8.3.0
|
||||
version: 8.3.0
|
||||
yaml:
|
||||
specifier: ^2.3.1
|
||||
version: 2.3.1
|
||||
@@ -1585,7 +1591,7 @@ packages:
|
||||
'@account-abstraction/contracts': 0.5.0
|
||||
'@ethersproject/abi': 5.7.0
|
||||
'@ethersproject/providers': 5.7.2
|
||||
'@openzeppelin/contracts': 4.8.3
|
||||
'@openzeppelin/contracts': 4.9.3
|
||||
debug: 4.3.4([email protected])
|
||||
ethers: 5.7.2
|
||||
transitivePeerDependencies:
|
||||
@@ -2308,13 +2314,6 @@ packages:
|
||||
dependencies:
|
||||
'@babel/types': 7.22.5
|
||||
|
||||
/@babel/[email protected]:
|
||||
resolution: {integrity: sha512-thqK5QFghPKWLhAV321lxF95yCg2K3Ob5yw+M3VHWfdia0IkPXUtoLH8x/6Fh486QUvzhb8YOWHChTVen2/PoQ==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
dependencies:
|
||||
'@babel/types': 7.22.5
|
||||
dev: false
|
||||
|
||||
/@babel/[email protected]:
|
||||
resolution: {integrity: sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
@@ -3599,7 +3598,7 @@ packages:
|
||||
'@babel/helper-environment-visitor': 7.22.5
|
||||
'@babel/helper-function-name': 7.22.5
|
||||
'@babel/helper-hoist-variables': 7.22.5
|
||||
'@babel/helper-split-export-declaration': 7.22.5
|
||||
'@babel/helper-split-export-declaration': 7.22.6
|
||||
'@babel/parser': 7.22.7
|
||||
'@babel/types': 7.22.5
|
||||
debug: 4.3.4([email protected])
|
||||
@@ -3786,7 +3785,7 @@ packages:
|
||||
outdent: 0.5.0
|
||||
prettier: 2.8.8
|
||||
resolve-from: 5.0.0
|
||||
semver: 7.5.3
|
||||
semver: 7.5.4
|
||||
dev: false
|
||||
|
||||
/@changesets/[email protected]:
|
||||
@@ -3797,7 +3796,7 @@ packages:
|
||||
'@changesets/get-dependents-graph': 1.3.6
|
||||
'@changesets/types': 5.2.1
|
||||
'@manypkg/get-packages': 1.1.3
|
||||
semver: 7.5.3
|
||||
semver: 7.5.4
|
||||
dev: false
|
||||
|
||||
/@changesets/[email protected]:
|
||||
@@ -6125,7 +6124,7 @@ packages:
|
||||
'@magic-sdk/provider': 17.4.0([email protected])
|
||||
'@magic-sdk/types': 15.6.0
|
||||
'@react-native-async-storage/async-storage': 1.18.2([email protected])
|
||||
'@types/lodash': 4.14.194
|
||||
'@types/lodash': 4.14.195
|
||||
buffer: 5.6.1
|
||||
localforage: 1.10.0
|
||||
localforage-driver-memory: 1.0.5([email protected])
|
||||
@@ -7180,10 +7179,6 @@ packages:
|
||||
resolution: {integrity: sha512-z0zMCjyhhp4y7XKAcDAi3Vgms4T2PstwBdahiO0+9NaGICQKjynK3wduSRplTgk4LXmoO1yfDGO5RbjKYxtuxA==}
|
||||
dev: false
|
||||
|
||||
/@openzeppelin/[email protected]:
|
||||
resolution: {integrity: sha512-bQHV8R9Me8IaJoJ2vPG4rXcL7seB7YVuskr4f+f5RyOStSZetwzkWtoqDMl5erkBJy0lDRUnIR2WIkPiC0GJlg==}
|
||||
dev: false
|
||||
|
||||
/@openzeppelin/[email protected]:
|
||||
resolution: {integrity: sha512-He3LieZ1pP2TNt5JbkPA4PNT9WC3gOTOlDcFGJW4Le4QKqwmiNJCRt44APfxMxvq7OugU/cqYuPcSBzOw38DAg==}
|
||||
dev: false
|
||||
@@ -10837,8 +10832,8 @@ packages:
|
||||
'@types/node': 18.17.1
|
||||
dev: true
|
||||
|
||||
/@types/[email protected]4:
|
||||
resolution: {integrity: sha512-r22s9tAS7imvBt2lyHC9B8AGwWnXaYb1tY09oyLkXDs4vArpYJzw09nj8MLx5VfciBPGIb+ZwG0ssYnEPJxn/g==}
|
||||
/@types/[email protected]5:
|
||||
resolution: {integrity: sha512-Hwx9EUgdwf2GLarOjQp5ZH8ZmblzcbTBC2wtQWNKARBSxM9ezRIAUpeDTgoQRAFB0+8CNWXVA9+MaSOzOF3nPg==}
|
||||
dev: false
|
||||
|
||||
/@types/[email protected]:
|
||||
@@ -15500,9 +15495,14 @@ packages:
|
||||
engines: {node: '>=10.0.0'}
|
||||
dev: true
|
||||
|
||||
/engine.io@6.4.1:
|
||||
resolution: {integrity: sha512-JFYQurD/nbsA5BSPmbaOSLa3tSVj8L6o4srSwXXY3NqE+gGUNmmPTbhn8tjzcCtSqhFgIeqef81ngny8JM25hw==}
|
||||
/engine.io[email protected].1:
|
||||
resolution: {integrity: sha512-9JktcM3u18nU9N2Lz3bWeBgxVgOKpw7yhRaoxQA3FUDZzzw+9WlA6p4G4u0RixNkg14fH7EfEc/RhpurtiROTQ==}
|
||||
engines: {node: '>=10.0.0'}
|
||||
dev: true
|
||||
|
||||
/[email protected]:
|
||||
resolution: {integrity: sha512-IXsMcGpw/xRfjra46sVZVHiSWo/nJ/3g1337q9KNXtS6YRzbW5yIzTCb9DjhrBe7r3GZQR0I4+nq+4ODk5g/cA==}
|
||||
engines: {node: '>=10.2.0'}
|
||||
dependencies:
|
||||
'@types/cookie': 0.4.1
|
||||
'@types/cors': 2.8.13
|
||||
@@ -15512,7 +15512,7 @@ packages:
|
||||
cookie: 0.4.2
|
||||
cors: 2.8.5
|
||||
debug: 4.3.4([email protected])
|
||||
engine.io-parser: 5.0.6
|
||||
engine.io-parser: 5.2.1
|
||||
ws: 8.11.0
|
||||
transitivePeerDependencies:
|
||||
- bufferutil
|
||||
@@ -16223,7 +16223,7 @@ packages:
|
||||
minimatch: 3.1.2
|
||||
object.values: 1.1.6
|
||||
resolve: 1.22.1
|
||||
semver: 7.5.3
|
||||
semver: 7.5.4
|
||||
tsconfig-paths: 3.14.2
|
||||
transitivePeerDependencies:
|
||||
- eslint-import-resolver-typescript
|
||||
@@ -18251,12 +18251,6 @@ packages:
|
||||
tslib: 2.5.0
|
||||
dev: true
|
||||
|
||||
/[email protected]:
|
||||
resolution: {integrity: sha512-o9bd30+5vLBvBtzCPwwGqpry2+n0Hi6H1+qwt6y+0kwRHGGF8TFIhJPmnuM0xO97zaKrDZMwO/V56fAnn8m/tA==}
|
||||
dependencies:
|
||||
rsvp: 3.2.1
|
||||
dev: false
|
||||
|
||||
/[email protected]:
|
||||
resolution: {integrity: sha512-W6JDAOLZ5pMPMjEiQGLCXSSV7pIBEgRR5zGkxgmzGSXHOxqV5dC/M1Zevqpbm9TZDE5tu358qZf8Vkzmsc+u7Q==}
|
||||
|
||||
@@ -20458,7 +20452,7 @@ packages:
|
||||
parse5: 6.0.1
|
||||
saxes: 5.0.1
|
||||
symbol-tree: 3.2.4
|
||||
tough-cookie: 4.1.2
|
||||
tough-cookie: 4.1.3
|
||||
w3c-hr-time: 1.0.2
|
||||
w3c-xmlserializer: 2.0.0
|
||||
webidl-conversions: 6.1.0
|
||||
@@ -22685,6 +22679,13 @@ packages:
|
||||
resolution: {integrity: sha512-B5JU3cabzk8c67mRRd3ECmROafjYMXbuzlwtqdM8IbS8ktlTix8aFGb2bAGKrSRIlnfKwovGUUr72JUPyOb6kQ==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
/[email protected]:
|
||||
resolution: {integrity: sha512-Ux1J4NUqC6tZayBqLN1kUlDAEvLiQlli/53sSddU4IN+h+3xxnv2HmRSMpVSvr1hvJzotfMs3ERvETGK+f4OwA==}
|
||||
engines: {node: '>= 4.0'}
|
||||
optionalDependencies:
|
||||
fsevents: 2.3.2
|
||||
dev: false
|
||||
|
||||
/[email protected]:
|
||||
resolution: {integrity: sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
@@ -22816,7 +22817,7 @@ packages:
|
||||
got: 11.8.5
|
||||
registry-auth-token: 4.2.2
|
||||
registry-url: 5.1.0
|
||||
semver: 7.5.3
|
||||
semver: 7.5.4
|
||||
dev: false
|
||||
|
||||
/[email protected]:
|
||||
@@ -24772,7 +24773,7 @@ packages:
|
||||
resolve: 1.22.1
|
||||
resolve-url-loader: 4.0.0
|
||||
sass-loader: 12.6.0([email protected])
|
||||
semver: 7.3.8
|
||||
semver: 7.5.4
|
||||
source-map-loader: 3.0.2([email protected])
|
||||
style-loader: 3.3.2([email protected])
|
||||
tailwindcss: 3.2.7([email protected])
|
||||
@@ -25337,10 +25338,6 @@ packages:
|
||||
bufferutil: 4.0.7
|
||||
utf-8-validate: 5.0.10
|
||||
|
||||
/[email protected]:
|
||||
resolution: {integrity: sha512-Rf4YVNYpKjZ6ASAmibcwTNciQ5Co5Ztq6iZPEykHpkoflnD/K5ryE/rHehFsTm4NJj8nKDhbi3eKBWGogmNnkg==}
|
||||
dev: false
|
||||
|
||||
/[email protected]:
|
||||
resolution: {integrity: sha512-C6DxhXt7bssQ1nHb154lqeL0SXz5Dx4RczXZu2Aa/L1NJFnEVDxFwCBo3fqtuljhHIGceg5JKBV4XJ0gW5JKyw==}
|
||||
engines: {node: '>=6.0.0', npm: '>=3.10.0'}
|
||||
@@ -25549,7 +25546,7 @@ packages:
|
||||
resolution: {integrity: sha512-Ij1vCAdFgWABd7zTg50Xw1/p0JgESNxuLlneEAsmBrKishA06ulTTL/SHGmNy2Zud7+rKrHTKNI6moJsn1ppAQ==}
|
||||
dependencies:
|
||||
'@types/semver': 6.2.3
|
||||
semver: 7.5.3
|
||||
semver: 7.5.4
|
||||
dev: false
|
||||
|
||||
/[email protected]:
|
||||
@@ -25559,14 +25556,6 @@ packages:
|
||||
semver: 7.5.4
|
||||
dev: false
|
||||
|
||||
/[email protected]:
|
||||
resolution: {integrity: sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==}
|
||||
engines: {node: '>=10'}
|
||||
hasBin: true
|
||||
dependencies:
|
||||
lru-cache: 6.0.0
|
||||
dev: false
|
||||
|
||||
/[email protected]:
|
||||
resolution: {integrity: sha512-QBlUtyVk/5EeHbi7X0fw6liDZc7BBmEaSYn01fMU1OUYbf6GPsbTtd8WmnqbI20SeycoHSeiybkE/q1Q+qlThQ==}
|
||||
engines: {node: '>=10'}
|
||||
@@ -25870,15 +25859,15 @@ packages:
|
||||
'@socket.io/component-emitter': 3.1.0
|
||||
debug: 4.3.4([email protected])
|
||||
engine.io-client: 6.4.0
|
||||
socket.io-parser: 4.2.2
|
||||
socket.io-parser: 4.2.4
|
||||
transitivePeerDependencies:
|
||||
- bufferutil
|
||||
- supports-color
|
||||
- utf-8-validate
|
||||
dev: true
|
||||
|
||||
/[email protected].2:
|
||||
resolution: {integrity: sha512-DJtziuKypFkMMHCm2uIshOYC7QaylbtzQwiMYDuCKy3OPkjLzu4B2vAhTlqipRHHzrI0NJeBAizTK7X+6m1jVw==}
|
||||
/[email protected].4:
|
||||
resolution: {integrity: sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==}
|
||||
engines: {node: '>=10.0.0'}
|
||||
dependencies:
|
||||
'@socket.io/component-emitter': 3.1.0
|
||||
@@ -25894,9 +25883,9 @@ packages:
|
||||
accepts: 1.3.8
|
||||
base64id: 2.0.0
|
||||
debug: 4.3.4([email protected])
|
||||
engine.io: 6.4.1
|
||||
engine.io: 6.5.2
|
||||
socket.io-adapter: 2.5.2
|
||||
socket.io-parser: 4.2.2
|
||||
socket.io-parser: 4.2.4
|
||||
transitivePeerDependencies:
|
||||
- bufferutil
|
||||
- supports-color
|
||||
@@ -26578,19 +26567,6 @@ packages:
|
||||
resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==}
|
||||
dev: false
|
||||
|
||||
/[email protected]:
|
||||
resolution: {integrity: sha512-vngT2JmkSapgq0z7uIoYtB9kWOOzMihAAYq/D3Pjm/ODOGMgS4r++B+OZ09U4hWR6EaOdy9eqQ7/8ygbH3wehA==}
|
||||
engines: {node: 8.* || >= 10.*}
|
||||
dependencies:
|
||||
debug: 4.3.4([email protected])
|
||||
heimdalljs: 0.2.6
|
||||
mkdirp: 0.5.6
|
||||
rimraf: 3.0.2
|
||||
username-sync: 1.0.3
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: false
|
||||
|
||||
/[email protected]:
|
||||
resolution: {integrity: sha512-L1dapNV6vu2s/4Sputv8xGsCdAVlb5nRDMFU/E27D44l5U6cw1g0dGd45uLc+OXjNMmF4ntiMdCimzcjFKQI8Q==}
|
||||
engines: {node: ^14.18.0 || >=16.0.0}
|
||||
@@ -26912,8 +26888,8 @@ packages:
|
||||
resolution: {integrity: sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w==}
|
||||
dev: true
|
||||
|
||||
/[email protected].2:
|
||||
resolution: {integrity: sha512-G9fqXWoYFZgTc2z8Q5zaHy/vJMjm+WV0AkAeHxVCQiEB1b+dGvWzFW6QV07cY5jQ5gRkeid2qIkzkxUnmoQZUQ==}
|
||||
/[email protected].3:
|
||||
resolution: {integrity: sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw==}
|
||||
engines: {node: '>=6'}
|
||||
dependencies:
|
||||
psl: 1.9.0
|
||||
@@ -27557,7 +27533,7 @@ packages:
|
||||
is-yarn-global: 0.4.1
|
||||
latest-version: 7.0.0
|
||||
pupa: 3.1.0
|
||||
semver: 7.3.8
|
||||
semver: 7.5.4
|
||||
semver-diff: 4.0.0
|
||||
xdg-basedir: 5.1.0
|
||||
dev: false
|
||||
@@ -27652,10 +27628,6 @@ packages:
|
||||
resolution: {integrity: sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
/[email protected]:
|
||||
resolution: {integrity: sha512-m/7/FSqjJNAzF2La448c/aEom0gJy7HY7Y509h6l0ePvEkFictAGptwWaj1msWJ38JbfEDOUoE8kqFee9EHKdA==}
|
||||
dev: false
|
||||
|
||||
/[email protected]:
|
||||
resolution: {integrity: sha512-Z6czzLq4u8fPOyx7TU6X3dvUZVvoJmxSQ+IcrlmagKhilxlhZgxPK6C5Jqbkw1IDUmFTM+cz9QDnnLTwDz/2gQ==}
|
||||
engines: {node: '>=6.14.2'}
|
||||
@@ -28791,11 +28763,29 @@ packages:
|
||||
simple-plist: 1.3.1
|
||||
uuid: 7.0.3
|
||||
|
||||
/[email protected]:
|
||||
resolution: {integrity: sha512-mgxlWVZw0TNWHoGmXq+NC3uhCIc55dDpAlDkMQUaIAcQzysb0kxctwv//fvuW61/nAAeUBJMQ8mnZjMmuYwOcQ==}
|
||||
engines: {node: '>= 4.0'}
|
||||
dependencies:
|
||||
xdg-portable: 10.6.0
|
||||
optionalDependencies:
|
||||
fsevents: 2.3.2
|
||||
dev: false
|
||||
|
||||
/[email protected]:
|
||||
resolution: {integrity: sha512-GCPAHLvrIH13+c0SuacwvRYj2SxJXQ4kaVTT5xgL3kPrz56XxkF21IGhjSE1+W0aw7gpBWRGXLCPnPby6lSpmQ==}
|
||||
engines: {node: '>=12'}
|
||||
dev: false
|
||||
|
||||
/[email protected]:
|
||||
resolution: {integrity: sha512-xrcqhWDvtZ7WLmt8G4f3hHy37iK7D2idtosRgkeiSPZEPmBShp0VfmRBLWAPC6zLF48APJ21yfea+RfQMF4/Aw==}
|
||||
engines: {node: '>= 4.0'}
|
||||
dependencies:
|
||||
os-paths: 7.4.0
|
||||
optionalDependencies:
|
||||
fsevents: 2.3.2
|
||||
dev: false
|
||||
|
||||
/[email protected]:
|
||||
resolution: {integrity: sha512-YUBytBsuwgitWtdRzXDDkWAXzhdGB8bYm0sSzMPZT7Z2MBjMSTHFsyCT1yCRATY+XC69DUrQraRAEgcoCRaIPg==}
|
||||
dependencies:
|
||||
|
||||
Reference in New Issue
Block a user