pakstr 0.0.4 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/android-template/app/build.gradle.kts +3 -0
- package/android-template/app/src/androidTest/java/com/pakstr/app/ExampleInstrumentedTest.kt +8 -3
- package/android-template/app/src/androidTest/java/com/pakstr/app/signer/NostrEventBuilderTest.kt +67 -0
- package/android-template/app/src/androidTest/java/com/pakstr/app/signer/NostrSignatureVerifierTest.kt +43 -0
- package/android-template/app/src/main/AndroidManifest.xml +15 -3
- package/android-template/app/src/main/assets/nip07.js +85 -4
- package/android-template/app/src/main/assets/www/index.html +215 -0
- package/android-template/app/src/main/java/com/pakstr/app/ApplicationClass.kt +2 -0
- package/android-template/app/src/main/java/com/pakstr/app/LocalServer.kt +35 -10
- package/android-template/app/src/main/java/com/pakstr/app/MainActivity.kt +121 -101
- package/android-template/app/src/main/java/com/pakstr/app/ShellRuntime.kt +5 -6
- package/android-template/app/src/main/java/com/pakstr/app/WebViewController.kt +69 -20
- package/android-template/app/src/main/java/com/pakstr/app/crypto/Bip340Verifier.kt +318 -0
- package/android-template/app/src/main/java/com/pakstr/app/crypto/CryptoInitializer.kt +34 -0
- package/android-template/app/src/main/java/com/pakstr/app/crypto/Nip04Crypto.kt +33 -0
- package/android-template/app/src/main/java/com/pakstr/app/crypto/NostrEncryption.kt +16 -0
- package/android-template/app/src/main/java/com/pakstr/app/crypto/NostrEventHasher.kt +100 -0
- package/android-template/app/src/main/java/com/pakstr/app/crypto/NostrEventVerifier.kt +54 -0
- package/android-template/app/src/main/java/com/pakstr/app/crypto/NostrSignatureVerifier.kt +43 -0
- package/android-template/app/src/main/java/com/pakstr/app/crypto/Secp256k1.kt +63 -0
- package/android-template/app/src/main/java/com/pakstr/app/debug/AppDebugLogger.kt +21 -0
- package/android-template/app/src/main/java/com/pakstr/app/signer/AmberSigner.kt +427 -74
- package/android-template/app/src/main/java/com/pakstr/app/signer/BunkerSigner.kt +14 -0
- package/android-template/app/src/main/java/com/pakstr/app/signer/FakeSigner.kt +14 -0
- package/android-template/app/src/main/java/com/pakstr/app/signer/NostrBridge.kt +297 -32
- package/android-template/app/src/main/java/com/pakstr/app/signer/NostrEventBuilder.kt +39 -0
- package/android-template/app/src/main/java/com/pakstr/app/signer/SignerManager.kt +103 -73
- package/android-template/app/src/main/java/com/pakstr/app/signer/SignerType.kt +0 -1
- package/android-template/app/src/main/java/com/pakstr/app/signer/exceptions/SignerUnavailableException.kt +5 -0
- package/android-template/app/src/main/java/com/pakstr/app/signer/interfaces/NostrSigner.kt +10 -0
- package/android-template/app/src/main/res/values/strings.xml +1 -1
- package/package.json +1 -1
|
@@ -1,167 +1,520 @@
|
|
|
1
1
|
package com.pakstr.app.signer
|
|
2
2
|
|
|
3
3
|
import android.app.Activity
|
|
4
|
-
import android.content.
|
|
4
|
+
import android.content.ActivityNotFoundException
|
|
5
5
|
import android.content.Intent
|
|
6
|
+
import android.net.Uri
|
|
6
7
|
import androidx.activity.result.ActivityResult
|
|
8
|
+
import androidx.activity.result.ActivityResultLauncher
|
|
9
|
+
import com.pakstr.app.crypto.NostrEventVerifier
|
|
10
|
+
import com.pakstr.app.debug.AppDebugLogger
|
|
7
11
|
import com.pakstr.app.signer.interfaces.NostrSigner
|
|
8
|
-
import kotlinx.coroutines.CancellableContinuation
|
|
9
12
|
import kotlinx.coroutines.suspendCancellableCoroutine
|
|
13
|
+
import kotlinx.coroutines.withTimeout
|
|
14
|
+
import org.json.JSONObject
|
|
10
15
|
import kotlin.coroutines.resume
|
|
11
16
|
|
|
12
|
-
|
|
17
|
+
/**
|
|
18
|
+
* NIP-07 signer implementation using Amber as an external signer.
|
|
19
|
+
*
|
|
20
|
+
* This class communicates with the Amber app through Android intents.
|
|
21
|
+
* The private key never leaves Amber. This app only sends signing requests
|
|
22
|
+
* and receives public keys or signatures back.
|
|
23
|
+
*
|
|
24
|
+
* Supported operations:
|
|
25
|
+
*
|
|
26
|
+
* - getPublicKey()
|
|
27
|
+
* Requests the user's public key from Amber.
|
|
28
|
+
*
|
|
29
|
+
* - signEvent(eventJson)
|
|
30
|
+
* Sends an unsigned Nostr event to Amber for signing.
|
|
31
|
+
* After receiving the signature, the event ID is generated and the
|
|
32
|
+
* signature is locally verified before returning the signed event.
|
|
33
|
+
*
|
|
34
|
+
* The class uses suspendCancellableCoroutine to bridge the asynchronous
|
|
35
|
+
* Android Activity Result API with Kotlin coroutines.
|
|
36
|
+
*/
|
|
13
37
|
class AmberSigner(
|
|
14
|
-
private val
|
|
15
|
-
private val launchIntent: (Intent) -> Unit
|
|
38
|
+
private val launcher: ActivityResultLauncher<Intent>
|
|
16
39
|
) : NostrSigner {
|
|
17
40
|
|
|
41
|
+
// Stores the current pending signer request.
|
|
42
|
+
// Android intents return results asynchronously, so the callback is used
|
|
43
|
+
// to resume the suspended coroutine when Amber responds.
|
|
44
|
+
private var pendingCallback: ((String) -> Unit)? = null
|
|
45
|
+
private var cachedPubkey: String? = null
|
|
46
|
+
override suspend fun getPublicKey(): String {
|
|
47
|
+
|
|
48
|
+
cachedPubkey?.let {
|
|
18
49
|
|
|
19
|
-
|
|
20
|
-
CancellableContinuation<String>? = null
|
|
50
|
+
return it
|
|
21
51
|
|
|
52
|
+
}
|
|
22
53
|
|
|
54
|
+
return withTimeout(30_000) {
|
|
23
55
|
|
|
24
|
-
|
|
56
|
+
suspendCancellableCoroutine { continuation ->
|
|
25
57
|
|
|
26
|
-
|
|
58
|
+
pendingCallback = { pubkey ->
|
|
27
59
|
|
|
28
|
-
|
|
60
|
+
cachedPubkey = pubkey
|
|
29
61
|
|
|
30
|
-
|
|
62
|
+
if (continuation.isActive) {
|
|
31
63
|
|
|
32
|
-
|
|
64
|
+
continuation.resume(pubkey)
|
|
33
65
|
|
|
34
|
-
|
|
66
|
+
}
|
|
35
67
|
|
|
36
|
-
|
|
68
|
+
}
|
|
37
69
|
|
|
38
|
-
|
|
70
|
+
val intent = Intent(
|
|
39
71
|
|
|
40
|
-
|
|
72
|
+
Intent.ACTION_VIEW
|
|
41
73
|
|
|
42
|
-
|
|
74
|
+
).apply {
|
|
43
75
|
|
|
44
|
-
|
|
76
|
+
data = Uri.parse(
|
|
45
77
|
|
|
46
|
-
|
|
78
|
+
"nostrsigner:?type=get_public_key"
|
|
79
|
+
|
|
80
|
+
)
|
|
47
81
|
|
|
48
|
-
|
|
49
|
-
activities.forEach {
|
|
82
|
+
putExtra(
|
|
50
83
|
|
|
51
|
-
|
|
84
|
+
"type",
|
|
52
85
|
|
|
53
|
-
"
|
|
86
|
+
"get_public_key"
|
|
54
87
|
|
|
55
88
|
)
|
|
56
89
|
|
|
57
90
|
}
|
|
58
|
-
pendingPublicKey = null
|
|
59
91
|
|
|
60
|
-
|
|
92
|
+
try {
|
|
61
93
|
|
|
62
|
-
|
|
94
|
+
launcher.launch(intent)
|
|
63
95
|
|
|
64
|
-
|
|
96
|
+
} catch (_: ActivityNotFoundException) {
|
|
65
97
|
|
|
66
|
-
|
|
98
|
+
if (continuation.isActive) {
|
|
67
99
|
|
|
68
|
-
)
|
|
100
|
+
continuation.resume("")
|
|
69
101
|
|
|
70
|
-
|
|
102
|
+
}
|
|
71
103
|
|
|
72
|
-
|
|
104
|
+
}
|
|
73
105
|
|
|
74
|
-
|
|
106
|
+
continuation.invokeOnCancellation {
|
|
75
107
|
|
|
76
|
-
|
|
108
|
+
pendingCallback = null
|
|
77
109
|
|
|
78
|
-
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
}
|
|
79
113
|
|
|
80
114
|
}
|
|
81
115
|
|
|
82
116
|
}
|
|
83
117
|
|
|
118
|
+
override suspend fun signEvent(
|
|
119
|
+
eventJson: String
|
|
120
|
+
): String =
|
|
84
121
|
|
|
122
|
+
withTimeout(30_000) {
|
|
85
123
|
|
|
86
|
-
|
|
87
|
-
result: ActivityResult
|
|
88
|
-
) {
|
|
124
|
+
suspendCancellableCoroutine { continuation ->
|
|
89
125
|
|
|
90
|
-
|
|
126
|
+
val event = JSONObject(eventJson)
|
|
127
|
+
|
|
128
|
+
pendingCallback = { signature ->
|
|
91
129
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
130
|
+
if (signature.isEmpty()) {
|
|
131
|
+
|
|
132
|
+
if (continuation.isActive) {
|
|
133
|
+
|
|
134
|
+
continuation.resume("")
|
|
135
|
+
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
} else {
|
|
139
|
+
|
|
140
|
+
val signedEvent =
|
|
141
|
+
|
|
142
|
+
NostrEventBuilder.addId(event)
|
|
143
|
+
.apply {
|
|
144
|
+
|
|
145
|
+
put(
|
|
146
|
+
"sig", signature
|
|
147
|
+
)
|
|
148
|
+
|
|
149
|
+
}
|
|
150
|
+
// Verify the signed event locally before returning it.
|
|
151
|
+
// This ensures that the received signature matches the event data
|
|
152
|
+
// and protects against invalid signer responses.
|
|
153
|
+
val verified = NostrEventVerifier.verify(signedEvent)
|
|
154
|
+
|
|
155
|
+
AppDebugLogger.log(
|
|
156
|
+
"NOSTR_VERIFY", "Event verified=$verified"
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
if (continuation.isActive) {
|
|
160
|
+
if (verified) {
|
|
161
|
+
continuation.resume(
|
|
162
|
+
signedEvent.toString()
|
|
163
|
+
)
|
|
164
|
+
|
|
165
|
+
} else {
|
|
166
|
+
continuation.resume("")
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
val intent = Intent(
|
|
173
|
+
Intent.ACTION_VIEW, Uri.parse(
|
|
174
|
+
"nostrsigner:${Uri.encode(event.toString())}"
|
|
96
175
|
)
|
|
97
|
-
)
|
|
98
|
-
|
|
176
|
+
).apply {
|
|
177
|
+
putExtra(
|
|
178
|
+
"type", "sign_event"
|
|
179
|
+
)
|
|
180
|
+
}
|
|
181
|
+
try {
|
|
182
|
+
launcher.launch(intent)
|
|
99
183
|
|
|
100
|
-
|
|
184
|
+
} catch (_: ActivityNotFoundException) {
|
|
101
185
|
|
|
102
|
-
|
|
186
|
+
if (continuation.isActive) {
|
|
187
|
+
continuation.resume("")
|
|
188
|
+
}
|
|
189
|
+
}
|
|
103
190
|
|
|
191
|
+
continuation.invokeOnCancellation {
|
|
192
|
+
pendingCallback = null
|
|
193
|
+
}
|
|
194
|
+
}
|
|
104
195
|
}
|
|
105
196
|
|
|
197
|
+
override suspend fun nip04Encrypt(
|
|
198
|
+
pubkey: String,
|
|
199
|
+
plaintext: String
|
|
200
|
+
): String =
|
|
201
|
+
withTimeout(30_000) {
|
|
202
|
+
|
|
203
|
+
suspendCancellableCoroutine { continuation ->
|
|
106
204
|
|
|
107
|
-
|
|
108
|
-
result.data
|
|
109
|
-
?.getStringExtra("pubkey")
|
|
205
|
+
pendingCallback = { encrypted ->
|
|
110
206
|
|
|
207
|
+
if (continuation.isActive) {
|
|
208
|
+
continuation.resume(encrypted)
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
val intent = Intent(
|
|
213
|
+
Intent.ACTION_VIEW
|
|
214
|
+
).apply {
|
|
111
215
|
|
|
112
|
-
|
|
216
|
+
data = Uri.parse(
|
|
217
|
+
"nostrsigner:?type=nip04_encrypt" +
|
|
218
|
+
"&pubkey=$pubkey" +
|
|
219
|
+
"&plaintext=${Uri.encode(plaintext)}"
|
|
220
|
+
)
|
|
113
221
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
222
|
+
putExtra(
|
|
223
|
+
"type",
|
|
224
|
+
"nip04_encrypt"
|
|
225
|
+
)
|
|
117
226
|
|
|
118
|
-
|
|
227
|
+
putExtra(
|
|
228
|
+
"pubkey",
|
|
229
|
+
pubkey
|
|
230
|
+
)
|
|
119
231
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
"No public key returned"
|
|
232
|
+
putExtra(
|
|
233
|
+
"plaintext",
|
|
234
|
+
plaintext
|
|
124
235
|
)
|
|
125
|
-
|
|
126
|
-
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
try {
|
|
239
|
+
|
|
240
|
+
launcher.launch(intent)
|
|
241
|
+
|
|
242
|
+
} catch (_: ActivityNotFoundException) {
|
|
243
|
+
|
|
244
|
+
if (continuation.isActive) {
|
|
245
|
+
continuation.resume("")
|
|
246
|
+
}
|
|
247
|
+
}
|
|
127
248
|
|
|
249
|
+
continuation.invokeOnCancellation {
|
|
250
|
+
pendingCallback = null
|
|
251
|
+
}
|
|
252
|
+
}
|
|
128
253
|
}
|
|
129
254
|
|
|
255
|
+
override suspend fun nip04Decrypt(
|
|
256
|
+
pubkey: String,
|
|
257
|
+
ciphertext: String
|
|
258
|
+
): String = withTimeout(30_000) {
|
|
130
259
|
|
|
131
|
-
|
|
260
|
+
suspendCancellableCoroutine { continuation ->
|
|
132
261
|
|
|
133
|
-
|
|
262
|
+
pendingCallback = { result ->
|
|
134
263
|
|
|
264
|
+
if (continuation.isActive) {
|
|
265
|
+
continuation.resume(result)
|
|
266
|
+
}
|
|
267
|
+
}
|
|
135
268
|
|
|
269
|
+
val intent = Intent(
|
|
270
|
+
Intent.ACTION_VIEW
|
|
271
|
+
).apply {
|
|
136
272
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
273
|
+
data = Uri.parse(
|
|
274
|
+
"nostrsigner:?type=nip04_decrypt" +
|
|
275
|
+
"&pubkey=$pubkey" +
|
|
276
|
+
"&message=${Uri.encode(ciphertext)}"
|
|
277
|
+
)
|
|
278
|
+
|
|
279
|
+
putExtra(
|
|
280
|
+
"type",
|
|
281
|
+
"nip04_decrypt"
|
|
282
|
+
)
|
|
140
283
|
|
|
141
|
-
|
|
284
|
+
putExtra(
|
|
285
|
+
"pubkey",
|
|
286
|
+
pubkey
|
|
287
|
+
)
|
|
142
288
|
|
|
143
|
-
|
|
289
|
+
putExtra(
|
|
290
|
+
"message",
|
|
291
|
+
ciphertext
|
|
292
|
+
)
|
|
293
|
+
}
|
|
144
294
|
|
|
295
|
+
try {
|
|
145
296
|
|
|
297
|
+
launcher.launch(intent)
|
|
298
|
+
|
|
299
|
+
} catch (_: ActivityNotFoundException) {
|
|
300
|
+
|
|
301
|
+
if (continuation.isActive) {
|
|
302
|
+
continuation.resume("")
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
continuation.invokeOnCancellation {
|
|
307
|
+
pendingCallback = null
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
override suspend fun nip44Encrypt(
|
|
146
313
|
|
|
147
|
-
override suspend fun nip04Encrypt(
|
|
148
314
|
pubkey: String,
|
|
315
|
+
|
|
149
316
|
plaintext: String
|
|
150
|
-
): String {
|
|
151
317
|
|
|
152
|
-
|
|
318
|
+
): String =
|
|
153
319
|
|
|
154
|
-
|
|
320
|
+
withTimeout(30_000) {
|
|
155
321
|
|
|
322
|
+
val currentUser = getCachedPublicKey()
|
|
156
323
|
|
|
324
|
+
suspendCancellableCoroutine { continuation ->
|
|
157
325
|
|
|
158
|
-
|
|
326
|
+
pendingCallback = { encrypted ->
|
|
327
|
+
|
|
328
|
+
if (continuation.isActive) {
|
|
329
|
+
|
|
330
|
+
continuation.resume(encrypted)
|
|
331
|
+
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
val intent = Intent(
|
|
337
|
+
|
|
338
|
+
Intent.ACTION_VIEW
|
|
339
|
+
|
|
340
|
+
).apply {
|
|
341
|
+
|
|
342
|
+
data = Uri.parse(
|
|
343
|
+
|
|
344
|
+
"nostrsigner:${Uri.encode(plaintext)}"
|
|
345
|
+
|
|
346
|
+
)
|
|
347
|
+
|
|
348
|
+
putExtra(
|
|
349
|
+
|
|
350
|
+
"type",
|
|
351
|
+
|
|
352
|
+
"nip44_encrypt"
|
|
353
|
+
|
|
354
|
+
)
|
|
355
|
+
|
|
356
|
+
putExtra(
|
|
357
|
+
|
|
358
|
+
"pubkey",
|
|
359
|
+
|
|
360
|
+
pubkey
|
|
361
|
+
|
|
362
|
+
)
|
|
363
|
+
|
|
364
|
+
putExtra(
|
|
365
|
+
|
|
366
|
+
"current_user",
|
|
367
|
+
|
|
368
|
+
currentUser
|
|
369
|
+
|
|
370
|
+
)
|
|
371
|
+
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
try {
|
|
375
|
+
|
|
376
|
+
launcher.launch(intent)
|
|
377
|
+
|
|
378
|
+
} catch (_: ActivityNotFoundException) {
|
|
379
|
+
|
|
380
|
+
if (continuation.isActive) {
|
|
381
|
+
|
|
382
|
+
continuation.resume("")
|
|
383
|
+
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
continuation.invokeOnCancellation {
|
|
389
|
+
|
|
390
|
+
pendingCallback = null
|
|
391
|
+
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
override suspend fun nip44Decrypt(
|
|
159
399
|
pubkey: String,
|
|
160
400
|
ciphertext: String
|
|
161
|
-
): String
|
|
401
|
+
): String =
|
|
402
|
+
withTimeout(30_000) {
|
|
403
|
+
val currentUser = getCachedPublicKey()
|
|
404
|
+
suspendCancellableCoroutine { continuation ->
|
|
405
|
+
|
|
406
|
+
pendingCallback = { result ->
|
|
407
|
+
|
|
408
|
+
if (continuation.isActive) {
|
|
409
|
+
continuation.resume(result)
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
val intent = Intent(
|
|
414
|
+
Intent.ACTION_VIEW
|
|
415
|
+
).apply {
|
|
416
|
+
|
|
417
|
+
data = Uri.parse(
|
|
418
|
+
"nostrsigner:${Uri.encode(ciphertext)}"
|
|
419
|
+
)
|
|
162
420
|
|
|
163
|
-
|
|
421
|
+
putExtra(
|
|
422
|
+
"type",
|
|
423
|
+
"nip44_decrypt"
|
|
424
|
+
)
|
|
164
425
|
|
|
426
|
+
putExtra(
|
|
427
|
+
"pubkey",
|
|
428
|
+
pubkey
|
|
429
|
+
)
|
|
430
|
+
|
|
431
|
+
putExtra(
|
|
432
|
+
"current_user",
|
|
433
|
+
currentUser
|
|
434
|
+
)
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
|
|
438
|
+
AppDebugLogger.log(
|
|
439
|
+
"NIP44",
|
|
440
|
+
"decrypt sender=$pubkey current=$pubkey length=${ciphertext.length}"
|
|
441
|
+
)
|
|
442
|
+
|
|
443
|
+
|
|
444
|
+
try {
|
|
445
|
+
|
|
446
|
+
launcher.launch(intent)
|
|
447
|
+
|
|
448
|
+
} catch (_: ActivityNotFoundException) {
|
|
449
|
+
|
|
450
|
+
if (continuation.isActive) {
|
|
451
|
+
continuation.resume("")
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
|
|
456
|
+
continuation.invokeOnCancellation {
|
|
457
|
+
pendingCallback = null
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
fun onResult(
|
|
463
|
+
result: ActivityResult
|
|
464
|
+
) {
|
|
465
|
+
|
|
466
|
+
val callback = pendingCallback
|
|
467
|
+
|
|
468
|
+
pendingCallback = null
|
|
469
|
+
|
|
470
|
+
if (result.resultCode != Activity.RESULT_OK) {
|
|
471
|
+
callback?.let {
|
|
472
|
+
it("")
|
|
473
|
+
}
|
|
474
|
+
return
|
|
475
|
+
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
val value =
|
|
479
|
+
|
|
480
|
+
result.data?.getStringExtra("result")
|
|
481
|
+
|
|
482
|
+
?: result.data?.getStringExtra("event")
|
|
483
|
+
|
|
484
|
+
?: result.data?.getStringExtra("signature")
|
|
485
|
+
|
|
486
|
+
?: result.data?.getStringExtra("plaintext")
|
|
487
|
+
|
|
488
|
+
?: result.data?.getStringExtra("message")
|
|
489
|
+
?: result.data?.getStringExtra("content")
|
|
490
|
+
|
|
491
|
+
?: ""
|
|
492
|
+
|
|
493
|
+
AppDebugLogger.log(
|
|
494
|
+
|
|
495
|
+
"AMBER_RESULT",
|
|
496
|
+
|
|
497
|
+
value
|
|
498
|
+
|
|
499
|
+
)
|
|
500
|
+
AppDebugLogger.log(
|
|
501
|
+
|
|
502
|
+
"AMBER_RESULT_KEYS",
|
|
503
|
+
|
|
504
|
+
result.data?.extras?.keySet()?.joinToString()
|
|
505
|
+
|
|
506
|
+
?: "NO_KEYS"
|
|
507
|
+
|
|
508
|
+
)
|
|
509
|
+
|
|
510
|
+
callback?.invoke(
|
|
511
|
+
value
|
|
512
|
+
)
|
|
165
513
|
}
|
|
166
514
|
|
|
515
|
+
private suspend fun getCachedPublicKey(): String {
|
|
516
|
+
|
|
517
|
+
return cachedPubkey ?: getPublicKey()
|
|
518
|
+
|
|
519
|
+
}
|
|
167
520
|
}
|
|
@@ -25,4 +25,18 @@ class BunkerSigner(context: Context) : NostrSigner {
|
|
|
25
25
|
): String {
|
|
26
26
|
TODO("Not yet implemented")
|
|
27
27
|
}
|
|
28
|
+
|
|
29
|
+
override suspend fun nip44Encrypt(
|
|
30
|
+
pubkey: String,
|
|
31
|
+
plaintext: String
|
|
32
|
+
): String {
|
|
33
|
+
TODO("Not yet implemented")
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
override suspend fun nip44Decrypt(
|
|
37
|
+
pubkey: String,
|
|
38
|
+
ciphertext: String
|
|
39
|
+
): String {
|
|
40
|
+
TODO("Not yet implemented")
|
|
41
|
+
}
|
|
28
42
|
}
|
|
@@ -28,4 +28,18 @@ class FakeSigner : NostrSigner {
|
|
|
28
28
|
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
+
override suspend fun nip44Encrypt(
|
|
32
|
+
pubkey: String,
|
|
33
|
+
plaintext: String
|
|
34
|
+
): String {
|
|
35
|
+
TODO("Not yet implemented")
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
override suspend fun nip44Decrypt(
|
|
39
|
+
pubkey: String,
|
|
40
|
+
ciphertext: String
|
|
41
|
+
): String {
|
|
42
|
+
TODO("Not yet implemented")
|
|
43
|
+
}
|
|
44
|
+
|
|
31
45
|
}
|