@qntx/nostr-native 0.0.0-stage → 0.12.1

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.
Files changed (106) hide show
  1. package/LICENSE-APACHE +201 -0
  2. package/LICENSE-MIT +21 -0
  3. package/NostrNative.podspec +37 -0
  4. package/README.md +30 -2
  5. package/android/CMakeLists.txt +38 -0
  6. package/android/build.gradle +136 -0
  7. package/android/gradle.properties +4 -0
  8. package/android/src/main/AndroidManifest.xml +2 -0
  9. package/android/src/main/cpp/cpp-adapter.cpp +7 -0
  10. package/android/src/main/java/com/margelo/nitro/nostrnative/NostrNativePackage.java +29 -0
  11. package/cpp/HybridNostrNative.cpp +52 -0
  12. package/cpp/HybridNostrNative.hpp +22 -0
  13. package/cpp/nostr_core.c +128 -0
  14. package/cpp/nostr_core.h +65 -0
  15. package/cpp/nostr_native.c +54 -0
  16. package/cpp/nostr_native.h +47 -0
  17. package/dist/index.d.mts +15 -0
  18. package/dist/index.mjs +26 -0
  19. package/dist/index.mjs.map +1 -0
  20. package/nitro.json +19 -0
  21. package/nitrogen/generated/.gitattributes +1 -0
  22. package/nitrogen/generated/android/NostrNative+autolinking.cmake +81 -0
  23. package/nitrogen/generated/android/NostrNative+autolinking.gradle +27 -0
  24. package/nitrogen/generated/android/NostrNativeOnLoad.cpp +49 -0
  25. package/nitrogen/generated/android/NostrNativeOnLoad.hpp +34 -0
  26. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nostrnative/NostrNativeOnLoad.kt +35 -0
  27. package/nitrogen/generated/ios/NostrNative+autolinking.rb +62 -0
  28. package/nitrogen/generated/ios/NostrNative-Swift-Cxx-Bridge.cpp +17 -0
  29. package/nitrogen/generated/ios/NostrNative-Swift-Cxx-Bridge.hpp +27 -0
  30. package/nitrogen/generated/ios/NostrNative-Swift-Cxx-Umbrella.hpp +38 -0
  31. package/nitrogen/generated/ios/NostrNativeAutolinking.mm +35 -0
  32. package/nitrogen/generated/ios/NostrNativeAutolinking.swift +16 -0
  33. package/nitrogen/generated/shared/c++/HybridNostrNativeSpec.cpp +23 -0
  34. package/nitrogen/generated/shared/c++/HybridNostrNativeSpec.hpp +64 -0
  35. package/package.json +86 -4
  36. package/react-native.config.js +12 -0
  37. package/vendor/secp256k1/COPYING +19 -0
  38. package/vendor/secp256k1/include/secp256k1.h +931 -0
  39. package/vendor/secp256k1/include/secp256k1_ecdh.h +63 -0
  40. package/vendor/secp256k1/include/secp256k1_ellswift.h +200 -0
  41. package/vendor/secp256k1/include/secp256k1_extrakeys.h +250 -0
  42. package/vendor/secp256k1/include/secp256k1_musig.h +588 -0
  43. package/vendor/secp256k1/include/secp256k1_preallocated.h +134 -0
  44. package/vendor/secp256k1/include/secp256k1_recovery.h +123 -0
  45. package/vendor/secp256k1/include/secp256k1_schnorrsig.h +179 -0
  46. package/vendor/secp256k1/include/secp256k1_silentpayments.h +396 -0
  47. package/vendor/secp256k1/src/assumptions.h +87 -0
  48. package/vendor/secp256k1/src/checkmem.h +117 -0
  49. package/vendor/secp256k1/src/ecdsa.h +21 -0
  50. package/vendor/secp256k1/src/ecdsa_impl.h +309 -0
  51. package/vendor/secp256k1/src/eckey.h +28 -0
  52. package/vendor/secp256k1/src/eckey_impl.h +94 -0
  53. package/vendor/secp256k1/src/ecmult.h +64 -0
  54. package/vendor/secp256k1/src/ecmult_compute_table.h +16 -0
  55. package/vendor/secp256k1/src/ecmult_compute_table_impl.h +49 -0
  56. package/vendor/secp256k1/src/ecmult_const.h +38 -0
  57. package/vendor/secp256k1/src/ecmult_const_impl.h +402 -0
  58. package/vendor/secp256k1/src/ecmult_gen.h +145 -0
  59. package/vendor/secp256k1/src/ecmult_gen_compute_table.h +14 -0
  60. package/vendor/secp256k1/src/ecmult_gen_compute_table_impl.h +108 -0
  61. package/vendor/secp256k1/src/ecmult_gen_impl.h +347 -0
  62. package/vendor/secp256k1/src/ecmult_impl.h +869 -0
  63. package/vendor/secp256k1/src/field.h +351 -0
  64. package/vendor/secp256k1/src/field_10x26.h +57 -0
  65. package/vendor/secp256k1/src/field_10x26_impl.h +1210 -0
  66. package/vendor/secp256k1/src/field_5x52.h +62 -0
  67. package/vendor/secp256k1/src/field_5x52_impl.h +496 -0
  68. package/vendor/secp256k1/src/field_5x52_int128_impl.h +274 -0
  69. package/vendor/secp256k1/src/field_impl.h +457 -0
  70. package/vendor/secp256k1/src/group.h +218 -0
  71. package/vendor/secp256k1/src/group_impl.h +1014 -0
  72. package/vendor/secp256k1/src/hash.h +56 -0
  73. package/vendor/secp256k1/src/hash_impl.h +397 -0
  74. package/vendor/secp256k1/src/hsort.h +33 -0
  75. package/vendor/secp256k1/src/hsort_impl.h +125 -0
  76. package/vendor/secp256k1/src/int128.h +90 -0
  77. package/vendor/secp256k1/src/int128_impl.h +18 -0
  78. package/vendor/secp256k1/src/int128_native.h +19 -0
  79. package/vendor/secp256k1/src/int128_native_impl.h +94 -0
  80. package/vendor/secp256k1/src/int128_struct.h +14 -0
  81. package/vendor/secp256k1/src/int128_struct_impl.h +205 -0
  82. package/vendor/secp256k1/src/modinv32.h +43 -0
  83. package/vendor/secp256k1/src/modinv32_impl.h +725 -0
  84. package/vendor/secp256k1/src/modinv64.h +47 -0
  85. package/vendor/secp256k1/src/modinv64_impl.h +780 -0
  86. package/vendor/secp256k1/src/modules/extrakeys/main_impl.h +292 -0
  87. package/vendor/secp256k1/src/modules/schnorrsig/main_impl.h +256 -0
  88. package/vendor/secp256k1/src/precomputed_ecmult.c +16456 -0
  89. package/vendor/secp256k1/src/precomputed_ecmult.h +40 -0
  90. package/vendor/secp256k1/src/precomputed_ecmult_gen.c +1779 -0
  91. package/vendor/secp256k1/src/precomputed_ecmult_gen.h +28 -0
  92. package/vendor/secp256k1/src/scalar.h +105 -0
  93. package/vendor/secp256k1/src/scalar_4x64.h +19 -0
  94. package/vendor/secp256k1/src/scalar_4x64_impl.h +1005 -0
  95. package/vendor/secp256k1/src/scalar_8x32.h +19 -0
  96. package/vendor/secp256k1/src/scalar_8x32_impl.h +820 -0
  97. package/vendor/secp256k1/src/scalar_impl.h +321 -0
  98. package/vendor/secp256k1/src/scalar_low.h +24 -0
  99. package/vendor/secp256k1/src/scalar_low_impl.h +217 -0
  100. package/vendor/secp256k1/src/scratch.h +44 -0
  101. package/vendor/secp256k1/src/scratch_impl.h +99 -0
  102. package/vendor/secp256k1/src/secp256k1.c +855 -0
  103. package/vendor/secp256k1/src/selftest.h +41 -0
  104. package/vendor/secp256k1/src/util.h +479 -0
  105. package/vendor/secp256k1/src/util_local_visibility.h +12 -0
  106. package/vendor/secp256k1/vendored.json +6 -0
