Guide to mint a Generative Token

This document will walk you through all the concepts you need to know to understand how you can build and publish a Generative Token (GT) on fxhash.

Table of Contents

Knowledge requirements

GT on fxhash can only be written in html/css/javascript. Ultimately, GT are documents which can be interpreted by a web browser. When someone will collect your GT, it will create a unique web document derived from the one you provided. Don't worry, as an artist, the generation process is automated, and if you follow the guidelines it should be straightforward to implement a GT. However, you will need to know how to render graphics within a web document to use the platform.

General overview

This section will give you a rough overview of the Generative Tokens on fxhash. Don't worry if some informations are missing for you to properly understand the process, it will be covered later in this document.

Upload and mint a GT

First, you upload your project and mint it as a Generative Token. This project is a tiny website which sole purpose is to generate some visual/audio based on a 51-characters base 58 encoded number (Tezos transaction hashes have the same signature). The project needs to be designed in a way that, when the same string is given to it, it always produces the same output. However, a different string should produce a different output.

Generative Token overview

Your project is stored

Your project will be stored on the IPFS network, and then stored on the tezos blockchain. It ensures its immutability.

People mint a unique token from your GT

When a GT is published on the platform, anyone will be able to mint unique iterations from it. When such an event arises, the mint transaction generates a unique hash. The hash is sent as a URL parameter to your project. A code snippet is used to get this hash from the URL so that it can be used in your code.

Mint overview

Image preview

When a token is minted, fxhash provides a service to generate a preview, which will be attached to the tokens as an alternate way to visualize them.

How to build a GT

This section covers the different aspects you need to know to create a GT.

Project structure

All the files needed by your project must be in the same directory, with an index.html file at its root.


When you link to a file in your index.html, paths must be relative.

  • src="./path/to/file.js" -> OK
  • src="/path/to/file.js" -> NOT OK

You can use as many sub-directories as you see fit.

fxhash code snippet

fxhash requires you to insert the following code snippet in the <head> section of your index.html

