Backend Configuration
To get your Storefront Backend working with our Sales Widget, you will need to expose specific APIs and deploy some contracts. This guide will walk you through how to set that all up.
To gain access to the Primary Sales Widget, please complete the following form and our team will be in contact.
1. Set up your project in the Immutable Hub and create API keys
- Follow this guide on how to create a Project in Immutable Hub
- Follow this guide on how to create API Keys on a Project
Copy the environment Id
created since it will be used later on, it appears in the URL near the end (see image below).
![](/img/products/checkout/hub-envid.webp)
2. Create a Signing key (KMS)
A Signing key needs to be created to sign the transactions the Multicaller will execute, a KMS key mimics an HSM and the actual keys cannot be retrieved by Immutable or other parties.
Call the endpoints documented below with a POST method, passing the API key obtained from the step above in an http header with the name x-immutable-api-key
.
- Testnet:
https://api.sandbox.immutable.com/v1/primary-sales/key
- Mainnet:
https://api.immutable.com/v1/primary-sales/key
This is an example call for Testnet.
curl --location --request POST 'https://api.sandbox.immutable.com/v1/primary-sales/key' \
--header 'x-immutable-api-key: <API KEY HERE>'
Wait approximately 1 minute after the previous API call and then make this second call to get the KMS address.
curl --location --request GET 'https://api.sandbox.immutable.com/v1/primary-sales/key' \
--header 'x-immutable-api-key: <API KEY HERE>'
Note down this address, it will be used in a later step.
3. Set up your ERC721 collection
The easiest way to deploy your ERC721 collection is using the Immutable Hub, a guide on how to do it is available here
Once the ERC721 collection is deployed, make sure you copy the collection contract address.
4. The Guarded Multi-Caller
The guarded multicaller is what allows the game studio to perform multiple operations across different smart contracts such as transfer of ERC20 tokens and minting of ERC721/ERC1155 tokens in the same transaction, this needs to be deployed and owned by the game studio, follow these steps to deploy it.
4.1.1 Clone the repo
https://github.com/immutable/multicaller-contracts
and install all the dependencies: Node, npm, yarn.4.1.2 Run command
npx hardhat compile
to create the necessary artifacts.4.1.3 Copy the .env.example file with command
cp .env.example .env
once copied, add the relevant values you need.
Make sure .env contains:
PRIVATE_KEY=<private_key_used_to_deploy_contract>
IMMUTABLE_ZKEVM_TESTNET_URL=https://rpc.testnet.immutable.com
- 4.1.4 Run:
yarn interact deploy --contractName=<contractName> --contractVersion=<contractVersion>
Make sure you remember the values used in contractName , contractVersion and the contract address after deployment, those will be required on a later step.
4.2 Multicaller Permissions to KMS
Permission to allow the address of the KMS key to use and execute in the multicaller contract.
Run: yarn interact grantMulticallSignerRole --contractAddress=<contractAddress> --signerAddress=<signerAddress>
- contractAddress: Pass the contract address where the multicaller was deployed (Step 4.1.3).
- signerAddress: Pass the address of the KMS key created in Step 2.
4.3 Multicaller Permissions to call Mint in the ERC721 collection
Permission to allow the multicaller to mint
yarn interact permitFunction --contractAddress=<contractAddress> --targetAddress=<targetAddress> --functionSignature=<functionSignature> --permitted=true
- contractAddress: Pass the contract address where the multicaller was deployed
- targetAddress: The contract address of the erc721 collection contract.
- functionSignature: The function signature of the mint function selected, these are the function signatures we support:
mint(address,uint256)
-> does NOT offer gas optimisations for multiple NFTs.safeMint(address,uint256)
-> does NOT offer gas optimisations for multiple NFTs.mintBatch((address,uint256[])[])
-> offers gas optimisations for multiple NFTs.safeMintBatch((address,uint256[])[])
-> offers gas optimisations for multiple NFTs.
Note: Methods with safe
prefix perform validations to make sure the recipient address is prepared to receive the NFT.
4.4 Multicaller Permissions to call transfer of ERC20 tokens
yarn interact permitFunction --contractAddress=<contractAddress> --targetAddress=<targetAddress> --functionSignature=<functionSignature> --permitted=true
- contractAddress: Pass the contract address where the multicaller was deployed
- targetAddress: The contract address of the erc20 token.
- functionSignature: The function signature of the transfer function (
transferFrom(address,address,uint256)
)
4.5 ERC721 Permissions to Mint (Minter role)
The multicaller contract needs permissions to mint in the ERC721 collection (Minter role).
Run: yarn interact grantMinterRole --contractAddress=<contractAddress> --collectionAddress=<collectionAddress>
- contractAddress: Pass the contract address where the multicaller was deployed.
- collectionAddress: Pass the address of the ERC721 collection contract.
4.6 Verifying your Multicaller contract (Optional)
Verifying your multicaller contract helps debugging potential errors that may arise, it's not mandatory but it's recommended.
Run: npx hardhat verify --network <network> --contract contracts/GuardedMulticaller.sol:GuardedMulticaller <contractAddress> "<deployerAddress>" "<contractName>" "<contractVersion>"
- network: Either
immutableTestnet
orimmutableMainnet
depending on the chain you want to verify on. - contractAddress: Pass the contract address where the multicaller was deployed.
- deployerAddress: Pass the address of the wallet deploying the contract, it's the wallet for the key used in the PRIVATE_KEY env var.
- contractName: Pass the contract name you defined when the contract was deployed.
- contractVersion: Pass the contract version you defined when the contract was deployed.
Once the contract is verified, a green check mark (✅) appears next to the Contracts
tab when inquiring the contract address on our Immutable explorer.
- Testnet explorer: https://explorer.testnet.immutable.com/
- Mainnet explorer: https://explorer.immutable.com/
5. Setup your Game backend for stock management.
Most games have an inventory system of items available for sale, you can use your existing system with the Primary Sales widget (Bring Your Own) Or we offer an alternative to connect a store in WooCommerce (Wordpress Plugin) with the Primary Sales Widget.
6. Connecting your stock management system with the Primary Sales Widget
Once you have decided and setup your game backend for stock management, you are ready to make all the configurations in order for the Primary Sales Widget to work.
Let's review all configuration fields required to configure the Primary Sales widget:
Property | Description |
---|---|
payouts | The list of wallets that will receive the revenue of the Primary Sale, if you only need one, add one value to the array with a percentage of 100, values needed are: - The wallet address that will receive the payout percentage - The percentage |
expiry | Number of seconds configured for the orders to expire, signed orders need to be executed on-chain before this expiry. This value should encompass the time it takes for a user to review an order until it’s executed in the chain. |
contract_id | The contract ID given by Immutable, this is used by Transak to know which game is using their widget, if you are not using Transak, set value to None . |
currencies | Array of ERC20 currencies supported by the partner game to receive payouts. The information needed to configure a currency is: - The contact address of the ERC20 contract - The number of decimals - The Symbol - Base currency (true/false) - Exchange ID (how the currency appears in coingecko, this is used to fetch conversion rates) |
mint_type | The type of mint method used to deliver the NFTs to the final user, the available methods are: - mint: Standard method used to mint a single NFT, does not offer gas optimisations for multiple items or validation of the recipient wallet. - safeMint: Standard method used to mint a single NFT but incorporates a validation to only allow the minting to happen if the recipient is prepared to receive an NFT. - mintBatch: Gas optimised method to mint multiple NFTs to a recipient, it can consume ~40% less gas than standard mint. - safeMintBatch: Gas optimised method to mint multiple NFTs to a recipient, it also incorporates a validation to only allow the minting to happen if the recipient is prepared to receive an NFT. |
multicall_contract_address multicall_contract_name multicall_contract_version | Multicaller contract address, name and version, used in the task 4. The Guarded Multi-Caller. Name and version are used mostly as part of security checks. |
quote_url quote_api_key | The URL and API key used to get a quote for draft orders. These can be part of your own stock management system or WooCommerce depending on what was configured in the previous step. |
authorization_url authorization_api_key | The URL and API key used to authorize the sales. These can be part of your own stock management system or WooCommerce depending on what was configured in the previous step. |
confirmation_url confirmation_api_key | The URL and API key used to confirm the orders once executed on-chain. These can be part of your own stock management system or WooCommerce depending on what was configured in the previous step. |
expiration_url expiration_api_key | The URL and API key used to inform about expired orders. These can be part of your own stock management system or WooCommerce depending on what was configured in the previous step. |
6.1 Supported Currencies
It is required to set one or more currencies in order to receive payouts.
This is done in the configuration API endpoint by setting currencies
as an array of ERC20 token details:
erc20_address <string>
: The address of the ERC20 contract in zkEVMdecimals <number>
The number of decimals of the ERC20name <string>
: Currency nameexchange_id <string>
: "The ID of the ERC20 token as it appears in the currency conversion service (ie: Coingecko)"base <boolean>
:true
if this is the base currency,false
otherwise.
Wallets with insufficient funds in the base currency will be prompted to swap their tokens.
Setting up a configuration with two currencies in testnet
would look like this:
{
"currencies": [
{
"base": true,
"decimals": 6,
"erc20_address": "0x3b2d8a1931736fc321c24864bceee981b11c3c57",
"exchange_id": "usd-coin",
"name": "USDC"
},
{
"base": true,
"decimals": 18,
"erc20_address": "0xe9e96d1aad82562b7588f03f49ad34186f996478",
"exchange_id": "ethereum",
"name": "ETH"
}
]
}
Wallets with insufficient USDC or ETH, will be prompted to swap their tokens to USDC (if their tokens have liquidity pairs with USDC on QuickSwap).
6.2 Configuration API endpoint
Finally, must call the configuration API endpoint to set up the Primary Sales Widget with the configuration values from the previous steps.
Here is an example of a call to the config endpoint to create and update a the Primary Sales Widget config:
curl --location --request PUT 'https://api.sandbox.immutable.com/v1/primary-sales/config' \
--header 'x-immutable-api-key: <API KEY HERE>' \
--header 'Content-Type: application/json' \
--data-raw '{
"authorization_api_key": "<authorization_api_key>",
"authorization_url": "<authorization_url>",
"confirmation_api_key": "<confirmation_api_key>",
"confirmation_url": "<confirmation_url>",
"currencies": [
{
"erc20_address": "<erc20_address>",
"decimals": <decimals>,
"name": "<name>",
"base": <base>,
"exchange_id": "<exchange_id>"
}
],
"expiration_api_key": "<expiration_api_key>",
"expiration_url": "<expiration_url>",
"quote_api_key": "<quote_api_key>",
"quote_url": "<quote_url>",
"expiry": <expiry>,
"contract_id": "<contract_id>",
"mint_type": "<mint_type>",
"multicall_contract_address": "<multicall_contract_address>",
"multicall_contract_name": "<multicall_contract_name>",
"multicall_contract_version": "<multicall_contract_version>",
"payouts": [
{
"wallet_address": "<payout_address>",
"percentage": <payout_percentage>
}
]
}'