refactor: get signup token

Upgrades bindings.
Adds and implements getSignupToken.
Adds signupToken param to signUp method.
Update README.md.
This commit is contained in:
coreyphillips
2025-02-28 10:20:49 -05:00
parent 1a990ce7cf
commit bd5432378f
18 changed files with 220 additions and 23 deletions

View File

@@ -16,7 +16,8 @@ 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] [getSignupToken](#getSignupToken): Get a signup token from a homeserver with admin credentials.
- [x] [signUp](#signUp): Sign-up to a homeserver and update Pkarr accordingly, with optional signup token support.
- [x] [signIn](#signIn): Sign-in to a homeserver.
- [x] [session](#session): Check the current session for a given Pubky in its homeserver.
- [x] [signOut](#signOut): Sign-out from a homeserver.
@@ -28,7 +29,6 @@ npm install @synonymdev/react-native-pubky
- [x] [getPublicKeyFromSecretKey](#getPublicKeyFromSecretKey): Get the public key string and uri from a secret key.
- [x] [create_recovery_file](#createRecoveryFile): Create a recovery file.
- [x] [decrypt_recovery_file](#decryptRecoveryFile): Decrypt a recovery file.
## Usage
### <a name="auth"></a>Auth
```js
@@ -196,10 +196,26 @@ if (getPublicKeyFromSecretKeyRes.isErr()) {
console.log(getPublicKeyFromSecretKeyRes.value);
```
### <a name="getSignupToken"></a>getSignupToken
```js
import { getSignupToken } from '@synonymdev/react-native-pubky';
const getSignupTokenRes = await getSignupToken(
'8pinxxgqs41n4aididenw5apqp1urfmzdztr8jt4abrkdn435ewo', // Homeserver pubky
'admin_password' // Admin Password
);
if (getSignupTokenRes.isErr()) {
console.log(getSignupTokenRes.error.message);
return;
}
console.log('Signup Token:', getSignupTokenRes.value);
```
### <a name="signUp"></a>signUp
```js
import { signUp } from '@synonymdev/react-native-pubky';
// Standard signup
const signUpRes = await signUp(
'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855', // Secret
'pubky://8pinxxgqs41n4aididenw5apqp1urfmzdztr8jt4abrkdn435ewo', // Homeserver
@@ -209,6 +225,18 @@ if (signUpRes.isErr()) {
return;
}
console.log(signUpRes.value);
// Signup with token
const signUpWithTokenRes = await signUp(
'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855', // Secret
'pubky://8pinxxgqs41n4aididenw5apqp1urfmzdztr8jt4abrkdn435ewo', // Homeserver
'your_signup_token' // Optional signup token
);
if (signUpWithTokenRes.isErr()) {
console.log(signUpWithTokenRes.error.message);
return;
}
console.log(signUpWithTokenRes.value);
```
### <a name="signIn"></a>signIn

View File

@@ -168,10 +168,29 @@ class PubkyModule(reactContext: ReactApplicationContext) :
}
@ReactMethod
fun signUp(secretKey: String, homeserver: String, promise: Promise) {
fun getSignupToken(homeserverPubky: String, adminPassword: String, promise: Promise) {
CoroutineScope(Dispatchers.IO).launch {
try {
val result = signUp(secretKey, homeserver)
val result = getSignupToken(homeserverPubky, adminPassword)
val array = Arguments.createArray().apply {
result.forEach { pushString(it) }
}
withContext(Dispatchers.Main) {
promise.resolve(array)
}
} catch (e: Exception) {
withContext(Dispatchers.Main) {
promise.reject("Error", e.message)
}
}
}
}
@ReactMethod
fun signUp(secretKey: String, homeserver: String, signupToken: String, promise: Promise) {
CoroutineScope(Dispatchers.IO).launch {
try {
val result = signUp(secretKey, homeserver, signupToken)
val array = Arguments.createArray().apply {
result.forEach { pushString(it) }
}

View File

@@ -404,6 +404,8 @@ internal interface _UniFFILib : Library {
): RustBuffer.ByValue
fun uniffi_pubkycore_fn_func_get_public_key_from_secret_key(`secretKey`: RustBuffer.ByValue,_uniffi_out_err: RustCallStatus,
): RustBuffer.ByValue
fun uniffi_pubkycore_fn_func_get_signup_token(`homeserverPubky`: RustBuffer.ByValue,`adminPassword`: RustBuffer.ByValue,_uniffi_out_err: RustCallStatus,
): RustBuffer.ByValue
fun uniffi_pubkycore_fn_func_list(`url`: RustBuffer.ByValue,_uniffi_out_err: RustCallStatus,
): RustBuffer.ByValue
fun uniffi_pubkycore_fn_func_parse_auth_url(`url`: RustBuffer.ByValue,_uniffi_out_err: RustCallStatus,
@@ -428,7 +430,7 @@ internal interface _UniFFILib : Library {
): RustBuffer.ByValue
fun uniffi_pubkycore_fn_func_sign_out(`secretKey`: RustBuffer.ByValue,_uniffi_out_err: RustCallStatus,
): RustBuffer.ByValue
fun uniffi_pubkycore_fn_func_sign_up(`secretKey`: RustBuffer.ByValue,`homeserver`: RustBuffer.ByValue,_uniffi_out_err: RustCallStatus,
fun uniffi_pubkycore_fn_func_sign_up(`secretKey`: RustBuffer.ByValue,`homeserver`: RustBuffer.ByValue,`signupToken`: RustBuffer.ByValue,_uniffi_out_err: RustCallStatus,
): RustBuffer.ByValue
fun uniffi_pubkycore_fn_func_switch_network(`useTestnet`: Byte,_uniffi_out_err: RustCallStatus,
): RustBuffer.ByValue
@@ -560,6 +562,8 @@ internal interface _UniFFILib : Library {
): Short
fun uniffi_pubkycore_checksum_func_get_public_key_from_secret_key(
): Short
fun uniffi_pubkycore_checksum_func_get_signup_token(
): Short
fun uniffi_pubkycore_checksum_func_list(
): Short
fun uniffi_pubkycore_checksum_func_parse_auth_url(
@@ -628,6 +632,9 @@ private fun uniffiCheckApiChecksums(lib: _UniFFILib) {
if (lib.uniffi_pubkycore_checksum_func_get_public_key_from_secret_key() != 40316.toShort()) {
throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project")
}
if (lib.uniffi_pubkycore_checksum_func_get_signup_token() != 47927.toShort()) {
throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project")
}
if (lib.uniffi_pubkycore_checksum_func_list() != 43198.toShort()) {
throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project")
}
@@ -664,7 +671,7 @@ private fun uniffiCheckApiChecksums(lib: _UniFFILib) {
if (lib.uniffi_pubkycore_checksum_func_sign_out() != 34903.toShort()) {
throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project")
}
if (lib.uniffi_pubkycore_checksum_func_sign_up() != 37999.toShort()) {
if (lib.uniffi_pubkycore_checksum_func_sign_up() != 48789.toShort()) {
throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project")
}
if (lib.uniffi_pubkycore_checksum_func_switch_network() != 64215.toShort()) {
@@ -1135,6 +1142,35 @@ public object FfiConverterTypeEventListener: FfiConverterCallbackInterface<Event
public object FfiConverterOptionalString: FfiConverterRustBuffer<String?> {
override fun read(buf: ByteBuffer): String? {
if (buf.get().toInt() == 0) {
return null
}
return FfiConverterString.read(buf)
}
override fun allocationSize(value: String?): Int {
if (value == null) {
return 1
} else {
return 1 + FfiConverterString.allocationSize(value)
}
}
override fun write(value: String?, buf: ByteBuffer) {
if (value == null) {
buf.put(0)
} else {
buf.put(1)
FfiConverterString.write(value, buf)
}
}
}
public object FfiConverterSequenceString: FfiConverterRustBuffer<List<String>> {
override fun read(buf: ByteBuffer): List<String> {
val len = buf.getInt()
@@ -1213,6 +1249,14 @@ fun `getPublicKeyFromSecretKey`(`secretKey`: String): List<String> {
}
fun `getSignupToken`(`homeserverPubky`: String, `adminPassword`: String): List<String> {
return FfiConverterSequenceString.lift(
rustCall() { _status ->
_UniFFILib.INSTANCE.uniffi_pubkycore_fn_func_get_signup_token(FfiConverterString.lower(`homeserverPubky`),FfiConverterString.lower(`adminPassword`),_status)
})
}
fun `list`(`url`: String): List<String> {
return FfiConverterSequenceString.lift(
rustCall() { _status ->
@@ -1309,10 +1353,10 @@ fun `signOut`(`secretKey`: String): List<String> {
}
fun `signUp`(`secretKey`: String, `homeserver`: String): List<String> {
fun `signUp`(`secretKey`: String, `homeserver`: String, `signupToken`: String?): List<String> {
return FfiConverterSequenceString.lift(
rustCall() { _status ->
_UniFFILib.INSTANCE.uniffi_pubkycore_fn_func_sign_up(FfiConverterString.lower(`secretKey`),FfiConverterString.lower(`homeserver`),_status)
_UniFFILib.INSTANCE.uniffi_pubkycore_fn_func_sign_up(FfiConverterString.lower(`secretKey`),FfiConverterString.lower(`homeserver`),FfiConverterOptionalString.lower(`signupToken`),_status)
})
}

View File

@@ -1237,7 +1237,7 @@ PODS:
- ReactCommon/turbomodule/bridging
- ReactCommon/turbomodule/core
- Yoga
- react-native-pubky (0.9.5):
- react-native-pubky (0.10.0):
- DoubleConversion
- glog
- hermes-engine
@@ -1757,7 +1757,7 @@ SPEC CHECKSUMS:
React-logger: 4072f39df335ca443932e0ccece41fbeb5ca8404
React-Mapbuffer: 714f2fae68edcabfc332b754e9fbaa8cfc68fdd4
React-microtasksnativemodule: 4943ad8f99be8ccf5a63329fa7d269816609df9e
react-native-pubky: 7c1f0436da7e93cd17fc7aa22ff3f89c6cb3445d
react-native-pubky: f45bed8e9a6ccbb350c2e40131be2e92d394722c
React-nativeconfig: 4a9543185905fe41014c06776bf126083795aed9
React-NativeModulesApple: 0506da59fc40d2e1e6e12a233db5e81c46face27
React-perflogger: 3bbb82f18e9ac29a1a6931568e99d6305ef4403b

View File

@@ -21,6 +21,7 @@ import {
removeEventListener,
session,
deleteFile,
getSignupToken,
} from '@synonymdev/react-native-pubky';
const HOMESERVER = '8pinxxgqs41n4aididenw5apqp1urfmzdztr8jt4abrkdn435ewo';
@@ -131,13 +132,36 @@ export default function App() {
}
}}
/>
<Button
title={'Get Signup Token'}
onPress={async (): Promise<void> => {
try {
const res = await getSignupToken(
HOMESERVER, // Homeserver pubky
'admin_password' // Admin Password
);
if (res.isErr()) {
console.log(res.error);
return;
}
console.log('Signup Token:', res.value);
// Store this token for use with signUpWithToken
} catch (e) {
console.log(e);
}
}}
/>
<Button
title={'signup'}
onPress={async (): Promise<void> => {
try {
const signupToken = 'signup_token';
const res = await signUp(
SECRET_KEY, // Secret Key
`pubky://${HOMESERVER}` // Homeserver
`pubky://${HOMESERVER}`, // Homeserver
signupToken
);
if (res.isErr()) {
console.log(res.error.message);

View File

@@ -82,6 +82,8 @@ RustBuffer uniffi_pubkycore_fn_func_get(RustBuffer url, RustCallStatus *_Nonnull
);
RustBuffer uniffi_pubkycore_fn_func_get_public_key_from_secret_key(RustBuffer secret_key, RustCallStatus *_Nonnull out_status
);
RustBuffer uniffi_pubkycore_fn_func_get_signup_token(RustBuffer homeserver_pubky, RustBuffer admin_password, RustCallStatus *_Nonnull out_status
);
RustBuffer uniffi_pubkycore_fn_func_list(RustBuffer url, RustCallStatus *_Nonnull out_status
);
RustBuffer uniffi_pubkycore_fn_func_parse_auth_url(RustBuffer url, RustCallStatus *_Nonnull out_status
@@ -107,7 +109,7 @@ RustBuffer uniffi_pubkycore_fn_func_sign_in(RustBuffer secret_key, RustCallStatu
);
RustBuffer uniffi_pubkycore_fn_func_sign_out(RustBuffer secret_key, RustCallStatus *_Nonnull out_status
);
RustBuffer uniffi_pubkycore_fn_func_sign_up(RustBuffer secret_key, RustBuffer homeserver, RustCallStatus *_Nonnull out_status
RustBuffer uniffi_pubkycore_fn_func_sign_up(RustBuffer secret_key, RustBuffer homeserver, RustBuffer signup_token, RustCallStatus *_Nonnull out_status
);
RustBuffer uniffi_pubkycore_fn_func_switch_network(int8_t use_testnet, RustCallStatus *_Nonnull out_status
);
@@ -245,6 +247,9 @@ uint16_t uniffi_pubkycore_checksum_func_get(void
);
uint16_t uniffi_pubkycore_checksum_func_get_public_key_from_secret_key(void
);
uint16_t uniffi_pubkycore_checksum_func_get_signup_token(void
);
uint16_t uniffi_pubkycore_checksum_func_list(void

View File

@@ -82,6 +82,8 @@ RustBuffer uniffi_pubkycore_fn_func_get(RustBuffer url, RustCallStatus *_Nonnull
);
RustBuffer uniffi_pubkycore_fn_func_get_public_key_from_secret_key(RustBuffer secret_key, RustCallStatus *_Nonnull out_status
);
RustBuffer uniffi_pubkycore_fn_func_get_signup_token(RustBuffer homeserver_pubky, RustBuffer admin_password, RustCallStatus *_Nonnull out_status
);
RustBuffer uniffi_pubkycore_fn_func_list(RustBuffer url, RustCallStatus *_Nonnull out_status
);
RustBuffer uniffi_pubkycore_fn_func_parse_auth_url(RustBuffer url, RustCallStatus *_Nonnull out_status
@@ -107,7 +109,7 @@ RustBuffer uniffi_pubkycore_fn_func_sign_in(RustBuffer secret_key, RustCallStatu
);
RustBuffer uniffi_pubkycore_fn_func_sign_out(RustBuffer secret_key, RustCallStatus *_Nonnull out_status
);
RustBuffer uniffi_pubkycore_fn_func_sign_up(RustBuffer secret_key, RustBuffer homeserver, RustCallStatus *_Nonnull out_status
RustBuffer uniffi_pubkycore_fn_func_sign_up(RustBuffer secret_key, RustBuffer homeserver, RustBuffer signup_token, RustCallStatus *_Nonnull out_status
);
RustBuffer uniffi_pubkycore_fn_func_switch_network(int8_t use_testnet, RustCallStatus *_Nonnull out_status
);
@@ -245,6 +247,9 @@ uint16_t uniffi_pubkycore_checksum_func_get(void
);
uint16_t uniffi_pubkycore_checksum_func_get_public_key_from_secret_key(void
);
uint16_t uniffi_pubkycore_checksum_func_get_signup_token(void
);
uint16_t uniffi_pubkycore_checksum_func_list(void

View File

@@ -36,8 +36,14 @@ RCT_EXTERN_METHOD(resolve:(NSString *)publicKey
withResolver:(RCTPromiseResolveBlock)resolve
withRejecter:(RCTPromiseRejectBlock)reject)
RCT_EXTERN_METHOD(getSignupToken:(NSString *)homeserverPubky
adminPassword:(NSString *)adminPassword
withResolver:(RCTPromiseResolveBlock)resolve
withRejecter:(RCTPromiseRejectBlock)reject)
RCT_EXTERN_METHOD(signUp:(NSString *)secretKey
homeserver:(NSString *)homeserver
signupToken:(NSString *)signupToken
withResolver:(RCTPromiseResolveBlock)resolve
withRejecter:(RCTPromiseRejectBlock)reject)

View File

@@ -87,11 +87,23 @@ class Pubky: RCTEventEmitter {
}
}
@objc(signUp:homeserver:withResolver:withRejecter:)
func signUp(_ secretKey: String, homeserver: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
@objc(getSignupToken:adminPassword:withResolver:withRejecter:)
func getSignupToken(_ homeserverPubky: String, adminPassword: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
Task {
do {
let result = try await react_native_pubky.signUp(secretKey: secretKey, homeserver: homeserver)
let result = try await react_native_pubky.getSignupToken(homeserverPubky: homeserverPubky, adminPassword: adminPassword)
resolve(result)
} catch {
reject("getSignupToken Error", "Failed to get signup token", error)
}
}
}
@objc(signUp:homeserver:signupToken:withResolver:withRejecter:)
func signUp(_ secretKey: String, homeserver: String, signupToken: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
Task {
do {
let result = try await react_native_pubky.signUp(secretKey: secretKey, homeserver: homeserver, signupToken: signupToken)
resolve(result)
} catch {
reject("signUp Error", "Failed to sign up", error)

View File

@@ -590,6 +590,27 @@ extension FfiConverterCallbackInterfaceEventListener : FfiConverter {
}
}
fileprivate struct FfiConverterOptionString: FfiConverterRustBuffer {
typealias SwiftType = String?
public static func write(_ value: SwiftType, into buf: inout [UInt8]) {
guard let value = value else {
writeInt(&buf, Int8(0))
return
}
writeInt(&buf, Int8(1))
FfiConverterString.write(value, into: &buf)
}
public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> SwiftType {
switch try readInt(&buf) as Int8 {
case 0: return nil
case 1: return try FfiConverterString.read(from: &buf)
default: throw UniffiInternalError.unexpectedOptionalTag
}
}
}
fileprivate struct FfiConverterSequenceString: FfiConverterRustBuffer {
typealias SwiftType = [String]
@@ -677,6 +698,16 @@ public func getPublicKeyFromSecretKey(secretKey: String) -> [String] {
)
}
public func getSignupToken(homeserverPubky: String, adminPassword: String) -> [String] {
return try! FfiConverterSequenceString.lift(
try! rustCall() {
uniffi_pubkycore_fn_func_get_signup_token(
FfiConverterString.lower(homeserverPubky),
FfiConverterString.lower(adminPassword),$0)
}
)
}
public func list(url: String) -> [String] {
return try! FfiConverterSequenceString.lift(
try! rustCall() {
@@ -789,12 +820,13 @@ public func signOut(secretKey: String) -> [String] {
)
}
public func signUp(secretKey: String, homeserver: String) -> [String] {
public func signUp(secretKey: String, homeserver: String, signupToken: String?) -> [String] {
return try! FfiConverterSequenceString.lift(
try! rustCall() {
uniffi_pubkycore_fn_func_sign_up(
FfiConverterString.lower(secretKey),
FfiConverterString.lower(homeserver),$0)
FfiConverterString.lower(homeserver),
FfiConverterOptionString.lower(signupToken),$0)
}
)
}
@@ -844,6 +876,9 @@ private var initializationResult: InitializationResult {
if (uniffi_pubkycore_checksum_func_get_public_key_from_secret_key() != 40316) {
return InitializationResult.apiChecksumMismatch
}
if (uniffi_pubkycore_checksum_func_get_signup_token() != 47927) {
return InitializationResult.apiChecksumMismatch
}
if (uniffi_pubkycore_checksum_func_list() != 43198) {
return InitializationResult.apiChecksumMismatch
}
@@ -880,7 +915,7 @@ private var initializationResult: InitializationResult {
if (uniffi_pubkycore_checksum_func_sign_out() != 34903) {
return InitializationResult.apiChecksumMismatch
}
if (uniffi_pubkycore_checksum_func_sign_up() != 37999) {
if (uniffi_pubkycore_checksum_func_sign_up() != 48789) {
return InitializationResult.apiChecksumMismatch
}
if (uniffi_pubkycore_checksum_func_switch_network() != 64215) {

View File

@@ -1,6 +1,6 @@
{
"name": "@synonymdev/react-native-pubky",
"version": "0.9.5",
"version": "0.10.0",
"description": "React Native Implementation of Pubky",
"source": "./src/index.tsx",
"main": "./lib/commonjs/index.js",
@@ -54,7 +54,7 @@
"update-remote-bindings:ios": "npm run reinstall && node setup-remote-ios-bindings.js && npm run reinstall",
"update-remote-bindings:android": "npm run reinstall && node setup-remote-android-bindings.js && npm run reinstall",
"update-remote-bindings": "npm run reinstall && npm run update-remote-bindings:ios && npm run update-remote-bindings:android",
"rebuild-remote": "rm -rf node_modules && cd example && rm -rf node_modules && cd ios && rm -rf Pods Podfile.lock build && cd ../../ && yarn install && npm run update-remote-bindings && cd example && yarn install && bundle install && cd ios && pod install && cd ../ && yarn build:ios && yarn ios"
"rebuild-remote": "rm -rf node_modules && cd example && rm -rf node_modules && cd ios && rm -rf Pods Podfile.lock build && cd ../../ && yarn install && npm run update-remote-bindings && cd example && yarn install && bundle install && cd ios && pod install && cd ../ && yarn build:ios && yarn ios --simulator 'iPhone 16 Pro'"
},
"keywords": [
"pubky",

View File

@@ -126,12 +126,31 @@ export async function resolve(publicKey: string): Promise<Result<IDNSPacket>> {
}
}
/*
Returns the signupToken used in signUp
*/
export async function getSignupToken(
homeserverPubky: string,
adminPassword: string
): Promise<Result<string>> {
try {
const res = await Pubky.getSignupToken(homeserverPubky, adminPassword);
if (res[0] === 'error') {
return err(res[1]);
}
return ok(res[1]);
} catch (e) {
return err(JSON.stringify(e));
}
}
export async function signUp(
secretKey: string,
homeserver: string
homeserver: string,
signupToken?: string
): Promise<Result<SessionInfo>> {
try {
const res = await Pubky.signUp(secretKey, homeserver);
const res = await Pubky.signUp(secretKey, homeserver, signupToken);
if (res[0] === 'error') {
return err(res[1]);
}