Skip to content

Commit cde9f15

Browse files
authored
Merge pull request #10 from oasisprotocol/ptrus/feature/cryptocompare-api
Use cryptocompare API for prices instead of binance
2 parents 5c445cc + 5a472a7 commit cde9f15

File tree

8 files changed

+1803
-1762
lines changed

8 files changed

+1803
-1762
lines changed

.changelog/10.internal.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Use cryptocompare API for prices instead of binance
2+
3+
Binance API doesn't work from ci runners since they are hosted in US

.github/workflows/update-prices.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ jobs:
2222
node-version: '24'
2323

2424
- name: Update ROSE prices
25+
env:
26+
CRYPTOCOMPARE_API_KEY: ${{ secrets.CRYPTOCOMPARE_API_KEY }}
2527
run: node scripts/update-prices.js
2628

2729
- name: Commit and push changes

.nvmrc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
24

scripts/update-prices.js

Lines changed: 40 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,18 @@
11
/**
2-
* Fetches latest ROSE/USD prices from Binance and updates the price file.
2+
* Fetches latest ROSE/USD prices from CryptoCompare and updates the price file.
33
* Only adds new dates that don't already exist.
44
*
55
* Usage:
66
* node scripts/update-prices.js [--dry-run]
77
*
88
* Options:
99
* --dry-run Print what would be added without modifying the file
10+
*
11+
* Environment Variables:
12+
* CRYPTOCOMPARE_API_KEY - CryptoCompare API key (required)
13+
*
14+
* Price Source:
15+
* CryptoCompare (daily close prices, aggregated from multiple exchanges)
1016
*/
1117

1218
import fs from "fs";
@@ -15,8 +21,11 @@ import { fileURLToPath } from "url";
1521

1622
const __dirname = path.dirname(fileURLToPath(import.meta.url));
1723
const PRICE_FILE = path.join(__dirname, "..", "src", "prices", "rose-usd.json");
18-
const BINANCE_API = "https://api.binance.com/api/v3/klines";
19-
const SYMBOL = "ROSEUSDT";
24+
25+
// CryptoCompare API configuration
26+
const CRYPTOCOMPARE_API = "https://min-api.cryptocompare.com/data/v2/histoday";
27+
const SYMBOL = "ROSE";
28+
const CURRENCY = "USD";
2029
const DAYS_TO_FETCH = 30;
2130

2231
/**
@@ -26,35 +35,48 @@ const DAYS_TO_FETCH = 30;
2635
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
2736

2837
/**
29-
* Fetch daily prices from Binance API with retry logic.
38+
* Fetch daily prices from CryptoCompare API.
3039
* @param {number} limit - Number of days to fetch
3140
* @param {number} retries - Number of retries on failure
3241
* @param {number} retryDelay - Delay between retries in ms
3342
* @returns {Promise<Array<{date: string, price: number}>>}
3443
*/
35-
export async function fetchPricesFromBinance(limit = DAYS_TO_FETCH, retries = 3, retryDelay = 5000) {
36-
const url = `${BINANCE_API}?symbol=${SYMBOL}&interval=1d&limit=${limit}`;
44+
export async function fetchPricesFromCryptoCompare(limit = DAYS_TO_FETCH, retries = 3, retryDelay = 5000) {
45+
const apiKey = process.env.CRYPTOCOMPARE_API_KEY;
46+
if (!apiKey) {
47+
throw new Error("CRYPTOCOMPARE_API_KEY environment variable not set");
48+
}
49+
50+
const url = `${CRYPTOCOMPARE_API}?fsym=${SYMBOL}&tsym=${CURRENCY}&limit=${limit}`;
3751

3852
let lastError;
3953
for (let attempt = 1; attempt <= retries; attempt++) {
4054
try {
41-
console.log(`Fetching prices from Binance (attempt ${attempt}/${retries})...`);
42-
const response = await fetch(url);
55+
console.log(`Fetching prices from CryptoCompare (attempt ${attempt}/${retries})...`);
56+
const response = await fetch(url, {
57+
headers: {
58+
authorization: `Apikey ${apiKey}`,
59+
},
60+
});
4361

4462
if (!response.ok) {
45-
throw new Error(`Binance API error: ${response.status} ${response.statusText}`);
63+
throw new Error(`CryptoCompare API error: ${response.status} ${response.statusText}`);
4664
}
4765

4866
const data = await response.json();
4967

50-
if (!Array.isArray(data) || data.length === 0) {
51-
throw new Error("No data returned from Binance API");
68+
if (data.Response === "Error") {
69+
throw new Error(`CryptoCompare API error: ${data.Message}`);
70+
}
71+
72+
const prices = data.Data?.Data;
73+
if (!Array.isArray(prices) || prices.length === 0) {
74+
throw new Error("No data returned from CryptoCompare API");
5275
}
5376

54-
return data.map((kline) => {
55-
const [openTime, , , , close] = kline;
56-
const date = new Date(openTime).toISOString().split("T")[0];
57-
return { date, price: parseFloat(close) };
77+
return prices.map((day) => {
78+
const date = new Date(day.time * 1000).toISOString().split("T")[0];
79+
return { date, price: day.close };
5880
});
5981
} catch (err) {
6082
lastError = err;
@@ -136,9 +158,9 @@ export function savePrices(prices, filePath = PRICE_FILE) {
136158
export async function updatePrices(options = {}) {
137159
const { dryRun = false, filePath = PRICE_FILE } = options;
138160

139-
// Fetch new prices from Binance
140-
const newPrices = await fetchPricesFromBinance();
141-
console.log(`Fetched ${newPrices.length} prices from Binance`);
161+
// Fetch new prices from CryptoCompare
162+
const newPrices = await fetchPricesFromCryptoCompare();
163+
console.log(`Fetched ${newPrices.length} prices from CryptoCompare`);
142164

143165
// Load existing prices
144166
const existing = loadPrices(filePath);

src/pages/AccountingEvents.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ const AccountingEvents = () => {
238238
</li>
239239
<li>
240240
<strong>usd_price, usd_amount</strong> - USD price and value at time of transaction
241-
(ROSE and wROSE only, prices sourced from Binance)
241+
(ROSE and wROSE only, daily close prices from CryptoCompare)
242242
</li>
243243
</ul>
244244
</div>

src/pages/StakingRewards.jsx

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -233,8 +233,8 @@ const StakingRewards = () => {
233233
<strong>rewards</strong> - Staking rewards earned in this period
234234
</li>
235235
<li>
236-
<strong>usd_price, usd_reward</strong> - USD price at period end and reward value
237-
(prices sourced from Binance)
236+
<strong>usd_price, usd_reward</strong> - USD price at period end and reward value (daily
237+
close prices from CryptoCompare)
238238
</li>
239239
</ul>
240240
</div>
@@ -269,8 +269,9 @@ const StakingRewards = () => {
269269
marginBottom: "20px",
270270
}}
271271
>
272-
Experimental: This tool calculates rewards based on share value changes. Data is provided
273-
as-is without warranty. Please verify all data independently before use.
272+
Experimental: Rewards are calculated from share value changes. USD values use end-of-period
273+
prices, but rewards only become realized when you undelegate. Consider using the USD price
274+
at undelegation time via the Accounting Events tool. Verify all data independently.
274275
</p>
275276

276277
{rows.length > 0 && (

0 commit comments

Comments
 (0)