Skip to content

Instantly share code, notes, and snippets.

@daragao
Created March 3, 2021 17:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save daragao/472fe397ce1290e9daf10d87f84aae85 to your computer and use it in GitHub Desktop.
Save daragao/472fe397ce1290e9daf10d87f84aae85 to your computer and use it in GitHub Desktop.
API3 Airnode contracts make a request and fulfill it
const hre = require("hardhat");
async function main() {
const signers = await hre.ethers.getSigners();
const owner = signers[0];
const Airnode = await hre.ethers.getContractFactory("Airnode", owner);
const Convenience = await hre.ethers.getContractFactory("Convenience", owner);
const airnode = await Airnode.deploy();
await airnode.deployed();
const convenience = await Convenience.deploy(airnode.address);
await convenience.deployed();
console.log("Airnode deployed to:", airnode.address);
console.log("Convenience deployed to:", convenience.address);
// Create client
const client = signers[1];
const MockAirnodeClient = await hre.ethers.getContractFactory("MockAirnodeClient", client);
const mockAirnodeClient = await MockAirnodeClient.deploy(airnode.address);
await mockAirnodeClient.deployed();
console.log("Client deployed to:", mockAirnodeClient.address);
// -------------------------------
// Setup data provider ID
const overrides = { value: 10 };
const xpub = 'what is this?';
const providerSigner = client;
const providerAddress = client.address;
await airnode.connect(providerSigner).createProvider(providerAddress, xpub, overrides);
const encodedAddress = ethers.utils.defaultAbiCoder.encode(['address'], [providerAddress]);
const providerID = ethers.utils.keccak256(encodedAddress);
console.log("Provider ID:", providerID);
// -------------------------------
// Setup endpoint ID
const endpointId = ethers.utils.keccak256(ethers.utils.defaultAbiCoder.encode(['string'], ['callThisEndpoint']));
console.log("Endpoint ID:", endpointId);
// -------------------------------
// Setup requester index
const requesterAdmin = signers[3];
await airnode.connect(requesterAdmin).createRequester(requesterAdmin.address);
const createRequesterEventFilter = airnode.filters.RequesterCreated();
const createRequesterEvents = await airnode.queryFilter(createRequesterEventFilter);
const requesterIndex = createRequesterEvents[0].args.requesterIndex;
console.log("Request ID:", requesterIndex.toString());
// -------------------------------
// Setup wallet (owned by the data provider)
const designatedWalletAddress = client.address;
const fulfillAddress = mockAirnodeClient.address;
const callbackContractFunctionSignature = ethers.utils.keccak256(ethers.utils.toUtf8Bytes('fulfill(bytes32,uint256,bytes32)'));
const fulfillFunctionId = ethers.utils.hexDataSlice(callbackContractFunctionSignature, 0, 4);
const parameters = ethers.utils.randomBytes(8);
// -------------------------------
// Setup a basic template
await airnode.createTemplate(
providerID,
endpointId,
requesterIndex,
designatedWalletAddress,
fulfillAddress,
fulfillFunctionId,
parameters
);
const createTemplateEventFilter = airnode.filters.TemplateCreated();
const createTemplateEvents = await airnode.queryFilter(createTemplateEventFilter);
const templateID = createTemplateEvents[0].args.templateId;
console.log("Template ID:", templateID);
// -------------------------------
// Endorse the requester
await airnode.connect(requesterAdmin)
.updateClientEndorsementStatus(requesterIndex, mockAirnodeClient.address, true); // event ClientEndorsementStatusUpdated
// -------------------------------
// Make a request to be fulfilled
await mockAirnodeClient.connect(client)
.makeRequest(
templateID,
requesterIndex,
designatedWalletAddress,
fulfillAddress,
fulfillFunctionId,
parameters
);
const makeRequestEventFilter = airnode.filters.ClientRequestCreated();
const makeRequestEvents = await airnode.queryFilter(makeRequestEventFilter);
const requestID = makeRequestEvents[0].args.requestId;
console.log("Request ID:", requestID);
// -------------------------------
// Fulfill request
const statusCode = 200;
const data = ethers.utils.formatBytes32String('this is your answer!');
await airnode.connect(providerSigner)
.fulfill(requestID, providerID, statusCode, data, fulfillAddress, fulfillFunctionId);
const requestFulfillEventFilter = airnode.filters.ClientRequestFulfilled();
const requestFulfillEvents = await airnode.queryFilter(requestFulfillEventFilter);
console.log('Airnode fulfilled request emited event:', requestFulfillEvents[0].eventSignature);
const requestFulfillMockEventFilter = mockAirnodeClient.filters.RequestFulfilled();
const requestFulfillMockEvents = await mockAirnodeClient.queryFilter(requestFulfillMockEventFilter);
console.log('Mock Client fulfilled request emited event:', requestFulfillMockEvents[0].eventSignature);
}
// We recommend this pattern to be able to use async/await everywhere
// and properly handle errors.
main()
.then(() => process.exit(0))
.catch(error => {
console.error(error);
process.exit(1);
});
/*
// script run from the protocol package directory root (https://github.com/api3dao/airnode/tree/master/packages/protocol)
$ npx hardhat run singleFileAPI3.js
Airnode deployed to: 0x5FbDB2315678afecb367f032d93F642f64180aa3
Convenience deployed to: 0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512
Client deployed to: 0x8464135c8F25Da09e49BC8782676a84730C318bC
Provider ID: 0x7ceb58780fb137bb02223b79c88bc6404f736f8bb4d1f0895d9884122804fb73
Endpoint ID: 0x2a4620329246f24d4b283ac30ea12994d2d25278774d5d681693c710727e31bc
Request ID: 1
Template ID: 0x924f5be69f737b4017151e7898b61ebce1cdb8e5401702f6b2b37f4e7eeaf794
Request ID: 0x37bcd7510d0c581bf28c65995c29bfeed9119f0eba134db41b64ff449d6aaad3
Airnode fulfilled request emited event: ClientRequestFulfilled(bytes32,bytes32,uint256,bytes32)
Mock Client fulfilled request emited event: RequestFulfilled(bytes32,uint256,bytes32)
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment