Quick Start
Every Fluence reference node comes with a set of builtin services that are accessible to Aqua programs. Let's use those readily available services to get the timestamp of a few of our peer-to-peer neighborhood nodes with Aqua.
aqua
-- timestamp_getter.aquaaqua Mainimport "@fluencelabs/aqua-lib/builtin.aqua"export ts_getterfunc ts_getter(node: string, num_peers: u32) -> []u64:res: *u64on node:key <- Op.string_to_b58(node)nodes <- Kademlia.neighborhood(key, nil, [num_peers])for n <- nodes par:on n:try:res <- Peer.timestamp_ms()join res[num_peers - 1]<- res
aqua
-- timestamp_getter.aquaaqua Mainimport "@fluencelabs/aqua-lib/builtin.aqua"export ts_getterfunc ts_getter(node: string, num_peers: u32) -> []u64:res: *u64on node:key <- Op.string_to_b58(node)nodes <- Kademlia.neighborhood(key, nil, [num_peers])for n <- nodes par:on n:try:res <- Peer.timestamp_ms()join res[num_peers - 1]<- res
Let's explain this script line by line. First of all, we need to specify module header.
aqua
aqua Main
aqua
aqua Main
Next, it brings builtin services (see aqua-lib) in scope by import:
aqua
import "@fluencelabs/aqua-lib/builtin.aqua"
aqua
import "@fluencelabs/aqua-lib/builtin.aqua"
Next, it export ts_getter
function, cause we want to call it from outer scope:
aqua
export ts_getter
aqua
export ts_getter
Next it defines a function named ts_getter
with two parameters: node
which is peer id and num_peers
which is how many neighbors to check.
(to get list of node ids on dar
network you can execute: fluence default peers dar
)
That function returns array of obtained timestamps.
aqua
func ts_getter(node: string, num_peers: u32) -> []u64:
aqua
func ts_getter(node: string, num_peers: u32) -> []u64:
On the first line it creates stream variable (see CRDT Streams) res
:
aqua
res: *u64
aqua
res: *u64
Then execution is transfered on peer with id that was passed in node
(see on
expression):
aqua
on node:
aqua
on node:
On node
it obtains no more than num_peers
neighbour nodes using builtin services:
aqua
key <- Op.string_to_b58(node)nodes <- Kademlia.neighborhood(key, nil, [num_peers])
aqua
key <- Op.string_to_b58(node)nodes <- Kademlia.neighborhood(key, nil, [num_peers])
After that for each of the obtained nodes in parallel (see Parallel for
) it tries (see try) to push local timestamp to res
:
aqua
for n <- nodes par:on n:try:res <- Peer.timestamp_ms()
aqua
for n <- nodes par:on n:try:res <- Peer.timestamp_ms()
Back on node
element res[num_peers - 1]
is joined (see join
expression) thus making all results available:
aqua
join res[num_peers - 1]
aqua
join res[num_peers - 1]
Finally, stream is converted to scalar (see Streams Lifecycle) and returned:
aqua
<- res
aqua
<- res
See the ts-oracle example for the corresponding Aqua files in the aqua-script
directory.
Now that we have our script, let's use Fluence CLI to run it:
- Run
- Result
sh
# use `fluence run` as your client with some peer idfluence run \-i aqua-scripts/timestamp_getter.aqua \-f 'ts_getter("12D3KooWBUJifCTgaxAUrcM9JysqCcS4CS8tiYH5hExbdWCAoNwb", 10)'
sh
# use `fluence run` as your client with some peer idfluence run \-i aqua-scripts/timestamp_getter.aqua \-f 'ts_getter("12D3KooWBUJifCTgaxAUrcM9JysqCcS4CS8tiYH5hExbdWCAoNwb", 10)'
Here we go. Ten timestamps in micro seconds obtained in parallel:
json
[[1624928596292,1624928596291,1624928596291,1624928596299,1624928596295,1624928596286,1624928596295,1624928596284,1624928596293,1624928596289]]
json
[[1624928596292,1624928596291,1624928596291,1624928596299,1624928596295,1624928596286,1624928596295,1624928596284,1624928596293,1624928596289]]
And that's it. We now have ten timestamps right from our selected peer's neighbors.
Note that if you try to request too many peers, execution could halt.