Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c2b6d977ed | ||
|
|
7cb8e59be4 | ||
|
|
04a47e8971 | ||
|
|
8a6a97a3e9 | ||
|
|
612bcdd16f | ||
|
|
0ed77d2c9e | ||
|
|
7129aef6e1 | ||
|
|
f50b74819d | ||
|
|
3eba69afd7 | ||
|
|
98c2253e8f | ||
|
|
32d91ef709 | ||
|
|
b79dc18f7a | ||
|
|
4af785c37c | ||
|
|
6f818f393e | ||
|
|
97ed4779a9 | ||
|
|
2d3fca5237 | ||
|
|
7016019f2a | ||
|
|
4e7b293c54 | ||
|
|
c9c0e4ff39 |
+2
-1
@@ -16,4 +16,5 @@ public/dist
|
||||
.yalc/
|
||||
yalc.lock
|
||||
build/
|
||||
playwright-report/
|
||||
playwright-report/
|
||||
.vscode/
|
||||
+3
-3
@@ -15,8 +15,8 @@
|
||||
"scripts": {
|
||||
"test": "turbo run test test:evm test:solana",
|
||||
"e2e": "turbo run e2e",
|
||||
"build": "turbo run build",
|
||||
"build:release": "turbo run build --force",
|
||||
"build": "turbo run build --filter=./packages/*",
|
||||
"build:release": "turbo run build --force --filter=./packages/*",
|
||||
"dev": "turbo run dev --no-cache --parallel --continue",
|
||||
"fix:repo": "manypkg fix",
|
||||
"lint": "turbo run lint",
|
||||
@@ -28,7 +28,7 @@
|
||||
"release": "node ./scripts/pre-release.mjs && changeset publish",
|
||||
"version-packages:nightly": "changeset version --snapshot nightly",
|
||||
"release:nightly": "node ./scripts/pre-release.mjs && changeset publish --tag nightly",
|
||||
"push": "turbo run push"
|
||||
"push": "turbo run push --filter=./packages/*"
|
||||
},
|
||||
"packageManager": "[email protected]",
|
||||
"dependencies": {
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
# @thirdweb-dev/auth
|
||||
|
||||
## 2.0.30
|
||||
|
||||
## 2.0.29
|
||||
|
||||
## 2.0.28
|
||||
|
||||
## 2.0.27
|
||||
|
||||
## 2.0.26
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@thirdweb-dev/auth",
|
||||
"version": "2.0.27",
|
||||
"version": "2.0.30",
|
||||
"exports": {
|
||||
"./next": {
|
||||
"module": "./next/dist/thirdweb-dev-auth-next.esm.js",
|
||||
|
||||
@@ -1,5 +1,26 @@
|
||||
# thirdweb
|
||||
|
||||
## 0.8.16
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`7cb8e59`](https://github.com/thirdweb-dev/js/commit/7cb8e59be48dc923316eb36ab43a1bef7364f6b1), [`0ed77d2`](https://github.com/thirdweb-dev/js/commit/0ed77d2c9e7526444ef660aab82a950865234aa6), [`04a47e8`](https://github.com/thirdweb-dev/js/commit/04a47e8971d28da2532ebd9db824eeb459c17bd4)]:
|
||||
- @thirdweb-dev/sdk@3.6.0
|
||||
|
||||
## 0.8.15
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`3eba69a`](https://github.com/thirdweb-dev/js/commit/3eba69afd78b7aa472a9c00c9d4220bb69ad1d3e), [`4af785c`](https://github.com/thirdweb-dev/js/commit/4af785c37c831ecd7087c1c9eb9095922cac0855), [`6f818f3`](https://github.com/thirdweb-dev/js/commit/6f818f393eb9023b53a3358d62d60ec23a9246bd), [`b79dc18`](https://github.com/thirdweb-dev/js/commit/b79dc18f7ab5155bbf4af02dc1a953546160bad0)]:
|
||||
- @thirdweb-dev/sdk@3.5.2
|
||||
|
||||
## 0.8.14
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`4e7b293`](https://github.com/thirdweb-dev/js/commit/4e7b293c543244de79c150ca8c37d941221fc9a3), [`c9c0e4f`](https://github.com/thirdweb-dev/js/commit/c9c0e4ff39b054af746f3aec75fcbd0a3ef7239d)]:
|
||||
- @thirdweb-dev/sdk@3.5.1
|
||||
|
||||
## 0.8.13
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "thirdweb",
|
||||
"main": "dist/cli/index.js",
|
||||
"version": "0.8.13",
|
||||
"version": "0.8.16",
|
||||
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/cli",
|
||||
"author": "thirdweb eng <[email protected]>",
|
||||
"license": "Apache-2.0",
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
# @thirdweb-dev/contracts-js
|
||||
|
||||
## 1.2.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#376](https://github.com/thirdweb-dev/js/pull/376) [`4af785c`](https://github.com/thirdweb-dev/js/commit/4af785c37c831ecd7087c1c9eb9095922cac0855) Thanks [@adam-maj](https://github.com/adam-maj)! - Update tiered-drop with tokens claimed
|
||||
|
||||
- [#373](https://github.com/thirdweb-dev/js/pull/373) [`6f818f3`](https://github.com/thirdweb-dev/js/commit/6f818f393eb9023b53a3358d62d60ec23a9246bd) Thanks [@adam-maj](https://github.com/adam-maj)! - Update tiered-drop contract version
|
||||
|
||||
## 1.2.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "@thirdweb-dev/contracts-js",
|
||||
"version": "1.2.0",
|
||||
"version": "1.2.1",
|
||||
"main": "dist/thirdweb-dev-contracts-js.cjs.js",
|
||||
"module": "dist/thirdweb-dev-contracts-js.esm.js",
|
||||
"license": "Apache-2.0",
|
||||
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/contracts-js",
|
||||
"dependencies": {
|
||||
"@thirdweb-dev/contracts": "3.2.0-4"
|
||||
"@thirdweb-dev/contracts": "^3.2.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/preset-env": "^7.18.10",
|
||||
|
||||
@@ -1,5 +1,25 @@
|
||||
# @thirdweb-dev/react
|
||||
|
||||
## 3.6.0
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#386](https://github.com/thirdweb-dev/js/pull/386) [`612bcdd`](https://github.com/thirdweb-dev/js/commit/612bcdd16fc242d8b04bc70d609e44b0df47ed3f) Thanks [@jnsdls](https://github.com/jnsdls)! - [Gnosis Connector] - switch to safe.global hostname & add support for bsc and optimism chains
|
||||
|
||||
- [#364](https://github.com/thirdweb-dev/js/pull/364) [`7cb8e59`](https://github.com/thirdweb-dev/js/commit/7cb8e59be48dc923316eb36ab43a1bef7364f6b1) Thanks [@joaquim-verges](https://github.com/joaquim-verges)! - Add experimental `useActiveClaimConditionForWallet()` hook
|
||||
|
||||
## 3.5.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#369](https://github.com/thirdweb-dev/js/pull/369) [`2d3fca5`](https://github.com/thirdweb-dev/js/commit/2d3fca52373046c88392139922e9c9da79f9a2d4) Thanks [@nachoiacovino](https://github.com/nachoiacovino)! - Add useClaimerProofs hook
|
||||
|
||||
- [#378](https://github.com/thirdweb-dev/js/pull/378) [`32d91ef`](https://github.com/thirdweb-dev/js/commit/32d91ef709c8fb92a903e52c65b27538a80ea4eb) Thanks [@mykcryptodev](https://github.com/mykcryptodev)! - round borders for buttons and menus on safari
|
||||
|
||||
- [#377](https://github.com/thirdweb-dev/js/pull/377) [`b79dc18`](https://github.com/thirdweb-dev/js/commit/b79dc18f7ab5155bbf4af02dc1a953546160bad0) Thanks [@adam-maj](https://github.com/adam-maj)! - Add event filters
|
||||
|
||||
## 3.5.1
|
||||
|
||||
## 3.5.0
|
||||
|
||||
## 3.4.5
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@thirdweb-dev/react",
|
||||
"version": "3.5.0",
|
||||
"version": "3.6.0",
|
||||
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/react",
|
||||
"author": "thirdweb eng <[email protected]>",
|
||||
"license": "Apache-2.0",
|
||||
|
||||
@@ -37,8 +37,19 @@ const BaseButton = styled.button<BaseButtonProps>`
|
||||
cursor: not-allowed;
|
||||
}
|
||||
&:focus {
|
||||
outline: 2px solid ${(props) => (props.theme as TwUiTheme).colors.accent};
|
||||
outline-offset: 1px;
|
||||
position: relative;
|
||||
border-radius: 0.5em;
|
||||
outline: 0;
|
||||
}
|
||||
&:focus:after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: -5px;
|
||||
right: -5px;
|
||||
bottom: -5px;
|
||||
left: -5px;
|
||||
border: 2px solid ${(props) => (props.theme as TwUiTheme).colors.accent};
|
||||
border-radius: 11px;
|
||||
}
|
||||
`;
|
||||
|
||||
|
||||
@@ -8,10 +8,23 @@ export const Menu = styled.ul<MenuProps>`
|
||||
margin: 0;
|
||||
background: ${(props) => (props.theme as TwUiTheme).colors.background};
|
||||
color: ${(props) => (props.theme as TwUiTheme).colors.text};
|
||||
outline-color: ${(props) => (props.theme as TwUiTheme).colors.accent};
|
||||
outline-style: solid;
|
||||
outline-offset: 0px;
|
||||
list-style: none;
|
||||
border-radius: 0.5em;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
pointer-events: auto;
|
||||
&:focus {
|
||||
outline: 0;
|
||||
}
|
||||
&:after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
border: 1px solid ${(props) => (props.theme as TwUiTheme).colors.accent};
|
||||
border-radius: 0.5em;
|
||||
pointer-events: none;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
`;
|
||||
|
||||
@@ -9,16 +9,21 @@ import {
|
||||
useContext as useWagmiContext,
|
||||
} from "wagmi";
|
||||
|
||||
// exerpt from https://docs.gnosis-safe.io/backend/available-services
|
||||
const CHAIN_ID_TO_GNOSIS_SERVER_URL = {
|
||||
// mainnet
|
||||
1: "https://safe-transaction.mainnet.gnosis.io",
|
||||
1: "https://safe-transaction-mainnet.safe.global",
|
||||
// avalanche
|
||||
43114: "https://safe-transaction.avalanche.gnosis.io",
|
||||
43114: "https://safe-transaction-avalanche.safe.global",
|
||||
// polygon
|
||||
137: "https://safe-transaction.polygon.gnosis.io",
|
||||
137: "https://safe-transaction-polygon.safe.global",
|
||||
// goerli
|
||||
5: "https://safe-transaction.goerli.gnosis.io",
|
||||
};
|
||||
5: "https://safe-transaction-goerli.safe.global",
|
||||
// bsc
|
||||
56: "https://safe-transaction-bsc.safe.global",
|
||||
// optimism
|
||||
10: "https://safe-transaction-optimism.safe.global",
|
||||
} as const;
|
||||
|
||||
export interface GnosisConnectorArguments {
|
||||
safeAddress: string;
|
||||
@@ -28,6 +33,8 @@ export interface GnosisConnectorArguments {
|
||||
const __IS_SERVER__ = typeof window === "undefined";
|
||||
|
||||
export class GnosisSafeConnector extends Connector {
|
||||
static supportedChains = Object.keys(CHAIN_ID_TO_GNOSIS_SERVER_URL);
|
||||
public supportedChains = GnosisSafeConnector.supportedChains;
|
||||
id = "gnosis";
|
||||
ready = __IS_SERVER__;
|
||||
name = "Gnosis Safe";
|
||||
@@ -60,6 +67,11 @@ export class GnosisSafeConnector extends Connector {
|
||||
};
|
||||
}
|
||||
|
||||
public isChainSupported(chainId: string | number) {
|
||||
const id = normalizeChainId(chainId);
|
||||
return !this.isChainUnsupported(id);
|
||||
}
|
||||
|
||||
private async createSafeSigner() {
|
||||
const signer = await this.previousConnector?.getSigner();
|
||||
const safeAddress = this.config?.safeAddress;
|
||||
|
||||
@@ -2,7 +2,7 @@ import {
|
||||
RequiredParam,
|
||||
requiredParamInvariant,
|
||||
} from "../../../core/query-utils/required-param";
|
||||
import { useSDKChainId } from "../../providers/base";
|
||||
import { useSDK, useSDKChainId } from "../../providers/base";
|
||||
import { getErcs, DropContract, WalletAddress } from "../../types";
|
||||
import {
|
||||
cacheKeys,
|
||||
@@ -14,8 +14,12 @@ import {
|
||||
ClaimCondition,
|
||||
ClaimConditionFetchOptions,
|
||||
ClaimConditionInput,
|
||||
SnapshotEntryWithProof,
|
||||
fetchCurrencyValue,
|
||||
convertToReadableQuantity,
|
||||
fetchCurrencyMetadata,
|
||||
} from "@thirdweb-dev/sdk";
|
||||
import { BigNumberish } from "ethers";
|
||||
import { BigNumberish, utils } from "ethers";
|
||||
import invariant from "tiny-invariant";
|
||||
|
||||
/**
|
||||
@@ -45,7 +49,7 @@ export type SetClaimConditionsParams = {
|
||||
/** **********************/
|
||||
|
||||
/**
|
||||
* Use this to get the active claim conditon for ERC20, ERC721 or ERC1155 based contracts. They need to extend the `claimCondition` extension for this hook to work.
|
||||
* Use this to get the active claim condition for ERC20, ERC721 or ERC1155 based contracts. They need to extend the `claimCondition` extension for this hook to work.
|
||||
*
|
||||
* @example
|
||||
* ```javascript
|
||||
@@ -60,7 +64,7 @@ export type SetClaimConditionsParams = {
|
||||
* const { data: activeClaimCondition, isLoading, error } = useActiveClaimCondition(<YourERC1155ContractInstance>, <tokenId>);
|
||||
* ```
|
||||
*
|
||||
* @param contract - an instance of a contract that extends the ERC721 or ERC1155 spec and implements the `claimConditions` extension.
|
||||
* @param contract - an instance of a contract that extends the ERC721, ERC1155 or ERC20 spec and implements the `claimConditions` extension.
|
||||
* @param tokenId - the id of the token to fetch the claim conditions for (if the contract is an ERC1155 contract)
|
||||
* @returns a response object with the currently active claim condition
|
||||
* @twfeature ERC721ClaimableWithConditions | ERC1155ClaimableWithConditions | ERC20ClaimableWithConditions
|
||||
@@ -106,7 +110,80 @@ export function useActiveClaimCondition(
|
||||
}
|
||||
|
||||
/**
|
||||
* Use this to get all claim conditons for ERC20, ERC721 or ERC1155 based contracts. They need to extend the `claimCondition` extension for this hook to work.
|
||||
* Use this to get the claimer proofs for an adddress for ERC20, ERC721 or ERC1155 based contracts. They need to extend the `claimCondition` extension for this hook to work.
|
||||
*
|
||||
* @example
|
||||
* ```javascript
|
||||
* const { data: claimerProofs, isLoading, error } = useClaimerProofs(<YourERC20ContractInstance>);
|
||||
* ```
|
||||
* @example
|
||||
* ```javascript
|
||||
* const { data: claimerProofs, isLoading, error } = useClaimerProofs(<YourERC721ContractInstance>);
|
||||
* ```
|
||||
* @example
|
||||
* ```javascript
|
||||
* const { data: claimerProofs, isLoading, error } = useClaimerProofs(<YourERC1155ContractInstance>, <tokenId>);
|
||||
* ```
|
||||
*
|
||||
* @param contract - an instance of a contract that extends the ERC721, ERC1155 or ERC20 spec and implements the `claimConditions` extension.
|
||||
* @param claimerAddress - the address of the claimer to fetch the claimer proofs for
|
||||
* @param tokenId - the id of the token to fetch the claimer proofs for (if the contract is an ERC1155 contract)
|
||||
* @param claimConditionId - optional the claim condition id to get the proofs for
|
||||
* @returns a response object with the snapshot for the provided address
|
||||
* @twfeature ERC721ClaimableWithConditions | ERC1155ClaimableWithConditions | ERC20ClaimableWithConditions
|
||||
* @beta
|
||||
*/
|
||||
export function useClaimerProofs(
|
||||
contract: RequiredParam<DropContract>,
|
||||
claimerAddress: string,
|
||||
tokenId?: BigNumberish,
|
||||
claimConditionId?: BigNumberish,
|
||||
) {
|
||||
const contractAddress = contract?.getAddress();
|
||||
const { erc1155, erc721, erc20 } = getErcs(contract);
|
||||
|
||||
return useQueryWithNetwork(
|
||||
cacheKeys.extensions.claimConditions.getClaimerProofs(
|
||||
contractAddress,
|
||||
tokenId,
|
||||
),
|
||||
() => {
|
||||
if (erc1155) {
|
||||
requiredParamInvariant(
|
||||
tokenId,
|
||||
"tokenId is required for ERC1155 claim conditions",
|
||||
);
|
||||
return erc1155.claimConditions.getClaimerProofs(
|
||||
tokenId,
|
||||
claimerAddress,
|
||||
claimConditionId,
|
||||
);
|
||||
}
|
||||
if (erc721) {
|
||||
return erc721.claimConditions.getClaimerProofs(
|
||||
claimerAddress,
|
||||
claimConditionId,
|
||||
);
|
||||
}
|
||||
if (erc20) {
|
||||
return erc20.claimConditions.getClaimerProofs(
|
||||
claimerAddress,
|
||||
claimConditionId,
|
||||
);
|
||||
}
|
||||
throw new Error("Contract must be ERC721, ERC1155 or ERC20");
|
||||
},
|
||||
{
|
||||
// Checks that happen here:
|
||||
// 1. if the contract is based on ERC1155 contract => tokenId cannot be `undefined`
|
||||
// 2. if the contract is NOT based on ERC1155 => we have to have either an ERC721 or ERC20 contract
|
||||
enabled: erc1155 ? tokenId !== undefined : !!erc721 || !!erc20,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Use this to get all claim conditions for ERC20, ERC721 or ERC1155 based contracts. They need to extend the `claimCondition` extension for this hook to work.
|
||||
*
|
||||
* @example
|
||||
* ```javascript
|
||||
@@ -121,7 +198,7 @@ export function useActiveClaimCondition(
|
||||
* const { data: claimConditions, isLoading, error } = useClaimConditions(<YourERC1155ContractInstance>, <tokenId>);
|
||||
* ```
|
||||
*
|
||||
* @param contract - an instance of a contract that extends the ERC721 or ERC1155 spec and implements the `claimConditions` extension.
|
||||
* @param contract - an instance of a contract that extends the ERC721, ERC1155 or ERC20 spec and implements the `claimConditions` extension.
|
||||
* @param tokenId - the id of the token to fetch the claim conditions for (if the contract is an ERC1155 contract)
|
||||
* @returns a response object with the list of claim conditions
|
||||
* @twfeature ERC721ClaimableWithConditions | ERC1155ClaimableWithConditions | ERC20ClaimableWithConditions
|
||||
@@ -242,6 +319,134 @@ export function useClaimIneligibilityReasons(
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Use this to check the claim condition for a given wallet address (including checking for overrides that may exist for that given wallet address).
|
||||
*
|
||||
* @param contract - an instance of a contract that extends the ERC20, ERC721 or ERC1155 spec and implements the `claimConditions` extension.
|
||||
* @param walletAddress - the wallet address to check the active claim condition for
|
||||
* @param tokenId - the id of the token to fetch the claim conditions for (if the contract is an ERC1155 contract)
|
||||
* @returns the active claim conditon for the wallet address or null if there is no active claim condition
|
||||
*
|
||||
* @beta
|
||||
*/
|
||||
export function useActiveClaimConditionForWallet(
|
||||
contract: RequiredParam<DropContract>,
|
||||
walletAddress: RequiredParam<WalletAddress>,
|
||||
tokenId?: BigNumberish,
|
||||
) {
|
||||
const sdk = useSDK();
|
||||
const contractAddress = contract?.getAddress();
|
||||
const { erc1155, erc721, erc20 } = getErcs(contract);
|
||||
return useQueryWithNetwork<ClaimCondition | null>(
|
||||
cacheKeys.extensions.claimConditions.useActiveClaimConditionForWallet(
|
||||
contractAddress,
|
||||
walletAddress || "_NO_WALLET_",
|
||||
tokenId,
|
||||
),
|
||||
async () => {
|
||||
// if we do not have a walletAddress just do the same logic as basic useClaimCondition
|
||||
if (!walletAddress) {
|
||||
if (erc1155) {
|
||||
requiredParamInvariant(
|
||||
tokenId,
|
||||
"tokenId is required for ERC1155 claim conditions",
|
||||
);
|
||||
return erc1155.claimConditions.getActive(tokenId);
|
||||
}
|
||||
if (erc721) {
|
||||
return erc721.claimConditions.getActive();
|
||||
}
|
||||
if (erc20) {
|
||||
return erc20.claimConditions.getActive();
|
||||
}
|
||||
throw new Error("Contract must be ERC721, ERC1155 or ERC20");
|
||||
}
|
||||
invariant(sdk, "sdk is required");
|
||||
let activeGeneralClaimCondition: ClaimCondition | null = null;
|
||||
let claimerProofForWallet: SnapshotEntryWithProof | null = null;
|
||||
|
||||
if (erc1155) {
|
||||
requiredParamInvariant(tokenId, "tokenId is required for ERC1155");
|
||||
const [cc, cp] = await Promise.all([
|
||||
erc1155.claimConditions.getActive(tokenId),
|
||||
erc1155.claimConditions.getClaimerProofs(tokenId, walletAddress),
|
||||
]);
|
||||
activeGeneralClaimCondition = cc;
|
||||
claimerProofForWallet = cp;
|
||||
}
|
||||
if (erc721) {
|
||||
const [cc, cp] = await Promise.all([
|
||||
erc721.claimConditions.getActive(),
|
||||
erc721.claimConditions.getClaimerProofs(walletAddress),
|
||||
]);
|
||||
activeGeneralClaimCondition = cc;
|
||||
claimerProofForWallet = cp;
|
||||
}
|
||||
if (erc20) {
|
||||
const [cc, cp] = await Promise.all([
|
||||
erc20.claimConditions.getActive(),
|
||||
erc20.claimConditions.getClaimerProofs(walletAddress),
|
||||
]);
|
||||
activeGeneralClaimCondition = cc;
|
||||
claimerProofForWallet = cp;
|
||||
}
|
||||
// if there is no active claim condition nothing matters, return null
|
||||
if (!activeGeneralClaimCondition) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// if there is no claimer proof then just fall back to the active general claim condition
|
||||
if (!claimerProofForWallet) {
|
||||
return activeGeneralClaimCondition;
|
||||
}
|
||||
|
||||
const { maxClaimable, currencyAddress, price } = claimerProofForWallet;
|
||||
|
||||
const currencyWithOverride =
|
||||
currencyAddress || activeGeneralClaimCondition.currencyAddress;
|
||||
|
||||
const currencyMetadata = await fetchCurrencyMetadata(
|
||||
sdk.getProvider(),
|
||||
currencyWithOverride,
|
||||
);
|
||||
|
||||
const normalizedPrize = price
|
||||
? utils.parseUnits(price, currencyMetadata.decimals)
|
||||
: null;
|
||||
|
||||
const priceWithOverride =
|
||||
normalizedPrize || activeGeneralClaimCondition.price;
|
||||
|
||||
const maxClaimableWithOverride =
|
||||
// have to transform this the same way that claim conditions do it in SDK
|
||||
convertToReadableQuantity(maxClaimable, currencyMetadata.decimals) ||
|
||||
activeGeneralClaimCondition.maxClaimablePerWallet;
|
||||
|
||||
const currencyValueWithOverride = await fetchCurrencyValue(
|
||||
sdk.getProvider(),
|
||||
currencyWithOverride,
|
||||
priceWithOverride,
|
||||
);
|
||||
return {
|
||||
// inherit the entire claim condition
|
||||
...activeGeneralClaimCondition,
|
||||
// overwrite all keys that could be changed based on overwrites
|
||||
maxClaimablePerWallet: maxClaimableWithOverride,
|
||||
price: priceWithOverride,
|
||||
currency: currencyWithOverride,
|
||||
currencyAddress: currencyWithOverride,
|
||||
currencyMetadata: currencyValueWithOverride,
|
||||
};
|
||||
},
|
||||
{
|
||||
// Checks that happen here:
|
||||
// 1. if the contract is based on ERC1155 contract => tokenId cannot be `undefined`
|
||||
// 2. if the contract is NOT based on ERC1155 => we have to have either an ERC721 or ERC20 contract
|
||||
enabled: erc1155 ? tokenId !== undefined : !!erc721 || !!erc20,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/** **********************/
|
||||
/** WRITE HOOKS **/
|
||||
/** **********************/
|
||||
|
||||
@@ -23,7 +23,7 @@ import {
|
||||
ContractEvent,
|
||||
ContractForPrebuiltContractType,
|
||||
ContractType,
|
||||
EventQueryFilter,
|
||||
EventQueryOptions,
|
||||
PrebuiltContractType,
|
||||
SUPPORTED_CHAIN_ID,
|
||||
ThirdwebSDK,
|
||||
@@ -346,7 +346,7 @@ export function useContractMetadataUpdate(
|
||||
export function useContractEvents(
|
||||
contract: RequiredParam<ValidContractInstance>,
|
||||
eventName?: string,
|
||||
options: { queryFilter?: EventQueryFilter; subscribe?: boolean } = {
|
||||
options: { queryFilter?: EventQueryOptions; subscribe?: boolean } = {
|
||||
subscribe: true,
|
||||
},
|
||||
) {
|
||||
|
||||
@@ -11,7 +11,7 @@ import { useContract } from "../async/contracts";
|
||||
* import { useContract } from '@thirdweb-dev/react'
|
||||
*
|
||||
* export default function Component() {
|
||||
* const { contract } = useNFTCollection("<YOUR-CONTRACT-ADDRESS>", "nft-collection")
|
||||
* const { contract, isLoading, error } = useContract("<YOUR-CONTRACT-ADDRESS>", "nft-collection")
|
||||
*
|
||||
* // Now you can use the nftCollection contract in the rest of the component
|
||||
*
|
||||
|
||||
@@ -287,6 +287,16 @@ export const cacheKeys = {
|
||||
? ["claimConditions", "getAll", { tokenId }, options]
|
||||
: ["claimConditions", "getAll", options],
|
||||
),
|
||||
getClaimerProofs: (
|
||||
contractAddress: RequiredParam<ContractAddress>,
|
||||
tokenId?: BigNumberish,
|
||||
) =>
|
||||
createContractCacheKey(
|
||||
contractAddress,
|
||||
tokenId
|
||||
? ["claimConditions", "getClaimerProofs", { tokenId }]
|
||||
: ["claimConditions", "getClaimerProofs"],
|
||||
),
|
||||
getClaimIneligibilityReasons: (
|
||||
contractAddress: RequiredParam<ContractAddress>,
|
||||
params: { walletAddress?: WalletAddress; quantity: string | number },
|
||||
@@ -303,6 +313,23 @@ export const cacheKeys = {
|
||||
]
|
||||
: ["claimConditions", "getIneligibilityReasons", params],
|
||||
),
|
||||
// combinations of queries cache keys
|
||||
useActiveClaimConditionForWallet: (
|
||||
contractAddress: RequiredParam<ContractAddress>,
|
||||
walletAddress: WalletAddress,
|
||||
tokenId?: BigNumberish,
|
||||
) =>
|
||||
createContractCacheKey(
|
||||
contractAddress,
|
||||
tokenId
|
||||
? [
|
||||
"claimConditions",
|
||||
"useActiveClaimConditionForWallet",
|
||||
{ tokenId, walletAddress },
|
||||
,
|
||||
]
|
||||
: ["claimConditions", "getIneligibilityReasons", { walletAddress }],
|
||||
),
|
||||
},
|
||||
|
||||
// primary sale contracts
|
||||
|
||||
@@ -4,7 +4,8 @@ import {
|
||||
RequiredParam,
|
||||
} from "../../../core/query-utils/required-param";
|
||||
import { useMutation, useQueryClient } from "@tanstack/react-query";
|
||||
import type { Amount, Token } from "@thirdweb-dev/sdk/solana";
|
||||
import type { Amount } from "@thirdweb-dev/sdk";
|
||||
import type { Token } from "@thirdweb-dev/sdk/solana";
|
||||
|
||||
export type TransferTokenMutationParams = {
|
||||
amount: Amount;
|
||||
|
||||
@@ -1,5 +1,40 @@
|
||||
# @thirdweb-dev/sdk
|
||||
|
||||
## 3.6.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- [#364](https://github.com/thirdweb-dev/js/pull/364) [`7cb8e59`](https://github.com/thirdweb-dev/js/commit/7cb8e59be48dc923316eb36ab43a1bef7364f6b1) Thanks [@joaquim-verges](https://github.com/joaquim-verges)! - Enable new Drop contracts
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#382](https://github.com/thirdweb-dev/js/pull/382) [`0ed77d2`](https://github.com/thirdweb-dev/js/commit/0ed77d2c9e7526444ef660aab82a950865234aa6) Thanks [@jnsdls](https://github.com/jnsdls)! - Add `constructorParams` to `ExtraPublishMetadataSchemaInput` schema to support better deploys from releases.
|
||||
|
||||
- [#385](https://github.com/thirdweb-dev/js/pull/385) [`04a47e8`](https://github.com/thirdweb-dev/js/commit/04a47e8971d28da2532ebd9db824eeb459c17bd4) Thanks [@adam-maj](https://github.com/adam-maj)! - Add retroactive royalty and creator setting
|
||||
|
||||
## 3.5.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#380](https://github.com/thirdweb-dev/js/pull/380) [`3eba69a`](https://github.com/thirdweb-dev/js/commit/3eba69afd78b7aa472a9c00c9d4220bb69ad1d3e) Thanks [@joaquim-verges](https://github.com/joaquim-verges)! - Expose sdk.wallet.getChainId()
|
||||
|
||||
- [#376](https://github.com/thirdweb-dev/js/pull/376) [`4af785c`](https://github.com/thirdweb-dev/js/commit/4af785c37c831ecd7087c1c9eb9095922cac0855) Thanks [@adam-maj](https://github.com/adam-maj)! - Update tiered-drop with tokens claimed
|
||||
|
||||
- [#373](https://github.com/thirdweb-dev/js/pull/373) [`6f818f3`](https://github.com/thirdweb-dev/js/commit/6f818f393eb9023b53a3358d62d60ec23a9246bd) Thanks [@adam-maj](https://github.com/adam-maj)! - Update tiered-drop contract version
|
||||
|
||||
- [#377](https://github.com/thirdweb-dev/js/pull/377) [`b79dc18`](https://github.com/thirdweb-dev/js/commit/b79dc18f7ab5155bbf4af02dc1a953546160bad0) Thanks [@adam-maj](https://github.com/adam-maj)! - Add event filters
|
||||
|
||||
- Updated dependencies [[`4af785c`](https://github.com/thirdweb-dev/js/commit/4af785c37c831ecd7087c1c9eb9095922cac0855), [`6f818f3`](https://github.com/thirdweb-dev/js/commit/6f818f393eb9023b53a3358d62d60ec23a9246bd)]:
|
||||
- @thirdweb-dev/contracts-js@1.2.1
|
||||
|
||||
## 3.5.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#368](https://github.com/thirdweb-dev/js/pull/368) [`4e7b293`](https://github.com/thirdweb-dev/js/commit/4e7b293c543244de79c150ca8c37d941221fc9a3) Thanks [@joaquim-verges](https://github.com/joaquim-verges)! - Fix handling of old allowlist proof format
|
||||
|
||||
- [#365](https://github.com/thirdweb-dev/js/pull/365) [`c9c0e4f`](https://github.com/thirdweb-dev/js/commit/c9c0e4ff39b054af746f3aec75fcbd0a3ef7239d) Thanks [@jnsdls](https://github.com/jnsdls)! - [EVM] - now React Native compatible
|
||||
|
||||
## 3.5.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@thirdweb-dev/sdk",
|
||||
"version": "3.5.0",
|
||||
"version": "3.6.0",
|
||||
"description": "The main thirdweb SDK.",
|
||||
"repository": "https://github.com/thirdweb-dev/js/tree/main/packages/sdk",
|
||||
"license": "Apache-2.0",
|
||||
@@ -108,7 +108,6 @@
|
||||
"@thirdweb-dev/storage": "*",
|
||||
"bn.js": "^5.2.1",
|
||||
"bs58": "^5.0.0",
|
||||
"cbor-x": "^1.4.1",
|
||||
"cross-fetch": "^3.1.5",
|
||||
"eventemitter3": "^4.0.7",
|
||||
"fast-deep-equal": "^3.1.3",
|
||||
|
||||
@@ -2,8 +2,14 @@ import BN from "bn.js";
|
||||
import { BigNumber } from "ethers";
|
||||
import { z } from "zod";
|
||||
|
||||
const isBrowser = () => typeof window !== "undefined";
|
||||
const FileOrBufferUnionSchema = isBrowser()
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export const isBrowser = () => typeof window !== "undefined";
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export const FileOrBufferUnionSchema = isBrowser()
|
||||
? (z.instanceof(File) as z.ZodType<InstanceType<typeof File>>)
|
||||
: (z.instanceof(Buffer) as z.ZodTypeAny); // @fixme, this is a hack to make browser happy for now
|
||||
|
||||
@@ -96,6 +102,11 @@ export const AmountSchema = z
|
||||
])
|
||||
.transform((arg) => (typeof arg === "number" ? arg.toString() : arg));
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export type Amount = z.input<typeof AmountSchema>;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
|
||||
@@ -31,8 +31,8 @@ import {
|
||||
SnapshotFormatVersion,
|
||||
} from "./sharded-merkle-tree";
|
||||
import { createSnapshot } from "./snapshots";
|
||||
import { IClaimCondition } from "@thirdweb-dev/contracts-js/dist/declarations/src/Drop";
|
||||
import { IDropClaimCondition_V2 } from "@thirdweb-dev/contracts-js/dist/declarations/src/IDropERC20_V2";
|
||||
import { IClaimCondition } from "@thirdweb-dev/contracts-js/src/IDrop";
|
||||
import { ThirdwebStorage } from "@thirdweb-dev/storage";
|
||||
import {
|
||||
BigNumber,
|
||||
@@ -50,6 +50,7 @@ import {
|
||||
* @returns - `overrides` and `proofs` as an object.
|
||||
*/
|
||||
export async function prepareClaim(
|
||||
addressToClaim: string,
|
||||
quantity: BigNumberish,
|
||||
activeClaimCondition: ClaimCondition,
|
||||
merkleMetadataFetcher: () => Promise<Record<string, string>>,
|
||||
@@ -59,7 +60,6 @@ export async function prepareClaim(
|
||||
checkERC20Allowance: boolean,
|
||||
snapshotFormatVersion: SnapshotFormatVersion,
|
||||
): Promise<ClaimVerification> {
|
||||
const addressToClaim = await contractWrapper.getSignerAddress();
|
||||
let maxClaimable = convertQuantityToBigNumber(
|
||||
activeClaimCondition.maxClaimablePerWallet,
|
||||
tokenDecimals,
|
||||
@@ -92,14 +92,16 @@ export async function prepareClaim(
|
||||
tokenDecimals,
|
||||
);
|
||||
priceInProof =
|
||||
snapshotEntry.price === undefined ||
|
||||
snapshotEntry.price === "unlimited"
|
||||
? ethers.constants.MaxUint256
|
||||
: await normalizePriceValue(
|
||||
contractWrapper.getProvider(),
|
||||
snapshotEntry.price,
|
||||
snapshotEntry.currencyAddress,
|
||||
snapshotEntry.currencyAddress || ethers.constants.AddressZero,
|
||||
);
|
||||
currencyAddressInProof = snapshotEntry.currencyAddress;
|
||||
currencyAddressInProof =
|
||||
snapshotEntry.currencyAddress || ethers.constants.AddressZero;
|
||||
} else {
|
||||
// if no snapshot entry, and it's a v1 format (exclusive allowlist) then address can't claim
|
||||
if (snapshotFormatVersion === SnapshotFormatVersion.V1) {
|
||||
@@ -152,8 +154,10 @@ export async function prepareClaim(
|
||||
overrides,
|
||||
proofs,
|
||||
maxClaimable,
|
||||
price: priceInProof,
|
||||
currencyAddress: currencyAddressInProof,
|
||||
price: pricePerToken,
|
||||
currencyAddress: currencyAddress,
|
||||
priceInProof,
|
||||
currencyAddressInProof,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -282,62 +286,6 @@ export async function updateExistingClaimConditions(
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches the proof for the current signer for a particular wallet.
|
||||
*
|
||||
* @param addressToClaim
|
||||
* @param merkleRoot - The merkle root of the condition to check.
|
||||
* @param tokenDecimals
|
||||
* @param merkleMetadata
|
||||
* @param storage
|
||||
* @param provider
|
||||
* @param snapshotFormatVersion
|
||||
* @returns - The proof for the current signer for the specified condition.
|
||||
*/
|
||||
export async function getClaimerProofs(
|
||||
addressToClaim: string,
|
||||
merkleRoot: string,
|
||||
tokenDecimals: number,
|
||||
merkleMetadata: Record<string, string>,
|
||||
storage: ThirdwebStorage,
|
||||
provider: ethers.providers.Provider,
|
||||
snapshotFormatVersion: SnapshotFormatVersion,
|
||||
): Promise<
|
||||
| {
|
||||
proof: string[];
|
||||
maxClaimable: BigNumber;
|
||||
price: BigNumber;
|
||||
currencyAddress: string;
|
||||
}
|
||||
| undefined
|
||||
> {
|
||||
const claim = await fetchSnapshotEntryForAddress(
|
||||
addressToClaim,
|
||||
merkleRoot,
|
||||
merkleMetadata,
|
||||
provider,
|
||||
storage,
|
||||
snapshotFormatVersion,
|
||||
);
|
||||
if (!claim) {
|
||||
return undefined;
|
||||
}
|
||||
const price =
|
||||
claim.price === "unlimited"
|
||||
? ethers.constants.MaxUint256
|
||||
: await normalizePriceValue(provider, claim.price, claim.currencyAddress);
|
||||
const maxClaimable =
|
||||
claim.maxClaimable === "unlimited"
|
||||
? ethers.constants.MaxUint256
|
||||
: ethers.utils.parseUnits(claim.maxClaimable, tokenDecimals);
|
||||
return {
|
||||
proof: claim.proof,
|
||||
maxClaimable,
|
||||
price,
|
||||
currencyAddress: claim.currencyAddress,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* Decorates claim conditions with merkle roots from snapshots if present
|
||||
@@ -572,6 +520,10 @@ export async function transformResultToClaimCondition(
|
||||
pm.supplyClaimed,
|
||||
tokenDecimals,
|
||||
);
|
||||
let resolvedMetadata;
|
||||
if (pm.metadata) {
|
||||
resolvedMetadata = await storage.downloadJSON(pm.metadata);
|
||||
}
|
||||
return ClaimConditionOutputSchema.parse({
|
||||
startTime: pm.startTimestamp,
|
||||
maxClaimableSupply,
|
||||
@@ -587,7 +539,7 @@ export async function transformResultToClaimCondition(
|
||||
snapshot: shouldDownloadSnapshot
|
||||
? await fetchSnapshot(pm.merkleRoot, merkleMetadata, storage)
|
||||
: undefined,
|
||||
metadata: pm.metadata,
|
||||
metadata: resolvedMetadata,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { AmountSchema } from "../../core/schema/shared";
|
||||
import {
|
||||
getNativeTokenByChainId,
|
||||
NATIVE_TOKEN_ADDRESS,
|
||||
} from "../constants/currency";
|
||||
import { ContractWrapper } from "../core/classes/contract-wrapper";
|
||||
import { AmountSchema } from "../schema/shared";
|
||||
import { Amount, Currency, CurrencyValue, Price } from "../types/currency";
|
||||
import { BaseERC20 } from "../types/eips";
|
||||
import type { IERC20, IERC20Metadata } from "@thirdweb-dev/contracts-js";
|
||||
@@ -33,6 +33,14 @@ export function cleanCurrencyAddress(currencyAddress: string): string {
|
||||
return currencyAddress;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param provider
|
||||
* @param inputPrice
|
||||
* @param currencyAddress
|
||||
* @returns
|
||||
* @internal
|
||||
*/
|
||||
export async function normalizePriceValue(
|
||||
provider: providers.Provider,
|
||||
inputPrice: Price,
|
||||
@@ -42,6 +50,13 @@ export async function normalizePriceValue(
|
||||
return utils.parseUnits(AmountSchema.parse(inputPrice), metadata.decimals);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param provider
|
||||
* @param asset
|
||||
* @returns
|
||||
* @internal
|
||||
*/
|
||||
export async function fetchCurrencyMetadata(
|
||||
provider: providers.Provider,
|
||||
asset: string,
|
||||
@@ -73,6 +88,14 @@ export async function fetchCurrencyMetadata(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param providerOrSigner
|
||||
* @param asset
|
||||
* @param price
|
||||
* @returns
|
||||
* @internal
|
||||
*/
|
||||
export async function fetchCurrencyValue(
|
||||
providerOrSigner: providers.Provider,
|
||||
asset: string,
|
||||
|
||||
@@ -6,7 +6,9 @@ import {
|
||||
} from "../constants/contract-features";
|
||||
import { ContractWrapper } from "../core/classes/contract-wrapper";
|
||||
import { DetectableFeature } from "../core/interfaces/DetectableFeature";
|
||||
import { decode } from "../lib/cbor-decode.js";
|
||||
import {
|
||||
Abi,
|
||||
AbiEvent,
|
||||
AbiFunction,
|
||||
AbiSchema,
|
||||
@@ -23,7 +25,6 @@ import {
|
||||
import { ExtensionNotImplementedError } from "./error";
|
||||
import { ThirdwebStorage } from "@thirdweb-dev/storage";
|
||||
import bs58 from "bs58";
|
||||
import { decode } from "cbor-x";
|
||||
import { BaseContract, BigNumber, ethers } from "ethers";
|
||||
import { z } from "zod";
|
||||
|
||||
@@ -32,26 +33,57 @@ import { z } from "zod";
|
||||
* @param abi
|
||||
* @param feature
|
||||
*/
|
||||
function matchesAbiInterface(
|
||||
abi: z.input<typeof AbiSchema>,
|
||||
feature: Feature,
|
||||
): boolean {
|
||||
function matchesAbiInterface(abi: Abi, feature: Feature): boolean {
|
||||
// returns true if all the functions in `interfaceToMatch` are found in `contract` (removing any duplicates)
|
||||
const contractFn = [
|
||||
...new Set(extractFunctionsFromAbi(abi).map((f) => f.name)),
|
||||
];
|
||||
const interfaceFn = [
|
||||
...new Set(
|
||||
feature.abis
|
||||
.flatMap((i: any) => extractFunctionsFromAbi(i))
|
||||
.map((f: AbiFunction) => f.name),
|
||||
),
|
||||
];
|
||||
return hasMatchingAbi(abi, feature.abis);
|
||||
}
|
||||
|
||||
return (
|
||||
contractFn.filter((k) => interfaceFn.includes(k)).length ===
|
||||
interfaceFn.length
|
||||
/**
|
||||
* @internal
|
||||
* @param contractWrapper
|
||||
* @param abi
|
||||
* @returns
|
||||
*/
|
||||
export function matchesPrebuiltAbi<T extends BaseContract>(
|
||||
contractWrapper: ContractWrapper<BaseContract>,
|
||||
abi: Abi,
|
||||
): contractWrapper is ContractWrapper<T> {
|
||||
return hasMatchingAbi(contractWrapper.abi as Abi, [abi]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* @param contractAbi
|
||||
* @param featureAbis
|
||||
* @returns
|
||||
*/
|
||||
export function hasMatchingAbi(contractAbi: Abi, featureAbis: readonly Abi[]) {
|
||||
const contractFn = extractFunctionsFromAbi(contractAbi);
|
||||
const interfaceFn = featureAbis.flatMap((i: any) =>
|
||||
extractFunctionsFromAbi(i),
|
||||
);
|
||||
// match every function and their arguments
|
||||
const intersection = contractFn.filter((fn) => {
|
||||
const match = interfaceFn.find(
|
||||
(iFn) =>
|
||||
iFn.name === fn.name &&
|
||||
iFn.inputs.length === fn.inputs.length &&
|
||||
iFn.inputs.every((i, index) => {
|
||||
if (i.type === "tuple" || i.type === "tuple[]") {
|
||||
// check that all properties in the tuple are the same type
|
||||
return (
|
||||
i.type === fn.inputs[index].type &&
|
||||
i.components?.every((c, cIndex) => {
|
||||
return c.type === fn.inputs[index].components?.[cIndex]?.type;
|
||||
})
|
||||
);
|
||||
}
|
||||
return i.type === fn.inputs[index].type;
|
||||
}),
|
||||
);
|
||||
return match !== undefined;
|
||||
});
|
||||
return intersection.length === interfaceFn.length;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -145,7 +177,7 @@ export function extractFunctionParamsFromAbi(
|
||||
* @param metadata
|
||||
*/
|
||||
export function extractFunctionsFromAbi(
|
||||
abi: z.input<typeof AbiSchema>,
|
||||
abi: Abi,
|
||||
metadata?: Record<string, any>,
|
||||
): AbiFunction[] {
|
||||
const functions = (abi || []).filter((el) => el.type === "function");
|
||||
@@ -178,7 +210,7 @@ export function extractFunctionsFromAbi(
|
||||
* @param metadata
|
||||
*/
|
||||
export function extractEventsFromAbi(
|
||||
abi: z.input<typeof AbiSchema>,
|
||||
abi: Abi,
|
||||
metadata?: Record<string, any>,
|
||||
): AbiEvent[] {
|
||||
const events = (abi || []).filter((el) => el.type === "event");
|
||||
@@ -405,7 +437,9 @@ export async function fetchSourceFilesFromMetadata(
|
||||
Object.entries(publishedMetadata.metadata.sources).map(
|
||||
async ([path, info]) => {
|
||||
const urls = (info as any).urls as string[];
|
||||
const ipfsLink = urls.find((url) => url.includes("ipfs"));
|
||||
const ipfsLink = urls
|
||||
? urls.find((url) => url.includes("ipfs"))
|
||||
: undefined;
|
||||
if (ipfsLink) {
|
||||
const ipfsHash = ipfsLink.split("ipfs/")[1];
|
||||
// 5 sec timeout for sources that haven't been uploaded to ipfs
|
||||
@@ -423,7 +457,9 @@ export async function fetchSourceFilesFromMetadata(
|
||||
} else {
|
||||
return {
|
||||
filename: path,
|
||||
source: "Could not find source for this contract",
|
||||
source:
|
||||
(info as any).content ||
|
||||
"Could not find source for this contract",
|
||||
};
|
||||
}
|
||||
},
|
||||
|
||||
@@ -3,3 +3,10 @@ export * from "./snapshots";
|
||||
export * from "./role";
|
||||
export * from "./feature-detection";
|
||||
export * from "./version-checker";
|
||||
// export helpful util
|
||||
export {
|
||||
fetchCurrencyValue,
|
||||
fetchCurrencyMetadata,
|
||||
normalizePriceValue,
|
||||
} from "./currency";
|
||||
export { convertToReadableQuantity } from "./claim-conditions";
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { MAX_BPS } from "../../core/schema/shared";
|
||||
import {
|
||||
InterfaceId_IERC1155,
|
||||
InterfaceId_IERC721,
|
||||
} from "../constants/contract";
|
||||
import { SignerOrProvider } from "../core";
|
||||
import { ContractWrapper } from "../core/classes/contract-wrapper";
|
||||
import { MAX_BPS } from "../schema/shared";
|
||||
import {
|
||||
NewAuctionListing,
|
||||
NewDirectListing,
|
||||
|
||||
@@ -101,8 +101,11 @@ export class ShardedMerkleTree {
|
||||
[
|
||||
entry.address,
|
||||
convertQuantityToBigNumber(entry.maxClaimable, tokenDecimals),
|
||||
convertQuantityToBigNumber(entry.price, currencyDecimals),
|
||||
entry.currencyAddress,
|
||||
convertQuantityToBigNumber(
|
||||
entry.price || "unlimited",
|
||||
currencyDecimals,
|
||||
),
|
||||
entry.currencyAddress || ethers.constants.AddressZero,
|
||||
],
|
||||
);
|
||||
}
|
||||
@@ -111,11 +114,14 @@ export class ShardedMerkleTree {
|
||||
static async fetchAndCacheDecimals(
|
||||
cache: Record<string, number>,
|
||||
provider: ethers.providers.Provider,
|
||||
currencyAddress: string,
|
||||
currencyAddress?: string,
|
||||
): Promise<number> {
|
||||
if (!currencyAddress) {
|
||||
return 18;
|
||||
}
|
||||
// cache decimals for each currency to avoid refetching for every address
|
||||
let currencyDecimals = cache[currencyAddress];
|
||||
if (!currencyDecimals) {
|
||||
if (currencyDecimals === undefined) {
|
||||
const currencyMetadata = await fetchCurrencyMetadata(
|
||||
provider,
|
||||
currencyAddress,
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { PrebuiltContractType } from "../core/types";
|
||||
import { ChainId, SUPPORTED_CHAIN_ID } from "./chains";
|
||||
import { constants } from "ethers";
|
||||
|
||||
@@ -142,6 +143,118 @@ export const CONTRACT_ADDRESSES: Record<
|
||||
},
|
||||
};
|
||||
|
||||
type DropContract = Extract<
|
||||
PrebuiltContractType,
|
||||
"nft-drop" | "token-drop" | "edition-drop" | "signature-drop"
|
||||
>;
|
||||
export const APPROVED_IMPLEMENTATIONS: Record<
|
||||
SUPPORTED_CHAIN_ID,
|
||||
Record<DropContract, string>
|
||||
> = {
|
||||
[ChainId.Mainnet]: {
|
||||
"nft-drop": "0x60fF9952e0084A6DEac44203838cDC91ABeC8736",
|
||||
"edition-drop": "0x74af262d0671F378F97a1EDC3d0970Dbe8A1C550",
|
||||
"token-drop": "0xE1eE43D23f247b6A9aF81fcE2766E76709482728",
|
||||
"signature-drop": "0x6fD690EB509BdE4C50028C5D9C0dE3750C2Fad6A",
|
||||
},
|
||||
[ChainId.Polygon]: {
|
||||
"nft-drop": "0xB96508050Ba0925256184103560EBADA912Fcc69",
|
||||
"edition-drop": "0x74af262d0671F378F97a1EDC3d0970Dbe8A1C550",
|
||||
"token-drop": "0x5A8eA4Adad8289746D073947BA06D69A62499aaf",
|
||||
"signature-drop": "0xBE2fDc35410E268e41Bec62DBb01AEb43245c7d5",
|
||||
},
|
||||
[ChainId.Fantom]: {
|
||||
"nft-drop": "0x2A396b2D90BAcEF19cDa973586B2633d22710fC2",
|
||||
"edition-drop": "0x06395FCF9AC6ED827f9dD6e776809cEF1Be0d21B",
|
||||
"token-drop": "0x0148b28a38efaaC31b6aa0a6D9FEb70FE7C91FFa",
|
||||
"signature-drop": "0xe135Ef65C2B2213C3fD56d0Bd6500A2cA147aC10",
|
||||
},
|
||||
[ChainId.Avalanche]: {
|
||||
"nft-drop": "0x9cF91118C8ee2913F0588e0F10e36B3d63F68bF6",
|
||||
"edition-drop": "0x135fC9D26E5eC51260ece1DF4ED424E2f55c7766",
|
||||
"token-drop": "0xca0B071899E575BA86495D46c5066971b6f3A901",
|
||||
"signature-drop": "0x1d47526C3292B0130ef0afD5F02c1DA052A017B3",
|
||||
},
|
||||
[ChainId.Optimism]: {
|
||||
"nft-drop": "0xFBd7D24d80ee005671E731a7287DEB6073264dD1",
|
||||
"edition-drop": "0xe135Ef65C2B2213C3fD56d0Bd6500A2cA147aC10",
|
||||
"token-drop": "0x902Dd246e66d8C3CE652375a723F2a52b43b9AAE",
|
||||
"signature-drop": "0x8a4cd3549e548bbEEb38C16E041FFf040a5acabD",
|
||||
},
|
||||
[ChainId.Arbitrum]: {
|
||||
"nft-drop": "0xC4903c1Ff5367b9ac2c349B63DC2409421AaEE2a",
|
||||
"edition-drop": "0xCcddcec1831646Beff2753249f1B9C580327E89F",
|
||||
"token-drop": "0x1b5947e1a2d5a29D0df20931DeAB0B87818209B9",
|
||||
"signature-drop": "0x2dF9851af45dd41C8584ac55D983C604da985Bc7",
|
||||
},
|
||||
[ChainId.BinanceSmartChainMainnet]: {
|
||||
"nft-drop": "0x902Dd246e66d8C3CE652375a723F2a52b43b9AAE",
|
||||
"edition-drop": "0x2A396b2D90BAcEF19cDa973586B2633d22710fC2",
|
||||
"token-drop": "0xe135Ef65C2B2213C3fD56d0Bd6500A2cA147aC10",
|
||||
"signature-drop": "0xFBd7D24d80ee005671E731a7287DEB6073264dD1",
|
||||
},
|
||||
[ChainId.Goerli]: {
|
||||
"nft-drop": "0xD11c97DD5F5546B5bBd630D7D1d7327481B0b92C",
|
||||
"edition-drop": "0x5A8eA4Adad8289746D073947BA06D69A62499aaf",
|
||||
"token-drop": "0x5680933221B752EB443654a014f88B101F868d50",
|
||||
"signature-drop": "0x1b5947e1a2d5a29D0df20931DeAB0B87818209B9",
|
||||
},
|
||||
[ChainId.Mumbai]: {
|
||||
"nft-drop": "0xC4903c1Ff5367b9ac2c349B63DC2409421AaEE2a",
|
||||
"edition-drop": "0xCcddcec1831646Beff2753249f1B9C580327E89F",
|
||||
"token-drop": "0x1b5947e1a2d5a29D0df20931DeAB0B87818209B9",
|
||||
"signature-drop": "0x2dF9851af45dd41C8584ac55D983C604da985Bc7",
|
||||
},
|
||||
[ChainId.FantomTestnet]: {
|
||||
"nft-drop": "0x8a4cd3549e548bbEEb38C16E041FFf040a5acabD",
|
||||
"edition-drop": "0x902Dd246e66d8C3CE652375a723F2a52b43b9AAE",
|
||||
"token-drop": "0xFBd7D24d80ee005671E731a7287DEB6073264dD1",
|
||||
"signature-drop": "0x5A8eA4Adad8289746D073947BA06D69A62499aaf",
|
||||
},
|
||||
[ChainId.AvalancheFujiTestnet]: {
|
||||
"nft-drop": "0xD11c97DD5F5546B5bBd630D7D1d7327481B0b92C",
|
||||
"edition-drop": "0xE1eE43D23f247b6A9aF81fcE2766E76709482728",
|
||||
"token-drop": "0x6fD690EB509BdE4C50028C5D9C0dE3750C2Fad6A",
|
||||
"signature-drop": "0xCcddcec1831646Beff2753249f1B9C580327E89F",
|
||||
},
|
||||
[ChainId.OptimismGoerli]: {
|
||||
"nft-drop": "0xCcddcec1831646Beff2753249f1B9C580327E89F",
|
||||
"edition-drop": "0x6fD690EB509BdE4C50028C5D9C0dE3750C2Fad6A",
|
||||
"token-drop": "0xD11c97DD5F5546B5bBd630D7D1d7327481B0b92C",
|
||||
"signature-drop": "0x1b5947e1a2d5a29D0df20931DeAB0B87818209B9",
|
||||
},
|
||||
[ChainId.ArbitrumGoerli]: {
|
||||
"nft-drop": "0x9CfE807a5b124b962064Fa8F7FD823Cc701255b6",
|
||||
"edition-drop": "0x9cF91118C8ee2913F0588e0F10e36B3d63F68bF6",
|
||||
"token-drop": "0x1d47526C3292B0130ef0afD5F02c1DA052A017B3",
|
||||
"signature-drop": "0xE1eE43D23f247b6A9aF81fcE2766E76709482728",
|
||||
},
|
||||
[ChainId.BinanceSmartChainTestnet]: {
|
||||
"nft-drop": "",
|
||||
"edition-drop": "",
|
||||
"token-drop": "",
|
||||
"signature-drop": "", // TODO
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* @param chainId
|
||||
* @param contractType
|
||||
*/
|
||||
export function getApprovedImplementation(
|
||||
chainId: SUPPORTED_CHAIN_ID, // TODO use SupportedChainId once we deploy to all chains
|
||||
contractType: PrebuiltContractType,
|
||||
): string | null {
|
||||
if (chainId in APPROVED_IMPLEMENTATIONS) {
|
||||
const approvedImpls = APPROVED_IMPLEMENTATIONS[chainId];
|
||||
if (contractType in approvedImpls) {
|
||||
return approvedImpls[contractType as keyof typeof approvedImpls];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
|
||||
@@ -6,7 +6,6 @@ export enum ChainId {
|
||||
Goerli = 5,
|
||||
Polygon = 137,
|
||||
Mumbai = 80001,
|
||||
Harmony = 1666600000,
|
||||
Localhost = 1337,
|
||||
Hardhat = 31337,
|
||||
Fantom = 250,
|
||||
|
||||
@@ -3,35 +3,45 @@ import {
|
||||
FEATURE_TOKEN_BATCH_MINTABLE,
|
||||
FEATURE_TOKEN_BURNABLE,
|
||||
FEATURE_TOKEN_MINTABLE,
|
||||
FEATURE_TOKEN_CLAIMABLE_WITH_CONDITIONS,
|
||||
FEATURE_TOKEN_SIGNATURE_MINTABLE,
|
||||
FEATURE_TOKEN_CLAIM_CONDITIONS_V1,
|
||||
FEATURE_TOKEN_CLAIM_CONDITIONS_V2,
|
||||
FEATURE_TOKEN_CLAIM_PHASES_V2,
|
||||
FEATURE_TOKEN_CLAIM_PHASES_V1,
|
||||
} from "./erc20-features";
|
||||
import {
|
||||
FEATURE_NFT,
|
||||
FEATURE_NFT_BATCH_MINTABLE,
|
||||
FEATURE_NFT_BURNABLE,
|
||||
FEATURE_NFT_CLAIMABLE,
|
||||
FEATURE_NFT_CLAIM_CUSTOM,
|
||||
FEATURE_NFT_LAZY_MINTABLE,
|
||||
FEATURE_NFT_ENUMERABLE,
|
||||
FEATURE_NFT_MINTABLE,
|
||||
FEATURE_NFT_REVEALABLE,
|
||||
FEATURE_NFT_SIGNATURE_MINTABLE,
|
||||
FEATURE_NFT_SUPPLY,
|
||||
FEATURE_NFT_CLAIMABLE_WITH_CONDITIONS_V1,
|
||||
FEATURE_NFT_CLAIMABLE_WITH_CONDITIONS_V2,
|
||||
FEATURE_NFT_CLAIM_CONDITIONS_V1,
|
||||
FEATURE_NFT_CLAIM_CONDITIONS_V2,
|
||||
FEATURE_NFT_CLAIM_PHASES_V2,
|
||||
FEATURE_NFT_TIERED_DROP,
|
||||
FEATURE_NFT_CLAIM_PHASES_V1,
|
||||
FEATURE_NFT_SIGNATURE_MINTABLE_V1,
|
||||
FEATURE_NFT_SIGNATURE_MINTABLE_V2,
|
||||
} from "./erc721-features";
|
||||
import {
|
||||
FEATURE_EDITION,
|
||||
FEATURE_EDITION_BATCH_MINTABLE,
|
||||
FEATURE_EDITION_BURNABLE,
|
||||
FEATURE_EDITION_CLAIMABLE,
|
||||
FEATURE_EDITION_CLAIMABLE_WITH_CONDITIONS,
|
||||
FEATURE_EDITION_CLAIM_CUSTOM,
|
||||
FEATURE_EDITION_CLAIM_CONDITIONS_V1,
|
||||
FEATURE_EDITION_CLAIM_CONDITIONS_V2,
|
||||
FEATURE_EDITION_CLAIM_PHASES_V2,
|
||||
FEATURE_EDITION_ENUMERABLE,
|
||||
FEATURE_EDITION_LAZY_MINTABLE,
|
||||
FEATURE_EDITION_LAZY_MINTABLE_V1,
|
||||
FEATURE_EDITION_LAZY_MINTABLE_V2,
|
||||
FEATURE_EDITION_MINTABLE,
|
||||
FEATURE_EDITION_REVEALABLE,
|
||||
FEATURE_EDITION_SIGNATURE_MINTABLE,
|
||||
FEATURE_EDITION_CLAIM_PHASES_V1,
|
||||
} from "./erc1155-features";
|
||||
import {
|
||||
FEATURE_METADATA,
|
||||
@@ -52,7 +62,10 @@ export type Feature =
|
||||
| typeof FEATURE_TOKEN_MINTABLE
|
||||
| typeof FEATURE_TOKEN_BATCH_MINTABLE
|
||||
| typeof FEATURE_TOKEN_BURNABLE
|
||||
| typeof FEATURE_TOKEN_CLAIMABLE_WITH_CONDITIONS
|
||||
| typeof FEATURE_TOKEN_CLAIM_CONDITIONS_V1
|
||||
| typeof FEATURE_TOKEN_CLAIM_CONDITIONS_V2
|
||||
| typeof FEATURE_TOKEN_CLAIM_PHASES_V1
|
||||
| typeof FEATURE_TOKEN_CLAIM_PHASES_V2
|
||||
| typeof FEATURE_TOKEN_SIGNATURE_MINTABLE
|
||||
| typeof FEATURE_NFT
|
||||
| typeof FEATURE_NFT_SUPPLY
|
||||
@@ -60,19 +73,26 @@ export type Feature =
|
||||
| typeof FEATURE_NFT_MINTABLE
|
||||
| typeof FEATURE_NFT_BATCH_MINTABLE
|
||||
| typeof FEATURE_NFT_LAZY_MINTABLE
|
||||
| typeof FEATURE_NFT_CLAIMABLE
|
||||
| typeof FEATURE_NFT_CLAIMABLE_WITH_CONDITIONS_V1
|
||||
| typeof FEATURE_NFT_CLAIMABLE_WITH_CONDITIONS_V2
|
||||
| typeof FEATURE_NFT_CLAIM_CUSTOM
|
||||
| typeof FEATURE_NFT_CLAIM_CONDITIONS_V1
|
||||
| typeof FEATURE_NFT_CLAIM_CONDITIONS_V2
|
||||
| typeof FEATURE_NFT_CLAIM_PHASES_V1
|
||||
| typeof FEATURE_NFT_CLAIM_PHASES_V2
|
||||
| typeof FEATURE_NFT_REVEALABLE
|
||||
| typeof FEATURE_NFT_SIGNATURE_MINTABLE
|
||||
| typeof FEATURE_NFT_SIGNATURE_MINTABLE_V1
|
||||
| typeof FEATURE_NFT_SIGNATURE_MINTABLE_V2
|
||||
| typeof FEATURE_NFT_BURNABLE
|
||||
| typeof FEATURE_NFT_TIERED_DROP
|
||||
| typeof FEATURE_EDITION
|
||||
| typeof FEATURE_EDITION_ENUMERABLE
|
||||
| typeof FEATURE_EDITION_MINTABLE
|
||||
| typeof FEATURE_EDITION_CLAIMABLE
|
||||
| typeof FEATURE_EDITION_CLAIMABLE_WITH_CONDITIONS
|
||||
| typeof FEATURE_EDITION_LAZY_MINTABLE
|
||||
| typeof FEATURE_EDITION_CLAIM_CUSTOM
|
||||
| typeof FEATURE_EDITION_CLAIM_CONDITIONS_V1
|
||||
| typeof FEATURE_EDITION_CLAIM_CONDITIONS_V2
|
||||
| typeof FEATURE_EDITION_CLAIM_PHASES_V1
|
||||
| typeof FEATURE_EDITION_CLAIM_PHASES_V2
|
||||
| typeof FEATURE_EDITION_LAZY_MINTABLE_V1
|
||||
| typeof FEATURE_EDITION_LAZY_MINTABLE_V2
|
||||
| typeof FEATURE_EDITION_REVEALABLE
|
||||
| typeof FEATURE_EDITION_BATCH_MINTABLE
|
||||
| typeof FEATURE_EDITION_BURNABLE
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
import DelayedRevealAbi from "@thirdweb-dev/contracts-js/dist/abis/DelayedReveal.json";
|
||||
import DropERC1155_V2Abi from "@thirdweb-dev/contracts-js/dist/abis/DropERC1155_V2.json";
|
||||
import IBurnableERC1155Abi from "@thirdweb-dev/contracts-js/dist/abis/IBurnableERC1155.json";
|
||||
import IClaimableERC1155 from "@thirdweb-dev/contracts-js/dist/abis/IClaimableERC1155.json";
|
||||
import DelayedRevealAbi from "@thirdweb-dev/contracts-js/dist/abis/IDelayedReveal.json";
|
||||
import IDropMultiPhase1155 from "@thirdweb-dev/contracts-js/dist/abis/IDrop1155.json";
|
||||
import IDropSinglePhase1155 from "@thirdweb-dev/contracts-js/dist/abis/IDropSinglePhase1155.json";
|
||||
import IDropSinglePhase1155_V1 from "@thirdweb-dev/contracts-js/dist/abis/IDropSinglePhase1155_V1.json";
|
||||
import Erc1155Abi from "@thirdweb-dev/contracts-js/dist/abis/IERC1155.json";
|
||||
import Erc1155EnumerableAbi from "@thirdweb-dev/contracts-js/dist/abis/IERC1155Enumerable.json";
|
||||
import ILazyMintAbi from "@thirdweb-dev/contracts-js/dist/abis/ILazyMint.json";
|
||||
@@ -20,8 +23,19 @@ export const FEATURE_EDITION_BURNABLE = {
|
||||
features: {},
|
||||
} as const;
|
||||
|
||||
export const FEATURE_EDITION_CLAIMABLE_WITH_CONDITIONS = {
|
||||
name: "ERC1155ClaimableWithConditions",
|
||||
export const FEATURE_EDITION_CLAIM_CONDITIONS_V1 = {
|
||||
name: "ERC1155ClaimConditionsV1",
|
||||
namespace: "edition.drop.claim",
|
||||
docLinks: {
|
||||
sdk: "sdk.erc1155claimable",
|
||||
contracts: "DropSinglePhase1155",
|
||||
},
|
||||
abis: [Erc1155Abi, ILazyMintAbi, IDropSinglePhase1155_V1],
|
||||
features: {},
|
||||
} as const;
|
||||
|
||||
export const FEATURE_EDITION_CLAIM_CONDITIONS_V2 = {
|
||||
name: "ERC1155ClaimConditionsV2",
|
||||
namespace: "edition.drop.claim",
|
||||
docLinks: {
|
||||
sdk: "sdk.erc1155claimable",
|
||||
@@ -31,8 +45,30 @@ export const FEATURE_EDITION_CLAIMABLE_WITH_CONDITIONS = {
|
||||
features: {},
|
||||
} as const;
|
||||
|
||||
export const FEATURE_EDITION_CLAIMABLE = {
|
||||
name: "ERC1155Claimable",
|
||||
export const FEATURE_EDITION_CLAIM_PHASES_V2 = {
|
||||
name: "ERC1155ClaimPhasesV2",
|
||||
namespace: "edition.drop.claim",
|
||||
docLinks: {
|
||||
sdk: "sdk.erc1155claimable",
|
||||
contracts: "Drop1155",
|
||||
},
|
||||
abis: [Erc1155Abi, ILazyMintAbi, IDropMultiPhase1155],
|
||||
features: {},
|
||||
} as const;
|
||||
|
||||
export const FEATURE_EDITION_CLAIM_PHASES_V1 = {
|
||||
name: "ERC1155ClaimPhasesV1",
|
||||
namespace: "edition.drop.claim",
|
||||
docLinks: {
|
||||
sdk: "sdk.erc1155claimable",
|
||||
contracts: "Drop1155",
|
||||
},
|
||||
abis: [DropERC1155_V2Abi],
|
||||
features: {},
|
||||
} as const;
|
||||
|
||||
export const FEATURE_EDITION_CLAIM_CUSTOM = {
|
||||
name: "ERC1155ClaimCustom",
|
||||
namespace: "edition.drop.claim",
|
||||
docLinks: {
|
||||
sdk: "sdk.erc1155claimable",
|
||||
@@ -42,21 +78,6 @@ export const FEATURE_EDITION_CLAIMABLE = {
|
||||
features: {},
|
||||
} as const;
|
||||
|
||||
export const FEATURE_EDITION_LAZY_MINTABLE = {
|
||||
name: "ERC1155LazyMintable",
|
||||
namespace: "edition.drop",
|
||||
docLinks: {
|
||||
sdk: "sdk.erc1155droppable",
|
||||
contracts: "LazyMint",
|
||||
},
|
||||
abis: [Erc1155Abi, ILazyMintAbi],
|
||||
features: {
|
||||
[FEATURE_EDITION_CLAIMABLE.name]: FEATURE_EDITION_CLAIMABLE,
|
||||
[FEATURE_EDITION_CLAIMABLE_WITH_CONDITIONS.name]:
|
||||
FEATURE_EDITION_CLAIMABLE_WITH_CONDITIONS,
|
||||
},
|
||||
} as const;
|
||||
|
||||
export const FEATURE_EDITION_REVEALABLE = {
|
||||
name: "ERC1155Revealable",
|
||||
namespace: "edition.drop.revealer",
|
||||
@@ -68,6 +89,38 @@ export const FEATURE_EDITION_REVEALABLE = {
|
||||
features: {},
|
||||
} as const;
|
||||
|
||||
export const FEATURE_EDITION_LAZY_MINTABLE_V2 = {
|
||||
name: "ERC1155LazyMintableV2",
|
||||
namespace: "edition.drop",
|
||||
docLinks: {
|
||||
sdk: "sdk.erc1155droppable",
|
||||
contracts: "LazyMint",
|
||||
},
|
||||
abis: [Erc1155Abi, ILazyMintAbi],
|
||||
features: {
|
||||
[FEATURE_EDITION_REVEALABLE.name]: FEATURE_EDITION_REVEALABLE,
|
||||
[FEATURE_EDITION_CLAIM_CUSTOM.name]: FEATURE_EDITION_CLAIM_CUSTOM,
|
||||
[FEATURE_EDITION_CLAIM_CONDITIONS_V1.name]:
|
||||
FEATURE_EDITION_CLAIM_CONDITIONS_V1,
|
||||
[FEATURE_EDITION_CLAIM_CONDITIONS_V2.name]:
|
||||
FEATURE_EDITION_CLAIM_CONDITIONS_V2,
|
||||
[FEATURE_EDITION_CLAIM_PHASES_V2.name]: FEATURE_EDITION_CLAIM_PHASES_V2,
|
||||
},
|
||||
} as const;
|
||||
|
||||
export const FEATURE_EDITION_LAZY_MINTABLE_V1 = {
|
||||
name: "ERC1155LazyMintableV1",
|
||||
namespace: "edition.drop",
|
||||
docLinks: {
|
||||
sdk: "sdk.erc1155droppable",
|
||||
contracts: "LazyMint",
|
||||
},
|
||||
abis: [DropERC1155_V2Abi],
|
||||
features: {
|
||||
[FEATURE_EDITION_CLAIM_PHASES_V1.name]: FEATURE_EDITION_CLAIM_PHASES_V1,
|
||||
},
|
||||
} as const;
|
||||
|
||||
export const FEATURE_EDITION_SIGNATURE_MINTABLE = {
|
||||
name: "ERC1155SignatureMintable",
|
||||
namespace: "edition.signature",
|
||||
@@ -126,7 +179,8 @@ export const FEATURE_EDITION = {
|
||||
[FEATURE_EDITION_BURNABLE.name]: FEATURE_EDITION_BURNABLE,
|
||||
[FEATURE_EDITION_ENUMERABLE.name]: FEATURE_EDITION_ENUMERABLE,
|
||||
[FEATURE_EDITION_MINTABLE.name]: FEATURE_EDITION_MINTABLE,
|
||||
[FEATURE_EDITION_LAZY_MINTABLE.name]: FEATURE_EDITION_LAZY_MINTABLE,
|
||||
[FEATURE_EDITION_LAZY_MINTABLE_V1.name]: FEATURE_EDITION_LAZY_MINTABLE_V1,
|
||||
[FEATURE_EDITION_LAZY_MINTABLE_V2.name]: FEATURE_EDITION_LAZY_MINTABLE_V2,
|
||||
[FEATURE_EDITION_REVEALABLE.name]: FEATURE_EDITION_REVEALABLE,
|
||||
[FEATURE_EDITION_SIGNATURE_MINTABLE.name]:
|
||||
FEATURE_EDITION_SIGNATURE_MINTABLE,
|
||||
|
||||
@@ -1,12 +1,26 @@
|
||||
import DropERC20_V2Abi from "@thirdweb-dev/contracts-js/dist/abis/DropERC20_V2.json";
|
||||
import IBurnableERC20Abi from "@thirdweb-dev/contracts-js/dist/abis/IBurnableERC20.json";
|
||||
import IDrop from "@thirdweb-dev/contracts-js/dist/abis/IDrop.json";
|
||||
import IDropSinglePhase from "@thirdweb-dev/contracts-js/dist/abis/IDropSinglePhase.json";
|
||||
import IDropSinglePhaseV1 from "@thirdweb-dev/contracts-js/dist/abis/IDropSinglePhase_V1.json";
|
||||
import ERC20Abi from "@thirdweb-dev/contracts-js/dist/abis/IERC20.json";
|
||||
import IMintableERC20Abi from "@thirdweb-dev/contracts-js/dist/abis/IMintableERC20.json";
|
||||
import MulticallAbi from "@thirdweb-dev/contracts-js/dist/abis/IMulticall.json";
|
||||
import ISignatureMintERC20Abi from "@thirdweb-dev/contracts-js/dist/abis/ISignatureMintERC20.json";
|
||||
|
||||
export const FEATURE_TOKEN_CLAIMABLE_WITH_CONDITIONS = {
|
||||
name: "ERC20ClaimableWithConditions",
|
||||
export const FEATURE_TOKEN_CLAIM_CONDITIONS_V1 = {
|
||||
name: "ERC20ClaimConditionsV1",
|
||||
namespace: "token.drop.claim",
|
||||
docLinks: {
|
||||
sdk: "sdk.erc20dclaimable",
|
||||
contracts: "DropSinglePhase_V1",
|
||||
},
|
||||
abis: [ERC20Abi, IDropSinglePhaseV1],
|
||||
features: {},
|
||||
} as const;
|
||||
|
||||
export const FEATURE_TOKEN_CLAIM_CONDITIONS_V2 = {
|
||||
name: "ERC20ClaimConditionsV2",
|
||||
namespace: "token.drop.claim",
|
||||
docLinks: {
|
||||
sdk: "sdk.erc20dclaimable",
|
||||
@@ -16,6 +30,28 @@ export const FEATURE_TOKEN_CLAIMABLE_WITH_CONDITIONS = {
|
||||
features: {},
|
||||
} as const;
|
||||
|
||||
export const FEATURE_TOKEN_CLAIM_PHASES_V2 = {
|
||||
name: "ERC20ClaimPhasesV2",
|
||||
namespace: "token.drop.claim",
|
||||
docLinks: {
|
||||
sdk: "sdk.erc20dclaimable",
|
||||
contracts: "Drop",
|
||||
},
|
||||
abis: [ERC20Abi, IDrop],
|
||||
features: {},
|
||||
} as const;
|
||||
|
||||
export const FEATURE_TOKEN_CLAIM_PHASES_V1 = {
|
||||
name: "ERC20ClaimPhasesV1",
|
||||
namespace: "token.drop.claim",
|
||||
docLinks: {
|
||||
sdk: "sdk.erc20dclaimable",
|
||||
contracts: "Drop",
|
||||
},
|
||||
abis: [DropERC20_V2Abi],
|
||||
features: {},
|
||||
} as const;
|
||||
|
||||
export const FEATURE_TOKEN_BURNABLE = {
|
||||
name: "ERC20Burnable",
|
||||
namespace: "token.burn",
|
||||
@@ -73,8 +109,10 @@ export const FEATURE_TOKEN = {
|
||||
features: {
|
||||
[FEATURE_TOKEN_BURNABLE.name]: FEATURE_TOKEN_BURNABLE,
|
||||
[FEATURE_TOKEN_MINTABLE.name]: FEATURE_TOKEN_MINTABLE,
|
||||
[FEATURE_TOKEN_CLAIMABLE_WITH_CONDITIONS.name]:
|
||||
FEATURE_TOKEN_CLAIMABLE_WITH_CONDITIONS,
|
||||
[FEATURE_TOKEN_CLAIM_CONDITIONS_V1.name]: FEATURE_TOKEN_CLAIM_CONDITIONS_V1,
|
||||
[FEATURE_TOKEN_CLAIM_CONDITIONS_V2.name]: FEATURE_TOKEN_CLAIM_CONDITIONS_V2,
|
||||
[FEATURE_TOKEN_CLAIM_PHASES_V1.name]: FEATURE_TOKEN_CLAIM_PHASES_V1,
|
||||
[FEATURE_TOKEN_CLAIM_PHASES_V2.name]: FEATURE_TOKEN_CLAIM_PHASES_V2,
|
||||
[FEATURE_TOKEN_SIGNATURE_MINTABLE.name]: FEATURE_TOKEN_SIGNATURE_MINTABLE,
|
||||
},
|
||||
} as const;
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import DropERC721_V3Abi from "@thirdweb-dev/contracts-js/dist/abis/DropERC721_V3.json";
|
||||
import IBurnableERC721Abi from "@thirdweb-dev/contracts-js/dist/abis/IBurnableERC721.json";
|
||||
import IClaimableERC721 from "@thirdweb-dev/contracts-js/dist/abis/IClaimableERC721.json";
|
||||
import DelayedRevealAbi from "@thirdweb-dev/contracts-js/dist/abis/IDelayedReveal.json";
|
||||
import IDrop from "@thirdweb-dev/contracts-js/dist/abis/IDrop.json";
|
||||
import IDropSinglePhase from "@thirdweb-dev/contracts-js/dist/abis/IDropSinglePhase.json";
|
||||
import IDropSinglePhaseV1 from "@thirdweb-dev/contracts-js/dist/abis/IDropSinglePhase_V1.json";
|
||||
import Erc721Abi from "@thirdweb-dev/contracts-js/dist/abis/IERC721.json";
|
||||
@@ -9,8 +11,9 @@ import Erc721SupplyAbi from "@thirdweb-dev/contracts-js/dist/abis/IERC721Supply.
|
||||
import ILazyMintAbi from "@thirdweb-dev/contracts-js/dist/abis/ILazyMint.json";
|
||||
import IMintableERC721Abi from "@thirdweb-dev/contracts-js/dist/abis/IMintableERC721.json";
|
||||
import MulticallAbi from "@thirdweb-dev/contracts-js/dist/abis/IMulticall.json";
|
||||
import SignatureMintERC721Abi from "@thirdweb-dev/contracts-js/dist/abis/ISignatureMintERC721.json";
|
||||
import TieredDropAbi from "@thirdweb-dev/contracts-js/dist/abis/LazyMintWithTier.json";
|
||||
import SignatureMintERC721Abi from "@thirdweb-dev/contracts-js/dist/abis/SignatureMintERC721.json";
|
||||
import TokenERC721Abi from "@thirdweb-dev/contracts-js/dist/abis/TokenERC721.json";
|
||||
|
||||
export const FEATURE_NFT_BURNABLE = {
|
||||
name: "ERC721Burnable",
|
||||
@@ -45,19 +48,8 @@ export const FEATURE_NFT_TIERED_DROP = {
|
||||
features: {},
|
||||
} as const;
|
||||
|
||||
export const FEATURE_NFT_CLAIMABLE_WITH_CONDITIONS_V2 = {
|
||||
name: "ERC721ClaimableWithConditionsV2",
|
||||
namespace: "nft.drop.claim",
|
||||
docLinks: {
|
||||
sdk: "sdk.erc721claimable",
|
||||
contracts: "DropSinglePhase",
|
||||
},
|
||||
abis: [Erc721Abi, ILazyMintAbi, IDropSinglePhase],
|
||||
features: {},
|
||||
} as const;
|
||||
|
||||
export const FEATURE_NFT_CLAIMABLE_WITH_CONDITIONS_V1 = {
|
||||
name: "ERC721ClaimableWithConditionsV1",
|
||||
export const FEATURE_NFT_CLAIM_CONDITIONS_V1 = {
|
||||
name: "ERC721ClaimConditionsV1",
|
||||
namespace: "nft.drop.claim",
|
||||
docLinks: {
|
||||
sdk: "sdk.erc721claimable",
|
||||
@@ -67,8 +59,41 @@ export const FEATURE_NFT_CLAIMABLE_WITH_CONDITIONS_V1 = {
|
||||
features: {},
|
||||
} as const;
|
||||
|
||||
export const FEATURE_NFT_CLAIMABLE = {
|
||||
name: "ERC721Claimable",
|
||||
export const FEATURE_NFT_CLAIM_CONDITIONS_V2 = {
|
||||
name: "ERC721ClaimConditionsV2",
|
||||
namespace: "nft.drop.claim",
|
||||
docLinks: {
|
||||
sdk: "sdk.erc721claimable",
|
||||
contracts: "DropSinglePhase",
|
||||
},
|
||||
abis: [Erc721Abi, ILazyMintAbi, IDropSinglePhase],
|
||||
features: {},
|
||||
} as const;
|
||||
|
||||
export const FEATURE_NFT_CLAIM_PHASES_V1 = {
|
||||
name: "ERC721ClaimPhasesV1",
|
||||
namespace: "nft.drop.claim",
|
||||
docLinks: {
|
||||
sdk: "sdk.erc721claimable",
|
||||
contracts: "Drop",
|
||||
},
|
||||
abis: [DropERC721_V3Abi],
|
||||
features: {},
|
||||
} as const;
|
||||
|
||||
export const FEATURE_NFT_CLAIM_PHASES_V2 = {
|
||||
name: "ERC721ClaimPhasesV2",
|
||||
namespace: "nft.drop.claim",
|
||||
docLinks: {
|
||||
sdk: "sdk.erc721claimable",
|
||||
contracts: "Drop",
|
||||
},
|
||||
abis: [Erc721Abi, ILazyMintAbi, IDrop],
|
||||
features: {},
|
||||
} as const;
|
||||
|
||||
export const FEATURE_NFT_CLAIM_CUSTOM = {
|
||||
name: "ERC721ClaimCustom",
|
||||
namespace: "nft.drop.claim",
|
||||
docLinks: {
|
||||
sdk: "sdk.erc721claimable",
|
||||
@@ -88,11 +113,11 @@ export const FEATURE_NFT_LAZY_MINTABLE = {
|
||||
abis: [Erc721Abi, ILazyMintAbi],
|
||||
features: {
|
||||
[FEATURE_NFT_REVEALABLE.name]: FEATURE_NFT_REVEALABLE,
|
||||
[FEATURE_NFT_CLAIMABLE.name]: FEATURE_NFT_CLAIMABLE,
|
||||
[FEATURE_NFT_CLAIMABLE_WITH_CONDITIONS_V2.name]:
|
||||
FEATURE_NFT_CLAIMABLE_WITH_CONDITIONS_V2,
|
||||
[FEATURE_NFT_CLAIMABLE_WITH_CONDITIONS_V1.name]:
|
||||
FEATURE_NFT_CLAIMABLE_WITH_CONDITIONS_V1,
|
||||
[FEATURE_NFT_CLAIM_CUSTOM.name]: FEATURE_NFT_CLAIM_CUSTOM,
|
||||
[FEATURE_NFT_CLAIM_CONDITIONS_V1.name]: FEATURE_NFT_CLAIM_CONDITIONS_V1,
|
||||
[FEATURE_NFT_CLAIM_CONDITIONS_V2.name]: FEATURE_NFT_CLAIM_CONDITIONS_V2,
|
||||
[FEATURE_NFT_CLAIM_PHASES_V1.name]: FEATURE_NFT_CLAIM_PHASES_V1,
|
||||
[FEATURE_NFT_CLAIM_PHASES_V2.name]: FEATURE_NFT_CLAIM_PHASES_V2,
|
||||
},
|
||||
} as const;
|
||||
|
||||
@@ -120,8 +145,8 @@ export const FEATURE_NFT_MINTABLE = {
|
||||
},
|
||||
} as const;
|
||||
|
||||
export const FEATURE_NFT_SIGNATURE_MINTABLE = {
|
||||
name: "ERC721SignatureMint",
|
||||
export const FEATURE_NFT_SIGNATURE_MINTABLE_V2 = {
|
||||
name: "ERC721SignatureMintV2",
|
||||
namespace: "nft.signature",
|
||||
docLinks: {
|
||||
sdk: "sdk.erc721signaturemint",
|
||||
@@ -131,6 +156,17 @@ export const FEATURE_NFT_SIGNATURE_MINTABLE = {
|
||||
features: {},
|
||||
} as const;
|
||||
|
||||
export const FEATURE_NFT_SIGNATURE_MINTABLE_V1 = {
|
||||
name: "ERC721SignatureMintV1",
|
||||
namespace: "nft.signature",
|
||||
docLinks: {
|
||||
sdk: "sdk.erc721signaturemint",
|
||||
contracts: "ISignatureMintERC721",
|
||||
},
|
||||
abis: [TokenERC721Abi],
|
||||
features: {},
|
||||
} as const;
|
||||
|
||||
export const FEATURE_NFT_ENUMERABLE = {
|
||||
name: "ERC721Enumerable",
|
||||
namespace: "nft.query.owned",
|
||||
@@ -168,7 +204,8 @@ export const FEATURE_NFT = {
|
||||
[FEATURE_NFT_SUPPLY.name]: FEATURE_NFT_SUPPLY,
|
||||
[FEATURE_NFT_MINTABLE.name]: FEATURE_NFT_MINTABLE,
|
||||
[FEATURE_NFT_LAZY_MINTABLE.name]: FEATURE_NFT_LAZY_MINTABLE,
|
||||
[FEATURE_NFT_SIGNATURE_MINTABLE.name]: FEATURE_NFT_SIGNATURE_MINTABLE,
|
||||
[FEATURE_NFT_SIGNATURE_MINTABLE_V1.name]: FEATURE_NFT_SIGNATURE_MINTABLE_V1,
|
||||
[FEATURE_NFT_SIGNATURE_MINTABLE_V2.name]: FEATURE_NFT_SIGNATURE_MINTABLE_V2,
|
||||
[FEATURE_NFT_TIERED_DROP.name]: FEATURE_NFT_TIERED_DROP,
|
||||
},
|
||||
} as const;
|
||||
|
||||
@@ -40,10 +40,6 @@ export const EditionDropInitializer = {
|
||||
...[network, address, storage, options]: InitalizeParams
|
||||
) => {
|
||||
const [, provider] = getSignerAndProvider(network, options);
|
||||
const contractInfo = await getPrebuiltInfo(address, provider);
|
||||
if (!contractInfo || contractInfo.type !== "DropERC1155") {
|
||||
throw new Error("Contract is not a DropERC1155");
|
||||
}
|
||||
const [abi, contract, _network] = await Promise.all([
|
||||
await EditionDropInitializer.getAbi(address, provider),
|
||||
import("./prebuilt-implementations/edition-drop"),
|
||||
@@ -213,10 +209,6 @@ export const NFTDropInitializer = {
|
||||
...[network, address, storage, options]: InitalizeParams
|
||||
) => {
|
||||
const [, provider] = getSignerAndProvider(network, options);
|
||||
const contractInfo = await getPrebuiltInfo(address, provider);
|
||||
if (!contractInfo || contractInfo.type !== "DropERC721") {
|
||||
throw new Error("Contract is not a DropERC721");
|
||||
}
|
||||
const [abi, contract, _network] = await Promise.all([
|
||||
NFTDropInitializer.getAbi(address, provider),
|
||||
import("./prebuilt-implementations/nft-drop"),
|
||||
@@ -368,10 +360,6 @@ export const TokenDropInitializer = {
|
||||
...[network, address, storage, options]: InitalizeParams
|
||||
) => {
|
||||
const [, provider] = getSignerAndProvider(network, options);
|
||||
const contractInfo = await getPrebuiltInfo(address, provider);
|
||||
if (!contractInfo || contractInfo.type !== "DropERC20") {
|
||||
throw new Error("Contract is not a DropERC20");
|
||||
}
|
||||
const [abi, contract, _network] = await Promise.all([
|
||||
TokenDropInitializer.getAbi(address, provider),
|
||||
import("./prebuilt-implementations/token-drop"),
|
||||
|
||||
@@ -22,7 +22,7 @@ import {
|
||||
TransactionResult,
|
||||
TransactionResultWithId,
|
||||
} from "../../core/types";
|
||||
import { PaperCheckout } from "../../integrations/checkout";
|
||||
import { PaperCheckout } from "../../integrations/thirdweb-checkout";
|
||||
import { DropErc1155ContractSchema } from "../../schema/contracts/drop-erc1155";
|
||||
import { SDKOptions } from "../../schema/sdk-options";
|
||||
import { PrebuiltEditionDrop } from "../../types/eips";
|
||||
@@ -39,7 +39,7 @@ import { BigNumber, BigNumberish, CallOverrides, constants } from "ethers";
|
||||
* import { ThirdwebSDK } from "@thirdweb-dev/sdk";
|
||||
*
|
||||
* const sdk = new ThirdwebSDK("{{chainName}}");
|
||||
* const contract = sdk.getContract("{{contract_address}}", "edition-drop");
|
||||
* const contract = await sdk.getContract("{{contract_address}}", "edition-drop");
|
||||
* ```
|
||||
*
|
||||
* @public
|
||||
|
||||
@@ -37,7 +37,7 @@ import { BigNumber, BigNumberish, CallOverrides, constants } from "ethers";
|
||||
* import { ThirdwebSDK } from "@thirdweb-dev/sdk";
|
||||
*
|
||||
* const sdk = new ThirdwebSDK("{{chainName}}");
|
||||
* const contract = sdk.getContract("{{contract_address}}", "edition");
|
||||
* const contract = await sdk.getContract("{{contract_address}}", "edition");
|
||||
* ```
|
||||
*
|
||||
* @public
|
||||
|
||||
@@ -3,10 +3,7 @@ import { ListingNotFoundError } from "../../common";
|
||||
import { isNativeToken } from "../../common/currency";
|
||||
import { mapOffer } from "../../common/marketplace";
|
||||
import { getRoleHash } from "../../common/role";
|
||||
import {
|
||||
NATIVE_TOKENS,
|
||||
SUPPORTED_CHAIN_ID,
|
||||
} from "../../constants";
|
||||
import { NATIVE_TOKENS, SUPPORTED_CHAIN_ID } from "../../constants";
|
||||
import { ContractEncoder } from "../../core/classes/contract-encoder";
|
||||
import { ContractEvents } from "../../core/classes/contract-events";
|
||||
import { ContractInterceptor } from "../../core/classes/contract-interceptor";
|
||||
@@ -42,7 +39,7 @@ import invariant from "tiny-invariant";
|
||||
* import { ThirdwebSDK } from "@thirdweb-dev/sdk";
|
||||
*
|
||||
* const sdk = new ThirdwebSDK("{{chainName}}");
|
||||
* const contract = sdk.getContract("{{contract_address}}", "marketplace");
|
||||
* const contract = await sdk.getContract("{{contract_address}}", "marketplace");
|
||||
* ```
|
||||
*
|
||||
* @public
|
||||
@@ -326,9 +323,15 @@ export class Marketplace implements UpdateableNetwork {
|
||||
*/
|
||||
public async getOffers(listingId: BigNumberish): Promise<Offer[]> {
|
||||
// get all new offer events from this contract
|
||||
const events = await this.events.getEvents<NewOfferEventObject>("NewOffer");
|
||||
// get only the events for this listing id
|
||||
const listingEvents = events.filter((e) => e.data.listingId.eq(listingId));
|
||||
const listingEvents = await this.events.getEvents<NewOfferEventObject>(
|
||||
"NewOffer",
|
||||
{
|
||||
order: "desc",
|
||||
filters: {
|
||||
listingId,
|
||||
},
|
||||
},
|
||||
);
|
||||
// derive the offers from the events
|
||||
return await Promise.all(
|
||||
listingEvents.map(async (e): Promise<Offer> => {
|
||||
|
||||
@@ -47,7 +47,7 @@ import { BigNumberish, CallOverrides, ethers } from "ethers";
|
||||
* import { ThirdwebSDK } from "@thirdweb-dev/sdk";
|
||||
*
|
||||
* const sdk = new ThirdwebSDK("{{chainName}}");
|
||||
* const contract = sdk.getContract("{{contract_address}}", "multiwrap");
|
||||
* const contract = await sdk.getContract("{{contract_address}}", "multiwrap");
|
||||
* ```
|
||||
*
|
||||
* @beta
|
||||
|
||||
@@ -35,7 +35,7 @@ import { BigNumberish, CallOverrides, constants } from "ethers";
|
||||
* import { ThirdwebSDK } from "@thirdweb-dev/sdk";
|
||||
*
|
||||
* const sdk = new ThirdwebSDK("{{chainName}}");
|
||||
* const contract = sdk.getContract("{{contract_address}}", "nft-collection");
|
||||
* const contract = await sdk.getContract("{{contract_address}}", "nft-collection");
|
||||
* ```
|
||||
*
|
||||
* @public
|
||||
|
||||
@@ -26,7 +26,7 @@ import {
|
||||
TransactionResult,
|
||||
TransactionResultWithId,
|
||||
} from "../../core/types";
|
||||
import { PaperCheckout } from "../../integrations/checkout";
|
||||
import { PaperCheckout } from "../../integrations/thirdweb-checkout";
|
||||
import { DropErc721ContractSchema } from "../../schema/contracts/drop-erc721";
|
||||
import { SDKOptions } from "../../schema/sdk-options";
|
||||
import { PrebuiltNFTDrop } from "../../types/eips";
|
||||
@@ -44,7 +44,7 @@ import { BigNumber, BigNumberish, CallOverrides, constants } from "ethers";
|
||||
* import { ThirdwebSDK } from "@thirdweb-dev/sdk";
|
||||
*
|
||||
* const sdk = new ThirdwebSDK("{{chainName}}");
|
||||
* const contract = sdk.getContract("{{contract_address}}", "nft-drop");
|
||||
* const contract = await sdk.getContract("{{contract_address}}", "nft-drop");
|
||||
* ```
|
||||
*
|
||||
* @public
|
||||
@@ -409,9 +409,9 @@ export class NFTDrop extends StandardErc721<PrebuiltNFTDrop> {
|
||||
* const quantity = 1; // how many unique NFTs you want to claim
|
||||
*
|
||||
* const tx = await contract.claimTo(address, quantity);
|
||||
* const receipt = tx.receipt; // the transaction receipt
|
||||
* const claimedTokenId = tx.id; // the id of the NFT claimed
|
||||
* const claimedNFT = await tx.data(); // (optional) get the claimed NFT metadata
|
||||
* const receipt = tx[0].receipt; // the transaction receipt
|
||||
* const claimedTokenId = tx[0].id; // the id of the NFT claimed
|
||||
* const claimedNFT = await tx[0].data(); // (optional) get the claimed NFT metadata
|
||||
* ```
|
||||
*
|
||||
* @param destinationAddress - Address you want to send the token to
|
||||
|
||||
@@ -52,7 +52,7 @@ import { BigNumber, BigNumberish, CallOverrides, ethers } from "ethers";
|
||||
* import { ThirdwebSDK } from "@thirdweb-dev/sdk";
|
||||
*
|
||||
* const sdk = new ThirdwebSDK("{{chainName}}");
|
||||
* const contract = sdk.getContract("{{contract_address}}", "pack");
|
||||
* const contract = await sdk.getContract("{{contract_address}}", "pack");
|
||||
* ```
|
||||
*
|
||||
* @public
|
||||
|
||||
@@ -27,7 +27,7 @@ import {
|
||||
TransactionResult,
|
||||
TransactionResultWithId,
|
||||
} from "../../core/types";
|
||||
import { PaperCheckout } from "../../integrations/checkout";
|
||||
import { PaperCheckout } from "../../integrations/thirdweb-checkout";
|
||||
import { DropErc721ContractSchema } from "../../schema/contracts/drop-erc721";
|
||||
import { SDKOptions } from "../../schema/sdk-options";
|
||||
import { ClaimOptions, UploadProgressEvent } from "../../types";
|
||||
@@ -47,7 +47,7 @@ import { BigNumber, BigNumberish, CallOverrides, constants } from "ethers";
|
||||
* import { ThirdwebSDK } from "@thirdweb-dev/sdk";
|
||||
*
|
||||
* const sdk = new ThirdwebSDK("{{chainName}}");
|
||||
* const contract = sdk.getContract("{{contract_address}}", "signature-drop");
|
||||
* const contract = await sdk.getContract("{{contract_address}}", "signature-drop");
|
||||
* ```
|
||||
*
|
||||
* @public
|
||||
|
||||
@@ -30,7 +30,7 @@ import { BigNumber, CallOverrides, Contract } from "ethers";
|
||||
* import { ThirdwebSDK } from "@thirdweb-dev/sdk";
|
||||
*
|
||||
* const sdk = new ThirdwebSDK("{{chainName}}");
|
||||
* const contract = sdk.getContract("{{contract_address}}", "split");
|
||||
* const contract = await sdk.getContract("{{contract_address}}", "split");
|
||||
* ```
|
||||
*
|
||||
* @public
|
||||
|
||||
@@ -28,7 +28,7 @@ import { CallOverrides, constants } from "ethers";
|
||||
* import { ThirdwebSDK } from "@thirdweb-dev/sdk";
|
||||
*
|
||||
* const sdk = new ThirdwebSDK("{{chainName}}");
|
||||
* const contract = sdk.getContract("{{contract_address}}", "token-drop");
|
||||
* const contract = await sdk.getContract("{{contract_address}}", "token-drop");
|
||||
* ```
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -30,7 +30,7 @@ import { CallOverrides, constants } from "ethers";
|
||||
* import { ThirdwebSDK } from "@thirdweb-dev/sdk";
|
||||
*
|
||||
* const sdk = new ThirdwebSDK("{{chainName}}");
|
||||
* const contract = sdk.getContract("{{contract_address}}", "token");
|
||||
* const contract = await sdk.getContract("{{contract_address}}", "token");
|
||||
* ```
|
||||
*
|
||||
* @public
|
||||
|
||||
@@ -46,7 +46,7 @@ import {
|
||||
* import { ThirdwebSDK } from "@thirdweb-dev/sdk";
|
||||
*
|
||||
* const sdk = new ThirdwebSDK("{{chainName}}");
|
||||
* const contract = sdk.getContract("{{contract_address}}", "vote");
|
||||
* const contract = await sdk.getContract("{{contract_address}}", "vote");
|
||||
* ```
|
||||
*
|
||||
* @public
|
||||
|
||||
@@ -4,10 +4,12 @@ import {
|
||||
fetchExtendedReleaseMetadata,
|
||||
fetchPreDeployMetadata,
|
||||
} from "../../common/index";
|
||||
import { ChainId } from "../../constants";
|
||||
import { getContractAddressByChainId } from "../../constants/addresses";
|
||||
import {
|
||||
EditionDropInitializer,
|
||||
EditionInitializer,
|
||||
getContractName,
|
||||
MarketplaceInitializer,
|
||||
MultiwrapInitializer,
|
||||
NFTCollectionInitializer,
|
||||
@@ -397,14 +399,61 @@ export class ContractDeployer extends RPCConnectionHandler {
|
||||
contractMetadata: z.input<
|
||||
DeploySchemaForPrebuiltContractType<TContractType>
|
||||
>,
|
||||
version?: number,
|
||||
version: string = "latest",
|
||||
): Promise<string> {
|
||||
const parsed =
|
||||
const activeChainId = (await this.getProvider().getNetwork()).chainId;
|
||||
|
||||
const parsedMetadata =
|
||||
PREBUILT_CONTRACTS_MAP[contractType].schema.deploy.parse(
|
||||
contractMetadata,
|
||||
);
|
||||
const factory = await this.getFactory();
|
||||
return await factory.deploy(contractType, parsed, version);
|
||||
|
||||
if (
|
||||
activeChainId === ChainId.Hardhat ||
|
||||
activeChainId === ChainId.Localhost
|
||||
) {
|
||||
//
|
||||
// old behavior for hardhat and localhost chains
|
||||
//
|
||||
|
||||
// parse version into the first number of the version string (or undefined if unparseable)
|
||||
let parsedVersion: number | undefined = undefined;
|
||||
try {
|
||||
parsedVersion = parseInt(version);
|
||||
if (isNaN(parsedVersion)) {
|
||||
parsedVersion = undefined;
|
||||
}
|
||||
} catch (e) {
|
||||
parsedVersion = undefined;
|
||||
}
|
||||
return await factory.deploy(contractType, parsedMetadata, parsedVersion);
|
||||
}
|
||||
|
||||
//
|
||||
// new behavior for all other chains
|
||||
//
|
||||
|
||||
// resolve contract name from type
|
||||
const contractName = getContractName(contractType);
|
||||
invariant(contractName, "contract name not found");
|
||||
// get deploy arugments for the contractType
|
||||
// first upload the contractmetadata
|
||||
const contractURI = await this.storage.upload(parsedMetadata);
|
||||
// the get the deploy arguments
|
||||
const constructorParams = await factory.getDeployArguments(
|
||||
contractType,
|
||||
parsedMetadata,
|
||||
contractURI,
|
||||
);
|
||||
|
||||
return this.deployReleasedContract(
|
||||
// 0xdd99b75f095d0c4d5112aCe938e4e6ed962fb024 === deployer.thirdweb.eth
|
||||
"0xdd99b75f095d0c4d5112aCe938e4e6ed962fb024",
|
||||
contractName,
|
||||
constructorParams,
|
||||
version,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -428,13 +477,14 @@ export class ContractDeployer extends RPCConnectionHandler {
|
||||
releaserAddress: string,
|
||||
contractName: string,
|
||||
constructorParams: any[],
|
||||
version = "latest",
|
||||
): Promise<string> {
|
||||
const release = await new ThirdwebSDK("polygon")
|
||||
.getPublisher()
|
||||
.getLatest(releaserAddress, contractName);
|
||||
.getVersion(releaserAddress, contractName, version);
|
||||
if (!release) {
|
||||
throw new Error(
|
||||
`No release found for '${contractName}' by ${releaserAddress}`,
|
||||
`No release found for '${contractName}' at version '${version}' by '${releaserAddress}'`,
|
||||
);
|
||||
}
|
||||
return await this.deployContractFromUri(
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { EventType } from "../../constants";
|
||||
import { ContractEvent, EventQueryFilter } from "../../types/index";
|
||||
import { ContractEvent, EventQueryOptions } from "../../types/index";
|
||||
import { ContractWrapper } from "./contract-wrapper";
|
||||
import { EventFragment } from "@ethersproject/abi";
|
||||
import { BaseContract, Event, providers } from "ethers";
|
||||
@@ -198,7 +198,7 @@ export class ContractEvents<TContract extends BaseContract> {
|
||||
* @returns The event objects of the events emitted with event names and data for each event
|
||||
*/
|
||||
public async getAllEvents<TEvent extends Record<string, any>>(
|
||||
filters: EventQueryFilter = {
|
||||
filters: Omit<EventQueryOptions, "filters"> = {
|
||||
fromBlock: 0,
|
||||
toBlock: "latest",
|
||||
order: "desc",
|
||||
@@ -226,23 +226,34 @@ export class ContractEvents<TContract extends BaseContract> {
|
||||
* ```javascript
|
||||
* // The name of the event to get logs for
|
||||
* const eventName = "Transfer";
|
||||
* // Optionally pass in filters to limit the blocks from which events are retrieved
|
||||
* const filters = {
|
||||
*
|
||||
* // Optionally pass in options to limit the blocks from which events are retrieved
|
||||
* const options = {
|
||||
* fromBlock: 0,
|
||||
* toBlock: 1000000,
|
||||
* }
|
||||
* const events = await contract.events.getEvents(eventName, filters);
|
||||
* toBlock: 1000000, // can also pass "latest"
|
||||
* order: "desc",
|
||||
* // Configure event filters (filter on indexed event parameters)
|
||||
* filters: {
|
||||
* from: "0x...",
|
||||
* to: "0x..."
|
||||
* }
|
||||
* };
|
||||
*
|
||||
* const events = await contract.events.getEvents(eventName, options);
|
||||
* console.log(events[0].eventName);
|
||||
* console.log(events[0].data);
|
||||
* ```
|
||||
*
|
||||
* @param eventName - The name of the event to get logs for
|
||||
* @param filters - Specify the from and to block numbers to get events for, defaults to all blocks. @see EventQueryFilter
|
||||
* @param options - Specify the from and to block numbers to get events for, defaults to all blocks. @see EventQueryOptions
|
||||
* @returns The requested event objects with event data
|
||||
*/
|
||||
public async getEvents<TEvent extends Record<string, any>>(
|
||||
public async getEvents<
|
||||
TEvent extends Record<string, any> = Record<string, any>,
|
||||
TFilter extends Record<string, any> = Record<string, any>,
|
||||
>(
|
||||
eventName: string,
|
||||
filters: EventQueryFilter = {
|
||||
options: EventQueryOptions<TFilter> = {
|
||||
fromBlock: 0,
|
||||
toBlock: "latest",
|
||||
order: "desc",
|
||||
@@ -251,24 +262,32 @@ export class ContractEvents<TContract extends BaseContract> {
|
||||
const event = this.contractWrapper.readContract.interface.getEvent(
|
||||
eventName as string,
|
||||
);
|
||||
const filter = this.contractWrapper.readContract.filters[event.name];
|
||||
|
||||
const eventInterface =
|
||||
this.contractWrapper.readContract.interface.getEvent(eventName);
|
||||
const args = options.filters
|
||||
? eventInterface.inputs.map((e) => (options.filters as TFilter)[e.name])
|
||||
: [];
|
||||
const filter = this.contractWrapper.readContract.filters[event.name](
|
||||
...args,
|
||||
);
|
||||
|
||||
const events = await this.contractWrapper.readContract.queryFilter(
|
||||
filter(),
|
||||
filters.fromBlock,
|
||||
filters.toBlock,
|
||||
filter,
|
||||
options.fromBlock,
|
||||
options.toBlock,
|
||||
);
|
||||
|
||||
const orderedEvents = events.sort((a, b) => {
|
||||
return filters.order === "desc"
|
||||
return options.order === "desc"
|
||||
? b.blockNumber - a.blockNumber
|
||||
: a.blockNumber - b.blockNumber;
|
||||
});
|
||||
|
||||
return this.parseEvents(orderedEvents);
|
||||
return this.parseEvents<TEvent>(orderedEvents);
|
||||
}
|
||||
|
||||
private parseEvents<TEvent extends Record<string, any>>(
|
||||
private parseEvents<TEvent = Record<string, any>>(
|
||||
events: Event[],
|
||||
): ContractEvent<TEvent>[] {
|
||||
return events.map((e) => {
|
||||
|
||||
@@ -293,6 +293,30 @@ export class ContractPublisher extends RPCConnectionHandler {
|
||||
return contractStructs.map((d) => this.toPublishedContract(d));
|
||||
}
|
||||
|
||||
public async getVersion(
|
||||
publisherAddress: string,
|
||||
contractId: string,
|
||||
version = "latest",
|
||||
): Promise<PublishedContract | undefined> {
|
||||
if (version === "latest") {
|
||||
return this.getLatest(publisherAddress, contractId);
|
||||
}
|
||||
const allVersions = await this.getAllVersions(publisherAddress, contractId);
|
||||
// get the metadata for each version
|
||||
const versionMetadata = await Promise.all(
|
||||
allVersions.map((contract) => this.fetchPublishedContractInfo(contract)),
|
||||
);
|
||||
// find the version that matches the version string
|
||||
const versionMatch = versionMetadata.find(
|
||||
(metadata) => metadata.publishedMetadata.version === version,
|
||||
);
|
||||
invariant(versionMatch, "Contract version not found");
|
||||
// match the version back to the contract based on the release timestamp
|
||||
return allVersions.find(
|
||||
(contract) => contract.timestamp === versionMatch.publishedTimestamp,
|
||||
);
|
||||
}
|
||||
|
||||
public async getLatest(
|
||||
publisherAddress: string,
|
||||
contractId: string,
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { AmountSchema } from "../../../core/schema/shared";
|
||||
import { includesErrorMessage } from "../../common";
|
||||
import {
|
||||
abstractContractModelToLegacy,
|
||||
abstractContractModelToNew,
|
||||
convertQuantityToBigNumber,
|
||||
fetchSnapshotEntryForAddress,
|
||||
getClaimerProofs,
|
||||
legacyContractModelToAbstract,
|
||||
newContractModelToAbstract,
|
||||
prepareClaim,
|
||||
@@ -22,7 +22,6 @@ import { isNode } from "../../common/utils";
|
||||
import { ClaimEligibility } from "../../enums";
|
||||
import {
|
||||
AbstractClaimConditionContractStruct,
|
||||
AmountSchema,
|
||||
SnapshotEntryWithProof,
|
||||
} from "../../schema";
|
||||
import {
|
||||
@@ -279,20 +278,9 @@ export class DropClaimConditions<
|
||||
claimCondition.merkleRootHash,
|
||||
);
|
||||
const hasAllowList = merkleRootArray.length > 0;
|
||||
let allowListEntry;
|
||||
let allowListEntry: SnapshotEntryWithProof | null = null;
|
||||
if (hasAllowList) {
|
||||
const merkleLower = claimCondition.merkleRootHash.toString();
|
||||
const metadata = await this.metadata.get();
|
||||
allowListEntry = await getClaimerProofs(
|
||||
addressToCheck,
|
||||
merkleLower,
|
||||
await this.getTokenDecimals(),
|
||||
metadata.merkle,
|
||||
this.storage,
|
||||
this.contractWrapper.getProvider(),
|
||||
this.getSnapshotFormatVersion(),
|
||||
);
|
||||
|
||||
allowListEntry = await this.getClaimerProofs(addressToCheck);
|
||||
if (
|
||||
!allowListEntry &&
|
||||
(this.isLegacySinglePhaseDrop(this.contractWrapper) ||
|
||||
@@ -305,6 +293,13 @@ export class DropClaimConditions<
|
||||
|
||||
if (allowListEntry) {
|
||||
try {
|
||||
const claimVerification = await this.prepareClaim(
|
||||
quantity,
|
||||
false,
|
||||
decimals,
|
||||
addressToCheck,
|
||||
);
|
||||
|
||||
let validMerkleProof;
|
||||
if (this.isLegacyMultiPhaseDrop(this.contractWrapper)) {
|
||||
activeConditionIndex =
|
||||
@@ -315,8 +310,8 @@ export class DropClaimConditions<
|
||||
activeConditionIndex,
|
||||
addressToCheck,
|
||||
quantity,
|
||||
allowListEntry.proof,
|
||||
allowListEntry.maxClaimable,
|
||||
claimVerification.proofs,
|
||||
claimVerification.maxClaimable,
|
||||
);
|
||||
if (!validMerkleProof) {
|
||||
reasons.push(ClaimEligibility.AddressNotAllowed);
|
||||
@@ -328,8 +323,8 @@ export class DropClaimConditions<
|
||||
addressToCheck,
|
||||
quantity,
|
||||
{
|
||||
proof: allowListEntry.proof,
|
||||
maxQuantityInAllowlist: allowListEntry.maxClaimable,
|
||||
proof: claimVerification.proofs,
|
||||
maxQuantityInAllowlist: claimVerification.maxClaimable,
|
||||
},
|
||||
);
|
||||
if (!validMerkleProof) {
|
||||
@@ -340,25 +335,23 @@ export class DropClaimConditions<
|
||||
await this.contractWrapper.readContract.verifyClaim(
|
||||
addressToCheck,
|
||||
quantity,
|
||||
claimCondition.currencyAddress,
|
||||
claimCondition.price,
|
||||
claimVerification.currencyAddress,
|
||||
claimVerification.price,
|
||||
{
|
||||
proof: allowListEntry.proof,
|
||||
quantityLimitPerWallet: allowListEntry.maxClaimable,
|
||||
currency: allowListEntry.currencyAddress,
|
||||
pricePerToken: allowListEntry.price,
|
||||
proof: claimVerification.proofs,
|
||||
quantityLimitPerWallet: claimVerification.maxClaimable,
|
||||
currency: claimVerification.currencyAddressInProof,
|
||||
pricePerToken: claimVerification.priceInProof,
|
||||
} as IDropSinglePhase.AllowlistProofStruct,
|
||||
);
|
||||
// TODO (cc) in new override format, anyone can claim (no allow list restriction)
|
||||
// TODO (cc) instead check if maxClaimablePerWallet is 0 and this address has no overrides
|
||||
// TODO (cc) meaning this address is not allowed to claim
|
||||
if (
|
||||
(convertQuantityToBigNumber(
|
||||
claimCondition.maxClaimablePerWallet,
|
||||
decimals,
|
||||
).eq(0) &&
|
||||
allowListEntry.maxClaimable === ethers.constants.MaxUint256) ||
|
||||
allowListEntry.maxClaimable === BigNumber.from(0)
|
||||
claimVerification.maxClaimable ===
|
||||
ethers.constants.MaxUint256) ||
|
||||
claimVerification.maxClaimable === BigNumber.from(0)
|
||||
) {
|
||||
reasons.push(ClaimEligibility.AddressNotAllowed);
|
||||
return reasons;
|
||||
@@ -370,13 +363,13 @@ export class DropClaimConditions<
|
||||
activeConditionIndex,
|
||||
addressToCheck,
|
||||
quantity,
|
||||
claimCondition.currencyAddress,
|
||||
claimCondition.price,
|
||||
claimVerification.currencyAddress,
|
||||
claimVerification.price,
|
||||
{
|
||||
proof: allowListEntry.proof,
|
||||
quantityLimitPerWallet: allowListEntry.maxClaimable,
|
||||
currency: allowListEntry.currencyAddress,
|
||||
pricePerToken: allowListEntry.price,
|
||||
proof: claimVerification.proofs,
|
||||
quantityLimitPerWallet: claimVerification.maxClaimable,
|
||||
currency: claimVerification.currencyAddressInProof,
|
||||
pricePerToken: claimVerification.priceInProof,
|
||||
} as IDropSinglePhase.AllowlistProofStruct,
|
||||
);
|
||||
if (
|
||||
@@ -384,8 +377,9 @@ export class DropClaimConditions<
|
||||
claimCondition.maxClaimablePerWallet,
|
||||
decimals,
|
||||
).eq(0) &&
|
||||
allowListEntry.maxClaimable === ethers.constants.MaxUint256) ||
|
||||
allowListEntry.maxClaimable === BigNumber.from(0)
|
||||
claimVerification.maxClaimable ===
|
||||
ethers.constants.MaxUint256) ||
|
||||
claimVerification.maxClaimable === BigNumber.from(0)
|
||||
) {
|
||||
reasons.push(ClaimEligibility.AddressNotAllowed);
|
||||
return reasons;
|
||||
@@ -578,6 +572,48 @@ export class DropClaimConditions<
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// if using new snapshot format, make sure that maxClaimablePerWallet is set if allowlist is set as well
|
||||
if (
|
||||
this.isNewSinglePhaseDrop(this.contractWrapper) ||
|
||||
this.isNewMultiphaseDrop(this.contractWrapper)
|
||||
) {
|
||||
claimConditionsProcessed.forEach((cc) => {
|
||||
if (
|
||||
cc.snapshot &&
|
||||
cc.snapshot.length > 0 &&
|
||||
(cc.maxClaimablePerWallet === undefined ||
|
||||
cc.maxClaimablePerWallet === "unlimited")
|
||||
) {
|
||||
throw new Error(
|
||||
"maxClaimablePerWallet must be set to a specific value when an allowlist is set.\n" +
|
||||
"Example: Set it to 0 to only allow addresses in the allowlist to claim the amount specified in the allowlist.\n" +
|
||||
"contract.claimConditions.set([{ snapshot: [{ address: '0x...', maxClaimable: 1 }], maxClaimablePerWallet: 0 }])",
|
||||
);
|
||||
}
|
||||
if (
|
||||
cc.snapshot &&
|
||||
cc.snapshot.length > 0 &&
|
||||
cc.maxClaimablePerWallet?.toString() === "0" &&
|
||||
cc.snapshot
|
||||
.map((s) => {
|
||||
if (typeof s === "string") {
|
||||
return 0;
|
||||
} else {
|
||||
return Number(s.maxClaimable?.toString() || 0);
|
||||
}
|
||||
})
|
||||
.reduce((acc, current) => {
|
||||
return acc + current;
|
||||
}, 0) === 0
|
||||
) {
|
||||
throw new Error(
|
||||
"maxClaimablePerWallet is set to 0, and all addresses in the allowlist have max claimable 0. This means that no one can claim.",
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// process inputs
|
||||
const { snapshotInfos, sortedConditions } =
|
||||
await processClaimConditionInputs(
|
||||
@@ -706,8 +742,13 @@ export class DropClaimConditions<
|
||||
quantity: BigNumberish,
|
||||
checkERC20Allowance: boolean,
|
||||
decimals = 0,
|
||||
address?: string,
|
||||
): Promise<ClaimVerification> {
|
||||
const addressToClaim = address
|
||||
? address
|
||||
: await this.contractWrapper.getSignerAddress();
|
||||
return prepareClaim(
|
||||
addressToClaim,
|
||||
quantity,
|
||||
await this.getActive(),
|
||||
async () => (await this.metadata.get()).merkle,
|
||||
@@ -724,13 +765,12 @@ export class DropClaimConditions<
|
||||
quantity: BigNumberish,
|
||||
claimVerification: ClaimVerification,
|
||||
): Promise<any[]> {
|
||||
const activeClaimCondition = await this.getActive();
|
||||
if (this.isLegacyMultiPhaseDrop(this.contractWrapper)) {
|
||||
return [
|
||||
destinationAddress,
|
||||
quantity,
|
||||
activeClaimCondition.currencyAddress,
|
||||
activeClaimCondition.price,
|
||||
claimVerification.currencyAddress,
|
||||
claimVerification.price,
|
||||
claimVerification.proofs,
|
||||
claimVerification.maxClaimable,
|
||||
];
|
||||
@@ -738,8 +778,8 @@ export class DropClaimConditions<
|
||||
return [
|
||||
destinationAddress,
|
||||
quantity,
|
||||
activeClaimCondition.currencyAddress,
|
||||
activeClaimCondition.price,
|
||||
claimVerification.currencyAddress,
|
||||
claimVerification.price,
|
||||
{
|
||||
proof: claimVerification.proofs,
|
||||
maxQuantityInAllowlist: claimVerification.maxClaimable,
|
||||
@@ -750,13 +790,13 @@ export class DropClaimConditions<
|
||||
return [
|
||||
destinationAddress,
|
||||
quantity,
|
||||
activeClaimCondition.currencyAddress,
|
||||
activeClaimCondition.price,
|
||||
claimVerification.currencyAddress,
|
||||
claimVerification.price,
|
||||
{
|
||||
proof: claimVerification.proofs,
|
||||
quantityLimitPerWallet: claimVerification.maxClaimable,
|
||||
pricePerToken: claimVerification.price,
|
||||
currency: claimVerification.currencyAddress,
|
||||
pricePerToken: claimVerification.priceInProof,
|
||||
currency: claimVerification.currencyAddressInProof,
|
||||
} as IDropSinglePhase.AllowlistProofStruct,
|
||||
ethers.utils.toUtf8Bytes(""),
|
||||
];
|
||||
@@ -803,8 +843,14 @@ export class DropClaimConditions<
|
||||
contractWrapper: ContractWrapper<any>,
|
||||
): contractWrapper is ContractWrapper<DropSinglePhase> {
|
||||
return (
|
||||
!hasFunction<DropSinglePhase>("getClaimConditionById", contractWrapper) &&
|
||||
hasFunction<DropSinglePhase>("getSupplyClaimedByWallet", contractWrapper)
|
||||
detectContractFeature<DropSinglePhase>(
|
||||
contractWrapper,
|
||||
"ERC721ClaimConditionsV2",
|
||||
) ||
|
||||
detectContractFeature<DropSinglePhase>(
|
||||
contractWrapper,
|
||||
"ERC20ClaimConditionsV2",
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -812,8 +858,8 @@ export class DropClaimConditions<
|
||||
contractWrapper: ContractWrapper<any>,
|
||||
): contractWrapper is ContractWrapper<Drop> {
|
||||
return (
|
||||
hasFunction<Drop>("getClaimConditionById", contractWrapper) &&
|
||||
hasFunction<Drop>("getSupplyClaimedByWallet", contractWrapper)
|
||||
detectContractFeature<Drop>(contractWrapper, "ERC721ClaimPhasesV2") ||
|
||||
detectContractFeature<Drop>(contractWrapper, "ERC20ClaimPhasesV2")
|
||||
);
|
||||
}
|
||||
|
||||
@@ -821,10 +867,14 @@ export class DropClaimConditions<
|
||||
contractWrapper: ContractWrapper<any>,
|
||||
): contractWrapper is ContractWrapper<DropSinglePhase_V1> {
|
||||
return (
|
||||
!hasFunction<DropSinglePhase_V1>(
|
||||
"getClaimConditionById",
|
||||
detectContractFeature<DropSinglePhase_V1>(
|
||||
contractWrapper,
|
||||
) && hasFunction<DropSinglePhase_V1>("getClaimTimestamp", contractWrapper)
|
||||
"ERC721ClaimConditionsV1",
|
||||
) ||
|
||||
detectContractFeature<DropSinglePhase_V1>(
|
||||
contractWrapper,
|
||||
"ERC20ClaimConditionsV1",
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -832,8 +882,14 @@ export class DropClaimConditions<
|
||||
contractWrapper: ContractWrapper<any>,
|
||||
): contractWrapper is ContractWrapper<DropERC721_V3 | DropERC20_V2> {
|
||||
return (
|
||||
hasFunction<DropERC721_V3>("getClaimConditionById", contractWrapper) &&
|
||||
hasFunction<DropERC721_V3>("setWalletClaimCount", contractWrapper)
|
||||
detectContractFeature<DropERC721_V3 | DropERC20_V2>(
|
||||
contractWrapper,
|
||||
"ERC721ClaimPhasesV1",
|
||||
) ||
|
||||
detectContractFeature<DropERC721_V3 | DropERC20_V2>(
|
||||
contractWrapper,
|
||||
"ERC20ClaimPhasesV1",
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@ import {
|
||||
abstractContractModelToLegacy,
|
||||
abstractContractModelToNew,
|
||||
fetchSnapshotEntryForAddress,
|
||||
getClaimerProofs,
|
||||
legacyContractModelToAbstract,
|
||||
newContractModelToAbstract,
|
||||
prepareClaim,
|
||||
@@ -12,7 +11,10 @@ import {
|
||||
updateExistingClaimConditions,
|
||||
} from "../../common/claim-conditions";
|
||||
import { isNativeToken } from "../../common/currency";
|
||||
import { hasFunction } from "../../common/feature-detection";
|
||||
import {
|
||||
detectContractFeature,
|
||||
hasFunction,
|
||||
} from "../../common/feature-detection";
|
||||
import { SnapshotFormatVersion } from "../../common/sharded-merkle-tree";
|
||||
import { isNode } from "../../common/utils";
|
||||
import { ClaimEligibility } from "../../enums";
|
||||
@@ -272,20 +274,9 @@ export class DropErc1155ClaimConditions<
|
||||
claimCondition.merkleRootHash,
|
||||
);
|
||||
const hasAllowList = merkleRootArray.length > 0;
|
||||
let allowListEntry;
|
||||
let allowListEntry: SnapshotEntryWithProof | null = null;
|
||||
if (hasAllowList) {
|
||||
const merkleLower = claimCondition.merkleRootHash.toString();
|
||||
const metadata = await this.metadata.get();
|
||||
allowListEntry = await getClaimerProofs(
|
||||
addressToCheck,
|
||||
merkleLower,
|
||||
0,
|
||||
metadata.merkle,
|
||||
this.storage,
|
||||
this.contractWrapper.getProvider(),
|
||||
this.getSnapshotFormatVersion(),
|
||||
);
|
||||
|
||||
allowListEntry = await this.getClaimerProofs(tokenId, addressToCheck);
|
||||
if (
|
||||
!allowListEntry &&
|
||||
(this.isLegacySinglePhaseDrop(this.contractWrapper) ||
|
||||
@@ -298,6 +289,13 @@ export class DropErc1155ClaimConditions<
|
||||
|
||||
if (allowListEntry) {
|
||||
try {
|
||||
const claimVerification = await this.prepareClaim(
|
||||
tokenId,
|
||||
quantity,
|
||||
false,
|
||||
addressToCheck,
|
||||
);
|
||||
|
||||
let validMerkleProof;
|
||||
if (this.isLegacyMultiPhaseDrop(this.contractWrapper)) {
|
||||
activeConditionIndex =
|
||||
@@ -311,8 +309,8 @@ export class DropErc1155ClaimConditions<
|
||||
addressToCheck,
|
||||
tokenId,
|
||||
quantity,
|
||||
allowListEntry.proof,
|
||||
allowListEntry.maxClaimable,
|
||||
claimVerification.proofs,
|
||||
claimVerification.maxClaimable,
|
||||
);
|
||||
if (!validMerkleProof) {
|
||||
reasons.push(ClaimEligibility.AddressNotAllowed);
|
||||
@@ -325,8 +323,8 @@ export class DropErc1155ClaimConditions<
|
||||
addressToCheck,
|
||||
quantity,
|
||||
{
|
||||
proof: allowListEntry.proof,
|
||||
maxQuantityInAllowlist: allowListEntry.maxClaimable,
|
||||
proof: claimVerification.proofs,
|
||||
maxQuantityInAllowlist: claimVerification.maxClaimable,
|
||||
},
|
||||
);
|
||||
if (!validMerkleProof) {
|
||||
@@ -338,13 +336,13 @@ export class DropErc1155ClaimConditions<
|
||||
tokenId,
|
||||
addressToCheck,
|
||||
quantity,
|
||||
claimCondition.currencyAddress,
|
||||
claimCondition.price,
|
||||
claimVerification.currencyAddress,
|
||||
claimVerification.price,
|
||||
{
|
||||
proof: allowListEntry.proof,
|
||||
quantityLimitPerWallet: allowListEntry.maxClaimable,
|
||||
currency: allowListEntry.currencyAddress,
|
||||
pricePerToken: allowListEntry.price,
|
||||
proof: claimVerification.proofs,
|
||||
quantityLimitPerWallet: claimVerification.maxClaimable,
|
||||
currency: claimVerification.currencyAddressInProof,
|
||||
pricePerToken: claimVerification.priceInProof,
|
||||
} as IDropSinglePhase.AllowlistProofStruct,
|
||||
);
|
||||
// TODO (cc) in new override format, anyone can claim (no allow list restriction)
|
||||
@@ -352,8 +350,9 @@ export class DropErc1155ClaimConditions<
|
||||
// TODO (cc) meaning this address is not allowed to claim
|
||||
if (
|
||||
(claimCondition.maxClaimablePerWallet === "0" &&
|
||||
allowListEntry.maxClaimable === ethers.constants.MaxUint256) ||
|
||||
allowListEntry.maxClaimable === BigNumber.from(0)
|
||||
claimVerification.maxClaimable ===
|
||||
ethers.constants.MaxUint256) ||
|
||||
claimVerification.maxClaimable === BigNumber.from(0)
|
||||
) {
|
||||
reasons.push(ClaimEligibility.AddressNotAllowed);
|
||||
return reasons;
|
||||
@@ -368,19 +367,20 @@ export class DropErc1155ClaimConditions<
|
||||
addressToCheck,
|
||||
tokenId,
|
||||
quantity,
|
||||
claimCondition.currencyAddress,
|
||||
claimCondition.price,
|
||||
claimVerification.currencyAddress,
|
||||
claimVerification.price,
|
||||
{
|
||||
proof: allowListEntry.proof,
|
||||
quantityLimitPerWallet: allowListEntry.maxClaimable,
|
||||
currency: allowListEntry.currencyAddress,
|
||||
pricePerToken: allowListEntry.price,
|
||||
proof: claimVerification.proofs,
|
||||
quantityLimitPerWallet: claimVerification.maxClaimable,
|
||||
currency: claimVerification.currencyAddressInProof,
|
||||
pricePerToken: claimVerification.priceInProof,
|
||||
} as IDropSinglePhase.AllowlistProofStruct,
|
||||
);
|
||||
if (
|
||||
(claimCondition.maxClaimablePerWallet === "0" &&
|
||||
allowListEntry.maxClaimable === ethers.constants.MaxUint256) ||
|
||||
allowListEntry.maxClaimable === BigNumber.from(0)
|
||||
claimVerification.maxClaimable ===
|
||||
ethers.constants.MaxUint256) ||
|
||||
claimVerification.maxClaimable === BigNumber.from(0)
|
||||
) {
|
||||
reasons.push(ClaimEligibility.AddressNotAllowed);
|
||||
return reasons;
|
||||
@@ -621,6 +621,47 @@ export class DropErc1155ClaimConditions<
|
||||
);
|
||||
}
|
||||
}
|
||||
// if using new snapshot format, make sure that maxClaimablePerWallet is set if allowlist is set as well
|
||||
if (
|
||||
this.isNewSinglePhaseDrop(this.contractWrapper) ||
|
||||
this.isNewMultiphaseDrop(this.contractWrapper)
|
||||
) {
|
||||
claimConditionsProcessed.forEach((cc) => {
|
||||
if (
|
||||
cc.snapshot &&
|
||||
cc.snapshot.length > 0 &&
|
||||
(cc.maxClaimablePerWallet === undefined ||
|
||||
cc.maxClaimablePerWallet === "unlimited")
|
||||
) {
|
||||
throw new Error(
|
||||
"maxClaimablePerWallet must be set to a specific value when an allowlist is set.\n" +
|
||||
"Set it to 0 to only allow addresses in the allowlist to claim the amount specified in the allowlist." +
|
||||
"\n\nex:\n" +
|
||||
"contract.claimConditions.set(tokenId, [{ snapshot: [{ address: '0x...', maxClaimable: 1 }], maxClaimablePerWallet: 0 }])",
|
||||
);
|
||||
}
|
||||
if (
|
||||
cc.snapshot &&
|
||||
cc.snapshot.length > 0 &&
|
||||
cc.maxClaimablePerWallet?.toString() === "0" &&
|
||||
cc.snapshot
|
||||
.map((s) => {
|
||||
if (typeof s === "string") {
|
||||
return 0;
|
||||
} else {
|
||||
return Number(s.maxClaimable?.toString() || 0);
|
||||
}
|
||||
})
|
||||
.reduce((acc, current) => {
|
||||
return acc + current;
|
||||
}, 0) === 0
|
||||
) {
|
||||
throw new Error(
|
||||
"maxClaimablePerWallet is set to 0, and all addresses in the allowlist have max claimable 0. This means that no one can claim.",
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
// process inputs
|
||||
const { snapshotInfos, sortedConditions } =
|
||||
await processClaimConditionInputs(
|
||||
@@ -763,8 +804,13 @@ export class DropErc1155ClaimConditions<
|
||||
tokenId: BigNumberish,
|
||||
quantity: BigNumberish,
|
||||
checkERC20Allowance: boolean,
|
||||
address?: string,
|
||||
): Promise<ClaimVerification> {
|
||||
const addressToClaim = address
|
||||
? address
|
||||
: await this.contractWrapper.getSignerAddress();
|
||||
return prepareClaim(
|
||||
addressToClaim,
|
||||
quantity,
|
||||
await this.getActive(tokenId),
|
||||
async () => (await this.metadata.get()).merkle,
|
||||
@@ -782,14 +828,13 @@ export class DropErc1155ClaimConditions<
|
||||
quantity: BigNumberish,
|
||||
claimVerification: ClaimVerification,
|
||||
): Promise<any[]> {
|
||||
const activeClaimCondition = await this.getActive(tokenId);
|
||||
if (this.isLegacyMultiPhaseDrop(this.contractWrapper)) {
|
||||
return [
|
||||
destinationAddress,
|
||||
tokenId,
|
||||
quantity,
|
||||
activeClaimCondition.currencyAddress,
|
||||
activeClaimCondition.price,
|
||||
claimVerification.currencyAddress,
|
||||
claimVerification.price,
|
||||
claimVerification.proofs,
|
||||
claimVerification.maxClaimable,
|
||||
];
|
||||
@@ -798,8 +843,8 @@ export class DropErc1155ClaimConditions<
|
||||
destinationAddress,
|
||||
tokenId,
|
||||
quantity,
|
||||
activeClaimCondition.currencyAddress,
|
||||
activeClaimCondition.price,
|
||||
claimVerification.currencyAddress,
|
||||
claimVerification.price,
|
||||
{
|
||||
proof: claimVerification.proofs,
|
||||
maxQuantityInAllowlist: claimVerification.maxClaimable,
|
||||
@@ -811,13 +856,13 @@ export class DropErc1155ClaimConditions<
|
||||
destinationAddress,
|
||||
tokenId,
|
||||
quantity,
|
||||
activeClaimCondition.currencyAddress,
|
||||
activeClaimCondition.price,
|
||||
claimVerification.currencyAddress,
|
||||
claimVerification.price,
|
||||
{
|
||||
proof: claimVerification.proofs,
|
||||
quantityLimitPerWallet: claimVerification.maxClaimable,
|
||||
pricePerToken: claimVerification.price,
|
||||
currency: claimVerification.currencyAddress,
|
||||
pricePerToken: claimVerification.priceInProof,
|
||||
currency: claimVerification.currencyAddressInProof,
|
||||
} as IDropSinglePhase.AllowlistProofStruct,
|
||||
ethers.utils.toUtf8Bytes(""),
|
||||
];
|
||||
@@ -862,45 +907,36 @@ export class DropErc1155ClaimConditions<
|
||||
isNewSinglePhaseDrop(
|
||||
contractWrapper: ContractWrapper<any>,
|
||||
): contractWrapper is ContractWrapper<DropSinglePhase1155> {
|
||||
return (
|
||||
!hasFunction<DropSinglePhase1155>(
|
||||
"getClaimConditionById",
|
||||
contractWrapper,
|
||||
) &&
|
||||
hasFunction<DropSinglePhase1155>(
|
||||
"getSupplyClaimedByWallet",
|
||||
contractWrapper,
|
||||
)
|
||||
return detectContractFeature<DropSinglePhase1155>(
|
||||
contractWrapper,
|
||||
"ERC1155ClaimConditionsV2",
|
||||
);
|
||||
}
|
||||
|
||||
isNewMultiphaseDrop(
|
||||
contractWrapper: ContractWrapper<any>,
|
||||
): contractWrapper is ContractWrapper<Drop1155> {
|
||||
return (
|
||||
hasFunction<Drop1155>("getClaimConditionById", contractWrapper) &&
|
||||
hasFunction<Drop1155>("getSupplyClaimedByWallet", contractWrapper)
|
||||
return detectContractFeature<Drop1155>(
|
||||
contractWrapper,
|
||||
"ERC1155ClaimPhasesV2",
|
||||
);
|
||||
}
|
||||
|
||||
isLegacySinglePhaseDrop(
|
||||
contractWrapper: ContractWrapper<any>,
|
||||
): contractWrapper is ContractWrapper<DropSinglePhase1155_V1> {
|
||||
return (
|
||||
!hasFunction<DropSinglePhase1155_V1>(
|
||||
"getClaimConditionById",
|
||||
contractWrapper,
|
||||
) &&
|
||||
hasFunction<DropSinglePhase1155_V1>("getClaimTimestamp", contractWrapper)
|
||||
return detectContractFeature<DropSinglePhase1155_V1>(
|
||||
contractWrapper,
|
||||
"ERC1155ClaimConditionsV1",
|
||||
);
|
||||
}
|
||||
|
||||
isLegacyMultiPhaseDrop(
|
||||
contractWrapper: ContractWrapper<any>,
|
||||
): contractWrapper is ContractWrapper<DropERC1155_V2> {
|
||||
return (
|
||||
hasFunction<DropERC1155_V2>("getClaimConditionById", contractWrapper) &&
|
||||
hasFunction<DropERC1155_V2>("setWalletClaimCount", contractWrapper)
|
||||
return detectContractFeature<DropERC1155_V2>(
|
||||
contractWrapper,
|
||||
"ERC1155ClaimPhasesV1",
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { FEATURE_EDITION_CLAIMABLE_WITH_CONDITIONS } from "../../constants/erc1155-features";
|
||||
import { FEATURE_EDITION_CLAIM_CONDITIONS_V2 } from "../../constants/erc1155-features";
|
||||
import { CustomContractSchema } from "../../schema/contracts/custom";
|
||||
import { ClaimOptions } from "../../types/claim-conditions/claim-conditions";
|
||||
import { BaseClaimConditionERC1155 } from "../../types/eips";
|
||||
@@ -21,7 +21,7 @@ import { BigNumberish } from "ethers";
|
||||
* ```
|
||||
*/
|
||||
export class Erc1155ClaimableWithConditions implements DetectableFeature {
|
||||
featureName = FEATURE_EDITION_CLAIMABLE_WITH_CONDITIONS.name;
|
||||
featureName = FEATURE_EDITION_CLAIM_CONDITIONS_V2.name;
|
||||
|
||||
public conditions: DropErc1155ClaimConditions<BaseClaimConditionERC1155>;
|
||||
private contractWrapper: ContractWrapper<BaseClaimConditionERC1155>;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { calculateClaimCost } from "../../common/claim-conditions";
|
||||
import { FEATURE_EDITION_CLAIMABLE } from "../../constants/erc1155-features";
|
||||
import { FEATURE_EDITION_CLAIM_CUSTOM } from "../../constants/erc1155-features";
|
||||
import { ClaimOptions } from "../../types";
|
||||
import { DetectableFeature } from "../interfaces/DetectableFeature";
|
||||
import { TransactionResult } from "../types";
|
||||
@@ -18,7 +18,7 @@ import { BigNumberish, CallOverrides } from "ethers";
|
||||
* ```
|
||||
*/
|
||||
export class ERC1155Claimable implements DetectableFeature {
|
||||
featureName = FEATURE_EDITION_CLAIMABLE.name;
|
||||
featureName = FEATURE_EDITION_CLAIM_CUSTOM.name;
|
||||
|
||||
private contractWrapper: ContractWrapper<IClaimableERC1155>;
|
||||
|
||||
|
||||
@@ -1,12 +1,9 @@
|
||||
import { NFTMetadata, NFTMetadataOrUri } from "../../../core/schema/nft";
|
||||
import {
|
||||
detectContractFeature,
|
||||
hasFunction,
|
||||
} from "../../common/feature-detection";
|
||||
import { detectContractFeature } from "../../common/feature-detection";
|
||||
import { getPrebuiltInfo } from "../../common/legacy";
|
||||
import { uploadOrExtractURIs } from "../../common/nft";
|
||||
import {
|
||||
FEATURE_EDITION_LAZY_MINTABLE,
|
||||
FEATURE_EDITION_LAZY_MINTABLE_V2,
|
||||
FEATURE_EDITION_REVEALABLE,
|
||||
} from "../../constants/erc1155-features";
|
||||
import {
|
||||
@@ -28,7 +25,7 @@ import { ThirdwebStorage } from "@thirdweb-dev/storage";
|
||||
import { ethers } from "ethers";
|
||||
|
||||
export class Erc1155LazyMintable implements DetectableFeature {
|
||||
featureName = FEATURE_EDITION_LAZY_MINTABLE.name;
|
||||
featureName = FEATURE_EDITION_LAZY_MINTABLE_V2.name;
|
||||
|
||||
/**
|
||||
* Delayed reveal
|
||||
@@ -91,7 +88,7 @@ export class Erc1155LazyMintable implements DetectableFeature {
|
||||
this.storage = storage;
|
||||
this.claim = this.detectErc1155Claimable();
|
||||
this.claimWithConditions = this.detectErc1155ClaimableWithConditions();
|
||||
this.revealer = this.detectErc721Revealable();
|
||||
this.revealer = this.detectErc1155Revealable();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -184,9 +181,8 @@ export class Erc1155LazyMintable implements DetectableFeature {
|
||||
if (
|
||||
detectContractFeature<IClaimableERC1155>(
|
||||
this.contractWrapper,
|
||||
"ERC1155Claimable",
|
||||
) &&
|
||||
!hasFunction("setClaimConditions", this.contractWrapper)
|
||||
"ERC1155ClaimCustom",
|
||||
)
|
||||
) {
|
||||
return new ERC1155Claimable(this.contractWrapper);
|
||||
}
|
||||
@@ -199,7 +195,19 @@ export class Erc1155LazyMintable implements DetectableFeature {
|
||||
if (
|
||||
detectContractFeature<BaseClaimConditionERC1155>(
|
||||
this.contractWrapper,
|
||||
"ERC1155ClaimableWithConditions",
|
||||
"ERC1155ClaimConditionsV1",
|
||||
) ||
|
||||
detectContractFeature<BaseClaimConditionERC1155>(
|
||||
this.contractWrapper,
|
||||
"ERC1155ClaimConditionsV2",
|
||||
) ||
|
||||
detectContractFeature<BaseClaimConditionERC1155>(
|
||||
this.contractWrapper,
|
||||
"ERC1155ClaimPhasesV1",
|
||||
) ||
|
||||
detectContractFeature<BaseClaimConditionERC1155>(
|
||||
this.contractWrapper,
|
||||
"ERC1155ClaimPhasesV2",
|
||||
)
|
||||
) {
|
||||
return new Erc1155ClaimableWithConditions(
|
||||
@@ -210,7 +218,7 @@ export class Erc1155LazyMintable implements DetectableFeature {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
private detectErc721Revealable():
|
||||
private detectErc1155Revealable():
|
||||
| DelayedReveal<BaseDelayedRevealERC1155>
|
||||
| undefined {
|
||||
if (
|
||||
|
||||
@@ -12,13 +12,13 @@ import {
|
||||
FEATURE_EDITION,
|
||||
FEATURE_EDITION_BATCH_MINTABLE,
|
||||
FEATURE_EDITION_BURNABLE,
|
||||
FEATURE_EDITION_LAZY_MINTABLE,
|
||||
FEATURE_EDITION_ENUMERABLE,
|
||||
FEATURE_EDITION_MINTABLE,
|
||||
FEATURE_EDITION_REVEALABLE,
|
||||
FEATURE_EDITION_SIGNATURE_MINTABLE,
|
||||
FEATURE_EDITION_CLAIMABLE_WITH_CONDITIONS,
|
||||
FEATURE_EDITION_CLAIMABLE,
|
||||
FEATURE_EDITION_CLAIM_CUSTOM,
|
||||
FEATURE_EDITION_CLAIM_CONDITIONS_V2,
|
||||
FEATURE_EDITION_LAZY_MINTABLE_V2,
|
||||
} from "../../constants/erc1155-features";
|
||||
import { AirdropInputSchema } from "../../schema/contracts/common/airdrop";
|
||||
import { EditionMetadataOrUri } from "../../schema/tokens/edition";
|
||||
@@ -770,7 +770,7 @@ export class Erc1155<
|
||||
): Promise<TransactionResultWithId<NFTMetadata>[]> {
|
||||
return assertEnabled(
|
||||
this.lazyMintable,
|
||||
FEATURE_EDITION_LAZY_MINTABLE,
|
||||
FEATURE_EDITION_LAZY_MINTABLE_V2,
|
||||
).lazyMint(metadatas, options);
|
||||
}
|
||||
|
||||
@@ -808,7 +808,7 @@ export class Erc1155<
|
||||
options,
|
||||
);
|
||||
}
|
||||
throw new ExtensionNotImplementedError(FEATURE_EDITION_CLAIMABLE);
|
||||
throw new ExtensionNotImplementedError(FEATURE_EDITION_CLAIM_CUSTOM);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -887,7 +887,7 @@ export class Erc1155<
|
||||
if (claim) {
|
||||
return claim.to(destinationAddress, tokenId, quantity, options);
|
||||
}
|
||||
throw new ExtensionNotImplementedError(FEATURE_EDITION_CLAIMABLE);
|
||||
throw new ExtensionNotImplementedError(FEATURE_EDITION_CLAIM_CUSTOM);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -916,7 +916,7 @@ export class Erc1155<
|
||||
get claimConditions() {
|
||||
return assertEnabled(
|
||||
this.lazyMintable?.claimWithConditions,
|
||||
FEATURE_EDITION_CLAIMABLE_WITH_CONDITIONS,
|
||||
FEATURE_EDITION_CLAIM_CONDITIONS_V2,
|
||||
).conditions;
|
||||
}
|
||||
|
||||
@@ -1041,7 +1041,11 @@ export class Erc1155<
|
||||
if (
|
||||
detectContractFeature<BaseDropERC1155>(
|
||||
this.contractWrapper,
|
||||
"ERC1155LazyMintable",
|
||||
"ERC1155LazyMintableV1",
|
||||
) ||
|
||||
detectContractFeature<BaseDropERC1155>(
|
||||
this.contractWrapper,
|
||||
"ERC1155LazyMintableV2",
|
||||
)
|
||||
) {
|
||||
return new Erc1155LazyMintable(this, this.contractWrapper, this.storage);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { FEATURE_TOKEN_CLAIMABLE_WITH_CONDITIONS } from "../../constants/erc20-features";
|
||||
import { FEATURE_TOKEN_CLAIM_CONDITIONS_V2 } from "../../constants/erc20-features";
|
||||
import { CustomContractSchema } from "../../schema/contracts/custom";
|
||||
import { ClaimOptions } from "../../types";
|
||||
import { Amount } from "../../types/currency";
|
||||
@@ -21,7 +21,7 @@ import { ThirdwebStorage } from "@thirdweb-dev/storage";
|
||||
* ```
|
||||
*/
|
||||
export class Erc20ClaimableWithConditions implements DetectableFeature {
|
||||
featureName = FEATURE_TOKEN_CLAIMABLE_WITH_CONDITIONS.name;
|
||||
featureName = FEATURE_TOKEN_CLAIM_CONDITIONS_V2.name;
|
||||
/**
|
||||
* Configure claim conditions
|
||||
* @remarks Define who can claim NFTs in the collection, when and how many.
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { NetworkOrSignerOrProvider, TransactionResult } from "..";
|
||||
import { AmountSchema } from "../../../core/schema/shared";
|
||||
import { assertEnabled, detectContractFeature } from "../../common";
|
||||
import {
|
||||
fetchCurrencyMetadata,
|
||||
@@ -10,9 +11,9 @@ import {
|
||||
FEATURE_TOKEN_BATCH_MINTABLE,
|
||||
FEATURE_TOKEN_BURNABLE,
|
||||
FEATURE_TOKEN_SIGNATURE_MINTABLE,
|
||||
FEATURE_TOKEN_CLAIMABLE_WITH_CONDITIONS,
|
||||
FEATURE_TOKEN_CLAIM_CONDITIONS_V2,
|
||||
} from "../../constants/erc20-features";
|
||||
import { TokenMintInput, AmountSchema } from "../../schema";
|
||||
import { TokenMintInput } from "../../schema";
|
||||
import { Currency, CurrencyValue, Amount, ClaimOptions } from "../../types";
|
||||
import {
|
||||
BaseERC20,
|
||||
@@ -515,7 +516,7 @@ export class Erc20<
|
||||
): Promise<TransactionResult> {
|
||||
return assertEnabled(
|
||||
this.droppable?.claim,
|
||||
FEATURE_TOKEN_CLAIMABLE_WITH_CONDITIONS,
|
||||
FEATURE_TOKEN_CLAIM_CONDITIONS_V2,
|
||||
).to(destinationAddress, amount, options);
|
||||
}
|
||||
|
||||
@@ -545,7 +546,7 @@ export class Erc20<
|
||||
get claimConditions() {
|
||||
return assertEnabled(
|
||||
this.droppable?.claim,
|
||||
FEATURE_TOKEN_CLAIMABLE_WITH_CONDITIONS,
|
||||
FEATURE_TOKEN_CLAIM_CONDITIONS_V2,
|
||||
).conditions;
|
||||
}
|
||||
|
||||
@@ -619,7 +620,19 @@ export class Erc20<
|
||||
if (
|
||||
detectContractFeature<BaseDropERC20>(
|
||||
this.contractWrapper,
|
||||
"ERC20ClaimableWithConditions",
|
||||
"ERC20ClaimConditionsV1",
|
||||
) ||
|
||||
detectContractFeature<BaseDropERC20>(
|
||||
this.contractWrapper,
|
||||
"ERC20ClaimConditionsV2",
|
||||
) ||
|
||||
detectContractFeature<BaseDropERC20>(
|
||||
this.contractWrapper,
|
||||
"ERC20ClaimPhasesV1",
|
||||
) ||
|
||||
detectContractFeature<BaseDropERC20>(
|
||||
this.contractWrapper,
|
||||
"ERC20ClaimPhasesV2",
|
||||
)
|
||||
) {
|
||||
return new Erc20Droppable(this, this.contractWrapper, this.storage);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { NFT } from "../../../core/schema/nft";
|
||||
import { FEATURE_NFT_CLAIMABLE_WITH_CONDITIONS_V2 } from "../../constants/erc721-features";
|
||||
import { FEATURE_NFT_CLAIM_CONDITIONS_V2 } from "../../constants/erc721-features";
|
||||
import { CustomContractSchema } from "../../schema/contracts/custom";
|
||||
import { ClaimOptions } from "../../types";
|
||||
import { BaseClaimConditionERC721 } from "../../types/eips";
|
||||
@@ -24,7 +24,7 @@ import { BigNumber, BigNumberish } from "ethers";
|
||||
* ```
|
||||
*/
|
||||
export class Erc721ClaimableWithConditions implements DetectableFeature {
|
||||
featureName = FEATURE_NFT_CLAIMABLE_WITH_CONDITIONS_V2.name;
|
||||
featureName = FEATURE_NFT_CLAIM_CONDITIONS_V2.name;
|
||||
|
||||
/**
|
||||
* Configure claim conditions
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { NFT } from "../../../core/schema/nft";
|
||||
import { calculateClaimCost } from "../../common/claim-conditions";
|
||||
import { FEATURE_NFT_CLAIMABLE } from "../../constants/erc721-features";
|
||||
import { FEATURE_NFT_CLAIM_CUSTOM } from "../../constants/erc721-features";
|
||||
import { ClaimOptions } from "../../types";
|
||||
import { DetectableFeature } from "../interfaces/DetectableFeature";
|
||||
import { TransactionResultWithId } from "../types";
|
||||
@@ -21,7 +21,7 @@ import { BigNumber, BigNumberish, CallOverrides } from "ethers";
|
||||
* ```
|
||||
*/
|
||||
export class Erc721Claimable implements DetectableFeature {
|
||||
featureName = FEATURE_NFT_CLAIMABLE.name;
|
||||
featureName = FEATURE_NFT_CLAIM_CUSTOM.name;
|
||||
|
||||
private erc721: Erc721;
|
||||
private contractWrapper: ContractWrapper<IClaimableERC721>;
|
||||
@@ -77,7 +77,7 @@ export class Erc721Claimable implements DetectableFeature {
|
||||
* const quantity = 1; // how many NFTs you want to claim
|
||||
*
|
||||
* const tx = await contract.erc721.claimTo(address, tokenId, quantity);
|
||||
* const receipt = tx.receipt; // the transaction receipt
|
||||
* const receipt = tx[0].receipt; // the transaction receipt
|
||||
* ```
|
||||
*
|
||||
* @param destinationAddress - Address you want to send the token to
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
import { NFTMetadata, NFTMetadataOrUri } from "../../../core/schema/nft";
|
||||
import {
|
||||
detectContractFeature,
|
||||
hasFunction,
|
||||
} from "../../common/feature-detection";
|
||||
import { detectContractFeature } from "../../common/feature-detection";
|
||||
import { getBaseUriFromBatch, uploadOrExtractURIs } from "../../common/nft";
|
||||
import {
|
||||
FEATURE_NFT_LAZY_MINTABLE,
|
||||
@@ -194,11 +191,19 @@ export class Erc721LazyMintable implements DetectableFeature {
|
||||
if (
|
||||
detectContractFeature<BaseClaimConditionERC721>(
|
||||
this.contractWrapper,
|
||||
"ERC721ClaimableWithConditionsV1",
|
||||
"ERC721ClaimConditionsV1",
|
||||
) ||
|
||||
detectContractFeature<BaseClaimConditionERC721>(
|
||||
this.contractWrapper,
|
||||
"ERC721ClaimableWithConditionsV2",
|
||||
"ERC721ClaimConditionsV2",
|
||||
) ||
|
||||
detectContractFeature<BaseClaimConditionERC721>(
|
||||
this.contractWrapper,
|
||||
"ERC721ClaimPhasesV1",
|
||||
) ||
|
||||
detectContractFeature<BaseClaimConditionERC721>(
|
||||
this.contractWrapper,
|
||||
"ERC721ClaimPhasesV2",
|
||||
)
|
||||
) {
|
||||
return new Erc721ClaimableWithConditions(
|
||||
@@ -214,9 +219,8 @@ export class Erc721LazyMintable implements DetectableFeature {
|
||||
if (
|
||||
detectContractFeature<IClaimableERC721>(
|
||||
this.contractWrapper,
|
||||
"ERC721Claimable",
|
||||
) &&
|
||||
!hasFunction("setClaimConditions", this.contractWrapper)
|
||||
"ERC721ClaimCustom",
|
||||
)
|
||||
) {
|
||||
return new Erc721Claimable(this.erc721, this.contractWrapper);
|
||||
}
|
||||
|
||||
@@ -21,7 +21,10 @@ import { TransactionResult, TransactionResultWithId } from "../types";
|
||||
import { ContractWrapper } from "./contract-wrapper";
|
||||
import { Erc721 } from "./erc-721";
|
||||
import type { TieredDrop, ISignatureAction } from "@thirdweb-dev/contracts-js";
|
||||
import { TokensLazyMintedEvent } from "@thirdweb-dev/contracts-js/dist/declarations/src/TieredDrop";
|
||||
import {
|
||||
TokensLazyMintedEvent,
|
||||
TokensClaimedEvent,
|
||||
} from "@thirdweb-dev/contracts-js/dist/declarations/src/TieredDrop";
|
||||
import { ThirdwebStorage } from "@thirdweb-dev/storage";
|
||||
import { BigNumberish, ethers } from "ethers";
|
||||
import invariant from "tiny-invariant";
|
||||
@@ -46,12 +49,16 @@ export class Erc721TieredDrop implements DetectableFeature {
|
||||
public async getMetadataInTier(
|
||||
tier: string,
|
||||
): Promise<Omit<NFTMetadata, "id">[]> {
|
||||
const batches = await this.contractWrapper.readContract.getMetadataInTier(
|
||||
tier,
|
||||
);
|
||||
const tiers =
|
||||
await this.contractWrapper.readContract.getMetadataForAllTiers();
|
||||
const batches = tiers.find((t) => t.tier === tier);
|
||||
|
||||
if (!batches) {
|
||||
throw new Error("Tier not found in contract.");
|
||||
}
|
||||
|
||||
const nfts = await Promise.all(
|
||||
batches.tokens
|
||||
batches.ranges
|
||||
.map((range, i) => {
|
||||
const nftsInRange = [];
|
||||
const baseUri = batches.baseURIs[i];
|
||||
@@ -133,8 +140,9 @@ export class Erc721TieredDrop implements DetectableFeature {
|
||||
"TokensLazyMinted",
|
||||
receipt?.logs,
|
||||
);
|
||||
const startingIndex = event[0].args.startTokenId;
|
||||
const endingIndex = event[0].args.endTokenId;
|
||||
|
||||
const startingIndex = event[0].args[1];
|
||||
const endingIndex = event[0].args[2];
|
||||
const results: TransactionResultWithId<NFTMetadata>[] = [];
|
||||
for (let id = startingIndex; id.lte(endingIndex); id = id.add(1)) {
|
||||
results.push({
|
||||
@@ -214,8 +222,8 @@ export class Erc721TieredDrop implements DetectableFeature {
|
||||
"TokensLazyMinted",
|
||||
receipt?.logs,
|
||||
);
|
||||
const startingIndex = event[0].args.startTokenId;
|
||||
const endingIndex = event[0].args.endTokenId;
|
||||
const startingIndex = event[0].args[1];
|
||||
const endingIndex = event[0].args[2];
|
||||
const results: TransactionResultWithId<NFTMetadata>[] = [];
|
||||
for (let id = startingIndex; id.lte(endingIndex); id = id.add(1)) {
|
||||
results.push({
|
||||
@@ -314,7 +322,7 @@ export class Erc721TieredDrop implements DetectableFeature {
|
||||
|
||||
public async claimWithSignature(
|
||||
signedPayload: TieredDropPayloadWithSignature,
|
||||
): Promise<TransactionResult> {
|
||||
): Promise<TransactionResultWithId<NFT>[]> {
|
||||
const message = await this.mapPayloadToContractStruct(
|
||||
signedPayload.payload,
|
||||
);
|
||||
@@ -338,9 +346,22 @@ export class Erc721TieredDrop implements DetectableFeature {
|
||||
[message, signedPayload.signature],
|
||||
overrides,
|
||||
);
|
||||
const event = this.contractWrapper.parseLogs<TokensClaimedEvent>(
|
||||
"TokensClaimed",
|
||||
receipt?.logs,
|
||||
);
|
||||
const startingIndex = event[0].args.startTokenId;
|
||||
const endingIndex = startingIndex.add(event[0].args.quantityClaimed);
|
||||
const results: TransactionResultWithId<NFT>[] = [];
|
||||
for (let id = startingIndex; id.lt(endingIndex); id = id.add(1)) {
|
||||
results.push({
|
||||
id,
|
||||
receipt,
|
||||
data: () => this.erc721.get(id),
|
||||
});
|
||||
}
|
||||
|
||||
// TODO: Listen for TokensClaimed event once it gets emitted
|
||||
return { receipt };
|
||||
return results;
|
||||
}
|
||||
|
||||
private async mapPayloadToContractStruct(
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { hasFunction } from "../../common";
|
||||
import { normalizePriceValue, setErc20Allowance } from "../../common/currency";
|
||||
import { uploadOrExtractURIs } from "../../common/nft";
|
||||
import { FEATURE_NFT_SIGNATURE_MINTABLE } from "../../constants/erc721-features";
|
||||
import { FEATURE_NFT_SIGNATURE_MINTABLE_V2 } from "../../constants/erc721-features";
|
||||
import {
|
||||
MintRequest721,
|
||||
MintRequest721withQuantity,
|
||||
@@ -30,7 +30,7 @@ import invariant from "tiny-invariant";
|
||||
* @public
|
||||
*/
|
||||
export class Erc721WithQuantitySignatureMintable implements DetectableFeature {
|
||||
featureName = FEATURE_NFT_SIGNATURE_MINTABLE.name;
|
||||
featureName = FEATURE_NFT_SIGNATURE_MINTABLE_V2.name;
|
||||
|
||||
private contractWrapper: ContractWrapper<SignatureMintERC721 | TokenERC721>;
|
||||
|
||||
|
||||
@@ -12,14 +12,14 @@ import {
|
||||
FEATURE_NFT,
|
||||
FEATURE_NFT_BATCH_MINTABLE,
|
||||
FEATURE_NFT_BURNABLE,
|
||||
FEATURE_NFT_CLAIMABLE,
|
||||
FEATURE_NFT_CLAIMABLE_WITH_CONDITIONS_V2,
|
||||
FEATURE_NFT_CLAIM_CUSTOM,
|
||||
FEATURE_NFT_CLAIM_CONDITIONS_V2,
|
||||
FEATURE_NFT_LAZY_MINTABLE,
|
||||
FEATURE_NFT_MINTABLE,
|
||||
FEATURE_NFT_REVEALABLE,
|
||||
FEATURE_NFT_SIGNATURE_MINTABLE,
|
||||
FEATURE_NFT_SUPPLY,
|
||||
FEATURE_NFT_TIERED_DROP,
|
||||
FEATURE_NFT_SIGNATURE_MINTABLE_V2,
|
||||
} from "../../constants/erc721-features";
|
||||
import { BaseDropERC721, BaseERC721 } from "../../types/eips";
|
||||
import { ClaimOptions, UploadProgressEvent } from "../../types/index";
|
||||
@@ -600,7 +600,7 @@ export class Erc721<
|
||||
if (claim) {
|
||||
return claim.to(destinationAddress, quantity, options);
|
||||
}
|
||||
throw new ExtensionNotImplementedError(FEATURE_NFT_CLAIMABLE);
|
||||
throw new ExtensionNotImplementedError(FEATURE_NFT_CLAIM_CUSTOM);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -627,7 +627,7 @@ export class Erc721<
|
||||
if (claim) {
|
||||
return claim.getClaimTransaction(destinationAddress, quantity, options);
|
||||
}
|
||||
throw new ExtensionNotImplementedError(FEATURE_NFT_CLAIMABLE);
|
||||
throw new ExtensionNotImplementedError(FEATURE_NFT_CLAIM_CUSTOM);
|
||||
}
|
||||
|
||||
public async totalClaimedSupply(): Promise<BigNumber> {
|
||||
@@ -687,7 +687,7 @@ export class Erc721<
|
||||
get claimConditions() {
|
||||
return assertEnabled(
|
||||
this.lazyMintable?.claimWithConditions,
|
||||
FEATURE_NFT_CLAIMABLE_WITH_CONDITIONS_V2,
|
||||
FEATURE_NFT_CLAIM_CONDITIONS_V2,
|
||||
).conditions;
|
||||
}
|
||||
|
||||
@@ -721,7 +721,7 @@ export class Erc721<
|
||||
get signature() {
|
||||
return assertEnabled(
|
||||
this.signatureMintable,
|
||||
FEATURE_NFT_SIGNATURE_MINTABLE,
|
||||
FEATURE_NFT_SIGNATURE_MINTABLE_V2,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -861,7 +861,11 @@ export class Erc721<
|
||||
if (
|
||||
detectContractFeature<ISignatureMintERC721>(
|
||||
this.contractWrapper,
|
||||
"ERC721SignatureMint",
|
||||
"ERC721SignatureMintV1",
|
||||
) ||
|
||||
detectContractFeature<ISignatureMintERC721>(
|
||||
this.contractWrapper,
|
||||
"ERC721SignatureMintV2",
|
||||
)
|
||||
) {
|
||||
return new Erc721WithQuantitySignatureMintable(
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
import { CONTRACT_ADDRESSES, SUPPORTED_CHAIN_IDS } from "../../constants";
|
||||
import {
|
||||
CONTRACT_ADDRESSES,
|
||||
getApprovedImplementation,
|
||||
SUPPORTED_CHAIN_IDS,
|
||||
} from "../../constants";
|
||||
import {
|
||||
EditionDropInitializer,
|
||||
EditionInitializer,
|
||||
@@ -150,7 +154,15 @@ export class ContractFactory extends ContractWrapper<TWFactory> {
|
||||
return events[0].args.proxy;
|
||||
}
|
||||
|
||||
private async getDeployArguments<TContractType extends PrebuiltContractType>(
|
||||
/**
|
||||
*
|
||||
* @param contractType
|
||||
* @param metadata
|
||||
* @param contractURI
|
||||
* @returns
|
||||
* @internal
|
||||
*/
|
||||
public async getDeployArguments<TContractType extends PrebuiltContractType>(
|
||||
contractType: TContractType,
|
||||
metadata: z.input<DeploySchemaForPrebuiltContractType<TContractType>>,
|
||||
contractURI: string,
|
||||
@@ -301,6 +313,19 @@ export class ContractFactory extends ContractWrapper<TWFactory> {
|
||||
version?: number,
|
||||
) {
|
||||
const encodedType = ethers.utils.formatBytes32String(contract.name);
|
||||
const chainId = await this.getChainID();
|
||||
const approvedImplementation = getApprovedImplementation(
|
||||
chainId,
|
||||
contract.contractType,
|
||||
);
|
||||
// return approved implementation if it exists and we're not overriding the version
|
||||
if (
|
||||
approvedImplementation &&
|
||||
approvedImplementation.length > 0 &&
|
||||
version === undefined
|
||||
) {
|
||||
return approvedImplementation;
|
||||
}
|
||||
return this.readContract.getImplementation(
|
||||
encodedType,
|
||||
version !== undefined
|
||||
|
||||
@@ -139,10 +139,31 @@ export class UserWallet {
|
||||
* const address = await sdk.wallet.getAddress();
|
||||
* ```
|
||||
*/
|
||||
async getAddress(): Promise<string> {
|
||||
public async getAddress(): Promise<string> {
|
||||
return await this.requireWallet().getAddress();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the currently connected wallet's chainId
|
||||
* @internal
|
||||
*/
|
||||
public async getChainId(): Promise<number> {
|
||||
return await this.requireWallet().getChainId();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether there's a signer connected with the SDK
|
||||
* @internal
|
||||
*/
|
||||
public isConnected(): boolean {
|
||||
try {
|
||||
this.requireWallet();
|
||||
return true;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sign any message with the connected wallet private key
|
||||
* @param message - the message to sign
|
||||
@@ -157,7 +178,7 @@ export class UserWallet {
|
||||
* const signature = await sdk.wallet.sign(message);
|
||||
* ```
|
||||
*/
|
||||
async sign(message: string): Promise<string> {
|
||||
public async sign(message: string): Promise<string> {
|
||||
const signer = this.requireWallet();
|
||||
return await signer.signMessage(message);
|
||||
}
|
||||
@@ -187,7 +208,7 @@ export class UserWallet {
|
||||
* Send a raw transaction to the blockchain from the connected wallet
|
||||
* @param transactionRequest - raw transaction data to send to the blockchain
|
||||
*/
|
||||
async sendRawTransaction(
|
||||
public async sendRawTransaction(
|
||||
transactionRequest: providers.TransactionRequest,
|
||||
): Promise<TransactionResult> {
|
||||
const signer = this.requireWallet();
|
||||
|
||||
@@ -29,7 +29,7 @@ export * from "./constants";
|
||||
export * from "./contracts";
|
||||
|
||||
// export integration things
|
||||
export * from "./integrations/checkout";
|
||||
export * from "./integrations/thirdweb-checkout";
|
||||
|
||||
// explcitly export the *TYPES* of prebuilt contracts
|
||||
export type { Edition } from "./contracts/prebuilt-implementations/edition";
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@ import { ContractWrapper } from "../core/classes/contract-wrapper";
|
||||
import { SignedPayload721WithQuantitySignature } from "../schema/contracts/common/signature";
|
||||
import { PrebuiltEditionDrop, PrebuiltNFTDrop } from "../types/eips";
|
||||
import { SignatureDrop } from "@thirdweb-dev/contracts-js/dist/declarations/src/SignatureDrop";
|
||||
import fetch from "cross-fetch";
|
||||
// import fetch from "cross-fetch";
|
||||
import invariant from "tiny-invariant";
|
||||
|
||||
const PAPER_API_BASE = `https://paper.xyz/api` as const;
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,5 @@
|
||||
import { AddressSchema, AmountSchema } from "../../shared";
|
||||
import { AmountSchema } from "../../../../core/schema/shared";
|
||||
import { AddressSchema } from "../../shared";
|
||||
import { z } from "zod";
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
import { QuantitySchema } from "../../../../core/schema/shared";
|
||||
import {
|
||||
AmountSchema,
|
||||
BytesLikeSchema,
|
||||
QuantitySchema,
|
||||
} from "../../../../core/schema/shared";
|
||||
import { NATIVE_TOKEN_ADDRESS } from "../../../constants/currency";
|
||||
import {
|
||||
BigNumberishSchema,
|
||||
BigNumberSchema,
|
||||
BytesLikeSchema,
|
||||
AmountSchema,
|
||||
StartDateSchema,
|
||||
} from "../../shared";
|
||||
import { CurrencyValueSchema } from "./currency";
|
||||
@@ -12,6 +14,15 @@ import { SnapshotInputSchema } from "./snapshots";
|
||||
import { BigNumber, BigNumberish, utils } from "ethers";
|
||||
import { z } from "zod";
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export const ClaimConditionMetadataSchema = z
|
||||
.object({
|
||||
name: z.string().optional(),
|
||||
})
|
||||
.catchall(z.unknown());
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
@@ -24,7 +35,7 @@ export const ClaimConditionInputSchema = z.object({
|
||||
waitInSeconds: BigNumberishSchema.default(0),
|
||||
merkleRootHash: BytesLikeSchema.default(utils.hexZeroPad([0], 32)),
|
||||
snapshot: z.optional(SnapshotInputSchema).nullable(),
|
||||
metadata: z.union([z.string(), z.object({})]).optional(),
|
||||
metadata: ClaimConditionMetadataSchema.optional(),
|
||||
});
|
||||
|
||||
/**
|
||||
@@ -55,7 +66,6 @@ export const ClaimConditionOutputSchema = ClaimConditionInputSchema.extend({
|
||||
waitInSeconds: BigNumberSchema,
|
||||
startTime: BigNumberSchema.transform((n) => new Date(n.toNumber() * 1000)),
|
||||
snapshot: SnapshotInputSchema.optional().nullable(),
|
||||
metadata: z.string().optional(),
|
||||
});
|
||||
|
||||
export type AbstractClaimConditionContractStruct = {
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import {
|
||||
AddressSchema,
|
||||
BasisPointsSchema,
|
||||
FileOrBufferOrStringSchema,
|
||||
} from "../../shared";
|
||||
} from "../../../../core/schema/shared";
|
||||
import { AddressSchema } from "../../shared";
|
||||
import { constants } from "ethers";
|
||||
import { z } from "zod";
|
||||
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
import { NFTInputOrUriSchema } from "../../../../core/schema/nft";
|
||||
import {
|
||||
AmountSchema,
|
||||
BasisPointsSchema,
|
||||
} from "../../../../core/schema/shared";
|
||||
import { resolveOrGenerateId } from "../../../common/signature-minting";
|
||||
import { NATIVE_TOKEN_ADDRESS } from "../../../constants/currency";
|
||||
import {
|
||||
BasisPointsSchema,
|
||||
BigNumberishSchema,
|
||||
BigNumberSchema,
|
||||
EndDateSchema,
|
||||
AmountSchema,
|
||||
StartDateSchema,
|
||||
} from "../../shared";
|
||||
import { constants } from "ethers";
|
||||
|
||||
@@ -13,8 +13,10 @@ export const MerkleSchema = z.object({
|
||||
export const SnapshotEntryInput = z.object({
|
||||
address: AddressSchema,
|
||||
maxClaimable: QuantitySchema.default(0), // defaults to 0
|
||||
price: QuantitySchema, // defaults to unlimited
|
||||
currencyAddress: AddressSchema.default(ethers.constants.AddressZero),
|
||||
price: QuantitySchema.optional(), // defaults to unlimited, but can be undefined in old snapshots
|
||||
currencyAddress: AddressSchema.default(
|
||||
ethers.constants.AddressZero,
|
||||
).optional(), // defaults to AddressZero, but can be undefined for old snapshots
|
||||
});
|
||||
|
||||
export type SnapshotEntry = z.output<typeof SnapshotEntryInput>;
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { FileOrBufferOrStringSchema } from "../../../core/schema/shared";
|
||||
import { toSemver } from "../../common/index";
|
||||
import {
|
||||
AddressSchema,
|
||||
BigNumberishSchema,
|
||||
BigNumberTransformSchema,
|
||||
FileOrBufferOrStringSchema,
|
||||
} from "../shared";
|
||||
import {
|
||||
CommonContractOutputSchema,
|
||||
@@ -96,6 +96,7 @@ export const AbiObjectSchema = z
|
||||
* @internal
|
||||
*/
|
||||
export const AbiSchema = z.array(AbiObjectSchema);
|
||||
export type Abi = z.input<typeof AbiSchema>;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
@@ -154,6 +155,17 @@ export const ExtraPublishMetadataSchemaInput = z
|
||||
isDeployableViaFactory: z.boolean().optional(),
|
||||
isDeployableViaProxy: z.boolean().optional(),
|
||||
factoryDeploymentData: FactoryDeploymentSchema.optional(),
|
||||
constructorParams: z
|
||||
.record(
|
||||
z.string(),
|
||||
z
|
||||
.object({
|
||||
displayName: z.string().optional(),
|
||||
description: z.string().optional(),
|
||||
})
|
||||
.catchall(z.any()),
|
||||
)
|
||||
.optional(),
|
||||
})
|
||||
.catchall(z.any());
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { AddressSchema, BasisPointsSchema } from "../shared";
|
||||
import { BasisPointsSchema } from "../../../core/schema/shared";
|
||||
import { AddressSchema } from "../shared";
|
||||
import {
|
||||
CommonContractOutputSchema,
|
||||
CommonContractSchema,
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { BasisPointsSchema, BigNumberSchema } from "../shared";
|
||||
import { BasisPointsSchema } from "../../../core/schema/shared";
|
||||
import { BigNumberSchema } from "../shared";
|
||||
import { BaseSignaturePayloadInput } from "./common";
|
||||
import { constants } from "ethers";
|
||||
import { z } from "zod";
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
import {
|
||||
AddressSchema,
|
||||
BigNumberishSchema,
|
||||
BigNumberSchema,
|
||||
PercentSchema,
|
||||
} from "../shared";
|
||||
import { PercentSchema } from "../../../core/schema/shared";
|
||||
import { AddressSchema, BigNumberishSchema, BigNumberSchema } from "../shared";
|
||||
import {
|
||||
CommonContractOutputSchema,
|
||||
CommonContractSchema,
|
||||
|
||||
@@ -1,34 +1,6 @@
|
||||
import { BigNumber, CallOverrides, utils } from "ethers";
|
||||
import { z } from "zod";
|
||||
|
||||
const isBrowser = () => typeof window !== "undefined";
|
||||
const FileOrBufferUnionSchema = isBrowser()
|
||||
? (z.instanceof(File) as z.ZodType<InstanceType<typeof File>>)
|
||||
: (z.instanceof(Buffer) as z.ZodTypeAny); // @fixme, this is a hack to make browser happy for now
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export const FileOrBufferSchema = z.union([
|
||||
FileOrBufferUnionSchema,
|
||||
z.object({
|
||||
data: z.union([FileOrBufferUnionSchema, z.string()]),
|
||||
name: z.string(),
|
||||
}),
|
||||
]);
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export const FileOrBufferOrStringSchema = z.union([
|
||||
FileOrBufferSchema,
|
||||
z.string(),
|
||||
]);
|
||||
|
||||
export const MAX_BPS = 10000;
|
||||
|
||||
export const BytesLikeSchema = z.union([z.array(z.number()), z.string()]);
|
||||
|
||||
export const BigNumberSchema = z
|
||||
.union([
|
||||
z.string(),
|
||||
@@ -55,16 +27,6 @@ export const BigNumberTransformSchema = z
|
||||
return BigNumber.from(arg).toString();
|
||||
});
|
||||
|
||||
export const BasisPointsSchema = z
|
||||
.number()
|
||||
.max(MAX_BPS, "Cannot exceed 100%")
|
||||
.min(0, "Cannot be below 0%");
|
||||
|
||||
export const PercentSchema = z
|
||||
.number()
|
||||
.max(100, "Cannot exceed 100%")
|
||||
.min(0, "Cannot be below 0%");
|
||||
|
||||
export const AddressSchema = z.string().refine(
|
||||
(arg) => utils.isAddress(arg),
|
||||
(out) => {
|
||||
@@ -74,13 +36,6 @@ export const AddressSchema = z.string().refine(
|
||||
},
|
||||
);
|
||||
|
||||
export const AmountSchema = z
|
||||
.union([
|
||||
z.string().regex(/^([0-9]+\.?[0-9]*|\.[0-9]+)$/, "Invalid amount"),
|
||||
z.number().min(0, "Amount cannot be negative"),
|
||||
])
|
||||
.transform((arg) => (typeof arg === "number" ? arg.toString() : arg));
|
||||
|
||||
export const RawDateSchema = z.date().transform((i) => {
|
||||
return BigNumber.from(Math.floor(i.getTime() / 1000));
|
||||
});
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { AddressSchema, BigNumberishSchema, AmountSchema } from "../../shared";
|
||||
import { AmountSchema } from "../../../../core/schema/shared";
|
||||
import { AddressSchema, BigNumberishSchema } from "../../shared";
|
||||
import { z } from "zod";
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { NFTInputOrUriSchema } from "../../../core/schema/nft";
|
||||
import { BigNumberishSchema, AmountSchema, RawDateSchema } from "../shared";
|
||||
import { AmountSchema } from "../../../core/schema/shared";
|
||||
import { BigNumberishSchema, RawDateSchema } from "../shared";
|
||||
import {
|
||||
ERC1155WrappableSchema,
|
||||
ERC20WrappableSchema,
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { AddressSchema, AmountSchema } from "../shared";
|
||||
import { AmountSchema } from "../../../core/schema/shared";
|
||||
import { AddressSchema } from "../shared";
|
||||
import { z } from "zod";
|
||||
|
||||
/**
|
||||
|
||||
@@ -56,6 +56,8 @@ export type ClaimVerification = {
|
||||
maxClaimable: BigNumber;
|
||||
price: BigNumber;
|
||||
currencyAddress: string;
|
||||
priceInProof: BigNumber;
|
||||
currencyAddressInProof: string;
|
||||
};
|
||||
|
||||
export type ClaimConditionsForToken = {
|
||||
|
||||
@@ -2,11 +2,11 @@
|
||||
* Currency metadata.
|
||||
* @public
|
||||
*/
|
||||
import { AmountSchema } from "../../core/schema/shared";
|
||||
import {
|
||||
CurrencySchema,
|
||||
CurrencyValueSchema,
|
||||
} from "../schema/contracts/common/currency";
|
||||
import { AmountSchema } from "../schema/shared";
|
||||
import { z } from "zod";
|
||||
|
||||
/**
|
||||
|
||||
@@ -37,8 +37,11 @@ export type ContractEvent<TEvent = Record<string, any>> = {
|
||||
/**
|
||||
* Filters for querying past events
|
||||
*/
|
||||
export interface EventQueryFilter {
|
||||
export interface EventQueryOptions<
|
||||
TFilter extends Record<string, any> = Record<string, any>,
|
||||
> {
|
||||
fromBlock?: string | number;
|
||||
toBlock?: string | number;
|
||||
order?: "asc" | "desc";
|
||||
filters?: TFilter;
|
||||
}
|
||||
|
||||
@@ -8,7 +8,9 @@ import {
|
||||
METAPLEX_PROGRAM_ID,
|
||||
} from "../../constants/addresses";
|
||||
import { TransactionResult } from "../../types/common";
|
||||
import { CreatorOutput } from "../../types/programs";
|
||||
import { getPublicRpc } from "../../utils/urls";
|
||||
import { parseCreators } from "./creators-helper";
|
||||
import {
|
||||
findMasterEditionV2Pda,
|
||||
GmaBuilder,
|
||||
@@ -46,13 +48,17 @@ export class NFTHelper {
|
||||
this.connection = metaplex.connection;
|
||||
}
|
||||
|
||||
async get(nftAddress: string): Promise<NFT> {
|
||||
const meta = await this.metaplex
|
||||
async getRaw(nftAddress: string) {
|
||||
return await this.metaplex
|
||||
.nfts()
|
||||
.findByMint({
|
||||
mintAddress: new PublicKey(nftAddress),
|
||||
})
|
||||
.run();
|
||||
}
|
||||
|
||||
async get(nftAddress: string): Promise<NFT> {
|
||||
const meta = await this.getRaw(nftAddress);
|
||||
return await this.toNFTMetadata(meta);
|
||||
}
|
||||
|
||||
@@ -75,6 +81,11 @@ export class NFTHelper {
|
||||
};
|
||||
}
|
||||
|
||||
async creatorsOf(nftAddress: string): Promise<CreatorOutput[]> {
|
||||
const meta = await this.getRaw(nftAddress);
|
||||
return parseCreators(meta.creators);
|
||||
}
|
||||
|
||||
async balanceOf(walletAddress: string, nftAddress: string): Promise<number> {
|
||||
const address = await getAssociatedTokenAddress(
|
||||
new PublicKey(nftAddress),
|
||||
@@ -253,10 +264,7 @@ export class NFTHelper {
|
||||
let mint = "mint" in meta ? meta.mint : undefined;
|
||||
let fullModel = meta;
|
||||
if (meta.model === "metadata") {
|
||||
fullModel = await this.metaplex
|
||||
.nfts()
|
||||
.findByMint({ mintAddress: meta.mintAddress })
|
||||
.run();
|
||||
fullModel = await this.getRaw(meta.mintAddress.toBase58());
|
||||
mint = fullModel.mint;
|
||||
}
|
||||
if (!mint) {
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import { QueryAllParams } from "../../core/schema/QueryParams";
|
||||
import { NFT, NFTMetadata, NFTMetadataOrUri } from "../../core/schema/nft";
|
||||
import { Amount } from "../../core/schema/shared";
|
||||
import {
|
||||
enforceCreator,
|
||||
parseCreators,
|
||||
} from "../classes/helpers/creators-helper";
|
||||
import { NFTHelper } from "../classes/helpers/nft-helper";
|
||||
import { Amount, TransactionResult } from "../types/common";
|
||||
import { TransactionResult } from "../types/common";
|
||||
import { CreatorInput, CreatorOutput } from "../types/programs";
|
||||
import { sendMultipartTransaction } from "../utils/transactions";
|
||||
import { getNework } from "../utils/urls";
|
||||
@@ -15,6 +16,7 @@ import {
|
||||
toBigNumber,
|
||||
toNftOriginalEdition,
|
||||
toOriginalEditionAccount,
|
||||
TransactionBuilder,
|
||||
} from "@metaplex-foundation/js";
|
||||
import { PublicKey } from "@solana/web3.js";
|
||||
import { ThirdwebStorage } from "@thirdweb-dev/storage";
|
||||
@@ -294,12 +296,14 @@ export class NFTCollection {
|
||||
: await this.storage.upload(metadata);
|
||||
const name =
|
||||
typeof metadata === "string" ? "" : metadata.name?.toString() || "";
|
||||
const collection = await this.getCollection();
|
||||
const { nft } = await this.metaplex
|
||||
.nfts()
|
||||
.create({
|
||||
name,
|
||||
uri,
|
||||
sellerFeeBasisPoints: 0,
|
||||
creators: collection.creators,
|
||||
sellerFeeBasisPoints: collection.sellerFeeBasisPoints,
|
||||
collection: this.publicKey,
|
||||
collectionAuthority: this.metaplex.identity(),
|
||||
tokenOwner: new PublicKey(to),
|
||||
@@ -426,35 +430,131 @@ export class NFTCollection {
|
||||
/**
|
||||
* 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
|
||||
.nfts()
|
||||
.update({
|
||||
nftOrSft: await this.getCollection(),
|
||||
creators: enforceCreator(creators, this.metaplex.identity().publicKey),
|
||||
})
|
||||
.run();
|
||||
return {
|
||||
signature: tx.response.signature,
|
||||
};
|
||||
async updateCreators(
|
||||
creators: CreatorInput[],
|
||||
updateAll: boolean = false,
|
||||
): Promise<TransactionResult[]> {
|
||||
if (updateAll) {
|
||||
const txs: TransactionBuilder[] = [];
|
||||
|
||||
txs.push(
|
||||
this.metaplex
|
||||
.nfts()
|
||||
.builders()
|
||||
.update({
|
||||
nftOrSft: await this.getCollection(),
|
||||
creators: enforceCreator(
|
||||
creators,
|
||||
this.metaplex.identity().publicKey,
|
||||
),
|
||||
}),
|
||||
);
|
||||
|
||||
// TODO: Don't use a get all here, all we need is mint addresses :(
|
||||
const allNfts = await this.nft.getAll(this.publicKey.toBase58());
|
||||
await Promise.all(
|
||||
allNfts.map(async (nft) => {
|
||||
const metaplexNft = await this.metaplex
|
||||
.nfts()
|
||||
.findByMint({ mintAddress: new PublicKey(nft.metadata.id) })
|
||||
.run();
|
||||
|
||||
txs.push(
|
||||
this.metaplex
|
||||
.nfts()
|
||||
.builders()
|
||||
.update({
|
||||
collection: this.publicKey,
|
||||
nftOrSft: metaplexNft,
|
||||
creators: enforceCreator(
|
||||
creators,
|
||||
this.metaplex.identity().publicKey,
|
||||
),
|
||||
}),
|
||||
);
|
||||
}),
|
||||
);
|
||||
|
||||
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();
|
||||
|
||||
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
|
||||
.nfts()
|
||||
.update({
|
||||
nftOrSft: await this.getCollection(),
|
||||
sellerFeeBasisPoints,
|
||||
})
|
||||
.run();
|
||||
return {
|
||||
signature: tx.response.signature,
|
||||
};
|
||||
async updateRoyalty(
|
||||
sellerFeeBasisPoints: number,
|
||||
updateAll: boolean = false,
|
||||
) {
|
||||
if (updateAll) {
|
||||
const txs: TransactionBuilder[] = [];
|
||||
|
||||
txs.push(
|
||||
this.metaplex
|
||||
.nfts()
|
||||
.builders()
|
||||
.update({
|
||||
nftOrSft: await this.getCollection(),
|
||||
sellerFeeBasisPoints,
|
||||
}),
|
||||
);
|
||||
|
||||
// TODO: Don't use a get all here, all we need is mint addresses :(
|
||||
const allNfts = await this.nft.getAll(this.publicKey.toBase58());
|
||||
await Promise.all(
|
||||
allNfts.map(async (nft) => {
|
||||
const metaplexNft = await this.metaplex
|
||||
.nfts()
|
||||
.findByMint({ mintAddress: new PublicKey(nft.metadata.id) })
|
||||
.run();
|
||||
|
||||
txs.push(
|
||||
this.metaplex.nfts().builders().update({
|
||||
collection: this.publicKey,
|
||||
nftOrSft: metaplexNft,
|
||||
sellerFeeBasisPoints,
|
||||
}),
|
||||
);
|
||||
}),
|
||||
);
|
||||
|
||||
return await sendMultipartTransaction(txs, this.metaplex);
|
||||
} else {
|
||||
const tx = await this.metaplex
|
||||
.nfts()
|
||||
.update({
|
||||
nftOrSft: await this.getCollection(),
|
||||
sellerFeeBasisPoints,
|
||||
})
|
||||
.run();
|
||||
|
||||
return [
|
||||
{
|
||||
signature: tx.response.signature,
|
||||
},
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
private async getCollection() {
|
||||
|
||||
@@ -4,13 +4,14 @@ import {
|
||||
NFTMetadata,
|
||||
NFTMetadataInput,
|
||||
} from "../../core/schema/nft";
|
||||
import { Amount } from "../../core/schema/shared";
|
||||
import { ClaimConditions } from "../classes/claim-conditions";
|
||||
import {
|
||||
enforceCreator,
|
||||
parseCreators,
|
||||
} from "../classes/helpers/creators-helper";
|
||||
import { NFTHelper } from "../classes/helpers/nft-helper";
|
||||
import { Amount, TransactionResult } from "../types/common";
|
||||
import { TransactionResult } from "../types/common";
|
||||
import { CreatorInput, CreatorOutput } from "../types/programs";
|
||||
import { sendMultipartTransaction } from "../utils/transactions";
|
||||
import { getNework } from "../utils/urls";
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { Amount, AmountSchema } from "../../core/schema/shared";
|
||||
import { CurrencyValue, TokenMetadata } from "../../core/schema/token";
|
||||
import { Amount, AmountSchema, TransactionResult } from "../types/common";
|
||||
import { TransactionResult } from "../types/common";
|
||||
import { toCurrencyValue } from "../utils/token";
|
||||
import { getNework } from "../utils/urls";
|
||||
import {
|
||||
|
||||
@@ -2,52 +2,6 @@ import { Signer, WalletAdapter } from "@metaplex-foundation/js";
|
||||
import { PublicKey } from "@solana/web3.js";
|
||||
import { z } from "zod";
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export const MAX_BPS = 10000;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export const BasisPointsSchema = z
|
||||
.number()
|
||||
.max(MAX_BPS, "Cannot exceed 100%")
|
||||
.min(0, "Cannot be below 0%");
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export const PercentSchema = z
|
||||
.number()
|
||||
.max(100, "Cannot exceed 100%")
|
||||
.min(0, "Cannot be below 0%");
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export const JsonLiteral = z.union([
|
||||
z.string(),
|
||||
z.number(),
|
||||
z.boolean(),
|
||||
z.null(),
|
||||
]);
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export type JsonLiteral = number | string | null | boolean;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export type Json = JsonLiteral | JsonObject | Json[];
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export type JsonObject = { [key: string]: Json };
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
@@ -60,16 +14,6 @@ export const OptionalPropertiesInput = z
|
||||
.union([z.array(PropertiesInput), PropertiesInput])
|
||||
.optional();
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export const AmountSchema = z
|
||||
.union([
|
||||
z.string().regex(/^([0-9]+\.?[0-9]*|\.[0-9]+)$/, "Invalid amount"),
|
||||
z.number().min(0, "Amount cannot be negative"),
|
||||
])
|
||||
.transform((arg) => (typeof arg === "number" ? arg.toString() : arg));
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
@@ -77,11 +21,6 @@ export const RawDateSchema = z.date().transform((i) => {
|
||||
return Math.floor(i.getTime() / 1000);
|
||||
});
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export type Amount = z.input<typeof AmountSchema>;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
@@ -115,27 +54,3 @@ export const AddressSchema = z.union([
|
||||
z.string(),
|
||||
z.instanceof(PublicKey).transform((key) => key.toBase58()),
|
||||
]);
|
||||
|
||||
const isBrowser = () => typeof window !== "undefined";
|
||||
const FileOrBufferUnionSchema = isBrowser()
|
||||
? (z.instanceof(File) as z.ZodType<InstanceType<typeof File>>)
|
||||
: (z.instanceof(Buffer) as z.ZodTypeAny); // @fixme, this is a hack to make browser happy for now
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export const FileOrBufferSchema = z.union([
|
||||
FileOrBufferUnionSchema,
|
||||
z.object({
|
||||
data: z.union([FileOrBufferUnionSchema, z.string()]),
|
||||
name: z.string(),
|
||||
}),
|
||||
]);
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export const FileOrBufferOrStringSchema = z.union([
|
||||
FileOrBufferSchema,
|
||||
z.string(),
|
||||
]);
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
import { AmountSchema, FileOrBufferOrStringSchema, PercentSchema } from "../common";
|
||||
import {
|
||||
AmountSchema,
|
||||
FileOrBufferOrStringSchema,
|
||||
PercentSchema,
|
||||
} from "../../../core/schema/shared";
|
||||
import { Creator } from "@metaplex-foundation/js";
|
||||
import { z } from "zod";
|
||||
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
import { NFTCollectionMetadataInputSchema } from ".";
|
||||
import { BasisPointsSchema, QuantitySchema } from "../../../core/schema/shared";
|
||||
import {
|
||||
AmountSchema,
|
||||
BasisPointsSchema,
|
||||
QuantitySchema,
|
||||
} from "../../../core/schema/shared";
|
||||
import { CurrencyValueSchema } from "../../../core/schema/token";
|
||||
import { AmountSchema } from "../common";
|
||||
import { z } from "zod";
|
||||
|
||||
/**
|
||||
|
||||
@@ -275,7 +275,7 @@ describe("Custom Contracts", async () => {
|
||||
{
|
||||
startTime: new Date(new Date().getTime() - 1000 * 60 * 60),
|
||||
price: 0,
|
||||
maxQuantity: 10,
|
||||
maxClaimableSupply: 10,
|
||||
},
|
||||
]);
|
||||
|
||||
|
||||
@@ -64,11 +64,13 @@ describe("Edition Drop Contract (V4)", async () => {
|
||||
await bdContract.claimConditions.set(0, [
|
||||
{
|
||||
startTime: new Date(Date.now() / 2),
|
||||
maxClaimablePerWallet: 1,
|
||||
snapshot: [bobWallet.address, samWallet.address, abbyWallet.address],
|
||||
price: 1,
|
||||
},
|
||||
{
|
||||
startTime: new Date(),
|
||||
maxClaimablePerWallet: 1,
|
||||
snapshot: [bobWallet.address],
|
||||
},
|
||||
]);
|
||||
@@ -147,6 +149,7 @@ describe("Edition Drop Contract (V4)", async () => {
|
||||
await bdContract.claimConditions.set("0", [
|
||||
{
|
||||
maxClaimableSupply: 1000,
|
||||
maxClaimablePerWallet: 1,
|
||||
snapshot: members,
|
||||
},
|
||||
]);
|
||||
@@ -257,6 +260,7 @@ describe("Edition Drop Contract (V4)", async () => {
|
||||
]);
|
||||
await bdContract.claimConditions.set(0, [
|
||||
{
|
||||
maxClaimablePerWallet: 0,
|
||||
snapshot: [
|
||||
{ address: w1.address, maxClaimable: 2 },
|
||||
{ address: w2.address, maxClaimable: 1 },
|
||||
@@ -273,6 +277,24 @@ describe("Edition Drop Contract (V4)", async () => {
|
||||
}
|
||||
});
|
||||
|
||||
it("should not allow setting a claim condition where no one can claim", async () => {
|
||||
await bdContract.createBatch([{ name: "test", description: "test" }]);
|
||||
|
||||
try {
|
||||
await bdContract.claimConditions.set(0, [
|
||||
{
|
||||
maxClaimablePerWallet: 0,
|
||||
snapshot: [adminWallet.address, bobWallet.address],
|
||||
},
|
||||
]);
|
||||
assert.fail(
|
||||
"should not allow setting a claim condition where no one can claim",
|
||||
);
|
||||
} catch (e) {
|
||||
expectError(e, "no one can claim");
|
||||
}
|
||||
});
|
||||
|
||||
it("should allow a default claim condition to be used to claim", async () => {
|
||||
await bdContract.createBatch([
|
||||
{
|
||||
@@ -555,6 +577,7 @@ describe("Edition Drop Contract (V4)", async () => {
|
||||
await bdContract.claimConditions.set("0", [
|
||||
{
|
||||
maxClaimableSupply: 1,
|
||||
maxClaimablePerWallet: 1,
|
||||
snapshot: [w1.address],
|
||||
},
|
||||
]);
|
||||
@@ -634,6 +657,7 @@ describe("Edition Drop Contract (V4)", async () => {
|
||||
await bdContract.claimConditions.set("0", [
|
||||
{
|
||||
maxClaimableSupply: 10,
|
||||
maxClaimablePerWallet: 1,
|
||||
price: "100",
|
||||
currencyAddress: NATIVE_TOKEN_ADDRESS,
|
||||
snapshot: [w1.address, w2.address, w3.address],
|
||||
@@ -676,6 +700,7 @@ describe("Edition Drop Contract (V4)", async () => {
|
||||
|
||||
await bdContract.claimConditions.set(0, [
|
||||
{
|
||||
maxClaimablePerWallet: 1,
|
||||
snapshot: [samWallet.address],
|
||||
},
|
||||
]);
|
||||
@@ -725,12 +750,14 @@ describe("Edition Drop Contract (V4)", async () => {
|
||||
|
||||
await bdContract.claimConditions.set("1", [
|
||||
{
|
||||
maxClaimablePerWallet: 1,
|
||||
snapshot: [w1.address, w2.address, bobWallet.address],
|
||||
},
|
||||
]);
|
||||
|
||||
await bdContract.claimConditions.set("2", [
|
||||
{
|
||||
maxClaimablePerWallet: 1,
|
||||
snapshot: [w3.address, w1.address, w2.address, adminWallet.address],
|
||||
},
|
||||
]);
|
||||
|
||||
@@ -49,6 +49,149 @@ describe("NFT Drop Contract (v4)", async () => {
|
||||
dropContract = await sdk.getNFTDrop(address);
|
||||
});
|
||||
|
||||
it("comprehensive test", async () => {
|
||||
const metadata = [];
|
||||
for (let i = 0; i < 10; i++) {
|
||||
metadata.push({ name: `test${i}`, description: `desc${i}` });
|
||||
}
|
||||
await dropContract.createBatch(metadata);
|
||||
// claiming with default conditions
|
||||
await dropContract.claimConditions.set([{}]);
|
||||
await dropContract.claim(1);
|
||||
// claiming with max supply
|
||||
await dropContract.claimConditions.set([
|
||||
{
|
||||
maxClaimableSupply: 2,
|
||||
},
|
||||
]);
|
||||
try {
|
||||
await dropContract.claim(2);
|
||||
expect.fail("should not be able to claim 2 - maxSupply");
|
||||
} catch (e) {
|
||||
expectError(e, "!MaxSupply");
|
||||
}
|
||||
await dropContract.claim(1);
|
||||
// claiming with max per wallet
|
||||
await dropContract.claimConditions.set(
|
||||
[
|
||||
{
|
||||
maxClaimablePerWallet: 1,
|
||||
},
|
||||
],
|
||||
true,
|
||||
);
|
||||
try {
|
||||
await dropContract.claim(2);
|
||||
expect.fail("should not be able to claim 2 - maxClaimablePerWallet");
|
||||
} catch (e) {
|
||||
expectError(e, "!Qty");
|
||||
}
|
||||
await dropContract.claim(1);
|
||||
expect((await dropContract.totalClaimedSupply()).toString()).eq("3");
|
||||
});
|
||||
|
||||
it("comprehensive test with allowlist and price override", async () => {
|
||||
const metadata = [];
|
||||
for (let i = 0; i < 10; i++) {
|
||||
metadata.push({ name: `test${i}`, description: `desc${i}` });
|
||||
}
|
||||
await dropContract.createBatch(metadata);
|
||||
// claiming with default conditions
|
||||
await dropContract.claimConditions.set([
|
||||
{
|
||||
maxClaimablePerWallet: 0,
|
||||
price: 0.1,
|
||||
snapshot: [
|
||||
{ address: adminWallet.address, maxClaimable: 1, price: 0.1 },
|
||||
],
|
||||
},
|
||||
]);
|
||||
console.log(
|
||||
await dropContract.claimConditions.getClaimIneligibilityReasons(1),
|
||||
);
|
||||
await dropContract.claim(1);
|
||||
});
|
||||
|
||||
it("comprehensive test with allowlist", async () => {
|
||||
const metadata = [];
|
||||
for (let i = 0; i < 10; i++) {
|
||||
metadata.push({ name: `test${i}`, description: `desc${i}` });
|
||||
}
|
||||
await dropContract.createBatch(metadata);
|
||||
// claiming with default conditions
|
||||
await dropContract.claimConditions.set([
|
||||
{
|
||||
maxClaimablePerWallet: 0,
|
||||
snapshot: [{ address: adminWallet.address, maxClaimable: 1 }],
|
||||
},
|
||||
]);
|
||||
try {
|
||||
sdk.updateSignerOrProvider(bobWallet);
|
||||
await dropContract.claim(1);
|
||||
expect.fail("should not be able to claim - not in allowlist");
|
||||
} catch (e) {
|
||||
expectError(e, "!Qty");
|
||||
}
|
||||
sdk.updateSignerOrProvider(adminWallet);
|
||||
await dropContract.claim(1);
|
||||
|
||||
// // claiming with max supply
|
||||
await dropContract.claimConditions.set([
|
||||
{
|
||||
maxClaimablePerWallet: 0,
|
||||
snapshot: [{ address: adminWallet.address, maxClaimable: 10 }],
|
||||
maxClaimableSupply: 2,
|
||||
},
|
||||
]);
|
||||
try {
|
||||
await dropContract.claim(2);
|
||||
expect.fail("should not be able to claim - maxClaimableSupply");
|
||||
} catch (e) {
|
||||
expectError(e, "!MaxSupply");
|
||||
}
|
||||
await dropContract.claim(1);
|
||||
// claiming with max per wallet
|
||||
await dropContract.claimConditions.set(
|
||||
[
|
||||
{
|
||||
snapshot: [adminWallet.address],
|
||||
maxClaimablePerWallet: 1,
|
||||
},
|
||||
],
|
||||
true,
|
||||
);
|
||||
try {
|
||||
await dropContract.claim(2);
|
||||
expect.fail("should not be able to claim - maxClaimablePerWallet");
|
||||
} catch (e) {
|
||||
expectError(e, "!Qty");
|
||||
}
|
||||
await dropContract.claim(1);
|
||||
// claiming with max per wallet in snapshot
|
||||
await dropContract.claimConditions.set(
|
||||
[
|
||||
{
|
||||
snapshot: [{ address: adminWallet.address, maxClaimable: 1 }],
|
||||
maxClaimablePerWallet: 0,
|
||||
},
|
||||
],
|
||||
true,
|
||||
);
|
||||
try {
|
||||
await dropContract.claim(2);
|
||||
expect.fail("should not be able to claim - proof maxClaimable");
|
||||
} catch (e) {
|
||||
expectError(e, "!Qty");
|
||||
}
|
||||
await dropContract.claim(1);
|
||||
try {
|
||||
await dropContract.claim(1);
|
||||
expect.fail("should not be able to claim - proof used");
|
||||
} catch (e) {
|
||||
expectError(e, "!Qty");
|
||||
}
|
||||
});
|
||||
|
||||
it("should lazy mint with URI", async () => {
|
||||
const uri = await storage.upload({
|
||||
name: "Test1",
|
||||
@@ -59,8 +202,25 @@ describe("NFT Drop Contract (v4)", async () => {
|
||||
assert.equal(nft.metadata.name, "Test1");
|
||||
});
|
||||
|
||||
it("should upload and resolve claim condition metadata", async () => {
|
||||
const uri = await storage.upload({
|
||||
name: "Test1",
|
||||
});
|
||||
await dropContract.createBatch([uri]);
|
||||
await dropContract.claimConditions.set([
|
||||
{
|
||||
metadata: {
|
||||
name: "Test",
|
||||
description: "Description",
|
||||
},
|
||||
},
|
||||
]);
|
||||
const condition = await dropContract.claimConditions.getActive();
|
||||
expect(condition.metadata?.name).to.equal("Test");
|
||||
});
|
||||
|
||||
it("should respect global maxClaimable per wallet with default snapshot", async () => {
|
||||
const metadata = [];
|
||||
const metadata: NFTMetadataInput[] = [];
|
||||
for (let i = 0; i < 10; i++) {
|
||||
metadata.push({ name: `test${i}`, description: `desc${i}` });
|
||||
}
|
||||
@@ -101,11 +261,13 @@ describe("NFT Drop Contract (v4)", async () => {
|
||||
await dropContract.claimConditions.set([
|
||||
{
|
||||
startTime: new Date(Date.now() / 2),
|
||||
maxClaimablePerWallet: 1,
|
||||
snapshot: [bobWallet.address, samWallet.address, abbyWallet.address],
|
||||
price: 1,
|
||||
},
|
||||
{
|
||||
startTime: new Date(),
|
||||
maxClaimablePerWallet: 1,
|
||||
snapshot: [bobWallet.address],
|
||||
},
|
||||
]);
|
||||
@@ -126,7 +288,7 @@ describe("NFT Drop Contract (v4)", async () => {
|
||||
const proof = await dropContract.claimConditions.getClaimerProofs(
|
||||
bobWallet.address,
|
||||
);
|
||||
expect(proof.address).to.eq(bobWallet.address);
|
||||
expect(proof?.address).to.eq(bobWallet.address);
|
||||
});
|
||||
|
||||
it("should return snapshot data on claim conditions", async () => {
|
||||
@@ -137,6 +299,7 @@ describe("NFT Drop Contract (v4)", async () => {
|
||||
|
||||
await dropContract.claimConditions.set([
|
||||
{
|
||||
maxClaimablePerWallet: 1,
|
||||
snapshot: [samWallet.address],
|
||||
},
|
||||
]);
|
||||
@@ -153,10 +316,12 @@ describe("NFT Drop Contract (v4)", async () => {
|
||||
{
|
||||
startTime: new Date(),
|
||||
waitInSeconds: 10,
|
||||
maxClaimablePerWallet: 1,
|
||||
snapshot: [bobWallet.address, samWallet.address, abbyWallet.address],
|
||||
},
|
||||
{
|
||||
startTime: new Date(Date.now() + 60 * 60 * 1000),
|
||||
maxClaimablePerWallet: 1,
|
||||
snapshot: [bobWallet.address],
|
||||
},
|
||||
]);
|
||||
@@ -229,12 +394,31 @@ describe("NFT Drop Contract (v4)", async () => {
|
||||
}
|
||||
});
|
||||
|
||||
it("should not allow setting a claim condition where no one can claim", async () => {
|
||||
await dropContract.createBatch([{ name: "test", description: "test" }]);
|
||||
|
||||
try {
|
||||
await dropContract.claimConditions.set([
|
||||
{
|
||||
maxClaimablePerWallet: 0,
|
||||
snapshot: [adminWallet.address, bobWallet.address],
|
||||
},
|
||||
]);
|
||||
assert.fail(
|
||||
"should not allow setting a claim condition where no one can claim",
|
||||
);
|
||||
} catch (e) {
|
||||
expectError(e, "no one can claim");
|
||||
}
|
||||
});
|
||||
|
||||
it("allow one address in the merkle tree to claim", async () => {
|
||||
const testWallets: SignerWithAddress[] = [bobWallet];
|
||||
const members = testWallets.map((w) => w.address);
|
||||
|
||||
await dropContract.claimConditions.set([
|
||||
{
|
||||
maxClaimablePerWallet: 1,
|
||||
snapshot: members,
|
||||
},
|
||||
]);
|
||||
@@ -544,6 +728,7 @@ describe("NFT Drop Contract (v4)", async () => {
|
||||
await dropContract.claimConditions.set([
|
||||
{
|
||||
maxClaimableSupply: 10,
|
||||
maxClaimablePerWallet: 1,
|
||||
price: "100",
|
||||
currencyAddress: NATIVE_TOKEN_ADDRESS,
|
||||
snapshot: [w1.address, w2.address, w3.address],
|
||||
@@ -569,7 +754,7 @@ describe("NFT Drop Contract (v4)", async () => {
|
||||
await dropContract.claimConditions.set([
|
||||
{
|
||||
maxClaimablePerWallet: 0,
|
||||
snapshot: [w1.address],
|
||||
snapshot: [{ address: w1.address, maxClaimable: 1 }],
|
||||
},
|
||||
]);
|
||||
|
||||
|
||||
@@ -9,7 +9,6 @@ import { AddressZero } from "@ethersproject/constants";
|
||||
import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers";
|
||||
import {
|
||||
DropERC721__factory,
|
||||
DropERC721_V3__factory,
|
||||
TokenERC721__factory,
|
||||
} from "@thirdweb-dev/contracts-js";
|
||||
import { ThirdwebStorage } from "@thirdweb-dev/storage";
|
||||
@@ -85,10 +84,7 @@ describe("Publishing", async () => {
|
||||
|
||||
// Drop
|
||||
expect(
|
||||
isFeatureEnabled(
|
||||
DropERC721__factory.abi,
|
||||
"ERC721ClaimableWithConditionsV2",
|
||||
),
|
||||
isFeatureEnabled(DropERC721__factory.abi, "ERC721ClaimPhasesV2"),
|
||||
).to.eq(true);
|
||||
expect(isFeatureEnabled(DropERC721__factory.abi, "ERC721Supply")).to.eq(
|
||||
true,
|
||||
@@ -96,14 +92,6 @@ describe("Publishing", async () => {
|
||||
expect(isFeatureEnabled(DropERC721__factory.abi, "ERC721Mintable")).to.eq(
|
||||
false,
|
||||
);
|
||||
|
||||
// Drop legacy
|
||||
expect(
|
||||
isFeatureEnabled(
|
||||
DropERC721_V3__factory.abi,
|
||||
"ERC721ClaimableWithConditionsV1",
|
||||
),
|
||||
).to.eq(true);
|
||||
});
|
||||
|
||||
it("should update bio", async () => {
|
||||
|
||||
@@ -486,6 +486,7 @@ describe("Signature drop tests (v5)", async () => {
|
||||
|
||||
await signatureDropContract.claimConditions.set([
|
||||
{
|
||||
maxClaimablePerWallet: 1,
|
||||
snapshot: [samWallet.address],
|
||||
},
|
||||
]);
|
||||
@@ -500,6 +501,7 @@ describe("Signature drop tests (v5)", async () => {
|
||||
await signatureDropContract.claimConditions.set([
|
||||
{
|
||||
startTime: new Date(),
|
||||
maxClaimablePerWallet: 1,
|
||||
snapshot: [bobWallet.address, samWallet.address, abbyWallet.address],
|
||||
},
|
||||
]);
|
||||
@@ -715,6 +717,7 @@ describe("Signature drop tests (v5)", async () => {
|
||||
]);
|
||||
await signatureDropContract.claimConditions.set([
|
||||
{
|
||||
maxClaimablePerWallet: 0,
|
||||
snapshot: [
|
||||
{ address: w1.address, maxClaimable: 2 },
|
||||
{ address: w2.address, maxClaimable: 1 },
|
||||
|
||||
@@ -13,7 +13,7 @@ describe("Tiered Drop Contract", async () => {
|
||||
async function deployTieredDrop() {
|
||||
// This needs to match the release for the currently used ABI
|
||||
const releaseUri =
|
||||
"ipfs://QmTK2dpcDMiePacs6bNh6LhQdPB9RkxXHmx9CtrPLPRBuS/0";
|
||||
"ipfs://QmXu9ezFNgXBX1juLZ7kwdf5KpTD1x9GPHnk14QB2NpUvK/0";
|
||||
const address = await sdk.deployer.deployContractFromUri(releaseUri, [], {
|
||||
forceDirectDeploy: true,
|
||||
});
|
||||
@@ -103,7 +103,10 @@ describe("Tiered Drop Contract", async () => {
|
||||
assert.isTrue(isValid);
|
||||
|
||||
sdk.updateSignerOrProvider(claimerWallet);
|
||||
await contract.erc721.tieredDrop.claimWithSignature(signedPayload);
|
||||
const txs = await contract.erc721.tieredDrop.claimWithSignature(
|
||||
signedPayload,
|
||||
);
|
||||
expect((await txs[0].data()).metadata.name).to.equal("NFT #1");
|
||||
});
|
||||
|
||||
it("Should get tokens in tier", async () => {
|
||||
|
||||
+10
-1
@@ -13,7 +13,7 @@ import invariant from "tiny-invariant";
|
||||
|
||||
global.fetch = require("cross-fetch");
|
||||
|
||||
describe("Token Drop Contract (v3)", async () => {
|
||||
describe("Token Drop Contract (v4)", async () => {
|
||||
let dropContract: TokenDrop;
|
||||
let adminWallet: SignerWithAddress,
|
||||
samWallet: SignerWithAddress,
|
||||
@@ -49,11 +49,13 @@ describe("Token Drop Contract (v3)", async () => {
|
||||
await dropContract.claimConditions.set([
|
||||
{
|
||||
startTime: new Date(Date.now() / 2),
|
||||
maxClaimablePerWallet: 1,
|
||||
snapshot: [bobWallet.address, samWallet.address, abbyWallet.address],
|
||||
price: 1,
|
||||
},
|
||||
{
|
||||
startTime: new Date(),
|
||||
maxClaimablePerWallet: 1,
|
||||
snapshot: [bobWallet.address],
|
||||
},
|
||||
]);
|
||||
@@ -77,6 +79,7 @@ describe("Token Drop Contract (v3)", async () => {
|
||||
it("should return snapshot data on claim conditions", async () => {
|
||||
await dropContract.claimConditions.set([
|
||||
{
|
||||
maxClaimablePerWallet: 1,
|
||||
snapshot: [samWallet.address],
|
||||
},
|
||||
]);
|
||||
@@ -93,10 +96,12 @@ describe("Token Drop Contract (v3)", async () => {
|
||||
{
|
||||
startTime: new Date(),
|
||||
waitInSeconds: 10,
|
||||
maxClaimablePerWallet: 1,
|
||||
snapshot: [bobWallet.address, samWallet.address, abbyWallet.address],
|
||||
},
|
||||
{
|
||||
startTime: new Date(Date.now() + 60 * 60 * 1000),
|
||||
maxClaimablePerWallet: 1,
|
||||
snapshot: [bobWallet.address],
|
||||
},
|
||||
]);
|
||||
@@ -141,6 +146,7 @@ describe("Token Drop Contract (v3)", async () => {
|
||||
);
|
||||
await dropContract.claimConditions.set([
|
||||
{
|
||||
maxClaimablePerWallet: 2.1,
|
||||
snapshot: members,
|
||||
},
|
||||
]);
|
||||
@@ -159,6 +165,7 @@ describe("Token Drop Contract (v3)", async () => {
|
||||
|
||||
await dropContract.claimConditions.set([
|
||||
{
|
||||
maxClaimablePerWallet: 1,
|
||||
snapshot: members,
|
||||
},
|
||||
]);
|
||||
@@ -220,6 +227,7 @@ describe("Token Drop Contract (v3)", async () => {
|
||||
it("should allow setting max claims per wallet", async () => {
|
||||
await dropContract.claimConditions.set([
|
||||
{
|
||||
maxClaimablePerWallet: 0,
|
||||
snapshot: [
|
||||
{ address: w1.address, maxClaimable: "2.1" },
|
||||
{ address: w2.address, maxClaimable: 1 },
|
||||
@@ -344,6 +352,7 @@ describe("Token Drop Contract (v3)", async () => {
|
||||
await dropContract.claimConditions.set([
|
||||
{
|
||||
maxClaimableSupply: 10,
|
||||
maxClaimablePerWallet: 1,
|
||||
price: "100",
|
||||
currencyAddress: NATIVE_TOKEN_ADDRESS,
|
||||
snapshot: [w1.address, w2.address, w3.address],
|
||||
@@ -12,6 +12,12 @@ describe("NFTCollection", async () => {
|
||||
name: "Test Collection",
|
||||
description: "Test Description",
|
||||
symbol: "TC",
|
||||
creators: [
|
||||
{
|
||||
address: sdk.wallet.getAddress() || "",
|
||||
share: 100,
|
||||
},
|
||||
],
|
||||
});
|
||||
collection = await sdk.getNFTCollection(addr);
|
||||
});
|
||||
@@ -25,6 +31,7 @@ describe("NFTCollection", async () => {
|
||||
expect(nft.metadata.name).to.eq("Test NFT");
|
||||
expect(nft.owner).to.eq(sdk.wallet.getAddress());
|
||||
expect(nft.supply).to.eq(1);
|
||||
expect(nft.metadata);
|
||||
});
|
||||
|
||||
it("should fetch NFTs", async () => {
|
||||
@@ -142,10 +149,16 @@ describe("NFTCollection", async () => {
|
||||
expect(creators[0].share).to.equal(100);
|
||||
|
||||
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);
|
||||
@@ -153,13 +166,36 @@ describe("NFTCollection", 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 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);
|
||||
}
|
||||
});
|
||||
|
||||
it("Should update royalty", async () => {
|
||||
let royalty = await collection.getRoyalty();
|
||||
expect(royalty).to.equal(0);
|
||||
await collection.updateRoyalty(100);
|
||||
|
||||
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);
|
||||
|
||||
await collection.updateRoyalty(100, true);
|
||||
|
||||
royalty = await collection.getRoyalty();
|
||||
expect(royalty).to.equal(100);
|
||||
|
||||
// @ts-ignore
|
||||
nft = await collection.nft.getRaw(mintAddress);
|
||||
expect(nft.sellerFeeBasisPoints).to.equal(100);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
{
|
||||
"extends": "@thirdweb-dev/tsconfig/sdk.json",
|
||||
"include": ["src", "types"],
|
||||
"exclude": ["dist", "build", "node_modules"]
|
||||
"exclude": ["dist", "build", "node_modules"],
|
||||
"compilerOptions": {
|
||||
"allowJs": true
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user