Full guide about redstone-api
Note⚠
The data below is the README.md file from the official RedStone Github. This is followed by my personal review of the __tests__ file for informative purposes only.
Redstone API
In this article, I will talk about Redstone API, which is a JavaScript library for fetching trusted token price data from the Redstone data ecosystem. The Redstone data ecosystem is a decentralized network of oracles that provide trusted data on the prices of various tokens. The Redstone API is secured on Arweave, a decentralized storage network, and is protected by a pledge of oracles.
The Redstone API is used by a variety of applications including DeFi platforms, trading bots, and price aggregators. It provides a reliable and secure way to access trusted token pricing data.
Here are some of the key features of the Redstone API:
It is secured on Arweave, a decentralized storage network.
It is secured by oracle provisioning.
It supports a variety of tokens, including ERC-20, ERC-721, and BEP-20.
It provides real-time price data.
It is easy to use.
If you are looking for a reliable and secure way to access trusted token pricing data, Redstone API is a good option.
Redstone API is a Javascript library for fetching trusted token pricing data from Redstone data ecosystem.
It is a Javascript wrapper for Redstone HTTP Api.
🚀 Demo
Try it directly in CodeSandbox: demo link
✅ Why Redstone API
✓ Secure
Redstone pricing data is secured on Arweave and protected by the provider's collateral. Learn more
✓ Easy to use
You don't need any API keys. Just install the npm package and add a single line of code. Quick start
✓ 100+ tokens
We support BTC, ETH, AR, EUR, and many other crypto and fiat currencies. All supported tokens
✓ TypeScript Support
Redstone API is fully written in Typescript and then compiled to JavaScript. Source code
📖 Documentation
This readme should provide you with all the information you need to start using redstone api. If you want to see the full documentation, visit api.docs.redstone.finance
📦 Installation
Using npm
npm install redstone-api
Using yarn
yarn add redstone-api
🤖 Usage
Importing
// Using Node.js `require()` const redstone = require('redstone-api'); // Using ES6 imports import redstone from 'redstone-api';
Get the latest price for a single token
const price = await redstone.getPrice("AR"); console.log(price.value); // latest price value for AR token (in USD) console.log(price.timestamp); // the exact timestamp of the price
💡 Note: All the prices are denominated in USD. You can fetch price data for BTC, ETH, AR, EUR and any other of 100+ supported tokens.
Available symbols
You can use a symbols
object to explore all available symbols right in the code.
import redstone from 'redstone-api'; const price = await redstone.getPrice("AR");
{ value: 123.23, // Number: Price value in USD timestamp: 1617146511173, // Number: Timestamp (ms) for price provider: "I-5rWUehEv-MjdK9gFw09RxfSLQX9DIHxG614Wf8qo0", // String: Provider arweave address permawebTx: "V8FUU0BG4kVOJwKWHzgkn1aEFm-eanhqqEXfPFY7pmI", // String: Arweave transaction id source: {"coingecko": 123,"sushiswap": 123.23,"uniswap": 123.35}, // Object: Prices from different sources }
// As async/await is only a syntactic sugar on Javascript // Promises you can use them in a "standard" way const price = redstone.getPrice("AR").then((price) => { console.log(price.value); // latest price value for AR token });
Get the latest prices for several tokens
To fetch prices for several tokens use the getPrice
method and pass an array with any subset of supported tokens.
const prices = await redstone.getPrice(["BTC", "ETH", "AR", "EUR"]); console.log(prices); // Example output below /* { "BTC": { value: 58953.39, timestamp: 1617152802779, ... }, "ETH": { value: 1856.75, timestamp: 1617152802779, ... }, ... } */ console.log(prices["BTC"].value); // latest price value for BTC console.log(prices["ETH"].value); // latest price value for ETH console.log(prices["AR"].value); // latest price value for AR
Get prices for all available tokens
To fetch the latest prices for all available tokens use the getAllPrices
method.
const prices = await redstone.getAllPrices(); console.log(prices); // Example output below /* { "BTC": {...}, "ETH": {...}, ... } */ console.log(prices["AR"].value); // latest price value for AR console.log(prices["EUR"].value); // latest price value for EUR
Get the historical price for a single token
To get the historical price use the getHistoricalPrice
method.
const price = await redstone.getHistoricalPrice("AR", { date: "2021-03-30T12:35:09", // Any convertable to date type }); console.log(price.value); // AR price for specific time
💡 Note: date
argument must be convertable to Date type. You may pass date (e.g. new Date(2021-04-01)
), timestamp (e.g. 1617709771289
), or just string (e.g. 2021-04-01
or 2021-04-01T12:30:58
).
Get the historical price for several tokens
To fetch the historical price for several tokens pass an array of symbols to getHistoricalPrice
method.
const symbols = ["AR", "BTC", "UNI", "ETH", "EUR"]; const prices = await redstone.getHistoricalPrice(symbols, { date: "2021-03-30T12:35:09", }); console.log(prices["BTC"].value); // BTC price for specific time
Get the historical prices in a time range
To fetch the historical prices in a time range specify token symbol as the first argument of the getHistoricalPrice
method, and startDate
, endDate
and interval
as fields of the second argument.
💡 Note: currently Redstone API supports fetching historical prices in a time range only for a single token.
const prices = await redstone.getHistoricalPrice("AR", { startDate: "2021-03-29T12:35:09", endDate: "2021-03-30T12:35:09", interval: 3600 * 1000, // 1 hour }); console.log(prices); // Example output below /* [ { value: 28.8, timestamp: 1617016995624, ... }, { value: 28.59, timestamp: 1617014111705, ... }, ... ] */
💡 Note: startDate
and endDate
argument must be convertable to Date type.
Get prices with pagination
To fetch prices with pagination specify token symbol as the first argument of the getHistoricalPrice
method, and offset
with limit
as properties of the second argument.
💡 Note: pagination is supported only for a single token.
const prices = await redstone.getHistoricalPrice("AR", { offset: 1000, limit: 100, });
Verify signature
All prices saved in Redstone have a signature, thanks to which you always can verify if the price data has been submitted by the trusted provider.
To do so you can set verifySignature
option to true
in getPrice
, getHistoricalPrice
or getAllPrices
methods. If signature is invalid - error will be thrown.
const price = await redstone.getPrice("AR", { verifySignature: true, }); console.log(price.value);
Fluent Interface
Redstone implements a fluent interface to simplify query creation thanks to a human readable syntax. Learn more
Using a custom cache api url
Option 1. Using a setCacheApiUrl method
redstone.setCacheApiUrl("http://localhost:9000/prices"); redstone.getPrice("AR").then(console.log);
Option 2. Initialising a new redstone api instance with a cacheApiUrl param
const redstoneApi = new redstone.Api({ cacheApiUrl: "http://localhost:9000/prices", }); redstoneApi.getPrice("AR").then(console.log);
💡 Note: To use a custom cache api url with the redstone fluent interface you should pass a cacheApiUrl
as an argument of the exec
method each time you make a query.
redstone.query().symbol("AR").latest().exec({ cacheApiUrl: "http://localhost:9000/prices", }).then(console.log);
Get prices from Arweave
By default, Redstone API fetches data from the Redstone cache layer. It works way faster than fetching directly from Arweave Blockchain. Even so, thanks to signature verification prices data is still trusted and secure.
We strongly recommend using the default fetching mechanism which leverages cache to speed up queries. But if you want to fetch data directly from Arweave you can do it by initialising a new Api
client and setting useCache
option to false
.
const redstoneArweaveClient = new redstone.Api({ useCache: false }); const price = await redstoneArweaveClient.getPrice("AR"); console.log(price.value); // AR price value fetched directly from Arweave
🚀 Examples
💬 Contributing
Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.
Please make sure to update tests as appropriate.
📜 License
This software is licensed under the MIT © Redstone
Contents of redstone-api
__tests__
folder contains the unit tests for the project.docs
folder contains the documentation for the project.examples
folder contains example code for using the project.src
folder contains the source code for the project..gitignore
file tells Git which files to ignore when tracking changes to the repository.README.md
file is the project README, which provides an overview of the project.jestconfig.json
file configures Jest, a JavaScript testing framework.package.json
file lists the dependencies for the project.tsconfig.json
file configures TypeScript, a programming language for JavaScript.tslint.json
file configures TSLint, a linter for TypeScript.yarn.lock
file tracks the exact versions of the dependencies for the project.
redstone-api/__tests__/arweave-signing.test.ts
The first thing the code does is import the ArweaveMultihost
library. This library provides a way to interact with the Arweave blockchain.
The next part of the code defines a test case called shouldSignAndVerifySignature
. This test case first generates a pair of cryptographic keys using the generate()
method from the wallets
module. The public key is then used to sign a string of data using the sign()
method from the crypto
module. The signature is then verified using the verify()
method from the crypto
module. The test case asserts that the signature is valid.
The next test case, shouldGetAddressFromOwner
, also generates a pair of cryptographic keys. It then uses the jwkToAddress()
method to convert the JSON Web Key (JWK) to an Arweave address. The ownerToAddress()
method is then used to get the Arweave address from the public key. The test case asserts that the two addresses are the same.
In summary, the code in arweave-signing.test.ts
tests the ability to sign and verify signatures on the Arweave blockchain. It also tests the ability to get the Arweave address from a public key.
Here are some additional details about the code:
- The
ArweaveMultihost
library uses the Arweave API to interact with the blockchain. The API is a RESTful API that provides a way to read, write, and manage data on the blockchain. - The
wallets
module provides methods for generating, managing, and using cryptographic keys on Arweave. - The
crypto
module provides methods for signing and verifying signatures on Arweave.
redstone-api/__tests__/fluent-interface.test.ts
The code in fluent-interface.test.ts
tests the fluent interface of the redstone
API. The fluent interface allows you to chain together methods to specify the data you want to fetch.
The first test case, shouldGetARPrice
, fetches the latest price of AR. It does this by calling the query()
method, specifying the symbol AR
and the latest()
method. The exec()
method executes the request and returns the price.
The second test case, shouldGetAAPLPriceWithRedstoneStocksProvider
, fetches the latest price of AAPL using the redstone-stocks
provider. It does this by calling the query()
method, specifying the symbol AAPL
, the latest()
method, and the provider
option.
The third test case, shouldGetASingleHistoricalARPrice
, fetches a single historical price of AR. It does this by calling the query()
method, specifying the symbol AR
, the atDate()
method, and the provider
option.
The fourth test case, shouldGetHistoricalARPriceForTheLast12Hours
, fetches the historical prices of AR for the last 12 hours. It does this by calling the query()
method, specifying the symbol AR
, the forLastHours()
method, and the exec()
method.
The fifth test case, shouldGetSingleHistoricalARPriceForThe24HoursAgo
, fetches a single historical price of AR for the 24 hours ago. It does this by calling the query()
method, specifying the symbol AR
, the hoursAgo()
method, and the exec()
method.
The sixth test case, shouldGetHistoricalARPriceForLast7Days
, fetches the historical prices of AR for the last 7 days. It does this by calling the query()
method, specifying the symbol AR
, the forLastDays()
method, and the exec()
method.
The seventh test case, shouldGetHistoricalARPriceForTheLast1Day
, fetches the historical prices of AR for the last 1 day. It does this by calling the query()
method, specifying the symbol AR
, the forLastDays()
method, and the exec()
method.
The eighth test case, shouldGetARPriceInTimeRange
, fetches the prices of AR in a specific time range. It does this by calling the query()
method, specifying the symbol AR
, the fromDate()
method, the toDate()
method, and the exec()
method.
The ninth test case, shouldGetLatestPricesForARETHAndBTC
, fetches the latest prices for AR, ETH, and BTC. It does this by calling the query()
method, specifying the symbols ["AR", "ETH", "BTC"]
, the latest()
method, and the exec()
method.
The tenth test case, shouldGetTheHistoricalPriceForARETHAndBTC
, fetches the historical prices for AR, ETH, and BTC for a specific date. It does this by calling the query()
method, specifying the symbols ["AR", "ETH", "BTC"]
, the atDate()
method, and the exec()
method.
The eleventh test case, shouldGetTheLatestPricesForAllSymbols
, fetches the latest prices for all symbols. It does this by calling the query()
method, specifying the allSymbols()
method, the latest()
method, and the exec()
method.
These are just a few examples of how the fluent interface can be used to fetch data from the RedStone Oracle API. The API also supports a number of other methods, such as filtering, sorting, and pagination.
redstone-api/__tests__/get-all-prices.test.ts
The code in get-all-prices.test.ts
tests the getAllPrices()
method of the redstone
API. The getAllPrices()
method fetches the latest prices for all symbols.
The first test case, shouldGetAllPrices
, fetches all prices and asserts that the prices are for BTC, ETH, and AR. It also asserts that the prices are not older than 150 seconds.
The second test case, shouldGetAllPricesAndVerifyTheirSignatures
, fetches all prices and verifies their signatures. This is done by setting the verifySignature
option to true
.
The third test case, shouldNotHaveTechnicalProps
, fetches all prices and asserts that they do not have any technical properties. Technical properties are properties that are used by the RedStone Oracle API, but are not relevant to users.
These are just a few examples of how the getAllPrices()
method can be used. The method also supports a number of other options, such as specifying the providers to use and the time range to fetch prices for.
redstone-api/__tests__/get-historical-price.test.ts
The code in get-historical-price.test.ts
tests the getHistoricalPrice()
method of the redstone
API. The getHistoricalPrice()
method fetches the historical price of a symbol for a given date.
The first test case, shouldGetARPriceFor2021-04-17
, fetches the historical price of AR for 2021-04-17. It asserts that the price is 25.923827794046517 USD.
The second test case, shouldGetETHPriceFor2021-04-17
, fetches the historical price of ETH for 2021-04-17. It asserts that the price is 2421.882615498678 USD.
The third test case, shouldGetETHPriceFor2021-04-17AndVerifySignature
, fetches the historical price of ETH for 2021-04-17 and verifies the signature.
The fourth test case, shouldGetARBTCAndETHPriceFor2021-04-17
, fetches the historical prices of AR, BTC, and ETH for 2021-04-17. It asserts that the prices are greater than 0.1 USD, 100 USD, and 1000 USD, respectively.
The fifth test case, shouldGetARPricesInATimeRange
, fetches the historical prices of AR in the time range 2021-06-17 to 2021-06-18. It asserts that the number of prices is 144.
The sixth test case, shouldGetARPricesWithHourlyInterval
, fetches the historical prices of AR with an hourly interval. It asserts that the number of prices is greater than or equal to 48 and less than or equal to 50.
The seventh test case, shouldGetARPricesWithPaging
, fetches the historical prices of AR with paging. It asserts that the number of prices is 100.
The eighth test case, shouldNotFoundARPriceFor2019-01-01
, tries to fetch the historical price of AR for 2019-01-01. It asserts that an error is thrown with the message Price not found for symbol: AR
.
These are just a few examples of how the getHistoricalPrice()
method can be used. The method also supports a number of other options, such as specifying the providers to use and the time range to fetch prices for.
redstone-api/__tests__/get-price.test.ts
This file contains unit tests for the getPrice()
method of the redstone
API. The getPrice()
method fetches the latest price of a symbol.
The test cases in the file check for the following:
- The method can fetch the latest price of AR.
- The method can fetch the latest price of ETH.
- The method does not have technical properties.
- The method can fetch the latest prices for AR, ETH, and BTC.
- The method can fetch the latest price of AAPL without explicitly setting the provider.
- The method can fetch the latest price of LINK without explicitly setting the provider.
- The method does not have technical properties.
- The method can fetch the latest prices for AR, ETH, BNB, and BTC and verify the signatures.
- The method can verify the signature for the latest ETH price.
The tests are well-written and cover all the possible scenarios. They are also concise and easy to read.
This is a breakdown of the code:
import redstone from "../src/index"; import config from "../src/config"; const MAX_TIME_DIFF = 90000; // 90s const shouldNotHaveTechProps = (price: any) => { const technicalProps = ["signature", "version", "providerPublicKey"]; for (const prop of technicalProps) { expect(price).not.toHaveProperty(prop); } };
This code imports the redstone
and config
modules. The redstone
module provides the API for fetching prices. The config
module provides the configuration for the API.
The MAX_TIME_DIFF
constant defines the maximum difference between the current time and the timestamp of a price before it is considered stale.
The shouldNotHaveTechProps()
function checks if a price object does not have any technical properties. Technical properties are properties that are used to verify the authenticity of a price.
describe("Test getPrice method", () => { test("Should get AR price", async () => { const symbol = "AR"; const price: any = await redstone.getPrice(symbol); expect(price).toBeDefined(); expect(price.symbol).toBe(symbol); expect(price.provider).toBe(config.providers["redstone-rapid"].address); expect(price.value).toBeGreaterThan(0.1); expect(Date.now() - price.timestamp).toBeLessThan(MAX_TIME_DIFF); });
This test case checks if the getPrice()
method can fetch the latest price of AR. The test case first creates a price object for AR. Then, it calls the getPrice()
method and passes the symbol AR
as an argument. Finally, the test case asserts that the price object returned by the getPrice()
method has the expected properties.
The other test cases in the file are similar. They check if the getPrice()
method can fetch the latest prices of ETH, AAPL, LINK, and other symbols. They also check if the getPrice()
method can verify the signatures of prices.
Conclusion
As you have already realized, the tests/
folder contains unit tests for the Redstone API. Unit tests are small tests that test a single unit of code, such as a function or class. They are an important part of software development because they make sure that the code works correctly.
The unit tests in the tests/ folder are written in JavaScript and use the Jest framework. Jest is a popular JavaScript testing framework that makes it easy to write and execute unit tests.
Unit tests in the tests/ folder test the functionality of the Redstone API by making requests to the API and checking the results. For example, there is a unit test that tests the functionality of the getPrice() function. This function is used to get the current price of a token. The unit test executes a request to the API to get the price of the token and then verifies that the price returned is correct.
Unit tests in the tests/
folder are an important part of the Redstone API because they ensure that the API is working correctly. By running the unit tests, you can be sure that the API is returning the correct results.
Thank you for reading ❤
Official site http://redstone.finance
Docs https://docs.redstone.finance
Blog https://blog.redstone.finance
Github https://github.com/redstone-finance
Twitter(x) @redstone_defi
Discord http://redstone.finance/discord