Mango Markets
Mango รวม lend, borrow, swap, และ leverage trade crypto assets ไว้ที่เดียวบน on-chain risk engine. เราสามารถต่อกับ Mango's on-chain program โดยใช้ Client API libraries. เรายังต้องการ Solana javascript API library ด้วย
"@blockworks-foundation/mango-client": "^3.3.27",
"@solana/web3.js": "^1.37.0"
วิธีดึงข้อมูล Mango Group
mango group คือตะกร้า (basket) ของ cross-margined tokens. มันจะมีข้อมูลกว้างๆ ของ market เกี่ยวกับ tokens, serum dex markets, perp markets, oracles, insurance fund และ fees vaults. แต่ละ version ของ Mango Markets ใช้ Mango Group ที่แตกต่างกัน และมี tokens ที่แตกต่างกัน ใน v3 ปัจจุบันนั้นมีชื่อ group คือ mainnet.1
นี่คือตาราง table ที่แสดงข้อมูลกลุ่มต่างๆ:
Group | Version | Cluster |
---|---|---|
mainnet.1 | v3 | mainnet |
devnet.2 | v3 | devnet |
devnet.3 | v3 | devnet |
BTC_ETH_SOL_SRM_USDC | v2 | mainnet & devnet |
BTC_ETH_USDT | v2 | devnet |
BTC_ETH_USDC | v2 | testnet |
Note
ถ้าเราต้องการใช้ v2 groups เราต้องใช้ v2 client library ซึ่งเราสามารถหามันได้ ที่นี่
import { Connection, PublicKey } from "@solana/web3.js";
import {
IDS,
MangoClient,
Config,
I80F48,
} from "@blockworks-foundation/mango-client";
(async () => {
const cluster = "devnet";
const group = "devnet.3";
const config = new Config(IDS);
const groupConfig = config.getGroup(cluster, group);
if (!groupConfig) {
throw new Error("unable to get mango group config");
}
const mangoGroupKey = groupConfig.publicKey;
const clusterData = IDS.groups.find((g) => {
return g.name == group && g.cluster == cluster;
});
const mangoProgramIdPk = new PublicKey(clusterData.mangoProgramId);
const clusterUrl = IDS.cluster_urls[cluster];
const connection = new Connection(clusterUrl, "singleGossip");
const client = new MangoClient(connection, mangoProgramIdPk);
const mangoGroup = await client.getMangoGroup(mangoGroupKey);
})();
const mangoGroup = await client.getMangoGroup(mangoGroupKey);
วิธีสร้าง Mango Account
Mango Account จะเกี่ยวข้องกับ a Mango Group, และมันจะเก็บ tokens ของเรา และทำให้เรา trade ได้ใน Group’s markets นั้น Yเราสามารถหาข้อมูลอ้างอิงเพิ่มเติมได้ ที่นี่.
import { useWallet } from "@solana/wallet-adapter-react";
import { Connection, PublicKey } from "@solana/web3.js";
import { IDS, MangoClient, Config } from "@blockworks-foundation/mango-client";
(async () => {
const { wallet } = useWallet();
const cluster = "devnet";
const group = "devnet.3";
const config = new Config(IDS);
const groupConfig = config.getGroup(cluster, group);
if (!groupConfig) {
throw new Error("unable to get mango group config");
}
const mangoGroupKey = groupConfig.publicKey;
const clusterData = IDS.groups.find((g) => {
return g.name == group && g.cluster == cluster;
});
const mangoProgramIdPk = new PublicKey(clusterData.mangoProgramId);
const clusterUrl = IDS.cluster_urls[cluster];
const connection = new Connection(clusterUrl, "singleGossip");
const client = new MangoClient(connection, mangoProgramIdPk);
const mangoGroup = await client.getMangoGroup(mangoGroupKey);
const mangoAccount = await client.createMangoAccount(
mangoGroup,
wallet?.adapter,
23
);
})();
const mangoAccount = await client.createMangoAccount(
mangoGroup,
wallet.adapter,
23
);
use borsh::{BorshDeserialize, BorshSerialize};
use solana_program::{
account_info::{next_account_info, AccountInfo},
entrypoint::ProgramResult,
msg,
program::{invoke_signed},
program_error::ProgramError,
pubkey::Pubkey,
system_instruction,
system_program::ID as SYSTEM_PROGRAM_ID,
sysvar::{rent::Rent, Sysvar},
};
// Add this to Cargo.toml to be able to use the mango program repository as a crate
// mango = { version = "3.4.2", git = "https://github.com/blockworks-foundation/mango-v3.git", default-features=false, features = ["no-entrypoint", "program"] }
use mango::instruction::MangoInstruction;
use crate::instruction::ProgramInstruction;
pub struct Processor {}
impl Processor {
pub fn process_instruction(
program_id: &Pubkey,
accounts: &[AccountInfo],
instruction_data: &[u8]
) -> ProgramResult {
let instruction = ProgramInstruction::try_from_slice(instruction_data)
.map_err(|_| ProgramError::InvalidInstructionData)?;
let accounts_iter = &mut accounts.iter();
match instruction {
ProgramInstruction::CreateMangoAccount { account_num } => {
msg!("Instruction: CreateMangoAccount");
let mango_group_ai = next_account_info(accounts_iter)?;
let mango_account_ai = next_account_info(accounts_iter)?;
let user = next_account_info(accounts_iter)?;
let mango_program = next_account_info(accounts_iter)?;
let system_program = next_account_info(accounts_iter)?;
invoke(
&mango::instruction::create_mango_account(
*mango_program.key,
*mango_account_ai.key,
*user.key,
*system_program.key,
*user.key,
*account_num
),
&[
mango_program.clone(),
user.clone(),
system_program.clone(),
mango_account_ai.clone(),
]
)?;
}
}
Ok(())
}
}
invoke(
&mango_v3::instruction::create_mango_account(
*mango_program.key,
*mango_account_ai.key,
*mango_account_ai.key,
*user.key,
*system_program.key,
*user.key,
*account_num
),
&[
mango_program.clone(),
user.clone(),
system_program.clone(),
mango_account_ai.clone(),
]
)?;
วิธีฝาก (deposit) USDC เข้าไปใน Mango Account
หลังจากสร้าง mango account แล้วเราต้องลงทุน tokens เข้าไปด้วยเพื่อเอาไว้ trade. เราสามารถหาข้อมูลของ deposit method ได้ ที่นี่.
import { useWallet } from "@solana/wallet-adapter-react";
import { Connection, PublicKey } from "@solana/web3.js";
import {
IDS,
MangoClient,
Config,
getTokenAccountsByOwnerWithWrappedSol,
} from "@blockworks-foundation/mango-client";
(async () => {
const { wallet } = useWallet();
const cluster = "devnet";
const group = "devnet.3";
const config = new Config(IDS);
const groupConfig = config.getGroup(cluster, group);
if (!groupConfig) {
throw new Error("unable to get mango group config");
}
const mangoGroupKey = groupConfig.publicKey;
const clusterData = IDS.groups.find((g) => {
return g.name == group && g.cluster == cluster;
});
const mangoProgramIdPk = new PublicKey(clusterData.mangoProgramId);
const clusterUrl = IDS.cluster_urls[cluster];
const connection = new Connection(clusterUrl, "singleGossip");
const client = new MangoClient(connection, mangoProgramIdPk);
const mangoGroup = await client.getMangoGroup(mangoGroupKey);
const mangoAccount = await client.createMangoAccount(
mangoGroup,
wallet?.adapter,
23
);
const tokenAccounts = await getTokenAccountsByOwnerWithWrappedSol(
connection,
wallet.adapter.publicKey
);
const tokenAccount = tokenAccounts.find((account) =>
account.mint.equals(
new PublicKey("EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v")
)
); // USDC mint address
const tokenIndex = mangoGroup.getTokenIndex(tokenAccount.mint);
await client.deposit(
mangoGroup,
mangoAccount,
wallet?.adapter,
mangoGroup.tokens[tokenIndex].rootBank,
mangoGroup.rootBankAccounts[tokenIndex].nodeBankAccounts[0].publicKey,
mangoGroup.rootBankAccounts[tokenIndex].nodeBankAccounts[0].vault,
tokenAccount.publicKey,
Number(4)
);
})();
await client.deposit(
mangoGroup,
mangoAccount,
wallet?.adapter,
mangoGroup.tokens[tokenIndex].rootBank,
mangoGroup.rootBankAccounts[tokenIndex].nodeBankAccounts[0].publicKey,
mangoGroup.rootBankAccounts[tokenIndex].nodeBankAccounts[0].vault,
tokenAccount.publicKey,
Number(4)
);
วิธีตั้ง spot order
Mango ติดต่อกับ Serum Protocol เพื่อวาง spot orders บน markets เราจะวาง spot order ได้ถ้าทำตามนี้ เราสามารถหาข้ออมูลอ้างอิงของ placeSpotOrder function ได้ ที่นี่. Mango มี config file ที่มี่ข้อมูลเกี่ญซกับ groups, markets, tokens และ oracles, เราสามารถหาจ้อมูลได้ ที่นี่. เราได้ข้อมูลจาก file นั้นเพื่อหา group และ market ที่ถต้องการได้
import { useWallet } from "@solana/wallet-adapter-react";
import { Connection, PublicKey } from "@solana/web3.js";
import { Market } from "@project-serum/serum";
import {
IDS,
MangoClient,
Config,
getSpotMarketByBaseSymbol,
} from "@blockworks-foundation/mango-client";
(async () => {
const { wallet } = useWallet();
const cluster = "devnet";
const group = "devnet.3";
const config = new Config(IDS);
const groupConfig = config.getGroup(cluster, group);
if (!groupConfig) {
throw new Error("unable to get mango group config");
}
const mangoGroupKey = groupConfig.publicKey;
const clusterData = IDS.groups.find((g) => {
return g.name == group && g.cluster == cluster;
});
const mangoProgramIdPk = new PublicKey(clusterData.mangoProgramId);
const clusterUrl = IDS.cluster_urls[cluster];
const connection = new Connection(clusterUrl, "singleGossip");
const client = new MangoClient(connection, mangoProgramIdPk);
const mangoGroup = await client.getMangoGroup(mangoGroupKey);
const mangoAccount = await client.createMangoAccount(
mangoGroup,
wallet?.adapter,
23
);
const marketConfig = getSpotMarketByBaseSymbol(groupConfig, "SOL");
const market = await Market.load(
connection,
marketConfig.publicKey,
{},
groupConfig.serumProgramId
);
await client.placeSpotOrder(
mangoGroup,
mangoAccount,
mangoGroup.mangoCache,
market,
wallet?.adapter,
"buy",
3,
3.5
);
})();
await client.placeSpotOrder(
mangoGroup,
mangoAccount,
mangoGroup.mangoCache,
market,
wallet?.adapter,
"buy",
3,
3.5
);
วิธี load bids
Mango uses the market information from Serum Protocol to load bids. เราสามารถ load them directly from Serum to work with on Mango. เราสามารถ find out more about Serum's markets ที่นี่
import { Connection, PublicKey } from "@solana/web3.js";
import { Market } from "@project-serum/serum";
import {
IDS,
Config,
getSpotMarketByBaseSymbol,
} from "@blockworks-foundation/mango-client";
(async () => {
const cluster = "devnet";
const group = "devnet.3";
const config = new Config(IDS);
const groupConfig = config.getGroup(cluster, group);
if (!groupConfig) {
throw new Error("unable to get mango group config");
}
const clusterUrl = IDS.cluster_urls[cluster];
const connection = new Connection(clusterUrl, "singleGossip");
const marketConfig = getSpotMarketByBaseSymbol(groupConfig, "SOL");
const market = await Market.load(
connection,
marketConfig.publicKey,
{},
groupConfig.serumProgramId
);
const bids = market.loadBids(connection);
})();
const bids = market.loadBids(connection);
วิธีดึงข้อมูลราคาขาย (asks)
Mango ใช้ข้อมูล market จาก Serum Protocol เพื่อดึงข้อมูลราคาขาย asks. เราสามารถดึงข้อมูลได้โดยตรงจาก Serum เพื่อทำงานบน Mango เราสามารถอ่านรายละเอียดเพิ่มเกี่ยวกับ Serum's markets ได้ ที่นี่
import { Connection, PublicKey } from "@solana/web3.js";
import { Market } from "@project-serum/serum";
import {
IDS,
MangoClient,
Config,
getSpotMarketByBaseSymbol,
} from "@blockworks-foundation/mango-client";
(async () => {
const cluster = "devnet";
const group = "devnet.3";
const config = new Config(IDS);
const groupConfig = config.getGroup(cluster, group);
if (!groupConfig) {
throw new Error("unable to get mango group config");
}
const clusterUrl = IDS.cluster_urls[cluster];
const connection = new Connection(clusterUrl, "singleGossip");
const marketConfig = getSpotMarketByBaseSymbol(groupConfig, "SOL");
const market = await Market.load(
connection,
marketConfig.publicKey,
{},
groupConfig.serumProgramId
);
const asks = await market.loadBids(connection);
})();
const asks = await market.loadBids(connection);