<script id="fxhash-snippet">
  //---- do not edit the following code (you can indent as you wish)
  let alphabet = "123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ"
  var fxhash = "oo" + Array(49).fill(0).map(_=>alphabet[(Math.random()*alphabet.length)|0]).join('')
  let b58dec = str=>[...str].reduce((p,c)=>p*alphabet.length+alphabet.indexOf(c)|0, 0)
  let fxhashTrunc = fxhash.slice(2)
  let regex = new RegExp(".{" + ((fxhashTrunc.length/4)|0) + "}", 'g')
  let hashes = fxhashTrunc.match(regex).map(h => b58dec(h))
  let sfc32 = (a, b, c, d) => {
    return () => {
      a |= 0; b |= 0; c |= 0; d |= 0
      var t = (a + b | 0) + d | 0
      d = d + 1 | 0
      a = b ^ b >>> 9
      b = c + (c << 3) | 0
      c = c << 21 | c >>> 11
      c = c + t | 0
      return (t >>> 0) / 4294967296
  var fxrand = sfc32(...hashes)
  // true if preview mode active, false otherwise
  // you can append preview=1 to the URL to simulate preview active
  var isFxpreview = new URLSearchParams(window.location.search).get('preview') === "1"
  // call this method to trigger the preview
  function fxpreview() {
    console.log("fxhash: TRIGGER PREVIEW")
  //---- /do not edit the following code

This snippet serves 2 purposes:

  • some parts of it will be replaced by fxhash to generate unique tokens from your GT (a static hash will be inserted instead of the random generation)
  • during the development stages, it emulates eventual hashes your program could get as an input. Every time you refresh the page, it generates a random hash. This way, you can really build your GT properly before deploying it.

The code snippet exposes 4 variables:

  • fxhash: a random 51 characters base 58 encoded string (designed to have the same signature has a Tezos transaction hash). When someone mints a unique Token from a Generative Token, the transaction hash is hardcoded in place of the code that generates a random one.
  • fxrand(): a PRNG function that generates deterministic PRN between 0 and 1. Simply use it instead of Math.random().
  • fxpreview(): a function you can call whenever the code is ready to be captured
  • isFxpreview: a boolean, true when the code is executed to take the capture, false otherwise

Those 2 variable/function will be globally accessible by your program, and must be used to drive any random process required by your piece.


Fxhash supports the definition of features. To add features to a Token, you simply have to populate a $fxhashFeatures object in the window object.

window.$fxhashFeatures = {
  // here define the token features

If you want the token features to be available, the window.$fxhashFeatures must be defined once the page is loaded. For instance, the following code might result in features not getting picked up by our module:

setTimeout(() => {
  window.$fxhashFeatures = {
    // here define the token features
}, 1000)

Each propery of the $fxhashFeatures object will define one feature of the Tokens.

Features should also be derived from the fxhash string and from the fxhash string only. They should match the visual characteristics of the Token (ie reflect the settings behind the generative process of the token).

The type of a feature value can only be string, number or boolean. Any other type will be discarded.

For instance, this object will define 3 features:

window.$fxhashFeatures = {
  "Dark": true,
  "Colors number": 7,
  "Head size": "Big"

Fxhash automatically computes the rarity of a particular feature by counting the number of occurences among all the tokens of the collection. Two feature values are considered the same if a strict equality between those returns true. If you want the rarity of a feature to be meaningful, you must define its values in a way that ensures multiple occurences to appear.

For instance, this will not work well with the rarity module:

window.$fxhashFeatures = {
  // each token will have a different "Super" feature value between 0 and 1
  "Super": fxrand()

If defined in such a way, each token will have a different "Super" feature value and thus they will all have the same rarity in regard to that feature.

What you can do instead, is to assign a string to a range of values:

function getFeatureString(value) {
  if (value < 0.5) return "low"
  if (value < 0.9) return "medium"
  else return "high"

window.$fxhashFeatures = {
  // feature can only be "low", "medium" or "high"
  "Super": getFeatureString(fxrand())

With this implementation, the value of the feature will only be low, medium or high. This ensures that the rarity module will correctly assign the Super feature rarity when a Token is minted. Of course, this is a very naïve implementation, you may want to adapt it to fit your needs in a better way.

Zip, test & mint

Once you are done developing your GT, you will need to compress all of its content into a ZIP archive. fxhash only accepts the ZIP format. The index.html file must be located at the root of the archive.

Once you have your ZIP file, you can check that it behaves properly by uploading it to the sandbox. The sandbox can be used as a quick way to test your project.

Once you have properly tested your project, you can mint it by following the instructions on the page.

How to publish (mint) a GT

Sync your wallet

First of all, you will need to have a Tezos wallet synced with fxhash.

Mint your GT

Once your GT is ready to be published (once it's been carefully tested in the sandbox), you can open the mint page. This page will guide you through the different steps of the process:

  • authoring: select who's authoring the piece: yourself alone or collaboration ?
  • upload to IPFS: drop your .ZIP file and wait until it gets uploaded to IPFS through fxhash servers
  • check files: check again if your project behaves properly once uploaded to IPFS. Also if you implemented features, check if they work properly. This step is also used to configure which hash will be used for the preview of your project.
  • configure capture: select the capture mode and configure it. Also check if the capture is working properly
  • verifications: a comparative check between the preview & the live version
  • distribution: number of editions, pricing & general distribution settings
  • explore variation settings: configure the variations a collector can explore when viewing your token
  • project details: contextual informations about your piece
  • preview & mint: a preview of your project once published, and the mint button

There are lots of steps, but each step is required for your project to be released in the best conditions possible.

You can find more information on individual steps in the following articles:


Some guidelines must be followed to ensure your GT works properly.

Network requests

You cannot make any network request. If you need an external library/font/image, you must put it in your project folder. I know, this isn't an ideal workflow, but the point is to create self-contained tokens which can execute properly regardless of external conditions.

Respond to window size

Your web page must be responsive (ie adapt itself to any screen size). Moreover, we advise that your application should respond to the "resize" event of the "window". It may eventually happen in the lifetime of the tokens that the viewport size changes during its execution. If you want to keep a fixed size canvas, you can do so, and maybe center the canvas in the viewport.

Random numbers generation

Your program must use pseudorandom number generation with a seed, where the seed is the fxhash variable. You can use the fxrand() function for that matter. It implements the Small Fast Counter algorithm, which is part of the PracRand PRNG test suite. It passes PractRand, as well as Crush/BigCrush (TestU01). It's fast, and its usage is recommended. You can however use your own PRNG function as long as you give it the fxhash seed.


  • the ZIP file must be <= 30 MB. Please try to optimize your projects as much as possible.

Best practices and common mistakes

A list of best practices and common mistakes (and how to fix them) to ensure that your token has as long a life as possible.

Test often

This section comes first as it's the most important in ensuring that your token is as good as you can make it. Remember that once you release, you can't edit the token, so make sure to test as often as you can when developing.

Testing often will also allow you to catch problems early that would become big issues later on. Nobody likes to get to the minting stage - or worse, selling out - only to discover that their token doesn't work properly.

Resolutions and DPRs

Ensure your token looks the same in all resolutions and DPRs.

It is ideal if your token produces the same artwork at different sizes. Make sure to test your token often at different resolutions and DPRs. One of the most common pitfalls that artists fall into is not doing so and having their tokens look different at different sizes - as well as different to the preview - as a result.

There are a number of different ways of getting your token to work in a resolution independent manor. Jump into the creator-support channel if you'd like to ask any questions.


WebGL is a big subject and there are a number of items worth talking about in relation to it.

Power of two textures and framebuffers

Some GPUs allow you to specify non power of two textures and framebuffers, however using non power of two textures and framebuffers will break the preview system.

WebGL on different silicone

WebGL is an emulation layer on top of different graphics APIs which talk to hardware, as such implementation of basic things like sine calculation and float precision can vary.

One important thing to remember about WebGL is that you should be doing as muchof your calculation up-front, in javascript, and providing those values to WebGL as uniforms.

WebGL and previews

As of right now the preview system doesn't have a GPU. As such, rendering your scene falls to the CPU, which will render WebGL but at an extremely low framerate.

If your token is WebGL then you want to make sure that you're rendering an accepable preview in the first couple of frames.

Computational complexity and previews

If your token is computationally expensive, then it's possible that the preview system will stumble over it and the signer will not be able to sign mints! Please be aware that there exist ways to generate less complex previews for your tokens, but the implementation of this necessarily needs to fall on you, the artist. Jump into the creator-support channel if you'd like to ask any questions.

Test often

This is such an important point that it bears mentioning twice.

  • Test often
  • Test in many different environments
  • Test using the same hash at different resolutions
  • Test in the sandbox as well as standalone

3 ways to start a project

This section will provide you with some boilerplate projects to make the development on your GT easier.

Using our webpack boilerplate

We encourage you to use our webpack boilerplate, specifically designed to create projects on fxhash. It comes with the following features:

  • already setup: code snippet is injected, you can start to work on your content immediately
  • local environment with Live Reload so that you can iterate faster on your projects
  • javascript imports: you can import npm packages, use the import syntax, and webpack will bundle everything in a single minified javascript file
  • automated deployment: run a command to build your files and create a ZIP archive ready to be deployed on fxhash

All the instructions are in the README in the Github repository.

Using our simplest boilerplate

We also provide a simpler boilerplate, with a single html and javascript file. The snippet is already injected, but that's it.

Starting from scratch

You can also start from scratch, just remember to inject the snippet in the <head> of your index, before importing your scripts.

Have fun

We hope this guide will cover most of what you need to know to build tokens on fxhash. If you have any issues, feel free to join our Discord server.