prepare crate for publishing. with examples. more docs

pull/19/head
Niko PLP 8 months ago
parent fc4924ac87
commit bada481432
  1. 88
      Cargo.lock
  2. 10
      README.md
  3. 12
      nextgraph/Cargo.toml
  4. 32
      nextgraph/README.md
  5. 15
      nextgraph/examples/README.md
  6. 13
      nextgraph/examples/in_memory.md
  7. 133
      nextgraph/examples/in_memory.rs
  8. 13
      nextgraph/examples/persistent.md
  9. 28
      nextgraph/examples/persistent.rs
  10. BIN
      nextgraph/examples/wallet-security-image-demo.png
  11. 61
      nextgraph/src/lib.rs
  12. 178
      nextgraph/src/local_broker.rs
  13. 118
      ng-app/src-tauri/src/lib.rs
  14. 16
      ng-app/src/App.svelte
  15. 26
      ng-app/src/api.ts
  16. 2
      ng-app/src/routes/User.svelte
  17. 2
      ng-app/src/routes/WalletCreate.svelte
  18. 12
      ng-app/src/wallet_emojis.ts
  19. 4
      ng-broker/README.md
  20. 5
      ng-broker/src/server_ws.rs
  21. 4
      ng-client-ws/README.md
  22. 4
      ng-net/README.md
  23. 2
      ng-net/src/actor.rs
  24. 2
      ng-net/src/actors/mod.rs
  25. 2
      ng-net/src/broker.rs
  26. 6
      ng-net/src/connection.rs
  27. 7
      ng-net/src/lib.rs
  28. 2
      ng-net/src/server_storage.rs
  29. 1
      ng-net/src/tests/mod.rs
  30. 106
      ng-net/src/types.rs
  31. 3
      ng-repo/Cargo.toml
  32. 4
      ng-repo/README.md
  33. 2
      ng-repo/src/block.rs
  34. 2
      ng-repo/src/commit.rs
  35. 44
      ng-repo/src/errors.rs
  36. 2
      ng-repo/src/event.rs
  37. 2
      ng-repo/src/file.rs
  38. 2
      ng-repo/src/kcv_store.rs
  39. 2
      ng-repo/src/lib.rs
  40. 2
      ng-repo/src/object.rs
  41. 56
      ng-repo/src/os_info.rs
  42. 2
      ng-repo/src/repo.rs
  43. 2
      ng-repo/src/site.rs
  44. 2
      ng-repo/src/store.rs
  45. 79
      ng-repo/src/types.rs
  46. 4
      ng-sdk-js/README.md
  47. 4
      ng-sdk-js/app-react/README.md
  48. 4
      ng-sdk-js/app-web/README.md
  49. 16
      ng-sdk-js/js/node.js
  50. 109
      ng-sdk-js/src/lib.rs
  51. 4
      ng-stores-rocksdb/README.md
  52. 4
      ng-verifier/README.md
  53. 4
      ng-wallet/README.md
  54. 82
      ng-wallet/src/emojis.rs
  55. 100
      ng-wallet/src/lib.rs
  56. 90
      ng-wallet/src/types.rs
  57. 4
      ngcli/README.md
  58. 4
      ngd/README.md
  59. 2
      ngd/src/cli.rs
  60. 6
      ngd/src/main.rs

88
Cargo.lock generated

