diff --git a/android/src/main/java/uniffi/pubkymobile/pubkymobile.kt b/android/src/main/java/uniffi/pubkymobile/pubkymobile.kt index 46a4c9b..1639053 100644 --- a/android/src/main/java/uniffi/pubkymobile/pubkymobile.kt +++ b/android/src/main/java/uniffi/pubkymobile/pubkymobile.kt @@ -29,9 +29,6 @@ import java.nio.ByteOrder import java.nio.CharBuffer import java.nio.charset.CodingErrorAction import java.util.concurrent.ConcurrentHashMap -import kotlin.coroutines.resume -import kotlinx.coroutines.CancellableContinuation -import kotlinx.coroutines.suspendCancellableCoroutine // This is a helper for safely working with byte buffers returned from the Rust code. // A rust-owned buffer is represented by its capacity, its current length, and a @@ -380,13 +377,12 @@ internal interface _UniFFILib : Library { .also { lib: _UniFFILib -> uniffiCheckContractApiVersion(lib) uniffiCheckApiChecksums(lib) - uniffiRustFutureContinuationCallback.register(lib) } } } - fun uniffi_pubkymobile_fn_func_auth(`url`: RustBuffer.ByValue,`secretKey`: RustBuffer.ByValue, - ): Pointer + fun uniffi_pubkymobile_fn_func_auth(`url`: RustBuffer.ByValue,`secretKey`: RustBuffer.ByValue,_uniffi_out_err: RustCallStatus, + ): RustBuffer.ByValue fun uniffi_pubkymobile_fn_func_parse_auth_url(`url`: RustBuffer.ByValue,_uniffi_out_err: RustCallStatus, ): RustBuffer.ByValue fun ffi_pubkymobile_rustbuffer_alloc(`size`: Int,_uniffi_out_err: RustCallStatus, @@ -524,7 +520,7 @@ private fun uniffiCheckContractApiVersion(lib: _UniFFILib) { @Suppress("UNUSED_PARAMETER") private fun uniffiCheckApiChecksums(lib: _UniFFILib) { - if (lib.uniffi_pubkymobile_checksum_func_auth() != 46918.toShort()) { + if (lib.uniffi_pubkymobile_checksum_func_auth() != 61378.toShort()) { throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") } if (lib.uniffi_pubkymobile_checksum_func_parse_auth_url() != 29088.toShort()) { @@ -533,50 +529,6 @@ private fun uniffiCheckApiChecksums(lib: _UniFFILib) { } // Async support -// Async return type handlers - -internal const val UNIFFI_RUST_FUTURE_POLL_READY = 0.toShort() -internal const val UNIFFI_RUST_FUTURE_POLL_MAYBE_READY = 1.toShort() - -internal val uniffiContinuationHandleMap = UniFfiHandleMap>() - -// FFI type for Rust future continuations -internal object uniffiRustFutureContinuationCallback: UniFffiRustFutureContinuationCallbackType { - override fun callback(continuationHandle: USize, pollResult: Short) { - uniffiContinuationHandleMap.remove(continuationHandle)?.resume(pollResult) - } - - internal fun register(lib: _UniFFILib) { - lib.ffi_pubkymobile_rust_future_continuation_callback_set(this) - } -} - -internal suspend fun uniffiRustCallAsync( - rustFuture: Pointer, - pollFunc: (Pointer, USize) -> Unit, - completeFunc: (Pointer, RustCallStatus) -> F, - freeFunc: (Pointer) -> Unit, - liftFunc: (F) -> T, - errorHandler: CallStatusErrorHandler -): T { - try { - do { - val pollResult = suspendCancellableCoroutine { continuation -> - pollFunc( - rustFuture, - uniffiContinuationHandleMap.insert(continuation) - ) - } - } while (pollResult != UNIFFI_RUST_FUTURE_POLL_READY); - - return liftFunc( - rustCallWithError(errorHandler, { status -> completeFunc(rustFuture, status) }) - ) - } finally { - freeFunc(rustFuture) - } -} - // Public interface members begin here. @@ -660,24 +612,14 @@ public object FfiConverterSequenceString: FfiConverterRustBuffer> { } } - - - - -@Suppress("ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE") -suspend fun `auth`(`url`: String, `secretKey`: String) : List { - return uniffiRustCallAsync( - _UniFFILib.INSTANCE.uniffi_pubkymobile_fn_func_auth(FfiConverterString.lower(`url`),FfiConverterString.lower(`secretKey`),), - { future, continuation -> _UniFFILib.INSTANCE.ffi_pubkymobile_rust_future_poll_rust_buffer(future, continuation) }, - { future, continuation -> _UniFFILib.INSTANCE.ffi_pubkymobile_rust_future_complete_rust_buffer(future, continuation) }, - { future -> _UniFFILib.INSTANCE.ffi_pubkymobile_rust_future_free_rust_buffer(future) }, - // lift function - { FfiConverterSequenceString.lift(it) }, - // Error FFI converter - NullCallStatusErrorHandler, - ) +fun `auth`(`url`: String, `secretKey`: String): List { + return FfiConverterSequenceString.lift( + rustCall() { _status -> + _UniFFILib.INSTANCE.uniffi_pubkymobile_fn_func_auth(FfiConverterString.lower(`url`),FfiConverterString.lower(`secretKey`),_status) +}) } + fun `parseAuthUrl`(`url`: String): List { return FfiConverterSequenceString.lift( rustCall() { _status -> diff --git a/android/src/main/jniLibs/arm64-v8a/libpubkymobile.so b/android/src/main/jniLibs/arm64-v8a/libpubkymobile.so index 0b51049..5dd9007 100755 Binary files a/android/src/main/jniLibs/arm64-v8a/libpubkymobile.so and b/android/src/main/jniLibs/arm64-v8a/libpubkymobile.so differ diff --git a/android/src/main/jniLibs/armeabi-v7a/libpubkymobile.so b/android/src/main/jniLibs/armeabi-v7a/libpubkymobile.so index aa8fc8f..c68a197 100755 Binary files a/android/src/main/jniLibs/armeabi-v7a/libpubkymobile.so and b/android/src/main/jniLibs/armeabi-v7a/libpubkymobile.so differ diff --git a/android/src/main/jniLibs/x86/libpubkymobile.so b/android/src/main/jniLibs/x86/libpubkymobile.so index 6623f56..61017b7 100755 Binary files a/android/src/main/jniLibs/x86/libpubkymobile.so and b/android/src/main/jniLibs/x86/libpubkymobile.so differ diff --git a/android/src/main/jniLibs/x86_64/libpubkymobile.so b/android/src/main/jniLibs/x86_64/libpubkymobile.so index fb2bafc..f1878d4 100755 Binary files a/android/src/main/jniLibs/x86_64/libpubkymobile.so and b/android/src/main/jniLibs/x86_64/libpubkymobile.so differ diff --git a/example/src/App.tsx b/example/src/App.tsx index 1a91ceb..052895a 100644 --- a/example/src/App.tsx +++ b/example/src/App.tsx @@ -9,7 +9,7 @@ export default function App() { onPress={async (): Promise => { try { const res = await auth( - 'pubkyAuthUrl', + 'pubkyauth:///?caps=/pub/pubky.app/:rw,/pub/foo.bar/file:r&secret=_K8yj2nS4naHWytpECCX48XhjhGc8KAhlpnuLUiHYBI&relay=http://localhost:52244/', 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855' ); if (res.isErr()) { diff --git a/ios/Frameworks/PubkyMobile.xcframework/ios-arm64-simulator/Headers/pubkymobileFFI.h b/ios/Frameworks/PubkyMobile.xcframework/ios-arm64-simulator/Headers/pubkymobileFFI.h index 669671c..66a4ff0 100644 --- a/ios/Frameworks/PubkyMobile.xcframework/ios-arm64-simulator/Headers/pubkymobileFFI.h +++ b/ios/Frameworks/PubkyMobile.xcframework/ios-arm64-simulator/Headers/pubkymobileFFI.h @@ -63,7 +63,7 @@ typedef struct RustCallStatus { typedef void (*UniFfiRustFutureContinuation)(void * _Nonnull, int8_t); // Scaffolding functions -void* _Nonnull uniffi_pubkymobile_fn_func_auth(RustBuffer url, RustBuffer secret_key +RustBuffer uniffi_pubkymobile_fn_func_auth(RustBuffer url, RustBuffer secret_key, RustCallStatus *_Nonnull out_status ); RustBuffer uniffi_pubkymobile_fn_func_parse_auth_url(RustBuffer url, RustCallStatus *_Nonnull out_status ); diff --git a/ios/Frameworks/PubkyMobile.xcframework/ios-arm64-simulator/libpubkymobile.a b/ios/Frameworks/PubkyMobile.xcframework/ios-arm64-simulator/libpubkymobile.a index c3f3dc4..15c65f8 100644 Binary files a/ios/Frameworks/PubkyMobile.xcframework/ios-arm64-simulator/libpubkymobile.a and b/ios/Frameworks/PubkyMobile.xcframework/ios-arm64-simulator/libpubkymobile.a differ diff --git a/ios/Frameworks/PubkyMobile.xcframework/ios-arm64/Headers/pubkymobileFFI.h b/ios/Frameworks/PubkyMobile.xcframework/ios-arm64/Headers/pubkymobileFFI.h index 669671c..66a4ff0 100644 --- a/ios/Frameworks/PubkyMobile.xcframework/ios-arm64/Headers/pubkymobileFFI.h +++ b/ios/Frameworks/PubkyMobile.xcframework/ios-arm64/Headers/pubkymobileFFI.h @@ -63,7 +63,7 @@ typedef struct RustCallStatus { typedef void (*UniFfiRustFutureContinuation)(void * _Nonnull, int8_t); // Scaffolding functions -void* _Nonnull uniffi_pubkymobile_fn_func_auth(RustBuffer url, RustBuffer secret_key +RustBuffer uniffi_pubkymobile_fn_func_auth(RustBuffer url, RustBuffer secret_key, RustCallStatus *_Nonnull out_status ); RustBuffer uniffi_pubkymobile_fn_func_parse_auth_url(RustBuffer url, RustCallStatus *_Nonnull out_status ); diff --git a/ios/Frameworks/PubkyMobile.xcframework/ios-arm64/libpubkymobile.a b/ios/Frameworks/PubkyMobile.xcframework/ios-arm64/libpubkymobile.a index 3eb1b1b..c9cb50d 100644 Binary files a/ios/Frameworks/PubkyMobile.xcframework/ios-arm64/libpubkymobile.a and b/ios/Frameworks/PubkyMobile.xcframework/ios-arm64/libpubkymobile.a differ diff --git a/ios/pubkymobile.swift b/ios/pubkymobile.swift index 106c1d3..d66009f 100644 --- a/ios/pubkymobile.swift +++ b/ios/pubkymobile.swift @@ -356,88 +356,17 @@ fileprivate struct FfiConverterSequenceString: FfiConverterRustBuffer { return seq } } -private let UNIFFI_RUST_FUTURE_POLL_READY: Int8 = 0 -private let UNIFFI_RUST_FUTURE_POLL_MAYBE_READY: Int8 = 1 -fileprivate func uniffiRustCallAsync( - rustFutureFunc: () -> UnsafeMutableRawPointer, - pollFunc: (UnsafeMutableRawPointer, UnsafeMutableRawPointer) -> (), - completeFunc: (UnsafeMutableRawPointer, UnsafeMutablePointer) -> F, - freeFunc: (UnsafeMutableRawPointer) -> (), - liftFunc: (F) throws -> T, - errorHandler: ((RustBuffer) throws -> Error)? -) async throws -> T { - // Make sure to call uniffiEnsureInitialized() since future creation doesn't have a - // RustCallStatus param, so doesn't use makeRustCall() - uniffiEnsureInitialized() - let rustFuture = rustFutureFunc() - defer { - freeFunc(rustFuture) - } - var pollResult: Int8; - repeat { - pollResult = await withUnsafeContinuation { - pollFunc(rustFuture, ContinuationHolder($0).toOpaque()) - } - } while pollResult != UNIFFI_RUST_FUTURE_POLL_READY - - return try liftFunc(makeRustCall( - { completeFunc(rustFuture, $0) }, - errorHandler: errorHandler - )) +public func auth(url: String, secretKey: String) -> [String] { + return try! FfiConverterSequenceString.lift( + try! rustCall() { + uniffi_pubkymobile_fn_func_auth( + FfiConverterString.lower(url), + FfiConverterString.lower(secretKey),$0) } - -// Callback handlers for an async calls. These are invoked by Rust when the future is ready. They -// lift the return value or error and resume the suspended function. -fileprivate func uniffiFutureContinuationCallback(ptr: UnsafeMutableRawPointer, pollResult: Int8) { - ContinuationHolder.fromOpaque(ptr).resume(pollResult) -} - -// Wraps UnsafeContinuation in a class so that we can use reference counting when passing it across -// the FFI -fileprivate class ContinuationHolder { - let continuation: UnsafeContinuation - - init(_ continuation: UnsafeContinuation) { - self.continuation = continuation - } - - func resume(_ pollResult: Int8) { - self.continuation.resume(returning: pollResult) - } - - func toOpaque() -> UnsafeMutableRawPointer { - return Unmanaged.passRetained(self).toOpaque() - } - - static func fromOpaque(_ ptr: UnsafeRawPointer) -> ContinuationHolder { - return Unmanaged.fromOpaque(ptr).takeRetainedValue() - } -} - -fileprivate func uniffiInitContinuationCallback() { - ffi_pubkymobile_rust_future_continuation_callback_set(uniffiFutureContinuationCallback) -} - -public func auth(url: String, secretKey: String) async -> [String] { - return try! await uniffiRustCallAsync( - rustFutureFunc: { - uniffi_pubkymobile_fn_func_auth( - FfiConverterString.lower(url), - FfiConverterString.lower(secretKey) - ) - }, - pollFunc: ffi_pubkymobile_rust_future_poll_rust_buffer, - completeFunc: ffi_pubkymobile_rust_future_complete_rust_buffer, - freeFunc: ffi_pubkymobile_rust_future_free_rust_buffer, - liftFunc: FfiConverterSequenceString.lift, - errorHandler: nil - ) } - - public func parseAuthUrl(url: String) -> [String] { return try! FfiConverterSequenceString.lift( try! rustCall() { @@ -462,14 +391,13 @@ private var initializationResult: InitializationResult { if bindings_contract_version != scaffolding_contract_version { return InitializationResult.contractVersionMismatch } - if (uniffi_pubkymobile_checksum_func_auth() != 46918) { + if (uniffi_pubkymobile_checksum_func_auth() != 61378) { return InitializationResult.apiChecksumMismatch } if (uniffi_pubkymobile_checksum_func_parse_auth_url() != 29088) { return InitializationResult.apiChecksumMismatch } - uniffiInitContinuationCallback() return InitializationResult.ok } diff --git a/package.json b/package.json index c2811c3..4d2cd35 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@synonymdev/react-native-pubky", - "version": "0.2.0", + "version": "0.2.1", "description": "React Native Implementation of Pubky", "source": "./src/index.tsx", "main": "./lib/commonjs/index.js", diff --git a/rust/Cargo.lock b/rust/Cargo.lock index f14c6fa..2b81ef9 100644 --- a/rust/Cargo.lock +++ b/rust/Cargo.lock @@ -87,9 +87,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.88" +version = "1.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e1496f8fb1fbf272686b8d37f523dab3e4a7443300055e74cdaa449f3114356" +checksum = "86fdf8605db99b54d3cd748a44c6d04df638eb5dafb219b135d0149bd0db01f6" [[package]] name = "argon2" @@ -424,9 +424,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.1.18" +version = "1.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b62ac837cdb5cb22e10a256099b4fc502b1dfe560cb282963a974d7abd80e476" +checksum = "2d74707dde2ba56f86ae90effb3b43ddd369504387e718014de010cec7959800" dependencies = [ "shlex", ] @@ -1411,9 +1411,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.20.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33ea5043e58958ee56f3e15a90aee535795cd7dfd319846288d93c5b57d85cbe" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "oneshot-uniffi" @@ -1566,7 +1566,7 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "pkarr" version = "2.2.0" -source = "git+https://github.com/Pubky/pkarr?branch=v3#2d1abb4d28624c298a38996ee3f40914676cd5d1" +source = "git+https://github.com/Pubky/pkarr?branch=v3#7a4575f4c60689765ba0567aa27248df2b31b2d4" dependencies = [ "base32", "bytes", diff --git a/rust/src/lib.rs b/rust/src/lib.rs index da9e546..0f4b794 100644 --- a/rust/src/lib.rs +++ b/rust/src/lib.rs @@ -5,9 +5,9 @@ use pubky::PubkyClient; use hex; use serde::Serialize; use url::Url; +use tokio; -#[uniffi::export] -async fn auth(url: String, secret_key: String) -> Vec { +async fn authorize(url: String, secret_key: String) -> Vec { let bytes = match hex::decode(&secret_key) { Ok(bytes) => bytes, Err(_) => return create_response_vector(true, "Failed to decode secret key".to_string()) @@ -20,8 +20,20 @@ async fn auth(url: String, secret_key: String) -> Vec { } }; - let keypair = pkarr::Keypair::from_secret_key(&secret_key_bytes); let client = PubkyClient::testnet(); + let keypair = pkarr::Keypair::from_secret_key(&secret_key_bytes); + + // const HOMESERVER: &'static str = "8pinxxgqs41n4aididenw5apqp1urfmzdztr8jt4abrkdn435ewo"; + // const URL: &'static str = "http://localhost:6287?relay=http://demo.httprelay.io/link"; + // match client.signin(&keypair).await { + // Ok(_) => {}, // Signin successful, continue to send_auth_token + // Err(_) => { + // match client.signup(&keypair, &PublicKey::try_from(HOMESERVER).unwrap()).await { + // Ok(_) => {}, // Signup successful, continue to send_auth_token + // Err(error) => return create_response_vector(true, format!("Failed to signup: {}", error)), + // } + // } + // } let parsed_url = match Url::parse(&url) { Ok(url) => url, @@ -29,11 +41,18 @@ async fn auth(url: String, secret_key: String) -> Vec { }; match client.send_auth_token(&keypair, parsed_url).await { - Ok(_) => create_response_vector(false, "Auth token sent successfully".to_string()), - Err(error) => create_response_vector(true, format!("Error sending auth token: {:?}", error)), + Ok(_) => create_response_vector(false, "send_auth_token success".to_string()), + Err(error) => create_response_vector(true, format!("send_auth_token failure: {}", error)), } } + +#[uniffi::export] +fn auth(url: String, secret_key: String) -> Vec { + let rt = tokio::runtime::Runtime::new().unwrap(); + rt.block_on(authorize(url, secret_key)) +} + #[uniffi::export] fn parse_auth_url(url: String) -> Vec { let parsed_details = match parse_pubky_auth_url(&url) {