Type alias Safe<ok_t, err_t>

Safe<ok_t, err_t>: Ok<ok_t> | Error<err_t>

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 SkTimeoutError or 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 awcp.ERROR_CODE_RpcRejectedByUserError). If the user does not do anything within the timeout parameter you specify, that generates a SkTimeoutError which has code: 420.

There are two branches: Ok and Error

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 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.

// 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 Parameters

Generated using TypeDoc