mirror of
https://github.com/uqbar-dao/nectar.git
synced 2024-11-21 15:59:32 +03:00
contacts FE
This commit is contained in:
parent
d7a94beac3
commit
c2cce9d376
26
Cargo.lock
generated
26
Cargo.lock
generated
@ -1867,7 +1867,7 @@ checksum = "f7144d30dcf0fafbce74250a3963025d8d52177934239851c917d29f1df280c2"
|
|||||||
name = "contacts"
|
name = "contacts"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"kinode_process_lib 0.9.3",
|
"kinode_process_lib 0.9.4",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"wit-bindgen",
|
"wit-bindgen",
|
||||||
@ -3759,6 +3759,28 @@ dependencies = [
|
|||||||
"wit-bindgen",
|
"wit-bindgen",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "kinode_process_lib"
|
||||||
|
version = "0.9.4"
|
||||||
|
source = "git+https://github.com/kinode-dao/process_lib?rev=088a549#088a5497257eada697e0869d6a8d7e9ef5e620f6"
|
||||||
|
dependencies = [
|
||||||
|
"alloy 0.1.4",
|
||||||
|
"alloy-primitives",
|
||||||
|
"alloy-sol-macro",
|
||||||
|
"alloy-sol-types",
|
||||||
|
"anyhow",
|
||||||
|
"bincode",
|
||||||
|
"http 1.1.0",
|
||||||
|
"mime_guess",
|
||||||
|
"rand 0.8.5",
|
||||||
|
"rmp-serde",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
"thiserror",
|
||||||
|
"url",
|
||||||
|
"wit-bindgen",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "kit"
|
name = "kit"
|
||||||
version = "0.7.7"
|
version = "0.7.7"
|
||||||
@ -5580,7 +5602,7 @@ dependencies = [
|
|||||||
"anyhow",
|
"anyhow",
|
||||||
"base64 0.22.1",
|
"base64 0.22.1",
|
||||||
"bincode",
|
"bincode",
|
||||||
"kinode_process_lib 0.9.3",
|
"kinode_process_lib 0.9.4",
|
||||||
"rmp-serde",
|
"rmp-serde",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
@ -129,6 +129,7 @@ The distro userspace packages are:
|
|||||||
|
|
||||||
- `app_store:sys`
|
- `app_store:sys`
|
||||||
- `chess:sys`
|
- `chess:sys`
|
||||||
|
- `contacts:sys`
|
||||||
- `homepage:sys`
|
- `homepage:sys`
|
||||||
- `kino_updates:sys`
|
- `kino_updates:sys`
|
||||||
- `kns_indexer:sys`
|
- `kns_indexer:sys`
|
||||||
|
5
kinode/packages/contacts/Cargo.lock
generated
5
kinode/packages/contacts/Cargo.lock
generated
@ -1462,9 +1462,8 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "kinode_process_lib"
|
name = "kinode_process_lib"
|
||||||
version = "0.9.3"
|
version = "0.9.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "git+https://github.com/kinode-dao/process_lib?rev=088a549#088a5497257eada697e0869d6a8d7e9ef5e620f6"
|
||||||
checksum = "7722aef4bff0625445fafda89a02f82ce0e16c7def6024e1317ae55a632ad331"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"alloy",
|
"alloy",
|
||||||
"alloy-primitives",
|
"alloy-primitives",
|
||||||
|
@ -26,6 +26,7 @@ interface contacts {
|
|||||||
add-field,
|
add-field,
|
||||||
remove-contact,
|
remove-contact,
|
||||||
remove-field,
|
remove-field,
|
||||||
|
error(string),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@ edition = "2021"
|
|||||||
simulation-mode = []
|
simulation-mode = []
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
kinode_process_lib = "0.9.3"
|
kinode_process_lib = { git = "https://github.com/kinode-dao/process_lib", rev = "088a549" }
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
wit-bindgen = "0.24.0"
|
wit-bindgen = "0.24.0"
|
||||||
|
@ -1 +1 @@
|
|||||||
data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTM2IiBoZWlnaHQ9IjEzNiIgdmlld0JveD0iMCAwIDEzNiAxMzYiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxyZWN0IHdpZHRoPSIxMzYiIGhlaWdodD0iMTM2IiByeD0iNjgiIGZpbGw9IiNGRkY1RDkiIGZpbGwtb3BhY2l0eT0iMC40Ii8+CjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMF8xODIxXzkwOTMpIj4KPHBhdGggZD0iTTY3LjQ4NTUgOTQuOTg4MUM2NS44MTYxIDk0Ljk4ODEgNjQuMTQ2NyA5NC45NjQzIDYyLjQ3NzIgOTQuOTg4MUM2MS41NjAyIDk1LjAxMTkgNjEuMDQyOSA5NC40MTc0IDYwLjkzNzEgOTMuNjQ0N0M2MC42NjY3IDkxLjU1MjMgNjAuMzQ5MyA4OS40NTk4IDYwLjA2NzEgODcuMzY3NEM2MC4wMjAxIDg3LjAxMDggNTkuODc5IDg2Ljc5NjggNTkuNTM4MSA4Ni42NTQxQzU4LjIzMzEgODYuMDgzNCA1Ny4wMjIyIDg1LjM1ODIgNTUuODgxOCA4NC40OTA0QzU1LjYyMzEgODQuMjg4MiA1NS4zOTk4IDg0LjI2NDUgNTUuMDk0MSA4NC4zOTUyQzUzLjE1NDMgODUuMjAzNyA1MS4yMTQ0IDg1Ljk4ODMgNDkuMjc0NiA4Ni43NzNDNDguMjc1MyA4Ny4xNzcyIDQ3Ljc5MzMgODcuMDIyNyA0Ny4yNTI1IDg2LjA5NTNDNDUuNTcxMyA4My4xNTg4IDQzLjg5MDEgODAuMjEwNCA0Mi4yMDg5IDc3LjI2MkM0MS44MDkyIDc2LjU3MjUgNDEuOTI2NyA3NS45NDIzIDQyLjU0OTggNzUuNDQzQzQ0LjIzMSA3NC4wOTk2IDQ1LjkxMjIgNzIuNzU2MiA0Ny42MDUyIDcxLjQzNjVDNDcuODk5MSA3MS4yMTA2IDQ4LjAwNDkgNzAuOTYxIDQ3Ljk1NzkgNzAuNTkyNEM0Ny43ODE1IDY5LjIwMTQgNDcuNzkzMyA2Ny43OTg2IDQ3Ljk1NzkgNjYuNDA3NkM0OC4wMDQ5IDY2LjA1MDkgNDcuOTEwOCA2NS44MTMxIDQ3LjYyODcgNjUuNTg3M0M0NS45OTQ1IDY0LjMwMzMgNDQuMzYwNCA2My4wMDc0IDQyLjczNzkgNjEuNzExNUM0MS44Nzk3IDYxLjAzMzkgNDEuNzczOSA2MC41MTA4IDQyLjMxNDcgNTkuNTcxNkM0NC4wMDc3IDU2LjYxMTMgNDUuNjg4OCA1My42MzkxIDQ3LjM5MzYgNTAuNjc4OEM0Ny43NDYyIDUwLjA3MjUgNDguMzgxMSA0OS44NTg1IDQ5LjA3NDcgNTAuMTQzOEM1MC40MjY3IDUwLjY5MDcgNTEuNzc4OCA1MS4yMzc1IDUzLjEzMDggNTEuNzk2M0M1My44MjQ0IDUyLjA4MTcgNTQuNTE4IDUyLjM1NTEgNTUuMjExNyA1Mi42NTIzQzU1LjQyMzMgNTIuNzQ3NCA1NS41ODc5IDUyLjczNTUgNTUuNzc2IDUyLjU5MjlDNTYuOTg2OSA1MS42NjU1IDU4LjMwMzYgNTAuODkyOCA1OS43MDI3IDUwLjI4NjVDNTkuOTQ5NiA1MC4xNzk1IDYwLjAyMDEgNDkuOTg5MiA2MC4wNDM2IDQ5Ljc1MTVDNjAuMzE0IDQ3LjgxMzYgNjAuNTg0NCA0NS44NzU3IDYwLjg1NDggNDMuOTM3OUM2MC44OTAxIDQzLjcxMiA2MC45MTM2IDQzLjQ4NjEgNjAuOTQ4OSA0My4yNjAyQzYxLjA5IDQyLjQxNjEgNjEuNTYwMiA0MiA2Mi4zNzE0IDQyQzY0LjQ0MDYgNDIgNjYuNTA5NyA0MiA2OC41Nzg5IDQyQzY5LjkwNzQgNDIgNzEuMjQ3NiA0MiA3Mi41NzYxIDQyQzczLjQ0NjEgNDIgNzMuOTI4MSA0Mi40NTE4IDc0LjA1NzUgNDMuMzMxNUM3NC4zNTE0IDQ1LjQzNTggNzQuNjQ1MyA0Ny41NDAyIDc0LjkyNzQgNDkuNjQ0NUM3NC45NzQ1IDQ5Ljk4OTIgNzUuMTE1NSA1MC4xNzk1IDc1LjQzMyA1MC4zMzRDNzYuNzM4IDUwLjkxNjYgNzcuOTcyNCA1MS42Mjk5IDc5LjExMjggNTIuNTA5NkM3OS4zNTk3IDUyLjY5OTkgNzkuNTU5NSA1Mi43MjM2IDc5Ljg0MTcgNTIuNjA0OEM4MS44MDUgNTEuNzk2MyA4My43Njg0IDUwLjk4NzkgODUuNzQzNSA1MC4xOTEzQzg2LjY3MjMgNDkuODEwOSA4Ny4yMTMxIDUwLjAxMyA4Ny43MTg2IDUwLjg5MjhDODkuMzc2MyA1My44MDU1IDkxLjAzMzkgNTYuNzE4MyA5Mi42OTE2IDU5LjYxOTFDOTMuMTczNiA2MC40NTEzIDkzLjA2NzggNjEuMDIyIDkyLjMxNTQgNjEuNjI4M0M5MC42NDYgNjIuOTU5OCA4OC45NzY1IDY0LjI3OTUgODcuMjk1NCA2NS41ODczQzg3LjAyNDkgNjUuODAxMyA4Ni45NDI3IDY2LjAyNzEgODYuOTc3OSA2Ni4zNkM4Ny4xNTQzIDY3Ljc4NjcgODcuMTU0MyA2OS4yMTMzIDg2Ljk3NzkgNzAuNjRDODYuOTQyNyA3MC45NjEgODcuMDI1IDcxLjE4NjkgODcuMjgzNiA3MS4zODlDODguOTI5NSA3Mi42ODQ4IDkwLjU3NTQgNzMuOTkyNiA5Mi4yMjE0IDc1LjMwMDRDOTMuMDU2MSA3NS45NjYxIDkzLjE2MTkgNzYuNDg5MiA5Mi42MzI4IDc3LjQxNjZDOTAuOTc1MiA4MC4zNDEyIDg5LjMwNTcgODMuMjUzOSA4Ny42MzYzIDg2LjE2NjdDODcuMTg5NSA4Ni45NTEzIDg2LjYwMTcgODcuMTUzNCA4NS43NjcgODYuODA4N0M4My44MDM3IDg2LjAxMjEgODEuODUyMSA4NS4yMTU2IDc5LjkwMDUgODQuNDA3MUM3OS41NzEzIDg0LjI2NDUgNzkuMzI0NCA4NC4yODgyIDc5LjAzMDUgODQuNTE0MUM3Ny45MDE5IDg1LjM5MzkgNzYuNjc5MiA4Ni4wOTUzIDc1LjM3NDIgODYuNjY2Qzc1LjA2ODUgODYuNzk2OCA3NC45MzkyIDg2Ljk4NyA3NC44OTIyIDg3LjMwOEM3NC42MSA4OS40MDA0IDc0LjMxNjEgOTEuNDkyOCA3NC4wMTA0IDkzLjU4NTJDNzMuOTYzNCA5My45MDYyIDczLjgzNDEgOTQuMjI3MiA3My42Njk1IDk0LjUwMDdDNzMuNDM0NCA5NC44NTczIDczLjA1ODEgOTQuOTg4MSA3Mi42MjMxIDk0Ljk4ODFDNzAuOTA2NyA5NC45ODgxIDY5LjE3ODUgOTQuOTg4MSA2Ny40NjIgOTQuOTg4MUg2Ny40ODU1Wk02Ny40NzM4IDU5LjE1NTVDNjIuNDMwMiA1OS4xNTU1IDU4LjI2ODQgNjMuMzUyMiA1OC4yNTY2IDY4LjQ2NDNDNTguMjQ0OSA3My42MDAzIDYyLjQwNjcgNzcuODIwOCA2Ny40ODU1IDc3LjgyMDhDNzIuNTUyNiA3Ny44MjA4IDc2LjcxNDQgNzMuNjEyMiA3Ni43MTQ0IDY4LjQ4ODFDNzYuNzE0NCA2My4zNDAzIDcyLjU2NDQgNTkuMTU1NSA2Ny40NjIgNTkuMTQzNkw2Ny40NzM4IDU5LjE1NTVaIiBmaWxsPSIjRkZGNUQ5Ii8+CjwvZz4KPGRlZnM+CjxjbGlwUGF0aCBpZD0iY2xpcDBfMTgyMV85MDkzIj4KPHJlY3Qgd2lkdGg9IjUxIiBoZWlnaHQ9IjUzIiBmaWxsPSJ3aGl0ZSIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoNDIgNDIpIi8+CjwvY2xpcFBhdGg+CjwvZGVmcz4KPC9zdmc+Cg==
|
data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTAwMCIgaGVpZ2h0PSIxMDAwIiB2aWV3Qm94PSIwIDAgMTAwMCAxMDAwIiBmaWxsPSJub25lIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPgo8cmVjdCB4PSIyMCIgeT0iMjAiIHdpZHRoPSI5NjAiIGhlaWdodD0iOTYwIiByeD0iNDgwIiBmaWxsPSJ1cmwoI3BhaW50MF9saW5lYXJfMjA5MV8xMDI4MikiIGZpbGwtb3BhY2l0eT0iMC40Ii8+CjxyZWN0IHg9IjIwIiB5PSIyMCIgd2lkdGg9Ijk2MCIgaGVpZ2h0PSI5NjAiIHJ4PSI0ODAiIHN0cm9rZT0idXJsKCNwYWludDFfbGluZWFyXzIwOTFfMTAyODIpIiBzdHJva2Utd2lkdGg9IjQwIi8+CjxwYXRoIGQ9Ik01ODEuMTE2IDU4NS43ODNMNjY0LjUzOCA2NjkuMTJDNjE3LjY5OSA3MTUuNzU4IDU1Ni42MjUgNzM5IDQ5NS4yNDUgNzM5QzQzMy44NjUgNzM5IDM3Mi42MzggNzE1LjYwNSAzMjYuMTA1IDY2OS4xMkMyODAuNzk3IDYyMy44NTggMjU2IDU2My45MTcgMjU2IDUwMEMyNTYgNDM2LjA4MyAyODAuOTUgMzc2LjE0MiAzMjYuMTA1IDMzMC44OEMzNzEuMjYgMjg1LjYxOSA0MzEuMjYyIDI2MSA0OTUuMjQ1IDI2MUM1NTkuMjI3IDI2MSA2MTkuMjMgMjg1LjkyNCA2NjQuNTM4IDMzMC44OEw1ODAuOTYzIDQxNC41MjNDNTQ1LjYwNCAzODMuOTQgNTA1LjE5NCAzNzQuNzY2IDQ2MS4yNjQgMzkxLjEyN0MzOTQuOTg1IDQxNS44OTkgMzY2LjgyMSA0ODkuMjk2IDM5Ny40MzUgNTUyLjc1NEMzOTguNjU5IDU1NS4yMDEgMzk4Ljk2NSA1NTguNzE4IDM5OC4zNTMgNTYxLjMxN0MzOTUuNzUxIDU3Mi40OCAzOTIuNjg5IDU4My40OSAzODkuNzgxIDU5NC4zNDZDMzg2LjEwNyA2MDcuOTU1IDM5My45MTQgNjE1Ljc1NCA0MDcuNTM3IDYxMi4yMzdDNDE4LjU1OCA2MDkuMzMxIDQyOS41NzkgNjA2LjEyIDQ0MC42IDYwMy42NzRDNDQzLjM1NSA2MDIuOTA5IDQ0Ny4wMjkgNjAzLjIxNSA0NDkuNjMxIDYwNC40MzhDNDkwLjUgNjIzLjM5OSA1MjkuOTkxIDYyMC44IDU2Ny43OTkgNTk2LjE4MUM1NzIuNTQ0IDU5My4xMjMgNTc2LjY3NyA1ODkuNDUzIDU4MS4xMTYgNTg1Ljc4M1oiIGZpbGw9InVybCgjcGFpbnQyX2xpbmVhcl8yMDkxXzEwMjgyKSIvPgo8ZGVmcz4KPGxpbmVhckdyYWRpZW50IGlkPSJwYWludDBfbGluZWFyXzIwOTFfMTAyODIiIHgxPSI1MDAiIHkxPSIwIiB4Mj0iNTAwIiB5Mj0iMTAwMCIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiPgo8c3RvcCBzdG9wLWNvbG9yPSIjRjM1NDIyIi8+CjxzdG9wIG9mZnNldD0iMSIgc3RvcC1vcGFjaXR5PSIwIi8+CjwvbGluZWFyR3JhZGllbnQ+CjxsaW5lYXJHcmFkaWVudCBpZD0icGFpbnQxX2xpbmVhcl8yMDkxXzEwMjgyIiB4MT0iNzgyLjUiIHkxPSI3My41IiB4Mj0iMTg1LjUiIHkyPSI4OTQuNSIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiPgo8c3RvcCBzdG9wLWNvbG9yPSIjRjM1NDIyIi8+CjxzdG9wIG9mZnNldD0iMSIgc3RvcC1jb2xvcj0iI0E1MzEwQyIvPgo8L2xpbmVhckdyYWRpZW50Pgo8bGluZWFyR3JhZGllbnQgaWQ9InBhaW50Ml9saW5lYXJfMjA5MV8xMDI4MiIgeDE9Ijc1NCIgeTE9Ijg5LjUiIHgyPSIyNTYiIHkyPSIxMDE1LjUiIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIj4KPHN0b3Agc3RvcC1jb2xvcj0iI0YzNTQyMiIvPgo8c3RvcCBvZmZzZXQ9IjEiIHN0b3AtY29sb3I9IiNBNzMyMEQiLz4KPC9saW5lYXJHcmFkaWVudD4KPC9kZWZzPgo8L3N2Zz4K
|
@ -1,7 +1,7 @@
|
|||||||
use crate::kinode::process::contacts::{ContactsRequest, ContactsResponse};
|
use crate::kinode::process::contacts::{ContactsRequest, ContactsResponse};
|
||||||
use kinode_process_lib::{
|
use kinode_process_lib::{
|
||||||
await_message, call_init, get_blob, get_typed_state, homepage, http, println, set_state,
|
await_message, call_init, eth, get_blob, get_typed_state, homepage, http, kimap, kiprintln,
|
||||||
Address, LazyLoadBlob, Message, NodeId, Response,
|
set_state, Address, LazyLoadBlob, Message, NodeId, Response,
|
||||||
};
|
};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
@ -17,6 +17,7 @@ struct Contacts(HashMap<NodeId, Contact>);
|
|||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
struct ContactsState {
|
struct ContactsState {
|
||||||
our: Address,
|
our: Address,
|
||||||
|
kimap: kimap::Kimap,
|
||||||
contacts: Contacts,
|
contacts: Contacts,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -24,6 +25,7 @@ impl ContactsState {
|
|||||||
fn new(our: Address) -> Self {
|
fn new(our: Address) -> Self {
|
||||||
get_typed_state(|bytes| serde_json::from_slice(bytes)).unwrap_or(Self {
|
get_typed_state(|bytes| serde_json::from_slice(bytes)).unwrap_or(Self {
|
||||||
our,
|
our,
|
||||||
|
kimap: kimap::Kimap::default(30),
|
||||||
contacts: Contacts(HashMap::new()),
|
contacts: Contacts(HashMap::new()),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -42,10 +44,12 @@ impl ContactsState {
|
|||||||
|
|
||||||
fn add_contact(&mut self, node: NodeId) {
|
fn add_contact(&mut self, node: NodeId) {
|
||||||
self.contacts.0.insert(node, Contact(HashMap::new()));
|
self.contacts.0.insert(node, Contact(HashMap::new()));
|
||||||
|
self.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn remove_contact(&mut self, node: NodeId) {
|
fn remove_contact(&mut self, node: NodeId) {
|
||||||
self.contacts.0.remove(&node);
|
self.contacts.0.remove(&node);
|
||||||
|
self.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_field(&mut self, node: NodeId, field: String, value: serde_json::Value) {
|
fn add_field(&mut self, node: NodeId, field: String, value: serde_json::Value) {
|
||||||
@ -55,12 +59,25 @@ impl ContactsState {
|
|||||||
.or_insert_with(|| Contact(HashMap::new()))
|
.or_insert_with(|| Contact(HashMap::new()))
|
||||||
.0
|
.0
|
||||||
.insert(field, value);
|
.insert(field, value);
|
||||||
|
self.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn remove_field(&mut self, node: NodeId, field: String) {
|
fn remove_field(&mut self, node: NodeId, field: String) {
|
||||||
if let Some(contact) = self.contacts.0.get_mut(&node) {
|
if let Some(contact) = self.contacts.0.get_mut(&node) {
|
||||||
contact.0.remove(&field);
|
contact.0.remove(&field);
|
||||||
}
|
}
|
||||||
|
self.save();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ws_update(&self, http_server: &mut http::server::HttpServer) {
|
||||||
|
http_server.ws_push_all_channels(
|
||||||
|
"/",
|
||||||
|
http::server::WsMessageType::Text,
|
||||||
|
LazyLoadBlob::new(
|
||||||
|
Some("application/json"),
|
||||||
|
serde_json::to_vec(self.contacts()).unwrap(),
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -73,6 +90,8 @@ wit_bindgen::generate!({
|
|||||||
|
|
||||||
call_init!(initialize);
|
call_init!(initialize);
|
||||||
fn initialize(our: Address) {
|
fn initialize(our: Address) {
|
||||||
|
kiprintln!("started");
|
||||||
|
|
||||||
homepage::add_to_homepage("Contacts", Some(ICON), Some("/"), None);
|
homepage::add_to_homepage("Contacts", Some(ICON), Some("/"), None);
|
||||||
|
|
||||||
let mut state: ContactsState = ContactsState::new(our);
|
let mut state: ContactsState = ContactsState::new(our);
|
||||||
@ -101,24 +120,13 @@ fn main_loop(state: &mut ContactsState, http_server: &mut http::server::HttpServ
|
|||||||
// ignore send errors, local-only process
|
// ignore send errors, local-only process
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
Ok(Message::Request {
|
Ok(Message::Request { source, body, .. }) => {
|
||||||
source,
|
// ignore messages from other nodes -- technically superfluous check
|
||||||
body,
|
// since manifest does not acquire networking capability
|
||||||
expects_response,
|
|
||||||
..
|
|
||||||
}) => {
|
|
||||||
if source.node() != state.our.node {
|
if source.node() != state.our.node {
|
||||||
continue; // ignore messages from other nodes
|
continue;
|
||||||
}
|
|
||||||
let response_and_blob = handle_request(&source, &body, state, http_server);
|
|
||||||
// state.ws_update(http_server);
|
|
||||||
if expects_response.is_some() && response_and_blob.is_some() {
|
|
||||||
let (response, blob) = response_and_blob.unwrap();
|
|
||||||
Response::new()
|
|
||||||
.body(serde_json::to_vec(&response).unwrap())
|
|
||||||
.send()
|
|
||||||
.unwrap();
|
|
||||||
}
|
}
|
||||||
|
handle_request(&source, &body, state, http_server);
|
||||||
}
|
}
|
||||||
_ => continue, // ignore responses
|
_ => continue, // ignore responses
|
||||||
}
|
}
|
||||||
@ -130,7 +138,7 @@ fn handle_request(
|
|||||||
body: &[u8],
|
body: &[u8],
|
||||||
state: &mut ContactsState,
|
state: &mut ContactsState,
|
||||||
http_server: &mut http::server::HttpServer,
|
http_server: &mut http::server::HttpServer,
|
||||||
) -> Option<ContactsResponse> {
|
) {
|
||||||
// source node is ALWAYS ourselves since networking is disabled
|
// source node is ALWAYS ourselves since networking is disabled
|
||||||
if source.process == "http_server:distro:sys" {
|
if source.process == "http_server:distro:sys" {
|
||||||
// receive HTTP requests and websocket connection messages from our server
|
// receive HTTP requests and websocket connection messages from our server
|
||||||
@ -143,13 +151,15 @@ fn handle_request(
|
|||||||
// we don't expect websocket messages
|
// we don't expect websocket messages
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
None
|
|
||||||
} else {
|
} else {
|
||||||
// let settings_request = serde_json::from_slice::<SettingsRequest>(body)
|
let (response, blob) = handle_contacts_request(state, body);
|
||||||
// .map_err(|_| SettingsError::MalformedRequest)?;
|
let mut response = Response::new().body(serde_json::to_vec(&response).unwrap());
|
||||||
// handle_settings_request(state, settings_request)
|
if let Some(blob) = blob {
|
||||||
None
|
response = response.blob(blob);
|
||||||
|
}
|
||||||
|
response.send().unwrap();
|
||||||
}
|
}
|
||||||
|
state.ws_update(http_server);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Handle HTTP requests from our own frontend.
|
/// Handle HTTP requests from our own frontend.
|
||||||
@ -158,21 +168,27 @@ fn handle_http_request(
|
|||||||
http_request: &http::server::IncomingHttpRequest,
|
http_request: &http::server::IncomingHttpRequest,
|
||||||
) -> (http::server::HttpResponse, Option<LazyLoadBlob>) {
|
) -> (http::server::HttpResponse, Option<LazyLoadBlob>) {
|
||||||
match http_request.method().unwrap().as_str() {
|
match http_request.method().unwrap().as_str() {
|
||||||
"GET" => {
|
"GET" => (
|
||||||
// state.fetch().unwrap();
|
http::server::HttpResponse::new(http::StatusCode::OK)
|
||||||
(
|
.header("Content-Type", "application/json"),
|
||||||
http::server::HttpResponse::new(http::StatusCode::OK)
|
Some(LazyLoadBlob::new(
|
||||||
.header("Content-Type", "application/json"),
|
Some("application/json"),
|
||||||
Some(LazyLoadBlob::new(
|
serde_json::to_vec(state.contacts()).unwrap(),
|
||||||
Some("application/json"),
|
)),
|
||||||
serde_json::to_vec(&state).unwrap(),
|
),
|
||||||
)),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
"POST" => {
|
"POST" => {
|
||||||
let blob = get_blob().unwrap();
|
let blob = get_blob().unwrap();
|
||||||
let request = serde_json::from_slice::<ContactsRequest>(&blob.bytes).unwrap();
|
let (response, blob) = handle_contacts_request(state, blob.bytes());
|
||||||
let (_response, blob) = handle_contacts_request(state, request);
|
if let ContactsResponse::Error(e) = response {
|
||||||
|
return (
|
||||||
|
http::server::HttpResponse::new(http::StatusCode::BAD_REQUEST)
|
||||||
|
.header("Content-Type", "application/json"),
|
||||||
|
Some(LazyLoadBlob::new(
|
||||||
|
Some("application/json"),
|
||||||
|
serde_json::to_vec(&e).unwrap(),
|
||||||
|
)),
|
||||||
|
);
|
||||||
|
}
|
||||||
(
|
(
|
||||||
http::server::HttpResponse::new(http::StatusCode::OK)
|
http::server::HttpResponse::new(http::StatusCode::OK)
|
||||||
.header("Content-Type", "application/json"),
|
.header("Content-Type", "application/json"),
|
||||||
@ -195,23 +211,83 @@ fn handle_http_request(
|
|||||||
|
|
||||||
fn handle_contacts_request(
|
fn handle_contacts_request(
|
||||||
state: &mut ContactsState,
|
state: &mut ContactsState,
|
||||||
request: ContactsRequest,
|
request_bytes: &[u8],
|
||||||
) -> (ContactsResponse, Option<LazyLoadBlob>) {
|
) -> (ContactsResponse, Option<LazyLoadBlob>) {
|
||||||
let response = match request {
|
let Ok(request) = serde_json::from_slice::<ContactsRequest>(request_bytes) else {
|
||||||
ContactsRequest::GetNames => ContactsResponse::GetNames(
|
return (
|
||||||
state
|
ContactsResponse::Error("Malformed request".to_string()),
|
||||||
.contacts()
|
None,
|
||||||
.0
|
);
|
||||||
.keys()
|
|
||||||
.map(|node| node.to_string())
|
|
||||||
.collect(),
|
|
||||||
),
|
|
||||||
ContactsRequest::GetAllContacts => ContactsResponse::GetAllContacts,
|
|
||||||
ContactsRequest::GetContact(node) => ContactsResponse::GetContact,
|
|
||||||
ContactsRequest::AddContact(node) => ContactsResponse::AddContact,
|
|
||||||
ContactsRequest::AddField((node, field, value)) => ContactsResponse::AddField,
|
|
||||||
ContactsRequest::RemoveContact(node) => ContactsResponse::RemoveContact,
|
|
||||||
ContactsRequest::RemoveField((node, field)) => ContactsResponse::RemoveField,
|
|
||||||
};
|
};
|
||||||
(response, None)
|
match request {
|
||||||
|
ContactsRequest::GetNames => (
|
||||||
|
ContactsResponse::GetNames(
|
||||||
|
state
|
||||||
|
.contacts()
|
||||||
|
.0
|
||||||
|
.keys()
|
||||||
|
.map(|node| node.to_string())
|
||||||
|
.collect(),
|
||||||
|
),
|
||||||
|
None,
|
||||||
|
),
|
||||||
|
ContactsRequest::GetAllContacts => (
|
||||||
|
ContactsResponse::GetAllContacts,
|
||||||
|
Some(LazyLoadBlob::new(
|
||||||
|
Some("application/json"),
|
||||||
|
serde_json::to_vec(state.contacts()).unwrap(),
|
||||||
|
)),
|
||||||
|
),
|
||||||
|
ContactsRequest::GetContact(node) => (
|
||||||
|
ContactsResponse::GetContact,
|
||||||
|
Some(LazyLoadBlob::new(
|
||||||
|
Some("application/json"),
|
||||||
|
serde_json::to_vec(&state.get_contact(node)).unwrap(),
|
||||||
|
)),
|
||||||
|
),
|
||||||
|
ContactsRequest::AddContact(node) => {
|
||||||
|
if let Some((response, blob)) = invalid_node(state, &node) {
|
||||||
|
return (response, blob);
|
||||||
|
}
|
||||||
|
state.add_contact(node);
|
||||||
|
(ContactsResponse::AddContact, None)
|
||||||
|
}
|
||||||
|
ContactsRequest::AddField((node, field, value)) => {
|
||||||
|
if let Some((response, blob)) = invalid_node(state, &node) {
|
||||||
|
return (response, blob);
|
||||||
|
}
|
||||||
|
let Ok(value) = serde_json::from_str::<serde_json::Value>(&value) else {
|
||||||
|
return (ContactsResponse::Error("Malformed value".to_string()), None);
|
||||||
|
};
|
||||||
|
state.add_field(node, field, value);
|
||||||
|
(ContactsResponse::AddField, None)
|
||||||
|
}
|
||||||
|
ContactsRequest::RemoveContact(node) => {
|
||||||
|
state.remove_contact(node);
|
||||||
|
(ContactsResponse::RemoveContact, None)
|
||||||
|
}
|
||||||
|
ContactsRequest::RemoveField((node, field)) => {
|
||||||
|
state.remove_field(node, field);
|
||||||
|
(ContactsResponse::RemoveField, None)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn invalid_node(
|
||||||
|
state: &ContactsState,
|
||||||
|
node: &str,
|
||||||
|
) -> Option<(ContactsResponse, Option<LazyLoadBlob>)> {
|
||||||
|
if state
|
||||||
|
.kimap
|
||||||
|
.get(&node)
|
||||||
|
.map(|(tba, _, _)| tba != eth::Address::ZERO)
|
||||||
|
.unwrap_or(false)
|
||||||
|
{
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some((
|
||||||
|
ContactsResponse::Error("Node name invalid or does not exist".to_string()),
|
||||||
|
None,
|
||||||
|
))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,11 +5,13 @@
|
|||||||
"on_exit": "Restart",
|
"on_exit": "Restart",
|
||||||
"request_networking": false,
|
"request_networking": false,
|
||||||
"request_capabilities": [
|
"request_capabilities": [
|
||||||
|
"eth:distro:sys",
|
||||||
"homepage:homepage:sys",
|
"homepage:homepage:sys",
|
||||||
"http_server:distro:sys",
|
"http_server:distro:sys",
|
||||||
"vfs:distro:sys"
|
"vfs:distro:sys"
|
||||||
],
|
],
|
||||||
"grant_capabilities": [
|
"grant_capabilities": [
|
||||||
|
"eth:distro:sys",
|
||||||
"http_server:distro:sys",
|
"http_server:distro:sys",
|
||||||
"vfs:distro:sys"
|
"vfs:distro:sys"
|
||||||
],
|
],
|
||||||
|
@ -47,6 +47,18 @@
|
|||||||
<body>
|
<body>
|
||||||
<h1>contacts</h1>
|
<h1>contacts</h1>
|
||||||
<main>
|
<main>
|
||||||
|
<article id="edit">
|
||||||
|
<h2>Contacts</h2>
|
||||||
|
<form id="add-contact">
|
||||||
|
<input type="text" name="node">
|
||||||
|
<button type="submit">add contact</button>
|
||||||
|
</form>
|
||||||
|
</article>
|
||||||
|
|
||||||
|
<article id="contacts-article">
|
||||||
|
<ul id="contacts"></ul>
|
||||||
|
</article>
|
||||||
|
|
||||||
<script src="/contacts:contacts:sys/script.js"></script>
|
<script src="/contacts:contacts:sys/script.js"></script>
|
||||||
</main>
|
</main>
|
||||||
</body>
|
</body>
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
const APP_PATH = '/contacts:contacts:sys/';
|
const APP_PATH = '/contacts:contacts:sys/ask';
|
||||||
|
|
||||||
// Fetch initial data and populate the UI
|
// Fetch initial data and populate the UI
|
||||||
function init() {
|
function init() {
|
||||||
fetch(APP_PATH + 'get')
|
fetch(APP_PATH)
|
||||||
.then(response => response.json())
|
.then(response => response.json())
|
||||||
.then(data => {
|
.then(data => {
|
||||||
populate(data);
|
populate(data);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function api_call(path, body) {
|
function api_call(body) {
|
||||||
fetch(APP_PATH + path, {
|
fetch(APP_PATH, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
@ -21,17 +21,58 @@ function api_call(path, body) {
|
|||||||
|
|
||||||
function populate(data) {
|
function populate(data) {
|
||||||
console.log(data);
|
console.log(data);
|
||||||
|
populate_contacts(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function populate_contacts(contacts) {
|
||||||
|
const ul = document.getElementById('contacts');
|
||||||
|
ul.innerHTML = '';
|
||||||
|
Object.entries(contacts).forEach(([node, contact]) => {
|
||||||
|
const li = document.createElement('li');
|
||||||
|
li.innerHTML = `${JSON.stringify(node, undefined, 2)}`;
|
||||||
|
ul.appendChild(li);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
document.getElementById('add-contact').addEventListener('submit', (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
const data = new FormData(e.target);
|
||||||
|
const node = data.get('node');
|
||||||
|
const body = {
|
||||||
|
"AddContact": node
|
||||||
|
};
|
||||||
|
fetch(APP_PATH, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
body: JSON.stringify(body),
|
||||||
|
}).then(response => {
|
||||||
|
if (response.status === 200) {
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
return response.json();
|
||||||
|
}
|
||||||
|
}).then(data => {
|
||||||
|
if (data === null) {
|
||||||
|
e.target.reset();
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
alert(JSON.stringify(data));
|
||||||
|
}
|
||||||
|
}).catch(error => {
|
||||||
|
console.error('Error:', error);
|
||||||
|
});
|
||||||
|
})
|
||||||
|
|
||||||
// Call init to start the application
|
// Call init to start the application
|
||||||
init();
|
init();
|
||||||
|
|
||||||
// Setup WebSocket connection
|
// Setup WebSocket connection
|
||||||
// const wsProtocol = location.protocol === 'https:' ? 'wss://' : 'ws://';
|
const wsProtocol = location.protocol === 'https:' ? 'wss://' : 'ws://';
|
||||||
// const ws = new WebSocket(wsProtocol + location.host + "/settings:settings:sys/");
|
const ws = new WebSocket(wsProtocol + location.host + "/contacts:contacts:sys/");
|
||||||
// ws.onmessage = event => {
|
ws.onmessage = event => {
|
||||||
// const data = JSON.parse(event.data);
|
const data = JSON.parse(event.data);
|
||||||
// console.log(data);
|
populate(data);
|
||||||
// populate(data);
|
};
|
||||||
// };
|
|
||||||
|
|
||||||
|
5
kinode/packages/settings/Cargo.lock
generated
5
kinode/packages/settings/Cargo.lock
generated
@ -1452,9 +1452,8 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "kinode_process_lib"
|
name = "kinode_process_lib"
|
||||||
version = "0.9.1"
|
version = "0.9.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "git+https://github.com/kinode-dao/process_lib?rev=088a549#088a5497257eada697e0869d6a8d7e9ef5e620f6"
|
||||||
checksum = "76c5b69ac1fc0cb457c7714ceb8c0a5bdbee4ee00b837f9f16ea711e902bdfe8"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"alloy",
|
"alloy",
|
||||||
"alloy-primitives",
|
"alloy-primitives",
|
||||||
|
@ -10,7 +10,7 @@ simulation-mode = []
|
|||||||
anyhow = "1.0"
|
anyhow = "1.0"
|
||||||
base64 = "0.22.0"
|
base64 = "0.22.0"
|
||||||
bincode = "1.3.3"
|
bincode = "1.3.3"
|
||||||
kinode_process_lib = "0.9.1"
|
kinode_process_lib = { git = "https://github.com/kinode-dao/process_lib", rev = "088a549" }
|
||||||
rmp-serde = "1.2.0"
|
rmp-serde = "1.2.0"
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
|
Loading…
Reference in New Issue
Block a user