DEV Community

Cover image for Learning Xahau: Building an Automatic NFT Factory with Hooks
Ekiserrepe
Ekiserrepe

Posted on • Edited on

Learning Xahau: Building an Automatic NFT Factory with Hooks

Welcome to a new chapter of Learning Xahau, where we explore the theoretical and practical aspects of the Xahau blockchain. If you are new to the series, I recommend starting with the first article to understand what Xahau is and what makes it different.

Today we are going to build something concrete: an automatic NFT factory. A Hook that turns a Xahau account into a URIToken vending machine: the user pays, the Hook mints. No marketplace. No backend. No servers. Just on-chain logic.

The source code is available at: https://github.com/Ekiserrepe/auto_nft_factory_xahau


The problem we want to solve

Imagine you are an artist, a project, or simply someone who wants to distribute an NFT collection on Xahau. You have your images uploaded to IPFS, your metadata prepared, and you know exactly how much you want to charge for each piece. Now what?

The usual options are:

  • Registering on a marketplace and giving control of the process to a third-party platform.
  • Building your own backend: a server that listens for incoming payments, mints the corresponding NFT, and sends it to the buyer. This means infrastructure, maintenance, costs, and a centralized point of failure.

None of these options are ideal if what you want is autonomy and simplicity. This is where Xahau, with its Hook system, offers a completely different alternative.


The solution: a Hook as an automatic factory

The NFT Factory Hook is a smart contract written in C that is installed directly on a Xahau account. From that moment on, every time someone sends an exact payment of XAH to that account, the Hook:

  1. Validates that the received amount exactly matches the configured price.
  2. Reads the minted NFT counter from the Hook state.
  3. Increments the counter and verifies that the collection limit has not been exceeded.
  4. Builds the final URI: base path + zero-padded number + extension.
  5. Emits a URIToken Remit transaction that mints the NFT and sends it directly to the buyer.
  6. Stores the new counter in the Hook state for the next mint.

All of this happens in a single atomic process, without external servers and without human intervention.


What is a URIToken?

Before diving into the technical details, it is worth clarifying what URITokens are, which is the native NFT standard of Xahau.

URITokens are simple and unique objects directly linked to an account. Each URIToken has:

  • A URI pointing to the content (image, metadata, etc.), typically stored on IPFS.
  • A single owner at any given time.
  • The ability to be transferred or burned.

They are easy to index and manage, and thanks to Hooks you can implement custom logic such as royalties or transfer restrictions.

If you need to find information about NFTs on Xahau for your projects, here are a couple of APIs you can use:

The Xahau Remit transaction allows you, in a single operation, to mint a new URIToken and transfer it to the recipient without requiring the recipient to authorize receiving it, as happens with URITokenCreateSellOffer. This is exactly what we use in this Hook.


How the Hook works internally

Configuration parameters

When installing our Hook, we must prepare the following parameters. The Hook is configured at installation time using these four parameters:

Parameter Type Size Description
AMOUNT uint64 big-endian 8 bytes Exact price in XAH drops
URI ASCII 1–200 bytes Base IPFS content path (with trailing slash)
EXT ASCII 1–16 bytes File extension: .json, .png, etc.
NUM uint32 big-endian 4 bytes Maximum number of NFTs in the collection

For example, for a collection of 100 NFTs priced at 10 XAH each:

AMOUNT → 0000000000989680   (10,000,000 drops = 10 XAH)
NUM    → 00000064            (100 NFTs)
URI    → ipfs://bafybei.../  (your IPFS CID)
EXT    → .json
Enter fullscreen mode Exit fullscreen mode

You can encode your own values here:
https://transia-rnd.github.io/xrpl-hex-visualizer/

Example parameters

To make it easier for you to practice with this exercise, I have uploaded two test NFT collections to IPFS: one with 100 NFTs and another with 10 NFTs.

100 NFTs (Includes files XXX.json)

ipfs://bafybeig5t3mn2s2mv6ns7o65ee4qz6gw7w47hdovjtmq54qz6fsiv2ctfu/

10 NFTs (Includes files XX.json)

