Skip to content

Commit 867f277

Browse files
committed
update
1 parent 5398cb4 commit 867f277

File tree

2 files changed

+70
-14
lines changed
  • apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/_components/claim-conditions/claim-conditions-form

2 files changed

+70
-14
lines changed

apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/_components/claim-conditions/claim-conditions-form/hooks.ts

Lines changed: 46 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import {
22
type BaseTransactionOptions,
33
type ThirdwebClient,
44
toTokens,
5+
toUnits,
56
} from "thirdweb";
67
import type { OverrideEntry } from "thirdweb/dist/types/utils/extensions/drops/types";
78
import type { Prettify } from "thirdweb/dist/types/utils/type-utils";
@@ -42,6 +43,7 @@ type CombinedClaimCondition = Prettify<
4243
type Options =
4344
| {
4445
type: "erc20";
46+
decimals?: number;
4547
}
4648
| {
4749
type: "erc721";
@@ -91,12 +93,24 @@ export async function getClaimPhasesInLegacyFormat(
9193
startTime: new Date(Number(condition.startTimestamp * 1000n)),
9294
currencyAddress: condition.currency,
9395
price: condition.pricePerToken,
94-
maxClaimableSupply: toUnlimited(condition.maxClaimableSupply),
96+
// This value from ERC20Ext.getClaimConditions is in wei
97+
// so we have to convert it using toTokens for readability
98+
// (when user updates this value, we convert it back to wei - see `function setClaimPhasesTx`)
99+
maxClaimableSupply: toUnlimited(
100+
condition.maxClaimableSupply,
101+
options.type === "erc20" ? currencyMetadata.decimals : undefined,
102+
),
95103
currencyMetadata,
96104
currentMintSupply: (
97105
condition.maxClaimableSupply - condition.supplyClaimed
98106
).toString(),
99-
maxClaimablePerWallet: toUnlimited(condition.quantityLimitPerWallet),
107+
// This value from ERC20Ext.getClaimConditions is in wei
108+
// so we have to convert it using toTokens for readability
109+
// (when user updates this value, we convert it back to wei - see `function setClaimPhasesTx`)
110+
maxClaimablePerWallet: toUnlimited(
111+
condition.quantityLimitPerWallet,
112+
options.type === "erc20" ? currencyMetadata.decimals : undefined,
113+
),
100114
merkleRootHash: condition.merkleRoot,
101115
metadata,
102116
snapshot,
@@ -114,8 +128,18 @@ export function setClaimPhasesTx(
114128
const phases = rawPhases.map((phase) => {
115129
return {
116130
startTime: toDate(phase.startTime),
117-
maxClaimableSupply: toBigInt(phase.maxClaimableSupply),
118-
maxClaimablePerWallet: toBigInt(phase.maxClaimablePerWallet),
131+
// The input from client-side is non-wei, but the extension is expecting value in wei
132+
// so we need to convert it using toUnits
133+
maxClaimableSupply: toBigInt(
134+
phase.maxClaimableSupply,
135+
baseOptions.type === "erc20" ? baseOptions.decimals : undefined,
136+
),
137+
// The input from client-side is non-wei, but the ERC20 extension is expecting value in wei
138+
// so we need to convert it using toUnits
139+
maxClaimablePerWallet: toBigInt(
140+
phase.maxClaimablePerWallet,
141+
baseOptions.type === "erc20" ? baseOptions.decimals : undefined,
142+
),
119143
merkleRootHash: phase.merkleRootHash as string | undefined,
120144
overrideList: phase.snapshot?.length
121145
? snapshotToOverrides(phase.snapshot)
@@ -175,18 +199,33 @@ function toDate(timestamp: number | Date | undefined) {
175199
}
176200
return new Date(timestamp);
177201
}
178-
function toBigInt(value: string | number | undefined) {
202+
function toBigInt(
203+
value: string | number | undefined,
204+
decimals?: number,
205+
): bigint | undefined {
179206
if (value === undefined) {
180207
return undefined;
181208
}
182209
if (value === "unlimited") {
183210
return maxUint256;
184211
}
212+
// The ERC20Claim condition extension in v5 does not convert to wei for us
213+
// so we have to, manually
214+
if (decimals) {
215+
return toUnits(value.toString(), decimals);
216+
}
217+
185218
return BigInt(value);
186219
}
187220

188-
function toUnlimited(value: bigint) {
189-
return value === maxUint256 ? "unlimited" : value.toString();
221+
function toUnlimited(value: bigint, decimals?: number) {
222+
if (value === maxUint256) {
223+
return "unlimited";
224+
}
225+
if (decimals) {
226+
return toTokens(value, decimals);
227+
}
228+
return value.toString();
190229
}
191230

192231
async function fetchSnapshot(

apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/_components/claim-conditions/claim-conditions-form/index.tsx

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import {
2626
useFieldArray,
2727
useForm,
2828
} from "react-hook-form";
29+
import { toast } from "sonner";
2930
import {
3031
NATIVE_TOKEN_ADDRESS,
3132
type ThirdwebContract,
@@ -152,7 +153,7 @@ interface ClaimsConditionFormContextData {
152153
field: ControlledField;
153154
phaseIndex: number;
154155
formDisabled: boolean;
155-
tokenDecimals: number;
156+
tokenDecimals: number | undefined;
156157
isMultiPhase: boolean;
157158
isActive: boolean;
158159
dropType: DropType;
@@ -210,7 +211,6 @@ export const ClaimConditionsForm: React.FC<ClaimConditionsFormProps> = ({
210211
enabled: isErc20,
211212
},
212213
});
213-
const tokenDecimalsData = tokenDecimals.data ?? 0;
214214
const saveClaimPhaseNotification = useTxNotifications(
215215
"Saved claim phases",
216216
"Failed to save claim phases",
@@ -219,7 +219,7 @@ export const ClaimConditionsForm: React.FC<ClaimConditionsFormProps> = ({
219219
const claimConditionsQuery = useReadContract(getClaimPhasesInLegacyFormat, {
220220
contract,
221221
...(isErc20
222-
? { type: "erc20" }
222+
? { type: "erc20", decimals: tokenDecimals.data }
223223
: isErc721
224224
? { type: "erc721" }
225225
: { type: "erc1155", tokenId: BigInt(tokenId || 0) }),
@@ -259,7 +259,11 @@ export const ClaimConditionsForm: React.FC<ClaimConditionsFormProps> = ({
259259
);
260260
}, [claimConditionsQuery.data, isMultiPhase]);
261261

262-
const isFetchingData = claimConditionsQuery.isFetching || sendTx.isPending;
262+
const isFetchingData =
263+
claimConditionsQuery.isFetching ||
264+
sendTx.isPending ||
265+
// Need to make sure the tokenDecimals.data is present when interacting with ERC20 claim conditions
266+
(isErc20 && tokenDecimals.isLoading);
263267

264268
const canEditForm = isAdmin && !isFetchingData;
265269

@@ -353,13 +357,17 @@ export const ClaimConditionsForm: React.FC<ClaimConditionsFormProps> = ({
353357
action: "set-claim-conditions",
354358
label: "attempt",
355359
});
356-
360+
if (isErc20 && !tokenDecimals.data) {
361+
return toast.error(
362+
`Could not fetch token decimals for contract ${contract.address}`,
363+
);
364+
}
357365
try {
358366
const tx = setClaimPhasesTx(
359367
{
360368
contract,
361369
...(isErc20
362-
? { type: "erc20" }
370+
? { type: "erc20", decimals: tokenDecimals.data }
363371
: isErc721
364372
? { type: "erc721" }
365373
: { type: "erc1155", tokenId: BigInt(tokenId || 0) }),
@@ -453,6 +461,15 @@ export const ClaimConditionsForm: React.FC<ClaimConditionsFormProps> = ({
453461
);
454462
}
455463

464+
// Do not proceed if fails to load the tokenDecimals.data - for ERC20 drop contracts specifically
465+
if (isErc20 && tokenDecimals.data === undefined) {
466+
return (
467+
<div className="flex h-[400px] w-full items-center justify-center rounded-lg border border-border">
468+
Failed to load token decimals
469+
</div>
470+
);
471+
}
472+
456473
return (
457474
<>
458475
<Flex onSubmit={handleFormSubmit} direction="column" as="form" gap={10}>
@@ -508,7 +525,7 @@ export const ClaimConditionsForm: React.FC<ClaimConditionsFormProps> = ({
508525
phaseIndex: index,
509526
formDisabled: !canEditForm,
510527
isErc20,
511-
tokenDecimals: tokenDecimalsData,
528+
tokenDecimals: tokenDecimals.data,
512529
dropType,
513530
setOpenSnapshotIndex,
514531
isAdmin,

0 commit comments

Comments
 (0)