Extending the client, make more use friendly, make serum3 place order work for example
Signed-off-by: microwavedcola1 <microwavedcola@gmail.com>
This commit is contained in:
parent
f7fb0bbec8
commit
89aa667985
|
@ -5,13 +5,54 @@ import {
|
|||
TransactionSignature,
|
||||
} from '@solana/web3.js';
|
||||
import { MangoClient } from '../../client';
|
||||
import {
|
||||
DEVNET_MINTS_REVERSE,
|
||||
DEVNET_SERUM3_MARKETS_REVERSE,
|
||||
} from '../../constants';
|
||||
import { Bank } from './bank';
|
||||
import { Serum3Market } from './serum3';
|
||||
|
||||
export class Group {
|
||||
static from(publicKey: PublicKey, obj: { admin: PublicKey }): Group {
|
||||
return new Group(publicKey, obj.admin);
|
||||
return new Group(publicKey, obj.admin, new Map(), new Map());
|
||||
}
|
||||
|
||||
constructor(public publicKey: PublicKey, public admin: PublicKey) {}
|
||||
constructor(
|
||||
public publicKey: PublicKey,
|
||||
public admin: PublicKey,
|
||||
public banksMap: Map<string, Bank>,
|
||||
public serum3MarketsMap: Map<string, Serum3Market>,
|
||||
) {}
|
||||
|
||||
public findBank(tokenIndex: number): Bank | undefined {
|
||||
return Array.from(this.banksMap.values()).find(
|
||||
(bank) => bank.tokenIndex === tokenIndex,
|
||||
);
|
||||
}
|
||||
|
||||
public async reload(client: MangoClient) {
|
||||
await this.reloadBanks(client);
|
||||
await this.reloadSerum3Markets(client);
|
||||
}
|
||||
|
||||
public async reloadBanks(client: MangoClient) {
|
||||
const banks = await client.getBanksForGroup(this);
|
||||
this.banksMap = new Map(
|
||||
banks.map((bank) => [DEVNET_MINTS_REVERSE[bank.mint.toBase58()], bank]),
|
||||
);
|
||||
}
|
||||
|
||||
public async reloadSerum3Markets(client: MangoClient) {
|
||||
const serum3Markets = await client.serum3GetMarket(this);
|
||||
this.serum3MarketsMap = new Map(
|
||||
serum3Markets.map((serum3Market) => [
|
||||
DEVNET_SERUM3_MARKETS_REVERSE[
|
||||
serum3Market.serumMarketExternal.toBase58()
|
||||
],
|
||||
serum3Market,
|
||||
]),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -68,6 +68,10 @@ export class MangoAccount {
|
|||
return this.tokens.find((ta) => ta.tokenIndex == tokenIndex);
|
||||
}
|
||||
|
||||
findSerum3Account(marketIndex: number): Serum3Account | undefined {
|
||||
return this.serum3.find((sa) => sa.marketIndex == marketIndex);
|
||||
}
|
||||
|
||||
getNativeDeposit(bank: Bank): I80F48 {
|
||||
const ta = this.findToken(bank.tokenIndex);
|
||||
return bank.depositIndex.mul(ta?.indexedValue!);
|
||||
|
|
255
ts/client.ts
255
ts/client.ts
|
@ -1,7 +1,9 @@
|
|||
import { BN, Program, Provider } from '@project-serum/anchor';
|
||||
import { Market } from '@project-serum/serum';
|
||||
import * as spl from '@solana/spl-token';
|
||||
import {
|
||||
AccountMeta,
|
||||
MemcmpFilter,
|
||||
PublicKey,
|
||||
SYSVAR_RENT_PUBKEY,
|
||||
TransactionSignature,
|
||||
|
@ -12,7 +14,12 @@ import { Group } from './accounts/types/group';
|
|||
import { I80F48 } from './accounts/types/I80F48';
|
||||
import { MangoAccount } from './accounts/types/mangoAccount';
|
||||
import { StubOracle } from './accounts/types/oracle';
|
||||
import { Serum3Market } from './accounts/types/serum3';
|
||||
import {
|
||||
Serum3Market,
|
||||
Serum3OrderType,
|
||||
Serum3SelfTradeBehavior,
|
||||
Serum3Side,
|
||||
} from './accounts/types/serum3';
|
||||
import { IDL, MangoV4 } from './mango_v4';
|
||||
|
||||
export const MANGO_V4_ID = new PublicKey(
|
||||
|
@ -48,6 +55,7 @@ export class MangoClient {
|
|||
},
|
||||
])
|
||||
).map((tuple) => Group.from(tuple.publicKey, tuple.account));
|
||||
await groups[0].reload(this);
|
||||
return groups[0];
|
||||
}
|
||||
|
||||
|
@ -151,6 +159,19 @@ export class MangoClient {
|
|||
|
||||
// MangoAccount
|
||||
|
||||
public async getOrCreateMangoAccount(
|
||||
group: Group,
|
||||
ownerPk: PublicKey,
|
||||
accountNumber?: number,
|
||||
): Promise<MangoAccount> {
|
||||
let mangoAccounts = await this.getMangoAccountForOwner(group, ownerPk);
|
||||
if (mangoAccounts.length === 0) {
|
||||
await this.createMangoAccount(group, accountNumber ?? 0);
|
||||
}
|
||||
mangoAccounts = await this.getMangoAccountForOwner(group, ownerPk);
|
||||
return mangoAccounts[0];
|
||||
}
|
||||
|
||||
public async createMangoAccount(
|
||||
group: Group,
|
||||
accountNumber: number,
|
||||
|
@ -165,7 +186,14 @@ export class MangoClient {
|
|||
.rpc();
|
||||
}
|
||||
|
||||
public async getMangoAccount(
|
||||
public async getMangoAccount(mangoAccount: MangoAccount) {
|
||||
return MangoAccount.from(
|
||||
mangoAccount.publicKey,
|
||||
await this.program.account.mangoAccount.fetch(mangoAccount.publicKey),
|
||||
);
|
||||
}
|
||||
|
||||
public async getMangoAccountForOwner(
|
||||
group: Group,
|
||||
ownerPk: PublicKey,
|
||||
): Promise<MangoAccount[]> {
|
||||
|
@ -192,9 +220,11 @@ export class MangoClient {
|
|||
public async deposit(
|
||||
group: Group,
|
||||
mangoAccount: MangoAccount,
|
||||
bank: Bank,
|
||||
tokenName: string,
|
||||
amount: number,
|
||||
) {
|
||||
const bank = group.banksMap.get(tokenName)!;
|
||||
|
||||
const tokenAccountPk = await spl.getAssociatedTokenAddress(
|
||||
bank.mint,
|
||||
mangoAccount.owner,
|
||||
|
@ -225,10 +255,12 @@ export class MangoClient {
|
|||
public async withdraw(
|
||||
group: Group,
|
||||
mangoAccount: MangoAccount,
|
||||
bank: Bank,
|
||||
tokenName: string,
|
||||
amount: number,
|
||||
allowBorrow: boolean,
|
||||
) {
|
||||
const bank = group.banksMap.get(tokenName)!;
|
||||
|
||||
const tokenAccountPk = await spl.getAssociatedTokenAddress(
|
||||
bank.mint,
|
||||
mangoAccount.owner,
|
||||
|
@ -280,49 +312,57 @@ export class MangoClient {
|
|||
.rpc();
|
||||
}
|
||||
|
||||
public async serum3GetMarketForBaseAndQuote(
|
||||
public async serum3GetMarket(
|
||||
group: Group,
|
||||
baseTokenIndex: number,
|
||||
quoteTokenIndex: number,
|
||||
baseTokenIndex?: number,
|
||||
quoteTokenIndex?: number,
|
||||
): Promise<Serum3Market[]> {
|
||||
const bbuf = Buffer.alloc(2);
|
||||
bbuf.writeUInt16LE(baseTokenIndex);
|
||||
|
||||
const qbuf = Buffer.alloc(2);
|
||||
qbuf.writeUInt16LE(quoteTokenIndex);
|
||||
|
||||
const bumpfbuf = Buffer.alloc(1);
|
||||
bumpfbuf.writeUInt8(255);
|
||||
|
||||
return (
|
||||
await this.program.account.serum3Market.all([
|
||||
{
|
||||
memcmp: {
|
||||
bytes: group.publicKey.toBase58(),
|
||||
offset: 8,
|
||||
},
|
||||
const filters: MemcmpFilter[] = [
|
||||
{
|
||||
memcmp: {
|
||||
bytes: group.publicKey.toBase58(),
|
||||
offset: 8,
|
||||
},
|
||||
{
|
||||
memcmp: {
|
||||
bytes: bs58.encode(bbuf),
|
||||
offset: 106,
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
if (baseTokenIndex) {
|
||||
const bbuf = Buffer.alloc(2);
|
||||
bbuf.writeUInt16LE(baseTokenIndex);
|
||||
filters.push({
|
||||
memcmp: {
|
||||
bytes: bs58.encode(bbuf),
|
||||
offset: 106,
|
||||
},
|
||||
{
|
||||
memcmp: {
|
||||
bytes: bs58.encode(qbuf),
|
||||
offset: 108,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
if (quoteTokenIndex) {
|
||||
const qbuf = Buffer.alloc(2);
|
||||
qbuf.writeUInt16LE(quoteTokenIndex);
|
||||
filters.push({
|
||||
memcmp: {
|
||||
bytes: bs58.encode(qbuf),
|
||||
offset: 106,
|
||||
},
|
||||
])
|
||||
).map((tuple) => Serum3Market.from(tuple.publicKey, tuple.account));
|
||||
});
|
||||
}
|
||||
|
||||
return (await this.program.account.serum3Market.all(filters)).map((tuple) =>
|
||||
Serum3Market.from(tuple.publicKey, tuple.account),
|
||||
);
|
||||
}
|
||||
|
||||
public async serum3CreateOpenOrders(
|
||||
group: Group,
|
||||
mangoAccount: MangoAccount,
|
||||
serum3Market: Serum3Market,
|
||||
marketName: string,
|
||||
): Promise<TransactionSignature> {
|
||||
const serum3Market: Serum3Market = group.serum3MarketsMap.get(marketName)!;
|
||||
|
||||
return await this.program.methods
|
||||
.serum3CreateOpenOrders()
|
||||
.accounts({
|
||||
|
@ -337,6 +377,92 @@ export class MangoClient {
|
|||
.rpc();
|
||||
}
|
||||
|
||||
public async serum3PlaceOrder(
|
||||
group: Group,
|
||||
mangoAccount: MangoAccount,
|
||||
serum3ProgramId: PublicKey,
|
||||
serum3MarketName: string,
|
||||
side: Serum3Side,
|
||||
limitPrice: number,
|
||||
maxBaseQty: number,
|
||||
maxNativeQuoteQtyIncludingFees: number,
|
||||
selfTradeBehavior: Serum3SelfTradeBehavior,
|
||||
orderType: Serum3OrderType,
|
||||
clientOrderId: number,
|
||||
limit: number,
|
||||
) {
|
||||
const serum3Market = group.serum3MarketsMap.get(serum3MarketName)!;
|
||||
|
||||
if (!mangoAccount.findSerum3Account(serum3Market.marketIndex)) {
|
||||
await this.serum3CreateOpenOrders(group, mangoAccount, 'BTC/USDC');
|
||||
mangoAccount = await this.getMangoAccount(mangoAccount);
|
||||
}
|
||||
|
||||
const serum3MarketExternal = await Market.load(
|
||||
this.program.provider.connection,
|
||||
serum3Market.serumMarketExternal,
|
||||
{ commitment: this.program.provider.connection.commitment },
|
||||
serum3ProgramId,
|
||||
);
|
||||
|
||||
const serum3MarketExternalVaultSigner =
|
||||
await PublicKey.createProgramAddress(
|
||||
[
|
||||
serum3Market.serumMarketExternal.toBuffer(),
|
||||
serum3MarketExternal.decoded.vaultSignerNonce.toArrayLike(
|
||||
Buffer,
|
||||
'le',
|
||||
8,
|
||||
),
|
||||
],
|
||||
serum3ProgramId,
|
||||
);
|
||||
|
||||
const healthRemainingAccounts: PublicKey[] =
|
||||
await this.buildHealthRemainingAccounts(group, mangoAccount);
|
||||
|
||||
return await this.program.methods
|
||||
.serum3PlaceOrder(
|
||||
side,
|
||||
new BN(limitPrice),
|
||||
new BN(maxBaseQty),
|
||||
new BN(maxNativeQuoteQtyIncludingFees),
|
||||
selfTradeBehavior,
|
||||
orderType,
|
||||
new BN(clientOrderId),
|
||||
limit,
|
||||
)
|
||||
.accounts({
|
||||
group: group.publicKey,
|
||||
account: mangoAccount.publicKey,
|
||||
owner: this.program.provider.wallet.publicKey,
|
||||
openOrders: mangoAccount.findSerum3Account(serum3Market.marketIndex)
|
||||
?.openOrders,
|
||||
serumMarket: serum3Market.publicKey,
|
||||
serumProgram: serum3ProgramId,
|
||||
serumMarketExternal: serum3Market.serumMarketExternal,
|
||||
marketBids: serum3MarketExternal.bidsAddress,
|
||||
marketAsks: serum3MarketExternal.asksAddress,
|
||||
marketEventQueue: serum3MarketExternal.decoded.eventQueue,
|
||||
marketRequestQueue: serum3MarketExternal.decoded.requestQueue,
|
||||
marketBaseVault: serum3MarketExternal.decoded.baseVault,
|
||||
marketQuoteVault: serum3MarketExternal.decoded.quoteVault,
|
||||
marketVaultSigner: serum3MarketExternalVaultSigner,
|
||||
quoteBank: group.findBank(serum3Market.quoteTokenIndex)?.publicKey,
|
||||
quoteVault: group.findBank(serum3Market.quoteTokenIndex)?.vault,
|
||||
baseBank: group.findBank(serum3Market.baseTokenIndex)?.publicKey,
|
||||
baseVault: group.findBank(serum3Market.baseTokenIndex)?.vault,
|
||||
})
|
||||
.remainingAccounts(
|
||||
healthRemainingAccounts.map(
|
||||
(pk) =>
|
||||
({ pubkey: pk, isWritable: false, isSigner: false } as AccountMeta),
|
||||
),
|
||||
)
|
||||
|
||||
.rpc();
|
||||
}
|
||||
|
||||
/// static
|
||||
|
||||
static async connect(
|
||||
|
@ -383,40 +509,43 @@ export class MangoClient {
|
|||
private async buildHealthRemainingAccounts(
|
||||
group: Group,
|
||||
mangoAccount: MangoAccount,
|
||||
bank: Bank,
|
||||
bank?: Bank /** TODO for serum3PlaceOrde we are just ingoring this atm */,
|
||||
) {
|
||||
const healthRemainingAccounts: PublicKey[] = [];
|
||||
{
|
||||
const tokenIndices = mangoAccount.tokens
|
||||
.filter((token) => token.tokenIndex !== 65535)
|
||||
.map((token) => token.tokenIndex);
|
||||
tokenIndices.push(bank.tokenIndex);
|
||||
|
||||
const mintInfos = await Promise.all(
|
||||
[...new Set(tokenIndices)].map(async (tokenIndex) =>
|
||||
getMintInfoForTokenIndex(this, group.publicKey, tokenIndex),
|
||||
),
|
||||
);
|
||||
healthRemainingAccounts.push(
|
||||
...mintInfos.flatMap((mintinfos) => {
|
||||
return mintinfos.flatMap((mintinfo) => {
|
||||
return mintinfo.bank;
|
||||
});
|
||||
}),
|
||||
);
|
||||
healthRemainingAccounts.push(
|
||||
...mintInfos.flatMap((mintinfos) => {
|
||||
return mintinfos.flatMap((mintinfo) => {
|
||||
return mintinfo.oracle;
|
||||
});
|
||||
}),
|
||||
);
|
||||
healthRemainingAccounts.push(
|
||||
...mangoAccount.serum3
|
||||
.filter((serum3Account) => serum3Account.marketIndex !== 65535)
|
||||
.map((serum3Account) => serum3Account.openOrders),
|
||||
);
|
||||
const tokenIndices = mangoAccount.tokens
|
||||
.filter((token) => token.tokenIndex !== 65535)
|
||||
.map((token) => token.tokenIndex);
|
||||
|
||||
if (bank) {
|
||||
tokenIndices.push(bank.tokenIndex);
|
||||
}
|
||||
|
||||
const mintInfos = await Promise.all(
|
||||
[...new Set(tokenIndices)].map(async (tokenIndex) =>
|
||||
getMintInfoForTokenIndex(this, group.publicKey, tokenIndex),
|
||||
),
|
||||
);
|
||||
healthRemainingAccounts.push(
|
||||
...mintInfos.flatMap((mintinfos) => {
|
||||
return mintinfos.flatMap((mintinfo) => {
|
||||
return mintinfo.bank;
|
||||
});
|
||||
}),
|
||||
);
|
||||
healthRemainingAccounts.push(
|
||||
...mintInfos.flatMap((mintinfos) => {
|
||||
return mintinfos.flatMap((mintinfo) => {
|
||||
return mintinfo.oracle;
|
||||
});
|
||||
}),
|
||||
);
|
||||
healthRemainingAccounts.push(
|
||||
...mangoAccount.serum3
|
||||
.filter((serum3Account) => serum3Account.marketIndex !== 65535)
|
||||
.map((serum3Account) => serum3Account.openOrders),
|
||||
);
|
||||
|
||||
return healthRemainingAccounts;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
import { PublicKey } from '@solana/web3.js';
|
||||
|
||||
export const DEVNET_GROUP = '6ACH752p6FsdLzuociVkmDwc3wJW8pcCoxZKfXJKfKcD';
|
||||
|
||||
export const DEVNET_MINTS = new Map([
|
||||
['USDC', '8FRFC6MoGGkMFQwngccyu69VnYbzykGeez7ignHVAFSN'],
|
||||
['BTC', '3UNBZ6o52WTWwjac2kPUb4FyodhU1vFkRJheu1Sh2TvU'],
|
||||
]);
|
||||
|
||||
export const DEVNET_MINTS_REVERSE = Array.from(DEVNET_MINTS.entries()).reduce(
|
||||
function (map, obj) {
|
||||
map[obj[1]] = obj[0];
|
||||
return map;
|
||||
},
|
||||
{},
|
||||
);
|
||||
|
||||
export const DEVNET_ORACLES = new Map([
|
||||
['BTC', 'HovQMDrbAgAYPCmHVSrezcSmkMtXSSUsLDFANExrZh2J'],
|
||||
]);
|
||||
|
||||
export const DEVNET_SERUM3_MARKETS = new Map([
|
||||
['BTC/USDC', 'DW83EpHFywBxCHmyARxwj3nzxJd7MUdSeznmrdzZKNZB'],
|
||||
]);
|
||||
|
||||
export const DEVNET_SERUM3_MARKETS_REVERSE = Array.from(
|
||||
DEVNET_SERUM3_MARKETS.entries(),
|
||||
).reduce(function (map, obj) {
|
||||
map[obj[1]] = obj[0];
|
||||
return map;
|
||||
}, {});
|
||||
|
||||
export const DEVNET_SERUM3_PROGRAM_ID = new PublicKey(
|
||||
'DESVgJVGajEgKGXhb6XmqDHGz3VjdgP7rEVESBgxmroY',
|
||||
);
|
|
@ -35,6 +35,11 @@ import {
|
|||
Serum3Side,
|
||||
} from './accounts/types/serum3';
|
||||
import { MangoClient } from './client';
|
||||
import {
|
||||
DEVNET_MINTS,
|
||||
DEVNET_ORACLES,
|
||||
DEVNET_SERUM3_PROGRAM_ID,
|
||||
} from './constants';
|
||||
import { findOrCreate } from './utils';
|
||||
|
||||
//
|
||||
|
@ -86,9 +91,7 @@ async function main() {
|
|||
//
|
||||
// Find existing or register new oracles
|
||||
//
|
||||
const usdcDevnetMint = new PublicKey(
|
||||
'8FRFC6MoGGkMFQwngccyu69VnYbzykGeez7ignHVAFSN',
|
||||
);
|
||||
const usdcDevnetMint = new PublicKey(DEVNET_MINTS['USDC']);
|
||||
const usdcDevnetStubOracle = await findOrCreate<StubOracle>(
|
||||
'stubOracle',
|
||||
getStubOracleForGroupAndMint,
|
||||
|
@ -99,12 +102,8 @@ async function main() {
|
|||
console.log(
|
||||
`usdcDevnetStubOracle ${usdcDevnetStubOracle.publicKey.toBase58()}`,
|
||||
);
|
||||
const btcDevnetMint = new PublicKey(
|
||||
'3UNBZ6o52WTWwjac2kPUb4FyodhU1vFkRJheu1Sh2TvU',
|
||||
);
|
||||
const btcDevnetOracle = new PublicKey(
|
||||
'HovQMDrbAgAYPCmHVSrezcSmkMtXSSUsLDFANExrZh2J',
|
||||
);
|
||||
const btcDevnetMint = new PublicKey(DEVNET_MINTS['BTC']);
|
||||
const btcDevnetOracle = new PublicKey(DEVNET_ORACLES['BTC']);
|
||||
|
||||
//
|
||||
// Find existing or register new tokens
|
||||
|
@ -185,9 +184,7 @@ async function main() {
|
|||
//
|
||||
// Find existing or register a new serum3 market
|
||||
//
|
||||
const serumProgramId = new web3.PublicKey(
|
||||
'DESVgJVGajEgKGXhb6XmqDHGz3VjdgP7rEVESBgxmroY',
|
||||
);
|
||||
|
||||
const serumMarketExternalPk = new web3.PublicKey(
|
||||
'DW83EpHFywBxCHmyARxwj3nzxJd7MUdSeznmrdzZKNZB',
|
||||
);
|
||||
|
@ -200,7 +197,7 @@ async function main() {
|
|||
adminClient,
|
||||
group.publicKey,
|
||||
admin.publicKey,
|
||||
serumProgramId,
|
||||
DEVNET_SERUM3_PROGRAM_ID,
|
||||
serumMarketExternalPk,
|
||||
usdcBank.publicKey,
|
||||
btcBank.publicKey,
|
||||
|
@ -219,7 +216,7 @@ async function main() {
|
|||
group.publicKey,
|
||||
mangoAccount.publicKey,
|
||||
serum3Market.publicKey,
|
||||
serumProgramId,
|
||||
DEVNET_SERUM3_PROGRAM_ID,
|
||||
serumMarketExternalPk,
|
||||
user.publicKey,
|
||||
);
|
||||
|
@ -317,7 +314,7 @@ async function main() {
|
|||
userClient.program.provider.connection,
|
||||
serumMarketExternalPk,
|
||||
{ commitment: userClient.program.provider.connection.commitment },
|
||||
serumProgramId,
|
||||
DEVNET_SERUM3_PROGRAM_ID,
|
||||
);
|
||||
const serum3MarketExternalVaultSigner = await PublicKey.createProgramAddress(
|
||||
[
|
||||
|
@ -328,7 +325,7 @@ async function main() {
|
|||
8,
|
||||
),
|
||||
],
|
||||
serumProgramId,
|
||||
DEVNET_SERUM3_PROGRAM_ID,
|
||||
);
|
||||
const clientOrderId = Date.now();
|
||||
await serum3PlaceOrder(
|
||||
|
@ -338,7 +335,7 @@ async function main() {
|
|||
user.publicKey,
|
||||
mangoAccount.serum3[0].openOrders,
|
||||
serum3Market.publicKey,
|
||||
serumProgramId,
|
||||
DEVNET_SERUM3_PROGRAM_ID,
|
||||
serumMarketExternalPk,
|
||||
serum3MarketExternal.bidsAddress,
|
||||
serum3MarketExternal.asksAddress,
|
||||
|
|
|
@ -2,6 +2,12 @@ import { Provider, Wallet } from '@project-serum/anchor';
|
|||
import { Connection, Keypair, PublicKey } from '@solana/web3.js';
|
||||
import fs from 'fs';
|
||||
import { MangoClient } from './client';
|
||||
import {
|
||||
DEVNET_MINTS,
|
||||
DEVNET_ORACLES,
|
||||
DEVNET_SERUM3_MARKETS,
|
||||
DEVNET_SERUM3_PROGRAM_ID,
|
||||
} from './constants';
|
||||
|
||||
//
|
||||
// An example for admins based on high level api i.e. the client
|
||||
|
@ -31,20 +37,14 @@ async function main() {
|
|||
console.log(`Group ${group.publicKey}`);
|
||||
|
||||
// register token 0
|
||||
const btcDevnetMint = new PublicKey(
|
||||
'3UNBZ6o52WTWwjac2kPUb4FyodhU1vFkRJheu1Sh2TvU',
|
||||
);
|
||||
const btcDevnetOracle = new PublicKey(
|
||||
'HovQMDrbAgAYPCmHVSrezcSmkMtXSSUsLDFANExrZh2J',
|
||||
);
|
||||
const btcDevnetMint = new PublicKey(DEVNET_MINTS['BTC']);
|
||||
const btcDevnetOracle = new PublicKey(DEVNET_ORACLES['BTC']);
|
||||
try {
|
||||
await client.registerToken(group, btcDevnetMint, btcDevnetOracle, 0);
|
||||
} catch (error) {}
|
||||
|
||||
// stub oracle + register token 1
|
||||
const usdcDevnetMint = new PublicKey(
|
||||
'8FRFC6MoGGkMFQwngccyu69VnYbzykGeez7ignHVAFSN',
|
||||
);
|
||||
const usdcDevnetMint = new PublicKey(DEVNET_MINTS['USDC']);
|
||||
try {
|
||||
await client.createStubOracle(group, usdcDevnetMint, 1.0);
|
||||
} catch (error) {}
|
||||
|
@ -67,24 +67,21 @@ async function main() {
|
|||
}
|
||||
|
||||
// register serum market
|
||||
const serumProgramId = new PublicKey(
|
||||
'DESVgJVGajEgKGXhb6XmqDHGz3VjdgP7rEVESBgxmroY',
|
||||
);
|
||||
const serumMarketExternalPk = new PublicKey(
|
||||
'DW83EpHFywBxCHmyARxwj3nzxJd7MUdSeznmrdzZKNZB',
|
||||
DEVNET_SERUM3_MARKETS['BTC/USDC'],
|
||||
);
|
||||
try {
|
||||
} catch (error) {
|
||||
await client.serum3RegisterMarket(
|
||||
group,
|
||||
serumProgramId,
|
||||
DEVNET_SERUM3_PROGRAM_ID,
|
||||
serumMarketExternalPk,
|
||||
banks[0],
|
||||
banks[1],
|
||||
0,
|
||||
);
|
||||
}
|
||||
const markets = await client.serum3GetMarketForBaseAndQuote(
|
||||
const markets = await client.serum3GetMarket(
|
||||
group,
|
||||
banks[0].tokenIndex,
|
||||
banks[1].tokenIndex,
|
||||
|
|
|
@ -1,8 +1,13 @@
|
|||
import { Provider, Wallet } from '@project-serum/anchor';
|
||||
import { Connection, Keypair, PublicKey } from '@solana/web3.js';
|
||||
import fs from 'fs';
|
||||
import { MangoAccount } from './accounts/types/mangoAccount';
|
||||
import {
|
||||
Serum3OrderType,
|
||||
Serum3SelfTradeBehavior,
|
||||
Serum3Side,
|
||||
} from './accounts/types/serum3';
|
||||
import { MangoClient } from './client';
|
||||
import { DEVNET_GROUP, DEVNET_SERUM3_PROGRAM_ID } from './constants';
|
||||
|
||||
//
|
||||
// An example for users based on high level api i.e. the client
|
||||
|
@ -25,42 +30,39 @@ async function main() {
|
|||
console.log(`User ${userWallet.publicKey.toBase58()}`);
|
||||
|
||||
// fetch group
|
||||
const group = await client.getGroup(
|
||||
new PublicKey('6ACH752p6FsdLzuociVkmDwc3wJW8pcCoxZKfXJKfKcD'),
|
||||
);
|
||||
console.log(`Group ${group.publicKey}`);
|
||||
|
||||
// fetch banks
|
||||
const banks = await client.getBanksForGroup(group);
|
||||
for (const bank of banks) {
|
||||
console.log(`Bank ${bank.tokenIndex} ${bank.publicKey}`);
|
||||
}
|
||||
const group = await client.getGroup(new PublicKey(DEVNET_GROUP));
|
||||
console.log(`Group ${group.publicKey.toBase58()}`);
|
||||
|
||||
// create + fetch account
|
||||
let mangoAccounts: MangoAccount[] = [];
|
||||
let mangoAccount: MangoAccount;
|
||||
mangoAccounts = await client.getMangoAccount(group, user.publicKey);
|
||||
if (mangoAccounts.length === 0) {
|
||||
await client.createMangoAccount(group, 0);
|
||||
mangoAccounts = await client.getMangoAccount(group, user.publicKey);
|
||||
}
|
||||
mangoAccount = mangoAccounts[0];
|
||||
const mangoAccount = await client.getOrCreateMangoAccount(
|
||||
group,
|
||||
user.publicKey,
|
||||
0,
|
||||
);
|
||||
console.log(`MangoAccount ${mangoAccount.publicKey}`);
|
||||
|
||||
// deposit and withdraw
|
||||
console.log(`Depositing...1000`);
|
||||
await client.deposit(group, mangoAccount, banks[0], 1000);
|
||||
console.log(`Withdrawing...500`);
|
||||
await client.withdraw(group, mangoAccount, banks[0], 500, false);
|
||||
console.log(`Depositing...1000000`);
|
||||
await client.deposit(group, mangoAccount, 'USDC', 1000000);
|
||||
console.log(`Withdrawing...500000`);
|
||||
await client.withdraw(group, mangoAccount, 'USDC', 500000, false);
|
||||
|
||||
// serum3
|
||||
const markets = await client.serum3GetMarketForBaseAndQuote(
|
||||
console.log(`Placing serum3 order`);
|
||||
await client.serum3PlaceOrder(
|
||||
group,
|
||||
banks[1].tokenIndex,
|
||||
banks[0].tokenIndex,
|
||||
mangoAccount,
|
||||
DEVNET_SERUM3_PROGRAM_ID,
|
||||
'BTC/USDC',
|
||||
Serum3Side.bid,
|
||||
40000,
|
||||
1,
|
||||
1000000,
|
||||
Serum3SelfTradeBehavior.decrementTake,
|
||||
Serum3OrderType.limit,
|
||||
Date.now(),
|
||||
10,
|
||||
);
|
||||
console.log(markets);
|
||||
await client.serum3CreateOpenOrders(group, mangoAccount, markets[0]);
|
||||
|
||||
process.exit();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue