Compare commits
80
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a20be881e3 | ||
|
|
47f8945325 | ||
|
|
1b0bf99da7 | ||
|
|
f03be398e0 | ||
|
|
27996cb4bc | ||
|
|
2eaa67acbe | ||
|
|
aafd7968df | ||
|
|
48797c7cf0 | ||
|
|
4edcb37100 | ||
|
|
83dcaf7058 | ||
|
|
b4e005be7f | ||
|
|
ccb7db4873 | ||
|
|
9151aa7dc8 | ||
|
|
5a01c537e3 | ||
|
|
f09c153ff7 | ||
|
|
15431621fd | ||
|
|
887af24450 | ||
|
|
15514f190a | ||
|
|
72589ec234 | ||
|
|
f8bceec10c | ||
|
|
7c0744a006 | ||
|
|
846022e2cf | ||
|
|
96bd92e724 | ||
|
|
c2b6d977ed | ||
|
|
7cb8e59be4 | ||
|
|
04a47e8971 | ||
|
|
8a6a97a3e9 | ||
|
|
612bcdd16f | ||
|
|
0ed77d2c9e | ||
|
|
7129aef6e1 | ||
|
|
f50b74819d | ||
|
|
3eba69afd7 | ||
|
|
98c2253e8f | ||
|
|
32d91ef709 | ||
|
|
b79dc18f7a | ||
|
|
4af785c37c | ||
|
|
6f818f393e | ||
|
|
97ed4779a9 | ||
|
|
2d3fca5237 | ||
|
|
7016019f2a | ||
|
|
4e7b293c54 | ||
|
|
c9c0e4ff39 | ||
|
|
06c24c153a | ||
|
|
aa6d9ed75d | ||
|
|
42a606588d | ||
|
|
2820761003 | ||
|
|
5200d5d7e7 | ||
|
|
e731c1a7c3 | ||
|
|
2e8d3fd6e7 | ||
|
|
cc4613b5fd | ||
|
|
78566babaa | ||
|
|
65fc7ba6ff | ||
|
|
1c24c3c3c4 | ||
|
|
408c5a81fa | ||
|
|
352291791e | ||
|
|
aabbb149e8 | ||
|
|
d59450f814 | ||
|
|
7d9a4c6abc | ||
|
|
99806e595d | ||
|
|
21c21c1adf | ||
|
|
4b10719047 | ||
|
|
989cf7347c | ||
|
|
72227b2e16 | ||
|
|
ed6c54f20d | ||
|
|
26116a6f63 | ||
|
|
f11a2719ff | ||
|
|
ef27aad0aa | ||
|
|
b03a902145 | ||
|
|
340605b507 | ||
|
|
15f8006e1f | ||
|
|
811c5a1166 | ||
|
|
c41a80d86d | ||
|
|
ad851f7b4d | ||
|
|
6218c88584 | ||
|
|
c9b564feaf | ||
|
|
87fd6ab14e | ||
|
|
df74340fa5 | ||
|
|
a57b4f01f3 | ||
|
|
126752d7d0 | ||
|
|
89ff921a7d |
@@ -7,7 +7,7 @@
|
||||
"access": "public",
|
||||
"baseBranch": "main",
|
||||
"updateInternalDependencies": "patch",
|
||||
"ignore": [],
|
||||
"ignore": ["e2e-cra-5", "e2e-next-12", "e2e-vite-3"],
|
||||
"___experimentalUnsafeOptions_WILL_CHANGE_IN_PATCH": {
|
||||
"updateInternalDependents": "always",
|
||||
"onlyUpdatePeerDependentsWhenOutOfRange": true
|
||||
|
||||
@@ -9,7 +9,7 @@ runs:
|
||||
with:
|
||||
node-version: 16
|
||||
registry-url: "https://registry.npmjs.org"
|
||||
# cache: "yarn"
|
||||
cache: "yarn"
|
||||
|
||||
- name: Install dependencies
|
||||
shell: bash
|
||||
|
||||
@@ -14,8 +14,7 @@ jobs:
|
||||
build:
|
||||
name: Build and Test
|
||||
# timeout-minutes: 15
|
||||
# try out buildjet to speed up build and test
|
||||
runs-on: buildjet-32vcpu-ubuntu-2204
|
||||
runs-on: ubuntu-latest-32
|
||||
# To use Remote Caching, uncomment the next lines and follow the steps below.
|
||||
env:
|
||||
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
|
||||
|
||||
@@ -13,8 +13,7 @@ concurrency:
|
||||
jobs:
|
||||
integration-tests:
|
||||
timeout-minutes: 60
|
||||
# try out buildjet to speed up build and test
|
||||
runs-on: buildjet-32vcpu-ubuntu-2204
|
||||
runs-on: ubuntu-latest-32
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
@@ -28,9 +27,3 @@ jobs:
|
||||
run: yarn e2e
|
||||
env:
|
||||
NODE_OPTIONS: "--max_old_space_size=4096"
|
||||
- uses: actions/upload-artifact@v2
|
||||
if: always()
|
||||
with:
|
||||
name: playwright-report
|
||||
path: packages/react/playwright-report/
|
||||
retention-days: 30
|
||||
|
||||
@@ -40,8 +40,7 @@ jobs:
|
||||
comment_body: ${{ github.event.comment.body }}
|
||||
|
||||
deploy:
|
||||
# try out buildjet to speed up build and test
|
||||
runs-on: buildjet-32vcpu-ubuntu-2204
|
||||
runs-on: ubuntu-latest-32
|
||||
needs: deploy-check
|
||||
if: needs.deploy-check.outputs.triggered == 'true'
|
||||
steps:
|
||||
|
||||
@@ -14,8 +14,7 @@ concurrency:
|
||||
jobs:
|
||||
release:
|
||||
name: Release
|
||||
# try out buildjet to speed up build and test
|
||||
runs-on: buildjet-32vcpu-ubuntu-2204
|
||||
runs-on: ubuntu-latest-32
|
||||
steps:
|
||||
- name: Checkout branch
|
||||
uses: actions/checkout@v3
|
||||
|
||||
@@ -4,8 +4,7 @@ on: [pull_request]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
# try out buildjet to speed up build and test
|
||||
runs-on: buildjet-32vcpu-ubuntu-2204
|
||||
runs-on: ubuntu-latest-32
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
@@ -16,3 +15,5 @@ jobs:
|
||||
repo-token: "${{ secrets.GITHUB_TOKEN }}"
|
||||
strip-hash: "\\-(\\w{8})(?:\\.esm|\\.cjs)"
|
||||
minimum-change-threshold: 100
|
||||
# exclude source maps, node modules and any test related files
|
||||
exclude: "{**/*.map,**/node_modules/**,**/test/**}"
|
||||
|
||||
+6
-1
@@ -12,4 +12,9 @@ server/dist
|
||||
public/dist
|
||||
.turbo
|
||||
./packages/contracts-js/abis
|
||||
.idea/
|
||||
.idea/
|
||||
.yalc/
|
||||
yalc.lock
|
||||
build/
|
||||
playwright-report/
|
||||
.vscode/
|
||||
@@ -1,4 +1,3 @@
|
||||
lib
|
||||
node_modules
|
||||
dist
|
||||
contracts-js
|
||||
|
||||
@@ -28,7 +28,6 @@
|
||||
| [/storage](./packages/storage) | Best in class decentralized storage SDK for Browser and Node | <a href="https://www.npmjs.com/package/@thirdweb-dev/storage"><img src="https://img.shields.io/npm/v/@thirdweb-dev/storage?color=red&label=npm&logo=npm" alt="npm version"/></a> |
|
||||
| [/cli](./packages/cli) | Publish and deploy smart contracts without dealing with private keys | <a href="https://www.npmjs.com/package/thirdweb"><img src="https://img.shields.io/npm/v/thirdweb?color=red&label=npm&logo=npm" alt="npm version"/></a> |
|
||||
|
||||
|
||||
## Documentation
|
||||
|
||||
Visit [https://portal.thirdweb.com/](https://portal.thirdweb.com/) to view the full documentation.
|
||||
|
||||
+5
-9
@@ -8,14 +8,15 @@
|
||||
"private": true,
|
||||
"workspaces": {
|
||||
"packages": [
|
||||
"packages/*"
|
||||
"packages/*",
|
||||
"test/**/*"
|
||||
]
|
||||
},
|
||||
"scripts": {
|
||||
"test": "turbo run test test:evm test:solana",
|
||||
"e2e": "turbo run e2e",
|
||||
"build": "turbo run build",
|
||||
"build:release": "turbo run build --force",
|
||||
"build": "turbo run build --filter=./packages/*",
|
||||
"build:release": "turbo run build --force --filter=./packages/*",
|
||||
"dev": "turbo run dev --no-cache --parallel --continue",
|
||||
"fix:repo": "manypkg fix",
|
||||
"lint": "turbo run lint",
|
||||
@@ -27,12 +28,7 @@
|
||||
"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",
|
||||
"push": "turbo run push"
|
||||
},
|
||||
"preconstruct": {
|
||||
"packages": [
|
||||
"packages/*"
|
||||
]
|
||||
"push": "turbo run push --filter=./packages/*"
|
||||
},
|
||||
"packageManager": "[email protected]",
|
||||
"dependencies": {
|
||||
|
||||
@@ -1,5 +1,43 @@
|
||||
# @thirdweb-dev/auth
|
||||
|
||||
## 2.0.33
|
||||
|
||||
## 2.0.32
|
||||
|
||||
## 2.0.31
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#397](https://github.com/thirdweb-dev/js/pull/397) [`72589ec`](https://github.com/thirdweb-dev/js/commit/72589ec234d86939b67b0ca8b3b789f2e9c54cc2) Thanks [@adam-maj](https://github.com/adam-maj)! - Call user callback in getUser
|
||||
|
||||
## 2.0.30
|
||||
|
||||
## 2.0.29
|
||||
|
||||
## 2.0.28
|
||||
|
||||
## 2.0.27
|
||||
|
||||
## 2.0.26
|
||||
|
||||
## 2.0.25
|
||||
|
||||
## 2.0.24
|
||||
|
||||
## 2.0.23
|
||||
|
||||
## 2.0.22
|
||||
|
||||
## 2.0.21
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#327](https://github.com/thirdweb-dev/js/pull/327) [`ef27aad`](https://github.com/thirdweb-dev/js/commit/ef27aad0aafc4577e85f44dc77dfbe880bd239b5) Thanks [@jnsdls](https://github.com/jnsdls)! - enable e2e testing
|
||||
|
||||
## 2.0.20
|
||||
|
||||
## 2.0.19
|
||||
|
||||
## 2.0.18
|
||||
|
||||
## 2.0.17
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@thirdweb-dev/auth",
|
||||
"version": "2.0.18",
|
||||
"version": "2.0.33",
|
||||
"exports": {
|
||||
"./next": {
|
||||
"module": "./next/dist/thirdweb-dev-auth-next.esm.js",
|
||||
@@ -73,7 +73,7 @@
|
||||
"eslint-plugin-inclusive-language": "^2.2.0",
|
||||
"eslint-plugin-prettier": "^4.2.1",
|
||||
"eslint-plugin-tsdoc": "^0.2.16",
|
||||
"ethers": "^5.7.1",
|
||||
"ethers": "^5.7.2",
|
||||
"express": "^4.18.1",
|
||||
"next": "^12.2.0",
|
||||
"next-auth": "^4.10.3",
|
||||
|
||||
@@ -70,7 +70,13 @@ export function ThirdwebAuth(cfg: ThirdwebAuthConfig) {
|
||||
if (token) {
|
||||
try {
|
||||
const address = await sdk.auth.authenticate(domain, token);
|
||||
user = { address };
|
||||
|
||||
let data = {};
|
||||
if (ctx.callbacks?.user) {
|
||||
data = await ctx.callbacks.user(address);
|
||||
}
|
||||
|
||||
user = { ...data, address };
|
||||
} catch {
|
||||
// No-op
|
||||
}
|
||||
|
||||
@@ -70,7 +70,13 @@ export function ThirdwebAuth(cfg: ThirdwebAuthConfig) {
|
||||
if (token) {
|
||||
try {
|
||||
const address = await sdk.auth.authenticate(domain, token);
|
||||
user = { address };
|
||||
|
||||
let data = {};
|
||||
if (ctx.callbacks?.user) {
|
||||
data = await ctx.callbacks.user(address);
|
||||
}
|
||||
|
||||
user = { ...data, address };
|
||||
} catch {
|
||||
// No-op
|
||||
}
|
||||
|
||||
@@ -1,5 +1,122 @@
|
||||
# thirdweb
|
||||
|
||||
## 0.9.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- [#403](https://github.com/thirdweb-dev/js/pull/403) [`27996cb`](https://github.com/thirdweb-dev/js/commit/27996cb4bc6f054f45b0a66b0a3aca732e0ef610) Thanks [@avneesh0612](https://github.com/avneesh0612)! - Add CLI Support for solana with --solana flag on create command
|
||||
|
||||
- [#283](https://github.com/thirdweb-dev/js/pull/283) [`2eaa67a`](https://github.com/thirdweb-dev/js/commit/2eaa67acbe21464e7715d0b696afdc024460a44d) Thanks [@adam-maj](https://github.com/adam-maj)! - add capability to deploy apps
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#413](https://github.com/thirdweb-dev/js/pull/413) [`1b0bf99`](https://github.com/thirdweb-dev/js/commit/1b0bf99da796df88ff307dd004cdaf239fb2b1ba) Thanks [@furqanrydhan](https://github.com/furqanrydhan)! - small interface tweaks
|
||||
|
||||
- Updated dependencies [[`48797c7`](https://github.com/thirdweb-dev/js/commit/48797c7cf0695965e33eb6bf602be4652f7085a8), [`83dcaf7`](https://github.com/thirdweb-dev/js/commit/83dcaf70584af8c5cdf0427f9fc1ba82d89f0887), [`f03be39`](https://github.com/thirdweb-dev/js/commit/f03be398e0d7b75c9c5b4fb643f35903e89a17e7), [`2eaa67a`](https://github.com/thirdweb-dev/js/commit/2eaa67acbe21464e7715d0b696afdc024460a44d), [`47f8945`](https://github.com/thirdweb-dev/js/commit/47f8945325447874b1ace0359919c1d54fd55436)]:
|
||||
- @thirdweb-dev/sdk@3.6.3
|
||||
|
||||
## 0.8.18
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`ccb7db4`](https://github.com/thirdweb-dev/js/commit/ccb7db48739b8dddcb2c032b3b6e3e5200485715), [`9151aa7`](https://github.com/thirdweb-dev/js/commit/9151aa7dc80754a7aa4fd3f6ce0207bccbb6451f), [`5a01c53`](https://github.com/thirdweb-dev/js/commit/5a01c537e30bd7ef562aad1012413990de6faedf)]:
|
||||
- @thirdweb-dev/sdk@3.6.2
|
||||
|
||||
## 0.8.17
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`15514f1`](https://github.com/thirdweb-dev/js/commit/15514f190a844d809ae5b1edb580aab46a682485), [`7c0744a`](https://github.com/thirdweb-dev/js/commit/7c0744a006e78987ad8b271b2c64f4bac7759510), [`f8bceec`](https://github.com/thirdweb-dev/js/commit/f8bceec10c60b30dc3d6f45926e2a9e018202578), [`887af24`](https://github.com/thirdweb-dev/js/commit/887af24450e316c2ea390cd49c0563cebe793c0f), [`96bd92e`](https://github.com/thirdweb-dev/js/commit/96bd92e724ec7d880d23348071b26ab8c21dd868)]:
|
||||
- @thirdweb-dev/sdk@3.6.1
|
||||
|
||||
## 0.8.16
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`7cb8e59`](https://github.com/thirdweb-dev/js/commit/7cb8e59be48dc923316eb36ab43a1bef7364f6b1), [`0ed77d2`](https://github.com/thirdweb-dev/js/commit/0ed77d2c9e7526444ef660aab82a950865234aa6), [`04a47e8`](https://github.com/thirdweb-dev/js/commit/04a47e8971d28da2532ebd9db824eeb459c17bd4)]:
|
||||
- @thirdweb-dev/sdk@3.6.0
|
||||
|
||||
## 0.8.15
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`3eba69a`](https://github.com/thirdweb-dev/js/commit/3eba69afd78b7aa472a9c00c9d4220bb69ad1d3e), [`4af785c`](https://github.com/thirdweb-dev/js/commit/4af785c37c831ecd7087c1c9eb9095922cac0855), [`6f818f3`](https://github.com/thirdweb-dev/js/commit/6f818f393eb9023b53a3358d62d60ec23a9246bd), [`b79dc18`](https://github.com/thirdweb-dev/js/commit/b79dc18f7ab5155bbf4af02dc1a953546160bad0)]:
|
||||
- @thirdweb-dev/sdk@3.5.2
|
||||
|
||||
## 0.8.14
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`4e7b293`](https://github.com/thirdweb-dev/js/commit/4e7b293c543244de79c150ca8c37d941221fc9a3), [`c9c0e4f`](https://github.com/thirdweb-dev/js/commit/c9c0e4ff39b054af746f3aec75fcbd0a3ef7239d)]:
|
||||
- @thirdweb-dev/sdk@3.5.1
|
||||
|
||||
## 0.8.13
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`5200d5d`](https://github.com/thirdweb-dev/js/commit/5200d5d7e730da58bd4d3e7c222e3c661265f913), [`42a6065`](https://github.com/thirdweb-dev/js/commit/42a606588dfed03c67c57357dd0ee1ad19fad6ea)]:
|
||||
- @thirdweb-dev/sdk@3.5.0
|
||||
|
||||
## 0.8.12
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`e731c1a`](https://github.com/thirdweb-dev/js/commit/e731c1a7c341e6f2b9cc42c88d5c1b036dcf4a7c)]:
|
||||
- @thirdweb-dev/sdk@3.4.5
|
||||
|
||||
## 0.8.11
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies []:
|
||||
- @thirdweb-dev/sdk@3.4.4
|
||||
|
||||
## 0.8.10
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`1c24c3c`](https://github.com/thirdweb-dev/js/commit/1c24c3c3c48476a824f817e09e7bf0fbe67c1db5), [`65fc7ba`](https://github.com/thirdweb-dev/js/commit/65fc7ba6fff093a971b53cb0979c39768e090ba1)]:
|
||||
- @thirdweb-dev/sdk@3.4.3
|
||||
|
||||
## 0.8.9
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`21c21c1`](https://github.com/thirdweb-dev/js/commit/21c21c1adfd09b60ad563bfd4c308597140de33c), [`3522917`](https://github.com/thirdweb-dev/js/commit/352291791ee900e1500f84f095290497934d2f60)]:
|
||||
- @thirdweb-dev/sdk@3.4.2
|
||||
|
||||
## 0.8.8
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`72227b2`](https://github.com/thirdweb-dev/js/commit/72227b2e166a3a68bbb41cf2b389322f5b7547a2)]:
|
||||
- @thirdweb-dev/sdk@3.4.1
|
||||
|
||||
## 0.8.7
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#327](https://github.com/thirdweb-dev/js/pull/327) [`ef27aad`](https://github.com/thirdweb-dev/js/commit/ef27aad0aafc4577e85f44dc77dfbe880bd239b5) Thanks [@jnsdls](https://github.com/jnsdls)! - enable e2e testing
|
||||
|
||||
- Updated dependencies [[`340605b`](https://github.com/thirdweb-dev/js/commit/340605b507f384fbd2999b9c16542af3c53e84a9), [`26116a6`](https://github.com/thirdweb-dev/js/commit/26116a6f637ee845f7bd17f20ffe17caf184658e), [`15f8006`](https://github.com/thirdweb-dev/js/commit/15f8006e1fb22333b7ee239b45e7b1b12d6dccc8), [`ef27aad`](https://github.com/thirdweb-dev/js/commit/ef27aad0aafc4577e85f44dc77dfbe880bd239b5)]:
|
||||
- @thirdweb-dev/sdk@3.4.0
|
||||
|
||||
## 0.8.6
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`ad851f7`](https://github.com/thirdweb-dev/js/commit/ad851f7b4d6abb5ab9364ef3dec229f913e18ce5), [`6218c88`](https://github.com/thirdweb-dev/js/commit/6218c885842e6b4e44ec38ec92a9211e56c49bf4)]:
|
||||
- @thirdweb-dev/sdk@3.3.1
|
||||
|
||||
## 0.8.5
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#326](https://github.com/thirdweb-dev/js/pull/326) [`126752d`](https://github.com/thirdweb-dev/js/commit/126752d7d02c9a808a63fb9e67a9df6658b5682b) Thanks [@jnsdls](https://github.com/jnsdls)! - remove tons of unused dependencies, use SDK function for extracting ipfs has from bytecode
|
||||
|
||||
- Updated dependencies [[`126752d`](https://github.com/thirdweb-dev/js/commit/126752d7d02c9a808a63fb9e67a9df6658b5682b), [`df74340`](https://github.com/thirdweb-dev/js/commit/df74340fa51323304c32419761d6f18628b060fa), [`89ff921`](https://github.com/thirdweb-dev/js/commit/89ff921a7d9f0e42b4e6707c8b56d0aab95c1aa0), [`a57b4f0`](https://github.com/thirdweb-dev/js/commit/a57b4f01f3a49590b897101f2730582e4124a554)]:
|
||||
- @thirdweb-dev/sdk@3.3.0
|
||||
|
||||
## 0.8.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
export const CREATE_MESSAGES = {
|
||||
typeOfProject: "What type of project do you want to create?",
|
||||
projectName: "What is your project named?",
|
||||
chain: "Which blockchain do you want to use?",
|
||||
framework: "What framework do you want to use?",
|
||||
language: "What language do you want to use?",
|
||||
contract: "What type of contract do you want to start from?",
|
||||
|
||||
@@ -2,7 +2,7 @@ import { CREATE_MESSAGES } from "../constants/constants";
|
||||
import { prepareEnvironment } from "@gmrchk/cli-testing-library";
|
||||
|
||||
// this creates an app, can take some time that's fine
|
||||
jest.setTimeout(120_000);
|
||||
jest.setTimeout(150_000);
|
||||
|
||||
describe("npx thirdweb create", () => {
|
||||
it("should create app (CRA) successfully", async () => {
|
||||
@@ -16,6 +16,8 @@ describe("npx thirdweb create", () => {
|
||||
await pressKey("enter");
|
||||
await waitForText(CREATE_MESSAGES.projectName);
|
||||
await pressKey("enter");
|
||||
await waitForText(CREATE_MESSAGES.chain);
|
||||
await pressKey("enter");
|
||||
await waitForText(CREATE_MESSAGES.framework);
|
||||
// select CRA
|
||||
await pressKey("arrowDown");
|
||||
|
||||
@@ -15,8 +15,8 @@ describe("npx thirdweb deploy", () => {
|
||||
`${path}/BasicContract.sol`,
|
||||
);
|
||||
|
||||
const { waitForText, waitForFinish, getExitCode, writeText, getStdout } =
|
||||
await spawn("node", "./dist/cli/index.js deploy");
|
||||
const { waitForText, waitForFinish, getExitCode, writeText, getStderr } =
|
||||
await spawn("node", "./dist/cli/index.js deploy --contract");
|
||||
|
||||
expect(await exists("BasicContract.sol")).toEqual(true);
|
||||
|
||||
@@ -26,7 +26,7 @@ describe("npx thirdweb deploy", () => {
|
||||
// wait for program to finish
|
||||
await waitForFinish();
|
||||
|
||||
expect(getStdout().at(-1)).toContain(
|
||||
expect(getStderr().at(-1)).toContain(
|
||||
"https://thirdweb.com/contracts/deploy/",
|
||||
);
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ describe("npx thirdweb release", () => {
|
||||
`${path}/BasicContract.sol`,
|
||||
);
|
||||
|
||||
const { waitForText, waitForFinish, getExitCode, writeText, getStdout } =
|
||||
const { waitForText, waitForFinish, getExitCode, writeText, getStderr } =
|
||||
await spawn("node", "./dist/cli/index.js release");
|
||||
|
||||
expect(await exists("BasicContract.sol")).toEqual(true);
|
||||
@@ -26,7 +26,7 @@ describe("npx thirdweb release", () => {
|
||||
// wait for program to finish
|
||||
await waitForFinish();
|
||||
|
||||
expect(getStdout().at(-1)).toContain(
|
||||
expect(getStderr().at(-1)).toContain(
|
||||
"https://thirdweb.com/contracts/release/",
|
||||
);
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "thirdweb",
|
||||
"main": "dist/cli/index.js",
|
||||
"version": "0.8.4",
|
||||
"version": "0.9.0",
|
||||
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/cli",
|
||||
"author": "thirdweb eng <[email protected]>",
|
||||
"license": "Apache-2.0",
|
||||
@@ -10,7 +10,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@gmrchk/cli-testing-library": "^0.1.2",
|
||||
"@types/async-retry": "1.3.0",
|
||||
"@types/async-retry": "^1.3.0",
|
||||
"@types/cross-spawn": "^6.0.2",
|
||||
"@types/inquirer": "^8.2.1",
|
||||
"@types/jest": "^29.0.0",
|
||||
@@ -31,24 +31,17 @@
|
||||
"dependencies": {
|
||||
"@thirdweb-dev/sdk": "*",
|
||||
"async-retry": "^1.3.3",
|
||||
"cbor": "^8.1.0",
|
||||
"commander": "^9.1.0",
|
||||
"cpy": "^9.0.1",
|
||||
"enquirer": "^2.3.6",
|
||||
"ethers": "^5.7.0",
|
||||
"form-data": "^4.0.0",
|
||||
"ethers": "^5.7.2",
|
||||
"got": "11.8.5",
|
||||
"inquirer": "^8.2.3",
|
||||
"ipfs-unixfs": "^6.0.7",
|
||||
"ipld-dag-pb": "^0.22.3",
|
||||
"multihashes": "^4.0.3",
|
||||
"open": "^8.4.0",
|
||||
"prompts": "^2.4.2",
|
||||
"rimraf": "^3.0.2",
|
||||
"solc": "0.8.13",
|
||||
"solc": "0.8.17",
|
||||
"tar": "^6.1.11",
|
||||
"tslog": "^3.3.3",
|
||||
"update-check": "^1.5.4",
|
||||
"update-notifier": "^6.0.2",
|
||||
"validate-npm-package-name": "^4.0.0",
|
||||
"yaml": "^2.1.1"
|
||||
|
||||
@@ -4,7 +4,7 @@ import { processProject } from "../common/processor";
|
||||
import { cliVersion, pkg } from "../constants/urls";
|
||||
import { info, logger } from "../core/helpers/logger";
|
||||
import { twCreate } from "../create/command";
|
||||
import generateDashboardUrl from "../helpers/generate-dashboard-url";
|
||||
import { deploy } from "../deploy";
|
||||
import { upload } from "../storage/command";
|
||||
import { ThirdwebStorage } from "@thirdweb-dev/storage";
|
||||
import chalk from "chalk";
|
||||
@@ -40,34 +40,36 @@ $$$$$$\\ $$$$$$$\\ $$\\ $$$$$$\\ $$$$$$$ |$$\\ $$\\ $$\\ $$$$$$\\ $$$$
|
||||
.version(cliVersion, "-v, --version");
|
||||
|
||||
program
|
||||
.command("create")
|
||||
.command("create [projectType] [projectPath]")
|
||||
.description(
|
||||
"Create a web3 app from any of our official templates: https://github.com/thirdweb-example/",
|
||||
)
|
||||
.option("--app", `Create a web3 app.`)
|
||||
.option("--contract", `Create a web3 contract 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("--app", "Create a web3 app.")
|
||||
.option("--contract", "Create a web3 contract 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`,
|
||||
"Explicitly tell the CLI to bootstrap the app using npm",
|
||||
)
|
||||
.option(
|
||||
"--use-pnpm",
|
||||
`Explicitly tell the CLI to bootstrap the app using pnpm`,
|
||||
"Explicitly tell the CLI to bootstrap the app using pnpm",
|
||||
)
|
||||
.option("--framework [name]", `The preferred framework.`)
|
||||
.option("--framework [name]", "The preferred framework.")
|
||||
.option("--solana", "Initialize as a Solana project.")
|
||||
.option("--evm", "Initialize as an Ethereum project.")
|
||||
.option(
|
||||
"-t, --template [name]",
|
||||
`A template to start your project from. You can use an template repository name from the official thirdweb-example org.`,
|
||||
"A template to start your project from. You can use an template repository name from the official thirdweb-example org.",
|
||||
)
|
||||
.action(async (options) => {
|
||||
await twCreate(options);
|
||||
.action(async (type, path, options) => {
|
||||
await twCreate(type, path, options);
|
||||
});
|
||||
|
||||
program
|
||||
@@ -87,6 +89,10 @@ $$$$$$\\ $$$$$$$\\ $$\\ $$$$$$\\ $$$$$$$ |$$\\ $$\\ $$\\ $$$$$$\\ $$$$
|
||||
.option("--dry-run", "dry run (skip actually publishing)")
|
||||
.option("-d, --debug", "show debug logs")
|
||||
.option("--ci", "Continuous Integration mode")
|
||||
.option(
|
||||
"--dist-path [distPath]",
|
||||
"Path to the dist folder where the HTML based App is",
|
||||
)
|
||||
.option(
|
||||
"-n, --name [name]",
|
||||
"Name of the pre-built or released contract (such as nft-drop)",
|
||||
@@ -95,31 +101,13 @@ $$$$$$\\ $$$$$$$\\ $$\\ $$$$$$\\ $$$$$$$ |$$\\ $$\\ $$\\ $$$$$$\\ $$$$
|
||||
"-cv, --contract-version [version]",
|
||||
"Version of the released contract",
|
||||
)
|
||||
.option("--app", "Deploy a web app to decentralized storage")
|
||||
.option("--contract", "Deploy a smart contract to blockchains")
|
||||
.action(async (options) => {
|
||||
if (options.name) {
|
||||
const url = generateDashboardUrl(options.name, options.contractVersion);
|
||||
|
||||
if (!url) {
|
||||
logger.error(
|
||||
chalk.red(
|
||||
`Could not find a contract named ${options.name} ${
|
||||
options.contractVersion || ""
|
||||
}`,
|
||||
),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
info(`Open this link to deploy your contract:`);
|
||||
logger.info(chalk.blueBright(url));
|
||||
open(url.toString());
|
||||
return;
|
||||
const url = await deploy(options);
|
||||
if (url) {
|
||||
open(url);
|
||||
}
|
||||
|
||||
const url = await processProject(options, "deploy");
|
||||
info(`Open this link to deploy your contracts:`);
|
||||
logger.info(chalk.blueBright(url.toString()));
|
||||
open(url.toString());
|
||||
});
|
||||
|
||||
program
|
||||
@@ -133,8 +121,11 @@ $$$$$$\\ $$$$$$$\\ $$\\ $$$$$$\\ $$$$$$$ |$$\\ $$\\ $$\\ $$$$$$\\ $$$$
|
||||
.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()));
|
||||
info(
|
||||
`Open this link to release your contracts: ${chalk.blueBright(
|
||||
url.toString(),
|
||||
)}`,
|
||||
);
|
||||
open(url.toString());
|
||||
});
|
||||
|
||||
@@ -144,13 +135,35 @@ $$$$$$\\ $$$$$$$\\ $$\\ $$$$$$\\ $$$$$$$ |$$\\ $$\\ $$\\ $$$$$$\\ $$$$
|
||||
.argument("[upload]", "path to file or directory to upload")
|
||||
.action(async (path) => {
|
||||
const storage = new ThirdwebStorage();
|
||||
const uri = await upload(storage, path);
|
||||
info(`Files stored at the following IPFS URI:`);
|
||||
logger.info(chalk.blueBright(uri.toString()));
|
||||
try {
|
||||
const uri = await upload(storage, path);
|
||||
info(
|
||||
`Files stored at the following IPFS URI: ${chalk.blueBright(
|
||||
uri.toString(),
|
||||
)}`,
|
||||
);
|
||||
|
||||
const url = storage.resolveScheme(uri);
|
||||
info(`Open this link to view your upload:`);
|
||||
logger.info(chalk.blueBright(url.toString()));
|
||||
const url = storage.resolveScheme(uri);
|
||||
info(
|
||||
`Open this link to view your upload: ${chalk.blueBright(
|
||||
url.toString(),
|
||||
)}`,
|
||||
);
|
||||
} catch (err: any) {
|
||||
if (
|
||||
err.toString() === "No files detected in specified directory" ||
|
||||
err.toString() === "Invalid path provided" ||
|
||||
err.toString() === "No path provided"
|
||||
) {
|
||||
logger.error(
|
||||
chalk.redBright(
|
||||
"Please specify a valid file or directory to upload",
|
||||
),
|
||||
);
|
||||
} else {
|
||||
logger.error(chalk.redBright("Failed to upload files"), err);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
program
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { extractIPFSHashFromBytecode } from "../helpers/ipfs";
|
||||
import { logger } from "../helpers/logger";
|
||||
import { CompileOptions, IBuilder } from "../interfaces/Builder";
|
||||
import { ContractPayload } from "../interfaces/ContractPayload";
|
||||
import { extractIPFSHashFromBytecode } from "@thirdweb-dev/sdk/evm";
|
||||
|
||||
export abstract class BaseBuilder implements IBuilder {
|
||||
abstract compile(
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
import { ProjectType } from "../types/ProjectType";
|
||||
import { Detector } from "./detector";
|
||||
import { existsSync } from "fs";
|
||||
|
||||
export default class NPMDetector implements Detector {
|
||||
public projectType: ProjectType = "npm";
|
||||
|
||||
public matches(path: string): boolean {
|
||||
return existsSync(path + "/package-lock.json");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
import { ProjectType } from "../types/ProjectType";
|
||||
import { Detector } from "./detector";
|
||||
import { existsSync } from "fs";
|
||||
|
||||
export default class ViteDetector implements Detector {
|
||||
public projectType: ProjectType = "vite";
|
||||
|
||||
public matches(path: string): boolean {
|
||||
return (
|
||||
existsSync(path + "/vite.config.js") ||
|
||||
existsSync(path + "/vite.config.ts")
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
import { ProjectType } from "../types/ProjectType";
|
||||
import { Detector } from "./detector";
|
||||
import { existsSync } from "fs";
|
||||
|
||||
export default class YarnDetector implements Detector {
|
||||
public projectType: ProjectType = "yarn";
|
||||
|
||||
public matches(path: string): boolean {
|
||||
return existsSync(path + "/yarn.lock");
|
||||
}
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
import { decodeFirstSync } from "cbor";
|
||||
import { UnixFS } from "ipfs-unixfs";
|
||||
import { DAGNode } from "ipld-dag-pb";
|
||||
import { toB58String } from "multihashes";
|
||||
|
||||
/**
|
||||
* Derives IPFS hash of string
|
||||
* @param {String} str
|
||||
* @return {String} IPFS hash (ex: "Qm")
|
||||
*/
|
||||
export async function getIPFSHash(str: string) {
|
||||
const file = new UnixFS({
|
||||
type: "file",
|
||||
data: Buffer.from(str),
|
||||
});
|
||||
const node = new DAGNode(file.marshal());
|
||||
const metadataLink = await node.toDAGLink();
|
||||
return toB58String(metadataLink.Hash.multihash);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract the IPFS hash from the given bytecode
|
||||
* @param bytecode
|
||||
* @returns
|
||||
*/
|
||||
export function extractIPFSHashFromBytecode(
|
||||
bytecode: string,
|
||||
): string | undefined {
|
||||
const numericBytecode = hexToBytes(bytecode);
|
||||
const cborLength: number =
|
||||
numericBytecode[numericBytecode.length - 2] * 0x100 +
|
||||
numericBytecode[numericBytecode.length - 1];
|
||||
const bytecodeBuffer = Buffer.from(
|
||||
numericBytecode.slice(numericBytecode.length - 2 - cborLength, -2),
|
||||
);
|
||||
const cborData = decodeFirstSync(bytecodeBuffer);
|
||||
if (cborData["ipfs"]) {
|
||||
const uri = toB58String(cborData["ipfs"]);
|
||||
return uri;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function hexToBytes(hex: string | number) {
|
||||
hex = hex.toString(16);
|
||||
if (!hex.startsWith("0x")) {
|
||||
hex = `0x${hex}`;
|
||||
}
|
||||
if (!isHexStrict(hex)) {
|
||||
throw new Error('Given value "' + hex + '" is not a valid hex string.');
|
||||
}
|
||||
|
||||
hex = hex.replace(/^0x/i, "");
|
||||
|
||||
for (var bytes = [], c = 0; c < hex.length; c += 2) {
|
||||
bytes.push(parseInt(hex.slice(c, c + 2), 16));
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
||||
function isHexStrict(hex: string | number) {
|
||||
return (
|
||||
(typeof hex === "string" || typeof hex === "number") &&
|
||||
/^(-)?0x[0-9a-f]*$/i.test(hex.toString())
|
||||
);
|
||||
}
|
||||
@@ -4,4 +4,10 @@ export type ProjectType =
|
||||
| "hardhat"
|
||||
| "truffle"
|
||||
| "solc"
|
||||
| "vite"
|
||||
| "next"
|
||||
| "cra"
|
||||
| "spa-webapp"
|
||||
| "yarn"
|
||||
| "npm"
|
||||
| "none";
|
||||
|
||||
@@ -10,52 +10,67 @@ import chalk from "chalk";
|
||||
import path from "path";
|
||||
import prompts from "prompts";
|
||||
|
||||
let projectType: string = "";
|
||||
let projectPath: string = "";
|
||||
let projectType: string = "";
|
||||
let framework: string = "";
|
||||
let language: string = "";
|
||||
let baseContract: string = "";
|
||||
let chain: string = "";
|
||||
/* let createType: string = "app"; */
|
||||
|
||||
export async function twCreate(options: any) {
|
||||
if (typeof projectPath === "string") {
|
||||
projectPath = projectPath.trim();
|
||||
export async function twCreate(
|
||||
pType: string,
|
||||
pPath: string = "",
|
||||
options: any,
|
||||
) {
|
||||
if (typeof pPath === "string") {
|
||||
projectPath = pPath;
|
||||
}
|
||||
|
||||
if (options.app) {
|
||||
if (pType === "app" || options.app) {
|
||||
projectType = "app";
|
||||
}
|
||||
|
||||
if (options.contract) {
|
||||
} else if (pType === "contract" || options.contract) {
|
||||
projectType = "contract";
|
||||
}
|
||||
|
||||
if (options.typescript) {
|
||||
language = "typescript";
|
||||
if (projectType === "app") {
|
||||
if (options.typescript) {
|
||||
language = "typescript";
|
||||
}
|
||||
|
||||
if (options.javascript) {
|
||||
language = "javascript";
|
||||
}
|
||||
|
||||
if (options.next) {
|
||||
framework = "next";
|
||||
}
|
||||
|
||||
if (options.cra) {
|
||||
framework = "cra";
|
||||
}
|
||||
|
||||
if (options.vite) {
|
||||
framework = "vite";
|
||||
}
|
||||
|
||||
if (options.solana) {
|
||||
chain = "solana";
|
||||
}
|
||||
|
||||
if (options.evm) {
|
||||
chain = "evm";
|
||||
}
|
||||
}
|
||||
|
||||
if (options.javascript) {
|
||||
language = "javascript";
|
||||
}
|
||||
if (projectType === "contract") {
|
||||
if (options.forge) {
|
||||
framework = "forge";
|
||||
}
|
||||
|
||||
if (options.next) {
|
||||
framework = "next";
|
||||
}
|
||||
|
||||
if (options.cra) {
|
||||
framework = "cra";
|
||||
}
|
||||
|
||||
if (options.vite) {
|
||||
framework = "vite";
|
||||
}
|
||||
|
||||
if (options.forge) {
|
||||
framework = "forge";
|
||||
}
|
||||
|
||||
if (options.hardhat) {
|
||||
framework = "hardhat";
|
||||
if (options.hardhat) {
|
||||
framework = "hardhat";
|
||||
}
|
||||
}
|
||||
|
||||
if (options.framework) {
|
||||
@@ -76,7 +91,7 @@ export async function twCreate(options: any) {
|
||||
if (typeof res.projectType === "string") {
|
||||
projectType = res.projectType.trim();
|
||||
}
|
||||
} else if (!projectType && options.template) {
|
||||
} else if (!projectType || options.template) {
|
||||
// If no project type is specified, but a template is, we assume the user wants to create an app.
|
||||
// We do this so old users can still use the --template flag to create an app.
|
||||
projectType = "app";
|
||||
@@ -123,16 +138,42 @@ export async function twCreate(options: any) {
|
||||
}
|
||||
|
||||
if (!options.template) {
|
||||
if (projectType === "app" && !chain) {
|
||||
const res = await prompts({
|
||||
type: "select",
|
||||
name: "chain",
|
||||
message: CREATE_MESSAGES.chain,
|
||||
choices: [
|
||||
{ title: "EVM", value: "evm" },
|
||||
{ title: "Solana", value: "solana" },
|
||||
],
|
||||
});
|
||||
|
||||
if (res.chain === "solana") {
|
||||
chain = "solana";
|
||||
} else {
|
||||
chain = "evm";
|
||||
}
|
||||
}
|
||||
|
||||
if (projectType === "app" && !framework) {
|
||||
const res = await prompts({
|
||||
type: "select",
|
||||
name: "framework",
|
||||
message: CREATE_MESSAGES.framework,
|
||||
choices: [
|
||||
{ title: "Next.js", value: "next" },
|
||||
{ title: "Create React App", value: "cra" },
|
||||
{ title: "Vite", value: "vite" },
|
||||
],
|
||||
choices:
|
||||
// Solana doesn't support Vite just yet:
|
||||
chain === "solana"
|
||||
? [
|
||||
{ title: "Next.js", value: "next" },
|
||||
{ title: "Create React App", value: "cra" },
|
||||
// { title: "Vite", value: "vite" },
|
||||
]
|
||||
: [
|
||||
{ title: "Next.js", value: "next" },
|
||||
{ title: "Create React App", value: "cra" },
|
||||
{ title: "Vite", value: "vite" },
|
||||
],
|
||||
});
|
||||
|
||||
if (typeof res.framework === "string") {
|
||||
@@ -288,6 +329,7 @@ export async function twCreate(options: any) {
|
||||
framework,
|
||||
language,
|
||||
template,
|
||||
chain,
|
||||
});
|
||||
} else {
|
||||
await createContract({
|
||||
|
||||
@@ -22,12 +22,14 @@ export async function createApp({
|
||||
framework,
|
||||
language,
|
||||
template,
|
||||
chain,
|
||||
}: {
|
||||
appPath: string;
|
||||
packageManager: PackageManager;
|
||||
framework?: string;
|
||||
language?: string;
|
||||
template?: string;
|
||||
chain?: string;
|
||||
}): Promise<void> {
|
||||
let frameworkPath = "";
|
||||
|
||||
@@ -43,7 +45,9 @@ export async function createApp({
|
||||
process.exit(1);
|
||||
}
|
||||
} else if (framework) {
|
||||
frameworkPath = `${framework}-${language || "javascript"}-starter`;
|
||||
frameworkPath = `${framework}-${language || "javascript"}-${
|
||||
chain === "solana" ? "solana-" : ""
|
||||
}starter`;
|
||||
const found = await hasTemplate(frameworkPath);
|
||||
|
||||
if (!found) {
|
||||
|
||||
@@ -1,11 +1,26 @@
|
||||
import spawn from "cross-spawn";
|
||||
|
||||
export async function runCommand(command: string, args: string[]) {
|
||||
export async function runCommand(
|
||||
command: string,
|
||||
args: string[],
|
||||
logging: boolean = false,
|
||||
) {
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
/**
|
||||
* Spawn the installation process.
|
||||
*/
|
||||
const child = spawn(command, args);
|
||||
child.stdout?.on("data", (data) => {
|
||||
if (logging) {
|
||||
console.log(data.toString());
|
||||
}
|
||||
});
|
||||
|
||||
child.stderr?.on("error", (err) => {
|
||||
if (logging) {
|
||||
console.error(err);
|
||||
}
|
||||
});
|
||||
child.on("close", (code) => {
|
||||
if (code !== 0) {
|
||||
reject({ command: `${command}` });
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
import NPMDetector from "../core/detection/npm";
|
||||
import ViteDetector from "../core/detection/vite";
|
||||
import YarnDetector from "../core/detection/yarn";
|
||||
import { runCommand } from "../create/helpers/run-command";
|
||||
import { upload } from "../storage/command";
|
||||
import { DEFAULT_IPFS_GATEWAY } from "@thirdweb-dev/sdk";
|
||||
import { ThirdwebStorage } from "@thirdweb-dev/storage";
|
||||
|
||||
export async function deployApp(distPath = "dist", projectPath = ".") {
|
||||
const storage = new ThirdwebStorage();
|
||||
const supportedFrameworks = [new ViteDetector()];
|
||||
|
||||
const possibleProjects = supportedFrameworks
|
||||
.filter((detector) => detector.matches(projectPath))
|
||||
.map((detector) => detector.projectType);
|
||||
|
||||
const hasYarn = new YarnDetector().matches(".");
|
||||
const hasNPM = new NPMDetector().matches(".");
|
||||
|
||||
if (possibleProjects.length === 0) {
|
||||
throw new Error("No supported project detected");
|
||||
}
|
||||
|
||||
try {
|
||||
if (hasYarn) {
|
||||
await runCommand("yarn", ["build"]);
|
||||
} else if (hasNPM) {
|
||||
await runCommand("npm", ["build"]);
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("Can't build project");
|
||||
return Promise.reject("Can't build project");
|
||||
}
|
||||
|
||||
try {
|
||||
let url = await upload(storage, distPath);
|
||||
url = url.replace("ipfs://", DEFAULT_IPFS_GATEWAY);
|
||||
return `${url}/index.html`;
|
||||
} catch (err) {
|
||||
console.error("Can't upload project");
|
||||
return Promise.reject("Can't upload project");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
import { processProject } from "../common/processor";
|
||||
import { info, logger } from "../core/helpers/logger";
|
||||
import generateDashboardUrl from "../helpers/generate-dashboard-url";
|
||||
import { deployApp } from "./app";
|
||||
import chalk from "chalk";
|
||||
|
||||
type DeployOptions = {
|
||||
name: string;
|
||||
contractVersion: string;
|
||||
app: boolean;
|
||||
path?: string;
|
||||
distPath?: string;
|
||||
};
|
||||
|
||||
export async function deploy(options: DeployOptions) {
|
||||
if (options.name) {
|
||||
const url = generateDashboardUrl(options.name, options.contractVersion);
|
||||
|
||||
if (!url) {
|
||||
logger.error(
|
||||
chalk.red(
|
||||
`Could not find a contract named ${options.name} ${
|
||||
options.contractVersion || ""
|
||||
}`,
|
||||
),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
info(`Open this link to deploy your contract: ${chalk.blueBright(url)}`);
|
||||
return url.toString();
|
||||
}
|
||||
|
||||
if (options.app) {
|
||||
try {
|
||||
let url = await deployApp(options.distPath, options.path);
|
||||
info(`Here is the link to your app: ${chalk.blueBright(url.toString())}`);
|
||||
return url.toString();
|
||||
} catch (err) {
|
||||
logger.error("Failed to deploy app, No compatible project found", err);
|
||||
return Promise.reject(
|
||||
"failed to deploy app, no compatible project found",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const url = await processProject(options, "deploy");
|
||||
info(
|
||||
`Open this link to deploy your contracts: ${chalk.blueBright(
|
||||
url.toString(),
|
||||
)}`,
|
||||
);
|
||||
return url.toString();
|
||||
}
|
||||
@@ -1,7 +1,5 @@
|
||||
import { logger } from "../core/helpers/logger";
|
||||
import { spinner } from "../core/helpers/logger";
|
||||
import { BufferOrStringWithName, ThirdwebStorage } from "@thirdweb-dev/storage";
|
||||
import chalk from "chalk";
|
||||
import fs from "fs";
|
||||
import path from "path";
|
||||
|
||||
@@ -33,22 +31,12 @@ export async function upload(
|
||||
uploadPath: string,
|
||||
): Promise<string> {
|
||||
if (!uploadPath) {
|
||||
logger.error(
|
||||
`Please pass a path to a file or directory to upload with the following format:\n ${chalk.blueBright(
|
||||
`npx thirdweb@latest upload path/to/file.jpg`,
|
||||
)}\n`,
|
||||
);
|
||||
process.exit(1);
|
||||
return Promise.reject("No path provided");
|
||||
}
|
||||
|
||||
const pathExists = fs.existsSync(uploadPath);
|
||||
if (!pathExists) {
|
||||
logger.error(
|
||||
`Invalid path ${chalk.blueBright(
|
||||
uploadPath,
|
||||
)} provided. Please provide a valid path to a file or directory to upload."`,
|
||||
);
|
||||
process.exit(1);
|
||||
return Promise.reject("Invalid path provided");
|
||||
}
|
||||
|
||||
let uri = "";
|
||||
@@ -57,12 +45,7 @@ export async function upload(
|
||||
const files = recurseFiles(uploadPath, uploadPath);
|
||||
|
||||
if (files.length === 0) {
|
||||
logger.error(
|
||||
`No files detected in specified directory ${chalk.blueBright(
|
||||
uploadPath,
|
||||
)} to upload.`,
|
||||
);
|
||||
process.exit(1);
|
||||
return Promise.reject("No files detected in specified directory");
|
||||
}
|
||||
|
||||
const spin = spinner(
|
||||
@@ -82,12 +65,7 @@ export async function upload(
|
||||
uri = await storage.upload(file, { uploadWithoutDirectory: true });
|
||||
spin.succeed("Succesfully uploaded file to IPFS.");
|
||||
} else {
|
||||
logger.error(
|
||||
`Path ${chalk.blueBright(
|
||||
uploadPath,
|
||||
)} does not point to a valid file or directory. Please provide a valid path to a file or directory to upload`,
|
||||
);
|
||||
process.exit(1);
|
||||
return Promise.reject("Invalid path provided");
|
||||
}
|
||||
|
||||
return uri;
|
||||
|
||||
@@ -1,5 +1,19 @@
|
||||
# @thirdweb-dev/contracts-js
|
||||
|
||||
## 1.2.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#376](https://github.com/thirdweb-dev/js/pull/376) [`4af785c`](https://github.com/thirdweb-dev/js/commit/4af785c37c831ecd7087c1c9eb9095922cac0855) Thanks [@adam-maj](https://github.com/adam-maj)! - Update tiered-drop with tokens claimed
|
||||
|
||||
- [#373](https://github.com/thirdweb-dev/js/pull/373) [`6f818f3`](https://github.com/thirdweb-dev/js/commit/6f818f393eb9023b53a3358d62d60ec23a9246bd) Thanks [@adam-maj](https://github.com/adam-maj)! - Update tiered-drop contract version
|
||||
|
||||
## 1.2.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- [#333](https://github.com/thirdweb-dev/js/pull/333) [`aa6d9ed`](https://github.com/thirdweb-dev/js/commit/aa6d9ed75d126d7a0cca9fb8fc389ff94e9d1e14) Thanks [@joaquim-verges](https://github.com/joaquim-verges)! - Update to contracts package v3.2.0
|
||||
|
||||
## 1.1.9
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"main": "dist/thirdweb-dev-contracts-js-factories-TWMultichainRegistry__factory.cjs.js",
|
||||
"module": "dist/thirdweb-dev-contracts-js-factories-TWMultichainRegistry__factory.esm.js"
|
||||
}
|
||||
@@ -1,19 +1,19 @@
|
||||
{
|
||||
"name": "@thirdweb-dev/contracts-js",
|
||||
"version": "1.1.9",
|
||||
"version": "1.2.1",
|
||||
"main": "dist/thirdweb-dev-contracts-js.cjs.js",
|
||||
"module": "dist/thirdweb-dev-contracts-js.esm.js",
|
||||
"license": "Apache-2.0",
|
||||
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/contracts-js",
|
||||
"dependencies": {
|
||||
"@thirdweb-dev/contracts": "3.1.8-0"
|
||||
"@thirdweb-dev/contracts": "^3.2.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/preset-env": "^7.18.10",
|
||||
"@babel/preset-typescript": "^7.18.6",
|
||||
"@preconstruct/cli": "^2.2.1",
|
||||
"@typechain/ethers-v5": "10.0.0",
|
||||
"ethers": "^5.7.0",
|
||||
"ethers": "^5.7.2",
|
||||
"typechain": "^8.1.0",
|
||||
"typescript": "^4.7.4"
|
||||
},
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
"dependencies": {
|
||||
"@typescript-eslint/eslint-plugin": "^5.33.0",
|
||||
"@typescript-eslint/parser": "^5.33.0",
|
||||
"eslint-config-next": "^12.0.8",
|
||||
"eslint-config-next": "12.3.1",
|
||||
"eslint-config-prettier": "^8.3.0",
|
||||
"eslint-config-turbo": "latest",
|
||||
"eslint-plugin-react": "^7.28.0"
|
||||
|
||||
@@ -1,5 +1,120 @@
|
||||
# @thirdweb-dev/react
|
||||
|
||||
## 3.6.3
|
||||
|
||||
## 3.6.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#405](https://github.com/thirdweb-dev/js/pull/405) [`ccb7db4`](https://github.com/thirdweb-dev/js/commit/ccb7db48739b8dddcb2c032b3b6e3e5200485715) Thanks [@nachoiacovino](https://github.com/nachoiacovino)! - Add updateAll param to creators and royalty update hooks for Solana
|
||||
|
||||
## 3.6.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#392](https://github.com/thirdweb-dev/js/pull/392) [`846022e`](https://github.com/thirdweb-dev/js/commit/846022e2cfb12b846aae029b85899fb72fd2c9ad) Thanks [@nachoiacovino](https://github.com/nachoiacovino)! - Fix unlimited price for useActiveClaimConditionForWallet
|
||||
|
||||
- [#388](https://github.com/thirdweb-dev/js/pull/388) [`7c0744a`](https://github.com/thirdweb-dev/js/commit/7c0744a006e78987ad8b271b2c64f4bac7759510) Thanks [@adam-maj](https://github.com/adam-maj)! - Add support for total supply and pagination on get all
|
||||
|
||||
## 3.6.0
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#386](https://github.com/thirdweb-dev/js/pull/386) [`612bcdd`](https://github.com/thirdweb-dev/js/commit/612bcdd16fc242d8b04bc70d609e44b0df47ed3f) Thanks [@jnsdls](https://github.com/jnsdls)! - [Gnosis Connector] - switch to safe.global hostname & add support for bsc and optimism chains
|
||||
|
||||
- [#364](https://github.com/thirdweb-dev/js/pull/364) [`7cb8e59`](https://github.com/thirdweb-dev/js/commit/7cb8e59be48dc923316eb36ab43a1bef7364f6b1) Thanks [@joaquim-verges](https://github.com/joaquim-verges)! - Add experimental `useActiveClaimConditionForWallet()` hook
|
||||
|
||||
## 3.5.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#369](https://github.com/thirdweb-dev/js/pull/369) [`2d3fca5`](https://github.com/thirdweb-dev/js/commit/2d3fca52373046c88392139922e9c9da79f9a2d4) Thanks [@nachoiacovino](https://github.com/nachoiacovino)! - Add useClaimerProofs hook
|
||||
|
||||
- [#378](https://github.com/thirdweb-dev/js/pull/378) [`32d91ef`](https://github.com/thirdweb-dev/js/commit/32d91ef709c8fb92a903e52c65b27538a80ea4eb) Thanks [@mykcryptodev](https://github.com/mykcryptodev)! - round borders for buttons and menus on safari
|
||||
|
||||
- [#377](https://github.com/thirdweb-dev/js/pull/377) [`b79dc18`](https://github.com/thirdweb-dev/js/commit/b79dc18f7ab5155bbf4af02dc1a953546160bad0) Thanks [@adam-maj](https://github.com/adam-maj)! - Add event filters
|
||||
|
||||
## 3.5.1
|
||||
|
||||
## 3.5.0
|
||||
|
||||
## 3.4.5
|
||||
|
||||
## 3.4.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#356](https://github.com/thirdweb-dev/js/pull/356) [`cc4613b`](https://github.com/thirdweb-dev/js/commit/cc4613b5fd69840f4f9cfd0ac1c4e6743e62fe52) Thanks [@nachoiacovino](https://github.com/nachoiacovino)! - Add Pack and Multiwrap as NFTContract types
|
||||
|
||||
## 3.4.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#353](https://github.com/thirdweb-dev/js/pull/353) [`1c24c3c`](https://github.com/thirdweb-dev/js/commit/1c24c3c3c48476a824f817e09e7bf0fbe67c1db5) Thanks [@nachoiacovino](https://github.com/nachoiacovino)! - Add useUpdateCreators hook, fix CreatorInput schema
|
||||
|
||||
## 3.4.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#348](https://github.com/thirdweb-dev/js/pull/348) [`7d9a4c6`](https://github.com/thirdweb-dev/js/commit/7d9a4c6abcad1b4f43e431ce7b0b38db9016ea9a) Thanks [@nachoiacovino](https://github.com/nachoiacovino)! - [SOL] - add `useUpdateRoyaltySettings()` hook
|
||||
[SOL] - change `useRoyalty()` hook -> `useRoyaltySettings()` for consistency
|
||||
|
||||
- [#352](https://github.com/thirdweb-dev/js/pull/352) [`3522917`](https://github.com/thirdweb-dev/js/commit/352291791ee900e1500f84f095290497934d2f60) Thanks [@joaquim-verges](https://github.com/joaquim-verges)! - expose useExecuteAuctionSale and useAcceptDirectListingOffer
|
||||
|
||||
- [#351](https://github.com/thirdweb-dev/js/pull/351) [`aabbb14`](https://github.com/thirdweb-dev/js/commit/aabbb149e81d6824015a4797b2b6c929ca359545) Thanks [@jnsdls](https://github.com/jnsdls)! - [EVM] - fix wallet connection during dev (hot reload)
|
||||
|
||||
## 3.4.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#343](https://github.com/thirdweb-dev/js/pull/343) [`72227b2`](https://github.com/thirdweb-dev/js/commit/72227b2e166a3a68bbb41cf2b389322f5b7547a2) Thanks [@joaquim-verges](https://github.com/joaquim-verges)! - Expose new useOffers and useMakeOffer hooks
|
||||
|
||||
## 3.4.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- [#327](https://github.com/thirdweb-dev/js/pull/327) [`ef27aad`](https://github.com/thirdweb-dev/js/commit/ef27aad0aafc4577e85f44dc77dfbe880bd239b5) Thanks [@jnsdls](https://github.com/jnsdls)! - Gnosis Safe and Magic Link connectors are no longer included in the default export. They are now available as named exports instead.
|
||||
|
||||
## Gnosis Safe
|
||||
|
||||
### Connector
|
||||
|
||||
```diff
|
||||
- import { GnosisSafeConnector } from "@thirdweb-dev/react";
|
||||
+ import { GnosisSafeConnector } from "@thirdweb-dev/react/evm/connectors/gnosis-safe";
|
||||
```
|
||||
|
||||
### Hook
|
||||
|
||||
```diff
|
||||
- import { useGnosis } from "@thirdweb-dev/react";
|
||||
+ import { useGnosis } from "@thirdweb-dev/react/evm/connectors/gnosis-safe";
|
||||
```
|
||||
|
||||
## Magic Link
|
||||
|
||||
### Connector
|
||||
|
||||
```diff
|
||||
- import { MagicLink } from "@thirdweb-dev/react";
|
||||
+ import { MagicConnector } from "@thirdweb-dev/react/evm/connectors/magic";
|
||||
```
|
||||
|
||||
### Hook
|
||||
|
||||
```diff
|
||||
- import { useMagic } from "@thirdweb-dev/react";
|
||||
+ import { useMagic } from "@thirdweb-dev/react/evm/connectors/magic";
|
||||
```
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#339](https://github.com/thirdweb-dev/js/pull/339) [`b03a902`](https://github.com/thirdweb-dev/js/commit/b03a9021451b79f802f682f66e5ae8e9355d7e6f) Thanks [@nachoiacovino](https://github.com/nachoiacovino)! - Fix docs for some functions
|
||||
|
||||
## 3.3.1
|
||||
|
||||
## 3.3.0
|
||||
|
||||
## 3.2.6
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -26,11 +26,11 @@ The `useContractCall` hook to call a smart contract function has been renamed to
|
||||
|
||||
### Prebuilt Contract Hooks
|
||||
|
||||
Hooks to connect to prebuilt contracts such as `useNFTDrop` and `useMarketplace` are now deprecated in favour of using the generic `useContract` hook:
|
||||
Hooks to connect to prebuilt contracts such as `useNFTDrop` and `useMarketplace` are now deprecated in favour of using the generic `useContract` hook followed by the contract type:
|
||||
|
||||
```diff
|
||||
- const contract = useNFTDrop("0x...")
|
||||
+ const { contract } = useContract("0x...")
|
||||
+ const { contract } = useContract("0x...", "nft-drop")
|
||||
```
|
||||
|
||||
You can currently still continue to use the prebuilt hooks, however they provide a warning in the console informing you of their deprecation. We will likely remove these hooks in a future version of the SDK.
|
||||
|
||||
@@ -191,7 +191,7 @@ export default function Home() {
|
||||
<div>
|
||||
{nfts.map((nft) => (
|
||||
<ThirdwebNftMedia
|
||||
key={nft.tokenId}
|
||||
key={nft.metadata.id}
|
||||
metadata={nft.metadata}
|
||||
height={200}
|
||||
/>
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"main": "dist/thirdweb-dev-react-evm-connectors-gnosis-safe.cjs.js",
|
||||
"module": "dist/thirdweb-dev-react-evm-connectors-gnosis-safe.esm.js"
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"main": "dist/thirdweb-dev-react-evm-connectors-magic.cjs.js",
|
||||
"module": "dist/thirdweb-dev-react-evm-connectors-magic.esm.js"
|
||||
}
|
||||
+21
-19
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@thirdweb-dev/react",
|
||||
"version": "3.2.6",
|
||||
"version": "3.6.3",
|
||||
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/react",
|
||||
"author": "thirdweb eng <[email protected]>",
|
||||
"license": "Apache-2.0",
|
||||
@@ -20,6 +20,14 @@
|
||||
"module": "./solana/dist/thirdweb-dev-react-solana.esm.js",
|
||||
"default": "./solana/dist/thirdweb-dev-react-solana.cjs.js"
|
||||
},
|
||||
"./evm/connectors/magic": {
|
||||
"module": "./evm/connectors/magic/dist/thirdweb-dev-react-evm-connectors-magic.esm.js",
|
||||
"default": "./evm/connectors/magic/dist/thirdweb-dev-react-evm-connectors-magic.cjs.js"
|
||||
},
|
||||
"./evm/connectors/gnosis-safe": {
|
||||
"module": "./evm/connectors/gnosis-safe/dist/thirdweb-dev-react-evm-connectors-gnosis-safe.esm.js",
|
||||
"default": "./evm/connectors/gnosis-safe/dist/thirdweb-dev-react-evm-connectors-gnosis-safe.cjs.js"
|
||||
},
|
||||
"./package.json": "./package.json"
|
||||
},
|
||||
"files": [
|
||||
@@ -31,7 +39,8 @@
|
||||
"entrypoints": [
|
||||
"index.ts",
|
||||
"solana/index.ts",
|
||||
"evm/index.ts"
|
||||
"evm/index.ts",
|
||||
"evm/connectors/**.ts"
|
||||
],
|
||||
"___experimentalFlags_WILL_CHANGE_IN_PATCH": {
|
||||
"exports": true
|
||||
@@ -49,13 +58,11 @@
|
||||
"generate-docs:solana": "api-extractor run --local --config ./config/api-extractor-solana.json && api-documenter markdown -i ./temp -o ./docs/solana && rm -rf ./temp-solana && mv ./temp ./temp-solana",
|
||||
"generate-snippets": "node ./scripts/generate-snippets-evm.mjs && node ./scripts/generate-snippets-solana.mjs && node ./scripts/generate-feature-snippets-evm.mjs",
|
||||
"build": "tsc && preconstruct build",
|
||||
"e2e": "yarn test-ct",
|
||||
"test-ct": "playwright test -c playwright-ct.config.ts",
|
||||
"push": "yalc push"
|
||||
},
|
||||
"sideEffects:": false,
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.18.10",
|
||||
"@babel/core": "^7.19.3",
|
||||
"@babel/preset-env": "^7.18.10",
|
||||
"@babel/preset-react": "^7.18.6",
|
||||
"@babel/preset-typescript": "^7.18.6",
|
||||
@@ -63,15 +70,12 @@
|
||||
"@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",
|
||||
"@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",
|
||||
"@solana/web3.js": "^1.62.0",
|
||||
"@thirdweb-dev/sdk": "*",
|
||||
"@thirdweb-dev/solana": "*",
|
||||
"@types/color": "^3.0.3",
|
||||
"@types/mime": "^3.0.1",
|
||||
"@types/react": "^18.0.5",
|
||||
@@ -84,7 +88,7 @@
|
||||
"eslint-plugin-inclusive-language": "^2.2.0",
|
||||
"eslint-plugin-prettier": "^4.2.1",
|
||||
"eslint-plugin-tsdoc": "^0.2.16",
|
||||
"ethers": "^5.7.1",
|
||||
"ethers": "^5.7.2",
|
||||
"prettier": "^2.7.1",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
@@ -93,13 +97,14 @@
|
||||
"dependencies": {
|
||||
"@emotion/react": "^11.10.0",
|
||||
"@emotion/styled": "^11.10.0",
|
||||
"@gnosis.pm/safe-core-sdk": "2.1.0",
|
||||
"@gnosis.pm/safe-ethers-adapters": "0.1.0-alpha.9",
|
||||
"@gnosis.pm/safe-ethers-lib": "1.1.0",
|
||||
"@gnosis.pm/safe-core-sdk": "^3.1.1",
|
||||
"@gnosis.pm/safe-ethers-adapters": "0.1.0-alpha.11",
|
||||
"@gnosis.pm/safe-ethers-lib": "^1.6.1",
|
||||
"@react-icons/all-files": "^4.1.0",
|
||||
"@solana/wallet-adapter-phantom": "^0.9.17",
|
||||
"@tanstack/react-query": "^4.0.10",
|
||||
"@zag-js/menu": "0.1.14",
|
||||
"@zag-js/react": "0.1.16",
|
||||
"@zag-js/menu": "^0.1.16",
|
||||
"@zag-js/react": "^0.1.18",
|
||||
"buffer": "^6.0.3",
|
||||
"color": "^4.2.3",
|
||||
"copy-to-clipboard": "^3.3.2",
|
||||
@@ -114,7 +119,7 @@
|
||||
"@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",
|
||||
"@solana/web3.js": "^1.62.0",
|
||||
"@thirdweb-dev/sdk": "*",
|
||||
"ethers": ">=5.5.1",
|
||||
"react": ">=18.0.0",
|
||||
@@ -136,9 +141,6 @@
|
||||
},
|
||||
"@solana/web3.js": {
|
||||
"optional": true
|
||||
},
|
||||
"@thirdweb-dev/solana": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
import type { PlaywrightTestConfig } from "@playwright/experimental-ct-react";
|
||||
import { devices } from "@playwright/experimental-ct-react";
|
||||
|
||||
/**
|
||||
* See https://playwright.dev/docs/test-configuration.
|
||||
*/
|
||||
const config: PlaywrightTestConfig = {
|
||||
testDir: "./",
|
||||
/* The base directory, relative to the config file, for snapshot files created with toMatchSnapshot and toHaveScreenshot. */
|
||||
snapshotDir: "./__snapshots__",
|
||||
/* Maximum time one test can run for. */
|
||||
timeout: 10 * 1000,
|
||||
/* Run tests in files in parallel */
|
||||
fullyParallel: true,
|
||||
/* Fail the build on CI if you accidentally left test.only in the source code. */
|
||||
forbidOnly: !!process.env.CI,
|
||||
/* Retry on CI only */
|
||||
retries: process.env.CI ? 2 : 0,
|
||||
/* Opt out of parallel tests on CI. */
|
||||
// workers: process.env.CI ? 1 : undefined,
|
||||
// we can use parallel tests because we have more cores now
|
||||
workers: undefined,
|
||||
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
|
||||
reporter: "html",
|
||||
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
|
||||
use: {
|
||||
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
|
||||
trace: "on-first-retry",
|
||||
|
||||
/* Port to use for Playwright component endpoint. */
|
||||
ctPort: 3100,
|
||||
},
|
||||
|
||||
/* Configure projects for major browsers */
|
||||
projects: [
|
||||
{
|
||||
name: "chromium",
|
||||
use: {
|
||||
...devices["Desktop Chrome"],
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "firefox",
|
||||
use: {
|
||||
...devices["Desktop Firefox"],
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "webkit",
|
||||
use: {
|
||||
...devices["Desktop Safari"],
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export default config;
|
||||
@@ -1,4 +0,0 @@
|
||||
// Import styles, initialize component theme here.
|
||||
// import '../src/common.css';
|
||||
|
||||
export {};
|
||||
@@ -1,15 +0,0 @@
|
||||
import { ConnectWallet } from ".";
|
||||
import { ThirdwebProvider } from "../../providers/full";
|
||||
import { test, expect } from "@playwright/experimental-ct-react";
|
||||
|
||||
test.use({ viewport: { width: 500, height: 500 } });
|
||||
|
||||
test("should render the connect wallet button", async ({ mount }) => {
|
||||
const component = await mount(
|
||||
<ThirdwebProvider desiredChainId={1}>
|
||||
<ConnectWallet />
|
||||
</ThirdwebProvider>,
|
||||
);
|
||||
|
||||
await expect(component).toContainText("Connect Wallet");
|
||||
});
|
||||
@@ -144,7 +144,7 @@ export const ConnectWallet: React.FC<ConnectWalletProps> = ({
|
||||
},
|
||||
connect,
|
||||
] = useConnect();
|
||||
const disconnect = useDisconnect({ reconnectAfterGnosis: false });
|
||||
const disconnect = useDisconnect({ reconnectPrevious: false });
|
||||
|
||||
const supportedConnectors = connectors.filter((c) =>
|
||||
SUPPORTED_CONNECTORS.includes(c.id as typeof SUPPORTED_CONNECTORS[number]),
|
||||
|
||||
@@ -13,12 +13,14 @@ export interface ThirdwebNftMediaProps extends SharedMediaProps {
|
||||
}
|
||||
|
||||
/**
|
||||
* This component can be used to render NFTs from the thirdweb SDK.
|
||||
* Props: {@link ThirdwebNftMediaProps}
|
||||
*
|
||||
* @example
|
||||
* ```jsx
|
||||
* import { ThirdwebNftMedia, useNFTCollection, useNFT } from "@thirdweb-dev/react";
|
||||
* import { ThirdwebNftMedia, useContract, useNFT } from "@thirdweb-dev/react";
|
||||
* export default function NFTCollectionRender() {
|
||||
* const contract = useNFTCollection(<your-contract-address>);
|
||||
* const { contract } = useContract(<your-contract-address>);
|
||||
* const { data: nft, isLoading } = useNFT(contract, 0);
|
||||
*
|
||||
* return (
|
||||
@@ -32,11 +34,6 @@ export interface ThirdwebNftMediaProps extends SharedMediaProps {
|
||||
* );
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* 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
|
||||
* @beta
|
||||
*/
|
||||
export const ThirdwebNftMedia = React.forwardRef<
|
||||
HTMLMediaElement,
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
import { Web3Button } from ".";
|
||||
import { ThirdwebProvider } from "../../providers/full";
|
||||
import { test, expect } from "@playwright/experimental-ct-react";
|
||||
|
||||
test.use({ viewport: { width: 500, height: 500 } });
|
||||
|
||||
test("should render the connect wallet button", async ({ mount }) => {
|
||||
const component = await mount(
|
||||
<ThirdwebProvider desiredChainId={1}>
|
||||
<Web3Button contractAddress="0x123" action={() => undefined}>
|
||||
Do the thing
|
||||
</Web3Button>
|
||||
</ThirdwebProvider>,
|
||||
);
|
||||
await expect(component).toContainText("Connect Wallet");
|
||||
});
|
||||
@@ -37,8 +37,19 @@ const BaseButton = styled.button<BaseButtonProps>`
|
||||
cursor: not-allowed;
|
||||
}
|
||||
&:focus {
|
||||
outline: 2px solid ${(props) => (props.theme as TwUiTheme).colors.accent};
|
||||
outline-offset: 1px;
|
||||
position: relative;
|
||||
border-radius: 0.5em;
|
||||
outline: 0;
|
||||
}
|
||||
&:focus:after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: -5px;
|
||||
right: -5px;
|
||||
bottom: -5px;
|
||||
left: -5px;
|
||||
border: 2px solid ${(props) => (props.theme as TwUiTheme).colors.accent};
|
||||
border-radius: 11px;
|
||||
}
|
||||
`;
|
||||
|
||||
|
||||
@@ -8,10 +8,23 @@ export const Menu = styled.ul<MenuProps>`
|
||||
margin: 0;
|
||||
background: ${(props) => (props.theme as TwUiTheme).colors.background};
|
||||
color: ${(props) => (props.theme as TwUiTheme).colors.text};
|
||||
outline-color: ${(props) => (props.theme as TwUiTheme).colors.accent};
|
||||
outline-style: solid;
|
||||
outline-offset: 0px;
|
||||
list-style: none;
|
||||
border-radius: 0.5em;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
pointer-events: auto;
|
||||
&:focus {
|
||||
outline: 0;
|
||||
}
|
||||
&:after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
border: 1px solid ${(props) => (props.theme as TwUiTheme).colors.accent};
|
||||
border-radius: 0.5em;
|
||||
pointer-events: none;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
`;
|
||||
|
||||
@@ -1,14 +1,29 @@
|
||||
import { ChainId } from "@thirdweb-dev/sdk";
|
||||
import { useConnect } from "../hooks/wagmi-required/useConnect";
|
||||
import { Signer, ethers, utils } from "ethers";
|
||||
import invariant from "tiny-invariant";
|
||||
import { Chain, Connector, ConnectorData, normalizeChainId } from "wagmi";
|
||||
import {
|
||||
Chain,
|
||||
Connector,
|
||||
ConnectorData,
|
||||
normalizeChainId,
|
||||
useContext as useWagmiContext,
|
||||
} from "wagmi";
|
||||
|
||||
// exerpt from https://docs.gnosis-safe.io/backend/available-services
|
||||
const CHAIN_ID_TO_GNOSIS_SERVER_URL = {
|
||||
[ChainId.Mainnet]: "https://safe-transaction.mainnet.gnosis.io",
|
||||
[ChainId.Avalanche]: "https://safe-transaction.avalanche.gnosis.io",
|
||||
[ChainId.Polygon]: "https://safe-transaction.polygon.gnosis.io",
|
||||
[ChainId.Goerli]: "https://safe-transaction.goerli.gnosis.io",
|
||||
};
|
||||
// mainnet
|
||||
1: "https://safe-transaction-mainnet.safe.global",
|
||||
// avalanche
|
||||
43114: "https://safe-transaction-avalanche.safe.global",
|
||||
// polygon
|
||||
137: "https://safe-transaction-polygon.safe.global",
|
||||
// goerli
|
||||
5: "https://safe-transaction-goerli.safe.global",
|
||||
// bsc
|
||||
56: "https://safe-transaction-bsc.safe.global",
|
||||
// optimism
|
||||
10: "https://safe-transaction-optimism.safe.global",
|
||||
} as const;
|
||||
|
||||
export interface GnosisConnectorArguments {
|
||||
safeAddress: string;
|
||||
@@ -18,6 +33,8 @@ export interface GnosisConnectorArguments {
|
||||
const __IS_SERVER__ = typeof window === "undefined";
|
||||
|
||||
export class GnosisSafeConnector extends Connector {
|
||||
static supportedChains = Object.keys(CHAIN_ID_TO_GNOSIS_SERVER_URL);
|
||||
public supportedChains = GnosisSafeConnector.supportedChains;
|
||||
id = "gnosis";
|
||||
ready = __IS_SERVER__;
|
||||
name = "Gnosis Safe";
|
||||
@@ -50,6 +67,11 @@ export class GnosisSafeConnector extends Connector {
|
||||
};
|
||||
}
|
||||
|
||||
public isChainSupported(chainId: string | number) {
|
||||
const id = normalizeChainId(chainId);
|
||||
return !this.isChainUnsupported(id);
|
||||
}
|
||||
|
||||
private async createSafeSigner() {
|
||||
const signer = await this.previousConnector?.getSigner();
|
||||
const safeAddress = this.config?.safeAddress;
|
||||
@@ -163,3 +185,67 @@ export class GnosisSafeConnector extends Connector {
|
||||
this.config = config;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook for connecting to a Gnosis Safe. This enables multisig wallets to connect to your application and sing transactions.
|
||||
*
|
||||
* ```javascript
|
||||
* import { useGnosis } from "@thirdweb-dev/react"
|
||||
* ```
|
||||
*
|
||||
*
|
||||
* @example
|
||||
* ```javascript
|
||||
* import { useGnosis } from "@thirdweb-dev/react"
|
||||
*
|
||||
* const App = () => {
|
||||
* const connectWithGnosis = useGnosis()
|
||||
*
|
||||
* return (
|
||||
* <button onClick={() => connectWithGnosis({ safeAddress: "0x...", safeChainId: 1 })}>
|
||||
* Connect Gnosis Safe
|
||||
* </button>
|
||||
* )
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @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");
|
||||
}
|
||||
const connector = connectors.data.connectors.find((c) => c.id === "gnosis");
|
||||
invariant(
|
||||
connector,
|
||||
"Gnosis connector not found, please make sure it is provided to your <ThirdwebProvider />",
|
||||
);
|
||||
|
||||
return async (config: GnosisConnectorArguments) => {
|
||||
const previousConnector = connectors.data.connector;
|
||||
const previousConnectorChain = await previousConnector?.getChainId();
|
||||
invariant(
|
||||
!!previousConnector,
|
||||
"Cannot connect to Gnosis Safe without first being connected to a personal wallet.",
|
||||
);
|
||||
invariant(
|
||||
previousConnectorChain === config.safeChainId,
|
||||
"Gnosis safe chain id must match personal wallet chain id.",
|
||||
);
|
||||
invariant(
|
||||
utils.isAddress(config.safeAddress),
|
||||
"Gnosis safe address must be a valid address.",
|
||||
);
|
||||
(connector as GnosisSafeConnector).setConfiguration(
|
||||
previousConnector,
|
||||
config,
|
||||
);
|
||||
return connect(connector);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { useConnect } from "../hooks/wagmi-required/useConnect";
|
||||
import { providers, utils } from "ethers";
|
||||
import type {
|
||||
LoginWithMagicLinkConfiguration,
|
||||
@@ -5,7 +6,12 @@ import type {
|
||||
MagicSDKAdditionalConfiguration,
|
||||
} from "magic-sdk";
|
||||
import invariant from "tiny-invariant";
|
||||
import { Chain, Connector, normalizeChainId } from "wagmi";
|
||||
import {
|
||||
Chain,
|
||||
Connector,
|
||||
normalizeChainId,
|
||||
useContext as useWagmiContext,
|
||||
} from "wagmi";
|
||||
|
||||
export interface MagicConnectorArguments
|
||||
extends MagicSDKAdditionalConfiguration {
|
||||
@@ -186,3 +192,89 @@ export class MagicConnector extends Connector {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook for connecting to an email wallet using magic link.
|
||||
* This enables users without their own wallets to connect to your application and sign transactions securely using their email.
|
||||
*
|
||||
* ```javascript
|
||||
* import { useMagic } from "@thirdweb-dev/react"
|
||||
* ```
|
||||
*
|
||||
*
|
||||
* @example
|
||||
* Before using this hook, you first need to set up the magic configuration in your `ThirdwebProvider`, including your magic API key.
|
||||
*
|
||||
* ```javascript
|
||||
* // Add the magic configuration object to your wallet connectors
|
||||
* const connectors = [
|
||||
* "metamask",
|
||||
* "walletConnect",
|
||||
* "walletLink",
|
||||
* {
|
||||
* name: "magic",
|
||||
* options: {
|
||||
* apiKey: "your-magic-api-key",
|
||||
* }
|
||||
* }
|
||||
* ]
|
||||
*
|
||||
* // Add the above to the walletConnectors prop of your <ThirdwebProvider />
|
||||
* const Provider = ({ children }) => (
|
||||
* return (
|
||||
* <ThirdwebProvider
|
||||
* walletConnectors={connectors}
|
||||
* // Specify remaining parameters
|
||||
* ...
|
||||
* >
|
||||
* {children}
|
||||
* </ThirdwebProvider>
|
||||
* )
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* In order to use the hook to connect users with magic link, you just need to provide the users email to the connect function.
|
||||
*
|
||||
* You can setup the hook with the following configuration:
|
||||
* ```javascript
|
||||
* import { useMagic } from "@thirdweb-dev/react"
|
||||
* import { useState } from "react"
|
||||
*
|
||||
* const LoginWithMagicLink = () => {
|
||||
* const connectWithMagic = useMagic()
|
||||
* const [email, setEmail] = useState()
|
||||
*
|
||||
* return (
|
||||
* <div>
|
||||
* <input value={email} onChange={(e) => setEmail(e.target.value)} />
|
||||
* <button onClick={() => connectWithMagic({ email })}>Login</button>
|
||||
* </div>
|
||||
* )
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @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");
|
||||
}
|
||||
|
||||
const connector = connectors.data.connectors.find((c) => c.id === "magic");
|
||||
|
||||
invariant(
|
||||
connector,
|
||||
"Magic connector not found, please make sure it is provided to your <ThirdwebProvider />",
|
||||
);
|
||||
|
||||
return (configuration: LoginWithMagicLinkConfiguration) => {
|
||||
(connector as MagicConnector).setConfiguration(configuration);
|
||||
return connect(connector);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -33,7 +33,17 @@ export const ThirdwebConnectedWalletProvider: React.FC<
|
||||
const { rpcUrlMap } = useThirdwebConfigContext();
|
||||
|
||||
const [contextValue, setContextValue] =
|
||||
useState<ThirdwebConnectedWalletContext>(INITIAL_CONTEXT_VALUE);
|
||||
useState<ThirdwebConnectedWalletContext>({
|
||||
...INITIAL_CONTEXT_VALUE,
|
||||
signer: signer ? signer : undefined,
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
setContextValue((val) => ({
|
||||
...val,
|
||||
signer: signer ? signer : undefined,
|
||||
}));
|
||||
}, [signer]);
|
||||
|
||||
useEffect(() => {
|
||||
let s = signer;
|
||||
|
||||
@@ -2,7 +2,7 @@ import {
|
||||
RequiredParam,
|
||||
requiredParamInvariant,
|
||||
} from "../../../core/query-utils/required-param";
|
||||
import { useSDKChainId } from "../../providers/base";
|
||||
import { useSDK, useSDKChainId } from "../../providers/base";
|
||||
import { getErcs, DropContract, WalletAddress } from "../../types";
|
||||
import {
|
||||
cacheKeys,
|
||||
@@ -10,8 +10,16 @@ import {
|
||||
} from "../../utils/cache-keys";
|
||||
import { useQueryWithNetwork } from "../query-utils/useQueryWithNetwork";
|
||||
import { useMutation, useQueryClient } from "@tanstack/react-query";
|
||||
import { ClaimCondition, ClaimConditionInput } from "@thirdweb-dev/sdk";
|
||||
import { BigNumberish } from "ethers";
|
||||
import {
|
||||
ClaimCondition,
|
||||
ClaimConditionFetchOptions,
|
||||
ClaimConditionInput,
|
||||
SnapshotEntryWithProof,
|
||||
fetchCurrencyValue,
|
||||
convertToReadableQuantity,
|
||||
fetchCurrencyMetadata,
|
||||
} from "@thirdweb-dev/sdk";
|
||||
import { BigNumberish, constants, utils } from "ethers";
|
||||
import invariant from "tiny-invariant";
|
||||
|
||||
/**
|
||||
@@ -41,7 +49,7 @@ export type SetClaimConditionsParams = {
|
||||
/** **********************/
|
||||
|
||||
/**
|
||||
* Use this to get the active claim conditon for ERC20, ERC721 or ERC1155 based contracts. They need to extend the `claimCondition` extension for this hook to work.
|
||||
* Use this to get the active claim condition for ERC20, ERC721 or ERC1155 based contracts. They need to extend the `claimCondition` extension for this hook to work.
|
||||
*
|
||||
* @example
|
||||
* ```javascript
|
||||
@@ -56,7 +64,7 @@ export type SetClaimConditionsParams = {
|
||||
* const { data: activeClaimCondition, isLoading, error } = useActiveClaimCondition(<YourERC1155ContractInstance>, <tokenId>);
|
||||
* ```
|
||||
*
|
||||
* @param contract - an instance of a contract that extends the ERC721 or ERC1155 spec and implements the `claimConditions` extension.
|
||||
* @param contract - an instance of a contract that extends the ERC721, ERC1155 or ERC20 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
|
||||
@@ -65,25 +73,30 @@ export type SetClaimConditionsParams = {
|
||||
export function useActiveClaimCondition(
|
||||
contract: RequiredParam<DropContract>,
|
||||
tokenId?: BigNumberish,
|
||||
options?: ClaimConditionFetchOptions,
|
||||
) {
|
||||
const contractAddress = contract?.getAddress();
|
||||
const { erc1155, erc721, erc20 } = getErcs(contract);
|
||||
|
||||
return useQueryWithNetwork(
|
||||
cacheKeys.extensions.claimConditions.getActive(contractAddress, tokenId),
|
||||
cacheKeys.extensions.claimConditions.getActive(
|
||||
contractAddress,
|
||||
tokenId,
|
||||
options,
|
||||
),
|
||||
() => {
|
||||
if (erc1155) {
|
||||
requiredParamInvariant(
|
||||
tokenId,
|
||||
"tokenId is required for ERC1155 claim conditions",
|
||||
);
|
||||
return erc1155.claimConditions.getActive(tokenId);
|
||||
return erc1155.claimConditions.getActive(tokenId, options);
|
||||
}
|
||||
if (erc721) {
|
||||
return erc721.claimConditions.getActive();
|
||||
return erc721.claimConditions.getActive(options);
|
||||
}
|
||||
if (erc20) {
|
||||
return erc20.claimConditions.getActive();
|
||||
return erc20.claimConditions.getActive(options);
|
||||
}
|
||||
throw new Error("Contract must be ERC721, ERC1155 or ERC20");
|
||||
},
|
||||
@@ -97,7 +110,80 @@ export function useActiveClaimCondition(
|
||||
}
|
||||
|
||||
/**
|
||||
* Use this to get all claim conditons for ERC20, ERC721 or ERC1155 based contracts. They need to extend the `claimCondition` extension for this hook to work.
|
||||
* Use this to get the claimer proofs for an adddress for ERC20, ERC721 or ERC1155 based contracts. They need to extend the `claimCondition` extension for this hook to work.
|
||||
*
|
||||
* @example
|
||||
* ```javascript
|
||||
* const { data: claimerProofs, isLoading, error } = useClaimerProofs(<YourERC20ContractInstance>);
|
||||
* ```
|
||||
* @example
|
||||
* ```javascript
|
||||
* const { data: claimerProofs, isLoading, error } = useClaimerProofs(<YourERC721ContractInstance>);
|
||||
* ```
|
||||
* @example
|
||||
* ```javascript
|
||||
* const { data: claimerProofs, isLoading, error } = useClaimerProofs(<YourERC1155ContractInstance>, <tokenId>);
|
||||
* ```
|
||||
*
|
||||
* @param contract - an instance of a contract that extends the ERC721, ERC1155 or ERC20 spec and implements the `claimConditions` extension.
|
||||
* @param claimerAddress - the address of the claimer to fetch the claimer proofs for
|
||||
* @param tokenId - the id of the token to fetch the claimer proofs for (if the contract is an ERC1155 contract)
|
||||
* @param claimConditionId - optional the claim condition id to get the proofs for
|
||||
* @returns a response object with the snapshot for the provided address
|
||||
* @twfeature ERC721ClaimableWithConditions | ERC1155ClaimableWithConditions | ERC20ClaimableWithConditions
|
||||
* @beta
|
||||
*/
|
||||
export function useClaimerProofs(
|
||||
contract: RequiredParam<DropContract>,
|
||||
claimerAddress: string,
|
||||
tokenId?: BigNumberish,
|
||||
claimConditionId?: BigNumberish,
|
||||
) {
|
||||
const contractAddress = contract?.getAddress();
|
||||
const { erc1155, erc721, erc20 } = getErcs(contract);
|
||||
|
||||
return useQueryWithNetwork(
|
||||
cacheKeys.extensions.claimConditions.getClaimerProofs(
|
||||
contractAddress,
|
||||
tokenId,
|
||||
),
|
||||
() => {
|
||||
if (erc1155) {
|
||||
requiredParamInvariant(
|
||||
tokenId,
|
||||
"tokenId is required for ERC1155 claim conditions",
|
||||
);
|
||||
return erc1155.claimConditions.getClaimerProofs(
|
||||
tokenId,
|
||||
claimerAddress,
|
||||
claimConditionId,
|
||||
);
|
||||
}
|
||||
if (erc721) {
|
||||
return erc721.claimConditions.getClaimerProofs(
|
||||
claimerAddress,
|
||||
claimConditionId,
|
||||
);
|
||||
}
|
||||
if (erc20) {
|
||||
return erc20.claimConditions.getClaimerProofs(
|
||||
claimerAddress,
|
||||
claimConditionId,
|
||||
);
|
||||
}
|
||||
throw new Error("Contract must be ERC721, ERC1155 or ERC20");
|
||||
},
|
||||
{
|
||||
// Checks that happen here:
|
||||
// 1. if the contract is based on ERC1155 contract => tokenId cannot be `undefined`
|
||||
// 2. if the contract is NOT based on ERC1155 => we have to have either an ERC721 or ERC20 contract
|
||||
enabled: erc1155 ? tokenId !== undefined : !!erc721 || !!erc20,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Use this to get all claim conditions for ERC20, ERC721 or ERC1155 based contracts. They need to extend the `claimCondition` extension for this hook to work.
|
||||
*
|
||||
* @example
|
||||
* ```javascript
|
||||
@@ -112,7 +198,7 @@ export function useActiveClaimCondition(
|
||||
* const { data: claimConditions, isLoading, error } = useClaimConditions(<YourERC1155ContractInstance>, <tokenId>);
|
||||
* ```
|
||||
*
|
||||
* @param contract - an instance of a contract that extends the ERC721 or ERC1155 spec and implements the `claimConditions` extension.
|
||||
* @param contract - an instance of a contract that extends the ERC721, ERC1155 or ERC20 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
|
||||
@@ -121,25 +207,30 @@ export function useActiveClaimCondition(
|
||||
export function useClaimConditions(
|
||||
contract: RequiredParam<DropContract>,
|
||||
tokenId?: BigNumberish,
|
||||
options?: ClaimConditionFetchOptions,
|
||||
) {
|
||||
const contractAddress = contract?.getAddress();
|
||||
const { erc1155, erc721, erc20 } = getErcs(contract);
|
||||
|
||||
return useQueryWithNetwork(
|
||||
cacheKeys.extensions.claimConditions.getAll(contractAddress, tokenId),
|
||||
cacheKeys.extensions.claimConditions.getAll(
|
||||
contractAddress,
|
||||
tokenId,
|
||||
options,
|
||||
),
|
||||
() => {
|
||||
if (erc1155) {
|
||||
requiredParamInvariant(
|
||||
tokenId,
|
||||
"tokenId is required for ERC1155 claim conditions",
|
||||
);
|
||||
return erc1155.claimConditions.getAll(tokenId);
|
||||
return erc1155.claimConditions.getAll(tokenId, options);
|
||||
}
|
||||
if (erc721) {
|
||||
return erc721.claimConditions.getAll();
|
||||
return erc721.claimConditions.getAll(options);
|
||||
}
|
||||
if (erc20) {
|
||||
return erc20.claimConditions.getAll();
|
||||
return erc20.claimConditions.getAll(options);
|
||||
}
|
||||
throw new Error("Contract must be ERC721, ERC1155 or ERC20");
|
||||
},
|
||||
@@ -228,6 +319,136 @@ export function useClaimIneligibilityReasons(
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Use this to check the claim condition for a given wallet address (including checking for overrides that may exist for that given wallet address).
|
||||
*
|
||||
* @param contract - an instance of a contract that extends the ERC20, ERC721 or ERC1155 spec and implements the `claimConditions` extension.
|
||||
* @param walletAddress - the wallet address to check the active claim condition for
|
||||
* @param tokenId - the id of the token to fetch the claim conditions for (if the contract is an ERC1155 contract)
|
||||
* @returns the active claim conditon for the wallet address or null if there is no active claim condition
|
||||
*
|
||||
* @beta
|
||||
*/
|
||||
export function useActiveClaimConditionForWallet(
|
||||
contract: RequiredParam<DropContract>,
|
||||
walletAddress: RequiredParam<WalletAddress>,
|
||||
tokenId?: BigNumberish,
|
||||
) {
|
||||
const sdk = useSDK();
|
||||
const contractAddress = contract?.getAddress();
|
||||
const { erc1155, erc721, erc20 } = getErcs(contract);
|
||||
return useQueryWithNetwork<ClaimCondition | null>(
|
||||
cacheKeys.extensions.claimConditions.useActiveClaimConditionForWallet(
|
||||
contractAddress,
|
||||
walletAddress || "_NO_WALLET_",
|
||||
tokenId,
|
||||
),
|
||||
async () => {
|
||||
// if we do not have a walletAddress just do the same logic as basic useClaimCondition
|
||||
if (!walletAddress) {
|
||||
if (erc1155) {
|
||||
requiredParamInvariant(
|
||||
tokenId,
|
||||
"tokenId is required for ERC1155 claim conditions",
|
||||
);
|
||||
return erc1155.claimConditions.getActive(tokenId);
|
||||
}
|
||||
if (erc721) {
|
||||
return erc721.claimConditions.getActive();
|
||||
}
|
||||
if (erc20) {
|
||||
return erc20.claimConditions.getActive();
|
||||
}
|
||||
throw new Error("Contract must be ERC721, ERC1155 or ERC20");
|
||||
}
|
||||
invariant(sdk, "sdk is required");
|
||||
let activeGeneralClaimCondition: ClaimCondition | null = null;
|
||||
let claimerProofForWallet: SnapshotEntryWithProof | null = null;
|
||||
|
||||
if (erc1155) {
|
||||
requiredParamInvariant(tokenId, "tokenId is required for ERC1155");
|
||||
const [cc, cp] = await Promise.all([
|
||||
erc1155.claimConditions.getActive(tokenId),
|
||||
erc1155.claimConditions.getClaimerProofs(tokenId, walletAddress),
|
||||
]);
|
||||
activeGeneralClaimCondition = cc;
|
||||
claimerProofForWallet = cp;
|
||||
}
|
||||
if (erc721) {
|
||||
const [cc, cp] = await Promise.all([
|
||||
erc721.claimConditions.getActive(),
|
||||
erc721.claimConditions.getClaimerProofs(walletAddress),
|
||||
]);
|
||||
activeGeneralClaimCondition = cc;
|
||||
claimerProofForWallet = cp;
|
||||
}
|
||||
if (erc20) {
|
||||
const [cc, cp] = await Promise.all([
|
||||
erc20.claimConditions.getActive(),
|
||||
erc20.claimConditions.getClaimerProofs(walletAddress),
|
||||
]);
|
||||
activeGeneralClaimCondition = cc;
|
||||
claimerProofForWallet = cp;
|
||||
}
|
||||
// if there is no active claim condition nothing matters, return null
|
||||
if (!activeGeneralClaimCondition) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// if there is no claimer proof then just fall back to the active general claim condition
|
||||
if (!claimerProofForWallet) {
|
||||
return activeGeneralClaimCondition;
|
||||
}
|
||||
|
||||
const { maxClaimable, currencyAddress, price } = claimerProofForWallet;
|
||||
|
||||
const currencyWithOverride =
|
||||
currencyAddress || activeGeneralClaimCondition.currencyAddress;
|
||||
|
||||
const currencyMetadata = await fetchCurrencyMetadata(
|
||||
sdk.getProvider(),
|
||||
currencyWithOverride,
|
||||
);
|
||||
|
||||
const normalizedPrize = price
|
||||
? price === "unlimited"
|
||||
? constants.MaxUint256
|
||||
: utils.parseUnits(price, currencyMetadata.decimals)
|
||||
: null;
|
||||
|
||||
const priceWithOverride =
|
||||
normalizedPrize || activeGeneralClaimCondition.price;
|
||||
|
||||
const maxClaimableWithOverride =
|
||||
// have to transform this the same way that claim conditions do it in SDK
|
||||
convertToReadableQuantity(maxClaimable, currencyMetadata.decimals) ||
|
||||
activeGeneralClaimCondition.maxClaimablePerWallet;
|
||||
|
||||
const currencyValueWithOverride = await fetchCurrencyValue(
|
||||
sdk.getProvider(),
|
||||
currencyWithOverride,
|
||||
priceWithOverride,
|
||||
);
|
||||
return {
|
||||
// inherit the entire claim condition
|
||||
...activeGeneralClaimCondition,
|
||||
// overwrite all keys that could be changed based on overwrites
|
||||
maxClaimablePerWallet: maxClaimableWithOverride,
|
||||
price: priceWithOverride,
|
||||
currency: currencyWithOverride,
|
||||
currencyAddress: currencyWithOverride,
|
||||
currencyMetadata: currencyValueWithOverride,
|
||||
};
|
||||
},
|
||||
{
|
||||
// Checks that happen here:
|
||||
// 1. if the contract is based on ERC1155 contract => tokenId cannot be `undefined`
|
||||
// 2. if the contract is NOT based on ERC1155 => we have to have either an ERC721 or ERC20 contract
|
||||
enabled: erc1155 ? tokenId !== undefined : !!erc721 || !!erc20,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/** **********************/
|
||||
/** WRITE HOOKS **/
|
||||
/** **********************/
|
||||
@@ -350,12 +571,10 @@ export function useResetClaimConditions(
|
||||
|
||||
return useMutation(
|
||||
async () => {
|
||||
const cleanConditions = (conditions: ClaimCondition[]) => {
|
||||
const cleanConditions = async (conditions: ClaimCondition[]) => {
|
||||
return conditions.map((c) => ({
|
||||
...c,
|
||||
price: c.currencyMetadata.displayValue,
|
||||
maxQuantity: c.maxQuantity.toString(),
|
||||
quantityLimitPerTransaction: c.quantityLimitPerTransaction.toString(),
|
||||
}));
|
||||
};
|
||||
|
||||
@@ -364,24 +583,30 @@ export function useResetClaimConditions(
|
||||
tokenId,
|
||||
"tokenId is required for ERC1155 claim conditions",
|
||||
);
|
||||
const claimConditions = await erc1155.claimConditions.getAll(tokenId);
|
||||
const claimConditions = await erc1155.claimConditions.getAll(tokenId, {
|
||||
withAllowList: true,
|
||||
});
|
||||
return erc1155.claimConditions.set(
|
||||
tokenId,
|
||||
cleanConditions(claimConditions || []),
|
||||
await cleanConditions(claimConditions || []),
|
||||
true,
|
||||
);
|
||||
}
|
||||
if (erc721) {
|
||||
const claimConditions = await erc721.claimConditions.getAll();
|
||||
const claimConditions = await erc721.claimConditions.getAll({
|
||||
withAllowList: true,
|
||||
});
|
||||
return await erc721.claimConditions.set(
|
||||
cleanConditions(claimConditions || []),
|
||||
await cleanConditions(claimConditions || []),
|
||||
true,
|
||||
);
|
||||
}
|
||||
if (erc20) {
|
||||
const claimConditions = await erc20.claimConditions.getAll();
|
||||
const claimConditions = await erc20.claimConditions.getAll({
|
||||
withAllowList: true,
|
||||
});
|
||||
return await erc20.claimConditions.set(
|
||||
cleanConditions(claimConditions || []),
|
||||
await cleanConditions(claimConditions || []),
|
||||
true,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ import {
|
||||
ContractEvent,
|
||||
ContractForPrebuiltContractType,
|
||||
ContractType,
|
||||
EventQueryFilter,
|
||||
EventQueryOptions,
|
||||
PrebuiltContractType,
|
||||
SUPPORTED_CHAIN_ID,
|
||||
ThirdwebSDK,
|
||||
@@ -346,7 +346,7 @@ export function useContractMetadataUpdate(
|
||||
export function useContractEvents(
|
||||
contract: RequiredParam<ValidContractInstance>,
|
||||
eventName?: string,
|
||||
options: { queryFilter?: EventQueryFilter; subscribe?: boolean } = {
|
||||
options: { queryFilter?: EventQueryOptions; subscribe?: boolean } = {
|
||||
subscribe: true,
|
||||
},
|
||||
) {
|
||||
|
||||
@@ -106,7 +106,7 @@ export function useUnclaimedNFTSupply(contract: RequiredParam<DropContract>) {
|
||||
invariant(erc721, "No ERC721 Contract instance provided");
|
||||
return erc721.totalUnclaimedSupply();
|
||||
}
|
||||
invariant(false, "Contract is not an instance of ERC721")
|
||||
invariant(false, "Contract is not an instance of ERC721");
|
||||
},
|
||||
{ enabled: !!erc721 },
|
||||
);
|
||||
@@ -129,7 +129,7 @@ export function useClaimedNFTSupply(contract: RequiredParam<DropContract>) {
|
||||
if (erc721) {
|
||||
return erc721.totalClaimedSupply();
|
||||
}
|
||||
invariant(false, "Contract is not an instance of ERC721")
|
||||
invariant(false, "Contract is not an instance of ERC721");
|
||||
},
|
||||
{ enabled: !!erc721 },
|
||||
);
|
||||
|
||||
@@ -3,13 +3,20 @@ import {
|
||||
requiredParamInvariant,
|
||||
} from "../../../core/query-utils/required-param";
|
||||
import { useSDKChainId } from "../../providers/base";
|
||||
import { BuyNowParams, MakeBidParams } from "../../types";
|
||||
import {
|
||||
AcceptDirectOffer,
|
||||
BuyNowParams,
|
||||
ExecuteAuctionSale,
|
||||
MakeBidParams,
|
||||
MakeOfferParams,
|
||||
} from "../../types";
|
||||
import {
|
||||
cacheKeys,
|
||||
invalidateContractAndBalances,
|
||||
} from "../../utils/cache-keys";
|
||||
import { useQueryWithNetwork } from "../query-utils/useQueryWithNetwork";
|
||||
import { useAddress } from "../wallet";
|
||||
import { useContractEvents } from "./contracts";
|
||||
import { useMutation, useQueryClient } from "@tanstack/react-query";
|
||||
import type {
|
||||
AuctionListing,
|
||||
@@ -514,6 +521,203 @@ export function useMakeBid(contract: RequiredParam<Marketplace>) {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Use this to make an offer on direct or auction listing from your marketplace contract.
|
||||
*
|
||||
* @example
|
||||
* ```jsx
|
||||
* const Component = () => {
|
||||
* const {
|
||||
* mutate: makeOffer,
|
||||
* isLoading,
|
||||
* error,
|
||||
* } = useMakeOffer(">>YourMarketplaceContractInstance<<");
|
||||
*
|
||||
* if (error) {
|
||||
* console.error("failed to make a bid", error);
|
||||
* }
|
||||
*
|
||||
* return (
|
||||
* <button
|
||||
* disabled={isLoading}
|
||||
* onClick={() => makeOffer({ listingId: 1, pricePerToken: 0.5, quantity: 1 })}
|
||||
* >
|
||||
* Bid!
|
||||
* </button>
|
||||
* );
|
||||
* };
|
||||
* ```
|
||||
*
|
||||
* @param contract - an instance of a Marketplace contract
|
||||
* @returns a mutation object that can be used to make a bid on an auction listing
|
||||
* @beta
|
||||
*/
|
||||
export function useMakeOffer(contract: RequiredParam<Marketplace>) {
|
||||
const activeChainId = useSDKChainId();
|
||||
const contractAddress = contract?.getAddress();
|
||||
const queryClient = useQueryClient();
|
||||
const walletAddress = useAddress();
|
||||
return useMutation(
|
||||
async (data: MakeOfferParams) => {
|
||||
invariant(walletAddress, "no wallet connected, cannot make bid");
|
||||
requiredParamInvariant(contract, "No Contract instance provided");
|
||||
return await contract.makeOffer(
|
||||
data.listingId,
|
||||
data.pricePerToken,
|
||||
data.quantity,
|
||||
);
|
||||
},
|
||||
{
|
||||
onSettled: () =>
|
||||
invalidateContractAndBalances(
|
||||
queryClient,
|
||||
contractAddress,
|
||||
activeChainId,
|
||||
),
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Accept an offer on a direct listing from an offeror, will accept the latest offer by the given offeror.
|
||||
*
|
||||
* @example
|
||||
* ```jsx
|
||||
* const Component = () => {
|
||||
* const {
|
||||
* mutate: acceptOffer,
|
||||
* isLoading,
|
||||
* error,
|
||||
* } = useAcceptDirectListingOffer(">>YourMarketplaceContractInstance<<");
|
||||
*
|
||||
* if (error) {
|
||||
* console.error("failed to accept offer", error);
|
||||
* }
|
||||
*
|
||||
* return (
|
||||
* <button
|
||||
* disabled={isLoading}
|
||||
* onClick={() => acceptOffer({ listingId: 1, addressOfOfferor: "0x..." })}
|
||||
* >
|
||||
* Accept offer
|
||||
* </button>
|
||||
* );
|
||||
* };
|
||||
* ```
|
||||
*
|
||||
* @param contract - an instance of a Marketplace contract
|
||||
* @returns a mutation object that can be used to accept an offer on a direct listing
|
||||
* @beta
|
||||
*/
|
||||
export function useAcceptDirectListingOffer(
|
||||
contract: RequiredParam<Marketplace>,
|
||||
) {
|
||||
const activeChainId = useSDKChainId();
|
||||
const contractAddress = contract?.getAddress();
|
||||
const queryClient = useQueryClient();
|
||||
const walletAddress = useAddress();
|
||||
return useMutation(
|
||||
async (data: AcceptDirectOffer) => {
|
||||
invariant(walletAddress, "no wallet connected, cannot make bid");
|
||||
requiredParamInvariant(contract?.direct, "No Direct instance provided");
|
||||
return await contract.direct.acceptOffer(
|
||||
data.listingId,
|
||||
data.addressOfOfferor,
|
||||
);
|
||||
},
|
||||
{
|
||||
onSettled: () =>
|
||||
invalidateContractAndBalances(
|
||||
queryClient,
|
||||
contractAddress,
|
||||
activeChainId,
|
||||
),
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute an auction sale. Can only be executed once the auction has ended and the auction has a winning bid.
|
||||
*
|
||||
* @example
|
||||
* ```jsx
|
||||
* const Component = () => {
|
||||
* const {
|
||||
* mutate: executeAuctionSale,
|
||||
* isLoading,
|
||||
* error,
|
||||
* } = useExecuteAuctionSale(">>YourMarketplaceContractInstance<<");
|
||||
*
|
||||
* if (error) {
|
||||
* console.error("failed to execute sale", error);
|
||||
* }
|
||||
*
|
||||
* return (
|
||||
* <button
|
||||
* disabled={isLoading}
|
||||
* onClick={() => executeAuctionSale({ listingId: 1 })}
|
||||
* >
|
||||
* Execute sale
|
||||
* </button>
|
||||
* );
|
||||
* };
|
||||
* ```
|
||||
*
|
||||
* @param contract - an instance of a Marketplace contract
|
||||
* @returns a mutation object that can be used to accept an offer on a direct listing
|
||||
* @beta
|
||||
*/
|
||||
export function useExecuteAuctionSale(contract: RequiredParam<Marketplace>) {
|
||||
const activeChainId = useSDKChainId();
|
||||
const contractAddress = contract?.getAddress();
|
||||
const queryClient = useQueryClient();
|
||||
const walletAddress = useAddress();
|
||||
return useMutation(
|
||||
async (data: ExecuteAuctionSale) => {
|
||||
invariant(walletAddress, "no wallet connected, cannot make bid");
|
||||
requiredParamInvariant(
|
||||
contract?.auction,
|
||||
"No Auction marketplace instance provided",
|
||||
);
|
||||
return await contract.auction.executeSale(data.listingId);
|
||||
},
|
||||
{
|
||||
onSettled: () =>
|
||||
invalidateContractAndBalances(
|
||||
queryClient,
|
||||
contractAddress,
|
||||
activeChainId,
|
||||
),
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all the offers for a listing
|
||||
*
|
||||
* @remarks Fetch all the offers for a specified direct or auction listing.
|
||||
* @example
|
||||
* ```javascript
|
||||
* const { data: offers, isLoading, error } = useOffers(<YourMarketplaceContractInstance>, <listingId>);
|
||||
* ```
|
||||
*
|
||||
* @param contract - an instance of a Marketplace contract
|
||||
* @param listingId - the id of the listing to fetch offers for
|
||||
* @beta
|
||||
*/
|
||||
export function useOffers(
|
||||
contract: RequiredParam<Marketplace>,
|
||||
listingId: RequiredParam<BigNumberish>,
|
||||
) {
|
||||
const result = useContractEvents(contract, "NewOffer");
|
||||
return {
|
||||
...result,
|
||||
data: result.data
|
||||
?.filter((ev) => ev.data.listingId.eq(listingId))
|
||||
?.map((ev) => ev.data),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Use this to buy out an auction listing from your marketplace contract.
|
||||
*
|
||||
|
||||
@@ -542,7 +542,7 @@ export function useTransferNFT<TContract extends NFTContract>(
|
||||
* @example
|
||||
* ```jsx
|
||||
* const Component = () => {
|
||||
* const editionDrop = useEditionDrop(<ContractAddress>);
|
||||
* const editionDrop = useContract(<ContractAddress>, "edition-drop");
|
||||
* const {
|
||||
* mutate: airdropNFT,
|
||||
* isLoading,
|
||||
|
||||
@@ -232,11 +232,9 @@ export function useClaimToken(contract: RequiredParam<TokenContract>) {
|
||||
invariant(data.to, 'No "to" address provided');
|
||||
if (erc20) {
|
||||
invariant(erc20?.claimTo, "contract does not support claimTo");
|
||||
return await erc20.claimTo(
|
||||
data.to,
|
||||
data.amount,
|
||||
data.checkERC20Allowance,
|
||||
);
|
||||
return await erc20.claimTo(data.to, data.amount, {
|
||||
checkERC20Allowance: data.checkERC20Allowance,
|
||||
});
|
||||
}
|
||||
invariant(false, "Smart contract is not a valid erc20 contract");
|
||||
},
|
||||
|
||||
@@ -1,72 +0,0 @@
|
||||
import {
|
||||
GnosisConnectorArguments,
|
||||
GnosisSafeConnector,
|
||||
} from "../../connectors/gnosis-safe";
|
||||
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.
|
||||
*
|
||||
* ```javascript
|
||||
* import { useGnosis } from "@thirdweb-dev/react"
|
||||
* ```
|
||||
*
|
||||
*
|
||||
* @example
|
||||
* ```javascript
|
||||
* import { useGnosis } from "@thirdweb-dev/react"
|
||||
*
|
||||
* const App = () => {
|
||||
* const connectWithGnosis = useGnosis()
|
||||
*
|
||||
* return (
|
||||
* <button onClick={() => connectWithGnosis({ safeAddress: "0x...", safeChainId: 1 })}>
|
||||
* Connect Gnosis Safe
|
||||
* </button>
|
||||
* )
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @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");
|
||||
}
|
||||
const connector = connectors.data.connectors.find((c) => c.id === "gnosis");
|
||||
invariant(
|
||||
connector,
|
||||
"Gnosis connector not found, please make sure it is provided to your <ThirdwebProvider />",
|
||||
);
|
||||
|
||||
return async (config: GnosisConnectorArguments) => {
|
||||
const previousConnector = connectors.data.connector;
|
||||
const previousConnectorChain = await previousConnector?.getChainId();
|
||||
invariant(
|
||||
!!previousConnector,
|
||||
"Cannot connect to Gnosis Safe without first being connected to a personal wallet.",
|
||||
);
|
||||
invariant(
|
||||
previousConnectorChain === config.safeChainId,
|
||||
"Gnosis safe chain id must match personal wallet chain id.",
|
||||
);
|
||||
invariant(
|
||||
utils.isAddress(config.safeAddress),
|
||||
"Gnosis safe address must be a valid address.",
|
||||
);
|
||||
(connector as GnosisSafeConnector).setConfiguration(
|
||||
previousConnector,
|
||||
config,
|
||||
);
|
||||
return connect(connector);
|
||||
};
|
||||
}
|
||||
@@ -1,91 +0,0 @@
|
||||
import { MagicConnector } from "../../connectors/magic";
|
||||
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.
|
||||
* This enables users without their own wallets to connect to your application and sign transactions securely using their email.
|
||||
*
|
||||
* ```javascript
|
||||
* import { useMagic } from "@thirdweb-dev/react"
|
||||
* ```
|
||||
*
|
||||
*
|
||||
* @example
|
||||
* Before using this hook, you first need to set up the magic configuration in your `ThirdwebProvider`, including your magic API key.
|
||||
*
|
||||
* ```javascript
|
||||
* // Add the magic configuration object to your wallet connectors
|
||||
* const connectors = [
|
||||
* "metamask",
|
||||
* "walletConnect",
|
||||
* "walletLink",
|
||||
* {
|
||||
* name: "magic",
|
||||
* options: {
|
||||
* apiKey: "your-magic-api-key",
|
||||
* }
|
||||
* }
|
||||
* ]
|
||||
*
|
||||
* // Add the above to the walletConnectors prop of your <ThirdwebProvider />
|
||||
* const Provider = ({ children }) => (
|
||||
* return (
|
||||
* <ThirdwebProvider
|
||||
* walletConnectors={connectors}
|
||||
* // Specify remaining parameters
|
||||
* ...
|
||||
* >
|
||||
* {children}
|
||||
* </ThirdwebProvider>
|
||||
* )
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* In order to use the hook to connect users with magic link, you just need to provide the users email to the connect function.
|
||||
*
|
||||
* You can setup the hook with the following configuration:
|
||||
* ```javascript
|
||||
* import { useMagic } from "@thirdweb-dev/react"
|
||||
* import { useState } from "react"
|
||||
*
|
||||
* const LoginWithMagicLink = () => {
|
||||
* const connectWithMagic = useMagic()
|
||||
* const [email, setEmail] = useState()
|
||||
*
|
||||
* return (
|
||||
* <div>
|
||||
* <input value={email} onChange={(e) => setEmail(e.target.value)} />
|
||||
* <button onClick={() => connectWithMagic({ email })}>Login</button>
|
||||
* </div>
|
||||
* )
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @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");
|
||||
}
|
||||
|
||||
const connector = connectors.data.connectors.find((c) => c.id === "magic");
|
||||
|
||||
invariant(
|
||||
connector,
|
||||
"Magic connector not found, please make sure it is provided to your <ThirdwebProvider />",
|
||||
);
|
||||
|
||||
return (configuration: LoginWithMagicLinkConfiguration) => {
|
||||
(connector as MagicConnector).setConfiguration(configuration);
|
||||
return connect(connector);
|
||||
};
|
||||
}
|
||||
@@ -1,10 +1,10 @@
|
||||
import { useConnect } from "../wagmi-required/useConnect";
|
||||
import { Buffer } from "buffer";
|
||||
import invariant from "tiny-invariant";
|
||||
import { useContext as useWagmiContext } from "wagmi";
|
||||
|
||||
if (!globalThis.Buffer) {
|
||||
globalThis.Buffer = require("buffer/").Buffer;
|
||||
}
|
||||
globalThis.Buffer = Buffer;
|
||||
|
||||
/**
|
||||
* Hook for connecting to a mobile wallet with Wallet Connect
|
||||
*
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { useConnect } from "../wagmi-required/useConnect";
|
||||
import { Buffer } from "buffer";
|
||||
import invariant from "tiny-invariant";
|
||||
import { useContext as useWagmiContext } from "wagmi";
|
||||
|
||||
if (!globalThis.Buffer) {
|
||||
globalThis.Buffer = require("buffer/").Buffer;
|
||||
}
|
||||
globalThis.Buffer = Buffer;
|
||||
|
||||
/**
|
||||
* Hook for connecting to a Coinbase wallet.
|
||||
*
|
||||
|
||||
@@ -28,8 +28,8 @@ import { useContract } from "../async/contracts";
|
||||
* @deprecated
|
||||
* This hook is deprecated and will be removed in a future major version. You should use {@link useContract} instead.
|
||||
* ```diff
|
||||
* - const edition = await sdk.useEdition("0x1234...");
|
||||
* + const edition = await sdk.useContract("0x1234...", "edition").contract;
|
||||
* - const edition = useEdition("0x1234...");
|
||||
* + const edition = useContract("0x1234...", "edition").contract;
|
||||
* ```
|
||||
*/
|
||||
export function useEdition(contractAddress: RequiredParam<string>) {
|
||||
|
||||
@@ -27,8 +27,8 @@ import { useContract } from "../async/contracts";
|
||||
* @deprecated
|
||||
* This hook is deprecated and will be removed in a future major version. You should use {@link useContract} instead.
|
||||
* ```diff
|
||||
* - const editionDrop = await sdk.useEditionDrop("0x1234...");
|
||||
* + const editionDrop = await sdk.useContract("0x1234...", "edition-drop").contract;
|
||||
* - const editionDrop = useEditionDrop("0x1234...");
|
||||
* + const editionDrop = useContract("0x1234...", "edition-drop").contract;
|
||||
* ```
|
||||
*/
|
||||
export function useEditionDrop(contractAddress: RequiredParam<string>) {
|
||||
|
||||
@@ -28,8 +28,8 @@ import { useContract } from "../async/contracts";
|
||||
* @deprecated
|
||||
* This hook is deprecated and will be removed in a future major version. You should use {@link useContract} instead.
|
||||
* ```diff
|
||||
* - const marketplace = await sdk.useMarketplace("0x1234...");
|
||||
* + const marketplace = await sdk.useContract("0x1234...", "marketplace").contract;
|
||||
* - const marketplace = useMarketplace("0x1234...");
|
||||
* + const marketplace = useContract("0x1234...", "marketplace").contract;
|
||||
* ```
|
||||
*/
|
||||
export function useMarketplace(contractAddress: RequiredParam<string>) {
|
||||
|
||||
@@ -27,8 +27,8 @@ import { useContract } from "../async/contracts";
|
||||
* @deprecated
|
||||
* This hook is deprecated and will be removed in a future major version. You should use {@link useContract} instead.
|
||||
* ```diff
|
||||
* - const multiwrap = await sdk.useMultiwrap("0x1234...");
|
||||
* + const multiwrap = await sdk.useContract("0x1234...", "multiwrap").contract;
|
||||
* - const multiwrap = useMultiwrap("0x1234...");
|
||||
* + const multiwrap = useContract("0x1234...", "multiwrap").contract;
|
||||
* ```
|
||||
*/
|
||||
export function useMultiwrap(contractAddress: RequiredParam<string>) {
|
||||
|
||||
@@ -11,7 +11,7 @@ import { useContract } from "../async/contracts";
|
||||
* import { useContract } from '@thirdweb-dev/react'
|
||||
*
|
||||
* export default function Component() {
|
||||
* const { contract } = useNFTCollection("<YOUR-CONTRACT-ADDRESS>", "nft-collection")
|
||||
* const { contract, isLoading, error } = useContract("<YOUR-CONTRACT-ADDRESS>", "nft-collection")
|
||||
*
|
||||
* // Now you can use the nftCollection contract in the rest of the component
|
||||
*
|
||||
@@ -28,8 +28,8 @@ import { useContract } from "../async/contracts";
|
||||
* @deprecated
|
||||
* This hook is deprecated and will be removed in a future major version. You should use {@link useContract} instead.
|
||||
* ```diff
|
||||
* - const nftCollection = await sdk.useNFTCollection("0x1234...");
|
||||
* + const nftCollection = await sdk.useContract("0x1234...", "nft-collection").contract;
|
||||
* - const nftCollection = useNFTCollection("0x1234...");
|
||||
* + const nftCollection = useContract("0x1234...", "nft-collection").contract;
|
||||
* ```
|
||||
*/
|
||||
export function useNFTCollection(contractAddress: RequiredParam<string>) {
|
||||
|
||||
@@ -27,8 +27,8 @@ import { useContract } from "../async/contracts";
|
||||
* @deprecated
|
||||
* This hook is deprecated and will be removed in a future major version. You should use {@link useContract} instead.
|
||||
* ```diff
|
||||
* - const nftDrop = await sdk.useNFTDrop("0x1234...");
|
||||
* + const nftDrop = await sdk.useContract("0x1234...", "nft-drop").contract;
|
||||
* - const nftDrop = useNFTDrop("0x1234...");
|
||||
* + const nftDrop = useContract("0x1234...", "nft-drop").contract;
|
||||
* ```
|
||||
*/
|
||||
export function useNFTDrop(contractAddress: RequiredParam<string>) {
|
||||
|
||||
@@ -28,8 +28,8 @@ import { useContract } from "../async/contracts";
|
||||
* @deprecated
|
||||
* This hook is deprecated and will be removed in a future major version. You should use {@link useContract} instead.
|
||||
* ```diff
|
||||
* - const pack = await sdk.usePack("0x1234...");
|
||||
* + const pack = await sdk.useContract("0x1234...", "pack").contract;
|
||||
* - const pack = usePack("0x1234...");
|
||||
* + const pack = useContract("0x1234...", "pack").contract;
|
||||
* ```
|
||||
*/
|
||||
export function usePack(contractAddress: RequiredParam<string>) {
|
||||
|
||||
@@ -27,8 +27,8 @@ import { useContract } from "../async/contracts";
|
||||
* @deprecated
|
||||
* This hook is deprecated and will be removed in a future major version. You should use {@link useContract} instead.
|
||||
* ```diff
|
||||
* - const signatureDrop = await sdk.useSignatureDrop("0x1234...");
|
||||
* + const signatureDrop = await sdk.useContract("0x1234...", "signature-drop").contract;
|
||||
* - const signatureDrop = useSignatureDrop("0x1234...");
|
||||
* + const signatureDrop = useContract("0x1234...", "signature-drop").contract;
|
||||
* ```
|
||||
*/
|
||||
export function useSignatureDrop(contractAddress?: RequiredParam<string>) {
|
||||
|
||||
@@ -28,8 +28,8 @@ import { useContract } from "../async/contracts";
|
||||
* @deprecated
|
||||
* This hook is deprecated and will be removed in a future major version. You should use {@link useContract} instead.
|
||||
* ```diff
|
||||
* - const split = await sdk.useSplit("0x1234...");
|
||||
* + const split = await sdk.useContract("0x1234...", "split").contract;
|
||||
* - const split = useSplit("0x1234...");
|
||||
* + const split = useContract("0x1234...", "split").contract;
|
||||
* ```
|
||||
*/
|
||||
export function useSplit(contractAddress: RequiredParam<string>) {
|
||||
|
||||
@@ -28,8 +28,8 @@ import { useContract } from "../async/contracts";
|
||||
* @deprecated
|
||||
* This hook is deprecated and will be removed in a future major version. You should use {@link useContract} instead.
|
||||
* ```diff
|
||||
* - const token = await sdk.useToken("0x1234...");
|
||||
* + const token = await sdk.useContract("0x1234...", "token").contract;
|
||||
* - const token = useToken("0x1234...");
|
||||
* + const token = useContract("0x1234...", "token").contract;
|
||||
* ```
|
||||
*/
|
||||
export function useToken(contractAddress: RequiredParam<string>) {
|
||||
|
||||
@@ -28,8 +28,8 @@ import { useContract } from "../async/contracts";
|
||||
* @deprecated
|
||||
* This hook is deprecated and will be removed in a future major version. You should use {@link useContract} instead.
|
||||
* ```diff
|
||||
* - const token = await sdk.useTokenDrop("0x1234...");
|
||||
* + const token = await sdk.useContract("0x1234...", "token-drop").contract;
|
||||
* - const token = useTokenDrop("0x1234...");
|
||||
* + const token = useContract("0x1234...", "token-drop").contract;
|
||||
* ```
|
||||
*/
|
||||
export function useTokenDrop(contractAddress: RequiredParam<string>) {
|
||||
|
||||
@@ -28,8 +28,8 @@ import { useContract } from "../async/contracts";
|
||||
* @deprecated
|
||||
* This hook is deprecated and will be removed in a future major version. You should use {@link useContract} instead.
|
||||
* ```diff
|
||||
* - const vote = await sdk.useVote("0x1234...");
|
||||
* + const vote = await sdk.useContract("0x1234...", "vote").contract;
|
||||
* - const vote = useVote("0x1234...");
|
||||
* + const vote = useContract("0x1234...", "vote").contract;
|
||||
* ```
|
||||
*/
|
||||
export function useVote(contractAddress: RequiredParam<string>) {
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { GnosisSafeConnector } from "../../connectors/gnosis-safe";
|
||||
import { useConnect } from "./useConnect";
|
||||
import invariant from "tiny-invariant";
|
||||
import { useAccount, useContext as useWagmiContext } from "wagmi";
|
||||
import { Connector, useAccount, useContext as useWagmiContext } from "wagmi";
|
||||
|
||||
/**
|
||||
* Hook for disconnecting the currently connected wallet
|
||||
@@ -31,23 +30,22 @@ import { useAccount, useContext as useWagmiContext } from "wagmi";
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export function useDisconnect(options?: { reconnectAfterGnosis?: boolean }) {
|
||||
export function useDisconnect(options?: { reconnectPrevious?: 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 optsWithDefaults = { ...{ reconnectPrevious: true }, ...options };
|
||||
const [, connect] = useConnect();
|
||||
const [data, disconnect] = useAccount();
|
||||
|
||||
return async () => {
|
||||
const previousConnector =
|
||||
(data.data?.connector instanceof GnosisSafeConnector &&
|
||||
data.data.connector.previousConnector) ||
|
||||
undefined;
|
||||
// if there is a previous connector get it
|
||||
const previousConnector: Connector | undefined =
|
||||
(data?.data?.connector as any)?.previousConnector || undefined;
|
||||
// if it's gnosis, just connect the previous connector
|
||||
if (optsWithDefaults.reconnectAfterGnosis && previousConnector) {
|
||||
if (optsWithDefaults.reconnectPrevious && previousConnector) {
|
||||
try {
|
||||
return await connect(previousConnector);
|
||||
} catch (err) {
|
||||
|
||||
@@ -31,8 +31,6 @@ 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";
|
||||
|
||||
@@ -1,90 +1,93 @@
|
||||
import { useState, useCallback, useLayoutEffect, useEffect, useRef, PropsWithChildren } from "react";
|
||||
import { createPortal } from "react-dom";
|
||||
import {
|
||||
useState,
|
||||
useCallback,
|
||||
useLayoutEffect,
|
||||
useEffect,
|
||||
useRef,
|
||||
PropsWithChildren,
|
||||
} from "react";
|
||||
import { createPortal } from "react-dom";
|
||||
|
||||
|
||||
function canUseDOM() {
|
||||
function canUseDOM() {
|
||||
return !!(
|
||||
typeof window !== "undefined" &&
|
||||
window.document &&
|
||||
window.document.createElement
|
||||
);
|
||||
typeof window !== "undefined" &&
|
||||
window.document &&
|
||||
window.document.createElement
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Forces a re-render, similar to `forceUpdate` in class components.
|
||||
*/
|
||||
function useForceUpdate() {
|
||||
const [, dispatch] = useState<{}>(Object.create(null));
|
||||
return useCallback(() => {
|
||||
dispatch(Object.create(null));
|
||||
}, []);
|
||||
const [, dispatch] = useState<{}>(Object.create(null));
|
||||
return useCallback(() => {
|
||||
dispatch(Object.create(null));
|
||||
}, []);
|
||||
}
|
||||
|
||||
|
||||
const useIsomorphicLayoutEffect = canUseDOM() ? useLayoutEffect : useEffect;
|
||||
|
||||
/**
|
||||
* Portal from `@reach/portal`
|
||||
*
|
||||
* @see Docs https://reach.tech/portal#portal
|
||||
*/
|
||||
const PortalImpl: React.FC<PortalProps> = ({
|
||||
children,
|
||||
type = "reach-portal",
|
||||
containerRef,
|
||||
}) => {
|
||||
const mountNode = useRef<HTMLDivElement | null>(null);
|
||||
const portalNode = useRef<HTMLElement | null>(null);
|
||||
const forceUpdate = useForceUpdate();
|
||||
|
||||
/**
|
||||
* Portal from `@reach/portal`
|
||||
*
|
||||
* @see Docs https://reach.tech/portal#portal
|
||||
*/
|
||||
const PortalImpl: React.FC<PortalProps> = ({
|
||||
children,
|
||||
type = "reach-portal",
|
||||
containerRef,
|
||||
}) => {
|
||||
const mountNode = useRef<HTMLDivElement | null>(null);
|
||||
const portalNode = useRef<HTMLElement | null>(null);
|
||||
const forceUpdate = useForceUpdate();
|
||||
useIsomorphicLayoutEffect(() => {
|
||||
// This ref may be null when a hot-loader replaces components on the page
|
||||
if (!mountNode.current) {
|
||||
return;
|
||||
}
|
||||
// It's possible that the content of the portal has, itself, been portaled.
|
||||
// In that case, it's important to append to the correct document element.
|
||||
const ownerDocument = mountNode.current.ownerDocument;
|
||||
const body = containerRef?.current || ownerDocument.body;
|
||||
portalNode.current = ownerDocument?.createElement(type);
|
||||
body.appendChild(portalNode.current);
|
||||
forceUpdate();
|
||||
return () => {
|
||||
if (portalNode.current && body) {
|
||||
body.removeChild(portalNode.current);
|
||||
}
|
||||
};
|
||||
}, [type, forceUpdate, containerRef]);
|
||||
|
||||
return portalNode.current ? (
|
||||
createPortal(children, portalNode.current)
|
||||
) : (
|
||||
<span ref={mountNode} />
|
||||
);
|
||||
};
|
||||
|
||||
useIsomorphicLayoutEffect(() => {
|
||||
// This ref may be null when a hot-loader replaces components on the page
|
||||
if (!mountNode.current) {return;}
|
||||
// It's possible that the content of the portal has, itself, been portaled.
|
||||
// In that case, it's important to append to the correct document element.
|
||||
const ownerDocument = mountNode.current.ownerDocument;
|
||||
const body = containerRef?.current || ownerDocument.body;
|
||||
portalNode.current = ownerDocument?.createElement(type);
|
||||
body.appendChild(portalNode.current);
|
||||
forceUpdate();
|
||||
return () => {
|
||||
if (portalNode.current && body) {
|
||||
body.removeChild(portalNode.current);
|
||||
}
|
||||
};
|
||||
}, [type, forceUpdate, containerRef]);
|
||||
export const Portal: React.FC<PortalProps> = ({
|
||||
unstable_skipInitialRender,
|
||||
...props
|
||||
}) => {
|
||||
const [hydrated, setHydrated] = useState(false);
|
||||
useEffect(() => {
|
||||
if (unstable_skipInitialRender) {
|
||||
setHydrated(true);
|
||||
}
|
||||
}, [unstable_skipInitialRender]);
|
||||
if (unstable_skipInitialRender && !hydrated) {
|
||||
return null;
|
||||
}
|
||||
return <PortalImpl {...props} />;
|
||||
};
|
||||
|
||||
return portalNode.current ? (
|
||||
createPortal(children, portalNode.current)
|
||||
) : (
|
||||
<span ref={mountNode} />
|
||||
);
|
||||
};
|
||||
|
||||
export const Portal: React.FC<PortalProps> = ({
|
||||
unstable_skipInitialRender,
|
||||
...props
|
||||
}) => {
|
||||
const [hydrated, setHydrated] = useState(false);
|
||||
useEffect(() => {
|
||||
if (unstable_skipInitialRender) {
|
||||
setHydrated(true);
|
||||
}
|
||||
}, [unstable_skipInitialRender]);
|
||||
if (unstable_skipInitialRender && !hydrated) {
|
||||
return null;
|
||||
}
|
||||
return <PortalImpl {...props} />;
|
||||
};
|
||||
|
||||
|
||||
export type PortalProps = PropsWithChildren<{
|
||||
type?: string;
|
||||
containerRef?: React.RefObject<Node>;
|
||||
unstable_skipInitialRender?: boolean;
|
||||
}>;
|
||||
|
||||
Portal.displayName = "Portal";
|
||||
export type PortalProps = PropsWithChildren<{
|
||||
type?: string;
|
||||
containerRef?: React.RefObject<Node>;
|
||||
unstable_skipInitialRender?: boolean;
|
||||
}>;
|
||||
|
||||
Portal.displayName = "Portal";
|
||||
|
||||
@@ -21,7 +21,7 @@ import {
|
||||
} from "@thirdweb-dev/sdk";
|
||||
import { ThirdwebStorage } from "@thirdweb-dev/storage";
|
||||
import { Signer } from "ethers";
|
||||
import { createContext, useContext, useEffect, useMemo } from "react";
|
||||
import { createContext, useContext, useEffect, useMemo, useState } from "react";
|
||||
import invariant from "tiny-invariant";
|
||||
|
||||
interface TWSDKContext {
|
||||
@@ -60,21 +60,36 @@ export const WrappedThirdwebSDKProvider: ComponentWithChildren<
|
||||
}) => {
|
||||
const { signer } = useThirdwebConnectedWalletContext();
|
||||
|
||||
const sdk = useMemo(() => {
|
||||
const [sdk, setSDK] = useState<ThirdwebSDK>();
|
||||
|
||||
useEffect(() => {
|
||||
if (!desiredChainId || typeof window === "undefined") {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const _sdk = new ThirdwebSDK(provider, sdkOptions, storageInterface);
|
||||
// if we already have a signer from the wallet context, use it immediately
|
||||
if (signer) {
|
||||
_sdk.updateSignerOrProvider(signer);
|
||||
}
|
||||
|
||||
(_sdk as any)._constructedAt = Date.now();
|
||||
(_sdk as any)._chainId = desiredChainId;
|
||||
return _sdk;
|
||||
setSDK(_sdk);
|
||||
|
||||
// explicitly *not* passing the signer, if we have it we use it if we don't we don't
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [provider, sdkOptions, storageInterface, desiredChainId]);
|
||||
|
||||
useEffect(() => {
|
||||
if (signer && sdk && (sdk as any)._chainId === desiredChainId) {
|
||||
sdk.updateSignerOrProvider(signer);
|
||||
if (sdk && (sdk as any)._chainId === desiredChainId) {
|
||||
if (signer) {
|
||||
sdk.updateSignerOrProvider(signer);
|
||||
} else {
|
||||
sdk.updateSignerOrProvider(provider);
|
||||
}
|
||||
}
|
||||
}, [signer, sdk, desiredChainId]);
|
||||
}, [signer, sdk, desiredChainId, provider]);
|
||||
|
||||
const ctxValue = useMemo(
|
||||
() => ({
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
import {
|
||||
GnosisConnectorArguments,
|
||||
GnosisSafeConnector,
|
||||
} from "../connectors/gnosis-safe";
|
||||
import { MagicConnector, MagicConnectorArguments } from "../connectors/magic";
|
||||
import type { GnosisSafeConnector } from "../connectors/gnosis-safe";
|
||||
import type { MagicConnector } from "../connectors/magic";
|
||||
import {
|
||||
Chain,
|
||||
SupportedChain,
|
||||
@@ -25,6 +22,7 @@ import {
|
||||
ProviderProps as WagmiproviderProps,
|
||||
useProvider,
|
||||
useSigner,
|
||||
Connector,
|
||||
} from "wagmi";
|
||||
import { CoinbaseWalletConnector } from "wagmi/connectors/coinbaseWallet";
|
||||
import { InjectedConnector } from "wagmi/connectors/injected";
|
||||
@@ -56,26 +54,6 @@ export type WalletLinkConnectorType =
|
||||
options: CoinbaseWalletConnector["options"];
|
||||
};
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export type MagicConnectorType =
|
||||
| "magic"
|
||||
| {
|
||||
name: "magic";
|
||||
options: Omit<MagicConnectorArguments, "network">;
|
||||
};
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export type GnosisConnectorType =
|
||||
| "gnosis"
|
||||
| {
|
||||
name: "gnosis";
|
||||
options: GnosisConnectorArguments;
|
||||
};
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
@@ -83,8 +61,8 @@ export type WalletConnector =
|
||||
| InjectedConnectorType
|
||||
| WalletConnectConnectorType
|
||||
| WalletLinkConnectorType
|
||||
| MagicConnectorType
|
||||
| GnosisConnectorType;
|
||||
| GnosisSafeConnector
|
||||
| MagicConnector;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
@@ -280,6 +258,9 @@ export const ThirdwebProvider = <
|
||||
connectors: ({ chainId }: { chainId?: number }) => {
|
||||
return walletConnectors
|
||||
.map((connector) => {
|
||||
if (connector instanceof Connector) {
|
||||
return connector;
|
||||
}
|
||||
// injected connector
|
||||
if (
|
||||
(typeof connector === "string" &&
|
||||
@@ -344,25 +325,7 @@ export const ThirdwebProvider = <
|
||||
},
|
||||
});
|
||||
}
|
||||
if (typeof connector === "object" && connector.name === "magic") {
|
||||
const jsonRpcUrl = _rpcUrlMap[chainId || desiredChainId || 1];
|
||||
return new MagicConnector({
|
||||
chains: _supporrtedChains,
|
||||
options: {
|
||||
...connector.options,
|
||||
network: { rpcUrl: jsonRpcUrl, chainId: desiredChainId || 1 },
|
||||
rpcUrls: _rpcUrlMap,
|
||||
},
|
||||
});
|
||||
}
|
||||
if (
|
||||
(typeof connector === "string" && connector === "gnosis") ||
|
||||
(typeof connector === "object" && connector.name === "gnosis")
|
||||
) {
|
||||
return new GnosisSafeConnector({
|
||||
chains: _supporrtedChains,
|
||||
});
|
||||
}
|
||||
|
||||
return null;
|
||||
})
|
||||
.filter((c) => c !== null);
|
||||
|
||||
@@ -14,6 +14,8 @@ import type {
|
||||
ClaimOptions,
|
||||
NFTMetadataOrUri,
|
||||
Token,
|
||||
Multiwrap,
|
||||
Pack,
|
||||
} from "@thirdweb-dev/sdk";
|
||||
import type { Edition } from "@thirdweb-dev/sdk/dist/declarations/src/evm/contracts/prebuilt-implementations/edition";
|
||||
import type { EditionDrop } from "@thirdweb-dev/sdk/dist/declarations/src/evm/contracts/prebuilt-implementations/edition-drop";
|
||||
@@ -68,6 +70,8 @@ export type TokenBurnParams = {
|
||||
export type NFTContract =
|
||||
| NFTCollection
|
||||
| Edition
|
||||
| Pack
|
||||
| Multiwrap
|
||||
| Exclude<DropContract, "TokenDrop">;
|
||||
|
||||
/**
|
||||
@@ -212,6 +216,18 @@ export type ClaimNFTReturnType =
|
||||
// MARKETPLACE //
|
||||
|
||||
export type MakeBidParams = { listingId: BigNumberish; bid: Price };
|
||||
export type MakeOfferParams = {
|
||||
listingId: BigNumberish;
|
||||
pricePerToken: Price;
|
||||
quantity?: Amount;
|
||||
};
|
||||
export type AcceptDirectOffer = {
|
||||
listingId: BigNumberish;
|
||||
addressOfOfferor: string;
|
||||
};
|
||||
export type ExecuteAuctionSale = {
|
||||
listingId: BigNumberish;
|
||||
};
|
||||
|
||||
export type BuyNowParams<TListingType = ListingType> =
|
||||
TListingType extends ListingType.Direct
|
||||
|
||||
@@ -3,6 +3,7 @@ import { SupportedChainId } from "../constants/chain";
|
||||
import { ContractAddress, WalletAddress } from "../types";
|
||||
import { QueryClient, QueryKey } from "@tanstack/react-query";
|
||||
import type {
|
||||
ClaimConditionFetchOptions,
|
||||
MarketplaceFilter,
|
||||
QueryAllParams,
|
||||
SUPPORTED_CHAIN_ID,
|
||||
@@ -267,22 +268,34 @@ export const cacheKeys = {
|
||||
getActive: (
|
||||
contractAddress: RequiredParam<ContractAddress>,
|
||||
tokenId?: BigNumberish,
|
||||
options?: ClaimConditionFetchOptions,
|
||||
) =>
|
||||
createContractCacheKey(
|
||||
contractAddress,
|
||||
tokenId
|
||||
? ["claimConditions", "getActive", { tokenId }]
|
||||
: ["claimConditions", "getActive"],
|
||||
? ["claimConditions", "getActive", { tokenId }, options]
|
||||
: ["claimConditions", "getActive", options],
|
||||
),
|
||||
getAll: (
|
||||
contractAddress: RequiredParam<ContractAddress>,
|
||||
tokenId?: BigNumberish,
|
||||
options?: ClaimConditionFetchOptions,
|
||||
) =>
|
||||
createContractCacheKey(
|
||||
contractAddress,
|
||||
tokenId
|
||||
? ["claimConditions", "getAll", { tokenId }, options]
|
||||
: ["claimConditions", "getAll", options],
|
||||
),
|
||||
getClaimerProofs: (
|
||||
contractAddress: RequiredParam<ContractAddress>,
|
||||
tokenId?: BigNumberish,
|
||||
) =>
|
||||
createContractCacheKey(
|
||||
contractAddress,
|
||||
tokenId
|
||||
? ["claimConditions", "getAll", { tokenId }]
|
||||
: ["claimConditions", "getAll"],
|
||||
? ["claimConditions", "getClaimerProofs", { tokenId }]
|
||||
: ["claimConditions", "getClaimerProofs"],
|
||||
),
|
||||
getClaimIneligibilityReasons: (
|
||||
contractAddress: RequiredParam<ContractAddress>,
|
||||
@@ -300,6 +313,23 @@ export const cacheKeys = {
|
||||
]
|
||||
: ["claimConditions", "getIneligibilityReasons", params],
|
||||
),
|
||||
// combinations of queries cache keys
|
||||
useActiveClaimConditionForWallet: (
|
||||
contractAddress: RequiredParam<ContractAddress>,
|
||||
walletAddress: WalletAddress,
|
||||
tokenId?: BigNumberish,
|
||||
) =>
|
||||
createContractCacheKey(
|
||||
contractAddress,
|
||||
tokenId
|
||||
? [
|
||||
"claimConditions",
|
||||
"useActiveClaimConditionForWallet",
|
||||
{ tokenId, walletAddress },
|
||||
,
|
||||
]
|
||||
: ["claimConditions", "getIneligibilityReasons", { walletAddress }],
|
||||
),
|
||||
},
|
||||
|
||||
// primary sale contracts
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// at the moment we'll re-export everything from the ethereum package (only!)
|
||||
// at the moment we'll re-export everything from the ethereum package
|
||||
export * from "./evm";
|
||||
|
||||
// core exports
|
||||
|
||||
@@ -4,17 +4,22 @@ import {
|
||||
RequiredParam,
|
||||
} from "../../../core/query-utils/required-param";
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import { QueryAllParams } from "@thirdweb-dev/sdk";
|
||||
import type { NFTCollection, NFTDrop } from "@thirdweb-dev/sdk/solana";
|
||||
|
||||
export function nftGetAllQuery(
|
||||
program: RequiredParam<NFTCollection | NFTDrop>,
|
||||
queryParams?: QueryAllParams,
|
||||
) {
|
||||
return {
|
||||
queryKey: createSOLProgramQueryKey(program, ["getAll"] as const),
|
||||
queryKey: createSOLProgramQueryKey(program, [
|
||||
"getAll",
|
||||
queryParams,
|
||||
] as const),
|
||||
|
||||
queryFn: async () => {
|
||||
requiredParamInvariant(program, "program is required");
|
||||
return await program.getAll();
|
||||
return program.getAll(queryParams);
|
||||
},
|
||||
enabled: !!program,
|
||||
};
|
||||
@@ -40,6 +45,9 @@ export function nftGetAllQuery(
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export function useNFTs(program: RequiredParam<NFTCollection | NFTDrop>) {
|
||||
return useQuery(nftGetAllQuery(program));
|
||||
export function useNFTs(
|
||||
program: RequiredParam<NFTCollection | NFTDrop>,
|
||||
queryParams?: QueryAllParams,
|
||||
) {
|
||||
return useQuery(nftGetAllQuery(program, queryParams));
|
||||
}
|
||||
|
||||
+4
-2
@@ -30,7 +30,7 @@ export function nftRoyaltyQuery(
|
||||
*
|
||||
* export default function Component() {
|
||||
* const { program } = useProgram("{{program_address}}");
|
||||
* const { data: royalty, isLoading } = useRoyalty(program);
|
||||
* const { data: royalty, isLoading } = useRoyaltySettings(program);
|
||||
*
|
||||
* return (
|
||||
* <p>{royalty}</p>
|
||||
@@ -40,6 +40,8 @@ export function nftRoyaltyQuery(
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export function useRoyalty(program: RequiredParam<NFTCollection | NFTDrop>) {
|
||||
export function useRoyaltySettings(
|
||||
program: RequiredParam<NFTCollection | NFTDrop>,
|
||||
) {
|
||||
return useQuery(nftRoyaltyQuery(program));
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
import { createSOLProgramQueryKey } from "../../../core/query-utils/query-key";
|
||||
import {
|
||||
requiredParamInvariant,
|
||||
RequiredParam,
|
||||
} from "../../../core/query-utils/required-param";
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import type { NFTCollection, NFTDrop } from "@thirdweb-dev/sdk/solana";
|
||||
|
||||
export function nftTotalSupplyQuery(
|
||||
program: RequiredParam<NFTCollection | NFTDrop>,
|
||||
) {
|
||||
return {
|
||||
queryKey: createSOLProgramQueryKey(program, ["supply"] as const),
|
||||
|
||||
queryFn: async () => {
|
||||
requiredParamInvariant(program, "program is required");
|
||||
return program.totalSupply();
|
||||
},
|
||||
enabled: !!program,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the totaly supply of NFTs on the program
|
||||
* @param program - The NFT program to get the total supply of
|
||||
*
|
||||
* @example
|
||||
* ```jsx
|
||||
* import { useProgram, useTotalSupply } from "@thirdweb-dev/react/solana";
|
||||
*
|
||||
* export default function Component() {
|
||||
* const { program } = useProgram("{{program_address}}");
|
||||
* const { data: supply, isLoading } = useTotalSupply(program);
|
||||
*
|
||||
* return (
|
||||
* <pre>{JSON.stringify(supply)}</pre>
|
||||
* )
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export function useTotalSupply(
|
||||
program: RequiredParam<NFTCollection | NFTDrop>,
|
||||
) {
|
||||
return useQuery(nftTotalSupplyQuery(program));
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
import { createSOLProgramQueryKey } from "../../../core/query-utils/query-key";
|
||||
import {
|
||||
requiredParamInvariant,
|
||||
RequiredParam,
|
||||
} from "../../../core/query-utils/required-param";
|
||||
import { useMutation, useQueryClient } from "@tanstack/react-query";
|
||||
import type {
|
||||
NFTCollection,
|
||||
NFTDrop,
|
||||
UpdateCreatorInput,
|
||||
} from "@thirdweb-dev/sdk/solana";
|
||||
|
||||
/**
|
||||
* Update the creators for an NFT program
|
||||
* @param program - The NFT program instance to update the creators for
|
||||
*
|
||||
* @example
|
||||
* ```jsx
|
||||
* import { useProgram, useUpdateCreators } from "@thirdweb-dev/react/solana";
|
||||
*
|
||||
* export default function Component() {
|
||||
* const { program } = useProgram("{{program_address}}");
|
||||
* const { mutateAsync: updateCreators, isLoading, error } = useUpdateCreators(program);
|
||||
*
|
||||
* return (
|
||||
* <button
|
||||
* onClick={() => updateCreators([{ address: "0x...", share: 10 }])}
|
||||
* >
|
||||
* Update Creators
|
||||
* </button>
|
||||
* )
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export function useUpdateCreators(
|
||||
program: RequiredParam<NFTCollection | NFTDrop>,
|
||||
) {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation(
|
||||
async ({ creators, updateAll }: UpdateCreatorInput) => {
|
||||
requiredParamInvariant(program, "program is required");
|
||||
return await program.updateCreators(creators, updateAll);
|
||||
},
|
||||
{
|
||||
onSettled: () =>
|
||||
queryClient.invalidateQueries(createSOLProgramQueryKey(program)),
|
||||
},
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
import { createSOLProgramQueryKey } from "../../../core/query-utils/query-key";
|
||||
import {
|
||||
requiredParamInvariant,
|
||||
RequiredParam,
|
||||
} from "../../../core/query-utils/required-param";
|
||||
import { useMutation, useQueryClient } from "@tanstack/react-query";
|
||||
import type {
|
||||
NFTCollection,
|
||||
NFTDrop,
|
||||
UpdateRoyaltySettingsInput,
|
||||
} from "@thirdweb-dev/sdk/solana";
|
||||
|
||||
/**
|
||||
* Update the royalty for an NFT program
|
||||
* @param program - The NFT program instance to update the royalty for
|
||||
*
|
||||
* @example
|
||||
* ```jsx
|
||||
* import { useProgram, useUpdateRoyaltySettings } from "@thirdweb-dev/react/solana";
|
||||
*
|
||||
* export default function Component() {
|
||||
* const { program } = useProgram("{{program_address}}");
|
||||
* const { mutateAsync: updateRoyalties, isLoading, error } = useUpdateRoyaltySettings(program);
|
||||
*
|
||||
* return (
|
||||
* <button
|
||||
* onClick={() => updateRoyalties(300)}
|
||||
* >
|
||||
* Update Royalties
|
||||
* </button>
|
||||
* )
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export function useUpdateRoyaltySettings(
|
||||
program: RequiredParam<NFTCollection | NFTDrop>,
|
||||
) {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation(
|
||||
async ({ sellerFeeBasisPoints, updateAll }: UpdateRoyaltySettingsInput) => {
|
||||
requiredParamInvariant(program, "program is required");
|
||||
return await program.updateRoyalty(sellerFeeBasisPoints, updateAll);
|
||||
},
|
||||
{
|
||||
onSettled: () =>
|
||||
queryClient.invalidateQueries(createSOLProgramQueryKey(program)),
|
||||
},
|
||||
);
|
||||
}
|
||||
@@ -4,7 +4,8 @@ import {
|
||||
RequiredParam,
|
||||
} from "../../../core/query-utils/required-param";
|
||||
import { useMutation, useQueryClient } from "@tanstack/react-query";
|
||||
import type { Amount, Token } from "@thirdweb-dev/sdk/solana";
|
||||
import type { Amount } from "@thirdweb-dev/sdk";
|
||||
import type { Token } from "@thirdweb-dev/sdk/solana";
|
||||
|
||||
export type TransferTokenMutationParams = {
|
||||
amount: Amount;
|
||||
|
||||
@@ -14,6 +14,11 @@ export * from "./hooks/program/useProgramAccountType";
|
||||
export * from "./hooks/nft/useNFTs";
|
||||
export * from "./hooks/nft/useTransferNFT";
|
||||
export * from "./hooks/nft/useBurnNFT";
|
||||
export * from "./hooks/nft/useRoyaltySettings";
|
||||
export * from "./hooks/nft/useUpdateRoyaltySettings";
|
||||
export * from "./hooks/nft/useCreators";
|
||||
export * from "./hooks/nft/useUpdateCreators";
|
||||
export * from "./hooks/nft/useTotalSupply";
|
||||
|
||||
// NFT Collection
|
||||
export * from "./hooks/nft/collection/useMintNFT";
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import { ThirdwebAuthConfig } from "../contexts/thirdweb-auth";
|
||||
import { ThirdwebSDKProvider } from "./base";
|
||||
import type { WalletAdapter } from "@solana/wallet-adapter-base";
|
||||
import { PhantomWalletAdapter } from "@solana/wallet-adapter-phantom";
|
||||
import {
|
||||
ConnectionProvider,
|
||||
useWallet,
|
||||
WalletProvider,
|
||||
} from "@solana/wallet-adapter-react";
|
||||
import { PhantomWalletAdapter } from "@solana/wallet-adapter-wallets";
|
||||
import { getUrlForNetwork, Network } from "@thirdweb-dev/sdk/solana";
|
||||
import { PropsWithChildren } from "react";
|
||||
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1,5 +1,195 @@
|
||||
# @thirdweb-dev/sdk
|
||||
|
||||
## 3.6.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#408](https://github.com/thirdweb-dev/js/pull/408) [`48797c7`](https://github.com/thirdweb-dev/js/commit/48797c7cf0695965e33eb6bf602be4652f7085a8) Thanks [@jnsdls](https://github.com/jnsdls)! - [EVM] - add `Gasless` as a possible extension to feature-detect
|
||||
|
||||
- [#402](https://github.com/thirdweb-dev/js/pull/402) [`83dcaf7`](https://github.com/thirdweb-dev/js/commit/83dcaf70584af8c5cdf0427f9fc1ba82d89f0887) Thanks [@adam-maj](https://github.com/adam-maj)! - Expose sdk.fromWallet and wallet classes
|
||||
|
||||
- [#412](https://github.com/thirdweb-dev/js/pull/412) [`f03be39`](https://github.com/thirdweb-dev/js/commit/f03be398e0d7b75c9c5b4fb643f35903e89a17e7) Thanks [@easonchai](https://github.com/easonchai)! - Correctly handle contracts using the SignatureMintERC1155 ContractKit extension
|
||||
|
||||
- [#283](https://github.com/thirdweb-dev/js/pull/283) [`2eaa67a`](https://github.com/thirdweb-dev/js/commit/2eaa67acbe21464e7715d0b696afdc024460a44d) Thanks [@adam-maj](https://github.com/adam-maj)! - AppURI detection now enabled
|
||||
|
||||
- [#414](https://github.com/thirdweb-dev/js/pull/414) [`47f8945`](https://github.com/thirdweb-dev/js/commit/47f8945325447874b1ace0359919c1d54fd55436) Thanks [@joaquim-verges](https://github.com/joaquim-verges)! - Improve error parsing
|
||||
|
||||
## 3.6.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#405](https://github.com/thirdweb-dev/js/pull/405) [`ccb7db4`](https://github.com/thirdweb-dev/js/commit/ccb7db48739b8dddcb2c032b3b6e3e5200485715) Thanks [@nachoiacovino](https://github.com/nachoiacovino)! - Add updateAll param to creators and royalty update hooks for Solana
|
||||
|
||||
- [#404](https://github.com/thirdweb-dev/js/pull/404) [`9151aa7`](https://github.com/thirdweb-dev/js/commit/9151aa7dc80754a7aa4fd3f6ce0207bccbb6451f) Thanks [@jnsdls](https://github.com/jnsdls)! - [EVM] - expose `getDefaultTrustedForwarders` helper function
|
||||
|
||||
- [#305](https://github.com/thirdweb-dev/js/pull/305) [`5a01c53`](https://github.com/thirdweb-dev/js/commit/5a01c537e30bd7ef562aad1012413990de6faedf) Thanks [@joaquim-verges](https://github.com/joaquim-verges)! - Update to Metaplex 0.17
|
||||
|
||||
## 3.6.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#398](https://github.com/thirdweb-dev/js/pull/398) [`15514f1`](https://github.com/thirdweb-dev/js/commit/15514f190a844d809ae5b1edb580aab46a682485) Thanks [@jnsdls](https://github.com/jnsdls)! - [EVM] - add `defaultValue` to constructorParams schema for releases
|
||||
|
||||
- [#388](https://github.com/thirdweb-dev/js/pull/388) [`7c0744a`](https://github.com/thirdweb-dev/js/commit/7c0744a006e78987ad8b271b2c64f4bac7759510) Thanks [@adam-maj](https://github.com/adam-maj)! - Add support for total supply and pagination on get all
|
||||
|
||||
- [#395](https://github.com/thirdweb-dev/js/pull/395) [`f8bceec`](https://github.com/thirdweb-dev/js/commit/f8bceec10c60b30dc3d6f45926e2a9e018202578) Thanks [@jnsdls](https://github.com/jnsdls)! - [Solana] - fix claim condition reset to native token from custom
|
||||
|
||||
- [#399](https://github.com/thirdweb-dev/js/pull/399) [`887af24`](https://github.com/thirdweb-dev/js/commit/887af24450e316c2ea390cd49c0563cebe793c0f) Thanks [@jnsdls](https://github.com/jnsdls)! - [EVM] - fix custom error handling for null-ish error values
|
||||
|
||||
- [#390](https://github.com/thirdweb-dev/js/pull/390) [`96bd92e`](https://github.com/thirdweb-dev/js/commit/96bd92e724ec7d880d23348071b26ab8c21dd868) Thanks [@joaquim-verges](https://github.com/joaquim-verges)! - [SDK] Expose `getAllDetectedFeatures(ABI)` helper function
|
||||
|
||||
## 3.6.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- [#364](https://github.com/thirdweb-dev/js/pull/364) [`7cb8e59`](https://github.com/thirdweb-dev/js/commit/7cb8e59be48dc923316eb36ab43a1bef7364f6b1) Thanks [@joaquim-verges](https://github.com/joaquim-verges)! - Enable new Drop contracts
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#382](https://github.com/thirdweb-dev/js/pull/382) [`0ed77d2`](https://github.com/thirdweb-dev/js/commit/0ed77d2c9e7526444ef660aab82a950865234aa6) Thanks [@jnsdls](https://github.com/jnsdls)! - Add `constructorParams` to `ExtraPublishMetadataSchemaInput` schema to support better deploys from releases.
|
||||
|
||||
- [#385](https://github.com/thirdweb-dev/js/pull/385) [`04a47e8`](https://github.com/thirdweb-dev/js/commit/04a47e8971d28da2532ebd9db824eeb459c17bd4) Thanks [@adam-maj](https://github.com/adam-maj)! - Add retroactive royalty and creator setting
|
||||
|
||||
## 3.5.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#380](https://github.com/thirdweb-dev/js/pull/380) [`3eba69a`](https://github.com/thirdweb-dev/js/commit/3eba69afd78b7aa472a9c00c9d4220bb69ad1d3e) Thanks [@joaquim-verges](https://github.com/joaquim-verges)! - Expose sdk.wallet.getChainId()
|
||||
|
||||
- [#376](https://github.com/thirdweb-dev/js/pull/376) [`4af785c`](https://github.com/thirdweb-dev/js/commit/4af785c37c831ecd7087c1c9eb9095922cac0855) Thanks [@adam-maj](https://github.com/adam-maj)! - Update tiered-drop with tokens claimed
|
||||
|
||||
- [#373](https://github.com/thirdweb-dev/js/pull/373) [`6f818f3`](https://github.com/thirdweb-dev/js/commit/6f818f393eb9023b53a3358d62d60ec23a9246bd) Thanks [@adam-maj](https://github.com/adam-maj)! - Update tiered-drop contract version
|
||||
|
||||
- [#377](https://github.com/thirdweb-dev/js/pull/377) [`b79dc18`](https://github.com/thirdweb-dev/js/commit/b79dc18f7ab5155bbf4af02dc1a953546160bad0) Thanks [@adam-maj](https://github.com/adam-maj)! - Add event filters
|
||||
|
||||
- Updated dependencies [[`4af785c`](https://github.com/thirdweb-dev/js/commit/4af785c37c831ecd7087c1c9eb9095922cac0855), [`6f818f3`](https://github.com/thirdweb-dev/js/commit/6f818f393eb9023b53a3358d62d60ec23a9246bd)]:
|
||||
- @thirdweb-dev/contracts-js@1.2.1
|
||||
|
||||
## 3.5.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#368](https://github.com/thirdweb-dev/js/pull/368) [`4e7b293`](https://github.com/thirdweb-dev/js/commit/4e7b293c543244de79c150ca8c37d941221fc9a3) Thanks [@joaquim-verges](https://github.com/joaquim-verges)! - Fix handling of old allowlist proof format
|
||||
|
||||
- [#365](https://github.com/thirdweb-dev/js/pull/365) [`c9c0e4f`](https://github.com/thirdweb-dev/js/commit/c9c0e4ff39b054af746f3aec75fcbd0a3ef7239d) Thanks [@jnsdls](https://github.com/jnsdls)! - [EVM] - now React Native compatible
|
||||
|
||||
## 3.5.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- [#329](https://github.com/thirdweb-dev/js/pull/329) [`5200d5d`](https://github.com/thirdweb-dev/js/commit/5200d5d7e730da58bd4d3e7c222e3c661265f913) Thanks [@adam-maj](https://github.com/adam-maj)! - ### Breaking changes:
|
||||
|
||||
1. claim conditions had some changes to support the new drop contracts:
|
||||
|
||||
- `maxClaimablePerTransaction` is now named `maxClaimablePerWallet`
|
||||
- `maxQuantity` is now named `maxClaimable`
|
||||
|
||||
2. signature minting now requires a `to` address to be set for security purposees
|
||||
|
||||
### Main Changes:
|
||||
|
||||
- Support for new optimized Drop contracts
|
||||
- Support for new claim conditions with overrides
|
||||
- Don't allow zero address recipient on signature minting
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#362](https://github.com/thirdweb-dev/js/pull/362) [`42a6065`](https://github.com/thirdweb-dev/js/commit/42a606588dfed03c67c57357dd0ee1ad19fad6ea) Thanks [@joaquim-verges](https://github.com/joaquim-verges)! - [SDK] Fix fetching NFTs with numbers as ids
|
||||
|
||||
- Updated dependencies [[`aa6d9ed`](https://github.com/thirdweb-dev/js/commit/aa6d9ed75d126d7a0cca9fb8fc389ff94e9d1e14)]:
|
||||
- @thirdweb-dev/contracts-js@1.2.0
|
||||
|
||||
## 3.4.5
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#359](https://github.com/thirdweb-dev/js/pull/359) [`e731c1a`](https://github.com/thirdweb-dev/js/commit/e731c1a7c341e6f2b9cc42c88d5c1b036dcf4a7c) Thanks [@joaquim-verges](https://github.com/joaquim-verges)! - [SDK] Allow fetching claimerProofs from any claim condition
|
||||
|
||||
## 3.4.4
|
||||
|
||||
## 3.4.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#353](https://github.com/thirdweb-dev/js/pull/353) [`1c24c3c`](https://github.com/thirdweb-dev/js/commit/1c24c3c3c48476a824f817e09e7bf0fbe67c1db5) Thanks [@nachoiacovino](https://github.com/nachoiacovino)! - Add useUpdateCreators hook, fix CreatorInput schema
|
||||
|
||||
- [#357](https://github.com/thirdweb-dev/js/pull/357) [`65fc7ba`](https://github.com/thirdweb-dev/js/commit/65fc7ba6fff093a971b53cb0979c39768e090ba1) Thanks [@joaquim-verges](https://github.com/joaquim-verges)! - Expose claimConditions.getClaimerProofs(address) to get allowlist information for a given address
|
||||
|
||||
## 3.4.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#344](https://github.com/thirdweb-dev/js/pull/344) [`21c21c1`](https://github.com/thirdweb-dev/js/commit/21c21c1adfd09b60ad563bfd4c308597140de33c) Thanks [@nachoiacovino](https://github.com/nachoiacovino)! - Update internal function resolveContractUriFromAddress -> resolveContractUriFromAddress
|
||||
|
||||
- [#352](https://github.com/thirdweb-dev/js/pull/352) [`3522917`](https://github.com/thirdweb-dev/js/commit/352291791ee900e1500f84f095290497934d2f60) Thanks [@joaquim-verges](https://github.com/joaquim-verges)! - Expose marketplace.auction.executeSale(listingId)
|
||||
|
||||
## 3.4.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#343](https://github.com/thirdweb-dev/js/pull/343) [`72227b2`](https://github.com/thirdweb-dev/js/commit/72227b2e166a3a68bbb41cf2b389322f5b7547a2) Thanks [@joaquim-verges](https://github.com/joaquim-verges)! - Expose general marketplace.makeOffer() function
|
||||
|
||||
## 3.4.0
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#337](https://github.com/thirdweb-dev/js/pull/337) [`340605b`](https://github.com/thirdweb-dev/js/commit/340605b507f384fbd2999b9c16542af3c53e84a9) Thanks [@adam-maj](https://github.com/adam-maj)! - Clean native token address in listing
|
||||
|
||||
- [#342](https://github.com/thirdweb-dev/js/pull/342) [`26116a6`](https://github.com/thirdweb-dev/js/commit/26116a6f637ee845f7bd17f20ffe17caf184658e) Thanks [@joaquim-verges](https://github.com/joaquim-verges)! - Add new univeral RPC urls
|
||||
|
||||
- [#335](https://github.com/thirdweb-dev/js/pull/335) [`15f8006`](https://github.com/thirdweb-dev/js/commit/15f8006e1fb22333b7ee239b45e7b1b12d6dccc8) Thanks [@adam-maj](https://github.com/adam-maj)! - Export smart contract
|
||||
|
||||
- [#327](https://github.com/thirdweb-dev/js/pull/327) [`ef27aad`](https://github.com/thirdweb-dev/js/commit/ef27aad0aafc4577e85f44dc77dfbe880bd239b5) Thanks [@jnsdls](https://github.com/jnsdls)! - enable e2e testing
|
||||
|
||||
- Updated dependencies [[`ef27aad`](https://github.com/thirdweb-dev/js/commit/ef27aad0aafc4577e85f44dc77dfbe880bd239b5)]:
|
||||
- @thirdweb-dev/storage@1.0.6
|
||||
|
||||
## 3.3.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#332](https://github.com/thirdweb-dev/js/pull/332) [`ad851f7`](https://github.com/thirdweb-dev/js/commit/ad851f7b4d6abb5ab9364ef3dec229f913e18ce5) Thanks [@joaquim-verges](https://github.com/joaquim-verges)! - Fix for finding addresses in legacy merkle tree format
|
||||
|
||||
- [#330](https://github.com/thirdweb-dev/js/pull/330) [`6218c88`](https://github.com/thirdweb-dev/js/commit/6218c885842e6b4e44ec38ec92a9211e56c49bf4) Thanks [@joaquim-verges](https://github.com/joaquim-verges)! - Fix deploying contracts with non-32 bytes parameters like bytes4
|
||||
|
||||
## 3.3.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- [#315](https://github.com/thirdweb-dev/js/pull/315) [`89ff921`](https://github.com/thirdweb-dev/js/commit/89ff921a7d9f0e42b4e6707c8b56d0aab95c1aa0) Thanks [@furqanrydhan](https://github.com/furqanrydhan)! - fixing vite, multihash moved to non lazy load + cbor-x instead of cbor-web
|
||||
|
||||
- [#321](https://github.com/thirdweb-dev/js/pull/321) [`a57b4f0`](https://github.com/thirdweb-dev/js/commit/a57b4f01f3a49590b897101f2730582e4124a554) Thanks [@joaquim-verges](https://github.com/joaquim-verges)! - [SDK] Implement sharded merkle trees for lightweight allowlist checks
|
||||
|
||||
**Behavior change**
|
||||
|
||||
We've made allowlists much more performant using sharded merkle trees. This allows us to process large allowlists (1M+) efficiently.
|
||||
|
||||
To support those large allowlists, fetching claim conditions does not fetch the allowlist data by default anymore. Instead, you can pass an options object to additionally fetch the allowlist data along with the rest of the claim conditions data.
|
||||
|
||||
This affects `ClaimConditions.getActive()` and `ClaimConditions.getAll()`
|
||||
|
||||
Examples:
|
||||
|
||||
```ts
|
||||
const activeClaimCondition =
|
||||
await contract.erc721.claimConditions.getActive();
|
||||
// `activeClaimCondition.snapshot` is undefined
|
||||
const activeclaimConditionWithtAllowList =
|
||||
await contract.erc721.claimConditions.getActive({
|
||||
withAllowList: true,
|
||||
});
|
||||
// `activeClaimCondition.snapshot` returns the allowlist data
|
||||
```
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#326](https://github.com/thirdweb-dev/js/pull/326) [`126752d`](https://github.com/thirdweb-dev/js/commit/126752d7d02c9a808a63fb9e67a9df6658b5682b) Thanks [@jnsdls](https://github.com/jnsdls)! - [EVM] - expose fn to get ipfs hash from bytecote publicly
|
||||
|
||||
- [#328](https://github.com/thirdweb-dev/js/pull/328) [`df74340`](https://github.com/thirdweb-dev/js/commit/df74340fa51323304c32419761d6f18628b060fa) Thanks [@joaquim-verges](https://github.com/joaquim-verges)! - Update cbor-x import to work with es2018 builds (embeds)
|
||||
|
||||
- Updated dependencies [[`87fd6ab`](https://github.com/thirdweb-dev/js/commit/87fd6ab14e1a67a1b12e72bd397fb21769537307)]:
|
||||
- @thirdweb-dev/[email protected]
|
||||
|
||||
## 3.2.6
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"main": "dist/thirdweb-dev-sdk-evm-wallets.cjs.js",
|
||||
"module": "dist/thirdweb-dev-sdk-evm-wallets.esm.js"
|
||||
}
|
||||
+23
-17
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@thirdweb-dev/sdk",
|
||||
"version": "3.2.6",
|
||||
"version": "3.6.3",
|
||||
"description": "The main thirdweb SDK.",
|
||||
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/sdk",
|
||||
"license": "Apache-2.0",
|
||||
@@ -19,6 +19,10 @@
|
||||
"module": "./solana/dist/thirdweb-dev-sdk-solana.esm.js",
|
||||
"default": "./solana/dist/thirdweb-dev-sdk-solana.cjs.js"
|
||||
},
|
||||
"./evm/wallets": {
|
||||
"module": "./evm/wallets/dist/thirdweb-dev-sdk-evm-wallets.esm.js",
|
||||
"default": "./evm/wallets/dist/thirdweb-dev-sdk-evm-wallets.cjs.js"
|
||||
},
|
||||
"./solana/server": {
|
||||
"module": "./solana/server/dist/thirdweb-dev-sdk-solana-server.esm.js",
|
||||
"default": "./solana/server/dist/thirdweb-dev-sdk-solana-server.cjs.js"
|
||||
@@ -28,6 +32,7 @@
|
||||
"files": [
|
||||
"dist/",
|
||||
"evm/",
|
||||
"wallets/",
|
||||
"solana/",
|
||||
"server/"
|
||||
],
|
||||
@@ -35,6 +40,7 @@
|
||||
"entrypoints": [
|
||||
"index.ts",
|
||||
"evm/index.ts",
|
||||
"evm/wallets/index.ts",
|
||||
"solana/index.ts",
|
||||
"solana/server/index.ts"
|
||||
],
|
||||
@@ -57,7 +63,7 @@
|
||||
"test:evm:all": "SWC_NODE_PROJECT=./tsconfig.test.json mocha --config './test/evm/.mocharc.json' --timeout 30000 --parallel './test/evm/**/*.test.ts'",
|
||||
"test:evm": "make test-evm",
|
||||
"test:evm:single": "SWC_NODE_PROJECT=./tsconfig.test.json mocha --config './test/evm/.mocharc.json' --timeout 30000",
|
||||
"node:solana:start": "DEBUG='amman:(info|error|debug)' amman start",
|
||||
"node:solana:start": "DEBUG='amman:(info|error|debug)' amman start --forceClone",
|
||||
"node:solana:stop": "amman stop",
|
||||
"test:solana:all": "SWC_NODE_PROJECT=./tsconfig.test.json mocha --config './test/solana/.mocharc.json' --timeout 30000 --parallel './test/solana/**/*.test.ts'",
|
||||
"test:solana": "make test-sol",
|
||||
@@ -65,24 +71,23 @@
|
||||
"push": "yalc push"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@gmrchk/cli-testing-library": "^0.1.2",
|
||||
"@metaplex-foundation/amman": "^0.10.0",
|
||||
"@aws-sdk/client-secrets-manager": "^3.216.0",
|
||||
"@metaplex-foundation/amman": "^0.12.0",
|
||||
"@metaplex-foundation/amman-client": "^0.2.1",
|
||||
"@microsoft/api-documenter": "^7.19.4",
|
||||
"@microsoft/api-extractor": "^7.29.2",
|
||||
"@microsoft/tsdoc": "^0.14.1",
|
||||
"@nomiclabs/hardhat-ethers": "2.0.5",
|
||||
"@nomiclabs/hardhat-ethers": "^2.0.5",
|
||||
"@preconstruct/cli": "^2.2.1",
|
||||
"@swc-node/register": "^1.5.1",
|
||||
"@swc/core": "^1.2.177",
|
||||
"@types/chai": "^4.3.3",
|
||||
"@types/deep-equal-in-any-order": "^1.0.1",
|
||||
"@types/mocha": "^9.1.1",
|
||||
"@types/mocha": "^10.0.0",
|
||||
"@types/node": "^18.0.0",
|
||||
"@types/uuid": "^8.3.3",
|
||||
"@typescript-eslint/eslint-plugin": "^5.33.0",
|
||||
"@typescript-eslint/parser": "^5.33.0",
|
||||
"cbor": "^8.1.0",
|
||||
"chai": "^4.3.6",
|
||||
"deep-equal-in-any-order": "^1.1.18",
|
||||
"eslint": "^8.21.0",
|
||||
@@ -91,34 +96,35 @@
|
||||
"eslint-plugin-inclusive-language": "^2.2.0",
|
||||
"eslint-plugin-prettier": "^4.2.1",
|
||||
"eslint-plugin-tsdoc": "^0.2.16",
|
||||
"esm": "^3.2.25",
|
||||
"ethers": "^5.7.0",
|
||||
"ethers": "^5.7.2",
|
||||
"hardhat": "^2.9.3",
|
||||
"mocha": "^10.0.0",
|
||||
"node-stdlib-browser": "^1.2.0",
|
||||
"prettier": "^2.7.1",
|
||||
"typescript": "^4.7.4"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@aws-sdk/client-secrets-manager": "^3.215.0",
|
||||
"ethers": "^5"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@aws-sdk/client-secrets-manager": {
|
||||
"optional": true
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"@metaplex-foundation/js": "^0.15.0",
|
||||
"@metaplex-foundation/mpl-token-metadata": "^2.2.2",
|
||||
"@metaplex-foundation/js": "^0.17.6",
|
||||
"@metaplex-foundation/mpl-token-metadata": "^2.3.3",
|
||||
"@project-serum/anchor": "^0.25.0",
|
||||
"@solana/spl-token": "^0.2.0",
|
||||
"@solana/web3.js": "^1.50.1",
|
||||
"@solana/spl-token": "^0.3.5",
|
||||
"@solana/web3.js": "^1.62.0",
|
||||
"@thirdweb-dev/contracts-js": "*",
|
||||
"@thirdweb-dev/storage": "*",
|
||||
"bn.js": "^5.2.1",
|
||||
"bs58": "^5.0.0",
|
||||
"cbor-web": "^8.1.0",
|
||||
"cross-fetch": "^3.1.5",
|
||||
"eventemitter3": "^4.0.7",
|
||||
"fast-deep-equal": "^3.1.3",
|
||||
"form-data": "^4.0.0",
|
||||
"merkletreejs": "^0.2.24",
|
||||
"multihashes": "^4.0.3",
|
||||
"tiny-invariant": "^1.2.0",
|
||||
"tweetnacl": "^1.0.3",
|
||||
"uuid": "^9.0.0",
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
export const DEFAULT_API_KEY =
|
||||
"c6634ad2d97b74baf15ff556016830c251050e6c36b9da508ce3ec80095d3dc1";
|
||||
|
||||
export function getRpcUrl(network: string) {
|
||||
return `https://${network}.rpc.thirdweb.com/${DEFAULT_API_KEY}`;
|
||||
}
|
||||
@@ -1,19 +1,25 @@
|
||||
import { z } from "zod";
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export const DEFAULT_QUERY_ALL_COUNT = 100;
|
||||
|
||||
export const QueryAllParamsSchema = z
|
||||
.object({
|
||||
start: z.number().default(0),
|
||||
count: z.number().default(DEFAULT_QUERY_ALL_COUNT),
|
||||
})
|
||||
.default({
|
||||
start: 0,
|
||||
count: DEFAULT_QUERY_ALL_COUNT,
|
||||
});
|
||||
|
||||
/**
|
||||
* Pagination Parameters
|
||||
* @public
|
||||
*/
|
||||
export interface QueryAllParams {
|
||||
/**
|
||||
* the index to start from (default: 0)
|
||||
*/
|
||||
start?: number;
|
||||
/**
|
||||
* how many items to return (default: 100)
|
||||
*/
|
||||
count?: number;
|
||||
}
|
||||
export type QueryAllParams = Exclude<
|
||||
z.input<typeof QueryAllParamsSchema>,
|
||||
undefined
|
||||
>;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user