mirror of
https://github.com/logos-blockchain/logos-execution-zone.git
synced 2026-07-11 00:09:39 +00:00
317 lines
8.3 KiB
Rust
317 lines
8.3 KiB
Rust
use std::{
|
|
ffi::{c_char, CString},
|
|
str::FromStr as _,
|
|
};
|
|
|
|
use crate::{
|
|
c_str_to_string,
|
|
error::{print_error, WalletFfiError},
|
|
wallet::get_wallet,
|
|
FfiAccountIdWithPrivacy, WalletHandle,
|
|
};
|
|
|
|
#[repr(C)]
|
|
pub struct LabelAvailability {
|
|
pub is_available: bool,
|
|
pub error: WalletFfiError,
|
|
}
|
|
|
|
impl LabelAvailability {
|
|
#[must_use]
|
|
pub const fn availability(is_available: bool) -> Self {
|
|
Self {
|
|
is_available,
|
|
error: WalletFfiError::Success,
|
|
}
|
|
}
|
|
|
|
#[must_use]
|
|
pub const fn error(error: WalletFfiError) -> Self {
|
|
Self {
|
|
is_available: false,
|
|
error,
|
|
}
|
|
}
|
|
}
|
|
|
|
#[repr(C)]
|
|
#[derive(Debug, Clone, Copy)]
|
|
pub struct AccountIdResolvedFromLabel {
|
|
pub account_id: FfiAccountIdWithPrivacy,
|
|
pub error: WalletFfiError,
|
|
}
|
|
|
|
impl AccountIdResolvedFromLabel {
|
|
#[must_use]
|
|
pub const fn account_id(account_id: FfiAccountIdWithPrivacy) -> Self {
|
|
Self {
|
|
account_id,
|
|
error: WalletFfiError::Success,
|
|
}
|
|
}
|
|
|
|
#[must_use]
|
|
pub fn error(error: WalletFfiError) -> Self {
|
|
Self {
|
|
account_id: FfiAccountIdWithPrivacy::default(),
|
|
error,
|
|
}
|
|
}
|
|
}
|
|
|
|
#[repr(C)]
|
|
pub struct LabelList {
|
|
pub labels_data: *mut *const c_char,
|
|
pub labels_size: usize,
|
|
pub error: WalletFfiError,
|
|
}
|
|
|
|
impl LabelList {
|
|
#[must_use]
|
|
pub fn from_labels(labels: Vec<*const c_char>) -> Self {
|
|
let labels_size = labels.len();
|
|
let boxed_slice = labels.into_boxed_slice();
|
|
let labels_data = Box::into_raw(boxed_slice).cast::<*const c_char>();
|
|
|
|
Self {
|
|
labels_data,
|
|
labels_size,
|
|
error: WalletFfiError::Success,
|
|
}
|
|
}
|
|
|
|
#[must_use]
|
|
pub const fn error(error: WalletFfiError) -> Self {
|
|
Self {
|
|
labels_data: std::ptr::null_mut(),
|
|
labels_size: 0,
|
|
error,
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Check if label is available.
|
|
///
|
|
/// # Parameters
|
|
/// - `handle`: Valid wallet handle
|
|
/// - `label`: Input null terminated C string for a label
|
|
///
|
|
/// # Returns
|
|
/// - `LabelAvailability` struct
|
|
///
|
|
/// # Safety
|
|
/// - `handle` must be a valid wallet handle from `wallet_ffi_create_new` or `wallet_ffi_open`
|
|
/// - `label` must be a valid pointer to a null-terminated C string
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn wallet_ffi_check_label_available(
|
|
handle: *mut WalletHandle,
|
|
label: *const c_char,
|
|
) -> LabelAvailability {
|
|
let wrapper = match get_wallet(handle) {
|
|
Ok(w) => w,
|
|
Err(e) => return LabelAvailability::error(e),
|
|
};
|
|
|
|
let label = match c_str_to_string(label, "label") {
|
|
Ok(value) => value,
|
|
Err(e) => return LabelAvailability::error(e),
|
|
};
|
|
|
|
let wallet = match wrapper.core.lock() {
|
|
Ok(w) => w,
|
|
Err(e) => {
|
|
print_error(format!("Failed to lock wallet: {e}"));
|
|
return LabelAvailability::error(WalletFfiError::InternalError);
|
|
}
|
|
};
|
|
|
|
let is_available = wallet
|
|
.storage()
|
|
.check_label_availability(&label.into())
|
|
.is_ok();
|
|
|
|
LabelAvailability::availability(is_available)
|
|
}
|
|
|
|
/// Add new label.
|
|
///
|
|
/// # Parameters
|
|
/// - `handle`: Valid wallet handle
|
|
/// - `label`: Input null terminated C string for a label
|
|
/// - `account_id_with_privacy`: The account ID (32 bytes) and its privacy.
|
|
///
|
|
/// # Returns
|
|
/// - `Success` on successful query
|
|
/// - Error code on failure
|
|
///
|
|
/// # Safety
|
|
/// - `handle` must be a valid wallet handle from `wallet_ffi_create_new` or `wallet_ffi_open`
|
|
/// - `label` must be a valid pointer to a null-terminated C string
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn wallet_ffi_add_label(
|
|
handle: *mut WalletHandle,
|
|
label: *const c_char,
|
|
account_id_with_privacy: FfiAccountIdWithPrivacy,
|
|
) -> WalletFfiError {
|
|
let wrapper = match get_wallet(handle) {
|
|
Ok(w) => w,
|
|
Err(e) => return e,
|
|
};
|
|
|
|
let label = match c_str_to_string(label, "label") {
|
|
Ok(value) => value,
|
|
Err(e) => return e,
|
|
};
|
|
|
|
let mut wallet = match wrapper.core.lock() {
|
|
Ok(w) => w,
|
|
Err(e) => {
|
|
print_error(format!("Failed to lock wallet: {e}"));
|
|
return WalletFfiError::InternalError;
|
|
}
|
|
};
|
|
|
|
match wallet
|
|
.storage_mut()
|
|
.add_label(label.into(), account_id_with_privacy.into())
|
|
{
|
|
Ok(()) => WalletFfiError::Success,
|
|
Err(err) => {
|
|
print_error(format!("Failed to add label : {err}"));
|
|
WalletFfiError::InternalError
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Resolve a label.
|
|
///
|
|
/// # Parameters
|
|
/// - `handle`: Valid wallet handle
|
|
/// - `label`: Input null terminated C string for a label
|
|
///
|
|
/// # Returns
|
|
/// - `AccountIdResolvedFromLabel` struct
|
|
///
|
|
/// # Safety
|
|
/// - `handle` must be a valid wallet handle from `wallet_ffi_create_new` or `wallet_ffi_open`
|
|
/// - `label` must be a valid pointer to a null-terminated C string
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn wallet_ffi_resolve_label(
|
|
handle: *mut WalletHandle,
|
|
label: *const c_char,
|
|
) -> AccountIdResolvedFromLabel {
|
|
let wrapper = match get_wallet(handle) {
|
|
Ok(w) => w,
|
|
Err(e) => return AccountIdResolvedFromLabel::error(e),
|
|
};
|
|
|
|
let label = match c_str_to_string(label, "label") {
|
|
Ok(value) => value,
|
|
Err(e) => return AccountIdResolvedFromLabel::error(e),
|
|
};
|
|
|
|
let mut wallet = match wrapper.core.lock() {
|
|
Ok(w) => w,
|
|
Err(e) => {
|
|
print_error(format!("Failed to lock wallet: {e}"));
|
|
return AccountIdResolvedFromLabel::error(WalletFfiError::InternalError);
|
|
}
|
|
};
|
|
|
|
wallet
|
|
.storage_mut()
|
|
.resolve_label(&label.into())
|
|
.map_or_else(
|
|
|| {
|
|
print_error("Failed to resolve label");
|
|
AccountIdResolvedFromLabel::error(WalletFfiError::InternalError)
|
|
},
|
|
|acc_id| AccountIdResolvedFromLabel::account_id(acc_id.into()),
|
|
)
|
|
}
|
|
|
|
/// Get all labels for account.
|
|
///
|
|
/// # Parameters
|
|
/// - `handle`: Valid wallet handle
|
|
/// - `account_id_with_privacy`: The account ID (32 bytes) and its privacy.
|
|
///
|
|
/// # Returns
|
|
/// - `LabelList` struct
|
|
///
|
|
/// # Safety
|
|
/// - `handle` must be a valid wallet handle from `wallet_ffi_create_new` or `wallet_ffi_open`
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn wallet_ffi_get_all_labels_for_account(
|
|
handle: *mut WalletHandle,
|
|
account_id_with_privacy: FfiAccountIdWithPrivacy,
|
|
) -> LabelList {
|
|
let wrapper = match get_wallet(handle) {
|
|
Ok(w) => w,
|
|
Err(e) => return LabelList::error(e),
|
|
};
|
|
|
|
let wallet = match wrapper.core.lock() {
|
|
Ok(w) => w,
|
|
Err(e) => {
|
|
print_error(format!("Failed to lock wallet: {e}"));
|
|
return LabelList::error(WalletFfiError::InternalError);
|
|
}
|
|
};
|
|
|
|
let mut labels = vec![];
|
|
|
|
for label in wallet
|
|
.storage()
|
|
.labels_for_account(account_id_with_privacy.into())
|
|
{
|
|
let Ok(label_c) = CString::from_str(label.as_ref()) else {
|
|
print_error(format!("Failed to cast label into C string: {label}"));
|
|
return LabelList::error(WalletFfiError::InternalError);
|
|
};
|
|
|
|
let label_raw = label_c.into_raw().cast_const();
|
|
|
|
labels.push(label_raw);
|
|
}
|
|
|
|
LabelList::from_labels(labels)
|
|
}
|
|
|
|
/// Free label list.
|
|
///
|
|
/// # Parameters
|
|
/// - `label_list`: Input list of labels
|
|
///
|
|
/// # Returns
|
|
/// - `Success` on successful query
|
|
/// - Error code on failure
|
|
///
|
|
/// # Safety
|
|
/// - `label_list` must be a valid pointer to `LabelList`, received from
|
|
/// `wallet_ffi_get_all_labels_for_account`
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn wallet_ffi_free_label_list(label_list: *mut LabelList) -> WalletFfiError {
|
|
if label_list.is_null() {
|
|
return WalletFfiError::NullPointer;
|
|
}
|
|
|
|
let labels_raw = unsafe { &*label_list };
|
|
|
|
if !labels_raw.labels_data.is_null() && labels_raw.labels_size > 0 {
|
|
let labels_slice =
|
|
std::slice::from_raw_parts_mut(labels_raw.labels_data, labels_raw.labels_size);
|
|
|
|
for label_ptr in labels_slice.iter() {
|
|
if !(*label_ptr).is_null() {
|
|
drop(CString::from_raw((*label_ptr).cast_mut()));
|
|
}
|
|
}
|
|
|
|
let boxed_slice = Box::from_raw(std::ptr::from_mut::<[*const c_char]>(labels_slice));
|
|
drop(boxed_slice);
|
|
}
|
|
|
|
WalletFfiError::Success
|
|
}
|