refactor to run from root and format

This commit is contained in:
Maximilian Schneider 2023-05-14 21:44:25 +02:00
parent 3c99ebf336
commit 6fc642d491
20 changed files with 4305 additions and 4637 deletions

2
.gitignore vendored
View File

@ -1,4 +1,4 @@
/target
node_modules
/configure/config.json
package-lock.json
**/config.json

View File

@ -30,7 +30,7 @@ Here are arguments required by the script, all the arguments are optional:
--authority, -a <str> - a string [optional][default: ~/.config/solana/id.json]
--number-of-payers, -p <number> - Number of payers used for testing [optional][default: 10]
--payer-balance, -b <number> - Balance of payer in SOLs [optional][default: 1 SOLs]
--output-file, -o <str> - a string [optional][default: config.json]
--output-file, -o <str> - a string [optional][default: configure/config.json]
```
Once the cluster configuration is successfully done we create a json file `config.json`
@ -39,7 +39,7 @@ To configure cluster:
```sh
cd configure
ts-node configure_all.ts -a /home/user/.config/solana/id.json
yarn configure -a ../solana_configure_local_cluster/faucet.json
cd ..
```

View File

@ -1,6 +1,21 @@
import { AnchorProvider, BN, Program, Provider, web3 } from "@project-serum/anchor";
import {
AnchorProvider,
BN,
Program,
Provider,
web3,
} from "@project-serum/anchor";
import { SuccessfulTxSimulationResponse } from "@project-serum/anchor/dist/cjs/utils/rpc";
import { Connection, PublicKey, Transaction, Signer, SendOptions, ConfirmOptions, Commitment, Keypair } from "@solana/web3.js";
import {
Connection,
PublicKey,
Transaction,
Signer,
SendOptions,
ConfirmOptions,
Commitment,
Keypair,
} from "@solana/web3.js";
import { Command } from "./output_file";
import { IDL, OpenbookV2 } from "./openbook-v2/openbook_v2";
import { U64_MAX_BN } from "@blockworks-foundation/mango-v4";
@ -12,26 +27,26 @@ export class TestProvider extends AnchorProvider {
constructor(connection: Connection, keypair: Keypair) {
let txSigner = async (tx: Transaction) => {
tx.partialSign(this.keypair);
return tx
return tx;
};
let allSigner = async (txs : Transaction[]) => {
txs.forEach(x=> x.partialSign(this.keypair));
let allSigner = async (txs: Transaction[]) => {
txs.forEach((x) => x.partialSign(this.keypair));
return txs;
};
super(
connection,
connection,
{
signTransaction: txSigner,
signAllTransactions: allSigner,
publicKey : keypair.publicKey,
publicKey: keypair.publicKey,
},
{commitment: 'confirmed'}
)
{ commitment: "confirmed" }
);
this.keypair = keypair;
}
getKeypair() : Keypair {
return this.keypair
getKeypair(): Keypair {
return this.keypair;
}
}
}

View File

@ -1,13 +1,12 @@
import { Keypair } from "@solana/web3.js";
import * as fs from 'fs';
import * as fs from "fs";
export function getKeypairFromFile(filePath: String): Keypair {
return Keypair.fromSecretKey(
Uint8Array.from(
JSON.parse(
process.env.KEYPAIR ||
fs.readFileSync(filePath.toString(), 'utf-8'),
),
),
return Keypair.fromSecretKey(
Uint8Array.from(
JSON.parse(
process.env.KEYPAIR || fs.readFileSync(filePath.toString(), "utf-8")
)
)
);
}

View File

@ -1,229 +0,0 @@
import { command, number, option, string, run, boolean, flag } from 'cmd-ts';
import * as fs from 'fs';
import programs from './programs.json';
import { Commitment, Connection, Keypair, LAMPORTS_PER_SOL, Transaction } from '@solana/web3.js';
import { getKeypairFromFile } from './common_utils';
import { deploy_programs } from './deploy_programs';
import { User, createUser, mintUser } from './general/create_users';
import { configure_accounts } from './general/accounts';
import { Command, OutputFile } from './output_file';
import { MintUtils } from './general/mint_utils';
import { OpenbookConfigurator } from './openbook-v2/configure_openbook';
const numberOfAccountsToBeCreated = option({
type: number,
defaultValue: () => 256,
long: 'number-of-accounts',
});
const endpoint = option({
type: string,
defaultValue: () => "http://127.0.0.1:8899",
long: 'url',
short: 'u',
description: "RPC url",
});
const authority = option({
type: string,
defaultValue: () => "~/.config/solana/id.json",
long: 'authority',
short: 'a'
});
const nbPayers = option({
type: number,
defaultValue: () => 10,
long: 'number-of-payers',
short: 'p',
description: "Number of payers used for testing"
});
const balancePerPayer = option({
type: number,
defaultValue: () => 1,
long: 'payer-balance',
short: 'b',
description: "Balance of payer in SOLs"
});
const nbMints = option({
type: number,
defaultValue: () => 10,
long: 'number-of-mints',
short: 'm',
description: "Number of mints"
});
const skipProgramDeployment = flag({
type: boolean,
defaultValue: () => false,
long: 'skip-program-deployment',
short: 's',
description: "Skip deploying programs"
});
const outFile = option({
type: string,
defaultValue: () => "config.json",
long: 'output-file',
short: 'o'
});
const app = command(
{
name: "configure",
args: {
endpoint,
numberOfAccountsToBeCreated,
authority,
nbPayers,
balancePerPayer,
nbMints,
skipProgramDeployment,
outFile,
},
handler: ({
endpoint,
numberOfAccountsToBeCreated,
authority,
nbPayers,
balancePerPayer,
nbMints,
skipProgramDeployment,
outFile,
}) => {
console.log("configuring a new test instance");
configure(
endpoint,
numberOfAccountsToBeCreated,
authority,
nbPayers,
balancePerPayer,
nbMints,
skipProgramDeployment,
outFile,
).then(_ => {
console.log("configuration finished");
});
},
}
)
run(app, process.argv.slice(2))
// configure part
async function configure(
endpoint: String,
numberOfAccountsToBeCreated: number,
authorityFile: String,
nbPayers: number,
balancePerPayer: number,
nbMints: number,
skipProgramDeployment: boolean,
outFile: String,
) {
// create connections
const connection = new Connection(
endpoint.toString(),
'confirmed' as Commitment,
);
// configure authority
const authority = getKeypairFromFile(authorityFile);
const authorityBalance = await connection.getBalance(authority.publicKey);
const requiredBalance = nbPayers * (balancePerPayer * LAMPORTS_PER_SOL) + 100 * LAMPORTS_PER_SOL;
if (authorityBalance < requiredBalance) {
console.log("authority may have low balance balance " + authorityBalance + " required balance " + requiredBalance);
}
let programOutputData = programs.map(x => {
let kp = getKeypairFromFile(x.programKeyPath);
let emptyCommands : Command[] = [];
return {
name: x.name,
program_id: kp.publicKey,
commands: emptyCommands,
}
})
let programIds = programOutputData.map(x => {
return x.program_id
});
if (!skipProgramDeployment) {
console.log("starting program deployment");
await deploy_programs(endpoint, authorityFile.toString(), programs);
console.log("programs deployed");
}
console.log("Creating Mints");
let mintUtils = new MintUtils(connection, authority);
let mints = await mintUtils.createMints(nbMints);
console.log("Mints created")
console.log("Configuring openbook-v2")
let index = programs.findIndex(x => x.name === "openbook_v2");
let openbookProgramId = programOutputData[index].program_id;
let openbookConfigurator = new OpenbookConfigurator(connection, authority, mintUtils, openbookProgramId);
let markets = await openbookConfigurator.configureOpenbookV2(mints);
programOutputData[index].commands = await openbookConfigurator.getCommands();
console.log("Finished configuring openbook")
console.log("Creating users");
let users = await Promise.all(Array.from(Array(nbPayers).keys()).map(_ => createUser(connection, authority, balancePerPayer)));
let tokenAccounts = await Promise.all(users.map(
/// user is richer than bill gates, but not as rich as certain world leaders
async(user) => await mintUser(connection, authority, mints, mintUtils, user.publicKey, 100_000_000_000_000_000)
))
let userOpenOrders = await Promise.all(users.map(
/// user is crazy betting all his money in crypto market
async(user) => await openbookConfigurator.configureMarketForUser(user, markets)
))
let userData: User [] = users.map((user, i) => {
return {
secret: Array.from(user.secretKey),
open_orders: userOpenOrders[i],
token_data: tokenAccounts[i],
}
})
console.log("Users created");
console.log("Filling up orderbook");
await Promise.all( userData.map( async(user, i) => {
for (const market of markets) {
await openbookConfigurator.fillOrderBook(user, users[i], market, 32);
}
}) )
console.log("Orderbook filled");
console.log("Creating accounts")
let accounts = await configure_accounts(connection, authority, numberOfAccountsToBeCreated, programIds);
// adding known accounts
const marketAccountsList = markets.map(market => [market.asks, market.bids, market.market_pk, market.oracle, market.quote_vault, market.base_vault, market.base_mint, market.quote_mint] ).flat();
const userAccountsList = userData.map(user => {
const allOpenOrdersAccounts = user.open_orders.map(x=>x.open_orders).flat();
const allTokenAccounts = user.token_data.map(x => x.token_account);
return allOpenOrdersAccounts.concat(allTokenAccounts)
}).flat()
accounts = accounts.concat(marketAccountsList).concat(userAccountsList);
console.log("Accounts created")
let outputFile: OutputFile = {
programs: programOutputData,
known_accounts: accounts,
users: userData,
mints,
markets,
}
console.log("creating output file")
fs.writeFileSync(outFile.toString(), JSON.stringify(outputFile));
}

View File

@ -1,31 +1,52 @@
import { Connection, Keypair, LAMPORTS_PER_SOL, SystemProgram, PublicKey, Transaction, sendAndConfirmTransaction } from "@solana/web3.js";
import {
Connection,
Keypair,
LAMPORTS_PER_SOL,
SystemProgram,
PublicKey,
Transaction,
sendAndConfirmTransaction,
} from "@solana/web3.js";
import * as web3 from "@solana/web3.js";
import { exec } from "child_process";
import * as fs from "fs"
import * as fs from "fs";
import { promisify } from "util";
import { getKeypairFromFile } from "./common_utils";
export interface ProgramData {
name: string,
programPath: string,
programKeyPath: string,
idl: string,
name: string;
programPath: string;
programKeyPath: string;
idl: string;
}
export async function deploy_programs(url: String, payer: string, programs: ProgramData[]) {
for (const program of programs) {
let cmd = 'solana program deploy --program-id ' + program.programKeyPath + ' --keypair ' + payer + ' --url ' + url + ' ' + program.programPath;
let execPromise = promisify(exec)
// wait for exec to complete
const {stdout, stderr} = await execPromise(cmd);
if (stdout.length > 0) {
console.log(stdout);
}
export async function deploy_programs(
url: String,
payer: string,
programs: ProgramData[]
) {
for (const program of programs) {
let cmd =
"solana program deploy --program-id " +
program.programKeyPath +
" --keypair " +
payer +
" --url " +
url +
" " +
program.programPath;
let execPromise = promisify(exec);
// wait for exec to complete
const { stdout, stderr } = await execPromise(cmd);
if (stdout.length > 0) {
console.log(stdout);
}
if (stderr.length > 0) {
console.log(stderr);
}
if (stderr.length > 0) {
console.log(stderr);
}
/** TODO: this is not working yet bc. anchor wants a workspace
if (program.idl.length > 0) {
let programId = getKeypairFromFile(program.programKeyPath);
console.log("deploying idl file for program " + programId.publicKey);
@ -44,5 +65,6 @@ export async function deploy_programs(url: String, payer: string, programs: Prog
}
}
}
}
*/
}
}

View File

@ -1,46 +1,62 @@
import { Connection, Keypair, SystemProgram, PublicKey, Transaction, sendAndConfirmTransaction } from "@solana/web3.js";
import {
Connection,
Keypair,
SystemProgram,
PublicKey,
Transaction,
sendAndConfirmTransaction,
} from "@solana/web3.js";
export async function configure_accounts(connection: Connection, authority: Keypair, count: number, programs: PublicKey[]): Promise<PublicKey[]> {
export async function configure_accounts(
connection: Connection,
authority: Keypair,
count: number,
programs: PublicKey[]
): Promise<PublicKey[]> {
let all_accounts: PublicKey[] = [];
// create accounts in batches of 16
for (let i = 0; i < count; i += 16) {
let end = Math.min(i + 16, count);
let nbOfAccs = end - i;
let accounts = await Promise.all(
Array.from(Array(nbOfAccs).keys()).map(async (_) => {
let size = Math.random() * 10_000_000;
if (size < 100) {
size = 100;
}
size = Math.floor(size);
let all_accounts: PublicKey[] = [];
// create accounts in batches of 16
for (let i = 0; i < count; i += 16) {
let end = Math.min(i + 16, count);
let nbOfAccs = end - i;
let accounts = await Promise.all(Array.from(Array(nbOfAccs).keys()).map(async _ => {
let size = Math.random() * 10_000_000;
if (size < 100) {
size = 100;
}
size = Math.floor(size);
const lamports = await connection.getMinimumBalanceForRentExemption(
size
);
let kp = Keypair.generate();
const program = programs[Math.floor(Math.random() * programs.length)];
const lamports = await connection.getMinimumBalanceForRentExemption(size);
let kp = Keypair.generate();
const program = programs[Math.floor(Math.random() * programs.length)];
const transaction = new Transaction().add(
SystemProgram.createAccount({
fromPubkey: authority.publicKey,
newAccountPubkey: kp.publicKey,
lamports,
space: size,
programId: program,
})
);
const transaction = new Transaction().add(
SystemProgram.createAccount({
fromPubkey: authority.publicKey,
newAccountPubkey: kp.publicKey,
lamports,
space: size,
programId: program,
}))
transaction.feePayer = authority.publicKey;
let hash = await connection.getRecentBlockhash();
transaction.recentBlockhash = hash.blockhash;
// Sign transaction, broadcast, and confirm
await sendAndConfirmTransaction(
connection,
transaction,
[authority, kp],
{ commitment: "confirmed" }
);
transaction.feePayer = authority.publicKey;
let hash = await connection.getRecentBlockhash();
transaction.recentBlockhash = hash.blockhash;
// Sign transaction, broadcast, and confirm
await sendAndConfirmTransaction(
connection,
transaction,
[authority, kp],
{ commitment: 'confirmed' },
);
return kp.publicKey
}))
all_accounts = all_accounts.concat(accounts);
}
return all_accounts
return kp.publicKey;
})
);
all_accounts = all_accounts.concat(accounts);
}
return all_accounts;
}

View File

@ -1,44 +1,74 @@
import { Connection, Keypair, LAMPORTS_PER_SOL, PublicKey, SystemProgram, Transaction, sendAndConfirmTransaction } from "@solana/web3.js";
import {
Connection,
Keypair,
LAMPORTS_PER_SOL,
PublicKey,
SystemProgram,
Transaction,
sendAndConfirmTransaction,
} from "@solana/web3.js";
import { Market } from "../openbook-v2/create_markets";
import { MintUtils } from "./mint_utils";
import * as splToken from '@solana/spl-token'
import * as splToken from "@solana/spl-token";
import { OpenOrders } from "../openbook-v2/configure_openbook";
export interface User {
secret: number[],
token_data : TokenAccountData[],
open_orders: OpenOrders[],
secret: number[];
token_data: TokenAccountData[];
open_orders: OpenOrders[];
}
export async function createUser(connection: Connection, authority: Keypair, balancePerPayer: number): Promise<Keypair> {
let payer = Keypair.generate();
let transfer_ix = SystemProgram.transfer({
fromPubkey: authority.publicKey,
toPubkey: payer.publicKey,
lamports: balancePerPayer * LAMPORTS_PER_SOL,
});
let tx = new Transaction().add(transfer_ix);
tx.feePayer = authority.publicKey;
const bh = await connection.getLatestBlockhash();
tx.recentBlockhash = bh.blockhash;
sendAndConfirmTransaction(connection, tx, [authority]);
return payer
export async function createUser(
connection: Connection,
authority: Keypair,
balancePerPayer: number
): Promise<Keypair> {
let payer = Keypair.generate();
let transfer_ix = SystemProgram.transfer({
fromPubkey: authority.publicKey,
toPubkey: payer.publicKey,
lamports: balancePerPayer * LAMPORTS_PER_SOL,
});
let tx = new Transaction().add(transfer_ix);
tx.feePayer = authority.publicKey;
const bh = await connection.getLatestBlockhash();
tx.recentBlockhash = bh.blockhash;
sendAndConfirmTransaction(connection, tx, [authority]);
return payer;
}
interface TokenAccountData {
mint: PublicKey,
token_account: PublicKey
mint: PublicKey;
token_account: PublicKey;
}
export async function mintUser(connection: Connection, authority: Keypair, mints: PublicKey[], mintUtils: MintUtils, user: PublicKey, amount: number) : Promise<TokenAccountData[]> {
return await Promise.all(
mints.map(async(mint)=> {
const tokenAccount = await mintUtils.createTokenAccount(mint, authority, user);
await splToken.mintTo(connection, authority, mint, tokenAccount, authority, amount);
return {
mint: mint,
token_account: tokenAccount
}
})
)
export async function mintUser(
connection: Connection,
authority: Keypair,
mints: PublicKey[],
mintUtils: MintUtils,
user: PublicKey,
amount: number
): Promise<TokenAccountData[]> {
return await Promise.all(
mints.map(async (mint) => {
const tokenAccount = await mintUtils.createTokenAccount(
mint,
authority,
user
);
await splToken.mintTo(
connection,
authority,
mint,
tokenAccount,
authority,
amount
);
return {
mint: mint,
token_account: tokenAccount,
};
})
);
}

View File

@ -1,63 +1,59 @@
import * as splToken from "@solana/spl-token";
import {
PublicKey,
Connection,
Keypair,
} from "@solana/web3.js";
import { PublicKey, Connection, Keypair } from "@solana/web3.js";
export interface TokenData {
mint : PublicKey,
startingPrice : number,
nbDecimals: number,
priceOracle: Keypair | undefined,
mint: PublicKey;
startingPrice: number;
nbDecimals: number;
priceOracle: Keypair | undefined;
}
export class MintUtils {
private conn: Connection;
private authority: Keypair;
private conn: Connection;
private authority: Keypair;
constructor(conn: Connection, authority: Keypair) {
this.conn = conn;
this.authority = authority;
}
async createMint(nb_decimals = 6): Promise<PublicKey> {
const kp = Keypair.generate();
return await splToken.createMint(
this.conn,
this.authority,
this.authority.publicKey,
this.authority.publicKey,
nb_decimals,
kp
);
}
constructor(conn: Connection, authority: Keypair) {
this.conn = conn;
this.authority = authority;
}
public async createMints(nbMints: number): Promise<PublicKey[]> {
return await Promise.all(
Array.from(Array(nbMints).keys()).map((_) => {
return this.createMint();
})
);
}
async createMint(nb_decimals = 6) : Promise<PublicKey> {
const kp = Keypair.generate();
return await splToken.createMint(this.conn,
this.authority,
this.authority.publicKey,
this.authority.publicKey,
nb_decimals,
kp)
}
public async createNewToken(nbDecimals = 6, startingPrice = 1_000_000) {
const mint = await this.createMint(nbDecimals);
const tokenData: TokenData = {
mint: mint,
startingPrice: startingPrice,
nbDecimals: nbDecimals,
priceOracle: undefined,
};
return tokenData;
}
public async createMints(nbMints: number) : Promise<PublicKey[]> {
return await Promise.all(Array.from(Array(nbMints).keys()).map(_ => {
return this.createMint()
}))
}
public async createNewToken(nbDecimals = 6, startingPrice = 1_000_000) {
const mint = await this.createMint(nbDecimals);
const tokenData : TokenData = {
mint: mint,
startingPrice : startingPrice,
nbDecimals: nbDecimals,
priceOracle : undefined,
};
return tokenData;
}
public async createTokenAccount(mint: PublicKey, payer: Keypair, owner: PublicKey) {
const account = Keypair.generate();
return splToken.createAccount(
this.conn,
payer,
mint,
owner,
account
)
}
}
public async createTokenAccount(
mint: PublicKey,
payer: Keypair,
owner: PublicKey
) {
const account = Keypair.generate();
return splToken.createAccount(this.conn, payer, mint, owner, account);
}
}

View File

@ -1,27 +1,40 @@
import { Connection, Keypair, PublicKey, SystemProgram, Transaction, sendAndConfirmTransaction } from "@solana/web3.js";
import {
Connection,
Keypair,
PublicKey,
SystemProgram,
Transaction,
sendAndConfirmTransaction,
} from "@solana/web3.js";
export async function createAccount(connection: Connection, authority: Keypair, size: number, owner: PublicKey): Promise<PublicKey> {
const lamports = await connection.getMinimumBalanceForRentExemption(size);
let address = Keypair.generate();
export async function createAccount(
connection: Connection,
authority: Keypair,
size: number,
owner: PublicKey
): Promise<PublicKey> {
const lamports = await connection.getMinimumBalanceForRentExemption(size);
let address = Keypair.generate();
const transaction = new Transaction().add(
SystemProgram.createAccount({
fromPubkey: authority.publicKey,
newAccountPubkey: address.publicKey,
lamports,
space: size,
programId: owner,
}))
const transaction = new Transaction().add(
SystemProgram.createAccount({
fromPubkey: authority.publicKey,
newAccountPubkey: address.publicKey,
lamports,
space: size,
programId: owner,
})
);
transaction.feePayer = authority.publicKey;
let hash = await connection.getRecentBlockhash();
transaction.recentBlockhash = hash.blockhash;
// Sign transaction, broadcast, and confirm
await sendAndConfirmTransaction(
connection,
transaction,
[authority, address],
{ commitment: 'confirmed' },
);
return address.publicKey;
}
transaction.feePayer = authority.publicKey;
let hash = await connection.getRecentBlockhash();
transaction.recentBlockhash = hash.blockhash;
// Sign transaction, broadcast, and confirm
await sendAndConfirmTransaction(
connection,
transaction,
[authority, address],
{ commitment: "confirmed" }
);
return address.publicKey;
}

282
configure/main.ts Normal file
View File

@ -0,0 +1,282 @@
import { command, number, option, string, run, boolean, flag } from "cmd-ts";
import * as fs from "fs";
import programs from "./programs.json";
import {
Commitment,
Connection,
Keypair,
LAMPORTS_PER_SOL,
Transaction,
} from "@solana/web3.js";
import { getKeypairFromFile } from "./common_utils";
import { deploy_programs } from "./deploy_programs";
import { User, createUser, mintUser } from "./general/create_users";
import { configure_accounts } from "./general/accounts";
import { Command, OutputFile } from "./output_file";
import { MintUtils } from "./general/mint_utils";
import { OpenbookConfigurator } from "./openbook-v2/configure_openbook";
const numberOfAccountsToBeCreated = option({
type: number,
defaultValue: () => 256,
long: "number-of-accounts",
});
const endpoint = option({
type: string,
defaultValue: () => "http://127.0.0.1:8899",
long: "url",
short: "u",
description: "RPC url",
});
const authority = option({
type: string,
defaultValue: () => "~/.config/solana/id.json",
long: "authority",
short: "a",
});
const nbPayers = option({
type: number,
defaultValue: () => 10,
long: "number-of-payers",
short: "p",
description: "Number of payers used for testing",
});
const balancePerPayer = option({
type: number,
defaultValue: () => 1,
long: "payer-balance",
short: "b",
description: "Balance of payer in SOLs",
});
const nbMints = option({
type: number,
defaultValue: () => 10,
long: "number-of-mints",
short: "m",
description: "Number of mints",
});
const skipProgramDeployment = flag({
type: boolean,
defaultValue: () => false,
long: "skip-program-deployment",
short: "s",
description: "Skip deploying programs",
});
const outFile = option({
type: string,
defaultValue: () => "cofigure/config.json",
long: "output-file",
short: "o",
});
const app = command({
name: "configure",
args: {
endpoint,
numberOfAccountsToBeCreated,
authority,
nbPayers,
balancePerPayer,
nbMints,
skipProgramDeployment,
outFile,
},
handler: ({
endpoint,
numberOfAccountsToBeCreated,
authority,
nbPayers,
balancePerPayer,
nbMints,
skipProgramDeployment,
outFile,
}) => {
console.log("configuring a new test instance");
configure(
endpoint,
numberOfAccountsToBeCreated,
authority,
nbPayers,
balancePerPayer,
nbMints,
skipProgramDeployment,
outFile
).then((_) => {
console.log("configuration finished");
});
},
});
run(app, process.argv.slice(2));
// configure part
async function configure(
endpoint: String,
numberOfAccountsToBeCreated: number,
authorityFile: String,
nbPayers: number,
balancePerPayer: number,
nbMints: number,
skipProgramDeployment: boolean,
outFile: String
) {
// create connections
const connection = new Connection(
endpoint.toString(),
"confirmed" as Commitment
);
// configure authority
const authority = getKeypairFromFile(authorityFile);
const authorityBalance = await connection.getBalance(authority.publicKey);
const requiredBalance =
nbPayers * (balancePerPayer * LAMPORTS_PER_SOL) + 100 * LAMPORTS_PER_SOL;
if (authorityBalance < requiredBalance) {
console.log(
"authority may have low balance balance " +
authorityBalance +
" required balance " +
requiredBalance
);
}
let programOutputData = programs.map((x) => {
let kp = getKeypairFromFile(x.programKeyPath);
let emptyCommands: Command[] = [];
return {
name: x.name,
program_id: kp.publicKey,
commands: emptyCommands,
};
});
let programIds = programOutputData.map((x) => {
return x.program_id;
});
if (!skipProgramDeployment) {
console.log("starting program deployment");
await deploy_programs(endpoint, authorityFile.toString(), programs);
console.log("programs deployed");
}
console.log("Creating Mints");
let mintUtils = new MintUtils(connection, authority);
let mints = await mintUtils.createMints(nbMints);
console.log("Mints created");
console.log("Configuring openbook-v2");
let index = programs.findIndex((x) => x.name === "openbook_v2");
let openbookProgramId = programOutputData[index].program_id;
let openbookConfigurator = new OpenbookConfigurator(
connection,
authority,
mintUtils,
openbookProgramId
);
let markets = await openbookConfigurator.configureOpenbookV2(mints);
programOutputData[index].commands = await openbookConfigurator.getCommands();
console.log("Finished configuring openbook");
console.log("Creating users");
let users = await Promise.all(
Array.from(Array(nbPayers).keys()).map((_) =>
createUser(connection, authority, balancePerPayer)
)
);
let tokenAccounts = await Promise.all(
users.map(
/// user is richer than bill gates, but not as rich as certain world leaders
async (user) =>
await mintUser(
connection,
authority,
mints,
mintUtils,
user.publicKey,
100_000_000_000_000_000
)
)
);
let userOpenOrders = await Promise.all(
users.map(
/// user is crazy betting all his money in crypto market
async (user) =>
await openbookConfigurator.configureMarketForUser(user, markets)
)
);
let userData: User[] = users.map((user, i) => {
return {
secret: Array.from(user.secretKey),
open_orders: userOpenOrders[i],
token_data: tokenAccounts[i],
};
});
console.log("Users created");
console.log("Filling up orderbook");
await Promise.all(
userData.map(async (user, i) => {
for (const market of markets) {
await openbookConfigurator.fillOrderBook(user, users[i], market, 32);
}
})
);
console.log("Orderbook filled");
console.log("Creating accounts");
let accounts = await configure_accounts(
connection,
authority,
numberOfAccountsToBeCreated,
programIds
);
// adding known accounts
const marketAccountsList = markets
.map((market) => [
market.asks,
market.bids,
market.market_pk,
market.oracle,
market.quote_vault,
market.base_vault,
market.base_mint,
market.quote_mint,
])
.flat();
const userAccountsList = userData
.map((user) => {
const allOpenOrdersAccounts = user.open_orders
.map((x) => x.open_orders)
.flat();
const allTokenAccounts = user.token_data.map((x) => x.token_account);
return allOpenOrdersAccounts.concat(allTokenAccounts);
})
.flat();
accounts = accounts.concat(marketAccountsList).concat(userAccountsList);
console.log("Accounts created");
let outputFile: OutputFile = {
programs: programOutputData,
known_accounts: accounts,
users: userData,
mints,
markets,
};
console.log("creating output file");
fs.writeFileSync(outFile.toString(), JSON.stringify(outputFile));
}

View File

@ -3,7 +3,7 @@ import { TestProvider } from "../anchor_utils";
import { Market, createMarket } from "./create_markets";
import { MintUtils } from "../general/mint_utils";
import { OpenbookV2 } from "./openbook_v2";
import IDL from '../programs/openbook_v2.json'
import IDL from "../programs/openbook_v2.json";
import { BN, Program, web3, IdlTypes } from "@project-serum/anchor";
import { User } from "../general/create_users";
import { U64_MAX_BN } from "@blockworks-foundation/mango-v4";
@ -12,136 +12,176 @@ import { Command } from "../output_file";
import assert from "assert";
export interface OpenOrders {
market: PublicKey,
open_orders: PublicKey
market: PublicKey;
open_orders: PublicKey;
}
export class OpenbookConfigurator {
anchorProvider: TestProvider;
mintUtils: MintUtils;
openbookProgramId: PublicKey;
program: Program<OpenbookV2>;
anchorProvider: TestProvider;
mintUtils: MintUtils;
openbookProgramId: PublicKey;
program: Program<OpenbookV2>;
constructor(
connection: Connection,
authority: Keypair,
mintUtils: MintUtils,
openbookProgramId: PublicKey
) {
this.anchorProvider = new TestProvider(connection, authority);
this.mintUtils = mintUtils;
this.openbookProgramId = openbookProgramId;
this.program = new Program<OpenbookV2>(
IDL as OpenbookV2,
this.openbookProgramId,
this.anchorProvider
);
}
constructor(connection: Connection, authority: Keypair, mintUtils: MintUtils, openbookProgramId: PublicKey) {
this.anchorProvider = new TestProvider(connection, authority);
this.mintUtils = mintUtils;
this.openbookProgramId = openbookProgramId;
this.program = new Program<OpenbookV2>(
IDL as OpenbookV2,
this.openbookProgramId,
public async configureOpenbookV2(mints: PublicKey[]): Promise<Market[]> {
let quoteMint = mints[0];
let admin = Keypair.generate();
return await Promise.all(
mints
.slice(1)
.map((mint, index) =>
createMarket(
this.program,
this.anchorProvider,
);
}
public async configureOpenbookV2(mints: PublicKey[]): Promise<Market[]> {
let quoteMint = mints[0];
let admin = Keypair.generate();
return await Promise.all(mints.slice(1).map((mint, index) => createMarket(this.program, this.anchorProvider, this.mintUtils, admin, this.openbookProgramId, mint, quoteMint, index)))
}
public async configureMarketForUser(user: Keypair, markets: Market[],) : Promise<OpenOrders[]> {
const openOrders = await Promise.all(
markets.map(async(market) => {
let accountIndex = new BN(0);
let [openOrders, _tmp] = PublicKey.findProgramAddressSync([Buffer.from("OpenOrders"), user.publicKey.toBuffer(), market.market_pk.toBuffer(), accountIndex.toBuffer("le", 4)], this.openbookProgramId)
await this.program.methods.initOpenOrders(
0,
64
).accounts({
openOrdersAccount: openOrders,
market: market.market_pk,
owner: user.publicKey,
payer: this.anchorProvider.publicKey,
systemProgram: web3.SystemProgram.programId,
}).signers([user]).rpc();
return [market.market_pk, openOrders]
})
this.mintUtils,
admin,
this.openbookProgramId,
mint,
quoteMint,
index
)
)
);
}
return openOrders.map(x=> {
return {
market : x[0],
open_orders : x[1],
}
public async configureMarketForUser(
user: Keypair,
markets: Market[]
): Promise<OpenOrders[]> {
const openOrders = await Promise.all(
markets.map(async (market) => {
let accountIndex = new BN(0);
let [openOrders, _tmp] = PublicKey.findProgramAddressSync(
[
Buffer.from("OpenOrders"),
user.publicKey.toBuffer(),
market.market_pk.toBuffer(),
accountIndex.toBuffer("le", 4),
],
this.openbookProgramId
);
await this.program.methods
.initOpenOrders(0, 64)
.accounts({
openOrdersAccount: openOrders,
market: market.market_pk,
owner: user.publicKey,
payer: this.anchorProvider.publicKey,
systemProgram: web3.SystemProgram.programId,
})
.signers([user])
.rpc();
return [market.market_pk, openOrders];
})
);
return openOrders.map((x) => {
return {
market: x[0],
open_orders: x[1],
};
});
}
public async fillOrderBook(
user: User,
userKp: Keypair,
market: Market,
nbOrders: number
) {
for (let i = 0; i < nbOrders; ++i) {
let side = { bid: {} };
let placeOrder = { limit: {} };
await this.program.methods
.placeOrder(
side,
new BN(1000 - 1 - i),
new BN(10),
new BN(1000000),
new BN(i),
placeOrder,
false,
U64_MAX_BN,
255
)
.accounts({
asks: market.asks,
baseVault: market.base_vault,
bids: market.bids,
eventQueue: market.event_queue,
market: market.market_pk,
openOrdersAccount: user.open_orders[market.market_index].open_orders,
oracle: market.oracle,
owner: userKp.publicKey,
payer: user.token_data[0].token_account,
quoteVault: market.quote_vault,
systemProgram: web3.SystemProgram.programId,
tokenProgram: TOKEN_PROGRAM_ID,
})
.signers([userKp])
.rpc();
}
public async fillOrderBook(user: User, userKp: Keypair, market: Market, nbOrders: number) {
for (let i = 0; i < nbOrders; ++i) {
let side = { ask: {} };
let placeOrder = { limit: {} };
for( let i=0; i<nbOrders; ++i) {
let side = {bid:{}} ;
let placeOrder = {limit:{}};
await this.program.methods.placeOrder(
side,
new BN(1000-1-i),
new BN(10),
new BN(1000000),
new BN(i),
placeOrder,
false,
U64_MAX_BN,
255,
).accounts({
asks: market.asks,
baseVault: market.base_vault,
bids: market.bids,
eventQueue: market.event_queue,
market: market.market_pk,
openOrdersAccount: user.open_orders[market.market_index].open_orders,
oracle: market.oracle,
owner: userKp.publicKey,
payer: user.token_data[0].token_account,
quoteVault: market.quote_vault,
systemProgram: web3.SystemProgram.programId,
tokenProgram: TOKEN_PROGRAM_ID,
}).signers([userKp]).rpc();
}
for( let i=0; i<nbOrders; ++i) {
let side = {ask:{}} ;
let placeOrder = {limit:{}};
await this.program.methods.placeOrder(
side,
new BN(1000+1+i),
new BN(10000),
new BN(1000000),
new BN(i+nbOrders+1),
placeOrder,
false,
U64_MAX_BN,
255,
).accounts({
asks: market.asks,
baseVault: market.base_vault,
bids: market.bids,
eventQueue: market.event_queue,
market: market.market_pk,
openOrdersAccount: user.open_orders[market.market_index].open_orders,
oracle: market.oracle,
owner: userKp.publicKey,
payer: user.token_data[market.market_index+1].token_account,
quoteVault: market.quote_vault,
systemProgram: web3.SystemProgram.programId,
tokenProgram: TOKEN_PROGRAM_ID,
}).signers([userKp]).rpc();
}
await this.program.methods
.placeOrder(
side,
new BN(1000 + 1 + i),
new BN(10000),
new BN(1000000),
new BN(i + nbOrders + 1),
placeOrder,
false,
U64_MAX_BN,
255
)
.accounts({
asks: market.asks,
baseVault: market.base_vault,
bids: market.bids,
eventQueue: market.event_queue,
market: market.market_pk,
openOrdersAccount: user.open_orders[market.market_index].open_orders,
oracle: market.oracle,
owner: userKp.publicKey,
payer: user.token_data[market.market_index + 1].token_account,
quoteVault: market.quote_vault,
systemProgram: web3.SystemProgram.programId,
tokenProgram: TOKEN_PROGRAM_ID,
})
.signers([userKp])
.rpc();
}
}
/// this is a special method.
/// It is pain to create an anchor instruction in rust
/// so this method will create the instruction in typescript and serialize into bytes and store it into command type
public async getCommands() : Promise<Command[]> {
let side = {bid:{}} ;
let placeOrder = {limit:{}};
let placeOrderIx = await this.program.methods.placeOrder(
/// this is a special method.
/// It is pain to create an anchor instruction in rust
/// so this method will create the instruction in typescript and serialize into bytes and store it into command type
public async getCommands(): Promise<Command[]> {
let side = { bid: {} };
let placeOrder = { limit: {} };
let placeOrderIx = await this.program.methods
.placeOrder(
side,
new BN(0),
new BN(0),
@ -150,8 +190,9 @@ export class OpenbookConfigurator {
placeOrder,
false,
U64_MAX_BN,
255,
).accounts({
255
)
.accounts({
asks: PublicKey.default,
baseVault: PublicKey.default,
bids: PublicKey.default,
@ -164,31 +205,34 @@ export class OpenbookConfigurator {
quoteVault: PublicKey.default,
systemProgram: web3.SystemProgram.programId,
tokenProgram: TOKEN_PROGRAM_ID,
}).instruction();
})
.instruction();
let argument_sizes = [8, 1, 8, 8, 8, 8, 1, 1, 8, 1];
assert(argument_sizes.reduce( (sum, current) => sum + current, 0 ) === placeOrderIx.data.length);
let placeOrderCommand : Command = {
name: "placeOrder",
instruction: Array.from(placeOrderIx.data),
argument_sizes,
assert(
argument_sizes.reduce((sum, current) => sum + current, 0) ===
placeOrderIx.data.length
);
let placeOrderCommand: Command = {
name: "placeOrder",
instruction: Array.from(placeOrderIx.data),
argument_sizes,
};
let consumeEvents = await this.program.methods.consumeEvents(
new BN(0),
).accounts(
{
eventQueue: PublicKey.default,
market: PublicKey.default,
}
).instruction();
let consumeEvents = await this.program.methods
.consumeEvents(new BN(0))
.accounts({
eventQueue: PublicKey.default,
market: PublicKey.default,
})
.instruction();
let consumeEventsCommand : Command = {
instruction: Array.from(consumeEvents.data),
name: "consumeEvents",
argument_sizes: [8, 1]
}
let consumeEventsCommand: Command = {
instruction: Array.from(consumeEvents.data),
name: "consumeEvents",
argument_sizes: [8, 1],
};
return [placeOrderCommand, consumeEventsCommand]
return [placeOrderCommand, consumeEventsCommand];
}
}
}

View File

@ -1,92 +1,136 @@
import { Connection, Keypair, PublicKey } from '@solana/web3.js';
import IDL from '../programs/openbook_v2.json'
import { Program, web3, BN } from '@project-serum/anchor';
import { createAccount } from '../general/solana_utils';
import { MintUtils } from '../general/mint_utils';
import { I80F48, I80F48Dto } from '@blockworks-foundation/mango-v4';
import { OpenbookV2 } from './openbook_v2';
import { TestProvider } from '../anchor_utils';
import { Connection, Keypair, PublicKey } from "@solana/web3.js";
import IDL from "../programs/openbook_v2.json";
import { Program, web3, BN } from "@project-serum/anchor";
import { createAccount } from "../general/solana_utils";
import { MintUtils } from "../general/mint_utils";
import { I80F48, I80F48Dto } from "@blockworks-foundation/mango-v4";
import { OpenbookV2 } from "./openbook_v2";
import { TestProvider } from "../anchor_utils";
export interface Market {
name: string,
admin : number[],
market_pk: PublicKey
oracle: PublicKey,
asks: PublicKey,
bids: PublicKey,
event_queue: PublicKey,
base_vault: PublicKey,
quote_vault: PublicKey,
base_mint: PublicKey,
quote_mint: PublicKey,
market_index: number,
name: string;
admin: number[];
market_pk: PublicKey;
oracle: PublicKey;
asks: PublicKey;
bids: PublicKey;
event_queue: PublicKey;
base_vault: PublicKey;
quote_vault: PublicKey;
base_mint: PublicKey;
quote_mint: PublicKey;
market_index: number;
}
export async function createMarket(program:Program<OpenbookV2>, anchorProvider: TestProvider, mintUtils: MintUtils, adminKp: Keypair, openbookProgramId: PublicKey, baseMint: PublicKey, quoteMint: PublicKey, index: number): Promise<Market> {
let [oracleId, _tmp] = PublicKey.findProgramAddressSync([Buffer.from("StubOracle"), baseMint.toBytes()], openbookProgramId)
const admin:PublicKey = adminKp.publicKey;
export async function createMarket(
program: Program<OpenbookV2>,
anchorProvider: TestProvider,
mintUtils: MintUtils,
adminKp: Keypair,
openbookProgramId: PublicKey,
baseMint: PublicKey,
quoteMint: PublicKey,
index: number
): Promise<Market> {
let [oracleId, _tmp] = PublicKey.findProgramAddressSync(
[Buffer.from("StubOracle"), baseMint.toBytes()],
openbookProgramId
);
const admin: PublicKey = adminKp.publicKey;
await program.methods.stubOracleCreate({ val: I80F48.fromNumber(1.0).getData() })
await program.methods
.stubOracleCreate({ val: I80F48.fromNumber(1.0).getData() })
.accounts({
oracle: oracleId,
admin,
mint: baseMint,
payer: anchorProvider.wallet.publicKey,
systemProgram: web3.SystemProgram.programId,
oracle: oracleId,
admin,
mint: baseMint,
payer: anchorProvider.wallet.publicKey,
systemProgram: web3.SystemProgram.programId,
})
.signers([adminKp])
.rpc();
// bookside size = 123720
let asks = await createAccount(anchorProvider.connection, anchorProvider.keypair, 123720, openbookProgramId);
let bids = await createAccount(anchorProvider.connection, anchorProvider.keypair, 123720, openbookProgramId);
let eventQueue = await createAccount(anchorProvider.connection, anchorProvider.keypair, 97688, openbookProgramId);
let marketIndex : BN = new BN(index);
// bookside size = 123720
let asks = await createAccount(
anchorProvider.connection,
anchorProvider.keypair,
123720,
openbookProgramId
);
let bids = await createAccount(
anchorProvider.connection,
anchorProvider.keypair,
123720,
openbookProgramId
);
let eventQueue = await createAccount(
anchorProvider.connection,
anchorProvider.keypair,
97688,
openbookProgramId
);
let marketIndex: BN = new BN(index);
let [marketPk, _tmp2] = PublicKey.findProgramAddressSync([Buffer.from("Market"), admin.toBuffer(), marketIndex.toBuffer("le", 4)], openbookProgramId)
let [marketPk, _tmp2] = PublicKey.findProgramAddressSync(
[Buffer.from("Market"), admin.toBuffer(), marketIndex.toBuffer("le", 4)],
openbookProgramId
);
let baseVault = await mintUtils.createTokenAccount(baseMint, anchorProvider.keypair, marketPk);
let quoteVault = await mintUtils.createTokenAccount(quoteMint, anchorProvider.keypair, marketPk);
let name = 'index ' + index.toString() + ' wrt 0';
let baseVault = await mintUtils.createTokenAccount(
baseMint,
anchorProvider.keypair,
marketPk
);
let quoteVault = await mintUtils.createTokenAccount(
quoteMint,
anchorProvider.keypair,
marketPk
);
let name = "index " + index.toString() + " wrt 0";
await program.methods.createMarket(
marketIndex,
name,
{
confFilter: 0,
maxStalenessSlots: 100,
},
new BN(1), new BN(1), 0, 0, 0
).accounts(
{
admin,
market: marketPk,
bids,
asks,
eventQueue,
payer: anchorProvider.publicKey,
baseVault,
quoteVault,
baseMint,
quoteMint,
systemProgram: web3.SystemProgram.programId,
oracle: oracleId,
}
).signers([adminKp])
await program.methods
.createMarket(
marketIndex,
name,
{
confFilter: 0,
maxStalenessSlots: 100,
},
new BN(1),
new BN(1),
0,
0,
0
)
.accounts({
admin,
market: marketPk,
bids,
asks,
eventQueue,
payer: anchorProvider.publicKey,
baseVault,
quoteVault,
baseMint,
quoteMint,
systemProgram: web3.SystemProgram.programId,
oracle: oracleId,
})
.signers([adminKp])
.rpc();
return {
admin: Array.from(adminKp.secretKey),
name,
bids,
asks,
event_queue: eventQueue,
base_mint: baseMint,
base_vault: baseVault,
market_index: index,
market_pk: marketPk,
oracle: oracleId,
quote_mint: quoteMint,
quote_vault: quoteVault,
}
}
return {
admin: Array.from(adminKp.secretKey),
name,
bids,
asks,
event_queue: eventQueue,
base_mint: baseMint,
base_vault: baseVault,
market_index: index,
market_pk: marketPk,
oracle: oracleId,
quote_mint: quoteMint,
quote_vault: quoteVault,
};
}

File diff suppressed because it is too large Load Diff

View File

@ -3,21 +3,21 @@ import { Market } from "./openbook-v2/create_markets";
import { User } from "./general/create_users";
export interface Command {
name: String,
instruction: number[],
argument_sizes: number[],
name: String;
instruction: number[];
argument_sizes: number[];
}
export interface ProgramOutputData {
name: String,
program_id: PublicKey,
commands: Command [],
name: String;
program_id: PublicKey;
commands: Command[];
}
export interface OutputFile {
users: User[],
programs: ProgramOutputData[],
known_accounts: PublicKey[],
mints: PublicKey[],
markets: Market[],
users: User[];
programs: ProgramOutputData[];
known_accounts: PublicKey[];
mints: PublicKey[];
markets: Market[];
}

View File

@ -1,14 +1,14 @@
[
{
"name": "pyth_mock",
"programPath": "programs/pyth_mock.so",
"programKeyPath": "programs/pyth_mock.json",
"idl": ""
},
{
"name": "openbook_v2",
"programPath": "programs/openbook_v2.so",
"programKeyPath": "programs/openbook_v2-keypair.json",
"idl": "programs/openbook_v2.json"
}
{
"name": "pyth_mock",
"programPath": "configure/programs/pyth_mock.so",
"programKeyPath": "configure/programs/pyth_mock.json",
"idl": ""
},
{
"name": "openbook_v2",
"programPath": "configure/programs/openbook_v2.so",
"programKeyPath": "configure/programs/openbook_v2-keypair.json",
"idl": ""
}
]

View File

@ -1 +1,6 @@
[171,85,64,152,85,43,106,98,158,185,190,190,234,79,138,30,140,60,95,30,192,14,16,22,82,32,87,208,65,91,89,245,57,63,214,97,128,249,112,13,187,5,224,38,17,8,25,178,88,226,115,45,80,88,164,168,139,142,172,189,196,225,156,28]
[
171, 85, 64, 152, 85, 43, 106, 98, 158, 185, 190, 190, 234, 79, 138, 30, 140,
60, 95, 30, 192, 14, 16, 22, 82, 32, 87, 208, 65, 91, 89, 245, 57, 63, 214,
97, 128, 249, 112, 13, 187, 5, 224, 38, 17, 8, 25, 178, 88, 226, 115, 45, 80,
88, 164, 168, 139, 142, 172, 189, 196, 225, 156, 28
]

View File

@ -640,9 +640,7 @@
},
{
"name": "cancelAllOrders",
"docs": [
"Cancel up to `limit` orders."
],
"docs": ["Cancel up to `limit` orders."],
"accounts": [
{
"name": "openOrdersAccount",
@ -679,9 +677,7 @@
},
{
"name": "cancelAllOrdersBySide",
"docs": [
"Cancel up to `limit` orders on a single side of the book."
],
"docs": ["Cancel up to `limit` orders on a single side of the book."],
"accounts": [
{
"name": "openOrdersAccount",
@ -793,9 +789,7 @@
},
{
"name": "settleFunds",
"docs": [
"Withdraw any available tokens."
],
"docs": ["Withdraw any available tokens."],
"accounts": [
{
"name": "openOrdersAccount",
@ -842,9 +836,7 @@
},
{
"name": "sweepFees",
"docs": [
"Sweep fees, as a [`Market`](crate::state::Market)'s admin."
],
"docs": ["Sweep fees, as a [`Market`](crate::state::Market)'s admin."],
"accounts": [
{
"name": "market",
@ -876,9 +868,7 @@
},
{
"name": "closeMarket",
"docs": [
"Close a [`Market`](crate::state::Market)."
],
"docs": ["Close a [`Market`](crate::state::Market)."],
"accounts": [
{
"name": "admin",
@ -1014,23 +1004,17 @@
"fields": [
{
"name": "admin",
"docs": [
"Admin who can close this market"
],
"docs": ["Admin who can close this market"],
"type": "publicKey"
},
{
"name": "marketIndex",
"docs": [
"Index of this market"
],
"docs": ["Index of this market"],
"type": "u32"
},
{
"name": "bump",
"docs": [
"PDA bump"
],
"docs": ["PDA bump"],
"type": "u8"
},
{
@ -1049,57 +1033,39 @@
{
"name": "padding1",
"type": {
"array": [
"u8",
1
]
"array": ["u8", 1]
}
},
{
"name": "name",
"docs": [
"Name. Trailing zero bytes are ignored."
],
"docs": ["Name. Trailing zero bytes are ignored."],
"type": {
"array": [
"u8",
16
]
"array": ["u8", 16]
}
},
{
"name": "bids",
"docs": [
"Address of the BookSide account for bids"
],
"docs": ["Address of the BookSide account for bids"],
"type": "publicKey"
},
{
"name": "asks",
"docs": [
"Address of the BookSide account for asks"
],
"docs": ["Address of the BookSide account for asks"],
"type": "publicKey"
},
{
"name": "eventQueue",
"docs": [
"Address of the EventQueue account"
],
"docs": ["Address of the EventQueue account"],
"type": "publicKey"
},
{
"name": "oracle",
"docs": [
"Oracle account address"
],
"docs": ["Oracle account address"],
"type": "publicKey"
},
{
"name": "oracleConfig",
"docs": [
"Oracle configuration"
],
"docs": ["Oracle configuration"],
"type": {
"defined": "OracleConfig"
}
@ -1137,16 +1103,12 @@
},
{
"name": "seqNum",
"docs": [
"Total number of orders seen"
],
"docs": ["Total number of orders seen"],
"type": "u64"
},
{
"name": "registrationTime",
"docs": [
"Timestamp in seconds that the market was registered at."
],
"docs": ["Timestamp in seconds that the market was registered at."],
"type": "u64"
},
{
@ -1161,45 +1123,34 @@
},
{
"name": "takerFee",
"docs": [
"Fee for taker orders, may not be negative."
],
"docs": ["Fee for taker orders, may not be negative."],
"type": {
"defined": "I80F48"
}
},
{
"name": "feesAccrued",
"docs": [
"Fees accrued in native quote currency"
],
"docs": ["Fees accrued in native quote currency"],
"type": {
"defined": "I80F48"
}
},
{
"name": "feesSettled",
"docs": [
"Fees settled in native quote currency"
],
"docs": ["Fees settled in native quote currency"],
"type": {
"defined": "I80F48"
}
},
{
"name": "feePenalty",
"docs": [
"Fee (in quote native) to charge for ioc orders"
],
"docs": ["Fee (in quote native) to charge for ioc orders"],
"type": "f32"
},
{
"name": "padding2",
"type": {
"array": [
"u8",
4
]
"array": ["u8", 4]
}
},
{
@ -1249,10 +1200,7 @@
{
"name": "reserved",
"type": {
"array": [
"u8",
1888
]
"array": ["u8", 1888]
}
}
]
@ -1270,10 +1218,7 @@
{
"name": "name",
"type": {
"array": [
"u8",
32
]
"array": ["u8", 32]
}
},
{
@ -1291,10 +1236,7 @@
{
"name": "padding",
"type": {
"array": [
"u8",
3
]
"array": ["u8", 3]
}
},
{
@ -1307,9 +1249,7 @@
},
{
"name": "buybackFeesAccruedPrevious",
"docs": [
"Fees buyback amount from the previous expiry interval."
],
"docs": ["Fees buyback amount from the previous expiry interval."],
"type": "u64"
},
{
@ -1328,10 +1268,7 @@
{
"name": "reserved",
"type": {
"array": [
"u8",
208
]
"array": ["u8", 208]
}
},
{
@ -1341,10 +1278,7 @@
{
"name": "padding3",
"type": {
"array": [
"u8",
7
]
"array": ["u8", 7]
}
},
{
@ -1388,10 +1322,7 @@
{
"name": "reserved",
"type": {
"array": [
"u8",
128
]
"array": ["u8", 128]
}
}
]
@ -1427,10 +1358,7 @@
{
"name": "reserved",
"type": {
"array": [
"u8",
256
]
"array": ["u8", 256]
}
},
{
@ -1467,10 +1395,7 @@
{
"name": "reserved",
"type": {
"array": [
"u8",
64
]
"array": ["u8", 64]
}
}
]
@ -1490,10 +1415,7 @@
{
"name": "name",
"type": {
"array": [
"u8",
32
]
"array": ["u8", 32]
}
},
{
@ -1511,10 +1433,7 @@
{
"name": "padding",
"type": {
"array": [
"u8",
3
]
"array": ["u8", 3]
}
},
{
@ -1538,10 +1457,7 @@
{
"name": "reserved",
"type": {
"array": [
"u8",
208
]
"array": ["u8", 208]
}
}
]
@ -1561,16 +1477,12 @@
},
{
"name": "bidsBaseLots",
"docs": [
"Base lots in open bids"
],
"docs": ["Base lots in open bids"],
"type": "i64"
},
{
"name": "asksBaseLots",
"docs": [
"Base lots in open asks"
],
"docs": ["Base lots in open asks"],
"type": "i64"
},
{
@ -1618,10 +1530,7 @@
{
"name": "reserved",
"type": {
"array": [
"u8",
88
]
"array": ["u8", 88]
}
}
]
@ -1639,10 +1548,7 @@
{
"name": "padding1",
"type": {
"array": [
"u8",
7
]
"array": ["u8", 7]
}
},
{
@ -1660,10 +1566,7 @@
{
"name": "reserved",
"type": {
"array": [
"u8",
64
]
"array": ["u8", 64]
}
}
]
@ -1687,10 +1590,7 @@
{
"name": "reserved",
"type": {
"array": [
"u8",
72
]
"array": ["u8", 72]
}
}
]
@ -1733,10 +1633,7 @@
{
"name": "padding",
"type": {
"array": [
"u8",
3
]
"array": ["u8", 3]
}
},
{
@ -1749,21 +1646,14 @@
},
{
"name": "key",
"docs": [
"only the top `prefix_len` bits of `key` are relevant"
],
"docs": ["only the top `prefix_len` bits of `key` are relevant"],
"type": "u128"
},
{
"name": "children",
"docs": [
"indexes into `BookSide::nodes`"
],
"docs": ["indexes into `BookSide::nodes`"],
"type": {
"array": [
"u32",
2
]
"array": ["u32", 2]
}
},
{
@ -1775,19 +1665,13 @@
"iterate through the whole bookside."
],
"type": {
"array": [
"u64",
2
]
"array": ["u64", 2]
}
},
{
"name": "reserved",
"type": {
"array": [
"u8",
72
]
"array": ["u8", 72]
}
}
]
@ -1795,24 +1679,18 @@
},
{
"name": "LeafNode",
"docs": [
"LeafNodes represent an order in the binary tree"
],
"docs": ["LeafNodes represent an order in the binary tree"],
"type": {
"kind": "struct",
"fields": [
{
"name": "tag",
"docs": [
"NodeTag"
],
"docs": ["NodeTag"],
"type": "u8"
},
{
"name": "ownerSlot",
"docs": [
"Index into the owning OpenOrdersAccount's OpenOrders"
],
"docs": ["Index into the owning OpenOrdersAccount's OpenOrders"],
"type": "u8"
},
{
@ -1825,10 +1703,7 @@
{
"name": "padding",
"type": {
"array": [
"u8",
1
]
"array": ["u8", 1]
}
},
{
@ -1842,38 +1717,27 @@
{
"name": "padding2",
"type": {
"array": [
"u8",
2
]
"array": ["u8", 2]
}
},
{
"name": "key",
"docs": [
"The binary tree key, see new_node_key()"
],
"docs": ["The binary tree key, see new_node_key()"],
"type": "u128"
},
{
"name": "owner",
"docs": [
"Address of the owning OpenOrdersAccount"
],
"docs": ["Address of the owning OpenOrdersAccount"],
"type": "publicKey"
},
{
"name": "quantity",
"docs": [
"Number of base lots to buy or sell, always >=1"
],
"docs": ["Number of base lots to buy or sell, always >=1"],
"type": "i64"
},
{
"name": "timestamp",
"docs": [
"The time the order was placed"
],
"docs": ["The time the order was placed"],
"type": "u64"
},
{
@ -1888,18 +1752,13 @@
},
{
"name": "clientOrderId",
"docs": [
"User defined id for this order, used in FillEvents"
],
"docs": ["User defined id for this order, used in FillEvents"],
"type": "u64"
},
{
"name": "reserved",
"type": {
"array": [
"u8",
32
]
"array": ["u8", 32]
}
}
]
@ -1917,10 +1776,7 @@
{
"name": "data",
"type": {
"array": [
"u8",
119
]
"array": ["u8", 119]
}
}
]
@ -1959,10 +1815,7 @@
{
"name": "padding",
"type": {
"array": [
"u8",
3
]
"array": ["u8", 3]
}
},
{
@ -1980,10 +1833,7 @@
{
"name": "reserved",
"type": {
"array": [
"u8",
512
]
"array": ["u8", 512]
}
},
{
@ -2032,10 +1882,7 @@
{
"name": "padding",
"type": {
"array": [
"u8",
199
]
"array": ["u8", 199]
}
}
]
@ -2065,10 +1912,7 @@
{
"name": "padding",
"type": {
"array": [
"u8",
4
]
"array": ["u8", 4]
}
},
{
@ -2086,10 +1930,7 @@
{
"name": "padding2",
"type": {
"array": [
"u8",
32
]
"array": ["u8", 32]
}
},
{
@ -2103,10 +1944,7 @@
{
"name": "padding3",
"type": {
"array": [
"u8",
16
]
"array": ["u8", 16]
}
},
{
@ -2116,10 +1954,7 @@
{
"name": "padding4",
"type": {
"array": [
"u8",
16
]
"array": ["u8", 16]
}
},
{
@ -2137,10 +1972,7 @@
{
"name": "reserved",
"type": {
"array": [
"u8",
8
]
"array": ["u8", 8]
}
}
]
@ -2166,10 +1998,7 @@
{
"name": "padding0",
"type": {
"array": [
"u8",
5
]
"array": ["u8", 5]
}
},
{
@ -2191,10 +2020,7 @@
{
"name": "padding1",
"type": {
"array": [
"u8",
136
]
"array": ["u8", 136]
}
}
]
@ -2220,9 +2046,7 @@
"fields": [
{
"name": "stablePrice",
"docs": [
"Current stable price to use in health"
],
"docs": ["Current stable price to use in health"],
"type": "f64"
},
{
@ -2239,10 +2063,7 @@
"we use the next one."
],
"type": {
"array": [
"f64",
24
]
"array": ["f64", 24]
}
},
{
@ -2255,16 +2076,12 @@
},
{
"name": "delayAccumulatorTime",
"docs": [
"Accumulating the total time for the above average."
],
"docs": ["Accumulating the total time for the above average."],
"type": "u32"
},
{
"name": "delayIntervalSeconds",
"docs": [
"Length of a delay_interval"
],
"docs": ["Length of a delay_interval"],
"type": "u32"
},
{
@ -2292,19 +2109,13 @@
{
"name": "padding",
"type": {
"array": [
"u8",
7
]
"array": ["u8", 7]
}
},
{
"name": "reserved",
"type": {
"array": [
"u8",
48
]
"array": ["u8", 48]
}
}
]
@ -2925,4 +2736,4 @@
"msg": "The receiver is invalid. Makes sure the receiver's owner is the market admin"
}
]
}
}

View File

@ -1 +1,6 @@
[247,81,41,82,59,37,100,159,77,210,53,136,212,197,48,156,35,235,118,52,60,249,192,135,247,217,123,52,53,60,223,78,205,15,251,191,21,149,104,160,69,71,75,237,133,4,137,222,132,215,169,167,197,234,74,145,175,129,228,68,34,166,170,187]
[
247, 81, 41, 82, 59, 37, 100, 159, 77, 210, 53, 136, 212, 197, 48, 156, 35,
235, 118, 52, 60, 249, 192, 135, 247, 217, 123, 52, 53, 60, 223, 78, 205, 15,
251, 191, 21, 149, 104, 160, 69, 71, 75, 237, 133, 4, 137, 222, 132, 215, 169,
167, 197, 234, 74, 145, 175, 129, 228, 68, 34, 166, 170, 187
]

View File

@ -4,6 +4,9 @@
"main": "index.js",
"repository": "https://github.com/blockworks-foundation/solana-rpc-testing.git",
"license": "MIT",
"scripts": {
"configure": "ts-node configure/main.ts"
},
"devDependencies": {
"@types/node": "^20.1.0",
"ts-node": "^10.9.1",