Skip to content

Commit 77cb864

Browse files
authored
Merge pull request #347 from LIT-Protocol/andrew/fetch-in-la
fetch-in-lit-action Docs Update
2 parents 53c5ac3 + bd5990f commit 77cb864

1 file changed

Lines changed: 40 additions & 90 deletions

File tree

docs/sdk/serverless-signing/fetch.md

Lines changed: 40 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -3,119 +3,69 @@ import FeedbackComponent from "@site/src/pages/feedback.md";
33
import Tabs from '@theme/Tabs';
44
import TabItem from '@theme/TabItem';
55

6-
# Using Fetch
7-
8-
## Prerequisites
9-
10-
- Familiarity with JavaScript
11-
- Basic understanding of [serverless signing](../serverless-signing/quick-start.md)
6+
# Fetching Data from the Web within a Lit Action
127

138
## Overview
14-
Unlike traditional smart contract ecosystems, Lit Actions can natively talk to the external world. This is useful for things like fetching data from the web, or sending API requests to other services.
159

16-
The Lit Action below will get the current temperature from the [National Weather Service](https://www.weather.gov/) API, and ONLY sign a txn if the temperature is forecast to be **above 60 degrees F**. Since you can put this HTTP request and logic that uses the response directly in your Lit Action, you don't have to worry about using a 3rd party oracle to pull data in.
10+
Unlike traditional smart contract ecosystems, Lit Actions can natively talk to the external world. This is useful for things like fetching data from the web, or sending API requests to other services.
1711

18-
### How it works
12+
This Lit Action fetches the current temperature from the [National Weather Service](https://www.weather.gov/) API. It will only sign the given message if the temperature forecast exceeds 60°F (15.5°C). By incorporating the API request and response logic directly within the Lit Action, you eliminate the need for a third-party oracle.
1913

20-
The HTTP request will be sent out by all the Lit Nodes in parallel, and consensus is based on at least 2/3 of the nodes getting the same response. If less than 2/3 nodes get the same response, then the user can not collect the signature shares above the threshold and therefore cannot produce the final signature. Note that your HTTP request will be sent N times where N is the number of nodes in the Lit Network, because it's sent from every Lit Node in parallel.
14+
## Prerequisites
2115

22-
Be careful about how many requests you're making and note that this may trigger rate limiting issues on some servers.
16+
- Basic understanding of [PKPs](../../../user-wallets/pkps/overview)
17+
- Basic understanding of [Lit Actions](../serverless-signing/quick-start)
2318

24-
## Example
19+
## Complete Code Example
2520

26-
### Lit Action code
21+
The complete code example is available in the [Lit Developer Guides Code Repository](https://github.com/LIT-Protocol/developer-guides-code/tree/master/lit-action-using-fetch). There you can find a Node.js and browser implementation of this example code.
2722

28-
:::note
29-
`toSign` data is required to be in 32 byte format.
23+
### Example Lit Action
3024

31-
The `ethers.utils.arrayify(ethers.utils.keccak256(...)` can be used to convert the `toSign` data to the correct format.
32-
:::
25+
The `signEcdsa` function returns a boolean value stored in the `sigShare` variable. It's `true` if the message is successfully signed, and `false` if an error occurs during the Lit Action. If the temperature is below 60°F (15.5°C), the Lit Action will instead return a response message to the user.
3326

3427
```jsx
35-
const litActionCode = `
36-
const go = async () => {
37-
const url = "https://api.weather.gov/gridpoints/TOP/31,80/forecast";
38-
const resp = await fetch(url).then((response) => response.json());
39-
const temp = resp.properties.periods[0].temperature;
40-
41-
// only sign if the temperature is above 60. if it's below 60, exit.
42-
if (temp < 60) {
43-
return;
28+
const _litActionCode = async () => {
29+
try {
30+
const url = "https://api.weather.gov/gridpoints/TOP/31,80/forecast";
31+
const resp = await fetch(url).then((response) => response.json());
32+
const temp = resp.properties.periods[0].temperature;
33+
console.log("Current temperature from the API:", temp);
34+
35+
if (temp < 60) {
36+
Lit.Actions.setResponse({ response: "It's too cold to sign the message!" });
37+
return;
38+
}
39+
40+
const sigShare = await LitActions.signEcdsa({ toSign, publicKey, sigName });
41+
Lit.Actions.setResponse({ response: sigShare });
42+
} catch (error) {
43+
Lit.Actions.setResponse({ response: error.message });
4444
}
45-
46-
// this requests a signature share from the Lit Node
47-
// the signature share will be automatically returned in the HTTP response from the node
48-
// all the params (toSign, publicKey, sigName) are passed in from the LitJsSdk.executeJs() function
49-
const sigShare = await LitActions.signEcdsa({ toSign, publicKey , sigName });
5045
};
5146

52-
go();
53-
`;
47+
export const litActionCode = `(${_litActionCode.toString()})();`;
5448
```
5549

56-
### Execute Lit Action code on Lit nodes
50+
## Important Considerations
51+
You can use fetch() inside a Lit Action to write data, but caution is necessary. The HTTP request will execute multiple times, once for each Lit Node in the network.
52+
When writing data, it's crucial to use operations that produce the same result regardless of how often they're repeated. Consider these examples:
5753

58-
```jsx
59-
const runLitAction = async () => {
60-
const message = new Uint8Array(
61-
await crypto.subtle.digest('SHA-256', new TextEncoder().encode('Hello world'))
62-
);
63-
64-
const litNodeClient = new LitJsSdk.LitNodeClient({
65-
alertWhenUnauthorized: false,
66-
litNetwork: "datil-dev",
67-
debug: true,
68-
});
69-
await litNodeClient.connect();
70-
const signatures = await litNodeClient.executeJs({
71-
code: litActionCode,
72-
sessionSigs,
73-
// all jsParams can be used anywhere in your litActionCode
74-
jsParams: {
75-
toSign: message,
76-
publicKey:
77-
"0x02e5896d70c1bc4b4844458748fe0f936c7919d7968341e391fb6d82c258192e64",
78-
sigName: "sig1",
79-
},
80-
});
81-
console.log("signatures: ", signatures);
82-
};
83-
84-
runLitAction();
85-
```
54+
1. Repeatable operation (preferred):
8655

87-
## Using fetch() to write data
88-
You can also use fetch() inside a Lit Action to write data, but you **must be careful** (because the HTTP request will be run N times where N is the number of Lit Nodes). On Datil networks, N is 10, so any fetch() request will be sent to the server 10 times.
56+
- SQL Update: Running it multiple times only changes the row once.
57+
- Result: Consistent outcome, regardless of repetition.
8958

90-
**This is safe**, however, if the place you're writing the data to is *idempotent*. Idempotent means that applying the same operation over and over will not change the result. So for example, a SQL Insert is not idempotent, because if you run it 10 times, it will create 10 rows. On the other hand, a SQL Update is idempotent, because if you run it 10 times, it will only update the row once. So if you're using fetch() to write data, make sure the server you're writing to is idempotent.
59+
2. Non-repeatable operation (avoid):
9160

92-
### Lit Action code
61+
- SQL Insert: Each execution creates a new row.
62+
- Result: Unintended duplicates with multiple executions.
9363

94-
```jsx
95-
const runLitAction = async () => {
96-
if (day === "") {
97-
alert("Select a day first!");
98-
return;
99-
}
64+
For Lit Actions using fetch() to write data, aim for repeatable operations. This approach prevents issues like duplicate entries or unintended changes if the request repeats due to network conditions or distributed execution across nodes.
10065

101-
const litActionCode = `
102-
const fetchWeatherApiResponse = async () => {
103-
const url = "https://api.weather.gov/gridpoints/LWX/97,71/forecast";
104-
let toSign;
105-
try {
106-
const response = await fetch(url).then((res) => res.json());
107-
const forecast = response.properties.periods[day];
108-
toSign = { temp: forecast.temperature + " " + forecast.temperatureUnit, shortForecast: forecast.shortForecast };
109-
const sigShare = await LitActions.signEcdsa({ toSign, publicKey, sigName });
110-
} catch(e) {
111-
console.log(e);
112-
}
113-
LitActions.setResponse({ response: JSON.stringify(toSign) });
114-
};
115-
116-
fetchWeatherApiResponse();
117-
`;
66+
## Summary
67+
This guide demonstrates how to fetch data from the web within a Lit Action.
11868

119-
```
69+
If you'd like to learn more about Lit Actions, check out the [Lit Actions SDK](https://actions-docs.litprotocol.com/), or our [Advanced Topics](https://developer.litprotocol.com/category/advanced-topics-1) section on Lit Actions.
12070

12171
<FeedbackComponent/>

0 commit comments

Comments
 (0)