Compare commits

...
Author SHA1 Message Date
github-actions[bot]andGitHub e39b66f309 Version Packages (#198) 2022-09-23 19:34:55 -07:00
5f5ab015e1 [SDK, SOL] Fixes for getOwned and solana balance (#199)
Co-authored-by: Jonas Daniels <[email protected]>
2022-09-24 02:11:58 +00:00
Jonas DanielsandGitHub f4f05bd9a4 [React] - make web3 button network switch obvious (#197) 2022-09-24 00:16:56 +00:00
github-actions[bot]GitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>
2f5b66bef9 Version Packages (#193)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-09-23 15:27:49 -07:00
63258bc9c3 [React] Expose simple provider and useSDK hook for solana (#179)
Co-authored-by: Jonas Daniels <[email protected]>
2022-09-23 19:12:24 +00:00
Jonas DanielsandGitHub a80fc97b6a [SDK] - update prebuilt contract roles to match contracts (#195) 2022-09-23 18:49:41 +00:00
Adam MajmudarandGitHub 24f66e38c2 Switch to using XHR with timeout (#192) 2022-09-23 05:32:45 +00:00
github-actions[bot]GitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>
b5bfaefa85 Version Packages (#157)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-09-22 17:11:41 -07:00
Adam MajmudarandGitHub 493ebf032e Add upload with gateway url for URIs (#190) 2022-09-22 17:06:59 -07:00
Adam MajmudarandGitHub d608cea197 Add progress tracking to file upload (#189) 2022-09-22 15:15:00 -07:00
Adam MajmudarandGitHub a9ec190ff9 Remove JSON types (#188) 2022-09-22 21:27:43 +00:00
3edec391be [CLI] thirdweb deploy redirects to contract deploy page if no contracts detected (#177)
Co-authored-by: Jonas Daniels <[email protected]>
Co-authored-by: Joaquim Verges <[email protected]>
2022-09-22 14:07:32 -07:00
bdec5a59af [CLI] Fix "Invalid Project name" when a project with a capital letter is entered (#184)
Co-authored-by: Jonas Daniels <[email protected]>
2022-09-22 20:20:15 +00:00
Jonas DanielsandGitHub 9d03619aab fix some lint issues (#187) 2022-09-22 19:02:22 +00:00
Jonas DanielsandGitHub 0ccbca78dc [Storage] - handle special chars (#185) 2022-09-22 11:29:42 -07:00
Adam MajmudarandGitHub 75c752cc14 Fix tests (#186) 2022-09-22 11:06:55 -07:00
Jonas DanielsandGitHub 3580182fa9 [Storage] - allow uploading the same file multiple times in uploadBatch if it is *the same file* (#183) 2022-09-22 09:33:24 +00:00
b54f95dc90 Update expected input types for storage (#163)
Co-authored-by: Jonas Daniels <[email protected]>
2022-09-22 08:12:52 +00:00
Adam MajmudarandGitHub f4074ddadc Replace schemes after replacing files (#180) 2022-09-22 06:43:22 +00:00
Jonas DanielsandGitHub 208b0389a5 [React] - use internal Signer (#168) 2022-09-22 06:04:27 +00:00
3b877ba221 [SDK] Ozdefender EOA forwarder option (#174)
Co-authored-by: Joaquim Verges <[email protected]>
2022-09-22 04:47:00 +00:00
Adam MajmudarandGitHub 45a400fd92 Change API for instantiating storage (#178) 2022-09-21 21:09:11 -07:00
Adam MajmudarandGitHub 3332fa5697 Split create contract flow into steps (#175) 2022-09-21 22:51:47 +00:00
Joaquim VergesandGitHub fdda564b1e [SOL] Fix browser build (#173) 2022-09-21 14:35:19 -07:00
Adam MajmudarandGitHub 89db3db7ff Add changeset for CLI (#172) 2022-09-21 20:15:09 +00:00
Adam MajmudarandGitHub bd9c705571 Add thirdweb deploy to end of thirdweb detect (#171) 2022-09-21 19:55:54 +00:00
Adam MajmudarandGitHub 0ad0f21bcd Display yarn build command at the end of thirdweb create --contract (#169) 2022-09-21 19:18:42 +00:00
Joaquim VergesandGitHub 4169b9428f [SDK] Syntax fixes for react native support (#167) 2022-09-21 09:35:22 -07:00
Jarrod WattsandGitHub 2f9e8aaab4 Jw/lazymintabletwfeature (#165) 2022-09-21 04:17:11 +00:00
Adam MajmudarandGitHub 421461ece0 Add README for Solana and Storage (#164) 2022-09-21 02:39:12 +00:00
Jarrod WattsandGitHub 485ebc8400 [REACT] - Feature snippet generation logic (#155) 2022-09-21 10:40:41 +10:00
Joaquim VergesandGitHub 772f8431e3 [SDK] Catch gas estimate errors in gasless tx (#162) 2022-09-20 23:00:12 +00:00
Joaquim VergesandGitHub 5345479922 [SDK] Allow forcing direct deploys to deploy implementations from release flow (#161) 2022-09-20 15:19:18 -07:00
Adam MajmudarandGitHub cfe8bbafa4 Add resolveScheme method to storage (#156) 2022-09-20 18:31:56 +00:00
Adam MajmudarandGitHub 18dc8d33ed Fix nft collection docs (#159) 2022-09-20 18:07:30 +00:00
Jonas DanielsandGitHub f8ab4779bb init paper checkout in v3 (#154) 2022-09-20 05:41:20 +00:00
Adam MajmudarandGitHub 6fe16c5bf2 Add documentation for Solana (#152) 2022-09-19 22:13:25 -07:00
Adam MajmudarandGitHub ba0e169654 Add support for string with name (#151) 2022-09-19 18:08:55 -07:00
Jarrod WattsandGitHub 27b869ed93 Update README.md (#150) 2022-09-20 00:25:11 +00:00
github-actions[bot]GitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>
091ce2eb45 Version Packages (#149)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-09-19 16:08:23 -07:00
Joaquim Verges e24a371508 fix changeset 2022-09-19 16:03:14 -07:00
Adam MajmudarandGitHub b86afb4b09 Add documentation for storage (#147) 2022-09-19 22:26:44 +00:00
Joaquim VergesandGitHub 964add6f20 [CLI, Storage] Fix deploy/release uploads via CLI (#148) 2022-09-19 14:56:42 -07:00
github-actions[bot]GitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>
ec414bbc42 Version Packages (#136)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-09-19 11:11:34 -07:00
Joaquim VergesandGitHub 51dde28224 [SDK, React] Fix using external signers with ThirdwebSDKProvider (#143) 2022-09-19 18:03:39 +00:00
Adam MajmudarandGitHub 57432d21c4 Update Storage SDK (#139) 2022-09-19 16:58:12 +00:00
Jarrod WattsandGitHub 19d87c2885 Jw/react readme (#144) 2022-09-19 07:20:08 +00:00
Joaquim VergesandGitHub 68812e9d27 Update README.md 2022-09-17 11:29:03 -07:00
Joaquim VergesandGitHub 90c53475f0 Update README.md 2022-09-17 11:23:54 -07:00
Joaquim VergesandGitHub 5a52585a7a [SOL] More solana integration (#140) 2022-09-16 19:15:35 -07:00
Joaquim VergesandGitHub 6b48b9288b [SOL] solana dashboard integration (#138) 2022-09-16 13:19:17 -07:00
Joaquim VergesandGitHub 9d74a43aac [SDK] Make contract events generic for better DX (#133) 2022-09-16 05:51:23 +00:00
Jonas DanielsandGitHub 9c7e5518ff [SOL] - enforce owner when deploying (#137) 2022-09-15 22:24:05 -07:00
Jonas DanielsandGitHub b234c58d44 [SDK] - less rpc calls = good (#135) 2022-09-16 03:43:24 +00:00
Adam MajmudarandGitHub b1ae844e8b Reorder CLI commands (#134) 2022-09-15 20:20:43 -07:00
github-actions[bot]GitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>
78bae497ba Version Packages (#126)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-09-15 14:00:20 -07:00
Joaquim VergesandGitHub 3e425bf8e6 [SOL] get account type for a given address (#132) 2022-09-15 20:54:45 +00:00
Jarrod WattsandGitHub 4dca5b21a6 Change feature detection URLs (#128) 2022-09-15 13:45:04 -07:00
Joaquim VergesandGitHub 42c79e93dc [SDK] fix editing releases from the dashboard (#131) 2022-09-15 19:17:02 +00:00
Joaquim VergesandGitHub 2951b5533c [SOL] New return type for registry.getAccountsForWallet (#130) 2022-09-15 18:09:52 +00:00
Joaquim VergesandGitHub fe8751eeae [SDK] add ownable feature detection (#124) 2022-09-15 17:41:32 +00:00
Jonas DanielsandGitHub a0cd47ec35 [SOL] - explicitly export the missing schemata (#129) 2022-09-15 17:13:20 +00:00
Jarrod WattsandGitHub 3902e7aba4 Update read and write hook names for snippet generation (#127) 2022-09-15 17:36:23 +10:00
github-actions[bot]GitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>
8717cb2c05 Version Packages (#118)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-09-14 19:38:16 -07:00
Jarrod WattsandGitHub d57ab03f5d Add useContract hook snippet back in (#125) 2022-09-15 12:34:57 +10:00
Joaquim VergesandGitHub 5aa3c433d7 [Solana] Add sdk.wallet.getBalance() (#123) 2022-09-14 19:27:52 +00:00
Joaquim VergesandGitHub 98dd64a375 [SDK] handle legacy claim method signature in extensions (#122) 2022-09-14 19:15:47 +00:00
Joaquim VergesandGitHub e25dd1ac8e [Solana] Handle WalletAdapter connections, internal cleanup (#120) 2022-09-14 05:04:08 +00:00
Jonas DanielsandGitHub e68f9685b3 fix snippets (#119) 2022-09-14 03:16:58 +00:00
Joaquim VergesandGitHub 84beda1cbb [Solana] Create account registry (#117) 2022-09-13 16:22:00 -07:00
255 changed files with 10144 additions and 5432 deletions
+6 -2
View File
@@ -26,7 +26,8 @@
"version-packages": "changeset version",
"release": "node ./scripts/pre-release.mjs && changeset publish",
"version-packages:nightly": "changeset version --snapshot nightly",
"release:nightly": "node ./scripts/pre-release.mjs && changeset publish --tag nightly"
"release:nightly": "node ./scripts/pre-release.mjs && changeset publish --tag nightly",
"push": "turbo run push"
},
"preconstruct": {
"packages": [
@@ -43,9 +44,12 @@
"eslint": "^8.21.0",
"postinstall-postinstall": "^2.1.0",
"prettier": "^2.7.1",
"turbo": "latest"
"turbo": "^1.4.6"
},
"manypkg": {
"defaultBranch": "main"
},
"devDependencies": {
"yalc": "^1.0.0-pre.53"
}
}
+49
View File
@@ -1,5 +1,54 @@
# @thirdweb-dev/auth
## 2.0.7
### Patch Changes
- Updated dependencies [[`5f5ab01`](https://github.com/thirdweb-dev/js/commit/5f5ab015e1dd3c471d6affe995ef36ec88932b3c)]:
- @thirdweb-dev/sdk@3.0.7
## 2.0.6
### Patch Changes
- Updated dependencies [[`a80fc97`](https://github.com/thirdweb-dev/js/commit/a80fc97b6a1e72ed46a400b4b602e180947fb870)]:
- @thirdweb-dev/sdk@3.0.6
## 2.0.5
### Patch Changes
- Updated dependencies [[`4169b94`](https://github.com/thirdweb-dev/js/commit/4169b9428f9001b7cad259a4e56fe610316cd191), [`3b877ba`](https://github.com/thirdweb-dev/js/commit/3b877ba221acfd85f80b99e1bc382055217f0a39), [`b54f95d`](https://github.com/thirdweb-dev/js/commit/b54f95dc906928ff2f9251748f254a16fe1f2cee), [`f8ab477`](https://github.com/thirdweb-dev/js/commit/f8ab4779bb2d6d66200e1e8fd558e0ac069a2f54), [`772f843`](https://github.com/thirdweb-dev/js/commit/772f8431e3a62d0ded62dae90a43e9a7edd5b1a2), [`a9ec190`](https://github.com/thirdweb-dev/js/commit/a9ec190ff99d2714cef2500d20ea0f3f73f07be3), [`208b038`](https://github.com/thirdweb-dev/js/commit/208b0389a50ea48bbb9600fec60fec2f1671d4b9), [`5345479`](https://github.com/thirdweb-dev/js/commit/534547992243bdd3a77e34ec2b2487b5adab366a)]:
- @thirdweb-dev/sdk@3.0.5
## 2.0.4
### Patch Changes
- Updated dependencies []:
- @thirdweb-dev/sdk@3.0.4
## 2.0.3
### Patch Changes
- Updated dependencies [[`51dde28`](https://github.com/thirdweb-dev/js/commit/51dde28224209f1b8b26f436c204a5e702281564), [`9d74a43`](https://github.com/thirdweb-dev/js/commit/9d74a43aac21448beba63ba4e2637945965a3634), [`b234c58`](https://github.com/thirdweb-dev/js/commit/b234c58d44d8322e44b2d2ba87ad4ec7d699e961)]:
- @thirdweb-dev/sdk@3.0.3
## 2.0.2
### Patch Changes
- Updated dependencies [[`42c79e9`](https://github.com/thirdweb-dev/js/commit/42c79e93dc958ca46a55d705aeea44ffdbbcc5f6), [`fe8751e`](https://github.com/thirdweb-dev/js/commit/fe8751eeae7ad013b890a8092ddbd091ecbd6708)]:
- @thirdweb-dev/sdk@3.0.2
## 2.0.1
### Patch Changes
- Updated dependencies [[`98dd64a`](https://github.com/thirdweb-dev/js/commit/98dd64a375c302a879aab3c628ecfb84b4dd19da)]:
- @thirdweb-dev/sdk@3.0.1
## 2.0.0
### Patch Changes
+3 -3
View File
@@ -1,6 +1,6 @@
{
"name": "@thirdweb-dev/auth",
"version": "2.0.0",
"version": "2.0.7",
"exports": {
"./package.json": "./package.json",
"./express": {
@@ -60,7 +60,7 @@
"eslint-plugin-tsdoc": "^0.2.16",
"ethers": "^5.7.0",
"express": "^4.18.1",
"next": "12.2.0",
"next": "^12.2.0",
"next-auth": "^4.10.3",
"prettier": "^2.7.1",
"typescript": "^4.7.4"
@@ -69,7 +69,7 @@
"@thirdweb-dev/sdk": "*",
"ethers": ">=5.5.1",
"express": "^4.18.1",
"next": "12.2.0",
"next": "^12.2.0",
"next-auth": "^4.10.3"
},
"peerDependenciesMeta": {
+63
View File
@@ -1,5 +1,68 @@
# thirdweb
## 0.7.18
### Patch Changes
- Updated dependencies [[`5f5ab01`](https://github.com/thirdweb-dev/js/commit/5f5ab015e1dd3c471d6affe995ef36ec88932b3c)]:
- @thirdweb-dev/sdk@3.0.7
## 0.7.17
### Patch Changes
- Updated dependencies [[`a80fc97`](https://github.com/thirdweb-dev/js/commit/a80fc97b6a1e72ed46a400b4b602e180947fb870)]:
- @thirdweb-dev/sdk@3.0.6
## 0.7.16
### Patch Changes
- [#172](https://github.com/thirdweb-dev/js/pull/172) [`89db3db`](https://github.com/thirdweb-dev/js/commit/89db3db7ff3d5af7e7a7b5f25e299b9faad44eb0) Thanks [@adam-maj](https://github.com/adam-maj)! - Add thirdweb deploy to end of thirdweb detect and yarn build to thirdweb create
- [#175](https://github.com/thirdweb-dev/js/pull/175) [`3332fa5`](https://github.com/thirdweb-dev/js/commit/3332fa5697b9ff2a4ded1f2c508304f59f434be2) Thanks [@adam-maj](https://github.com/adam-maj)! - Split create contract flow into two steps
- [#177](https://github.com/thirdweb-dev/js/pull/177) [`3edec39`](https://github.com/thirdweb-dev/js/commit/3edec391be169453aaee412846005a820939fab0) Thanks [@adam-maj](https://github.com/adam-maj)! - thirdweb deploy redirects to contract deploy page if no contracts detected
- [#184](https://github.com/thirdweb-dev/js/pull/184) [`bdec5a5`](https://github.com/thirdweb-dev/js/commit/bdec5a59af680802e206e3025b2c463fc7dcb740) Thanks [@aeither](https://github.com/aeither)! - Fix "Invalid Project name" when a project with a capital letter is entered
- Updated dependencies [[`4169b94`](https://github.com/thirdweb-dev/js/commit/4169b9428f9001b7cad259a4e56fe610316cd191), [`3b877ba`](https://github.com/thirdweb-dev/js/commit/3b877ba221acfd85f80b99e1bc382055217f0a39), [`b54f95d`](https://github.com/thirdweb-dev/js/commit/b54f95dc906928ff2f9251748f254a16fe1f2cee), [`f8ab477`](https://github.com/thirdweb-dev/js/commit/f8ab4779bb2d6d66200e1e8fd558e0ac069a2f54), [`772f843`](https://github.com/thirdweb-dev/js/commit/772f8431e3a62d0ded62dae90a43e9a7edd5b1a2), [`a9ec190`](https://github.com/thirdweb-dev/js/commit/a9ec190ff99d2714cef2500d20ea0f3f73f07be3), [`208b038`](https://github.com/thirdweb-dev/js/commit/208b0389a50ea48bbb9600fec60fec2f1671d4b9), [`5345479`](https://github.com/thirdweb-dev/js/commit/534547992243bdd3a77e34ec2b2487b5adab366a)]:
- @thirdweb-dev/sdk@3.0.5
## 0.7.15
### Patch Changes
- [#148](https://github.com/thirdweb-dev/js/pull/148) [`964add6`](https://github.com/thirdweb-dev/js/commit/964add6f205577298b8f4b9ce7298e5bf09e88e7) Thanks [@joaquim-verges](https://github.com/joaquim-verges)! - Fix deploy/release CLI uploads
- Updated dependencies []:
- @thirdweb-dev/sdk@3.0.4
## 0.7.14
### Patch Changes
- [#134](https://github.com/thirdweb-dev/js/pull/134) [`b1ae844`](https://github.com/thirdweb-dev/js/commit/b1ae844e8bbed59c0225b32f4115ae384fa23ef5) Thanks [@adam-maj](https://github.com/adam-maj)! - Update ordering of commands in npx thirdweb
- Updated dependencies [[`51dde28`](https://github.com/thirdweb-dev/js/commit/51dde28224209f1b8b26f436c204a5e702281564), [`9d74a43`](https://github.com/thirdweb-dev/js/commit/9d74a43aac21448beba63ba4e2637945965a3634), [`b234c58`](https://github.com/thirdweb-dev/js/commit/b234c58d44d8322e44b2d2ba87ad4ec7d699e961)]:
- @thirdweb-dev/sdk@3.0.3
## 0.7.13
### Patch Changes
- [#128](https://github.com/thirdweb-dev/js/pull/128) [`4dca5b2`](https://github.com/thirdweb-dev/js/commit/4dca5b21a66fe8ff4c4b24663e1b9ad6c446b7e2) Thanks [@jarrodwatts](https://github.com/jarrodwatts)! - Add new documentation for detectable features
- Updated dependencies [[`42c79e9`](https://github.com/thirdweb-dev/js/commit/42c79e93dc958ca46a55d705aeea44ffdbbcc5f6), [`fe8751e`](https://github.com/thirdweb-dev/js/commit/fe8751eeae7ad013b890a8092ddbd091ecbd6708)]:
- @thirdweb-dev/sdk@3.0.2
## 0.7.12
### Patch Changes
- Updated dependencies [[`98dd64a`](https://github.com/thirdweb-dev/js/commit/98dd64a375c302a879aab3c628ecfb84b4dd19da)]:
- @thirdweb-dev/sdk@3.0.1
## 0.7.11
### Patch Changes
+2 -1
View File
@@ -3,7 +3,8 @@ export const CREATE_MESSAGES = {
projectName: "What is your project named?",
framework: "What framework do you want to use?",
language: "What language do you want to use?",
contract: "What contract do you want to start from?",
contract: "What type of contract do you want to start from?",
extensions: "What extensions do you want to add to your contract?",
} as const;
export const ERROR_MESSAGES = {
+4 -1
View File
@@ -20,9 +20,12 @@ describe("npx thirdweb detect", () => {
// select hardhat
await create.pressKey("enter");
await create.waitForText(CREATE_MESSAGES.contract);
// select ERC721Base
// select ERC721
await create.pressKey("arrowDown");
await create.pressKey("enter");
await create.waitForText(CREATE_MESSAGES.extensions);
// select no extra extensions
await create.pressKey("enter");
// wait for program to finish
await create.waitForFinish();
+1 -2
View File
@@ -1,7 +1,7 @@
{
"name": "thirdweb",
"main": "dist/cli/index.js",
"version": "0.7.11",
"version": "0.7.18",
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/cli",
"author": "thirdweb eng <[email protected]>",
"license": "Apache-2.0",
@@ -25,7 +25,6 @@
"prettier": "^2.7.1",
"ts-jest": "^28.0.8",
"ts-node": "^10.7.0",
"tsc": "^2.0.4",
"tsup": "^6.2.3",
"typescript": "^4.7.4"
},
+46 -46
View File
@@ -39,31 +39,34 @@ $$$$$$\\ $$$$$$$\\ $$\\ $$$$$$\\ $$$$$$$ |$$\\ $$\\ $$\\ $$$$$$\\ $$$$
.version(cliVersion, "-v, --version");
program
.command("detect")
.command("create")
.description(
"Compile contracts and detect implemented thirdweb contract extensions",
"Create a thirdweb app from any of our official templates. Checkout some examples you can use here: https://github.com/thirdweb-example/",
)
.option("-p, --path <project-path>", "path to project", ".")
.option("-d, --debug", "show debug logs")
.option("-a, --all", "run detection on all contracts")
.action(async (options) => {
await detectExtensions(options);
});
program
.command("release")
.description(
"Release contracts, making them available for others to deploy and unlocking SDKs, Dashboards and Analytics.",
.option("--app", `Create a thirdweb app.`)
.option("--contract", `Create a thirdweb contracts project.`)
.option("--ts, --typescript", `Initialize as a TypeScript project.`)
.option("--js, --javascript", `Initialize as a JavaScript project.`)
.option("--forge", `Initialize as a Forge project.`)
.option("--hardhat", `Initialize as a Hardhat project.`)
.option("--cra", `Initialize as a Create React App project.`)
.option("--next", `Initialize as a Next.js project.`)
.option("--vite", `Initialize as a Vite project.`)
.option(
"--use-npm",
`Explicitly tell the CLI to bootstrap the app using npm`,
)
.option(
"--use-pnpm",
`Explicitly tell the CLI to bootstrap the app using pnpm`,
)
.option("--framework [name]", `The preferred framework.`)
.option(
"-t, --template [name]",
`A template to start your project from. You can use an template repository name from the official thirdweb-example org.`,
)
.option("-p, --path <project-path>", "path to project", ".")
.option("--dry-run", "dry run (skip actually publishing)")
.option("-d, --debug", "show debug logs")
.option("--ci", "Continuous Integration mode")
.action(async (options) => {
const url = await processProject(options, "release");
info(`Open this link to release your contracts:`);
logger.info(chalk.blueBright(url.toString()));
open(url.toString());
await twCreate(options);
});
program
@@ -111,34 +114,31 @@ $$$$$$\\ $$$$$$$\\ $$\\ $$$$$$\\ $$$$$$$ |$$\\ $$\\ $$\\ $$$$$$\\ $$$$
});
program
.command("create")
.command("release")
.description(
"Create a thirdweb app from any of our official templates. Checkout some examples you can use here: https://github.com/thirdweb-example/",
)
.option("--app", `Create a thirdweb app.`)
.option("--contract", `Create a thirdweb contracts project.`)
.option("--ts, --typescript", `Initialize as a TypeScript project.`)
.option("--js, --javascript", `Initialize as a JavaScript project.`)
.option("--forge", `Initialize as a Forge project.`)
.option("--hardhat", `Initialize as a Hardhat project.`)
.option("--cra", `Initialize as a Create React App project.`)
.option("--next", `Initialize as a Next.js project.`)
.option("--vite", `Initialize as a Vite project.`)
.option(
"--use-npm",
`Explicitly tell the CLI to bootstrap the app using npm`,
)
.option(
"--use-pnpm",
`Explicitly tell the CLI to bootstrap the app using pnpm`,
)
.option("--framework [name]", `The preferred framework.`)
.option(
"-t, --template [name]",
`A template to start your project from. You can use an template repository name from the official thirdweb-example org.`,
"Release contracts, making them available for others to deploy and unlocking SDKs, Dashboards and Analytics.",
)
.option("-p, --path <project-path>", "path to project", ".")
.option("--dry-run", "dry run (skip actually publishing)")
.option("-d, --debug", "show debug logs")
.option("--ci", "Continuous Integration mode")
.action(async (options) => {
await twCreate(options);
const url = await processProject(options, "release");
info(`Open this link to release your contracts:`);
logger.info(chalk.blueBright(url.toString()));
open(url.toString());
});
program
.command("detect")
.description(
"Compile contracts and detect implemented thirdweb contract extensions",
)
.option("-p, --path <project-path>", "path to project", ".")
.option("-d, --debug", "show debug logs")
.option("-a, --all", "run detection on all contracts")
.action(async (options) => {
await detectExtensions(options);
});
program
+3 -3
View File
@@ -1,5 +1,5 @@
import { spinner } from "../core/helpers/logger";
import { IpfsStorage } from "@thirdweb-dev/storage";
import { ThirdwebStorage } from "@thirdweb-dev/storage";
import { existsSync, mkdirSync, writeFileSync } from "fs";
import path, { join } from "path";
@@ -13,10 +13,10 @@ export async function installGithubAction(options: any) {
: path.resolve(`${projectPath}/${options.path}`);
projectPath = resolvedPath;
}
const storage = new IpfsStorage();
const storage = new ThirdwebStorage();
const log = spinner("Installing thirdweb Github Action...");
try {
const ghActionData = await storage.getRaw(ghActionHash);
const ghActionData = await (await storage.download(ghActionHash)).text();
const dir = join(projectPath, ".github/workflows");
if (!existsSync(dir)) {
mkdirSync(dir, { recursive: true });
+24 -2
View File
@@ -5,8 +5,10 @@ import { logger, spinner } from "../core/helpers/logger";
import { createContractsPrompt } from "../core/helpers/selector";
import { ContractFeatures, Feature } from "../core/interfaces/ContractFeatures";
import { ContractPayload } from "../core/interfaces/ContractPayload";
import { getPkgManager } from "../create/helpers/get-pkg-manager";
import { detectFeatures, FeatureWithEnabled } from "@thirdweb-dev/sdk";
import chalk from "chalk";
import { existsSync, readFileSync } from "fs";
import ora from "ora";
import path from "path";
@@ -70,13 +72,13 @@ export async function detectExtensions(options: any) {
const enabledFeatures: Feature[] = features.enabledFeatures.map(
(feature) => ({
name: feature.name,
reference: `https://portal.thirdweb.com/contracts/${feature.docLinks.contracts}`,
reference: `https://portal.thirdweb.com/extensions/${feature.name.toLowerCase()}`,
}),
);
const suggestedFeatures: Feature[] = features.suggestedFeatures.map(
(feature) => ({
name: feature.name,
reference: `https://portal.thirdweb.com/contracts/${feature.docLinks.contracts}`,
reference: `https://portal.thirdweb.com/extensions/${feature.name.toLowerCase()}`,
}),
);
@@ -113,6 +115,26 @@ export async function detectExtensions(options: any) {
)} - ${chalk.dim(chalk.gray(feature.reference))}`,
);
});
let deployCmd = `npx thirdweb@latest deploy`;
if (existsSync(projectPath + "/package.json")) {
const packageManager = getPkgManager();
const useYarn = packageManager === "yarn";
const pkgJson = JSON.parse(
readFileSync(projectPath + "/package.json", "utf-8"),
);
if (pkgJson?.scripts?.deploy === deployCmd) {
deployCmd = `${packageManager}${useYarn ? "" : " run"} deploy`;
}
}
logger.info(``);
ora(
`Once you're done writing your contracts, you can run the following command to deploy them:`,
).info();
logger.info(``);
logger.info(` ${chalk.cyan(deployCmd)}`);
logger.info(``);
});
}
+36 -12
View File
@@ -1,13 +1,14 @@
import { THIRDWEB_URL, cliVersion } from "../constants/urls";
import { cliVersion, THIRDWEB_URL } from "../constants/urls";
import build from "../core/builder/build";
import detect from "../core/detection/detect";
import { execute } from "../core/helpers/exec";
import { error, info, logger, spinner } from "../core/helpers/logger";
import { createContractsPrompt } from "../core/helpers/selector";
import { ContractPayload } from "../core/interfaces/ContractPayload";
import { IpfsStorage } from "@thirdweb-dev/storage";
import { ThirdwebStorage } from "@thirdweb-dev/storage";
import chalk from "chalk";
import { readFileSync } from "fs";
import ora from "ora";
import path from "path";
export async function processProject(
@@ -15,7 +16,7 @@ export async function processProject(
command: "deploy" | "release",
) {
// TODO: allow overriding the default storage
const storage = new IpfsStorage();
const storage = new ThirdwebStorage();
logger.setSettings({
minLevel: options.debug ? "debug" : "info",
@@ -35,6 +36,27 @@ export async function processProject(
const projectType = await detect(projectPath, options);
if (projectType === "none") {
if (command === "deploy") {
info(
"No contracts detected in this directory. Redirecting to the thirdweb contract deployment page.",
);
return "https://thirdweb.com/contracts";
}
error("No detected contracts in this directory.");
logger.info(``);
ora(
`Detected contract files must end with the '.sol' extension and exist in this directory or the '/contracts' subdirectory`,
).info();
logger.info(``);
ora("To create a new contracts project, run the following command:").info();
logger.info(``);
logger.info(` ${chalk.cyan(`npx thirdweb@latest create --contract`)}`);
logger.info(``);
process.exit(1);
}
if (options.ci) {
logger.info("Installing dependencies...");
try {
@@ -129,7 +151,9 @@ export async function processProject(
if (file.includes(soliditySDKPackage)) {
usesSoliditySDK = true;
}
return await storage.uploadSingle(file);
return await storage.upload(file, {
uploadWithoutDirectory: true,
});
}),
);
}
@@ -140,14 +164,15 @@ export async function processProject(
const metadataURIs = await Promise.all(
selectedContracts.map(async (c) => {
logger.debug(`Uploading ${c.name}...`);
const hash = await storage.uploadSingle(c.metadata);
return `ipfs://${hash}`;
return await storage.upload(JSON.parse(c.metadata), {
uploadWithoutDirectory: true,
});
}),
);
// Upload batch all bytecodes
const bytecodes = selectedContracts.map((c) => c.bytecode);
const { uris: bytecodeURIs } = await storage.uploadBatch(bytecodes);
const bytecodeURIs = await storage.uploadBatch(bytecodes);
const combinedContents = selectedContracts.map((c, i) => {
// attach analytics blob to metadata
@@ -169,14 +194,13 @@ export async function processProject(
let combinedURIs: string[] = [];
if (combinedContents.length === 1) {
// use upload single if only one contract to get a clean IPFS hash
const metadataUri = await storage.uploadSingle(
JSON.stringify(combinedContents[0]),
);
const metadataUri = await storage.upload(combinedContents[0], {
uploadWithoutDirectory: true,
});
combinedURIs.push(metadataUri);
} else {
// otherwise upload batch
const { uris } = await storage.uploadMetadataBatch(combinedContents);
combinedURIs = uris;
combinedURIs = await storage.uploadBatch(combinedContents);
}
loader.succeed("Upload successful");
+2 -2
View File
@@ -21,7 +21,7 @@ contract Contract is ERC721Base {
{}
}`,
ERC721Signature: `// SPDX-License-Identifier: Apache-2.0
ERC721SignatureMint: `// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.0;
import "@thirdweb-dev/contracts/base/ERC721SignatureMint.sol";
@@ -113,7 +113,7 @@ contract Contract is ERC1155Base {
{}
}`,
ERC1155Signature: `// SPDX-License-Identifier: Apache-2.0
ERC1155SignatureMint: `// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.0;
import "@thirdweb-dev/contracts/base/ERC1155SignatureMint.sol";
+40 -11
View File
@@ -5,7 +5,9 @@ import { Detector } from "./detector";
import FoundryDetector from "./foundry";
import HardhatDetector from "./hardhat";
import TruffleDetector from "./truffle";
import fs, { exists, existsSync } from "fs";
import inquirer from "inquirer";
import { parse } from "path";
const { Confirm } = require("enquirer");
@@ -26,18 +28,24 @@ export default async function detect(
//if there is no project returned at all then just return unknown}
if (!possibleProjectTypes.length) {
warn(`${ERROR_MESSAGES.noConfiguration} ${path}`);
const prompt = new Confirm({
name: "continue",
message:
"Do you want to continue and compile this project with solc instead?",
});
const shouldCompile = await prompt.run();
if (!shouldCompile) {
logger.warn("Aborted contract compilation");
process.exit(1);
const canCompile = hasContracts(path);
if (canCompile) {
warn(`${ERROR_MESSAGES.noConfiguration} ${path}`);
const prompt = new Confirm({
name: "continue",
message:
"Do you want to continue and compile this project with solc instead?",
});
const shouldCompile = await prompt.run();
if (!shouldCompile) {
logger.warn("Aborted contract compilation");
process.exit(1);
}
return "solc";
} else {
return "none";
}
return "unknown";
}
//if there is only one possible option just return it
if (possibleProjectTypes.length === 1) {
@@ -64,3 +72,24 @@ export default async function detect(
return answer[question];
}
}
// Check if a directory has any .sol files or a /contracts folder with .sol files
function hasContracts(path: any) {
return (
["", "/contracts"].filter((p) => {
const dirPath = path + p;
if (!existsSync(dirPath)) {
return false;
}
const files = fs.readdirSync(dirPath);
const contracts = files.filter((filePath) => {
const { ext } = parse(filePath);
return ext === ".sol";
});
return contracts.length > 0;
}).length > 0
);
}
+2 -1
View File
@@ -3,4 +3,5 @@ export type ProjectType =
| "foundry"
| "hardhat"
| "truffle"
| "unknown";
| "solc"
| "none";
+57 -26
View File
@@ -90,8 +90,11 @@ export async function twCreate(options: any) {
name: "path",
message: CREATE_MESSAGES.projectName,
initial: options.template || defaultName,
validate: (name) => {
const validation = validateNpmName(path.basename(path.resolve(name)));
format: (name: string) => name.toLowerCase(),
validate: (name: string) => {
const validation = validateNpmName(
path.basename(path.resolve(name.toLowerCase())),
);
if (validation.valid) {
return true;
}
@@ -175,36 +178,64 @@ export async function twCreate(options: any) {
// Select base contract
if (projectType === "contract" && !baseContract) {
const res = await prompts({
let standard = "none";
const standardPrompt = await prompts({
type: "select",
name: "baseContract",
name: "standard",
message: CREATE_MESSAGES.contract,
choices: [
{ title: "Empty Contract", value: "" },
{ title: "ERC721 Base", value: "ERC721Base" },
{ title: "ERC721 + Signature Mint", value: "ERC721Signature" },
{ title: "ERC721 + Lazy Mint", value: "ERC721LazyMint" },
{ title: "ERC721 + Delayed Reveal", value: "ERC721DelayedReveal" },
{ title: "ERC721 + Drop", value: "ERC721Drop" },
{ title: "ERC1155 Base", value: "ERC1155Base" },
{ title: "ERC1155 + Signature Mint", value: "ERC1155Signature" },
{ title: "ERC1155 + Lazy Mint", value: "ERC1155LazyMint" },
{ title: "ERC1155 + Delayed Reveal", value: "ERC1155DelayedReveal" },
{ title: "ERC1155 + Drop", value: "ERC1155Drop" },
{ title: "ERC20 Base", value: "ERC20Base" },
{ title: "ERC20 + Vote", value: "ERC20Vote" },
{ title: "ERC20 + Signature Mint", value: "ERC20SignatureMint" },
{
title: "ERC20 + Vote + Signature Mint",
value: "ERC20SignatureMintVote",
},
{ title: "ERC20 + Drop", value: "ERC20Drop" },
{ title: "ERC20 + Vote + Drop", value: "ERC20DropVote" },
{ title: "Empty Contract", value: "none" },
{ title: "ERC721", value: "erc721" },
{ title: "ERC20", value: "erc20" },
{ title: "ERC1155", value: "erc1155" },
],
});
if (typeof res.baseContract === "string") {
baseContract = res.baseContract.trim();
if (typeof standardPrompt.standard === "string") {
standard = standardPrompt.standard.trim();
}
if (standard === "none") {
baseContract = "";
} else {
let choices: prompts.Choice[] = [];
if (standard === "erc721") {
choices = [
{ title: "None", value: "ERC721Base" },
{ title: "Signature Mint", value: "ERC721SignatureMint" },
{ title: "Lazy Mint", value: "ERC721LazyMint" },
{ title: "Delayed Reveal", value: "ERC721DelayedReveal" },
{ title: "Drop", value: "ERC721Drop" },
];
} else if (standard === "erc20") {
choices = [
{ title: "None", value: "ERC20Base" },
{ title: "Vote", value: "ERC20Vote" },
{ title: "Signature Mint", value: "ERC20SignatureMint" },
{ title: "Vote + Signature Mint", value: "ERC20SignatureMintVote" },
{ title: "Drop", value: "ERC20Drop" },
{ title: "Vote + Drop", value: "ERC20DropVote" },
];
} else if (standard === "erc1155") {
choices = [
{ title: "None", value: "ERC1155Base" },
{ title: "Signature Mint", value: "ERC1155SignatureMint" },
{ title: "Lazy Mint", value: "ERC1155LazyMint" },
{ title: "Delayed Reveal", value: "ERC1155DelayedReveal" },
{ title: "Drop", value: "ERC1155Drop" },
];
}
const res = await prompts({
type: "select",
name: "baseContract",
message: CREATE_MESSAGES.extensions,
choices: choices,
});
if (typeof res.baseContract === "string") {
baseContract = res.baseContract.trim();
}
}
}
@@ -145,15 +145,21 @@ export async function createContract({
console.log(
`${chalk.green("Success!")} Created ${projectName} at ${contractPath}`,
);
console.log();
console.log("Inside that directory, you can run several commands:");
console.log();
console.log(chalk.cyan(` ${packageManager} ${useYarn ? "" : "run"} deploy`));
console.log(chalk.cyan(` ${packageManager}${useYarn ? "" : " run"} build`));
console.log(
" Compiles your contracts and detects thirdweb extensions implemented on them.",
);
console.log();
console.log(chalk.cyan(` ${packageManager}${useYarn ? "" : " run"} deploy`));
console.log(" Deploys your contracts with the thirdweb deploy flow.");
console.log();
console.log(
chalk.cyan(` ${packageManager} ${useYarn ? "" : "run"} release`),
chalk.cyan(` ${packageManager}${useYarn ? "" : " run"} release`),
);
console.log(" Releases your contracts with the thirdweb release flow..");
console.log(" Releases your contracts with the thirdweb release flow.");
console.log();
console.log("We suggest that you begin by typing:");
console.log();
+2 -2
View File
@@ -4,8 +4,8 @@
"main": "index.js",
"license": "Apache-2.0",
"dependencies": {
"@typescript-eslint/eslint-plugin": "^5.36.2",
"@typescript-eslint/parser": "^5.36.2",
"@typescript-eslint/eslint-plugin": "^5.33.0",
"@typescript-eslint/parser": "^5.33.0",
"eslint-config-next": "^12.0.8",
"eslint-config-prettier": "^8.3.0",
"eslint-config-turbo": "latest",
+65
View File
@@ -1,5 +1,70 @@
# @thirdweb-dev/react
## 3.0.7
### Patch Changes
- [#197](https://github.com/thirdweb-dev/js/pull/197) [`f4f05bd`](https://github.com/thirdweb-dev/js/commit/f4f05bd9a4ec98e9abc6716006353f330b7be055) Thanks [@jnsdls](https://github.com/jnsdls)! - make it obvious when the <Web3Button /> will trigger a network switch
- Updated dependencies [[`5f5ab01`](https://github.com/thirdweb-dev/js/commit/5f5ab015e1dd3c471d6affe995ef36ec88932b3c), [`5f5ab01`](https://github.com/thirdweb-dev/js/commit/5f5ab015e1dd3c471d6affe995ef36ec88932b3c)]:
- @thirdweb-dev/sdk@3.0.7
- @thirdweb-dev/solana@0.2.15
## 3.0.6
### Patch Changes
- [#179](https://github.com/thirdweb-dev/js/pull/179) [`63258bc`](https://github.com/thirdweb-dev/js/commit/63258bc9c3443db7d12fc1dc6fbd483926c92d3e) Thanks [@joaquim-verges](https://github.com/joaquim-verges)! - Expose simple provider and useSDK hooks for Solana
- Updated dependencies [[`a80fc97`](https://github.com/thirdweb-dev/js/commit/a80fc97b6a1e72ed46a400b4b602e180947fb870)]:
- @thirdweb-dev/sdk@3.0.6
- @thirdweb-dev/solana@0.2.14
## 3.0.5
### Patch Changes
- [#167](https://github.com/thirdweb-dev/js/pull/167) [`4169b94`](https://github.com/thirdweb-dev/js/commit/4169b9428f9001b7cad259a4e56fe610316cd191) Thanks [@joaquim-verges](https://github.com/joaquim-verges)! - Syntax changes for react native support
- [#168](https://github.com/thirdweb-dev/js/pull/168) [`208b038`](https://github.com/thirdweb-dev/js/commit/208b0389a50ea48bbb9600fec60fec2f1671d4b9) Thanks [@jnsdls](https://github.com/jnsdls)! - use internals wherever possible to allow wider usecases with `<ThirdwebSDKProvider>` & add invariants to catch improper use of functionality that requires the full `<ThirdwebProvider` earlier
- [#168](https://github.com/thirdweb-dev/js/pull/168) [`208b038`](https://github.com/thirdweb-dev/js/commit/208b0389a50ea48bbb9600fec60fec2f1671d4b9) Thanks [@jnsdls](https://github.com/jnsdls)! - fix case where `<ConnectWallet />` button would get stuck when user cancels connection
- [#168](https://github.com/thirdweb-dev/js/pull/168) [`208b038`](https://github.com/thirdweb-dev/js/commit/208b0389a50ea48bbb9600fec60fec2f1671d4b9) Thanks [@jnsdls](https://github.com/jnsdls)! - allow passing `className` to `<ConnectWallet />` and `<Web3Button />` for possible style overrides
- Updated dependencies [[`4169b94`](https://github.com/thirdweb-dev/js/commit/4169b9428f9001b7cad259a4e56fe610316cd191), [`3b877ba`](https://github.com/thirdweb-dev/js/commit/3b877ba221acfd85f80b99e1bc382055217f0a39), [`b54f95d`](https://github.com/thirdweb-dev/js/commit/b54f95dc906928ff2f9251748f254a16fe1f2cee), [`f8ab477`](https://github.com/thirdweb-dev/js/commit/f8ab4779bb2d6d66200e1e8fd558e0ac069a2f54), [`772f843`](https://github.com/thirdweb-dev/js/commit/772f8431e3a62d0ded62dae90a43e9a7edd5b1a2), [`a9ec190`](https://github.com/thirdweb-dev/js/commit/a9ec190ff99d2714cef2500d20ea0f3f73f07be3), [`208b038`](https://github.com/thirdweb-dev/js/commit/208b0389a50ea48bbb9600fec60fec2f1671d4b9), [`5345479`](https://github.com/thirdweb-dev/js/commit/534547992243bdd3a77e34ec2b2487b5adab366a)]:
- @thirdweb-dev/sdk@3.0.5
## 3.0.4
### Patch Changes
- Updated dependencies []:
- @thirdweb-dev/sdk@3.0.4
## 3.0.3
### Patch Changes
- [#143](https://github.com/thirdweb-dev/js/pull/143) [`51dde28`](https://github.com/thirdweb-dev/js/commit/51dde28224209f1b8b26f436c204a5e702281564) Thanks [@joaquim-verges](https://github.com/joaquim-verges)! - Fix using external signers with ThirdwebSDKProvider
- Updated dependencies [[`51dde28`](https://github.com/thirdweb-dev/js/commit/51dde28224209f1b8b26f436c204a5e702281564), [`9d74a43`](https://github.com/thirdweb-dev/js/commit/9d74a43aac21448beba63ba4e2637945965a3634), [`b234c58`](https://github.com/thirdweb-dev/js/commit/b234c58d44d8322e44b2d2ba87ad4ec7d699e961)]:
- @thirdweb-dev/sdk@3.0.3
## 3.0.2
### Patch Changes
- Updated dependencies [[`42c79e9`](https://github.com/thirdweb-dev/js/commit/42c79e93dc958ca46a55d705aeea44ffdbbcc5f6), [`fe8751e`](https://github.com/thirdweb-dev/js/commit/fe8751eeae7ad013b890a8092ddbd091ecbd6708)]:
- @thirdweb-dev/sdk@3.0.2
## 3.0.1
### Patch Changes
- Updated dependencies [[`98dd64a`](https://github.com/thirdweb-dev/js/commit/98dd64a375c302a879aab3c628ecfb84b4dd19da)]:
- @thirdweb-dev/sdk@3.0.1
## 3.0.0
### Major Changes
+177 -54
View File
@@ -13,9 +13,17 @@
<p align="center"><strong>Ultimate collection of React hooks for your web3 apps</strong></p>
<br />
<br />
## Installation
You can install this SDK with either `npm` or `yarn`:
The easiest way to get started with the React SDK is to use the CLI:
```sh
npx thirdweb create --app
```
Alternatively, you can install the SDK into your existing project using npm or yarn:
```sh
npm install @thirdweb-dev/react @thirdweb-dev/sdk ethers
@@ -25,21 +33,19 @@ npm install @thirdweb-dev/react @thirdweb-dev/sdk ethers
yarn add @thirdweb-dev/react @thirdweb-dev/sdk ethers
```
## Starter Templates
<br />
We provide template repositories that already have the thirdweb React SDK setup and ready-to-go to help you get started with thirdweb quickly. You can find all the available starter respositories below.
## Getting Started
- Next.js ([typescript](https://github.com/thirdweb-example/next-typescript-starter) / [javascript](https://github.com/thirdweb-example/next-javascript-starter))
- Create React App ([typescript](https://github.com/thirdweb-example/cra-typescript-starter) / [javascript](https://github.com/thirdweb-example/cra-javascript-starter))
- Vite ([typescript](https://github.com/thirdweb-example/vite-typescript-starter) / [javascript](https://github.com/thirdweb-example/vite-javascript-starter))
Our SDK uses a [Provider Pattern](https://flexiple.com/react/provider-pattern-with-react-context-api/); meaning any component within the `ThirdwebProvider` will have access to the SDK. If you use the CLI to initialize your project, this is already set up for you.
## Quick Start
Let's take a look at a typical setup:
**Configure the thirdweb Provider**
<br />
In order to use the hooks offered by the React SDK, you need to first setup a `ThirdwebProvider` for your app which lets you optionally configure your app. You can use this configuration to control what networks you want users to connect to, what types of wallets can connect to your app, and the settings for the [Typescript SDK](https://docs.thirdweb.com/typescript).
### Configure the `ThirdwebProvider`
At the top level of your application, add a `ThirdwebProvider` as follows:
Specify the network your smart contracts are deployed to in the `desiredChainId` prop and wrap your application like so:
```jsx title="App.jsx"
import { ChainId, ThirdwebProvider } from "@thirdweb-dev/react";
@@ -53,79 +59,196 @@ const App = () => {
};
```
Now you'll be able to use all the hooks provided by the React SDK! Let's take a look.
Below are examples of where to set this up in your application:
**Let Users Connect Wallets**
<p>
<a href="https://github.com/thirdweb-example/cra-javascript-starter/blob/main/src/index.js">Create React App</a> •
<a href="https://github.com/thirdweb-example/next-javascript-starter/blob/main/pages/_app.js">Next.js</a> •
<a href="https://github.com/thirdweb-example/vite-javascript-starter/blob/main/src/main.jsx">Vite</a>
</p>
Next, we'll add a button to our app which will let users connect their wallets. For now, we'll make it so that users with MetaMask wallets can connect.
<br />
### Connect to a User's Wallet
Now the provider is set up, we can use all of the hooks and UI components available in the SDK, such as the [ConnectWallet](https://portal.thirdweb.com/sdk/ui-components/connectwalletbutton) component.
Once the user has connected their wallet, all the calls we make to interact with contracts using the SDK will be on behalf of the user.
```jsx title="ConnectMetamaskButton.jsx"
import { useAddress, useDisconnect, useMetamask } from "@thirdweb-dev/react";
import { ConnectWallet, useAddress } from "@thirdweb-dev/react";
export const ConnectMetamaskButtonComponent = () => {
const connectWithMetamask = useMetamask();
export const YourApp = () => {
const address = useAddress();
return (
<div>
{address ? (
<h4>Connected as {address}</h4>
<ConnectWallet />
</div>
);
};
```
The `ConnectWallet` component handles everything for us, including switching networks, accounts, displaying balances and more.
We can then get the connected address using the `useAddress` hook anywhere in the app.
<br/>
### Interact With Contracts
Connect to your smart contract using the [`useContract`](https://portal.thirdweb.com/sdk/interacting-with-contracts/custom-contracts/getting-a-contract#connect-to-a-contract)
hook like so:
```jsx title="pages/index.jsx"
import { useContract } from "@thirdweb-dev/react";
export default function Home() {
const { contract } = useContract("<CONTRACT_ADDRESS>");
// Now you can use the contract in the rest of the component!
}
```
You can then use [`useContractRead`](https://portal.thirdweb.com/sdk/interacting-with-contracts/custom-contracts/using-contracts) and [`useContractWrite`](https://portal.thirdweb.com/sdk/interacting-with-contracts/custom-contracts/using-contracts) to read data and write transactions to the contract.
You pass the `contract` object returned from `useContract` to these hooks as the first parameter and the name of the function (or view/mapping, etc.) on your smart contract as the second parameter. If your function requires parameters, you can pass them as additional arguments.
For example, we can read the `name` of our contract like so:
```jsx title="pages/index.jsx"
import {
useContract,
useContractRead,
useContractWrite,
} from "@thirdweb-dev/react";
export default function Home() {
const { contract } = useContract("<CONTRACT_ADDRESS>");
const { data: name, isLoading: loadingName } = useContractRead(
contract,
"name", // The name of the view/mapping/variable on your contract
);
const { mutate: setName, isLoading: settingName } = useContractWrite(
contract,
"setName", // The name of the function on your contract
);
}
```
<br />
### Using Extensions
Each [extension](https://portal.thirdweb.com/extensions) you implement in your smart contract unlocks new functionality in the SDK.
These hooks make it easy to interact with your smart contracts by implementing the complex logic for you under the hood.
For example, if your smart contract implements [ERC721Supply](https://portal.thirdweb.com/extensions/erc721supply#unlocked-features), you unlock the ability to [view all NFTs](https://portal.thirdweb.com/sdk/interacting-with-contracts/erc721supply#get-all-minted-nfts) on that contract using the SDK; which fetches all of your NFT metadata and the current owner of each NFT in parallel. In the React SDK, that is available using `useNFTs`:
```jsx
import { useContract, useNFTs } from "@thirdweb-dev/react";
export default function Home() {
const { contract } = useContract("<CONTRACT_ADDRESS>");
const { data: nfts, isLoading: isReadingNfts } = useNFTs(contract);
}
```
If we want to mint an NFT and our contract implements [ERC721Mintable](https://portal.thirdweb.com/extensions/erc721mintable#unlocked-features), we can use the [`useMintNFT`](https://portal.thirdweb.com/sdk/interacting-with-contracts/erc721mintable) hook to mint an NFT from the connected wallet; handling all of the logic of uploading and pinning the metadata to IPFS for us behind the scenes.
```jsx
import { useContract, useNFTs, useMintNFT } from "@thirdweb-dev/react";
export default function Home() {
const { contract } = useContract("<CONTRACT_ADDRESS>");
const { data: nfts, isLoading: isReadingNfts } = useNFTs(contract);
const { mutate: mintNFT, isLoading: isMintingNFT } = useMintNFT(contract);
}
```
<br />
### UI Components
The SDK provides many UI components to help you build your application.
For example, we can render each of the NFTs using the [`NFT Media Renderer`](https://portal.thirdweb.com/sdk/ui-components/nft-renderer)
component, making use of the loading state from `useNFTs`:
```jsx title="pages/index.jsx"
import { useContract, useNFTs, ThirdwebNftMedia } from "@thirdweb-dev/react";
export default function Home() {
const { contract } = useContract("<CONTRACT_ADDRESS>");
const { data: nfts, isLoading: isReadingNfts } = useNFTs(contract);
return (
<div>
<h2>My NFTs</h2>
{isReadingNfts ? (
<p>Loading...</p>
) : (
<button onClick={connectWithMetamask}>Connect Metamask Wallet</button>
<div>
{nfts.map((nft) => (
<ThirdwebNftMedia
key={nft.tokenId}
metadata={nft.metadata}
height={200}
/>
))}
</div>
)}
</div>
);
};
}
```
Here, we use the `useMetamask` hook to handle metamask connection. When a user clicks the button, we'll call the `connectWithMetamask` function, which will prompt users to connect their metamask wallet.
The [`Web3Button`](https://portal.thirdweb.com/sdk/ui-components/web3button) component ensures the user has connected their wallet and is currently configured to the same network as your smart contract before calling the function. It also has access to the `contract` directly, allowing you to perform any action on your smart contract when the button is clicked.
**Interact With Contracts**
For example, we can mint an NFT like so:
The thirdweb React SDK also enables you to interact directly with contracts through simple hooks!
```jsx title="pages/index.jsx"
import {
useContract,
useNFTs,
ThirdwebNftMedia,
Web3Button,
} from "@thirdweb-dev/react";
Let's setup a simple component to interact with an NFT Collection contract and get the data of all the NFTs on the contract.
```jsx title="NFTList.jsx"
import { useMintNFT, useNFTCollection, useNFTs } from "@thirdweb-dev/react";
const NFTListComponent = () => {
const address = useAddress();
const nftCollection = useNFTCollection("<NFT-COLLECTION-CONTRACT-ADDRESS>");
const { data: nfts } = useNFTs(nftCollection);
const { mutate: mintNFT } = useMintNFT(nftCollection);
const mint = () => {
mintNFT({
to: address,
metadata: {
name: "Cool NFT",
description: "Minted from react",
},
});
};
const contractAddress = "<CONTRACT_ADDRESS>";
export default function Home() {
const { contract } = useContract(contractAddress);
const { data: nfts, isLoading: isReadingNfts } = useNFTs(contract);
return (
<div>
<button onClick={mint}>Mint</button>
<ul>
{nfts?.map((nft) => (
<li key={nft.metadata.id.toString()}>{nft.metadata.name}</li>
))}
</ul>
{/* ... Existing Display Logic here ... */}
<Web3Button
contractAddress={contractAddress}
action={(contract) =>
contract.erc721.mint({
name: "Hello world!",
image:
// You can use a file or URL here!
"ipfs://QmZbovNXznTHpYn2oqgCFQYP4ZCpKDquenv5rFCX8irseo/0.png",
})
}
>
Mint NFT
</Web3Button>
</div>
);
};
}
```
Here, we get an `NFT Collection` contract instance from the [TypeScript SDK](https://docs.thirdweb.com/typescript). We can then use all the methods on this thirdweb contract SDK instance - here we use the `mintTo` method to mint an NFT on the contract, and we use `useNFTList` to display all the NFTs in the collection on the page.
And that's all for the setup! Just like that, you can setup a `ThirdwebProvider` and use all the hooks of the SDK, allowing you to let users connect wallets, interact with contracts, and more!
<br />
## Advanced Configuration
The `ThirdwebProvider` offers a number of configuration options to control the behavior of the React and Typescript SDK.
These all the configuration options of the `<ThirdwebProvider />`.
These are all the configuration options of the `<ThirdwebProvider />`.
We provide defaults for all of these, but you customize them to suit your needs.
```jsx title="App.jsx"
+41 -8
View File
@@ -1,6 +1,6 @@
{
"name": "@thirdweb-dev/react",
"version": "3.0.0",
"version": "3.0.7",
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/react",
"author": "thirdweb eng <[email protected]>",
"license": "Apache-2.0",
@@ -8,21 +8,28 @@
"types": "dist/thirdweb-dev-react.cjs.d.ts",
"module": "dist/thirdweb-dev-react.esm.js",
"files": [
"dist/**/*",
"patches/**/*"
"dist/",
"solana/"
],
"preconstruct": {
"entrypoints": [
"index.ts",
"solana/index.ts"
]
},
"private": false,
"scripts": {
"format": "prettier --write 'src/**/*'",
"lint": "eslint src/",
"fix": "eslint src/ --fix",
"clean": "rm -rf dist/",
"extract-api": "api-extractor run --local",
"generate-docs": "api-extractor run --local && yarn api-documenter markdown -i ./temp -o ./docs && yarn generate-snippets",
"generate:md-docs": "yarn api-documenter markdown -i ./temp -o ./docs",
"generate-snippets": "node ./scripts/generate-snippets.mjs",
"generate-snippets": "node ./scripts/generate-snippets.mjs && node ./scripts/generate-feature-snippets.mjs",
"build": "tsc && preconstruct build",
"e2e": "yarn test-ct",
"test-ct": "playwright test -c playwright-ct.config.ts"
"test-ct": "playwright test -c playwright-ct.config.ts",
"push": "yalc push"
},
"sideEffects:": false,
"devDependencies": {
@@ -33,9 +40,13 @@
"@microsoft/api-documenter": "^7.19.4",
"@microsoft/api-extractor": "^7.29.2",
"@microsoft/tsdoc": "^0.14.1",
"@playwright/experimental-ct-react": "^1.25.1",
"@playwright/test": "^1.25.1",
"@playwright/experimental-ct-react": "1.25.1",
"@playwright/test": "1.25.1",
"@preconstruct/cli": "^2.2.1",
"@solana/wallet-adapter-base": "^0.9.17",
"@solana/wallet-adapter-react": "^0.15.19",
"@solana/wallet-adapter-wallets": "^0.19.0",
"@solana/web3.js": "^1.63.0",
"@thirdweb-dev/sdk": "*",
"@types/color": "^3.0.3",
"@types/mime": "^3.0.1",
@@ -75,7 +86,12 @@
"wagmi": "^0.2.28"
},
"peerDependencies": {
"@solana/wallet-adapter-base": "^0.9.17",
"@solana/wallet-adapter-react": "^0.15.19",
"@solana/wallet-adapter-wallets": "^0.19.0",
"@solana/web3.js": "^1.63.0",
"@thirdweb-dev/sdk": "*",
"@thirdweb-dev/solana": "*",
"ethers": ">=5.5.1",
"react": ">=18.0.0",
"react-dom": ">=18.0.0"
@@ -83,5 +99,22 @@
"resolutions": {
"ansi-regex": "^6.0.1",
"typescript": "^4.6.2"
},
"peerDependenciesMeta": {
"@solana/wallet-adapter-base": {
"optional": true
},
"@solana/wallet-adapter-react": {
"optional": true
},
"@solana/wallet-adapter-wallets": {
"optional": true
},
"@solana/web3.js": {
"optional": true
},
"@thirdweb-dev/solana": {
"optional": true
}
}
}
@@ -0,0 +1,165 @@
import {
TSDocParser,
DocExcerpt,
TSDocConfiguration,
TSDocTagSyntaxKind,
TSDocTagDefinition,
} from "@microsoft/tsdoc";
import fs from "fs";
/**
* This is a simplistic solution until we implement proper DocNode rendering APIs.
*/
export class Formatter {
static renderDocNode(docNode) {
let result = "";
if (docNode) {
if (docNode instanceof DocExcerpt) {
result += docNode.content.toString();
}
for (const childNode of docNode.getChildNodes()) {
result += Formatter.renderDocNode(childNode);
}
}
return result;
}
static renderDocNodes(docNodes) {
let result = "";
for (const docNode of docNodes) {
result += Formatter.renderDocNode(docNode);
}
return result;
}
}
const config = new TSDocConfiguration();
const tag = new TSDocTagDefinition({
tagName: "@twfeature",
allowMultiple: true,
syntaxKind: TSDocTagSyntaxKind.BlockTag,
});
config.addTagDefinition(tag);
config.setSupportForTag(tag, true);
const tsdocParser = new TSDocParser(config);
const json = JSON.parse(
fs.readFileSync(`${process.cwd()}/temp/react.api.json`, "utf8"),
);
function languageNameToKey(languageName) {
switch (languageName) {
case "js":
case "jsx":
return "javascript";
case "ts":
case "tsx":
return "tyepscript";
default:
return languageName;
}
}
// Get all the DetectableFeature classes
const classes = json.members[0].members;
const features = {};
function parseExampleTag(docComment) {
const exampleBlocks = docComment._customBlocks.filter(
(b) => b._blockTag._tagName === "@example",
);
const examplesString = Formatter.renderDocNodes(exampleBlocks);
const regex = /```([a-zA-Z]*)\n([\S\s]*?)\n```/g;
let matches;
const examples = {};
while ((matches = regex.exec(examplesString)) !== null) {
// This is necessary to avoid infinite loops with zero-width matches
if (matches.index === regex.lastIndex) {
regex.lastIndex++;
}
examples[languageNameToKey(matches[1])] = matches[2];
}
return examples;
}
function parseTWFeatureTag(docComment) {
const featureBlocks = docComment._customBlocks.filter(
(b) => b._blockTag._tagName === "@twfeature",
);
const featuresString = Formatter.renderDocNodes(featureBlocks);
return featuresString.split(" | ").map((f) =>
f
.trim()
.replace(/\\n/g, "")
.replace("\n\n", "")
.replace(/`/g, "")
.replace(/@twfeature/g, ""),
);
}
const baseDocUrl = "https://docs.thirdweb.com/react/react.";
const extractReferenceLink = (m, kind, contractName) => {
if (kind === "Property") {
return m.excerptTokens
.filter((e) => e.kind === "Reference")
.map((e) => `${baseDocUrl}${e.text.toLowerCase()}`)[0];
}
if (kind === "Method") {
return `${baseDocUrl}${contractName}.${m.name}`.toLowerCase();
}
return `${baseDocUrl}${m.name}`.toLowerCase();
};
const parseMembers = (members, kind, contractName) => {
if (!members) {
return [];
}
members = [members];
const validMembers = members.filter((m) => m.kind === kind);
return validMembers
.map((m) => {
const parserContext = tsdocParser.parseString(m.docComment);
const docComment = parserContext.docComment;
const featureNames = parseTWFeatureTag(docComment);
if (featureNames.length > 0) {
for (const feature of featureNames) {
const examples = parseExampleTag(docComment);
if (Object.keys(examples).length > 0) {
const example = {
name: m.name,
summary: Formatter.renderDocNode(docComment.summarySection),
remarks: docComment.remarksBlock
? Formatter.renderDocNode(docComment.remarksBlock.content)
: null,
examples,
reference: {
javascript: extractReferenceLink(m, kind, contractName),
},
};
features[feature] = features[feature]
? features[feature].concat(example)
: [example];
}
}
}
})
.filter((m) => !!m);
};
classes.forEach((m) => {
parseMembers(m, "Function", m.name);
});
fs.writeFileSync(
`${process.cwd()}/docs/feature_snippets.json`,
JSON.stringify(features, null, 2),
);
+2 -2
View File
@@ -115,13 +115,13 @@ const NETWORK_INFO_HOOKS = ["useChainId", "useNetwork", "useNetworkMismatch"];
const CUSTOM_CONTRACT_HOOKS = [
"useContract",
"useContractData",
"useContractRead",
"useContractWrite",
"useAllContractEvents",
"useContractEvents",
"useContractType",
"useContractPublishMetadata",
"useContractMetadata",
"useContractCall",
];
const CONTRACT_SETTINGS_HOOKS = [
+4
View File
@@ -0,0 +1,4 @@
{
"main": "dist/thirdweb-dev-react-solana.cjs.js",
"module": "dist/thirdweb-dev-react-solana.esm.js"
}
@@ -1,5 +1,5 @@
import { ConnectWallet } from ".";
import { ThirdwebProvider } from "../..";
import { ThirdwebProvider } from "../../providers/full";
import { test, expect } from "@playwright/experimental-ct-react";
test.use({ viewport: { width: 500, height: 500 } });
@@ -10,5 +10,6 @@ test("should render the connect wallet button", async ({ mount }) => {
<ConnectWallet />
</ThirdwebProvider>,
);
await expect(component).toContainText("Connect Wallet");
});
@@ -1,16 +1,13 @@
import { useThirdwebAuthConfig } from "../../contexts/thirdweb-auth";
import { useBalance } from "../../hooks/async/wallet";
import { LoginConfig, useAuth } from "../../hooks/auth";
import { useMetamask } from "../../hooks/connectors/useMetamask";
import { useAddress } from "../../hooks/useAddress";
import { useChainId } from "../../hooks/useChainId";
import { useConnect } from "../../hooks/useConnect";
import { useDisconnect } from "../../hooks/useDisconnect";
import { useNetwork } from "../../hooks/useNetwork";
import { useConnect } from "../../hooks/wagmi-required/useConnect";
import { useDisconnect } from "../../hooks/wagmi-required/useDisconnect";
import { useNetwork } from "../../hooks/wagmi-required/useNetwork";
import { useAddress, useBalance, useChainId } from "../../hooks/wallet";
import { Portal } from "../../lib/portal";
import { shortenIfAddress } from "../../utils/addresses";
import { useClipboard } from "../hooks/useCopyClipboard";
import { useIsMounted } from "../hooks/useIsMounted";
import { Box } from "../shared/Box";
import { Button } from "../shared/Button";
import { Icon } from "../shared/Icon";
@@ -30,8 +27,8 @@ import { FiXCircle } from "@react-icons/all-files/fi/FiXCircle";
import { ChainId, LoginOptions, SUPPORTED_CHAIN_ID } from "@thirdweb-dev/sdk";
import * as menu from "@zag-js/menu";
import { normalizeProps, useMachine } from "@zag-js/react";
import React, { useId, useMemo } from "react";
import { Connector } from "wagmi";
import React, { useId } from "react";
import type { Connector } from "wagmi";
const SUPPORTED_CONNECTORS = [
"injected",
@@ -65,6 +62,7 @@ interface ConnectWalletProps extends ThemeProviderProps {
loginConfig?: LoginConfig;
loginOptional?: boolean;
};
className?: string;
}
let connecting = false;
@@ -124,15 +122,12 @@ const chainIdToCurrencyMap: Record<
*/
export const ConnectWallet: React.FC<ConnectWalletProps> = ({
auth,
className,
...themeProps
}) => {
const id = useId();
const isMounted = useIsMounted();
const address = useAddress();
const mountedAddress = useMemo(() => {
return isMounted ? address : null;
}, [address, isMounted]);
const walletAddress = useAddress();
const [state, send] = useMachine(
menu.machine({
@@ -165,24 +160,26 @@ export const ConnectWallet: React.FC<ConnectWalletProps> = ({
const balanceQuery = useBalance();
const { onCopy, hasCopied } = useClipboard(mountedAddress || "");
const { onCopy, hasCopied } = useClipboard(walletAddress || "");
const authConfig = useThirdwebAuthConfig();
const { user, isLoading, login, logout } = useAuth(auth?.loginConfig);
const requiresSignIn = auth?.loginOptional
? false
: !!authConfig?.authUrl && !!mountedAddress && !user?.address;
: !!authConfig?.authUrl && !!walletAddress && !user?.address;
return (
<ThemeProvider {...themeProps}>
<div
style={{
position: "relative",
width: "100%",
}}
>
<Button
style={{ height: "50px", minWidth: "200px" }}
className={className}
style={{ height: "50px", minWidth: "200px", width: "100%" }}
onClick={async (e) => {
if (requiresSignIn) {
e.preventDefault();
@@ -204,7 +201,7 @@ export const ConnectWallet: React.FC<ConnectWalletProps> = ({
) : (
<FiLock />
)
) : mountedAddress && chainId && chainId in chainIdToCurrencyMap ? (
) : walletAddress && chainId && chainId in chainIdToCurrencyMap ? (
<Icon
boxSize="1.5em"
name={chainIdToCurrencyMap[chainId as SUPPORTED_CHAIN_ID]}
@@ -225,7 +222,7 @@ export const ConnectWallet: React.FC<ConnectWalletProps> = ({
)
}
>
{mountedAddress ? (
{walletAddress ? (
requiresSignIn ? (
<span style={{ whiteSpace: "nowrap" }}>Sign in</span>
) : (
@@ -249,7 +246,7 @@ export const ConnectWallet: React.FC<ConnectWalletProps> = ({
)}
</span>
<span style={{ fontSize: "0.9em" }}>
{shortenIfAddress(mountedAddress)}
{shortenIfAddress(walletAddress)}
</span>
</span>
)
@@ -267,7 +264,7 @@ export const ConnectWallet: React.FC<ConnectWalletProps> = ({
}}
>
<Menu {...api.contentProps}>
{!api.isOpen ? null : mountedAddress ? (
{!api.isOpen ? null : walletAddress ? (
<>
{authConfig?.authUrl && !user?.address && !requiresSignIn ? (
<MenuItem
@@ -396,10 +393,13 @@ export const ConnectWallet: React.FC<ConnectWalletProps> = ({
})}
onClick={async () => {
if (!connecting) {
connecting = true;
await connectWithMetamask();
connecting = false;
api.close();
try {
connecting = true;
await connectWithMetamask();
api.close();
} finally {
connecting = false;
}
}
}}
leftElement={<Icon boxSize="1.5em" name="metamask" />}
@@ -421,10 +421,13 @@ export const ConnectWallet: React.FC<ConnectWalletProps> = ({
})}
onClick={async () => {
if (!connecting) {
connecting = true;
await connect(c);
connecting = false;
api.close();
try {
connecting = true;
await connect(c);
api.close();
} finally {
connecting = false;
}
}
}}
leftElement={getIconForConnector(c)}
@@ -1,5 +1,5 @@
import { Web3Button } from ".";
import { ThirdwebProvider } from "../..";
import { ThirdwebProvider } from "../../providers/full";
import { test, expect } from "@playwright/experimental-ct-react";
test.use({ viewport: { width: 500, height: 500 } });
@@ -1,8 +1,8 @@
import { useActiveChainId } from "../../Provider";
import { useContract } from "../../hooks/async/contracts";
import { useAddress } from "../../hooks/useAddress";
import { useChainId } from "../../hooks/useChainId";
import { useNetwork } from "../../hooks/useNetwork";
import { useNetworkMismatch } from "../../hooks/useNetworkMismatch";
import { useNetwork } from "../../hooks/wagmi-required/useNetwork";
import { useAddress, useChainId } from "../../hooks/wallet";
import { useSDKChainId } from "../../providers/base";
import {
createCacheKeyWithNetwork,
createContractCacheKey,
@@ -10,6 +10,7 @@ import {
import { ConnectWallet } from "../ConnectWallet";
import { Button } from "../shared/Button";
import { ThemeProvider, ThemeProviderProps } from "../shared/ThemeProvider";
import { FiWifi } from "@react-icons/all-files/fi/FiWifi";
import { useMutation, useQueryClient } from "@tanstack/react-query";
import type { SmartContract } from "@thirdweb-dev/sdk/dist/declarations/src/contracts/smart-contract";
import type { CallOverrides } from "ethers";
@@ -20,6 +21,7 @@ type ActionFn = (contract: SmartContract) => any;
interface Web3ButtonProps<TActionFn extends ActionFn>
extends ThemeProviderProps {
className?: string;
contractAddress: `0x${string}` | `${string}.eth` | string;
overrides?: CallOverrides;
@@ -64,15 +66,18 @@ export const Web3Button = <TAction extends ActionFn>({
isDisabled,
children,
action,
className,
...themeProps
}: PropsWithChildren<Web3ButtonProps<TAction>>) => {
const address = useAddress();
const walletChainId = useChainId();
const sdkChainId = useActiveChainId();
const sdkChainId = useSDKChainId();
const [, switchNetwork] = useNetwork();
const queryClient = useQueryClient();
const hasMismatch = useNetworkMismatch();
const switchToChainId = useMemo(() => {
if (sdkChainId && walletChainId && sdkChainId !== walletChainId) {
return sdkChainId;
@@ -87,7 +92,7 @@ export const Web3Button = <TAction extends ActionFn>({
if (switchToChainId) {
if (switchNetwork) {
await switchNetwork(switchToChainId);
await new Promise((resolve) => setTimeout(resolve, 500));
return "__NETWORK_SWITCHED__";
} else {
throw new Error(
"need to switch chain but connected wallet does not support switching",
@@ -99,10 +104,14 @@ export const Web3Button = <TAction extends ActionFn>({
if (onSubmit) {
onSubmit();
}
return await action(contract);
},
{
onSuccess: (res) => {
if (res === "__NETWORK_SWITCHED__") {
return;
}
if (onSuccess) {
onSuccess(res);
}
@@ -122,18 +131,24 @@ export const Web3Button = <TAction extends ActionFn>({
},
);
if (!address) {
return <ConnectWallet {...themeProps} />;
return <ConnectWallet className={className} {...themeProps} />;
}
const willSwitchNetwork = hasMismatch && !!switchNetwork;
return (
<ThemeProvider {...themeProps}>
<Button
style={{ height: "50px" }}
className={className}
style={{ height: "50px", minWidth: "200px", width: "100%" }}
isLoading={mutation.isLoading || !contract}
onClick={() => mutation.mutate()}
isDisabled={isDisabled}
isDisabled={willSwitchNetwork ? false : isDisabled}
leftElement={
willSwitchNetwork ? <FiWifi width="1em" height="1em" /> : undefined
}
>
{children}
{willSwitchNetwork ? "Switch Network" : children}
</Button>
</ThemeProvider>
);
@@ -1,9 +0,0 @@
import { useEffect, useState } from "react";
export function useIsMounted() {
const [isMounted, setIsMounted] = useState(false);
useEffect(() => {
setIsMounted(true);
}, []);
return isMounted;
}
@@ -1,12 +0,0 @@
import { useAddress } from "../../hooks/useAddress";
import { useIsMounted } from "./useIsMounted";
import { useMemo } from "react";
export function useMountedAddress() {
const isMounted = useIsMounted();
const address = useAddress();
return useMemo(() => {
return isMounted ? address || null : null;
}, [address, isMounted]);
}
+2
View File
@@ -0,0 +1,2 @@
// eslint-disable-next-line turbo/no-undeclared-env-vars
export const __DEV__ = process.env.NODE_ENV !== "production";
@@ -0,0 +1,86 @@
import { __DEV__ } from "../constants/runtime";
import { useThirdwebConfigContext } from "./thirdweb-config";
import { UserWallet } from "@thirdweb-dev/sdk";
import { Signer } from "ethers";
import React, {
PropsWithChildren,
createContext,
useContext,
useState,
useEffect,
} from "react";
interface ThirdwebConnectedWalletContext {
wallet: UserWallet | undefined;
address: string | undefined;
chainId: number | undefined;
signer: Signer | undefined;
}
const INITIAL_CONTEXT_VALUE: ThirdwebConnectedWalletContext = {
wallet: undefined,
address: undefined,
chainId: undefined,
signer: undefined,
};
const ThirdwebConnectedWalletContext =
createContext<ThirdwebConnectedWalletContext>(INITIAL_CONTEXT_VALUE);
export const ThirdwebConnectedWalletProvider: React.FC<
PropsWithChildren<{ signer?: Signer }>
> = ({ signer, children }) => {
const { rpcUrlMap } = useThirdwebConfigContext();
const [contextValue, setContextValue] =
useState<ThirdwebConnectedWalletContext>(INITIAL_CONTEXT_VALUE);
useEffect(() => {
let s = signer;
if (signer) {
// just get both of these up front and keep them around with the context
Promise.all([signer.getAddress(), signer.getChainId()])
.then(([address, chainId]) => {
const rpcUrl = rpcUrlMap[chainId];
// only if the signer is still the same!
if (signer === s) {
const wallet = new UserWallet(signer, {
readonlySettings: rpcUrl
? {
rpcUrl,
chainId,
}
: undefined,
});
setContextValue({ wallet, address, chainId, signer });
}
})
.catch((err) => {
if (__DEV__) {
console.warn(
"failed to get wallet instance in `<ThirdwebConnectedWalletProvider />`",
err,
);
}
});
} else {
// if signer is not provided, re-set the context value to initial values
setContextValue(INITIAL_CONTEXT_VALUE);
}
return () => {
// set the previous signer to undefined because it is invalid now
s = undefined;
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [signer]);
return (
<ThirdwebConnectedWalletContext.Provider value={contextValue}>
{children}
</ThirdwebConnectedWalletContext.Provider>
);
};
export function useThirdwebConnectedWalletContext() {
return useContext(ThirdwebConnectedWalletContext);
}
@@ -1,4 +1,4 @@
import { useActiveChainId } from "../../Provider";
import { useSDKChainId } from "../../providers/base";
import {
getErcs,
DropContract,
@@ -60,7 +60,7 @@ export type SetClaimConditionsParams = {
* @param contract - an instance of a contract that extends the ERC721 or ERC1155 spec and implements the `claimConditions` extension.
* @param tokenId - the id of the token to fetch the claim conditions for (if the contract is an ERC1155 contract)
* @returns a response object with the currently active claim condition
*
* @twfeature ERC721ClaimableWithConditions | ERC1155ClaimableWithConditions | ERC20ClaimableWithConditions
* @beta
*/
export function useActiveClaimCondition(
@@ -83,7 +83,7 @@ export function useActiveClaimCondition(
if (erc20) {
return erc20.claimConditions.getActive();
}
return undefined;
throw new Error("Contract must be ERC721, ERC1155 or ERC20");
},
{
// Checks that happen here:
@@ -113,7 +113,7 @@ export function useActiveClaimCondition(
* @param contract - an instance of a contract that extends the ERC721 or ERC1155 spec and implements the `claimConditions` extension.
* @param tokenId - the id of the token to fetch the claim conditions for (if the contract is an ERC1155 contract)
* @returns a response object with the list of claim conditions
*
* @twfeature ERC721ClaimableWithConditions | ERC1155ClaimableWithConditions | ERC20ClaimableWithConditions
* @beta
*/
export function useClaimConditions(
@@ -136,7 +136,7 @@ export function useClaimConditions(
if (erc20) {
return erc20.claimConditions.getAll();
}
return undefined;
throw new Error("Contract must be ERC721, ERC1155 or ERC20");
},
{
// Checks that happen here:
@@ -166,7 +166,7 @@ export function useClaimConditions(
* @param eligibilityParams - the parameters for the eligibility check, see: {@link ClaimIneligibilityParams}
* @param tokenId - the id of the token to fetch the claim conditions for (if the contract is an ERC1155 contract)
* @returns a response object with the resons for the claim ineligibility
*
* @twfeature ERC721ClaimableWithConditions | ERC1155ClaimableWithConditions | ERC20ClaimableWithConditions
* @beta
*/
export function useClaimIneligibilityReasons(
@@ -207,7 +207,7 @@ export function useClaimIneligibilityReasons(
params.walletAddress,
);
}
return undefined;
throw new Error("Contract must be ERC721, ERC1155 or ERC20");
},
{
// Checks that happen here:
@@ -257,13 +257,14 @@ export function useClaimIneligibilityReasons(
*
* @param contract - an instance of a {@link DropContract}
* @returns a mutation object that can be used to set claim conditions
* @twfeature ERC721ClaimableWithConditions | ERC1155ClaimableWithConditions | ERC20ClaimableWithConditions
* @beta
*/
export function useSetClaimConditions(
contract: RequiredParam<DropContract>,
tokenId?: BigNumberish,
) {
const activeChainId = useActiveChainId();
const activeChainId = useSDKChainId();
const contractAddress = contract?.getAddress();
const queryClient = useQueryClient();
const { erc1155, erc721, erc20 } = getErcs(contract);
@@ -283,7 +284,7 @@ export function useSetClaimConditions(
if (erc20) {
return erc20.claimConditions.set(phases, reset);
}
return undefined;
throw new Error("Contract must be ERC721, ERC1155 or ERC20");
},
{
onSettled: () => {
@@ -327,13 +328,14 @@ export function useSetClaimConditions(
*
* @param contract - an instance of a {@link DropContract}
* @returns a mutation object that can be used to reset claim conditions
* @twfeature ERC721ClaimableWithConditions | ERC1155ClaimableWithConditions | ERC20ClaimableWithConditions
* @beta
*/
export function useResetClaimConditions(
contract: RequiredParam<DropContract>,
tokenId?: BigNumberish,
) {
const activeChainId = useActiveChainId();
const activeChainId = useSDKChainId();
const contractAddress = contract?.getAddress();
const queryClient = useQueryClient();
const { erc1155, erc721, erc20 } = getErcs(contract);
@@ -372,7 +374,7 @@ export function useResetClaimConditions(
true,
);
}
return undefined;
throw new Error("Contract must be ERC721, ERC1155 or ERC20");
},
{
onSettled: () => {
@@ -1,4 +1,4 @@
import { useActiveChainId } from "../../Provider";
import { useSDKChainId } from "../../providers/base";
import { RequiredParam, WalletAddress } from "../../types";
import {
cacheKeys,
@@ -24,6 +24,7 @@ import invariant from "tiny-invariant";
* Use this to get the primary sales recipient of your {@link SmartContract}
* @param contract - an instance of a {@link SmartContract}
* @returns the wallet address of the primary sales recipient
* @twfeature PrimarySale
* @beta
*/
export function usePrimarySaleRecipient(
@@ -73,6 +74,7 @@ export function usePrimarySaleRecipient(
*
* @param contract - an instance of a {@link SmartContract}
* @returns a mutation object that can be used to update the primary sales recipient
* @twfeature PrimarySale
* @beta
*/
export function useUpdatePrimarySaleRecipient(
@@ -80,7 +82,7 @@ export function useUpdatePrimarySaleRecipient(
) {
const queryClient = useQueryClient();
const contractAddress = contract?.getAddress();
const activeChainId = useActiveChainId();
const activeChainId = useSDKChainId();
return useMutation(
(newRecipient: WalletAddress) => {
invariant(contract, "No contract provided");
@@ -115,6 +117,7 @@ export function useUpdatePrimarySaleRecipient(
*
* @param contract - an instance of a {@link SmartContract}
* @returns an object containing recipient address and the royalty basis points
* @twfeature Royalty
* @beta
*/
export function useRoyaltySettings(
@@ -164,6 +167,7 @@ export function useRoyaltySettings(
*
* @param contract - an instance of a {@link SmartContract}
* @returns a mutation object that can be used to update the royalty settings
* @twfeature Royalty
* @beta
*/
export function useUpdateRoyaltySettings(
@@ -171,7 +175,7 @@ export function useUpdateRoyaltySettings(
) {
const queryClient = useQueryClient();
const contractAddress = contract?.getAddress();
const activeChainId = useActiveChainId();
const activeChainId = useSDKChainId();
return useMutation(
(updatePayload: {
seller_fee_basis_points?: number;
@@ -209,6 +213,7 @@ export function useUpdateRoyaltySettings(
*
* @param contract - an instance of a {@link SmartContract}
* @returns an object containing the platform fee basis points and the fee recipient address
* @twfeature PlatformFee
* @beta
*/
export function usePlatformFees(
@@ -257,6 +262,7 @@ export function usePlatformFees(
* ```
* @param contract - an instance of a {@link SmartContract}
* @returns a mutation object that can be used to update the platform fees settings
* @twfeature PlatformFee
* @beta
*/
export function useUpdatePlatformFees(
@@ -264,7 +270,7 @@ export function useUpdatePlatformFees(
) {
const queryClient = useQueryClient();
const contractAddress = contract?.getAddress();
const activeChainId = useActiveChainId();
const activeChainId = useSDKChainId();
return useMutation(
(updatePayload: {
platform_fee_basis_points?: number;
@@ -302,6 +308,7 @@ export function useUpdatePlatformFees(
*
* @param contract - an instance of a {@link SmartContract}
* @returns a {@link CustomContractMetadata} object containing the metadata
* @twfeature ContractMetadata
* @beta
*/
export function useMetadata(contract: RequiredParam<ValidContractInstance>) {
@@ -347,6 +354,7 @@ export function useMetadata(contract: RequiredParam<ValidContractInstance>) {
* ```
* @param contract - an instance of a {@link SmartContract}
* @returns a mutation object that can be used to update the metadata
* @twfeature ContractMetadata
* @beta
*/
export function useUpdateMetadata(
@@ -354,7 +362,7 @@ export function useUpdateMetadata(
) {
const queryClient = useQueryClient();
const contractAddress = contract?.getAddress();
const activeChainId = useActiveChainId();
const activeChainId = useSDKChainId();
return useMutation(
(updatePayload: CustomContractMetadata) => {
invariant(contract, "No contract provided");
+26 -10
View File
@@ -1,4 +1,4 @@
import { useActiveChainId, useSDK } from "../../Provider";
import { useSDK, useSDKChainId } from "../../providers/base";
import { ContractAddress, RequiredParam } from "../../types";
import {
cacheKeys,
@@ -6,8 +6,7 @@ import {
createContractCacheKey,
} from "../../utils/cache-keys";
import { useQueryWithNetwork } from "../query-utils/useQueryWithNetwork";
import { useAddress } from "../useAddress";
import { useChainId } from "../useChainId";
import { useAddress, useChainId } from "../wallet";
import {
useMutation,
useQuery,
@@ -134,12 +133,24 @@ export type UseContractResult<
contract: TContract | undefined;
};
/**
* Use this resolve a contract address to a smart contract instance.
*
* @example
* ```javascript
* const { contract, isLoading, error } = useContract("{{contract_address}}");
* ```
*
* @param contractAddress - the address of the deployed contract
* @returns a response object that includes the contract once it is resolved
* @public
*/
export function useContract<
TContract extends ValidContractInstance = SmartContract,
>(contractAddress: RequiredParam<ContractAddress>) {
const sdk = useSDK();
const queryClient = useQueryClient();
const activeChainId = useActiveChainId();
const activeChainId = useSDKChainId();
const wallet = useAddress();
const walletChainId = useChainId();
@@ -211,12 +222,17 @@ export function useContract<
*
* @param contract - the {@link ValidContractInstance} instance of the contract to get the metadata for
* @returns a response object that includes the contract metadata of the deployed contract
* @twfeature ContractMetadata
* @beta
*/
export function useContractMetadata(
contract: RequiredParam<ValidContractInstance>,
export function useContractMetadata<TContract extends ValidContractInstance>(
contract: RequiredParam<TContract>,
) {
return useQueryWithNetwork(
return useQueryWithNetwork<
typeof contract extends undefined
? undefined
: Awaited<ReturnType<TContract["metadata"]["get"]>>
>(
cacheKeys.contract.metadata(contract?.getAddress()),
async () => {
invariant(contract, "contract is required");
@@ -234,7 +250,7 @@ export function useContractMetadata(
export function useContractMetadataUpdate(
contract: RequiredParam<ValidContractInstance>,
) {
const activeChainId = useActiveChainId();
const activeChainId = useSDKChainId();
const contractAddress = contract?.getAddress();
const queryClient = useQueryClient();
@@ -279,7 +295,7 @@ export function useContractEvents(
const contractAddress = contract?.getAddress();
const queryClient = useQueryClient();
const activeChainId = useActiveChainId();
const activeChainId = useSDKChainId();
const cacheKey = useMemo(
() =>
@@ -408,7 +424,7 @@ export function useContractWrite(
contract: RequiredParam<ValidContractInstance>,
functionName: RequiredParam<string>,
) {
const activeChainId = useActiveChainId();
const activeChainId = useSDKChainId();
const contractAddress = contract?.getAddress();
const queryClient = useQueryClient();
+18 -7
View File
@@ -1,4 +1,4 @@
import { useActiveChainId } from "../../Provider";
import { useSDKChainId } from "../../providers/base";
import {
ClaimNFTParams,
ClaimNFTReturnType,
@@ -22,7 +22,7 @@ import {
QueryAllParams,
UploadProgressEvent,
} from "@thirdweb-dev/sdk";
import { NFTDropImpl } from "@thirdweb-dev/sdk/dist/declarations/src/contracts/prebuilt-implementations/nft-drop";
import { NFTDrop } from "@thirdweb-dev/sdk/dist/declarations/src/contracts/prebuilt-implementations/nft-drop";
import invariant from "tiny-invariant";
/** **********************/
@@ -40,10 +40,11 @@ import invariant from "tiny-invariant";
* @param contract - an instance of a contract that extends the Erc721 spec (nft drop, custom contract that follows the Erc721 & drop spec)
* @param queryParams - query params to pass to the query for the sake of pagination
* @returns a response object that includes an array of NFTs that are unclaimed
* @twfeature ERC721LazyMintable | ERC1155LazyMintable
* @beta
*/
export function useUnclaimedNFTs(
contract: RequiredParam<NFTDropImpl>,
contract: RequiredParam<NFTDrop>,
queryParams?: QueryAllParams,
) {
const contractAddress = contract?.getAddress();
@@ -75,6 +76,7 @@ export function useUnclaimedNFTs(
* @param contract - an instance of a {@link DropContract}
* @param queryParams - query params to pass to the query for the sake of pagination
* @returns a response object that includes an array of NFTs that are claimed
* @twfeature ERC721LazyMintable | ERC1155LazyMintable
* @beta
*/
export function useClaimedNFTs(
@@ -83,10 +85,12 @@ export function useClaimedNFTs(
) {
return useNFTs(contract, queryParams);
}
/**
*
* @param contract - an instance of a {@link NFTDrop}
* @returns a response object that includes the number of NFTs that are unclaimed
* @twfeature ERC721LazyMintable | ERC1155LazyMintable
*/
export function useUnclaimedNFTSupply(contract: RequiredParam<DropContract>) {
const contractAddress = contract?.getAddress();
@@ -106,9 +110,11 @@ export function useUnclaimedNFTSupply(contract: RequiredParam<DropContract>) {
}
/**
*
* @param contract - an instance of a {@link DropContract}
* @returns a response object that includes the number of NFTs that are claimed
* @twfeature ERC721LazyMintable | ERC1155LazyMintable
*/
export function useClaimedNFTSupply(contract: RequiredParam<DropContract>) {
const contractAddress = contract?.getAddress();
@@ -131,6 +137,7 @@ export function useClaimedNFTSupply(contract: RequiredParam<DropContract>) {
*
* @param contract - an instance of a {@link RevealableContract}
* @returns a response object that gets the batches to still be revealed
* @twfeature ERC721Revealable | ERC1155Revealable
*/
export function useBatchesToReveal<TContract extends RevealableContract>(
contract: RequiredParam<TContract>,
@@ -185,12 +192,13 @@ export function useBatchesToReveal<TContract extends RevealableContract>(
*
* @param contract - an instance of a {@link DropContract}
* @returns a mutation object that can be used to claim a NFT to the wallet specificed in the params
* @twfeature ERC721Claimable | ERC1155Claimable
* @beta
*/
export function useClaimNFT<TContract extends DropContract>(
contract: RequiredParam<TContract>,
) {
const activeChainId = useActiveChainId();
const activeChainId = useSDKChainId();
const contractAddress = contract?.getAddress();
const queryClient = useQueryClient();
@@ -236,13 +244,14 @@ export function useClaimNFT<TContract extends DropContract>(
* @param contract - an instance of a {@link NFTContract} with the drop extension
* @param onProgress - an optional callback that will be called with the progress of the upload
* @returns a mutation object that can be used to lazy mint a batch of NFTs
* @twfeature ERC721LazyMintable | ERC1155LazyMintable
* @beta
*/
export function useLazyMint<TContract extends DropContract>(
contract: RequiredParam<TContract>,
onProgress?: (progress: UploadProgressEvent) => void,
) {
const activeChainId = useActiveChainId();
const activeChainId = useSDKChainId();
const contractAddress = contract?.getAddress();
const queryClient = useQueryClient();
const { erc721, erc1155 } = getErcs(contract);
@@ -282,13 +291,14 @@ export function useLazyMint<TContract extends DropContract>(
* @param contract - an instance of a {@link DropContract}
* @param onProgress - an optional callback that will be called with the progress of the upload
* @returns a mutation object that can be used to lazy mint a batch of NFTs
* @twfeature ERC721Revealable | ERC1155Revealable
* @beta
*/
export function useDelayedRevealLazyMint<TContract extends RevealableContract>(
contract: RequiredParam<TContract>,
onProgress?: (progress: UploadProgressEvent) => void,
) {
const activeChainId = useActiveChainId();
const activeChainId = useSDKChainId();
const contractAddress = contract?.getAddress();
const queryClient = useQueryClient();
@@ -336,12 +346,13 @@ export function useDelayedRevealLazyMint<TContract extends RevealableContract>(
*
* @param contract - an instance of a {@link RevealableContract}
* @returns a mutation object that can be used to reveal a batch of delayed reveal NFTs
* @twfeature ERC721Revealable | ERC1155Revealable
* @beta
*/
export function useRevealLazyMint<TContract extends RevealableContract>(
contract: RequiredParam<TContract>,
) {
const activeChainId = useActiveChainId();
const activeChainId = useSDKChainId();
const contractAddress = contract?.getAddress();
const queryClient = useQueryClient();
+20 -24
View File
@@ -1,11 +1,11 @@
import { useActiveChainId } from "../../Provider";
import { useSDKChainId } from "../../providers/base";
import { BuyNowParams, MakeBidParams, RequiredParam } from "../../types";
import {
cacheKeys,
invalidateContractAndBalances,
} from "../../utils/cache-keys";
import { useQueryWithNetwork } from "../query-utils/useQueryWithNetwork";
import { useAddress } from "../useAddress";
import { useAddress } from "../wallet";
import { useMutation, useQueryClient } from "@tanstack/react-query";
import type {
AuctionListing,
@@ -15,7 +15,7 @@ import type {
NewDirectListing,
} from "@thirdweb-dev/sdk";
import { ListingType } from "@thirdweb-dev/sdk";
import { MarketplaceImpl } from "@thirdweb-dev/sdk/dist/declarations/src/contracts/prebuilt-implementations/marketplace";
import { Marketplace } from "@thirdweb-dev/sdk/dist/declarations/src/contracts/prebuilt-implementations/marketplace";
import { BigNumber, BigNumberish } from "ethers";
import invariant from "tiny-invariant";
@@ -37,7 +37,7 @@ import invariant from "tiny-invariant";
* @beta
*/
export function useListing(
contract: RequiredParam<MarketplaceImpl>,
contract: RequiredParam<Marketplace>,
listingId: RequiredParam<BigNumberish>,
) {
const contractAddress = contract?.getAddress();
@@ -68,7 +68,7 @@ export function useListing(
* @beta
*/
export function useListings(
contract: RequiredParam<MarketplaceImpl>,
contract: RequiredParam<Marketplace>,
filter?: MarketplaceFilter,
) {
const contractAddress = contract?.getAddress();
@@ -97,7 +97,7 @@ export function useListings(
* @returns a response object that includes an array of listings
* @beta
*/
export function useListingsCount(contract: RequiredParam<MarketplaceImpl>) {
export function useListingsCount(contract: RequiredParam<Marketplace>) {
const contractAddress = contract?.getAddress();
return useQueryWithNetwork(
cacheKeys.contract.marketplace.getTotalCount(contractAddress),
@@ -125,7 +125,7 @@ export function useListingsCount(contract: RequiredParam<MarketplaceImpl>) {
* @beta
*/
export function useActiveListings(
contract: RequiredParam<MarketplaceImpl>,
contract: RequiredParam<Marketplace>,
filter?: MarketplaceFilter,
) {
const contractAddress = contract?.getAddress();
@@ -157,7 +157,7 @@ export function useActiveListings(
* @beta
*/
export function useWinningBid(
contract: RequiredParam<MarketplaceImpl>,
contract: RequiredParam<Marketplace>,
listingId: RequiredParam<BigNumberish>,
) {
const contractAddress = contract?.getAddress();
@@ -190,7 +190,7 @@ export function useWinningBid(
* @beta
*/
export function useAuctionWinner(
contract: RequiredParam<MarketplaceImpl>,
contract: RequiredParam<Marketplace>,
listingId: RequiredParam<BigNumberish>,
) {
const contractAddress = contract?.getAddress();
@@ -232,7 +232,7 @@ export function useAuctionWinner(
* @returns a response object that includes an array of listings
* @beta
*/
export function useBidBuffer(contract: RequiredParam<MarketplaceImpl>) {
export function useBidBuffer(contract: RequiredParam<Marketplace>) {
const contractAddress = contract?.getAddress();
return useQueryWithNetwork(
cacheKeys.contract.marketplace.getBidBufferBps(contractAddress),
@@ -281,10 +281,8 @@ export function useBidBuffer(contract: RequiredParam<MarketplaceImpl>) {
* @returns a mutation object that can be used to create a new direct listing
* @beta
*/
export function useCreateDirectListing(
contract: RequiredParam<MarketplaceImpl>,
) {
const activeChainId = useActiveChainId();
export function useCreateDirectListing(contract: RequiredParam<Marketplace>) {
const activeChainId = useSDKChainId();
const contractAddress = contract?.getAddress();
const queryClient = useQueryClient();
const walletAddress = useAddress();
@@ -339,10 +337,8 @@ export function useCreateDirectListing(
* @returns a mutation object that can be used to create a new auction listing
* @beta
*/
export function useCreateAuctionListing(
contract: RequiredParam<MarketplaceImpl>,
) {
const activeChainId = useActiveChainId();
export function useCreateAuctionListing(contract: RequiredParam<Marketplace>) {
const activeChainId = useSDKChainId();
const contractAddress = contract?.getAddress();
const queryClient = useQueryClient();
const walletAddress = useAddress();
@@ -397,8 +393,8 @@ export function useCreateAuctionListing(
* @returns a mutation object that can be used to create a new auction listing
* @beta
*/
export function useCancelListing(contract: RequiredParam<MarketplaceImpl>) {
const activeChainId = useActiveChainId();
export function useCancelListing(contract: RequiredParam<Marketplace>) {
const activeChainId = useSDKChainId();
const contractAddress = contract?.getAddress();
const queryClient = useQueryClient();
return useMutation(
@@ -451,8 +447,8 @@ export function useCancelListing(contract: RequiredParam<MarketplaceImpl>) {
* @returns a mutation object that can be used to make a bid on an auction listing
* @beta
*/
export function useMakeBid(contract: RequiredParam<MarketplaceImpl>) {
const activeChainId = useActiveChainId();
export function useMakeBid(contract: RequiredParam<Marketplace>) {
const activeChainId = useSDKChainId();
const contractAddress = contract?.getAddress();
const queryClient = useQueryClient();
const walletAddress = useAddress();
@@ -507,8 +503,8 @@ export function useMakeBid(contract: RequiredParam<MarketplaceImpl>) {
* @returns a mutation object that can be used to buy out an auction listing
* @beta
*/
export function useBuyNow(contract: RequiredParam<MarketplaceImpl>) {
const activeChainId = useActiveChainId();
export function useBuyNow(contract: RequiredParam<Marketplace>) {
const activeChainId = useSDKChainId();
const contractAddress = contract?.getAddress();
const queryClient = useQueryClient();
const walletAddress = useAddress();
+20 -8
View File
@@ -1,4 +1,4 @@
import { useActiveChainId } from "../../Provider";
import { useSDKChainId } from "../../providers/base";
import {
AirdropNFTParams,
BurnNFTParams,
@@ -75,6 +75,7 @@ export function convertResponseToNFTTypeArray(
* @param tokenId - the tokenId to look up
* @returns a response object that includes the metadata for the given tokenId
* @beta
* @twfeature ERC721 | ERC1155
*/
export function useNFT<TContract extends NFTContract>(
contract: RequiredParam<TContract>,
@@ -122,6 +123,7 @@ export function useNFT<TContract extends NFTContract>(
* @param contract - an instance of a {@link NFTContract}
* @param queryParams - query params to pass to the query for the sake of pagination
* @returns a response object that includes an array of NFTs
* @twfeature ERC721Supply | ERC1155Enumerable
* @beta
*/
export function useNFTs<TContract extends NFTContract>(
@@ -170,6 +172,7 @@ export function useNFTs<TContract extends NFTContract>(
* @param contract - an instance of a {@link NFTContract}
* @returns a response object that includes the total count of NFTs
* @beta
* @twfeature ERC721Supply | ERC1155Enumerable
*/
export function useTotalCount<TContract extends NFTContract>(
contract: RequiredParam<TContract>,
@@ -216,10 +219,11 @@ export function useTotalCount<TContract extends NFTContract>(
* @param contract - an instance of a {@link NFTContract}
* @returns a response object that incudes the total minted supply
* @beta
* @twfeature ERC721Supply | ERC1155Enumerable
*/
export function useTotalCirculatingSupply(
contract: RequiredParam<NFTContract>,
tokenId: BigNumberish,
tokenId: RequiredParam<BigNumberish>,
) {
const contractAddress = contract?.getAddress();
const { erc721, erc1155 } = getErcs(contract);
@@ -234,6 +238,7 @@ export function useTotalCirculatingSupply(
erc1155.totalCirculatingSupply,
"Contract instance does not support totalCirculatingSupply",
);
invariant(tokenId, "No tokenId provided");
return await erc1155.totalCirculatingSupply(tokenId);
}
if (erc721) {
@@ -246,7 +251,7 @@ export function useTotalCirculatingSupply(
invariant(false, "Unknown NFT type");
},
{
enabled: !!erc721 || !!erc1155,
enabled: !!erc721 || (!!erc1155 && tokenId !== undefined),
},
);
}
@@ -264,6 +269,7 @@ export function useTotalCirculatingSupply(
* @param ownerWalletAddress - the wallet adress to get owned tokens for
* @returns a response object that includes the list of owned tokens
* @beta
* @twfeature ERC721Enumerable | ERC1155Enumerable
*/
export function useOwnedNFTs<TContract extends NFTContract>(
contract: RequiredParam<TContract>,
@@ -308,6 +314,7 @@ export function useOwnedNFTs<TContract extends NFTContract>(
* @param contract - an instance of a {@link NFTContract}
* @param ownerWalletAddress - the wallet adress to check the balance of
* @returns a response object that includes the total balance of the owner
* @twfeature ERC721 | ERC1155
* @beta
*/
export function useNFTBalance(
@@ -409,11 +416,12 @@ export function useNFTBalance(
* @param contract - an instance of a {@link NFTContract}
* @returns a mutation object that can be used to mint a new NFT token to the connected wallet
* @beta
* @twfeature ERC721Mintable | ERC1155Mintable
*/
export function useMintNFT<TContract extends NFTContract>(
contract: RequiredParam<TContract>,
) {
const activeChainId = useActiveChainId();
const activeChainId = useSDKChainId();
const contractAddress = contract?.getAddress();
const queryClient = useQueryClient();
const { erc1155, erc721 } = getErcs(contract);
@@ -480,9 +488,10 @@ export function useMintNFT<TContract extends NFTContract>(
* @param contract - an instance of a {@link Erc1155}
* @returns a mutation object that can be used to mint a more supply of a token id to the provided wallet
* @beta
* @twfeature ERC1155Mintable
*/
export function useMintNFTSupply(contract: Erc1155) {
const activeChainId = useActiveChainId();
const activeChainId = useSDKChainId();
const contractAddress = contract?.getAddress();
const queryClient = useQueryClient();
@@ -542,11 +551,12 @@ export function useMintNFTSupply(contract: Erc1155) {
* @param contract - an instance of a {@link NFTContract}
* @returns a mutation object that can be used to transfer NFTs
* @beta
* @twfeature ERC721 | ERC1155
*/
export function useTransferNFT<TContract extends NFTContract>(
contract: RequiredParam<TContract>,
) {
const activeChainId = useActiveChainId();
const activeChainId = useSDKChainId();
const contractAddress = contract?.getAddress();
const queryClient = useQueryClient();
const { erc1155, erc721 } = getErcs(contract);
@@ -636,10 +646,11 @@ export function useTransferNFT<TContract extends NFTContract>(
*
* @param contract - an instance of a {@link Erc1155}
* @returns a mutation object that can be used to transfer batch NFTs
* @twfeature ERC1155
* @beta
*/
export function useAirdropNFT(contract: Erc1155) {
const activeChainId = useActiveChainId();
const activeChainId = useSDKChainId();
const contractAddress = contract?.getAddress();
const queryClient = useQueryClient();
@@ -718,12 +729,13 @@ export function useAirdropNFT(contract: Erc1155) {
*
* @param contract - an instance of a {@link NFTContract}
* @returns a mutation object that can be used to burn an NFT token from the connected wallet
* @twfeature ERC721Burnable | ERC1155Burnable
* @beta
*/
export function useBurnNFT<TContract extends NFTContract>(
contract: RequiredParam<TContract>,
) {
const activeChainId = useActiveChainId();
const activeChainId = useSDKChainId();
const contractAddress = contract?.getAddress();
const queryClient = useQueryClient();
const { erc1155, erc721 } = getErcs(contract);
+12 -6
View File
@@ -1,4 +1,4 @@
import { useActiveChainId } from "../../Provider";
import { useSDKChainId } from "../../providers/base";
import { RequiredParam, WalletAddress } from "../../types";
import {
cacheKeys,
@@ -7,7 +7,7 @@ import {
import { useQueryWithNetwork } from "../query-utils/useQueryWithNetwork";
import { useMutation, useQueryClient } from "@tanstack/react-query";
import type { Role, ValidContractInstance } from "@thirdweb-dev/sdk";
import type { VoteImpl } from "@thirdweb-dev/sdk/dist/declarations/src/contracts/prebuilt-implementations/vote";
import type { Vote } from "@thirdweb-dev/sdk/dist/declarations/src/contracts/prebuilt-implementations/vote";
import type { SmartContract } from "@thirdweb-dev/sdk/dist/declarations/src/contracts/smart-contract";
import { constants } from "ethers";
import invariant from "tiny-invariant";
@@ -19,7 +19,7 @@ import invariant from "tiny-invariant";
/**
* @internal
*/
export type ContractWithRoles = Exclude<ValidContractInstance, VoteImpl>;
export type ContractWithRoles = Exclude<ValidContractInstance, Vote>;
/**
* @internal
@@ -50,6 +50,7 @@ type GetAllReturnType<TContract extends ContractWithRoles> = Promise<
*
* @param contract - an instance of a {@link SmartContract}
* @returns a list of addresses for all supported roles on the contract.
* @twfeature PermissionsEnumerable
* @beta
*/
export function useAllRoleMembers<TContract extends ContractWithRoles>(
@@ -81,6 +82,7 @@ export function useAllRoleMembers<TContract extends ContractWithRoles>(
* @param contract - an instance of a {@link SmartContract}
* @param role - the role to get the members of, see {@link Role}
* @returns a list of addresses that are members of the role
* @twfeature PermissionsEnumerable
* @beta
*/
export function useRoleMembers<TContract extends ContractWithRoles>(
@@ -113,6 +115,7 @@ export function useRoleMembers<TContract extends ContractWithRoles>(
* @param role - the role to check the member against, see {@link Role}
* @param walletAddress - the address to check
* @returns true if the address is a member of the role, or false if not
* @twfeature Permissions
* @beta
*/
export function useIsAddressRole<TContract extends ContractWithRoles>(
@@ -174,12 +177,13 @@ export function useIsAddressRole<TContract extends ContractWithRoles>(
*
* @param contract - an instance of a {@link SmartContract}
* @returns a mutation object that can be used to overwrite all roles on the contract
* @twfeature PermissionsEnumerable
* @beta
*/
export function useSetAllRoleMembers<TContract extends ContractWithRoles>(
contract: RequiredParam<TContract>,
) {
const activeChainId = useActiveChainId();
const activeChainId = useSDKChainId();
const contractAddress = contract?.getAddress();
const queryClient = useQueryClient();
@@ -233,12 +237,13 @@ export function useSetAllRoleMembers<TContract extends ContractWithRoles>(
*
* @param contract - an instance of a {@link SmartContract}
* @returns a mutation object that can be used to grant a member of a role on the contract
* @twfeature Permissions
* @beta
*/
export function useGrantRole<TContract extends ContractWithRoles>(
contract: RequiredParam<TContract>,
) {
const activeChainId = useActiveChainId();
const activeChainId = useSDKChainId();
const contractAddress = contract?.getAddress();
const queryClient = useQueryClient();
@@ -291,12 +296,13 @@ export function useGrantRole<TContract extends ContractWithRoles>(
*
* @param contract - an instance of a {@link SmartContract}
* @returns a mutation object that can be used to revoke a role from a member on the contract
* @twfeature Permissions
* @beta
*/
export function useRevokeRole<TContract extends ContractWithRoles>(
contract: RequiredParam<TContract>,
) {
const activeChainId = useActiveChainId();
const activeChainId = useSDKChainId();
const contractAddress = contract?.getAddress();
const queryClient = useQueryClient();
return useMutation(
+14 -6
View File
@@ -1,4 +1,4 @@
import { useActiveChainId } from "../../Provider";
import { useSDKChainId } from "../../providers/base";
import {
ClaimTokenParams,
RequiredParam,
@@ -29,6 +29,7 @@ import invariant from "tiny-invariant";
*
* @param contract - an instance of a ERC20 contract.
* @returns a response object that incudes the total minted supply
* @twfeature ERC20
* @beta
*/
export function useTokenSupply(contract: RequiredParam<Erc20>) {
@@ -55,6 +56,7 @@ export function useTokenSupply(contract: RequiredParam<Erc20>) {
*
* @param contract - an instance of a ERC20 contract.
* @returns a response object that includes the balance of the address
* @twfeature ERC20
* @beta
*/
export function useTokenBalance(
@@ -85,6 +87,7 @@ export function useTokenBalance(
*
* @param contract - an instance of an ERC20 contract.
* @returns a response object that includes the decimals of the ERC20 token
* @twfeature ERC20
* @beta
*/
export function useTokenDecimals(contract: RequiredParam<Erc20>) {
@@ -134,10 +137,11 @@ export function useTokenDecimals(contract: RequiredParam<Erc20>) {
*
* @param contract - an instance of a contract that extends the ERC20 spec (token, token drop, custom contract that follows the ERC20 spec)
* @returns a mutation object that can be used to mint new tokens to the connected wallet
* @twfeature ERC20Mintable
* @beta
*/
export function useMintToken(contract: RequiredParam<Erc20>) {
const activeChainId = useActiveChainId();
const activeChainId = useSDKChainId();
const contractAddress = contract?.getAddress();
const queryClient = useQueryClient();
@@ -187,12 +191,13 @@ export function useMintToken(contract: RequiredParam<Erc20>) {
*
* @param contract - an instance of a {@link Erc20}
* @returns a mutation object that can be used to tokens to the wallet specificed in the params
* @twfeature ERC20ClaimableWithConditions
* @beta
*/
export function useClaimToken<TContract extends Erc20>(
contract: RequiredParam<TContract>,
) {
const activeChainId = useActiveChainId();
const activeChainId = useSDKChainId();
const contractAddress = contract?.getAddress();
const queryClient = useQueryClient();
@@ -246,10 +251,11 @@ export function useClaimToken<TContract extends Erc20>(
*
* @param contract - an instance of a contract that extends the ERC20 spec (token, token drop, custom contract that follows the ERC20 spec)
* @returns a mutation object that can be used to transfer tokens
* @twfeature ERC20
* @beta
*/
export function useTransferToken(contract: RequiredParam<Erc20>) {
const activeChainId = useActiveChainId();
const activeChainId = useSDKChainId();
const contractAddress = contract?.getAddress();
const queryClient = useQueryClient();
@@ -299,10 +305,11 @@ export function useTransferToken(contract: RequiredParam<Erc20>) {
*
* @param contract - an instance of a contract that extends the ERC20 spec (token, token drop, custom contract that follows the ERC20 spec)
* @returns a mutation object that can be used to transfer batch tokens
* @twfeature ERC20
* @beta
*/
export function useTransferBatchToken(contract: RequiredParam<Erc20>) {
const activeChainId = useActiveChainId();
const activeChainId = useSDKChainId();
const contractAddress = contract?.getAddress();
const queryClient = useQueryClient();
@@ -359,10 +366,11 @@ export function useTransferBatchToken(contract: RequiredParam<Erc20>) {
*
* @param contract - an instance of a contract that extends the ERC20 spec (token, token drop, custom contract that follows the ERC20 spec)
* @returns a mutation object that can be used to burn tokens from the connected wallet
* @twfeature ERC20Burnable
* @beta
*/
export function useBurnToken(contract: RequiredParam<Erc20>) {
const activeChainId = useActiveChainId();
const activeChainId = useSDKChainId();
const contractAddress = contract?.getAddress();
const queryClient = useQueryClient();
-59
View File
@@ -1,59 +0,0 @@
import { SupportedChainId } from "../../constants/chain";
import { useThirdwebConfigContext } from "../../contexts/thirdweb-config";
import { ContractAddress } from "../../types";
import { cacheKeys } from "../../utils/cache-keys";
import { useAddress } from "../useAddress";
import { useChainId } from "../useChainId";
import { useSigner } from "../useSigner";
import { useQuery } from "@tanstack/react-query";
import { UserWallet } from "@thirdweb-dev/sdk";
import { useMemo } from "react";
/**
* A hook to get the native or (optional) ERC20 token balance of the connected wallet.
*
* @param tokenAddress - the address of the token contract, if empty will use the chain's native token
* @returns the balance of the connected wallet (native or ERC20)
* @beta
*/
export function useBalance(tokenAddress?: ContractAddress) {
const { rpcUrlMap } = useThirdwebConfigContext();
const chainId = useChainId() as SupportedChainId;
const signer = useSigner();
const walletAddress = useAddress();
const walletSDK = useMemo(() => {
if (signer) {
const rpcUrl = rpcUrlMap[chainId];
return new UserWallet(signer, {
readonlySettings: rpcUrl
? {
rpcUrl,
chainId,
}
: undefined,
});
}
return undefined;
// we're not apssing rpcUrlMap as a dependency because it should be constant anyways
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [signer, chainId]);
const cacheKey = useMemo(() => {
return cacheKeys.wallet.balance(chainId, walletAddress, tokenAddress);
}, [chainId, tokenAddress, walletAddress]);
return useQuery(
cacheKey,
() => {
return walletSDK?.balance(tokenAddress);
},
{
// if user is not logged in no reason to try to fetch
enabled: !!walletSDK && !!walletAddress,
retry: true,
keepPreviousData: false,
},
);
}
+1 -1
View File
@@ -1,5 +1,5 @@
import { useSDK } from "../../Provider";
import { useThirdwebAuthConfig } from "../../contexts/thirdweb-auth";
import { useSDK } from "../../providers/base";
import { cacheKeys } from "../../utils/cache-keys";
import { useQueryClient } from "@tanstack/react-query";
import { LoginOptions } from "@thirdweb-dev/sdk";
@@ -2,9 +2,10 @@ import {
GnosisConnectorArguments,
GnosisSafeConnector,
} from "../../connectors/gnosis-safe";
import { useConnect } from "../useConnect";
import { useConnect } from "../wagmi-required/useConnect";
import { utils } from "ethers";
import invariant from "tiny-invariant";
import { useContext as useWagmiContext } from "wagmi";
/**
* Hook for connecting to a Gnosis Safe. This enables multisig wallets to connect to your application and sing transactions.
@@ -32,6 +33,11 @@ import invariant from "tiny-invariant";
* @public
*/
export function useGnosis() {
const wagmiContext = useWagmiContext();
invariant(
wagmiContext,
`useGnosis() can only be used inside <ThirdwebProvider />. If you are using <ThirdwebSDKProvider /> you will have to use your own wallet-connection logic.`,
);
const [connectors, connect] = useConnect();
if (connectors.loading) {
return () => Promise.reject("Gnosis connector not ready to be used, yet");
@@ -1,7 +1,8 @@
import { MagicConnector } from "../../connectors/magic";
import { useConnect } from "../useConnect";
import { useConnect } from "../wagmi-required/useConnect";
import { LoginWithMagicLinkConfiguration } from "magic-sdk";
import invariant from "tiny-invariant";
import { useContext as useWagmiContext } from "wagmi";
/**
* Hook for connecting to an email wallet using magic link.
@@ -66,6 +67,11 @@ import invariant from "tiny-invariant";
* @public
*/
export function useMagic() {
const wagmiContext = useWagmiContext();
invariant(
wagmiContext,
`useMagic() can only be used inside <ThirdwebProvider />. If you are using <ThirdwebSDKProvider /> you will have to use your own wallet-connection logic.`,
);
const [connectors, connect] = useConnect();
if (connectors.loading) {
return () => Promise.reject("Magic connector not ready to be used, yet");
@@ -1,6 +1,7 @@
import { isMobile } from "../../utils/isMobile";
import { useConnect } from "../useConnect";
import { useConnect } from "../wagmi-required/useConnect";
import invariant from "tiny-invariant";
import { useContext as useWagmiContext } from "wagmi";
/**
* Hook for connecting to a Metamask wallet.
@@ -31,6 +32,11 @@ import invariant from "tiny-invariant";
* @public
*/
export function useMetamask() {
const wagmiContext = useWagmiContext();
invariant(
wagmiContext,
`useMetamask() can only be used inside <ThirdwebProvider />. If you are using <ThirdwebSDKProvider /> you will have to use your own wallet-connection logic.`,
);
const [connectors, connect] = useConnect();
const isMetaMaskInjected =
@@ -1,5 +1,6 @@
import { useConnect } from "../useConnect";
import { useConnect } from "../wagmi-required/useConnect";
import invariant from "tiny-invariant";
import { useContext as useWagmiContext } from "wagmi";
/**
* Hook for connecting to a mobile wallet with Wallet Connect
@@ -31,6 +32,11 @@ import invariant from "tiny-invariant";
* @public
*/
export function useWalletConnect() {
const wagmiContext = useWagmiContext();
invariant(
wagmiContext,
`useWalletConnect() can only be used inside <ThirdwebProvider />. If you are using <ThirdwebSDKProvider /> you will have to use your own wallet-connection logic.`,
);
const [connectors, connect] = useConnect();
if (connectors.loading) {
return () =>
@@ -1,5 +1,6 @@
import { useConnect } from "../useConnect";
import { useConnect } from "../wagmi-required/useConnect";
import invariant from "tiny-invariant";
import { useContext as useWagmiContext } from "wagmi";
/**
* Hook for connecting to a Coinbase wallet.
@@ -31,6 +32,11 @@ import invariant from "tiny-invariant";
* @public
*/
export function useCoinbaseWallet() {
const wagmiContext = useWagmiContext();
invariant(
wagmiContext,
`useCoinbaseWallet() can only be used inside <ThirdwebProvider />. If you are using <ThirdwebSDKProvider /> you will have to use your own wallet-connection logic.`,
);
const [connectors, connect] = useConnect();
if (connectors.loading) {
return () => Promise.reject("Coinbase connector not ready to be used, yet");
@@ -1,6 +1,6 @@
import { showDeprecationWarning } from "../../utils/deprecation-warning";
import { useContract } from "../async/contracts";
import { EditionImpl } from "@thirdweb-dev/sdk/dist/declarations/src/contracts/prebuilt-implementations/edition";
import { Edition } from "@thirdweb-dev/sdk/dist/declarations/src/contracts/prebuilt-implementations/edition";
/**
* Hook for getting an instance of an `Edition` contract. This contract is used to interface with ERC1155 compliant NFTs.
@@ -25,9 +25,9 @@ import { EditionImpl } from "@thirdweb-dev/sdk/dist/declarations/src/contracts/p
* }
* ```
* @public
* @depreated use `useContract()` instead
* @deprecated use `useContract()` instead
*/
export function useEdition(contractAddress?: string) {
showDeprecationWarning("useEdition()", "useContract<Edition>()");
return useContract<EditionImpl>(contractAddress).contract;
return useContract<Edition>(contractAddress).contract;
}
@@ -1,6 +1,6 @@
import { showDeprecationWarning } from "../../utils/deprecation-warning";
import { useContract } from "../async/contracts";
import { EditionDropImpl } from "@thirdweb-dev/sdk/dist/declarations/src/contracts/prebuilt-implementations/edition-drop";
import { EditionDrop } from "@thirdweb-dev/sdk/dist/declarations/src/contracts/prebuilt-implementations/edition-drop";
/**
* Hook for getting an instance of an `EditionDrop` contract. This conract is used to interface with ERC1155 compliant NFTs that can be lazily minted.
@@ -24,9 +24,9 @@ import { EditionDropImpl } from "@thirdweb-dev/sdk/dist/declarations/src/contrac
* }
* ```
* @public
* @depreated use `useContract()` instead
* @deprecated use `useContract()` instead
*/
export function useEditionDrop(contractAddress?: string) {
showDeprecationWarning("useEditionDrop()", "useContract<EditionDrop>()");
return useContract<EditionDropImpl>(contractAddress).contract;
return useContract<EditionDrop>(contractAddress).contract;
}
@@ -1,6 +1,6 @@
import { showDeprecationWarning } from "../../utils/deprecation-warning";
import { useContract } from "../async/contracts";
import { MarketplaceImpl } from "@thirdweb-dev/sdk/dist/declarations/src/contracts/prebuilt-implementations/marketplace";
import { Marketplace } from "@thirdweb-dev/sdk/dist/declarations/src/contracts/prebuilt-implementations/marketplace";
/**
* Hook for getting an instance of a `Marketplace` contract. This contract is used to support marketplace for purchase and sale of on-chain assets.
@@ -25,9 +25,9 @@ import { MarketplaceImpl } from "@thirdweb-dev/sdk/dist/declarations/src/contrac
* }
* ```
* @public
* @depreated use `useContract()` instead
* @deprecated use `useContract()` instead
*/
export function useMarketplace(contractAddress?: string) {
showDeprecationWarning("useMarketplace()", "useContract<Marketplace>()");
return useContract<MarketplaceImpl>(contractAddress).contract;
return useContract<Marketplace>(contractAddress).contract;
}
@@ -1,6 +1,6 @@
import { showDeprecationWarning } from "../../utils/deprecation-warning";
import { useContract } from "../async/contracts";
import { MultiwrapImpl } from "@thirdweb-dev/sdk/dist/declarations/src/contracts/prebuilt-implementations/multiwrap";
import { Multiwrap } from "@thirdweb-dev/sdk/dist/declarations/src/contracts/prebuilt-implementations/multiwrap";
/**
* Hook for getting an instance of an `Multiwrap` contract. This contract is an ERC721 in which you can wrap ERC721, ERC1155 and ERC20 tokens.
@@ -24,9 +24,9 @@ import { MultiwrapImpl } from "@thirdweb-dev/sdk/dist/declarations/src/contracts
* }
* ```
* @public
* @depreated use `useContract()` instead
* @deprecated use `useContract()` instead
*/
export function useMultiwrap(contractAddress?: string) {
showDeprecationWarning("useMultiwrap()", "useContract<Multiwrap>()");
return useContract<MultiwrapImpl>(contractAddress).contract;
return useContract<Multiwrap>(contractAddress).contract;
}
@@ -1,6 +1,6 @@
import { showDeprecationWarning } from "../../utils/deprecation-warning";
import { useContract } from "../async/contracts";
import { NFTCollectionImpl } from "@thirdweb-dev/sdk/dist/declarations/src/contracts/prebuilt-implementations/nft-collection";
import { NFTCollection } from "@thirdweb-dev/sdk/dist/declarations/src/contracts/prebuilt-implementations/nft-collection";
/**
* Hook for getting an instance of an `NFTCollection` contract. This contract is meant to interface with ERC721 compliant NFTs.
@@ -25,9 +25,9 @@ import { NFTCollectionImpl } from "@thirdweb-dev/sdk/dist/declarations/src/contr
* }
* ```
* @public
* @depreated use `useContract()` instead
* @deprecated use `useContract()` instead
*/
export function useNFTCollection(contractAddress?: string) {
showDeprecationWarning("useNFTCollection()", "useContract<NFTCollection>()");
return useContract<NFTCollectionImpl>(contractAddress).contract;
return useContract<NFTCollection>(contractAddress).contract;
}
@@ -1,6 +1,6 @@
import { showDeprecationWarning } from "../../utils/deprecation-warning";
import { useContract } from "../async/contracts";
import { NFTDropImpl } from "@thirdweb-dev/sdk/dist/declarations/src/contracts/prebuilt-implementations/nft-drop";
import { NFTDrop } from "@thirdweb-dev/sdk/dist/declarations/src/contracts/prebuilt-implementations/nft-drop";
/**
* Hook for getting an instance of an `NFTDrop` contract. This contract is meant to interface with ERC721 compliant NFTs that can be lazily minted.
@@ -24,9 +24,9 @@ import { NFTDropImpl } from "@thirdweb-dev/sdk/dist/declarations/src/contracts/p
* }
* ```
* @public
* @depreated use `useContract()` instead
* @deprecated use `useContract()` instead
*/
export function useNFTDrop(contractAddress?: string) {
showDeprecationWarning("useNFTDrop()", "useContract<NFTDrop>()");
return useContract<NFTDropImpl>(contractAddress).contract;
return useContract<NFTDrop>(contractAddress).contract;
}
@@ -1,6 +1,6 @@
import { showDeprecationWarning } from "../../utils/deprecation-warning";
import { useContract } from "../async/contracts";
import { PackImpl } from "@thirdweb-dev/sdk/dist/declarations/src/contracts/prebuilt-implementations/pack";
import { Pack } from "@thirdweb-dev/sdk/dist/declarations/src/contracts/prebuilt-implementations/pack";
/**
* Hook for getting an instance of a `Pack` contract. This contract supports the creation of on-chain luck-based lootboxes.
@@ -25,9 +25,9 @@ import { PackImpl } from "@thirdweb-dev/sdk/dist/declarations/src/contracts/preb
* }
* ```
* @public
* @depreated use `useContract()` instead
* @deprecated use `useContract()` instead
*/
export function usePack(contractAddress?: string) {
showDeprecationWarning("usePack()", "useContract<Pack>()");
return useContract<PackImpl>(contractAddress).contract;
return useContract<Pack>(contractAddress).contract;
}
@@ -1,6 +1,6 @@
import { showDeprecationWarning } from "../../utils/deprecation-warning";
import { useContract } from "../async/contracts";
import { SignatureDropImpl } from "@thirdweb-dev/sdk/dist/declarations/src/contracts/prebuilt-implementations/signature-drop";
import { SignatureDrop } from "@thirdweb-dev/sdk/dist/declarations/src/contracts/prebuilt-implementations/signature-drop";
/**
* Hook for getting an instance of an `SignatureDrop` contract. This contract is meant to interface with ERC721 compliant NFTs that can be lazily minted.
@@ -24,9 +24,9 @@ import { SignatureDropImpl } from "@thirdweb-dev/sdk/dist/declarations/src/contr
* }
* ```
* @public
* @depreated use `useContract()` instead
* @deprecated use `useContract()` instead
*/
export function useSignatureDrop(contractAddress?: string) {
showDeprecationWarning("useSignatureDrop()", "useContract<SignatureDrop>()");
return useContract<SignatureDropImpl>(contractAddress).contract;
return useContract<SignatureDrop>(contractAddress).contract;
}
@@ -1,6 +1,6 @@
import { showDeprecationWarning } from "../../utils/deprecation-warning";
import { useContract } from "../async/contracts";
import { SplitImpl } from "@thirdweb-dev/sdk/dist/declarations/src/contracts/prebuilt-implementations/split";
import { Split } from "@thirdweb-dev/sdk/dist/declarations/src/contracts/prebuilt-implementations/split";
/**
* Hook for getting an instance of a `Split` contract. This contract supports fund distribution to multiple parties.
@@ -25,9 +25,9 @@ import { SplitImpl } from "@thirdweb-dev/sdk/dist/declarations/src/contracts/pre
* }
* ```
* @public
* @depreated use `useContract()` instead
* @deprecated use `useContract()` instead
*/
export function useSplit(contractAddress?: string) {
showDeprecationWarning("useSplit()", "useContract<Split>()");
return useContract<SplitImpl>(contractAddress).contract;
return useContract<Split>(contractAddress).contract;
}
@@ -1,6 +1,6 @@
import { showDeprecationWarning } from "../../utils/deprecation-warning";
import { useContract } from "../async/contracts";
import { TokenImpl } from "@thirdweb-dev/sdk/dist/declarations/src/contracts/prebuilt-implementations/token";
import { Token } from "@thirdweb-dev/sdk/dist/declarations/src/contracts/prebuilt-implementations/token";
/**
* Hook for getting an instance of a `Token` contract. This contract supports ERC20 compliant tokens.
@@ -25,9 +25,9 @@ import { TokenImpl } from "@thirdweb-dev/sdk/dist/declarations/src/contracts/pre
* }
* ```
* @public
* @depreated use `useContract()` instead
* @deprecated use `useContract()` instead
*/
export function useToken(contractAddress?: string) {
showDeprecationWarning("useToken()", "useContract<Token>()");
return useContract<TokenImpl>(contractAddress).contract;
return useContract<Token>(contractAddress).contract;
}
@@ -1,6 +1,6 @@
import { showDeprecationWarning } from "../../utils/deprecation-warning";
import { useContract } from "../async/contracts";
import { TokenDropImpl } from "@thirdweb-dev/sdk/dist/declarations/src/contracts/prebuilt-implementations/token-drop";
import { TokenDrop } from "@thirdweb-dev/sdk/dist/declarations/src/contracts/prebuilt-implementations/token-drop";
/**
* Hook for getting an instance of a `Token Drop` contract.
@@ -25,9 +25,9 @@ import { TokenDropImpl } from "@thirdweb-dev/sdk/dist/declarations/src/contracts
* }
* ```
* @public
* @depreated use `useContract()` instead
* @deprecated use `useContract()` instead
*/
export function useTokenDrop(contractAddress?: string) {
showDeprecationWarning("useTokenDrop()", "useContract<TokenDrop>()");
return useContract<TokenDropImpl>(contractAddress).contract;
return useContract<TokenDrop>(contractAddress).contract;
}
@@ -1,6 +1,6 @@
import { showDeprecationWarning } from "../../utils/deprecation-warning";
import { useContract } from "../async/contracts";
import { VoteImpl } from "@thirdweb-dev/sdk/dist/declarations/src/contracts/prebuilt-implementations/vote";
import { Vote } from "@thirdweb-dev/sdk/dist/declarations/src/contracts/prebuilt-implementations/vote";
/**
* Hook for getting an instance of an `Vote` contract. This contract enables fully featured voting-based decentralized governance systems.
@@ -25,9 +25,9 @@ import { VoteImpl } from "@thirdweb-dev/sdk/dist/declarations/src/contracts/preb
* }
* ```
* @public
* @depreated use `useContract()` instead
* @deprecated use `useContract()` instead
*/
export function useVote(contractAddress?: string) {
showDeprecationWarning("useVote()", "useContract<Vote>()");
return useContract<VoteImpl>(contractAddress).contract;
return useContract<Vote>(contractAddress).contract;
}
@@ -1,4 +1,4 @@
import { useActiveChainId } from "../../Provider";
import { useSDKChainId } from "../../providers/base";
import { createCacheKeyWithNetwork } from "../../utils/cache-keys";
import {
QueryFunction,
@@ -22,7 +22,7 @@ export function useQueryWithNetwork<
"queryKey" | "queryFn"
>,
): UseQueryResult<TData, TError> {
const activeChainId = useActiveChainId();
const activeChainId = useSDKChainId();
const mergedOptions: Omit<
UseQueryOptions<TQueryFnData, TError, TData, TQueryKey>,
-31
View File
@@ -1,31 +0,0 @@
import { useAccount } from "wagmi";
/**
* Hook for accessing the address of the connected wallet
*
* ```javascript
* import { useAddress } from "@thirdweb-dev/react"
* ```
*
*
* @example
* To get the address of the connected wallet, you can use the hook as follows:
*
* ```javascript
* import { useAddress } from "@thirdweb-dev/react"
*
* const App = () => {
* const address = useAddress()
*
* return <div>{address}</div>
* }
* ```
*
* The `address` variable will hold the address of the connected wallet if a user has connected using one of the supported wallet connection hooks.
*
* @public
*/
export function useAddress(): string | undefined {
const [account] = useAccount();
return account.data?.address;
}
-25
View File
@@ -1,25 +0,0 @@
import { useNetwork } from "wagmi";
/**
* Hook for accessing the chain ID of the network the current wallet is connected to
*
* ```javascript
* import { useChainId } from "@thirdweb-dev/react"
* ```
*
* @example
* You can get the chain ID of the connected wallet by using the hook as follows:
* ```javascript
* import { useChainId } from "@thirdweb-dev/react"
*
* const App = () => {
* const chainId = useChainId()
*
* return <div>{chainId}</div>
* }
* ```
* @public
*/
export function useChainId(): number | undefined {
return useNetwork()["0"].data.chain?.id;
}
-9
View File
@@ -1,9 +0,0 @@
import { useConnect as useWagmiConnect } from "wagmi";
/**
* for now just re-exported
* @internal
*/
export function useConnect() {
return useWagmiConnect();
}
@@ -1,5 +1,5 @@
import { useDesiredChainId } from "../Provider";
import { useChainId } from "./useChainId";
import { useDesiredChainId } from "../providers/base";
import { useChainId } from "./wallet";
/**
* Hook for checking whether the connected wallet is on the correct network specified by the `desiredChainId` passed to the `<ThirdwebProvider />`.
@@ -28,16 +28,16 @@ import { useChainId } from "./useChainId";
*/
export function useNetworkMismatch() {
const desiredChainId = useDesiredChainId();
const activeChainId = useChainId();
const walletChainId = useChainId();
if (desiredChainId === -1) {
// means no desiredChainId is set in the <ThirdwebProvider />, so we don't care about the network mismatch
return false;
}
if (!activeChainId) {
if (!walletChainId) {
// means no wallet is connected yet, so we don't care about the network mismatch
return false;
}
// check if the chainIds are different
return desiredChainId !== activeChainId;
return desiredChainId !== walletChainId;
}
+2 -2
View File
@@ -1,5 +1,5 @@
import { SDKOptions, ThirdwebSDK } from "@thirdweb-dev/sdk";
import type { IStorage } from "@thirdweb-dev/storage";
import type { ThirdwebStorage } from "@thirdweb-dev/storage";
import { useMemo } from "react";
/**
@@ -8,7 +8,7 @@ import { useMemo } from "react";
export function useReadonlySDK(
readonlyRpcUrl: string,
sdkOptions: SDKOptions,
storageInterface?: IStorage,
storageInterface?: ThirdwebStorage,
): ThirdwebSDK {
return useMemo(() => {
return new ThirdwebSDK(
+4 -41
View File
@@ -1,47 +1,10 @@
import { Signer } from "ethers";
import { useEffect, useRef } from "react";
import { useAccount, useNetwork, useSigner as useWagmiSigner } from "wagmi";
import { useThirdwebConnectedWalletContext } from "../contexts/thirdweb-wallet";
import type { Signer } from "ethers";
/**
*
* @internal
*/
export function useSigner() {
const [signer, getSigner] = useWagmiSigner();
const [account] = useAccount();
const [network] = useNetwork();
const _getSignerPromise = useRef<ReturnType<typeof getSigner> | null>(null);
const address = account.data?.address;
const chainId = network.data.chain?.id;
const previousAddress = usePrevious(account.data?.address);
const previousChainId = usePrevious(network.data?.chain?.id);
useEffect(() => {
if (address !== previousAddress || chainId !== previousChainId) {
if (!_getSignerPromise.current) {
return;
} else {
_getSignerPromise.current = getSigner().finally(() => {
_getSignerPromise.current = null;
});
}
}
}, [address, chainId, getSigner, previousAddress, previousChainId]);
return Signer.isSigner(signer.data) ? signer.data : undefined;
}
function usePrevious<TVal>(value: TVal): TVal | undefined {
// The ref object is a generic container whose current property is mutable ...
// ... and can hold any value, similar to an instance property on a class
const ref = useRef<TVal>();
// Store current value in ref
useEffect(() => {
ref.current = value;
}, [value]); // Only re-run if value changes
// Return previous value (happens before update in useEffect above)
return ref.current;
export function useSigner(): Signer | undefined {
return useThirdwebConnectedWalletContext().signer;
}
@@ -0,0 +1,17 @@
import invariant from "tiny-invariant";
import {
useAccount as useWagmiAccount,
useContext as useWagmiContext,
} from "wagmi";
/**
* @internal
*/
export function useAccount() {
const wagmiContext = useWagmiContext();
invariant(
wagmiContext,
`useNetwork() can only be used inside <ThirdwebProvider />. If you are using <ThirdwebSDKProvider /> you will have to use your own network logic.`,
);
return useWagmiAccount();
}
@@ -0,0 +1,18 @@
import invariant from "tiny-invariant";
import {
useConnect as useWagmiConnect,
useContext as useWagmiContext,
} from "wagmi";
/**
* for now just re-exported
* @internal
*/
export function useConnect() {
const wagmiContext = useWagmiContext();
invariant(
wagmiContext,
`useConnect() can only be used inside <ThirdwebProvider />. If you are using <ThirdwebSDKProvider /> you will have to use your own connection logic.`,
);
return useWagmiConnect();
}
@@ -1,6 +1,7 @@
import { GnosisSafeConnector } from "../connectors/gnosis-safe";
import { GnosisSafeConnector } from "../../connectors/gnosis-safe";
import { useConnect } from "./useConnect";
import { useAccount } from "wagmi";
import invariant from "tiny-invariant";
import { useAccount, useContext as useWagmiContext } from "wagmi";
/**
* Hook for disconnecting the currently connected wallet
@@ -31,6 +32,11 @@ import { useAccount } from "wagmi";
* @public
*/
export function useDisconnect(options?: { reconnectAfterGnosis?: boolean }) {
const wagmiContext = useWagmiContext();
invariant(
wagmiContext,
`useDisconnect() can only be used inside <ThirdwebProvider />. If you are using <ThirdwebSDKProvider /> you will have to use your own connection logic.`,
);
const optsWithDefaults = { ...{ reconnectAfterGnosis: true }, ...options };
const [, connect] = useConnect();
const [data, disconnect] = useAccount();
@@ -1,4 +1,8 @@
import { useNetwork as useWagmiNetwork } from "wagmi";
import invariant from "tiny-invariant";
import {
useNetwork as useWagmiNetwork,
useContext as useWagmiContext,
} from "wagmi";
/**
* Hook for getting metadata about the network the current wallet is connected to and switching networks
@@ -25,5 +29,10 @@ import { useNetwork as useWagmiNetwork } from "wagmi";
*/
export function useNetwork() {
const wagmiContext = useWagmiContext();
invariant(
wagmiContext,
`useNetwork() can only be used inside <ThirdwebProvider />. If you are using <ThirdwebSDKProvider /> you will have to use your own network logic.`,
);
return useWagmiNetwork();
}
+95
View File
@@ -0,0 +1,95 @@
import { useThirdwebConnectedWalletContext } from "../contexts/thirdweb-wallet";
import { ContractAddress } from "../types";
import { cacheKeys } from "../utils/cache-keys";
import { useQuery } from "@tanstack/react-query";
import { useMemo } from "react";
/**
* A hook to get the native or (optional) ERC20 token balance of the connected wallet.
*
* @param tokenAddress - the address of the token contract, if empty will use the chain's native token
* @returns the balance of the connected wallet (native or ERC20)
* @beta
*/
export function useBalance(tokenAddress?: ContractAddress) {
const walletAddress = useAddress();
const { wallet, address, chainId } = useThirdwebConnectedWalletContext();
const cacheKey = useMemo(() => {
return cacheKeys.wallet.balance(chainId || -1, address, tokenAddress);
}, [chainId, tokenAddress, address]);
return useQuery(
cacheKey,
() => {
return wallet?.balance(tokenAddress);
},
{
// if user is not logged in no reason to try to fetch
enabled: !!wallet && !!walletAddress && !!chainId,
retry: true,
keepPreviousData: false,
},
);
}
/**
* @internal
*/
export function useConnectedWallet() {
return useThirdwebConnectedWalletContext().wallet;
}
/**
* Hook for accessing the address of the connected wallet
*
* ```javascript
* import { useAddress } from "@thirdweb-dev/react"
* ```
*
*
* @example
* To get the address of the connected wallet, you can use the hook as follows:
*
* ```javascript
* import { useAddress } from "@thirdweb-dev/react"
*
* const App = () => {
* const address = useAddress()
*
* return <div>{address}</div>
* }
* ```
*
* The `address` variable will hold the address of the connected wallet if a user has connected using one of the supported wallet connection hooks.
*
* @public
*/
export function useAddress(): string | undefined {
return useThirdwebConnectedWalletContext().address;
}
/**
* Hook for accessing the chain ID of the network the current wallet is connected to
*
* ```javascript
* import { useChainId } from "@thirdweb-dev/react"
* ```
*
* @example
* You can get the chain ID of the connected wallet by using the hook as follows:
* ```javascript
* import { useChainId } from "@thirdweb-dev/react"
*
* const App = () => {
* const chainId = useChainId()
*
* return <div>{chainId}</div>
* }
* ```
* @public
*/
export function useChainId(): number | undefined {
return useThirdwebConnectedWalletContext().chainId;
}
+27 -22
View File
@@ -1,36 +1,41 @@
// providers
export * from "./providers/base";
export * from "./providers/full";
// contract hooks
export * from "./Provider";
export * from "./hooks/auth";
export * from "./hooks/contracts";
export * from "./hooks/useDisconnect";
export * from "./hooks/useConnect";
export * from "./hooks/useSigner";
export * from "./hooks/useAddress";
export * from "./hooks/useReadonlySDK";
export * from "./hooks/connectors/useMetamask";
export * from "./hooks/connectors/useWalletConnect";
export * from "./hooks/connectors/useWalletLink";
export * from "./hooks/connectors/useGnosis";
export * from "./hooks/connectors/useMagic";
export * from "./hooks/useChainId";
export * from "./hooks/useNetworkMismatch";
export * from "./hooks/useNetwork";
// re-exports
export { defaultChains, defaultL2Chains, useAccount, useProvider } from "wagmi";
export { ChainId } from "@thirdweb-dev/sdk";
// async hooks
// async contract hooks
export * from "./hooks/async/contracts";
export * from "./hooks/async/nft";
export * from "./hooks/async/drop";
export * from "./hooks/async/marketplace";
export * from "./hooks/async/token";
export * from "./hooks/async/claim-conditions";
export * from "./hooks/async/wallet";
export * from "./hooks/async/contract-settings";
export * from "./hooks/async/roles";
// thirdweb hooks (work as long as at least `<ThirdwebSDkProvider>` is used)
export * from "./hooks/auth";
export * from "./hooks/useSigner";
export * from "./hooks/useReadonlySDK";
export * from "./hooks/useNetworkMismatch";
export * from "./hooks/wallet";
// require to be inside `<ThirdwebProvider />`
export * from "./hooks/wagmi-required/useAccount";
export * from "./hooks/wagmi-required/useNetwork";
export * from "./hooks/wagmi-required/useDisconnect";
export * from "./hooks/wagmi-required/useConnect";
export * from "./hooks/connectors/useMetamask";
export * from "./hooks/connectors/useWalletConnect";
export * from "./hooks/connectors/useWalletLink";
export * from "./hooks/connectors/useGnosis";
export * from "./hooks/connectors/useMagic";
// re-exports
export { ChainId } from "@thirdweb-dev/sdk";
// types
export * from "./types";
export type { ThirdwebAuthConfig } from "./contexts/thirdweb-auth";
+164
View File
@@ -0,0 +1,164 @@
import {
ThirdwebAuthConfig,
ThirdwebAuthConfigProvider,
} from "../contexts/thirdweb-auth";
import {
ThirdwebConnectedWalletProvider,
useThirdwebConnectedWalletContext,
} from "../contexts/thirdweb-wallet";
import { RequiredParam } from "../types";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import {
ChainOrRpc,
SDKOptions,
SignerOrProvider,
SUPPORTED_CHAIN_ID,
ThirdwebSDK,
} from "@thirdweb-dev/sdk";
import { ThirdwebStorage } from "@thirdweb-dev/storage";
import { Signer } from "ethers";
import { createContext, useContext, useEffect, useMemo } from "react";
import invariant from "tiny-invariant";
interface TWSDKContext {
sdk?: ThirdwebSDK;
_inProvider?: true;
desiredChainId: number;
}
const ThirdwebSDKContext = createContext<TWSDKContext>({ desiredChainId: -1 });
export interface ThirdwebSDKProviderProps {
desiredChainId: RequiredParam<SUPPORTED_CHAIN_ID>;
provider: ChainOrRpc | SignerOrProvider;
signer?: Signer;
sdkOptions?: SDKOptions;
storageInterface?: ThirdwebStorage;
authConfig?: ThirdwebAuthConfig;
queryClient?: QueryClient;
}
/**
*
* @internal
*/
export const WrappedThirdwebSDKProvider: React.FC<
React.PropsWithChildren<Omit<ThirdwebSDKProviderProps, "signer">>
> = ({
sdkOptions,
desiredChainId,
storageInterface,
provider,
queryClient,
authConfig,
children,
}) => {
const queryClientWithDefault: QueryClient = useMemo(() => {
return queryClient ? queryClient : new QueryClient();
}, [queryClient]);
const { signer } = useThirdwebConnectedWalletContext();
const sdk = useMemo(() => {
if (!desiredChainId || typeof window === "undefined") {
return undefined;
}
const _sdk = new ThirdwebSDK(provider, sdkOptions, storageInterface);
(_sdk as any)._constructedAt = Date.now();
(_sdk as any)._chainId = desiredChainId;
return _sdk;
}, [provider, sdkOptions, storageInterface, desiredChainId]);
useEffect(() => {
if (signer && sdk && (sdk as any)._chainId === desiredChainId) {
sdk.updateSignerOrProvider(signer);
}
}, [signer, sdk, desiredChainId]);
const ctxValue = useMemo(
() => ({
sdk,
desiredChainId: desiredChainId || -1,
_inProvider: true as const,
}),
[desiredChainId, sdk],
);
return (
<ThirdwebAuthConfigProvider value={authConfig}>
<QueryClientProvider client={queryClientWithDefault}>
<ThirdwebSDKContext.Provider value={ctxValue}>
{children}
</ThirdwebSDKContext.Provider>
</QueryClientProvider>
</ThirdwebAuthConfigProvider>
);
};
/**
* A basic wrapper around the Thirdweb SDK.
*
* You can use this in order to be able to pass a provider & signer directly to the SDK.
*
* @remarks Utilizing this provider will mean hooks for wallet management are not available, if you need those please use the {@link ThirdwebProvider} instead.
*
* @public
*/
export const ThirdwebSDKProvider: React.FC<
React.PropsWithChildren<ThirdwebSDKProviderProps>
> = ({ signer, children, ...restProps }) => {
return (
<ThirdwebConnectedWalletProvider signer={signer}>
<WrappedThirdwebSDKProvider {...restProps}>
{children}
</WrappedThirdwebSDKProvider>
</ThirdwebConnectedWalletProvider>
);
};
/**
* @internal
*/
function useSDKContext(): TWSDKContext {
const ctx = useContext(ThirdwebSDKContext);
invariant(
ctx._inProvider,
"useSDK must be called from within a ThirdwebProvider, did you forget to wrap your app in a <ThirdwebProvider />?",
);
return ctx;
}
/**
*
* @returns {@link ThirdwebSDK}
* Access the instance of the thirdweb SDK created by the ThirdwebProvider
* to call methods using the connected wallet on the desiredChainId.
* @example
* ```javascript
* const sdk = useSDK();
* ```
*/
export function useSDK(): ThirdwebSDK | undefined {
const { sdk } = useSDKContext();
return sdk;
}
/**
* @internal
*/
export function useDesiredChainId(): number {
const { desiredChainId } = useSDKContext();
return desiredChainId;
}
/**
* @internal
*/
export function useSDKChainId(): SUPPORTED_CHAIN_ID | undefined {
const sdk = useSDK();
return (sdk as any)?._chainId;
}
@@ -1,40 +1,32 @@
import {
GnosisConnectorArguments,
GnosisSafeConnector,
} from "./connectors/gnosis-safe";
import { MagicConnector, MagicConnectorArguments } from "./connectors/magic";
} from "../connectors/gnosis-safe";
import { MagicConnector, MagicConnectorArguments } from "../connectors/magic";
import {
Chain,
SupportedChain,
defaultSupportedChains,
} from "./constants/chain";
import {
ThirdwebAuthConfig,
ThirdwebAuthConfigProvider,
} from "./contexts/thirdweb-auth";
} from "../constants/chain";
import { ThirdwebAuthConfig } from "../contexts/thirdweb-auth";
import {
ThirdwebConfigProvider,
defaultChainRpc,
} from "./contexts/thirdweb-config";
import { useSigner } from "./hooks/useSigner";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
} from "../contexts/thirdweb-config";
import { ThirdwebSDKProvider, ThirdwebSDKProviderProps } from "./base";
import { QueryClient } from "@tanstack/react-query";
import {
ChainOrRpc,
SDKOptions,
SUPPORTED_CHAIN_ID,
SignerOrProvider,
ThirdwebSDK,
getProviderForNetwork,
SDKOptionsOutput,
} from "@thirdweb-dev/sdk";
import type { IStorage } from "@thirdweb-dev/storage";
import { Signer } from "ethers";
import React, { createContext, useEffect, useMemo } from "react";
import invariant from "tiny-invariant";
import type { ThirdwebStorage } from "@thirdweb-dev/storage";
import React, { useMemo } from "react";
import {
WagmiProvider,
ProviderProps as WagmiproviderProps,
useProvider,
useSigner,
} from "wagmi";
import { CoinbaseWalletConnector } from "wagmi/connectors/coinbaseWallet";
import { InjectedConnector } from "wagmi/connectors/injected";
@@ -181,7 +173,7 @@ export interface ThirdwebProviderProps<
/**
* The storage interface to use with the sdk.
*/
storageInterface?: IStorage;
storageInterface?: ThirdwebStorage;
/**
* The react-query client to use. (Defaults to a default client.)
@@ -447,143 +439,14 @@ export const ThirdwebProvider = <
);
};
export interface ThirdwebSDKProviderWagmiWrapper
extends Pick<
ThirdwebProviderProps,
"desiredChainId" | "sdkOptions" | "storageInterface" | "authConfig"
> {
signer?: Signer;
provider: ChainOrRpc | SignerOrProvider;
queryClient?: QueryClient;
}
const ThirdwebSDKProviderWagmiWrapper: React.FC<
React.PropsWithChildren<
Omit<ThirdwebSDKProviderWagmiWrapper, "signer" | "provider">
>
React.PropsWithChildren<Omit<ThirdwebSDKProviderProps, "signer" | "provider">>
> = ({ children, ...props }) => {
const provider = useProvider();
const signer = useSigner();
const [signer] = useSigner();
return (
<ThirdwebSDKProvider signer={signer} provider={provider} {...props}>
<ThirdwebSDKProvider signer={signer.data} provider={provider} {...props}>
{children}
</ThirdwebSDKProvider>
);
};
interface SDKContext {
sdk?: ThirdwebSDK;
_inProvider?: true;
desiredChainId: number;
}
const ThirdwebSDKContext = createContext<SDKContext>({ desiredChainId: -1 });
export interface ThirdwebSDKProviderProps
extends Omit<ThirdwebSDKProviderWagmiWrapper, "queryClient"> {
queryClient?: QueryClient;
}
/**
* A barebones wrapper around the Thirdweb SDK.
*
* You can use this in order to be able to pass a provider & signer directly to the SDK.
*
* @remarks Utilizing this provider will mean hooks for wallet management are not available, if you need those please use the {@link ThirdwebProvider} instead.
*
* @beta
*/
export const ThirdwebSDKProvider: React.FC<
React.PropsWithChildren<ThirdwebSDKProviderProps>
> = ({
sdkOptions,
desiredChainId,
storageInterface,
provider,
signer,
queryClient,
authConfig,
children,
}) => {
const queryClientWithDefault: QueryClient = useMemo(() => {
return queryClient ? queryClient : new QueryClient();
}, [queryClient]);
const sdk = useMemo(() => {
if (!desiredChainId || typeof window === "undefined") {
return undefined;
}
const _sdk = new ThirdwebSDK(provider, sdkOptions, storageInterface);
(_sdk as any)._constructedAt = Date.now();
(_sdk as any)._chainId = desiredChainId;
return _sdk;
}, [provider, sdkOptions, storageInterface, desiredChainId]);
useEffect(() => {
if (signer && sdk && (sdk as any)._chainId === desiredChainId) {
sdk.updateSignerOrProvider(signer);
}
}, [signer, sdk, desiredChainId]);
const ctxValue = useMemo(
() => ({
sdk,
desiredChainId: desiredChainId || -1,
_inProvider: true as const,
}),
[desiredChainId, sdk],
);
return (
<ThirdwebAuthConfigProvider value={authConfig}>
<QueryClientProvider client={queryClientWithDefault}>
<ThirdwebSDKContext.Provider value={ctxValue}>
{children}
</ThirdwebSDKContext.Provider>
</QueryClientProvider>
</ThirdwebAuthConfigProvider>
);
};
/**
* @internal
*/
function useSDKContext(): SDKContext {
const ctx = React.useContext(ThirdwebSDKContext);
invariant(
ctx._inProvider,
"useSDK must be called from within a ThirdwebProvider, did you forget to wrap your app in a <ThirdwebProvider />?",
);
return ctx;
}
/**
*
* @returns {@link ThirdwebSDK}
* Access the instance of the thirdweb SDK created by the ThirdwebProvider
* to call methods using the connected wallet on the desiredChainId.
* @example
* ```javascript
* const sdk = useSDK();
* ```
*/
export function useSDK(): ThirdwebSDK | undefined {
const { sdk } = useSDKContext();
return sdk;
}
/**
* @internal
*/
export function useDesiredChainId(): number {
const { desiredChainId } = useSDKContext();
return desiredChainId;
}
/**
* @internal
*/
export function useActiveChainId(): SUPPORTED_CHAIN_ID | undefined {
const sdk = useSDK();
return (sdk as any)?._chainId;
}
@@ -0,0 +1,6 @@
import { ThirdwebSDKContext } from "../providers/ThirdwebSDKProvider";
import { useContext } from "react";
export function useSDK() {
return useContext(ThirdwebSDKContext);
}
+5
View File
@@ -0,0 +1,5 @@
// Providers
export * from "./providers/ThirdwebSDKProvider";
export * from "./providers/ThirdwebProvider";
// Hooks
export * from "./hooks/useSDK";
@@ -0,0 +1,66 @@
import { ThirdwebSDKProvider } from "./ThirdwebSDKProvider";
import type { WalletAdapter } from "@solana/wallet-adapter-base";
import {
ConnectionProvider,
useConnection,
useWallet,
WalletProvider,
} from "@solana/wallet-adapter-react";
import { PhantomWalletAdapter } from "@solana/wallet-adapter-wallets";
import { getUrlForNetwork, Network } from "@thirdweb-dev/solana";
import { PropsWithChildren } from "react";
interface ThirdwebProviderProps {
endpoint: Network;
wallets?: WalletAdapter[];
autoConnect?: boolean;
}
const DEFAULT_WALLETS = [new PhantomWalletAdapter()];
/**
* Gives access to the ThirdwebSDK instance and other useful hooks to the rest of the app.
* Requires to be wrapped with a ConnectionProvider and a WalletProvider from @solana/wallet-adapter-react.
* @example
* ```tsx
* import { ThirdwebProvider } from "@thirdweb-dev/react/solana";
*
* const App = () => {
* return (
* <ThirdwebProvider endpoint="devnet">
* <YourApp />
* </ThirdwebProvider>
* )};
* ```
* @beta
*/
export const ThirdwebProvider: React.FC<
PropsWithChildren<ThirdwebProviderProps>
> = ({ endpoint, wallets, autoConnect, children }) => {
const clusterUrl = getUrlForNetwork(endpoint);
return (
<ConnectionProvider endpoint={clusterUrl}>
<WalletProvider
wallets={wallets || DEFAULT_WALLETS}
autoConnect={autoConnect || true}
>
<ThirdwebWrapperProvider>{children}</ThirdwebWrapperProvider>
</WalletProvider>
</ConnectionProvider>
);
};
/**
* @internal
*/
export const ThirdwebWrapperProvider: React.FC<PropsWithChildren> = ({
children,
}) => {
const { connection } = useConnection();
const wallet = useWallet();
return (
<ThirdwebSDKProvider connection={connection} wallet={wallet}>
{children}
</ThirdwebSDKProvider>
);
};
@@ -0,0 +1,68 @@
import type { WalletContextState } from "@solana/wallet-adapter-react";
import type { Connection } from "@solana/web3.js";
import { ThirdwebSDK } from "@thirdweb-dev/solana";
import {
createContext,
FC,
PropsWithChildren,
useEffect,
useState,
} from "react";
interface ThirdwebSDKProviderProps {
connection: Connection;
wallet?: WalletContextState;
}
/**
* Gives access to the ThirdwebSDK instance and other useful hooks to the rest of the app.
* Requires to be wrapped with a ConnectionProvider and a WalletProvider from @solana/wallet-adapter-react.
* @example
* ```tsx
* import {
* useConnection,
* useWallet,
* } from "@solana/wallet-adapter-react";
* import { ThirdwebProvider } from "@thirdweb-dev/react/solana";
*
* const ThirdwebApp = () => {
* const { connection } = useConnection();
* const wallet = useWallet();
* return (
* <ThirdwebSDKProvider connection={connection} wallet={wallet}>
* <YourApp />
* </ThirdwebSDKProvider>
* )};
* ```
*/
export const ThirdwebSDKProvider: FC<
PropsWithChildren<ThirdwebSDKProviderProps>
> = ({ children, connection, wallet }) => {
const [sdk, setSDK] = useState<ThirdwebSDK | null>(null);
useEffect(() => {
if (connection) {
setSDK(new ThirdwebSDK(connection));
} else {
setSDK(null);
}
}, [connection]);
useEffect(() => {
if (sdk) {
if (wallet?.publicKey) {
sdk.wallet.connect(wallet);
} else {
sdk.wallet.disconnect();
}
}
}, [sdk, wallet]);
return (
<ThirdwebSDKContext.Provider value={sdk}>
{children}
</ThirdwebSDKContext.Provider>
);
};
export const ThirdwebSDKContext = createContext<ThirdwebSDK | null>(null);
+13 -17
View File
@@ -14,12 +14,12 @@ import type {
Erc20,
ClaimOptions,
} from "@thirdweb-dev/sdk";
import type { EditionImpl } from "@thirdweb-dev/sdk/dist/declarations/src/contracts/prebuilt-implementations/edition";
import type { EditionDropImpl } from "@thirdweb-dev/sdk/dist/declarations/src/contracts/prebuilt-implementations/edition-drop";
import type { NFTCollectionImpl } from "@thirdweb-dev/sdk/dist/declarations/src/contracts/prebuilt-implementations/nft-collection";
import type { NFTDropImpl } from "@thirdweb-dev/sdk/dist/declarations/src/contracts/prebuilt-implementations/nft-drop";
import type { SignatureDropImpl } from "@thirdweb-dev/sdk/dist/declarations/src/contracts/prebuilt-implementations/signature-drop";
import type { TokenDropImpl } from "@thirdweb-dev/sdk/dist/declarations/src/contracts/prebuilt-implementations/token-drop";
import type { Edition } from "@thirdweb-dev/sdk/dist/declarations/src/contracts/prebuilt-implementations/edition";
import type { EditionDrop } from "@thirdweb-dev/sdk/dist/declarations/src/contracts/prebuilt-implementations/edition-drop";
import type { NFTCollection } from "@thirdweb-dev/sdk/dist/declarations/src/contracts/prebuilt-implementations/nft-collection";
import type { NFTDrop } from "@thirdweb-dev/sdk/dist/declarations/src/contracts/prebuilt-implementations/nft-drop";
import type { SignatureDrop } from "@thirdweb-dev/sdk/dist/declarations/src/contracts/prebuilt-implementations/signature-drop";
import type { TokenDrop } from "@thirdweb-dev/sdk/dist/declarations/src/contracts/prebuilt-implementations/token-drop";
import type { SmartContract } from "@thirdweb-dev/sdk/dist/declarations/src/contracts/smart-contract";
import type { BigNumberish } from "ethers";
@@ -72,8 +72,8 @@ export type TokenBurnParams = {
* @beta
*/
export type NFTContract =
| NFTCollectionImpl
| EditionImpl
| NFTCollection
| Edition
| Exclude<DropContract, "TokenDrop">;
/**
@@ -172,10 +172,10 @@ export type BurnNFTParams = { tokenId: BigNumberish; amount?: Amount };
* @beta
*/
export type DropContract =
| NFTDropImpl
| EditionDropImpl
| SignatureDropImpl
| TokenDropImpl
| NFTDrop
| EditionDrop
| SignatureDrop
| TokenDrop
| SmartContract
| null;
@@ -183,11 +183,7 @@ export type DropContract =
* The possible revealable contract types.
* @beta
*/
export type RevealableContract =
| NFTDropImpl
| SignatureDropImpl
| SmartContract
| null;
export type RevealableContract = NFTDrop | SignatureDrop | SmartContract | null;
/**
* The params for the {@link useDelayedRevealLazyMint} hook mutation.
+17 -13
View File
@@ -1,15 +1,19 @@
import { __DEV__ } from "../constants/runtime";
const warnSet = new Set<`${string}:${string}`>();
export const showDeprecationWarning =
// eslint-disable-next-line turbo/no-undeclared-env-vars
process.env.NODE_ENV !== "production"
? (deprecated: string, replacement: string) => {
if (warnSet.has(`${deprecated}:${replacement}`)) {
return;
}
warnSet.add(`${deprecated}:${replacement}`);
console.warn(
`\`${deprecated}\` is deprecated and will be removed in a future version. Please use \`${replacement}\` instead.`,
);
}
: () => undefined;
export const showDeprecationWarning = (
deprecated: string,
replacement: string,
) => {
// deprecation warnings only in dev only in dev
if (__DEV__) {
if (warnSet.has(`${deprecated}:${replacement}`)) {
return;
}
warnSet.add(`${deprecated}:${replacement}`);
console.warn(
`\`${deprecated}\` is deprecated and will be removed in a future major version. Please use \`${replacement}\` instead.`,
);
}
};
+1 -1
View File
@@ -27,7 +27,7 @@ export async function resolveMimeType(url?: string) {
method: "HEAD",
});
if (res.ok && res.headers.has("content-type")) {
return res.headers.get("content-type") ?? undefined;
return res.headers.get("content-type") || undefined;
}
// we failed to resolve the mime type, return null
return undefined;
+13
View File
@@ -0,0 +1,13 @@
{
"$schema": "https://developer.microsoft.com/json-schemas/tsdoc/v0/tsdoc.schema.json",
"extends": ["@microsoft/api-extractor/extends/tsdoc-base.json"],
"tagDefinitions": [
{
"tagName": "@twfeature",
"syntaxKind": "block"
}
],
"supportForTags": {
"@twfeature": true
}
}
+3
View File
@@ -1,6 +1,9 @@
module.exports = {
root: true,
extends: ["thirdweb"],
rules: {
"import/no-cycle": "off",
},
// allow all imports from within tests
overrides: [
{
+3
View File
@@ -0,0 +1,3 @@
docs/
etc/
temp/
+72
View File
@@ -1,5 +1,77 @@
# @thirdweb-dev/sdk
## 3.0.7
### Patch Changes
- [#199](https://github.com/thirdweb-dev/js/pull/199) [`5f5ab01`](https://github.com/thirdweb-dev/js/commit/5f5ab015e1dd3c471d6affe995ef36ec88932b3c) Thanks [@joaquim-verges](https://github.com/joaquim-verges)! - Fix getOwned for signature drop
## 3.0.6
### Patch Changes
- [#195](https://github.com/thirdweb-dev/js/pull/195) [`a80fc97`](https://github.com/thirdweb-dev/js/commit/a80fc97b6a1e72ed46a400b4b602e180947fb870) Thanks [@jnsdls](https://github.com/jnsdls)! - add missing roles for pre-built contracts
- Updated dependencies [[`24f66e3`](https://github.com/thirdweb-dev/js/commit/24f66e38c256f7bd69341b92ba30bd35d14b1caa)]:
- @thirdweb-dev/storage@1.0.3
## 3.0.5
### Patch Changes
- [#167](https://github.com/thirdweb-dev/js/pull/167) [`4169b94`](https://github.com/thirdweb-dev/js/commit/4169b9428f9001b7cad259a4e56fe610316cd191) Thanks [@joaquim-verges](https://github.com/joaquim-verges)! - Syntax changes for react native support
- [#174](https://github.com/thirdweb-dev/js/pull/174) [`3b877ba`](https://github.com/thirdweb-dev/js/commit/3b877ba221acfd85f80b99e1bc382055217f0a39) Thanks [@kumaryash90](https://github.com/kumaryash90)! - detect forwarder address for defender
- [#163](https://github.com/thirdweb-dev/js/pull/163) [`b54f95d`](https://github.com/thirdweb-dev/js/commit/b54f95dc906928ff2f9251748f254a16fe1f2cee) Thanks [@adam-maj](https://github.com/adam-maj)! - Use independent JSON types by package
- [#154](https://github.com/thirdweb-dev/js/pull/154) [`f8ab477`](https://github.com/thirdweb-dev/js/commit/f8ab4779bb2d6d66200e1e8fd558e0ac069a2f54) Thanks [@jnsdls](https://github.com/jnsdls)! - Add fiat checkout to nft-drop, edition-drop and signature-drop
- [#162](https://github.com/thirdweb-dev/js/pull/162) [`772f843`](https://github.com/thirdweb-dev/js/commit/772f8431e3a62d0ded62dae90a43e9a7edd5b1a2) Thanks [@joaquim-verges](https://github.com/joaquim-verges)! - Catch gas estimate errors in gasless tx
- [#188](https://github.com/thirdweb-dev/js/pull/188) [`a9ec190`](https://github.com/thirdweb-dev/js/commit/a9ec190ff99d2714cef2500d20ea0f3f73f07be3) Thanks [@adam-maj](https://github.com/adam-maj)! - Update JSON schema in SDKs
- [#168](https://github.com/thirdweb-dev/js/pull/168) [`208b038`](https://github.com/thirdweb-dev/js/commit/208b0389a50ea48bbb9600fec60fec2f1671d4b9) Thanks [@jnsdls](https://github.com/jnsdls)! - Switch naming of exported prebuilt contract types back from `<name>Impl` to `<name>` for easier use
- [#161](https://github.com/thirdweb-dev/js/pull/161) [`5345479`](https://github.com/thirdweb-dev/js/commit/534547992243bdd3a77e34ec2b2487b5adab366a) Thanks [@joaquim-verges](https://github.com/joaquim-verges)! - Allow forcing direct deploys to deploy implementations from release flow
- Updated dependencies [[`493ebf0`](https://github.com/thirdweb-dev/js/commit/493ebf032e82a66006b3d5b68f8eeff1973fc97a), [`b54f95d`](https://github.com/thirdweb-dev/js/commit/b54f95dc906928ff2f9251748f254a16fe1f2cee), [`cfe8bba`](https://github.com/thirdweb-dev/js/commit/cfe8bbafa464a9e768e6d31fbd9dd9760fdced16), [`f4074dd`](https://github.com/thirdweb-dev/js/commit/f4074ddadc9fb6e18dcc9251a936376c3f4a9144), [`d608cea`](https://github.com/thirdweb-dev/js/commit/d608cea1977dd418b6892c1c9368b06b17a9748b), [`3580182`](https://github.com/thirdweb-dev/js/commit/3580182fa903ed7a661444f0daa160c330e62ec5), [`0ccbca7`](https://github.com/thirdweb-dev/js/commit/0ccbca78dce38926ccfd5c902c06adff2f440f42), [`45a400f`](https://github.com/thirdweb-dev/js/commit/45a400fd9287582bfb5f21ab2cb2d7a4332434c5)]:
- @thirdweb-dev/storage@1.0.2
## 3.0.4
### Patch Changes
- Updated dependencies [[`964add6`](https://github.com/thirdweb-dev/js/commit/964add6f205577298b8f4b9ce7298e5bf09e88e7)]:
- @thirdweb-dev/storage@1.0.1
## 3.0.3
### Patch Changes
- [#143](https://github.com/thirdweb-dev/js/pull/143) [`51dde28`](https://github.com/thirdweb-dev/js/commit/51dde28224209f1b8b26f436c204a5e702281564) Thanks [@joaquim-verges](https://github.com/joaquim-verges)! - Fix using external signers with ThirdwebSDKProvider
- [#133](https://github.com/thirdweb-dev/js/pull/133) [`9d74a43`](https://github.com/thirdweb-dev/js/commit/9d74a43aac21448beba63ba4e2637945965a3634) Thanks [@joaquim-verges](https://github.com/joaquim-verges)! - Make contract events data generic for better DX
- [#135](https://github.com/thirdweb-dev/js/pull/135) [`b234c58`](https://github.com/thirdweb-dev/js/commit/b234c58d44d8322e44b2d2ba87ad4ec7d699e961) Thanks [@jnsdls](https://github.com/jnsdls)! - add a new StaticJsonRpcBatchProvider to stop calling `eth_getChainId` when possible
- Updated dependencies [[`57432d2`](https://github.com/thirdweb-dev/js/commit/57432d21c4c9e880a36c61f4988c60af61ac9d44)]:
- @thirdweb-dev/storage@1.0.0
## 3.0.2
### Patch Changes
- [#131](https://github.com/thirdweb-dev/js/pull/131) [`42c79e9`](https://github.com/thirdweb-dev/js/commit/42c79e93dc958ca46a55d705aeea44ffdbbcc5f6) Thanks [@joaquim-verges](https://github.com/joaquim-verges)! - Fix editing releases from the dashboard
- [#124](https://github.com/thirdweb-dev/js/pull/124) [`fe8751e`](https://github.com/thirdweb-dev/js/commit/fe8751eeae7ad013b890a8092ddbd091ecbd6708) Thanks [@joaquim-verges](https://github.com/joaquim-verges)! - Add feature detection for Ownable
## 3.0.1
### Patch Changes
- [#122](https://github.com/thirdweb-dev/js/pull/122) [`98dd64a`](https://github.com/thirdweb-dev/js/commit/98dd64a375c302a879aab3c628ecfb84b4dd19da) Thanks [@joaquim-verges](https://github.com/joaquim-verges)! - handle legacy claim method signature in extensions
## 3.0.0
### Major Changes
+19 -12
View File
@@ -32,7 +32,8 @@ yarn add @thirdweb-dev/sdk ethers
### 1. Deploy & customize your contracts
- Using your [thirdweb dashboard](https://thirdweb.com/dashboard) (recommended)
- Using the SDK directly (for advanced use cases)
- Using the [SDK directly](https://portal.thirdweb.com/typescript/sdk.contractdeployer)
- Using the [thirdweb CLI](https://portal.thirdweb.com/deploy)
### 2. Reading data from your contracts
@@ -44,16 +45,18 @@ This will allow you to query data from any contract with no additional setup.
import { ThirdwebSDK } from "@thirdweb-dev/sdk";
// instantiate the SDK in read-only mode (our example is running on `polygon` here)
// all major chains and testnets are supported (e.g. `mainnet`, `rinkeby`, `goerli`, 'polygon', 'mumbai', etc.)
// all major chains and testnets are supported (e.g. `mainnet`, 'optimism`, 'arbitrum', 'polygon', `goerli`, 'mumbai', etc.)
const sdk = new ThirdwebSDK("polygon");
// access your deployed contracts
const nftDrop = sdk.getNFTDrop("0x...");
const marketplace = sdk.getMarketplace("0x...");
const contract = await sdk.getContract("0x...");
// Read from your contracts
const claimedNFTs = await nftDrop.getAllClaimed();
const listings = await marketplace.getActiveListings();
// Read data using direct calls to your contract
const myData = await contract.call("myFunction");
// Or Using the extensions API matching to your contract extensions
const allNFTs = await contract.erc721.getAll();
const tokenSupply = await contract.erc20.totalSupply();
```
You can execute this code as a node script by executing:
@@ -62,6 +65,8 @@ You can execute this code as a node script by executing:
node my_script.js
```
Note that you can also access any deployed contract using its ABI, using `sdk.getContractFromAbi(address, abi)` and get the same functionality. For contracts deployed via thirdweb, we handle the ABI for you.
### 3. Executing transactions on your contracts
In order to execute transactions on your contract, the SDK needs to know which wallet is executing those transactions.
@@ -83,18 +88,20 @@ const privateKey = "<your-private-key-here>";
// instantiate the SDK based on your private key, with the desired chain to connect to
const sdk = ThirdwebSDK.fromPrivateKey(privateKey, "polygon");
// deploy contracts
// deploy existing contracts, or your own using the thirdweb CLI
const deployedAddress = sdk.deployer.deployNFTCollection({
name: "My NFT Collection",
primary_sale_recipient: "0x...",
});
// access your deployed contracts
const nftCollection = sdk.getNFTCollection(deployedAddress);
const contract = await sdk.getContract(deployedAddress);
// Execute transactions on your contracts from the connected wallet
const walletAddress = "0x...";
await nftCollection.mintTo(walletAddress, {
// Execute any of your functions on your contracts from the connected wallet
await contract.call("myFunction", arg1, arg2);
// Or execute transactions using the extensions API
await contract.erc721.mint({
name: "Cool NFT",
description: "Minted NFT from code!",
image: fs.readFileSync("path/to/image.png"), // This can be an image url or file
+4 -3
View File
@@ -1,6 +1,6 @@
{
"name": "@thirdweb-dev/sdk",
"version": "3.0.0",
"version": "3.0.7",
"description": "The main thirdweb SDK.",
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/sdk",
"license": "Apache-2.0",
@@ -20,7 +20,8 @@
"build": "tsc && preconstruct build",
"test:all": "SWC_NODE_PROJECT=./tsconfig.test.json mocha --timeout 30000 --parallel './test/**/*.test.ts'",
"test": "make test",
"test:single": "SWC_NODE_PROJECT=./tsconfig.test.json mocha --timeout 30000 --"
"test:single": "SWC_NODE_PROJECT=./tsconfig.test.json mocha --timeout 30000",
"push": "yalc push"
},
"devDependencies": {
"@esbuild-plugins/node-modules-polyfill": "^0.1.4",
@@ -73,7 +74,7 @@
"merkletreejs": "^0.2.24",
"multihashes": "^4.0.3",
"tiny-invariant": "^1.2.0",
"uuid": "^8.3.2",
"uuid": "^9.0.0",
"zod": "^3.11.6"
},
"resolutions": {
+2 -29
View File
@@ -46,35 +46,8 @@ function languageNameToKey(languageName) {
}
}
const additionalClassesToParse = [
"ThirdwebSDK",
"ContractDeployer",
"MarketplaceDirect",
"MarketplaceAuction",
"ContractMetadata",
"ContractEvents",
"DelayedReveal",
"ContractRoles",
"RemoteStorage",
"GasCostEstimator",
"ContractInterceptor",
"ContractRoles",
"DropClaimConditions",
"ContractPrimarySale",
"ContractRoyalty",
"ContractPlatformFee",
"WalletAuthenticator",
"UserWallet",
];
const modules = json.members[0].members.filter(
(m) =>
(m.kind === "Class" &&
m.members
.filter((cMember) => cMember.kind === "Property")
.findIndex((property) => property.name === "contractType") > -1) ||
additionalClassesToParse.includes(m.name),
);
// just include all classes
const modules = json.members[0].members.filter((m) => m.kind === "Class");
const bases = ["StandardErc20", "StandardErc721", "StandardErc1155"];
const baseClasses = json.members[0].members.filter(
+7 -7
View File
@@ -25,7 +25,7 @@ import {
} from "./currency";
import { createSnapshot } from "./snapshots";
import { IDropClaimCondition } from "@thirdweb-dev/contracts-js/dist/declarations/src/DropERC20";
import { IStorage } from "@thirdweb-dev/storage";
import { ThirdwebStorage } from "@thirdweb-dev/storage";
import {
BigNumber,
BigNumberish,
@@ -47,7 +47,7 @@ export async function prepareClaim(
merkleMetadataFetcher: () => Promise<Record<string, string>>,
tokenDecimals: number,
contractWrapper: ContractWrapper<any>,
storage: IStorage,
storage: ThirdwebStorage,
checkERC20Allowance: boolean,
): Promise<ClaimVerification> {
const addressToClaim = await contractWrapper.getSignerAddress();
@@ -131,7 +131,7 @@ type Snapshot =
export async function fetchSnapshot(
merkleRoot: string,
merkleMetadata: Record<string, string> | undefined,
storage: IStorage,
storage: ThirdwebStorage,
): Promise<Snapshot> {
if (!merkleMetadata) {
return undefined;
@@ -139,7 +139,7 @@ export async function fetchSnapshot(
const snapshotUri = merkleMetadata[merkleRoot];
let snapshot: Snapshot = undefined;
if (snapshotUri) {
const raw = await storage.get(snapshotUri);
const raw = await storage.downloadJSON(snapshotUri);
const snapshotData = SnapshotSchema.parse(raw);
if (merkleRoot === snapshotData.merkleRoot) {
snapshot = snapshotData.claims;
@@ -211,7 +211,7 @@ export async function getClaimerProofs(
merkleRoot: string,
tokenDecimals: number,
merkleMetadata: Record<string, string>,
storage: IStorage,
storage: ThirdwebStorage,
): Promise<{ maxClaimable: BigNumber; proof: string[] }> {
const claims: Snapshot = await fetchSnapshot(
merkleRoot,
@@ -252,7 +252,7 @@ export async function processClaimConditionInputs(
claimConditionInputs: ClaimConditionInput[],
tokenDecimals: number,
provider: providers.Provider,
storage: IStorage,
storage: ThirdwebStorage,
) {
const snapshotInfos: SnapshotInfo[] = [];
const inputsWithSnapshots = await Promise.all(
@@ -355,7 +355,7 @@ export async function transformResultToClaimCondition(
tokenDecimals: number,
provider: providers.Provider,
merkleMetadata: Record<string, string> | undefined,
storage: IStorage,
storage: ThirdwebStorage,
): Promise<ClaimCondition> {
const cv = await fetchCurrencyValue(provider, pm.currency, pm.pricePerToken);
+25 -23
View File
@@ -21,7 +21,7 @@ import {
PublishedMetadata,
} from "../schema/contracts/custom";
import { ExtensionNotImplementedError } from "./error";
import { IStorage } from "@thirdweb-dev/storage";
import { ThirdwebStorage } from "@thirdweb-dev/storage";
import { BaseContract, ethers } from "ethers";
import { z } from "zod";
@@ -57,7 +57,7 @@ function matchesAbiInterface(
*/
export async function extractConstructorParams(
predeployMetadataUri: string,
storage: IStorage,
storage: ThirdwebStorage,
) {
const meta = await fetchPreDeployMetadata(predeployMetadataUri, storage);
return extractConstructorParamsFromAbi(meta.abi);
@@ -70,7 +70,7 @@ export async function extractConstructorParams(
*/
export async function extractFunctions(
predeployMetadataUri: string,
storage: IStorage,
storage: ThirdwebStorage,
): Promise<AbiFunction[]> {
const metadata = await fetchPreDeployMetadata(predeployMetadataUri, storage);
return extractFunctionsFromAbi(metadata.abi, metadata.metadata);
@@ -112,7 +112,7 @@ export function extractConstructorParamsFromAbi(
) {
for (const input of abi) {
if (input.type === "constructor") {
return input.inputs ?? [];
return input.inputs || [];
}
}
return [];
@@ -131,7 +131,7 @@ export function extractFunctionParamsFromAbi(
) {
for (const input of abi) {
if (input.type === "function" && input.name === functionName) {
return input.inputs ?? [];
return input.inputs || [];
}
}
return [];
@@ -159,11 +159,11 @@ export function extractFunctionsFromAbi(
const promise = out ? `: Promise<${out}>` : `: Promise<TransactionResult>`;
const signature = `contract.call("${f.name}"${fargs})${promise}`;
parsed.push({
inputs: f.inputs ?? [],
outputs: f.outputs ?? [],
name: f.name ?? "unknown",
inputs: f.inputs || [],
outputs: f.outputs || [],
name: f.name || "unknown",
signature,
stateMutability: f.stateMutability ?? "",
stateMutability: f.stateMutability || "",
comment: doc,
});
}
@@ -184,9 +184,9 @@ export function extractEventsFromAbi(
for (const e of events) {
const doc = extractCommentFromMetadata(e.name, metadata, "events");
parsed.push({
inputs: e.inputs ?? [],
outputs: e.outputs ?? [],
name: e.name ?? "unknown",
inputs: e.inputs || [],
outputs: e.outputs || [],
name: e.name || "unknown",
comment: doc,
});
}
@@ -328,7 +328,7 @@ function isHexStrict(hex: string | number) {
export async function fetchContractMetadataFromAddress(
address: string,
provider: ethers.providers.Provider,
storage: IStorage,
storage: ThirdwebStorage,
) {
const compilerMetadataUri = await resolveContractUriFromAddress(
address,
@@ -347,9 +347,9 @@ export async function fetchContractMetadataFromAddress(
*/
export async function fetchContractMetadata(
compilerMetadataUri: string,
storage: IStorage,
storage: ThirdwebStorage,
): Promise<PublishedMetadata> {
const metadata = await storage.get(compilerMetadataUri);
const metadata = await storage.downloadJSON(compilerMetadataUri);
const abi = AbiSchema.parse(metadata.output.abi);
const compilationTarget = metadata.settings.compilationTarget;
const targets = Object.keys(compilationTarget);
@@ -381,7 +381,7 @@ export async function fetchContractMetadata(
*/
export async function fetchSourceFilesFromMetadata(
publishedMetadata: PublishedMetadata,
storage: IStorage,
storage: ThirdwebStorage,
): Promise<ContractSource[]> {
return await Promise.all(
Object.entries(publishedMetadata.metadata.sources).map(
@@ -395,7 +395,7 @@ export async function fetchSourceFilesFromMetadata(
setTimeout(() => rej("timeout"), 5000),
);
const source = await Promise.race([
storage.getRaw(`ipfs://${ipfsHash}`),
(await storage.download(`ipfs://${ipfsHash}`)).text(),
timeout,
]);
return {
@@ -420,10 +420,10 @@ export async function fetchSourceFilesFromMetadata(
*/
export async function fetchRawPredeployMetadata(
publishMetadataUri: string,
storage: IStorage,
storage: ThirdwebStorage,
) {
return PreDeployMetadata.parse(
JSON.parse(await storage.getRaw(publishMetadataUri)),
JSON.parse(await (await storage.download(publishMetadataUri)).text()),
);
}
@@ -435,10 +435,12 @@ export async function fetchRawPredeployMetadata(
*/
export async function fetchPreDeployMetadata(
publishMetadataUri: string,
storage: IStorage,
storage: ThirdwebStorage,
): Promise<PreDeployMetadataFetched> {
const rawMeta = await fetchRawPredeployMetadata(publishMetadataUri, storage);
const deployBytecode = await storage.getRaw(rawMeta.bytecodeUri);
const deployBytecode = await (
await storage.download(rawMeta.bytecodeUri)
).text();
const parsedMeta = await fetchContractMetadata(rawMeta.metadataUri, storage);
return PreDeployMetadataFetchedSchema.parse({
...rawMeta,
@@ -455,9 +457,9 @@ export async function fetchPreDeployMetadata(
*/
export async function fetchExtendedReleaseMetadata(
publishMetadataUri: string,
storage: IStorage,
storage: ThirdwebStorage,
): Promise<FullPublishMetadata> {
const meta = await storage.getRaw(publishMetadataUri);
const meta = await (await storage.download(publishMetadataUri)).text();
return FullPublishMetadataSchemaOutput.parse(JSON.parse(meta));
}
+34 -17
View File
@@ -9,7 +9,6 @@ import {
NFTMetadataInput,
NFTMetadataOrUri,
} from "../schema/tokens/common";
import { UploadProgressEvent } from "../types/index";
import { NotFoundError } from "./error";
import type {
IERC1155Metadata,
@@ -19,7 +18,10 @@ import type {
import ERC165MetadataAbi from "@thirdweb-dev/contracts-js/dist/abis/IERC165.json";
import ERC721MetadataAbi from "@thirdweb-dev/contracts-js/dist/abis/IERC721Metadata.json";
import ERC1155MetadataAbi from "@thirdweb-dev/contracts-js/dist/abis/IERC1155Metadata.json";
import type { IStorage } from "@thirdweb-dev/storage";
import type {
ThirdwebStorage,
UploadProgressEvent,
} from "@thirdweb-dev/storage";
import { BigNumber, BigNumberish, Contract, ethers, providers } from "ethers";
const FALLBACK_METADATA = {
@@ -37,7 +39,7 @@ const FALLBACK_METADATA = {
export async function fetchTokenMetadata(
tokenId: BigNumberish,
tokenUri: string,
storage: IStorage,
storage: ThirdwebStorage,
): Promise<NFTMetadata> {
const parsedUri = tokenUri.replace(
"{id}",
@@ -45,15 +47,15 @@ export async function fetchTokenMetadata(
);
let jsonMetadata;
try {
jsonMetadata = await storage.get(parsedUri);
jsonMetadata = await storage.downloadJSON(parsedUri);
} catch (err) {
const unparsedTokenIdUri = tokenUri.replace(
"{id}",
BigNumber.from(tokenId).toString(),
);
try {
jsonMetadata = await storage.get(unparsedTokenIdUri);
} catch (e) {
jsonMetadata = await storage.downloadJSON(unparsedTokenIdUri);
} catch (e: any) {
console.warn(
`failed to get token metadata: ${JSON.stringify({
tokenId: tokenId.toString(),
@@ -83,7 +85,7 @@ export async function fetchTokenMetadataForContract(
contractAddress: string,
provider: providers.Provider,
tokenId: BigNumberish,
storage: IStorage,
storage: ThirdwebStorage,
) {
let uri: string | undefined;
const erc165 = new Contract(
@@ -123,12 +125,12 @@ export async function fetchTokenMetadataForContract(
*/
export async function uploadOrExtractURI(
metadata: NFTMetadataOrUri,
storage: IStorage,
storage: ThirdwebStorage,
): Promise<string> {
if (typeof metadata === "string") {
return metadata;
} else {
return await storage.uploadMetadata(CommonNFTInput.parse(metadata));
return await storage.upload(CommonNFTInput.parse(metadata));
}
}
@@ -143,10 +145,8 @@ export async function uploadOrExtractURI(
*/
export async function uploadOrExtractURIs(
metadatas: NFTMetadataOrUri[],
storage: IStorage,
storage: ThirdwebStorage,
startNumber?: number,
contractAddress?: string,
signerAddress?: string,
options?: {
onProgress: (event: UploadProgressEvent) => void;
},
@@ -154,12 +154,14 @@ export async function uploadOrExtractURIs(
if (isUriList(metadatas)) {
return metadatas;
} else if (isMetadataList(metadatas)) {
const { uris } = await storage.uploadMetadataBatch(
const uris = await storage.uploadBatch(
metadatas.map((m) => CommonNFTInput.parse(m)),
startNumber,
contractAddress,
signerAddress,
options,
{
rewriteFileNames: {
fileStartNumber: startNumber || 0,
},
onProgress: options?.onProgress,
},
);
return uris;
} else {
@@ -169,6 +171,21 @@ export async function uploadOrExtractURIs(
}
}
export function getBaseUriFromBatch(uris: string[]): string {
const baseUri = uris[0].substring(0, uris[0].lastIndexOf("/"));
for (let i = 0; i < uris.length; i++) {
const uri = uris[i].substring(0, uris[i].lastIndexOf("/"));
if (baseUri !== uri) {
throw new Error(
`Can only create batches with the same base URI for every entry in the batch. Expected '${baseUri}' but got '${uri}'`,
);
}
}
// Ensure that baseUri ends with trailing slash
return baseUri.replace(/\/$/, "") + "/";
}
function isUriList(metadatas: NFTMetadataOrUri[]): metadatas is string[] {
return metadatas.find((m) => typeof m !== "string") === undefined;
}
+4 -4
View File
@@ -130,8 +130,8 @@ export async function signDAIPermit(
verifyingContract: currencyAddress,
});
nonce = nonce ?? (await getSignerNonce(signer, currencyAddress)).toString();
deadline = deadline ?? ethers.constants.MaxUint256;
nonce = nonce || (await getSignerNonce(signer, currencyAddress)).toString();
deadline = deadline || ethers.constants.MaxUint256;
const message = {
owner,
@@ -185,8 +185,8 @@ export async function signEIP2612Permit(
verifyingContract: currencyAddress,
});
nonce = nonce ?? (await getSignerNonce(signer, currencyAddress)).toString();
deadline = deadline ?? ethers.constants.MaxUint256;
nonce = nonce || (await getSignerNonce(signer, currencyAddress)).toString();
deadline = deadline || ethers.constants.MaxUint256;
const message = {
owner,
+3 -3
View File
@@ -7,7 +7,7 @@ import {
SnapshotInput,
} from "../types/claim-conditions/claim-conditions";
import { DuplicateLeafsError } from "./error";
import { IStorage } from "@thirdweb-dev/storage";
import { ThirdwebStorage } from "@thirdweb-dev/storage";
import { BigNumber, BigNumberish, utils } from "ethers";
/**
@@ -21,7 +21,7 @@ import { BigNumber, BigNumberish, utils } from "ethers";
export async function createSnapshot(
snapshotInput: SnapshotInput,
tokenDecimals: number,
storage: IStorage,
storage: ThirdwebStorage,
): Promise<SnapshotInfo> {
const input = SnapshotInputSchema.parse(snapshotInput);
const addresses = input.map((i) => i.address);
@@ -51,7 +51,7 @@ export async function createSnapshot(
}),
});
const uri = await storage.uploadMetadata(snapshot);
const uri = await storage.upload(snapshot);
return {
merkleRoot: tree.getHexRoot(),
snapshotUri: uri,
+19 -1
View File
@@ -18,6 +18,7 @@ export const CONTRACT_ADDRESSES: Record<
SUPPORTED_CHAIN_ID,
{
openzeppelinForwarder: string;
openzeppelinForwarderEOA: string;
biconomyForwarder: string;
twFactory: string;
twRegistry: string;
@@ -26,6 +27,7 @@ export const CONTRACT_ADDRESSES: Record<
> = {
[ChainId.Mainnet]: {
openzeppelinForwarder: OZ_DEFENDER_FORWARDER_ADDRESS,
openzeppelinForwarderEOA: "0x76ce2CB1Ae48Fa067f4fb8c5f803111AE0B24BEA",
biconomyForwarder: "0x84a0856b038eaAd1cC7E297cF34A7e72685A8693",
twFactory: TWFactory_address,
twRegistry: TWRegistry_address,
@@ -33,6 +35,7 @@ export const CONTRACT_ADDRESSES: Record<
},
[ChainId.Rinkeby]: {
openzeppelinForwarder: OZ_DEFENDER_FORWARDER_ADDRESS,
openzeppelinForwarderEOA: "0x0bBA31EAf82C649C0B9579F5F44374C74F4605Ea",
biconomyForwarder: "0xFD4973FeB2031D4409fB57afEE5dF2051b171104",
twFactory: TWFactory_address,
twRegistry: TWRegistry_address,
@@ -40,6 +43,7 @@ export const CONTRACT_ADDRESSES: Record<
},
[ChainId.Goerli]: {
openzeppelinForwarder: "0x5001A14CA6163143316a7C614e30e6041033Ac20",
openzeppelinForwarderEOA: "0xe73c50cB9c5B378627ff625BB6e6725A4A5D65d2",
biconomyForwarder: constants.AddressZero,
twFactory: TWFactory_address,
twRegistry: TWRegistry_address,
@@ -47,6 +51,7 @@ export const CONTRACT_ADDRESSES: Record<
},
[ChainId.Polygon]: {
openzeppelinForwarder: OZ_DEFENDER_FORWARDER_ADDRESS,
openzeppelinForwarderEOA: "0x4f247c69184ad61036EC2Bb3213b69F10FbEDe1F",
biconomyForwarder: "0x86C80a8aa58e0A4fa09A69624c31Ab2a6CAD56b8",
twFactory: TWFactory_address,
twRegistry: TWRegistry_address,
@@ -54,6 +59,7 @@ export const CONTRACT_ADDRESSES: Record<
},
[ChainId.Mumbai]: {
openzeppelinForwarder: OZ_DEFENDER_FORWARDER_ADDRESS,
openzeppelinForwarderEOA: "0xb1A2883fc4d287d9cB8Dbb96cFF60C76BEf2D250",
biconomyForwarder: "0x9399BB24DBB5C4b782C70c2969F58716Ebbd6a3b",
twFactory: TWFactory_address,
twRegistry: TWRegistry_address,
@@ -61,6 +67,7 @@ export const CONTRACT_ADDRESSES: Record<
},
[ChainId.Avalanche]: {
openzeppelinForwarder: OZ_DEFENDER_FORWARDER_ADDRESS,
openzeppelinForwarderEOA: "0xb1A2883fc4d287d9cB8Dbb96cFF60C76BEf2D250",
biconomyForwarder: "0x64CD353384109423a966dCd3Aa30D884C9b2E057",
twFactory: TWFactory_address,
twRegistry: TWRegistry_address,
@@ -68,6 +75,7 @@ export const CONTRACT_ADDRESSES: Record<
},
[ChainId.AvalancheFujiTestnet]: {
openzeppelinForwarder: OZ_DEFENDER_FORWARDER_ADDRESS,
openzeppelinForwarderEOA: "0xe73c50cB9c5B378627ff625BB6e6725A4A5D65d2",
biconomyForwarder: "0x6271Ca63D30507f2Dcbf99B52787032506D75BBF",
twFactory: TWFactory_address,
twRegistry: TWRegistry_address,
@@ -75,6 +83,7 @@ export const CONTRACT_ADDRESSES: Record<
},
[ChainId.Fantom]: {
openzeppelinForwarder: OZ_DEFENDER_FORWARDER_ADDRESS,
openzeppelinForwarderEOA: "0xb1A2883fc4d287d9cB8Dbb96cFF60C76BEf2D250",
biconomyForwarder: constants.AddressZero,
twFactory: "0x97EA0Fcc552D5A8Fb5e9101316AAd0D62Ea0876B",
twRegistry: TWRegistry_address,
@@ -82,6 +91,7 @@ export const CONTRACT_ADDRESSES: Record<
},
[ChainId.FantomTestnet]: {
openzeppelinForwarder: OZ_DEFENDER_FORWARDER_ADDRESS,
openzeppelinForwarderEOA: "0x42D3048b595B6e1c28a588d70366CcC2AA4dB47b",
biconomyForwarder: constants.AddressZero,
twFactory: TWFactory_address,
twRegistry: TWRegistry_address,
@@ -89,6 +99,7 @@ export const CONTRACT_ADDRESSES: Record<
},
[ChainId.Arbitrum]: {
openzeppelinForwarder: OZ_DEFENDER_FORWARDER_ADDRESS,
openzeppelinForwarderEOA: "0x4f247c69184ad61036EC2Bb3213b69F10FbEDe1F",
biconomyForwarder: constants.AddressZero,
twFactory: "0xd24b3de085CFd8c54b94feAD08a7962D343E6DE0",
twRegistry: "0x7c487845f98938Bb955B1D5AD069d9a30e4131fd",
@@ -96,6 +107,7 @@ export const CONTRACT_ADDRESSES: Record<
},
[ChainId.ArbitrumRinkeby]: {
openzeppelinForwarder: OZ_DEFENDER_FORWARDER_ADDRESS,
openzeppelinForwarderEOA: "0xE1eE43D23f247b6A9aF81fcE2766E76709482728",
biconomyForwarder: constants.AddressZero,
twFactory: "0xb0435b47ad26115A39c59735b814f3769F07C2c1",
twRegistry: "0xcF4c511551aE4dab1F997866FC3900cd2aaeC40D",
@@ -103,6 +115,7 @@ export const CONTRACT_ADDRESSES: Record<
},
[ChainId.ArbitrumGoerli]: {
openzeppelinForwarder: "0x8cbc8B5d71702032904750A66AEfE8B603eBC538",
openzeppelinForwarderEOA: "0x119704314Ef304EaAAE4b3c7C9ABd59272A28310",
biconomyForwarder: constants.AddressZero,
twFactory: "0xd24b3de085CFd8c54b94feAD08a7962D343E6DE0",
twRegistry: "0x7c487845f98938Bb955B1D5AD069d9a30e4131fd",
@@ -110,6 +123,7 @@ export const CONTRACT_ADDRESSES: Record<
},
[ChainId.Optimism]: {
openzeppelinForwarder: OZ_DEFENDER_FORWARDER_ADDRESS,
openzeppelinForwarderEOA: "0x7e80648EB2071E26937F9D42A513ccf4815fc702",
biconomyForwarder: constants.AddressZero,
twFactory: "0xd24b3de085CFd8c54b94feAD08a7962D343E6DE0",
twRegistry: "0x7c487845f98938Bb955B1D5AD069d9a30e4131fd",
@@ -117,6 +131,7 @@ export const CONTRACT_ADDRESSES: Record<
},
[ChainId.OptimismKovan]: {
openzeppelinForwarder: OZ_DEFENDER_FORWARDER_ADDRESS,
openzeppelinForwarderEOA: "0xE8dd2Ff0212F86d3197b4AfDC6dAC6ac47eb10aC",
biconomyForwarder: constants.AddressZero,
twFactory: "0xd24b3de085CFd8c54b94feAD08a7962D343E6DE0",
twRegistry: "0x7c487845f98938Bb955B1D5AD069d9a30e4131fd",
@@ -124,6 +139,7 @@ export const CONTRACT_ADDRESSES: Record<
},
[ChainId.OptimismGoerli]: {
openzeppelinForwarder: "0x8cbc8B5d71702032904750A66AEfE8B603eBC538",
openzeppelinForwarderEOA: "0x119704314Ef304EaAAE4b3c7C9ABd59272A28310",
biconomyForwarder: constants.AddressZero,
twFactory: "0xd24b3de085CFd8c54b94feAD08a7962D343E6DE0",
twRegistry: "0x7c487845f98938Bb955B1D5AD069d9a30e4131fd",
@@ -131,6 +147,7 @@ export const CONTRACT_ADDRESSES: Record<
},
[ChainId.BinanceSmartChainMainnet]: {
openzeppelinForwarder: "0x8cbc8B5d71702032904750A66AEfE8B603eBC538",
openzeppelinForwarderEOA: "0xE8dd2Ff0212F86d3197b4AfDC6dAC6ac47eb10aC",
biconomyForwarder: constants.AddressZero,
twBYOCRegistry: constants.AddressZero,
twFactory: "0xd24b3de085CFd8c54b94feAD08a7962D343E6DE0",
@@ -138,6 +155,7 @@ export const CONTRACT_ADDRESSES: Record<
},
[ChainId.BinanceSmartChainTestnet]: {
openzeppelinForwarder: "0x8cbc8B5d71702032904750A66AEfE8B603eBC538",
openzeppelinForwarderEOA: "0x7e80648EB2071E26937F9D42A513ccf4815fc702",
biconomyForwarder: constants.AddressZero,
twBYOCRegistry: constants.AddressZero,
twFactory: "0xd24b3de085CFd8c54b94feAD08a7962D343E6DE0",
@@ -179,4 +197,4 @@ export function getContractPublisherAddress() {
} else {
return ContractPublisher_address;
}
}
}
@@ -33,6 +33,7 @@ import {
} from "./erc1155-features";
import {
FEATURE_METADATA,
FEATURE_OWNER,
FEATURE_PERMISSIONS,
FEATURE_PLATFORM_FEE,
FEATURE_PRIMARY_SALE,
@@ -74,7 +75,8 @@ export type Feature =
| typeof FEATURE_PLATFORM_FEE
| typeof FEATURE_PRIMARY_SALE
| typeof FEATURE_PERMISSIONS
| typeof FEATURE_METADATA;
| typeof FEATURE_METADATA
| typeof FEATURE_OWNER;
/**
* @internal
@@ -100,4 +102,5 @@ export const SUPPORTED_FEATURES: Record<string, Feature> = {
[FEATURE_PRIMARY_SALE.name]: FEATURE_PRIMARY_SALE,
[FEATURE_PERMISSIONS.name]: FEATURE_PERMISSIONS,
[FEATURE_METADATA.name]: FEATURE_METADATA,
[FEATURE_OWNER.name]: FEATURE_OWNER,
};
@@ -3,6 +3,7 @@ import IPermissionsAbi from "@thirdweb-dev/contracts-js/dist/abis/IPermissions.j
import IThirdwebPlatformFeeAbi from "@thirdweb-dev/contracts-js/dist/abis/IPlatformFee.json";
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";
export const FEATURE_ROYALTY = {
name: "Royalty",
@@ -58,3 +59,14 @@ export const FEATURE_METADATA = {
abis: [IContractMetadataAbi],
features: {},
} as const;
export const FEATURE_OWNER = {
name: "Ownable",
namespace: "owner",
docLinks: {
sdk: "sdk.owner",
contracts: "Ownable",
},
abis: [IOwnableAbi],
features: {},
} as const;
+7 -1
View File
@@ -1,4 +1,5 @@
import { SignerOrProvider } from "../core/types";
import { StaticJsonRpcBatchProvider } from "../lib/static-batch-rpc";
import { ethers, providers } from "ethers";
/**
@@ -134,7 +135,12 @@ export function getReadOnlyProvider(network: string, chainId?: number) {
if (match) {
switch (match[1]) {
case "http":
return new providers.JsonRpcBatchProvider(network, chainId);
return chainId
? // if we know the chainId we should use the StaticJsonRpcBatchProvider
new StaticJsonRpcBatchProvider(network, chainId)
: // otherwise fall back to the built in json rpc batch provider
new providers.JsonRpcBatchProvider(network, chainId);
case "ws":
return new providers.WebSocketProvider(network, chainId);
default:
+52 -76
View File
@@ -15,16 +15,16 @@ import {
import { CustomContractSchema } from "../schema/contracts/custom";
import { DropErc20ContractSchema } from "../schema/contracts/drop-erc20";
import { MultiwrapContractSchema } from "../schema/contracts/multiwrap";
import type { IStorage } from "@thirdweb-dev/storage";
import type { ThirdwebStorage } from "@thirdweb-dev/storage";
type InitalizeParams = [
network: NetworkOrSignerOrProvider,
address: string,
storage: IStorage,
storage: ThirdwebStorage,
options?: SDKOptions,
];
export const EditionDrop = {
export const EditionDropInitializer = {
name: "DropERC1155" as const,
contractType: "edition-drop" as const,
schema: DropErc1155ContractSchema,
@@ -33,24 +33,18 @@ export const EditionDrop = {
...[network, address, storage, options]: InitalizeParams
) => {
const [abi, contract] = await Promise.all([
EditionDrop.getAbi(),
EditionDropInitializer.getAbi(),
import("./prebuilt-implementations/edition-drop"),
]);
return new contract.EditionDropImpl(
network,
address,
storage,
options,
abi,
);
return new contract.EditionDrop(network, address, storage, options, abi);
},
getAbi: async () =>
(await import("@thirdweb-dev/contracts-js/dist/abis/DropERC1155.json"))
.default,
};
export const Edition = {
export const EditionInitializer = {
name: "TokenERC1155" as const,
contractType: "edition" as const,
schema: TokenErc1155ContractSchema,
@@ -59,18 +53,18 @@ export const Edition = {
...[network, address, storage, options]: InitalizeParams
) => {
const [abi, contract] = await Promise.all([
Edition.getAbi(),
EditionInitializer.getAbi(),
import("./prebuilt-implementations/edition"),
]);
return new contract.EditionImpl(network, address, storage, options, abi);
return new contract.Edition(network, address, storage, options, abi);
},
getAbi: async () =>
(await import("@thirdweb-dev/contracts-js/dist/abis/TokenERC1155.json"))
.default,
};
export const Marketplace = {
export const MarketplaceInitializer = {
name: "Marketplace" as const,
contractType: "marketplace" as const,
schema: MarketplaceContractSchema,
@@ -79,44 +73,38 @@ export const Marketplace = {
...[network, address, storage, options]: InitalizeParams
) => {
const [abi, contract] = await Promise.all([
Marketplace.getAbi(),
MarketplaceInitializer.getAbi(),
import("./prebuilt-implementations/marketplace"),
]);
return new contract.MarketplaceImpl(
network,
address,
storage,
options,
abi,
);
return new contract.Marketplace(network, address, storage, options, abi);
},
getAbi: async () =>
(await import("@thirdweb-dev/contracts-js/dist/abis/Marketplace.json"))
.default,
};
export const Multiwrap = {
export const MultiwrapInitializer = {
name: "Multiwrap" as const,
contractType: "multiwrap" as const,
schema: MultiwrapContractSchema,
roles: ["transfer", "minter", "unwrap", "asset"] as const,
roles: ["admin", "transfer", "minter", "unwrap", "asset"] as const,
initialize: async (
...[network, address, storage, options]: InitalizeParams
) => {
const [abi, contract] = await Promise.all([
Multiwrap.getAbi(),
MultiwrapInitializer.getAbi(),
import("./prebuilt-implementations/multiwrap"),
]);
return new contract.MultiwrapImpl(network, address, storage, options, abi);
return new contract.Multiwrap(network, address, storage, options, abi);
},
getAbi: async () =>
(await import("@thirdweb-dev/contracts-js/dist/abis/Multiwrap.json"))
.default,
};
export const NFTCollection = {
export const NFTCollectionInitializer = {
name: "TokenERC721" as const,
contractType: "nft-collection" as const,
schema: TokenErc721ContractSchema,
@@ -126,24 +114,18 @@ export const NFTCollection = {
...[network, address, storage, options]: InitalizeParams
) => {
const [abi, contract] = await Promise.all([
NFTCollection.getAbi(),
NFTCollectionInitializer.getAbi(),
import("./prebuilt-implementations/nft-collection"),
]);
return new contract.NFTCollectionImpl(
network,
address,
storage,
options,
abi,
);
return new contract.NFTCollection(network, address, storage, options, abi);
},
getAbi: async () =>
(await import("@thirdweb-dev/contracts-js/dist/abis/TokenERC721.json"))
.default,
};
export const NFTDrop = {
export const NFTDropInitializer = {
name: "DropERC721" as const,
contractType: "nft-drop" as const,
schema: DropErc721ContractSchema,
@@ -152,38 +134,38 @@ export const NFTDrop = {
...[network, address, storage, options]: InitalizeParams
) => {
const [abi, contract] = await Promise.all([
NFTDrop.getAbi(),
NFTDropInitializer.getAbi(),
import("./prebuilt-implementations/nft-drop"),
]);
return new contract.NFTDropImpl(network, address, storage, options, abi);
return new contract.NFTDrop(network, address, storage, options, abi);
},
getAbi: async () =>
(await import("@thirdweb-dev/contracts-js/dist/abis/DropERC721.json"))
.default,
};
export const Pack = {
export const PackInitializer = {
name: "Pack" as const,
contractType: "pack" as const,
schema: PackContractSchema,
roles: ["admin", "minter", "pauser", "transfer"] as const,
roles: ["admin", "minter", "asset", "transfer"] as const,
initialize: async (
...[network, address, storage, options]: InitalizeParams
) => {
const [abi, contract] = await Promise.all([
Pack.getAbi(),
PackInitializer.getAbi(),
import("./prebuilt-implementations/pack"),
]);
return new contract.PackImpl(network, address, storage, options, abi);
return new contract.Pack(network, address, storage, options, abi);
},
getAbi: async () =>
(await import("@thirdweb-dev/contracts-js/dist/abis/Pack.json")).default,
};
export const SignatureDrop = {
export const SignatureDropInitializer = {
name: "SignatureDrop" as const,
contractType: "signature-drop" as const,
schema: DropErc721ContractSchema,
@@ -193,24 +175,18 @@ export const SignatureDrop = {
...[network, address, storage, options]: InitalizeParams
) => {
const [abi, contract] = await Promise.all([
SignatureDrop.getAbi(),
SignatureDropInitializer.getAbi(),
import("./prebuilt-implementations/signature-drop"),
]);
return new contract.SignatureDropImpl(
network,
address,
storage,
options,
abi,
);
return new contract.SignatureDrop(network, address, storage, options, abi);
},
getAbi: async () =>
(await import("@thirdweb-dev/contracts-js/dist/abis/SignatureDrop.json"))
.default,
};
export const Split = {
export const SplitInitializer = {
name: "Split" as const,
contractType: "split" as const,
schema: SplitsContractSchema,
@@ -220,17 +196,17 @@ export const Split = {
...[network, address, storage, options]: InitalizeParams
) => {
const [abi, contract] = await Promise.all([
Split.getAbi(),
SplitInitializer.getAbi(),
import("./prebuilt-implementations/split"),
]);
return new contract.SplitImpl(network, address, storage, options, abi);
return new contract.Split(network, address, storage, options, abi);
},
getAbi: async () =>
(await import("@thirdweb-dev/contracts-js/dist/abis/Split.json")).default,
};
export const TokenDrop = {
export const TokenDropInitializer = {
name: "DropERC20" as const,
contractType: "token-drop" as const,
schema: DropErc20ContractSchema,
@@ -240,18 +216,18 @@ export const TokenDrop = {
...[network, address, storage, options]: InitalizeParams
) => {
const [abi, contract] = await Promise.all([
TokenDrop.getAbi(),
TokenDropInitializer.getAbi(),
import("./prebuilt-implementations/token-drop"),
]);
return new contract.TokenDropImpl(network, address, storage, options, abi);
return new contract.TokenDrop(network, address, storage, options, abi);
},
getAbi: async () =>
(await import("@thirdweb-dev/contracts-js/dist/abis/DropERC20.json"))
.default,
};
export const Token = {
export const TokenInitializer = {
name: "TokenERC20" as const,
contractType: "token" as const,
schema: TokenErc20ContractSchema,
@@ -260,18 +236,18 @@ export const Token = {
...[network, address, storage, options]: InitalizeParams
) => {
const [abi, contract] = await Promise.all([
Token.getAbi(),
TokenInitializer.getAbi(),
import("./prebuilt-implementations/token"),
]);
return new contract.TokenImpl(network, address, storage, options, abi);
return new contract.Token(network, address, storage, options, abi);
},
getAbi: async () =>
(await import("@thirdweb-dev/contracts-js/dist/abis/TokenERC20.json"))
.default,
};
export const Vote = {
export const VoteInitializer = {
name: "VoteERC20" as const,
contractType: "vote" as const,
schema: VoteContractSchema,
@@ -281,11 +257,11 @@ export const Vote = {
...[network, address, storage, options]: InitalizeParams
) => {
const [abi, contract] = await Promise.all([
Vote.getAbi(),
VoteInitializer.getAbi(),
import("./prebuilt-implementations/vote"),
]);
return new contract.VoteImpl(network, address, storage, options, abi);
return new contract.Vote(network, address, storage, options, abi);
},
getAbi: async () =>
(await import("@thirdweb-dev/contracts-js/dist/abis/VoteERC20.json"))
@@ -297,18 +273,18 @@ export const Vote = {
* @internal
*/
export const PREBUILT_CONTRACTS_MAP = {
[EditionDrop.contractType]: EditionDrop,
[Edition.contractType]: Edition,
[Marketplace.contractType]: Marketplace,
[Multiwrap.contractType]: Multiwrap,
[NFTCollection.contractType]: NFTCollection,
[NFTDrop.contractType]: NFTDrop,
[Pack.contractType]: Pack,
[SignatureDrop.contractType]: SignatureDrop,
[Split.contractType]: Split,
[TokenDrop.contractType]: TokenDrop,
[Token.contractType]: Token,
[Vote.contractType]: Vote,
[EditionDropInitializer.contractType]: EditionDropInitializer,
[EditionInitializer.contractType]: EditionInitializer,
[MarketplaceInitializer.contractType]: MarketplaceInitializer,
[MultiwrapInitializer.contractType]: MultiwrapInitializer,
[NFTCollectionInitializer.contractType]: NFTCollectionInitializer,
[NFTDropInitializer.contractType]: NFTDropInitializer,
[PackInitializer.contractType]: PackInitializer,
[SignatureDropInitializer.contractType]: SignatureDropInitializer,
[SplitInitializer.contractType]: SplitInitializer,
[TokenDropInitializer.contractType]: TokenDropInitializer,
[TokenInitializer.contractType]: TokenInitializer,
[VoteInitializer.contractType]: VoteInitializer,
} as const;
const SmartContract = {
@@ -19,6 +19,7 @@ import {
TransactionResult,
TransactionResultWithId,
} from "../../core/types";
import { PaperCheckout } from "../../integrations/paper-xyz";
import { EditionMetadata, EditionMetadataOwner } from "../../schema";
import { DropErc1155ContractSchema } from "../../schema/contracts/drop-erc1155";
import { SDKOptions } from "../../schema/sdk-options";
@@ -26,7 +27,7 @@ import { NFTMetadata, NFTMetadataOrUri } from "../../schema/tokens/common";
import { QueryAllParams, UploadProgressEvent } from "../../types";
import type { DropERC1155 } from "@thirdweb-dev/contracts-js";
import type ABI from "@thirdweb-dev/contracts-js/dist/abis/DropERC1155.json";
import { IStorage } from "@thirdweb-dev/storage";
import { ThirdwebStorage } from "@thirdweb-dev/storage";
import { BigNumber, BigNumberish, CallOverrides, constants } from "ethers";
/**
@@ -43,7 +44,7 @@ import { BigNumber, BigNumberish, CallOverrides, constants } from "ethers";
*
* @public
*/
export class EditionDropImpl extends StandardErc1155<DropERC1155> {
export class EditionDrop extends StandardErc1155<DropERC1155> {
private static contractRoles = ["admin", "minter", "transfer"] as const;
public abi: typeof ABI;
@@ -58,7 +59,7 @@ export class EditionDropImpl extends StandardErc1155<DropERC1155> {
>;
public roles: ContractRoles<
DropERC1155,
typeof EditionDropImpl.contractRoles[number]
typeof EditionDrop.contractRoles[number]
>;
/**
* Configure royalties
@@ -106,6 +107,13 @@ export class EditionDropImpl extends StandardErc1155<DropERC1155> {
* ```
*/
public claimConditions: DropErc1155ClaimConditions<DropERC1155>;
/**
* Checkout
* @remarks Create a FIAT currency checkout for your NFT drop.
*/
public checkout: PaperCheckout<DropERC1155>;
public history: DropErc1155History;
public interceptor: ContractInterceptor<DropERC1155>;
public erc1155: Erc1155<DropERC1155>;
@@ -113,7 +121,7 @@ export class EditionDropImpl extends StandardErc1155<DropERC1155> {
constructor(
network: NetworkOrSignerOrProvider,
address: string,
storage: IStorage,
storage: ThirdwebStorage,
options: SDKOptions = {},
abi: typeof ABI,
contractWrapper = new ContractWrapper<DropERC1155>(
@@ -132,7 +140,7 @@ export class EditionDropImpl extends StandardErc1155<DropERC1155> {
);
this.roles = new ContractRoles(
this.contractWrapper,
EditionDropImpl.contractRoles,
EditionDrop.contractRoles,
);
this.royalties = new ContractRoyalty(this.contractWrapper, this.metadata);
this.sales = new ContractPrimarySale(this.contractWrapper);
@@ -148,6 +156,7 @@ export class EditionDropImpl extends StandardErc1155<DropERC1155> {
this.platformFees = new ContractPlatformFee(this.contractWrapper);
this.interceptor = new ContractInterceptor(this.contractWrapper);
this.erc1155 = new Erc1155(this.contractWrapper, this.storage);
this.checkout = new PaperCheckout(this.contractWrapper);
}
/**
@@ -281,25 +290,12 @@ export class EditionDropImpl extends StandardErc1155<DropERC1155> {
quantity: BigNumberish,
checkERC20Allowance = true, // TODO split up allowance checks
): Promise<TransactionTask> {
const claimVerification = await this.erc1155.claimConditions.prepareClaim(
return this.erc1155.getClaimTransaction(
destinationAddress,
tokenId,
quantity,
checkERC20Allowance,
{ checkERC20Allowance },
);
return TransactionTask.make({
contractWrapper: this.contractWrapper,
functionName: "claim",
args: [
destinationAddress,
tokenId,
quantity,
claimVerification.currencyAddress,
claimVerification.price,
claimVerification.proofs,
claimVerification.maxQuantityPerTransaction,
],
overrides: claimVerification.overrides,
});
}
/**
@@ -331,13 +327,9 @@ export class EditionDropImpl extends StandardErc1155<DropERC1155> {
quantity: BigNumberish,
checkERC20Allowance = true,
): Promise<TransactionResult> {
const tx = await this.getClaimTransaction(
destinationAddress,
tokenId,
quantity,
return this.erc1155.claimTo(destinationAddress, tokenId, quantity, {
checkERC20Allowance,
);
return await tx.execute();
});
}
/**
@@ -27,7 +27,7 @@ import {
import { QueryAllParams } from "../../types";
import type { TokenERC1155 } from "@thirdweb-dev/contracts-js";
import type ABI from "@thirdweb-dev/contracts-js/dist/abis/TokenERC1155.json";
import { IStorage } from "@thirdweb-dev/storage";
import { ThirdwebStorage } from "@thirdweb-dev/storage";
import { BigNumber, BigNumberish, CallOverrides, constants } from "ethers";
/**
@@ -44,7 +44,7 @@ import { BigNumber, BigNumberish, CallOverrides, constants } from "ethers";
*
* @public
*/
export class EditionImpl extends StandardErc1155<TokenERC1155> {
export class Edition extends StandardErc1155<TokenERC1155> {
static contractRoles = ["admin", "minter", "transfer"] as const;
public abi: typeof ABI;
@@ -54,7 +54,7 @@ export class EditionImpl extends StandardErc1155<TokenERC1155> {
>;
public roles: ContractRoles<
TokenERC1155,
typeof EditionImpl.contractRoles[number]
typeof Edition.contractRoles[number]
>;
public sales: ContractPrimarySale<TokenERC1155>;
public platformFees: ContractPlatformFee<TokenERC1155>;
@@ -103,7 +103,7 @@ export class EditionImpl extends StandardErc1155<TokenERC1155> {
constructor(
network: NetworkOrSignerOrProvider,
address: string,
storage: IStorage,
storage: ThirdwebStorage,
options: SDKOptions = {},
abi: typeof ABI,
contractWrapper = new ContractWrapper<TokenERC1155>(
@@ -120,10 +120,7 @@ export class EditionImpl extends StandardErc1155<TokenERC1155> {
TokenErc1155ContractSchema,
this.storage,
);
this.roles = new ContractRoles(
this.contractWrapper,
EditionImpl.contractRoles,
);
this.roles = new ContractRoles(this.contractWrapper, Edition.contractRoles);
this.royalties = new ContractRoyalty(this.contractWrapper, this.metadata);
this.sales = new ContractPrimarySale(this.contractWrapper);
this.encoder = new ContractEncoder(this.contractWrapper);
@@ -20,7 +20,7 @@ import { AuctionListing, DirectListing } from "../../types/marketplace";
import { MarketplaceFilter } from "../../types/marketplace/MarketPlaceFilter";
import type { Marketplace as MarketplaceContract } from "@thirdweb-dev/contracts-js";
import type ABI from "@thirdweb-dev/contracts-js/dist/abis/Marketplace.json";
import { IStorage } from "@thirdweb-dev/storage";
import { ThirdwebStorage } from "@thirdweb-dev/storage";
import { BigNumber, BigNumberish, CallOverrides, constants } from "ethers";
import invariant from "tiny-invariant";
@@ -38,12 +38,12 @@ import invariant from "tiny-invariant";
*
* @public
*/
export class MarketplaceImpl implements UpdateableNetwork {
export class Marketplace implements UpdateableNetwork {
static contractRoles = ["admin", "lister", "asset"] as const;
public abi: typeof ABI;
private contractWrapper: ContractWrapper<MarketplaceContract>;
private storage: IStorage;
private storage: ThirdwebStorage;
public encoder: ContractEncoder<MarketplaceContract>;
public events: ContractEvents<MarketplaceContract>;
@@ -55,7 +55,7 @@ export class MarketplaceImpl implements UpdateableNetwork {
>;
public roles: ContractRoles<
MarketplaceContract,
typeof MarketplaceImpl.contractRoles[number]
typeof Marketplace.contractRoles[number]
>;
/**
* @internal
@@ -135,7 +135,7 @@ export class MarketplaceImpl implements UpdateableNetwork {
constructor(
network: NetworkOrSignerOrProvider,
address: string,
storage: IStorage,
storage: ThirdwebStorage,
options: SDKOptions = {},
abi: typeof ABI,
contractWrapper = new ContractWrapper<MarketplaceContract>(
@@ -155,7 +155,7 @@ export class MarketplaceImpl implements UpdateableNetwork {
);
this.roles = new ContractRoles(
this.contractWrapper,
MarketplaceImpl.contractRoles,
Marketplace.contractRoles,
);
this.encoder = new ContractEncoder(this.contractWrapper);
this.estimator = new GasCostEstimator(this.contractWrapper);

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