refactor to run from root and format
This commit is contained in:
parent
3c99ebf336
commit
6fc642d491
|
@ -1,4 +1,4 @@
|
||||||
/target
|
/target
|
||||||
node_modules
|
node_modules
|
||||||
/configure/config.json
|
|
||||||
package-lock.json
|
package-lock.json
|
||||||
|
**/config.json
|
||||||
|
|
|
@ -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]
|
--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]
|
--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]
|
--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`
|
Once the cluster configuration is successfully done we create a json file `config.json`
|
||||||
|
@ -39,7 +39,7 @@ To configure cluster:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
cd configure
|
cd configure
|
||||||
ts-node configure_all.ts -a /home/user/.config/solana/id.json
|
yarn configure -a ../solana_configure_local_cluster/faucet.json
|
||||||
cd ..
|
cd ..
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -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 { 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 { Command } from "./output_file";
|
||||||
import { IDL, OpenbookV2 } from "./openbook-v2/openbook_v2";
|
import { IDL, OpenbookV2 } from "./openbook-v2/openbook_v2";
|
||||||
import { U64_MAX_BN } from "@blockworks-foundation/mango-v4";
|
import { U64_MAX_BN } from "@blockworks-foundation/mango-v4";
|
||||||
|
@ -12,26 +27,26 @@ export class TestProvider extends AnchorProvider {
|
||||||
constructor(connection: Connection, keypair: Keypair) {
|
constructor(connection: Connection, keypair: Keypair) {
|
||||||
let txSigner = async (tx: Transaction) => {
|
let txSigner = async (tx: Transaction) => {
|
||||||
tx.partialSign(this.keypair);
|
tx.partialSign(this.keypair);
|
||||||
return tx
|
return tx;
|
||||||
};
|
};
|
||||||
|
|
||||||
let allSigner = async (txs : Transaction[]) => {
|
let allSigner = async (txs: Transaction[]) => {
|
||||||
txs.forEach(x=> x.partialSign(this.keypair));
|
txs.forEach((x) => x.partialSign(this.keypair));
|
||||||
return txs;
|
return txs;
|
||||||
};
|
};
|
||||||
|
|
||||||
super(
|
super(
|
||||||
connection,
|
connection,
|
||||||
{
|
{
|
||||||
signTransaction: txSigner,
|
signTransaction: txSigner,
|
||||||
signAllTransactions: allSigner,
|
signAllTransactions: allSigner,
|
||||||
publicKey : keypair.publicKey,
|
publicKey: keypair.publicKey,
|
||||||
},
|
},
|
||||||
{commitment: 'confirmed'}
|
{ commitment: "confirmed" }
|
||||||
)
|
);
|
||||||
this.keypair = keypair;
|
this.keypair = keypair;
|
||||||
}
|
}
|
||||||
getKeypair() : Keypair {
|
getKeypair(): Keypair {
|
||||||
return this.keypair
|
return this.keypair;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,12 @@
|
||||||
import { Keypair } from "@solana/web3.js";
|
import { Keypair } from "@solana/web3.js";
|
||||||
import * as fs from 'fs';
|
import * as fs from "fs";
|
||||||
|
|
||||||
export function getKeypairFromFile(filePath: String): Keypair {
|
export function getKeypairFromFile(filePath: String): Keypair {
|
||||||
return Keypair.fromSecretKey(
|
return Keypair.fromSecretKey(
|
||||||
Uint8Array.from(
|
Uint8Array.from(
|
||||||
JSON.parse(
|
JSON.parse(
|
||||||
process.env.KEYPAIR ||
|
process.env.KEYPAIR || fs.readFileSync(filePath.toString(), "utf-8")
|
||||||
fs.readFileSync(filePath.toString(), 'utf-8'),
|
)
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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));
|
|
||||||
}
|
|
|
@ -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 * as web3 from "@solana/web3.js";
|
||||||
import { exec } from "child_process";
|
import { exec } from "child_process";
|
||||||
import * as fs from "fs"
|
import * as fs from "fs";
|
||||||
import { promisify } from "util";
|
import { promisify } from "util";
|
||||||
import { getKeypairFromFile } from "./common_utils";
|
import { getKeypairFromFile } from "./common_utils";
|
||||||
|
|
||||||
export interface ProgramData {
|
export interface ProgramData {
|
||||||
name: string,
|
name: string;
|
||||||
programPath: string,
|
programPath: string;
|
||||||
programKeyPath: string,
|
programKeyPath: string;
|
||||||
idl: string,
|
idl: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function deploy_programs(url: String, payer: string, programs: ProgramData[]) {
|
export async function deploy_programs(
|
||||||
for (const program of programs) {
|
url: String,
|
||||||
let cmd = 'solana program deploy --program-id ' + program.programKeyPath + ' --keypair ' + payer + ' --url ' + url + ' ' + program.programPath;
|
payer: string,
|
||||||
let execPromise = promisify(exec)
|
programs: ProgramData[]
|
||||||
// wait for exec to complete
|
) {
|
||||||
const {stdout, stderr} = await execPromise(cmd);
|
for (const program of programs) {
|
||||||
if (stdout.length > 0) {
|
let cmd =
|
||||||
console.log(stdout);
|
"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) {
|
if (stderr.length > 0) {
|
||||||
console.log(stderr);
|
console.log(stderr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** TODO: this is not working yet bc. anchor wants a workspace
|
||||||
if (program.idl.length > 0) {
|
if (program.idl.length > 0) {
|
||||||
let programId = getKeypairFromFile(program.programKeyPath);
|
let programId = getKeypairFromFile(program.programKeyPath);
|
||||||
console.log("deploying idl file for program " + programId.publicKey);
|
console.log("deploying idl file for program " + programId.publicKey);
|
||||||
|
@ -44,5 +65,6 @@ export async function deploy_programs(url: String, payer: string, programs: Prog
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
*/
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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[] = [];
|
const lamports = await connection.getMinimumBalanceForRentExemption(
|
||||||
// create accounts in batches of 16
|
size
|
||||||
for (let i = 0; i < count; i += 16) {
|
);
|
||||||
let end = Math.min(i + 16, count);
|
let kp = Keypair.generate();
|
||||||
let nbOfAccs = end - i;
|
const program = programs[Math.floor(Math.random() * programs.length)];
|
||||||
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);
|
const transaction = new Transaction().add(
|
||||||
let kp = Keypair.generate();
|
SystemProgram.createAccount({
|
||||||
const program = programs[Math.floor(Math.random() * programs.length)];
|
fromPubkey: authority.publicKey,
|
||||||
|
newAccountPubkey: kp.publicKey,
|
||||||
|
lamports,
|
||||||
|
space: size,
|
||||||
|
programId: program,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
const transaction = new Transaction().add(
|
transaction.feePayer = authority.publicKey;
|
||||||
SystemProgram.createAccount({
|
let hash = await connection.getRecentBlockhash();
|
||||||
fromPubkey: authority.publicKey,
|
transaction.recentBlockhash = hash.blockhash;
|
||||||
newAccountPubkey: kp.publicKey,
|
// Sign transaction, broadcast, and confirm
|
||||||
lamports,
|
await sendAndConfirmTransaction(
|
||||||
space: size,
|
connection,
|
||||||
programId: program,
|
transaction,
|
||||||
}))
|
[authority, kp],
|
||||||
|
{ commitment: "confirmed" }
|
||||||
|
);
|
||||||
|
|
||||||
transaction.feePayer = authority.publicKey;
|
return kp.publicKey;
|
||||||
let hash = await connection.getRecentBlockhash();
|
})
|
||||||
transaction.recentBlockhash = hash.blockhash;
|
);
|
||||||
// Sign transaction, broadcast, and confirm
|
all_accounts = all_accounts.concat(accounts);
|
||||||
await sendAndConfirmTransaction(
|
}
|
||||||
connection,
|
return all_accounts;
|
||||||
transaction,
|
|
||||||
[authority, kp],
|
|
||||||
{ commitment: 'confirmed' },
|
|
||||||
);
|
|
||||||
|
|
||||||
return kp.publicKey
|
|
||||||
}))
|
|
||||||
all_accounts = all_accounts.concat(accounts);
|
|
||||||
}
|
|
||||||
return all_accounts
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 { Market } from "../openbook-v2/create_markets";
|
||||||
import { MintUtils } from "./mint_utils";
|
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";
|
import { OpenOrders } from "../openbook-v2/configure_openbook";
|
||||||
|
|
||||||
export interface User {
|
export interface User {
|
||||||
secret: number[],
|
secret: number[];
|
||||||
token_data : TokenAccountData[],
|
token_data: TokenAccountData[];
|
||||||
open_orders: OpenOrders[],
|
open_orders: OpenOrders[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function createUser(connection: Connection, authority: Keypair, balancePerPayer: number): Promise<Keypair> {
|
export async function createUser(
|
||||||
let payer = Keypair.generate();
|
connection: Connection,
|
||||||
let transfer_ix = SystemProgram.transfer({
|
authority: Keypair,
|
||||||
fromPubkey: authority.publicKey,
|
balancePerPayer: number
|
||||||
toPubkey: payer.publicKey,
|
): Promise<Keypair> {
|
||||||
lamports: balancePerPayer * LAMPORTS_PER_SOL,
|
let payer = Keypair.generate();
|
||||||
});
|
let transfer_ix = SystemProgram.transfer({
|
||||||
let tx = new Transaction().add(transfer_ix);
|
fromPubkey: authority.publicKey,
|
||||||
tx.feePayer = authority.publicKey;
|
toPubkey: payer.publicKey,
|
||||||
const bh = await connection.getLatestBlockhash();
|
lamports: balancePerPayer * LAMPORTS_PER_SOL,
|
||||||
tx.recentBlockhash = bh.blockhash;
|
});
|
||||||
sendAndConfirmTransaction(connection, tx, [authority]);
|
let tx = new Transaction().add(transfer_ix);
|
||||||
return payer
|
tx.feePayer = authority.publicKey;
|
||||||
|
const bh = await connection.getLatestBlockhash();
|
||||||
|
tx.recentBlockhash = bh.blockhash;
|
||||||
|
sendAndConfirmTransaction(connection, tx, [authority]);
|
||||||
|
return payer;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface TokenAccountData {
|
interface TokenAccountData {
|
||||||
mint: PublicKey,
|
mint: PublicKey;
|
||||||
token_account: PublicKey
|
token_account: PublicKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function mintUser(connection: Connection, authority: Keypair, mints: PublicKey[], mintUtils: MintUtils, user: PublicKey, amount: number) : Promise<TokenAccountData[]> {
|
export async function mintUser(
|
||||||
return await Promise.all(
|
connection: Connection,
|
||||||
mints.map(async(mint)=> {
|
authority: Keypair,
|
||||||
const tokenAccount = await mintUtils.createTokenAccount(mint, authority, user);
|
mints: PublicKey[],
|
||||||
await splToken.mintTo(connection, authority, mint, tokenAccount, authority, amount);
|
mintUtils: MintUtils,
|
||||||
return {
|
user: PublicKey,
|
||||||
mint: mint,
|
amount: number
|
||||||
token_account: tokenAccount
|
): 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,
|
||||||
|
};
|
||||||
|
})
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,63 +1,59 @@
|
||||||
import * as splToken from "@solana/spl-token";
|
import * as splToken from "@solana/spl-token";
|
||||||
import {
|
import { PublicKey, Connection, Keypair } from "@solana/web3.js";
|
||||||
PublicKey,
|
|
||||||
Connection,
|
|
||||||
Keypair,
|
|
||||||
} from "@solana/web3.js";
|
|
||||||
|
|
||||||
export interface TokenData {
|
export interface TokenData {
|
||||||
mint : PublicKey,
|
mint: PublicKey;
|
||||||
startingPrice : number,
|
startingPrice: number;
|
||||||
nbDecimals: number,
|
nbDecimals: number;
|
||||||
priceOracle: Keypair | undefined,
|
priceOracle: Keypair | undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class MintUtils {
|
export class MintUtils {
|
||||||
|
private conn: Connection;
|
||||||
|
private authority: Keypair;
|
||||||
|
|
||||||
private conn: Connection;
|
constructor(conn: Connection, authority: Keypair) {
|
||||||
private 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) {
|
public async createMints(nbMints: number): Promise<PublicKey[]> {
|
||||||
this.conn = conn;
|
return await Promise.all(
|
||||||
this.authority = authority;
|
Array.from(Array(nbMints).keys()).map((_) => {
|
||||||
}
|
return this.createMint();
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
async createMint(nb_decimals = 6) : Promise<PublicKey> {
|
public async createNewToken(nbDecimals = 6, startingPrice = 1_000_000) {
|
||||||
const kp = Keypair.generate();
|
const mint = await this.createMint(nbDecimals);
|
||||||
return await splToken.createMint(this.conn,
|
const tokenData: TokenData = {
|
||||||
this.authority,
|
mint: mint,
|
||||||
this.authority.publicKey,
|
startingPrice: startingPrice,
|
||||||
this.authority.publicKey,
|
nbDecimals: nbDecimals,
|
||||||
nb_decimals,
|
priceOracle: undefined,
|
||||||
kp)
|
};
|
||||||
}
|
return tokenData;
|
||||||
|
}
|
||||||
|
|
||||||
public async createMints(nbMints: number) : Promise<PublicKey[]> {
|
public async createTokenAccount(
|
||||||
return await Promise.all(Array.from(Array(nbMints).keys()).map(_ => {
|
mint: PublicKey,
|
||||||
return this.createMint()
|
payer: Keypair,
|
||||||
}))
|
owner: PublicKey
|
||||||
}
|
) {
|
||||||
|
const account = Keypair.generate();
|
||||||
public async createNewToken(nbDecimals = 6, startingPrice = 1_000_000) {
|
return splToken.createAccount(this.conn, payer, mint, owner, account);
|
||||||
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
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -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> {
|
export async function createAccount(
|
||||||
const lamports = await connection.getMinimumBalanceForRentExemption(size);
|
connection: Connection,
|
||||||
let address = Keypair.generate();
|
authority: Keypair,
|
||||||
|
size: number,
|
||||||
|
owner: PublicKey
|
||||||
|
): Promise<PublicKey> {
|
||||||
|
const lamports = await connection.getMinimumBalanceForRentExemption(size);
|
||||||
|
let address = Keypair.generate();
|
||||||
|
|
||||||
const transaction = new Transaction().add(
|
const transaction = new Transaction().add(
|
||||||
SystemProgram.createAccount({
|
SystemProgram.createAccount({
|
||||||
fromPubkey: authority.publicKey,
|
fromPubkey: authority.publicKey,
|
||||||
newAccountPubkey: address.publicKey,
|
newAccountPubkey: address.publicKey,
|
||||||
lamports,
|
lamports,
|
||||||
space: size,
|
space: size,
|
||||||
programId: owner,
|
programId: owner,
|
||||||
}))
|
})
|
||||||
|
);
|
||||||
|
|
||||||
transaction.feePayer = authority.publicKey;
|
transaction.feePayer = authority.publicKey;
|
||||||
let hash = await connection.getRecentBlockhash();
|
let hash = await connection.getRecentBlockhash();
|
||||||
transaction.recentBlockhash = hash.blockhash;
|
transaction.recentBlockhash = hash.blockhash;
|
||||||
// Sign transaction, broadcast, and confirm
|
// Sign transaction, broadcast, and confirm
|
||||||
await sendAndConfirmTransaction(
|
await sendAndConfirmTransaction(
|
||||||
connection,
|
connection,
|
||||||
transaction,
|
transaction,
|
||||||
[authority, address],
|
[authority, address],
|
||||||
{ commitment: 'confirmed' },
|
{ commitment: "confirmed" }
|
||||||
);
|
);
|
||||||
return address.publicKey;
|
return address.publicKey;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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));
|
||||||
|
}
|
|
@ -3,7 +3,7 @@ import { TestProvider } from "../anchor_utils";
|
||||||
import { Market, createMarket } from "./create_markets";
|
import { Market, createMarket } from "./create_markets";
|
||||||
import { MintUtils } from "../general/mint_utils";
|
import { MintUtils } from "../general/mint_utils";
|
||||||
import { OpenbookV2 } from "./openbook_v2";
|
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 { BN, Program, web3, IdlTypes } from "@project-serum/anchor";
|
||||||
import { User } from "../general/create_users";
|
import { User } from "../general/create_users";
|
||||||
import { U64_MAX_BN } from "@blockworks-foundation/mango-v4";
|
import { U64_MAX_BN } from "@blockworks-foundation/mango-v4";
|
||||||
|
@ -12,136 +12,176 @@ import { Command } from "../output_file";
|
||||||
import assert from "assert";
|
import assert from "assert";
|
||||||
|
|
||||||
export interface OpenOrders {
|
export interface OpenOrders {
|
||||||
market: PublicKey,
|
market: PublicKey;
|
||||||
open_orders: PublicKey
|
open_orders: PublicKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class OpenbookConfigurator {
|
export class OpenbookConfigurator {
|
||||||
|
anchorProvider: TestProvider;
|
||||||
|
mintUtils: MintUtils;
|
||||||
|
openbookProgramId: PublicKey;
|
||||||
|
program: Program<OpenbookV2>;
|
||||||
|
|
||||||
anchorProvider: TestProvider;
|
constructor(
|
||||||
mintUtils: MintUtils;
|
connection: Connection,
|
||||||
openbookProgramId: PublicKey;
|
authority: Keypair,
|
||||||
program: Program<OpenbookV2>;
|
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) {
|
public async configureOpenbookV2(mints: PublicKey[]): Promise<Market[]> {
|
||||||
this.anchorProvider = new TestProvider(connection, authority);
|
let quoteMint = mints[0];
|
||||||
this.mintUtils = mintUtils;
|
let admin = Keypair.generate();
|
||||||
this.openbookProgramId = openbookProgramId;
|
return await Promise.all(
|
||||||
this.program = new Program<OpenbookV2>(
|
mints
|
||||||
IDL as OpenbookV2,
|
.slice(1)
|
||||||
this.openbookProgramId,
|
.map((mint, index) =>
|
||||||
|
createMarket(
|
||||||
|
this.program,
|
||||||
this.anchorProvider,
|
this.anchorProvider,
|
||||||
);
|
this.mintUtils,
|
||||||
}
|
admin,
|
||||||
|
this.openbookProgramId,
|
||||||
public async configureOpenbookV2(mints: PublicKey[]): Promise<Market[]> {
|
mint,
|
||||||
let quoteMint = mints[0];
|
quoteMint,
|
||||||
let admin = Keypair.generate();
|
index
|
||||||
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]
|
|
||||||
})
|
|
||||||
)
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return openOrders.map(x=> {
|
public async configureMarketForUser(
|
||||||
return {
|
user: Keypair,
|
||||||
market : x[0],
|
markets: Market[]
|
||||||
open_orders : x[1],
|
): 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) {
|
await this.program.methods
|
||||||
|
.placeOrder(
|
||||||
let side = {bid:{}} ;
|
side,
|
||||||
let placeOrder = {limit:{}};
|
new BN(1000 + 1 + i),
|
||||||
|
new BN(10000),
|
||||||
await this.program.methods.placeOrder(
|
new BN(1000000),
|
||||||
side,
|
new BN(i + nbOrders + 1),
|
||||||
new BN(1000-1-i),
|
placeOrder,
|
||||||
new BN(10),
|
false,
|
||||||
new BN(1000000),
|
U64_MAX_BN,
|
||||||
new BN(i),
|
255
|
||||||
placeOrder,
|
)
|
||||||
false,
|
.accounts({
|
||||||
U64_MAX_BN,
|
asks: market.asks,
|
||||||
255,
|
baseVault: market.base_vault,
|
||||||
).accounts({
|
bids: market.bids,
|
||||||
asks: market.asks,
|
eventQueue: market.event_queue,
|
||||||
baseVault: market.base_vault,
|
market: market.market_pk,
|
||||||
bids: market.bids,
|
openOrdersAccount: user.open_orders[market.market_index].open_orders,
|
||||||
eventQueue: market.event_queue,
|
oracle: market.oracle,
|
||||||
market: market.market_pk,
|
owner: userKp.publicKey,
|
||||||
openOrdersAccount: user.open_orders[market.market_index].open_orders,
|
payer: user.token_data[market.market_index + 1].token_account,
|
||||||
oracle: market.oracle,
|
quoteVault: market.quote_vault,
|
||||||
owner: userKp.publicKey,
|
systemProgram: web3.SystemProgram.programId,
|
||||||
payer: user.token_data[0].token_account,
|
tokenProgram: TOKEN_PROGRAM_ID,
|
||||||
quoteVault: market.quote_vault,
|
})
|
||||||
systemProgram: web3.SystemProgram.programId,
|
.signers([userKp])
|
||||||
tokenProgram: TOKEN_PROGRAM_ID,
|
.rpc();
|
||||||
}).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();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// this is a special method.
|
||||||
/// this is a special method.
|
/// It is pain to create an anchor instruction in rust
|
||||||
/// 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
|
||||||
/// so this method will create the instruction in typescript and serialize into bytes and store it into command type
|
public async getCommands(): Promise<Command[]> {
|
||||||
public async getCommands() : Promise<Command[]> {
|
let side = { bid: {} };
|
||||||
let side = {bid:{}} ;
|
let placeOrder = { limit: {} };
|
||||||
let placeOrder = {limit:{}};
|
let placeOrderIx = await this.program.methods
|
||||||
let placeOrderIx = await this.program.methods.placeOrder(
|
.placeOrder(
|
||||||
side,
|
side,
|
||||||
new BN(0),
|
new BN(0),
|
||||||
new BN(0),
|
new BN(0),
|
||||||
|
@ -150,8 +190,9 @@ export class OpenbookConfigurator {
|
||||||
placeOrder,
|
placeOrder,
|
||||||
false,
|
false,
|
||||||
U64_MAX_BN,
|
U64_MAX_BN,
|
||||||
255,
|
255
|
||||||
).accounts({
|
)
|
||||||
|
.accounts({
|
||||||
asks: PublicKey.default,
|
asks: PublicKey.default,
|
||||||
baseVault: PublicKey.default,
|
baseVault: PublicKey.default,
|
||||||
bids: PublicKey.default,
|
bids: PublicKey.default,
|
||||||
|
@ -164,31 +205,34 @@ export class OpenbookConfigurator {
|
||||||
quoteVault: PublicKey.default,
|
quoteVault: PublicKey.default,
|
||||||
systemProgram: web3.SystemProgram.programId,
|
systemProgram: web3.SystemProgram.programId,
|
||||||
tokenProgram: TOKEN_PROGRAM_ID,
|
tokenProgram: TOKEN_PROGRAM_ID,
|
||||||
}).instruction();
|
})
|
||||||
|
.instruction();
|
||||||
|
|
||||||
let argument_sizes = [8, 1, 8, 8, 8, 8, 1, 1, 8, 1];
|
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);
|
assert(
|
||||||
let placeOrderCommand : Command = {
|
argument_sizes.reduce((sum, current) => sum + current, 0) ===
|
||||||
name: "placeOrder",
|
placeOrderIx.data.length
|
||||||
instruction: Array.from(placeOrderIx.data),
|
);
|
||||||
argument_sizes,
|
let placeOrderCommand: Command = {
|
||||||
|
name: "placeOrder",
|
||||||
|
instruction: Array.from(placeOrderIx.data),
|
||||||
|
argument_sizes,
|
||||||
};
|
};
|
||||||
|
|
||||||
let consumeEvents = await this.program.methods.consumeEvents(
|
let consumeEvents = await this.program.methods
|
||||||
new BN(0),
|
.consumeEvents(new BN(0))
|
||||||
).accounts(
|
.accounts({
|
||||||
{
|
eventQueue: PublicKey.default,
|
||||||
eventQueue: PublicKey.default,
|
market: PublicKey.default,
|
||||||
market: PublicKey.default,
|
})
|
||||||
}
|
.instruction();
|
||||||
).instruction();
|
|
||||||
|
|
||||||
let consumeEventsCommand : Command = {
|
let consumeEventsCommand: Command = {
|
||||||
instruction: Array.from(consumeEvents.data),
|
instruction: Array.from(consumeEvents.data),
|
||||||
name: "consumeEvents",
|
name: "consumeEvents",
|
||||||
argument_sizes: [8, 1]
|
argument_sizes: [8, 1],
|
||||||
}
|
};
|
||||||
|
|
||||||
return [placeOrderCommand, consumeEventsCommand]
|
return [placeOrderCommand, consumeEventsCommand];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,92 +1,136 @@
|
||||||
import { Connection, Keypair, PublicKey } from '@solana/web3.js';
|
import { Connection, Keypair, PublicKey } from "@solana/web3.js";
|
||||||
import IDL from '../programs/openbook_v2.json'
|
import IDL from "../programs/openbook_v2.json";
|
||||||
import { Program, web3, BN } from '@project-serum/anchor';
|
import { Program, web3, BN } from "@project-serum/anchor";
|
||||||
import { createAccount } from '../general/solana_utils';
|
import { createAccount } from "../general/solana_utils";
|
||||||
import { MintUtils } from '../general/mint_utils';
|
import { MintUtils } from "../general/mint_utils";
|
||||||
import { I80F48, I80F48Dto } from '@blockworks-foundation/mango-v4';
|
import { I80F48, I80F48Dto } from "@blockworks-foundation/mango-v4";
|
||||||
import { OpenbookV2 } from './openbook_v2';
|
import { OpenbookV2 } from "./openbook_v2";
|
||||||
import { TestProvider } from '../anchor_utils';
|
import { TestProvider } from "../anchor_utils";
|
||||||
|
|
||||||
export interface Market {
|
export interface Market {
|
||||||
name: string,
|
name: string;
|
||||||
admin : number[],
|
admin: number[];
|
||||||
market_pk: PublicKey
|
market_pk: PublicKey;
|
||||||
oracle: PublicKey,
|
oracle: PublicKey;
|
||||||
asks: PublicKey,
|
asks: PublicKey;
|
||||||
bids: PublicKey,
|
bids: PublicKey;
|
||||||
event_queue: PublicKey,
|
event_queue: PublicKey;
|
||||||
base_vault: PublicKey,
|
base_vault: PublicKey;
|
||||||
quote_vault: PublicKey,
|
quote_vault: PublicKey;
|
||||||
base_mint: PublicKey,
|
base_mint: PublicKey;
|
||||||
quote_mint: PublicKey,
|
quote_mint: PublicKey;
|
||||||
market_index: number,
|
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> {
|
export async function createMarket(
|
||||||
let [oracleId, _tmp] = PublicKey.findProgramAddressSync([Buffer.from("StubOracle"), baseMint.toBytes()], openbookProgramId)
|
program: Program<OpenbookV2>,
|
||||||
const admin:PublicKey = adminKp.publicKey;
|
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({
|
.accounts({
|
||||||
oracle: oracleId,
|
oracle: oracleId,
|
||||||
admin,
|
admin,
|
||||||
mint: baseMint,
|
mint: baseMint,
|
||||||
payer: anchorProvider.wallet.publicKey,
|
payer: anchorProvider.wallet.publicKey,
|
||||||
systemProgram: web3.SystemProgram.programId,
|
systemProgram: web3.SystemProgram.programId,
|
||||||
})
|
})
|
||||||
.signers([adminKp])
|
.signers([adminKp])
|
||||||
.rpc();
|
.rpc();
|
||||||
|
|
||||||
// bookside size = 123720
|
// bookside size = 123720
|
||||||
let asks = await createAccount(anchorProvider.connection, anchorProvider.keypair, 123720, openbookProgramId);
|
let asks = await createAccount(
|
||||||
let bids = await createAccount(anchorProvider.connection, anchorProvider.keypair, 123720, openbookProgramId);
|
anchorProvider.connection,
|
||||||
let eventQueue = await createAccount(anchorProvider.connection, anchorProvider.keypair, 97688, openbookProgramId);
|
anchorProvider.keypair,
|
||||||
let marketIndex : BN = new BN(index);
|
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 baseVault = await mintUtils.createTokenAccount(
|
||||||
let quoteVault = await mintUtils.createTokenAccount(quoteMint, anchorProvider.keypair, marketPk);
|
baseMint,
|
||||||
let name = 'index ' + index.toString() + ' wrt 0';
|
anchorProvider.keypair,
|
||||||
|
marketPk
|
||||||
|
);
|
||||||
|
let quoteVault = await mintUtils.createTokenAccount(
|
||||||
|
quoteMint,
|
||||||
|
anchorProvider.keypair,
|
||||||
|
marketPk
|
||||||
|
);
|
||||||
|
let name = "index " + index.toString() + " wrt 0";
|
||||||
|
|
||||||
await program.methods.createMarket(
|
await program.methods
|
||||||
marketIndex,
|
.createMarket(
|
||||||
name,
|
marketIndex,
|
||||||
{
|
name,
|
||||||
confFilter: 0,
|
{
|
||||||
maxStalenessSlots: 100,
|
confFilter: 0,
|
||||||
},
|
maxStalenessSlots: 100,
|
||||||
new BN(1), new BN(1), 0, 0, 0
|
},
|
||||||
).accounts(
|
new BN(1),
|
||||||
{
|
new BN(1),
|
||||||
admin,
|
0,
|
||||||
market: marketPk,
|
0,
|
||||||
bids,
|
0
|
||||||
asks,
|
)
|
||||||
eventQueue,
|
.accounts({
|
||||||
payer: anchorProvider.publicKey,
|
admin,
|
||||||
baseVault,
|
market: marketPk,
|
||||||
quoteVault,
|
bids,
|
||||||
baseMint,
|
asks,
|
||||||
quoteMint,
|
eventQueue,
|
||||||
systemProgram: web3.SystemProgram.programId,
|
payer: anchorProvider.publicKey,
|
||||||
oracle: oracleId,
|
baseVault,
|
||||||
}
|
quoteVault,
|
||||||
).signers([adminKp])
|
baseMint,
|
||||||
|
quoteMint,
|
||||||
|
systemProgram: web3.SystemProgram.programId,
|
||||||
|
oracle: oracleId,
|
||||||
|
})
|
||||||
|
.signers([adminKp])
|
||||||
.rpc();
|
.rpc();
|
||||||
|
|
||||||
return {
|
return {
|
||||||
admin: Array.from(adminKp.secretKey),
|
admin: Array.from(adminKp.secretKey),
|
||||||
name,
|
name,
|
||||||
bids,
|
bids,
|
||||||
asks,
|
asks,
|
||||||
event_queue: eventQueue,
|
event_queue: eventQueue,
|
||||||
base_mint: baseMint,
|
base_mint: baseMint,
|
||||||
base_vault: baseVault,
|
base_vault: baseVault,
|
||||||
market_index: index,
|
market_index: index,
|
||||||
market_pk: marketPk,
|
market_pk: marketPk,
|
||||||
oracle: oracleId,
|
oracle: oracleId,
|
||||||
quote_mint: quoteMint,
|
quote_mint: quoteMint,
|
||||||
quote_vault: quoteVault,
|
quote_vault: quoteVault,
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -3,21 +3,21 @@ import { Market } from "./openbook-v2/create_markets";
|
||||||
import { User } from "./general/create_users";
|
import { User } from "./general/create_users";
|
||||||
|
|
||||||
export interface Command {
|
export interface Command {
|
||||||
name: String,
|
name: String;
|
||||||
instruction: number[],
|
instruction: number[];
|
||||||
argument_sizes: number[],
|
argument_sizes: number[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ProgramOutputData {
|
export interface ProgramOutputData {
|
||||||
name: String,
|
name: String;
|
||||||
program_id: PublicKey,
|
program_id: PublicKey;
|
||||||
commands: Command [],
|
commands: Command[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface OutputFile {
|
export interface OutputFile {
|
||||||
users: User[],
|
users: User[];
|
||||||
programs: ProgramOutputData[],
|
programs: ProgramOutputData[];
|
||||||
known_accounts: PublicKey[],
|
known_accounts: PublicKey[];
|
||||||
mints: PublicKey[],
|
mints: PublicKey[];
|
||||||
markets: Market[],
|
markets: Market[];
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
"name": "pyth_mock",
|
"name": "pyth_mock",
|
||||||
"programPath": "programs/pyth_mock.so",
|
"programPath": "configure/programs/pyth_mock.so",
|
||||||
"programKeyPath": "programs/pyth_mock.json",
|
"programKeyPath": "configure/programs/pyth_mock.json",
|
||||||
"idl": ""
|
"idl": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "openbook_v2",
|
"name": "openbook_v2",
|
||||||
"programPath": "programs/openbook_v2.so",
|
"programPath": "configure/programs/openbook_v2.so",
|
||||||
"programKeyPath": "programs/openbook_v2-keypair.json",
|
"programKeyPath": "configure/programs/openbook_v2-keypair.json",
|
||||||
"idl": "programs/openbook_v2.json"
|
"idl": ""
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
@ -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
|
||||||
|
]
|
||||||
|
|
|
@ -640,9 +640,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "cancelAllOrders",
|
"name": "cancelAllOrders",
|
||||||
"docs": [
|
"docs": ["Cancel up to `limit` orders."],
|
||||||
"Cancel up to `limit` orders."
|
|
||||||
],
|
|
||||||
"accounts": [
|
"accounts": [
|
||||||
{
|
{
|
||||||
"name": "openOrdersAccount",
|
"name": "openOrdersAccount",
|
||||||
|
@ -679,9 +677,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "cancelAllOrdersBySide",
|
"name": "cancelAllOrdersBySide",
|
||||||
"docs": [
|
"docs": ["Cancel up to `limit` orders on a single side of the book."],
|
||||||
"Cancel up to `limit` orders on a single side of the book."
|
|
||||||
],
|
|
||||||
"accounts": [
|
"accounts": [
|
||||||
{
|
{
|
||||||
"name": "openOrdersAccount",
|
"name": "openOrdersAccount",
|
||||||
|
@ -793,9 +789,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "settleFunds",
|
"name": "settleFunds",
|
||||||
"docs": [
|
"docs": ["Withdraw any available tokens."],
|
||||||
"Withdraw any available tokens."
|
|
||||||
],
|
|
||||||
"accounts": [
|
"accounts": [
|
||||||
{
|
{
|
||||||
"name": "openOrdersAccount",
|
"name": "openOrdersAccount",
|
||||||
|
@ -842,9 +836,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "sweepFees",
|
"name": "sweepFees",
|
||||||
"docs": [
|
"docs": ["Sweep fees, as a [`Market`](crate::state::Market)'s admin."],
|
||||||
"Sweep fees, as a [`Market`](crate::state::Market)'s admin."
|
|
||||||
],
|
|
||||||
"accounts": [
|
"accounts": [
|
||||||
{
|
{
|
||||||
"name": "market",
|
"name": "market",
|
||||||
|
@ -876,9 +868,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "closeMarket",
|
"name": "closeMarket",
|
||||||
"docs": [
|
"docs": ["Close a [`Market`](crate::state::Market)."],
|
||||||
"Close a [`Market`](crate::state::Market)."
|
|
||||||
],
|
|
||||||
"accounts": [
|
"accounts": [
|
||||||
{
|
{
|
||||||
"name": "admin",
|
"name": "admin",
|
||||||
|
@ -1014,23 +1004,17 @@
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
"name": "admin",
|
"name": "admin",
|
||||||
"docs": [
|
"docs": ["Admin who can close this market"],
|
||||||
"Admin who can close this market"
|
|
||||||
],
|
|
||||||
"type": "publicKey"
|
"type": "publicKey"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "marketIndex",
|
"name": "marketIndex",
|
||||||
"docs": [
|
"docs": ["Index of this market"],
|
||||||
"Index of this market"
|
|
||||||
],
|
|
||||||
"type": "u32"
|
"type": "u32"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "bump",
|
"name": "bump",
|
||||||
"docs": [
|
"docs": ["PDA bump"],
|
||||||
"PDA bump"
|
|
||||||
],
|
|
||||||
"type": "u8"
|
"type": "u8"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -1049,57 +1033,39 @@
|
||||||
{
|
{
|
||||||
"name": "padding1",
|
"name": "padding1",
|
||||||
"type": {
|
"type": {
|
||||||
"array": [
|
"array": ["u8", 1]
|
||||||
"u8",
|
|
||||||
1
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "name",
|
"name": "name",
|
||||||
"docs": [
|
"docs": ["Name. Trailing zero bytes are ignored."],
|
||||||
"Name. Trailing zero bytes are ignored."
|
|
||||||
],
|
|
||||||
"type": {
|
"type": {
|
||||||
"array": [
|
"array": ["u8", 16]
|
||||||
"u8",
|
|
||||||
16
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "bids",
|
"name": "bids",
|
||||||
"docs": [
|
"docs": ["Address of the BookSide account for bids"],
|
||||||
"Address of the BookSide account for bids"
|
|
||||||
],
|
|
||||||
"type": "publicKey"
|
"type": "publicKey"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "asks",
|
"name": "asks",
|
||||||
"docs": [
|
"docs": ["Address of the BookSide account for asks"],
|
||||||
"Address of the BookSide account for asks"
|
|
||||||
],
|
|
||||||
"type": "publicKey"
|
"type": "publicKey"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "eventQueue",
|
"name": "eventQueue",
|
||||||
"docs": [
|
"docs": ["Address of the EventQueue account"],
|
||||||
"Address of the EventQueue account"
|
|
||||||
],
|
|
||||||
"type": "publicKey"
|
"type": "publicKey"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "oracle",
|
"name": "oracle",
|
||||||
"docs": [
|
"docs": ["Oracle account address"],
|
||||||
"Oracle account address"
|
|
||||||
],
|
|
||||||
"type": "publicKey"
|
"type": "publicKey"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "oracleConfig",
|
"name": "oracleConfig",
|
||||||
"docs": [
|
"docs": ["Oracle configuration"],
|
||||||
"Oracle configuration"
|
|
||||||
],
|
|
||||||
"type": {
|
"type": {
|
||||||
"defined": "OracleConfig"
|
"defined": "OracleConfig"
|
||||||
}
|
}
|
||||||
|
@ -1137,16 +1103,12 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "seqNum",
|
"name": "seqNum",
|
||||||
"docs": [
|
"docs": ["Total number of orders seen"],
|
||||||
"Total number of orders seen"
|
|
||||||
],
|
|
||||||
"type": "u64"
|
"type": "u64"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "registrationTime",
|
"name": "registrationTime",
|
||||||
"docs": [
|
"docs": ["Timestamp in seconds that the market was registered at."],
|
||||||
"Timestamp in seconds that the market was registered at."
|
|
||||||
],
|
|
||||||
"type": "u64"
|
"type": "u64"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -1161,45 +1123,34 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "takerFee",
|
"name": "takerFee",
|
||||||
"docs": [
|
"docs": ["Fee for taker orders, may not be negative."],
|
||||||
"Fee for taker orders, may not be negative."
|
|
||||||
],
|
|
||||||
"type": {
|
"type": {
|
||||||
"defined": "I80F48"
|
"defined": "I80F48"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "feesAccrued",
|
"name": "feesAccrued",
|
||||||
"docs": [
|
"docs": ["Fees accrued in native quote currency"],
|
||||||
"Fees accrued in native quote currency"
|
|
||||||
],
|
|
||||||
"type": {
|
"type": {
|
||||||
"defined": "I80F48"
|
"defined": "I80F48"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "feesSettled",
|
"name": "feesSettled",
|
||||||
"docs": [
|
"docs": ["Fees settled in native quote currency"],
|
||||||
"Fees settled in native quote currency"
|
|
||||||
],
|
|
||||||
"type": {
|
"type": {
|
||||||
"defined": "I80F48"
|
"defined": "I80F48"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "feePenalty",
|
"name": "feePenalty",
|
||||||
"docs": [
|
"docs": ["Fee (in quote native) to charge for ioc orders"],
|
||||||
"Fee (in quote native) to charge for ioc orders"
|
|
||||||
],
|
|
||||||
"type": "f32"
|
"type": "f32"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "padding2",
|
"name": "padding2",
|
||||||
"type": {
|
"type": {
|
||||||
"array": [
|
"array": ["u8", 4]
|
||||||
"u8",
|
|
||||||
4
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -1249,10 +1200,7 @@
|
||||||
{
|
{
|
||||||
"name": "reserved",
|
"name": "reserved",
|
||||||
"type": {
|
"type": {
|
||||||
"array": [
|
"array": ["u8", 1888]
|
||||||
"u8",
|
|
||||||
1888
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -1270,10 +1218,7 @@
|
||||||
{
|
{
|
||||||
"name": "name",
|
"name": "name",
|
||||||
"type": {
|
"type": {
|
||||||
"array": [
|
"array": ["u8", 32]
|
||||||
"u8",
|
|
||||||
32
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -1291,10 +1236,7 @@
|
||||||
{
|
{
|
||||||
"name": "padding",
|
"name": "padding",
|
||||||
"type": {
|
"type": {
|
||||||
"array": [
|
"array": ["u8", 3]
|
||||||
"u8",
|
|
||||||
3
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -1307,9 +1249,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "buybackFeesAccruedPrevious",
|
"name": "buybackFeesAccruedPrevious",
|
||||||
"docs": [
|
"docs": ["Fees buyback amount from the previous expiry interval."],
|
||||||
"Fees buyback amount from the previous expiry interval."
|
|
||||||
],
|
|
||||||
"type": "u64"
|
"type": "u64"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -1328,10 +1268,7 @@
|
||||||
{
|
{
|
||||||
"name": "reserved",
|
"name": "reserved",
|
||||||
"type": {
|
"type": {
|
||||||
"array": [
|
"array": ["u8", 208]
|
||||||
"u8",
|
|
||||||
208
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -1341,10 +1278,7 @@
|
||||||
{
|
{
|
||||||
"name": "padding3",
|
"name": "padding3",
|
||||||
"type": {
|
"type": {
|
||||||
"array": [
|
"array": ["u8", 7]
|
||||||
"u8",
|
|
||||||
7
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -1388,10 +1322,7 @@
|
||||||
{
|
{
|
||||||
"name": "reserved",
|
"name": "reserved",
|
||||||
"type": {
|
"type": {
|
||||||
"array": [
|
"array": ["u8", 128]
|
||||||
"u8",
|
|
||||||
128
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -1427,10 +1358,7 @@
|
||||||
{
|
{
|
||||||
"name": "reserved",
|
"name": "reserved",
|
||||||
"type": {
|
"type": {
|
||||||
"array": [
|
"array": ["u8", 256]
|
||||||
"u8",
|
|
||||||
256
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -1467,10 +1395,7 @@
|
||||||
{
|
{
|
||||||
"name": "reserved",
|
"name": "reserved",
|
||||||
"type": {
|
"type": {
|
||||||
"array": [
|
"array": ["u8", 64]
|
||||||
"u8",
|
|
||||||
64
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -1490,10 +1415,7 @@
|
||||||
{
|
{
|
||||||
"name": "name",
|
"name": "name",
|
||||||
"type": {
|
"type": {
|
||||||
"array": [
|
"array": ["u8", 32]
|
||||||
"u8",
|
|
||||||
32
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -1511,10 +1433,7 @@
|
||||||
{
|
{
|
||||||
"name": "padding",
|
"name": "padding",
|
||||||
"type": {
|
"type": {
|
||||||
"array": [
|
"array": ["u8", 3]
|
||||||
"u8",
|
|
||||||
3
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -1538,10 +1457,7 @@
|
||||||
{
|
{
|
||||||
"name": "reserved",
|
"name": "reserved",
|
||||||
"type": {
|
"type": {
|
||||||
"array": [
|
"array": ["u8", 208]
|
||||||
"u8",
|
|
||||||
208
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -1561,16 +1477,12 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "bidsBaseLots",
|
"name": "bidsBaseLots",
|
||||||
"docs": [
|
"docs": ["Base lots in open bids"],
|
||||||
"Base lots in open bids"
|
|
||||||
],
|
|
||||||
"type": "i64"
|
"type": "i64"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "asksBaseLots",
|
"name": "asksBaseLots",
|
||||||
"docs": [
|
"docs": ["Base lots in open asks"],
|
||||||
"Base lots in open asks"
|
|
||||||
],
|
|
||||||
"type": "i64"
|
"type": "i64"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -1618,10 +1530,7 @@
|
||||||
{
|
{
|
||||||
"name": "reserved",
|
"name": "reserved",
|
||||||
"type": {
|
"type": {
|
||||||
"array": [
|
"array": ["u8", 88]
|
||||||
"u8",
|
|
||||||
88
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -1639,10 +1548,7 @@
|
||||||
{
|
{
|
||||||
"name": "padding1",
|
"name": "padding1",
|
||||||
"type": {
|
"type": {
|
||||||
"array": [
|
"array": ["u8", 7]
|
||||||
"u8",
|
|
||||||
7
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -1660,10 +1566,7 @@
|
||||||
{
|
{
|
||||||
"name": "reserved",
|
"name": "reserved",
|
||||||
"type": {
|
"type": {
|
||||||
"array": [
|
"array": ["u8", 64]
|
||||||
"u8",
|
|
||||||
64
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -1687,10 +1590,7 @@
|
||||||
{
|
{
|
||||||
"name": "reserved",
|
"name": "reserved",
|
||||||
"type": {
|
"type": {
|
||||||
"array": [
|
"array": ["u8", 72]
|
||||||
"u8",
|
|
||||||
72
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -1733,10 +1633,7 @@
|
||||||
{
|
{
|
||||||
"name": "padding",
|
"name": "padding",
|
||||||
"type": {
|
"type": {
|
||||||
"array": [
|
"array": ["u8", 3]
|
||||||
"u8",
|
|
||||||
3
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -1749,21 +1646,14 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "key",
|
"name": "key",
|
||||||
"docs": [
|
"docs": ["only the top `prefix_len` bits of `key` are relevant"],
|
||||||
"only the top `prefix_len` bits of `key` are relevant"
|
|
||||||
],
|
|
||||||
"type": "u128"
|
"type": "u128"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "children",
|
"name": "children",
|
||||||
"docs": [
|
"docs": ["indexes into `BookSide::nodes`"],
|
||||||
"indexes into `BookSide::nodes`"
|
|
||||||
],
|
|
||||||
"type": {
|
"type": {
|
||||||
"array": [
|
"array": ["u32", 2]
|
||||||
"u32",
|
|
||||||
2
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -1775,19 +1665,13 @@
|
||||||
"iterate through the whole bookside."
|
"iterate through the whole bookside."
|
||||||
],
|
],
|
||||||
"type": {
|
"type": {
|
||||||
"array": [
|
"array": ["u64", 2]
|
||||||
"u64",
|
|
||||||
2
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "reserved",
|
"name": "reserved",
|
||||||
"type": {
|
"type": {
|
||||||
"array": [
|
"array": ["u8", 72]
|
||||||
"u8",
|
|
||||||
72
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -1795,24 +1679,18 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "LeafNode",
|
"name": "LeafNode",
|
||||||
"docs": [
|
"docs": ["LeafNodes represent an order in the binary tree"],
|
||||||
"LeafNodes represent an order in the binary tree"
|
|
||||||
],
|
|
||||||
"type": {
|
"type": {
|
||||||
"kind": "struct",
|
"kind": "struct",
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
"name": "tag",
|
"name": "tag",
|
||||||
"docs": [
|
"docs": ["NodeTag"],
|
||||||
"NodeTag"
|
|
||||||
],
|
|
||||||
"type": "u8"
|
"type": "u8"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "ownerSlot",
|
"name": "ownerSlot",
|
||||||
"docs": [
|
"docs": ["Index into the owning OpenOrdersAccount's OpenOrders"],
|
||||||
"Index into the owning OpenOrdersAccount's OpenOrders"
|
|
||||||
],
|
|
||||||
"type": "u8"
|
"type": "u8"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -1825,10 +1703,7 @@
|
||||||
{
|
{
|
||||||
"name": "padding",
|
"name": "padding",
|
||||||
"type": {
|
"type": {
|
||||||
"array": [
|
"array": ["u8", 1]
|
||||||
"u8",
|
|
||||||
1
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -1842,38 +1717,27 @@
|
||||||
{
|
{
|
||||||
"name": "padding2",
|
"name": "padding2",
|
||||||
"type": {
|
"type": {
|
||||||
"array": [
|
"array": ["u8", 2]
|
||||||
"u8",
|
|
||||||
2
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "key",
|
"name": "key",
|
||||||
"docs": [
|
"docs": ["The binary tree key, see new_node_key()"],
|
||||||
"The binary tree key, see new_node_key()"
|
|
||||||
],
|
|
||||||
"type": "u128"
|
"type": "u128"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "owner",
|
"name": "owner",
|
||||||
"docs": [
|
"docs": ["Address of the owning OpenOrdersAccount"],
|
||||||
"Address of the owning OpenOrdersAccount"
|
|
||||||
],
|
|
||||||
"type": "publicKey"
|
"type": "publicKey"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "quantity",
|
"name": "quantity",
|
||||||
"docs": [
|
"docs": ["Number of base lots to buy or sell, always >=1"],
|
||||||
"Number of base lots to buy or sell, always >=1"
|
|
||||||
],
|
|
||||||
"type": "i64"
|
"type": "i64"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "timestamp",
|
"name": "timestamp",
|
||||||
"docs": [
|
"docs": ["The time the order was placed"],
|
||||||
"The time the order was placed"
|
|
||||||
],
|
|
||||||
"type": "u64"
|
"type": "u64"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -1888,18 +1752,13 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "clientOrderId",
|
"name": "clientOrderId",
|
||||||
"docs": [
|
"docs": ["User defined id for this order, used in FillEvents"],
|
||||||
"User defined id for this order, used in FillEvents"
|
|
||||||
],
|
|
||||||
"type": "u64"
|
"type": "u64"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "reserved",
|
"name": "reserved",
|
||||||
"type": {
|
"type": {
|
||||||
"array": [
|
"array": ["u8", 32]
|
||||||
"u8",
|
|
||||||
32
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -1917,10 +1776,7 @@
|
||||||
{
|
{
|
||||||
"name": "data",
|
"name": "data",
|
||||||
"type": {
|
"type": {
|
||||||
"array": [
|
"array": ["u8", 119]
|
||||||
"u8",
|
|
||||||
119
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -1959,10 +1815,7 @@
|
||||||
{
|
{
|
||||||
"name": "padding",
|
"name": "padding",
|
||||||
"type": {
|
"type": {
|
||||||
"array": [
|
"array": ["u8", 3]
|
||||||
"u8",
|
|
||||||
3
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -1980,10 +1833,7 @@
|
||||||
{
|
{
|
||||||
"name": "reserved",
|
"name": "reserved",
|
||||||
"type": {
|
"type": {
|
||||||
"array": [
|
"array": ["u8", 512]
|
||||||
"u8",
|
|
||||||
512
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -2032,10 +1882,7 @@
|
||||||
{
|
{
|
||||||
"name": "padding",
|
"name": "padding",
|
||||||
"type": {
|
"type": {
|
||||||
"array": [
|
"array": ["u8", 199]
|
||||||
"u8",
|
|
||||||
199
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -2065,10 +1912,7 @@
|
||||||
{
|
{
|
||||||
"name": "padding",
|
"name": "padding",
|
||||||
"type": {
|
"type": {
|
||||||
"array": [
|
"array": ["u8", 4]
|
||||||
"u8",
|
|
||||||
4
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -2086,10 +1930,7 @@
|
||||||
{
|
{
|
||||||
"name": "padding2",
|
"name": "padding2",
|
||||||
"type": {
|
"type": {
|
||||||
"array": [
|
"array": ["u8", 32]
|
||||||
"u8",
|
|
||||||
32
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -2103,10 +1944,7 @@
|
||||||
{
|
{
|
||||||
"name": "padding3",
|
"name": "padding3",
|
||||||
"type": {
|
"type": {
|
||||||
"array": [
|
"array": ["u8", 16]
|
||||||
"u8",
|
|
||||||
16
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -2116,10 +1954,7 @@
|
||||||
{
|
{
|
||||||
"name": "padding4",
|
"name": "padding4",
|
||||||
"type": {
|
"type": {
|
||||||
"array": [
|
"array": ["u8", 16]
|
||||||
"u8",
|
|
||||||
16
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -2137,10 +1972,7 @@
|
||||||
{
|
{
|
||||||
"name": "reserved",
|
"name": "reserved",
|
||||||
"type": {
|
"type": {
|
||||||
"array": [
|
"array": ["u8", 8]
|
||||||
"u8",
|
|
||||||
8
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -2166,10 +1998,7 @@
|
||||||
{
|
{
|
||||||
"name": "padding0",
|
"name": "padding0",
|
||||||
"type": {
|
"type": {
|
||||||
"array": [
|
"array": ["u8", 5]
|
||||||
"u8",
|
|
||||||
5
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -2191,10 +2020,7 @@
|
||||||
{
|
{
|
||||||
"name": "padding1",
|
"name": "padding1",
|
||||||
"type": {
|
"type": {
|
||||||
"array": [
|
"array": ["u8", 136]
|
||||||
"u8",
|
|
||||||
136
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -2220,9 +2046,7 @@
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
"name": "stablePrice",
|
"name": "stablePrice",
|
||||||
"docs": [
|
"docs": ["Current stable price to use in health"],
|
||||||
"Current stable price to use in health"
|
|
||||||
],
|
|
||||||
"type": "f64"
|
"type": "f64"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -2239,10 +2063,7 @@
|
||||||
"we use the next one."
|
"we use the next one."
|
||||||
],
|
],
|
||||||
"type": {
|
"type": {
|
||||||
"array": [
|
"array": ["f64", 24]
|
||||||
"f64",
|
|
||||||
24
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -2255,16 +2076,12 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "delayAccumulatorTime",
|
"name": "delayAccumulatorTime",
|
||||||
"docs": [
|
"docs": ["Accumulating the total time for the above average."],
|
||||||
"Accumulating the total time for the above average."
|
|
||||||
],
|
|
||||||
"type": "u32"
|
"type": "u32"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "delayIntervalSeconds",
|
"name": "delayIntervalSeconds",
|
||||||
"docs": [
|
"docs": ["Length of a delay_interval"],
|
||||||
"Length of a delay_interval"
|
|
||||||
],
|
|
||||||
"type": "u32"
|
"type": "u32"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -2292,19 +2109,13 @@
|
||||||
{
|
{
|
||||||
"name": "padding",
|
"name": "padding",
|
||||||
"type": {
|
"type": {
|
||||||
"array": [
|
"array": ["u8", 7]
|
||||||
"u8",
|
|
||||||
7
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "reserved",
|
"name": "reserved",
|
||||||
"type": {
|
"type": {
|
||||||
"array": [
|
"array": ["u8", 48]
|
||||||
"u8",
|
|
||||||
48
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -2925,4 +2736,4 @@
|
||||||
"msg": "The receiver is invalid. Makes sure the receiver's owner is the market admin"
|
"msg": "The receiver is invalid. Makes sure the receiver's owner is the market admin"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
]
|
||||||
|
|
|
@ -4,6 +4,9 @@
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"repository": "https://github.com/blockworks-foundation/solana-rpc-testing.git",
|
"repository": "https://github.com/blockworks-foundation/solana-rpc-testing.git",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"scripts": {
|
||||||
|
"configure": "ts-node configure/main.ts"
|
||||||
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "^20.1.0",
|
"@types/node": "^20.1.0",
|
||||||
"ts-node": "^10.9.1",
|
"ts-node": "^10.9.1",
|
||||||
|
|
Loading…
Reference in New Issue