Skip to content

Commit a2030a2

Browse files
some docs on account structure and getting started
1 parent 77b4783 commit a2030a2

File tree

4 files changed

+133
-9
lines changed

4 files changed

+133
-9
lines changed

doc/aggregate_price.md

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
# Aggregate price on-chain account structure
2+
3+
The pyth block-chain price oracle manages a number of on-chain accounts. Accounts are segregated into different types corresponding to product reference data, price/quote data and directory, or mapping data. Mapping accounts serve as a listing or mapping of other accounts.
4+
5+
The relationships between different account types on-chain are as follows:
6+
7+
```
8+
9+
------------- ------------- -------------
10+
| |1 m| | | |
11+
| mapping |------->| product |------>| price |
12+
| | | | | (price) |
13+
------------- ------------- -------------
14+
| |
15+
V V
16+
------------- -------------
17+
| | | |
18+
| mapping | | price |
19+
| | | (twap) |
20+
------------- -------------
21+
| |
22+
V V
23+
... ...
24+
25+
```
26+
27+
There exists a linked list of `mapping` accounts. Each contains a simple list of `product` account ids, or public keys. Each `product` contains a set of reference attributes corresponding to a single product or asset, such as BTC/USD or AAPL/USD. These attributes are stored as a list of text key/value pairs such as "symbol", "asset_type", "country" etc..
28+
29+
Each `product` account refers to the head of a linked-list of `price` accounts. `price` accounts are where a product's price and other metrics are stored. Each `price` account corresponds to a different "price_type". At the moment, these include "price", "twap" and "volatility".
30+
31+
32+
## pcrust example
33+
34+
The pcrust example program uses the solana rust RPC API to load and print all pyth product and price data by bootstrapping from the root `mapping` account key. The output looks something like this:
35+
36+
```
37+
product_account .. 4SxmcsbJWVBWvuP2cRQDjFtAgdqzWWLbHESnUTH4CegT
38+
symbol.......... AAPL/USD
39+
asset_type...... Equity
40+
country......... US
41+
quote_currency.. USD
42+
tenor........... Spot
43+
description..... APPLE INC
44+
cms_symbol...... AAPL
45+
cqs_symbol...... AAPL
46+
nasdaq_symbol... AAPL
47+
price_account .. CeLD8TC7Ktv2o57EHP7rddh6TZBHXkAhTyfWgxsTYs21
48+
price_type ... price
49+
exponent ..... -5
50+
status ....... trading
51+
corp_act ..... nocorpact
52+
price ........ 12276250
53+
conf ......... 1500
54+
valid_slot ... 55519683
55+
publish_slot . 55519684
56+
product_account .. 9BQ2WKSVbfzpSJYyLCJuxVuiUFxHmQvkhhez94AdffEZ
57+
symbol.......... BTC/USD
58+
asset_type...... Crypto
59+
country......... US
60+
quote_currency.. USD
61+
tenor........... Spot
62+
jlqd_symbol..... BTCUSD
63+
price_account .. FCLf9N8xcN9HBA9Cw68FfEZoSBr4bYYJtyRxosNzswMH
64+
price_type ... price
65+
exponent ..... -9
66+
status ....... trading
67+
corp_act ..... nocorpact
68+
price ........ 55233535000000
69+
conf ......... 81650000000
70+
valid_slot ... 55519684
71+
publish_slot . 55519685
72+
...
73+
74+
```
75+
76+
The details of each `product` account and their corresponding `price` accounts are dumped to stdout.
77+
78+
Each `product` may have a slightly different set of reference attributes, depending on their type, but all have "symbol", "asset_type", "quote_currency" and "tenor". US equity products, for example, include various additional reference symbology that is useful for mapping pyth products to other industry-standard identifiers.
79+
80+
Each `price` contains a "price" and "conf" value. "conf" represents a confidence interval on price and broadly corresponds to bid-offer spread. All "price"s are stored as 64bit integers with a fixed, implied number of decimal places defined by the "exponent" field. The AAPL price of 12276250 above, therefore, respresents a value of 122.76250 because the "exponent" is set at -5 or 5 decimal places.
81+
82+
Each `price` has a "status" which is an enumeration of the following values: "trading", "halted", "auction" or "unknown". Only "trading" prices are valid. Equity products also contain a "corp_act" status to notify users of any ongoing corprate action event that may affect a product's price or symbology.
83+
84+
The "valid_slot" and "publish_slot" fields correspond to which solana slots the aggregate price was published in. More on this in the next section.
85+
86+
87+
## Aggregate Price Procedure
88+
89+
The pyth price represents an aggregate derived from multiple contributing market "quoters". It is a two-stage process to derive the aggregate price: first, individual quoters submit their prices along with what they believe to be the most recently confirmed solana slot value. The second stage gathers the latest prices from each quoter, discards those that are too old or not in a valid trading state and derives an aggregate price, currently through a simple median.
90+
91+
The pyth program accumulates prices with respect to whatever the current slot is inside the solana node. This is called the "valid_slot" above. As soon as the slot ticks forward by one, the pyth program computes the aggregate price and publishes it with respect to the new "publish_slot" and starts repeating the process with a new "valid_slot".
92+
93+
The aggregate "status" of a price is subject to whether there are any valid contributors (i.e. "unknown" status) or whether any contributors are in a "halted" or "auction" state.

