work on reward faucet
This commit is contained in:
parent
a528f29958
commit
2f071eb75e
|
@ -20,15 +20,25 @@ import FluxAggregator from "./FluxAggregator"
|
||||||
import { AggregatorConfig, IAggregatorConfig } from "./schema"
|
import { AggregatorConfig, IAggregatorConfig } from "./schema"
|
||||||
import { jsonReplacer, jsonReviver } from "./json"
|
import { jsonReplacer, jsonReviver } from "./json"
|
||||||
import { log } from "./log"
|
import { log } from "./log"
|
||||||
|
import { config } from "dotenv/types"
|
||||||
|
|
||||||
interface OracleDeployInfo {
|
interface OracleDeployInfo {
|
||||||
pubkey: PublicKey
|
pubkey: PublicKey
|
||||||
owner: PublicKey
|
owner: PublicKey
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface FaucetInfo {
|
||||||
|
pubkey: PublicKey
|
||||||
|
// program account public key
|
||||||
|
owner: PublicKey
|
||||||
|
ownerSeed: Buffer
|
||||||
|
}
|
||||||
|
|
||||||
interface AggregatorDeployInfo {
|
interface AggregatorDeployInfo {
|
||||||
pubkey: PublicKey
|
pubkey: PublicKey
|
||||||
owner: PublicKey
|
owner: PublicKey
|
||||||
config: IAggregatorConfig
|
config: IAggregatorConfig
|
||||||
|
faucet: FaucetInfo
|
||||||
|
|
||||||
oracles: {
|
oracles: {
|
||||||
[key: string]: OracleDeployInfo
|
[key: string]: OracleDeployInfo
|
||||||
|
@ -124,6 +134,34 @@ export class Deployer {
|
||||||
return new FluxAggregator(this.wallet, this.state.programID)
|
return new FluxAggregator(this.wallet, this.state.programID)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async createRewardFaucet(
|
||||||
|
aggregatorInfo: AggregatorDeployInfo
|
||||||
|
): Promise<FaucetInfo> {
|
||||||
|
if (aggregatorInfo.faucet) {
|
||||||
|
return aggregatorInfo.faucet
|
||||||
|
}
|
||||||
|
|
||||||
|
const seed = Buffer.from(aggregatorInfo.config.description)
|
||||||
|
|
||||||
|
const faucetOwner = await ProgramAccount.forSeed(seed, this.state.programID)
|
||||||
|
|
||||||
|
const spltoken = new SPLToken(this.wallet)
|
||||||
|
|
||||||
|
const faucet = await spltoken.initializeAccount({
|
||||||
|
// TODO: check if rewardTokenAccount is null
|
||||||
|
token: aggregatorInfo.config.rewardTokenAccount,
|
||||||
|
owner: faucetOwner.pubkey,
|
||||||
|
})
|
||||||
|
|
||||||
|
aggregatorInfo.faucet = {
|
||||||
|
pubkey: faucet.publicKey,
|
||||||
|
owner: faucetOwner.pubkey,
|
||||||
|
ownerSeed: seed,
|
||||||
|
}
|
||||||
|
|
||||||
|
return aggregatorInfo.faucet
|
||||||
|
}
|
||||||
|
|
||||||
async createOracle(
|
async createOracle(
|
||||||
aggregatorInfo: AggregatorDeployInfo,
|
aggregatorInfo: AggregatorDeployInfo,
|
||||||
name: string,
|
name: string,
|
||||||
|
@ -164,11 +202,18 @@ export class Deployer {
|
||||||
owner: this.wallet.account,
|
owner: this.wallet.account,
|
||||||
})
|
})
|
||||||
|
|
||||||
return {
|
const info: AggregatorDeployInfo = {
|
||||||
pubkey: account.publicKey,
|
pubkey: account.publicKey,
|
||||||
owner: this.wallet.pubkey,
|
owner: this.wallet.pubkey,
|
||||||
config,
|
config,
|
||||||
|
// to be set by `createRewardFaucet`
|
||||||
|
faucet: undefined,
|
||||||
oracles: {},
|
oracles: {},
|
||||||
}
|
} as any
|
||||||
|
|
||||||
|
// will set
|
||||||
|
await this.createRewardFaucet(info)
|
||||||
|
|
||||||
|
return info
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,6 +36,7 @@ export class Submitter {
|
||||||
public aggregatorPK: PublicKey,
|
public aggregatorPK: PublicKey,
|
||||||
public oraclePK: PublicKey,
|
public oraclePK: PublicKey,
|
||||||
private oracleOwnerWallet: Wallet,
|
private oracleOwnerWallet: Wallet,
|
||||||
|
|
||||||
private priceFeed: IPriceFeed,
|
private priceFeed: IPriceFeed,
|
||||||
private cfg: SubmitterConfig
|
private cfg: SubmitterConfig
|
||||||
) {
|
) {
|
||||||
|
@ -58,7 +59,20 @@ export class Submitter {
|
||||||
await Promise.all([this.observeAggregatorState(), this.observePriceFeed()])
|
await Promise.all([this.observeAggregatorState(), this.observePriceFeed()])
|
||||||
}
|
}
|
||||||
|
|
||||||
public async withdrawRewards() {}
|
public async withdrawRewards() {
|
||||||
|
// if (this.oracle.withdrawable.isZero()) {
|
||||||
|
// return
|
||||||
|
// }
|
||||||
|
|
||||||
|
// //
|
||||||
|
|
||||||
|
// this.program.withdraw({
|
||||||
|
// accounts: {
|
||||||
|
// aggregator: this.aggregatorPK,
|
||||||
|
// // faucet
|
||||||
|
// }
|
||||||
|
// })
|
||||||
|
}
|
||||||
|
|
||||||
private async reloadState(loadAggregator = true) {
|
private async reloadState(loadAggregator = true) {
|
||||||
if (loadAggregator) {
|
if (loadAggregator) {
|
||||||
|
|
23
src/json.ts
23
src/json.ts
|
@ -7,18 +7,41 @@ export function jsonReviver(_key: string, val: any) {
|
||||||
if (val["type"] == "PublicKey") {
|
if (val["type"] == "PublicKey") {
|
||||||
return new PublicKey(val.base58)
|
return new PublicKey(val.base58)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (val["type"] == "Buffer") {
|
||||||
|
return Buffer.from(val.hex, "hex")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return val
|
return val
|
||||||
}
|
}
|
||||||
|
|
||||||
export function jsonReplacer(key: string, value: any) {
|
export function jsonReplacer(key: string, value: any) {
|
||||||
if (value && typeof value == "object") {
|
if (value && typeof value == "object") {
|
||||||
|
console.log("jsonReplacer", key, value)
|
||||||
if (value.constructor == PublicKey) {
|
if (value.constructor == PublicKey) {
|
||||||
return {
|
return {
|
||||||
type: "PublicKey",
|
type: "PublicKey",
|
||||||
base58: value.toBase58(),
|
base58: value.toBase58(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The Buffer class defines a `toJSON` method that returns:
|
||||||
|
//
|
||||||
|
// {
|
||||||
|
// type: 'Buffer',
|
||||||
|
// data: [
|
||||||
|
// 100, 101, 97, 100,
|
||||||
|
// 98, 101, 97, 102
|
||||||
|
// ]
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// Convert this to an hex string
|
||||||
|
if (value.type == "Buffer") {
|
||||||
|
return {
|
||||||
|
type: "Buffer",
|
||||||
|
hex: Buffer.from(value).toString("hex"),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return value
|
return value
|
||||||
|
|
148
test.ts
148
test.ts
|
@ -1,67 +1,141 @@
|
||||||
import dotenv from "dotenv"
|
import dotenv from "dotenv"
|
||||||
|
import { ProgramAccount, PublicKey, SPLToken, Wallet } from "solray"
|
||||||
dotenv.config()
|
dotenv.config()
|
||||||
|
|
||||||
import { AppContext, conn, network } from "./src/context"
|
import { AppContext, conn, network } from "./src/context"
|
||||||
import { AggregatorDeployFile, Deployer } from "./src/Deployer"
|
import { AggregatorDeployFile, Deployer } from "./src/Deployer"
|
||||||
import { coinbase } from "./src/feeds"
|
import { coinbase } from "./src/feeds"
|
||||||
import { loadJSONFile } from "./src/json"
|
import { jsonReplacer, jsonReviver, loadJSONFile } from "./src/json"
|
||||||
import { log } from "./src/log"
|
import { log } from "./src/log"
|
||||||
import { PriceFeeder } from "./src/PriceFeeder"
|
import { PriceFeeder } from "./src/PriceFeeder"
|
||||||
|
import { stateFromJSON } from "./src/state"
|
||||||
|
|
||||||
|
interface State {
|
||||||
|
rewardTokenPK: PublicKey
|
||||||
|
faucetPK: PublicKey
|
||||||
|
isMinted: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
class TestHarness {
|
||||||
|
public state: State
|
||||||
|
constructor(
|
||||||
|
stateFile: string,
|
||||||
|
private wallet: Wallet,
|
||||||
|
) {
|
||||||
|
this.state = stateFromJSON<State>(stateFile, {} as State, {
|
||||||
|
replacer: jsonReplacer,
|
||||||
|
reviver: jsonReviver,
|
||||||
|
})
|
||||||
|
// this.state = stateFromJSON<State>(`state.${network}.json`, {} as State)
|
||||||
|
}
|
||||||
|
|
||||||
|
// async setup() {
|
||||||
|
// // setup reward token plus mint
|
||||||
|
// await this.setupRewardTokenPK()
|
||||||
|
// await this.setupFaucet()
|
||||||
|
// await this.mintToFaucet(1e6 * 1e9)
|
||||||
|
// }
|
||||||
|
|
||||||
|
get spltoken() {
|
||||||
|
return new SPLToken(this.wallet)
|
||||||
|
}
|
||||||
|
|
||||||
|
// async mintToFaucet(amount: number) {
|
||||||
|
// if (this.state.isMinted) {
|
||||||
|
// return
|
||||||
|
// }
|
||||||
|
|
||||||
|
// await this.spltoken.mintTo({
|
||||||
|
// token: this.state.rewardTokenPK,
|
||||||
|
// to: await this.faucetOwnerPK(),
|
||||||
|
// amount: BigInt(amount), // 1M
|
||||||
|
// authority: this.wallet.pubkey,
|
||||||
|
// })
|
||||||
|
// }
|
||||||
|
|
||||||
|
// async faucetOwnerPK(): Promise<PublicKey> {
|
||||||
|
// const rewardTokenOwner = await ProgramAccount.forSeed(
|
||||||
|
// Buffer.from("solink"),
|
||||||
|
// this.aggregatorProgramID
|
||||||
|
// )
|
||||||
|
|
||||||
|
// return rewardTokenOwner.pubkey
|
||||||
|
// }
|
||||||
|
|
||||||
|
async setupFaucet(aggregatorProgramID: PublicKey): Promise<PublicKey> {
|
||||||
|
if (this.state.faucetPK) {
|
||||||
|
return this.state.faucetPK
|
||||||
|
}
|
||||||
|
|
||||||
|
const faucetOwner = await ProgramAccount.forSeed(
|
||||||
|
Buffer.from("solink"),
|
||||||
|
aggregatorProgramID
|
||||||
|
)
|
||||||
|
|
||||||
|
const faucet = await this.spltoken.initializeAccount({
|
||||||
|
token: this.state.rewardTokenPK,
|
||||||
|
owner: faucetOwner.pubkey,
|
||||||
|
})
|
||||||
|
|
||||||
|
await this.spltoken.mintTo({
|
||||||
|
token: this.state.rewardTokenPK,
|
||||||
|
to: faucet.publicKey,
|
||||||
|
amount: BigInt(1e6*1e9), // 1M
|
||||||
|
authority: this.wallet.pubkey,
|
||||||
|
})
|
||||||
|
|
||||||
|
this.state.faucetPK = faucet.publicKey
|
||||||
|
return faucet.publicKey
|
||||||
|
}
|
||||||
|
|
||||||
|
async setupRewardTokenPK(): Promise<PublicKey> {
|
||||||
|
if (this.state.rewardTokenPK) {
|
||||||
|
return this.state.rewardTokenPK
|
||||||
|
}
|
||||||
|
|
||||||
|
log.info("setup reward token")
|
||||||
|
const token = await this.spltoken.initializeMint({
|
||||||
|
mintAuthority: this.wallet.pubkey,
|
||||||
|
decimals: 9,
|
||||||
|
// account: this.wallet.deriveAccount("0")
|
||||||
|
})
|
||||||
|
|
||||||
|
this.state.rewardTokenPK = token.publicKey
|
||||||
|
return token.publicKey
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async function main() {
|
async function main() {
|
||||||
|
// persistent JSON state for test script
|
||||||
|
|
||||||
|
|
||||||
const setupFile = `config/setup.${network}.json`
|
const setupFile = `config/setup.${network}.json`
|
||||||
const deployFile = `deploy.${network}.json`
|
const deployFile = `deploy.${network}.json`
|
||||||
const feederConfigFile = "feeder.json"
|
const feederConfigFile = "feeder.json"
|
||||||
let ctx = new AppContext()
|
let ctx = new AppContext()
|
||||||
let adminWallet = await ctx.adminWallet()
|
let adminWallet = await ctx.adminWallet()
|
||||||
let oracleWallet = await ctx.oracleWallet()
|
let oracleWallet = await ctx.oracleWallet()
|
||||||
|
|
||||||
await conn.requestAirdrop(adminWallet.pubkey, 10 * 1e9)
|
await conn.requestAirdrop(adminWallet.pubkey, 10 * 1e9)
|
||||||
await conn.requestAirdrop(oracleWallet.pubkey, 10 * 1e9)
|
await conn.requestAirdrop(oracleWallet.pubkey, 10 * 1e9)
|
||||||
|
|
||||||
const deployer = new Deployer(deployFile, setupFile, adminWallet)
|
const t = new TestHarness(`test.${network}.json`, adminWallet)
|
||||||
|
await t.setupRewardTokenPK()
|
||||||
|
|
||||||
|
// return
|
||||||
|
|
||||||
|
const deployer = new Deployer(deployFile, setupFile, adminWallet)
|
||||||
await deployer.runAll()
|
await deployer.runAll()
|
||||||
|
|
||||||
|
// TODO: actually, creating the faucet should be in the deployer
|
||||||
|
// await t.setupFaucet(deployer.state.programID)
|
||||||
|
|
||||||
const deploy = loadJSONFile<AggregatorDeployFile>(deployFile)
|
const deploy = loadJSONFile<AggregatorDeployFile>(deployFile)
|
||||||
const feeder = new PriceFeeder(deploy, oracleWallet)
|
const feeder = new PriceFeeder(deploy, oracleWallet)
|
||||||
feeder.start()
|
feeder.start()
|
||||||
|
|
||||||
|
// TODO: try to to harvest rewards
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
// const spltoken = new SPLToken(adminWallet)
|
|
||||||
// const rewardToken = await deployer.ensure("create reward token", async () => {
|
|
||||||
// return spltoken.initializeMint({
|
|
||||||
// mintAuthority: adminWallet.pubkey,
|
|
||||||
// decimals: 8,
|
|
||||||
// })
|
|
||||||
// })
|
|
||||||
|
|
||||||
// const rewardTokenOwner = await ProgramAccount.forSeed(
|
|
||||||
// Buffer.from("solink"),
|
|
||||||
// aggregatorProgram.publicKey
|
|
||||||
// )
|
|
||||||
|
|
||||||
// const rewardTokenAccount = await deployer.ensure(
|
|
||||||
// "initialize reward token account",
|
|
||||||
// async () => {
|
|
||||||
// const vault = await spltoken.initializeAccount({
|
|
||||||
// token: rewardToken.publicKey,
|
|
||||||
// owner: rewardTokenOwner.pubkey,
|
|
||||||
// })
|
|
||||||
|
|
||||||
// await spltoken.mintTo({
|
|
||||||
// token: rewardToken.publicKey,
|
|
||||||
// to: vault.publicKey,
|
|
||||||
// amount: BigInt(1e6 * 1e8), // 1M
|
|
||||||
// authority: adminWallet.pubkey,
|
|
||||||
// })
|
|
||||||
|
|
||||||
// return vault
|
|
||||||
// }
|
|
||||||
// )
|
|
||||||
|
|
||||||
// console.log(await spltoken.mintInfo(rewardToken.publicKey))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
main().catch((err) => console.log(err))
|
main().catch((err) => console.log(err))
|
||||||
|
|
Loading…
Reference in New Issue