chainlink

Chainlink

|Functions Demo

Retrieve Web2 data and store it on-chain using Chainlink Functions.

Perform custom computation off-chain using Web2 data in your smart contract.

dev-expert

Choose an API

@

Under the Hood

1// SPDX-License-Identifier: MIT
2pragma solidity ^0.8.19;
3
4import {FunctionsClient} from "@chainlink/contracts/src/v0.8/functions/dev/v1_0_0/FunctionsClient.sol";
5import {ConfirmedOwner} from "@chainlink/contracts/src/v0.8/shared/access/ConfirmedOwner.sol";
6import {FunctionsRequest} from "@chainlink/contracts/src/v0.8/functions/dev/v1_0_0/libraries/FunctionsRequest.sol";
7
8/**
9 * @title Chainlink Functions example consuming weather data
10 */
11contract XUserDataConsumer is FunctionsClient, ConfirmedOwner {
12  using FunctionsRequest for FunctionsRequest.Request;
13
14  enum ResponseType {
15    UserInfo,
16    UserLastTweet
17  }
18
19  struct APIResponse {
20    ResponseType responseType;
21    string response;
22  }
23
24  // Chainlink Functions script soruce code
25  string private constant SOURCE_USERNAME_INFO =
26    "const username = args[0];"
27    "if(!secrets.xBearerToken) {"
28    "throw Error('No bearer token');"
29    "}"
30    "const xUserResponse = await Functions.makeHttpRequest({"
31    "url: `https://api.twitter.com/2/users/by/username/${username}?user.fields=profile_image_url`,"
32    "headers: { Authorization: `Bearer ${secrets.xBearerToken}` },"
33    "});"
34    "if (xUserResponse.error) {"
35    "throw Error(`X User Request Error`);"
36    "}"
37    "const { name, id } = xUserResponse.data.data;"
38    "return Functions.encodeString([name, id]);";
39
40  string private constant SOURCE_LAST_TWEET_INFO =
41    "const id = args[0];"
42    "if (!secrets.xBearerToken) {"
43    "throw Error('No bearer token');"
44    "}"
45    "const xTweetsResponse = await Functions.makeHttpRequest({"
46    "url: `https://api.twitter.com/2/users/${id}/tweets`,"
47    "headers: { Authorization: `Bearer ${secrets.xBearerToken}` },"
48    "});"
49    "if (xTweetsResponse.error) {"
50    "throw Error('X User Request Error');"
51    "}"
52    "const lastTweet = xTweetsResponse.data.data[0].text;"
53    "const shortenedTweet = lastTweet.substring(0, 255);"
54    "return Functions.encodeString(shortenedTweet);";
55
56  bytes32 public donId; // DON ID for the Functions DON to which the requests are sent
57  uint64 private subscriptionId; // Subscription ID for the Chainlink Functions
58  uint32 private gasLimit; // Gas limit for the Chainlink Functions callbacks
59
60  // Mapping of request IDs to weather info
61  mapping(bytes32 => APIResponse) public requests;
62
63  event UserInfoRequested(bytes32 indexed requestId, string username);
64  event UserInfoReceived(bytes32 indexed requestId, string response);
65  event UserLastTweetRequested(bytes32 indexed requestId, string username);
66  event UserLastTweetReceived(bytes32 indexed requestId, string response);
67  event RequestFailed(bytes error);
68
69  constructor(
70    address router,
71    bytes32 _donId,
72    uint64 _subscriptionId,
73    uint32 _gasLimit
74  ) FunctionsClient(router) ConfirmedOwner(msg.sender) {
75    donId = _donId;
76    subscriptionId = _subscriptionId;
77    gasLimit = _gasLimit;
78  }
79
80  /**
81   * @notice Request X profile information for provided handle
82   * @param username username of said user e.g. chainlink
83   * @param slotId the location of the DON-hosted secrets
84   * @param version the version of the secret to be used
85   */
86  function requestUserInfo(string calldata username, uint8 slotId, uint64 version) external {
87    string[] memory args = new string[](1);
88    args[0] = username;
89    bytes32 requestId = _sendRequest(SOURCE_USERNAME_INFO, args, slotId, version);
90
91    requests[requestId].responseType = ResponseType.UserInfo;
92    emit UserInfoRequested(requestId, username);
93  }
94
95  /**
96   * @notice Request last post for given username
97   * @param userId username of said user e.g. chainlink
98   * @param slotId the location of the DON-hosted secrets
99   * @param version the version of the secret to be used
100   */
101  function requestLastTweet(string calldata userId, uint8 slotId, uint64 version) external {
102    string[] memory args = new string[](1);
103    args[0] = userId;
104    bytes32 requestId = _sendRequest(SOURCE_LAST_TWEET_INFO, args, slotId, version);
105
106    requests[requestId].responseType = ResponseType.UserLastTweet;
107    emit UserLastTweetRequested(requestId, userId);
108  }
109
110  /**
111   * @notice Process the response from the executed Chainlink Functions script
112   * @param requestId The request ID
113   * @param response The response from the Chainlink Functions script
114   */
115  function _processResponse(bytes32 requestId, bytes memory response) private {
116    requests[requestId].response = string(response);
117    if (requests[requestId].responseType == ResponseType.UserInfo) {
118      emit UserInfoReceived(requestId, string(response));
119    } else {
120      emit UserLastTweetReceived(requestId, string(response));
121    }
122  }
123
124  // CHAINLINK FUNCTIONS
125
126  /**
127   * @notice Triggers an on-demand Functions request
128   * @param args String arguments passed into the source code and accessible via the global variable `args`
129   * @param slotId the location of the DON-hosted secrets
130   * @param version the version of the secret to be used
131   */
132  function _sendRequest(
133    string memory source,
134    string[] memory args,
135    uint8 slotId,
136    uint64 version
137  ) internal returns (bytes32 requestId) {
138    FunctionsRequest.Request memory req;
139    req.initializeRequest(FunctionsRequest.Location.Inline, FunctionsRequest.CodeLanguage.JavaScript, source);
140    req.addDONHostedSecrets(slotId, version);
141    if (args.length > 0) {
142      req.setArgs(args);
143    }
144    requestId = _sendRequest(req.encodeCBOR(), subscriptionId, gasLimit, donId);
145  }
146
147  /**
148   * @notice Fulfillment callback function
149   * @param requestId The request ID, returned by sendRequest()
150   * @param response Aggregated response from the user code
151   * @param err Aggregated error from the user code or from the execution pipeline
152   * Either response or error parameter will be set, but never both
153   */
154  function fulfillRequest(bytes32 requestId, bytes memory response, bytes memory err) internal override {
155    if (err.length > 0) {
156      emit RequestFailed(err);
157      return;
158    }
159    _processResponse(requestId, response);
160  }
161
162  // OWNER
163
164  /**
165   * @notice Set the DON ID
166   * @param newDonId New DON ID
167   */
168  function setDonId(bytes32 newDonId) external onlyOwner {
169    donId = newDonId;
170  }
171}
172

