Skip to content

Commit be291e7

Browse files
authored
feat(docs): add guide for modifying hardhat starter (#706)
2 parents 77b1d5f + 9a3fbbe commit be291e7

File tree

1 file changed

+155
-0
lines changed

1 file changed

+155
-0
lines changed
Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
---
2+
title: Web2Json for Custom API
3+
authors: [nikerzetic, filipkoprivec]
4+
description: Retrieve arbitrary Web2 data.
5+
tags: [intermediate, ethereum, fdc, hardhat]
6+
keywords: [ethereum, flare-data-connector, evm, flare-network]
7+
sidebar_position: 12
8+
---
9+
10+
The [Web2Json guide](/fdc/guides/hardhat/web-2-json) demonstrates how the Flare Data Connector can be used to fetch Web2 and store it on the chain.
11+
The code for this and other examples is available within the [Flare Hardhat starter](https://github.com/flare-foundation/flare-hardhat-starter) repository.
12+
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.
13+
That way, the example code can serve as the base building block for a custom project.
14+
15+
## Necessary modifications
16+
17+
In order to run on custom data, the example code needs to be modified in four places only.
18+
Those are:
19+
20+
1. The contract within the `contracts/fdcExample/Web2Json.sol` file.
21+
2. The attestation request parameters at the top of the `scripts/fdcExample/Web2Json.ts`.
22+
In particular the parameters:
23+
24+
- `apiUrl`
25+
- `postProcessJq`
26+
- `abiSignature`
27+
28+
3. The `deployAndVerifyContract` function within the `scripts/fdcExample/Web2Json.ts` file.
29+
4. The `interactWithContract` function within the `scripts/fdcExample/Web2Json.ts` file.
30+
31+
## Contract
32+
33+
The contract within the `contracts/fdcExample/Web2Json.sol` file should be changed to reflect the project goals.
34+
It could be omitted entirely and replaced with multiple files.
35+
The only requirement is that at least one contract - the one interacting with FDC - implements a function that accepts an `IWeb2Json.Proof` struct parameter.
36+
37+
## Attestation request parameters
38+
39+
```typescript title="scripts/fdcExample/Web2Json.ts"
40+
// Request data
41+
const apiUrl = "https://swapi.info/api/people/3";
42+
const postProcessJq = `{name: .name, height: .height, mass: .mass, numberOfFilms: .films | length, uid: (.url | split("/") | .[-1] | tonumber)}`;
43+
const httpMethod = "GET";
44+
const headers = "{}";
45+
const queryParams = "{}";
46+
const body = "{}";
47+
const 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"}`;
48+
```
49+
50+
The attestation request parameters should describe the new Web2 source.
51+
52+
The `apiUrl` is the URL of the API.
53+
It can additionally be configured with the `headers`, `queryParams`, and `body` fields.
54+
A different `httpMethod` can also be selected.
55+
56+
The `postProcessJq` is the jq-filter that will be applied to the JSON data retrieved from the `apiUrl` API.
57+
It rearranges and modifies the input JSON into a new JSON.
58+
The `postProcessJq` filter can be workshopped using an online tool, like [The JQ Playground](https://play.jqlang.org).
59+
60+
The `abiSignature` parameter determines how the modified JSON should be represented in Solidity.
61+
It is the ABI signature of an appropriate struct.
62+
63+
The easiest way to acquire it is to create a `DataTransportObject` struct with the correct fields within some solidity file.
64+
Then, create a public dummy function that accepts a `DataTransportObject` parameter.
65+
After running `yarn hardhat compile` or `npx hardhat compile`, the contract artifact will be created within the `artifacts/contracts` directory.
66+
The dummy function can be searched for within the file of its parent contract, and the `abiSignature` read from its `inputs` field.
67+
68+
## Deploy and verify function
69+
70+
```typescript title="scripts/fdcExample/Web2Json.ts"
71+
async function deployAndVerifyContract() {
72+
const args: any[] = [];
73+
const characterList: MyContractInstance = await MyContract.new(...args);
74+
try {
75+
await run("verify:verify", {
76+
address: characterList.address,
77+
constructorArguments: args,
78+
});
79+
} catch (e: any) {
80+
console.log(e);
81+
}
82+
console.log("MyContract deployed to", characterList.address, "\n");
83+
return characterList;
84+
}
85+
```
86+
87+
The `deployAndVerifyContract` function should be modified to deploy and verify the new contract.
88+
If the contract is deployed and verified by another script, and thus the script will only interact with an existing contract, the function should simply return that contract.
89+
90+
```typescript title="scripts/fdcExample/modifiedWeb2Json.ts"
91+
async function deployAndVerifyContract(address: str) {
92+
return MyContract.at(address);
93+
}
94+
```
95+
96+
## Interact with contract function
97+
98+
```typescript title="scripts/fdcExample/Web2Json.ts"
99+
async function interactWithContract(
100+
characterList: StarWarsCharacterListV2Instance,
101+
proof: any,
102+
) {
103+
console.log("Proof hex:", proof.response_hex, "\n");
104+
105+
// A piece of black magic that allows us to read the response type from an artifact
106+
const IWeb2JsonVerification = await artifacts.require(
107+
"IWeb2JsonVerification",
108+
);
109+
const responseType =
110+
IWeb2JsonVerification._json.abi[0].inputs[0].components[1];
111+
console.log("Response type:", responseType, "\n");
112+
113+
const decodedResponse = web3.eth.abi.decodeParameter(
114+
responseType,
115+
proof.response_hex,
116+
);
117+
console.log("Decoded proof:", decodedResponse, "\n");
118+
const transaction = await characterList.addCharacter({
119+
merkleProof: proof.proof,
120+
data: decodedResponse,
121+
});
122+
console.log("Transaction:", transaction.tx, "\n");
123+
console.log(
124+
"Star Wars Characters:\n",
125+
await characterList.getAllCharacters(),
126+
"\n",
127+
);
128+
}
129+
```
130+
131+
The `interactWithContract` function should be modified to interact with the new contract.
132+
Unless the dApp requires a more intricate interaction with the new contract, only the last few lines should be fundamentally changed.
133+
Likely, only the parameter type and the contract functions called should change.
134+
135+
```typescript title="scripts/fdcExample/modifiedWeb2Json.ts"
136+
async function interactWithContract(myContract: MyContractInstance, proof: any) {
137+
console.log("Proof hex:", proof.response_hex, "\n");
138+
139+
// A piece of black magic that allows us to read the response type from an artifact
140+
const IWeb2JsonVerification = await artifacts.require("IWeb2JsonVerification");
141+
const responseType = IWeb2JsonVerification._json.abi[0].inputs[0].components[1];
142+
console.log("Response type:", responseType, "\n");
143+
144+
const decodedResponse = web3.eth.abi.decodeParameter(responseType, proof.response_hex);
145+
console.log("Decoded proof:", decodedResponse, "\n");
146+
147+
// Only the bellow code fundamentally changed
148+
const transaction = await myContract.customFunction({
149+
merkleProof: proof.proof,
150+
data: decodedResponse,
151+
});
152+
console.log("Transaction:", transaction.tx, "\n");
153+
...
154+
}
155+
```

0 commit comments

Comments
 (0)