2020-12-09 03:41:15 -08:00
|
|
|
import { Connection, PublicKey } from "@solana/web3.js"
|
2020-12-08 05:14:05 -08:00
|
|
|
|
2020-12-08 23:52:28 -08:00
|
|
|
import { AggregatorLayout, SubmissionLayout, OracleLayout } from "./FluxAggregator"
|
2020-12-08 05:14:05 -08:00
|
|
|
|
2020-12-09 03:41:15 -08:00
|
|
|
import { solana, Wallet, NetworkName, Deployer } from "solray"
|
2020-12-08 05:14:05 -08:00
|
|
|
|
2020-12-10 03:39:52 -08:00
|
|
|
export function getMedian(submissions: number[]): number {
|
2020-12-08 05:14:05 -08:00
|
|
|
const values = submissions
|
|
|
|
.filter((s: any) => s.value != 0)
|
|
|
|
.map((s: any) => s.value)
|
2020-12-08 18:39:39 -08:00
|
|
|
.sort((a, b) => a - b)
|
2020-12-08 05:14:05 -08:00
|
|
|
|
2020-12-08 18:39:39 -08:00
|
|
|
let len = values.length
|
2020-12-08 05:14:05 -08:00
|
|
|
if (len == 0) {
|
2020-12-08 18:39:39 -08:00
|
|
|
return 0
|
2020-12-08 05:14:05 -08:00
|
|
|
} else if (len == 1) {
|
2020-12-08 18:39:39 -08:00
|
|
|
return values[0]
|
2020-12-08 05:14:05 -08:00
|
|
|
} else {
|
2020-12-08 18:39:39 -08:00
|
|
|
let i = len / 2
|
|
|
|
return len % 2 == 0 ? (values[i] + values[i-1])/2 : values[i]
|
2020-12-08 05:14:05 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
export function sleep(ms: number): Promise<void> {
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
setTimeout(() => {
|
2020-12-08 18:39:39 -08:00
|
|
|
resolve()
|
|
|
|
}, ms)
|
|
|
|
})
|
2020-12-08 05:14:05 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
export function decodeAggregatorInfo(accountInfo) {
|
2020-12-08 18:39:39 -08:00
|
|
|
const data = Buffer.from(accountInfo.data)
|
|
|
|
const aggregator = AggregatorLayout.decode(data)
|
2020-12-08 05:14:05 -08:00
|
|
|
|
2020-12-10 03:39:52 -08:00
|
|
|
const minSubmissionValue = aggregator.minSubmissionValue.readBigUInt64LE()
|
|
|
|
const maxSubmissionValue = aggregator.maxSubmissionValue.readBigUInt64LE()
|
2020-12-08 18:39:39 -08:00
|
|
|
const submitInterval = aggregator.submitInterval.readInt32LE()
|
2020-12-10 03:39:52 -08:00
|
|
|
const description = (aggregator.description.toString() as String).trim()
|
2020-12-09 03:41:15 -08:00
|
|
|
|
2020-12-08 05:14:05 -08:00
|
|
|
// decode oracles
|
2020-12-10 03:39:52 -08:00
|
|
|
let submissions: any[] = []
|
2020-12-08 18:39:39 -08:00
|
|
|
let submissionSpace = SubmissionLayout.span
|
2020-12-10 03:39:52 -08:00
|
|
|
let latestUpdateTime = BigInt(0)
|
2020-12-08 05:14:05 -08:00
|
|
|
|
|
|
|
for (let i = 0; i < aggregator.submissions.length / submissionSpace; i++) {
|
|
|
|
let submission = SubmissionLayout.decode(
|
|
|
|
aggregator.submissions.slice(i*submissionSpace, (i+1)*submissionSpace)
|
2020-12-08 18:39:39 -08:00
|
|
|
)
|
2020-12-10 03:39:52 -08:00
|
|
|
|
2020-12-08 18:39:39 -08:00
|
|
|
submission.oracle = new PublicKey(submission.oracle)
|
2020-12-10 03:39:52 -08:00
|
|
|
submission.time = submission.time.readBigInt64LE()
|
|
|
|
submission.value = submission.value.readBigInt64LE()
|
2020-12-09 03:41:15 -08:00
|
|
|
|
2020-12-08 05:14:05 -08:00
|
|
|
if (!submission.oracle.equals(new PublicKey(0))) {
|
2020-12-10 03:39:52 -08:00
|
|
|
submissions.push(submission)
|
2020-12-08 05:14:05 -08:00
|
|
|
}
|
2020-12-10 03:39:52 -08:00
|
|
|
|
|
|
|
if (submission.time > latestUpdateTime) {
|
|
|
|
latestUpdateTime = submission.time
|
2020-12-08 05:14:05 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return {
|
|
|
|
minSubmissionValue: minSubmissionValue,
|
|
|
|
maxSubmissionValue: maxSubmissionValue,
|
2020-12-10 03:39:52 -08:00
|
|
|
submissionValue: getMedian(submissions),
|
2020-12-08 05:14:05 -08:00
|
|
|
submitInterval,
|
|
|
|
description,
|
2020-12-10 03:39:52 -08:00
|
|
|
oracles: submissions.map(s => s.oracle.toString()),
|
|
|
|
latestUpdateTime: new Date(Number(latestUpdateTime)*1000),
|
2020-12-08 05:14:05 -08:00
|
|
|
}
|
2020-12-08 18:39:39 -08:00
|
|
|
}
|
|
|
|
|
2020-12-08 23:52:28 -08:00
|
|
|
export function decodeOracleInfo(accountInfo) {
|
|
|
|
const data = Buffer.from(accountInfo.data)
|
2020-12-09 03:41:15 -08:00
|
|
|
|
2020-12-08 23:52:28 -08:00
|
|
|
const oracle = OracleLayout.decode(data)
|
|
|
|
|
|
|
|
oracle.nextSubmitTime = oracle.nextSubmitTime.readBigUInt64LE().toString()
|
|
|
|
oracle.description = oracle.description.toString()
|
|
|
|
oracle.isInitialized = oracle.isInitialized != 0
|
|
|
|
oracle.withdrawable = oracle.withdrawable.readBigUInt64LE().toString()
|
|
|
|
oracle.aggregator = new PublicKey(oracle.aggregator).toBase58()
|
|
|
|
oracle.owner = new PublicKey(oracle.owner).toBase58()
|
|
|
|
|
|
|
|
return oracle
|
|
|
|
}
|
|
|
|
|
2020-12-09 03:41:15 -08:00
|
|
|
export async function walletFromEnv(key: string, conn: Connection): Promise<Wallet> {
|
|
|
|
const mnemonic = process.env[key]
|
|
|
|
if (!mnemonic) {
|
|
|
|
throw new Error(`Set ${key} in .env to be a mnemonic`)
|
|
|
|
}
|
2020-12-08 18:39:39 -08:00
|
|
|
|
2020-12-09 03:41:15 -08:00
|
|
|
return Wallet.fromMnemonic(mnemonic, conn)
|
|
|
|
}
|
2020-12-08 18:39:39 -08:00
|
|
|
|
2020-12-09 03:41:15 -08:00
|
|
|
export async function openDeployer(): Promise<Deployer> {
|
|
|
|
const deployFile = process.env.DEPLOY_FILE
|
2020-12-10 03:39:52 -08:00
|
|
|
|
2020-12-09 03:41:15 -08:00
|
|
|
if (!deployFile) {
|
|
|
|
throw new Error(`Set DEPLOY_FILE in .env`)
|
2020-12-08 18:39:39 -08:00
|
|
|
}
|
2020-12-09 03:41:15 -08:00
|
|
|
|
|
|
|
return Deployer.open(deployFile)
|
|
|
|
}
|