Compare commits

..

No commits in common. "ee35e6cf1fee74d4d2b78831952c91d9912046ed" and "60803b4a4ec4e7d6b52373213c3d0d2b220a95a1" have entirely different histories.

16 changed files with 39 additions and 491 deletions

View File

@ -1,43 +1,9 @@
fewd = front end web dev # fewd = front end web dev
=====================================================================
this is me (PRH) trying to learn some front end web dev because pixels are this is me (PRH) trying to learn some front end web dev because pixels are
important despite my wishes. important despite my wishes.
Building/Running # notes
---------------------------------------------------------------------
### Prereqs ## goal queue
1. [Install Erlang and ZX](https://git.qpq.swiss/QPQ-AG/research-megadoc/wiki/Installing-Erlang-and-zx)
2. **DEV ONLY**: `apt install node-typescript` (Devuan Excalibur)
This is needed if you want to **edit** the `.ts` files found in
`/priv/static/js/ts/*.ts`. The built JS files are under version control and can
be found in `/priv/static/js/dist/`
### Building/Running HTTP Server
If you are only changing the Erlang or simply just want to run the program
without developing it, then just run
```
zxh runlocal
```
### Building TS->JS
**This is only necessary if you edited the `.ts` files and want to transpile
them over to JS.**
This requires you installed `tsc` as above.
```
make tsc
```
If you're doing development you may want
```
make watch
```

View File

View File

@ -1,20 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>FIXME</title>
<link rel="stylesheet" href="/css/default.css">
</head>
<body>
<div id="titlebar">
<div class="content">
<a href="/" class="tb-home">Home</a>
</div>
</div>
<div class="content">
<h1 class="content-title">FEWD: FIXME</h1>
</div>
</body>
</html>

View File

@ -1,9 +0,0 @@
/**
* Title: Title
* Description: Description
* Author: Peter Harpending <peterharpending@qpq.swiss>
* Date: YYYY-MM-DD
* Last-Updated: YYYY-MM-DD
*
* @module
*/

View File

@ -1,59 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Basic GRIDS Demo</title>
<link rel="stylesheet" href="/css/default.css">
</head>
<body>
<div id="titlebar">
<div class="content">
<a href="/" class="tb-home">Home</a>
</div>
</div>
<div class="content">
<h1 class="content-title">FEWD: GRIDS DEMO</h1>
<h2>Making a Spend</h2>
<label for="grids-n">Network ID:</label>
<input type = "text"
id = "grids-n"
value = "groot.testnet"
disabled>
<br>
<label for="grids-r">Recipient:</label>
<input type = "text"
id = "grids-r"
value = "ak_n6aVQ6PkBdVdv7kRRcfnzDVmBsH6hqEwVWSB6UAEb3kkjrPMe"
disabled>
<br>
<label for="grids-a">Amount (P):</label>
<input type = "number"
id = "grids-a"
value = "6000000">
<br>
<label for="grids-p">Payload:</label>
<input type = "text"
id = "grids-p"
value = "test payload">
<br>
<input type = "button"
id = "grids-submit"
value = "Generate">
<br>
<textarea disabled id="grids-url" hidden></textarea>
<br>
<img id="grids-png" hidden>
</div>
<script src="/js/dist/grids-basic.js"></script>
</body>
</html>

View File

@ -17,7 +17,6 @@
<ul> <ul>
<li><a href="/echo.html">Echo</a></li> <li><a href="/echo.html">Echo</a></li>
<li><a href="/grids-basic.html">GRIDS: Basic Demo</a></li>
<li><a href="/wfc.html">WFC</a></li> <li><a href="/wfc.html">WFC</a></li>
</ul> </ul>
</div> </div>

View File

@ -1,29 +0,0 @@
/**
* Title: GRIDS Basic Page Script
* Description: Page Script for /grids-basic.html
* Author: Peter Harpending <peterharpending@qpq.swiss>
* Date: 2025-12-29
* Last-Updated: 2025-12-29
*
* @module
*/
/**
* Runs on page load
*/
declare function main(): Promise<void>;
declare function on_submit(n_input: HTMLInputElement, r_input: HTMLInputElement, a_input: HTMLInputElement, p_input: HTMLInputElement, grids_url_elt: HTMLTextAreaElement, grids_png_elt: HTMLImageElement): Promise<void>;
type Safe<t> = {
ok: true;
result: t;
} | {
ok: false;
error: string;
};
type GridsResult = {
url: string;
png_base64: string;
};
/**
* gets the grids url
*/
declare function grids_request(net_id: string, recipient: string, amount: number, payload: string): Promise<Safe<GridsResult>>;

View File

@ -1,83 +0,0 @@
"use strict";
/**
* Title: GRIDS Basic Page Script
* Description: Page Script for /grids-basic.html
* Author: Peter Harpending <peterharpending@qpq.swiss>
* Date: 2025-12-29
* Last-Updated: 2025-12-29
*
* @module
*/
main();
/**
* Runs on page load
*/
async function main() {
let n_input = document.getElementById('grids-n');
let r_input = document.getElementById('grids-r');
let a_input = document.getElementById('grids-a');
let p_input = document.getElementById('grids-p');
let submit_btn = document.getElementById('grids-submit');
let grids_url_elt = document.getElementById('grids-url');
let grids_png_elt = document.getElementById('grids-png');
// Page initialization
submit_btn.addEventListener('click', async function (e) {
await on_submit(n_input, r_input, a_input, p_input, grids_url_elt, grids_png_elt);
});
// enable buttons
submit_btn.disabled = false;
}
async function on_submit(n_input, r_input, a_input, p_input, grids_url_elt, grids_png_elt) {
// pull out values
let network_id = n_input.value;
let recipient = r_input.value;
let amount = parseInt(a_input.value);
let payload = p_input.value;
let result = await grids_request(network_id, recipient, amount, payload);
// show url field and png
if (result.ok) {
let url = result.result.url;
let png_base64 = result.result.png_base64;
let src_prefix = 'data:image/png;base64,';
let src = src_prefix + png_base64;
grids_url_elt.innerText = url;
grids_png_elt.src = src;
grids_url_elt.hidden = false;
grids_png_elt.hidden = false;
}
else {
alert('ERROR: ' + result.error);
}
}
/**
* gets the grids url
*/
async function grids_request(net_id, recipient, amount, payload) {
// format for network transmission
let obj = { 'network_id': net_id,
'recipient': recipient,
'amount': amount,
'payload': payload };
let obj_text = JSON.stringify(obj, undefined, 4);
let url = '/grids-spend';
let req_options = { method: 'POST',
headers: { 'content-type': 'application/json' },
body: obj_text };
let result = { ok: false,
error: 'IT DO BE LIKE THAT MISTA STANCIL' };
try {
let response = await fetch(url, req_options);
if (response.ok)
result = await response.json();
else {
console.log('bad http response:', response);
result = { ok: false, error: 'BAD HTTP RESPONSE' };
}
}
catch (x) {
console.log('network error:', x);
result = { ok: false, error: 'NETWORK ERROR' };
}
return result;
}
//# sourceMappingURL=grids-basic.js.map

View File

@ -1 +0,0 @@
{"version":3,"file":"grids-basic.js","sourceRoot":"","sources":["../ts/grids-basic.ts"],"names":[],"mappings":"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"}

View File

@ -1 +1 @@
{"version":3,"file":"libfewd.js","sourceRoot":"","sources":["../ts/libfewd.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EACH,WAAW,EACX,qBAAqB,EACxB,CAAC;AAGF,SACA,WAAW,CACN,gBAAmC,EACnC,cAAsC,EACtC,UAAyB;IAG1B,+DAA+D;IAC/D,IAAI,gBAAgB,CAAC,OAAO,EAAE;QAC1B,IAAI,aAAa,GAAW,cAAc,CAAC,YAAY,CAAC;QACxD,sCAAsC;QACtC,IAAI,aAAa,GAAG,UAAU;YAC1B,cAAc,CAAC,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,aAAa,CAAC,GAAG,IAAI,CAAC;;YAE3D,cAAc,CAAC,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,UAAU,CAAC,GAAG,IAAI,CAAC;KAC/D;AACL,CAAC;AAGD,SACA,qBAAqB,CAChB,gBAAmC,EACnC,cAAsC;IAGvC,IAAI,gBAAgB,CAAC,OAAO,EAAE;QAC1B,mBAAmB;QACnB,cAAc,CAAC,SAAS,GAAG,cAAc,CAAC,YAAY,CAAC;KAC1D;AACL,CAAC"} {"version":3,"file":"libfewd.js","sourceRoot":"","sources":["../ts/libfewd.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EACH,WAAW,EACX,qBAAqB,EACxB,CAAC;AAGF,SACA,WAAW,CACN,gBAAmC,EACnC,cAAsC,EACtC,UAAyB;IAG1B,+DAA+D;IAC/D,IAAI,gBAAgB,CAAC,OAAO,EAAE,CAAC;QAC3B,IAAI,aAAa,GAAW,cAAc,CAAC,YAAY,CAAC;QACxD,sCAAsC;QACtC,IAAI,aAAa,GAAG,UAAU;YAC1B,cAAc,CAAC,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,aAAa,CAAC,GAAG,IAAI,CAAC;;YAE3D,cAAc,CAAC,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,UAAU,CAAC,GAAG,IAAI,CAAC;IAChE,CAAC;AACL,CAAC;AAGD,SACA,qBAAqB,CAChB,gBAAmC,EACnC,cAAsC;IAGvC,IAAI,gBAAgB,CAAC,OAAO,EAAE,CAAC;QAC3B,mBAAmB;QACnB,cAAc,CAAC,SAAS,GAAG,cAAc,CAAC,YAAY,CAAC;IAC3D,CAAC;AACL,CAAC"}

View File

@ -1 +1 @@
{"version":3,"file":"wfc.js","sourceRoot":"","sources":["../ts/wfc.ts"],"names":[],"mappings":"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"} {"version":3,"file":"wfc.js","sourceRoot":"","sources":["../ts/wfc.ts"],"names":[],"mappings":"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"}

View File

@ -1,131 +0,0 @@
/**
* Title: GRIDS Basic Page Script
* Description: Page Script for /grids-basic.html
* Author: Peter Harpending <peterharpending@qpq.swiss>
* Date: 2025-12-29
* Last-Updated: 2025-12-29
*
* @module
*/
main();
/**
* Runs on page load
*/
async function
main
()
{
let n_input = document.getElementById('grids-n') as HTMLInputElement;
let r_input = document.getElementById('grids-r') as HTMLInputElement;
let a_input = document.getElementById('grids-a') as HTMLInputElement;
let p_input = document.getElementById('grids-p') as HTMLInputElement;
let submit_btn = document.getElementById('grids-submit') as HTMLInputElement;
let grids_url_elt = document.getElementById('grids-url') as HTMLTextAreaElement;
let grids_png_elt = document.getElementById('grids-png') as HTMLImageElement;
// Page initialization
submit_btn.addEventListener(
'click',
async function(e) {
await on_submit(n_input, r_input, a_input, p_input, grids_url_elt, grids_png_elt)
}
);
// enable buttons
submit_btn.disabled = false;
}
async function
on_submit
(n_input : HTMLInputElement,
r_input : HTMLInputElement,
a_input : HTMLInputElement,
p_input : HTMLInputElement,
grids_url_elt : HTMLTextAreaElement,
grids_png_elt : HTMLImageElement)
: Promise<void>
{
// pull out values
let network_id : string = n_input.value;
let recipient : string = r_input.value;
let amount : number = parseInt(a_input.value);
let payload : string = p_input.value;
let result: Safe<GridsResult> = await grids_request(network_id, recipient, amount, payload);
// show url field and png
if (result.ok) {
let url : string = result.result.url;
let png_base64 : string = result.result.png_base64;
let src_prefix : string = 'data:image/png;base64,'
let src = src_prefix + png_base64;
grids_url_elt.innerText = url;
grids_png_elt.src = src;
grids_url_elt.hidden = false;
grids_png_elt.hidden = false;
}
else {
alert('ERROR: ' + result.error);
}
}
type Safe<t> = {ok: true, result: t}
| {ok: false, error: string};
type GridsResult = {url : string,
png_base64: string};
/**
* gets the grids url
*/
async function
grids_request
(net_id : string,
recipient : string,
amount : number,
payload : string)
: Promise<Safe<GridsResult>>
{
// format for network transmission
let obj : object = {'network_id' : net_id,
'recipient' : recipient,
'amount' : amount,
'payload' : payload};
let obj_text : string = JSON.stringify(obj, undefined, 4);
let url = '/grids-spend';
let req_options = {method: 'POST',
headers: {'content-type': 'application/json'},
body: obj_text};
let result: Safe<GridsResult> =
{ok : false,
error : 'IT DO BE LIKE THAT MISTA STANCIL'};
try {
let response : Response = await fetch(url, req_options);
if (response.ok)
result = await response.json() as Safe<GridsResult>;
else {
console.log('bad http response:', response);
result = {ok: false, error: 'BAD HTTP RESPONSE'};
}
}
catch (x: any) {
console.log('network error:', x);
result = {ok: false, error: 'NETWORK ERROR'};
}
return result;
}

View File

@ -9,7 +9,7 @@
-export([ -export([
%% caller context %% caller context
mk_spend/4, get_url/2,
%% api %% api
start_link/0, start_link/0,
@ -21,6 +21,8 @@
-include("$zx_include/zx_logger.hrl"). -include("$zx_include/zx_logger.hrl").
-type mh_str() :: string().
%% for craig's autism %% for craig's autism
-record(sp, -record(sp,
{recipient :: string(), {recipient :: string(),
@ -28,11 +30,13 @@
payload :: binary()}). payload :: binary()}).
-type search_pattern() :: #sp{}. -type search_pattern() :: #sp{}.
-type sp() :: search_pattern().
-record(s, -record(s,
{looking_for = [] :: [{sp(), NotifyWhenSeen :: pid()}]}). {current_gen_height :: pos_integer(),
current_gen_hash :: string(),
current_gen_seen_mb_hashes :: [mh_str()],
past_gen_seen_mb_hashes :: [mh_str()],
looking_for :: [search_pattern()]}).
-type state() :: #s{}. -type state() :: #s{}.
@ -40,20 +44,14 @@
%% caller context %% caller context
%%----------------------------------------------------------------------------- %%-----------------------------------------------------------------------------
-spec mk_spend(NetworkId, Recipient, Amount, Payload) -> Result -spec get_url(Amount, Payload) -> {ok, URL, QR_PNG} | {error, term()}
when NetworkId :: string(), when Amount :: none | pos_integer(),
Recipient :: string(), Payload :: none | binary(),
Amount :: non_neg_integer(), URL :: string(),
Payload :: binary(), QR_PNG :: binary().
Result :: {ok, URL, QR_PNG}
| {error, string()},
URL :: string(),
QR_PNG :: binary().
% @doc
% Very important: amount MUST be an integer >= 0
mk_spend(NetworkId, Recipient, Amount, Payload) -> get_url(Amount, Payload) ->
gen_server:call(?MODULE, {mk_spend, NetworkId, Recipient, Amount, Payload}). gen_server:call(?MODULE, {get_url, Amount, Payload}).
%% gen_server callbacks %% gen_server callbacks
@ -73,8 +71,8 @@ init(none) ->
{ok, InitState}. {ok, InitState}.
handle_call({mk_spend, NetworkId, Recipient, Amount, Payload}, From, State) -> handle_call({get_url, Amount, Payload}, From, State) ->
case i_mk_spend(NetworkId, Recipient, Amount, Payload, From, State) of case i_get_url(Amount, Payload, From, State) of
{ok, URL, PNG, NewState} -> {ok, URL, PNG, NewState} ->
{reply, {ok, URL, PNG}, NewState}; {reply, {ok, URL, PNG}, NewState};
Error -> Error ->
@ -106,67 +104,19 @@ terminate(_, _) ->
%% internals %% internals
%%----------------------------------------------------------------------------- %%-----------------------------------------------------------------------------
-spec i_mk_spend(NetworkId, Recipient, Amount, Payload, From, State) -> Result -spec i_get_url(Amount, Payload, From, State) -> Result
when NetworkId :: string(), when Amount :: none | pos_integer(),
Recipient :: string(), Payload :: none | binary(),
Amount :: non_neg_integer(), From :: {pid(), reference()},
Payload :: binary(), State :: state(),
From :: {pid(), reference()}, URL :: string(),
State :: state(), QR_PNG :: binary().
Result :: {ok, URL, QR_PNG, NewState} Result :: {ok, URL, QR_PNG, NewState}
| {error, string()}, | {error, term()}.
URL :: string(),
QR_PNG :: binary(),
NewState :: state().
i_mk_spend(NetworkId, Recipient, Amount, Payload, {FromPID, _}, State) i_get_url(Amount, Payload, From, State) ->
when is_integer(Amount), Amount >= 0, NetworkId = fewd:network_id(),
is_binary(Payload) -> Pubkey = fewd:pubkey(),
URL = gmgrids:encode({spend, NetworkId, Recipient}, URL = gmgrids:encode({spend, NetworkId, Pubkey},
[{amount, Amount}, [{amount, Amount}, {payload, Payload}]),
{payload, Payload}]),
URLBin = unicode:characters_to_binary(URL),
PNG = qr:encode_png(URLBin),
case i_register(Recipient, Amount, Payload, FromPID, State) of
{ok, NewState} -> {ok, URL, PNG, NewState};
Error -> Error
end;
i_mk_spend(_, _, Amount, _, _, _) when (not is_integer(Amount)) ->
{error, "non_integer_amount"};
i_mk_spend(_, _, Amount, _, _, _) when Amount < 0 ->
{error, "negative_amount"};
i_mk_spend(_, _, _, _, _, _) ->
{error, "bad_payload"}.
i_register(Recipient, Amount, Payload, FromPID, State = #s{looking_for = Patterns}) ->
SP = i_sp(Recipient, Amount, Payload),
case i_lookup(SP, State) of
not_found ->
NewPattern = {SP, FromPID},
NewPatterns = [NewPattern | Patterns],
NewState = State#s{looking_for = NewPatterns},
{ok, NewState};
{found, _} ->
{error, already_registered}
end.
%% future proofing
i_sp(Recipient, Amount, Payload) ->
{sp, Recipient, Amount, Payload}.
-spec i_lookup(SearchPattern, State) -> Result
when SearchPattern :: sp(),
State :: state(),
Result :: {found, NotifyPID :: pid()}
| not_found.
% @private look up search pattern and see if we're looking for it
i_lookup(SearchPattern, State) ->
#s{looking_for = Patterns} = State,
case lists:keyfind(SearchPattern, 1, Patterns) of
false -> not_found;
{_, Notify} -> {found, Notify}
end.

View File

@ -238,7 +238,6 @@ route(Sock, get, Route, Request, Received) ->
end; end;
route(Sock, post, Route, Request, Received) -> route(Sock, post, Route, Request, Received) ->
case Route of case Route of
<<"/grids-spend">> -> grids_spend(Sock, Request) , Received;
<<"/wfcin">> -> wfcin(Sock, Request) , Received; <<"/wfcin">> -> wfcin(Sock, Request) , Received;
_ -> fd_httpd_utils:http_err(Sock, 404) , Received _ -> fd_httpd_utils:http_err(Sock, 404) , Received
end; end;
@ -320,36 +319,6 @@ ws_echo_loop(Sock, Frames, Received) ->
error(Error) error(Error)
end. end.
%% ------------------------------
%% grids
%% ------------------------------
grids_spend(Sock, #request{enctype = json,
body = B = #{"network_id" := NetId,
"recipient" := Recipient,
"amount" := Amount,
"payload" := Payload}}) ->
tell("grids_spend good request: ~tp", [B]),
RespObj =
case fd_gridsd:mk_spend(NetId, Recipient, Amount, unicode:characters_to_binary(Payload)) of
{ok, URL, PNG} ->
#{"ok" => true,
"result" => #{"url" => URL,
"png_base64" => unicode:characters_to_list(base64:encode(PNG))}};
{error, String} ->
#{"ok" => false,
"error" => String}
end,
Body = zj:encode(RespObj),
% update cache with new context
Response = #response{headers = [{"content-type", "application/json"}],
body = Body},
fd_httpd_utils:respond(Sock, Response);
grids_spend(Sock, Request) ->
tell("grids_spend: bad request: ~tp", [Request]),
fd_httpd_utils:http_err(Sock, 400).
%% ------------------------------ %% ------------------------------
%% wfc %% wfc

View File

@ -9,7 +9,7 @@
-copyright("Peter Harpending <peterharpending@qpq.swiss>"). -copyright("Peter Harpending <peterharpending@qpq.swiss>").
-license("BSD-2-Clause-FreeBSD"). -license("BSD-2-Clause-FreeBSD").
-export([network_id/0, pubkey/0, akstr/0]). -export([network_id/0, pubkey/0]).
-export([listen/1, ignore/0]). -export([listen/1, ignore/0]).
-export([start/2, stop/1]). -export([start/2, stop/1]).
@ -17,8 +17,7 @@
network_id() -> "groot.testnet". network_id() -> "groot.testnet".
pubkey() -> pad32(<<"fewd demo">>). pubkey() -> pad32("fewd demo").
akstr() -> gmgrids:akstr(pubkey()).
pad32(Bytes) -> pad32(Bytes) ->

View File

@ -7,9 +7,6 @@
{package_id,{"otpr","fewd",{0,2,0}}}. {package_id,{"otpr","fewd",{0,2,0}}}.
{deps,[{"otpr","hakuzaru",{0,7,0}}, {deps,[{"otpr","hakuzaru",{0,7,0}},
{"otpr","qr",{0,1,0}}, {"otpr","qr",{0,1,0}},
{"otpr","gmserialization",{0,1,3}},
{"otpr","eblake2",{1,0,1}},
{"otpr","base58",{0,1,1}},
{"otpr","zj",{1,1,2}}]}. {"otpr","zj",{1,1,2}}]}.
{key_name,none}. {key_name,none}.
{a_email,"peterharpending@qpq.swiss"}. {a_email,"peterharpending@qpq.swiss"}.