Merge remote-tracking branch 'origin/deploy' into dev
This commit is contained in:
commit
0aabd28cdc
|
@ -8262,14 +8262,28 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "changeAmount",
|
"name": "changeAmount",
|
||||||
|
"docs": [
|
||||||
|
"The amount by which the user's token position changed at the end",
|
||||||
|
"",
|
||||||
|
"So if the user repaid the approved_amount in full, it'd be 0.",
|
||||||
|
"",
|
||||||
|
"Does NOT include the loan_origination_fee or deposit_fee, so the true",
|
||||||
|
"change is `change_amount - loan_origination_fee - deposit_fee`."
|
||||||
|
],
|
||||||
"type": "i128"
|
"type": "i128"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "loan",
|
"name": "loan",
|
||||||
|
"docs": [
|
||||||
|
"The amount that was a loan (<= approved_amount, depends on user's deposits)"
|
||||||
|
],
|
||||||
"type": "i128"
|
"type": "i128"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "loanOriginationFee",
|
"name": "loanOriginationFee",
|
||||||
|
"docs": [
|
||||||
|
"The fee paid on the loan, not included in `loan` or `change_amount`"
|
||||||
|
],
|
||||||
"type": "i128"
|
"type": "i128"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -8286,7 +8300,19 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "depositFee",
|
"name": "depositFee",
|
||||||
|
"docs": [
|
||||||
|
"Deposit fee paid for positive change_amount.",
|
||||||
|
"",
|
||||||
|
"Not factored into change_amount."
|
||||||
|
],
|
||||||
"type": "i128"
|
"type": "i128"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "approvedAmount",
|
||||||
|
"docs": [
|
||||||
|
"The amount that was transfered out to the user"
|
||||||
|
],
|
||||||
|
"type": "u64"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@blockworks-foundation/mango-v4",
|
"name": "@blockworks-foundation/mango-v4",
|
||||||
"version": "0.18.14",
|
"version": "0.19.14",
|
||||||
"description": "Typescript Client for mango-v4 program.",
|
"description": "Typescript Client for mango-v4 program.",
|
||||||
"repository": "https://github.com/blockworks-foundation/mango-v4",
|
"repository": "https://github.com/blockworks-foundation/mango-v4",
|
||||||
"author": {
|
"author": {
|
||||||
|
|
|
@ -13,7 +13,8 @@
|
||||||
"mint": "So11111111111111111111111111111111111111112",
|
"mint": "So11111111111111111111111111111111111111112",
|
||||||
"tokenIndex": 5,
|
"tokenIndex": 5,
|
||||||
"bankNum": 0,
|
"bankNum": 0,
|
||||||
"active": true
|
"active": true,
|
||||||
|
"decimals": 99999
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "USDT",
|
"name": "USDT",
|
||||||
|
@ -21,7 +22,8 @@
|
||||||
"mint": "Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB",
|
"mint": "Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB",
|
||||||
"tokenIndex": 1,
|
"tokenIndex": 1,
|
||||||
"bankNum": 0,
|
"bankNum": 0,
|
||||||
"active": true
|
"active": true,
|
||||||
|
"decimals": 99999
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "USDC",
|
"name": "USDC",
|
||||||
|
@ -29,7 +31,8 @@
|
||||||
"mint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
|
"mint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
|
||||||
"tokenIndex": 0,
|
"tokenIndex": 0,
|
||||||
"bankNum": 0,
|
"bankNum": 0,
|
||||||
"active": true
|
"active": true,
|
||||||
|
"decimals": 99999
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "BTC",
|
"name": "BTC",
|
||||||
|
@ -37,7 +40,8 @@
|
||||||
"mint": "9n4nbM75f5Ui33ZbPYXn59EwSgE8CGsHtAeTH5YFeJ9E",
|
"mint": "9n4nbM75f5Ui33ZbPYXn59EwSgE8CGsHtAeTH5YFeJ9E",
|
||||||
"tokenIndex": 2,
|
"tokenIndex": 2,
|
||||||
"bankNum": 0,
|
"bankNum": 0,
|
||||||
"active": true
|
"active": true,
|
||||||
|
"decimals": 99999
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "soETH",
|
"name": "soETH",
|
||||||
|
@ -45,7 +49,8 @@
|
||||||
"mint": "2FPyTwcZLUg1MDrwsyoP4D6s1tM7hAkHYRjkNb5w6Pxk",
|
"mint": "2FPyTwcZLUg1MDrwsyoP4D6s1tM7hAkHYRjkNb5w6Pxk",
|
||||||
"tokenIndex": 4,
|
"tokenIndex": 4,
|
||||||
"bankNum": 0,
|
"bankNum": 0,
|
||||||
"active": true
|
"active": true,
|
||||||
|
"decimals": 99999
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "ETH",
|
"name": "ETH",
|
||||||
|
@ -53,7 +58,8 @@
|
||||||
"mint": "7vfCXTUXx5WJV5JADk17DUJ4ksgau7utNKj4b963voxs",
|
"mint": "7vfCXTUXx5WJV5JADk17DUJ4ksgau7utNKj4b963voxs",
|
||||||
"tokenIndex": 3,
|
"tokenIndex": 3,
|
||||||
"bankNum": 0,
|
"bankNum": 0,
|
||||||
"active": true
|
"active": true,
|
||||||
|
"decimals": 99999
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "MSOL",
|
"name": "MSOL",
|
||||||
|
@ -61,7 +67,8 @@
|
||||||
"mint": "mSoLzYCxHdYgdzU16g5QSh3i5K3z3KZK7ytfqcJm7So",
|
"mint": "mSoLzYCxHdYgdzU16g5QSh3i5K3z3KZK7ytfqcJm7So",
|
||||||
"tokenIndex": 6,
|
"tokenIndex": 6,
|
||||||
"bankNum": 0,
|
"bankNum": 0,
|
||||||
"active": true
|
"active": true,
|
||||||
|
"decimals": 99999
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"stubOracles": [
|
"stubOracles": [
|
||||||
|
|
|
@ -662,7 +662,7 @@ async function createAndPopulateAlt() {
|
||||||
);
|
);
|
||||||
|
|
||||||
console.log(`ALT: set at index 0 for group...`);
|
console.log(`ALT: set at index 0 for group...`);
|
||||||
sig = await client.altSet(group, createIx[1], 0);
|
sig = (await client.altSet(group, createIx[1], 0)).signature;
|
||||||
console.log(`...https://explorer.solana.com/tx/${sig}`);
|
console.log(`...https://explorer.solana.com/tx/${sig}`);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error);
|
console.log(error);
|
||||||
|
|
|
@ -0,0 +1,245 @@
|
||||||
|
import { AnchorProvider, Wallet } from '@coral-xyz/anchor';
|
||||||
|
import { Connection, Keypair, PublicKey } from '@solana/web3.js';
|
||||||
|
import fs from 'fs';
|
||||||
|
import { TokenIndex } from '../src/accounts/bank';
|
||||||
|
import { Group } from '../src/accounts/group';
|
||||||
|
import { MangoClient } from '../src/client';
|
||||||
|
import { DefaultTokenRegisterParams } from '../src/clientIxParamBuilder';
|
||||||
|
import { MANGO_V4_ID } from '../src/constants';
|
||||||
|
import { toNative } from '../src/utils';
|
||||||
|
|
||||||
|
const MAINNET_MINTS = new Map([
|
||||||
|
['USDC', 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v'], // 0
|
||||||
|
['SOL', 'So11111111111111111111111111111111111111112'], // 1
|
||||||
|
]);
|
||||||
|
const MAINNET_ORACLES = new Map([
|
||||||
|
['USDC', 'Gnt27xtC473ZT2Mw5u8wZ68Z3gULkSTb5DuxJy7eJotD'],
|
||||||
|
['SOL', 'H6ARHf6YXhGYeQfUzQNGk6rDNnLBQKrenN712K4AQJEG'],
|
||||||
|
]);
|
||||||
|
const MAINNET_SERUM3_MARKETS = new Map([
|
||||||
|
['SOL/USDC', '8BnEgHoWFysVcuFFX7QztDmzuH8r5ZFvyP3sYwn1XTh6'],
|
||||||
|
]);
|
||||||
|
const {
|
||||||
|
MB_CLUSTER_URL,
|
||||||
|
MB_PAYER_KEYPAIR,
|
||||||
|
GROUP_NUM,
|
||||||
|
}: {
|
||||||
|
MB_CLUSTER_URL: string;
|
||||||
|
MB_PAYER_KEYPAIR: string;
|
||||||
|
GROUP_NUM: number;
|
||||||
|
} = process.env as any;
|
||||||
|
|
||||||
|
const defaultOracleConfig = {
|
||||||
|
confFilter: 0.1,
|
||||||
|
maxStalenessSlots: null,
|
||||||
|
};
|
||||||
|
|
||||||
|
const defaultInterestRate = {
|
||||||
|
adjustmentFactor: 0.0,
|
||||||
|
util0: 0.0,
|
||||||
|
rate0: 0.0,
|
||||||
|
util1: 0.0,
|
||||||
|
rate1: 0.0,
|
||||||
|
maxRate: 0.51,
|
||||||
|
};
|
||||||
|
|
||||||
|
const defaultTokenParams = {
|
||||||
|
...DefaultTokenRegisterParams,
|
||||||
|
oracleConfig: defaultOracleConfig,
|
||||||
|
interestRateParams: defaultInterestRate,
|
||||||
|
loanOriginationFeeRate: 0.0,
|
||||||
|
loanFeeRate: 0.0,
|
||||||
|
initAssetWeight: 0,
|
||||||
|
maintAssetWeight: 0,
|
||||||
|
initLiabWeight: 1,
|
||||||
|
maintLiabWeight: 1,
|
||||||
|
liquidationFee: 0,
|
||||||
|
minVaultToDepositsRatio: 1,
|
||||||
|
netBorrowLimitPerWindowQuote: 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
async function buildAdminClient(): Promise<[MangoClient, Keypair]> {
|
||||||
|
const admin = Keypair.fromSecretKey(
|
||||||
|
Buffer.from(JSON.parse(fs.readFileSync(MB_PAYER_KEYPAIR!, 'utf-8'))),
|
||||||
|
);
|
||||||
|
const options = AnchorProvider.defaultOptions();
|
||||||
|
const connection = new Connection(MB_CLUSTER_URL!, options);
|
||||||
|
const adminWallet = new Wallet(admin);
|
||||||
|
const adminProvider = new AnchorProvider(connection, adminWallet, options);
|
||||||
|
const client = await MangoClient.connect(
|
||||||
|
adminProvider,
|
||||||
|
'mainnet-beta',
|
||||||
|
MANGO_V4_ID['mainnet-beta'],
|
||||||
|
{
|
||||||
|
idsSource: 'get-program-accounts',
|
||||||
|
},
|
||||||
|
);
|
||||||
|
return [client, admin];
|
||||||
|
}
|
||||||
|
|
||||||
|
async function buildUserClient(): Promise<[MangoClient, Group, Keypair]> {
|
||||||
|
const options = AnchorProvider.defaultOptions();
|
||||||
|
const connection = new Connection(MB_CLUSTER_URL!, options);
|
||||||
|
|
||||||
|
const user = Keypair.fromSecretKey(
|
||||||
|
Buffer.from(JSON.parse(fs.readFileSync(MB_PAYER_KEYPAIR, 'utf-8'))),
|
||||||
|
);
|
||||||
|
const userWallet = new Wallet(user);
|
||||||
|
const userProvider = new AnchorProvider(connection, userWallet, options);
|
||||||
|
|
||||||
|
const client = await MangoClient.connect(
|
||||||
|
userProvider,
|
||||||
|
'mainnet-beta',
|
||||||
|
MANGO_V4_ID['mainnet-beta'],
|
||||||
|
);
|
||||||
|
const group = await client.getGroupForCreator(user.publicKey, GROUP_NUM);
|
||||||
|
return [client, group, user];
|
||||||
|
}
|
||||||
|
|
||||||
|
async function createGroup(): Promise<void> {
|
||||||
|
const result = await buildAdminClient();
|
||||||
|
const client = result[0];
|
||||||
|
const admin = result[1];
|
||||||
|
|
||||||
|
const insuranceMint = new PublicKey(MAINNET_MINTS.get('USDC')!);
|
||||||
|
await client.groupCreate(GROUP_NUM, false, 2, insuranceMint);
|
||||||
|
const group = await client.getGroupForCreator(admin.publicKey, GROUP_NUM);
|
||||||
|
console.log(`...registered group ${group.publicKey}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function registerTokens(): Promise<void> {
|
||||||
|
const result = await buildAdminClient();
|
||||||
|
const client = result[0];
|
||||||
|
const admin = result[1];
|
||||||
|
|
||||||
|
const group = await client.getGroupForCreator(admin.publicKey, GROUP_NUM);
|
||||||
|
|
||||||
|
const usdcMainnetMint = new PublicKey(MAINNET_MINTS.get('USDC')!);
|
||||||
|
const usdcMainnetOracle = new PublicKey(MAINNET_ORACLES.get('USDC')!);
|
||||||
|
let sig = await client.tokenRegister(
|
||||||
|
group,
|
||||||
|
usdcMainnetMint,
|
||||||
|
usdcMainnetOracle,
|
||||||
|
0,
|
||||||
|
'USDC',
|
||||||
|
defaultTokenParams,
|
||||||
|
);
|
||||||
|
console.log(`registered usdc ${sig}`);
|
||||||
|
|
||||||
|
const solMainnetMint = new PublicKey(MAINNET_MINTS.get('SOL')!);
|
||||||
|
const solMainnetOracle = new PublicKey(MAINNET_ORACLES.get('SOL')!);
|
||||||
|
sig = await client.tokenRegister(
|
||||||
|
group,
|
||||||
|
solMainnetMint,
|
||||||
|
solMainnetOracle,
|
||||||
|
1,
|
||||||
|
'SOL',
|
||||||
|
defaultTokenParams,
|
||||||
|
);
|
||||||
|
console.log(`registered sol ${sig}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function registerSerum3Market(): Promise<void> {
|
||||||
|
const result = await buildAdminClient();
|
||||||
|
const client = result[0];
|
||||||
|
const admin = result[1];
|
||||||
|
|
||||||
|
const group = await client.getGroupForCreator(admin.publicKey, GROUP_NUM);
|
||||||
|
await client.serum3RegisterMarket(
|
||||||
|
group,
|
||||||
|
new PublicKey(MAINNET_SERUM3_MARKETS.get('SOL/USDC')!),
|
||||||
|
group.getFirstBankByTokenIndex(1 as TokenIndex),
|
||||||
|
group.getFirstBankByTokenIndex(0 as TokenIndex),
|
||||||
|
0,
|
||||||
|
'SOL/USDC',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function doUserAction(): Promise<void> {
|
||||||
|
const result = await buildUserClient();
|
||||||
|
const client = result[0];
|
||||||
|
const group = result[1];
|
||||||
|
const user = result[2];
|
||||||
|
|
||||||
|
let mangoAccount = await client.getMangoAccountForOwner(
|
||||||
|
group,
|
||||||
|
user.publicKey,
|
||||||
|
0,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!mangoAccount) {
|
||||||
|
await client.createMangoAccount(group, 0);
|
||||||
|
mangoAccount = await client.getMangoAccountForOwner(
|
||||||
|
group,
|
||||||
|
user.publicKey,
|
||||||
|
0,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// await client.tokenDeposit(
|
||||||
|
// group,
|
||||||
|
// mangoAccount!,
|
||||||
|
// new PublicKey(MAINNET_MINTS.get('SOL')!),
|
||||||
|
// 0.01,
|
||||||
|
// );
|
||||||
|
|
||||||
|
// await client.tcsStopLossOnDeposit(
|
||||||
|
// group,
|
||||||
|
// mangoAccount!,
|
||||||
|
// group.getFirstBankByTokenIndex(1 as TokenIndex),
|
||||||
|
// group.getFirstBankByTokenIndex(0 as TokenIndex),
|
||||||
|
// group.getFirstBankByTokenIndex(1 as TokenIndex).uiPrice * 1.1,
|
||||||
|
// false,
|
||||||
|
// null,
|
||||||
|
// null,
|
||||||
|
// null,
|
||||||
|
// );
|
||||||
|
|
||||||
|
await mangoAccount?.reload(client);
|
||||||
|
mangoAccount
|
||||||
|
?.tokenConditionalSwapsActive()
|
||||||
|
.map((tcs) => console.log(tcs.toString(group)));
|
||||||
|
}
|
||||||
|
|
||||||
|
async function doUserAction2(): Promise<void> {
|
||||||
|
const result = await buildUserClient();
|
||||||
|
const client = result[0];
|
||||||
|
const group = result[1];
|
||||||
|
const user = result[2];
|
||||||
|
|
||||||
|
let mangoAccount = await client.getMangoAccountForOwner(
|
||||||
|
group,
|
||||||
|
user.publicKey,
|
||||||
|
1,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!mangoAccount) {
|
||||||
|
await client.createMangoAccount(group, 1);
|
||||||
|
mangoAccount = await client.getMangoAccountForOwner(
|
||||||
|
group,
|
||||||
|
user.publicKey,
|
||||||
|
1,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
await client.tokenDeposit(
|
||||||
|
group,
|
||||||
|
mangoAccount!,
|
||||||
|
new PublicKey(MAINNET_MINTS.get('USDC')!),
|
||||||
|
5,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function main(): Promise<void> {
|
||||||
|
try {
|
||||||
|
// await createGroup();
|
||||||
|
// await registerTokens();
|
||||||
|
// await registerSerum3Market();
|
||||||
|
await doUserAction();
|
||||||
|
// await doUserAction2();
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
main();
|
|
@ -0,0 +1,72 @@
|
||||||
|
import { PublicKey } from '@solana/web3.js';
|
||||||
|
import { Group } from '../src/accounts/group';
|
||||||
|
import { isSwitchboardOracle } from '../src/accounts/oracle';
|
||||||
|
import { MangoClient } from '../src/client';
|
||||||
|
import { buildFetch } from '../src/utils';
|
||||||
|
|
||||||
|
function getNameForBank(group: Group, oracle: PublicKey): string {
|
||||||
|
let match: any[] = Array.from(group.banksMapByName.values())
|
||||||
|
.flat()
|
||||||
|
.filter((b) => b.oracle.equals(oracle));
|
||||||
|
if (match.length > 0) {
|
||||||
|
return match[0].name;
|
||||||
|
}
|
||||||
|
|
||||||
|
match = Array.from(group.perpMarketsMapByName.values()).filter((p) =>
|
||||||
|
p.oracle.equals(oracle),
|
||||||
|
);
|
||||||
|
if (match.length > 0) {
|
||||||
|
return match[0].name;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Error(`No token or perp market found for ${oracle}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function main(): Promise<void> {
|
||||||
|
const client = await MangoClient.connectDefault(process.env.MB_CLUSTER_URL!);
|
||||||
|
const group = await client.getGroup(
|
||||||
|
new PublicKey('78b8f4cGCwmZ9ysPFMWLaLTkkaYnUjwMJYStWe5RTSSX'),
|
||||||
|
);
|
||||||
|
|
||||||
|
const oracles1 = Array.from(group.banksMapByName.values()).map(
|
||||||
|
(b) => b[0].oracle,
|
||||||
|
);
|
||||||
|
const oracles2 = Array.from(group.perpMarketsMapByName.values()).map(
|
||||||
|
(p) => p.oracle,
|
||||||
|
);
|
||||||
|
const oracles = oracles1.concat(oracles2);
|
||||||
|
|
||||||
|
const ais = await client.program.provider.connection.getMultipleAccountsInfo(
|
||||||
|
oracles,
|
||||||
|
);
|
||||||
|
|
||||||
|
const switcboardOracles: PublicKey[] = ais
|
||||||
|
.map((ai, i) => [isSwitchboardOracle(ai!), oracles[i]])
|
||||||
|
.filter((r) => r[0])
|
||||||
|
.map((r) => r[1]) as PublicKey[];
|
||||||
|
|
||||||
|
for (const o of switcboardOracles) {
|
||||||
|
const r = await (
|
||||||
|
await buildFetch()
|
||||||
|
)('https://stats.switchboard.xyz/logs', {
|
||||||
|
headers: {
|
||||||
|
accept: '*/*',
|
||||||
|
'content-type': 'application/json',
|
||||||
|
},
|
||||||
|
body: `{"cluster":"solana-mainnet","query":"${o.toString()}","number":100,"severity":"INFO"}`,
|
||||||
|
method: 'POST',
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log(`${getNameForBank(group, o)} ${o}`);
|
||||||
|
|
||||||
|
(await r.json()).forEach((e: { message: string; timestamp: string }) => {
|
||||||
|
if (e.message.toLowerCase().includes('error')) {
|
||||||
|
console.log(`${e.timestamp}: ${e.message}`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log(``);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
main();
|
|
@ -138,7 +138,7 @@ export class Group {
|
||||||
),
|
),
|
||||||
this.reloadMintInfos(client, ids),
|
this.reloadMintInfos(client, ids),
|
||||||
this.reloadSerum3Markets(client, ids).then(() =>
|
this.reloadSerum3Markets(client, ids).then(() =>
|
||||||
this.reloadSerum3ExternalMarkets(client),
|
this.reloadSerum3ExternalMarkets(client, ids),
|
||||||
),
|
),
|
||||||
]);
|
]);
|
||||||
// console.timeEnd('group.reload');
|
// console.timeEnd('group.reload');
|
||||||
|
@ -274,23 +274,63 @@ export class Group {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async reloadSerum3ExternalMarkets(client: MangoClient): Promise<void> {
|
public async reloadSerum3ExternalMarkets(
|
||||||
const externalMarkets = await Promise.all(
|
client: MangoClient,
|
||||||
Array.from(this.serum3MarketsMapByExternal.values()).map((serum3Market) =>
|
ids?: Id,
|
||||||
Market.load(
|
): Promise<void> {
|
||||||
client.program.provider.connection,
|
let markets: Market[] = [];
|
||||||
serum3Market.serumMarketExternal,
|
const externalMarketIds = ids?.getSerum3ExternalMarkets();
|
||||||
{ commitment: client.program.provider.connection.commitment },
|
|
||||||
OPENBOOK_PROGRAM_ID[client.cluster],
|
if (ids && externalMarketIds && externalMarketIds.length) {
|
||||||
|
markets = await Promise.all(
|
||||||
|
(
|
||||||
|
await client.program.provider.connection.getMultipleAccountsInfo(
|
||||||
|
externalMarketIds,
|
||||||
|
)
|
||||||
|
).map(
|
||||||
|
(account, index) =>
|
||||||
|
new Market(
|
||||||
|
Market.getLayout(OPENBOOK_PROGRAM_ID[client.cluster]).decode(
|
||||||
|
account?.data,
|
||||||
|
),
|
||||||
|
ids.banks.find(
|
||||||
|
(b) =>
|
||||||
|
b.tokenIndex ===
|
||||||
|
this.serum3MarketsMapByExternal.get(
|
||||||
|
externalMarketIds[index].toString(),
|
||||||
|
)?.baseTokenIndex,
|
||||||
|
)?.decimals || 6,
|
||||||
|
ids.banks.find(
|
||||||
|
(b) =>
|
||||||
|
b.tokenIndex ===
|
||||||
|
this.serum3MarketsMapByExternal.get(
|
||||||
|
externalMarketIds[index].toString(),
|
||||||
|
)?.quoteTokenIndex,
|
||||||
|
)?.decimals || 6,
|
||||||
|
{ commitment: client.program.provider.connection.commitment },
|
||||||
|
OPENBOOK_PROGRAM_ID[client.cluster],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
);
|
||||||
);
|
} else {
|
||||||
|
markets = await Promise.all(
|
||||||
|
Array.from(this.serum3MarketsMapByExternal.values()).map(
|
||||||
|
(serum3Market) =>
|
||||||
|
Market.load(
|
||||||
|
client.program.provider.connection,
|
||||||
|
serum3Market.serumMarketExternal,
|
||||||
|
{ commitment: client.program.provider.connection.commitment },
|
||||||
|
OPENBOOK_PROGRAM_ID[client.cluster],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
this.serum3ExternalMarketsMap = new Map(
|
this.serum3ExternalMarketsMap = new Map(
|
||||||
Array.from(this.serum3MarketsMapByExternal.values()).map(
|
Array.from(this.serum3MarketsMapByExternal.values()).map(
|
||||||
(serum3Market, index) => [
|
(serum3Market, index) => [
|
||||||
serum3Market.serumMarketExternal.toBase58(),
|
serum3Market.serumMarketExternal.toBase58(),
|
||||||
externalMarkets[index],
|
markets[index],
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -463,7 +503,6 @@ export class Group {
|
||||||
await client.program.provider.connection.getMultipleAccountsInfo(
|
await client.program.provider.connection.getMultipleAccountsInfo(
|
||||||
vaultPks,
|
vaultPks,
|
||||||
);
|
);
|
||||||
const coder = new BorshAccountsCoder(client.program.idl);
|
|
||||||
this.vaultAmountsMap = new Map(
|
this.vaultAmountsMap = new Map(
|
||||||
vaultAccounts.map((vaultAi, i) => {
|
vaultAccounts.map((vaultAi, i) => {
|
||||||
if (!vaultAi) {
|
if (!vaultAi) {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { AnchorProvider, BN } from '@coral-xyz/anchor';
|
import { AnchorProvider, BN } from '@coral-xyz/anchor';
|
||||||
import { utf8 } from '@coral-xyz/anchor/dist/cjs/utils/bytes';
|
import { utf8 } from '@coral-xyz/anchor/dist/cjs/utils/bytes';
|
||||||
import { OpenOrders, Order, Orderbook } from '@project-serum/serum/lib/market';
|
import { OpenOrders, Order, Orderbook } from '@project-serum/serum/lib/market';
|
||||||
import { AccountInfo, PublicKey, TransactionSignature } from '@solana/web3.js';
|
import { AccountInfo, PublicKey } from '@solana/web3.js';
|
||||||
import { MangoClient } from '../client';
|
import { MangoClient } from '../client';
|
||||||
import { OPENBOOK_PROGRAM_ID, RUST_I64_MAX, RUST_I64_MIN } from '../constants';
|
import { OPENBOOK_PROGRAM_ID, RUST_I64_MAX, RUST_I64_MIN } from '../constants';
|
||||||
import { I80F48, I80F48Dto, ONE_I80F48, ZERO_I80F48 } from '../numbers/I80F48';
|
import { I80F48, I80F48Dto, ONE_I80F48, ZERO_I80F48 } from '../numbers/I80F48';
|
||||||
|
@ -13,6 +13,7 @@ import {
|
||||||
toUiDecimalsForQuote,
|
toUiDecimalsForQuote,
|
||||||
toUiSellPerBuyTokenPrice,
|
toUiSellPerBuyTokenPrice,
|
||||||
} from '../utils';
|
} from '../utils';
|
||||||
|
import { MangoSignatureStatus } from '../utils/rpc';
|
||||||
import { Bank, TokenIndex } from './bank';
|
import { Bank, TokenIndex } from './bank';
|
||||||
import { Group } from './group';
|
import { Group } from './group';
|
||||||
import { HealthCache } from './healthCache';
|
import { HealthCache } from './healthCache';
|
||||||
|
@ -888,7 +889,7 @@ export class MangoAccount {
|
||||||
public async serum3SettleFundsForAllMarkets(
|
public async serum3SettleFundsForAllMarkets(
|
||||||
client: MangoClient,
|
client: MangoClient,
|
||||||
group: Group,
|
group: Group,
|
||||||
): Promise<TransactionSignature[]> {
|
): Promise<MangoSignatureStatus[]> {
|
||||||
// Future: collect ixs, batch them, and send them in fewer txs
|
// Future: collect ixs, batch them, and send them in fewer txs
|
||||||
return await Promise.all(
|
return await Promise.all(
|
||||||
this.serum3Active().map((s) => {
|
this.serum3Active().map((s) => {
|
||||||
|
@ -906,7 +907,7 @@ export class MangoAccount {
|
||||||
public async serum3CancelAllOrdersForAllMarkets(
|
public async serum3CancelAllOrdersForAllMarkets(
|
||||||
client: MangoClient,
|
client: MangoClient,
|
||||||
group: Group,
|
group: Group,
|
||||||
): Promise<TransactionSignature[]> {
|
): Promise<MangoSignatureStatus[]> {
|
||||||
// Future: collect ixs, batch them, and send them in in fewer txs
|
// Future: collect ixs, batch them, and send them in in fewer txs
|
||||||
return await Promise.all(
|
return await Promise.all(
|
||||||
this.serum3Active().map((s) => {
|
this.serum3Active().map((s) => {
|
||||||
|
@ -1874,6 +1875,26 @@ export class TokenConditionalSwap {
|
||||||
return this.expiryTimestamp.toNumber();
|
return this.expiryTimestamp.toNumber();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: will be replaced by onchain enum in next release
|
||||||
|
private getTokenConditionalSwapDisplayPriceStyle(group: Group): boolean {
|
||||||
|
const buyBank = this.getBuyToken(group);
|
||||||
|
const sellBank = this.getSellToken(group);
|
||||||
|
|
||||||
|
// If we are tp/sl'ing SOL borrow, then price is stored in sol/usdc
|
||||||
|
// then don't flip
|
||||||
|
if (sellBank.tokenIndex == 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// E.g.
|
||||||
|
// If we are tp/sl'ing SOL deposit, then price is stored in usdc/sol
|
||||||
|
if (this.maxSell.eq(U64_MAX_BN)) {
|
||||||
|
true; // dont flip, i.e. continue using sellTokenPerBuyTokenUi price
|
||||||
|
}
|
||||||
|
// Flip the price if we know we are selling an exact amount of SOL
|
||||||
|
return false; // flip, i.e. use buyTokenPerSellTokenUi price
|
||||||
|
}
|
||||||
|
|
||||||
private priceLimitToUi(
|
private priceLimitToUi(
|
||||||
group: Group,
|
group: Group,
|
||||||
sellTokenPerBuyTokenNative: number,
|
sellTokenPerBuyTokenNative: number,
|
||||||
|
@ -1891,7 +1912,7 @@ export class TokenConditionalSwap {
|
||||||
// buytoken/selltoken or selltoken/buytoken
|
// buytoken/selltoken or selltoken/buytoken
|
||||||
|
|
||||||
// Buy limit / close short
|
// Buy limit / close short
|
||||||
if (this.maxSell.eq(U64_MAX_BN)) {
|
if (this.getTokenConditionalSwapDisplayPriceStyle(group)) {
|
||||||
return roundTo5(sellTokenPerBuyTokenUi);
|
return roundTo5(sellTokenPerBuyTokenUi);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1909,20 +1930,44 @@ export class TokenConditionalSwap {
|
||||||
}
|
}
|
||||||
|
|
||||||
getThresholdPriceUi(group: Group): number {
|
getThresholdPriceUi(group: Group): number {
|
||||||
const a = I80F48.fromNumber(this.priceLowerLimit);
|
|
||||||
const b = I80F48.fromNumber(this.priceUpperLimit);
|
|
||||||
|
|
||||||
const buyBank = this.getBuyToken(group);
|
const buyBank = this.getBuyToken(group);
|
||||||
const sellBank = this.getSellToken(group);
|
const sellBank = this.getSellToken(group);
|
||||||
const o = buyBank.price.div(sellBank.price);
|
|
||||||
|
const a = toUiSellPerBuyTokenPrice(this.priceLowerLimit, sellBank, buyBank);
|
||||||
|
const b = toUiSellPerBuyTokenPrice(this.priceUpperLimit, sellBank, buyBank);
|
||||||
|
|
||||||
|
const o = buyBank.uiPrice / sellBank.uiPrice;
|
||||||
|
|
||||||
// Choose the price closest to oracle
|
// Choose the price closest to oracle
|
||||||
if (o.sub(a).abs().lt(o.sub(b).abs())) {
|
if (Math.abs(o - a) < Math.abs(o - b)) {
|
||||||
return this.getPriceLowerLimitUi(group);
|
return this.getPriceLowerLimitUi(group);
|
||||||
}
|
}
|
||||||
return this.getPriceUpperLimitUi(group);
|
return this.getPriceUpperLimitUi(group);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getCurrentPairPriceUi(group: Group): number {
|
||||||
|
const buyBank = this.getBuyToken(group);
|
||||||
|
const sellBank = this.getSellToken(group);
|
||||||
|
const sellTokenPerBuyTokenUi = toUiSellPerBuyTokenPrice(
|
||||||
|
buyBank.price.div(sellBank.price).toNumber(),
|
||||||
|
sellBank,
|
||||||
|
buyBank,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Below are workarounds to know when to show an inverted price in ui
|
||||||
|
// We want to identify if the pair user is wanting to trade is
|
||||||
|
// buytoken/selltoken or selltoken/buytoken
|
||||||
|
|
||||||
|
// Buy limit / close short
|
||||||
|
if (this.getTokenConditionalSwapDisplayPriceStyle(group)) {
|
||||||
|
return roundTo5(sellTokenPerBuyTokenUi);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stop loss / take profit
|
||||||
|
const buyTokenPerSellTokenUi = 1 / sellTokenPerBuyTokenUi;
|
||||||
|
return roundTo5(buyTokenPerSellTokenUi);
|
||||||
|
}
|
||||||
|
|
||||||
// in percent
|
// in percent
|
||||||
getPricePremium(): number {
|
getPricePremium(): number {
|
||||||
return this.pricePremiumRate * 100;
|
return this.pricePremiumRate * 100;
|
||||||
|
@ -1945,16 +1990,20 @@ export class TokenConditionalSwap {
|
||||||
}
|
}
|
||||||
|
|
||||||
toString(group: Group): string {
|
toString(group: Group): string {
|
||||||
return `getMaxBuy ${this.getMaxBuyUi(
|
return `${
|
||||||
|
group.getFirstBankByTokenIndex(this.buyTokenIndex).name +
|
||||||
|
'/' +
|
||||||
|
group.getFirstBankByTokenIndex(this.sellTokenIndex).name
|
||||||
|
} , getMaxBuy ${this.getMaxBuyUi(group)}, getMaxSell ${this.getMaxSellUi(
|
||||||
group,
|
group,
|
||||||
)}, getMaxSell ${this.getMaxSellUi(group)}, bought ${this.getBoughtUi(
|
)}, bought ${this.getBoughtUi(group)}, sold ${this.getSoldUi(
|
||||||
group,
|
|
||||||
)}, sold ${this.getSoldUi(
|
|
||||||
group,
|
group,
|
||||||
)}, getPriceLowerLimitUi ${this.getPriceLowerLimitUi(
|
)}, getPriceLowerLimitUi ${this.getPriceLowerLimitUi(
|
||||||
group,
|
group,
|
||||||
)}, getPriceUpperLimitUi ${this.getPriceUpperLimitUi(
|
)}, getPriceUpperLimitUi ${this.getPriceUpperLimitUi(
|
||||||
group,
|
group,
|
||||||
|
)}, getCurrentPairPriceUi ${this.getCurrentPairPriceUi(
|
||||||
|
group,
|
||||||
)}, getThresholdPriceUi ${this.getThresholdPriceUi(
|
)}, getThresholdPriceUi ${this.getThresholdPriceUi(
|
||||||
group,
|
group,
|
||||||
)}, getPricePremium ${this.getPricePremium()}, expiry ${this.expiryTimestamp.toString()}`;
|
)}, getPricePremium ${this.getPricePremium()}, expiry ${this.expiryTimestamp.toString()}`;
|
||||||
|
|
|
@ -408,6 +408,13 @@ export class PerpMarket {
|
||||||
return funding;
|
return funding;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public getInstantaneousFundingRatePerSecond(
|
||||||
|
bids: BookSide,
|
||||||
|
asks: BookSide,
|
||||||
|
): number {
|
||||||
|
return this.getInstantaneousFundingRate(bids, asks) / (24 * 60 * 60);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* Returns instantaneous funding rate for the day. How is it actually applied - funding is
|
* Returns instantaneous funding rate for the day. How is it actually applied - funding is
|
||||||
|
|
|
@ -90,7 +90,7 @@ import {
|
||||||
toNative,
|
toNative,
|
||||||
toNativeSellPerBuyTokenPrice,
|
toNativeSellPerBuyTokenPrice,
|
||||||
} from './utils';
|
} from './utils';
|
||||||
import { sendTransaction } from './utils/rpc';
|
import { MangoSignatureStatus, sendTransaction } from './utils/rpc';
|
||||||
import { NATIVE_MINT, TOKEN_PROGRAM_ID } from './utils/spl';
|
import { NATIVE_MINT, TOKEN_PROGRAM_ID } from './utils/spl';
|
||||||
|
|
||||||
export const DEFAULT_TOKEN_CONDITIONAL_SWAP_COUNT = 8;
|
export const DEFAULT_TOKEN_CONDITIONAL_SWAP_COUNT = 8;
|
||||||
|
@ -109,6 +109,7 @@ export type MangoClientOptions = {
|
||||||
estimateFee?: boolean;
|
estimateFee?: boolean;
|
||||||
txConfirmationCommitment?: Commitment;
|
txConfirmationCommitment?: Commitment;
|
||||||
openbookFeesToDao?: boolean;
|
openbookFeesToDao?: boolean;
|
||||||
|
prependedGlobalAdditionalInstructions?: TransactionInstruction[];
|
||||||
};
|
};
|
||||||
|
|
||||||
export class MangoClient {
|
export class MangoClient {
|
||||||
|
@ -118,6 +119,7 @@ export class MangoClient {
|
||||||
private estimateFee: boolean;
|
private estimateFee: boolean;
|
||||||
private txConfirmationCommitment: Commitment;
|
private txConfirmationCommitment: Commitment;
|
||||||
private openbookFeesToDao: boolean;
|
private openbookFeesToDao: boolean;
|
||||||
|
private prependedGlobalAdditionalInstructions: TransactionInstruction[] = [];
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
public program: Program<MangoV4>,
|
public program: Program<MangoV4>,
|
||||||
|
@ -130,6 +132,8 @@ export class MangoClient {
|
||||||
this.estimateFee = opts?.estimateFee || false;
|
this.estimateFee = opts?.estimateFee || false;
|
||||||
this.postSendTxCallback = opts?.postSendTxCallback;
|
this.postSendTxCallback = opts?.postSendTxCallback;
|
||||||
this.openbookFeesToDao = opts?.openbookFeesToDao ?? true;
|
this.openbookFeesToDao = opts?.openbookFeesToDao ?? true;
|
||||||
|
this.prependedGlobalAdditionalInstructions =
|
||||||
|
opts.prependedGlobalAdditionalInstructions ?? [];
|
||||||
this.txConfirmationCommitment =
|
this.txConfirmationCommitment =
|
||||||
opts?.txConfirmationCommitment ??
|
opts?.txConfirmationCommitment ??
|
||||||
(program.provider as AnchorProvider).opts.commitment ??
|
(program.provider as AnchorProvider).opts.commitment ??
|
||||||
|
@ -151,7 +155,7 @@ export class MangoClient {
|
||||||
public async sendAndConfirmTransaction(
|
public async sendAndConfirmTransaction(
|
||||||
ixs: TransactionInstruction[],
|
ixs: TransactionInstruction[],
|
||||||
opts: any = {},
|
opts: any = {},
|
||||||
): Promise<string> {
|
): Promise<MangoSignatureStatus> {
|
||||||
let prioritizationFee: number;
|
let prioritizationFee: number;
|
||||||
if (opts.prioritizationFee) {
|
if (opts.prioritizationFee) {
|
||||||
prioritizationFee = opts.prioritizationFee;
|
prioritizationFee = opts.prioritizationFee;
|
||||||
|
@ -160,9 +164,9 @@ export class MangoClient {
|
||||||
} else {
|
} else {
|
||||||
prioritizationFee = this.prioritizationFee;
|
prioritizationFee = this.prioritizationFee;
|
||||||
}
|
}
|
||||||
return await sendTransaction(
|
const status = await sendTransaction(
|
||||||
this.program.provider as AnchorProvider,
|
this.program.provider as AnchorProvider,
|
||||||
ixs,
|
[...this.prependedGlobalAdditionalInstructions, ...ixs],
|
||||||
opts.alts ?? [],
|
opts.alts ?? [],
|
||||||
{
|
{
|
||||||
postSendTxCallback: this.postSendTxCallback,
|
postSendTxCallback: this.postSendTxCallback,
|
||||||
|
@ -171,13 +175,14 @@ export class MangoClient {
|
||||||
...opts,
|
...opts,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async sendAndConfirmTransactionForGroup(
|
public async sendAndConfirmTransactionForGroup(
|
||||||
group: Group,
|
group: Group,
|
||||||
ixs: TransactionInstruction[],
|
ixs: TransactionInstruction[],
|
||||||
opts: any = {},
|
opts: any = {},
|
||||||
): Promise<string> {
|
): Promise<MangoSignatureStatus> {
|
||||||
return await this.sendAndConfirmTransaction(ixs, {
|
return await this.sendAndConfirmTransaction(ixs, {
|
||||||
alts: group.addressLookupTablesList,
|
alts: group.addressLookupTablesList,
|
||||||
...opts,
|
...opts,
|
||||||
|
@ -188,7 +193,7 @@ export class MangoClient {
|
||||||
group: Group,
|
group: Group,
|
||||||
bank: Bank,
|
bank: Bank,
|
||||||
tokenAccountPk: PublicKey,
|
tokenAccountPk: PublicKey,
|
||||||
): Promise<TransactionSignature> {
|
): Promise<MangoSignatureStatus> {
|
||||||
const admin = (this.program.provider as AnchorProvider).wallet.publicKey;
|
const admin = (this.program.provider as AnchorProvider).wallet.publicKey;
|
||||||
const ix = await this.program.methods
|
const ix = await this.program.methods
|
||||||
.adminTokenWithdrawFees()
|
.adminTokenWithdrawFees()
|
||||||
|
@ -207,7 +212,7 @@ export class MangoClient {
|
||||||
group: Group,
|
group: Group,
|
||||||
perpMarket: PerpMarket,
|
perpMarket: PerpMarket,
|
||||||
tokenAccountPk: PublicKey,
|
tokenAccountPk: PublicKey,
|
||||||
): Promise<TransactionSignature> {
|
): Promise<MangoSignatureStatus> {
|
||||||
const bank = group.getFirstBankByTokenIndex(perpMarket.settleTokenIndex);
|
const bank = group.getFirstBankByTokenIndex(perpMarket.settleTokenIndex);
|
||||||
const admin = (this.program.provider as AnchorProvider).wallet.publicKey;
|
const admin = (this.program.provider as AnchorProvider).wallet.publicKey;
|
||||||
const ix = await this.program.methods
|
const ix = await this.program.methods
|
||||||
|
@ -230,7 +235,7 @@ export class MangoClient {
|
||||||
testing: boolean,
|
testing: boolean,
|
||||||
version: number,
|
version: number,
|
||||||
insuranceMintPk: PublicKey,
|
insuranceMintPk: PublicKey,
|
||||||
): Promise<TransactionSignature> {
|
): Promise<MangoSignatureStatus> {
|
||||||
const adminPk = (this.program.provider as AnchorProvider).wallet.publicKey;
|
const adminPk = (this.program.provider as AnchorProvider).wallet.publicKey;
|
||||||
const ix = await this.program.methods
|
const ix = await this.program.methods
|
||||||
.groupCreate(groupNum, testing ? 1 : 0, version)
|
.groupCreate(groupNum, testing ? 1 : 0, version)
|
||||||
|
@ -256,7 +261,7 @@ export class MangoClient {
|
||||||
feesSwapMangoAccount?: PublicKey,
|
feesSwapMangoAccount?: PublicKey,
|
||||||
feesMngoTokenIndex?: TokenIndex,
|
feesMngoTokenIndex?: TokenIndex,
|
||||||
feesExpiryInterval?: BN,
|
feesExpiryInterval?: BN,
|
||||||
): Promise<TransactionSignature> {
|
): Promise<MangoSignatureStatus> {
|
||||||
const ix = await this.program.methods
|
const ix = await this.program.methods
|
||||||
.groupEdit(
|
.groupEdit(
|
||||||
admin ?? null,
|
admin ?? null,
|
||||||
|
@ -282,7 +287,7 @@ export class MangoClient {
|
||||||
public async ixGateSet(
|
public async ixGateSet(
|
||||||
group: Group,
|
group: Group,
|
||||||
ixGateParams: IxGateParams,
|
ixGateParams: IxGateParams,
|
||||||
): Promise<TransactionSignature> {
|
): Promise<MangoSignatureStatus> {
|
||||||
const ix = await this.program.methods
|
const ix = await this.program.methods
|
||||||
.ixGateSet(buildIxGate(ixGateParams))
|
.ixGateSet(buildIxGate(ixGateParams))
|
||||||
.accounts({
|
.accounts({
|
||||||
|
@ -293,7 +298,7 @@ export class MangoClient {
|
||||||
return await this.sendAndConfirmTransactionForGroup(group, [ix]);
|
return await this.sendAndConfirmTransactionForGroup(group, [ix]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async groupClose(group: Group): Promise<TransactionSignature> {
|
public async groupClose(group: Group): Promise<MangoSignatureStatus> {
|
||||||
const adminPk = (this.program.provider as AnchorProvider).wallet.publicKey;
|
const adminPk = (this.program.provider as AnchorProvider).wallet.publicKey;
|
||||||
const ix = await this.program.methods
|
const ix = await this.program.methods
|
||||||
.groupClose()
|
.groupClose()
|
||||||
|
@ -379,7 +384,7 @@ export class MangoClient {
|
||||||
tokenIndex: number,
|
tokenIndex: number,
|
||||||
name: string,
|
name: string,
|
||||||
params: TokenRegisterParams,
|
params: TokenRegisterParams,
|
||||||
): Promise<TransactionSignature> {
|
): Promise<MangoSignatureStatus> {
|
||||||
const ix = await this.program.methods
|
const ix = await this.program.methods
|
||||||
.tokenRegister(
|
.tokenRegister(
|
||||||
tokenIndex,
|
tokenIndex,
|
||||||
|
@ -424,7 +429,7 @@ export class MangoClient {
|
||||||
oraclePk: PublicKey,
|
oraclePk: PublicKey,
|
||||||
tokenIndex: number,
|
tokenIndex: number,
|
||||||
name: string,
|
name: string,
|
||||||
): Promise<TransactionSignature> {
|
): Promise<MangoSignatureStatus> {
|
||||||
const ix = await this.program.methods
|
const ix = await this.program.methods
|
||||||
.tokenRegisterTrustless(tokenIndex, name)
|
.tokenRegisterTrustless(tokenIndex, name)
|
||||||
.accounts({
|
.accounts({
|
||||||
|
@ -443,7 +448,7 @@ export class MangoClient {
|
||||||
group: Group,
|
group: Group,
|
||||||
mintPk: PublicKey,
|
mintPk: PublicKey,
|
||||||
params: TokenEditParams,
|
params: TokenEditParams,
|
||||||
): Promise<TransactionSignature> {
|
): Promise<MangoSignatureStatus> {
|
||||||
const bank = group.getFirstBankByMint(mintPk);
|
const bank = group.getFirstBankByMint(mintPk);
|
||||||
const mintInfo = group.mintInfosMapByTokenIndex.get(bank.tokenIndex)!;
|
const mintInfo = group.mintInfosMapByTokenIndex.get(bank.tokenIndex)!;
|
||||||
|
|
||||||
|
@ -505,7 +510,7 @@ export class MangoClient {
|
||||||
assetTokenIndex: TokenIndex,
|
assetTokenIndex: TokenIndex,
|
||||||
liabTokenIndex: TokenIndex,
|
liabTokenIndex: TokenIndex,
|
||||||
maxLiabTransfer?: number,
|
maxLiabTransfer?: number,
|
||||||
): Promise<string> {
|
): Promise<MangoSignatureStatus> {
|
||||||
const assetBank = group.getFirstBankByTokenIndex(assetTokenIndex);
|
const assetBank = group.getFirstBankByTokenIndex(assetTokenIndex);
|
||||||
const liabBank = group.getFirstBankByTokenIndex(liabTokenIndex);
|
const liabBank = group.getFirstBankByTokenIndex(liabTokenIndex);
|
||||||
const healthRemainingAccounts: PublicKey[] =
|
const healthRemainingAccounts: PublicKey[] =
|
||||||
|
@ -548,7 +553,7 @@ export class MangoClient {
|
||||||
public async tokenDeregister(
|
public async tokenDeregister(
|
||||||
group: Group,
|
group: Group,
|
||||||
mintPk: PublicKey,
|
mintPk: PublicKey,
|
||||||
): Promise<TransactionSignature> {
|
): Promise<MangoSignatureStatus> {
|
||||||
const bank = group.getFirstBankByMint(mintPk);
|
const bank = group.getFirstBankByMint(mintPk);
|
||||||
const adminPk = (this.program.provider as AnchorProvider).wallet.publicKey;
|
const adminPk = (this.program.provider as AnchorProvider).wallet.publicKey;
|
||||||
|
|
||||||
|
@ -652,7 +657,7 @@ export class MangoClient {
|
||||||
group: Group,
|
group: Group,
|
||||||
mintPk: PublicKey,
|
mintPk: PublicKey,
|
||||||
price: number,
|
price: number,
|
||||||
): Promise<TransactionSignature> {
|
): Promise<MangoSignatureStatus> {
|
||||||
const ix = await this.program.methods
|
const ix = await this.program.methods
|
||||||
.stubOracleCreate({ val: I80F48.fromNumber(price).getData() })
|
.stubOracleCreate({ val: I80F48.fromNumber(price).getData() })
|
||||||
.accounts({
|
.accounts({
|
||||||
|
@ -668,7 +673,7 @@ export class MangoClient {
|
||||||
public async stubOracleClose(
|
public async stubOracleClose(
|
||||||
group: Group,
|
group: Group,
|
||||||
oracle: PublicKey,
|
oracle: PublicKey,
|
||||||
): Promise<TransactionSignature> {
|
): Promise<MangoSignatureStatus> {
|
||||||
const ix = await this.program.methods
|
const ix = await this.program.methods
|
||||||
.stubOracleClose()
|
.stubOracleClose()
|
||||||
.accounts({
|
.accounts({
|
||||||
|
@ -685,7 +690,7 @@ export class MangoClient {
|
||||||
group: Group,
|
group: Group,
|
||||||
oraclePk: PublicKey,
|
oraclePk: PublicKey,
|
||||||
price: number,
|
price: number,
|
||||||
): Promise<TransactionSignature> {
|
): Promise<MangoSignatureStatus> {
|
||||||
const ix = await this.program.methods
|
const ix = await this.program.methods
|
||||||
.stubOracleSet({ val: I80F48.fromNumber(price).getData() })
|
.stubOracleSet({ val: I80F48.fromNumber(price).getData() })
|
||||||
.accounts({
|
.accounts({
|
||||||
|
@ -734,7 +739,7 @@ export class MangoClient {
|
||||||
serum3Count?: number,
|
serum3Count?: number,
|
||||||
perpCount?: number,
|
perpCount?: number,
|
||||||
perpOoCount?: number,
|
perpOoCount?: number,
|
||||||
): Promise<TransactionSignature> {
|
): Promise<MangoSignatureStatus> {
|
||||||
const ix = await this.program.methods
|
const ix = await this.program.methods
|
||||||
.accountCreate(
|
.accountCreate(
|
||||||
accountNumber ?? 0,
|
accountNumber ?? 0,
|
||||||
|
@ -761,7 +766,7 @@ export class MangoClient {
|
||||||
serum3Count: number,
|
serum3Count: number,
|
||||||
perpCount: number,
|
perpCount: number,
|
||||||
perpOoCount: number,
|
perpOoCount: number,
|
||||||
): Promise<TransactionSignature> {
|
): Promise<MangoSignatureStatus> {
|
||||||
const ix = await this.program.methods
|
const ix = await this.program.methods
|
||||||
.accountExpand(tokenCount, serum3Count, perpCount, perpOoCount)
|
.accountExpand(tokenCount, serum3Count, perpCount, perpOoCount)
|
||||||
.accounts({
|
.accounts({
|
||||||
|
@ -782,7 +787,7 @@ export class MangoClient {
|
||||||
perpCount: number,
|
perpCount: number,
|
||||||
perpOoCount: number,
|
perpOoCount: number,
|
||||||
tokenConditionalSwapCount: number,
|
tokenConditionalSwapCount: number,
|
||||||
): Promise<TransactionSignature> {
|
): Promise<MangoSignatureStatus> {
|
||||||
const ix = await this.accountExpandV2Ix(
|
const ix = await this.accountExpandV2Ix(
|
||||||
group,
|
group,
|
||||||
account,
|
account,
|
||||||
|
@ -828,7 +833,7 @@ export class MangoClient {
|
||||||
delegate?: PublicKey,
|
delegate?: PublicKey,
|
||||||
temporaryDelegate?: PublicKey,
|
temporaryDelegate?: PublicKey,
|
||||||
delegateExpiry?: number,
|
delegateExpiry?: number,
|
||||||
): Promise<TransactionSignature> {
|
): Promise<MangoSignatureStatus> {
|
||||||
const ix = await this.program.methods
|
const ix = await this.program.methods
|
||||||
.accountEdit(
|
.accountEdit(
|
||||||
name ?? null,
|
name ?? null,
|
||||||
|
@ -849,7 +854,7 @@ export class MangoClient {
|
||||||
public async computeAccountData(
|
public async computeAccountData(
|
||||||
group: Group,
|
group: Group,
|
||||||
mangoAccount: MangoAccount,
|
mangoAccount: MangoAccount,
|
||||||
): Promise<TransactionSignature> {
|
): Promise<MangoSignatureStatus> {
|
||||||
const healthRemainingAccounts: PublicKey[] =
|
const healthRemainingAccounts: PublicKey[] =
|
||||||
this.buildHealthRemainingAccounts(group, [mangoAccount], [], []);
|
this.buildHealthRemainingAccounts(group, [mangoAccount], [], []);
|
||||||
|
|
||||||
|
@ -874,7 +879,7 @@ export class MangoClient {
|
||||||
group: Group,
|
group: Group,
|
||||||
mangoAccount: MangoAccount,
|
mangoAccount: MangoAccount,
|
||||||
freeze: boolean,
|
freeze: boolean,
|
||||||
): Promise<TransactionSignature> {
|
): Promise<MangoSignatureStatus> {
|
||||||
const ix = await this.program.methods
|
const ix = await this.program.methods
|
||||||
.accountToggleFreeze(freeze)
|
.accountToggleFreeze(freeze)
|
||||||
.accounts({
|
.accounts({
|
||||||
|
@ -900,7 +905,7 @@ export class MangoClient {
|
||||||
private async getMangoAccountFromPk(
|
private async getMangoAccountFromPk(
|
||||||
mangoAccountPk: PublicKey,
|
mangoAccountPk: PublicKey,
|
||||||
): Promise<MangoAccount> {
|
): Promise<MangoAccount> {
|
||||||
return await this.getMangoAccountFromAi(
|
return this.getMangoAccountFromAi(
|
||||||
mangoAccountPk,
|
mangoAccountPk,
|
||||||
(await this.program.provider.connection.getAccountInfo(
|
(await this.program.provider.connection.getAccountInfo(
|
||||||
mangoAccountPk,
|
mangoAccountPk,
|
||||||
|
@ -908,10 +913,10 @@ export class MangoClient {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async getMangoAccountFromAi(
|
public getMangoAccountFromAi(
|
||||||
mangoAccountPk: PublicKey,
|
mangoAccountPk: PublicKey,
|
||||||
ai: AccountInfo<Buffer>,
|
ai: AccountInfo<Buffer>,
|
||||||
): Promise<MangoAccount> {
|
): MangoAccount {
|
||||||
const decodedMangoAccount = this.program.coder.accounts.decode(
|
const decodedMangoAccount = this.program.coder.accounts.decode(
|
||||||
'mangoAccount',
|
'mangoAccount',
|
||||||
ai.data,
|
ai.data,
|
||||||
|
@ -1190,7 +1195,7 @@ export class MangoClient {
|
||||||
group: Group,
|
group: Group,
|
||||||
mangoAccount: MangoAccount,
|
mangoAccount: MangoAccount,
|
||||||
forceClose = false,
|
forceClose = false,
|
||||||
): Promise<TransactionSignature> {
|
): Promise<MangoSignatureStatus> {
|
||||||
const ix = await this.program.methods
|
const ix = await this.program.methods
|
||||||
.accountClose(forceClose)
|
.accountClose(forceClose)
|
||||||
.accounts({
|
.accounts({
|
||||||
|
@ -1207,7 +1212,7 @@ export class MangoClient {
|
||||||
public async emptyAndCloseMangoAccount(
|
public async emptyAndCloseMangoAccount(
|
||||||
group: Group,
|
group: Group,
|
||||||
mangoAccount: MangoAccount,
|
mangoAccount: MangoAccount,
|
||||||
): Promise<TransactionSignature> {
|
): Promise<MangoSignatureStatus> {
|
||||||
// Work on a deep cloned mango account, since we would deactivating positions
|
// Work on a deep cloned mango account, since we would deactivating positions
|
||||||
// before deactivation reaches on-chain state in order to simplify building a fresh list
|
// before deactivation reaches on-chain state in order to simplify building a fresh list
|
||||||
// of healthRemainingAccounts to each subsequent ix
|
// of healthRemainingAccounts to each subsequent ix
|
||||||
|
@ -1292,7 +1297,7 @@ export class MangoClient {
|
||||||
group: Group,
|
group: Group,
|
||||||
mangoAccount: MangoAccount,
|
mangoAccount: MangoAccount,
|
||||||
maxBuyback?: number,
|
maxBuyback?: number,
|
||||||
): Promise<TransactionSignature> {
|
): Promise<MangoSignatureStatus> {
|
||||||
const ix = await this.accountBuybackFeesWithMngoIx(
|
const ix = await this.accountBuybackFeesWithMngoIx(
|
||||||
group,
|
group,
|
||||||
mangoAccount,
|
mangoAccount,
|
||||||
|
@ -1307,7 +1312,7 @@ export class MangoClient {
|
||||||
mintPk: PublicKey,
|
mintPk: PublicKey,
|
||||||
amount: number,
|
amount: number,
|
||||||
reduceOnly = false,
|
reduceOnly = false,
|
||||||
): Promise<TransactionSignature> {
|
): Promise<MangoSignatureStatus> {
|
||||||
const decimals = group.getMintDecimals(mintPk);
|
const decimals = group.getMintDecimals(mintPk);
|
||||||
const nativeAmount = toNative(amount, decimals);
|
const nativeAmount = toNative(amount, decimals);
|
||||||
return await this.tokenDepositNative(
|
return await this.tokenDepositNative(
|
||||||
|
@ -1325,23 +1330,22 @@ export class MangoClient {
|
||||||
mintPk: PublicKey,
|
mintPk: PublicKey,
|
||||||
nativeAmount: BN,
|
nativeAmount: BN,
|
||||||
reduceOnly = false,
|
reduceOnly = false,
|
||||||
): Promise<TransactionSignature> {
|
): Promise<MangoSignatureStatus> {
|
||||||
const bank = group.getFirstBankByMint(mintPk);
|
const bank = group.getFirstBankByMint(mintPk);
|
||||||
|
|
||||||
const tokenAccountPk = await getAssociatedTokenAddress(
|
const tokenAccountPk = await getAssociatedTokenAddress(
|
||||||
mintPk,
|
mintPk,
|
||||||
mangoAccount.owner,
|
mangoAccount.owner,
|
||||||
true,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
let wrappedSolAccount: Keypair | undefined;
|
let wrappedSolAccount: PublicKey | undefined;
|
||||||
let preInstructions: TransactionInstruction[] = [];
|
let preInstructions: TransactionInstruction[] = [];
|
||||||
let postInstructions: TransactionInstruction[] = [];
|
let postInstructions: TransactionInstruction[] = [];
|
||||||
if (mintPk.equals(NATIVE_MINT)) {
|
if (mintPk.equals(NATIVE_MINT)) {
|
||||||
// Generate a random seed for wrappedSolAccount.
|
// Generate a random seed for wrappedSolAccount.
|
||||||
const seed = Keypair.generate().publicKey.toBase58().slice(0, 32);
|
const seed = Keypair.generate().publicKey.toBase58().slice(0, 32);
|
||||||
// Calculate a publicKey that will be controlled by the `mangoAccount.owner`.
|
// Calculate a publicKey that will be controlled by the `mangoAccount.owner`.
|
||||||
const wrappedSolAccount = await PublicKey.createWithSeed(
|
wrappedSolAccount = await PublicKey.createWithSeed(
|
||||||
mangoAccount.owner,
|
mangoAccount.owner,
|
||||||
seed,
|
seed,
|
||||||
TOKEN_PROGRAM_ID,
|
TOKEN_PROGRAM_ID,
|
||||||
|
@ -1386,7 +1390,7 @@ export class MangoClient {
|
||||||
bank: bank.publicKey,
|
bank: bank.publicKey,
|
||||||
vault: bank.vault,
|
vault: bank.vault,
|
||||||
oracle: bank.oracle,
|
oracle: bank.oracle,
|
||||||
tokenAccount: wrappedSolAccount?.publicKey ?? tokenAccountPk,
|
tokenAccount: wrappedSolAccount ?? tokenAccountPk,
|
||||||
tokenAuthority: mangoAccount.owner,
|
tokenAuthority: mangoAccount.owner,
|
||||||
})
|
})
|
||||||
.remainingAccounts(
|
.remainingAccounts(
|
||||||
|
@ -1410,7 +1414,7 @@ export class MangoClient {
|
||||||
mintPk: PublicKey,
|
mintPk: PublicKey,
|
||||||
amount: number,
|
amount: number,
|
||||||
allowBorrow: boolean,
|
allowBorrow: boolean,
|
||||||
): Promise<TransactionSignature> {
|
): Promise<MangoSignatureStatus> {
|
||||||
const nativeAmount = toNative(amount, group.getMintDecimals(mintPk));
|
const nativeAmount = toNative(amount, group.getMintDecimals(mintPk));
|
||||||
const ixes = await this.tokenWithdrawNativeIx(
|
const ixes = await this.tokenWithdrawNativeIx(
|
||||||
group,
|
group,
|
||||||
|
@ -1493,7 +1497,7 @@ export class MangoClient {
|
||||||
mintPk: PublicKey,
|
mintPk: PublicKey,
|
||||||
nativeAmount: BN,
|
nativeAmount: BN,
|
||||||
allowBorrow: boolean,
|
allowBorrow: boolean,
|
||||||
): Promise<TransactionSignature> {
|
): Promise<MangoSignatureStatus> {
|
||||||
const ixs = await this.tokenWithdrawNativeIx(
|
const ixs = await this.tokenWithdrawNativeIx(
|
||||||
group,
|
group,
|
||||||
mangoAccount,
|
mangoAccount,
|
||||||
|
@ -1513,7 +1517,7 @@ export class MangoClient {
|
||||||
quoteBank: Bank,
|
quoteBank: Bank,
|
||||||
marketIndex: number,
|
marketIndex: number,
|
||||||
name: string,
|
name: string,
|
||||||
): Promise<TransactionSignature> {
|
): Promise<MangoSignatureStatus> {
|
||||||
const ix = await this.program.methods
|
const ix = await this.program.methods
|
||||||
.serum3RegisterMarket(marketIndex, name)
|
.serum3RegisterMarket(marketIndex, name)
|
||||||
.accounts({
|
.accounts({
|
||||||
|
@ -1535,7 +1539,7 @@ export class MangoClient {
|
||||||
reduceOnly: boolean | null,
|
reduceOnly: boolean | null,
|
||||||
forceClose: boolean | null,
|
forceClose: boolean | null,
|
||||||
name: string | null,
|
name: string | null,
|
||||||
): Promise<TransactionSignature> {
|
): Promise<MangoSignatureStatus> {
|
||||||
const serum3Market =
|
const serum3Market =
|
||||||
group.serum3MarketsMapByMarketIndex.get(serum3MarketIndex);
|
group.serum3MarketsMapByMarketIndex.get(serum3MarketIndex);
|
||||||
const ix = await this.program.methods
|
const ix = await this.program.methods
|
||||||
|
@ -1552,7 +1556,7 @@ export class MangoClient {
|
||||||
public async serum3deregisterMarket(
|
public async serum3deregisterMarket(
|
||||||
group: Group,
|
group: Group,
|
||||||
externalMarketPk: PublicKey,
|
externalMarketPk: PublicKey,
|
||||||
): Promise<TransactionSignature> {
|
): Promise<MangoSignatureStatus> {
|
||||||
const serum3Market = group.serum3MarketsMapByExternal.get(
|
const serum3Market = group.serum3MarketsMapByExternal.get(
|
||||||
externalMarketPk.toBase58(),
|
externalMarketPk.toBase58(),
|
||||||
)!;
|
)!;
|
||||||
|
@ -1625,7 +1629,7 @@ export class MangoClient {
|
||||||
group: Group,
|
group: Group,
|
||||||
mangoAccount: MangoAccount,
|
mangoAccount: MangoAccount,
|
||||||
externalMarketPk: PublicKey,
|
externalMarketPk: PublicKey,
|
||||||
): Promise<TransactionSignature> {
|
): Promise<MangoSignatureStatus> {
|
||||||
const serum3Market: Serum3Market = group.serum3MarketsMapByExternal.get(
|
const serum3Market: Serum3Market = group.serum3MarketsMapByExternal.get(
|
||||||
externalMarketPk.toBase58(),
|
externalMarketPk.toBase58(),
|
||||||
)!;
|
)!;
|
||||||
|
@ -1701,7 +1705,7 @@ export class MangoClient {
|
||||||
group: Group,
|
group: Group,
|
||||||
mangoAccount: MangoAccount,
|
mangoAccount: MangoAccount,
|
||||||
externalMarketPk: PublicKey,
|
externalMarketPk: PublicKey,
|
||||||
): Promise<TransactionSignature> {
|
): Promise<MangoSignatureStatus> {
|
||||||
const ix = await this.serum3CloseOpenOrdersIx(
|
const ix = await this.serum3CloseOpenOrdersIx(
|
||||||
group,
|
group,
|
||||||
mangoAccount,
|
mangoAccount,
|
||||||
|
@ -1723,7 +1727,7 @@ export class MangoClient {
|
||||||
mangoAccount: MangoAccount,
|
mangoAccount: MangoAccount,
|
||||||
externalMarketPk: PublicKey,
|
externalMarketPk: PublicKey,
|
||||||
limit?: number,
|
limit?: number,
|
||||||
): Promise<string> {
|
): Promise<MangoSignatureStatus> {
|
||||||
const serum3Market = group.serum3MarketsMapByExternal.get(
|
const serum3Market = group.serum3MarketsMapByExternal.get(
|
||||||
externalMarketPk.toBase58(),
|
externalMarketPk.toBase58(),
|
||||||
)!;
|
)!;
|
||||||
|
@ -1918,7 +1922,7 @@ export class MangoClient {
|
||||||
orderType: Serum3OrderType,
|
orderType: Serum3OrderType,
|
||||||
clientOrderId: number,
|
clientOrderId: number,
|
||||||
limit: number,
|
limit: number,
|
||||||
): Promise<TransactionSignature> {
|
): Promise<MangoSignatureStatus> {
|
||||||
const placeOrderIxes = await this.serum3PlaceOrderIx(
|
const placeOrderIxes = await this.serum3PlaceOrderIx(
|
||||||
group,
|
group,
|
||||||
mangoAccount,
|
mangoAccount,
|
||||||
|
@ -1982,7 +1986,7 @@ export class MangoClient {
|
||||||
mangoAccount: MangoAccount,
|
mangoAccount: MangoAccount,
|
||||||
externalMarketPk: PublicKey,
|
externalMarketPk: PublicKey,
|
||||||
limit?: number,
|
limit?: number,
|
||||||
): Promise<TransactionSignature> {
|
): Promise<MangoSignatureStatus> {
|
||||||
return await this.sendAndConfirmTransactionForGroup(group, [
|
return await this.sendAndConfirmTransactionForGroup(group, [
|
||||||
await this.serum3CancelAllOrdersIx(
|
await this.serum3CancelAllOrdersIx(
|
||||||
group,
|
group,
|
||||||
|
@ -2076,7 +2080,7 @@ export class MangoClient {
|
||||||
group: Group,
|
group: Group,
|
||||||
mangoAccount: MangoAccount,
|
mangoAccount: MangoAccount,
|
||||||
externalMarketPk: PublicKey,
|
externalMarketPk: PublicKey,
|
||||||
): Promise<TransactionSignature> {
|
): Promise<MangoSignatureStatus> {
|
||||||
const ix = await this.serum3SettleFundsV2Ix(
|
const ix = await this.serum3SettleFundsV2Ix(
|
||||||
group,
|
group,
|
||||||
mangoAccount,
|
mangoAccount,
|
||||||
|
@ -2126,7 +2130,7 @@ export class MangoClient {
|
||||||
externalMarketPk: PublicKey,
|
externalMarketPk: PublicKey,
|
||||||
side: Serum3Side,
|
side: Serum3Side,
|
||||||
orderId: BN,
|
orderId: BN,
|
||||||
): Promise<TransactionSignature> {
|
): Promise<MangoSignatureStatus> {
|
||||||
const ixes = await Promise.all([
|
const ixes = await Promise.all([
|
||||||
this.serum3CancelOrderIx(
|
this.serum3CancelOrderIx(
|
||||||
group,
|
group,
|
||||||
|
@ -2173,7 +2177,7 @@ export class MangoClient {
|
||||||
settlePnlLimitFactor: number,
|
settlePnlLimitFactor: number,
|
||||||
settlePnlLimitWindowSize: number,
|
settlePnlLimitWindowSize: number,
|
||||||
positivePnlLiquidationFee: number,
|
positivePnlLiquidationFee: number,
|
||||||
): Promise<TransactionSignature> {
|
): Promise<MangoSignatureStatus> {
|
||||||
const bids = new Keypair();
|
const bids = new Keypair();
|
||||||
const asks = new Keypair();
|
const asks = new Keypair();
|
||||||
const eventQueue = new Keypair();
|
const eventQueue = new Keypair();
|
||||||
|
@ -2272,7 +2276,7 @@ export class MangoClient {
|
||||||
group: Group,
|
group: Group,
|
||||||
perpMarketIndex: PerpMarketIndex,
|
perpMarketIndex: PerpMarketIndex,
|
||||||
params: PerpEditParams,
|
params: PerpEditParams,
|
||||||
): Promise<TransactionSignature> {
|
): Promise<MangoSignatureStatus> {
|
||||||
const perpMarket = group.getPerpMarketByMarketIndex(perpMarketIndex);
|
const perpMarket = group.getPerpMarketByMarketIndex(perpMarketIndex);
|
||||||
|
|
||||||
const ix = await this.program.methods
|
const ix = await this.program.methods
|
||||||
|
@ -2325,7 +2329,7 @@ export class MangoClient {
|
||||||
perpMarketIndex: PerpMarketIndex,
|
perpMarketIndex: PerpMarketIndex,
|
||||||
accountA: MangoAccount,
|
accountA: MangoAccount,
|
||||||
accountB: MangoAccount,
|
accountB: MangoAccount,
|
||||||
): Promise<string> {
|
): Promise<MangoSignatureStatus> {
|
||||||
const perpMarket = group.getPerpMarketByMarketIndex(perpMarketIndex);
|
const perpMarket = group.getPerpMarketByMarketIndex(perpMarketIndex);
|
||||||
|
|
||||||
const ix = await this.program.methods
|
const ix = await this.program.methods
|
||||||
|
@ -2344,7 +2348,7 @@ export class MangoClient {
|
||||||
public async perpCloseMarket(
|
public async perpCloseMarket(
|
||||||
group: Group,
|
group: Group,
|
||||||
perpMarketIndex: PerpMarketIndex,
|
perpMarketIndex: PerpMarketIndex,
|
||||||
): Promise<TransactionSignature> {
|
): Promise<MangoSignatureStatus> {
|
||||||
const perpMarket = group.getPerpMarketByMarketIndex(perpMarketIndex);
|
const perpMarket = group.getPerpMarketByMarketIndex(perpMarketIndex);
|
||||||
|
|
||||||
const ix = await this.program.methods
|
const ix = await this.program.methods
|
||||||
|
@ -2410,7 +2414,7 @@ export class MangoClient {
|
||||||
group: Group,
|
group: Group,
|
||||||
mangoAccount: MangoAccount,
|
mangoAccount: MangoAccount,
|
||||||
perpMarketIndex: PerpMarketIndex,
|
perpMarketIndex: PerpMarketIndex,
|
||||||
): Promise<TransactionSignature> {
|
): Promise<MangoSignatureStatus> {
|
||||||
const ix = await this.perpDeactivatePositionIx(
|
const ix = await this.perpDeactivatePositionIx(
|
||||||
group,
|
group,
|
||||||
mangoAccount,
|
mangoAccount,
|
||||||
|
@ -2423,7 +2427,7 @@ export class MangoClient {
|
||||||
group: Group,
|
group: Group,
|
||||||
mangoAccount: MangoAccount,
|
mangoAccount: MangoAccount,
|
||||||
slippage = 0.01, // 1%, 100bps
|
slippage = 0.01, // 1%, 100bps
|
||||||
): Promise<TransactionSignature> {
|
): Promise<MangoSignatureStatus> {
|
||||||
if (mangoAccount.perpActive().length == 0) {
|
if (mangoAccount.perpActive().length == 0) {
|
||||||
throw new Error(`No perp positions found.`);
|
throw new Error(`No perp positions found.`);
|
||||||
}
|
}
|
||||||
|
@ -2447,7 +2451,7 @@ export class MangoClient {
|
||||||
pa.marketIndex,
|
pa.marketIndex,
|
||||||
isLong ? PerpOrderSide.ask : PerpOrderSide.bid,
|
isLong ? PerpOrderSide.ask : PerpOrderSide.bid,
|
||||||
pm.uiPrice * (isLong ? 1 - slippage : 1 + slippage), // Try to cross the spread to guarantee matching
|
pm.uiPrice * (isLong ? 1 - slippage : 1 + slippage), // Try to cross the spread to guarantee matching
|
||||||
pa.getBasePositionUi(pm) * 1.01, // Send a larger size to ensure full order is closed
|
Math.abs(pa.getBasePositionUi(pm) * 1.01), // Send a larger size to ensure full order is closed
|
||||||
undefined,
|
undefined,
|
||||||
Date.now(),
|
Date.now(),
|
||||||
PerpOrderType.immediateOrCancel,
|
PerpOrderType.immediateOrCancel,
|
||||||
|
@ -2485,7 +2489,7 @@ export class MangoClient {
|
||||||
reduceOnly?: boolean,
|
reduceOnly?: boolean,
|
||||||
expiryTimestamp?: number,
|
expiryTimestamp?: number,
|
||||||
limit?: number,
|
limit?: number,
|
||||||
): Promise<TransactionSignature> {
|
): Promise<MangoSignatureStatus> {
|
||||||
const ix = await this.perpPlaceOrderV2Ix(
|
const ix = await this.perpPlaceOrderV2Ix(
|
||||||
group,
|
group,
|
||||||
mangoAccount,
|
mangoAccount,
|
||||||
|
@ -2633,7 +2637,7 @@ export class MangoClient {
|
||||||
reduceOnly?: boolean,
|
reduceOnly?: boolean,
|
||||||
expiryTimestamp?: number,
|
expiryTimestamp?: number,
|
||||||
limit?: number,
|
limit?: number,
|
||||||
): Promise<TransactionSignature> {
|
): Promise<MangoSignatureStatus> {
|
||||||
const ix = await this.perpPlaceOrderPeggedV2Ix(
|
const ix = await this.perpPlaceOrderPeggedV2Ix(
|
||||||
group,
|
group,
|
||||||
mangoAccount,
|
mangoAccount,
|
||||||
|
@ -2774,6 +2778,26 @@ export class MangoClient {
|
||||||
.instruction();
|
.instruction();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async perpCancelOrderByClientOrderIdIx(
|
||||||
|
group: Group,
|
||||||
|
mangoAccount: MangoAccount,
|
||||||
|
perpMarketIndex: PerpMarketIndex,
|
||||||
|
clientOrderId: BN,
|
||||||
|
): Promise<TransactionInstruction> {
|
||||||
|
const perpMarket = group.getPerpMarketByMarketIndex(perpMarketIndex);
|
||||||
|
return await this.program.methods
|
||||||
|
.perpCancelOrderByClientOrderId(new BN(clientOrderId))
|
||||||
|
.accounts({
|
||||||
|
group: group.publicKey,
|
||||||
|
account: mangoAccount.publicKey,
|
||||||
|
owner: (this.program.provider as AnchorProvider).wallet.publicKey,
|
||||||
|
perpMarket: perpMarket.publicKey,
|
||||||
|
bids: perpMarket.bids,
|
||||||
|
asks: perpMarket.asks,
|
||||||
|
})
|
||||||
|
.instruction();
|
||||||
|
}
|
||||||
|
|
||||||
public async perpCancelOrderIx(
|
public async perpCancelOrderIx(
|
||||||
group: Group,
|
group: Group,
|
||||||
mangoAccount: MangoAccount,
|
mangoAccount: MangoAccount,
|
||||||
|
@ -2799,7 +2823,7 @@ export class MangoClient {
|
||||||
mangoAccount: MangoAccount,
|
mangoAccount: MangoAccount,
|
||||||
perpMarketIndex: PerpMarketIndex,
|
perpMarketIndex: PerpMarketIndex,
|
||||||
orderId: BN,
|
orderId: BN,
|
||||||
): Promise<TransactionSignature> {
|
): Promise<MangoSignatureStatus> {
|
||||||
const ix = await this.perpCancelOrderIx(
|
const ix = await this.perpCancelOrderIx(
|
||||||
group,
|
group,
|
||||||
mangoAccount,
|
mangoAccount,
|
||||||
|
@ -2815,7 +2839,7 @@ export class MangoClient {
|
||||||
mangoAccount: MangoAccount,
|
mangoAccount: MangoAccount,
|
||||||
perpMarketIndex: PerpMarketIndex,
|
perpMarketIndex: PerpMarketIndex,
|
||||||
limit: number,
|
limit: number,
|
||||||
): Promise<TransactionSignature> {
|
): Promise<MangoSignatureStatus> {
|
||||||
const ix = await this.perpCancelAllOrdersIx(
|
const ix = await this.perpCancelAllOrdersIx(
|
||||||
group,
|
group,
|
||||||
mangoAccount,
|
mangoAccount,
|
||||||
|
@ -2851,7 +2875,7 @@ export class MangoClient {
|
||||||
group: Group,
|
group: Group,
|
||||||
mangoAccount: MangoAccount,
|
mangoAccount: MangoAccount,
|
||||||
allMangoAccounts?: MangoAccount[],
|
allMangoAccounts?: MangoAccount[],
|
||||||
): Promise<TransactionSignature> {
|
): Promise<MangoSignatureStatus> {
|
||||||
if (!allMangoAccounts) {
|
if (!allMangoAccounts) {
|
||||||
allMangoAccounts = await client.getAllMangoAccounts(group, true);
|
allMangoAccounts = await client.getAllMangoAccounts(group, true);
|
||||||
}
|
}
|
||||||
|
@ -2932,7 +2956,7 @@ export class MangoClient {
|
||||||
settler: MangoAccount,
|
settler: MangoAccount,
|
||||||
perpMarketIndex: PerpMarketIndex,
|
perpMarketIndex: PerpMarketIndex,
|
||||||
maxSettleAmount?: number,
|
maxSettleAmount?: number,
|
||||||
): Promise<TransactionSignature> {
|
): Promise<MangoSignatureStatus> {
|
||||||
return await this.sendAndConfirmTransactionForGroup(group, [
|
return await this.sendAndConfirmTransactionForGroup(group, [
|
||||||
await this.perpSettlePnlIx(
|
await this.perpSettlePnlIx(
|
||||||
group,
|
group,
|
||||||
|
@ -2956,7 +2980,7 @@ export class MangoClient {
|
||||||
unprofitableAccount: MangoAccount,
|
unprofitableAccount: MangoAccount,
|
||||||
settler: MangoAccount,
|
settler: MangoAccount,
|
||||||
perpMarketIndex: PerpMarketIndex,
|
perpMarketIndex: PerpMarketIndex,
|
||||||
): Promise<TransactionSignature> {
|
): Promise<MangoSignatureStatus> {
|
||||||
return await this.sendAndConfirmTransactionForGroup(group, [
|
return await this.sendAndConfirmTransactionForGroup(group, [
|
||||||
await this.perpSettlePnlIx(
|
await this.perpSettlePnlIx(
|
||||||
group,
|
group,
|
||||||
|
@ -3012,7 +3036,7 @@ export class MangoClient {
|
||||||
account: MangoAccount,
|
account: MangoAccount,
|
||||||
perpMarketIndex: PerpMarketIndex,
|
perpMarketIndex: PerpMarketIndex,
|
||||||
maxSettleAmount?: number,
|
maxSettleAmount?: number,
|
||||||
): Promise<TransactionSignature> {
|
): Promise<MangoSignatureStatus> {
|
||||||
return await this.sendAndConfirmTransactionForGroup(group, [
|
return await this.sendAndConfirmTransactionForGroup(group, [
|
||||||
await this.perpSettleFeesIx(
|
await this.perpSettleFeesIx(
|
||||||
group,
|
group,
|
||||||
|
@ -3064,7 +3088,7 @@ export class MangoClient {
|
||||||
perpMarketIndex: PerpMarketIndex,
|
perpMarketIndex: PerpMarketIndex,
|
||||||
accounts: PublicKey[],
|
accounts: PublicKey[],
|
||||||
limit: number,
|
limit: number,
|
||||||
): Promise<TransactionSignature> {
|
): Promise<MangoSignatureStatus> {
|
||||||
return await this.sendAndConfirmTransactionForGroup(group, [
|
return await this.sendAndConfirmTransactionForGroup(group, [
|
||||||
await this.perpConsumeEventsIx(group, perpMarketIndex, accounts, limit),
|
await this.perpConsumeEventsIx(group, perpMarketIndex, accounts, limit),
|
||||||
]);
|
]);
|
||||||
|
@ -3162,7 +3186,7 @@ export class MangoClient {
|
||||||
userDefinedInstructions: TransactionInstruction[];
|
userDefinedInstructions: TransactionInstruction[];
|
||||||
userDefinedAlts: AddressLookupTableAccount[];
|
userDefinedAlts: AddressLookupTableAccount[];
|
||||||
flashLoanType: FlashLoanType;
|
flashLoanType: FlashLoanType;
|
||||||
}): Promise<TransactionSignature> {
|
}): Promise<MangoSignatureStatus> {
|
||||||
const isDelegate = (
|
const isDelegate = (
|
||||||
this.program.provider as AnchorProvider
|
this.program.provider as AnchorProvider
|
||||||
).wallet.publicKey.equals(mangoAccount.delegate);
|
).wallet.publicKey.equals(mangoAccount.delegate);
|
||||||
|
@ -3325,7 +3349,7 @@ export class MangoClient {
|
||||||
public async tokenUpdateIndexAndRate(
|
public async tokenUpdateIndexAndRate(
|
||||||
group: Group,
|
group: Group,
|
||||||
mintPk: PublicKey,
|
mintPk: PublicKey,
|
||||||
): Promise<TransactionSignature> {
|
): Promise<MangoSignatureStatus> {
|
||||||
return await this.sendAndConfirmTransactionForGroup(group, [
|
return await this.sendAndConfirmTransactionForGroup(group, [
|
||||||
await this.tokenUpdateIndexAndRateIx(group, mintPk),
|
await this.tokenUpdateIndexAndRateIx(group, mintPk),
|
||||||
]);
|
]);
|
||||||
|
@ -3365,7 +3389,7 @@ export class MangoClient {
|
||||||
assetMintPk: PublicKey,
|
assetMintPk: PublicKey,
|
||||||
liabMintPk: PublicKey,
|
liabMintPk: PublicKey,
|
||||||
maxLiabTransfer: number,
|
maxLiabTransfer: number,
|
||||||
): Promise<TransactionSignature> {
|
): Promise<MangoSignatureStatus> {
|
||||||
const assetBank: Bank = group.getFirstBankByMint(assetMintPk);
|
const assetBank: Bank = group.getFirstBankByMint(assetMintPk);
|
||||||
const liabBank: Bank = group.getFirstBankByMint(liabMintPk);
|
const liabBank: Bank = group.getFirstBankByMint(liabMintPk);
|
||||||
|
|
||||||
|
@ -3415,7 +3439,7 @@ export class MangoClient {
|
||||||
maxSellUi: number | null,
|
maxSellUi: number | null,
|
||||||
pricePremium: number | null,
|
pricePremium: number | null,
|
||||||
expiryTimestamp: number | null,
|
expiryTimestamp: number | null,
|
||||||
): Promise<TransactionSignature> {
|
): Promise<MangoSignatureStatus> {
|
||||||
if (account.getTokenBalanceUi(sellBank) < 0) {
|
if (account.getTokenBalanceUi(sellBank) < 0) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`Only allowed to take profits on deposits! Current balance ${account.getTokenBalanceUi(
|
`Only allowed to take profits on deposits! Current balance ${account.getTokenBalanceUi(
|
||||||
|
@ -3424,13 +3448,24 @@ export class MangoClient {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!thresholdPriceInSellPerBuyToken) {
|
||||||
|
thresholdPriceUi = 1 / thresholdPriceUi;
|
||||||
|
}
|
||||||
|
const thresholdPrice = toNativeSellPerBuyTokenPrice(
|
||||||
|
thresholdPriceUi,
|
||||||
|
sellBank,
|
||||||
|
buyBank,
|
||||||
|
);
|
||||||
|
const lowerLimit = 0;
|
||||||
|
const upperLimit = thresholdPrice;
|
||||||
|
|
||||||
return await this.tokenConditionalSwapCreate(
|
return await this.tokenConditionalSwapCreate(
|
||||||
group,
|
group,
|
||||||
account,
|
account,
|
||||||
sellBank,
|
sellBank,
|
||||||
buyBank,
|
buyBank,
|
||||||
thresholdPriceUi,
|
lowerLimit,
|
||||||
thresholdPriceInSellPerBuyToken,
|
upperLimit,
|
||||||
Number.MAX_SAFE_INTEGER,
|
Number.MAX_SAFE_INTEGER,
|
||||||
maxSellUi ?? account.getTokenBalanceUi(sellBank),
|
maxSellUi ?? account.getTokenBalanceUi(sellBank),
|
||||||
'TakeProfitOnDeposit',
|
'TakeProfitOnDeposit',
|
||||||
|
@ -3438,6 +3473,7 @@ export class MangoClient {
|
||||||
true,
|
true,
|
||||||
false,
|
false,
|
||||||
expiryTimestamp,
|
expiryTimestamp,
|
||||||
|
thresholdPriceInSellPerBuyToken,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3451,7 +3487,7 @@ export class MangoClient {
|
||||||
maxSellUi: number | null,
|
maxSellUi: number | null,
|
||||||
pricePremium: number | null,
|
pricePremium: number | null,
|
||||||
expiryTimestamp: number | null,
|
expiryTimestamp: number | null,
|
||||||
): Promise<TransactionSignature> {
|
): Promise<MangoSignatureStatus> {
|
||||||
if (account.getTokenBalanceUi(sellBank) < 0) {
|
if (account.getTokenBalanceUi(sellBank) < 0) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`Only allowed to set a stop loss on deposits! Current balance ${account.getTokenBalanceUi(
|
`Only allowed to set a stop loss on deposits! Current balance ${account.getTokenBalanceUi(
|
||||||
|
@ -3460,13 +3496,24 @@ export class MangoClient {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!thresholdPriceInSellPerBuyToken) {
|
||||||
|
thresholdPriceUi = 1 / thresholdPriceUi;
|
||||||
|
}
|
||||||
|
const thresholdPrice = toNativeSellPerBuyTokenPrice(
|
||||||
|
thresholdPriceUi,
|
||||||
|
sellBank,
|
||||||
|
buyBank,
|
||||||
|
);
|
||||||
|
const lowerLimit = thresholdPrice;
|
||||||
|
const upperLimit = Number.MAX_SAFE_INTEGER;
|
||||||
|
|
||||||
return await this.tokenConditionalSwapCreate(
|
return await this.tokenConditionalSwapCreate(
|
||||||
group,
|
group,
|
||||||
account,
|
account,
|
||||||
sellBank,
|
sellBank,
|
||||||
buyBank,
|
buyBank,
|
||||||
thresholdPriceUi,
|
lowerLimit,
|
||||||
thresholdPriceInSellPerBuyToken,
|
upperLimit,
|
||||||
Number.MAX_SAFE_INTEGER,
|
Number.MAX_SAFE_INTEGER,
|
||||||
maxSellUi ?? account.getTokenBalanceUi(sellBank),
|
maxSellUi ?? account.getTokenBalanceUi(sellBank),
|
||||||
'StopLossOnDeposit',
|
'StopLossOnDeposit',
|
||||||
|
@ -3474,6 +3521,7 @@ export class MangoClient {
|
||||||
true,
|
true,
|
||||||
false,
|
false,
|
||||||
expiryTimestamp,
|
expiryTimestamp,
|
||||||
|
thresholdPriceInSellPerBuyToken,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3488,7 +3536,7 @@ export class MangoClient {
|
||||||
pricePremium: number | null,
|
pricePremium: number | null,
|
||||||
allowMargin: boolean | null,
|
allowMargin: boolean | null,
|
||||||
expiryTimestamp: number | null,
|
expiryTimestamp: number | null,
|
||||||
): Promise<TransactionSignature> {
|
): Promise<MangoSignatureStatus> {
|
||||||
if (account.getTokenBalanceUi(buyBank) > 0) {
|
if (account.getTokenBalanceUi(buyBank) > 0) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`Only allowed to take profits on borrows! Current balance ${account.getTokenBalanceUi(
|
`Only allowed to take profits on borrows! Current balance ${account.getTokenBalanceUi(
|
||||||
|
@ -3497,13 +3545,24 @@ export class MangoClient {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!thresholdPriceInSellPerBuyToken) {
|
||||||
|
thresholdPriceUi = 1 / thresholdPriceUi;
|
||||||
|
}
|
||||||
|
const thresholdPrice = toNativeSellPerBuyTokenPrice(
|
||||||
|
thresholdPriceUi,
|
||||||
|
sellBank,
|
||||||
|
buyBank,
|
||||||
|
);
|
||||||
|
const lowerLimit = thresholdPrice;
|
||||||
|
const upperLimit = Number.MAX_SAFE_INTEGER;
|
||||||
|
|
||||||
return await this.tokenConditionalSwapCreate(
|
return await this.tokenConditionalSwapCreate(
|
||||||
group,
|
group,
|
||||||
account,
|
account,
|
||||||
sellBank,
|
sellBank,
|
||||||
buyBank,
|
buyBank,
|
||||||
thresholdPriceUi,
|
lowerLimit,
|
||||||
thresholdPriceInSellPerBuyToken,
|
upperLimit,
|
||||||
maxBuyUi ?? -account.getTokenBalanceUi(buyBank),
|
maxBuyUi ?? -account.getTokenBalanceUi(buyBank),
|
||||||
Number.MAX_SAFE_INTEGER,
|
Number.MAX_SAFE_INTEGER,
|
||||||
'TakeProfitOnBorrow',
|
'TakeProfitOnBorrow',
|
||||||
|
@ -3511,6 +3570,7 @@ export class MangoClient {
|
||||||
false,
|
false,
|
||||||
allowMargin ?? false,
|
allowMargin ?? false,
|
||||||
expiryTimestamp,
|
expiryTimestamp,
|
||||||
|
thresholdPriceInSellPerBuyToken,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3525,7 +3585,7 @@ export class MangoClient {
|
||||||
pricePremium: number | null,
|
pricePremium: number | null,
|
||||||
allowMargin: boolean | null,
|
allowMargin: boolean | null,
|
||||||
expiryTimestamp: number | null,
|
expiryTimestamp: number | null,
|
||||||
): Promise<TransactionSignature> {
|
): Promise<MangoSignatureStatus> {
|
||||||
if (account.getTokenBalanceUi(buyBank) > 0) {
|
if (account.getTokenBalanceUi(buyBank) > 0) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`Only allowed to set stop loss on borrows! Current balance ${account.getTokenBalanceUi(
|
`Only allowed to set stop loss on borrows! Current balance ${account.getTokenBalanceUi(
|
||||||
|
@ -3534,13 +3594,24 @@ export class MangoClient {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!thresholdPriceInSellPerBuyToken) {
|
||||||
|
thresholdPriceUi = 1 / thresholdPriceUi;
|
||||||
|
}
|
||||||
|
const thresholdPrice = toNativeSellPerBuyTokenPrice(
|
||||||
|
thresholdPriceUi,
|
||||||
|
sellBank,
|
||||||
|
buyBank,
|
||||||
|
);
|
||||||
|
const lowerLimit = 0;
|
||||||
|
const upperLimit = thresholdPrice;
|
||||||
|
|
||||||
return await this.tokenConditionalSwapCreate(
|
return await this.tokenConditionalSwapCreate(
|
||||||
group,
|
group,
|
||||||
account,
|
account,
|
||||||
sellBank,
|
sellBank,
|
||||||
buyBank,
|
buyBank,
|
||||||
thresholdPriceUi,
|
lowerLimit,
|
||||||
thresholdPriceInSellPerBuyToken,
|
upperLimit,
|
||||||
maxBuyUi ?? -account.getTokenBalanceUi(buyBank),
|
maxBuyUi ?? -account.getTokenBalanceUi(buyBank),
|
||||||
Number.MAX_SAFE_INTEGER,
|
Number.MAX_SAFE_INTEGER,
|
||||||
'StopLossOnBorrow',
|
'StopLossOnBorrow',
|
||||||
|
@ -3548,6 +3619,7 @@ export class MangoClient {
|
||||||
false,
|
false,
|
||||||
allowMargin ?? false,
|
allowMargin ?? false,
|
||||||
expiryTimestamp,
|
expiryTimestamp,
|
||||||
|
thresholdPriceInSellPerBuyToken,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3556,8 +3628,8 @@ export class MangoClient {
|
||||||
account: MangoAccount,
|
account: MangoAccount,
|
||||||
sellBank: Bank,
|
sellBank: Bank,
|
||||||
buyBank: Bank,
|
buyBank: Bank,
|
||||||
thresholdPriceUi: number,
|
lowerLimit: number,
|
||||||
thresholdPriceInSellPerBuyToken: boolean,
|
upperLimit: number,
|
||||||
maxBuyUi: number,
|
maxBuyUi: number,
|
||||||
maxSellUi: number,
|
maxSellUi: number,
|
||||||
tcsIntention:
|
tcsIntention:
|
||||||
|
@ -3570,50 +3642,43 @@ export class MangoClient {
|
||||||
allowCreatingDeposits: boolean,
|
allowCreatingDeposits: boolean,
|
||||||
allowCreatingBorrows: boolean,
|
allowCreatingBorrows: boolean,
|
||||||
expiryTimestamp: number | null,
|
expiryTimestamp: number | null,
|
||||||
): Promise<TransactionSignature> {
|
displayPriceInSellTokenPerBuyToken: boolean,
|
||||||
const maxBuy =
|
): Promise<MangoSignatureStatus> {
|
||||||
maxBuyUi == Number.MAX_SAFE_INTEGER
|
let maxBuy, maxSell, buyAmountInUsd, sellAmountInUsd;
|
||||||
? U64_MAX_BN
|
if (maxBuyUi == Number.MAX_SAFE_INTEGER) {
|
||||||
: toNative(maxBuyUi, buyBank.mintDecimals);
|
maxBuy = U64_MAX_BN;
|
||||||
const maxSell =
|
} else {
|
||||||
maxSellUi == Number.MAX_SAFE_INTEGER
|
buyAmountInUsd = maxBuyUi * buyBank.uiPrice;
|
||||||
? U64_MAX_BN
|
maxBuy = toNative(maxBuyUi, buyBank.mintDecimals);
|
||||||
: toNative(maxSellUi, sellBank.mintDecimals);
|
}
|
||||||
|
if (maxSellUi == Number.MAX_SAFE_INTEGER) {
|
||||||
if (!thresholdPriceInSellPerBuyToken) {
|
maxSell = U64_MAX_BN;
|
||||||
thresholdPriceUi = 1 / thresholdPriceUi;
|
} else {
|
||||||
|
sellAmountInUsd = maxSellUi * sellBank.uiPrice;
|
||||||
|
maxSell = toNative(maxSellUi, sellBank.mintDecimals);
|
||||||
}
|
}
|
||||||
|
|
||||||
let lowerLimit, upperLimit;
|
// Used for computing optimal premium
|
||||||
const thresholdPrice = toNativeSellPerBuyTokenPrice(
|
let liqorTcsChunkSizeInUsd = Math.min(buyAmountInUsd, sellAmountInUsd);
|
||||||
thresholdPriceUi,
|
if (liqorTcsChunkSizeInUsd > 5000) {
|
||||||
sellBank,
|
liqorTcsChunkSizeInUsd = 5000;
|
||||||
buyBank,
|
}
|
||||||
);
|
// For small TCS swaps, reduce chunk size to 1000 USD
|
||||||
const sellTokenPerBuyTokenPrice = buyBank.price
|
else {
|
||||||
.div(sellBank.price)
|
liqorTcsChunkSizeInUsd = 1000;
|
||||||
.toNumber();
|
|
||||||
|
|
||||||
if (
|
|
||||||
tcsIntention == 'TakeProfitOnDeposit' ||
|
|
||||||
tcsIntention == 'StopLossOnBorrow' ||
|
|
||||||
(tcsIntention == null && thresholdPrice > sellTokenPerBuyTokenPrice)
|
|
||||||
) {
|
|
||||||
lowerLimit = thresholdPrice;
|
|
||||||
upperLimit = Number.MAX_SAFE_INTEGER;
|
|
||||||
} else {
|
|
||||||
lowerLimit = 0;
|
|
||||||
upperLimit = thresholdPrice;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!pricePremium) {
|
if (!pricePremium) {
|
||||||
|
if (maxBuy.eq(U64_MAX_BN)) {
|
||||||
|
maxSell.toNumber() * sellBank.uiPrice;
|
||||||
|
}
|
||||||
const buyTokenPriceImpact = group.getPriceImpactByTokenIndex(
|
const buyTokenPriceImpact = group.getPriceImpactByTokenIndex(
|
||||||
buyBank.tokenIndex,
|
buyBank.tokenIndex,
|
||||||
5000,
|
liqorTcsChunkSizeInUsd,
|
||||||
);
|
);
|
||||||
const sellTokenPriceImpact = group.getPriceImpactByTokenIndex(
|
const sellTokenPriceImpact = group.getPriceImpactByTokenIndex(
|
||||||
sellBank.tokenIndex,
|
sellBank.tokenIndex,
|
||||||
5000,
|
liqorTcsChunkSizeInUsd,
|
||||||
);
|
);
|
||||||
pricePremium =
|
pricePremium =
|
||||||
((1 + buyTokenPriceImpact / 100) * (1 + sellTokenPriceImpact / 100) -
|
((1 + buyTokenPriceImpact / 100) * (1 + sellTokenPriceImpact / 100) -
|
||||||
|
@ -3650,7 +3715,7 @@ export class MangoClient {
|
||||||
pricePremiumRate,
|
pricePremiumRate,
|
||||||
allowCreatingDeposits,
|
allowCreatingDeposits,
|
||||||
allowCreatingBorrows,
|
allowCreatingBorrows,
|
||||||
thresholdPriceInSellPerBuyToken
|
displayPriceInSellTokenPerBuyToken
|
||||||
? TokenConditionalSwapDisplayPriceStyle.sellTokenPerBuyToken
|
? TokenConditionalSwapDisplayPriceStyle.sellTokenPerBuyToken
|
||||||
: TokenConditionalSwapDisplayPriceStyle.buyTokenPerSellToken,
|
: TokenConditionalSwapDisplayPriceStyle.buyTokenPerSellToken,
|
||||||
intention,
|
intention,
|
||||||
|
@ -3672,7 +3737,7 @@ export class MangoClient {
|
||||||
allowCreatingBorrows: boolean,
|
allowCreatingBorrows: boolean,
|
||||||
priceDisplayStyle: TokenConditionalSwapDisplayPriceStyle,
|
priceDisplayStyle: TokenConditionalSwapDisplayPriceStyle,
|
||||||
intention: TokenConditionalSwapIntention,
|
intention: TokenConditionalSwapIntention,
|
||||||
): Promise<TransactionSignature> {
|
): Promise<MangoSignatureStatus> {
|
||||||
const buyBank: Bank = group.getFirstBankByMint(buyMintPk);
|
const buyBank: Bank = group.getFirstBankByMint(buyMintPk);
|
||||||
const sellBank: Bank = group.getFirstBankByMint(sellMintPk);
|
const sellBank: Bank = group.getFirstBankByMint(sellMintPk);
|
||||||
const tcsIx = await this.program.methods
|
const tcsIx = await this.program.methods
|
||||||
|
@ -3720,7 +3785,7 @@ export class MangoClient {
|
||||||
group: Group,
|
group: Group,
|
||||||
account: MangoAccount,
|
account: MangoAccount,
|
||||||
tokenConditionalSwapId: BN,
|
tokenConditionalSwapId: BN,
|
||||||
): Promise<TransactionSignature> {
|
): Promise<MangoSignatureStatus> {
|
||||||
const tokenConditionalSwapIndex = account.tokenConditionalSwaps.findIndex(
|
const tokenConditionalSwapIndex = account.tokenConditionalSwaps.findIndex(
|
||||||
(tcs) => tcs.id.eq(tokenConditionalSwapId),
|
(tcs) => tcs.id.eq(tokenConditionalSwapId),
|
||||||
);
|
);
|
||||||
|
@ -3752,7 +3817,7 @@ export class MangoClient {
|
||||||
public async tokenConditionalSwapCancelAll(
|
public async tokenConditionalSwapCancelAll(
|
||||||
group: Group,
|
group: Group,
|
||||||
account: MangoAccount,
|
account: MangoAccount,
|
||||||
): Promise<TransactionSignature> {
|
): Promise<MangoSignatureStatus> {
|
||||||
const ixs = await Promise.all(
|
const ixs = await Promise.all(
|
||||||
account.tokenConditionalSwaps
|
account.tokenConditionalSwaps
|
||||||
.filter((tcs) => tcs.hasData)
|
.filter((tcs) => tcs.hasData)
|
||||||
|
@ -3785,7 +3850,7 @@ export class MangoClient {
|
||||||
tokenConditionalSwapId: BN,
|
tokenConditionalSwapId: BN,
|
||||||
maxBuyTokenToLiqee: number,
|
maxBuyTokenToLiqee: number,
|
||||||
maxSellTokenToLiqor: number,
|
maxSellTokenToLiqor: number,
|
||||||
): Promise<TransactionSignature> {
|
): Promise<MangoSignatureStatus> {
|
||||||
const tokenConditionalSwapIndex = liqee.tokenConditionalSwaps.findIndex(
|
const tokenConditionalSwapIndex = liqee.tokenConditionalSwaps.findIndex(
|
||||||
(tcs) => tcs.id.eq(tokenConditionalSwapId),
|
(tcs) => tcs.id.eq(tokenConditionalSwapId),
|
||||||
);
|
);
|
||||||
|
@ -3841,7 +3906,7 @@ export class MangoClient {
|
||||||
group: Group,
|
group: Group,
|
||||||
addressLookupTable: PublicKey,
|
addressLookupTable: PublicKey,
|
||||||
index: number,
|
index: number,
|
||||||
): Promise<TransactionSignature> {
|
): Promise<MangoSignatureStatus> {
|
||||||
const ix = await this.program.methods
|
const ix = await this.program.methods
|
||||||
.altSet(index)
|
.altSet(index)
|
||||||
.accounts({
|
.accounts({
|
||||||
|
@ -3859,7 +3924,7 @@ export class MangoClient {
|
||||||
addressLookupTable: PublicKey,
|
addressLookupTable: PublicKey,
|
||||||
index: number,
|
index: number,
|
||||||
pks: PublicKey[],
|
pks: PublicKey[],
|
||||||
): Promise<TransactionSignature> {
|
): Promise<MangoSignatureStatus> {
|
||||||
const ix = await this.program.methods
|
const ix = await this.program.methods
|
||||||
.altExtend(index, pks)
|
.altExtend(index, pks)
|
||||||
.accounts({
|
.accounts({
|
||||||
|
@ -4143,7 +4208,7 @@ export class MangoClient {
|
||||||
reduceOnly?: boolean,
|
reduceOnly?: boolean,
|
||||||
expiryTimestamp?: number,
|
expiryTimestamp?: number,
|
||||||
limit?: number,
|
limit?: number,
|
||||||
): Promise<TransactionSignature> {
|
): Promise<MangoSignatureStatus> {
|
||||||
const transactionInstructions: TransactionInstruction[] = [];
|
const transactionInstructions: TransactionInstruction[] = [];
|
||||||
const [cancelOrderIx, placeOrderIx] = await Promise.all([
|
const [cancelOrderIx, placeOrderIx] = await Promise.all([
|
||||||
this.perpCancelOrderIx(group, mangoAccount, perpMarketIndex, orderId),
|
this.perpCancelOrderIx(group, mangoAccount, perpMarketIndex, orderId),
|
||||||
|
@ -4181,7 +4246,7 @@ export class MangoClient {
|
||||||
orderType: Serum3OrderType,
|
orderType: Serum3OrderType,
|
||||||
clientOrderId: number,
|
clientOrderId: number,
|
||||||
limit: number,
|
limit: number,
|
||||||
): Promise<TransactionSignature> {
|
): Promise<MangoSignatureStatus> {
|
||||||
const transactionInstructions: TransactionInstruction[] = [];
|
const transactionInstructions: TransactionInstruction[] = [];
|
||||||
const [cancelOrderIx, settleIx, placeOrderIx] = await Promise.all([
|
const [cancelOrderIx, settleIx, placeOrderIx] = await Promise.all([
|
||||||
this.serum3CancelOrderIx(
|
this.serum3CancelOrderIx(
|
||||||
|
|
|
@ -8,7 +8,14 @@ export class Id {
|
||||||
public publicKey: string,
|
public publicKey: string,
|
||||||
public serum3ProgramId: string,
|
public serum3ProgramId: string,
|
||||||
public mangoProgramId: string,
|
public mangoProgramId: string,
|
||||||
public banks: { name: string; publicKey: string; active: boolean }[],
|
public banks: {
|
||||||
|
name: string;
|
||||||
|
mint: string;
|
||||||
|
tokenIndex: number;
|
||||||
|
publicKey: string;
|
||||||
|
active: boolean;
|
||||||
|
decimals: number;
|
||||||
|
}[],
|
||||||
public stubOracles: { name: string; publicKey: string }[],
|
public stubOracles: { name: string; publicKey: string }[],
|
||||||
public mintInfos: { name: string; publicKey: string }[],
|
public mintInfos: { name: string; publicKey: string }[],
|
||||||
public serum3Markets: {
|
public serum3Markets: {
|
||||||
|
@ -23,7 +30,7 @@ export class Id {
|
||||||
public getBanks(): PublicKey[] {
|
public getBanks(): PublicKey[] {
|
||||||
return Array.from(
|
return Array.from(
|
||||||
this.banks
|
this.banks
|
||||||
.filter((perpMarket) => perpMarket.active)
|
.filter((bank) => bank.active)
|
||||||
.map((bank) => new PublicKey(bank.publicKey)),
|
.map((bank) => new PublicKey(bank.publicKey)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -43,19 +50,26 @@ export class Id {
|
||||||
public getSerum3Markets(): PublicKey[] {
|
public getSerum3Markets(): PublicKey[] {
|
||||||
return Array.from(
|
return Array.from(
|
||||||
this.serum3Markets
|
this.serum3Markets
|
||||||
.filter((perpMarket) => perpMarket.active)
|
.filter((serum3Market) => serum3Market.active)
|
||||||
.map((serum3Market) => new PublicKey(serum3Market.publicKey)),
|
.map((serum3Market) => new PublicKey(serum3Market.publicKey)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public getSerum3ExternalMarkets(): PublicKey[] {
|
||||||
|
return Array.from(
|
||||||
|
this.serum3Markets
|
||||||
|
.filter((serum3Market) => serum3Market.active)
|
||||||
|
.map((serum3Market) => new PublicKey(serum3Market.marketExternal)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
public getPerpMarkets(): PublicKey[] {
|
public getPerpMarkets(): PublicKey[] {
|
||||||
return Array.from(
|
return Array.from(
|
||||||
this.perpMarkets
|
this.perpMarkets.map((perpMarket) => new PublicKey(perpMarket.publicKey)),
|
||||||
.filter((perpMarket) => perpMarket.active)
|
|
||||||
.map((perpMarket) => new PublicKey(perpMarket.publicKey)),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DEPRECATED
|
||||||
static fromIdsByName(name: string): Id {
|
static fromIdsByName(name: string): Id {
|
||||||
const groupConfig = ids.groups.find((id) => id['name'] === name);
|
const groupConfig = ids.groups.find((id) => id['name'] === name);
|
||||||
if (!groupConfig) throw new Error(`No group config ${name} found in Ids!`);
|
if (!groupConfig) throw new Error(`No group config ${name} found in Ids!`);
|
||||||
|
@ -73,6 +87,7 @@ export class Id {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DEPRECATED
|
||||||
static fromIdsByPk(groupPk: PublicKey): Id {
|
static fromIdsByPk(groupPk: PublicKey): Id {
|
||||||
const groupConfig = ids.groups.find(
|
const groupConfig = ids.groups.find(
|
||||||
(id) => id['publicKey'] === groupPk.toString(),
|
(id) => id['publicKey'] === groupPk.toString(),
|
||||||
|
@ -115,6 +130,8 @@ export class Id {
|
||||||
tokenIndex: t.tokenIndex,
|
tokenIndex: t.tokenIndex,
|
||||||
bankNum: b.bankNum,
|
bankNum: b.bankNum,
|
||||||
publicKey: b.publicKey,
|
publicKey: b.publicKey,
|
||||||
|
active: t.active,
|
||||||
|
decimals: t.decimals,
|
||||||
})),
|
})),
|
||||||
),
|
),
|
||||||
groupConfig.stubOracles.map((s) => ({
|
groupConfig.stubOracles.map((s) => ({
|
||||||
|
@ -126,15 +143,18 @@ export class Id {
|
||||||
mint: t.mint,
|
mint: t.mint,
|
||||||
tokenIndex: t.tokenIndex,
|
tokenIndex: t.tokenIndex,
|
||||||
publicKey: t.mintInfo,
|
publicKey: t.mintInfo,
|
||||||
|
active: t.active,
|
||||||
})),
|
})),
|
||||||
groupConfig.serum3Markets.map((s) => ({
|
groupConfig.serum3Markets.map((s) => ({
|
||||||
name: s.name,
|
name: s.name,
|
||||||
publicKey: s.publicKey,
|
publicKey: s.publicKey,
|
||||||
marketExternal: s.marketExternal,
|
marketExternal: s.serumMarketExternal,
|
||||||
|
active: s.active,
|
||||||
})),
|
})),
|
||||||
groupConfig.perpMarkets.map((p) => ({
|
groupConfig.perpMarkets.map((p) => ({
|
||||||
name: p.name,
|
name: p.name,
|
||||||
publicKey: p.publicKey,
|
publicKey: p.publicKey,
|
||||||
|
active: p.active,
|
||||||
})),
|
})),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,4 +26,5 @@ export * from './router';
|
||||||
export * from './stats';
|
export * from './stats';
|
||||||
export * from './types';
|
export * from './types';
|
||||||
export * from './utils';
|
export * from './utils';
|
||||||
|
export * from './utils/rpc';
|
||||||
export { Group, MANGO_V4_ID, MangoClient, OracleProvider, StubOracle };
|
export { Group, MANGO_V4_ID, MangoClient, OracleProvider, StubOracle };
|
||||||
|
|
|
@ -8262,14 +8262,28 @@ export type MangoV4 = {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "changeAmount",
|
"name": "changeAmount",
|
||||||
|
"docs": [
|
||||||
|
"The amount by which the user's token position changed at the end",
|
||||||
|
"",
|
||||||
|
"So if the user repaid the approved_amount in full, it'd be 0.",
|
||||||
|
"",
|
||||||
|
"Does NOT include the loan_origination_fee or deposit_fee, so the true",
|
||||||
|
"change is `change_amount - loan_origination_fee - deposit_fee`."
|
||||||
|
],
|
||||||
"type": "i128"
|
"type": "i128"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "loan",
|
"name": "loan",
|
||||||
|
"docs": [
|
||||||
|
"The amount that was a loan (<= approved_amount, depends on user's deposits)"
|
||||||
|
],
|
||||||
"type": "i128"
|
"type": "i128"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "loanOriginationFee",
|
"name": "loanOriginationFee",
|
||||||
|
"docs": [
|
||||||
|
"The fee paid on the loan, not included in `loan` or `change_amount`"
|
||||||
|
],
|
||||||
"type": "i128"
|
"type": "i128"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -8286,7 +8300,19 @@ export type MangoV4 = {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "depositFee",
|
"name": "depositFee",
|
||||||
|
"docs": [
|
||||||
|
"Deposit fee paid for positive change_amount.",
|
||||||
|
"",
|
||||||
|
"Not factored into change_amount."
|
||||||
|
],
|
||||||
"type": "i128"
|
"type": "i128"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "approvedAmount",
|
||||||
|
"docs": [
|
||||||
|
"The amount that was transfered out to the user"
|
||||||
|
],
|
||||||
|
"type": "u64"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -20831,14 +20857,28 @@ export const IDL: MangoV4 = {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "changeAmount",
|
"name": "changeAmount",
|
||||||
|
"docs": [
|
||||||
|
"The amount by which the user's token position changed at the end",
|
||||||
|
"",
|
||||||
|
"So if the user repaid the approved_amount in full, it'd be 0.",
|
||||||
|
"",
|
||||||
|
"Does NOT include the loan_origination_fee or deposit_fee, so the true",
|
||||||
|
"change is `change_amount - loan_origination_fee - deposit_fee`."
|
||||||
|
],
|
||||||
"type": "i128"
|
"type": "i128"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "loan",
|
"name": "loan",
|
||||||
|
"docs": [
|
||||||
|
"The amount that was a loan (<= approved_amount, depends on user's deposits)"
|
||||||
|
],
|
||||||
"type": "i128"
|
"type": "i128"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "loanOriginationFee",
|
"name": "loanOriginationFee",
|
||||||
|
"docs": [
|
||||||
|
"The fee paid on the loan, not included in `loan` or `change_amount`"
|
||||||
|
],
|
||||||
"type": "i128"
|
"type": "i128"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -20855,7 +20895,19 @@ export const IDL: MangoV4 = {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "depositFee",
|
"name": "depositFee",
|
||||||
|
"docs": [
|
||||||
|
"Deposit fee paid for positive change_amount.",
|
||||||
|
"",
|
||||||
|
"Not factored into change_amount."
|
||||||
|
],
|
||||||
"type": "i128"
|
"type": "i128"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "approvedAmount",
|
||||||
|
"docs": [
|
||||||
|
"The amount that was transfered out to the user"
|
||||||
|
],
|
||||||
|
"type": "u64"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,7 +73,7 @@ export function computePriceImpactOnJup(
|
||||||
(pi) => pi.symbol == tokenName && pi.target_amount == closestTo,
|
(pi) => pi.symbol == tokenName && pi.target_amount == closestTo,
|
||||||
);
|
);
|
||||||
if (filteredPis.length > 0) {
|
if (filteredPis.length > 0) {
|
||||||
return (filteredPis[0].max_price_impact_percent * 10000) / 100;
|
return (filteredPis[0].avg_price_impact_percent * 10000) / 100;
|
||||||
} else {
|
} else {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,16 +5,27 @@ import {
|
||||||
ComputeBudgetProgram,
|
ComputeBudgetProgram,
|
||||||
MessageV0,
|
MessageV0,
|
||||||
Signer,
|
Signer,
|
||||||
|
TransactionConfirmationStatus,
|
||||||
|
TransactionError,
|
||||||
TransactionInstruction,
|
TransactionInstruction,
|
||||||
|
TransactionSignature,
|
||||||
VersionedTransaction,
|
VersionedTransaction,
|
||||||
} from '@solana/web3.js';
|
} from '@solana/web3.js';
|
||||||
|
|
||||||
|
export interface MangoSignatureStatus {
|
||||||
|
slot: number;
|
||||||
|
confirmations: number | null;
|
||||||
|
err: TransactionError | null;
|
||||||
|
confirmationStatus?: TransactionConfirmationStatus;
|
||||||
|
signature: TransactionSignature;
|
||||||
|
}
|
||||||
|
|
||||||
export async function sendTransaction(
|
export async function sendTransaction(
|
||||||
provider: AnchorProvider,
|
provider: AnchorProvider,
|
||||||
ixs: TransactionInstruction[],
|
ixs: TransactionInstruction[],
|
||||||
alts: AddressLookupTableAccount[],
|
alts: AddressLookupTableAccount[],
|
||||||
opts: any = {},
|
opts: any = {},
|
||||||
): Promise<string> {
|
): Promise<MangoSignatureStatus> {
|
||||||
const connection = provider.connection;
|
const connection = provider.connection;
|
||||||
const latestBlockhash =
|
const latestBlockhash =
|
||||||
opts.latestBlockhash ??
|
opts.latestBlockhash ??
|
||||||
|
@ -102,7 +113,7 @@ export async function sendTransaction(
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return signature;
|
return { signature, ...status };
|
||||||
}
|
}
|
||||||
|
|
||||||
export const createComputeBudgetIx = (
|
export const createComputeBudgetIx = (
|
||||||
|
|
Loading…
Reference in New Issue