Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Guides section update + ABI encoding/decoding clarifications #1813

Merged
merged 5 commits into from
Mar 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 8 additions & 12 deletions src/config/sidebar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -518,10 +518,6 @@ export const SIDEBAR: Partial<Record<Sections, SectionEntry[]>> = {
title: "Call an API",
url: "chainlink-functions/tutorials/api-query-parameters",
},
{
title: "Return Custom Data Types",
url: "chainlink-functions/tutorials/api-custom-response",
},
{
title: "POST Data to an API",
url: "chainlink-functions/tutorials/api-post-data",
Expand All @@ -530,6 +526,14 @@ export const SIDEBAR: Partial<Record<Sections, SectionEntry[]>> = {
title: "Using DON-hosted Secrets in Requests",
url: "chainlink-functions/tutorials/api-use-secrets",
},
{
title: "Using Imports with Functions",
url: "chainlink-functions/tutorials/importing-packages",
},
{
title: "Return multiple responses and decode them in your smart contract",
url: "chainlink-functions/tutorials/abi-decoding",
},
{
title: "Offchain secrets - Using Gists",
url: "chainlink-functions/tutorials/api-use-secrets-gist",
Expand All @@ -554,14 +558,6 @@ export const SIDEBAR: Partial<Record<Sections, SectionEntry[]>> = {
title: "Automate your Functions (Custom Logic Automation)",
url: "chainlink-functions/tutorials/automate-functions-custom-logic",
},
{
title: "Using Imports with Functions",
url: "chainlink-functions/tutorials/importing-packages",
},
{
title: "Return multiple responses and decode them in your smart contract",
url: "chainlink-functions/tutorials/abi-decoding",
},
],
},
{
Expand Down
101 changes: 101 additions & 0 deletions src/content/chainlink-functions/tutorials/abi-decoding.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -224,3 +224,104 @@ The primary function that the script executes is `makeRequestMumbai`. This funct

- Call the `s_answer`, `s_updatedAt`, `s_decimals`, and `s_description` functions of your consumer contract to fetch the decoded values.
- Log the decoded values to the console.

## Handling complex data types with ABI Encoding and Decoding

This section details the process of encoding complex data types into [`Uint8Array` typed arrays](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array) to fulfill the Ethereum Virtual Machine (EVM) data handling requirements for transactions and smart contract interactions. It will then outline the steps for decoding these byte arrays to align with corresponding structures defined in Solidity.

Consider a scenario where a contract needs to interact with a data structure that encapsulates multiple properties, including nested objects:

```json
{
"id": 1,
"metadata": {
"description": "Decentralized Oracle Network",
"awesome": true
}
}
```

Transferring and storing this kind of structured data requires encoding it into a format (array of 8-bit unsigned integers) that smart contracts can accept and process.

### Encoding in JavaScript

Because Chainlink Functions supports important external modules, you can import a web3 library such as `ethers.js` and perform encoding.
To encode complex data structures, you can use the [`defaultAbiCoder.encode`](https://docs.ethers.org/v6/api/abi/abi-coder/#AbiCoder-encode) function from the `ethers.js` library. The function takes two arguments:

- An array of Solidity data types.
- The corresponding data in JavaScript format.

and returns the encoded data as a hexadecimal string.

Here's how you can encode the aforementioned complex data:

```javascript
const { ethers } = await import("npm:ethers@6.10.0") // Import ethers.js v6.10.0

const abiCoder = ethers.AbiCoder.defaultAbiCoder()

// Define the data structure
const complexData = {
id: 1,
metadata: {
description: "Decentralized Oracle Network",
awesome: true,
},
}

// Define the Solidity types for encoding
const types = ["tuple(uint256 id, tuple(string description, bool awesome) metadata)"]

// Data to encode
const data = [
[
complexData.id,
{
description: complexData.metadata.description,
awesome: complexData.metadata.awesome,
},
],
]

// Encoding the data
const encodedData = abiCoder.encode(types, data)
```

After encoding the data, it's necessary to format it as a `Uint8Array` array for smart contract interactions and blockchain transactions. In Solidity, the data type for byte arrays data is `bytes`. However, when working in a JavaScript environment, such as when using the `ethers.js` library, the equivalent data structure is a `Uint8Array`.

The `ethers.js` library provides the [`getBytes`](https://docs.ethers.org/v6/api/utils/#getBytes) function to convert encoded hexadecimal strings into a `Uint8Array`:

```javascript
return ethers.getBytes(encodedData) // Return the encoded data converted into a Uint8Array
```

### Decoding in Solidity

The encoded data can be decoded using the `abi.decode` function. To decode the data, you'll need to handle the decoding in your `fulfillRequest` function:

```solidity
// SPDX-License-Identifier: MIT
pragma solidity 0.8.19;

contract DataDecoder {
// Example of a structure to hold the complex data
struct Metadata {
string description;
bool awesome;
}

struct ComplexData {
uint256 id;
Metadata metadata;
}

// ... other contract functions (including the send request function)

// Fulfill function (callback function)
function fulfillRequest(bytes32 requestId, bytes memory response, bytes memory err) internal override {
// Decode the response
ComplexData memory metadata = abi.decode(response, (ComplexData));
// ... rest of the function
}
}
```
231 changes: 0 additions & 231 deletions src/content/chainlink-functions/tutorials/api-custom-response.mdx

This file was deleted.

Loading
Loading