Mango Markets
Mangoは、オンチェーンリスク エンジンを介して、取引暗号資産を貸与、借入、交換、および活用するための単一の場を提供します。 クライアントAPIライブラリを使用して、Mangoのオンチェーンプログラムに接続できます。Solana JavaScript APIライブラリも必要です。
"@blockworks-foundation/mango-client": "^3.3.27",
"@solana/web3.js": "^1.37.0"
Mango Groupの取得方法
Mango groupはクロスマージントークンのバスケットで、トークン、Serum dex market、perp market、Oracle、Insurance fund、Fees vaultに関する幅広い市場情報を保持しています。 Mango Markets の各バージョンは、異なるトークンを含む異なる Mango Group を使用します。現在の v3 グループはmainnet.1 です。さまざまなグループを示す表を次に示します:
| 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 グループを使用する場合は、v2 クライアント ライブラリを使用する必要があります。ここで見つけることができます
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は Mango Groupに関連付けられており、トークンを保持し、そのグループの市場での取引を可能にします。こちらからリファレンスを確認できます。
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(),
  ]
)?;
USDCをMango Accountに入金する方法
Mango accountアカウントを作成したら、取引用のトークンで資金を供給する必要があります。 入金方法のリファレンスはこちら。
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)
);
スポット注文の方法
MangoはSerum Protocolと対話し、市場でスポット注文を出します。これにより、スポット注文を出すことができます。placeSpotOrder関数のリファレンスはこちら。 Mangoには、グループ、マーケット、トークン、およびOracleに関する情報を含む構成ファイルがあります。 ここで見つけることができます。そのファイルの情報を使用して、適切なグループと市場を見つけます。
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
);
売値の読込方法
MangoはSerum Protocolから得た市場情報を使用して売値を読み込みます。Serumから直接読み込み、Mangoで操作できます。Serumの市場に関しての より詳しい情報はこちら。
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);
買値の読込方法
MangoはSerum Protocolから得た市場情報を使用して買値を読み込みます。 Serumから直接読み込み、Mangoで操作できます。Serumの市場の詳しい情報はこちら。
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);