1. Pyth 価格 ID を取得する方法は?#
Human: https://pyth.network/developers/price-feed-ids
API: https://benchmarks.pyth.network/v1/price_feeds/
例えば、BTC=0xe62df6c8b4a85fe1a67db44dc12de5db330f7ac66b72dc658afedf0f4a415b43
、ETH=0xff61491a931112ddf1bd8147cd1b641375f79f5825126d665480874634fd0ace
2. 最新の価格を取得する方法は?#
Python での使用をより簡単にするために:
>>> from simplebase import *
>>> PYTHP.eth
3141.0950000000003
>>> PYTHP.btc
64786.00749999
実装:
class class_PYTHPRICE():
def load_conf(self, refresh=False):
if not self.conf:
if (not refresh) and os.path.isfile("/tmp/pyth.json"):
self.conf = json.load(open("/tmp/pyth.json"))
else:
self.conf = sess.get("https://benchmarks.pyth.network/v1/price_feeds/").json()
open("/tmp/pyth.json", "w").write(json.dumps(self.conf))
return self.conf
def __init__(self, cachetime=60, refresh=False):
self.conf = None
self.cache = {}
self.cachetime = cachetime
if refresh:
self.load_conf(refresh=True)
def __getattr__(self, token):
if token in self.cache and time.time()-self.cache[token][0]<self.cachetime:
return self.cache[token][1]
conf = self.load_conf()
pythid = [i for i in conf if i["attributes"]["generic_symbol"]==token.upper()+"USD"][0]["id"]
x = sess.get("https://hermes.pyth.network/api/latest_price_feeds?ids[]="+pythid)
p = x.json()[0]["price"]
price = float(p["price"])*10**(p["expo"])
self.cache[token] = [p["publish_time"], price]
return price
PYTHP = class_PYTHPRICE()
3. リアルタイム価格フィードを購読する方法は?#
websocket に接続してwss://hermes.pyth.network/ws
、メッセージを送信します:{"type":"subscribe","ids":["0xff61491a931112ddf1bd8147cd1b641375f79f5825126d665480874634fd0ace", "0xe62df6c8b4a85fe1a67db44dc12de5db330f7ac66b72dc658afedf0f4a415b43"]}
# proxychains wscat --connect wss://hermes.pyth.network/ws
接続されました(CTRL+Cで終了)
> {"type":"subscribe","ids":["0xff61491a931112ddf1bd8147cd1b641375f79f5825126d665480874634fd0ace", "0xe62df6c8b4a85fe1a67db44dc12de5db330f7ac66b72dc658afedf0f4a415b43"]}
< {"type":"response","status":"success"}
< {"type":"price_update","price_feed":{"id":"ff61491a931112ddf1bd8147cd1b641375f79f5825126d665480874634fd0ace","price":{"price":"314558126642","conf":"204820667","expo":-8,"publish_time":1713754685},"ema_price":{"price":"314640770000","conf":"271902490","expo":-8,"publish_time":1713754685}}}
< {"type":"price_update","price_feed":{"id":"e62df6c8b4a85fe1a67db44dc12de5db330f7ac66b72dc658afedf0f4a415b43","price":{"price":"6478190154574","conf":"3512845425","expo":-8,"publish_time":1713754685},"ema_price":{"price":"6482023900000","conf":"3546467800","expo":-8,"publish_time":1713754685}}}
4. オンチェーン価格を取得する方法は?#
注意:オンチェーン価格は、誰も更新をプッシュしない場合は更新されません。ChainLink とは異なります。古い価格を読む際には注意してください。
契約アドレス:https://docs.pyth.network/price-feeds/contract-addresses/evm
struct Price {
// 価格
int64 price;
// 価格の信頼区間
uint64 conf;
// 価格の指数
int32 expo;
// 価格が公開された時刻を示すUnixタイムスタンプ
uint publishTime;
}
function getPriceUnsafe(
bytes32 id
) external returns (Price memory price);
5. オンチェーンで価格をプッシュする方法は?#
https://github.com/pyth-network/pyth-crosschain/tree/main/apps/price_pusher
私の実装の一部は以下の通りです:
import websocket, sys
from math import fabs
from simplebase import *
... # さらにインポート
pythids = [assetId2asset[i]["id"].replace("0x","") for i in tokenIds]
BAR1=4.8
BAR2=3
oldnonce = None
@lru_cache(10)
def get_onchain_prices(ts=None):
global oldnonce, olddata
nonce = eth_getNonce(RPC, MYADDR)
if nonce==oldnonce:
return olddata
oldnonce = nonce
print("fetch")
onchain_prices = batch_callfunction_decode(RPC, [[PYTH, "getPriceUnsafe(bytes32)", ec(["bytes32"], [bd(i)]) ] for i in pythids], ["(uint256,uint256,int256,uint256)"])
olddata = dict(zip(pythids, [i[0] for i in onchain_prices]))
return olddata
def process_push():
global oldnonce
oc = get_onchain_prices(int(time.time()))
prices = getprices(tokenIds, "https://hermes.pyth.network")
tosend = []
tmp = []
for myid, price, _, _ in prices:
token = assetId2asset[myid]
pythid = token["id"][2:]
onchainprice = oc[pythid]
diff = (price-onchainprice)/onchainprice*100
if diff>BAR2 or diff<-BAR2:
print("tosend:", myid, token["symbol"], diff)
tosend.append(pythid)
else:
tmp.append([pythid, fabs(diff)])
if len(tosend)<5:
tmp.sort(key=lambda i:i[1], reverse=True)
tosend += [i[0] for i in tmp[:5-len(tosend)]]
x = sess.get("https://hermes.pyth.network/api/latest_vaas?ids[]="+"&ids[]=".join(tosend))
sys.x = x
vaas = x.json()
updatefee = callfunction(RPC, PYTH, "getUpdateFee(bytes[])", ec(["bytes[]"], [[b64decode(i) for i in vaas]]))
print("updatefee:", updatefee)
tx = maketx(PYTH, "0xef9e5e28"+ec(["bytes[]"], [[b64decode(i) for i in vaas]]), oldnonce, 5*10**8, sendamount=updatefee, showgas=True, writetx=False)
waittx(tx)
oldnonce = 0
def on_message(wsapp, message):
oc = get_onchain_prices(int(time.time()))
try:
message = json.loads(message)
if message["type"]=="price_update":
pythid = message["price_feed"]["id"]
symbol = pythid2token[pythid]["pythSymbol"]
#ts = message["price_feed"]["price"]["publish_time"];
price = int(message["price_feed"]["price"]["price"])
oldprice = oc[pythid]
diff = (price-oldprice)/oldprice*100
if diff>BAR1 or diff<-BAR1:
print(symbol, price, diff)
process_push()
except:
traceback.print_exc()
raise
def on_open(wsapp):
print("open")
wsapp.send(json.dumps({"type":"subscribe","ids":pythids})+"\r\n")
if 1:
wsapp = websocket.WebSocketApp("wss://hermes.pyth.network/ws", on_message=on_message, on_open=on_open)
wsapp.run_forever()