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 ที่แสดงข้อมูลกลุ่มต่างๆ:

GroupVersionCluster
mainnet.1v3mainnet
devnet.2v3devnet
devnet.3v3devnet
BTC_ETH_SOL_SRM_USDCv2mainnet & devnet
BTC_ETH_USDTv2devnet
BTC_ETH_USDCv2testnet

Note

ถ้าเราต้องการใช้ v2 groups เราต้องใช้ v2 client library ซึ่งเราสามารถหามันได้ ที่นี่open in new window

Press </> button to view full source
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);
})();

วิธีสร้าง Mango Account

Mango Account จะเกี่ยวข้องกับ a Mango Group, และมันจะเก็บ tokens ของเรา และทำให้เรา trade ได้ใน Group’s markets นั้น Yเราสามารถหาข้อมูลอ้างอิงเพิ่มเติมได้ ที่นี่open in new window.

Press </> button to view full source
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
  );
})();
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(())
  }
}

วิธีฝาก (deposit) USDC เข้าไปใน Mango Account

หลังจากสร้าง mango account แล้วเราต้องลงทุน tokens เข้าไปด้วยเพื่อเอาไว้ trade. เราสามารถหาข้อมูลของ deposit method ได้ ที่นี่open in new window.

Press </> button to view full source
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)
  );
})();

วิธีตั้ง spot order

Mango ติดต่อกับ Serum Protocol เพื่อวาง spot orders บน markets เราจะวาง spot order ได้ถ้าทำตามนี้ เราสามารถหาข้ออมูลอ้างอิงของ placeSpotOrder function ได้ ที่นี่open in new window. Mango มี config file ที่มี่ข้อมูลเกี่ญซกับ groups, markets, tokens และ oracles, เราสามารถหาจ้อมูลได้ ที่นี่open in new window. เราได้ข้อมูลจาก file นั้นเพื่อหา group และ market ที่ถต้องการได้

Press </> button to view full source
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
  );
})();

วิธี 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 ที่นี่open in new window

Press </> button to view full source
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);
})();

วิธีดึงข้อมูลราคาขาย (asks)

Mango ใช้ข้อมูล market จาก Serum Protocol เพื่อดึงข้อมูลราคาขาย asks. เราสามารถดึงข้อมูลได้โดยตรงจาก Serum เพื่อทำงานบน Mango เราสามารถอ่านรายละเอียดเพิ่มเกี่ยวกับ Serum's markets ได้ ที่นี่open in new window

Press </> button to view full source
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);
})();

แหล่งข้อมูลอื่น

Last Updated:
Contributors: Todsaporn Banjerdkit