Skip to content
4 changes: 2 additions & 2 deletions controller/core/src/internal_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ macro_rules! impl_cast_from_acc_data {
}

/// # Safety
/// - `acc_data_arr` must have the same align as Self.
/// - `acc_data` must have the same align as Self.
#[inline]
pub const unsafe fn of_acc_data(
acc_data: &[u8],
Expand Down Expand Up @@ -55,7 +55,7 @@ macro_rules! impl_cast_from_acc_data {
}

/// # Safety
/// - `acc_data_arr` must have the same align as Self.
/// - `acc_data` must have the same align as Self.
#[inline]
pub const unsafe fn of_acc_data_mut(
acc_data: &mut [u8],
Expand Down
92 changes: 92 additions & 0 deletions ts/sdk/src/accounts.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
use inf1_std::inf1_ctl_core::{
accounts::lst_state_list::LstStatePackedList,
keys::{LST_STATE_LIST_ID, POOL_STATE_ID},
};
use wasm_bindgen::prelude::*;

use crate::{
Expand Down Expand Up @@ -37,12 +41,57 @@ pub fn get_pool_state(inf: &Inf) -> PoolState {
}
}

/// Sets the `PoolState` account data
#[wasm_bindgen(js_name = setPoolState)]
pub fn set_pool_state(
inf: &mut Inf,
&PoolState {
total_sol_value,
trading_protocol_fee_bps,
lp_protocol_fee_bps,
version,
is_disabled,
is_rebalancing,
admin,
rebalance_authority,
protocol_fee_beneficiary,
pricing_program,
lp_token_mint,
}: &PoolState,
) {
inf.0.pool = inf1_std::inf1_ctl_core::accounts::pool_state::PoolState {
total_sol_value,
trading_protocol_fee_bps,
lp_protocol_fee_bps,
version,
is_disabled,
is_rebalancing,
padding: Default::default(),
admin: admin.0,
rebalance_authority: rebalance_authority.0,
protocol_fee_beneficiary: protocol_fee_beneficiary.0,
pricing_program: pricing_program.0,
lp_token_mint: lp_token_mint.0,
};
}

/// Returns serialized `PoolState` account data
#[wasm_bindgen(js_name = serPoolState)]
pub fn ser_pool_state(inf: &Inf) -> Box<[u8]> {
Into::into(*inf.0.pool.as_acc_data_arr())
}

/// @throws if `pool_state_data` is invalid
#[wasm_bindgen(js_name = deserPoolState)]
pub fn deser_pool_state(inf: &mut Inf, pool_state_data: Box<[u8]>) -> Result<(), InfError> {
inf.0.pool = inf1_std::inf1_ctl_core::accounts::pool_state::PoolStatePacked::of_acc_data(
&pool_state_data,
)
.ok_or(inf1_std::err::InfErr::AccDeser { pk: POOL_STATE_ID })?
.into_pool_state();
Ok(())
}

/// @throws if stored lst state list account data is invalid
#[wasm_bindgen(js_name = getLstStateList)]
pub fn get_lst_state_list(inf: &Inf) -> Result<Vec<LstState>, InfError> {
Expand Down Expand Up @@ -72,8 +121,51 @@ pub fn get_lst_state_list(inf: &Inf) -> Result<Vec<LstState>, InfError> {
.collect())
}

/// Sets the `LstStateList` account data
#[wasm_bindgen(js_name = setLstStateList)]
pub fn set_lst_state_list(inf: &mut Inf, lst_state_list: Box<[LstState]>) {
inf.0.lst_state_list_data = lst_state_list
.iter()
.flat_map(
|&LstState {
is_input_disabled,
mint,
pool_reserves_bump,
protocol_fee_accumulator_bump,
sol_value,
sol_value_calculator,
}| {
*inf1_std::inf1_ctl_core::typedefs::lst_state::LstState {
is_input_disabled,
mint: mint.0,
pool_reserves_bump,
protocol_fee_accumulator_bump,
sol_value,
sol_value_calculator: sol_value_calculator.0,
padding: Default::default(),
}
.as_acc_data_arr()
},
)
.collect();
}

/// Returns serialized `LstStateList` account data
#[wasm_bindgen(js_name = serLstStateList)]
pub fn ser_lst_state_list(inf: &Inf) -> Box<[u8]> {
inf.0.lst_state_list_data.clone()
}

/// @throws if `lst_state_list_data` is invalid
#[wasm_bindgen(js_name = deserLstStateList)]
pub fn deser_lst_state_list(inf: &mut Inf, lst_state_list_data: Box<[u8]>) -> Result<(), InfError> {
LstStatePackedList::of_acc_data(&lst_state_list_data).ok_or(
inf1_std::err::InfErr::AccDeser {
pk: LST_STATE_LIST_ID,
},
)?;

inf.0.lst_state_list_data = lst_state_list_data;

Ok(())
}
176 changes: 149 additions & 27 deletions ts/tests/test/accounts.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,13 @@ import {
Inf,
serPoolState,
serLstStateList,
setPoolState,
deserPoolState,
setLstStateList,
deserLstStateList,
} from "@sanctumso/inf1";
import { beforeAll, describe, expect, it } from "vitest";
import {
fetchAccountMap,
localRpc,
LST_STATE_LIST_ID,
POOL_STATE_ID,
SPL_POOL_ACCOUNTS,
} from "../utils";
import { fetchAccountMap, localRpc, SPL_POOL_ACCOUNTS } from "../utils";
import { type Address, type Rpc, type SolanaRpcApi } from "@solana/kit";

async function splInf(rpc: Rpc<SolanaRpcApi>): Promise<Inf> {
Expand Down Expand Up @@ -51,16 +49,56 @@ describe("accounts test", () => {
`);
});

it("round trip serPoolState", async () => {
const data = serPoolState(await splInf(rpc));
// create a new inf, but overriding fetched account data
const initAccs = await fetchAccountMap(rpc, initPks() as Address[]);
initAccs.set(POOL_STATE_ID, {
...initAccs.get(POOL_STATE_ID)!,
data,
});
const rt = serPoolState(init(initAccs, SPL_POOL_ACCOUNTS));
expect(data).toStrictEqual(rt);
it("round trip setPoolState getPoolState", async () => {
const inf = await splInf(rpc);
const pool = {
admin: "8VE2uJkoheDbJd9rCyKzfXmiMqAS4o1B3XGshEh86BGk",
isDisabled: 1,
isRebalancing: 1,
lpProtocolFeeBps: 100,
lpTokenMint: "5oVNBeEEQvYi1cX3ir8Dx5n1P7pdxydbGF2X4TxVusJm",
pricingProgram: "s1b6NRXj6ygNu1QMKXh2H9LUR2aPApAAm1UQ2DjdhNV",
protocolFeeBeneficiary: "EeQmNqm1RcQnee8LTyx6ccVG9FnR8TezQuw2JXq2LC1T",
rebalanceAuthority: "GFHMc9BegxJXLdHJrABxNVoPRdnmVxXiNeoUCEpgXVHw",
totalSolValue: 74167603073316n,
tradingProtocolFeeBps: 100,
version: 1,
};

setPoolState(inf, pool);

const newPool = getPoolState(inf);

expect(pool).toStrictEqual(newPool);
});

it("round trip setPoolState serPoolState deserPoolState getPoolState", async () => {
const inf = await splInf(rpc);
const pool = {
admin: "8VE2uJkoheDbJd9rCyKzfXmiMqAS4o1B3XGshEh86BGk",
isDisabled: 1,
isRebalancing: 1,
lpProtocolFeeBps: 100,
lpTokenMint: "5oVNBeEEQvYi1cX3ir8Dx5n1P7pdxydbGF2X4TxVusJm",
pricingProgram: "s1b6NRXj6ygNu1QMKXh2H9LUR2aPApAAm1UQ2DjdhNV",
protocolFeeBeneficiary: "EeQmNqm1RcQnee8LTyx6ccVG9FnR8TezQuw2JXq2LC1T",
rebalanceAuthority: "GFHMc9BegxJXLdHJrABxNVoPRdnmVxXiNeoUCEpgXVHw",
totalSolValue: 74167603073316n,
tradingProtocolFeeBps: 100,
version: 1,
};

setPoolState(inf, pool);

const data = serPoolState(inf);

const newInf = await splInf(rpc);

deserPoolState(newInf, data);

const newPool = getPoolState(newInf);

expect(pool).toStrictEqual(newPool);
});

it("happy path getLstStateList", async () => {
Expand Down Expand Up @@ -106,15 +144,99 @@ describe("accounts test", () => {
`);
});

it("round trip serLstStateList", async () => {
const data = serLstStateList(await splInf(rpc));
// create a new inf, but overriding fetched account data
const initAccs = await fetchAccountMap(rpc, initPks() as Address[]);
initAccs.set(LST_STATE_LIST_ID, {
...initAccs.get(LST_STATE_LIST_ID)!,
data,
});
const rt = serLstStateList(init(initAccs, SPL_POOL_ACCOUNTS));
expect(data).toStrictEqual(rt);
it("round trip setLstStateList getLstStateList", async () => {
const inf = await splInf(rpc);

const lstStates = [
{
isInputDisabled: 1,
mint: "7dHbWXmci3dT8UFYWYZweBLXgycu7Y3iL6trKn1Y7ARj",
poolReservesBump: 255,
protocolFeeAccumulatorBump: 252,
solValue: 303444n,
solValueCalculator: "1idUSy4MGGKyKhvjSnGZ6Zc7Q4eKQcibym4BkEEw9KR",
},
{
isInputDisabled: 1,
mint: "So11111111111111111111111111111111111111112",
poolReservesBump: 250,
protocolFeeAccumulatorBump: 251,
solValue: 1341445067009n,
solValueCalculator: "wsoGmxQLSvwWpuaidCApxN5kEowLe2HLQLJhCQnj4bE",
},
{
isInputDisabled: 1,
mint: "mSoLzYCxHdYgdzU16g5QSh3i5K3z3KZK7ytfqcJm7So",
poolReservesBump: 255,
protocolFeeAccumulatorBump: 255,
solValue: 146510n,
solValueCalculator: "mare3SCyfZkAndpBRBeonETmkCCB3TJTTrz8ZN2dnhP",
},
{
isInputDisabled: 1,
mint: "jupSoLaHXQiZZTSfEWMTRRgpnyFm8f6sZdosWBjx93v",
poolReservesBump: 255,
protocolFeeAccumulatorBump: 240,
solValue: 9802594257518n,
solValueCalculator: "ssmbu3KZxgonUtjEMCKspZzxvUQCxAFnyh1rcHUeEDo",
},
];

setLstStateList(inf, lstStates);

let newLstStates = getLstStateList(inf);

expect(lstStates).toStrictEqual(newLstStates);
});

it("round trip setLstStateList serLstStateList deserLstStateList getLstStateList", async () => {
const inf = await splInf(rpc);

const lstStates = [
{
isInputDisabled: 1,
mint: "7dHbWXmci3dT8UFYWYZweBLXgycu7Y3iL6trKn1Y7ARj",
poolReservesBump: 255,
protocolFeeAccumulatorBump: 252,
solValue: 303444n,
solValueCalculator: "1idUSy4MGGKyKhvjSnGZ6Zc7Q4eKQcibym4BkEEw9KR",
},
{
isInputDisabled: 1,
mint: "So11111111111111111111111111111111111111112",
poolReservesBump: 250,
protocolFeeAccumulatorBump: 251,
solValue: 1341445067009n,
solValueCalculator: "wsoGmxQLSvwWpuaidCApxN5kEowLe2HLQLJhCQnj4bE",
},
{
isInputDisabled: 1,
mint: "mSoLzYCxHdYgdzU16g5QSh3i5K3z3KZK7ytfqcJm7So",
poolReservesBump: 255,
protocolFeeAccumulatorBump: 255,
solValue: 146510n,
solValueCalculator: "mare3SCyfZkAndpBRBeonETmkCCB3TJTTrz8ZN2dnhP",
},
{
isInputDisabled: 1,
mint: "jupSoLaHXQiZZTSfEWMTRRgpnyFm8f6sZdosWBjx93v",
poolReservesBump: 255,
protocolFeeAccumulatorBump: 240,
solValue: 9802594257518n,
solValueCalculator: "ssmbu3KZxgonUtjEMCKspZzxvUQCxAFnyh1rcHUeEDo",
},
];

setLstStateList(inf, lstStates);

const lstStateData = serLstStateList(inf);

const newInf = await splInf(rpc);

deserLstStateList(newInf, lstStateData);

const newLstStates = getLstStateList(newInf);

expect(lstStates).toStrictEqual(newLstStates);
});
});
Loading