react-native-ufsecp 3.10.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/src/main/java/com/ultrafast/ufsecp/UfsecpModule.java +207 -0
- package/android/src/main/java/com/ultrafastsecp256k1/UltrafastSecp256k1Module.java +385 -0
- package/android/src/main/java/com/ultrafastsecp256k1/UltrafastSecp256k1Package.java +28 -0
- package/ios/RNUfsecp.m +253 -0
- package/ios/UltrafastSecp256k1.h +4 -0
- package/ios/UltrafastSecp256k1.m +483 -0
- package/lib/ufsecp.js +176 -0
- package/package.json +24 -0
- package/react-native-ufsecp.podspec +17 -0
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* UltrafastSecp256k1 — React Native Android Module (ufsecp stable C ABI v1).
|
|
3
|
+
*
|
|
4
|
+
* Bridges NativeModule calls to ufsecp JNI (loads libufsecp_jni.so which links libufsecp.so).
|
|
5
|
+
* All byte-array I/O is hex-encoded.
|
|
6
|
+
*/
|
|
7
|
+
package com.ultrafast.ufsecp;
|
|
8
|
+
|
|
9
|
+
import androidx.annotation.NonNull;
|
|
10
|
+
|
|
11
|
+
import com.facebook.react.bridge.Promise;
|
|
12
|
+
import com.facebook.react.bridge.ReactApplicationContext;
|
|
13
|
+
import com.facebook.react.bridge.ReactContextBaseJavaModule;
|
|
14
|
+
import com.facebook.react.bridge.ReactMethod;
|
|
15
|
+
|
|
16
|
+
public class UfsecpModule extends ReactContextBaseJavaModule {
|
|
17
|
+
|
|
18
|
+
static {
|
|
19
|
+
System.loadLibrary("ufsecp_jni");
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
private final ReactApplicationContext ctx;
|
|
23
|
+
|
|
24
|
+
public UfsecpModule(ReactApplicationContext reactContext) {
|
|
25
|
+
super(reactContext);
|
|
26
|
+
this.ctx = reactContext;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
@NonNull
|
|
30
|
+
@Override
|
|
31
|
+
public String getName() {
|
|
32
|
+
return "Ufsecp";
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/* ── Hex helpers ────────────────────────────────────────────────── */
|
|
36
|
+
|
|
37
|
+
private static byte[] hexToBytes(String hex) {
|
|
38
|
+
int len = hex.length();
|
|
39
|
+
byte[] out = new byte[len / 2];
|
|
40
|
+
for (int i = 0; i < len; i += 2)
|
|
41
|
+
out[i / 2] = (byte) ((Character.digit(hex.charAt(i), 16) << 4)
|
|
42
|
+
+ Character.digit(hex.charAt(i + 1), 16));
|
|
43
|
+
return out;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
private static String bytesToHex(byte[] b) {
|
|
47
|
+
StringBuilder sb = new StringBuilder(b.length * 2);
|
|
48
|
+
for (byte v : b) sb.append(String.format("%02x", v & 0xff));
|
|
49
|
+
return sb.toString();
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/* ── Native JNI declarations (same as Ufsecp.java) ─────────────── */
|
|
53
|
+
|
|
54
|
+
private static native long nativeCreate();
|
|
55
|
+
private static native void nativeDestroy(long ptr);
|
|
56
|
+
private static native int nativeVersion();
|
|
57
|
+
private static native String nativeVersionString();
|
|
58
|
+
private static native byte[] nativePubkeyCreate(long ctx, byte[] privkey);
|
|
59
|
+
private static native byte[] nativePubkeyCreateUncompressed(long ctx, byte[] privkey);
|
|
60
|
+
private static native boolean nativeSeckeyVerify(long ctx, byte[] privkey);
|
|
61
|
+
private static native byte[] nativeEcdsaSign(long ctx, byte[] msgHash, byte[] privkey);
|
|
62
|
+
private static native boolean nativeEcdsaVerify(long ctx, byte[] msgHash, byte[] sig, byte[] pubkey);
|
|
63
|
+
private static native byte[] nativeSchnorrSign(long ctx, byte[] msg, byte[] privkey, byte[] auxRand);
|
|
64
|
+
private static native boolean nativeSchnorrVerify(long ctx, byte[] msg, byte[] sig, byte[] pubkeyX);
|
|
65
|
+
private static native byte[] nativeEcdh(long ctx, byte[] privkey, byte[] pubkey);
|
|
66
|
+
private static native byte[] nativeSha256(byte[] data);
|
|
67
|
+
private static native byte[] nativeHash160(byte[] data);
|
|
68
|
+
private static native String nativeAddrP2pkh(long ctx, byte[] pubkey, int network);
|
|
69
|
+
private static native String nativeAddrP2wpkh(long ctx, byte[] pubkey, int network);
|
|
70
|
+
private static native String nativeAddrP2tr(long ctx, byte[] xonly, int network);
|
|
71
|
+
private static native String nativeWifEncode(long ctx, byte[] privkey, boolean compressed, int network);
|
|
72
|
+
private static native byte[] nativeBip32Master(long ctx, byte[] seed);
|
|
73
|
+
private static native byte[] nativeBip32Derive(long ctx, byte[] parent, int index);
|
|
74
|
+
private static native byte[] nativeBip32DerivePath(long ctx, byte[] master, String path);
|
|
75
|
+
|
|
76
|
+
/* ── React Native methods ──────────────────────────────────────── */
|
|
77
|
+
|
|
78
|
+
@ReactMethod
|
|
79
|
+
public void create(Promise promise) {
|
|
80
|
+
try { promise.resolve((double) nativeCreate()); }
|
|
81
|
+
catch (Exception e) { promise.reject("UFSECP", e.getMessage()); }
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
@ReactMethod
|
|
85
|
+
public void destroy(double handle, Promise promise) {
|
|
86
|
+
try { nativeDestroy((long) handle); promise.resolve(null); }
|
|
87
|
+
catch (Exception e) { promise.reject("UFSECP", e.getMessage()); }
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
@ReactMethod
|
|
91
|
+
public void version(Promise promise) { promise.resolve(nativeVersion()); }
|
|
92
|
+
|
|
93
|
+
@ReactMethod
|
|
94
|
+
public void versionString(Promise promise) { promise.resolve(nativeVersionString()); }
|
|
95
|
+
|
|
96
|
+
@ReactMethod
|
|
97
|
+
public void pubkeyCreate(double handle, String privkeyHex, Promise promise) {
|
|
98
|
+
try { promise.resolve(bytesToHex(nativePubkeyCreate((long) handle, hexToBytes(privkeyHex)))); }
|
|
99
|
+
catch (Exception e) { promise.reject("UFSECP", e.getMessage()); }
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
@ReactMethod
|
|
103
|
+
public void pubkeyCreateUncompressed(double handle, String privkeyHex, Promise promise) {
|
|
104
|
+
try { promise.resolve(bytesToHex(nativePubkeyCreateUncompressed((long) handle, hexToBytes(privkeyHex)))); }
|
|
105
|
+
catch (Exception e) { promise.reject("UFSECP", e.getMessage()); }
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
@ReactMethod
|
|
109
|
+
public void seckeyVerify(double handle, String privkeyHex, Promise promise) {
|
|
110
|
+
try { promise.resolve(nativeSeckeyVerify((long) handle, hexToBytes(privkeyHex))); }
|
|
111
|
+
catch (Exception e) { promise.reject("UFSECP", e.getMessage()); }
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
@ReactMethod
|
|
115
|
+
public void ecdsaSign(double handle, String msgHashHex, String privkeyHex, Promise promise) {
|
|
116
|
+
try {
|
|
117
|
+
byte[] sig = nativeEcdsaSign((long) handle, hexToBytes(msgHashHex), hexToBytes(privkeyHex));
|
|
118
|
+
promise.resolve(bytesToHex(sig));
|
|
119
|
+
} catch (Exception e) { promise.reject("UFSECP", e.getMessage()); }
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
@ReactMethod
|
|
123
|
+
public void ecdsaVerify(double handle, String msgHashHex, String sigHex, String pubkeyHex, Promise promise) {
|
|
124
|
+
try {
|
|
125
|
+
boolean ok = nativeEcdsaVerify((long) handle, hexToBytes(msgHashHex), hexToBytes(sigHex), hexToBytes(pubkeyHex));
|
|
126
|
+
promise.resolve(ok);
|
|
127
|
+
} catch (Exception e) { promise.reject("UFSECP", e.getMessage()); }
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
@ReactMethod
|
|
131
|
+
public void schnorrSign(double handle, String msgHex, String privkeyHex, String auxRandHex, Promise promise) {
|
|
132
|
+
try {
|
|
133
|
+
byte[] sig = nativeSchnorrSign((long) handle, hexToBytes(msgHex), hexToBytes(privkeyHex), hexToBytes(auxRandHex));
|
|
134
|
+
promise.resolve(bytesToHex(sig));
|
|
135
|
+
} catch (Exception e) { promise.reject("UFSECP", e.getMessage()); }
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
@ReactMethod
|
|
139
|
+
public void schnorrVerify(double handle, String msgHex, String sigHex, String pubkeyXHex, Promise promise) {
|
|
140
|
+
try {
|
|
141
|
+
boolean ok = nativeSchnorrVerify((long) handle, hexToBytes(msgHex), hexToBytes(sigHex), hexToBytes(pubkeyXHex));
|
|
142
|
+
promise.resolve(ok);
|
|
143
|
+
} catch (Exception e) { promise.reject("UFSECP", e.getMessage()); }
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
@ReactMethod
|
|
147
|
+
public void ecdh(double handle, String privkeyHex, String pubkeyHex, Promise promise) {
|
|
148
|
+
try {
|
|
149
|
+
byte[] sec = nativeEcdh((long) handle, hexToBytes(privkeyHex), hexToBytes(pubkeyHex));
|
|
150
|
+
promise.resolve(bytesToHex(sec));
|
|
151
|
+
} catch (Exception e) { promise.reject("UFSECP", e.getMessage()); }
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
@ReactMethod
|
|
155
|
+
public void sha256(String dataHex, Promise promise) {
|
|
156
|
+
try { promise.resolve(bytesToHex(nativeSha256(hexToBytes(dataHex)))); }
|
|
157
|
+
catch (Exception e) { promise.reject("UFSECP", e.getMessage()); }
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
@ReactMethod
|
|
161
|
+
public void hash160(String dataHex, Promise promise) {
|
|
162
|
+
try { promise.resolve(bytesToHex(nativeHash160(hexToBytes(dataHex)))); }
|
|
163
|
+
catch (Exception e) { promise.reject("UFSECP", e.getMessage()); }
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
@ReactMethod
|
|
167
|
+
public void addrP2pkh(double handle, String pubkeyHex, int network, Promise promise) {
|
|
168
|
+
try { promise.resolve(nativeAddrP2pkh((long) handle, hexToBytes(pubkeyHex), network)); }
|
|
169
|
+
catch (Exception e) { promise.reject("UFSECP", e.getMessage()); }
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
@ReactMethod
|
|
173
|
+
public void addrP2wpkh(double handle, String pubkeyHex, int network, Promise promise) {
|
|
174
|
+
try { promise.resolve(nativeAddrP2wpkh((long) handle, hexToBytes(pubkeyHex), network)); }
|
|
175
|
+
catch (Exception e) { promise.reject("UFSECP", e.getMessage()); }
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
@ReactMethod
|
|
179
|
+
public void addrP2tr(double handle, String xonlyHex, int network, Promise promise) {
|
|
180
|
+
try { promise.resolve(nativeAddrP2tr((long) handle, hexToBytes(xonlyHex), network)); }
|
|
181
|
+
catch (Exception e) { promise.reject("UFSECP", e.getMessage()); }
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
@ReactMethod
|
|
185
|
+
public void wifEncode(double handle, String privkeyHex, boolean compressed, int network, Promise promise) {
|
|
186
|
+
try { promise.resolve(nativeWifEncode((long) handle, hexToBytes(privkeyHex), compressed, network)); }
|
|
187
|
+
catch (Exception e) { promise.reject("UFSECP", e.getMessage()); }
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
@ReactMethod
|
|
191
|
+
public void bip32Master(double handle, String seedHex, Promise promise) {
|
|
192
|
+
try { promise.resolve(bytesToHex(nativeBip32Master((long) handle, hexToBytes(seedHex)))); }
|
|
193
|
+
catch (Exception e) { promise.reject("UFSECP", e.getMessage()); }
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
@ReactMethod
|
|
197
|
+
public void bip32Derive(double handle, String parentHex, int index, Promise promise) {
|
|
198
|
+
try { promise.resolve(bytesToHex(nativeBip32Derive((long) handle, hexToBytes(parentHex), index))); }
|
|
199
|
+
catch (Exception e) { promise.reject("UFSECP", e.getMessage()); }
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
@ReactMethod
|
|
203
|
+
public void bip32DerivePath(double handle, String masterHex, String path, Promise promise) {
|
|
204
|
+
try { promise.resolve(bytesToHex(nativeBip32DerivePath((long) handle, hexToBytes(masterHex), path))); }
|
|
205
|
+
catch (Exception e) { promise.reject("UFSECP", e.getMessage()); }
|
|
206
|
+
}
|
|
207
|
+
}
|
|
@@ -0,0 +1,385 @@
|
|
|
1
|
+
package com.ultrafastsecp256k1;
|
|
2
|
+
|
|
3
|
+
import androidx.annotation.NonNull;
|
|
4
|
+
import androidx.annotation.Nullable;
|
|
5
|
+
|
|
6
|
+
import com.facebook.react.bridge.Arguments;
|
|
7
|
+
import com.facebook.react.bridge.Promise;
|
|
8
|
+
import com.facebook.react.bridge.ReactApplicationContext;
|
|
9
|
+
import com.facebook.react.bridge.ReactContextBaseJavaModule;
|
|
10
|
+
import com.facebook.react.bridge.ReactMethod;
|
|
11
|
+
import com.facebook.react.bridge.WritableMap;
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* React Native Android bridge for UltrafastSecp256k1.
|
|
15
|
+
*
|
|
16
|
+
* All byte data is passed as hex strings across the bridge.
|
|
17
|
+
*/
|
|
18
|
+
public class UltrafastSecp256k1Module extends ReactContextBaseJavaModule {
|
|
19
|
+
|
|
20
|
+
static {
|
|
21
|
+
System.loadLibrary("ultrafast_secp256k1_jni");
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
public UltrafastSecp256k1Module(ReactApplicationContext reactContext) {
|
|
25
|
+
super(reactContext);
|
|
26
|
+
nativeInit();
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
@NonNull
|
|
30
|
+
@Override
|
|
31
|
+
public String getName() {
|
|
32
|
+
return "UltrafastSecp256k1";
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// ── Hex helpers ──────────────────────────────────────────────────────
|
|
36
|
+
|
|
37
|
+
private static byte[] hexToBytes(String hex) {
|
|
38
|
+
int len = hex.length();
|
|
39
|
+
byte[] data = new byte[len / 2];
|
|
40
|
+
for (int i = 0; i < len; i += 2) {
|
|
41
|
+
data[i / 2] = (byte) ((Character.digit(hex.charAt(i), 16) << 4)
|
|
42
|
+
+ Character.digit(hex.charAt(i + 1), 16));
|
|
43
|
+
}
|
|
44
|
+
return data;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
private static final char[] HEX_CHARS = "0123456789abcdef".toCharArray();
|
|
48
|
+
|
|
49
|
+
private static String bytesToHex(byte[] bytes) {
|
|
50
|
+
char[] hex = new char[bytes.length * 2];
|
|
51
|
+
for (int i = 0; i < bytes.length; i++) {
|
|
52
|
+
int v = bytes[i] & 0xFF;
|
|
53
|
+
hex[i * 2] = HEX_CHARS[v >>> 4];
|
|
54
|
+
hex[i * 2 + 1] = HEX_CHARS[v & 0x0F];
|
|
55
|
+
}
|
|
56
|
+
return new String(hex);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// ── Bridge methods ───────────────────────────────────────────────────
|
|
60
|
+
|
|
61
|
+
@ReactMethod(isBlockingSynchronousMethod = true)
|
|
62
|
+
public String version() {
|
|
63
|
+
return nativeVersion();
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
@ReactMethod
|
|
67
|
+
public void ecPubkeyCreate(String privkeyHex, Promise promise) {
|
|
68
|
+
try {
|
|
69
|
+
byte[] pubkey = nativeEcPubkeyCreate(hexToBytes(privkeyHex));
|
|
70
|
+
promise.resolve(bytesToHex(pubkey));
|
|
71
|
+
} catch (Exception e) { promise.reject("ERR", e.getMessage()); }
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
@ReactMethod
|
|
75
|
+
public void ecPubkeyCreateUncompressed(String privkeyHex, Promise promise) {
|
|
76
|
+
try {
|
|
77
|
+
byte[] pubkey = nativeEcPubkeyCreateUncompressed(hexToBytes(privkeyHex));
|
|
78
|
+
promise.resolve(bytesToHex(pubkey));
|
|
79
|
+
} catch (Exception e) { promise.reject("ERR", e.getMessage()); }
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
@ReactMethod
|
|
83
|
+
public void ecPubkeyParse(String pubkeyHex, Promise promise) {
|
|
84
|
+
try {
|
|
85
|
+
byte[] pubkey = nativeEcPubkeyParse(hexToBytes(pubkeyHex));
|
|
86
|
+
promise.resolve(bytesToHex(pubkey));
|
|
87
|
+
} catch (Exception e) { promise.reject("ERR", e.getMessage()); }
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
@ReactMethod
|
|
91
|
+
public void ecSeckeyVerify(String privkeyHex, Promise promise) {
|
|
92
|
+
try {
|
|
93
|
+
promise.resolve(nativeEcSeckeyVerify(hexToBytes(privkeyHex)));
|
|
94
|
+
} catch (Exception e) { promise.reject("ERR", e.getMessage()); }
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
@ReactMethod
|
|
98
|
+
public void ecPrivkeyNegate(String privkeyHex, Promise promise) {
|
|
99
|
+
try {
|
|
100
|
+
byte[] result = nativeEcPrivkeyNegate(hexToBytes(privkeyHex));
|
|
101
|
+
promise.resolve(bytesToHex(result));
|
|
102
|
+
} catch (Exception e) { promise.reject("ERR", e.getMessage()); }
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
@ReactMethod
|
|
106
|
+
public void ecPrivkeyTweakAdd(String privkeyHex, String tweakHex, Promise promise) {
|
|
107
|
+
try {
|
|
108
|
+
byte[] result = nativeEcPrivkeyTweakAdd(hexToBytes(privkeyHex), hexToBytes(tweakHex));
|
|
109
|
+
promise.resolve(bytesToHex(result));
|
|
110
|
+
} catch (Exception e) { promise.reject("ERR", e.getMessage()); }
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
@ReactMethod
|
|
114
|
+
public void ecPrivkeyTweakMul(String privkeyHex, String tweakHex, Promise promise) {
|
|
115
|
+
try {
|
|
116
|
+
byte[] result = nativeEcPrivkeyTweakMul(hexToBytes(privkeyHex), hexToBytes(tweakHex));
|
|
117
|
+
promise.resolve(bytesToHex(result));
|
|
118
|
+
} catch (Exception e) { promise.reject("ERR", e.getMessage()); }
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
@ReactMethod
|
|
122
|
+
public void ecdsaSign(String msgHashHex, String privkeyHex, Promise promise) {
|
|
123
|
+
try {
|
|
124
|
+
byte[] sig = nativeEcdsaSign(hexToBytes(msgHashHex), hexToBytes(privkeyHex));
|
|
125
|
+
promise.resolve(bytesToHex(sig));
|
|
126
|
+
} catch (Exception e) { promise.reject("ERR", e.getMessage()); }
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
@ReactMethod
|
|
130
|
+
public void ecdsaVerify(String msgHashHex, String sigHex, String pubkeyHex, Promise promise) {
|
|
131
|
+
try {
|
|
132
|
+
promise.resolve(nativeEcdsaVerify(hexToBytes(msgHashHex), hexToBytes(sigHex), hexToBytes(pubkeyHex)));
|
|
133
|
+
} catch (Exception e) { promise.reject("ERR", e.getMessage()); }
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
@ReactMethod
|
|
137
|
+
public void ecdsaSerializeDer(String sigHex, Promise promise) {
|
|
138
|
+
try {
|
|
139
|
+
byte[] der = nativeEcdsaSerializeDer(hexToBytes(sigHex));
|
|
140
|
+
promise.resolve(bytesToHex(der));
|
|
141
|
+
} catch (Exception e) { promise.reject("ERR", e.getMessage()); }
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
@ReactMethod
|
|
145
|
+
public void ecdsaSignRecoverable(String msgHashHex, String privkeyHex, Promise promise) {
|
|
146
|
+
try {
|
|
147
|
+
Object[] result = nativeEcdsaSignRecoverable(hexToBytes(msgHashHex), hexToBytes(privkeyHex));
|
|
148
|
+
WritableMap map = Arguments.createMap();
|
|
149
|
+
map.putString("signature", bytesToHex((byte[]) result[0]));
|
|
150
|
+
map.putInt("recid", (int) result[1]);
|
|
151
|
+
promise.resolve(map);
|
|
152
|
+
} catch (Exception e) { promise.reject("ERR", e.getMessage()); }
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
@ReactMethod
|
|
156
|
+
public void ecdsaRecover(String msgHashHex, String sigHex, int recid, Promise promise) {
|
|
157
|
+
try {
|
|
158
|
+
byte[] pubkey = nativeEcdsaRecover(hexToBytes(msgHashHex), hexToBytes(sigHex), recid);
|
|
159
|
+
promise.resolve(bytesToHex(pubkey));
|
|
160
|
+
} catch (Exception e) { promise.reject("ERR", e.getMessage()); }
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
@ReactMethod
|
|
164
|
+
public void schnorrSign(String msgHex, String privkeyHex, String auxRandHex, Promise promise) {
|
|
165
|
+
try {
|
|
166
|
+
byte[] sig = nativeSchnorrSign(hexToBytes(msgHex), hexToBytes(privkeyHex), hexToBytes(auxRandHex));
|
|
167
|
+
promise.resolve(bytesToHex(sig));
|
|
168
|
+
} catch (Exception e) { promise.reject("ERR", e.getMessage()); }
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
@ReactMethod
|
|
172
|
+
public void schnorrVerify(String msgHex, String sigHex, String pubkeyXHex, Promise promise) {
|
|
173
|
+
try {
|
|
174
|
+
promise.resolve(nativeSchnorrVerify(hexToBytes(msgHex), hexToBytes(sigHex), hexToBytes(pubkeyXHex)));
|
|
175
|
+
} catch (Exception e) { promise.reject("ERR", e.getMessage()); }
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
@ReactMethod
|
|
179
|
+
public void schnorrPubkey(String privkeyHex, Promise promise) {
|
|
180
|
+
try {
|
|
181
|
+
byte[] pubkey = nativeSchnorrPubkey(hexToBytes(privkeyHex));
|
|
182
|
+
promise.resolve(bytesToHex(pubkey));
|
|
183
|
+
} catch (Exception e) { promise.reject("ERR", e.getMessage()); }
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
@ReactMethod
|
|
187
|
+
public void ecdh(String privkeyHex, String pubkeyHex, Promise promise) {
|
|
188
|
+
try {
|
|
189
|
+
byte[] secret = nativeEcdh(hexToBytes(privkeyHex), hexToBytes(pubkeyHex));
|
|
190
|
+
promise.resolve(bytesToHex(secret));
|
|
191
|
+
} catch (Exception e) { promise.reject("ERR", e.getMessage()); }
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
@ReactMethod
|
|
195
|
+
public void ecdhXonly(String privkeyHex, String pubkeyHex, Promise promise) {
|
|
196
|
+
try {
|
|
197
|
+
byte[] secret = nativeEcdhXonly(hexToBytes(privkeyHex), hexToBytes(pubkeyHex));
|
|
198
|
+
promise.resolve(bytesToHex(secret));
|
|
199
|
+
} catch (Exception e) { promise.reject("ERR", e.getMessage()); }
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
@ReactMethod
|
|
203
|
+
public void ecdhRaw(String privkeyHex, String pubkeyHex, Promise promise) {
|
|
204
|
+
try {
|
|
205
|
+
byte[] secret = nativeEcdhRaw(hexToBytes(privkeyHex), hexToBytes(pubkeyHex));
|
|
206
|
+
promise.resolve(bytesToHex(secret));
|
|
207
|
+
} catch (Exception e) { promise.reject("ERR", e.getMessage()); }
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
@ReactMethod
|
|
211
|
+
public void sha256(String dataHex, Promise promise) {
|
|
212
|
+
try {
|
|
213
|
+
byte[] digest = nativeSha256(hexToBytes(dataHex));
|
|
214
|
+
promise.resolve(bytesToHex(digest));
|
|
215
|
+
} catch (Exception e) { promise.reject("ERR", e.getMessage()); }
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
@ReactMethod
|
|
219
|
+
public void hash160(String dataHex, Promise promise) {
|
|
220
|
+
try {
|
|
221
|
+
byte[] digest = nativeHash160(hexToBytes(dataHex));
|
|
222
|
+
promise.resolve(bytesToHex(digest));
|
|
223
|
+
} catch (Exception e) { promise.reject("ERR", e.getMessage()); }
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
@ReactMethod
|
|
227
|
+
public void taggedHash(String tag, String dataHex, Promise promise) {
|
|
228
|
+
try {
|
|
229
|
+
byte[] digest = nativeTaggedHash(tag, hexToBytes(dataHex));
|
|
230
|
+
promise.resolve(bytesToHex(digest));
|
|
231
|
+
} catch (Exception e) { promise.reject("ERR", e.getMessage()); }
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
@ReactMethod
|
|
235
|
+
public void addressP2PKH(String pubkeyHex, int network, Promise promise) {
|
|
236
|
+
try {
|
|
237
|
+
promise.resolve(nativeAddressP2PKH(hexToBytes(pubkeyHex), network));
|
|
238
|
+
} catch (Exception e) { promise.reject("ERR", e.getMessage()); }
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
@ReactMethod
|
|
242
|
+
public void addressP2WPKH(String pubkeyHex, int network, Promise promise) {
|
|
243
|
+
try {
|
|
244
|
+
promise.resolve(nativeAddressP2WPKH(hexToBytes(pubkeyHex), network));
|
|
245
|
+
} catch (Exception e) { promise.reject("ERR", e.getMessage()); }
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
@ReactMethod
|
|
249
|
+
public void addressP2TR(String internalKeyXHex, int network, Promise promise) {
|
|
250
|
+
try {
|
|
251
|
+
promise.resolve(nativeAddressP2TR(hexToBytes(internalKeyXHex), network));
|
|
252
|
+
} catch (Exception e) { promise.reject("ERR", e.getMessage()); }
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
@ReactMethod
|
|
256
|
+
public void wifEncode(String privkeyHex, boolean compressed, int network, Promise promise) {
|
|
257
|
+
try {
|
|
258
|
+
promise.resolve(nativeWifEncode(hexToBytes(privkeyHex), compressed, network));
|
|
259
|
+
} catch (Exception e) { promise.reject("ERR", e.getMessage()); }
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
@ReactMethod
|
|
263
|
+
public void wifDecode(String wif, Promise promise) {
|
|
264
|
+
try {
|
|
265
|
+
Object[] result = nativeWifDecode(wif);
|
|
266
|
+
WritableMap map = Arguments.createMap();
|
|
267
|
+
map.putString("privkey", bytesToHex((byte[]) result[0]));
|
|
268
|
+
map.putBoolean("compressed", (boolean) result[1]);
|
|
269
|
+
map.putInt("network", (int) result[2]);
|
|
270
|
+
promise.resolve(map);
|
|
271
|
+
} catch (Exception e) { promise.reject("ERR", e.getMessage()); }
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
@ReactMethod
|
|
275
|
+
public void bip32MasterKey(String seedHex, Promise promise) {
|
|
276
|
+
try {
|
|
277
|
+
byte[] key = nativeBip32MasterKey(hexToBytes(seedHex));
|
|
278
|
+
promise.resolve(bytesToHex(key));
|
|
279
|
+
} catch (Exception e) { promise.reject("ERR", e.getMessage()); }
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
@ReactMethod
|
|
283
|
+
public void bip32DeriveChild(String parentKeyHex, int index, Promise promise) {
|
|
284
|
+
try {
|
|
285
|
+
byte[] key = nativeBip32DeriveChild(hexToBytes(parentKeyHex), index);
|
|
286
|
+
promise.resolve(bytesToHex(key));
|
|
287
|
+
} catch (Exception e) { promise.reject("ERR", e.getMessage()); }
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
@ReactMethod
|
|
291
|
+
public void bip32DerivePath(String masterKeyHex, String path, Promise promise) {
|
|
292
|
+
try {
|
|
293
|
+
byte[] key = nativeBip32DerivePath(hexToBytes(masterKeyHex), path);
|
|
294
|
+
promise.resolve(bytesToHex(key));
|
|
295
|
+
} catch (Exception e) { promise.reject("ERR", e.getMessage()); }
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
@ReactMethod
|
|
299
|
+
public void bip32GetPrivkey(String keyHex, Promise promise) {
|
|
300
|
+
try {
|
|
301
|
+
byte[] pk = nativeBip32GetPrivkey(hexToBytes(keyHex));
|
|
302
|
+
promise.resolve(bytesToHex(pk));
|
|
303
|
+
} catch (Exception e) { promise.reject("ERR", e.getMessage()); }
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
@ReactMethod
|
|
307
|
+
public void bip32GetPubkey(String keyHex, Promise promise) {
|
|
308
|
+
try {
|
|
309
|
+
byte[] pk = nativeBip32GetPubkey(hexToBytes(keyHex));
|
|
310
|
+
promise.resolve(bytesToHex(pk));
|
|
311
|
+
} catch (Exception e) { promise.reject("ERR", e.getMessage()); }
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
@ReactMethod
|
|
315
|
+
public void taprootOutputKey(String internalKeyXHex, @Nullable String merkleRootHex, Promise promise) {
|
|
316
|
+
try {
|
|
317
|
+
byte[] mr = merkleRootHex != null ? hexToBytes(merkleRootHex) : null;
|
|
318
|
+
Object[] result = nativeTaprootOutputKey(hexToBytes(internalKeyXHex), mr);
|
|
319
|
+
WritableMap map = Arguments.createMap();
|
|
320
|
+
map.putString("outputKeyX", bytesToHex((byte[]) result[0]));
|
|
321
|
+
map.putInt("parity", (int) result[1]);
|
|
322
|
+
promise.resolve(map);
|
|
323
|
+
} catch (Exception e) { promise.reject("ERR", e.getMessage()); }
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
@ReactMethod
|
|
327
|
+
public void taprootTweakPrivkey(String privkeyHex, @Nullable String merkleRootHex, Promise promise) {
|
|
328
|
+
try {
|
|
329
|
+
byte[] mr = merkleRootHex != null ? hexToBytes(merkleRootHex) : null;
|
|
330
|
+
byte[] result = nativeTaprootTweakPrivkey(hexToBytes(privkeyHex), mr);
|
|
331
|
+
promise.resolve(bytesToHex(result));
|
|
332
|
+
} catch (Exception e) { promise.reject("ERR", e.getMessage()); }
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
@ReactMethod
|
|
336
|
+
public void taprootVerifyCommitment(String outputKeyXHex, int parity,
|
|
337
|
+
String internalKeyXHex, @Nullable String merkleRootHex, Promise promise) {
|
|
338
|
+
try {
|
|
339
|
+
byte[] mr = merkleRootHex != null ? hexToBytes(merkleRootHex) : null;
|
|
340
|
+
promise.resolve(nativeTaprootVerifyCommitment(hexToBytes(outputKeyXHex), parity,
|
|
341
|
+
hexToBytes(internalKeyXHex), mr));
|
|
342
|
+
} catch (Exception e) { promise.reject("ERR", e.getMessage()); }
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
// ── Native declarations ──────────────────────────────────────────────
|
|
346
|
+
// These delegate to the JNI bridge (same as com.ultrafast.secp256k1.Secp256k1)
|
|
347
|
+
|
|
348
|
+
private static native int nativeInit();
|
|
349
|
+
private static native String nativeVersion();
|
|
350
|
+
private static native byte[] nativeEcPubkeyCreate(byte[] privkey);
|
|
351
|
+
private static native byte[] nativeEcPubkeyCreateUncompressed(byte[] privkey);
|
|
352
|
+
private static native byte[] nativeEcPubkeyParse(byte[] input);
|
|
353
|
+
private static native boolean nativeEcSeckeyVerify(byte[] privkey);
|
|
354
|
+
private static native byte[] nativeEcPrivkeyNegate(byte[] privkey);
|
|
355
|
+
private static native byte[] nativeEcPrivkeyTweakAdd(byte[] privkey, byte[] tweak);
|
|
356
|
+
private static native byte[] nativeEcPrivkeyTweakMul(byte[] privkey, byte[] tweak);
|
|
357
|
+
private static native byte[] nativeEcdsaSign(byte[] msgHash, byte[] privkey);
|
|
358
|
+
private static native boolean nativeEcdsaVerify(byte[] msgHash, byte[] sig, byte[] pubkey);
|
|
359
|
+
private static native byte[] nativeEcdsaSerializeDer(byte[] sig);
|
|
360
|
+
private static native Object[] nativeEcdsaSignRecoverable(byte[] msgHash, byte[] privkey);
|
|
361
|
+
private static native byte[] nativeEcdsaRecover(byte[] msgHash, byte[] sig, int recid);
|
|
362
|
+
private static native byte[] nativeSchnorrSign(byte[] msg, byte[] privkey, byte[] auxRand);
|
|
363
|
+
private static native boolean nativeSchnorrVerify(byte[] msg, byte[] sig, byte[] pubkeyX);
|
|
364
|
+
private static native byte[] nativeSchnorrPubkey(byte[] privkey);
|
|
365
|
+
private static native byte[] nativeEcdh(byte[] privkey, byte[] pubkey);
|
|
366
|
+
private static native byte[] nativeEcdhXonly(byte[] privkey, byte[] pubkey);
|
|
367
|
+
private static native byte[] nativeEcdhRaw(byte[] privkey, byte[] pubkey);
|
|
368
|
+
private static native byte[] nativeSha256(byte[] data);
|
|
369
|
+
private static native byte[] nativeHash160(byte[] data);
|
|
370
|
+
private static native byte[] nativeTaggedHash(String tag, byte[] data);
|
|
371
|
+
private static native String nativeAddressP2PKH(byte[] pubkey, int network);
|
|
372
|
+
private static native String nativeAddressP2WPKH(byte[] pubkey, int network);
|
|
373
|
+
private static native String nativeAddressP2TR(byte[] internalKeyX, int network);
|
|
374
|
+
private static native String nativeWifEncode(byte[] privkey, boolean compressed, int network);
|
|
375
|
+
private static native Object[] nativeWifDecode(String wif);
|
|
376
|
+
private static native byte[] nativeBip32MasterKey(byte[] seed);
|
|
377
|
+
private static native byte[] nativeBip32DeriveChild(byte[] parentKey, int index);
|
|
378
|
+
private static native byte[] nativeBip32DerivePath(byte[] masterKey, String path);
|
|
379
|
+
private static native byte[] nativeBip32GetPrivkey(byte[] key);
|
|
380
|
+
private static native byte[] nativeBip32GetPubkey(byte[] key);
|
|
381
|
+
private static native Object[] nativeTaprootOutputKey(byte[] internalKeyX, byte[] merkleRoot);
|
|
382
|
+
private static native byte[] nativeTaprootTweakPrivkey(byte[] privkey, byte[] merkleRoot);
|
|
383
|
+
private static native boolean nativeTaprootVerifyCommitment(byte[] outputKeyX, int parity,
|
|
384
|
+
byte[] internalKeyX, byte[] merkleRoot);
|
|
385
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
package com.ultrafastsecp256k1;
|
|
2
|
+
|
|
3
|
+
import androidx.annotation.NonNull;
|
|
4
|
+
|
|
5
|
+
import com.facebook.react.ReactPackage;
|
|
6
|
+
import com.facebook.react.bridge.NativeModule;
|
|
7
|
+
import com.facebook.react.bridge.ReactApplicationContext;
|
|
8
|
+
import com.facebook.react.uimanager.ViewManager;
|
|
9
|
+
|
|
10
|
+
import java.util.ArrayList;
|
|
11
|
+
import java.util.Collections;
|
|
12
|
+
import java.util.List;
|
|
13
|
+
|
|
14
|
+
public class UltrafastSecp256k1Package implements ReactPackage {
|
|
15
|
+
@NonNull
|
|
16
|
+
@Override
|
|
17
|
+
public List<NativeModule> createNativeModules(@NonNull ReactApplicationContext reactContext) {
|
|
18
|
+
List<NativeModule> modules = new ArrayList<>();
|
|
19
|
+
modules.add(new UltrafastSecp256k1Module(reactContext));
|
|
20
|
+
return modules;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
@NonNull
|
|
24
|
+
@Override
|
|
25
|
+
public List<ViewManager> createViewManagers(@NonNull ReactApplicationContext reactContext) {
|
|
26
|
+
return Collections.emptyList();
|
|
27
|
+
}
|
|
28
|
+
}
|