ipfs://bafybeifhquw7q5wsd3h5t6r5j6mjtvroivfv3du7wbqgl6jbdgyrmbn6vq/


The generated URI format

Each NFT receives a unique URI constructed as follows:

<URI> + <zero-padded counter> + <EXT>
Enter fullscreen mode Exit fullscreen mode

The counter width is automatically calculated from the number of digits in NUM:

NUM Width Resulting URI example
25 2 ipfs://.../01.json
1000 4 ipfs://.../0001.json
100000 6 ipfs://.../000001.json

This guarantees that NFTs are correctly ordered in any system that indexes by URI.

The Hook state

We need to store the number of NFTs minted so far in memory so that the hook does not mint the same NFT twice or skip any. The hook stores this counter value in the variable CNT:

Key Size Content
CNT 4 bytes Number of the last minted NFT, big-endian uint32

The state is only updated after a successful emission, so a failed transaction never advances the counter. The first mint starts from 0 and mints number 1. This ensures the hook does not skip NFTs.

The minting flow

Incoming XAH payment
       │
       ▼
Is it exactly AMOUNT drops?  ──No──▶ rollback (payment rejected)
       │ Yes
       ▼
Is CNT + 1 ≤ NUM?  ──No──▶ rollback (collection sold out, payment rejected)
       │ Yes
       ▼
Build URI: base + counter + extension
       │
       ▼
Emit URIToken Remit → NFT minted and sent to buyer
       │
       ▼
Store new CNT in state
       │
       ▼
accept ✓
Enter fullscreen mode Exit fullscreen mode

An important detail: when the collection is sold out or the payment does not match, the Hook calls rollback, which rejects the entire transaction. The buyer does not lose their XAH because the payment never gets executed.

Another detail is that the Remit transaction used to send the URIToken will send 0.20 XAH to the user so they can accept the NFT in case their balance reaches zero when purchasing the NFT. Therefore you will need to take this into account when setting the NFT price.


How to install the Hook

There are two ways to activate the Hook on your account.

Option A: Deploy from your own .wasm

Use create_hook_nft_factory.js to deploy the Hook from the .wasm binary you compiled yourself. This option gives you full control over the code running on-chain.

To compile the source code you need the hook-toolkit:

hooks-cli init c nft_factory
cd nft_factory
yarn install
yarn run build
Enter fullscreen mode Exit fullscreen mode

Option B: Install using the already deployed HookHash

If you prefer not to compile, use install_hook_nft_factory.js to reference the binary that is already deployed on the network. The script points directly to the Hook by its hash, without uploading new code.

The HookHash corresponding to the source code in this repository is:

6786DE24C37FFCDEED643CED581793D4E47BC54FA0D796D35FEA0CBF1338C19B
Enter fullscreen mode Exit fullscreen mode

This hash is valid on both Xahau Testnet and Xahau Mainnet.

You will need to edit each HookParameterValue with the values that define your collection. In this code, the order is IPFS, EXT, NUM, AMOUNT. Check the Configuration parameters section aboce to see how to fill them using https://transia-rnd.github.io/xrpl-hex-visualizer/

"TransactionType": "SetHook",
      "Account": my_wallet.address,
      "Flags": 0,
      "Hooks": [
        {
          "Hook": {
            "HookHash": "6786DE24C37FFCDEED643CED581793D4E47BC54FA0D796D35FEA0CBF1338C19B",
            "HookOn": 'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBFFFFE', //Only Payments https://richardah.github.io/xrpl-hookon-calculator/
            "HookCanEmit": "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFFFFFFFFBFFFFF", //Can emit remits
            "HookNamespace": crypto.createHash('sha256').update('nft_factory').digest('hex').toUpperCase(),
            "Flags": 1,
            "HookParameters": [
              {
              "HookParameter": {
              "HookParameterName": "555249", //URI base
              "HookParameterValue": stringToHex("ipfs://bafybeig5t3mn2s2mv6ns7o65ee4qz6gw7w47hdovjtmq54qz6fsiv2ctfu/"),
              }
              },
              {
              "HookParameter": {
              "HookParameterName": "455854", //EXTENSION
              "HookParameterValue": "2E6A736F6E" //.json
              }
              },
              {
              "HookParameter": {
              "HookParameterName": "4E554D", //NUMBER OF NFTS
              "HookParameterValue": "00000064" //100
              }
              },
                            {
              "HookParameter": {
              "HookParameterName": "414D4F554E54", //AMOUNT XAH
              "HookParameterValue": "0000000000989680" // 10000000
              }
              }
              ]
          }
        }
      ],
