starting jr controller api idiom

This commit is contained in:
2023-07-30 22:58:55 -06:00
parent c54c57b37a
commit b3eba95520
10 changed files with 4628 additions and 174 deletions
+270
View File
@@ -0,0 +1,270 @@
/**
* JR Controller
*
* Note that this is a *thread*. We put our business and storage logic within
* this thread. The reason we do that is we don't want to deal with the
* problem of conflicting concurrent writes..
*
* # Naming Conventions
*
* - `b_...` -> internal to background thread
* - `c_...` -> meant to be called/used from content script
* - `p_...` -> meant to be called/used from popup script
*
* @module
*/
//import * as awcp from './jex_include/local-awcp-0.2.1/dist/awcp.js';
export type {
// content script call/return data
// popup script call/return data
};
export {
// bg calling code
b_main
// content script api
// popup script api
};
//
//
////=============================================================================
//// TYPES
////=============================================================================
//
//
///**
// * @example
// * ```json
// * {
// * // EventData_A2w
// * "type": "to_waellet",
// * "data": {
// * // RpcCall
// * "jsonrpc": "2.0",
// * "id": "ske-connect-1",
// * "method": "connection.open",
// * "params": {
// * // Params_A2W_connection_open
// * "name": "sidekick examples",
// * "version": 1
// * }
// * }
// * }
// * ```
// *
// * @internal
// */
//type a2w_calldata
// = awcp.EventData_A2W<awcp.RpcCall<string, any>>;
// // method params
//
//
//
///**
// * Return data
// */
//type w2a_return_data
// = awcp.EventData_W2A<awcp.RpcResp<string, any>>;
//
//
//
///**
// * Type from NaCL
// */
//type nacl_keypair
// = {secretKey : Uint8Array,
// publicKey : Uint8Array};
//
//
//
///**
// * JR state
// */
//type jr_state = {keypairs: Array<nacl_keypair>};
//
//
/**
* main function for background thread
*/
async function
b_main
()
: Promise<void>
{
console.log('b_main');
//// get state
//let state: jr_state = await get_state();
//console.log(state);
//// handle messages from content or popup scripts
//browser.runtime.onMessage.addListener(bg_runtime_msg_handler);
}
//
//
//
//
///**
// * fetch the state from local storage
// *
// * if there is no state make an initial state and store it
// */
//async function
//b_get_state
// ()
// : Promise<jr_state>
//{
// console.log('jr bg get_state');
// // this may or may not have the keyword "jr_state"
// let gotten_state : object = await browser.storage.local.get();
//
// console.log('jr bg gotten_state', gotten_state);
//
// // if there is such a state, get it
// // @ts-ignore ts doesn't understand querying if a key exists
// if (!!(gotten_state.jr_state)) {
// // @ts-ignore ts doesn't understand that we have proved that the key exists
// return gotten_state.jr_state;
// }
// // otherwise return default state
// else {
// return jr_state_default();
// }
//}
//
//
//
///**
// * default state for JR
// */
//function
//jr_state_default
// ()
// : jr_state
//{
// console.log('jr_state_default');
// // if no key, generate one
// // @ts-ignore ts doesn't like that nacl is dumb. i don't like it either
// let init_keypair : nacl_keypair = nacl.sign.keyPair() as nacl_keypair;
// let default_state = { keypairs: [init_keypair] };
// console.log('jr_state_default default_state', default_state);
// return default_state;
//}
//
//
//
///**
// * wrap up bs for w2a message
// */
//function
//mk_w2a_msg_ok
// <result_t extends any>
// (method : string,
// id : string | number,
// result : result_t)
// : awcp.EventData_W2A<awcp.RpcResp_ok<string, result_t>>
//{
// return {type : "to_aepp",
// data : {jsonrpc : "2.0",
// method : method,
// id : id,
// result : result}};
//}
//
//
//
///**
// * Handle messages from either content or popup script
// *
// * Note to self: `sendResponse` is fake. Doesn't work. Instead just return the
// * response
// */
//async function
//bg_runtime_msg_handler
// (msg : {frum: 'content' | 'popup',
// data: any},
// sender : any,
// sendResponse : any)
// : Promise<w2a_return_data | popup_return_data>
//{
// //console.log('msg', msg);
// //console.log('sender', sender);
// //console.log('sendResponse', sendResponse);
//
// switch (msg.frum) {
// case 'content':
// return await bg_a2w_handler_content(msg.data as a2w_calldata, sender, sendResponse);
// case 'popup':
// return await bg_msg_handler_popup(msg.data as popup_calldata, sender, sendResponse);
// }
//}
//
//
///**
// * Handle messages from the content script
// *
// * Note to self: `sendResponse` is fake. Doesn't work. Instead just return the
// * response
// */
//async function
//bg_a2w_handler_content
// (msg : a2w_calldata,
// sender : any,
// sendResponse : any)
// : Promise<w2a_return_data>
//{
// //console.log('msg', msg);
// //console.log('sender', sender);
// //console.log('sendResponse', sendResponse);
//
// let msg_method : string = msg.data.method;
// let msg_id : string | number = msg.data.id;
//
// function w2a_ok(result_for_content_script: any) {
// return mk_w2a_msg_ok(msg_method, msg_id, result_for_content_script);
// }
//
// switch (msg.data.method) {
// case "connection.open":
// return w2a_ok({id : "jr",
// name : "JR",
// networkId : "ae_uat",
// origin : "foobar",
// type : "extension"});
// case "address.subscribe":
// return w2a_ok({subscription : ["connected"],
// address : {current : {"boobs": {}},
// connected : {}}});
// }
//}
//
//
//
//
//type popup_calldata
// = 'init';
//
//
//type popup_return_data
// = 'die';
//
//
///**
// * Handle messages from the popup
// */
//async function
//bg_msg_handler_popup
// (msg : popup_calldata,
// sender : any,
// sendResponse : any)
// : Promise<popup_return_data>
//{
// console.log('jr bg_msg_handler_popup msg', msg);
// return 'die';
//}
+8 -114
View File
@@ -1,119 +1,13 @@
/**
* JR Controller
* This is the "background script", which just calls b_lib:main/0
*
* Note that this is a *thread*. We put our business and storage logic within
* this thread. The reason we do that is we don't want to deal with the
* problem of conflicting concurrent writes..
*
* @module
* b_lib is the background "library". I want the popup and content script to be
* able to "call" the background script (really there's a rewrite layer there
* so the entire IPC messaging protocol is in one file). I don't want to fire the
* missiles whenever say the popup script loads the "background library", so
* the background "script" is a separate file.
*/
export {
};
import {b_main} from './b_lib.js';
import * as awcp from './jex_include/local-awcp-0.2.1/dist/awcp.js';
/**
* @example
* ```json
* {
* // EventData_A2w
* "type": "to_waellet",
* "data": {
* // RpcCall
* "jsonrpc": "2.0",
* "id": "ske-connect-1",
* "method": "connection.open",
* "params": {
* // Params_A2W_connection_open
* "name": "sidekick examples",
* "version": 1
* }
* }
* }
* ```
*/
// method params
type a2w_calldata = awcp.EventData_A2W<awcp.RpcCall<string, any>>;
/**
* wrap up bs for w2a message
*/
function
mk_w2a_msg_ok
<result_t extends any>
(method : string,
id : string | number,
result : result_t)
: awcp.EventData_W2A<awcp.RpcResp_ok<string, result_t>>
{
return {type : "to_aepp",
data : {jsonrpc : "2.0",
method : method,
id : id,
result : result}};
}
/**
* Handle messages from the content script
*
* Note to self: `sendResponse` is fake. Doesn't work. Instead just return the
* response
*/
async function
bg_a2w_handler
(msg: a2w_calldata, sender: any, sendResponse: any)
: Promise<void>
{
//console.log('msg', msg);
//console.log('sender', sender);
//console.log('sendResponse', sendResponse);
let msg_method : string = msg.data.method;
let msg_id : string | number = msg.data.id;
function w2a_ok(result_for_content_script: any) {
return mk_w2a_msg_ok(msg_method, msg_id, result_for_content_script);
}
switch (msg.data.method) {
case "connection.open":
return w2a_ok({id : "jr",
name : "JR",
networkId : "ae_uat",
origin : "foobar",
type : "extension"});
case "address.subscribe":
return w2a_ok({subscription : ["connected"],
address : {current : {"boobs": {}},
connected : {}}});
}
}
/**
* main function for background thread
*/
async function
jr_bg_main
()
: Promise<void>
{
console.log('jr_bg_main line 106 hello');
// handle messages from content script
browser.runtime.onMessage.addListener(bg_a2w_handler);
// TODO: ok so next step is to have startup hook
// try to fetch keys from storage
// if no key, generate one
let keypair = nacl.sign.keyPair();
console.log('jr_bg_main 112 keypair', keypair);
}
jr_bg_main();
b_main();
+118
View File
@@ -0,0 +1,118 @@
/**
* JR Content Script Library
*
* Notes:
*
* 1. This is a module.
* 2. All this does is relay messages between here and the background script
* (i.e. application controller).
*
* @module
*/
export {
c_main
};
/**
* Main function
*/
async function
c_main
()
{
console.log('c_main');
//// relay page messages back to the controller
//window.addEventListener('message', a2w_handler);
//// spam detect
//spam_detect();
}
//
//
//
//let detect_msg = {type : "to_aepp",
// data : {jsonrpc : "2.0",
// method : "connection.announcePresence",
// params : {id : "jr",
// name : "JR",
// networkId : "ae_uat",
// origin : "foobar",
// type : "extension"}}};
//
///**
// * Spam the "connection.announcePresence" (awcp terminology: "detect") message
// */
//async function
//spam_detect
// ()
//{
// while (true) {
// window.postMessage(detect_msg);
// await sleep(3000);
// }
//}
//
//
//
///**
// * Hack from stack overflow somewhere to sleep for the given number of ms
// */
//async function
//sleep
// (ms: number)
// : Promise<void>
//{
// return new Promise(resolve => setTimeout(resolve, ms));
//}
//
//
//
///**
// * Relays messages from page scripts to the background script
// */
//async function
//a2w_handler
// (msg: {data: {type? : "to_aepp" | "to_waellet"}})
//{
//
// //console.error('JR: a2w_handler', {msg: msg});
// function onSuccessCase(response_from_bg: any) {
// console.error('JR A2w success case', response_from_bg);
// window.postMessage(response_from_bg);
// }
// function onErrorCase(error: any) {
// console.error('JR: error from controller', error);
// }
//
// // branch
// // all messages are visible to us
// // if the message is for the wallet
// // send it to the wallet
// // otherwise ignore it
// if ("to_waellet" === msg.data.type) {
// console.error('JR: WAEEEEEEE');
// browser.runtime
// .sendMessage({frum: 'content',
// data: msg.data})
// .then(onSuccessCase,
// onErrorCase);
// //window.postMessage(response);
// }
// // otherwise ignore
//}
//
//
//
/////**
//// * Relays messages from background scripts to the page script
//// */
////function
////w2a_handler
//// (msg: any)
////{
//// window.postMessage(msg);
////}
//
+26 -39
View File
@@ -3,16 +3,18 @@
*
* Notes:
*
* 1. This is not loaded as a module, which means it has limited permissions.
* In particular, asynchronous calls are 1000x more annoying.
* 1. This is not a module, so calling async code is super annoying and
* everything has to be in script order.
* 2. All this does is relay messages between here and the background script
* (i.e. application controller).
*
* This is more or less a finished script. Doesn't need the "api call" idiom
* that the popup <-> controller IPC needs.
*
* @module
*/
let detect_msg = {type : "to_aepp",
data : {jsonrpc : "2.0",
method : "connection.announcePresence",
@@ -26,12 +28,12 @@ let detect_msg = {type : "to_aepp",
* Spam the "connection.announcePresence" (awcp terminology: "detect") message
*/
async function
spam_detect
c_spam_detect
()
{
while (true) {
window.postMessage(detect_msg);
await sleep(3000);
await c_sleep(3000);
}
}
@@ -41,7 +43,7 @@ spam_detect
* Hack from stack overflow somewhere to sleep for the given number of ms
*/
async function
sleep
c_sleep
(ms: number)
: Promise<void>
{
@@ -51,20 +53,21 @@ sleep
/**
* Relays messages from page scripts to the background script
* Relays messages between page scripts and the background script
*/
async function
a2w_handler
c_a2w_handler
(msg: {data: {type? : "to_aepp" | "to_waellet"}})
: Promise<void>
{
//console.error('JR: a2w_handler', {msg: msg});
function onSuccessCase(response_from_bg: any) {
console.error('JR A2w success case', response_from_bg);
console.log('jr: c_a2w_handler success ', response_from_bg);
window.postMessage(response_from_bg);
}
function onErrorCase(error: any) {
console.error('JR: error from controller', error);
console.error('jr: c_a2w_handler: error from controller', error);
}
// branch
@@ -73,47 +76,31 @@ a2w_handler
// send it to the wallet
// otherwise ignore it
if ("to_waellet" === msg.data.type) {
console.error('JR: WAEEEEEEE');
browser.runtime.sendMessage(msg.data).then(
onSuccessCase,
onErrorCase
);
//window.postMessage(response);
console.log('jr: c_a2w_handler relaying message', msg.data);
browser.runtime
.sendMessage({frum: 'content',
data: msg.data})
.then(onSuccessCase,
onErrorCase);
}
// otherwise ignore
}
///**
// * Relays messages from background scripts to the page script
// */
//function
//w2a_handler
// (msg: any)
//{
// window.postMessage(msg);
//}
/**
* Main function
*/
async function
jr_content_main
c_main
()
{
console.log('c_main');
// relay page messages back to the controller
window.addEventListener('message', a2w_handler);
// relay messages back and forth between page script and controller
window.addEventListener('message', c_a2w_handler);
//// relay controller messages back to page
//browser.runtime.onMessage.addListener(w2a_handler);
// spam detect
spam_detect();
// spam the detect message
c_spam_detect();
}
jr_content_main();
c_main()
-12
View File
@@ -1,12 +0,0 @@
/**
* Definitions of messages that are passed between process A and process B in
* JR. Example: how the content script talks to the background script.
*
* @module
*/
/**
* this is the message sent from the content script to the background script
* when a page script requests
*/
type c2b_addr_subscribe = "address_subscribe";
+75 -4
View File
@@ -2,17 +2,88 @@
* This is the script for the popup window
*/
main();
p_main();
/**
* runs whenever the popup opens
*
* also whenever a button is clicked it appears the page re-renders which
* re-runs this
*
* suggests the following structure:
*
* 1. Contact the background script and say "I'm a popup".
* 2. Get all relevant data.
* 3. Render
*
* On click:
*
* 1. Send relevant information back to background script
* 2. Epstein
*/
async function
main
p_main
()
: Promise<void>
{
let scratch = document.getElementById('scratch')!;
scratch.innerText += 'line 17 hello\n';
//let scratch = document.getElementById('scratch')!;
//scratch.innerText += 'line 17 hello\n';
console.log('popup main');
//function onSuccessCase(response_from_bg: any) {
// console.log('jr popup response from background script success', response_from_bg);
//}
//function onErrorCase(error_from_bg: any) {
// console.log('jr popup response from background script error', error_from_bg);
//}
//browser.runtime
// .sendMessage({frum: 'popup',
// data: 'init'})
// .then(onSuccessCase,
// onErrorCase);
//// add hooks for each button
//document.getElementById('generate-btn')!.addEventListener('click', onclick_generate);
//document.getElementById('faert-btn')!.addEventListener('click', onclick_faert);
////document.getElementById('seed-btn')!.addEventListener('click', onclick_seed);
}
///**
// * Runs when the user clicks the "generate" button
// */
//async function
//onclick_generate
// ()
// : Promise<void>
//{
// console.log('onclick_generate');
//}
//
//
//
///**
// * Runs when the user clicks the "recover from faert phrase" button
// */
//async function
//onclick_faert
// ()
// : Promise<void>
//{
// console.log('onclick_faert');
//}
//
//
//
/////**
//// * Runs when the user clicks the "recover from seed phrase" button
//// */
////async function
////onclick_seed
//// ()
////{
//// console.log('onclick_seed');
////}