# Intro In this section we will cover the JS SDK in-depth. # FluencePeer class The overall workflow with the `FluencePeer` is the following: 1. Create an instance of the peer 2. Initializing the peer 3. Using the peer in the application 4. Uninitializing 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 `init` 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 additonal 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.init({ connectTo: krasnodar[0], }); ``` connects the first node of the Kranodar 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](js-sdk/6_reference/modules.md) Most of the time a single peer is enough for the whole application. For these use cases`FluncePeer` class contains the default instance which can be accessed with the corresponding property: ```typescript await FluencePeer.default.init(); ``` The peer by itself does not do any useful work. You should take advantage of functions generated by the Aqua compiler. You can use them both with a single peer or in muliple peers scenario. If you are using the default peer for your application you don't need to explicitly pass it: the compiled functions will use the `default` instance in that case (see "Using multiple peers in one applicaton") To uninitialize the peer simply call `uninit` method. It will disconnect from the network and stop the Aqua vm, ```typescript await peer.unint(); ``` # Using multiple peers in one applicaton In most cases using a single peer is enough. However sometimes you might need to run multiple peers inside the same JS environment. When using a single peer you should initialize the `FluencePeer.default` and call Aqua compiler-generated functions without passing any peer. For example: ```typescript import { FluencePeer } from "@fluencelabs/fluence"; import { registerSomeService, someCallableFunction, } from "./_aqua/someFunction"; async function main() { await FluencePeer.default.init({ connectTo: relay, }); // ... more application logic registerSomeService({ handler: async (str) => { console.log(str); }, }); await someCallableFunction(arg1, arg2, arg3); await FluencePeer.default.uninit(); } // ... more application logic ``` If your application needs several peers, you should create a separate `FluncePeer` 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.init({ connectTo: relay, }); await peer2.init({ connectTo: relay, }); // ... more application logic // Pass the peer as the first agument // || // \/ registerSomeService(peer1, { handler: async (str) => { console.log("Called service on peer 1: " str); }, }); // Pass the peer as the first agument // || // \/ registerSomeService(peer2, { handler: async (str) => { console.log("Called service on peer 2: " str); }, }); // Pass the peer as the first agument // || // \/ await someCallableFunction(peer1, arg1, arg2, arg3); await peer1.uninit(); await peer2.uninit(); } // ... 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 peer registerSomeService({ handler: async (str) => { console.log("Called agains the default peer: " str); }, }); // Pay close attention to this // || // \/ registerSomeService(someOthePeer, { 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 environemt. The compiler outputs code for the following entities: 1. Exported `func` declarations are turned into callable async functiokns 2. Exported `service` declarations are turned into functions which register callback handler in a typed manner