From 3343dcf137b01eae54df2887c8fc3fed17baca32 Mon Sep 17 00:00:00 2001 From: Peter Harpending Date: Mon, 29 Dec 2025 14:04:03 -0800 Subject: [PATCH] basic grids demo seems to work... --- README.md | 40 +++++++- priv/skel/css.css | 0 priv/skel/html.html | 20 ++++ priv/skel/ts.ts | 9 ++ priv/static/grids-basic.html | 64 ++++++++++++ priv/static/index.html | 1 + priv/static/js/dist/grids-basic.d.ts | 29 ++++++ priv/static/js/dist/grids-basic.js | 83 ++++++++++++++++ priv/static/js/dist/grids-basic.js.map | 1 + priv/static/js/dist/libfewd.js.map | 2 +- priv/static/js/dist/wfc.js.map | 2 +- priv/static/js/ts/grids-basic.ts | 131 +++++++++++++++++++++++++ src/fd_gridsd.erl | 64 ++++++------ src/fd_httpd_client.erl | 31 ++++++ src/fewd.erl | 2 +- zomp.meta | 3 + 16 files changed, 445 insertions(+), 37 deletions(-) create mode 100644 priv/skel/css.css create mode 100644 priv/skel/html.html create mode 100644 priv/skel/ts.ts create mode 100644 priv/static/grids-basic.html create mode 100644 priv/static/js/dist/grids-basic.d.ts create mode 100644 priv/static/js/dist/grids-basic.js create mode 100644 priv/static/js/dist/grids-basic.js.map create mode 100644 priv/static/js/ts/grids-basic.ts diff --git a/README.md b/README.md index b4aa821..9aa3855 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,43 @@ -# 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 important despite my wishes. -# notes +Building/Running +--------------------------------------------------------------------- -## goal queue +### Prereqs +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 +``` diff --git a/priv/skel/css.css b/priv/skel/css.css new file mode 100644 index 0000000..e69de29 diff --git a/priv/skel/html.html b/priv/skel/html.html new file mode 100644 index 0000000..4efa876 --- /dev/null +++ b/priv/skel/html.html @@ -0,0 +1,20 @@ + + + + + FIXME + + + +
+
+ Home +
+
+ +
+

FEWD: FIXME

+ +
+ + diff --git a/priv/skel/ts.ts b/priv/skel/ts.ts new file mode 100644 index 0000000..fd79f2c --- /dev/null +++ b/priv/skel/ts.ts @@ -0,0 +1,9 @@ +/** + * Title: Title + * Description: Description + * Author: Peter Harpending + * Date: YYYY-MM-DD + * Last-Updated: YYYY-MM-DD + * + * @module + */ diff --git a/priv/static/grids-basic.html b/priv/static/grids-basic.html new file mode 100644 index 0000000..a8bff0c --- /dev/null +++ b/priv/static/grids-basic.html @@ -0,0 +1,64 @@ + + + + + Basic GRIDS Demo + + + +
+
+ Home +
+
+ +
+

FEWD: GRIDS DEMO

+ + +

Making a Spend

