mirror of
https://github.com/fluencelabs/fluence-js.git
synced 2024-12-04 18:00:18 +00:00
New aqua (#969)
This commit is contained in:
parent
6ebba3242d
commit
87af2bbe56
@ -70,7 +70,7 @@ console.log(serviceId);
|
||||
// { some_arg: "1" } – arguments passed to the function
|
||||
// "ipfs_node.wasm" – name of the module to find function in
|
||||
|
||||
let resp = await cl2.callService(peerAddr, serviceId, "ipfs_node.wasm", {some_arg: "1"}, "get_address")
|
||||
let resp = await cl2.service(peerAddr, serviceId, "ipfs_node.wasm", {some_arg: "1"}, "get_address")
|
||||
console.log(resp)
|
||||
```
|
||||
|
||||
|
112
package-lock.json
generated
112
package-lock.json
generated
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "fluence",
|
||||
"version": "0.7.24",
|
||||
"version": "0.7.54",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
@ -196,44 +196,6 @@
|
||||
"watchpack": "^1.6.0"
|
||||
}
|
||||
},
|
||||
"@wasmer/wasi": {
|
||||
"version": "0.12.0",
|
||||
"resolved": "https://registry.npmjs.org/@wasmer/wasi/-/wasi-0.12.0.tgz",
|
||||
"integrity": "sha512-FJhLZKAfLWm/yjQI7eCRHNbA8ezmb7LSpUYFkHruZXs2mXk2+DaQtSElEtOoNrVQ4vApTyVaAd5/b7uEu8w6wQ==",
|
||||
"requires": {
|
||||
"browser-process-hrtime": "^1.0.0",
|
||||
"buffer-es6": "^4.9.3",
|
||||
"path-browserify": "^1.0.0",
|
||||
"randomfill": "^1.0.4"
|
||||
},
|
||||
"dependencies": {
|
||||
"path-browserify": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz",
|
||||
"integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"@wasmer/wasm-transformer": {
|
||||
"version": "0.12.0",
|
||||
"resolved": "https://registry.npmjs.org/@wasmer/wasm-transformer/-/wasm-transformer-0.12.0.tgz",
|
||||
"integrity": "sha512-pz4hvrJhqjxsmrMgxIH6jaEJuaL4/1iPNUg0lSIdpWeszgoCYjpQUimzh7ekKCIxl8WuqKOmm2f5hX+Vt8Sx8w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"wasm-feature-detect": "^1.2.2"
|
||||
}
|
||||
},
|
||||
"@wasmer/wasmfs": {
|
||||
"version": "0.12.0",
|
||||
"resolved": "https://registry.npmjs.org/@wasmer/wasmfs/-/wasmfs-0.12.0.tgz",
|
||||
"integrity": "sha512-m1ftchyQ1DfSenm5XbbdGIpb6KJHH5z0gODo3IZr6lATkj4WXfX/UeBTZ0aG9YVShBp+kHLdUHvOkqjy6p/GWw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"memfs": "3.0.4",
|
||||
"pako": "^1.0.11",
|
||||
"tar-stream": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"@webassemblyjs/ast": {
|
||||
"version": "1.9.0",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.9.0.tgz",
|
||||
@ -914,11 +876,6 @@
|
||||
"resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz",
|
||||
"integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8="
|
||||
},
|
||||
"browser-process-hrtime": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz",
|
||||
"integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow=="
|
||||
},
|
||||
"browser-stdout": {
|
||||
"version": "1.3.1",
|
||||
"resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz",
|
||||
@ -1029,11 +986,6 @@
|
||||
"ieee754": "^1.1.4"
|
||||
}
|
||||
},
|
||||
"buffer-es6": {
|
||||
"version": "4.9.3",
|
||||
"resolved": "https://registry.npmjs.org/buffer-es6/-/buffer-es6-4.9.3.tgz",
|
||||
"integrity": "sha1-8mNHuC33b9N+GLy1KIxJcM/VxAQ="
|
||||
},
|
||||
"buffer-from": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz",
|
||||
@ -2383,12 +2335,6 @@
|
||||
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
|
||||
"dev": true
|
||||
},
|
||||
"fast-extend": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/fast-extend/-/fast-extend-1.0.2.tgz",
|
||||
"integrity": "sha512-XXA9RmlPatkFKUzqVZAFth18R4Wo+Xug/S+C7YlYA3xrXwfPlW3dqNwOb4hvQo7wZJ2cNDYhrYuPzVOfHy5/uQ==",
|
||||
"dev": true
|
||||
},
|
||||
"fast-fifo": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.0.0.tgz",
|
||||
@ -2744,12 +2690,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"fs-constants": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
|
||||
"integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==",
|
||||
"dev": true
|
||||
},
|
||||
"fs-extra": {
|
||||
"version": "9.0.1",
|
||||
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.0.1.tgz",
|
||||
@ -2761,12 +2701,6 @@
|
||||
"universalify": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"fs-monkey": {
|
||||
"version": "0.3.3",
|
||||
"resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-0.3.3.tgz",
|
||||
"integrity": "sha512-FNUvuTAJ3CqCQb5ELn+qCbGR/Zllhf2HtwsdAtBi59s1WeCjKMT81fHcSu7dwIskqGVK+MmOrb7VOBlq3/SItw==",
|
||||
"dev": true
|
||||
},
|
||||
"fs-write-stream-atomic": {
|
||||
"version": "1.0.10",
|
||||
"resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz",
|
||||
@ -4890,16 +4824,6 @@
|
||||
"p-is-promise": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"memfs": {
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/memfs/-/memfs-3.0.4.tgz",
|
||||
"integrity": "sha512-OcZEzwX9E5AoY8SXjuAvw0DbIAYwUzV/I236I8Pqvrlv7sL/Y0E9aRCon05DhaV8pg1b32uxj76RgW0s5xjHBA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"fast-extend": "1.0.2",
|
||||
"fs-monkey": "0.3.3"
|
||||
}
|
||||
},
|
||||
"memory-fs": {
|
||||
"version": "0.5.0",
|
||||
"resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.5.0.tgz",
|
||||
@ -6246,6 +6170,7 @@
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
|
||||
"integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"safe-buffer": "^5.1.0"
|
||||
}
|
||||
@ -6254,6 +6179,7 @@
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz",
|
||||
"integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"randombytes": "^2.0.5",
|
||||
"safe-buffer": "^5.1.0"
|
||||
@ -7331,32 +7257,6 @@
|
||||
"integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==",
|
||||
"dev": true
|
||||
},
|
||||
"tar-stream": {
|
||||
"version": "2.1.4",
|
||||
"resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.1.4.tgz",
|
||||
"integrity": "sha512-o3pS2zlG4gxr67GmFYBLlq+dM8gyRGUOvsrHclSkvtVtQbjV0s/+ZE8OpICbaj8clrX3tjeHngYGP7rweaBnuw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"bl": "^4.0.3",
|
||||
"end-of-stream": "^1.4.1",
|
||||
"fs-constants": "^1.0.0",
|
||||
"inherits": "^2.0.3",
|
||||
"readable-stream": "^3.1.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"bl": {
|
||||
"version": "4.0.3",
|
||||
"resolved": "https://registry.npmjs.org/bl/-/bl-4.0.3.tgz",
|
||||
"integrity": "sha512-fs4G6/Hu4/EE+F75J8DuN/0IpQqNjAdC7aEQv7Qt8MHGUH7Ckv2MwTEEeN9QehD0pfIDkMI1bkHYkKy7xHyKIg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"buffer": "^5.5.0",
|
||||
"inherits": "^2.0.4",
|
||||
"readable-stream": "^3.4.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"terser": {
|
||||
"version": "4.7.0",
|
||||
"resolved": "https://registry.npmjs.org/terser/-/terser-4.7.0.tgz",
|
||||
@ -7923,12 +7823,6 @@
|
||||
"integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==",
|
||||
"dev": true
|
||||
},
|
||||
"wasm-feature-detect": {
|
||||
"version": "1.2.9",
|
||||
"resolved": "https://registry.npmjs.org/wasm-feature-detect/-/wasm-feature-detect-1.2.9.tgz",
|
||||
"integrity": "sha512-2E9/gtLVLpv2wnZDyYv8WY2dR9gHbmyv5uhZsnOcMSzqc78aGZpKQORPNcnrPwAU23nFUo7GAwKuoTAWRgsJ7Q==",
|
||||
"dev": true
|
||||
},
|
||||
"watchpack": {
|
||||
"version": "1.7.2",
|
||||
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.7.2.tgz",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "fluence",
|
||||
"version": "0.7.54",
|
||||
"version": "0.7.62",
|
||||
"description": "the browser js-libp2p client for the Fluence network",
|
||||
"main": "./dist/fluence.js",
|
||||
"typings": "./dist/fluence.d.ts",
|
||||
@ -8,7 +8,7 @@
|
||||
"test": "mocha -r ts-node/register src/**/*.spec.ts",
|
||||
"test-ts": "ts-mocha -p tsconfig.json src/**/*.spec.ts",
|
||||
"package:build": "NODE_ENV=production webpack && npm run package",
|
||||
"package": "tsc && cp -r src/aqua dist",
|
||||
"package": "tsc && rsync -r src/aqua dist --exclude src/aqua/wasmBs64.ts",
|
||||
"compile": "tsc",
|
||||
"start": "webpack-dev-server -p",
|
||||
"build": "webpack"
|
||||
|
File diff suppressed because one or more lines are too long
27
src/dataStorage.ts
Normal file
27
src/dataStorage.ts
Normal file
@ -0,0 +1,27 @@
|
||||
import {getCurrentParticleId, registerService} from "./globalState";
|
||||
import {Service} from "./service";
|
||||
import log from "loglevel";
|
||||
|
||||
let storage: Map<string, Map<string, any>> = new Map();
|
||||
|
||||
export function addData(particleId: string, data: Map<string, any>, ttl: number) {
|
||||
storage.set(particleId, data)
|
||||
setTimeout(() => {
|
||||
log.debug(`data for ${particleId} is deleted`)
|
||||
storage.delete(particleId)
|
||||
}, ttl)
|
||||
}
|
||||
|
||||
export const storageService = new Service("")
|
||||
storageService.registerFunction("load", (args: any[]) => {
|
||||
let current = getCurrentParticleId();
|
||||
|
||||
let data = storage.get(current)
|
||||
|
||||
if (data) {
|
||||
return data.get(args[0])
|
||||
} else {
|
||||
return {}
|
||||
}
|
||||
})
|
||||
registerService(storageService);
|
@ -53,6 +53,7 @@ export default class Fluence {
|
||||
declare global {
|
||||
interface Window {
|
||||
Fluence: Fluence;
|
||||
test: any
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -15,32 +15,24 @@
|
||||
*/
|
||||
|
||||
|
||||
import {build, genUUID, Particle} from "./particle";
|
||||
import {build, Particle} from "./particle";
|
||||
import {StepperOutcome} from "./stepperOutcome";
|
||||
import * as PeerId from "peer-id";
|
||||
import Multiaddr from "multiaddr"
|
||||
import {FluenceConnection} from "./fluenceConnection";
|
||||
import {Subscriptions} from "./subscriptions";
|
||||
import {
|
||||
addParticle,
|
||||
deleteService,
|
||||
enqueueParticle,
|
||||
getCurrentParticleId,
|
||||
popParticle,
|
||||
registerService,
|
||||
setCurrentParticleId
|
||||
} from "./globalState";
|
||||
import {instantiateStepper, Stepper} from "./stepper";
|
||||
import log from "loglevel";
|
||||
import {Service} from "./callService";
|
||||
import {delay} from "./utils";
|
||||
import {waitService} from "./helpers/waitService";
|
||||
|
||||
const bs58 = require('bs58')
|
||||
|
||||
interface NamedPromise<T> {
|
||||
promise: Promise<T>,
|
||||
name: string
|
||||
}
|
||||
|
||||
export class FluenceClient {
|
||||
readonly selfPeerId: PeerId;
|
||||
readonly selfPeerIdStr: string;
|
||||
@ -62,14 +54,15 @@ export class FluenceClient {
|
||||
private async handleParticle(particle: Particle): Promise<void> {
|
||||
|
||||
// if a current particle is processing, add new particle to the queue
|
||||
if (getCurrentParticleId() !== undefined) {
|
||||
addParticle(particle);
|
||||
if (getCurrentParticleId() !== undefined && getCurrentParticleId() !== particle.id) {
|
||||
enqueueParticle(particle);
|
||||
} else {
|
||||
if (this.stepper === undefined) {
|
||||
throw new Error("Undefined. Stepper is not initialized. User 'Fluence.connect' to create a client.")
|
||||
}
|
||||
// start particle processing if queue is empty
|
||||
try {
|
||||
setCurrentParticleId(particle.id)
|
||||
// check if a particle is relevant
|
||||
let now = Date.now();
|
||||
let actualTtl = particle.timestamp + particle.ttl - now;
|
||||
@ -77,7 +70,7 @@ export class FluenceClient {
|
||||
log.info(`Particle expired. Now: ${now}, ttl: ${particle.ttl}, ts: ${particle.timestamp}`)
|
||||
} else {
|
||||
// if there is no subscription yet, previous data is empty
|
||||
let prevData = {};
|
||||
let prevData = [];
|
||||
let prevParticle = this.subscriptions.get(particle.id);
|
||||
if (prevParticle) {
|
||||
prevData = prevParticle.data;
|
||||
@ -96,7 +89,7 @@ export class FluenceClient {
|
||||
// do nothing if there is no `next_peer_pks`
|
||||
if (stepperOutcome.next_peer_pks.length > 0) {
|
||||
let newParticle: Particle = {...particle};
|
||||
newParticle.data = JSON.parse(stepperOutcome.data);
|
||||
newParticle.data = JSON.parse(stepperOutcome.call_path);
|
||||
|
||||
await this.connection.sendParticle(newParticle).catch((reason) => {
|
||||
console.error(`Error on sending particle with id ${particle.id}: ${reason}`)
|
||||
@ -183,36 +176,10 @@ export class FluenceClient {
|
||||
}
|
||||
|
||||
nodeIdentityCall(): string {
|
||||
return `(call ("${this.nodePeerIdStr}" ("identity" "") () void[]))`
|
||||
return `(call "${this.nodePeerIdStr}" ("identity" "") [] void[])`
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates service that will wait for a response from external peers.
|
||||
*/
|
||||
private waitService<T>(functionName: string, func: (args: any[]) => T, ttl: number): NamedPromise<T> {
|
||||
let serviceName = `${functionName}-${genUUID()}`;
|
||||
log.info(`Create waiting service '${serviceName}'`)
|
||||
let service = new Service(serviceName)
|
||||
registerService(service)
|
||||
|
||||
let promise: Promise<T> = new Promise(function(resolve){
|
||||
service.registerFunction("", (args: any[]) => {
|
||||
resolve(func(args))
|
||||
return {}
|
||||
})
|
||||
})
|
||||
|
||||
let timeout = delay<T>(ttl, "Timeout on waiting " + serviceName)
|
||||
|
||||
return {
|
||||
name: serviceName,
|
||||
promise: Promise.race([promise, timeout]).finally(() => {
|
||||
deleteService(serviceName)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
async requestResponse<T>(name: string, call: (nodeId: string) => string, returnValue: string, data: any, handleResponse: (args: any[]) => T, nodeId?: string, ttl?: number): Promise<T> {
|
||||
async requestResponse<T>(name: string, call: (nodeId: string) => string, returnValue: string, data: Map<string, any>, handleResponse: (args: any[]) => T, nodeId?: string, ttl?: number): Promise<T> {
|
||||
if (!ttl) {
|
||||
ttl = 10000
|
||||
}
|
||||
@ -223,18 +190,18 @@ export class FluenceClient {
|
||||
|
||||
let serviceCall = call(nodeId)
|
||||
|
||||
let namedPromise = this.waitService(name, handleResponse, ttl)
|
||||
let namedPromise = waitService(name, handleResponse, ttl)
|
||||
|
||||
let script = `(seq (
|
||||
let script = `(seq
|
||||
${this.nodeIdentityCall()}
|
||||
(seq (
|
||||
(seq (
|
||||
(seq
|
||||
(seq
|
||||
${serviceCall}
|
||||
${this.nodeIdentityCall()}
|
||||
))
|
||||
(call ("${this.selfPeerIdStr}" ("${namedPromise.name}" "") (${returnValue}) void[]))
|
||||
))
|
||||
))
|
||||
)
|
||||
(call "${this.selfPeerIdStr}" ("${namedPromise.name}" "") [${returnValue}] void[])
|
||||
)
|
||||
)
|
||||
`
|
||||
|
||||
let particle = await build(this.selfPeerId, script, data, ttl)
|
||||
@ -258,12 +225,11 @@ export class FluenceClient {
|
||||
}
|
||||
}
|
||||
|
||||
let data = {
|
||||
module_bytes: moduleBase64,
|
||||
module_config: config
|
||||
}
|
||||
let data = new Map()
|
||||
data.set("module_bytes", moduleBase64)
|
||||
data.set("module_config", config)
|
||||
|
||||
let call = (nodeId: string) => `(call ("${nodeId}" ("add_module" "") (module_bytes module_config) void[]))`
|
||||
let call = (nodeId: string) => `(call "${nodeId}" ("add_module" "") [module_bytes module_config] void[])`
|
||||
|
||||
return this.requestResponse("addModule", call, "", data, () => {}, nodeId, ttl)
|
||||
}
|
||||
@ -273,11 +239,10 @@ export class FluenceClient {
|
||||
*/
|
||||
async addBlueprint(name: string, dependencies: string[], nodeId?: string, ttl?: number): Promise<string> {
|
||||
let returnValue = "blueprint_id";
|
||||
let call = (nodeId: string) => `(call ("${nodeId}" ("add_blueprint" "") (blueprint) ${returnValue}))`
|
||||
let call = (nodeId: string) => `(call "${nodeId}" ("add_blueprint" "") [blueprint] ${returnValue})`
|
||||
|
||||
let data = {
|
||||
blueprint: { name: name, dependencies: dependencies }
|
||||
}
|
||||
let data = new Map()
|
||||
data.set("blueprint", { name: name, dependencies: dependencies })
|
||||
|
||||
return this.requestResponse("addBlueprint", call, returnValue, data, (args: any[]) => args[0] as string, nodeId, ttl)
|
||||
}
|
||||
@ -287,11 +252,10 @@ export class FluenceClient {
|
||||
*/
|
||||
async createService(blueprintId: string, nodeId?: string, ttl?: number): Promise<string> {
|
||||
let returnValue = "service_id";
|
||||
let call = (nodeId: string) => `(call ("${nodeId}" ("create" "") (blueprint_id) ${returnValue}))`
|
||||
let call = (nodeId: string) => `(call "${nodeId}" ("create" "") [blueprint_id] ${returnValue})`
|
||||
|
||||
let data = {
|
||||
blueprint_id: blueprintId
|
||||
}
|
||||
let data = new Map()
|
||||
data.set("blueprint_id", blueprintId)
|
||||
|
||||
return this.requestResponse("createService", call, returnValue, data, (args: any[]) => args[0] as string, nodeId, ttl)
|
||||
}
|
||||
@ -301,9 +265,9 @@ export class FluenceClient {
|
||||
*/
|
||||
async getAvailableModules(nodeId?: string, ttl?: number): Promise<string[]> {
|
||||
let returnValue = "modules";
|
||||
let call = (nodeId: string) => `(call ("${nodeId}" ("get_available_modules" "") () ${returnValue}))`
|
||||
let call = (nodeId: string) => `(call "${nodeId}" ("get_available_modules" "") [] ${returnValue})`
|
||||
|
||||
return this.requestResponse("getAvailableModules", call, returnValue, {}, (args: any[]) => args[0] as string[], nodeId, ttl)
|
||||
return this.requestResponse("getAvailableModules", call, returnValue, new Map(), (args: any[]) => args[0] as string[], nodeId, ttl)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -311,16 +275,16 @@ export class FluenceClient {
|
||||
*/
|
||||
async getBlueprints(nodeId: string, ttl?: number): Promise<string[]> {
|
||||
let returnValue = "blueprints";
|
||||
let call = (nodeId: string) => `(call ("${nodeId}" ("get_available_modules" "") () ${returnValue}))`
|
||||
let call = (nodeId: string) => `(call "${nodeId}" ("get_available_modules" "") [] ${returnValue})`
|
||||
|
||||
return this.requestResponse("getBlueprints", call, returnValue, {}, (args: any[]) => args[0] as string[], nodeId, ttl)
|
||||
return this.requestResponse("getBlueprints", call, returnValue, new Map(), (args: any[]) => args[0] as string[], nodeId, ttl)
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a provider to DHT network to neighborhood around a key.
|
||||
*/
|
||||
async addProvider(key: Buffer, providerPeer: string, providerServiceId?: string, nodeId?: string, ttl?: number): Promise<void> {
|
||||
let call = (nodeId: string) => `(call ("${nodeId}" ("add_provider" "") (key provider) void[]))`
|
||||
let call = (nodeId: string) => `(call "${nodeId}" ("add_provider" "") [key provider] void[])`
|
||||
|
||||
key = bs58.encode(key)
|
||||
|
||||
@ -329,7 +293,11 @@ export class FluenceClient {
|
||||
service_id: providerServiceId
|
||||
}
|
||||
|
||||
return this.requestResponse("addProvider", call, "", {key, provider}, () => {}, nodeId, ttl)
|
||||
let data = new Map()
|
||||
data.set("key", key)
|
||||
data.set("provider", provider)
|
||||
|
||||
return this.requestResponse("addProvider", call, "", data, () => {}, nodeId, ttl)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -339,9 +307,12 @@ export class FluenceClient {
|
||||
key = bs58.encode(key)
|
||||
|
||||
let returnValue = "providers"
|
||||
let call = (nodeId: string) => `(call ("${nodeId}" ("get_providers" "") (key) providers[]))`
|
||||
let call = (nodeId: string) => `(call "${nodeId}" ("get_providers" "") [key] providers[])`
|
||||
|
||||
return this.requestResponse("getProviders", call, returnValue, {key}, (args) => args[0], nodeId, ttl)
|
||||
let data = new Map()
|
||||
data.set("key", key)
|
||||
|
||||
return this.requestResponse("getProviders", call, returnValue, data, (args) => args[0], nodeId, ttl)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -349,17 +320,20 @@ export class FluenceClient {
|
||||
*/
|
||||
async neighborhood(node: string, ttl?: number): Promise<string[]> {
|
||||
let returnValue = "neighborhood"
|
||||
let call = (nodeId: string) => `(call ("${nodeId}" ("neighborhood" "") (node) ${returnValue}))`
|
||||
let call = (nodeId: string) => `(call "${nodeId}" ("neighborhood" "") [node] ${returnValue})`
|
||||
|
||||
return this.requestResponse("neighborhood", call, returnValue, {node}, (args) => args[0] as string[], node, ttl)
|
||||
let data = new Map()
|
||||
data.set("node", node)
|
||||
|
||||
return this.requestResponse("neighborhood", call, returnValue, data, (args) => args[0] as string[], node, ttl)
|
||||
}
|
||||
|
||||
/**
|
||||
* Call relays 'identity' method. It should return passed 'fields'
|
||||
*/
|
||||
async relayIdentity(fields: string[], data: any, nodeId?: string, ttl?: number): Promise<any> {
|
||||
async relayIdentity(fields: string[], data: Map<string, any>, nodeId?: string, ttl?: number): Promise<any> {
|
||||
let returnValue = "id";
|
||||
let call = (nodeId: string) => `(call ("${nodeId}" ("identity" "") (${fields.join(" ")}) ${returnValue}))`
|
||||
let call = (nodeId: string) => `(call "${nodeId}" ("identity" "") [${fields.join(" ")}] ${returnValue})`
|
||||
|
||||
return this.requestResponse("getIdentity", call, returnValue, data, (args: any[]) => args[0], nodeId, ttl)
|
||||
}
|
||||
|
@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import {Service} from "./callService";
|
||||
import {Service} from "./service";
|
||||
import {Particle} from "./particle";
|
||||
|
||||
// TODO put state with wasm file in each created FluenceClient
|
||||
@ -30,7 +30,7 @@ export function setCurrentParticleId(particle: string | undefined) {
|
||||
currentParticle = particle;
|
||||
}
|
||||
|
||||
export function addParticle(particle: Particle): void {
|
||||
export function enqueueParticle(particle: Particle): void {
|
||||
particlesQueue.push(particle);
|
||||
}
|
||||
|
||||
|
46
src/helpers/waitService.ts
Normal file
46
src/helpers/waitService.ts
Normal file
@ -0,0 +1,46 @@
|
||||
/**
|
||||
* Creates service that will wait for a response from external peers.
|
||||
*/
|
||||
import {genUUID} from "../particle";
|
||||
import log from "loglevel";
|
||||
import {Service} from "../service";
|
||||
import {deleteService, registerService} from "../globalState";
|
||||
import {delay} from "../utils";
|
||||
|
||||
interface NamedPromise<T> {
|
||||
promise: Promise<T>,
|
||||
name: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a service and a name of a service.
|
||||
* Name should be used in a script.
|
||||
* Promise will wait a result from a script or will be resolved after `ttl` milliseconds.
|
||||
* @param ttl
|
||||
*/
|
||||
export function waitResult(ttl: number): NamedPromise<any[]> {
|
||||
return waitService(genUUID(), (args: any[]) => args, ttl)
|
||||
}
|
||||
|
||||
export function waitService<T>(functionName: string, func: (args: any[]) => T, ttl: number): NamedPromise<T> {
|
||||
let serviceName = `${functionName}-${genUUID()}`;
|
||||
log.info(`Create waiting service '${serviceName}'`)
|
||||
let service = new Service(serviceName)
|
||||
registerService(service)
|
||||
|
||||
let promise: Promise<T> = new Promise(function (resolve) {
|
||||
service.registerFunction("", (args: any[]) => {
|
||||
resolve(func(args))
|
||||
return {}
|
||||
})
|
||||
})
|
||||
|
||||
let timeout = delay<T>(ttl, "Timeout on waiting " + serviceName)
|
||||
|
||||
return {
|
||||
name: serviceName,
|
||||
promise: Promise.race([promise, timeout]).finally(() => {
|
||||
deleteService(serviceName)
|
||||
})
|
||||
}
|
||||
}
|
@ -17,6 +17,7 @@
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import PeerId from "peer-id";
|
||||
import {encode} from "bs58";
|
||||
import {addData} from "./dataStorage";
|
||||
|
||||
const DEFAULT_TTL = 7000;
|
||||
|
||||
@ -31,7 +32,20 @@ export interface Particle {
|
||||
data: any
|
||||
}
|
||||
|
||||
export async function build(peerId: PeerId, script: string, data: object, ttl?: number): Promise<Particle> {
|
||||
function wrapScript(selfPeerId: string, script: string, fields: string[]): string {
|
||||
fields.forEach((v) => {
|
||||
script = `
|
||||
(seq
|
||||
(call "${selfPeerId}" ("" "load") ["${v}"] ${v})
|
||||
${script}
|
||||
)
|
||||
`
|
||||
});
|
||||
|
||||
return script;
|
||||
}
|
||||
|
||||
export async function build(peerId: PeerId, script: string, data: Map<string, any>, ttl?: number): Promise<Particle> {
|
||||
let id = genUUID();
|
||||
let currentTime = (new Date()).getTime();
|
||||
|
||||
@ -39,6 +53,9 @@ export async function build(peerId: PeerId, script: string, data: object, ttl?:
|
||||
ttl = DEFAULT_TTL
|
||||
}
|
||||
|
||||
addData(id, data, ttl);
|
||||
script = wrapScript(peerId.toB58String(), script, Array.from(data.keys()))
|
||||
|
||||
let particle: Particle = {
|
||||
id: id,
|
||||
init_peer_id: peerId.toB58String(),
|
||||
@ -46,7 +63,7 @@ export async function build(peerId: PeerId, script: string, data: object, ttl?:
|
||||
ttl: ttl,
|
||||
script: script,
|
||||
signature: "",
|
||||
data: data
|
||||
data: []
|
||||
}
|
||||
|
||||
particle.signature = await signParticle(peerId, particle);
|
||||
|
@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import {getService, registerService} from "./globalState";
|
||||
import {getService} from "./globalState";
|
||||
|
||||
export interface CallServiceResult {
|
||||
ret_code: number,
|
||||
@ -60,14 +60,7 @@ export class Service {
|
||||
}
|
||||
}
|
||||
|
||||
let logger = new Service("")
|
||||
logger.registerFunction("", (args: any[]) => {
|
||||
console.log("logger service: " + args)
|
||||
return { result: "done" }
|
||||
})
|
||||
registerService(logger);
|
||||
|
||||
export function callService(service_id: string, fn_name: string, args: string): CallServiceResult {
|
||||
export function service(service_id: string, fn_name: string, args: string): CallServiceResult {
|
||||
try {
|
||||
let argsObject = JSON.parse(args)
|
||||
if (!Array.isArray(argsObject)) {
|
@ -18,7 +18,7 @@ import {wasmBs64} from "./aqua/wasmBs64";
|
||||
import {toByteArray} from "base64-js";
|
||||
import * as aqua from "./aqua"
|
||||
|
||||
import {callService} from "./callService";
|
||||
import {service} from "./service";
|
||||
import {getInt32Memory0, getStringFromWasm0, passStringToWasm0, WASM_VECTOR_LEN} from "./aqua";
|
||||
import PeerId from "peer-id";
|
||||
import log from "loglevel";
|
||||
@ -34,12 +34,12 @@ export async function instantiateStepper(pid: PeerId): Promise<Stepper> {
|
||||
const importObject = {
|
||||
// __wbg_callserviceimpl_c0ca292e3c8c0c97 this is a function generated by bindgen. Could be changed.
|
||||
// If so, an error with a new name will be occurred after wasm initialization.
|
||||
"./index_bg.js": { __wbg_callserviceimpl_a0e7e7457d0787ac: (arg0: any, arg1: any, arg2: any, arg3: any, arg4: any, arg5: any, arg6: any) => {
|
||||
"./index_bg.js": { __wbg_callserviceimpl_543ea6b03160524e: (arg0: any, arg1: any, arg2: any, arg3: any, arg4: any, arg5: any, arg6: any) => {
|
||||
try {
|
||||
let serviceId = getStringFromWasm0(wasm, arg1, arg2)
|
||||
let fnName = getStringFromWasm0(wasm, arg3, arg4)
|
||||
let args = getStringFromWasm0(wasm, arg5, arg6);
|
||||
var ret = callService(serviceId, fnName, args);
|
||||
var ret = service(serviceId, fnName, args);
|
||||
let retStr = JSON.stringify(ret)
|
||||
var ptr0 = passStringToWasm0(wasm, retStr, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
||||
var len0 = WASM_VECTOR_LEN;
|
||||
@ -51,7 +51,7 @@ export async function instantiateStepper(pid: PeerId): Promise<Stepper> {
|
||||
wasm.__wbindgen_free(arg5, arg6);
|
||||
}
|
||||
},
|
||||
__wbg_getcurrentpeeridimpl_b463298bc6aec9ec: (arg0: any) => {
|
||||
__wbg_getcurrentpeeridimpl_8924d0a646015630: (arg0: any) => {
|
||||
var ret = pid.toB58String();
|
||||
var ptr0 = passStringToWasm0(wasm, ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
||||
var len0 = WASM_VECTOR_LEN;
|
||||
|
@ -16,6 +16,6 @@
|
||||
|
||||
export interface StepperOutcome {
|
||||
ret_code: number,
|
||||
data: string,
|
||||
call_path: string,
|
||||
next_peer_pks: string[]
|
||||
}
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
import {expect} from 'chai';
|
||||
|
||||
import 'mocha';
|
||||
@ -9,6 +8,9 @@ import {TrustGraph} from "../trust/trust_graph";
|
||||
import {nodeRootCert} from "../trust/misc";
|
||||
import {peerIdToSeed, seedToPeerId} from "../seed";
|
||||
import {build} from "../particle";
|
||||
import {Service} from "../service";
|
||||
import {registerService} from "../globalState";
|
||||
import {waitResult} from "../helpers/waitService";
|
||||
|
||||
describe("Typescript usage suite", () => {
|
||||
|
||||
@ -38,29 +40,45 @@ describe("Typescript usage suite", () => {
|
||||
expect(ser).to.be.equal(cert);
|
||||
});
|
||||
|
||||
it("test new client", async function () {
|
||||
let key1 = await Fluence.generatePeerId();
|
||||
let key2 = await Fluence.generatePeerId();
|
||||
|
||||
let nodePeerId = "12D3KooWQ8x4SMBmSSUrMzY2m13uzC7UoSyvHaDhTKx7hH8aXxpt"
|
||||
let addr = '/ip4/127.0.0.1/tcp/9001/ws/p2p/' + nodePeerId
|
||||
|
||||
// connect to two different nodes
|
||||
let cl1 = await Fluence.connect(addr, key1);
|
||||
|
||||
let script = "((call (%current% (local_service_id local_fn_name) () result_name)) (call (remote_peer_id (service_id fn_name) () g)))"
|
||||
|
||||
let particle = await build(key1, script, {})
|
||||
|
||||
let result = await cl1.sendParticle(particle)
|
||||
console.log(result)
|
||||
});
|
||||
|
||||
// delete `.skip` and run `npm run test` to check service's and certificate's api with Fluence nodes
|
||||
it.skip("test certs", async function () {
|
||||
this.timeout(15000);
|
||||
await testCerts();
|
||||
});
|
||||
|
||||
it.skip("", async function () {
|
||||
let pid = await Fluence.generatePeerId()
|
||||
let cl = await Fluence.connect("/ip4/138.197.177.2/tcp/9001/ws/p2p/12D3KooWEXNUbCXooUwHrHBbrmjsrpHXoEphPwbjQXEGyzbqKnE9", pid)
|
||||
|
||||
let service = new Service("test")
|
||||
service.registerFunction("test", (args: any[]) => {
|
||||
console.log("called: " + args)
|
||||
return {}
|
||||
})
|
||||
registerService(service);
|
||||
|
||||
let namedPromise = waitResult(30000)
|
||||
|
||||
let script = `
|
||||
(seq (
|
||||
(call ( "${pid.toB58String()}" ("test" "test") (a b c d) result))
|
||||
(call ( "${pid.toB58String()}" ("${namedPromise.name}" "") (d c b a) void[]))
|
||||
))
|
||||
`
|
||||
|
||||
let data: Map<string, any> = new Map();
|
||||
data.set("a", "some a")
|
||||
data.set("b", "some b")
|
||||
data.set("c", "some c")
|
||||
data.set("d", "some d")
|
||||
|
||||
let particle = await build(pid, script, data, 30000)
|
||||
|
||||
await cl.sendParticle(particle)
|
||||
|
||||
let res = await namedPromise.promise
|
||||
expect(res).to.be.equal(["some d", "some c", "some b", "some a"])
|
||||
})
|
||||
});
|
||||
|
||||
const delay = (ms: number) => new Promise(res => setTimeout(res, ms));
|
||||
|
Loading…
Reference in New Issue
Block a user