Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f202f597ca | ||
|
|
91f0245be7 | ||
|
|
ae74b8ef62 | ||
|
|
5a373a7509 | ||
|
|
088547f763 | ||
|
|
586e91dbe6 | ||
|
|
f65578d637 | ||
|
|
447d984653 | ||
|
|
34a3bb8ae3 | ||
|
|
bc003c2fef | ||
|
|
c88fa57591 | ||
|
|
c12f0874b4 | ||
|
|
184c325ab2 | ||
|
|
046c9ad604 | ||
|
|
2a7bbf8665 | ||
|
|
f97ddf4c7f | ||
|
|
66c53360cd | ||
|
|
bd1fcbae32 | ||
|
|
e196264172 |
@@ -1,5 +1,33 @@
|
||||
# @thirdweb-dev/auth
|
||||
|
||||
## 3.2.36
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies []:
|
||||
- @thirdweb-dev/wallets@1.1.19
|
||||
|
||||
## 3.2.35
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies []:
|
||||
- @thirdweb-dev/wallets@1.1.18
|
||||
|
||||
## 3.2.34
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies []:
|
||||
- @thirdweb-dev/wallets@1.1.17
|
||||
|
||||
## 3.2.33
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies []:
|
||||
- @thirdweb-dev/wallets@1.1.16
|
||||
|
||||
## 3.2.32
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@thirdweb-dev/auth",
|
||||
"version": "3.2.32",
|
||||
"version": "3.2.36",
|
||||
"main": "dist/thirdweb-dev-auth.cjs.js",
|
||||
"module": "dist/thirdweb-dev-auth.esm.js",
|
||||
"browser": {
|
||||
|
||||
@@ -1,5 +1,25 @@
|
||||
# @thirdweb-dev/chains
|
||||
|
||||
## 0.1.47
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#1518](https://github.com/thirdweb-dev/js/pull/1518) [`34a3bb8a`](https://github.com/thirdweb-dev/js/commit/34a3bb8ae3c1d7a506e5568a9e79ab7e469557a8) Thanks [@nkrishang](https://github.com/nkrishang)! - Update contracts package
|
||||
|
||||
## 0.1.46
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#1508](https://github.com/thirdweb-dev/js/pull/1508) [`184c325a`](https://github.com/thirdweb-dev/js/commit/184c325ab2ef028022a050c4274f2ab12b1a3a7f) Thanks [@jnsdls](https://github.com/jnsdls)! - update xpla chain icons
|
||||
|
||||
- [#1513](https://github.com/thirdweb-dev/js/pull/1513) [`c12f0874`](https://github.com/thirdweb-dev/js/commit/c12f0874b4dac43c263c7edb20d0343c16381c34) Thanks [@jnsdls](https://github.com/jnsdls)! - add additonal chains
|
||||
|
||||
## 0.1.45
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#1506](https://github.com/thirdweb-dev/js/pull/1506) [`f97ddf4c`](https://github.com/thirdweb-dev/js/commit/f97ddf4c7f14854f3b204ad9741b52ddb8dac736) Thanks [@jnsdls](https://github.com/jnsdls)! - add xpla chains & update chains
|
||||
|
||||
## 0.1.44
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -18,6 +18,7 @@ export default {
|
||||
"https://gnosis.api.onfinality.io/public",
|
||||
"https://gnosis.blockpi.network/v1/rpc/public",
|
||||
"https://web3endpoints.com/gnosischain-mainnet",
|
||||
"https://gnosis.oat.farm",
|
||||
"wss://rpc.gnosischain.com/wss"
|
||||
],
|
||||
"faucets": [
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
import type { Chain } from "../src/types";
|
||||
export default {
|
||||
"name": "Arthera Testnet",
|
||||
"chain": "AA",
|
||||
"icon": {
|
||||
"url": "ipfs://QmYQp3e52KjkT4bYdAvB6ACEEpXs2D8DozsDitaADRY2Ak",
|
||||
"width": 1024,
|
||||
"height": 998,
|
||||
"format": "png"
|
||||
},
|
||||
"rpc": [
|
||||
"https://arthera-testnet.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
|
||||
"https://rpc-test.arthera.net"
|
||||
],
|
||||
"faucets": [
|
||||
"https://faucet.arthera.net"
|
||||
],
|
||||
"nativeCurrency": {
|
||||
"name": "Arthera",
|
||||
"symbol": "AA",
|
||||
"decimals": 18
|
||||
},
|
||||
"infoURL": "https://docs.arthera.net",
|
||||
"shortName": "aa",
|
||||
"chainId": 10243,
|
||||
"networkId": 10243,
|
||||
"explorers": [
|
||||
{
|
||||
"name": "blockscout",
|
||||
"url": "https://explorer-test.arthera.net",
|
||||
"icon": {
|
||||
"url": "ipfs://QmYtUimyqHkkFxYdbXXRbUqNg2VLPUg6Uu2C2nmFWowiZM",
|
||||
"width": 551,
|
||||
"height": 540,
|
||||
"format": "png"
|
||||
},
|
||||
"standard": "EIP3091"
|
||||
}
|
||||
],
|
||||
"testnet": true,
|
||||
"slug": "arthera-testnet"
|
||||
} as const satisfies Chain;
|
||||
@@ -10,8 +10,8 @@ export default {
|
||||
"https://t.me/HumanodeTestnet5FaucetBot"
|
||||
],
|
||||
"nativeCurrency": {
|
||||
"name": "HMND",
|
||||
"symbol": "HMND",
|
||||
"name": "eHMND",
|
||||
"symbol": "eHMND",
|
||||
"decimals": 18
|
||||
},
|
||||
"infoURL": "https://humanode.io",
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
import type { Chain } from "../src/types";
|
||||
export default {
|
||||
"name": "Centrifuge",
|
||||
"chain": "CFG",
|
||||
"rpc": [
|
||||
"wss://fullnode.parachain.centrifuge.io"
|
||||
],
|
||||
"features": [
|
||||
{
|
||||
"name": "EIP155"
|
||||
},
|
||||
{
|
||||
"name": "EIP1559"
|
||||
}
|
||||
],
|
||||
"faucets": [],
|
||||
"nativeCurrency": {
|
||||
"name": "Centrifuge",
|
||||
"symbol": "CFG",
|
||||
"decimals": 18
|
||||
},
|
||||
"infoURL": "https://centrifuge.io",
|
||||
"shortName": "cfg",
|
||||
"chainId": 2031,
|
||||
"networkId": 2031,
|
||||
"explorers": [
|
||||
{
|
||||
"name": "subscan",
|
||||
"url": "https://centrifuge.subscan.io",
|
||||
"standard": "EIP3091"
|
||||
}
|
||||
],
|
||||
"testnet": false,
|
||||
"slug": "centrifuge"
|
||||
} as const satisfies Chain;
|
||||
@@ -0,0 +1,28 @@
|
||||
import type { Chain } from "../src/types";
|
||||
export default {
|
||||
"name": "Catalyst",
|
||||
"chain": "CFG",
|
||||
"rpc": [
|
||||
"wss://fullnode.catalyst.cntrfg.com"
|
||||
],
|
||||
"features": [
|
||||
{
|
||||
"name": "EIP155"
|
||||
},
|
||||
{
|
||||
"name": "EIP1559"
|
||||
}
|
||||
],
|
||||
"faucets": [],
|
||||
"nativeCurrency": {
|
||||
"name": "Catalyst CFG",
|
||||
"symbol": "NCFG",
|
||||
"decimals": 18
|
||||
},
|
||||
"infoURL": "https://centrifuge.io",
|
||||
"shortName": "ncfg",
|
||||
"chainId": 2032,
|
||||
"networkId": 2032,
|
||||
"testnet": false,
|
||||
"slug": "catalyst"
|
||||
} as const satisfies Chain;
|
||||
@@ -0,0 +1,33 @@
|
||||
import type { Chain } from "../src/types";
|
||||
export default {
|
||||
"name": "Kiwi Subnet",
|
||||
"chain": "KIWI",
|
||||
"rpc": [
|
||||
"https://kiwi-subnet.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
|
||||
"https://subnets.avax.network/kiwi/testnet/rpc"
|
||||
],
|
||||
"features": [
|
||||
{
|
||||
"name": "EIP1559"
|
||||
}
|
||||
],
|
||||
"faucets": [],
|
||||
"nativeCurrency": {
|
||||
"name": "Shrapgas",
|
||||
"symbol": "SHRAP",
|
||||
"decimals": 18
|
||||
},
|
||||
"infoURL": "",
|
||||
"shortName": "kiwi",
|
||||
"chainId": 2037,
|
||||
"networkId": 2037,
|
||||
"explorers": [
|
||||
{
|
||||
"name": "KIWI Explorer",
|
||||
"url": "https://subnets-test.avax.network/kiwi",
|
||||
"standard": "EIP3091"
|
||||
}
|
||||
],
|
||||
"testnet": true,
|
||||
"slug": "kiwi-subnet"
|
||||
} as const satisfies Chain;
|
||||
@@ -0,0 +1,28 @@
|
||||
import type { Chain } from "../src/types";
|
||||
export default {
|
||||
"name": "Altair",
|
||||
"chain": "AIR",
|
||||
"rpc": [
|
||||
"wss://fullnode.altair.centrifuge.io"
|
||||
],
|
||||
"features": [
|
||||
{
|
||||
"name": "EIP155"
|
||||
},
|
||||
{
|
||||
"name": "EIP1559"
|
||||
}
|
||||
],
|
||||
"faucets": [],
|
||||
"nativeCurrency": {
|
||||
"name": "Altair",
|
||||
"symbol": "AIR",
|
||||
"decimals": 18
|
||||
},
|
||||
"infoURL": "https://centrifuge.io",
|
||||
"shortName": "air",
|
||||
"chainId": 2088,
|
||||
"networkId": 2088,
|
||||
"testnet": false,
|
||||
"slug": "altair"
|
||||
} as const satisfies Chain;
|
||||
@@ -0,0 +1,28 @@
|
||||
import type { Chain } from "../src/types";
|
||||
export default {
|
||||
"name": "Algol",
|
||||
"chain": "algol",
|
||||
"rpc": [
|
||||
"wss://fullnode.algol.cntrfg.com"
|
||||
],
|
||||
"features": [
|
||||
{
|
||||
"name": "EIP155"
|
||||
},
|
||||
{
|
||||
"name": "EIP1559"
|
||||
}
|
||||
],
|
||||
"faucets": [],
|
||||
"nativeCurrency": {
|
||||
"name": "Algol",
|
||||
"symbol": "ALGL",
|
||||
"decimals": 18
|
||||
},
|
||||
"infoURL": "https://centrifuge.io",
|
||||
"shortName": "algl",
|
||||
"chainId": 2089,
|
||||
"networkId": 2089,
|
||||
"testnet": false,
|
||||
"slug": "algol"
|
||||
} as const satisfies Chain;
|
||||
@@ -1,10 +1,11 @@
|
||||
import type { Chain } from "../src/types";
|
||||
export default {
|
||||
"name": "Kava EVM Testnet",
|
||||
"name": "Kava Testnet",
|
||||
"chain": "KAVA",
|
||||
"rpc": [
|
||||
"https://kava-evm-testnet.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
|
||||
"https://kava-testnet.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
|
||||
"https://evm.testnet.kava.io",
|
||||
"https://kava-evm-testnet.rpc.thirdweb.com",
|
||||
"wss://wevm.testnet.kava.io"
|
||||
],
|
||||
"faucets": [
|
||||
@@ -28,7 +29,7 @@ export default {
|
||||
"explorers": [
|
||||
{
|
||||
"name": "Kava Testnet Explorer",
|
||||
"url": "https://explorer.testnet.kava.io",
|
||||
"url": "http://testnet.kavascan.com",
|
||||
"standard": "EIP3091",
|
||||
"icon": {
|
||||
"url": "ipfs://QmdpRTk6oL1HRW9xC6cAc4Rnf9gs6zgdAcr4Z3HcLztusm",
|
||||
@@ -39,5 +40,5 @@ export default {
|
||||
}
|
||||
],
|
||||
"testnet": true,
|
||||
"slug": "kava-evm-testnet"
|
||||
"slug": "kava-testnet"
|
||||
} as const satisfies Chain;
|
||||
@@ -1,11 +1,13 @@
|
||||
import type { Chain } from "../src/types";
|
||||
export default {
|
||||
"name": "Kava EVM",
|
||||
"name": "Kava",
|
||||
"chain": "KAVA",
|
||||
"rpc": [
|
||||
"https://kava-evm.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
|
||||
"https://kava.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
|
||||
"https://evm.kava.io",
|
||||
"https://evm2.kava.io",
|
||||
"https://kava-rpc.gateway.pokt.network",
|
||||
"https://kava-evm.rpc.thirdweb.com",
|
||||
"wss://wevm.kava.io",
|
||||
"wss://wevm2.kava.io",
|
||||
"https://kava-evm.publicnode.com"
|
||||
@@ -29,7 +31,7 @@ export default {
|
||||
"explorers": [
|
||||
{
|
||||
"name": "Kava EVM Explorer",
|
||||
"url": "https://explorer.kava.io",
|
||||
"url": "https://kavascan.com",
|
||||
"standard": "EIP3091",
|
||||
"icon": {
|
||||
"url": "ipfs://QmdpRTk6oL1HRW9xC6cAc4Rnf9gs6zgdAcr4Z3HcLztusm",
|
||||
@@ -40,5 +42,5 @@ export default {
|
||||
}
|
||||
],
|
||||
"testnet": false,
|
||||
"slug": "kava-evm"
|
||||
"slug": "kava"
|
||||
} as const satisfies Chain;
|
||||
@@ -4,7 +4,11 @@ export default {
|
||||
"chain": "SOMA",
|
||||
"rpc": [
|
||||
"https://soma-network-testnet.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
|
||||
"https://data-testnet-v1.somanetwork.io/"
|
||||
"https://data-testnet-v1.somanetwork.io/",
|
||||
"https://testnet-au-server-2.somanetwork.io",
|
||||
"https://testnet-au-server-1.somanetwork.io",
|
||||
"https://testnet-sg-server-1.somanetwork.io",
|
||||
"https://testnet-sg-server-2.somanetwork.io"
|
||||
],
|
||||
"faucets": [
|
||||
"https://faucet.somanetwork.io"
|
||||
|
||||
@@ -4,7 +4,10 @@ export default {
|
||||
"chain": "SOMA",
|
||||
"rpc": [
|
||||
"https://soma-network.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
|
||||
"https://data-mainnet-v1.somanetwork.io/"
|
||||
"https://data-mainnet-v1.somanetwork.io/",
|
||||
"https://id-mainnet.somanetwork.io",
|
||||
"https://hk-mainnet.somanetwork.io",
|
||||
"https://sg-mainnet.somanetwork.io"
|
||||
],
|
||||
"faucets": [
|
||||
"https://airdrop.somanetwork.io"
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
import type { Chain } from "../src/types";
|
||||
export default {
|
||||
"name": "Ancient8 Testnet",
|
||||
"chain": "Ancient8",
|
||||
"icon": {
|
||||
"url": "ipfs://QmSX8sHToRzyFupT8BvPQjVsegRWFYz2mdnLkVnqBFKohY",
|
||||
"width": 901,
|
||||
"height": 901,
|
||||
"format": "png"
|
||||
},
|
||||
"rpc": [
|
||||
"https://ancient8-testnet.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
|
||||
"https://rpc-testnet.ancient8.gg"
|
||||
],
|
||||
"faucets": [],
|
||||
"nativeCurrency": {
|
||||
"name": "Ether",
|
||||
"symbol": "ETH",
|
||||
"decimals": 18
|
||||
},
|
||||
"infoURL": "https://ancient8.gg/",
|
||||
"shortName": "a8",
|
||||
"chainId": 2863311531,
|
||||
"networkId": 2863311531,
|
||||
"explorers": [
|
||||
{
|
||||
"name": "a8scan-testnet",
|
||||
"url": "https://testnet.a8scan.io",
|
||||
"standard": "EIP3091"
|
||||
}
|
||||
],
|
||||
"testnet": true,
|
||||
"slug": "ancient8-testnet"
|
||||
} as const satisfies Chain;
|
||||
@@ -5,6 +5,12 @@ export default {
|
||||
"shortName": "POPTestnet",
|
||||
"chainId": 331769,
|
||||
"testnet": true,
|
||||
"icon": {
|
||||
"format": "png",
|
||||
"url": "ipfs://QmP8rYvcc7aJB3c2YZxjxaySvHapHnoK8MnxuSuDT4PtF2",
|
||||
"height": 400,
|
||||
"width": 400
|
||||
},
|
||||
"rpc": [
|
||||
"https://proofofpepe-testnet.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
|
||||
"https://testnet01.proofofpepe.tech"
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
import type { Chain } from "../src/types";
|
||||
export default {
|
||||
"name": "POP Mainnet",
|
||||
"chain": "POP",
|
||||
"shortName": "POP",
|
||||
"chainId": 331771,
|
||||
"testnet": false,
|
||||
"icon": {
|
||||
"format": "png",
|
||||
"url": "ipfs://QmP8rYvcc7aJB3c2YZxjxaySvHapHnoK8MnxuSuDT4PtF2",
|
||||
"height": 400,
|
||||
"width": 400
|
||||
},
|
||||
"rpc": [
|
||||
"https://pop.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
|
||||
"https://rpc00.proofofpepe.tech",
|
||||
"https://rpc01.proofofpepe.tech",
|
||||
"https://rpc02.proofofpepe.tech"
|
||||
],
|
||||
"nativeCurrency": {
|
||||
"name": "Pepe",
|
||||
"symbol": "PEPE",
|
||||
"decimals": 18
|
||||
},
|
||||
"explorers": [
|
||||
{
|
||||
"name": "Pepescan",
|
||||
"url": "https://pepescan.app",
|
||||
"standard": "none"
|
||||
}
|
||||
],
|
||||
"slug": "pop"
|
||||
} as const satisfies Chain;
|
||||
@@ -0,0 +1,38 @@
|
||||
import type { Chain } from "../src/types";
|
||||
export default {
|
||||
"name": "Yooldo Verse Mainnet",
|
||||
"chain": "Yooldo Verse",
|
||||
"icon": {
|
||||
"url": "ipfs://QmWvfA2usnYp1ktzLcqFS8eTLgdp4ifrxjiify46KyG9NZ",
|
||||
"width": 512,
|
||||
"height": 512,
|
||||
"format": "png"
|
||||
},
|
||||
"rpc": [
|
||||
"https://yooldo-verse.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
|
||||
"https://rpc.yooldo-verse.xyz/"
|
||||
],
|
||||
"faucets": [],
|
||||
"nativeCurrency": {
|
||||
"name": "OAS",
|
||||
"symbol": "OAS",
|
||||
"decimals": 18
|
||||
},
|
||||
"infoURL": "https://yooldo.gg/",
|
||||
"shortName": "YVM",
|
||||
"chainId": 345,
|
||||
"networkId": 345,
|
||||
"explorers": [
|
||||
{
|
||||
"name": "Yooldo Verse Explorer",
|
||||
"url": "https://explorer.yooldo-verse.xyz",
|
||||
"standard": "EIP3091"
|
||||
}
|
||||
],
|
||||
"parent": {
|
||||
"type": "L2",
|
||||
"chain": "eip155-248"
|
||||
},
|
||||
"testnet": false,
|
||||
"slug": "yooldo-verse"
|
||||
} as const satisfies Chain;
|
||||
@@ -1,27 +1,35 @@
|
||||
import type { Chain } from "../src/types";
|
||||
export default {
|
||||
"name": "SeedCoin-Network",
|
||||
"chain": "SeedCoin-Network",
|
||||
"name": "Xpla Mainnet",
|
||||
"chain": "XPLA",
|
||||
"rpc": [
|
||||
"https://seedcoin-network.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
|
||||
"https://node.seedcoin.network"
|
||||
"https://xpla.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
|
||||
"https://dimension-evm-rpc.xpla.dev"
|
||||
],
|
||||
"faucets": [],
|
||||
"nativeCurrency": {
|
||||
"name": "SeedCoin",
|
||||
"symbol": "SEED",
|
||||
"name": "XPLA",
|
||||
"symbol": "XPLA",
|
||||
"decimals": 18
|
||||
},
|
||||
"infoURL": "https://www.seedcoin.network/",
|
||||
"shortName": "SEED",
|
||||
"infoURL": "https://xpla.io/",
|
||||
"shortName": "xpla",
|
||||
"chainId": 37,
|
||||
"icon": {
|
||||
"url": "ipfs://QmSchLvCCZjBzcv5n22v1oFDAc2yHJ42NERyjZeL9hBgrh",
|
||||
"width": 64,
|
||||
"height": 64,
|
||||
"url": "ipfs://QmbvEAKZfgJckEziU3mpCwz6jqMeWRcLgd8TNsWA7g8sD9/xpla.png",
|
||||
"width": 512,
|
||||
"height": 512,
|
||||
"format": "png"
|
||||
},
|
||||
"chainId": 37,
|
||||
"networkId": 37,
|
||||
"explorers": [
|
||||
{
|
||||
"name": "XPLA Explorer",
|
||||
"url": "https://explorer.xpla.io",
|
||||
"standard": "none"
|
||||
}
|
||||
],
|
||||
"testnet": false,
|
||||
"slug": "seedcoin-network"
|
||||
"redFlags": [
|
||||
"reusedChainId"
|
||||
],
|
||||
"slug": "xpla"
|
||||
} as const satisfies Chain;
|
||||
@@ -0,0 +1,43 @@
|
||||
import type { Chain } from "../src/types";
|
||||
export default {
|
||||
"name": "Alterium L2 Testnet",
|
||||
"chain": "ALT",
|
||||
"icon": {
|
||||
"url": "ipfs://bafkreid3v7ow4c4t3ljya6aouiwvqbtssb2lzmkwt2eghryk234g7yynrq",
|
||||
"width": 756,
|
||||
"height": 756,
|
||||
"format": "png"
|
||||
},
|
||||
"rpc": [
|
||||
"https://alterium-l2-testnet.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
|
||||
"https://l2-testnet-rpc.altscan.org"
|
||||
],
|
||||
"faucets": [],
|
||||
"nativeCurrency": {
|
||||
"name": "Alterium ETH",
|
||||
"symbol": "AltETH",
|
||||
"decimals": 18
|
||||
},
|
||||
"infoURL": "https://alteriumprotocol.org",
|
||||
"shortName": "alterium",
|
||||
"chainId": 420692,
|
||||
"networkId": 420692,
|
||||
"parent": {
|
||||
"type": "L2",
|
||||
"chain": "eip155-5",
|
||||
"bridges": [
|
||||
{
|
||||
"url": "https://testnet-bridge.alteriumprotocol.org"
|
||||
}
|
||||
]
|
||||
},
|
||||
"explorers": [
|
||||
{
|
||||
"name": "Alterium L2 Testnet Explorer",
|
||||
"url": "https://l2-testnet.altscan.org",
|
||||
"standard": "EIP3091"
|
||||
}
|
||||
],
|
||||
"testnet": true,
|
||||
"slug": "alterium-l2-testnet"
|
||||
} as const satisfies Chain;
|
||||
@@ -1,36 +1,38 @@
|
||||
import type { Chain } from "../src/types";
|
||||
export default {
|
||||
"name": "Acria IntelliChain",
|
||||
"chain": "AIC",
|
||||
"name": "Xpla Testnet",
|
||||
"chain": "XPLA",
|
||||
"rpc": [
|
||||
"https://acria-intellichain.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
|
||||
"https://aic.acria.ai"
|
||||
"https://xpla-testnet.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
|
||||
"https://cube-evm-rpc.xpla.dev"
|
||||
],
|
||||
"faucets": [],
|
||||
"nativeCurrency": {
|
||||
"name": "ACRIA",
|
||||
"symbol": "ACRIA",
|
||||
"name": "XPLA",
|
||||
"symbol": "XPLA",
|
||||
"decimals": 18
|
||||
},
|
||||
"features": [
|
||||
{
|
||||
"name": "EIP155"
|
||||
},
|
||||
{
|
||||
"name": "EIP1559"
|
||||
}
|
||||
"faucets": [
|
||||
"https://faucet.xpla.io/"
|
||||
],
|
||||
"infoURL": "https://acria.ai",
|
||||
"shortName": "aic",
|
||||
"infoURL": "https://xpla.io/",
|
||||
"shortName": "xpla-test",
|
||||
"chainId": 47,
|
||||
"networkId": 47,
|
||||
"icon": {
|
||||
"url": "ipfs://QmbvEAKZfgJckEziU3mpCwz6jqMeWRcLgd8TNsWA7g8sD9/xpla.png",
|
||||
"width": 512,
|
||||
"height": 512,
|
||||
"format": "png"
|
||||
},
|
||||
"explorers": [
|
||||
{
|
||||
"name": "Acria IntelliChain-Explorer",
|
||||
"url": "https://explorer.acria.ai",
|
||||
"standard": "EIP3091"
|
||||
"name": "XPLA Explorer",
|
||||
"url": "https://explorer.xpla.io/testnet",
|
||||
"standard": "none"
|
||||
}
|
||||
],
|
||||
"testnet": false,
|
||||
"slug": "acria-intellichain"
|
||||
"testnet": true,
|
||||
"redFlags": [
|
||||
"reusedChainId"
|
||||
],
|
||||
"slug": "xpla-testnet"
|
||||
} as const satisfies Chain;
|
||||
@@ -8,8 +8,8 @@ export default {
|
||||
],
|
||||
"faucets": [],
|
||||
"nativeCurrency": {
|
||||
"name": "HMND",
|
||||
"symbol": "HMND",
|
||||
"name": "eHMND",
|
||||
"symbol": "eHMND",
|
||||
"decimals": 18
|
||||
},
|
||||
"infoURL": "https://humanode.io",
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
import type { Chain } from "../src/types";
|
||||
export default {
|
||||
"name": "LAOS Arrakis",
|
||||
"title": "LAOS Testnet Arrakis",
|
||||
"chain": "LAOS",
|
||||
"icon": {
|
||||
"url": "ipfs://QmZ4YYcvhcaeotMPaGXC5Vab7JFaVkka37V8TiTJpT7Mak",
|
||||
"width": 586,
|
||||
"height": 558,
|
||||
"format": "png"
|
||||
},
|
||||
"rpc": [
|
||||
"https://laos-arrakis.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
|
||||
"https://arrakis.gorengine.com/own",
|
||||
"wss://arrakis.gorengine.com/own"
|
||||
],
|
||||
"faucets": [],
|
||||
"nativeCurrency": {
|
||||
"name": "LAOS",
|
||||
"symbol": "LAOS",
|
||||
"decimals": 18
|
||||
},
|
||||
"infoURL": "https://www.laosfoundation.io/",
|
||||
"shortName": "laos",
|
||||
"chainId": 667,
|
||||
"networkId": 667,
|
||||
"explorers": [
|
||||
{
|
||||
"name": "blockscout",
|
||||
"url": "https://arrakis.gorengine.com",
|
||||
"icon": {
|
||||
"url": "ipfs://QmZ4YYcvhcaeotMPaGXC5Vab7JFaVkka37V8TiTJpT7Mak",
|
||||
"width": 586,
|
||||
"height": 558,
|
||||
"format": "png"
|
||||
},
|
||||
"standard": "EIP3091"
|
||||
}
|
||||
],
|
||||
"testnet": true,
|
||||
"slug": "laos-arrakis"
|
||||
} as const satisfies Chain;
|
||||
@@ -4,7 +4,11 @@ export default {
|
||||
"chain": "DSC",
|
||||
"rpc": [
|
||||
"https://decimal-smart-chain.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
|
||||
"https://node.decimalchain.com/web3/"
|
||||
"https://node.decimalchain.com/web3/",
|
||||
"https://node1-mainnet.decimalchain.com/web3/",
|
||||
"https://node2-mainnet.decimalchain.com/web3/",
|
||||
"https://node3-mainnet.decimalchain.com/web3/",
|
||||
"https://node4-mainnet.decimalchain.com/web3/"
|
||||
],
|
||||
"faucets": [],
|
||||
"nativeCurrency": {
|
||||
|
||||
@@ -4,7 +4,8 @@ export default {
|
||||
"chain": "ETH",
|
||||
"rpc": [
|
||||
"https://base.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
|
||||
"https://mainnet.base.org/"
|
||||
"https://mainnet.base.org/",
|
||||
"https://developer-access-mainnet.base.org/"
|
||||
],
|
||||
"faucets": [],
|
||||
"nativeCurrency": {
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
import type { Chain } from "../src/types";
|
||||
export default {
|
||||
"name": "Worlds Appchain",
|
||||
"chain": "WRLDS",
|
||||
"shortName": "WRLDS",
|
||||
"chainId": 91003,
|
||||
"testnet": true,
|
||||
"rpc": [
|
||||
"https://worlds-appchain.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
|
||||
"https://api.evm.worlds.dev.eclipsenetwork.xyz/"
|
||||
],
|
||||
"nativeCurrency": {
|
||||
"name": "WRLDS",
|
||||
"symbol": "WRLDS",
|
||||
"decimals": 18
|
||||
},
|
||||
"faucets": [
|
||||
"https://faucet.evm.worlds.dev.eclipsenetwork.xyz/request_neon"
|
||||
],
|
||||
"slug": "worlds-appchain"
|
||||
} as const satisfies Chain;
|
||||
@@ -8,6 +8,12 @@ export default {
|
||||
shortName: "POPTestnet",
|
||||
chainId: 331769,
|
||||
testnet: true,
|
||||
icon: {
|
||||
format: "png",
|
||||
url: "ipfs://QmP8rYvcc7aJB3c2YZxjxaySvHapHnoK8MnxuSuDT4PtF2",
|
||||
height: 400,
|
||||
width: 400,
|
||||
},
|
||||
rpc: ["https://testnet01.proofofpepe.tech"],
|
||||
nativeCurrency: {
|
||||
name: "POP",
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
// @ts-check
|
||||
/** @typedef { import("../../src/types").Chain } Chain */
|
||||
|
||||
/** @type {Omit<Chain, "slug">} */
|
||||
export default {
|
||||
name: "POP Mainnet",
|
||||
chain: "POP",
|
||||
shortName: "POP",
|
||||
chainId: 331771,
|
||||
testnet: false,
|
||||
icon: {
|
||||
format: "png",
|
||||
url: "ipfs://QmP8rYvcc7aJB3c2YZxjxaySvHapHnoK8MnxuSuDT4PtF2",
|
||||
height: 400,
|
||||
width: 400,
|
||||
},
|
||||
rpc: [
|
||||
"https://rpc00.proofofpepe.tech",
|
||||
"https://rpc01.proofofpepe.tech",
|
||||
"https://rpc02.proofofpepe.tech",
|
||||
],
|
||||
nativeCurrency: {
|
||||
name: "Pepe",
|
||||
symbol: "PEPE",
|
||||
decimals: 18,
|
||||
},
|
||||
explorers: [
|
||||
{ name: "Pepescan", url: "https://pepescan.app", standard: "none" },
|
||||
],
|
||||
};
|
||||
@@ -0,0 +1,32 @@
|
||||
// @ts-check
|
||||
/** @typedef { import("../../src/types").Chain } Chain */
|
||||
|
||||
/** @type {Omit<Chain, "slug">} */
|
||||
export default {
|
||||
name: "Xpla Mainnet",
|
||||
chain: "XPLA",
|
||||
rpc: ["https://dimension-evm-rpc.xpla.dev"],
|
||||
nativeCurrency: {
|
||||
name: "XPLA",
|
||||
symbol: "XPLA",
|
||||
decimals: 18,
|
||||
},
|
||||
infoURL: "https://xpla.io/",
|
||||
shortName: "xpla",
|
||||
chainId: 37,
|
||||
icon: {
|
||||
url: "ipfs://QmbvEAKZfgJckEziU3mpCwz6jqMeWRcLgd8TNsWA7g8sD9/xpla.png",
|
||||
width: 512,
|
||||
height: 512,
|
||||
format: "png",
|
||||
},
|
||||
explorers: [
|
||||
{
|
||||
name: "XPLA Explorer",
|
||||
url: "https://explorer.xpla.io",
|
||||
standard: "none",
|
||||
},
|
||||
],
|
||||
testnet: false,
|
||||
redFlags: ["reusedChainId"],
|
||||
};
|
||||
@@ -0,0 +1,33 @@
|
||||
// @ts-check
|
||||
/** @typedef { import("../../src/types").Chain } Chain */
|
||||
|
||||
/** @type {Omit<Chain, "slug">} */
|
||||
export default {
|
||||
name: "Xpla Testnet",
|
||||
chain: "XPLA",
|
||||
rpc: ["https://cube-evm-rpc.xpla.dev"],
|
||||
nativeCurrency: {
|
||||
name: "XPLA",
|
||||
symbol: "XPLA",
|
||||
decimals: 18,
|
||||
},
|
||||
faucets: ["https://faucet.xpla.io/"],
|
||||
infoURL: "https://xpla.io/",
|
||||
shortName: "xpla-test",
|
||||
chainId: 47,
|
||||
icon: {
|
||||
url: "ipfs://QmbvEAKZfgJckEziU3mpCwz6jqMeWRcLgd8TNsWA7g8sD9/xpla.png",
|
||||
width: 512,
|
||||
height: 512,
|
||||
format: "png",
|
||||
},
|
||||
explorers: [
|
||||
{
|
||||
name: "XPLA Explorer",
|
||||
url: "https://explorer.xpla.io/testnet",
|
||||
standard: "none",
|
||||
},
|
||||
],
|
||||
testnet: true,
|
||||
redFlags: ["reusedChainId"],
|
||||
};
|
||||
@@ -0,0 +1,18 @@
|
||||
// @ts-check
|
||||
/** @typedef { import("../../src/types").Chain } Chain */
|
||||
|
||||
/** @type {Omit<Chain, "slug">} */
|
||||
export default {
|
||||
name: "Worlds Appchain",
|
||||
chain: "WRLDS",
|
||||
shortName: "WRLDS",
|
||||
chainId: 91003,
|
||||
testnet: true,
|
||||
rpc: ["https://api.evm.worlds.dev.eclipsenetwork.xyz/"],
|
||||
nativeCurrency: {
|
||||
name: "WRLDS",
|
||||
symbol: "WRLDS",
|
||||
decimals: 18,
|
||||
},
|
||||
faucets: ["https://faucet.evm.worlds.dev.eclipsenetwork.xyz/request_neon"],
|
||||
};
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@thirdweb-dev/chains",
|
||||
"version": "0.1.44",
|
||||
"version": "0.1.47",
|
||||
"main": "dist/thirdweb-dev-chains.cjs.js",
|
||||
"module": "dist/thirdweb-dev-chains.esm.js",
|
||||
"browser": {
|
||||
|
||||
@@ -344,6 +344,7 @@ ${exports.join("\n")}
|
||||
export * from "./types";
|
||||
export * from "./utils";
|
||||
export const defaultChains = [c1, c5, c8453, c84531, c137, c80001, c42161, c421613, c10, c420, c56, c97, c250, c4002, c43114, c43113, c1337];
|
||||
// @ts-expect-error - TODO: fix this later
|
||||
export const allChains: Chain[] = [${exportNames.join(", ")}];
|
||||
|
||||
type ChainsById = {
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -1,5 +1,38 @@
|
||||
# thirdweb
|
||||
|
||||
## 0.11.19
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`586e91db`](https://github.com/thirdweb-dev/js/commit/586e91dbe610588cc7b24fade59172fed6481074), [`34a3bb8a`](https://github.com/thirdweb-dev/js/commit/34a3bb8ae3c1d7a506e5568a9e79ab7e469557a8), [`91f0245b`](https://github.com/thirdweb-dev/js/commit/91f0245be78ae523e1faea26b1032bfb283467d9), [`f65578d6`](https://github.com/thirdweb-dev/js/commit/f65578d637decc8b87cada5b5b0c8c504064d9d5), [`5a373a75`](https://github.com/thirdweb-dev/js/commit/5a373a75090da7e1e05724ed1a3a3a6aa9f7fd21), [`ae74b8ef`](https://github.com/thirdweb-dev/js/commit/ae74b8ef6200dba8affa8b52e7d834c5552350d0), [`bc003c2f`](https://github.com/thirdweb-dev/js/commit/bc003c2fef33fcf7ce5981d8634911ac4bcaa927), [`447d9846`](https://github.com/thirdweb-dev/js/commit/447d984653f77af6860ae907072e768b584b263d), [`f65578d6`](https://github.com/thirdweb-dev/js/commit/f65578d637decc8b87cada5b5b0c8c504064d9d5)]:
|
||||
- @thirdweb-dev/sdk@3.10.55
|
||||
- @thirdweb-dev/chains@0.1.47
|
||||
- @thirdweb-dev/storage@1.2.8
|
||||
|
||||
## 0.11.18
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`184c325a`](https://github.com/thirdweb-dev/js/commit/184c325ab2ef028022a050c4274f2ab12b1a3a7f), [`046c9ad6`](https://github.com/thirdweb-dev/js/commit/046c9ad604587ff79bf028c4fe7b1f9c94f4ea54), [`c12f0874`](https://github.com/thirdweb-dev/js/commit/c12f0874b4dac43c263c7edb20d0343c16381c34)]:
|
||||
- @thirdweb-dev/chains@0.1.46
|
||||
- @thirdweb-dev/storage@1.2.7
|
||||
- @thirdweb-dev/sdk@3.10.54
|
||||
|
||||
## 0.11.17
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`f97ddf4c`](https://github.com/thirdweb-dev/js/commit/f97ddf4c7f14854f3b204ad9741b52ddb8dac736)]:
|
||||
- @thirdweb-dev/chains@0.1.45
|
||||
- @thirdweb-dev/sdk@3.10.53
|
||||
|
||||
## 0.11.16
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`e1962641`](https://github.com/thirdweb-dev/js/commit/e19626417218767a0e44c00f440761d7b86d02eb), [`bd1fcbae`](https://github.com/thirdweb-dev/js/commit/bd1fcbae327e788124f5635673511f0b72e9d7ab)]:
|
||||
- @thirdweb-dev/sdk@3.10.52
|
||||
|
||||
## 0.11.15
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "thirdweb",
|
||||
"main": "dist/cli/index.js",
|
||||
"version": "0.11.15",
|
||||
"version": "0.11.19",
|
||||
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/cli",
|
||||
"author": "thirdweb eng <[email protected]>",
|
||||
"license": "Apache-2.0",
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
# @thirdweb-dev/contracts-js
|
||||
|
||||
## 1.3.12
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#1518](https://github.com/thirdweb-dev/js/pull/1518) [`34a3bb8a`](https://github.com/thirdweb-dev/js/commit/34a3bb8ae3c1d7a506e5568a9e79ab7e469557a8) Thanks [@nkrishang](https://github.com/nkrishang)! - Update contracts package
|
||||
|
||||
## 1.3.11
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@thirdweb-dev/contracts-js",
|
||||
"version": "1.3.11",
|
||||
"version": "1.3.12",
|
||||
"main": "dist/thirdweb-dev-contracts-js.cjs.js",
|
||||
"module": "dist/thirdweb-dev-contracts-js.esm.js",
|
||||
"browser": {
|
||||
@@ -10,7 +10,7 @@
|
||||
"license": "Apache-2.0",
|
||||
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/contracts-js",
|
||||
"dependencies": {
|
||||
"@thirdweb-dev/contracts": "3.8.3"
|
||||
"@thirdweb-dev/contracts": "3.8.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/preset-env": "^7.22.9",
|
||||
|
||||
@@ -1,5 +1,49 @@
|
||||
# @thirdweb-dev/react-core
|
||||
|
||||
## 3.14.36
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#1522](https://github.com/thirdweb-dev/js/pull/1522) [`088547f7`](https://github.com/thirdweb-dev/js/commit/088547f763294f1641c01ffe1aabac585f255dc0) Thanks [@MananTank](https://github.com/MananTank)! - - New prop `switchToActiveChain` added to `ConnectWallet`` component to show "Switch Network" button if wallet is not connected to the `activeChain`passed to the`ThirdwebProvider`
|
||||
- Add max-height on `ConnectWallet` modal
|
||||
- Local Wallet UI adjustments
|
||||
- Updated dependencies [[`586e91db`](https://github.com/thirdweb-dev/js/commit/586e91dbe610588cc7b24fade59172fed6481074), [`34a3bb8a`](https://github.com/thirdweb-dev/js/commit/34a3bb8ae3c1d7a506e5568a9e79ab7e469557a8), [`91f0245b`](https://github.com/thirdweb-dev/js/commit/91f0245be78ae523e1faea26b1032bfb283467d9), [`f65578d6`](https://github.com/thirdweb-dev/js/commit/f65578d637decc8b87cada5b5b0c8c504064d9d5), [`5a373a75`](https://github.com/thirdweb-dev/js/commit/5a373a75090da7e1e05724ed1a3a3a6aa9f7fd21), [`ae74b8ef`](https://github.com/thirdweb-dev/js/commit/ae74b8ef6200dba8affa8b52e7d834c5552350d0), [`bc003c2f`](https://github.com/thirdweb-dev/js/commit/bc003c2fef33fcf7ce5981d8634911ac4bcaa927), [`447d9846`](https://github.com/thirdweb-dev/js/commit/447d984653f77af6860ae907072e768b584b263d), [`f65578d6`](https://github.com/thirdweb-dev/js/commit/f65578d637decc8b87cada5b5b0c8c504064d9d5)]:
|
||||
- @thirdweb-dev/sdk@3.10.55
|
||||
- @thirdweb-dev/chains@0.1.47
|
||||
- @thirdweb-dev/storage@1.2.8
|
||||
- @thirdweb-dev/wallets@1.1.19
|
||||
- @thirdweb-dev/auth@3.2.36
|
||||
|
||||
## 3.14.35
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`184c325a`](https://github.com/thirdweb-dev/js/commit/184c325ab2ef028022a050c4274f2ab12b1a3a7f), [`046c9ad6`](https://github.com/thirdweb-dev/js/commit/046c9ad604587ff79bf028c4fe7b1f9c94f4ea54), [`c12f0874`](https://github.com/thirdweb-dev/js/commit/c12f0874b4dac43c263c7edb20d0343c16381c34)]:
|
||||
- @thirdweb-dev/chains@0.1.46
|
||||
- @thirdweb-dev/storage@1.2.7
|
||||
- @thirdweb-dev/sdk@3.10.54
|
||||
- @thirdweb-dev/wallets@1.1.18
|
||||
- @thirdweb-dev/auth@3.2.35
|
||||
|
||||
## 3.14.34
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`f97ddf4c`](https://github.com/thirdweb-dev/js/commit/f97ddf4c7f14854f3b204ad9741b52ddb8dac736)]:
|
||||
- @thirdweb-dev/chains@0.1.45
|
||||
- @thirdweb-dev/sdk@3.10.53
|
||||
- @thirdweb-dev/wallets@1.1.17
|
||||
- @thirdweb-dev/auth@3.2.34
|
||||
|
||||
## 3.14.33
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`e1962641`](https://github.com/thirdweb-dev/js/commit/e19626417218767a0e44c00f440761d7b86d02eb), [`bd1fcbae`](https://github.com/thirdweb-dev/js/commit/bd1fcbae327e788124f5635673511f0b72e9d7ab)]:
|
||||
- @thirdweb-dev/sdk@3.10.52
|
||||
- @thirdweb-dev/wallets@1.1.16
|
||||
- @thirdweb-dev/auth@3.2.33
|
||||
|
||||
## 3.14.32
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@thirdweb-dev/react-core",
|
||||
"version": "3.14.32",
|
||||
"version": "3.14.36",
|
||||
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/react-core",
|
||||
"author": "thirdweb eng <[email protected]>",
|
||||
"license": "Apache-2.0",
|
||||
@@ -98,7 +98,7 @@
|
||||
"typescript": "^5.1.6"
|
||||
},
|
||||
"dependencies": {
|
||||
"@tanstack/react-query": "^4.32.0",
|
||||
"@tanstack/react-query": "^4.33.0",
|
||||
"@thirdweb-dev/chains": "workspace:*",
|
||||
"@thirdweb-dev/generated-abis": "workspace:^",
|
||||
"@thirdweb-dev/sdk": "workspace:*",
|
||||
|
||||
@@ -152,6 +152,7 @@ export const ThirdwebProviderCore = <TChains extends Chain[]>({
|
||||
autoSwitch={props.autoSwitch}
|
||||
autoConnectTimeout={props.autoConnectTimeout}
|
||||
clientId={props.clientId}
|
||||
activeChainSetExplicitly={!!props.activeChain}
|
||||
>
|
||||
<ThirdwebSDKProviderWrapper
|
||||
queryClient={props.queryClient}
|
||||
|
||||
@@ -89,6 +89,7 @@ type ThirdwebWalletContextData = {
|
||||
* Get wallet config object from wallet instance
|
||||
*/
|
||||
getWalletConfig: (walletInstance: WalletInstance) => WalletConfig | undefined;
|
||||
activeChainSetExplicitly: boolean;
|
||||
};
|
||||
|
||||
const ThirdwebWalletContext = /* @__PURE__ */ createContext<
|
||||
@@ -106,6 +107,7 @@ export function ThirdwebWalletProvider(
|
||||
autoSwitch?: boolean;
|
||||
autoConnectTimeout?: number;
|
||||
clientId?: string;
|
||||
activeChainSetExplicitly: boolean;
|
||||
}>,
|
||||
) {
|
||||
const [signer, setSigner] = useState<Signer | undefined>(undefined);
|
||||
@@ -480,6 +482,7 @@ export function ThirdwebWalletProvider(
|
||||
getWalletConfig: (walletInstance: WalletInstance) => {
|
||||
return walletInstanceToConfig.get(walletInstance);
|
||||
},
|
||||
activeChainSetExplicitly: props.activeChainSetExplicitly,
|
||||
}}
|
||||
>
|
||||
{props.children}
|
||||
|
||||
@@ -21,7 +21,6 @@ import {
|
||||
} from "@tanstack/react-query";
|
||||
import { getCachedAbiForContract, TransactionResult } from "@thirdweb-dev/sdk";
|
||||
import type {
|
||||
Abi,
|
||||
CommonContractSchemaInput,
|
||||
ContractEvent,
|
||||
ContractForPrebuiltContractType,
|
||||
@@ -33,6 +32,7 @@ import type {
|
||||
ThirdwebSDK,
|
||||
ValidContractInstance,
|
||||
BaseContractForAddress,
|
||||
PublishedMetadata,
|
||||
} from "@thirdweb-dev/sdk";
|
||||
import type { CallOverrides, ContractInterface, providers } from "ethers";
|
||||
import { useEffect, useMemo } from "react";
|
||||
@@ -88,19 +88,11 @@ export const contractType = {
|
||||
|
||||
// end contract type
|
||||
|
||||
type FetchCompilerMetadataReturnType = {
|
||||
name: string;
|
||||
metadata: Record<string, any>;
|
||||
abi: Abi;
|
||||
info: Record<string, any>;
|
||||
licenses: string[];
|
||||
};
|
||||
|
||||
// contract compiler metadata
|
||||
function fetchCompilerMetadata(
|
||||
contractAddress: RequiredParam<ContractAddress>,
|
||||
sdk: RequiredParam<ThirdwebSDK>,
|
||||
): Promise<FetchCompilerMetadataReturnType> | null {
|
||||
): Promise<PublishedMetadata> | null {
|
||||
if (!contractAddress || !sdk) {
|
||||
return null;
|
||||
}
|
||||
@@ -114,7 +106,7 @@ function fetchCompilerMetadata(
|
||||
|
||||
export function useCompilerMetadata(
|
||||
contractAddress: RequiredParam<ContractAddress>,
|
||||
): UseQueryResult<FetchCompilerMetadataReturnType | null> {
|
||||
): UseQueryResult<PublishedMetadata | null> {
|
||||
const sdk = useSDK();
|
||||
|
||||
return useQueryWithNetwork(
|
||||
|
||||
@@ -251,6 +251,9 @@ export { ThirdwebSDKProvider } from "./providers/thirdweb-sdk-provider";
|
||||
export { useSDK, useSDKChainId } from "./hooks/useSDK";
|
||||
export type { ThirdwebSDKProviderProps } from "./providers/types";
|
||||
|
||||
// utils
|
||||
export { invalidateContractAndBalances } from "./utils/cache-keys";
|
||||
|
||||
// types
|
||||
export type {
|
||||
Chain,
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
# @thirdweb-dev/react-native-compat
|
||||
|
||||
## 0.2.55
|
||||
|
||||
## 0.2.54
|
||||
|
||||
## 0.2.53
|
||||
|
||||
## 0.2.52
|
||||
|
||||
## 0.2.51
|
||||
|
||||
## 0.2.50
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@thirdweb-dev/react-native-compat",
|
||||
"description": "Shims for Thirdweb in React Native Projects",
|
||||
"version": "0.2.51",
|
||||
"version": "0.2.55",
|
||||
"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,46 @@
|
||||
# @thirdweb-dev/react-native
|
||||
|
||||
## 0.2.55
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`586e91db`](https://github.com/thirdweb-dev/js/commit/586e91dbe610588cc7b24fade59172fed6481074), [`34a3bb8a`](https://github.com/thirdweb-dev/js/commit/34a3bb8ae3c1d7a506e5568a9e79ab7e469557a8), [`91f0245b`](https://github.com/thirdweb-dev/js/commit/91f0245be78ae523e1faea26b1032bfb283467d9), [`f65578d6`](https://github.com/thirdweb-dev/js/commit/f65578d637decc8b87cada5b5b0c8c504064d9d5), [`5a373a75`](https://github.com/thirdweb-dev/js/commit/5a373a75090da7e1e05724ed1a3a3a6aa9f7fd21), [`ae74b8ef`](https://github.com/thirdweb-dev/js/commit/ae74b8ef6200dba8affa8b52e7d834c5552350d0), [`bc003c2f`](https://github.com/thirdweb-dev/js/commit/bc003c2fef33fcf7ce5981d8634911ac4bcaa927), [`447d9846`](https://github.com/thirdweb-dev/js/commit/447d984653f77af6860ae907072e768b584b263d), [`f65578d6`](https://github.com/thirdweb-dev/js/commit/f65578d637decc8b87cada5b5b0c8c504064d9d5), [`088547f7`](https://github.com/thirdweb-dev/js/commit/088547f763294f1641c01ffe1aabac585f255dc0)]:
|
||||
- @thirdweb-dev/sdk@3.10.55
|
||||
- @thirdweb-dev/chains@0.1.47
|
||||
- @thirdweb-dev/storage@1.2.8
|
||||
- @thirdweb-dev/react-core@3.14.36
|
||||
- @thirdweb-dev/wallets@1.1.19
|
||||
|
||||
## 0.2.54
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`184c325a`](https://github.com/thirdweb-dev/js/commit/184c325ab2ef028022a050c4274f2ab12b1a3a7f), [`046c9ad6`](https://github.com/thirdweb-dev/js/commit/046c9ad604587ff79bf028c4fe7b1f9c94f4ea54), [`c12f0874`](https://github.com/thirdweb-dev/js/commit/c12f0874b4dac43c263c7edb20d0343c16381c34)]:
|
||||
- @thirdweb-dev/chains@0.1.46
|
||||
- @thirdweb-dev/storage@1.2.7
|
||||
- @thirdweb-dev/react-core@3.14.35
|
||||
- @thirdweb-dev/sdk@3.10.54
|
||||
- @thirdweb-dev/wallets@1.1.18
|
||||
|
||||
## 0.2.53
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`f97ddf4c`](https://github.com/thirdweb-dev/js/commit/f97ddf4c7f14854f3b204ad9741b52ddb8dac736)]:
|
||||
- @thirdweb-dev/chains@0.1.45
|
||||
- @thirdweb-dev/react-core@3.14.34
|
||||
- @thirdweb-dev/sdk@3.10.53
|
||||
- @thirdweb-dev/wallets@1.1.17
|
||||
|
||||
## 0.2.52
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`e1962641`](https://github.com/thirdweb-dev/js/commit/e19626417218767a0e44c00f440761d7b86d02eb), [`bd1fcbae`](https://github.com/thirdweb-dev/js/commit/bd1fcbae327e788124f5635673511f0b72e9d7ab)]:
|
||||
- @thirdweb-dev/sdk@3.10.52
|
||||
- @thirdweb-dev/react-core@3.14.33
|
||||
- @thirdweb-dev/wallets@1.1.16
|
||||
|
||||
## 0.2.51
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@thirdweb-dev/react-native",
|
||||
"version": "0.2.51",
|
||||
"version": "0.2.55",
|
||||
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/react-native",
|
||||
"author": "thirdweb eng <[email protected]>",
|
||||
"license": "Apache-2.0",
|
||||
@@ -28,7 +28,7 @@
|
||||
"@magic-sdk/provider": "17.2.0",
|
||||
"@magic-sdk/react-native-bare": "^18.5.0",
|
||||
"@shopify/restyle": "^2.4.2",
|
||||
"@tanstack/react-query": "^4.32.0",
|
||||
"@tanstack/react-query": "^4.33.0",
|
||||
"@thirdweb-dev/chains": "workspace:*",
|
||||
"@thirdweb-dev/react-core": "workspace:*",
|
||||
"@thirdweb-dev/sdk": "workspace:*",
|
||||
|
||||
@@ -1,5 +1,47 @@
|
||||
# @thirdweb-dev/react
|
||||
|
||||
## 3.14.36
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#1522](https://github.com/thirdweb-dev/js/pull/1522) [`088547f7`](https://github.com/thirdweb-dev/js/commit/088547f763294f1641c01ffe1aabac585f255dc0) Thanks [@MananTank](https://github.com/MananTank)! - - New prop `switchToActiveChain` added to `ConnectWallet`` component to show "Switch Network" button if wallet is not connected to the `activeChain`passed to the`ThirdwebProvider`
|
||||
- Add max-height on `ConnectWallet` modal
|
||||
- Local Wallet UI adjustments
|
||||
- Updated dependencies [[`586e91db`](https://github.com/thirdweb-dev/js/commit/586e91dbe610588cc7b24fade59172fed6481074), [`34a3bb8a`](https://github.com/thirdweb-dev/js/commit/34a3bb8ae3c1d7a506e5568a9e79ab7e469557a8), [`91f0245b`](https://github.com/thirdweb-dev/js/commit/91f0245be78ae523e1faea26b1032bfb283467d9), [`5a373a75`](https://github.com/thirdweb-dev/js/commit/5a373a75090da7e1e05724ed1a3a3a6aa9f7fd21), [`ae74b8ef`](https://github.com/thirdweb-dev/js/commit/ae74b8ef6200dba8affa8b52e7d834c5552350d0), [`bc003c2f`](https://github.com/thirdweb-dev/js/commit/bc003c2fef33fcf7ce5981d8634911ac4bcaa927), [`447d9846`](https://github.com/thirdweb-dev/js/commit/447d984653f77af6860ae907072e768b584b263d), [`f65578d6`](https://github.com/thirdweb-dev/js/commit/f65578d637decc8b87cada5b5b0c8c504064d9d5), [`088547f7`](https://github.com/thirdweb-dev/js/commit/088547f763294f1641c01ffe1aabac585f255dc0)]:
|
||||
- @thirdweb-dev/sdk@3.10.55
|
||||
- @thirdweb-dev/chains@0.1.47
|
||||
- @thirdweb-dev/react-core@3.14.36
|
||||
- @thirdweb-dev/wallets@1.1.19
|
||||
|
||||
## 3.14.35
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`184c325a`](https://github.com/thirdweb-dev/js/commit/184c325ab2ef028022a050c4274f2ab12b1a3a7f), [`c12f0874`](https://github.com/thirdweb-dev/js/commit/c12f0874b4dac43c263c7edb20d0343c16381c34)]:
|
||||
- @thirdweb-dev/chains@0.1.46
|
||||
- @thirdweb-dev/react-core@3.14.35
|
||||
- @thirdweb-dev/sdk@3.10.54
|
||||
- @thirdweb-dev/wallets@1.1.18
|
||||
|
||||
## 3.14.34
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`f97ddf4c`](https://github.com/thirdweb-dev/js/commit/f97ddf4c7f14854f3b204ad9741b52ddb8dac736)]:
|
||||
- @thirdweb-dev/chains@0.1.45
|
||||
- @thirdweb-dev/react-core@3.14.34
|
||||
- @thirdweb-dev/sdk@3.10.53
|
||||
- @thirdweb-dev/wallets@1.1.17
|
||||
|
||||
## 3.14.33
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`e1962641`](https://github.com/thirdweb-dev/js/commit/e19626417218767a0e44c00f440761d7b86d02eb), [`bd1fcbae`](https://github.com/thirdweb-dev/js/commit/bd1fcbae327e788124f5635673511f0b72e9d7ab)]:
|
||||
- @thirdweb-dev/sdk@3.10.52
|
||||
- @thirdweb-dev/react-core@3.14.33
|
||||
- @thirdweb-dev/wallets@1.1.16
|
||||
|
||||
## 3.14.32
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@thirdweb-dev/react",
|
||||
"version": "3.14.32",
|
||||
"version": "3.14.36",
|
||||
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/react",
|
||||
"author": "thirdweb eng <[email protected]>",
|
||||
"license": "Apache-2.0",
|
||||
@@ -131,7 +131,7 @@
|
||||
"@radix-ui/react-tabs": "^1.0.4",
|
||||
"@radix-ui/react-tooltip": "^1.0.6",
|
||||
"@react-icons/all-files": "^4.1.0",
|
||||
"@tanstack/react-query": "^4.32.0",
|
||||
"@tanstack/react-query": "^4.33.0",
|
||||
"@thirdweb-dev/chains": "workspace:*",
|
||||
"@thirdweb-dev/react-core": "workspace:*",
|
||||
"@thirdweb-dev/wallets": "workspace:*",
|
||||
|
||||
@@ -18,6 +18,7 @@ export const FormFieldWithIconButton: React.FC<{
|
||||
error?: string;
|
||||
noSave?: boolean;
|
||||
dataTest?: string;
|
||||
placeholder?: string;
|
||||
}> = (props) => {
|
||||
return (
|
||||
<div>
|
||||
@@ -42,6 +43,7 @@ export const FormFieldWithIconButton: React.FC<{
|
||||
: undefined
|
||||
}
|
||||
data-test={props.dataTest}
|
||||
placeholder={props.placeholder}
|
||||
/>
|
||||
|
||||
<InputButton type="button" onClick={props.right.onClick}>
|
||||
|
||||
@@ -97,7 +97,8 @@ export const ConnectModal = () => {
|
||||
>
|
||||
<Modal
|
||||
style={{
|
||||
maxWidth: "480px",
|
||||
maxWidth: "450px",
|
||||
maxHeight: "70vh",
|
||||
}}
|
||||
open={isWalletModalOpen}
|
||||
setOpen={(value) => {
|
||||
|
||||
@@ -7,9 +7,12 @@ import {
|
||||
useConnectionStatus,
|
||||
useLogin,
|
||||
useLogout,
|
||||
useNetworkMismatch,
|
||||
useSwitchChain,
|
||||
useThirdwebAuthContext,
|
||||
useUser,
|
||||
useWallet,
|
||||
useWalletContext,
|
||||
} from "@thirdweb-dev/react-core";
|
||||
import { useContext, useState } from "react";
|
||||
import {
|
||||
@@ -54,6 +57,13 @@ type ConnectWalletProps = {
|
||||
* @default false
|
||||
*/
|
||||
hideTestnetFaucet?: boolean;
|
||||
|
||||
/**
|
||||
* Whether to show "Switch Network" button if wallet connected, but it is not connected to the `activeChain` provided in `ThirdwebProvider`
|
||||
*
|
||||
* @default false
|
||||
*/
|
||||
switchToActiveChain?: boolean;
|
||||
};
|
||||
|
||||
const TW_CONNECT_WALLET = "tw-connect-wallet";
|
||||
@@ -83,6 +93,8 @@ export const ConnectWallet: React.FC<ConnectWalletProps> = (props) => {
|
||||
const { user } = useUser();
|
||||
const { login } = useLogin();
|
||||
const { logout } = useLogout();
|
||||
const isNetworkMismatch = useNetworkMismatch();
|
||||
const { activeChainSetExplicitly } = useWalletContext();
|
||||
|
||||
const requiresSignIn = props.auth?.loginOptional
|
||||
? false
|
||||
@@ -108,61 +120,87 @@ export const ConnectWallet: React.FC<ConnectWalletProps> = (props) => {
|
||||
/>
|
||||
)}
|
||||
|
||||
{/* Sign In Button */}
|
||||
{requiresSignIn && (
|
||||
<Button
|
||||
variant="inverted"
|
||||
onClick={signIn}
|
||||
data-theme={theme}
|
||||
className={`${TW_CONNECT_WALLET}--sign-in ${props.className || ""}}`}
|
||||
style={props.style}
|
||||
>
|
||||
<Flex
|
||||
alignItems="center"
|
||||
gap="sm"
|
||||
style={{
|
||||
paddingRight: spacing.xs,
|
||||
borderRight: "1px solid",
|
||||
marginRight: spacing.xs,
|
||||
}}
|
||||
>
|
||||
<LockIcon size={iconSize.sm} />
|
||||
<span> Sign in </span>
|
||||
</Flex>
|
||||
<span>{shortenAddress(address || "", true)}</span>
|
||||
</Button>
|
||||
)}
|
||||
{(() => {
|
||||
// wallet is not connected
|
||||
if (!activeWallet) {
|
||||
// Connect Wallet button
|
||||
return (
|
||||
<AnimatedButton
|
||||
disabled={isLoading}
|
||||
className={`${props.className || ""} ${TW_CONNECT_WALLET}`}
|
||||
data-theme={theme}
|
||||
data-is-loading={isLoading}
|
||||
variant="inverted"
|
||||
type="button"
|
||||
style={{
|
||||
minWidth: "140px",
|
||||
...props.style,
|
||||
}}
|
||||
aria-label={
|
||||
connectionStatus === "connecting" ? "Connecting" : btnTitle
|
||||
}
|
||||
onClick={() => {
|
||||
setModalConfig({
|
||||
title: props.modalTitle || "Choose your wallet",
|
||||
theme,
|
||||
data: undefined,
|
||||
});
|
||||
setIsWalletModalOpen(true);
|
||||
}}
|
||||
data-test="connect-wallet-button"
|
||||
>
|
||||
{isLoading ? <Spinner size="sm" color="inverted" /> : btnTitle}
|
||||
</AnimatedButton>
|
||||
);
|
||||
}
|
||||
|
||||
{!requiresSignIn &&
|
||||
(!activeWallet ? (
|
||||
// connect wallet button
|
||||
<AnimatedButton
|
||||
disabled={isLoading}
|
||||
className={`${props.className || ""} ${TW_CONNECT_WALLET}`}
|
||||
data-theme={theme}
|
||||
data-is-loading={isLoading}
|
||||
variant="inverted"
|
||||
type="button"
|
||||
style={{
|
||||
minWidth: "140px",
|
||||
...props.style,
|
||||
}}
|
||||
aria-label={
|
||||
connectionStatus === "connecting" ? "Connecting" : btnTitle
|
||||
}
|
||||
onClick={() => {
|
||||
setModalConfig({
|
||||
title: props.modalTitle || "Choose your wallet",
|
||||
theme,
|
||||
data: undefined,
|
||||
});
|
||||
setIsWalletModalOpen(true);
|
||||
}}
|
||||
data-test="connect-wallet-button"
|
||||
>
|
||||
{isLoading ? <Spinner size="sm" color="inverted" /> : btnTitle}
|
||||
</AnimatedButton>
|
||||
) : (
|
||||
// switch network button
|
||||
if (
|
||||
props.switchToActiveChain &&
|
||||
isNetworkMismatch &&
|
||||
activeChainSetExplicitly
|
||||
) {
|
||||
return (
|
||||
<SwitchNetworkButton
|
||||
style={props.style}
|
||||
theme={theme}
|
||||
className={props.className}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
// sign in button
|
||||
else if (requiresSignIn) {
|
||||
return (
|
||||
<Button
|
||||
variant="inverted"
|
||||
onClick={signIn}
|
||||
data-theme={theme}
|
||||
className={`${TW_CONNECT_WALLET}--sign-in ${
|
||||
props.className || ""
|
||||
}`}
|
||||
style={props.style}
|
||||
data-test="sign-in-button"
|
||||
>
|
||||
<Flex
|
||||
alignItems="center"
|
||||
gap="sm"
|
||||
style={{
|
||||
paddingRight: spacing.xs,
|
||||
borderRight: "1px solid",
|
||||
marginRight: spacing.xs,
|
||||
}}
|
||||
>
|
||||
<LockIcon size={iconSize.sm} />
|
||||
<span> Sign in </span>
|
||||
</Flex>
|
||||
<span>{shortenAddress(address || "", true)}</span>
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
|
||||
// wallet details button
|
||||
return (
|
||||
<ConnectedWalletDetails
|
||||
networkSelector={props.networkSelector}
|
||||
dropdownPosition={props.dropdownPosition}
|
||||
@@ -178,11 +216,52 @@ export const ConnectWallet: React.FC<ConnectWalletProps> = (props) => {
|
||||
}
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
);
|
||||
})()}
|
||||
</ThemeProvider>
|
||||
);
|
||||
};
|
||||
|
||||
function SwitchNetworkButton(props: {
|
||||
style?: React.CSSProperties;
|
||||
className?: string;
|
||||
theme: "dark" | "light";
|
||||
}) {
|
||||
const { activeChain } = useWalletContext();
|
||||
const switchChain = useSwitchChain();
|
||||
const [switching, setSwitching] = useState(false);
|
||||
|
||||
return (
|
||||
<AnimatedButton
|
||||
className={`${TW_CONNECT_WALLET}--switch-network ${
|
||||
props.className || ""
|
||||
}`}
|
||||
variant="inverted"
|
||||
type="button"
|
||||
data-theme={props.theme}
|
||||
data-is-loading={switching}
|
||||
data-test="switch-network-button"
|
||||
disabled={switching}
|
||||
onClick={async () => {
|
||||
setSwitching(true);
|
||||
try {
|
||||
await switchChain(activeChain.chainId);
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
setSwitching(false);
|
||||
}}
|
||||
style={{
|
||||
minWidth: "140px",
|
||||
...props.style,
|
||||
}}
|
||||
aria-label={switching ? "Switching Network" : undefined}
|
||||
>
|
||||
{switching ? <Spinner size="sm" color="inverted" /> : "Switch Network"}
|
||||
</AnimatedButton>
|
||||
);
|
||||
}
|
||||
|
||||
const AnimatedButton = /* @__PURE__ */ styled(Button)`
|
||||
animation: ${fadeInAnimation} 300ms ease;
|
||||
`;
|
||||
|
||||
@@ -113,7 +113,7 @@ export const WalletSelection: React.FC<{
|
||||
});
|
||||
|
||||
return (
|
||||
<WalletList>
|
||||
<WalletListContainer>
|
||||
{walletConfigs.map((walletConfig) => {
|
||||
const isInstalled = walletConfig.isInstalled
|
||||
? walletConfig.isInstalled()
|
||||
@@ -150,11 +150,11 @@ export const WalletSelection: React.FC<{
|
||||
</li>
|
||||
);
|
||||
})}
|
||||
</WalletList>
|
||||
</WalletListContainer>
|
||||
);
|
||||
};
|
||||
|
||||
const WalletList = styled.ul`
|
||||
const WalletListContainer = styled.ul`
|
||||
all: unset;
|
||||
list-style-type: none;
|
||||
display: flex;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Spacer } from "../../../components/Spacer";
|
||||
import { Button } from "../../../components/buttons";
|
||||
import { FormFooter, Label } from "../../../components/formElements";
|
||||
import { Label } from "../../../components/formElements";
|
||||
import {
|
||||
ModalTitle,
|
||||
ModalDescription,
|
||||
@@ -172,7 +172,7 @@ export const ExportLocalWallet: React.FC<{
|
||||
|
||||
<SavedWalletAddress>{shortenAddress(savedAddress)}</SavedWalletAddress>
|
||||
|
||||
<Spacer y="lg" />
|
||||
<Spacer y="xl" />
|
||||
|
||||
{passwordIsRequired && (
|
||||
<>
|
||||
@@ -207,22 +207,21 @@ export const ExportLocalWallet: React.FC<{
|
||||
error={isWrongPassword ? "Wrong Password" : ""}
|
||||
dataTest="current-password"
|
||||
/>
|
||||
<Spacer y="xl" />
|
||||
<Spacer y="md" />
|
||||
</>
|
||||
)}
|
||||
|
||||
<FormFooter>
|
||||
<Button
|
||||
disabled={exportDisabled}
|
||||
variant="inverted"
|
||||
style={{
|
||||
opacity: exportDisabled ? 0.5 : 1,
|
||||
}}
|
||||
type="submit"
|
||||
>
|
||||
Backup
|
||||
</Button>
|
||||
</FormFooter>
|
||||
<Button
|
||||
disabled={exportDisabled}
|
||||
variant="inverted"
|
||||
style={{
|
||||
opacity: exportDisabled ? 0.5 : 1,
|
||||
width: "100%",
|
||||
}}
|
||||
type="submit"
|
||||
>
|
||||
Backup
|
||||
</Button>
|
||||
</form>
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -8,7 +8,7 @@ import {
|
||||
import { EyeClosedIcon, EyeOpenIcon } from "@radix-ui/react-icons";
|
||||
import { WalletConfig, useWalletContext } from "@thirdweb-dev/react-core";
|
||||
import { useState } from "react";
|
||||
import { FormFooter, Label } from "../../../components/formElements";
|
||||
import { Label } from "../../../components/formElements";
|
||||
import { spacing } from "../../../design-system";
|
||||
import { Spinner } from "../../../components/Spinner";
|
||||
import { shortenAddress } from "../../../evm/utils/addresses";
|
||||
@@ -131,6 +131,7 @@ export const ReconnectLocalWallet: React.FC<ReconnectLocalWalletProps> = (
|
||||
meta={meta}
|
||||
hideBack={!props.renderBackButton}
|
||||
/>
|
||||
|
||||
<ModalTitle
|
||||
style={{
|
||||
textAlign: "left",
|
||||
@@ -138,12 +139,13 @@ export const ReconnectLocalWallet: React.FC<ReconnectLocalWalletProps> = (
|
||||
>
|
||||
Guest Wallet
|
||||
</ModalTitle>
|
||||
|
||||
<Spacer y="xs" />
|
||||
<ModalDescription>
|
||||
Connect to saved wallet on your device
|
||||
</ModalDescription>
|
||||
|
||||
<Spacer y="lg" />
|
||||
<Spacer y="xl" />
|
||||
|
||||
<Label>Saved Wallet</Label>
|
||||
|
||||
@@ -153,7 +155,7 @@ export const ReconnectLocalWallet: React.FC<ReconnectLocalWalletProps> = (
|
||||
{savedAddress === "" ? "Loading..." : shortenAddress(savedAddress)}
|
||||
</SecondaryText>
|
||||
|
||||
<Spacer y="lg" />
|
||||
<Spacer y="xl" />
|
||||
|
||||
<form
|
||||
onSubmit={(e) => {
|
||||
@@ -190,27 +192,27 @@ export const ReconnectLocalWallet: React.FC<ReconnectLocalWalletProps> = (
|
||||
value={password}
|
||||
error={isWrongPassword ? "Wrong Password" : ""}
|
||||
dataTest="current-password"
|
||||
placeholder="Enter your password"
|
||||
/>
|
||||
|
||||
<Spacer y="lg" />
|
||||
<Spacer y="md" />
|
||||
|
||||
{/* Connect Button */}
|
||||
<FormFooter>
|
||||
<Button
|
||||
variant="inverted"
|
||||
type="submit"
|
||||
style={{
|
||||
display: "flex",
|
||||
gap: spacing.sm,
|
||||
}}
|
||||
>
|
||||
Connect
|
||||
{isConnecting && <Spinner size="sm" color="inverted" />}
|
||||
</Button>
|
||||
</FormFooter>
|
||||
<Button
|
||||
variant="inverted"
|
||||
type="submit"
|
||||
style={{
|
||||
display: "flex",
|
||||
gap: spacing.sm,
|
||||
width: "100%",
|
||||
}}
|
||||
>
|
||||
Connect
|
||||
{isConnecting && <Spinner size="sm" color="inverted" />}
|
||||
</Button>
|
||||
</form>
|
||||
|
||||
<Spacer y="xxl" />
|
||||
<Spacer y="xl" />
|
||||
|
||||
<Button
|
||||
variant="link"
|
||||
|
||||
@@ -18,7 +18,7 @@ export const LocalWalletModalHeader: React.FC<{
|
||||
</>
|
||||
)}
|
||||
<Img src={props.meta.iconURL} width={iconSize.xl} height={iconSize.xl} />
|
||||
<Spacer y="sm" />
|
||||
<Spacer y="md" />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,5 +1,53 @@
|
||||
# @thirdweb-dev/sdk
|
||||
|
||||
## 3.10.55
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#1488](https://github.com/thirdweb-dev/js/pull/1488) [`586e91db`](https://github.com/thirdweb-dev/js/commit/586e91dbe610588cc7b24fade59172fed6481074) Thanks [@kumaryash90](https://github.com/kumaryash90)! - Dynamic contract detection and deployment using updated publish metadata
|
||||
|
||||
- [#1518](https://github.com/thirdweb-dev/js/pull/1518) [`34a3bb8a`](https://github.com/thirdweb-dev/js/commit/34a3bb8ae3c1d7a506e5568a9e79ab7e469557a8) Thanks [@nkrishang](https://github.com/nkrishang)! - Update contracts package
|
||||
|
||||
- [#1526](https://github.com/thirdweb-dev/js/pull/1526) [`91f0245b`](https://github.com/thirdweb-dev/js/commit/91f0245be78ae523e1faea26b1032bfb283467d9) Thanks [@kumaryash90](https://github.com/kumaryash90)! - Fix supported chains map in getChainProvider
|
||||
|
||||
- [#1525](https://github.com/thirdweb-dev/js/pull/1525) [`5a373a75`](https://github.com/thirdweb-dev/js/commit/5a373a75090da7e1e05724ed1a3a3a6aa9f7fd21) Thanks [@kumaryash90](https://github.com/kumaryash90)! - Correct chain / polygon rpc for fetching published contract
|
||||
|
||||
- [#1523](https://github.com/thirdweb-dev/js/pull/1523) [`ae74b8ef`](https://github.com/thirdweb-dev/js/commit/ae74b8ef6200dba8affa8b52e7d834c5552350d0) Thanks [@joaquim-verges](https://github.com/joaquim-verges)! - Separate ERC1155Supply extension
|
||||
|
||||
- [#1516](https://github.com/thirdweb-dev/js/pull/1516) [`bc003c2f`](https://github.com/thirdweb-dev/js/commit/bc003c2fef33fcf7ce5981d8634911ac4bcaa927) Thanks [@joaquim-verges](https://github.com/joaquim-verges)! - Return early for claim checks when possible
|
||||
|
||||
- [#1288](https://github.com/thirdweb-dev/js/pull/1288) [`447d9846`](https://github.com/thirdweb-dev/js/commit/447d984653f77af6860ae907072e768b584b263d) Thanks [@kumaryash90](https://github.com/kumaryash90)! - Airdrops
|
||||
|
||||
- [#1498](https://github.com/thirdweb-dev/js/pull/1498) [`f65578d6`](https://github.com/thirdweb-dev/js/commit/f65578d637decc8b87cada5b5b0c8c504064d9d5) Thanks [@joaquim-verges](https://github.com/joaquim-verges)! - Optimized fetching contract metadata, and fallback to bytecode extension detection for un-imported contracts
|
||||
|
||||
- Updated dependencies [[`34a3bb8a`](https://github.com/thirdweb-dev/js/commit/34a3bb8ae3c1d7a506e5568a9e79ab7e469557a8), [`f65578d6`](https://github.com/thirdweb-dev/js/commit/f65578d637decc8b87cada5b5b0c8c504064d9d5)]:
|
||||
- @thirdweb-dev/contracts-js@1.3.12
|
||||
- @thirdweb-dev/chains@0.1.47
|
||||
- @thirdweb-dev/storage@1.2.8
|
||||
|
||||
## 3.10.54
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`184c325a`](https://github.com/thirdweb-dev/js/commit/184c325ab2ef028022a050c4274f2ab12b1a3a7f), [`046c9ad6`](https://github.com/thirdweb-dev/js/commit/046c9ad604587ff79bf028c4fe7b1f9c94f4ea54), [`c12f0874`](https://github.com/thirdweb-dev/js/commit/c12f0874b4dac43c263c7edb20d0343c16381c34)]:
|
||||
- @thirdweb-dev/chains@0.1.46
|
||||
- @thirdweb-dev/storage@1.2.7
|
||||
|
||||
## 3.10.53
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`f97ddf4c`](https://github.com/thirdweb-dev/js/commit/f97ddf4c7f14854f3b204ad9741b52ddb8dac736)]:
|
||||
- @thirdweb-dev/chains@0.1.45
|
||||
|
||||
## 3.10.52
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#1503](https://github.com/thirdweb-dev/js/pull/1503) [`e1962641`](https://github.com/thirdweb-dev/js/commit/e19626417218767a0e44c00f440761d7b86d02eb) Thanks [@joaquim-verges](https://github.com/joaquim-verges)! - Pass custom storage instances to internal SDKs
|
||||
|
||||
- [#1505](https://github.com/thirdweb-dev/js/pull/1505) [`bd1fcbae`](https://github.com/thirdweb-dev/js/commit/bd1fcbae327e788124f5635673511f0b72e9d7ab) Thanks [@joaquim-verges](https://github.com/joaquim-verges)! - Expose Transaction.populateTransaction()
|
||||
|
||||
## 3.10.51
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@thirdweb-dev/sdk",
|
||||
"version": "3.10.51",
|
||||
"version": "3.10.55",
|
||||
"description": "The main thirdweb SDK.",
|
||||
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/sdk",
|
||||
"license": "Apache-2.0",
|
||||
|
||||
@@ -14,13 +14,23 @@ export async function computeCloneFactoryAddress(
|
||||
provider: providers.Provider,
|
||||
storage: ThirdwebStorage,
|
||||
create2Factory?: string,
|
||||
clientId?: string,
|
||||
secretKey?: string,
|
||||
): Promise<string> {
|
||||
if (!create2Factory) {
|
||||
create2Factory = await getCreate2FactoryAddress(provider);
|
||||
}
|
||||
return (
|
||||
await computeDeploymentInfo("infra", provider, storage, create2Factory, {
|
||||
contractName: "TWCloneFactory",
|
||||
})
|
||||
await computeDeploymentInfo(
|
||||
"infra",
|
||||
provider,
|
||||
storage,
|
||||
create2Factory,
|
||||
{
|
||||
contractName: "TWCloneFactory",
|
||||
},
|
||||
clientId,
|
||||
secretKey,
|
||||
)
|
||||
).transaction.predictedAddress;
|
||||
}
|
||||
|
||||
@@ -7,7 +7,10 @@ import {
|
||||
ContractOptions,
|
||||
DeploymentPreset,
|
||||
} from "../../types/any-evm/deploy-data";
|
||||
import { fetchAndCachePublishedContractURI } from "./fetchAndCachePublishedContractURI";
|
||||
import {
|
||||
THIRDWEB_DEPLOYER,
|
||||
fetchPublishedContractFromPolygon,
|
||||
} from "./fetchPublishedContractFromPolygon";
|
||||
import { fetchAndCacheDeployMetadata } from "./fetchAndCacheDeployMetadata";
|
||||
import { isContractDeployed } from "./isContractDeployed";
|
||||
import { getInitBytecodeWithSalt } from "./getInitBytecodeWithSalt";
|
||||
@@ -26,8 +29,12 @@ export async function computeDeploymentInfo(
|
||||
storage: ThirdwebStorage,
|
||||
create2Factory: string,
|
||||
contractOptions?: ContractOptions,
|
||||
clientId?: string,
|
||||
secretKey?: string,
|
||||
): Promise<DeploymentPreset> {
|
||||
const contractName = contractOptions && contractOptions.contractName;
|
||||
const version = contractOptions && contractOptions.version;
|
||||
let publisherAddress = contractOptions && contractOptions.publisherAddress;
|
||||
let metadata = contractOptions && contractOptions.metadata;
|
||||
invariant(contractName || metadata, "Require contract name or metadata");
|
||||
|
||||
@@ -57,9 +64,20 @@ export async function computeDeploymentInfo(
|
||||
|
||||
if (!metadata) {
|
||||
invariant(contractName, "Require contract name");
|
||||
const uri = await fetchAndCachePublishedContractURI(contractName);
|
||||
metadata = (await fetchAndCacheDeployMetadata(uri, storage))
|
||||
.compilerMetadata;
|
||||
if (!publisherAddress) {
|
||||
publisherAddress = THIRDWEB_DEPLOYER;
|
||||
}
|
||||
const publishedContract = await fetchPublishedContractFromPolygon(
|
||||
publisherAddress,
|
||||
contractName,
|
||||
version,
|
||||
storage,
|
||||
clientId,
|
||||
secretKey,
|
||||
);
|
||||
metadata = (
|
||||
await fetchAndCacheDeployMetadata(publishedContract.metadataUri, storage)
|
||||
).compilerMetadata;
|
||||
}
|
||||
|
||||
const encodedArgs = await encodeConstructorParamsForImplementation(
|
||||
@@ -68,6 +86,8 @@ export async function computeDeploymentInfo(
|
||||
storage,
|
||||
create2Factory,
|
||||
contractOptions?.constructorParams,
|
||||
clientId,
|
||||
secretKey,
|
||||
);
|
||||
const address = computeDeploymentAddress(
|
||||
metadata.bytecode,
|
||||
@@ -108,6 +128,8 @@ export async function encodeConstructorParamsForImplementation(
|
||||
storage: ThirdwebStorage,
|
||||
create2Factory: string,
|
||||
constructorParamMap?: ConstructorParamMap,
|
||||
clientId?: string,
|
||||
secretKey?: string,
|
||||
): Promise<BytesLike> {
|
||||
const constructorParams = extractConstructorParamsFromAbi(
|
||||
compilerMetadata.abi,
|
||||
@@ -147,6 +169,8 @@ export async function encodeConstructorParamsForImplementation(
|
||||
{
|
||||
contractName: "WETH9",
|
||||
},
|
||||
clientId,
|
||||
secretKey,
|
||||
);
|
||||
if (!caches.deploymentPresets["WETH9"]) {
|
||||
caches.deploymentPresets["WETH9"] = deploymentInfo;
|
||||
@@ -168,6 +192,8 @@ export async function encodeConstructorParamsForImplementation(
|
||||
{
|
||||
contractName: "ForwarderEOAOnly",
|
||||
},
|
||||
clientId,
|
||||
secretKey,
|
||||
);
|
||||
if (!caches.deploymentPresets["ForwarderEOAOnly"]) {
|
||||
caches.deploymentPresets["ForwarderEOAOnly"] = deploymentInfo;
|
||||
@@ -183,6 +209,8 @@ export async function encodeConstructorParamsForImplementation(
|
||||
{
|
||||
contractName: "Forwarder",
|
||||
},
|
||||
clientId,
|
||||
secretKey,
|
||||
);
|
||||
if (!caches.deploymentPresets["Forwarder"]) {
|
||||
caches.deploymentPresets["Forwarder"] = deploymentInfo;
|
||||
|
||||
@@ -14,13 +14,23 @@ export async function computeEOAForwarderAddress(
|
||||
provider: providers.Provider,
|
||||
storage: ThirdwebStorage,
|
||||
create2Factory?: string,
|
||||
clientId?: string,
|
||||
secretKey?: string,
|
||||
): Promise<string> {
|
||||
if (!create2Factory) {
|
||||
if (!create2Factory || create2Factory === "") {
|
||||
create2Factory = await getCreate2FactoryAddress(provider);
|
||||
}
|
||||
return (
|
||||
await computeDeploymentInfo("infra", provider, storage, create2Factory, {
|
||||
contractName: "ForwarderEOAOnly",
|
||||
})
|
||||
await computeDeploymentInfo(
|
||||
"infra",
|
||||
provider,
|
||||
storage,
|
||||
create2Factory,
|
||||
{
|
||||
contractName: "ForwarderEOAOnly",
|
||||
},
|
||||
clientId,
|
||||
secretKey,
|
||||
)
|
||||
).transaction.predictedAddress;
|
||||
}
|
||||
|
||||
@@ -14,13 +14,23 @@ export async function computeForwarderAddress(
|
||||
provider: providers.Provider,
|
||||
storage: ThirdwebStorage,
|
||||
create2Factory?: string,
|
||||
clientId?: string,
|
||||
secretKey?: string,
|
||||
): Promise<string> {
|
||||
if (!create2Factory) {
|
||||
if (!create2Factory || create2Factory === "") {
|
||||
create2Factory = await getCreate2FactoryAddress(provider);
|
||||
}
|
||||
return (
|
||||
await computeDeploymentInfo("infra", provider, storage, create2Factory, {
|
||||
contractName: "Forwarder",
|
||||
})
|
||||
await computeDeploymentInfo(
|
||||
"infra",
|
||||
provider,
|
||||
storage,
|
||||
create2Factory,
|
||||
{
|
||||
contractName: "Forwarder",
|
||||
},
|
||||
clientId,
|
||||
secretKey,
|
||||
)
|
||||
).transaction.predictedAddress;
|
||||
}
|
||||
|
||||
@@ -14,13 +14,23 @@ export async function computeNativeTokenAddress(
|
||||
provider: providers.Provider,
|
||||
storage: ThirdwebStorage,
|
||||
create2Factory?: string,
|
||||
clientId?: string,
|
||||
secretKey?: string,
|
||||
): Promise<string> {
|
||||
if (!create2Factory) {
|
||||
if (!create2Factory || create2Factory === "") {
|
||||
create2Factory = await getCreate2FactoryAddress(provider);
|
||||
}
|
||||
return (
|
||||
await computeDeploymentInfo("infra", provider, storage, create2Factory, {
|
||||
contractName: "WETH9",
|
||||
})
|
||||
await computeDeploymentInfo(
|
||||
"infra",
|
||||
provider,
|
||||
storage,
|
||||
create2Factory,
|
||||
{
|
||||
contractName: "WETH9",
|
||||
},
|
||||
clientId,
|
||||
secretKey,
|
||||
)
|
||||
).transaction.predictedAddress;
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ import { deployCreate2Factory } from "./deployCreate2Factory";
|
||||
import { convertParamValues } from "./convertParamValues";
|
||||
import { AbiInput } from "../../schema";
|
||||
import { getCreate2FactoryAddress } from "./getCreate2FactoryAddress";
|
||||
import { fetchPublishedContractFromPolygon } from "./fetchPublishedContractFromPolygon";
|
||||
|
||||
/**
|
||||
* Direct deploy a contract at a deterministic address, using Create2 method
|
||||
@@ -36,7 +37,7 @@ export async function directDeployDeterministic(
|
||||
constructorArgs: any[],
|
||||
saltForCreate2?: string,
|
||||
gasLimit: number = 7000000,
|
||||
) {
|
||||
): Promise<string> {
|
||||
invariant(signer.provider, "Provider is required");
|
||||
|
||||
const bytecodePrefixed = bytecode.startsWith("0x")
|
||||
@@ -97,6 +98,8 @@ export async function directDeployDeterministic(
|
||||
} else {
|
||||
throw new Error(`Contract already deployed at ${address}`);
|
||||
}
|
||||
|
||||
return address;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -118,13 +121,73 @@ export async function directDeployDeterministicWithUri(
|
||||
constructorArgs: any[],
|
||||
saltForCreate2?: string,
|
||||
gasLimit: number = 7000000,
|
||||
) {
|
||||
const { compilerMetadata } = await fetchAndCacheDeployMetadata(
|
||||
publishMetadataUri,
|
||||
storage,
|
||||
): Promise<string> {
|
||||
const { compilerMetadata, extendedMetadata } =
|
||||
await fetchAndCacheDeployMetadata(publishMetadataUri, storage);
|
||||
|
||||
invariant(
|
||||
extendedMetadata?.deployType === "standard",
|
||||
"Must be direct deploy",
|
||||
);
|
||||
|
||||
await directDeployDeterministic(
|
||||
return await directDeployDeterministic(
|
||||
compilerMetadata.bytecode,
|
||||
compilerMetadata.abi,
|
||||
signer,
|
||||
constructorArgs,
|
||||
saltForCreate2,
|
||||
gasLimit,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Direct deploy a contract at a deterministic address, using Create2 method
|
||||
* Address depends on the Create2 factory address and salt (if provided).
|
||||
*
|
||||
* @public
|
||||
*
|
||||
* @param contractName
|
||||
* @param publisherAddress
|
||||
* @param contractVersion
|
||||
* @param constructorArgs
|
||||
* @param signer
|
||||
* @param storage
|
||||
* @param clientId
|
||||
* @param secretKey
|
||||
* @param constructorArgs
|
||||
* @param saltForCreate2
|
||||
*/
|
||||
export async function directDeployDeterministicPublished(
|
||||
contractName: string,
|
||||
publisherAddress: string,
|
||||
contractVersion: string = "latest",
|
||||
constructorArgs: any[],
|
||||
signer: Signer,
|
||||
storage: ThirdwebStorage,
|
||||
clientId?: string,
|
||||
secretKey?: string,
|
||||
saltForCreate2?: string,
|
||||
gasLimit: number = 7000000,
|
||||
): Promise<string> {
|
||||
const publishMetadataUri = (
|
||||
await fetchPublishedContractFromPolygon(
|
||||
publisherAddress,
|
||||
contractName,
|
||||
contractVersion,
|
||||
storage,
|
||||
clientId,
|
||||
secretKey,
|
||||
)
|
||||
).metadataUri;
|
||||
const { compilerMetadata, extendedMetadata } =
|
||||
await fetchAndCacheDeployMetadata(publishMetadataUri, storage);
|
||||
|
||||
invariant(
|
||||
extendedMetadata?.deployType === "standard",
|
||||
"Must be direct deploy",
|
||||
);
|
||||
|
||||
return await directDeployDeterministic(
|
||||
compilerMetadata.bytecode,
|
||||
compilerMetadata.abi,
|
||||
signer,
|
||||
@@ -140,7 +203,7 @@ export async function predictAddressDeterministic(
|
||||
provider: providers.Provider,
|
||||
constructorArgs: any[],
|
||||
saltForCreate2?: string,
|
||||
) {
|
||||
): Promise<string> {
|
||||
const bytecodePrefixed = bytecode.startsWith("0x")
|
||||
? bytecode
|
||||
: `0x${bytecode}`;
|
||||
@@ -182,9 +245,50 @@ export async function predictAddressDeterministicWithUri(
|
||||
constructorArgs: any[],
|
||||
saltForCreate2?: string,
|
||||
): Promise<string> {
|
||||
const { compilerMetadata } = await fetchAndCacheDeployMetadata(
|
||||
publishMetadataUri,
|
||||
storage,
|
||||
const { compilerMetadata, extendedMetadata } =
|
||||
await fetchAndCacheDeployMetadata(publishMetadataUri, storage);
|
||||
|
||||
invariant(
|
||||
extendedMetadata?.deployType === "standard",
|
||||
"Must be direct deploy",
|
||||
);
|
||||
|
||||
return await predictAddressDeterministic(
|
||||
compilerMetadata.bytecode,
|
||||
compilerMetadata.abi,
|
||||
provider,
|
||||
constructorArgs,
|
||||
saltForCreate2,
|
||||
);
|
||||
}
|
||||
|
||||
export async function predictAddressDeterministicPublished(
|
||||
contractName: string,
|
||||
publisherAddress: string,
|
||||
contractVersion: string = "latest",
|
||||
constructorArgs: any[],
|
||||
provider: providers.Provider,
|
||||
storage: ThirdwebStorage,
|
||||
clientId?: string,
|
||||
secretKey?: string,
|
||||
saltForCreate2?: string,
|
||||
): Promise<string> {
|
||||
const publishMetadataUri = (
|
||||
await fetchPublishedContractFromPolygon(
|
||||
publisherAddress,
|
||||
contractName,
|
||||
contractVersion,
|
||||
storage,
|
||||
clientId,
|
||||
secretKey,
|
||||
)
|
||||
).metadataUri;
|
||||
const { compilerMetadata, extendedMetadata } =
|
||||
await fetchAndCacheDeployMetadata(publishMetadataUri, storage);
|
||||
|
||||
invariant(
|
||||
extendedMetadata?.deployType === "standard",
|
||||
"Must be direct deploy",
|
||||
);
|
||||
|
||||
return await predictAddressDeterministic(
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
import { Contract } from "ethers";
|
||||
import ContractPublisherAbi from "@thirdweb-dev/contracts-js/dist/abis/ContractPublisher.json";
|
||||
import type { ContractPublisher } from "@thirdweb-dev/contracts-js";
|
||||
import { getContractPublisherAddress } from "../../constants/addresses/getContractPublisherAddress";
|
||||
import { getChainProvider } from "../../constants/urls";
|
||||
|
||||
const uriCache: Record<string, string> = {};
|
||||
|
||||
const THIRDWEB_DEPLOYER = "0xdd99b75f095d0c4d5112aCe938e4e6ed962fb024";
|
||||
|
||||
export async function fetchAndCachePublishedContractURI(
|
||||
contractName: string,
|
||||
): Promise<string> {
|
||||
if (uriCache[contractName]) {
|
||||
return uriCache[contractName];
|
||||
}
|
||||
|
||||
const contract = new Contract(
|
||||
getContractPublisherAddress(),
|
||||
ContractPublisherAbi,
|
||||
getChainProvider("polygon", {}),
|
||||
) as ContractPublisher;
|
||||
|
||||
const model = await contract.getPublishedContract(
|
||||
THIRDWEB_DEPLOYER,
|
||||
contractName,
|
||||
);
|
||||
|
||||
if (!model) {
|
||||
throw new Error(
|
||||
`No published contract found for ${contractName} at version by '${THIRDWEB_DEPLOYER}'`,
|
||||
);
|
||||
}
|
||||
|
||||
const uri = model.publishMetadataUri;
|
||||
uriCache[contractName] = uri;
|
||||
|
||||
return uri;
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
import { Contract } from "ethers";
|
||||
import ContractPublisherAbi from "@thirdweb-dev/contracts-js/dist/abis/ContractPublisher.json";
|
||||
import type { ContractPublisher } from "@thirdweb-dev/contracts-js";
|
||||
import { getContractPublisherAddress } from "../../constants/addresses/getContractPublisherAddress";
|
||||
import { getChainProvider } from "../../constants/urls";
|
||||
import { AddressOrEns, PublishedContractSchema } from "../../schema";
|
||||
import { resolveAddress } from "../ens/resolveAddress";
|
||||
import invariant from "tiny-invariant";
|
||||
import { ThirdwebStorage } from "@thirdweb-dev/storage";
|
||||
import { fetchAndCacheDeployMetadata } from "./fetchAndCacheDeployMetadata";
|
||||
import { getSupportedChains } from "../../constants";
|
||||
import { Polygon } from "@thirdweb-dev/chains";
|
||||
|
||||
export const THIRDWEB_DEPLOYER = "0xdd99b75f095d0c4d5112aCe938e4e6ed962fb024";
|
||||
|
||||
export async function fetchPublishedContractFromPolygon(
|
||||
publisherAddress: AddressOrEns,
|
||||
contractName: string,
|
||||
version: string = "latest",
|
||||
storage: ThirdwebStorage,
|
||||
clientId?: string,
|
||||
secretKey?: string,
|
||||
) {
|
||||
const polygonChain = getSupportedChains().find((c) => c.chainId === 137);
|
||||
const chain = polygonChain || Polygon;
|
||||
const publisher = await resolveAddress(publisherAddress);
|
||||
const contract = new Contract(
|
||||
getContractPublisherAddress(),
|
||||
ContractPublisherAbi,
|
||||
getChainProvider(chain, { clientId, secretKey }),
|
||||
) as ContractPublisher;
|
||||
|
||||
let publishedContract;
|
||||
if (!version || version === "latest") {
|
||||
const model = await contract.getPublishedContract(publisher, contractName);
|
||||
publishedContract = PublishedContractSchema.parse({
|
||||
id: model.contractId,
|
||||
timestamp: model.publishTimestamp,
|
||||
metadataUri: model.publishMetadataUri,
|
||||
});
|
||||
} else {
|
||||
const allVersions = (
|
||||
await contract.getPublishedContractVersions(publisher, contractName)
|
||||
).map((c) => {
|
||||
return PublishedContractSchema.parse({
|
||||
id: c.contractId,
|
||||
timestamp: c.publishTimestamp,
|
||||
metadataUri: c.publishMetadataUri,
|
||||
});
|
||||
});
|
||||
|
||||
// get the metadata for each version
|
||||
const versionMetadata = await Promise.all(
|
||||
allVersions.map(async (c) => {
|
||||
return {
|
||||
name: c.id,
|
||||
publishedTimestamp: c.timestamp,
|
||||
publishedMetadata: await fetchAndCacheDeployMetadata(
|
||||
c.metadataUri,
|
||||
storage,
|
||||
),
|
||||
};
|
||||
}),
|
||||
);
|
||||
// find the version that matches the version string
|
||||
const versionMatch = versionMetadata.find(
|
||||
(metadata) =>
|
||||
metadata.publishedMetadata.extendedMetadata?.version === version,
|
||||
);
|
||||
invariant(versionMatch, "Contract version not found");
|
||||
// match the version back to the contract based on the published timestamp
|
||||
publishedContract = allVersions.find(
|
||||
(c) => c.timestamp === versionMatch.publishedTimestamp,
|
||||
);
|
||||
}
|
||||
|
||||
if (!publishedContract) {
|
||||
throw new Error(
|
||||
`No published contract found for ${contractName} at version by '${THIRDWEB_DEPLOYER}'`,
|
||||
);
|
||||
}
|
||||
|
||||
return publishedContract;
|
||||
}
|
||||
@@ -13,9 +13,9 @@ import {
|
||||
generateExtensionFunctions,
|
||||
generatePluginFunctions,
|
||||
} from "../plugin/generatePluginFunctions";
|
||||
import { getMetadataForPlugins } from "../plugin/getMetadataForPlugins";
|
||||
import { getMetadataForExtensions } from "../plugin/getMetadataForExtensions";
|
||||
import { Extension } from "../../types/extensions";
|
||||
import { fetchPublishedContractFromPolygon } from "./fetchPublishedContractFromPolygon";
|
||||
import invariant from "tiny-invariant";
|
||||
/**
|
||||
*
|
||||
* Returns txn data for keyless deploys as well as signer deploys.
|
||||
@@ -33,6 +33,8 @@ export async function getDeploymentInfo(
|
||||
storage: ThirdwebStorage,
|
||||
provider: providers.Provider,
|
||||
create2Factory?: string,
|
||||
clientId?: string,
|
||||
secretKey?: string,
|
||||
): Promise<DeploymentPreset[]> {
|
||||
caches.deploymentPresets = {};
|
||||
|
||||
@@ -42,18 +44,33 @@ export async function getDeploymentInfo(
|
||||
|
||||
const customParams: ConstructorParamMap = {};
|
||||
const finalDeploymentInfo: DeploymentPreset[] = [];
|
||||
const { compilerMetadata } = await fetchAndCacheDeployMetadata(
|
||||
metadataUri,
|
||||
storage,
|
||||
);
|
||||
const pluginMetadata = await getMetadataForPlugins(metadataUri, storage);
|
||||
const extensionMetadata = await getMetadataForExtensions(
|
||||
metadataUri,
|
||||
storage,
|
||||
);
|
||||
const { compilerMetadata, extendedMetadata } =
|
||||
await fetchAndCacheDeployMetadata(metadataUri, storage);
|
||||
const defaultExtensions = extendedMetadata?.defaultExtensions;
|
||||
|
||||
if (extendedMetadata?.routerType === "plugin" && defaultExtensions) {
|
||||
invariant(clientId || secretKey, "Require Client Id / Secret Key");
|
||||
const publishedExtensions = await Promise.all(
|
||||
defaultExtensions.map((e) => {
|
||||
return fetchPublishedContractFromPolygon(
|
||||
e.publisherAddress,
|
||||
e.extensionName,
|
||||
e.extensionVersion,
|
||||
storage,
|
||||
clientId,
|
||||
secretKey,
|
||||
);
|
||||
}),
|
||||
);
|
||||
|
||||
const pluginMetadata = (
|
||||
await Promise.all(
|
||||
publishedExtensions.map(async (c) => {
|
||||
return fetchAndCacheDeployMetadata(c.metadataUri, storage);
|
||||
}),
|
||||
)
|
||||
).map((fetchedMetadata) => fetchedMetadata.compilerMetadata);
|
||||
|
||||
// if pluginMetadata is not empty, then it's a plugin-pattern router contract
|
||||
if (pluginMetadata.length > 0) {
|
||||
// get deployment info for all plugins
|
||||
const pluginDeploymentInfo = await Promise.all(
|
||||
pluginMetadata.map(async (metadata) => {
|
||||
@@ -63,6 +80,8 @@ export async function getDeploymentInfo(
|
||||
storage,
|
||||
create2FactoryAddress,
|
||||
{ metadata: metadata },
|
||||
clientId,
|
||||
secretKey,
|
||||
);
|
||||
return info;
|
||||
}),
|
||||
@@ -88,6 +107,8 @@ export async function getDeploymentInfo(
|
||||
contractName: "PluginMap",
|
||||
constructorParams: { _pluginsToAdd: { value: mapInput } },
|
||||
},
|
||||
clientId,
|
||||
secretKey,
|
||||
);
|
||||
|
||||
// address of PluginMap is input for MarketplaceV3's constructor
|
||||
@@ -96,7 +117,29 @@ export async function getDeploymentInfo(
|
||||
};
|
||||
|
||||
finalDeploymentInfo.push(...pluginDeploymentInfo, pluginMapTransaction);
|
||||
} else if (extensionMetadata.length > 0) {
|
||||
} else if (extendedMetadata?.routerType === "dynamic" && defaultExtensions) {
|
||||
invariant(clientId || secretKey, "Require Client Id / Secret Key");
|
||||
const publishedExtensions = await Promise.all(
|
||||
defaultExtensions.map((e) => {
|
||||
return fetchPublishedContractFromPolygon(
|
||||
e.publisherAddress,
|
||||
e.extensionName,
|
||||
e.extensionVersion,
|
||||
storage,
|
||||
clientId,
|
||||
secretKey,
|
||||
);
|
||||
}),
|
||||
);
|
||||
|
||||
const extensionMetadata = (
|
||||
await Promise.all(
|
||||
publishedExtensions.map(async (c) => {
|
||||
return fetchAndCacheDeployMetadata(c.metadataUri, storage);
|
||||
}),
|
||||
)
|
||||
).map((fetchedMetadata) => fetchedMetadata.compilerMetadata);
|
||||
|
||||
// get deployment info for all extensions
|
||||
const extensionDeploymentInfo = await Promise.all(
|
||||
extensionMetadata.map(async (metadata) => {
|
||||
@@ -106,6 +149,8 @@ export async function getDeploymentInfo(
|
||||
storage,
|
||||
create2FactoryAddress,
|
||||
{ metadata: metadata },
|
||||
clientId,
|
||||
secretKey,
|
||||
);
|
||||
return info;
|
||||
}),
|
||||
@@ -143,6 +188,8 @@ export async function getDeploymentInfo(
|
||||
metadata: compilerMetadata,
|
||||
constructorParams: customParams,
|
||||
},
|
||||
clientId,
|
||||
secretKey,
|
||||
);
|
||||
|
||||
// get clone factory
|
||||
@@ -152,6 +199,8 @@ export async function getDeploymentInfo(
|
||||
storage,
|
||||
create2FactoryAddress,
|
||||
{ contractName: "TWCloneFactory" },
|
||||
clientId,
|
||||
secretKey,
|
||||
);
|
||||
|
||||
finalDeploymentInfo.push(factoryInfo);
|
||||
|
||||
+26
-5
@@ -3,8 +3,10 @@ import { BytesLike } from "ethers";
|
||||
import invariant from "tiny-invariant";
|
||||
import { getChainProvider } from "../../constants/urls";
|
||||
import { ConstructorParamMap } from "../../types/any-evm/deploy-data";
|
||||
import { getMetadataForPlugins } from "../plugin/getMetadataForPlugins";
|
||||
import { fetchAndCachePublishedContractURI } from "./fetchAndCachePublishedContractURI";
|
||||
import {
|
||||
THIRDWEB_DEPLOYER,
|
||||
fetchPublishedContractFromPolygon,
|
||||
} from "./fetchPublishedContractFromPolygon";
|
||||
import { fetchAndCacheDeployMetadata } from "./fetchAndCacheDeployMetadata";
|
||||
import { getCreate2FactoryAddress } from "./getCreate2FactoryAddress";
|
||||
import { encodeConstructorParamsForImplementation } from "./computeDeploymentInfo";
|
||||
@@ -21,6 +23,7 @@ export async function getEncodedConstructorParamsForThirdwebContract(
|
||||
contractName: string,
|
||||
chainId: number,
|
||||
storage: ThirdwebStorage,
|
||||
contractVersion: string = "latest",
|
||||
clientId?: string,
|
||||
secretKey?: string,
|
||||
constructorParamMap?: ConstructorParamMap,
|
||||
@@ -29,22 +32,38 @@ export async function getEncodedConstructorParamsForThirdwebContract(
|
||||
clientId,
|
||||
secretKey,
|
||||
});
|
||||
const publishUri = await fetchAndCachePublishedContractURI(contractName);
|
||||
const publishedContract = await fetchPublishedContractFromPolygon(
|
||||
THIRDWEB_DEPLOYER,
|
||||
contractName,
|
||||
contractVersion,
|
||||
storage,
|
||||
clientId,
|
||||
secretKey,
|
||||
);
|
||||
const publishUri = publishedContract.metadataUri;
|
||||
const metadata = await fetchAndCacheDeployMetadata(publishUri, storage);
|
||||
const create2Factory = await getCreate2FactoryAddress(provider);
|
||||
invariant(create2Factory, "Thirdweb stack not found");
|
||||
|
||||
const pluginMetadata = await getMetadataForPlugins(publishUri, storage);
|
||||
const { extendedMetadata } = await fetchAndCacheDeployMetadata(
|
||||
publishUri,
|
||||
storage,
|
||||
);
|
||||
|
||||
let encodedArgs;
|
||||
|
||||
// if pluginMetadata is not empty, then it's a plugin-pattern router contract
|
||||
if (pluginMetadata.length > 0) {
|
||||
if (
|
||||
extendedMetadata?.routerType === "plugin" ||
|
||||
extendedMetadata?.routerType === "dynamic"
|
||||
) {
|
||||
const deploymentInfo = await getDeploymentInfo(
|
||||
publishUri,
|
||||
storage,
|
||||
provider,
|
||||
create2Factory,
|
||||
clientId,
|
||||
secretKey,
|
||||
);
|
||||
encodedArgs = deploymentInfo.find(
|
||||
(contract) => contract.type === "implementation",
|
||||
@@ -56,6 +75,8 @@ export async function getEncodedConstructorParamsForThirdwebContract(
|
||||
storage,
|
||||
create2Factory,
|
||||
constructorParamMap,
|
||||
clientId,
|
||||
secretKey,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@ export async function getThirdwebContractAddress(
|
||||
contractName: string,
|
||||
chainId: number,
|
||||
storage: ThirdwebStorage,
|
||||
contractVersion: string = "latest",
|
||||
clientId?: string,
|
||||
secretKey?: string,
|
||||
): Promise<string> {
|
||||
@@ -27,6 +28,7 @@ export async function getThirdwebContractAddress(
|
||||
contractName,
|
||||
chainId,
|
||||
storage,
|
||||
contractVersion,
|
||||
clientId,
|
||||
secretKey,
|
||||
);
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
import { ThirdwebStorage } from "@thirdweb-dev/storage";
|
||||
import invariant from "tiny-invariant";
|
||||
import { getChainProvider } from "../../constants/urls";
|
||||
import { getMetadataForPlugins } from "../plugin/getMetadataForPlugins";
|
||||
import { fetchAndCachePublishedContractURI } from "./fetchAndCachePublishedContractURI";
|
||||
import {
|
||||
THIRDWEB_DEPLOYER,
|
||||
fetchPublishedContractFromPolygon,
|
||||
} from "./fetchPublishedContractFromPolygon";
|
||||
import { getCreate2FactoryAddress } from "./getCreate2FactoryAddress";
|
||||
import { computeDeploymentInfo } from "./computeDeploymentInfo";
|
||||
import { getDeploymentInfo } from "./getDeploymentInfo";
|
||||
import { fetchAndCacheDeployMetadata } from "./fetchAndCacheDeployMetadata";
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -18,6 +21,7 @@ export async function predictThirdwebContractAddress(
|
||||
contractName: string,
|
||||
chainId: number,
|
||||
storage: ThirdwebStorage,
|
||||
contractVersion: string = "latest",
|
||||
clientId?: string,
|
||||
secretKey?: string,
|
||||
): Promise<string> {
|
||||
@@ -25,19 +29,34 @@ export async function predictThirdwebContractAddress(
|
||||
clientId,
|
||||
secretKey,
|
||||
});
|
||||
const publishUri = await fetchAndCachePublishedContractURI(contractName);
|
||||
const publishedContract = await fetchPublishedContractFromPolygon(
|
||||
THIRDWEB_DEPLOYER,
|
||||
contractName,
|
||||
contractVersion,
|
||||
storage,
|
||||
clientId,
|
||||
secretKey,
|
||||
);
|
||||
const publishUri = publishedContract.metadataUri;
|
||||
const create2Factory = await getCreate2FactoryAddress(provider);
|
||||
invariant(create2Factory, "Thirdweb stack not found");
|
||||
|
||||
const pluginMetadata = await getMetadataForPlugins(publishUri, storage);
|
||||
const { extendedMetadata } = await fetchAndCacheDeployMetadata(
|
||||
publishUri,
|
||||
storage,
|
||||
);
|
||||
|
||||
// if pluginMetadata is not empty, then it's a plugin-pattern router contract
|
||||
if (pluginMetadata.length > 0) {
|
||||
if (
|
||||
extendedMetadata?.routerType === "plugin" ||
|
||||
extendedMetadata?.routerType === "dynamic"
|
||||
) {
|
||||
const deploymentInfo = await getDeploymentInfo(
|
||||
publishUri,
|
||||
storage,
|
||||
provider,
|
||||
create2Factory,
|
||||
clientId,
|
||||
secretKey,
|
||||
);
|
||||
|
||||
const implementation = deploymentInfo.find(
|
||||
@@ -54,6 +73,8 @@ export async function predictThirdwebContractAddress(
|
||||
storage,
|
||||
create2Factory,
|
||||
{ contractName: contractName },
|
||||
clientId,
|
||||
secretKey,
|
||||
);
|
||||
|
||||
return implementation.transaction.predictedAddress;
|
||||
|
||||
@@ -2,7 +2,7 @@ import { FeatureName } from "../../constants/contract-features";
|
||||
import { ContractWrapper } from "../../core/classes/contract-wrapper";
|
||||
import { AbiSchema } from "../../schema/contracts/custom";
|
||||
import { BaseContract } from "ethers";
|
||||
import { isFeatureEnabled } from "./isFeatureEnabled";
|
||||
import { isExtensionEnabled } from "./isFeatureEnabled";
|
||||
|
||||
/**
|
||||
* Type guard for contractWrappers depending on passed feature name
|
||||
@@ -14,5 +14,5 @@ export function detectContractFeature<T extends BaseContract>(
|
||||
contractWrapper: ContractWrapper<BaseContract>,
|
||||
featureName: FeatureName,
|
||||
): contractWrapper is ContractWrapper<T> {
|
||||
return isFeatureEnabled(AbiSchema.parse(contractWrapper.abi), featureName);
|
||||
return isExtensionEnabled(AbiSchema.parse(contractWrapper.abi), featureName);
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import {
|
||||
SUPPORTED_FEATURES,
|
||||
} from "../../constants/contract-features";
|
||||
import { AbiInput } from "../../schema/contracts/custom";
|
||||
import { hasMatchingAbi } from "./hasMatchingAbi";
|
||||
import { hasMatchingAbi, matchesAbiFromBytecode } from "./hasMatchingAbi";
|
||||
|
||||
/**
|
||||
* Processes ALL supported features and sets whether the passed in abi supports each individual feature
|
||||
@@ -31,6 +31,24 @@ export function detectFeatures(
|
||||
return results;
|
||||
}
|
||||
|
||||
export function detectFeaturesFromBytecode(
|
||||
bytecode: string,
|
||||
features: Record<string, Feature> = SUPPORTED_FEATURES,
|
||||
): Record<string, FeatureWithEnabled> {
|
||||
const results: Record<string, FeatureWithEnabled> = {};
|
||||
for (const featureKey in features) {
|
||||
const feature = features[featureKey];
|
||||
const enabled = matchesAbiFromBytecode(bytecode, feature.abis);
|
||||
const childResults = detectFeaturesFromBytecode(bytecode, feature.features);
|
||||
results[featureKey] = {
|
||||
...feature,
|
||||
features: childResults,
|
||||
enabled,
|
||||
} as FeatureWithEnabled;
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* @param abi
|
||||
|
||||
@@ -3,7 +3,8 @@ import {
|
||||
FeatureWithEnabled,
|
||||
} from "../../constants/contract-features";
|
||||
import { AbiInput } from "../../schema/contracts/custom";
|
||||
import { detectFeatures } from "./detectFeatures";
|
||||
import { joinABIs } from "../plugin/joinABIs";
|
||||
import { detectFeatures, detectFeaturesFromBytecode } from "./detectFeatures";
|
||||
import { extractFeatures } from "./extractFeatures";
|
||||
|
||||
/**
|
||||
@@ -19,6 +20,24 @@ export function getAllDetectedFeatures(abi: AbiInput): FeatureWithEnabled[] {
|
||||
return features;
|
||||
}
|
||||
|
||||
export function getAllDetectedExtensionsFromBytecode(
|
||||
bytecode: string,
|
||||
): FeatureWithEnabled[] {
|
||||
const features: FeatureWithEnabled[] = [];
|
||||
extractFeatures(detectFeaturesFromBytecode(bytecode), features);
|
||||
return features;
|
||||
}
|
||||
|
||||
export function constructAbiFromBytecode(bytecode: string): AbiInput {
|
||||
let extensions = getAllDetectedExtensionsFromBytecode(bytecode);
|
||||
// special deduping for ERC721 and ERC20
|
||||
if (extensions.find((f) => f.name === "ERC721")) {
|
||||
extensions = extensions.filter((f) => f.name !== "ERC20");
|
||||
}
|
||||
const abi = joinABIs(extensions.map((f) => joinABIs(f.abis as any)));
|
||||
return abi;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all the detected extensions in the abi
|
||||
* @param abi - parsed array of abi entries
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { Interface } from "ethers/lib/utils";
|
||||
import { AbiInput } from "../../schema/contracts/custom";
|
||||
import { extractFunctionsFromAbi } from "./extractFunctionsFromAbi";
|
||||
|
||||
@@ -38,3 +39,20 @@ export function hasMatchingAbi(
|
||||
});
|
||||
return intersection.length === interfaceFn.length;
|
||||
}
|
||||
|
||||
export function matchesAbiFromBytecode(
|
||||
contractBytecode: string,
|
||||
featureAbis: readonly AbiInput[],
|
||||
) {
|
||||
const interfaces = featureAbis.map((abi) => new Interface(abi));
|
||||
const selectors = interfaces.flatMap((i) => {
|
||||
return Object.values(i.functions).map((fn) =>
|
||||
Number(i.getSighash(fn)).toString(16),
|
||||
);
|
||||
});
|
||||
const uniqueSelectors = [...new Set(selectors)];
|
||||
// checks that all unique selectors are found in the bytecode
|
||||
return uniqueSelectors.every((selector) =>
|
||||
contractBytecode.includes(selector),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -11,6 +11,22 @@ export async function resolveContractUriFromAddress(
|
||||
address: string,
|
||||
provider: providers.Provider,
|
||||
): Promise<string | undefined> {
|
||||
const bytecode = await resolveImplementationBytecode(address, provider);
|
||||
return extractIPFSHashFromBytecode(bytecode);
|
||||
}
|
||||
|
||||
export async function resolveContractUriAndBytecode(
|
||||
address: string,
|
||||
provider: providers.Provider,
|
||||
): Promise<{ uri: string | undefined; bytecode: string }> {
|
||||
const bytecode = await resolveImplementationBytecode(address, provider);
|
||||
return { uri: extractIPFSHashFromBytecode(bytecode), bytecode };
|
||||
}
|
||||
|
||||
export async function resolveImplementationBytecode(
|
||||
address: string,
|
||||
provider: providers.Provider,
|
||||
): Promise<string> {
|
||||
let bytecode;
|
||||
try {
|
||||
bytecode = await provider.getCode(address);
|
||||
@@ -26,10 +42,11 @@ export async function resolveContractUriFromAddress(
|
||||
}
|
||||
|
||||
try {
|
||||
// TODO support other types of proxies
|
||||
const implementationAddress =
|
||||
extractMinimalProxyImplementationAddress(bytecode);
|
||||
if (implementationAddress) {
|
||||
return await resolveContractUriFromAddress(
|
||||
return await resolveImplementationBytecode(
|
||||
implementationAddress,
|
||||
provider,
|
||||
);
|
||||
@@ -51,7 +68,7 @@ export async function resolveContractUriFromAddress(
|
||||
utils.isAddress(implementationAddress) &&
|
||||
implementationAddress !== constants.AddressZero
|
||||
) {
|
||||
return await resolveContractUriFromAddress(
|
||||
return await resolveImplementationBytecode(
|
||||
implementationAddress,
|
||||
provider,
|
||||
);
|
||||
@@ -59,6 +76,8 @@ export async function resolveContractUriFromAddress(
|
||||
} catch (e) {
|
||||
// ignore
|
||||
}
|
||||
// TODO support other types of proxies
|
||||
return await extractIPFSHashFromBytecode(bytecode);
|
||||
if (!bytecode) {
|
||||
throw new Error(`Error fetching bytecode for ${address}`);
|
||||
}
|
||||
return bytecode;
|
||||
}
|
||||
|
||||
@@ -5,17 +5,21 @@ import {
|
||||
} from "../schema/contracts/custom";
|
||||
import type { ThirdwebStorage } from "@thirdweb-dev/storage";
|
||||
|
||||
const CONTRACT_METADATA_TIMEOUT_SEC = 2;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* @param compilerMetadataUri
|
||||
* @param storage
|
||||
*/
|
||||
|
||||
export async function fetchContractMetadata(
|
||||
compilerMetadataUri: string,
|
||||
storage: ThirdwebStorage,
|
||||
): Promise<PublishedMetadata> {
|
||||
const metadata = await storage.downloadJSON(compilerMetadataUri);
|
||||
// short timeout to avoid hanging on unpinned contract metadata CIDs
|
||||
const metadata = await storage.downloadJSON(compilerMetadataUri, {
|
||||
timeoutInSeconds: CONTRACT_METADATA_TIMEOUT_SEC,
|
||||
});
|
||||
if (!metadata || !metadata.output) {
|
||||
throw new Error(
|
||||
`Could not resolve metadata for contract at ${compilerMetadataUri}`,
|
||||
|
||||
@@ -3,6 +3,7 @@ export * from "./snapshots";
|
||||
export * from "./role";
|
||||
export * from "./metadata-resolver";
|
||||
export * from "./gas-price";
|
||||
export * from "./fetchContractMetadata";
|
||||
|
||||
// feature detection
|
||||
export * from "./feature-detection/matchesPrebuiltAbi";
|
||||
@@ -73,7 +74,7 @@ export * from "./any-evm-utils/deployWithThrowawayDeployer";
|
||||
export * from "./any-evm-utils/computeDeploymentInfo";
|
||||
export * from "./any-evm-utils/convertParamValues";
|
||||
export * from "./any-evm-utils/getCreate2FactoryDeploymentInfo";
|
||||
export * from "./any-evm-utils/fetchAndCachePublishedContractURI";
|
||||
export * from "./any-evm-utils/fetchPublishedContractFromPolygon";
|
||||
export * from "./any-evm-utils/fetchAndCacheDeployMetadata";
|
||||
export * from "./any-evm-utils/estimateGasForDeploy";
|
||||
export * from "./any-evm-utils/createTransactionBatches";
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Abi, PublishedMetadata } from "../schema/contracts/custom";
|
||||
import { Address } from "../schema/shared/Address";
|
||||
import { resolveContractUriFromAddress } from "./feature-detection/resolveContractUriFromAddress";
|
||||
import { resolveContractUriAndBytecode } from "./feature-detection/resolveContractUriFromAddress";
|
||||
import { ThirdwebStorage } from "@thirdweb-dev/storage";
|
||||
import { Contract, providers } from "ethers";
|
||||
import { fetchContractMetadata } from "./fetchContractMetadata";
|
||||
@@ -8,7 +8,9 @@ import TWRegistryABI from "@thirdweb-dev/contracts-js/dist/abis/TWMultichainRegi
|
||||
import { getMultichainRegistryAddress } from "../constants/addresses/getMultichainRegistryAddress";
|
||||
import { getChainProvider } from "../constants/urls";
|
||||
import type { TWMultichainRegistryLogic } from "@thirdweb-dev/contracts-js";
|
||||
import { constructAbiFromBytecode } from "./feature-detection/getAllDetectedFeatures";
|
||||
import { SDKOptions } from "../schema";
|
||||
import { Polygon } from "@thirdweb-dev/chains";
|
||||
|
||||
// Internal static cache
|
||||
const metadataCache: Record<string, PublishedMetadata> = {};
|
||||
@@ -41,61 +43,92 @@ export async function fetchContractMetadataFromAddress(
|
||||
provider: providers.Provider,
|
||||
storage: ThirdwebStorage,
|
||||
sdkOptions: SDKOptions = {},
|
||||
) {
|
||||
const chainId = (await provider.getNetwork()).chainId;
|
||||
): Promise<PublishedMetadata> {
|
||||
const chainId = (await provider.getNetwork()).chainId; // TODO resolve from sdk network
|
||||
const cached = getFromCache(address, chainId);
|
||||
if (cached) {
|
||||
return cached;
|
||||
}
|
||||
let metadata: PublishedMetadata | undefined;
|
||||
try {
|
||||
const compilerMetadataUri = await resolveContractUriFromAddress(
|
||||
address,
|
||||
provider,
|
||||
);
|
||||
if (!compilerMetadataUri) {
|
||||
throw new Error(`Could not resolve metadata for contract at ${address}`);
|
||||
}
|
||||
metadata = await fetchContractMetadata(compilerMetadataUri, storage);
|
||||
} catch (e) {
|
||||
console.debug(
|
||||
"Contract Metadata not found on IPFS, defaulting to onchain registry. Original error:",
|
||||
(e as any)?.message,
|
||||
);
|
||||
try {
|
||||
// try from multichain registry
|
||||
if (!multichainRegistry) {
|
||||
// TODO enforce always passing sdk options for clientId/secretKey
|
||||
multichainRegistry = new Contract(
|
||||
getMultichainRegistryAddress(),
|
||||
TWRegistryABI,
|
||||
getChainProvider("polygon", sdkOptions),
|
||||
) as TWMultichainRegistryLogic;
|
||||
}
|
||||
|
||||
const importedUri = await multichainRegistry.getMetadataUri(
|
||||
chainId,
|
||||
address,
|
||||
// we can't race here, because the contract URI might resolve first with a non pinned URI
|
||||
const [ipfsData, registryData] = await Promise.all([
|
||||
resolveContractUriAndBytecode(address, provider).catch(() => undefined),
|
||||
getMetadataUriFromMultichainRegistry(address, chainId, sdkOptions)
|
||||
.then((uri) => {
|
||||
if (!uri) {
|
||||
return undefined;
|
||||
}
|
||||
return {
|
||||
uri,
|
||||
bytecode: "",
|
||||
};
|
||||
})
|
||||
.catch(() => undefined),
|
||||
]);
|
||||
const bytecode = ipfsData?.bytecode;
|
||||
const metadataUri = registryData?.uri || ipfsData?.uri;
|
||||
if (!metadataUri && !bytecode) {
|
||||
throw new Error(
|
||||
`Could not fetch bytecode for contract at ${address} on chain ${chainId}, double check that the address and chainId are correct.`,
|
||||
);
|
||||
}
|
||||
try {
|
||||
metadata = await fetchContractMetadata(metadataUri, storage);
|
||||
} catch (e) {
|
||||
// Don't warn here, its common to not have IPFS metadata for a contract, fallback to bytecode
|
||||
}
|
||||
|
||||
if (!metadata && bytecode) {
|
||||
const abi = constructAbiFromBytecode(bytecode);
|
||||
if (abi && abi.length > 0) {
|
||||
console.warn(
|
||||
`Contract metadata could only be partially resolved, some contract functions might be unavailable. Try importing the contract by visiting: https://thirdweb.com/${chainId}/${address}`,
|
||||
);
|
||||
if (!importedUri) {
|
||||
throw new Error(
|
||||
`Could not resolve metadata for contract at ${address}`,
|
||||
);
|
||||
}
|
||||
metadata = await fetchContractMetadata(importedUri, storage);
|
||||
} catch (err) {
|
||||
throw new Error(`Could not resolve metadata for contract at ${address}`);
|
||||
// return partial ABI
|
||||
metadata = {
|
||||
name: "Unimported Contract",
|
||||
abi: abi as Abi,
|
||||
metadata: {},
|
||||
info: {},
|
||||
licenses: [],
|
||||
isPartialAbi: true,
|
||||
};
|
||||
// return without caching
|
||||
return metadata;
|
||||
}
|
||||
}
|
||||
|
||||
if (!metadata) {
|
||||
throw new Error(
|
||||
`No ABI found for this contract. Try importing it by visiting: https://thirdweb.com/${chainId}/${address}`,
|
||||
`Could not resolve contract. Try importing it by visiting: https://thirdweb.com/${chainId}/${address}`,
|
||||
);
|
||||
}
|
||||
putInCache(address, chainId, metadata);
|
||||
return metadata;
|
||||
}
|
||||
|
||||
async function getMetadataUriFromMultichainRegistry(
|
||||
address: string,
|
||||
chainId: number,
|
||||
sdkOptions: SDKOptions,
|
||||
) {
|
||||
if (!multichainRegistry) {
|
||||
const polygonChain = sdkOptions?.supportedChains?.find(
|
||||
(c) => c.chainId === 137,
|
||||
);
|
||||
const chain = polygonChain || Polygon;
|
||||
multichainRegistry = new Contract(
|
||||
getMultichainRegistryAddress(),
|
||||
TWRegistryABI,
|
||||
getChainProvider(chain, sdkOptions),
|
||||
) as TWMultichainRegistryLogic;
|
||||
}
|
||||
|
||||
const importedUri = await multichainRegistry.getMetadataUri(chainId, address);
|
||||
return importedUri;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* @param address
|
||||
|
||||
@@ -27,7 +27,9 @@ export function generatePluginFunctions(
|
||||
const pluginFunctions: Plugin[] = [];
|
||||
// TODO - filter out common functions like _msgSender(), contractType(), etc.
|
||||
for (const fnFragment of Object.values(pluginInterface.functions)) {
|
||||
const fn = pluginInterface.getFunction(fnFragment.name);
|
||||
const fn = pluginInterface.getFunction(
|
||||
pluginInterface.getSighash(fnFragment),
|
||||
);
|
||||
if (fn.name.includes("_")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -29,11 +29,11 @@ export async function getCompositePluginABI(
|
||||
AbiSchema.parse(abi),
|
||||
"PluginRouter",
|
||||
);
|
||||
const isExtensionRouter: boolean = isFeatureEnabled(
|
||||
const isbaseRouter: boolean = isFeatureEnabled(
|
||||
AbiSchema.parse(abi),
|
||||
"ExtensionRouter",
|
||||
"DynamicContract",
|
||||
);
|
||||
if (isExtensionRouter) {
|
||||
if (isbaseRouter) {
|
||||
const contract = new ContractWrapper(
|
||||
provider,
|
||||
address,
|
||||
|
||||
@@ -1,74 +0,0 @@
|
||||
import { getAllExtensionsAbi } from "../../constants/thirdweb-features";
|
||||
import { ContractWrapper } from "../../core/classes/contract-wrapper";
|
||||
import {
|
||||
AbiSchema,
|
||||
PreDeployMetadataFetched,
|
||||
} from "../../schema/contracts/custom";
|
||||
import { isFeatureEnabled } from "../feature-detection/isFeatureEnabled";
|
||||
import { ThirdwebStorage } from "@thirdweb-dev/storage";
|
||||
import { getChainProvider } from "../../constants/urls";
|
||||
import { fetchAndCachePublishedContractURI } from "../any-evm-utils/fetchAndCachePublishedContractURI";
|
||||
import { fetchAndCacheDeployMetadata } from "../any-evm-utils/fetchAndCacheDeployMetadata";
|
||||
import { Extension } from "../../types/extensions";
|
||||
|
||||
export async function getMetadataForExtensions(
|
||||
publishedMetadataUri: string,
|
||||
storage: ThirdwebStorage,
|
||||
): Promise<PreDeployMetadataFetched[]> {
|
||||
let extensionMetadata: PreDeployMetadataFetched[] = [];
|
||||
|
||||
const { compilerMetadata, extendedMetadata } =
|
||||
await fetchAndCacheDeployMetadata(publishedMetadataUri, storage);
|
||||
// check if contract is extension-pattern
|
||||
const isExtensionRouter: boolean = isFeatureEnabled(
|
||||
AbiSchema.parse(compilerMetadata.abi),
|
||||
"ExtensionRouter",
|
||||
);
|
||||
|
||||
if (isExtensionRouter) {
|
||||
if (
|
||||
extendedMetadata &&
|
||||
extendedMetadata.factoryDeploymentData?.implementationAddresses
|
||||
) {
|
||||
const implementationsAddresses = Object.entries(
|
||||
extendedMetadata.factoryDeploymentData.implementationAddresses,
|
||||
);
|
||||
try {
|
||||
const entry = implementationsAddresses.find(
|
||||
([, implementation]) => implementation !== "",
|
||||
);
|
||||
const [network, implementation] = entry ? entry : [];
|
||||
if (network && implementation) {
|
||||
const provider = getChainProvider(parseInt(network), {});
|
||||
const contract = new ContractWrapper(
|
||||
provider,
|
||||
implementation,
|
||||
getAllExtensionsAbi,
|
||||
{},
|
||||
storage,
|
||||
);
|
||||
|
||||
const extensions = await contract.call("getAllExtensions");
|
||||
|
||||
const extensionNames: string[] = Array.from(
|
||||
new Set(extensions.map((item: Extension) => item.metadata.name)),
|
||||
);
|
||||
|
||||
const extensionUris = await Promise.all(
|
||||
extensionNames.map((name) => {
|
||||
return fetchAndCachePublishedContractURI(name);
|
||||
}),
|
||||
);
|
||||
extensionMetadata = (
|
||||
await Promise.all(
|
||||
extensionUris.map(async (uri) => {
|
||||
return fetchAndCacheDeployMetadata(uri, storage);
|
||||
}),
|
||||
)
|
||||
).map((fetchedMetadata) => fetchedMetadata.compilerMetadata);
|
||||
}
|
||||
} catch {}
|
||||
}
|
||||
}
|
||||
return extensionMetadata;
|
||||
}
|
||||
@@ -1,91 +0,0 @@
|
||||
import { getAllPluginsAbi } from "../../constants/thirdweb-features";
|
||||
import { ContractWrapper } from "../../core/classes/contract-wrapper";
|
||||
import {
|
||||
AbiSchema,
|
||||
PreDeployMetadataFetched,
|
||||
} from "../../schema/contracts/custom";
|
||||
import { isFeatureEnabled } from "../feature-detection/isFeatureEnabled";
|
||||
import { fetchContractMetadataFromAddress } from "../metadata-resolver";
|
||||
import { ThirdwebStorage } from "@thirdweb-dev/storage";
|
||||
import { Plugin } from "../../types/plugins";
|
||||
import { getChainProvider } from "../../constants/urls";
|
||||
import { fetchAndCachePublishedContractURI } from "../any-evm-utils/fetchAndCachePublishedContractURI";
|
||||
import { fetchAndCacheDeployMetadata } from "../any-evm-utils/fetchAndCacheDeployMetadata";
|
||||
|
||||
export async function getMetadataForPlugins(
|
||||
publishedMetadataUri: string,
|
||||
storage: ThirdwebStorage,
|
||||
): Promise<PreDeployMetadataFetched[]> {
|
||||
let pluginMetadata: PreDeployMetadataFetched[] = [];
|
||||
|
||||
const { compilerMetadata, extendedMetadata } =
|
||||
await fetchAndCacheDeployMetadata(publishedMetadataUri, storage);
|
||||
// check if contract is plugin-pattern
|
||||
const isPluginRouter: boolean = isFeatureEnabled(
|
||||
AbiSchema.parse(compilerMetadata.abi),
|
||||
"PluginRouter",
|
||||
);
|
||||
|
||||
if (isPluginRouter) {
|
||||
if (
|
||||
extendedMetadata &&
|
||||
extendedMetadata.factoryDeploymentData?.implementationAddresses
|
||||
) {
|
||||
const implementationsAddresses = Object.entries(
|
||||
extendedMetadata.factoryDeploymentData.implementationAddresses,
|
||||
);
|
||||
|
||||
try {
|
||||
const entry = implementationsAddresses.find(
|
||||
([, implementation]) => implementation !== "",
|
||||
);
|
||||
const [network, implementation] = entry ? entry : [];
|
||||
if (network && implementation) {
|
||||
const provider = getChainProvider(parseInt(network), {});
|
||||
const contract = new ContractWrapper(
|
||||
provider,
|
||||
implementation,
|
||||
getAllPluginsAbi,
|
||||
{},
|
||||
storage,
|
||||
);
|
||||
|
||||
const pluginMap = await contract.call("getAllPlugins");
|
||||
|
||||
// get extension addresses
|
||||
const allPlugins = pluginMap.map(
|
||||
(item: Plugin) => item.pluginAddress,
|
||||
);
|
||||
const pluginAddresses = Array.from(new Set(allPlugins));
|
||||
|
||||
const pluginNames = (
|
||||
await Promise.all(
|
||||
pluginAddresses.map(async (address) => {
|
||||
const metadata = fetchContractMetadataFromAddress(
|
||||
address as string,
|
||||
provider,
|
||||
storage,
|
||||
);
|
||||
return metadata;
|
||||
}),
|
||||
)
|
||||
).map((metadata) => metadata.name);
|
||||
|
||||
const pluginUris = await Promise.all(
|
||||
pluginNames.map((name) => {
|
||||
return fetchAndCachePublishedContractURI(name);
|
||||
}),
|
||||
);
|
||||
pluginMetadata = (
|
||||
await Promise.all(
|
||||
pluginUris.map(async (uri) => {
|
||||
return fetchAndCacheDeployMetadata(uri, storage);
|
||||
}),
|
||||
)
|
||||
).map((fetchedMetadata) => fetchedMetadata.compilerMetadata);
|
||||
}
|
||||
} catch {}
|
||||
}
|
||||
}
|
||||
return pluginMetadata;
|
||||
}
|
||||
@@ -6,9 +6,9 @@ export function isRouterContract(abi: Abi) {
|
||||
AbiSchema.parse(abi),
|
||||
"PluginRouter",
|
||||
);
|
||||
const isExtensionRouter: boolean = isFeatureEnabled(
|
||||
const isBaseRouter: boolean = isFeatureEnabled(
|
||||
AbiSchema.parse(abi),
|
||||
"ExtensionRouter",
|
||||
"DynamicContract",
|
||||
);
|
||||
return isExtensionRouter || isPluginRouter;
|
||||
return isBaseRouter || isPluginRouter;
|
||||
}
|
||||
|
||||
@@ -61,6 +61,7 @@ export async function verifyThirdwebPrebuiltImplementation(
|
||||
explorerAPIUrl: string,
|
||||
explorerAPIKey: string,
|
||||
storage: ThirdwebStorage,
|
||||
contractVersion: string = "latest",
|
||||
clientId?: string,
|
||||
secretKey?: string,
|
||||
constructorArgs?: ConstructorParamMap,
|
||||
@@ -69,6 +70,7 @@ export async function verifyThirdwebPrebuiltImplementation(
|
||||
contractName,
|
||||
chainId,
|
||||
storage,
|
||||
contractVersion,
|
||||
clientId,
|
||||
secretKey,
|
||||
);
|
||||
@@ -76,6 +78,7 @@ export async function verifyThirdwebPrebuiltImplementation(
|
||||
contractName,
|
||||
chainId,
|
||||
storage,
|
||||
contractVersion,
|
||||
clientId,
|
||||
secretKey,
|
||||
constructorArgs,
|
||||
|
||||
@@ -48,6 +48,8 @@ import {
|
||||
FEATURE_EDITION_REVEALABLE,
|
||||
FEATURE_EDITION_SIGNATURE_MINTABLE,
|
||||
FEATURE_EDITION_CLAIM_PHASES_V1,
|
||||
FEATURE_EDITION_UPDATABLE_METADATA,
|
||||
FEATURE_EDITION_SUPPLY,
|
||||
} from "./erc1155-features";
|
||||
import {
|
||||
FEATURE_METADATA,
|
||||
@@ -64,7 +66,10 @@ import {
|
||||
FEATURE_DIRECT_LISTINGS,
|
||||
FEATURE_ENGLISH_AUCTIONS,
|
||||
FEATURE_OFFERS,
|
||||
FEATURE_EXTENSION_ROUTER,
|
||||
FEATURE_DYNAMIC_CONTRACT,
|
||||
FEATURE_AIRDROP_ERC20,
|
||||
FEATURE_AIRDROP_ERC721,
|
||||
FEATURE_AIRDROP_ERC1155,
|
||||
FEATURE_ACCOUNT,
|
||||
FEATURE_ACCOUNT_FACTORY,
|
||||
FEATURE_ACCOUNT_PERMISSIONS,
|
||||
@@ -119,6 +124,8 @@ export type Feature =
|
||||
| typeof FEATURE_EDITION_BATCH_MINTABLE
|
||||
| typeof FEATURE_EDITION_BURNABLE
|
||||
| typeof FEATURE_EDITION_SIGNATURE_MINTABLE
|
||||
| typeof FEATURE_EDITION_UPDATABLE_METADATA
|
||||
| typeof FEATURE_EDITION_SUPPLY
|
||||
| typeof FEATURE_ROYALTY
|
||||
| typeof FEATURE_PLATFORM_FEE
|
||||
| typeof FEATURE_PRIMARY_SALE
|
||||
@@ -130,10 +137,13 @@ export type Feature =
|
||||
| typeof FEATURE_GASLESS
|
||||
| typeof FEATURE_PACK_VRF
|
||||
| typeof FEATURE_PLUGIN_ROUTER
|
||||
| typeof FEATURE_EXTENSION_ROUTER
|
||||
| typeof FEATURE_DYNAMIC_CONTRACT
|
||||
| typeof FEATURE_DIRECT_LISTINGS
|
||||
| typeof FEATURE_ENGLISH_AUCTIONS
|
||||
| typeof FEATURE_OFFERS
|
||||
| typeof FEATURE_AIRDROP_ERC20
|
||||
| typeof FEATURE_AIRDROP_ERC721
|
||||
| typeof FEATURE_AIRDROP_ERC1155
|
||||
| typeof FEATURE_ACCOUNT
|
||||
| typeof FEATURE_ACCOUNT_PERMISSIONS
|
||||
| typeof FEATURE_ACCOUNT_FACTORY;
|
||||
@@ -174,10 +184,13 @@ export const SUPPORTED_FEATURES: Record<string, Feature> = /* @__PURE__ */ {
|
||||
[FEATURE_GASLESS.name]: FEATURE_GASLESS,
|
||||
[FEATURE_PACK_VRF.name]: FEATURE_PACK_VRF,
|
||||
[FEATURE_PLUGIN_ROUTER.name]: FEATURE_PLUGIN_ROUTER,
|
||||
[FEATURE_EXTENSION_ROUTER.name]: FEATURE_EXTENSION_ROUTER,
|
||||
[FEATURE_DYNAMIC_CONTRACT.name]: FEATURE_DYNAMIC_CONTRACT,
|
||||
[FEATURE_DIRECT_LISTINGS.name]: FEATURE_DIRECT_LISTINGS,
|
||||
[FEATURE_ENGLISH_AUCTIONS.name]: FEATURE_ENGLISH_AUCTIONS,
|
||||
[FEATURE_OFFERS.name]: FEATURE_OFFERS,
|
||||
[FEATURE_AIRDROP_ERC20.name]: FEATURE_AIRDROP_ERC20,
|
||||
[FEATURE_AIRDROP_ERC721.name]: FEATURE_AIRDROP_ERC721,
|
||||
[FEATURE_AIRDROP_ERC1155.name]: FEATURE_AIRDROP_ERC1155,
|
||||
[FEATURE_ACCOUNT_FACTORY.name]: FEATURE_ACCOUNT_FACTORY,
|
||||
[FEATURE_ACCOUNT.name]: FEATURE_ACCOUNT,
|
||||
[FEATURE_NFT_LOYALTY_CARD.name]: FEATURE_NFT_LOYALTY_CARD,
|
||||
|
||||
@@ -6,11 +6,44 @@ import DropERC1155_V2Abi from "@thirdweb-dev/contracts-js/dist/abis/IDropERC1155
|
||||
import IDropSinglePhase1155 from "@thirdweb-dev/contracts-js/dist/abis/IDropSinglePhase1155.json";
|
||||
import IDropSinglePhase1155_V1 from "@thirdweb-dev/contracts-js/dist/abis/IDropSinglePhase1155_V1.json";
|
||||
import Erc1155Abi from "@thirdweb-dev/contracts-js/dist/abis/IERC1155.json";
|
||||
import Erc1155MetadataAbi from "@thirdweb-dev/contracts-js/dist/abis/IERC1155Metadata.json";
|
||||
import Erc1155SupplyAbi from "@thirdweb-dev/contracts-js/dist/abis/IERC1155Supply.json";
|
||||
import Erc1155EnumerableAbi from "@thirdweb-dev/contracts-js/dist/abis/IERC1155Enumerable.json";
|
||||
import ILazyMintAbi from "@thirdweb-dev/contracts-js/dist/abis/ILazyMint.json";
|
||||
import IMintableERC1155Abi from "@thirdweb-dev/contracts-js/dist/abis/IMintableERC1155.json";
|
||||
import MulticallAbi from "@thirdweb-dev/contracts-js/dist/abis/IMulticall.json";
|
||||
import ISignatureMintERC1155Abi from "@thirdweb-dev/contracts-js/dist/abis/ISignatureMintERC1155.json";
|
||||
import INFTMetadataAbi from "@thirdweb-dev/contracts-js/dist/abis/INFTMetadata.json";
|
||||
|
||||
// TODO could be part of IERC1155Metadata even though its not in the spec
|
||||
const NAME_SYMBOL_ABI = [
|
||||
{
|
||||
inputs: [],
|
||||
name: "name",
|
||||
outputs: [
|
||||
{
|
||||
internalType: "string",
|
||||
name: "",
|
||||
type: "string",
|
||||
},
|
||||
],
|
||||
stateMutability: "view",
|
||||
type: "function",
|
||||
},
|
||||
{
|
||||
inputs: [],
|
||||
name: "symbol",
|
||||
outputs: [
|
||||
{
|
||||
internalType: "string",
|
||||
name: "",
|
||||
type: "string",
|
||||
},
|
||||
],
|
||||
stateMutability: "view",
|
||||
type: "function",
|
||||
},
|
||||
];
|
||||
|
||||
export const FEATURE_EDITION_BURNABLE = {
|
||||
name: "ERC1155Burnable",
|
||||
@@ -172,6 +205,29 @@ export const FEATURE_EDITION_ENUMERABLE = {
|
||||
features: {},
|
||||
} as const;
|
||||
|
||||
export const FEATURE_EDITION_UPDATABLE_METADATA = {
|
||||
name: "ERC1155UpdatableMetadata",
|
||||
namespace: "edition.metadata",
|
||||
docLinks: {
|
||||
// TODO
|
||||
sdk: "",
|
||||
contracts: "",
|
||||
},
|
||||
abis: [Erc1155Abi, INFTMetadataAbi],
|
||||
features: {},
|
||||
} as const;
|
||||
|
||||
export const FEATURE_EDITION_SUPPLY = {
|
||||
name: "ERC1155Supply",
|
||||
namespace: "edition.supply",
|
||||
docLinks: {
|
||||
sdk: "",
|
||||
contracts: "",
|
||||
},
|
||||
abis: [Erc1155Abi, Erc1155SupplyAbi],
|
||||
features: {},
|
||||
} as const;
|
||||
|
||||
export const FEATURE_EDITION = /* @__PURE__ */ {
|
||||
name: "ERC1155",
|
||||
namespace: "edition",
|
||||
@@ -179,8 +235,9 @@ export const FEATURE_EDITION = /* @__PURE__ */ {
|
||||
sdk: "sdk.erc1155enumerable",
|
||||
contracts: "erc1155",
|
||||
},
|
||||
abis: [Erc1155Abi],
|
||||
abis: [Erc1155Abi, Erc1155MetadataAbi, NAME_SYMBOL_ABI],
|
||||
features: {
|
||||
[FEATURE_EDITION_SUPPLY.name]: FEATURE_EDITION_SUPPLY,
|
||||
[FEATURE_EDITION_BURNABLE.name]: FEATURE_EDITION_BURNABLE,
|
||||
[FEATURE_EDITION_ENUMERABLE.name]: FEATURE_EDITION_ENUMERABLE,
|
||||
[FEATURE_EDITION_MINTABLE.name]: FEATURE_EDITION_MINTABLE,
|
||||
@@ -195,5 +252,7 @@ export const FEATURE_EDITION = /* @__PURE__ */ {
|
||||
[FEATURE_EDITION_CLAIM_CONDITIONS_V2.name]:
|
||||
FEATURE_EDITION_CLAIM_CONDITIONS_V2,
|
||||
[FEATURE_EDITION_CLAIM_PHASES_V2.name]: FEATURE_EDITION_CLAIM_PHASES_V2,
|
||||
[FEATURE_EDITION_UPDATABLE_METADATA.name]:
|
||||
FEATURE_EDITION_UPDATABLE_METADATA,
|
||||
},
|
||||
} as const;
|
||||
|
||||
@@ -8,6 +8,7 @@ import IERC20PermitAbi from "@thirdweb-dev/contracts-js/dist/abis/IERC20Permit.j
|
||||
import IMintableERC20Abi from "@thirdweb-dev/contracts-js/dist/abis/IMintableERC20.json";
|
||||
import MulticallAbi from "@thirdweb-dev/contracts-js/dist/abis/IMulticall.json";
|
||||
import ISignatureMintERC20Abi from "@thirdweb-dev/contracts-js/dist/abis/ISignatureMintERC20.json";
|
||||
import IERC20MetadataAbi from "@thirdweb-dev/contracts-js/dist/abis/IERC20Metadata.json";
|
||||
|
||||
export const FEATURE_TOKEN_CLAIM_CONDITIONS_V1 = {
|
||||
name: "ERC20ClaimConditionsV1",
|
||||
@@ -117,7 +118,7 @@ export const FEATURE_TOKEN = /* @__PURE__ */ {
|
||||
sdk: "sdk.erc20",
|
||||
contracts: "erc20",
|
||||
},
|
||||
abis: [ERC20Abi],
|
||||
abis: [ERC20Abi, IERC20MetadataAbi],
|
||||
features: {
|
||||
[FEATURE_TOKEN_BURNABLE.name]: FEATURE_TOKEN_BURNABLE,
|
||||
[FEATURE_TOKEN_MINTABLE.name]: FEATURE_TOKEN_MINTABLE,
|
||||
|
||||
@@ -19,6 +19,7 @@ import SharedMetadataAbi from "@thirdweb-dev/contracts-js/dist/abis/SharedMetada
|
||||
import zora_IDropERC721 from "@thirdweb-dev/contracts-js/dist/abis/zora_IERC721Drop.json";
|
||||
import ILoyaltyCardAbi from "@thirdweb-dev/contracts-js/dist/abis/ILoyaltyCard.json";
|
||||
import INFTMetadataAbi from "@thirdweb-dev/contracts-js/dist/abis/INFTMetadata.json";
|
||||
import IERC721MetadataAbi from "@thirdweb-dev/contracts-js/dist/abis/IERC721Metadata.json";
|
||||
|
||||
export const FEATURE_NFT_BURNABLE = {
|
||||
name: "ERC721Burnable",
|
||||
@@ -246,7 +247,7 @@ export const FEATURE_NFT_UPDATABLE_METADATA = {
|
||||
sdk: "",
|
||||
contracts: "",
|
||||
},
|
||||
abis: [INFTMetadataAbi],
|
||||
abis: [Erc721Abi, INFTMetadataAbi],
|
||||
features: {},
|
||||
} as const;
|
||||
|
||||
@@ -257,7 +258,7 @@ export const FEATURE_NFT = /* @__PURE__ */ {
|
||||
sdk: "sdk.erc721",
|
||||
contracts: "erc721",
|
||||
},
|
||||
abis: [Erc721Abi],
|
||||
abis: [Erc721Abi, IERC721MetadataAbi],
|
||||
features: {
|
||||
[FEATURE_NFT_BURNABLE.name]: FEATURE_NFT_BURNABLE,
|
||||
[FEATURE_NFT_SUPPLY.name]: FEATURE_NFT_SUPPLY,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import IERC2771ContextAbi from "@thirdweb-dev/contracts-js/dist/abis/ERC2771Context.json";
|
||||
import IERC2771ContextAbi from "@thirdweb-dev/contracts-js/dist/abis/IERC2771Context.json";
|
||||
import IAppURI from "@thirdweb-dev/contracts-js/dist/abis/IAppURI.json";
|
||||
import IContractMetadataAbi from "@thirdweb-dev/contracts-js/dist/abis/IContractMetadata.json";
|
||||
import IDirectListingsAbi from "@thirdweb-dev/contracts-js/dist/abis/IDirectListings.json";
|
||||
@@ -11,6 +11,9 @@ import IThirdwebPlatformFeeAbi from "@thirdweb-dev/contracts-js/dist/abis/IPlatf
|
||||
import IThirdwebPrimarySaleAbi from "@thirdweb-dev/contracts-js/dist/abis/IPrimarySale.json";
|
||||
import IThirdwebRoyaltyAbi from "@thirdweb-dev/contracts-js/dist/abis/IRoyalty.json";
|
||||
import IOwnableAbi from "@thirdweb-dev/contracts-js/dist/abis/Ownable.json";
|
||||
import IAirdropERC20 from "@thirdweb-dev/contracts-js/dist/abis/IAirdropERC20.json";
|
||||
import IAirdropERC721 from "@thirdweb-dev/contracts-js/dist/abis/IAirdropERC721.json";
|
||||
import IAirdropERC1155 from "@thirdweb-dev/contracts-js/dist/abis/IAirdropERC1155.json";
|
||||
import IAccountFactory from "@thirdweb-dev/contracts-js/dist/abis/IAccountFactory.json";
|
||||
import IAccountPermissions from "@thirdweb-dev/contracts-js/dist/abis/IAccountPermissions.json";
|
||||
import IAccount from "@thirdweb-dev/contracts-js/dist/abis/IAccount.json";
|
||||
@@ -232,9 +235,9 @@ export const FEATURE_PLUGIN_ROUTER = {
|
||||
features: {},
|
||||
} as const;
|
||||
|
||||
export const FEATURE_EXTENSION_ROUTER = {
|
||||
name: "ExtensionRouter",
|
||||
namespace: "extension.router",
|
||||
export const FEATURE_DYNAMIC_CONTRACT = {
|
||||
name: "DynamicContract",
|
||||
namespace: "dynamic.contract",
|
||||
docLinks: {
|
||||
sdk: "",
|
||||
//TODO
|
||||
@@ -315,3 +318,39 @@ export const FEATURE_ACCOUNT = {
|
||||
abis: [IAccount],
|
||||
features: { [FEATURE_ACCOUNT_PERMISSIONS.name]: FEATURE_ACCOUNT_PERMISSIONS },
|
||||
} as const;
|
||||
|
||||
export const FEATURE_AIRDROP_ERC20 = {
|
||||
name: "AirdropERC20",
|
||||
namespace: "airdrop20",
|
||||
docLinks: {
|
||||
// TODO
|
||||
sdk: "",
|
||||
contracts: "",
|
||||
},
|
||||
abis: [IAirdropERC20],
|
||||
features: {},
|
||||
} as const;
|
||||
|
||||
export const FEATURE_AIRDROP_ERC721 = {
|
||||
name: "AirdropERC721",
|
||||
namespace: "airdrop721",
|
||||
docLinks: {
|
||||
// TODO
|
||||
sdk: "",
|
||||
contracts: "",
|
||||
},
|
||||
abis: [IAirdropERC721],
|
||||
features: {},
|
||||
} as const;
|
||||
|
||||
export const FEATURE_AIRDROP_ERC1155 = {
|
||||
name: "AirdropERC1155",
|
||||
namespace: "airdrop1155",
|
||||
docLinks: {
|
||||
// TODO
|
||||
sdk: "",
|
||||
contracts: "",
|
||||
},
|
||||
abis: [IAirdropERC1155],
|
||||
features: {},
|
||||
} as const;
|
||||
|
||||
@@ -41,8 +41,11 @@ export function getChainProvider(
|
||||
// Add the chain to the supportedChains
|
||||
const options = SDKOptionsSchema.parse(sdkOptions);
|
||||
if (isChainConfig(network)) {
|
||||
// @ts-expect-error - we know this is a chain and it will work to build the map
|
||||
options.supportedChains = [network, ...options.supportedChains];
|
||||
options.supportedChains = [
|
||||
// @ts-expect-error - we know this is a chain and it will work to build the map
|
||||
network,
|
||||
...options.supportedChains.filter((c) => c.chainId !== network.chainId),
|
||||
];
|
||||
}
|
||||
|
||||
// Build a map of chainId -> ChainInfo based on the supportedChains
|
||||
@@ -105,10 +108,35 @@ export function getChainIdFromNetwork(
|
||||
);
|
||||
}
|
||||
|
||||
export async function getChainIdOrName(
|
||||
network: NetworkInput,
|
||||
): Promise<number | string> {
|
||||
if (isChainConfig(network)) {
|
||||
// If it's a chain just return the chain id
|
||||
return network.chainId;
|
||||
} else if (typeof network === "number") {
|
||||
// If it's a number (chainId) return it directly
|
||||
return network;
|
||||
} else if (typeof network === "number") {
|
||||
// If it's a string (chain name) return the chain id from the map
|
||||
return network;
|
||||
} else if (isProvider(network)) {
|
||||
return network.getNetwork().then((n) => n.chainId);
|
||||
} else if (isSigner(network)) {
|
||||
if (!network.provider) {
|
||||
throw new Error("Signer does not have a provider");
|
||||
}
|
||||
return network.provider.getNetwork().then((n) => n.chainId);
|
||||
}
|
||||
throw new Error(`Cannot resolve chainId from: ${network}.`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether a NetworkInput value is a Chain config (naively, without parsing)
|
||||
*/
|
||||
export function isChainConfig(network: NetworkInput): network is Chain {
|
||||
export function isChainConfig(
|
||||
network: NetworkInput,
|
||||
): network is Chain | ChainInfo {
|
||||
return (
|
||||
typeof network !== "string" &&
|
||||
typeof network !== "number" &&
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
import { fetchAndCachePublishedContractURI } from "../common/any-evm-utils/fetchAndCachePublishedContractURI";
|
||||
import {
|
||||
THIRDWEB_DEPLOYER,
|
||||
fetchPublishedContractFromPolygon,
|
||||
} from "../common/any-evm-utils/fetchPublishedContractFromPolygon";
|
||||
import { getPrebuiltInfo } from "../common/legacy";
|
||||
import { fetchAbiFromAddress } from "../common/metadata-resolver";
|
||||
import { ALL_ROLES } from "../common/role";
|
||||
@@ -194,7 +197,7 @@ export const MarketplaceV3Initializer = {
|
||||
) => {
|
||||
const [, provider] = getSignerAndProvider(network, options);
|
||||
const [abi, contract, _network] = await Promise.all([
|
||||
MarketplaceV3Initializer.getAbi(address, provider, storage),
|
||||
MarketplaceV3Initializer.getAbi(address, provider, storage, options),
|
||||
import("./prebuilt-implementations/marketplacev3"),
|
||||
provider.getNetwork(),
|
||||
]);
|
||||
@@ -212,6 +215,7 @@ export const MarketplaceV3Initializer = {
|
||||
address: Address,
|
||||
provider: providers.Provider,
|
||||
storage: ThirdwebStorage,
|
||||
options?: SDKOptions,
|
||||
) => {
|
||||
const chainId = (await provider.getNetwork()).chainId;
|
||||
const isZkSync = chainId === 280 || chainId === 324;
|
||||
@@ -219,7 +223,15 @@ export const MarketplaceV3Initializer = {
|
||||
// Can't resolve IPFS hash from plugin bytecode on ZkSync
|
||||
// Thus, pull the composite ABI from the release page
|
||||
if (isZkSync) {
|
||||
const uri = await fetchAndCachePublishedContractURI("MarketplaceV3");
|
||||
const publishedContract = await fetchPublishedContractFromPolygon(
|
||||
THIRDWEB_DEPLOYER,
|
||||
"MarketplaceV3",
|
||||
"latest",
|
||||
storage,
|
||||
options?.clientId,
|
||||
options?.secretKey,
|
||||
);
|
||||
const uri = publishedContract.metadataUri;
|
||||
const compositeAbi = await getCompositeABIfromRelease(uri, storage);
|
||||
|
||||
return compositeAbi;
|
||||
|
||||
@@ -5,6 +5,9 @@ import { FEATURE_TOKEN } from "../constants/erc20-features";
|
||||
import { FEATURE_NFT } from "../constants/erc721-features";
|
||||
import { FEATURE_EDITION } from "../constants/erc1155-features";
|
||||
import {
|
||||
FEATURE_AIRDROP_ERC20,
|
||||
FEATURE_AIRDROP_ERC721,
|
||||
FEATURE_AIRDROP_ERC1155,
|
||||
FEATURE_APPURI,
|
||||
FEATURE_DIRECT_LISTINGS,
|
||||
FEATURE_ENGLISH_AUCTIONS,
|
||||
@@ -53,13 +56,15 @@ import type {
|
||||
DirectListingsLogic,
|
||||
EnglishAuctionsLogic,
|
||||
OffersLogic,
|
||||
AirdropERC20,
|
||||
IAccountFactory,
|
||||
IAccountCore,
|
||||
AirdropERC721,
|
||||
AirdropERC1155,
|
||||
} from "@thirdweb-dev/contracts-js";
|
||||
import { ThirdwebStorage } from "@thirdweb-dev/storage";
|
||||
import { BaseContract, CallOverrides } from "ethers";
|
||||
import { BaseContractInterface } from "../types/contract";
|
||||
|
||||
import { NetworkInput } from "../core/types";
|
||||
import { ContractEncoder } from "../core/classes/contract-encoder";
|
||||
import { ContractOwner } from "../core/classes/contract-owner";
|
||||
@@ -68,6 +73,9 @@ import { MarketplaceV3EnglishAuctions } from "../core/classes/marketplacev3-engl
|
||||
import { MarketplaceV3Offers } from "../core/classes/marketplacev3-offers";
|
||||
import { AccountFactory } from "../core/classes/account-factory";
|
||||
import { Account } from "../core/classes/account";
|
||||
import { Airdrop20 } from "../core/classes/airdrop-erc20";
|
||||
import { Airdrop721 } from "../core/classes/airdrop-erc721";
|
||||
import { Airdrop1155 } from "../core/classes/airdrop-erc1155";
|
||||
|
||||
/**
|
||||
* Custom contract dynamic class with feature detection
|
||||
@@ -298,6 +306,18 @@ export class SmartContract<
|
||||
return assertEnabled(this.detectOffers(), FEATURE_OFFERS);
|
||||
}
|
||||
|
||||
get airdrop20(): Airdrop20<AirdropERC20> {
|
||||
return assertEnabled(this.detectAirdrop20(), FEATURE_AIRDROP_ERC20);
|
||||
}
|
||||
|
||||
get airdrop721(): Airdrop721<AirdropERC721> {
|
||||
return assertEnabled(this.detectAirdrop721(), FEATURE_AIRDROP_ERC721);
|
||||
}
|
||||
|
||||
get airdrop1155(): Airdrop1155<AirdropERC1155> {
|
||||
return assertEnabled(this.detectAirdrop1155(), FEATURE_AIRDROP_ERC1155);
|
||||
}
|
||||
|
||||
/**
|
||||
* Account Factory
|
||||
*
|
||||
@@ -563,6 +583,33 @@ export class SmartContract<
|
||||
return undefined;
|
||||
}
|
||||
|
||||
private detectAirdrop20() {
|
||||
if (
|
||||
detectContractFeature<AirdropERC20>(this.contractWrapper, "AirdropERC20")
|
||||
) {
|
||||
return new Airdrop20(this.contractWrapper);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
private detectAirdrop721() {
|
||||
if (
|
||||
detectContractFeature<AirdropERC721>(this.contractWrapper, "AirdropERC721")
|
||||
) {
|
||||
return new Airdrop721(this.contractWrapper);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
private detectAirdrop1155() {
|
||||
if (
|
||||
detectContractFeature<AirdropERC1155>(this.contractWrapper, "AirdropERC1155")
|
||||
) {
|
||||
return new Airdrop1155(this.contractWrapper);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// ========== Account features ==========
|
||||
|
||||
private detectAccountFactory() {
|
||||
|
||||
@@ -0,0 +1,107 @@
|
||||
import { AirdropFailedEvent } from "@thirdweb-dev/contracts-js/dist/declarations/src/AirdropERC1155";
|
||||
import { buildTransactionFunction } from "../../common/transactions";
|
||||
import { FEATURE_AIRDROP_ERC1155 } from "../../constants/thirdweb-features";
|
||||
import { Address } from "../../schema";
|
||||
import { Airdrop1155Content, Airdrop1155Output } from "../../types";
|
||||
import { DetectableFeature } from "../interfaces/DetectableFeature";
|
||||
import { ContractWrapper } from "./contract-wrapper";
|
||||
import { Transaction } from "./transactions";
|
||||
import type {
|
||||
AirdropERC1155,
|
||||
IAirdropERC1155,
|
||||
} from "@thirdweb-dev/contracts-js";
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export class Airdrop1155<T extends IAirdropERC1155 | AirdropERC1155>
|
||||
implements DetectableFeature
|
||||
{
|
||||
featureName = FEATURE_AIRDROP_ERC1155.name;
|
||||
protected contractWrapper: ContractWrapper<T>;
|
||||
|
||||
constructor(contractWrapper: ContractWrapper<T>) {
|
||||
this.contractWrapper = contractWrapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
getAddress(): Address {
|
||||
return this.contractWrapper.readContract.address;
|
||||
}
|
||||
|
||||
/** ******************************
|
||||
* WRITE FUNCTIONS
|
||||
*******************************/
|
||||
|
||||
/**
|
||||
* Perform airdrop of ERC1155 tokens
|
||||
*
|
||||
* @example
|
||||
* ```javascript
|
||||
* // Airdrop content array, with recipients and tokenIds
|
||||
* const contents = [
|
||||
* {
|
||||
* recipient: "0xabc...", // first recipient address
|
||||
* tokenId: 0,
|
||||
* amount: "10" // number of tokens
|
||||
* },
|
||||
* {
|
||||
* recipient: "0x123...", // second recipient address
|
||||
* tokenId: 0
|
||||
* amount: "20" // number of tokens
|
||||
* }
|
||||
* ]
|
||||
*
|
||||
* const tokenAddress = "0x..." // Address of the ERC1155 token being airdropped
|
||||
* const tokenOwner = "0x..." // Address of the owner of the tokens being airdropped
|
||||
*
|
||||
* const output = await contract.airdrop1155.drop(tokenAddress, tokenOwner, contents);
|
||||
*
|
||||
* // the `output` return value above contains:
|
||||
* // - count of successful and failed drops
|
||||
* // - array containing failed drops, if any
|
||||
*
|
||||
* ```
|
||||
* @param tokenAddress
|
||||
* @param tokenOwner
|
||||
* @param contents
|
||||
*
|
||||
* @returns an array of recipients for who the airdrop failed (empty means all transfers were successful)
|
||||
* @twfeature AirdropERC1155
|
||||
*/
|
||||
drop = /* @__PURE__ */ buildTransactionFunction(
|
||||
async (
|
||||
tokenAddress: string,
|
||||
tokenOwner: string,
|
||||
contents: Airdrop1155Content[],
|
||||
): Promise<Transaction<Airdrop1155Output>> => {
|
||||
return Transaction.fromContractWrapper({
|
||||
contractWrapper: this.contractWrapper,
|
||||
method: "airdrop",
|
||||
args: [tokenAddress, tokenOwner, contents],
|
||||
parse: (receipt) => {
|
||||
const events = this.contractWrapper.parseLogs<AirdropFailedEvent>(
|
||||
"AirdropFailed",
|
||||
receipt.logs,
|
||||
);
|
||||
|
||||
const failedDrops = events.map((e) => {
|
||||
return {
|
||||
recipient: e.args.recipient,
|
||||
tokenId: e.args.tokenId.toNumber(),
|
||||
amount: e.args.amount.toString(),
|
||||
};
|
||||
});
|
||||
|
||||
return {
|
||||
successfulDropCount: contents.length - failedDrops.length,
|
||||
failedDropCount: failedDrops.length,
|
||||
failedDrops,
|
||||
};
|
||||
},
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
import { AirdropFailedEvent } from "@thirdweb-dev/contracts-js/dist/declarations/src/AirdropERC1155";
|
||||
import { buildTransactionFunction } from "../../common/transactions";
|
||||
import { FEATURE_AIRDROP_ERC20 } from "../../constants/thirdweb-features";
|
||||
import { Address } from "../../schema";
|
||||
import { Airdrop20Content, Airdrop20Output } from "../../types";
|
||||
import { DetectableFeature } from "../interfaces/DetectableFeature";
|
||||
import { ContractWrapper } from "./contract-wrapper";
|
||||
import { Transaction } from "./transactions";
|
||||
import type { IAirdropERC20, AirdropERC20 } from "@thirdweb-dev/contracts-js";
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export class Airdrop20<T extends IAirdropERC20 | AirdropERC20>
|
||||
implements DetectableFeature
|
||||
{
|
||||
featureName = FEATURE_AIRDROP_ERC20.name;
|
||||
protected contractWrapper: ContractWrapper<T>;
|
||||
|
||||
constructor(contractWrapper: ContractWrapper<T>) {
|
||||
this.contractWrapper = contractWrapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
getAddress(): Address {
|
||||
return this.contractWrapper.readContract.address;
|
||||
}
|
||||
|
||||
/** ******************************
|
||||
* WRITE FUNCTIONS
|
||||
*******************************/
|
||||
|
||||
/**
|
||||
* Perform airdrop of ERC20 tokens
|
||||
*
|
||||
* @example
|
||||
* ```javascript
|
||||
* // Airdrop content array, with recipients and token amounts
|
||||
* const contents = [
|
||||
* {
|
||||
* recipient: "0xabc...", // first recipient address
|
||||
* amount: "10" // number of tokens in wei units
|
||||
* },
|
||||
* {
|
||||
* recipient: "0x123...", // second recipient address
|
||||
* amount: "20" // number of tokens in wei units
|
||||
* }
|
||||
* ]
|
||||
*
|
||||
* const tokenAddress = "0x..." // Address of the ERC20 token being airdropped
|
||||
* const tokenOwner = "0x..." // Address of the owner of the tokens being airdropped
|
||||
*
|
||||
* const output = await contract.airdrop20.drop(tokenAddress, tokenOwner, contents);
|
||||
*
|
||||
* // the `output` return value above contains:
|
||||
* // - count of successful and failed drops
|
||||
* // - array containing failed drops, if any
|
||||
*
|
||||
* ```
|
||||
* @param tokenAddress
|
||||
* @param tokenOwner
|
||||
* @param contents
|
||||
*
|
||||
* @returns an array of recipients for who the airdrop failed (empty means all transfers were successful)
|
||||
* @twfeature AirdropERC20
|
||||
*/
|
||||
drop = /* @__PURE__ */ buildTransactionFunction(
|
||||
async (
|
||||
tokenAddress: string,
|
||||
tokenOwner: string,
|
||||
contents: Airdrop20Content[],
|
||||
): Promise<Transaction<Airdrop20Output>> => {
|
||||
return Transaction.fromContractWrapper({
|
||||
contractWrapper: this.contractWrapper,
|
||||
method: "airdrop",
|
||||
args: [tokenAddress, tokenOwner, contents],
|
||||
parse: (receipt) => {
|
||||
const events = this.contractWrapper.parseLogs<AirdropFailedEvent>(
|
||||
"AirdropFailed",
|
||||
receipt.logs,
|
||||
);
|
||||
|
||||
const failedDrops = events.map((e) => {
|
||||
return {
|
||||
recipient: e.args.recipient,
|
||||
amount: e.args.amount.toString(),
|
||||
};
|
||||
});
|
||||
|
||||
return {
|
||||
successfulDropCount: contents.length - failedDrops.length,
|
||||
failedDropCount: failedDrops.length,
|
||||
failedDrops,
|
||||
};
|
||||
},
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
import { AirdropFailedEvent } from "@thirdweb-dev/contracts-js/dist/declarations/src/AirdropERC1155";
|
||||
import { buildTransactionFunction } from "../../common/transactions";
|
||||
import { FEATURE_AIRDROP_ERC721 } from "../../constants/thirdweb-features";
|
||||
import { Address } from "../../schema";
|
||||
import { Airdrop721Content, Airdrop721Output } from "../../types";
|
||||
import { DetectableFeature } from "../interfaces/DetectableFeature";
|
||||
import { ContractWrapper } from "./contract-wrapper";
|
||||
import { Transaction } from "./transactions";
|
||||
import type { AirdropERC721, IAirdropERC721 } from "@thirdweb-dev/contracts-js";
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export class Airdrop721<T extends IAirdropERC721 | AirdropERC721>
|
||||
implements DetectableFeature
|
||||
{
|
||||
featureName = FEATURE_AIRDROP_ERC721.name;
|
||||
protected contractWrapper: ContractWrapper<T>;
|
||||
|
||||
constructor(contractWrapper: ContractWrapper<T>) {
|
||||
this.contractWrapper = contractWrapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
getAddress(): Address {
|
||||
return this.contractWrapper.readContract.address;
|
||||
}
|
||||
|
||||
/** ******************************
|
||||
* WRITE FUNCTIONS
|
||||
*******************************/
|
||||
|
||||
/**
|
||||
* Perform airdrop of ERC721 tokens
|
||||
*
|
||||
* @example
|
||||
* ```javascript
|
||||
* // Airdrop content array, with recipients and tokenIds
|
||||
* const contents = [
|
||||
* {
|
||||
* recipient: "0xabc...", // first recipient address
|
||||
* tokenId: 0
|
||||
* },
|
||||
* {
|
||||
* recipient: "0x123...", // second recipient address
|
||||
* tokenId: 2
|
||||
* }
|
||||
* ]
|
||||
*
|
||||
* const tokenAddress = "0x..." // Address of the ERC721 token being airdropped
|
||||
* const tokenOwner = "0x..." // Address of the owner of the tokens being airdropped
|
||||
*
|
||||
* const output = await contract.airdrop721.drop(tokenAddress, tokenOwner, contents);
|
||||
*
|
||||
* // the `output` return value above contains:
|
||||
* // - count of successful and failed drops
|
||||
* // - array containing failed drops, if any
|
||||
*
|
||||
* ```
|
||||
* @param tokenAddress
|
||||
* @param tokenOwner
|
||||
* @param contents
|
||||
*
|
||||
* @returns an array of recipients for who the airdrop failed (empty means all transfers were successful)
|
||||
* @twfeature AirdropERC721
|
||||
*/
|
||||
drop = /* @__PURE__ */ buildTransactionFunction(
|
||||
async (
|
||||
tokenAddress: string,
|
||||
tokenOwner: string,
|
||||
contents: Airdrop721Content[],
|
||||
): Promise<Transaction<Airdrop721Output>> => {
|
||||
return Transaction.fromContractWrapper({
|
||||
contractWrapper: this.contractWrapper,
|
||||
method: "airdrop",
|
||||
args: [tokenAddress, tokenOwner, contents],
|
||||
parse: (receipt) => {
|
||||
const events = this.contractWrapper.parseLogs<AirdropFailedEvent>(
|
||||
"AirdropFailed",
|
||||
receipt.logs,
|
||||
);
|
||||
const failedDrops = events.map((e) => {
|
||||
return {
|
||||
recipient: e.args.recipient,
|
||||
tokenId: e.args.tokenId.toNumber(),
|
||||
};
|
||||
});
|
||||
|
||||
return {
|
||||
successfulDropCount: contents.length - failedDrops.length,
|
||||
failedDropCount: failedDrops.length,
|
||||
failedDrops,
|
||||
};
|
||||
},
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
||||
@@ -8,11 +8,9 @@ import { resolveContractUriFromAddress } from "../../common/feature-detection/re
|
||||
import { fetchContractMetadataFromAddress } from "../../common/metadata-resolver";
|
||||
import { fetchContractMetadata } from "../../common/fetchContractMetadata";
|
||||
import { fetchSourceFilesFromMetadata } from "../../common/fetchSourceFilesFromMetadata";
|
||||
import { getCompositePluginABI } from "../../common/plugin/getCompositePluginABI";
|
||||
import { buildTransactionFunction } from "../../common/transactions";
|
||||
import { isIncrementalVersion } from "../../common/version-checker";
|
||||
import { getContractPublisherAddress } from "../../constants/addresses/getContractPublisherAddress";
|
||||
import { getChainProvider } from "../../constants/urls";
|
||||
import {
|
||||
AbiFunction,
|
||||
AbiSchema,
|
||||
@@ -44,6 +42,12 @@ import { ContractPublishedEvent } from "@thirdweb-dev/contracts-js/dist/declarat
|
||||
import { ThirdwebStorage } from "@thirdweb-dev/storage";
|
||||
import { constants, utils } from "ethers";
|
||||
import invariant from "tiny-invariant";
|
||||
import {
|
||||
fetchAndCacheDeployMetadata,
|
||||
fetchPublishedContractFromPolygon,
|
||||
isFeatureEnabled,
|
||||
} from "../../common";
|
||||
import { joinABIs } from "../../common/plugin/joinABIs";
|
||||
|
||||
/**
|
||||
* Handles publishing contracts (EXPERIMENTAL)
|
||||
@@ -369,34 +373,59 @@ export class ContractPublisher extends RPCConnectionHandler {
|
||||
this.storage,
|
||||
);
|
||||
|
||||
const compilerMetadata = await fetchContractMetadata(
|
||||
predeployMetadata.metadataUri,
|
||||
this.storage,
|
||||
);
|
||||
const isPlugin = isFeatureEnabled(
|
||||
AbiSchema.parse(compilerMetadata.abi),
|
||||
"PluginRouter",
|
||||
);
|
||||
const isDynamic = isFeatureEnabled(
|
||||
AbiSchema.parse(compilerMetadata.abi),
|
||||
"DynamicContract",
|
||||
);
|
||||
extraMetadata.routerType = isPlugin
|
||||
? "plugin"
|
||||
: isDynamic
|
||||
? "dynamic"
|
||||
: "none";
|
||||
|
||||
// For a dynamic contract Router, try to fetch plugin/extension metadata
|
||||
// from the implementation addresses, if any
|
||||
if (extraMetadata.factoryDeploymentData?.implementationAddresses) {
|
||||
const implementationsAddresses = Object.entries(
|
||||
extraMetadata.factoryDeploymentData.implementationAddresses,
|
||||
);
|
||||
if (isDynamic || isPlugin) {
|
||||
const defaultExtensions = extraMetadata.defaultExtensions;
|
||||
|
||||
const entry = implementationsAddresses.find(
|
||||
([, implementation]) => implementation !== "",
|
||||
);
|
||||
const [network, implementation] = entry ? entry : [];
|
||||
|
||||
if (network && implementation) {
|
||||
if (defaultExtensions && defaultExtensions.length > 0) {
|
||||
try {
|
||||
const compilerMetadata = await fetchContractMetadata(
|
||||
predeployMetadata.metadataUri,
|
||||
this.storage,
|
||||
);
|
||||
const composite = await getCompositePluginABI(
|
||||
implementation,
|
||||
compilerMetadata.abi,
|
||||
getChainProvider(parseInt(network), {
|
||||
clientId: this.options.clientId,
|
||||
secretKey: this.options.secretKey,
|
||||
const publishedExtensions = await Promise.all(
|
||||
defaultExtensions.map((e) => {
|
||||
return fetchPublishedContractFromPolygon(
|
||||
e.publisherAddress,
|
||||
e.extensionName,
|
||||
e.extensionVersion,
|
||||
this.storage,
|
||||
this.options.clientId,
|
||||
this.options.secretKey,
|
||||
);
|
||||
}),
|
||||
{}, // pass empty object for options instead of this.options
|
||||
this.storage,
|
||||
);
|
||||
|
||||
const publishedExtensionUris = publishedExtensions.map(
|
||||
(ext) => ext.metadataUri,
|
||||
);
|
||||
|
||||
const extensionABIs = (
|
||||
await Promise.all(
|
||||
publishedExtensionUris.map(async (uri) => {
|
||||
return fetchAndCacheDeployMetadata(uri, this.storage);
|
||||
}),
|
||||
)
|
||||
).map((fetchedMetadata) => fetchedMetadata.compilerMetadata.abi);
|
||||
|
||||
const composite = joinABIs([
|
||||
compilerMetadata.abi,
|
||||
...extensionABIs,
|
||||
]);
|
||||
extraMetadata.compositeAbi = AbiSchema.parse(composite);
|
||||
} catch {}
|
||||
}
|
||||
@@ -430,7 +459,7 @@ export class ContractPublisher extends RPCConnectionHandler {
|
||||
const bytecodeHash = utils.solidityKeccak256(["bytes"], [bytecode]);
|
||||
const contractId = predeployMetadata.name;
|
||||
|
||||
const fullMetadata = FullPublishMetadataSchemaInput.parse({
|
||||
const fullMetadata = await FullPublishMetadataSchemaInput.parseAsync({
|
||||
...extraMetadata,
|
||||
metadataUri: predeployMetadata.metadataUri,
|
||||
bytecodeUri: predeployMetadata.bytecodeUri,
|
||||
|
||||
@@ -59,6 +59,7 @@ export class ContractVerifier extends RPCConnectionHandler {
|
||||
contractName: string,
|
||||
explorerAPIUrl: string,
|
||||
explorerAPIKey: string,
|
||||
contractVersion: string = "latest",
|
||||
constructorArgs?: ConstructorParamMap,
|
||||
) {
|
||||
const chainId = (await this.getProvider().getNetwork()).chainId;
|
||||
@@ -68,6 +69,7 @@ export class ContractVerifier extends RPCConnectionHandler {
|
||||
explorerAPIUrl,
|
||||
explorerAPIKey,
|
||||
this.storage,
|
||||
contractVersion,
|
||||
this.options.clientId,
|
||||
this.options.secretKey,
|
||||
constructorArgs,
|
||||
|
||||
@@ -797,11 +797,23 @@ export class ContractWrapper<
|
||||
? CONTRACT_ADDRESSES[
|
||||
transaction.chainId as keyof typeof CONTRACT_ADDRESSES
|
||||
].openzeppelinForwarderEOA ||
|
||||
(await computeEOAForwarderAddress(this.getProvider(), this.storage))
|
||||
(await computeEOAForwarderAddress(
|
||||
this.getProvider(),
|
||||
this.storage,
|
||||
"",
|
||||
this.options.clientId,
|
||||
this.options.secretKey,
|
||||
))
|
||||
: CONTRACT_ADDRESSES[
|
||||
transaction.chainId as keyof typeof CONTRACT_ADDRESSES
|
||||
].openzeppelinForwarder ||
|
||||
(await computeForwarderAddress(this.getProvider(), this.storage)));
|
||||
(await computeForwarderAddress(
|
||||
this.getProvider(),
|
||||
this.storage,
|
||||
"",
|
||||
this.options.clientId,
|
||||
this.options.secretKey,
|
||||
)));
|
||||
|
||||
const forwarder = new Contract(forwarderAddress, ForwarderABI, provider);
|
||||
const nonce = await getAndIncrementNonce(forwarder, "getNonce", [
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user