The Pubky Core Mobile SDK provides native bindings for iOS and Android platforms to interact with Pubky. This SDK allows you to perform operations like publishing content, retrieving data and managing authentication.
./build.sh all
./build.sh ios
./build.sh android
./build.sh python
cargo test -- --test-threads=1
-
Add the XCFramework to your Xcode project:
- Drag bindings/ios/PubkyCore.xcframework into your Xcode project Ensure "Copy items if needed" is checked Add the framework to your target
-
Copy the Swift bindings:
- Add bindings/ios/pubkycore.swift to your project
import PubkyCore
class PubkyManager {
// Generate a new secret key
func generateNewAccount() throws -> String {
let result = try generateSecretKey()
guard let jsonData = result[1].data(using: .utf8),
let json = try? JSONSerialization.jsonObject(with: jsonData) as? [String: Any],
let secretKey = json["secret_key"] as? String else {
throw NSError(domain: "PubkyError", code: -1, userInfo: [NSLocalizedDescriptionKey: "Failed to parse response"])
}
return secretKey
}
// Sign up with a homeserver
func signUp(secretKey: String, homeserver: String) async throws -> String {
let result = try signUp(secretKey: secretKey, homeserver: homeserver)
if result[0] == "error" {
throw NSError(domain: "PubkyError", code: -1, userInfo: [NSLocalizedDescriptionKey: result[1]])
}
return result[1]
}
// Publish content
func publishContent(recordName: String, content: String, secretKey: String) async throws -> String {
let result = try publish(recordName: recordName, recordContent: content, secretKey: secretKey)
if result[0] == "error" {
throw NSError(domain: "PubkyError", code: -1, userInfo: [NSLocalizedDescriptionKey: result[1]])
}
return result[1]
}
// Retrieve content
func getContent(url: String) async throws -> String {
let result = try get(url: url)
if result[0] == "error" {
throw NSError(domain: "PubkyError", code: -1, userInfo: [NSLocalizedDescriptionKey: result[1]])
}
return result[1]
}
}
class ViewController: UIViewController {
let pubkyManager = PubkyManager()
func setupAccount() async {
do {
// Generate new account
let secretKey = try pubkyManager.generateNewAccount()
// Sign up with homeserver
let homeserver = "pubky://8pinxxgqs41n4aididenw5apqp1urfmzdztr8jt4abrkdn435ewo"
let publicKey = try await pubkyManager.signUp(secretKey: secretKey, homeserver: homeserver)
// Publish content
let content = "Hello, Pubky!"
let recordName = "example.com"
let publishResult = try await pubkyManager.publishContent(
recordName: recordName,
content: content,
secretKey: secretKey
)
print("Published with public key: \(publishResult)")
} catch {
print("Error: \(error.localizedDescription)")
}
}
}
-
Add the JNI libraries to your project:
- Copy the contents of bindings/android/jniLibs to your project's app/src/main/jniLibs directory
-
Add the Kotlin bindings:
- Copy bindings/android/pubkycore.kt to your project's source directory
class PubkyManager {
init {
// Initialize the library
System.loadLibrary("pubkycore")
}
fun generateNewAccount(): String {
val result = generateSecretKey()
if (result[0] == "error") {
throw Exception(result[1])
}
val json = JSONObject(result[1])
return json.getString("secret_key")
}
suspend fun signUp(secretKey: String, homeserver: String): String {
val result = signUp(secretKey, homeserver)
if (result[0] == "error") {
throw Exception(result[1])
}
return result[1]
}
suspend fun publishContent(recordName: String, content: String, secretKey: String): String {
val result = publish(recordName, content, secretKey)
if (result[0] == "error") {
throw Exception(result[1])
}
return result[1]
}
suspend fun getContent(url: String): String {
val result = get(url)
if (result[0] == "error") {
throw Exception(result[1])
}
return result[1]
}
}
class MainActivity : AppCompatActivity() {
private val pubkyManager = PubkyManager()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
lifecycleScope.launch {
try {
// Generate new account
val secretKey = pubkyManager.generateNewAccount()
// Sign up with homeserver
val homeserver = "pubky://8pinxxgqs41n4aididenw5apqp1urfmzdztr8jt4abrkdn435ewo"
val publicKey = pubkyManager.signUp(secretKey, homeserver)
// Publish content
val content = "Hello, Pubky!"
val recordName = "example.com"
val publishResult = pubkyManager.publishContent(
recordName = recordName,
content = content,
secretKey = secretKey
)
Log.d("Pubky", "Published with public key: $publishResult")
} catch (e: Exception) {
Log.e("Pubky", "Error: ${e.message}")
}
}
}
}
// iOS
func publishHttps(recordName: String, target: String, secretKey: String) async throws -> String {
let result = try publishHttps(recordName: recordName, target: target, secretKey: secretKey)
if result[0] == "error" {
throw NSError(domain: "PubkyError", code: -1, userInfo: [NSLocalizedDescriptionKey: result[1]])
}
return result[1]
}
// Android
suspend fun publishHttps(recordName: String, target: String, secretKey: String): String {
val result = publishHttps(recordName, target, secretKey)
if (result[0] == "error") {
throw Exception(result[1])
}
return result[1]
}
// iOS
func createRecoveryFile(secretKey: String, passphrase: String) throws -> String {
let result = try createRecoveryFile(secretKey: secretKey, passphrase: passphrase)
if result[0] == "error" {
throw NSError(domain: "PubkyError", code: -1, userInfo: [NSLocalizedDescriptionKey: result[1]])
}
return result[1]
}
// Android
fun createRecoveryFile(secretKey: String, passphrase: String): String {
val result = createRecoveryFile(secretKey, passphrase)
if (result[0] == "error") {
throw Exception(result[1])
}
return result[1]
}
All methods return a Vec<String>
where:
- The first element ([0]) is either "success" or "error"
- The second element ([1]) contains either the result data or error message
It's recommended to wrap all calls in try-catch blocks and handle errors appropriately in your application.
You can switch between default and testnet:
// iOS
try switchNetwork(useTestnet: true) // For testnet
try switchNetwork(useTestnet: false) // For default
// Android
switchNetwork(true) // For testnet
switchNetwork(false) // For default