Compare commits
15
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
36f2b70d57 | ||
|
|
849146bf5c | ||
|
|
4cac79c45d | ||
|
|
1bda83b114 | ||
|
|
ce05bfd861 | ||
|
|
d982a98b0c | ||
|
|
b983087101 | ||
|
|
b25789fa46 | ||
|
|
e39b66f309 | ||
|
|
5f5ab015e1 | ||
|
|
f4f05bd9a4 | ||
|
|
2f5b66bef9 | ||
|
|
63258bc9c3 | ||
|
|
a80fc97b6a | ||
|
|
24f66e38c2 |
+60
-56
@@ -1,5 +1,9 @@
|
||||
# Contributing to thirdweb
|
||||
|
||||
You can find a full video tutorial on how to contribute to thirdweb below:
|
||||
|
||||
https://www.youtube.com/watch?v=TXsQ3qok3B0
|
||||
|
||||
## Getting Started
|
||||
|
||||
To get started, read the [How this repo works](#how-this-repo-works) section below to learn about the structure of this repo.
|
||||
@@ -16,7 +20,7 @@ If you have any questions about the issue, feel free to ask on our [Discord serv
|
||||
|
||||
We use [Turborepo](https://turborepo.org/docs/getting-started) to manage the monorepo, and help speed up the [CI/CD](https://www.atlassian.com/continuous-delivery/principles/continuous-integration-vs-delivery-vs-deployment) pipeline to ship to production faster 🚢.
|
||||
|
||||
You can see a quick outline of each of the projects within this repo below, which each live within the [/packages](/packages) directory:
|
||||
You can see a quick outline of each of the projects within this repo below, each living within the [/packages](/packages) directory:
|
||||
|
||||
| Package | Description | Latest Version |
|
||||
| ------------------------------ | -------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
@@ -58,75 +62,75 @@ To begin:
|
||||
|
||||
Now you have got the repo on your local machine, and you're ready to start making your changes!
|
||||
|
||||
### Test Your Changes
|
||||
|
||||
We use [yalc](https://github.com/wclr/yalc) to test changes locally.
|
||||
|
||||
Install the yalc CLI globally:
|
||||
|
||||
```bash
|
||||
yarn global add yalc
|
||||
```
|
||||
|
||||
First, create a test project where you can experiment with your changes:
|
||||
|
||||
You can create a basic starter project with the `sdk` and `react` packages installed using the CLI:
|
||||
|
||||
```bash
|
||||
npx thirdweb create --app
|
||||
```
|
||||
|
||||
Use `yalc` to link your local changes in the monorepo to the test project, by running the following command from your test repo:
|
||||
|
||||
```bash
|
||||
yalc add @thirdweb-dev/react # Link the react package
|
||||
yalc add @thirdweb-dev/sdk # Link the sdk package
|
||||
# etc...
|
||||
```
|
||||
|
||||
From the monorepo, run the following command to publish your local changes to the test project:
|
||||
|
||||
```bash
|
||||
yarn push
|
||||
```
|
||||
|
||||
Now, each time you make a change to the monorepo, you can run `yarn push` to publish your changes to the test project.
|
||||
|
||||
In your test project, you need to:
|
||||
|
||||
1. Delete the dependencies cache. If you're using Next.js, that is the `.next` directory, and if you're using CRA, that is the `node_modules/.cache` directory.
|
||||
2. Restart the development server.
|
||||
|
||||
<br/>
|
||||
|
||||
### Publish Your Changes
|
||||
|
||||
Once you're satisfied with your changes, you are ready to submit them for review!
|
||||
|
||||
1. Use [changeset](https://github.com/changesets/changesets) to generate a changeset file:
|
||||
|
||||
```
|
||||
yarn changeset
|
||||
```
|
||||
```
|
||||
yarn changeset
|
||||
```
|
||||
|
||||
We follow [semantic versioning](https://semver.org/) for generating versioned releases of our packages (i.e. version = `MAJOR.MINOR.PATCH`)
|
||||
We follow [semantic versioning](https://semver.org/) for generating versioned releases of our packages (i.e. version = `MAJOR.MINOR.PATCH`)
|
||||
|
||||
- Update `major` for breaking changes
|
||||
- Update `minor` for new features,
|
||||
- Update `patch` for non-breaking bug fixes, etc)
|
||||
- Update `major` for breaking changes
|
||||
- Update `minor` for new features,
|
||||
- Update `patch` for non-breaking bug fixes, etc)
|
||||
|
||||
2. Commit the changeset along with your changes:
|
||||
|
||||
```
|
||||
git commit -am "My commit message"
|
||||
```
|
||||
```
|
||||
git commit -am "My commit message"
|
||||
```
|
||||
|
||||
3. Push your changes to the SDK:
|
||||
|
||||
```
|
||||
git push origin MY_BRANCH_NAME
|
||||
```
|
||||
```
|
||||
git push origin MY_BRANCH_NAME
|
||||
```
|
||||
|
||||
4. Create a [pull request](https://www.atlassian.com/git/tutorials/making-a-pull-request) to the `main` branch of the official (not your fork) SDK repo.
|
||||
|
||||
It's helpful to tag PRs with `[SDK]`, `[REACT]`, `[AUTH]`, (the name of the package you're modifying) to indicate the package that you are engaging with.
|
||||
|
||||
<br/>
|
||||
|
||||
### Testing Your Changes
|
||||
|
||||
When you make a pull request, your changes will be tested automatically by our CI/CD pipeline using [GitHub Actions](https://github.com/features/actions).
|
||||
|
||||
On your pull request, you can release your changes to a `dev` version by adding a **comment** with the following text:
|
||||
|
||||
```
|
||||
/release-pr
|
||||
```
|
||||
|
||||
This comment triggers the `release-pr` GitHub Action that publishes your changes to a `dev` version of the package(s) you are modifying.
|
||||
|
||||
Once this is done, you can test your changes by installing the `dev` version of the package(s).
|
||||
|
||||
If you don't already have a test project, you can use the [CLI](https://github.com/thirdweb-dev/thirdweb-cli) to create one:
|
||||
|
||||
```bash
|
||||
npx thirdweb create
|
||||
```
|
||||
|
||||
Inside your test project, you can install the `dev` version of the package(s) you are modifying.
|
||||
|
||||
For example, if you are modifying the `@thirdweb-dev/react` package, you can install the `dev` version of the package by running:
|
||||
|
||||
```
|
||||
yarn add @thirdweb-dev/sdk@dev
|
||||
```
|
||||
|
||||
This will install the `dev` version of the `@thirdweb-dev/react` package in your project, as you can see in the `package.json` file:
|
||||
|
||||
```diff
|
||||
"dependencies": {
|
||||
- "@thirdweb-dev/react": "^2",
|
||||
+ "@thirdweb-dev/react": "^2.9.7-dev-b073878",
|
||||
}
|
||||
```
|
||||
|
||||
You can now test your changes in your test project!
|
||||
It's helpful to tag PRs with `[SDK]`, `[REACT]`, `[AUTH]`, (the name of the package you're modifying) to indicate the package that you are engaging with.
|
||||
|
||||
+5
-1
@@ -26,7 +26,8 @@
|
||||
"version-packages": "changeset version",
|
||||
"release": "node ./scripts/pre-release.mjs && changeset publish",
|
||||
"version-packages:nightly": "changeset version --snapshot nightly",
|
||||
"release:nightly": "node ./scripts/pre-release.mjs && changeset publish --tag nightly"
|
||||
"release:nightly": "node ./scripts/pre-release.mjs && changeset publish --tag nightly",
|
||||
"push": "turbo run push"
|
||||
},
|
||||
"preconstruct": {
|
||||
"packages": [
|
||||
@@ -47,5 +48,8 @@
|
||||
},
|
||||
"manypkg": {
|
||||
"defaultBranch": "main"
|
||||
},
|
||||
"devDependencies": {
|
||||
"yalc": "^1.0.0-pre.53"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,26 @@
|
||||
# @thirdweb-dev/auth
|
||||
|
||||
## 2.0.8
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`ce05bfd`](https://github.com/thirdweb-dev/js/commit/ce05bfd8615a9c79664856bce53de8b43bed5c87)]:
|
||||
- @thirdweb-dev/sdk@3.0.8
|
||||
|
||||
## 2.0.7
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`5f5ab01`](https://github.com/thirdweb-dev/js/commit/5f5ab015e1dd3c471d6affe995ef36ec88932b3c)]:
|
||||
- @thirdweb-dev/sdk@3.0.7
|
||||
|
||||
## 2.0.6
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`a80fc97`](https://github.com/thirdweb-dev/js/commit/a80fc97b6a1e72ed46a400b4b602e180947fb870)]:
|
||||
- @thirdweb-dev/sdk@3.0.6
|
||||
|
||||
## 2.0.5
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@thirdweb-dev/auth",
|
||||
"version": "2.0.5",
|
||||
"version": "2.0.8",
|
||||
"exports": {
|
||||
"./package.json": "./package.json",
|
||||
"./express": {
|
||||
|
||||
@@ -1,5 +1,26 @@
|
||||
# thirdweb
|
||||
|
||||
## 0.7.19
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`ce05bfd`](https://github.com/thirdweb-dev/js/commit/ce05bfd8615a9c79664856bce53de8b43bed5c87)]:
|
||||
- @thirdweb-dev/sdk@3.0.8
|
||||
|
||||
## 0.7.18
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`5f5ab01`](https://github.com/thirdweb-dev/js/commit/5f5ab015e1dd3c471d6affe995ef36ec88932b3c)]:
|
||||
- @thirdweb-dev/sdk@3.0.7
|
||||
|
||||
## 0.7.17
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`a80fc97`](https://github.com/thirdweb-dev/js/commit/a80fc97b6a1e72ed46a400b4b602e180947fb870)]:
|
||||
- @thirdweb-dev/sdk@3.0.6
|
||||
|
||||
## 0.7.16
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "thirdweb",
|
||||
"main": "dist/cli/index.js",
|
||||
"version": "0.7.16",
|
||||
"version": "0.7.19",
|
||||
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/cli",
|
||||
"author": "thirdweb eng <[email protected]>",
|
||||
"license": "Apache-2.0",
|
||||
|
||||
@@ -1,5 +1,34 @@
|
||||
# @thirdweb-dev/react
|
||||
|
||||
## 3.0.8
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#209](https://github.com/thirdweb-dev/js/pull/209) [`1bda83b`](https://github.com/thirdweb-dev/js/commit/1bda83b1142406892acfb64576fce25d2647afa7) Thanks [@jnsdls](https://github.com/jnsdls)! - fix useLayoutEffect during SSR warning
|
||||
|
||||
- Updated dependencies [[`ce05bfd`](https://github.com/thirdweb-dev/js/commit/ce05bfd8615a9c79664856bce53de8b43bed5c87)]:
|
||||
- @thirdweb-dev/sdk@3.0.8
|
||||
|
||||
## 3.0.7
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#197](https://github.com/thirdweb-dev/js/pull/197) [`f4f05bd`](https://github.com/thirdweb-dev/js/commit/f4f05bd9a4ec98e9abc6716006353f330b7be055) Thanks [@jnsdls](https://github.com/jnsdls)! - make it obvious when the <Web3Button /> will trigger a network switch
|
||||
|
||||
- Updated dependencies [[`5f5ab01`](https://github.com/thirdweb-dev/js/commit/5f5ab015e1dd3c471d6affe995ef36ec88932b3c), [`5f5ab01`](https://github.com/thirdweb-dev/js/commit/5f5ab015e1dd3c471d6affe995ef36ec88932b3c)]:
|
||||
- @thirdweb-dev/sdk@3.0.7
|
||||
- @thirdweb-dev/solana@0.2.15
|
||||
|
||||
## 3.0.6
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#179](https://github.com/thirdweb-dev/js/pull/179) [`63258bc`](https://github.com/thirdweb-dev/js/commit/63258bc9c3443db7d12fc1dc6fbd483926c92d3e) Thanks [@joaquim-verges](https://github.com/joaquim-verges)! - Expose simple provider and useSDK hooks for Solana
|
||||
|
||||
- Updated dependencies [[`a80fc97`](https://github.com/thirdweb-dev/js/commit/a80fc97b6a1e72ed46a400b4b602e180947fb870)]:
|
||||
- @thirdweb-dev/sdk@3.0.6
|
||||
- @thirdweb-dev/solana@0.2.14
|
||||
|
||||
## 3.0.5
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
# Migration Guide
|
||||
|
||||
If you are looking to upgrade from an earlier version of the React SDK, below are the breaking changes that you should be aware of between each version.
|
||||
|
||||
## Upgrading to Version 3
|
||||
|
||||
Version 3 of the React SDK introduces a significant (87%) reduction in package size and first-class support for using custom contracts with the SDK. Learn more about why we made these changes and how it improves the SDK in our [blog post](https://blog.thirdweb.com/sdk-major-update/).
|
||||
|
||||
### useContractData
|
||||
|
||||
The `useContractData` hook to read data from a smart contract has been renamed to `useContractRead`.
|
||||
|
||||
```diff
|
||||
- const { data } = useContractData(contract, 'name')
|
||||
+ const { data } = useContractRead(contract, 'name')
|
||||
```
|
||||
|
||||
### useContractCall
|
||||
|
||||
The `useContractCall` hook to call a smart contract function has been renamed to `useContractWrite`.
|
||||
|
||||
```diff
|
||||
- const { mutate } = useContractCall(contract, 'setName')
|
||||
+ const { mutate } = useContractWrite(contract, 'setName')
|
||||
```
|
||||
|
||||
### 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:
|
||||
|
||||
```diff
|
||||
- const contract = useNFTDrop("0x...")
|
||||
+ const { contract } = useContract("0x...")
|
||||
```
|
||||
|
||||
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.
|
||||
|
||||
### New Contract Namespaces
|
||||
|
||||
When working with contracts using the `useContract` hook, we now expose all the convenient high level APIs for each ERC standard top level.
|
||||
Calling a function that is not supported in your contract will give you an error with instructions on how to unlock that functionality.
|
||||
|
||||
```diff
|
||||
// ERC721 contracts
|
||||
- const contract.nft?.drop?.claim?.to(...)
|
||||
+ const contract.erc721.claimTo(...)
|
||||
- const contract.nft?.drop?.claim?.conditions.set(...)
|
||||
+ const contract.erc721.claimConditions.set(...)
|
||||
|
||||
// ERC1155 contracts
|
||||
- const contract.edition?.mint?.to(...)
|
||||
+ const contract.erc1155.mintTo(...)
|
||||
|
||||
// ERC20 contracts
|
||||
- const contract.token?.burn.tokens(...)
|
||||
+ const contract.erc20.burn(...)
|
||||
```
|
||||
|
||||
The `Web3Button`'s `contract` benefits from these changes as well:
|
||||
|
||||
```diff jsx
|
||||
<Web3Button
|
||||
contractAddress={...}
|
||||
- action={(contract) => contract.nft?.drop?.claim?.to(...)}
|
||||
+ action={(contract) => contract.erc721.claim(...)}
|
||||
>
|
||||
Claim
|
||||
</Web3Button>
|
||||
```
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@thirdweb-dev/react",
|
||||
"version": "3.0.5",
|
||||
"version": "3.0.8",
|
||||
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/react",
|
||||
"author": "thirdweb eng <[email protected]>",
|
||||
"license": "Apache-2.0",
|
||||
@@ -8,9 +8,15 @@
|
||||
"types": "dist/thirdweb-dev-react.cjs.d.ts",
|
||||
"module": "dist/thirdweb-dev-react.esm.js",
|
||||
"files": [
|
||||
"dist/**/*",
|
||||
"patches/**/*"
|
||||
"dist/",
|
||||
"solana/"
|
||||
],
|
||||
"preconstruct": {
|
||||
"entrypoints": [
|
||||
"index.ts",
|
||||
"solana/index.ts"
|
||||
]
|
||||
},
|
||||
"private": false,
|
||||
"scripts": {
|
||||
"format": "prettier --write 'src/**/*'",
|
||||
@@ -22,7 +28,8 @@
|
||||
"generate-snippets": "node ./scripts/generate-snippets.mjs && node ./scripts/generate-feature-snippets.mjs",
|
||||
"build": "tsc && preconstruct build",
|
||||
"e2e": "yarn test-ct",
|
||||
"test-ct": "playwright test -c playwright-ct.config.ts"
|
||||
"test-ct": "playwright test -c playwright-ct.config.ts",
|
||||
"push": "yalc push"
|
||||
},
|
||||
"sideEffects:": false,
|
||||
"devDependencies": {
|
||||
@@ -36,6 +43,10 @@
|
||||
"@playwright/experimental-ct-react": "1.25.1",
|
||||
"@playwright/test": "1.25.1",
|
||||
"@preconstruct/cli": "^2.2.1",
|
||||
"@solana/wallet-adapter-base": "^0.9.17",
|
||||
"@solana/wallet-adapter-react": "^0.15.19",
|
||||
"@solana/wallet-adapter-wallets": "^0.19.0",
|
||||
"@solana/web3.js": "^1.63.0",
|
||||
"@thirdweb-dev/sdk": "*",
|
||||
"@types/color": "^3.0.3",
|
||||
"@types/mime": "^3.0.1",
|
||||
@@ -75,7 +86,12 @@
|
||||
"wagmi": "^0.2.28"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@solana/wallet-adapter-base": "^0.9.17",
|
||||
"@solana/wallet-adapter-react": "^0.15.19",
|
||||
"@solana/wallet-adapter-wallets": "^0.19.0",
|
||||
"@solana/web3.js": "^1.63.0",
|
||||
"@thirdweb-dev/sdk": "*",
|
||||
"@thirdweb-dev/solana": "*",
|
||||
"ethers": ">=5.5.1",
|
||||
"react": ">=18.0.0",
|
||||
"react-dom": ">=18.0.0"
|
||||
@@ -83,5 +99,22 @@
|
||||
"resolutions": {
|
||||
"ansi-regex": "^6.0.1",
|
||||
"typescript": "^4.6.2"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@solana/wallet-adapter-base": {
|
||||
"optional": true
|
||||
},
|
||||
"@solana/wallet-adapter-react": {
|
||||
"optional": true
|
||||
},
|
||||
"@solana/wallet-adapter-wallets": {
|
||||
"optional": true
|
||||
},
|
||||
"@solana/web3.js": {
|
||||
"optional": true
|
||||
},
|
||||
"@thirdweb-dev/solana": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"main": "dist/thirdweb-dev-react-solana.cjs.js",
|
||||
"module": "dist/thirdweb-dev-react-solana.esm.js"
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
import { useContract } from "../../hooks/async/contracts";
|
||||
import { useNetworkMismatch } from "../../hooks/useNetworkMismatch";
|
||||
import { useNetwork } from "../../hooks/wagmi-required/useNetwork";
|
||||
import { useAddress, useChainId } from "../../hooks/wallet";
|
||||
import { useSDKChainId } from "../../providers/base";
|
||||
@@ -9,6 +10,7 @@ import {
|
||||
import { ConnectWallet } from "../ConnectWallet";
|
||||
import { Button } from "../shared/Button";
|
||||
import { ThemeProvider, ThemeProviderProps } from "../shared/ThemeProvider";
|
||||
import { FiWifi } from "@react-icons/all-files/fi/FiWifi";
|
||||
import { useMutation, useQueryClient } from "@tanstack/react-query";
|
||||
import type { SmartContract } from "@thirdweb-dev/sdk/dist/declarations/src/contracts/smart-contract";
|
||||
import type { CallOverrides } from "ethers";
|
||||
@@ -74,6 +76,8 @@ export const Web3Button = <TAction extends ActionFn>({
|
||||
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
const hasMismatch = useNetworkMismatch();
|
||||
|
||||
const switchToChainId = useMemo(() => {
|
||||
if (sdkChainId && walletChainId && sdkChainId !== walletChainId) {
|
||||
return sdkChainId;
|
||||
@@ -130,6 +134,8 @@ export const Web3Button = <TAction extends ActionFn>({
|
||||
return <ConnectWallet className={className} {...themeProps} />;
|
||||
}
|
||||
|
||||
const willSwitchNetwork = hasMismatch && !!switchNetwork;
|
||||
|
||||
return (
|
||||
<ThemeProvider {...themeProps}>
|
||||
<Button
|
||||
@@ -137,9 +143,12 @@ export const Web3Button = <TAction extends ActionFn>({
|
||||
style={{ height: "50px", minWidth: "200px", width: "100%" }}
|
||||
isLoading={mutation.isLoading || !contract}
|
||||
onClick={() => mutation.mutate()}
|
||||
isDisabled={isDisabled}
|
||||
isDisabled={willSwitchNetwork ? false : isDisabled}
|
||||
leftElement={
|
||||
willSwitchNetwork ? <FiWifi width="1em" height="1em" /> : undefined
|
||||
}
|
||||
>
|
||||
{children}
|
||||
{willSwitchNetwork ? "Switch Network" : children}
|
||||
</Button>
|
||||
</ThemeProvider>
|
||||
);
|
||||
|
||||
@@ -83,7 +83,7 @@ export function useActiveClaimCondition(
|
||||
if (erc20) {
|
||||
return erc20.claimConditions.getActive();
|
||||
}
|
||||
return undefined;
|
||||
throw new Error("Contract must be ERC721, ERC1155 or ERC20");
|
||||
},
|
||||
{
|
||||
// Checks that happen here:
|
||||
@@ -136,7 +136,7 @@ export function useClaimConditions(
|
||||
if (erc20) {
|
||||
return erc20.claimConditions.getAll();
|
||||
}
|
||||
return undefined;
|
||||
throw new Error("Contract must be ERC721, ERC1155 or ERC20");
|
||||
},
|
||||
{
|
||||
// Checks that happen here:
|
||||
@@ -207,7 +207,7 @@ export function useClaimIneligibilityReasons(
|
||||
params.walletAddress,
|
||||
);
|
||||
}
|
||||
return undefined;
|
||||
throw new Error("Contract must be ERC721, ERC1155 or ERC20");
|
||||
},
|
||||
{
|
||||
// Checks that happen here:
|
||||
@@ -284,7 +284,7 @@ export function useSetClaimConditions(
|
||||
if (erc20) {
|
||||
return erc20.claimConditions.set(phases, reset);
|
||||
}
|
||||
return undefined;
|
||||
throw new Error("Contract must be ERC721, ERC1155 or ERC20");
|
||||
},
|
||||
{
|
||||
onSettled: () => {
|
||||
@@ -374,7 +374,7 @@ export function useResetClaimConditions(
|
||||
true,
|
||||
);
|
||||
}
|
||||
return undefined;
|
||||
throw new Error("Contract must be ERC721, ERC1155 or ERC20");
|
||||
},
|
||||
{
|
||||
onSettled: () => {
|
||||
|
||||
@@ -223,7 +223,7 @@ export function useTotalCount<TContract extends NFTContract>(
|
||||
*/
|
||||
export function useTotalCirculatingSupply(
|
||||
contract: RequiredParam<NFTContract>,
|
||||
tokenId: BigNumberish,
|
||||
tokenId: RequiredParam<BigNumberish>,
|
||||
) {
|
||||
const contractAddress = contract?.getAddress();
|
||||
const { erc721, erc1155 } = getErcs(contract);
|
||||
@@ -238,6 +238,7 @@ export function useTotalCirculatingSupply(
|
||||
erc1155.totalCirculatingSupply,
|
||||
"Contract instance does not support totalCirculatingSupply",
|
||||
);
|
||||
invariant(tokenId, "No tokenId provided");
|
||||
return await erc1155.totalCirculatingSupply(tokenId);
|
||||
}
|
||||
if (erc721) {
|
||||
@@ -250,7 +251,7 @@ export function useTotalCirculatingSupply(
|
||||
invariant(false, "Unknown NFT type");
|
||||
},
|
||||
{
|
||||
enabled: !!erc721 || !!erc1155,
|
||||
enabled: !!erc721 || (!!erc1155 && tokenId !== undefined),
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ dispatch(Object.create(null));
|
||||
}
|
||||
|
||||
|
||||
export const useIsomorphicLayoutEffect = canUseDOM() ? useLayoutEffect : useEffect;
|
||||
const useIsomorphicLayoutEffect = canUseDOM() ? useLayoutEffect : useEffect;
|
||||
|
||||
|
||||
/**
|
||||
@@ -39,7 +39,7 @@ export const useIsomorphicLayoutEffect = canUseDOM() ? useLayoutEffect : useEffe
|
||||
const forceUpdate = useForceUpdate();
|
||||
|
||||
|
||||
useLayoutEffect(() => {
|
||||
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.
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
import { ThirdwebSDKContext } from "../providers/ThirdwebSDKProvider";
|
||||
import { useContext } from "react";
|
||||
|
||||
export function useSDK() {
|
||||
return useContext(ThirdwebSDKContext);
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
// Providers
|
||||
export * from "./providers/ThirdwebSDKProvider";
|
||||
export * from "./providers/ThirdwebProvider";
|
||||
// Hooks
|
||||
export * from "./hooks/useSDK";
|
||||
@@ -0,0 +1,66 @@
|
||||
import { ThirdwebSDKProvider } from "./ThirdwebSDKProvider";
|
||||
import type { WalletAdapter } from "@solana/wallet-adapter-base";
|
||||
import {
|
||||
ConnectionProvider,
|
||||
useConnection,
|
||||
useWallet,
|
||||
WalletProvider,
|
||||
} from "@solana/wallet-adapter-react";
|
||||
import { PhantomWalletAdapter } from "@solana/wallet-adapter-wallets";
|
||||
import { getUrlForNetwork, Network } from "@thirdweb-dev/solana";
|
||||
import { PropsWithChildren } from "react";
|
||||
|
||||
interface ThirdwebProviderProps {
|
||||
endpoint: Network;
|
||||
wallets?: WalletAdapter[];
|
||||
autoConnect?: boolean;
|
||||
}
|
||||
|
||||
const DEFAULT_WALLETS = [new PhantomWalletAdapter()];
|
||||
|
||||
/**
|
||||
* Gives access to the ThirdwebSDK instance and other useful hooks to the rest of the app.
|
||||
* Requires to be wrapped with a ConnectionProvider and a WalletProvider from @solana/wallet-adapter-react.
|
||||
* @example
|
||||
* ```tsx
|
||||
* import { ThirdwebProvider } from "@thirdweb-dev/react/solana";
|
||||
*
|
||||
* const App = () => {
|
||||
* return (
|
||||
* <ThirdwebProvider endpoint="devnet">
|
||||
* <YourApp />
|
||||
* </ThirdwebProvider>
|
||||
* )};
|
||||
* ```
|
||||
* @beta
|
||||
*/
|
||||
export const ThirdwebProvider: React.FC<
|
||||
PropsWithChildren<ThirdwebProviderProps>
|
||||
> = ({ endpoint, wallets, autoConnect, children }) => {
|
||||
const clusterUrl = getUrlForNetwork(endpoint);
|
||||
return (
|
||||
<ConnectionProvider endpoint={clusterUrl}>
|
||||
<WalletProvider
|
||||
wallets={wallets || DEFAULT_WALLETS}
|
||||
autoConnect={autoConnect || true}
|
||||
>
|
||||
<ThirdwebWrapperProvider>{children}</ThirdwebWrapperProvider>
|
||||
</WalletProvider>
|
||||
</ConnectionProvider>
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export const ThirdwebWrapperProvider: React.FC<PropsWithChildren> = ({
|
||||
children,
|
||||
}) => {
|
||||
const { connection } = useConnection();
|
||||
const wallet = useWallet();
|
||||
return (
|
||||
<ThirdwebSDKProvider connection={connection} wallet={wallet}>
|
||||
{children}
|
||||
</ThirdwebSDKProvider>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,68 @@
|
||||
import type { WalletContextState } from "@solana/wallet-adapter-react";
|
||||
import type { Connection } from "@solana/web3.js";
|
||||
import { ThirdwebSDK } from "@thirdweb-dev/solana";
|
||||
import {
|
||||
createContext,
|
||||
FC,
|
||||
PropsWithChildren,
|
||||
useEffect,
|
||||
useState,
|
||||
} from "react";
|
||||
|
||||
interface ThirdwebSDKProviderProps {
|
||||
connection: Connection;
|
||||
wallet?: WalletContextState;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gives access to the ThirdwebSDK instance and other useful hooks to the rest of the app.
|
||||
* Requires to be wrapped with a ConnectionProvider and a WalletProvider from @solana/wallet-adapter-react.
|
||||
* @example
|
||||
* ```tsx
|
||||
* import {
|
||||
* useConnection,
|
||||
* useWallet,
|
||||
* } from "@solana/wallet-adapter-react";
|
||||
* import { ThirdwebProvider } from "@thirdweb-dev/react/solana";
|
||||
*
|
||||
* const ThirdwebApp = () => {
|
||||
* const { connection } = useConnection();
|
||||
* const wallet = useWallet();
|
||||
* return (
|
||||
* <ThirdwebSDKProvider connection={connection} wallet={wallet}>
|
||||
* <YourApp />
|
||||
* </ThirdwebSDKProvider>
|
||||
* )};
|
||||
* ```
|
||||
*/
|
||||
export const ThirdwebSDKProvider: FC<
|
||||
PropsWithChildren<ThirdwebSDKProviderProps>
|
||||
> = ({ children, connection, wallet }) => {
|
||||
const [sdk, setSDK] = useState<ThirdwebSDK | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (connection) {
|
||||
setSDK(new ThirdwebSDK(connection));
|
||||
} else {
|
||||
setSDK(null);
|
||||
}
|
||||
}, [connection]);
|
||||
|
||||
useEffect(() => {
|
||||
if (sdk) {
|
||||
if (wallet?.publicKey) {
|
||||
sdk.wallet.connect(wallet);
|
||||
} else {
|
||||
sdk.wallet.disconnect();
|
||||
}
|
||||
}
|
||||
}, [sdk, wallet]);
|
||||
|
||||
return (
|
||||
<ThirdwebSDKContext.Provider value={sdk}>
|
||||
{children}
|
||||
</ThirdwebSDKContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
export const ThirdwebSDKContext = createContext<ThirdwebSDK | null>(null);
|
||||
@@ -1,5 +1,26 @@
|
||||
# @thirdweb-dev/sdk
|
||||
|
||||
## 3.0.8
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#205](https://github.com/thirdweb-dev/js/pull/205) [`ce05bfd`](https://github.com/thirdweb-dev/js/commit/ce05bfd8615a9c79664856bce53de8b43bed5c87) Thanks [@joaquim-verges](https://github.com/joaquim-verges)! - Fix Buffer usage in SDK
|
||||
|
||||
## 3.0.7
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#199](https://github.com/thirdweb-dev/js/pull/199) [`5f5ab01`](https://github.com/thirdweb-dev/js/commit/5f5ab015e1dd3c471d6affe995ef36ec88932b3c) Thanks [@joaquim-verges](https://github.com/joaquim-verges)! - Fix getOwned for signature drop
|
||||
|
||||
## 3.0.6
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#195](https://github.com/thirdweb-dev/js/pull/195) [`a80fc97`](https://github.com/thirdweb-dev/js/commit/a80fc97b6a1e72ed46a400b4b602e180947fb870) Thanks [@jnsdls](https://github.com/jnsdls)! - add missing roles for pre-built contracts
|
||||
|
||||
- Updated dependencies [[`24f66e3`](https://github.com/thirdweb-dev/js/commit/24f66e38c256f7bd69341b92ba30bd35d14b1caa)]:
|
||||
- @thirdweb-dev/storage@1.0.3
|
||||
|
||||
## 3.0.5
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
# Migration Guide
|
||||
|
||||
If you are looking to upgrade from an earlier version of the SDK, below are the breaking changes that you should be aware of between each version.
|
||||
|
||||
## Upgrading to Version 3
|
||||
|
||||
Version 3 of the SDK introduces a significant (87%) reduction in package size and first-class support for using custom contracts with the SDK. Learn more about why we made these changes and how it improves the SDK in our [blog post](https://blog.thirdweb.com/sdk-major-update/).
|
||||
|
||||
### Getting Contracts is now Async
|
||||
|
||||
The `getContract` and similar functions such as `getNFTDrop` or `getMarketplace` are now asynchronous. This means that you will need to `await` the result of these functions before using them.
|
||||
|
||||
**Custom**:
|
||||
|
||||
```diff
|
||||
- const contract = getContract("0x...")
|
||||
+ const contract = await getContract("0x...")
|
||||
```
|
||||
|
||||
**Prebuilt**:
|
||||
|
||||
```diff
|
||||
- const contract = getNFTDrop("0x...")
|
||||
+ const contract = await getNFTDrop("0x...")
|
||||
```
|
||||
|
||||
### New Contract Namespaces
|
||||
|
||||
When working with contracts, we now expose all the convenient high-level APIs for each ERC standard top level.
|
||||
Calling a function that is not supported in your contract will give you an error with instructions on how to unlock that functionality.
|
||||
|
||||
```diff
|
||||
// ERC721 contracts
|
||||
- const contract.nft?.drop?.claim?.to(...)
|
||||
+ const contract.erc721.claimTo(...)
|
||||
- const contract.nft?.drop?.claim?.conditions.set(...)
|
||||
+ const contract.erc721.claimConditions.set(...)
|
||||
|
||||
// ERC1155 contracts
|
||||
- const contract.edition?.mint?.to(...)
|
||||
+ const contract.erc1155.mintTo(...)
|
||||
|
||||
// ERC20 contracts
|
||||
- const contract.token?.burn.tokens(...)
|
||||
+ const contract.erc20.burn(...)
|
||||
```
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@thirdweb-dev/sdk",
|
||||
"version": "3.0.5",
|
||||
"version": "3.0.8",
|
||||
"description": "The main thirdweb SDK.",
|
||||
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/sdk",
|
||||
"license": "Apache-2.0",
|
||||
@@ -20,7 +20,8 @@
|
||||
"build": "tsc && preconstruct build",
|
||||
"test:all": "SWC_NODE_PROJECT=./tsconfig.test.json mocha --timeout 30000 --parallel './test/**/*.test.ts'",
|
||||
"test": "make test",
|
||||
"test:single": "SWC_NODE_PROJECT=./tsconfig.test.json mocha --timeout 30000"
|
||||
"test:single": "SWC_NODE_PROJECT=./tsconfig.test.json mocha --timeout 30000",
|
||||
"push": "yalc push"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@esbuild-plugins/node-modules-polyfill": "^0.1.4",
|
||||
|
||||
@@ -271,7 +271,7 @@ async function extractIPFSHashFromBytecode(
|
||||
const cborLength: number =
|
||||
numericBytecode[numericBytecode.length - 2] * 0x100 +
|
||||
numericBytecode[numericBytecode.length - 1];
|
||||
const bytecodeBuffer = Buffer.from(
|
||||
const bytecodeBuffer = Uint8Array.from(
|
||||
numericBytecode.slice(numericBytecode.length - 2 - cborLength, -2),
|
||||
);
|
||||
|
||||
|
||||
@@ -88,7 +88,7 @@ export const MultiwrapInitializer = {
|
||||
name: "Multiwrap" as const,
|
||||
contractType: "multiwrap" as const,
|
||||
schema: MultiwrapContractSchema,
|
||||
roles: ["transfer", "minter", "unwrap", "asset"] as const,
|
||||
roles: ["admin", "transfer", "minter", "unwrap", "asset"] as const,
|
||||
initialize: async (
|
||||
...[network, address, storage, options]: InitalizeParams
|
||||
) => {
|
||||
@@ -149,7 +149,7 @@ export const PackInitializer = {
|
||||
name: "Pack" as const,
|
||||
contractType: "pack" as const,
|
||||
schema: PackContractSchema,
|
||||
roles: ["admin", "minter", "pauser", "transfer"] as const,
|
||||
roles: ["admin", "minter", "asset", "transfer"] as const,
|
||||
|
||||
initialize: async (
|
||||
...[network, address, storage, options]: InitalizeParams
|
||||
|
||||
@@ -51,7 +51,13 @@ import { BigNumberish, CallOverrides, ethers } from "ethers";
|
||||
* @beta
|
||||
*/
|
||||
export class Multiwrap extends StandardErc721<MultiwrapContract> {
|
||||
static contractRoles = ["transfer", "minter", "unwrap", "asset"] as const;
|
||||
static contractRoles = [
|
||||
"admin",
|
||||
"transfer",
|
||||
"minter",
|
||||
"unwrap",
|
||||
"asset",
|
||||
] as const;
|
||||
|
||||
public abi: typeof ABI;
|
||||
public encoder: ContractEncoder<MultiwrapContract>;
|
||||
|
||||
@@ -57,7 +57,7 @@ import { BigNumber, BigNumberish, CallOverrides, ethers } from "ethers";
|
||||
* @public
|
||||
*/
|
||||
export class Pack extends StandardErc1155<PackContract> {
|
||||
static contractRoles = ["admin", "minter", "pauser", "transfer"] as const;
|
||||
static contractRoles = ["admin", "minter", "asset", "transfer"] as const;
|
||||
|
||||
public abi: typeof ABI;
|
||||
public metadata: ContractMetadata<PackContract, typeof PackContractSchema>;
|
||||
@@ -712,4 +712,4 @@ export class Pack extends StandardErc1155<PackContract> {
|
||||
): Promise<any> {
|
||||
return this.contractWrapper.call(functionName, ...args);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,14 +59,13 @@ export class Erc1155SignatureMintable implements DetectableFeature {
|
||||
* @example
|
||||
* ```javascript
|
||||
* // see how to craft a payload to sign in the `generate()` documentation
|
||||
* const signedPayload = contract.signature.generate(payload);
|
||||
* const signedPayload = contract.erc1155.signature.generate(payload);
|
||||
*
|
||||
* // now anyone can mint the NFT
|
||||
* const tx = contract.signature.mint(signedPayload);
|
||||
* const receipt = tx.receipt; // the mint transaction receipt
|
||||
* const mintedId = tx.id; // the id of the NFT minted
|
||||
* const tx = contract.erc1155.signature.mint(signedPayload);
|
||||
* ```
|
||||
* @param signedPayload - the previously generated payload and signature with {@link Erc1155SignatureMintable.generate}
|
||||
* @twfeature ERC1155SignatureMintable
|
||||
*/
|
||||
public async mint(
|
||||
signedPayload: SignedPayload1155,
|
||||
@@ -103,7 +102,18 @@ export class Erc1155SignatureMintable implements DetectableFeature {
|
||||
/**
|
||||
* Mint any number of dynamically generated NFT at once
|
||||
* @remarks Mint multiple dynamic NFTs in one transaction. Note that this is only possible for free mints (cannot batch mints with a price attached to it for security reasons)
|
||||
*
|
||||
* @example
|
||||
* ```javascript
|
||||
* // see how to craft a batch of payloads to sign in the `generateBatch()` documentation
|
||||
* const signedPayloads = contract.erc1155.signature.generateBatch(payloads);
|
||||
*
|
||||
* // now anyone can mint the NFT
|
||||
* const tx = contract.erc1155.signature.mintBatch(signedPayloads);
|
||||
* ```
|
||||
*
|
||||
* @param signedPayloads - the array of signed payloads to mint
|
||||
* @twfeature ERC1155SignatureMintable
|
||||
*/
|
||||
public async mintBatch(
|
||||
signedPayloads: SignedPayload1155[],
|
||||
@@ -148,6 +158,7 @@ export class Erc1155SignatureMintable implements DetectableFeature {
|
||||
/**
|
||||
* Verify that a payload is correctly signed
|
||||
* @param signedPayload - the payload to verify
|
||||
* @twfeature ERC1155SignatureMintable
|
||||
*/
|
||||
public async verify(signedPayload: SignedPayload1155): Promise<boolean> {
|
||||
const mintRequest = signedPayload.payload;
|
||||
@@ -186,11 +197,12 @@ export class Erc1155SignatureMintable implements DetectableFeature {
|
||||
* primarySaleRecipient: "0x...", // custom sale recipient for this NFT
|
||||
* };
|
||||
*
|
||||
* const signedPayload = contract.signature.generate(payload);
|
||||
* // now anyone can use these to mint the NFT using `contract.signature.mint(signedPayload)`
|
||||
* const signedPayload = contract.erc1155.signature.generate(payload);
|
||||
* // now anyone can use these to mint the NFT using `contract.erc1155.signature.mint(signedPayload)`
|
||||
* ```
|
||||
* @param payloadToSign - the payload to sign
|
||||
* @returns the signed payload and the corresponding signature
|
||||
* @twfeature ERC1155SignatureMintable
|
||||
*/
|
||||
public async generate(
|
||||
payloadToSign: PayloadToSign1155,
|
||||
@@ -230,11 +242,12 @@ export class Erc1155SignatureMintable implements DetectableFeature {
|
||||
* primarySaleRecipient: "0x...", // custom sale recipient for this NFT
|
||||
* };
|
||||
*
|
||||
* const signedPayload = contract.signature.generate(payload);
|
||||
* // now anyone can use these to mint the NFT using `contract.signature.mint(signedPayload)`
|
||||
* const signedPayload = contract.erc1155.signature.generate(payload);
|
||||
* // now anyone can use these to mint the NFT using `contract.erc1155.signature.mint(signedPayload)`
|
||||
* ```
|
||||
* @param payloadToSign - the payload to sign
|
||||
* @returns the signed payload and the corresponding signature
|
||||
* @twfeature ERC1155SignatureMintable
|
||||
*/
|
||||
public async generateFromTokenId(
|
||||
payloadToSign: PayloadToSign1155WithTokenId,
|
||||
@@ -250,6 +263,7 @@ export class Erc1155SignatureMintable implements DetectableFeature {
|
||||
*
|
||||
* @param payloadsToSign - the payloads to sign
|
||||
* @returns an array of payloads and signatures
|
||||
* @twfeature ERC1155SignatureMintable
|
||||
*/
|
||||
public async generateBatch(
|
||||
payloadsToSign: PayloadToSign1155[],
|
||||
@@ -268,6 +282,7 @@ export class Erc1155SignatureMintable implements DetectableFeature {
|
||||
*
|
||||
* @param payloadsToSign - the payloads to sign with tokenIds specified
|
||||
* @returns an array of payloads and signatures
|
||||
* @twfeature ERC1155SignatureMintable
|
||||
*/
|
||||
public async generateBatchFromTokenIds(
|
||||
payloadsToSign: PayloadToSign1155WithTokenId[],
|
||||
|
||||
@@ -919,11 +919,11 @@ export class Erc1155<
|
||||
* @remarks Generate dynamic NFTs with your own signature, and let others mint them using that signature.
|
||||
* @example
|
||||
* ```javascript
|
||||
* // see how to craft a payload to sign in the `contract.signature.generate()` documentation
|
||||
* const signedPayload = contract.signature().generate(payload);
|
||||
* // see how to craft a payload to sign in the `contract.erc1155.signature.generate()` documentation
|
||||
* const signedPayload = contract.erc1155.signature().generate(payload);
|
||||
*
|
||||
* // now anyone can mint the NFT
|
||||
* const tx = contract.signature.mint(signedPayload);
|
||||
* const tx = contract.erc1155.signature.mint(signedPayload);
|
||||
* const receipt = tx.receipt; // the mint transaction receipt
|
||||
* const mintedId = tx.id; // the id of the NFT minted
|
||||
* ```
|
||||
|
||||
@@ -1,15 +1,7 @@
|
||||
import { normalizePriceValue, setErc20Allowance } from "../../common/currency";
|
||||
import { FEATURE_TOKEN_SIGNATURE_MINTABLE } from "../../constants/erc20-features";
|
||||
import type { TokenInitializer } from "../../contracts";
|
||||
import {
|
||||
FilledSignaturePayload20,
|
||||
MintRequest20,
|
||||
PayloadToSign20,
|
||||
PayloadWithUri20,
|
||||
Signature20PayloadInput,
|
||||
Signature20PayloadOutput,
|
||||
SignedPayload20,
|
||||
} from "../../schema/contracts/common/signature";
|
||||
import { FilledSignaturePayload20, MintRequest20, PayloadToSign20, PayloadWithUri20, Signature20PayloadInput, Signature20PayloadOutput, SignedPayload20 } from "../../schema/contracts/common/signature";
|
||||
import { DetectableFeature } from "../interfaces/DetectableFeature";
|
||||
import { TransactionResult } from "../types";
|
||||
import { ContractRoles } from "./contract-roles";
|
||||
@@ -18,6 +10,7 @@ import type { ITokenERC20, TokenERC20 } from "@thirdweb-dev/contracts-js";
|
||||
import { BigNumber, ethers } from "ethers";
|
||||
import invariant from "tiny-invariant";
|
||||
|
||||
|
||||
/**
|
||||
* Enables generating ERC20 Tokens with rules and an associated signature, which can then be minted by anyone securely
|
||||
* @public
|
||||
@@ -47,14 +40,13 @@ export class Erc20SignatureMintable implements DetectableFeature {
|
||||
* @example
|
||||
* ```javascript
|
||||
* // see how to craft a payload to sign in the `generate()` documentation
|
||||
* const signedPayload = contract.signature.generate(payload);
|
||||
* const signedPayload = contract.erc20.signature.generate(payload);
|
||||
*
|
||||
* // now anyone can mint the NFT
|
||||
* const tx = contract.signature.mint(signedPayload);
|
||||
* const receipt = tx.receipt; // the mint transaction receipt
|
||||
* const mintedId = tx.id; // the id of the NFT minted
|
||||
* // Use the signed payload to mint the tokens
|
||||
* const tx = contract.erc20.signature.mint(signedPayload);
|
||||
* ```
|
||||
* @param signedPayload - the previously generated payload and signature with {@link Erc20SignatureMintable.generate}
|
||||
* @twfeature ERC20SignatureMintable
|
||||
*/
|
||||
public async mint(
|
||||
signedPayload: SignedPayload20,
|
||||
@@ -82,6 +74,7 @@ export class Erc20SignatureMintable implements DetectableFeature {
|
||||
* Mint any number of generated tokens signatures at once
|
||||
* @remarks Mint multiple token signatures in one transaction. Note that this is only possible for free mints (cannot batch mints with a price attached to it for security reasons)
|
||||
* @param signedPayloads - the array of signed payloads to mint
|
||||
* @twfeature ERC20SignatureMintable
|
||||
*/
|
||||
public async mintBatch(
|
||||
signedPayloads: SignedPayload20[],
|
||||
@@ -116,6 +109,7 @@ export class Erc20SignatureMintable implements DetectableFeature {
|
||||
/**
|
||||
* Verify that a payload is correctly signed
|
||||
* @param signedPayload - the payload to verify
|
||||
* @twfeature ERC20SignatureMintable
|
||||
*/
|
||||
public async verify(signedPayload: SignedPayload20): Promise<boolean> {
|
||||
const mintRequest = signedPayload.payload;
|
||||
@@ -145,11 +139,12 @@ export class Erc20SignatureMintable implements DetectableFeature {
|
||||
* primarySaleRecipient: "0x...", // custom sale recipient for this token mint
|
||||
* };
|
||||
*
|
||||
* const signedPayload = contract.signature.generate(payload);
|
||||
* // now anyone can use these to mint the NFT using `contract.signature.mint(signedPayload)`
|
||||
* const signedPayload = contract.erc20.signature.generate(payload);
|
||||
* // now anyone can use these to mint the NFT using `contract.erc20.signature.mint(signedPayload)`
|
||||
* ```
|
||||
* @param mintRequest - the payload to sign
|
||||
* @returns the signed payload and the corresponding signature
|
||||
* @twfeature ERC20SignatureMintable
|
||||
*/
|
||||
public async generate(
|
||||
mintRequest: PayloadToSign20,
|
||||
@@ -164,6 +159,7 @@ export class Erc20SignatureMintable implements DetectableFeature {
|
||||
*
|
||||
* @param payloadsToSign - the payloads to sign
|
||||
* @returns an array of payloads and signatures
|
||||
* @twfeature ERC20SignatureMintable
|
||||
*/
|
||||
public async generateBatch(
|
||||
payloadsToSign: PayloadToSign20[],
|
||||
@@ -241,4 +237,4 @@ export class Erc20SignatureMintable implements DetectableFeature {
|
||||
uid: mintRequest.uid,
|
||||
} as ITokenERC20.MintRequestStructOutput;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -551,16 +551,14 @@ export class Erc20<
|
||||
|
||||
/**
|
||||
* Signature Minting
|
||||
* @remarks Generate dynamic NFTs with your own signature, and let others mint them using that signature.
|
||||
* @remarks Generate dynamic tokens with your own signature, and let others mint them using that signature.
|
||||
* @example
|
||||
* ```javascript
|
||||
* // see how to craft a payload to sign in the `contract.signature.generate()` documentation
|
||||
* const signedPayload = contract.signature().generate(payload);
|
||||
* // see how to craft a payload to sign in the `contract.erc20.signature.generate()` documentation
|
||||
* const signedPayload = contract.erc20.signature().generate(payload);
|
||||
*
|
||||
* // now anyone can mint the NFT
|
||||
* // now the payload can be used to mint tokens
|
||||
* const tx = contract.erc20.signature.mint(signedPayload);
|
||||
* const receipt = tx.receipt; // the mint transaction receipt
|
||||
* const mintedId = tx.id; // the id of the NFT minted
|
||||
* ```
|
||||
* @twfeature ERC20SignatureMintable
|
||||
*/
|
||||
|
||||
@@ -11,7 +11,7 @@ import type {
|
||||
IERC721Enumerable,
|
||||
IERC721Supply,
|
||||
} from "@thirdweb-dev/contracts-js";
|
||||
import { BigNumber } from "ethers";
|
||||
import { BigNumber, constants } from "ethers";
|
||||
|
||||
/**
|
||||
* List ERC721 NFTs
|
||||
@@ -68,6 +68,23 @@ export class Erc721Supply implements DetectableFeature {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all the owners of each token id in this contract
|
||||
* @returns
|
||||
*/
|
||||
public async allOwners() {
|
||||
return Promise.all(
|
||||
[...new Array((await this.totalCount()).toNumber()).keys()].map(
|
||||
async (i) => ({
|
||||
tokenId: i,
|
||||
owner: await this.erc721
|
||||
.ownerOf(i)
|
||||
.catch(() => constants.AddressZero),
|
||||
}),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of NFTs minted
|
||||
* @remarks This returns the total number of NFTs minted in this contract, **not** the total supply of a given token.
|
||||
|
||||
@@ -52,14 +52,15 @@ export class Erc721WithQuantitySignatureMintable implements DetectableFeature {
|
||||
* @example
|
||||
* ```javascript
|
||||
* // see how to craft a payload to sign in the `generate()` documentation
|
||||
* const signedPayload = contract.signature.generate(payload);
|
||||
* const signedPayload = contract.erc721.signature.generate(payload);
|
||||
*
|
||||
* // now anyone can mint the NFT
|
||||
* const tx = contract.signature.mint(signedPayload);
|
||||
* const tx = contract.erc721.signature.mint(signedPayload);
|
||||
* const receipt = tx.receipt; // the mint transaction receipt
|
||||
* const mintedId = tx.id; // the id of the NFT minted
|
||||
* ```
|
||||
* @param signedPayload - the previously generated payload and signature with {@link Erc721WithQuantitySignatureMintable.generate}
|
||||
* @twfeature ERC721SignatureMint
|
||||
*/
|
||||
public async mint(
|
||||
signedPayload: SignedPayload721WithQuantitySignature,
|
||||
@@ -111,6 +112,7 @@ export class Erc721WithQuantitySignatureMintable implements DetectableFeature {
|
||||
* Mint any number of dynamically generated NFT at once
|
||||
* @remarks Mint multiple dynamic NFTs in one transaction. Note that this is only possible for free mints (cannot batch mints with a price attached to it for security reasons)
|
||||
* @param signedPayloads - the array of signed payloads to mint
|
||||
* @twfeature ERC721SignatureMint
|
||||
*/
|
||||
public async mintBatch(
|
||||
signedPayloads: SignedPayload721WithQuantitySignature[],
|
||||
@@ -174,6 +176,7 @@ export class Erc721WithQuantitySignatureMintable implements DetectableFeature {
|
||||
/**
|
||||
* Verify that a payload is correctly signed
|
||||
* @param signedPayload - the payload to verify
|
||||
* @twfeature ERC721SignatureMint
|
||||
*/
|
||||
public async verify(
|
||||
signedPayload: SignedPayload721WithQuantitySignature,
|
||||
@@ -227,11 +230,12 @@ export class Erc721WithQuantitySignatureMintable implements DetectableFeature {
|
||||
* primarySaleRecipient: "0x...", // custom sale recipient for this NFT
|
||||
* };
|
||||
*
|
||||
* const signedPayload = contract.signature.generate(payload);
|
||||
* // now anyone can use these to mint the NFT using `contract.signature.mint(signedPayload)`
|
||||
* const signedPayload = contract.erc721.signature.generate(payload);
|
||||
* // now anyone can use these to mint the NFT using `contract.erc721.signature.mint(signedPayload)`
|
||||
* ```
|
||||
* @param mintRequest - the payload to sign
|
||||
* @returns the signed payload and the corresponding signature
|
||||
* @twfeature ERC721SignatureMint
|
||||
*/
|
||||
public async generate(
|
||||
mintRequest: PayloadToSign721withQuantity,
|
||||
@@ -246,6 +250,7 @@ export class Erc721WithQuantitySignatureMintable implements DetectableFeature {
|
||||
*
|
||||
* @param payloadsToSign - the payloads to sign
|
||||
* @returns an array of payloads and signatures
|
||||
* @twfeature ERC721SignatureMint
|
||||
*/
|
||||
public async generateBatch(
|
||||
payloadsToSign: PayloadToSign721withQuantity[],
|
||||
|
||||
@@ -259,6 +259,15 @@ export class Erc721<
|
||||
return assertEnabled(this.query, FEATURE_NFT_SUPPLY).all(queryParams);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get All owners of minted NFTs on this contract
|
||||
* @returns an array of token ids and owners
|
||||
* @twfeature ERC721Supply
|
||||
*/
|
||||
public async getAllOwners() {
|
||||
return assertEnabled(this.query, FEATURE_NFT_SUPPLY).allOwners();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of NFTs minted
|
||||
* @remarks This returns the total number of NFTs minted in this contract, **not** the total supply of a given token.
|
||||
@@ -302,9 +311,13 @@ export class Erc721<
|
||||
if (this.query?.owned) {
|
||||
return this.query.owned.all(walletAddress);
|
||||
} else {
|
||||
const allNFTs = await this.getAll();
|
||||
return (allNFTs || []).filter(
|
||||
({ owner }) => walletAddress?.toLowerCase() === owner?.toLowerCase(),
|
||||
const address =
|
||||
walletAddress || (await this.contractWrapper.getSignerAddress());
|
||||
const allOwners = await this.getAllOwners();
|
||||
return Promise.all(
|
||||
(allOwners || [])
|
||||
.filter((i) => address?.toLowerCase() === i.owner?.toLowerCase())
|
||||
.map(async (i) => await this.get(i.tokenId)),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -317,12 +330,12 @@ export class Erc721<
|
||||
if (this.query?.owned) {
|
||||
return this.query.owned.tokenIds(walletAddress);
|
||||
} else {
|
||||
const allNFTs = await this.getAll();
|
||||
return (allNFTs || [])
|
||||
.filter(
|
||||
({ owner }) => walletAddress?.toLowerCase() === owner?.toLowerCase(),
|
||||
)
|
||||
.map(({ metadata: { id } }) => id);
|
||||
const address =
|
||||
walletAddress || (await this.contractWrapper.getSignerAddress());
|
||||
const allOwners = await this.getAllOwners();
|
||||
return (allOwners || [])
|
||||
.filter((i) => address?.toLowerCase() === i.owner?.toLowerCase())
|
||||
.map((i) => BigNumber.from(i.tokenId));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -640,11 +653,11 @@ export class Erc721<
|
||||
* @remarks Generate dynamic NFTs with your own signature, and let others mint them using that signature.
|
||||
* @example
|
||||
* ```javascript
|
||||
* // see how to craft a payload to sign in the `contract.signature.generate()` documentation
|
||||
* const signedPayload = contract.signature().generate(payload);
|
||||
* // see how to craft a payload to sign in the `contract.erc721.signature.generate()` documentation
|
||||
* const signedPayload = contract.erc721.signature().generate(payload);
|
||||
*
|
||||
* // now anyone can mint the NFT
|
||||
* const tx = contract.signature.mint(signedPayload);
|
||||
* const tx = contract.erc721.signature.mint(signedPayload);
|
||||
* const receipt = tx.receipt; // the mint transaction receipt
|
||||
* const mintedId = tx.id; // the id of the NFT minted
|
||||
* ```
|
||||
|
||||
@@ -452,7 +452,7 @@ export class ThirdwebSDK extends RPCConnectionHandler {
|
||||
* @beta
|
||||
* @example
|
||||
* ```javascript
|
||||
* const contract = sdk.getContract("{{contract_address}}");
|
||||
* const contract = await sdk.getContract("{{contract_address}}");
|
||||
* ```
|
||||
*/
|
||||
public async getContract(address: string) {
|
||||
@@ -473,7 +473,7 @@ export class ThirdwebSDK extends RPCConnectionHandler {
|
||||
);
|
||||
return this.getContractFromAbi(address, metadata.abi);
|
||||
} catch (e) {
|
||||
throw new Error(`Error fetching ABI for this contract\n\n${err}`);
|
||||
throw new Error(`Error fetching ABI for this contract\n\n${e}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -631,9 +631,14 @@ describe("Signature drop tests", async () => {
|
||||
}
|
||||
await signatureDropContract.createBatch(metadatas);
|
||||
const all = await signatureDropContract.getAll();
|
||||
let owned = await signatureDropContract.getOwned();
|
||||
expect(all.length).to.eq(100);
|
||||
expect(owned.length).to.eq(0);
|
||||
await signatureDropContract.claimConditions.set([{}]);
|
||||
await signatureDropContract.claim(1);
|
||||
owned = await signatureDropContract.getOwned();
|
||||
expect(owned.length).to.eq(1);
|
||||
expect(owned[0].owner).to.eq(adminWallet.address);
|
||||
const claimed = await signatureDropContract.totalClaimedSupply();
|
||||
const unclaimed = await signatureDropContract.totalUnclaimedSupply();
|
||||
expect(claimed.toNumber()).to.eq(1);
|
||||
|
||||
@@ -1,5 +1,18 @@
|
||||
# @thirdweb-dev/solana
|
||||
|
||||
## 0.2.15
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#199](https://github.com/thirdweb-dev/js/pull/199) [`5f5ab01`](https://github.com/thirdweb-dev/js/commit/5f5ab015e1dd3c471d6affe995ef36ec88932b3c) Thanks [@joaquim-verges](https://github.com/joaquim-verges)! - Fix getting wallet balance
|
||||
|
||||
## 0.2.14
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`24f66e3`](https://github.com/thirdweb-dev/js/commit/24f66e38c256f7bd69341b92ba30bd35d14b1caa)]:
|
||||
- @thirdweb-dev/storage@1.0.3
|
||||
|
||||
## 0.2.13
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -33,13 +33,10 @@ import { ThirdwebSDK } from "@thirdweb-dev/solana";
|
||||
// First, we instantiate the SDK and connect to Solana devnet
|
||||
const sdk = ThirdwebSDK.fromNetwork("devnet");
|
||||
|
||||
// Next, we pass in a signer to the SDK (you can generate this or use your own)
|
||||
// If you want to generate this, you can use Kepair.generate() from @solana/web3.js
|
||||
const signer = {
|
||||
publicKey: "...",
|
||||
secretKey: "...",
|
||||
};
|
||||
sdk.wallet.connect(signer);
|
||||
// Next, we pass in a keypair to the SDK (you can generate this or use your own)
|
||||
// You can also generate one, using Kepair.generate() from @solana/web3.js
|
||||
const keypair = Keypair.fromSecretKey(...)
|
||||
sdk.wallet.connect(keypair);
|
||||
|
||||
// Finally, we can deploy a new NFT Collection program
|
||||
const address = await sdk.deployer.createNftCollection({
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@thirdweb-dev/solana",
|
||||
"version": "0.2.13",
|
||||
"version": "0.2.15",
|
||||
"description": "thirdweb Solana SDK",
|
||||
"main": "dist/thirdweb-dev-solana.cjs.js",
|
||||
"module": "dist/thirdweb-dev-solana.esm.js",
|
||||
@@ -18,7 +18,8 @@
|
||||
"node:stop": "amman stop",
|
||||
"test:all": "SWC_NODE_PROJECT=./tsconfig.test.json mocha --timeout 30000 --parallel './test/**/*.test.ts'",
|
||||
"test": "make test",
|
||||
"test:single": "SWC_NODE_PROJECT=./tsconfig.test.json mocha --timeout 30000"
|
||||
"test:single": "SWC_NODE_PROJECT=./tsconfig.test.json mocha --timeout 30000",
|
||||
"push": "yalc push"
|
||||
},
|
||||
"files": [
|
||||
"dist/",
|
||||
|
||||
@@ -1,16 +1,17 @@
|
||||
import { CurrencyValue, WalletSigner } from "../types/common";
|
||||
import { toCurrencyValue } from "../utils/token";
|
||||
import {
|
||||
amount,
|
||||
guestIdentity,
|
||||
isIdentitySigner,
|
||||
isKeypairSigner,
|
||||
keypairIdentity,
|
||||
Metaplex,
|
||||
Signer,
|
||||
sol,
|
||||
SOL,
|
||||
walletAdapterIdentity,
|
||||
} from "@metaplex-foundation/js";
|
||||
import { Keypair } from "@solana/web3.js";
|
||||
import { Keypair, PublicKey } from "@solana/web3.js";
|
||||
import EventEmitter from "eventemitter3";
|
||||
import invariant from "tiny-invariant";
|
||||
|
||||
@@ -83,6 +84,13 @@ export class UserWallet {
|
||||
this.events.emit("disconnected");
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether a wallet is connected
|
||||
*/
|
||||
public isConnected() {
|
||||
return this.metaplex.identity().publicKey !== PublicKey.default;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the address of the connected wallet
|
||||
* @returns the address of the connected wallet
|
||||
@@ -123,7 +131,7 @@ export class UserWallet {
|
||||
const value = await this.metaplex.connection.getBalance(
|
||||
this.metaplex.identity().publicKey,
|
||||
);
|
||||
return toCurrencyValue(sol(value));
|
||||
return toCurrencyValue(amount(value, SOL));
|
||||
}
|
||||
|
||||
private connectToMetaplex(signer: WalletSigner) {
|
||||
|
||||
@@ -14,6 +14,8 @@ export * from "./types/index";
|
||||
export * from "./types/common";
|
||||
export * from "./types/contracts";
|
||||
export * from "./types/contracts/nft-drop";
|
||||
// utils
|
||||
export * from "./utils/urls";
|
||||
|
||||
//schema for dashboard use
|
||||
export {
|
||||
|
||||
@@ -22,6 +22,7 @@ describe("Registry", async () => {
|
||||
});
|
||||
nftDrop = await freshSDK.deployer.createNftDrop({
|
||||
name: "Reg Test Drop",
|
||||
itemsAvailable: 10,
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
import { sdk } from "./before-setup";
|
||||
import { expect } from "chai";
|
||||
|
||||
describe("Wallet", async () => {
|
||||
it("balance", async () => {
|
||||
const balance = await sdk.wallet.getBalance();
|
||||
expect(balance.displayValue).to.eq("100.000000000");
|
||||
});
|
||||
});
|
||||
@@ -1,5 +1,11 @@
|
||||
# @thirdweb-dev/storage
|
||||
|
||||
## 1.0.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#192](https://github.com/thirdweb-dev/js/pull/192) [`24f66e3`](https://github.com/thirdweb-dev/js/commit/24f66e38c256f7bd69341b92ba30bd35d14b1caa) Thanks [@adam-maj](https://github.com/adam-maj)! - Use XHR for upload
|
||||
|
||||
## 1.0.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@thirdweb-dev/storage",
|
||||
"version": "1.0.2",
|
||||
"version": "1.0.3",
|
||||
"main": "dist/thirdweb-dev-storage.cjs.js",
|
||||
"module": "dist/thirdweb-dev-storage.esm.js",
|
||||
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/storage",
|
||||
@@ -15,7 +15,8 @@
|
||||
"build": "tsc && preconstruct build",
|
||||
"test:all": "SWC_NODE_PROJECT=./tsconfig.test.json mocha --timeout 30000 --parallel './test/**/*.test.ts'",
|
||||
"test": "yarn test:all",
|
||||
"test:single": "SWC_NODE_PROJECT=./tsconfig.test.json mocha --timeout 30000"
|
||||
"test:single": "SWC_NODE_PROJECT=./tsconfig.test.json mocha --timeout 30000",
|
||||
"push": "yalc push"
|
||||
},
|
||||
"files": [
|
||||
"dist/"
|
||||
|
||||
@@ -183,41 +183,102 @@ export class IpfsUploader implements IStorageUploader<IpfsUploadBatchOptions> {
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
const xhr = new XMLHttpRequest();
|
||||
|
||||
let timer = setTimeout(() => {
|
||||
xhr.abort();
|
||||
reject(
|
||||
new Error(
|
||||
"Request to upload timed out! No upload progress received in 30s",
|
||||
),
|
||||
);
|
||||
}, 30000);
|
||||
|
||||
xhr.upload.addEventListener("loadstart", () => {
|
||||
console.log(`[${Date.now()}] [IPFS] Started`);
|
||||
});
|
||||
|
||||
xhr.upload.addEventListener("progress", (event) => {
|
||||
console.log(`[IPFS] Progress Event ${event.loaded}/${event.total}`);
|
||||
|
||||
clearTimeout(timer);
|
||||
|
||||
if (event.loaded < event.total) {
|
||||
timer = setTimeout(() => {
|
||||
xhr.abort();
|
||||
reject(
|
||||
new Error(
|
||||
"Request to upload timed out! No upload progress received in 30s",
|
||||
),
|
||||
);
|
||||
}, 30000);
|
||||
} else {
|
||||
console.log(
|
||||
`[${Date.now()}] [IPFS] Uploaded files. Waiting for response.`,
|
||||
);
|
||||
}
|
||||
|
||||
if (event.lengthComputable && options?.onProgress) {
|
||||
options?.onProgress({
|
||||
progress: event.loaded,
|
||||
total: event.total,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
xhr.addEventListener("load", () => {
|
||||
console.log(`[${Date.now()}] [IPFS] Load`);
|
||||
clearTimeout(timer);
|
||||
|
||||
if (xhr.status >= 200 && xhr.status < 300) {
|
||||
let body;
|
||||
try {
|
||||
body = JSON.parse(xhr.responseText);
|
||||
} catch (err) {
|
||||
return reject(
|
||||
new Error("Failed to parse JSON from upload response"),
|
||||
);
|
||||
}
|
||||
|
||||
const cid = body.IpfsHash;
|
||||
if (!cid) {
|
||||
throw new Error("Failed to get IPFS hash from upload response");
|
||||
}
|
||||
|
||||
if (options?.uploadWithoutDirectory) {
|
||||
return resolve([`ipfs://${cid}`]);
|
||||
} else {
|
||||
return resolve(fileNames.map((name) => `ipfs://${cid}/${name}`));
|
||||
}
|
||||
}
|
||||
|
||||
return reject(
|
||||
new Error(
|
||||
`Upload failed with status ${xhr.status} - ${xhr.responseText}`,
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
xhr.addEventListener("error", () => {
|
||||
console.log("[IPFS] Load");
|
||||
clearTimeout(timer);
|
||||
|
||||
if (
|
||||
(xhr.readyState !== 0 && xhr.readyState !== 4) ||
|
||||
xhr.status === 0
|
||||
) {
|
||||
return reject(
|
||||
new Error(
|
||||
"This looks like a network error, the endpoint might be blocked by an internet provider or a firewall.",
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
return reject(new Error("Unknown upload error occured"));
|
||||
});
|
||||
|
||||
xhr.open("POST", PINATA_IPFS_URL);
|
||||
xhr.setRequestHeader("Authorization", `Bearer ${token}`);
|
||||
|
||||
xhr.onloadend = () => {
|
||||
if (xhr.status !== 200) {
|
||||
throw new Error("Failed to upload files to IPFS");
|
||||
}
|
||||
|
||||
const cid = JSON.parse(xhr.responseText).IpfsHash;
|
||||
if (!cid) {
|
||||
throw new Error("Failed to upload files to IPFS");
|
||||
}
|
||||
|
||||
if (options?.uploadWithoutDirectory) {
|
||||
resolve([`ipfs://${cid}`]);
|
||||
} else {
|
||||
resolve(fileNames.map((name) => `ipfs://${cid}/${name}`));
|
||||
}
|
||||
};
|
||||
|
||||
xhr.onerror = (err) => {
|
||||
reject(err);
|
||||
};
|
||||
|
||||
if (xhr.upload) {
|
||||
xhr.upload.onprogress = (event) => {
|
||||
if (options?.onProgress) {
|
||||
options?.onProgress({
|
||||
progress: event.loaded,
|
||||
total: event.total,
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
xhr.send(form as any);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -42,6 +42,10 @@
|
||||
},
|
||||
"clean": {
|
||||
"cache": false
|
||||
},
|
||||
"push": {
|
||||
"cache": false,
|
||||
"dependsOn": ["build"]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user