Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/blue-geese-refuse.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"thirdweb": patch
---

Single phase functionality for erc1155
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ export async function getClaimPhasesInLegacyFormat(
type PhaseInput = z.input<typeof LegacyClaimConditionInputSchema>;

export function setClaimPhasesTx(
baseOptions: BaseTransactionOptions<Options>,
baseOptions: BaseTransactionOptions<Options> & { isSinglePhase?: boolean },
rawPhases: PhaseInput[],
) {
const phases = rawPhases.map((phase) => {
Expand Down Expand Up @@ -172,6 +172,7 @@ export function setClaimPhasesTx(
contract: baseOptions.contract,
phases,
tokenId: baseOptions.tokenId,
singlePhaseDrop: baseOptions.isSinglePhase,
});
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,10 @@ export const ClaimConditionsForm: React.FC<ClaimConditionsFormProps> = ({
? { type: "erc20", decimals: tokenDecimals.data }
: isErc721
? { type: "erc721" }
: { type: "erc1155", tokenId: BigInt(tokenId || 0) }),
: {
type: "erc1155",
tokenId: BigInt(tokenId || 0),
}),
});

const transformedQueryData = useMemo(() => {
Expand Down Expand Up @@ -370,6 +373,7 @@ export const ClaimConditionsForm: React.FC<ClaimConditionsFormProps> = ({
const tx = setClaimPhasesTx(
{
contract,
isSinglePhase: !isMultiPhase,
...(isErc20
? { type: "erc20", decimals: tokenDecimals.data }
: isErc721
Expand Down Expand Up @@ -635,6 +639,7 @@ export const ClaimConditionsForm: React.FC<ClaimConditionsFormProps> = ({
isErc20={isErc20}
contract={contract}
tokenId={tokenId}
isMultiphase={isMultiPhase}
/>
)}
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,15 @@ interface ClaimConditionsProps {
isColumn?: true;
isERC20: boolean;
twAccount: Account | undefined;
isMultiphase: boolean;
}
export const ClaimConditions: React.FC<ClaimConditionsProps> = ({
contract,
tokenId,
isColumn,
isERC20,
twAccount,
isMultiphase,
}) => {
return (
<div className="flex w-full flex-col gap-6">
Expand All @@ -37,8 +39,7 @@ export const ClaimConditions: React.FC<ClaimConditionsProps> = ({
contract={contract}
tokenId={tokenId}
isColumn={isColumn}
// always multi phase!
isMultiPhase={true}
isMultiPhase={isMultiphase}
/>
</div>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,15 @@ interface ResetClaimEligibilityProps {
contract: ThirdwebContract;
tokenId?: string;
twAccount: Account | undefined;
isMultiphase: boolean;
}

export const ResetClaimEligibility: React.FC<ResetClaimEligibilityProps> = ({
contract,
tokenId,
isErc20,
twAccount,
isMultiphase,
}) => {
const trackEvent = useTrack();

Expand Down Expand Up @@ -55,6 +57,7 @@ export const ResetClaimEligibility: React.FC<ResetClaimEligibilityProps> = ({
return ERC1155Ext.resetClaimEligibility({
contract,
tokenId: BigInt(tokenId),
singlePhaseDrop: !isMultiphase,
});
}
// assume erc 721
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ export function ClaimConditionsClient(props: {
contract={props.contract}
isERC20={supportedERCs.isERC20}
twAccount={props.twAccount}
isMultiphase={true}
/>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ export default async function Page(props: {
contract={contract}
isERC20={supportedERCs.isERC20}
twAccount={account}
isMultiphase={true}
/>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,6 @@ export function useNFTDrawerTabs({
const hasERC1155ClaimConditions = (() => {
return [
// reads
ERC1155Ext.isGetClaimConditionByIdSupported(functionSelectors),
ERC1155Ext.isGetClaimConditionsSupported(functionSelectors),
ERC1155Ext.isGetActiveClaimConditionSupported(functionSelectors),
// writes
Expand All @@ -77,6 +76,10 @@ export function useNFTDrawerTabs({
].every(Boolean);
})();

const isERC1155Multiphase = (() => {
return ERC1155Ext.isGetClaimConditionByIdSupported(functionSelectors);
})();

const isBurnable = (() => {
if (isERC721) {
return ERC721Ext.isBurnSupported(functionSelectors);
Expand Down Expand Up @@ -130,6 +133,7 @@ export function useNFTDrawerTabs({
tokenId={tokenId}
isColumn
twAccount={twAccount}
isMultiphase={isERC1155Multiphase}
/>
),
},
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[
"function claim(address receiver, uint256 tokenId, uint256 quantity, address currency, uint256 pricePerToken, (bytes32[] proof, uint256 quantityLimitPerWallet, uint256 pricePerToken, address currency) allowlistProof, bytes data) payable",
"function setClaimConditions(uint256 tokenId, (uint256 startTimestamp, uint256 maxClaimableSupply, uint256 supplyClaimed, uint256 quantityLimitPerWallet, bytes32 merkleRoot, uint256 pricePerToken, address currency, string metadata) phase, bool resetClaimEligibility)",
"function claimCondition(uint256 tokenId) view returns ((uint256 startTimestamp, uint256 maxClaimableSupply, uint256 supplyClaimed, uint256 quantityLimitPerWallet, bytes32 merkleRoot, uint256 pricePerToken, address currency, string metadata) condition)",
"function claimCondition(uint256 tokenId) view returns (uint256 startTimestamp, uint256 maxClaimableSupply, uint256 supplyClaimed, uint256 quantityLimitPerWallet, bytes32 merkleRoot, uint256 pricePerToken, address currency, string metadata)",
"event ClaimConditionUpdated(uint256 indexed tokenId, (uint256 startTimestamp, uint256 maxClaimableSupply, uint256 supplyClaimed, uint256 quantityLimitPerWallet, bytes32 merkleRoot, uint256 pricePerToken, address currency, string metadata) condition, bool resetEligibility)",
"event TokensClaimed(address indexed claimer, address indexed receiver, uint256 indexed tokenId, uint256 quantityClaimed)"
]
1 change: 1 addition & 0 deletions packages/thirdweb/src/exports/extensions/erc1155.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ export {
type CanClaimParams,
type CanClaimResult,
} from "../../extensions/erc1155/drops/read/canClaim.js";
export { claimCondition } from "../../extensions/erc1155/__generated__/IDropSinglePhase1155/read/claimCondition.js";

// WRITE
export {
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

86 changes: 86 additions & 0 deletions packages/thirdweb/src/extensions/erc1155/customDrop1155.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,16 @@ import { TEST_CLIENT } from "../../../test/src/test-clients.js";
import {
TEST_ACCOUNT_B,
TEST_ACCOUNT_C,
TEST_ACCOUNT_D,
} from "../../../test/src/test-wallets.js";
import { type ThirdwebContract, getContract } from "../../contract/contract.js";
import { sendAndConfirmTransaction } from "../../transaction/actions/send-and-confirm-transaction.js";
import { deployContractfromDeployMetadata } from "../prebuilts/deploy-published.js";
import { balanceOf } from "./__generated__/IERC1155/read/balanceOf.js";
import { nextTokenIdToMint } from "./__generated__/IERC1155Enumerable/read/nextTokenIdToMint.js";
import { getClaimConditions } from "./drops/read/getClaimConditions.js";
import { claimTo } from "./drops/write/claimTo.js";
import { resetClaimEligibility } from "./drops/write/resetClaimEligibility.js";
import { setClaimConditions } from "./drops/write/setClaimConditions.js";
import { getNFT } from "./read/getNFT.js";
import { lazyMint } from "./write/lazyMint.js";
Expand Down Expand Up @@ -92,6 +95,14 @@ describe.runIf(process.env.TW_SECRET_KEY)(
}),
account: TEST_ACCOUNT_C,
});

const condition = await getClaimConditions({
contract,
tokenId: 0n,
});
expect(condition.length).to.eq(1);
expect(condition[0]?.maxClaimableSupply).to.eq(10n);

const claimTx = claimTo({
contract,
to: TEST_ACCOUNT_C.address,
Expand Down Expand Up @@ -166,5 +177,80 @@ describe.runIf(process.env.TW_SECRET_KEY)(
chainId: ${contract.chain.id}]
`);
});

it("should reset claim eligibility", async () => {
await sendAndConfirmTransaction({
transaction: setClaimConditions({
contract,
phases: [
{
startTime: new Date(0),
maxClaimableSupply: 10n,
maxClaimablePerWallet: 1n,
},
],
tokenId: 0n,
singlePhaseDrop: true,
}),
account: TEST_ACCOUNT_C,
});
// claim one token
const claimTx = claimTo({
contract,
to: TEST_ACCOUNT_D.address,
tokenId: 0n,
quantity: 1n,
singlePhaseDrop: true,
});
await sendAndConfirmTransaction({
transaction: claimTx,
account: TEST_ACCOUNT_D,
});
await expect(
balanceOf({ contract, owner: TEST_ACCOUNT_D.address, tokenId: 0n }),
).resolves.toBe(1n);

// attempt to claim another token (this should fail)
await expect(
sendAndConfirmTransaction({
transaction: claimTo({
tokenId: 0n,
contract,
to: TEST_ACCOUNT_D.address,
quantity: 1n,
}),
account: TEST_ACCOUNT_D,
}),
).rejects.toThrowErrorMatchingInlineSnapshot(`
[TransactionError: Error - !Qty

contract: ${contract.address}
chainId: ${contract.chain.id}]
`);

// reset claim eligibility
await sendAndConfirmTransaction({
transaction: resetClaimEligibility({
tokenId: 0n,
contract,
singlePhaseDrop: true,
}),
account: TEST_ACCOUNT_C,
});
// attempt to claim another token (this should succeed)
await sendAndConfirmTransaction({
transaction: claimTo({
tokenId: 0n,
contract,
to: TEST_ACCOUNT_D.address,
quantity: 1n,
}),
account: TEST_ACCOUNT_D,
});
// check that the account has claimed two tokens
await expect(
balanceOf({ tokenId: 0n, contract, owner: TEST_ACCOUNT_D.address }),
).resolves.toBe(2n);
});
},
);
Loading
Loading