# FunctionsClient API Reference
Source: https://docs.chain.link/chainlink-functions/api-reference/functions-client
Consumer contract developers inherit [FunctionsClient](https://github.com/smartcontractkit/chainlink/blob/contracts-v1.3.0/contracts/src/v0.8/functions/v1_0_0/FunctionsClient.sol) to create Chainlink Functions requests.
## Events
### RequestSent
```solidity
event RequestSent(bytes32 id)
```
### RequestFulfilled
```solidity
event RequestFulfilled(bytes32 id)
```
## Errors
### OnlyRouterCanFulfill
```solidity
error OnlyRouterCanFulfill()
```
## Methods
### constructor
```solidity
constructor(address router)
```
### _sendRequest
```solidity
function _sendRequest(bytes data, uint64 subscriptionId, uint32 callbackGasLimit, bytes32 donId) internal returns (bytes32)
```
Sends a Chainlink Functions request to the stored router address
#### Parameters
| Name | Type | Description |
| ---------------- | ------- | --------------------------------------------------------------------- |
| data | bytes | The CBOR encoded bytes data for a Functions request |
| subscriptionId | uint64 | The subscription ID that will be charged to service the request |
| callbackGasLimit | uint32 | the amount of gas that will be available for the fulfillment callback |
| donId | bytes32 | |
#### Return Values
| Name | Type | Description |
| ---- | ------- | --------------------------------------------------- |
| [0] | bytes32 | requestId The generated request ID for this request |
### fulfillRequest
```solidity
function fulfillRequest(bytes32 requestId, bytes response, bytes err) internal virtual
```
User defined function to handle a response from the DON
*Either response or error parameter will be set, but never both*
#### Parameters
| Name | Type | Description |
| --------- | ------- | ----------------------------------------------------------------------------------- |
| requestId | bytes32 | The request ID, returned by sendRequest() |
| response | bytes | Aggregated response from the execution of the user's source code |
| err | bytes | Aggregated error from the execution of the user code or from the execution pipeline |
### handleOracleFulfillment
```solidity
function handleOracleFulfillment(bytes32 requestId, bytes response, bytes err) external
```
Chainlink Functions response handler called by the Functions Router during fulfillment from the designated transmitter node in an OCR round
*Either response or error parameter will be set, but never both*
#### Parameters
| Name | Type | Description |
| --------- | ------- | -------------------------------------------------------------------------------------- |
| requestId | bytes32 | The requestId returned by FunctionsClient.sendRequest(). |
| response | bytes | Aggregated response from the request's source code. |
| err | bytes | Aggregated error either from the request's source code or from the execution pipeline. |
---
# FunctionsRequest library API Reference
Source: https://docs.chain.link/chainlink-functions/api-reference/functions-request
Consumer contract developers use the [FunctionsRequest library](https://github.com/smartcontractkit/chainlink/blob/contracts-v1.3.0/contracts/src/v0.8/functions/v1_0_0/libraries/FunctionsRequest.sol) to build their [requests](#request).
## Types and Constants
### REQUEST_DATA_VERSION
```solidity
uint16 REQUEST_DATA_VERSION
```
### DEFAULT_BUFFER_SIZE
```solidity
uint256 DEFAULT_BUFFER_SIZE
```
### Location
```solidity
enum Location {
Inline,
Remote,
DONHosted
}
```
| Value | Description |
| ----------- | ----------------------------------------------------------------------------- |
| `Inline` | Provided within the Request. |
| `Remote` | Hosted through a remote location that can be accessed through a provided URL. |
| `DONHosted` | Hosted on the DON's storage. |
### CodeLanguage
```solidity
enum CodeLanguage {
JavaScript
}
```
### Request
```solidity
struct Request {
enum FunctionsRequest.Location codeLocation;
enum FunctionsRequest.Location secretsLocation;
enum FunctionsRequest.CodeLanguage language;
string source;
bytes encryptedSecretsReference;
string[] args;
bytes[] bytesArgs;
}
```
| Field | Type | Description |
| --------------------------- | -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `codeLocation` | `Location` | The location of the source code that will be executed on each node in the DON. |
| `secretsLocation` | `Location` | The location of secrets that will be passed into the source code. \*Only Remote secrets are supported. |
| `language` | `CodeLanguage` | The coding language that the source code is written in. |
| `source` | `string` | Raw source code for `Request.codeLocation` of `Location.Inline`, URL for `Request.codeLocation` of `Location.Remote`, or slot decimal number for `Request.codeLocation` of `Location.DONHosted`. |
| `encryptedSecretsReference` | `bytes` | Encrypted URLs for `Request.secretsLocation` of `Location.Remote`, or CBOR encoded `slotid+version` for `Request.secretsLocation` of `Location.DONHosted`. |
| `args` | `string[]` | String arguments that will be passed into the source code. |
| `bytesArgs` | `bytes[]` | Bytes arguments that will be passed into the source code. |
## Errors
### EmptySource
```solidity
error EmptySource()
```
### EmptySecrets
```solidity
error EmptySecrets()
```
### EmptyArgs
```solidity
error EmptyArgs()
```
### NoInlineSecrets
```solidity
error NoInlineSecrets()
```
## Functions
### encodeCBOR
```solidity
function encodeCBOR(struct FunctionsRequest.Request self) internal pure returns (bytes)
```
Encodes a Request to CBOR encoded bytes
#### Parameters
| Name | Type | Description |
| ---- | ------------------------------- | --------------------- |
| self | struct FunctionsRequest.Request | The request to encode |
#### Return values
| Name | Type | Description |
| ---- | ----- | ------------------ |
| [0] | bytes | CBOR encoded bytes |
### initializeRequest
```solidity
function initializeRequest(struct FunctionsRequest.Request self, enum FunctionsRequest.Location codeLocation, enum FunctionsRequest.CodeLanguage language, string source) internal pure
```
Initializes a Chainlink Functions Request
*Sets the codeLocation and code on the request*
#### Parameters
| Name | Type | Description |
| ------------ | ---------------------------------- | ----------------------------------------- |
| self | struct FunctionsRequest.Request | The uninitialized request |
| codeLocation | enum FunctionsRequest.Location | The user provided source code location |
| language | enum FunctionsRequest.CodeLanguage | The programming language of the user code |
| source | string | The user provided source code or a url |
### initializeRequestForInlineJavaScript
```solidity
function initializeRequestForInlineJavaScript(struct FunctionsRequest.Request self, string javaScriptSource) internal pure
```
Initializes a Chainlink Functions Request
*Simplified version of initializeRequest for PoC*
#### Parameters
| Name | Type | Description |
| ---------------- | ------------------------------- | --------------------------------------------- |
| self | struct FunctionsRequest.Request | The uninitialized request |
| javaScriptSource | string | The user provided JS code (must not be empty) |
### addSecretsReference
```solidity
function addSecretsReference(struct FunctionsRequest.Request self, bytes encryptedSecretsReference) internal pure
```
Adds Remote user encrypted secrets to a Request
#### Parameters
| Name | Type | Description |
| ------------------------- | ------------------------------- | --------------------------------------------------------------------- |
| self | struct FunctionsRequest.Request | The initialized request |
| encryptedSecretsReference | bytes | Encrypted comma-separated string of URLs pointing to offchain secrets |
### addDONHostedSecrets
```solidity
function addDONHostedSecrets(struct FunctionsRequest.Request self, uint8 slotID, uint64 version) internal pure
```
Adds DON-hosted secrets reference to a Request
#### Parameters
| Name | Type | Description |
| ------- | ------------------------------- | ------------------------------------------- |
| self | struct FunctionsRequest.Request | The initialized request |
| slotID | uint8 | Slot ID of the user's secrets hosted on DON |
| version | uint64 | User data version (for the slotID) |
### setArgs
```solidity
function setArgs(struct FunctionsRequest.Request self, string[] args) internal pure
```
Sets args for the user run function
#### Parameters
| Name | Type | Description |
| ---- | ------------------------------- | -------------------------------------------- |
| self | struct FunctionsRequest.Request | The initialized request |
| args | string[] | The array of string args (must not be empty) |
### setBytesArgs
```solidity
function setBytesArgs(struct FunctionsRequest.Request self, bytes[] args) internal pure
```
Sets bytes args for the user run function
#### Parameters
| Name | Type | Description |
| ---- | ------------------------------- | ------------------------------------------- |
| self | struct FunctionsRequest.Request | The initialized request |
| args | bytes[] | The array of bytes args (must not be empty) |
---
# JavaScript code API Reference
Source: https://docs.chain.link/chainlink-functions/api-reference/javascript-source
JavaScript source code for a Functions request should comply with certain restrictions:
- **Allowed Modules**: Vanilla [Deno](https://deno.land/) and module [imports](/chainlink-functions/tutorials/importing-packages).
- **Return Type**: Must return a JavaScript `Buffer` object representing the response bytes sent back to the invoking contract.
- **Time Limit**: Scripts must execute within a 10-second timeframe; otherwise, they will be terminated, and an error will be returned to the requesting contract.
## HTTP requests
For making HTTP requests, use the `Functions.makeHttpRequest` function.
### Syntax
```javascript
const response = await Functions.makeHttpRequest({
url: "http://example.com",
method: "GET", // Optional
// Other optional parameters
})
```
### Parameters
| Parameter | Optionality | Description | Default Value |
| -------------- | ----------- | ----------------------------------------- | ------------- |
| `url` | Required | The target URL. | N/A |
| `method` | Optional | HTTP method to be used. | `'GET'` |
| `headers` | Optional | HTTP headers for the request. | N/A |
| `params` | Optional | URL query parameters. | N/A |
| `data` | Optional | Body content for the request. | N/A |
| `timeout` | Optional | Maximum request duration in milliseconds. | `3000 ms` |
| `responseType` | Optional | Expected response type. | `'json'` |
### Return Object
| Response Type | Fields | Description |
| ------------- | ------------ | ------------------------------------------------ |
| Success | `data` | Response data sent by the server. |
| | `status` | Numeric HTTP status code. |
| | `statusText` | Textual representation of HTTP status. |
| | `headers` | HTTP headers sent by the server in the response. |
| Error | `error` | Indicates an error occurred (`true`). |
| | `message` | Optional error message. |
| | `code` | Optional error code. |
| | `response` | Optional server response. |
## Data encoding functions
The Functions library includes several encoding functions, which are useful for preparing data for blockchain contracts.
| Function | Input Type | Output Type | Description |
| ------------------------- | ---------------- | ---------------- | ------------------------------------------------------------------------------ |
| `Functions.encodeUint256` | Positive Integer | 32-byte `Buffer` | Converts a positive integer to a 32-byte `Buffer` for a `uint256` in Solidity. |
| `Functions.encodeInt256` | Integer | 32-byte `Buffer` | Converts an integer to a 32-byte `Buffer` for an `int256` in Solidity. |
| `Functions.encodeString` | String | `Buffer` | Converts a string to a `Buffer` for a `string` type in Solidity. |
**Note**: Using these encoding functions is optional. The source code must return a [Uint8Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array) which represents the `bytes` that are returned onchain.
```javascript
const myArr = new Uint8Array(ARRAY_LENGTH)
```
---
# Getting Started
Source: https://docs.chain.link/chainlink-functions/getting-started
Learn how to make requests to the Chainlink Functions Decentralized Oracle Network (DON) and make any computation or API calls offchain. Chainlink Functions is available on several blockchains (see the [supported networks page](/chainlink-functions/supported-networks)), but this guide uses Sepolia to simplify access to testnet funds. Complete the following tasks to get started with Chainlink Functions:
- Set up your web3 wallet and fund it with testnet tokens.
- Simulate a Chainlink Functions on the [Chainlink Functions
Playground](https://functions.chain.link/playground).
- Send a Chainlink Functions request to the DON. The JavaScript source code makes an API call to the [Star Wars API](https://swapi.info) and fetches the name of a given character.
- Receive the response from Chainlink Functions and parse the result.
## Simulation
Before making a Chainlink Functions request from your smart contract, it is always a good practice to simulate the source code offchain to make any adjustments or corrections.
1. Open the [Functions playground](https://functions.chain.link/playground).
2. Copy and paste the following source code into the playground's code block.
3. Under *Argument*, set the first argument to 1. You are going to fetch the name of the first Star Wars character.
4. Click on *Run code*. Under *Output*, you should see *Luke Skywalker*.
## Configure your resources
### Configure your wallet
You will test on Sepolia, so you must have an Ethereum web3 wallet with enough testnet ETH and LINK tokens. Testnet ETH is the native gas fee token on Sepolia. You will use testnet ETH tokens to pay for gas whenever you make a transaction on Sepolia. On the other hand, you will use LINK tokens to pay the Chainlink Functions Decentralized Oracles Network (DON) for processing your request.
1. [Install the MetaMask wallet](/quickstarts/deploy-your-first-contract#install-and-fund-your-metamask-wallet) or other Ethereum web3 wallet.
2. Set the network for your wallet to the Sepolia testnet. If you need to add Sepolia to your wallet, you can find the chain ID and the LINK token contract address on the [LINK Token Contracts](/resources/link-token-contracts#sepolia-testnet) page.
-
3. Request testnet LINK and ETH from [faucets.chain.link/sepolia](https://faucets.chain.link/sepolia).
### Deploy a Functions consumer contract on Sepolia
1. Open the [GettingStartedFunctionsConsumer.sol](https://remix.ethereum.org/#url=https://docs.chain.link/samples/ChainlinkFunctions/GettingStartedFunctionsConsumer.sol) contract in Remix.
2. Compile the contract.
3. Open MetaMask and select the *Sepolia* network.
4. In Remix under the **Deploy & Run Transactions** tab, select *Injected Provider - MetaMask* in the **Environment** list. Remix will use the MetaMask wallet to communicate with *Sepolia*.
5. Click the **Deploy** button to deploy the contract. MetaMask prompts you to confirm the transaction. Check the transaction details to make sure you are deploying the contract to *Sepolia*.
6. After you confirm the transaction, the contract address appears in the **Deployed Contracts** list. Copy the contract address and save it for later. You will use this address with a Functions Subscription.
### Create a subscription
You use a Chainlink Functions subscription to pay for, manage, and track Functions requests.
1. Go to [functions.chain.link](https://functions.chain.link/).
2. Click **Connect wallet**:
3. Read and accept the Chainlink Foundation Terms of Service. Then click **MetaMask**.
4. Make sure your wallet is connected to the *Sepolia* testnet. If not, click the network name in the top right corner of the page and select *Sepolia*.
5. Click **Create Subscription**:
6. Provide an email address and an optional subscription name:
7. The first time you interact with the Subscription Manager using your EOA, you must accept the Terms of Service (ToS). A MetaMask popup appears and you are asked to accept the ToS:
8. After you approve the ToS, another MetaMask popup appears, and you are asked to approve the subscription creation:
9. After the subscription is created, MetaMask prompts you to sign a message that links the subscription name and email address to your subscription:
### Fund your subscription
1. After the subscription is created, the Functions UI prompts you to fund your subscription. Click **Add funds**:
2. For this example, add 2 LINK and click **Add funds**:
### Add a consumer to your subscription
1. After you fund your subscription, add your consumer to it. Specify the address for the consumer contract that you deployed earlier and click **Add consumer**. MetaMask prompts you to confirm the transaction.
2. Subscription creation and configuration is complete. You can always see the details of your subscription again at [functions.chain.link](https://functions.chain.link):
## Run the example
The example is hardcoded to communicate with Chainlink Functions on Sepolia. After this example is run, you can examine the code and see a detailed description of all components.
1. In Remix under the **Deploy & Run Transactions** tab, expand your contract in the **Deployed Contracts** section.
2. Expand the `sendRequest` function to display its parameters.
3. Fill in the `subscriptionId` with your subscription ID and `args` with `[1]`. You can find your subscription ID on the Chainlink Functions Subscription Manager at [functions.chain.link](https://functions.chain.link/). The `[1]` value for `args` specifies which argument in the response will be retrieved.
4. Click the **transact** button.
5. Wait for the request to be fulfilled. You can monitor the status of your request on the Chainlink Functions Subscription Manager.
6. Refresh the Functions UI to get the latest request status.
7. After the status is *Success*, check the character name. In Remix, under the **Deploy & Run Transactions** tab, click the `character` function. If the transaction and request ran correctly, you will see the name of your character in the response.
Chainlink Functions is capable of much more than just retrieving data. Try one of the [Tutorials](/chainlink-functions/tutorials) to see examples that can GET and POST to public APIs, securely handle API secrets, handle custom responses, and query multiple APIs.
## Examine the code
### Solidity code
- To write a Chainlink Functions consumer contract, your contract must import [FunctionsClient.sol](https://github.com/smartcontractkit/chainlink/blob/contracts-v1.3.0/contracts/src/v0.8/functions/v1_0_0/FunctionsClient.sol) and [FunctionsRequest.sol](https://github.com/smartcontractkit/chainlink/blob/contracts-v1.3.0/contracts/src/v0.8/functions/v1_0_0/libraries/FunctionsRequest.sol). You can read the API references: [FunctionsClient](/chainlink-functions/api-reference/functions-client) and [FunctionsRequest](/chainlink-functions/api-reference/functions-request).
These contracts are available in an NPM package so that you can import them from within your project.
```
import {FunctionsClient} from "@chainlink/contracts/src/v0.8/functions/v1_0_0/FunctionsClient.sol";
import {FunctionsRequest} from "@chainlink/contracts/src/v0.8/functions/v1_0_0/libraries/FunctionsRequest.sol";
```
- Use the FunctionsRequest.sol library to get all the functions needed for building a Chainlink Functions request.
```
using FunctionsRequest for FunctionsRequest.Request;
```
- The latest request ID, latest received response, and latest received error (if any) are defined as state variables:
```
bytes32 public s_lastRequestId;
bytes public s_lastResponse;
bytes public s_lastError;
```
- We define the `Response` event that your smart contract will emit during the callback
```
event Response(bytes32 indexed requestId, string character, bytes response, bytes err);
```
- The Chainlink Functions router address and donID are hardcoded for Sepolia. Check the [supported networks page](/chainlink-functions/supported-networks) to try the code sample on another testnet.
- The `gasLimit` is hardcoded to `300000`, the amount of gas that Chainlink Functions will use to fulfill your request.
- The JavaScript source code is hardcoded in the `source` state variable. For more explanation, read the [JavaScript code section](#javascript-code).
- Pass the router address for your network when you deploy the contract:
```
constructor() FunctionsClient(router)
```
- The two remaining functions are:
- `sendRequest` for sending a request. It receives the subscription ID and list of arguments to pass to the source code. Then:
- It uses the `FunctionsRequest` library to initialize the request and add the source code and arguments. You can read the API Reference for [Initializing a request](/chainlink-functions/api-reference/functions-request/#initializerequestforinlinejavascript) and [adding arguments](/chainlink-functions/api-reference/functions-request/#setargs).
```
FunctionsRequest.Request memory req;
req.initializeRequestForInlineJavaScript(source);
if (args.length > 0) req.setArgs(args);
```
- It sends the request to the router by calling the `FunctionsClient` `sendRequest` function. You can read the API reference for [sending a request](/chainlink-functions/api-reference/functions-client/#_sendrequest). Finally, it stores the request id in `s_lastRequestId` and returns it.
```
s_lastRequestId = _sendRequest(
req.encodeCBOR(),
subscriptionId,
gasLimit,
jobId
);
return s_lastRequestId;
```
**Note**: `_sendRequest` accepts requests encoded in `bytes`. Therefore, you must encode it using [encodeCBOR](/chainlink-functions/api-reference/functions-request/#encodecbor).
- `fulfillRequest` to be invoked during the callback. This function is defined in `FunctionsClient` as `virtual` (read `fulfillRequest` [API reference](/chainlink-functions/api-reference/functions-client/#fulfillrequest)). So, your smart contract must override the function to implement the callback. The implementation of the callback is straightforward: the contract stores the latest response and error in `s_lastResponse` and `s_lastError`, parses the `response` from `bytes` to `string` to fetch the character name before emitting the `Response` event.
```
s_lastResponse = response;
character = string(response);
s_lastError = err;
emit Response(requestId, s_lastResponse, s_lastError);
```
### JavaScript code
This JavaScript source code uses [Functions.makeHttpRequest](/chainlink-functions/api-reference/javascript-source#http-requests) to make HTTP requests. The source code calls the `https://swapi.info/` API to request a Star Wars character name. If you read the [Functions.makeHttpRequest](/chainlink-functions/api-reference/javascript-source#http-requests) documentation and the [Star Wars API documentation](https://swapi.info/people), you notice that URL has the following format where `$characterId` is provided as parameter when making the HTTP request:
```
url: `https://swapi.info/api/people/${characterId}/`
```
To check the expected API response for the first character, you can directly paste the following URL in your browser `https://swapi.info/api/people/1/` or run the `curl` command in your terminal:
```bash
curl -X 'GET' \
'https://swapi.info/api/people/1/' \
-H 'accept: application/json'
```
The response should be similar to the following example:
```json
{
"name": "Luke Skywalker",
"height": "172",
"mass": "77",
"hair_color": "blond",
"skin_color": "fair",
"eye_color": "blue",
"birth_year": "19BBY",
"gender": "male",
"homeworld": "https://swapi.info/api/planets/1/",
"films": [
"https://swapi.info/api/films/1/",
"https://swapi.info/api/films/2/",
"https://swapi.info/api/films/3/",
"https://swapi.info/api/films/6/"
],
"species": [],
"vehicles": ["https://swapi.info/api/vehicles/14/", "https://swapi.info/api/vehicles/30/"],
"starships": ["https://swapi.info/api/starships/12/", "https://swapi.info/api/starships/22/"],
"created": "2014-12-09T13:50:51.644000Z",
"edited": "2014-12-20T21:17:56.891000Z",
"url": "https://swapi.info/api/people/1/"
}
```
Now that you understand the structure of the API. Let's delve into the JavaScript code. The main steps are:
- Fetch `characterId` from `args`. Args is an array. The `characterId` is located in the first element.
- Make the HTTP call using `Functions.makeHttpRequest` and store the response in `apiResponse`.
- Throw an error if the call is not successful.
- The API response is located at `data`.
- Read the name from the API response `data.name` and return the result as a [buffer](https://nodejs.org/api/buffer.html#buffer) using the `Functions.encodeString` helper function. Because the `name` is a `string`, we use `encodeString`. For other data types, you can use different [data encoding functions](/chainlink-functions/api-reference/javascript-source#data-encoding-functions).
**Note**: Read this [article](https://www.freecodecamp.org/news/do-you-want-a-better-understanding-of-buffer-in-node-js-check-this-out-2e29de2968e8/) if you are new to Javascript Buffers and want to understand why they are important.
---
# Chainlink Functions
Source: https://docs.chain.link/chainlink-functions
Chainlink Functions provides your smart contracts access to trust-minimized compute infrastructure, allowing you to fetch data from APIs and perform custom computation. Your smart contract sends source code in a request to a [Decentralized Oracle Network (DON)](/chainlink-functions/resources/concepts), and each node in the DON executes the code in a serverless environment. The DON then aggregates all the independent return values from each execution and sends the final result back to your smart contract.
Chainlink Functions eliminates the need for you to manage your own Chainlink node and provides decentralized offchain computation and consensus, ensuring that a minority of the network cannot manipulate the response sent back to your smart contract.
Furthermore, Chainlink Functions allows you to include secret values in your request that are encrypted using threshold encryption. These values can only be decrypted via a multi-party decryption process, meaning that every node can only decrypt the secrets with participation from other DON nodes. This feature can provide API keys or other sensitive values to your source code, enabling access to APIs that require authentication.
To pay for requests, you fund a subscription account with LINK. Your subscription is billed when the DON fulfills your requests. Check out the [subscriptions](/chainlink-functions/resources/subscriptions) page for more information.
Read the [architecture](/chainlink-functions/resources/architecture) page to learn more about how Chainlink Functions works.
See the [Tutorials](/chainlink-functions/tutorials) page for simple tutorials showing you different GET and POST requests that run on Chainlink Functions. You can also gain hands-on experience with Chainlink Functions with the [Chainlink Functions Playground](https://functions.chain.link/playground).
## When to use Chainlink Functions
Chainlink Functions enables a variety of use cases. Use Chainlink Functions to:
- Connect to any public data. For example, you can connect your smart contracts to weather statistics for parametric insurance or real-time sports results for Dynamic NFTs.
- Connect to public data and transform it before consumption. You could calculate Twitter sentiment after reading data from the Twitter API, or derive asset prices after reading price data from [Chainlink Price Feeds](/data-feeds/price-feeds).
- Connect to a password-protected data source; from IoT devices like smartwatches to enterprise resource planning systems.
- Connect to an external decentralized database, such as IPFS, to facilitate offchain processes for a dApp or build a low-cost governance voting system.
- Connect to your Web2 application and build complex hybrid smart contracts.
- Fetch data from almost any Web2 system such as AWS S3, Firebase, or Google Cloud Storage.
You can find several community examples at [useChainlinkFunctions.com](https://www.usechainlinkfunctions.com/)
## Supported networks
See the [Supported Networks](/chainlink-functions/supported-networks) page to find a list of supported networks and contract addresses.
---
# Chainlink Functions Architecture
Source: https://docs.chain.link/chainlink-functions/resources/architecture
## Request and Receive Data
This model is similar to the [Basic Request Model](/architecture-overview/architecture-request-model): The consumer contract initiates the cycle by sending a request to the [FunctionsRouter contract](https://github.com/smartcontractkit/chainlink/blob/contracts-v1.3.0/contracts/src/v0.8/functions/v1_0_0/FunctionsRouter.sol). Oracle nodes watch for events emitted by the [FunctionsCoordinator contract](https://github.com/smartcontractkit/chainlink/blob/contracts-v1.3.0/contracts/src/v0.8/functions/v1_1_0/FunctionsCoordinator.sol) and run the computation offchain. Finally, oracle nodes use the [Chainlink OCR](/architecture-overview/off-chain-reporting) protocol to aggregate all the returned before passing the single aggregated response back to the consumer contract via a callback function.
The main actors and components are:
- Initiator (or end-user): initiates the request to Chainlink Functions. It can be an [EOA (Externally Owned Account)](https://ethereum.org/en/developers/docs/accounts/#types-of-account) or Chainlink Automation.
- Consumer contract: smart contract deployed by developers, which purpose is to interact with the FunctionsRouter to initiate a request.
- FunctionsRouter contract: manages subscriptions and is the entry point for consumers. The interface of the router is stable. Consumers call the `sendRequest` method to initiate a request.
- FunctionsCoordinator contracts: interface for the [Decentralized Oracle Network](https://chain.link/education/blockchain-oracles#decentralized-oracles). Oracle nodes listen to events emitted by the coordinator contract and interact with the coordinator to transmit the responses.
- DON: Chainlink Functions are powered by a [Decentralized Oracle Network](https://chain.link/education/blockchain-oracles#decentralized-oracles). The oracle nodes are independent of each other and are responsible for executing the request's source code. The nodes use the [Chainlink OCR](/architecture-overview/off-chain-reporting) protocol to aggregate all the nodes' responses. Finally, a DON's oracle sends the aggregate response to the consumer contract in a callback.
- Secrets endpoint: To transmit their secrets, users can encrypt them with the DON public key and then upload them to the secrets endpoint, a highly available service for securely sharing encrypted secrets with the nodes. **Note**: An alternative method involves self-hosting secrets. In this approach, users provide a publicly accessible HTTP(s) URL, allowing nodes to retrieve the encrypted secrets. Refer to the [secrets management](/chainlink-functions/resources/secrets) page for detailed information on both methods.
- Serverless Environment: Every Oracle node accesses a distinct, sandboxed environment for computation. While the diagram illustrates an API request, the computation isn't restricted solely to this. You can perform any computation, from API calls to mathematical operations, using vanilla [Deno](https://deno.land/) code without module imports. Note: All nodes execute identical computations. If the target API has throttling limits, know that multiple simultaneous calls will occur since each DON node will independently run the request's source code.
Let's walk through the sequence of interactions among these components, as illustrated in the diagram:
1. If there are secrets, a user encrypts secrets with the public key linked to the DON master secret key (MSK) and then uploads the encrypted secrets to the secrets endpoint. The secrets endpoint pushes the encrypted secrets to the nodes part of the DON (The secrets capability depicted in this diagram is called *threshold encryption* and is explained in [secrets management](/chainlink-functions/resources/secrets#threshold-encryption)).
2. An [EOA (Externally Owned Account)](https://ethereum.org/en/developers/docs/accounts/#types-of-account) or Chainlink Automation initiates the request by calling the consumer contract.
3. The consumer contract should inherit the [FunctionsClient](https://github.com/smartcontractkit/chainlink/blob/contracts-v1.3.0/contracts/src/v0.8/functions/v1_0_0/FunctionsClient.sol) contract. This ensures it will be able to receive responses from the [FunctionsRouter](https://github.com/smartcontractkit/chainlink/blob/contracts-v1.3.0/contracts/src/v0.8/functions/v1_0_0/FunctionsRouter.sol) contract via the `handleOracleFulfillment` callback. The router contract starts the billing to estimate the fulfillment costs and block the amount in the *reservation balance* (To learn more, read [Cost simulation](/chainlink-functions/resources/billing#cost-simulation-reservation)). Then it calls the [FunctionsCoordinator contract](https://github.com/smartcontractkit/chainlink/blob/contracts-v1.3.0/contracts/src/v0.8/functions/v1_1_0/FunctionsCoordinator.sol).
4. The coordinator contract emits an `OracleRequest` event containing information about the request.
5. On reception of the event by the DON, the DON's nodes decrypt the secrets using threshold decryption (The threshold encryption feature is explained in [secrets management](/chainlink-functions/resources/secrets#threshold-encryption)). Each DON's Oracle node executes the request's source code in a serverless environment.
6. The DON runs the Offchain Reporting protocol (OCR) to aggregate the values returned by each node's execution of the source code.
7. A DON's oracle node transmits the attested report (which includes the aggregated response) to the FunctionsCoordinator contract.
8. The FunctionsCoordinator contract calls the FunctionsRouter's `fulfill` method to calculate the fulfillment costs and finalize the billing (To learn more, read [Cost calculation](/chainlink-functions/resources/billing#cost-calculation-fulfillment)).
9. The FunctionsRouter contract calls the consumer contract's callback with the aggregated response.
**Note**: Chainlink Functions requests are not limited to API requests. The diagram depicts an example of API requests, but you can request the DON to run any computation.
## Subscription management
Chainlink Functions do not require your consumer contracts to hold LINK tokens and send them to oracles when making requests. Instead, you must create a subscription account and fund it to pay for your Chainlink Functions requests, so your consumer contracts don't need to hold LINK when calling Chainlink Functions.
### Concepts
- Terms of service (ToS): Before interacting with Chainlink Functions, users must agree to the terms of service. Once signed, the accounts that can manage subscriptions are added to the `allowedSenders` in the [ToS allow list contract](https://github.com/smartcontractkit/chainlink/blob/contracts-v1.3.0/contracts/src/v0.8/functions/v1_0_0/accessControl/TermsOfServiceAllowList.sol).
- Chainlink Functions Subscription Manager: A user interface that allows users to agree to the sign Terms of service and interact with the FunctionsRouter to manage subscriptions.
- Subscription account: An account that holds LINK tokens and makes them available to fund requests to Chainlink DON. A *Subscription ID* uniquely identifies each account.
- Subscription ID: 64-bit unsigned integer representing the unique identifier of the *Subscription account*.
- Subscription owner: The wallet address that creates and manages a *Subscription account*. Any account can add LINK tokens to the subscription balance. Still, only the owner can add consumer contracts to the subscription, remove consumer contracts from the subscription, withdraw funds, or transfer a subscription. Only the subscription owner can generate encrypted secrets for requests that use their *Subscription ID*.
- Subscription balance: The amount of LINK maintained on your *Subscription account*. Requests from consumer contracts are funded as long as sufficient funds are in the balance, so be sure to maintain sufficient funds in your *Subscription balance* to pay for the requests and keep your applications running.
- Subscription reservation: The amount of LINK blocked on the *Subscription balance*. It corresponds to the total LINK amount to be paid by in-flight requests.
- Effective balance: The amount of LINK available on your *Subscription account*. `Effective balance = Subscription balance - Subscription reservation`.
- Subscription consumers: Consumer contracts are approved to use funding from your *Subscription account* while making Chainlink Functions requests. The consumers receive response data in a callback.
### Accept ToS
To ensure compliance and governance, Chainlink Functions mandates that any account that manages a subscription must first accept the platform's Terms of Service (ToS). The acceptance is verified by cross-referencing the account with the `allowedSenders` registry contained within the [TermsOfServiceAllowList contract](https://github.com/smartcontractkit/chainlink/blob/contracts-v1.3.0/contracts/src/v0.8/functions/v1_0_0/accessControl/TermsOfServiceAllowList.sol).
The acceptance process is initiated via the Chainlink Functions Subscription Manager. After a user accepts the ToS by generating the required signature with their externally owned account (EOA), they transmit proof of acceptance to the [TermsOfServiceAllowList contract](https://github.com/smartcontractkit/chainlink/blob/contracts-v1.3.0/contracts/src/v0.8/functions/v1_0_0/accessControl/TermsOfServiceAllowList.sol). Upon successful validation of the proof, the EOA is added to the `allowedSenders` registry, permitting it to manage subscriptions.
### Create subscription
After the ToS is accepted, EOAs can create subscriptions. Upon creation, the [FunctionsRouter](https://github.com/smartcontractkit/chainlink/blob/contracts-v1.3.0/contracts/src/v0.8/functions/v1_0_0/FunctionsRouter.sol) assigns a unique identifier, *Subscription ID*.
**Note**: EOAs can directly interact with the FunctionsRouter contract using their preferred web3 library, such as web3.js or ethers.js.
### Fund subscription
You must fund your subscription accounts with enough LINK tokens:
1. Connect your EOA to the Chainlink Functions Subscription Manager.
2. Fund your subscription account. The Chainlink Functions Subscription Manager abstracts the following:
1. Call `transferAndCall` on the LINK token contract, transferring LINK tokens along with the *Subscription ID* in the payload.
2. The FunctionsRouter contract implements `onTokenTransfer`: It parses the *Subscription ID* from the payload and funds the subscription account with the transferred LINK amount.
**Note**: EOAs can directly interact with the LinkToken contract using their preferred web3 library, such as web3.js or ethers.js.
### Add consumer
You must allowlist your consumers' contracts on your subscription account before they can make Chainlink Functions requests:
1. Connect your EOA to the Chainlink Functions Subscription Manager.
2. Add the address of the consumer contract to the subscription account.
3. The Chainlink Functions Subscription Manager interacts with the FunctionsRouter contract to register the consumer contract address to the subscription account.
**Note**: EOAs can directly interact with the FunctionsRouter contract using a web3 library, such as web3.js or ethers.js.
### Remove consumer
To prevent further Chainlink Functions requests from a given consumer contract, you must remove it from your subscription account:
1. Connect your EOA to the Chainlink Functions Subscription Manager.
2. Remove the address of the consumer contract from the subscription account.
3. The Chainlink Functions Subscription Manager communicates with the FunctionsRouter contract to remove the consumer contract address from the subscription account.
**Note**: You can still remove consumers from your subscription even if in-flight requests exist. The consumer contract will still receive a callback, and your *Subscription Account* will be charged.
**Note**: EOAs can directly interact with the FunctionsRouter contract using a web3 library, such as web3.js or ethers.js.
### Cancel subscription
To cancel a subscription:
1. Connect your EOA to the Chainlink Functions Subscription Manager.
2. Cancel your subscription, providing the *Subscription Balance* receiver account address. The Chainlink Functions Subscription Manager handles the following processes:
1. Invokes the `cancelSubscription` function on the FunctionsRouter contract, deleting the *Subscription ID* and removing all associated consumers.
2. Transfers the remaining *Subscription Balance* to the specified receiver account.
**Note**: EOAs can directly interact with the FunctionsRouter contract using their preferred web3 library, such as web3.js or ethers.js.
**Note**: Subscriptions cannot be canceled while there are in-flight requests. Furthermore, any expired requests (requests that have yet to receive a response within 5 minutes) must be timed out before cancellation.
### Transferring ownership of a Subscription
Transferring ownership is currently only supported using the [Functions Hardhat Starter kit](https://github.com/smartcontractkit/functions-hardhat-starter-kit) or the [Functions Toolkit NPM package](https://github.com/smartcontractkit/functions-toolkit):
1. Use the `functions-sub-transfer` command to initiate the transfer of ownership by specifying the new owner's address.
2. As a prerequisite, the prospective owner must be part of the `allowedSenders` registry within the [TermsOfServiceAllowList contract](https://github.com/smartcontractkit/chainlink/blob/contracts-v1.3.0/contracts/src/v0.8/functions/v1_0_0/accessControl/TermsOfServiceAllowList.sol). This verifies their acceptance of the Chainlink Functions' Terms of Service (ToS).
3. The prospective owner should use the [Functions Hardhat Starter kit](https://github.com/smartcontractkit/functions-hardhat-starter-kit) and run the `functions-sub-accept` command to confirm the ownership transfer.
**Note**: This guide will be updated as soon as the Chainlink Functions Subscription Manager supports ownership transfers.
---
# Chainlink Functions Billing
Source: https://docs.chain.link/chainlink-functions/resources/billing
## Request costs
To send Chainlink Functions requests, you must maintain a sufficient amount of LINK in your subscription balance. Because Chainlink Functions follows the [Request and Receive Data](/chainlink-functions/resources/architecture) model, billing is done in two steps:
1. During the **request** step, the cost to fulfill a Chainlink Functions request is **estimated** and blocked on the subscription balance by adding it to the subscription reservation.
2. During the **receive** step, the exact fulfillment cost is **calculated**, then billed to the subscription account, and the subscription reservation is removed.
You can break down total costs into the following components:
- Gas cost: This cost is paid back to the transmitter oracle in LINK for fulfilling the request.
- Premium fees: These fees are paid in LINK to compensate nodes for their work and for the maintenance of the FunctionsRouter contract.
Gas cost calculation includes the following variables:
- Gas price: The current gas price fluctuates depending on network conditions.
- Overestimated gas price: refers to a deliberately higher gas price estimation to account for potential price fluctuations between the time a request is made and the time Chainlink Functions fulfills it. By setting the gas price higher than the current one, Chainlink Functions increases the likelihood that the request will be fulfilled, even if gas prices rise unexpectedly in the short term. The overestimation is calculated as a percentage increase over the current gas price.
- Callback gas: The amount of gas used for the callback request. See the [Cost Calculation](#cost-calculation-fulfillment) section.
- Callback gas limit: The maximum amount of gas that can be used to call the `handleOracleFulfillment` callback function of the consumer contract in order to provide the response. See the [Cost Simulation](#cost-simulation-reservation) section.
- Gas overhead: The amount of gas used by the FunctionsRouter and FunctionsCoordinator contracts. It is an estimate of the total gas cost of fulfilling a request.
- Native to LINK translation: Your subscription balance can be billed only in LINK tokens.
- Translate the network's native gas tokens to LINK: The total gas cost in *native* units is translated using the correct [Price Feed](/data-feeds/price-feeds/addresses). For example, on Sepolia, the translation uses the ETH/LINK Price Feed, and on Polygon, the translation uses POL/LINK Price Feed.
- Fallback Wei to LINK ratio: In the unlikely event that the *Native to LINK* price data feed is unavailable, the fallback translation is used. You can find this ratio by running the `getConfig` function in the FunctionsCoordinator contract. See the [Supported Networks](/chainlink-functions/supported-networks) page to find the contract addresses for each network.
### Cost simulation (reservation)
During the **request** step:
1. The total cost in LINK is **estimated** using the following formula:
```
total estimated gas cost in LINK = (Overestimated gas price * (Gas overhead + Callback gas limit)) / Native to LINK translation
total estimated cost in LINK = total estimated gas cost + premium fees
```
All networks have USD-denominated premium fees. This means that the fixed premium fee is denominated in USD, but no USD is ever used. The LINK equivalent of this fee is calculated at request time.
2. The total estimated cost is then added to the subscription reservation.
### Cost calculation (fulfillment)
When a DON's oracle reports the response, subscription accounts are charged based on the gas amount used in the callback:
1. The total cost in LINK is **calculated** using the following formula:
```
total gas cost in LINK = (Gas price * (Gas overhead + Callback gas)) / Native to LINK translation
total cost in LINK = total gas cost + premium fees
```
All networks have USD-denominated premium fees. This means that the fixed premium fee is denominated in USD, but no USD is ever used. The LINK equivalent of this fee is calculated at request time.
2. The FunctionsRouter contract performs several accounting movements.
### Cost calculation example
This is an example of cost estimation for a request and then cost calculation at fulfillment.
For networks with USD-denominated premium fees, the premium fees are set in USD, but no USD is ever used. The LINK equivalent of the fee is calculated at request time, and then deducted from your subscription in LINK at response time.
#### Cost Simulation (Reservation)
| Parameter | Value |
| ----------------------- | ------------- |
| Overestimated gas price | 9 gwei |
| Callback gas limit | 300000 |
| Gas overhead | 185000 |
| Premium fee | 320 cents USD |
1. Calculate the total estimated gas cost in LINK, using an overestimated gas price, the gas overhead, and the full callback gas limit:
| Gas cost calculation | Total estimated gas cost |
| ------------------------------------------------------------- | --------------------------- |
| Overestimated gas price x (Gas overhead + Callback gas limit) | |
| 9 gwei x (300000 + 185000) | 4365000 gwei (0.004365 ETH) |
2. Convert the gas cost to LINK using the [LINK/ETH feed](https://data.chain.link/ethereum/mainnet/crypto-eth/link-eth).
For this example, assume the feed returns a conversion value of Ξ0.007 ETH per 1 LINK.
| ETH to LINK cost conversion | Total gas cost (LINK) |
| ----------------------------- | --------------------- |
| 0.004365 ETH / 0.007 ETH/LINK | 0.62 LINK |
3. Convert the USD-denominated premium fee to LINK using the [LINK/USD feed](https://data.chain.link/feeds/ethereum/mainnet/link-usd).
For this example, assume the feed returns a conversion value of $20.00 USD per 1 LINK:
| USD to LINK cost conversion | Premium fee (LINK) |
| --------------------------- | ------------------ |
| $3.20 USD / 20.00 USD/LINK | 0.16 LINK |
4. Add the converted premium fee to get the estimated cost for a subscription reservation:
| Adding converted LINK premium | Maximum request cost (LINK) |
| ----------------------------------- | --------------------------- |
| Total gas cost (LINK) + Premium fee | |
| 0.62 LINK + 0.16 LINK | 0.78 LINK |
For this example request, 0.78 LINK is reserved from your subscription balance, but not yet deducted. When the request is fulfilled, the exact request cost is deducted. The estimated cost of a request is overestimated to allow for 99% of gas price fluctuation increases in between request and response time.
#### Cost calculation (fulfillment)
| Parameter | Value |
| ----------------------------- | --------- |
| Gas price | 1.5 gwei |
| Callback gas | 200000 |
| Gas overhead | 185000 |
| Premium fee converted to LINK | 0.16 LINK |
1. Calculate the total gas cost:
| Gas cost calculation | Total gas cost |
| ----------------------------------------- | --------------------------- |
| Gas price x (Gas overhead + Callback gas) | |
| 1.5 gwei x (200000 + 185000) | 577500 gwei (0.0005775 ETH) |
2. Convert the gas cost to LINK using the [LINK/ETH feed](https://data.chain.link/ethereum/mainnet/crypto-eth/link-eth).
For this example, assume the feed returns a conversion value of Ξ0.007 ETH per 1 LINK.
| ETH to LINK cost conversion | Total gas cost (LINK) |
| ------------------------------ | --------------------- |
| 0.0005775 ETH / 0.007 ETH/LINK | 0.0825 LINK |
3. The premium fee was converted from USD to LINK at the time of the request. Add this converted premium fee to get the total cost of a request:
| Adding premium fee | Total request cost (LINK) |
| ----------------------------------- | ------------------------- |
| Total gas cost (LINK) + premium fee | |
| 0.0825 LINK + 0.16 LINK | 0.2425 LINK |
This example request would cost 0.2425 LINK when it is fulfilled. The subscription reservation for the 0.78 LINK is released, and the actual cost of 0.2425 LINK is deducted from your subscription balance.
## Minimum balance for uploading encrypted secrets
If you choose to store the encrypted secrets with the DON (learn more on the [Secrets Management page](/chainlink-functions/resources/secrets)), then one of your subscriptions must maintain a balance greater than the minimum required for uploading encrypted secrets. This balance is blockchain-specific. You can find the specific values for each blockchain on the [Supported Networks](/chainlink-functions/supported-networks) page.
**Note**: Uploading encrypted secrets is free of charge. However, to prevent misuse of Chainlink Functions, you are required to maintain a minimum balance in one of the subscriptions owned by your externally-owned account (EOA) before you can upload encrypted secrets to a DON.
## Withdrawing funds
To withdraw your LINK balance, you must first cancel your subscription. To prevent misuse of Chainlink Functions, any subscription with fulfilled requests below the *request threshold* will incur a cancellation fee. Both the request threshold and the cancellation fee are blockchain-specific. You can find their values for each blockchain on the [Supported Networks](/chainlink-functions/supported-networks) page.
**Example 1**:
- **Request Threshold**: Two requests
- **Cancellation Fee**: 0.5 LINK
- **Your Balance**: 0.4 LINK
- **Number of Fulfilled Requests**: One
- **Outcome**: Canceling your subscription results in a non-refundable balance
**Example 2**:
- **Request Threshold**: Two requests
- **Cancellation Fee**: 0.5 LINK
- **Your Balance**: 1 LINK
- **Number of Fulfilled Requests**: One
- **Outcome**: You will receive 0.5 LINK if you cancel your subscription
**Example 3**:
- **Request Threshold**: Two requests
- **Cancellation Fee**: 0.5 LINK
- **Your Balance**: 1 LINK
- **Number of Fulfilled Requests**: Two or more
- **Outcome**: You will receive 1 LINK if you cancel your subscription. Your subscription will not incur the cancellation fee
---
# Chainlink Functions Resources
Source: https://docs.chain.link/chainlink-functions/resources
## Topics
- [Architecture](/chainlink-functions/resources/architecture)
- [Managing Subscriptions](/chainlink-functions/resources/subscriptions)
- [Billing](/chainlink-functions/resources/billing)
- [Supported Networks](/chainlink-functions/supported-networks)
- [Service Limits](/chainlink-functions/resources/service-limits)
---
# Secrets Management
Source: https://docs.chain.link/chainlink-functions/resources/secrets
Chainlink Functions enables users to fetch data from HTTP(s) APIs and perform custom computation. To enable access to APIs that require authentication credentials, Chainlink Functions allows users to provide encrypted secret values, which can be used when the DON executes a Functions request. These values can only be decrypted via a multi-party decryption process called threshold decryption. This means that every node can only decrypt the secrets with participation from other DON nodes.
These encrypted secret values can either be uploaded to the DON or hosted at a remote URL. Then, a reference to the encrypted secrets can be used when making a Functions request.
## Threshold encryption
Using a single private key to decrypt user secrets poses a considerable security risk. If any node with this key becomes malicious or compromised, it can decrypt all accessible user secrets.
To address this vulnerability, we have integrated a feature known as *threshold encryption*. The characteristics of this enhanced security measure include:
1. Decentralized Nodes Deployment: The system operates on a Decentralized Oracle Network (DON) with N nodes.
2. Master Secret Key Distribution: Instead of centralizing the private key, the master secret key (MSK) is partitioned into shares. Each node within the DON possesses a distinct share of this MSK.
3. The system enforces two thresholds:
- Liveness: This feature ensures the system's availability and fault tolerance. It can tolerate up to F Byzantine nodes (nodes that can act arbitrarily or maliciously) while remaining operational. The system adheres to the mathematical relationship `3F+1≤N`. This means the total number of nodes N must be at least three times the number of faulty or malicious nodes F, plus one more.
- Decryption security: Considering that the MSK is distributed across multiple nodes, safeguarding it is essential. To recover the master secret key (MSK), an attacker must corrupt a number of K nodes, adhering to the relationship:
`FContact us to increase the limits for your Chainlink
Function.
| Item | Description | Limits |
| ---------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------- |
| Supported languages | Supported language of the Source code that is submitted in the Chainlink Functions request | JavaScript compatible with [Deno](https://deno.land/) runtime and module imports |
| Maximum requests in flight | The maximum number of simultaneous Chainlink Functions requests that are not fulfilled yet by the DON | Limited by the [effective balance](/chainlink-functions/resources/architecture#subscription-management) |
| Maximum callback gas limit | The maximum amount of gas that you can set for Chainlink Functions to fulfill your callback function | 300,000 |
| Maximum subscriptions | Maximum subscriptions that you can create | unbounded |
| Maximum consumer contracts per subscription | The maximum number of consumer contracts that you can add to a subscription | 100 |
| Maximum duration of a request (Request fulfillment timeout) | The maximum duration of a request is the time allowed for processing a Chainlink Functions request from start to finish, covering all steps such as reading from the chain, executing code, and posting back on chain. If processing takes longer, the request times out, and no charges are applied to your subscription for that request. In such cases, the initially locked estimated request costs must be manually requested to be returned to your subscription balance | 5 minutes |
| Maximum request size | The maximum size of a Chainlink Request. This includes the source code, arguments, and secrets | 30 kilobytes |
| Maximum returned value size | The maximum size of the value that your Function can return | 256 bytes |
| Maximum source code execution time | The maximum amount of time that a source code can run | 10 seconds |
| Maximum memory allocated to the source code | The maximum amount of memory allocated to your source code during execution | 128 megabytes |
| HTTP - Maximum queries | The maximum number of HTTP requests that your source code can make | 5 |
| HTTP - query timeout | The maximum duration of an HTTP request before it times out | 9 seconds |
| HTTP - Maximum URL length | Length of the HTTP URL | 2048 characters |
| HTTP - Maximum request length | The maximum size of an HTTP request, including the request body and HTTP headers | 30 kilobytes |
| HTTP - Maximum response length | The maximum size of an HTTP response | 2 megabytes |
| Max size of request payload CBOR | The maximum size of an encoded request | 30 kilobytes |
| Don-hosted secrets - Maximum Time to live (TTL) | The maximum duration for which a secret hosted on a DON remains valid before it gets deleted |
Mainnets: 3 months (2160 hours)
Testnets: 3 days (72 hours)
|
| External module imports - Maximum size | The maximum size in MB that each imported module can be | 10 MB |
| External module imports - Number of imports | The maximum number of external module imports allowed in each request | 100 imports |
---
# Simulate your Functions
Source: https://docs.chain.link/chainlink-functions/resources/simulation
Before making a Chainlink Functions request from your smart contract, it is always a good practice to simulate the source code off-chain to make any adjustments or corrections.
Currently, there are several options for simulating a request:
- [Chainlink Functions playground](https://functions.chain.link/playground).
- [Chainlink Functions Hardhat Starter Kit](https://github.com/smartcontractkit/functions-hardhat-starter-kit): Use the `npx hardhat functions-simulate-script` command to simulate your Functions JavaScript source code.
- [Chainlink Functions Toolkit NPM package](https://github.com/smartcontractkit/functions-toolkit): Import this NPM package into your JavaScript/TypeScript project, then use the `simulateScript` function to simulate your Functions JavaScript source code.
## Chainlink Functions playground
To use the [Chainlink Functions
Playground](https://functions.chain.link/playground), enter any source code, arguments, and secrets you would like to use. Click the **Run code** button to view the output.
## Chainlink Functions Hardhat Starter Kit
This repository comes preconfigured with [Hardhat](https://hardhat.org/) and the [Chainlink Functions Toolkit NPM package](https://github.com/smartcontractkit/functions-toolkit), allowing you to quickly get started with Functions.
To simulate:
1. In a terminal, clone the [functions-hardhat-starter-kit repository](https://github.com/smartcontractkit/functions-hardhat-starter-kit) and change to the `functions-hardhat-starter-kit` directory.
```shell
git clone https://github.com/smartcontractkit/functions-hardhat-starter-kit && \
cd functions-hardhat-starter-kit
```
2. Run `npm install` to install the dependencies.
```shell
npm install
```
3. For simulation, you don't need to set up the environment variables. Run `npx hardhat functions-simulate-script` to simulate the [calculation-example.js](https://github.com/smartcontractkit/functions-hardhat-starter-kit/blob/main/calculation-example.js) JavaScript source code. **Note:** This example calculates the continuously compounding interest for a given principal amount over one month. It takes the principal amount and annual percentage yield (APY) as input arguments and uses [Euler's number](https://www.investopedia.com/terms/e/eulers-constant.asp) to compute the total amount after interest.
```shell
npx hardhat functions-simulate-script
```
Result:
```text
secp256k1 unavailable, reverting to browser version
Response returned by script during local simulation: 1003757
```
## Chainlink Functions Toolkit NPM package
Follow the [Simple Computation](/chainlink-functions/tutorials/simple-computation) guide to learn how to import the [Chainlink Functions Toolkit NPM package](https://github.com/smartcontractkit/functions-toolkit) into your JavaScript project to simulate and execute a Functions request.
You can read the [Examine the code section](/chainlink-functions/tutorials/simple-computation#javascript-example) for a detailed description of the code example.
**Note**: You can also import and use the Chainlink Functions Toolkit NPM package as a scripting dependency inside [Remix IDE scripts](https://remix-ide.readthedocs.io/en/latest/running_js_scripts.html) in your browser.
---
# Managing CL Functions Subscriptions
Source: https://docs.chain.link/chainlink-functions/resources/subscriptions
The Chainlink Functions Subscription Manager is available [here](https://functions.chain.link/). The Functions Subscription Manager lets you create a subscription, add consumers to it, remove consumers from it, fund it with LINK, and delete it.
When you connect to the Subscription Manager, choose the correct network, then click *connect wallet*.
## Subscriptions
You use a Chainlink Functions subscription to pay for, manage, and track Functions requests.
### Create a subscription
1. Open [functions.chain.link](https://functions.chain.link/) and click *Create Subscription*:
2. Provide an email address and an optional subscription name:
3. The first time that you interact with the Subscription Manager using your EOA, you have to approve the Terms of Service (ToS):
4. When you approve the ToS, a MetaMask popup appears that asks you to approve the subscription creation:
5. After the subscription is created, you are asked to sign a message in MetaMask to link the subscription name and email address to your subscription:
{" "}
1. After the subscription is created, fund it with LINK:
2. After funding, you can add a consumer to it:
3. After creation, you can fetch the details of your subscription:
### Fund a subscription
1. Open your subscription details and click *Actions* then click *Fund subscription*:
2. Fund your subscription. For instance, *0.1 LINK*:
3. A MetaMask popup appears, and you are asked to confirm the transaction. After you confirm the transaction, a confirmation screen appears:
### Add a consumer contract to a subscription
1. Open your subscription details and click *Add Consumer*:
2. Fill in the consumer address:
3. A MetaMask popup appears, and you are asked to confirm the transaction. After you confirm the transaction, a confirmation screen appears:
### Remove a consumer contract from a subscription
1. Open your subscription details and click the consumer you want to remove, then *Remove Consumer*:
2. A MetaMask popup appears, and you are asked to confirm the transaction.
3. After you confirm the transaction, a confirmation screen appears:
### Cancel a subscription
**Note**: You cannot cancel a subscription if there are in-flight requests. In-flight requests are requests that still need to be fulfilled.
1. Open your subscription details, click *Actions*, then *Cancel subscription*:
2. Fill in the receiver address of the remaining funds:
3. A MetaMask popup appears, and you are asked to confirm the transaction.
4. After you confirm the transaction, a confirmation screen appears:
## Time out pending requests manually
The Subscription Manager provides the option to time out requests manually. You can time out requests that have been pending for longer than five minutes to unlock your subscription funds.
1. Open your subscription details and scroll to the **Pending** section. If a request has been pending longer than five minutes, its status displays as *Time out required*. Click the link within the red banner that says **Time out request**:
If you have multiple requests that are eligible for timeout, the **Time out request** link in the red banner times out all the requests at once.
Alternatively, you can time out an individual request. Open the **Actions** menu for that request, and click **Time out request**:
{" "}
2. A MetaMask popup appears, and you are asked to confirm the transaction:
3. After you confirm the transaction, a confirmation screen appears:
4. The subscription details page displays another confirmation in the upper right corner showing that the request has been timed out successfully:
5. The timed out request appears in the **Failed fulfillments** tab of the **History** section:
---
# Chainlink Functions Service Responsibility
Source: https://docs.chain.link/chainlink-functions/service-responsibility
Chainlink Functions provides access to trust-minimized compute infrastructure that allows you to retrieve data and run computation. Because the service is highly-flexible and runs offchain, both developers and Chainlink service providers share responsibility in ensuring that operation and performance match expectations.
## Developer responsibilities
Developers who implement Chainlink Functions in their code and applications are responsible for several components.
### Data
- **Data quality:** When using Chainlink Functions, developers are responsible for ensuring that any external data they retrieve meet the data quality requirements for their applications. This responsibility applies to data retrieved via APIs or other data retrieval mechanisms. You must ensure that the data sources you consume through Chainlink Functions are accurate, reliable, secure, and not at risk of manipulation by malicious actors. When possible, use multiple data sources to reduce single points of failure and manipulation risks.
- **Data availability:** Developers must ensure that the data sources and APIs that they use with Chainlink Functions meet the fault-tolerance and availability requirements for their applications. Node operators are geographically distributed, so developers must ensure that APIs do not have geographic or other restrictions that would prohibit node operators from retrieving data. When possible, use redundant data sources to reduce the risk that your applications cannot execute due to unavailable data. In situations where data isn't available, ensure proper error handling.
- **Data privacy and ethics:** Developers are responsible for determining what data they have a right to use with Chainlink Functions and ensuring that they use that data ethically. Developers must ensure that their Chainlink Functions code does not expose their private information or the private information of users without proper consent. Do not use data that you are not authorized to access. Your Chainlink Functions code and your application must ensure that private or sensitive information remains secure.
### Code
- **Code quality and reliability:** Developers must execute code on Chainlink Functions only if the code meets the quality and reliability requirements for their use case and application.
- **Code and application audits:** Developers are responsible for auditing their code and applications before deploying to production. You must determine the quality of any audits and ensure that they meet the requirements for your application and any code that runs on Chainlink Functions.
- **Code dependencies and imports:** Developers are responsible for ensuring the quality, reliability, and security of any dependencies or imported packages that they use with Chainlink Functions. Review and audit these dependencies and packages.
### Secrets
- **Self-hosted secrets**: Developers are responsible for securing self-hosted secrets, monitoring unauthorized access, auditing permissions, and ensuring that secrets are available for retrieval by Chainlink Functions when executing code.
- **Secrets best practices**: For all types of secrets used with Chainlink Functions, developers must follow common best practices for managing secrets for applications. Developers are responsible for selecting, setting expiration time, monitoring, and rotating secrets to ensure the security of their applications and Chainlink Functions code.
### Subscriptions
- **Subscription owner wallet management:** Developers must ensure the security of any wallets that own Chainlink Functions subscriptions or wallets that secure funds for subscriptions.
- **Subscription balances:** Subscription owners are responsible for maintaining the Chainlink Function balance that is necessary to fund Chainlink Functions requests and computation. Monitor your subscription balance and implement the necessary processes to fund your subscription balance at a level that meets your application's requirements.
## Node Operator responsibilities
High-quality node operators participate in the Functions DONs using a configuration specified in the Chainlink software. As participants in these deployments, Node Operators are responsible for the following components of Chainlink Functions:
- Ensuring the proper configuration, maintenance, and monitoring of nodes participating in the Chainlink Functions DON.
- Storing encrypted secrets that developers provide using threshold encryption.
- Ensuring that transactions execute onchain in a timely manner and apply gas bumping when necessary.
- Selecting and properly employing blockchain clients to connect to supported blockchain networks.
- Maintaining continuous uptime and active participation in OCR consensus.
- Employ defensive measures to prevent unauthorized access to their Chainlink node deployments.
- Ensure that Chainlink node deployments are running the latest software versions.
- Responding to important communication from Chainlink Labs or from other node operators in a timely manner.
---
# Supported Networks
Source: https://docs.chain.link/chainlink-functions/supported-networks
{/* Static anchor points for link checker */}
Read the [LINK Token Contracts](/resources/link-token-contracts) page to learn where to get testnet LINK and ETH.
To use Chainlink Functions on certain networks, you may need to conduct token transfers. You can transfer tokens by using [Chainlink CCIP](/ccip/tutorials/evm/transfer-tokens-from-contract), [Transporter](https://www.transporter.io/) or third-party applications such as [XSwap](https://xswap.link/).
## Arbitrum
### Arbitrum Mainnet
| Item | Value |
| ---------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Functions router | |
| | fun-arbitrum-mainnet-1 / 0x66756e2d617262697472756d2d6d61696e6e65742d3100000000000000000000 |
| Encrypted secrets upload endpoints |
|
| Billing Item | Value |
| ------------------------------------------------ | ------------- |
| Premium fees (converted to LINK at request time) | 320 cents USD |
| Request threshold (withdrawing funds) | 10 requests |
| Cancellation fees (withdrawing funds) | 2 LINK |
| Minimum balance for uploading encrypted secrets | 2 LINK |
---
# Return multiple responses and decode them in your smart contract
Source: https://docs.chain.link/chainlink-functions/tutorials/abi-decoding
In the [Using Imports with Functions](/chainlink-functions/tutorials/importing-packages) tutorial, we explored the fundamentals of module imports. This tutorial will teach you how to use the Ethers library [encode](https://docs.ethers.org/v6/api/abi/abi-coder/#AbiCoder-encode) function to perform ABI encoding of several responses. Then, you will use the [ABI specifications](https://docs.soliditylang.org/en/v0.8.24/abi-spec.html) in Solidity to decode the responses in your smart contract.
## Prerequisites
This tutorial assumes you have completed the [Using Imports with Functions](/chainlink-functions/tutorials/importing-packages) tutorial. Also,
check your subscription details (including the balance in LINK) in the [Chainlink Functions Subscription
Manager](https://functions.chain.link/). If your subscription runs out of LINK, follow the [Fund a
Subscription](/chainlink-functions/resources/subscriptions#fund-a-subscription) guide.
In this tutorial, you will use a different Chainlink Functions consumer contract, which shows how to use ABI decoding to decode the response received from Chainlink Functions:
1. [Open the FunctionsConsumerDecoder.sol contract](https://remix.ethereum.org/#url=https://docs.chain.link/samples/ChainlinkFunctions/FunctionsConsumerDecoder.sol) in Remix.
2. Compile the contract.
3. Open MetaMask and select the *Ethereum Sepolia* network.
4. In Remix under the **Deploy & Run Transactions** tab, select *Injected Provider - MetaMask* in the **Environment** list. Remix will use the MetaMask wallet to communicate with *Ethereum Sepolia*.
5. Under the **Deploy** section, fill in the router address for your specific blockchain. You can find this address on the [Supported Networks](/chainlink-functions/supported-networks) page. For *Ethereum Sepolia*, the router address is 0xb83E47C2bC239B3bf370bc41e1459A34b41238D0.
6. Click the **Deploy** button to deploy the contract. MetaMask prompts you to confirm the transaction. Check the transaction details to make sure you are deploying the contract to *Ethereum Sepolia*.
7. After you confirm the transaction, the contract address appears in the **Deployed Contracts** list. Copy the contract address.
8. Add your consumer contract address to your subscription on *Ethereum Sepolia*.
## Tutorial
This tutorial demonstrates using the [ethers](https://www.npmjs.com/package/ethers) library to interact with smart contract functions through a JSON RPC provider. It involves calling the [`latestRoundData`](/data-feeds/api-reference#latestrounddata), [`decimals`](/data-feeds/api-reference#decimals), and [`description`](/data-feeds/api-reference#description) functions of a price feed contract based on the `AggregatorV3Interface`.
After retrieving the necessary data, the guide shows how to use ABI encoding to encode these responses into a single hexadecimal string and then convert this string to a [Uint8Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array). This step ensures compliance with the [Chainlink Functions API requirements](/chainlink-functions/api-reference/javascript-source#data-encoding-functions), which specify that the source code must return a Uint8Array representing the bytes for on-chain use.
You can locate the scripts used in this tutorial in the [*examples/12-abi-encoding* directory](https://github.com/smartcontractkit/smart-contract-examples/tree/main/functions-examples/examples/12-abi-encoding).
To run the example:
1. Make sure you have correctly set up your environment first. If you haven't already, follow the [Set up your environment](/chainlink-functions/tutorials/importing-packages#set-up-your-environment) section of the [Using Imports with Functions](/chainlink-functions/tutorials/importing-packages) tutorial.
2. Open the file `request.js`, located in the [`12-abi-encoding`](https://github.com/smartcontractkit/smart-contract-examples/tree/main/functions-examples/examples/12-abi-encoding) folder.
3. Replace the consumer contract address and the subscription ID with your own values.
```javascript
const consumerAddress = "0x5fC6e53646CC53f0C3575fd2c71b5056c4823f5c" // REPLACE this with your Functions consumer address
const subscriptionId = 139 // REPLACE this with your subscription ID
```
4. Make a request:
```shell
node examples/12-abi-encoding/request.js
```
The script runs your function in a sandbox environment before making an onchain transaction:
```text
$ node examples/12-abi-encoding/request.js
secp256k1 unavailable, reverting to browser version
Start simulation...
Simulation result {
capturedTerminalOutput: 'Fetched BTC / USD price: dataFeedResponse.answer\n' +
'Updated at: 1712941559\n' +
'Decimals: 8\n' +
'Description: BTC / USD\n',
responseBytesHexstring: '0x0000000000000000000000000000000000000000000000000000063c3570cc8400000000000000000000000000000000000000000000000000000000661969f7000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000009425443202f205553440000000000000000000000000000000000000000000000'
}
✅ Decoded response to bytes: 0x0000000000000000000000000000000000000000000000000000063c3570cc8400000000000000000000000000000000000000000000000000000000661969f7000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000009425443202f205553440000000000000000000000000000000000000000000000
Estimate request costs...
Fulfillment cost estimated to 1.007671833192655 LINK
Make request...
✅ Functions request sent! Transaction hash 0x5618089ec9b5e662ec72c81241d78cb6daa135ecc3fa3a33032d910e3b47c2b1. Waiting for a response...
See your request in the explorer https://sepolia.etherscan.io/tx/0x5618089ec9b5e662ec72c81241d78cb6daa135ecc3fa3a33032d910e3b47c2b1
✅ Request 0xdf22fa28c81a3ea78f356334b6d28d969e953009fae8ece4fe544f2eb466419b successfully fulfilled. Cost is 0.282344694329387405 LINK.Complete response: {
requestId: '0xdf22fa28c81a3ea78f356334b6d28d969e953009fae8ece4fe544f2eb466419b',
subscriptionId: 2303,
totalCostInJuels: 282344694329387405n,
responseBytesHexstring: '0x0000000000000000000000000000000000000000000000000000063c3570cc8400000000000000000000000000000000000000000000000000000000661969f7000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000009425443202f205553440000000000000000000000000000000000000000000000',
errorString: '',
returnDataBytesHexstring: '0x',
fulfillmentCode: 0
}
✅ Raw response: 0x0000000000000000000000000000000000000000000000000000063c3570cc8400000000000000000000000000000000000000000000000000000000661969f7000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000009425443202f205553440000000000000000000000000000000000000000000000
✅ Fetched BTC / USD price: 6855664389252 (updatedAt: 1712941559) (decimals: 8) (description: BTC / USD)
```
The output of the example gives you the following information:
- Your request is first run on a sandbox environment to ensure it is correctly configured.
- The fulfillment costs are estimated before making the request.
- Your request was successfully sent to Chainlink Functions. The transaction in this example is `0x5618089ec9b5e662ec72c81241d78cb6daa135ecc3fa3a33032d910e3b47c2b1`, and the request ID is `0xdf22fa28c81a3ea78f356334b6d28d969e953009fae8ece4fe544f2eb466419b`.
- The DON successfully fulfilled your request. The total cost was: `0.282344694329387405 LINK`.
- The consumer contract received a response in hexadecimal string with a value of `0x0000000000000000000000000000000000000000000000000000063c3570cc8400000000000000000000000000000000000000000000000000000000661969f7000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000009425443202f205553440000000000000000000000000000000000000000000000`. This value is the ABI encoded response of the `latestRoundData`, `decimals`, and `description` of the *BTC / USD* price feed. This value is then decoded and stored in the consumer contract.
- The script calls the consumer contract to fetch the decoded values and then logs them to the console. The output is `Fetched BTC / USD price: 6855664389252 (updatedAt: 1712941559) (decimals: 8) (description: BTC / USD)`.
## Examine the code
### FunctionsConsumerDecoder.sol
This Solidity contract is similar to the [FunctionsConsumer.sol](https://remix.ethereum.org/#url=https://docs.chain.link/samples/ChainlinkFunctions/FunctionsConsumer.sol) contract used in the [Using Imports with Functions](/chainlink-functions/tutorials/importing-packages) tutorial. The main difference is the processing of the response in the `fulfillRequest` function:
- It uses Solidity `abi.decode` to decode the `response` to retrieve the `answer`, `updatedAt`, `decimals`, and `description`.
```solidity
(
uint256 answer,
uint256 updatedAt,
uint8 decimals,
string memory description
) = abi.decode(response, (uint256, uint256, uint8, string));
```
- Then stores the decoded values in the contract state.
```solidity
s_answer = answer;
s_updatedAt = updatedAt;
s_decimals = decimals;
s_description = description;
```
### JavaScript example
#### source.js
The Decentralized Oracle Network will run the [JavaScript code](https://github.com/smartcontractkit/smart-contract-examples/blob/main/functions-examples/examples/12-abi-encoding/source.js). The code is self-explanatory and has comments to help you understand all the steps.
The example `source.js` file is similar to the one used in the [Using Imports with Functions](/chainlink-functions/tutorials/importing-packages#sourcejs) tutorial. It uses a JSON RPC call to the [`latestRoundData`](/data-feeds/api-reference#latestrounddata), [`decimals`](/data-feeds/api-reference#decimals), and [`description`](/data-feeds/api-reference#description) functions of a [Chainlink Data Feed](/data-feeds). It then uses the `ethers` library to encode the response of these functions into a single hexadecimal string.
```javascript
const encoded = ethers.AbiCoder.defaultAbiCoder().encode(
["uint256", "uint256", "uint8", "string"],
[dataFeedResponse.answer, dataFeedResponse.updatedAt, decimals, description]
)
```
Finally, it uses the `ethers` library [`getBytes`](https://docs.ethers.org/v6/api/utils/#getBytes) to convert the hexadecimal string to a `Uint8Array`:
```javascript
return ethers.getBytes(encoded)
```
#### request.js
This explanation focuses on the [request.js](https://github.com/smartcontractkit/smart-contract-examples/blob/main/functions-examples/examples/12-abi-encoding/request.js) script and shows how to use the [Chainlink Functions NPM package](https://github.com/smartcontractkit/functions-toolkit) in your own JavaScript/TypeScript project to send requests to a DON. The code is self-explanatory and has comments to help you understand all the steps.
The script imports:
- [path](https://nodejs.org/docs/latest/api/path.html) and [fs](https://nodejs.org/api/fs.html): Used to read the [source file](https://github.com/smartcontractkit/smart-contract-examples/blob/main/functions-examples/examples/12-abi-encoding/source.js).
- [ethers](https://docs.ethers.org/v5/): Ethers.js library, enables the script to interact with the blockchain.
- `@chainlink/functions-toolkit`: Chainlink Functions NPM package. All its utilities are documented in the [NPM README](https://github.com/smartcontractkit/functions-toolkit/blob/main/README.md).
- `@chainlink/env-enc`: A tool for loading and storing encrypted environment variables. Read the [official documentation](https://www.npmjs.com/package/@chainlink/env-enc) to learn more.
- `../abi/functionsDecoder.json`: The abi of the contract your script will interact with. **Note**: The script was tested with this [FunctionsConsumerDecoder contract](https://remix.ethereum.org/#url=https://docs.chain.link/samples/ChainlinkFunctions/FunctionsConsumerDecoder.sol).
The script has two hardcoded values that you have to change using your own Functions consumer contract and subscription ID:
```javascript
const consumerAddress = "0x5fC6e53646CC53f0C3575fd2c71b5056c4823f5c" // REPLACE this with your Functions consumer address
const subscriptionId = 139 // REPLACE this with your subscription ID
```
The primary function that the script executes is `makeRequestSepolia`. This function consists of five main parts:
1. Definition of necessary identifiers:
- `routerAddress`: Chainlink Functions router address on Sepolia.
- `donId`: Identifier of the DON that will fulfill your requests on Sepolia.
- `explorerUrl`: Block explorer URL of the Sepolia testnet.
- `source`: The source code must be a string object. That's why we use `fs.readFileSync` to read `source.js` and then call `toString()` to get the content as a `string` object.
- `args`: During the execution of your function, These arguments are passed to the source code.
- `gasLimit`: Maximum gas that Chainlink Functions can use when transmitting the response to your contract.
- Initialization of ethers `signer` and `provider` objects. The signer is used to make transactions on the blockchain, and the provider reads data from the blockchain.
2. Simulating your request in a local sandbox environment:
- Use `simulateScript` from the Chainlink Functions NPM package.
- Read the `response` of the simulation. If successful, use the Functions NPM package `decodeResult` function and `ReturnType` enum to decode the response to the expected returned type (`ReturnType.bytes` in this example).
3. Estimating the costs:
- Initialize a `SubscriptionManager` from the Functions NPM package, then call the `estimateFunctionsRequestCost`.
- The response is returned in Juels (1 LINK = 10\*\*18 Juels). Use the `ethers.utils.formatEther` utility function to convert the output to LINK.
4. Making a Chainlink Functions request:
- Initialize your functions consumer contract using the contract address, abi, and ethers signer.
- Call the `sendRequest` function of your consumer contract.
5. Waiting for the response:
- Initialize a `ResponseListener` from the Functions NPM package and then call the `listenForResponseFromTransaction` function to wait for a response. By default, this function waits for five minutes.
- Upon reception of the response, use the Functions NPM package `decodeResult` function and `ReturnType` enum to decode the response to the expected returned type (`ReturnType.bytes` in this example).
6. Read the decoded response:
- 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)"]
// Encoding the data
const encodedData = abiCoder.encode(types, [complexData])
```
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
}
}
```
---
# Call Multiple Data Sources
Source: https://docs.chain.link/chainlink-functions/tutorials/api-multiple-calls
This tutorial shows you how make multiple API calls from your smart contract to a Decentralized Oracle Network. After [OCR](/chainlink-functions/resources/architecture) completes offchain computation and aggregation, the DON returns the asset price to your smart contract. This example returns the `BTC/USD` price.
This guide assumes that you know how to build HTTP requests and how to use secrets. Read the [API query parameters](/chainlink-functions/tutorials/api-query-parameters) and [API use secrets](/chainlink-functions/tutorials/api-use-secrets) guides before you follow the example in this document.
To build a decentralized asset price, send a request to the DON to fetch the price from many different API providers. Then, calculate the median price. The API providers in this example are:
- [CoinMarket](https://coinmarketcap.com/api/documentation/v1/)
- [CoinGecko](https://www.coingecko.com/en/api/documentation)
- [CoinPaprika](https://api.coinpaprika.com/)
## Tutorial
This tutorial is configured to get the median `BTC/USD` price from multiple data sources. For a detailed explanation of the code example, read the [Examine the code](#examine-the-code) section.
You can locate the scripts used in this tutorial in the [*examples/8-multiple-apis* directory](https://github.com/smartcontractkit/smart-contract-examples/tree/main/functions-examples/examples/8-multiple-apis).
1. Make sure your subscription has enough LINK to pay for your requests. Also, you must maintain a minimum balance to upload encrypted secrets to the DON (Read the [minimum balance for uploading encrypted secrets section](/chainlink-functions/resources/billing#minimum-balance-for-uploading-encrypted-secrets) to learn more). You can check your subscription details (including the balance in LINK) in the [Chainlink Functions Subscription Manager](/chainlink-functions/resources/subscriptions). If your subscription runs out of LINK, follow the [Fund a Subscription](/chainlink-functions/resources/subscriptions#fund-a-subscription) guide. This guide recommends maintaining at least 2 LINK within your subscription.
2. Get a free API key from [CoinMarketCap](https://coinmarketcap.com/api/) and note your API key.
3. Run `npx env-enc set` to add an encrypted `COINMARKETCAP_API_KEY` to your `.env.enc` file.
```shell
npx env-enc set
```
To run the example:
1. Open the file `request.js`, which is located in the `8-multiple-apis` folder.
2. Replace the consumer contract address and the subscription ID with your own values.
```javascript
const consumerAddress = "0x8dFf78B7EE3128D00E90611FBeD20A71397064D9" // REPLACE this with your Functions consumer address
const subscriptionId = 3 // REPLACE this with your subscription ID
```
3. Make a request:
```shell
node examples/8-multiple-apis/request.js
```
The script runs your function in a sandbox environment before making an onchain transaction:
```text
$ node examples/8-multiple-apis/request.js
secp256k1 unavailable, reverting to browser version
Start simulation...
Simulation result {
capturedTerminalOutput: 'Median Bitcoin price: 66822.81\n',
responseBytesHexstring: '0x000000000000000000000000000000000000000000000000000000000065f6a9'
}
✅ Decoded response to uint256: 6682281n
Estimate request costs...
Fulfillment cost estimated to 1.104471544715335 LINK
Make request...
Upload encrypted secret to gateways https://01.functions-gateway.testnet.chain.link/,https://02.functions-gateway.testnet.chain.link/. slotId 0. Expiration in minutes: 15
✅ Secrets uploaded properly to gateways https://01.functions-gateway.testnet.chain.link/,https://02.functions-gateway.testnet.chain.link/! Gateways response: { version: 1712949659, success: true }
✅ Functions request sent! Transaction hash 0x8defda7d48f91efa4f7bfa8e7d99f115a4e1d71882852ee6e91f438542d840ec. Waiting for a response...
See your request in the explorer https://sepolia.etherscan.io/tx/0x8defda7d48f91efa4f7bfa8e7d99f115a4e1d71882852ee6e91f438542d840ec
✅ Request 0xff18de309a7845ef99b042d008aa3c5e67c51e649b771cbaab7dd96fada66e27 successfully fulfilled. Cost is 0.25590956997723491 LINK.Complete response: {
requestId: '0xff18de309a7845ef99b042d008aa3c5e67c51e649b771cbaab7dd96fada66e27',
subscriptionId: 2303,
totalCostInJuels: 255909569977234910n,
responseBytesHexstring: '0x000000000000000000000000000000000000000000000000000000000065f6a9',
errorString: '',
returnDataBytesHexstring: '0x',
fulfillmentCode: 0
}
✅ Decoded response to uint256: 6682281n
```
The output of the example gives you the following information:
- Your request is first run on a sandbox environment to ensure it is correctly configured.
- The fulfillment costs are estimated before making the request.
- The encrypted secrets were uploaded to the secrets endpoint `https://01.functions-gateway.testnet.chain.link/user`.
- Your request was successfully sent to Chainlink Functions.
- The DON successfully fulfilled your request. The total cost was: `0.25590956997723491 LINK`.
- The consumer contract received a response in `bytes` with a value of `0x000000000000000000000000000000000000000000000000000000000065f6a9`. Decoding it offchain to `uint256` gives you a result: `6682281`. The median BTC price is 66822.81 USD.
## Examine the code
### FunctionsConsumerExample.sol
### JavaScript example
#### source.js
The Decentralized Oracle Network will run the [JavaScript code](https://github.com/smartcontractkit/smart-contract-examples/blob/main/functions-examples/examples/8-multiple-apis/source.js). The code is self-explanatory and has comments to help you understand all the steps.
This JavaScript source code uses [Functions.makeHttpRequest](/chainlink-functions/api-reference/javascript-source#http-requests) to make HTTP requests. The source code fetches the BTC/USD price from different data sources: `https://pro-api.coinmarketcap.com/v1/cryptocurrency/quotes/latest/`, `https://api.coingecko.com/api/v3/simple/price`, and `https://api.coinpaprika.com/v1/tickers/btc-bitcoin` and then calculate the median price. you can read the API docs of [CoinMarketCap](https://coinmarketcap.com/api/documentation/v1/), [CoinGecko](https://www.coingecko.com/en/api/documentation), and [CoinPaprika](https://api.coinpaprika.com/) for details.
To check the expected API responses, run these commands in your terminal:
- CoinMarketCap:
```bash
curl -X 'GET' \
'https://pro-api.coinmarketcap.com/v1/cryptocurrency/quotes/latest?id=1&convert=USD' \
-H 'accept: application/json' \
-H 'X-CMC_PRO_API_KEY: REPLACE_WITH_YOUR_API_KEY'
```
- CoinGecko:
```bash
curl -X 'GET' \
'https://api.coingecko.com/api/v3/simple/price?vs_currencies=USD&ids=bitcoin' \
-H 'accept: application/json'
```
- Coinpaprika:
```bash
curl -X 'GET' \
'https://api.coinpaprika.com/v1/tickers/btc-bitcoin' \
-H 'accept: application/json'
```
The prices are respectively located at:
- CoinMarketCap: `data,1,quote,USD,price`
- CoinGecko: `bitcoin,usd`
- Coinpaprika: `quotes,USD,price`
The main steps of the scripts are:
- Construct the HTTP objects `coinMarketCapRequest`, `coinGeckoRequest`, and `coinPaprikaRequest` using `Functions.makeHttpRequest`. The values for `coinMarketCapCoinId`, `coinGeckoCoinId`, and `coinPaprikaCoinId` are fetched from the `args`.
- Make the HTTP calls.
- Read the asset price from each response.
- Calculate the median of all the prices.
- Return the result as a [buffer](https://nodejs.org/api/buffer.html#buffer) using the `Functions.encodeUint256` helper function. Because solidity doesn't support decimals, multiply the result by `100` and round the result to the nearest integer. **Note**: Read this [article](https://www.freecodecamp.org/news/do-you-want-a-better-understanding-of-buffer-in-node-js-check-this-out-2e29de2968e8/) if you are new to Javascript Buffers and want to understand why they are important.
#### request.js
This explanation focuses on the [request.js](https://github.com/smartcontractkit/smart-contract-examples/blob/main/functions-examples/examples/8-multiple-apis/request.js) script and shows how to use the [Chainlink Functions NPM package](https://github.com/smartcontractkit/functions-toolkit) in your own JavaScript/TypeScript project to send requests to a DON. The code is self-explanatory and has comments to help you understand all the steps.
The script imports:
- [path](https://nodejs.org/docs/latest/api/path.html) and [fs](https://nodejs.org/api/fs.html) : Used to read the [source file](https://github.com/smartcontractkit/smart-contract-examples/blob/main/functions-examples/examples/8-multiple-apis/source.js).
- [ethers](https://docs.ethers.org/v5/): Ethers.js library, enables the script to interact with the blockchain.
- `@chainlink/functions-toolkit`: Chainlink Functions NPM package. All its utilities are documented in the [NPM README](https://github.com/smartcontractkit/functions-toolkit/blob/main/README.md).
- `@chainlink/env-enc`: A tool for loading and storing encrypted environment variables. Read the [official documentation](https://www.npmjs.com/package/@chainlink/env-enc) to learn more.
- `../abi/functionsClient.json`: The ABI of the contract your script will interact with. **Note**: The script was tested with this [FunctionsConsumerExample contract](https://remix.ethereum.org/#url=https://docs.chain.link/samples/ChainlinkFunctions/FunctionsConsumerExample.sol).
The script has two hardcoded values that you have to change using your own Functions consumer contract and subscription ID:
```javascript
const consumerAddress = "0x8dFf78B7EE3128D00E90611FBeD20A71397064D9" // REPLACE this with your Functions consumer address
const subscriptionId = 3 // REPLACE this with your subscription ID
```
The primary function that the script executes is `makeRequestSepolia`. This function can be broken into six main parts:
1. Definition of necessary identifiers:
- `routerAddress`: Chainlink Functions router address on Sepolia.
- `donId`: Identifier of the DON that will fulfill your requests on Sepolia.
- `gatewayUrls`: The secrets endpoint URL to which you will upload the encrypted secrets.
- `explorerUrl`: Block explorer URL of the Sepolia testnet.
- `source`: The source code must be a string object. That's why we use `fs.readFileSync` to read `source.js` and then call `toString()` to get the content as a `string` object.
- `args`: During the execution of your function, These arguments are passed to the source code. The `args` value is `["1", "bitcoin", "btc-bitcoin"]`. These arguments are BTC IDs at CoinMarketCap, CoinGecko, and Coinpaprika. You can adapt args to fetch other asset prices.
- `secrets`: The secrets object that will be encrypted.
- `slotIdNumber`: Slot ID at the DON where to upload the encrypted secrets.
- `expirationTimeMinutes`: Expiration time in minutes of the encrypted secrets.
- `gasLimit`: Maximum gas that Chainlink Functions can use when transmitting the response to your contract.
- Initialization of ethers `signer` and `provider` objects. The signer is used to make transactions on the blockchain, and the provider reads data from the blockchain.
2. Simulating your request in a local sandbox environment:
- Use `simulateScript` from the Chainlink Functions NPM package.
- Read the `response` of the simulation. If successful, use the Functions NPM package `decodeResult` function and `ReturnType` enum to decode the response to the expected returned type (`ReturnType.uint256` in this example).
3. Estimating the costs:
- Initialize a `SubscriptionManager` from the Functions NPM package, then call the `estimateFunctionsRequestCost` function.
- The response is returned in Juels (1 LINK = 10\*\*18 Juels). Use the `ethers.utils.formatEther` utility function to convert the output to LINK.
4. Encrypt the secrets, then upload the encrypted secrets to the DON. This is done in two steps:
- Initialize a `SecretsManager` instance from the Functions NPM package, then call the `encryptSecrets` function.
- Call the `uploadEncryptedSecretsToDON` function of the `SecretsManager` instance. This function returns an object containing a `success` boolean as long as `version`, the secret version on the DON storage. **Note**: When making the request, you must pass the slot ID and version to tell the DON where to fetch the encrypted secrets.
5. Making a Chainlink Functions request:
- Initialize your functions consumer contract using the contract address, abi, and ethers signer.
- Call the `sendRequest` function of your consumer contract.
6. Waiting for the response:
- Initialize a `ResponseListener` from the Functions NPM package and then call the `listenForResponseFromTransaction` function to wait for a response. By default, this function waits for five minutes.
- Upon reception of the response, use the Functions NPM package `decodeResult` function and `ReturnType` enum to decode the response to the expected returned type (`ReturnType.uint256` in this example).
---
# POST Data to an API
Source: https://docs.chain.link/chainlink-functions/tutorials/api-post-data
This tutorial shows you how to send a request to a Decentralized Oracle Network to call the [Countries information GraphQL API](https://trevorblades.github.io/countries/queries/continent). After [OCR](/chainlink-functions/resources/architecture) completes offchain computation and aggregation, it returns the name, capital, and currency for the specified country to your smart contract. Because the endpoint is a GraphQL API, write a function that sends a GraphQL query in a [POST HTTP method](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST).
## Tutorial
This tutorial is configured to get the country name, capital, and currency from [countries.trevorblades.com](https://countries.trevorblades.com/) in one request. For a detailed explanation of the code example, read the [Examine the code](#examine-the-code) section.
You can locate the scripts used in this tutorial in the [*examples/4-post-data* directory](https://github.com/smartcontractkit/smart-contract-examples/tree/main/functions-examples/examples/4-post-data).
To run the example:
1. Open the file `request.js`, which is located in the `4-post-data` folder.
2. Replace the consumer contract address and the subscription ID with your own values.
```javascript
const consumerAddress = "0x8dFf78B7EE3128D00E90611FBeD20A71397064D9" // REPLACE this with your Functions consumer address
const subscriptionId = 3 // REPLACE this with your subscription ID
```
3. Make a request:
```shell
node examples/4-post-data/request.js
```
The script runs your function in a sandbox environment before making an onchain transaction:
```text
$ node examples/4-post-data/request.js
secp256k1 unavailable, reverting to browser version
Start simulation...
Simulation result {
capturedTerminalOutput: 'Get name, capital and currency for country code: JP\n' +
'HTTP POST Request to https://countries.trevorblades.com/\n' +
'country response { country: { name: "Japan", capital: "Tokyo", currency: "JPY" } }\n',
responseBytesHexstring: '0x7b226e616d65223a224a6170616e222c226361706974616c223a22546f6b796f222c2263757272656e6379223a224a5059227d'
}
✅ Decoded response to string: {"name":"Japan","capital":"Tokyo","currency":"JPY"}
Estimate request costs...
Fulfillment cost estimated to 1.007671833192655 LINK
Make request...
✅ Functions request sent! Transaction hash 0x5a315eeebea90f4828d176906d13dd3133e8a8d9afa912b1f8c34e90e775d081. Waiting for a response...
See your request in the explorer https://sepolia.etherscan.io/tx/0x5a315eeebea90f4828d176906d13dd3133e8a8d9afa912b1f8c34e90e775d081
✅ Request 0xc760ee5ca5c73999ca9c4ce426b9d2d44eab4429d3110276e57c445537ad5ddd successfully fulfilled. Cost is 0.257726519296170771 LINK.Complete response: {
requestId: '0xc760ee5ca5c73999ca9c4ce426b9d2d44eab4429d3110276e57c445537ad5ddd',
subscriptionId: 2303,
totalCostInJuels: 257726519296170771n,
responseBytesHexstring: '0x7b226e616d65223a224a6170616e222c226361706974616c223a22546f6b796f222c2263757272656e6379223a224a5059227d',
errorString: '',
returnDataBytesHexstring: '0x',
fulfillmentCode: 0
}
✅ Decoded response to string: {"name":"Japan","capital":"Tokyo","currency":"JPY"}
```
The output of the example gives you the following information:
- Your request is first run on a sandbox environment to ensure it is correctly configured.
- The fulfillment costs are estimated before making the request.
- Your request was successfully sent to Chainlink Functions. The transaction in this example is [0x5a315eeebea90f4828d176906d13dd3133e8a8d9afa912b1f8c34e90e775d081](https://sepolia.etherscan.io/tx/0x5a315eeebea90f4828d176906d13dd3133e8a8d9afa912b1f8c34e90e775d081) and the request ID is `0xc760ee5ca5c73999ca9c4ce426b9d2d44eab4429d3110276e57c445537ad5ddd`.
- The DON successfully fulfilled your request. The total cost was: `0.257726519296170771 LINK`.
- The consumer contract received a response in `bytes` with a value of `0x7b226e616d65223a224a6170616e222c226361706974616c223a22546f6b796f222c2263757272656e6379223a224a5059227d`. Decoding it offchain to `string` gives you a result:
`{"name":"Japan","capital":"Tokyo","currency":"JPY"}`.
## Examine the code
### FunctionsConsumerExample.sol
### JavaScript example
#### source.js
The Decentralized Oracle Network will run the [JavaScript code](https://github.com/smartcontractkit/smart-contract-examples/blob/main/functions-examples/examples/4-post-data/source.js). The code is self-explanatory and has comments to help you understand all the steps.
This JavaScript source code uses [Functions.makeHttpRequest](/chainlink-functions/api-reference/javascript-source#http-requests) to make HTTP requests. To request the `JP` country information, the source code calls the `https://countries.trevorblades.com/` URL and provides the query data in the HTTP request body. If you read the [Functions.makeHttpRequest](/chainlink-functions/api-reference/javascript-source#http-requests) documentation, you see that you must provide the following parameters:
- url: `https://countries.trevorblades.com/`
- data (HTTP body):
```
{
query: `{\
country(code: "${countryCode}") { \
name \
capital \
currency \
} \
}`,
}
```
To check the expected API response:
- In your browser, open the countries GraphQL playground: `https://countries.trevorblades.com/`
- Write this query:
```
{
country(code: "JP") {
name
capital
currency
}
}
```
- Click on *play* to get the answer :
```json
{
"data": {
"country": {
"name": "Japan",
"capital": "Tokyo",
"currency": "JPY"
}
}
}
```
The main steps of the scripts are:
- Fetch the `countryCode` from `args`.
- Construct the HTTP object `countryRequest` using `Functions.makeHttpRequest`.
- Run the HTTP request.
- Read the country name, capital, and currency from the response.
- Construct a JSON object:
```javascript
const result = {
name: countryData.country.name,
capital: countryData.country.capital,
currency: countryData.country.currency,
}
```
- Convert the JSON object to a JSON string using `JSON.stringify(result)`. This step is mandatory before encoding `string` to `bytes`.
- Return the result as a [buffer](https://nodejs.org/api/buffer.html#buffer) using the `Functions.string` helper function. **Note**: Read this [article](https://www.freecodecamp.org/news/do-you-want-a-better-understanding-of-buffer-in-node-js-check-this-out-2e29de2968e8/) if you are new to Javascript Buffers and want to understand why they are important.
#### request.js
This explanation focuses on the [request.js](https://github.com/smartcontractkit/smart-contract-examples/blob/main/functions-examples/examples/4-post-data/request.js) script and shows how to use the [Chainlink Functions NPM package](https://github.com/smartcontractkit/functions-toolkit) in your own JavaScript/TypeScript project to send requests to a DON. The code is self-explanatory and has comments to help you understand all the steps.
The script imports:
- [path](https://nodejs.org/docs/latest/api/path.html) and [fs](https://nodejs.org/api/fs.html) : Used to read the [source file](https://github.com/smartcontractkit/smart-contract-examples/blob/main/functions-examples/examples/4-post-data/source.js).
- [ethers](https://docs.ethers.org/v5/): Ethers.js library, enables the script to interact with the blockchain.
- `@chainlink/functions-toolkit`: Chainlink Functions NPM package. All its utilities are documented in the [NPM README](https://github.com/smartcontractkit/functions-toolkit/blob/main/README.md).
- `@chainlink/env-enc`: A tool for loading and storing encrypted environment variables. Read the [official documentation](https://www.npmjs.com/package/@chainlink/env-enc) to learn more.
- `../abi/functionsClient.json`: The abi of the contract your script will interact with. **Note**: The script was tested with this [FunctionsConsumerExample contract](https://remix.ethereum.org/#url=https://docs.chain.link/samples/ChainlinkFunctions/FunctionsConsumerExample.sol).
The script has two hardcoded values that you have to change using your own Functions consumer contract and subscription ID:
```javascript
const consumerAddress = "0x8dFf78B7EE3128D00E90611FBeD20A71397064D9" // REPLACE this with your Functions consumer address
const subscriptionId = 3 // REPLACE this with your subscription ID
```
The primary function that the script executes is `makeRequestSepolia`. This function consists of five main parts:
1. Definition of necessary identifiers:
- `routerAddress`: Chainlink Functions router address on Sepolia.
- `donId`: Identifier of the DON that will fulfill your requests on Sepolia.
- `explorerUrl`: Block explorer URL of the Sepolia testnet.
- `source`: The source code must be a string object. That's why we use `fs.readFileSync` to read `source.js` and then call `toString()` to get the content as a `string` object.
- `args`: During the execution of your function, These arguments are passed to the source code. The `args` value is `["JP"]`, which fetches country data for Japan.
- `gasLimit`: Maximum gas that Chainlink Functions can use when transmitting the response to your contract.
- Initialization of ethers `signer` and `provider` objects. The signer is used to make transactions on the blockchain, and the provider reads data from the blockchain.
2. Simulating your request in a local sandbox environment:
- Use `simulateScript` from the Chainlink Functions NPM package.
- Read the `response` of the simulation. If successful, use the Functions NPM package `decodeResult` function and `ReturnType` enum to decode the response to the expected returned type (`ReturnType.string` in this example).
3. Estimating the costs:
- Initialize a `SubscriptionManager` from the Functions NPM package, then call the `estimateFunctionsRequestCost`.
- The response is returned in Juels (1 LINK = 10\*\*18 Juels). Use the `ethers.utils.formatEther` utility function to convert the output to LINK.
4. Making a Chainlink Functions request:
- Initialize your functions consumer contract using the contract address, abi, and ethers signer.
- Call the `sendRequest` function of your consumer contract.
5. Waiting for the response:
- Initialize a `ResponseListener` from the Functions NPM package and then call the `listenForResponseFromTransaction` function to wait for a response. By default, this function waits for five minutes.
- Upon reception of the response, use the Functions NPM package `decodeResult` function and `ReturnType` enum to decode the response to the expected returned type (`ReturnType.string` in this example).
---
# Call an API with HTTP Query Parameters
Source: https://docs.chain.link/chainlink-functions/tutorials/api-query-parameters
This tutorial shows you how to send a request to a Decentralized Oracle Network to call the [Cryptocompare GET /data/pricemultifull API](https://min-api.cryptocompare.com/documentation?key=Price\&cat=multipleSymbolsFullPriceEndpoint). After [OCR](/chainlink-functions/resources/architecture) completes offchain computation and aggregation, it returns the asset price for ETH/USD to your smart contract. This guide also shows you how to configure HTTP query parameters to request different asset prices.
## Tutorial
This tutorial is configured to get the `ETH/USD` price. For a detailed explanation of the code example, read the [Examine the code](#examine-the-code) section.
You can locate the scripts used in this tutorial in the [*examples/2-call-api* directory](https://github.com/smartcontractkit/smart-contract-examples/tree/main/functions-examples/examples/2-call-api).
To run the example:
1. Open the file `request.js`, which is located in the `2-call-api` folder.
2. Replace the consumer contract address and the subscription ID with your own values.
```javascript
const consumerAddress = "0x8dFf78B7EE3128D00E90611FBeD20A71397064D9" // REPLACE this with your Functions consumer address
const subscriptionId = 3 // REPLACE this with your subscription ID
```
3. Make a request:
```shell
node examples/2-call-api/request.js
```
The script runs your function in a sandbox environment before making an onchain transaction:
```text
$ node examples/2-call-api/request.js
secp256k1 unavailable, reverting to browser version
Start simulation...
Simulation result {
capturedTerminalOutput: 'HTTP GET Request to https://min-api.cryptocompare.com/data/pricemultifull?fsyms=ETH&tsyms=USD\n' +
'ETH price is: 3420.54 USD\n',
responseBytesHexstring: '0x0000000000000000000000000000000000000000000000000000000000053826'
}
✅ Decoded response to uint256: 342054n
Estimate request costs...
Fulfillment cost estimated to 1.004325887213695 LINK
Make request...
✅ Functions request sent! Transaction hash 0xbbe473ccc6593b6f3baf30fd66b2329b05a32fe0321a319d09142f4b9ba4547c. Waiting for a response...
See your request in the explorer https://sepolia.etherscan.io/tx/0xbbe473ccc6593b6f3baf30fd66b2329b05a32fe0321a319d09142f4b9ba4547c
✅ Request 0xe55201188012e3ec198427937f7897729999ab7b287207ff8f0c157a9662e5f0 successfully fulfilled. Cost is 0.249819373001796045 LINK.Complete response: {
requestId: '0xe55201188012e3ec198427937f7897729999ab7b287207ff8f0c157a9662e5f0',
subscriptionId: 2303,
totalCostInJuels: 249819373001796045n,
responseBytesHexstring: '0x0000000000000000000000000000000000000000000000000000000000053892',
errorString: '',
returnDataBytesHexstring: '0x',
fulfillmentCode: 0
}
✅ Decoded response to uint256: 342162n
```
The output of the example gives you the following information:
- Your request is first run on a sandbox environment to ensure it is correctly configured.
- The fulfillment costs are estimated before making the request.
- Your request was successfully sent to Chainlink Functions. The transaction in this example is [0xbbe473ccc6593b6f3baf30fd66b2329b05a32fe0321a319d09142f4b9ba4547c](https://sepolia.etherscan.io/tx/0xbbe473ccc6593b6f3baf30fd66b2329b05a32fe0321a319d09142f4b9ba4547c) and the request ID is `0xe55201188012e3ec198427937f7897729999ab7b287207ff8f0c157a9662e5f0`.
- The DON successfully fulfilled your request. The total cost was: `0.249819373001796045 LINK`.
- The consumer contract received a response in `bytes` with a value of `0x0000000000000000000000000000000000000000000000000000000000053892`. Decoding it offchain to `uint256` gives you a result: `342162`.
## Examine the code
### FunctionsConsumerExample.sol
### JavaScript example
#### source.js
The Decentralized Oracle Network will run the [JavaScript code](https://github.com/smartcontractkit/smart-contract-examples/blob/main/functions-examples/examples/2-call-api/source.js). The code is self-explanatory and has comments to help you understand all the steps.
This JavaScript source code uses [Functions.makeHttpRequest](/chainlink-functions/api-reference/javascript-source#http-requests) to make HTTP requests. To request the `ETH/USD` price, the source code calls the `https://min-api.cryptocompare.com/data/pricemultifull?fsyms=ETH&tsyms=USD` URL. If you read the [Functions.makeHttpRequest](/chainlink-functions/api-reference/javascript-source#http-requests) documentation, you see that you must provide the following parameters:
- `url`: `https://min-api.cryptocompare.com/data/pricemultifull`
- `params`: The query parameters object:
```
{
fsyms: fromSymbol,
tsyms: toSymbol
}
```
To check the expected API response, you can directly paste the following URL in your browser `https://min-api.cryptocompare.com/data/pricemultifull?fsyms=ETH&tsyms=USD` or run the `curl` command in your terminal:
```bash
curl -X 'GET' \
'https://min-api.cryptocompare.com/data/pricemultifull?fsyms=ETH&tsyms=USD' \
-H 'accept: application/json'
```
The response should be similar to the following example:
```json
{
"RAW": {
"ETH": {
"USD": {
"TYPE": "5",
"MARKET": "CCCAGG",
"FROMSYMBOL": "ETH",
"TOSYMBOL": "USD",
"FLAGS": "2049",
"PRICE": 2867.04,
"LASTUPDATE": 1650896942,
"MEDIAN": 2866.2,
"LASTVOLUME": 0.16533939,
"LASTVOLUMETO": 474.375243849,
"LASTTRADEID": "1072154517",
"VOLUMEDAY": 195241.78281014622,
"VOLUMEDAYTO": 556240560.4621655,
"VOLUME24HOUR": 236248.94641103,
...
}
```
The price is located at `RAW,ETH,USD,PRICE`.
The main steps of the scripts are:
- Fetch `fromSymbol` and `toSymbol` from `args`.
- Construct the HTTP object `cryptoCompareRequest` using `Functions.makeHttpRequest`.
- Make the HTTP call.
- Read the asset price from the response.
- Return the result as a [buffer](https://nodejs.org/api/buffer.html#buffer) using the `Functions.encodeUint256` helper function. Because solidity doesn't support decimals, multiply the result by `100` and round the result to the nearest integer. **Note**: Read this [article](https://www.freecodecamp.org/news/do-you-want-a-better-understanding-of-buffer-in-node-js-check-this-out-2e29de2968e8/) if you are new to Javascript Buffers and want to understand why they are important.
#### request.js
This explanation focuses on the [request.js](https://github.com/smartcontractkit/smart-contract-examples/blob/main/functions-examples/examples/2-call-api/request.js) script and shows how to use the [Chainlink Functions NPM package](https://github.com/smartcontractkit/functions-toolkit) in your own JavaScript/TypeScript project to send requests to a DON. The code is self-explanatory and has comments to help you understand all the steps.
The script imports:
- [path](https://nodejs.org/docs/latest/api/path.html) and [fs](https://nodejs.org/api/fs.html) : Used to read the [source file](https://github.com/smartcontractkit/smart-contract-examples/blob/main/functions-examples/examples/2-call-api/source.js).
- [ethers](https://docs.ethers.org/v5/): Ethers.js library, enables the script to interact with the blockchain.
- `@chainlink/functions-toolkit`: Chainlink Functions NPM package. All its utilities are documented in the [NPM README](https://github.com/smartcontractkit/functions-toolkit/blob/main/README.md).
- `@chainlink/env-enc`: A tool for loading and storing encrypted environment variables. Read the [official documentation](https://www.npmjs.com/package/@chainlink/env-enc) to learn more.
- `../abi/functionsClient.json`: The abi of the contract your script will interact with. **Note**: The script was tested with this [FunctionsConsumerExample contract](https://remix.ethereum.org/#url=https://docs.chain.link/samples/ChainlinkFunctions/FunctionsConsumerExample.sol).
The script has two hardcoded values that you have to change using your own Functions consumer contract and subscription ID:
```javascript
const consumerAddress = "0x8dFf78B7EE3128D00E90611FBeD20A71397064D9" // REPLACE this with your Functions consumer address
const subscriptionId = 3 // REPLACE this with your subscription ID
```
The primary function that the script executes is `makeRequestSepolia`. This function consists of five main parts:
1. Definition of necessary identifiers:
- `routerAddress`: Chainlink Functions router address on Sepolia.
- `donId`: Identifier of the DON that will fulfill your requests on Sepolia.
- `explorerUrl`: Block explorer URL of the Sepolia testnet.
- `source`: The source code must be a string object. That's why we use `fs.readFileSync` to read `source.js` and then call `toString()` to get the content as a `string` object.
- `args`: During the execution of your function, These arguments are passed to the source code. The `args` value is `["ETH", "USD"]`, which fetches the current `ETH/USD` price. You can adapt `args` to fetch another asset price. See the [CryptoCompare API docs](https://min-api.cryptocompare.com/documentation?key=Price\&cat=multipleSymbolsFullPriceEndpoint) to get the list of supported symbols.
- `gasLimit`: Maximum gas that Chainlink Functions can use when transmitting the response to your contract.
- Initialization of ethers `signer` and `provider` objects. The signer is used to make transactions on the blockchain, and the provider reads data from the blockchain.
2. Simulating your request in a local sandbox environment:
- Use `simulateScript` from the Chainlink Functions NPM package.
- Read the `response` of the simulation. If successful, use the Functions NPM package `decodeResult` function and `ReturnType` enum to decode the response to the expected returned type (`ReturnType.uint256` in this example).
3. Estimating the costs:
- Initialize a `SubscriptionManager` from the Functions NPM package, then call the `estimateFunctionsRequestCost`.
- The response is returned in Juels (1 LINK = 10\*\*18 Juels). Use the `ethers.utils.formatEther` utility function to convert the output to LINK.
4. Making a Chainlink Functions request:
- Initialize your functions consumer contract using the contract address, abi, and ethers signer.
- Call the `sendRequest` function of your consumer contract.
5. Waiting for the response:
- Initialize a `ResponseListener` from the Functions NPM package and then call the `listenForResponseFromTransaction` function to wait for a response. By default, this function waits for five minutes.
- Upon reception of the response, use the Functions NPM package `decodeResult` function and `ReturnType` enum to decode the response to the expected returned type (`ReturnType.uint256` in this example).
---
# Using User-hosted (gist) Secrets in Requests
Source: https://docs.chain.link/chainlink-functions/tutorials/api-use-secrets-gist
This tutorial shows you how to send a request to a Decentralized Oracle Network to call the [Coinmarketcap API](https://coinmarketcap.com/api/documentation/v1/). After [OCR](/chainlink-functions/resources/architecture) completes offchain computation and aggregation, it returns the `BTC/USD` asset price to your smart contract. Because the API requires you to provide an API key, this guide will also show you how to encrypt, sign your API key, and share the encrypted secret offchain with a Decentralized Oracle Network (DON).
The encrypted secrets are never stored onchain. This tutorial uses the threshold encryption feature. The encrypted secrets are stored by the user as [gists](https://docs.github.com/en/get-started/writing-on-github/editing-and-sharing-content-with-gists/creating-gists). Read the [Secrets Management page](/chainlink-functions/resources/secrets) to learn more.
Read the [Using Secrets in Requests](/chainlink-functions/tutorials/api-use-secrets) tutorial before you follow the steps in this example. This tutorial uses the same example but with a slightly different process:
1. Instead of uploading the encrypted secrets to the DON, you will host your encrypted secrets as gist.
2. Encrypt the gist URL.
3. Include the encrypted gist URL in your Chainlink Functions request.
## Tutorial
This tutorial is configured to get the `BTC/USD` price with a request that requires API keys. For a detailed explanation of the code example, read the [Examine the code](#examine-the-code) section.
You can locate the scripts used in this tutorial in the [*examples/6-use-secrets-gist* directory](https://github.com/smartcontractkit/smart-contract-examples/tree/main/functions-examples/examples/6-use-secrets-gist).
1. Get a free API key from [CoinMarketCap](https://coinmarketcap.com/api/) and note your API key.
2. The [request.js](https://github.com/smartcontractkit/smart-contract-examples/blob/main/functions-examples/examples/6-use-secrets-gist/request.js) example stores encrypted secrets as [gists](https://docs.github.com/en/get-started/writing-on-github/editing-and-sharing-content-with-gists/creating-gists) to share them offchain with the Decentralized Oracle Network. To allow the `request.js` script to write gists on your behalf, create a [github fine-grained personal access token](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token#creating-a-fine-grained-personal-access-token).
1. Visit [Github tokens settings page](https://github.com/settings/tokens?type=beta).
2. Click on *Generate new token*.
3. Provide a name to your token and define the expiration date.
4. Under `Account permissions`, enable *Read and write* for Gists. **Note**: Do not enable additional settings.
5. Click on *Generate token* and copy your fine-grained personal access token.
3. Run `npx env-enc set` to add an encrypted `GITHUB_API_TOKEN` and `COINMARKETCAP_API_KEY` to your `.env.enc` file.
```shell
npx env-enc set
```
To run the example:
1. Open the file `request.js`, which is located in the `6-use-secrets-gist` folder.
2. Replace the consumer contract address and the subscription ID with your own values.
```javascript
const consumerAddress = "0x8dFf78B7EE3128D00E90611FBeD20A71397064D9" // REPLACE this with your Functions consumer address
const subscriptionId = 3 // REPLACE this with your subscription ID
```
3. Make a request:
```shell
node examples/6-use-secrets-gist/request.js
```
The script runs your function in a sandbox environment before making an onchain transaction:
```text
$ node examples/6-use-secrets-gist/request.js
secp256k1 unavailable, reverting to browser version
Start simulation...
Simulation result {
capturedTerminalOutput: 'Price: 66918.25 USD\n',
responseBytesHexstring: '0x0000000000000000000000000000000000000000000000000000000000661bf1'
}
✅ Decoded response to uint256: 6691825n
Estimate request costs...
Fulfillment cost estimated to 1.104471544715335 LINK
Make request...
Creating gist...
✅Gist created https://gist.github.com/thedriftofwords/f00db83b79df7e064253a3f396aee1f7/raw . Encrypt the URLs..
✅ Functions request sent! Transaction hash 0xe5db77b3994e0c30934dbac779608af0b08eb9ddf57fb121c0f481a95ea9b579. Waiting for a response...
See your request in the explorer https://sepolia.etherscan.io/tx/0xe5db77b3994e0c30934dbac779608af0b08eb9ddf57fb121c0f481a95ea9b579
✅ Request 0x37f860fba46af84b84f5ce48efbb7c6ebbfb2ecde5063621f695bbd1c2547975 successfully fulfilled. Cost is 0.237283011969506455 LINK.Complete response: {
requestId: '0x37f860fba46af84b84f5ce48efbb7c6ebbfb2ecde5063621f695bbd1c2547975',
subscriptionId: 2303,
totalCostInJuels: 237283011969506455n,
responseBytesHexstring: '0x0000000000000000000000000000000000000000000000000000000000661bf1',
errorString: '',
returnDataBytesHexstring: '0x',
fulfillmentCode: 0
}
✅ Decoded response to uint256: 6691825n
Delete gistUrl https://gist.github.com/thedriftofwords/f00db83b79df7e064253a3f396aee1f7/raw
✅ Gist https://gist.github.com/thedriftofwords/f00db83b79df7e064253a3f396aee1f7/raw deleted
```
The output of the example gives you the following information:
- Your request is first run on a sandbox environment to ensure it is correctly configured.
- The fulfillment costs are estimated before making the request.
- A gist `https://gist.github.com/thedriftofwords/f00db83b79df7e064253a3f396aee1f7/raw` containing the encrypted secrets was created .
- The gist URL is encrypted before sending it in the request.
- Your request was successfully sent to Chainlink Functions. The transaction in this example is [0xe5db77b3994e0c30934dbac779608af0b08eb9ddf57fb121c0f481a95ea9b579](https://sepolia.etherscan.io/tx/0xe5db77b3994e0c30934dbac779608af0b08eb9ddf57fb121c0f481a95ea9b579) and the request ID is `0x37f860fba46af84b84f5ce48efbb7c6ebbfb2ecde5063621f695bbd1c2547975`.
- The DON successfully fulfilled your request. The total cost was: `0.237283011969506455 LINK`.
- The consumer contract received a response in `bytes` with a value of `0x0000000000000000000000000000000000000000000000000000000000661bf1`. Decoding it offchain to `uint256` gives you a result: `6691825`.
- After the request is fulfilled, the gist `https://gist.github.com/thedriftofwords/f00db83b79df7e064253a3f396aee1f7/raw` is deleted.
## Examine the code
### FunctionsConsumerExample.sol
### JavaScript example
#### source.js
The JavaScript code is similar to the [Using Secrets in Requests](/chainlink-functions/tutorials/api-use-secrets) tutorial.
#### request.js
This explanation focuses on the [request.js](https://github.com/smartcontractkit/smart-contract-examples/blob/main/functions-examples/examples/6-use-secrets-gist/request.js) script and shows how to use the [Chainlink Functions NPM package](https://github.com/smartcontractkit/functions-toolkit) in your own JavaScript/TypeScript project to send requests to a DON. The code is self-explanatory and has comments to help you understand all the steps.
The script imports:
- [path](https://nodejs.org/docs/latest/api/path.html) and [fs](https://nodejs.org/api/fs.html) : Used to read the [source file](https://github.com/smartcontractkit/smart-contract-examples/blob/main/functions-examples/examples/6-use-secrets-gist/source.js).
- [ethers](https://docs.ethers.org/v5/): Ethers.js library, enables the script to interact with the blockchain.
- `@chainlink/functions-toolkit`: Chainlink Functions NPM package. All its utilities are documented in the [NPM README](https://github.com/smartcontractkit/functions-toolkit/blob/main/README.md).
- `@chainlink/env-enc`: A tool for loading and storing encrypted environment variables. Read the [official documentation](https://www.npmjs.com/package/@chainlink/env-enc) to learn more.
- `../abi/functionsClient.json`: The abi of the contract your script will interact with. **Note**: The script was tested with this [FunctionsConsumerExample contract](https://remix.ethereum.org/#url=https://docs.chain.link/samples/ChainlinkFunctions/FunctionsConsumerExample.sol).
The script has two hardcoded values that you have to change using your own Functions consumer contract and subscription ID:
```javascript
const consumerAddress = "0x8dFf78B7EE3128D00E90611FBeD20A71397064D9" // REPLACE this with your Functions consumer address
const subscriptionId = 3 // REPLACE this with your subscription ID
```
The primary function that the script executes is `makeRequestSepolia`. This function can be broken into six main parts:
1. Definition of necessary identifiers:
- `routerAddress`: Chainlink Functions router address on the Sepolia testnet.
- `donId`: Identifier of the DON that will fulfill your requests on the Sepolia testnet.
- `explorerUrl`: Block explorer url of the Sepolia testnet.
- `source`: The source code must be a string object. That's why we use `fs.readFileSync` to read `source.js` and then call `toString()` to get the content as a `string` object.
- `args`: During the execution of your function, These arguments are passed to the source code. The `args` value is `["1", "USD"]`, which fetches the BTC/USD price.
- `secrets`: The secrets object that will be encrypted.
- `gasLimit`: Maximum gas that Chainlink Functions can use when transmitting the response to your contract.
- Initialization of ethers `signer` and `provider` objects. The signer is used to make transactions on the blockchain, and the provider reads data from the blockchain.
2. Simulating your request in a local sandbox environment:
- Use `simulateScript` from the Chainlink Functions NPM package.
- Read the `response` of the simulation. If successful, use the Functions NPM package `decodeResult` function and `ReturnType` enum to decode the response to the expected returned type (`ReturnType.uint256` in this example).
3. Estimating the costs:
- Initialize a `SubscriptionManager` from the Functions NPM package, then call the `estimateFunctionsRequestCost` function.
- The response is returned in Juels (1 LINK = 10\*\*18 Juels). Use the `ethers.utils.formatEther` utility function to convert the output to LINK.
4. Encrypt the secrets, then create a gist containing the encrypted secrets object. This is done in two steps:
- Initialize a `SecretsManager` instance from the Functions NPM package, then call the `encryptSecrets` function.
- Call the `createGist` utility function from the Functions NPM package to create a gist.
- Call the `encryptedSecretsUrls` function of the `SecretsManager` instance. This function encrypts the gist URL. **Note**: The encrypted URL will be sent to the DON when making a request.
5. Making a Chainlink Functions request:
- Initialize your functions consumer contract using the contract address, abi, and ethers signer.
- Call the `sendRequest` function of your consumer contract.
6. Waiting for the response:
- Initialize a `ResponseListener` from the Functions NPM package and then call the `listenForResponseFromTransaction` function to wait for a response. By default, this function waits for five minutes.
- Upon reception of the response, use the Functions NPM package `decodeResult` function and `ReturnType` enum to decode the response to the expected returned type (`ReturnType.uint256` in this example).
- Call the `deleteGist` utility function from the Functions NPM package to delete the gist.
---
# Using User-hosted Secrets in Requests
Source: https://docs.chain.link/chainlink-functions/tutorials/api-use-secrets-offchain
This tutorial shows you how to send a request to a Decentralized Oracle Network to call the [Coinmarketcap API](https://coinmarketcap.com/api/documentation/v1/). After [OCR](/chainlink-functions/resources/architecture) completes offchain computation and aggregation, it returns the `BTC/USD` asset price to your smart contract. Because the API requires you to provide an API key, this guide will also show you how to encrypt, sign your API key, and share the encrypted secret offchain with a Decentralized Oracle Network (DON).
The encrypted secrets are never stored onchain. This tutorial uses the threshold decryption feature. This tutorial shows you how to share encrypted secrets offchain with a Decentralized Oracle Network (DON) using a storage platform such as AWS S3, Google Drive, IPFS, or any other service where the DON can fetch secrets via HTTP. Read the [Secrets Management page](/chainlink-functions/resources/secrets) to learn more.
Read the [Using User-hosted (gist) Secrets in Requests](/chainlink-functions/tutorials/api-use-secrets-gist) tutorial before you follow the steps in this example. This tutorial uses the same example but with a slightly different process:
1. Instead of relying on storing the encrypted secrets on gist, you will host your encrypted secrets on AWS S3.
2. Include the encrypted secrets in an `offchain-secrets.json` file.
3. Host the secrets file offchain (AWS S3).
4. Encrypt the S3 HTTPs URL .
5. Include the encrypted URL in your Chainlink Functions request.
## Tutorial
This tutorial is configured to get the `BTC/USD` price with a request that requires API keys. For a detailed explanation of the code example, read the [Examine the code](#examine-the-code) section.
You can locate the scripts used in this tutorial in the [*examples/7-use-secrets-url* directory](https://github.com/smartcontractkit/smart-contract-examples/tree/main/functions-examples/examples/7-use-secrets-url).
1. Get a free API key from [CoinMarketCap](https://coinmarketcap.com/api/).
2. Run `npx env-enc set` to add an encrypted `COINMARKETCAP_API_KEY` to your `.env.enc` file.
```shell
npx env-enc set
```
3. Prepare the store for your encrypted secrets file.
1. Create a [AWS free tier account](https://aws.amazon.com/free/).
2. Follow [these steps](https://docs.aws.amazon.com/AmazonS3/latest/userguide/creating-bucket.html) to create a AWS S3 bucket. Choose a name for your bucket, set *ACLs enabled*, and turn off *Block all public access*.
### Build Offchain Secrets
Before you make a request, prepare the secrets file and host it offchain:
1. Encrypt the secrets and store them in the `offchain-secrets.json` file using the `gen-offchain-secrets` script of the `7-use-secrets-url` folder.
```bash
node examples/7-use-secrets-url/gen-offchain-secrets.js
```
Example:
```text
$ node examples/7-use-secrets-url/gen-offchain-secrets.js
secp256k1 unavailable, reverting to browser version
Encrypted secrets object written to /functions-examples/offchain-secrets.json
```
2. Follow these [steps](https://docs.aws.amazon.com/AmazonS3/latest/userguide/uploading-an-object-bucket.html) to upload the file `offchain-secrets.json` to your AWS S3 bucket.
3. To make the file publicly accessible without authentication:
1. Find the file in the bucket list, and click on it to open the object overview.
2. Click on the *Permissions* tab to display the *Access control list (ACL)*.
3. Click on *Edit*.
4. Set *Everyone (public access)* Objects read, then confirm. This action makes the object readable by anyone on the internet.
5. Note the object URL.
6. To verify that the URL is publicly readable without authentication, open a new browser tab and copy/paste the object URL in the browser location bar. After you hit *Enter* , the browser will display the content of your encrypted secrets file.
4. Note the URL. You will need it in the following section. For example: `https://clfunctions.s3.eu-north-1.amazonaws.com/offchain-secrets.json`.
### Send a Request
To run the example:
1. Open the file `request.js`, which is located in the `7-use-secrets-url` folder.
2. Replace the consumer contract address and the subscription ID with your own values.
```javascript
const consumerAddress = "0x8dFf78B7EE3128D00E90611FBeD20A71397064D9" // REPLACE this with your Functions consumer address
const subscriptionId = 3 // REPLACE this with your subscription ID
```
3. Replace the `secretsUrls` with your AWS S3 URL:
```javascript
const secretsUrls = ["https://clfunctions.s3.eu-north-1.amazonaws.com/offchain-secrets.json"] // REPLACE WITH YOUR VALUES after running gen-offchain-secrets.js and uploading offchain-secrets.json to a public URL
```
4. Make a request:
```shell
node examples/7-use-secrets-url/request.js
```
The script runs your function in a sandbox environment before making an onchain transaction:
```text
$ node examples/7-use-secrets-url/request.js
secp256k1 unavailable, reverting to browser version
Encrypted secrets object written to /Users/crystalgomes/smart-contract-examples/functions-examples/offchain-secrets.json
crystalgomes@MB-CY16VK6DPG functions-examples % node examples/7-use-secrets-url/request.js
secp256k1 unavailable, reverting to browser version
Start simulation...
Simulation result {
capturedTerminalOutput: 'Price: 68196.20 USD\n',
responseBytesHexstring: '0x0000000000000000000000000000000000000000000000000000000000680f24'
}
✅ Decoded response to uint256: 6819620n
Estimate request costs...
Fulfillment cost estimated to 1.018348822253235 LINK
Make request...
Encrypt the URLs..
✅ Functions request sent! Transaction hash 0xadc0db0ddea7b9836b86a9c9e008bc97d47e5f92b0dcec9694d3944d0065c789. Waiting for a response...
See your request in the explorer https://sepolia.etherscan.io/tx/0xadc0db0ddea7b9836b86a9c9e008bc97d47e5f92b0dcec9694d3944d0065c789
✅ Request 0xb308ca293859dab47d8848578291e687a0d9373274d1451a9c9667dc4bba5fca successfully fulfilled. Cost is 0.260029208488139025 LINK.Complete response: {
requestId: '0xb308ca293859dab47d8848578291e687a0d9373274d1451a9c9667dc4bba5fca',
subscriptionId: 2303,
totalCostInJuels: 260029208488139025n,
responseBytesHexstring: '0x000000000000000000000000000000000000000000000000000000000068146a',
errorString: '',
returnDataBytesHexstring: '0x',
fulfillmentCode: 0
}
✅ Decoded response to uint256: 6820970n
```
The output of the example gives you the following information:
- Your request is first run on a sandbox environment to ensure it is correctly configured.
- The fulfillment costs are estimated before making the request.
- The AWS S3 URL is encrypted before sending it in the request.
- Your request was successfully sent to Chainlink Functions. The transaction in this example is [0xadc0db0ddea7b9836b86a9c9e008bc97d47e5f92b0dcec9694d3944d0065c789](https://sepolia.etherscan.io/tx/0xadc0db0ddea7b9836b86a9c9e008bc97d47e5f92b0dcec9694d3944d0065c789) and the request ID is `0xb308ca293859dab47d8848578291e687a0d9373274d1451a9c9667dc4bba5fca`.
- The DON successfully fulfilled your request. The total cost was: `0.260029208488139025 LINK`.
- The consumer contract received a response in `bytes` with a value of `0x000000000000000000000000000000000000000000000000000000000068146a`. Decoding it offchain to `uint256` gives you a result: `6820970`.
## Examine the code
### FunctionsConsumerExample.sol
### JavaScript example
#### source.js
The JavaScript code is similar to the [Using Secrets in Requests](/chainlink-functions/tutorials/api-use-secrets) tutorial.
#### gen-offchain-secrets.js
This explanation focuses on the [gen-offchain-secrets.js](https://github.com/smartcontractkit/smart-contract-examples/blob/main/functions-examples/examples/7-use-secrets-url/gen-offchain-secrets.js) script and shows how to use the [Chainlink Functions NPM package](https://github.com/smartcontractkit/functions-toolkit) in your own JavaScript/TypeScript project to encrypts your secrets. After encryption, the script saves the encrypted secrets on a local file, `offchain-secrets.json`. You can then upload the file to your storage of choice (AWS S3 in this example).
The script imports:
- [path](https://nodejs.org/docs/latest/api/path.html) and [fs](https://nodejs.org/api/fs.html) : Used to read the [source file](https://github.com/smartcontractkit/smart-contract-examples/blob/main/functions-examples/examples/7-use-secrets-url/source.js).
- [ethers](https://docs.ethers.org/v5/): Ethers.js library, enables the script to interact with the blockchain.
- `@chainlink/functions-toolkit`: Chainlink Functions NPM package. All its utilities are documented in the [NPM README](https://github.com/smartcontractkit/functions-toolkit/blob/main/README.md).
- `@chainlink/env-enc`: A tool for loading and storing encrypted environment variables. Read the [official documentation](https://www.npmjs.com/package/@chainlink/env-enc) to learn more.
The primary function that the script executes is `generateOffchainSecretsFile`. This function can be broken into three main parts:
1. Definition of necessary identifiers:
- `routerAddress`: Chainlink Functions router address on Sepolia.
- `donId`: Identifier of the DON that will fulfill your requests on Sepolia.
- `secrets`: The secrets object.
- Initialization of ethers `signer` and `provider` objects. The Chainlink NPM package uses the signer to sign the encrypted secrets with your private key.
2. Encrypt the secrets:
- Initialize a `SecretsManager` instance from the Chainlink Functions NPM package.
- Call the `encryptSecrets` function from the created instance to encrypt the secrets.
3. Use the `fs` library to store the encrypted secrets on a local file, `offchain-secrets.json`.
#### request.js
This explanation focuses on the [request.js](https://github.com/smartcontractkit/smart-contract-examples/blob/main/functions-examples/examples/7-use-secrets-url/request.js) script and shows how to use the [Chainlink Functions NPM package](https://github.com/smartcontractkit/functions-toolkit) in your own JavaScript/TypeScript project to send requests to a DON. The code is self-explanatory and has comments to help you understand all the steps.
The script imports:
- [path](https://nodejs.org/docs/latest/api/path.html) and [fs](https://nodejs.org/api/fs.html) : Used to read the [source file](https://github.com/smartcontractkit/smart-contract-examples/blob/main/functions-examples/examples/7-use-secrets-url/source.js).
- [ethers](https://docs.ethers.org/v5/): Ethers.js library, enables the script to interact with the blockchain.
- `@chainlink/functions-toolkit`: Chainlink Functions NPM package. All its utilities are documented in the [NPM README](https://github.com/smartcontractkit/functions-toolkit/blob/main/README.md).
- `@chainlink/env-enc`: A tool for loading and storing encrypted environment variables. Read the [official documentation](https://www.npmjs.com/package/@chainlink/env-enc) to learn more.
- `../abi/functionsClient.json`: The abi of the contract your script will interact with. **Note**: The script was tested with this [FunctionsConsumerExample contract](https://remix.ethereum.org/#url=https://docs.chain.link/samples/ChainlinkFunctions/FunctionsConsumerExample.sol).
The script has two hardcoded values that you have to change using your own Functions consumer contract and subscription ID:
```javascript
const consumerAddress = "0x8dFf78B7EE3128D00E90611FBeD20A71397064D9" // REPLACE this with your Functions consumer address
const subscriptionId = 3 // REPLACE this with your subscription ID
```
The primary function that the script executes is `makeRequestSepolia`. This function can be broken into six main parts:
1. Definition of necessary identifiers:
- `routerAddress`: Chainlink Functions router address on Sepolia.
- `donId`: Identifier of the DON that will fulfill your requests on Sepolia.
- `explorerUrl`: Block explorer URL of the Sepolia testnet.
- `source`: The source code must be a string object. That's why we use `fs.readFileSync` to read `source.js` and then call `toString()` to get the content as a `string` object.
- `args`: During the execution of your function, These arguments are passed to the source code. The `args` value is `["1", "USD"]`, which fetches the BTC/USD price.
- `secrets`: The secrets object. **Note**: Because we are sharing the URL of the encrypted secrets with the DON, the `secrets` object is only used during simulation.
- `secretsUrls`: The URL of the encrypted secrets object.
- `gasLimit`: Maximum gas that Chainlink Functions can use when transmitting the response to your contract.
- Initialization of ethers `signer` and `provider` objects. The signer is used to make transactions on the blockchain, and the provider reads data from the blockchain.
2. Simulating your request in a local sandbox environment:
- Use `simulateScript` from the Chainlink Functions NPM package.
- Read the `response` of the simulation. If successful, use the Functions NPM package `decodeResult` function and `ReturnType` enum to decode the response to the expected returned type (`ReturnType.uint256` in this example).
3. Estimating the costs:
- Initialize a `SubscriptionManager` from the Functions NPM package, then call the `estimateFunctionsRequestCost` function.
- The response is returned in Juels (1 LINK = 10\*\*18 Juels). Use the `ethers.utils.formatEther` utility function to convert the output to LINK.
4. Encrypt the secrets, then create a gist containing the encrypted secrets object. This is done in two steps:
- Initialize a `SecretsManager` instance from the Functions NPM package, then call the `encryptSecrets` function.
- Call the `encryptedSecretsUrls` function of the `SecretsManager` instance. This function encrypts the secrets URL. **Note**: The encrypted URL will be sent to the DON when making a request.
5. Making a Chainlink Functions request:
- Initialize your functions consumer contract using the contract address, abi, and ethers signer.
- Call the `sendRequest` function of your consumer contract.
6. Waiting for the response:
- Initialize a `ResponseListener` from the Functions NPM package and then call the `listenForResponseFromTransaction` function to wait for a response. By default, this function waits for five minutes.
- Upon reception of the response, use the Functions NPM package `decodeResult` function and `ReturnType` enum to decode the response to the expected returned type (`ReturnType.uint256` in this example).
---
# Using DON-hosted Secrets in Requests
Source: https://docs.chain.link/chainlink-functions/tutorials/api-use-secrets
This tutorial shows you how to send a request to a Decentralized Oracle Network to call the [Coinmarketcap API](https://coinmarketcap.com/api/documentation/v1/). After [OCR](/chainlink-functions/resources/architecture) completes offchain computation and aggregation, it returns the `BTC/USD` asset price to your smart contract. Because the API requires you to provide an API key, this guide will also show you how to encrypt, sign your API key, and share the encrypted secret with a Decentralized Oracle Network (DON).
The encrypted secrets are never stored onchain. This tutorial uses the threshold encryption feature. The encrypted secrets are stored with the DON. Read the [Secrets Management page](/chainlink-functions/resources/secrets) to learn more.
## Tutorial
This tutorial is configured to get the `BTC/USD` price with a request that requires API keys. For a detailed explanation of the code example, read the [Examine the code](#examine-the-code) section.
You can locate the scripts used in this tutorial in the [*examples/5-use-secrets-threshold* directory](https://github.com/smartcontractkit/smart-contract-examples/tree/main/functions-examples/examples/5-use-secrets-threshold).
1. Get a free API key from [CoinMarketCap](https://coinmarketcap.com/api/) and note your API key.
2. Run `npx env-enc set` to add an encrypted `COINMARKETCAP_API_KEY` to your `.env.enc` file.
```shell
npx env-enc set
```
3. Make sure your subscription has enough LINK to pay for your requests. Also, you must maintain a minimum balance to upload encrypted secrets to the DON (Read the [minimum balance for uploading encrypted secrets section](/chainlink-functions/resources/billing#minimum-balance-for-uploading-encrypted-secrets) to learn more). You can check your subscription details (including the balance in LINK) in the [Chainlink Functions Subscription Manager](/chainlink-functions/resources/subscriptions). If your subscription runs out of LINK, follow the [Fund a Subscription](/chainlink-functions/resources/subscriptions#fund-a-subscription) guide. This guide recommends maintaining at least 2 LINK within your subscription.
To run the example:
1. Open the file `request.js`, which is located in the `5-use-secrets-threshold` folder.
2. Replace the consumer contract address and the subscription ID with your own values.
```javascript
const consumerAddress = "0x8dFf78B7EE3128D00E90611FBeD20A71397064D9" // REPLACE this with your Functions consumer address
const subscriptionId = 3 // REPLACE this with your subscription ID
```
3. Make a request:
```shell
node examples/5-use-secrets-threshold/request.js
```
The script runs your function in a sandbox environment before making an onchain transaction:
```text
$ node examples/5-use-secrets-threshold/request.js
secp256k1 unavailable, reverting to browser version
Start simulation...
Simulation result {
capturedTerminalOutput: 'Price: 66757.65 USD\n',
responseBytesHexstring: '0x000000000000000000000000000000000000000000000000000000000065dd35'
}
✅ Decoded response to uint256: 6675765n
Estimate request costs...
Fulfillment cost estimated to 1.104471544715335 LINK
Make request...
Upload encrypted secret to gateways https://01.functions-gateway.testnet.chain.link/,https://02.functions-gateway.testnet.chain.link/. slotId 0. Expiration in minutes: 15
✅ Secrets uploaded properly to gateways https://01.functions-gateway.testnet.chain.link/,https://02.functions-gateway.testnet.chain.link/! Gateways response: { version: 1712949090, success: true }
✅ Functions request sent! Transaction hash 0xcac39aeea98651f307da185aed387314c453272d185e58b26b3bb399b82a90b6. Waiting for a response...
See your request in the explorer https://sepolia.etherscan.io/tx/0xcac39aeea98651f307da185aed387314c453272d185e58b26b3bb399b82a90b6
✅ Request 0xbc09de04f4dd39fa78d4b00b7ab4d2f4a37d8b9a8edf97df5c86061175b9d9c3 successfully fulfilled. Cost is 0.23730142355580769 LINK.Complete response: {
requestId: '0xbc09de04f4dd39fa78d4b00b7ab4d2f4a37d8b9a8edf97df5c86061175b9d9c3',
subscriptionId: 2303,
totalCostInJuels: 237301423555807690n,
responseBytesHexstring: '0x000000000000000000000000000000000000000000000000000000000065dc31',
errorString: '',
returnDataBytesHexstring: '0x',
fulfillmentCode: 0
}
✅ Decoded response to uint256: 6675505n
```
The output of the example gives you the following information:
- Your request is first run on a sandbox environment to ensure it is correctly configured.
- The fulfillment costs are estimated before making the request.
- The encrypted secrets were uploaded to the secrets endpoint `https://01.functions-gateway.testnet.chain.link/user`.
- Your request was successfully sent to Chainlink Functions. The transaction in this example is [0xcac39aeea98651f307da185aed387314c453272d185e58b26b3bb399b82a90b6](https://sepolia.etherscan.io/tx/0xcac39aeea98651f307da185aed387314c453272d185e58b26b3bb399b82a90b6) and the request ID is `0xbc09de04f4dd39fa78d4b00b7ab4d2f4a37d8b9a8edf97df5c86061175b9d9c3`.
- The DON successfully fulfilled your request. The total cost was: `0.23730142355580769 LINK`.
- The consumer contract received a response in `bytes` with a value of `0x000000000000000000000000000000000000000000000000000000000065dc31`. Decoding it offchain to `uint256` gives you a result: `6675505`. The median BTC price is 66755.05 USD.
## Examine the code
### FunctionsConsumerExample.sol
### JavaScript example
#### source.js
The Decentralized Oracle Network will run the [JavaScript code](https://github.com/smartcontractkit/smart-contract-examples/blob/main/functions-examples/examples/5-use-secrets-threshold/source.js). The code is self-explanatory and has comments to help you understand all the steps.
This JavaScript source code uses [Functions.makeHttpRequest](/chainlink-functions/api-reference/javascript-source#http-requests) to make HTTP requests. To request the `BTC` asset price, the source code calls the `https://pro-api.coinmarketcap.com/v1/cryptocurrency/quotes/latest/` URL. If you read the [Functions.makeHttpRequest](/chainlink-functions/api-reference/javascript-source#http-requests) documentation, you see that you must provide the following parameters:
- `url`: `https://pro-api.coinmarketcap.com/v1/cryptocurrency/quotes/latest`
- `headers`: This is an HTTP headers object set to `"X-CMC_PRO_API_KEY": secrets.apiKey`. The `apiKey` is passed in the secrets, see [request](#requestjs).
- `params`: The query parameters object:
```
{
convert: currencyCode,
id: coinMarketCapCoinId
}
```
To check the expected API response, run the `curl` command in your terminal:
```bash
curl -X 'GET' \
'https://pro-api.coinmarketcap.com/v1/cryptocurrency/quotes/latest?id=1&convert=USD' \
-H 'accept: application/json' \
-H 'X-CMC_PRO_API_KEY: REPLACE_WITH_YOUR_API_KEY'
```
The response should be similar to the following example:
```json
{
...,
"data": {
"1": {
"id": 1,
"name": "Bitcoin",
"symbol": "BTC",
"slug": "bitcoin",
...,
"quote": {
"USD": {
"price": 23036.068560170934,
"volume_24h": 33185308895.694683,
"volume_change_24h": 24.8581,
"percent_change_1h": 0.07027098,
"percent_change_24h": 1.79073805,
"percent_change_7d": 10.29859656,
"percent_change_30d": 38.10735851,
"percent_change_60d": 39.26624921,
"percent_change_90d": 11.59835416,
"market_cap": 443982488416.99316,
"market_cap_dominance": 42.385,
"fully_diluted_market_cap": 483757439763.59,
"tvl": null,
"last_updated": "2023-01-26T18:27:00.000Z"
}
}
}
}
}
```
The price is located at `data,1,quote,USD,price`.
The main steps of the scripts are:
- Fetch the `currencyCode` and `coinMarketCapCoinId` from `args`.
- Construct the HTTP object `coinMarketCapRequest` using `Functions.makeHttpRequest`.
- Make the HTTP call.
- Read the asset price from the response.
- Return the result as a [buffer](https://nodejs.org/api/buffer.html#buffer) using the helper function: `Functions.encodeUint256`. Note: Because solidity doesn't support decimals, we multiply the result by `100` and round the result to the nearest integer. **Note**: Read this [article](https://www.freecodecamp.org/news/do-you-want-a-better-understanding-of-buffer-in-node-js-check-this-out-2e29de2968e8/) if you are new to Javascript Buffers and want to understand why they are important.
#### request.js
This explanation focuses on the [request.js](https://github.com/smartcontractkit/smart-contract-examples/blob/main/functions-examples/examples/5-use-secrets-threshold/request.js) script and shows how to use the [Chainlink Functions NPM package](https://github.com/smartcontractkit/functions-toolkit) in your own JavaScript/TypeScript project to send requests to a DON. The code is self-explanatory and has comments to help you understand all the steps.
The script imports:
- [path](https://nodejs.org/docs/latest/api/path.html) and [fs](https://nodejs.org/api/fs.html) : Used to read the [source file](https://github.com/smartcontractkit/smart-contract-examples/blob/main/functions-examples/examples/5-use-secrets-threshold/source.js).
- [ethers](https://docs.ethers.org/v5/): Ethers.js library, enables the script to interact with the blockchain.
- `@chainlink/functions-toolkit`: Chainlink Functions NPM package. All its utilities are documented in the [NPM README](https://github.com/smartcontractkit/functions-toolkit/blob/main/README.md).
- `@chainlink/env-enc`: A tool for loading and storing encrypted environment variables. Read the [official documentation](https://www.npmjs.com/package/@chainlink/env-enc) to learn more.
- `../abi/functionsClient.json`: The abi of the contract your script will interact with. **Note**: The script was tested with this [FunctionsConsumerExample contract](https://remix.ethereum.org/#url=https://docs.chain.link/samples/ChainlinkFunctions/FunctionsConsumerExample.sol).
The script has two hardcoded values that you have to change using your own Functions consumer contract and subscription ID:
```javascript
const consumerAddress = "0x8dFf78B7EE3128D00E90611FBeD20A71397064D9" // REPLACE this with your Functions consumer address
const subscriptionId = 3 // REPLACE this with your subscription ID
```
The primary function that the script executes is `makeRequestSepolia`. This function can be broken into six main parts:
1. Definition of necessary identifiers:
- `routerAddress`: Chainlink Functions router address on Sepolia.
- `donId`: Identifier of the DON that will fulfill your requests on Sepolia.
- `gatewayUrls`: The secrets endpoint URL to which you will upload the encrypted secrets.
- `explorerUrl`: Block explorer URL of the Sepolia testnet.
- `source`: The source code must be a string object. That's why we use `fs.readFileSync` to read `source.js` and then call `toString()` to get the content as a `string` object.
- `args`: During the execution of your function, These arguments are passed to the source code. The `args` value is `["1", "USD"]`, which fetches the BTC/USD price.
- `secrets`: The secrets object that will be encrypted.
- `slotIdNumber`: Slot ID at the DON where to upload the encrypted secrets.
- `expirationTimeMinutes`: Expiration time in minutes of the encrypted secrets.
- `gasLimit`: Maximum gas that Chainlink Functions can use when transmitting the response to your contract.
- Initialization of ethers `signer` and `provider` objects. The signer is used to make transactions on the blockchain, and the provider reads data from the blockchain.
2. Simulating your request in a local sandbox environment:
- Use `simulateScript` from the Chainlink Functions NPM package.
- Read the `response` of the simulation. If successful, use the Functions NPM package `decodeResult` function and `ReturnType` enum to decode the response to the expected returned type (`ReturnType.uint256` in this example).
3. Estimating the costs:
- Initialize a `SubscriptionManager` from the Functions NPM package, then call the `estimateFunctionsRequestCost` function.
- The response is returned in Juels (1 LINK = 10\*\*18 Juels). Use the `ethers.utils.formatEther` utility function to convert the output to LINK.
4. Encrypt the secrets, then upload the encrypted secrets to the DON. This is done in two steps:
- Initialize a `SecretsManager` instance from the Functions NPM package, then call the `encryptSecrets` function.
- Call the `uploadEncryptedSecretsToDON` function of the `SecretsManager` instance. This function returns an object containing a `success` boolean as long as `version`, the secret version on the DON storage. **Note**: When making the request, you must pass the slot ID and version to tell the DON where to fetch the encrypted secrets.
5. Making a Chainlink Functions request:
- Initialize your functions consumer contract using the contract address, abi, and ethers signer.
- Call the `sendRequest` function of your consumer contract.
6. Waiting for the response:
- Initialize a `ResponseListener` from the Functions NPM package and then call the `listenForResponseFromTransaction` function to wait for a response. By default, this function waits for five minutes.
- Upon reception of the response, use the Functions NPM package `decodeResult` function and `ReturnType` enum to decode the response to the expected returned type (`ReturnType.uint256` in this example).
---
# Automate your Functions (Custom Logic Automation)
Source: https://docs.chain.link/chainlink-functions/tutorials/automate-functions-custom-logic
This tutorial shows you how to use [Chainlink Automation](/chainlink-automation) to automate your Chainlink Functions. Automation is essential when you want to trigger the same function regularly, such as fetching weather data daily or fetching an asset price on every block.
Read the [Automate your Functions (Time-based Automation)](/chainlink-functions/tutorials/automate-functions) tutorial before you follow the steps in this example. This tutorial explains how to trigger your functions using an [Automation compatible contract](/chainlink-automation/guides/compatible-contracts).
After you deploy and set up your contract, Chainlink Automation triggers your function on every block.
## Tutorial
This tutorial is configured to get the median `BTC/USD` price from multiple data sources on every block. Read the [Examine the code](#examine-the-code) section for a detailed explanation of the code example.
You can locate the scripts used in this tutorial in the [*examples/10-automate-functions* directory](https://github.com/smartcontractkit/smart-contract-examples/tree/main/functions-examples/examples/10-automate-functions).
1. Make sure to understand the [API multiple calls](/chainlink-functions/tutorials/api-multiple-calls) guide.
2. Make sure your subscription has enough LINK to pay for your requests. Also, you must maintain a minimum balance to upload encrypted secrets to the DON (Read the [minimum balance for uploading encrypted secrets section](/chainlink-functions/resources/billing#minimum-balance-for-uploading-encrypted-secrets) to learn more). You can check your subscription details (including the balance in LINK) in the [Chainlink Functions Subscription Manager](/chainlink-functions/resources/subscriptions). If your subscription runs out of LINK, follow the [Fund a Subscription](/chainlink-functions/resources/subscriptions#fund-a-subscription) guide. This guide recommends maintaining at least 2 LINK within your subscription.
3. Get a free API key from [CoinMarketCap](https://coinmarketcap.com/api/) and note your API key.
4. Run `npx env-enc set` to add an encrypted `COINMARKETCAP_API_KEY` to your `.env.enc` file.
```shell
npx env-enc set
```
### Deploy a Custom Automated Functions Consumer contract
The consumer contract for Custom Automated Functions is different from the consumer in other tutorials. Deploy the `CustomAutomatedFunctionsConsumerExample` contract on *Ethereum Sepolia*:
1. Open the [CustomAutomatedFunctionsConsumerExample.sol](https://remix.ethereum.org/#url=https://docs.chain.link/samples/ChainlinkFunctions/CustomAutomatedFunctionsConsumerExample.sol) in Remix.
2. Compile the contract.
3. Open MetaMask and select the *Ethereum Sepolia* network.
4. In Remix under the **Deploy & Run Transactions** tab, select *Injected Provider - MetaMask* in the **Environment** list. Remix will use the MetaMask wallet to communicate with *Ethereum Sepolia*.
5. Under the **Deploy** section, fill in the router address for your specific blockchain. You can find this address on the [Supported Networks](/chainlink-functions/supported-networks) page. For *Ethereum Sepolia*, the router address is 0xb83E47C2bC239B3bf370bc41e1459A34b41238D0.
6. Click the **Deploy** button to deploy the contract. MetaMask prompts you to confirm the transaction. Check the transaction details to make sure you are deploying the contract to *Ethereum Sepolia*.
7. After you confirm the transaction, the contract address appears in the Deployed Contracts list. Copy your contract address.
### Add your Consumer contract to your Functions subscription
Add your contract as an approved consumer contract to your Functions subscription using the [Chainlink Functions Subscription Manager](https://functions.chain.link/).
### Configure your Consumer contract
Configure the request details by calling the `updateRequest` function. This step stores the encoded request (source code, reference to encrypted secrets if any, arguments), gas limit, subscription ID, and job ID in the contract storage (see [Examine the code](#examine-the-code)). To do so, follow these steps:
1. On a terminal, change directories to the [*10-automate-functions*](https://github.com/smartcontractkit/smart-contract-examples/tree/main/functions-examples/examples/10-automate-functions) directory.
2. Open [updateRequest.js](https://github.com/smartcontractkit/smart-contract-examples/blob/main/functions-examples/examples/10-automate-functions/updateRequest.js) and replace the consumer contract address and the subscription ID with your own values:
```javascript
const consumerAddress = "0x5abE77Ba2aE8918bfD96e2e382d5f213f10D39fA" // REPLACE this with your Functions consumer address
const subscriptionId = 3 // REPLACE this with your subscription ID
```
3. Run the [updateRequest.js](https://github.com/smartcontractkit/smart-contract-examples/blob/main/functions-examples/examples/10-automate-functions/updateRequest.js) script to update your Functions consumer contract's request details.
### Configure Chainlink Automation
The consumer contract that you deployed is designed to be used with a **custom logic** automation. Follow the instructions in the [Register a Custom Logic Upkeep](/chainlink-automation/guides/register-upkeep) guide to register your deployed contract using the [Chainlink Automation App](https://automation.chain.link/). Use the following upkeep settings:
- Trigger: Custom logic
- Target contract address: The address of the Chainlink Functions consumer contract that you deployed
- Name: Give your upkeep a name
- Check data: Leave this field blank
- Gas limit: 1000000
- Starting balance (LINK): 1
You can leave the other settings at their default values for the example in this tutorial.
At this stage, your Functions consumer contract is configured to get the median Bitcoin price on every block.
### Check Result
Go to the [Chainlink Automation App](https://automation.chain.link/) and connect to the Sepolia testnet. Your upkeep will be listed under *My upkeeps*:
Click on your upkeep to fetch de details:
On your terminal, run the [readLatest](https://github.com/smartcontractkit/smart-contract-examples/blob/main/functions-examples/examples/10-automate-functions/readLatest.js) to read the latest received response:
1. Open `readLatest.js` and replace the consumer contract address with your own values:
```javascript
const consumerAddress = "0x5abE77Ba2aE8918bfD96e2e382d5f213f10D39fA" // REPLACE this with your Functions consumer address
```
2. Run the [readLatest](https://github.com/smartcontractkit/smart-contract-examples/blob/main/functions-examples/examples/10-automate-functions/readLatest.js) script.
```shell
node examples/10-automate-functions/readLatest.js
```
Output Example:
```text
$ node examples/10-automate-functions/readLatest.js
secp256k1 unavailable, reverting to browser version
Last request ID is 0xf4ae51b028ded52d33376810cd97f02e2b1dff424bb78d45730820fefc0b8060
✅ Decoded response to uint256: 6688012n
```
### Clean up
After you finish the guide, cancel your upkeep in the [Chainlink Automation App](https://automation.chain.link/) and withdraw the remaining funds. After you cancel the upkeep, there is a 50-block delay before you can withdraw the funds.
## Examine the code
### CustomAutomatedFunctionsConsumer.sol
### source.js
The JavaScript code is similar to the one used in the [Call Multiple Data Sources](/chainlink-functions/tutorials/api-multiple-calls) tutorial.
### updateRequest.js
The JavaScript code is similar to the one used in the [Automate your Functions (Time-based Automation)](/chainlink-functions/tutorials/automate-functions) tutorial.
### readLatest.js
The JavaScript code is similar to the one used in the [Automate your Functions (Time-based Automation)](/chainlink-functions/tutorials/automate-functions) tutorial.
---
# Automate your Functions (Time-based Automation)
Source: https://docs.chain.link/chainlink-functions/tutorials/automate-functions
This tutorial shows you how to use [Chainlink Automation](/chainlink-automation) to automate your Chainlink Functions. Automation is essential when you want to trigger the same function regularly, such as fetching weather data daily or fetching an asset price on every block.
Read the [API multiple calls](/chainlink-functions/tutorials/api-multiple-calls) tutorial before you follow the steps in this example. This tutorial uses the same example but with an important difference:
- You will deploy [AutomatedFunctionsConsumerExample.sol](https://remix.ethereum.org/#url=https://docs.chain.link/samples/ChainlinkFunctions/AutomatedFunctionsConsumerExample.sol) instead of the [FunctionsConsumerExample contract](https://remix.ethereum.org/#url=https://docs.chain.link/samples/ChainlinkFunctions/FunctionsConsumerExample.sol).
After you deploy and set up your contract, Chainlink Automation triggers your function according to a time schedule.
## Tutorial
This tutorial is configured to get the median `BTC/USD` price from multiple data sources according to a time schedule. For a detailed explanation of the code example, read the [Examine the code](#examine-the-code) section.
You can locate the scripts used in this tutorial in the [*examples/10-automate-functions* directory](https://github.com/smartcontractkit/smart-contract-examples/tree/main/functions-examples/examples/10-automate-functions).
1. Make sure to understand the [API multiple calls](/chainlink-functions/tutorials/api-multiple-calls) guide.
2. Make sure your subscription has enough LINK to pay for your requests. Also, you must maintain a minimum balance to upload encrypted secrets to the DON (Read the [minimum balance for uploading encrypted secrets section](/chainlink-functions/resources/billing#minimum-balance-for-uploading-encrypted-secrets) to learn more). You can check your subscription details (including the balance in LINK) in the [Chainlink Functions Subscription Manager](/chainlink-functions/resources/subscriptions). If your subscription runs out of LINK, follow the [Fund a Subscription](/chainlink-functions/resources/subscriptions#fund-a-subscription) guide. This guide recommends maintaining at least 2 LINK within your subscription.
3. Get a free API key from [CoinMarketCap](https://coinmarketcap.com/api/) and note your API key.
4. Run `npx env-enc set` to add an encrypted `COINMARKETCAP_API_KEY` to your `.env.enc` file.
```shell
npx env-enc set
```
### Deploy an Automated Functions Consumer contract
The consumer contract for Automated Functions is different from the consumer in other tutorials. Deploy the `AutomatedFunctionsConsumerExample` contract on *Ethereum Sepolia*:
1. Open the [AutomatedFunctionsConsumerExample.sol](https://remix.ethereum.org/#url=https://docs.chain.link/samples/ChainlinkFunctions/AutomatedFunctionsConsumerExample.sol) in Remix.
2. Compile the contract.
3. Open MetaMask and select the *Ethereum Sepolia* network.
4. In Remix under the **Deploy & Run Transactions** tab, select *Injected Provider - MetaMask* in the **Environment** list. Remix will use the MetaMask wallet to communicate with *Ethereum Sepolia*.
5. Under the **Deploy** section, fill in the router address for your specific blockchain. You can find this address on the [Supported Networks](/chainlink-functions/supported-networks) page. For *Ethereum Sepolia*, the router address is 0xb83E47C2bC239B3bf370bc41e1459A34b41238D0.
6. Click the **Deploy** button to deploy the contract. MetaMask prompts you to confirm the transaction. Check the transaction details to make sure you are deploying the contract to *Ethereum Sepolia*.
7. After you confirm the transaction, the contract address appears in the Deployed Contracts list. Copy your contract address.
### Add your Consumer contract to your Functions subscription
Add your contract as an approved consumer contract to your Functions subscription using the [Chainlink Functions Subscription Manager](https://functions.chain.link/).
### Configure Chainlink Automation
The consumer contract that you deployed is designed to be used with a **time-based** automation. Follow the instructions in the [Automation Job Scheduler](/chainlink-automation/guides/job-scheduler) guide to register your deployed contract using the [Chainlink Automation App](https://automation.chain.link/). Use the following upkeep settings:
- Trigger: Time-based
- Target contract address: The address of the automated Functions consumer contract that you deployed
- ABI: copy/paste the ABI from [automatedFunctions.json](https://github.com/smartcontractkit/smart-contract-examples/blob/main/functions-examples/abi/automatedFunctions.json)
- Target function: sendRequestCBOR
- Time interval: Every 15 minutes
- Name: Give your upkeep a name
- Gas limit: 1000000
- Starting balance (LINK): 1
You can leave the other settings at their default values for the example in this tutorial.
**Note**: After creation, check your upkeep details and note the address of the upkeep contract. The upkeep contract is responsible for calling your Functions consumer contract at regular times intervals.
### Configure your Consumer contract
Two important steps are done here:
1. Configure your contract so only the upkeep contract can call the `sendRequestCBOR` function. This security measure is important to prevent anyone from calling several times `sendRequestCBOR` and draining your Functions subscription balance. Follow these steps:
1. On RemixIDE, under the *Deploy & Transactions* tab, locate your deployed Functions consumer contract.
2. Open the list of functions.
3. Fill in the `setAutomationCronContract` function with the upkeep contract address you copied from the previous step.
4. Click on *transact*. A Metamask popup appears and asks you to confirm the transaction.
5. Confirm the transaction and wait for it to be confirmed.
2. Configure the request details by calling the `updateRequest` function. This step stores the encoded request (source code, reference to encrypted secrets if any, arguments), gas limit, subscription ID, and job ID in the contract storage (see [Examine the code](#examine-the-code)). To do so, follow these steps:
1. On a terminal, change directories to the [*10-automate-functions*](https://github.com/smartcontractkit/smart-contract-examples/tree/main/functions-examples/examples/10-automate-functions) directory.
2. Open [updateRequest.js](https://github.com/smartcontractkit/smart-contract-examples/blob/main/functions-examples/examples/10-automate-functions/updateRequest.js) and replace the consumer contract address and the subscription ID with your own values:
```javascript
const consumerAddress = "0x5abE77Ba2aE8918bfD96e2e382d5f213f10D39fA" // REPLACE this with your Functions consumer address
const subscriptionId = 3 // REPLACE this with your subscription ID
```
3. Run the [updateRequest.js](https://github.com/smartcontractkit/smart-contract-examples/blob/main/functions-examples/examples/10-automate-functions/updateRequest.js) script.
```shell
node examples/10-automate-functions/updateRequest.js
```
Output example:
```text
$ node examples/10-automate-functions/updateRequest.js
secp256k1 unavailable, reverting to browser version
Start simulation...
Simulation result {
capturedTerminalOutput: 'Median Bitcoin price: 66725.29\n',
responseBytesHexstring: '0x000000000000000000000000000000000000000000000000000000000065d091'
}
✅ Decoded response to uint256: 6672529n
Make request...
Upload encrypted secret to gateways https://01.functions-gateway.testnet.chain.link/,https://02.functions-gateway.testnet.chain.link/. slotId 0. Expiration in minutes: 150
✅ Secrets uploaded properly to gateways https://01.functions-gateway.testnet.chain.link/,https://02.functions-gateway.testnet.chain.link/! Gateways response: { version: 1712948932, success: true }
✅ Automated Functions request settings updated! Transaction hash 0x670c6a768a3fbccdcc344e51827ba41a13a579427272522550ad5810ca5b81a3 - Check the explorer https://sepolia.etherscan.io/tx/0x670c6a768a3fbccdcc344e51827ba41a13a579427272522550ad5810ca5b81a3
```
The output of the example gives you the following information:
- Your request is first run on a sandbox environment to ensure it is correctly configured.
- The encrypted secrets were uploaded to the secrets endpoint `https://01.functions-gateway.testnet.chain.link/user`.
- The Functions consumer contract's request details are updated.
At this stage, your Functions consumer contract is configured to get the median Bitcoin price every 15 minutes.
### Check Result
Go to the [Chainlink Automation App](https://automation.chain.link/) and connect to the Sepolia testnet. Your upkeep will be listed under *My upkeeps*:
Click on your upkeep to fetch de details:
As you can see in the *History* table, the upkeep is running every 15 minutes.
On your terminal, run the [readLatest](https://github.com/smartcontractkit/smart-contract-examples/blob/main/functions-examples/examples/10-automate-functions/readLatest.js) script to read the latest received response:
1. Open `readLatest.js` and replace the consumer contract address with your own values:
```javascript
const consumerAddress = "0x5abE77Ba2aE8918bfD96e2e382d5f213f10D39fA" // REPLACE this with your Functions consumer address
```
2. Run the [readLatest](https://github.com/smartcontractkit/smart-contract-examples/blob/main/functions-examples/examples/10-automate-functions/readLatest.js) script.
```shell
node examples/10-automate-functions/readLatest.js
```
Output example:
```text
$ node examples/10-automate-functions/readLatest.js
secp256k1 unavailable, reverting to browser version
Last request ID is 0xa6c0a45c9a24981e0112381f9addeeb8f8a9ad0ea91dd0426703eaa11d5a773a
✅ Decoded response to uint256: 6675568n
```
### Clean up
After you finish the guide, cancel your upkeep in the [Chainlink Automation App](https://automation.chain.link/) and withdraw the remaining funds. After you cancel the upkeep, there is a 50-block delay before you can withdraw the funds.
## Examine the code
### AutomatedFunctionsConsumer.sol
### source.js
The JavaScript code is similar to the [Call Multiple Data Sources](/chainlink-functions/tutorials/api-multiple-calls) tutorial.
### updateRequest.js
This explanation focuses on the [updateRequest.js](https://github.com/smartcontractkit/smart-contract-examples/blob/main/functions-examples/examples/10-automate-functions/updateRequest.js) script and shows how to use the [Chainlink Functions NPM package](https://github.com/smartcontractkit/functions-toolkit) in your own JavaScript/TypeScript project to encode a request offchain and store it in your contract. The code is self-explanatory and has comments to help you understand all the steps.
The script imports:
- [path](https://nodejs.org/docs/latest/api/path.html) and [fs](https://nodejs.org/api/fs.html) : Used to read the [source file](https://github.com/smartcontractkit/smart-contract-examples/blob/main/functions-examples/examples/5-use-secrets-threshold/source.js).
- [ethers](https://docs.ethers.org/v5/): Ethers.js library, enables the script to interact with the blockchain.
- `@chainlink/functions-toolkit`: Chainlink Functions NPM package. All its utilities are documented in the [NPM README](https://github.com/smartcontractkit/functions-toolkit/blob/main/README.md).
- `@chainlink/env-enc`: A tool for loading and storing encrypted environment variables. Read the [official documentation](https://www.npmjs.com/package/@chainlink/env-enc) to learn more.
- `../abi/automatedFunctions.json`: The ABI of the contract your script will interact with. **Note**: The script was tested with this [AutomatedFunctionsConsumer contract](https://remix.ethereum.org/#url=https://docs.chain.link/samples/ChainlinkFunctions/AutomatedFunctionsConsumerExample.sol).
The script has two hardcoded values that you have to change using your own Functions consumer contract and subscription ID:
```javascript
const consumerAddress = "0x5abE77Ba2aE8918bfD96e2e382d5f213f10D39fA" // REPLACE this with your Functions consumer address
const subscriptionId = 3 // REPLACE this with your subscription ID
```
The primary function that the script executes is `updateRequestSepolia`. This function consists of five main parts:
1. Definition of necessary identifiers:
- `routerAddress`: Chainlink Functions router address on the Sepolia testnet.
- `donId`: Identifier of the DON that will fulfill your requests on the Sepolia testnet.
- `gatewayUrls`: The secrets endpoint URL to which you will upload the encrypted secrets.
- `explorerUrl`: Block explorer URL of the Sepolia testnet.
- `source`: The source code must be a string object. That's why we use `fs.readFileSync` to read `source.js` and then call `toString()` to get the content as a `string` object.
- `args`: During the execution of your function, These arguments are passed to the source code. The `args` value is `["1", "bitcoin", "btc-bitcoin"]`. These arguments are BTC IDs at CoinMarketCap, CoinGecko, and Coinpaprika. You can adapt args to fetch other asset prices.
- `secrets`: The secrets object that will be encrypted.
- `slotIdNumber`: Slot ID at the DON where to upload the encrypted secrets.
- `expirationTimeMinutes`: Expiration time in minutes of the encrypted secrets.
- `gasLimit`: Maximum gas that Chainlink Functions can use when transmitting the response to your contract.
- Initialization of ethers `signer` and `provider` objects. The signer is used to make transactions on the blockchain, and the provider reads data from the blockchain.
2. Simulating your request in a local sandbox environment:
- Use `simulateScript` from the Chainlink Functions NPM package.
- Read the `response` of the simulation. If successful, use the Functions NPM package `decodeResult` function and `ReturnType` enum to decode the response to the expected returned type (`ReturnType.uint256` in this example).
3. Encrypt the secrets, upload the encrypted secrets to the DON, and then encode the reference to the DON-hosted encrypted secrets. This is done in three steps:
- Initialize a `SecretsManager` instance from the Functions NPM package, then call the `encryptSecrets` function.
- Call the `uploadEncryptedSecretsToDON` function of the `SecretsManager` instance. This function returns an object containing a `success` boolean as long as `version`, the secret version on the DON storage.
- Call the `buildDONHostedEncryptedSecretsReference` function of the `SecretsManager` instance and use the slot ID and version to encode the DON-hosted encrypted secrets reference.
4. Encode the request data offchain using the `buildRequestCBOR` function from the Functions NPM package.
5. Update the Functions consumer contract:
- Initialize your functions consumer contract using the contract address, abi, and ethers signer.
- Call the `updateRequest` function of your consumer contract.
### readLatest.js
This explanation focuses on the [readLatest.js](https://github.com/smartcontractkit/smart-contract-examples/blob/main/functions-examples/examples/10-automate-functions/readLatest.js) script that reads your consumer contract's latest received response and decodes it offchain using the Chainlink Function NPM package.
The script contains a hardcoded value that you must replace with your own Functions consumer contract address:
```javascript
const consumerAddress = "0x5abE77Ba2aE8918bfD96e2e382d5f213f10D39fA" // REPLACE this with your Functions consumer address
```
The primary function that the script executes is `readLatest`. This function can be broken down into two main parts:
1. Read the latest response:
- Initialize your functions consumer contract using the contract address, ABI, and ethers provider.
- Call the `s_lastRequestId`, `s_lastResponse`, and `s_lastError` functions of your consumer contract.
2. Decode the latest response:
- If there was an error, read the latest error and parse it into a `string`.
- If there was no error, use the Functions NPM package's `decodeResult` function and the `ReturnType` enum to decode the response to the expected return type (`ReturnType.uint256` in this example).
---
# Encode request data offchain
Source: https://docs.chain.link/chainlink-functions/tutorials/encode-request-offchain
This tutorial shows you how make multiple API calls from your smart contract to a Decentralized Oracle Network. After [OCR](/chainlink-functions/resources/architecture) completes offchain computation and aggregation, the DON returns the asset price to your smart contract. This example returns the `BTC/USD` price.
This guide assumes that you know how to build HTTP requests and how to use secrets. Read the [API query parameters](/chainlink-functions/tutorials/api-query-parameters) and [API use secrets](/chainlink-functions/tutorials/api-use-secrets) guides before you follow the example in this document.
To build a decentralized asset price, send a request to the DON to fetch the price from many different API providers. Then, calculate the median price. The API providers in this example are:
- [CoinMarket](https://coinmarketcap.com/api/documentation/v1/)
- [CoinGecko](https://www.coingecko.com/en/api/documentation)
- [CoinPaprika](https://api.coinpaprika.com/)
Read the [Call Multiple Data Sources](/chainlink-functions/tutorials/api-multiple-calls) tutorial before you follow the steps in this example. This tutorial uses the same example but with a slightly different process:
- Instead of sending the request data (source code, encrypted secrets reference, and arguments) in the request, you will first encode it offchain and then send the encoded request. Encoding the request offchain from your front end or a server rather than onchain from your smart contract. This helps save gas.
## Tutorial
This tutorial is configured to get the median `BTC/USD` price from multiple data sources. For a detailed explanation of the code example, read the [Examine the code](#examine-the-code) section.
You can locate the scripts used in this tutorial in the [*examples/9-send-cbor* directory](https://github.com/smartcontractkit/smart-contract-examples/tree/main/functions-examples/examples/9-send-cbor).
1. Make sure your subscription has enough LINK to pay for your requests. Also, you must maintain a minimum balance to upload encrypted secrets to the DON (Read the [minimum balance for uploading encrypted secrets section](/chainlink-functions/resources/billing#minimum-balance-for-uploading-encrypted-secrets) to learn more). You can check your subscription details (including the balance in LINK) in the [Chainlink Functions Subscription Manager](/chainlink-functions/resources/subscriptions). If your subscription runs out of LINK, follow the [Fund a Subscription](/chainlink-functions/resources/subscriptions#fund-a-subscription) guide. This guide recommends maintaining at least 2 LINK within your subscription.
2. Get a free API key from [CoinMarketCap](https://coinmarketcap.com/api/) and note your API key.
3. Run `npx env-enc set` to add an encrypted `COINMARKETCAP_API_KEY` to your `.env.enc` file.
```shell
npx env-enc set
```
To run the example:
1. Open the file `request.js`, which is located in the `9-send-cbor` folder.
2. Replace the consumer contract address and the subscription ID with your own values.
```javascript
const consumerAddress = "0x8dFf78B7EE3128D00E90611FBeD20A71397064D9" // REPLACE this with your Functions consumer address
const subscriptionId = 3 // REPLACE this with your subscription ID
```
3. Make a request:
```shell
node examples/9-send-cbor/request.js
```
The script runs your function in a sandbox environment before making an onchain transaction:
```text
$ node examples/9-send-cbor/request.js
secp256k1 unavailable, reverting to browser version
Start simulation...
Simulation result {
capturedTerminalOutput: 'Median Bitcoin price: 66346.16\n',
responseBytesHexstring: '0x0000000000000000000000000000000000000000000000000000000000653c78'
}
✅ Decoded response to uint256: 6634616n
Estimate request costs...
Fulfillment cost estimated to 1.08425528035514 LINK
Make request...
Upload encrypted secret to gateways https://01.functions-gateway.testnet.chain.link/,https://02.functions-gateway.testnet.chain.link/. slotId 0. Expiration in minutes: 15
✅ Secrets uploaded properly to gateways https://01.functions-gateway.testnet.chain.link/,https://02.functions-gateway.testnet.chain.link/! Gateways response: { version: 1712947615, success: true }
✅ Functions request sent! Transaction hash 0x730a66676cd797b11943635d53af9941c561d90a7088106800d05b4fdb2de189. Waiting for a response...
See your request in the explorer https://sepolia.etherscan.io/tx/0x730a66676cd797b11943635d53af9941c561d90a7088106800d05b4fdb2de189
✅ Request 0x8329a6e56461117508885f9eaee338f25095eb0f863d6972877f38c4412c0a29 successfully fulfilled. Cost is 0.236443904180225775 LINK.Complete response: {
requestId: '0x8329a6e56461117508885f9eaee338f25095eb0f863d6972877f38c4412c0a29',
subscriptionId: 2303,
totalCostInJuels: 236443904180225775n,
responseBytesHexstring: '0x0000000000000000000000000000000000000000000000000000000000653c78',
errorString: '',
returnDataBytesHexstring: '0x',
fulfillmentCode: 0
}
✅ Decoded response to uint256: 6634616n
```
The output of the example gives you the following information:
- Your request is first run on a sandbox environment to ensure it is correctly configured.
- The fulfillment costs are estimated before making the request.
- The encrypted secrets were uploaded to the secrets endpoint `https://01.functions-gateway.testnet.chain.link/user`.
- Your request was successfully sent to Chainlink Functions. The transaction in this example is [0x730a66676cd797b11943635d53af9941c561d90a7088106800d05b4fdb2de189](https://sepolia.etherscan.io/tx/0x730a66676cd797b11943635d53af9941c561d90a7088106800d05b4fdb2de189) and the request ID is `0x8329a6e56461117508885f9eaee338f25095eb0f863d6972877f38c4412c0a29`.
- The DON successfully fulfilled your request. The total cost was: `0.236443904180225775 LINK`.
- The consumer contract received a response in `bytes` with a value of `0x0000000000000000000000000000000000000000000000000000000000653c78`. Decoding it offchain to `uint256` gives you a result: `6634616`. The median BTC price is 66346.16 USD.
## Examine the code
### FunctionsConsumerExample.sol
### JavaScript example
#### source.js
The JavaScript code is similar to the [Call Multiple Data Sources](/chainlink-functions/tutorials/api-multiple-calls) tutorial.
#### request.js
This explanation focuses on the [request.js](https://github.com/smartcontractkit/smart-contract-examples/blob/main/functions-examples/examples/8-multiple-apis/request.js) script and shows how to use the [Chainlink Functions NPM package](https://github.com/smartcontractkit/functions-toolkit) in your own JavaScript/TypeScript project to send requests to a DON. The code is self-explanatory and has comments to help you understand all the steps.
The script imports:
- [path](https://nodejs.org/docs/latest/api/path.html) and [fs](https://nodejs.org/api/fs.html) : Used to read the [source file](https://github.com/smartcontractkit/smart-contract-examples/blob/main/functions-examples/examples/8-multiple-apis/source.js).
- [ethers](https://docs.ethers.org/v5/): Ethers.js library, enables the script to interact with the blockchain.
- `@chainlink/functions-toolkit`: Chainlink Functions NPM package. All its utilities are documented in the [NPM README](https://github.com/smartcontractkit/functions-toolkit/blob/main/README.md).
- `@chainlink/env-enc`: A tool for loading and storing encrypted environment variables. Read the [official documentation](https://www.npmjs.com/package/@chainlink/env-enc) to learn more.
- `../abi/functionsClient.json`: The abi of the contract your script will interact with. **Note**: The script was tested with this [FunctionsConsumerExample contract](https://remix.ethereum.org/#url=https://docs.chain.link/samples/ChainlinkFunctions/FunctionsConsumerExample.sol).
The script has two hardcoded values that you have to change using your own Functions consumer contract and subscription ID:
```javascript
const consumerAddress = "0x8dFf78B7EE3128D00E90611FBeD20A71397064D9" // REPLACE this with your Functions consumer address
const subscriptionId = 3 // REPLACE this with your subscription ID
```
The primary function that the script executes is `makeRequestSepolia`. This function can be broken into seven main parts:
1. Definition of necessary identifiers:
- `routerAddress`: Chainlink Functions router address on the Sepolia testnet.
- `donId`: Identifier of the DON that will fulfill your requests on the Sepolia testnet.
- `gatewayUrls`: The secrets endpoint URL to which you will upload the encrypted secrets.
- `explorerUrl`: Block explorer url of the Sepolia testnet.
- `source`: The source code must be a string object. That's why we use `fs.readFileSync` to read `source.js` and then call `toString()` to get the content as a `string` object.
- `args`: During the execution of your function, These arguments are passed to the source code. The `args` value is `["1", "bitcoin", "btc-bitcoin"]`. These arguments are BTC IDs at CoinMarketCap, CoinGecko, and Coinpaprika. You can adapt args to fetch other asset prices.
- `secrets`: The secrets object that will be encrypted.
- `slotIdNumber`: Slot ID at the DON where to upload the encrypted secrets.
- `expirationTimeMinutes`: Expiration time in minutes of the encrypted secrets.
- `gasLimit`: Maximum gas that Chainlink Functions can use when transmitting the response to your contract.
- Initialization of ethers `signer` and `provider` objects. The signer is used to make transactions on the blockchain, and the provider reads data from the blockchain.
2. Simulating your request in a local sandbox environment:
- Use `simulateScript` from the Chainlink Functions NPM package.
- Read the `response` of the simulation. If successful, use the Functions NPM package `decodeResult` function and `ReturnType` enum to decode the response to the expected returned type (`ReturnType.uint256` in this example).
3. Estimating the costs:
- Initialize a `SubscriptionManager` from the Functions NPM package, then call the `estimateFunctionsRequestCost` function.
- The response is returned in Juels (1 LINK = 10\*\*18 Juels). Use the `ethers.utils.formatEther` utility function to convert the output to LINK.
4. Encrypt the secrets, upload the encrypted secrets to the DON, and then encode the reference to the DON-hosted encrypted secrets. This is done in three steps:
- Initialize a `SecretsManager` instance from the Functions NPM package, then call the `encryptSecrets` function.
- Call the `uploadEncryptedSecretsToDON` function of the `SecretsManager` instance. This function returns an object containing a `success` boolean as long as `version`, the secret version on the DON storage.
- Call the `buildDONHostedEncryptedSecretsReference` function of the `SecretsManager` instance and use the slot ID and version to encode the DON-hosted encrypted secrets reference.
5. Encode the request data offchain using the `buildRequestCBOR` function from the Functions NPM package.
6. Making a Chainlink Functions request:
- Initialize your functions consumer contract using the contract address, abi, and ethers signer.
- Make a [static call](https://docs.ethers.org/v5/api/contract/contract/#contract-callStatic) to the `sendRequestCBOR` function of your consumer contract to return the request ID that Chainlink Functions will generate.
- Call the `sendRequestCBOR` function of your consumer contract. **Note**: The encoded data that was generated by `buildRequestCBOR` is passed in the request.
7. Waiting for the response:
- Initialize a `ResponseListener` from the Functions NPM package and then call the `listenForResponseFromTransaction` function to wait for a response. By default, this function waits for five minutes.
- Upon reception of the response, use the Functions NPM package `decodeResult` function and `ReturnType` enum to decode the response to the expected returned type (`ReturnType.uint256` in this example).
---
# Using Imports with Functions
Source: https://docs.chain.link/chainlink-functions/tutorials/importing-packages
This tutorial demonstrates how to import modules and use them with your Functions source code. Modules that are imported into Functions source code must meet the following requirements:
- Each import must be 10 MB or less in size.
- Up to 100 imports total are supported.
- Deno supports [ESM compatible NPM imports](https://docs.deno.com/runtime/manual/node/npm_specifiers) and some [standard Node modules](https://docs.deno.com/runtime/manual/node/node_specifiers). See the [Compatibility List](https://docs.deno.com/runtime/manual/node/compatibility) for details.
- Third-party modules are imported at runtime, so import statements must use asynchronous logic like the following examples:
- Importing from `deno.land`:
```javascript
const { escape } = await import("https://deno.land/std/regexp/mod.ts")
```
- ESM-compatible packages:
```javascript
const { format } = await import("npm:date-fns")
```
- Standard Node modules:
```javascript
const path = await import("node:path")
```
- CDN imports:
```javascript
const lodash = await import("http://cdn.skypack.dev/lodash")
```
- Imported modules abide by all sandbox restrictions and do not have access to the file system, environment variables, or any other Deno permissions.
## Tutorial
This example imports [ethers](https://www.npmjs.com/package/ethers) and demonstrates how to call a smart contract functions using a JSON RPC provider to call an onchain function. In this example, the source code calls the [`latestRoundData()` function](/data-feeds/api-reference#latestrounddata) from the `AggregatorV3Interface`. Read the [Examine the code](#examine-the-code) section for a detailed description of the code example.
You can locate the scripts used in this tutorial in the [*examples/11-package-imports* directory](https://github.com/smartcontractkit/smart-contract-examples/tree/main/functions-examples/examples/11-package-imports).
To run the example:
1. Open the file `request.js`, which is located in the `11-package-imports` folder.
2. Replace the consumer contract address and the subscription ID with your own values.
```javascript
const consumerAddress = "0x8dFf78B7EE3128D00E90611FBeD20A71397064D9" // REPLACE this with your Functions consumer address
const subscriptionId = 3 // REPLACE this with your subscription ID
```
3. Make a request:
```shell
node examples/11-package-imports/request.js
```
The script runs your function in a sandbox environment before making an onchain transaction:
```text
$ node examples/11-package-imports/request.js
secp256k1 unavailable, reverting to browser version
Start simulation...
Simulation result {
capturedTerminalOutput: 'Fetched BTC / USD price: 6644228390483\n',
responseBytesHexstring: '0x0000000000000000000000000000000000000000000000000000060afadf7e53'
}
✅ Decoded response to int256: 6644228390483n
Estimate request costs...
Fulfillment cost estimated to 1.09518769822223 LINK
Make request...
✅ Functions request sent! Transaction hash 0xa73d895adb28360d1737a695647390a3a7f000368d976135fcfe9c834ee75ed6. Waiting for a response...
See your request in the explorer https://sepolia.etherscan.io/tx/0xa73d895adb28360d1737a695647390a3a7f000368d976135fcfe9c834ee75ed6
✅ Request 0x5bac800974596113a3013bf788919a6b3df5ea65ec6238a1c98114a60daff6d2 successfully fulfilled. Cost is 0.236901088749168095 LINK.Complete response: {
requestId: '0x5bac800974596113a3013bf788919a6b3df5ea65ec6238a1c98114a60daff6d2',
subscriptionId: 2303,
totalCostInJuels: 236901088749168095n,
responseBytesHexstring: '0x0000000000000000000000000000000000000000000000000000060afadf7e53',
errorString: '',
returnDataBytesHexstring: '0x',
fulfillmentCode: 0
}
✅ Decoded response to int256: 6644228390483n
```
The output of the example gives you the following information:
- Your request is first run on a sandbox environment to ensure it is correctly configured.
- The fulfillment costs are estimated before making the request.
- Your request was successfully sent to Chainlink Functions. The transaction in this example is `0xa73d895adb28360d1737a695647390a3a7f000368d976135fcfe9c834ee75ed6` and the request ID is `0x5bac800974596113a3013bf788919a6b3df5ea65ec6238a1c98114a60daff6d2`.
- The DON successfully fulfilled your request. The total cost was: `0.236901088749168095 LINK`.
- The consumer contract received a response in `bytes` with a value of `0x0000000000000000000000000000000000000000000000000000060afadf7e53`. Decoding it offchain to `int256` gives you a result: `6644228390483`.
## Examine the code
### FunctionsConsumerExample.sol
### JavaScript example
#### source.js
The Decentralized Oracle Network will run the [JavaScript code](https://github.com/smartcontractkit/smart-contract-examples/blob/main/functions-examples/examples/11-package-imports/source.js). The code is self-explanatory and has comments to help you understand all the steps.
The example `source.js` file uses a JSON RPC call to the [`latestRoundData()` function](/data-feeds/api-reference#latestrounddata) of a [Chainlink Data Feed](/data-feeds).
The request requires a few modifications to work in the Chainlink Functions environment. For example, the `JsonRpcProvider` class must be inherited to override the JsonRpcProvider [`_send` method](https://docs.ethers.org/v6/api/providers/jsonrpc/#JsonRpcProvider). This customization is necessary because Deno does not natively support Node.js modules like [http](https://nodejs.org/api/http.html) or [https](https://nodejs.org/api/https.html). We override the `_send` method to use the [fetch API](https://docs.deno.com/api/web/~/fetch), which is the standard way to make HTTP(s) requests in Deno. **Note**: The `url` passed in the constructor is the URL of the JSON RPC provider.
```javascript
// Chainlink Functions compatible Ethers JSON RPC provider class
// (this is required for making Ethers RPC calls with Chainlink Functions)
class FunctionsJsonRpcProvider extends ethers.JsonRpcProvider {
constructor(url) {
super(url)
this.url = url
}
async _send(payload) {
let resp = await fetch(this.url, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(payload),
})
return resp.json()
}
}
```
After the class is extended, you can initialize the provider object with the `RPC_URL` and await the response.
```javascript
const provider = new FunctionsJsonRpcProvider(RPC_URL)
const dataFeedContract = new ethers.Contract(CONTRACT_ADDRESS, abi, provider)
const dataFeedResponse = await dataFeedContract.latestRoundData()
```
In this example, the contract returns an `int256` value. Encode the value so request.js can properly decode it.
```javascript
return Functions.encodeInt256(dataFeedResponse.answer)
```
#### request.js
This explanation focuses on the [request.js](https://github.com/smartcontractkit/smart-contract-examples/blob/main/functions-examples/examples/11-package-imports/request.js) script and shows how to use the [Chainlink Functions NPM package](https://github.com/smartcontractkit/functions-toolkit) in your own JavaScript/TypeScript project to send requests to a DON. The code is self-explanatory and has comments to help you understand all the steps.
The script imports:
- [path](https://nodejs.org/docs/latest/api/path.html) and [fs](https://nodejs.org/api/fs.html) : Used to read the [source file](https://github.com/smartcontractkit/smart-contract-examples/blob/main/functions-examples/examples/11-package-imports/source.js).
- [ethers](https://docs.ethers.org/v5/): Ethers.js library, enables the script to interact with the blockchain.
- `@chainlink/functions-toolkit`: Chainlink Functions NPM package. All its utilities are documented in the [NPM README](https://github.com/smartcontractkit/functions-toolkit/blob/main/README.md).
- `@chainlink/env-enc`: A tool for loading and storing encrypted environment variables. Read the [official documentation](https://www.npmjs.com/package/@chainlink/env-enc) to learn more.
- `../abi/functionsClient.json`: The abi of the contract your script will interact with. **Note**: The script was tested with this [FunctionsConsumerExample contract](https://remix.ethereum.org/#url=https://docs.chain.link/samples/ChainlinkFunctions/FunctionsConsumerExample.sol).
The script has two hardcoded values that you have to change using your own Functions consumer contract and subscription ID:
```javascript
const consumerAddress = "0x91257aa1c6b7f382759c357fbc53c565c80f7fee" // REPLACE this with your Functions consumer address
const subscriptionId = 38 // REPLACE this with your subscription ID
```
The primary function that the script executes is `makeRequestSepolia`. This function consists of five main parts:
1. Definition of necessary identifiers:
- `routerAddress`: Chainlink Functions router address on the Sepolia testnet.
- `donId`: Identifier of the DON that will fulfill your requests on the Sepolia testnet.
- `explorerUrl`: Block explorer URL of the Sepolia testnet.
- `source`: The source code must be a string object. That's why we use `fs.readFileSync` to read `source.js` and then call `toString()` to get the content as a `string` object.
- `args`: During the execution of your function, these arguments are passed to the source code.
- `gasLimit`: Maximum gas that Chainlink Functions can use when transmitting the response to your contract.
- Initialization of ethers `signer` and `provider` objects. The signer is used to make transactions on the blockchain, and the provider reads data from the blockchain.
2. Simulating your request in a local sandbox environment:
- Use `simulateScript` from the Chainlink Functions NPM package.
- Read the `response` of the simulation. If successful, use the Functions NPM package `decodeResult` function and `ReturnType` enum to decode the response to the expected returned type (`ReturnType.int256` in this example).
3. Estimating the costs:
- Initialize a `SubscriptionManager` from the Functions NPM package, then call the `estimateFunctionsRequestCost`.
- The response is returned in Juels (1 LINK = 10\*\*18 Juels). Use the `ethers.utils.formatEther` utility function to convert the output to LINK.
4. Making a Chainlink Functions request:
- Initialize your functions consumer contract using the contract address, abi, and ethers signer.
- Call the `sendRequest` function of your consumer contract.
5. Waiting for the response:
- Initialize a `ResponseListener` from the Functions NPM package and then call the `listenForResponseFromTransaction` function to wait for a response. By default, this function waits for five minutes.
- Upon reception of the response, use the Functions NPM package `decodeResult` function and `ReturnType` enum to decode the response to the expected returned type (`ReturnType.int256` in this example).
---
# Chainlink Functions Tutorials
Source: https://docs.chain.link/chainlink-functions/tutorials
## Topics
- [Simple Computation](/chainlink-functions/tutorials/simple-computation)
- [Call an API](/chainlink-functions/tutorials/api-query-parameters)
- [POST Data to an API](/chainlink-functions/tutorials/api-post-data)
- [Using DON-hosted Secrets in Requests](/chainlink-functions/tutorials/api-use-secrets)
- [Using Imports with Functions](/chainlink-functions/tutorials/importing-packages)
- [Use ABI encoding and decoding](/chainlink-functions/tutorials/abi-decoding)
- [Using User-hosted (gist) Secrets in Requests](/chainlink-functions/tutorials/api-use-secrets-gist)
- [Using User-hosted Secrets in Requests](/chainlink-functions/tutorials/api-use-secrets-offchain)
- [Call Multiple Data Sources](/chainlink-functions/tutorials/api-multiple-calls)
- [Encode request data offchain](/chainlink-functions/tutorials/encode-request-offchain)
- [Automate your Functions (Time-based Automation)](/chainlink-functions/tutorials/automate-functions)
- [Automate your Functions (Custom Logic Automation)](/chainlink-functions/tutorials/automate-functions-custom-logic)
---
# Request Computation
Source: https://docs.chain.link/chainlink-functions/tutorials/simple-computation
This tutorial shows you how to run computations on the Chainlink Functions Decentralized Oracle Network (DON). The example code computes the [geometric mean](https://www.mathsisfun.com/numbers/geometric-mean.html) of numbers in a list. After [OCR](/chainlink-functions/resources/concepts) completes offchain computation and aggregation, it returns the result to your smart contract.
## Tutorial
This tutorial is configured to get the average (geometric mean) from a list of numbers `1,2,3,4,5,6,7,8,9,10`. Read the [Examine the code](#examine-the-code) section for a detailed description of the code example.
You can locate the scripts used in this tutorial in the [*examples/1-simple-computation* directory](https://github.com/smartcontractkit/smart-contract-examples/tree/main/functions-examples/examples/1-simple-computation).
To run the example:
1. Open the file `request.js`, which is located in the `1-simple-computation` folder.
2. Replace the consumer contract address and the subscription ID with your own values.
```javascript
const consumerAddress = "0x8dFf78B7EE3128D00E90611FBeD20A71397064D9" // REPLACE this with your Functions consumer address
const subscriptionId = 3 // REPLACE this with your subscription ID
```
3. Make a request:
```shell
node examples/1-simple-computation/request.js
```
The script runs your function in a sandbox environment before making an onchain transaction:
```text
$ node examples/1-simple-computation/request.js
secp256k1 unavailable, reverting to browser version
Start simulation...
Simulation result {
capturedTerminalOutput: 'calculate geometric mean of 1,2,3,4,5,6,7,8,9,10\ngeometric mean is: 4.53\n',
responseBytesHexstring: '0x00000000000000000000000000000000000000000000000000000000000001c5'
}
✅ Decoded response to uint256: 453n
Estimate request costs...
Fulfillment cost estimated to 1.004325887213695 LINK
Make request...
✅ Functions request sent! Transaction hash 0x7df8240d23ef5c951ea73634b2346a459c8cd5b9a0bf76dbe0bb4d912e099b22. Waiting for a response...
See your request in the explorer https://sepolia.etherscan.io/tx/0x7df8240d23ef5c951ea73634b2346a459c8cd5b9a0bf76dbe0bb4d912e099b22
✅ Request 0x91a72a36a94ddedfc9e7bcfe33aaa13dd5747c4e985d9baa8c0c34175ac6c715 successfully fulfilled. Cost is 0.240613623834519812 LINK.Complete response: {
requestId: '0x91a72a36a94ddedfc9e7bcfe33aaa13dd5747c4e985d9baa8c0c34175ac6c715',
subscriptionId: 2303,
totalCostInJuels: 240613623834519812n,
responseBytesHexstring: '0x00000000000000000000000000000000000000000000000000000000000001c5',
errorString: '',
returnDataBytesHexstring: '0x',
fulfillmentCode: 0
}
✅ Decoded response to uint256: 453n
```
The output of the example gives you the following information:
- Your request is first run on a sandbox environment to ensure it is correctly configured.
- The fulfillment costs are estimated before making the request.
- Your request was successfully sent to Chainlink Functions. The transaction in this example is [0x7df8240d23ef5c951ea73634b2346a459c8cd5b9a0bf76dbe0bb4d912e099b22](https://sepolia.etherscan.io/tx/0x7df8240d23ef5c951ea73634b2346a459c8cd5b9a0bf76dbe0bb4d912e099b22) and the request ID is `0x91a72a36a94ddedfc9e7bcfe33aaa13dd5747c4e985d9baa8c0c34175ac6c715`.
- The DON successfully fulfilled your request. The total cost was: `0.240613623834519812 LINK`.
- The consumer contract received a response in `bytes` with a value of `0x00000000000000000000000000000000000000000000000000000000000001c5`. Decoding it offchain to `uint256` gives you a result: `453`.
## Examine the code
### FunctionsConsumerExample.sol
### JavaScript example
#### source.js
The Decentralized Oracle Network will run the [JavaScript code](https://github.com/smartcontractkit/smart-contract-examples/blob/main/functions-examples/examples/1-simple-computation/source.js). The code is self-explanatory and has comments to help you understand all the steps.
The main steps are:
- Read the numbers provided as arguments in the `args` setting. Because `args` is an array of `string`, call `parseInt` to convert from `string` to `number`. **Note**: `args` contains string values that are injected into the JavaScript source code when the Decentralized Oracle Network executes your function. You can access theses values from your JavaScript code using the name `args`.
- Calculate the average (geometric mean): First, compute the product of the numbers. Then, calculate the nth root of the product where `n` is the length of `args`.
- Return the result as a [buffer](https://nodejs.org/api/buffer.html#buffer) using the `Functions.encodeUint256` helper function. Because Solidity doesn't support decimals, multiply the result by `100` and round the result to the nearest integer. There are other helper functions that you could use depending on the response type:
- `Functions.encodeUint256`: Takes a positive JavaScript integer number and returns a Buffer of 32 bytes representing a uint256 type in Solidity.
- `Functions.encodeInt256`: Takes a JavaScript integer number and returns a Buffer of 32 bytes representing an int256 type in Solidity.
- `Functions.encodeString`: Takes a JavaScript string and returns a Buffer representing a string type in Solidity.
**Note**: You are not required to use these encoding functions as long as the JavaScript code returns a Buffer representing the bytes array returned onchain. Read this [article](https://www.freecodecamp.org/news/do-you-want-a-better-understanding-of-buffer-in-node-js-check-this-out-2e29de2968e8/) if you are new to Javascript Buffers and want to understand why they are important.
#### request.js
This explanation focuses on the [request.js](https://github.com/smartcontractkit/smart-contract-examples/blob/main/functions-examples/examples/1-simple-computation/request.js) script and shows how to use the [Chainlink Functions NPM package](https://github.com/smartcontractkit/functions-toolkit) in your own JavaScript/TypeScript project to send requests to a DON. The code is self-explanatory and has comments to help you understand all the steps.
The script imports:
- [path](https://nodejs.org/docs/latest/api/path.html) and [fs](https://nodejs.org/api/fs.html) : Used to read the [source file](https://github.com/smartcontractkit/smart-contract-examples/blob/main/functions-examples/examples/1-simple-computation/source.js).
- [ethers](https://docs.ethers.org/v5/): Ethers.js library, enables the script to interact with the blockchain.
- `@chainlink/functions-toolkit`: Chainlink Functions NPM package. All its utilities are documented in the [NPM README](https://github.com/smartcontractkit/functions-toolkit/blob/main/README.md).
- `@chainlink/env-enc`: A tool for loading and storing encrypted environment variables. Read the [official documentation](https://www.npmjs.com/package/@chainlink/env-enc) to learn more.
- `../abi/functionsClient.json`: The abi of the contract your script will interact with. **Note**: The script was tested with this [FunctionsConsumerExample contract](https://remix.ethereum.org/#url=https://docs.chain.link/samples/ChainlinkFunctions/FunctionsConsumerExample.sol).
The script has two hardcoded values that you have to change using your own Functions consumer contract and subscription ID:
```javascript
const consumerAddress = "0x8dFf78B7EE3128D00E90611FBeD20A71397064D9" // REPLACE this with your Functions consumer address
const subscriptionId = 3 // REPLACE this with your subscription ID
```
The primary function that the script executes is `makeRequestSepolia`. This function consists of five main parts:
1. Definition of necessary identifiers:
- `routerAddress`: Chainlink Functions router address on the Sepolia testnet.
- `donId`: Identifier of the DON that will fulfill your requests on the Sepolia testnet.
- `explorerUrl`: Block explorer URL of the Sepolia testnet.
- `source`: The source code must be a string object. That's why we use `fs.readFileSync` to read `source.js` and then call `toString()` to get the content as a `string` object.
- `args`: During the execution of your function, These arguments are passed to the source code.
- `gasLimit`: Maximum gas that Chainlink Functions can use when transmitting the response to your contract.
- Initialization of ethers `signer` and `provider` objects. The signer is used to make transactions on the blockchain, and the provider reads data from the blockchain.
2. Simulating your request in a local sandbox environment:
- Use `simulateScript` from the Chainlink Functions NPM package.
- Read the `response` of the simulation. If successful, use the Functions NPM package `decodeResult` function and `ReturnType` enum to decode the response to the expected returned type (`ReturnType.uint256` in this example).
3. Estimating the costs:
- Initialize a `SubscriptionManager` from the Functions NPM package, then call the `estimateFunctionsRequestCost`.
- The response is returned in Juels (1 LINK = 10\*\*18 Juels). Use the `ethers.utils.formatEther` utility function to convert the output to LINK.
4. Making a Chainlink Functions request:
- Initialize your functions consumer contract using the contract address, abi, and ethers signer.
- Call the `sendRequest` function of your consumer contract.
5. Waiting for the response:
- Initialize a `ResponseListener` from the Functions NPM package and then call the `listenForResponseFromTransaction` function to wait for a response. By default, this function waits for five minutes.
- Upon reception of the response, use the Functions NPM package `decodeResult` function and `ReturnType` enum to decode the response to the expected returned type (`ReturnType.uint256` in this example).