forked from smartcontractkit/solana-prediction-game
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgetLatestDataRound.js
149 lines (131 loc) · 4.95 KB
/
getLatestDataRound.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
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
const anchor = require("@project-serum/anchor");
const chainlink = require("@chainlink/solana-sdk");
const solanaWeb3 = require("@solana/web3.js");
const { Wallet } = require("../../models/wallet.model");
const { CURRENCY_PAIRS } = require("../../src/lib/constants");
const { connectToDatabase } = require("../../lib/mongoose");
const Feed = require("../../models/feed.model");
const { bs58 } = require("@project-serum/anchor/dist/cjs/utils/bytes");
let secretKey;
if (process.env.WALLET_PRIVATE_KEY.includes(",")) {
// creation of wallet using your private key
secretKey = Uint8Array.from(process.env.WALLET_PRIVATE_KEY.split(","));
} else {
// get private from base58
secretKey = bs58.decode(process.env.WALLET_PRIVATE_KEY);
}
// Escrow Account Wallet
const wallet = new Wallet(solanaWeb3.Keypair.fromSecretKey(secretKey));
console.log(wallet.publicKey);
/**
* This function retrieves the latest price feed data round from Chainlink Data Feeds.
*
*
* It creates it connects to solana cluster (devnet | mainnet)
* Then creates an anchor client provider that uses:
* 1. A solana connection
* 2. A wallet to sign transactions and pay for fees
* 3. Options to confirm transactions
*
* Then retrieves the latest price feed data round from Chainlink Data Feeds.
*
* For more info view How to get Data Feeds On-Chain (Solana) via the link:
* https://docs.chain.link/solana/overview
* @param address Address of the token pair to retrieve the latest data round from
* @param pair Pair of the token price feed to retrieve the latest data round from
*/
const getLatestDataRound = async (address, pair) => {
let round = null;
// connection to solana cluster node
const connection = new solanaWeb3.Connection(
solanaWeb3.clusterApiUrl(process.env.REACT_APP_SOLANA_CLUSTER_NETWORK),
"confirmed"
);
// creation of a new anchor client provider that uses the connection to solana cluster node
const options = anchor.AnchorProvider.defaultOptions(); // default Options for confirming transactions
const provider = new anchor.AnchorProvider(connection, wallet, options);
anchor.setProvider(provider);
const CHAINLINK_FEED_ADDRESS = address;
console.log("Fetching pair:", pair);
console.log("Fetching address:", address);
const feedAddress = new anchor.web3.PublicKey(CHAINLINK_FEED_ADDRESS);
// load the data feed account using the predefined chainlink program ID
const CHAINLINK_PROGRAM_ID = new anchor.web3.PublicKey(
process.env.CHAINLINK_PROGRAM_ID_ADDRESS
);
let dataFeed = await chainlink.OCR2Feed.load(CHAINLINK_PROGRAM_ID, provider);
let listener = null;
return new Promise(async (res, rej) => {
// listen for events from the price feed, and grab the latest rounds' price data
listener = dataFeed.onRound(feedAddress, (event) => {
round = {
pair: pair,
feed: address,
answer: event.answer,
answerToNumber: event.answer.toNumber(),
roundId: event.roundId,
observationsTS: event.observationsTS,
slot: event.slot,
};
// return the latest round only if event data is available
if (round !== undefined) {
provider.connection.removeOnLogsListener(listener);
res(round);
}
});
});
};
/**
* This function is deployed as a standalone endpoint via Vercel Cloud Functions.
* Given the expected request query payload, it retrieves the latest price feed data round from Chainlink Data Feeds.
* The request is expected to come in as a GET request to `/api/feed/getLatestDataRound`.
* The request body should have the shape:
* { address: "0x...", pair: "XXX-USD" }
* For more info view How to get Data Feeds On-Chain (Solana) via the link:
* https://docs.chain.link/solana/overview
* @param req NextApiRequest HTTP request object wrapped by Vercel function helpers
* @param res NextApiResponse HTTP response object wrapped by Vercel function helpers
*/
module.exports = async (req, res) => {
const { cached } = req.query;
const updateRoundCache = async (round) => {
await Feed.findOneAndUpdate({ feed: round.feed }, round, { upsert: true });
};
const getRoundsCache = async () => {
const feed = await Feed.find();
if (feed.length === 0) {
getLatestDataRounds();
return;
}
res.status(200).send(feed);
};
const getLatestDataRounds = async () => {
const promises = await CURRENCY_PAIRS.map((pair) => {
return new Promise((resolve, reject) => {
return getLatestDataRound(pair.feedAddress, pair.pair).then(
async (res) => {
await updateRoundCache(res);
resolve(res);
}
);
});
});
Promise.allSettled(promises)
.then((response) => {
res.status(200).send(response);
})
.catch((err) => {
res.status(500).send(err);
});
};
try {
await connectToDatabase();
if (cached === "true") {
getRoundsCache();
} else {
getLatestDataRounds();
}
} catch (err) {
res.status(500).send(err);
}
};