autonomi_nodejs/
lib.rs

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