Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 28 additions & 1 deletion dash-spv-ffi/FFI_API.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ This document provides a comprehensive reference for all FFI (Foreign Function I

**Auto-generated**: This documentation is automatically generated from the source code. Do not edit manually.

**Total Functions**: 49
**Total Functions**: 50

## Table of Contents

Expand All @@ -13,6 +13,7 @@ This document provides a comprehensive reference for all FFI (Foreign Function I
- [Synchronization](#synchronization)
- [Wallet Operations](#wallet-operations)
- [Transaction Management](#transaction-management)
- [Mempool Operations](#mempool-operations)
- [Platform Integration](#platform-integration)
- [Event Callbacks](#event-callbacks)
- [Error Handling](#error-handling)
Expand Down Expand Up @@ -82,6 +83,14 @@ Functions: 1
|----------|-------------|--------|
| `dash_spv_ffi_client_broadcast_transaction` | Broadcasts a transaction to the Dash network via connected peers | client |

### Mempool Operations

Functions: 1

| Function | Description | Module |
|----------|-------------|--------|
| `dash_spv_ffi_mempool_progress_destroy` | Destroy an `FFIMempoolProgress` object | types |

### Platform Integration

Functions: 2
Expand Down Expand Up @@ -558,6 +567,24 @@ Broadcasts a transaction to the Dash network via connected peers. # Safety - `

---

### Mempool Operations - Detailed

#### `dash_spv_ffi_mempool_progress_destroy`

```c
dash_spv_ffi_mempool_progress_destroy(progress: *mut FFIMempoolProgress) -> ()
```

**Description:**
Destroy an `FFIMempoolProgress` object. # Safety - `progress` must be a pointer returned from this crate, or null.

**Safety:**
- `progress` must be a pointer returned from this crate, or null.

**Module:** `types`

---

### Platform Integration - Detailed

#### `ffi_dash_spv_get_platform_activation_height`
Expand Down
37 changes: 37 additions & 0 deletions dash-spv-ffi/include/dash_spv_ffi.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ typedef enum FFIManagerId {
Masternodes = 4,
ChainLocks = 5,
InstantSend = 6,
Mempool = 7,
} FFIManagerId;

typedef enum FFIMempoolStrategy {
Expand Down Expand Up @@ -144,6 +145,18 @@ typedef struct FFIInstantSendProgress {
uint64_t last_activity;
} FFIInstantSendProgress;

/**
* Progress for mempool transaction monitoring.
*/
typedef struct FFIMempoolProgress {
enum FFISyncState state;
uint32_t received;
uint32_t relevant;
uint32_t tracked;
uint32_t removed;
uint64_t last_activity;
} FFIMempoolProgress;

/**
* Aggregate progress for all sync managers.
* Provides a complete view of the parallel sync system's state.
Expand All @@ -162,6 +175,7 @@ typedef struct FFISyncProgress {
struct FFIMasternodesProgress *masternodes;
struct FFIChainLockProgress *chainlocks;
struct FFIInstantSendProgress *instantsend;
struct FFIMempoolProgress *mempool;
} FFISyncProgress;

/**
Expand Down Expand Up @@ -249,6 +263,8 @@ typedef void (*OnBlocksNeededCallback)(const struct FFIBlockNeeded *blocks,
typedef void (*OnBlockProcessedCallback)(uint32_t height,
const uint8_t (*hash)[32],
uint32_t new_address_count,
const uint8_t (*confirmed_txids)[32],
uint32_t confirmed_txid_count,
void *user_data);

/**
Expand Down Expand Up @@ -375,12 +391,24 @@ typedef struct FFINetworkEventCallbacks {
* copy any data they need to retain after the callback returns.
*/
typedef void (*OnTransactionReceivedCallback)(const char *wallet_id,
FFITransactionContext status,
uint32_t account_index,
const uint8_t (*txid)[32],
int64_t amount,
const char *addresses,
void *user_data);

/**
* Callback for WalletEvent::TransactionStatusChanged
*
* The `wallet_id` string pointer and `txid` hash pointer are borrowed and only
* valid for the duration of the callback.
*/
typedef void (*OnTransactionStatusChangedCallback)(const char *wallet_id,
const uint8_t (*txid)[32],
FFITransactionContext status,
void *user_data);

/**
* Callback for WalletEvent::BalanceUpdated
*
Expand All @@ -406,6 +434,7 @@ typedef void (*OnBalanceUpdatedCallback)(const char *wallet_id,
*/
typedef struct FFIWalletEventCallbacks {
OnTransactionReceivedCallback on_transaction_received;
OnTransactionStatusChangedCallback on_transaction_status_changed;
OnBalanceUpdatedCallback on_balance_updated;
void *user_data;
} FFIWalletEventCallbacks;
Expand Down Expand Up @@ -963,6 +992,14 @@ struct FFIResult ffi_dash_spv_get_platform_activation_height(struct FFIDashSpvCl
*/
void dash_spv_ffi_instantsend_progress_destroy(struct FFIInstantSendProgress *progress) ;

/**
* Destroy an `FFIMempoolProgress` object.
*
* # Safety
* - `progress` must be a pointer returned from this crate, or null.
*/
void dash_spv_ffi_mempool_progress_destroy(struct FFIMempoolProgress *progress) ;

/**
* Destroy an `FFISyncProgress` object and all its nested pointers.
*
Expand Down
25 changes: 22 additions & 3 deletions dash-spv-ffi/src/bin/ffi_cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use std::ptr;
use clap::{Arg, ArgAction, Command};

use dash_spv_ffi::*;
use key_wallet_ffi::types::FFITransactionContext;
use key_wallet_ffi::wallet_manager::wallet_manager_add_wallet_from_mnemonic;
use key_wallet_ffi::{FFIError, FFINetwork};

Expand All @@ -28,6 +29,7 @@ extern "C" fn on_sync_start(manager_id: FFIManagerId, _user_data: *mut c_void) {
FFIManagerId::Masternodes => "Masternodes",
FFIManagerId::ChainLocks => "ChainLocks",
FFIManagerId::InstantSend => "InstantSend",
FFIManagerId::Mempool => "Mempool",
};
println!("[Sync] Manager started: {}", manager_name);
}
Expand Down Expand Up @@ -75,9 +77,14 @@ extern "C" fn on_block_processed(
height: u32,
_hash: *const [u8; 32],
new_address_count: u32,
_confirmed_txids: *const [u8; 32],
confirmed_txid_count: u32,
_user_data: *mut c_void,
) {
println!("[Sync] Block processed: height={}, new_addresses={}", height, new_address_count);
println!(
"[Sync] Block processed: height={}, new_addresses={}, confirmed_txs={}",
height, new_address_count, confirmed_txid_count
);
}

extern "C" fn on_masternode_state_updated(height: u32, _user_data: *mut c_void) {
Expand Down Expand Up @@ -150,6 +157,7 @@ extern "C" fn on_peers_updated(connected_count: u32, best_height: u32, _user_dat

extern "C" fn on_transaction_received(
wallet_id: *const c_char,
status: FFITransactionContext,
account_index: u32,
txid: *const [u8; 32],
amount: i64,
Expand All @@ -165,11 +173,21 @@ extern "C" fn on_transaction_received(
};
let txid_hex = unsafe { hex::encode(*txid) };
println!(
"[Wallet] TX received: wallet={}..., txid={}, account={}, amount={} duffs, addresses={}",
wallet_short, txid_hex, account_index, amount, addr_str
"[Wallet] TX received: wallet={}..., txid={}, account={}, amount={} duffs, status={:?}, addresses={}",
wallet_short, txid_hex, account_index, amount, status, addr_str
);
}

extern "C" fn on_transaction_status_changed(
_wallet_id: *const c_char,
txid: *const [u8; 32],
status: FFITransactionContext,
_user_data: *mut c_void,
) {
let txid_hex = unsafe { hex::encode(*txid) };
println!("[Wallet] TX status changed: txid={}, status={:?}", txid_hex, status);
}

extern "C" fn on_balance_updated(
wallet_id: *const c_char,
spendable: u64,
Expand Down Expand Up @@ -431,6 +449,7 @@ fn main() {

let wallet_callbacks = FFIWalletEventCallbacks {
on_transaction_received: Some(on_transaction_received),
on_transaction_status_changed: Some(on_transaction_status_changed),
on_balance_updated: Some(on_balance_updated),
user_data: ptr::null_mut(),
};
Expand Down
46 changes: 46 additions & 0 deletions dash-spv-ffi/src/callbacks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

use crate::{dash_spv_ffi_sync_progress_destroy, FFISyncProgress};
use dashcore::hashes::Hash;
use key_wallet_ffi::types::FFITransactionContext;
use std::ffi::CString;
use std::os::raw::{c_char, c_void};

Expand All @@ -26,6 +27,7 @@ pub enum FFIManagerId {
Masternodes = 4,
ChainLocks = 5,
InstantSend = 6,
Mempool = 7,
}

impl From<dash_spv::sync::ManagerIdentifier> for FFIManagerId {
Expand All @@ -38,6 +40,7 @@ impl From<dash_spv::sync::ManagerIdentifier> for FFIManagerId {
dash_spv::sync::ManagerIdentifier::Masternode => FFIManagerId::Masternodes,
dash_spv::sync::ManagerIdentifier::ChainLock => FFIManagerId::ChainLocks,
dash_spv::sync::ManagerIdentifier::InstantSend => FFIManagerId::InstantSend,
dash_spv::sync::ManagerIdentifier::Mempool => FFIManagerId::Mempool,
}
}
}
Expand Down Expand Up @@ -161,6 +164,8 @@ pub type OnBlockProcessedCallback = Option<
height: u32,
hash: *const [u8; 32],
new_address_count: u32,
confirmed_txids: *const [u8; 32],
confirmed_txid_count: u32,
user_data: *mut c_void,
),
>;
Expand Down Expand Up @@ -349,13 +354,18 @@ impl FFISyncEventCallbacks {
block_hash,
height,
new_addresses,
confirmed_txids,
} => {
if let Some(cb) = self.on_block_processed {
let hash_bytes = block_hash.as_byte_array();
let txid_bytes: Vec<[u8; 32]> =
confirmed_txids.iter().map(|txid| *txid.as_byte_array()).collect();
cb(
*height,
hash_bytes as *const [u8; 32],
new_addresses.len() as u32,
txid_bytes.as_ptr(),
txid_bytes.len() as u32,
self.user_data,
);
}
Expand Down Expand Up @@ -416,6 +426,7 @@ impl FFISyncEventCallbacks {
cb(*header_tip, *cycle, self.user_data);
}
}
SyncEvent::WalletAddressesChanged => {}
}
}
}
Expand Down Expand Up @@ -522,6 +533,7 @@ impl FFINetworkEventCallbacks {
pub type OnTransactionReceivedCallback = Option<
extern "C" fn(
wallet_id: *const c_char,
status: FFITransactionContext,
account_index: u32,
txid: *const [u8; 32],
amount: i64,
Expand All @@ -530,6 +542,19 @@ pub type OnTransactionReceivedCallback = Option<
),
>;

/// Callback for WalletEvent::TransactionStatusChanged
///
/// The `wallet_id` string pointer and `txid` hash pointer are borrowed and only
/// valid for the duration of the callback.
pub type OnTransactionStatusChangedCallback = Option<
extern "C" fn(
wallet_id: *const c_char,
txid: *const [u8; 32],
status: FFITransactionContext,
user_data: *mut c_void,
),
>;

/// Callback for WalletEvent::BalanceUpdated
///
/// The `wallet_id` string pointer is borrowed and only valid for the duration
Expand Down Expand Up @@ -557,6 +582,7 @@ pub type OnBalanceUpdatedCallback = Option<
#[derive(Clone)]
pub struct FFIWalletEventCallbacks {
pub on_transaction_received: OnTransactionReceivedCallback,
pub on_transaction_status_changed: OnTransactionStatusChangedCallback,
pub on_balance_updated: OnBalanceUpdatedCallback,
pub user_data: *mut c_void,
}
Expand All @@ -569,6 +595,7 @@ impl Default for FFIWalletEventCallbacks {
fn default() -> Self {
Self {
on_transaction_received: None,
on_transaction_status_changed: None,
on_balance_updated: None,
user_data: std::ptr::null_mut(),
}
Expand Down Expand Up @@ -625,6 +652,7 @@ impl FFIWalletEventCallbacks {
match event {
WalletEvent::TransactionReceived {
wallet_id,
status,
account_index,
txid,
amount,
Expand All @@ -639,6 +667,7 @@ impl FFIWalletEventCallbacks {
let c_addresses = CString::new(addresses_str.join(",")).unwrap_or_default();
cb(
c_wallet_id.as_ptr(),
FFITransactionContext::from(*status),
*account_index,
txid_bytes as *const [u8; 32],
*amount,
Expand All @@ -647,6 +676,23 @@ impl FFIWalletEventCallbacks {
);
}
}
WalletEvent::TransactionStatusChanged {
wallet_id,
txid,
status,
} => {
if let Some(cb) = self.on_transaction_status_changed {
let wallet_id_hex = hex::encode(wallet_id);
let c_wallet_id = CString::new(wallet_id_hex).unwrap_or_default();
let txid_bytes = txid.as_byte_array();
cb(
c_wallet_id.as_ptr(),
txid_bytes as *const [u8; 32],
FFITransactionContext::from(*status),
self.user_data,
);
}
}
WalletEvent::BalanceUpdated {
wallet_id,
spendable,
Expand Down
Loading
Loading