@@ -0,0 +1,128 @@
1
+ /*
2
+ * The vendored libsecp256k1 is compiled as a single translation unit inside this file:
3
+ * secp256k1.c includes every implementation header plus the modules enabled with
4
+ * -DENABLE_MODULE_EXTRAKEYS / -DENABLE_MODULE_SCHNORRSIG, so this TU also sees the library's
5
+ * internal SHA-256 (nostr_native_secp256k1_sha256_*) and
6
+ * nostr_native_secp256k1_memclear_explicit. Those are internal APIs of the pinned vendor tree —
7
+ * the NIST SHA-256 vectors in tests/host guard them.
8
+ *
9
+ * The vendor script prefixes every secp256k1_ identifier with nostr_native_ (see
10
+ * scripts/vendor-secp256k1.ts): React Native pods are statically linked into one binary and an
11
+ * unprefixed libsecp256k1 would collide with any other pod embedding it. This is the only TU
12
+ * that may include secp256k1.c — the two precomputed-table TUs stay separate. It must come
13
+ * before nostr_core.h: secp256k1.c defines SECP256K1_BUILD and refuses to be the second
14
+ * includer of its own public header.
15
+ */
16
+ #include "../vendor/secp256k1/src/secp256k1.c"
17
+ #include "../vendor/secp256k1/include/secp256k1_extrakeys.h"
18
+ #include "../vendor/secp256k1/include/secp256k1_schnorrsig.h"
19
+
20
+ #include "nostr_core.h"
21
+
22
+ void nostr_core_wipe(void *ptr, size_t len) {
23
+ nostr_native_secp256k1_memclear_explicit(ptr, len);
24
+ }
25
+
26
+ int nostr_core_verify(const nostr_native_secp256k1_context *ctx, const unsigned char id[32],
27
+ const unsigned char pubkey[32], const unsigned char sig[64]) {
28
+ nostr_native_secp256k1_xonly_pubkey parsed;
29
+
30
+ if (ctx == NULL || id == NULL || pubkey == NULL || sig == NULL) {
31
+ return NOSTR_CORE_INVALID_INPUT;
32
+ }
33
+ if (!nostr_native_secp256k1_xonly_pubkey_parse(ctx, &parsed, pubkey)) {
34
+ return NOSTR_CORE_INVALID_INPUT;
35
+ }
36
+ return nostr_native_secp256k1_schnorrsig_verify(ctx, sig, id, 32, &parsed)
37
+ ? NOSTR_CORE_OK
38
+ : NOSTR_CORE_VERIFY_FAILED;
39
+ }
40
+
41
+ int nostr_core_verify_serialized(const nostr_native_secp256k1_context *ctx,
42
+ const unsigned char *serialized, size_t len,
43
+ const unsigned char id[32], const unsigned char pubkey[32],
44
+ const unsigned char sig[64]) {
45
+ unsigned char digest[32];
46
+ nostr_native_secp256k1_sha256 sha;
47
+ const nostr_native_secp256k1_hash_ctx *hash_ctx;
48
+ size_t i;
49
+
50
+ if (ctx == NULL || serialized == NULL || id == NULL || pubkey == NULL || sig == NULL) {
51
+ return NOSTR_CORE_INVALID_INPUT;
52
+ }
53
+
54
+ hash_ctx = nostr_native_secp256k1_get_hash_context(ctx);
55
+ nostr_native_secp256k1_sha256_initialize(&sha);
56
+ nostr_native_secp256k1_sha256_write(hash_ctx, &sha, serialized, len);
57
+ nostr_native_secp256k1_sha256_finalize(hash_ctx, &sha, digest);
58
+ for (i = 0; i < 32; i++) {
59
+ if (digest[i] != id[i]) {
60
+ return NOSTR_CORE_VERIFY_FAILED;
61
+ }
62
+ }
63
+ return nostr_core_verify(ctx, id, pubkey, sig);
64
+ }
65
+
66
+ int nostr_core_sign(const nostr_native_secp256k1_context *ctx, const unsigned char id[32],
67
+ const unsigned char seckey[32], const unsigned char aux[32],
68
+ unsigned char out_sig[64]) {
69
+ nostr_native_secp256k1_keypair keypair;
70
+ int ok;
71
+
72
+ if (ctx == NULL || id == NULL || seckey == NULL || aux == NULL || out_sig == NULL) {
73
+ return NOSTR_CORE_INVALID_INPUT;
74
+ }
75
+
76
+ ok = nostr_native_secp256k1_keypair_create(ctx, &keypair, seckey) &&
77
+ nostr_native_secp256k1_schnorrsig_sign32(ctx, out_sig, id, &keypair, aux);
78
+ nostr_native_secp256k1_memclear_explicit(&keypair, sizeof(keypair));
79
+ return ok ? NOSTR_CORE_OK : NOSTR_CORE_INVALID_INPUT;
80
+ }
81
+
82
+ int nostr_core_public_key(const nostr_native_secp256k1_context *ctx,
83
+ const unsigned char seckey[32], unsigned char out_xonly[32]) {
84
+ nostr_native_secp256k1_keypair keypair;
85
+ nostr_native_secp256k1_xonly_pubkey pubkey;
86
+ int ok;
87
+
88
+ if (ctx == NULL || seckey == NULL || out_xonly == NULL) {
89
+ return NOSTR_CORE_INVALID_INPUT;
90
+ }
91
+
92
+ ok = nostr_native_secp256k1_keypair_create(ctx, &keypair, seckey) &&
93
+ nostr_native_secp256k1_keypair_xonly_pub(ctx, &pubkey, NULL, &keypair) &&
94
+ nostr_native_secp256k1_xonly_pubkey_serialize(ctx, out_xonly, &pubkey);
95
+ nostr_native_secp256k1_memclear_explicit(&keypair, sizeof(keypair));
96
+ return ok ? NOSTR_CORE_OK : NOSTR_CORE_INVALID_INPUT;
97
+ }
98
+
99
+ #ifdef NOSTR_NATIVE_TEST
100
+
101
+ nostr_native_secp256k1_context *nostr_native_test_context(void) {
102
+ static nostr_native_secp256k1_context *ctx;
103
+ if (ctx == NULL) {
104
+ ctx = nostr_native_secp256k1_context_create(SECP256K1_CONTEXT_NONE);
105
+ }
106
+ return ctx;
107
+ }
108
+
109
+ void nostr_native_test_sha256(const unsigned char *data, size_t len, unsigned char out32[32]) {
110
+ nostr_native_secp256k1_context *ctx = nostr_native_test_context();
111
+ const nostr_native_secp256k1_hash_ctx *hash_ctx = nostr_native_secp256k1_get_hash_context(ctx);
112
+ nostr_native_secp256k1_sha256 sha;
113
+ nostr_native_secp256k1_sha256_initialize(&sha);
114
+ nostr_native_secp256k1_sha256_write(hash_ctx, &sha, data, len);
115
+ nostr_native_secp256k1_sha256_finalize(hash_ctx, &sha, out32);
116
+ }
117
+
118
+ int nostr_native_test_schnorr_verify(const unsigned char *msg, size_t msglen,
119
+ const unsigned char pubkey[32], const unsigned char sig[64]) {
120
+ nostr_native_secp256k1_context *ctx = nostr_native_test_context();
121
+ nostr_native_secp256k1_xonly_pubkey parsed;
122
+ if (!nostr_native_secp256k1_xonly_pubkey_parse(ctx, &parsed, pubkey)) {
123
+ return 0;
124
+ }
125
+ return nostr_native_secp256k1_schnorrsig_verify(ctx, sig, msg, msglen, &parsed);
126
+ }
127
+
128
+ #endif
@@ -0,0 +1,65 @@
1
+ #ifndef NOSTR_CORE_H
2
+ #define NOSTR_CORE_H
3
+
4
+ #include <stddef.h>
5
+
6
+ #include "../vendor/secp256k1/include/secp256k1.h"
7
+
8
+ #ifdef __cplusplus
9
+ extern "C" {
10
+ #endif
11
+
12
+ /*
13
+ * Platform-independent secp256k1 operations shared by the React Native layer
14
+ * (nostr_native.c) and the wasm32 layer (packages/nostr-wasm/c/nostr_wasm.c).
15
+ * Every entry point takes the caller's context; status codes:
16
+ */
17
+
18
+ /* Success, or the signature verified. */
19
+ #define NOSTR_CORE_OK 0
20
+ /* The hash or signature check failed. */
21
+ #define NOSTR_CORE_VERIFY_FAILED 1
22
+ /* NULL argument, invalid scalar, or a non-point public key. */
23
+ #define NOSTR_CORE_INVALID_INPUT 2
24
+
25
+ /* BIP-340 verify of the 32-byte `id` for the x-only `pubkey`. */
26
+ int nostr_core_verify(const nostr_native_secp256k1_context *ctx, const unsigned char id[32],
27
+ const unsigned char pubkey[32], const unsigned char sig[64]);
28
+
29
+ /* `sha256(serialized[0..len])` must equal `id`, then BIP-340 verify. */
30
+ int nostr_core_verify_serialized(const nostr_native_secp256k1_context *ctx,
31
+ const unsigned char *serialized, size_t len,
32
+ const unsigned char id[32], const unsigned char pubkey[32],
33
+ const unsigned char sig[64]);
34
+
35
+ /* BIP-340 sign the 32-byte `id` with caller-supplied `aux` randomness; writes
36
+ * 64 signature bytes on NOSTR_CORE_OK. The keypair is wiped on every path. */
37
+ int nostr_core_sign(const nostr_native_secp256k1_context *ctx, const unsigned char id[32],
38
+ const unsigned char seckey[32], const unsigned char aux[32],
39
+ unsigned char out_sig[64]);
40
+
41
+ /* Write the 32-byte x-only public key of `seckey` to `out_xonly`. */
42
+ int nostr_core_public_key(const nostr_native_secp256k1_context *ctx,
43
+ const unsigned char seckey[32], unsigned char out_xonly[32]);
44
+
45
+ /* Secure wipe for platform layers that must clear caller-provided regions. */
46
+ void nostr_core_wipe(void *ptr, size_t len);
47
+
48
+ #ifdef NOSTR_NATIVE_TEST
49
+ /* Test-only entry points (host suite only): expose the SHA-256 and Schnorr halves individually
50
+ * so BIP-340 vectors with arbitrary-length messages and raw SHA-256 vectors can run. */
51
+
52
+ /* A lazily created context owned by the test binary; never destroyed. */
53
+ nostr_native_secp256k1_context *nostr_native_test_context(void);
54
+
55
+ void nostr_native_test_sha256(const unsigned char *data, size_t len, unsigned char out32[32]);
56
+
57
+ int nostr_native_test_schnorr_verify(const unsigned char *msg, size_t msglen,
58
+ const unsigned char pubkey[32], const unsigned char sig[64]);
59
+ #endif
60
+
61
+ #ifdef __cplusplus
62
+ }
63
+ #endif
64
+
65
+ #endif /* NOSTR_CORE_H */
@@ -0,0 +1,54 @@
1
+ #include "nostr_native.h"
2
+
3
+ #include "nostr_core.h"
4
+
5
+ #include <pthread.h>
6
+ #include <stdlib.h>
7
+ #include <string.h>
8
+
9
+ /*
10
+ * React Native platform layer: owns the process context (pthread_once creation plus an
11
+ * arc4random seed) and delegates the crypto work to nostr_core.c — the single TU that
12
+ * compiles the vendored libsecp256k1. CONTEXT_NONE runs the library self test; randomizing
13
+ * with an arc4random seed blinds ecmult_gen against side-channel leakage of the secret key
14
+ * while signing. Every public entry point resolves the context first.
15
+ */
16
+ static nostr_native_secp256k1_context *module_ctx;
17
+ static pthread_once_t module_ctx_once = PTHREAD_ONCE_INIT;
18
+
19
+ static void init_module_context(void) {
20
+ unsigned char seed[32];
21
+ nostr_native_secp256k1_context *created =
22
+ nostr_native_secp256k1_context_create(SECP256K1_CONTEXT_NONE);
23
+ if (created == NULL) {
24
+ abort();
25
+ }
26
+ arc4random_buf(seed, sizeof(seed));
27
+ if (!nostr_native_secp256k1_context_randomize(created, seed)) {
28
+ abort();
29
+ }
30
+ nostr_core_wipe(seed, sizeof(seed));
31
+ module_ctx = created;
32
+ }
33
+
34
+ static nostr_native_secp256k1_context *module_context(void) {
35
+ pthread_once(&module_ctx_once, init_module_context);
36
+ return module_ctx;
37
+ }
38
+
39
+ int nostr_native_verify_serialized(const unsigned char *serialized, size_t len,
40
+ const unsigned char id[32],
41
+ const unsigned char pubkey[32],
42
+ const unsigned char sig[64]) {
43
+ return nostr_core_verify_serialized(module_context(), serialized, len, id, pubkey, sig) ==
44
+ NOSTR_CORE_OK;
45
+ }
46
+
47
+ int nostr_native_public_key(const unsigned char seckey[32], unsigned char out_xonly[32]) {
48
+ return nostr_core_public_key(module_context(), seckey, out_xonly) == NOSTR_CORE_OK;
49
+ }
50
+
51
+ int nostr_native_sign(const unsigned char id[32], const unsigned char seckey[32],
52
+ const unsigned char aux_rand[32], unsigned char out_sig[64]) {
53
+ return nostr_core_sign(module_context(), id, seckey, aux_rand, out_sig) == NOSTR_CORE_OK;
54
+ }
@@ -0,0 +1,47 @@
1
+ #ifndef NOSTR_NATIVE_H
2
+ #define NOSTR_NATIVE_H
3
+
4
+ #include <stddef.h>
5
+
6
+ #ifdef __cplusplus
7
+ extern "C" {
8
+ #endif
9
+
10
+ /**
11
+ * Return 1 iff `sha256(serialized[0..len])` equals `id` and `sig` is a valid BIP-340 signature of
12
+ * `id` for the x-only `pubkey`. `id`/`pubkey` are 32 bytes and `sig` is 64 bytes; NULL pointers
13
+ * return 0.
14
+ */
15
+ int nostr_native_verify_serialized(const unsigned char *serialized, size_t len,
16
+ const unsigned char id[32],
17
+ const unsigned char pubkey[32],
18
+ const unsigned char sig[64]);
19
+
20
+ /**
21
+ * Write the 32-byte x-only BIP-340 public key of `seckey` to `out_xonly`.
22
+ * Returns 1 on success; 0 on NULL input or an invalid secret key (zero or >= group order).
23
+ */
24
+ int nostr_native_public_key(const unsigned char seckey[32], unsigned char out_xonly[32]);
25
+
26
+ /**
27
+ * Write the 64-byte BIP-340 signature of `id` by `seckey` with `aux_rand` auxiliary randomness
28
+ * to `out_sig`. Returns 1 on success; 0 on NULL input or an invalid secret key.
29
+ */
30
+ int nostr_native_sign(const unsigned char id[32], const unsigned char seckey[32],
31
+ const unsigned char aux_rand[32], unsigned char out_sig[64]);
32
+
33
+ #ifdef NOSTR_NATIVE_TEST
34
+ /* Test-only entry points (host suite only): expose the SHA-256 and Schnorr halves individually
35
+ * so BIP-340 vectors with arbitrary-length messages and raw SHA-256 vectors can run. */
36
+
37
+ void nostr_native_test_sha256(const unsigned char *data, size_t len, unsigned char out32[32]);
38
+
39
+ int nostr_native_test_schnorr_verify(const unsigned char *msg, size_t msglen,
40
+ const unsigned char pubkey[32], const unsigned char sig[64]);
41
+ #endif
42
+
43
+ #ifdef __cplusplus
44
+ }
45
+ #endif
46
+
47
+ #endif /* NOSTR_NATIVE_H */
@@ -0,0 +1,15 @@
1
+ import { SerializedEventVerifier, SigningBackend } from "@qntx/nostr/core";
2
+ //#region src/index.d.ts
3
+ /**
4
+ * `SerializedEventVerifier` backed by native libsecp256k1 — plug into `createEventVerifier` from
5
+ * `@qntx/nostr/core`. The Nitro hybrid object is created once at module load.
6
+ */
7
+ export declare const verifySerialized: SerializedEventVerifier;
8
+ /**
9
+ * `SigningBackend` backed by native libsecp256k1 — plug into `Keys.fromSecretKey(secretKey,
10
+ * signing)` or `Keys.generate(signing)` so signing runs on the same randomized context as
11
+ * verification. Throws on an invalid secret key or wrong-length input.
12
+ */
13
+ export declare const signing: SigningBackend;
14
+ //#endregion
15
+ //# sourceMappingURL=index.d.mts.map
package/dist/index.mjs ADDED
@@ -0,0 +1,26 @@
1
+ import { NitroModules } from "react-native-nitro-modules";
2
+ //#region src/index.ts
3
+ const nostrNative = NitroModules.createHybridObject("NostrNative");
4
+ function asArrayBuffer(view) {
5
+ const { buffer, byteOffset, byteLength } = view;
6
+ if (buffer instanceof ArrayBuffer && byteOffset === 0 && byteLength === buffer.byteLength) return buffer;
7
+ return new Uint8Array(view).buffer;
8
+ }
9
+ /**
10
+ * `SerializedEventVerifier` backed by native libsecp256k1 — plug into `createEventVerifier` from
11
+ * `@qntx/nostr/core`. The Nitro hybrid object is created once at module load.
12
+ */
13
+ const verifySerialized = (serializedUtf8, id, pubkey, sig) => nostrNative.verifySerialized(asArrayBuffer(serializedUtf8), asArrayBuffer(id), asArrayBuffer(pubkey), asArrayBuffer(sig));
14
+ /**
15
+ * `SigningBackend` backed by native libsecp256k1 — plug into `Keys.fromSecretKey(secretKey,
16
+ * signing)` or `Keys.generate(signing)` so signing runs on the same randomized context as
17
+ * verification. Throws on an invalid secret key or wrong-length input.
18
+ */
19
+ const signing = {
20
+ publicKey: (secretKey) => new Uint8Array(nostrNative.publicKey(asArrayBuffer(secretKey))),
21
+ sign: (id, secretKey, auxRand) => new Uint8Array(nostrNative.sign(asArrayBuffer(id), asArrayBuffer(secretKey), asArrayBuffer(auxRand)))
22
+ };
23
+ //#endregion
24
+ export { signing, verifySerialized };
25
+
26
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../src/index.ts"],"sourcesContent":["import { NitroModules } from \"react-native-nitro-modules\";\n\nimport type { SerializedEventVerifier, SigningBackend } from \"@qntx/nostr/core\";\n\nimport type { NostrNative } from \"./specs/nostr-native.nitro.ts\";\n\nconst nostrNative = NitroModules.createHybridObject<NostrNative>(\"NostrNative\");\n\nfunction asArrayBuffer(view: Uint8Array): ArrayBuffer {\n const { buffer, byteOffset, byteLength } = view;\n if (buffer instanceof ArrayBuffer && byteOffset === 0 && byteLength === buffer.byteLength) {\n return buffer;\n }\n return new Uint8Array(view).buffer;\n}\n\n/**\n * `SerializedEventVerifier` backed by native libsecp256k1 — plug into `createEventVerifier` from\n * `@qntx/nostr/core`. The Nitro hybrid object is created once at module load.\n */\nexport const verifySerialized: SerializedEventVerifier = (serializedUtf8, id, pubkey, sig) =>\n nostrNative.verifySerialized(\n asArrayBuffer(serializedUtf8),\n asArrayBuffer(id),\n asArrayBuffer(pubkey),\n asArrayBuffer(sig),\n );\n\n/**\n * `SigningBackend` backed by native libsecp256k1 — plug into `Keys.fromSecretKey(secretKey,\n * signing)` or `Keys.generate(signing)` so signing runs on the same randomized context as\n * verification. Throws on an invalid secret key or wrong-length input.\n */\nexport const signing: SigningBackend = {\n publicKey: (secretKey) => new Uint8Array(nostrNative.publicKey(asArrayBuffer(secretKey))),\n sign: (id, secretKey, auxRand) =>\n new Uint8Array(\n nostrNative.sign(asArrayBuffer(id), asArrayBuffer(secretKey), asArrayBuffer(auxRand)),\n ),\n};\n"],"mappings":";;AAMA,MAAM,cAAc,aAAa,mBAAgC,aAAa;AAE9E,SAAS,cAAc,MAA+B;CACpD,MAAM,EAAE,QAAQ,YAAY,eAAe;CAC3C,IAAI,kBAAkB,eAAe,eAAe,KAAK,eAAe,OAAO,YAC7E,OAAO;CAET,OAAO,IAAI,WAAW,IAAI,CAAC,CAAC;AAC9B;;;;;AAMA,MAAa,oBAA6C,gBAAgB,IAAI,QAAQ,QACpF,YAAY,iBACV,cAAc,cAAc,GAC5B,cAAc,EAAE,GAChB,cAAc,MAAM,GACpB,cAAc,GAAG,CACnB;;;;;;AAOF,MAAa,UAA0B;CACrC,YAAY,cAAc,IAAI,WAAW,YAAY,UAAU,cAAc,SAAS,CAAC,CAAC;CACxF,OAAO,IAAI,WAAW,YACpB,IAAI,WACF,YAAY,KAAK,cAAc,EAAE,GAAG,cAAc,SAAS,GAAG,cAAc,OAAO,CAAC,CACtF;AACJ"}
package/nitro.json ADDED
@@ -0,0 +1,19 @@
1
+ {
2
+ "$schema": "https://nitro.margelo.com/nitro.schema.json",
3
+ "cxxNamespace": ["nostrnative"],
4
+ "ios": {
5
+ "iosModuleName": "NostrNative"
6
+ },
7
+ "android": {
8
+ "androidNamespace": ["nostrnative"],
9
+ "androidCxxLibName": "NostrNative"
10
+ },
11
+ "autolinking": {
12
+ "NostrNative": {
13
+ "all": {
14
+ "language": "c++",
15
+ "implementationClassName": "HybridNostrNative"
16
+ }
17
+ }
18
+ }
19
+ }
@@ -0,0 +1 @@
1
+ ** linguist-generated=true
@@ -0,0 +1,81 @@
1
+ #
2
+ # NostrNative+autolinking.cmake
3
+ # This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
4
+ # https://github.com/mrousavy/nitro
5
+ # Copyright © Marc Rousavy @ Margelo
6
+ #
7
+
8
+ # This is a CMake file that adds all files generated by Nitrogen
9
+ # to the current CMake project.
10
+ #
11
+ # To use it, add this to your CMakeLists.txt:
12
+ # ```cmake
13
+ # include(${CMAKE_SOURCE_DIR}/../nitrogen/generated/android/NostrNative+autolinking.cmake)
14
+ # ```
15
+
16
+ # Define a flag to check if we are building properly
17
+ add_definitions(-DBUILDING_NOSTRNATIVE_WITH_GENERATED_CMAKE_PROJECT)
18
+
19
+ # Enable Raw Props parsing in react-native (for Nitro Views)
20
+ add_definitions(-DRN_SERIALIZABLE_STATE)
21
+
22
+ # Add all headers that were generated by Nitrogen
23
+ include_directories(
24
+ "../nitrogen/generated/shared/c++"
25
+ "../nitrogen/generated/android/c++"
26
+ "../nitrogen/generated/android/"
27
+ )
28
+
29
+ # Add all .cpp sources that were generated by Nitrogen
30
+ target_sources(
31
+ # CMake project name (Android C++ library name)
32
+ NostrNative PRIVATE
33
+ # Autolinking Setup
34
+ ../nitrogen/generated/android/NostrNativeOnLoad.cpp
35
+ # Shared Nitrogen C++ sources
36
+ ../nitrogen/generated/shared/c++/HybridNostrNativeSpec.cpp
37
+ # Android-specific Nitrogen C++ sources
38
+
39
+ )
40
+
41
+ # From node_modules/react-native/ReactAndroid/cmake-utils/folly-flags.cmake
42
+ # Used in node_modules/react-native/ReactAndroid/cmake-utils/ReactNative-application.cmake
43
+ target_compile_definitions(
44
+ NostrNative PRIVATE
45
+ -DFOLLY_NO_CONFIG=1
46
+ -DFOLLY_HAVE_CLOCK_GETTIME=1
47
+ -DFOLLY_USE_LIBCPP=1
48
+ -DFOLLY_CFG_NO_COROUTINES=1
49
+ -DFOLLY_MOBILE=1
50
+ -DFOLLY_HAVE_RECVMMSG=1
51
+ -DFOLLY_HAVE_PTHREAD=1
52
+ # Once we target android-23 above, we can comment
53
+ # the following line. NDK uses GNU style stderror_r() after API 23.
54
+ -DFOLLY_HAVE_XSI_STRERROR_R=1
55
+ )
56
+
57
+ # Add all libraries required by the generated specs
58
+ find_package(fbjni REQUIRED) # <-- Used for communication between Java <-> C++
59
+ find_package(ReactAndroid REQUIRED) # <-- Used to set up React Native bindings (e.g. CallInvoker/TurboModule)
60
+ find_package(react-native-nitro-modules REQUIRED) # <-- Used to create all HybridObjects and use the Nitro core library
61
+
62
+ # Link all libraries together
63
+ target_link_libraries(
64
+ NostrNative
65
+ fbjni::fbjni # <-- Facebook C++ JNI helpers
66
+ ReactAndroid::jsi # <-- RN: JSI
67
+ react-native-nitro-modules::NitroModules # <-- NitroModules Core :)
68
+ )
69
+
70
+ # Link react-native (different prefab between RN 0.75 and RN 0.76)
71
+ if(ReactAndroid_VERSION_MINOR GREATER_EQUAL 76)
72
+ target_link_libraries(
73
+ NostrNative
74
+ ReactAndroid::reactnative # <-- RN: Native Modules umbrella prefab
75
+ )
76
+ else()
77
+ target_link_libraries(
78
+ NostrNative
79
+ ReactAndroid::react_nativemodule_core # <-- RN: TurboModules Core
80
+ )
81
+ endif()
@@ -0,0 +1,27 @@
1
+ ///
2
+ /// NostrNative+autolinking.gradle
3
+ /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
4
+ /// https://github.com/mrousavy/nitro
5
+ /// Copyright © Marc Rousavy @ Margelo
6
+ ///
7
+
8
+ /// This is a Gradle file that adds all files generated by Nitrogen
9
+ /// to the current Gradle project.
10
+ ///
11
+ /// To use it, add this to your build.gradle:
12
+ /// ```gradle
13
+ /// apply from: '../nitrogen/generated/android/NostrNative+autolinking.gradle'
14
+ /// ```
15
+
16
+ logger.warn("[NitroModules] 🔥 NostrNative is boosted by nitro!")
17
+
18
+ android {
19
+ sourceSets {
20
+ main {
21
+ java.srcDirs += [
22
+ // Nitrogen files
23
+ "${project.projectDir}/../nitrogen/generated/android/kotlin"
24
+ ]
25
+ }
26
+ }
27
+ }
@@ -0,0 +1,49 @@
1
+ ///
2
+ /// NostrNativeOnLoad.cpp
3
+ /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
4
+ /// https://github.com/mrousavy/nitro
5
+ /// Copyright © Marc Rousavy @ Margelo
6
+ ///
7
+
8
+ #ifndef BUILDING_NOSTRNATIVE_WITH_GENERATED_CMAKE_PROJECT
9
+ #error NostrNativeOnLoad.cpp is not being built with the autogenerated CMakeLists.txt project. Is a different CMakeLists.txt building this?
10
+ #endif
11
+
12
+ #include "NostrNativeOnLoad.hpp"
13
+
14
+ #include <jni.h>
15
+ #include <fbjni/fbjni.h>
16
+ #include <NitroModules/HybridObjectRegistry.hpp>
17
+
18
+ #include "HybridNostrNative.hpp"
19
+
20
+ namespace margelo::nitro::nostrnative {
21
+
22
+ int initialize(JavaVM* vm) {
23
+ return facebook::jni::initialize(vm, []() {
24
+ ::margelo::nitro::nostrnative::registerAllNatives();
25
+ });
26
+ }
27
+
28
+
29
+
30
+ void registerAllNatives() {
31
+ using namespace margelo::nitro;
32
+ using namespace margelo::nitro::nostrnative;
33
+
34
+ // Register native JNI methods
35
+
36
+
37
+ // Register Nitro Hybrid Objects
38
+ HybridObjectRegistry::registerHybridObjectConstructor(
39
+ "NostrNative",
40
+ []() -> std::shared_ptr<HybridObject> {
41
+ static_assert(std::is_default_constructible_v<HybridNostrNative>,
42
+ "The HybridObject \"HybridNostrNative\" is not default-constructible! "
43
+ "Create a public constructor that takes zero arguments to be able to autolink this HybridObject.");
44
+ return std::make_shared<HybridNostrNative>();
45
+ }
46
+ );
47
+ }
48
+
49
+ } // namespace margelo::nitro::nostrnative
@@ -0,0 +1,34 @@
1
+ ///
2
+ /// NostrNativeOnLoad.hpp
3
+ /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
4
+ /// https://github.com/mrousavy/nitro
5
+ /// Copyright © Marc Rousavy @ Margelo
6
+ ///
7
+
8
+ #include <jni.h>
9
+ #include <functional>
10
+ #include <NitroModules/NitroDefines.hpp>
11
+
12
+ namespace margelo::nitro::nostrnative {
13
+
14
+ [[deprecated("Use registerNatives() instead.")]]
15
+ int initialize(JavaVM* vm);
16
+
17
+ /**
18
+ * Register the native (C++) part of NostrNative, and autolinks all Hybrid Objects.
19
+ * Call this in your `JNI_OnLoad` function (probably inside `cpp-adapter.cpp`),
20
+ * inside a `facebook::jni::initialize(vm, ...)` call.
21
+ * Example:
22
+ * ```cpp (cpp-adapter.cpp)
23
+ * JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void*) {
24
+ * return facebook::jni::initialize(vm, []() {
25
+ * // register all NostrNative HybridObjects
26
+ * margelo::nitro::nostrnative::registerNatives();
27
+ * // any other custom registrations go here.
28
+ * });
29
+ * }
30
+ * ```
31
+ */
32
+ void registerAllNatives();
33
+
34
+ } // namespace margelo::nitro::nostrnative
@@ -0,0 +1,35 @@
1
+ ///
2
+ /// NostrNativeOnLoad.kt
3
+ /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
4
+ /// https://github.com/mrousavy/nitro
5
+ /// Copyright © Marc Rousavy @ Margelo
6
+ ///
7
+
8
+ package com.margelo.nitro.nostrnative
9
+
10
+ import android.util.Log
11
+
12
+ internal class NostrNativeOnLoad {
13
+ companion object {
14
+ private const val TAG = "NostrNativeOnLoad"
15
+ private var didLoad = false
16
+ /**
17
+ * Initializes the native part of "NostrNative".
18
+ * This method is idempotent and can be called more than once.
19
+ */
20
+ @JvmStatic
21
+ fun initializeNative() {
22
+ if (didLoad) return
23
+ try {
24
+ Log.i(TAG, "Loading NostrNative C++ library...")
25
+ System.loadLibrary("NostrNative")
26
+ Log.i(TAG, "Successfully loaded NostrNative C++ library!")
27
+ didLoad = true
28
+ } catch (e: Error) {
29
+ Log.e(TAG, "Failed to load NostrNative C++ library! Is it properly installed and linked? " +
30
+ "Is the name correct? (see `CMakeLists.txt`, at `add_library(...)`)", e)
31
+ throw e
32
+ }
33
+ }
34
+ }
35
+ }
@@ -0,0 +1,62 @@
1
+ #
2
+ # NostrNative+autolinking.rb
3
+ # This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
4
+ # https://github.com/mrousavy/nitro
5
+ # Copyright © Marc Rousavy @ Margelo
6
+ #
7
+
8
+ # This is a Ruby script that adds all files generated by Nitrogen
9
+ # to the given podspec.
10
+ #
11
+ # To use it, add this to your .podspec:
12
+ # ```ruby
13
+ # Pod::Spec.new do |spec|
14
+ # # ...
15
+ #
16
+ # # Add all files generated by Nitrogen
17
+ # load 'nitrogen/generated/ios/NostrNative+autolinking.rb'
18
+ # add_nitrogen_files(spec)
19
+ # end
20
+ # ```
21
+
22
+ def add_nitrogen_files(spec)
23
+ Pod::UI.puts "[NitroModules] 🔥 NostrNative is boosted by nitro!"
24
+
25
+ spec.dependency "NitroModules"
26
+
27
+ current_source_files = Array(spec.attributes_hash['source_files'])
28
+ spec.source_files = current_source_files + [
29
+ # Generated cross-platform specs
30
+ "nitrogen/generated/shared/**/*.{h,hpp,c,cpp,swift}",
31
+ # Generated bridges for the cross-platform specs
32
+ "nitrogen/generated/ios/**/*.{h,hpp,c,cpp,mm,swift}",
33
+ ]
34
+
35
+ current_public_header_files = Array(spec.attributes_hash['public_header_files'])
36
+ spec.public_header_files = current_public_header_files + [
37
+ # Generated specs
38
+ "nitrogen/generated/shared/**/*.{h,hpp}",
39
+ # Swift to C++ bridging helpers
40
+ "nitrogen/generated/ios/NostrNative-Swift-Cxx-Bridge.hpp"
41
+ ]
42
+
43
+ current_private_header_files = Array(spec.attributes_hash['private_header_files'])
44
+ spec.private_header_files = current_private_header_files + [
45
+ # iOS specific specs
46
+ "nitrogen/generated/ios/c++/**/*.{h,hpp}",
47
+ # Views are framework-specific and should be private
48
+ "nitrogen/generated/shared/**/views/**/*"
49
+ ]
50
+
51
+ current_pod_target_xcconfig = spec.attributes_hash['pod_target_xcconfig'] || {}
52
+ spec.pod_target_xcconfig = current_pod_target_xcconfig.merge({
53
+ # Use C++ 20
54
+ "CLANG_CXX_LANGUAGE_STANDARD" => "c++20",
55
+ # Enables C++ <-> Swift interop (by default it's only ObjC)
56
+ "SWIFT_OBJC_INTEROP_MODE" => "objcxx",
57
+ # Enables stricter modular headers
58
+ "DEFINES_MODULE" => "YES",
59
+ # Disable auto-generated ObjC header for Swift (Static linkage on Xcode 26.4 breaks here)
60
+ "SWIFT_INSTALL_OBJC_HEADER" => "NO",
61
+ })
62
+ end