Skip to content

Commit 4e1daf7

Browse files
committed
Merge remote-tracking branch 'origin/main' into devnet
2 parents 521c617 + 4b02739 commit 4e1daf7

16 files changed

+836
-224
lines changed

doc/websocket_api.md

+178-1
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
# pyth-client websocket API
2-
The pythd daemon supports a websocket interface based on the jsoni-rpc 2.0 standard. Methods include:
2+
The pythd daemon supports a websocket interface based on the json-rpc 2.0 standard. Methods include:
33

44
- [get_product_list](#get_product_list)
55
- [update_price](#update_price)
66
- [subscribe_price](#subscribe_price)
77
- [subscribe_price_sched](#subscribe_price_sched)
8+
- [get_product](#get_product)
9+
- [get_all_products](#get_all_products)
810

911
Batch requests are processed in the order the requests appear within the batch.
1012

@@ -196,3 +198,178 @@ Where the result is an integer corresponding to a subscription identifier. All s
196198
}
197199
}
198200
```
201+
202+
## get_product
203+
204+
Get full set of data for the given product.
205+
206+
Request looks like:
207+
```
208+
{
209+
"jsonrpc": "2.0",
210+
"method": "get_product",
211+
"params": {
212+
"account": "4aDoSXJ5o3AuvL7QFeR6h44jALQfTmUUCTVGDD6aoJTM"
213+
},
214+
"id" : 1
215+
}
216+
```
217+
218+
A successful response looks something like:
219+
```
220+
{
221+
"jsonrpc": "2.0",
222+
"result": {
223+
"account": "4aDoSXJ5o3AuvL7QFeR6h44jALQfTmUUCTVGDD6aoJTM",
224+
"attr_dict": {
225+
"asset_type": "Crypto",
226+
"symbol": "BTC/USD",
227+
"country": "US",
228+
"quote_currency": "USD",
229+
"description": "BTC/USD",
230+
"tenor": "Spot",
231+
"generic_symbol": "BTCUSD"
232+
},
233+
"price_accounts": [
234+
{
235+
"account": "GVXRSBjFk6e6J3NbVPXohDJetcTjaeeuykUpbQF8UoMU",
236+
"price_type": "price",
237+
"price_exponent": -8,
238+
"status": "trading",
239+
"price": 4426101900000,
240+
"conf": 4271150000,
241+
"twap": 4433467600000,
242+
"twac": 1304202670,
243+
"valid_slot": 91402257,
244+
"pub_slot": 91402259,
245+
"prev_slot": 91402256,
246+
"prev_price": 4425895500000,
247+
"prev_conf": 3315350000,
248+
"publisher_accounts": [
249+
{
250+
"account": "HekM1hBawXQu6wK6Ah1yw1YXXeMUDD2bfCHEzo25vnEB",
251+
"status": "trading",
252+
"price": 4426958500000,
253+
"conf": 1492500000,
254+
"slot": 91402255
255+
},
256+
{
257+
"account": "GKNcUmNacSJo4S2Kq3DuYRYRGw3sNUfJ4tyqd198t6vQ",
258+
"status": "trading",
259+
"price": 4424690000000,
260+
"conf": 3690000000,
261+
"slot": 91402256
262+
}
263+
]
264+
}
265+
]
266+
},
267+
"id": 1
268+
}
269+
```
270+
271+
## get_all_products
272+
273+
Get full set of data for all products.
274+
275+
Request looks like:
276+
```
277+
{
278+
"jsonrpc": "2.0",
279+
"method": "get_all_products",
280+
"id" : 1
281+
}
282+
```
283+
284+
A successful response looks something like:
285+
```
286+
{
287+
"jsonrpc": "2.0",
288+
"result": [
289+
{
290+
"account": "5uKdRzB3FzdmwyCHrqSGq4u2URja617jqtKkM71BVrkw",
291+
"attr_dict": {
292+
"asset_type": "Crypto",
293+
"symbol": "BCH/USD",
294+
"country": "US",
295+
"quote_currency": "USD",
296+
"description": "BCH/USD",
297+
"tenor": "Spot",
298+
"generic_symbol": "BCHUSD"
299+
},
300+
"price_accounts": [
301+
{
302+
"account": "5ALDzwcRJfSyGdGyhP3kP628aqBNHZzLuVww7o9kdspe",
303+
"price_type": "price",
304+
"price_exponent": -8,
305+
"status": "trading",
306+
"price": 60282000000,
307+
"conf": 26000000,
308+
"twap": 60321475000,
309+
"twac": 22504746,
310+
"valid_slot": 91402601,
311+
"pub_slot": 91402604,
312+
"prev_slot": 91402600,
313+
"prev_price": 60282000000,
314+
"prev_conf": 26000000,
315+
"publisher_accounts": [
316+
{
317+
"account": "HekM1hBawXQu6wK6Ah1yw1YXXeMUDD2bfCHEzo25vnEB",
318+
"status": "trading",
319+
"price": 60282000000,
320+
"conf": 26000000,
321+
"slot": 91402599
322+
},
323+
{
324+
"account": "2V7t5NaKY7aGkwytCWQgvUYZfEr9XMwNChhJEakTExk6",
325+
"status": "unknown",
326+
"price": 0,
327+
"conf": 0,
328+
"slot": 0
329+
}
330+
]
331+
}
332+
]
333+
},
334+
{
335+
"account": "3nuELNFBkbXqsXtnCzphRPCX6toKKYxVDnkyr9pTwB1K",
336+
"attr_dict": {
337+
"asset_type": "Crypto",
338+
"symbol": "SABER/USD",
339+
"country": "US",
340+
"quote_currency": "USD",
341+
"description": "SABER/USD",
342+
"tenor": "Spot",
343+
"generic_symbol": "SABERUSD"
344+
},
345+
"price_accounts": [
346+
{
347+
"account": "8Td9VML1nHxQK6M8VVyzsHo32D7VBk72jSpa9U861z2A",
348+
"price_type": "price",
349+
"price_exponent": -8,
350+
"status": "trading",
351+
"price": 5785000,
352+
"conf": 5000,
353+
"twap": 5856365,
354+
"twac": 10241,
355+
"valid_slot": 91402601,
356+
"pub_slot": 91402604,
357+
"prev_slot": 91402600,
358+
"prev_price": 5785000,
359+
"prev_conf": 5000,
360+
"publisher_accounts": [
361+
{
362+
"account": "GKNcUmNacSJo4S2Kq3DuYRYRGw3sNUfJ4tyqd198t6vQ",
363+
"status": "trading",
364+
"price": 5785000,
365+
"conf": 5000,
366+
"slot": 91402601
367+
}
368+
]
369+
}
370+
]
371+
}
372+
],
373+
"id": 1
374+
}
375+
```

pc/attr_id.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ void attr_dict::write_account( net_wtr& wtr )
107107
}
108108
}
109109

110-
void attr_dict::write_json( json_wtr& wtr )
110+
void attr_dict::write_json( json_wtr& wtr ) const
111111
{
112112
str vstr, kstr;
113113
for( unsigned id=1; id < avec_.size(); ++id ) {

pc/attr_id.hpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ namespace pc
5959
void write_account( net_wtr& );
6060

6161
// serialize to json
62-
void write_json( json_wtr& );
62+
void write_json( json_wtr& ) const;
6363

6464
private:
6565

pc/manager.cpp

+53-7
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ manager::manager()
5555
ctimeout_( PC_NSECS_IN_SEC ),
5656
slot_( 0UL ),
5757
slot_cnt_( 0UL ),
58+
slot_ts_{ 0UL },
5859
curr_ts_( 0L ),
5960
pub_ts_( 0L ),
6061
pub_int_( PC_PUB_INTERVAL ),
@@ -69,6 +70,7 @@ manager::manager()
6970
breq_->set_sub( this );
7071
sreq_->set_sub( this );
7172
preq_->set_sub( this );
73+
areq_->set_sub( this );
7274
tconn_.set_net_parser( &txp_ );
7375
txp_.mgr_ = this;
7476
}
@@ -130,6 +132,16 @@ std::string manager::get_tx_host() const
130132
return thost_;
131133
}
132134

135+
void manager::set_do_ws( bool do_ws )
136+
{
137+
do_ws_ = do_ws;
138+
}
139+
140+
bool manager::get_do_ws() const
141+
{
142+
return do_ws_;
143+
}
144+
133145
void manager::set_do_tx( bool do_tx )
134146
{
135147
do_tx_ = do_tx;
@@ -343,6 +355,11 @@ bool manager::get_is_tx_send() const
343355
return tconn_.get_is_send();
344356
}
345357

358+
bool manager::get_is_rpc_send() const
359+
{
360+
return hconn_.get_is_send() || wconn_.get_is_send();
361+
}
362+
346363
bool manager::bootstrap()
347364
{
348365
int status = PC_PYTH_RPC_CONNECTED | PC_PYTH_HAS_BLOCK_HASH;
@@ -441,6 +458,13 @@ void manager::poll( bool do_wait )
441458
clnt_.send( sreq_ );
442459
}
443460
}
461+
if ( ! get_do_ws() ) {
462+
if ( areq_->get_is_recv() ) {
463+
if ( has_status( PC_PYTH_RPC_CONNECTED ) ) {
464+
clnt_.send( areq_ );
465+
}
466+
}
467+
}
444468
}
445469

446470
// try to (re)connect to tx proxy
@@ -523,9 +547,15 @@ void manager::reconnect_rpc()
523547
set_err_msg( "missing or invalid program public key [" +
524548
get_program_pub_key_file() + "]" );
525549
} else {
526-
preq_->set_commitment( get_commitment() );
527-
preq_->set_program( gpub );
528-
clnt_.send( preq_ );
550+
if ( get_do_ws() ) {
551+
preq_->set_commitment( get_commitment() );
552+
preq_->set_program( get_program_pub_key() );
553+
clnt_.send( preq_ );
554+
}
555+
else {
556+
areq_->set_commitment( get_commitment() );
557+
areq_->set_program( get_program_pub_key() );
558+
}
529559
}
530560

531561
// gather latest info on mapping accounts
@@ -673,7 +703,7 @@ void manager::on_response( rpc::get_slot *res )
673703

674704
PC_LOG_DBG( "received get_slot" )
675705
.add( "slot", slot_ )
676-
.add( "rount_trip_time(ms)", 1e-6*ack_ts )
706+
.add( "round_trip_time(ms)", 1e-6*ack_ts )
677707
.end();
678708

679709
// submit block hash every N slots
@@ -710,18 +740,34 @@ void manager::on_response( rpc::get_recent_block_hash *m )
710740
PC_LOG_INF( "received_recent_block_hash" )
711741
.add( "curr_slot", slot_ )
712742
.add( "hash_slot", m->get_slot() )
713-
.add( "rount_trip_time(ms)", 1e-6*ack_ts )
743+
.add( "round_trip_time(ms)", 1e-6*ack_ts )
714744
.end();
715745

716746
}
717747

718-
void manager::on_response( rpc::program_subscribe *m )
748+
void manager::on_response( rpc::account_update *m )
719749
{
720750
if ( m->get_is_err() ) {
721-
set_err_msg( "failed to program_subscribe ["
751+
set_err_msg( "account update failed ["
722752
+ m->get_err_msg() + "]" );
723753
return;
724754
}
755+
756+
if ( m->get_is_http() ) {
757+
int64_t ack_ts = m->get_recv_time() - m->get_sent_time();
758+
PC_LOG_DBG( "received account_update" )
759+
.add( "account", *m->get_account() )
760+
.add( "slot", slot_ )
761+
.add( "round_trip_time(ms)", 1e-6*ack_ts )
762+
.end();
763+
}
764+
else {
765+
PC_LOG_DBG( "received account_update" )
766+
.add( "account", *m->get_account() )
767+
.add( "slot", slot_ )
768+
.end();
769+
}
770+
725771
// look up by account and dispatch update
726772
acc_map_t::iter_t it = amap_.find( *m->get_account() );
727773
if ( it ) {

pc/manager.hpp

+9-2
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ namespace pc
5050
public rpc_sub,
5151
public rpc_sub_i<rpc::get_slot>,
5252
public rpc_sub_i<rpc::get_recent_block_hash>,
53-
public rpc_sub_i<rpc::program_subscribe>
53+
public rpc_sub_i<rpc::account_update>
5454
{
5555
public:
5656

@@ -65,6 +65,10 @@ namespace pc
6565
void set_tx_host( const std::string& );
6666
std::string get_tx_host() const;
6767

68+
// turn on/off ws subscriptions
69+
void set_do_ws( bool );
70+
bool get_do_ws() const;
71+
6872
// turn on/off tx proxy mode
6973
void set_do_tx( bool );
7074
bool get_do_tx() const;
@@ -166,9 +170,10 @@ namespace pc
166170
// rpc callbacks
167171
void on_response( rpc::get_slot * ) override;
168172
void on_response( rpc::get_recent_block_hash * ) override;
169-
void on_response( rpc::program_subscribe * ) override;
173+
void on_response( rpc::account_update * ) override;
170174
void set_status( int );
171175
get_mapping *get_last_mapping() const;
176+
bool get_is_rpc_send() const;
172177

173178
private:
174179

@@ -235,6 +240,7 @@ namespace pc
235240
kpx_vec_t kvec_; // symbol price scheduling
236241
bool wait_conn_;// waiting on connection
237242
bool do_cap_; // do capture flag
243+
bool do_ws_; // do ws subscriptions
238244
bool do_tx_; // do tx proxy connectivity
239245
bool is_pub_; // is publishing mode
240246
capture cap_; // aggregate price capture
@@ -245,6 +251,7 @@ namespace pc
245251
rpc::get_slot sreq_[1]; // slot subscription
246252
rpc::get_recent_block_hash breq_[1]; // block hash request
247253
rpc::program_subscribe preq_[1]; // program account subscription
254+
rpc::get_program_accounts areq_[1]; // alternative to program_subscribe
248255
};
249256

250257
inline bool manager::get_is_tx_connect() const

pc/misc.hpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44
#include <string>
55

66
#define PC_PACKED __attribute__((__packed__))
7-
#define PC_UNLIKELY(ARG) __builtin_expect((ARG),1)
7+
#define PC_LIKELY(ARG) __builtin_expect((ARG),1)
8+
#define PC_UNLIKELY(ARG) __builtin_expect((ARG),0)
89
#define PC_NSECS_IN_SEC 1000000000L
910
#define PC_NSECS_IN_MSEC 1000000L
1011

0 commit comments

Comments
 (0)