GitBook: [#252] Fix small issues with tutorial's deploy section
BIN
.gitbook/assets/air_call_execution_1 (1).png
Normal file
After Width: | Height: | Size: 167 KiB |
BIN
.gitbook/assets/air_call_execution_1.png
Normal file
After Width: | Height: | Size: 167 KiB |
After Width: | Height: | Size: 43 KiB |
After Width: | Height: | Size: 43 KiB |
After Width: | Height: | Size: 43 KiB |
After Width: | Height: | Size: 43 KiB |
After Width: | Height: | Size: 41 KiB |
After Width: | Height: | Size: 41 KiB |
After Width: | Height: | Size: 41 KiB |
After Width: | Height: | Size: 41 KiB |
BIN
.gitbook/assets/air_par_3.png
Normal file
After Width: | Height: | Size: 80 KiB |
After Width: | Height: | Size: 86 KiB |
After Width: | Height: | Size: 86 KiB |
After Width: | Height: | Size: 86 KiB |
After Width: | Height: | Size: 86 KiB |
After Width: | Height: | Size: 86 KiB |
After Width: | Height: | Size: 86 KiB |
BIN
.gitbook/assets/air_xor_5.png
Normal file
After Width: | Height: | Size: 62 KiB |
BIN
.gitbook/assets/image (1).png
Normal file
After Width: | Height: | Size: 62 KiB |
BIN
.gitbook/assets/image (10).png
Normal file
After Width: | Height: | Size: 54 KiB |
BIN
.gitbook/assets/image (11).png
Normal file
After Width: | Height: | Size: 55 KiB |
BIN
.gitbook/assets/image (12).png
Normal file
After Width: | Height: | Size: 704 KiB |
BIN
.gitbook/assets/image (13).png
Normal file
After Width: | Height: | Size: 251 KiB |
BIN
.gitbook/assets/image (14).png
Normal file
After Width: | Height: | Size: 369 KiB |
BIN
.gitbook/assets/image (15).png
Normal file
After Width: | Height: | Size: 698 KiB |
BIN
.gitbook/assets/image (16).png
Normal file
After Width: | Height: | Size: 549 KiB |
BIN
.gitbook/assets/image (17).png
Normal file
After Width: | Height: | Size: 110 KiB |
BIN
.gitbook/assets/image (18) (1) (1) (2) (2) (1).png
Normal file
After Width: | Height: | Size: 355 KiB |
BIN
.gitbook/assets/image (18) (1) (1) (2) (2).png
Normal file
After Width: | Height: | Size: 355 KiB |
BIN
.gitbook/assets/image (18) (1) (1).png
Normal file
After Width: | Height: | Size: 355 KiB |
BIN
.gitbook/assets/image (18).png
Normal file
After Width: | Height: | Size: 132 KiB |
BIN
.gitbook/assets/image (19) (1).png
Normal file
After Width: | Height: | Size: 696 KiB |
BIN
.gitbook/assets/image (19).png
Normal file
After Width: | Height: | Size: 696 KiB |
BIN
.gitbook/assets/image (2).png
Normal file
After Width: | Height: | Size: 40 KiB |
BIN
.gitbook/assets/image (20).png
Normal file
After Width: | Height: | Size: 578 KiB |
BIN
.gitbook/assets/image (21).png
Normal file
After Width: | Height: | Size: 191 KiB |
BIN
.gitbook/assets/image (22).png
Normal file
After Width: | Height: | Size: 101 KiB |
BIN
.gitbook/assets/image (23).png
Normal file
After Width: | Height: | Size: 438 KiB |
BIN
.gitbook/assets/image (24) (1) (1).png
Normal file
After Width: | Height: | Size: 385 KiB |
BIN
.gitbook/assets/image (24) (1).png
Normal file
After Width: | Height: | Size: 385 KiB |
BIN
.gitbook/assets/image (24).png
Normal file
After Width: | Height: | Size: 418 KiB |
BIN
.gitbook/assets/image (25).png
Normal file
After Width: | Height: | Size: 549 KiB |
BIN
.gitbook/assets/image (26).png
Normal file
After Width: | Height: | Size: 483 KiB |
BIN
.gitbook/assets/image (27) (1).png
Normal file
After Width: | Height: | Size: 150 KiB |
BIN
.gitbook/assets/image (27).png
Normal file
After Width: | Height: | Size: 409 KiB |
BIN
.gitbook/assets/image (28) (1) (1).png
Normal file
After Width: | Height: | Size: 389 KiB |
BIN
.gitbook/assets/image (28) (1).png
Normal file
After Width: | Height: | Size: 389 KiB |
BIN
.gitbook/assets/image (28).png
Normal file
After Width: | Height: | Size: 462 KiB |
BIN
.gitbook/assets/image (29).png
Normal file
After Width: | Height: | Size: 150 KiB |
BIN
.gitbook/assets/image (3).png
Normal file
After Width: | Height: | Size: 32 KiB |
BIN
.gitbook/assets/image (30).png
Normal file
After Width: | Height: | Size: 56 KiB |
BIN
.gitbook/assets/image (31) (1).png
Normal file
After Width: | Height: | Size: 486 KiB |
BIN
.gitbook/assets/image (31).png
Normal file
After Width: | Height: | Size: 486 KiB |
BIN
.gitbook/assets/image (32).png
Normal file
After Width: | Height: | Size: 150 KiB |
BIN
.gitbook/assets/image (33).png
Normal file
After Width: | Height: | Size: 334 KiB |
BIN
.gitbook/assets/image (34).png
Normal file
After Width: | Height: | Size: 409 KiB |
BIN
.gitbook/assets/image (35).png
Normal file
After Width: | Height: | Size: 195 KiB |
BIN
.gitbook/assets/image (36).png
Normal file
After Width: | Height: | Size: 150 KiB |
BIN
.gitbook/assets/image (37).png
Normal file
After Width: | Height: | Size: 578 KiB |
BIN
.gitbook/assets/image (38) (1).png
Normal file
After Width: | Height: | Size: 595 KiB |
BIN
.gitbook/assets/image (38) (2) (2) (2) (1).png
Normal file
After Width: | Height: | Size: 595 KiB |
BIN
.gitbook/assets/image (38) (2) (2) (2).png
Normal file
After Width: | Height: | Size: 595 KiB |
BIN
.gitbook/assets/image (38).png
Normal file
After Width: | Height: | Size: 195 KiB |
BIN
.gitbook/assets/image (39) (1) (1).png
Normal file
After Width: | Height: | Size: 502 KiB |
BIN
.gitbook/assets/image (39) (1).png
Normal file
After Width: | Height: | Size: 502 KiB |
BIN
.gitbook/assets/image (39).png
Normal file
After Width: | Height: | Size: 296 KiB |
BIN
.gitbook/assets/image (4).png
Normal file
After Width: | Height: | Size: 41 KiB |
BIN
.gitbook/assets/image (40).png
Normal file
After Width: | Height: | Size: 432 KiB |
BIN
.gitbook/assets/image (41).png
Normal file
After Width: | Height: | Size: 59 KiB |
BIN
.gitbook/assets/image (42).png
Normal file
After Width: | Height: | Size: 81 KiB |
BIN
.gitbook/assets/image (43).png
Normal file
After Width: | Height: | Size: 216 KiB |
BIN
.gitbook/assets/image (44).png
Normal file
After Width: | Height: | Size: 59 KiB |
BIN
.gitbook/assets/image (45).png
Normal file
After Width: | Height: | Size: 36 KiB |
BIN
.gitbook/assets/image (46).png
Normal file
After Width: | Height: | Size: 237 KiB |
BIN
.gitbook/assets/image (47).png
Normal file
After Width: | Height: | Size: 242 KiB |
BIN
.gitbook/assets/image (48).png
Normal file
After Width: | Height: | Size: 221 KiB |
BIN
.gitbook/assets/image (49).png
Normal file
After Width: | Height: | Size: 221 KiB |
BIN
.gitbook/assets/image (5).png
Normal file
After Width: | Height: | Size: 46 KiB |
BIN
.gitbook/assets/image (50).png
Normal file
After Width: | Height: | Size: 221 KiB |
BIN
.gitbook/assets/image (51).png
Normal file
After Width: | Height: | Size: 156 KiB |
BIN
.gitbook/assets/image (6) (1) (1).png
Normal file
After Width: | Height: | Size: 67 KiB |
BIN
.gitbook/assets/image (6) (1).png
Normal file
After Width: | Height: | Size: 67 KiB |
BIN
.gitbook/assets/image (6).png
Normal file
After Width: | Height: | Size: 62 KiB |
BIN
.gitbook/assets/image (7).png
Normal file
After Width: | Height: | Size: 57 KiB |
BIN
.gitbook/assets/image (8).png
Normal file
After Width: | Height: | Size: 75 KiB |
BIN
.gitbook/assets/image (9).png
Normal file
After Width: | Height: | Size: 71 KiB |
BIN
.gitbook/assets/image.png
Normal file
After Width: | Height: | Size: 82 KiB |
@ -4,7 +4,7 @@ Fluence provides an open Web3 protocol, framework and tooling to develop and hos
|
|||||||
|
|
||||||
The Fluence Web3 stack enables
|
The Fluence Web3 stack enables
|
||||||
|
|
||||||
* programmable network requests
|
* programmable network requests 
|
||||||
* distributed applications from composition without centralization
|
* distributed applications from composition without centralization
|
||||||
* communication, access and transactional security as first class citizens
|
* communication, access and transactional security as first class citizens
|
||||||
* extensibility through adapter/wrapper services
|
* extensibility through adapter/wrapper services
|
||||||
@ -18,13 +18,12 @@ Additional resources and support are available:
|
|||||||
|
|
||||||
* [Youtube](https://www.youtube.com/channel/UC3b5eFyKRFlEMwSJ1BTjpbw)
|
* [Youtube](https://www.youtube.com/channel/UC3b5eFyKRFlEMwSJ1BTjpbw)
|
||||||
* [Github](https://github.com/fluencelabs)
|
* [Github](https://github.com/fluencelabs)
|
||||||
* [Discord](https://discord.gg/aR2AYErM)
|
* [Discord](https://fluence.chat)
|
||||||
* [Telegram](https://t.me/fluence_project)
|
* [Telegram](https://t.me/fluence\_project)
|
||||||
* [Twitter](https://twitter.com/fluence_project)
|
* [Twitter](https://twitter.com/fluence\_project)
|
||||||
|
|
||||||
Documentation is work in progress and your feedback is extremely valuable and much appreciated. If you have suggestions or unearth errors or inaccuracies, please open an Issue or push a PR.
|
Documentation is work in progress and your feedback is extremely valuable and much appreciated. If you have suggestions or unearth errors or inaccuracies, please open an Issue or push a PR.
|
||||||
|
|
||||||
Thank You and Enjoy,
|
Thank You and Enjoy,
|
||||||
|
|
||||||
The Fluence Team
|
The Fluence Team
|
||||||
|
|
||||||
|
34
SUMMARY.md
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
# Table of contents
|
||||||
|
|
||||||
|
* [Introduction](README.md)
|
||||||
|
* [Thinking In Aquamarine](p2p.md)
|
||||||
|
* [Concepts](concepts.md)
|
||||||
|
* [Quick Start](quick-start/README.md)
|
||||||
|
* [1. Browser-to-Browser](quick-start/1.-browser-to-browser-1.md)
|
||||||
|
* [2. Hosted Services](quick-start/2.-hosted-services.md)
|
||||||
|
* [3. Browser-to-Service](quick-start/3.-browser-to-service.md)
|
||||||
|
* [4. Service Composition And Reuse With Aqua](quick-start/4.-service-composition-and-reuse-with-aqua.md)
|
||||||
|
* [5. Decentralized Oracles With Fluence And Aqua](quick-start/5.-decentralized-oracles-with-fluence-and-aqua.md)
|
||||||
|
* [Aquamarine](knowledge\_aquamarine/README.md)
|
||||||
|
* [Aqua](knowledge\_aquamarine/hll.md)
|
||||||
|
* [Marine](knowledge\_aquamarine/marine/README.md)
|
||||||
|
* [Marine CLI](knowledge\_aquamarine/marine/marine-cli.md)
|
||||||
|
* [Marine REPL](knowledge\_aquamarine/marine/marine-repl.md)
|
||||||
|
* [Marine Rust SDK](knowledge\_aquamarine/marine/marine-rs-sdk.md)
|
||||||
|
* [Tools](knowledge\_tools.md)
|
||||||
|
* [Node](node.md)
|
||||||
|
* [Fluence JS](fluence-js/README.md)
|
||||||
|
* [Concepts](fluence-js/1\_concepts.md)
|
||||||
|
* [Basics](fluence-js/2\_basics.md)
|
||||||
|
* [Running app in nodejs](fluence-js/5\_run\_in\_node.md)
|
||||||
|
* [Running app in browser](fluence-js/4\_run\_in\_browser-1.md)
|
||||||
|
* [In-depth](fluence-js/3\_in\_depth.md)
|
||||||
|
* [API reference](fluence-js/6-reference.md)
|
||||||
|
* [Changelog](fluence-js/changelog.md)
|
||||||
|
* [Security](knowledge\_security.md)
|
||||||
|
* [Tutorials](tutorials\_tutorials/README.md)
|
||||||
|
* [Setting Up Your Environment](tutorials\_tutorials/recipes\_setting\_up.md)
|
||||||
|
* [Deploy A Local Fluence Node](tutorials\_tutorials/tutorial\_run\_local\_node.md)
|
||||||
|
* [cUrl As A Service](tutorials\_tutorials/curl-as-a-service.md)
|
||||||
|
* [Add Your Own Builtins](tutorials\_tutorials/add-your-own-builtin.md)
|
||||||
|
* [Research, Papers And References](research-papers-and-references.md)
|
143
concepts.md
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
# Concepts
|
||||||
|
|
||||||
|
## Concepts
|
||||||
|
|
||||||
|
The Fluence solution enables a new class of decentralized Web3 solutions providing technical, security and business benefits otherwise not available. In order for solution architects and developers to realize these benefits, a shift in philosophy and implementation is required. With the Fluence tool chain available, developers should find it possible to code meaningful Web3 solutions in short order once an understanding of the core concepts and Aqua is in place.
|
||||||
|
|
||||||
|
The remainder of this section introduces the core concepts underlying the Fluence solution.
|
||||||
|
|
||||||
|
### **Particles**
|
||||||
|
|
||||||
|
Particles are Fluence's secure distributed state medium, i.e., conflict free replication data structures containing application data, workflow scripts and some metadata, that traverse programmatically specified routes in a highly secure manner. That is, _particles_ hop from distributed compute service to distributed compute service across the peer-to-peer network as specified by the application workflow updating along the way.
|
||||||
|
|
||||||
|
Figure 4: Node-Service Perspective Of Particle Workflow
|
||||||
|
|
||||||
|
![](https://i.imgur.com/u4beJgh.png)
|
||||||
|
|
||||||
|
Not surprisingly, particles are an integral part of the Fluence protocol and stack. It is the very decoupling of data + workflow instructions from the service and network components that allows the secure composition of applications from services distributed across a permissionless peer-to-peer network.
|
||||||
|
|
||||||
|
While the application state change resulting from passing a particle "through" a service with respect of the data components is quite obvious, the ensuing state change with respect to the workflow also needs to be recognized, which is handled by the Aqua VM.
|
||||||
|
|
||||||
|
As depicted in Figure 4, a particle traverses to a destination node's Aqua VM where the next execution step is evaluated and, if specified, triggered. That is, the service programmatically specified to operate on the particle's data is called from the Aqua VM, the particle's data and workflow (step) are updated and the Aqua VM routes the particle to the next specified destination, which may be on the same, another or the client peer.
|
||||||
|
|
||||||
|
### **Aqua**
|
||||||
|
|
||||||
|
An integral enabler of the Fluence solution is Aqua, an open source language purpose-built to enable developers to ergonomically program distributed networks and applications by composition. Aqua scripts compile to an intermediary representation, called AIR, which execute on the Aqua Virtual Machine, Aqua VM, itself a Wasm module hosted on the Marine interpreter on every peer node.
|
||||||
|
|
||||||
|
Figure 5: From Aqua Script To Particle Execution
|
||||||
|
|
||||||
|
![](<.gitbook/assets/image (5).png>)
|
||||||
|
|
||||||
|
Currently, compiled Aqua scripts can be executed from Typescript clients based on [Fluence SDK](https://github.com/fluencelabs/fluence-js). For more information about Aqua, see the [Aqua book](https://doc.fluence.dev/aqua-book/).
|
||||||
|
|
||||||
|
### **Marine**
|
||||||
|
|
||||||
|
Marine is Fluence's generalized Wasm runtime executing Wasm Interface Type (IT) modules with Aqua VM compatible interfaces on each peer. Let's unpack.
|
||||||
|
|
||||||
|
Services behave similarly to microservices: They are created on nodes and served by the Marine VM and can _only_ be called by Aqua VM. They also are passive in that they can accept incoming calls but can't initiate an outgoing request without being called.
|
||||||
|
|
||||||
|
Services are
|
||||||
|
|
||||||
|
* comprised of Wasm IT modules that can be composed into applications
|
||||||
|
* developed in Rust for a wasm32-wasi compile target
|
||||||
|
* deployed on one or more nodes
|
||||||
|
* running on the Marine VM which is deployed to every node
|
||||||
|
|
||||||
|
Figure 6: Stylized Execution Flow On Peer
|
||||||
|
|
||||||
|
![](<.gitbook/assets/image (6).png>)
|
||||||
|
|
||||||
|
Please note that the Aqua VM is itself a Wasm module running on the Marine VM.
|
||||||
|
|
||||||
|
The [Marine Rust SDK](https://github.com/fluencelabs/marine-rs-sdk) abstracts the Wasm IT implementation detail behind a handy macro that allows developers to easily create Marine VM compatible Wasm modules. In the example below, applying the `marine` macro turns a basic Rust function into a Wasm IT compatible function and enforces the types requirements at the compiler level.
|
||||||
|
|
||||||
|
```rust
|
||||||
|
#[marine]
|
||||||
|
pub fn greeting(name: String) -> String {
|
||||||
|
format!("Hi, {}", name)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### **Services**
|
||||||
|
|
||||||
|
Services are logical constructs instantiated from Wasm modules that contain some business logic and configuration data. That is, services are created, i.e., linked, at the Marine VM runtime level from uploaded Wasm modules and the relevant metadata
|
||||||
|
|
||||||
|
_Blueprints_ are json documents that provide the necessary information to build a service from the associated Wasm modules.
|
||||||
|
|
||||||
|
Figure 7: Service Composition and Execution Model
|
||||||
|
|
||||||
|
![](<.gitbook/assets/image (7).png>)
|
||||||
|
|
||||||
|
Please note that services are not capable to accept more than one request at any given time. Consider a service, FooBar, comprised of two functions, foo() and bar() where foo is a longer running function.
|
||||||
|
|
||||||
|
```
|
||||||
|
-- Stylized FooBar service with two functions
|
||||||
|
-- foo() and bar()
|
||||||
|
-- foo is long-running
|
||||||
|
--- if foo is called before bar, bar is blocked
|
||||||
|
service FooBar("service-id"):
|
||||||
|
bar() -> string
|
||||||
|
foo() -> string --< long running function
|
||||||
|
|
||||||
|
func foobar(node:string, service_id:string, func_name:string) -> string:
|
||||||
|
res: *string
|
||||||
|
on node:
|
||||||
|
BlockedService service_id
|
||||||
|
if func_name == "foo":
|
||||||
|
res <- BlockedService.foo()
|
||||||
|
else:
|
||||||
|
res <- BlockedService.bar()
|
||||||
|
<- res!
|
||||||
|
```
|
||||||
|
|
||||||
|
As long as foo() is running, the entire FooBar service, including bar(), is blocked. This has implications with respect to both service granularity and redundancy.
|
||||||
|
|
||||||
|
### **Modules**
|
||||||
|
|
||||||
|
In the Fluence solution, Wasm IT modules take one of three forms:
|
||||||
|
|
||||||
|
* Facade Module: expose the API of the service comprised of one or more modules. Every service has exactly one facade module
|
||||||
|
* Pure Module: perform computations without side-effects
|
||||||
|
* Effector Module: perform at least one computation with a side-effect
|
||||||
|
|
||||||
|
It is important for architects and developers to be aware of their module and services construction with respect to state changes.
|
||||||
|
|
||||||
|
### **Authentication And Permissioning**
|
||||||
|
|
||||||
|
Authentication at the service API level is an inherent feature of the Fluence solution. This fine-grained approach essentially provides [ambient authority](https://en.wikipedia.org/wiki/Ambient\_authority) out of the box.
|
||||||
|
|
||||||
|
In the Fluence solution, this is accomplished by a SecurityTetraplet, which is data structure with four data fields:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
struct SecurityTetraplet:
|
||||||
|
peer_id: string
|
||||||
|
service_id: string
|
||||||
|
fn_name: string
|
||||||
|
getter: string
|
||||||
|
```
|
||||||
|
|
||||||
|
SecurityTetraplets are provided with the function call arguments for each (service) function call and are checked by the called service. Hence, authentication based on the **(service caller id == service owner id)** relation can be established at service ingress and leveraged to build powerful, fine-grained identity and access management solutions enabling true zero trust architectures.
|
||||||
|
|
||||||
|
### **Trust Layer**
|
||||||
|
|
||||||
|
The Fluence protocol offers an alternative to node selection, i.e. connection and permissioning, approaches, such as [Kademlia](https://en.wikipedia.org/wiki/Kademlia), called TrustGraph. A TrustGraph is comprised of subjectively weights assigned to nodes to manage peer connections. TrustGraphs are node operator specific and transitive. That is, a trusted node's trusted neighbors are considered trustworthy.
|
||||||
|
|
||||||
|
{% hint style="info" %}
|
||||||
|
[TrustGraph](https://github.com/fluencelabs/trust-graph) is currently under active development. Please check the repo for progress.
|
||||||
|
{% endhint %}
|
||||||
|
|
||||||
|
## **Application**
|
||||||
|
|
||||||
|
An application is the "frontend" to one or more services and their execution sequence. Applications are developed by coordinating one or more services into a logical compute unit and tend to live outside the Fluence network**,** e.g., the browser as a peer-client. They can be executed in various runtime environments ranging from browsers to backend daemons.
|
||||||
|
|
||||||
|
#### **Scaling Applications**
|
||||||
|
|
||||||
|
As discussed previously, decoupling at the network and business logic levels is at the core of the Fluence protocol and provides the major entry points for scaling solutions.
|
||||||
|
|
||||||
|
At the peer-to-peer network level, scaling can be achieved with subnetworks. Subnetworks are currently under development and we will update this section in the near future.
|
||||||
|
|
||||||
|
At the service level, we can achieve scale through parallelization due to the decoupling of resource management from infrastructure. That is, sequential and parallel execution flow logic are an inherent part of Aqua's programming model. In order to be able to achieve concurrency, the target services need to be available on multiple peers as module calls are blocking.
|
||||||
|
|
||||||
|
Figure 8: Stylized Par Execution
|
||||||
|
|
||||||
|
![](<.gitbook/assets/image (8).png>)
|
43
fluence-js/1_concepts.md
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
# Concepts
|
||||||
|
|
||||||
|
## Creating applications with Aqua language
|
||||||
|
|
||||||
|
The official way to write applications for Fluence is using Aqua programming language. Aqua compiler emits TypeScript or JavaScript which in turn can be called from a js-based environment. The compiler outputs code for the following entities:
|
||||||
|
|
||||||
|
1. Exported `func` declarations are turned into callable async functions
|
||||||
|
2. Exported `service` declarations are turned into functions which register callback handler in a typed manner
|
||||||
|
|
||||||
|
To learn more about Aqua see [aqua book](https://doc.fluence.dev/aqua-book/)
|
||||||
|
|
||||||
|
The building block of the application are:
|
||||||
|
|
||||||
|
* Aqua code for peer-to-peer communication
|
||||||
|
* Compiler cli package for aqua to (java)typescript compilation
|
||||||
|
* Initialization of the `FluencePeer`
|
||||||
|
* Application specific code (java)typescript in the framework of your choice
|
||||||
|
|
||||||
|
In the next section we see it in action
|
||||||
|
|
||||||
|
## Facade API
|
||||||
|
|
||||||
|
The main entry point `@fluencelabs/fluence` is `Fluence` facade. It provides easy way to start and stop the Fluence Peer. The facade API is enough for the most of the uses cases.
|
||||||
|
|
||||||
|
## Fluence peer in JS
|
||||||
|
|
||||||
|
`@fluencelabs/fluence` package also exports the `FluencePeer` class. This class implements the Fluence protocol for javascript-based environments. It provides all the necessary features to communicate with Fluence network namely:
|
||||||
|
|
||||||
|
1. Connectivity with one or many Fluence Node which allows sending particles to and receiving from other Peers
|
||||||
|
2. The Peer Id identifying the node in the network
|
||||||
|
3. Aqua VM which allows the execution of air scripts inside particles
|
||||||
|
4. A set of builtin functions required by Fluence protocol
|
||||||
|
5. Support for the typescript code which is generated by Aqua compiler
|
||||||
|
|
||||||
|
Even though the js-based implementation closely resembles [node](https://doc.fluence.dev/docs/node) there are some considerable differences to the latter.
|
||||||
|
|
||||||
|
`FluencePeer` does not host services composed of wasm modules. Instead it allows to register service call handlers directly in javascript. The Aqua language compiler creates a typed helpers for that task.
|
||||||
|
|
||||||
|
Due to the limitations of browser-based environment `FluencePeer` cannot be discovered by it's Peer Id on it's own. To overcome this `FluencePeer` must use an existing node which will act as a `relay`. When a peer is connected through a relay it is considered to be `client`. The `FluencePeer` routes all it's particle through it's relay thus taking advantage of the peer discovery implemented on the node. A particle sent to the connected client must be routed through it's relay.
|
||||||
|
|
||||||
|
The js-based peer does not implement the full set of builtin functions due the limitations described previously. E.g there is no built-ins implementation for _kad_ or _srv_ services. However _op_ service is fully implemented. For the full descriptions of implemented built-ins refer to [Api reference](https://doc.fluence.dev/docs/fluence-js/6-reference)
|
||||||
|
|
||||||
|
In contrast with the node implementation `FluencePeer` can initiate new particles execution. Aqua compiler generates executable functions from `func` definitions in aqua code.
|
194
fluence-js/2_basics.md
Normal file
@ -0,0 +1,194 @@
|
|||||||
|
# Basics
|
||||||
|
|
||||||
|
## Intro
|
||||||
|
|
||||||
|
In this section we will show you how Fluence JS can be used to create a hello world application with Fluence stack.
|
||||||
|
|
||||||
|
## Aqua code
|
||||||
|
|
||||||
|
Let's start with the aqua code first:
|
||||||
|
|
||||||
|
```
|
||||||
|
import Peer from "@fluencelabs/aqua-lib/builtin.aqua" -- (1)
|
||||||
|
|
||||||
|
service HelloWorld("hello-world"): -- (2)
|
||||||
|
hello(str: string)
|
||||||
|
getFortune() -> string
|
||||||
|
|
||||||
|
func sayHello(): -- (3)
|
||||||
|
HelloWorld.hello("Hello, world!")
|
||||||
|
|
||||||
|
func tellFortune() -> string: -- (4)
|
||||||
|
res <- HelloWorld.getFortune()
|
||||||
|
<- res
|
||||||
|
|
||||||
|
func getRelayTime() -> u64: -- (5)
|
||||||
|
on HOST_PEER_ID:
|
||||||
|
ts <- Peer.timestamp_ms()
|
||||||
|
<- ts
|
||||||
|
```
|
||||||
|
|
||||||
|
We need to import definitions to call standard Peer operations (1)
|
||||||
|
|
||||||
|
This file has three definitions.
|
||||||
|
|
||||||
|
(2) is a service named `HelloWorld`. A Service interfaces functions executable on a peer. We will register a handler for this interface in our typescript application.
|
||||||
|
|
||||||
|
(3) and (4) are functions `sayHello` and `tellFortune` correspondingly. These functions very simple. The only thing the first one does is calling the `hello` method of `HelloWorld` service located on the current peer. Similarly `tellFortune` calls the `getFortune` method from the same service and returns the value to the caller. We will show you how to call these function from the typescript application.
|
||||||
|
|
||||||
|
Finally we have a function (5) which demonstrate how to work with the network. It asks the current time from the relay peer and return back the our peer.
|
||||||
|
|
||||||
|
## Installing dependencies
|
||||||
|
|
||||||
|
Initialize an empty npm package:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm init
|
||||||
|
```
|
||||||
|
|
||||||
|
We will need these two packages for the application runtime
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install @fluencelabs/fluence @fluencelabs/fluence-network-environment
|
||||||
|
```
|
||||||
|
|
||||||
|
The first one is the SDK itself and the second is a maintained list of Fluence networks and nodes to connect to.
|
||||||
|
|
||||||
|
Aqua compiler cli has to be installed, but is not needed at runtime.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install --save-dev @fluencelabs/aqua
|
||||||
|
```
|
||||||
|
|
||||||
|
Aqua comes with the standard library which can accessed from "@fluencelabs/aqua-lib" package. All the aqua packages are only needed at compiler time, so we install it as a development dependency
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install --save-dev @fluencelabs/aqua-lib
|
||||||
|
```
|
||||||
|
|
||||||
|
Also we might want to have aqua source files automatically recompiled on every save. We will take advantage of chokidar for that:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install --save-dev chokidar-cli
|
||||||
|
```
|
||||||
|
|
||||||
|
And last, but no least we will need TypeScript
|
||||||
|
|
||||||
|
```
|
||||||
|
npm install --save-dev typescript
|
||||||
|
npx tsc --init
|
||||||
|
```
|
||||||
|
|
||||||
|
## Setting up aqua compiler
|
||||||
|
|
||||||
|
Let's put aqua described earlier into `aqua/hello-world.aqua` file. You probably want to keep the generated TypeScript in the same directory with other typescript files, usually `src`. Let's create the `src/_aqua` directory for that.
|
||||||
|
|
||||||
|
The overall project structure looks like this:
|
||||||
|
|
||||||
|
```
|
||||||
|
┣ aqua
|
||||||
|
┃ ┗ hello-world.aqua
|
||||||
|
┣ src
|
||||||
|
┃ ┣ _aqua
|
||||||
|
┃ ┃ ┗ hello-world.ts
|
||||||
|
┃ ┗ index.ts
|
||||||
|
┣ package-lock.json
|
||||||
|
┣ package.json
|
||||||
|
┗ tsconfig.json
|
||||||
|
```
|
||||||
|
|
||||||
|
The Aqua compiler can be run with `npm`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npx aqua -i ./aqua/ -o ./src/_aqua
|
||||||
|
```
|
||||||
|
|
||||||
|
We recommend to store this logic inside a script in `packages.json` file:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
{
|
||||||
|
...
|
||||||
|
"scripts": {
|
||||||
|
...
|
||||||
|
"compile-aqua": "aqua -i ./aqua/ -o ./src/_aqua", // (1)
|
||||||
|
"watch-aqua": "chokidar \"**/*.aqua\" -c \"npm run compile-aqua\"" // (2)
|
||||||
|
},
|
||||||
|
...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
`compile-aqua` (1) runs the compilation once, producing `src/_aqua/hello-world.ts` in our case `watch-aqua` (2) starts watching for any changes in .aqua files recompiling them on the fly
|
||||||
|
|
||||||
|
## Using the compiled code in typescript application
|
||||||
|
|
||||||
|
Using the code generated by the compiler is as easy as calling a function. The compiler generates all the boilerplate needed to send a particle into the network and wraps it into a single call. It also generate a function for service callback registration. Note that all the type information and therefore type checking and code completion facilities are there!
|
||||||
|
|
||||||
|
Let's see how use generated code in our application. `index.ts`:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { Fluence } from "@fluencelabs/fluence";
|
||||||
|
import { krasnodar } from "@fluencelabs/fluence-network-environment"; // (1)
|
||||||
|
import {
|
||||||
|
registerHelloWorld,
|
||||||
|
sayHello,
|
||||||
|
getRelayTime,
|
||||||
|
tellFortune,
|
||||||
|
} from "./_aqua/hello-world"; // (2)
|
||||||
|
|
||||||
|
async function main() {
|
||||||
|
await Fluence.start({ connectTo: krasnodar[0] }); // (3)
|
||||||
|
|
||||||
|
// (4)
|
||||||
|
registerHelloWorld({
|
||||||
|
hello: (str) => {
|
||||||
|
console.log(str);
|
||||||
|
},
|
||||||
|
getFortune: async () => {
|
||||||
|
await new Promise((resolve) => {
|
||||||
|
setTimeout(resolve, 1000);
|
||||||
|
});
|
||||||
|
return "Wealth awaits you very soon.";
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
await sayHello(); // (4)
|
||||||
|
|
||||||
|
console.log(await tellFortune()); // (6)
|
||||||
|
|
||||||
|
const relayTime = await getRelayTime();
|
||||||
|
|
||||||
|
console.log("The relay time is: ", new Date(relayTime).toLocaleString());
|
||||||
|
|
||||||
|
await Fluence.stop(); // (7)
|
||||||
|
}
|
||||||
|
|
||||||
|
main();
|
||||||
|
```
|
||||||
|
|
||||||
|
(1) Import list of possible relay nodes (network environment)
|
||||||
|
|
||||||
|
(2) Aqua compiler provides functions which can be directly imported like any normal typescript function.
|
||||||
|
|
||||||
|
(3) A Fluence peer has to be started before running any application in Fluence Network. For the vast majority of use cases you should use `Fluence` facade to start and stop the peer. The `start` method accepts a parameters object which. The most common parameter is the address of the relay node the peer should connect to. In this example we are using the first node of the `krasnodar` network. If you do not specify the `connectTo` options will only be able to execute air on the local machine only. Please keep in mind that the init function is asynchronous.
|
||||||
|
|
||||||
|
For every exported `service XXX` definition in aqua code, the compiler provides a `registerXXX` counterpart. These functions provide a type-safe way of registering callback handlers for the services. The callbacks are executed when the appropriate service is called in aqua on the current peer. The handlers take form of the object where keys are the name of functions and the values are async functions used as the corresponding callbacks. For example in (4) we are registering handlers for `HelloWorld` service functions which outputs it's parameter to the console. Please note that the handlers can be implemented in both: synchronous and asynchronous way. The handler can be made asynchronous like any other function in javascript: either return a Promise or mark it with async keyword to take advantage of async-await pattern.
|
||||||
|
|
||||||
|
For every exported `func XXX` definition in aqua code, the compiler provides an async function which can be directly called from typescript. In (5, 6) we are calling exported aqua function with no arguments. Note that every function is asynchronous.
|
||||||
|
|
||||||
|
(7) You should call `stop` when the peer is no longer needed. As a rule of thumb all the peers should be uninitialized before destroying the application.
|
||||||
|
|
||||||
|
Let's try running the example:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
node -r ts-node/register src/index.ts
|
||||||
|
```
|
||||||
|
|
||||||
|
If everything has been done correctly yuo should see `Hello, world!` in the console.
|
||||||
|
|
||||||
|
The next section will cover in-depth and advanced usage of Fluence JS
|
||||||
|
|
||||||
|
The code from this section is available in on [github](https://github.com/fluencelabs/examples/tree/main/fluence-js-examples/hello-world)
|
||||||
|
|
||||||
|
## Running Fluence application in different environments
|
||||||
|
|
||||||
|
Fluence JS instantiates Aqua Virtual Machine (AVM) from wasm file and runs it in the background thread. Different mechanism are used depending on the JS environment. In nodejs worker threads are used for background execution and wasm file is read from the filesystem. In browser-based environments web workers are used and the wasm file is being loaded from server hosting the application. Next two sections cover how to configure a fluence application depending on the environment.
|
529
fluence-js/3_in_depth.md
Normal file
@ -0,0 +1,529 @@
|
|||||||
|
# In-depth
|
||||||
|
|
||||||
|
## Intro
|
||||||
|
|
||||||
|
In this section we will cover the Fluence JS in-depth.
|
||||||
|
|
||||||
|
## Fluence
|
||||||
|
|
||||||
|
`@fluencelabs/fluence` exports a facade `Fluence` which provides all the needed functionality for the most uses cases. It defined 4 functions:
|
||||||
|
|
||||||
|
* `start`: Start the default peer.
|
||||||
|
* `stop`: Stops the default peer
|
||||||
|
* `getStatus`: Gets the status of the default peer. This includes connection
|
||||||
|
* `getPeer`: Gets the default Fluence Peer instance (see below)
|
||||||
|
|
||||||
|
Under the hood `Fluence` facade calls the corresponding method on the default instance of FluencePeer. This instance is passed to the Aqua-compiler generated functions by default.
|
||||||
|
|
||||||
|
## FluencePeer class
|
||||||
|
|
||||||
|
The second export `@fluencelabs/fluence` package is `FluencePeer` class. It is useful in scenarios when the application need to run several different peer at once. The overall workflow with the `FluencePeer` is the following:
|
||||||
|
|
||||||
|
1. Create an instance of the peer
|
||||||
|
2. Starting the peer
|
||||||
|
3. Using the peer in the application
|
||||||
|
4. Stopping the peer
|
||||||
|
|
||||||
|
To create a new peer simple instantiate the `FluencePeer` class:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const peer = new FluencePeer();
|
||||||
|
```
|
||||||
|
|
||||||
|
The constructor simply creates a new object and does not initialize any workflow. The `start` function starts the Aqua VM, initializes the default call service handlers and (optionally) connect to the Fluence network. The function takes an optional object specifying additional peer configuration. On option you will be using a lot is `connectTo`. It tells the peer to connect to a relay. For example:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
await peer.star({
|
||||||
|
connectTo: krasnodar[0],
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
connects to the first node of the Krasnodar network. You can find the officially maintained list networks in the `@fluencelabs/fluence-network-environment` package. The full list of supported options is described in the [API reference](https://github.com/fluencelabs/gitbook-docs/tree/77344eb147c2ce17fe1c0f37013082fc85c1ffa3/js-sdk/js-sdk/6\_reference/modules.md)
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
await peer.stop();
|
||||||
|
```
|
||||||
|
|
||||||
|
## Using multiple peers in one application
|
||||||
|
|
||||||
|
The peer by itself does not do any useful work. You should take advantage of functions generated by the Aqua compiler.
|
||||||
|
|
||||||
|
If your application needs several peers, you should create a separate `FluencePeer` instance for each of them. The generated functions accept the peer as the first argument. For example:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { FluencePeer } from "@fluencelabs/fluence";
|
||||||
|
import {
|
||||||
|
registerSomeService,
|
||||||
|
someCallableFunction,
|
||||||
|
} from "./_aqua/someFunction";
|
||||||
|
|
||||||
|
async function main() {
|
||||||
|
const peer1 = new FluencePeer();
|
||||||
|
const peer2 = new FluencePeer();
|
||||||
|
|
||||||
|
// Don't forget to initialize peers
|
||||||
|
await peer1.start({
|
||||||
|
connectTo: relay,
|
||||||
|
});
|
||||||
|
await peer2.start({
|
||||||
|
connectTo: relay,
|
||||||
|
});
|
||||||
|
|
||||||
|
// ... more application logic
|
||||||
|
|
||||||
|
// Pass the peer as the first argument
|
||||||
|
// ||
|
||||||
|
// \/
|
||||||
|
registerSomeService(peer1, {
|
||||||
|
handler: async (str) => {
|
||||||
|
console.log("Called service on peer 1: " str);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// Pass the peer as the first argument
|
||||||
|
// ||
|
||||||
|
// \/
|
||||||
|
registerSomeService(peer2, {
|
||||||
|
handler: async (str) => {
|
||||||
|
console.log("Called service on peer 2: " str);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// Pass the peer as the first argument
|
||||||
|
// ||
|
||||||
|
// \/
|
||||||
|
await someCallableFunction(peer1, arg1, arg2, arg3);
|
||||||
|
|
||||||
|
|
||||||
|
await peer1.stop();
|
||||||
|
await peer2.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ... more application logic
|
||||||
|
```
|
||||||
|
|
||||||
|
It is possible to combine usage of the default peer with another one. Pay close attention to which peer you are calling the functions against.
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Registering handler for the default peerS
|
||||||
|
registerSomeService({
|
||||||
|
handler: async (str) => {
|
||||||
|
console.log("Called against the default peer: " str);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// Pay close attention to this
|
||||||
|
// ||
|
||||||
|
// \/
|
||||||
|
registerSomeService(someOtherPeer, {
|
||||||
|
handler: async (str) => {
|
||||||
|
console.log("Called against the peer named someOtherPeer: " str);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
## Understanding the Aqua compiler output
|
||||||
|
|
||||||
|
Aqua compiler emits TypeScript or JavaScript which in turn can be called from a js-based environment. The compiler outputs code for the following entities:
|
||||||
|
|
||||||
|
1. Exported `func` declarations are turned into callable async functions
|
||||||
|
2. Exported `service` declarations are turned into functions which register callback handler in a typed manner
|
||||||
|
3. For every exported `service` the compiler generated it's interface under the name `{serviceName}Def`
|
||||||
|
|
||||||
|
### Function definitions
|
||||||
|
|
||||||
|
For every exported function definition in aqua the compiler generated two overloads. One accepting the `FluencePeer` instance as the first argument, and one without it. Otherwise arguments are the same and correspond to the arguments of aqua functions. The last argument is always an optional config object with the following properties:
|
||||||
|
|
||||||
|
* `ttl`: Optional parameter which specify TTL (time to live) of particle with execution logic for the function
|
||||||
|
|
||||||
|
The return type is always a promise of the aqua function return type. If the function does not return anything, the return type will be `Promise<void>`.
|
||||||
|
|
||||||
|
Consider the following example:
|
||||||
|
|
||||||
|
```
|
||||||
|
func myFunc(arg0: string, arg1: string):
|
||||||
|
-- implementation
|
||||||
|
```
|
||||||
|
|
||||||
|
The compiler will generate the following overloads:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
export async function myFunc(
|
||||||
|
arg0: string,
|
||||||
|
arg1: string,
|
||||||
|
config?: { ttl?: number }
|
||||||
|
): Promise<void>;
|
||||||
|
|
||||||
|
export async function callMeBack(
|
||||||
|
peer: FluencePeer,
|
||||||
|
arg0: string,
|
||||||
|
arg1: string,
|
||||||
|
config?: { ttl?: number }
|
||||||
|
): Promise<void>;
|
||||||
|
```
|
||||||
|
|
||||||
|
### Service definitions
|
||||||
|
|
||||||
|
```
|
||||||
|
service ServiceName:
|
||||||
|
-- service interface
|
||||||
|
```
|
||||||
|
|
||||||
|
For every exported `service` declaration the compiler will generate two entities: service interface under the name `{serviceName}Def` and a function named `register{serviceName}` with several overloads. First let's describe the most complete one using the following example:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
export interface ServiceNameDef {
|
||||||
|
//... service function definitions
|
||||||
|
}
|
||||||
|
|
||||||
|
export function registerServiceName(
|
||||||
|
peer: FluencePeer,
|
||||||
|
serviceId: string,
|
||||||
|
service: ServiceNameDef
|
||||||
|
): void;
|
||||||
|
```
|
||||||
|
|
||||||
|
* `peer` - the Fluence Peer instance where the handler should be registered. The peer can be omitted. In that case the default Fluence Peer will be used instead
|
||||||
|
* `serviceId` - the name of the service id. If the service was defined with the default service id in aqua code, this argument can be omitted.
|
||||||
|
* `service` - the handler for the service.
|
||||||
|
|
||||||
|
Depending on whether or not the services was defined with the default id the number of overloads will be different. In the case it **is defined**, there would be four overloads:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// (1)
|
||||||
|
export function registerServiceName(
|
||||||
|
//
|
||||||
|
service: ServiceNameDef
|
||||||
|
): void;
|
||||||
|
|
||||||
|
// (2)
|
||||||
|
export function registerServiceName(
|
||||||
|
serviceId: string,
|
||||||
|
service: ServiceNameDef
|
||||||
|
): void;
|
||||||
|
|
||||||
|
// (3)
|
||||||
|
export function registerServiceName(
|
||||||
|
peer: FluencePeer,
|
||||||
|
service: ServiceNameDef
|
||||||
|
): void;
|
||||||
|
|
||||||
|
// (4)
|
||||||
|
export function registerServiceName(
|
||||||
|
peer: FluencePeer,
|
||||||
|
serviceId: string,
|
||||||
|
service: ServiceNameDef
|
||||||
|
): void;
|
||||||
|
```
|
||||||
|
|
||||||
|
1. Uses default Fluence Peer and the default id taken from aqua definition
|
||||||
|
2. Uses default Fluence Peer and specifies the service id explicitly
|
||||||
|
3. The default id is taken from aqua definition. The peer is specified explicitly
|
||||||
|
4. Specifying both peer and the service id.
|
||||||
|
|
||||||
|
If the default id **is not defined** in aqua code the overloads will exclude ones without service id:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// (1)
|
||||||
|
export function registerServiceName(
|
||||||
|
serviceId: string,
|
||||||
|
service: ServiceNameDef
|
||||||
|
): void;
|
||||||
|
|
||||||
|
// (2)
|
||||||
|
export function registerServiceName(
|
||||||
|
peer: FluencePeer,
|
||||||
|
serviceId: string,
|
||||||
|
service: ServiceNameDef
|
||||||
|
): void;
|
||||||
|
```
|
||||||
|
|
||||||
|
1. Uses default Fluence Peer and specifies the service id explicitly
|
||||||
|
2. Specifying both peer and the service id.
|
||||||
|
|
||||||
|
### Service interface
|
||||||
|
|
||||||
|
The service interface type follows closely the definition in aqua code. It has the form of the object which keys correspond to the names of service members and the values are functions of the type translated from aqua definition (see Type convertion). For example, for the following aqua definition:
|
||||||
|
|
||||||
|
```
|
||||||
|
service Calc("calc"):
|
||||||
|
add(n: f32)
|
||||||
|
subtract(n: f32)
|
||||||
|
multiply(n: f32)
|
||||||
|
divide(n: f32)
|
||||||
|
reset()
|
||||||
|
getResult() -> f32
|
||||||
|
```
|
||||||
|
|
||||||
|
The typescript interface will be:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
export interface CalcDef {
|
||||||
|
add: (n: number, callParams: CallParams<"n">) => void | Promise<void>;
|
||||||
|
subtract: (n: number, callParams: CallParams<"n">) => void | Promise<void>;
|
||||||
|
multiply: (n: number, callParams: CallParams<"n">) => void | Promise<void>;
|
||||||
|
divide: (n: number, callParams: CallParams<"n">) => void | Promise<void>;
|
||||||
|
reset: (callParams: CallParams<null>) => void | Promise<void>;
|
||||||
|
getResult: (callParams: CallParams<null>) => number | Promise<number>;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
`CallParams` will be described later in the section
|
||||||
|
|
||||||
|
### Type conversion
|
||||||
|
|
||||||
|
Basic types conversion is pretty much straightforward:
|
||||||
|
|
||||||
|
* `string` is converted to `string` in typescript
|
||||||
|
* `bool` is converted to `boolean` in typescript
|
||||||
|
* All number types (`u8`, `u16`, `u32`, `u64`, `s8`, `s16`, `s32`, `s64`, `f32`, `f64`) are converted to `number` in typescript
|
||||||
|
|
||||||
|
Arrow types translate to functions in typescript which have their arguments translated to typescript types. In addition to arguments defined in aqua, typescript counterparts have an additional argument for call params. For the majority of use cases this parameter is not needed and can be omitted.
|
||||||
|
|
||||||
|
The type conversion works the same way for `service` and `func` definitions. For example a `func` with a callback might look like this:
|
||||||
|
|
||||||
|
```
|
||||||
|
func callMeBack(callback: string, i32 -> ()):
|
||||||
|
callback("hello, world", 42)
|
||||||
|
```
|
||||||
|
|
||||||
|
The type for `callback` argument will be:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
callback: (arg0: string, arg1: number, callParams: CallParams<'arg0' | 'arg1'>) => void | Promise<void>,
|
||||||
|
```
|
||||||
|
|
||||||
|
For the service definitions arguments are named (see calc example above)
|
||||||
|
|
||||||
|
### Using asynchronous code in callbacks
|
||||||
|
|
||||||
|
Typescript code generated by Aqua compiler has two scenarios where a user should specify a callback function. These are services and callback arguments of function in aqua. If you look at the return type of the generated function you will see a union of callback return type and the promise with this type, e.g `string | Promise<string>`. Fluence-js supports both sync and async version of callbacks and figures out which one is used under the hood. The callback be made asynchronous like any other function in javascript: either return a Promise or mark it with async keyword to take advantage of async-await pattern.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
```
|
||||||
|
func withCallback(callback: string -> ()):
|
||||||
|
callback()
|
||||||
|
|
||||||
|
service MyService:
|
||||||
|
callMe(string)
|
||||||
|
```
|
||||||
|
|
||||||
|
Here we are returning a promise
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
registerMyService({
|
||||||
|
callMe: (arg): Promise<void> => {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
setTimeout(() => {
|
||||||
|
console.log("I'm running 3 seconds after call");
|
||||||
|
resolve();
|
||||||
|
}, 3000);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
And here we are using async-await pattern
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
await withCallback(async (arg) => {
|
||||||
|
const data = await getStuffFromDatabase(arg);
|
||||||
|
console.log("");
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
### Call params and tetraplets
|
||||||
|
|
||||||
|
Each service call is accompanied by additional information specific to Fluence Protocol. Including `initPeerId` - the peer which initiated the particle execution, particle signature and most importantly security tetraplets. All this data is contained inside the last `callParams` argument in every generated function definition. These data is passed to the handler on each function call can be used in the application.
|
||||||
|
|
||||||
|
Tetraplets have the form of:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
{
|
||||||
|
argName0: SecurityTetraplet[],
|
||||||
|
argName1: SecurityTetraplet[],
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
To learn more about tetraplets and application security see [Security](../knowledge\_security.md)
|
||||||
|
|
||||||
|
To see full specification of `CallParams` type see [API reference](6-reference.md)
|
||||||
|
|
||||||
|
## Signing service
|
||||||
|
|
||||||
|
Signing service is useful when you want to sign arbitrary data and pass it further inside a single aqua script. Signing service allows to restrict its usage for security reasons: e.g you don't want to sign anything except it comes from a trusted source. The aqua side API is the following:
|
||||||
|
|
||||||
|
```
|
||||||
|
data SignResult:
|
||||||
|
-- Was call successful or not
|
||||||
|
success: bool
|
||||||
|
-- Error message. Will be null if the call is successful
|
||||||
|
error: ?string
|
||||||
|
-- Signature as byte array. Will be null if the call is not successful
|
||||||
|
signature: ?[]u8
|
||||||
|
|
||||||
|
-- Available only on FluenceJS peers
|
||||||
|
-- The service can also be resolved by it's host peer id
|
||||||
|
service Sig("sig"):
|
||||||
|
-- Signs data with the private key used by signing service.
|
||||||
|
-- Depending on implementation the service might check call params to restrict usage for security reasons.
|
||||||
|
-- By default signing service is only allowed to be used on the same peer the particle was initiated
|
||||||
|
-- and accepts data only from the following sources:
|
||||||
|
-- trust-graph.get_trust_bytes
|
||||||
|
-- trust-graph.get_revocation_bytes
|
||||||
|
-- registry.get_key_bytes
|
||||||
|
-- registry.get_record_bytes
|
||||||
|
-- registry.get_host_record_bytes
|
||||||
|
-- Argument: data - byte array to sign
|
||||||
|
-- Returns: signature as SignResult structure
|
||||||
|
sign(data: []u8) -> SignResult
|
||||||
|
|
||||||
|
-- Given the data and signature both as byte arrays, returns true if the signature is correct, false otherwise.
|
||||||
|
verify(signature: []u8, data: []u8) -> bool
|
||||||
|
|
||||||
|
-- Gets service's public key.
|
||||||
|
get_pub_key() -> string
|
||||||
|
```
|
||||||
|
|
||||||
|
FluenceJS ships the service implementation as the JavaScript class:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
/**
|
||||||
|
* Whether signing operation is allowed or not.
|
||||||
|
* Implemented as a predicate of CallParams.
|
||||||
|
*/
|
||||||
|
export type SigSecurityGuard = (params: CallParams<"data">) => boolean;
|
||||||
|
|
||||||
|
export class Sig implements SigDef {
|
||||||
|
private _keyPair: KeyPair;
|
||||||
|
|
||||||
|
constructor(keyPair: KeyPair) {
|
||||||
|
this._keyPair = keyPair;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Security guard predicate
|
||||||
|
*/
|
||||||
|
securityGuard: SigSecurityGuard;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the public key of KeyPair. Required by aqua
|
||||||
|
*/
|
||||||
|
get_pub_key() {
|
||||||
|
// implementation ommited
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Signs the data using key pair's private key. Required by aqua
|
||||||
|
*/
|
||||||
|
async sign(
|
||||||
|
data: number[],
|
||||||
|
callParams: CallParams<"data">
|
||||||
|
): Promise<SignResult> {
|
||||||
|
// implementation ommited
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verifies the signature. Required by aqua
|
||||||
|
*/
|
||||||
|
verify(signature: number[], data: number[]): Promise<boolean> {
|
||||||
|
// implementation ommited
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
`securityGuard` specifies the way the `sign` method checks where the incoming data is allowed to be signed or not. It accepts one argument: call params (see "Call params and tetraplets") and must return either true or false. Any predicate can be specified. Also, FluenceJS is shipped with a set of useful predicates:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
/**
|
||||||
|
* Only allow calls when tetraplet for 'data' argument satisfies the predicate
|
||||||
|
*/
|
||||||
|
export const allowTetraplet = (pred: (tetraplet: SecurityTetraplet) => boolean): SigSecurityGuard => {/*...*/};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Only allow data which comes from the specified serviceId and fnName
|
||||||
|
*/
|
||||||
|
export const allowServiceFn = (serviceId: string, fnName: string): SigSecurityGuard => {/*...*/};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Only allow data originated from the specified json_path
|
||||||
|
*/
|
||||||
|
export const allowExactJsonPath = (jsonPath: string): SigSecurityGuard => {/*...*/};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Only allow signing when particle is initiated at the specified peer
|
||||||
|
*/
|
||||||
|
export const allowOnlyParticleOriginatedAt = (peerId: PeerIdB58): SigSecurityGuard => {/*...*/};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Only allow signing when all of the predicates are satisfied.
|
||||||
|
* Useful for predicates reuse
|
||||||
|
*/
|
||||||
|
export const and = (...predicates: SigSecurityGuard[]): SigSecurityGuard => {/*...*/};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Only allow signing when any of the predicates are satisfied.
|
||||||
|
* Useful for predicates reuse
|
||||||
|
*/
|
||||||
|
export const or = (...predicates: SigSecurityGuard[]): SigSecurityGuard => {/*...*/};
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
Predicates as well as the `Sig` definition can be found in `@fluencelabs/fluence/dist/services`
|
||||||
|
|
||||||
|
`Sig` class is accompanied by `registerSig` which allows registering different signing services with different keys. The mechanism is exactly the same as with ordinary aqua services e.g:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// create a key per from pk bytes
|
||||||
|
const customKeyPair = await KeyPair.fromEd25519SK(pkBytes);
|
||||||
|
|
||||||
|
// create a signing service with the specific key pair
|
||||||
|
const customSig = new Sig(customKeyPair);
|
||||||
|
|
||||||
|
// restrict sign usage to our needs
|
||||||
|
customSig.securityGuard = allowServiceFn("my_service", "my_function");
|
||||||
|
|
||||||
|
// register the service. Please note, that service id ("CustomSig" here) has to be specified.
|
||||||
|
registerSig("CustomSig", customSig);
|
||||||
|
```
|
||||||
|
|
||||||
|
for a [non-default peer](3\_in\_depth.md#using-multiple-peers-in-one-application), the instance has to be specified:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const peer = new FluencePeer();
|
||||||
|
await peer.start();
|
||||||
|
|
||||||
|
// ...
|
||||||
|
|
||||||
|
registerSig(peer, "CustomSig", customSig);
|
||||||
|
```
|
||||||
|
|
||||||
|
`FluencePeer` ships with the default signing service implementation, registered with id "Sig". Is is useful to work with TrustGraph and Registry API. The default implementation has the following restrictions on the `sign` operation:
|
||||||
|
|
||||||
|
* Only allowed to be used on the same peer the particle was initiated
|
||||||
|
* Restricts data to following services:
|
||||||
|
* trust-graph.get\_trust\_bytes
|
||||||
|
* trust-graph.get\_revocation\_bytes
|
||||||
|
* registry.get\_key\_bytes
|
||||||
|
* registry.get\_record\_bytes
|
||||||
|
* Argument: data - byte array to sign
|
||||||
|
|
||||||
|
The default signing service class can be accessed in the following way:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// for default FluencePeer:
|
||||||
|
const sig = Fluence.getPeer().getServices().sig;
|
||||||
|
|
||||||
|
// for non-default FluencePeer:
|
||||||
|
// const peer = FluencePeer();
|
||||||
|
// await peer.start()
|
||||||
|
const sig = peer.getServices().sig;
|
||||||
|
|
||||||
|
// change securityGuard for the default service:
|
||||||
|
sig.securityGuard = or(
|
||||||
|
sig.securityGuard,
|
||||||
|
allowServiceFn("my_service", "my_function")
|
||||||
|
);
|
||||||
|
```
|
28
fluence-js/4_run_in_browser-1.md
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
# Running app in browser
|
||||||
|
|
||||||
|
You can use the Fluence JS with any framework (or even without it). The "fluence" part of the application is a collection of pure typescript\javascript functions which can be called withing any framework of your choosing.
|
||||||
|
|
||||||
|
## Configuring application to run in browser
|
||||||
|
|
||||||
|
To run application in browser you need to configure the server which hosts the application to serve two additional files:
|
||||||
|
|
||||||
|
* `avm.wasm` is the execution file of AquaVM. The file is located in `@fluencelabs/avm` package
|
||||||
|
* `runnerScript.web.js` is the web worker script responsible for running AVM in background. The file is located in `@fluencelabs/avm-runner-background` package
|
||||||
|
|
||||||
|
Fluence JS provides a utility script named `copy-avm-public` which locates described above files and copies them into the specified directory. For example if static files are served from the `public` directory you can run `copy-avm-public public` to copy files needed to run Fluence. It is recommended to put their names into `.gitignore` and run the script on every build to prevent possible inconsistencies with file versions. This can be done using npm's `postinstall` script:
|
||||||
|
|
||||||
|
```
|
||||||
|
...
|
||||||
|
"scripts": {
|
||||||
|
"postinstall": "copy-avm-public public",
|
||||||
|
"start": "...",
|
||||||
|
..
|
||||||
|
},
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
## Demo applications
|
||||||
|
|
||||||
|
See the browser-example which demonstrate integrating Fluence with React: [github](https://github.com/fluencelabs/examples/tree/main/fluence-js-examples/browser-example)
|
||||||
|
|
||||||
|
Also take a look at FluentPad. It is an example application written in React: [https://github.com/fluencelabs/fluent-pad](https://github.com/fluencelabs/fluent-pad)
|
124
fluence-js/5_run_in_node.md
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
# Running app in nodejs
|
||||||
|
|
||||||
|
It is easy to use Fluence JS in NodeJS applications. You can take full advantage of the javascript ecosystem and at the save time expose service to the Fluence Network. That makes is an excellent choice for quick prototyping of applications for Fluence Stack.
|
||||||
|
|
||||||
|
## Configuring application to run in nodejs
|
||||||
|
|
||||||
|
`@fluencelabs/fluence` delivers AquaVM wasm file through the npm package. No additional configuration is needed.
|
||||||
|
|
||||||
|
## Calc app example
|
||||||
|
|
||||||
|
Lets implement a very simple app which simulates a desk calculator. The calculator has internal memory and implements the following set of operations:
|
||||||
|
|
||||||
|
* Add a number
|
||||||
|
* Subtract a number
|
||||||
|
* Multiply by a number
|
||||||
|
* Divide by a number
|
||||||
|
* Get the current memory state
|
||||||
|
* Reset the memory state to 0.0
|
||||||
|
|
||||||
|
First, let's write the service definition in aqua:
|
||||||
|
|
||||||
|
```
|
||||||
|
-- service definition
|
||||||
|
service Calc("calc"):
|
||||||
|
add(n: f32)
|
||||||
|
subtract(n: f32)
|
||||||
|
multiply(n: f32)
|
||||||
|
divide(n: f32)
|
||||||
|
reset()
|
||||||
|
getResult() -> f32
|
||||||
|
```
|
||||||
|
|
||||||
|
Now write the implementation for this service in typescript:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { Fluence } from "@fluencelabs/fluence";
|
||||||
|
import { krasnodar } from "@fluencelabs/fluence-network-environment";
|
||||||
|
import { registerCalc, CalcDef } from "./_aqua/calc";
|
||||||
|
|
||||||
|
class Calc implements CalcDef {
|
||||||
|
private _state: number = 0;
|
||||||
|
|
||||||
|
add(n: number) {
|
||||||
|
this._state += n;
|
||||||
|
}
|
||||||
|
|
||||||
|
subtract(n: number) {
|
||||||
|
this._state -= n;
|
||||||
|
}
|
||||||
|
|
||||||
|
multiply(n: number) {
|
||||||
|
this._state *= n;
|
||||||
|
}
|
||||||
|
|
||||||
|
divide(n: number) {
|
||||||
|
this._state /= n;
|
||||||
|
}
|
||||||
|
|
||||||
|
reset() {
|
||||||
|
this._state = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
getResult() {
|
||||||
|
return this._state;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const keypress = async () => {
|
||||||
|
process.stdin.setRawMode(true);
|
||||||
|
return new Promise<void>((resolve) =>
|
||||||
|
process.stdin.once("data", () => {
|
||||||
|
process.stdin.setRawMode(false);
|
||||||
|
resolve();
|
||||||
|
})
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
async function main() {
|
||||||
|
await Fluence.start({
|
||||||
|
connectTo: krasnodar[0],
|
||||||
|
});
|
||||||
|
|
||||||
|
registerCalc(new Calc());
|
||||||
|
|
||||||
|
console.log("application started");
|
||||||
|
console.log("peer id is: ", Fluence.getStatus().peerId);
|
||||||
|
console.log("relay is: ", Fluence.getStatus().relayPeerId);
|
||||||
|
console.log("press any key to continue");
|
||||||
|
await keypress();
|
||||||
|
|
||||||
|
await Fluence.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
main();
|
||||||
|
```
|
||||||
|
|
||||||
|
As you can see all the service logic has been implemented in typescript. You have full power of npm at your disposal.
|
||||||
|
|
||||||
|
Now try running the application:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
> node -r ts-node/register src/index.ts
|
||||||
|
|
||||||
|
application started
|
||||||
|
peer id is: 12D3KooWLBkw4Tz8bRoSriy5WEpHyWfU11jEK3b5yCa7FBRDRWH3
|
||||||
|
relay is: 12D3KooWSD5PToNiLQwKDXsu8JSysCwUt8BVUJEqCHcDe7P5h45e
|
||||||
|
press any key to continue
|
||||||
|
```
|
||||||
|
|
||||||
|
And the service can be called from aqua. For example:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
const peer ?= "12D3KooWLBkw4Tz8bRoSriy5WEpHyWfU11jEK3b5yCa7FBRDRWH3"
|
||||||
|
const relay ?= "12D3KooWSD5PToNiLQwKDXsu8JSysCwUt8BVUJEqCHcDe7P5h45e"
|
||||||
|
|
||||||
|
func demoCalculation() -> f32:
|
||||||
|
on peer via relay
|
||||||
|
Calc.add(10)
|
||||||
|
Calc.multiply(5)
|
||||||
|
Calc.subtract(8)
|
||||||
|
Calc.divide(6)
|
||||||
|
res <- Calc.getResult()
|
||||||
|
<- res
|
||||||
|
```
|
3
fluence-js/6-reference.md
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# API reference
|
||||||
|
|
||||||
|
API reference is available at [http://fluence.one/fluence-js/](http://fluence.one/fluence-js/)
|
13
fluence-js/README.md
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
# Fluence JS
|
||||||
|
|
||||||
|
Fluence JS is an implementation of the Fluence protocol for JavaScript-based environments. It can connect browsers, Node.js applications, and so on to the Fluence p2p network.
|
||||||
|
|
||||||
|
Similar to the [Rust Fluence Peer implementation](https://github.com/fluencelabs/fluence) it includes:
|
||||||
|
|
||||||
|
* Peer-to-peer communication layer (via [js-libp2p](https://github.com/libp2p/js-libp2p))
|
||||||
|
* [Aqua VM](https://github.com/fluencelabs/aquavm)
|
||||||
|
* Builtin services
|
||||||
|
|
||||||
|
Fluence JS can call services and functions on the Fluence network, and expose new APIs to the p2p network directly from TypeScript and JavaScript. [Aqua language](https://github.com/fluencelabs/aqua) uses Fluence JS as a compilation target, and they are designed to [work in tandem](https://doc.fluence.dev/docs/js-sdk/3\_in\_depth#understanding-the-aqua-compiler-output).
|
||||||
|
|
||||||
|
Fluence JS can be used with any framework of your choice (or even without frameworks).
|
137
fluence-js/changelog.md
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
# Changelog
|
||||||
|
|
||||||
|
Fluence JS versioning scheme is the following: `0.BREAKING.ENHANCING`
|
||||||
|
|
||||||
|
* `0` shows that Fluence JS does not meet its vision yet, so API can change quickly
|
||||||
|
* `BREAKING` part is incremented for each breaking API change
|
||||||
|
* `ENHANCING` part is incremented for every fix and update which is compatible on API level
|
||||||
|
|
||||||
|
## [0.20.2](https://github.com/fluencelabs/fluence-js/releases/tag/v0.19.1) – February 23, 2022
|
||||||
|
|
||||||
|
Fix copy-avm-public script: include marine-js.wasm to the copy process ([#134](https://github.com/fluencelabs/fluence-js/pull/134))
|
||||||
|
|
||||||
|
## [0.20.1](https://github.com/fluencelabs/fluence-js/releases/tag/v0.19.1) – February 21, 2022
|
||||||
|
|
||||||
|
Add missing builtins, Implement timestamps\_ms and timestamps\_sec ([#133](https://github.com/fluencelabs/fluence-js/pull/133))
|
||||||
|
|
||||||
|
## [0.20.0](https://github.com/fluencelabs/fluence-js/releases/tag/v0.19.1) – February 18, 2022
|
||||||
|
|
||||||
|
Switch to marine-web based AquaVM runner ([#132](https://github.com/fluencelabs/fluence-js/pull/132))
|
||||||
|
|
||||||
|
## [0.19.2](https://github.com/fluencelabs/fluence-js/releases/tag/v0.19.1) – February 17, 2022
|
||||||
|
|
||||||
|
Using polyfill for Buffer in browsers ([#129](https://github.com/fluencelabs/fluence-js/pull/129))
|
||||||
|
|
||||||
|
Implement additional builtins: array\_length, sha256\_string, concat\_strings ([#130](https://github.com/fluencelabs/fluence-js/pull/130))
|
||||||
|
|
||||||
|
Implement debug.stringify service ([#125](https://github.com/fluencelabs/fluence-js/pull/125))
|
||||||
|
|
||||||
|
Update avm version to 0.20.5 ([#131](https://github.com/fluencelabs/fluence-js/pull/131))
|
||||||
|
|
||||||
|
## [0.19.1](https://github.com/fluencelabs/fluence-js/releases/tag/v0.19.1) – February 4, 2022
|
||||||
|
|
||||||
|
Sig service redesign. ([#126](https://github.com/fluencelabs/fluence-js/pull/126))
|
||||||
|
|
||||||
|
## [0.19.0](https://github.com/fluencelabs/fluence-js/releases/tag/v0.19.0) – January 27, 2022
|
||||||
|
|
||||||
|
Update libp2p-related packages versions. Fix 'stream reset' error. ([#123](https://github.com/fluencelabs/fluence-js/pull/123))
|
||||||
|
|
||||||
|
## [0.18.0](https://github.com/fluencelabs/fluence-js/releases/tag/v0.18.0) – December 29, 2021
|
||||||
|
|
||||||
|
FluencePeer: Update AVM version to 0.20.0 ([#120](https://github.com/fluencelabs/fluence-js/pull/120))
|
||||||
|
|
||||||
|
## [0.17.1](https://github.com/fluencelabs/fluence-js/releases/tag/v0.17.1) – December 29, 2021
|
||||||
|
|
||||||
|
FluencePeer: Update AvmRunner to 0.1.2 (fix issue with incorrect baseUrl) ([#119](https://github.com/fluencelabs/fluence-js/pull/119))
|
||||||
|
|
||||||
|
## [0.17.0](https://github.com/fluencelabs/fluence-js/releases/tag/v0.17.0) – December 28, 2021
|
||||||
|
|
||||||
|
JS Peer does not embed AVM interpreter any more. Instead [AVM Runner](https://github.com/fluencelabs/avm-runner-background) is used to run AVM in background giving huge performance boost. This is a **breaking change**: all browser applications now not need to bundle `avm.wasm` file and the runner script. See [documentation](4\_run\_in\_browser-1.md) for more info.
|
||||||
|
|
||||||
|
([#111](https://github.com/fluencelabs/fluence-js/pull/120))
|
||||||
|
|
||||||
|
## [0.16.0](https://github.com/fluencelabs/fluence-js/releases/tag/v0.16.0) – December 22, 2021
|
||||||
|
|
||||||
|
FluencePeer: Update AVM version to 0.19.3 ([#115](https://github.com/fluencelabs/fluence-js/pull/115))
|
||||||
|
|
||||||
|
## [0.15.4](https://github.com/fluencelabs/fluence-js/releases/tag/v0.15.4) – December 13, 2021
|
||||||
|
|
||||||
|
FluencePeer: Update AVM version to 0.17.7 ([#113](https://github.com/fluencelabs/fluence-js/pull/113))
|
||||||
|
|
||||||
|
## [0.15.3](https://github.com/fluencelabs/fluence-js/releases/tag/v0.15.3) – December 10, 2021
|
||||||
|
|
||||||
|
**FluencePeer:**
|
||||||
|
|
||||||
|
* Add built-in service to sign data and verify signatures ([#110](https://github.com/fluencelabs/fluence-js/pull/110))
|
||||||
|
* Update AVM version to 0.17.6 ([#112](https://github.com/fluencelabs/fluence-js/pull/112))
|
||||||
|
|
||||||
|
## [0.15.2](https://github.com/fluencelabs/fluence-js/releases/tag/v0.15.2) – November 30, 2021
|
||||||
|
|
||||||
|
Add particleId to error message when an aqua function times out ([#106](https://github.com/fluencelabs/fluence-js/pull/106))
|
||||||
|
|
||||||
|
## [0.15.1](https://github.com/fluencelabs/fluence-js/releases/tag/v0.15.0) – November 28, 2021
|
||||||
|
|
||||||
|
**FluencePeer:**
|
||||||
|
|
||||||
|
* Fix timeout builtin error message ([#103](https://github.com/fluencelabs/fluence-js/pull/103))
|
||||||
|
|
||||||
|
**Compiler support:**
|
||||||
|
|
||||||
|
Issue fixes for `registerService` function
|
||||||
|
|
||||||
|
* Throwing error if registerService was called on a non-initialized peer.
|
||||||
|
* Fix issue with incorrect context being passed to class-based implementations of user services
|
||||||
|
* Fix typo in JSDoc
|
||||||
|
|
||||||
|
([#104](https://github.com/fluencelabs/fluence-js/pull/104))
|
||||||
|
|
||||||
|
## [0.15.0](https://github.com/fluencelabs/fluence-js/releases/tag/v0.15.0) – November 17, 2021
|
||||||
|
|
||||||
|
**FluencePeer:**
|
||||||
|
|
||||||
|
* Implement peer.timeout built-in function ([#101](https://github.com/fluencelabs/fluence-js/pull/101))
|
||||||
|
* Update AVM: add support for the restriction operator ([#102](https://github.com/fluencelabs/fluence-js/pull/102))
|
||||||
|
|
||||||
|
## [0.14.3](https://github.com/fluencelabs/fluence-js/releases/tag/v0.14.3) – November 10, 2021
|
||||||
|
|
||||||
|
**FluencePeer:**
|
||||||
|
|
||||||
|
* Extend error handling. Now aqua function calls fail early with the user-friendly error message ([#91](https://github.com/fluencelabs/fluence-js/pull/98))
|
||||||
|
|
||||||
|
**Compiler support:**
|
||||||
|
|
||||||
|
* Define and export FnConfig interface ([#97](https://github.com/fluencelabs/fluence-js/pull/97))
|
||||||
|
* Fix issue with incorrect TTL value in function calls config ([#100](https://github.com/fluencelabs/fluence-js/pull/100))
|
||||||
|
|
||||||
|
## [0.14.2](https://github.com/fluencelabs/fluence-js/releases/tag/v0.14.2) – October 21, 2021
|
||||||
|
|
||||||
|
FluencePeer: add option to specify default TTL for all new particles ([#91](https://github.com/fluencelabs/fluence-js/pull/91))
|
||||||
|
|
||||||
|
## [0.14.1](https://github.com/fluencelabs/fluence-js/releases/tag/v0.14.1) – October 20, 2021
|
||||||
|
|
||||||
|
Compiler support: fix issue with incorrect check for missing fields in service registration ([#90](https://github.com/fluencelabs/fluence-js/pull/90))
|
||||||
|
|
||||||
|
## [0.14.0](https://github.com/fluencelabs/fluence-js/releases/tag/v0.14.0) – October 20, 2021
|
||||||
|
|
||||||
|
Compiler support: added support for asynchronous code in service definitions and callback parameters of functions. ([#83](https://github.com/fluencelabs/fluence-js/pull/83))
|
||||||
|
|
||||||
|
## [0.12.1](https://github.com/fluencelabs/fluence-js/releases/tag/v0.12.1) – September 14, 2021
|
||||||
|
|
||||||
|
* `KeyPair`: add fromBytes, toEd25519PrivateKey ([#78](https://github.com/fluencelabs/fluence-js/pull/78))
|
||||||
|
|
||||||
|
## [0.12.0](https://github.com/fluencelabs/fluence-js/releases/tag/v0.13.0) – September 10, 2021
|
||||||
|
|
||||||
|
* The API to work with the default Fluence Peer has been put under the facade `Fluence`. Method `init` was renamed to `start` and `uninit` renamed to `stop`. `connectionStatus` migrated to `getStatus`.
|
||||||
|
|
||||||
|
To migrate from 0.11.0 to 0.12.0
|
||||||
|
|
||||||
|
1. `import { Fluence } from "@fluencelabs/fluence"`; instead of `FluencePeer`
|
||||||
|
2. replace `Fluence.default` with just `Fluence`
|
||||||
|
3. replace `init` with `start` and `uninit` with `stop`
|
||||||
|
4. replace `connectionInfo()` with `getStatus()`
|
||||||
|
|
||||||
|
([#72](https://github.com/fluencelabs/fluence-js/pull/72))
|
||||||
|
|
||||||
|
## [0.11.0](https://github.com/fluencelabs/fluence-js/releases/tag/v0.11.0) – September 08, 2021
|
||||||
|
|
||||||
|
* Update JS SDK api to the new version ([#61](https://github.com/fluencelabs/fluence-js/pull/61))
|
6
knowledge_aquamarine/README.md
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
# Aquamarine
|
||||||
|
|
||||||
|
Fluence's Aquamarine stack is comprised of Aqua and Marine. Aqua is a programming language and runtime environment for peer-to-peer workflows. Marine, on the other hand, is a general purpose runtime that executes hosted code on nodes, whereas Aqua facilitates the programming of workflows composed from hosted code. In combination, Aqua and Marine enable any distributed application.
|
||||||
|
|
||||||
|
At the core of Aqua is the design ideal and idea to pair concurrent systems, and especially decentralized networks, with a programming and execution tool chain to avoid centralized bottlenecks commonly introduced with workflow engines and business rule engines. To this end, Aqua manages the communication and coordination between services, devices, and APIs without introducing a centralized gateway and can be used to express various distributed systems: from simple request-response models to comprehensive network consensus algorithms.
|
||||||
|
|
5
knowledge_aquamarine/hll.md
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
# Aqua
|
||||||
|
|
||||||
|
 At the core of Fluence is the open-source language **Aqua** that allows for the programming of peer-to-peer scenarios separately from the computations on peers. 
|
||||||
|
|
||||||
|
Please see the[ Aqua book ](https://doc.fluence.dev/aqua-book/)for an introduction to the language and reference materials.
|