wip - margin trade with orca
This commit is contained in:
parent
e7d5b7cff9
commit
d4097e5fc2
|
@ -0,0 +1,59 @@
|
||||||
|
{
|
||||||
|
"name": "@blockworks-foundation/mango-client",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"description": "Typescript Client for mango-v4 program.",
|
||||||
|
"main": "lib/src/index.js",
|
||||||
|
"types": "lib/src/index.d.ts",
|
||||||
|
"repository": "https://github.com/blockworks-foundation/mango-v4",
|
||||||
|
"scripts": {
|
||||||
|
"build": "tsc",
|
||||||
|
"clean": "rm -rf dist",
|
||||||
|
"example1-user": "ts-node src/scripts/example1-user.ts",
|
||||||
|
"example1-admin": "ts-node src/scripts/example1-admin.ts",
|
||||||
|
"format": "prettier --check .",
|
||||||
|
"lint": "eslint . --ext ts --ext tsx --ext js --quiet",
|
||||||
|
"type-check": "tsc --pretty --noEmit"
|
||||||
|
},
|
||||||
|
"author": {
|
||||||
|
"name": "Blockworks Foundation",
|
||||||
|
"email": "hello@blockworks.foundation",
|
||||||
|
"url": "https://blockworks.foundation"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@tsconfig/recommended": "^1.0.1",
|
||||||
|
"@types/chai": "^4.3.0",
|
||||||
|
"@types/mocha": "^9.1.0",
|
||||||
|
"@types/node": "^14.14.37",
|
||||||
|
"@typescript-eslint/eslint-plugin": "^4.14.2",
|
||||||
|
"@typescript-eslint/parser": "^4.14.2",
|
||||||
|
"chai": "^4.3.4",
|
||||||
|
"eslint": "^7.28.0",
|
||||||
|
"eslint-config-prettier": "^7.2.0",
|
||||||
|
"mocha": "^9.1.3",
|
||||||
|
"prettier": "^2.0.5",
|
||||||
|
"ts-mocha": "^8.0.0",
|
||||||
|
"ts-node": "^9.1.1",
|
||||||
|
"typedoc": "^0.22.5",
|
||||||
|
"typescript": "^4.4.4"
|
||||||
|
},
|
||||||
|
"publishConfig": {
|
||||||
|
"access": "public"
|
||||||
|
},
|
||||||
|
"prettier": {
|
||||||
|
"singleQuote": true,
|
||||||
|
"trailingComma": "all"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@orca-so/sdk": "^1.2.24",
|
||||||
|
"@project-serum/anchor": "^0.24.2",
|
||||||
|
"@project-serum/serum": "^0.13.65",
|
||||||
|
"@solana/spl-token": "^0.2.0",
|
||||||
|
"@types/bs58": "^4.0.1",
|
||||||
|
"big.js": "^6.1.1",
|
||||||
|
"bs58": "^5.0.0"
|
||||||
|
},
|
||||||
|
"resolutions": {
|
||||||
|
"@solana/spl-token": "^0.2.0"
|
||||||
|
},
|
||||||
|
"license": "MIT"
|
||||||
|
}
|
|
@ -2,6 +2,8 @@ import { AnchorProvider, BN, Program, Provider } from '@project-serum/anchor';
|
||||||
import { getFeeRates, getFeeTier, Market } from '@project-serum/serum';
|
import { getFeeRates, getFeeTier, Market } from '@project-serum/serum';
|
||||||
import { Order } from '@project-serum/serum/lib/market';
|
import { Order } from '@project-serum/serum/lib/market';
|
||||||
import * as spl from '@solana/spl-token';
|
import * as spl from '@solana/spl-token';
|
||||||
|
import { TokenSwap } from '@solana/spl-token-swap';
|
||||||
|
import { TOKEN_PROGRAM_ID } from '@solana/spl-token';
|
||||||
import {
|
import {
|
||||||
AccountMeta,
|
AccountMeta,
|
||||||
Keypair,
|
Keypair,
|
||||||
|
@ -12,6 +14,9 @@ import {
|
||||||
TransactionSignature,
|
TransactionSignature,
|
||||||
} from '@solana/web3.js';
|
} from '@solana/web3.js';
|
||||||
import bs58 from 'bs58';
|
import bs58 from 'bs58';
|
||||||
|
import { ORCA_TOKEN_SWAP_ID_DEVNET } from '@orca-so/sdk';
|
||||||
|
import { orcaDevnetPoolConfigs } from '@orca-so/sdk/dist/constants/devnet/pools';
|
||||||
|
import { OrcaPoolConfig as OrcaDevnetPoolConfig } from '@orca-so/sdk/dist/public/devnet/pools';
|
||||||
import { Bank, getMintInfoForTokenIndex } from './accounts/bank';
|
import { Bank, getMintInfoForTokenIndex } from './accounts/bank';
|
||||||
import { Group } from './accounts/group';
|
import { Group } from './accounts/group';
|
||||||
import { I80F48 } from './accounts/I80F48';
|
import { I80F48 } from './accounts/I80F48';
|
||||||
|
@ -803,6 +808,72 @@ export class MangoClient {
|
||||||
.rpc();
|
.rpc();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// margin trade (orca)
|
||||||
|
|
||||||
|
public async marginTrade({
|
||||||
|
group,
|
||||||
|
mangoAccount,
|
||||||
|
inputToken,
|
||||||
|
amountIn,
|
||||||
|
outputToken,
|
||||||
|
minimumAmountOut,
|
||||||
|
}: {
|
||||||
|
group: Group;
|
||||||
|
mangoAccount: MangoAccount;
|
||||||
|
inputToken: string;
|
||||||
|
amountIn: number;
|
||||||
|
outputToken: string;
|
||||||
|
minimumAmountOut: number;
|
||||||
|
}): Promise<TransactionSignature> {
|
||||||
|
const healthRemainingAccounts: PublicKey[] =
|
||||||
|
await this.buildHealthRemainingAccounts(group, mangoAccount);
|
||||||
|
const parsedHealthAccounts = healthRemainingAccounts.map(
|
||||||
|
(pk) =>
|
||||||
|
({
|
||||||
|
pubkey: pk,
|
||||||
|
isWritable: false,
|
||||||
|
isSigner: false,
|
||||||
|
} as AccountMeta),
|
||||||
|
);
|
||||||
|
|
||||||
|
const inputBank = group.banksMap.get(inputToken);
|
||||||
|
const outputBank = group.banksMap.get(outputToken);
|
||||||
|
|
||||||
|
if (!inputBank || !outputBank) throw new Error('Invalid token');
|
||||||
|
|
||||||
|
const targetProgramId = ORCA_TOKEN_SWAP_ID_DEVNET;
|
||||||
|
|
||||||
|
const instruction = await this.buildOrcaInstruction(
|
||||||
|
targetProgramId,
|
||||||
|
inputBank,
|
||||||
|
outputBank,
|
||||||
|
amountIn, // todo: convert to u64?
|
||||||
|
minimumAmountOut, // todo: convert to u64?
|
||||||
|
);
|
||||||
|
const targetRemainingAccounts = instruction.keys;
|
||||||
|
|
||||||
|
const withdraws = []; // todo:
|
||||||
|
const cpiData = instruction.data; // todo: is it just instruction.data?
|
||||||
|
|
||||||
|
return await this.program.methods
|
||||||
|
.marginTrade(new BN(parsedHealthAccounts.length), withdraws, cpiData)
|
||||||
|
.accounts({
|
||||||
|
group: group.publicKey,
|
||||||
|
account: mangoAccount.publicKey,
|
||||||
|
owner: (this.program.provider as AnchorProvider).wallet.publicKey,
|
||||||
|
})
|
||||||
|
.remainingAccounts([
|
||||||
|
...parsedHealthAccounts,
|
||||||
|
{
|
||||||
|
pubkey: targetProgramId,
|
||||||
|
isWritable: false,
|
||||||
|
isSigner: false,
|
||||||
|
} as AccountMeta,
|
||||||
|
...targetRemainingAccounts,
|
||||||
|
])
|
||||||
|
.rpc();
|
||||||
|
}
|
||||||
|
|
||||||
/// static
|
/// static
|
||||||
|
|
||||||
static connect(provider?: Provider, devnet?: boolean): MangoClient {
|
static connect(provider?: Provider, devnet?: boolean): MangoClient {
|
||||||
|
@ -871,4 +942,45 @@ export class MangoClient {
|
||||||
|
|
||||||
return healthRemainingAccounts;
|
return healthRemainingAccounts;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async buildOrcaInstruction(
|
||||||
|
orcaTokenSwapId,
|
||||||
|
inputBank,
|
||||||
|
outputBank,
|
||||||
|
amountInU64,
|
||||||
|
minimumAmountOutU64,
|
||||||
|
) {
|
||||||
|
const poolParams = orcaDevnetPoolConfigs[OrcaDevnetPoolConfig.SOL_USDC];
|
||||||
|
|
||||||
|
const [authorityForPoolAddress] = await PublicKey.findProgramAddress(
|
||||||
|
[poolParams.address.toBuffer()],
|
||||||
|
orcaTokenSwapId,
|
||||||
|
);
|
||||||
|
|
||||||
|
const userTransferAuthority = new Keypair();
|
||||||
|
|
||||||
|
/*
|
||||||
|
Orca references:
|
||||||
|
swap fn: https://github.com/orca-so/typescript-sdk/blob/main/src/model/orca/pool/orca-pool.ts#L162
|
||||||
|
swap ix: https://github.com/orca-so/typescript-sdk/blob/main/src/public/utils/web3/instructions/pool-instructions.ts#L41
|
||||||
|
*/
|
||||||
|
const swapInstruction = TokenSwap.swapInstruction(
|
||||||
|
poolParams.address,
|
||||||
|
authorityForPoolAddress,
|
||||||
|
userTransferAuthority.publicKey, // what is this?
|
||||||
|
inputBank.vault, // inputTokenUserAddress
|
||||||
|
inputBank.mint, // inputToken.addr
|
||||||
|
outputBank.mint, // outputToken.addr
|
||||||
|
outputBank.vault, // outputTokenUserAddress
|
||||||
|
poolParams.poolTokenMint,
|
||||||
|
poolParams.feeAccount,
|
||||||
|
null, // hostFeeAccount
|
||||||
|
orcaTokenSwapId,
|
||||||
|
TOKEN_PROGRAM_ID,
|
||||||
|
amountInU64,
|
||||||
|
minimumAmountOutU64,
|
||||||
|
);
|
||||||
|
|
||||||
|
return swapInstruction;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue