Merge branch 'master' into resubmit_sol_srm
This commit is contained in:
commit
88de4f5669
17
README.md
17
README.md
|
@ -54,6 +54,23 @@ not use this key for production!
|
||||||
NOTE 2: You might get error messages if somebody else is also running the
|
NOTE 2: You might get error messages if somebody else is also running the
|
||||||
oracle.
|
oracle.
|
||||||
|
|
||||||
|
### Manual price feed
|
||||||
|
Alternatively, you can submit prices to the oracle manually by instructing the oracle to watch for changes to a local file.
|
||||||
|
This can be useful for testing specific behaviour (such as triggering liquidations).
|
||||||
|
|
||||||
|
Run the oracle:
|
||||||
|
```
|
||||||
|
yarn solink oracle-file {pair} {filepath}
|
||||||
|
```
|
||||||
|
|
||||||
|
{pair} must be one of the aggregator pairs in deploy.sandbox.json
|
||||||
|
|
||||||
|
Then you can update prices by running
|
||||||
|
```
|
||||||
|
echo {price} > {filepath}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
# Observe The Aggregators
|
# Observe The Aggregators
|
||||||
|
|
||||||
With the oracle running, you can subscribe to price changes. In another
|
With the oracle running, you can subscribe to price changes. In another
|
||||||
|
|
|
@ -0,0 +1,67 @@
|
||||||
|
{
|
||||||
|
"aggregators": {
|
||||||
|
"btc:usd": {
|
||||||
|
"decimals": 2,
|
||||||
|
"minSubmissions": 1,
|
||||||
|
"maxSubmissions": 3,
|
||||||
|
"restartDelay": 0,
|
||||||
|
"rewardAmount": 10000,
|
||||||
|
"rewardTokenAccount": "3oLHHTaRqNsuTMjsTtkVy8bock6Bx8gCmDxku4TurVj1",
|
||||||
|
"oracles": [
|
||||||
|
"blockworks",
|
||||||
|
"bartosz",
|
||||||
|
"defacto"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"eth:usd": {
|
||||||
|
"decimals": 2,
|
||||||
|
"minSubmissions": 1,
|
||||||
|
"maxSubmissions": 3,
|
||||||
|
"restartDelay": 0,
|
||||||
|
"rewardAmount": 10000,
|
||||||
|
"rewardTokenAccount": "3oLHHTaRqNsuTMjsTtkVy8bock6Bx8gCmDxku4TurVj1",
|
||||||
|
"oracles": [
|
||||||
|
"blockworks",
|
||||||
|
"bartosz",
|
||||||
|
"defacto"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"sol:usd": {
|
||||||
|
"decimals": 2,
|
||||||
|
"minSubmissions": 1,
|
||||||
|
"maxSubmissions": 3,
|
||||||
|
"restartDelay": 0,
|
||||||
|
"rewardAmount": 10000,
|
||||||
|
"rewardTokenAccount": "3oLHHTaRqNsuTMjsTtkVy8bock6Bx8gCmDxku4TurVj1",
|
||||||
|
"oracles": [
|
||||||
|
"blockworks",
|
||||||
|
"bartosz",
|
||||||
|
"defacto"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"srm:usd": {
|
||||||
|
"decimals": 2,
|
||||||
|
"minSubmissions": 1,
|
||||||
|
"maxSubmissions": 3,
|
||||||
|
"restartDelay": 0,
|
||||||
|
"rewardAmount": 10000,
|
||||||
|
"rewardTokenAccount": "3oLHHTaRqNsuTMjsTtkVy8bock6Bx8gCmDxku4TurVj1",
|
||||||
|
"oracles": [
|
||||||
|
"blockworks",
|
||||||
|
"bartosz",
|
||||||
|
"defacto"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"oracles": {
|
||||||
|
"blockworks": {
|
||||||
|
"owner": "GW6bnJN6cMNzVnoVfV9hW6vx6XxTfP8k3HA1PgWCumxV"
|
||||||
|
},
|
||||||
|
"bartosz": {
|
||||||
|
"owner": "3cGZFMZavPHzciggMLWzT74qdaakNAosMwQokHTEKmbx"
|
||||||
|
},
|
||||||
|
"defacto": {
|
||||||
|
"owner": "6KwCmCtjmaQg3jbX7dejnB29RqMByx32KryX3Lyuqmq8"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
49
src/cli.ts
49
src/cli.ts
|
@ -10,6 +10,8 @@ import { PriceFeeder } from "./PriceFeeder"
|
||||||
import { sleep, walletFromEnv } from "./utils"
|
import { sleep, walletFromEnv } from "./utils"
|
||||||
import { PublicKey, Wallet } from "solray"
|
import { PublicKey, Wallet } from "solray"
|
||||||
import { log } from "./log"
|
import { log } from "./log"
|
||||||
|
import { Submitter } from "./Submitter"
|
||||||
|
import { file } from "./feeds"
|
||||||
|
|
||||||
const cli = new Command()
|
const cli = new Command()
|
||||||
|
|
||||||
|
@ -86,4 +88,51 @@ cli.command("observe").action(async (name?: string) => {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
cli.command("oracle-file <pair> <path>").action(async (pair, path) => {
|
||||||
|
|
||||||
|
console.log(pair);
|
||||||
|
console.log(path);
|
||||||
|
|
||||||
|
let deployInfo = loadJSONFile<AggregatorDeployFile>(process.env.DEPLOY_FILE!)
|
||||||
|
|
||||||
|
// validate pair arg here
|
||||||
|
if (!(pair in deployInfo.aggregators)) {
|
||||||
|
throw 'Invalid pair ' + pair;
|
||||||
|
}
|
||||||
|
|
||||||
|
let slot = await conn.getSlot()
|
||||||
|
conn.onSlotChange((slotInfo) => {
|
||||||
|
slot = slotInfo.slot
|
||||||
|
})
|
||||||
|
|
||||||
|
const wallet = await walletFromEnv("ORACLE_MNEMONIC", conn)
|
||||||
|
// await maybeRequestAirdrop(wallet.pubkey)
|
||||||
|
|
||||||
|
let aggregatorInfo = deployInfo.aggregators[pair];
|
||||||
|
|
||||||
|
const oracleInfo = Object.values(aggregatorInfo.oracles).find(
|
||||||
|
(oracleInfo) => {
|
||||||
|
return oracleInfo.owner.equals(wallet.pubkey)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
let minValueChangeForNewRound = 0
|
||||||
|
|
||||||
|
const submitter = new Submitter(
|
||||||
|
deployInfo.programID,
|
||||||
|
aggregatorInfo.pubkey,
|
||||||
|
oracleInfo!.pubkey,
|
||||||
|
wallet,
|
||||||
|
file(pair, path),
|
||||||
|
{
|
||||||
|
minValueChangeForNewRound,
|
||||||
|
},
|
||||||
|
() => slot
|
||||||
|
)
|
||||||
|
|
||||||
|
submitter.start();
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
cli.parse(process.argv)
|
cli.parse(process.argv)
|
||||||
|
|
32
src/feeds.ts
32
src/feeds.ts
|
@ -6,7 +6,7 @@ import { eventsIter, median, notify } from "./utils"
|
||||||
|
|
||||||
import { log } from "./log"
|
import { log } from "./log"
|
||||||
import winston from "winston"
|
import winston from "winston"
|
||||||
|
import fs from "fs";
|
||||||
|
|
||||||
const SECONDS = 1000
|
const SECONDS = 1000
|
||||||
export const UPDATE = "UPDATE"
|
export const UPDATE = "UPDATE"
|
||||||
|
@ -292,6 +292,7 @@ export class Binance extends PriceFeed {
|
||||||
const quoteCurrency = payload.s.slice(3).toLowerCase();
|
const quoteCurrency = payload.s.slice(3).toLowerCase();
|
||||||
const pair = `${baseCurrency}:${quoteCurrency == 'busd' ? 'usd' : quoteCurrency}`;
|
const pair = `${baseCurrency}:${quoteCurrency == 'busd' ? 'usd' : quoteCurrency}`;
|
||||||
|
|
||||||
|
|
||||||
const price: IPrice = {
|
const price: IPrice = {
|
||||||
source: Binance.name,
|
source: Binance.name,
|
||||||
pair,
|
pair,
|
||||||
|
@ -511,3 +512,32 @@ export function coinbase(pair: string): IPriceFeed {
|
||||||
|
|
||||||
return eventsIter(emitter, UPDATE)
|
return eventsIter(emitter, UPDATE)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function file(pair: string, filepath: string): IPriceFeed {
|
||||||
|
const emitter = new EventEmitter()
|
||||||
|
|
||||||
|
try {
|
||||||
|
fs.accessSync(filepath);
|
||||||
|
} catch {
|
||||||
|
fs.writeFileSync(filepath, '');
|
||||||
|
console.log('feed file created at ' + filepath)
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('started file feed for ' + pair)
|
||||||
|
|
||||||
|
fs.watch(filepath, (event) => {
|
||||||
|
if (event === 'change') {
|
||||||
|
const data = fs.readFileSync(filepath, 'utf8')
|
||||||
|
const price: IPrice = {
|
||||||
|
source: "file",
|
||||||
|
pair,
|
||||||
|
decimals: 2,
|
||||||
|
value: parseFloat(data)
|
||||||
|
}
|
||||||
|
console.log('price update: ', price)
|
||||||
|
emitter.emit(UPDATE, price)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return eventsIter(emitter, UPDATE)
|
||||||
|
}
|
Loading…
Reference in New Issue