Mango Markets
Mango offre un lieu unique pour prêter, emprunter, échanger et négocier des crypto-actifs par le biais d'un mécanisme de gestion des risques on-chain. Vous pouvez vous connecter au programme de Mango à l'aide des bibliothèques API Client. Vous aurez également besoin de la bibliothèque API javascript de Solana.
"@blockworks-foundation/mango-client": "^3.3.27",
"@solana/web3.js": "^1.37.0"
Comment récupérer un Groupe Mango
Un groupe Mango est un panier de jetons à marges croisées. Il contient des informations générales sur le marché des jetons, les dex de Serum, les marchés perp, les oracles, les fonds d'assurance et les vaults de frais. Chaque version de Mango Markets utilise un groupe Mango différent contenant des jetons différents. Le groupe v3 actuel mainnet.1
. Voici un tableau présentant les différents groupes :
Groupe | 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 |
Remarque
Si vous souhaitez utiliser les groupes v2, vous devrez utiliser la bibliothèque client v2. Vous pouvez la trouver ici
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);
Comment créer un Compte Mango
Un Compte Mango est associé à un Groupe Mango, il détient vos jetons et vous permet de négocier sur les marchés de ce groupe. Vous pouvez trouver la référence ici.
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(),
]
)?;
Comment déposer des USDC sur un Compte Mango
Après avoir créé un compte mango, vous devrez l'approvisionner en jetons pour pouvoir trader. Vous pouvez trouver la référence de la procédure de dépôt ici.
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)
);
Comment placer un ordre spot
Mango interagit avec le Protocole Serum pour placer des ordres spot sur les marchés. Vous pouvez passer un ordre spot en procédant ainsi. Vous pouvez trouver la référence de la fonction placeSpotOrder ici. Mango possède un fichier de configuration qui contient des informations sur les groupes, les marchés, les jetons et les oracles que vous pouvez trouver ici. Nous utilisons les informations de ce dossier pour trouver le bon groupe et le bon marché.
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
);
Comment charger les offres
Mango utilise les informations de marché du Protocole Serum pour charger les offres. Vous pouvez les charger directement depuis Serum pour travailler avec sur Mango. Vous pouvez en savoir plus sur les marchés de Serum ici
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);
Comment charger les demandes
Mango utilise les informations de marché du Protocole Serum pour charger les demandes. Vous pouvez les charger directement depuis Serum pour travailler avec sur Mango. Vous pouvez en savoir plus sur les marchés de Serum ici
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);