Skip to content

Commit

Permalink
Global matching in ui wrapper (#110)
Browse files Browse the repository at this point in the history
* global matching in ui wrapper
* global utils in ts

---------

Co-authored-by: Maximilian Schneider <[email protected]>
  • Loading branch information
brittcyr and mschneider authored Sep 20, 2024
1 parent d1c69f5 commit 0197c60
Show file tree
Hide file tree
Showing 9 changed files with 364 additions and 11 deletions.
64 changes: 64 additions & 0 deletions client/idl/ui_wrapper.json
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,70 @@
"docs": [
"Payer of rent and gas"
]
},
{
"name": "baseMint",
"isMut": false,
"isSigner": false,
"docs": [
"Base mint"
]
},
{
"name": "baseGlobal",
"isMut": true,
"isSigner": false,
"docs": [
"Base global account"
]
},
{
"name": "baseGlobalVault",
"isMut": true,
"isSigner": false,
"docs": [
"Base global vault"
]
},
{
"name": "baseMarketVault",
"isMut": true,
"isSigner": false,
"docs": [
"Base market vault"
]
},
{
"name": "quoteMint",
"isMut": false,
"isSigner": false,
"docs": [
"Quote mint"
]
},
{
"name": "quoteGlobal",
"isMut": true,
"isSigner": false,
"docs": [
"Quote global account"
]
},
{
"name": "quoteGlobalVault",
"isMut": true,
"isSigner": false,
"docs": [
"Quote global vault"
]
},
{
"name": "quoteMarketVault",
"isMut": true,
"isSigner": false,
"docs": [
"Quote market vault"
]
}
],
"args": [
Expand Down
16 changes: 16 additions & 0 deletions client/ts/src/uiWrapperObj.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { getVaultAddress } from './utils/market';
import { getAssociatedTokenAddressSync } from '@solana/spl-token';
import { convertU128 } from './utils/numbers';
import { BN } from 'bn.js';
import { getGlobalAddress, getGlobalVaultAddress } from './utils/global';

/**
* All data stored on a wrapper account.
Expand Down Expand Up @@ -327,6 +328,13 @@ export class UiWrapper {
}
priceMantissa = Math.round(priceMantissa);

const baseGlobal: PublicKey = getGlobalAddress(market.baseMint());
const quoteGlobal: PublicKey = getGlobalAddress(market.quoteMint());
const baseGlobalVault: PublicKey = getGlobalVaultAddress(market.baseMint());
const quoteGlobalVault: PublicKey = getGlobalVaultAddress(
market.quoteMint(),
);

return createPlaceOrderInstruction(
{
wrapperState: this.address,
Expand All @@ -337,6 +345,14 @@ export class UiWrapper {
mint,
manifestProgram: MANIFEST_PROGRAM_ID,
payer,
baseMint: market.baseMint(),
baseGlobal,
baseGlobalVault,
baseMarketVault: getVaultAddress(market.address, market.baseMint()),
quoteMint: market.quoteMint(),
quoteGlobal,
quoteGlobalVault,
quoteMarketVault: getVaultAddress(market.address, market.quoteMint()),
},
{
params: {
Expand Down
56 changes: 56 additions & 0 deletions client/ts/src/ui_wrapper/instructions/PlaceOrder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,14 @@ export const PlaceOrderStruct = new beet.BeetArgsStruct<
* @property [_writable_] mint
* @property [] manifestProgram
* @property [_writable_, **signer**] payer
* @property [] baseMint
* @property [_writable_] baseGlobal
* @property [_writable_] baseGlobalVault
* @property [_writable_] baseMarketVault
* @property [] quoteMint
* @property [_writable_] quoteGlobal
* @property [_writable_] quoteGlobalVault
* @property [_writable_] quoteMarketVault
* @category Instructions
* @category PlaceOrder
* @category generated
Expand All @@ -63,6 +71,14 @@ export type PlaceOrderInstructionAccounts = {
tokenProgram?: web3.PublicKey;
manifestProgram: web3.PublicKey;
payer: web3.PublicKey;
baseMint: web3.PublicKey;
baseGlobal: web3.PublicKey;
baseGlobalVault: web3.PublicKey;
baseMarketVault: web3.PublicKey;
quoteMint: web3.PublicKey;
quoteGlobal: web3.PublicKey;
quoteGlobalVault: web3.PublicKey;
quoteMarketVault: web3.PublicKey;
};

export const placeOrderInstructionDiscriminator = 2;
Expand Down Expand Up @@ -137,6 +153,46 @@ export function createPlaceOrderInstruction(
isWritable: true,
isSigner: true,
},
{
pubkey: accounts.baseMint,
isWritable: false,
isSigner: false,
},
{
pubkey: accounts.baseGlobal,
isWritable: true,
isSigner: false,
},
{
pubkey: accounts.baseGlobalVault,
isWritable: true,
isSigner: false,
},
{
pubkey: accounts.baseMarketVault,
isWritable: true,
isSigner: false,
},
{
pubkey: accounts.quoteMint,
isWritable: false,
isSigner: false,
},
{
pubkey: accounts.quoteGlobal,
isWritable: true,
isSigner: false,
},
{
pubkey: accounts.quoteGlobalVault,
isWritable: true,
isSigner: false,
},
{
pubkey: accounts.quoteMarketVault,
isWritable: true,
isSigner: false,
},
];

const ix = new web3.TransactionInstruction({
Expand Down
19 changes: 19 additions & 0 deletions client/ts/src/utils/global.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { PROGRAM_ID } from '../manifest/index';

import { PublicKey } from '@solana/web3.js';

export function getGlobalAddress(mint: PublicKey): PublicKey {
const [globalAddress, _unusedBump] = PublicKey.findProgramAddressSync(
[Buffer.from('global'), mint.toBuffer()],
PROGRAM_ID,
);
return globalAddress;
}

export function getGlobalVaultAddress(mint: PublicKey): PublicKey {
const [globalVaultAddress, _unusedBump] = PublicKey.findProgramAddressSync(
[Buffer.from('global-vault'), mint.toBuffer()],
PROGRAM_ID,
);
return globalVaultAddress;
}
47 changes: 46 additions & 1 deletion client/ts/tests/uiWrapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,10 @@ import {
PRICE_MIN_EXP,
U32_MAX,
} from '../src/constants';
import { PROGRAM_ID as MANIFEST_PROGRAM_ID } from '../src/manifest';
import {
PROGRAM_ID as MANIFEST_PROGRAM_ID,
createGlobalCreateInstruction,
} from '../src/manifest';
import {
PROGRAM_ID,
createCreateWrapperInstruction,
Expand All @@ -29,11 +32,13 @@ import {
} from '../src/ui_wrapper';
import { UiWrapper, OpenOrder } from '../src/uiWrapperObj';
import {
TOKEN_PROGRAM_ID,
createAssociatedTokenAccountIdempotentInstruction,
createMintToInstruction,
getAssociatedTokenAddressSync,
} from '@solana/spl-token';
import { getVaultAddress } from '../src/utils/market';
import { getGlobalAddress, getGlobalVaultAddress } from '../src/utils/global';

type WrapperResponse = Readonly<{
account: AccountInfo<Buffer>;
Expand Down Expand Up @@ -136,6 +141,13 @@ async function placeOrderCreateWrapperIfNotExists(
}
priceMantissa = Math.round(priceMantissa);

const baseGlobal: PublicKey = getGlobalAddress(market.baseMint());
const quoteGlobal: PublicKey = getGlobalAddress(market.quoteMint());
const baseGlobalVault: PublicKey = getGlobalVaultAddress(market.baseMint());
const quoteGlobalVault: PublicKey = getGlobalVaultAddress(
market.quoteMint(),
);

const placeIx = createPlaceOrderInstruction(
{
wrapperState: result.signers[0].publicKey,
Expand All @@ -146,6 +158,14 @@ async function placeOrderCreateWrapperIfNotExists(
mint,
manifestProgram: MANIFEST_PROGRAM_ID,
payer,
baseMint: market.baseMint(),
baseGlobal,
baseGlobalVault,
baseMarketVault: getVaultAddress(market.address, market.baseMint()),
quoteMint: market.quoteMint(),
quoteGlobal,
quoteGlobalVault,
quoteMarketVault: getVaultAddress(market.address, market.quoteMint()),
},
{
params: {
Expand Down Expand Up @@ -219,6 +239,31 @@ async function testWrapper(): Promise<void> {

{
const tx = new Transaction();

const baseGlobal: PublicKey = getGlobalAddress(market.baseMint());
const baseGlobalVault: PublicKey = getGlobalVaultAddress(market.baseMint());
const baseGlobalIx = createGlobalCreateInstruction({
payer: payerKeypair.publicKey,
global: baseGlobal,
mint: market.baseMint(),
globalVault: baseGlobalVault,
tokenProgram: TOKEN_PROGRAM_ID,
});
tx.add(baseGlobalIx);

const quoteGlobal: PublicKey = getGlobalAddress(market.quoteMint());
const quoteGlobalVault: PublicKey = getGlobalVaultAddress(
market.quoteMint(),
);
const quoteGlobalIx = createGlobalCreateInstruction({
payer: payerKeypair.publicKey,
global: quoteGlobal,
mint: market.quoteMint(),
globalVault: quoteGlobalVault,
tokenProgram: TOKEN_PROGRAM_ID,
});
tx.add(quoteGlobalIx);

tx.add(
createAssociatedTokenAccountIdempotentInstruction(
payerKeypair.publicKey,
Expand Down
8 changes: 8 additions & 0 deletions programs/ui-wrapper/src/instruction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,14 @@ pub enum ManifestWrapperInstruction {
#[account(7, name = "token_program", desc = "Token program owning trader token account")]
#[account(8, name = "manifest_program", desc = "Manifest program")]
#[account(9, writable, signer, name = "payer", desc = "Payer of rent and gas")]
#[account(10, name = "base_mint", desc = "Base mint")]
#[account(11, writable, name = "base_global", desc = "Base global account")]
#[account(12, writable, name = "base_global_vault", desc = "Base global vault")]
#[account(13, writable, name = "base_market_vault", desc = "Base market vault")]
#[account(14, name = "quote_mint", desc = "Quote mint")]
#[account(15, writable, name = "quote_global", desc = "Quote global account")]
#[account(16, writable, name = "quote_global_vault", desc = "Quote global vault")]
#[account(17, writable, name = "quote_market_vault", desc = "Quote market vault")]
PlaceOrder = 2,

/// Edit order, deposits additional funds needed. TODO: Not implemented yet
Expand Down
39 changes: 34 additions & 5 deletions programs/ui-wrapper/src/processors/place_order.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,13 @@ use manifest::{
program::{
batch_update::{BatchUpdateReturn, PlaceOrderParams},
batch_update_instruction, deposit_instruction, expand_market_instruction,
get_mut_dynamic_account,
get_dynamic_account, get_mut_dynamic_account,
},
quantities::{BaseAtoms, QuoteAtoms, QuoteAtomsPerBaseAtom, WrapperU64},
state::{DynamicAccount, MarketFixed, OrderType, NO_EXPIRATION_LAST_VALID_SLOT},
state::{
DynamicAccount, GlobalFixed, MarketFixed, MarketRef, OrderType,
NO_EXPIRATION_LAST_VALID_SLOT,
},
validation::{ManifestAccountInfo, Program, Signer},
};
use solana_program::{
Expand Down Expand Up @@ -88,13 +91,32 @@ pub(crate) fn process_place_order(
Program::new(next_account_info(account_iter)?, &manifest::id())?;
let payer: Signer = Signer::new(next_account_info(account_iter)?)?;

let base_mint: &AccountInfo = next_account_info(account_iter)?;
let base_global: ManifestAccountInfo<GlobalFixed> =
ManifestAccountInfo::<GlobalFixed>::new(next_account_info(account_iter)?)?;
let base_global_vault: &AccountInfo = next_account_info(account_iter)?;
let base_market_vault: &AccountInfo = next_account_info(account_iter)?;
let quote_mint: &AccountInfo = next_account_info(account_iter)?;
let quote_global: ManifestAccountInfo<GlobalFixed> =
ManifestAccountInfo::<GlobalFixed>::new(next_account_info(account_iter)?)?;
let quote_global_vault: &AccountInfo = next_account_info(account_iter)?;
let quote_market_vault: &AccountInfo = next_account_info(account_iter)?;

if spl_token_2022::id() == *token_program.key {
unimplemented!("token2022 not yet supported")
}

check_signer(&wrapper_state, owner.key);
let market_info_index: DataIndex = get_market_info_index_for_market(&wrapper_state, market.key);

let (base_mint_key, quote_mint_key) = {
let market_data: &Ref<&mut [u8]> = &market.try_borrow_data()?;
let dynamic_account: MarketRef = get_dynamic_account(market_data);
let base_mint_key: Pubkey = *dynamic_account.get_base_mint();
let quote_mint_key: Pubkey = *dynamic_account.get_quote_mint();
(base_mint_key, quote_mint_key)
};

// Do an initial sync to get all existing orders and balances fresh. This is
// needed for modifying user orders for insufficient funds.
sync_fast(&wrapper_state, &market, market_info_index)?;
Expand Down Expand Up @@ -174,17 +196,16 @@ pub(crate) fn process_place_order(

trace!("cpi place {core_place:?}");

// TODO: optionally pass global orders accounts to cpi
invoke(
&batch_update_instruction(
market.key,
owner.key,
Some(trader_index),
vec![],
vec![core_place],
Some(base_mint_key),
None,
None,
None,
Some(quote_mint_key),
None,
),
&[
Expand All @@ -196,6 +217,14 @@ pub(crate) fn process_place_order(
vault.clone(),
token_program.clone(),
mint.clone(),
base_mint.clone(),
base_global.info.clone(),
base_global_vault.clone(),
base_market_vault.clone(),
quote_mint.clone(),
quote_global.info.clone(),
quote_global_vault.clone(),
quote_market_vault.clone(),
],
)?;

Expand Down
Loading

0 comments on commit 0197c60

Please sign in to comment.