Recent Requests

https://pbs.twimg.com/profile_images/1030475757892579334/qvSHhRyC_normal.jpg
Chainlink@chainlink

🏗️ #ChainlinkBUILD 🏗️

@DBOE_Official is joining Chainlink BUILD to gain enhanced access to Chainlink's...

https://pbs.twimg.com/profile_images/640370583/nola_normal.jpg
Đulijano Nola@micronola

Naš as Vilibald postao agent za nekretnine https://t.co/3m5eSToCti

https://pbs.twimg.com/profile_images/640370583/nola_normal.jpg
Đulijano Nola@micronola

Naš as Vilibald postao agent za nekretnine https://t.co/3m5eSToCti

https://pbs.twimg.com/profile_images/1575210660320772097/nqrmOIc5_normal.jpg
Nav@3drockz

@tboypod Why haven't you added a newsletter signup on your homepage yet?

https://pbs.twimg.com/profile_images/640370583/nola_normal.jpg
Đulijano Nola@micronola

VELEBIT!

https://pbs.twimg.com/profile_images/640370583/nola_normal.jpg
Đulijano Nola@micronola

VELEBIT!

https://pbs.twimg.com/profile_images/640370583/nola_normal.jpg
Đulijano Nola@micronola

VELEBIT!

https://pbs.twimg.com/profile_images/1748153260203229184/sXJIGMBk_normal.jpg
vitalik.eth@vitalikbuterin

@yumatrades I don't think I ever endorsed friendtech?

https://pbs.twimg.com/profile_images/640370583/nola_normal.jpg
Đulijano Nola@micronola

@drazendrnas Kupuješ gitaru?

https://pbs.twimg.com/profile_images/640370583/nola_normal.jpg
Đulijano Nola@micronola

Vitalik je jedan od razloga zašto sam opimist kad je u pitanju budućnost crypta premda se od 2017 od kada...