Merge branch 'main' into marvin/bip-32-comp

This commit is contained in:
jonesmarvin8 2026-02-27 11:32:30 -05:00
commit 5a0ef060fd
22 changed files with 383 additions and 120 deletions

1
Cargo.lock generated
View File

@ -2733,6 +2733,7 @@ dependencies = [
"env_logger",
"indexer_service_protocol",
"indexer_service_rpc",
"itertools 0.14.0",
"jsonrpsee",
"leptos",
"leptos_axum",

Binary file not shown.

View File

@ -50,6 +50,9 @@ clap = { workspace = true, features = ["derive"], optional = true }
url = { workspace = true, optional = true }
env_logger = { workspace = true, optional = true }
# Mandatory server side dependencies
itertools.workspace = true
[features]
hydrate = ["leptos/hydrate"]
ssr = [

View File

@ -83,6 +83,17 @@ pub async fn get_block_by_id(block_id: BlockId) -> Result<Block, ServerFnError>
.map_err(|e| ServerFnError::ServerError(format!("RPC error: {}", e)))
}
/// Get latest block ID
#[server]
pub async fn get_latest_block_id() -> Result<BlockId, ServerFnError> {
use indexer_service_rpc::RpcClient as _;
let client = expect_context::<IndexerRpcClient>();
client
.get_last_finalized_block_id()
.await
.map_err(|e| ServerFnError::ServerError(format!("RPC error: {}", e)))
}
/// Get block by hash
#[server]
pub async fn get_block_by_hash(block_hash: HashType) -> Result<Block, ServerFnError> {

View File

@ -28,7 +28,7 @@ pub fn App() -> impl IntoView {
view! {
<Stylesheet id="leptos" href="/explorer.css" />
<Title text="LEE Blockchain Explorer" />
<Title text="LEZ Block Explorer" />
<Meta name="description" content="Explore the blockchain - view blocks, transactions, and accounts" />
<Router>
@ -36,7 +36,7 @@ pub fn App() -> impl IntoView {
<header class="app-header">
<nav class="app-nav">
<a href="/" class="nav-logo">
"LEE Blockchain Explorer"
"LEZ Block Explorer"
</a>
</nav>
</header>
@ -69,7 +69,7 @@ pub fn App() -> impl IntoView {
</main>
<footer class="app-footer">
<p>"LEE Blockchain Explorer © 2026"</p>
<p>"LEZ Block Explorer © 2026"</p>
</footer>
</div>
</Router>

View File

@ -10,7 +10,7 @@ async fn main() {
env_logger::init();
/// LEE Blockchain Explorer Server CLI arguments.
/// LEZ Block Explorer Server CLI arguments.
#[derive(Parser, Debug)]
#[command(version, about, long_about = None)]
struct Args {

View File

@ -7,6 +7,8 @@ use crate::{
components::{AccountPreview, BlockPreview, TransactionPreview},
};
const RECENT_BLOCKS_LIMIT: u64 = 10;
/// Main page component
#[component]
pub fn MainPage() -> impl IntoView {
@ -38,7 +40,21 @@ pub fn MainPage() -> impl IntoView {
});
// Load recent blocks on mount
let recent_blocks_resource = Resource::new(|| (), |_| async { api::get_blocks(0, 10).await });
let recent_blocks_resource = Resource::new(
|| (),
|_| async {
match api::get_latest_block_id().await {
Ok(last_id) => {
api::get_blocks(
std::cmp::max(last_id.saturating_sub(RECENT_BLOCKS_LIMIT) as u32, 1),
(RECENT_BLOCKS_LIMIT + 1) as u32,
)
.await
}
Err(err) => Err(err),
}
},
);
// Handle search - update URL parameter
let on_search = move |ev: SubmitEvent| {
@ -58,7 +74,7 @@ pub fn MainPage() -> impl IntoView {
view! {
<div class="main-page">
<div class="page-header">
<h1>"LEE Blockchain Explorer"</h1>
<h1>"LEZ Block Explorer"</h1>
</div>
<div class="search-section">

View File

@ -4,6 +4,7 @@ use indexer_service_protocol::{
HashType, PrivacyPreservingMessage, PrivacyPreservingTransaction, ProgramDeploymentMessage,
ProgramDeploymentTransaction, PublicMessage, PublicTransaction, Transaction, WitnessSet,
};
use itertools::{EitherOrBoth, Itertools};
use leptos::prelude::*;
use leptos_router::{components::A, hooks::use_params_map};
@ -65,7 +66,8 @@ pub fn TransactionPage() -> impl IntoView {
</div>
</div>
{match tx {
{
match tx {
Transaction::Public(ptx) => {
let PublicTransaction {
hash: _,
@ -115,9 +117,11 @@ pub fn TransactionPage() -> impl IntoView {
<div class="accounts-list">
{account_ids
.into_iter()
.zip(nonces.into_iter())
.map(|(account_id, nonce)| {
let account_id_str = account_id.to_string();
.zip_longest(nonces.into_iter())
.map(|maybe_pair| {
match maybe_pair {
EitherOrBoth::Both(account_id, nonce) => {
let account_id_str = account_id.to_string();
view! {
<div class="account-item">
<A href=format!("/account/{}", account_id_str)>
@ -128,6 +132,33 @@ pub fn TransactionPage() -> impl IntoView {
</span>
</div>
}
}
EitherOrBoth::Left(account_id) => {
let account_id_str = account_id.to_string();
view! {
<div class="account-item">
<A href=format!("/account/{}", account_id_str)>
<span class="hash">{account_id_str}</span>
</A>
<span class="nonce">
" (nonce: "{"Not affected by this transaction".to_string()}" )"
</span>
</div>
}
}
EitherOrBoth::Right(_) => {
view! {
<div class="account-item">
<A href=format!("/account/{}", "Account not found")>
<span class="hash">{"Account not found"}</span>
</A>
<span class="nonce">
" (nonce: "{"Account not found".to_string()}" )"
</span>
</div>
}
}
}
})
.collect::<Vec<_>>()}
</div>
@ -189,9 +220,11 @@ pub fn TransactionPage() -> impl IntoView {
<div class="accounts-list">
{public_account_ids
.into_iter()
.zip(nonces.into_iter())
.map(|(account_id, nonce)| {
let account_id_str = account_id.to_string();
.zip_longest(nonces.into_iter())
.map(|maybe_pair| {
match maybe_pair {
EitherOrBoth::Both(account_id, nonce) => {
let account_id_str = account_id.to_string();
view! {
<div class="account-item">
<A href=format!("/account/{}", account_id_str)>
@ -202,6 +235,33 @@ pub fn TransactionPage() -> impl IntoView {
</span>
</div>
}
}
EitherOrBoth::Left(account_id) => {
let account_id_str = account_id.to_string();
view! {
<div class="account-item">
<A href=format!("/account/{}", account_id_str)>
<span class="hash">{account_id_str}</span>
</A>
<span class="nonce">
" (nonce: "{"Not affected by this transaction".to_string()}" )"
</span>
</div>
}
}
EitherOrBoth::Right(_) => {
view! {
<div class="account-item">
<A href=format!("/account/{}", "Account not found")>
<span class="hash">{"Account not found"}</span>
</A>
<span class="nonce">
" (nonce: "{"Account not found".to_string()}" )"
</span>
</div>
}
}
}
})
.collect::<Vec<_>>()}
</div>

37
flake.lock generated
View File

@ -15,7 +15,41 @@
"type": "github"
}
},
"logos-blockchain-circuits": {
"inputs": {
"nixpkgs": "nixpkgs"
},
"locked": {
"lastModified": 1770979891,
"narHash": "sha256-cvkVnE7btuFLzv70ORAZve9K1Huiplq0iECgXSXb0ZY=",
"owner": "logos-blockchain",
"repo": "logos-blockchain-circuits",
"rev": "ec7d298e5a3a0507bb8570df86cdf78dc452d024",
"type": "github"
},
"original": {
"owner": "logos-blockchain",
"repo": "logos-blockchain-circuits",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1769461804,
"narHash": "sha256-msG8SU5WsBUfVVa/9RPLaymvi5bI8edTavbIq3vRlhI=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "bfc1b8a4574108ceef22f02bafcf6611380c100d",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_2": {
"locked": {
"lastModified": 1770019141,
"narHash": "sha256-VKS4ZLNx4PNrABoB0L8KUpc1fE7CLpQXQs985tGfaCU=",
@ -34,7 +68,8 @@
"root": {
"inputs": {
"crane": "crane",
"nixpkgs": "nixpkgs",
"logos-blockchain-circuits": "logos-blockchain-circuits",
"nixpkgs": "nixpkgs_2",
"rust-overlay": "rust-overlay"
}
},

View File

@ -10,6 +10,10 @@
};
crane.url = "github:ipetkov/crane";
logos-blockchain-circuits = {
url = "github:logos-blockchain/logos-blockchain-circuits";
};
};
outputs =
@ -18,6 +22,7 @@
nixpkgs,
rust-overlay,
crane,
logos-blockchain-circuits,
...
}:
let
@ -107,6 +112,7 @@
'' + pkgs.lib.optionalString pkgs.stdenv.isDarwin ''
export PATH="$PATH:/usr/bin"
'';
LOGOS_BLOCKCHAIN_CIRCUITS = logos-blockchain-circuits.packages.${system}.default;
};
walletFfiPackage = craneLib.buildPackage (

View File

@ -2,7 +2,10 @@ use std::{path::Path, sync::Arc};
use anyhow::Result;
use bedrock_client::HeaderId;
use common::{block::Block, transaction::NSSATransaction};
use common::{
block::{BedrockStatus, Block},
transaction::NSSATransaction,
};
use nssa::{Account, AccountId, V02State};
use storage::indexer::RocksDBIO;
@ -100,7 +103,7 @@ impl IndexerStore {
Ok(self.final_state()?.get_account_by_id(*account_id))
}
pub fn put_block(&self, block: Block, l1_header: HeaderId) -> Result<()> {
pub fn put_block(&self, mut block: Block, l1_header: HeaderId) -> Result<()> {
let mut final_state = self.dbio.final_state()?;
for transaction in &block.body.transactions {
@ -110,6 +113,11 @@ impl IndexerStore {
.execute_check_on_state(&mut final_state)?;
}
// ToDo: Currently we are fetching only finalized blocks
// if it changes, the following lines need to be updated
// to represent correct block finality
block.bedrock_status = BedrockStatus::Finalized;
Ok(self.dbio.put_block(block, l1_header.into())?)
}
}

View File

@ -15,7 +15,6 @@ use crate::{block_store::IndexerStore, config::IndexerConfig};
pub mod block_store;
pub mod config;
pub mod state;
#[derive(Clone)]
pub struct IndexerCore {
@ -123,6 +122,10 @@ impl IndexerCore {
l2_blocks: l2_block_vec,
l1_header,
} in start_buff {
let mut l2_blocks_parsed_ids: Vec<_> = l2_block_vec.iter().map(|block| block.header.block_id).collect();
l2_blocks_parsed_ids.sort();
info!("Parsed {} L2 blocks with ids {:?}", l2_block_vec.len(), l2_blocks_parsed_ids);
for l2_block in l2_block_vec {
self.store.put_block(l2_block.clone(), l1_header)?;
@ -153,6 +156,10 @@ impl IndexerCore {
l2_blocks: l2_block_vec,
l1_header: header,
} in buff {
let mut l2_blocks_parsed_ids: Vec<_> = l2_block_vec.iter().map(|block| block.header.block_id).collect();
l2_blocks_parsed_ids.sort();
info!("Parsed {} L2 blocks with ids {:?}", l2_block_vec.len(), l2_blocks_parsed_ids);
for l2_block in l2_block_vec {
self.store.put_block(l2_block.clone(), header)?;
@ -260,7 +267,7 @@ impl IndexerCore {
Ok(BackfillData {
block_data: block_buffer,
curr_fin_l1_lib_header: backfill_limit,
curr_fin_l1_lib_header: curr_last_l1_lib_header,
})
}

View File

@ -1,9 +0,0 @@
use std::sync::Arc;
use tokio::sync::RwLock;
#[derive(Debug, Clone)]
pub struct IndexerState {
// Only one field for now, for testing.
pub latest_seen_block: Arc<RwLock<u64>>,
}

View File

@ -3,13 +3,43 @@ FROM lukemathwalker/cargo-chef:latest-rust-1.91.1-slim-trixie AS chef
# Install build dependencies
RUN apt-get update && apt-get install -y \
build-essential \
pkg-config \
libssl-dev \
libclang-dev \
clang \
cmake \
ninja-build \
curl \
git \
&& rm -rf /var/lib/apt/lists/*
# Install r0vm
# Use quick install for x86-64 (risczero provides binaries only for this linux platform)
# Manual build for other platforms (including arm64 Linux)
RUN ARCH=$(uname -m); \
if [ "$ARCH" = "x86_64" ]; then \
echo "Using quick install for $ARCH"; \
curl -L https://risczero.com/install | bash; \
export PATH="/root/.cargo/bin:/root/.risc0/bin:${PATH}"; \
rzup install; \
else \
echo "Using manual build for $ARCH"; \
git clone --depth 1 --branch release-3.0 https://github.com/risc0/risc0.git; \
git clone --depth 1 --branch r0.1.91.1 https://github.com/risc0/rust.git; \
cd /risc0; \
cargo install --path rzup; \
rzup build --path /rust rust --verbose; \
cargo install --path risc0/cargo-risczero; \
fi
ENV PATH="/root/.cargo/bin:/root/.risc0/bin:${PATH}"
RUN cp "$(which r0vm)" /usr/local/bin/r0vm
RUN test -x /usr/local/bin/r0vm
RUN r0vm --version
# Install logos blockchain circuits
RUN curl -sSL https://raw.githubusercontent.com/logos-blockchain/logos-blockchain/main/scripts/setup-logos-blockchain-circuits.sh | bash
WORKDIR /indexer_service
# Planner stage - generates dependency recipe
@ -48,6 +78,12 @@ RUN useradd -m -u 1000 -s /bin/bash indexer_service_user && \
# Copy binary from builder
COPY --from=builder --chown=indexer_service_user:indexer_service_user /indexer_service/target/release/indexer_service /usr/local/bin/indexer_service
# Copy r0vm binary from builder
COPY --from=builder --chown=indexer_service_user:indexer_service_user /usr/local/bin/r0vm /usr/local/bin/r0vm
# Copy logos blockchain circuits from builder
COPY --from=builder --chown=indexer_service_user:indexer_service_user /root/.logos-blockchain-circuits /home/indexer_service_user/.logos-blockchain-circuits
# Copy entrypoint script
COPY indexer/service/docker-entrypoint.sh /docker-entrypoint.sh
RUN chmod +x /docker-entrypoint.sh

View File

@ -1,6 +1,6 @@
{
"home": "./indexer/service",
"consensus_info_polling_interval": "1s",
"consensus_info_polling_interval": "60s",
"bedrock_client_config": {
"addr": "http://localhost:8080",
"backoff": {

View File

@ -5,7 +5,7 @@ edition = "2024"
license = { workspace = true }
[dependencies]
indexer_service_protocol = { workspace = true }
indexer_service_protocol = { workspace = true, features = ["convert"] }
jsonrpsee = { workspace = true, features = ["macros"] }
serde_json.workspace = true

View File

@ -2504,6 +2504,12 @@ pub mod tests {
fn user_token_b_holding_new_definition() -> u128 {
7_500
}
fn lp_supply_init() -> u128 {
// isqrt(vault_a_balance_init * vault_b_balance_init) = isqrt(5_000 * 2_500) = 3535
(BalanceForTests::vault_a_balance_init() * BalanceForTests::vault_b_balance_init())
.isqrt()
}
}
struct IdForTests;
@ -3098,7 +3104,7 @@ pub mod tests {
balance: 0u128,
data: Data::from(&TokenHolding::Fungible {
definition_id: IdForTests::token_lp_definition_id(),
balance: BalanceForTests::user_token_a_holding_new_definition(),
balance: BalanceForTests::lp_supply_init(),
}),
nonce: 0,
}
@ -3110,7 +3116,7 @@ pub mod tests {
balance: 0u128,
data: Data::from(&TokenDefinition::Fungible {
name: String::from("LP Token"),
total_supply: BalanceForTests::vault_a_balance_init(),
total_supply: BalanceForTests::lp_supply_init(),
metadata_id: None,
}),
nonce: 0,
@ -3127,7 +3133,7 @@ pub mod tests {
vault_a_id: IdForTests::vault_a_id(),
vault_b_id: IdForTests::vault_b_id(),
liquidity_pool_id: IdForTests::token_lp_definition_id(),
liquidity_pool_supply: BalanceForTests::user_token_a_holding_new_definition(),
liquidity_pool_supply: BalanceForTests::lp_supply_init(),
reserve_a: BalanceForTests::vault_a_balance_init(),
reserve_b: BalanceForTests::vault_b_balance_init(),
fees: 0u128,
@ -3417,7 +3423,7 @@ pub mod tests {
let user_token_b_post = state.get_account_by_id(IdForTests::user_token_b_id());
let user_token_lp_post = state.get_account_by_id(IdForTests::user_token_lp_id());
let expected_pool = AccountForTests::pool_definition_init();
let expected_pool = AccountForTests::pool_definition_new_init();
let expected_vault_a = AccountForTests::vault_a_init();
let expected_vault_b = AccountForTests::vault_b_init();
let expected_token_lp = AccountForTests::token_lp_definition_new_init();

View File

@ -77,7 +77,7 @@ pub fn new_definition(
);
// LP Token minting calculation
// We assume LP is based on the initial deposit amount for Token_A.
let initial_lp = (token_a_amount.get() * token_b_amount.get()).isqrt();
// Update pool account
let mut pool_post = pool.account.clone();
@ -87,7 +87,7 @@ pub fn new_definition(
vault_a_id: vault_a.account_id,
vault_b_id: vault_b.account_id,
liquidity_pool_id: pool_definition_lp.account_id,
liquidity_pool_supply: token_a_amount.into(),
liquidity_pool_supply: initial_lp,
reserve_a: token_a_amount.into(),
reserve_b: token_b_amount.into(),
fees: 0u128, // TODO: we assume all fees are 0 for now.
@ -124,11 +124,11 @@ pub fn new_definition(
let instruction = if pool.account == Account::default() {
token_core::Instruction::NewFungibleDefinition {
name: String::from("LP Token"),
total_supply: token_a_amount.into(),
total_supply: initial_lp,
}
} else {
token_core::Instruction::Mint {
amount_to_mint: token_a_amount.into(),
amount_to_mint: initial_lp,
}
};

View File

@ -70,7 +70,7 @@ impl BalanceForTests {
}
fn remove_actual_a_successful() -> u128 {
100
141
}
fn remove_min_amount_b_low() -> u128 {
@ -105,6 +105,11 @@ impl BalanceForTests {
20
}
fn lp_supply_init() -> u128 {
// sqrt(vault_a_reserve_init * vault_b_reserve_init) = sqrt(1000 * 500) = 707
(BalanceForTests::vault_a_reserve_init() * BalanceForTests::vault_b_reserve_init()).isqrt()
}
fn vault_a_swap_test_1() -> u128 {
1_500
}
@ -142,11 +147,11 @@ impl BalanceForTests {
}
fn vault_a_remove_successful() -> u128 {
900
859
}
fn vault_b_remove_successful() -> u128 {
450
430
}
}
@ -249,7 +254,7 @@ impl ChainedCallForTests {
TOKEN_PROGRAM_ID,
vec![pool_lp_auth, AccountForTests::user_holding_lp_init()],
&token_core::Instruction::Mint {
amount_to_mint: BalanceForTests::add_successful_amount_a(),
amount_to_mint: 282,
},
)
.with_pda_seeds(vec![compute_liquidity_token_pda_seed(
@ -282,7 +287,7 @@ impl ChainedCallForTests {
TOKEN_PROGRAM_ID,
vec![vault_b_auth, AccountForTests::user_holding_b()],
&token_core::Instruction::Transfer {
amount_to_transfer: BalanceForTests::remove_min_amount_b_low(),
amount_to_transfer: 70,
},
)
.with_pda_seeds(vec![compute_vault_pda_seed(
@ -341,7 +346,7 @@ impl ChainedCallForTests {
AccountForTests::user_holding_lp_uninit(),
],
&token_core::Instruction::Mint {
amount_to_mint: BalanceForTests::add_successful_amount_a(),
amount_to_mint: BalanceForTests::lp_supply_init(),
},
)
.with_pda_seeds(vec![compute_liquidity_token_pda_seed(
@ -568,7 +573,7 @@ impl AccountForTests {
balance: 0u128,
data: Data::from(&TokenDefinition::Fungible {
name: String::from("test"),
total_supply: BalanceForTests::vault_a_reserve_init(),
total_supply: BalanceForTests::lp_supply_init(),
metadata_id: None,
}),
nonce: 0,
@ -585,7 +590,7 @@ impl AccountForTests {
balance: 0u128,
data: Data::from(&TokenDefinition::Fungible {
name: String::from("test"),
total_supply: BalanceForTests::vault_a_reserve_init(),
total_supply: BalanceForTests::lp_supply_init(),
metadata_id: None,
}),
nonce: 0,
@ -638,7 +643,7 @@ impl AccountForTests {
vault_a_id: IdForTests::vault_a_id(),
vault_b_id: IdForTests::vault_b_id(),
liquidity_pool_id: IdForTests::token_lp_definition_id(),
liquidity_pool_supply: BalanceForTests::vault_a_reserve_init(),
liquidity_pool_supply: BalanceForTests::lp_supply_init(),
reserve_a: BalanceForTests::vault_a_reserve_init(),
reserve_b: BalanceForTests::vault_b_reserve_init(),
fees: 0u128,
@ -662,7 +667,7 @@ impl AccountForTests {
vault_a_id: IdForTests::vault_a_id(),
vault_b_id: IdForTests::vault_b_id(),
liquidity_pool_id: IdForTests::token_lp_definition_id(),
liquidity_pool_supply: BalanceForTests::vault_a_reserve_init(),
liquidity_pool_supply: BalanceForTests::lp_supply_init(),
reserve_a: 0,
reserve_b: BalanceForTests::vault_b_reserve_init(),
fees: 0u128,
@ -686,7 +691,7 @@ impl AccountForTests {
vault_a_id: IdForTests::vault_a_id(),
vault_b_id: IdForTests::vault_b_id(),
liquidity_pool_id: IdForTests::token_lp_definition_id(),
liquidity_pool_supply: BalanceForTests::vault_a_reserve_init(),
liquidity_pool_supply: BalanceForTests::lp_supply_init(),
reserve_a: BalanceForTests::vault_a_reserve_init(),
reserve_b: 0,
fees: 0u128,
@ -758,7 +763,7 @@ impl AccountForTests {
vault_a_id: IdForTests::vault_a_id(),
vault_b_id: IdForTests::vault_b_id(),
liquidity_pool_id: IdForTests::token_lp_definition_id(),
liquidity_pool_supply: BalanceForTests::vault_a_reserve_init(),
liquidity_pool_supply: BalanceForTests::lp_supply_init(),
reserve_a: BalanceForTests::vault_a_swap_test_1(),
reserve_b: BalanceForTests::vault_b_swap_test_1(),
fees: 0u128,
@ -782,7 +787,7 @@ impl AccountForTests {
vault_a_id: IdForTests::vault_a_id(),
vault_b_id: IdForTests::vault_b_id(),
liquidity_pool_id: IdForTests::token_lp_definition_id(),
liquidity_pool_supply: BalanceForTests::vault_a_reserve_init(),
liquidity_pool_supply: BalanceForTests::lp_supply_init(),
reserve_a: BalanceForTests::vault_a_swap_test_2(),
reserve_b: BalanceForTests::vault_b_swap_test_2(),
fees: 0u128,
@ -830,7 +835,7 @@ impl AccountForTests {
vault_a_id: IdForTests::vault_a_id(),
vault_b_id: IdForTests::vault_b_id(),
liquidity_pool_id: IdForTests::token_lp_definition_id(),
liquidity_pool_supply: BalanceForTests::vault_a_add_successful(),
liquidity_pool_supply: 989,
reserve_a: BalanceForTests::vault_a_add_successful(),
reserve_b: BalanceForTests::vault_b_add_successful(),
fees: 0u128,
@ -854,7 +859,7 @@ impl AccountForTests {
vault_a_id: IdForTests::vault_a_id(),
vault_b_id: IdForTests::vault_b_id(),
liquidity_pool_id: IdForTests::token_lp_definition_id(),
liquidity_pool_supply: BalanceForTests::vault_a_remove_successful(),
liquidity_pool_supply: 607,
reserve_a: BalanceForTests::vault_a_remove_successful(),
reserve_b: BalanceForTests::vault_b_remove_successful(),
fees: 0u128,
@ -878,7 +883,7 @@ impl AccountForTests {
vault_a_id: IdForTests::vault_a_id(),
vault_b_id: IdForTests::vault_b_id(),
liquidity_pool_id: IdForTests::token_lp_definition_id(),
liquidity_pool_supply: BalanceForTests::vault_a_reserve_init(),
liquidity_pool_supply: BalanceForTests::lp_supply_init(),
reserve_a: BalanceForTests::vault_a_reserve_init(),
reserve_b: BalanceForTests::vault_b_reserve_init(),
fees: 0u128,
@ -902,7 +907,7 @@ impl AccountForTests {
vault_a_id: IdForTests::vault_a_id(),
vault_b_id: IdForTests::vault_b_id(),
liquidity_pool_id: IdForTests::token_lp_definition_id(),
liquidity_pool_supply: BalanceForTests::vault_a_reserve_init(),
liquidity_pool_supply: BalanceForTests::lp_supply_init(),
reserve_a: BalanceForTests::vault_a_reserve_init(),
reserve_b: BalanceForTests::vault_b_reserve_init(),
fees: 0u128,
@ -958,7 +963,7 @@ impl AccountForTests {
vault_a_id: IdForTests::vault_a_id(),
vault_b_id: IdForTests::vault_b_id(),
liquidity_pool_id: IdForTests::token_lp_definition_id(),
liquidity_pool_supply: BalanceForTests::vault_a_reserve_init(),
liquidity_pool_supply: BalanceForTests::lp_supply_init(),
reserve_a: BalanceForTests::vault_a_reserve_init(),
reserve_b: BalanceForTests::vault_b_reserve_init(),
fees: 0u128,
@ -1717,3 +1722,73 @@ fn test_call_swap_chained_call_successful_2() {
ChainedCallForTests::cc_swap_token_b_test_2()
);
}
#[test]
fn test_new_definition_lp_asymmetric_amounts() {
let (post_states, chained_calls) = new_definition(
AccountForTests::pool_definition_inactive(),
AccountForTests::vault_a_init(),
AccountForTests::vault_b_init(),
AccountForTests::pool_lp_init(),
AccountForTests::user_holding_a(),
AccountForTests::user_holding_b(),
AccountForTests::user_holding_lp_uninit(),
NonZero::new(BalanceForTests::vault_a_reserve_init()).unwrap(),
NonZero::new(BalanceForTests::vault_b_reserve_init()).unwrap(),
AMM_PROGRAM_ID,
);
// check the minted LP amount
let pool_post = post_states[0].clone();
let pool_def = PoolDefinition::try_from(&pool_post.account().data).unwrap();
assert_eq!(
pool_def.liquidity_pool_supply,
BalanceForTests::lp_supply_init()
);
let chained_call_lp = chained_calls[0].clone();
assert!(chained_call_lp == ChainedCallForTests::cc_new_definition_token_lp());
}
#[test]
fn test_new_definition_lp_symmetric_amounts() {
// token_a=100, token_b=100 → LP=sqrt(10_000)=100
let token_a_amount = 100u128;
let token_b_amount = 100u128;
let expected_lp = (token_a_amount * token_b_amount).isqrt();
assert_eq!(expected_lp, 100);
let (post_states, chained_calls) = new_definition(
AccountForTests::pool_definition_inactive(),
AccountForTests::vault_a_init(),
AccountForTests::vault_b_init(),
AccountForTests::pool_lp_init(),
AccountForTests::user_holding_a(),
AccountForTests::user_holding_b(),
AccountForTests::user_holding_lp_uninit(),
NonZero::new(token_a_amount).unwrap(),
NonZero::new(token_b_amount).unwrap(),
AMM_PROGRAM_ID,
);
let pool_post = post_states[0].clone();
let pool_def = PoolDefinition::try_from(&pool_post.account().data).unwrap();
assert_eq!(pool_def.liquidity_pool_supply, expected_lp);
let chained_call_lp = chained_calls[0].clone();
let expected_lp_call = ChainedCall::new(
TOKEN_PROGRAM_ID,
vec![
AccountForTests::pool_lp_init(),
AccountForTests::user_holding_lp_uninit(),
],
&token_core::Instruction::Mint {
amount_to_mint: expected_lp,
},
)
.with_pda_seeds(vec![compute_liquidity_token_pda_seed(
IdForTests::pool_definition_id(),
)]);
assert_eq!(chained_call_lp, expected_lp_call);
}

View File

@ -28,7 +28,7 @@ pub trait BlockSettlementClientTrait: Clone {
/// Create and sign a transaction for inscribing data.
fn create_inscribe_tx(&self, block: &Block) -> Result<(SignedMantleTx, MsgId)> {
let inscription_data = borsh::to_vec(block)?;
log::info!(
log::debug!(
"The size of the block {} is {} bytes",
block.header.block_id,
inscription_data.len()
@ -104,7 +104,7 @@ impl BlockSettlementClientTrait for BlockSettlementClient {
.await
.context("Failed to post transaction to Bedrock")?;
log::info!("Posted block to Bedrock with parent id {parent_id:?} and msg id: {msg_id:?}");
log::debug!("Posted block to Bedrock with parent id {parent_id:?} and msg id: {msg_id:?}");
Ok(())
}

View File

@ -20,50 +20,50 @@
"indexer_rpc_url": "ws://localhost:8779",
"initial_accounts": [
{
"account_id": "BLgCRDXYdQPMMWVHYRFGQZbgeHx9frkipa8GtpG2Syqy",
"account_id": "6iArKUXxhUJqS7kCaPNhwMWt3ro71PDyBj7jwAyE2VQV",
"balance": 10000
},
{
"account_id": "Gj1mJy5W7J5pfmLRujmQaLfLMWidNxQ6uwnhb666ZwHw",
"account_id": "7wHg9sbJwc6h3NP1S9bekfAzB8CHifEcxKswCKUt3YQo",
"balance": 20000
}
],
"initial_commitments": [
{
"npk": [
63,
202,
178,
231,
183,
82,
237,
212,
216,
221,
215,
255,
153,
101,
"npk":[
177,
161,
254,
210,
128,
122,
54,
190,
230,
151,
183,
64,
225,
229,
113,
1,
228,
97
],
11,
87,
38,
254,
159,
231,
165,
1,
94,
64,
137,
243,
76,
249,
101,
251,
129,
33,
101,
189,
30,
42,
11,
191,
34,
103,
186,
227,
230
] ,
"account": {
"program_owner": [
0,
@ -82,38 +82,38 @@
},
{
"npk": [
192,
251,
166,
243,
167,
236,
84,
249,
35,
32,
67,
72,
164,
106,
53,
66,
239,
141,
15,
52,
230,
136,
130,
172,
219,
225,
161,
139,
229,
89,
177,
2,
236,
207,
243,
125,
134,
135,
210,
143,
87,
232,
215,
128,
194,
213,
209,
30,
23,
174,
100,
244,
124,
74,
140,
47
120,
113,
224,
4,
165
],
"account": {
"program_owner": [

View File

@ -182,8 +182,16 @@ async fn retry_pending_blocks(seq_core: &Arc<Mutex<SequencerCore>>) -> Result<()
(pending_blocks, client)
};
for block in pending_blocks.iter() {
if !pending_blocks.is_empty() {
info!(
"Resubmitting blocks from {} to {}",
pending_blocks.first().unwrap().header.block_id,
pending_blocks.last().unwrap().header.block_id
);
}
for block in pending_blocks.iter() {
debug!(
"Resubmitting pending block with id {}",
block.header.block_id
);