Skip to content

Commit

Permalink
c-ffi bindings: get nums as strings
Browse files Browse the repository at this point in the history
  • Loading branch information
zoedberg committed Oct 22, 2024
1 parent 4b4434e commit 0fbdfdf
Show file tree
Hide file tree
Showing 6 changed files with 165 additions and 44 deletions.
22 changes: 11 additions & 11 deletions bindings/c-ffi/example.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ int main() {
char wallet_data[300];
sprintf(wallet_data,
"{ \"data_dir\": \"./data\", \"bitcoin_network\": \"Regtest\", "
"\"database_type\": \"Sqlite\", \"max_allocations_per_utxo\": 1, "
"\"pubkey\": \"%s\", \"mnemonic\": \"%s\", \"vanilla_keychain\": "
"null }",
"\"database_type\": \"Sqlite\", \"max_allocations_per_utxo\": "
"\"1\", \"pubkey\": \"%s\", \"mnemonic\": \"%s\", "
"\"vanilla_keychain\": null }",
account_xpub, mnemonic);

printf("Creating wallet...\n");
Expand Down Expand Up @@ -82,25 +82,25 @@ int main() {
printf("BTC balance after sync: %s\n", btc_balance_2);

CResultString created_res =
rgblib_create_utxos(wlt, online, false, "25", NULL, 1.5, false);
rgblib_create_utxos(wlt, online, false, "25", NULL, "1.5", false);
if (created_res.result == Err) {
printf("ERR: %s\n", created_res.inner);
return EXIT_FAILURE;
}
const char *created = created_res.inner;
printf("Created %s UTXOs\n", created);

CResultString asset_nia_res =
rgblib_issue_asset_nia(wlt, online, "USDT", "Tether", 2, "[777, 66]");
CResultString asset_nia_res = rgblib_issue_asset_nia(
wlt, online, "USDT", "Tether", "2", "[\"777\", \"66\"]");
if (asset_nia_res.result == Ok) {
printf("Issued a NIA asset: %s\n", asset_nia_res.inner);
} else {
printf("ERR: %s\n", asset_nia_res.inner);
return EXIT_FAILURE;
}

CResultString asset_cfa_res =
rgblib_issue_asset_cfa(wlt, online, "Cfa", "desc", 2, "[777]", NULL);
CResultString asset_cfa_res = rgblib_issue_asset_cfa(
wlt, online, "Cfa", "desc", "2", "[\"777\"]", NULL);
if (asset_cfa_res.result == Ok) {
printf("Issued a CFA asset: %s\n", asset_cfa_res.inner);
} else {
Expand All @@ -109,7 +109,7 @@ int main() {
}

CResultString asset_uda_res = rgblib_issue_asset_uda(
wlt, online, "TKN", "Token", NULL, 2, "README.md", "[]");
wlt, online, "TKN", "Token", NULL, "2", "README.md", "[]");
if (asset_uda_res.result == Ok) {
printf("Issued a UDA asset: %s\n", asset_uda_res.inner);
} else {
Expand Down Expand Up @@ -139,7 +139,7 @@ int main() {

const char *transport_endpoints = "[\"rpc://127.0.0.1:3000/json-rpc\"]";
CResultString receive_data_res =
rgblib_blind_receive(wlt, NULL, NULL, NULL, transport_endpoints, 1);
rgblib_blind_receive(wlt, NULL, NULL, NULL, transport_endpoints, "1");
if (receive_data_res.result == Ok) {
printf("Receive data: %s\n", receive_data_res.inner);
} else {
Expand All @@ -155,7 +155,7 @@ int main() {
return EXIT_FAILURE;
}

CResultString fee_res = rgblib_get_fee_estimation(wlt, online, 7);
CResultString fee_res = rgblib_get_fee_estimation(wlt, online, "7");
printf("Fee estimation: %s\n", fee_res.inner);

return EXIT_SUCCESS;
Expand Down
24 changes: 12 additions & 12 deletions bindings/c-ffi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use crate::utils::*;
use std::{
any::TypeId,
collections::{hash_map::DefaultHasher, HashMap},
ffi::{c_char, c_float, c_uchar, c_ushort, c_void, CStr, CString},
ffi::{c_char, c_void, CStr, CString},
hash::{Hash, Hasher},
ptr::null_mut,
str::FromStr,
Expand Down Expand Up @@ -61,7 +61,7 @@ pub extern "C" fn rgblib_blind_receive(
amount_opt: *const c_char,
duration_seconds_opt: *const c_char,
transport_endpoints: *const c_char,
min_confirmations: c_uchar,
min_confirmations: *const c_char,
) -> CResultString {
blind_receive(
wallet,
Expand All @@ -81,7 +81,7 @@ pub extern "C" fn rgblib_create_utxos(
up_to: bool,
num_opt: *const c_char,
size_opt: *const c_char,
fee_rate: c_float,
fee_rate: *const c_char,
skip_sync: bool,
) -> CResultString {
create_utxos(
Expand Down Expand Up @@ -121,7 +121,7 @@ pub extern "C" fn rgblib_get_btc_balance(
pub extern "C" fn rgblib_get_fee_estimation(
wallet: &COpaqueStruct,
online: &COpaqueStruct,
blocks: c_ushort,
blocks: *const c_char,
) -> CResultString {
get_fee_estimation(wallet, online, blocks).into()
}
Expand All @@ -141,7 +141,7 @@ pub extern "C" fn rgblib_issue_asset_cfa(
online: &COpaqueStruct,
name: *const c_char,
details_opt: *const c_char,
precision: c_uchar,
precision: *const c_char,
amounts: *const c_char,
file_path_opt: *const c_char,
) -> CResultString {
Expand All @@ -163,7 +163,7 @@ pub extern "C" fn rgblib_issue_asset_nia(
online: &COpaqueStruct,
ticker: *const c_char,
name: *const c_char,
precision: c_uchar,
precision: *const c_char,
amounts: *const c_char,
) -> CResultString {
issue_asset_nia(wallet, online, ticker, name, precision, amounts).into()
Expand All @@ -176,7 +176,7 @@ pub extern "C" fn rgblib_issue_asset_uda(
ticker: *const c_char,
name: *const c_char,
details_opt: *const c_char,
precision: c_uchar,
precision: *const c_char,
media_file_path_opt: *const c_char,
attachments_file_paths: *const c_char,
) -> CResultString {
Expand Down Expand Up @@ -258,8 +258,8 @@ pub extern "C" fn rgblib_send(
online: &COpaqueStruct,
recipient_map: *const c_char,
donation: bool,
fee_rate: c_float,
min_confirmations: c_uchar,
fee_rate: *const c_char,
min_confirmations: *const c_char,
skip_sync: bool,
) -> CResultString {
send(
Expand All @@ -279,8 +279,8 @@ pub extern "C" fn rgblib_send_btc(
wallet: &COpaqueStruct,
online: &COpaqueStruct,
address: *const c_char,
amount: u64,
fee_rate: c_float,
amount: *const c_char,
fee_rate: *const c_char,
skip_sync: bool,
) -> CResultString {
send_btc(wallet, online, address, amount, fee_rate, skip_sync).into()
Expand All @@ -298,7 +298,7 @@ pub extern "C" fn rgblib_witness_receive(
amount_opt: *const c_char,
duration_seconds_opt: *const c_char,
transport_endpoints: *const c_char,
min_confirmations: c_uchar,
min_confirmations: *const c_char,
) -> CResultString {
witness_receive(
wallet,
Expand Down
67 changes: 48 additions & 19 deletions bindings/c-ffi/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ pub(crate) enum Error {
#[error("Error converting JSON: {0}")]
JSONConversion(#[from] serde_json::Error),

#[error("Error converting string into number")]
StringToNumberConversion,

#[error("Error from rgb-lib: {0}")]
RgbLib(#[from] RgbLibError),

Expand Down Expand Up @@ -103,6 +106,15 @@ where
}
}

fn convert_strings_array<T: FromStr>(ptr: *const c_char) -> Result<Vec<T>, Error> {
let str_array: Vec<String> = serde_json::from_str(&ptr_to_string(ptr))?;
str_array
.iter()
.map(|a| a.parse())
.collect::<Result<Vec<T>, _>>()
.map_err(|_| Error::StringToNumberConversion)
}

fn convert_optional_number<T: serde::de::DeserializeOwned>(
ptr: *const c_char,
) -> Result<Option<T>, Error> {
Expand Down Expand Up @@ -132,6 +144,12 @@ fn convert_optional_string(ptr: *const c_char) -> Option<String> {
}
}

fn ptr_to_num<T: FromStr>(ptr: *const c_char) -> Result<T, Error> {
ptr_to_string(ptr)
.parse()
.map_err(|_| Error::StringToNumberConversion)
}

fn ptr_to_string(ptr: *const c_char) -> String {
unsafe { CStr::from_ptr(ptr).to_string_lossy().into_owned() }
}
Expand All @@ -154,14 +172,15 @@ pub(crate) fn blind_receive(
amount_opt: *const c_char,
duration_seconds_opt: *const c_char,
transport_endpoints: *const c_char,
min_confirmations: c_uchar,
min_confirmations: *const c_char,
) -> Result<String, Error> {
let wallet = Wallet::from_opaque(wallet)?;
let transport_endpoints: Vec<String> =
serde_json::from_str(&ptr_to_string(transport_endpoints))?;
let asset_id = convert_optional_string(asset_id_opt);
let amount: Option<u64> = convert_optional_number(amount_opt)?;
let duration_seconds: Option<u32> = convert_optional_number(duration_seconds_opt)?;
let amount = convert_optional_number(amount_opt)?;
let duration_seconds = convert_optional_number(duration_seconds_opt)?;
let min_confirmations = ptr_to_num(min_confirmations)?;
let res = wallet.blind_receive(
asset_id,
amount,
Expand All @@ -178,13 +197,14 @@ pub(crate) fn create_utxos(
up_to: bool,
num_opt: *const c_char,
size_opt: *const c_char,
fee_rate: c_float,
fee_rate: *const c_char,
skip_sync: bool,
) -> Result<String, Error> {
let wallet = Wallet::from_opaque(wallet)?;
let online = Online::from_opaque(online)?;
let num: Option<u8> = convert_optional_number(num_opt)?;
let size: Option<u32> = convert_optional_number(size_opt)?;
let num = convert_optional_number(num_opt)?;
let size = convert_optional_number(size_opt)?;
let fee_rate = ptr_to_num(fee_rate)?;
let res = wallet.create_utxos((*online).clone(), up_to, num, size, fee_rate, skip_sync)?;
Ok(serde_json::to_string(&res)?)
}
Expand Down Expand Up @@ -224,10 +244,11 @@ pub(crate) fn get_btc_balance(
pub(crate) fn get_fee_estimation(
wallet: &COpaqueStruct,
online: &COpaqueStruct,
blocks: c_ushort,
blocks: *const c_char,
) -> Result<String, Error> {
let wallet = Wallet::from_opaque(wallet)?;
let online = Online::from_opaque(online)?;
let blocks = ptr_to_num(blocks)?;
let res = wallet.get_fee_estimation((*online).clone(), blocks)?;
Ok(serde_json::to_string(&res)?)
}
Expand All @@ -246,13 +267,14 @@ pub(crate) fn issue_asset_cfa(
online: &COpaqueStruct,
name: *const c_char,
details_opt: *const c_char,
precision: c_uchar,
precision: *const c_char,
amounts: *const c_char,
file_path_opt: *const c_char,
) -> Result<String, Error> {
let wallet = Wallet::from_opaque(wallet)?;
let online = Online::from_opaque(online)?;
let amounts: Vec<u64> = serde_json::from_str(&ptr_to_string(amounts))?;
let precision = ptr_to_num(precision)?;
let amounts = convert_strings_array(amounts)?;
let details = convert_optional_string(details_opt);
let file_path = convert_optional_string(file_path_opt);
let res = wallet.issue_asset_cfa(
Expand All @@ -271,12 +293,13 @@ pub(crate) fn issue_asset_nia(
online: &COpaqueStruct,
ticker: *const c_char,
name: *const c_char,
precision: c_uchar,
precision: *const c_char,
amounts: *const c_char,
) -> Result<String, Error> {
let wallet = Wallet::from_opaque(wallet)?;
let online = Online::from_opaque(online)?;
let amounts: Vec<u64> = serde_json::from_str(&ptr_to_string(amounts))?;
let precision = ptr_to_num(precision)?;
let amounts = convert_strings_array(amounts)?;
let res = wallet.issue_asset_nia(
(*online).clone(),
ptr_to_string(ticker),
Expand All @@ -294,13 +317,14 @@ pub(crate) fn issue_asset_uda(
ticker: *const c_char,
name: *const c_char,
details_opt: *const c_char,
precision: c_uchar,
precision: *const c_char,
media_file_path_opt: *const c_char,
attachments_file_paths: *const c_char,
) -> Result<String, Error> {
let wallet = Wallet::from_opaque(wallet)?;
let online = Online::from_opaque(online)?;
let details = convert_optional_string(details_opt);
let precision = ptr_to_num(precision)?;
let media_file_path = convert_optional_string(media_file_path_opt);
let attachments_file_paths: Vec<String> =
serde_json::from_str(&ptr_to_string(attachments_file_paths))?;
Expand Down Expand Up @@ -395,14 +419,16 @@ pub(crate) fn send(
online: &COpaqueStruct,
recipient_map: *const c_char,
donation: bool,
fee_rate: c_float,
min_confirmations: c_uchar,
fee_rate: *const c_char,
min_confirmations: *const c_char,
skip_sync: bool,
) -> Result<String, Error> {
let wallet = Wallet::from_opaque(wallet)?;
let online = Online::from_opaque(online)?;
let recipient_map: HashMap<String, Vec<Recipient>> =
serde_json::from_str(&ptr_to_string(recipient_map))?;
let fee_rate = ptr_to_num(fee_rate)?;
let min_confirmations = ptr_to_num(min_confirmations)?;
let res = wallet.send(
(*online).clone(),
recipient_map,
Expand All @@ -418,13 +444,15 @@ pub(crate) fn send_btc(
wallet: &COpaqueStruct,
online: &COpaqueStruct,
address: *const c_char,
amount: u64,
fee_rate: c_float,
amount: *const c_char,
fee_rate: *const c_char,
skip_sync: bool,
) -> Result<String, Error> {
let wallet = Wallet::from_opaque(wallet)?;
let online = Online::from_opaque(online)?;
let address = ptr_to_string(address);
let amount = ptr_to_num(amount)?;
let fee_rate = ptr_to_num(fee_rate)?;
let res = wallet.send_btc((*online).clone(), address, amount, fee_rate, skip_sync)?;
Ok(res)
}
Expand All @@ -442,14 +470,15 @@ pub(crate) fn witness_receive(
amount_opt: *const c_char,
duration_seconds_opt: *const c_char,
transport_endpoints: *const c_char,
min_confirmations: c_uchar,
min_confirmations: *const c_char,
) -> Result<String, Error> {
let wallet = Wallet::from_opaque(wallet)?;
let transport_endpoints: Vec<String> =
serde_json::from_str(&ptr_to_string(transport_endpoints))?;
let asset_id = convert_optional_string(asset_id_opt);
let amount: Option<u64> = convert_optional_number(amount_opt)?;
let duration_seconds: Option<u32> = convert_optional_number(duration_seconds_opt)?;
let amount = convert_optional_number(amount_opt)?;
let duration_seconds = convert_optional_number(duration_seconds_opt)?;
let min_confirmations = ptr_to_num(min_confirmations)?;
let res = wallet.witness_receive(
asset_id,
amount,
Expand Down
6 changes: 4 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,8 @@ use sea_orm::{
EntityTrait, EnumIter, IntoActiveValue, QueryFilter, QueryOrder, TryIntoModel,
};
use seals::SecretSeal;
use serde::{Deserialize, Serialize};
use serde::de::{self, Unexpected, Visitor};
use serde::{Deserialize, Deserializer, Serialize};
use slog::{debug, error, info, o, warn, Drain, Logger};
use slog_async::AsyncGuard;
use slog_term::{FullFormat, PlainDecorator};
Expand Down Expand Up @@ -286,7 +287,8 @@ use crate::{
error::InternalError,
utils::{
adjust_canonicalization, beneficiary_from_script_buf, calculate_descriptor_from_xprv,
calculate_descriptor_from_xpub, derive_account_xprv_from_mnemonic, get_xpub_from_xprv,
calculate_descriptor_from_xpub, derive_account_xprv_from_mnemonic,
from_str_or_number_mandatory, from_str_or_number_optional, get_xpub_from_xprv,
load_rgb_runtime, now, setup_logger, RgbInExt, RgbOutExt, RgbPsbtExt, RgbRuntime, LOG_FILE,
},
wallet::{Balance, Outpoint, NUM_KNOWN_SCHEMAS, SCHEMA_ID_CFA, SCHEMA_ID_NIA, SCHEMA_ID_UDA},
Expand Down
Loading

0 comments on commit 0fbdfdf

Please sign in to comment.