react-native-nitro-ark 0.0.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.
Files changed (55) hide show
  1. package/LICENSE +20 -0
  2. package/NitroArk.podspec +30 -0
  3. package/README.md +22 -0
  4. package/android/CMakeLists.txt +64 -0
  5. package/android/build.gradle +145 -0
  6. package/android/gradle.properties +5 -0
  7. package/android/src/main/AndroidManifest.xml +3 -0
  8. package/android/src/main/AndroidManifestNew.xml +2 -0
  9. package/android/src/main/cpp/cpp-adapter.cpp +6 -0
  10. package/android/src/main/java/com/nitroark/NitroArkPackage.kt +22 -0
  11. package/cpp/HybridArk.cpp +8 -0
  12. package/cpp/NitroArk.hpp +558 -0
  13. package/cpp/bark-cpp.h +382 -0
  14. package/lib/commonjs/NitroArk.nitro.js +6 -0
  15. package/lib/commonjs/NitroArk.nitro.js.map +1 -0
  16. package/lib/commonjs/index.js +292 -0
  17. package/lib/commonjs/index.js.map +1 -0
  18. package/lib/commonjs/package.json +1 -0
  19. package/lib/module/NitroArk.nitro.js +4 -0
  20. package/lib/module/NitroArk.nitro.js.map +1 -0
  21. package/lib/module/index.js +268 -0
  22. package/lib/module/index.js.map +1 -0
  23. package/lib/module/package.json +1 -0
  24. package/lib/typescript/commonjs/package.json +1 -0
  25. package/lib/typescript/commonjs/src/NitroArk.nitro.d.ts +59 -0
  26. package/lib/typescript/commonjs/src/NitroArk.nitro.d.ts.map +1 -0
  27. package/lib/typescript/commonjs/src/index.d.ts +180 -0
  28. package/lib/typescript/commonjs/src/index.d.ts.map +1 -0
  29. package/lib/typescript/module/package.json +1 -0
  30. package/lib/typescript/module/src/NitroArk.nitro.d.ts +59 -0
  31. package/lib/typescript/module/src/NitroArk.nitro.d.ts.map +1 -0
  32. package/lib/typescript/module/src/index.d.ts +180 -0
  33. package/lib/typescript/module/src/index.d.ts.map +1 -0
  34. package/nitrogen/generated/android/NitroArk+autolinking.cmake +78 -0
  35. package/nitrogen/generated/android/NitroArk+autolinking.gradle +27 -0
  36. package/nitrogen/generated/android/NitroArkOnLoad.cpp +44 -0
  37. package/nitrogen/generated/android/NitroArkOnLoad.hpp +25 -0
  38. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroark/NitroArkOnLoad.kt +35 -0
  39. package/nitrogen/generated/ios/NitroArk+autolinking.rb +60 -0
  40. package/nitrogen/generated/ios/NitroArk-Swift-Cxx-Bridge.cpp +17 -0
  41. package/nitrogen/generated/ios/NitroArk-Swift-Cxx-Bridge.hpp +27 -0
  42. package/nitrogen/generated/ios/NitroArk-Swift-Cxx-Umbrella.hpp +38 -0
  43. package/nitrogen/generated/ios/NitroArkAutolinking.mm +35 -0
  44. package/nitrogen/generated/ios/NitroArkAutolinking.swift +12 -0
  45. package/nitrogen/generated/shared/c++/BarkBalance.hpp +77 -0
  46. package/nitrogen/generated/shared/c++/BarkConfigOpts.hpp +90 -0
  47. package/nitrogen/generated/shared/c++/BarkCreateOpts.hpp +96 -0
  48. package/nitrogen/generated/shared/c++/BarkRefreshModeType.hpp +94 -0
  49. package/nitrogen/generated/shared/c++/BarkRefreshOpts.hpp +81 -0
  50. package/nitrogen/generated/shared/c++/BarkSendManyOutput.hpp +73 -0
  51. package/nitrogen/generated/shared/c++/HybridNitroArkSpec.cpp +40 -0
  52. package/nitrogen/generated/shared/c++/HybridNitroArkSpec.hpp +95 -0
  53. package/package.json +178 -0
  54. package/src/NitroArk.nitro.ts +159 -0
  55. package/src/index.tsx +443 -0
