203 lines
5.9 KiB
JavaScript
203 lines
5.9 KiB
JavaScript
const assert = require("assert");
|
|
const { Token } = require("@solana/spl-token");
|
|
const anchor = require("@project-serum/anchor");
|
|
const serumCmn = require("@project-serum/common");
|
|
const { Market } = require("@project-serum/serum");
|
|
const { PublicKey, SystemProgram, SYSVAR_RENT_PUBKEY } = anchor.web3;
|
|
const utils = require("./utils");
|
|
const { setupStakePool } = require("./utils/stake");
|
|
|
|
const DEX_PID = new PublicKey("9xQeWvG816bUx9EPjHmaT23yvVM2ZWbrrpZb9PusVFin");
|
|
const SWAP_PID = new PublicKey("22Y43yTVxuUkoRKdm9thyRhQ3SdgQS7c7kB6UNCiaczD");
|
|
const TOKEN_PID = new PublicKey("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA");
|
|
const REGISTRY_PID = new PublicKey(
|
|
"GrAkKfEpTKQuVHG2Y97Y2FF4i7y7Q5AHLK94JBy7Y5yv"
|
|
);
|
|
const LOCKUP_PID = new PublicKey(
|
|
"6ebQNeTPZ1j7k3TtkCCtEPRvG7GQsucQrZ7sSEDQi9Ks"
|
|
);
|
|
const FEES = "6160355581";
|
|
|
|
describe("cfo", () => {
|
|
anchor.setProvider(anchor.Provider.env());
|
|
|
|
const program = anchor.workspace.Cfo;
|
|
let officer;
|
|
let TOKEN_CLIENT;
|
|
let officerAccount;
|
|
const sweepAuthority = program.provider.wallet.publicKey;
|
|
|
|
// Accounts used to setup the orderbook.
|
|
let ORDERBOOK_ENV,
|
|
// Accounts used for A -> USDC swap transactions.
|
|
SWAP_A_USDC_ACCOUNTS,
|
|
// Accounts used for USDC -> A swap transactions.
|
|
SWAP_USDC_A_ACCOUNTS,
|
|
// Serum DEX vault PDA for market A/USDC.
|
|
marketAVaultSigner,
|
|
// Serum DEX vault PDA for market B/USDC.
|
|
marketBVaultSigner;
|
|
|
|
let registrar, msrmRegistrar;
|
|
|
|
it("BOILERPLATE: Sets up a market with funded fees", async () => {
|
|
ORDERBOOK_ENV = await utils.initMarket({
|
|
provider: program.provider,
|
|
});
|
|
console.log("Token A: ", ORDERBOOK_ENV.marketA.baseMintAddress.toString());
|
|
console.log(
|
|
"Token USDC: ",
|
|
ORDERBOOK_ENV.marketA.quoteMintAddress.toString()
|
|
);
|
|
TOKEN_CLIENT = new Token(
|
|
program.provider.connection,
|
|
ORDERBOOK_ENV.usdc,
|
|
TOKEN_PID,
|
|
program.provider.wallet.payer
|
|
);
|
|
|
|
await TOKEN_CLIENT.transfer(
|
|
ORDERBOOK_ENV.godUsdc,
|
|
ORDERBOOK_ENV.marketA._decoded.quoteVault,
|
|
program.provider.wallet.payer,
|
|
[],
|
|
10000000000000
|
|
);
|
|
|
|
const tokenAccount = await TOKEN_CLIENT.getAccountInfo(
|
|
ORDERBOOK_ENV.marketA._decoded.quoteVault
|
|
);
|
|
assert.ok(tokenAccount.amount.toString() === "10000902263700");
|
|
});
|
|
|
|
it("BOILERPLATE: Executes trades to generate fees", async () => {
|
|
await utils.runTradeBot(
|
|
ORDERBOOK_ENV.marketA._decoded.ownAddress,
|
|
program.provider,
|
|
1
|
|
);
|
|
let marketClient = await Market.load(
|
|
program.provider.connection,
|
|
ORDERBOOK_ENV.marketA._decoded.ownAddress,
|
|
{ commitment: "recent" },
|
|
DEX_PID
|
|
);
|
|
assert.ok(marketClient._decoded.quoteFeesAccrued.toString() === FEES);
|
|
});
|
|
|
|
it("BOILERPLATE: Sets up the staking pools", async () => {
|
|
await setupStakePool(ORDERBOOK_ENV.mintA, ORDERBOOK_ENV.godA);
|
|
registrar = ORDERBOOK_ENV.usdc;
|
|
msrmRegistrar = registrar;
|
|
});
|
|
|
|
it("Creates a CFO!", async () => {
|
|
let distribution = {
|
|
burn: 80,
|
|
stake: 20,
|
|
treasury: 0,
|
|
};
|
|
officer = await program.account.officer.associatedAddress(DEX_PID);
|
|
const srmVault = await anchor.utils.publicKey.associated(
|
|
program.programId,
|
|
officer,
|
|
anchor.utils.bytes.utf8.encode("vault"),
|
|
);
|
|
const stake = await anchor.utils.publicKey.associated(
|
|
program.programId,
|
|
officer,
|
|
anchor.utils.bytes.utf8.encode("stake"),
|
|
);
|
|
const treasury = await anchor.utils.publicKey.associated(
|
|
program.programId,
|
|
officer,
|
|
Buffer.from(anchor.utils.bytes.utf8.encode("treasury")),
|
|
);
|
|
await program.rpc.createOfficer(distribution, registrar, msrmRegistrar, {
|
|
accounts: {
|
|
officer,
|
|
srmVault,
|
|
stake,
|
|
treasury,
|
|
mint: ORDERBOOK_ENV.mintA,
|
|
authority: program.provider.wallet.publicKey,
|
|
dexProgram: DEX_PID,
|
|
swapProgram: SWAP_PID,
|
|
tokenProgram: TOKEN_PID,
|
|
systemProgram: SystemProgram.programId,
|
|
rent: SYSVAR_RENT_PUBKEY,
|
|
},
|
|
});
|
|
|
|
officerAccount = await program.account.officer.associated(DEX_PID);
|
|
assert.ok(
|
|
officerAccount.authority.equals(program.provider.wallet.publicKey)
|
|
);
|
|
assert.ok(
|
|
JSON.stringify(officerAccount.distribution) ===
|
|
JSON.stringify(distribution)
|
|
);
|
|
});
|
|
|
|
it("Creates a token account for the officer associated with the market", async () => {
|
|
const token = await anchor.utils.publicKey.associated(
|
|
program.programId,
|
|
officer,
|
|
ORDERBOOK_ENV.usdc
|
|
);
|
|
await program.rpc.createOfficerToken({
|
|
accounts: {
|
|
officer,
|
|
token,
|
|
mint: ORDERBOOK_ENV.usdc,
|
|
payer: program.provider.wallet.publicKey,
|
|
systemProgram: SystemProgram.programId,
|
|
tokenProgram: TOKEN_PID,
|
|
rent: SYSVAR_RENT_PUBKEY,
|
|
},
|
|
});
|
|
const tokenAccount = await TOKEN_CLIENT.getAccountInfo(token);
|
|
assert.ok(tokenAccount.state === 1);
|
|
assert.ok(tokenAccount.isInitialized);
|
|
});
|
|
|
|
it("Sweeps fees", async () => {
|
|
const sweepVault = await anchor.utils.publicKey.associated(
|
|
program.programId,
|
|
officer,
|
|
ORDERBOOK_ENV.usdc
|
|
);
|
|
const beforeTokenAccount = await serumCmn.getTokenAccount(
|
|
program.provider,
|
|
sweepVault
|
|
);
|
|
await program.rpc.sweepFees({
|
|
accounts: {
|
|
officer,
|
|
sweepVault,
|
|
mint: ORDERBOOK_ENV.usdc,
|
|
dex: {
|
|
market: ORDERBOOK_ENV.marketA._decoded.ownAddress,
|
|
pcVault: ORDERBOOK_ENV.marketA._decoded.quoteVault,
|
|
sweepAuthority,
|
|
vaultSigner: ORDERBOOK_ENV.vaultSigner,
|
|
dexProgram: DEX_PID,
|
|
tokenProgram: TOKEN_PID,
|
|
},
|
|
},
|
|
});
|
|
const afterTokenAccount = await serumCmn.getTokenAccount(
|
|
program.provider,
|
|
sweepVault
|
|
);
|
|
assert.ok(
|
|
afterTokenAccount.amount.sub(beforeTokenAccount.amount).toString() ===
|
|
FEES
|
|
);
|
|
});
|
|
|
|
it("TODO", async () => {
|
|
// todo
|
|
});
|
|
});
|