mirror of
https://github.com/uqbar-dao/nectar.git
synced 2024-12-22 16:11:38 +03:00
contacts: make kimap work in sim-mode, improve FE
This commit is contained in:
parent
5ef0771abd
commit
c24d2b51f9
@ -5,9 +5,22 @@ use kinode_process_lib::{
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::HashMap;
|
||||
use std::str::FromStr;
|
||||
|
||||
const ICON: &str = include_str!("icon");
|
||||
|
||||
#[cfg(not(feature = "simulation-mode"))]
|
||||
const CHAIN_ID: u64 = kimap::KIMAP_CHAIN_ID;
|
||||
#[cfg(feature = "simulation-mode")]
|
||||
const CHAIN_ID: u64 = 31337; // local
|
||||
|
||||
const CHAIN_TIMEOUT: u64 = 60; // 60s
|
||||
|
||||
#[cfg(not(feature = "simulation-mode"))]
|
||||
const KIMAP_ADDRESS: &'static str = kimap::KIMAP_ADDRESS; // optimism
|
||||
#[cfg(feature = "simulation-mode")]
|
||||
const KIMAP_ADDRESS: &str = "0xEce71a05B36CA55B895427cD9a440eEF7Cf3669D";
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
struct Contact(HashMap<String, serde_json::Value>);
|
||||
|
||||
@ -17,7 +30,6 @@ struct Contacts(HashMap<NodeId, Contact>);
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
struct ContactsState {
|
||||
our: Address,
|
||||
kimap: kimap::Kimap,
|
||||
contacts: Contacts,
|
||||
}
|
||||
|
||||
@ -25,7 +37,6 @@ impl ContactsState {
|
||||
fn new(our: Address) -> Self {
|
||||
get_typed_state(|bytes| serde_json::from_slice(bytes)).unwrap_or(Self {
|
||||
our,
|
||||
kimap: kimap::Kimap::default(30),
|
||||
contacts: Contacts(HashMap::new()),
|
||||
})
|
||||
}
|
||||
@ -96,6 +107,11 @@ fn initialize(our: Address) {
|
||||
|
||||
let mut state: ContactsState = ContactsState::new(our);
|
||||
|
||||
let kimap = kimap::Kimap::new(
|
||||
eth::Provider::new(CHAIN_ID, CHAIN_TIMEOUT),
|
||||
eth::Address::from_str(KIMAP_ADDRESS).unwrap(),
|
||||
);
|
||||
|
||||
let mut http_server = http::server::HttpServer::new(5);
|
||||
|
||||
// serve the frontend on a secure subdomain
|
||||
@ -110,10 +126,14 @@ fn initialize(our: Address) {
|
||||
http_server.secure_bind_http_path("/ask").unwrap();
|
||||
http_server.secure_bind_ws_path("/").unwrap();
|
||||
|
||||
main_loop(&mut state, &mut http_server);
|
||||
main_loop(&mut state, &kimap, &mut http_server);
|
||||
}
|
||||
|
||||
fn main_loop(state: &mut ContactsState, http_server: &mut http::server::HttpServer) {
|
||||
fn main_loop(
|
||||
state: &mut ContactsState,
|
||||
kimap: &kimap::Kimap,
|
||||
http_server: &mut http::server::HttpServer,
|
||||
) {
|
||||
loop {
|
||||
match await_message() {
|
||||
Err(_send_error) => {
|
||||
@ -131,7 +151,7 @@ fn main_loop(state: &mut ContactsState, http_server: &mut http::server::HttpServ
|
||||
if source.node() != state.our.node {
|
||||
continue;
|
||||
}
|
||||
handle_request(&source, &body, capabilities, state, http_server);
|
||||
handle_request(&source, &body, capabilities, state, kimap, http_server);
|
||||
}
|
||||
_ => continue, // ignore responses
|
||||
}
|
||||
@ -143,6 +163,7 @@ fn handle_request(
|
||||
body: &[u8],
|
||||
capabilities: Vec<Capability>,
|
||||
state: &mut ContactsState,
|
||||
kimap: &kimap::Kimap,
|
||||
http_server: &mut http::server::HttpServer,
|
||||
) {
|
||||
// source node is ALWAYS ourselves since networking is disabled
|
||||
@ -152,14 +173,14 @@ fn handle_request(
|
||||
|
||||
http_server.handle_request(
|
||||
server_request,
|
||||
|req| handle_http_request(state, &req),
|
||||
|req| handle_http_request(state, kimap, &req),
|
||||
|_channel_id, _message_type, _blob| {
|
||||
// we don't expect websocket messages
|
||||
},
|
||||
);
|
||||
} else {
|
||||
// if request is not from frontend, check that it has the required capabilities
|
||||
let (response, blob) = handle_contacts_request(state, body, Some(capabilities));
|
||||
let (response, blob) = handle_contacts_request(state, kimap, body, Some(capabilities));
|
||||
let mut response = Response::new().body(serde_json::to_vec(&response).unwrap());
|
||||
if let Some(blob) = blob {
|
||||
response = response.blob(blob);
|
||||
@ -172,6 +193,7 @@ fn handle_request(
|
||||
/// Handle HTTP requests from our own frontend.
|
||||
fn handle_http_request(
|
||||
state: &mut ContactsState,
|
||||
kimap: &kimap::Kimap,
|
||||
http_request: &http::server::IncomingHttpRequest,
|
||||
) -> (http::server::HttpResponse, Option<LazyLoadBlob>) {
|
||||
match http_request.method().unwrap().as_str() {
|
||||
@ -185,7 +207,7 @@ fn handle_http_request(
|
||||
),
|
||||
"POST" => {
|
||||
let blob = get_blob().unwrap();
|
||||
let (response, blob) = handle_contacts_request(state, blob.bytes(), None);
|
||||
let (response, blob) = handle_contacts_request(state, kimap, blob.bytes(), None);
|
||||
if let contacts::Response::Error(e) = response {
|
||||
return (
|
||||
http::server::HttpResponse::new(http::StatusCode::BAD_REQUEST)
|
||||
@ -218,6 +240,7 @@ fn handle_http_request(
|
||||
|
||||
fn handle_contacts_request(
|
||||
state: &mut ContactsState,
|
||||
kimap: &kimap::Kimap,
|
||||
request_bytes: &[u8],
|
||||
capabilities: Option<Vec<Capability>>,
|
||||
) -> (contacts::Response, Option<LazyLoadBlob>) {
|
||||
@ -281,14 +304,14 @@ fn handle_contacts_request(
|
||||
)),
|
||||
),
|
||||
contacts::Request::AddContact(node) => {
|
||||
if let Some((response, blob)) = invalid_node(state, &node) {
|
||||
if let Some((response, blob)) = invalid_node(kimap, &node) {
|
||||
return (response, blob);
|
||||
}
|
||||
state.add_contact(node);
|
||||
(contacts::Response::AddContact, None)
|
||||
}
|
||||
contacts::Request::AddField((node, field, value)) => {
|
||||
if let Some((response, blob)) = invalid_node(state, &node) {
|
||||
if let Some((response, blob)) = invalid_node(kimap, &node) {
|
||||
return (response, blob);
|
||||
}
|
||||
let Ok(value) = serde_json::from_str::<serde_json::Value>(&value) else {
|
||||
@ -312,11 +335,10 @@ fn handle_contacts_request(
|
||||
}
|
||||
|
||||
fn invalid_node(
|
||||
state: &ContactsState,
|
||||
kimap: &kimap::Kimap,
|
||||
node: &str,
|
||||
) -> Option<(contacts::Response, Option<LazyLoadBlob>)> {
|
||||
if state
|
||||
.kimap
|
||||
if kimap
|
||||
.get(&node)
|
||||
.map(|(tba, _, _)| tba != eth::Address::ZERO)
|
||||
.unwrap_or(false)
|
||||
|
@ -9,7 +9,7 @@
|
||||
<link href="https://api.fontshare.com/v2/css?f[]=clash-display@400,700,500,600,300&display=swap" rel="stylesheet" />
|
||||
<script src="/our.js"></script>
|
||||
<script>
|
||||
document.title = window.our.node + " - contacts";
|
||||
document.title = "contacts - " + window.our.node;
|
||||
</script>
|
||||
<style>
|
||||
h1,
|
||||
@ -33,14 +33,58 @@
|
||||
|
||||
main {
|
||||
margin: 0 auto;
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr 1fr;
|
||||
gap: 20px 20px;
|
||||
grid-auto-flow: row;
|
||||
padding: 20px;
|
||||
max-width: 960px;
|
||||
min-width: 300px;
|
||||
}
|
||||
|
||||
form.add-contact {
|
||||
max-width: 400px;
|
||||
}
|
||||
|
||||
#contacts {
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.contact:first-of-type {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.contact {
|
||||
padding: 10px;
|
||||
border: 1px solid var(--tasteful-dark);
|
||||
border-radius: 5px;
|
||||
margin-bottom: 10px;
|
||||
display: grid;
|
||||
gap: 10px;
|
||||
grid-auto-flow: row;
|
||||
grid-template-areas:
|
||||
"name name delete"
|
||||
"fields fields fields"
|
||||
"add-field add-field add-field";
|
||||
}
|
||||
|
||||
.contact h3 {
|
||||
grid-area: name;
|
||||
}
|
||||
|
||||
.contact ul {
|
||||
grid-area: fields;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.contact ul li {
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
form.delete-contact {
|
||||
grid-area: delete;
|
||||
}
|
||||
|
||||
form.add-field {
|
||||
grid-area: add-field;
|
||||
max-width: 400px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
@ -48,7 +92,6 @@
|
||||
<h1>contacts</h1>
|
||||
<main>
|
||||
<article id="edit">
|
||||
<h2>Contacts</h2>
|
||||
<form id="add-contact">
|
||||
<input type="text" name="node">
|
||||
<button type="submit">add contact</button>
|
||||
|
@ -20,9 +20,45 @@ function populate_contacts(contacts) {
|
||||
ul.innerHTML = '';
|
||||
Object.entries(contacts).forEach(([node, contact]) => {
|
||||
const li = document.createElement('li');
|
||||
li.innerHTML = `${JSON.stringify(node, undefined, 2)}`;
|
||||
const div = document.createElement('div');
|
||||
div.classList.add('contact');
|
||||
div.innerHTML = `<h3>${node}</h3>
|
||||
<ul>
|
||||
${Object.entries(contact).map(([field, value]) => `<li>${field}: ${value}</li>`).join('')}
|
||||
</ul>
|
||||
<form class="delete-contact" id="${node}">
|
||||
<button type="submit">delete</button>
|
||||
</form>
|
||||
<form class="add-field" id="${node}">
|
||||
<input type="text" name="field" placeholder="Field">
|
||||
<input type="text" name="value" placeholder="Value">
|
||||
<button type="submit">add</button>
|
||||
</form>
|
||||
`;
|
||||
li.appendChild(div);
|
||||
ul.appendChild(li);
|
||||
});
|
||||
|
||||
ul.querySelectorAll('.delete-contact').forEach(form => {
|
||||
form.addEventListener('submit', function (e) {
|
||||
e.preventDefault();
|
||||
const node = this.getAttribute('id');
|
||||
api_call({
|
||||
"RemoveContact": node
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
ul.querySelectorAll('.add-field').forEach(form => {
|
||||
form.addEventListener('submit', function (e) {
|
||||
e.preventDefault();
|
||||
const node = this.getAttribute('id');
|
||||
const data = new FormData(e.target);
|
||||
api_call({
|
||||
"AddField": [node, data.get('field'), data.get('value')]
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
document.getElementById('add-contact').addEventListener('submit', (e) => {
|
||||
@ -39,6 +75,7 @@ document.getElementById('add-contact').addEventListener('submit', (e) => {
|
||||
},
|
||||
body: JSON.stringify(body),
|
||||
}).then(response => {
|
||||
e.target.reset();
|
||||
if (response.status === 200) {
|
||||
return null;
|
||||
} else {
|
||||
@ -46,7 +83,6 @@ document.getElementById('add-contact').addEventListener('submit', (e) => {
|
||||
}
|
||||
}).then(data => {
|
||||
if (data === null) {
|
||||
e.target.reset();
|
||||
return;
|
||||
} else {
|
||||
alert(JSON.stringify(data));
|
||||
|
Loading…
Reference in New Issue
Block a user