@ -1220,6 +1220,12 @@ dependencies = [
"rand 0.7.3",
]
[[package]]
name = "current_platform"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a74858bcfe44b22016cb49337d7b6f04618c58e5dbfdef61b06b8c434324a0bc"
[[package]]
name = "curve25519-dalek"
version = "3.2.0"
@ -3124,12 +3130,14 @@ dependencies = [
"ng-client-ws",
"ng-net",
"ng-repo",
"ng-stores-rocksdb",
"ng-verifier",
"ng-wallet",
"once_cell",
"serde",
"serde_bare",
"serde_bytes",
"serde_json",
"web-time",
"zeroize",
]
@ -3239,6 +3247,7 @@ dependencies = [
"base64-url",
"blake3",
"chacha20",
"current_platform",
"curve25519-dalek 3.2.0",
"debug_print",
"ed25519-dalek",
@ -3249,10 +3258,12 @@ dependencies = [
"hex",
"log",
"once_cell",
"os_info",
"rand 0.7.3",
"serde",
"serde_bare",
"serde_bytes",
"serde_json",
"slice_as_array",
"threshold_crypto",
"time 0.3.23",
@ -3688,6 +3699,17 @@ dependencies = [
"pin-project-lite",
]
[[package]]
name = "os_info"
version = "3.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ae99c7fa6dd38c7cafe1ec085e804f8f555a2f8659b0dbe03f1f9963a9b51092"
dependencies = [
"log",
"serde",
"windows-sys 0.52.0",
]
[[package]]
name = "overload"
version = "0.1.1"
@ -6312,6 +6334,15 @@ dependencies = [
"windows-targets 0.48.0",
]
[[package]]
name = "windows-sys"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
dependencies = [
"windows-targets 0.52.4",
]
[[package]]
name = "windows-targets"
version = "0.42.2"
@ -6342,6 +6373,21 @@ dependencies = [
"windows_x86_64_msvc 0.48.0",
]
[[package]]
name = "windows-targets"
version = "0.52.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b"
dependencies = [
"windows_aarch64_gnullvm 0.52.4",
"windows_aarch64_msvc 0.52.4",
"windows_i686_gnu 0.52.4",
"windows_i686_msvc 0.52.4",
"windows_x86_64_gnu 0.52.4",
"windows_x86_64_gnullvm 0.52.4",
"windows_x86_64_msvc 0.52.4",
]
[[package]]
name = "windows-tokens"
version = "0.48.0"
@ -6360,6 +6406,12 @@ version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc"
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.52.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9"
[[package]]
name = "windows_aarch64_msvc"
version = "0.42.2"
@ -6372,6 +6424,12 @@ version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3"
[[package]]
name = "windows_aarch64_msvc"
version = "0.52.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675"
[[package]]
name = "windows_i686_gnu"
version = "0.42.2"
@ -6384,6 +6442,12 @@ version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241"
[[package]]
name = "windows_i686_gnu"
version = "0.52.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3"
[[package]]
name = "windows_i686_msvc"
version = "0.42.2"
@ -6396,6 +6460,12 @@ version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00"
[[package]]
name = "windows_i686_msvc"
version = "0.52.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02"
[[package]]
name = "windows_x86_64_gnu"
version = "0.42.2"
@ -6408,6 +6478,12 @@ version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1"
[[package]]
name = "windows_x86_64_gnu"
version = "0.52.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.42.2"
@ -6420,6 +6496,12 @@ version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.52.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177"
[[package]]
name = "windows_x86_64_msvc"
version = "0.42.2"
@ -6432,6 +6514,12 @@ version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a"
[[package]]
name = "windows_x86_64_msvc"
version = "0.52.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8"
[[package]]
name = "winnow"
version = "0.4.7"

@ -8,6 +8,8 @@
[![Apache 2.0 Licensed][license-image]][license-link]
[![MIT Licensed][license-image2]][license-link2]
[![project chat](https://img.shields.io/badge/zulip-join_chat-brightgreen.svg)](https://forum.nextgraph.org)
![Crates.io Version](https://img.shields.io/crates/v/nextgraph)
![docs.rs](https://img.shields.io/docsrs/nextgraph)
Rust implementation of NextGraph
@ -15,9 +17,9 @@ This repository is in active development at [https://git.nextgraph.org/NextGraph
## NextGraph
> NextGraph brings about the convergence between P2P and Semantic Web technologies, towards a decentralized, secure and privacy-preserving cloud, based on CRDTs.
> NextGraph brings about the convergence of P2P and Semantic Web technologies, towards a decentralized, secure and privacy-preserving cloud, based on CRDTs.
>
> This open source ecosystem provides solutions for end-users and software developers alike, wishing to use or create **decentralized** apps featuring: **live collaboration** on rich-text documents, peer to peer communication with **end-to-end encryption**, offline-first, **local-first**, portable and interoperable data, total ownership of data and software, security and privacy. Centered on repositories containing **semantic data** (RDF), **rich text**, and structured data formats like **JSON**, synced between peers belonging to permissioned groups of users, it offers strong eventual consistency, thanks to the use of **CRDTs**. Documents can be linked together, signed, shared securely, queried using the **SPARQL** language and organized into sites and containers.
> This open source ecosystem provides solutions for end-users (a platform) and software developers (a framework), wishing to use or create **decentralized** apps featuring: **live collaboration** on rich-text documents, peer to peer communication with **end-to-end encryption**, offline-first, **local-first**, portable and interoperable data, total ownership of data and software, security and privacy. Centered on repositories containing **semantic data** (RDF), **rich text**, and structured data formats like **JSON**, synced between peers belonging to permissioned groups of users, it offers strong eventual consistency, thanks to the use of **CRDTs**. Documents can be linked together, signed, shared securely, queried using the **SPARQL** language and organized into sites and containers.
>
> More info here [https://nextgraph.org](https://nextgraph.org)
@ -65,11 +67,11 @@ The crates are organized as follow :
- [ngd](ngd/README.md) : binary executable of the daemon (that can run a broker, verifier and/or Rust services)
- ng-repo : Repositories common library
- ng-net : Network common library
- ng-verifier : Verifier library, that exposes the document API to the app
- ng-wallet : keeps the secret keys of all identities of the user in a safe wallet
- ng-broker : Core and Server Broker library
- ng-client-ws : Websocket client library
- ng-verifier : Verifier library, that exposes the document API to the app
- ng-stores-rocksdb : RocksDB backed stores. see also dependency [repo here](https://git.nextgraph.org/NextGraph/rust-rocksdb)
- ng-wallet : keeps the secret keys of all identities of the user in a safe wallet
- [ng-sdk-js](ng-sdk-js/README.md) : contains the JS SDK, with example apps: web app, react app, or node service.
- [ng-app](ng-app/README.md) : all the native apps, based on Tauri, and the web app.
- ngone : server for nextgraph.one. helps user bootstrap into the right app. Not useful to you. Published here for transparency

@ -21,6 +21,7 @@ ng-net = { path = "../ng-net", version = "0.1.0" }
ng-wallet = { path = "../ng-wallet", version = "0.1.0" }
ng-client-ws = { path = "../ng-client-ws", version = "0.1.0" }
ng-verifier = { path = "../ng-verifier", version = "0.1.0" }
ng-stores-rocksdb = { path = "../ng-stores-rocksdb", version = "0.1.0" }
async-once-cell = "0.5.3"
once_cell = "1.17.1"
serde = { version = "1.0", features = ["derive"] }
@ -28,5 +29,14 @@ serde_bare = "0.5.0"
serde_bytes = "0.11.7"
base64-url = "2.0.0"
web-time = "0.2.0"
async-std = { version = "1.12.0", features = ["attributes","unstable"] }
async-std = { version = "1.12.0", features = [ "attributes", "unstable" ] }
zeroize = { version = "1.6.0", features = ["zeroize_derive"] }
serde_json = "1.0"
[[example]]
name = "in_memory"
required-features = []
[[example]]
name = "persistent"
required-features = []

@ -7,29 +7,51 @@
![MSRV][rustc-image]
[![Apache 2.0 Licensed][license-image]][license-link]
[![MIT Licensed][license-image2]][license-link2]
![Crates.io Version](https://img.shields.io/crates/v/nextgraph)
![docs.rs](https://img.shields.io/docsrs/nextgraph)
Rust client library of NextGraph
Rust client library of NextGraph framework
This repository is in active development at [https://git.nextgraph.org/NextGraph/nextgraph-rs](https://git.nextgraph.org/NextGraph/nextgraph-rs), a Gitea instance. For bug reports, issues, merge requests, and in order to join the dev team, please visit the link above and create an account (you can do so with a github account). The [github repo](https://github.com/nextgraph-org/nextgraph-rs) is just a read-only mirror that does not accept issues.
This library is in active development at [https://git.nextgraph.org/NextGraph/nextgraph-rs](https://git.nextgraph.org/NextGraph/nextgraph-rs), a Gitea instance. For bug reports, issues, merge requests, and in order to join the dev team, please visit the link above and create an account (you can do so with a github account). The [github repo](https://github.com/nextgraph-org/nextgraph-rs) is just a read-only mirror that does not accept issues.
## NextGraph
> NextGraph brings about the convergence between P2P and Semantic Web technologies, towards a decentralized, secure and privacy-preserving cloud, based on CRDTs.
> NextGraph brings about the convergence of P2P and Semantic Web technologies, towards a decentralized, secure and privacy-preserving cloud, based on CRDTs.
>
> This open source ecosystem provides solutions for end-users and software developers alike, wishing to use or create **decentralized** apps featuring: **live collaboration** on rich-text documents, peer to peer communication with **end-to-end encryption**, offline-first, **local-first**, portable and interoperable data, total ownership of data and software, security and privacy. Centered on repositories containing **semantic data** (RDF), **rich text**, and structured data formats like **JSON**, synced between peers belonging to permissioned groups of users, it offers strong eventual consistency, thanks to the use of **CRDTs**. Documents can be linked together, signed, shared securely, queried using the **SPARQL** language and organized into sites and containers.
> This open source ecosystem provides solutions for end-users (a platform) and software developers (a framework), wishing to use or create **decentralized** apps featuring: **live collaboration** on rich-text documents, peer to peer communication with **end-to-end encryption**, offline-first, **local-first**, portable and interoperable data, total ownership of data and software, security and privacy. Centered on repositories containing **semantic data** (RDF), **rich text**, and structured data formats like **JSON**, synced between peers belonging to permissioned groups of users, it offers strong eventual consistency, thanks to the use of **CRDTs**. Documents can be linked together, signed, shared securely, queried using the **SPARQL** language and organized into sites and containers.
>
> More info here [https://nextgraph.org](https://nextgraph.org)
## Support
This crate has official documentation at [docs.rs](https://docs.rs/nextgraph/0.1.0/nextgraph/)
Documentation can be found here [https://docs.nextgraph.org](https://docs.nextgraph.org)
And our community forum where you can ask questions is here [https://forum.nextgraph.org](https://forum.nextgraph.org)
## How to use the library
## Status
NextGraph is not ready yet. You can subscribe to [our newsletter](https://list.nextgraph.org/subscription/form) to get updates, and support us with a [donation](https://nextgraph.org/donate/).
## Dependencies
Nextgraph library is dependent on [async-std](https://async.rs/). You must include it in your `Cargo.toml`.
A tokio-based version (as a feature) might be available in the future.
```toml
[dependencies]
nextgraph = "0.1.0"
async-std = "1.12.0"
```
## Examples
You can find some examples on how to use the library:
- [in_memory](examples/in_memory)
- [persistent](examples/persistent)
## License
Licensed under either of

@ -0,0 +1,15 @@
# Examples
Some examples of using `nextgraph` client library
run them with:
```
cargo run -p nextgraph --example in_memory
cargo run -p nextgraph --example persistent
```
See the code:
- [in_memory](in_memory)
- [persistent](persistent)

@ -0,0 +1,13 @@
# in-memory LocalBroker
Example of LocalBroker configured with in-memory (no persistence).
run with:
```
cargo run -p nextgraph -r --example in_memory
```
we assume that you run this command from the root of the git repo (nextgraph-rs)
the `-r` for release version is important, without it, the creation and opening of the wallet will take ages.

@ -0,0 +1,133 @@
// Copyright (c) 2022-2024 Niko Bonnieure, Par le Peuple, NextGraph.org developers
// All rights reserved.
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE2 or http://www.apache.org/licenses/LICENSE-2.0>
// or the MIT license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.
use nextgraph::local_broker::{
init_local_broker, session_start, session_stop, user_connect, user_disconnect, wallet_close,
wallet_create_v0, wallet_get_file, wallet_import, wallet_open_with_pazzle_words,
wallet_read_file, wallet_was_opened, LocalBrokerConfig, SessionConfig,
};
use nextgraph::net::types::BootstrapContentV0;
use nextgraph::repo::errors::NgError;
use nextgraph::repo::types::PubKey;
use nextgraph::wallet::types::CreateWalletV0;
use nextgraph::wallet::{display_mnemonic, emojis::display_pazzle};
use std::env::current_dir;
use std::fs::read;
#[async_std::main]
async fn main() -> std::io::Result<()> {
// initialize the local_broker with in-memory config.
// all sessions will be lost when the program exits
init_local_broker(Box::new(|| LocalBrokerConfig::InMemory)).await;
// load some image that will be used as security_img
// we assume here for the sake of this example,
// that the current directory contains this demo image file
let mut current_path = current_dir()?;
current_path.push("nextgraph");
current_path.push("examples");
current_path.push("wallet-security-image-demo.png");
let security_img = read(current_path)?;
// the peer_id should come from somewhere else.
// this is just given for the sake of an example
#[allow(deprecated)]
let peer_id_of_server_broker = PubKey::nil();
// Create your wallet
// this will take some time !
println!("Creating the wallet. this will take some time...");
let wallet_result = wallet_create_v0(CreateWalletV0 {
security_img,
security_txt: "know yourself".to_string(),
pin: [1, 2, 1, 2],
pazzle_length: 9,
send_bootstrap: false,
send_wallet: false,
result_with_wallet_file: true,
local_save: false,
// we default to localhost:14400. this is just for the sake of an example
core_bootstrap: BootstrapContentV0::new_localhost(peer_id_of_server_broker),
core_registration: None,
additional_bootstrap: None,
})
.await?;
let pazzle = display_pazzle(&wallet_result.pazzle);
let mut pazzle_words = vec![];
println!("Your pazzle is: {:?}", wallet_result.pazzle);
for emoji in pazzle {
println!(" {}:\t{}", emoji.0, emoji.1);
pazzle_words.push(emoji.1.to_string());
}
println!("Your mnemonic is:");
display_mnemonic(&wallet_result.mnemonic)
.iter()
.for_each(|word| print!("{} ", word.as_str()));
println!("");
// at this point, the wallet is kept in the internal memory of the LocalBroker, but it hasn't been saved to disk
// and it hasn't been opened yet, so it is not usable right away.
// now let's open the wallet, by providing the pazzle and PIN code
let opened_wallet =
wallet_open_with_pazzle_words(&wallet_result.wallet, &pazzle_words, [1, 2, 1, 2])?;
let user_id = opened_wallet.personal_identity();
// once the wallet is opened, we notify the LocalBroker that we have opened it.
let _client = wallet_was_opened(opened_wallet).await?;
// if you need the Wallet File again (if you didn't select `result_with_wallet_file` by example), you can retrieve it with:
let wallet_file = wallet_get_file(&wallet_result.wallet_name).await?;
// if you did ask for `result_with_wallet_file`, as we did above, then the 2 vectors should be identical
assert_eq!(wallet_file, wallet_result.wallet_file);
{
// this part should happen on another device. just given here as an example
// on another device, you could use the Wallet File and import it there so it could be used for login.
// first you would read and decode the Wallet File
// this fails here because we already added this wallet in the LocalBroker (when we created it). But on another device, it would work.
let wallet = wallet_read_file(wallet_file).await;
assert_eq!(wallet.unwrap_err(), NgError::WalletAlreadyAdded);
// on another device, we would then open the wallet (here we take the Wallet as we received it from wallet_create_v0, but in real case you would use `wallet`)
let opened_wallet2 =
wallet_open_with_pazzle_words(&wallet_result.wallet, &pazzle_words, [1, 2, 1, 2])?;
// once it has been opened, the Wallet can be imported into the LocalBroker
// if you try to import the same wallet in a LocalBroker where it is already opened, it will fail. So here it fails. But on another device, it would work.
let client_fail = wallet_import(wallet_result.wallet.clone(), opened_wallet2, true).await;
assert_eq!(client_fail.unwrap_err(), NgError::WalletAlreadyAdded);
}
// anyway, now that the wallet is opened, let's start a session.
// we pass the user_id and the wallet_name
let _session = session_start(SessionConfig::new(&user_id, &wallet_result.wallet_name)).await?;
// if the user has internet access, they can now decide to connect to its Server Broker, in order to sync data
let status = user_connect(&user_id).await?;
// The connection cannot succeed because we miss-configured the core_bootstrap of the wallet. it's Peer ID is invalid.
assert_eq!(status[0].3.as_ref().unwrap(), "NoiseHandshakeFailed");
// Then we should disconnect
user_disconnect(&user_id).await?;
// stop the session
session_stop(&user_id).await?;
// closes the wallet
wallet_close(&wallet_result.wallet_name).await?;
Ok(())
}

@ -0,0 +1,13 @@
# persistent LocalBroker
Example of LocalBroker configured with persistence to disk
run with:
```
cargo run -p nextgraph -r --example persistent
```
we assume that you run this command from the root of the git repo (nextgraph-rs).
the `-r` for release version is important, without it, the creation and opening of the wallet will take ages.

@ -0,0 +1,28 @@
// Copyright (c) 2022-2024 Niko Bonnieure, Par le Peuple, NextGraph.org developers
// All rights reserved.
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE2 or http://www.apache.org/licenses/LICENSE-2.0>
// or the MIT license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.
use nextgraph::local_broker::{init_local_broker, LocalBrokerConfig};
use std::env::current_dir;
use std::fs::create_dir_all;
#[async_std::main]
async fn main() -> std::io::Result<()> {
// get the current working directory
let mut current_path = current_dir()?;
current_path.push("ng");
create_dir_all(current_path.clone())?;
// initialize the local_broker with config to save to disk in a folder called `ng` in the current directory
init_local_broker(Box::new(move || {
LocalBrokerConfig::BasePath(current_path.clone())
}))
.await;
Ok(())
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

@ -1 +1,62 @@
#![doc(html_logo_url = "https://file.nextgraph.org/download/1fd175bb6d7d832156bd5ad4abcdee7e")]
#![doc(issue_tracker_base_url = "https://git.nextgraph.org/NextGraph/nextgraph-rs/issues")]
#![doc(html_favicon_url = "https://nextgraph.org/favicon.svg")]
//! # NextGraph framework client library
//!
//! NextGraph brings about the convergence of P2P and Semantic Web technologies, towards a decentralized, secure and privacy-preserving cloud, based on CRDTs.
//!
//! This open source ecosystem provides solutions for end-users (a platform) and software developers (a framework), wishing to use or create **decentralized** apps featuring: **live collaboration** on rich-text documents, peer to peer communication with **end-to-end encryption**, offline-first, **local-first**, portable and interoperable data, total ownership of data and software, security and privacy. Centered on repositories containing **semantic data** (RDF), **rich text**, and structured data formats like **JSON**, synced between peers belonging to permissioned groups of users, it offers strong eventual consistency, thanks to the use of **CRDTs**. Documents can be linked together, signed, shared securely, queried using the **SPARQL** language and organized into sites and containers.
//!
//! More info here [https://nextgraph.org](https://nextgraph.org). Documentation available here [https://docs.nextgraph.org](https://docs.nextgraph.org).
//!
//! ## LocalBroker, the entrypoint to NextGraph network
//!
//! `local_broker` contains the API for controlling the Local Broker, which is a reduced instance of the network Broker.
//! This is your entrypoint to NextGraph network.
//! It runs embedded in your client program, and once configured (by opening a Session), it can keep for you (on disk or in memory):
//! - the blocks of the repos,
//! - the connection(s) to your Server Broker
//! - the events that you send to the Overlay, if there is no connectivity (Outbox)
//! - A reference to the verifier (optional)
//!
//! In addition, the API for creating and managing your wallet is provided here.
//!
//! The same API is also made available in Javascript for the browser (and is used by our webapp), nodejs, in the CLI, and for all the Tauri-based Apps.
//!
//! The library requires `async-std` minimal version 1.12.0
//!
//! See [examples](https://git.nextgraph.org/NextGraph/nextgraph-rs/src/branch/master/nextgraph/examples) for a quick start.
//!
//! ## In-memory
//!
//! With this config, no data will be persisted to disk.
//!
//! ```
//! use nextgraph::local_broker::{init_local_broker, LocalBrokerConfig};
//!
//! #[async_std::main]
//! async fn main() -> std::io::Result<()> {
//! // initialize the local_broker with in-memory config.
//! // all sessions will be lost when the program exits
//! init_local_broker(Box::new(|| LocalBrokerConfig::InMemory)).await;
//! Ok(())
//! }
//! ```
pub mod local_broker;
pub mod repo {
pub use ng_repo::*;
}
pub mod net {
pub use ng_net::*;
}
pub mod verifier {
pub use ng_verifier::*;
}
pub mod wallet {
pub use ng_wallet::*;
}

@ -11,9 +11,12 @@ use async_once_cell::OnceCell;
use async_std::sync::{Arc, RwLock};
use core::fmt;
use ng_net::connection::{ClientConfig, IConnect, StartConfig};
use ng_net::types::ClientInfo;
use ng_net::types::{ClientInfo, ClientType};
use ng_repo::os_info::get_os_info;
use ng_wallet::emojis::encode_pazzle;
use once_cell::sync::Lazy;
use serde_bare::to_vec;
use serde_json::json;
use std::collections::HashMap;
use std::fs::{read, write, File, OpenOptions};
use std::path::PathBuf;
@ -34,6 +37,7 @@ type JsStorageReadFn = dyn Fn(String) -> Result<String, NgError> + 'static + Syn
type JsStorageWriteFn = dyn Fn(String, String) -> Result<(), NgError> + 'static + Sync + Send;
type JsCallback = dyn Fn() + 'static + Sync + Send;
#[doc(hidden)]
pub struct JsStorageConfig {
pub local_read: Box<JsStorageReadFn>,
pub local_write: Box<JsStorageWriteFn>,
@ -47,10 +51,15 @@ impl fmt::Debug for JsStorageConfig {
}
}
/// Configuration for the LocalBroker. must be returned by a function or closure passed to [init_local_broker]
#[derive(Debug)]
pub enum LocalBrokerConfig {
/// Local broker will not save any wallet, session or user's data
InMemory,
/// Local broker will save all wallets, sessions and user's data on disk, in the provided `Path`
BasePath(PathBuf),
#[doc(hidden)]
/// used internally for the JS SDK
JsStorage(JsStorageConfig),
}
@ -61,12 +70,14 @@ impl LocalBrokerConfig {
_ => false,
}
}
#[doc(hidden)]
pub fn is_js(&self) -> bool {
match self {
Self::JsStorage(_) => true,
_ => false,
}
}
#[doc(hidden)]
pub fn js_config(&self) -> Option<&JsStorageConfig> {
match self {
Self::JsStorage(c) => Some(c),
@ -78,14 +89,14 @@ impl LocalBrokerConfig {
//type LastSeqFn = fn(PubKey, u16) -> Result<u64, NgError>;
pub type LastSeqFn = dyn Fn(PubKey, u16) -> Result<u64, NgError> + 'static + Sync + Send;
/// peer_id: PubKey, seq_num:u64, event_ser: vec<u8>,
// peer_id: PubKey, seq_num:u64, event_ser: vec<u8>,
pub type OutboxWriteFn =
dyn Fn(PubKey, u64, Vec<u8>) -> Result<(), NgError> + 'static + Sync + Send;
/// peer_id: PubKey,
// peer_id: PubKey,
pub type OutboxReadFn = dyn Fn(PubKey) -> Result<Vec<Vec<u8>>, NgError> + 'static + Sync + Send;
/// Session Config to initiate a session at a local broker V0
/// used to initiate a session at a local broker V0
pub struct SessionConfigV0 {
pub user_id: UserId,
pub wallet_name: String,
@ -94,7 +105,7 @@ pub struct SessionConfigV0 {
// pub outbox_read_function: Box<OutboxReadFn>,
}
/// Session Config to initiate a session at a local broker
/// used to initiate a session at a local broker
pub enum SessionConfig {
V0(SessionConfigV0),
}
@ -118,6 +129,14 @@ impl SessionConfig {
Self::V0(v0) => v0.wallet_name.clone(),
}
}
/// Creates a new SessionConfig with a UserId and a wallet name
/// that should be passed to [session_start]
pub fn new(user_id: &UserId, wallet_name: &String) -> Self {
SessionConfig::V0(SessionConfigV0 {
user_id: user_id.clone(),
wallet_name: wallet_name.clone(),
})
}
}
impl fmt::Debug for SessionConfigV0 {
@ -164,9 +183,7 @@ impl LocalBroker {
}
}
//static LOCAL_BROKER: OnceCell<Result<(), NgError>> = OnceCell::new();
static LOCAL_BROKER: OnceCell<Result<Arc<RwLock<LocalBroker>>, NgError>> = OnceCell::new(); //Lazy::new(|| Arc::new(RwLock::new(Broker::new())));
static LOCAL_BROKER: OnceCell<Result<Arc<RwLock<LocalBroker>>, NgError>> = OnceCell::new();
pub type ConfigInitFn = dyn Fn() -> LocalBrokerConfig + 'static + Sync + Send;
@ -213,7 +230,7 @@ async fn init_(config: LocalBrokerConfig) -> Result<Arc<RwLock<LocalBroker>>, Ng
Ok(Arc::new(RwLock::new(local_broker)))
}
//-> &'static Result<Arc<RwLock<LocalBroker>>, NgError>
#[doc(hidden)]
pub async fn init_local_broker_with_lazy(config_fn: &Lazy<Box<ConfigInitFn>>) {
LOCAL_BROKER
.get_or_init(async {
@ -223,6 +240,11 @@ pub async fn init_local_broker_with_lazy(config_fn: &Lazy<Box<ConfigInitFn>>) {
.await;
}
/// Initialize the configuration of your local broker
///
/// , by passing in a function (or closure) that returns a `LocalBrokerConfig`.
/// You must call `init_local_broker` at least once before you can start to use the broker.
/// After the first call, all subsequent calls will have no effect.
pub async fn init_local_broker(config_fn: Box<ConfigInitFn>) {
LOCAL_BROKER
.get_or_init(async {
@ -232,7 +254,8 @@ pub async fn init_local_broker(config_fn: Box<ConfigInitFn>) {
.await;
}
pub async fn get_all_wallets() -> Result<HashMap<String, LocalWalletStorageV0>, NgError> {
/// Retrieves a HashMap of wallets known to the LocalBroker. The name of the Wallet is used as key
pub async fn wallets_get_all() -> Result<HashMap<String, LocalWalletStorageV0>, NgError> {
let broker = match LOCAL_BROKER.get() {
Some(Err(e)) => {
log_err!("LocalBrokerNotInitialized: {}", e);
@ -247,14 +270,32 @@ pub async fn get_all_wallets() -> Result<HashMap<String, LocalWalletStorageV0>,
Ok(broker.wallets.clone())
}
/// Creates a new Wallet for the user. Each user should create only one Wallet.
///
/// See [CreateWalletV0] for a list of parameters.
///
/// Wallets are transferable to to other devices (see [wallet_get_file] and [wallet_import])
pub async fn wallet_create_v0(params: CreateWalletV0) -> Result<CreateWalletResultV0, NgError> {
{
// entering sub-block to release the lock asap
let broker = match LOCAL_BROKER.get() {
None | Some(Err(_)) => return Err(NgError::LocalBrokerNotInitialized),
Some(Ok(broker)) => broker.read().await,
};
if params.local_save && broker.config.is_in_memory() {
return Err(NgError::CannotSaveWhenInMemoryConfig);
}
}
let res = create_wallet_v0(params)?;
let lws: LocalWalletStorageV0 = (&res).into();
wallet_add(lws).await?;
Ok(res)
}
pub async fn reload_wallets() -> Result<(), NgError> {
#[doc(hidden)]
/// Only used by JS SDK when the localStorage changes and brings out of sync for the Rust side copy of the wallets
pub async fn wallets_reload() -> Result<(), NgError> {
let mut broker = match LOCAL_BROKER.get() {
None | Some(Err(_)) => return Err(NgError::LocalBrokerNotInitialized),
Some(Ok(broker)) => broker.write().await,
@ -274,6 +315,10 @@ pub async fn reload_wallets() -> Result<(), NgError> {
Ok(())
}
#[doc(hidden)]
/// This should not be used by programmers. Only here because the JS SDK needs it.
///
/// It will throw and error if you use it.
pub async fn wallet_add(lws: LocalWalletStorageV0) -> Result<(), NgError> {
let mut broker = match LOCAL_BROKER.get() {
None | Some(Err(_)) => return Err(NgError::LocalBrokerNotInitialized),
@ -319,6 +364,11 @@ pub async fn wallet_add(lws: LocalWalletStorageV0) -> Result<(), NgError> {
Ok(())
}
/// Reads a binary Wallet File and decodes it to a Wallet object.
///
/// This object can be used to import the wallet into a new Device
/// with the help of the function [wallet_open_with_pazzle_words]
/// followed by [wallet_import]
pub async fn wallet_read_file(file: Vec<u8>) -> Result<Wallet, NgError> {
let ngf: NgFile = file.try_into()?;
if let NgFile::V0(NgFileV0::Wallet(wallet)) = ngf {
@ -338,7 +388,8 @@ pub async fn wallet_read_file(file: Vec<u8>) -> Result<Wallet, NgError> {
}
}
pub async fn wallet_download_file(wallet_name: &String) -> Result<Vec<u8>, NgError> {
/// Retrieves the binary content of a Wallet File for the Wallet identified by its name
pub async fn wallet_get_file(wallet_name: &String) -> Result<Vec<u8>, NgError> {
let broker = match LOCAL_BROKER.get() {
None | Some(Err(_)) => return Err(NgError::LocalBrokerNotInitialized),
Some(Ok(broker)) => broker.read().await,
@ -350,8 +401,11 @@ pub async fn wallet_download_file(wallet_name: &String) -> Result<Vec<u8>, NgErr
}
}
#[doc(hidden)]
/// This is a bit hard to use as the pazzle words are encoded in unsigned bytes.
/// prefer the function wallet_open_with_pazzle_words
pub fn wallet_open_with_pazzle(
wallet: Wallet,
wallet: &Wallet,
pazzle: Vec<u8>,
pin: [u8; 4],
) -> Result<SensitiveWallet, NgError> {
@ -360,6 +414,25 @@ pub fn wallet_open_with_pazzle(
Ok(opened_wallet)
}
/// Opens a wallet by providing an ordered list of words, and the pin.
///
/// If you are opening a wallet that is already known to the LocalBroker, you must then call [wallet_was_opened].
/// Otherwise, if you are importing, then you must call [wallet_import].
///
/// For a list of words, see [list_all_words](crate::wallet::emojis::list_all_words)
pub fn wallet_open_with_pazzle_words(
wallet: &Wallet,
pazzle_words: &Vec<String>,
pin: [u8; 4],
) -> Result<SensitiveWallet, NgError> {
wallet_open_with_pazzle(wallet, encode_pazzle(pazzle_words)?, pin)
}
/// Imports a wallet into the LocalBroker so the user can then access its content.
///
/// the wallet should have been previous opened with [wallet_open_with_pazzle_words].
/// Once import is done, the wallet is already marked as opened, and the user can start a new session right away.
/// There is no need to call wallet_was_opened.
pub async fn wallet_import(
encrypted_wallet: Wallet,
mut opened_wallet: SensitiveWallet,
@ -374,7 +447,7 @@ pub async fn wallet_import(
let wallet_name = encrypted_wallet.name();
if broker.wallets.get(&wallet_name).is_some() {
return Err(NgError::WalletAlreadyOpened);
return Err(NgError::WalletAlreadyAdded);
}
}
@ -385,6 +458,7 @@ pub async fn wallet_import(
wallet_was_opened(opened_wallet).await
}
/// Must be called after [wallet_open_with_pazzle_words] if you are not importing
pub async fn wallet_was_opened(mut wallet: SensitiveWallet) -> Result<ClientV0, NgError> {
let mut broker = match LOCAL_BROKER.get() {
None | Some(Err(_)) => return Err(NgError::LocalBrokerNotInitialized),
@ -411,6 +485,11 @@ pub async fn wallet_was_opened(mut wallet: SensitiveWallet) -> Result<ClientV0,
Ok(client)
}
/// Starts a session with the LocalBroker. The type of verifier is selected at this moment.
///
/// The session is valid even if there is no internet. The local data will be used in this case.
/// The returned value is not really useful. Might be removed
//TODO: remove return value?
pub async fn session_start(config: SessionConfig) -> Result<SessionPeerStorageV0, NgError> {
let mut broker = match LOCAL_BROKER.get() {
None | Some(Err(_)) => return Err(NgError::LocalBrokerNotInitialized),
@ -489,7 +568,7 @@ pub async fn session_start(config: SessionConfig) -> Result<SessionPeerStorageV0
}
None => {
// the user was not found in the SWS. we need to create a SPS, add it, encrypt and serialize the new SWS,
// add the SPS to broker.sessions, and return the newly created SPS and the new SWS encryped serialization
// add the SPS to broker.sessions, and return the newly created SPS and the new SWS encrypted serialization
let sps = SessionPeerStorageV0::new(user_id);
sws.users.insert(user_id.to_string(), sps.clone());
let encrypted = sws.enc_session(&wallet_id)?;
@ -551,10 +630,58 @@ fn get_unix_time() -> f64 {
.as_millis() as f64
}
/// Attempts a TCP connection to the Server Broker of the User.
///
/// The configuration about which Server to contact is stored in the Wallet.
/// The LocalBroker will be in charge of maintaining this connection alive,
/// cycling through optional alternative servers to contact in case of failure,
/// and will notify the user if connection is lost permanently.
/// Result is a list of (user_id, server_id, server_ip, error, since_date)
/// If error is None, it means the connection is successful
///
/// Once the connection is established, the user can sync data, open documents, etc.. with the Verifier API
///
/// In a future version, it will be possible to be connected to several brokers at the same time
/// (for different users/identities opened concurrently on the same Client)
// TODO: improve this return value
// TODO: give public access to the API for subscribing to disconnections
pub async fn user_connect(
user_id: &UserId,
) -> Result<Vec<(String, String, String, Option<String>, f64)>, NgError> {
let os_info = get_os_info();
let info = json!({
"platform": {
"type": "program",
"arch": os_info.get("rust").unwrap().get("arch"),
"debug": os_info.get("rust").unwrap().get("debug"),
"target": os_info.get("rust").unwrap().get("target"),
"arch_uname": os_info.get("uname").unwrap().get("arch"),
"bitness": os_info.get("uname").unwrap().get("bitness"),
"codename": os_info.get("uname").unwrap().get("codename"),
"edition": os_info.get("uname").unwrap().get("edition"),
},
"os": {
"name": os_info.get("uname").unwrap().get("os_name"),
"family": os_info.get("rust").unwrap().get("family"),
"version": os_info.get("uname").unwrap().get("version"),
"name_rust": os_info.get("rust").unwrap().get("os_name"),
}
});
let client_info = ClientInfo::new(
ClientType::NativeService,
info.to_string(),
env!("CARGO_PKG_VERSION").to_string(),
);
user_connect_with_device_info(client_info, &user_id, None).await
}
/// Used internally by JS SDK and Tauri Apps. Do not use "as is". See [user_connect] instead.
#[doc(hidden)]
pub async fn user_connect_with_device_info(
info: ClientInfo,
user_id: UserId,
user_id: &UserId,
location: Option<String>,
) -> Result<Vec<(String, String, String, Option<String>, f64)>, NgError> {
let local_broker = match LOCAL_BROKER.get() {
@ -564,7 +691,7 @@ pub async fn user_connect(
let session = local_broker
.opened_sessions
.get(&user_id)
.get(user_id)
.ok_or(NgError::SessionNotFound)?;
let wallet = local_broker.get_wallet_for_session(&session.config)?;
@ -574,7 +701,6 @@ pub async fn user_connect(
match wallet {
SensitiveWallet::V0(wallet) => {
let client = wallet.client.as_ref().unwrap();
let client_id = client.id;
let client_priv = &client.sensitive_client_storage.priv_key;
let client_name = &client.name;
let auto_open = &client.auto_open;
@ -688,13 +814,14 @@ pub async fn user_connect(
Ok(result)
}
pub async fn session_stop(user_id: UserId) -> Result<(), NgError> {
/// Stops the session, that can be resumed later on. All the local data is flushed from RAM.
pub async fn session_stop(user_id: &UserId) -> Result<(), NgError> {
let mut broker = match LOCAL_BROKER.get() {
None | Some(Err(_)) => return Err(NgError::LocalBrokerNotInitialized),
Some(Ok(broker)) => broker.write().await,
};
if broker.opened_sessions.remove(&user_id).is_some() {
if broker.opened_sessions.remove(user_id).is_some() {
// TODO: change the logic here once it will be possible to have several users connected at the same time
Broker::close_all_connections().await;
}
@ -702,13 +829,14 @@ pub async fn session_stop(user_id: UserId) -> Result<(), NgError> {
Ok(())
}
pub async fn user_disconnect(user_id: UserId) -> Result<(), NgError> {
/// Disconnects the user from the Server Broker(s), but keep all the local data opened and ready.
pub async fn user_disconnect(user_id: &UserId) -> Result<(), NgError> {
let broker = match LOCAL_BROKER.get() {
None | Some(Err(_)) => return Err(NgError::LocalBrokerNotInitialized),
Some(Ok(broker)) => broker.read().await,
};
if broker.opened_sessions.get(&user_id).is_some() {
if broker.opened_sessions.get(user_id).is_some() {
// TODO: change the logic here once it will be possible to have several users connected at the same time
Broker::close_all_connections().await;
}
@ -716,13 +844,14 @@ pub async fn user_disconnect(user_id: UserId) -> Result<(), NgError> {
Ok(())
}
pub async fn wallet_close(wallet_name: String) -> Result<(), NgError> {
/// Closes a wallet, which means that the pazzle will have to be entered again if the user wants to use it
pub async fn wallet_close(wallet_name: &String) -> Result<(), NgError> {
let mut broker = match LOCAL_BROKER.get() {
None | Some(Err(_)) => return Err(NgError::LocalBrokerNotInitialized),
Some(Ok(broker)) => broker.write().await,
};
match broker.opened_wallets.remove(&wallet_name) {
match broker.opened_wallets.remove(wallet_name) {
Some(mut wallet) => {
for user in wallet.sites() {
let key: PubKey = (user.as_str()).try_into().unwrap();
@ -738,6 +867,7 @@ pub async fn wallet_close(wallet_name: String) -> Result<(), NgError> {
Ok(())
}
/// (not implemented yet)
pub async fn wallet_remove(wallet_name: String) -> Result<(), NgError> {
let mut broker = match LOCAL_BROKER.get() {
None | Some(Err(_)) => return Err(NgError::LocalBrokerNotInitialized),

@ -17,6 +17,7 @@ use ng_repo::types::*;
use ng_wallet::types::*;
use ng_wallet::*;
use serde::{Deserialize, Serialize};
use serde_json::Value;
use std::collections::HashMap;
use std::fs::{read, write, File, OpenOptions};
use std::io::Write;
@ -86,14 +87,14 @@ async fn wallet_open_with_pazzle(
app: tauri::AppHandle,
) -> Result<SensitiveWallet, String> {
//log_debug!("wallet_open_with_pazzle from rust {:?}", pazzle);
let wallet = nextgraph::local_broker::wallet_open_with_pazzle(wallet, pazzle, pin)
let wallet = nextgraph::local_broker::wallet_open_with_pazzle(&wallet, pazzle, pin)
.map_err(|e| e.to_string())?;
Ok(wallet)
}
#[tauri::command(rename_all = "snake_case")]
async fn wallet_download_file(wallet_name: String, app: tauri::AppHandle) -> Result<(), String> {
let ser = nextgraph::local_broker::wallet_download_file(&wallet_name)
async fn wallet_get_file(wallet_name: String, app: tauri::AppHandle) -> Result<(), String> {
let ser = nextgraph::local_broker::wallet_get_file(&wallet_name)
.await
.map_err(|e| e.to_string())?;
@ -135,34 +136,6 @@ async fn wallet_create(
Ok(cwr)
}
// // TODO: use https://lib.rs/crates/keyring instead of AppLocalData
// async fn save_wallet_locally(
// res: &CreateWalletResultV0,
// app: tauri::AppHandle,
// ) -> Result<SessionWalletStorageV0, ()> {
// let path = app
// .path()
// .resolve("wallets", BaseDirectory::AppLocalData)
// .map_err(|_| ())?;
// let mut wallets: HashMap<String, LocalWalletStorageV0> =
// get_all_wallets().unwrap_or(HashMap::new());
// // check that the wallet is not already present in localStorage
// if wallets.get(&res.wallet_name).is_none() {
// let lws: LocalWalletStorageV0 = res.into();
// wallets.insert(res.wallet_name.clone(), lws);
// let lws_ser = LocalWalletStorage::v0_to_vec(&wallets);
// let r = write(path.clone(), &lws_ser);
// if r.is_err() {
// log_debug!("write {:?} {}", path, r.unwrap_err());
// return Err(());
// }
// let sws = save_new_session(&res.wallet_name, res.wallet.id(), res.user, app)?;
// Ok(sws)
// } else {
// Err(())
// }
// }
fn take_some_peer_last_seq_numbers(
peer_id: PubKey,
qty: u16,
@ -233,41 +206,6 @@ async fn wallet_import(
nextgraph::local_broker::wallet_import(encrypted_wallet, opened_wallet, in_memory)
.await
.map_err(|e: NgError| e.to_string())
// let path = app
// .path()
// .resolve("wallets", BaseDirectory::AppLocalData)
// .map_err(|_| "wallet directory error".to_string())?;
// let mut wallets: HashMap<String, LocalWalletStorageV0> =
// get_all_wallets().unwrap_or(HashMap::new());
// // check that the wallet is not already present in localStorage
// let SensitiveWallet::V0(mut opened_wallet_v0) = opened_wallet;
// let wallet_name = opened_wallet_v0.wallet_id.clone();
// if wallets.get(&wallet_name).is_none() {
// let session = save_new_session(
// &wallet_name,
// opened_wallet_v0.wallet_privkey.to_pub(),
// opened_wallet_v0.personal_site,
// app,
// )
// .map_err(|_| "Cannot create new session".to_string())?;
// let lws = opened_wallet_v0
// .import(previous_wallet)
// .map_err(|e| e.to_string())?;
// //let lws = LocalWalletStorageV0::new(wallet, &client);
// wallets.insert(wallet_name, lws);
// let lws_ser = LocalWalletStorage::v0_to_vec(&wallets);
// let r = write(path.clone(), &lws_ser);
// if r.is_err() {
// log_debug!("write {:?} {}", path, r.unwrap_err());
// Err("Write error".to_string())
// } else {
// Ok(client)
// }
// } else {
// Err("Already present on this device".to_string())
// }
}
#[tauri::command(rename_all = "snake_case")]
@ -281,8 +219,8 @@ async fn get_wallets(
.unwrap();
init_local_broker(Box::new(move || LocalBrokerConfig::BasePath(path.clone()))).await;
let res = get_all_wallets().await.map_err(|e| {
log_err!("get_all_wallets error {}", e.to_string());
let res = wallets_get_all().await.map_err(|e| {
log_err!("wallets_get_all error {}", e.to_string());
});
if res.is_ok() {
return Ok(Some(res.unwrap()));
@ -290,32 +228,6 @@ async fn get_wallets(
Ok(None)
}
// fn save_new_session(
// wallet_name: &String,
// wallet_id: PubKey,
// user: PubKey,
// app: tauri::AppHandle,
// ) -> Result<SessionWalletStorageV0, ()> {
// let mut path = app
// .path()
// .resolve("sessions", BaseDirectory::AppLocalData)
// .map_err(|_| ())?;
// let session_v0 = create_new_session(wallet_id, user);
// if session_v0.is_err() {
// log_debug!("create_new_session failed {}", session_v0.unwrap_err());
// return Err(());
// }
// let sws = session_v0.unwrap();
// std::fs::create_dir_all(path.clone()).unwrap();
// path.push(wallet_name);
// let res = write(path.clone(), &sws.1);
// if res.is_err() {
// log_debug!("write {:?} {}", path, res.unwrap_err());
// return Err(());
// }
// Ok(sws.0)
// }
#[tauri::command(rename_all = "snake_case")]
async fn session_start(
wallet_name: String,
@ -465,21 +377,21 @@ async fn doc_get_file_from_store_with_object_ref(
#[tauri::command(rename_all = "snake_case")]
async fn session_stop(user_id: UserId) -> Result<(), String> {
nextgraph::local_broker::session_stop(user_id)
nextgraph::local_broker::session_stop(&user_id)
.await
.map_err(|e: NgError| e.to_string())
}
#[tauri::command(rename_all = "snake_case")]
async fn user_disconnect(user_id: UserId) -> Result<(), String> {
nextgraph::local_broker::user_disconnect(user_id)
nextgraph::local_broker::user_disconnect(&user_id)
.await
.map_err(|e: NgError| e.to_string())
}
#[tauri::command(rename_all = "snake_case")]
async fn wallet_close(wallet_name: String) -> Result<(), String> {
nextgraph::local_broker::wallet_close(wallet_name)
nextgraph::local_broker::wallet_close(&wallet_name)
.await
.map_err(|e: NgError| e.to_string())
}
@ -500,7 +412,7 @@ async fn user_connect(
) -> Result<HashMap<String, ConnectionInfo>, String> {
let mut opened_connections: HashMap<String, ConnectionInfo> = HashMap::new();
let results = nextgraph::local_broker::user_connect(info, user_id, None)
let results = nextgraph::local_broker::user_connect_with_device_info(info, &user_id, None)
.await
.map_err(|e| e.to_string())?;
@ -518,11 +430,14 @@ async fn user_connect(
);
}
//BROKER.read().await.print_status();
Ok(opened_connections)
}
#[tauri::command(rename_all = "snake_case")]
fn client_info_rust() -> Result<Value, String> {
Ok(ng_repo::os_info::get_os_info())
}
#[derive(Default)]
pub struct AppBuilder {
setup: Option<SetupHook>,
@ -577,7 +492,7 @@ impl AppBuilder {
wallet_was_opened,
wallet_create,
wallet_read_file,
wallet_download_file,
wallet_get_file,
wallet_import,
wallet_close,
encode_create_account,
@ -589,6 +504,7 @@ impl AppBuilder {
disconnections_subscribe,
user_connect,
user_disconnect,
client_info_rust,
])
.run(tauri::generate_context!())
.expect("error while running tauri application");

@ -108,7 +108,7 @@
window.addEventListener("storage", async (event) => {
if (event.storageArea != localStorage) return;
if (event.key === "ng_wallets") {
await ng.reload_wallets();
await ng.wallets_reload();
wallets.set(await ng.get_wallets());
}
});
@ -158,12 +158,12 @@
break;
case "opened":
if (!$opened_wallets[event.data.wallet.id]) {
console.log(
"ADDING TO OPENED",
event.data.wallet.id,