remove unused code
This commit is contained in:
parent
3a6b17f03d
commit
b77e338c4b
|
@ -16,40 +16,11 @@ import {
|
|||
SystemProgram,
|
||||
} from "@solana/web3.js"
|
||||
|
||||
import {
|
||||
publicKey,
|
||||
u64LEBuffer,
|
||||
uint64,
|
||||
BufferLayout,
|
||||
} from "solray/lib/util/encoding"
|
||||
|
||||
import { decodeOracleInfo } from "./utils"
|
||||
|
||||
// @ts-ignore
|
||||
// import BufferLayout from "buffer-layout";
|
||||
|
||||
import { AggregatorConfig, IAggregatorConfig, schema } from "./schema"
|
||||
import * as encoding from "./schema"
|
||||
import { deserialize, serialize } from "borsh"
|
||||
import { conn } from "./context"
|
||||
|
||||
export const AggregatorLayout = BufferLayout.struct([])
|
||||
|
||||
export const OracleLayout = BufferLayout.struct([
|
||||
uint64("nextSubmitTime"),
|
||||
BufferLayout.blob(32, "description"),
|
||||
BufferLayout.u8("isInitialized"),
|
||||
uint64("withdrawable"),
|
||||
publicKey("aggregator"),
|
||||
publicKey("owner"),
|
||||
])
|
||||
|
||||
export const SubmissionLayout = BufferLayout.struct([
|
||||
uint64("time"),
|
||||
uint64("value"),
|
||||
publicKey("oracle"),
|
||||
])
|
||||
|
||||
interface InitializeParams {
|
||||
config: IAggregatorConfig
|
||||
owner: Account
|
||||
|
|
344
src/cli.ts
344
src/cli.ts
|
@ -1,344 +0,0 @@
|
|||
import { Command, option } from "commander"
|
||||
|
||||
import fs from "fs"
|
||||
import path from "path"
|
||||
|
||||
import {
|
||||
BPFLoader,
|
||||
PublicKey,
|
||||
Wallet,
|
||||
NetworkName,
|
||||
solana,
|
||||
Deployer,
|
||||
SPLToken,
|
||||
ProgramAccount,
|
||||
} from "solray"
|
||||
|
||||
import dotenv from "dotenv"
|
||||
|
||||
import FluxAggregator from "./FluxAggregator"
|
||||
|
||||
import { decodeAggregatorInfo, sleep } from "./utils"
|
||||
|
||||
import * as feed from "./feed"
|
||||
import { AggregatorConfig } from "./schema"
|
||||
|
||||
dotenv.config()
|
||||
|
||||
const cli = new Command()
|
||||
|
||||
const FLUX_AGGREGATOR_SO = path.resolve(
|
||||
__dirname,
|
||||
"../build/flux_aggregator.so"
|
||||
)
|
||||
const network = (process.env.NETWORK || "local") as NetworkName
|
||||
const conn = solana.connect(network)
|
||||
|
||||
import { AppContext } from "./context"
|
||||
|
||||
function color(s, c = "black", b = false): string {
|
||||
// 30m Black, 31m Red, 32m Green, 33m Yellow, 34m Blue, 35m Magenta, 36m Cyanic, 37m White
|
||||
const cArr = [
|
||||
"black",
|
||||
"red",
|
||||
"green",
|
||||
"yellow",
|
||||
"blue",
|
||||
"megenta",
|
||||
"cyanic",
|
||||
"white",
|
||||
]
|
||||
|
||||
let cIdx = cArr.indexOf(c)
|
||||
let bold = b ? "\x1b[1m" : ""
|
||||
|
||||
return `\x1b[${30 + (cIdx > -1 ? cIdx : 0)}m${bold}${s}\x1b[0m`
|
||||
}
|
||||
|
||||
function error(message: string) {
|
||||
console.log("\n")
|
||||
console.error(color(message, "red"))
|
||||
console.log("\n")
|
||||
process.exit()
|
||||
}
|
||||
|
||||
function log(message: any) {
|
||||
console.log(message)
|
||||
}
|
||||
|
||||
cli.command("generate-wallet").action(async () => {
|
||||
const mnemonic = Wallet.generateMnemonic()
|
||||
const wallet = await Wallet.fromMnemonic(mnemonic, conn)
|
||||
|
||||
log(`address: ${wallet.address}`)
|
||||
log(`mnemonic: ${mnemonic}`)
|
||||
})
|
||||
|
||||
cli
|
||||
.command("airdrop <address>")
|
||||
.description(`request airdrop to the address`)
|
||||
.option("-m, --amount <amount>", "request amount in sol (10e9)", "10")
|
||||
.action(async (address, opts) => {
|
||||
const dest = new PublicKey(address)
|
||||
|
||||
const { amount } = opts
|
||||
|
||||
log(`requesting 10 sol airdrop to: ${address}`)
|
||||
await conn.requestAirdrop(dest, amount * 1e9)
|
||||
log("airdrop success")
|
||||
})
|
||||
|
||||
cli
|
||||
.command("deploy-program")
|
||||
.description("deploy the aggregator program")
|
||||
.action(async () => {
|
||||
const { wallet, deployer } = await AppContext.forAdmin()
|
||||
|
||||
const programAccount = await deployer.ensure(
|
||||
AppContext.AGGREGATOR_PROGRAM,
|
||||
async () => {
|
||||
const programBinary = fs.readFileSync(FLUX_AGGREGATOR_SO)
|
||||
|
||||
log(`deploying ${FLUX_AGGREGATOR_SO}...`)
|
||||
const bpfLoader = new BPFLoader(wallet)
|
||||
|
||||
return bpfLoader.load(programBinary)
|
||||
}
|
||||
)
|
||||
|
||||
log(
|
||||
`deployed aggregator program. program id: ${color(
|
||||
programAccount.publicKey.toBase58(),
|
||||
"blue"
|
||||
)}`
|
||||
)
|
||||
})
|
||||
|
||||
cli
|
||||
.command("add-aggregator")
|
||||
.description("create an aggregator")
|
||||
.option("--feedName <string>", "feed pair name")
|
||||
.option("--decimals <number>", "submission decimals", "2")
|
||||
.option("--minSubmissions <number>", "minSubmissions", "1")
|
||||
.option("--maxSubmissions <number>", "maxSubmissions", "12")
|
||||
.option("--rewardAmount <number>", "rewardAmount", "1")
|
||||
.option("--restartDelay <number>", "restartDelay", "1")
|
||||
.action(async (opts) => {
|
||||
const {
|
||||
deployer,
|
||||
wallet,
|
||||
aggregatorProgramAccount: aggregatorProgram,
|
||||
} = await AppContext.forAdmin()
|
||||
|
||||
const {
|
||||
feedName,
|
||||
restartDelay,
|
||||
minSubmissions,
|
||||
maxSubmissions,
|
||||
decimals,
|
||||
rewardAmount,
|
||||
} = opts
|
||||
|
||||
const aggregator = new FluxAggregator(wallet, aggregatorProgram.publicKey)
|
||||
|
||||
const feed = await deployer.ensure(feedName, async () => {
|
||||
return aggregator.initialize({
|
||||
config: new AggregatorConfig({
|
||||
description: feedName,
|
||||
decimals,
|
||||
minSubmissions,
|
||||
maxSubmissions,
|
||||
restartDelay,
|
||||
rewardAmount: BigInt(rewardAmount),
|
||||
}),
|
||||
owner: wallet.account,
|
||||
})
|
||||
})
|
||||
|
||||
log(`feed initialized, pubkey: ${color(feed.publicKey.toBase58(), "blue")}`)
|
||||
})
|
||||
|
||||
// cli
|
||||
// .command("aggregators")
|
||||
// .description("show all aggregators")
|
||||
// .action(() => {
|
||||
// // show current network
|
||||
// showNetwork()
|
||||
|
||||
// if (!fs.existsSync(deployedPath)) {
|
||||
// error("program haven't deployed yet")
|
||||
// }
|
||||
|
||||
// const deployed = JSON.parse(fs.readFileSync(deployedPath).toString())
|
||||
|
||||
// if (deployed.network != network) {
|
||||
// error("deployed network not match, please try `npm run clean:deployed`, and deploy again")
|
||||
// }
|
||||
|
||||
// if (!deployed.programId) {
|
||||
// error("program haven't deployed yet")
|
||||
// }
|
||||
|
||||
// log(deployed.pairs)
|
||||
// })
|
||||
|
||||
cli
|
||||
.command("add-oracle")
|
||||
.description("add an oracle to aggregator")
|
||||
.option("--aggregatorAddress <string>", "aggregator address")
|
||||
.option("--oracleName <string>", "oracle name")
|
||||
.option("--oracleOwner <string>", "oracle owner address")
|
||||
.action(async (opts) => {
|
||||
const { wallet, aggregator, deployer } = await AppContext.forAdmin()
|
||||
|
||||
const { oracleName, oracleOwner, feedAddress } = opts
|
||||
|
||||
log("add oracle...")
|
||||
const oracle = await aggregator.addOracle({
|
||||
oracleOwner: new PublicKey(oracleOwner),
|
||||
description: oracleName,
|
||||
aggregator: new PublicKey(feedAddress),
|
||||
aggregatorOwner: wallet.account,
|
||||
})
|
||||
|
||||
log(`added oracle. pubkey: ${color(oracle.publicKey.toBase58(), "blue")}`)
|
||||
})
|
||||
|
||||
cli
|
||||
.command("remove-oracle")
|
||||
.option("--feedAddress <string>", "feed to remove oracle from")
|
||||
.option("--oracleAddress <string>", "oracle address")
|
||||
.action(async (opts) => {
|
||||
const { feedAddress, oracleAddress } = opts
|
||||
|
||||
const { aggregator } = await AppContext.forAdmin()
|
||||
|
||||
await aggregator.removeOracle({
|
||||
aggregator: new PublicKey(feedAddress),
|
||||
oracle: new PublicKey(oracleAddress),
|
||||
})
|
||||
})
|
||||
|
||||
// cli
|
||||
// .command("oracles")
|
||||
// .description("show all oracles")
|
||||
// .action(() => {
|
||||
// // show current network
|
||||
// showNetwork()
|
||||
|
||||
// if (!fs.existsSync(deployedPath)) {
|
||||
// error("program haven't deployed yet")
|
||||
// }
|
||||
|
||||
// const deployed = JSON.parse(fs.readFileSync(deployedPath).toString())
|
||||
|
||||
// if (deployed.network != network) {
|
||||
// error("deployed network not match, please try `npm run clean:deployed`, and deploy again")
|
||||
// }
|
||||
|
||||
// if (!deployed.programId) {
|
||||
// error("program haven't deployed yet")
|
||||
// }
|
||||
|
||||
// log(deployed.oracles)
|
||||
// })
|
||||
|
||||
cli
|
||||
.command("feed-poll")
|
||||
.description("poll current feed value")
|
||||
.option("--feedAddress <string>", "feed address to submit values to")
|
||||
.action(async (opts) => {
|
||||
const { feedAddress } = opts
|
||||
|
||||
while (true) {
|
||||
const feedInfo = await conn.getAccountInfo(new PublicKey(feedAddress))
|
||||
log(decodeAggregatorInfo(feedInfo))
|
||||
|
||||
await sleep(1000)
|
||||
}
|
||||
})
|
||||
|
||||
cli
|
||||
.command("feed")
|
||||
.description("oracle feeds to aggregator")
|
||||
.option("--feedAddress <string>", "feed address to submit values to")
|
||||
.option("--oracleAddress <string>", "feed address to submit values to")
|
||||
.option("--pairSymbol <string>", "market pair to feed")
|
||||
.action(async (opts) => {
|
||||
const {
|
||||
wallet,
|
||||
aggregatorProgramAccount: aggregatorProgram,
|
||||
} = await AppContext.forOracle()
|
||||
|
||||
const { feedAddress, oracleAddress, pairSymbol } = opts
|
||||
|
||||
feed.start({
|
||||
oracle: new PublicKey(oracleAddress),
|
||||
oracleOwner: wallet.account,
|
||||
feed: new PublicKey(feedAddress),
|
||||
pairSymbol: pairSymbol,
|
||||
payerWallet: wallet,
|
||||
programId: aggregatorProgram.publicKey,
|
||||
})
|
||||
})
|
||||
|
||||
cli
|
||||
.command("testToken")
|
||||
.description("create test token")
|
||||
.option("--amount <number>", "amount of the test token")
|
||||
.action(async (opts) => {
|
||||
const {
|
||||
wallet,
|
||||
aggregatorProgramAccount: aggregatorProgram,
|
||||
deployer,
|
||||
} = await AppContext.forAdmin()
|
||||
|
||||
const { amount } = opts
|
||||
|
||||
if (!amount || amount < 0) {
|
||||
error("invalid amount")
|
||||
}
|
||||
|
||||
const spltoken = new SPLToken(wallet)
|
||||
|
||||
log(`create test token...`)
|
||||
// 1. create token
|
||||
const token = await spltoken.initializeMint({
|
||||
mintAuthority: wallet.account.publicKey,
|
||||
decimals: 8,
|
||||
})
|
||||
|
||||
// 2. create tokenOwner (program account)
|
||||
const tokenOwner = await ProgramAccount.forSeed(
|
||||
Buffer.from(token.publicKey.toBuffer()).slice(0, 30),
|
||||
aggregatorProgram.publicKey
|
||||
)
|
||||
|
||||
log(`create token acount...`)
|
||||
// 3. create token account
|
||||
const tokenAccount = await spltoken.initializeAccount({
|
||||
token: token.publicKey,
|
||||
owner: tokenOwner.pubkey,
|
||||
})
|
||||
|
||||
log(`mint ${amount} token to token account...`)
|
||||
// 4. and then, mint tokens to that account
|
||||
await spltoken.mintTo({
|
||||
token: token.publicKey,
|
||||
to: tokenAccount.publicKey,
|
||||
amount: BigInt(amount),
|
||||
authority: wallet.account,
|
||||
})
|
||||
|
||||
log({
|
||||
token: token.publicKey.toBase58(),
|
||||
tokenAccount: tokenAccount.publicKey.toBase58(),
|
||||
tokenOwner: {
|
||||
address: tokenOwner.address,
|
||||
seed: tokenOwner.noncedSeed.toString("hex"),
|
||||
nonce: tokenOwner.nonce,
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
cli.parse(process.argv)
|
94
src/feed.ts
94
src/feed.ts
|
@ -1,94 +0,0 @@
|
|||
import { PublicKey, Account, Wallet } from "solray"
|
||||
import WebSocket from "ws"
|
||||
|
||||
import { decodeOracleInfo, sleep } from "./utils"
|
||||
|
||||
import FluxAggregator from "./FluxAggregator"
|
||||
|
||||
const submitInterval = 10 * 1000
|
||||
|
||||
interface StartParams {
|
||||
oracle: PublicKey;
|
||||
oracleOwner: Account;
|
||||
feed: PublicKey;
|
||||
pairSymbol: string;
|
||||
payerWallet: Wallet;
|
||||
programId: PublicKey;
|
||||
}
|
||||
|
||||
export async function start(params: StartParams) {
|
||||
const {
|
||||
oracle,
|
||||
oracleOwner,
|
||||
feed,
|
||||
pairSymbol,
|
||||
payerWallet,
|
||||
programId,
|
||||
} = params
|
||||
|
||||
console.log("connecting to wss://ws-feed.pro.coinbase.com ()")
|
||||
const ws = new WebSocket("wss://ws-feed.pro.coinbase.com")
|
||||
|
||||
ws.on("open", () => {
|
||||
console.log(`${pairSymbol} price feed connected`)
|
||||
ws.send(JSON.stringify({
|
||||
"type": "subscribe",
|
||||
"product_ids": [
|
||||
pairSymbol.replace("/", "-").toUpperCase(),
|
||||
],
|
||||
"channels": [
|
||||
"ticker"
|
||||
]
|
||||
}))
|
||||
})
|
||||
|
||||
// in penny
|
||||
let curPriceCent = 0
|
||||
|
||||
ws.on("message", async (data) => {
|
||||
const json = JSON.parse(data)
|
||||
if (!json || !json.price) {
|
||||
return console.log(data)
|
||||
}
|
||||
|
||||
curPriceCent = Math.floor(json.price * 100)
|
||||
|
||||
console.log("current price:", json.price)
|
||||
})
|
||||
|
||||
ws.on("close", (err) => {
|
||||
console.error(`websocket closed: ${err}`)
|
||||
process.exit(1)
|
||||
})
|
||||
|
||||
const program = new FluxAggregator(payerWallet, programId)
|
||||
|
||||
console.log(await program.oracleInfo(oracle))
|
||||
console.log({ owner: oracleOwner.publicKey.toString() })
|
||||
|
||||
while (true) {
|
||||
if (curPriceCent == 0) {
|
||||
await sleep(1000)
|
||||
}
|
||||
|
||||
try {
|
||||
await program.submit({
|
||||
aggregator: feed,
|
||||
oracle,
|
||||
submission: BigInt(curPriceCent),
|
||||
owner: oracleOwner,
|
||||
})
|
||||
} catch(err) {
|
||||
console.log(err)
|
||||
}
|
||||
|
||||
console.log("submit success!")
|
||||
|
||||
payerWallet.conn.getAccountInfo(oracle).then((accountInfo) => {
|
||||
console.log("oracle info:", decodeOracleInfo(accountInfo))
|
||||
})
|
||||
|
||||
console.log("wait for cooldown success!")
|
||||
await sleep(submitInterval)
|
||||
}
|
||||
}
|
67
src/utils.ts
67
src/utils.ts
|
@ -1,11 +1,5 @@
|
|||
import { Connection, PublicKey } from "@solana/web3.js"
|
||||
|
||||
import {
|
||||
AggregatorLayout,
|
||||
SubmissionLayout,
|
||||
OracleLayout,
|
||||
} from "./FluxAggregator"
|
||||
|
||||
import { solana, Wallet, NetworkName, Deployer } from "solray"
|
||||
|
||||
export function getMedian(submissions: number[]): number {
|
||||
|
@ -33,67 +27,6 @@ export function sleep(ms: number): Promise<void> {
|
|||
})
|
||||
}
|
||||
|
||||
export function decodeAggregatorInfo(accountInfo) {
|
||||
const data = Buffer.from(accountInfo.data)
|
||||
const aggregator = AggregatorLayout.decode(data)
|
||||
|
||||
const minSubmissionValue = aggregator.minSubmissionValue.readBigUInt64LE()
|
||||
const maxSubmissionValue = aggregator.maxSubmissionValue.readBigUInt64LE()
|
||||
const submitInterval = aggregator.submitInterval.readInt32LE()
|
||||
const description = (aggregator.description.toString() as String).trim()
|
||||
|
||||
// decode oracles
|
||||
let submissions: any[] = []
|
||||
let submissionSpace = SubmissionLayout.span
|
||||
let latestUpdateTime = BigInt(0)
|
||||
|
||||
for (let i = 0; i < aggregator.submissions.length / submissionSpace; i++) {
|
||||
let submission = SubmissionLayout.decode(
|
||||
aggregator.submissions.slice(
|
||||
i * submissionSpace,
|
||||
(i + 1) * submissionSpace
|
||||
)
|
||||
)
|
||||
|
||||
submission.oracle = new PublicKey(submission.oracle)
|
||||
submission.time = submission.time.readBigInt64LE()
|
||||
submission.value = submission.value.readBigInt64LE()
|
||||
|
||||
if (!submission.oracle.equals(new PublicKey(0))) {
|
||||
submissions.push(submission)
|
||||
}
|
||||
|
||||
if (submission.time > latestUpdateTime) {
|
||||
latestUpdateTime = submission.time
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
minSubmissionValue: minSubmissionValue,
|
||||
maxSubmissionValue: maxSubmissionValue,
|
||||
submissionValue: getMedian(submissions),
|
||||
submitInterval,
|
||||
description,
|
||||
oracles: submissions.map((s) => s.oracle.toString()),
|
||||
latestUpdateTime: new Date(Number(latestUpdateTime) * 1000),
|
||||
}
|
||||
}
|
||||
|
||||
export function decodeOracleInfo(accountInfo) {
|
||||
const data = Buffer.from(accountInfo.data)
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
export async function walletFromEnv(
|
||||
key: string,
|
||||
conn: Connection
|
||||
|
|
Loading…
Reference in New Issue