docs
Signed-off-by: microwavedcola1 <microwavedcola@gmail.com>
This commit is contained in:
parent
b39662b804
commit
e5ed7936eb
33
README.md
33
README.md
|
@ -8,33 +8,6 @@
|
||||||
|
|
||||||
Devnet deployment - m43thNJ58XCjL798ZSq6JGAG1BnWskhdq5or6kcnfsD
|
Devnet deployment - m43thNJ58XCjL798ZSq6JGAG1BnWskhdq5or6kcnfsD
|
||||||
|
|
||||||
TS client - see ts dir, and ts/example.ts, run as `yarn ts-node ts/example.ts`
|
TS client based examples (for details check respective scripts)
|
||||||
|
(cd ts/client && yarn example1-admin) - create a devnet group
|
||||||
### Module structure
|
(cd ts/client && yarn example1-user) - run through some mangoaccount operations for a user on devnet
|
||||||
|
|
||||||
As and when we move to a more complete project, we should think of having multiple modules
|
|
||||||
e.g. core/shared, spot, perpetuals, etc., and then each would have its own instructions
|
|
||||||
and state sub module. Goal is that new contributors find relevant code easily and can navigate
|
|
||||||
easily.
|
|
||||||
|
|
||||||
```
|
|
||||||
programs
|
|
||||||
└── mango-v4
|
|
||||||
├── Cargo.toml
|
|
||||||
├── Xargo.toml
|
|
||||||
└── src
|
|
||||||
│ ├── error.rs
|
|
||||||
│ ├── instructions # instructions go here, each instruction gets an individual file
|
|
||||||
│ │ ├── initialiaze.rs
|
|
||||||
│ │ └── mod.rs
|
|
||||||
│ ├── lib.rs
|
|
||||||
│ └── state # state goes here, each account state gets an individual file
|
|
||||||
│ └── mod.rs
|
|
||||||
└── tests # rust tests, TODO
|
|
||||||
```
|
|
||||||
|
|
||||||
### How to open and manage pull requests
|
|
||||||
|
|
||||||
- when in doubt dont squash commits, specially when merge request is very large, specially if your branch contains unrelated commits
|
|
||||||
- use the why along with what for commit messages, code comments, makes it easy to understand the context
|
|
||||||
- add descriptions to your merge requests if they are non trivial, helps code reviewer watch out for things, understand the motivation for the merge request
|
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
See example1-user.ts and example1-admin.ts
|
|
|
@ -8,8 +8,8 @@
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "tsc",
|
"build": "tsc",
|
||||||
"clean": "rm -rf dist",
|
"clean": "rm -rf dist",
|
||||||
"example1-user": "ts-node src/example1-user.ts",
|
"example1-user": "ts-node src/scripts/example1-user.ts",
|
||||||
"example1-admin": "ts-node src/example1-admin.ts",
|
"example1-admin": "ts-node src/scripts/example1-admin.ts",
|
||||||
"format": "prettier --check .",
|
"format": "prettier --check .",
|
||||||
"lint": "eslint . --ext ts --ext tsx --ext js --quiet",
|
"lint": "eslint . --ext ts --ext tsx --ext js --quiet",
|
||||||
"type-check": "tsc --pretty --noEmit"
|
"type-check": "tsc --pretty --noEmit"
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import { Provider, Wallet } from '@project-serum/anchor';
|
import { Provider, Wallet } from '@project-serum/anchor';
|
||||||
import { Connection, Keypair, PublicKey } from '@solana/web3.js';
|
import { Connection, Keypair, PublicKey } from '@solana/web3.js';
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
import { MangoClient } from './client';
|
import { MangoClient } from '../client';
|
||||||
import { DEVNET_SERUM3_PROGRAM_ID } from './constants';
|
import { DEVNET_SERUM3_PROGRAM_ID } from '../constants';
|
||||||
|
|
||||||
const DEVNET_SERUM3_MARKETS = new Map([
|
const DEVNET_SERUM3_MARKETS = new Map([
|
||||||
['BTC/USDC', 'DW83EpHFywBxCHmyARxwj3nzxJd7MUdSeznmrdzZKNZB'],
|
['BTC/USDC', 'DW83EpHFywBxCHmyARxwj3nzxJd7MUdSeznmrdzZKNZB'],
|
||||||
|
@ -17,6 +17,12 @@ const DEVNET_ORACLES = new Map([
|
||||||
|
|
||||||
//
|
//
|
||||||
// An example for admins based on high level api i.e. the client
|
// An example for admins based on high level api i.e. the client
|
||||||
|
// Depoys a new mango group to devnet, registers 2 tokens, and 1 serum3 spot market
|
||||||
|
//
|
||||||
|
// process.env.ADMIN_KEYPAIR - group admin keypair path
|
||||||
|
// to create a new admin keypair:
|
||||||
|
// * solana-keygen new --outfile ~/.config/solana/admin.json
|
||||||
|
// * solana airdrop 1 -k ~/.config/solana/admin.json
|
||||||
//
|
//
|
||||||
async function main() {
|
async function main() {
|
||||||
const options = Provider.defaultOptions();
|
const options = Provider.defaultOptions();
|
||||||
|
@ -36,15 +42,15 @@ async function main() {
|
||||||
const client = await MangoClient.connect(adminProvider, true);
|
const client = await MangoClient.connect(adminProvider, true);
|
||||||
|
|
||||||
// group
|
// group
|
||||||
console.log(`Group...`);
|
console.log(`Creating Group...`);
|
||||||
try {
|
try {
|
||||||
await client.createGroup();
|
await client.createGroup();
|
||||||
} catch (error) {}
|
} catch (error) {}
|
||||||
const group = await client.getGroupForAdmin(admin.publicKey);
|
const group = await client.getGroupForAdmin(admin.publicKey);
|
||||||
console.log(`Group ${group.publicKey}`);
|
console.log(`...registered group ${group.publicKey}`);
|
||||||
|
|
||||||
// register token 0
|
// register token 0
|
||||||
console.log(`Token 0...`);
|
console.log(`Registering BTC...`);
|
||||||
const btcDevnetMint = new PublicKey(DEVNET_MINTS.get('BTC')!);
|
const btcDevnetMint = new PublicKey(DEVNET_MINTS.get('BTC')!);
|
||||||
const btcDevnetOracle = new PublicKey(DEVNET_ORACLES.get('BTC')!);
|
const btcDevnetOracle = new PublicKey(DEVNET_ORACLES.get('BTC')!);
|
||||||
try {
|
try {
|
||||||
|
@ -69,7 +75,7 @@ async function main() {
|
||||||
} catch (error) {}
|
} catch (error) {}
|
||||||
|
|
||||||
// stub oracle + register token 1
|
// stub oracle + register token 1
|
||||||
console.log(`Token 1...`);
|
console.log(`Registering USDC...`);
|
||||||
const usdcDevnetMint = new PublicKey(DEVNET_MINTS.get('USDC')!);
|
const usdcDevnetMint = new PublicKey(DEVNET_MINTS.get('USDC')!);
|
||||||
try {
|
try {
|
||||||
await client.createStubOracle(group, usdcDevnetMint, 1.0);
|
await client.createStubOracle(group, usdcDevnetMint, 1.0);
|
||||||
|
@ -99,12 +105,12 @@ async function main() {
|
||||||
// log tokens/banks
|
// log tokens/banks
|
||||||
for (const bank of await group.banksMap.values()) {
|
for (const bank of await group.banksMap.values()) {
|
||||||
console.log(
|
console.log(
|
||||||
`Bank ${bank.tokenIndex} ${bank.publicKey}, mint ${bank.mint}, oracle ${bank.oracle}`,
|
`...registered Bank ${bank.tokenIndex} ${bank.publicKey}, mint ${bank.mint}, oracle ${bank.oracle}`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// register serum market
|
// register serum market
|
||||||
console.log(`Serum3 market...`);
|
console.log(`Registering serum3 market...`);
|
||||||
const serumMarketExternalPk = new PublicKey(
|
const serumMarketExternalPk = new PublicKey(
|
||||||
DEVNET_SERUM3_MARKETS.get('BTC/USDC')!,
|
DEVNET_SERUM3_MARKETS.get('BTC/USDC')!,
|
||||||
);
|
);
|
||||||
|
@ -124,7 +130,7 @@ async function main() {
|
||||||
group.banksMap.get('BTC')?.tokenIndex,
|
group.banksMap.get('BTC')?.tokenIndex,
|
||||||
group.banksMap.get('USDC')?.tokenIndex,
|
group.banksMap.get('USDC')?.tokenIndex,
|
||||||
);
|
);
|
||||||
console.log(`Serum3 market ${markets[0].publicKey}`);
|
console.log(`...registerd serum3 market ${markets[0].publicKey}`);
|
||||||
|
|
||||||
process.exit();
|
process.exit();
|
||||||
}
|
}
|
|
@ -5,12 +5,15 @@ import {
|
||||||
Serum3OrderType,
|
Serum3OrderType,
|
||||||
Serum3SelfTradeBehavior,
|
Serum3SelfTradeBehavior,
|
||||||
Serum3Side,
|
Serum3Side,
|
||||||
} from './accounts/serum3';
|
} from '../accounts/serum3';
|
||||||
import { MangoClient } from './client';
|
import { MangoClient } from '../client';
|
||||||
import { DEVNET_SERUM3_PROGRAM_ID } from './constants';
|
import { DEVNET_SERUM3_PROGRAM_ID } from '../constants';
|
||||||
|
|
||||||
//
|
//
|
||||||
// An example for users based on high level api i.e. the client
|
// An example for users based on high level api i.e. the client
|
||||||
|
// Create
|
||||||
|
// process.env.USER_KEYPAIR - mango account owner keypair path
|
||||||
|
// process.env.ADMIN_KEYPAIR - group admin keypair path (useful for automatically finding the group)
|
||||||
//
|
//
|
||||||
async function main() {
|
async function main() {
|
||||||
const options = Provider.defaultOptions();
|
const options = Provider.defaultOptions();
|
||||||
|
@ -36,16 +39,17 @@ async function main() {
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
const group = await client.getGroupForAdmin(admin.publicKey);
|
const group = await client.getGroupForAdmin(admin.publicKey);
|
||||||
console.log(`Group ${group.publicKey.toBase58()}`);
|
console.log(`Found group ${group.publicKey.toBase58()}`);
|
||||||
|
|
||||||
// create + fetch account
|
// create + fetch account
|
||||||
|
console.log(`Creating mangoaccount...`);
|
||||||
const mangoAccount = await client.getOrCreateMangoAccount(
|
const mangoAccount = await client.getOrCreateMangoAccount(
|
||||||
group,
|
group,
|
||||||
user.publicKey,
|
user.publicKey,
|
||||||
0,
|
0,
|
||||||
'my_mango_account',
|
'my_mango_account',
|
||||||
);
|
);
|
||||||
console.log(`MangoAccount ${mangoAccount.publicKey}`);
|
console.log(`...created/found mangoAccount ${mangoAccount.publicKey}`);
|
||||||
|
|
||||||
// deposit and withdraw
|
// deposit and withdraw
|
||||||
console.log(`Depositing...5000000 USDC`);
|
console.log(`Depositing...5000000 USDC`);
|
||||||
|
@ -56,13 +60,13 @@ async function main() {
|
||||||
await client.deposit(group, mangoAccount, 'BTC', 5000000);
|
await client.deposit(group, mangoAccount, 'BTC', 5000000);
|
||||||
await mangoAccount.reload(client);
|
await mangoAccount.reload(client);
|
||||||
|
|
||||||
console.log(`Withdrawing...1000000`);
|
console.log(`Withdrawing...1000000 USDC`);
|
||||||
await client.withdraw(group, mangoAccount, 'USDC', 1_000000, false);
|
await client.withdraw(group, mangoAccount, 'USDC', 1_000000, false);
|
||||||
await mangoAccount.reload(client);
|
await mangoAccount.reload(client);
|
||||||
|
|
||||||
// serum3
|
// serum3
|
||||||
console.log(
|
console.log(
|
||||||
`Placing serum3 bid which would not be settled since its relatively low then midprice`,
|
`Placing serum3 bid which would not be settled since its relatively low then midprice...`,
|
||||||
);
|
);
|
||||||
await client.serum3PlaceOrder(
|
await client.serum3PlaceOrder(
|
||||||
group,
|
group,
|
||||||
|
@ -79,7 +83,7 @@ async function main() {
|
||||||
);
|
);
|
||||||
await mangoAccount.reload(client);
|
await mangoAccount.reload(client);
|
||||||
|
|
||||||
console.log(`Placing serum3 bid way above midprice`);
|
console.log(`Placing serum3 bid way above midprice...`);
|
||||||
await client.serum3PlaceOrder(
|
await client.serum3PlaceOrder(
|
||||||
group,
|
group,
|
||||||
mangoAccount,
|
mangoAccount,
|
||||||
|
@ -95,7 +99,7 @@ async function main() {
|
||||||
);
|
);
|
||||||
await mangoAccount.reload(client);
|
await mangoAccount.reload(client);
|
||||||
|
|
||||||
console.log(`Placing serum3 ask way below midprice`);
|
console.log(`Placing serum3 ask way below midprice...`);
|
||||||
await client.serum3PlaceOrder(
|
await client.serum3PlaceOrder(
|
||||||
group,
|
group,
|
||||||
mangoAccount,
|
mangoAccount,
|
||||||
|
@ -118,9 +122,9 @@ async function main() {
|
||||||
);
|
);
|
||||||
for (const order of orders) {
|
for (const order of orders) {
|
||||||
console.log(
|
console.log(
|
||||||
`Order orderId ${order.orderId}, ${order.side}, ${order.price}, ${order.size}`,
|
` - Order orderId ${order.orderId}, ${order.side}, ${order.price}, ${order.size}`,
|
||||||
);
|
);
|
||||||
console.log(`Cancelling order with ${order.orderId}`);
|
console.log(` - Cancelling order with ${order.orderId}`);
|
||||||
await client.serum3CancelOrder(
|
await client.serum3CancelOrder(
|
||||||
group,
|
group,
|
||||||
mangoAccount,
|
mangoAccount,
|
||||||
|
@ -131,7 +135,7 @@ async function main() {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(`Current own orders on OB...`);
|
console.log(` - Current own orders on OB...`);
|
||||||
orders = await client.getSerum3Orders(
|
orders = await client.getSerum3Orders(
|
||||||
group,
|
group,
|
||||||
DEVNET_SERUM3_PROGRAM_ID,
|
DEVNET_SERUM3_PROGRAM_ID,
|
Loading…
Reference in New Issue