Creating a Decentralized Art Marketplace with Cargo JS and ERC721 tokens
This tutorial assumes you are familiar with MetaMask, or another product that provides the Ethereum blockchain to your browser. If you don’t know what MetaMask is check out this tutorial on installing it.
Once you’ve installed MetaMask and logged in you need to switch the Rinkeby network.
Adding test funds to your wallet
You can add test funds to your wallet by using a Rinkeby faucet. To do this go to https://www.rinkeby.io/#faucet. To get some test funds in your wallet you will need to post your address on Twitter or Facebook and give the faucet the link. It will read your address from your social post and deposit funds into your wallet.
Starting the server
Fist let’s grab the starter files from Github. You can find the files within the digital-art-marketplace folder in this repo https://github.com/cargo-eth/examples. There’s a start and finish folder within the digital-art-marketplace directory. Go to the start folder in your terminal and run the following commands to get the web server running:
This will start the simple Express server I made to serve the index.html file. For this tutorial we will be editing the main.js file inside the assets folder within the start folder.
Walking through the initial code
The starter code is pretty simple. Here is the initial JS file for our application. I’ve bootstrapped it to initialize and enable Cargo JS and show content based on whether or not the user’s browser can interact with the Ethereum blockchain. Read through the comments below to understand what this simple code is doing.
If you start the server by running
yarn run:start in your terminal and go to http://localhost:3000 you will see this code in action. If you have MetaMask installed you will see a popup asking for authorization to connect — if you don’t then you will automatically see a message that says you need to install it.
Creating a crate
Now it’s time to create a crate. Make sure you have installed MetaMask and are on the Rinkeby network. Go to https://rinkeby.cargo.build/dashboard and click the “Create a crate” button. A MetaMask transaction dialogue will pop up — confirm the transaction and wait until it completes. When the transaction is complete Cargo will automatically reload your crates.
When your crate is created click the blue arrow to the right of the crate name to enter the crate. Once on the crate detail page click the “Create contract” button.
You will now be on “Create a token contract” page. Enter a name and a symbol for you new contract. Click the “Create contract” button and confirm the MetaMask transaction.
Minting a token
You will be redirected to the crate detail page. Once your transaction is confirmed Cargo will automatically reload your contracts and you will see your newly created contract. Once you do — click the “Mint” button.
For this tutorial you don’t need to upload anything, so check the “I do not need to upload anything” box. By default the newly minted token will be sent to your connected address.
You can use the preview image I included repo call “preview-baby-rex.png”. Drag and drop the image onto the “Preview Image” box, or click the box to open the file browser.
When you click the Mint button two things will happen. You will see two MetaMask popups. First you will be asked for your signature. Cargo uses this signature on the backend to verify you are the owner of the connected address. Cargo’s backend will send transaction data back to you and you will then see a MetaMask transaction popup. Confirm the transaction and once your transaction is completed you will have minted your new token.
Once your transaction is completed you should be able to click “View tokens” and see your new token.
Wow, that was a lot. If you are still with me give yourself a hand. You just created an ERC-721 contract on the Ethereum blockchain and minted a token within that contract without writing a single line of Solidity code.
We need our crate Id to get the contracts and tokens within that crate — so let’s get that. You can get it from the crate list page in the Cargo dashboard. Here’s an image of what I am talking about:
CRATE_ID variable on line four is a string — the crate ID that you found above. Add that variable to the top of the file (ex.
const CRATE_ID = '98'; )
What this is doing is fetching information about our newly created contract. Contracts are associated to vendors and vendors are associated to crates. By default you are added as a crate vendor when you create a crate. So, in the code above, first we get the crate vendors and then we get the contracts those vendors created.
Now let’s add a function to display the data in our HTML. Here’s the JS file up to this point — copy this into your main.js file and replace the CRATE_ID at the top of the file with your crate ID.
You can see above that I added the
displayContractContent function to display our contracts in the HTML. Once you add this new code to your main.js file refresh the HTML page and you will see your new contract appear!
OK great. There’s our contract, but where is our token we created? We only want to display tokens that are for sale — in order to do that we need to set it for sale. We will do this in the Cargo dashboard, but everything we do on Cargo can be done programmatically — either through Cargo JS or through interacting with the smart contracts directly.
Setting our token for sale
Go back to the Cargo dashboard and enter into your crate so you can see your contract. Expand the token list by clicking “View Tokens”. You will see an option to sell the token, click the “Sell” button.
You will see the sell modal pop up. Enter the price for your token and click sell. Confirm the MetaMask transaction and wait for it to be confirmed.
Once the transaction is confirmed we will be able to retrieve the token and show it in our app. We will add a couple additional methods to our JS file to get all the information we need to display token data to the user.
Let’s add the
cargo.api.getContractResaleItems function. When you set a token for sale a resale item is created. You as the seller can always cancel the sale. Starting on line 40 add this code. We will update
displayContractContent to take a second argument which is the resale items for our contracts.
The response of
cargo.api.getContractResaleItems is an object that maps token contract IDs to a list of resale items. So we can get the token contract ID from within
displayContractContent and display resale items based on that. Here’s the updated function:
Now our resale items will show up in our app.
Not too bad right? You’ve done a lot so far, so what’s left? We want to be able to buy these tokens through our app and then we want to be able see which tokens we own. So let’s implement that.
Adding a buy button
Now let’s add a buy button for tokens that are for sale. I am going to update the
displayContractContent function to include a button. The button will have three data attributes — an id, a resale ID, and the price. We will use the resale ID and the price when calling
cargo.api.purchaseResaleToken . I’ve also made the
tokenRows variable which we inject our markup into, but now I have added a click event listener. This listener checks to see if we clicked the buy now button. If we did then we will call
If you want to copy the full code up to this point you can get it here.
Once you have implemented the additional code you can click the Buy button and you will get a MetaMask popup. Confirm the confirmation and you will see a message show up in the UI. You can check the status of your transaction on Etherscan. Once the transaction is complete refresh the page — the token is gone! You’ve purchased the token so it’s not longer a resale item. The token was transferred to you and funds were deposited in your Cargo wallet. You can withdraw your funds by going to https://rinkeby.cargo.build/dashboard/my-funds.
Displaying Owned Tokens
We want to display owned tokens to our users — so they can have a way to manage their assets. In the code below I created a few new functions —
getOwnedTokens which gets the owned tokens for the current user,
getResaleItems which is the code that was initially in the
run function, but I moved out so we could run both functions in parallel, and I added
getTokenInfo which is a helper function that will get all the information about the owned tokens so we can display them on the screen. Here is the updated code to this point:
If you made it to this point, congrats 🎉! You’ve created a basic marketplace that combines using the Cargo dashboard and Cargo JS. There’s so much more that can be added to this application, but we will stop here. Next you could add a way for users to sell their Owned Tokens and transfer them. You could add new vendors to your crate through the Cargo dashboard (or programmatically) and create UI that allows them to create tokens. You could even create a new smart contract that Cargo calls when certain events take place. I hope this helped you learn a little about how you can make decentralized applications using Cargo.