doc/getting_started.md

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
The pyth-client repo consists of a C++ library (libpc.a), a command-line administration tool (pyth) and a json/websocket-based server (pythd).
44

5-
You can integrate with libpc directly in your application. See `pctest/test_publish.cpp` ifor an example.
5+
You can integrate with libpc directly in your application. See `pctest/test_publish.cpp` for an example. Or, you can integrate with the pythd server via json/websockets. See `pctest/test_publish.py` for an example.
66

77
Before doing this you need to setup a *key-store* directory. A key-store is a collection of cryptographic keys for interracting with the solana block-chain. This can be done via the pyth command-line tool. First, build the project by following the instructions in the README.md file and cd to the build directory, then run the following:
88

@@ -29,16 +29,26 @@ This will output the public key in base58 encoding and will look something like:
2929
5rYvdyWAunZgD2EC1aKo7hQbutUUnkt7bBFM6xNq2z7Z
3030
```
3131

32-
Once permissioned, you need two additional public keys in the key-store. The id of the mapping-account that contains the directory listing of the on-chain symbols and the id of the on-chain oracle program that you use to publish prices. A program already exists to initialize these for testing:
32+
Once permissioned, you need two additional public keys in the key-store. The id of the mapping-account that contains the directory listing of the on-chain symbols and the id of the on-chain oracle program that you use to publish prices. Mapping and program accounts are maintained in three separate environments: pythnet, devnet and forthcoming mainnet-beta.
33+
34+
Use the init_key_store.sh script to initialize these account keys:
3335

3436
```
35-
../pctest/init_key_store.sh $KDIR
37+
KENV=pythnet # or devnet or mainnet-beta
38+
39+
# initialize keys for solana devnet
40+
../pctest/init_key_store.sh $KENV $KDIR
41+
3642
```
3743

3844
This creates two files: `$KDIR/program_key.json` and `$KDIR/mapping_key.json`.
3945

40-
Once pemissioned, you can test your setup by running the test_publish.cpp example program for publishing and subscribing to two symbols on the test solana node:
46+
Once pemissioned, you can test your setup by running the test_publish.cpp example program for publishing and subscribing to two test symbols. To test publishing on pythnet you need to run:
47+
4148

4249
```
43-
./test_publish -k $KDIR -r 44.232.27.44
50+
KHOST=44.232.27.44 # or devnet.solana.com
51+
./test_publish -k $KDIR -r $KHOST
4452
```
53+
54+
The certification environment can be found at the IP address 44.232.27.44. Solana devnet can be found at: devnet.solana.com

pcrust/src/main.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ fn get_status( st: &PriceStatus ) -> &'static str
5353
fn get_corp_act( cact: &CorpAction ) -> &'static str
5454
{
5555
match cact {
56-
CorpAction::NoCorpAct => "NoCorpAct",
56+
CorpAction::NoCorpAct => "nocorpact",
5757
}
5858
}
5959

pctest/init_key_store.sh

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,32 @@ check()
1212
fi
1313
}
1414

15-
KDIR=$1
15+
KENV=$1
16+
KDIR=$2
17+
case $KENV in
18+
devnet)
19+
MAP_KEY=ArppEFcsybCLE8CRtQJLQ9tLv2peGmQoKWFuiUWm4KBP
20+
PGM_KEY=5mkqGkkWSaSk2NL9p4XptwEQu4d5jFTJiurbbzdqYexF
21+
;;
22+
pythnet)
23+
MAP_KEY=CpmU3oZqTWtPoFatbgpQAJNhmTq816Edp1xZpZAQiTUv
24+
PGM_KEY=FKVZxSxY4WnwLTgQQmzMoBF87hpsT2K4BPcMcT9u1YGD
25+
;;
26+
*)
27+
echo "Unknown environment. Please use: devnet, pythnet"
28+
exit 1;
29+
esac
1630
if [ -z "$KDIR" ] ; then
1731
KDIR=$HOME/.pythd
1832
fi
19-
echo "7LmwnZDXi2d9dYsp45WsPkudU2Gb2ftjUC6fsxYvZocu" > $KDIR/program_key.json
33+
34+
PKEY_FILE=$KDIR/publish_key_pair.json
35+
if [ ! -f $PKEY_FILE ] ; then
36+
echo "cannot find $PKEY_FILE"
37+
exit 1
38+
fi
39+
40+
echo $PGM_KEY > $KDIR/program_key.json
2041
check "chmod 0400 $KDIR/program_key.json"
21-
echo "HQ9xBAuxpXcd9BgNjgE1Jm4uhwvU8BicP5w3gKfPRuAo" > $KDIR/mapping_key.json
42+
echo $MAP_KEY > $KDIR/mapping_key.json
2243
check "chmod 0400 $KDIR/mapping_key.json"

0 commit comments

Comments
 (0)