react-native-nitro-ark 0.0.76 → 0.0.77-rc.2
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/CMakeLists.txt +1 -0
- package/android/src/main/cpp/NitroArkJni.cpp +388 -0
- package/android/src/main/java/com/margelo/nitro/nitroark/NativeTypes.kt +21 -0
- package/android/src/main/java/com/margelo/nitro/nitroark/NitroArkNative.kt +98 -0
- package/android/src/main/jniLibs/arm64-v8a/libbark_cpp.a +0 -0
- package/android/src/main/jniLibs/x86_64/libbark_cpp.a +0 -0
- package/package.json +1 -1
package/android/CMakeLists.txt
CHANGED
|
@@ -0,0 +1,388 @@
|
|
|
1
|
+
#include <android/log.h>
|
|
2
|
+
#include <cstdint>
|
|
3
|
+
#include <exception>
|
|
4
|
+
#include <jni.h>
|
|
5
|
+
#include <optional>
|
|
6
|
+
#include <stdexcept>
|
|
7
|
+
#include <string>
|
|
8
|
+
#include <type_traits>
|
|
9
|
+
#include <vector>
|
|
10
|
+
|
|
11
|
+
#include "generated/ark_cxx.h"
|
|
12
|
+
|
|
13
|
+
namespace {
|
|
14
|
+
|
|
15
|
+
constexpr const char* LOG_TAG = "NitroArkJni";
|
|
16
|
+
|
|
17
|
+
// Convert a jstring to a std::string, handling null safely.
|
|
18
|
+
std::string JStringToString(JNIEnv* env, jstring jStr) {
|
|
19
|
+
if (jStr == nullptr) {
|
|
20
|
+
return std::string();
|
|
21
|
+
}
|
|
22
|
+
const char* chars = env->GetStringUTFChars(jStr, nullptr);
|
|
23
|
+
if (chars == nullptr) {
|
|
24
|
+
return std::string();
|
|
25
|
+
}
|
|
26
|
+
std::string result(chars);
|
|
27
|
+
env->ReleaseStringUTFChars(jStr, chars);
|
|
28
|
+
return result;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
void ThrowJavaException(JNIEnv* env, const char* message) {
|
|
32
|
+
jclass exClass = env->FindClass("java/lang/RuntimeException");
|
|
33
|
+
if (exClass != nullptr) {
|
|
34
|
+
env->ThrowNew(exClass, message);
|
|
35
|
+
}
|
|
36
|
+
__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, "Throwing Java exception: %s", message);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
template <typename T, typename J>
|
|
40
|
+
std::optional<T> GetOptionalNumber(JNIEnv* env, jobject obj, const char* className, const char* methodName,
|
|
41
|
+
const char* methodSig) {
|
|
42
|
+
if (obj == nullptr) {
|
|
43
|
+
return std::nullopt;
|
|
44
|
+
}
|
|
45
|
+
jclass cls = env->FindClass(className);
|
|
46
|
+
if (cls == nullptr) {
|
|
47
|
+
return std::nullopt;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
std::optional<T> result = std::nullopt;
|
|
51
|
+
jmethodID mid = env->GetMethodID(cls, methodName, methodSig);
|
|
52
|
+
if (mid != nullptr) {
|
|
53
|
+
if constexpr (std::is_same_v<J, jint>) {
|
|
54
|
+
jint value = env->CallIntMethod(obj, mid);
|
|
55
|
+
result = static_cast<T>(value);
|
|
56
|
+
} else if constexpr (std::is_same_v<J, jlong>) {
|
|
57
|
+
jlong value = env->CallLongMethod(obj, mid);
|
|
58
|
+
result = static_cast<T>(value);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
env->DeleteLocalRef(cls);
|
|
63
|
+
return result;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
std::optional<int32_t> GetOptionalInt(JNIEnv* env, jobject obj) {
|
|
67
|
+
return GetOptionalNumber<int32_t, jint>(env, obj, "java/lang/Integer", "intValue", "()I");
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
std::optional<int64_t> GetOptionalLong(JNIEnv* env, jobject obj) {
|
|
71
|
+
return GetOptionalNumber<int64_t, jlong>(env, obj, "java/lang/Long", "longValue", "()J");
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
void HandleException(JNIEnv* env, const std::exception& e) {
|
|
75
|
+
__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, "Native exception: %s", e.what());
|
|
76
|
+
ThrowJavaException(env, e.what());
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
void HandleUnknownException(JNIEnv* env) {
|
|
80
|
+
__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, "Unknown exception in NitroArk native call.");
|
|
81
|
+
ThrowJavaException(env, "Unknown exception in NitroArk native call.");
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Helpers to construct Java/Kotlin objects for return values.
|
|
85
|
+
jobject MakeArrayList(JNIEnv* env, const std::vector<std::string>& elements) {
|
|
86
|
+
jclass arrayListClass = env->FindClass("java/util/ArrayList");
|
|
87
|
+
if (arrayListClass == nullptr)
|
|
88
|
+
return nullptr;
|
|
89
|
+
jmethodID arrayListCtor = env->GetMethodID(arrayListClass, "<init>", "()V");
|
|
90
|
+
jmethodID arrayListAdd = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
|
|
91
|
+
if (arrayListCtor == nullptr || arrayListAdd == nullptr)
|
|
92
|
+
return nullptr;
|
|
93
|
+
|
|
94
|
+
jobject arrayListObj = env->NewObject(arrayListClass, arrayListCtor);
|
|
95
|
+
if (arrayListObj == nullptr)
|
|
96
|
+
return nullptr;
|
|
97
|
+
|
|
98
|
+
for (const auto& element : elements) {
|
|
99
|
+
jstring jStr = env->NewStringUTF(element.c_str());
|
|
100
|
+
if (jStr != nullptr) {
|
|
101
|
+
env->CallBooleanMethod(arrayListObj, arrayListAdd, jStr);
|
|
102
|
+
env->DeleteLocalRef(jStr);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
env->DeleteLocalRef(arrayListClass);
|
|
106
|
+
return arrayListObj;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
jobject MakeRoundStatusResult(JNIEnv* env, const bark_cxx::RoundStatus& status) {
|
|
110
|
+
jclass cls = env->FindClass("com/margelo/nitro/nitroark/RoundStatusResult");
|
|
111
|
+
if (cls == nullptr)
|
|
112
|
+
return nullptr;
|
|
113
|
+
jmethodID ctor =
|
|
114
|
+
env->GetMethodID(cls, "<init>", "(Ljava/lang/String;Ljava/lang/String;Ljava/util/List;Ljava/lang/String;ZZ)V");
|
|
115
|
+
if (ctor == nullptr)
|
|
116
|
+
return nullptr;
|
|
117
|
+
|
|
118
|
+
std::string statusStr(status.status.data(), status.status.length());
|
|
119
|
+
std::string fundingTxid(status.funding_txid.data(), status.funding_txid.length());
|
|
120
|
+
std::string error(status.error.data(), status.error.length());
|
|
121
|
+
|
|
122
|
+
// Convert unsigned txids
|
|
123
|
+
std::vector<std::string> txids;
|
|
124
|
+
txids.reserve(status.unsigned_funding_txids.size());
|
|
125
|
+
for (const auto& tx : status.unsigned_funding_txids) {
|
|
126
|
+
txids.emplace_back(std::string(tx.data(), tx.length()));
|
|
127
|
+
}
|
|
128
|
+
jobject txidList = MakeArrayList(env, txids);
|
|
129
|
+
|
|
130
|
+
jstring jStatus = env->NewStringUTF(statusStr.c_str());
|
|
131
|
+
jstring jFundingTxid = fundingTxid.empty() ? nullptr : env->NewStringUTF(fundingTxid.c_str());
|
|
132
|
+
jstring jError = error.empty() ? nullptr : env->NewStringUTF(error.c_str());
|
|
133
|
+
|
|
134
|
+
jobject result =
|
|
135
|
+
env->NewObject(cls, ctor, jStatus, jFundingTxid, txidList, jError, status.is_final, status.is_success);
|
|
136
|
+
|
|
137
|
+
if (jStatus)
|
|
138
|
+
env->DeleteLocalRef(jStatus);
|
|
139
|
+
if (jFundingTxid)
|
|
140
|
+
env->DeleteLocalRef(jFundingTxid);
|
|
141
|
+
if (jError)
|
|
142
|
+
env->DeleteLocalRef(jError);
|
|
143
|
+
if (txidList)
|
|
144
|
+
env->DeleteLocalRef(txidList);
|
|
145
|
+
env->DeleteLocalRef(cls);
|
|
146
|
+
return result;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
jobject MakeKeyPairResult(JNIEnv* env, const bark_cxx::KeyPairResult& keypair) {
|
|
150
|
+
jclass cls = env->FindClass("com/margelo/nitro/nitroark/KeyPairResultAndroid");
|
|
151
|
+
if (cls == nullptr)
|
|
152
|
+
return nullptr;
|
|
153
|
+
jmethodID ctor = env->GetMethodID(cls, "<init>", "(Ljava/lang/String;Ljava/lang/String;)V");
|
|
154
|
+
if (ctor == nullptr)
|
|
155
|
+
return nullptr;
|
|
156
|
+
|
|
157
|
+
std::string pub(keypair.public_key.data(), keypair.public_key.length());
|
|
158
|
+
std::string sec(keypair.secret_key.data(), keypair.secret_key.length());
|
|
159
|
+
|
|
160
|
+
jstring jPub = env->NewStringUTF(pub.c_str());
|
|
161
|
+
jstring jSec = env->NewStringUTF(sec.c_str());
|
|
162
|
+
|
|
163
|
+
jobject result = env->NewObject(cls, ctor, jPub, jSec);
|
|
164
|
+
|
|
165
|
+
if (jPub)
|
|
166
|
+
env->DeleteLocalRef(jPub);
|
|
167
|
+
if (jSec)
|
|
168
|
+
env->DeleteLocalRef(jSec);
|
|
169
|
+
env->DeleteLocalRef(cls);
|
|
170
|
+
return result;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
jobject MakeBolt11Invoice(JNIEnv* env, const bark_cxx::Bolt11Invoice& invoice) {
|
|
174
|
+
jclass cls = env->FindClass("com/margelo/nitro/nitroark/Bolt11InvoiceResult");
|
|
175
|
+
if (cls == nullptr)
|
|
176
|
+
return nullptr;
|
|
177
|
+
jmethodID ctor = env->GetMethodID(cls, "<init>", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
|
|
178
|
+
if (ctor == nullptr)
|
|
179
|
+
return nullptr;
|
|
180
|
+
|
|
181
|
+
std::string bolt11(invoice.bolt11_invoice.data(), invoice.bolt11_invoice.length());
|
|
182
|
+
std::string paymentSecret(invoice.payment_secret.data(), invoice.payment_secret.length());
|
|
183
|
+
std::string paymentHash(invoice.payment_hash.data(), invoice.payment_hash.length());
|
|
184
|
+
|
|
185
|
+
jstring jBolt11 = env->NewStringUTF(bolt11.c_str());
|
|
186
|
+
jstring jSecret = env->NewStringUTF(paymentSecret.c_str());
|
|
187
|
+
jstring jHash = env->NewStringUTF(paymentHash.c_str());
|
|
188
|
+
|
|
189
|
+
jobject result = env->NewObject(cls, ctor, jBolt11, jSecret, jHash);
|
|
190
|
+
|
|
191
|
+
if (jBolt11)
|
|
192
|
+
env->DeleteLocalRef(jBolt11);
|
|
193
|
+
if (jSecret)
|
|
194
|
+
env->DeleteLocalRef(jSecret);
|
|
195
|
+
if (jHash)
|
|
196
|
+
env->DeleteLocalRef(jHash);
|
|
197
|
+
env->DeleteLocalRef(cls);
|
|
198
|
+
return result;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
} // namespace
|
|
202
|
+
|
|
203
|
+
extern "C" {
|
|
204
|
+
|
|
205
|
+
JNIEXPORT jboolean JNICALL Java_com_margelo_nitro_nitroark_NitroArkNative_isWalletLoaded(JNIEnv* env,
|
|
206
|
+
jobject /*thiz*/) {
|
|
207
|
+
try {
|
|
208
|
+
return bark_cxx::is_wallet_loaded();
|
|
209
|
+
} catch (const std::exception& e) {
|
|
210
|
+
HandleException(env, e);
|
|
211
|
+
return JNI_FALSE;
|
|
212
|
+
} catch (...) {
|
|
213
|
+
HandleUnknownException(env);
|
|
214
|
+
return JNI_FALSE;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
JNIEXPORT void JNICALL Java_com_margelo_nitro_nitroark_NitroArkNative_closeWallet(JNIEnv* env, jobject /*thiz*/) {
|
|
219
|
+
try {
|
|
220
|
+
bark_cxx::close_wallet();
|
|
221
|
+
} catch (const std::exception& e) {
|
|
222
|
+
HandleException(env, e);
|
|
223
|
+
} catch (...) {
|
|
224
|
+
HandleUnknownException(env);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
JNIEXPORT void JNICALL Java_com_margelo_nitro_nitroark_NitroArkNative_loadWalletNative(
|
|
229
|
+
JNIEnv* env, jobject /*thiz*/, jstring jDatadir, jstring jMnemonic, jboolean jRegtest, jboolean jSignet,
|
|
230
|
+
jboolean jBitcoin, jobject jBirthdayHeight, jstring jArk, jstring jEsplora, jstring jBitcoind,
|
|
231
|
+
jstring jBitcoindCookie, jstring jBitcoindUser, jstring jBitcoindPass, jobject jVtxoRefreshExpiryThreshold,
|
|
232
|
+
jobject jFallbackFeeRate, jobject jHtlcRecvClaimDelta, jobject jVtxoExitMargin,
|
|
233
|
+
jobject jRoundTxRequiredConfirmations) {
|
|
234
|
+
try {
|
|
235
|
+
const std::string datadir = JStringToString(env, jDatadir);
|
|
236
|
+
const std::string mnemonic = JStringToString(env, jMnemonic);
|
|
237
|
+
|
|
238
|
+
bark_cxx::CreateOpts opts{};
|
|
239
|
+
opts.regtest = jRegtest == JNI_TRUE;
|
|
240
|
+
opts.signet = jSignet == JNI_TRUE;
|
|
241
|
+
opts.bitcoin = jBitcoin == JNI_TRUE;
|
|
242
|
+
opts.mnemonic = mnemonic;
|
|
243
|
+
|
|
244
|
+
auto birthday_height = GetOptionalInt(env, jBirthdayHeight);
|
|
245
|
+
thread_local uint32_t birthday_height_val = 0;
|
|
246
|
+
if (birthday_height.has_value()) {
|
|
247
|
+
birthday_height_val = static_cast<uint32_t>(birthday_height.value());
|
|
248
|
+
opts.birthday_height = &birthday_height_val;
|
|
249
|
+
} else {
|
|
250
|
+
opts.birthday_height = nullptr;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
bark_cxx::ConfigOpts config{};
|
|
254
|
+
config.ark = JStringToString(env, jArk);
|
|
255
|
+
config.esplora = JStringToString(env, jEsplora);
|
|
256
|
+
config.bitcoind = JStringToString(env, jBitcoind);
|
|
257
|
+
config.bitcoind_cookie = JStringToString(env, jBitcoindCookie);
|
|
258
|
+
config.bitcoind_user = JStringToString(env, jBitcoindUser);
|
|
259
|
+
config.bitcoind_pass = JStringToString(env, jBitcoindPass);
|
|
260
|
+
|
|
261
|
+
config.vtxo_refresh_expiry_threshold =
|
|
262
|
+
static_cast<uint32_t>(GetOptionalInt(env, jVtxoRefreshExpiryThreshold).value_or(0));
|
|
263
|
+
config.fallback_fee_rate = static_cast<uint64_t>(GetOptionalLong(env, jFallbackFeeRate).value_or(0));
|
|
264
|
+
config.htlc_recv_claim_delta = static_cast<uint16_t>(GetOptionalInt(env, jHtlcRecvClaimDelta).value_or(0));
|
|
265
|
+
config.vtxo_exit_margin = static_cast<uint16_t>(GetOptionalInt(env, jVtxoExitMargin).value_or(0));
|
|
266
|
+
config.round_tx_required_confirmations =
|
|
267
|
+
static_cast<uint32_t>(GetOptionalInt(env, jRoundTxRequiredConfirmations).value_or(0));
|
|
268
|
+
|
|
269
|
+
opts.config = config;
|
|
270
|
+
|
|
271
|
+
__android_log_print(ANDROID_LOG_INFO, LOG_TAG,
|
|
272
|
+
"load_wallet(native) datadir=%s regtest=%s signet=%s bitcoin=%s birthday_height=%s ark=%s "
|
|
273
|
+
"esplora=%s bitcoind=%s",
|
|
274
|
+
datadir.c_str(), opts.regtest ? "true" : "false", opts.signet ? "true" : "false",
|
|
275
|
+
opts.bitcoin ? "true" : "false",
|
|
276
|
+
opts.birthday_height != nullptr ? std::to_string(*opts.birthday_height).c_str() : "null",
|
|
277
|
+
config.ark.c_str(), config.esplora.c_str(), config.bitcoind.c_str());
|
|
278
|
+
|
|
279
|
+
bark_cxx::load_wallet(datadir, opts);
|
|
280
|
+
__android_log_print(ANDROID_LOG_INFO, LOG_TAG, "load_wallet(native) success");
|
|
281
|
+
} catch (const std::exception& e) {
|
|
282
|
+
HandleException(env, e);
|
|
283
|
+
} catch (...) {
|
|
284
|
+
HandleUnknownException(env);
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
JNIEXPORT void JNICALL Java_com_margelo_nitro_nitroark_NitroArkNative_maintenance(JNIEnv* env, jobject /*thiz*/) {
|
|
289
|
+
try {
|
|
290
|
+
bark_cxx::maintenance();
|
|
291
|
+
} catch (const std::exception& e) {
|
|
292
|
+
HandleException(env, e);
|
|
293
|
+
} catch (...) {
|
|
294
|
+
HandleUnknownException(env);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
JNIEXPORT void JNICALL Java_com_margelo_nitro_nitroark_NitroArkNative_maintenanceRefresh(JNIEnv* env,
|
|
299
|
+
jobject /*thiz*/) {
|
|
300
|
+
try {
|
|
301
|
+
bark_cxx::maintenance_refresh();
|
|
302
|
+
} catch (const std::exception& e) {
|
|
303
|
+
HandleException(env, e);
|
|
304
|
+
} catch (...) {
|
|
305
|
+
HandleUnknownException(env);
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
JNIEXPORT void JNICALL Java_com_margelo_nitro_nitroark_NitroArkNative_tryClaimLightningReceive(
|
|
310
|
+
JNIEnv* env, jobject /*thiz*/, jstring jPaymentHash, jboolean jWait, jstring jToken) {
|
|
311
|
+
try {
|
|
312
|
+
const std::string payment_hash = JStringToString(env, jPaymentHash);
|
|
313
|
+
const std::string token_str = JStringToString(env, jToken);
|
|
314
|
+
|
|
315
|
+
rust::String payment_hash_rs(payment_hash);
|
|
316
|
+
rust::String token_rs(token_str);
|
|
317
|
+
const rust::String* token_ptr = token_str.empty() ? nullptr : &token_rs;
|
|
318
|
+
|
|
319
|
+
bark_cxx::try_claim_lightning_receive(payment_hash_rs, jWait == JNI_TRUE, token_ptr);
|
|
320
|
+
} catch (const std::exception& e) {
|
|
321
|
+
HandleException(env, e);
|
|
322
|
+
} catch (...) {
|
|
323
|
+
HandleUnknownException(env);
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
JNIEXPORT jobject JNICALL Java_com_margelo_nitro_nitroark_NitroArkNative_offboardAll(JNIEnv* env, jobject /*thiz*/,
|
|
328
|
+
jstring jDestination) {
|
|
329
|
+
try {
|
|
330
|
+
const std::string destination = JStringToString(env, jDestination);
|
|
331
|
+
bark_cxx::RoundStatus status = bark_cxx::offboard_all(destination);
|
|
332
|
+
return MakeRoundStatusResult(env, status);
|
|
333
|
+
} catch (const std::exception& e) {
|
|
334
|
+
HandleException(env, e);
|
|
335
|
+
return nullptr;
|
|
336
|
+
} catch (...) {
|
|
337
|
+
HandleUnknownException(env);
|
|
338
|
+
return nullptr;
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
JNIEXPORT jobject JNICALL Java_com_margelo_nitro_nitroark_NitroArkNative_peakKeyPair(JNIEnv* env, jobject /*thiz*/,
|
|
343
|
+
jint jIndex) {
|
|
344
|
+
try {
|
|
345
|
+
bark_cxx::KeyPairResult keypair = bark_cxx::peak_keypair(static_cast<uint32_t>(jIndex));
|
|
346
|
+
return MakeKeyPairResult(env, keypair);
|
|
347
|
+
} catch (const std::exception& e) {
|
|
348
|
+
HandleException(env, e);
|
|
349
|
+
return nullptr;
|
|
350
|
+
} catch (...) {
|
|
351
|
+
HandleUnknownException(env);
|
|
352
|
+
return nullptr;
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
JNIEXPORT jboolean JNICALL Java_com_margelo_nitro_nitroark_NitroArkNative_verifyMessage(JNIEnv* env, jobject /*thiz*/,
|
|
357
|
+
jstring jMessage,
|
|
358
|
+
jstring jSignature,
|
|
359
|
+
jstring jPublicKey) {
|
|
360
|
+
try {
|
|
361
|
+
const std::string message = JStringToString(env, jMessage);
|
|
362
|
+
const std::string signature = JStringToString(env, jSignature);
|
|
363
|
+
const std::string publicKey = JStringToString(env, jPublicKey);
|
|
364
|
+
return bark_cxx::verify_message(message, signature, publicKey);
|
|
365
|
+
} catch (const std::exception& e) {
|
|
366
|
+
HandleException(env, e);
|
|
367
|
+
return JNI_FALSE;
|
|
368
|
+
} catch (...) {
|
|
369
|
+
HandleUnknownException(env);
|
|
370
|
+
return JNI_FALSE;
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
JNIEXPORT jobject JNICALL Java_com_margelo_nitro_nitroark_NitroArkNative_bolt11Invoice(JNIEnv* env, jobject /*thiz*/,
|
|
375
|
+
jlong jAmountMsat) {
|
|
376
|
+
try {
|
|
377
|
+
bark_cxx::Bolt11Invoice invoice = bark_cxx::bolt11_invoice(static_cast<uint64_t>(jAmountMsat));
|
|
378
|
+
return MakeBolt11Invoice(env, invoice);
|
|
379
|
+
} catch (const std::exception& e) {
|
|
380
|
+
HandleException(env, e);
|
|
381
|
+
return nullptr;
|
|
382
|
+
} catch (...) {
|
|
383
|
+
HandleUnknownException(env);
|
|
384
|
+
return nullptr;
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
} // extern "C"
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
package com.margelo.nitro.nitroark
|
|
2
|
+
|
|
3
|
+
data class Bolt11InvoiceResult(
|
|
4
|
+
val bolt11Invoice: String,
|
|
5
|
+
val paymentSecret: String,
|
|
6
|
+
val paymentHash: String,
|
|
7
|
+
)
|
|
8
|
+
|
|
9
|
+
data class KeyPairResultAndroid(
|
|
10
|
+
val publicKey: String,
|
|
11
|
+
val secretKey: String,
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
data class RoundStatusResult(
|
|
15
|
+
val status: String,
|
|
16
|
+
val fundingTxid: String?,
|
|
17
|
+
val unsignedFundingTxids: List<String>,
|
|
18
|
+
val error: String?,
|
|
19
|
+
val isFinal: Boolean,
|
|
20
|
+
val isSuccess: Boolean,
|
|
21
|
+
)
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
package com.margelo.nitro.nitroark
|
|
2
|
+
|
|
3
|
+
import android.util.Log
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Kotlin facade for JNI helpers that call directly into the NitroArk C++/Rust layer.
|
|
7
|
+
* This is intended for Android-only consumers who want to bypass the JS surface.
|
|
8
|
+
*/
|
|
9
|
+
object NitroArkNative {
|
|
10
|
+
data class AndroidBarkConfig(
|
|
11
|
+
val ark: String? = null,
|
|
12
|
+
val esplora: String? = null,
|
|
13
|
+
val bitcoind: String? = null,
|
|
14
|
+
val bitcoindCookie: String? = null,
|
|
15
|
+
val bitcoindUser: String? = null,
|
|
16
|
+
val bitcoindPass: String? = null,
|
|
17
|
+
val vtxoRefreshExpiryThreshold: Int? = null,
|
|
18
|
+
val fallbackFeeRate: Long? = null,
|
|
19
|
+
val htlcRecvClaimDelta: Int? = null,
|
|
20
|
+
val vtxoExitMargin: Int? = null,
|
|
21
|
+
val roundTxRequiredConfirmations: Int? = null,
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
init {
|
|
25
|
+
// Reuse existing loader to ensure the shared library is available.
|
|
26
|
+
NitroArkOnLoad.initializeNative()
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Load an existing wallet using optional chain/config overrides.
|
|
31
|
+
*/
|
|
32
|
+
fun loadWallet(
|
|
33
|
+
datadir: String,
|
|
34
|
+
mnemonic: String,
|
|
35
|
+
regtest: Boolean = false,
|
|
36
|
+
signet: Boolean = false,
|
|
37
|
+
bitcoin: Boolean = true,
|
|
38
|
+
birthdayHeight: Int? = null,
|
|
39
|
+
config: AndroidBarkConfig? = null
|
|
40
|
+
) {
|
|
41
|
+
Log.i("NitroArkNative", "loadWallet(datadir=$datadir regtest=$regtest signet=$signet bitcoin=$bitcoin)")
|
|
42
|
+
loadWalletNative(
|
|
43
|
+
datadir,
|
|
44
|
+
mnemonic,
|
|
45
|
+
regtest,
|
|
46
|
+
signet,
|
|
47
|
+
bitcoin,
|
|
48
|
+
birthdayHeight,
|
|
49
|
+
config?.ark,
|
|
50
|
+
config?.esplora,
|
|
51
|
+
config?.bitcoind,
|
|
52
|
+
config?.bitcoindCookie,
|
|
53
|
+
config?.bitcoindUser,
|
|
54
|
+
config?.bitcoindPass,
|
|
55
|
+
config?.vtxoRefreshExpiryThreshold,
|
|
56
|
+
config?.fallbackFeeRate,
|
|
57
|
+
config?.htlcRecvClaimDelta,
|
|
58
|
+
config?.vtxoExitMargin,
|
|
59
|
+
config?.roundTxRequiredConfirmations)
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
external fun isWalletLoaded(): Boolean
|
|
63
|
+
external fun closeWallet()
|
|
64
|
+
|
|
65
|
+
// Native entrypoint with all parameters expanded for JNI.
|
|
66
|
+
private external fun loadWalletNative(
|
|
67
|
+
datadir: String,
|
|
68
|
+
mnemonic: String,
|
|
69
|
+
regtest: Boolean,
|
|
70
|
+
signet: Boolean,
|
|
71
|
+
bitcoin: Boolean,
|
|
72
|
+
birthdayHeight: Int?,
|
|
73
|
+
ark: String?,
|
|
74
|
+
esplora: String?,
|
|
75
|
+
bitcoind: String?,
|
|
76
|
+
bitcoindCookie: String?,
|
|
77
|
+
bitcoindUser: String?,
|
|
78
|
+
bitcoindPass: String?,
|
|
79
|
+
vtxoRefreshExpiryThreshold: Int?,
|
|
80
|
+
fallbackFeeRate: Long?,
|
|
81
|
+
htlcRecvClaimDelta: Int?,
|
|
82
|
+
vtxoExitMargin: Int?,
|
|
83
|
+
roundTxRequiredConfirmations: Int?,
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
// Additional helpers
|
|
87
|
+
external fun maintenance()
|
|
88
|
+
external fun maintenanceRefresh()
|
|
89
|
+
external fun tryClaimLightningReceive(
|
|
90
|
+
paymentHash: String,
|
|
91
|
+
wait: Boolean,
|
|
92
|
+
token: String?
|
|
93
|
+
)
|
|
94
|
+
external fun offboardAll(destinationAddress: String): RoundStatusResult
|
|
95
|
+
external fun peakKeyPair(index: Int): KeyPairResultAndroid
|
|
96
|
+
external fun verifyMessage(message: String, signature: String, publicKey: String): Boolean
|
|
97
|
+
external fun bolt11Invoice(amountMsat: Long): Bolt11InvoiceResult
|
|
98
|
+
}
|
|
Binary file
|
|
Binary file
|