diff --git a/README.md b/README.md
index 3d95119..c4613e1 100644
--- a/README.md
+++ b/README.md
@@ -16,15 +16,17 @@ npm install @synonymdev/react-native-pubky
- [x] [resolve](#resolve): Functionality to resolve content.
- [x] [publishHttps](#publishHttps): Publish HTTPS records.
- [x] [resolveHttps](#resolveHttps): Resolve HTTPS records.
+- [x] [signUp](#signUp): Sign-up to a homeserver and update Pkarr accordingly.
+- [x] [signIn](#signIn): Sign-in to a homeserver.
+- [x] [signOut](#signOut): Sign-out from a homeserver.
- [x] [put](#put): Upload a small payload to a given path.
- [x] [get](#get): Download a small payload from a given path relative to a pubky author.
- [x] [list](#list): Returns a list of Pubky URLs of the files in the path of the `url` provided.
- [x] [generateSecretKey](#generateSecretKey): Generate a secret key.
- [x] [getPublicKeyFromSecretKey](#getPublicKeyFromSecretKey): Get the public key string and uri from a secret key.
### Methods to be Implemented
-- [ ] signIn: Sign-in to a homeserver.
-- [ ] signUp: Sign-up to a homeserver and update Pkarr accordingly.
-- [ ] signOut: Sign-out from a homeserver.
+- [ ] getProfile: Retrieve the profile of a user.
+- [ ] editProfile: Submit changes to the specified profile.
## Usage
@@ -118,8 +120,8 @@ console.log(resolveHttpsRes.value);
import { put } from '@synonymdev/react-native-pubky';
const putRes = await put(
- 'url', // URL
- 'content', // Content
+ 'pubky://z4e8s17cou9qmuwen8p1556jzhf1wktmzo6ijsfnri9c4hnrdfty/pub/synonym.to', // URL
+ { data: 'test content' }, // Content
);
if (putRes.isErr()) {
console.log(putRes.error.message);
@@ -133,7 +135,7 @@ console.log(putRes.value);
import { get } from '@synonymdev/react-native-pubky';
const getRes = await get(
- 'url' // URL
+ 'pubky://z4e8s17cou9qmuwen8p1556jzhf1wktmzo6ijsfnri9c4hnrdfty/pub/synonym.to' // URL
);
if (getRes.isErr()) {
console.log(getRes.error.message);
@@ -147,7 +149,7 @@ console.log(getRes.value);
import { list } from '@synonymdev/react-native-pubky';
const listRes = await list(
- 'url' // URL
+ 'pubky://z4e8s17cou9qmuwen8p1556jzhf1wktmzo6ijsfnri9c4hnrdfty/pub/' // URL
);
if (listRes.isErr()) {
console.log(listRes.error.message);
@@ -180,6 +182,49 @@ if (getPublicKeyFromSecretKeyRes.isErr()) {
console.log(getPublicKeyFromSecretKeyRes.value);
```
+### signUp
+```js
+import { signUp } from '@synonymdev/react-native-pubky';
+
+const signUpRes = await signUp(
+ 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855', // Secret
+ 'pubky://8pinxxgqs41n4aididenw5apqp1urfmzdztr8jt4abrkdn435ewo', // Homeserver
+);
+if (signUpRes.isErr()) {
+ console.log(signUpRes.error.message);
+ return;
+}
+console.log(signUpRes.value);
+```
+
+### signIn
+```js
+import { signIn } from '@synonymdev/react-native-pubky';
+
+const signInRes = await signIn(
+ 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855' // Secret Key
+);
+if (signInRes.isErr()) {
+ console.log(signInRes.error.message);
+ return;
+}
+console.log(signInRes.value);
+```
+
+### signIn
+```js
+import { signOut } from '@synonymdev/react-native-pubky';
+
+const signOutRes = await signOut(
+ 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855' // Secret Key
+);
+if (signOutRes.isErr()) {
+ console.log(signOutRes.error.message);
+ return;
+}
+console.log(signOutRes.value);
+```
+
## Local Installation
1. Clone & npm install:
diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock
index c523763..8080bf3 100644
--- a/example/ios/Podfile.lock
+++ b/example/ios/Podfile.lock
@@ -1237,7 +1237,7 @@ PODS:
- ReactCommon/turbomodule/bridging
- ReactCommon/turbomodule/core
- Yoga
- - react-native-pubky (0.7.0):
+ - react-native-pubky (0.7.1):
- DoubleConversion
- glog
- hermes-engine
@@ -1757,7 +1757,7 @@ SPEC CHECKSUMS:
React-logger: 4072f39df335ca443932e0ccece41fbeb5ca8404
React-Mapbuffer: 714f2fae68edcabfc332b754e9fbaa8cfc68fdd4
React-microtasksnativemodule: 4943ad8f99be8ccf5a63329fa7d269816609df9e
- react-native-pubky: e296eaeb8422b0864f5807592eac144d7d9a6eae
+ react-native-pubky: 1740252f1e510886c4239242d0b731bc4d96b91b
React-nativeconfig: 4a9543185905fe41014c06776bf126083795aed9
React-NativeModulesApple: 0506da59fc40d2e1e6e12a233db5e81c46face27
React-perflogger: 3bbb82f18e9ac29a1a6931568e99d6305ef4403b
diff --git a/example/src/App.tsx b/example/src/App.tsx
index 4cc7547..a395143 100644
--- a/example/src/App.tsx
+++ b/example/src/App.tsx
@@ -16,6 +16,11 @@ import {
getPublicKeyFromSecretKey,
} from '@synonymdev/react-native-pubky';
+const HOMESERVER = '8pinxxgqs41n4aididenw5apqp1urfmzdztr8jt4abrkdn435ewo';
+const SECRET_KEY =
+ 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855';
+const PUBLIC_KEY = 'z4e8s17cou9qmuwen8p1556jzhf1wktmzo6ijsfnri9c4hnrdfty';
+
export default function App() {
return (
@@ -25,7 +30,7 @@ export default function App() {
try {
const res = await auth(
'pubkyauth:///?caps=/pub/pubky.app/:rw,/pub/foo.bar/file:r&secret=U55XnoH6vsMCpx1pxHtt8fReVg4Brvu9C0gUBuw-Jkw&relay=http://167.86.102.121:4173/',
- 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855'
+ SECRET_KEY
);
if (res.isErr()) {
console.log(res.error.message);
@@ -61,7 +66,7 @@ export default function App() {
const res = await publish(
'recordnametest', // Record Name
'recordcontenttest', // Record Content
- 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855' // Secret Key
+ SECRET_KEY // Secret Key
);
if (res.isErr()) {
console.log(res.error.message);
@@ -78,7 +83,7 @@ export default function App() {
onPress={async (): Promise => {
try {
const res = await resolve(
- 'z4e8s17cou9qmuwen8p1556jzhf1wktmzo6ijsfnri9c4hnrdfty' // Public key
+ PUBLIC_KEY // Public key
);
if (res.isErr()) {
console.log(res.error.message);
@@ -95,8 +100,8 @@ export default function App() {
onPress={async (): Promise => {
try {
const res = await signUp(
- 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855', // Secret Key
- 'pubky://8pinxxgqs41n4aididenw5apqp1urfmzdztr8jt4abrkdn435ewo' // Homeserver
+ SECRET_KEY, // Secret Key
+ `pubky://${HOMESERVER}` // Homeserver
);
if (res.isErr()) {
console.log(res.error.message);
@@ -113,7 +118,7 @@ export default function App() {
onPress={async (): Promise => {
try {
const res = await signIn(
- 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855' // Secret Key
+ SECRET_KEY // Secret Key
);
if (res.isErr()) {
console.log(res.error.message);
@@ -130,7 +135,7 @@ export default function App() {
onPress={async (): Promise => {
try {
const res = await signOut(
- 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855' // Secret Key
+ SECRET_KEY // Secret Key
);
if (res.isErr()) {
console.log(res.error.message);
@@ -146,7 +151,9 @@ export default function App() {
title={'put'}
onPress={async (): Promise => {
try {
- const res = await put('', { data: 'test data' });
+ const res = await put(`pubky://${PUBLIC_KEY}/pub/synonym.to`, {
+ data: 'test data',
+ });
if (res.isErr()) {
console.log(res.error.message);
return;
@@ -161,7 +168,7 @@ export default function App() {
title={'get'}
onPress={async (): Promise => {
try {
- const res = await get('');
+ const res = await get(`pubky://${PUBLIC_KEY}/pub/synonym.to`);
if (res.isErr()) {
console.log(res.error.message);
return;
@@ -180,7 +187,7 @@ export default function App() {
const res = await publishHttps(
'example.com', // Record Name
'target.example.com', // Target
- 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855' // Secret Key
+ SECRET_KEY // Secret Key
);
if (res.isErr()) {
console.log(res.error.message);
@@ -198,7 +205,7 @@ export default function App() {
onPress={async (): Promise => {
try {
const res = await resolveHttps(
- 'z4e8s17cou9qmuwen8p1556jzhf1wktmzo6ijsfnri9c4hnrdfty' // Public key
+ PUBLIC_KEY // Public key
);
if (res.isErr()) {
console.log(res.error.message);
@@ -216,7 +223,7 @@ export default function App() {
onPress={async (): Promise => {
try {
const res = await list(
- 'url' // URL
+ `pubky://${PUBLIC_KEY}/pub/synonym.to` // URL
);
if (res.isErr()) {
console.log(res.error.message);
@@ -249,7 +256,7 @@ export default function App() {
onPress={async (): Promise => {
try {
const res = await getPublicKeyFromSecretKey(
- 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855' // Secret Key
+ SECRET_KEY // Secret Key
);
if (res.isErr()) {
console.log(res.error.message);
diff --git a/ios/Frameworks/PubkyMobile.xcframework/Info.plist b/ios/Frameworks/PubkyMobile.xcframework/Info.plist
index bb3ac5e..e1d4787 100644
--- a/ios/Frameworks/PubkyMobile.xcframework/Info.plist
+++ b/ios/Frameworks/PubkyMobile.xcframework/Info.plist
@@ -4,22 +4,6 @@
AvailableLibraries
-
- BinaryPath
- libpubkymobile.a
- HeadersPath
- Headers
- LibraryIdentifier
- ios-arm64
- LibraryPath
- libpubkymobile.a
- SupportedArchitectures
-
- arm64
-
- SupportedPlatform
- ios
-
BinaryPath
libpubkymobile.a
@@ -38,6 +22,22 @@
SupportedPlatformVariant
simulator
+
+ BinaryPath
+ libpubkymobile.a
+ HeadersPath
+ Headers
+ LibraryIdentifier
+ ios-arm64
+ LibraryPath
+ libpubkymobile.a
+ SupportedArchitectures
+
+ arm64
+
+ SupportedPlatform
+ ios
+
CFBundlePackageType
XFWK
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 1d9357c..c3eb798 100644
--- a/ios/Frameworks/PubkyMobile.xcframework/ios-arm64-simulator/Headers/pubkymobileFFI.h
+++ b/ios/Frameworks/PubkyMobile.xcframework/ios-arm64-simulator/Headers/pubkymobileFFI.h
@@ -68,7 +68,7 @@ RustBuffer uniffi_pubkymobile_fn_func_auth(RustBuffer url, RustBuffer secret_key
RustBuffer uniffi_pubkymobile_fn_func_generate_secret_key(RustCallStatus *_Nonnull out_status
);
-void* _Nonnull uniffi_pubkymobile_fn_func_get(RustBuffer url
+RustBuffer uniffi_pubkymobile_fn_func_get(RustBuffer url, RustCallStatus *_Nonnull out_status
);
RustBuffer uniffi_pubkymobile_fn_func_get_public_key_from_secret_key(RustBuffer secret_key, RustCallStatus *_Nonnull out_status
);
@@ -80,17 +80,17 @@ RustBuffer uniffi_pubkymobile_fn_func_publish(RustBuffer record_name, RustBuffer
);
RustBuffer uniffi_pubkymobile_fn_func_publish_https(RustBuffer record_name, RustBuffer target, RustBuffer secret_key, RustCallStatus *_Nonnull out_status
);
-void* _Nonnull uniffi_pubkymobile_fn_func_put(RustBuffer url, RustBuffer content
+RustBuffer uniffi_pubkymobile_fn_func_put(RustBuffer url, RustBuffer content, RustCallStatus *_Nonnull out_status
);
RustBuffer uniffi_pubkymobile_fn_func_resolve(RustBuffer public_key, RustCallStatus *_Nonnull out_status
);
RustBuffer uniffi_pubkymobile_fn_func_resolve_https(RustBuffer public_key, RustCallStatus *_Nonnull out_status
);
-void* _Nonnull uniffi_pubkymobile_fn_func_sign_in(RustBuffer secret_key
+RustBuffer uniffi_pubkymobile_fn_func_sign_in(RustBuffer secret_key, RustCallStatus *_Nonnull out_status
);
-void* _Nonnull uniffi_pubkymobile_fn_func_sign_out(RustBuffer secret_key
+RustBuffer uniffi_pubkymobile_fn_func_sign_out(RustBuffer secret_key, RustCallStatus *_Nonnull out_status
);
-void* _Nonnull uniffi_pubkymobile_fn_func_sign_up(RustBuffer secret_key, RustBuffer homeserver
+RustBuffer uniffi_pubkymobile_fn_func_sign_up(RustBuffer secret_key, RustBuffer homeserver, RustCallStatus *_Nonnull out_status
);
RustBuffer ffi_pubkymobile_rustbuffer_alloc(int32_t size, 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 9e662f0..5cf3087 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 1d9357c..c3eb798 100644
--- a/ios/Frameworks/PubkyMobile.xcframework/ios-arm64/Headers/pubkymobileFFI.h
+++ b/ios/Frameworks/PubkyMobile.xcframework/ios-arm64/Headers/pubkymobileFFI.h
@@ -68,7 +68,7 @@ RustBuffer uniffi_pubkymobile_fn_func_auth(RustBuffer url, RustBuffer secret_key
RustBuffer uniffi_pubkymobile_fn_func_generate_secret_key(RustCallStatus *_Nonnull out_status
);
-void* _Nonnull uniffi_pubkymobile_fn_func_get(RustBuffer url
+RustBuffer uniffi_pubkymobile_fn_func_get(RustBuffer url, RustCallStatus *_Nonnull out_status
);
RustBuffer uniffi_pubkymobile_fn_func_get_public_key_from_secret_key(RustBuffer secret_key, RustCallStatus *_Nonnull out_status
);
@@ -80,17 +80,17 @@ RustBuffer uniffi_pubkymobile_fn_func_publish(RustBuffer record_name, RustBuffer
);
RustBuffer uniffi_pubkymobile_fn_func_publish_https(RustBuffer record_name, RustBuffer target, RustBuffer secret_key, RustCallStatus *_Nonnull out_status
);
-void* _Nonnull uniffi_pubkymobile_fn_func_put(RustBuffer url, RustBuffer content
+RustBuffer uniffi_pubkymobile_fn_func_put(RustBuffer url, RustBuffer content, RustCallStatus *_Nonnull out_status
);
RustBuffer uniffi_pubkymobile_fn_func_resolve(RustBuffer public_key, RustCallStatus *_Nonnull out_status
);
RustBuffer uniffi_pubkymobile_fn_func_resolve_https(RustBuffer public_key, RustCallStatus *_Nonnull out_status
);
-void* _Nonnull uniffi_pubkymobile_fn_func_sign_in(RustBuffer secret_key
+RustBuffer uniffi_pubkymobile_fn_func_sign_in(RustBuffer secret_key, RustCallStatus *_Nonnull out_status
);
-void* _Nonnull uniffi_pubkymobile_fn_func_sign_out(RustBuffer secret_key
+RustBuffer uniffi_pubkymobile_fn_func_sign_out(RustBuffer secret_key, RustCallStatus *_Nonnull out_status
);
-void* _Nonnull uniffi_pubkymobile_fn_func_sign_up(RustBuffer secret_key, RustBuffer homeserver
+RustBuffer uniffi_pubkymobile_fn_func_sign_up(RustBuffer secret_key, RustBuffer homeserver, RustCallStatus *_Nonnull out_status
);
RustBuffer ffi_pubkymobile_rustbuffer_alloc(int32_t size, 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 3104b16..72f9fae 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 ae97cd3..862e86e 100644
--- a/ios/pubkymobile.swift
+++ b/ios/pubkymobile.swift
@@ -356,68 +356,6 @@ 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
- ))
-}
-
-// 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) -> [String] {
return try! FfiConverterSequenceString.lift(
@@ -437,24 +375,15 @@ public func generateSecretKey() -> [String] {
)
}
-public func get(url: String) async -> [String] {
- return try! await uniffiRustCallAsync(
- rustFutureFunc: {
- uniffi_pubkymobile_fn_func_get(
- FfiConverterString.lower(url)
- )
- },
- 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 get(url: String) -> [String] {
+ return try! FfiConverterSequenceString.lift(
+ try! rustCall() {
+ uniffi_pubkymobile_fn_func_get(
+ FfiConverterString.lower(url),$0)
+}
)
}
-
-
public func getPublicKeyFromSecretKey(secretKey: String) -> [String] {
return try! FfiConverterSequenceString.lift(
try! rustCall() {
@@ -504,25 +433,16 @@ public func publishHttps(recordName: String, target: String, secretKey: String)
)
}
-public func put(url: String, content: String) async -> [String] {
- return try! await uniffiRustCallAsync(
- rustFutureFunc: {
- uniffi_pubkymobile_fn_func_put(
- FfiConverterString.lower(url),
- FfiConverterString.lower(content)
- )
- },
- 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 put(url: String, content: String) -> [String] {
+ return try! FfiConverterSequenceString.lift(
+ try! rustCall() {
+ uniffi_pubkymobile_fn_func_put(
+ FfiConverterString.lower(url),
+ FfiConverterString.lower(content),$0)
+}
)
}
-
-
public func resolve(publicKey: String) -> [String] {
return try! FfiConverterSequenceString.lift(
try! rustCall() {
@@ -541,61 +461,34 @@ public func resolveHttps(publicKey: String) -> [String] {
)
}
-public func signIn(secretKey: String) async -> [String] {
- return try! await uniffiRustCallAsync(
- rustFutureFunc: {
- uniffi_pubkymobile_fn_func_sign_in(
- 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 signIn(secretKey: String) -> [String] {
+ return try! FfiConverterSequenceString.lift(
+ try! rustCall() {
+ uniffi_pubkymobile_fn_func_sign_in(
+ FfiConverterString.lower(secretKey),$0)
+}
)
}
-
-
-public func signOut(secretKey: String) async -> [String] {
- return try! await uniffiRustCallAsync(
- rustFutureFunc: {
- uniffi_pubkymobile_fn_func_sign_out(
- 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 signOut(secretKey: String) -> [String] {
+ return try! FfiConverterSequenceString.lift(
+ try! rustCall() {
+ uniffi_pubkymobile_fn_func_sign_out(
+ FfiConverterString.lower(secretKey),$0)
+}
)
}
-
-
-public func signUp(secretKey: String, homeserver: String) async -> [String] {
- return try! await uniffiRustCallAsync(
- rustFutureFunc: {
- uniffi_pubkymobile_fn_func_sign_up(
- FfiConverterString.lower(secretKey),
- FfiConverterString.lower(homeserver)
- )
- },
- 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 signUp(secretKey: String, homeserver: String) -> [String] {
+ return try! FfiConverterSequenceString.lift(
+ try! rustCall() {
+ uniffi_pubkymobile_fn_func_sign_up(
+ FfiConverterString.lower(secretKey),
+ FfiConverterString.lower(homeserver),$0)
+}
)
}
-
-
private enum InitializationResult {
case ok
case contractVersionMismatch
@@ -617,7 +510,7 @@ private var initializationResult: InitializationResult {
if (uniffi_pubkymobile_checksum_func_generate_secret_key() != 63116) {
return InitializationResult.apiChecksumMismatch
}
- if (uniffi_pubkymobile_checksum_func_get() != 5395) {
+ if (uniffi_pubkymobile_checksum_func_get() != 21596) {
return InitializationResult.apiChecksumMismatch
}
if (uniffi_pubkymobile_checksum_func_get_public_key_from_secret_key() != 23603) {
@@ -635,7 +528,7 @@ private var initializationResult: InitializationResult {
if (uniffi_pubkymobile_checksum_func_publish_https() != 14705) {
return InitializationResult.apiChecksumMismatch
}
- if (uniffi_pubkymobile_checksum_func_put() != 47594) {
+ if (uniffi_pubkymobile_checksum_func_put() != 51107) {
return InitializationResult.apiChecksumMismatch
}
if (uniffi_pubkymobile_checksum_func_resolve() != 18303) {
@@ -644,17 +537,16 @@ private var initializationResult: InitializationResult {
if (uniffi_pubkymobile_checksum_func_resolve_https() != 34593) {
return InitializationResult.apiChecksumMismatch
}
- if (uniffi_pubkymobile_checksum_func_sign_in() != 53969) {
+ if (uniffi_pubkymobile_checksum_func_sign_in() != 21006) {
return InitializationResult.apiChecksumMismatch
}
- if (uniffi_pubkymobile_checksum_func_sign_out() != 32961) {
+ if (uniffi_pubkymobile_checksum_func_sign_out() != 59116) {
return InitializationResult.apiChecksumMismatch
}
- if (uniffi_pubkymobile_checksum_func_sign_up() != 28083) {
+ if (uniffi_pubkymobile_checksum_func_sign_up() != 58756) {
return InitializationResult.apiChecksumMismatch
}
- uniffiInitContinuationCallback()
return InitializationResult.ok
}
diff --git a/package.json b/package.json
index 4407f80..e6d7e02 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "@synonymdev/react-native-pubky",
- "version": "0.7.0",
+ "version": "0.7.1",
"description": "React Native Implementation of Pubky",
"source": "./src/index.tsx",
"main": "./lib/commonjs/index.js",
diff --git a/rust/src/lib.rs b/rust/src/lib.rs
index 7bfb062..6a635ba 100644
--- a/rust/src/lib.rs
+++ b/rust/src/lib.rs
@@ -10,6 +10,7 @@ pub use utils::*;
uniffi::setup_scaffolding!();
+use std::str;
use std::collections::HashMap;
use base64::Engine;
use base64::engine::general_purpose;
@@ -26,16 +27,9 @@ use serde_json::json;
use utils::*;
use once_cell::sync::Lazy;
use std::sync::Arc;
+use pkarr::bytes::Bytes;
use tokio::runtime::Runtime;
-static PKARR_CLIENT: Lazy> = Lazy::new(|| {
- Arc::new(
- PkarrClient::builder()
- .build()
- .expect("Failed to build PkarrClient"),
- )
-});
-
static PUBKY_CLIENT: Lazy> = Lazy::new(|| {
Arc::new(PubkyClient::testnet())
});
@@ -87,209 +81,239 @@ pub fn get_public_key_from_secret_key(secret_key: String) -> Vec {
#[uniffi::export]
pub fn publish_https(record_name: String, target: String, secret_key: String) -> Vec {
- let client = PKARR_CLIENT.clone();
+ let runtime = TOKIO_RUNTIME.clone();
+ runtime.block_on(async {
+ let client = PUBKY_CLIENT.clone();
- let keypair = match get_keypair_from_secret_key(&secret_key) {
- Ok(keypair) => keypair,
- Err(error) => return create_response_vector(true, error),
- };
+ let keypair = match get_keypair_from_secret_key(&secret_key) {
+ Ok(keypair) => keypair,
+ Err(error) => return create_response_vector(true, error),
+ };
- // Create SVCB record with the target domain
- let target = match target.as_str().try_into() {
- Ok(target) => target,
- Err(e) => return create_response_vector(true, format!("Invalid target: {}", e)),
- };
- let svcb = SVCB::new(0, target);
+ // Create SVCB record with the target domain
+ let target = match target.as_str().try_into() {
+ Ok(target) => target,
+ Err(e) => return create_response_vector(true, format!("Invalid target: {}", e)),
+ };
+ let svcb = SVCB::new(0, target);
- // Create HTTPS record
- let https_record = HTTPS(svcb);
+ // Create HTTPS record
+ let https_record = HTTPS(svcb);
- // Create DNS packet
- let mut packet = Packet::new_reply(0);
- let dns_name = match dns::Name::new(&record_name) {
- Ok(name) => name,
- Err(e) => return create_response_vector(true, format!("Invalid DNS name: {}", e)),
- };
+ // Create DNS packet
+ let mut packet = Packet::new_reply(0);
+ let dns_name = match dns::Name::new(&record_name) {
+ Ok(name) => name,
+ Err(e) => return create_response_vector(true, format!("Invalid DNS name: {}", e)),
+ };
- packet.answers.push(ResourceRecord::new(
- dns_name,
- dns::CLASS::IN,
- 3600, // TTL in seconds
- dns::rdata::RData::HTTPS(https_record),
- ));
+ packet.answers.push(ResourceRecord::new(
+ dns_name,
+ dns::CLASS::IN,
+ 3600, // TTL in seconds
+ dns::rdata::RData::HTTPS(https_record),
+ ));
- let signed_packet = match SignedPacket::from_packet(&keypair, &packet) {
- Ok(signed_packet) => signed_packet,
- Err(e) => return create_response_vector(true, format!("Failed to create signed packet: {}", e)),
- };
+ let signed_packet = match SignedPacket::from_packet(&keypair, &packet) {
+ Ok(signed_packet) => signed_packet,
+ Err(e) => return create_response_vector(true, format!("Failed to create signed packet: {}", e)),
+ };
- match client.publish(&signed_packet) {
- Ok(()) => create_response_vector(false, keypair.public_key().to_string()),
- Err(e) => create_response_vector(true, format!("Failed to publish: {}", e)),
- }
+ match client.pkarr().publish(&signed_packet).await {
+ Ok(()) => create_response_vector(false, keypair.public_key().to_string()),
+ Err(e) => create_response_vector(true, format!("Failed to publish: {}", e)),
+ }
+ })
}
#[uniffi::export]
pub fn resolve_https(public_key: String) -> Vec {
- let public_key = match public_key.as_str().try_into() {
- Ok(key) => key,
- Err(e) => return create_response_vector(true, format!("Invalid public key: {}", e)),
- };
+ let runtime = TOKIO_RUNTIME.clone();
+ runtime.block_on(async {
+ let public_key = match public_key.as_str().try_into() {
+ Ok(key) => key,
+ Err(e) => return create_response_vector(true, format!("Invalid public key: {}", e)),
+ };
- let client = PKARR_CLIENT.clone();
+ let client = PUBKY_CLIENT.clone();
- match client.resolve(&public_key) {
- Ok(Some(signed_packet)) => {
- // Extract HTTPS records from the signed packet
- let https_records: Vec = signed_packet.packet().answers.iter()
- .filter_map(|record| {
- if let dns::rdata::RData::HTTPS(https) = &record.rdata {
- // Create a JSON object
- let mut https_json = serde_json::json!({
- "name": record.name.to_string(),
- "class": format!("{:?}", record.class),
- "ttl": record.ttl,
- "priority": https.0.priority,
- "target": https.0.target.to_string(),
- });
+ match client.pkarr().resolve(&public_key).await {
+ Ok(Some(signed_packet)) => {
+ // Extract HTTPS records from the signed packet
+ let https_records: Vec = signed_packet.packet().answers.iter()
+ .filter_map(|record| {
+ if let dns::rdata::RData::HTTPS(https) = &record.rdata {
+ // Create a JSON object
+ let mut https_json = serde_json::json!({
+ "name": record.name.to_string(),
+ "class": format!("{:?}", record.class),
+ "ttl": record.ttl,
+ "priority": https.0.priority,
+ "target": https.0.target.to_string(),
+ });
- // Access specific parameters using the constants from SVCB
- if let Some(port_param) = https.0.get_param(SVCB::PORT) {
- if port_param.len() == 2 {
- let port = u16::from_be_bytes([port_param[0], port_param[1]]);
- https_json["port"] = serde_json::json!(port);
- }
- }
-
- // Access ALPN parameter if needed
- if let Some(alpn_param) = https.0.get_param(SVCB::ALPN) {
- // Parse ALPN protocols (list of character strings)
- let mut position = 0;
- let mut alpn_protocols = Vec::new();
- while position < alpn_param.len() {
- let length = alpn_param[position] as usize;
- position += 1;
- if position + length <= alpn_param.len() {
- let protocol = String::from_utf8_lossy(
- &alpn_param[position..position + length],
- );
- alpn_protocols.push(protocol.to_string());
- position += length;
- } else {
- break; // Malformed ALPN parameter
+ // Access specific parameters using the constants from SVCB
+ if let Some(port_param) = https.0.get_param(SVCB::PORT) {
+ if port_param.len() == 2 {
+ let port = u16::from_be_bytes([port_param[0], port_param[1]]);
+ https_json["port"] = serde_json::json!(port);
}
}
- https_json["alpn"] = serde_json::json!(alpn_protocols);
+
+ // Access ALPN parameter if needed
+ if let Some(alpn_param) = https.0.get_param(SVCB::ALPN) {
+ // Parse ALPN protocols (list of character strings)
+ let mut position = 0;
+ let mut alpn_protocols = Vec::new();
+ while position < alpn_param.len() {
+ let length = alpn_param[position] as usize;
+ position += 1;
+ if position + length <= alpn_param.len() {
+ let protocol = String::from_utf8_lossy(
+ &alpn_param[position..position + length],
+ );
+ alpn_protocols.push(protocol.to_string());
+ position += length;
+ } else {
+ break; // Malformed ALPN parameter
+ }
+ }
+ https_json["alpn"] = serde_json::json!(alpn_protocols);
+ }
+ // TODO: Add other parameters as needed.
+ Some(https_json)
+ } else {
+ None
}
- // TODO: Add other parameters as needed.
- Some(https_json)
- } else {
- None
- }
- })
- .collect();
+ })
+ .collect();
- if https_records.is_empty() {
- return create_response_vector(true, "No HTTPS records found".to_string());
+ if https_records.is_empty() {
+ return create_response_vector(true, "No HTTPS records found".to_string());
+ }
+
+ // Create JSON response
+ let json_obj = json!({
+ "public_key": public_key.to_string(),
+ "https_records": https_records,
+ "last_seen": signed_packet.last_seen(),
+ "timestamp": signed_packet.timestamp(),
+ });
+
+ let json_str = match serde_json::to_string(&json_obj) {
+ Ok(json) => json,
+ Err(e) => return create_response_vector(true, format!("Failed to serialize JSON: {}", e)),
+ };
+
+ create_response_vector(false, json_str)
+ },
+ Ok(None) => create_response_vector(true, "No signed packet found".to_string()),
+ Err(e) => create_response_vector(true, format!("Failed to resolve: {}", e)),
+ }
+ })
+}
+
+#[uniffi::export]
+pub fn sign_up(secret_key: String, homeserver: String) -> Vec {
+ let runtime = TOKIO_RUNTIME.clone();
+ runtime.block_on(async {
+ let client = PUBKY_CLIENT.clone();
+ let keypair = match get_keypair_from_secret_key(&secret_key) {
+ Ok(keypair) => keypair,
+ Err(error) => return create_response_vector(true, error),
+ };
+
+ let homeserver_public_key = match PublicKey::try_from(homeserver) {
+ Ok(key) => key,
+ Err(error) => return create_response_vector(true, format!("Invalid homeserver public key: {}", error)),
+ };
+
+ match client.signup(&keypair, &homeserver_public_key).await {
+ Ok(session) => create_response_vector(false, session.pubky().to_string()),
+ Err(error) => create_response_vector(true, format!("signup failure: {}", error)),
+ }
+ })
+}
+
+#[uniffi::export]
+pub fn sign_in(secret_key: String) -> Vec {
+ let runtime = TOKIO_RUNTIME.clone();
+ runtime.block_on(async {
+ let client = PUBKY_CLIENT.clone();
+ let keypair = match get_keypair_from_secret_key(&secret_key) {
+ Ok(keypair) => keypair,
+ Err(error) => return create_response_vector(true, error),
+ };
+ match client.signin(&keypair).await {
+ Ok(_) => create_response_vector(false, "Sign in success".to_string()),
+ Err(error) => {
+ create_response_vector(true, format!("Failed to sign in: {}", error))
}
-
- // Create JSON response
- let json_obj = json!({
- "public_key": public_key.to_string(),
- "https_records": https_records,
- "last_seen": signed_packet.last_seen(),
- "timestamp": signed_packet.timestamp(),
- });
-
- let json_str = match serde_json::to_string(&json_obj) {
- Ok(json) => json,
- Err(e) => return create_response_vector(true, format!("Failed to serialize JSON: {}", e)),
- };
-
- create_response_vector(false, json_str)
- },
- Ok(None) => create_response_vector(true, "No signed packet found".to_string()),
- Err(e) => create_response_vector(true, format!("Failed to resolve: {}", e)),
- }
-}
-
-#[uniffi::export]
-pub async fn sign_up(secret_key: String, homeserver: String) -> Vec {
- let client = PUBKY_CLIENT.clone();
- let keypair = match get_keypair_from_secret_key(&secret_key) {
- Ok(keypair) => keypair,
- Err(error) => return create_response_vector(true, error),
- };
-
- let homeserver_public_key = match PublicKey::try_from(homeserver) {
- Ok(key) => key,
- Err(error) => return create_response_vector(true, format!("Invalid homeserver public key: {}", error)),
- };
-
- match client.signup(&keypair, &homeserver_public_key).await {
- Ok(_) => create_response_vector(false, "signup success".to_string()),
- Err(error) => create_response_vector(true, format!("signup failure: {}", error)),
- }
-}
-
-#[uniffi::export]
-pub async fn sign_in(secret_key: String) -> Vec {
- let client = PUBKY_CLIENT.clone();
- let keypair = match get_keypair_from_secret_key(&secret_key) {
- Ok(keypair) => keypair,
- Err(error) => return create_response_vector(true, error),
- };
- match client.signin(&keypair).await {
- Ok(_) => create_response_vector(false, "Sign in success".to_string()),
- Err(error) => {
- create_response_vector(true, format!("Failed to sign in: {}", error))
}
- }
+ })
}
#[uniffi::export]
-pub async fn sign_out(secret_key: String) -> Vec {
- let client = PUBKY_CLIENT.clone();
- let keypair = match get_keypair_from_secret_key(&secret_key) {
- Ok(keypair) => keypair,
- Err(error) => return create_response_vector(true, error),
- };
- match client.signout(&keypair.public_key()).await {
- Ok(_) => create_response_vector(false, "Sign out success".to_string()),
- Err(error) => {
- create_response_vector(true, format!("Failed to sign out: {}", error))
+pub fn sign_out(secret_key: String) -> Vec {
+ let runtime = TOKIO_RUNTIME.clone();
+ runtime.block_on(async {
+ let client = PUBKY_CLIENT.clone();
+ let keypair = match get_keypair_from_secret_key(&secret_key) {
+ Ok(keypair) => keypair,
+ Err(error) => return create_response_vector(true, error),
+ };
+ match client.signout(&keypair.public_key()).await {
+ Ok(_) => create_response_vector(false, "Sign out success".to_string()),
+ Err(error) => {
+ create_response_vector(true, format!("Failed to sign out: {}", error))
+ }
}
- }
+ })
}
#[uniffi::export]
-pub async fn put(url: String, content: String) -> Vec {
- let client = PUBKY_CLIENT.clone();
- let parsed_url = match Url::parse(&url) {
- Ok(url) => url,
- Err(_) => return create_response_vector(true, "Failed to parse URL".to_string()),
- };
- match client.put(parsed_url, &content.as_bytes()).await {
- Ok(_) => create_response_vector(false, "Put success".to_string()),
- Err(error) => {
- create_response_vector(true, format!("Failed to put: {}", error))
+pub fn put(url: String, content: String) -> Vec {
+ let runtime = TOKIO_RUNTIME.clone();
+ runtime.block_on(async {
+ let client = PUBKY_CLIENT.clone();
+ let trimmed_url = url.trim_end_matches('/');
+ let parsed_url = match Url::parse(&trimmed_url) {
+ Ok(url) => url,
+ Err(_) => return create_response_vector(true, "Failed to parse URL".to_string()),
+ };
+ match client.put(parsed_url, &content.as_bytes()).await {
+ Ok(_) => create_response_vector(false, trimmed_url.to_string()),
+ Err(error) => {
+ create_response_vector(true, format!("Failed to put: {}", error))
+ }
}
- }
+ })
}
#[uniffi::export]
-pub async fn get(url: String) -> Vec {
- let client = PUBKY_CLIENT.clone();
- let parsed_url = match Url::parse(&url) {
- Ok(url) => url,
- Err(_) => return create_response_vector(true, "Failed to parse URL".to_string()),
- };
- match client.get(parsed_url).await {
- Ok(_) => create_response_vector(false, "Get success".to_string()),
- Err(error) => {
- create_response_vector(true, format!("Failed to get: {}", error))
- }
- }
+pub fn get(url: String) -> Vec {
+ let runtime = TOKIO_RUNTIME.clone();
+ runtime.block_on(async {
+ let client = PUBKY_CLIENT.clone();
+ let trimmed_url = url.trim_end_matches('/');
+ let parsed_url = match Url::parse(&trimmed_url) {
+ Ok(url) => url,
+ Err(_) => return create_response_vector(true, "Failed to parse URL".to_string()),
+ };
+ let result: Option = match client.get(parsed_url).await {
+ Ok(res) => res,
+ Err(_) => return create_response_vector(true, "Request failed".to_string()),
+ };
+ let bytes = match result {
+ Some(bytes) => bytes,
+ None => return create_response_vector(true, "No data returned".to_string()),
+ };
+ let string = match str::from_utf8(&bytes) {
+ Ok(s) => s.to_string(),
+ Err(_) => return create_response_vector(true, "Invalid UTF-8 sequence".to_string()),
+ };
+ create_response_vector(false, string)
+ })
}
/**
@@ -300,115 +324,122 @@ pub async fn get(url: String) -> Vec {
**/
#[uniffi::export]
pub fn resolve(public_key: String) -> Vec {
- let public_key = match public_key.as_str().try_into() {
- Ok(key) => key,
- Err(e) => return create_response_vector(true, format!("Invalid zbase32 encoded key: {}", e)),
- };
- let client = PKARR_CLIENT.clone();
+ let runtime = TOKIO_RUNTIME.clone();
+ runtime.block_on(async {
+ let public_key = match public_key.as_str().try_into() {
+ Ok(key) => key,
+ Err(e) => return create_response_vector(true, format!("Invalid zbase32 encoded key: {}", e)),
+ };
+ let client = PUBKY_CLIENT.clone();
- match client.resolve(&public_key) {
- Ok(Some(signed_packet)) => {
- // Collect references to ResourceRecords from the signed packet's answers
- let all_records: Vec<&ResourceRecord> = signed_packet.packet().answers.iter().collect();
- // Convert each ResourceRecord to a JSON value, handling errors appropriately
- let json_records: Vec = all_records
- .iter()
- .filter_map(|record| {
- match resource_record_to_json(record) {
- Ok(json_value) => Some(json_value),
- Err(e) => {
- eprintln!("Error converting record to JSON: {}", e);
- None
+ match client.pkarr().resolve(&public_key).await {
+ Ok(Some(signed_packet)) => {
+ // Collect references to ResourceRecords from the signed packet's answers
+ let all_records: Vec<&ResourceRecord> = signed_packet.packet().answers.iter().collect();
+ // Convert each ResourceRecord to a JSON value, handling errors appropriately
+ let json_records: Vec = all_records
+ .iter()
+ .filter_map(|record| {
+ match resource_record_to_json(record) {
+ Ok(json_value) => Some(json_value),
+ Err(e) => {
+ eprintln!("Error converting record to JSON: {}", e);
+ None
+ }
}
- }
- })
- .collect();
+ })
+ .collect();
- let bytes = signed_packet.as_bytes();
- let public_key = &bytes[..32];
- let signature = &bytes[32..96];
- let timestamp = signed_packet.timestamp();
- let dns_packet = &bytes[104..];
- let hex: String = signed_packet.encode_hex();
+ let bytes = signed_packet.as_bytes();
+ let public_key = &bytes[..32];
+ let signature = &bytes[32..96];
+ let timestamp = signed_packet.timestamp();
+ let dns_packet = &bytes[104..];
+ let hex: String = signed_packet.encode_hex();
- let json_obj = json!({
- "signed_packet": hex,
- "public_key": general_purpose::STANDARD.encode(public_key),
- "signature": general_purpose::STANDARD.encode(signature),
- "timestamp": timestamp,
- "last_seen": signed_packet.last_seen(),
- "dns_packet": general_purpose::STANDARD.encode(dns_packet),
- "records": json_records
- });
+ let json_obj = json!({
+ "signed_packet": hex,
+ "public_key": general_purpose::STANDARD.encode(public_key),
+ "signature": general_purpose::STANDARD.encode(signature),
+ "timestamp": timestamp,
+ "last_seen": signed_packet.last_seen(),
+ "dns_packet": general_purpose::STANDARD.encode(dns_packet),
+ "records": json_records
+ });
- let json_str = serde_json::to_string(&json_obj)
- .expect("Failed to convert JSON object to string");
+ let json_str = serde_json::to_string(&json_obj)
+ .expect("Failed to convert JSON object to string");
- create_response_vector(false, json_str)
- },
- Ok(None) => {
- create_response_vector(true, "No signed packet found".to_string())
+ create_response_vector(false, json_str)
+ },
+ Ok(None) => {
+ create_response_vector(true, "No signed packet found".to_string())
+ }
+ Err(e) => {
+ create_response_vector(true, format!("Failed to resolve: {}", e))
+ }
}
- Err(e) => {
- create_response_vector(true, format!("Failed to resolve: {}", e))
- }
- }
+ })
}
#[uniffi::export]
pub fn publish(record_name: String, record_content: String, secret_key: String) -> Vec {
- let client = PKARR_CLIENT.clone();
+ let runtime = TOKIO_RUNTIME.clone();
+ runtime.block_on(async {
+ let client = PUBKY_CLIENT.clone();
- let keypair = match get_keypair_from_secret_key(&secret_key) {
- Ok(keypair) => keypair,
- Err(error) => return create_response_vector(true, error),
- };
+ let keypair = match get_keypair_from_secret_key(&secret_key) {
+ Ok(keypair) => keypair,
+ Err(error) => return create_response_vector(true, error),
+ };
- let mut packet = dns::Packet::new_reply(0);
+ let mut packet = dns::Packet::new_reply(0);
- let dns_name = match dns::Name::new(&record_name) {
- Ok(name) => name,
- Err(e) => return create_response_vector(true, format!("Failed to create DNS name: {}", e)),
- };
+ let dns_name = match dns::Name::new(&record_name) {
+ Ok(name) => name,
+ Err(e) => return create_response_vector(true, format!("Failed to create DNS name: {}", e)),
+ };
- let record_content_str: &str = record_content.as_str();
+ let record_content_str: &str = record_content.as_str();
- let txt_record = match record_content_str.try_into() {
- Ok(value) => RData::TXT(value),
- Err(e) => {
- return create_response_vector(true, format!("Failed to convert string to TXT record: {}", e))
- }
- };
+ let txt_record = match record_content_str.try_into() {
+ Ok(value) => RData::TXT(value),
+ Err(e) => {
+ return create_response_vector(true, format!("Failed to convert string to TXT record: {}", e))
+ }
+ };
- packet.answers.push(dns::ResourceRecord::new(
- dns_name,
- dns::CLASS::IN,
- 30,
- txt_record,
- ));
+ packet.answers.push(dns::ResourceRecord::new(
+ dns_name,
+ dns::CLASS::IN,
+ 30,
+ txt_record,
+ ));
- match SignedPacket::from_packet(&keypair, &packet) {
- Ok(signed_packet) => {
- match client.publish(&signed_packet) {
- Ok(()) => {
- create_response_vector(false, keypair.public_key().to_string())
- }
- Err(e) => {
- create_response_vector(true, format!("Failed to publish: {}", e))
+ match SignedPacket::from_packet(&keypair, &packet) {
+ Ok(signed_packet) => {
+ match client.pkarr().publish(&signed_packet).await {
+ Ok(()) => {
+ create_response_vector(false, keypair.public_key().to_string())
+ }
+ Err(e) => {
+ create_response_vector(true, format!("Failed to publish: {}", e))
+ }
}
}
+ Err(e) => {
+ create_response_vector(true, format!("Failed to create signed packet: {}", e))
+ }
}
- Err(e) => {
- create_response_vector(true, format!("Failed to create signed packet: {}", e))
- }
- }
+ })
}
#[uniffi::export]
pub fn list(url: String) -> Vec {
let runtime = TOKIO_RUNTIME.clone();
runtime.block_on(async {
let client = PUBKY_CLIENT.clone();
- let parsed_url = match Url::parse(&url) {
+ let trimmed_url = url.trim_end_matches('/');
+ let parsed_url = match Url::parse(&trimmed_url) {
Ok(url) => url,
Err(_) => return create_response_vector(true, "Failed to parse URL".to_string()),
};
diff --git a/rust/src/utils.rs b/rust/src/utils.rs
index f85d6b0..58833f7 100644
--- a/rust/src/utils.rs
+++ b/rust/src/utils.rs
@@ -201,3 +201,44 @@ pub fn resource_record_to_json(record: &ResourceRecord) -> Result String {
+ // Construct the base URL
+ let mut url = format!("pubky://{}/pub/{}", public_key, domain);
+
+ // Append each path segment, separated by '/'
+ for segment in path_segments {
+ if !segment.is_empty() {
+ url.push('/');
+ url.push_str(segment);
+ }
+ }
+
+ // Remove trailing slash if present
+ if url.ends_with('/') {
+ url.pop();
+ }
+
+ url
+}
+
+/**
+* Extract everything up to the first instance of "pub/" in a Pubky URL
+*
+* # Arguments
+* * `full_url` - The full URL
+*
+* # Returns
+* * `Some(String)` - The "pub/" part of the URL
+* * `None` - If "pub/" is not found in the URL
+*/
+pub fn get_list_url(full_url: &str) -> Option {
+ if let Some(index) = full_url.find("pub/") {
+ let end_index = index + "pub/".len();
+ let substring = &full_url[..end_index];
+ Some(substring.to_string())
+ } else {
+ // "pub/" not found in the string
+ None
+ }
+}
diff --git a/rust/testing/main.rs b/rust/testing/main.rs
index 0b8e1cf..c37f146 100644
--- a/rust/testing/main.rs
+++ b/rust/testing/main.rs
@@ -2,10 +2,11 @@ use std::string::ToString;
use std::sync::Arc;
use once_cell::sync::Lazy;
use pkarr::{dns, Keypair, PublicKey, SignedPacket};
+use pkarr::bytes::Bytes;
use pkarr::dns::rdata::RData;
-use pkarr::mainline::Testnet;
use pubky::PubkyClient;
use url::Url;
+use std::str;
static PUBKY_CLIENT: Lazy> = Lazy::new(|| {
// let custom_testnet = Testnet {
@@ -43,15 +44,55 @@ static PUBKY_CLIENT: Lazy> = Lazy::new(|| {
const HOMESERVER: &str = "pubky://8pinxxgqs41n4aididenw5apqp1urfmzdztr8jt4abrkdn435ewo";
const SECRET_KEY: &str = "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855";
+fn construct_pubky_url(public_key: &str, domain: &str, path_segments: &[&str]) -> String {
+ // Construct the base URL
+ let mut url = format!("pubky://{}/pub/{}", public_key, domain);
+
+ // Append each path segment, separated by '/'
+ for segment in path_segments {
+ if !segment.is_empty() {
+ url.push('/');
+ url.push_str(segment);
+ }
+ }
+
+ // Remove trailing slash if present
+ if url.ends_with('/') {
+ url.pop();
+ }
+
+ url
+}
+
+fn get_list_url(full_url: &str) -> Option {
+ if let Some(index) = full_url.find("pub/") {
+ // Add length of "pub/" to include it in the substring
+ let end_index = index + "pub/".len();
+ let substring = &full_url[..end_index];
+ Some(substring.to_string())
+ } else {
+ // "pub/" not found in the string
+ None
+ }
+}
+
+
+
+
#[tokio::main]
async fn main() {
let sign_in_res = signin_or_signup(SECRET_KEY, HOMESERVER).await;
- println!("{:?}", sign_in_res);
+ println!("Sign In/Up Response: {:?}", sign_in_res);
// let res = publish("recordname".to_string(), "recordcontent".to_string(), "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855".to_string()).await;
- // println!("{:?}", res);
- let url = "pubky://z4e8s17cou9qmuwen8p1556jzhf1wktmzo6ijsfnri9c4hnrdfty/pub/mydomain.com";
- let putRes = put(url.to_string(), "content".to_string()).await;
- println!("{:?}", putRes);
+ // // println!("{:?}", res);
+ let public_key = &sign_in_res[1];
+ let url = construct_pubky_url(public_key, "mydomain.com", &[]);
+ let put_res = put(&url, &"newcontent".to_string()).await;
+ println!("Put Response: {:?}", put_res);
+ let get_res = get(&url).await;
+ println!("Get Response: {:?}", get_res);
+ let list_res = list(url).await;
+ println!("List Response: {:?}", list_res);
}
pub async fn signin_or_signup(secret_key: &str, homeserver: &str) -> Vec {
@@ -76,7 +117,7 @@ pub async fn sign_up(secret_key: &str, homeserver: &str) -> Vec {
};
match client.signup(&keypair, &homeserver_public_key).await {
- Ok(session) => create_response_vector(false, session.pubky().to_uri_string()),
+ Ok(session) => create_response_vector(false, session.pubky().to_string()),
Err(error) => create_response_vector(true, format!("signup failure: {}", error)),
}
}
@@ -89,7 +130,7 @@ pub async fn sign_in(secret_key: &str) -> Vec {
};
match client.signin(&keypair).await {
Ok(session) => {
- create_response_vector(false, session.pubky().to_uri_string())
+ create_response_vector(false, session.pubky().to_string())
},
Err(error) => {
create_response_vector(true, format!("Failed to sign in: {}", error))
@@ -169,16 +210,73 @@ pub fn create_response_vector(error: bool, data: String) -> Vec {
}
}
-pub async fn put(url: String, content: String) -> Vec {
+pub async fn put(url: &String, content: &String) -> Vec {
let client = PUBKY_CLIENT.clone();
- let parsed_url = match Url::parse(&url) {
+ let trimmed_url = url.trim_end_matches('/');
+ let parsed_url = match Url::parse(&trimmed_url) {
Ok(url) => url,
Err(_) => return create_response_vector(true, "Failed to parse URL".to_string()),
};
match client.put(parsed_url, &content.as_bytes()).await {
- Ok(_) => create_response_vector(false, "put success".to_string()),
+ Ok(_) => create_response_vector(false, trimmed_url.to_string()),
Err(error) => {
create_response_vector(true, format!("Failed to put: {}", error))
}
}
}
+
+pub async fn get(url: &String) -> Vec {
+ let client = PUBKY_CLIENT.clone();
+ let trimmed_url = url.trim_end_matches('/');
+
+ // Parse the URL and return error early if it fails
+ let parsed_url = match Url::parse(&trimmed_url) {
+ Ok(url) => url,
+ Err(_) => return create_response_vector(true, "Failed to parse URL".to_string()),
+ };
+
+ // Perform the request and return error early if no data is returned
+ let result: Option = match client.get(parsed_url).await {
+ Ok(res) => res,
+ Err(_) => return create_response_vector(true, "Request failed".to_string()),
+ };
+
+ // If there are bytes, attempt to convert to UTF-8
+ let bytes = match result {
+ Some(bytes) => bytes,
+ None => return create_response_vector(true, "No data returned".to_string()),
+ };
+
+ // Try to convert bytes to string and return error if it fails
+ let string = match str::from_utf8(&bytes) {
+ Ok(s) => s.to_string(),
+ Err(_) => return create_response_vector(true, "Invalid UTF-8 sequence".to_string()),
+ };
+
+ // If everything is successful, return the formatted response
+ create_response_vector(false, string)
+}
+
+pub async fn list(url: String) -> Vec {
+ let client = PUBKY_CLIENT.clone();
+ let trimmed_url = url.trim_end_matches('/');
+ let parsed_url = match Url::parse(&trimmed_url) {
+ Ok(url) => url,
+ Err(_) => return create_response_vector(true, "Failed to parse URL".to_string()),
+ };
+ let list_builder = match client.list(parsed_url) {
+ Ok(list) => list,
+ Err(error) => return create_response_vector(true, format!("Failed to list: {}", error)),
+ };
+ // Execute the non-Send part synchronously
+ let send_future = list_builder.send();
+ let send_res = match send_future.await {
+ Ok(res) => res,
+ Err(error) => return create_response_vector(true, format!("Failed to send list request: {}", error))
+ };
+ let json_string = match serde_json::to_string(&send_res) {
+ Ok(json) => json,
+ Err(error) => return create_response_vector(true, format!("Failed to serialize JSON: {}", error)),
+ };
+ create_response_vector(false, json_string)
+}
\ No newline at end of file