Skip to content

Commit 6353b62

Browse files
authored
Merge pull request #1587 from drift-labs/nour/add-mapping-datum
Nour/add mapping datum
2 parents 1d7fd00 + 188ab4e commit 6353b62

File tree

8 files changed

+529
-15
lines changed

8 files changed

+529
-15
lines changed

programs/drift/src/error.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -635,8 +635,8 @@ pub enum ErrorCode {
635635
InvalidSignedMsgUserOrdersResize,
636636
#[msg("Invalid Constituent")]
637637
InvalidConstituent,
638-
#[msg("Misatch amm mapping and constituent target weights")]
639-
MismatchAmmConstituentMappingAndConstituentTargetWeights,
638+
#[msg("Invalid Amm Constituent Mapping argument")]
639+
InvalidAmmConstituentMappingArgument,
640640
}
641641

642642
#[macro_export]

programs/drift/src/instructions/admin.rs

Lines changed: 92 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4600,6 +4600,62 @@ pub fn handle_initialize_constituent<'info>(
46004600
Ok(())
46014601
}
46024602

4603+
#[derive(AnchorSerialize, AnchorDeserialize, Clone, Default)]
4604+
pub struct InitializeAmmConstituentMappingDatum {
4605+
pub constituent_index: u16,
4606+
pub perp_market_index: u16,
4607+
}
4608+
4609+
pub fn handle_add_amm_constituent_data<'info>(
4610+
ctx: Context<AddAmmConstituentMappingData>,
4611+
init_amm_constituent_mapping_data: Vec<InitializeAmmConstituentMappingDatum>,
4612+
) -> Result<()> {
4613+
let amm_mapping = &mut ctx.accounts.amm_constituent_mapping;
4614+
let constituent_target_weights = &ctx.accounts.constituent_target_weights;
4615+
let state = &ctx.accounts.state;
4616+
let mut current_len = amm_mapping.data.len();
4617+
4618+
for init_datum in init_amm_constituent_mapping_data {
4619+
let perp_market_index = init_datum.perp_market_index;
4620+
4621+
validate!(
4622+
perp_market_index < state.number_of_markets,
4623+
ErrorCode::InvalidAmmConstituentMappingArgument,
4624+
"perp_market_index too large compared to number of markets"
4625+
)?;
4626+
4627+
validate!(
4628+
(init_datum.constituent_index as usize) < constituent_target_weights.data.len(),
4629+
ErrorCode::InvalidAmmConstituentMappingArgument,
4630+
"constituent_index too large compared to number of constituents in target weights"
4631+
)?;
4632+
4633+
let constituent_index = init_datum.constituent_index;
4634+
let mut datum = AmmConstituentDatum::default();
4635+
datum.perp_market_index = perp_market_index;
4636+
datum.constituent_index = constituent_index;
4637+
4638+
// Check if the datum already exists
4639+
let exists = amm_mapping.data.iter().any(|d| {
4640+
d.perp_market_index == perp_market_index && d.constituent_index == constituent_index
4641+
});
4642+
4643+
validate!(
4644+
!exists,
4645+
ErrorCode::InvalidAmmConstituentMappingArgument,
4646+
"AmmConstituentDatum already exists for perp_market_index {} and constituent_index {}",
4647+
perp_market_index,
4648+
constituent_index
4649+
)?;
4650+
4651+
// Add the new datum to the mapping
4652+
current_len += 1;
4653+
amm_mapping.data.resize(current_len, datum);
4654+
}
4655+
4656+
Ok(())
4657+
}
4658+
46034659
#[derive(Accounts)]
46044660
pub struct Initialize<'info> {
46054661
#[account(mut)]
@@ -5409,8 +5465,43 @@ pub struct InitializeConstituent<'info> {
54095465
payer = admin,
54105466
)]
54115467
pub constituent: AccountLoader<'info, Constituent>,
5468+
pub rent: Sysvar<'info, Rent>,
5469+
pub system_program: Program<'info, System>,
5470+
}
54125471

