Welcome! This guide helps Node-as-a-Service (NAAS) providers to set up and run their own Orchestrator Node
Download the latest release for your platform from GitHub:
➡️ Orchestrator Node Software v0.0.1
Before deploying the node, ensure your environment meets the minimum specs:
- RAM: 64 MB
- CPU: 1 x86 Core >2.5GHz
- Internet: 10 Mbps stable connection
- OS: Linux recommended
Set the following environment variables before running the binary:
export RPC_URL="https://nodeops-orchestrator-network.calderachain.xyz/http"
export CONTRACT_ADDRESS="0xa234B8924Bb2707195664e4C4Cf17668db9b7286"
export PRIVATE_KEY="<your-operator-wallet-private-key>"
The following are the UNO NFT contract addresses deployed across supported chains. These contracts represent the NFT licenses that grant permission to operate as a node
You can query the NFTs held by a wallet address on any of these networks using the appropriate chain and contract address below. To programmatically check the licenses held by a user, use the checkUserLicenses()
function
Make sure the user wallet owns or is delegated at least one license NFT from any of the above chains. This is required for the node to start participating in epochs and reporting activity
Chain | UNO NFT Contract Address |
---|---|
Arbitrum | 0x2C8515B14Fb9feBCe6d3845d5A0e643D84205Ba1 |
Ethereum | 0x2Eab5E11cfe22Db4dA9F63b0B5d3F620ADa9a4bf |
Base | 0xC0d2aF6d32240494742Ae486B9b73ec6dCC54Aa1 |
You can use our UNO Orchestrator API to retrieve all delegated and free UNO NFTs associated with a wallet
API Endpoint
GET https://uno-orchestrator.nodeops.xyz/api/v1/nodeops/free-sentry-keys
Parameters
Name | Type | Description |
---|---|---|
wallet_id | string | The wallet address you want to query |
Headers
Name | Description |
---|---|
x-api-key | Your assigned API key |
Note: API key will be sent via the appropriate channels
Example Request
curl --location 'https://uno-orchestrator.nodeops.xyz/api/v1/nodeops/free-sentry-keys?wallet_id=<WALLET_ADDR>' \
--header 'x-api-key: <YOUR_API_KEY>'
Response: Returns a list of all UNO NFTs (delegated + free) linked to the given wallet.
You can also use Alchemy’s NFT API
🔗 Example API Call on Arbitrum(Alchemy)
GET https://arb-mainnet.g.alchemy.com/nft/v3/<ALCHEMY_API_KEY>/getNFTsForOwner?owner=<WALLET_ADDRESS>&contractAddresses[]=<UNO_CONTRACT_ADDRESS>&pageSize=100
As we attempt to retrieve the NFTs on the Arbitrum chain, we will use the 0x2C8515B14Fb9feBCe6d3845d5A0e643D84205Ba1
as the parameter for <UNO_CONTRACT_ADDRESS>
Replace placeholders:
<ALCHEMY_API_KEY>
— Your Alchemy API Key<WALLET_ADDRESS>
— The address to check<UNO_CONTRACT_ADDRESS>
— One of the supported license contracts (see table above)
To programmatically interact with the UNO License NFT (e.g. to read ownership, metadata, or validate delegation), use this ABI:
mapping(uint256 => uint256) public canonicalTokenId;
This maps tokenId ➝ canonical ID to support cross-chain license resolution.
You can find the full ABI used by the NFT contract here
The delegation process involves signing license-specific messages and sending them to the orchestrator contract.
The delegateLicense
function is used to bind a UNO license to an operator address.
Note: This function requires a valid signature, which must be generated by the UNO Orchestrator API
delegateLicense(address _operator, uint256 _licenseId, bytes signature)
- The operator signs a message containing license ID and their address.
- This signed message is passed to the orchestrator contract.
- The license becomes bound to the operator address.
You can request a license signature for a specific wallet and license ID using our API
API Endpoint
POST https://uno-orchestrator.nodeops.xyz/api/v1/nodeops/generate-signature
Name | Type | Description |
---|---|---|
wallet_id |
string | The wallet address requesting the signature. |
license |
string | The UNO license ID you want to sign. |
Name | Type | Description |
---|---|---|
x-api-key |
string | Your assigned API key. |
Example Request
curl --location --request POST \
'https://uno-orchestrator.nodeops.xyz/api/v1/nodeops/generate-signature?wallet_id=<WALLET_ADDR>&license=<LICENSE_ID>' \
--header 'x-api-key: <YOUR_API_KEY>'
Example Response
{"data":"6c7e7bc117575339ea62948cba6d841a64c73ec40edc81634502e082da91cd937e4020bbb4f6644634fe538c266c70a5364774139ce187a5a34aee8ef501b"}
Note: The generated signature that must be passed as the third argument (bytes signature) in delegateLicense
undelegateLicense(uint256 _licenseId)
• Call this function to remove the operator’s assignment from a license.
Use the following read-only functions:
// View current epoch
function currentEpoch() public view returns (uint256)
// Check assigned operator of a license
function getOperator(uint256 _licenseId) public view returns (address)
// Fetch operator's full info
function getOperatorInfo(address _operator) public view returns (OperatorInfo)
You can fetch all licenses delegated by an address using:
function getDelegatedLicensesForOwner(address _owner) public view returns (uint256[])
Or fetch multiple operators under the same owner:
function getOperatorsForOwner(address _owner) public view returns (address[])
The Orchestrator contract exposes functions and events to support: • Delegation • Undelegation • Role-based access control • Epoch tracking • Operator activity reporting
You can find the full ABI here