import { PublicKey, BaseProgram, Account, Wallet, System, SPLToken, } from "solray" import BN from "bn.js" import { SYSVAR_RENT_PUBKEY, SYSVAR_CLOCK_PUBKEY, TransactionInstruction, SystemProgram, } from "@solana/web3.js" import { AggregatorConfig, IAggregatorConfig, schema } from "./schema" import * as encoding from "./schema" import { deserialize, serialize } from "borsh" import { conn } from "./context" interface InitializeParams { config: IAggregatorConfig owner: Account } interface InitializeInstructionParams extends InitializeParams { aggregator: PublicKey } interface AddOracleParams { aggregator: PublicKey aggregatorOwner: Account oracleOwner: PublicKey description: string } interface RemoveOracleParams { aggregator: PublicKey oracle: PublicKey // To prove you are the aggregator owner authority?: Account } interface RemoveOracleInstructionParams extends RemoveOracleParams {} interface SubmitParams { accounts: { aggregator: { write: PublicKey } roundSubmissions: { write: PublicKey } answerSubmissions: { write: PublicKey } oracle: { write: PublicKey } oracle_owner: Account } round_id: BN value: BN } interface WithdrawParams { accounts: { aggregator: PublicKey faucet: { write: PublicKey }, faucetOwner: PublicKey, oracle: { write: PublicKey }, oracleOwner: Account, receiver: { write: PublicKey }, } faucetOwnerSeed: Buffer } interface WithdrawInstructionParams extends WithdrawParams {} export default class FluxAggregator extends BaseProgram { private sys: System constructor(wallet: Wallet, programID: PublicKey) { super(wallet, programID) this.sys = new System(this.wallet) } public async initialize(params: InitializeParams): Promise { const aggregator = new Account() const answer_submissions = new Account() const round_submissions = new Account() const input = encoding.Initialize.serialize({ config: new AggregatorConfig(params.config), }) await this.sendTx( [ await this.sys.createRentFreeAccountInstruction({ newPubicKey: aggregator.publicKey, space: encoding.Aggregator.size, programID: this.programID, }), await this.sys.createRentFreeAccountInstruction({ newPubicKey: answer_submissions.publicKey, space: encoding.Submissions.size, programID: this.programID, }), await this.sys.createRentFreeAccountInstruction({ newPubicKey: round_submissions.publicKey, space: encoding.Submissions.size, programID: this.programID, }), this.instruction(input, [ SYSVAR_RENT_PUBKEY, { write: aggregator }, params.owner, // signed { write: round_submissions }, { write: answer_submissions }, ]), ], [ this.account, aggregator, params.owner, round_submissions, answer_submissions, ] ) return aggregator } public async addOracle(params: AddOracleParams): Promise { const oracle = new Account() const input = encoding.AddOracle.serialize({ description: params.description, }) await this.sendTx( [ await this.sys.createRentFreeAccountInstruction({ newPubicKey: oracle.publicKey, space: encoding.Oracle.size, programID: this.programID, }), this.instruction(input, [ SYSVAR_RENT_PUBKEY, params.aggregator, params.aggregatorOwner, // signed oracle.publicKey, params.oracleOwner, ]), ], [this.account, oracle, params.aggregatorOwner] ) return oracle } // public async oracleInfo(pubkey: PublicKey) { // const info = await this.conn.getAccountInfo(pubkey) // return decodeOracleInfo(info) // } // public async removeOracle(params: RemoveOracleParams): Promise { // await this.sendTx( // [this.removeOracleInstruction(params)], // [this.account, params.authority || this.wallet.account] // ) // } // private removeOracleInstruction( // params: RemoveOracleInstructionParams // ): TransactionInstruction { // const { authority, aggregator, oracle } = params // const layout = BufferLayout.struct([ // BufferLayout.u8("instruction"), // BufferLayout.blob(32, "oracle"), // ]) // return this.instructionEncode( // layout, // { // instruction: 2, // remove oracle instruction // oracle: oracle.toBuffer(), // }, // [ // // // { write: aggregator }, // authority || this.wallet.account, // ] // ) // } public async submit(params: SubmitParams): Promise { const input = encoding.Submit.serialize(params) let auths = [SYSVAR_CLOCK_PUBKEY, ...Object.values(params.accounts)] await this.sendTx( [this.instruction(input, auths)], [this.account, params.accounts.oracle_owner] ) } public async withdraw(params: WithdrawParams): Promise { const input = encoding.Withdraw.serialize(params) let auths = [SPLToken.programID, ...Object.values(params.accounts)] await this.sendTx( [this.instruction(input, auths)], [this.account, params.accounts.oracleOwner] ) } // private withdrawInstruction( // params: WithdrawInstructionParams // ): TransactionInstruction { // const { // aggregator, // receiver, // amount, // tokenOwner, // tokenAccount, // authority, // } = params // const layout = BufferLayout.struct([ // BufferLayout.u8("instruction"), // uint64("amount"), // ]) // return this.instructionEncode( // layout, // { // instruction: 4, // withdraw instruction // amount: u64LEBuffer(amount), // }, // [ // { write: aggregator }, // { write: tokenAccount }, // { write: receiver }, // SPLToken.programID, // tokenOwner, // { write: authority }, // ] // ) // } }