How to mint NFT without the Internet
How to generate tokens without using an API when using the Rarible protocol
How are you generating the tokenIds for your NFTs? If you are using the Rarible protocol, you are probably making a generateNftTokenId
API request call to Rarible’s server every time you want to mint an NFT.
Today I’m going to share how you can get rid of this step, and replace it with a more efficient, scalable, and and a completely offline approach to doing this.
Not requiring a network connection for minting opens up doors to a lot of cool things. You can:
- save network traffic (save one round trip to Rarible’s server)
- mint tokens privately
- mint completely offline
Being able to mint offline means you can store and route your NFTs in a completely peer to peer manner with other NFT applications, resulting in an overlay distributed network of NFTs.
Demo
Let’s get right into it. Try the embedded demo below.
It does not use any network API and doesn’t even require any network connection, so you can even try it while you’re offline.
Code
So how does it work? Here’s the full JavaScript code for the decentralized tokenId generation algorithm. It can be used both in the browser and in node.js:
const make = (creator) => {
// 13 digit unix timestamp
const timestamp = Date.now()
// 11 digit random number
const rand = (Math.random() * 10**18).toString().slice(0,11)
// append creator + timestamp + random and convert to uint
return BigInt(creator + timestamp + rand).toString(10)
}
All you need to do is call:
const tokenId = make("0x069dC295FFe6e58a63C89f5C0B56a5c70b9AA4e7")
And that’s all! No API endpoint, no Internet connection needed. All token IDs are algorithmically generated.
Because it does not require an API endpoint, this way you can mint millions and billions of tokens without ever being connected to the Internet at all! It’s as decentralized as generating UUIDs.
This tokenId generation algorithm is a part of Rarepress, which not only decentralizes the tokenId generation step, but also decentralizes the entire workflow involving NFT minting and storage, which lets you mint millions and billions of NFTs offline without relying on an API. Check it out: https://rarepress.org
Now, let’s walk through how this tokenId algorithm works.
Rarible Protocol is already decentralized
What most developers don’t realize yet is, the Rarible protocol is already decentralized and has everything you need to do things in a completely decentralized way.
Let’s take a look at the smart contract code: https://github.com/rarible/protocol-contracts/blob/master/tokens/contracts/erc-721/ERC721Lazy.sol#L49
In line 49, it takes the tokenid
, and right shifts by 96 to compute the “minter” variable. Then in line 52, it compares the included creator address (data.creators[0].account
) with the address computed from the tokenId (minter
), and only moves forward if the two match.
From this we can conclude that the tokenId
is derived from the minter’s address. It also means that we already have everything needed to reverse engineer and generate tokenIds without relying on any API endpoint!
Algorithm
The most important part is the line 49:
address minter = address(data.tokenId >> 96)
This basically means “take the tokenId and shift it 96 bits (24 hex digits) to the right”, and that address must match the first address in the creators array.
Long story short, we can reverse engineer this to generate a tokenId from an address. The algorithm is:
- Take an address
- Append random 24 hex digits to its right
- Convert it to
uint
(which is what solidity is expecting)
And that’s all! Here’s the full code:
const make = (creator) => {
// 13 digit unix timestamp
const timestamp = Date.now()
// 11 digit random number
const rand = (Math.random() * 10**18).toString().slice(0,11)
// append creator + timestamp + random and convert to uint
return BigInt(creator + timestamp + rand).toString(10)
}
- First, we first generate the current unix timestamp (13 digits)
- Second, we generate a random number of 11 digits
- We then combine them together by appending the creator (ethereum address hex), the timestamp, the random number
- Then we convert it to uint string
Ok, so we get that we need 24 digits to the right side of the address, but why are we using the timestamps and and the random number?
We use the unix timestamp to ensure that every call to the make()
function returns a tokenId
that increases in value (since time only goes forward and not backward). But unix timestamp is only 13 digits, so we need a random filler to make a 24 digit hex. That’s why we generate a 11 digit random number.
This algorithm will ensure that the tokenId
of every token generated this way will keep going up in a single threaded situation (which is at the moment most of the use cases).
In a multithreaded situation where you need to mint millions of billions of tokens in parallel, the tokens minted within the same millisecond will have the same unix timestamp prefix, but likely won’t have a collision because of the random number.
Conclusion
It is important to build NFT applications to be as decentralized as possible. The whole point of the NFT marketplace as a smart contract, is that it gets rid of a single point of failure.
The offline tokenId generation algorithm is just one aspect, but you can imagine how this paradigm applies to everything else, such as having your own NFT database and file system from which you can serve your own users, etc.
If you are interested in building NFT applications and NFT collections this way, check out Rarepress, an open source NFT Operating System that makes use of Rarible NFT marketplace protocol to help you build fully decentralized NFT infrastructure effortlessly: