Create and use a custom API to Chainlink with an example from Sedo.network module.

Jeevanjot Singh
5 min readNov 28, 2020

Sedo network was my hackathon project which creates a domain offering marketplace on Ethereum blockchain [Work in progress].

It is based on the idea to register a top-level domain anywhere with any registrar and later verify and park that domain on the Ethereum blockchain where you can choose to sell it or buy already on sale domains.

To work on the example for this tutorial, I would like to choose one of the modules from its verification process. Which is easy to implement in the range of this tutorial.

Prerequisite:

If you wondering then the TXT record is a domain name record that returns a string and can be set manually and most of the time it is used to verify domains and we are using that too.

Setup Backend

Create a new node project with npm init -y then create a new file for your js like index.js or anything after that put the below code into it.

const dns = require(‘dns’)
const express = require(‘express’)
const app = express()
const port = 8080
app.get(‘/’, (req, res) => {
res.send(“hello”)
})
app.get(‘/auth’, (req, res) => {
dns.resolveTxt(req.query.domain, (err, records) => {
if (records && records[0] && records[0][0]) {
res.send(records[0][0])
}
});
})
app.listen(port, () => {
console.log(`Example app listening at http://localhost:${port}`)
})

no need to install any npm packages right now.

This endpoint function is to read the first returned txt record and send it back to the smart contract that requests it.

Setup Smart Contract

Go to https://remix.ethereum.org/ create a new .sol file and write the below code in it.

pragma solidity ^0.6.0;import "https://raw.githubusercontent.com/smartcontractkit/chainlink/develop/evm-contracts/src/v0.6/ChainlinkClient.sol";contract GetTXTRecord is ChainlinkClient {

uint256 public txt;

address private oracle;
bytes32 private jobId;
uint256 private fee;
constructor() public {
setPublicChainlinkToken();
oracle = 0xA1eaDB935335a9d7a48d8160b4Dc372ff16b39Ac;
jobId = "a4013f7ddbd849cd9b90445da212b107";
fee = 0.1 * 10 ** 18; // 0.1 LINK
}

function requestTxt(string memory domain) public returns (bytes32 requestId)
{
Chainlink.Request memory request = buildChainlinkRequest(jobId, address(this), this.fulfill.selector);
request.add("get", "<Your Url Endpoint to handle request>");
request.add("queryParams", domain);
return sendChainlinkRequestTo(oracle, request, fee);
}

function fulfill(bytes32 _requestId, uint256 _txt) public recordChainlinkFulfillment(_requestId)
{
txt = _txt;
}
}

Notice the line

request.add("get", "<Your Url Endpoint to handle request>");

Here you have to put your backend serving url, Which might not be running yet and you can’t put localhost:8080 there.

Quickly serve your API to the internet

Create a new file in the same directory okteto.yml and add the below code to it.

name: your-projectimage: okteto/node:12command:  - bashremote: 22000sync:  - .:/usr/src/appforward:  - 8080:8080persistentVolume:  enabled: true

Add another file .stignore and add node_modules inside it. It will stop syncing cloud node modules to the localhost(saves bandwidth and sync time).

After that, open a new terminal in that directory, and with okteto up start your dev server.

This will start a new nodejs environment which is synced with your current directory and your localhost port 8080 is forwarding to the port provided by okteto cloud service.

Now install DNS & express node packages using npm install before moving forward.

Start API Script

I use nodemon to start because it picks the changes (But this cannot be applied everywhere)

nodemon index.js

Goto Okteto cloud and get your public endpoint (Which automatically configured to serve by default at port 8080 as default)

As long as you run above script the API will serve the request. To run it in production mode you need to make a Dockerfile that start this script then build and push the image to okteto cloud explained here

Get API Endpoint

Goto okteto cloud dashboard and you can find your API endpoint there

and this is what it returns as the default route

But when you point your route to the right direction (Where we are receiving and sending TXT back in the script)

we are passing a route /auth and a query parameter ?domain=blockin.network which is my domain and I have set its TXT record to return the above string.

which is handled here in the code…

Setup our contract

Now add the endpoint to the internal adapter include /auth route.

request.add("get", "https://chainlink-genievot.cloud.okteto.net/auth");

Change the above endpoint with yours.

Test

Deploy smart contracts and send some test LINK tokens (≥ the fee which is 0.1 Link tokens) to it for testing.

Call requestTxt with query parameter value like domain=<your_tld>

After the call wait for it to get published on-chain and call it back the fulfillment function.

After that, I have the same TXT record on the chain I was having on my domain name.

The oracle and jobid in this contract is used by the node I am hosting right now on kovan network for development purposes. In future the node might go down so it is recommended that you change job id and oracle id provided in this contract to something you know can process if do custom then you can do with the jobs specs like this.

In Json…

{
"initiators": [
{
"type": "runlog",
"params": {
"address": "0xa1eadb935335a9d7a48d8160b4dc372ff16b39ac"
}
}
],
"tasks": [
{
"type": "httpget",
"confirmations": null,
"params": {
}
},
{
"type": "ethuint256",
"confirmations": null,
"params": {
}
},
{
"type": "ethtx",
"confirmations": null,
"params": {
}
}
],
"startAt": null,
"endAt": null
}

Where to go from here

--

--