1
1
import {
2
- Button ,
3
2
Center ,
4
3
ChakraProvider ,
4
+ ColorMode ,
5
5
Flex ,
6
6
Grid ,
7
7
Heading ,
@@ -24,21 +24,18 @@ import {
24
24
ThirdwebProvider ,
25
25
useActiveClaimCondition ,
26
26
useAddress ,
27
- useChainId ,
28
27
useClaimIneligibilityReasons ,
29
- useClaimNFT ,
30
- useEditionDrop ,
28
+ useContract ,
31
29
useNFT ,
32
30
useTotalCirculatingSupply ,
31
+ Web3Button ,
33
32
} from "@thirdweb-dev/react" ;
34
- import { EditionDrop } from "@thirdweb-dev/sdk" ;
35
- import { IpfsStorage } from "@thirdweb-dev/storage" ;
33
+ import { SmartContract } from "@thirdweb-dev/sdk/dist/declarations/src/contracts/smart-contract " ;
34
+ import { ThirdwebStorage } from "@thirdweb-dev/storage" ;
36
35
import { BigNumber } from "ethers" ;
37
36
import { formatUnits , parseUnits } from "ethers/lib/utils" ;
38
37
import React , { useEffect , useMemo , useRef , useState } from "react" ;
39
38
import { createRoot } from "react-dom/client" ;
40
- import { IoDiamondOutline } from "react-icons/io5" ;
41
- import { ConnectWalletButton } from "../shared/connect-wallet-button" ;
42
39
import { Footer } from "../shared/footer" ;
43
40
import { Header } from "../shared/header" ;
44
41
import { DropSvg } from "../shared/svg/drop" ;
@@ -48,22 +45,19 @@ import { parseIneligibility } from "../utils/parseIneligibility";
48
45
import { parseIpfsGateway } from "../utils/parseIpfsGateway" ;
49
46
50
47
interface ClaimPageProps {
51
- contract ?: EditionDrop ;
52
- expectedChainId : number ;
48
+ contract ?: SmartContract | null ;
53
49
tokenId : string ;
54
50
primaryColor : string ;
55
- secondaryColor : string ;
51
+ colorScheme : ColorMode ;
56
52
}
57
53
58
54
const ClaimButton : React . FC < ClaimPageProps > = ( {
59
55
contract,
60
- expectedChainId,
61
56
tokenId,
62
57
primaryColor,
63
- secondaryColor ,
58
+ colorScheme ,
64
59
} ) => {
65
60
const address = useAddress ( ) ;
66
- const chainId = useChainId ( ) ;
67
61
const [ quantity , setQuantity ] = useState ( 1 ) ;
68
62
const loaded = useRef ( false ) ;
69
63
const { data : totalSupply } = useTotalCirculatingSupply ( contract , tokenId ) ;
@@ -74,10 +68,6 @@ const ClaimButton: React.FC<ClaimPageProps> = ({
74
68
{ quantity, walletAddress : address || "" } ,
75
69
tokenId ,
76
70
) ;
77
- const claimMutation = useClaimNFT ( contract ) ;
78
-
79
- const isEnabled = ! ! contract && ! ! address && chainId === expectedChainId ;
80
-
81
71
const bnPrice = parseUnits (
82
72
activeClaimCondition . data ?. currencyMetadata . displayValue || "0" ,
83
73
activeClaimCondition . data ?. currencyMetadata . decimals ,
@@ -116,51 +106,29 @@ const ClaimButton: React.FC<ClaimPageProps> = ({
116
106
isNaN ( Number ( availableSupply ) ) ? 1000 : Number ( availableSupply ) ,
117
107
) ;
118
108
119
- const claim = async ( ) => {
120
- claimMutation . mutate (
121
- { to : address as string , tokenId, quantity } ,
122
- {
123
- onSuccess : ( ) => {
124
- toast ( {
125
- title : "Successfully claimed." ,
126
- status : "success" ,
127
- duration : 5000 ,
128
- isClosable : true ,
129
- } ) ;
130
- } ,
131
- onError : ( err ) => {
132
- console . error ( err ) ;
133
- toast ( {
134
- title : "Failed to claim drop." ,
135
- status : "error" ,
136
- duration : 9000 ,
137
- isClosable : true ,
138
- } ) ;
139
- } ,
140
- } ,
141
- ) ;
142
- } ;
143
-
144
109
const isLoading = claimIneligibilityReasons . isLoading && ! loaded . current ;
145
110
146
111
const canClaim =
147
112
! isSoldOut && ! ! address && ! claimIneligibilityReasons . data ?. length ;
148
113
149
- if ( ! isEnabled ) {
150
- return (
151
- < ConnectWalletButton
152
- expectedChainId = { expectedChainId }
153
- primaryColor = { primaryColor }
154
- secondaryColor = { secondaryColor }
155
- />
156
- ) ;
114
+ if ( ! contract ) {
115
+ return null ;
157
116
}
158
117
159
118
const maxQuantity = activeClaimCondition . data ?. maxQuantity ;
160
119
120
+ const colors = chakraTheme . colors ;
121
+ const accentColor = colors [ primaryColor as keyof typeof colors ] [ 500 ] ;
122
+
161
123
return (
162
124
< Stack spacing = { 4 } align = "center" w = "100%" >
163
- < Flex w = "100%" direction = { { base : "column" , sm : "row" } } gap = { 2 } >
125
+ < Flex
126
+ w = "100%"
127
+ direction = { { base : "column" , sm : "row" } }
128
+ gap = { 2 }
129
+ justifyContent = "center"
130
+ alignItems = "center"
131
+ >
164
132
< NumberInput
165
133
inputMode = "numeric"
166
134
value = { quantity }
@@ -183,14 +151,29 @@ const ClaimButton: React.FC<ClaimPageProps> = ({
183
151
</ NumberInputStepper >
184
152
</ NumberInput >
185
153
< LightMode >
186
- < Button
187
- isLoading = { isLoading || claimMutation . isLoading }
188
- isDisabled = { ! canClaim }
189
- leftIcon = { < IoDiamondOutline /> }
190
- onClick = { claim }
191
- w = "full"
192
- colorScheme = { primaryColor }
193
- fontSize = { { base : "label.md" , md : "label.lg" } }
154
+ < Web3Button
155
+ colorMode = { colorScheme }
156
+ contractAddress = { contract ?. getAddress ( ) }
157
+ isDisabled = { ! canClaim || isLoading }
158
+ action = { ( cntr ) => cntr . erc1155 . claim ( tokenId , quantity ) }
159
+ accentColor = { accentColor }
160
+ onError = { ( err ) => {
161
+ console . error ( err ) ;
162
+ toast ( {
163
+ title : "Failed to claim drop." ,
164
+ status : "error" ,
165
+ duration : 9000 ,
166
+ isClosable : true ,
167
+ } ) ;
168
+ } }
169
+ onSuccess = { ( ) => {
170
+ toast ( {
171
+ title : "Successfully claimed." ,
172
+ status : "success" ,
173
+ duration : 5000 ,
174
+ isClosable : true ,
175
+ } ) ;
176
+ } }
194
177
>
195
178
{ isSoldOut
196
179
? "Sold out"
@@ -208,7 +191,7 @@ const ClaimButton: React.FC<ClaimPageProps> = ({
208
191
: claimIneligibilityReasons . data ?. length
209
192
? parseIneligibility ( claimIneligibilityReasons . data , quantity )
210
193
: "Minting Unavailable" }
211
- </ Button >
194
+ </ Web3Button >
212
195
</ LightMode >
213
196
</ Flex >
214
197
{ activeClaimCondition . data && (
@@ -228,10 +211,9 @@ const ClaimButton: React.FC<ClaimPageProps> = ({
228
211
229
212
const ClaimPage : React . FC < ClaimPageProps > = ( {
230
213
contract,
231
- expectedChainId,
232
214
tokenId,
233
215
primaryColor,
234
- secondaryColor ,
216
+ colorScheme ,
235
217
} ) => {
236
218
const tokenMetadata = useNFT ( contract , tokenId ) ;
237
219
@@ -283,9 +265,8 @@ const ClaimPage: React.FC<ClaimPageProps> = ({
283
265
< ClaimButton
284
266
contract = { contract }
285
267
tokenId = { tokenId }
286
- expectedChainId = { expectedChainId }
287
268
primaryColor = { primaryColor }
288
- secondaryColor = { secondaryColor }
269
+ colorScheme = { colorScheme }
289
270
/>
290
271
</ Flex >
291
272
</ Center >
@@ -307,22 +288,18 @@ const Body: React.FC<BodyProps> = ({ children }) => {
307
288
interface EditionDropEmbedProps {
308
289
contractAddress : string ;
309
290
tokenId : string ;
310
- expectedChainId : number ;
311
- colorScheme : string ;
291
+ colorScheme : ColorMode ;
312
292
primaryColor : string ;
313
- secondaryColor : string ;
314
293
}
315
294
316
295
const EditionDropEmbed : React . FC < EditionDropEmbedProps > = ( {
317
296
contractAddress,
318
297
tokenId,
319
- expectedChainId,
320
298
colorScheme,
321
299
primaryColor,
322
- secondaryColor,
323
300
} ) => {
324
301
const { setColorMode } = useColorMode ( ) ;
325
- const editionDrop = useEditionDrop ( contractAddress ) ;
302
+ const { contract : editionDrop } = useContract ( contractAddress ) ;
326
303
327
304
useEffect ( ( ) => {
328
305
setColorMode ( colorScheme ) ;
@@ -348,9 +325,8 @@ const EditionDropEmbed: React.FC<EditionDropEmbedProps> = ({
348
325
< ClaimPage
349
326
contract = { editionDrop }
350
327
tokenId = { tokenId }
351
- expectedChainId = { expectedChainId }
352
328
primaryColor = { primaryColor }
353
- secondaryColor = { secondaryColor }
329
+ colorScheme = { colorScheme }
354
330
/>
355
331
</ Body >
356
332
< Footer />
@@ -361,18 +337,16 @@ const EditionDropEmbed: React.FC<EditionDropEmbedProps> = ({
361
337
const urlParams = new URL ( window . location . toString ( ) ) . searchParams ;
362
338
363
339
const App : React . FC = ( ) => {
364
- const expectedChainId = Number ( urlParams . get ( "chainId" ) ) ;
340
+ const chainId = Number ( urlParams . get ( "chainId" ) ) ;
365
341
const contractAddress = urlParams . get ( "contract" ) || "" ;
366
- // default to expectedChainId default
367
342
const rpcUrl = urlParams . get ( "rpcUrl" ) || "" ;
368
343
const tokenId = urlParams . get ( "tokenId" ) || "0" ;
369
344
const relayerUrl = urlParams . get ( "relayUrl" ) || "" ;
370
345
371
346
const ipfsGateway = parseIpfsGateway ( urlParams . get ( "ipfsGateway" ) || "" ) ;
372
347
373
- const colorScheme = urlParams . get ( "theme" ) || "light" ;
374
- const primaryColor = urlParams . get ( "primaryColor" ) || "blue" ;
375
- const secondaryColor = urlParams . get ( "secondaryColor" ) || "orange" ;
348
+ const colorScheme = urlParams . get ( "theme" ) === "dark" ? "dark" : "light" ;
349
+ const primaryColor = urlParams . get ( "primaryColor" ) || "purple" ;
376
350
377
351
const sdkOptions = useMemo (
378
352
( ) =>
@@ -398,20 +372,24 @@ const App: React.FC = () => {
398
372
/>
399
373
< ChakraProvider theme = { chakraTheme } >
400
374
< ThirdwebProvider
401
- desiredChainId = { expectedChainId }
375
+ desiredChainId = { chainId }
402
376
sdkOptions = { sdkOptions }
403
377
storageInterface = {
404
- ipfsGateway ? new IpfsStorage ( ipfsGateway ) : undefined
378
+ ipfsGateway
379
+ ? new ThirdwebStorage ( {
380
+ gatewayUrls : {
381
+ "ipfs://" : [ ipfsGateway ] ,
382
+ } ,
383
+ } )
384
+ : undefined
405
385
}
406
- chainRpc = { { [ expectedChainId ] : rpcUrl } }
386
+ chainRpc = { { [ chainId ] : rpcUrl } }
407
387
>
408
388
< EditionDropEmbed
409
389
contractAddress = { contractAddress }
410
390
tokenId = { tokenId }
411
- expectedChainId = { expectedChainId }
412
391
colorScheme = { colorScheme }
413
392
primaryColor = { primaryColor }
414
- secondaryColor = { secondaryColor }
415
393
/>
416
394
</ ThirdwebProvider >
417
395
</ ChakraProvider >
0 commit comments