Skip to content

Commit 6513693

Browse files
committed
feat: satscard status
1 parent f23819a commit 6513693

2 files changed

Lines changed: 88 additions & 3 deletions

File tree

cktap-ffi/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ crate-type = ["staticlib", "cdylib"]
1111
[dependencies]
1212
rust-cktap = { path = "../lib" }
1313
uniffi = { version = "0.29", features = ["cli"], optional = true }
14+
thiserror = "1.0"
1415

1516
[build-dependencies]
1617
uniffi = { version = "0.29", features = ["build"], optional = true }

cktap-ffi/src/lib.rs

Lines changed: 87 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,94 @@
11
#[cfg(feature = "uniffi")]
22
uniffi::setup_scaffolding!();
33

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;
77

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
892
#[cfg(feature = "uniffi")]
993
#[derive(uniffi::Object)]
1094
pub struct TestStruct {

0 commit comments

Comments
 (0)