feat: Simplify JS Client public API (#257)

This commit is contained in:
Pavel 2023-02-16 14:38:48 +03:00 committed by GitHub
parent 35dfb1bfbc
commit 9daaf41096
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 774 additions and 476 deletions

View File

@ -1,5 +1,9 @@
import "@fluencelabs/registry/resources-api.aqua"
func smokeTest(label: string) -> ?string, *string:
service HelloWorld("hello-world"):
hello(str: string) -> string
func smokeTest(label: string) -> ?string, *string, string:
res, errors <- createResource(label)
<- res, errors
hello <- HelloWorld.hello("Fluence user")
<- res, errors, hello

View File

@ -17,8 +17,8 @@
"author": "Fluence Labs",
"license": "Apache-2.0",
"dependencies": {
"@fluencelabs/js-client.api": "workspace:*",
"@fluencelabs/fluence-network-environment": "1.0.13",
"@fluencelabs/js-client.api": "workspace:^",
"@fluencelabs/fluence-network-environment": "1.0.14",
"base64-js": "1.5.1"
},
"devDependencies": {

View File

@ -1,3 +1,5 @@
/* eslint-disable */
// @ts-nocheck
/**
*
* This file is auto-generated. Do not edit manually: changes may be erased.
@ -6,17 +8,54 @@
* Aqua version: 0.9.4
*
*/
// eslint-disable
//ts-nocheck
import type { IFluenceClient as IFluenceClient$$, CallParams as CallParams$$ } from '@fluencelabs/js-client.api';
import { v5_callFunction as callFunction$$, v5_registerService as registerService$$ } from '@fluencelabs/js-client.api';
// Services
export interface HelloWorldDef {
hello: (str: string, callParams: CallParams$$<'str'>) => string | Promise<string>;
}
export function registerHelloWorld(service: HelloWorldDef): void;
export function registerHelloWorld(serviceId: string, service: HelloWorldDef): void;
export function registerHelloWorld(peer: IFluenceClient$$, service: HelloWorldDef): void;
export function registerHelloWorld(peer: IFluenceClient$$, serviceId: string, service: HelloWorldDef): void;
export function registerHelloWorld(...args: any) {
registerService$$(args, {
defaultServiceId: 'hello-world',
functions: {
tag: 'labeledProduct',
fields: {
hello: {
tag: 'arrow',
domain: {
tag: 'labeledProduct',
fields: {
str: {
tag: 'scalar',
name: 'string',
},
},
},
codomain: {
tag: 'unlabeledProduct',
items: [
{
tag: 'scalar',
name: 'string',
},
],
},
},
},
},
});
}
// Functions
export type SmokeTestResult = [string | null, string[]];
export type SmokeTestResult = [string | null, string[], string];
export function smokeTest(label: string, config?: { ttl?: number }): Promise<SmokeTestResult>;
export function smokeTest(peer: IFluenceClient$$, label: string, config?: { ttl?: number }): Promise<SmokeTestResult>;
@ -27,208 +66,211 @@ export function smokeTest(...args: any) {
(seq
(seq
(seq
(call %init_peer_id% ("getDataSrv" "-relay-") [] -relay-)
(call %init_peer_id% ("getDataSrv" "label") [] label)
)
(new $resource_id
(new $successful
(seq
(seq
(call %init_peer_id% ("getDataSrv" "-relay-") [] -relay-)
(call %init_peer_id% ("getDataSrv" "label") [] label)
)
(new $resource_id
(new $successful
(seq
(seq
(call %init_peer_id% ("peer" "timestamp_sec") [] t)
(xor
(seq
(seq
(call %init_peer_id% ("peer" "timestamp_sec") [] t)
(xor
(seq
(call -relay- ("registry" "get_key_bytes") [label [] t [] ""] bytes)
(xor
(call %init_peer_id% ("sig" "sign") [bytes] result)
(call %init_peer_id% ("errorHandlingSrv" "error") [%last_error% 1])
)
)
(xor
(match result.$.success! false
(ap result.$.error.[0]! $error)
)
(seq
(call -relay- ("registry" "get_key_bytes") [label [] t [] ""] bytes)
(xor
(call %init_peer_id% ("sig" "sign") [bytes] result)
(call %init_peer_id% ("errorHandlingSrv" "error") [%last_error% 1])
)
)
(xor
(match result.$.success! false
(ap result.$.error.[0]! $error)
)
(seq
(seq
(seq
(seq
(seq
(ap result.$.signature! result_flat)
(call -relay- ("registry" "get_key_id") [label %init_peer_id%] id)
(seq
(ap result.$.signature! result_flat)
(call -relay- ("registry" "get_key_id") [label %init_peer_id%] id)
)
(call -relay- ("op" "string_to_b58") [id] k)
)
(call -relay- ("op" "string_to_b58") [id] k)
(call -relay- ("kad" "neighborhood") [k [] []] nodes)
)
(call -relay- ("kad" "neighborhood") [k [] []] nodes)
)
(par
(fold nodes n-0
(par
(seq
(xor
(xor
(seq
(seq
(seq
(call n-0 ("peer" "timestamp_sec") [] t-0)
(call n-0 ("trust-graph" "get_weight") [%init_peer_id% t-0] weight)
)
(call n-0 ("registry" "register_key") [label [] t [] "" result_flat.$.[0]! weight t-0] result-0)
)
(xor
(match result-0.$.success! true
(ap true $successful)
)
(ap result-0.$.error! $error)
)
)
(call n-0 ("op" "noop") [])
)
(seq
(call -relay- ("op" "noop") [])
(call %init_peer_id% ("errorHandlingSrv" "error") [%last_error% 2])
)
)
(call -relay- ("op" "noop") [])
)
(next n-0)
)
(never)
)
(null)
)
)
(new $status
(new $result-1
(seq
(seq
(seq
(par
(seq
(seq
(seq
(call -relay- ("math" "sub") [1 1] sub)
(new $successful_test
(seq
(seq
(seq
(call -relay- ("math" "add") [sub 1] successful_incr)
(fold $successful s
(seq
(seq
(ap s $successful_test)
(canon -relay- $successful_test #successful_iter_canon)
)
(xor
(match #successful_iter_canon.length successful_incr
(null)
)
(next s)
)
)
(never)
)
)
(canon -relay- $successful_test #successful_result_canon)
)
(ap #successful_result_canon successful_gate)
)
)
)
(call -relay- ("math" "sub") [1 1] sub-0)
)
(ap "ok" $status)
)
(call -relay- ("peer" "timeout") [6000 "timeout"] $status)
)
(new $status_test
(seq
(seq
(seq
(call -relay- ("math" "add") [0 1] status_incr)
(fold $status s
(seq
(seq
(ap s $status_test)
(canon -relay- $status_test #status_iter_canon)
)
(xor
(match #status_iter_canon.length status_incr
(null)
)
(next s)
)
)
(never)
)
)
(canon -relay- $status_test #status_result_canon)
)
(ap #status_result_canon status_gate)
)
)
)
(xor
(match status_gate.$.[0]! "ok"
(ap true $result-1)
)
(ap false $result-1)
)
)
(new $result-1_test
(seq
(par
(fold nodes n-0
(par
(seq
(seq
(call -relay- ("math" "add") [0 1] result-1_incr)
(fold $result-1 s
(xor
(xor
(seq
(seq
(ap s $result-1_test)
(canon -relay- $result-1_test #result-1_iter_canon)
(seq
(call n-0 ("peer" "timestamp_sec") [] t-0)
(call n-0 ("trust-graph" "get_weight") [%init_peer_id% t-0] weight)
)
(call n-0 ("registry" "register_key") [label [] t [] "" result_flat.$.[0]! weight t-0] result-0)
)
(xor
(match #result-1_iter_canon.length result-1_incr
(null)
(match result-0.$.success! true
(ap true $successful)
)
(next s)
(ap result-0.$.error! $error)
)
)
(never)
(call n-0 ("op" "noop") [])
)
(seq
(call -relay- ("op" "noop") [])
(call %init_peer_id% ("errorHandlingSrv" "error") [%last_error% 2])
)
)
(canon -relay- $result-1_test #result-1_result_canon)
(call -relay- ("op" "noop") [])
)
(next n-0)
)
(never)
)
(null)
)
)
(new $status
(new $result-1
(seq
(seq
(seq
(par
(seq
(seq
(seq
(call -relay- ("math" "sub") [1 1] sub)
(new $successful_test
(seq
(seq
(seq
(call -relay- ("math" "add") [sub 1] successful_incr)
(fold $successful s
(seq
(seq
(ap s $successful_test)
(canon -relay- $successful_test #successful_iter_canon)
)
(xor
(match #successful_iter_canon.length successful_incr
(null)
)
(next s)
)
)
(never)
)
)
(canon -relay- $successful_test #successful_result_canon)
)
(ap #successful_result_canon successful_gate)
)
)
)
(call -relay- ("math" "sub") [1 1] sub-0)
)
(ap "ok" $status)
)
(call -relay- ("peer" "timeout") [6000 "timeout"] $status)
)
(new $status_test
(seq
(seq
(seq
(call -relay- ("math" "add") [0 1] status_incr)
(fold $status s
(seq
(seq
(ap s $status_test)
(canon -relay- $status_test #status_iter_canon)
)
(xor
(match #status_iter_canon.length status_incr
(null)
)
(next s)
)
)
(never)
)
)
(canon -relay- $status_test #status_result_canon)
)
(ap #status_result_canon status_gate)
)
)
)
(xor
(match status_gate.$.[0]! "ok"
(ap true $result-1)
)
(ap false $result-1)
)
)
(new $result-1_test
(seq
(seq
(seq
(call -relay- ("math" "add") [0 1] result-1_incr)
(fold $result-1 s
(seq
(seq
(ap s $result-1_test)
(canon -relay- $result-1_test #result-1_iter_canon)
)
(xor
(match #result-1_iter_canon.length result-1_incr
(null)
)
(next s)
)
)
(never)
)
)
(canon -relay- $result-1_test #result-1_result_canon)
)
(ap #result-1_result_canon result-1_gate)
)
(ap #result-1_result_canon result-1_gate)
)
)
)
)
)
)
(xor
(match result-1_gate.$.[0]! false
(ap "resource wasn't created: timeout exceeded" $error)
(xor
(match result-1_gate.$.[0]! false
(ap "resource wasn't created: timeout exceeded" $error)
)
(ap id $resource_id)
)
(ap id $resource_id)
)
)
)
(call %init_peer_id% ("errorHandlingSrv" "error") [%last_error% 3])
)
(call %init_peer_id% ("errorHandlingSrv" "error") [%last_error% 3])
)
(canon %init_peer_id% $resource_id #-resource_id-fix-0)
)
(canon %init_peer_id% $resource_id #-resource_id-fix-0)
(ap #-resource_id-fix-0 -resource_id-flat-0)
)
(ap #-resource_id-fix-0 -resource_id-flat-0)
)
)
)
(call %init_peer_id% ("hello-world" "hello") ["Fluence user"] hello)
)
(xor
(seq
(canon %init_peer_id% $error #error_canon)
(call %init_peer_id% ("callbackSrv" "response") [-resource_id-flat-0 #error_canon])
(call %init_peer_id% ("callbackSrv" "response") [-resource_id-flat-0 #error_canon hello])
)
(call %init_peer_id% ("errorHandlingSrv" "error") [%last_error% 4])
)
@ -268,6 +310,10 @@ export function smokeTest(...args: any) {
name: 'string',
},
},
{
tag: 'scalar',
name: 'string',
},
],
},
},
@ -284,3 +330,5 @@ export function smokeTest(...args: any) {
script,
);
}
/* eslint-enable */

View File

@ -1,50 +1,65 @@
import { fromByteArray } from 'base64-js';
import { Fluence } from '@fluencelabs/js-client.api';
import { krasnodar } from '@fluencelabs/fluence-network-environment';
import { smokeTest } from './_aqua/smoke_test.js';
import { kras, randomKras } from '@fluencelabs/fluence-network-environment';
import { registerHelloWorld, smokeTest } from './_aqua/smoke_test.js';
// const relay = {
// multiaddr: '/ip4/127.0.0.1/tcp/4310/ws/p2p/12D3KooWKEprYXUXqoV5xSBeyqrWLpQLLH4PXfvVkDJtmcqmh5V3',
// peerId: '12D3KooWKEprYXUXqoV5xSBeyqrWLpQLLH4PXfvVkDJtmcqmh5V3',
// };
const relay = krasnodar[4];
const relay = randomKras();
const rndSk = () => {
// if (getRandomValues) {
// return getRandomValues(new Uint8Array(32));
// }
// @ts-ignore
// return globalThis.crypto.webcrypto.getRandomValues(new Uint8Array(32));
function generateRandomUint8Array() {
const uint8Array = new Uint8Array(32);
for (let i = 0; i < uint8Array.length; i++) {
uint8Array[i] = Math.floor(Math.random() * 256);
}
return uint8Array;
}
const optsWithRandomKeyPair = () => {
return {
keyPair: {
type: 'Ed25519',
source: generateRandomUint8Array(),
},
} as const;
};
export const main = async () => {
console.log('starting fluence...');
await Fluence.start({
relay: relay,
// keyPair: {
// type: 'Ed25519',
// source: rndSk(),
// },
});
try {
Fluence.onConnectionStateChange((state) => console.info('connection state changed: ', state));
console.log('started fluence');
const p = await Fluence.getPeer();
console.log('connecting to Fluence Network...');
await Fluence.connect(relay, optsWithRandomKeyPair());
console.log('my peer id: ', p.getStatus().peerId);
console.log('my sk id: ', fromByteArray(p.getSk()));
console.log('connected');
console.log('running some aqua...');
const [res, errors] = await smokeTest('my_resource');
if (res === null) {
console.log('aqua failed, errors', errors);
} else {
console.log('aqua finished, result', res);
await registerHelloWorld({
hello(str) {
return 'Hello, ' + str + '!';
},
});
const client = await Fluence.getClient();
console.log('my peer id: ', client.getPeerId());
console.log('my sk id: ', fromByteArray(client.getPeerSecretKey()));
console.log('running some aqua...');
const [res, errors, hello] = await smokeTest('my_resource');
console.log(hello);
if (res === null) {
console.log('aqua failed, errors', errors);
} else {
console.log('aqua finished, result', res);
}
} finally {
console.log('disconnecting from Fluence Network...');
await Fluence.disconnect();
console.log('disconnected');
}
console.log('stopping fluence...');
await Fluence.stop();
console.log('stopped fluence...');
};
export const runMain = () => {

View File

@ -3,8 +3,8 @@
"version": "0.1.0",
"private": true,
"dependencies": {
"@fluencelabs/js-client.api": "workspace:*",
"@test/aqua_for_test": "workspace:*",
"@fluencelabs/js-client.api": "workspace:^",
"@test/aqua_for_test": "workspace:^",
"@testing-library/jest-dom": "5.16.5",
"@testing-library/react": "13.4.0",
"@testing-library/user-event": "13.5.0",

View File

@ -17,9 +17,9 @@
"author": "Fluence Labs",
"license": "Apache-2.0",
"dependencies": {
"@fluencelabs/js-client.api": "workspace:*",
"@fluencelabs/js-client.node": "workspace:*",
"@test/aqua_for_test": "workspace:*"
"@fluencelabs/js-client.api": "workspace:^",
"@fluencelabs/js-client.node": "workspace:^",
"@test/aqua_for_test": "workspace:^"
},
"devDependencies": {}
}

View File

@ -18,7 +18,7 @@
"license": "Apache-2.0",
"dependencies": {},
"devDependencies": {
"@fluencelabs/js-client.web.standalone": "workspace:*",
"@fluencelabs/js-client.web.standalone": "workspace:^",
"http-server": "14.1.1"
}
}

View File

@ -19,7 +19,7 @@ import type { IFluenceClient } from '@fluencelabs/interfaces';
import { getArgumentTypes } from '@fluencelabs/interfaces';
import { isFluencePeer } from '@fluencelabs/interfaces';
import { getDefaultPeer } from '../util.js';
import { getFluenceInterface } from '../util.js';
/**
* Convenience function to support Aqua `func` generation backend
@ -30,12 +30,20 @@ import { getDefaultPeer } from '../util.js';
* @param script - air script with function execution logic generated by the Aqua compiler
*/
export const callFunction = async (rawFnArgs: Array<any>, def: FunctionCallDef, script: string): Promise<unknown> => {
const { args, peer, config } = await extractFunctionArgs(rawFnArgs, def);
return peer.compilerSupport.callFunction({
const { args, client: peer, config } = await extractFunctionArgs(rawFnArgs, def);
if (peer.internals.getConnectionState() !== 'connected') {
throw new Error(
'Could not call the Aqua function because client is disconnected. Did you forget to call Fluence.connect()?',
);
}
const fluence = await getFluenceInterface();
return fluence.callAquaFunction({
args,
def,
script,
config: config || {},
peer: peer,
});
};
@ -47,10 +55,21 @@ export const callFunction = async (rawFnArgs: Array<any>, def: FunctionCallDef,
*/
export const registerService = async (args: any[], def: ServiceDef): Promise<unknown> => {
const { peer, service, serviceId } = await extractServiceArgs(args, def.defaultServiceId);
return peer.compilerSupport.registerService({
// TODO: TBH service registration is just putting some stuff into a hashmap
// there should not be such a check at all
if (peer.internals.getConnectionState() !== 'connected') {
throw new Error(
'Could not register Aqua service because the client is disconnected. Did you forget to call Fluence.connect()?',
);
}
const fluence = await getFluenceInterface();
return fluence.registerService({
def,
service,
serviceId,
peer,
});
};
@ -68,7 +87,7 @@ const extractFunctionArgs = async (
args: any[],
def: FunctionCallDef,
): Promise<{
peer: IFluenceClient;
client: IFluenceClient;
config?: FnConfig;
args: { [key: string]: any };
}> => {
@ -84,7 +103,8 @@ const extractFunctionArgs = async (
structuredArgs = args.slice(1, numberOfExpectedArgs + 1);
config = args[numberOfExpectedArgs + 1];
} else {
peer = await getDefaultPeer();
const fluence = await getFluenceInterface();
peer = fluence.defaultClient;
structuredArgs = args.slice(0, numberOfExpectedArgs);
config = args[numberOfExpectedArgs];
}
@ -96,7 +116,7 @@ const extractFunctionArgs = async (
const argsRes = argumentNames.reduce((acc, name, index) => ({ ...acc, [name]: structuredArgs[index] }), {});
return {
peer: peer,
client: peer,
config: config,
args: argsRes,
};
@ -124,7 +144,8 @@ const extractServiceArgs = async (
if (isFluencePeer(args[0])) {
peer = args[0];
} else {
peer = await getDefaultPeer();
const fluence = await getFluenceInterface();
peer = fluence.defaultClient;
}
if (typeof args[0] === 'string') {

View File

@ -1,5 +1,11 @@
import { getDefaultPeer } from './util.js';
import type { IFluenceClient, ClientOptions } from '@fluencelabs/interfaces';
import { getFluenceInterface, getFluenceInterfaceFromGlobalThis } from './util.js';
import {
IFluenceClient,
ClientOptions,
RelayOptions,
ConnectionState,
ConnectionStates,
} from '@fluencelabs/interfaces';
export type { IFluenceClient, ClientOptions, CallParams } from '@fluencelabs/interfaces';
export {
@ -30,33 +36,56 @@ export {
} from './compilerSupport/implementation.js';
/**
* Public interface to Fluence JS
* Public interface to Fluence Network
*/
export const Fluence = {
/**
* Initializes the default peer: starts the Aqua VM, initializes the default call service handlers
* and (optionally) connect to the Fluence network
* @param options - object specifying peer configuration
* Connect to the Fluence network
* @param relay - relay node to connect to
* @param options - client options
*/
start: async (options?: ClientOptions): Promise<void> => {
const peer = await getDefaultPeer();
return peer.start(options);
connect: async (relay: RelayOptions, options?: ClientOptions): Promise<void> => {
const fluence = await getFluenceInterface();
return fluence.defaultClient.connect(relay, options);
},
/**
* Un-initializes the default peer: stops all the underlying workflows, stops the Aqua VM
* and disconnects from the Fluence network
* Disconnect from the Fluence network
*/
stop: async (): Promise<void> => {
const peer = await getDefaultPeer();
return peer.stop();
disconnect: async (): Promise<void> => {
const fluence = await getFluenceInterface();
return fluence.defaultClient.disconnect();
},
/**
* Get the default peer instance
* @returns the default peer instance
* Handle connection state changes. Immediately returns the current connection state
*/
getPeer: async (): Promise<IFluenceClient> => {
return getDefaultPeer();
onConnectionStateChange(handler: (state: ConnectionState) => void): ConnectionState {
const optimisticResult = getFluenceInterfaceFromGlobalThis();
if (optimisticResult) {
return optimisticResult.defaultClient.onConnectionStateChange(handler);
}
getFluenceInterface().then((fluence) => fluence.defaultClient.onConnectionStateChange(handler));
return 'disconnected';
},
/**
* Low level API. Get the underlying client instance which holds the connection to the network
* @returns IFluenceClient instance
*/
getClient: async (): Promise<IFluenceClient> => {
const fluence = await getFluenceInterface();
return fluence.defaultClient;
},
};
/**
* Low level API. Generally you need Fluence.connect() instead.
* @returns IFluenceClient instance
*/
export const createClient = async (): Promise<IFluenceClient> => {
const fluence = await getFluenceInterface();
return fluence.clientFactory();
};

View File

@ -1,12 +1,23 @@
import type { IFluenceClient } from '@fluencelabs/interfaces';
import type { CallAquaFunction, IFluenceClient, RegisterService } from '@fluencelabs/interfaces';
const getPeerFromGlobalThis = (): IFluenceClient | undefined => {
// @ts-ignore
return globalThis.defaultPeer;
type PublicFluenceInterface = {
clientFactory: () => IFluenceClient;
defaultClient: IFluenceClient;
callAquaFunction: CallAquaFunction;
registerService: RegisterService;
};
// TODO: DXJ-271
const REJECT_MESSAGE = 'You probably forgot to add script tag. Read about it here: ';
export const getFluenceInterfaceFromGlobalThis = (): PublicFluenceInterface | undefined => {
// @ts-ignore
return globalThis.fluence;
};
// TODO: fix link DXJ-271
const REJECT_MESSAGE = `Could not load Fluence JS Client library.
If you are using Node.js that probably means that you forgot in install or import the @fluencelabs/js-client.node package.
If you are using a browser, then you probably forgot to add the <script> tag to your HTML.
Please refer to the documentation page for more details: https://fluence.dev/
`;
// Let's assume that if the library has not been loaded in 5 seconds, then the user has forgotten to add the script tag
const POLL_PEER_TIMEOUT = 5000;
@ -17,7 +28,13 @@ const POLL_PEER_INTERVAL = 100;
/**
* Wait until the js client script it loaded and return the default peer from globalThis
*/
export const getDefaultPeer = (): Promise<IFluenceClient> => {
export const getFluenceInterface = (): Promise<PublicFluenceInterface> => {
// If the script is already loaded, then return the value immediately
const optimisticResult = getFluenceInterfaceFromGlobalThis();
if (optimisticResult) {
return Promise.resolve(optimisticResult);
}
return new Promise((resolve, reject) => {
// This function is internal
// Make it sure that would be zero way for unnecessary types
@ -30,7 +47,7 @@ export const getDefaultPeer = (): Promise<IFluenceClient> => {
reject(REJECT_MESSAGE);
}
let res = getPeerFromGlobalThis();
let res = getFluenceInterfaceFromGlobalThis();
if (res) {
clearInterval(interval);
resolve(res);

View File

@ -1,6 +1,8 @@
import * as platform from 'platform';
import { FluencePeer } from '@fluencelabs/js-peer/dist/js-peer/FluencePeer.js';
import { callAquaFunction } from '@fluencelabs/js-peer/dist/compilerSupport/callFunction.js';
import { registerService } from '@fluencelabs/js-peer/dist/compilerSupport/registerService.js';
import { MarineBasedAvmRunner } from '@fluencelabs/js-peer/dist/js-peer/avm.js';
import { MarineBackgroundRunner } from '@fluencelabs/js-peer/dist/marine/worker/index.js';
import { marineLogFunction } from '@fluencelabs/js-peer/dist/js-peer/utils.js';
@ -20,7 +22,7 @@ export const defaultNames = {
},
};
export const makeDefaultPeer = () => {
export const createClient = () => {
const workerLoader = new WorkerLoader();
const controlModuleLoader = new WasmLoaderFromNpm(defaultNames.marine.package, defaultNames.marine.file);
const avmModuleLoader = new WasmLoaderFromNpm(defaultNames.avm.package, defaultNames.avm.file);
@ -30,8 +32,15 @@ export const makeDefaultPeer = () => {
return new FluencePeer(marine, avm);
};
const publicFluenceInterface = {
clientFactory: createClient,
defaultClient: createClient(),
callAquaFunction,
registerService,
};
// @ts-ignore
globalThis.defaultPeer = makeDefaultPeer();
globalThis.fluence = publicFluenceInterface;
function throwIfNotSupported() {
if (platform.name === 'Node.js' && platform.version) {
@ -39,7 +48,7 @@ function throwIfNotSupported() {
const major = version[0];
if (major < 16) {
throw new Error(
'FluenceJS requires node.js version >= "16.x"; Detected ' +
'Fluence JS Client requires node.js version >= "16.x"; Detected ' +
platform.description +
' Please update node.js to version 16 or higher.\nYou can use https://nvm.sh utility to update node.js version: "nvm install 17 && nvm use 17 && nvm alias default 17"',
);

View File

@ -1,10 +1,12 @@
import { FluencePeer } from '@fluencelabs/js-peer/dist/js-peer/FluencePeer.js';
import { callAquaFunction } from '@fluencelabs/js-peer/dist/compilerSupport/callFunction.js';
import { registerService } from '@fluencelabs/js-peer/dist/compilerSupport/registerService.js';
import { MarineBasedAvmRunner } from '@fluencelabs/js-peer/dist/js-peer/avm.js';
import { MarineBackgroundRunner } from '@fluencelabs/js-peer/dist/marine/worker';
import { checkConnection, marineLogFunction } from '@fluencelabs/js-peer/dist/js-peer/utils.js';
import { InlinedWorkerLoader, InlinedWasmLoader } from '@fluencelabs/js-peer/dist/marine/deps-loader/common.js';
export const makeDefaultPeer = () => {
const createClient = () => {
const workerLoader = new InlinedWorkerLoader('___worker___');
const controlModuleLoader = new InlinedWasmLoader('___marine___');
const avmModuleLoader = new InlinedWasmLoader('___avm___');
@ -14,5 +16,12 @@ export const makeDefaultPeer = () => {
return new FluencePeer(marine, avm);
};
const publicFluenceInterface = {
clientFactory: createClient,
defaultClient: createClient(),
callAquaFunction,
registerService,
};
// @ts-ignore
globalThis.defaultPeer = makeDefaultPeer();
globalThis.fluence = publicFluenceInterface;

View File

@ -53,6 +53,14 @@ type Node = {
};
// TODO: either drop support for this exact type or get it back
/**
* A node in Fluence network a client can connect to.
* Can be in the form of:
* - string: multiaddr in string format
* - Multiaddr: multiaddr object, @see https://github.com/multiformats/js-multiaddr
* - Node: node structure, @see Node
*/
export type RelayOptions = string | /* MultiaddrInput | */ Node;
export type KeyTypes = 'RSA' | 'Ed25519' | 'secp256k1';
@ -66,17 +74,6 @@ export type KeyPairOptions = {
* Configuration used when initiating Fluence Client
*/
export interface ClientOptions {
/**
* Node in Fluence network to connect to.
* Can be in the form of:
* - string: multiaddr in string format
* - Multiaddr: multiaddr object, @see https://github.com/multiformats/js-multiaddr
* - Node: node structure, @see Node
* - Implementation of FluenceConnection class, @see FluenceConnection
* If not specified the will work locally and would not be able to send or receive particles.
*/
relay?: RelayOptions;
/**
* Specify the KeyPair to be used to identify the Fluence Peer.
* Will be generated randomly if not specified
@ -88,7 +85,6 @@ export interface ClientOptions {
* When the peer established the connection to the network it sends a ping-like message to check if it works correctly.
* The options allows to specify the timeout for that message in milliseconds.
* If not specified the default timeout will be used
CallParams,
*/
skipCheckConnection?: boolean;
@ -121,89 +117,68 @@ export interface ClientOptions {
};
}
/**
* Information about Fluence Peer connection.
* Represented as object with the following keys:
* - `isInitialized`: Is the peer initialized or not.
* - `peerId`: Peer Id of the peer. Null if the peer is not initialized
* - `isConnected`: Is the peer connected to network or not
* - `relayPeerId`: Peer Id of the relay the peer is connected to. If the connection is direct relayPeerId is null
* - `isDirect`: True if the peer is connected to the network directly (not through relay)
*/
export type PeerStatus =
| {
isInitialized: false;
peerId: null;
isConnected: false;
relayPeerId: null;
}
| {
isInitialized: true;
peerId: PeerIdB58;
isConnected: false;
relayPeerId: null;
}
| {
isInitialized: true;
peerId: PeerIdB58;
isConnected: true;
relayPeerId: PeerIdB58;
}
| {
isInitialized: true;
peerId: PeerIdB58;
isConnected: true;
isDirect: true;
relayPeerId: null;
};
export type FluenceStartConfig = ClientOptions & { relay: RelayOptions };
export const ConnectionStates = ['disconnected', 'connecting', 'connected', 'disconnecting'] as const;
export type ConnectionState = typeof ConnectionStates[number];
export interface IFluenceClient {
/**
* Get the peer's status
* Connect to the Fluence network
* @param relay - relay node to connect to
* @param options - client options
*/
start(config?: ClientOptions): Promise<void>;
connect: (relay: RelayOptions, options?: ClientOptions) => Promise<void>;
/**
* Un-initializes the peer: stops all the underlying workflows, stops the Aqua VM and disconnects from the Fluence network
* Disconnect from the Fluence network
*/
stop(): Promise<void>;
disconnect(): Promise<void>;
/**
* Get the peer's status
* Handle connection state changes. Immediately returns current connection state
*/
getStatus(): PeerStatus;
onConnectionStateChange(handler: (state: ConnectionState) => void): ConnectionState;
/**
* Return peers SK
* Return peers secret key as byte array.
*/
getSk(): Uint8Array;
getPeerSecretKey(): Uint8Array;
/**
* Return peers public key as a base58 string (multihash/CIDv0).
*/
getPeerId(): string;
// TODO: come up with a working interface for
// - particle creation
// - particle initialization
// - service registration
/**
* For internal use only. Do not call directly
*/
internals: any;
// TODO: extract this out of Client interface
compilerSupport: {
callFunction: (args: CallFunctionArgs) => Promise<unknown>;
registerService: (args: RegisterServiceArgs) => void;
};
}
export interface CallFunctionArgs {
export interface CallAquaFunctionArgs {
def: FunctionCallDef;
script: string;
config: FnConfig;
peer: IFluenceClient;
args: { [key: string]: any };
}
export type CallAquaFunction = (args: CallAquaFunctionArgs) => Promise<unknown>;
export interface RegisterServiceArgs {
peer: IFluenceClient;
def: ServiceDef;
serviceId: string | undefined;
service: any;
}
export type RegisterService = (args: RegisterServiceArgs) => void;
export const asFluencePeer = (fluencePeerCandidate: unknown): IFluenceClient => {
if (isFluencePeer(fluencePeerCandidate)) {
return fluencePeerCandidate;

View File

@ -6,6 +6,7 @@ import {
getArgumentTypes,
isReturnTypeVoid,
IFluenceClient,
CallAquaFunction,
} from '@fluencelabs/interfaces';
import {
@ -29,13 +30,7 @@ import {
* @param args - args in the form of JSON where each key corresponds to the name of the argument
* @returns
*/
export function callFunctionImpl(
def: FunctionCallDef,
script: string,
config: FnConfig,
peer: IFluenceClient,
args: { [key: string]: any },
): Promise<unknown> {
export const callAquaFunction: CallAquaFunction = ({ def, script, config, peer, args }) => {
const argumentTypes = getArgumentTypes(def);
const promise = new Promise((resolve, reject) => {
@ -87,4 +82,4 @@ export function callFunctionImpl(
});
return promise;
}
};

View File

@ -1,20 +1,7 @@
import type { IFluenceClient, ServiceDef } from '@fluencelabs/interfaces';
import type { RegisterService } from '@fluencelabs/interfaces';
import { registerGlobalService, userHandlerService } from './services.js';
export const registerServiceImpl = (
peer: IFluenceClient,
def: ServiceDef,
serviceId: string | undefined,
service: any,
) => {
// TODO: TBH service registration is just putting some stuff into a hashmap
// there should not be such a check at all
if (!peer.getStatus().isInitialized) {
throw new Error(
'Could not register the service because the peer is not initialized. Are you passing the wrong peer to the register function?',
);
}
export const registerService: RegisterService = ({ peer, def, serviceId, service }) => {
// Checking for missing keys
const requiredKeys = def.functions.tag === 'nil' ? [] : Object.keys(def.functions.fields);
const incorrectServiceDefinitions = requiredKeys.filter((f) => !(f in service));

View File

@ -30,7 +30,7 @@ export const injectRelayService = (def: FunctionCallDef, peer: IFluenceClient) =
handler: () => {
return {
retCode: ResultCodes.success,
result: peer.getStatus().relayPeerId,
result: peer.internals.getRelayPeerId(),
};
},
};

View File

@ -27,12 +27,10 @@ import {
import type {
PeerIdB58,
IFluenceClient,
PeerStatus,
CallFunctionArgs,
RegisterServiceArgs,
ClientOptions,
KeyPairOptions,
RelayOptions,
ClientOptions,
ConnectionState,
} from '@fluencelabs/interfaces/dist/fluenceClient';
import { Particle, ParticleExecutionStage, ParticleQueueItem } from './Particle.js';
import { dataToString, jsonify, isString, ServiceError } from './utils.js';
@ -49,18 +47,46 @@ import { LogLevel } from '@fluencelabs/marine-js/dist/types';
import { NodeUtils, Srv } from './builtins/SingleModuleSrv.js';
import { registerNodeUtils } from './_aqua/node-utils.js';
import type { MultiaddrInput } from '@multiformats/multiaddr';
import { callFunctionImpl } from '../compilerSupport/callFunction.js';
import { registerServiceImpl } from '../compilerSupport/registerService.js';
const DEFAULT_TTL = 7000;
export type PeerConfig = ClientOptions;
export type PeerConfig = ClientOptions & { relay?: RelayOptions };
type PeerStatus =
| {
isInitialized: false;
peerId: null;
isConnected: false;
relayPeerId: null;
}
| {
isInitialized: true;
peerId: PeerIdB58;
isConnected: false;
relayPeerId: null;
}
| {
isInitialized: true;
peerId: PeerIdB58;
isConnected: true;
relayPeerId: PeerIdB58;
}
| {
isInitialized: true;
peerId: PeerIdB58;
isConnected: true;
isDirect: true;
relayPeerId: null;
};
/**
* This class implements the Fluence protocol for javascript-based environments.
* It provides all the necessary features to communicate with Fluence network
*/
export class FluencePeer implements IFluenceClient {
connectionState: ConnectionState = 'disconnected';
connectionStateChangeHandler: (state: ConnectionState) => void = () => {};
constructor(private marine: IMarine, private avmRunner: IAvmRunner) {}
/**
@ -72,10 +98,10 @@ export class FluencePeer implements IFluenceClient {
__isFluenceAwesome = true;
/**
* Get the peer's status
* TODO: remove this from here. Switch to `ConnectionState` instead
* @deprecated
*/
getStatus(): PeerStatus {
// TODO:: use explicit mechanism for peer's state
if (this._keyPair === undefined) {
return {
isInitialized: false,
@ -112,10 +138,11 @@ export class FluencePeer implements IFluenceClient {
};
}
/**
* Return peers SK
*/
getSk(): Uint8Array {
getPeerId(): string {
return this.getStatus().peerId!;
}
getPeerSecretKey(): Uint8Array {
if (!this._keyPair) {
throw new Error("Can't get key pair: peer is not initialized");
}
@ -123,20 +150,44 @@ export class FluencePeer implements IFluenceClient {
return this._keyPair.toEd25519PrivateKey();
}
onConnectionStateChange(handler: (state: ConnectionState) => void): ConnectionState {
this.connectionStateChangeHandler = handler;
return this.connectionState;
}
/**
* Connect to the Fluence network
* @param relay - relay node to connect to
* @param options - client options
*/
async connect(relay: RelayOptions, options?: ClientOptions): Promise<void> {
return this.start({ relay, ...options });
}
/**
* Disconnect from the Fluence network
*/
disconnect(): Promise<void> {
return this.stop();
}
/**
* Initializes the peer: starts the Aqua VM, initializes the default call service handlers
* and (optionally) connect to the Fluence network
* @param config - object specifying peer configuration
*/
async start(config: PeerConfig = {}): Promise<void> {
this.changeConnectionState('connecting');
const keyPair = await makeKeyPair(config.keyPair);
await this.init(config, keyPair);
const conn = await configToConnection(keyPair, config?.relay, config?.connectionOptions?.dialTimeoutMs);
const conn = await configToConnection(keyPair, config.relay, config.connectionOptions?.dialTimeoutMs);
if (conn !== null) {
await this.connect(conn);
await this._connect(conn);
}
this.changeConnectionState('connected');
}
getServices() {
@ -182,9 +233,10 @@ export class FluencePeer implements IFluenceClient {
* and disconnects from the Fluence network
*/
async stop() {
this.changeConnectionState('disconnecting');
this._keyPair = undefined; // This will set peer to non-initialized state and stop particle processing
this._stopParticleProcessing();
await this.disconnect();
await this._disconnect();
await this.marine.stop();
await this.avmRunner.stop();
this._classServices = undefined;
@ -192,25 +244,20 @@ export class FluencePeer implements IFluenceClient {
this._particleSpecificHandlers.clear();
this._commonHandlers.clear();
this._marineServices.clear();
this.changeConnectionState('disconnected');
}
// internal api
get compilerSupport() {
return {
callFunction: (args: CallFunctionArgs): Promise<unknown> => {
return callFunctionImpl(args.def, args.script, args.config, this, args.args);
},
registerService: (args: RegisterServiceArgs): void => {
return registerServiceImpl(this, args.def, args.serviceId, args.service);
},
};
}
/**
* @private Is not intended to be used manually. Subject to change
*/
get internals() {
return {
getConnectionState: () => this.connectionState,
getRelayPeerId: () => this.getStatus().relayPeerId,
parseAst: async (air: string): Promise<{ success: boolean; data: any }> => {
const status = this.getStatus();
@ -352,7 +399,7 @@ export class FluencePeer implements IFluenceClient {
/**
* @private Subject to change. Do not use this method directly
*/
async connect(connection: FluenceConnection): Promise<void> {
async _connect(connection: FluenceConnection): Promise<void> {
if (this.connection) {
await this.connection.disconnect();
}
@ -364,12 +411,17 @@ export class FluencePeer implements IFluenceClient {
/**
* @private Subject to change. Do not use this method directly
*/
async disconnect(): Promise<void> {
async _disconnect(): Promise<void> {
await this.connection?.disconnect();
}
// private
private changeConnectionState(state: ConnectionState) {
this.connectionState = state;
this.connectionStateChangeHandler(state);
}
// Queues for incoming and outgoing particles
private _incomingParticles = new Subject<ParticleQueueItem>();

View File

@ -6,7 +6,7 @@ import { Particle } from '../Particle.js';
import { MakeServiceCall } from '../utils.js';
import { avmModuleLoader, controlModuleLoader } from '../utilsForNode.js';
import { ServiceDef } from '@fluencelabs/interfaces';
import { callFunctionImpl } from '../../compilerSupport/callFunction.js';
import { callAquaFunction } from '../../compilerSupport/callFunction.js';
import { marineLogFunction } from '../utils.js';
import { MarineBackgroundRunner } from '../../marine/worker/index.js';
@ -40,7 +40,13 @@ export const compileAqua = async (aquaFile: string): Promise<CompiledFile> => {
const functions = Object.entries(compilationResult.functions)
.map(([name, fnInfo]) => {
const callFn = (peer: FluencePeer, args: { [key: string]: any }) => {
return callFunctionImpl(fnInfo.funcDef, fnInfo.script, {}, peer, args);
return callAquaFunction({
def: fnInfo.funcDef,
script: fnInfo.script,
config: {},
peer: peer,
args,
});
};
return { [name]: callFn };
})

View File

@ -7,7 +7,7 @@
*
*/
import { CallParams } from '@fluencelabs/interfaces';
import { registerServiceImpl } from '../../compilerSupport/registerService.js';
import { registerServiceImpl } from './util.js';
import { FluencePeer } from '../FluencePeer.js';
// Services

View File

@ -7,7 +7,7 @@
*
*/
import { CallParams } from '@fluencelabs/interfaces';
import { registerServiceImpl } from '../../compilerSupport/registerService.js';
import { registerServiceImpl } from './util.js';
import { FluencePeer } from '../FluencePeer.js';
// Services

View File

@ -7,7 +7,7 @@
*
*/
import { CallParams } from '@fluencelabs/interfaces';
import { registerServiceImpl } from '../../compilerSupport/registerService.js';
import { registerServiceImpl } from './util.js';
import { FluencePeer } from '../FluencePeer.js';
// Services

View File

@ -0,0 +1,9 @@
import { IFluenceClient, ServiceDef } from '@fluencelabs/interfaces';
import { registerService } from '../../compilerSupport/registerService.js';
export const registerServiceImpl = (
peer: IFluenceClient,
def: ServiceDef,
serviceId: string | undefined,
service: any,
) => registerService({ peer, def, service, serviceId });

View File

@ -157,7 +157,7 @@ export class EphemeralNetwork {
sendParticle = sendParticle;
};
await peer.connect(new connectionCtor());
await peer._connect(new connectionCtor());
const peerId = peer.getStatus().peerId!;
const ephPeer: PeerAdapter = {
@ -181,7 +181,7 @@ export class EphemeralNetwork {
log.debug('Shutting down ephemeral network...');
const peers = Array.from(this._peers.entries());
const promises = peers.map(([k, p]) => {
return p.isEphemeral ? p.peer.stop() : p.peer.disconnect();
return p.isEphemeral ? p.peer.stop() : p.peer._disconnect();
});
await Promise.all(promises);
this._peers.clear();

344
pnpm-lock.yaml generated
View File

@ -21,22 +21,22 @@ importers:
packages/@tests/aqua:
specifiers:
'@fluencelabs/aqua': 0.9.4
'@fluencelabs/fluence-network-environment': 1.0.13
'@fluencelabs/js-client.api': workspace:*
'@fluencelabs/fluence-network-environment': 1.0.14
'@fluencelabs/js-client.api': workspace:^
'@fluencelabs/registry': 0.7.0
base64-js: 1.5.1
dependencies:
'@fluencelabs/fluence-network-environment': 1.0.13
'@fluencelabs/js-client.api': 0.10.0
'@fluencelabs/fluence-network-environment': 1.0.14
'@fluencelabs/js-client.api': link:../../client/api
base64-js: 1.5.1
devDependencies:
'@fluencelabs/aqua': 0.9.4_jaxubti5gf66xc76fsqhxmuwn4
'@fluencelabs/aqua': 0.9.4_sxyfz5frysr7cnkewysdljfvwu
'@fluencelabs/registry': 0.7.0
packages/@tests/frameworks/cra-ts:
specifiers:
'@fluencelabs/js-client.api': workspace:*
'@test/aqua_for_test': workspace:*
'@fluencelabs/js-client.api': workspace:^
'@test/aqua_for_test': workspace:^
'@testing-library/jest-dom': 5.16.5
'@testing-library/react': 13.4.0
'@testing-library/user-event': 13.5.0
@ -50,7 +50,7 @@ importers:
typescript: 4.9.5
web-vitals: 2.1.4
dependencies:
'@fluencelabs/js-client.api': 0.10.0
'@fluencelabs/js-client.api': link:../../../client/api
'@test/aqua_for_test': link:../../aqua
'@testing-library/jest-dom': 5.16.5
'@testing-library/react': 13.4.0_biqbaboplfbrettd7655fr4n2y
@ -67,17 +67,17 @@ importers:
packages/@tests/smoke_node:
specifiers:
'@fluencelabs/js-client.api': workspace:*
'@fluencelabs/js-client.node': workspace:*
'@test/aqua_for_test': workspace:*
'@fluencelabs/js-client.api': workspace:^
'@fluencelabs/js-client.node': workspace:^
'@test/aqua_for_test': workspace:^
dependencies:
'@fluencelabs/js-client.api': 0.10.0
'@fluencelabs/js-client.node': 0.5.0_uint8arraylist@2.4.3
'@fluencelabs/js-client.api': link:../../client/api
'@fluencelabs/js-client.node': link:../../client/js-client.node
'@test/aqua_for_test': link:../aqua
packages/@tests/smoke_web:
specifiers:
'@fluencelabs/js-client.web.standalone': workspace:*
'@fluencelabs/js-client.web.standalone': workspace:^
http-server: 14.1.1
devDependencies:
'@fluencelabs/js-client.web.standalone': link:../../client/js-client.web.standalone
@ -141,10 +141,10 @@ importers:
'@types/node': 16.11.59
jest: 28.1.0_@types+node@16.11.59
js-base64: 3.7.2
ts-jest: 28.0.2_byf75w6xilfwy3ncjzlldwxox4
ts-jest: 28.0.2_m4pn7vsromlf5ffrouypoapnnq
vite: 4.0.4_@types+node@16.11.59
vite-plugin-replace: 0.1.1_vite@4.0.4
vite-tsconfig-paths: 4.0.3_trrwuuiz4f5khno7hdf3cjz2ky
vite-tsconfig-paths: 4.0.3_egung5nfepmolqa7uavvqho3gq
packages/client/tools:
specifiers:
@ -233,7 +233,7 @@ importers:
uint8arrays: 4.0.3
uuid: 8.3.2
devDependencies:
'@fluencelabs/aqua': 0.7.7-362_cgl6iwuyfzkj3bzihtpi7yfmsi
'@fluencelabs/aqua': 0.7.7-362_4ybkoodcah37urerzfcwvnjsoe
'@fluencelabs/aqua-api': 0.9.1-373
'@fluencelabs/aqua-lib': 0.6.0
'@fluencelabs/fluence-network-environment': 1.0.13
@ -241,7 +241,7 @@ importers:
'@types/jest': 29.4.0
'@types/uuid': 8.3.2
jest: 29.4.1
ts-jest: 29.0.5_knhdxpg4pvwuf6vrybjt5d2q5i
ts-jest: 29.0.5_ecv55cdbauq6znr7ci2lzguwra
packages:
@ -2037,13 +2037,13 @@ packages:
resolution: {integrity: sha512-ifjtCM93KO3LhzPkMxqmXhwLmrg/scjOiyTihEVg7ns5N+BVzaK1eWzdOdqGdl9ZVoah43pdlQUepEo7VdRmsw==}
dev: true
/@fluencelabs/aqua/0.7.7-362_cgl6iwuyfzkj3bzihtpi7yfmsi:
/@fluencelabs/aqua/0.7.7-362_4ybkoodcah37urerzfcwvnjsoe:
resolution: {integrity: sha512-CwvBc3wKQdvnDM4Zxj6yFE5MR2oeh+EZ++m2hLvENt7OWl3cnZVR4cJQkRxMMLVT0MxRwLiy97UIBwGsPqlSCA==}
hasBin: true
dependencies:
'@fluencelabs/aqua-ipfs': 0.5.5
'@fluencelabs/aqua-lib': 0.5.2
'@fluencelabs/fluence': 0.26.3-snapshot-4_cgl6iwuyfzkj3bzihtpi7yfmsi
'@fluencelabs/fluence': 0.26.3-snapshot-4_4ybkoodcah37urerzfcwvnjsoe
'@fluencelabs/fluence-network-environment': 1.0.13
ipfs-http-client: 50.1.2_node-fetch@3.3.0
transitivePeerDependencies:
@ -2083,13 +2083,13 @@ packages:
- utf-8-validate
dev: true
/@fluencelabs/aqua/0.9.4_jaxubti5gf66xc76fsqhxmuwn4:
/@fluencelabs/aqua/0.9.4_sxyfz5frysr7cnkewysdljfvwu:
resolution: {integrity: sha512-DAy2XT4E4oR4Imgsc9ns8jd14StwxktHcZe3MTaZT1PDo3KdbrXda5MBGWFiuqhZcB/Xr4EruCvH/LscrsKlQg==}
hasBin: true
dependencies:
'@fluencelabs/aqua-ipfs': 0.5.8
'@fluencelabs/aqua-lib': 0.6.0
'@fluencelabs/fluence': 0.28.0_jaxubti5gf66xc76fsqhxmuwn4
'@fluencelabs/fluence': 0.28.0_sxyfz5frysr7cnkewysdljfvwu
'@fluencelabs/fluence-network-environment': 1.0.13
ipfs-http-client: 50.1.2_node-fetch@3.3.0
transitivePeerDependencies:
@ -2148,8 +2148,13 @@ packages:
/@fluencelabs/fluence-network-environment/1.0.13:
resolution: {integrity: sha512-2pci3T0sUHE08jwEs1r/vHKVT4XUh/A3j/QJ0eIhddsxyIjEksjdn05X7DF6STD14CF8GgBVOJEPgav8qaUMpA==}
dev: true
/@fluencelabs/fluence/0.26.3-snapshot-4_cgl6iwuyfzkj3bzihtpi7yfmsi:
/@fluencelabs/fluence-network-environment/1.0.14:
resolution: {integrity: sha512-lMiH+7obmJW2Q+PMUR/vNAuX6TcVqlKmsWAHvnBogH7s8IeMT+UGN8qrweILWmE57G7MfauB302dIFQowR9tug==}
dev: false
/@fluencelabs/fluence/0.26.3-snapshot-4_4ybkoodcah37urerzfcwvnjsoe:
resolution: {integrity: sha512-M/iQhnViXfMaATj3gFPQXrZe9zSVcyN9F9A9hfJBUn0VLamhmbfeIoSZeheK8VGBxYbRGcrtoqLPTy1vJQVgVw==}
engines: {node: '>=10', pnpm: '>=3'}
hasBin: true
@ -2158,7 +2163,7 @@ packages:
'@fluencelabs/connection': 0.2.0_node-fetch@3.3.0
'@fluencelabs/interfaces': 0.1.0
'@fluencelabs/keypair': 0.2.0
'@fluencelabs/marine-js': 0.3.18_2g5e7lwqsvuxdxojhdo55sfvve
'@fluencelabs/marine-js': 0.3.18_ddylxr3wxksmlyjpihqkkowegi
async: 3.2.3
base64-js: 1.5.1
browser-or-node: 2.1.1
@ -2223,7 +2228,7 @@ packages:
- utf-8-validate
dev: true
/@fluencelabs/fluence/0.28.0_jaxubti5gf66xc76fsqhxmuwn4:
/@fluencelabs/fluence/0.28.0_sxyfz5frysr7cnkewysdljfvwu:
resolution: {integrity: sha512-SXb2vjTj8m/nw4jEILV0tu9VIFprGo8mNb2nOB5btxdsOI8GzQZkpGzTLrSd/+UagIo2GdxAu0GhBP8dxZXaqg==}
engines: {node: '>=10', pnpm: '>=3'}
hasBin: true
@ -2232,7 +2237,7 @@ packages:
'@fluencelabs/connection': 0.2.0_node-fetch@3.3.0
'@fluencelabs/interfaces': 0.1.0
'@fluencelabs/keypair': 0.2.0
'@fluencelabs/marine-js': 0.3.37_g4n3hsjlbmz4ag5o32ytojordu
'@fluencelabs/marine-js': 0.3.37_cnngzrja2umb46xxazlucyx2qu
async: 3.2.4
base64-js: 1.5.1
browser-or-node: 2.0.0
@ -2265,78 +2270,6 @@ packages:
engines: {node: '>=10', pnpm: '>=3'}
dev: true
/@fluencelabs/interfaces/0.5.0:
resolution: {integrity: sha512-L3bukC3eYog82cEANAg+K7OS7CQxWvFRcdItWVZkW+Bz49uDALdkBD8Isgyl94MTKElK5i5kCiwyrxYoNmHBfA==}
engines: {node: '>=10', pnpm: '>=3'}
dev: false
/@fluencelabs/interfaces/0.6.0:
resolution: {integrity: sha512-WK3TbFJQ9lXW6PU4aeBj1ZY5cuRG/nd765F6aoA1+SfQk+zrC9D4t1hxOkv7kpI6Msuop0Rt3cJH2tBjlvGKrQ==}
engines: {node: '>=10', pnpm: '>=3'}
dev: false
/@fluencelabs/js-client.api/0.10.0:
resolution: {integrity: sha512-MHMKW1/Jp8FuPib7c1DqNDxJNm7HHrW0Wm3Wqzu9RaXymmjlq9iz1sbWXFzpcHR7GvTKa97XlbSPIBUG1vUoLA==}
engines: {node: '>=10', pnpm: '>=3'}
dependencies:
'@fluencelabs/interfaces': 0.5.0
dev: false
/@fluencelabs/js-client.node/0.5.0_uint8arraylist@2.4.3:
resolution: {integrity: sha512-H5qqTZzauB9eLVjEtiBBhaO2bTMH+ESHogKF9jcCvDHyCyhCK19xgl6POz73dmWLBRpxYgR+5XNkNs5LS0ocvQ==}
engines: {node: '>=10', pnpm: '>=3'}
dependencies:
'@fluencelabs/avm': 0.35.4
'@fluencelabs/js-peer': 0.7.0_uint8arraylist@2.4.3
'@fluencelabs/marine-js': 0.3.45
platform: 1.3.6
transitivePeerDependencies:
- bufferutil
- supports-color
- uint8arraylist
- utf-8-validate
dev: false
/@fluencelabs/js-peer/0.7.0_uint8arraylist@2.4.3:
resolution: {integrity: sha512-TB+jw2jv33DxJl0NAGfgPJaHlARruJy7QHumANPQG1NZsFPz5KiY4OnHEPFPgQFZLa1KvKzsm5ABOg1vEXzycQ==}
engines: {node: '>=10', pnpm: '>=3'}
dependencies:
'@chainsafe/libp2p-noise': 11.0.0
'@fluencelabs/avm': 0.35.4
'@fluencelabs/interfaces': 0.6.0
'@fluencelabs/marine-js': 0.3.45
'@libp2p/crypto': 1.0.8_uint8arraylist@2.4.3
'@libp2p/interface-connection': 3.0.8
'@libp2p/interface-keys': 1.0.7
'@libp2p/interface-peer-id': 2.0.1
'@libp2p/interfaces': 3.3.1
'@libp2p/mplex': 7.1.1
'@libp2p/peer-id': 2.0.1
'@libp2p/peer-id-factory': 2.0.1
'@libp2p/websockets': 5.0.3
'@multiformats/multiaddr': 11.3.0
async: 3.2.4
bs58: 5.0.0
buffer: 6.0.3
it-length-prefixed: 8.0.4
it-map: 2.0.0
it-pipe: 2.0.5
js-base64: 3.7.2
libp2p: 0.42.2
loglevel: 1.8.1
multiformats: 11.0.1
rxjs: 7.5.5
threads: 1.7.0
ts-pattern: 3.3.3
uint8arrays: 4.0.3
uuid: 8.3.2
transitivePeerDependencies:
- bufferutil
- supports-color
- uint8arraylist
- utf-8-validate
dev: false
/@fluencelabs/keypair/0.2.0:
resolution: {integrity: sha512-sNFvoeefSa0Xa/xzzLwWBXPMB4y/vHEFh3BaA6FCGNPwbtN0pje9rd8AOgSP9fjlTPpxy3TuBI+eAIzBk5b+SQ==}
engines: {node: '>=10', pnpm: '>=3'}
@ -2346,7 +2279,7 @@ packages:
peer-id: 0.16.0
dev: true
/@fluencelabs/marine-js/0.3.18_2g5e7lwqsvuxdxojhdo55sfvve:
/@fluencelabs/marine-js/0.3.18_ddylxr3wxksmlyjpihqkkowegi:
resolution: {integrity: sha512-aNuGtyY910kJvtRwfqmZKjVs+1l3LVWShv5xvkY04faHm65nX3sZLe8UHwughdja/4ixV1IFKlaTUgw2u3Sf5A==}
dependencies:
'@wasmer/wasi': 0.12.0
@ -2354,7 +2287,26 @@ packages:
browser-or-node: 2.1.1
buffer: 6.0.3
threads: 1.7.0
ts-jest: 27.1.5_2g5e7lwqsvuxdxojhdo55sfvve
ts-jest: 27.1.5_ddylxr3wxksmlyjpihqkkowegi
transitivePeerDependencies:
- '@babel/core'
- '@types/jest'
- babel-jest
- esbuild
- jest
- supports-color
- typescript
dev: true
/@fluencelabs/marine-js/0.3.37_cnngzrja2umb46xxazlucyx2qu:
resolution: {integrity: sha512-/Kpu3S+aDOfrOpKBAK1VeWSHKCoD36/dxtHEWHbj3Lsro0GB9zkoaZPHlFFL7rorCB+hyjAJqLDuBGI8f3l/qg==}
dependencies:
'@wasmer/wasi': 0.12.0
'@wasmer/wasmfs': 0.12.0
browser-or-node: 2.0.0
buffer: 6.0.3
threads: 1.7.0
ts-jest: 27.1.5_cnngzrja2umb46xxazlucyx2qu
transitivePeerDependencies:
- '@babel/core'
- '@types/jest'
@ -2516,6 +2468,51 @@ packages:
- ts-node
- utf-8-validate
/@jest/core/27.5.1_ts-node@10.9.1:
resolution: {integrity: sha512-AK6/UTrvQD0Cd24NSqmIA6rKsu0tKIxfiCducZvqxYdmMisOYAsdItspT+fQDQYARPf8XgjAFZi0ogW2agH5nQ==}
engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0}
peerDependencies:
node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0
peerDependenciesMeta:
node-notifier:
optional: true
dependencies:
'@jest/console': 27.5.1
'@jest/reporters': 27.5.1
'@jest/test-result': 27.5.1
'@jest/transform': 27.5.1
'@jest/types': 27.5.1
'@types/node': 18.13.0
ansi-escapes: 4.3.2
chalk: 4.1.2
emittery: 0.8.1
exit: 0.1.2
graceful-fs: 4.2.10
jest-changed-files: 27.5.1
jest-config: 27.5.1_ts-node@10.9.1
jest-haste-map: 27.5.1
jest-message-util: 27.5.1
jest-regex-util: 27.5.1
jest-resolve: 27.5.1
jest-resolve-dependencies: 27.5.1
jest-runner: 27.5.1
jest-runtime: 27.5.1
jest-snapshot: 27.5.1
jest-util: 27.5.1
jest-validate: 27.5.1
jest-watcher: 27.5.1
micromatch: 4.0.5
rimraf: 3.0.2
slash: 3.0.0
strip-ansi: 6.0.1
transitivePeerDependencies:
- bufferutil
- canvas
- supports-color
- ts-node
- utf-8-validate
dev: true
/@jest/core/28.1.3:
resolution: {integrity: sha512-CIKBrlaKOzA7YG19BEqCw3SLIsEwjZkeJzf5bdooVnW4bH5cktqe3JX+G2YV1aK5vP8N9na1IGWFzYaTp6k6NA==}
engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0}
@ -9183,6 +9180,36 @@ packages:
- ts-node
- utf-8-validate
/jest-cli/27.5.1_ts-node@10.9.1:
resolution: {integrity: sha512-Hc6HOOwYq4/74/c62dEE3r5elx8wjYqxY0r0G/nFrLDPMFRu6RA/u8qINOIkvhxG7mMQ5EJsOGfRpI8L6eFUVw==}
engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0}
hasBin: true
peerDependencies:
node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0
peerDependenciesMeta:
node-notifier:
optional: true
dependencies:
'@jest/core': 27.5.1_ts-node@10.9.1
'@jest/test-result': 27.5.1
'@jest/types': 27.5.1
chalk: 4.1.2
exit: 0.1.2
graceful-fs: 4.2.10
import-local: 3.1.0
jest-config: 27.5.1_ts-node@10.9.1
jest-util: 27.5.1
jest-validate: 27.5.1
prompts: 2.4.2
yargs: 16.2.0
transitivePeerDependencies:
- bufferutil
- canvas
- supports-color
- ts-node
- utf-8-validate
dev: true
/jest-cli/28.1.3_@types+node@16.11.59:
resolution: {integrity: sha512-roY3kvrv57Azn1yPgdTebPAXvdR2xfezaKKYzVxZ6It/5NCxzJym6tUI5P1zkdWhfUYkxEI9uZWcQdaFLo8mJQ==}
engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0}
@ -9278,6 +9305,47 @@ packages:
- supports-color
- utf-8-validate
/jest-config/27.5.1_ts-node@10.9.1:
resolution: {integrity: sha512-5sAsjm6tGdsVbW9ahcChPAFCk4IlkQUknH5AvKjuLTSlcO/wCZKyFdn7Rg0EkC+OGgWODEy2hDpWB1PgzH0JNA==}
engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0}
peerDependencies:
ts-node: '>=9.0.0'
peerDependenciesMeta:
ts-node:
optional: true
dependencies:
'@babel/core': 7.20.12
'@jest/test-sequencer': 27.5.1
'@jest/types': 27.5.1
babel-jest: 27.5.1_@babel+core@7.20.12
chalk: 4.1.2
ci-info: 3.8.0
deepmerge: 4.3.0
glob: 7.2.3
graceful-fs: 4.2.10
jest-circus: 27.5.1
jest-environment-jsdom: 27.5.1
jest-environment-node: 27.5.1
jest-get-type: 27.5.1
jest-jasmine2: 27.5.1
jest-regex-util: 27.5.1
jest-resolve: 27.5.1
jest-runner: 27.5.1
jest-util: 27.5.1
jest-validate: 27.5.1
micromatch: 4.0.5
parse-json: 5.2.0
pretty-format: 27.5.1
slash: 3.0.0
strip-json-comments: 3.1.1
ts-node: 10.9.1_j777nnsruz44drbtesvg2fqc7y
transitivePeerDependencies:
- bufferutil
- canvas
- supports-color
- utf-8-validate
dev: true
/jest-config/28.1.3_@types+node@16.11.59:
resolution: {integrity: sha512-MG3INjByJ0J4AsNBm7T3hsuxKQqFIiRo/AUqb1q9LRKI5UU6Aar9JHbr9Ivn1TVwfUD9KirRoM/T6u8XlcQPHQ==}
engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0}
@ -10359,6 +10427,27 @@ packages:
- ts-node
- utf-8-validate
/jest/27.5.1_ts-node@10.9.1:
resolution: {integrity: sha512-Yn0mADZB89zTtjkPJEXwrac3LHudkQMR+Paqa8uxJHCBr9agxztUifWCyiYrjhMPBoUVBjyny0I7XH6ozDr7QQ==}
engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0}
hasBin: true
peerDependencies:
node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0
peerDependenciesMeta:
node-notifier:
optional: true
dependencies:
'@jest/core': 27.5.1_ts-node@10.9.1
import-local: 3.1.0
jest-cli: 27.5.1_ts-node@10.9.1
transitivePeerDependencies:
- bufferutil
- canvas
- supports-color
- ts-node
- utf-8-validate
dev: true
/jest/28.1.0_@types+node@16.11.59:
resolution: {integrity: sha512-TZR+tHxopPhzw3c3560IJXZWLNHgpcz1Zh0w5A65vynLGNcg/5pZ+VildAd7+XGOu6jd58XMY/HNn0IkZIXVXg==}
engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0}
@ -14461,7 +14550,40 @@ packages:
resolution: {integrity: sha512-c3zayb8/kWWpycWYg87P71E1S1ZL6b6IJxfb5fvsUgsf0S2MVGaDhDXXjDMpdCpfWXqptc+4mXwmiy1ypXqRAA==}
dev: false
/ts-jest/27.1.5_2g5e7lwqsvuxdxojhdo55sfvve:
/ts-jest/27.1.5_cnngzrja2umb46xxazlucyx2qu:
resolution: {integrity: sha512-Xv6jBQPoBEvBq/5i2TeSG9tt/nqkbpcurrEG1b+2yfBrcJelOZF9Ml6dmyMh7bcW9JyFbRYpR5rxROSlBLTZHA==}
engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0}
hasBin: true
peerDependencies:
'@babel/core': '>=7.0.0-beta.0 <8'
'@types/jest': ^27.0.0
babel-jest: '>=27.0.0 <28'
esbuild: '*'
jest: ^27.0.0
typescript: '>=3.8 <5.0'
peerDependenciesMeta:
'@babel/core':
optional: true
'@types/jest':
optional: true
babel-jest:
optional: true
esbuild:
optional: true
dependencies:
bs-logger: 0.2.6
fast-json-stable-stringify: 2.1.0
jest: 27.5.1
jest-util: 27.5.1
json5: 2.2.3
lodash.memoize: 4.1.2
make-error: 1.3.6
semver: 7.3.8
typescript: 4.9.5
yargs-parser: 20.2.9
dev: true
/ts-jest/27.1.5_ddylxr3wxksmlyjpihqkkowegi:
resolution: {integrity: sha512-Xv6jBQPoBEvBq/5i2TeSG9tt/nqkbpcurrEG1b+2yfBrcJelOZF9Ml6dmyMh7bcW9JyFbRYpR5rxROSlBLTZHA==}
engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0}
hasBin: true
@ -14492,7 +14614,7 @@ packages:
lodash.memoize: 4.1.2
make-error: 1.3.6
semver: 7.3.8
typescript: 4.7.4
typescript: 4.9.5
yargs-parser: 20.2.9
dev: true
@ -14519,7 +14641,7 @@ packages:
dependencies:
bs-logger: 0.2.6
fast-json-stable-stringify: 2.1.0
jest: 27.5.1
jest: 27.5.1_ts-node@10.9.1
jest-util: 27.5.1
json5: 2.2.3
lodash.memoize: 4.1.2
@ -14529,7 +14651,7 @@ packages:
yargs-parser: 20.2.9
dev: true
/ts-jest/28.0.2_byf75w6xilfwy3ncjzlldwxox4:
/ts-jest/28.0.2_m4pn7vsromlf5ffrouypoapnnq:
resolution: {integrity: sha512-IOZMb3D0gx6IHO9ywPgiQxJ3Zl4ECylEFwoVpENB55aTn5sdO0Ptyx/7noNBxAaUff708RqQL4XBNxxOVjY0vQ==}
engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0}
hasBin: true
@ -14560,11 +14682,11 @@ packages:
lodash.memoize: 4.1.2
make-error: 1.3.6
semver: 7.3.8
typescript: 4.7.4
typescript: 4.9.5
yargs-parser: 20.2.9
dev: true
/ts-jest/29.0.5_knhdxpg4pvwuf6vrybjt5d2q5i:
/ts-jest/29.0.5_ecv55cdbauq6znr7ci2lzguwra:
resolution: {integrity: sha512-PL3UciSgIpQ7f6XjVOmbi96vmDHUqAyqDr8YxzopDqX3kfgYtX1cuNeBjP+L9sFXi6nzsGGA6R3fP3DDDJyrxA==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
hasBin: true
@ -14594,7 +14716,7 @@ packages:
lodash.memoize: 4.1.2
make-error: 1.3.6
semver: 7.3.8
typescript: 4.7.4
typescript: 4.9.5
yargs-parser: 21.1.1
dev: true
@ -14632,7 +14754,7 @@ packages:
/ts-pattern/3.3.3:
resolution: {integrity: sha512-Z5EFi6g6wyX3uDFHqxF5W5c5h663oZg9O6aOiAT7fqNu0HPSfCxtHzrQ7SblTy738Mrg2Ezorky8H5aUOm8Pvg==}
/tsconfck/2.0.2_typescript@4.7.4:
/tsconfck/2.0.2_typescript@4.9.5:
resolution: {integrity: sha512-H3DWlwKpow+GpVLm/2cpmok72pwRr1YFROV3YzAmvzfGFiC1zEM/mc9b7+1XnrxuXtEbhJ7xUSIqjPFbedp7aQ==}
engines: {node: ^14.13.1 || ^16 || >=18, pnpm: ^7.18.0}
hasBin: true
@ -14642,7 +14764,7 @@ packages:
typescript:
optional: true
dependencies:
typescript: 4.7.4
typescript: 4.9.5
dev: true
/tsconfig-paths/3.14.1:
@ -14969,14 +15091,14 @@ packages:
vite: 4.0.4_@types+node@16.11.59
dev: true
/vite-tsconfig-paths/4.0.3_trrwuuiz4f5khno7hdf3cjz2ky:
/vite-tsconfig-paths/4.0.3_egung5nfepmolqa7uavvqho3gq:
resolution: {integrity: sha512-gRO2Q/tOkV+9kMht5tz90+IaEKvW2zCnvwJV3tp2ruPNZOTM5rF+yXorJT4ggmAMYEaJ3nyXjx5P5jY5FwiZ+A==}
peerDependencies:
vite: '>2.0.0-0'
dependencies:
debug: 4.3.4
globrex: 0.1.2
tsconfck: 2.0.2_typescript@4.7.4
tsconfck: 2.0.2_typescript@4.9.5
vite: 4.0.4_@types+node@16.11.59
transitivePeerDependencies:
- supports-color