@@ -0,0 +1,558 @@
1
+ #pragma once
2
+
3
+ #include "HybridNitroArkSpec.hpp"
4
+ #include "bark-cpp.h"
5
+ #include <memory>
6
+ #include <stdexcept>
7
+ #include <string>
8
+ #include <vector>
9
+
10
+ namespace margelo::nitro::nitroark {
11
+
12
+ // Helper function to handle potential errors from bark-cpp calls
13
+ inline void check_bark_error(bark::bark_BarkError *error) {
14
+ if (error != nullptr) {
15
+ std::string error_message = "Bark-cpp error: Unknown";
16
+ if (error->message != nullptr) {
17
+ // Assuming error->message is valid C string allocated correctly
18
+ error_message = std::string("Bark-cpp error: ") + error->message;
19
+ }
20
+ // Use the FFI function to free the error struct and its contents
21
+ bark::bark_free_error(error);
22
+ throw std::runtime_error(error_message);
23
+ }
24
+ }
25
+
26
+ class NitroArk : public HybridNitroArkSpec {
27
+ public:
28
+ NitroArk() : HybridObject(TAG) {
29
+ // Initialize the Rust logger once when a NitroArk object is created.
30
+ bark::bark_init_logger();
31
+ }
32
+
33
+ // --- Management ---
34
+
35
+ std::shared_ptr<Promise<std::string>> createMnemonic() override {
36
+ return Promise<std::string>::async([]() {
37
+ char *mnemonic_c = bark::bark_create_mnemonic();
38
+ if (mnemonic_c == nullptr) {
39
+ throw std::runtime_error(
40
+ "Bark-cpp error: Failed to create mnemonic (returned NULL)");
41
+ }
42
+ std::string mnemonic_str(mnemonic_c);
43
+ bark::bark_free_string(mnemonic_c);
44
+ return mnemonic_str;
45
+ });
46
+ }
47
+
48
+ std::shared_ptr<Promise<void>>
49
+ createWallet(const std::string &datadir,
50
+ const BarkCreateOpts &opts) override {
51
+ return Promise<void>::async([datadir, opts]() {
52
+ bark::bark_BarkConfigOpts config = {
53
+ opts.config.has_value() && opts.config->asp.has_value()
54
+ ? opts.config->asp->c_str()
55
+ : nullptr,
56
+ opts.config.has_value() && opts.config->esplora.has_value()
57
+ ? opts.config->esplora->c_str()
58
+ : nullptr,
59
+ opts.config.has_value() && opts.config->bitcoind.has_value()
60
+ ? opts.config->bitcoind->c_str()
61
+ : nullptr,
62
+ opts.config.has_value() && opts.config->bitcoind_cookie.has_value()
63
+ ? opts.config->bitcoind_cookie->c_str()
64
+ : nullptr,
65
+ opts.config.has_value() && opts.config->bitcoind_user.has_value()
66
+ ? opts.config->bitcoind_user->c_str()
67
+ : nullptr,
68
+ opts.config.has_value() && opts.config->bitcoind_pass.has_value()
69
+ ? opts.config->bitcoind_pass->c_str()
70
+ : nullptr};
71
+
72
+ bark::bark_BarkCreateOpts barkOpts = {
73
+ opts.force.value_or(false),
74
+ opts.regtest.value_or(false),
75
+ opts.signet.value_or(false),
76
+ opts.bitcoin.value_or(true),
77
+ opts.mnemonic.empty() ? nullptr : opts.mnemonic.c_str(),
78
+ opts.birthday_height.has_value()
79
+ ? static_cast<uint32_t>(opts.birthday_height.value())
80
+ : 0,
81
+ config};
82
+
83
+ bark::bark_BarkError *error =
84
+ bark::bark_create_wallet(datadir.c_str(), barkOpts);
85
+ check_bark_error(error);
86
+ });
87
+ }
88
+
89
+ // --- Wallet Info ---
90
+
91
+ std::shared_ptr<Promise<BarkBalance>>
92
+ getBalance(const std::string &datadir, bool no_sync,
93
+ const std::string &mnemonic) override {
94
+ return Promise<BarkBalance>::async([datadir, no_sync, mnemonic]() {
95
+ bark::bark_BarkBalance c_balance;
96
+ bark::bark_BarkError *error = bark::bark_get_balance(
97
+ datadir.c_str(), no_sync, mnemonic.c_str(), &c_balance);
98
+ check_bark_error(error);
99
+
100
+ return BarkBalance(static_cast<double>(c_balance.onchain),
101
+ static_cast<double>(c_balance.offchain),
102
+ static_cast<double>(c_balance.pending_exit));
103
+ });
104
+ }
105
+
106
+ std::shared_ptr<Promise<std::string>>
107
+ getOnchainAddress(const std::string &datadir,
108
+ const std::string &mnemonic) override {
109
+ return Promise<std::string>::async([datadir, mnemonic]() {
110
+ char *address_c = nullptr;
111
+ bark::bark_BarkError *error = bark::bark_get_onchain_address(
112
+ datadir.c_str(), mnemonic.c_str(), &address_c);
113
+ check_bark_error(error);
114
+ if (address_c == nullptr) {
115
+ throw std::runtime_error("Bark-cpp error: getOnchainAddress returned "
116
+ "success but address is null");
117
+ }
118
+ std::string address_str(address_c);
119
+ bark::bark_free_string(address_c); // Use helper
120
+ return address_str;
121
+ });
122
+ }
123
+
124
+ std::shared_ptr<Promise<std::string>>
125
+ getOnchainUtxos(const std::string &datadir, const std::string &mnemonic,
126
+ bool no_sync) override {
127
+ return Promise<std::string>::async([datadir, mnemonic, no_sync]() {
128
+ char *json_c = nullptr;
129
+ bark::bark_BarkError *error = bark::bark_get_onchain_utxos(
130
+ datadir.c_str(), mnemonic.c_str(), no_sync, &json_c);
131
+ check_bark_error(error);
132
+ if (json_c == nullptr) {
133
+ throw std::runtime_error("Bark-cpp error: getOnchainUtxos returned "
134
+ "success but JSON is null");
135
+ }
136
+ std::string json_str(json_c);
137
+ bark::bark_free_string(json_c); // Use helper
138
+ return json_str;
139
+ });
140
+ }
141
+
142
+ std::shared_ptr<Promise<std::string>>
143
+ getVtxoPubkey(const std::string &datadir,
144
+ const std::string &mnemonic) override {
145
+ return Promise<std::string>::async([datadir, mnemonic]() {
146
+ char *pubkey_c = nullptr;
147
+ bark::bark_BarkError *error = bark::bark_get_vtxo_pubkey(
148
+ datadir.c_str(), mnemonic.c_str(), &pubkey_c);
149
+ check_bark_error(error);
150
+ if (pubkey_c == nullptr) {
151
+ throw std::runtime_error("Bark-cpp error: getVtxoPubkey returned "
152
+ "success but pubkey is null");
153
+ }
154
+ std::string pubkey_str(pubkey_c);
155
+ bark::bark_free_string(pubkey_c); // Use helper
156
+ return pubkey_str;
157
+ });
158
+ }
159
+
160
+ std::shared_ptr<Promise<std::string>> getVtxos(const std::string &datadir,
161
+ const std::string &mnemonic,
162
+ bool no_sync) override {
163
+ return Promise<std::string>::async([datadir, mnemonic, no_sync]() {
164
+ char *json_c = nullptr;
165
+ bark::bark_BarkError *error = bark::bark_get_vtxos(
166
+ datadir.c_str(), mnemonic.c_str(), no_sync, &json_c);
167
+ check_bark_error(error);
168
+ if (json_c == nullptr) {
169
+ throw std::runtime_error(
170
+ "Bark-cpp error: getVtxos returned success but JSON is null");
171
+ }
172
+ std::string json_str(json_c);
173
+ bark::bark_free_string(json_c); // Use helper
174
+ return json_str;
175
+ });
176
+ }
177
+
178
+ // --- Onchain Operations ---
179
+
180
+ std::shared_ptr<Promise<std::string>>
181
+ sendOnchain(const std::string &datadir, const std::string &mnemonic,
182
+ const std::string &destination, double amountSat,
183
+ bool no_sync) override {
184
+ return Promise<std::string>::async([datadir, mnemonic, destination,
185
+ amountSat, no_sync]() {
186
+ char *txid_c = nullptr;
187
+ bark::bark_BarkError *error = bark::bark_send_onchain(
188
+ datadir.c_str(), mnemonic.c_str(), destination.c_str(),
189
+ static_cast<uint64_t>(amountSat), no_sync, &txid_c);
190
+ check_bark_error(error);
191
+ if (txid_c == nullptr) {
192
+ throw std::runtime_error(
193
+ "Bark-cpp error: sendOnchain returned success but txid is null");
194
+ }
195
+ std::string txid_str(txid_c);
196
+ bark::bark_free_string(txid_c); // Use helper
197
+ return txid_str;
198
+ });
199
+ }
200
+
201
+ std::shared_ptr<Promise<std::string>>
202
+ drainOnchain(const std::string &datadir, const std::string &mnemonic,
203
+ const std::string &destination, bool no_sync) override {
204
+ return Promise<std::string>::async(
205
+ [datadir, mnemonic, destination, no_sync]() {
206
+ char *txid_c = nullptr;
207
+ bark::bark_BarkError *error =
208
+ bark::bark_drain_onchain(datadir.c_str(), mnemonic.c_str(),
209
+ destination.c_str(), no_sync, &txid_c);
210
+ check_bark_error(error);
211
+ if (txid_c == nullptr) {
212
+ throw std::runtime_error("Bark-cpp error: drainOnchain returned "
213
+ "success but txid is null");
214
+ }
215
+ std::string txid_str(txid_c);
216
+ bark::bark_free_string(txid_c); // Use helper
217
+ return txid_str;
218
+ });
219
+ }
220
+
221
+ std::shared_ptr<Promise<std::string>>
222
+ sendManyOnchain(const std::string &datadir, const std::string &mnemonic,
223
+ const std::vector<BarkSendManyOutput> &outputs,
224
+ bool no_sync) override {
225
+ return Promise<std::string>::async([datadir, mnemonic, outputs, no_sync]() {
226
+ size_t num_outputs = outputs.size();
227
+ if (num_outputs == 0) {
228
+ throw std::runtime_error(
229
+ "sendManyOnchain requires at least one output");
230
+ }
231
+
232
+ std::vector<const char *> destinations_c;
233
+ std::vector<uint64_t> amounts_c;
234
+ destinations_c.reserve(num_outputs);
235
+ amounts_c.reserve(num_outputs);
236
+
237
+ for (const auto &output : outputs) {
238
+ // --- FIX: Access directly, no .value() ---
239
+ destinations_c.push_back(output.destination.c_str());
240
+ amounts_c.push_back(static_cast<uint64_t>(output.amountSat));
241
+ // --- End FIX ---
242
+ }
243
+
244
+ char *txid_c = nullptr;
245
+ bark::bark_BarkError *error = bark::bark_send_many_onchain(
246
+ datadir.c_str(), mnemonic.c_str(), destinations_c.data(),
247
+ amounts_c.data(), num_outputs, no_sync, &txid_c);
248
+ check_bark_error(error);
249
+ if (txid_c == nullptr) {
250
+ throw std::runtime_error("Bark-cpp error: sendManyOnchain returned "
251
+ "success but txid is null");
252
+ }
253
+ std::string txid_str(txid_c);
254
+ bark::bark_free_string(txid_c); // Use helper
255
+ return txid_str;
256
+ });
257
+ }
258
+
259
+ // --- Ark Operations ---
260
+
261
+ std::shared_ptr<Promise<std::string>>
262
+ refreshVtxos(const std::string &datadir, const std::string &mnemonic,
263
+ const BarkRefreshOpts &refreshOpts, bool no_sync) override {
264
+ return Promise<std::string>::async([datadir, mnemonic, refreshOpts,
265
+ no_sync]() {
266
+ bark::bark_BarkRefreshOpts c_opts;
267
+ std::vector<const char *> specific_ids_c; // Keep alive for the C call
268
+
269
+ // Map the C++ enum to the C FFI enum using a switch
270
+ switch (refreshOpts.mode_type) {
271
+ case margelo::nitro::nitroark::BarkRefreshModeType::DEFAULTTHRESHOLD:
272
+ c_opts.mode_type = bark::bark_BarkRefreshModeType::DefaultThreshold;
273
+ break;
274
+ case margelo::nitro::nitroark::BarkRefreshModeType::THRESHOLDBLOCKS:
275
+ c_opts.mode_type = bark::bark_BarkRefreshModeType::ThresholdBlocks;
276
+ break;
277
+ case margelo::nitro::nitroark::BarkRefreshModeType::THRESHOLDHOURS:
278
+ c_opts.mode_type = bark::bark_BarkRefreshModeType::ThresholdHours;
279
+ break;
280
+ case margelo::nitro::nitroark::BarkRefreshModeType::COUNTERPARTY:
281
+ c_opts.mode_type = bark::bark_BarkRefreshModeType::Counterparty;
282
+ break;
283
+ case margelo::nitro::nitroark::BarkRefreshModeType::ALL:
284
+ c_opts.mode_type = bark::bark_BarkRefreshModeType::All;
285
+ break;
286
+ case margelo::nitro::nitroark::BarkRefreshModeType::SPECIFIC:
287
+ c_opts.mode_type = bark::bark_BarkRefreshModeType::Specific;
288
+ break;
289
+ default:
290
+ // This should ideally not happen with a closed enum, but handle
291
+ // defensively
292
+ throw std::runtime_error(
293
+ "Unknown BarkRefreshModeType encountered: " +
294
+ std::to_string(static_cast<int>(refreshOpts.mode_type)));
295
+ }
296
+
297
+ // Assign threshold_value (handle optional)
298
+ // Note: C struct expects uint32_t, C++ has optional<double>. Cast needed.
299
+ c_opts.threshold_value =
300
+ static_cast<uint32_t>(refreshOpts.threshold_value.value_or(0));
301
+
302
+ // Handle specific_vtxo_ids only if mode is Specific
303
+ if (c_opts.mode_type == bark::bark_BarkRefreshModeType::Specific) {
304
+ if (!refreshOpts.specific_vtxo_ids.has_value() ||
305
+ refreshOpts.specific_vtxo_ids->empty()) {
306
+ throw std::runtime_error(
307
+ "Specific refresh mode requires non-empty specific_vtxo_ids");
308
+ }
309
+ specific_ids_c.reserve(refreshOpts.specific_vtxo_ids->size());
310
+ for (const auto &id : refreshOpts.specific_vtxo_ids.value()) {
311
+ specific_ids_c.push_back(id.c_str()); // Get C string pointer
312
+ }
313
+ c_opts.specific_vtxo_ids =
314
+ specific_ids_c.data(); // Point to the data in the vector
315
+ c_opts.num_specific_vtxo_ids = specific_ids_c.size(); // Get the size
316
+ } else {
317
+ // Ensure these are null/zero if not in Specific mode
318
+ c_opts.specific_vtxo_ids = nullptr;
319
+ c_opts.num_specific_vtxo_ids = 0;
320
+ }
321
+
322
+ // Make the C FFI call
323
+ char *status_c = nullptr;
324
+ bark::bark_BarkError *error = bark::bark_refresh_vtxos(
325
+ datadir.c_str(), mnemonic.c_str(), c_opts, no_sync, &status_c);
326
+
327
+ check_bark_error(error);
328
+ if (status_c == nullptr) {
329
+ // Decide if null status is an error or just empty status
330
+ // For consistency let's assume null should not happen on success.
331
+ throw std::runtime_error("Bark-cpp error: refreshVtxos returned "
332
+ "success but status pointer is null");
333
+ }
334
+ std::string status_str(status_c);
335
+ bark::bark_free_string(status_c); // Use helper
336
+ return status_str;
337
+ });
338
+ }
339
+
340
+ std::shared_ptr<Promise<std::string>> boardAmount(const std::string &datadir,
341
+ const std::string &mnemonic,
342
+ double amountSat,
343
+ bool no_sync) override {
344
+ return Promise<std::string>::async([datadir, mnemonic, amountSat,
345
+ no_sync]() {
346
+ char *status_c = nullptr;
347
+ bark::bark_BarkError *error = bark::bark_board_amount(
348
+ datadir.c_str(), mnemonic.c_str(), static_cast<uint64_t>(amountSat),
349
+ no_sync, &status_c);
350
+ check_bark_error(error);
351
+ if (status_c == nullptr) {
352
+ throw std::runtime_error(
353
+ "Bark-cpp error: boardAmount returned success but status is null");
354
+ }
355
+ std::string status_str(status_c);
356
+ bark::bark_free_string(status_c); // Use helper
357
+ return status_str;
358
+ });
359
+ }
360
+
361
+ std::shared_ptr<Promise<std::string>> boardAll(const std::string &datadir,
362
+ const std::string &mnemonic,
363
+ bool no_sync) override {
364
+ return Promise<std::string>::async([datadir, mnemonic, no_sync]() {
365
+ char *status_c = nullptr;
366
+ bark::bark_BarkError *error = bark::bark_board_all(
367
+ datadir.c_str(), mnemonic.c_str(), no_sync, &status_c);
368
+ check_bark_error(error);
369
+ if (status_c == nullptr) {
370
+ throw std::runtime_error(
371
+ "Bark-cpp error: boardAll returned success but status is null");
372
+ }
373
+ std::string status_str(status_c);
374
+ bark::bark_free_string(status_c); // Use helper
375
+ return status_str;
376
+ });
377
+ }
378
+
379
+ std::shared_ptr<Promise<std::string>>
380
+ send(const std::string &datadir, const std::string &mnemonic,
381
+ const std::string &destination, double amountSat,
382
+ const std::optional<std::string> &comment, bool no_sync) override {
383
+ return Promise<std::string>::async([datadir, mnemonic, destination,
384
+ amountSat, comment, no_sync]() {
385
+ char *status_c = nullptr;
386
+ const char *comment_c = comment.has_value() ? comment->c_str() : nullptr;
387
+ // NOTE: bark_send in ffi.rs expects u64::MAX if amount is not provided.
388
+ // Here, amountSat (double) is always passed from TS. If you want to
389
+ // support sending MAX, the TS/Nitro interface needs adjustment (e.g.,
390
+ // optional amount). Assuming amountSat passed from TS is always the
391
+ // intended amount.
392
+ bark::bark_BarkError *error = bark::bark_send(
393
+ datadir.c_str(), mnemonic.c_str(), destination.c_str(),
394
+ static_cast<uint64_t>(amountSat), comment_c, no_sync, &status_c);
395
+ check_bark_error(error);
396
+ if (status_c == nullptr) {
397
+ throw std::runtime_error(
398
+ "Bark-cpp error: send returned success but status is null");
399
+ }
400
+ std::string status_str(status_c);
401
+ bark::bark_free_string(status_c); // Use helper
402
+ return status_str;
403
+ });
404
+ }
405
+
406
+ std::shared_ptr<Promise<std::string>>
407
+ sendRoundOnchain(const std::string &datadir, const std::string &mnemonic,
408
+ const std::string &destination, double amountSat,
409
+ bool no_sync) override {
410
+ return Promise<std::string>::async(
411
+ [datadir, mnemonic, destination, amountSat, no_sync]() {
412
+ char *status_c = nullptr;
413
+ bark::bark_BarkError *error = bark::bark_send_round_onchain(
414
+ datadir.c_str(), mnemonic.c_str(), destination.c_str(),
415
+ static_cast<uint64_t>(amountSat), no_sync, &status_c);
416
+ check_bark_error(error);
417
+ if (status_c == nullptr) {
418
+ throw std::runtime_error("Bark-cpp error: sendRoundOnchain "
419
+ "returned success but status is null");
420
+ }
421
+ std::string status_str(status_c);
422
+ bark::bark_free_string(status_c); // Use helper
423
+ return status_str;
424
+ });
425
+ }
426
+
427
+ // --- Offboarding / Exiting ---
428
+
429
+ std::shared_ptr<Promise<std::string>>
430
+ offboardSpecific(const std::string &datadir, const std::string &mnemonic,
431
+ const std::vector<std::string> &vtxoIds,
432
+ const std::optional<std::string> &optionalAddress,
433
+ bool no_sync) override {
434
+ return Promise<std::string>::async(
435
+ [datadir, mnemonic, vtxoIds, optionalAddress, no_sync]() {
436
+ if (vtxoIds.empty()) {
437
+ throw std::runtime_error(
438
+ "offboardSpecific requires at least one vtxoId");
439
+ }
440
+ std::vector<const char *> ids_c;
441
+ ids_c.reserve(vtxoIds.size());
442
+ for (const auto &id : vtxoIds) {
443
+ ids_c.push_back(id.c_str());
444
+ }
445
+ const char *addr_c =
446
+ optionalAddress.has_value() ? optionalAddress->c_str() : nullptr;
447
+ char *status_c = nullptr;
448
+
449
+ bark::bark_BarkError *error = bark::bark_offboard_specific(
450
+ datadir.c_str(), mnemonic.c_str(), ids_c.data(), ids_c.size(),
451
+ addr_c, no_sync, &status_c);
452
+ check_bark_error(error);
453
+ if (status_c == nullptr) {
454
+ throw std::runtime_error("Bark-cpp error: offboardSpecific "
455
+ "returned success but status is null");
456
+ }
457
+ std::string status_str(status_c);
458
+ bark::bark_free_string(status_c); // Use helper
459
+ return status_str;
460
+ });
461
+ }
462
+
463
+ std::shared_ptr<Promise<std::string>>
464
+ offboardAll(const std::string &datadir, const std::string &mnemonic,
465
+ const std::optional<std::string> &optionalAddress,
466
+ bool no_sync) override {
467
+ return Promise<std::string>::async([datadir, mnemonic, optionalAddress,
468
+ no_sync]() {
469
+ const char *addr_c =
470
+ optionalAddress.has_value() ? optionalAddress->c_str() : nullptr;
471
+ char *status_c = nullptr;
472
+ bark::bark_BarkError *error = bark::bark_offboard_all(
473
+ datadir.c_str(), mnemonic.c_str(), addr_c, no_sync, &status_c);
474
+ check_bark_error(error);
475
+ if (status_c == nullptr) {
476
+ throw std::runtime_error(
477
+ "Bark-cpp error: offboardAll returned success but status is null");
478
+ }
479
+ std::string status_str(status_c);
480
+ bark::bark_free_string(status_c); // Use helper
481
+ return status_str;
482
+ });
483
+ }
484
+
485
+ std::shared_ptr<Promise<std::string>> exitStartSpecific(
486
+ const std::string &datadir, const std::string &mnemonic,
487
+ const std::vector<std::string> &vtxoIds,
488
+ bool no_sync /* Potential C header mismatch noted */) override {
489
+ return Promise<std::string>::async([datadir, mnemonic, vtxoIds, no_sync]() {
490
+ if (vtxoIds.empty()) {
491
+ throw std::runtime_error(
492
+ "exitStartSpecific requires at least one vtxoId");
493
+ }
494
+ std::vector<const char *> ids_c;
495
+ ids_c.reserve(vtxoIds.size());
496
+ for (const auto &id : vtxoIds) {
497
+ ids_c.push_back(id.c_str());
498
+ }
499
+ char *status_c = nullptr;
500
+
501
+ // Call reflects C header (which might be missing no_sync)
502
+ bark::bark_BarkError *error =
503
+ bark::bark_exit_start_specific(datadir.c_str(), mnemonic.c_str(),
504
+ ids_c.data(), ids_c.size(), &status_c);
505
+ check_bark_error(error);
506
+ if (status_c == nullptr) {
507
+ throw std::runtime_error("Bark-cpp error: exitStartSpecific returned "
508
+ "success but status is null");
509
+ }
510
+ std::string status_str(status_c);
511
+ bark::bark_free_string(status_c); // Use helper
512
+ return status_str;
513
+ });
514
+ }
515
+
516
+ std::shared_ptr<Promise<std::string>>
517
+ exitStartAll(const std::string &datadir, const std::string &mnemonic,
518
+ bool no_sync /* Potential C header mismatch noted */) override {
519
+ return Promise<std::string>::async([datadir, mnemonic, no_sync]() {
520
+ char *status_c = nullptr;
521
+ // Call reflects C header (which might be missing no_sync)
522
+ bark::bark_BarkError *error = bark::bark_exit_start_all(
523
+ datadir.c_str(), mnemonic.c_str(), &status_c);
524
+ check_bark_error(error);
525
+ if (status_c == nullptr) {
526
+ throw std::runtime_error(
527
+ "Bark-cpp error: exitStartAll returned success but status is null");
528
+ }
529
+ std::string status_str(status_c);
530
+ bark::bark_free_string(status_c); // Use helper
531
+ return status_str;
532
+ });
533
+ }
534
+
535
+ std::shared_ptr<Promise<std::string>>
536
+ exitProgressOnce(const std::string &datadir,
537
+ const std::string &mnemonic) override {
538
+ return Promise<std::string>::async([datadir, mnemonic]() {
539
+ char *status_c = nullptr;
540
+ bark::bark_BarkError *error = bark::bark_exit_progress_once(
541
+ datadir.c_str(), mnemonic.c_str(), &status_c);
542
+ check_bark_error(error);
543
+ if (status_c == nullptr) {
544
+ throw std::runtime_error("Bark-cpp error: exitProgressOnce returned "
545
+ "success but status is null");
546
+ }
547
+ std::string status_str(status_c);
548
+ bark::bark_free_string(status_c); // Use helper
549
+ return status_str;
550
+ });
551
+ }
552
+
553
+ private:
554
+ // Tag for logging/debugging within Nitro
555
+ static constexpr auto TAG = "NitroArk";
556
+ };
557
+
558
+ } // namespace margelo::nitro::nitroark