Overview of the fxhash project SDK and API
In the previous sections we've had a look at the structure of an fxhash project, introduced the boilerplate as a minimal starting point for new projects and also had a first look at the CLI as an alternative method to setting up blank projects.
Both the boilerplate and the CLI are a part of the fxhash Project SDK—essentially a number of resources that fxhash provides, with the aim of facilitating the development and creation of projects for the platform. This encompasses this documentation, the CLI, the Boilerplate, and most importantly the fxhash.js script. This script file is also referred to as an API.
In other words, the fxhash API is simply a fancy term to refer to the functions that the fxhash.js script exposes within the scope of an fxhash project. These functions provide useful functionality for artists to build deterministic generative artworks that work properly and are platform compatible once uploaded to fx(hash).
How does this API work? Why do we need to use it? And moreover, how do we use it? All of these questions should be answered by the end of this page. If you’re more experienced, know what an API is, and simply want to have an overview of the different functions it provides you can jump to the following , and .
The fxhash API is a code library designed for developing deterministic generative systems. It provides a pseudo random number generator (PRNG) that can be used as the primary source of randomness throughout a generative token's code. Moreover, it automatically seeds this pseudo random number generator with the hash that is injected into the code.
Furthermore, depending on what kind of token you want to develop, and depending on how the randomness should behave, the SDK provides a couple of options for that as well. It provides a number of functions to generate different kinds of random numbers and/or make random decisions throughout the code.
Technically, the PRNG provided by the API isn't mandatory - as an artist you can also equivalently implement your own PRNG function, under the condition that it is seeded correctly with the hash that the API script injects into your code. The hash is therefore the only part of the API that is required. We strongly recommended to use the API however, in this manner you can focus on building your generative artwork rather than spending time on programming a PRNG.
fxhash.js script file do?When we had a look at and introduced , we’ve seen that the index.html should reference the fxhash.js script within it’s head tag. By doing so the fxhash.js script is run when the webpage is viewed in a browser. Although there is a lot of code inside of the fx(hash) script file, the main purpose of it is the creation an $fx object and attaching it to the window object as a property.
This $fx object is essentially a container for the functions of the fxhash project API, making them available for usage in the artist script, namely the index.js file.
$fx object?If you’ve already installed the CLI and created a new blank fxhash project, we can see for ourselves what this $fx object is. While keeping all of the files unchanged, we’ll only delete the contents of the index.js file, and replace it with a single line of code that logs this $fx object to the console:
If we now open the index.html in our browser, we'll get a blank, white browser window (because we deleted the previous code), but if we check the console however, we'll see that something has been logged:
This is the content of the $fx object created by the fxhash.js script. There's a bunch of stuff inside of it: a number of properties, functions, and other objects. All of these are now accessible in the artist script and available for our convenience to build a generative artwork with.
One last note here, it is not recommended to change the code inside of the fxhash.js script for your generative token to work properly:
You should not change or edit the code inside of fxhash.js for your GENTK to function properly.
A complete run-down of all API functions can be found in the A detailed explanation of these functions can be found in the .
console.log($fx) // logging the $fx object to the console
An introduction to the fx(params) module.
⚠️ fx(params) is not currently supported on mainnet ETH or Base ETH based projects. It is however planned at some point in the future.
Traditionally, projects on fx(hash) generate random outputs for their collectors. This means that collectors have no prior knowledge as to what the iteration they will receive look like beforehand. This is because the hash that is used to seed the PRNG of the generative artwork, can not be known in advance. With fx(params) this paradigm changes.
From the collectors point of view, this changes a couple of things. Instead of directly collecting an iteration from a project, when a project that makes use of fx(params) is collected they obtain a mint ticket instead. This mint ticket is essentially a voucher that they can exchange for an iteration of the project.
This system is in place to give collectors the time to customise their iteration without having to worry about running out of time and the project completely minting out. Once a mint ticket is secured, the collector can then take their time crafting their own unique individual iteration. You can read more about this in the collector guides.
From the artist's point of view, to create an fx(params) piece, they will need to make use of the fx(params) module of the API. In this section we will give an overview of the module and explain how to use it. A detailed explanation of the different functions that this module provides can be found in the .
Creating an fx(hash) project that makes use of fx(params) boils down to using the respective functions in the API such that certain variables in the code are exposed as collector tweakable parameters. The most important function in the API to this end is:
Invoking the $fx.params() function in your code informs fx(hash) that the project is intended to be an fx(params) piece. Equally important is that this function requires an input in form of an array that defines the desired parameters such that they can be created in the interface by fx(hash). During local development of your project these parameters will also appear in fx(lens).
For the purpose of an fx(params) piece, the definitions array needs to follow a specific structure:
In essence this array is a list of objects, each of which represents an individual parameter. We'll talk more about the content of these objects in a second. Another effect of the $fx.params() function is that it feeds the parameter values back into our generative artwork’s code, such that these values can be used for the purpose of shaping the rendered graphics.
Hence, if we were to copy the above snippet of code into the index.js of a blank fx(hash) project and then boot up fx(lens) (via the CLI with fxhash dev), we would see the following controllers show up in the interface:
To recap, the effect of $fx.params() is twofold:
It informs fx(hash) of the parameters that should be exposed in the minting interface. (during local development these parameters should appear in the fx(lens) interface)
It exposes the value of these parameters in our code, such that the generative artwork’s characteristics can be based off of them.
The objects contained in the definitions array that we pass as an input to the $fx.params() function needs to follow a strict shape. In essence they are objects containing a number of key/value pairs that describe the controllers in the interface, such as the label next to the controller, the type of controller it is, the value it modulates, and the possible values that it can assume.
That is why we call these objects Parameter definitions, they essentially define (describe) the parameter controllers in the interface:
Here's an example of such a parameter definition object:
Some of the key/value pairs are optional, others are mandatory. The structure of these key/value pairs need to follow a strict set of specifications, you can find a detailed overview of these specifications in the page.
Just like the iteration hash, parameters are passed into a generative token as a URL parameter, not individually, but under the form of a single serialised string that concatenates all of the parameters. The API then de-serializes this string splitting it into individual values and mapping them to their respective variables, such that they can be accessed throughout the code:
It would not be convenient at all to input this string manually, as such we recommend using to work on your fx(hash) projects. fx(lens) comes with built-in tools and hot-reloading to facilitate iterating on your project and manipulating the various parameters as you define those in your code.
The snippet API exposes a set of utility functions which lets artists retrieve the active value of the parameters - these functions need to be called after the parameters have been defined with $fx.params():
$fx.getParam('parameter_id'): gets the value of a single parameter by its id
$fx.getParams(): gets all the parameter values as an object
$fx.getRawParam('parameter_id'): gets the raw value of a single parameter as a hexadecimal string
The $fx.getParam() function for example lets us fetch the active value of a parameter by its id (as a string value) - ‘active value’ here means the value that the parameter is set to by its respective controller in the interface (fx(lens) or minting interface):
So far, we’ve seen fx(params) as collector tweak-able variables that control certain aspects of the generated artwork. What’s more, is that fx(hash) also gives the artists control over how these parameters are updated - they don’t have to necessarily be updated from the control panel, but can also be modulated via the code itself.
The parameter definitions have a special property called ‘update’ which allows the artist to control how this parameter is updated.
The default update mode is page-reload and describes the known behaviour of updating the parameter by performing a full page-reload of the project. Meaning that the entire code of the generative artwork needs to be re-run to apply this parameter change. The are other options for update property, that behave differently and don’t require a full refresh of the project page.
For instance, when setting the update mode of a parameter to sync, the change of this parameter via its respective controller would not trigger a full page reload and update the parameter value in real-time:
Updates on parameters with update: "sync" are received in the background in real-time. Naturally this also requires the artist to structure their code differently for this parameter change to be applied. When using the sync update mode, the artwork code needs to be actively redrawn inside of a loop that can respond when such a synced parameter is changed, (e.g. via requestAnimationFrame), in that manner the code can receive those changes during the runtime of this loop.
For even more advanced use cases, e.g. if you want to only re-render your artwork when the values of your parameters are changing, you can use the new event listeners described in the section on , which is detailed in the .
Besides the sync update mode, another mode is code-driven, which is by far the most interesting and versatile one. page-reload and sync both rely on a signal and change in the external UI to update the parameter value. The code-driven update mode breaks this principle, and gives artists the ability to change the value of a parameter from the code, enabling completely customised minting experiences.
code-driven parameters can’t be updated from the UI and have to be controlled via the $fx.on() and $fx.emit() functions. Additionally we also need to make use of the $fx.context property to detect if the code is executed during mint time, in which we would execute additional code that accounts for the update of the code-driven parameter, or in the other contexts where this behaviour is not needed.
The following code snippt exemplifies a code-driven approach:
This is an example of an implementation. You are free to follow the patterns of your choice.
$fx.params(definitions) // API function that creates the parameters in the interfacedefinitions = [
{
id: "number_id",
name: "A number",
type: "number",
},
{
id: "boolean_id",
name: "A boolean",
type: "boolean",
},
{
id: "color_id",
name: "A color",
type: "color",
},
]**{
id: "number_id", // required
name: "A number", // optional
type: "number", // required
options: { // optional
min: -10,
max: 10,
step: 0.1,
},
}**const paramValue = $fx.getParam('number_id'){
id: "number_id",
name: "A number/float64",
type: "number",
update: "sync", // <-- new update property
},
// defining parameters two code-driven parameters
// that are uneditable from ui, and will be controlled by the code!!
$fx.params([
{
id: "size",
name: "Size",
type: "number",
update: "code-driven",
},
{
id: "x_pos",
name: "X position",
type: "number",
update: "code-driven",
},
])
// this is the draw loop in which we render the graphics
// and listen for changes of the code-driven parameters
function draw() {
// resetting the fx.rand function is important to ensure every time it's
// called, the same values will be generated
$fx.rand.reset()
// GRAHPICS ARE DRAWN HERE
}
// this renders an interactive UI in the minting context
function drawUI() {
// draw UI here
}
// depending on the execution context, 2 different codes are executed
// when the code is executed in a "minting" context
// we run the first clause of the condition
if ($fx.context === "minting") {
// we draw the piece, and the UI on top
draw()
drawUI()
// updating the parameter from the code - this would be called when some input
// is registered, such as clicking the mouse for example
window.addEventListener("click", () => {
$fx.emit("params:update", {
size: Math.random(), // anything here, it will update the parameter value
})
})
// when the params are updated we re-draw the graphics and the UI
$fx.on(
"params:update",
// we do nothing when the event is received
() => {},
// once the params are updated and available, we trigger a re-draw
() => {
draw()
drawUI()
}
)
}
// the piece is ran by itself, for the final output or for the capture
else {
// we just draw
draw()
}


