All pages
Powered by GitBook
1 of 7

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

API Overview

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).

What is an SDK?

SDK is an abbreviation for the term Software Development Kit, an SDK usually represents a bundle of code, tools, and documentation provided by the creators of a platform for third party developers, and is aimed at aiding them in creating software that is compatible with the platform.

What is an API?

The abbreviation API stands for Application Programming Interface, and refers to the code part of an SDK. It's a software-to-software interface that allows developers to build platform specific software. APIs usually provide numerous functionalities that are useful and sometimes necessary for the purpose of compatibility.

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 .

Why do we need to use the API?

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.

What does the 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.

What is the window Object?

In JavaScript, the window object represents the global context for a web page or a browser environment. It is the top-level object that contains global variables and functions accessible throughout the entire JavaScript runtime in a web page. Attaching new properties/variables makes them accessible throughout the scope of all scripts, which is why the $fx API object is attached as such 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.

What is this $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.

What is an Object in programming?

Objects in programming are usually containers for variables and functions. The contained variables and functions are referred to as member variables and methods respectively. They can be accessed and invoked using the dot notation, for example $fx.rand() invokes the rand() function contained inside the $fx object.

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 .

page
for an reference of the general API
this page for a reference of the fxparams module of the API
Projects on fxhash are deterministic generative artworks that can reliably re-generate the same output when the same input hash is used injected into their code.
the structure of an fx(hash) project
the boilerplate
API Overview
API Reference
The $fx object that is instantiated by the fxhash.js script, logged to the browser console.
console.log($fx) // logging the $fx object to the console

fxhash API

fxparams module

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.

What is fx(params)?

fx(params) is an alternative method to building and collecting generative art on fx(hash).

Instead of entirely leaving all aspects of the minted iteration up to randomness, the artist can now choose certain parameters that they would like to expose and give the collector control over at mint time.

fx(params) is the name of the module in the fx(hash) API that gives artists the tools to expose a set of parameters and custom minting interfaces for the collectors to modulate and play with before minting/collecting their own individually customised iterations.

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 .

Using the fx(params) Module of the API

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.

Parameter Definitions

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:

What is a Parameter Definition?

In the context of fx(hash), a Parameter definition is a small Javascript object that contains a number of properties (key/value pairs) that define specific parameters. These parameter definitions describe the appearance of the parameter controller in the interface, and how they should be referenced within the artists’ code.

Parameter definitions always require an id and a type, where the id is needed to later retrieve this parameter in the artist's code, and the type, as the name suggests, is required to specify what kind of parameter it is.

Parameter definitions also have optional properties, such as a name, that the artist can assign and will be displayed as a label in the controller interface. Another options property can be appended depending on the type of the parameter.

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.

How does fx(hash) inject Parameters?

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.

Retrieving Parameter Values within the Artist’s 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):

Update Modes

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 .

Code-driven parameters

What are Code Driven Parameters?

Code driven parameters are special interactive parameters that are controlled via the artists’ code rather than controllers in the interface. Similarly to the sync update mode, the parameters are also updated in real time without reloading the artwork, with the difference that they’re updated from within the code rather than the controller interface.

This allows for much more intricate ways of collector collaboration, where in some instances they can directly interact with the artwork, can get hands on for customisation purposes, and artists can even set up custom minting interfaces.

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) API Reference
Parameter Definition Specifications
fx(lens)
$fx.on
fx(params) API reference
$fx.params(definitions) // API function that creates the parameters in the interface
definitions = [
{
	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()
}

API Reference

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)

API Overview

Explanation of the open-form part of the API:

$fx.hash

The 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.minter

The 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.context

The $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.iteration

The $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.isPreview

The $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.

Programming Open-form Genart
Standard Fast Counter 32
Standard Fast Counter 32
Minting Interface Walkthrough
strict equality
console.log($fx.hash) // output example: ooj2HmX8dgniNPuPRcapyXBn9vYpsNwgD1uwx98SLceF6iCZJZK
const 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.124
console.log($fx.minter) // output example: tz18jgjtEDRtkvNoV9LToradSmVNYFS9aXEe
const 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.124
if ($fx.context === "minting") {
// run code for the minting UI
} else {
// otherwise display the final output
}
console.log($fx.iteration) // output example: 42
function 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())

Parameter Definition Specs

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:

Definition Specifications

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.


Parameter Types

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)

number

Numbers are deserialised into (default javascript number type).

Option Table

Example:

Corresponding controller: a slider and a text input


string

Strings are deserialised into a series of UTF-8 characters.

Option Table

Example:

Corresponding controller: a text input


boolean

Booleans are deserialised into native javascript booleans.

There are no available options for the boolean type.

Example:

Corresponding controller: a checkbox


color

Colours 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


bytes

Arbitrary 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:


select

A 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


bigint

A 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

fxparams API Reference

Detailed explanations of the individual API functions related to fxparams

Function
Function Signature
Purpose Effect

$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.

You can learn more about the speficications for the these parameter definitions here:

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.params() must be called before trying to access any parameter value with the parameter fetching functions that follow.

$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

Number.MIN_VALUE

The minimum value the number can take. Controllers will be bound to [min; max]

max

number

Number.MAX_VALUE

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]

a params:update event
emitting a params.update event
fx(params) section
javascript float64 numbers
Uint8Array
BigInt javascript type

$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.

Parameter Definition Specifications
See the parameter definition specifications
$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
) => () => void
const 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)
})

Capture Contexts & Preview Settings

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:

$fx.context
description

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.

How to use $fx.context in your project code

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.

Capture & Preview Settings

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):

Using GPU accelerated captures

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.

GIF captures

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.

Notes about the fast-capture context

There 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.

Automatically after a fixed delay: a fixed time delay indicates that the capture module should trigger automatically after a certain amount of time after the project is loaded. Selecting this option will make a slider appear where you can set how many seconds the capture should wait before triggering, up to 300 seconds.

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.

For this project we are using the $fx.preview() function
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
}