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);