Skip to content

Commit f4c9781

Browse files
jayantkJayant Krishnamurthy
and
Jayant Krishnamurthy
authored
Document http client (#32)
* Document PythHttpClient * ignore intellij files * update changelog * fix lint * bad test * 2.6.2 * bump version again * 2.6.3 Co-authored-by: Jayant Krishnamurthy <[email protected]>
1 parent b8f330a commit f4c9781

9 files changed

+81
-24
lines changed

Diff for: .gitignore

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,6 @@
11
node_modules
2-
/lib
2+
/lib
3+
4+
# IntelliJ temp files
5+
.idea
6+
*.iml

Diff for: CHANGELOG.md

+9
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,14 @@
11
# Changelog
22

3+
## 2.6.3
4+
5+
### Changed
6+
- Renamed websocket usage example to `example_ws_usage.ts`
7+
- Updated documentation to describe usage for `PythHttpClient`
8+
9+
### Added
10+
- Example code for using the http client in `example_http_usage.ts`
11+
312
## 2.6.1
413

514
### Changed

Diff for: README.md

+30-5
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,17 @@ $ yarn add @pythnetwork/client
2222

2323
## Example Usage
2424

25-
This library provides a subscription model for consuming price updates:
25+
This library lets you consume prices in two different ways: you can either get continuously-streaming price updates via a websocket connection, or send one-off requests every time you want the current price.
2626

27-
```javascript
27+
### Streaming updates
28+
29+
The websocket connection provides a subscription model for consuming price updates:
30+
31+
```typescript
2832
const pythConnection = new PythConnection(solanaWeb3Connection, getPythProgramKeyForCluster(solanaClusterName))
2933
pythConnection.onPriceChange((product, price) => {
3034
// sample output:
31-
// SRM/USD: $8.68725 ±$0.0131
35+
// Crypto.SRM/USD: $8.68725 ±$0.0131 Status: Trading
3236
console.log(`${product.symbol}: $${price.price} \xB1$${price.confidence} Status: ${PriceStatus[price.status]}`)
3337
})
3438

@@ -41,12 +45,33 @@ This callback gets two arguments:
4145
* `price` contains the official Pyth price and confidence, along with the component prices that were combined to produce this result.
4246
* `product` contains metadata about the price feed, such as the symbol (e.g., "BTC/USD") and the number of decimal points.
4347

44-
See `src/example_usage.ts` for a runnable example of the above usage.
45-
You can run this example with `npm run example`.
48+
See `src/example_ws_usage.ts` for a runnable example of the above usage.
49+
You can run this example with `npm run ws_example`.
4650

4751
You may also register to specific account updates using `connection.onAccountChange` in the solana web3 API, then
4852
use the methods in `index.ts` to parse the on-chain data structures into Javascript-friendly objects.
4953

54+
### Request an update
55+
56+
The request model allows you to send one-off HTTP requests to get the current price without subscribing to ongoing updates:
57+
58+
```typescript
59+
const pythClient = new PythHttpClient(connection, pythPublicKey);
60+
const data = await pythClient.getData();
61+
62+
for (let symbol of data.symbols) {
63+
const price = data.productPrice.get(symbol)!;
64+
// Sample output:
65+
// Crypto.SRM/USD: $8.68725 ±$0.0131 Status: Trading
66+
console.log(`${symbol}: $${price.price} \xB1$${price.confidence} Status: ${PriceStatus[price.status]}`)
67+
}
68+
```
69+
70+
The `getData` function will fetch all information about every product listed on Pyth.
71+
This includes the current price as well as metadata, such as the base and quote currencies.
72+
See `src/example_http_usage.ts` for a runnable example of the above usage.
73+
You can run this example with `npm run http_example`.
74+
5075
## Releases
5176

5277
In order to release a new version of this library and publish it to npm, follow these steps:

Diff for: package-lock.json

+2-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: package.json

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@pythnetwork/client",
3-
"version": "2.6.1",
3+
"version": "2.6.3",
44
"description": "Client for consuming Pyth price data",
55
"homepage": "https://pyth.network",
66
"main": "lib/index.js",
@@ -19,7 +19,8 @@
1919
"preversion": "npm run lint",
2020
"version": "npm run format && git add -A src",
2121
"postversion": "git push && git push --tags",
22-
"example": "npm run build && node lib/example_usage.js"
22+
"ws_example": "npm run build && node lib/example_ws_usage.js",
23+
"http_example": "npm run build && node lib/example_http_usage.js"
2324
},
2425
"keywords": [
2526
"pyth",

Diff for: src/PythHttpClient.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,12 @@ import { Product, PriceData, parseProductData, parsePriceData, parseBaseData, Ac
33

44
export interface PythHttpClientResult {
55
assetTypes: string[]
6+
/** The name of each product, e.g., "Crypto.BTC/USD" */
67
symbols: string[]
78
products: Product[]
9+
/** Metadata for each product. */
810
productFromSymbol: Map<string, Product>
11+
/** The current price of each product. */
912
productPrice: Map<string, PriceData>
1013
prices: PriceData[]
1114
}
@@ -40,7 +43,7 @@ export class PythHttpClient {
4043
// Retrieve data from blockchain
4144
const accountList = await this.connection.getProgramAccounts(this.pythProgramKey, this.commitment)
4245

43-
// Popolate producs and prices
46+
// Populate products and prices
4447
const priceDataQueue = new Array<PriceData>()
4548
const productAccountKeyToProduct = new Map<string, Product>()
4649
const currentSlot = await this.connection.getSlot(this.commitment)

Diff for: src/__tests__/PythNetworkRestClient-test.ts

-11
Original file line numberDiff line numberDiff line change
@@ -10,21 +10,10 @@ test('PythHttpClientCall', (done) => {
1010
pyth_client.getData().then(
1111
(result) => {
1212
try {
13-
console.log('products number: ', result.products.length)
14-
console.log('asset types: ', result.assetTypes)
15-
console.log('product symbols: ', result.symbols)
16-
1713
// Find a product with symbol "SOL/USD"
1814
const products = result.products.filter((p) => p.symbol === 'Crypto.SOL/USD')
1915
expect(products.length).toBeGreaterThan(0)
2016

21-
// Find product prices
22-
const price = result.productPrice.get(products[0].symbol)
23-
expect(price).toBeDefined()
24-
25-
console.log('products', products)
26-
console.log('price', price)
27-
2817
done()
2918
} catch (cerr) {
3019
done(cerr)

Diff for: src/example_http_usage.ts

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { Cluster, clusterApiUrl, Connection } from '@solana/web3.js'
2+
import { getPythProgramKeyForCluster } from './cluster'
3+
import { PriceStatus, PythHttpClient } from '.'
4+
5+
const SOLANA_CLUSTER_NAME: Cluster = 'mainnet-beta'
6+
const connection = new Connection(clusterApiUrl(SOLANA_CLUSTER_NAME))
7+
const pythPublicKey = getPythProgramKeyForCluster(SOLANA_CLUSTER_NAME)
8+
9+
async function runQuery(): Promise<void> {
10+
const pythClient = new PythHttpClient(connection, pythPublicKey)
11+
const data = await pythClient.getData()
12+
13+
for (const symbol of data.symbols) {
14+
const price = data.productPrice.get(symbol)!
15+
16+
if (price.price && price.confidence) {
17+
// tslint:disable-next-line:no-console
18+
console.log(`${symbol}: $${price.price} \xB1$${price.confidence}`)
19+
} else {
20+
// tslint:disable-next-line:no-console
21+
console.log(`${symbol}: price currently unavailable. status is ${PriceStatus[price.status]}`)
22+
}
23+
}
24+
}
25+
26+
runQuery()

Diff for: src/example_usage.ts renamed to src/example_ws_usage.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
import { Cluster, clusterApiUrl, Connection, PublicKey } from '@solana/web3.js'
1+
import { Cluster, clusterApiUrl, Connection } from '@solana/web3.js'
22
import { PythConnection } from './PythConnection'
33
import { getPythProgramKeyForCluster } from './cluster'
44
import { PriceStatus } from '.'
55

6-
const SOLANA_CLUSTER_NAME: Cluster = 'devnet'
6+
const SOLANA_CLUSTER_NAME: Cluster = 'mainnet-beta'
77
const connection = new Connection(clusterApiUrl(SOLANA_CLUSTER_NAME))
88
const pythPublicKey = getPythProgramKeyForCluster(SOLANA_CLUSTER_NAME)
99

0 commit comments

Comments
 (0)