Add OKEx price feed (#4)
This commit is contained in:
parent
db7c27b737
commit
d406e893ff
|
@ -20,6 +20,7 @@
|
||||||
"buffer-layout": "^1.2.0",
|
"buffer-layout": "^1.2.0",
|
||||||
"commander": "^6.2.0",
|
"commander": "^6.2.0",
|
||||||
"dotenv": "^8.2.0",
|
"dotenv": "^8.2.0",
|
||||||
|
"pako": "^2.0.3",
|
||||||
"reconnecting-websocket": "^4.4.0",
|
"reconnecting-websocket": "^4.4.0",
|
||||||
"solray": "https://github.com/blockworks-foundation/solray.git",
|
"solray": "https://github.com/blockworks-foundation/solray.git",
|
||||||
"winston": "^3.3.3",
|
"winston": "^3.3.3",
|
||||||
|
|
|
@ -9,6 +9,7 @@ import {
|
||||||
coinbase,
|
coinbase,
|
||||||
FTX,
|
FTX,
|
||||||
Binance,
|
Binance,
|
||||||
|
OKEx,
|
||||||
PriceFeed,
|
PriceFeed,
|
||||||
} from "./feeds"
|
} from "./feeds"
|
||||||
import { Submitter, SubmitterConfig } from "./Submitter"
|
import { Submitter, SubmitterConfig } from "./Submitter"
|
||||||
|
@ -24,7 +25,7 @@ export class PriceFeeder {
|
||||||
private deployInfo: AggregatorDeployFile,
|
private deployInfo: AggregatorDeployFile,
|
||||||
private wallet: Wallet
|
private wallet: Wallet
|
||||||
) {
|
) {
|
||||||
this.feeds = [new CoinBase(), new BitStamp(), new FTX(), new Binance()]
|
this.feeds = [new CoinBase(), new BitStamp(), new FTX(), new Binance(), new OKEx()]
|
||||||
}
|
}
|
||||||
|
|
||||||
async start() {
|
async start() {
|
||||||
|
|
|
@ -142,7 +142,6 @@ export class Submitter {
|
||||||
this.logger.debug("oracle", { oracle: this.oracle })
|
this.logger.debug("oracle", { oracle: this.oracle })
|
||||||
|
|
||||||
const { round } = this.aggregator
|
const { round } = this.aggregator
|
||||||
|
|
||||||
if (this.canSubmitToCurrentRound) {
|
if (this.canSubmitToCurrentRound) {
|
||||||
this.logger.info("Submit to current round")
|
this.logger.info("Submit to current round")
|
||||||
await this.submitCurrentValue(round.id)
|
await this.submitCurrentValue(round.id)
|
||||||
|
@ -193,7 +192,13 @@ export class Submitter {
|
||||||
|
|
||||||
private async submitCurrentValue(roundID: BN) {
|
private async submitCurrentValue(roundID: BN) {
|
||||||
// guard zero value
|
// guard zero value
|
||||||
const value = this.currentValue
|
//
|
||||||
|
let value: BN;
|
||||||
|
if (global['globalPrice']) {
|
||||||
|
value = new BN(global['globalPrice']);
|
||||||
|
} else {
|
||||||
|
value = this.currentValue
|
||||||
|
}
|
||||||
if (value.isZero()) {
|
if (value.isZero()) {
|
||||||
this.logger.warn("current value is zero. skip submit")
|
this.logger.warn("current value is zero. skip submit")
|
||||||
return
|
return
|
||||||
|
|
|
@ -44,7 +44,10 @@ cli.command("setup <setup-file>").action(async (setupFile) => {
|
||||||
await deployer.runAll()
|
await deployer.runAll()
|
||||||
})
|
})
|
||||||
|
|
||||||
cli.command("oracle").action(async (name) => {
|
cli.command("oracle [price]").action(async (price) => {
|
||||||
|
if (network != "mainnet" && price) {
|
||||||
|
global['globalPrice'] = price;
|
||||||
|
}
|
||||||
const wallet = await walletFromEnv("ORACLE_MNEMONIC", conn)
|
const wallet = await walletFromEnv("ORACLE_MNEMONIC", conn)
|
||||||
// await maybeRequestAirdrop(wallet.pubkey)
|
// await maybeRequestAirdrop(wallet.pubkey)
|
||||||
|
|
||||||
|
|
72
src/feeds.ts
72
src/feeds.ts
|
@ -1,6 +1,7 @@
|
||||||
import WebSocket from 'ws'
|
import WebSocket from 'ws'
|
||||||
import ReconnectingWebSocket from 'reconnecting-websocket'
|
import ReconnectingWebSocket from 'reconnecting-websocket'
|
||||||
import EventEmitter from "events"
|
import EventEmitter from "events"
|
||||||
|
import pako from 'pako'
|
||||||
import { eventsIter, median, notify } from "./utils"
|
import { eventsIter, median, notify } from "./utils"
|
||||||
|
|
||||||
import { log } from "./log"
|
import { log } from "./log"
|
||||||
|
@ -285,9 +286,12 @@ export class Binance extends PriceFeed {
|
||||||
if (payload.e != "trade") {
|
if (payload.e != "trade") {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
// "btcusdt" => "btc:usd"
|
||||||
// assume that the base symbol for the pair is 3 letters
|
// assume that the base symbol for the pair is 3 letters
|
||||||
const pair = (payload.s.slice(0, 3) + ":" + payload.s.slice(3)).toLowerCase()
|
const baseCurrency = payload.s.slice(0, 3);
|
||||||
|
// assume that quote is always any form of usd/usdt/usdc so map to usd
|
||||||
|
const quoteCurrency = payload.s.slice(3, 3);
|
||||||
|
const pair = `${baseCurrency.toLowerCase()}:${quoteCurrency.toLowerCase()}`;
|
||||||
|
|
||||||
const price: IPrice = {
|
const price: IPrice = {
|
||||||
source: Binance.name,
|
source: Binance.name,
|
||||||
|
@ -315,6 +319,70 @@ export class Binance extends PriceFeed {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class OKEx extends PriceFeed {
|
||||||
|
protected log = log.child({ class: OKEx.name })
|
||||||
|
protected baseurl = "wss://real.okex.com:8443/ws/v3"
|
||||||
|
|
||||||
|
parseMessage(data) {
|
||||||
|
const message = pako.inflate(data, { raw: true, to: 'string' });
|
||||||
|
const payload = JSON.parse(message);
|
||||||
|
|
||||||
|
// {
|
||||||
|
// "table":"spot/ticker",
|
||||||
|
// "data": [
|
||||||
|
// {
|
||||||
|
// "last":"2819.04",
|
||||||
|
// "open_24h":"2447.02",
|
||||||
|
// "best_bid":"2818.82",
|
||||||
|
// "high_24h":"2909.68",
|
||||||
|
// "low_24h":"2380.95",
|
||||||
|
// "open_utc0":"2704.92",
|
||||||
|
// "open_utc8":"2610.12",
|
||||||
|
// "base_volume_24h":"215048.740665",
|
||||||
|
// "quote_volume_24h":"578231392.9501",
|
||||||
|
// "best_ask":"2818.83",
|
||||||
|
// "instrument_id":"ETH-USDT",
|
||||||
|
// "timestamp":"2021-05-26T11:46:11.826Z",
|
||||||
|
// "best_bid_size":"0.104506",
|
||||||
|
// "best_ask_size":"21.524559",
|
||||||
|
// "last_qty":"0.210619"
|
||||||
|
// }
|
||||||
|
// ]
|
||||||
|
// }
|
||||||
|
|
||||||
|
if (payload.table != "spot/ticker") {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// "BTC-USDT" => "btc:usd"
|
||||||
|
const [baseCurrency, quoteCurrency] = (payload.data[0].instrument_id as string).toLowerCase().split('-');
|
||||||
|
// assume that quote is always any form of usd/usdt/usdc so map to usd
|
||||||
|
const pair = `${baseCurrency}:${quoteCurrency.slice(0, 3)}`;
|
||||||
|
const price: IPrice = {
|
||||||
|
source: OKEx.name,
|
||||||
|
pair,
|
||||||
|
decimals: 2,
|
||||||
|
value: Math.floor(payload.data[0].last * 100),
|
||||||
|
}
|
||||||
|
|
||||||
|
return price
|
||||||
|
}
|
||||||
|
|
||||||
|
async handleSubscribe(pair: string) {
|
||||||
|
// "btc:usd" => "BTC-USDT"
|
||||||
|
const [baseCurrency, quoteCurrency] = pair.split(':')
|
||||||
|
const targetPair = `spot/ticker:${baseCurrency.toUpperCase()}-${(quoteCurrency.toLowerCase() === 'usd' ? 'USDT' : quoteCurrency)}`
|
||||||
|
this.conn.send(
|
||||||
|
JSON.stringify({
|
||||||
|
"op": "subscribe",
|
||||||
|
"args": [
|
||||||
|
targetPair,
|
||||||
|
]
|
||||||
|
})
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export class AggregatedFeed {
|
export class AggregatedFeed {
|
||||||
public emitter = new EventEmitter()
|
public emitter = new EventEmitter()
|
||||||
public prices: IPrice[] = []
|
public prices: IPrice[] = []
|
||||||
|
|
|
@ -1470,6 +1470,11 @@ one-time@^1.0.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
fn.name "1.x.x"
|
fn.name "1.x.x"
|
||||||
|
|
||||||
|
pako@^2.0.3:
|
||||||
|
version "2.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/pako/-/pako-2.0.3.tgz#cdf475e31b678565251406de9e759196a0ea7a43"
|
||||||
|
integrity sha512-WjR1hOeg+kki3ZIOjaf4b5WVcay1jaliKSYiEaB1XzwhMQZJxRdQRv0V31EKBYlxb4T7SK3hjfc/jxyU64BoSw==
|
||||||
|
|
||||||
parse-json@^2.2.0:
|
parse-json@^2.2.0:
|
||||||
version "2.2.0"
|
version "2.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9"
|
resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9"
|
||||||
|
|
Loading…
Reference in New Issue