Signed-off-by: microwavedcola1 <microwavedcola@gmail.com>
This commit is contained in:
microwavedcola1 2022-06-11 13:49:45 +02:00
parent 4a257cd694
commit 7013d775b2
16 changed files with 4473 additions and 4261 deletions

34
ts/client/ids.json Normal file
View File

@ -0,0 +1,34 @@
{
"testnet": {},
"devnet": {
"m43thNJ58XCjL798ZSq6JGAG1BnWskhdq5or6kcnfsD": {
"8nBa69Ed8LCeP5YpZ1qB58DTEXq8fq7epfH5RsUVFATb": {
"banks": {
"USDC": "ChuTYko8TLHb8Xn72gAe7PQTS9ULvrTayjMzjRGSmUn8",
"SOL": "3V7vwKfQPhJn2bSywqsrvJwwCK9B5Dy3mE2SXCFxfW1N",
"ORCA": "fiHgPevezzWH3zWFsqnHdcA9Qeg6B15HfsDXGygBcqF",
"BTC": "HGw2wgfnytS3uEwPeyNijhoruA3K7msQaogkxC8EKdGX"
},
"stubOracles": {
"USDC": "DfbZP2mdLnHKWT5tVGb3MyaqEJpEfVQGi8LSP1gxgCeN"
},
"mintInfos": {
"ORCA": "GXW8pBd3wZx8QZCoxsTj4CT3qGfoSGED6SB2bKXonZAs",
"BTC": "6onpaK9yFJBcV5d6Vs8vUnWF5pKDBDCo3rq4E9gva6nh",
"USDC": "4gdSUfDBo5YibmanYL1N5uDdcBSdkpx75AwmUZWasFPW",
"SOL": "BEckAgpZQmSpcA2ncgb3LWfRHxnwG3WsNqpkaXQzAMA2"
},
"serum3Markets": {
"BTC/USDC": "AThBBA35mBxnUi3rT7YPVZKDnpZbi2ZsNSzJZkfJrFoA"
},
"serum3MarketExternals": {
"BTC/USDC": "DW83EpHFywBxCHmyARxwj3nzxJd7MUdSeznmrdzZKNZB"
},
"perpMarkets": {
"BTC/USDC": "D2cYz3LdYfzcpNcbx4TFr4P8C24XUzPtXPnyZSyhA8oa"
}
}
}
},
"mainnet": {}
}

View File

@ -126,13 +126,20 @@ export class MintInfo {
vault: PublicKey;
oracle: PublicKey;
addressLookupTable: PublicKey;
tokenIndex: Number;
tokenIndex: number;
addressLookupTableBankIndex: Number;
addressLookupTableOracleIndex: Number;
reserved: unknown;
},
) {
return new MintInfo(publicKey, obj.mint, obj.bank, obj.vault, obj.oracle);
return new MintInfo(
publicKey,
obj.mint,
obj.bank,
obj.vault,
obj.oracle,
obj.tokenIndex,
);
}
constructor(
@ -141,5 +148,6 @@ export class MintInfo {
public bank: PublicKey,
public vault: PublicKey,
public oracle: PublicKey,
public tokenIndex: number,
) {}
}

View File