+ + + +
+ + + +
+ + + +
+ + + +
+ + +
+ + +
+ +
+ + + + diff --git a/priv/static/index.html b/priv/static/index.html index 06d33ab..e53d199 100644 --- a/priv/static/index.html +++ b/priv/static/index.html @@ -17,6 +17,7 @@ diff --git a/priv/static/js/dist/grids-basic.d.ts b/priv/static/js/dist/grids-basic.d.ts new file mode 100644 index 0000000..6ae61d1 --- /dev/null +++ b/priv/static/js/dist/grids-basic.d.ts @@ -0,0 +1,29 @@ +/** + * Title: GRIDS Basic Page Script + * Description: Page Script for /grids-basic.html + * Author: Peter Harpending + * Date: 2025-12-29 + * Last-Updated: 2025-12-29 + * + * @module + */ +/** + * Runs on page load + */ +declare function main(): Promise; +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; +type Safe = { + 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>; diff --git a/priv/static/js/dist/grids-basic.js b/priv/static/js/dist/grids-basic.js new file mode 100644 index 0000000..d338d7c --- /dev/null +++ b/priv/static/js/dist/grids-basic.js @@ -0,0 +1,83 @@ +"use strict"; +/** + * Title: GRIDS Basic Page Script + * Description: Page Script for /grids-basic.html + * Author: Peter Harpending + * 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 \ No newline at end of file diff --git a/priv/static/js/dist/grids-basic.js.map b/priv/static/js/dist/grids-basic.js.map new file mode 100644 index 0000000..84466f6 --- /dev/null +++ b/priv/static/js/dist/grids-basic.js.map @@ -0,0 +1 @@ +{"version":3,"file":"grids-basic.js","sourceRoot":"","sources":["../ts/grids-basic.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/priv/static/js/dist/libfewd.js.map b/priv/static/js/dist/libfewd.js.map index 83dbe5c..de16114 100644 --- a/priv/static/js/dist/libfewd.js.map +++ b/priv/static/js/dist/libfewd.js.map @@ -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,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"} \ No newline at end of file +{"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"} \ No newline at end of file diff --git a/priv/static/js/dist/wfc.js.map b/priv/static/js/dist/wfc.js.map index ca3d152..c9cb10c 100644 --- a/priv/static/js/dist/wfc.js.map +++ b/priv/static/js/dist/wfc.js.map @@ -1 +1 @@ -{"version":3,"file":"wfc.js","sourceRoot":"","sources":["../ts/wfc.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"wfc.js","sourceRoot":"","sources":["../ts/wfc.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/priv/static/js/ts/grids-basic.ts b/priv/static/js/ts/grids-basic.ts new file mode 100644 index 0000000..f1e8390 --- /dev/null +++ b/priv/static/js/ts/grids-basic.ts @@ -0,0 +1,131 @@ +/** + * Title: GRIDS Basic Page Script + * Description: Page Script for /grids-basic.html + * Author: Peter Harpending + * 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 +{ + // 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 = 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 = {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> +{ + // 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 = + {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; + 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; +} diff --git a/src/fd_gridsd.erl b/src/fd_gridsd.erl index c969629..3cd0486 100644 --- a/src/fd_gridsd.erl +++ b/src/fd_gridsd.erl @@ -9,7 +9,7 @@ -export([ %% caller context - get_url/2, + mk_spend/4, %% api start_link/0, @@ -40,18 +40,20 @@ %% caller context %%----------------------------------------------------------------------------- --spec get_url(Amount, Payload) -> Result - when Amount :: non_neg_integer(), - Payload :: binary(), - Result :: {ok, URL, QR_PNG} - | {error, term()}, - URL :: string(), - QR_PNG :: binary(). +-spec mk_spend(NetworkId, Recipient, Amount, Payload) -> Result + when NetworkId :: string(), + Recipient :: string(), + Amount :: non_neg_integer(), + Payload :: binary(), + Result :: {ok, URL, QR_PNG} + | {error, string()}, + URL :: string(), + QR_PNG :: binary(). % @doc % Very important: amount MUST be an integer >= 0 -get_url(Amount, Payload) -> - gen_server:call(?MODULE, {get_url, Amount, Payload}). +mk_spend(NetworkId, Recipient, Amount, Payload) -> + gen_server:call(?MODULE, {mk_spend, NetworkId, Recipient, Amount, Payload}). %% gen_server callbacks @@ -71,8 +73,8 @@ init(none) -> {ok, InitState}. -handle_call({get_url, Amount, Payload}, From, State) -> - case i_get_url(Amount, Payload, From, State) of +handle_call({mk_spend, NetworkId, Recipient, Amount, Payload}, From, State) -> + case i_mk_spend(NetworkId, Recipient, Amount, Payload, From, State) of {ok, URL, PNG, NewState} -> {reply, {ok, URL, PNG}, NewState}; Error -> @@ -104,22 +106,22 @@ terminate(_, _) -> %% internals %%----------------------------------------------------------------------------- --spec i_get_url(Amount, Payload, From, State) -> Result - when Amount :: non_neg_integer(), - Payload :: binary(), - From :: {pid(), reference()}, - State :: state(), - Result :: {ok, URL, QR_PNG, NewState} - | {error, term()}, - URL :: string(), - QR_PNG :: binary(), - NewState :: state(). +-spec i_mk_spend(NetworkId, Recipient, Amount, Payload, From, State) -> Result + when NetworkId :: string(), + Recipient :: string(), + Amount :: non_neg_integer(), + Payload :: binary(), + From :: {pid(), reference()}, + State :: state(), + Result :: {ok, URL, QR_PNG, NewState} + | {error, string()}, + URL :: string(), + QR_PNG :: binary(), + NewState :: state(). -i_get_url(Amount, Payload, {FromPID, _}, State) +i_mk_spend(NetworkId, Recipient, Amount, Payload, {FromPID, _}, State) when is_integer(Amount), Amount >= 0, is_binary(Payload) -> - NetworkId = fewd:network_id(), - Recipient = fewd:akstr(), URL = gmgrids:encode({spend, NetworkId, Recipient}, [{amount, Amount}, {payload, Payload}]), @@ -129,12 +131,12 @@ i_get_url(Amount, Payload, {FromPID, _}, State) {ok, NewState} -> {ok, URL, PNG, NewState}; Error -> Error end; -i_get_url(Amount, _, _, _) when (not is_integer(Amount)) -> - {error, non_integer_amount}; -i_get_url(Amount, _, _, _) when Amount < 0 -> - {error, negative_amount}; -i_get_url(_, _, _, _) -> - {error, bad_payload}. +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}) -> diff --git a/src/fd_httpd_client.erl b/src/fd_httpd_client.erl index e163dae..9c0b9c1 100644 --- a/src/fd_httpd_client.erl +++ b/src/fd_httpd_client.erl @@ -238,6 +238,7 @@ route(Sock, get, Route, Request, Received) -> end; route(Sock, post, Route, Request, Received) -> case Route of + <<"/grids-spend">> -> grids_spend(Sock, Request) , Received; <<"/wfcin">> -> wfcin(Sock, Request) , Received; _ -> fd_httpd_utils:http_err(Sock, 404) , Received end; @@ -319,6 +320,36 @@ ws_echo_loop(Sock, Frames, Received) -> error(Error) 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 diff --git a/src/fewd.erl b/src/fewd.erl index 21b86a7..0647131 100644 --- a/src/fewd.erl +++ b/src/fewd.erl @@ -17,7 +17,7 @@ network_id() -> "groot.testnet". -pubkey() -> pad32("fewd demo"). +pubkey() -> pad32(<<"fewd demo">>). akstr() -> gmgrids:akstr(pubkey()). diff --git a/zomp.meta b/zomp.meta index 24e5499..e87c40b 100644 --- a/zomp.meta +++ b/zomp.meta @@ -7,6 +7,9 @@ {package_id,{"otpr","fewd",{0,2,0}}}. {deps,[{"otpr","hakuzaru",{0,7,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}}]}. {key_name,none}. {a_email,"peterharpending@qpq.swiss"}.