Identify a (X-)Node
Nodes, especially X-Nodes are lovingly supported by the community thru benefits sometimes. VeChain-Nodes are NFTs with all code-relevant information on their contracts and their interfaces located on GitHub: https://github.com/vechain/ThorNode-contracts (opens in a new tab)
The contract on the MainNet is found at:
0xb81E9C5f9644Dec9e5e3Cac86b4461A222072302
An interface for Solidity can be generated using abi-to-sol
(opens in a new tab) and the public b32 (opens in a new tab) archive:
curl -s https://raw.githubusercontent.com/vechain/b32/master/ABIs/thornode-tokenauction.json | npx abi-to-sol IThorNode > src/IThorNode.sol
Just a simple Yes and No
isX(address)
returns a boolean about the XNode status. The function is defined here:
https://github.com/vechain/ThorNode-contracts/blob/b3e1765ed7b1599b301602a0e0f72587cf24be1b/contracts/ThunderFactory.sol#L101-L109 (opens in a new tab)
function isX(address _target)
public
view
returns(bool)
{
// return false if given address doesn't hold a token
return tokens[ownerToId[_target]].level >= strengthLevel.VeThorX;
}
Solidity
Calling this in solidity using the previously generated Interface:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
import "./IThorNode.sol";
contract XNode {
address ThorAuction = 0xb81E9C5f9644Dec9e5e3Cac86b4461A222072302;
function isXNode(address _owner) external view returns (bool isX) {
return IThorNode(ThorAuction).isX(_owner);
}
}
Connex
const abiIsX = {
"constant": true,
"inputs": [
{
"name": "_target",
"type": "address"
}
],
"name": "isX",
"outputs": [
{
"name": "isX",
"type": "bool"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
}
const {
decoded: { 0: isX }
} = await connex.thor
.account(CONTRACT_ADDRESS)
.method(abiIsX)
.call(address);
Call-API
On the Call-API (opens in a new tab):
https://call.api.vechain.energy/main/0xb81e9c5f9644dec9e5e3cac86b4461a222072302/isX(address <ADDRESS>) returns (bool)
For example address 0xf84090b27109454feE78987ae123EC7AEe4c27aE
it returns true
:
Identify Token ID by address
The Token ID of each Node-NFT is available with ownerToId
explained here:
https://github.com/vechain/ThorNode-contracts#ownertoid (opens in a new tab)
function ownerToId(address _owner) public view
returns (uint256)
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
import "./IThorNode.sol";
contract XNode {
address ThorAuction = 0xb81E9C5f9644Dec9e5e3Cac86b4461A222072302;
function getMetadataForOwner(address _owner)
external
view
{
uint256 tokenId = IThorNode(ThorAuction).ownerToId(_owner);
}
}
Connex
const abiOwnerToId = {
"constant": true,
"inputs": [
{ "name": "", "type": "address" }
],
"name": "ownerToId",
"outputs": [
{ "name": "tokenId", "type": "uint256" }
],
"payable": false,
"stateMutability": "view",
"type": "function"
}
const {
decoded: { 0: tokenId }
} = await connex.thor
.account(CONTRACT_ADDRESS)
.method(abiOwnerToId)
.call(address);
Call-API
On the Call-API (opens in a new tab): https://call.api.vechain.energy/main/0xb81e9c5f9644dec9e5e3cac86b4461a222072302/ownerToId(address <ADDRESS>) returns (uint256)
For example address 0xf84090b27109454feE78987ae123EC7AEe4c27aE
gives tokenId #1:
Identify Token-Status using Token ID
The (X-Node-)Status and more is available with getMetadata
explained here:
https://github.com/vechain/ThorNode-contracts#getmetadata (opens in a new tab)
function getMetadata(uint256 _tokenId) public view
returns(
address owner,
uint8 level,
bool isOnUpgrade,
bool isOnAuction,
uint64 lastTransferTime,
uint64 createdAt,
uint64 updatedAt
)
Solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
import "./IThorNode.sol";
contract XNode {
address ThorAuction = 0xb81E9C5f9644Dec9e5e3Cac86b4461A222072302;
function getMetadataForOwner(address _owner)
external
view
returns (
address owner,
uint8 level,
bool isOnUpgrade,
bool isOnAuction,
uint64 lastTransferTime,
uint64 createdAt,
uint64 updatedAt
)
{
uint256 tokenId = IThorNode(ThorAuction).ownerToId(_owner);
return IThorNode(ThorAuction).getMetadata(tokenId);
}
}
Connex
const abiGetMetadata = {
"constant": true,
"inputs": [
{ "name": "_tokenId", "type": "uint256" }
],
"name": "getMetadata",
"outputs": [
{ "name": "owner", "type": "address" },
{ "name": "level", "type": "uint8" },
{ "name": "isOnUpgrade", "type": "bool" },
{ "name": "isOnAuction", "type": "bool" },
{ "name": "lastTransferTime", "type": "uint64" },
{ "name": "createdAt", "type": "uint64" },
{ "name": "updatedAt", "type": "uint64" }
],
"payable": false,
"stateMutability": "view",
"type": "function"
}
const {
decoded: metadata
} = await connex.thor
.account(CONTRACT_ADDRESS)
.method(abiGetMetadata)
.call(tokenId);
Call-API
On the Call-API (opens in a new tab):
ttps://call.api.vechain.energy/main/0xb81e9c5f9644dec9e5e3cac86b4461a222072302/getMetadata(uint256 <TOKEN_ID>) returns (address owner, uint8 level, bool isOnUpgrade, bool isOnAuction, uint256 lastTransferTime, uint64 createdAt, uint64 updatedAt)
For example Token Id 1
results are:
{
"owner": "0xf84090b27109454feE78987ae123EC7AEe4c27aE",
"level": "4",
"isOnUpgrade": false,
"isOnAuction": false,
"lastTransferTime": "1543977040",
"createdAt": "1543977040",
"updatedAt": "1543977040"
}
Token-Level as readable name
The level can be translated into a readable name to with the following table:
Level | Name |
---|---|
1 | VeChainThor Strength Node |
2 | VeChainThor Thunder Node |
3 | VeChainThor Mjolnir Node |
4 | VeChainThor X Node |
5 | VeChainThor Strength X Node |
6 | VeChainThor Thunder X Node |
7 | VeChainThor Mjolnir X Node |
Links
The sample contract is available on GitLab here: https://gitlab.com/vechain.energy/examples/contract-xnode (opens in a new tab)
The connex example is available as Sandbox here:
https://codesandbox.io/s/read-node-status-of-an-address-3u1vli (opens in a new tab)
Details about the Call-API can be found here:
https://vechain.energy/docs/api/call (opens in a new tab)