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