Skip to content

Commit

Permalink
Merge pull request #313 from hirosystems/develop
Browse files Browse the repository at this point in the history
release 2.2.1
  • Loading branch information
rafaelcr committed Jun 11, 2024
2 parents 66e92a5 + 2b235d2 commit bd511a2
Show file tree
Hide file tree
Showing 14 changed files with 296 additions and 50 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ name: CI
on:
push:
branches:
- main
- develop
- feat/ordhook-sdk-js
paths-ignore:
- "**/CHANGELOG.md"
pull_request:
Expand Down
5 changes: 4 additions & 1 deletion components/ordhook-cli/src/cli/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -568,6 +568,7 @@ async fn handle_command(opts: Opts, ctx: &Context) -> Result<(), String> {
Some(&block_heights),
None,
cmd.auth_token,
false,
)?;

let _ = initialize_observers_db(&config.expected_cache_path(), ctx);
Expand Down Expand Up @@ -751,6 +752,7 @@ async fn handle_command(opts: Opts, ctx: &Context) -> Result<(), String> {
None,
Some(start_block),
cmd.auth_token.clone(),
true,
)?;
predicates.push(predicate);
}
Expand Down Expand Up @@ -965,6 +967,7 @@ pub fn build_predicate_from_cli(
block_heights: Option<&BlockHeights>,
start_block: Option<u64>,
auth_token: Option<String>,
is_streaming: bool,
) -> Result<BitcoinChainhookSpecification, String> {
// Retrieve last block height known, and display it
let (start_block, end_block, blocks) = match (start_block, block_heights) {
Expand Down Expand Up @@ -994,7 +997,7 @@ pub fn build_predicate_from_cli(
include_outputs: false,
include_witness: false,
expired_at: None,
enabled: true,
enabled: is_streaming,
predicate: BitcoinPredicateType::OrdinalsProtocol(OrdinalOperations::InscriptionFeed(
InscriptionFeedData { meta_protocols },
)),
Expand Down
203 changes: 199 additions & 4 deletions components/ordhook-core/src/core/meta_protocols/brc20/db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ use crate::db::{
};
use chainhook_sdk::{
types::{
BitcoinTransactionData, BlockIdentifier, Brc20BalanceData, Brc20Operation,
Brc20TokenDeployData, Brc20TransferData,
BitcoinBlockData, BitcoinTransactionData, BlockIdentifier, Brc20BalanceData,
Brc20Operation, Brc20TokenDeployData, Brc20TransferData, OrdinalInscriptionRevealData,
OrdinalOperation,
},
utils::Context,
};
Expand Down Expand Up @@ -259,7 +260,7 @@ pub fn get_transfer_send_receiver_address(
perform_query_one(query, args, &db_tx, ctx, |row| row.get(0).unwrap())
}

pub fn insert_ledger_rows(rows: &Vec<Brc20DbLedgerRow>, db_tx: &Transaction, ctx: &Context) {
pub fn insert_ledger_rows(rows: &Vec<Brc20DbLedgerRow>, db_tx: &Connection, ctx: &Context) {
match db_tx.prepare_cached("INSERT INTO ledger
(inscription_id, inscription_number, ordinal_number, block_height, tx_index, tick, address, avail_balance, trans_balance, operation)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)") {
Expand All @@ -286,7 +287,7 @@ pub fn insert_ledger_rows(rows: &Vec<Brc20DbLedgerRow>, db_tx: &Transaction, ctx
}
}

pub fn insert_token_rows(rows: &Vec<Brc20DbTokenRow>, db_tx: &Transaction, ctx: &Context) {
pub fn insert_token_rows(rows: &Vec<Brc20DbTokenRow>, db_tx: &Connection, ctx: &Context) {
match db_tx.prepare_cached(
"INSERT INTO tokens
(inscription_id, inscription_number, block_height, tick, max, lim, dec, address, self_mint)
Expand Down Expand Up @@ -424,6 +425,200 @@ pub fn augment_transaction_with_brc20_operation_data(
inscription_id: entry.inscription_id,
}));
}
// `transfer_receive` ops are not reflected in transaction metadata.
_ => {}
}
}

/// Retrieves the inscription number and ordinal number from a `transfer` operation.
fn get_transfer_inscription_info(
inscription_id: &String,
db_tx: &Connection,
ctx: &Context,
) -> Option<(u64, u64)> {
let args: &[&dyn ToSql] = &[&inscription_id.to_sql().unwrap()];
let query = "
SELECT inscription_number, ordinal_number
FROM ledger
WHERE inscription_id = ? AND operation = 'transfer'
LIMIT 1
";
perform_query_one(query, args, &db_tx, ctx, |row| {
(row.get(0).unwrap(), row.get(1).unwrap())
})
}

/// Finds an inscription reveal with a specific inscription ID within an augmented block.
fn find_reveal_in_tx<'a>(
inscription_id: &String,
tx: &'a BitcoinTransactionData,
) -> Option<&'a OrdinalInscriptionRevealData> {
for operation in tx.metadata.ordinal_operations.iter() {
match operation {
OrdinalOperation::InscriptionRevealed(reveal) => {
if reveal.inscription_id == *inscription_id {
return Some(reveal);
}
}
OrdinalOperation::InscriptionTransferred(_) => return None,
}
}
None
}

