Compare commits

..
Author SHA1 Message Date
github-actions[bot]GitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>
85dd18e8f0 Version Packages (#541)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-02-03 10:53:16 -08:00
Joaquim VergesandGitHub ec1f2324c7 [SDK] Solana - Expose getTransaction pagination options + transactions for given wallet (#542) 2023-02-03 10:39:40 -08:00
b59a31c365 Add support for rendering 3D NFTs (#470)
Co-authored-by: Jonas Daniels <[email protected]>
Co-authored-by: Jarrod Watts <[email protected]>
Co-authored-by: Nacho Iacovino <[email protected]>
Co-authored-by: Nacho Iacovino <[email protected]>
2023-02-03 16:38:59 +01:00
Joaquim VergesandGitHub d29f7e78f0 [SDK] expose getMintTransaction() for fine grain control on mint calls (#540) 2023-02-02 19:32:29 -08:00
github-actions[bot]andGitHub 3e2b392b6b Version Packages (#538) 2023-02-02 09:21:36 -08:00
Adam MajmudarandGitHub cf96333fa2 Fix cache error on mkdir (#537) 2023-02-02 17:12:57 +00:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
4213cfee77 Bump http-cache-semantics from 4.1.0 to 4.1.1 (#536)
Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-02-02 00:26:26 +00:00
github-actions[bot]GitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>
25ef4be50f Version Packages (#534)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-02-01 16:16:07 -08:00
ab1f8bb6f6 [CLI] Modify auto-update process with flag and caching (#528)
Co-authored-by: Jonas Daniels <[email protected]>
2023-02-02 00:04:50 +00:00
Jonas DanielsandGitHub 5f8ec45af7 [SDK] - add burnBatch and getTransactions in solana (#535) 2023-02-01 15:35:22 -08:00
Adam MajmudarandGitHub b45d761f8f [SDK] add creator and royalty settings update for drop (#410) 2023-02-01 15:47:49 -05:00
Adam MajmudarandGitHub 04de5b2783 [SDK] expose getSnapshotEntryForAddress (#471) 2023-02-01 17:34:20 +00:00
Adam MajmudarandGitHub dee4596549 [Auth] Update peerDependencies (#533) 2023-02-01 12:21:16 -05:00
Nacho IacovinoandGitHub 3547901ddd Add all available hooks to React readme (#530) 2023-02-01 02:21:47 +00:00
github-actions[bot]GitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>
fe7ab1c5d3 Version Packages (#526)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-01-31 15:06:05 -08:00
Jonas DanielsandGitHub bdd9ed2298 [react] - fix zag-js/react issues (#527) 2023-01-31 14:57:55 -08:00
ciaranightingaleandGitHub 0977454d45 update readme (#529) 2023-01-31 14:49:24 -08:00
Joaquim VergesandGitHub 19b8e18b6b [SDK] Fix getClaimTransaction().estimateGasCostInEther() for claims costing native currency (#525) 2023-01-31 09:21:00 -08:00
Adam MajmudarandGitHub 7c0060b7fd Fix useMagic and useGnosis documentation (#523) 2023-01-30 22:34:25 +00:00
47 changed files with 4811 additions and 3306 deletions
+1
View File
@@ -38,6 +38,7 @@
"@manypkg/get-packages": "^1.1.3",
"@trivago/prettier-plugin-sort-imports": "^4.0.0",
"eslint": "^8.21.0",
"mocha": "^10.2.0",
"postinstall-postinstall": "^2.1.0",
"prettier": "^2.7.1",
"turbo": "^1.4.6",
+8
View File
@@ -1,5 +1,13 @@
# @thirdweb-dev/auth
## 3.0.3
### Patch Changes
- [#533](https://github.com/thirdweb-dev/js/pull/533) [`dee4596`](https://github.com/thirdweb-dev/js/commit/dee45965496d5d0298944031dd13a4345f9e1683) Thanks [@adam-maj](https://github.com/adam-maj)! - Remove next major version pin on auth
## 3.0.2
## 3.0.1
### Patch Changes
+6 -2
View File
@@ -16,9 +16,13 @@
Install the latest version of the SDK with either `npm` or `yarn`:
```shell
npm install @thirdweb-dev/auth @thirdweb-dev/sdk ethers
npm install @thirdweb-dev/auth
```
```shell
yarn add @thirdweb-dev/auth @thirdweb-dev/sdk ethers
yarn add @thirdweb-dev/auth
```
## Documentation
- [Auth Docs](https://portal.thirdweb.com/auth)
+6 -8
View File
@@ -1,6 +1,6 @@
{
"name": "@thirdweb-dev/auth",
"version": "3.0.1",
"version": "3.0.3",
"main": "dist/thirdweb-dev-auth.cjs.js",
"module": "dist/thirdweb-dev-auth.esm.js",
"exports": {
@@ -66,7 +66,6 @@
"@solana/web3.js": "^1.73.0",
"@swc-node/register": "^1.5.4",
"@swc/core": "^1.3.23",
"@thirdweb-dev/sdk": "*",
"@thirdweb-dev/wallets": "*",
"@types/bs58": "^4.0.1",
"@types/chai": "^4.3.4",
@@ -97,13 +96,12 @@
"peerDependencies": {
"@noble/ed25519": "^1.7.1",
"@solana/web3.js": "^1.73.0",
"@thirdweb-dev/sdk": "*",
"bs58": "^5.0.0",
"cookie-parser": "^1.4.6",
"ethers": ">=5.5.1",
"express": "^4.18.1",
"next": "^12.2.0",
"next-auth": "^4.10.3",
"ethers": "^5",
"express": "^4",
"next": "^12 || ^13",
"next-auth": "^4",
"tweetnacl": "^1.0.3"
},
"peerDependenciesMeta": {
@@ -140,4 +138,4 @@
"uuid": "^9.0.0",
"zod": "^3.20.2"
}
}
}
+29
View File
@@ -1,5 +1,34 @@
# thirdweb
## 0.9.16
### Patch Changes
- Updated dependencies [[`ec1f232`](https://github.com/thirdweb-dev/js/commit/ec1f2324c7a0e58c2d2a209cfe0d194807ba5b70), [`d29f7e7`](https://github.com/thirdweb-dev/js/commit/d29f7e78f09063630e812dd41164d8a41d4f97dd)]:
- @thirdweb-dev/sdk@3.7.4
## 0.9.15
### Patch Changes
- [#537](https://github.com/thirdweb-dev/js/pull/537) [`cf96333`](https://github.com/thirdweb-dev/js/commit/cf96333fa2f46a4a73a822a0b1248891cc890267) Thanks [@adam-maj](https://github.com/adam-maj)! - Fix cache error on windows OS
## 0.9.14
### Patch Changes
- [#528](https://github.com/thirdweb-dev/js/pull/528) [`ab1f8bb`](https://github.com/thirdweb-dev/js/commit/ab1f8bb6f658dadbca2cb53decbc893050217407) Thanks [@adam-maj](https://github.com/adam-maj)! - Added --skip-update-check flag to CLI to prevent checking for new versions and automatically updating before running commands. Also, only check for check for updates every 24 hours.
- Updated dependencies [[`b45d761`](https://github.com/thirdweb-dev/js/commit/b45d761f8f2695b48312ec6eff15e0549e6a8a41), [`5f8ec45`](https://github.com/thirdweb-dev/js/commit/5f8ec45af7c81d075a84846098f38cad90d03fb9), [`04de5b2`](https://github.com/thirdweb-dev/js/commit/04de5b278362573991140c3a496de7451e5c770d)]:
- @thirdweb-dev/sdk@3.7.3
## 0.9.13
### Patch Changes
- Updated dependencies [[`19b8e18`](https://github.com/thirdweb-dev/js/commit/19b8e18b6bf68e374c817fefbf2fd29ac5573052)]:
- @thirdweb-dev/sdk@3.7.2
## 0.9.12
### Patch Changes
+11 -2
View File
@@ -101,8 +101,17 @@ $ npx thirdweb@latest release
The simplest way to work on the CLI locally is to:
1. Install the package locally
2. Run the `build:watch` command to compile any changes in realtime
1. Install the package locally by running
```bash
git clone https://github.com/thirdweb-dev/js.git
```
2. From the project root run
```bash
yarn && yarn build
```
3. From inside `js/packages/cli` Run the `build:watch` command to compile any changes in real time
```bash
$ npm install -g ./
+2 -1
View File
@@ -1,7 +1,7 @@
{
"name": "thirdweb",
"main": "dist/cli/index.js",
"version": "0.9.12",
"version": "0.9.16",
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/cli",
"author": "thirdweb eng <[email protected]>",
"license": "Apache-2.0",
@@ -41,6 +41,7 @@
"prompts": "^2.4.2",
"rimraf": "^3.0.2",
"solc": "0.8.17",
"sync-disk-cache": "^2.1.0",
"tar": "^6.1.11",
"tslog": "^3.3.3",
"update-notifier": "^6.0.2",
+165 -129
View File
@@ -3,6 +3,7 @@ import { detectExtensions } from "../common/feature-detector";
import { processProject } from "../common/processor";
import { cliVersion, pkg } from "../constants/urls";
import { info, logger, spinner } from "../core/helpers/logger";
import { CacheEntry } from "../core/types/cache";
import { twCreate } from "../create/command";
import { deploy } from "../deploy";
import { findPackageInstallation } from "../helpers/detect-local-packages";
@@ -13,12 +14,14 @@ import { exec, spawn } from "child_process";
import { Command } from "commander";
import open from "open";
import prompts from "prompts";
import Cache from "sync-disk-cache";
const main = async () => {
// eslint-disable-next-line turbo/no-undeclared-env-vars
const skipIntro = process.env.THIRDWEB_CLI_SKIP_INTRO === "true";
const program = new Command();
const cache = new Cache("thirdweb:cli");
// yes this has to look like this, eliminates whitespace
if (!skipIntro) {
@@ -37,7 +40,168 @@ const main = async () => {
program
.name("thirdweb-cli")
.description("Official thirdweb command line interface")
.version(cliVersion, "-v, --version");
.version(cliVersion, "-v, --version")
.option("--skip-update-check", "Skip check for auto updates")
.hook("preAction", async () => {
if (skipIntro || program.opts().skipUpdateCheck) {
return;
}
let shouldCheckVersion = true;
try {
const lastCheckCache: CacheEntry = cache.get("last-version-check");
if (lastCheckCache.isCached) {
const lastVersionCheck = new Date(lastCheckCache.value);
// Don't check for updates if already checked within past 24 hours
if (
new Date().getTime() - lastVersionCheck.getTime() <
1000 * 60 * 60 * 24
) {
shouldCheckVersion = false;
}
}
} catch {
// no-op
}
if (!shouldCheckVersion) {
return;
}
const versionSpinner = spinner("Checking for updates...");
await import("update-notifier").then(
async ({ default: updateNotifier }) => {
const notifier = updateNotifier({
pkg,
shouldNotifyInNpmScript: true,
// check every time while we're still building the CLI
updateCheckInterval: 0,
});
const versionInfo = await notifier.fetchInfo();
versionSpinner.stop();
try {
// Set cache to prevent checking for updates again for 24 hours
cache.set("last-version-check", new Date().toISOString());
} catch {
// no-op
}
if (versionInfo.type !== "latest") {
const res = await prompts({
type: "toggle",
name: "upgrade",
message: `A new version of the CLI is available. Would you like to upgrade?`,
initial: true,
active: "yes",
inactive: "no",
});
if (res.upgrade) {
const updateSpinner = spinner(
`Upgrading CLI to version ${versionInfo.latest}...`,
);
const clonedEnvironment = { ...process.env };
clonedEnvironment.THIRDWEB_CLI_SKIP_INTRO = "true";
const installation = await findPackageInstallation();
// If the package isn't installed anywhere, just defer to npx thirdweb@latest
if (!installation) {
updateSpinner.succeed(
`Now using CLI version ${versionInfo.latest}. Continuing execution...`,
);
await new Promise((done, failed) => {
const shell = spawn(
`npx --yes thirdweb@latest ${process.argv
.slice(2)
.join(" ")}`,
[],
{ stdio: "inherit", shell: true, env: clonedEnvironment },
);
shell.on("close", (code) => {
if (code === 0) {
done("");
} else {
failed();
}
});
});
return process.exit(0);
}
// Otherwise, get the correct command based on package manager and local vs. global
let command = "";
switch (installation.packageManager) {
case "npm":
command = installation.isGlobal
? `npm install -g thirdweb`
: `npm install thirdweb`;
break;
case "yarn":
command = installation.isGlobal
? `yarn global add thirdweb`
: `yarn add thirdweb`;
break;
case "pnpm":
command = installation.isGlobal
? `pnpm add -g thirdweb@latest`
: `pnpm add thirdweb@latest`;
break;
default:
console.error(
`Could not detect package manager in use, aborting automatic upgrade.\nIf you want to upgrade the CLI, please do it manually with your package manager.`,
);
process.exit(1);
}
await new Promise((done, failed) => {
exec(command, (err, stdout, stderr) => {
if (err) {
failed(err);
return;
}
done({ stdout, stderr });
});
});
updateSpinner.succeed(
`Successfully upgraded CLI to version ${versionInfo.latest}. Continuing execution...`,
);
// If the package is installed globally with yarn or pnpm, then npx won't recognize it
// So we need to make sure to run the command directly
const executionCommand =
!installation.isGlobal || installation.packageManager === "npm"
? `npx thirdweb`
: `thirdweb`;
await new Promise((done, failed) => {
const shell = spawn(
`${executionCommand} ${process.argv.slice(2).join(" ")}`,
[],
{ stdio: "inherit", shell: true, env: clonedEnvironment },
);
shell.on("close", (code) => {
if (code === 0) {
done("");
} else {
failed();
}
});
});
process.exit(0);
}
}
},
);
});
program
.command("create [projectType] [projectPath]")
@@ -201,134 +365,6 @@ const main = async () => {
await detectExtensions(options);
});
if (!skipIntro) {
const versionSpinner = spinner("Checking for updates...");
await import("update-notifier").then(
async ({ default: updateNotifier }) => {
const notifier = updateNotifier({
pkg,
shouldNotifyInNpmScript: true,
// check every time while we're still building the CLI
updateCheckInterval: 0,
});
const versionInfo = await notifier.fetchInfo();
versionSpinner.stop();
if (versionInfo.type !== "latest") {
const res = await prompts({
type: "toggle",
name: "upgrade",
message: `A new version of the CLI is available. Would you like to upgrade?`,
initial: true,
active: "yes",
inactive: "no",
});
if (res.upgrade) {
const updateSpinner = spinner(
`Upgrading CLI to version ${versionInfo.latest}...`,
);
const clonedEnvironment = { ...process.env };
clonedEnvironment.THIRDWEB_CLI_SKIP_INTRO = "true";
const installation = await findPackageInstallation();
// If the package isn't installed anywhere, just defer to npx thirdweb@latest
if (!installation) {
updateSpinner.succeed(
`Now using CLI version ${versionInfo.latest}. Continuing execution...`,
);
await new Promise((done, failed) => {
const shell = spawn(
`npx --yes thirdweb@latest ${process.argv
.slice(2)
.join(" ")}`,
[],
{ stdio: "inherit", shell: true, env: clonedEnvironment },
);
shell.on("close", (code) => {
if (code === 0) {
done("");
} else {
failed();
}
});
});
return process.exit(0);
}
// Otherwise, get the correct command based on package manager and local vs. global
let command = "";
switch (installation.packageManager) {
case "npm":
command = installation.isGlobal
? `npm install -g thirdweb`
: `npm install thirdweb`;
break;
case "yarn":
command = installation.isGlobal
? `yarn global add thirdweb`
: `yarn add thirdweb`;
break;
case "pnpm":
command = installation.isGlobal
? `pnpm add -g thirdweb@latest`
: `pnpm add thirdweb@latest`;
break;
default:
console.error(
`Could not detect package manager in use, aborting automatic upgrade.\nIf you want to upgrade the CLI, please do it manually with your package manager.`,
);
process.exit(1);
}
await new Promise((done, failed) => {
exec(command, (err, stdout, stderr) => {
if (err) {
failed(err);
return;
}
done({ stdout, stderr });
});
});
updateSpinner.succeed(
`Successfully upgraded CLI to version ${versionInfo.latest}. Continuing execution...`,
);
// If the package is installed globally with yarn or pnpm, then npx won't recognize it
// So we need to make sure to run the command directly
const executionCommand =
!installation.isGlobal || installation.packageManager === "npm"
? `npx thirdweb`
: `thirdweb`;
await new Promise((done, failed) => {
const shell = spawn(
`${executionCommand} ${process.argv.slice(2).join(" ")}`,
[],
{ stdio: "inherit", shell: true, env: clonedEnvironment },
);
shell.on("close", (code) => {
if (code === 0) {
done("");
} else {
failed();
}
});
});
process.exit(0);
}
}
},
);
}
await program.parseAsync();
};
+2 -2
View File
@@ -39,9 +39,9 @@ export async function processProject(
if (projectType === "none") {
if (command === "deploy") {
info(
"No contracts detected in this directory. Redirecting to the thirdweb contract deployment page.",
"No contracts detected in this directory. Redirecting to the thirdweb contract explore page.",
);
return "https://thirdweb.com/contracts";
return "https://thirdweb.com/explore";
}
error("No detected contracts in this directory.");
+5
View File
@@ -0,0 +1,5 @@
export type CacheEntry = {
isCached: boolean;
key: string;
value: string;
};
+2
View File
@@ -0,0 +1,2 @@
declare module 'sync-disk-cache';
declare module "solc";
-1
View File
@@ -1 +0,0 @@
declare module "solc";
+16
View File
@@ -1,5 +1,21 @@
# @thirdweb-dev/react-core
## 3.7.4
## 3.7.3
### Patch Changes
- Updated dependencies [[`dee4596`](https://github.com/thirdweb-dev/js/commit/dee45965496d5d0298944031dd13a4345f9e1683)]:
- @thirdweb-dev/auth@3.0.3
## 3.7.2
### Patch Changes
- Updated dependencies []:
- @thirdweb-dev/auth@3.0.2
## 3.7.1
### Patch Changes
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@thirdweb-dev/react-core",
"version": "3.7.1",
"version": "3.7.4",
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/react-core",
"author": "thirdweb eng <[email protected]>",
"license": "Apache-2.0",
+2
View File
@@ -9,4 +9,6 @@ etc/
temp/
temp-evm/
temp-solana/
temp-evm-gnosis-safe/
temp-evm-magic/
docs/
+25
View File
@@ -1,5 +1,30 @@
# @thirdweb-dev/react
## 3.7.4
### Patch Changes
- [#470](https://github.com/thirdweb-dev/js/pull/470) [`b59a31c`](https://github.com/thirdweb-dev/js/commit/b59a31c365380c4dc9aed8d7678d46b4b21a029d) Thanks [@JustinTime42](https://github.com/JustinTime42)! - Added support for displaying 3d model NFTs
- Updated dependencies []:
- @thirdweb-dev/react-core@3.7.4
## 3.7.3
### Patch Changes
- Updated dependencies []:
- @thirdweb-dev/react-core@3.7.3
## 3.7.2
### Patch Changes
- [#527](https://github.com/thirdweb-dev/js/pull/527) [`bdd9ed2`](https://github.com/thirdweb-dev/js/commit/bdd9ed22989f5baa511bec70ef1ae9d88bfb957e) Thanks [@jnsdls](https://github.com/jnsdls)! - fix dependency issues with @zag-js/react
- Updated dependencies []:
- @thirdweb-dev/react-core@3.7.2
## 3.7.1
### Patch Changes
+108
View File
@@ -305,3 +305,111 @@ const KitchenSinkExample = () => {
);
};
```
## Available hooks
### Main hooks
| Hook | Description |
| --- | --- |
| [`useSDK`](https://portal.thirdweb.com/react/react.usesdk) | Access the instance of the thirdweb SDK created by the ThirdwebProvider. |
| [`useContract`](https://portal.thirdweb.com/react/react.usecontract) | Use this resolve a contract address to a smart contract instance. |
| [`useContractWrite`](https://portal.thirdweb.com/react/react.usecontractwrite) | Use this to get data from a contract read-function call. |
| [`useContractRead`](https://portal.thirdweb.com/react/react.usecontractread) | Use this to get a function to make a write call to your contract. |
| [`useContractEvents`](https://portal.thirdweb.com/react/react.usecontractevents) | Use this to get the contract metadata for a (built-in or custom) contract. |
| [`useContractMetadata`](https://portal.thirdweb.com/react/react.usecontractmetadata) | Use this to get the contract metadata for a (built-in or custom) contract. |
### Wallet connection
| Hook | Description |
| --- | --- |
| [`useAddress`](https://portal.thirdweb.com/react/react.useaddress) | Hook for accessing the address of the connected wallet. |
| [`useMetamask`](https://portal.thirdweb.com/react/react.usemetamask) | Hook for connecting to a Metamask wallet. |
| [`useWalletConnect`](https://portal.thirdweb.com/react/react.usewalletconnect) | Hook for connecting to a mobile wallet with Wallet Connect. |
| [`useCoinbaseWallet`](https://portal.thirdweb.com/react/react.usecoinbasewallet) | Hook for connecting to a Coinbase wallet. |
| [`useMagic`](https://portal.thirdweb.com/react/react.usemagic) | Hook for connecting to an email wallet using magic link. |
| [`useGnosis`](https://portal.thirdweb.com/react/react.usegnosis) | Hook for connecting to a Gnosis Safe. |
| [`useDisconnect`](https://portal.thirdweb.com/react/react.usedisconnect) | Hook for disconnecting the currently connected wallet. |
### Network connection
| Hook | Description |
| --- | --- |
| [`useChainId`](https://portal.thirdweb.com/react/react.usechainid) | Hook for accessing the chain ID of the network the current wallet is connected to |
| [`useNetwork`](https://portal.thirdweb.com/react/react.usenetwork) | Hook for getting metadata about the network the current wallet is connected to and switching networks. |
| [`useNetworkMismatch`](https://portal.thirdweb.com/react/react.usenetworkmismatch) | Hook for checking whether the connected wallet is on the correct network specified by the desiredChainId passed to the <ThirdwebProvider />. |
### NFT
| Hook | Description |
| --- | --- |
| [`useNFT`](https://portal.thirdweb.com/react/react.usenft) | Use this to get an individual NFT token of your NFTContract. |
| [`useNFTs`](https://portal.thirdweb.com/react/react.usenfts) | Use this to get a list of NFT tokens of your NFTContract. |
| [`useTotalCirculatingSupply`](https://portal.thirdweb.com/react/react.usetotalcirculatingsupply) | Use this to get a the total (minted) supply of your NFTContract. |
| [`useOwnedNFTs`](https://portal.thirdweb.com/react/react.useownednfts) | Use this to get a the owned NFTs for a specific Erc721OrErc1155 and wallet address. |
| [`useNFTBalance`](https://portal.thirdweb.com/react/react.usenftbalance) | Use this to get a the total balance of a NFTContract and wallet address. |
| [`useTotalCount`](https://portal.thirdweb.com/react/react.usetotalcount) | Use this to get the total count of NFT tokens of your NFTContract. |
| [`useMintNFT`](https://portal.thirdweb.com/react/react.usemintnft) | Use this to mint a new NFT on your Erc721OrErc1155. |
| [`useMintNFTSupply`](https://portal.thirdweb.com/react/react.usemintnftsupply) | Use this mint extra supply on your Erc1155. |
| [`useTransferNFT`](https://portal.thirdweb.com/react/react.usetransfernft) | Use this to transfer tokens on your NFTContract. |
| [`useAirdropNFT`](https://portal.thirdweb.com/react/react.useairdropnft) | Use this to airdrop tokens on your Erc1155. |
| [`useBurnNFT`](https://portal.thirdweb.com/react/react.useburnnft) | Use this to burn an NFT on your Erc721OrErc1155. |
### Token
| Hook | Description |
| --- | --- |
| [`useTokenSupply`](https://portal.thirdweb.com/react/react.usetokensupply) | Use this to get a the total supply of your contract. |
| [`useTokenBalance`](https://portal.thirdweb.com/react/react.usetokenbalance) | Use this to get the balance of your contract for a given address. |
| [`useTokenDecimals`](https://portal.thirdweb.com/react/react.usetokendecimals) | Use this to get the decimals of your contract for a given address. |
| [`useMintToken`](https://portal.thirdweb.com/react/react.useminttoken) | Use this to mint new tokens on your contract. |
| [`useClaimToken`](https://portal.thirdweb.com/react/react.useclaimtoken) | Use this to claim tokens from your contract. |
| [`useTransferToken`](https://portal.thirdweb.com/react/react.usetransfertoken) | Use this to transfer tokens on your contract. |
| [`useTransferBatchToken`](https://portal.thirdweb.com/react/react.usetransferbatchtoken) | Use this to transfer batch tokens on your contract. |
| [`useBurnToken`](https://portal.thirdweb.com/react/react.useburntoken) | Use this to burn tokens on your contract. |
### Marketplace
| Hook | Description |
| --- | --- |
| [`useListing`](https://portal.thirdweb.com/react/react.uselisting) | Use this to get a specific listing from the marketplace. |
| [`useListings`](https://portal.thirdweb.com/react/react.uselistings) | Use this to get a list all listings from your marketplace contract. |
| [`useListingsCount`](https://portal.thirdweb.com/react/react.uselistingscount) | Use this to get a count of all listings on your marketplace contract. |
| [`useActiveListings`](https://portal.thirdweb.com/react/react.useactivelistings) | Use this to get a list active listings from your marketplace contract. |
| [`useWinningBid`](https://portal.thirdweb.com/react/react.usewinningbid) | Use this to get a the winning bid for an auction listing from your marketplace contract. |
| [`useAuctionWinner`](https://portal.thirdweb.com/react/react.useauctionwinner) | Use this to get the winner of an auction listing from your marketplace contract. |
| [`useBidBuffer`](https://portal.thirdweb.com/react/react.usebidbuffer) | Use this to get the buffer in basis points between offers from your marketplace contract. |
| [`useCreateDirectListing`](https://portal.thirdweb.com/react/react.usecreatedirectlisting) | Use this to create a new Direct Listing on your marketplace contract. |
| [`useCreateAuctionListing`](https://portal.thirdweb.com/react/react.usecreateauctionlisting) | Use this to create a new Auction Listing on your marketplace contract. |
| [`useCancelListing`](https://portal.thirdweb.com/react/react.usecancellisting) | Use this to cancel a listing on your marketplace contract. |
| [`useMakeBid`](https://portal.thirdweb.com/react/react.usemakebid) | Use this to place a bid on an auction listing from your marketplace contract. |
| [`useBuyNow`](https://portal.thirdweb.com/react/react.usebuynow) | Use this to buy out an auction listing from your marketplace contract. |
### Permissions Controls
| Hook | Description |
| --- | --- |
| [`useAllRoleMembers`](https://portal.thirdweb.com/react/react.useallrolemembers) | Use this to get the roles of all members. |
| [`useRoleMembers`](https://portal.thirdweb.com/react/react.userolemembers) | Use this to get the members of a role. |
| [`useIsAddressRole`](https://portal.thirdweb.com/react/react.useisaddressrole) | Use this to check if a WalletAddress is a member of a role. |
| [`useSetAllRoleMembers`](https://portal.thirdweb.com/react/react.usesetallrolemembers) | Use this to OVERWRITE the list of addresses that are members of specific roles. |
| [`useGrantRole`](https://portal.thirdweb.com/react/react.usegrantrole) | Use this to grant a WalletAddress a specific role. |
| [`useRevokeRole`](https://portal.thirdweb.com/react/react.userevokerole) | Use this to revoke a WalletAddress a specific role. |
### Drop
| Hook | Description |
| --- | --- |
| [`useUnclaimedNFTs`](https://portal.thirdweb.com/react/react.useunclaimednfts) | Use this to get a list of unclaimed NFT tokens of your ERC721 Drop contract. |
| [`useClaimedNFTs`](https://portal.thirdweb.com/react/react.useclaimednfts) | Use this to get a list of claimed (minted) NFT tokens of your ERC721 Drop contract.. |
| [`useUnclaimedNFTSupply`](https://portal.thirdweb.com/react/react.useunclaimednftsupply) | Use this to get the total unclaimed NFT supply of your ERC721 Drop contract. |
| [`useClaimedNFTSupply`](https://portal.thirdweb.com/react/react.useclaimednftsupply) | Use this to get the total claimed (minted) NFT supply of your ERC721 Drop contract. |
| [`useBatchesToReveal`](https://portal.thirdweb.com/react/react.usebatchestoreveal) | Use this to get a list of batches that are ready to be revealed. |
| [`useClaimNFT`](https://portal.thirdweb.com/react/react.useclaimnft) | Use this to claim a NFT on your DropContract |
| [`useLazyMint`](https://portal.thirdweb.com/react/react.uselazymint) | Use this to lazy mint a batch of NFTs on your DropContract. |
| [`useDelayedRevealLazyMint`](https://portal.thirdweb.com/react/react.usedelayedreveallazymint) | Use this to lazy mint a batch of delayed reveal NFTs on your DropContract. |
| [`useRevealLazyMint`](https://portal.thirdweb.com/react/react.usereveallazymint) | Use this to reveal a batch of delayed reveal NFTs on your RevealableContract. |
### Claim Conditions
| Hook | Description |
| --- | --- |
| [`useActiveClaimCondition`](https://portal.thirdweb.com/react/react.useactiveclaimcondition) | Use this to get the active claim condition for ERC20, ERC721 or ERC1155 based contracts. |
| [`useClaimConditions`](https://portal.thirdweb.com/react/react.useclaimconditions) | Use this to get all claim conditions for ERC20, ERC721 or ERC1155 based contracts. |
| [`useClaimIneligibilityReasons`](https://portal.thirdweb.com/react/react.useclaimineligibilityreasons) | Use this to check for reasons that prevent claiming for either ERC20, ERC721 or ERC1155 based contracts. |
| [`useSetClaimConditions`](https://portal.thirdweb.com/react/react.usesetclaimconditions) | Use this to set claim conditions on your DropContract. |
| [`useResetClaimConditions`](https://portal.thirdweb.com/react/react.useresetclaimconditions) | Use this to reset claim conditions on your DropContract. |
@@ -0,0 +1,342 @@
/**
* Config file for API Extractor. For more info, please visit: https://api-extractor.com
*/
{
"$schema": "https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json",
/**
* Optionally specifies another JSON config file that this file extends from. This provides a way for
* standard settings to be shared across multiple projects.
*
* If the path starts with "./" or "../", the path is resolved relative to the folder of the file that contains
* the "extends" field. Otherwise, the first path segment is interpreted as an NPM package name, and will be
* resolved using NodeJS require().
*
* SUPPORTED TOKENS: none
* DEFAULT VALUE: ""
*/
// "extends": "./shared/api-extractor-base.json"
// "extends": "my-package/include/api-extractor-base.json"
/**
* Determines the "<projectFolder>" token that can be used with other config file settings. The project folder
* typically contains the tsconfig.json and package.json config files, but the path is user-defined.
*
* The path is resolved relative to the folder of the config file that contains the setting.
*
* The default value for "projectFolder" is the token "<lookup>", which means the folder is determined by traversing
* parent folders, starting from the folder containing api-extractor.json, and stopping at the first folder
* that contains a tsconfig.json file. If a tsconfig.json file cannot be found in this way, then an error
* will be reported.
*
* SUPPORTED TOKENS: <lookup>
* DEFAULT VALUE: "<lookup>"
*/
// "projectFolder": "..",
/**
* (REQUIRED) Specifies the .d.ts file to be used as the starting point for analysis. API Extractor
* analyzes the symbols exported by this module.
*
* The file extension must be ".d.ts" and not ".ts".
*
* The path is resolved relative to the folder of the config file that contains the setting; to change this,
* prepend a folder token such as "<projectFolder>".
*
* SUPPORTED TOKENS: <projectFolder>, <packageName>, <unscopedPackageName>
*/
"mainEntryPointFilePath": "<projectFolder>/evm/connectors/gnosis-safe/dist/thirdweb-dev-react-evm-connectors-gnosis-safe.cjs.d.ts",
/**
* A list of NPM package names whose exports should be treated as part of this package.
*
* For example, suppose that Webpack is used to generate a distributed bundle for the project "library1",
* and another NPM package "library2" is embedded in this bundle. Some types from library2 may become part
* of the exported API for library1, but by default API Extractor would generate a .d.ts rollup that explicitly
* imports library2. To avoid this, we can specify:
*
* "bundledPackages": [ "library2" ],
*
* This would direct API Extractor to embed those types directly in the .d.ts rollup, as if they had been
* local files for library1.
*/
"bundledPackages": [
"wagmi",
"wagmi-core"
],
/**
* Determines how the TypeScript compiler engine will be invoked by API Extractor.
*/
"compiler": {
/**
* Specifies the path to the tsconfig.json file to be used by API Extractor when analyzing the project.
*
* The path is resolved relative to the folder of the config file that contains the setting; to change this,
* prepend a folder token such as "<projectFolder>".
*
* Note: This setting will be ignored if "overrideTsconfig" is used.
*
* SUPPORTED TOKENS: <projectFolder>, <packageName>, <unscopedPackageName>
* DEFAULT VALUE: "<projectFolder>/tsconfig.json"
*/
// "tsconfigFilePath": "<projectFolder>/tsconfig.json",
/**
* Provides a compiler configuration that will be used instead of reading the tsconfig.json file from disk.
* The object must conform to the TypeScript tsconfig schema:
*
* http://json.schemastore.org/tsconfig
*
* If omitted, then the tsconfig.json file will be read from the "projectFolder".
*
* DEFAULT VALUE: no overrideTsconfig section
*/
"overrideTsconfig": {
"skipLibCheck": true
}
/**
* This option causes the compiler to be invoked with the --skipLibCheck option. This option is not recommended
* and may cause API Extractor to produce incomplete or incorrect declarations, but it may be required when
* dependencies contain declarations that are incompatible with the TypeScript engine that API Extractor uses
* for its analysis. Where possible, the underlying issue should be fixed rather than relying on skipLibCheck.
*
* DEFAULT VALUE: false
*/
// "skipLibCheck": true,
},
/**
* Configures how the API report file (*.api.md) will be generated.
*/
"apiReport": {
/**
* (REQUIRED) Whether to generate an API report.
*/
"enabled": true
/**
* The filename for the API report files. It will be combined with "reportFolder" or "reportTempFolder" to produce
* a full file path.
*
* The file extension should be ".api.md", and the string should not contain a path separator such as "\" or "/".
*
* SUPPORTED TOKENS: <packageName>, <unscopedPackageName>
* DEFAULT VALUE: "<unscopedPackageName>.api.md"
*/
// "reportFileName": "<unscopedPackageName>.api.md",
/**
* Specifies the folder where the API report file is written. The file name portion is determined by
* the "reportFileName" setting.
*
* The API report file is normally tracked by Git. Changes to it can be used to trigger a branch policy,
* e.g. for an API review.
*
* The path is resolved relative to the folder of the config file that contains the setting; to change this,
* prepend a folder token such as "<projectFolder>".
*
* SUPPORTED TOKENS: <projectFolder>, <packageName>, <unscopedPackageName>
* DEFAULT VALUE: "<projectFolder>/etc/"
*/
// "reportFolder": "<projectFolder>/etc/",
/**
* Specifies the folder where the temporary report file is written. The file name portion is determined by
* the "reportFileName" setting.
*
* After the temporary file is written to disk, it is compared with the file in the "reportFolder".
* If they are different, a production build will fail.
*
* The path is resolved relative to the folder of the config file that contains the setting; to change this,
* prepend a folder token such as "<projectFolder>".
*
* SUPPORTED TOKENS: <projectFolder>, <packageName>, <unscopedPackageName>
* DEFAULT VALUE: "<projectFolder>/temp/"
*/
// "reportTempFolder": "<projectFolder>/temp/"
},
/**
* Configures how the doc model file (*.api.json) will be generated.
*/
"docModel": {
/**
* (REQUIRED) Whether to generate a doc model file.
*/
"enabled": true
/**
* The output path for the doc model file. The file extension should be ".api.json".
*
* The path is resolved relative to the folder of the config file that contains the setting; to change this,
* prepend a folder token such as "<projectFolder>".
*
* SUPPORTED TOKENS: <projectFolder>, <packageName>, <unscopedPackageName>
* DEFAULT VALUE: "<projectFolder>/temp/<unscopedPackageName>.api.json"
*/
// "apiJsonFilePath": "<projectFolder>/temp/<unscopedPackageName>.api.json"
},
/**
* Configures how the .d.ts rollup file will be generated.
*/
"dtsRollup": {
/**
* (REQUIRED) Whether to generate the .d.ts rollup file.
*/
"enabled": false,
/**
* Specifies the output path for a .d.ts rollup file to be generated without any trimming.
* This file will include all declarations that are exported by the main entry point.
*
* If the path is an empty string, then this file will not be written.
*
* The path is resolved relative to the folder of the config file that contains the setting; to change this,
* prepend a folder token such as "<projectFolder>".
*
* SUPPORTED TOKENS: <projectFolder>, <packageName>, <unscopedPackageName>
* DEFAULT VALUE: "<projectFolder>/dist/<unscopedPackageName>.d.ts"
*/
"untrimmedFilePath": "<projectFolder>/lib/<unscopedPackageName>.d.ts"
/**
* Specifies the output path for a .d.ts rollup file to be generated with trimming for a "beta" release.
* This file will include only declarations that are marked as "@public" or "@beta".
*
* The path is resolved relative to the folder of the config file that contains the setting; to change this,
* prepend a folder token such as "<projectFolder>".
*
* SUPPORTED TOKENS: <projectFolder>, <packageName>, <unscopedPackageName>
* DEFAULT VALUE: ""
*/
// "betaTrimmedFilePath": "<projectFolder>/dist/<unscopedPackageName>-beta.d.ts",
/**
* Specifies the output path for a .d.ts rollup file to be generated with trimming for a "public" release.
* This file will include only declarations that are marked as "@public".
*
* If the path is an empty string, then this file will not be written.
*
* The path is resolved relative to the folder of the config file that contains the setting; to change this,
* prepend a folder token such as "<projectFolder>".
*
* SUPPORTED TOKENS: <projectFolder>, <packageName>, <unscopedPackageName>
* DEFAULT VALUE: ""
*/
// "publicTrimmedFilePath": "<projectFolder>/dist/<unscopedPackageName>-public.d.ts",
/**
* When a declaration is trimmed, by default it will be replaced by a code comment such as
* "Excluded from this release type: exampleMember". Set "omitTrimmingComments" to true to remove the
* declaration completely.
*
* DEFAULT VALUE: false
*/
// "omitTrimmingComments": true
},
/**
* Configures how the tsdoc-metadata.json file will be generated.
*/
"tsdocMetadata": {
/**
* Whether to generate the tsdoc-metadata.json file.
*
* DEFAULT VALUE: true
*/
// "enabled": true,
/**
* Specifies where the TSDoc metadata file should be written.
*
* The path is resolved relative to the folder of the config file that contains the setting; to change this,
* prepend a folder token such as "<projectFolder>".
*
* The default value is "<lookup>", which causes the path to be automatically inferred from the "tsdocMetadata",
* "typings" or "main" fields of the project's package.json. If none of these fields are set, the lookup
* falls back to "tsdoc-metadata.json" in the package folder.
*
* SUPPORTED TOKENS: <projectFolder>, <packageName>, <unscopedPackageName>
* DEFAULT VALUE: "<lookup>"
*/
// "tsdocMetadataFilePath": "<projectFolder>/dist/tsdoc-metadata.json"
},
/**
* Specifies what type of newlines API Extractor should use when writing output files. By default, the output files
* will be written with Windows-style newlines. To use POSIX-style newlines, specify "lf" instead.
* To use the OS's default newline kind, specify "os".
*
* DEFAULT VALUE: "crlf"
*/
// "newlineKind": "crlf",
/**
* Configures how API Extractor reports error and warning messages produced during analysis.
*
* There are three sources of messages: compiler messages, API Extractor messages, and TSDoc messages.
*/
"messages": {
/**
* Configures handling of diagnostic messages reported by the TypeScript compiler engine while analyzing
* the input .d.ts files.
*
* TypeScript message identifiers start with "TS" followed by an integer. For example: "TS2551"
*
* DEFAULT VALUE: A single "default" entry with logLevel=warning.
*/
"compilerMessageReporting": {
/**
* Configures the default routing for messages that don't match an explicit rule in this table.
*/
"default": {
/**
* Specifies whether the message should be written to the the tool's output log. Note that
* the "addToApiReportFile" property may supersede this option.
*
* Possible values: "error", "warning", "none"
*
* Errors cause the build to fail and return a nonzero exit code. Warnings cause a production build fail
* and return a nonzero exit code. For a non-production build (e.g. when "api-extractor run" includes
* the "--local" option), the warning is displayed but the build will not fail.
*
* DEFAULT VALUE: "warning"
*/
"logLevel": "warning"
/**
* When addToApiReportFile is true: If API Extractor is configured to write an API report file (.api.md),
* then the message will be written inside that file; otherwise, the message is instead logged according to
* the "logLevel" option.
*
* DEFAULT VALUE: false
*/
// "addToApiReportFile": false
}
// "TS2551": {
// "logLevel": "warning",
// "addToApiReportFile": true
// },
//
// . . .
},
/**
* Configures handling of messages reported by API Extractor during its analysis.
*
* API Extractor message identifiers start with "ae-". For example: "ae-extra-release-tag"
*
* DEFAULT VALUE: See api-extractor-defaults.json for the complete table of extractorMessageReporting mappings
*/
"extractorMessageReporting": {
"default": {
"logLevel": "warning"
// "addToApiReportFile": false
}
// "ae-extra-release-tag": {
// "logLevel": "warning",
// "addToApiReportFile": true
// },
//
// . . .
},
/**
* Configures handling of messages reported by the TSDoc parser when analyzing code comments.
*
* TSDoc message identifiers start with "tsdoc-". For example: "tsdoc-link-tag-unescaped-text"
*
* DEFAULT VALUE: A single "default" entry with logLevel=warning.
*/
"tsdocMessageReporting": {
"default": {
"logLevel": "warning"
// "addToApiReportFile": false
}
// "tsdoc-link-tag-unescaped-text": {
// "logLevel": "warning",
// "addToApiReportFile": true
// },
//
// . . .
}
}
}
@@ -0,0 +1,342 @@
/**
* Config file for API Extractor. For more info, please visit: https://api-extractor.com
*/
{
"$schema": "https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json",
/**
* Optionally specifies another JSON config file that this file extends from. This provides a way for
* standard settings to be shared across multiple projects.
*
* If the path starts with "./" or "../", the path is resolved relative to the folder of the file that contains
* the "extends" field. Otherwise, the first path segment is interpreted as an NPM package name, and will be
* resolved using NodeJS require().
*
* SUPPORTED TOKENS: none
* DEFAULT VALUE: ""
*/
// "extends": "./shared/api-extractor-base.json"
// "extends": "my-package/include/api-extractor-base.json"
/**
* Determines the "<projectFolder>" token that can be used with other config file settings. The project folder
* typically contains the tsconfig.json and package.json config files, but the path is user-defined.
*
* The path is resolved relative to the folder of the config file that contains the setting.
*
* The default value for "projectFolder" is the token "<lookup>", which means the folder is determined by traversing
* parent folders, starting from the folder containing api-extractor.json, and stopping at the first folder
* that contains a tsconfig.json file. If a tsconfig.json file cannot be found in this way, then an error
* will be reported.
*
* SUPPORTED TOKENS: <lookup>
* DEFAULT VALUE: "<lookup>"
*/
// "projectFolder": "..",
/**
* (REQUIRED) Specifies the .d.ts file to be used as the starting point for analysis. API Extractor
* analyzes the symbols exported by this module.
*
* The file extension must be ".d.ts" and not ".ts".
*
* The path is resolved relative to the folder of the config file that contains the setting; to change this,
* prepend a folder token such as "<projectFolder>".
*
* SUPPORTED TOKENS: <projectFolder>, <packageName>, <unscopedPackageName>
*/
"mainEntryPointFilePath": "<projectFolder>/evm/connectors/magic/dist/thirdweb-dev-react-evm-connectors-magic.cjs.d.ts",
/**
* A list of NPM package names whose exports should be treated as part of this package.
*
* For example, suppose that Webpack is used to generate a distributed bundle for the project "library1",
* and another NPM package "library2" is embedded in this bundle. Some types from library2 may become part
* of the exported API for library1, but by default API Extractor would generate a .d.ts rollup that explicitly
* imports library2. To avoid this, we can specify:
*
* "bundledPackages": [ "library2" ],
*
* This would direct API Extractor to embed those types directly in the .d.ts rollup, as if they had been
* local files for library1.
*/
"bundledPackages": [
"wagmi",
"wagmi-core"
],
/**
* Determines how the TypeScript compiler engine will be invoked by API Extractor.
*/
"compiler": {
/**
* Specifies the path to the tsconfig.json file to be used by API Extractor when analyzing the project.
*
* The path is resolved relative to the folder of the config file that contains the setting; to change this,
* prepend a folder token such as "<projectFolder>".
*
* Note: This setting will be ignored if "overrideTsconfig" is used.
*
* SUPPORTED TOKENS: <projectFolder>, <packageName>, <unscopedPackageName>
* DEFAULT VALUE: "<projectFolder>/tsconfig.json"
*/
// "tsconfigFilePath": "<projectFolder>/tsconfig.json",
/**
* Provides a compiler configuration that will be used instead of reading the tsconfig.json file from disk.
* The object must conform to the TypeScript tsconfig schema:
*
* http://json.schemastore.org/tsconfig
*
* If omitted, then the tsconfig.json file will be read from the "projectFolder".
*
* DEFAULT VALUE: no overrideTsconfig section
*/
"overrideTsconfig": {
"skipLibCheck": true
}
/**
* This option causes the compiler to be invoked with the --skipLibCheck option. This option is not recommended
* and may cause API Extractor to produce incomplete or incorrect declarations, but it may be required when
* dependencies contain declarations that are incompatible with the TypeScript engine that API Extractor uses
* for its analysis. Where possible, the underlying issue should be fixed rather than relying on skipLibCheck.
*
* DEFAULT VALUE: false
*/
// "skipLibCheck": true,
},
/**
* Configures how the API report file (*.api.md) will be generated.
*/
"apiReport": {
/**
* (REQUIRED) Whether to generate an API report.
*/
"enabled": true
/**
* The filename for the API report files. It will be combined with "reportFolder" or "reportTempFolder" to produce
* a full file path.
*
* The file extension should be ".api.md", and the string should not contain a path separator such as "\" or "/".
*
* SUPPORTED TOKENS: <packageName>, <unscopedPackageName>
* DEFAULT VALUE: "<unscopedPackageName>.api.md"
*/
// "reportFileName": "<unscopedPackageName>.api.md",
/**
* Specifies the folder where the API report file is written. The file name portion is determined by
* the "reportFileName" setting.
*
* The API report file is normally tracked by Git. Changes to it can be used to trigger a branch policy,
* e.g. for an API review.
*
* The path is resolved relative to the folder of the config file that contains the setting; to change this,
* prepend a folder token such as "<projectFolder>".
*
* SUPPORTED TOKENS: <projectFolder>, <packageName>, <unscopedPackageName>
* DEFAULT VALUE: "<projectFolder>/etc/"
*/
// "reportFolder": "<projectFolder>/etc/",
/**
* Specifies the folder where the temporary report file is written. The file name portion is determined by
* the "reportFileName" setting.
*
* After the temporary file is written to disk, it is compared with the file in the "reportFolder".
* If they are different, a production build will fail.
*
* The path is resolved relative to the folder of the config file that contains the setting; to change this,
* prepend a folder token such as "<projectFolder>".
*
* SUPPORTED TOKENS: <projectFolder>, <packageName>, <unscopedPackageName>
* DEFAULT VALUE: "<projectFolder>/temp/"
*/
// "reportTempFolder": "<projectFolder>/temp/"
},
/**
* Configures how the doc model file (*.api.json) will be generated.
*/
"docModel": {
/**
* (REQUIRED) Whether to generate a doc model file.
*/
"enabled": true
/**
* The output path for the doc model file. The file extension should be ".api.json".
*
* The path is resolved relative to the folder of the config file that contains the setting; to change this,
* prepend a folder token such as "<projectFolder>".
*
* SUPPORTED TOKENS: <projectFolder>, <packageName>, <unscopedPackageName>
* DEFAULT VALUE: "<projectFolder>/temp/<unscopedPackageName>.api.json"
*/
// "apiJsonFilePath": "<projectFolder>/temp/<unscopedPackageName>.api.json"
},
/**
* Configures how the .d.ts rollup file will be generated.
*/
"dtsRollup": {
/**
* (REQUIRED) Whether to generate the .d.ts rollup file.
*/
"enabled": false,
/**
* Specifies the output path for a .d.ts rollup file to be generated without any trimming.
* This file will include all declarations that are exported by the main entry point.
*
* If the path is an empty string, then this file will not be written.
*
* The path is resolved relative to the folder of the config file that contains the setting; to change this,
* prepend a folder token such as "<projectFolder>".
*
* SUPPORTED TOKENS: <projectFolder>, <packageName>, <unscopedPackageName>
* DEFAULT VALUE: "<projectFolder>/dist/<unscopedPackageName>.d.ts"
*/
"untrimmedFilePath": "<projectFolder>/lib/<unscopedPackageName>.d.ts"
/**
* Specifies the output path for a .d.ts rollup file to be generated with trimming for a "beta" release.
* This file will include only declarations that are marked as "@public" or "@beta".
*
* The path is resolved relative to the folder of the config file that contains the setting; to change this,
* prepend a folder token such as "<projectFolder>".
*
* SUPPORTED TOKENS: <projectFolder>, <packageName>, <unscopedPackageName>
* DEFAULT VALUE: ""
*/
// "betaTrimmedFilePath": "<projectFolder>/dist/<unscopedPackageName>-beta.d.ts",
/**
* Specifies the output path for a .d.ts rollup file to be generated with trimming for a "public" release.
* This file will include only declarations that are marked as "@public".
*
* If the path is an empty string, then this file will not be written.
*
* The path is resolved relative to the folder of the config file that contains the setting; to change this,
* prepend a folder token such as "<projectFolder>".
*
* SUPPORTED TOKENS: <projectFolder>, <packageName>, <unscopedPackageName>
* DEFAULT VALUE: ""
*/
// "publicTrimmedFilePath": "<projectFolder>/dist/<unscopedPackageName>-public.d.ts",
/**
* When a declaration is trimmed, by default it will be replaced by a code comment such as
* "Excluded from this release type: exampleMember". Set "omitTrimmingComments" to true to remove the
* declaration completely.
*
* DEFAULT VALUE: false
*/
// "omitTrimmingComments": true
},
/**
* Configures how the tsdoc-metadata.json file will be generated.
*/
"tsdocMetadata": {
/**
* Whether to generate the tsdoc-metadata.json file.
*
* DEFAULT VALUE: true
*/
// "enabled": true,
/**
* Specifies where the TSDoc metadata file should be written.
*
* The path is resolved relative to the folder of the config file that contains the setting; to change this,
* prepend a folder token such as "<projectFolder>".
*
* The default value is "<lookup>", which causes the path to be automatically inferred from the "tsdocMetadata",
* "typings" or "main" fields of the project's package.json. If none of these fields are set, the lookup
* falls back to "tsdoc-metadata.json" in the package folder.
*
* SUPPORTED TOKENS: <projectFolder>, <packageName>, <unscopedPackageName>
* DEFAULT VALUE: "<lookup>"
*/
// "tsdocMetadataFilePath": "<projectFolder>/dist/tsdoc-metadata.json"
},
/**
* Specifies what type of newlines API Extractor should use when writing output files. By default, the output files
* will be written with Windows-style newlines. To use POSIX-style newlines, specify "lf" instead.
* To use the OS's default newline kind, specify "os".
*
* DEFAULT VALUE: "crlf"
*/
// "newlineKind": "crlf",
/**
* Configures how API Extractor reports error and warning messages produced during analysis.
*
* There are three sources of messages: compiler messages, API Extractor messages, and TSDoc messages.
*/
"messages": {
/**
* Configures handling of diagnostic messages reported by the TypeScript compiler engine while analyzing
* the input .d.ts files.
*
* TypeScript message identifiers start with "TS" followed by an integer. For example: "TS2551"
*
* DEFAULT VALUE: A single "default" entry with logLevel=warning.
*/
"compilerMessageReporting": {
/**
* Configures the default routing for messages that don't match an explicit rule in this table.
*/
"default": {
/**
* Specifies whether the message should be written to the the tool's output log. Note that
* the "addToApiReportFile" property may supersede this option.
*
* Possible values: "error", "warning", "none"
*
* Errors cause the build to fail and return a nonzero exit code. Warnings cause a production build fail
* and return a nonzero exit code. For a non-production build (e.g. when "api-extractor run" includes
* the "--local" option), the warning is displayed but the build will not fail.
*
* DEFAULT VALUE: "warning"
*/
"logLevel": "warning"
/**
* When addToApiReportFile is true: If API Extractor is configured to write an API report file (.api.md),
* then the message will be written inside that file; otherwise, the message is instead logged according to
* the "logLevel" option.
*
* DEFAULT VALUE: false
*/
// "addToApiReportFile": false
}
// "TS2551": {
// "logLevel": "warning",
// "addToApiReportFile": true
// },
//
// . . .
},
/**
* Configures handling of messages reported by API Extractor during its analysis.
*
* API Extractor message identifiers start with "ae-". For example: "ae-extra-release-tag"
*
* DEFAULT VALUE: See api-extractor-defaults.json for the complete table of extractorMessageReporting mappings
*/
"extractorMessageReporting": {
"default": {
"logLevel": "warning"
// "addToApiReportFile": false
}
// "ae-extra-release-tag": {
// "logLevel": "warning",
// "addToApiReportFile": true
// },
//
// . . .
},
/**
* Configures handling of messages reported by the TSDoc parser when analyzing code comments.
*
* TSDoc message identifiers start with "tsdoc-". For example: "tsdoc-link-tag-unescaped-text"
*
* DEFAULT VALUE: A single "default" entry with logLevel=warning.
*/
"tsdocMessageReporting": {
"default": {
"logLevel": "warning"
// "addToApiReportFile": false
}
// "tsdoc-link-tag-unescaped-text": {
// "logLevel": "warning",
// "addToApiReportFile": true
// },
//
// . . .
}
}
}
+12 -8
View File
@@ -1,6 +1,6 @@
{
"name": "@thirdweb-dev/react",
"version": "3.7.1",
"version": "3.7.4",
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/react",
"author": "thirdweb eng <[email protected]>",
"license": "Apache-2.0",
@@ -54,7 +54,10 @@
"fix": "eslint src/ --fix",
"clean": "rm -rf dist/",
"generate-docs": "yarn generate-docs:evm && yarn generate-docs:solana && yarn generate-snippets",
"generate-docs:evm": "api-extractor run --local --config ./config/api-extractor-evm.json && api-documenter markdown -i ./temp -o ./docs/evm && rm -rf ./temp-evm && mv ./temp ./temp-evm",
"generate-docs:evm": "yarn generate-docs:evm:base && yarn generate-docs:evm:magic && yarn generate-docs:evm:gnosis-safe",
"generate-docs:evm:base": "api-extractor run --local --config ./config/api-extractor-evm.json && api-documenter markdown -i ./temp -o ./docs/evm && rm -rf ./temp-evm && mv ./temp ./temp-evm",
"generate-docs:evm:magic": "api-extractor run --local --config ./config/api-extractor-magic.json && api-documenter markdown -i ./temp -o ./docs/evm/magic && rm -rf ./temp-evm-magic && mv ./temp ./temp-evm-magic && mv ./docs/evm/magic/react.usemagic.md ./docs/evm/react.usemagic.md && rm -rf ./docs/evm/magic",
"generate-docs:evm:gnosis-safe": "api-extractor run --local --config ./config/api-extractor-gnosis.json && api-documenter markdown -i ./temp -o ./docs/evm/gnosis-safe && rm -rf ./temp-evm-gnosis-safe && mv ./temp ./temp-evm-gnosis-safe && mv ./docs/evm/gnosis-safe/react.usegnosis.md ./docs/evm/react.usegnosis.md && rm -rf ./docs/evm/gnosis-safe",
"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",
@@ -72,9 +75,9 @@
"@microsoft/tsdoc": "^0.14.1",
"@preconstruct/cli": "^2.2.1",
"@solana/wallet-adapter-base": "^0.9.17",
"@solana/wallet-adapter-phantom": "^0.9.17",
"@solana/wallet-adapter-react": "^0.15.19",
"@solana/wallet-adapter-wallets": "^0.19.0",
"@solana/wallet-adapter-phantom": "^0.9.17",
"@solana/web3.js": "^1.62.0",
"@thirdweb-dev/auth": "*",
"@thirdweb-dev/sdk": "*",
@@ -97,16 +100,17 @@
"typescript": "^4.7.4"
},
"dependencies": {
"@thirdweb-dev/react-core": "*",
"@emotion/react": "^11.10.0",
"@emotion/styled": "^11.10.0",
"@google/model-viewer": "^2.1.1",
"@react-icons/all-files": "^4.1.0",
"@safe-global/safe-core-sdk": "^3.2.0",
"@safe-global/safe-ethers-adapters": "0.1.0-alpha.13",
"@safe-global/safe-ethers-lib": "^1.7.0",
"@tanstack/react-query": "^4.0.10",
"@zag-js/menu": "^0.3.0",
"@zag-js/react": "^0.3.1",
"@thirdweb-dev/react-core": "*",
"@zag-js/menu": "0.3.4",
"@zag-js/react": "0.3.4",
"buffer": "^6.0.3",
"color": "^4.2.3",
"copy-to-clipboard": "^3.3.2",
@@ -119,9 +123,9 @@
},
"peerDependencies": {
"@solana/wallet-adapter-base": "^0.9.17",
"@solana/wallet-adapter-phantom": "^0.9.17",
"@solana/wallet-adapter-react": "^0.15.19",
"@solana/wallet-adapter-wallets": "^0.19.0",
"@solana/wallet-adapter-phantom": "^0.9.17",
"@solana/web3.js": "^1.62.0",
"@thirdweb-dev/sdk": "*",
"ethers": ">=5.5.1",
@@ -149,4 +153,4 @@
"optional": true
}
}
}
}
@@ -9,9 +9,19 @@ import {
CarbonPlayFilledAlt,
} from "./Icons";
import { useQuery } from "@tanstack/react-query";
import React, { useEffect, useMemo, useRef, useState } from "react";
import React, {
ReactNode,
useEffect,
useMemo,
useRef,
useState,
lazy,
Suspense,
} from "react";
import useDimensions from "react-cool-dimensions";
const ModelViewer = lazy(() => import("./ModelViewer"));
export interface SharedMediaProps {
className?: string;
style?: React.CSSProperties;
@@ -25,6 +35,8 @@ export interface SharedMediaProps {
* Show the media controls (where applicable) (default false)
*/
controls?: HTMLVideoElement["controls"];
children?: ReactNode;
}
/**
@@ -45,6 +57,8 @@ export interface MediaRendererProps extends SharedMediaProps {
* The media poster image uri. (if applicable)
*/
poster?: string | null;
width?: string;
height?: string;
}
interface PlayButtonProps {
@@ -399,6 +413,7 @@ LinkPlayer.displayName = "LinkPlayer";
* This component can be used to render any media type, including image, audio, video, and html files.
* Its convenient for rendering NFT media files, as these can be a variety of different types.
* The component falls back to a external link if the media type is not supported.
* The default size is 300px by 300px, but this can be changed using the `width` and `height` props.
*
* Props: {@link MediaRendererProps}
*
@@ -420,10 +435,10 @@ export const MediaRenderer = React.forwardRef<
MediaRendererProps
>(
(
{ src, poster, alt, requireInteraction = false, style, ...restProps },
{ src, poster, alt, requireInteraction = false, width = "300px", height = "300px", style, ...restProps },
ref,
) => {
const mergedStyle: React.CSSProperties = { objectFit: "contain", ...style };
const mergedStyle: React.CSSProperties = { objectFit: "contain", width, height, ...style };
const videoOrImageSrc = useResolvedMediaType(src ?? undefined);
const possiblePosterSrc = useResolvedMediaType(poster ?? undefined);
if (!videoOrImageSrc.mimeType) {
@@ -445,6 +460,30 @@ export const MediaRenderer = React.forwardRef<
{...restProps}
/>
);
} else if (videoOrImageSrc.mimeType.startsWith("model")) {
return (
<Suspense
fallback={
poster ? (
<img
style={mergedStyle}
src={poster}
alt={alt}
ref={ref as unknown as React.LegacyRef<HTMLImageElement>}
{...restProps}
/>
) : null
}
>
<ModelViewer
style={mergedStyle}
src={videoOrImageSrc.url || ""}
poster={poster}
alt={alt}
{...restProps}
/>
</Suspense>
);
} else if (shouldRenderVideoTag(videoOrImageSrc.mimeType)) {
return (
<VideoPlayer
@@ -0,0 +1,34 @@
import type { MediaRendererProps } from "./MediaRenderer";
import "@google/model-viewer";
import type { ModelViewerElement } from "@google/model-viewer";
import React from "react";
declare global {
namespace JSX {
interface IntrinsicElements {
"model-viewer": Partial<ModelViewerElement>;
}
}
}
export const ModelViewer = React.forwardRef<HTMLDivElement, MediaRendererProps>(
({ src, alt, poster, style }, ref) => {
return (
<div style={{ ...style }} ref={ref}>
{src ? (
<model-viewer
src={src}
alt={alt || "3D Model"}
camera-controls
poster={poster ? poster : null}
style={{ width: '100%', height: '100%'} as CSSStyleDeclaration}
/>
) : null}
</div>
);
},
);
ModelViewer.displayName = "ModelViewer";
export default ModelViewer;
@@ -10,10 +10,15 @@ export interface ThirdwebNftMediaProps extends SharedMediaProps {
* The NFT metadata of the NFT returned by the thirdweb sdk.
*/
metadata: NFTMetadata;
width?: string;
height?: string;
}
/**
* This component can be used to render NFTs from the thirdweb SDK.
* It will render the animation_url if it exists, otherwise it will render the image.
* The default size is 300px by 300px, but this can be changed using the `width` and `height` props.
*
* Props: {@link ThirdwebNftMediaProps}
*
* @example
@@ -38,13 +43,16 @@ export interface ThirdwebNftMediaProps extends SharedMediaProps {
export const ThirdwebNftMedia = React.forwardRef<
HTMLMediaElement,
ThirdwebNftMediaProps
>(({ metadata, ...props }, ref) => {
>(({ metadata, width = "300px", height = "300px", style, ...props }, ref) => {
return (
<MediaRenderer
src={metadata.animation_url || metadata.image}
poster={metadata.image}
alt={metadata.name?.toString() || ""}
ref={ref}
width={width}
height={height}
style={{ ...style }}
{...props}
/>
);
File diff suppressed because one or more lines are too long
+24
View File
@@ -1,5 +1,29 @@
# @thirdweb-dev/sdk
## 3.7.4
### Patch Changes
- [#542](https://github.com/thirdweb-dev/js/pull/542) [`ec1f232`](https://github.com/thirdweb-dev/js/commit/ec1f2324c7a0e58c2d2a209cfe0d194807ba5b70) Thanks [@joaquim-verges](https://github.com/joaquim-verges)! - Solana - Expose getTransaction pagination options + transactions for given wallet
- [#540](https://github.com/thirdweb-dev/js/pull/540) [`d29f7e7`](https://github.com/thirdweb-dev/js/commit/d29f7e78f09063630e812dd41164d8a41d4f97dd) Thanks [@joaquim-verges](https://github.com/joaquim-verges)! - expose `getMintTransaction()` for fine grain control on mint calls
## 3.7.3
### Patch Changes
- [#410](https://github.com/thirdweb-dev/js/pull/410) [`b45d761`](https://github.com/thirdweb-dev/js/commit/b45d761f8f2695b48312ec6eff15e0549e6a8a41) Thanks [@adam-maj](https://github.com/adam-maj)! - Add creator and royalty settings to drop
- [#535](https://github.com/thirdweb-dev/js/pull/535) [`5f8ec45`](https://github.com/thirdweb-dev/js/commit/5f8ec45af7c81d075a84846098f38cad90d03fb9) Thanks [@jnsdls](https://github.com/jnsdls)! - [Solana] - add `burnBatch()` and `getTransactions()` for NFTCollection and NFTDrop
- [#471](https://github.com/thirdweb-dev/js/pull/471) [`04de5b2`](https://github.com/thirdweb-dev/js/commit/04de5b278362573991140c3a496de7451e5c770d) Thanks [@adam-maj](https://github.com/adam-maj)! - Expose getSnapshotEntryForAddress
## 3.7.2
### Patch Changes
- [#525](https://github.com/thirdweb-dev/js/pull/525) [`19b8e18`](https://github.com/thirdweb-dev/js/commit/19b8e18b6bf68e374c817fefbf2fd29ac5573052) Thanks [@joaquim-verges](https://github.com/joaquim-verges)! - Fix `getClaimTransaction().estimateGasCostInEther()` for claims costing native currency
## 3.7.1
## 3.7.0
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@thirdweb-dev/sdk",
"version": "3.7.1",
"version": "3.7.4",
"description": "The main thirdweb SDK.",
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/sdk",
"license": "Apache-2.0",
+4 -1
View File
@@ -10,4 +10,7 @@ export {
fetchCurrencyMetadata,
normalizePriceValue,
} from "./currency";
export { convertToReadableQuantity } from "./claim-conditions";
export {
convertToReadableQuantity,
fetchSnapshotEntryForAddress,
} from "./claim-conditions";
@@ -258,6 +258,19 @@ export class Edition extends StandardErc1155<TokenERC1155> {
return this.erc1155.mintTo(to, metadataWithSupply);
}
/**
* Construct a mint transaction without executing it.
* This is useful for estimating the gas cost of a mint transaction, overriding transaction options and having fine grained control over the transaction execution.
* @param receiver - Address you want to send the token to
* @param metadataWithSupply - The metadata of the NFT you want to mint
*/
public async getMintTransaction(
receiver: string,
metadataWithSupply: EditionMetadataOrUri,
) {
return this.erc1155.getMintTransaction(receiver, metadataWithSupply);
}
/**
* Increase the supply of an existing NFT and mint it to the connected wallet
*
@@ -229,6 +229,19 @@ export class NFTCollection extends StandardErc721<TokenERC721> {
return this.erc721.mintTo(walletAddress, metadata);
}
/**
* Construct a mint transaction without executing it.
* This is useful for estimating the gas cost of a mint transaction, overriding transaction options and having fine grained control over the transaction execution.
* @param receiver - Address you want to send the token to
* @param metadata - The metadata of the NFT you want to mint
*/
public async getMintTransaction(
receiver: string,
metadata: NFTMetadataOrUri,
) {
return this.erc721.getMintTransaction(receiver, metadata);
}
/**
* Mint Many unique NFTs
*
@@ -186,6 +186,16 @@ export class Token extends StandardErc20<TokenERC20> {
return this.erc20.mintTo(to, amount);
}
/**
* Construct a mint transaction without executing it.
* This is useful for estimating the gas cost of a mint transaction, overriding transaction options and having fine grained control over the transaction execution.
* @param receiver - Address you want to send the token to
* @param amount - The amount of tokens you want to mint
*/
public async getMintTransaction(to: string, amount: Amount) {
return this.erc20.getMintTransaction(to, amount);
}
/**
* Mint Tokens To Many Wallets
*
@@ -104,7 +104,10 @@ export class TransactionTask {
* @returns the gas limit in gas units
*/
public async estimateGasLimit(): Promise<BigNumber> {
return await this.estimator.gasLimitOf(this.functionName, this.args);
return await this.estimator.gasLimitOf(this.functionName, [
...this.args,
this.overrides || {},
]);
}
/**
@@ -112,7 +115,10 @@ export class TransactionTask {
* @returns the gas cost in ether
*/
public async estimateGasCostInEther(): Promise<string> {
return await this.estimator.gasCostOf(this.functionName, this.args);
return await this.estimator.gasCostOf(this.functionName, [
...this.args,
this.overrides || {},
]);
}
// ////////////// Actions ////////////////
@@ -5,6 +5,7 @@ import { FEATURE_EDITION_MINTABLE } from "../../constants/erc1155-features";
import { EditionMetadataOrUri } from "../../schema";
import { DetectableFeature } from "../interfaces/DetectableFeature";
import { TransactionResultWithId } from "../types";
import { TransactionTask } from "./TransactionTask";
import { ContractWrapper } from "./contract-wrapper";
import { Erc1155 } from "./erc-1155";
import { Erc1155BatchMintable } from "./erc-1155-batch-mintable";
@@ -77,16 +78,8 @@ export class Erc1155Mintable implements DetectableFeature {
to: string,
metadataWithSupply: EditionMetadataOrUri,
): Promise<TransactionResultWithId<NFT>> {
const uri = await uploadOrExtractURI(
metadataWithSupply.metadata,
this.storage,
);
const receipt = await this.contractWrapper.sendTransaction("mintTo", [
to,
ethers.constants.MaxUint256,
uri,
metadataWithSupply.supply,
]);
const tx = await this.getMintTransaction(to, metadataWithSupply);
const { receipt } = await tx.execute();
const event = this.contractWrapper.parseLogs<TransferSingleEvent>(
"TransferSingle",
receipt?.logs,
@@ -102,6 +95,21 @@ export class Erc1155Mintable implements DetectableFeature {
};
}
public async getMintTransaction(
to: string,
metadataWithSupply: EditionMetadataOrUri,
): Promise<TransactionTask> {
const uri = await uploadOrExtractURI(
metadataWithSupply.metadata,
this.storage,
);
return TransactionTask.make({
contractWrapper: this.contractWrapper,
functionName: "mintTo",
args: [to, ethers.constants.MaxUint256, uri, metadataWithSupply.supply],
});
}
/**
* Increase the supply of an existing NFT and mint it to a given wallet address
*
@@ -473,6 +473,22 @@ export class Erc1155<
);
}
/**
* Construct a mint transaction without executing it.
* This is useful for estimating the gas cost of a mint transaction, overriding transaction options and having fine grained control over the transaction execution.
* @param receiver - Address you want to send the token to
* @param metadataWithSupply - The metadata of the NFT you want to mint
*/
public async getMintTransaction(
receiver: string,
metadataWithSupply: EditionMetadataOrUri,
) {
return assertEnabled(
this.mintable,
FEATURE_EDITION_MINTABLE,
).getMintTransaction(receiver, metadataWithSupply);
}
/**
* Increase the supply of an existing NFT
* @remarks Increase the supply of an existing NFT and mint it to the connected wallet address
@@ -3,6 +3,7 @@ import { FEATURE_TOKEN_MINTABLE } from "../../constants/erc20-features";
import { Amount } from "../../types";
import { DetectableFeature } from "../interfaces/DetectableFeature";
import { TransactionResult } from "../types";
import { TransactionTask } from "./TransactionTask";
import { ContractWrapper } from "./contract-wrapper";
import { Erc20 } from "./erc-20";
import { Erc20BatchMintable } from "./erc-20-batch-mintable";
@@ -47,12 +48,19 @@ export class Erc20Mintable implements DetectableFeature {
* ```
*/
public async to(to: string, amount: Amount): Promise<TransactionResult> {
return {
receipt: await this.contractWrapper.sendTransaction("mintTo", [
to,
await this.erc20.normalizeAmount(amount),
]),
};
const tx = await this.getMintTransaction(to, amount);
return tx.execute();
}
public async getMintTransaction(
to: string,
amount: Amount,
): Promise<TransactionTask> {
return TransactionTask.make({
contractWrapper: this.contractWrapper,
functionName: "mintTo",
args: [to, await this.erc20.normalizeAmount(amount)],
});
}
private detectErc20BatchMintable() {
@@ -376,6 +376,19 @@ export class Erc20<
);
}
/**
* Construct a mint transaction without executing it.
* This is useful for estimating the gas cost of a mint transaction, overriding transaction options and having fine grained control over the transaction execution.
* @param receiver - Address you want to send the token to
* @param amount - The amount of tokens you want to mint
*/
public async getMintTransaction(receiver: string, amount: Amount) {
return assertEnabled(
this.mintable,
FEATURE_TOKEN_MINTABLE,
).getMintTransaction(receiver, amount);
}
////// ERC20 BatchMintable Extension //////
/**
@@ -4,6 +4,7 @@ import { uploadOrExtractURI } from "../../common/nft";
import { FEATURE_NFT_MINTABLE } from "../../constants/erc721-features";
import { DetectableFeature } from "../interfaces/DetectableFeature";
import { TransactionResultWithId } from "../types";
import { TransactionTask } from "./TransactionTask";
import { ContractWrapper } from "./contract-wrapper";
import { Erc721 } from "./erc-721";
import { Erc721BatchMintable } from "./erc-721-batch-mintable";
@@ -67,11 +68,8 @@ export class Erc721Mintable implements DetectableFeature {
to: string,
metadata: NFTMetadataOrUri,
): Promise<TransactionResultWithId<NFT>> {
const uri = await uploadOrExtractURI(metadata, this.storage);
const receipt = await this.contractWrapper.sendTransaction("mintTo", [
to,
uri,
]);
const tx = await this.getMintTransaction(to, metadata);
const { receipt } = await tx.execute();
const event = this.contractWrapper.parseLogs<TransferEvent>(
"Transfer",
receipt?.logs,
@@ -87,6 +85,18 @@ export class Erc721Mintable implements DetectableFeature {
};
}
public async getMintTransaction(
to: string,
metadata: NFTMetadataOrUri,
): Promise<TransactionTask> {
const uri = await uploadOrExtractURI(metadata, this.storage);
return TransactionTask.make({
contractWrapper: this.contractWrapper,
functionName: "mintTo",
args: [to, uri],
});
}
private detectErc721BatchMintable(): Erc721BatchMintable | undefined {
if (
detectContractFeature<IMintableERC721 & IMulticall>(
@@ -409,6 +409,22 @@ export class Erc721<
);
}
/**
* Construct a mint transaction without executing it.
* This is useful for estimating the gas cost of a mint transaction, overriding transaction options and having fine grained control over the transaction execution.
* @param receiver - Address you want to send the token to
* @param metadata - The metadata of the NFT you want to mint
*/
public async getMintTransaction(
receiver: string,
metadata: NFTMetadataOrUri,
) {
return assertEnabled(
this.mintable,
FEATURE_NFT_MINTABLE,
).getMintTransaction(receiver, metadata);
}
////// ERC721 Batch Mintable Extension //////
/**
@@ -33,6 +33,8 @@ import {
Connection,
ParsedAccountData,
PublicKey,
SignaturesForAddressOptions,
TransactionResponse,
} from "@solana/web3.js";
/**
@@ -174,30 +176,42 @@ export class NFTHelper {
return nfts;
}
private async getAllMetadataAddresses(collectionAddress: string) {
async getTransactions(
collectionAddress: string,
options?: SignaturesForAddressOptions,
): Promise<TransactionResponse[]> {
const collectionKey = new PublicKey(collectionAddress);
// TODO cache signatures <> transactions mapping in memory so pagination doesn't re-request this everytime
const allSignatures: ConfirmedSignatureInfo[] = [];
// This returns the first 1000, so we need to loop through until we run out of signatures to get.
let signatures = await this.metaplex.connection.getSignaturesForAddress(
collectionKey,
);
allSignatures.push(...signatures);
do {
const options = {
before: signatures[signatures.length - 1]?.signature,
};
signatures = await this.metaplex.connection.getSignaturesForAddress(
collectionKey,
options,
if (options) {
// only fetch the specified options
allSignatures.push(
...(await this.metaplex.connection.getSignaturesForAddress(
collectionKey,
options,
)),
);
} else {
// fetch everything
// This returns the first 1000, so we need to loop through until we run out of signatures to get.
let signatures = await this.metaplex.connection.getSignaturesForAddress(
collectionKey,
);
allSignatures.push(...signatures);
} while (signatures.length > 0);
const metadataAddresses: PublicKey[] = [];
do {
signatures = await this.metaplex.connection.getSignaturesForAddress(
collectionKey,
{
before: signatures[signatures.length - 1]?.signature,
},
);
allSignatures.push(...signatures);
} while (signatures.length > 0);
}
let txns: TransactionResponse[] = [];
// TODO RPC's will throttle this, need to do some optimizations here
const batchSize = 1000; // alchemy RPC batch limit
for (let i = 0; i < allSignatures.length; i += batchSize) {
@@ -206,13 +220,25 @@ export class NFTHelper {
Math.min(allSignatures.length, i + batchSize),
);
const transactions = (
await this.metaplex.connection.getTransactions(
batch.map((s) => s.signature),
)
).reverse();
txns = [
...txns,
...((
await this.metaplex.connection.getTransactions(
batch.map((s) => s.signature),
)
).filter((tx) => !!tx) as TransactionResponse[]),
];
}
return txns;
}
for (const tx of transactions) {
async getAllMetadataAddresses(
collectionAddress: string,
): Promise<PublicKey[]> {
const txns = (await this.getTransactions(collectionAddress)).reverse();
return txns
.map((tx) => {
if (tx) {
const programIds = tx.transaction.message
.programIds()
@@ -230,9 +256,8 @@ export class NFTHelper {
accountKeys[ix.programIdIndex] === METAPLEX_PROGRAM_ID
) {
const metadataAddressIndex = ix.accounts[0];
const metadata_address =
tx.transaction.message.accountKeys[metadataAddressIndex];
metadataAddresses.push(metadata_address);
return tx.transaction.message.accountKeys[metadataAddressIndex];
}
}
} else if (programIds.includes(CANDYMACHINE_PROGRAM_ID)) {
@@ -243,17 +268,14 @@ export class NFTHelper {
ix.data === "JEuNFGs7wrU"
) {
const metadataAddressIndex = ix.accounts[1];
const metadata_address =
tx.transaction.message.accountKeys[metadataAddressIndex];
metadataAddresses.push(metadata_address);
return tx.transaction.message.accountKeys[metadataAddressIndex];
}
}
}
}
}
}
return metadataAddresses;
})
.filter((a) => !!a) as PublicKey[];
}
async toNFTMetadata(
+21 -1
View File
@@ -1,6 +1,7 @@
import { CurrencyValue } from "../../core/schema/token";
import { WalletSigner } from "../types/common";
import { toCurrencyValue } from "../utils/token";
import { NFTHelper } from "./helpers/nft-helper";
import {
amount,
guestIdentity,
@@ -12,7 +13,12 @@ import {
SOL,
walletAdapterIdentity,
} from "@metaplex-foundation/js";
import { Keypair, PublicKey } from "@solana/web3.js";
import {
Keypair,
PublicKey,
SignaturesForAddressOptions,
TransactionResponse,
} from "@solana/web3.js";
import bs58 from "bs58";
import EventEmitter from "eventemitter3";
import invariant from "tiny-invariant";
@@ -172,6 +178,20 @@ export class UserWallet {
return toCurrencyValue(amount(value, SOL));
}
/**
* Get the all transactions for this program
* @beta
*/
async getTransactions(
options?: SignaturesForAddressOptions,
): Promise<TransactionResponse[]> {
const helper = new NFTHelper(this.metaplex);
return helper.getTransactions(
this.metaplex.identity().publicKey.toBase58(),
options,
);
}
private connectToMetaplex(signer: WalletSigner) {
invariant(signer, "Wallet is not connected");
const plugin = isKeypairSigner(signer)
@@ -18,7 +18,11 @@ import {
toOriginalEditionAccount,
TransactionBuilder,
} from "@metaplex-foundation/js";
import { PublicKey } from "@solana/web3.js";
import {
PublicKey,
SignaturesForAddressOptions,
TransactionResponse,
} from "@solana/web3.js";
import { ThirdwebStorage } from "@thirdweb-dev/storage";
import invariant from "tiny-invariant";
@@ -140,6 +144,16 @@ export class NFTCollection {
return this.nft.getAll(this.publicKey.toBase58(), queryParams);
}
/**
* Get the all transactions for this program
* @beta
*/
async getTransactions(
options?: SignaturesForAddressOptions,
): Promise<TransactionResponse[]> {
return this.nft.getTransactions(this.publicKey.toBase58(), options);
}
/**
* Get the total number of nfts minted on this program
* @returns the total number of NFTs minted on this program
@@ -420,14 +434,39 @@ export class NFTCollection {
* ```
*/
async burn(nftAddress: string): Promise<TransactionResult> {
const tx = await this.metaplex.nfts().delete({
mintAddress: new PublicKey(nftAddress),
collection: this.publicKey,
});
return this.burnBatch([nftAddress]).then((txs) => txs[0]);
}
return {
signature: tx.response.signature,
};
/**
* Burn multiple NFTs
* @param nftAddresses - the mint addresses of the NFT to burn
* @returns the transaction signature
*
* @example
* ```jsx
* // Specify the address of the NFT to burn
* const nftAddress1 = "..."
* const nftAddress2 = "..."
* // And send the actual burn transaction
* const tx = await program.burnBatch([nftAddress1, nftAddress2]);
* ```
*/
async burnBatch(nftAddresses: string[]): Promise<TransactionResult[]> {
const txs: TransactionBuilder[] = [];
for (let nftAddress of nftAddresses) {
txs.push(
this.metaplex
.nfts()
.builders()
.delete({
mintAddress: new PublicKey(nftAddress),
collection: this.publicKey,
}),
);
}
return await sendMultipartTransaction(txs, this.metaplex);
}
/**
@@ -472,7 +511,6 @@ export class NFTCollection {
.nfts()
.builders()
.update({
collection: this.publicKey,
nftOrSft: metaplexNft,
creators: enforceCreator(
creators,
@@ -530,7 +568,6 @@ export class NFTCollection {
txs.push(
this.metaplex.nfts().builders().update({
collection: this.publicKey,
nftOrSft: metaplexNft,
sellerFeeBasisPoints,
}),
+169 -24
View File
@@ -21,10 +21,16 @@ import { sendMultipartTransaction } from "../utils/transactions";
import { getNework } from "../utils/urls";
import {
CandyMachineV2Item,
findCandyMachineV2CreatorPda,
Metaplex,
toBigNumber,
TransactionBuilder,
} from "@metaplex-foundation/js";
import { PublicKey } from "@solana/web3.js";
import {
PublicKey,
SignaturesForAddressOptions,
TransactionResponse,
} from "@solana/web3.js";
import { ThirdwebStorage, UploadProgressEvent } from "@thirdweb-dev/storage";
import invariant from "tiny-invariant";
@@ -218,6 +224,16 @@ export class NFTDrop {
return [...claimedNfts, ...unclaimedNfts];
}
/**
* Get the all transactions for this program
* @beta
*/
async getTransactions(
options?: SignaturesForAddressOptions,
): Promise<TransactionResponse[]> {
return this.nft.getTransactions(this.publicKey.toBase58(), options);
}
/**
* Get the metadata for all the claimed NFTs on this drop
* @returns metadata for all claimed NFTs
@@ -493,47 +509,176 @@ export class NFTDrop {
* ```
*/
async burn(nftAddress: string): Promise<TransactionResult> {
return this.burnBatch([nftAddress]).then((txs) => txs[0]);
}
/**
* Burn multiple NFTs
* @param nftAddresses - the mint addresses of the NFT to burn
* @returns the transaction signature
*
* @example
* ```jsx
* // Specify the address of the NFT to burn
* const nftAddress1 = "..."
* const nftAddress2 = "..."
* // And send the actual burn transaction
* const tx = await program.burnBatch([nftAddress1, nftAddress2]);
* ```
*/
async burnBatch(nftAddresses: string[]): Promise<TransactionResult[]> {
const candyMachine = await this.getCandyMachine();
const collection = candyMachine.collectionMintAddress
? candyMachine.collectionMintAddress
: undefined;
const tx = await this.metaplex.nfts().delete({
mintAddress: new PublicKey(nftAddress),
collection,
});
return {
signature: tx.response.signature,
};
const txs: TransactionBuilder[] = [];
for (let nftAddress of nftAddresses) {
txs.push(
this.metaplex
.nfts()
.builders()
.delete({
mintAddress: new PublicKey(nftAddress),
collection,
}),
);
}
return await sendMultipartTransaction(txs, this.metaplex);
}
/**
* Update the creators of the collection
* @param creators - the creators to update
* @param updateAll - whether or not to retroactively update the creators of all past NFTs
*/
async updateCreators(creators: CreatorInput[]) {
const tx = await this.metaplex.candyMachinesV2().update({
candyMachine: await this.getCandyMachine(),
creators: enforceCreator(creators, this.metaplex.identity().publicKey),
});
async updateCreators(
creators: CreatorInput[],
updateAll: boolean = false,
): Promise<TransactionResult[]> {
if (updateAll) {
const txs: TransactionBuilder[] = [];
return {
signature: tx.response.signature,
};
const candyMachine = await this.getCandyMachine();
const collectionAddress = candyMachine.collectionMintAddress;
invariant(collectionAddress, "Collection mint address not found");
// We need to find the candy machine creator PDA which is auto populated onto NFTs
// minted with the candy machine, and add it to the list of creators for each NFT
const candyMachineCreatorPda = findCandyMachineV2CreatorPda(
candyMachine.address,
);
const nftCreators = [
{
address: candyMachineCreatorPda.toBase58(),
share: 0,
},
...creators,
];
const allNfts = await this.nft.getAll(collectionAddress.toBase58());
await Promise.all(
allNfts.map(async (nft) => {
const metaplexNft = await this.metaplex
.nfts()
.findByMint({ mintAddress: new PublicKey(nft.metadata.id) });
txs.push(
this.metaplex
.nfts()
.builders()
.update({
nftOrSft: metaplexNft,
creators: enforceCreator(
nftCreators,
this.metaplex.identity().publicKey,
),
}),
);
}),
);
const results = await sendMultipartTransaction(txs, this.metaplex);
const tx = await this.metaplex.candyMachinesV2().update({
candyMachine: await this.getCandyMachine(),
creators: enforceCreator(creators, this.metaplex.identity().publicKey),
});
return [
{
signature: tx.response.signature,
},
...results,
];
} else {
const tx = await this.metaplex.candyMachinesV2().update({
candyMachine: await this.getCandyMachine(),
creators: enforceCreator(creators, this.metaplex.identity().publicKey),
});
return [
{
signature: tx.response.signature,
},
];
}
}
/**
* Update the royalty basis points of the collection
* @param sellerFeeBasisPoints - the royalty basis points of the collection
* @param updateAll - whether or not to retroactively update the royalty basis points of all past NFTs
*/
async updateRoyalty(sellerFeeBasisPoints: number) {
const tx = await this.metaplex.candyMachinesV2().update({
candyMachine: await this.getCandyMachine(),
sellerFeeBasisPoints,
});
async updateRoyalty(
sellerFeeBasisPoints: number,
updateAll: boolean = false,
) {
if (updateAll) {
const txs: TransactionBuilder[] = [];
return {
signature: tx.response.signature,
};
const candyMachine = await this.getCandyMachine();
const collectionAddress = candyMachine.collectionMintAddress;
invariant(collectionAddress, "Collection mint address not found");
const allNfts = await this.nft.getAll(collectionAddress.toBase58());
await Promise.all(
allNfts.map(async (nft) => {
const metaplexNft = await this.metaplex
.nfts()
.findByMint({ mintAddress: new PublicKey(nft.metadata.id) });
txs.push(
this.metaplex.nfts().builders().update({
nftOrSft: metaplexNft,
sellerFeeBasisPoints,
}),
);
}),
);
const results = await sendMultipartTransaction(txs, this.metaplex);
const tx = await this.metaplex.candyMachinesV2().update({
candyMachine: await this.getCandyMachine(),
sellerFeeBasisPoints,
});
return [
{
signature: tx.response.signature,
},
...results,
];
} else {
const tx = await this.metaplex.candyMachinesV2().update({
candyMachine: await this.getCandyMachine(),
sellerFeeBasisPoints,
});
return {
signature: tx.response.signature,
};
}
}
private async getCandyMachine() {
+18 -2
View File
@@ -1,3 +1,4 @@
import { NFTMetadata, NFTMetadataInput } from "../../src/core/schema/nft";
import {
ClaimEligibility,
EditionDrop,
@@ -49,7 +50,7 @@ describe("Edition Drop Contract (V2)", async () => {
platform_fee_basis_points: 10,
platform_fee_recipient: adminWallet.address,
},
2,
"2",
);
bdContract = await sdk.getEditionDrop(address);
});
@@ -60,10 +61,25 @@ describe("Edition Drop Contract (V2)", async () => {
"mock://12398172398172389/0",
]);
expect(parseFloat(cost)).gt(0);
await bdContract.createBatch([{ name: `test$`, description: `desc` }]);
await bdContract.claimConditions.set(0, [
{
price: 0.1,
},
]);
const claimTx = await bdContract.getClaimTransaction(
adminWallet.address,
0,
1,
);
const cost2 = await claimTx.estimateGasCostInEther();
console.log("cost2", cost2);
expect(parseFloat(cost2)).gt(0);
});
it("comprehensive test", async () => {
const metadata = [];
const metadata: NFTMetadataInput[] = [];
for (let i = 0; i < 3; i++) {
metadata.push({ name: `test${i}`, description: `desc${i}` });
}
+37 -27
View File
@@ -40,6 +40,11 @@ describe("NFTCollection", async () => {
expect(all[0].metadata.name).to.eq("Test NFT");
});
it("should fetch transactions", async () => {
const txns = await collection.getTransactions();
expect(txns.length).to.eq(2);
});
it("should fetch balance of NFTs", async () => {
const all = await collection.getAll();
const balance = await collection.balanceOf(
@@ -148,14 +153,19 @@ describe("NFTCollection", async () => {
expect(creators[0].address).to.equal(sdk.wallet.getAddress());
expect(creators[0].share).to.equal(100);
const numNfts = (await collection.getAll()).length;
const newCreator = Keypair.generate().publicKey.toBase58();
await collection.updateCreators([
{
address: sdk.wallet.getAddress() as string,
share: 75,
},
{ address: newCreator, share: 25 },
]);
await collection.updateCreators(
[
{
address: sdk.wallet.getAddress() as string,
share: 75,
},
{ address: newCreator, share: 25 },
],
true,
);
creators = await collection.getCreators();
expect(creators.length).to.equal(2);
@@ -164,36 +174,36 @@ describe("NFTCollection", async () => {
expect(creators[1].address).to.equal(newCreator);
expect(creators[1].share).to.equal(25);
// TODO (adam): fix this test
// const all = await collection.getAll();
// for (const nft of all) {
// // @ts-ignore
// const creatorsOfNft = await collection.nft.creatorsOf(nft.metadata.id);
// expect(creatorsOfNft.length).to.equal(2);
// expect(creatorsOfNft[0].address).to.equal(sdk.wallet.getAddress());
// expect(creatorsOfNft[0].share).to.equal(75);
// expect(creatorsOfNft[1].address).to.equal(newCreator);
// expect(creatorsOfNft[1].share).to.equal(25);
// }
const all = await collection.getAll();
expect(all.length).to.equal(numNfts);
for (const nft of all) {
// @ts-ignore
const creatorsOfNft = await collection.nft.creatorsOf(nft.metadata.id);
expect(creatorsOfNft.length).to.equal(2);
expect(creatorsOfNft[0].address).to.equal(sdk.wallet.getAddress());
expect(creatorsOfNft[0].share).to.equal(75);
expect(creatorsOfNft[1].address).to.equal(newCreator);
expect(creatorsOfNft[1].share).to.equal(25);
}
});
it("Should update royalty", async () => {
let royalty = await collection.getRoyalty();
expect(royalty).to.equal(0);
const mintAddress = (await collection.getAll())[0].metadata.id;
// @ts-ignore
let nft = await collection.nft.getRaw(mintAddress);
expect(nft.isMutable).to.equal(true);
expect(nft.sellerFeeBasisPoints).to.equal(0);
const numNfts = (await collection.getAll()).length;
await collection.updateRoyalty(100);
await collection.updateRoyalty(100, true);
royalty = await collection.getRoyalty();
expect(royalty).to.equal(100);
// TODO (adam): fix this test
// nft = await collection.nft.getRaw(mintAddress);
// expect(nft.sellerFeeBasisPoints).to.equal(100);
const all = await collection.getAll();
expect(all.length).to.equal(numNfts);
for (const singleNft of all) {
// @ts-ignore
const royaltyOfNft = await collection.nft.getRaw(singleNft.metadata.id);
expect(royaltyOfNft.sellerFeeBasisPoints).to.equal(100);
}
});
});
+39 -5
View File
@@ -131,11 +131,20 @@ describe("NFTDrop", async () => {
expect(creators[0].address).to.equal(sdk.wallet.getAddress());
expect(creators[0].share).to.equal(100);
const numNfts = (await drop.getAllClaimed()).length;
const newCreator = Keypair.generate().publicKey.toBase58();
await drop.updateCreators([
{ address: sdk.wallet.getAddress() as string, share: 75 },
{ address: newCreator, share: 25 },
]);
await drop.updateCreators(
[
{
address: sdk.wallet.getAddress() as string,
share: 75,
verified: true,
},
{ address: newCreator, share: 25, verified: true },
],
true,
);
creators = await drop.getCreators();
expect(creators.length).to.equal(2);
@@ -143,14 +152,39 @@ describe("NFTDrop", async () => {
expect(creators[0].share).to.equal(75);
expect(creators[1].address).to.equal(newCreator);
expect(creators[1].share).to.equal(25);
const all = await drop.getAllClaimed();
expect(all.length).to.equal(numNfts);
for (const nft of all) {
// @ts-ignore
const creatorsOfNft = await drop.nft.creatorsOf(nft.metadata.id);
expect(creatorsOfNft.length).to.equal(3);
// Skip checking the first creator which is the candy machine creator pda
expect(creatorsOfNft[1].address).to.equal(sdk.wallet.getAddress());
expect(creatorsOfNft[1].share).to.equal(75);
expect(creatorsOfNft[2].address).to.equal(newCreator);
expect(creatorsOfNft[2].share).to.equal(25);
}
});
it("Should update royalty", async () => {
let royalty = await drop.getRoyalty();
expect(royalty).to.equal(0);
await drop.updateRoyalty(100);
const mintAddress = (await drop.getAll())[0].metadata.id;
// @ts-ignore
let nft = await drop.nft.getRaw(mintAddress);
expect(nft.isMutable).to.equal(true);
expect(nft.sellerFeeBasisPoints).to.equal(0);
await drop.updateRoyalty(100, true);
royalty = await drop.getRoyalty();
expect(royalty).to.equal(100);
// @ts-ignore
nft = await drop.nft.getRaw(mintAddress);
expect(nft.sellerFeeBasisPoints).to.equal(100);
});
it("Should get all correctly", async () => {
+21
View File
@@ -1,5 +1,26 @@
# @thirdweb-dev/unity-js-bridge
## 0.2.4
### Patch Changes
- Updated dependencies [[`ec1f232`](https://github.com/thirdweb-dev/js/commit/ec1f2324c7a0e58c2d2a209cfe0d194807ba5b70), [`d29f7e7`](https://github.com/thirdweb-dev/js/commit/d29f7e78f09063630e812dd41164d8a41d4f97dd)]:
- @thirdweb-dev/sdk@3.7.4
## 0.2.3
### Patch Changes
- Updated dependencies [[`b45d761`](https://github.com/thirdweb-dev/js/commit/b45d761f8f2695b48312ec6eff15e0549e6a8a41), [`5f8ec45`](https://github.com/thirdweb-dev/js/commit/5f8ec45af7c81d075a84846098f38cad90d03fb9), [`04de5b2`](https://github.com/thirdweb-dev/js/commit/04de5b278362573991140c3a496de7451e5c770d)]:
- @thirdweb-dev/sdk@3.7.3
## 0.2.2
### Patch Changes
- Updated dependencies [[`19b8e18`](https://github.com/thirdweb-dev/js/commit/19b8e18b6bf68e374c817fefbf2fd29ac5573052)]:
- @thirdweb-dev/sdk@3.7.2
## 0.2.1
### Patch Changes
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@thirdweb-dev/unity-js-bridge",
"version": "0.2.1",
"version": "0.2.4",
"main": "dist/thirdweb-unity-bridge.js",
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/unity-js-bridge",
"license": "Apache-2.0",
+3067 -3019
View File
File diff suppressed because it is too large Load Diff