mirror of
https://github.com/logos-blockchain/lssa.git
synced 2026-02-28 01:03:25 +00:00
Merge branch 'main' into marvin/bip-32-comp
This commit is contained in:
commit
5a0ef060fd
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -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.
@ -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 = [
|
||||
|
||||
@ -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> {
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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">
|
||||
|
||||
@ -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
37
flake.lock
generated
@ -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"
|
||||
}
|
||||
},
|
||||
|
||||
@ -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 (
|
||||
|
||||
@ -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())?)
|
||||
}
|
||||
}
|
||||
|
||||
@ -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,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@ -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>>,
|
||||
}
|
||||
@ -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
|
||||
|
||||
@ -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": {
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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,
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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(())
|
||||
}
|
||||
|
||||
@ -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": [
|
||||
|
||||
@ -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
|
||||
);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user