-
Notifications
You must be signed in to change notification settings - Fork 1
/
API-request-example.js
94 lines (84 loc) · 3.68 KB
/
API-request-example.js
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
// This example shows how to make a decentralized price feed using multiple APIs
// Arguments can be provided when a request is initated on-chain and used in the request source code as shown below
const coinMarketCapCoinId = args[0]
const coinGeckoCoinId = args[1]
const coinPaprikaCoinId = args[2]
const badApiCoinId = args[3]
if (
secrets.apiKey == "" ||
secrets.apiKey === "Your coinmarketcap API key (get a free one: https://coinmarketcap.com/api/)"
) {
throw Error(
"COINMARKETCAP_API_KEY environment variable not set for CoinMarketCap API. Get a free key from https://coinmarketcap.com/api/"
)
}
// To make an HTTP request, use the Functions.makeHttpRequest function
// Functions.makeHttpRequest function parameters:
// - url
// - method (optional, defaults to 'GET')
// - headers: headers supplied as an object (optional)
// - params: URL query parameters supplied as an object (optional)
// - data: request body supplied as an object (optional)
// - timeout: maximum request duration in ms (optional, defaults to 10000ms)
// - responseType: expected response type (optional, defaults to 'json')
// Use multiple APIs & aggregate the results to enhance decentralization
const coinMarketCapRequest = Functions.makeHttpRequest({
url: `https://pro-api.coinmarketcap.com/v1/cryptocurrency/quotes/latest?convert=USD&id=${coinMarketCapCoinId}`,
// Get a free API key from https://coinmarketcap.com/api/
headers: { "X-CMC_PRO_API_KEY": secrets.apiKey },
})
const coinGeckoRequest = Functions.makeHttpRequest({
url: `https://api.coingecko.com/api/v3/simple/price?ids=${coinGeckoCoinId}&vs_currencies=usd`,
})
const coinPaprikaRequest = Functions.makeHttpRequest({
url: `https://api.coinpaprika.com/v1/tickers/${coinPaprikaCoinId}`,
})
// This dummy request simulates a failed API request
const badApiRequest = Functions.makeHttpRequest({
url: `https://badapi.com/price/symbol/${badApiCoinId}`,
})
// First, execute all the API requests are executed concurrently, then wait for the responses
const [coinMarketCapResponse, coinGeckoResponse, coinPaprikaResponse, badApiResponse] = await Promise.all([
coinMarketCapRequest,
coinGeckoRequest,
coinPaprikaRequest,
badApiRequest,
])
const prices = []
if (!coinMarketCapResponse.error) {
prices.push(coinMarketCapResponse.data.data[coinMarketCapCoinId].quote.USD.price)
} else {
console.log("CoinMarketCap Error")
}
if (!coinGeckoResponse.error) {
prices.push(coinGeckoResponse.data[coinGeckoCoinId].usd)
} else {
console.log("CoinGecko Error")
}
if (!coinPaprikaResponse.error) {
prices.push(coinPaprikaResponse.data.quotes.USD.price)
} else {
console.log("CoinPaprika Error")
}
// A single failed API request does not cause the whole request to fail
if (!badApiResponse.error) {
prices.push(httpResponses[3].data.price.usd)
} else {
console.log(
"Bad API request failed. (This message is expected to demonstrate using console.log for debugging locally with the simulator)"
)
}
// At least 3 out of 4 prices are needed to aggregate the median price
if (prices.length < 3) {
// If an error is thrown, it will be returned back to the smart contract
throw Error("More than 1 API failed")
}
const medianPrice = prices.sort((a, b) => a - b)[Math.round(prices.length / 2)]
console.log(`Median Bitcoin price: $${medianPrice.toFixed(2)}`)
// The source code MUST return a Buffer or the request will return an error message
// Use one of the following functions to convert to a Buffer representing the response bytes that are returned to the client smart contract:
// - Functions.encodeUint256
// - Functions.encodeInt256
// - Functions.encodeString
// Or return a custom Buffer for a custom byte encoding
return Functions.encodeUint256(Math.round(medianPrice * 100))