solana-flux-aggregator/src/utils.ts

108 lines
3.1 KiB
TypeScript
Raw Normal View History

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)
}