Overview and detailed explanations of the individual API functions
A reference for fx(params) related API functions can be found in the API Reference fx(params)
$fx.hashThe string hash injected into the iteration. Will be unique for every iteration of a project. Directly grabbed from the fxhash URL parameter when the iteration is loaded.
$fx.rand()The $fx.rand() function is a Pseudorandom Number Generator which outputs a number between 0 and 1 ([0; 1[). It uses the unique hash injected into the code as a seed, and will always output the same sequence of numbers.
The fx(hash) API provides an implementation of SFC32 () as the PRNG. The $fx.rand() function also points to the equivalent fxrand() function, although they can be used interchangeably, we recommend using the syntax that prepends the $fx object for consistency across your code.
It is not mandatory to use the $fx.rand() function as your source of randomness, you can implement the PRNG of your choice instead, as long as it uses the hash as the seed.
$fx.rand.reset()You can reset $fx.rand() PRNG to its initial state by calling $fx.rand.reset():
$fx.minterThe string wallet address of the minter injected into the iteration. Directly grabbed from the fxminter URL parameter when the iteration is loaded.
$fx.randminter()Similarly to the $fx.rand() function, the $fx.randminter() function is another Pseudorandom Number Generator that derives its randomness from the minter address injected into the code as a seed, and will always output the same sequence of numbers. It outputs a number between 0 and 1 ([0; 1[).
The fxhash snippet provides an implementation of SFC32 () as the PRNG. The $fx.randminter() function also points to the fxrandminter() function. You can use the two of them interchangeably, but we recommend using the $fx syntax for consistency accross your code.
It is not mandatory to use the $fx.randminter() function as your source of randomness, you can implement the PRNG of your choice instead, as long as it uses the minter address as the seed.
$fx.randminter.reset()Similarly to $fx.rand.reset() you can also reset the $fx.randminter() PRNG to its initial state by calling $fx.randminter.reset().
$fx.contextThe $fx.context property is a flag that indicates the context in which the code is executed. There are 3 possible values for this flag:
standalone: (default) when the final output should be displayed, on the main project page for instance
capture: when the code is executed in the capture environment, to get an image preview of an iteration
minting: when the code is executed during the minting flow of the collector
This flag is passed in by fx(hash) via the fxcontext URL parameter.
$fx.iterationThe $fx.iteration property indicates the iteration number of the collected GENTK, it can be used for experimental purposes to base certain aspects of the artwork off of it:
The iteration number is passed in by fx(hash) via the fxiteration URL parameter.
$fx.preview()The $fx.preview() function triggers the capture module when the code is run in the capture context, which creates the image previews that will be displayed by fxhash and other websites to show the collected iterations.
For projects where an animation is rendered, this function can be particularly useful to trigger a capture for a particular frame:
Also make sure to properly configure the capture settings when minting your project on fxhash, you can read more about this in
$fx.isPreviewThe $fx.isPreview is a boolean which will be set to true if your code is being run in the capture context. It can be useful when you want to run a certain snippet of code only during when the artwork is being captured.
When a capture of an iteration is taken by fxhash capture module, an url parameter preview=1 is added. The fxhash snippet detects if this parameter is set to 1 and sets $fx.isPreview to true or false based on that.
$fx.features(features)Artists have the option to expose certain characteristics in an explicit manner via fx(hash) ‘features’. Features are essentially attributes that describe certain aspects of the artwork once it is collected. For instance, the artist can choose to explicitely indicate the rarity of a certain output with a feature, or can also describe the randomly chosen color palette that is used for the coloration of the artwork by exposing the name of this color palette with another feature.
In other words, features are tags that describe the randomly chosen qualities of the collected artwork. They are entirely optional.
If you would like to set them in your project, you can do so via the $fx.features() function. This function expects as input an object with key:value pairs, where these values can have the following types string, number or boolean. Here’s an example:
What’s important is that features should not be hardcoded, but rather be randomly generated with the PRNG, and they should always match the visual characteristics of the Token (ie reflect the settings behind the generative process of the token).
$fx.features() should only be called once, as multiple calls of $fx.features() will erase features set by a previous function call. For the fx(hash) module to pick up the artist set features, the $fx.features() function must be called once the page is loaded. For instance, the following code might result in features not getting picked up by our module:
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 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 occurrences to appear.
For instance, this will not work well with the rarity module:
If defined in such a way, each token will have a different Intensity 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:
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 Intensity 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.
$fx.getFeature(name)This function outputs the value of a feature, given its name. Must be called after $fx.features(). The name parameter should match a key defined of the object passed to $fx.features():
Since this function requires the name of the feature to be passed to it, it can become quite verbose and redundant to call it every time you need to access the value of a feature, especially if you need this value a lot. In such a case, we recommend storing the feature value in a variable instead:
$fx.getFeatures()Returns the whole object passed to the $fx.features(object) function. Must be called after $fx.features().
Function
Function Signature
Purpose / Effect
$fx.hash
string
The hash string provided (or injected into) for each iteration.
$fx.rand()
() => number
Generates a pseudo-random number using the hash as the seed, ranging from 0 (inclusive) to just under 1 (exclusive).
$fx.rand.reset()
() => void
Reinitialises the $fx.rand() generator to its original state.
$fx.minter
string
The wallet address of the minter, provided (or injected into) for each iteration.
$fx.randminter()
() => number
Similar to rand(), but uses the minter's address as the seed, with the same output range.
$fx.randminter.reset()
() => void
Reinitialises the $fx.randminter() generator just like rand.reset().
$fx.context
string
Indicates where the code is running: standalone, during capture, or while minting.
$fx.iteration
number
The iteration number of the collected GENTK.
$fx.preview()
() => void
Triggers the image capture module at mint time to create the image preview for the collected iteration.
$fx.isPreview
boolean
Set to true when the code runs in the fxhash capture module. Useful for defining capture-specific properties.
$fx.features()
(object) => void
Function that specifies the features of the collected iteration.
$fx.getFeature()
(string) => any
Retrieves the value of a named feature as set by the features() function.
$fx.getFeatures()
() => object
Returns the entire features object as defined by features().
$fx.params()
(array) => void
Define collector-modifiable parameters for your piece by calling this with an array.
$fx.getParam()
(string) => any
Returns the value of a param via its ID.
$fx.getParams()
() => object
Returns a dictionary of all parameter key-value pairs, as currently set.
$fx.getRawParam()
(string) => string
Provides the raw parameter data (as a bytes string) as it was passed to the iteration.
$fx.on()
(string, function, function) => function
Registers an event listener and returns a function to deregister it.
$fx.emit()
(string, any) => void
Sends an event to the parent context, useful for dynamic parameter updates from within the code.
Open-form API
—
—
$fx.lineage
string[]
An array of hash strings. One for each of the parents in an evolved edition's lineage of parent tokens.
$fx.depth
number
Simply a number that represents the number of parents a minted edition has.
$fx.randAt: (depth: number)
number
A random number that's generated by a PRNG seeded by the individual lineage hashes at a given depth.
console.log($fx.hash) // output example: ooj2HmX8dgniNPuPRcapyXBn9vYpsNwgD1uwx98SLceF6iCZJZKconst randomNumber = $fx.rand() // number [0; 1[
const otherRandomNumber = fxrand() // same effect as above$fx.rand() // 0.25
$fx.rand() // 0.88
$fx.rand() // 0.124
// reset fxrand
$fx.rand.reset()
// calling fxrand again will yield the same outputs as the first calls
$fx.rand() // 0.25
$fx.rand() // 0.88
$fx.rand() // 0.124console.log($fx.minter) // output example: tz18jgjtEDRtkvNoV9LToradSmVNYFS9aXEeconst rand01 = $fx.randminter() // number [0; 1[
const r2 = fxrandminter() // same effect as above$fx.randminter() // 0.25
$fx.randminter() // 0.88
$fx.randminter() // 0.124
// reset fxrandminter
$fx.randminter.reset()
// calling fxrandminter again will yield the same outputs as the first calls
$fx.randminter() // 0.25
$fx.randminter() // 0.88
$fx.randminter() // 0.124if ($fx.context === "minting") {
// run code for the minting UI
} else {
// otherwise display the final output
}console.log($fx.iteration) // output example: 42function draw() {
// ...
// code that generates the graphics
// ...
// trigger the capture module when all graphics have been generated
$fx.preview()
}let counter = 0
function draw() {
// ...
// code that generates the graphics
// ...
// increment frame counter
counter++
// when reaching frame 6000, trigger the capture
if (counter === 6000) {
$fx.preview()
}
requestAnimationFrame(draw)
}
requestAnimationFrame(draw)if ($fx.isPreview) {
// will be executed only when preview is taken by fxhash
} else {
// usual execution
}// call this function before performing computations
$fx.features({
'A feature of type string': $fx.rand() > 0.5 ? 'Super cool' : 'Not cool !',
'Feature number': Math.floor($fx.rand() * 100),
'A boolean feature': $fx.rand() > 0.8 > true : false,
'A constant feature': 'constant value',
})// WILL NOT WORK CONSISTENTLY
setTimeout(() => {
$fx.features({
// here define the token features
})
}, 1000)$fx.features({
// each token will have a different "Intensity" feature value between 0 and 1
Intensity: fxrand(),
})function getFeatureString(value) {
if (value < 0.5) return "low"
if (value < 0.9) return "medium"
else return "high"
}
$fx.features({
// feature can only be "low", "medium" or "high"
Intensity: getFeatureString(fxrand()),
})// defining the features
$fx.features({
"First feature": 0.5,
"Another feature": true,
})
// outputs "0.5"
console.log($fx.getFeature("First feature"))
// outputs "true"
console.log($fx.getFeature("Another feature"))const feat1 = "feature value here"
$fx.features({
"A very long feature name, not practical": feat1,
})
// same outputs
console.log($fx.getFeature("A very long feature name, not practical"))
console.log(feat1)// first define the features
$fx.features({
"feat 1": 0.8,
"feat 2": true,
})
// outputs:
// {
// "feat 1": 0.8,
// "feat 2": true
// }
console.log($fx.getFeatures())An overview of the parameter definition specifications and the different types of parameters that are currently available.
When calling $fx.params(definition), a definition array of parameter definitions must be passed to the function. This array must be constant, which means that the same value must be passed every time the code is executed. There cannot be any source of randomness in the definition.
A parameter definition is an object following strict guidelines. Example:
The TypeScript type for a parameter definition is:
Each property's role is outlined as follows:
id required
A string identifier, which will be used to get the parameter value later in the code. This is also used to populate an object of the different parameter [id; value] when the bytes are deserialized into values when $fx.params() is called.
Each id must be unique! Two parameters cannot have the same id.
name optional
A string which will be used as a display name on the minting interface. If not set, the parameter name will be its id. We recommend setting a name for every parameter so that collectors can see a nice text displayed next to the controller. We also recommend sticking with short names to keep the minting UI clean.
type required
The type of the parameter, must be one of the available types (number, string, boolean, color, select, bigint). See below for each type specification.
default optional
A default value for the parameter. If defined, when the minting interface with the controllers is loaded, the corresponding value of the controller will be set to this one. If not set, the controller value will be set to a random one within the constraints defined in the parameter options.
update optional
Specifies the update mode of the parameter. There are 3 update modes available:
page-reload: (default) the parameter can only be updated from the fxhash UI, the whole project will be refreshed when any page-reload parameter is updated
sync: the parameter can only be updated from the fxhash UI, will be sent to the project when the parameter is update. The page is not refreshed, so you need to handle the update of the view yourself
code-driven: the parameter can only be updated from your code, by.
General overview of params update in the .
options optional
An object with type-specific options. Each type has specific options, described in the section below. Default values are used for each option if not defined. The default values are also described in the section below.
Each type comes with specifications:
a list of available options
a format in which the bytes are deserialized and made available to your code
a kind of controller which will be displayed to modulate the parameter (this will happen outside the context of the piece itself, most often in a parent context)
numberNumbers are deserialised into (default javascript number type).
Option Table
Example:
Corresponding controller: a slider and a text input
stringStrings are deserialised into a series of UTF-8 characters.
Option Table
Example:
Corresponding controller: a text input
booleanBooleans are deserialised into native javascript booleans.
There are no available options for the boolean type.
Example:
Corresponding controller: a checkbox
colorColours are serialised with 4 bytes, each byte representing the value between 0 and 255 of one channel (red, green, blue, alpha). When a colour is deserialised, it is processed into an utility-object to facilitate their usage.
The object is constructed as follows:
There are no available options for the color type.
Example:
Corresponding controller: a color picker and a text input
bytesArbitrary data which can only be manipulated with code, not from the UI; the update mode must be code-driven. Allows to store bytes in an optimised way, the bytes are serialised to hexadecimal and deserialised to .
Example:
selectA select is defined by a list of strings, where each string defines an option which can be selected. A select can take up to 256 entries. A select is stored as a single byte on-chain, which is the hexadecimal representation of a number between 0 and 255, corresponding to the index of the selected option in the array of options. When deserialised, the string of the option is extracted.
The options property of a select is required and must be an array of strings, corresponding to the available options.
Option Table:
Example:
Corresponding controller: a select with various options
bigintA bigint is deserialized into an int64, which is the . Bigint can represent very big integer values which cannot be represented usually with javascript float numbers (between -9223372036854775808 and 9223372036854775807). If you need an integer value between -9007199254740991 and 9007199254740991, use the number type instead as integer values can be represented with 100% precision with float64.
Option Table:
Example:
Corresponding controller: a slider and a text input
Detailed explanations of the individual API functions related to fxparams
$fx.params()
(array) => void
Define collector-modifiable parameters for your piece by calling this with an array.
$fx.getParam()
(string) => any
Returns the value of a param via its ID.
$fx.getParams()
() => object
Returns a dictionary of all parameter key-value pairs, as currently set.
$fx.params(definition)The $fx.params(definition) function is necessary to create an fx(params) piece, it takes as input a list of parameters definitions that collectors can modulate and tweak to create their own custom iterations. Parameter definitions are object that contain a number of key/value pairs that describe the parameters.
Here is an example of this definition array:
Invoking the $fx.params() function has a number of important effects:
It informs fxhash that the project is an fx(params) project and creates the respective controllers in the UI (if the params are not code-driven)
It reads the fxparams URL parameter, processes the bytes and converts it into values based on the provided definitions and maps them to their respective variables to generate the corresponding artwork.
The values of the parameters are stored and made accessible throughout the artist’s code via utility functions.
$fx.getParam(id)Returns the value of a parameter based on the params definition provided to $fx.params(definition) and the input bytes passed to the code via URL parameters (&fxparams={byte_sequence_here}), the bytes sequence will be processed by $fx.params() when it is called.
The $fx.getParam(id) will fetch and return the value of parameter through its id as defined in your params definition:
Depending on the type of the parameter, the fxhash snippet may apply extra processing to facilitate their usage in your code. For instance, in the case of color parameter, it will be returned in different forms. section for more details on each parameter type.
$fx.getParams()Returns an object containing all parameters, where the keys in this object are the individual parameter ids:
$fx.getRawParam(id)Given a parameter id, $fx.getRawParam(id) returns the hexadecimal string byte sequence corresponding to that parameter, before processing and converting it into a value:
$fx.emit(eventId, data)This function is mainly used for the purpose of updating parameters that have their update mode set to code-driven. As its name suggests, $fx.emit(eventId, data) allows you to emit events (think of it like a signal), to an fxhash specific pipeline of events, which can then be listened to by the $fx.on() function. Currently there is only one type of event that is supported, namely the param:update signal.
Additionally, this event can also carry a payload which can be specified with the second input parameter of the $fx.emit function, the data variable. The data variable should be an object where the key/value pairs are the parameter ids and the updated associated values respectively. This is still subject to the constraints of the parameter (as set by its parameter definition), so for instance if a number between 0 and 10 is expected and you pass a value of 12, it will clamp to 10. You are not required to pass all the parameters in the data, only those which need to be updated.
Here’s an example, let’s first set up a couple of parameters:
And then send out an event whenever we move the mouse:
Here we used a native Javascript eventlistener to detect whenever the mouse is moved, making it in turn trigger the $fx.emit() function to update the mouse_x parameter.
Following is the typescript definition of the $fx.emit function:
$fx.on(eventId, handler, onDone)The $fx.on() function listens to events in the fxhash pipeline that are emitted by $fx.emit(). Currently there is only one type of event that is supported, namely the param:update event. $fx.on() can then trigger functions when this event is registered and certain conditions are met. Note that the eventId must match an existing eventId that you can subscribe to.
The handler is the function that is called when the event is triggered. Additionally you can opt-out of the default behaviour of an event handler by returning false from the handler. The onDone function is called as the last thing of any event, e.g. after the default behaviour of the event was applied.
Following is the typescript definition of the $fx.on function:
The function returned by the $fx.on function can be called to remove the registered event listener.
Note: there are 2 ways to apply changes to the UI when you emit a parameter from the code:
$fx.params([
{
id: "number_id",
name: "A number",
type: "number",
options: {
min: -10,
max: 10,
step: 0.1,
},
},
{
id: "boolean_id",
name: "A boolean",
type: "boolean",
},
{
id: "color_id",
name: "A color",
type: "color",
},
])// a parameter definition
type ParameterDefinitionType = {
id: string // required
name?: string // optional, if not defined name == id
type: "number" | "string" | "boolean" | "color" | "select" | "bigint" // required
default?: string | number | bigint | boolean // optional
update?: "page-reload" | "sync" | "code-driven" // optional
options?: TYPE_SPECIFIC_OPTIONS // (optional) different options per type (see below)
}Property
Type
Default
Description
min
number
The minimum value the number can take. Controllers will be bound to [min; max]
max
number
The maximum value the number can take. Controllers will be bound to [min; max]
step
number
undefined
If defined, specifies the granularity that the value must adhere to. Only values which are equal to the basis for stepping (default if specified, min otherwise, eventually the random value generated if none are specified) are valid. If undefined, any number is accepted.
Property
Type
Default
Description
minLength
number
0
The minimum number of characters which has to be inputted
maxLength
number
64
The maximum number of character which can be inputted. We recommend keeping this value as low as possible, because this will always be the number of bytes sent onchain, even if a smaller string is inputted.
Property
Type
Default
Description
length
number
0
(Required) The maximum number of bytes which can be stored by this bytes parameter buffer.
Property
Required
Type
Default
Description
options
Required
string[]
/
A list of strings, corresponding to available options in the select.
Property
Type
Default
Description
min
number
-9223372036854775808
The minimum value the number can take. Controllers will be bound to [min; max]
max
number
9223372036854775807
The maximum value the number can take. Controllers will be bound to [min; max]
$fx.getRawParam()
(string) => string
Provides the raw parameter data (as a bytes string) as it was passed to the iteration.
von()
(string, function, function) => function
Registers an event listener and returns a function to deregister it.
$fx.emit()
(string, any) => void
Sends an event to the parent context, useful for dynamic parameter updates from within the code.
$fx.params([
{
id: "a_number",
name: "A number",
type: "number",
default: 5,
options: {
min: -10,
max: 10,
step: 1,
},
},
])$fx.params([
{
id: "a_string",
name: "A string",
type: "string",
default: "Default value",
options: {
minLength: 5,
maxLength: 32,
},
},
])$fx.params([
{
id: "a_boolean",
name: "A boolean",
type: "boolean",
default: false,
},
]){
arr: {
rgb: [25, 6, 158],
rgba: [25, 6, 158, 104],
},
hex: {
rgb: "#19069e",
rgba: "#19069e68",
},
obj: {
rgb: { r: 25, g: 6, b: 158 },
rgba: { r: 25, g: 6, b: 158, a: 104 },
}
}$fx.params([
{
id: "a_color",
name: "A color",
type: "color",
default: "abababff",
},
])$fx.params([
{
id: "some_bytes",
name: "Some bytes",
type: "bytes",
update: "code-driven", // required!!
options: {
length: 4,
},
// the default value must be an Uint8Array
default: new Uint8Array([0, 255, 48, 57]),
},
])$fx.params([
{
id: "a_select",
name: "A select",
type: "select",
default: "one",
options: {
options: ["one", "two", "three", "four"],
},
},
])// output example:
// "one"
console.log($fx.getParam("a_select"))$fx.params([
{
id: "a_bigint",
name: "A BigInt",
type: "bigint",
default: 1458965n,
options: {
min: -1000000000000000n,
max: 1000000000000000n,
},
},
])// this is how params are defined
$fx.params([
{
id: "number_id",
name: "A number",
type: "number",
options: {
min: -10,
max: 10,
step: 0.1,
},
},
{
id: "boolean_id",
name: "A boolean",
type: "boolean",
//default: true,
},
{
id: "color_id",
name: "A color",
type: "color",
},
])// define the params
$fx.params([
{
id: "a_param_id", // this property will be used for $fx.getParam(id)
name: "A random name",
type: "boolean",
},
{
id: "another_param",
name: "Super param!",
type: "color",
},
])
// depending on the sequence of bytes injected into the code when it's executed,
// the values will be different
// get the value of parameter "A random name"
// output example:
// true
console.log($fx.getParam("a_param_id"))
// get the value of parameter "Super param!"
// output example:
// {
// arr: {
// rgb: [25, 6, 158],
// rgba: [25, 6, 158, 104],
// },
// hex: {
// rgb: "#19069e",
// rgba: "#19069e68",
// },
// obj: {
// rgb: { r: 25, g: 6, b: 158 },
// rgba: { r: 25, g: 6, b: 158, a: 104 },
// }
// }
console.log($fx.getParam("another_param"))// define the params
$fx.params([
{
id: "a_param_id", // this property will be used for $fx.getParam(id)
name: "A random name",
type: "boolean",
},
{
id: "another_param",
name: "Super param!",
type: "color",
},
])
console.log($fx.getParams())
// output example:
// {
// a_param_id: false,
// another_param: {
// arr: {
// rgb: [25, 6, 158],
// rgba: [25, 6, 158, 104],
// },
// hex: {
// rgb: "#19069e",
// rgba: "#19069e68",
// },
// obj: {
// rgb: { r: 25, g: 6, b: 158 },
// rgba: { r: 25, g: 6, b: 158, a: 104 },
// }
// }
// }
// the byte sequence injected determines the value of the parameters
// define the params
$fx.params([
{
id: "a_param_id", // this property will be used for $fx.getParam(id)
name: "A random name",
type: "boolean",
},
{
id: "another_param",
name: "Super param!",
type: "color",
},
])
// depending on the sequence of bytes injected into the code when it's executed,
// the values will be different
// get the value of parameter "A random name"
// output example:
// "01"
console.log($fx.getRawParam("a_param_id"))
// get the value of parameter "Super param!"
// output example:
// "19069e68"
console.log($fx.getParam("another_param"))// define your parameters
$fx.params([
{
id: "mouse_x",
type: "number",
// a code-driven parameter
update: "code-driven",
},
{
id: "number_2",
type: "number",
// a code-driven parameter
update: "code-driven",
},
{
id: "number_3",
type: "number",
// a normal parameter, cannot update with params:update
update: "page-reload",
},
])// example: when the mouse moves, we update the first parameter
window.addEventListener("mousemove", evt => {
const X = evt.clientX / window.innerWidth // normalized X position of mouse
// we request the update of a parameter
$fx.emit("params:update", {
mouse_x: X,
})
})type FxEmitFunction = (
eventId: string
data: any
) => void// define your parameters
$fx.params([
{
id: "number_id",
type: "number",
update: "sync",
},
])
function main() {
// render artwork
}
$fx.on(
"params:update", // subscribe to the params update event
newValues => {
// opt-out param update when number_id is 5
if (newValues.number_id === 5) return false
// opt-in any other param value update
return true
},
() => main() // render artwork when event was handled
)type FxOnFunction = (
eventId: string
handler: (...args) => boolean | Promise<boolean>
onDone: (optInDefault: boolean, ...args) => void
) => () => voidconst removeListener = $fx.on("params:update", newValues => {
// do something
})
removeListener() // <-- Will remove the event listener// FIRST WAY
// Emit the update, and update the view only when receiving the params:update
// back. This ensures a proper flow of data, and a proper sync of the minting
// UI and your project
window.addEventListener("mousemove", evt => {
const X = evt.clientX / window.innerWidth
$fx.emit("params:update", {
mouse_x: X,
})
})
$fx.on("params:update",
() => {}, // do nothing to check the params received
() => { // once the update is fully registered, update the view
draw()
// in this case draw() can rely on $fx.getParam("mouse_x") to be synced with
// the up-to-date value
}
)// SECOND WAY
// Custom draw logic where the params effects are applied right after emitting
// the update
window.addEventListener("mousemove", evt => {
const X = evt.clientX / window.innerWidth
$fx.emit("params:update", {
mouse_x: X,
})
// here trigger a draw, but you need to handle the change in value manually,
// as $fx.getParam("mouse_x) will point to the old value
draw(X)
})An overview of the different capture contexts and capture settings
The fxhash API exposes a $fx.context flag—a string value that specifies in which execution context fxhash is running your code. The $fx.context variable can currently assume one of four values:
standalone
When fxhash runs your project's code directly in the browser—"live mode".
capture
When fxhash runs your code on the backend to generate an image/GIF preview to display on the frontend.
Since the $fx.context property is a flag that indicates the context in which the code is executed—in most cases you will want to have a conditional block in your code that checks for the different contexts and then renders the artwork according to the use-case:
This is useful when you want to display your artwork differently in each context. If your artwork display the same everywhere, you can simply not use $fx.context at all, and invoke the preview when the artwork has finished rendering.
Capture contexts work the same way in both long-form and open-form projects—during the check-files step of the creation flow you can toggle between the different contexts to check that they are working properly and the way you have intended with your code.
fxlens will also let you set this execution context to verify that your code is working properly.
In the configure-capture step of the creation flow, you will set up how fxhash creates the preview images of the artworks that your code generates, whenever a collectors mints or evolves a new edition:
There’s two different methods for triggering the capture module:
Programmatically with $fx.preview(): The capture module will wait until your code calls the fxpreview() function. As soon as it is invoked, the capture will be triggered. The placement of this function in your code is up to you, but usually it should be placed towards the end of your code, when all of the graphics have been rendered. If the piece is animated you might want to trigger it after the initial frame has been drawn.
If your project is loading asynchronous requests from the project's folder, always consider that these resources may be slow to load—please always use fxpreview() to trigger the capture in this case.
The capture module will automatically take a capture after 300 seconds have passed after your project was loaded in the browser. Hence it is important that the rendering of your graphics completes within this timeframe, otherwise it might lead to undesirable preview images.
In the case of our example token we’re using the programmatic trigger since it is a static artwork where we want to trigger the capture after all shapes have been rendered to the canvas. After setting the capture trigger we also need to indicate the target of this capture; this can be a canvas element, or the entire viewport.
In this example we only want to capture the canvas element, and not the entire viewport—selecting the From <canvas> option will reveal a third input field that lets us point the capture module to the HTML canvas element we want to capture:
Otherwise, if you choose to capture the entire viewport, you can specifiy the dimensions of the viewport at the time of capture (the size of the browser window essentially, in which your code runs):
If your project requires a GPU to render, you should use enable GPU-supported rendering for your capture.
Booting up the GPU capture can be slow however, and can take up to a couple of minutes to finish rendering.
We now also support GIF preview captures, that enable animated thumbnails for collected editions of your project. Currently GIF captures are limited in that fxhash will simply record your selected target or viewport for a set number of frames and at a specified interval—rather than programmatically triggering individual frame captures from your code (but this is in the works!)
When toggling on GIF capture for your project, you don't need to trigger $fx.preview(), it will simply start recording from when your code runs.
In other settings where GIF previews are not available, the middle frame of the GIF will be used a thumbnail. For example, if the GIF has 20 frames, it will use the 10th frame as a thumbnail.
fast-capture contextThere are a few limitations to the fast-capture context:
The GPU is disabled during fast-captures
GIF captures are not available as fast-captures
This is simply because both of these capture methods can not be generated very quickly—if this doesn't suit your project, you can either ignore the fast-capture context or build a creative intermediary preview into your artwork that reveals something about the artwork before the actual preview is rendered.
Additionaly, the fast-capture will also be taken according to the capture trigger method you have selected for your project:
If you're using $fx.preview() as a trigger method, simply call $fx.preview() when you want the fast capture to be taken—preferably as early as possible—in a fast-capture clause in your code.
If you're taking the capture after a timed delay, the fast capture will trigger when the selected delay has elapsed, or at a maximum of 1 second.
And in case you are using the GIF capture for your previews, you still need to call $fx.preview() as a fast-capture trigger.
fast-capture
A new context that lets you generate a preliminary preview to display before the actual preview image is generated—useful for intensive projects that require a couple of seconds to render. In essence this can be your custom "waiting to be signed" preview image.
minting
When fxhash runs your project's code in the fxparams minting interface.
if ($fx.context === "fast-capture") {
// generate your fast-capture placeholder image here
// then trigger the capture with $fx.preview()
$fx.preview()
} else if ($fx.context === "capture") {
// generate the preview image that you want to display on fxhash
// then trigger the capture with $fx.preview()
$fx.preview()
} else {
// here goes what you intend to display when your
// code is run and viewed directly in the browser
}








