Web2Json for Custom API
The Web2Json guide demonstrates how the Flare Data Connector can be used to fetch Web2 and store it on the chain.
The code for this and other examples is available within the Flare Hardhat starter repository.
In this guide, we will see how the Web2Json
example script within the Flare Hardhat starter can be modified to work with custom data and custom contracts.
That way, the example code can serve as the base building block for a custom project.
Necessary modifications
In order to run on custom data, the example code needs to be modified in four places only. Those are:
- The contract within the
src/fdcExample/Web2Json.sol
file. - The attestation request parameters at the top of the
script/fdcExample/Web2Json.s.sol
. In particular the parameters:
apiUrl
postProcessJq
abiSignature
- The
DeployContract
script within thescript/fdcExample/Web2Json.s.sol
file. - The
InteractWithContract
function within thescript/fdcExample/Web2Json.s.sol
file.
Contract
The contract within the src/fdcExample/Web2Json.sol
file should be changed to reflect the project goals.
It could be omitted entirely and replaced with multiple files.
The only requirement is that at least one contract - the one interacting with FDC - implements a function that accepts an IWeb2Json.Proof
struct parameter.
Attestation request parameters
// Setting request data
string public apiUrl = "https://swapi.info/api/people/3";
string public httpMethod = "GET";
string public headers = '{\\"Content-Type\\":\\"text/plain\\"}';
string public queryParams = "{}";
string public body = "{}";
string public postProcessJq =
'{name: .name, height: .height, mass: .mass, numberOfFilms: .films | length, uid: (.url | split(\\"/\\") | .[-1] | tonumber)}';
string public abiSignature =
'{\\"components\\": [{\\"internalType\\": \\"string\\", \\"name\\": \\"name\\", \\"type\\": \\"string\\"},{\\"internalType\\": \\"uint256\\", \\"name\\": \\"height\\", \\"type\\": \\"uint256\\"},{\\"internalType\\": \\"uint256\\", \\"name\\": \\"mass\\", \\"type\\": \\"uint256\\"},{\\"internalType\\": \\"uint256\\", \\"name\\": \\"numberOfFilms\\", \\"type\\": \\"uint256\\"},{\\"internalType\\": \\"uint256\\", \\"name\\": \\"uid\\", \\"type\\": \\"uint256\\"}],\\"name\\": \\"task\\",\\"type\\": \\"tuple\\"}';
The attestation request parameters should describe the new Web2 source.
The apiUrl
is the URL of the API.
It can additionally be configured with the headers
, queryParams
, and body
fields.
A different httpMethod
can also be selected.
The postProcessJq
is the jq-filter that will be applied to the JSON data retrieved from the apiUrl
API.
It rearranges and modifies the input JSON into a new JSON.
The postProcessJq
filter can be workshopped using an online tool, like The JQ Playground.
The abiSignature
parameter determines how the modified JSON should be represented in Solidity.
It is the ABI signature of an appropriate struct.
The easiest way to acquire it is to create a DataTransportObject
struct with the correct fields within some solidity file.
Then, create a public dummy function that accepts a DataTransportObject
parameter.
After running yarn hardhat compile
or npx hardhat compile
, the contract artifact will be created within the artifacts/contracts
directory.
The dummy function can be searched for within the file of its parent contract, and the abiSignature
read from its inputs
field.
Deploy script
contract DeployContract is Script {
function run() external {
uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY");
vm.startBroadcast(deployerPrivateKey);
StarWarsCharacterList characterList = new StarWarsCharacterList();
address _address = address(characterList);
vm.stopBroadcast();
Base.writeToFile(
dirPath,
string.concat(attestationTypeName, "_address"),
StringsBase.toHexString(abi.encodePacked(_address)),
true
);
}
}
The DeployContract
script should be modified to deploy and verify the new contract.
If the contract is deployed and verified by another script, and thus the script will only interact with an existing contract, the script can be omitted.
Interact with contract script
contract InteractWithContract is Script {
function run() external {
string memory addressString = vm.readLine(
string.concat(dirPath, attestationTypeName, "_address", ".txt")
);
address _address = vm.parseAddress(addressString);
string memory proofString = vm.readLine(
string.concat(dirPath, attestationTypeName, "_proof", ".txt")
);
bytes memory proofBytes = vm.parseBytes(proofString);
IWeb2Json.Proof memory proof = abi.decode(
proofBytes,
(IWeb2Json.Proof)
);
uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY");
vm.startBroadcast(deployerPrivateKey);
IStarWarsCharacterList characterList = IStarWarsCharacterList(_address);
characterList.addCharacter(proof);
vm.stopBroadcast();
}
}
The InteractWithContract
script should be modified to interact with the new contract.
Unless the dApp requires a more intricate interaction with the new contract, only the last few lines should be fundamentally changed.
Likely, only the parameter type and the contract functions called should change.