diff --git a/jrx/pages/popup.html b/jrx/pages/popup.html
index a96eedc..d32b246 100644
--- a/jrx/pages/popup.html
+++ b/jrx/pages/popup.html
@@ -141,6 +141,30 @@
+
+
+
+
+  |
+
+ SEND SOMEONE MONEY
+ |
+
+
+
+
+
+
+
+
diff --git a/jrx/src/popup.ts b/jrx/src/popup.ts
index caf54e8..082f8dd 100644
--- a/jrx/src/popup.ts
+++ b/jrx/src/popup.ts
@@ -6,6 +6,10 @@ import * as b_lib from './b_lib.js';
p_main();
+let EXPLORER_URL = 'https://explorer.qpq.swiss';
+
+let active_account_next_nonce = 0;
+
/**
* runs whenever the popup opens
*
@@ -33,6 +37,8 @@ p_main
console.log('popup main');
await pi_repop();
+ let pdata = await b_lib.p_get_data();
+
// add unique name for default
let unique_name: string = await b_lib.p_get_unique_name();
@@ -70,6 +76,73 @@ p_main
document
.getElementById('faert-btn')!
.addEventListener('click', onclick_gphrase);
+
+ // spend
+ let onclick_spend =
+ async function () {
+ console.log('onclick_spend');
+ // grab recipient address
+ // @ts-ignore fuck off it's my website
+ let recip_address = document.getElementById('spend-recipient').value;
+ // grab recipient amount and parse
+ // @ts-ignore fuck off it's my website
+ let amount = parseInt(document.getElementById('spend-amount').value);
+ let source = active_account(pdata);
+
+ console.log('onclick_spend params', {recipient: recip_address, amount: amount, source: source});
+
+ // hack
+ if ('' === source) {
+ console.log('onclick_spend no active key');
+ // HACK: otherwise populate field with no key
+ let spend_result_p = document.getElementById('spend-result')!;
+ spend_result_p.innerHTML = 'ERROR: no active key';
+ }
+ else {
+ let maybe_hash = await do_spend(source, recip_address, amount);
+ console.log('onclick_spend maybe_hash', maybe_hash);
+ if (maybe_hash.ok) {
+ // @ts-ignore fuck off
+ let tx_hash = maybe_hash.tx_hash;
+ // @ts-ignore fuck off
+ let spend_result_p = document.getElementById('spend-result')!;
+ let spend_result_a = document.createElement('a')!;
+ spend_result_a.href = EXPLORER_URL + '/transactions/' + tx_hash;
+ spend_result_a.innerHTML = tx_hash;
+ spend_result_p.appendChild(spend_result_a);
+ }
+ else {
+ // @ts-ignore fuck off
+ let reason = maybe_hash.reason;
+ let spend_result_p = document.getElementById('spend-result')!;
+ spend_result_p.innerHTML = 'ERROR: ' + reason;
+ }
+ }
+ };
+ document
+ .getElementById('spend-btn')!
+ .addEventListener('click', onclick_spend);
+}
+
+function
+active_account
+ (pdata: b_lib.p_data)
+ : string
+{
+ // type p_data
+ // = {rich_pubkeys: Array,
+ // netid_cur : string,
+ // netids_alt : Array};
+ // type p_rich_pubkey
+ // = {akstr : string,
+ // active : boolean,
+ // name : string};
+ for (let rkp of pdata.rich_pubkeys) {
+ if (rkp.active)
+ return rkp.akstr;
+ }
+
+ return '';
}
@@ -216,8 +289,17 @@ pi_repop
pi_balance(this_rkp.akstr).then(
function(maybe_balance) {
// if there is a balance, show it in green
+ // also make nonce nonce if account is active
if (maybe_balance.ok)
{
+ if (this_rkp.active) {
+ // @ts-ignore fuck off i know what i'm doing
+ let nonce = maybe_balance.nonce;
+ active_account_next_nonce = nonce;
+ }
+
+
+
let greentext = document.createElement('span');
greentext.classList.add('balance-found');
// @ts-ignore fuck off i know what i'm doing
@@ -226,8 +308,12 @@ pi_repop
bal_li.appendChild(greentext);
}
// if not, show reason and make it red
+ // also make nonce 0 if account is active
else
{
+ if (this_rkp.active) {
+ active_account_next_nonce = 0;
+ }
let redtext = document.createElement('span');
redtext.classList.add('balance-not-found');
// @ts-ignore fuck off i know what i'm doing
@@ -313,20 +399,134 @@ pi_repop
}
-//async function
-//mk_spend
-// (source : string,
-// recipient : string,
-// amount : number)
-//{
-// let nonce: number = await get_nonce(source);
-//}
-//
-//async function
-//get_nonce
-// (source: string)
-//{
-//}
+async function
+do_spend
+ (source : string,
+ recipient : string,
+ amount : number)
+ : Promise< {ok : true,
+ tx_hash : string}
+ | {ok : false,
+ reason : string}
+ >
+{
+ console.log('popup do_spend', {source: source, recipient: recipient, amount: amount});
+ let maybe_spendtx = await mk_spend(source, recipient, amount);
+ if (maybe_spendtx.ok) {
+ return await post_spend(maybe_spendtx.tx);
+ }
+ else {
+ // @ts-ignore fuck off
+ return maybe_spendtx;
+ }
+}
+
+async function
+post_spend
+ (tx: string)
+ : Promise< {ok : true,
+ tx_hash : string}
+ | {ok : false,
+ reason : string}
+ >
+{
+ console.log('popup post_spend', tx);
+ let req_obj = {tx: tx};
+ let req_body = JSON.stringify(req_obj, undefined, 4);
+ let endpoint_init_url = 'https://demonet.qpq.swiss/v2';
+ let this_endpoint = endpoint_init_url + '/transactions';
+ // fetch: https://developer.mozilla.org/en-US/docs/Web/API/fetch
+ let response = await fetch(this_endpoint, {method: 'POST', body: req_body});
+ let return_data = await response.json();
+ console.log('popup post_spend return data', return_data);
+ // 200 = ok
+ // 400 = bad tx
+ switch (response.status) {
+ case 200:
+ // get the hash
+ // @ts-ignore talking to foreign api
+ return {ok: true, tx_hash: return_data.tx_hash};
+ // wtf
+ default:
+ // @ts-ignore talking to foreign api
+ return {ok: false, reason: return_data.reason};
+ }
+}
+let MIN_FEE = 17000;
+
+async function
+mk_spend
+ (source : string,
+ recipient : string,
+ amount : number)
+ : Promise< {ok : true,
+ tx : string}
+ | {ok : false,
+ reason : string}
+ >
+{
+ console.log('popup mk_spend', {source: source, recipient: recipient, amount: amount});
+ let nonce: number = active_account_next_nonce;
+ let req_obj = {recipient_id : recipient,
+ amount : amount,
+ fee : MIN_FEE,
+ ttl : 0,
+ sender_id : source,
+ nonce : nonce,
+ payload : ''};
+ console.log('popup mk_spend req_obj', req_obj);
+ let req_body = JSON.stringify(req_obj, undefined, 4);
+ console.log('popup mk_spend req_body', req_body);
+
+ let endpoint_init_url = 'https://demonet.qpq.swiss/v2';
+ let this_endpoint = endpoint_init_url + '/debug/transactions/spend';
+
+ // fetch: https://developer.mozilla.org/en-US/docs/Web/API/fetch
+ let response = await fetch(this_endpoint, {method: 'POST', body: req_body, headers: [['Content-Type', 'application/json']]});
+ let return_data = await response.json();
+ console.log('popup mk_spend return data', return_data);
+
+ // 200 = ok
+ // 400 = pubkey malformed
+ // 404 = account dne
+ switch (response.status) {
+ case 200:
+ // get the nonce
+ // @ts-ignore talking to foreign api
+ return {ok: true, tx: return_data.tx};
+ // wtf
+ default:
+ // @ts-ignore talking to foreign api
+ return {ok: false, reason: return_data.reason};
+ }
+}
+
+async function
+get_nonce
+ (source: string)
+ : Promise
+{
+ console.log('popup get_nonce', source);
+ let endpoint_init_url = 'https://demonet.qpq.swiss/v2';
+ let this_endpoint = endpoint_init_url + '/accounts/' + source;
+ // fetch: https://developer.mozilla.org/en-US/docs/Web/API/fetch
+ let response = await fetch(this_endpoint);
+ // 200 = ok
+ // 400 = pubkey malformed
+ // 404 = account dne
+ switch (response.status) {
+ case 200:
+ // unstringify the body
+ let return_data = await response.json();
+ console.log('popup get_nonce return data', return_data);
+ // get the nonce
+ // @ts-ignore talking to foreign api
+ return return_data.nonce;
+ // wtf
+ default:
+ return 0;
+ }
+}
/**
* get account balance of ak_... str
@@ -335,14 +535,14 @@ async function
pi_balance
(akstr : string)
: Promise< {ok : true,
- balance : string}
+ balance : string,
+ nonce : number}
| {ok : false,
reason : string}
>
{
let endpoint_init_url = 'https://demonet.qpq.swiss/v2';
let this_endpoint = endpoint_init_url + '/accounts/' + akstr;
- let input_params = {pubkey: akstr};
// fetch: https://developer.mozilla.org/en-US/docs/Web/API/fetch
let response = await fetch(this_endpoint);
// 200 = ok
@@ -357,7 +557,8 @@ pi_balance
// @ts-ignore talking to foreign api
let balance = return_data.balance.toString();
return {ok : true,
- balance : balance};
+ balance : balance,
+ nonce : return_data.nonce};
// pubkey malformed
case 400:
return {ok : false,