-
Notifications
You must be signed in to change notification settings - Fork 477
Expand file tree
/
Copy pathllms-full.txt
More file actions
5034 lines (3602 loc) · 321 KB
/
Copy pathllms-full.txt
File metadata and controls
5034 lines (3602 loc) · 321 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
# FunctionsClient API Reference
Source: https://docs.chain.link/chainlink-functions/api-reference/functions-client
<ChainlinkFunctions callout="shutdown" />
<Aside type="note" title="Add Chainlink to your project">
If you need to integrate Chainlink into your project, install the [@chainlink/contracts NPM package](https://www.npmjs.com/package/@chainlink/contracts).
- If you use [NPM](https://www.npmjs.com/): npm install @chainlink/contracts --save
- If you use [Yarn](https://yarnpkg.com/): yarn add @chainlink/contracts
Functions contracts are available starting from version *0.7.1*.
</Aside>
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
<ChainlinkFunctions callout="shutdown" />
<Aside type="note" title="Add Chainlink to your project">
If you need to integrate Chainlink into your project, install the [@chainlink/contracts NPM package](https://www.npmjs.com/package/@chainlink/contracts).
- If you use [NPM](https://www.npmjs.com/): npm install @chainlink/contracts --save
- If you use [Yarn](https://yarnpkg.com/): yarn add @chainlink/contracts
Functions contracts are available starting from version *0.7.1*.
</Aside>
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
<ChainlinkFunctions callout="shutdown" />
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
<ChainlinkFunctions callout="shutdown" />
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.
```javascript
const characterId = args[0];
const apiResponse = await Functions.makeHttpRequest({
url: `https://swapi.info/api/people/${characterId}/`,
});
if (apiResponse.error) {
throw Error("Request failed");
}
const { data } = apiResponse;
return Functions.encodeString(data.name);
```
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.
```sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
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";
import {ConfirmedOwner} from "@chainlink/contracts/src/v0.8/shared/access/ConfirmedOwner.sol";
/**
* Request testnet LINK and ETH here: https://faucets.chain.link/
* Find information on LINK Token Contracts and get the latest ETH and LINK faucets here:
* https://docs.chain.link/resources/link-token-contracts/
*/
/**
* @title GettingStartedFunctionsConsumer
* @notice This is an example contract to show how to make HTTP requests using Chainlink
* @dev This contract uses hardcoded values and should not be used in production.
*/
contract GettingStartedFunctionsConsumer is FunctionsClient, ConfirmedOwner {
using FunctionsRequest for FunctionsRequest.Request;
// State variables to store the last request ID, response, and error
bytes32 public s_lastRequestId;
bytes public s_lastResponse;
bytes public s_lastError;
// Custom error type
error UnexpectedRequestID(bytes32 requestId);
// Event to log responses
event Response(bytes32 indexed requestId, string character, bytes response, bytes err);
// Router address - Hardcoded for Sepolia
// Check to get the router address for your supported network
// https://docs.chain.link/chainlink-functions/supported-networks
address router = 0xb83E47C2bC239B3bf370bc41e1459A34b41238D0;
// JavaScript source code
// Fetch character name from the Star Wars API.
// Documentation: https://swapi.info/people
string source = "const characterId = args[0];" "const apiResponse = await Functions.makeHttpRequest({"
"url: `https://swapi.info/api/people/${characterId}/`" "});" "if (apiResponse.error) {"
"throw Error('Request failed');" "}" "const { data } = apiResponse;" "return Functions.encodeString(data.name);";
//Callback gas limit
uint32 gasLimit = 300_000;
// donID - Hardcoded for Sepolia
// Check to get the donID for your supported network https://docs.chain.link/chainlink-functions/supported-networks
bytes32 donID = 0x66756e2d657468657265756d2d7365706f6c69612d3100000000000000000000;
// State variable to store the returned character information
string public character;
/**
* @notice Initializes the contract with the Chainlink router address and sets the contract owner
*/
constructor() FunctionsClient(router) ConfirmedOwner(msg.sender) {}
/**
* @notice Sends an HTTP request for character information
* @param subscriptionId The ID for the Chainlink subscription
* @param args The arguments to pass to the HTTP request
* @return requestId The ID of the request
*/
function sendRequest(
uint64 subscriptionId,
string[] calldata args
) external onlyOwner returns (bytes32 requestId) {
FunctionsRequest.Request memory req;
req.initializeRequestForInlineJavaScript(source); // Initialize the request with JS code
if (args.length > 0) req.setArgs(args); // Set the arguments for the request
// Send the request and store the request ID
s_lastRequestId = _sendRequest(req.encodeCBOR(), subscriptionId, gasLimit, donID);
return s_lastRequestId;
}
/**
* @notice Callback function for fulfilling a request
* @param requestId The ID of the request to fulfill
* @param response The HTTP response data
* @param err Any errors from the Functions request
*/
function fulfillRequest(
bytes32 requestId,
bytes memory response,
bytes memory err
) internal override {
if (s_lastRequestId != requestId) {
revert UnexpectedRequestID(requestId); // Check if request IDs match
}
// Update the contract's state variables with the response and any errors
s_lastResponse = response;
character = string(response);
s_lastError = err;
// Emit an event to log the response
emit Response(requestId, character, s_lastResponse, s_lastError);
}
}
```
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:
<ClickToZoom src="/images/chainlink-functions/tutorials/subscription/sign-message-tos-metamask.jpg" alt="Chainlink Functions sign message ToS MetaMask" style="max-width: 70%;" />
### 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.
<ClickToZoom src="/images/chainlink-functions/tutorials/subscription/subscription-created-add-consumer-2.jpg" alt="Chainlink Functions subscription add consumer" style="max-width: 70%;" />
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
```sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
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";
import {ConfirmedOwner} from "@chainlink/contracts/src/v0.8/shared/access/ConfirmedOwner.sol";
/**
* Request testnet LINK and ETH here: https://faucets.chain.link/
* Find information on LINK Token Contracts and get the latest ETH and LINK faucets here:
* https://docs.chain.link/resources/link-token-contracts/
*/
/**
* @title GettingStartedFunctionsConsumer
* @notice This is an example contract to show how to make HTTP requests using Chainlink
* @dev This contract uses hardcoded values and should not be used in production.
*/
contract GettingStartedFunctionsConsumer is FunctionsClient, ConfirmedOwner {
using FunctionsRequest for FunctionsRequest.Request;
// State variables to store the last request ID, response, and error
bytes32 public s_lastRequestId;
bytes public s_lastResponse;
bytes public s_lastError;
// Custom error type
error UnexpectedRequestID(bytes32 requestId);
// Event to log responses
event Response(bytes32 indexed requestId, string character, bytes response, bytes err);
// Router address - Hardcoded for Sepolia
// Check to get the router address for your supported network
// https://docs.chain.link/chainlink-functions/supported-networks
address router = 0xb83E47C2bC239B3bf370bc41e1459A34b41238D0;
// JavaScript source code
// Fetch character name from the Star Wars API.
// Documentation: https://swapi.info/people
string source = "const characterId = args[0];" "const apiResponse = await Functions.makeHttpRequest({"
"url: `https://swapi.info/api/people/${characterId}/`" "});" "if (apiResponse.error) {"
"throw Error('Request failed');" "}" "const { data } = apiResponse;" "return Functions.encodeString(data.name);";
//Callback gas limit
uint32 gasLimit = 300_000;
// donID - Hardcoded for Sepolia
// Check to get the donID for your supported network https://docs.chain.link/chainlink-functions/supported-networks
bytes32 donID = 0x66756e2d657468657265756d2d7365706f6c69612d3100000000000000000000;
// State variable to store the returned character information
string public character;
/**
* @notice Initializes the contract with the Chainlink router address and sets the contract owner
*/
constructor() FunctionsClient(router) ConfirmedOwner(msg.sender) {}
/**
* @notice Sends an HTTP request for character information
* @param subscriptionId The ID for the Chainlink subscription
* @param args The arguments to pass to the HTTP request
* @return requestId The ID of the request
*/
function sendRequest(
uint64 subscriptionId,
string[] calldata args
) external onlyOwner returns (bytes32 requestId) {
FunctionsRequest.Request memory req;
req.initializeRequestForInlineJavaScript(source); // Initialize the request with JS code
if (args.length > 0) req.setArgs(args); // Set the arguments for the request
// Send the request and store the request ID
s_lastRequestId = _sendRequest(req.encodeCBOR(), subscriptionId, gasLimit, donID);
return s_lastRequestId;
}
/**
* @notice Callback function for fulfilling a request
* @param requestId The ID of the request to fulfill
* @param response The HTTP response data
* @param err Any errors from the Functions request
*/
function fulfillRequest(
bytes32 requestId,
bytes memory response,
bytes memory err
) internal override {
if (s_lastRequestId != requestId) {
revert UnexpectedRequestID(requestId); // Check if request IDs match
}
// Update the contract's state variables with the response and any errors
s_lastResponse = response;
character = string(response);
s_lastError = err;
// Emit an event to log the response
emit Response(requestId, character, s_lastResponse, s_lastError);
}
}
```
- 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
```javascript
const characterId = args[0];
const apiResponse = await Functions.makeHttpRequest({
url: `https://swapi.info/api/people/${characterId}/`,
});
if (apiResponse.error) {
throw Error("Request failed");
}
const { data } = apiResponse;
return Functions.encodeString(data.name);
```
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.
---
# Cancel a Subscription and Withdraw Funds
Source: https://docs.chain.link/chainlink-functions/guides/cancel-subscription
<ChainlinkFunctions callout="shutdown" />
Cancelling a Chainlink Functions subscription and withdrawing its remaining LINK balance is a single onchain transaction: calling `cancelSubscription` deletes the subscription, removes all associated consumers, and transfers the remaining balance in one call. Only the subscription owner can perform this action.
## Prerequisites
- **Your Subscription ID.** If you don't know it, see [Find your Subscription ID](#find-your-subscription-id) below.
- **The FunctionsRouter address** for the network your subscription is on. Find it in the [Supported Networks](/chainlink-functions/supported-networks) reference.
- **No in-flight requests.** A subscription cannot be canceled while it has pending requests. Any request that has been pending for longer than five minutes must first be [timed out](/chainlink-functions/resources/subscriptions#time-out-pending-requests-manually).
- **A wallet you can sign transactions with** using the subscription owner address. The examples below use [Foundry's `cast`](https://getfoundry.sh/cast/overview) with a raw private key, but you can substitute a keystore or Ledger. See [Sending Transactions](https://www.getfoundry.sh/cast/sending-transactions) in the Foundry docs for the equivalent `--account` or `--ledger` flags.
## Find your Subscription ID
If you already know your Subscription ID, skip to [Cancel the subscription and withdraw funds](#cancel-the-subscription-and-withdraw-funds).
- **Using the Subscription Manager:** Go to the [Chainlink Functions Subscription Manager](https://functions.chain.link/), connect the owner wallet, and open the subscription under **My Subscriptions**. The Subscription ID is shown on the subscription's detail page.
- **Using the lookup tool below:** If you no longer have access to the owner wallet's session or the subscription isn't showing in the app, enter your owner address to find its Subscription IDs.
This tool searches the same data published in the [Chainlink Functions Subscription ID Registry](https://docs.google.com/spreadsheets/d/1X33O8ra6lwhhFKV7o3Ut-dOq8pXVAyb6gcHlXOtYmUA/edit?gid=1541416076#gid=1541416076) spreadsheet.
## Cancel the subscription and withdraw funds
Call `cancelSubscription` on the FunctionsRouter contract, passing your Subscription ID and the address that should receive the remaining LINK balance:
```shell
cast send FUNCTIONS_ROUTER_ADDRESS \
"cancelSubscription(uint64,address)" \
SUBSCRIPTION_ID \
TO_ADDRESS \
--rpc-url $CHAIN_RPC_URL \
--private-key $PRIVATE_KEY
```
Where:
- `FUNCTIONS_ROUTER_ADDRESS` is the address of the FunctionsRouter contract for your network.
- `SUBSCRIPTION_ID` is your numerical Subscription ID.
- `TO_ADDRESS` is the wallet address that should receive the withdrawn LINK.
- `CHAIN_RPC_URL` is the HTTP RPC URL for your network.
<Aside type="note" title="Cancellation fee">
If your subscription has not spent enough in fees to clear the request threshold for your network, a cancellation fee
is deducted from its balance before the remainder is sent to `TO_ADDRESS`. See [Supported
Networks](/chainlink-functions/supported-networks) for the cancellation fee on each network.
</Aside>
Once this transaction confirms, the Subscription ID is deleted, all consumers are removed, and the remaining LINK balance is transferred to `TO_ADDRESS`.
---
# Chainlink Functions
Source: https://docs.chain.link/chainlink-functions
<ChainlinkFunctions callout="shutdown" />
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
<Aside type="note">
Chainlink Functions is a self-service solution. You are responsible for independently reviewing any code and API dependencies that you submit in a request. Community-created code examples might not be audited, so you must independently review this code before you use it.
Chainlink Functions is offered "as is" and "as available" without conditions or warranties of any kind. Neither Chainlink Labs, the Chainlink Foundation, nor Chainlink node operators are responsible for unintended outputs from Functions due to issues in your code or downstream issues with API dependencies. You must ensure that the data sources or APIs specified in requests are of sufficient quality and have the proper availability for your use case. Users are responsible for complying with the licensing agreements for all data providers that they connect with through Chainlink Functions. Violations of data provider licensing agreements or the [terms](https://chain.link/terms) can result in suspension or termination of your Chainlink Functions account or subscription.
</Aside>
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
<ChainlinkFunctions callout="shutdown" />
<Aside type="note" title="Prerequisites">
Read the Chainlink Functions [introduction](/chainlink-functions) to understand all the concepts discussed on this
page.
</Aside>
## 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.