5472+
#[derive(Accounts)]
5473+
#[instruction(
5474+
lp_pool_name: [u8; 32],
5475+
market_index_constituent_index_pairs: Vec<(u16, u16)>,
5476+
)]
5477+
pub struct AddAmmConstituentMappingData<'info> {
54135478
#[account(mut)]
5414-
pub payer: Signer<'info>,
5479+
pub admin: Signer<'info>,
5480+
5481+
#[account(
5482+
seeds = [b"lp_pool", lp_pool_name.as_ref()],
5483+
bump,
5484+
)]
5485+
pub lp_pool: AccountLoader<'info, LPPool>,
5486+
5487+
#[account(
5488+
mut,
5489+
seeds = [AMM_MAP_PDA_SEED.as_ref(), lp_pool.key().as_ref()],
5490+
bump,
5491+
realloc = AmmConstituentMapping::space(amm_constituent_mapping.data.len() + market_index_constituent_index_pairs.len()),
5492+
realloc::payer = admin,
5493+
realloc::zero = false,
5494+
)]
5495+
pub amm_constituent_mapping: Box<Account<'info, AmmConstituentMapping>>,
5496+
#[account(
5497+
mut,
5498+
seeds = [CONSTITUENT_TARGET_WEIGHT_PDA_SEED.as_ref(), lp_pool.key().as_ref()],
5499+
bump,
5500+
realloc = ConstituentTargetWeights::space(constituent_target_weights.data.len() + 1 as usize),
5501+
realloc::payer = admin,
5502+
realloc::zero = false,
5503+
)]
5504+
pub constituent_target_weights: Box<Account<'info, ConstituentTargetWeights>>,
5505+
pub state: Box<Account<'info, State>>,
54155506
pub system_program: Program<'info, System>,
54165507
}

programs/drift/src/lib.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1706,6 +1706,33 @@ pub mod drift {
17061706
) -> Result<()> {
17071707
handle_update_protected_maker_mode_config(ctx, max_users, reduce_only, current_users)
17081708
}
1709+
1710+
pub fn initialize_constituent(
1711+
ctx: Context<InitializeConstituent>,
1712+
lp_pool_name: [u8; 32],
1713+
spot_market_index: u16,
1714+
decimals: u8,
1715+
max_weight_deviation: i64,
1716+
swap_fee_min: i64,
1717+
swap_fee_max: i64,
1718+
) -> Result<()> {
1719+
handle_initialize_constituent(
1720+
ctx,
1721+
spot_market_index,
1722+
decimals,
1723+
max_weight_deviation,
1724+
swap_fee_min,
1725+
swap_fee_max,
1726+
)
1727+
}
1728+
1729+
pub fn add_amm_constituent_mapping_data(
1730+
ctx: Context<AddAmmConstituentMappingData>,
1731+
lp_pool_name: [u8; 32],
1732+
init_amm_constituent_mapping_data: Vec<InitializeAmmConstituentMappingDatum>,
1733+
) -> Result<()> {
1734+
handle_add_amm_constituent_data(ctx, init_amm_constituent_mapping_data)
1735+
}
17091736
}
17101737

17111738
#[cfg(not(feature = "no-entrypoint"))]

programs/drift/src/state/lp_pool.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,7 @@ pub struct BLPosition {
208208
pub market_index: u16,
209209
/// Whether the position is deposit or borrow
210210
pub balance_type: SpotBalanceType,
211-
pub padding: [u8; 4],
211+
pub padding: [u8; 5],
212212
}
213213

