|
1 | 1 | #[cfg(feature = "uniffi")] |
2 | 2 | uniffi::setup_scaffolding!(); |
3 | 3 |
|
4 | | -pub use rust_cktap::{ |
5 | | - rand_chaincode, rand_nonce as core_rand_nonce, CkTapCard, Error, SatsCard, TapSigner, |
6 | | -}; |
| 4 | +use rust_cktap::apdu::{AppletSelect, CommandApdu, ResponseApdu, StatusResponse}; |
| 5 | +use rust_cktap::{rand_nonce as core_rand_nonce, Error as CoreError}; |
| 6 | +use std::fmt::Debug; |
7 | 7 |
|
| 8 | +#[cfg(feature = "uniffi")] |
| 9 | +#[derive(Debug, thiserror::Error, uniffi::Error)] |
| 10 | +pub enum Error { |
| 11 | + #[error("Core Error: {msg}")] |
| 12 | + Core { msg: String }, |
| 13 | + #[error("Transport Error: {msg}")] |
| 14 | + Transport { msg: String }, |
| 15 | +} |
| 16 | + |
| 17 | +#[cfg(feature = "uniffi")] |
| 18 | +impl From<CoreError> for Error { |
| 19 | + fn from(e: CoreError) -> Self { |
| 20 | + Error::Core { msg: e.to_string() } |
| 21 | + } |
| 22 | +} |
| 23 | + |
| 24 | +#[cfg(feature = "uniffi")] |
| 25 | +#[derive(uniffi::Record)] |
| 26 | +pub struct FfiStatusResponse { |
| 27 | + pub proto: u64, |
| 28 | + pub ver: String, |
| 29 | + pub birth: u64, |
| 30 | + // Flatten Option<(u8, u8)> to slot_0 and slot_1 |
| 31 | + pub slot_0: Option<u8>, |
| 32 | + pub slot_1: Option<u8>, |
| 33 | + pub addr: Option<String>, |
| 34 | + pub tapsigner: Option<bool>, |
| 35 | + pub satschip: Option<bool>, |
| 36 | + pub path: Option<Vec<u64>>, |
| 37 | + pub num_backups: Option<u64>, |
| 38 | + pub pubkey: Vec<u8>, |
| 39 | + pub card_nonce: Vec<u8>, // Use Vec<u8> for [u8; 16] |
| 40 | + pub testnet: Option<bool>, |
| 41 | + pub auth_delay: Option<u64>, |
| 42 | +} |
| 43 | + |
| 44 | +#[cfg(feature = "uniffi")] |
| 45 | +impl From<StatusResponse> for FfiStatusResponse { |
| 46 | + fn from(sr: StatusResponse) -> Self { |
| 47 | + Self { |
| 48 | + proto: sr.proto as u64, |
| 49 | + ver: sr.ver, |
| 50 | + birth: sr.birth as u64, |
| 51 | + slot_0: sr.slots.map(|s| s.0), |
| 52 | + slot_1: sr.slots.map(|s| s.1), |
| 53 | + addr: sr.addr, |
| 54 | + tapsigner: sr.tapsigner, |
| 55 | + satschip: sr.satschip, |
| 56 | + path: sr.path.map(|p| p.into_iter().map(|u| u as u64).collect()), |
| 57 | + num_backups: sr.num_backups.map(|n| n as u64), |
| 58 | + pubkey: sr.pubkey, |
| 59 | + card_nonce: sr.card_nonce.to_vec(), |
| 60 | + testnet: sr.testnet, |
| 61 | + auth_delay: sr.auth_delay.map(|d| d as u64), |
| 62 | + } |
| 63 | + } |
| 64 | +} |
| 65 | + |
| 66 | +#[cfg(feature = "uniffi")] |
| 67 | +#[uniffi::export(callback_interface)] |
| 68 | +pub trait CkTransportFfi: Send + Sync + Debug + 'static { |
| 69 | + fn transmit_apdu(&self, command_apdu: Vec<u8>) -> Result<Vec<u8>, Error>; |
| 70 | +} |
| 71 | + |
| 72 | +#[cfg(feature = "uniffi")] |
| 73 | +#[uniffi::export] |
| 74 | +pub async fn get_status(transport: Box<dyn CkTransportFfi>) -> Result<FfiStatusResponse, Error> { |
| 75 | + let cmd = AppletSelect::default(); |
| 76 | + let command_apdu = cmd.apdu_bytes(); |
| 77 | + let rapdu = transport |
| 78 | + .transmit_apdu(command_apdu) |
| 79 | + .map_err(|e| Error::Transport { msg: e.to_string() })?; |
| 80 | + let response = StatusResponse::from_cbor(rapdu)?; |
| 81 | + Ok(response.into()) |
| 82 | +} |
| 83 | + |
| 84 | +#[cfg(feature = "uniffi")] |
| 85 | +#[derive(uniffi::Record)] |
| 86 | +pub struct TestRecord { |
| 87 | + pub message: String, |
| 88 | + pub count: u32, |
| 89 | +} |
| 90 | + |
| 91 | +// this is actually a class per Object not Record |
8 | 92 | #[cfg(feature = "uniffi")] |
9 | 93 | #[derive(uniffi::Object)] |
10 | 94 | pub struct TestStruct { |
|
0 commit comments