Node.js
The simplest interaction with the registry is with ethers (opens in a new tab) and using fetch directly on a vechain node.
Resolve Utility Contract
const { Interface, isAddress } = require('ethers')
const VET_UTILITY_ADDRESS = "0xA11413086e163e41901bb81fdc5617c975Fa5a1A";
const NODE_URL = "https://node-mainnet.vechain.energy"
const utilityInterface = new Interface([
'function getAddresses(string[] memory names) external view returns (address[] memory addresses)',
'function getNamehashes(string[] memory names) external pure returns (bytes32[] memory nodes)',
'function getNames(address[] memory addresses) external view returns (string[] memory names)'
])
async function getRecord(name) {
const [{ data: addressData }] = await fetch(`${NODE_URL}/accounts/*`, {
method: 'POST',
headers: {
'content-type': 'application/json'
},
body: JSON.stringify({
clauses: [
{
to: VET_UTILITY_ADDRESS,
data: utilityInterface.encodeFunctionData('getAddresses', [[name]])
}
]
})
}).then(res => res.json());
const { addresses } = utilityInterface.decodeFunctionResult('getAddresses', addressData);
return addresses[0];
}
async function getName(address) {
const [{ data: nameData }] = await fetch(`${NODE_URL}/accounts/*`, {
method: 'POST',
headers: {
'content-type': 'application/json'
},
body: JSON.stringify({
clauses: [
{
to: VET_UTILITY_ADDRESS,
data: utilityInterface.encodeFunctionData('getNames', [[address]])
}
]
})
}).then(res => res.json());
const { names } = utilityInterface.decodeFunctionResult('getNames', nameData);
return names[0];
}
async function getAddress(addressOrName) {
return isAddress(addressOrName) ? addressOrName : getRecord(addressOrName)
}
async function main() {
const testName = 'hello.vet'
const address = await getRecord(testName)
console.log(testName, 'resolves to', address)
const name = await getName(address)
console.log('primary name of', address, 'is', name)
const addressTest1 = await getAddress(address)
const addressTest2 = await getAddress(name)
console.log('getAddress(address) replies with', addressTest1)
console.log('getAddress(name) replies with', addressTest2)
}
main()
.then(() => process.exit(0))
.catch(error => {
console.error(error);
process.exit(1);
});
Pure Registry
const { namehash, Interface, ZeroAddress, isAddress } = require('ethers')
const VET_REGISTRY_ADDRESS = "0xa9231da8BF8D10e2df3f6E03Dd5449caD600129b";
const NODE_URL = "https://node-mainnet.vechain.energy"
const nameInterface = new Interface([
'function resolver(bytes32 node) returns (address resolverAddress)',
'function addr(bytes32 node) returns (address resolvedAddress)',
'function name(bytes32 node) returns (string memory name)'
])
async function getRecord(name) {
const node = namehash(name);
const [{ data: resolverData, reverted: noResolver }] = await fetch(`${NODE_URL}/accounts/*`, {
method: 'POST',
headers: {
'content-type': 'application/json'
},
body: JSON.stringify({
clauses: [
{
to: VET_REGISTRY_ADDRESS,
data: nameInterface.encodeFunctionData('resolver', [node])
}
]
})
}).then(res => res.json());
// return zero address if no resolver has been set
if (noResolver) { return ZeroAddress; }
const { resolverAddress } = nameInterface.decodeFunctionResult('resolver', resolverData);
const [{ data: lookupData, reverted: noLookup }] = await fetch(`${NODE_URL}/accounts/*`, {
method: 'POST',
headers: {
'content-type': 'application/json'
},
body: JSON.stringify({
clauses: [
{
to: resolverAddress,
data: nameInterface.encodeFunctionData('addr', [node])
}
]
})
}).then(res => res.json());
// return zero address if resolver does respond with error
if (noLookup) { return ZeroAddress; }
const { resolvedAddress } = nameInterface.decodeFunctionResult('addr', lookupData);
return resolvedAddress;
}
async function getName(address) {
const reverseLookup = `${address.slice(2).toLowerCase()}.addr.reverse`;
const node = namehash(reverseLookup);
const [{ data: resolverData, reverted: noResolver }] = await fetch(`${NODE_URL}/accounts/*`, {
method: 'POST',
headers: {
'content-type': 'application/json'
},
body: JSON.stringify({
clauses: [
{
to: VET_REGISTRY_ADDRESS,
data: nameInterface.encodeFunctionData('resolver', [node])
}
]
})
}).then(res => res.json());
// return empty string if no resolver has been set
if (noResolver) { return ''; }
const { resolverAddress } = nameInterface.decodeFunctionResult('resolver', resolverData);
const [{ data: lookupData, reverted: noLookup }] = await fetch(`${NODE_URL}/accounts/*`, {
method: 'POST',
headers: {
'content-type': 'application/json'
},
body: JSON.stringify({
clauses: [
{
to: resolverAddress,
data: nameInterface.encodeFunctionData('name', [node])
}
]
})
}).then(res => res.json());
// return empty string if resolver does respond with error
if (noLookup) { return ''; }
const { name } = nameInterface.decodeFunctionResult('name', lookupData);
return name;
}
async function getAddress(addressOrName) {
return isAddress(addressOrName) ? addressOrName : getRecord(addressOrName)
}
async function main() {
const testName = 'hello.vet'
const address = await getRecord(testName)
console.log(testName, 'resolves to', address)
const name = await getName(address)
console.log('primary name of', address, 'is', name)
const addressTest1 = await getAddress(address)
const addressTest2 = await getAddress(name)
console.log('getAddress(address) replies with', addressTest1)
console.log('getAddress(name) replies with', addressTest2)
}
main()
.then(() => process.exit(0))
.catch(error => {
console.error(error);
process.exit(1);
});