/// Takes a block already augmented with BRC-20 data and writes its operations into the brc20.sqlite DB. Called when
/// receiving a block back from Chainhook SDK.
pub fn write_augmented_block_to_brc20_db(
block: &BitcoinBlockData,
db_conn: &Connection,
ctx: &Context,
) {
let mut tokens: Vec<Brc20DbTokenRow> = vec![];
let mut ledger_rows: Vec<Brc20DbLedgerRow> = vec![];
let mut transfers = HashMap::<String, (u64, u64)>::new();
for tx in block.transactions.iter() {
if let Some(brc20_operation) = &tx.metadata.brc20_operation {
match brc20_operation {
Brc20Operation::Deploy(token) => {
let Some(reveal) = find_reveal_in_tx(&token.inscription_id, tx) else {
ctx.try_log(|logger| {
warn!(
logger,
"Could not find BRC-20 deploy inscription in augmented block: {}",
token.inscription_id
)
});
continue;
};
tokens.push(Brc20DbTokenRow {
inscription_id: token.inscription_id.clone(),
inscription_number: reveal.inscription_number.jubilee as u64,
block_height: block.block_identifier.index,
tick: token.tick.clone(),
max: token.max.parse::<f64>().unwrap(),
lim: token.lim.parse::<f64>().unwrap(),
dec: token.dec.parse::<u64>().unwrap(),
address: token.address.clone(),
self_mint: token.self_mint,
});
ledger_rows.push(Brc20DbLedgerRow {
inscription_id: token.inscription_id.clone(),
inscription_number: reveal.inscription_number.jubilee as u64,
ordinal_number: reveal.ordinal_number,
block_height: block.block_identifier.index,
tx_index: tx.metadata.index as u64,
tick: token.tick.clone(),
address: token.address.clone(),
avail_balance: 0.0,
trans_balance: 0.0,
operation: "deploy".to_string(),
});
}
Brc20Operation::Mint(balance) => {
let Some(reveal) = find_reveal_in_tx(&balance.inscription_id, tx) else {
ctx.try_log(|logger| {
warn!(
logger,
"Could not find BRC-20 mint inscription in augmented block: {}",
balance.inscription_id
)
});
continue;
};
ledger_rows.push(Brc20DbLedgerRow {
inscription_id: balance.inscription_id.clone(),
inscription_number: reveal.inscription_number.jubilee as u64,
ordinal_number: reveal.ordinal_number,
block_height: block.block_identifier.index,
tx_index: tx.metadata.index as u64,
tick: balance.tick.clone(),
address: balance.address.clone(),
avail_balance: balance.amt.parse::<f64>().unwrap(),
trans_balance: 0.0,
operation: "mint".to_string(),
});
}
Brc20Operation::Transfer(balance) => {
let Some(reveal) = find_reveal_in_tx(&balance.inscription_id, tx) else {
ctx.try_log(|logger| {
warn!(
logger,
"Could not find BRC-20 transfer inscription in augmented block: {}",
balance.inscription_id
)
});
continue;
};
ledger_rows.push(Brc20DbLedgerRow {
inscription_id: balance.inscription_id.clone(),
inscription_number: reveal.inscription_number.jubilee as u64,
ordinal_number: reveal.ordinal_number,
block_height: block.block_identifier.index,
tx_index: tx.metadata.index as u64,
tick: balance.tick.clone(),
address: balance.address.clone(),
avail_balance: balance.amt.parse::<f64>().unwrap() * -1.0,
trans_balance: balance.amt.parse::<f64>().unwrap(),
operation: "transfer".to_string(),
});
transfers.insert(
balance.inscription_id.clone(),
(
reveal.inscription_number.jubilee as u64,
reveal.ordinal_number,
),
);
}
Brc20Operation::TransferSend(transfer) => {
let inscription_number: u64;
let ordinal_number: u64;
if let Some(info) = transfers.get(&transfer.inscription_id) {
inscription_number = info.0;
ordinal_number = info.1;
} else if let Some(info) =
get_transfer_inscription_info(&transfer.inscription_id, db_conn, ctx)
{
inscription_number = info.0;
ordinal_number = info.1;
} else {
ctx.try_log(|logger| {
warn!(
logger,
"Could not find BRC-20 transfer inscription in brc20 db: {}",
transfer.inscription_id
)
});
continue;
};
let amt = transfer.amt.parse::<f64>().unwrap();
ledger_rows.push(Brc20DbLedgerRow {
inscription_id: transfer.inscription_id.clone(),
inscription_number,
ordinal_number,
block_height: block.block_identifier.index,
tx_index: tx.metadata.index as u64,
tick: transfer.tick.clone(),
address: transfer.sender_address.clone(),
avail_balance: 0.0,
trans_balance: amt * -1.0,
operation: "transfer_send".to_string(),
});
ledger_rows.push(Brc20DbLedgerRow {
inscription_id: transfer.inscription_id.clone(),
inscription_number,
ordinal_number,
block_height: block.block_identifier.index,
tx_index: tx.metadata.index as u64,
tick: transfer.tick.clone(),
address: transfer.receiver_address.clone(),
avail_balance: amt,
trans_balance: 0.0,
operation: "transfer_receive".to_string(),
});
}
}
}
}
insert_token_rows(&tokens, db_conn, ctx);
insert_ledger_rows(&ledger_rows, db_conn, ctx);
}
4 changes: 2 additions & 2 deletions components/ordhook-core/src/core/meta_protocols/brc20/mod.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
use chainhook_sdk::types::BitcoinNetwork;