@ -1,5 +1,8 @@
import { Market } from '@project-serum/serum';
import { PublicKey } from '@solana/web3.js';
import { MangoClient } from '../client';
import { MANGO_V4_ID, SERUM3_PROGRAM_ID } from '../constants';
import { Id } from '../ids';
import { Bank, MintInfo } from './bank';
import { PerpMarket } from './perp';
import { Serum3Market } from './serum3';
@ -17,6 +20,7 @@ export class Group {
new Map(),
new Map(),
new Map(),
new Map(),
);
}
@ -26,8 +30,9 @@ export class Group {
public groupNum: number,
public banksMap: Map<string, Bank>,
public serum3MarketsMap: Map<string, Serum3Market>,
public serum3MarketExternalsMap: Map<string, Market>,
public perpMarketsMap: Map<string, PerpMarket>,
public mintInfosMap: Map<string, MintInfo>,
public mintInfosMap: Map<number, MintInfo>,
) {}
public findBank(tokenIndex: number): Bank | undefined {
@ -36,43 +41,116 @@ export class Group {
);
}
public async reload(client: MangoClient) {
public async reloadAll(client: MangoClient) {
let ids: Id | undefined = undefined;
if (client.useIds) {
ids = Id.fromIds(
client.cluster,
MANGO_V4_ID[client.cluster],
this.publicKey,
);
}
// console.time('group.reload');
await Promise.all([
this.reloadBanks(client),
this.reloadMintInfos(client),
this.reloadSerum3Markets(client),
this.reloadPerpMarkets(client),
this.reloadBanks(client, ids),
this.reloadMintInfos(client, ids),
this.reloadSerum3Markets(client, ids).then,
this.reloadPerpMarkets(client, ids),
]);
// requires reloadSerum3Markets to have finished loading
await this.reloadSerum3ExternalMarkets(client, ids);
// console.timeEnd('group.reload');
}
public async reloadBanks(client: MangoClient) {
const banks = await client.getBanksForGroup(this);
public async reloadBanks(client: MangoClient, ids?: Id) {
let banks: Bank[];
if (ids) {
banks = (
await client.program.account.bank.fetchMultiple(ids.getBanks())
).map((account, index) =>
Bank.from(ids.getBanks()[index], account as any),
);
} else {
banks = await client.getBanksForGroup(this);
}
this.banksMap = new Map(banks.map((bank) => [bank.name, bank]));
}
public async reloadMintInfos(client: MangoClient) {
const mintInfos = await client.getMintInfosForGroup(this);
public async reloadMintInfos(client: MangoClient, ids?: Id) {
let mintInfos: MintInfo[];
if (ids) {
mintInfos = (
await client.program.account.mintInfo.fetchMultiple(ids.getMintInfos())
).map((account, index) =>
MintInfo.from(ids.getMintInfos()[index], account as any),
);
} else {
mintInfos = await client.getMintInfosForGroup(this);
}
this.mintInfosMap = new Map(
mintInfos.map((mintInfo) => {
return [
Array.from(this.banksMap.values()).find(
(bank) => bank.mint.toBase58() === mintInfo.mint.toBase58(),
)?.name!,
mintInfo,
];
return [mintInfo.tokenIndex, mintInfo];
}),
);
}
public async reloadSerum3Markets(client: MangoClient) {
const serum3Markets = await client.serum3GetMarket(this);
public async reloadSerum3Markets(client: MangoClient, ids?: Id) {
let serum3Markets: Serum3Market[];
if (ids) {
serum3Markets = (
await client.program.account.serum3Market.fetchMultiple(
ids.getSerum3Markets(),
)
).map((account, index) =>
Serum3Market.from(ids.getSerum3Markets()[index], account as any),
);
} else {
serum3Markets = await client.serum3GetMarkets(this);
}
this.serum3MarketsMap = new Map(
serum3Markets.map((serum3Market) => [serum3Market.name, serum3Market]),
);
}
public async reloadPerpMarkets(client: MangoClient) {
const perpMarkets = await client.perpGetMarket(this);
public async reloadSerum3ExternalMarkets(client: MangoClient, ids?: Id) {
const externalMarkets = await Promise.all(
Array.from(this.serum3MarketsMap.values()).map((serum3Market) =>
Market.load(
client.program.provider.connection,
serum3Market.serumMarketExternal,
{ commitment: client.program.provider.connection.commitment },
SERUM3_PROGRAM_ID[client.cluster],
),
),
);
this.serum3MarketExternalsMap = new Map(
Array.from(this.serum3MarketsMap.values()).map((serum3Market, index) => [
serum3Market.name,
externalMarkets[index],
]),
);
}
public async reloadPerpMarkets(client: MangoClient, ids?: Id) {
let perpMarkets: PerpMarket[];
if (ids) {
perpMarkets = (
await client.program.account.perpMarket.fetchMultiple(
ids.getPerpMarkets(),
)
).map((account, index) =>
PerpMarket.from(ids.getPerpMarkets()[index], account as any),
);
} else {
perpMarkets = await client.perpGetMarkets(this);
}
this.perpMarketsMap = new Map(
perpMarkets.map((perpMarket) => [perpMarket.name, perpMarket]),
);

View File

@ -2,7 +2,7 @@ import { ORCA_TOKEN_SWAP_ID_DEVNET } from '@orca-so/sdk';
import { orcaDevnetPoolConfigs } from '@orca-so/sdk/dist/constants/devnet/pools';
import { OrcaPoolConfig as OrcaDevnetPoolConfig } from '@orca-so/sdk/dist/public/devnet/pools';
import { AnchorProvider, BN, Program, Provider } from '@project-serum/anchor';
import { getFeeRates, getFeeTier, Market } from '@project-serum/serum';
import { getFeeRates, getFeeTier } from '@project-serum/serum';
import { Order } from '@project-serum/serum/lib/market';
import {
closeAccount,
@ -13,6 +13,7 @@ import { TOKEN_PROGRAM_ID } from '@solana/spl-token';
import { TokenSwap } from '@solana/spl-token-swap';
import {
AccountMeta,
Cluster,
Keypair,
LAMPORTS_PER_SOL,
MemcmpFilter,
@ -36,6 +37,7 @@ import {
Serum3SelfTradeBehavior,
Serum3Side,
} from './accounts/serum3';
import { SERUM3_PROGRAM_ID } from './constants';
import { IDL, MangoV4 } from './mango_v4';
import { MarginTradeWithdraw } from './types';
import {
@ -45,12 +47,13 @@ import {
toU64,
} from './utils';
export const MANGO_V4_ID = new PublicKey(
'm43thNJ58XCjL798ZSq6JGAG1BnWskhdq5or6kcnfsD',
);
export class MangoClient {
constructor(public program: Program<MangoV4>, public devnet?: boolean) {}
constructor(
public program: Program<MangoV4>,
public programId: PublicKey,
public cluster: Cluster,
public useIds: boolean,
) {}
/// public
@ -86,7 +89,7 @@ export class MangoClient {
public async getGroup(groupPk: PublicKey): Promise<Group> {
const groupAccount = await this.program.account.group.fetch(groupPk);
const group = Group.from(groupPk, groupAccount);
await group.reload(this);
await group.reloadAll(this);
return group;
}
@ -117,7 +120,7 @@ export class MangoClient {
const groups = (await this.program.account.group.all(filters)).map(
(tuple) => Group.from(tuple.publicKey, tuple.account),
);
await groups[0].reload(this);
await groups[0].reloadAll(this);
return groups[0];
}
@ -180,7 +183,7 @@ export class MangoClient {
admin: adminPk,
bank: bank.publicKey,
vault: bank.vault,
mintInfo: group.mintInfosMap.get(bank.name)?.publicKey,
mintInfo: group.mintInfosMap.get(bank.tokenIndex)?.publicKey,
solDestination: (this.program.provider as AnchorProvider).wallet
.publicKey,
})
@ -292,25 +295,29 @@ export class MangoClient {
public async getStubOracle(
group: Group,
mintPk: PublicKey,
): Promise<StubOracle> {
const stubOracles = (
await this.program.account.stubOracle.all([
{
memcmp: {
bytes: group.publicKey.toBase58(),
offset: 8,
},
mintPk?: PublicKey,
): Promise<StubOracle[]> {
const filters = [
{
memcmp: {
bytes: group.publicKey.toBase58(),
offset: 8,
},
{
memcmp: {
bytes: mintPk.toBase58(),
offset: 40,
},
},
];
if (mintPk) {
filters.push({
memcmp: {
bytes: mintPk.toBase58(),
offset: 40,
},
])
).map((pa) => StubOracle.from(pa.publicKey, pa.account));
return stubOracles[0];
});
}
return (await this.program.account.stubOracle.all(filters)).map((pa) =>
StubOracle.from(pa.publicKey, pa.account),
);
}
// MangoAccount
@ -498,7 +505,6 @@ export class MangoClient {
public async serum3RegisterMarket(
group: Group,
serum3ProgramId: PublicKey,
serum3MarketExternalPk: PublicKey,
baseBank: Bank,
quoteBank: Bank,
@ -510,7 +516,7 @@ export class MangoClient {
.accounts({
group: group.publicKey,
admin: (this.program.provider as AnchorProvider).wallet.publicKey,
serumProgram: serum3ProgramId,
serumProgram: SERUM3_PROGRAM_ID[this.cluster],
serumMarketExternal: serum3MarketExternalPk,
baseBank: baseBank.publicKey,
quoteBank: quoteBank.publicKey,
@ -536,7 +542,7 @@ export class MangoClient {
.rpc();
}
public async serum3GetMarket(
public async serum3GetMarkets(
group: Group,
baseTokenIndex?: number,
quoteTokenIndex?: number,
@ -630,7 +636,6 @@ export class MangoClient {
public async serum3PlaceOrder(
group: Group,
mangoAccount: MangoAccount,
serum3ProgramId: PublicKey,
serum3MarketName: string,
side: Serum3Side,
price: number,
@ -647,12 +652,8 @@ export class MangoClient {
mangoAccount = await this.getMangoAccount(mangoAccount);
}
const serum3MarketExternal = await Market.load(
this.program.provider.connection,
serum3Market.serumMarketExternal,
{ commitment: this.program.provider.connection.commitment },
serum3ProgramId,
);
const serum3MarketExternal =
group.serum3MarketExternalsMap.get(serum3MarketName)!;
const serum3MarketExternalVaultSigner =
await PublicKey.createProgramAddress(
@ -664,7 +665,7 @@ export class MangoClient {
8,
),
],
serum3ProgramId,
SERUM3_PROGRAM_ID[this.cluster],
);
const healthRemainingAccounts: PublicKey[] =
@ -701,7 +702,7 @@ export class MangoClient {
openOrders: mangoAccount.findSerum3Account(serum3Market.marketIndex)
?.openOrders,
serumMarket: serum3Market.publicKey,
serumProgram: serum3ProgramId,
serumProgram: SERUM3_PROGRAM_ID[this.cluster],
serumMarketExternal: serum3Market.serumMarketExternal,
marketBids: serum3MarketExternal.bidsAddress,
marketAsks: serum3MarketExternal.asksAddress,
@ -727,18 +728,13 @@ export class MangoClient {
async serum3CancelAllorders(
group: Group,
mangoAccount: MangoAccount,
serum3ProgramId: PublicKey,
serum3MarketName: string,
limit: number,
) {
const serum3Market = group.serum3MarketsMap.get(serum3MarketName)!;
const serum3MarketExternal = await Market.load(
this.program.provider.connection,
serum3Market.serumMarketExternal,
{ commitment: this.program.provider.connection.commitment },
serum3ProgramId,
);
const serum3MarketExternal =
group.serum3MarketExternalsMap.get(serum3MarketName)!;
return await this.program.methods
.serum3CancelAllOrders(limit)
@ -749,7 +745,7 @@ export class MangoClient {
openOrders: mangoAccount.findSerum3Account(serum3Market.marketIndex)
?.openOrders,
serumMarket: serum3Market.publicKey,
serumProgram: serum3ProgramId,
serumProgram: SERUM3_PROGRAM_ID[this.cluster],
serumMarketExternal: serum3Market.serumMarketExternal,
marketBids: serum3MarketExternal.bidsAddress,
marketAsks: serum3MarketExternal.asksAddress,
@ -761,17 +757,12 @@ export class MangoClient {
async serum3SettleFunds(
group: Group,
mangoAccount: MangoAccount,
serum3ProgramId: PublicKey,
serum3MarketName: string,
): Promise<TransactionSignature> {
const serum3Market = group.serum3MarketsMap.get(serum3MarketName)!;
const serum3MarketExternal = await Market.load(
this.program.provider.connection,
serum3Market.serumMarketExternal,
{ commitment: this.program.provider.connection.commitment },
serum3ProgramId,
);
const serum3MarketExternal =
group.serum3MarketExternalsMap.get(serum3MarketName)!;
const serum3MarketExternalVaultSigner =
// TODO: put into a helper method, and remove copy pasta
@ -784,7 +775,7 @@ export class MangoClient {
8,
),
],
serum3ProgramId,
SERUM3_PROGRAM_ID[this.cluster],
);
return await this.program.methods
@ -796,7 +787,7 @@ export class MangoClient {
openOrders: mangoAccount.findSerum3Account(serum3Market.marketIndex)
?.openOrders,
serumMarket: serum3Market.publicKey,
serumProgram: serum3ProgramId,
serumProgram: SERUM3_PROGRAM_ID[this.cluster],
serumMarketExternal: serum3Market.serumMarketExternal,
marketBaseVault: serum3MarketExternal.decoded.baseVault,
marketQuoteVault: serum3MarketExternal.decoded.quoteVault,
@ -812,19 +803,15 @@ export class MangoClient {
async serum3CancelOrder(
group: Group,
mangoAccount: MangoAccount,
serum3ProgramId: PublicKey,
serum3MarketName: string,
side: Serum3Side,
orderId: BN,
): Promise<TransactionSignature> {
const serum3Market = group.serum3MarketsMap.get(serum3MarketName)!;
const serum3MarketExternal = await Market.load(
this.program.provider.connection,
serum3Market.serumMarketExternal,
{ commitment: this.program.provider.connection.commitment },
serum3ProgramId,
);
const serum3MarketExternal =
group.serum3MarketExternalsMap.get(serum3MarketName)!;
return await this.program.methods
.serum3CancelOrder(side, orderId)
.accounts({
@ -833,7 +820,7 @@ export class MangoClient {
openOrders: mangoAccount.findSerum3Account(serum3Market.marketIndex)
?.openOrders,
serumMarket: serum3Market.publicKey,
serumProgram: serum3ProgramId,
serumProgram: SERUM3_PROGRAM_ID[this.cluster],
serumMarketExternal: serum3Market.serumMarketExternal,
marketBids: serum3MarketExternal.bidsAddress,
marketAsks: serum3MarketExternal.asksAddress,
@ -844,17 +831,11 @@ export class MangoClient {
async getSerum3Orders(
group: Group,
serum3ProgramId: PublicKey,
serum3MarketName: string,
): Promise<Order[]> {
const serum3Market = group.serum3MarketsMap.get(serum3MarketName)!;
const serum3MarketExternal =
group.serum3MarketExternalsMap.get(serum3MarketName)!;
const serum3MarketExternal = await Market.load(
this.program.provider.connection,
serum3Market.serumMarketExternal,
{ commitment: this.program.provider.connection.commitment },
serum3ProgramId,
);
// TODO: filter for mango account
return await serum3MarketExternal.loadOrdersForOwner(
this.program.provider.connection,
@ -978,7 +959,7 @@ export class MangoClient {
.rpc();
}
public async perpGetMarket(
public async perpGetMarkets(
group: Group,
baseTokenIndex?: number,
quoteTokenIndex?: number,
@ -1156,15 +1137,22 @@ export class MangoClient {
/// static
static connect(provider?: Provider, devnet?: boolean): MangoClient {
static connect(
provider: Provider,
cluster: Cluster,
programId: PublicKey,
useIds: boolean,
): MangoClient {
// TODO: use IDL on chain or in repository? decide...
// Alternatively we could fetch IDL from chain.
// const idl = await Program.fetchIdl(MANGO_V4_ID, provider);
let idl = IDL;
return new MangoClient(
new Program<MangoV4>(idl as MangoV4, MANGO_V4_ID, provider),
devnet,
new Program<MangoV4>(idl as MangoV4, programId, provider),
programId,
cluster,
useIds,
);
}
@ -1187,24 +1175,12 @@ export class MangoClient {
}
}
const mintInfos = await Promise.all(
[...new Set(tokenIndices)].map(async (tokenIndex) =>
this.getMintInfoForTokenIndex(group, tokenIndex),
),
const mintInfos = [...new Set(tokenIndices)].map(
(tokenIndex) => group.mintInfosMap.get(tokenIndex)!,
);
healthRemainingAccounts.push(...mintInfos.map((mintInfo) => mintInfo.bank));
healthRemainingAccounts.push(
...mintInfos.flatMap((mintinfos) => {
return mintinfos.flatMap((mintinfo) => {
return mintinfo.bank;
});
}),
);
healthRemainingAccounts.push(
...mintInfos.flatMap((mintinfos) => {
return mintinfos.flatMap((mintinfo) => {
return mintinfo.oracle;
});
}),
...mintInfos.map((mintInfo) => mintInfo.oracle),
);
healthRemainingAccounts.push(
...mangoAccount.serum3

View File

@ -1,5 +1,13 @@
import { PublicKey } from '@solana/web3.js';
export const DEVNET_SERUM3_PROGRAM_ID = new PublicKey(
'DESVgJVGajEgKGXhb6XmqDHGz3VjdgP7rEVESBgxmroY',
);
export const SERUM3_PROGRAM_ID = {
testnet: new PublicKey('DESVgJVGajEgKGXhb6XmqDHGz3VjdgP7rEVESBgxmroY'), // todo: fix
devnet: new PublicKey('DESVgJVGajEgKGXhb6XmqDHGz3VjdgP7rEVESBgxmroY'),
mainnet: new PublicKey('9xQeWvG816bUx9EPjHmaT23yvVM2ZWbrrpZb9PusVFin'),
};
export const MANGO_V4_ID = {
testnet: new PublicKey('m43thNJ58XCjL798ZSq6JGAG1BnWskhdq5or6kcnfsD'), // todo: fix
devnet: new PublicKey('m43thNJ58XCjL798ZSq6JGAG1BnWskhdq5or6kcnfsD'),
mainnet: new PublicKey('m43thNJ58XCjL798ZSq6JGAG1BnWskhdq5or6kcnfsD'), // note: never deployed so far
};

47
ts/client/src/ids.ts Normal file
View File

@ -0,0 +1,47 @@
import { Cluster, PublicKey } from '@solana/web3.js';
import ids from '../ids.json';
import { MANGO_V4_ID } from './constants';
export class Id {
constructor(
public banks: Map<String, PublicKey>,
public stubOracles: Map<String, PublicKey>,
public mintInfos: Map<String, PublicKey>,
public serum3Markets: Map<String, PublicKey>,
public serum3MarketExternals: Map<String, PublicKey>,
public perpMarkets: Map<String, PublicKey>,
) {}
public getBanks(): PublicKey[] {
return Array.from(this.banks.values());
}
public getStubOracles(): PublicKey[] {
return Array.from(this.stubOracles.values());
}
public getMintInfos(): PublicKey[] {
return Array.from(this.mintInfos.values());
}
public getSerum3Markets(): PublicKey[] {
return Array.from(this.serum3Markets.values());
}
public getPerpMarkets(): PublicKey[] {
return Array.from(this.perpMarkets.values());
}
static fromIds(cluster: Cluster, programId: PublicKey, group: PublicKey): Id {
let groupConfig =
ids['devnet'][MANGO_V4_ID['devnet'].toBase58()][group.toString()];
return new Id(
new Map(Object.entries(groupConfig['banks'])),
new Map(Object.entries(groupConfig['stubOracles'])),
new Map(Object.entries(groupConfig['mintInfos'])),
new Map(Object.entries(groupConfig['serum3Markets'])),
new Map(Object.entries(groupConfig['serum3MarketExternals'])),
new Map(Object.entries(groupConfig['perpMarkets'])),
);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,89 @@
import { AnchorProvider, Wallet } from '@project-serum/anchor';
import { Connection, Keypair } from '@solana/web3.js';
import fs from 'fs';
import idsJson from '../../ids.json';
import { MangoClient } from '../client';
import { MANGO_V4_ID } from '../constants';
import { Id } from '../ids';
function replacer(key, value) {
if (value instanceof Map) {
return Object.fromEntries(value);
} else {
return value;
}
}
async function main() {
// build client and fetch group for admin
const options = AnchorProvider.defaultOptions();
const connection = new Connection(
'https://mango.devnet.rpcpool.com',
options,
);
const user = Keypair.fromSecretKey(
Buffer.from(
JSON.parse(fs.readFileSync(process.env.USER_KEYPAIR!, 'utf-8')),
),
);
const userWallet = new Wallet(user);
const userProvider = new AnchorProvider(connection, userWallet, options);
const client = await MangoClient.connect(
userProvider,
'devnet',
MANGO_V4_ID['devnet'],
false,
);
const admin = Keypair.fromSecretKey(
Buffer.from(
JSON.parse(fs.readFileSync(process.env.ADMIN_KEYPAIR!, 'utf-8')),
),
);
const group = await client.getGroupForAdmin(admin.publicKey, 0);
// collect mappings &
// collect pubkeys
const banks = await client.getBanksForGroup(group);
const banksMapByMint = new Map(
banks.map((tuple) => [tuple.mint.toBase58(), tuple]),
);
const stubOracles = await client.getStubOracle(group);
const mintInfos = await client.getMintInfosForGroup(group);
const serum3Markets = await client.serum3GetMarkets(group);
const perpMarkets = await client.perpGetMarkets(group);
// build ids
const toDump = new Id(
new Map(banks.map((tuple) => [tuple.name, tuple.publicKey])),
new Map(
stubOracles.map((tuple) => [
banksMapByMint.get(tuple.mint.toBase58())!.name,
tuple.publicKey,
]),
),
new Map(
mintInfos.map((tuple) => [
banksMapByMint.get(tuple.mint.toBase58())!.name,
tuple.publicKey,
]),
),
new Map(serum3Markets.map((tuple) => [tuple.name, tuple.publicKey])),
new Map(
serum3Markets.map((tuple) => [tuple.name, tuple.serumMarketExternal]),
),
new Map(perpMarkets.map((tuple) => [tuple.name, tuple.publicKey])),
);
// adds ids for group in existing ids.json
idsJson['devnet'][MANGO_V4_ID['devnet'].toBase58()] = {};
idsJson['devnet'][MANGO_V4_ID['devnet'].toBase58()][
group.publicKey.toBase58()
] = toDump;
// dump
const file = `${process.cwd()}/ts/client/ids.json`;
await fs.writeFileSync(file, JSON.stringify(idsJson, replacer, 2));
process.exit();
}
main();

View File

@ -2,6 +2,7 @@ import { AnchorProvider, Wallet } from '@project-serum/anchor';
import { Connection, Keypair, PublicKey } from '@solana/web3.js';
import fs from 'fs';
import { MangoClient } from '../client';
import { MANGO_V4_ID } from '../constants';
export const DEVNET_MINTS = new Map([
['USDC', '8FRFC6MoGGkMFQwngccyu69VnYbzykGeez7ignHVAFSN'], // use devnet usdc
@ -22,7 +23,12 @@ async function main() {
const adminWallet = new Wallet(admin);
console.log(`Admin ${adminWallet.publicKey.toBase58()}`);
const adminProvider = new AnchorProvider(connection, adminWallet, options);
const client = await MangoClient.connect(adminProvider, true);
const client = await MangoClient.connect(
adminProvider,
'devnet',
MANGO_V4_ID['devnet'],
false,
);
const group = await client.getGroupForAdmin(admin.publicKey);
console.log(`Group ${group.publicKey}`);
@ -32,7 +38,10 @@ async function main() {
// close stub oracle
const usdcDevnetMint = new PublicKey(DEVNET_MINTS.get('USDC')!);
try {
const usdcDevnetOracle = await client.getStubOracle(group, usdcDevnetMint);
const usdcDevnetOracle = await client.getStubOracle(
group,
usdcDevnetMint,
)[0];
let sig = await client.closeStubOracle(group, usdcDevnetOracle.publicKey);
console.log(
`Closed USDC stub oracle, sig https://explorer.solana.com/address/${sig}?cluster=devnet`,

View File

@ -2,7 +2,7 @@ import { AnchorProvider, Wallet } from '@project-serum/anchor';
import { Connection, Keypair, PublicKey } from '@solana/web3.js';
import fs from 'fs';
import { MangoClient } from '../client';
import { DEVNET_SERUM3_PROGRAM_ID } from '../constants';
import { MANGO_V4_ID } from '../constants';
const DEVNET_SERUM3_MARKETS = new Map([
['BTC/USDC', 'DW83EpHFywBxCHmyARxwj3nzxJd7MUdSeznmrdzZKNZB'],
@ -44,7 +44,12 @@ async function main() {
const adminWallet = new Wallet(admin);
console.log(`Admin ${adminWallet.publicKey.toBase58()}`);
const adminProvider = new AnchorProvider(connection, adminWallet, options);
const client = await MangoClient.connect(adminProvider, true);
const client = await MangoClient.connect(
adminProvider,
'devnet',
MANGO_V4_ID['devnet'],
false,
);
// group
console.log(`Creating Group...`);
@ -80,7 +85,7 @@ async function main() {
1.4,
0.02,
);
await group.reload(client);
await group.reloadAll(client);
} catch (error) {
console.log(error);
}
@ -93,7 +98,7 @@ async function main() {
} catch (error) {
console.log(error);
}
const usdcDevnetOracle = await client.getStubOracle(group, usdcDevnetMint);
const usdcDevnetOracle = await client.getStubOracle(group, usdcDevnetMint)[0];
console.log(`...created stub oracle ${usdcDevnetOracle.publicKey}`);
try {
await client.tokenRegister(
@ -115,7 +120,7 @@ async function main() {
1.4,
0.02,
);
await group.reload(client);
await group.reloadAll(client);
} catch (error) {}
// register token 2
@ -142,7 +147,7 @@ async function main() {
1.4,
0.02,
);
await group.reload(client);
await group.reloadAll(client);
} catch (error) {
console.log(error);
}
@ -171,7 +176,7 @@ async function main() {
1.4,
0.02,
);
await group.reload(client);
await group.reloadAll(client);
} catch (error) {
console.log(error);
}
@ -191,7 +196,7 @@ async function main() {
try {
await client.serum3RegisterMarket(
group,
DEVNET_SERUM3_PROGRAM_ID,
serumMarketExternalPk,
group.banksMap.get('BTC')!,
group.banksMap.get('USDC')!,
@ -201,7 +206,7 @@ async function main() {
} catch (error) {
console.log(error);
}
const markets = await client.serum3GetMarket(
const markets = await client.serum3GetMarkets(
group,
group.banksMap.get('BTC')?.tokenIndex,
group.banksMap.get('USDC')?.tokenIndex,
@ -236,7 +241,7 @@ async function main() {
} catch (error) {
console.log(error);
}
const perpMarkets = await client.perpGetMarket(
const perpMarkets = await client.perpGetMarkets(
group,
group.banksMap.get('BTC')?.tokenIndex,
group.banksMap.get('USDC')?.tokenIndex,

View File

@ -0,0 +1,39 @@
import { AnchorProvider, Wallet } from '@project-serum/anchor';
import { Connection, Keypair } from '@solana/web3.js';
import fs from 'fs';
import { MangoClient } from '../client';
import { MANGO_V4_ID } from '../constants';
async function main() {
const options = AnchorProvider.defaultOptions();
const connection = new Connection(
'https://mango.devnet.rpcpool.com',
options,
);
const user = Keypair.fromSecretKey(
Buffer.from(
JSON.parse(fs.readFileSync(process.env.USER_KEYPAIR!, 'utf-8')),
),
);
const userWallet = new Wallet(user);
const userProvider = new AnchorProvider(connection, userWallet, options);
const client = await MangoClient.connect(
userProvider,
'devnet',
MANGO_V4_ID['devnet'],
true /* Use ids json instead of getProgramAccounts */,
);
console.log(`User ${userWallet.publicKey.toBase58()}`);
const admin = Keypair.fromSecretKey(
Buffer.from(
JSON.parse(fs.readFileSync(process.env.ADMIN_KEYPAIR!, 'utf-8')),
),
);
const group = await client.getGroupForAdmin(admin.publicKey, 0);
console.log(`Found group ${group.publicKey.toBase58()}`);
process.exit();
}
main();

View File

@ -8,7 +8,7 @@ import {
Serum3Side,
} from '../accounts/serum3';
import { MangoClient } from '../client';
import { DEVNET_SERUM3_PROGRAM_ID } from '../constants';
import { MANGO_V4_ID } from '../constants';
//
// An example for users based on high level api i.e. the client
@ -30,7 +30,12 @@ async function main() {
);
const userWallet = new Wallet(user);
const userProvider = new AnchorProvider(connection, userWallet, options);
const client = await MangoClient.connect(userProvider, true);
const client = await MangoClient.connect(
userProvider,
'devnet',
MANGO_V4_ID['devnet'],
false,
);
console.log(`User ${userWallet.publicKey.toBase58()}`);
// fetch group
@ -73,7 +78,7 @@ async function main() {
await client.serum3PlaceOrder(
group,
mangoAccount,
DEVNET_SERUM3_PROGRAM_ID,
'BTC/USDC',
Serum3Side.bid,
20,
@ -89,7 +94,7 @@ async function main() {
await client.serum3PlaceOrder(
group,
mangoAccount,
DEVNET_SERUM3_PROGRAM_ID,
'BTC/USDC',
Serum3Side.bid,
90000,
@ -105,7 +110,7 @@ async function main() {
await client.serum3PlaceOrder(
group,
mangoAccount,
DEVNET_SERUM3_PROGRAM_ID,
'BTC/USDC',
Serum3Side.ask,
30000,
@ -119,7 +124,7 @@ async function main() {
console.log(`Current own orders on OB...`);
let orders = await client.getSerum3Orders(
group,
DEVNET_SERUM3_PROGRAM_ID,
'BTC/USDC',
);
for (const order of orders) {
@ -130,7 +135,7 @@ async function main() {
await client.serum3CancelOrder(
group,
mangoAccount,
DEVNET_SERUM3_PROGRAM_ID,
'BTC/USDC',
order.side === 'buy' ? Serum3Side.bid : Serum3Side.ask,
order.orderId,
@ -140,7 +145,7 @@ async function main() {
console.log(`Current own orders on OB...`);
orders = await client.getSerum3Orders(
group,
DEVNET_SERUM3_PROGRAM_ID,
'BTC/USDC',
);
for (const order of orders) {
@ -151,7 +156,7 @@ async function main() {
await client.serum3SettleFunds(
group,
mangoAccount,
DEVNET_SERUM3_PROGRAM_ID,
'BTC/USDC',
);

View File

@ -2,7 +2,7 @@ import { AnchorProvider, Wallet } from '@project-serum/anchor';
import { Connection, Keypair } from '@solana/web3.js';
import fs from 'fs';
import { MangoClient } from '../../client';
import { DEVNET_SERUM3_PROGRAM_ID } from '../../constants';
import { MANGO_V4_ID } from '../../constants';
//
// An example for users based on high level api i.e. the client
@ -24,7 +24,12 @@ async function main() {
);
const userWallet = new Wallet(user);
const userProvider = new AnchorProvider(connection, userWallet, options);
const client = await MangoClient.connect(userProvider, true);
const client = await MangoClient.connect(
userProvider,
'devnet',
MANGO_V4_ID['devnet'],
false,
);
console.log(`User ${userWallet.publicKey.toBase58()}`);
// fetch group
@ -51,7 +56,7 @@ async function main() {
console.log(`Current own orders on OB...`);
const orders = await client.getSerum3Orders(
group,
DEVNET_SERUM3_PROGRAM_ID,
'BTC/USDC',
);
for (const order of orders) {

View File

@ -3,6 +3,7 @@ import { Connection, Keypair } from '@solana/web3.js';
import fs from 'fs';
import { TokenAccount } from '../../accounts/mangoAccount';
import { MangoClient } from '../../client';
import { MANGO_V4_ID } from '../../constants';
//
// An example for users based on high level api i.e. the client
@ -24,7 +25,12 @@ async function main() {
);
const userWallet = new Wallet(user);
const userProvider = new AnchorProvider(connection, userWallet, options);
const client = await MangoClient.connect(userProvider, true);
const client = await MangoClient.connect(
userProvider,
'devnet',
MANGO_V4_ID['devnet'],
false,
);
console.log(`User ${userWallet.publicKey.toBase58()}`);
// fetch group

View File

@ -2,6 +2,7 @@ import { AnchorProvider, Wallet } from '@project-serum/anchor';
import { Connection, Keypair } from '@solana/web3.js';
import fs from 'fs';
import { MangoClient } from '../../client';
import { MANGO_V4_ID } from '../../constants';
async function main() {
const options = AnchorProvider.defaultOptions();
@ -18,7 +19,12 @@ async function main() {
);
const user1Wallet = new Wallet(user1);
const user1Provider = new AnchorProvider(connection, user1Wallet, options);
const user1Client = await MangoClient.connect(user1Provider, true);
const user1Client = await MangoClient.connect(
user1Provider,
'devnet',
MANGO_V4_ID['devnet'],
false,
);
console.log(`user1 ${user1Wallet.publicKey.toBase58()}`);
/// fetch group
@ -60,7 +66,12 @@ async function main() {
);
const user2Wallet = new Wallet(user2);
const user2Provider = new AnchorProvider(connection, user2Wallet, options);
const user2Client = await MangoClient.connect(user2Provider, true);
const user2Client = await MangoClient.connect(
user2Provider,
'devnet',
MANGO_V4_ID['devnet'],
false,
);
console.log(`user2 ${user2Wallet.publicKey.toBase58()}`);
// create + fetch account

View File

@ -1,10 +1,11 @@
import fs from 'fs';
import * as os from 'os';
import { AnchorProvider, Wallet } from '@project-serum/anchor';
import { Market } from '@project-serum/serum';
import { Connection, Keypair, PublicKey } from '@solana/web3.js';
import fs from 'fs';
import * as os from 'os';
import { MangoClient } from '../../client';
import { MANGO_V4_ID } from '../../constants';
const main = async () => {
const options = AnchorProvider.defaultOptions();
@ -23,7 +24,12 @@ const main = async () => {
const adminWallet = new Wallet(admin);
console.log(`Admin ${adminWallet.publicKey.toBase58()}`);
const adminProvider = new AnchorProvider(connection, adminWallet, options);
const client = await MangoClient.connect(adminProvider, true);
const client = await MangoClient.connect(
adminProvider,
'devnet',
MANGO_V4_ID['devnet'],
false,
);
const btcMint = new PublicKey('3UNBZ6o52WTWwjac2kPUb4FyodhU1vFkRJheu1Sh2TvU');
const usdcMint = new PublicKey(