@withautonomi/autonomi 0.2.2-rc.3 → 0.4.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/src/lib.rs ADDED
@@ -0,0 +1,2290 @@
1
+ use std::{path::PathBuf, str::FromStr};
2
+
3
+ use autonomi::{
4
+ chunk::DataMapChunk,
5
+ client::{data::DataAddress, payment::PaymentOption},
6
+ files::{
7
+ archive_private::PrivateArchiveDataMap, archive_public::ArchiveAddress, Metadata,
8
+ PrivateArchive, PublicArchive,
9
+ },
10
+ pointer::PointerTarget,
11
+ register::{RegisterAddress, RegisterHistory},
12
+ vault::{UserData, VaultContentType, VaultSecretKey},
13
+ AttoTokens, Bytes, Chunk, ChunkAddress, Client, GraphEntry, GraphEntryAddress, Multiaddr,
14
+ Network, Pointer, PointerAddress, PublicKey, Scratchpad, ScratchpadAddress, SecretKey,
15
+ Signature, Wallet, XorName,
16
+ };
17
+
18
+ use napi::bindgen_prelude::*;
19
+ use napi_derive::napi;
20
+ use tokio::sync::Mutex;
21
+
22
+ // Convert Rust errors to JavaScript errors
23
+ fn map_error<E>(err: E) -> napi::Error
24
+ where
25
+ E: std::error::Error,
26
+ {
27
+ let mut err_str = String::new();
28
+ err_str.push_str(&format!("{err:?}: {err}\n"));
29
+ let mut source = err.source();
30
+ while let Some(err) = source {
31
+ err_str.push_str(&format!(" Caused by: {err:?}: {err}\n"));
32
+ source = err.source();
33
+ }
34
+
35
+ napi::Error::new(Status::GenericFailure, err_str)
36
+ }
37
+
38
+ fn big_int_to_u64(value: BigInt, arg: &str) -> Result<u64> {
39
+ let (_signed, value, losless) = value.get_u64();
40
+ if !losless {
41
+ return Err(napi::Error::new(
42
+ Status::InvalidArg,
43
+ format!("expected `{arg}` to fit in a u64"),
44
+ ));
45
+ }
46
+
47
+ Ok(value)
48
+ }
49
+
50
+ fn uint8_array_to_array<const LEN: usize>(value: Uint8Array, arg: &str) -> Result<[u8; LEN]> {
51
+ value.as_ref().try_into().map_err(|_err| {
52
+ napi::Error::new(
53
+ Status::InvalidArg,
54
+ format!(
55
+ "`{arg}` is expected to be a {LEN}-byte array, but is {} bytes long",
56
+ value.len()
57
+ ),
58
+ )
59
+ })
60
+ }
61
+
62
+ /// Represents a client for the Autonomi network.
63
+ #[napi(js_name = "Client")]
64
+ pub struct JsClient(Client);
65
+
66
+ #[napi]
67
+ impl JsClient {
68
+ /// Initialize the client with default configuration.
69
+ ///
70
+ /// See `init_with_config`.
71
+ #[napi(factory)]
72
+ pub async fn init() -> Result<Self> {
73
+ let client = Client::init().await.map_err(map_error)?;
74
+
75
+ Ok(Self(client))
76
+ }
77
+
78
+ /// Initialize a client that is configured to be local.
79
+ ///
80
+ /// See `init_with_config`.
81
+ #[napi(factory)]
82
+ pub async fn init_local() -> Result<Self> {
83
+ let client = Client::init_local().await.map_err(map_error)?;
84
+
85
+ Ok(Self(client))
86
+ }
87
+
88
+ /// Initialize a client that bootstraps from a list of peers.
89
+ ///
90
+ /// If any of the provided peers is a global address, the client will not be local.
91
+ #[napi]
92
+ pub async fn init_with_peers(peers: Vec<String>) -> Result<Self> {
93
+ let peers = peers
94
+ .iter()
95
+ .map(|p| Multiaddr::from_str(p))
96
+ .collect::<std::result::Result<Vec<Multiaddr>, _>>()
97
+ .map_err(map_error)?;
98
+
99
+ let client = Client::init_with_peers(peers).await.map_err(map_error)?;
100
+
101
+ Ok(Self(client))
102
+ }
103
+
104
+ // /// Initialize the client with the given configuration.
105
+ // ///
106
+ // /// This will block until CLOSE_GROUP_SIZE have been added to the routing table.
107
+ // ///
108
+ // /// See ClientConfig.
109
+ // #[napi]
110
+ // pub async fn init_with_config(config: ClientConfig) -> Result<Self> {
111
+ // todo!()
112
+ // }
113
+
114
+ #[napi]
115
+ pub fn evm_network(&self) -> JsNetwork {
116
+ JsNetwork(self.0.evm_network().clone())
117
+ }
118
+
119
+ // Chunks
120
+
121
+ /// Get a chunk from the network.
122
+ #[napi]
123
+ pub async fn chunk_get(&self, addr: &JsChunkAddress) -> Result<Buffer> {
124
+ let chunk = self.0.chunk_get(&addr.0).await.map_err(map_error)?;
125
+
126
+ Ok(Buffer::from(chunk.value.to_vec()))
127
+ }
128
+
129
+ /// Manually upload a chunk to the network.
130
+ ///
131
+ /// It is recommended to use the `data_put` method instead to upload data.
132
+ #[napi]
133
+ pub async fn chunk_put(
134
+ &self,
135
+ data: Buffer,
136
+ payment_option: &JsPaymentOption,
137
+ ) -> Result<tuple_result::ChunkPut> {
138
+ let chunk = Chunk::new(Bytes::from(data.as_ref().to_vec()));
139
+
140
+ let (cost, addr) = self
141
+ .0
142
+ .chunk_put(&chunk, payment_option.0.clone())
143
+ .await
144
+ .map_err(map_error)?;
145
+
146
+ Ok(tuple_result::ChunkPut { cost, addr })
147
+ }
148
+
149
+ /// Get the cost of a chunk.
150
+ #[napi]
151
+ pub async fn chunk_cost(&self, addr: &JsChunkAddress) -> Result</* AttoTokens */ String> {
152
+ let cost = self.0.chunk_cost(&addr.0).await.map_err(map_error)?;
153
+
154
+ Ok(cost.to_string())
155
+ }
156
+
157
+ // /// Upload chunks and retry failed uploads up to RETRY_ATTEMPTS times.
158
+ // #[napi]
159
+ // pub async fn upload_chunks_with_retries(&self, chunks: Vec<Chunk>, receipt: &Receipt) -> Vec<(Chunk, PutError)> {
160
+ // todo!()
161
+ // }
162
+
163
+ // Graph entries
164
+
165
+ /// Fetches a GraphEntry from the network.
166
+ #[napi]
167
+ pub async fn graph_entry_get(&self, address: &JsGraphEntryAddress) -> Result<JsGraphEntry> {
168
+ let graph_entry = self
169
+ .0
170
+ .graph_entry_get(&address.0)
171
+ .await
172
+ .map_err(map_error)?;
173
+
174
+ Ok(JsGraphEntry(graph_entry))
175
+ }
176
+
177
+ /// Check if a graph_entry exists on the network
178
+ #[napi]
179
+ pub async fn graph_entry_check_existance(&self, address: &JsGraphEntryAddress) -> Result<bool> {
180
+ let exists = self
181
+ .0
182
+ .graph_entry_check_existance(&address.0)
183
+ .await
184
+ .map_err(map_error)?;
185
+
186
+ Ok(exists)
187
+ }
188
+
189
+ /// Manually puts a GraphEntry to the network.
190
+ #[napi]
191
+ pub async fn graph_entry_put(
192
+ &self,
193
+ entry: &JsGraphEntry,
194
+ payment_option: &JsPaymentOption,
195
+ ) -> Result</* (AttoTokens, JsGraphEntryAddress) */ tuple_result::GraphEntryPut> {
196
+ let (cost, addr) = self
197
+ .0
198
+ .graph_entry_put(entry.0.clone(), payment_option.0.clone())
199
+ .await
200
+ .map_err(map_error)?;
201
+
202
+ Ok(tuple_result::GraphEntryPut { cost, addr })
203
+ }
204
+
205
+ /// Get the cost to create a GraphEntry
206
+ #[napi]
207
+ pub async fn graph_entry_cost(&self, key: &JsPublicKey) -> Result</* AttoTokens */ String> {
208
+ self.0
209
+ .graph_entry_cost(&key.0)
210
+ .await
211
+ .map(|c| c.to_string())
212
+ .map_err(map_error)
213
+ }
214
+
215
+ // Pointers
216
+
217
+ /// Get a pointer from the network
218
+ #[napi]
219
+ pub async fn pointer_get(&self, address: &JsPointerAddress) -> Result<JsPointer> {
220
+ self.0
221
+ .pointer_get(&address.0)
222
+ .await
223
+ .map(JsPointer)
224
+ .map_err(map_error)
225
+ }
226
+
227
+ /// Check if a pointer exists on the network
228
+ #[napi]
229
+ pub async fn pointer_check_existance(&self, address: &JsPointerAddress) -> Result<bool> {
230
+ self.0
231
+ .pointer_check_existance(&address.0)
232
+ .await
233
+ .map_err(map_error)
234
+ }
235
+
236
+ /// Verify a pointer
237
+ #[napi]
238
+ pub fn pointer_verify(pointer: &JsPointer) -> Result<()> {
239
+ Client::pointer_verify(&pointer.0).map_err(map_error)
240
+ }
241
+
242
+ /// Manually store a pointer on the network
243
+ #[napi]
244
+ pub async fn pointer_put(
245
+ &self,
246
+ pointer: &JsPointer,
247
+ payment_option: &JsPaymentOption,
248
+ ) -> Result</* (AttoTokens, JsPointerAddress) */ tuple_result::PointerPut> {
249
+ let (cost, addr) = self
250
+ .0
251
+ .pointer_put(pointer.0.clone(), payment_option.0.clone())
252
+ .await
253
+ .map_err(map_error)?;
254
+
255
+ Ok(tuple_result::PointerPut { cost, addr })
256
+ }
257
+
258
+ /// Create a new pointer on the network.
259
+ ///
260
+ /// Make sure that the owner key is not already used for another pointer as each key is associated with one pointer
261
+ #[napi]
262
+ pub async fn pointer_create(
263
+ &self,
264
+ owner: &JsSecretKey,
265
+ target: &JsPointerTarget,
266
+ payment_option: &JsPaymentOption,
267
+ ) -> Result</* (AttoTokens, JsPointerAddress) */ tuple_result::PointerPut> {
268
+ let (cost, addr) = self
269
+ .0
270
+ .pointer_create(&owner.0, target.0.clone(), payment_option.0.clone())
271
+ .await
272
+ .map_err(map_error)?;
273
+
274
+ Ok(tuple_result::PointerPut { cost, addr })
275
+ }
276
+
277
+ /// Update an existing pointer to point to a new target on the network.
278
+ ///
279
+ /// The pointer needs to be created first with Client::pointer_put.
280
+ /// This operation is free as the pointer was already paid for at creation.
281
+ /// Only the latest version of the pointer is kept on the Network,
282
+ /// previous versions will be overwritten and unrecoverable.
283
+ #[napi]
284
+ pub async fn pointer_update(
285
+ &self,
286
+ owner: &JsSecretKey,
287
+ target: &JsPointerTarget,
288
+ ) -> Result<()> {
289
+ self.0
290
+ .pointer_update(&owner.0, target.0.clone())
291
+ .await
292
+ .map_err(map_error)
293
+ }
294
+
295
+ /// Calculate the cost of storing a pointer
296
+ #[napi]
297
+ pub async fn pointer_cost(&self, key: &JsPublicKey) -> Result</* AttoTokens */ String> {
298
+ let cost = self.0.pointer_cost(&key.0).await.map_err(map_error)?;
299
+
300
+ Ok(cost.to_string())
301
+ }
302
+
303
+ // Scratchpad
304
+
305
+ /// Get Scratchpad from the Network. A Scratchpad is stored at the owner's public key so we can derive the address from it.
306
+ #[napi]
307
+ pub async fn scratchpad_get_from_public_key(
308
+ &self,
309
+ public_key: &JsPublicKey,
310
+ ) -> Result<JsScratchpad> {
311
+ self.0
312
+ .scratchpad_get_from_public_key(&public_key.0)
313
+ .await
314
+ .map(JsScratchpad)
315
+ .map_err(map_error)
316
+ }
317
+
318
+ /// Get Scratchpad from the Network
319
+ #[napi]
320
+ pub async fn scratchpad_get(&self, address: &JsScratchpadAddress) -> Result<JsScratchpad> {
321
+ self.0
322
+ .scratchpad_get(&address.0)
323
+ .await
324
+ .map(JsScratchpad)
325
+ .map_err(map_error)
326
+ }
327
+
328
+ /// Check if a scratchpad exists on the network
329
+ #[napi]
330
+ pub async fn scratchpad_check_existance(&self, address: &JsScratchpadAddress) -> Result<bool> {
331
+ self.0
332
+ .scratchpad_check_existance(&address.0)
333
+ .await
334
+ .map_err(map_error)
335
+ }
336
+
337
+ /// Verify a scratchpad
338
+ #[napi]
339
+ pub fn scratchpad_verify(scratchpad: &JsScratchpad) -> Result<()> {
340
+ Client::scratchpad_verify(&scratchpad.0).map_err(map_error)
341
+ }
342
+
343
+ /// Manually store a scratchpad on the network
344
+ #[napi]
345
+ pub async fn scratchpad_put(
346
+ &self,
347
+ scratchpad: &JsScratchpad,
348
+ payment_option: &JsPaymentOption,
349
+ ) -> Result</* (AttoTokens, JsScratchpadAddress) */ tuple_result::ScratchpadPut> {
350
+ let (cost, addr) = self
351
+ .0
352
+ .scratchpad_put(scratchpad.0.clone(), payment_option.0.clone())
353
+ .await
354
+ .map_err(map_error)?;
355
+
356
+ Ok(tuple_result::ScratchpadPut { cost, addr })
357
+ }
358
+
359
+ /// Create a new scratchpad to the network.
360
+ ///
361
+ /// Make sure that the owner key is not already used for another scratchpad as each key is associated with one scratchpad. The data will be encrypted with the owner key before being stored on the network. The content type is used to identify the type of data stored in the scratchpad, the choice is up to the caller.
362
+ ///
363
+ /// Returns the cost and the address of the scratchpad.
364
+ #[napi]
365
+ pub async fn scratchpad_create(
366
+ &self,
367
+ owner: &JsSecretKey,
368
+ content_type: BigInt, // `u64`
369
+ initial_data: Buffer,
370
+ payment_option: &JsPaymentOption,
371
+ ) -> Result</* (AttoTokens, JsScratchpadAddress) */ tuple_result::ScratchpadPut> {
372
+ let content_type = big_int_to_u64(content_type, "content_type")?;
373
+
374
+ let (cost, addr) = self
375
+ .0
376
+ .scratchpad_create(
377
+ &owner.0,
378
+ content_type,
379
+ &Bytes::copy_from_slice(&initial_data),
380
+ payment_option.0.clone(),
381
+ )
382
+ .await
383
+ .map_err(map_error)?;
384
+
385
+ Ok(tuple_result::ScratchpadPut { cost, addr })
386
+ }
387
+
388
+ /// Update an existing scratchpad to the network.
389
+ /// The scratchpad needs to be created first with Client::scratchpad_create.
390
+ /// This operation is free as the scratchpad was already paid for at creation.
391
+ /// Only the latest version of the scratchpad is kept on the Network,
392
+ /// previous versions will be overwritten and unrecoverable.
393
+ #[napi]
394
+ pub async fn scratchpad_update(
395
+ &self,
396
+ owner: &JsSecretKey,
397
+ content_type: BigInt, // `u64`
398
+ data: Buffer,
399
+ ) -> Result<()> {
400
+ let content_type = big_int_to_u64(content_type, "content_type")?;
401
+
402
+ self.0
403
+ .scratchpad_update(&owner.0, content_type, &Bytes::copy_from_slice(&data))
404
+ .await
405
+ .map_err(map_error)
406
+ }
407
+
408
+ /// Get the cost of creating a new Scratchpad
409
+ #[napi]
410
+ pub async fn scratchpad_cost(&self, owner: &JsPublicKey) -> Result</* AttoTokens */ String> {
411
+ let cost = self.0.scratchpad_cost(&owner.0).await.map_err(map_error)?;
412
+
413
+ Ok(cost.to_string())
414
+ }
415
+
416
+ // Data
417
+
418
+ /// Fetch a blob of (private) data from the network
419
+ #[napi]
420
+ pub async fn data_get(&self, data_map: &JsDataMapChunk) -> Result<Buffer> {
421
+ let data = self.0.data_get(&data_map.0).await.map_err(map_error)?;
422
+
423
+ Ok(Buffer::from(data.as_ref()))
424
+ }
425
+
426
+ /// Upload a piece of private data to the network. This data will be self-encrypted.
427
+ /// The DataMapChunk is not uploaded to the network, keeping the data private.
428
+ ///
429
+ /// Returns the DataMapChunk containing the map to the encrypted chunks.
430
+ #[napi]
431
+ pub async fn data_put(
432
+ &self,
433
+ data: Buffer,
434
+ payment_option: &JsPaymentOption,
435
+ ) -> Result</* (AttoTokens, JsDataMapChunk) */ tuple_result::DataPutResult> {
436
+ let data = Bytes::copy_from_slice(&data);
437
+
438
+ let (cost, data_map) = self
439
+ .0
440
+ .data_put(data, payment_option.0.clone())
441
+ .await
442
+ .map_err(map_error)?;
443
+
444
+ Ok(tuple_result::DataPutResult { cost, data_map })
445
+ }
446
+
447
+ /// Fetch a blob of data from the network
448
+ #[napi]
449
+ pub async fn data_get_public(&self, addr: &JsDataAddress) -> Result<Buffer> {
450
+ let data = self.0.data_get_public(&addr.0).await.map_err(map_error)?;
451
+
452
+ Ok(Buffer::from(data.as_ref()))
453
+ }
454
+
455
+ /// Upload a piece of data to the network. This data is publicly accessible.
456
+ ///
457
+ /// Returns the Data Address at which the data was stored.
458
+ #[napi]
459
+ pub async fn data_put_public(
460
+ &self,
461
+ data: Buffer,
462
+ payment_option: &JsPaymentOption,
463
+ ) -> Result</* (AttoTokens, JsDataAddress) */ tuple_result::DataPutPublicResult> {
464
+ let data = Bytes::copy_from_slice(&data);
465
+
466
+ let (cost, addr) = self
467
+ .0
468
+ .data_put_public(data, payment_option.0.clone())
469
+ .await
470
+ .map_err(map_error)?;
471
+
472
+ Ok(tuple_result::DataPutPublicResult { cost, addr })
473
+ }
474
+
475
+ /// Get the estimated cost of storing a piece of data.
476
+ #[napi]
477
+ pub async fn data_cost(&self, data: Buffer) -> Result</* AttoTokens */ String> {
478
+ let cost = self
479
+ .0
480
+ .data_cost(Bytes::copy_from_slice(&data))
481
+ .await
482
+ .map_err(map_error)?;
483
+
484
+ Ok(cost.to_string())
485
+ }
486
+
487
+ // Archives
488
+
489
+ /// Fetch a PrivateArchive from the network
490
+ #[napi]
491
+ pub async fn archive_get(&self, addr: &JsPrivateArchiveDataMap) -> Result<JsPrivateArchive> {
492
+ let archive = self.0.archive_get(&addr.0).await.map_err(map_error)?;
493
+
494
+ Ok(JsPrivateArchive(archive))
495
+ }
496
+
497
+ /// Upload a PrivateArchive to the network
498
+ #[napi]
499
+ pub async fn archive_put(
500
+ &self,
501
+ archive: &JsPrivateArchive,
502
+ payment_option: &JsPaymentOption,
503
+ ) -> Result</*(AttoTokens, JsPrivateArchiveDataMap)*/ tuple_result::ArchivePutResult> {
504
+ let (cost, data_map) = self
505
+ .0
506
+ .archive_put(&archive.0, payment_option.0.clone())
507
+ .await
508
+ .map_err(map_error)?;
509
+
510
+ Ok(tuple_result::ArchivePutResult { cost, data_map })
511
+ }
512
+
513
+ // <TOPIC>
514
+
515
+ /// Fetch an archive from the network
516
+ #[napi]
517
+ pub async fn archive_get_public(&self, addr: &JsArchiveAddress) -> Result<JsPublicArchive> {
518
+ let archive = self
519
+ .0
520
+ .archive_get_public(&addr.0)
521
+ .await
522
+ .map_err(map_error)?;
523
+
524
+ Ok(JsPublicArchive(archive))
525
+ }
526
+
527
+ /// Upload an archive to the network
528
+ #[napi]
529
+ pub async fn archive_put_public(
530
+ &self,
531
+ archive: &JsPublicArchive,
532
+ payment_option: &JsPaymentOption,
533
+ ) -> Result</* (AttoTokens, JsArchiveAddress) */ tuple_result::ArchivePutPublicResult> {
534
+ let (cost, addr) = self
535
+ .0
536
+ .archive_put_public(&archive.0, payment_option.0.clone())
537
+ .await
538
+ .map_err(map_error)?;
539
+
540
+ Ok(tuple_result::ArchivePutPublicResult { cost, addr })
541
+ }
542
+
543
+ /// Get the cost to upload an archive
544
+ #[napi]
545
+ pub async fn archive_cost(&self, archive: &JsPublicArchive) -> Result</* AttoTokens */ String> {
546
+ let cost = self
547
+ .0
548
+ .archive_cost(&archive.0.clone())
549
+ .await
550
+ .map_err(map_error)?;
551
+
552
+ Ok(cost.to_string())
553
+ }
554
+
555
+ // Files
556
+
557
+ /// Download a private file from network to local file system
558
+ #[napi]
559
+ pub async fn file_download(
560
+ &self,
561
+ data_map: &JsDataMapChunk,
562
+ to_dest: /* PathBuf */ String,
563
+ ) -> Result<()> {
564
+ let to_dest = PathBuf::from(to_dest);
565
+
566
+ self.0
567
+ .file_download(&data_map.0, to_dest)
568
+ .await
569
+ .map_err(map_error)
570
+ }
571
+
572
+ /// Download a private directory from network to local file system
573
+ #[napi]
574
+ pub async fn dir_download(
575
+ &self,
576
+ archive_access: &JsPrivateArchiveDataMap,
577
+ to_dest: /* PathBuf */ String,
578
+ ) -> Result<()> {
579
+ let to_dest = PathBuf::from(to_dest);
580
+
581
+ self.0
582
+ .dir_download(&archive_access.0, to_dest)
583
+ .await
584
+ .map_err(map_error)
585
+ }
586
+
587
+ /// Upload the content of all files in a directory to the network.
588
+ /// The directory is recursively walked and each file is uploaded to the network.
589
+ ///
590
+ /// The data maps of these (private) files are not uploaded but returned within
591
+ /// the PrivateArchive return type.
592
+
593
+ #[napi]
594
+ pub async fn dir_content_upload(
595
+ &self,
596
+ dir_path: /* PathBuf */ String,
597
+ payment_option: &JsPaymentOption,
598
+ ) -> Result</* (AttoTokens, JsPrivateArchive) */ tuple_result::DirContentUpload> {
599
+ let dir_path = PathBuf::from(dir_path);
600
+
601
+ let (cost, archive) = self
602
+ .0
603
+ .dir_content_upload(dir_path, payment_option.0.clone())
604
+ .await
605
+ .map_err(map_error)?;
606
+
607
+ Ok(tuple_result::DirContentUpload { cost, archive })
608
+ }
609
+
610
+ /// Same as Client::dir_content_upload but also uploads the archive (privately) to the network.
611
+ ///
612
+ /// Returns the PrivateArchiveDataMap allowing the private archive to be downloaded from the network.
613
+ #[napi]
614
+ pub async fn dir_upload(
615
+ &self,
616
+ dir_path: /* PathBuf */ String,
617
+ payment_option: &JsPaymentOption,
618
+ ) -> Result</* (AttoTokens, JsPrivateArchiveDataMap) */ tuple_result::DirUpload> {
619
+ let dir_path = PathBuf::from(dir_path);
620
+
621
+ let (cost, data_map) = self
622
+ .0
623
+ .dir_upload(dir_path, payment_option.0.clone())
624
+ .await
625
+ .map_err(map_error)?;
626
+
627
+ Ok(tuple_result::DirUpload { cost, data_map })
628
+ }
629
+
630
+ /// Upload the content of a private file to the network. Reads file, splits into
631
+ /// chunks, uploads chunks, uploads datamap, returns DataMapChunk (pointing to the datamap)
632
+ #[napi]
633
+ pub async fn file_content_upload(
634
+ &self,
635
+ path: /* PathBuf */ String,
636
+ payment_option: &JsPaymentOption,
637
+ ) -> Result</* (AttoTokens, JsDataMapChunk) */ tuple_result::FileContentUpload> {
638
+ let path = PathBuf::from(path);
639
+
640
+ let (cost, data_map) = self
641
+ .0
642
+ .file_content_upload(path, payment_option.0.clone())
643
+ .await
644
+ .map_err(map_error)?;
645
+
646
+ Ok(tuple_result::FileContentUpload { cost, data_map })
647
+ }
648
+
649
+ /// Download file from network to local file system
650
+ #[napi]
651
+ pub async fn file_download_public(
652
+ &self,
653
+ data_addr: &JsDataAddress,
654
+ to_dest: /* PathBuf */ String,
655
+ ) -> Result<()> {
656
+ let to_dest = PathBuf::from(to_dest);
657
+
658
+ self.0
659
+ .file_download_public(&data_addr.0, to_dest)
660
+ .await
661
+ .map_err(map_error)
662
+ }
663
+
664
+ /// Download directory from network to local file system
665
+ #[napi]
666
+ pub async fn dir_download_public(
667
+ &self,
668
+ archive_addr: &JsArchiveAddress,
669
+ to_dest: /* PathBuf */ String,
670
+ ) -> Result<()> {
671
+ let to_dest = PathBuf::from(to_dest);
672
+
673
+ self.0
674
+ .dir_download_public(&archive_addr.0, to_dest)
675
+ .await
676
+ .map_err(map_error)
677
+ }
678
+
679
+ /// Upload the content of all files in a directory to the network. The directory is recursively walked and each file is uploaded to the network.
680
+ ///
681
+ /// The data maps of these files are uploaded on the network, making the individual files publicly available.
682
+ ///
683
+ /// This returns, but does not upload (!),the PublicArchive containing the data maps of the uploaded files.
684
+ #[napi]
685
+ pub async fn dir_content_upload_public(
686
+ &self,
687
+ dir_path: /* PathBuf */ String,
688
+ payment_option: &JsPaymentOption,
689
+ ) -> Result</* (AttoTokens, JsPublicArchive) */ tuple_result::DirContentUploadPublic> {
690
+ let dir_path = PathBuf::from(dir_path);
691
+
692
+ let (cost, archive) = self
693
+ .0
694
+ .dir_content_upload_public(dir_path, payment_option.0.clone())
695
+ .await
696
+ .map_err(map_error)?;
697
+
698
+ Ok(tuple_result::DirContentUploadPublic { cost, archive })
699
+ }
700
+
701
+ /// Same as Client::dir_content_upload_public but also uploads the archive to the network.
702
+ ///
703
+ /// Returns the ArchiveAddress of the uploaded archive.
704
+ #[napi]
705
+ pub async fn dir_upload_public(
706
+ &self,
707
+ dir_path: /* PathBuf */ String,
708
+ payment_option: &JsPaymentOption,
709
+ ) -> Result</* (AttoTokens, JsArchiveAddress) */ tuple_result::DirUploadPublic> {
710
+ let dir_path = PathBuf::from(dir_path);
711
+
712
+ let (cost, addr) = self
713
+ .0
714
+ .dir_upload_public(dir_path, payment_option.0.clone())
715
+ .await
716
+ .map_err(map_error)?;
717
+
718
+ Ok(tuple_result::DirUploadPublic { cost, addr })
719
+ }
720
+
721
+ /// Upload the content of a file to the network. Reads file, splits into chunks,
722
+ /// uploads chunks, uploads datamap, returns DataAddr (pointing to the datamap)
723
+ #[napi]
724
+ pub async fn file_content_upload_public(
725
+ &self,
726
+ _path: /* PathBuf */ String,
727
+ _payment_option: &JsPaymentOption,
728
+ ) -> Result</* (AttoTokens, JsDataAddress) */ tuple_result::FileContentUploadPublic> {
729
+ todo!()
730
+ }
731
+
732
+ /// Get the cost to upload a file/dir to the network. quick and dirty implementation, please refactor once files are cleanly implemented
733
+ #[napi]
734
+ pub async fn file_cost(&self, path: /* &PathBuf */ String) -> Result</* AttoTokens */ String> {
735
+ let cost = self
736
+ .0
737
+ .file_cost(&PathBuf::from(path))
738
+ .await
739
+ .map_err(map_error)?;
740
+
741
+ Ok(cost.to_string())
742
+ }
743
+
744
+ // Vault/user data
745
+
746
+ /// Get the user data from the vault
747
+ #[napi]
748
+ pub async fn get_user_data_from_vault(
749
+ &self,
750
+ secret_key: &JsVaultSecretKey,
751
+ ) -> Result<JsUserData> {
752
+ self.0
753
+ .get_user_data_from_vault(&secret_key.0)
754
+ .await
755
+ .map(JsUserData)
756
+ .map_err(map_error)
757
+ }
758
+
759
+ /// Put the user data to the vault
760
+ ///
761
+ /// Returns the total cost of the put operation
762
+ #[napi]
763
+ pub async fn put_user_data_to_vault(
764
+ &self,
765
+ secret_key: &JsVaultSecretKey,
766
+ payment_option: &JsPaymentOption,
767
+ user_data: &JsUserData,
768
+ ) -> Result</* AttoTokens */ String> {
769
+ self.0
770
+ .put_user_data_to_vault(&secret_key.0, payment_option.0.clone(), user_data.0.clone())
771
+ .await
772
+ .map(|c| c.to_string())
773
+ .map_err(map_error)
774
+ }
775
+
776
+ /// Retrieves and returns a decrypted vault if one exists.
777
+ ///
778
+ /// Returns the content type of the bytes in the vault.
779
+ #[napi]
780
+ pub async fn fetch_and_decrypt_vault(
781
+ &self,
782
+ secret_key: &JsVaultSecretKey,
783
+ ) -> Result</* (Bytes, JsVaultContentType) */ tuple_result::FetchAndDecryptVault> {
784
+ let (data, content_type) = self
785
+ .0
786
+ .fetch_and_decrypt_vault(&secret_key.0)
787
+ .await
788
+ .map_err(map_error)?;
789
+
790
+ Ok(tuple_result::FetchAndDecryptVault { data, content_type })
791
+ }
792
+
793
+ /// Get the cost of creating a new vault A quick estimation of cost:
794
+ /// num_of_graph_entry * graph_entry_cost + num_of_scratchpad * scratchpad_cost
795
+ #[napi]
796
+ pub async fn vault_cost(
797
+ &self,
798
+ owner: &JsVaultSecretKey,
799
+ max_size: /* u64 */ BigInt,
800
+ ) -> Result</* AttoTokens */ String> {
801
+ let max_size = big_int_to_u64(max_size, "max_size")?;
802
+
803
+ let cost = self
804
+ .0
805
+ .vault_cost(&owner.0.clone(), max_size)
806
+ .await
807
+ .map_err(map_error)?;
808
+
809
+ Ok(cost.to_string())
810
+ }
811
+
812
+ /// Put data into the client’s VaultPacket
813
+ ///
814
+ /// Dynamically expand the vault capacity by paying for more space (Scratchpad) when needed.
815
+ ///
816
+ /// It is recommended to use the hash of the app name or unique identifier as the content type.
817
+
818
+ #[napi]
819
+ pub async fn write_bytes_to_vault(
820
+ &self,
821
+ data: Buffer,
822
+ payment_option: &JsPaymentOption,
823
+ secret_key: &JsVaultSecretKey,
824
+ content_type: &JsVaultContentType,
825
+ ) -> Result</* AttoTokens */ String> {
826
+ let data = Bytes::copy_from_slice(&data);
827
+
828
+ self.0
829
+ .write_bytes_to_vault(
830
+ data,
831
+ payment_option.0.clone(),
832
+ &secret_key.0,
833
+ content_type.0,
834
+ )
835
+ .await
836
+ .map(|c| c.to_string())
837
+ .map_err(map_error)
838
+ }
839
+
840
+ // Registers
841
+
842
+ /// Get the register history, starting from the root to the latest entry.
843
+ ///
844
+ /// This returns a RegisterHistory that can be use to get the register values from the history.
845
+ ///
846
+ /// RegisterHistory::next can be used to get the values one by one, from the first to the latest entry.
847
+ /// RegisterHistory::collect can be used to get all the register values from the history from the first to the latest entry.
848
+ #[napi]
849
+ pub fn register_history(&self, addr: &JsRegisterAddress) -> JsRegisterHistory {
850
+ let history = self.0.register_history(&addr.0);
851
+
852
+ JsRegisterHistory(Mutex::new(history))
853
+ }
854
+
855
+ /// Create a new register key from a SecretKey and a name.
856
+ ///
857
+ /// This derives a new SecretKey from the owner’s SecretKey using the name. Note that you will need to keep track of the names you used to create the register key.
858
+ #[napi]
859
+ pub fn register_key_from_name(owner: &JsSecretKey, name: String) -> JsSecretKey {
860
+ let key = Client::register_key_from_name(&owner.0, &name);
861
+ JsSecretKey(key)
862
+ }
863
+
864
+ /// Create a new RegisterValue from bytes, make sure the bytes are not longer than REGISTER_VALUE_SIZE
865
+ #[napi]
866
+ pub fn register_value_from_bytes(bytes: &[u8]) -> Result</* JsRegisterValue */ Uint8Array> {
867
+ Client::register_value_from_bytes(bytes)
868
+ .map(Uint8Array::from)
869
+ .map_err(map_error)
870
+ }
871
+
872
+ /// Create a new register with an initial value.
873
+ ///
874
+ /// Note that two payments are required, one for the underlying GraphEntry and one for the crate::Pointer
875
+ #[napi]
876
+ pub async fn register_create(
877
+ &self,
878
+ owner: &JsSecretKey,
879
+ initial_value: /* RegisterValue */ Uint8Array,
880
+ payment_option: &JsPaymentOption,
881
+ ) -> Result</* (AttoTokens, JsRegisterAddress) */ tuple_result::RegisterCreate> {
882
+ let initial_value: [u8; 32] = uint8_array_to_array(initial_value, "initial_value")?;
883
+
884
+ let (cost, addr) = self
885
+ .0
886
+ .register_create(&owner.0, initial_value, payment_option.0.clone())
887
+ .await
888
+ .map_err(map_error)?;
889
+
890
+ Ok(tuple_result::RegisterCreate { cost, addr })
891
+ }
892
+
893
+ /// Update the value of a register.
894
+ ////
895
+ /// The register needs to be created first with Client::register_create
896
+ #[napi]
897
+ pub async fn register_update(
898
+ &self,
899
+ owner: &JsSecretKey,
900
+ new_value: /* RegisterValue */ Uint8Array,
901
+ payment_option: &JsPaymentOption,
902
+ ) -> Result</* AttoTokens */ String> {
903
+ let new_value: [u8; 32] = uint8_array_to_array(new_value, "new_value")?;
904
+ self.0
905
+ .register_update(&owner.0, new_value, payment_option.0.clone())
906
+ .await
907
+ .map(|c| c.to_string())
908
+ .map_err(map_error)
909
+ }
910
+
911
+ /// Get the current value of the register
912
+ #[napi]
913
+ pub async fn register_get(
914
+ &self,
915
+ addr: &JsRegisterAddress,
916
+ ) -> Result</* JsRegisterValue */ Uint8Array> {
917
+ self.0
918
+ .register_get(&addr.0)
919
+ .await
920
+ .map(Uint8Array::from)
921
+ .map_err(map_error)
922
+ }
923
+
924
+ /// Get the cost of a register operation. Returns the cost of creation if it doesn’t exist, else returns the cost of an update
925
+ #[napi]
926
+ pub async fn register_cost(&self, owner: &JsPublicKey) -> Result</* AttoTokens */ String> {
927
+ let cost = self
928
+ .0
929
+ .register_cost(&owner.0.clone())
930
+ .await
931
+ .map_err(map_error)?;
932
+
933
+ Ok(cost.to_string())
934
+ }
935
+
936
+ // Quotes
937
+
938
+ // /// Get raw quotes from nodes. These quotes do not include actual record prices. You will likely want to use get_store_quotes instead.
939
+ // #[napi]
940
+ // pub async fn get_raw_quotes(
941
+ // &self,
942
+ // data_type: DataTypes,
943
+ // content_addrs: impl Iterator<Item = (XorName, usize)>,
944
+ // ) -> Vec<Result<(XorName, Vec<(PeerId, PaymentQuote)>)>> {
945
+ // todo!()
946
+ // }
947
+
948
+ // ///
949
+ // #[napi]
950
+ // pub async fn get_store_quotes(
951
+ // &self,
952
+ // data_type: DataTypes,
953
+ // content_addrs: impl Iterator<Item = (XorName, usize)>,
954
+ // ) -> Result<StoreQuote> {
955
+ // todo!()
956
+ // }
957
+ }
958
+
959
+ pub mod tuple_result {
960
+ use super::*;
961
+
962
+ // This type exists because NAPI-RS does not support returning tuples.
963
+ #[napi]
964
+ pub struct ChunkPut {
965
+ pub(crate) cost: AttoTokens,
966
+ pub(crate) addr: ChunkAddress, // Can't be `JsChunkAddress` as NAPI-RS expects a reference in that case.
967
+ }
968
+ #[napi]
969
+ impl ChunkPut {
970
+ #[napi(getter)]
971
+ pub fn cost(&self) -> String {
972
+ self.cost.to_string()
973
+ }
974
+ #[napi(getter)]
975
+ pub fn addr(&self) -> JsChunkAddress {
976
+ JsChunkAddress(self.addr)
977
+ }
978
+ }
979
+
980
+ #[napi]
981
+ pub struct GraphEntryPut {
982
+ pub(crate) cost: AttoTokens,
983
+ pub(crate) addr: GraphEntryAddress,
984
+ }
985
+ #[napi]
986
+ impl GraphEntryPut {
987
+ #[napi(getter)]
988
+ pub fn cost(&self) -> String {
989
+ self.cost.to_string()
990
+ }
991
+ #[napi(getter)]
992
+ pub fn addr(&self) -> JsGraphEntryAddress {
993
+ JsGraphEntryAddress(self.addr)
994
+ }
995
+ }
996
+
997
+ #[napi]
998
+ pub struct ScratchpadPut {
999
+ pub(crate) cost: AttoTokens,
1000
+ pub(crate) addr: ScratchpadAddress,
1001
+ }
1002
+ #[napi]
1003
+ impl ScratchpadPut {
1004
+ #[napi(getter)]
1005
+ pub fn cost(&self) -> String {
1006
+ self.cost.to_string()
1007
+ }
1008
+ #[napi(getter)]
1009
+ pub fn addr(&self) -> JsScratchpadAddress {
1010
+ JsScratchpadAddress(self.addr)
1011
+ }
1012
+ }
1013
+
1014
+ #[napi]
1015
+ pub struct PointerPut {
1016
+ pub(crate) cost: AttoTokens,
1017
+ pub(crate) addr: PointerAddress,
1018
+ }
1019
+ #[napi]
1020
+ impl PointerPut {
1021
+ #[napi(getter)]
1022
+ pub fn cost(&self) -> String {
1023
+ self.cost.to_string()
1024
+ }
1025
+ #[napi(getter)]
1026
+ pub fn addr(&self) -> JsPointerAddress {
1027
+ JsPointerAddress(self.addr)
1028
+ }
1029
+ }
1030
+
1031
+ #[napi]
1032
+ pub struct DataPutResult {
1033
+ pub(crate) cost: AttoTokens,
1034
+ pub(crate) data_map: DataMapChunk,
1035
+ }
1036
+ #[napi]
1037
+ impl DataPutResult {
1038
+ #[napi(getter)]
1039
+ pub fn cost(&self) -> String {
1040
+ self.cost.to_string()
1041
+ }
1042
+ #[napi(getter)]
1043
+ pub fn data_map(&self) -> JsDataMapChunk {
1044
+ JsDataMapChunk(self.data_map.clone())
1045
+ }
1046
+ }
1047
+
1048
+ #[napi]
1049
+ pub struct DataPutPublicResult {
1050
+ pub(crate) cost: AttoTokens,
1051
+ pub(crate) addr: DataAddress,
1052
+ }
1053
+ #[napi]
1054
+ impl DataPutPublicResult {
1055
+ #[napi(getter)]
1056
+ pub fn cost(&self) -> String {
1057
+ self.cost.to_string()
1058
+ }
1059
+ #[napi(getter)]
1060
+ pub fn addr(&self) -> JsDataAddress {
1061
+ JsDataAddress(self.addr)
1062
+ }
1063
+ }
1064
+
1065
+ #[napi]
1066
+ pub struct ArchivePutResult {
1067
+ pub(crate) cost: AttoTokens,
1068
+ pub(crate) data_map: PrivateArchiveDataMap,
1069
+ }
1070
+ #[napi]
1071
+ impl ArchivePutResult {
1072
+ #[napi(getter)]
1073
+ pub fn cost(&self) -> String {
1074
+ self.cost.to_string()
1075
+ }
1076
+ #[napi(getter)]
1077
+ pub fn data_map(&self) -> JsPrivateArchiveDataMap {
1078
+ JsPrivateArchiveDataMap(self.data_map.clone())
1079
+ }
1080
+ }
1081
+
1082
+ #[napi]
1083
+ pub struct ArchivePutPublicResult {
1084
+ pub(crate) cost: AttoTokens,
1085
+ pub(crate) addr: DataAddress,
1086
+ }
1087
+ #[napi]
1088
+ impl ArchivePutPublicResult {
1089
+ #[napi(getter)]
1090
+ pub fn cost(&self) -> String {
1091
+ self.cost.to_string()
1092
+ }
1093
+ #[napi(getter)]
1094
+ pub fn addr(&self) -> JsDataAddress {
1095
+ JsDataAddress(self.addr)
1096
+ }
1097
+ }
1098
+
1099
+ #[napi]
1100
+ pub struct DirContentUpload {
1101
+ pub(crate) cost: AttoTokens,
1102
+ pub(crate) archive: PrivateArchive,
1103
+ }
1104
+ #[napi]
1105
+ impl DirContentUpload {
1106
+ #[napi(getter)]
1107
+ pub fn cost(&self) -> String {
1108
+ self.cost.to_string()
1109
+ }
1110
+ #[napi(getter)]
1111
+ pub fn archive(&self) -> JsPrivateArchive {
1112
+ JsPrivateArchive(self.archive.clone())
1113
+ }
1114
+ }
1115
+
1116
+ #[napi]
1117
+ pub struct DirUpload {
1118
+ pub(crate) cost: AttoTokens,
1119
+ pub(crate) data_map: DataMapChunk,
1120
+ }
1121
+ #[napi]
1122
+ impl DirUpload {
1123
+ #[napi(getter)]
1124
+ pub fn cost(&self) -> String {
1125
+ self.cost.to_string()
1126
+ }
1127
+ #[napi(getter)]
1128
+ pub fn data_map(&self) -> JsDataMapChunk {
1129
+ JsDataMapChunk(self.data_map.clone())
1130
+ }
1131
+ }
1132
+
1133
+ #[napi]
1134
+ pub struct FileContentUpload {
1135
+ pub(crate) cost: AttoTokens,
1136
+ pub(crate) data_map: DataMapChunk,
1137
+ }
1138
+ #[napi]
1139
+ impl FileContentUpload {
1140
+ #[napi(getter)]
1141
+ pub fn cost(&self) -> String {
1142
+ self.cost.to_string()
1143
+ }
1144
+ #[napi(getter)]
1145
+ pub fn data_map(&self) -> JsDataMapChunk {
1146
+ JsDataMapChunk(self.data_map.clone())
1147
+ }
1148
+ }
1149
+
1150
+ #[napi]
1151
+ pub struct DirContentUploadPublic {
1152
+ pub(crate) cost: AttoTokens,
1153
+ pub(crate) archive: PublicArchive,
1154
+ }
1155
+ #[napi]
1156
+ impl DirContentUploadPublic {
1157
+ #[napi(getter)]
1158
+ pub fn cost(&self) -> String {
1159
+ self.cost.to_string()
1160
+ }
1161
+ #[napi(getter)]
1162
+ pub fn addr(&self) -> JsPublicArchive {
1163
+ JsPublicArchive(self.archive.clone())
1164
+ }
1165
+ }
1166
+
1167
+ #[napi]
1168
+ pub struct DirUploadPublic {
1169
+ pub(crate) cost: AttoTokens,
1170
+ pub(crate) addr: ArchiveAddress,
1171
+ }
1172
+ #[napi]
1173
+ impl DirUploadPublic {
1174
+ #[napi(getter)]
1175
+ pub fn cost(&self) -> String {
1176
+ self.cost.to_string()
1177
+ }
1178
+ #[napi(getter)]
1179
+ pub fn addr(&self) -> JsArchiveAddress {
1180
+ JsArchiveAddress(self.addr)
1181
+ }
1182
+ }
1183
+
1184
+ #[napi]
1185
+ pub struct FileContentUploadPublic {
1186
+ pub(crate) cost: AttoTokens,
1187
+ pub(crate) addr: PointerAddress,
1188
+ }
1189
+ #[napi]
1190
+ impl FileContentUploadPublic {
1191
+ #[napi(getter)]
1192
+ pub fn cost(&self) -> String {
1193
+ self.cost.to_string()
1194
+ }
1195
+ #[napi(getter)]
1196
+ pub fn addr(&self) -> JsPointerAddress {
1197
+ JsPointerAddress(self.addr)
1198
+ }
1199
+ }
1200
+
1201
+ #[napi]
1202
+ pub struct FetchAndDecryptVault {
1203
+ pub(crate) data: Bytes,
1204
+ pub(crate) content_type: VaultContentType,
1205
+ }
1206
+ #[napi]
1207
+ impl FetchAndDecryptVault {
1208
+ #[napi(getter)]
1209
+ pub fn data(&self) -> Buffer {
1210
+ Buffer::from(self.data.as_ref())
1211
+ }
1212
+ #[napi(getter)]
1213
+ pub fn content_type(&self) -> u64 {
1214
+ self.content_type
1215
+ }
1216
+ }
1217
+
1218
+ #[napi]
1219
+ pub struct RegisterCreate {
1220
+ pub(crate) cost: AttoTokens,
1221
+ pub(crate) addr: RegisterAddress,
1222
+ }
1223
+ #[napi]
1224
+ impl RegisterCreate {
1225
+ #[napi(getter)]
1226
+ pub fn cost(&self) -> String {
1227
+ self.cost.to_string()
1228
+ }
1229
+ #[napi(getter)]
1230
+ pub fn addr(&self) -> JsRegisterAddress {
1231
+ JsRegisterAddress(self.addr)
1232
+ }
1233
+ }
1234
+
1235
+ #[napi]
1236
+ pub struct GraphEntryDescendant {
1237
+ pub(crate) public_key: PublicKey,
1238
+ pub(crate) content: [u8; 32],
1239
+ }
1240
+ #[napi]
1241
+ impl GraphEntryDescendant {
1242
+ #[napi(getter)]
1243
+ pub fn public_key(&self) -> JsPublicKey {
1244
+ JsPublicKey(self.public_key)
1245
+ }
1246
+ #[napi(getter)]
1247
+ pub fn content(&self) -> Uint8Array {
1248
+ Uint8Array::from(self.content.as_ref())
1249
+ }
1250
+ }
1251
+
1252
+ #[napi(object)]
1253
+ pub struct ArchiveFile {
1254
+ pub path: String,
1255
+ pub created: BigInt,
1256
+ pub modified: BigInt,
1257
+ pub size: BigInt,
1258
+ pub extra: Option<String>,
1259
+ }
1260
+ }
1261
+
1262
+ /// A 256-bit number, viewed as a point in XOR space.
1263
+ ///
1264
+ /// This wraps an array of 32 bytes, i. e. a number between 0 and 2<sup>256</sup> - 1.
1265
+ ///
1266
+ /// XOR space is the space of these numbers, with the [XOR metric][1] as a notion of distance,
1267
+ /// i. e. the points with IDs `x` and `y` are considered to have distance `x xor y`.
1268
+ ///
1269
+ /// [1]: https://en.wikipedia.org/wiki/Kademlia#System_details
1270
+ #[napi(js_name = "XorName")]
1271
+ pub struct JsXorName(XorName);
1272
+ #[napi]
1273
+ impl JsXorName {
1274
+ /// Generate a XorName for the given content.
1275
+ #[napi(factory)]
1276
+ pub fn from_content(content: &[u8]) -> Self {
1277
+ Self(XorName::from_content_parts(&[content]))
1278
+ }
1279
+
1280
+ /// Generate a random XorName
1281
+ #[napi(factory)]
1282
+ pub fn random() -> Self {
1283
+ Self(XorName::random(&mut rand::thread_rng()))
1284
+ }
1285
+ }
1286
+
1287
+ /// Address of a chunk.
1288
+ ///
1289
+ /// It is derived from the content of the chunk.
1290
+ #[napi(js_name = "ChunkAddress")]
1291
+ pub struct JsChunkAddress(ChunkAddress);
1292
+
1293
+ #[napi]
1294
+ impl JsChunkAddress {
1295
+ /// Creates a new ChunkAddress.
1296
+ #[napi(constructor)]
1297
+ pub fn new(xor_name: &JsXorName) -> Self {
1298
+ Self(ChunkAddress::new(xor_name.0))
1299
+ }
1300
+
1301
+ /// Returns the XorName.
1302
+ #[napi]
1303
+ pub fn xorname(&self) -> JsXorName {
1304
+ JsXorName(*self.0.xorname())
1305
+ }
1306
+
1307
+ /// Returns the hex string representation of the address.
1308
+ #[napi]
1309
+ pub fn to_hex(&self) -> String {
1310
+ self.0.to_hex()
1311
+ }
1312
+
1313
+ /// Creates a new ChunkAddress from a hex string.
1314
+ #[napi(factory)]
1315
+ pub fn from_hex(hex: String) -> Result<Self> {
1316
+ let addr = ChunkAddress::from_hex(&hex).map_err(map_error)?;
1317
+
1318
+ Ok(Self(addr))
1319
+ }
1320
+ }
1321
+
1322
+ /// Address of a `GraphEntry`.
1323
+ ///
1324
+ /// It is derived from the owner's unique public key
1325
+ #[napi(js_name = "GraphEntryAddress")]
1326
+ pub struct JsGraphEntryAddress(GraphEntryAddress);
1327
+
1328
+ #[napi]
1329
+ impl JsGraphEntryAddress {
1330
+ /// Creates a new GraphEntryAddress.
1331
+ #[napi(constructor)]
1332
+ pub fn new(owner: &JsPublicKey) -> Self {
1333
+ Self(GraphEntryAddress::new(owner.0))
1334
+ }
1335
+
1336
+ /// Return the network name of the scratchpad.
1337
+ /// This is used to locate the scratchpad on the network.
1338
+ #[napi]
1339
+ pub fn xorname(&self) -> JsXorName {
1340
+ JsXorName(self.0.xorname())
1341
+ }
1342
+
1343
+ /// Serialize this `GraphEntryAddress` into a hex-encoded string.
1344
+ #[napi]
1345
+ pub fn to_hex(&self) -> String {
1346
+ self.0.to_hex()
1347
+ }
1348
+
1349
+ /// Parse a hex-encoded string into a `GraphEntryAddress`.
1350
+ #[napi(factory)]
1351
+ pub fn from_hex(hex: String) -> Result<Self> {
1352
+ let addr = GraphEntryAddress::from_hex(&hex).map_err(map_error)?;
1353
+
1354
+ Ok(Self(addr))
1355
+ }
1356
+ }
1357
+
1358
+ #[napi(js_name = "DataAddress")]
1359
+ pub struct JsDataAddress(DataAddress);
1360
+
1361
+ #[napi]
1362
+ impl JsDataAddress {
1363
+ /// Creates a new DataAddress.
1364
+ #[napi(constructor)]
1365
+ pub fn new(xor_name: &JsXorName) -> Self {
1366
+ Self(DataAddress::new(xor_name.0))
1367
+ }
1368
+
1369
+ /// Returns the XorName.
1370
+ #[napi]
1371
+ pub fn xorname(&self) -> JsXorName {
1372
+ JsXorName(*self.0.xorname())
1373
+ }
1374
+
1375
+ /// Returns the hex string representation of the address.
1376
+ #[napi]
1377
+ pub fn to_hex(&self) -> String {
1378
+ self.0.to_hex()
1379
+ }
1380
+
1381
+ /// Creates a new DataAddress from a hex string.
1382
+ #[napi(factory)]
1383
+ pub fn from_hex(hex: String) -> Result<Self> {
1384
+ DataAddress::from_hex(&hex).map(Self).map_err(map_error)
1385
+ }
1386
+ }
1387
+
1388
+ #[napi(js_name = "ArchiveAddress")]
1389
+ pub struct JsArchiveAddress(ArchiveAddress);
1390
+
1391
+ #[napi]
1392
+ impl JsArchiveAddress {
1393
+ /// Creates a new ArchiveAddress.
1394
+ #[napi(constructor)]
1395
+ pub fn new(xor_name: &JsXorName) -> Self {
1396
+ Self(ArchiveAddress::new(xor_name.0))
1397
+ }
1398
+
1399
+ /// Returns the XorName.
1400
+ #[napi]
1401
+ pub fn xorname(&self) -> JsXorName {
1402
+ JsXorName(*self.0.xorname())
1403
+ }
1404
+
1405
+ /// Returns the hex string representation of the address.
1406
+ #[napi]
1407
+ pub fn to_hex(&self) -> String {
1408
+ self.0.to_hex()
1409
+ }
1410
+
1411
+ /// Creates a new ArchiveAddress from a hex string.
1412
+ #[napi(factory)]
1413
+ pub fn from_hex(hex: String) -> Result<Self> {
1414
+ ArchiveAddress::from_hex(&hex).map(Self).map_err(map_error)
1415
+ }
1416
+ }
1417
+
1418
+ /// A wallet for interacting with the network's payment system
1419
+ #[napi(js_name = "Wallet")]
1420
+ pub struct JsWallet(Wallet);
1421
+
1422
+ #[napi]
1423
+ impl JsWallet {
1424
+ /// Convenience function that creates a new Wallet with a random EthereumWallet.
1425
+ pub fn new_with_random_wallet(network: Network) -> Self {
1426
+ JsWallet(Wallet::new_with_random_wallet(network))
1427
+ }
1428
+
1429
+ /// Creates a new Wallet based on the given Ethereum private key. It will fail with Error::PrivateKeyInvalid if private_key is invalid.
1430
+ #[napi(factory)]
1431
+ pub fn new_from_private_key(network: &JsNetwork, private_key: String) -> Result<Self> {
1432
+ let wallet =
1433
+ Wallet::new_from_private_key(network.0.clone(), &private_key).map_err(map_error)?;
1434
+
1435
+ Ok(Self(wallet))
1436
+ }
1437
+
1438
+ /// Returns a string representation of the wallet's address
1439
+ #[napi]
1440
+ pub fn address(&self) -> String {
1441
+ self.0.address().to_string()
1442
+ }
1443
+
1444
+ /// Returns the `Network` of this wallet.
1445
+ pub fn network(&self) -> JsNetwork {
1446
+ JsNetwork(self.0.network().clone())
1447
+ }
1448
+
1449
+ /// Returns the raw balance of payment tokens in the wallet
1450
+ #[napi]
1451
+ pub async fn balance(&self) -> Result<String> {
1452
+ let balance = self.0.balance_of_tokens().await.map_err(map_error)?;
1453
+
1454
+ Ok(balance.to_string())
1455
+ }
1456
+
1457
+ /// Returns the current balance of gas tokens in the wallet
1458
+ #[napi]
1459
+ pub async fn balance_of_gas(&self) -> Result<String> {
1460
+ let balance = self.0.balance_of_gas_tokens().await.map_err(map_error)?;
1461
+
1462
+ Ok(balance.to_string())
1463
+ }
1464
+ }
1465
+
1466
+ /// Options for making payments on the network
1467
+ #[napi(js_name = "PaymentOption")]
1468
+ pub struct JsPaymentOption(PaymentOption);
1469
+
1470
+ #[napi]
1471
+ impl JsPaymentOption {
1472
+ #[napi(factory)]
1473
+ pub fn from_wallet(wallet: &JsWallet) -> Self {
1474
+ Self(PaymentOption::from(&wallet.0))
1475
+ }
1476
+
1477
+ #[napi(factory)]
1478
+ pub fn from_receipt() -> Self {
1479
+ unimplemented!()
1480
+ }
1481
+ }
1482
+
1483
+ #[napi(js_name = "Network")]
1484
+ pub struct JsNetwork(Network);
1485
+
1486
+ #[napi]
1487
+ impl JsNetwork {
1488
+ #[napi(constructor)]
1489
+ pub fn new(local: bool) -> Result<Self> {
1490
+ let network = Network::new(local).map_err(map_error)?;
1491
+ Ok(Self(network))
1492
+ }
1493
+ }
1494
+
1495
+ #[napi(js_name = "PublicKey")]
1496
+ pub struct JsPublicKey(PublicKey);
1497
+
1498
+ #[napi]
1499
+ impl JsPublicKey {
1500
+ /// Returns a byte string representation of the public key.
1501
+ #[napi]
1502
+ pub fn to_bytes(&self) -> Uint8Array {
1503
+ Uint8Array::from(self.0.to_bytes())
1504
+ }
1505
+
1506
+ /// Returns the key with the given representation, if valid.
1507
+ #[napi(factory)]
1508
+ pub fn from_bytes(bytes: Uint8Array) -> Result<Self> {
1509
+ let bytes = uint8_array_to_array(bytes, "bytes")?;
1510
+ let key = PublicKey::from_bytes(bytes).map_err(map_error)?;
1511
+ Ok(Self(key))
1512
+ }
1513
+
1514
+ /// Returns the hex string representation of the public key.
1515
+ #[napi]
1516
+ pub fn to_hex(&self) -> String {
1517
+ self.0.to_hex()
1518
+ }
1519
+
1520
+ /// Creates a new PublicKey from a hex string.
1521
+ #[napi(factory)]
1522
+ pub fn from_hex(hex: String) -> Result<Self> {
1523
+ let key = PublicKey::from_hex(&hex).map_err(map_error)?;
1524
+ Ok(Self(key))
1525
+ }
1526
+ }
1527
+
1528
+ #[napi(js_name = "SecretKey")]
1529
+ pub struct JsSecretKey(SecretKey);
1530
+
1531
+ #[napi]
1532
+ impl JsSecretKey {
1533
+ /// Generate a random SecretKey
1534
+ #[napi(factory)]
1535
+ pub fn random() -> Self {
1536
+ Self(SecretKey::random())
1537
+ }
1538
+
1539
+ /// Returns the public key corresponding to this secret key.
1540
+ #[napi]
1541
+ pub fn public_key(&self) -> JsPublicKey {
1542
+ JsPublicKey(self.0.public_key())
1543
+ }
1544
+
1545
+ /// Converts the secret key to big endian bytes
1546
+ #[napi]
1547
+ pub fn to_bytes(&self) -> Uint8Array {
1548
+ Uint8Array::from(self.0.to_bytes())
1549
+ }
1550
+
1551
+ /// Deserialize from big endian bytes
1552
+ #[napi(factory)]
1553
+ pub fn from_bytes(bytes: Uint8Array) -> Result<Self> {
1554
+ let bytes = uint8_array_to_array(bytes, "bytes")?;
1555
+ let key = SecretKey::from_bytes(bytes).map_err(map_error)?;
1556
+ Ok(Self(key))
1557
+ }
1558
+
1559
+ /// Returns the hex string representation of the secret key.
1560
+ #[napi]
1561
+ pub fn to_hex(&self) -> String {
1562
+ self.0.to_hex()
1563
+ }
1564
+
1565
+ /// Creates a new SecretKey from a hex string.
1566
+ #[napi(factory)]
1567
+ pub fn from_hex(hex: String) -> Result<Self> {
1568
+ let key = SecretKey::from_hex(&hex).map_err(map_error)?;
1569
+ Ok(Self(key))
1570
+ }
1571
+ }
1572
+
1573
+ #[napi(js_name = "GraphEntry")]
1574
+ pub struct JsGraphEntry(GraphEntry);
1575
+
1576
+ #[napi]
1577
+ impl JsGraphEntry {
1578
+ /// Create a new graph entry, signing it with the provided secret key.
1579
+ #[napi(constructor)]
1580
+ pub fn new(
1581
+ owner: &JsSecretKey,
1582
+ parents: Vec<&JsPublicKey>,
1583
+ content: Uint8Array,
1584
+ descendants: Vec<(&JsPublicKey, Uint8Array)>,
1585
+ ) -> Result<Self> {
1586
+ let content: [u8; 32] = uint8_array_to_array(content, "content")?;
1587
+
1588
+ let parents = parents.iter().map(|p| p.0).collect();
1589
+
1590
+ let descendants = descendants
1591
+ .iter()
1592
+ .map(|(pk, content)| {
1593
+ let content_array: [u8; 32] = uint8_array_to_array(content.clone(), "content")?;
1594
+ Ok((pk.0, content_array))
1595
+ })
1596
+ .collect::<Result<Vec<(PublicKey, [u8; 32])>>>()?;
1597
+
1598
+ Ok(Self(GraphEntry::new(
1599
+ &owner.0,
1600
+ parents,
1601
+ content,
1602
+ descendants,
1603
+ )))
1604
+ }
1605
+
1606
+ /// Create a new graph entry with the signature already calculated.
1607
+ #[napi(factory)]
1608
+ pub fn new_with_signature(
1609
+ owner: &JsPublicKey,
1610
+ parents: Vec<&JsPublicKey>,
1611
+ content: Uint8Array,
1612
+ descendants: Vec<(&JsPublicKey, Uint8Array)>,
1613
+ signature: Uint8Array,
1614
+ ) -> Result<Self> {
1615
+ let content: [u8; 32] = uint8_array_to_array(content, "content")?;
1616
+
1617
+ let parents = parents.iter().map(|p| p.0).collect();
1618
+
1619
+ let descendants_result: Result<Vec<(PublicKey, [u8; 32])>> = descendants
1620
+ .iter()
1621
+ .map(|(pk, content)| {
1622
+ let content_array: [u8; 32] = uint8_array_to_array(content.clone(), "content")?;
1623
+ Ok((pk.0, content_array))
1624
+ })
1625
+ .collect();
1626
+
1627
+ let descendants = descendants_result?;
1628
+
1629
+ let signature = uint8_array_to_array(signature, "signature")?;
1630
+ let signature = Signature::from_bytes(signature).map_err(map_error)?;
1631
+
1632
+ Ok(Self(GraphEntry::new_with_signature(
1633
+ owner.0,
1634
+ parents,
1635
+ content,
1636
+ descendants,
1637
+ signature,
1638
+ )))
1639
+ }
1640
+
1641
+ /// Get the address of the graph entry
1642
+ #[napi]
1643
+ pub fn address(&self) -> JsGraphEntryAddress {
1644
+ JsGraphEntryAddress(self.0.address())
1645
+ }
1646
+
1647
+ /// Get the owner of the graph entry
1648
+ #[napi]
1649
+ pub fn owner(&self) -> JsPublicKey {
1650
+ JsPublicKey(self.0.owner)
1651
+ }
1652
+
1653
+ /// Get the parents of the graph entry
1654
+ #[napi]
1655
+ pub fn parents(&self) -> Vec<JsPublicKey> {
1656
+ self.0.parents.iter().map(|p| JsPublicKey(*p)).collect()
1657
+ }
1658
+
1659
+ /// Get the content of the graph entry
1660
+ #[napi]
1661
+ pub fn content(&self) -> Buffer {
1662
+ Buffer::from(self.0.content.to_vec())
1663
+ }
1664
+
1665
+ /// Get the descendants of the graph entry
1666
+ #[napi]
1667
+ pub fn descendants(&self) -> Vec<tuple_result::GraphEntryDescendant> {
1668
+ self.0
1669
+ .descendants
1670
+ .iter()
1671
+ .map(|(pk, data)| tuple_result::GraphEntryDescendant {
1672
+ public_key: *pk,
1673
+ content: *data,
1674
+ })
1675
+ .collect()
1676
+ }
1677
+
1678
+ /// Get the bytes that were signed for this graph entry
1679
+ #[napi]
1680
+ pub fn bytes_for_signature(&self) -> Buffer {
1681
+ Buffer::from(self.0.bytes_for_signature())
1682
+ }
1683
+
1684
+ /// Verifies if the graph entry has a valid signature
1685
+ #[napi]
1686
+ pub fn verify_signature(&self) -> bool {
1687
+ self.0.verify_signature()
1688
+ }
1689
+
1690
+ /// Size of the graph entry
1691
+ #[napi]
1692
+ pub fn size(&self) -> usize {
1693
+ self.0.size()
1694
+ }
1695
+
1696
+ #[napi(getter)]
1697
+ pub fn signature(&self) -> Uint8Array {
1698
+ Uint8Array::from(self.0.signature.to_bytes())
1699
+ }
1700
+
1701
+ /// Returns true if the graph entry is too big
1702
+ #[napi]
1703
+ pub fn is_too_big(&self) -> bool {
1704
+ self.0.is_too_big()
1705
+ }
1706
+ }
1707
+
1708
+ #[napi(js_name = "Pointer")]
1709
+ pub struct JsPointer(Pointer);
1710
+
1711
+ #[napi]
1712
+ impl JsPointer {
1713
+ /// Create a new pointer, signing it with the provided secret key.
1714
+ /// This pointer would be stored on the network at the provided key's public key.
1715
+ /// There can only be one pointer at a time at the same address (one per key).
1716
+ #[napi(constructor)]
1717
+ pub fn new(owner: &JsSecretKey, counter: u32, target: &JsPointerTarget) -> Self {
1718
+ JsPointer(Pointer::new(&owner.0, counter, target.0.clone()))
1719
+ }
1720
+
1721
+ /// Get the address of the pointer
1722
+ #[napi]
1723
+ pub fn address(&self) -> JsPointerAddress {
1724
+ JsPointerAddress(self.0.address())
1725
+ }
1726
+
1727
+ /// Get the owner of the pointer
1728
+ #[napi]
1729
+ pub fn owner(&self) -> JsPublicKey {
1730
+ JsPublicKey(*self.0.owner())
1731
+ }
1732
+
1733
+ /// Get the target of the pointer
1734
+ #[napi]
1735
+ pub fn target(&self) -> JsPointerTarget {
1736
+ JsPointerTarget(self.0.target().clone())
1737
+ }
1738
+
1739
+ /// Get the bytes that were signed for this pointer
1740
+ #[napi]
1741
+ pub fn bytes_for_signature(&self) -> Buffer {
1742
+ Buffer::from(self.0.bytes_for_signature())
1743
+ }
1744
+
1745
+ /// Get the xorname of the pointer target
1746
+ #[napi]
1747
+ pub fn xorname(&self) -> JsXorName {
1748
+ JsXorName(self.0.xorname())
1749
+ }
1750
+
1751
+ /// Get the counter of the pointer, the higher the counter, the more recent the pointer is
1752
+ /// Similarly to counter CRDTs only the latest version (highest counter) of the pointer is kept on the network
1753
+ #[napi]
1754
+ pub fn counter(&self) -> u32 {
1755
+ self.0.counter()
1756
+ }
1757
+
1758
+ /// Verifies if the pointer has a valid signature
1759
+ #[napi]
1760
+ pub fn verify_signature(&self) -> bool {
1761
+ self.0.verify_signature()
1762
+ }
1763
+
1764
+ /// Size of the pointer
1765
+ #[napi]
1766
+ pub fn size() -> usize {
1767
+ Pointer::size()
1768
+ }
1769
+ }
1770
+
1771
+ #[napi(js_name = "PointerTarget")]
1772
+ pub struct JsPointerTarget(PointerTarget);
1773
+
1774
+ #[napi]
1775
+ impl JsPointerTarget {
1776
+ /// Returns the xorname of the target
1777
+ #[napi]
1778
+ pub fn xorname(&self) -> JsXorName {
1779
+ JsXorName(self.0.xorname())
1780
+ }
1781
+
1782
+ /// Returns the hex string representation of the target
1783
+ #[napi]
1784
+ pub fn to_hex(&self) -> String {
1785
+ self.0.to_hex()
1786
+ }
1787
+
1788
+ /// Creates a new PointerTarget from a ChunkAddress
1789
+ #[napi(factory, js_name = "ChunkAddress")]
1790
+ pub fn from_chunk_address(addr: &JsChunkAddress) -> Self {
1791
+ Self(PointerTarget::ChunkAddress(addr.0))
1792
+ }
1793
+
1794
+ /// Creates a new PointerTarget from a GraphEntryAddress
1795
+ #[napi(factory, js_name = "GraphEntryAddress")]
1796
+ pub fn from_graph_entry_address(addr: &JsGraphEntryAddress) -> Self {
1797
+ Self(PointerTarget::GraphEntryAddress(addr.0))
1798
+ }
1799
+
1800
+ /// Creates a new PointerTarget from a PointerAddress
1801
+ #[napi(factory, js_name = "PointerAddress")]
1802
+ pub fn from_pointer_address(addr: &JsPointerAddress) -> Self {
1803
+ Self(PointerTarget::PointerAddress(addr.0))
1804
+ }
1805
+
1806
+ /// Creates a new PointerTarget from a ScratchpadAddress
1807
+ #[napi(factory, js_name = "ScratchpadAddress")]
1808
+ pub fn from_scratchpad_address(addr: &JsScratchpadAddress) -> Self {
1809
+ Self(PointerTarget::ScratchpadAddress(addr.0))
1810
+ }
1811
+ }
1812
+
1813
+ #[napi(js_name = "PointerAddress")]
1814
+ pub struct JsPointerAddress(PointerAddress);
1815
+
1816
+ #[napi]
1817
+ impl JsPointerAddress {
1818
+ /// Creates a new PointerAddress.
1819
+ #[napi(constructor)]
1820
+ pub fn new(owner: &JsPublicKey) -> Self {
1821
+ Self(PointerAddress::new(owner.0))
1822
+ }
1823
+
1824
+ /// Return the network name of the pointer.
1825
+ /// This is used to locate the pointer on the network.
1826
+ #[napi]
1827
+ pub fn xorname(&self) -> JsXorName {
1828
+ JsXorName(self.0.xorname())
1829
+ }
1830
+
1831
+ /// Return the owner.
1832
+ #[napi]
1833
+ pub fn owner(&self) -> JsPublicKey {
1834
+ JsPublicKey(*self.0.owner())
1835
+ }
1836
+
1837
+ /// Serialize this PointerAddress into a hex-encoded string.
1838
+ #[napi]
1839
+ pub fn to_hex(&self) -> String {
1840
+ self.0.to_hex()
1841
+ }
1842
+
1843
+ /// Parse a hex-encoded string into a PointerAddress.
1844
+ #[napi(factory)]
1845
+ pub fn from_hex(hex: String) -> Result<Self> {
1846
+ let addr = PointerAddress::from_hex(&hex).map_err(map_error)?;
1847
+ Ok(Self(addr))
1848
+ }
1849
+ }
1850
+
1851
+ #[napi(js_name = "Scratchpad")]
1852
+ pub struct JsScratchpad(Scratchpad);
1853
+
1854
+ #[napi]
1855
+ impl JsScratchpad {
1856
+ /// Create a new scratchpad, signing it with the provided secret key.
1857
+ #[napi(constructor)]
1858
+ pub fn new(
1859
+ owner: &JsSecretKey,
1860
+ data_encoding: BigInt, // `u64`
1861
+ data: Buffer,
1862
+ counter: BigInt, // `u64`
1863
+ ) -> Result<Self> {
1864
+ let data_encoding = big_int_to_u64(data_encoding, "data_encoding")?;
1865
+ let counter = big_int_to_u64(counter, "counter")?;
1866
+ let data = Bytes::copy_from_slice(&data);
1867
+
1868
+ Ok(Self(Scratchpad::new(
1869
+ &owner.0,
1870
+ data_encoding,
1871
+ &data,
1872
+ counter,
1873
+ )))
1874
+ }
1875
+
1876
+ /// Get the address of the scratchpad
1877
+ #[napi]
1878
+ pub fn address(&self) -> JsScratchpadAddress {
1879
+ JsScratchpadAddress(*self.0.address())
1880
+ }
1881
+
1882
+ /// Get the owner of the scratchpad
1883
+ #[napi]
1884
+ pub fn owner(&self) -> JsPublicKey {
1885
+ JsPublicKey(*self.0.owner())
1886
+ }
1887
+
1888
+ /// Get the data encoding (content type) of the scratchpad
1889
+ #[napi]
1890
+ pub fn data_encoding(&self) -> u64 {
1891
+ self.0.data_encoding()
1892
+ }
1893
+
1894
+ /// Decrypt the data of the scratchpad
1895
+ #[napi]
1896
+ pub fn decrypt_data(&self, key: &JsSecretKey) -> Result<Buffer> {
1897
+ let data = self.0.decrypt_data(&key.0).map_err(map_error)?;
1898
+ Ok(Buffer::from(data.to_vec()))
1899
+ }
1900
+
1901
+ /// Get the counter of the scratchpad
1902
+ #[napi]
1903
+ pub fn counter(&self) -> u64 {
1904
+ self.0.counter()
1905
+ }
1906
+
1907
+ /// Verify the signature of the scratchpad
1908
+ #[napi]
1909
+ pub fn verify_signature(&self) -> bool {
1910
+ self.0.verify_signature()
1911
+ }
1912
+ }
1913
+
1914
+ #[napi(js_name = "ScratchpadAddress")]
1915
+ pub struct JsScratchpadAddress(ScratchpadAddress);
1916
+
1917
+ #[napi]
1918
+ impl JsScratchpadAddress {
1919
+ /// Creates a new ScratchpadAddress.
1920
+ #[napi(constructor)]
1921
+ pub fn new(owner: &JsPublicKey) -> Self {
1922
+ Self(ScratchpadAddress::new(owner.0))
1923
+ }
1924
+
1925
+ /// Return the network name of the scratchpad.
1926
+ /// This is used to locate the scratchpad on the network.
1927
+ #[napi]
1928
+ pub fn xorname(&self) -> JsXorName {
1929
+ JsXorName(self.0.xorname())
1930
+ }
1931
+
1932
+ /// Return the owner.
1933
+ #[napi]
1934
+ pub fn owner(&self) -> JsPublicKey {
1935
+ JsPublicKey(*self.0.owner())
1936
+ }
1937
+
1938
+ /// Serialize this ScratchpadAddress into a hex-encoded string.
1939
+ #[napi]
1940
+ pub fn to_hex(&self) -> String {
1941
+ self.0.to_hex()
1942
+ }
1943
+
1944
+ /// Parse a hex-encoded string into a ScratchpadAddress.
1945
+ #[napi(factory)]
1946
+ pub fn from_hex(hex: String) -> Result<Self> {
1947
+ let addr = ScratchpadAddress::from_hex(&hex).map_err(map_error)?;
1948
+ Ok(Self(addr))
1949
+ }
1950
+ }
1951
+
1952
+ #[napi(js_name = "DataMapChunk")]
1953
+ pub struct JsDataMapChunk(DataMapChunk);
1954
+
1955
+ #[napi(js_name = "PrivateArchiveDataMap")]
1956
+ pub struct JsPrivateArchiveDataMap(PrivateArchiveDataMap);
1957
+
1958
+ #[napi]
1959
+ impl JsPrivateArchiveDataMap {
1960
+ /// Serialize this PrivateArchiveDataMap into a hex-encoded string.
1961
+ #[napi]
1962
+ pub fn to_hex(&self) -> String {
1963
+ self.0.to_hex()
1964
+ }
1965
+
1966
+ /// Parse a hex-encoded string into a PrivateArchiveDataMap.
1967
+ #[napi(factory)]
1968
+ pub fn from_hex(hex: String) -> Result<Self> {
1969
+ let data_map = PrivateArchiveDataMap::from_hex(&hex).map_err(map_error)?;
1970
+ Ok(Self(data_map))
1971
+ }
1972
+ }
1973
+
1974
+ #[napi(js_name = "PrivateArchive")]
1975
+ pub struct JsPrivateArchive(PrivateArchive);
1976
+
1977
+ #[napi]
1978
+ impl JsPrivateArchive {
1979
+ /// Create a new empty local archive
1980
+ #[napi(constructor)]
1981
+ #[allow(clippy::new_without_default, reason = "`Default` not useful")]
1982
+ pub fn new() -> Self {
1983
+ Self(PrivateArchive::new())
1984
+ }
1985
+
1986
+ /// Add a file to a local archive
1987
+ #[napi]
1988
+ pub fn add_file(&mut self, path: String, data_map: &JsDataMapChunk, metadata: &JsMetadata) {
1989
+ self.0
1990
+ .add_file(PathBuf::from(path), data_map.0.clone(), metadata.0.clone());
1991
+ }
1992
+
1993
+ /// Rename a file in an archive
1994
+ #[napi]
1995
+ pub fn rename_file(&mut self, old_path: String, new_path: String) -> Result<()> {
1996
+ self.0
1997
+ .rename_file(&PathBuf::from(old_path), &PathBuf::from(new_path))
1998
+ .map_err(map_error)
1999
+ }
2000
+
2001
+ /// List all files in the archive with their metadata
2002
+ #[napi]
2003
+ pub fn files(&self) -> Vec<tuple_result::ArchiveFile> {
2004
+ self.0
2005
+ .files()
2006
+ .into_iter()
2007
+ .map(|(path, meta)| tuple_result::ArchiveFile {
2008
+ path: path.to_string_lossy().to_string(),
2009
+ created: BigInt::from(meta.created),
2010
+ modified: BigInt::from(meta.modified),
2011
+ size: BigInt::from(meta.size),
2012
+ extra: meta.extra.clone(),
2013
+ })
2014
+ .collect()
2015
+ }
2016
+
2017
+ /// List all data maps of the files in the archive
2018
+ #[napi]
2019
+ pub fn data_maps(&self) -> Vec<JsDataMapChunk> {
2020
+ self.0.data_maps().into_iter().map(JsDataMapChunk).collect()
2021
+ }
2022
+
2023
+ /// Convert the archive to bytes
2024
+ #[napi]
2025
+ pub fn to_bytes(&self) -> Result<Buffer> {
2026
+ let bytes = self.0.to_bytes().map_err(|e| {
2027
+ napi::Error::new(
2028
+ Status::GenericFailure,
2029
+ format!("Failed to serialize archive: {e:?}"),
2030
+ )
2031
+ })?;
2032
+
2033
+ Ok(Buffer::from(bytes.to_vec()))
2034
+ }
2035
+
2036
+ /// Create an archive from bytes
2037
+ #[napi(factory)]
2038
+ pub fn from_bytes(data: Buffer) -> Result<Self> {
2039
+ let bytes = Bytes::from(data.as_ref().to_vec());
2040
+ let archive = PrivateArchive::from_bytes(bytes).map_err(|e| {
2041
+ napi::Error::new(
2042
+ Status::GenericFailure,
2043
+ format!("Failed to deserialize archive: {e:?}"),
2044
+ )
2045
+ })?;
2046
+
2047
+ Ok(Self(archive))
2048
+ }
2049
+
2050
+ /// Merge with another archive
2051
+ #[napi]
2052
+ pub fn merge(&mut self, other: &JsPrivateArchive) {
2053
+ self.0.merge(&other.0);
2054
+ }
2055
+ }
2056
+
2057
+ #[napi(js_name = "VaultSecretKey")]
2058
+ pub struct JsVaultSecretKey(VaultSecretKey);
2059
+
2060
+ #[napi(js_name = "UserData")]
2061
+ pub struct JsUserData(UserData);
2062
+
2063
+ #[napi(js_name = "VaultContentType")]
2064
+ pub struct JsVaultContentType(VaultContentType);
2065
+
2066
+ /// File metadata
2067
+ #[napi(js_name = "Metadata")]
2068
+ pub struct JsMetadata(Metadata);
2069
+
2070
+ #[napi]
2071
+ impl JsMetadata {
2072
+ /// Create a new metadata struct with the current time as uploaded, created and modified.
2073
+ #[napi(factory)]
2074
+ pub fn new_with_size(size: BigInt) -> Result<Self> {
2075
+ let size = big_int_to_u64(size, "size")?;
2076
+ Ok(Self(Metadata::new_with_size(size)))
2077
+ }
2078
+
2079
+ /// Create new metadata with all custom fields
2080
+ #[napi(factory)]
2081
+ pub fn with_custom_fields(
2082
+ created: BigInt,
2083
+ modified: BigInt,
2084
+ size: BigInt,
2085
+ extra: Option<String>,
2086
+ ) -> Result<Self> {
2087
+ let created = big_int_to_u64(created, "created")?;
2088
+ let modified = big_int_to_u64(modified, "modified")?;
2089
+ let size = big_int_to_u64(size, "size")?;
2090
+
2091
+ Ok(Self(autonomi::files::Metadata {
2092
+ created,
2093
+ modified,
2094
+ size,
2095
+ extra,
2096
+ }))
2097
+ }
2098
+
2099
+ /// Create a new empty metadata struct with zeros
2100
+ #[napi(factory)]
2101
+ pub fn empty() -> Self {
2102
+ Self(Metadata::empty())
2103
+ }
2104
+
2105
+ /// Get the creation timestamp
2106
+ #[napi(getter)]
2107
+ pub fn created(&self) -> u64 {
2108
+ self.0.created
2109
+ }
2110
+
2111
+ /// Get the modification timestamp
2112
+ #[napi(getter)]
2113
+ pub fn modified(&self) -> u64 {
2114
+ self.0.modified
2115
+ }
2116
+
2117
+ /// Get the file size
2118
+ #[napi(getter)]
2119
+ pub fn size(&self) -> u64 {
2120
+ self.0.size
2121
+ }
2122
+
2123
+ /// Get the extra metadata
2124
+ #[napi(getter)]
2125
+ pub fn extra(&self) -> Option<String> {
2126
+ self.0.extra.clone()
2127
+ }
2128
+ }
2129
+
2130
+ #[napi(js_name = "RegisterAddress")]
2131
+ pub struct JsRegisterAddress(RegisterAddress);
2132
+
2133
+ #[napi]
2134
+ impl JsRegisterAddress {
2135
+ /// Creates a new RegisterAddress.
2136
+ #[napi(constructor)]
2137
+ pub fn new(owner: &JsPublicKey) -> Self {
2138
+ Self(RegisterAddress::new(owner.0))
2139
+ }
2140
+
2141
+ /// Get the owner of the register
2142
+ #[napi]
2143
+ pub fn owner(&self) -> JsPublicKey {
2144
+ JsPublicKey(self.0.owner())
2145
+ }
2146
+
2147
+ /// Get the underlying graph root address
2148
+ #[napi]
2149
+ pub fn to_underlying_graph_root(&self) -> JsGraphEntryAddress {
2150
+ JsGraphEntryAddress(self.0.to_underlying_graph_root())
2151
+ }
2152
+
2153
+ /// Get the underlying head pointer address
2154
+ #[napi]
2155
+ pub fn to_underlying_head_pointer(&self) -> JsPointerAddress {
2156
+ JsPointerAddress(self.0.to_underlying_head_pointer())
2157
+ }
2158
+
2159
+ /// Serialize this RegisterAddress into a hex-encoded string.
2160
+ #[napi]
2161
+ pub fn to_hex(&self) -> String {
2162
+ self.0.to_hex()
2163
+ }
2164
+
2165
+ /// Parse a hex-encoded string into a RegisterAddress.
2166
+ #[napi(factory)]
2167
+ pub fn from_hex(hex: String) -> Result<Self> {
2168
+ let addr = RegisterAddress::from_hex(&hex).map_err(map_error)?;
2169
+ Ok(Self(addr))
2170
+ }
2171
+ }
2172
+
2173
+ #[napi(js_name = "RegisterHistory")]
2174
+ pub struct JsRegisterHistory(Mutex<RegisterHistory>);
2175
+
2176
+ #[napi]
2177
+ impl JsRegisterHistory {
2178
+ // Somehow without this stub, NAPI-RS fails to create this object with an error:
2179
+ // error: `Failed to get constructor of class`
2180
+ #[allow(clippy::new_without_default, reason = "`Default` not useful")]
2181
+ #[napi(constructor)]
2182
+ pub fn new() -> Self {
2183
+ unimplemented!()
2184
+ }
2185
+
2186
+ /// Fetch and go to the next register value from the history.
2187
+ ///
2188
+ /// Returns null when we reached the end.
2189
+ #[napi]
2190
+ pub async fn next(&self) -> Result<Option<Uint8Array>> {
2191
+ self.0
2192
+ .lock()
2193
+ .await
2194
+ .next()
2195
+ .await
2196
+ .map(|v| v.map(Uint8Array::from))
2197
+ .map_err(map_error)
2198
+ }
2199
+
2200
+ /// Get all the register values from the history, starting from the first to the latest entry
2201
+ #[napi]
2202
+ pub async fn collect(&self) -> Result<Vec<Uint8Array>> {
2203
+ let values = self.0.lock().await.collect().await.map_err(map_error)?;
2204
+ let values = values.into_iter().map(Uint8Array::from).collect();
2205
+ Ok(values)
2206
+ }
2207
+ }
2208
+
2209
+ #[napi(js_name = "PublicArchive")]
2210
+ pub struct JsPublicArchive(PublicArchive);
2211
+
2212
+ #[napi]
2213
+ impl JsPublicArchive {
2214
+ /// Create a new empty local archive
2215
+ #[napi(constructor)]
2216
+ #[allow(clippy::new_without_default, reason = "`Default` not useful")]
2217
+ pub fn new() -> Self {
2218
+ Self(PublicArchive::new())
2219
+ }
2220
+
2221
+ /// Add a file to a local archive
2222
+ #[napi]
2223
+ pub fn add_file(&mut self, path: String, data_addr: &JsDataAddress, metadata: &JsMetadata) {
2224
+ self.0
2225
+ .add_file(PathBuf::from(path), data_addr.0, metadata.0.clone());
2226
+ }
2227
+
2228
+ /// Rename a file in an archive
2229
+ #[napi]
2230
+ pub fn rename_file(&mut self, old_path: String, new_path: String) -> Result<()> {
2231
+ self.0
2232
+ .rename_file(&PathBuf::from(old_path), &PathBuf::from(new_path))
2233
+ .map_err(map_error)
2234
+ }
2235
+
2236
+ /// List all files in the archive with their metadata
2237
+ #[napi]
2238
+ pub fn files(&self) -> Vec<tuple_result::ArchiveFile> {
2239
+ self.0
2240
+ .files()
2241
+ .into_iter()
2242
+ .map(|(path, meta)| tuple_result::ArchiveFile {
2243
+ path: path.to_string_lossy().to_string(),
2244
+ created: BigInt::from(meta.created),
2245
+ modified: BigInt::from(meta.modified),
2246
+ size: BigInt::from(meta.size),
2247
+ extra: meta.extra.clone(),
2248
+ })
2249
+ .collect()
2250
+ }
2251
+
2252
+ /// List all data addresses of the files in the archive
2253
+ #[napi]
2254
+ pub fn addresses(&self) -> Vec<JsDataAddress> {
2255
+ self.0.addresses().into_iter().map(JsDataAddress).collect()
2256
+ }
2257
+
2258
+ /// Convert the archive to bytes
2259
+ #[napi]
2260
+ pub fn to_bytes(&self) -> Result<Buffer> {
2261
+ let bytes = self.0.to_bytes().map_err(|e| {
2262
+ napi::Error::new(
2263
+ Status::GenericFailure,
2264
+ format!("Failed to serialize archive: {e:?}"),
2265
+ )
2266
+ })?;
2267
+
2268
+ Ok(Buffer::from(bytes.to_vec()))
2269
+ }
2270
+
2271
+ /// Create an archive from bytes
2272
+ #[napi(factory)]
2273
+ pub fn from_bytes(data: Buffer) -> Result<Self> {
2274
+ let bytes = Bytes::from(data.as_ref().to_vec());
2275
+ let archive = PublicArchive::from_bytes(bytes).map_err(|e| {
2276
+ napi::Error::new(
2277
+ Status::GenericFailure,
2278
+ format!("Failed to deserialize archive: {e:?}"),
2279
+ )
2280
+ })?;
2281
+
2282
+ Ok(Self(archive))
2283
+ }
2284
+
2285
+ /// Merge with another archive
2286
+ #[napi]
2287
+ pub fn merge(&mut self, other: &JsPublicArchive) {
2288
+ self.0.merge(&other.0);
2289
+ }
2290
+ }