ready for zx message sign demo

This commit is contained in:
2022-11-27 00:12:15 -07:00
parent c3194b1ec2
commit 3ddca3db2f
11 changed files with 451 additions and 85 deletions
+1 -1
View File
@@ -1,3 +1,3 @@
# awcp (package documentation) # awcp (package documentation)
Please click the word "(Documentation)" in the sidebar Please click the word "Documentation" in the sidebar
+178 -15
View File
@@ -206,7 +206,7 @@
*/ */
// TODONE: enumerate RPC errors // TODONE: enumerate RPC errors
// TODO: examples // TODONE: examples
// TODO: transaction.sign and propagate // TODO: transaction.sign and propagate
// TODO: constants for method names // TODO: constants for method names
@@ -529,7 +529,6 @@ type RpcCall
* and I hit "deny". This is what was sent back. Code `4` corresponds to * and I hit "deny". This is what was sent back. Code `4` corresponds to
* {@link ERROR_CODE_RpcRejectedByUserError}. * {@link ERROR_CODE_RpcRejectedByUserError}.
* *
* @example
* ```ts * ```ts
* // layer 3: RPC * // layer 3: RPC
* {jsonrpc : "2.0", * {jsonrpc : "2.0",
@@ -756,7 +755,7 @@ type Params_A2W_connection_open
/** /**
* Result type of "connection.open" call * Result type of "connection.open" call
* *
* Same as `Params_W2A_connection_open` empirically * Same as {@link Params_W2A_connection_announcePresence} empirically
* *
* (layer 4) * (layer 4)
* *
@@ -1076,6 +1075,34 @@ type EventData_A2W_address_subscribe
* } * }
* } * }
* ``` * ```
*
* @example
* Case of many keypairs, the current one will be in `current`.
* ```json
* {
* "type": "to_aepp",
* "data": {
* "jsonrpc": "2.0",
* "id": "ske-address-1",
* "method": "address.subscribe",
* "result": {
* "subscription": [
* "connected"
* ],
* "address": {
* "current": {
* "ak_2RT9RPbcX8RtjBpMWqsKtVRVKASAbj8V4c3f7cCdJfuVdihhyL": {}
* },
* "connected": {
* "ak_sMM2sUiyeBeMiRAj8viHVCVDxevmCacALhoHdrkobyhoqnR85": {},
* "ak_o355SAx4n1V6xbrYv4Zaxm7GAYaZwEFXwgKBVEQTSm8MPnwjn": {},
* "ak_2Up7dDMVBbPc4xAequf41zyzBqwWpUcVTYvcGF1ApAcCy7nGfA": {}
* }
* }
* }
* }
* }
* ```
*/ */
type EventData_W2A_address_subscribe type EventData_W2A_address_subscribe
= EventData_W2A<RpcResp_W2A_address_subscribe>; = EventData_W2A<RpcResp_W2A_address_subscribe>;
@@ -1092,6 +1119,15 @@ type EventData_W2A_address_subscribe
* If `returnSigned` is `false`, then Superhero will propagate the transaction. * If `returnSigned` is `false`, then Superhero will propagate the transaction.
* *
* (layer 4) * (layer 4)
*
* @example
* ```json
* {
* "tx": "tx_+FgMAaEBuzbuuWjOzR7ecjOY8+u7HdNk0KoxTQcCDerZELEQ+UShAXtm5sMFBwg25Ol5IFI9w+pZy7/YbFi6BwPqi80KuKdsCoYPJvVhyAAAAYdoYWluYW5h9uAnNQ==",
* "returnSigned": true,
* "networkId": "ae_uat"
* }
* ```
*/ */
type Params_A2W_tx_sign_noprop type Params_A2W_tx_sign_noprop
= {tx : string, = {tx : string,
@@ -1104,6 +1140,11 @@ type Params_A2W_tx_sign_noprop
* Success result type for "transaction.sign" (do not propagate) * Success result type for "transaction.sign" (do not propagate)
* *
* (layer 4) * (layer 4)
*
* @example
* {
* "signedTransaction": "tx_+KILAfhCuEDxWnvffMvyrkFWnrImYej38rh99vM9f6pORl/yWTvU97nvUcY8/ck8lgtPA8w5odGSDb9LGY/JSZXsmsXhgKkHuFr4WAwBoQG7Nu65aM7NHt5yM5jz67sd02TQqjFNBwIN6tkQsRD5RKEBe2bmwwUHCDbk6XkgUj3D6lnLv9hsWLoHA+qLzQq4p2wKhg8m9WHIAAABh2hhaW5hbmF7X54G"
* }
*/ */
type Result_W2A_tx_sign_noprop type Result_W2A_tx_sign_noprop
= {signedTransaction : string}; = {signedTransaction : string};
@@ -1113,6 +1154,20 @@ type Result_W2A_tx_sign_noprop
* Request type for "transaction.sign" (do not propagate) * Request type for "transaction.sign" (do not propagate)
* *
* (layer 3) * (layer 3)
*
* @example
* ```json
* {
* "jsonrpc": "2.0",
* "id": "sk-tx-sign-1",
* "method": "transaction.sign",
* "params": {
* "tx": "tx_+FgMAaEBuzbuuWjOzR7ecjOY8+u7HdNk0KoxTQcCDerZELEQ+UShAXtm5sMFBwg25Ol5IFI9w+pZy7/YbFi6BwPqi80KuKdsCoYPJvVhyAAAAYdoYWluYW5h9uAnNQ==",
* "returnSigned": true,
* "networkId": "ae_uat"
* }
* }
* ```
*/ */
type RpcCall_A2W_tx_sign_noprop type RpcCall_A2W_tx_sign_noprop
= RpcCall<"transaction.sign", = RpcCall<"transaction.sign",
@@ -1124,6 +1179,18 @@ type RpcCall_A2W_tx_sign_noprop
* Response type for "transaction.sign" (do not propagate) * Response type for "transaction.sign" (do not propagate)
* *
* (layer 3) * (layer 3)
*
* @example
* ```json
* {
* "jsonrpc": "2.0",
* "id": "sk-tx-sign-1",
* "method": "transaction.sign",
* "result": {
* "signedTransaction": "tx_+KILAfhCuEDxWnvffMvyrkFWnrImYej38rh99vM9f6pORl/yWTvU97nvUcY8/ck8lgtPA8w5odGSDb9LGY/JSZXsmsXhgKkHuFr4WAwBoQG7Nu65aM7NHt5yM5jz67sd02TQqjFNBwIN6tkQsRD5RKEBe2bmwwUHCDbk6XkgUj3D6lnLv9hsWLoHA+qLzQq4p2wKhg8m9WHIAAABh2hhaW5hbmF7X54G"
* }
* }
* ```
*/ */
type RpcResp_W2A_tx_sign_noprop type RpcResp_W2A_tx_sign_noprop
= RpcResp<"transaction.sign", = RpcResp<"transaction.sign",
@@ -1135,6 +1202,23 @@ type RpcResp_W2A_tx_sign_noprop
* Event data for aepp-to-waellet "transaction.sign" (do not propagate) message * Event data for aepp-to-waellet "transaction.sign" (do not propagate) message
* *
* (layer 2) * (layer 2)
*
* @example
* ```json
* {
* "type": "to_waellet",
* "data": {
* "jsonrpc": "2.0",
* "id": "sk-tx-sign-1",
* "method": "transaction.sign",
* "params": {
* "tx": "tx_+FgMAaEBuzbuuWjOzR7ecjOY8+u7HdNk0KoxTQcCDerZELEQ+UShAXtm5sMFBwg25Ol5IFI9w+pZy7/YbFi6BwPqi80KuKdsCoYPJvVhyAAAAYdoYWluYW5h9uAnNQ==",
* "returnSigned": true,
* "networkId": "ae_uat"
* }
* }
* }
* ```
*/ */
type EventData_A2W_tx_sign_noprop type EventData_A2W_tx_sign_noprop
= EventData_A2W<RpcCall_A2W_tx_sign_noprop>; = EventData_A2W<RpcCall_A2W_tx_sign_noprop>;
@@ -1142,9 +1226,24 @@ type EventData_A2W_tx_sign_noprop
/** /**
* Event data for aepp-to-waellet "transaction.sign" (do not propagate) response * Event data for waellet-to-aepp "transaction.sign" (do not propagate) response
* *
* (layer 2) * (layer 2)
*
* @example
* ```json
* {
* "type": "to_aepp",
* "data": {
* "jsonrpc": "2.0",
* "id": "sk-tx-sign-1",
* "method": "transaction.sign",
* "result": {
* "signedTransaction": "tx_+KILAfhCuEDxWnvffMvyrkFWnrImYej38rh99vM9f6pORl/yWTvU97nvUcY8/ck8lgtPA8w5odGSDb9LGY/JSZXsmsXhgKkHuFr4WAwBoQG7Nu65aM7NHt5yM5jz67sd02TQqjFNBwIN6tkQsRD5RKEBe2bmwwUHCDbk6XkgUj3D6lnLv9hsWLoHA+qLzQq4p2wKhg8m9WHIAAABh2hhaW5hbmF7X54G"
* }
* }
* }
* ```
*/ */
type EventData_W2A_tx_sign_noprop type EventData_W2A_tx_sign_noprop
= EventData_W2A<RpcResp_W2A_tx_sign_noprop>; = EventData_W2A<RpcResp_W2A_tx_sign_noprop>;
@@ -1157,14 +1256,15 @@ type EventData_W2A_tx_sign_noprop
/** /**
* Parameters for "message.sign" * Parameters for "message.sign"
* *
* FIXME: example
*
* ```ts
* {message : 'hello world',
* onAccount : 'ak_...'}
* ```
*
* (layer 4) * (layer 4)
*
* @example
* ```json
* {
* "onAccount": "ak_2RT9RPbcX8RtjBpMWqsKtVRVKASAbj8V4c3f7cCdJfuVdihhyL",
* "message": "MESSSSSSSSSSAGGGGGGGGGGGGGGGGGGGGGGGGGGGE"
* }
* ```
*/ */
type Params_A2W_msg_sign type Params_A2W_msg_sign
= {message : string, = {message : string,
@@ -1176,15 +1276,35 @@ type Params_A2W_msg_sign
* Success result type for "message.sign" * Success result type for "message.sign"
* *
* (layer 4) * (layer 4)
*
* @example
* ```json
* {
* "signature": "3ec195484965a60dd4179fbb616947a85e4e9961cb468816a2a22870382954bc374f8569e4ddc729dfc1b14e09e670b7d2c70c33c592caca29ff6c212f1f8b0f"
* }
* ```
*/ */
type Result_W2A_msg_sign type Result_W2A_msg_sign
= {signature : string}; = {signature : string};
/** /**
* Request type for "message.sign" (do not propagate) * Request type for "message.sign"
* *
* (layer 3) * (layer 3)
*
* @example
* ```json
* {
* "jsonrpc": "2.0",
* "id": "sk-msg-sign-1",
* "method": "message.sign",
* "params": {
* "onAccount": "ak_2RT9RPbcX8RtjBpMWqsKtVRVKASAbj8V4c3f7cCdJfuVdihhyL",
* "message": "MESSSSSSSSSSAGGGGGGGGGGGGGGGGGGGGGGGGGGGE"
* }
* }
* ```
*/ */
type RpcCall_A2W_msg_sign type RpcCall_A2W_msg_sign
= RpcCall<"message.sign", = RpcCall<"message.sign",
@@ -1193,9 +1313,21 @@ type RpcCall_A2W_msg_sign
/** /**
* Response type for "message.sign" (do not propagate) * Response type for "message.sign"
* *
* (layer 3) * (layer 3)
*
* @example
* ```json
* {
* "jsonrpc": "2.0",
* "id": "sk-msg-sign-1",
* "method": "message.sign",
* "result": {
* "signature": "3ec195484965a60dd4179fbb616947a85e4e9961cb468816a2a22870382954bc374f8569e4ddc729dfc1b14e09e670b7d2c70c33c592caca29ff6c212f1f8b0f"
* }
* }
* ```
*/ */
type RpcResp_W2A_msg_sign type RpcResp_W2A_msg_sign
= RpcResp<"message.sign", = RpcResp<"message.sign",
@@ -1204,9 +1336,25 @@ type RpcResp_W2A_msg_sign
/** /**
* Event data for aepp-to-waellet "message.sign" (do not propagate) message * Event data for aepp-to-waellet "message.sign"
* *
* (layer 2) * (layer 2)
*
* @example
* ```json
* {
* "type": "to_waellet",
* "data": {
* "jsonrpc": "2.0",
* "id": "sk-msg-sign-1",
* "method": "message.sign",
* "params": {
* "onAccount": "ak_2RT9RPbcX8RtjBpMWqsKtVRVKASAbj8V4c3f7cCdJfuVdihhyL",
* "message": "MESSSSSSSSSSAGGGGGGGGGGGGGGGGGGGGGGGGGGGE"
* }
* }
* }
* ```
*/ */
type EventData_A2W_msg_sign type EventData_A2W_msg_sign
= EventData_A2W<RpcCall_A2W_msg_sign>; = EventData_A2W<RpcCall_A2W_msg_sign>;
@@ -1214,9 +1362,24 @@ type EventData_A2W_msg_sign
/** /**
* Event data for aepp-to-waellet "message.sign" (do not propagate) response * Event data for waellet-to-aepp "message.sign"
* *
* (layer 2) * (layer 2)
*
* @example
* ```json
* {
* "type": "to_aepp",
* "data": {
* "jsonrpc": "2.0",
* "id": "sk-msg-sign-1",
* "method": "message.sign",
* "result": {
* "signature": "3ec195484965a60dd4179fbb616947a85e4e9961cb468816a2a22870382954bc374f8569e4ddc729dfc1b14e09e670b7d2c70c33c592caca29ff6c212f1f8b0f"
* }
* }
* }
* ```
*/ */
type EventData_W2A_msg_sign type EventData_W2A_msg_sign
= EventData_W2A<RpcResp_W2A_msg_sign>; = EventData_W2A<RpcResp_W2A_msg_sign>;
+1
View File
@@ -4,3 +4,4 @@ jex_mindist
dist dist
src/jex_include src/jex_include
erl_crash.dump erl_crash.dump
docs
+1 -1
View File
@@ -1,5 +1,5 @@
{type, library}. {type, library}.
{realm, local}. {realm, local}.
{name, parasite}. {name, parasite}.
{version, "0.1.0"}. {version, "0.2.0"}.
{deps, []}. {deps, []}.
+2 -2
View File
@@ -26,8 +26,8 @@ import * as ae_compiler from './ae_compiler.js'
export const MIN_FEE = 16660000000000; export const MIN_FEE = 16660000000000;
export const MIN_CONTRACT_FEE = 79080000000000; export const MIN_CONTRACT_FEE = 79080000000000;
export const MIN_GAS_PRICE = 1000000000; export const MIN_GAS_PRICE = 1000000000;
export const URL_MAINNET = "https://mainnet.aeternity.io/v2"; export const URL_MAINNET = "https://mainnet.aeternity.io/v3";
export const URL_TESTNET = "https://testnet.aeternity.io/v2"; export const URL_TESTNET = "https://testnet.aeternity.io/v3";
//------------------------------------------------------------------- //-------------------------------------------------------------------
+2
View File
@@ -70,6 +70,8 @@
<h1>5. Sign a message</h1> <h1>5. Sign a message</h1>
<textarea id="message-text" rows="5" cols="80">MESSSSSSSSSSAGGGGGGGGGGGGGGGGGGGGGGGGGGGE</textarea>
<br>
<button id="sign-message">Sign Message</button> <button id="sign-message">Sign Message</button>
<!-- script --> <!-- script -->
+3 -3
View File
@@ -2,6 +2,6 @@
{realm, local}. {realm, local}.
{name, sk_examples}. {name, sk_examples}.
{version, "0.1.0"}. {version, "0.1.0"}.
{deps, ["local-awcp-0.1.0", {deps, ["local-awcp-0.2.0",
"local-parasite-0.1.0", "local-parasite-0.2.0",
"local-sidekick-0.1.0"]}. "local-sidekick-0.2.0"]}.
+11 -6
View File
@@ -1,6 +1,6 @@
import * as ae_node from './jex_include/local-parasite-0.1.0/dist/ae_node.js'; import * as ae_node from './jex_include/local-parasite-0.2.0/dist/ae_node.js';
import * as awcp from './jex_include/local-awcp-0.1.0/dist/awcp.js'; import * as awcp from './jex_include/local-awcp-0.2.0/dist/awcp.js';
import * as sk from './jex_include/local-sidekick-0.1.0/dist/sidekick.js'; import * as sk from './jex_include/local-sidekick-0.2.0/dist/sidekick.js';
var pv_address: string; var pv_address: string;
var pv_spendtx_base64: string; var pv_spendtx_base64: string;
@@ -197,10 +197,15 @@ sign_tx
document.getElementById("sign-spendtx-result")!.innerHTML = JSON.stringify(signedTx, undefined, 4); document.getElementById("sign-spendtx-result")!.innerHTML = JSON.stringify(signedTx, undefined, 4);
} }
async function sign_msg(logger: sk.Logger): Promise<void> { async function
console.log('poop'); sign_msg
(logger: sk.Logger)
: Promise<void>
{
let acc_pubkey : string = pv_address; let acc_pubkey : string = pv_address;
let signed_msg = await sk.msg_sign('sk-msg-sign-1', acc_pubkey, 'I make stinky poo poo', sk.TIMEOUT_DEF_TX_SIGN_NOPROP_MS, 'stinky poo poo too long', logger); // @ts-ignore value property exists because i say so
let msg_text : string = document.getElementById('message-text').value;
let signed_msg = await sk.msg_sign('sk-msg-sign-1', acc_pubkey, msg_text, sk.TIMEOUT_DEF_MSG_SIGN_MS, 'message signing took too long', logger);
console.log('signed message:', signed_msg); console.log('signed message:', signed_msg);
} }
+1 -1
View File
@@ -1,3 +1,3 @@
import * as sk from './jex_include/local-sidekick-0.1.0/dist/sidekick.js'; import * as sk from './jex_include/local-sidekick-0.2.0/dist/sidekick.js';
sk.hello(); sk.hello();
+226 -48
View File
@@ -44,6 +44,8 @@ export {
unsafe, unsafe,
ok, ok,
error, error,
Ok,
Error,
// timeout errors // timeout errors
ERROR_CODE_SkTimeoutError, ERROR_CODE_SkTimeoutError,
SkTimeoutError, SkTimeoutError,
@@ -69,6 +71,7 @@ export {
TIMEOUT_DEF_CONNECT_MS, TIMEOUT_DEF_CONNECT_MS,
TIMEOUT_DEF_ADDRESS_MS, TIMEOUT_DEF_ADDRESS_MS,
TIMEOUT_DEF_TX_SIGN_NOPROP_MS, TIMEOUT_DEF_TX_SIGN_NOPROP_MS,
TIMEOUT_DEF_MSG_SIGN_MS,
// API // API
// detect // detect
detect, detect,
@@ -89,7 +92,7 @@ export {
// IMPORTS // IMPORTS
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
import * as awcp from './jex_include/local-awcp-0.1.0/dist/awcp.js'; import * as awcp from './jex_include/local-awcp-0.2.0/dist/awcp.js';
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@@ -97,20 +100,104 @@ import * as awcp from './jex_include/local-awcp-0.1.0/dist/awcp.js';
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
/** /**
* Use for debugging/to check if import worked correctly * Just `console.log`s `hello`. Use for debugging/to check if import worked correctly
*/ */
function function
hello hello
() ()
: void : void
{ {
console.log('hællo'); console.log('hello');
} }
/** /**
* Type that catches positive errors * The idea behind this type is that some errors are known to be likely (e.g.
* the user rejects a transaction request, or something times out, etc). These
* errors (called "positive errors") should not generate exceptions. Exceptions
* should occur when exceptional behavior occurs (e.g. hardware faults,
* dividing by zero). Exceptions should not occur on events that are known to
* be likely. Instead, branching is the correct idiom.
*
* Furthermore, there are often many possible sources of errors. What this
* provides is a single "did it work or not" branch point.
*
* Further, in practice, all errors (either {@link SkTimeoutError} or {@link
* awcp.RpcError}) have a field called `code` which uniquely identifies the
* error, so it's easy to algorithmically respond to specific positive errors.
* For instance, if the user rejects a request in a popup, that is `code: 4`
* (see {@link awcp.ERROR_CODE_RpcRejectedByUserError}). If the user does not
* do anything within the timeout parameter you specify, that generates a
* {@link SkTimeoutError} which has `code: 420`.
*
* There are two branches: {@link Ok} and {@link Error}
*
* ```ts
* type Ok<ok_t>
* = {ok : true,
* result : ok_t};
*
* type Error<err_t>
* = {ok : false,
* error : err_t};
*
* type Safe<ok_t, err_t>
* = Ok<ok_t>
* | Error<err_t>;
* ```
*
* @example
* Suppose you are trying to get the user's {@link address}. This pops up a
* confirmation dialog asking the user if he wants to connect to your
* application. There's a good chance the user says no. There's also a
* possibility he just doesn't do anything and things just time out.
*
* ```ts
* // there is a button in the document that when pressed triggers this function
* async function address(logger: sk.Logger): Promise<void>
* {
* let h4 = document.getElementById("addressed")!;
* let pre = document.getElementById("address-info")!;
*
* h4.innerHTML = 'addressing...';
* h4.style.color = 'GoldenRod';
*
* // try to address to the wallet
* // will fail on timeout error
* let maybe_wallet_info = await sk.address(
* 'ske-address-1',
* {type: 'subscribe',
* value: 'connected'},
* sk.TIMEOUT_DEF_ADDRESS_MS,
* "failed to address to wallet",
* logger
* );
*
* console.log(maybe_wallet_info);
*
* // ok means wallet was addressed
* if (maybe_wallet_info.ok)
* {
* h4.innerHTML = "addressed";
* h4.style.color = "green";
* pre.innerHTML = JSON.stringify(maybe_wallet_info.result, undefined, 4);
* // update global variable
* let the_address = Object.keys(maybe_wallet_info.result.address.current)[0];
* set_pv_address(the_address);
* }
* else
* {
* h4.innerHTML = "error";
* h4.style.color = "crimson";
* pre.innerHTML = JSON.stringify(maybe_wallet_info.error, undefined, 4);
* }
* }
* ```
*
* The important part is the `if/else`. That branch point corresponds to "did
* it work or not?" The `else` branch corresponds to the subset of "not" that
* you know is likely: timeouts, rejections, etc.
*/ */
type Safe<ok_t, err_t> type Safe<ok_t, err_t>
= Ok<ok_t> = Ok<ok_t>
@@ -119,7 +206,25 @@ type Safe<ok_t, err_t>
/** /**
* Ok type * See {@link Safe} for context
*
* @example
* ```json
* {
* "ok": true,
* "result": {
* "type": "to_aepp",
* "data": {
* "jsonrpc": "2.0",
* "id": "sk-msg-sign-1",
* "method": "message.sign",
* "result": {
* "signature": "3ec195484965a60dd4179fbb616947a85e4e9961cb468816a2a22870382954bc374f8569e4ddc729dfc1b14e09e670b7d2c70c33c592caca29ff6c212f1f8b0f"
* }
* }
* }
* }
* ```
*/ */
type Ok<ok_t> type Ok<ok_t>
= {ok : true, = {ok : true,
@@ -128,7 +233,19 @@ type Ok<ok_t>
/** /**
* Err type * See {@link Safe} for context
*
* @example
* ```json
* {
* "ok": false,
* "error": {
* "code": 4,
* "data": {},
* "message": "Operation rejected by user"
* }
* }
* ```
*/ */
type Error<err_t> type Error<err_t>
= {ok : false, = {ok : false,
@@ -399,6 +516,14 @@ const TIMEOUT_DEF_ADDRESS_MS = 5*MIN;
const TIMEOUT_DEF_TX_SIGN_NOPROP_MS = 5*MIN; const TIMEOUT_DEF_TX_SIGN_NOPROP_MS = 5*MIN;
/**
* In the general case, this pops up the modal that requires the user to
* manually confirm, so is set to 5 minutes. This is an instance where you as
* the developer need to exercise some discretion.
*/
const TIMEOUT_DEF_MSG_SIGN_MS = 5*MIN;
// Ah ok // Ah ok
// //
// so for connection.announcePresence, we just listen and recieve, unwrap, send back // so for connection.announcePresence, we just listen and recieve, unwrap, send back
@@ -421,41 +546,42 @@ const TIMEOUT_DEF_TX_SIGN_NOPROP_MS = 5*MIN;
* *
* Wait for wallet to announce itself, and then return. * Wait for wallet to announce itself, and then return.
* *
* Example message data: * @example
* ```ts
* // document has a button with id=detect
* // this is the function that is triggered when the button is clicked
* async function detect(logger: sk.Logger): Promise<void> {
* let h4 = document.getElementById("detected")!;
* let pre = document.getElementById("detect-info")!;
* *
* ```json * h4.innerHTML = 'detecting...';
* { * h4.style.color = 'GoldenRod';
* "type": "to_aepp", *
* "data": { * // try to detect the wallet
* "jsonrpc": "2.0", * // will fail on timeout error
* "method": "connection.announcePresence", * // console logger
* "params": { * let maybe_wallet_info =//: sk.Safe<awcp.EventData_W2A_connection_announcePresence, sk.TimeoutError> =
* "id": "{aee9e933-52b6-410a-8c3f-99c6be596b4e}", * await sk.detect(sk.TIMEOUT_DEF_DETECT_MS, "failed to detect wallet", logger);
* "name": "Superhero", *
* "networkId": "ae_mainnet", * console.log(maybe_wallet_info);
* "origin": "moz-extension://ee425d81-d5b2-44b6-9406-4da31b019e7c", *
* "type": "extension" * // ok means wallet was detected
* if (maybe_wallet_info.ok) {
* h4.innerHTML = "detected";
* h4.style.color = "green";
* pre.innerHTML = JSON.stringify(maybe_wallet_info.result, undefined, 4);
* }
* else {
* h4.innerHTML = "error";
* h4.style.color = "crimson";
* pre.innerHTML = JSON.stringify(maybe_wallet_info.error, undefined, 4);
* } * }
* } * }
* }
* ```
* *
* Example return data: * // want to create a logger down here
* * let logger = sk.cl();
* ```json * // detect button
* { * document.getElementById('detect')!.onclick = function() { detect(logger); } ;
* "id": "{aee9e933-52b6-410a-8c3f-99c6be596b4e}",
* "name": "Superhero",
* "networkId": "ae_mainnet",
* "origin": "moz-extension://ee425d81-d5b2-44b6-9406-4da31b019e7c",
* "type": "extension"
* }
* ```
*
* Example usage:
*
* ```typescript
* let wallet_info = await sk.detect(sk.TIMEOUT_DEF_DETECT_MS, "wallet timed out", sk.cl());
* ``` * ```
*/ */
async function async function
@@ -617,6 +743,58 @@ class CAPListener
/**
* Connect to the wallet. This is a necessary step if you want {@link address}
* to work. You **must** wait for Superhero to announce itself (see {@link
* detect}) before attempting to connect. This has the same return data as
* {@link detect}. This does not pop up the confirmation dialog for the user.
* Superhero never rejects the connection request. This call is instantaneous
* in practice.
*
* @example
* ```ts
* // document has a button with id=connect
* // this is the function that is triggered when the button is clicked
* // you want your user to do the detect sequence first
* async function connect (logger: sk.Logger) : Promise<void> {
* let h4 = document.getElementById("connected")!;
* let pre = document.getElementById("connect-info")!;
*
* h4.innerHTML = 'connecting...';
* h4.style.color = 'GoldenRod';
*
* // try to connect to the wallet
* // will fail on timeout error
* let maybe_wallet_info = await sk.connect(
* 'ske-connect-1',
* {name: 'sidekick examples',
* version: 1},
* sk.TIMEOUT_DEF_CONNECT_MS,
* "failed to connect to wallet",
* logger
* );
*
* console.log(maybe_wallet_info);
*
* // ok means wallet was connected
* if (maybe_wallet_info.ok)
* {
* h4.innerHTML = "connected";
* h4.style.color = "green";
* pre.innerHTML = JSON.stringify(maybe_wallet_info.result, undefined, 4);
* }
* else
* {
* h4.innerHTML = "error";
* h4.style.color = "crimson";
* pre.innerHTML = JSON.stringify(maybe_wallet_info.error, undefined, 4);
* }
* }
*
* let logger = sk.cl();
* document.getElementById('connect')!.onclick = function() { connect(logger); };
* ```
*/
async function async function
connect connect
(id : number | string, (id : number | string,
@@ -639,13 +817,16 @@ connect
return result; return result;
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// API: get address // API: get address
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
/**
*
*/
async function async function
address address
(id : number | string, (id : number | string,
@@ -669,12 +850,10 @@ address
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// API: message sign // API: message sign
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
async function async function
msg_sign msg_sign
(id : number | string, (id : number | string,
@@ -683,9 +862,9 @@ msg_sign
timeout_ms : number, timeout_ms : number,
timeout_msg : string, timeout_msg : string,
logger : Logger) logger : Logger)
: Promise<Safe<any, awcp.RpcError | SkTimeoutError>> : Promise<Safe<awcp.Result_W2A_msg_sign, awcp.RpcError | SkTimeoutError>>
{ {
logger.debug('address', {id:id, account_pubkey:account_pubkey, message:message, timeout_ms:timeout_ms, timeout_msg:timeout_msg}); logger.debug('msg_sign', {id:id, account_pubkey:account_pubkey, message:message, timeout_ms:timeout_ms, timeout_msg:timeout_msg});
let msgr = new MsgR(logger); let msgr = new MsgR(logger);
// FIXME: for type purposes, making the correct RPC message should be up here // FIXME: for type purposes, making the correct RPC message should be up here
// this way we can enforce that it's a correct RPC call with typescript // this way we can enforce that it's a correct RPC call with typescript
@@ -693,17 +872,16 @@ msg_sign
// let result = await msgr.send_raseev(id, awcp.METHOD_CONNECTION_OPEN, params, target, timeout_ms, timeout_msg); // let result = await msgr.send_raseev(id, awcp.METHOD_CONNECTION_OPEN, params, target, timeout_ms, timeout_msg);
let result = let result =
await msgr.send_raseev await msgr.send_raseev
<any, any, any> <"message.sign", awcp.Params_A2W_msg_sign, awcp.Result_W2A_msg_sign>
(id, "message.sign", {onAccount: account_pubkey, message: message}, timeout_ms, timeout_msg); (id, "message.sign", {onAccount: account_pubkey, message: message}, timeout_ms, timeout_msg);
return result; return result;
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// API: tx sign (no prop) // API: tx sign (no prop)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
async function async function
tx_sign_noprop tx_sign_noprop
(id : number | string, (id : number | string,
+25 -8
View File
@@ -37,26 +37,31 @@ help() ->
% TODONE: jex viewdocs PKG [port] % TODONE: jex viewdocs PKG [port]
% TODONE: jex fulldist % TODONE: jex fulldist
% TODONE: jex install % TODONE: jex install
% TODO: jex get_mindist PKG % TODONE: jex get_mindist PKG
% TODO: jex dwim++ = install % TODONE: jex dwim++ = install
% TODO: --name option for docs
% TODO: use less than full qualified names (not priority) % TODO: use less than full qualified names (not priority)
% TODO: --name option for docs (not priority)
% TODO: make fulldist for arbitrary installed package (requires storing jex.eterms, not hard but also not a priority) % TODO: make fulldist for arbitrary installed package (requires storing jex.eterms, not hard but also not a priority)
% TODO: be smart about creating jex_include % TODO: be smart about creating jex_include
% TODO: tarball shas % TODO: tarball shas
% TODO: tarball signatures % TODO: tarball signatures
% TODO: jex install
help_screen() -> help_screen() ->
["Jex: simple JavaScript packaging system\n" ["Jex: simple JavaScript packaging system\n"
"\n" "\n"
"If you have never run jex before, you need to run `jex init` first\n" "QUICK REFERENCE\n"
" You have a package tarball and want to install it ->\n"
" jex install foo-bar-X.Y.Z.tar.gz\n"
" You are in the current directory of a project and want to build it ->\n"
" jex install\n"
" There is a package installed and you need its mindist to put on a server or something ->\n"
" jex get_mindist foo-bar-X.Y.Z # must use fully qualified package name\n"
"\n" "\n"
"PORCELAIN COMMANDS:\n" "PORCELAIN COMMANDS:\n"
" dwim- build project but don't make a release (init, pull, build)\n" " dwim- build project but don't make a release (init, clean, pull, build)\n"
" dwim+ build and make a minimal release (init, pull, build, mindist, push)\n" " dwim+ build and make a minimal release (init, clean, pull, build, mindist, push)\n"
" dwim++ build and make a full release (init, pull, build, mindist, push, mkdocs, pushdocs)\n" " dwim++ build and make a full release (init, clean, pull, build, mindist, push, mkdocs, pushdocs)\n"
" install synonym for dwim++\n" " install synonym for dwim++\n"
" install [TARBALL_PATH] install the given package\n" " install [TARBALL_PATH] install the given package\n"
" ls list installed packages\n" " ls list installed packages\n"
@@ -65,6 +70,7 @@ help_screen() ->
"\n" "\n"
"PLUMBING COMMANDS:\n" "PLUMBING COMMANDS:\n"
" init mkdir -p $HOME/.jex/{dev,docs,tmp}\n" " init mkdir -p $HOME/.jex/{dev,docs,tmp}\n"
" clean rm -r ./src/jex_include && rm -r dist\n"
" build tsc && cp -r ./src/jex_include ./dist/\n" " build tsc && cp -r ./src/jex_include ./dist/\n"
" -w, --weak continue building even if tsc fails\n" " -w, --weak continue building even if tsc fails\n"
" -f, --force use cp -rf instead of cp -r\n" " -f, --force use cp -rf instead of cp -r\n"
@@ -111,6 +117,7 @@ dispatch(["viewdocs", Pkg, Port]) -> viewdocs(Pkg, Port);
dispatch(["get_mindist", Pkg]) -> get_mindist(Pkg); dispatch(["get_mindist", Pkg]) -> get_mindist(Pkg);
%% plumbing %% plumbing
dispatch(["init"]) -> init(); dispatch(["init"]) -> init();
dispatch(["clean"]) -> clean();
dispatch(["build" | Opts]) -> build(Opts); dispatch(["build" | Opts]) -> build(Opts);
dispatch(["mindist" | Opts]) -> mindist(Opts); dispatch(["mindist" | Opts]) -> mindist(Opts);
dispatch(["push"]) -> push(); dispatch(["push"]) -> push();
@@ -158,6 +165,7 @@ man() ->
dwim(minus) -> dwim(minus) ->
init(), init(),
clean(),
pull(), pull(),
build([]); build([]);
dwim(plus) -> dwim(plus) ->
@@ -641,6 +649,15 @@ get_mindist2(PkgName) ->
ok. ok.
%%-----------------------------------------------------------------------------
%% jex clean
%%-----------------------------------------------------------------------------
clean() ->
_ = cmdf("rm -r ./src/jex_include", []),
_ = cmdf("rm -r ./dist", []),
ok.
%%----------------------------------------------------------------------------- %%-----------------------------------------------------------------------------
%% INTERNALS %% INTERNALS