5.6.1 JavaScript
The Reach JavaScript backend produces a compilation output named "input.export.mjs" which exports an asynchronous function for each participant. This will normally be imported by writing:
Each function accepts three arguments: stdlib
, ctc
, and interact
. These functions should be called by the frontend.
For example, if a Reach program contains a participant named 'A'
in the argument to Reach.App
, then the JavaScript backend will include a function named A
.
the module @reach-sh/stdlib/ETH.mjs;
the module @reach-sh/stdlib/ALGO.mjs;
the module @reach-sh/stdlib/FAKE.mjs; or,
the
async
function loadStdlib from @reach-sh/stdlib/loader.mjs.
The ctc
argument is the result of a call to acc.deploy
or acc.attach
.
The interact
argument is an object matching the participant interact interface for the corresponding participant.
The JavaScript backend also provides an export named _version
, which is a string representation of the Reach version used to compile the program.
For example, the version of Reach used to produce this documentation would contain the string '0.1.2'
.
Finally, the backend will provide an export named _Connectors
, which is an opaque object representing the connectors this app was compiled to.
5.6.1.1 Guarantees
This backend does not guarantee that values in a positive position in a participant interact interface, that are later passed to a negative position in a participant interact interface, will be identical, in the sense of JavaScript’s ===
operator, to the original value.
In other words, this backend does not ensure that Reach programs are parametric over JavaScript values that they interact with.
Positive and negative are best understood by example with a function type: a positive position is supplied by the function, such as the result; while a negative position is supplied by the caller, such as the arguments. These notions generalize, however, to higher (and lower) order contexts. In the case of Reach, this means that non-function values in a participant interact interface are positive.
For example, if the Reach program,
Reach.App({},
[Participant("A", { get: Bytes(32), give: Fun([Bytes(32)], Bool) })],
(A) => {
A.only(() => {
const x = interact.give(interact.get); });
A.publish(x);
commit(); });
is given the interact
object,
const x = "A string";
{ get: x,
give: (str) => x === str }
then it is not guaranteed that A
will publish true
, because the str
given to give
may not be identical to x
.
(However, they are bytesEq
.)
5.6.1.2 loader.mjs
The loader.mjs module exports the following functions that might help you write code that is portable to multiple consensus networks.
—
Expands a connector mode prefix to its full, canonical name. The canonical connector modes are:
'ETH-test-dockerized-geth' // Default for ETH, ETH-test, and ETH-test-dockerized
'ETH-test-embedded-ganache' // Default for ETH-test-embedded
'FAKE-test-embedded-mock' // Default for FAKE, FAKE-test, and FAKE-test-embedded
'ALGO-test-dockerized-algod' // Default for ALGO, ALGO-test, and ALGO-test-dockerized
—
Returns the canonicalized connector mode, based on the
process.env.REACH_CONNECTOR_MODE
environment variable.
If the variable is missing or empty, it will return the canonicalized form of 'ETH'
.
—
Returns the first piece of getConnectorMode()
,
which indicates the abbreviated name of the network being connected to.
Connectors are one of the following: ['ETH', 'FAKE', 'ALGO']
.
—
loadStdlib(connectorMode) => Promise<stdlib>
Returns a Promise for a stlib based on the provided connectorMode
string.
You may omit the connectorMode
argument, in which case
getConnectorMode()
will be used to select the correct stdlib.
5.6.1.3 Standard Library
The stdlib
modules export the following functions that might be used in this frontend:
—
Returns a Promise for a Reach account abstraction for a "default" account on the consensus network. The meaning of "default account" varies between contexts. When running in the browser, the default account will be connected to a wallet such as MetaMask or AlgoSigner. When running in node.js while connected to one of reach’s standard devnets, the default account will be connected to a faucet on the devnet. This promise will be rejected with an exception if no sensible default account can be accessed for the current context.
—
Returns a Promise for a Reach account abstraction for an account on the consensus network specified by the given secret. The details of the secret encoding are specified uniquely to the consensus network.
—
Returns a Promise for a Reach account abstraction for an account on the consensus network specified by the given mnemonic phrase. The details of the mnemonic phrase encoding are specified uniquely to the consensus network.
—
Returns a Promise for a Reach account abstraction for a new account on the consensus network with a given balance of network tokens. This can only be used in private testing scenarios, as it uses a private faucet to issue network tokens.
bigNumberify
is transparently applied to the balance
argument.
—
Returns a Promise for a Reach account abstraction for a new account on the consensus network. The account will have an empty balance of network tokens.
—
Adds the given balance of network tokens to a Reach account abstraction. This can only be used in private testing scenarios, as it uses a private faucet to issue network tokens.
bigNumberify
is transparently applied to the balance
argument.
—
connectAccount(networkAccount) => Promise<acc>
Returns a Promise for a Reach account abstraction for an existing account for the consensus network based on the connector-specific account specification provided by the networkAccount
argument.
// network => networkAccount type
ETH => ethers.Wallet
ALGO => {addr: string, sk: UInt8Array(64)}
—
acc.networkAccount => networkAccount
Returns the connector-specific account specification of a Reach account abstraction.
—
Returns a Reach contract abstraction after kicking off the deploy of a Reach DApp contract based on the bin
argument provided.
This bin
argument is the "input.mjs" module produced by the JavaScript backend.
This function does not block on the completion of deployment.
To wait for deployment, see ctc.getInfo
.
—
Returns a Promise for an object that may be given to attach
to construct a Reach contract abstraction representing this contract.
This object may be stringified with JSON.stringify
for printing and parsed again with JSON.parse
without any loss of information.
The Promise will only be resolved after the contract is actually deployed on the network.
If you are using {deployMode: 'firstMsg'}
,
avoid blocking on this Promise with await
until after the first publish
has occurred.
Awaiting getInfo
too early may cause your program to enter a state of deadlock.
—
Returns a Reach contract abstraction based on a deployed Reach DApp contract provided in the ctcInfo
argument (or a Promise for ctcInfo) and the bin
argument.
This bin
argument is the "input.mjs" module produced by the JavaScript backend.
—
Returns a Promise for the balance of network tokens held by the account given by a Reach account abstraction provided by the acc
argument.
—
Transfers amount
network tokens from from
to to
,
which are accounts, such as those returned by connectAccount
.
The returned Promise will only be resolved after the transfer completes.
bigNumberify
is transparently applied to the amount
argument.
—
Returns a Promise for the current consensus network time. For ETH, ALGO, and FAKE, this is the current block number, represented as a BigNumber.
—
Returns a Promise that will only be resolved after the specified consensus network time. In isolated testing modes, which are REACH_CONNECTOR_MODEs $NET-test-dockerized-$IMPL and $NET-test-embedded-$IMPL for all valid $NET and $IMPL, this will also force time to pass on the network, usually by sending trivial transactions.
You may provide an optional onProgress
callback, used for reporting progress,
which may be called many times up until the specified time.
It will receive an object with keys currentTime
and targetTime
,
—
Returns a Promise that will only be resolved after the specified time delta has elapsed.
The expression await wait(delta, onProgress)
is the same as
await waitUntilTime(add(await getNetworkTime(), delta), onProgress)
.
As with waitUntilTime
, the onProgress
callback is optional.
5.6.1.3.1 Utilities
Asserts that value x
has Reach type t
. An exception is thrown if this is not the case.
—
T_Null => ReachType
T_Bool => ReachType
T_UInt => ReachType
T_Bytes(number) => ReachType
T_Digest => ReachType
T_Address => ReachType
T_Array(ReachType, number) => ReachType
T_Tuple([ReachType ...]) => ReachType
T_Object({Key: ReachType ...}) => ReachType
T_Data({Variant: ReachType ...}) => ReachType
Each of these represent the corresponding Reach type. See the table below for Reach types and their corresponding JavaScript representation:
// Reach => JavaScript
Null => null
Bool => 'boolean'
UInt => 'BigNumber' or 'number'
Bytes => 'string'
Digest => 'BigNumber'
Address => NetworkAccount
Array => array
Tuple => array
Object => object
Data => ['variant', value]
For example, the Reach type MInt = Data({None: Null, Some: UInt})
inhabitant MInt.Some(42)
is represented as ['Some', 42]
in JavaScript.
—
Throws an exception if not given true
.
—
Returns a new array identical to arr
, except that index idx
is val
.
—
bigNumberify converts a JavaScript number to a BigNumber,
the JavaScript representation of Reach’s UInt
.
isBigNumber checks if its input is a BigNumber.
bigNumberToNumber transparently applies bigNumberify to its argument and returns a JavaScript number.
—
isHex(x) => bool
hexToBigNumber(bytes) => UInt
stringToHex(string) => bytes
bigNumberToHex(UInt) => bytes
uintToBytes(UInt) => bytes
bytesEq(bytes, bytes) => bool
digestEq(Digest, Digest) => bool
addressEq(Address, Address) => bool
These are additional conversion and comparison utilities.
—
Hashes the value.
—
Generates random bits as a UInt
.
The number of bits generated depends on the particular consensus network.
hasRandom
A value suitable for use as a participant interact interface requiring a random function.
—
Parses a FixedPoint
number into a Javascript number.
—
Parses a signed Int
into a Javascript number.
—
add(UInt, UInt) => UInt
sub(UInt, UInt) => UInt
mod(UInt, UInt) => UInt
mul(UInt, UInt) => UInt
div(UInt, UInt) => UInt
Integer arithmetic on UInt
.
—
eq(UInt, UInt) => bool
ge(UInt, UInt) => bool
gt(UInt, UInt) => bool
le(UInt, UInt) => bool
lt(UInt, UInt) => bool
Integer comparisons on UInt
.
—
The following exports are for dealing with network tokens.
standardUnit // string
atomicUnit // string
minimumBalance // atomicUnitAmount
parseCurrency(standardUnitAmount) => atomicUnitAmount
formatCurrency(atomicUnitAmount, int) => string // display amount in standard unit
These functions handle amounts in a network’s standard unit and its atomic unit. A standard unit is the network token unit most commonly associated with a network. For example, the standard unit of Ethereum is ETH. An atomic unit is the smallest unit of measure for the standard unit. For example, the atomic unit of Ethereum is WEI. An atomic unit is atomic, which means it cannot be divided into smaller units.
Some consensus networks, typically those with proof-of-stake, have minimum balances on their accounts, so this is exposed as minimumBalance
.
Because there are 1,000,000,000,000,000,000 WEI in 1 ETH, BigNumber is used to represet values in WEI.
Quantities of a network token should always be passed into Reach in the token’s atomic unit.
Note that bigNumberify
is transparently applied to formatCurrency
’s first argument.
5.6.1.4 ask.mjs
This backend also provides the helper module @reach-sh/stdlib/ask.mjs for constructing console interfaces to your frontends.
It provides the following exports:
ask(string, (string => result)) => Promise<result>
yesno(string) => boolean
done() => null
ask
is an asynchronous function that asks a question on the console and returns a Promise for the first result that its second argument does not error on.
yesno
is an argument appropriate to give as the second argument to ask
that parses "Yes"/"No" answers.
done
indicates that no more questions will be asked.