Compare commits

...
Author SHA1 Message Date
github-actions[bot]GitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>
b4e005be7f Version Packages (#401)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-11-22 14:31:57 -08:00
Nacho IacovinoandGitHub ccb7db4873 [Solana + React] Update hooks for creators/royalties (#405) 2022-11-22 19:22:51 +00:00
Jonas DanielsandGitHub 9151aa7dc8 [SDK] - expose getDefaultTrustedForwarders helper fn (#404) 2022-11-22 03:35:01 +00:00
5a01c537e3 [DO NOT MERGE] Update to Metaplex v0.17 (#305)
Co-authored-by: Jonas Daniels <[email protected]>
2022-11-21 16:14:39 -08:00
github-actions[bot]GitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>
f09c153ff7 Version Packages (#391)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-11-21 15:22:56 -08:00
Nacho IacovinoandGitHub 15431621fd [React] Remove console.log (#400) 2022-11-21 20:03:32 +00:00
Jonas DanielsandGitHub 887af24450 [SDK] - fix error handling for nullish error values (#399) 2022-11-21 18:52:02 +00:00
Jonas DanielsandGitHub 15514f190a [SDK] - add default value option to constructorParams schema (#398) 2022-11-21 18:28:18 +00:00
Adam MajmudarandGitHub 72589ec234 Call user callback in getUser (#397) 2022-11-21 17:46:18 +00:00
Jonas DanielsandGitHub f8bceec10c fix solana claim condition native token (#395) 2022-11-19 05:36:42 +00:00
Adam MajmudarandGitHub 7c0744a006 Add support for total supply and pagination on get all (#388) 2022-11-18 02:21:32 +00:00
Nacho IacovinoandGitHub 846022e2cf [React] Fix unlimited price (#392) 2022-11-17 22:25:25 +00:00
Joaquim VergesandGitHub 96bd92e724 [SDK] Expose getAllDetectedFeatures(ABI) helper function (#390) 2022-11-17 14:07:37 -08:00
43 changed files with 4072 additions and 3727 deletions
+8
View File
@@ -1,5 +1,13 @@
# @thirdweb-dev/auth
## 2.0.32
## 2.0.31
### Patch Changes
- [#397](https://github.com/thirdweb-dev/js/pull/397) [`72589ec`](https://github.com/thirdweb-dev/js/commit/72589ec234d86939b67b0ca8b3b789f2e9c54cc2) Thanks [@adam-maj](https://github.com/adam-maj)! - Call user callback in getUser
## 2.0.30
## 2.0.29
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@thirdweb-dev/auth",
"version": "2.0.30",
"version": "2.0.32",
"exports": {
"./next": {
"module": "./next/dist/thirdweb-dev-auth-next.esm.js",
@@ -73,7 +73,7 @@
"eslint-plugin-inclusive-language": "^2.2.0",
"eslint-plugin-prettier": "^4.2.1",
"eslint-plugin-tsdoc": "^0.2.16",
"ethers": "^5.7.1",
"ethers": "^5.7.2",
"express": "^4.18.1",
"next": "^12.2.0",
"next-auth": "^4.10.3",
+7 -1
View File
@@ -70,7 +70,13 @@ export function ThirdwebAuth(cfg: ThirdwebAuthConfig) {
if (token) {
try {
const address = await sdk.auth.authenticate(domain, token);
user = { address };
let data = {};
if (ctx.callbacks?.user) {
data = await ctx.callbacks.user(address);
}
user = { ...data, address };
} catch {
// No-op
}
+7 -1
View File
@@ -70,7 +70,13 @@ export function ThirdwebAuth(cfg: ThirdwebAuthConfig) {
if (token) {
try {
const address = await sdk.auth.authenticate(domain, token);
user = { address };
let data = {};
if (ctx.callbacks?.user) {
data = await ctx.callbacks.user(address);
}
user = { ...data, address };
} catch {
// No-op
}
+14
View File
@@ -1,5 +1,19 @@
# thirdweb
## 0.8.18
### Patch Changes
- Updated dependencies [[`ccb7db4`](https://github.com/thirdweb-dev/js/commit/ccb7db48739b8dddcb2c032b3b6e3e5200485715), [`9151aa7`](https://github.com/thirdweb-dev/js/commit/9151aa7dc80754a7aa4fd3f6ce0207bccbb6451f), [`5a01c53`](https://github.com/thirdweb-dev/js/commit/5a01c537e30bd7ef562aad1012413990de6faedf)]:
- @thirdweb-dev/sdk@3.6.2
## 0.8.17
### Patch Changes
- Updated dependencies [[`15514f1`](https://github.com/thirdweb-dev/js/commit/15514f190a844d809ae5b1edb580aab46a682485), [`7c0744a`](https://github.com/thirdweb-dev/js/commit/7c0744a006e78987ad8b271b2c64f4bac7759510), [`f8bceec`](https://github.com/thirdweb-dev/js/commit/f8bceec10c60b30dc3d6f45926e2a9e018202578), [`887af24`](https://github.com/thirdweb-dev/js/commit/887af24450e316c2ea390cd49c0563cebe793c0f), [`96bd92e`](https://github.com/thirdweb-dev/js/commit/96bd92e724ec7d880d23348071b26ab8c21dd868)]:
- @thirdweb-dev/sdk@3.6.1
## 0.8.16
### Patch Changes
+4 -4
View File
@@ -1,7 +1,7 @@
{
"name": "thirdweb",
"main": "dist/cli/index.js",
"version": "0.8.16",
"version": "0.8.18",
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/cli",
"author": "thirdweb eng <[email protected]>",
"license": "Apache-2.0",
@@ -10,7 +10,7 @@
},
"devDependencies": {
"@gmrchk/cli-testing-library": "^0.1.2",
"@types/async-retry": "1.3.0",
"@types/async-retry": "^1.3.0",
"@types/cross-spawn": "^6.0.2",
"@types/inquirer": "^8.2.1",
"@types/jest": "^29.0.0",
@@ -33,13 +33,13 @@
"async-retry": "^1.3.3",
"commander": "^9.1.0",
"enquirer": "^2.3.6",
"ethers": "^5.7.0",
"ethers": "^5.7.2",
"got": "11.8.5",
"inquirer": "^8.2.3",
"open": "^8.4.0",
"prompts": "^2.4.2",
"rimraf": "^3.0.2",
"solc": "0.8.13",
"solc": "0.8.17",
"tar": "^6.1.11",
"tslog": "^3.3.3",
"update-notifier": "^6.0.2",
+1 -1
View File
@@ -13,7 +13,7 @@
"@babel/preset-typescript": "^7.18.6",
"@preconstruct/cli": "^2.2.1",
"@typechain/ethers-v5": "10.0.0",
"ethers": "^5.7.0",
"ethers": "^5.7.2",
"typechain": "^8.1.0",
"typescript": "^4.7.4"
},
+1 -1
View File
@@ -6,7 +6,7 @@
"dependencies": {
"@typescript-eslint/eslint-plugin": "^5.33.0",
"@typescript-eslint/parser": "^5.33.0",
"eslint-config-next": "^12.0.8",
"eslint-config-next": "12.3.1",
"eslint-config-prettier": "^8.3.0",
"eslint-config-turbo": "latest",
"eslint-plugin-react": "^7.28.0"
+14
View File
@@ -1,5 +1,19 @@
# @thirdweb-dev/react
## 3.6.2
### Patch Changes
- [#405](https://github.com/thirdweb-dev/js/pull/405) [`ccb7db4`](https://github.com/thirdweb-dev/js/commit/ccb7db48739b8dddcb2c032b3b6e3e5200485715) Thanks [@nachoiacovino](https://github.com/nachoiacovino)! - Add updateAll param to creators and royalty update hooks for Solana
## 3.6.1
### Patch Changes
- [#392](https://github.com/thirdweb-dev/js/pull/392) [`846022e`](https://github.com/thirdweb-dev/js/commit/846022e2cfb12b846aae029b85899fb72fd2c9ad) Thanks [@nachoiacovino](https://github.com/nachoiacovino)! - Fix unlimited price for useActiveClaimConditionForWallet
- [#388](https://github.com/thirdweb-dev/js/pull/388) [`7c0744a`](https://github.com/thirdweb-dev/js/commit/7c0744a006e78987ad8b271b2c64f4bac7759510) Thanks [@adam-maj](https://github.com/adam-maj)! - Add support for total supply and pagination on get all
## 3.6.0
### Patch Changes
+4 -3
View File
@@ -1,6 +1,6 @@
{
"name": "@thirdweb-dev/react",
"version": "3.6.0",
"version": "3.6.2",
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/react",
"author": "thirdweb eng <[email protected]>",
"license": "Apache-2.0",
@@ -62,7 +62,7 @@
},
"sideEffects:": false,
"devDependencies": {
"@babel/core": "^7.18.10",
"@babel/core": "^7.19.3",
"@babel/preset-env": "^7.18.10",
"@babel/preset-react": "^7.18.6",
"@babel/preset-typescript": "^7.18.6",
@@ -73,6 +73,7 @@
"@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.62.0",
"@thirdweb-dev/sdk": "*",
"@types/color": "^3.0.3",
@@ -87,7 +88,7 @@
"eslint-plugin-inclusive-language": "^2.2.0",
"eslint-plugin-prettier": "^4.2.1",
"eslint-plugin-tsdoc": "^0.2.16",
"ethers": "^5.7.1",
"ethers": "^5.7.2",
"prettier": "^2.7.1",
"react": "^18.2.0",
"react-dom": "^18.2.0",
@@ -19,7 +19,7 @@ import {
convertToReadableQuantity,
fetchCurrencyMetadata,
} from "@thirdweb-dev/sdk";
import { BigNumberish, utils } from "ethers";
import { BigNumberish, constants, utils } from "ethers";
import invariant from "tiny-invariant";
/**
@@ -411,7 +411,9 @@ export function useActiveClaimConditionForWallet(
);
const normalizedPrize = price
? utils.parseUnits(price, currencyMetadata.decimals)
? price === "unlimited"
? constants.MaxUint256
: utils.parseUnits(price, currencyMetadata.decimals)
: null;
const priceWithOverride =
+12 -4
View File
@@ -4,17 +4,22 @@ import {
RequiredParam,
} from "../../../core/query-utils/required-param";
import { useQuery } from "@tanstack/react-query";
import { QueryAllParams } from "@thirdweb-dev/sdk";
import type { NFTCollection, NFTDrop } from "@thirdweb-dev/sdk/solana";
export function nftGetAllQuery(
program: RequiredParam<NFTCollection | NFTDrop>,
queryParams?: QueryAllParams,
) {
return {
queryKey: createSOLProgramQueryKey(program, ["getAll"] as const),
queryKey: createSOLProgramQueryKey(program, [
"getAll",
queryParams,
] as const),
queryFn: async () => {
requiredParamInvariant(program, "program is required");
return await program.getAll();
return program.getAll(queryParams);
},
enabled: !!program,
};
@@ -40,6 +45,9 @@ export function nftGetAllQuery(
*
* @public
*/
export function useNFTs(program: RequiredParam<NFTCollection | NFTDrop>) {
return useQuery(nftGetAllQuery(program));
export function useNFTs(
program: RequiredParam<NFTCollection | NFTDrop>,
queryParams?: QueryAllParams,
) {
return useQuery(nftGetAllQuery(program, queryParams));
}
@@ -0,0 +1,47 @@
import { createSOLProgramQueryKey } from "../../../core/query-utils/query-key";
import {
requiredParamInvariant,
RequiredParam,
} from "../../../core/query-utils/required-param";
import { useQuery } from "@tanstack/react-query";
import type { NFTCollection, NFTDrop } from "@thirdweb-dev/sdk/solana";
export function nftTotalSupplyQuery(
program: RequiredParam<NFTCollection | NFTDrop>,
) {
return {
queryKey: createSOLProgramQueryKey(program, ["supply"] as const),
queryFn: async () => {
requiredParamInvariant(program, "program is required");
return program.totalSupply();
},
enabled: !!program,
};
}
/**
* Get the totaly supply of NFTs on the program
* @param program - The NFT program to get the total supply of
*
* @example
* ```jsx
* import { useProgram, useTotalSupply } from "@thirdweb-dev/react/solana";
*
* export default function Component() {
* const { program } = useProgram("{{program_address}}");
* const { data: supply, isLoading } = useTotalSupply(program);
*
* return (
* <pre>{JSON.stringify(supply)}</pre>
* )
* }
* ```
*
* @public
*/
export function useTotalSupply(
program: RequiredParam<NFTCollection | NFTDrop>,
) {
return useQuery(nftTotalSupplyQuery(program));
}
@@ -4,7 +4,7 @@ import {
RequiredParam,
} from "../../../core/query-utils/required-param";
import { useMutation, useQueryClient } from "@tanstack/react-query";
import type { CreatorInput, NFTCollection, NFTDrop } from "@thirdweb-dev/sdk/solana";
import type { NFTCollection, NFTDrop, UpdateCreatorInput } from "@thirdweb-dev/sdk/solana";
/**
* Update the creators for an NFT program
@@ -35,9 +35,9 @@ export function useUpdateCreators(
) {
const queryClient = useQueryClient();
return useMutation(
async (creators: CreatorInput[]) => {
async ({ creators, updateAll }: UpdateCreatorInput) => {
requiredParamInvariant(program, "program is required");
return await program.updateCreators(creators);
return await program.updateCreators(creators, updateAll);
},
{
onSettled: () =>
@@ -4,7 +4,7 @@ import {
RequiredParam,
} from "../../../core/query-utils/required-param";
import { useMutation, useQueryClient } from "@tanstack/react-query";
import type { NFTCollection, NFTDrop } from "@thirdweb-dev/sdk/solana";
import type { NFTCollection, NFTDrop, UpdateRoyaltySettingsInput } from "@thirdweb-dev/sdk/solana";
/**
* Update the royalty for an NFT program
@@ -35,9 +35,9 @@ export function useUpdateRoyaltySettings(
) {
const queryClient = useQueryClient();
return useMutation(
async (sellerFeeBasisPoints: number) => {
async ({ sellerFeeBasisPoints, updateAll }: UpdateRoyaltySettingsInput) => {
requiredParamInvariant(program, "program is required");
return await program.updateRoyalty(sellerFeeBasisPoints);
return await program.updateRoyalty(sellerFeeBasisPoints, updateAll);
},
{
onSettled: () =>
+1
View File
@@ -18,6 +18,7 @@ export * from "./hooks/nft/useRoyaltySettings";
export * from "./hooks/nft/useUpdateRoyaltySettings";
export * from "./hooks/nft/useCreators";
export * from "./hooks/nft/useUpdateCreators";
export * from "./hooks/nft/useTotalSupply";
// NFT Collection
export * from "./hooks/nft/collection/useMintNFT";
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+24
View File
@@ -1,5 +1,29 @@
# @thirdweb-dev/sdk
## 3.6.2
### Patch Changes
- [#405](https://github.com/thirdweb-dev/js/pull/405) [`ccb7db4`](https://github.com/thirdweb-dev/js/commit/ccb7db48739b8dddcb2c032b3b6e3e5200485715) Thanks [@nachoiacovino](https://github.com/nachoiacovino)! - Add updateAll param to creators and royalty update hooks for Solana
- [#404](https://github.com/thirdweb-dev/js/pull/404) [`9151aa7`](https://github.com/thirdweb-dev/js/commit/9151aa7dc80754a7aa4fd3f6ce0207bccbb6451f) Thanks [@jnsdls](https://github.com/jnsdls)! - [EVM] - expose `getDefaultTrustedForwarders` helper function
- [#305](https://github.com/thirdweb-dev/js/pull/305) [`5a01c53`](https://github.com/thirdweb-dev/js/commit/5a01c537e30bd7ef562aad1012413990de6faedf) Thanks [@joaquim-verges](https://github.com/joaquim-verges)! - Update to Metaplex 0.17
## 3.6.1
### Patch Changes
- [#398](https://github.com/thirdweb-dev/js/pull/398) [`15514f1`](https://github.com/thirdweb-dev/js/commit/15514f190a844d809ae5b1edb580aab46a682485) Thanks [@jnsdls](https://github.com/jnsdls)! - [EVM] - add `defaultValue` to constructorParams schema for releases
- [#388](https://github.com/thirdweb-dev/js/pull/388) [`7c0744a`](https://github.com/thirdweb-dev/js/commit/7c0744a006e78987ad8b271b2c64f4bac7759510) Thanks [@adam-maj](https://github.com/adam-maj)! - Add support for total supply and pagination on get all
- [#395](https://github.com/thirdweb-dev/js/pull/395) [`f8bceec`](https://github.com/thirdweb-dev/js/commit/f8bceec10c60b30dc3d6f45926e2a9e018202578) Thanks [@jnsdls](https://github.com/jnsdls)! - [Solana] - fix claim condition reset to native token from custom
- [#399](https://github.com/thirdweb-dev/js/pull/399) [`887af24`](https://github.com/thirdweb-dev/js/commit/887af24450e316c2ea390cd49c0563cebe793c0f) Thanks [@jnsdls](https://github.com/jnsdls)! - [EVM] - fix custom error handling for null-ish error values
- [#390](https://github.com/thirdweb-dev/js/pull/390) [`96bd92e`](https://github.com/thirdweb-dev/js/commit/96bd92e724ec7d880d23348071b26ab8c21dd868) Thanks [@joaquim-verges](https://github.com/joaquim-verges)! - [SDK] Expose `getAllDetectedFeatures(ABI)` helper function
## 3.6.0
### Minor Changes
+12 -12
View File
@@ -1,6 +1,6 @@
{
"name": "@thirdweb-dev/sdk",
"version": "3.6.0",
"version": "3.6.2",
"description": "The main thirdweb SDK.",
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/sdk",
"license": "Apache-2.0",
@@ -57,7 +57,7 @@
"test:evm:all": "SWC_NODE_PROJECT=./tsconfig.test.json mocha --config './test/evm/.mocharc.json' --timeout 30000 --parallel './test/evm/**/*.test.ts'",
"test:evm": "make test-evm",
"test:evm:single": "SWC_NODE_PROJECT=./tsconfig.test.json mocha --config './test/evm/.mocharc.json' --timeout 30000",
"node:solana:start": "DEBUG='amman:(info|error|debug)' amman start",
"node:solana:start": "DEBUG='amman:(info|error|debug)' amman start --forceClone",
"node:solana:stop": "amman stop",
"test:solana:all": "SWC_NODE_PROJECT=./tsconfig.test.json mocha --config './test/solana/.mocharc.json' --timeout 30000 --parallel './test/solana/**/*.test.ts'",
"test:solana": "make test-sol",
@@ -65,18 +65,18 @@
"push": "yalc push"
},
"devDependencies": {
"@metaplex-foundation/amman": "0.10.0",
"@metaplex-foundation/amman-client": "0.2.1",
"@metaplex-foundation/amman": "^0.12.0",
"@metaplex-foundation/amman-client": "^0.2.1",
"@microsoft/api-documenter": "^7.19.4",
"@microsoft/api-extractor": "^7.29.2",
"@microsoft/tsdoc": "^0.14.1",
"@nomiclabs/hardhat-ethers": "2.0.5",
"@nomiclabs/hardhat-ethers": "^2.0.5",
"@preconstruct/cli": "^2.2.1",
"@swc-node/register": "^1.5.1",
"@swc/core": "^1.2.177",
"@types/chai": "^4.3.3",
"@types/deep-equal-in-any-order": "^1.0.1",
"@types/mocha": "^9.1.1",
"@types/mocha": "^10.0.0",
"@types/node": "^18.0.0",
"@types/uuid": "^8.3.3",
"@typescript-eslint/eslint-plugin": "^5.33.0",
@@ -89,7 +89,7 @@
"eslint-plugin-inclusive-language": "^2.2.0",
"eslint-plugin-prettier": "^4.2.1",
"eslint-plugin-tsdoc": "^0.2.16",
"ethers": "^5.7.0",
"ethers": "^5.7.2",
"hardhat": "^2.9.3",
"mocha": "^10.0.0",
"prettier": "^2.7.1",
@@ -99,11 +99,11 @@
"ethers": "^5"
},
"dependencies": {
"@metaplex-foundation/js": "0.15.0",
"@metaplex-foundation/mpl-token-metadata": "2.2.2",
"@project-serum/anchor": "0.25.0",
"@solana/spl-token": "0.2.0",
"@solana/web3.js": "1.62.0",
"@metaplex-foundation/js": "^0.17.6",
"@metaplex-foundation/mpl-token-metadata": "^2.3.3",
"@project-serum/anchor": "^0.25.0",
"@solana/spl-token": "^0.3.5",
"@solana/web3.js": "^1.62.0",
"@thirdweb-dev/contracts-js": "*",
"@thirdweb-dev/storage": "*",
"bn.js": "^5.2.1",
+16 -10
View File
@@ -1,19 +1,25 @@
import { z } from "zod";
/**
* @internal
*/
export const DEFAULT_QUERY_ALL_COUNT = 100;
export const QueryAllParamsSchema = z
.object({
start: z.number().default(0),
count: z.number().default(DEFAULT_QUERY_ALL_COUNT),
})
.default({
start: 0,
count: DEFAULT_QUERY_ALL_COUNT,
});
/**
* Pagination Parameters
* @public
*/
export interface QueryAllParams {
/**
* the index to start from (default: 0)
*/
start?: number;
/**
* how many items to return (default: 100)
*/
count?: number;
}
export type QueryAllParams = Exclude<
z.input<typeof QueryAllParamsSchema>,
undefined
>;
+5 -2
View File
@@ -459,9 +459,12 @@ function parseMessageParts(regex: RegExp, raw: string): string {
* @param message
*/
export function includesErrorMessage(err: any, message: string): boolean {
if (!err) {
return false;
}
return (
(err && err.toString().includes(message)) ||
(err.message && err.message.toString().includes(message)) ||
(err.error && err.error.toString().includes(message))
(err && err.message && err.message.toString().includes(message)) ||
(err && err.error && err.error.toString().includes(message))
);
}
@@ -525,7 +525,7 @@ export async function fetchExtendedReleaseMetadata(
* @returns the nested struct of all features and whether they're detected in the abi
*/
export function detectFeatures(
abi: z.input<typeof AbiSchema>,
abi: Abi,
features: Record<string, Feature> = SUPPORTED_FEATURES,
): Record<string, FeatureWithEnabled> {
const results: Record<string, FeatureWithEnabled> = {};
@@ -542,6 +542,51 @@ export function detectFeatures(
return results;
}
function extractFeatures(
input: Record<string, FeatureWithEnabled>,
enabledExtensions: FeatureWithEnabled[],
) {
if (!input) {
return;
}
for (const extensionKey in input) {
const extension = input[extensionKey];
// if extension is enabled, then add it to enabledFeatures
if (extension.enabled) {
enabledExtensions.push(extension);
}
// recurse
extractFeatures(
extension.features,
enabledExtensions,
);
}
}
/**
* Return all the detected features in the abi
* @param abi - parsed array of abi entries
* @returns array of all detected extensions with full information on each feature
* @public
*/
export function getAllDetectedFeatures(abi: Abi): FeatureWithEnabled[] {
const features: FeatureWithEnabled[] = [];
extractFeatures(detectFeatures(abi), features);
return features;
}
/**
* Return all the detected features names in the abi
* @param abi - parsed array of abi entries
* @returns array of all detected features names
* @public
*/
export function getAllDetectedFeatureNames(abi: Abi): string[] {
const features: FeatureWithEnabled[] = [];
extractFeatures(detectFeatures(abi), features);
return features.map((f) => f.name);
}
/**
* Checks whether the given ABI supports a given feature
* @internal
+22 -1
View File
@@ -1,5 +1,5 @@
import { PrebuiltContractType } from "../core/types";
import { ChainId, SUPPORTED_CHAIN_ID } from "./chains";
import { ChainId, SUPPORTED_CHAIN_ID, SUPPORTED_CHAIN_IDS } from "./chains";
import { constants } from "ethers";
/**
@@ -290,3 +290,24 @@ export function getContractPublisherAddress() {
return ContractPublisher_address;
}
}
/**
*
* @param chainId - chain id
* @returns the array of trusted forwarders for the given chain id
* @internal
*/
export function getDefaultTrustedForwarders(
chainId: SUPPORTED_CHAIN_ID,
): string[] {
const chainEnum = SUPPORTED_CHAIN_IDS.find((c) => c === chainId);
const biconomyForwarder = chainEnum
? CONTRACT_ADDRESSES[chainEnum].biconomyForwarder
: constants.AddressZero;
const openzeppelinForwarder = chainEnum
? CONTRACT_ADDRESSES[chainEnum].openzeppelinForwarder
: constants.AddressZero;
return biconomyForwarder !== constants.AddressZero
? [openzeppelinForwarder, biconomyForwarder]
: [openzeppelinForwarder];
}
+2 -12
View File
@@ -1,7 +1,6 @@
import {
CONTRACT_ADDRESSES,
getApprovedImplementation,
SUPPORTED_CHAIN_IDS,
getDefaultTrustedForwarders,
} from "../../constants";
import {
EditionDropInitializer,
@@ -296,16 +295,7 @@ export class ContractFactory extends ContractWrapper<TWFactory> {
private async getDefaultTrustedForwarders(): Promise<string[]> {
const chainId = await this.getChainID();
const chainEnum = SUPPORTED_CHAIN_IDS.find((c) => c === chainId);
const biconomyForwarder = chainEnum
? CONTRACT_ADDRESSES[chainEnum].biconomyForwarder
: constants.AddressZero;
const openzeppelinForwarder = chainEnum
? CONTRACT_ADDRESSES[chainEnum].openzeppelinForwarder
: constants.AddressZero;
return biconomyForwarder !== constants.AddressZero
? [openzeppelinForwarder, biconomyForwarder]
: [openzeppelinForwarder];
return getDefaultTrustedForwarders(chainId);
}
private async getImplementation(
@@ -162,6 +162,7 @@ export const ExtraPublishMetadataSchemaInput = z
.object({
displayName: z.string().optional(),
description: z.string().optional(),
defaultValue: z.string().optional(),
})
.catchall(z.any()),
)
@@ -7,7 +7,7 @@ import {
import { toCurrencyValue } from "../utils/token";
import {
Amount,
CandyMachineEndSettings,
CandyMachineV2EndSettings,
DateTime,
Metaplex,
sol,
@@ -168,8 +168,7 @@ export class ClaimConditions {
if (parsed.currencyAddress && parsed.price) {
const fetchedToken = await this.metaplex
.tokens()
.findMintByAddress({ address: new PublicKey(parsed.currencyAddress) })
.run();
.findMintByAddress({ address: new PublicKey(parsed.currencyAddress) });
price = token(Number(parsed.price), fetchedToken.decimals);
tokenMint = fetchedToken.address;
}
@@ -180,7 +179,7 @@ export class ClaimConditions {
: undefined;
// max claimable
const endSettings: CandyMachineEndSettings | null | undefined =
const endSettings: CandyMachineV2EndSettings | null | undefined =
parsed.maxClaimable
? parsed.maxClaimable === "unlimited"
? null
@@ -194,20 +193,22 @@ export class ClaimConditions {
const data = {
...(wallet && { wallet }),
...(tokenMint && { tokenMint }),
...(tokenMint
? { tokenMint }
: // if passing currencyAddress explcitly as null we need to honor that!
parsed.currencyAddress === null
? { tokenMint: null }
: {}),
...(price && { price }),
...(goLiveDate && { goLiveDate }),
...(sellerFeeBasisPoints && { sellerFeeBasisPoints }),
...(endSettings !== undefined && { endSettings }),
};
const result = await this.metaplex
.candyMachines()
.update({
candyMachine: await this.getCandyMachine(),
...data,
})
.run();
const result = await this.metaplex.candyMachinesV2().update({
candyMachine: await this.getCandyMachine(),
...data,
});
return {
signature: result.response.signature,
@@ -216,8 +217,7 @@ export class ClaimConditions {
private async getCandyMachine() {
return this.metaplex
.candyMachines()
.findByAddress({ address: this.dropMintAddress })
.run();
.candyMachinesV2()
.findByAddress({ address: this.dropMintAddress });
}
}
+13 -13
View File
@@ -234,7 +234,7 @@ export class Deployer {
// initialize candy machine with default config
// final claim conditions can be updated later
const candyMachineTx = await this.metaplex
.candyMachines()
.candyMachinesV2()
.builders()
.create({
itemsAvailable: toBigNumber(candyMachineInfo.totalSupply),
@@ -264,23 +264,20 @@ export class Deployer {
const block = await this.metaplex.connection.getLatestBlockhash();
const dropTx = collectionTx
.add(candyMachineTx)
.setFeePayer(this.metaplex.identity())
.setTransactionOptions({
blockhash: block.blockhash,
feePayer: this.metaplex.identity().publicKey,
lastValidBlockHeight: block.lastValidBlockHeight,
});
const regTx = TransactionBuilder.make()
.setFeePayer(this.metaplex.identity());
const regTransaction = TransactionBuilder.make()
.add(...registryInstructions)
.setFeePayer(this.metaplex.identity())
.setTransactionOptions({
.toTransaction({
blockhash: block.blockhash,
feePayer: this.metaplex.identity().publicKey,
lastValidBlockHeight: block.lastValidBlockHeight,
});
const dropSigners = [this.metaplex.identity(), ...dropTx.getSigners()];
const { keypairs } = getSignerHistogram(dropSigners);
const dropTransaction = dropTx.toTransaction();
const dropTransaction = dropTx.toTransaction({
blockhash: block.blockhash,
lastValidBlockHeight: block.lastValidBlockHeight,
});
// partially sign with the PDA keypairs
if (keypairs.length > 0) {
dropTransaction.partialSign(...keypairs);
@@ -288,7 +285,7 @@ export class Deployer {
// make the connected wallet sign both candyMachine + registry transactions
const signedTx = await this.metaplex
.identity()
.signAllTransactions([dropTransaction, regTx.toTransaction()]);
.signAllTransactions([dropTransaction, regTransaction]);
// send the signed transactions *sequentially* the drop creation needs to succeed first before adding to registry
const signatures: string[] = [];
@@ -301,7 +298,10 @@ export class Deployer {
// wait for confirmations in parallel
const confirmations = await Promise.all(
signatures.map((sig) => {
return this.metaplex.rpc().confirmTransaction(sig);
return this.metaplex.rpc().confirmTransaction(sig, {
blockhash: block.blockhash,
lastValidBlockHeight: block.lastValidBlockHeight,
});
}),
);
@@ -1,6 +1,6 @@
import {
QueryAllParams,
DEFAULT_QUERY_ALL_COUNT,
QueryAllParamsSchema,
} from "../../../core/schema/QueryParams";
import { NFT } from "../../../core/schema/nft";
import {
@@ -49,12 +49,9 @@ export class NFTHelper {
}
async getRaw(nftAddress: string) {
return await this.metaplex
.nfts()
.findByMint({
mintAddress: new PublicKey(nftAddress),
})
.run();
return await this.metaplex.nfts().findByMint({
mintAddress: new PublicKey(nftAddress),
});
}
async get(nftAddress: string): Promise<NFT> {
@@ -67,14 +64,11 @@ export class NFTHelper {
nftAddress: string,
quantity: number = 1,
): Promise<TransactionResult> {
const result = await this.metaplex
.nfts()
.send({
mintAddress: new PublicKey(nftAddress),
toOwner: new PublicKey(receiverAddress),
amount: token(quantity, 0),
})
.run();
const result = await this.metaplex.nfts().send({
mintAddress: new PublicKey(nftAddress),
toOwner: new PublicKey(receiverAddress),
amount: token(quantity, 0),
});
return {
signature: result.response.signature,
@@ -121,13 +115,73 @@ export class NFTHelper {
}
}
async supplyOf(nftAddress: string): Promise<number> {
let originalEdition;
const originalEditionAccount = await this.metaplex
.rpc()
.getAccount(findMasterEditionV2Pda(new PublicKey(nftAddress)));
if (originalEditionAccount.exists) {
originalEdition = toNftOriginalEdition(
toOriginalEditionAccount(originalEditionAccount),
);
} else {
return 0;
}
// Add one to supply to account for the master edition
return originalEdition.supply.toNumber() + 1;
}
async totalSupply(collectionAddress: string): Promise<number> {
const metadataAddresses = await this.getAllMetadataAddresses(
collectionAddress,
);
return metadataAddresses.length;
}
async getAll(
collectionAddress: string,
queryParams?: QueryAllParams,
): Promise<NFT[]> {
const { start, count } = QueryAllParamsSchema.parse(queryParams);
const metadataAddresses = await this.getAllMetadataAddresses(
collectionAddress,
);
// Metaplex GmaBuilder has a weird thing where they always start at 1 not 0
// so we workaround it by adding an extra address, and shifting the count to get the actual count we want
const fixedMetadataAddresses = (
start === 0 ? [PublicKey.default] : []
).concat(metadataAddresses);
const metadataInfos = await GmaBuilder.make(
this.metaplex,
fixedMetadataAddresses,
).getBetween(start, start === 0 ? count + 1 : start + count);
// Parse each account into a metadata account
const metadataParsed: Metadata<JsonMetadata<string>>[] = [];
for (const metadataInfo of metadataInfos) {
if (metadataInfo.exists) {
try {
metadataParsed.push(toMetadata(toMetadataAccount(metadataInfo)));
} catch (error) {
// no-op
}
}
}
// Finally, fetch the metadata + mint for each in parallel
const nfts = await Promise.all(
metadataParsed.map((m) => this.toNFTMetadata(m)),
);
return nfts;
}
private async getAllMetadataAddresses(collectionAddress: string) {
const collectionKey = new PublicKey(collectionAddress);
const start = queryParams?.start || 0;
const count = queryParams?.count || DEFAULT_QUERY_ALL_COUNT;
// TODO cache signatures <> transactions mapping in memory so pagination doesn't re-request this everytime
const allSignatures: ConfirmedSignatureInfo[] = [];
@@ -205,52 +259,7 @@ export class NFTHelper {
}
}
// Metaplex GmaBuilder has a weird thing where they always start at 1 not 0
// so we workaround it by adding an extra address, and shifting the count to get the actual count we want
const fixedMetadataAddresses = (
start === 0 ? [PublicKey.default] : []
).concat(metadataAddresses);
const metadataInfos = await GmaBuilder.make(
this.metaplex,
fixedMetadataAddresses,
).getBetween(start, start === 0 ? count + 1 : start + count);
// parse each account into a metadata account
const metadataParsed: Metadata<JsonMetadata<string>>[] = [];
for (const metadataInfo of metadataInfos) {
if (metadataInfo.exists) {
try {
metadataParsed.push(toMetadata(toMetadataAccount(metadataInfo)));
} catch (error) {
// ignore
}
}
}
// finally fetch the metadta + mint for each in parallel
const nfts = await Promise.all(
metadataParsed.map((m) => this.toNFTMetadata(m)),
);
return nfts;
}
async supplyOf(nftAddress: string): Promise<number> {
let originalEdition;
const originalEditionAccount = await this.metaplex
.rpc()
.getAccount(findMasterEditionV2Pda(new PublicKey(nftAddress)));
if (originalEditionAccount.exists) {
originalEdition = toNftOriginalEdition(
toOriginalEditionAccount(originalEditionAccount),
);
} else {
return 0;
}
// Add one to supply to account for the master edition
return originalEdition.supply.toNumber() + 1;
return metadataAddresses;
}
async toNFTMetadata(
+15 -20
View File
@@ -6,12 +6,12 @@ import { WalletAccount } from "../types/common";
import { RegisteredProgram } from "../types/programs";
import { UserWallet } from "./user-wallet";
import {
CandyMachine,
CandyMachineV2,
InstructionWithSigners,
Metadata,
Metaplex,
Pda,
TokenProgram,
TokenGpaBuilder,
} from "@metaplex-foundation/js";
import { TokenStandard } from "@metaplex-foundation/mpl-token-metadata";
import type { BN, Idl } from "@project-serum/anchor";
@@ -38,9 +38,8 @@ export class Registry {
public async getProgramType(address: string) {
try {
const candyMachine = await this.metaplex
.candyMachines()
.findByAddress({ address: new PublicKey(address) })
.run();
.candyMachinesV2()
.findByAddress({ address: new PublicKey(address) });
if (candyMachine) {
return "nft-drop";
}
@@ -49,8 +48,7 @@ export class Registry {
}
const metadata = await this.metaplex
.nfts()
.findByMint({ mintAddress: new PublicKey(address) })
.run();
.findByMint({ mintAddress: new PublicKey(address) });
if (metadata) {
if (metadata.collectionDetails) {
@@ -198,7 +196,10 @@ export class Registry {
return account.exists;
}
private getDropForCollection(candyMachines: CandyMachine[], meta: Metadata) {
private getDropForCollection(
candyMachines: CandyMachineV2[],
meta: Metadata,
) {
return candyMachines.find(
(candyMachine) =>
candyMachine.collectionMintAddress?.toBase58() ===
@@ -211,18 +212,12 @@ export class Registry {
walletAddress: string,
): Promise<WalletAccount[]> {
const mints = await this.getOwnedTokenAddreses(walletAddress);
const metadatas = await this.metaplex
.nfts()
.findAllByMintList({ mints })
.run();
const metadatas = await this.metaplex.nfts().findAllByMintList({ mints });
const candyMachines = await this.metaplex
.candyMachines()
.findAllBy({
type: "authority",
publicKey: new PublicKey(walletAddress),
})
.run();
const candyMachines = await this.metaplex.candyMachinesV2().findAllBy({
type: "authority",
publicKey: new PublicKey(walletAddress),
});
return metadatas
.map((mintMetadata) => {
@@ -260,7 +255,7 @@ export class Registry {
}
private async getOwnedTokenAddreses(walletAddress: string) {
return await TokenProgram.tokenAccounts(this.metaplex)
return await new TokenGpaBuilder(this.metaplex)
.selectMint()
.whereOwner(new PublicKey(walletAddress))
.getDataAsPublicKeys();
@@ -140,6 +140,18 @@ export class NFTCollection {
return this.nft.getAll(this.publicKey.toBase58(), queryParams);
}
/**
* Get the total number of nfts minted on this program
* @returns the total number of NFTs minted on this program
*
* ```jsx
* const totalSupply = await program.totalSupply();
* ```
*/
async totalSupply(): Promise<number> {
return this.nft.totalSupply(this.publicKey.toBase58());
}
/**
* Get the NFT balance of the connected wallet
* @returns the NFT balance
@@ -297,20 +309,17 @@ export class NFTCollection {
const name =
typeof metadata === "string" ? "" : metadata.name?.toString() || "";
const collection = await this.getCollection();
const { nft } = await this.metaplex
.nfts()
.create({
name,
uri,
creators: collection.creators,
sellerFeeBasisPoints: collection.sellerFeeBasisPoints,
collection: this.publicKey,
collectionAuthority: this.metaplex.identity(),
tokenOwner: new PublicKey(to),
// Always sets max supply to unlimited so editions can be minted
maxSupply: null,
})
.run();
const { nft } = await this.metaplex.nfts().create({
name,
uri,
creators: collection.creators,
sellerFeeBasisPoints: collection.sellerFeeBasisPoints,
collection: this.publicKey,
collectionAuthority: this.metaplex.identity(),
tokenOwner: new PublicKey(to),
// Always sets max supply to unlimited so editions can be minted
maxSupply: null,
});
return nft.address.toBase58();
}
@@ -411,13 +420,11 @@ export class NFTCollection {
* ```
*/
async burn(nftAddress: string): Promise<TransactionResult> {
const tx = await this.metaplex
.nfts()
.delete({
mintAddress: new PublicKey(nftAddress),
collection: this.publicKey,
})
.run();
const tx = await this.metaplex.nfts().delete({
mintAddress: new PublicKey(nftAddress),
collection: this.publicKey,
});
return {
signature: tx.response.signature,
};
@@ -458,8 +465,7 @@ export class NFTCollection {
allNfts.map(async (nft) => {
const metaplexNft = await this.metaplex
.nfts()
.findByMint({ mintAddress: new PublicKey(nft.metadata.id) })
.run();
.findByMint({ mintAddress: new PublicKey(nft.metadata.id) });
txs.push(
this.metaplex
@@ -479,16 +485,10 @@ export class NFTCollection {
return await sendMultipartTransaction(txs, this.metaplex);
} else {
const tx = await this.metaplex
.nfts()
.update({
nftOrSft: await this.getCollection(),
creators: enforceCreator(
creators,
this.metaplex.identity().publicKey,
),
})
.run();
const tx = await this.metaplex.nfts().update({
nftOrSft: await this.getCollection(),
creators: enforceCreator(creators, this.metaplex.identity().publicKey),
});
return [
{
@@ -526,8 +526,7 @@ export class NFTCollection {
allNfts.map(async (nft) => {
const metaplexNft = await this.metaplex
.nfts()
.findByMint({ mintAddress: new PublicKey(nft.metadata.id) })
.run();
.findByMint({ mintAddress: new PublicKey(nft.metadata.id) });
txs.push(
this.metaplex.nfts().builders().update({
@@ -541,13 +540,10 @@ export class NFTCollection {
return await sendMultipartTransaction(txs, this.metaplex);
} else {
const tx = await this.metaplex
.nfts()
.update({
nftOrSft: await this.getCollection(),
sellerFeeBasisPoints,
})
.run();
const tx = await this.metaplex.nfts().update({
nftOrSft: await this.getCollection(),
sellerFeeBasisPoints,
});
return [
{
@@ -560,7 +556,6 @@ export class NFTCollection {
private async getCollection() {
return await this.metaplex
.nfts()
.findByMint({ mintAddress: this.publicKey })
.run();
.findByMint({ mintAddress: this.publicKey });
}
}
+77 -46
View File
@@ -1,3 +1,7 @@
import {
QueryAllParams,
QueryAllParamsSchema,
} from "../../core/schema/QueryParams";
import {
CommonNFTInput,
NFT,
@@ -16,7 +20,7 @@ import { CreatorInput, CreatorOutput } from "../types/programs";
import { sendMultipartTransaction } from "../utils/transactions";
import { getNework } from "../utils/urls";
import {
CandyMachineItem,
CandyMachineV2Item,
Metaplex,
toBigNumber,
} from "@metaplex-foundation/js";
@@ -99,8 +103,7 @@ export class NFTDrop {
invariant(info.collectionMintAddress, "Collection mint address not found");
const metadata = await this.metaplex
.nfts()
.findByMint({ mintAddress: info.collectionMintAddress })
.run();
.findByMint({ mintAddress: info.collectionMintAddress });
return (await this.nft.toNFTMetadata(metadata)).metadata;
}
@@ -166,22 +169,37 @@ export class NFTDrop {
* console.log(nfts[0].metadata.name);
* ```
*/
async getAll(): Promise<NFT[]> {
// TODO: Add pagination to get NFT functions
async getAll(queryParams?: QueryAllParams): Promise<NFT[]> {
const parsedQueryParams = QueryAllParamsSchema.parse(queryParams);
const info = await this.getCandyMachine();
const claimed = await this.getAllClaimed();
return await Promise.all(
info.items.map(async (item) => {
// Check if the NFT has been claimed
// TODO: This only checks name/uri which is potentially not unique
const claimedNFT = claimed.find(
// First, get all the claimed NFTs within the query params range
const claimedNfts = await this.getAllClaimed(parsedQueryParams);
const totalClaimed = await this.totalClaimedSupply();
// Then filter out all claimed NFTs from items to leave only unclaimed remaining
const unclaimedItems: CandyMachineV2Item[] = [];
info.items.forEach((item) => {
const isClaimed =
claimedNfts.filter(
(nft) =>
nft.metadata.name === item.name && nft.metadata.uri === item.uri,
);
if (claimedNFT) {
return claimedNFT;
}
// not claimed yet, return a unclaimed NFT with just the metadata
).length > 0;
if (!isClaimed) {
unclaimedItems.push(item);
}
});
// Only fill the remaining count left over after claimed NFTs with unclaimed NFTs
const startIndex = Math.max(0, parsedQueryParams.start - totalClaimed);
const endIndex = Math.max(
0,
startIndex + parsedQueryParams.count - claimedNfts.length,
);
const unclaimedNfts = await Promise.all(
unclaimedItems.slice(startIndex, endIndex).map(async (item) => {
const metadata: NFTMetadata = await this.storage.downloadJSON(item.uri);
return {
metadata: {
@@ -195,6 +213,9 @@ export class NFTDrop {
} as NFT;
}),
);
// Always return claimed NFTs first, and then fill remaining query count with unclaimed NFTs
return [...claimedNfts, ...unclaimedNfts];
}
/**
@@ -208,11 +229,14 @@ export class NFTDrop {
* console.log(nfts[0].name)
* ```
*/
async getAllClaimed(): Promise<NFT[]> {
async getAllClaimed(queryParams?: QueryAllParams): Promise<NFT[]> {
// using getAll from collection here because candy machin findAllMinted doesn't return anything
const candy = await this.getCandyMachine();
invariant(candy.collectionMintAddress, "Collection mint address not found");
return await this.nft.getAll(candy.collectionMintAddress.toBase58());
return await this.nft.getAll(
candy.collectionMintAddress.toBase58(),
queryParams,
);
}
/**
@@ -268,6 +292,21 @@ export class NFTDrop {
return this.nft.ownerOf(nftAddress);
}
/**
* Get the total minted supply of this drop
* @returns the total supply
*
* @example
* ```jsx
* // Get the total number of NFTs that have been minted on this drop
* const supply = await program.totalSupply();
* ```
*/
async totalSupply(): Promise<number> {
const info = await this.getCandyMachine();
return info.itemsLoaded.toNumber();
}
/**
* Get the total unclaimed supply of this drop
* @returns the total supply
@@ -361,20 +400,20 @@ export class NFTDrop {
CommonNFTInput.parse(metadata),
);
const uris = await this.storage.uploadBatch(parsedMetadatas, options);
const items: CandyMachineItem[] = uris.map((uri, i) => ({
const items: CandyMachineV2Item[] = uris.map((uri, i) => ({
name: parsedMetadatas[i].name?.toString() || "",
uri,
}));
// turn items into batches of $LAZY_MINT_BATCH_SIZE
const batches: CandyMachineItem[][] = [];
const batches: CandyMachineV2Item[][] = [];
while (items.length) {
batches.push(items.splice(0, LAZY_MINT_BATCH_SIZE));
}
const builders = batches.map((batch, i) =>
this.metaplex
.candyMachines()
.candyMachinesV2()
.builders()
.insertItems({
candyMachine,
@@ -425,7 +464,7 @@ export class NFTDrop {
const builders = await Promise.all(
[...Array(amount).keys()].map(async () => {
return await this.metaplex
.candyMachines()
.candyMachinesV2()
.builders()
.mint({
candyMachine,
@@ -458,13 +497,10 @@ export class NFTDrop {
const collection = candyMachine.collectionMintAddress
? candyMachine.collectionMintAddress
: undefined;
const tx = await this.metaplex
.nfts()
.delete({
mintAddress: new PublicKey(nftAddress),
collection,
})
.run();
const tx = await this.metaplex.nfts().delete({
mintAddress: new PublicKey(nftAddress),
collection,
});
return {
signature: tx.response.signature,
};
@@ -475,13 +511,11 @@ export class NFTDrop {
* @param creators - the creators to update
*/
async updateCreators(creators: CreatorInput[]) {
const tx = await this.metaplex
.candyMachines()
.update({
candyMachine: await this.getCandyMachine(),
creators: enforceCreator(creators, this.metaplex.identity().publicKey),
})
.run();
const tx = await this.metaplex.candyMachinesV2().update({
candyMachine: await this.getCandyMachine(),
creators: enforceCreator(creators, this.metaplex.identity().publicKey),
});
return {
signature: tx.response.signature,
};
@@ -492,13 +526,11 @@ export class NFTDrop {
* @param sellerFeeBasisPoints - the royalty basis points of the collection
*/
async updateRoyalty(sellerFeeBasisPoints: number) {
const tx = await this.metaplex
.candyMachines()
.update({
candyMachine: await this.getCandyMachine(),
sellerFeeBasisPoints,
})
.run();
const tx = await this.metaplex.candyMachinesV2().update({
candyMachine: await this.getCandyMachine(),
sellerFeeBasisPoints,
});
return {
signature: tx.response.signature,
};
@@ -506,8 +538,7 @@ export class NFTDrop {
private async getCandyMachine() {
return this.metaplex
.candyMachines()
.findByAddress({ address: this.publicKey })
.run();
.candyMachinesV2()
.findByAddress({ address: this.publicKey });
}
}
+11 -18
View File
@@ -131,14 +131,11 @@ export class Token {
): Promise<TransactionResult> {
const amountParsed = AmountSchema.parse(amount);
const info = await this.getMint();
const result = await this.metaplex
.tokens()
.mint({
amount: token(amountParsed, info.decimals),
mintAddress: this.publicKey,
toOwner: new PublicKey(receiverAddress),
})
.run();
const result = await this.metaplex.tokens().mint({
amount: token(amountParsed, info.decimals),
mintAddress: this.publicKey,
toOwner: new PublicKey(receiverAddress),
});
return {
signature: result.response.signature,
};
@@ -165,14 +162,11 @@ export class Token {
amount: Amount,
): Promise<TransactionResult> {
const info = await this.getMint();
const result = await this.metaplex
.tokens()
.send({
mintAddress: this.publicKey,
amount: token(amount, info.decimals),
toOwner: new PublicKey(receiverAddress),
})
.run();
const result = await this.metaplex.tokens().send({
mintAddress: this.publicKey,
amount: token(amount, info.decimals),
toOwner: new PublicKey(receiverAddress),
});
return {
signature: result.response.signature,
};
@@ -228,7 +222,6 @@ export class Token {
private async getMint() {
return await this.metaplex
.tokens()
.findMintByAddress({ address: this.publicKey })
.run(); // TODO abstract types away
.findMintByAddress({ address: this.publicKey });
}
}
@@ -69,6 +69,22 @@ export type TokenMetadataInput = z.input<typeof TokenMetadataInputSchema>;
*/
export type CreatorInput = z.input<typeof CreatorInputSchema>;
/**
* @public
*/
export type UpdateCreatorInput = {
creators: CreatorInput[];
updateAll: boolean;
};
/**
* @public
*/
export type UpdateRoyaltySettingsInput = {
sellerFeeBasisPoints: number;
updateAll: boolean;
};
/**
* @public
*/
@@ -11,17 +11,14 @@ export async function sendMultipartTransaction(
): Promise<TransactionResult[]> {
const block = await metaplex.connection.getLatestBlockhash();
const txns = builders.map((builder) => {
const builderTx = builder
.setTransactionOptions({
blockhash: block.blockhash,
feePayer: metaplex.identity().publicKey,
lastValidBlockHeight: block.lastValidBlockHeight,
})
.setFeePayer(metaplex.identity());
const builderTx = builder.setFeePayer(metaplex.identity());
const dropSigners = [metaplex.identity(), ...builderTx.getSigners()];
const { keypairs } = getSignerHistogram(dropSigners);
const tx = builderTx.toTransaction();
const tx = builderTx.toTransaction({
blockhash: block.blockhash,
lastValidBlockHeight: block.lastValidBlockHeight,
});
if (keypairs.length > 0) {
tx.partialSign(...keypairs);
@@ -44,7 +41,10 @@ export async function sendMultipartTransaction(
// wait for confirmations in parallel
const confirmations = await Promise.all(
signatures.map((sig) => {
return metaplex.rpc().confirmTransaction(sig);
return metaplex.rpc().confirmTransaction(sig, {
blockhash: block.blockhash,
lastValidBlockHeight: block.lastValidBlockHeight,
});
}),
);
+1 -1
View File
@@ -158,7 +158,7 @@ export const mochaHooks = {
if (contractType === "custom") {
continue;
}
let factories = [];
let factories: any[] = [];
switch (contractType) {
case TokenInitializer.contractType:
factories.push(TokenERC20__factory);
+15 -3
View File
@@ -1,6 +1,5 @@
import {
ChainId,
isFeatureEnabled,
ChainId, getAllDetectedFeatureNames, isFeatureEnabled,
resolveContractUriFromAddress,
ThirdwebSDK,
} from "../../src/evm";
@@ -8,7 +7,7 @@ import { implementations, signers } from "./before-setup";
import { AddressZero } from "@ethersproject/constants";
import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers";
import {
DropERC721__factory,
DropERC721__factory, DropERC721_V3__factory,
TokenERC721__factory,
} from "@thirdweb-dev/contracts-js";
import { ThirdwebStorage } from "@thirdweb-dev/storage";
@@ -94,6 +93,19 @@ describe("Publishing", async () => {
);
});
it("should extract all features", async () => {
const tokenFeatures = getAllDetectedFeatureNames(TokenERC721__factory.abi);
expect(
tokenFeatures
).to.contain("ERC721Enumerable");
expect(
getAllDetectedFeatureNames(DropERC721__factory.abi)
).to.contain("ERC721ClaimPhasesV2");
expect(
getAllDetectedFeatureNames(DropERC721_V3__factory.abi)
).to.contain("ERC721ClaimPhasesV1");
});
it("should update bio", async () => {
const address = adminWallet.address;
const publisher = sdk.getPublisher();
+40
View File
@@ -152,4 +152,44 @@ describe("NFTDrop", async () => {
royalty = await drop.getRoyalty();
expect(royalty).to.equal(100);
});
it("Should get all correctly", async () => {
const address = await sdk.deployer.createNftDrop({
name: "NFT Drop #1",
totalSupply: 5,
});
const contract = await sdk.getNFTDrop(address);
await contract.lazyMint([
{ name: "NFT #1", description: "This is the #1 NFT" },
{ name: "NFT #2", description: "This is the #2 NFT" },
{ name: "NFT #3", description: "This is the #3 NFT" },
{ name: "NFT #4", description: "This is the #4 NFT" },
{ name: "NFT #5", description: "This is the #5 NFT" },
]);
let all = await contract.getAll();
expect(all.length).to.equal(5);
expect(all[0].metadata.name).to.equal("NFT #1");
expect(all.filter((nft) => nft.supply > 0).length).to.equal(0);
await contract.claimConditions.set({
price: 0,
maxClaimable: 5,
});
await contract.claim(2);
all = await contract.getAll();
expect(all.length).to.equal(5);
expect(all[0].supply).to.equal(1);
expect(all[1].supply).to.equal(1);
expect(all[2].supply).to.equal(0);
all = await contract.getAll({ start: 2, count: 3 });
expect(all.length).to.equal(3);
expect(all.filter((nft) => nft.supply > 0).length).to.equal(0);
all = await contract.getAll({ start: 0, count: 3 });
expect(all.filter((nft) => nft.supply > 0).length).to.equal(2);
});
});
+1 -1
View File
@@ -43,7 +43,7 @@
"@preconstruct/cli": "^2.2.1",
"@swc-node/register": "^1.5.1",
"@types/chai": "^4.3.3",
"@types/mocha": "^9.1.1",
"@types/mocha": "^10.0.0",
"@typescript-eslint/eslint-plugin": "^5.33.0",
"@typescript-eslint/parser": "^5.33.0",
"chai": "^4.3.6",
+2 -1
View File
@@ -29,5 +29,6 @@
"devDependencies": {
"@playwright/test": "^1.27.1",
"serve": "^14.0.1"
}
},
"repository": "https://github.com/thirdweb-dev/js/tree/main/test/e2e/cra-5"
}
+4 -3
View File
@@ -11,13 +11,14 @@
"@thirdweb-dev/react": "*",
"@thirdweb-dev/sdk": "*",
"ethers": "^5.7.2",
"next": "^12",
"next": "^12.2.0",
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
"devDependencies": {
"@playwright/test": "^1.27.1",
"eslint": "8.25.0",
"eslint": "^8.21.0",
"eslint-config-next": "12.3.1"
}
},
"repository": "https://github.com/thirdweb-dev/js/tree/main/test/e2e/next-12"
}
+4 -3
View File
@@ -15,9 +15,10 @@
"react-dom": "^18.2.0"
},
"devDependencies": {
"@playwright/test": "^1.27.1",
"@vitejs/plugin-react": "^2",
"vite": "^3",
"serve": "^14.0.1",
"@playwright/test": "^1.27.1"
}
"vite": "^3"
},
"repository": "https://github.com/thirdweb-dev/js/tree/main/test/e2e/vite-3"
}
+3474 -3420
View File
File diff suppressed because it is too large Load Diff