pub mod cache;
pub mod db;
pub mod parser;
pub mod verifier;
pub mod cache;
pub mod test_utils;
pub mod verifier;

pub fn brc20_activation_height(network: &BitcoinNetwork) -> u64 {
match network {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
use chainhook_sdk::{types::{OrdinalInscriptionNumber, OrdinalInscriptionRevealData, OrdinalInscriptionTransferData, OrdinalInscriptionTransferDestination}, utils::Context};
use chainhook_sdk::{
types::{
OrdinalInscriptionNumber, OrdinalInscriptionRevealData, OrdinalInscriptionTransferData,
OrdinalInscriptionTransferDestination,
},
utils::Context,
};

pub fn get_test_ctx() -> Context {
let logger = hiro_system_kit::log::setup_logger();
Expand All @@ -25,8 +31,8 @@ impl Brc20RevealBuilder {
jubilee: 0,
},
inscriber_address: Some("324A7GHA2azecbVBAFy4pzEhcPT1GjbUAp".to_string()),
inscription_id:
"9bb2314d666ae0b1db8161cb373fcc1381681f71445c4e0335aa80ea9c37fcddi0".to_string(),
inscription_id: "9bb2314d666ae0b1db8161cb373fcc1381681f71445c4e0335aa80ea9c37fcddi0"
.to_string(),
ordinal_number: 0,
parent: None,
}
Expand Down Expand Up @@ -82,8 +88,7 @@ impl Brc20RevealBuilder {
tx_index: 0,
transfers_pre_inscription: 0,
satpoint_post_inscription:
"9bb2314d666ae0b1db8161cb373fcc1381681f71445c4e0335aa80ea9c37fcdd:0:0"
.to_string(),
"9bb2314d666ae0b1db8161cb373fcc1381681f71445c4e0335aa80ea9c37fcdd:0:0".to_string(),
curse_type: None,
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,13 +148,13 @@ pub fn verify_brc20_operation(
token.tick, data.amt
));
}
let Some(avail_balance) = cache.get_token_address_avail_balance(
&token.tick,
&inscriber_address,
db_tx,
ctx,
) else {
return Err(format!("Balance does not exist for {} transfer, attempting to transfer {}", token.tick, data.amt));
let Some(avail_balance) =
cache.get_token_address_avail_balance(&token.tick, &inscriber_address, db_tx, ctx)
else {
return Err(format!(
"Balance does not exist for {} transfer, attempting to transfer {}",
token.tick, data.amt
));
};
if avail_balance < data.float_amt() {
return Err(format!("Insufficient balance for {} transfer, attempting to transfer {}, only {} available", token.tick, data.amt, avail_balance));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -571,6 +571,7 @@ pub fn augment_block_with_ordinals_inscriptions_data_and_write_to_db_tx(
// Handle re-inscriptions
let mut reinscriptions_data = HashMap::new();
for (_, inscription_data) in inscriptions_data.iter() {
// TODO: Comment on why this is necessary.
if inscription_data.ordinal_number != 0 {
if let Some(inscription_id) = find_blessed_inscription_with_ordinal_number(
&inscription_data.ordinal_number,
Expand Down
17 changes: 10 additions & 7 deletions components/ordhook-core/src/core/protocol/satoshi_tracking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,12 @@ pub fn compute_satpoint_post_transfer(
SatPosition::Fee(offset) => {
// Get Coinbase TX
let total_offset = coinbase_subsidy + *cumulated_fees + offset;
let outputs = coinbase_tx.metadata.outputs.iter().map(|o| o.value).collect();
let outputs = coinbase_tx
.metadata
.outputs
.iter()
.map(|o| o.value)
.collect();
let post_transfer_data = compute_next_satpoint_data(
0,
&vec![total_offset],
Expand All @@ -153,16 +158,14 @@ pub fn compute_satpoint_post_transfer(
SatPosition::Output(pos) => pos,
_ => {
ctx.try_log(|logger| {
info!(
logger,
"unable to locate satoshi in coinbase outputs",
)
});
info!(logger, "unable to locate satoshi in coinbase outputs",)
});
(0, total_offset)
}
};

let outpoint = format_outpoint_to_watch(&coinbase_tx.transaction_identifier, output_index);
let outpoint =
format_outpoint_to_watch(&coinbase_tx.transaction_identifier, output_index);
(
outpoint,
offset,
Expand Down
2 changes: 1 addition & 1 deletion components/ordhook-core/src/db/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -809,7 +809,7 @@ pub fn find_latest_inscription_block_height(
ctx: &Context,
) -> Result<Option<u64>, String> {
let args: &[&dyn ToSql] = &[];
let query = "SELECT block_height FROM inscriptions ORDER BY block_height DESC LIMIT 1";
let query = "SELECT block_height FROM sequence_metadata ORDER BY block_height DESC LIMIT 1";
let entry = perform_query_one(query, args, db_conn, ctx, |row| {
let block_height: u64 = row.get(0).unwrap();
block_height
Expand Down
Loading

0 comments on commit bd511a2

Please sign in to comment.