react-native-nitro-ark 0.0.24 → 0.0.25

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/cpp/NitroArk.hpp CHANGED
@@ -1,7 +1,8 @@
1
1
  #pragma once
2
2
 
3
3
  #include "HybridNitroArkSpec.hpp"
4
- #include "bark-cpp.h"
4
+ #include "generated/ark_cxx.h"
5
+ #include "generated/cxx.h"
5
6
  #include <memory>
6
7
  #include <stdexcept>
7
8
  #include <string>
@@ -10,613 +11,428 @@
10
11
  namespace margelo::nitro::nitroark
11
12
  {
12
13
 
13
- // Helper function to handle potential errors from bark-cpp calls
14
- inline void check_bark_error(bark::bark_BarkError *error)
15
- {
16
- if (error != nullptr)
14
+ class NitroArk : public HybridNitroArkSpec
17
15
  {
18
- std::string error_message = "Bark-cpp error: Unknown";
19
- if (error->message != nullptr)
20
- {
21
- // Assuming error->message is valid C string allocated correctly
22
- error_message = std::string("Bark-cpp error: ") + error->message;
23
- }
24
- // Use the FFI function to free the error struct and its contents
25
- bark::bark_free_error(error);
26
- throw std::runtime_error(error_message);
27
- }
28
- }
29
-
30
- class NitroArk : public HybridNitroArkSpec
31
- {
32
- public:
33
- NitroArk() : HybridObject(TAG)
34
- {
35
- // Initialize the Rust logger once when a NitroArk object is created.
36
- bark::bark_init_logger();
37
- }
16
+ public:
17
+ NitroArk() : HybridObject(TAG)
18
+ {
19
+ // Initialize the Rust logger once when a NitroArk object is created.
20
+ bark_cxx::init_logger();
21
+ }
38
22
 
39
- // --- Management ---
23
+ // --- Management ---
24
+
25
+ std::shared_ptr<Promise<std::string>> createMnemonic() override
26
+ {
27
+ return Promise<std::string>::async([]()
28
+ {
29
+ try {
30
+ rust::String mnemonic_rs = bark_cxx::create_mnemonic();
31
+ return std::string(mnemonic_rs.data(), mnemonic_rs.length());
32
+ } catch (const rust::Error &e) {
33
+ throw std::runtime_error(e.what());
34
+ } });
35
+ }
40
36
 
41
- std::shared_ptr<Promise<std::string>> createMnemonic() override
42
- {
43
- return Promise<std::string>::async([]()
44
- {
45
- char *mnemonic_c = bark::bark_create_mnemonic();
46
- if (mnemonic_c == nullptr) {
47
- throw std::runtime_error(
48
- "Bark-cpp error: Failed to create mnemonic (returned NULL)");
49
- }
50
- std::string mnemonic_str(mnemonic_c);
51
- bark::bark_free_string(mnemonic_c);
52
- return mnemonic_str; });
53
- }
54
-
55
- std::shared_ptr<Promise<void>>
56
- loadWallet(const std::string &datadir,
57
- const BarkCreateOpts &opts) override
58
- {
59
- return Promise<void>::async([datadir, opts]()
60
- {
61
- // Keep fee rate value alive for the C call
62
- std::optional<uint64_t> fallback_fee_rate_val;
63
- if (opts.config.has_value() &&
64
- opts.config->fallback_fee_rate.has_value()) {
65
- fallback_fee_rate_val =
66
- static_cast<uint64_t>(opts.config->fallback_fee_rate.value());
67
- }
68
-
69
- bark::bark_BarkConfigOpts config = {
70
- opts.config.has_value() && opts.config->asp.has_value()
71
- ? opts.config->asp->c_str()
72
- : nullptr,
73
- opts.config.has_value() && opts.config->esplora.has_value()
74
- ? opts.config->esplora->c_str()
75
- : nullptr,
76
- opts.config.has_value() && opts.config->bitcoind.has_value()
77
- ? opts.config->bitcoind->c_str()
78
- : nullptr,
79
- opts.config.has_value() && opts.config->bitcoind_cookie.has_value()
80
- ? opts.config->bitcoind_cookie->c_str()
81
- : nullptr,
82
- opts.config.has_value() && opts.config->bitcoind_user.has_value()
83
- ? opts.config->bitcoind_user->c_str()
84
- : nullptr,
85
- opts.config.has_value() && opts.config->bitcoind_pass.has_value()
86
- ? opts.config->bitcoind_pass->c_str()
87
- : nullptr,
88
- opts.config.has_value() &&
89
- opts.config->vtxo_refresh_expiry_threshold.has_value()
90
- ? static_cast<uint32_t>(
91
- opts.config->vtxo_refresh_expiry_threshold.value())
92
- : 0,
93
- fallback_fee_rate_val.has_value() ? &fallback_fee_rate_val.value()
94
- : nullptr};
95
-
96
- bark::bark_BarkCreateOpts barkOpts = {
97
- opts.regtest.value_or(false),
98
- opts.signet.value_or(false),
99
- opts.bitcoin.value_or(true),
100
- opts.mnemonic.empty() ? nullptr : opts.mnemonic.c_str(),
101
- opts.birthday_height.has_value()
102
- ? static_cast<uint32_t>(opts.birthday_height.value())
103
- : 0,
104
- config};
105
-
106
- bark::bark_BarkError *error =
107
- bark::bark_load_wallet(datadir.c_str(), barkOpts);
108
- check_bark_error(error); });
109
- }
110
-
111
- std::shared_ptr<Promise<void>> closeWallet() override
112
- {
113
- return Promise<void>::async([]()
114
- {
115
- bark::bark_BarkError *error = bark::bark_close_wallet();
116
- check_bark_error(error); });
117
- }
37
+ std::shared_ptr<Promise<void>>
38
+ loadWallet(const std::string &datadir,
39
+ const BarkCreateOpts &opts) override
40
+ {
41
+ return Promise<void>::async([datadir, opts]()
42
+ {
43
+ try {
44
+ bark_cxx::ConfigOpts config_opts;
45
+ if (opts.config.has_value()) {
46
+ config_opts.asp = opts.config->asp.value_or("");
47
+ config_opts.esplora = opts.config->esplora.value_or("");
48
+ config_opts.bitcoind = opts.config->bitcoind.value_or("");
49
+ config_opts.bitcoind_cookie = opts.config->bitcoind_cookie.value_or("");
50
+ config_opts.bitcoind_user = opts.config->bitcoind_user.value_or("");
51
+ config_opts.bitcoind_pass = opts.config->bitcoind_pass.value_or("");
52
+ config_opts.vtxo_refresh_expiry_threshold = static_cast<uint32_t>(opts.config->vtxo_refresh_expiry_threshold.value_or(0));
53
+ config_opts.fallback_fee_rate = static_cast<uint64_t>(opts.config->fallback_fee_rate.value_or(0));
54
+ }
55
+
56
+ bark_cxx::CreateOpts create_opts;
57
+ create_opts.regtest = opts.regtest.value_or(false);
58
+ create_opts.signet = opts.signet.value_or(false);
59
+ create_opts.bitcoin = opts.bitcoin.value_or(true);
60
+ create_opts.mnemonic = opts.mnemonic;
61
+ create_opts.birthday_height = static_cast<uint32_t>(opts.birthday_height.value_or(0));
62
+ create_opts.config = config_opts;
63
+
64
+ bark_cxx::load_wallet(datadir, create_opts);
65
+ } catch (const rust::Error &e) {
66
+ throw std::runtime_error(e.what());
67
+ } });
68
+ }
118
69
 
119
- std::shared_ptr<Promise<bool>> isWalletLoaded() override
120
- {
121
- return Promise<bool>::async([]()
122
- { return bark::bark_is_wallet_loaded(); });
123
- }
70
+ std::shared_ptr<Promise<void>> closeWallet() override
71
+ {
72
+ return Promise<void>::async([]()
73
+ {
74
+ try {
75
+ bark_cxx::close_wallet();
76
+ } catch (const rust::Error &e) {
77
+ throw std::runtime_error(e.what());
78
+ } });
79
+ }
124
80
 
125
- // --- Wallet Info ---
81
+ std::shared_ptr<Promise<bool>> isWalletLoaded() override
82
+ {
83
+ return Promise<bool>::async([]()
84
+ { return bark_cxx::is_wallet_loaded(); });
85
+ }
126
86
 
127
- std::shared_ptr<Promise<BarkBalance>>
128
- getBalance(bool no_sync) override
129
- {
130
- return Promise<BarkBalance>::async([no_sync]()
131
- {
132
- bark::bark_BarkBalance c_balance;
133
- bark::bark_BarkError *error = bark::bark_get_balance(no_sync, &c_balance);
134
- check_bark_error(error);
135
-
136
- return BarkBalance(static_cast<double>(c_balance.onchain),
137
- static_cast<double>(c_balance.offchain),
138
- static_cast<double>(c_balance.pending_exit)); });
139
- }
140
-
141
- std::shared_ptr<Promise<std::string>>
142
- getOnchainAddress() override
143
- {
144
- return Promise<std::string>::async([]()
145
- {
146
- char *address_c = nullptr;
147
- bark::bark_BarkError *error = bark::bark_get_onchain_address(&address_c);
148
- check_bark_error(error);
149
- if (address_c == nullptr) {
150
- throw std::runtime_error("Bark-cpp error: getOnchainAddress returned "
151
- "success but address is null");
152
- }
153
- std::string address_str(address_c);
154
- bark::bark_free_string(address_c); // Use helper
155
- return address_str; });
156
- }
157
-
158
- std::shared_ptr<Promise<std::string>>
159
- getOnchainUtxos(bool no_sync) override
160
- {
161
- return Promise<std::string>::async([no_sync]()
162
- {
163
- char *json_c = nullptr;
164
- bark::bark_BarkError *error = bark::bark_get_onchain_utxos(no_sync, &json_c);
165
- check_bark_error(error);
166
- if (json_c == nullptr) {
167
- throw std::runtime_error("Bark-cpp error: getOnchainUtxos returned "
168
- "success but JSON is null");
169
- }
170
- std::string json_str(json_c);
171
- bark::bark_free_string(json_c); // Use helper
172
- return json_str; });
173
- }
174
-
175
- std::shared_ptr<Promise<std::string>>
176
- getVtxoPubkey(std::optional<double> index) override
177
- {
178
- return Promise<std::string>::async([index]()
179
- {
180
- char *pubkey_c = nullptr;
181
- std::optional<uint32_t> index_val;
182
- if (index.has_value()) {
183
- index_val = static_cast<uint32_t>(index.value());
184
- }
185
-
186
- bark::bark_BarkError *error = bark::bark_get_vtxo_pubkey(
187
- index_val.has_value() ? &index_val.value() : nullptr, &pubkey_c);
188
- check_bark_error(error);
189
- if (pubkey_c == nullptr) {
190
- throw std::runtime_error("Bark-cpp error: getVtxoPubkey returned "
191
- "success but pubkey is null");
192
- }
193
- std::string pubkey_str(pubkey_c);
194
- bark::bark_free_string(pubkey_c); // Use helper
195
- return pubkey_str; });
196
- }
197
-
198
- std::shared_ptr<Promise<std::string>> getVtxos(bool no_sync) override
199
- {
200
- return Promise<std::string>::async([no_sync]()
201
- {
202
- char *json_c = nullptr;
203
- bark::bark_BarkError *error = bark::bark_get_vtxos(no_sync, &json_c);
204
- check_bark_error(error);
205
- if (json_c == nullptr) {
206
- throw std::runtime_error(
207
- "Bark-cpp error: getVtxos returned success but JSON is null");
208
- }
209
- std::string json_str(json_c);
210
- bark::bark_free_string(json_c); // Use helper
211
- return json_str; });
212
- }
213
-
214
- // --- Onchain Operations ---
215
-
216
- std::shared_ptr<Promise<std::string>>
217
- sendOnchain(const std::string &destination, double amountSat,
218
- bool no_sync) override
219
- {
220
- return Promise<std::string>::async([destination, amountSat, no_sync]()
221
- {
222
- char *txid_c = nullptr;
223
- bark::bark_BarkError *error = bark::bark_send_onchain(
224
- destination.c_str(), static_cast<uint64_t>(amountSat), no_sync, &txid_c);
225
- check_bark_error(error);
226
- if (txid_c == nullptr) {
227
- throw std::runtime_error(
228
- "Bark-cpp error: sendOnchain returned success but txid is null");
229
- }
230
- std::string txid_str(txid_c);
231
- bark::bark_free_string(txid_c); // Use helper
232
- return txid_str; });
233
- }
234
-
235
- std::shared_ptr<Promise<std::string>>
236
- drainOnchain(const std::string &destination, bool no_sync) override
237
- {
238
- return Promise<std::string>::async(
239
- [destination, no_sync]()
240
- {
241
- char *txid_c = nullptr;
242
- bark::bark_BarkError *error =
243
- bark::bark_drain_onchain(destination.c_str(), no_sync, &txid_c);
244
- check_bark_error(error);
245
- if (txid_c == nullptr)
246
- {
247
- throw std::runtime_error("Bark-cpp error: drainOnchain returned "
248
- "success but txid is null");
249
- }
250
- std::string txid_str(txid_c);
251
- bark::bark_free_string(txid_c); // Use helper
252
- return txid_str;
253
- });
254
- }
255
-
256
- std::shared_ptr<Promise<std::string>>
257
- sendManyOnchain(const std::vector<BarkSendManyOutput> &outputs,
87
+ // --- Wallet Info ---
88
+
89
+ std::shared_ptr<Promise<BarkBalance>>
90
+ getBalance(bool no_sync) override
91
+ {
92
+ return Promise<BarkBalance>::async([no_sync]()
93
+ {
94
+ try {
95
+ bark_cxx::CxxBalance c_balance = bark_cxx::get_balance(no_sync);
96
+ return BarkBalance{static_cast<double>(c_balance.onchain),
97
+ static_cast<double>(c_balance.offchain),
98
+ static_cast<double>(c_balance.pending_exit)};
99
+ } catch (const rust::Error &e) {
100
+ throw std::runtime_error(e.what());
101
+ } });
102
+ }
103
+
104
+ std::shared_ptr<Promise<std::string>>
105
+ getOnchainAddress() override
106
+ {
107
+ return Promise<std::string>::async([]()
108
+ {
109
+ try {
110
+ rust::String address_rs = bark_cxx::get_onchain_address();
111
+ return std::string(address_rs.data(), address_rs.length());
112
+ } catch (const rust::Error &e) {
113
+ throw std::runtime_error(e.what());
114
+ } });
115
+ }
116
+
117
+ std::shared_ptr<Promise<std::string>>
118
+ getOnchainUtxos(bool no_sync) override
119
+ {
120
+ return Promise<std::string>::async([no_sync]()
121
+ {
122
+ try {
123
+ rust::String json_rs = bark_cxx::get_onchain_utxos(no_sync);
124
+ return std::string(json_rs.data(), json_rs.length());
125
+ } catch (const rust::Error &e) {
126
+ throw std::runtime_error(e.what());
127
+ } });
128
+ }
129
+
130
+ std::shared_ptr<Promise<std::string>>
131
+ getVtxoPubkey(std::optional<double> index) override
132
+ {
133
+ return Promise<std::string>::async([index]()
134
+ {
135
+ try {
136
+ uint32_t index_val = index.has_value() ? static_cast<uint32_t>(index.value()) : UINT32_MAX;
137
+ rust::String pubkey_rs = bark_cxx::get_vtxo_pubkey(index_val);
138
+ return std::string(pubkey_rs.data(), pubkey_rs.length());
139
+ } catch (const rust::Error &e) {
140
+ throw std::runtime_error(e.what());
141
+ } });
142
+ }
143
+
144
+ std::shared_ptr<Promise<std::string>> getVtxos(bool no_sync) override
145
+ {
146
+ return Promise<std::string>::async([no_sync]()
147
+ {
148
+ try {
149
+ rust::String json_rs = bark_cxx::get_vtxos(no_sync);
150
+ return std::string(json_rs.data(), json_rs.length());
151
+ } catch (const rust::Error &e) {
152
+ throw std::runtime_error(e.what());
153
+ } });
154
+ }
155
+
156
+ // --- Onchain Operations ---
157
+
158
+ std::shared_ptr<Promise<std::string>>
159
+ sendOnchain(const std::string &destination, double amountSat,
258
160
  bool no_sync) override
259
- {
260
- return Promise<std::string>::async([outputs, no_sync]()
261
- {
262
- size_t num_outputs = outputs.size();
263
- if (num_outputs == 0) {
264
- throw std::runtime_error(
265
- "sendManyOnchain requires at least one output");
266
- }
267
-
268
- std::vector<const char *> destinations_c;
269
- std::vector<uint64_t> amounts_c;
270
- destinations_c.reserve(num_outputs);
271
- amounts_c.reserve(num_outputs);
272
-
273
- for (const auto &output : outputs) {
274
- destinations_c.push_back(output.destination.c_str());
275
- amounts_c.push_back(static_cast<uint64_t>(output.amountSat));
276
- }
277
-
278
- char *txid_c = nullptr;
279
- bark::bark_BarkError *error = bark::bark_send_many_onchain(
280
- destinations_c.data(), amounts_c.data(), num_outputs, no_sync, &txid_c);
281
- check_bark_error(error);
282
- if (txid_c == nullptr) {
283
- throw std::runtime_error("Bark-cpp error: sendManyOnchain returned "
284
- "success but txid is null");
285
- }
286
- std::string txid_str(txid_c);
287
- bark::bark_free_string(txid_c); // Use helper
288
- return txid_str; });
289
- }
290
-
291
- // --- Ark Operations ---
292
-
293
- std::shared_ptr<Promise<std::string>>
294
- refreshVtxos(const BarkRefreshOpts &refreshOpts, bool no_sync) override
295
- {
296
- return Promise<std::string>::async([refreshOpts,
297
- no_sync]()
298
- {
299
- bark::bark_BarkRefreshOpts c_opts;
300
- std::vector<const char *> specific_ids_c; // Keep alive for the C call
301
-
302
- // Map the C++ enum to the C FFI enum using a switch
303
- switch (refreshOpts.mode_type) {
304
- case margelo::nitro::nitroark::BarkRefreshModeType::DEFAULTTHRESHOLD:
305
- c_opts.mode_type = bark::bark_BarkRefreshModeType::DefaultThreshold;
306
- break;
307
- case margelo::nitro::nitroark::BarkRefreshModeType::THRESHOLDBLOCKS:
308
- c_opts.mode_type = bark::bark_BarkRefreshModeType::ThresholdBlocks;
309
- break;
310
- case margelo::nitro::nitroark::BarkRefreshModeType::THRESHOLDHOURS:
311
- c_opts.mode_type = bark::bark_BarkRefreshModeType::ThresholdHours;
312
- break;
313
- case margelo::nitro::nitroark::BarkRefreshModeType::COUNTERPARTY:
314
- c_opts.mode_type = bark::bark_BarkRefreshModeType::Counterparty;
315
- break;
316
- case margelo::nitro::nitroark::BarkRefreshModeType::ALL:
317
- c_opts.mode_type = bark::bark_BarkRefreshModeType::All;
318
- break;
319
- case margelo::nitro::nitroark::BarkRefreshModeType::SPECIFIC:
320
- c_opts.mode_type = bark::bark_BarkRefreshModeType::Specific;
321
- break;
322
- default:
323
- // This should ideally not happen with a closed enum, but handle
324
- // defensively
325
- throw std::runtime_error(
326
- "Unknown BarkRefreshModeType encountered: " +
327
- std::to_string(static_cast<int>(refreshOpts.mode_type)));
328
- }
329
-
330
- // Assign threshold_value (handle optional)
331
- // Note: C struct expects uint32_t, C++ has optional<double>. Cast needed.
332
- c_opts.threshold_value =
333
- static_cast<uint32_t>(refreshOpts.threshold_value.value_or(0));
334
-
335
- // Handle specific_vtxo_ids only if mode is Specific
336
- if (c_opts.mode_type == bark::bark_BarkRefreshModeType::Specific) {
337
- if (!refreshOpts.specific_vtxo_ids.has_value() ||
338
- refreshOpts.specific_vtxo_ids->empty()) {
339
- throw std::runtime_error(
340
- "Specific refresh mode requires non-empty specific_vtxo_ids");
161
+ {
162
+ return Promise<std::string>::async([destination, amountSat, no_sync]()
163
+ {
164
+ try {
165
+ rust::String txid_rs = bark_cxx::send_onchain(destination, static_cast<uint64_t>(amountSat), no_sync);
166
+ return std::string(txid_rs.data(), txid_rs.length());
167
+ } catch (const rust::Error &e) {
168
+ throw std::runtime_error(e.what());
169
+ } });
341
170
  }
342
- specific_ids_c.reserve(refreshOpts.specific_vtxo_ids->size());
343
- for (const auto &id : refreshOpts.specific_vtxo_ids.value()) {
344
- specific_ids_c.push_back(id.c_str()); // Get C string pointer
171
+
172
+ std::shared_ptr<Promise<std::string>>
173
+ drainOnchain(const std::string &destination, bool no_sync) override
174
+ {
175
+ return Promise<std::string>::async(
176
+ [destination, no_sync]()
177
+ {
178
+ try
179
+ {
180
+ rust::String txid_rs = bark_cxx::drain_onchain(destination, no_sync);
181
+ return std::string(txid_rs.data(), txid_rs.length());
182
+ }
183
+ catch (const rust::Error &e)
184
+ {
185
+ throw std::runtime_error(e.what());
186
+ }
187
+ });
345
188
  }
346
- c_opts.specific_vtxo_ids =
347
- specific_ids_c.data(); // Point to the data in the vector
348
- c_opts.num_specific_vtxo_ids = specific_ids_c.size(); // Get the size
349
- } else {
350
- // Ensure these are null/zero if not in Specific mode
351
- c_opts.specific_vtxo_ids = nullptr;
352
- c_opts.num_specific_vtxo_ids = 0;
353
- }
354
-
355
- // Make the C FFI call
356
- char *status_c = nullptr;
357
- bark::bark_BarkError *error = bark::bark_refresh_vtxos(c_opts, no_sync, &status_c);
358
-
359
- check_bark_error(error);
360
- if (status_c == nullptr) {
361
- // Decide if null status is an error or just empty status
362
- // For consistency let's assume null should not happen on success.
363
- throw std::runtime_error("Bark-cpp error: refreshVtxos returned "
364
- "success but status pointer is null");
365
- }
366
- std::string status_str(status_c);
367
- bark::bark_free_string(status_c); // Use helper
368
- return status_str; });
369
- }
370
-
371
- std::shared_ptr<Promise<std::string>> boardAmount(double amountSat,
372
- bool no_sync) override
373
- {
374
- return Promise<std::string>::async([amountSat,
375
- no_sync]()
376
- {
377
- char *status_c = nullptr;
378
- bark::bark_BarkError *error = bark::bark_board_amount(
379
- static_cast<uint64_t>(amountSat),
380
- no_sync, &status_c);
381
- check_bark_error(error);
382
- if (status_c == nullptr) {
383
- throw std::runtime_error(
384
- "Bark-cpp error: boardAmount returned success but status is null");
385
- }
386
- std::string status_str(status_c);
387
- bark::bark_free_string(status_c); // Use helper
388
- return status_str; });
389
- }
390
-
391
- std::shared_ptr<Promise<std::string>> boardAll(bool no_sync) override
392
- {
393
- return Promise<std::string>::async([no_sync]()
394
- {
395
- char *status_c = nullptr;
396
- bark::bark_BarkError *error = bark::bark_board_all(no_sync, &status_c);
397
- check_bark_error(error);
398
- if (status_c == nullptr) {
399
- throw std::runtime_error(
400
- "Bark-cpp error: boardAll returned success but status is null");
401
- }
402
- std::string status_str(status_c);
403
- bark::bark_free_string(status_c); // Use helper
404
- return status_str; });
405
- }
406
-
407
- std::shared_ptr<Promise<std::string>>
408
- send(const std::string &destination, std::optional<double> amountSat,
409
- const std::optional<std::string> &comment, bool no_sync) override
410
- {
411
- return Promise<std::string>::async([destination, amountSat, comment, no_sync]()
412
- {
413
- char *status_c = nullptr;
414
- const char *comment_c = comment.has_value() ? comment->c_str() : nullptr;
415
-
416
- uint64_t amount_val = 0;
417
- const uint64_t* amount_ptr = nullptr;
418
-
419
- if (amountSat.has_value()) {
420
- amount_val = static_cast<uint64_t>(amountSat.value());
421
- amount_ptr = &amount_val;
422
- }
423
-
424
- bark::bark_BarkError *error = bark::bark_send(
425
- destination.c_str(),
426
- amount_ptr,
427
- comment_c,
428
- no_sync,
429
- &status_c);
430
- check_bark_error(error);
431
- if (status_c == nullptr) {
432
- throw std::runtime_error(
433
- "Bark-cpp error: send returned success but status is null");
434
- }
435
- std::string status_str(status_c);
436
- bark::bark_free_string(status_c); // Use helper
437
- return status_str; });
438
- }
439
-
440
- std::shared_ptr<Promise<std::string>>
441
- sendRoundOnchain(const std::string &destination, double amountSat,
442
- bool no_sync) override
443
- {
444
- return Promise<std::string>::async(
445
- [destination, amountSat, no_sync]()
446
- {
447
- char *status_c = nullptr;
448
- bark::bark_BarkError *error = bark::bark_send_round_onchain(
449
- destination.c_str(),
450
- static_cast<uint64_t>(amountSat), no_sync, &status_c);
451
- check_bark_error(error);
452
- if (status_c == nullptr)
453
- {
454
- throw std::runtime_error("Bark-cpp error: sendRoundOnchain "
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
- // --- Lightning Operations ---
464
-
465
- std::shared_ptr<Promise<std::string>>
466
- bolt11Invoice(double amountMsat) override
467
- {
468
- return Promise<std::string>::async([amountMsat]()
469
- {
470
- char *invoice_c = nullptr;
471
- bark::bark_BarkError *error = bark::bark_bolt11_invoice(
472
- static_cast<uint64_t>(amountMsat),
473
- &invoice_c);
474
- check_bark_error(error);
475
- if (invoice_c == nullptr) {
476
- throw std::runtime_error("Bark-cpp error: bolt11Invoice returned "
477
- "success but invoice is null");
478
- }
479
- std::string invoice_str(invoice_c);
480
- bark::bark_free_string(invoice_c);
481
- return invoice_str; });
482
- }
483
-
484
- std::shared_ptr<Promise<void>>
485
- claimBolt11Payment(const std::string &bolt11) override
486
- {
487
- return Promise<void>::async([bolt11]()
488
- {
489
- bark::bark_BarkError *error = bark::bark_claim_bolt11_payment(bolt11.c_str());
490
- check_bark_error(error); });
491
- }
492
-
493
- // --- Offboarding / Exiting ---
494
-
495
- std::shared_ptr<Promise<std::string>>
496
- offboardSpecific(const std::vector<std::string> &vtxoIds,
497
- const std::optional<std::string> &optionalAddress,
498
- bool no_sync) override
499
- {
500
- return Promise<std::string>::async(
501
- [vtxoIds, optionalAddress, no_sync]()
502
- {
503
- if (vtxoIds.empty())
504
- {
505
- throw std::runtime_error(
506
- "offboardSpecific requires at least one vtxoId");
507
- }
508
- std::vector<const char *> ids_c;
509
- ids_c.reserve(vtxoIds.size());
510
- for (const auto &id : vtxoIds)
511
- {
512
- ids_c.push_back(id.c_str());
513
- }
514
- const char *addr_c =
515
- optionalAddress.has_value() ? optionalAddress->c_str() : nullptr;
516
- char *status_c = nullptr;
517
-
518
- bark::bark_BarkError *error = bark::bark_offboard_specific(
519
- ids_c.data(), ids_c.size(),
520
- addr_c, no_sync, &status_c);
521
- check_bark_error(error);
522
- if (status_c == nullptr)
523
- {
524
- throw std::runtime_error("Bark-cpp error: offboardSpecific "
525
- "returned success but status is null");
526
- }
527
- std::string status_str(status_c);
528
- bark::bark_free_string(status_c); // Use helper
529
- return status_str;
530
- });
531
- }
532
-
533
- std::shared_ptr<Promise<std::string>>
534
- offboardAll(const std::optional<std::string> &optionalAddress,
535
- bool no_sync) override
536
- {
537
- return Promise<std::string>::async([optionalAddress,
538
- no_sync]()
539
- {
540
- const char *addr_c =
541
- optionalAddress.has_value() ? optionalAddress->c_str() : nullptr;
542
- char *status_c = nullptr;
543
- bark::bark_BarkError *error = bark::bark_offboard_all(
544
- addr_c, no_sync, &status_c);
545
- check_bark_error(error);
546
- if (status_c == nullptr) {
547
- throw std::runtime_error(
548
- "Bark-cpp error: offboardAll returned success but status is null");
549
- }
550
- std::string status_str(status_c);
551
- bark::bark_free_string(status_c); // Use helper
552
- return status_str; });
553
- }
554
-
555
- std::shared_ptr<Promise<std::string>> exitStartSpecific(
556
- const std::vector<std::string> &vtxoIds) override
557
- {
558
- return Promise<std::string>::async([vtxoIds]()
559
- {
560
- if (vtxoIds.empty()) {
561
- throw std::runtime_error(
562
- "exitStartSpecific requires at least one vtxoId");
563
- }
564
- std::vector<const char *> ids_c;
565
- ids_c.reserve(vtxoIds.size());
566
- for (const auto &id : vtxoIds) {
567
- ids_c.push_back(id.c_str());
568
- }
569
- char *status_c = nullptr;
570
-
571
- bark::bark_BarkError *error =
572
- bark::bark_exit_start_specific(ids_c.data(), ids_c.size(), &status_c);
573
- check_bark_error(error);
574
- if (status_c == nullptr) {
575
- throw std::runtime_error("Bark-cpp error: exitStartSpecific returned "
576
- "success but status is null");
577
- }
578
- std::string status_str(status_c);
579
- bark::bark_free_string(status_c); // Use helper
580
- return status_str; });
581
- }
582
-
583
- std::shared_ptr<Promise<std::string>>
584
- exitStartAll() override
585
- {
586
- return Promise<std::string>::async([]()
587
- {
588
- char *status_c = nullptr;
589
- bark::bark_BarkError *error = bark::bark_exit_start_all(&status_c);
590
- check_bark_error(error);
591
- if (status_c == nullptr) {
592
- throw std::runtime_error(
593
- "Bark-cpp error: exitStartAll returned success but status is null");
594
- }
595
- std::string status_str(status_c);
596
- bark::bark_free_string(status_c); // Use helper
597
- return status_str; });
598
- }
599
-
600
- std::shared_ptr<Promise<std::string>>
601
- exitProgressOnce() override
602
- {
603
- return Promise<std::string>::async([]()
604
- {
605
- char *status_c = nullptr;
606
- bark::bark_BarkError *error = bark::bark_exit_progress_once(&status_c);
607
- check_bark_error(error);
608
- if (status_c == nullptr) {
609
- throw std::runtime_error("Bark-cpp error: exitProgressOnce returned "
610
- "success but status is null");
611
- }
612
- std::string status_str(status_c);
613
- bark::bark_free_string(status_c); // Use helper
614
- return status_str; });
615
- }
616
-
617
- private:
618
- // Tag for logging/debugging within Nitro
619
- static constexpr auto TAG = "NitroArk";
620
- };
189
+
190
+ std::shared_ptr<Promise<std::string>>
191
+ sendManyOnchain(const std::vector<BarkSendManyOutput> &outputs,
192
+ bool no_sync) override
193
+ {
194
+ return Promise<std::string>::async([outputs, no_sync]()
195
+ {
196
+ try {
197
+ rust::Vec<bark_cxx::SendManyOutput> cxx_outputs;
198
+ for (const auto &output : outputs) {
199
+ cxx_outputs.push_back({rust::String(output.destination), static_cast<uint64_t>(output.amountSat)});
200
+ }
201
+ rust::String txid_rs = bark_cxx::send_many_onchain(std::move(cxx_outputs), no_sync);
202
+ return std::string(txid_rs.data(), txid_rs.length());
203
+ } catch (const rust::Error &e) {
204
+ throw std::runtime_error(e.what());
205
+ } });
206
+ }
207
+
208
+ // --- Ark Operations ---
209
+
210
+ std::shared_ptr<Promise<std::string>>
211
+ refreshVtxos(const BarkRefreshOpts &refreshOpts, bool no_sync) override
212
+ {
213
+ return Promise<std::string>::async([refreshOpts,
214
+ no_sync]()
215
+ {
216
+ try {
217
+ bark_cxx::RefreshOpts opts;
218
+ switch (refreshOpts.mode_type) {
219
+ case BarkRefreshModeType::DEFAULTTHRESHOLD:
220
+ opts.mode_type = bark_cxx::RefreshModeType::DefaultThreshold;
221
+ break;
222
+ case BarkRefreshModeType::THRESHOLDBLOCKS:
223
+ opts.mode_type = bark_cxx::RefreshModeType::ThresholdBlocks;
224
+ break;
225
+ case BarkRefreshModeType::THRESHOLDHOURS:
226
+ opts.mode_type = bark_cxx::RefreshModeType::ThresholdHours;
227
+ break;
228
+ case BarkRefreshModeType::COUNTERPARTY:
229
+ opts.mode_type = bark_cxx::RefreshModeType::Counterparty;
230
+ break;
231
+ case BarkRefreshModeType::ALL:
232
+ opts.mode_type = bark_cxx::RefreshModeType::All;
233
+ break;
234
+ case BarkRefreshModeType::SPECIFIC:
235
+ opts.mode_type = bark_cxx::RefreshModeType::Specific;
236
+ break;
237
+ }
238
+ opts.threshold_value = static_cast<uint32_t>(refreshOpts.threshold_value.value_or(0));
239
+ if (refreshOpts.specific_vtxo_ids.has_value()) {
240
+ for (const auto &id : refreshOpts.specific_vtxo_ids.value()) {
241
+ opts.specific_vtxo_ids.push_back(id);
242
+ }
243
+ }
244
+ rust::String status_rs = bark_cxx::refresh_vtxos(opts, no_sync);
245
+ return std::string(status_rs.data(), status_rs.length());
246
+ } catch (const rust::Error &e) {
247
+ throw std::runtime_error(e.what());
248
+ } });
249
+ }
250
+
251
+ std::shared_ptr<Promise<std::string>> boardAmount(double amountSat,
252
+ bool no_sync) override
253
+ {
254
+ return Promise<std::string>::async([amountSat,
255
+ no_sync]()
256
+ {
257
+ try {
258
+ rust::String status_rs = bark_cxx::board_amount(static_cast<uint64_t>(amountSat), no_sync);
259
+ return std::string(status_rs.data(), status_rs.length());
260
+ } catch (const rust::Error &e) {
261
+ throw std::runtime_error(e.what());
262
+ } });
263
+ }
264
+
265
+ std::shared_ptr<Promise<std::string>> boardAll(bool no_sync) override
266
+ {
267
+ return Promise<std::string>::async([no_sync]()
268
+ {
269
+ try {
270
+ rust::String status_rs = bark_cxx::board_all(no_sync);
271
+ return std::string(status_rs.data(), status_rs.length());
272
+ } catch (const rust::Error &e) {
273
+ throw std::runtime_error(e.what());
274
+ } });
275
+ }
276
+
277
+ std::shared_ptr<Promise<std::string>>
278
+ send(const std::string &destination, std::optional<double> amountSat,
279
+ const std::optional<std::string> &comment, bool no_sync) override
280
+ {
281
+ return Promise<std::string>::async([destination, amountSat, comment, no_sync]()
282
+ {
283
+ try {
284
+ uint64_t amount_val = 0;
285
+ if (amountSat.has_value()) {
286
+ amount_val = static_cast<uint64_t>(amountSat.value());
287
+ }
288
+ std::string comment_val = "";
289
+ if (comment.has_value()) {
290
+ comment_val = comment.value();
291
+ }
292
+ rust::String status_rs = bark_cxx::send_payment(destination, amount_val, comment_val, no_sync);
293
+ return std::string(status_rs.data(), status_rs.length());
294
+ } catch (const rust::Error &e) {
295
+ throw std::runtime_error(e.what());
296
+ } });
297
+ }
298
+
299
+ std::shared_ptr<Promise<std::string>>
300
+ sendRoundOnchain(const std::string &destination, double amountSat,
301
+ bool no_sync) override
302
+ {
303
+ return Promise<std::string>::async(
304
+ [destination, amountSat, no_sync]()
305
+ {
306
+ try
307
+ {
308
+ rust::String status_rs = bark_cxx::send_round_onchain(destination, static_cast<uint64_t>(amountSat), no_sync);
309
+ return std::string(status_rs.data(), status_rs.length());
310
+ }
311
+ catch (const rust::Error &e)
312
+ {
313
+ throw std::runtime_error(e.what());
314
+ }
315
+ });
316
+ }
317
+
318
+ // --- Lightning Operations ---
319
+
320
+ std::shared_ptr<Promise<std::string>>
321
+ bolt11Invoice(double amountMsat) override
322
+ {
323
+ return Promise<std::string>::async([amountMsat]()
324
+ {
325
+ try {
326
+ rust::String invoice_rs = bark_cxx::bolt11_invoice(static_cast<uint64_t>(amountMsat));
327
+ return std::string(invoice_rs.data(), invoice_rs.length());
328
+ } catch (const rust::Error &e) {
329
+ throw std::runtime_error(e.what());
330
+ } });
331
+ }
332
+
333
+ std::shared_ptr<Promise<void>>
334
+ claimBolt11Payment(const std::string &bolt11) override
335
+ {
336
+ return Promise<void>::async([bolt11]()
337
+ {
338
+ try {
339
+ bark_cxx::claim_bolt11_payment(bolt11);
340
+ } catch (const rust::Error &e) {
341
+ throw std::runtime_error(e.what());
342
+ } });
343
+ }
344
+
345
+ // --- Offboarding / Exiting ---
346
+
347
+ std::shared_ptr<Promise<std::string>>
348
+ offboardSpecific(const std::vector<std::string> &vtxoIds,
349
+ const std::optional<std::string> &optionalAddress,
350
+ bool no_sync) override
351
+ {
352
+ return Promise<std::string>::async(
353
+ [vtxoIds, optionalAddress, no_sync]()
354
+ {
355
+ try
356
+ {
357
+ rust::Vec<rust::String> rust_vtxo_ids;
358
+ for (const auto &id : vtxoIds)
359
+ {
360
+ rust_vtxo_ids.push_back(rust::String(id));
361
+ }
362
+ std::string address = optionalAddress.has_value() ? optionalAddress.value() : "";
363
+ rust::String status_rs = bark_cxx::offboard_specific(std::move(rust_vtxo_ids), address, no_sync);
364
+ return std::string(status_rs.data(), status_rs.length());
365
+ }
366
+ catch (const rust::Error &e)
367
+ {
368
+ throw std::runtime_error(e.what());
369
+ }
370
+ });
371
+ }
372
+
373
+ std::shared_ptr<Promise<std::string>>
374
+ offboardAll(const std::optional<std::string> &optionalAddress,
375
+ bool no_sync) override
376
+ {
377
+ return Promise<std::string>::async([optionalAddress,
378
+ no_sync]()
379
+ {
380
+ try {
381
+ std::string address = optionalAddress.has_value() ? optionalAddress.value() : "";
382
+ rust::String status_rs = bark_cxx::offboard_all(address, no_sync);
383
+ return std::string(status_rs.data(), status_rs.length());
384
+ } catch (const rust::Error &e) {
385
+ throw std::runtime_error(e.what());
386
+ } });
387
+ }
388
+
389
+ std::shared_ptr<Promise<std::string>> exitStartSpecific(
390
+ const std::vector<std::string> &vtxoIds) override
391
+ {
392
+ return Promise<std::string>::async([vtxoIds]()
393
+ {
394
+ try {
395
+ rust::Vec<rust::String> rust_vtxo_ids;
396
+ for (const auto &id : vtxoIds)
397
+ {
398
+ rust_vtxo_ids.push_back(rust::String(id));
399
+ }
400
+ rust::String status_rs = bark_cxx::start_exit_for_vtxos(std::move(rust_vtxo_ids));
401
+ return std::string(status_rs.data(), status_rs.length());
402
+ } catch (const rust::Error &e) {
403
+ throw std::runtime_error(e.what());
404
+ } });
405
+ }
406
+
407
+ std::shared_ptr<Promise<std::string>>
408
+ exitStartAll() override
409
+ {
410
+ return Promise<std::string>::async([]()
411
+ {
412
+ try {
413
+ rust::String status_rs = bark_cxx::start_exit_for_entire_wallet();
414
+ return std::string(status_rs.data(), status_rs.length());
415
+ } catch (const rust::Error &e) {
416
+ throw std::runtime_error(e.what());
417
+ } });
418
+ }
419
+
420
+ std::shared_ptr<Promise<std::string>>
421
+ exitProgressOnce() override
422
+ {
423
+ return Promise<std::string>::async([]()
424
+ {
425
+ try {
426
+ rust::String status_rs = bark_cxx::exit_progress_once();
427
+ return std::string(status_rs.data(), status_rs.length());
428
+ } catch (const rust::Error &e) {
429
+ throw std::runtime_error(e.what());
430
+ } });
431
+ }
432
+
433
+ private:
434
+ // Tag for logging/debugging within Nitro
435
+ static constexpr auto TAG = "NitroArk";
436
+ };
621
437
 
622
438
  } // namespace margelo::nitro::nitroark