Skip to content

Commit

Permalink
RPC: Output bitcoin address for transaction and object (#1891)
Browse files Browse the repository at this point in the history
  • Loading branch information
pause125 authored Jun 15, 2024
1 parent d33054c commit 97166b8
Show file tree
Hide file tree
Showing 6 changed files with 194 additions and 34 deletions.
18 changes: 18 additions & 0 deletions crates/rooch-open-rpc-spec/schemas/openrpc.json
Original file line number Diff line number Diff line change
Expand Up @@ -1237,6 +1237,12 @@
"owner": {
"$ref": "#/components/schemas/rooch_types::address::RoochAddress"
},
"owner_bitcoin_address": {
"type": [
"string",
"null"
]
},
"size": {
"type": "integer",
"format": "uint64",
Expand Down Expand Up @@ -1676,6 +1682,12 @@
"sender": {
"type": "string"
},
"sender_bitcoin_address": {
"type": [
"string",
"null"
]
},
"sequence_number": {
"type": "integer",
"format": "uint64",
Expand Down Expand Up @@ -1914,6 +1926,12 @@
"owner": {
"$ref": "#/components/schemas/rooch_types::address::RoochAddress"
},
"owner_bitcoin_address": {
"type": [
"string",
"null"
]
},
"size": {
"type": "integer",
"format": "uint64",
Expand Down
9 changes: 7 additions & 2 deletions crates/rooch-rpc-api/src/jsonrpc_types/rooch_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,16 +44,21 @@ pub struct PageView<T, C> {
pub struct TransactionView {
pub sequence_number: u64,
pub sender: String,
pub sender_bitcoin_address: Option<String>,
pub action_type: MoveActionTypeView,
pub action: MoveActionView,
pub raw: BytesView,
}

impl From<RoochTransaction> for TransactionView {
fn from(transaction: RoochTransaction) -> Self {
impl TransactionView {
pub fn new_from_rooch_transaction(
transaction: RoochTransaction,
sender_bitcoin_address: Option<String>,
) -> Self {
Self {
sequence_number: transaction.sequence_number(),
sender: transaction.sender().to_string(),
sender_bitcoin_address,
action: transaction.action().clone().into(),
action_type: transaction.action().clone().into(),
raw: transaction.encode().into(),
Expand Down
11 changes: 11 additions & 0 deletions crates/rooch-rpc-api/src/jsonrpc_types/state_view.rs
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,7 @@ impl From<StateSyncFilterView> for StateSyncFilter {
pub struct IndexerObjectStateView {
pub object_id: ObjectID,
pub owner: RoochAddressView,
pub owner_bitcoin_address: Option<String>,
pub flag: u8,
/// bcs bytes of the Object.
pub value: BytesView,
Expand All @@ -373,12 +374,14 @@ impl IndexerObjectStateView {
pub fn new_from_object_state(
state: IndexerObjectState,
value: Vec<u8>,
owner_bitcoin_address: Option<String>,
decoded_value: Option<AnnotatedMoveStructView>,
display_fields: Option<DisplayFieldsView>,
) -> IndexerObjectStateView {
IndexerObjectStateView {
object_id: state.object_id,
owner: state.owner.into(),
owner_bitcoin_address,
flag: state.flag,
value: value.into(),
decoded_value,
Expand Down Expand Up @@ -437,6 +440,7 @@ impl ObjectStateFilterView {
pub struct ObjectStateView {
pub id: ObjectID,
pub owner: RoochAddressView,
pub owner_bitcoin_address: Option<String>,
pub flag: u8,
pub object_type: StructTagView,
pub state_root: H256View,
Expand All @@ -453,6 +457,7 @@ impl ObjectStateView {
ObjectStateView {
id: object.id,
owner: object.owner.into(),
owner_bitcoin_address: None,
flag: object.flag,
object_type: object.value.type_.clone().into(),
state_root: object.state_root.into(),
Expand All @@ -473,6 +478,7 @@ impl ObjectStateView {
ObjectStateView {
id: object.id,
owner: object.owner.into(),
owner_bitcoin_address: None,
flag: object.flag,
object_type: object.value.struct_tag.into(),
state_root: object.state_root.into(),
Expand All @@ -489,4 +495,9 @@ impl ObjectStateView {
self.display_fields = display_fields;
self
}

pub fn with_owner_bitcoin_address(mut self, owner_bitcoin_address: Option<String>) -> Self {
self.owner_bitcoin_address = owner_bitcoin_address;
self
}
}
32 changes: 23 additions & 9 deletions crates/rooch-rpc-api/src/jsonrpc_types/transaction_view.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,16 @@ pub enum LedgerTxDataView {
L2Tx(TransactionView),
}

impl From<LedgerTxData> for LedgerTxDataView {
fn from(data: LedgerTxData) -> Self {
impl LedgerTxDataView {
pub fn new_from_ledger_txdata(
data: LedgerTxData,
sender_bitcoin_address: Option<String>,
) -> Self {
match data {
LedgerTxData::L1Block(block) => LedgerTxDataView::L1Block(block.into()),
LedgerTxData::L2Tx(tx) => LedgerTxDataView::L2Tx(tx.into()),
LedgerTxData::L2Tx(tx) => LedgerTxDataView::L2Tx(
TransactionView::new_from_rooch_transaction(tx, sender_bitcoin_address),
),
}
}
}
Expand All @@ -50,10 +55,13 @@ pub struct LedgerTransactionView {
pub sequence_info: TransactionSequenceInfoView,
}

impl From<LedgerTransaction> for LedgerTransactionView {
fn from(tx: LedgerTransaction) -> Self {
impl LedgerTransactionView {
pub fn new_from_ledger_transaction(
tx: LedgerTransaction,
sender_bitcoin_address: Option<String>,
) -> Self {
Self {
data: tx.data.into(),
data: LedgerTxDataView::new_from_ledger_txdata(tx.data, sender_bitcoin_address),
sequence_info: tx.sequence_info.into(),
}
}
Expand All @@ -65,10 +73,16 @@ pub struct TransactionWithInfoView {
pub execution_info: TransactionExecutionInfoView,
}

impl From<TransactionWithInfo> for TransactionWithInfoView {
fn from(tx: TransactionWithInfo) -> Self {
impl TransactionWithInfoView {
pub fn new_from_transaction_with_info(
tx: TransactionWithInfo,
sender_bitcoin_address: Option<String>,
) -> Self {
Self {
transaction: tx.transaction.into(),
transaction: LedgerTransactionView::new_from_ledger_transaction(
tx.transaction,
sender_bitcoin_address,
),
execution_info: tx.execution_info.into(),
}
}
Expand Down
145 changes: 123 additions & 22 deletions crates/rooch-rpc-server/src/server/rooch_server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ use rooch_rpc_api::{
};
use rooch_types::indexer::event::IndexerEventID;
use rooch_types::indexer::state::IndexerStateID;
use rooch_types::transaction::rooch::RoochTransaction;
use rooch_types::transaction::{RoochTransaction, TransactionWithInfo};
use std::cmp::min;
use std::str::FromStr;
use tracing::info;
Expand Down Expand Up @@ -116,6 +116,39 @@ impl RoochServer {
}
Ok(display_field_views)
}

async fn transactions_to_view(
&self,
data: Vec<TransactionWithInfo>,
) -> Result<Vec<TransactionWithInfoView>> {
let rooch_addresses = data
.iter()
.filter_map(|tx| tx.transaction.sender())
.collect::<Vec<_>>();
let address_mapping = self
.rpc_service
.get_bitcoin_addresses(rooch_addresses)
.await?;
let bitcoin_network = self.rpc_service.get_bitcoin_network().await?;
let data = data
.into_iter()
.map(|tx| {
let sender_bitcoin_address = match tx.transaction.sender() {
Some(rooch_address) => address_mapping
.get(&rooch_address)
.map(|addr| addr.clone().map(|a| a.format(bitcoin_network))),
None => None,
}
.flatten()
.transpose()?;
Ok(TransactionWithInfoView::new_from_transaction_with_info(
tx,
sender_bitcoin_address,
))
})
.collect::<Result<Vec<_>>>()?;
Ok(data)
}
}

#[async_trait]
Expand Down Expand Up @@ -362,6 +395,31 @@ impl RoochAPIServer for RoochServer {
})
.collect()
};

// Get owner_bitcoin_address
let addresses = objects_view
.iter()
.filter_map(|o| o.as_ref().map(|s| s.owner.into()))
.collect::<Vec<_>>();
let btc_network = self.rpc_service.get_bitcoin_network().await?;
let address_mapping = self.rpc_service.get_bitcoin_addresses(addresses).await?;

let objects_view = objects_view
.into_iter()
.map(|o| {
o.map(|s| {
let rooch_address = s.owner.into();
let bitcoin_address = address_mapping
.get(&rooch_address)
.expect("should exist.")
.clone()
.map(|a| a.format(btc_network))
.transpose()?;
Ok(s.with_owner_bitcoin_address(bitcoin_address))
})
.transpose()
})
.collect::<Result<Vec<_>>>()?;
Ok(objects_view)
}

Expand Down Expand Up @@ -427,13 +485,41 @@ impl RoochAPIServer for RoochServer {
) -> RpcResult<Vec<Option<TransactionWithInfoView>>> {
let tx_hashes: Vec<H256> = tx_hashes.iter().map(|m| (*m).into()).collect::<Vec<_>>();

let bitcoin_network = self.rpc_service.get_bitcoin_network().await?;
let data = self
.aggregate_service
.get_transaction_with_info(tx_hashes)
.await?
.into_iter()
.map(|item| item.map(TransactionWithInfoView::from))
.await?;

let rooch_addresses = data
.iter()
.filter_map(|tx| tx.as_ref().and_then(|tx| tx.transaction.sender()))
.collect::<Vec<_>>();
let address_mapping = self
.rpc_service
.get_bitcoin_addresses(rooch_addresses)
.await?;

let data = data
.into_iter()
.map(|item| {
item.map(|tx| {
let sender_bitcoin_address = match tx.transaction.sender() {
Some(rooch_address) => address_mapping
.get(&rooch_address)
.map(|addr| addr.clone().map(|a| a.format(bitcoin_network))),
None => None,
}
.flatten()
.transpose()?;
Ok(TransactionWithInfoView::new_from_transaction_with_info(
tx,
sender_bitcoin_address,
))
})
.transpose()
})
.collect::<Result<Vec<_>>>()?;

Ok(data)
}
Expand Down Expand Up @@ -502,9 +588,10 @@ impl RoochAPIServer for RoochServer {
.await?
.into_iter()
.flatten()
.map(TransactionWithInfoView::from)
.collect::<Vec<_>>();

let data = self.transactions_to_view(data).await?;

Ok(TransactionWithInfoPageView {
data,
next_cursor,
Expand Down Expand Up @@ -582,13 +669,13 @@ impl RoochAPIServer for RoochServer {
let mut data = self
.aggregate_service
.build_transaction_with_infos(txs)
.await?
.into_iter()
.map(TransactionWithInfoView::from)
.collect::<Vec<_>>();
.await?;

let has_next_page = data.len() > limit_of;
data.truncate(limit_of);

let data = self.transactions_to_view(data).await?;

let next_cursor = data
.last()
.cloned()
Expand Down Expand Up @@ -703,22 +790,36 @@ impl RoochAPIServer for RoochServer {
.collect::<Vec<_>>()
};

let network = self.rpc_service.get_bitcoin_network().await?;
let rooch_addresses = states.iter().map(|s| s.owner).collect::<Vec<_>>();
let bitcoin_addresses = self
.rpc_service
.get_bitcoin_addresses(rooch_addresses)
.await?
.into_values()
.map(|btc_addr| btc_addr.map(|addr| addr.format(network)).transpose())
.collect::<Result<Vec<Option<String>>>>()?;

let mut data = annotated_states_with_display
.into_iter()
.zip(states)
.map(|((value, annotated_state, display_fields), state)| {
let decoded_value = if decode {
Some(AnnotatedMoveStructView::from(annotated_state.value))
} else {
None
};
IndexerObjectStateView::new_from_object_state(
state,
value,
decoded_value,
display_fields,
)
})
.zip(bitcoin_addresses)
.map(
|(((value, annotated_state, display_fields), state), bitcoin_address)| {
let decoded_value = if decode {
Some(AnnotatedMoveStructView::from(annotated_state.value))
} else {
None
};
IndexerObjectStateView::new_from_object_state(
state,
value,
bitcoin_address,
decoded_value,
display_fields,
)
},
)
.collect::<Vec<_>>();

let has_next_page = data.len() > limit_of;
Expand Down
Loading

0 comments on commit 97166b8

Please sign in to comment.