🎉 ⏱ Ready to build? Get early access now!⏱ 🎉
Build an auction button in React for your dApp with TypeScript
Create an auction button in your website
What you get
This guide gives you a simple React component to create an auction
and a component for a connect wallet
button. Check the code at GitHub over here.

Dependencies
Quick heads up, in these examples, the thirdweb sdk is integrated with React components, but we're 'just' using javascript. You can do the same magic with another framework!
Make sure to have the dependencies installed
npm install @3rdweb/sdk @3rdweb/react @3rdweb/hooks ethers
The App.js - Connect your wallet
In your App.jsx
file we can use the code from this guide for our connect wallet
button. thirdweb created a component for the connect wallet
button so we don't have to code it ourself. This is great so we don't have to mess around with private keys later.
Inside our app we import our component for the claim
button.
import { ThirdwebProvider, ConnectWallet } from '@3rdweb/react'; import './App.css'; //import component for claim button import AuctionComponent from './AuctionListing'; const supportedChainIds = [1, 4, 137, 250, 43114, 80001]; const connectors = { injected: {}, magic: { }, walletconnect: {}, walletlink: { appName: "thirdweb - demo", url: "https://thirdweb.com", darkMode: false, }, }; function exampleApp() { return ( <ThirdwebProvider connectors={connectors} supportedChainIds={supportedChainIds} > <ConnectWallet /> <AuctionComponent /> /*render the claim button*/ </ThirdwebProvider> ); } export default exampleApp;
You can learn more about the walletconnect options on their official docs here and wallet link here
The AuctionListing.js - The Buy button
In your AuctionListing.js
file we will write the code for the button.
Let's take it step by step, but feel free to scroll to the bottom to copy the full piece of code.
First we import all the necessary dependencies. The hooks and sdk should be familiar :).
import { useCallback, useMemo, useEffect, useState } from "react"; import { ThirdwebSDK } from "@3rdweb/sdk"; import { ethers } from "ethers"; import React from "react";
In this guide we will not be passing the private keys manually. This is not considered best practice and is actually a security issue when applied on the client side.
Instead we will make use of provider
, which we pull when a wallet is connected via the Connect Wallet
component.
The cool thing about this component, is that it's using the connect wallet
component to authorise the transaction 😄.
const AuctionComponent = () => { const { provider } = useWeb3();
Next up we instantiate the sdk, marketplace module and create variables with our contracts.
// We won't always have a provider, and so we need to be sure to // instantiate the ThirdwebSDK with a provider *only if we have one* const sdk = useMemo( () => provider ? new ThirdwebSDK(provider.getSigner()) : new ThirdwebSDK(), [provider] ); // We should use the `useMemo` to ensure that the `market` is always // initiated with the latest `sdk` variable const market = useMemo( () => sdk.getMarketplaceModule("0xCb67A96FAd36D8c24f192B9eDaD5fF3c7A7A867f"), [sdk] ); // Declaring the nft smart contract address const nftSmartContractAddress = "0x95c78aca2c99df3E7469769C56565ECc0e8eCe95"; const currencySmartContractAddress = "0x0d5fb8942eEa62093944F3e91C6Ac4e584336741";
This part is a bit big, but it doenst make sense to split it up. First we declare some variables that will be passed through a form such as, tokend Id's, listings Id's and the amounts. Then we use the variables in our function.
A couple of notes.
The createAuctionListing
method takes two prices as input.
buyoutPricePerToken
is the variable that is used to define the buy now amount.
reservePricePerToken
is the variable that is used to define the minimum bid.
function auctionListingTokenId(event) { setTokenId(event.target.value); } function auctionListingTokenIdOffer(event) { setTokenIdOffer(event.target.value); } function submitAuctionListing(event) { event.preventDefault(); createAuctionListing(); } const [listId, setListId] = React.useState(""); const [listIdBid, setListIdOffer] = React.useState(""); function auctionListingListId(event) { setListId(event.target.value); } function auctionListingListIdQuantity(event) { setListIdOffer(event.target.value); } function submitAuctionListingOffer(event) { event.preventDefault(); makeBid(); } //setting the minimum bid as 100th of the buyout price const tokenIdReserve = BigNumber.from(tokenIdOffer).div(100); const tokenIdReservePrice = tokenIdReserve.toString(); // We should use the `useCallback` to ensure that the `buy` // function is always initiated with the latest `market` variable const createAuctionListing = async () => { await market.createAuctionListing({ assetContractAddress: nftSmartContractAddress, buyoutPricePerToken: ethers.utils.parseUnits(tokenIdOffer, 18), currencyContractAddress: currencySmartContractAddress, startTimeInSeconds: Math.floor(Date.now() / 1000), listingDurationInSeconds: 60 * 2, tokenId: tokenId, quantity: 1, reservePricePerToken: ethers.utils.parseUnits(tokenIdReservePrice, 18), }); }, [market, tokenId, tokenIdOffer, tokenIdReservePrice]; const makeBid = async (listingId) => { await market.makeAuctionListingBid({ listingId: listId, pricePerToken: ethers.utils.parseUnits(listIdBid, 18), }); }, [listId, listIdBid, market] ;
Finally render out the forms :).
return ( <div> <form onSubmit={submitAuctionListing}> <input type="text" placeholder="enter token ID to list AUCTION" onChange={auctionListingTokenId} /> <input type="text" placeholder="enter offer for the listing AUCTION" onChange={auctionListingTokenIdOffer} /> <button>Submit Token ID for Auction Listing</button> </form> <form onSubmit={submitAuctionListingOffer}> <input type="text" placeholder="enter AUCTION listing ID" onChange={auctionListingListId} /> <input type="text" placeholder="enter bid for AUCTION" onChange={auctionListingListIdQuantity} /> <button>Make a Bid</button> </form> <button style={{ padding: "10px 20px", textAlign: "center", backgroundColor: "#44014C", color: "white", }} class="btn" onClick={createAuctionListing} > Create auction listing! </button> <br /> </div> ); }; export default AuctionComponent;
The full piece of code that goes inside AuctionListing.js
import { useWeb3 } from "@3rdweb/hooks"; import { useCallback, useMemo, useEffect, useState } from "react"; import { ThirdwebSDK } from "@3rdweb/sdk"; import { ethers } from "ethers"; import React from "react"; const AuctionComponent = () => { const { provider } = useWeb3(); // We won't always have a provider, and so we need to be sure to // instantiate the ThirdwebSDK with a provider *only if we have one* const sdk = useMemo( () => provider ? new ThirdwebSDK(provider.getSigner()) : new ThirdwebSDK(), [provider] ); // const sdk = useMemo(() => { // We should use the `useMemo` to ensure that the `market` is always // initiated with the latest `sdk` variable const market = useMemo( () => sdk.getMarketplaceModule("0xCb67A96FAd36D8c24f192B9eDaD5fF3c7A7A867f"), [sdk] ); // Declaring the nft smart contract address const nftSmartContractAddress = "0x95c78aca2c99df3E7469769C56565ECc0e8eCe95"; const currencySmartContractAddress = "0x0d5fb8942eEa62093944F3e91C6Ac4e584336741"; const [tokenId, setTokenId] = React.useState(""); const [tokenIdOffer, setTokenIdOffer] = React.useState(""); function auctionListingTokenId(event) { setTokenId(event.target.value); } function auctionListingTokenIdOffer(event) { setTokenIdOffer(event.target.value); } function submitAuctionListing(event) { event.preventDefault(); createAuctionListing(); } const [listId, setListId] = React.useState(""); const [listIdBid, setListIdOffer] = React.useState(""); function auctionListingListId(event) { setListId(event.target.value); } function auctionListingListIdQuantity(event) { setListIdOffer(event.target.value); } function submitAuctionListingOffer(event) { event.preventDefault(); makeBid(); } //setting the minimum bid as 100th of the buyout price const tokenIdReserve = tokenIdOffer / 1000; const tokenIdReservePrice = tokenIdReserve.toString(); // We should use the `useCallback` to ensure that the `buy` // function is always initiated with the latest `market` variable const createAuctionListing = useCallback(async () => { await market.createAuctionListing({ assetContractAddress: nftSmartContractAddress, buyoutPricePerToken: ethers.utils.parseUnits(tokenIdOffer, 18), currencyContractAddress: currencySmartContractAddress, startTimeInSeconds: Math.floor(Date.now() / 1000), listingDurationInSeconds: 60 * 2, tokenId: tokenId, quantity: 1, reservePricePerToken: ethers.utils.parseUnits(tokenIdReservePrice, 18), }); }, [market, tokenId, tokenIdOffer, tokenIdReservePrice]); const makeBid = useCallback( async (listingId) => { await market.makeAuctionListingBid({ listingId: listId, pricePerToken: ethers.utils.parseUnits(listIdBid, 18), }); }, [listId, listIdBid, market] ); return ( <div> <form onSubmit={submitAuctionListing}> <input type="text" placeholder="enter token ID to list AUCTION" onChange={auctionListingTokenId} /> <input type="text" placeholder="enter offer for the listing AUCTION" onChange={auctionListingTokenIdOffer} /> <button>Submit Token ID for Auction Listing</button> </form> <form onSubmit={submitAuctionListingOffer}> <input type="text" placeholder="enter AUCTION listing ID" onChange={auctionListingListId} /> <input type="text" placeholder="enter bid for AUCTION" onChange={auctionListingListIdQuantity} /> <button>Make a Bid</button> </form> <button style={{ padding: "10px 20px", textAlign: "center", backgroundColor: "#44014C", color: "white", }} class="btn" onClick={createAuctionListing} > Create auction listing! </button> <br /> </div> ); }; export default AuctionComponent;
That's it!
It's really that easy. If you have any questions, drop by our discord!