Enter fullscreen mode Exit fullscreen mode

Warning: This Hook is provided as-is. The author is not responsible for any problems it may cause. It is strongly recommended that you compile and audit your own version. Community forks and improvements are welcome.


Practical considerations

Always test on testnet first

Before installing the Hook on mainnet, deploy it on testnet:

const network = 'wss://xahau-test.net'; // Testnet
// const network = 'wss://xahau.network'; // Mainnet
Enter fullscreen mode Exit fullscreen mode

You can obtain a testnet account at https://xahau-test.net/


The business layer perspective

This project is a very direct example of what Xahau enables: turning an account into an autonomous service. There is no database, no API, no server to maintain. The business logic lives on the blockchain and runs by itself.

This opens the door to scenarios that previously required complex infrastructure:

  • Digital art collection launches where the artist only needs an account and a folder on IPFS.
  • Credential or ticket distribution as on-chain verifiable URITokens.
  • Generative collections where metadata for each number is pre-generated and stored on IPFS.
  • Membership systems where each NFT represents an access level.
  • Game unlockables where each NFT represents parts of a game, characters, or items.

The NFT factory is a building block. From here, combining it with additional Hooks, CronSet, adapting it for marketplaces or any other logic is simply a matter of imagination.


Web Service for Non-Coders

Not everyone has, or wants to have, the technical knowledge required to manage a hook. For this reason, I have created a front-end that allows users to generate collections and have a minting page for anyone who wants to experiment with the hook. The address is: https://nft.xahau.love/

The Xahau NFT Pop-Up Shop allows users, through a simple form, to install, modify, or remove a Hook on a Xahau Mainnet/Testnet account provided through Xaman. This means you don’t have to deal with servers or password management within them.

The website also generates a unique page, based on the Xahau address and the selected network, where others can mint NFTs from the collection through Xaman.

This project is purely educational. I am aware that some members of the Xahau community are working on a marketplace for URITokens on Xahau, and I hope to see and enjoy it soon.


Conclusion

The NFT Factory Hook demonstrates that you do not need a marketplace or a backend to launch an NFT collection on Xahau. With a properly configured Hook, your account becomes an autonomous vending machine: it receives the exact payment, mints the NFT, and delivers it, all within the same transaction and without human intervention. Of course, a marketplace offers additional services beyond minting third-party tokens, such as visibility and marketing. Marketplaces on Xahau can also be managed by Hooks.

The code for this exercise is open and available at
https://github.com/Ekiserrepe/auto_nft_factory_xahau

I invite you to test it on testnet, audit it, and most importantly, build better versions.

As always: we are still in the early days of Xahau. The tools are there. What is missing are the ideas—and those are up to you.


Possible improvements and ideas

Mientras estaba escribiendo este artículo se me han ocurrido los siguientes puntos de mejoras o ideas:

  • Create a front-end to give other people the ability to mint their own collections.
  • Add improvements to the Hook for error handling. For example, stopping the collection emission if an error is detected or resetting the minted NFT counter.
  • Generate a version with time-based bidding. Users send their bids to the minting account, and when the time period ends, the NFT is issued to the highest bidder while the funds are returned to the non-winning bidders.
  • A middleman version. Improve the Hook and add a service fee for minting NFTs on behalf of others.
  • Static or dynamic blacklisting, for example: once an address receives an NFT, it is no longer allowed to purchase another NFT from that collection.
  • Handle PreAuth cases

Acknowledgements

Thanks to Handy_4ndy for his library XahauHooks101, which made this project possible.


Links

Top comments (0)