214214
impl SpotBalance for BLPosition {
@@ -269,7 +269,7 @@ pub struct Constituent {
269269
}
270270

271271
impl Size for Constituent {
272-
const SIZE: usize = 108;
272+
const SIZE: usize = 112;
273273
}
274274

275275
impl Constituent {
@@ -433,7 +433,7 @@ impl ConstituentTargetWeights {
433433

434434
pub fn validate(&self) -> DriftResult<()> {
435435
validate!(
436-
self.data.len() >= 0 && self.data.len() <= 128,
436+
self.data.len() <= 128,
437437
ErrorCode::DefaultError,
438438
"Number of constituents len must be between 1 and 128"
439439
)?;

sdk/src/adminClient.ts

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import {
1515
ContractTier,
1616
AssetTier,
1717
SpotFulfillmentConfigStatus,
18+
InitAmmConstituentMappingDatum,
1819
} from './types';
1920
import { DEFAULT_MARKET_NAME, encodeName } from './userName';
2021
import { BN } from '@coral-xyz/anchor';
@@ -40,6 +41,7 @@ import {
4041
getLpPoolPublicKey,
4142
getAmmConstituentMappingPublicKey,
4243
getConstituentTargetWeightsPublicKey,
44+
getConstituentPublicKey,
4345
} from './addresses/pda';
4446
import { squareRootBN } from './math/utils';
4547
import {
@@ -4272,4 +4274,111 @@ export class AdminClient extends DriftClient {
42724274
createAtaIx,
42734275
];
42744276
}
4277+
4278+
public async initializeConstituent(
4279+
lpPoolName: number[],
4280+
spotMarketIndex: number,
4281+
decimals: number,
4282+
maxWeightDeviation: BN,
4283+
swapFeeMin: BN,
4284+
swapFeeMax: BN
4285+
): Promise<TransactionSignature> {
4286+
const ixs = await this.getInitializeConstituentIx(
4287+
lpPoolName,
4288+
spotMarketIndex,
4289+
decimals,
4290+
maxWeightDeviation,
4291+
swapFeeMin,
4292+
swapFeeMax
4293+
);
4294+
const tx = await this.buildTransaction(ixs);
4295+
const { txSig } = await this.sendTransaction(tx, []);
4296+
return txSig;
4297+
}
4298+
4299+
public async getInitializeConstituentIx(
4300+
lpPoolName: number[],
4301+
spotMarketIndex: number,
4302+
decimals: number,
4303+
maxWeightDeviation: BN,
4304+
swapFeeMin: BN,
4305+
swapFeeMax: BN
4306+
): Promise<TransactionInstruction[]> {
4307+
const lpPool = getLpPoolPublicKey(this.program.programId, lpPoolName);
4308+
const constituentTargetWeights = getConstituentTargetWeightsPublicKey(
4309+
this.program.programId,
4310+
lpPool
4311+
);
4312+
const constituent = getConstituentPublicKey(
4313+
this.program.programId,
4314+
lpPool,
4315+
spotMarketIndex
4316+
);
4317+
return [
4318+
this.program.instruction.initializeConstituent(
4319+
lpPoolName,
4320+
spotMarketIndex,
4321+
decimals,
4322+
maxWeightDeviation,
4323+
swapFeeMin,
4324+
swapFeeMax,
4325+
{
4326+
accounts: {
4327+
admin: this.wallet.publicKey,
4328+
lpPool,
4329+
constituentTargetWeights,
4330+
constituent,
4331+
rent: SYSVAR_RENT_PUBKEY,
4332+
systemProgram: SystemProgram.programId,
4333+
},
4334+
signers: [],
4335+
}
4336+
),
4337+
];
4338+
}
4339+
4340+
public async addInitAmmConstituentMappingData(
4341+
lpPoolName: number[],
4342+
marketIndexConstituentIndexPairs: InitAmmConstituentMappingDatum[]
4343+
): Promise<TransactionSignature> {
4344+
const ixs = await this.getAddInitAmmConstituentMappingDataIx(
4345+
lpPoolName,
4346+
marketIndexConstituentIndexPairs
4347+
);
4348+
const tx = await this.buildTransaction(ixs);
4349+
const { txSig } = await this.sendTransaction(tx, []);
4350+
return txSig;
4351+
}
4352+
4353+
public async getAddInitAmmConstituentMappingDataIx(
4354+
lpPoolName: number[],
4355+
marketIndexConstituentIndexPairs: InitAmmConstituentMappingDatum[]
4356+
): Promise<TransactionInstruction[]> {
4357+
const lpPool = getLpPoolPublicKey(this.program.programId, lpPoolName);
4358+
const ammConstituentMapping = getAmmConstituentMappingPublicKey(
4359+
this.program.programId,
4360+
lpPool
4361+
);
4362+
const constituentTargetWeights = getConstituentTargetWeightsPublicKey(
4363+
this.program.programId,
4364+
lpPool
4365+
);
4366+
return [
4367+
this.program.instruction.addAmmConstituentMappingData(
4368+
lpPoolName,
4369+
marketIndexConstituentIndexPairs,
4370+
{
4371+
accounts: {
4372+
admin: this.wallet.publicKey,
4373+
lpPool,
4374+
ammConstituentMapping,
4375+
constituentTargetWeights,
4376+
rent: SYSVAR_RENT_PUBKEY,
4377+
systemProgram: SystemProgram.programId,
4378+
state: await this.getStatePublicKey(),
4379+
},
4380+
}
4381+
),
4382+
];
4383+
}
42754384
}

0 commit comments

Comments
 (0)