mirror of
https://github.com/fluencelabs/fluence-js.git
synced 2024-12-04 18:00:18 +00:00
Turn on noImplicitAny and strictNullChecks (#153)
* Turn on noImplicitAny and strictNullChecks * code review fixes
This commit is contained in:
parent
e9454473ed
commit
5234ba24ed
12
.editorconfig
Normal file
12
.editorconfig
Normal file
@ -0,0 +1,12 @@
|
||||
# EditorConfig is awesome: https://EditorConfig.org
|
||||
|
||||
# top-most EditorConfig file
|
||||
root = true
|
||||
|
||||
[*]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
end_of_line = lf
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = false
|
||||
insert_final_newline = false
|
32
package-lock.json
generated
32
package-lock.json
generated
@ -38,8 +38,10 @@
|
||||
"devDependencies": {
|
||||
"@fluencelabs/aqua": "^0.7.0-285",
|
||||
"@fluencelabs/aqua-lib": "^0.4.3",
|
||||
"@types/bs58": "^4.0.1",
|
||||
"@types/jest": "^26.0.22",
|
||||
"@types/platform": "^1.3.4",
|
||||
"@types/uuid": "^8.3.4",
|
||||
"jest": "^26.6.3",
|
||||
"js-base64": "^3.7.2",
|
||||
"ts-jest": "^26.5.4",
|
||||
@ -2369,6 +2371,15 @@
|
||||
"@babel/types": "^7.3.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/bs58": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/bs58/-/bs58-4.0.1.tgz",
|
||||
"integrity": "sha512-yfAgiWgVLjFCmRv8zAcOIHywYATEwiTVccTLnRp6UxTNavT55M9d/uhK3T03St/+8/z/wW+CRjGKUNmEqoHHCA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"base-x": "^3.0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/graceful-fs": {
|
||||
"version": "4.1.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.5.tgz",
|
||||
@ -2450,6 +2461,12 @@
|
||||
"resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz",
|
||||
"integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw=="
|
||||
},
|
||||
"node_modules/@types/uuid": {
|
||||
"version": "8.3.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-8.3.4.tgz",
|
||||
"integrity": "sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/yargs": {
|
||||
"version": "15.0.14",
|
||||
"resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.14.tgz",
|
||||
@ -14239,6 +14256,15 @@
|
||||
"@babel/types": "^7.3.0"
|
||||
}
|
||||
},
|
||||
"@types/bs58": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/bs58/-/bs58-4.0.1.tgz",
|
||||
"integrity": "sha512-yfAgiWgVLjFCmRv8zAcOIHywYATEwiTVccTLnRp6UxTNavT55M9d/uhK3T03St/+8/z/wW+CRjGKUNmEqoHHCA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"base-x": "^3.0.6"
|
||||
}
|
||||
},
|
||||
"@types/graceful-fs": {
|
||||
"version": "4.1.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.5.tgz",
|
||||
@ -14320,6 +14346,12 @@
|
||||
"resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz",
|
||||
"integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw=="
|
||||
},
|
||||
"@types/uuid": {
|
||||
"version": "8.3.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-8.3.4.tgz",
|
||||
"integrity": "sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/yargs": {
|
||||
"version": "15.0.14",
|
||||
"resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.14.tgz",
|
||||
|
@ -48,8 +48,10 @@
|
||||
"devDependencies": {
|
||||
"@fluencelabs/aqua": "^0.7.0-285",
|
||||
"@fluencelabs/aqua-lib": "^0.4.3",
|
||||
"@types/bs58": "^4.0.1",
|
||||
"@types/jest": "^26.0.22",
|
||||
"@types/platform": "^1.3.4",
|
||||
"@types/uuid": "^8.3.4",
|
||||
"jest": "^26.6.3",
|
||||
"js-base64": "^3.7.2",
|
||||
"ts-jest": "^26.5.4",
|
||||
|
@ -1,34 +1,33 @@
|
||||
import { FluencePeer, setLogLevel } from '../../index';
|
||||
import { Particle } from '../../internal/Particle';
|
||||
import { FluencePeer } from '../../index';
|
||||
import { handleTimeout } from '../../internal/utils';
|
||||
import { registerHandlersHelper } from '../util';
|
||||
|
||||
let peer: FluencePeer;
|
||||
|
||||
describe('Avm spec', () => {
|
||||
afterEach(async () => {
|
||||
if (peer) {
|
||||
await peer.stop();
|
||||
}
|
||||
beforeEach(async () => {
|
||||
peer = new FluencePeer();
|
||||
await peer.start();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
peer = new FluencePeer();
|
||||
afterEach(async () => {
|
||||
await peer.stop();
|
||||
});
|
||||
|
||||
it('Simple call', async () => {
|
||||
// arrange
|
||||
await peer.start();
|
||||
|
||||
// act
|
||||
const promise = new Promise<string[]>((resolve, reject) => {
|
||||
const res = await new Promise<string[]>((resolve, reject) => {
|
||||
const script = `
|
||||
(call %init_peer_id% ("print" "print") ["1"])
|
||||
`;
|
||||
const particle = Particle.createNew(script);
|
||||
const particle = peer.internals.createNewParticle(script);
|
||||
|
||||
if (particle instanceof Error) {
|
||||
return reject(particle.message);
|
||||
}
|
||||
|
||||
registerHandlersHelper(peer, particle, {
|
||||
print: {
|
||||
print: async (args) => {
|
||||
print: (args: Array<Array<string>>) => {
|
||||
const [res] = args;
|
||||
resolve(res);
|
||||
},
|
||||
@ -38,20 +37,12 @@ describe('Avm spec', () => {
|
||||
peer.internals.initiateParticle(particle, handleTimeout(reject));
|
||||
});
|
||||
|
||||
// assert
|
||||
const res = await promise;
|
||||
expect(res).toBe('1');
|
||||
|
||||
await peer.stop();
|
||||
});
|
||||
|
||||
it('Par call', async () => {
|
||||
// arrange
|
||||
await peer.start();
|
||||
|
||||
// act
|
||||
const promise = new Promise<string[]>((resolve, reject) => {
|
||||
let res = [];
|
||||
const res = await new Promise<string[]>((resolve, reject) => {
|
||||
const res: any[] = [];
|
||||
const script = `
|
||||
(seq
|
||||
(par
|
||||
@ -61,10 +52,15 @@ describe('Avm spec', () => {
|
||||
(call %init_peer_id% ("print" "print") ["2"])
|
||||
)
|
||||
`;
|
||||
const particle = Particle.createNew(script);
|
||||
const particle = peer.internals.createNewParticle(script);
|
||||
|
||||
if (particle instanceof Error) {
|
||||
return reject(particle.message);
|
||||
}
|
||||
|
||||
registerHandlersHelper(peer, particle, {
|
||||
print: {
|
||||
print: (args) => {
|
||||
print: (args: any) => {
|
||||
res.push(args[0]);
|
||||
if (res.length == 2) {
|
||||
resolve(res);
|
||||
@ -76,19 +72,11 @@ describe('Avm spec', () => {
|
||||
peer.internals.initiateParticle(particle, handleTimeout(reject));
|
||||
});
|
||||
|
||||
// assert
|
||||
const res = await promise;
|
||||
expect(res).toStrictEqual(['1', '2']);
|
||||
|
||||
await peer.stop();
|
||||
});
|
||||
|
||||
it('Timeout in par call: race', async () => {
|
||||
// arrange
|
||||
await peer.start();
|
||||
|
||||
// act
|
||||
const promise = new Promise((resolve, reject) => {
|
||||
const res = await new Promise((resolve, reject) => {
|
||||
const script = `
|
||||
(seq
|
||||
(call %init_peer_id% ("op" "identity") ["slow_result"] arg)
|
||||
@ -101,10 +89,15 @@ describe('Avm spec', () => {
|
||||
)
|
||||
)
|
||||
`;
|
||||
const particle = Particle.createNew(script);
|
||||
const particle = peer.internals.createNewParticle(script);
|
||||
|
||||
if (particle instanceof Error) {
|
||||
return reject(particle.message);
|
||||
}
|
||||
|
||||
registerHandlersHelper(peer, particle, {
|
||||
return: {
|
||||
return: (args) => {
|
||||
return: (args: any) => {
|
||||
resolve(args[0]);
|
||||
},
|
||||
},
|
||||
@ -113,19 +106,11 @@ describe('Avm spec', () => {
|
||||
peer.internals.initiateParticle(particle, handleTimeout(reject));
|
||||
});
|
||||
|
||||
// assert
|
||||
const res = await promise;
|
||||
expect(res).toBe('fast_result');
|
||||
|
||||
await peer.stop();
|
||||
});
|
||||
|
||||
it('Timeout in par call: wait', async () => {
|
||||
// arrange
|
||||
await peer.start();
|
||||
|
||||
// act
|
||||
const promise = new Promise((resolve, reject) => {
|
||||
const res = await new Promise((resolve, reject) => {
|
||||
const script = `
|
||||
(seq
|
||||
(call %init_peer_id% ("op" "identity") ["timeout_msg"] arg)
|
||||
@ -146,10 +131,15 @@ describe('Avm spec', () => {
|
||||
)
|
||||
)
|
||||
`;
|
||||
const particle = Particle.createNew(script);
|
||||
const particle = peer.internals.createNewParticle(script);
|
||||
|
||||
if (particle instanceof Error) {
|
||||
return reject(particle.message);
|
||||
}
|
||||
|
||||
registerHandlersHelper(peer, particle, {
|
||||
return: {
|
||||
return: (args) => {
|
||||
return: (args: any) => {
|
||||
resolve(args[0]);
|
||||
},
|
||||
},
|
||||
@ -158,10 +148,6 @@ describe('Avm spec', () => {
|
||||
peer.internals.initiateParticle(particle, handleTimeout(reject));
|
||||
});
|
||||
|
||||
// assert
|
||||
const res = await promise;
|
||||
expect(res).toBe('failed_with_timeout');
|
||||
|
||||
await peer.stop();
|
||||
});
|
||||
});
|
||||
|
@ -1,8 +1,8 @@
|
||||
import { Multiaddr } from 'multiaddr';
|
||||
|
||||
import { nodes } from '../connection';
|
||||
import { Fluence, FluencePeer, setLogLevel } from '../../index';
|
||||
import { FluencePeer } from '../../index';
|
||||
import { checkConnection, doNothing, handleTimeout } from '../../internal/utils';
|
||||
import { Particle } from '../../internal/Particle';
|
||||
import { registerHandlersHelper } from '../util';
|
||||
|
||||
let peer: FluencePeer;
|
||||
@ -20,10 +20,9 @@ describe('Typescript usage suite', () => {
|
||||
|
||||
it('should perform test for FluencePeer class correctly', () => {
|
||||
// arrange
|
||||
const peer: any = new FluencePeer();
|
||||
const number: any = 1;
|
||||
const object: any = { str: 'Hello!' };
|
||||
const undefinedVal: any = undefined;
|
||||
const number = 1;
|
||||
const object = { str: 'Hello!' };
|
||||
const undefinedVal = undefined;
|
||||
|
||||
// act
|
||||
const isPeerPeer = FluencePeer.isInstance(peer);
|
||||
@ -40,13 +39,8 @@ describe('Typescript usage suite', () => {
|
||||
|
||||
describe('Should expose correct peer status', () => {
|
||||
it('Should expose correct status for uninitialized peer', () => {
|
||||
// arrange
|
||||
const nonStartedPeer = new FluencePeer();
|
||||
const status = peer.getStatus();
|
||||
|
||||
// act
|
||||
const status = nonStartedPeer.getStatus();
|
||||
|
||||
// assert
|
||||
expect(status.isConnected).toBe(false);
|
||||
expect(status.isInitialized).toBe(false);
|
||||
expect(status.peerId).toBe(null);
|
||||
@ -65,8 +59,6 @@ describe('Typescript usage suite', () => {
|
||||
expect(status.isInitialized).toBe(true);
|
||||
expect(status.peerId).not.toBe(null);
|
||||
expect(status.relayPeerId).toBe(null);
|
||||
|
||||
await peer.stop();
|
||||
});
|
||||
|
||||
it('Should expose correct status for connected peer', async () => {
|
||||
@ -81,8 +73,6 @@ describe('Typescript usage suite', () => {
|
||||
expect(status.isInitialized).toBe(true);
|
||||
expect(status.peerId).not.toBe(null);
|
||||
expect(status.relayPeerId).not.toBe(null);
|
||||
|
||||
await peer.stop();
|
||||
});
|
||||
});
|
||||
|
||||
@ -90,8 +80,7 @@ describe('Typescript usage suite', () => {
|
||||
// arrange
|
||||
await peer.start({ connectTo: nodes[0] });
|
||||
|
||||
// act
|
||||
const promise = new Promise<string[]>((resolve, reject) => {
|
||||
const result = await new Promise<string[]>((resolve, reject) => {
|
||||
const script = `
|
||||
(xor
|
||||
(seq
|
||||
@ -106,19 +95,24 @@ describe('Typescript usage suite', () => {
|
||||
(call %init_peer_id% ("callback" "error") [%last_error%])
|
||||
)
|
||||
)`;
|
||||
const particle = Particle.createNew(script);
|
||||
const particle = peer.internals.createNewParticle(script);
|
||||
|
||||
if (particle instanceof Error) {
|
||||
return reject(particle.message);
|
||||
}
|
||||
|
||||
registerHandlersHelper(peer, particle, {
|
||||
load: {
|
||||
relay: (args) => {
|
||||
relay: () => {
|
||||
return peer.getStatus().relayPeerId;
|
||||
},
|
||||
},
|
||||
callback: {
|
||||
callback: (args) => {
|
||||
callback: (args: any) => {
|
||||
const [val] = args;
|
||||
resolve(val);
|
||||
},
|
||||
error: (args) => {
|
||||
error: (args: any) => {
|
||||
const [error] = args;
|
||||
reject(error);
|
||||
},
|
||||
@ -128,15 +122,13 @@ describe('Typescript usage suite', () => {
|
||||
peer.internals.initiateParticle(particle, handleTimeout(reject));
|
||||
});
|
||||
|
||||
// assert
|
||||
const result = await promise;
|
||||
expect(result).toBe('hello world!');
|
||||
});
|
||||
|
||||
it('check connection should work', async function () {
|
||||
await peer.start({ connectTo: nodes[0] });
|
||||
|
||||
let isConnected = await checkConnection(peer);
|
||||
const isConnected = await checkConnection(peer);
|
||||
|
||||
expect(isConnected).toEqual(true);
|
||||
});
|
||||
@ -144,20 +136,18 @@ describe('Typescript usage suite', () => {
|
||||
it('check connection should work with ttl', async function () {
|
||||
await peer.start({ connectTo: nodes[0] });
|
||||
|
||||
let isConnected = await checkConnection(peer, 10000);
|
||||
const isConnected = await checkConnection(peer, 10000);
|
||||
|
||||
expect(isConnected).toEqual(true);
|
||||
});
|
||||
|
||||
it('two clients should work inside the same time browser', async () => {
|
||||
// arrange
|
||||
const peer1 = new FluencePeer();
|
||||
await peer1.start({ connectTo: nodes[0] });
|
||||
const peer2 = new FluencePeer();
|
||||
await peer2.start({ connectTo: nodes[0] });
|
||||
|
||||
// act
|
||||
const resMakingPromise = new Promise((resolve) => {
|
||||
const res = new Promise((resolve) => {
|
||||
peer2.internals.regHandler.common('test', 'test', (req) => {
|
||||
resolve(req.args[0]);
|
||||
return {
|
||||
@ -173,12 +163,15 @@ describe('Typescript usage suite', () => {
|
||||
(call "${peer2.getStatus().peerId}" ("test" "test") ["test"])
|
||||
)
|
||||
`;
|
||||
const particle = Particle.createNew(script);
|
||||
await peer1.internals.initiateParticle(particle, doNothing);
|
||||
const particle = peer1.internals.createNewParticle(script);
|
||||
|
||||
// assert
|
||||
const res = await resMakingPromise;
|
||||
expect(res).toEqual('test');
|
||||
if (particle instanceof Error) {
|
||||
throw particle;
|
||||
}
|
||||
|
||||
peer1.internals.initiateParticle(particle, doNothing);
|
||||
|
||||
expect(await res).toEqual('test');
|
||||
|
||||
await peer1.stop();
|
||||
await peer2.stop();
|
||||
@ -186,130 +179,74 @@ describe('Typescript usage suite', () => {
|
||||
|
||||
describe('should make connection to network', () => {
|
||||
it('address as string', async () => {
|
||||
// arrange
|
||||
const addr = nodes[0];
|
||||
|
||||
// act
|
||||
await peer.start({ connectTo: addr });
|
||||
await peer.start({ connectTo: nodes[0].multiaddr });
|
||||
const isConnected = await checkConnection(peer);
|
||||
|
||||
// assert
|
||||
expect(isConnected).toBeTruthy();
|
||||
});
|
||||
|
||||
it('address as multiaddr', async () => {
|
||||
// arrange
|
||||
const addr = new Multiaddr(nodes[0].multiaddr);
|
||||
|
||||
// act
|
||||
await peer.start({ connectTo: addr });
|
||||
await peer.start({ connectTo: new Multiaddr(nodes[0].multiaddr) });
|
||||
const isConnected = await checkConnection(peer);
|
||||
|
||||
// assert
|
||||
expect(isConnected).toBeTruthy();
|
||||
});
|
||||
|
||||
it('address as node', async () => {
|
||||
// arrange
|
||||
const addr = nodes[0];
|
||||
|
||||
// act
|
||||
await peer.start({ connectTo: addr });
|
||||
await peer.start({ connectTo: nodes[0] });
|
||||
const isConnected = await checkConnection(peer);
|
||||
|
||||
// assert
|
||||
expect(isConnected).toBeTruthy();
|
||||
});
|
||||
|
||||
it('peerid as peer id', async () => {
|
||||
// arrange
|
||||
const addr = nodes[0];
|
||||
|
||||
// act
|
||||
await peer.start({ connectTo: addr });
|
||||
const isConnected = await checkConnection(peer);
|
||||
|
||||
// assert
|
||||
expect(isConnected).toBeTruthy();
|
||||
});
|
||||
|
||||
it('peerid as seed', async () => {
|
||||
// arrange
|
||||
const addr = nodes[0];
|
||||
|
||||
// act
|
||||
await peer.start({ connectTo: addr });
|
||||
const isConnected = await checkConnection(peer);
|
||||
|
||||
// assert
|
||||
expect(isConnected).toBeTruthy();
|
||||
});
|
||||
|
||||
it('With connection options: dialTimeout', async () => {
|
||||
// arrange
|
||||
const addr = nodes[0];
|
||||
|
||||
// act
|
||||
await peer.start({ connectTo: addr, dialTimeoutMs: 100000 });
|
||||
await peer.start({ connectTo: nodes[0], dialTimeoutMs: 100000 });
|
||||
const isConnected = await checkConnection(peer);
|
||||
|
||||
// assert
|
||||
expect(isConnected).toBeTruthy();
|
||||
});
|
||||
|
||||
it('With connection options: skipCheckConnection', async () => {
|
||||
// arrange
|
||||
const addr = nodes[0];
|
||||
|
||||
// act
|
||||
await peer.start({ connectTo: addr, skipCheckConnection: true });
|
||||
await peer.start({ connectTo: nodes[0], skipCheckConnection: true });
|
||||
const isConnected = await checkConnection(peer);
|
||||
|
||||
// assert
|
||||
expect(isConnected).toBeTruthy();
|
||||
});
|
||||
|
||||
it('With connection options: checkConnectionTTL', async () => {
|
||||
// arrange
|
||||
const addr = nodes[0];
|
||||
|
||||
// act
|
||||
await peer.start({ connectTo: addr, checkConnectionTimeoutMs: 1000 });
|
||||
await peer.start({ connectTo: nodes[0], checkConnectionTimeoutMs: 1000 });
|
||||
const isConnected = await checkConnection(peer);
|
||||
|
||||
// assert
|
||||
expect(isConnected).toBeTruthy();
|
||||
});
|
||||
|
||||
it('With connection options: defaultTTL', async () => {
|
||||
// arrange
|
||||
const addr = nodes[0];
|
||||
|
||||
// act
|
||||
await peer.start({ connectTo: addr, defaultTtlMs: 1 });
|
||||
await peer.start({ connectTo: nodes[0], defaultTtlMs: 1 });
|
||||
const isConnected = await checkConnection(peer);
|
||||
|
||||
// assert
|
||||
expect(isConnected).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
||||
it('Should successfully call identity on local peer', async function () {
|
||||
// arrange
|
||||
await peer.start();
|
||||
|
||||
// act
|
||||
const promise = new Promise<string>((resolve, reject) => {
|
||||
const res = await new Promise<string>((resolve, reject) => {
|
||||
const script = `
|
||||
(seq
|
||||
(call %init_peer_id% ("op" "identity") ["test"] res)
|
||||
(call %init_peer_id% ("callback" "callback") [res])
|
||||
)
|
||||
`;
|
||||
const particle = Particle.createNew(script);
|
||||
const particle = peer.internals.createNewParticle(script);
|
||||
|
||||
if (particle instanceof Error) {
|
||||
return reject(particle.message);
|
||||
}
|
||||
|
||||
registerHandlersHelper(peer, particle, {
|
||||
callback: {
|
||||
callback: async (args) => {
|
||||
callback: async (args: any) => {
|
||||
const [res] = args;
|
||||
resolve(res);
|
||||
},
|
||||
@ -319,21 +256,14 @@ describe('Typescript usage suite', () => {
|
||||
peer.internals.initiateParticle(particle, handleTimeout(reject));
|
||||
});
|
||||
|
||||
// assert
|
||||
const res = await promise;
|
||||
expect(res).toBe('test');
|
||||
});
|
||||
|
||||
it('Should throw correct message when calling non existing local service', async function () {
|
||||
// arrange
|
||||
await peer.start({ connectTo: nodes[0] });
|
||||
|
||||
// act
|
||||
const res = callIncorrectService(peer);
|
||||
|
||||
// console.log(await res);
|
||||
|
||||
// assert
|
||||
await expect(res).rejects.toMatchObject({
|
||||
message: expect.stringContaining(
|
||||
`No handler has been registered for serviceId='incorrect' fnName='incorrect' args='[]'\"'`,
|
||||
@ -343,11 +273,9 @@ describe('Typescript usage suite', () => {
|
||||
});
|
||||
|
||||
it('Should not crash if undefined is passed as a variable', async () => {
|
||||
// arrange;
|
||||
await peer.start();
|
||||
|
||||
// act
|
||||
const promise = new Promise<any>((resolve, reject) => {
|
||||
const res = await new Promise<any>((resolve, reject) => {
|
||||
const script = `
|
||||
(seq
|
||||
(call %init_peer_id% ("load" "arg") [] arg)
|
||||
@ -356,20 +284,22 @@ describe('Typescript usage suite', () => {
|
||||
(call %init_peer_id% ("callback" "callback") [res])
|
||||
)
|
||||
)`;
|
||||
const particle = Particle.createNew(script);
|
||||
const particle = peer.internals.createNewParticle(script);
|
||||
|
||||
if (particle instanceof Error) {
|
||||
return reject(particle.message);
|
||||
}
|
||||
|
||||
registerHandlersHelper(peer, particle, {
|
||||
load: {
|
||||
arg: (args) => {
|
||||
return undefined;
|
||||
},
|
||||
arg: () => undefined,
|
||||
},
|
||||
callback: {
|
||||
callback: (args) => {
|
||||
callback: (args: any) => {
|
||||
const [val] = args;
|
||||
resolve(val);
|
||||
},
|
||||
error: (args) => {
|
||||
error: (args: any) => {
|
||||
const [error] = args;
|
||||
reject(error);
|
||||
},
|
||||
@ -379,32 +309,32 @@ describe('Typescript usage suite', () => {
|
||||
peer.internals.initiateParticle(particle, handleTimeout(reject));
|
||||
});
|
||||
|
||||
// assert
|
||||
const res = await promise;
|
||||
expect(res).toBe(null);
|
||||
});
|
||||
|
||||
it('Should not crash if an error ocurred in user-defined handler', async () => {
|
||||
// arrange;
|
||||
await peer.start();
|
||||
|
||||
// act
|
||||
const promise = new Promise<any>((resolve, reject) => {
|
||||
const promise = new Promise<any>((_resolve, reject) => {
|
||||
const script = `
|
||||
(xor
|
||||
(call %init_peer_id% ("load" "arg") [] arg)
|
||||
(call %init_peer_id% ("callback" "error") [%last_error%])
|
||||
)`;
|
||||
const particle = Particle.createNew(script);
|
||||
const particle = peer.internals.createNewParticle(script);
|
||||
|
||||
if (particle instanceof Error) {
|
||||
return reject(particle.message);
|
||||
}
|
||||
|
||||
registerHandlersHelper(peer, particle, {
|
||||
load: {
|
||||
arg: (args) => {
|
||||
throw 'my super custom error message';
|
||||
arg: () => {
|
||||
throw new Error('my super custom error message');
|
||||
},
|
||||
},
|
||||
callback: {
|
||||
error: (args) => {
|
||||
error: (args: any) => {
|
||||
const [error] = args;
|
||||
reject(error);
|
||||
},
|
||||
@ -414,44 +344,36 @@ describe('Typescript usage suite', () => {
|
||||
peer.internals.initiateParticle(particle, handleTimeout(reject));
|
||||
});
|
||||
|
||||
// assert
|
||||
await expect(promise).rejects.toMatchObject({
|
||||
message: expect.stringContaining('my super custom error message'),
|
||||
});
|
||||
});
|
||||
|
||||
it('Should throw error if particle is initiated on a stopped peer', async () => {
|
||||
// arrange;
|
||||
const stoppedPeer = new FluencePeer();
|
||||
it('Should return error if particle is created on a stopped peer', async () => {
|
||||
await peer.stop();
|
||||
const particle = peer.internals.createNewParticle(`(null)`);
|
||||
|
||||
// act
|
||||
const action = () => {
|
||||
const script = `(null)`;
|
||||
const particle = Particle.createNew(script);
|
||||
|
||||
stoppedPeer.internals.initiateParticle(particle, doNothing);
|
||||
};
|
||||
|
||||
// assert
|
||||
await expect(action).toThrow('Cannot initiate new particle: peer is not initialized');
|
||||
expect(particle instanceof Error).toBe(true);
|
||||
});
|
||||
|
||||
it.skip('Should throw correct error when the client tries to send a particle not to the relay', async () => {
|
||||
// arrange;
|
||||
await peer.start({ connectTo: nodes[0] });
|
||||
|
||||
// act
|
||||
const promise = new Promise((resolve, reject) => {
|
||||
const script = `
|
||||
(xor
|
||||
(call "incorrect_peer_id" ("any" "service") [])
|
||||
(call %init_peer_id% ("callback" "error") [%last_error%])
|
||||
)`;
|
||||
const particle = Particle.createNew(script);
|
||||
const particle = peer.internals.createNewParticle(script);
|
||||
|
||||
if (particle instanceof Error) {
|
||||
return reject(particle.message);
|
||||
}
|
||||
|
||||
registerHandlersHelper(peer, particle, {
|
||||
callback: {
|
||||
error: (args) => {
|
||||
error: (args: any) => {
|
||||
const [error] = args;
|
||||
reject(error);
|
||||
},
|
||||
@ -461,7 +383,6 @@ describe('Typescript usage suite', () => {
|
||||
peer.internals.initiateParticle(particle, doNothing);
|
||||
});
|
||||
|
||||
// assert
|
||||
await expect(promise).rejects.toMatch(
|
||||
'Particle is expected to be sent to only the single peer (relay which client is connected to)',
|
||||
);
|
||||
@ -469,20 +390,24 @@ describe('Typescript usage suite', () => {
|
||||
});
|
||||
|
||||
async function callIncorrectService(peer: FluencePeer): Promise<string[]> {
|
||||
const promise = new Promise<any[]>((resolve, reject) => {
|
||||
return new Promise<any[]>((resolve, reject) => {
|
||||
const script = `
|
||||
(xor
|
||||
(call %init_peer_id% ("incorrect" "incorrect") [] res)
|
||||
(call %init_peer_id% ("callback" "error") [%last_error%])
|
||||
)`;
|
||||
const particle = Particle.createNew(script);
|
||||
const particle = peer.internals.createNewParticle(script);
|
||||
|
||||
if (particle instanceof Error) {
|
||||
return reject(particle.message);
|
||||
}
|
||||
|
||||
registerHandlersHelper(peer, particle, {
|
||||
callback: {
|
||||
callback: (args) => {
|
||||
callback: (args: any) => {
|
||||
resolve(args);
|
||||
},
|
||||
error: (args) => {
|
||||
error: (args: any) => {
|
||||
const [error] = args;
|
||||
reject(error);
|
||||
},
|
||||
@ -491,6 +416,4 @@ async function callIncorrectService(peer: FluencePeer): Promise<string[]> {
|
||||
|
||||
peer.internals.initiateParticle(particle, handleTimeout(reject));
|
||||
});
|
||||
|
||||
return promise;
|
||||
}
|
||||
|
@ -34,7 +34,7 @@ describe('Sig service test suite', () => {
|
||||
const result = await callSig(peer, 'CustomSig');
|
||||
|
||||
expect(result.success).toBe(true);
|
||||
const isSigCorrect = await customSig.verify(result.signature, data);
|
||||
const isSigCorrect = await customSig.verify(result.signature as number[], data);
|
||||
expect(isSigCorrect).toBe(true);
|
||||
});
|
||||
|
||||
@ -67,7 +67,7 @@ describe('Sig service test suite', () => {
|
||||
});
|
||||
|
||||
const callAsSigRes = await callSig(peer, 'sig');
|
||||
const callAsPeerIdRes = await callSig(peer, peer.getStatus().peerId);
|
||||
const callAsPeerIdRes = await callSig(peer, peer.getStatus().peerId as string);
|
||||
|
||||
expect(callAsSigRes.success).toBe(false);
|
||||
expect(callAsPeerIdRes.success).toBe(false);
|
||||
@ -75,12 +75,12 @@ describe('Sig service test suite', () => {
|
||||
sig.securityGuard = () => true;
|
||||
|
||||
const callAsSigResAfterGuardChange = await callSig(peer, 'sig');
|
||||
const callAsPeerIdResAfterGuardChange = await callSig(peer, peer.getStatus().peerId);
|
||||
const callAsPeerIdResAfterGuardChange = await callSig(peer, peer.getStatus().peerId as string);
|
||||
|
||||
expect(callAsSigResAfterGuardChange.success).toBe(true);
|
||||
expect(callAsPeerIdResAfterGuardChange.success).toBe(true);
|
||||
|
||||
const isValid = await sig.verify(callAsSigResAfterGuardChange.signature, data);
|
||||
const isValid = await sig.verify(callAsSigResAfterGuardChange.signature as number[], data);
|
||||
|
||||
expect(isValid).toBe(true);
|
||||
});
|
||||
|
@ -246,7 +246,7 @@ describe('Sig service tests', () => {
|
||||
const sig = new Sig(ctx.peerKeyPair);
|
||||
|
||||
const signature = await sig.sign(testData, makeTetraplet(ctx.peerId));
|
||||
const res = await sig.verify(signature.signature, testData);
|
||||
const res = await sig.verify(signature.signature as number[], testData);
|
||||
|
||||
expect(res).toBe(true);
|
||||
});
|
||||
|
@ -1,4 +1,5 @@
|
||||
import each from 'jest-each';
|
||||
|
||||
import { Fluence, FluencePeer } from '../../..';
|
||||
import { forTests } from '../../../internal/compilerSupport/v2';
|
||||
|
||||
@ -19,7 +20,7 @@ describe('Compiler support tests', () => {
|
||||
`.test(
|
||||
//
|
||||
'raw rawArgs: $rawArgs, numArgs: $numArgs. expected args: $expectedArgs, config: $expectedConfig, default peer?: $isExpectedPeerDefault',
|
||||
async ({ rawArgs, numArgs, expectedArgs, expectedConfig, isExpectedPeerDefault }) => {
|
||||
({ rawArgs, numArgs, expectedArgs, expectedConfig, isExpectedPeerDefault }) => {
|
||||
// arrange
|
||||
const testFn = forTests.extractFunctionArgs;
|
||||
|
||||
|
@ -2,12 +2,14 @@ import { FluencePeer } from '../index';
|
||||
import { Particle } from '../internal/Particle';
|
||||
import { MakeServiceCall } from '../internal/utils';
|
||||
|
||||
export const registerHandlersHelper = (peer: FluencePeer, particle: Particle, handlers) => {
|
||||
for (let serviceId in handlers) {
|
||||
for (let fnName in handlers[serviceId]) {
|
||||
// of type [args] => result
|
||||
const h = handlers[serviceId][fnName];
|
||||
peer.internals.regHandler.forParticle(particle.id, serviceId, fnName, MakeServiceCall(h));
|
||||
}
|
||||
}
|
||||
export const registerHandlersHelper = (
|
||||
peer: FluencePeer,
|
||||
particle: Particle,
|
||||
handlers: Record<string, Record<string, any>>,
|
||||
) => {
|
||||
Object.entries(handlers).forEach(([serviceId, service]) => {
|
||||
Object.entries(service).forEach(([fnName, fn]) => {
|
||||
peer.internals.regHandler.forParticle(particle.id, serviceId, fnName, MakeServiceCall(fn));
|
||||
});
|
||||
});
|
||||
};
|
||||
|
@ -15,6 +15,7 @@
|
||||
*/
|
||||
|
||||
import log, { LogLevelDesc } from 'loglevel';
|
||||
|
||||
import { FluencePeer, PeerConfig } from './internal/FluencePeer';
|
||||
|
||||
export { PeerStatus } from './internal/FluencePeer';
|
||||
|
@ -13,10 +13,12 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
// @ts-ignore
|
||||
import Websockets from 'libp2p-websockets';
|
||||
// @ts-ignore
|
||||
import Mplex from 'libp2p-mplex';
|
||||
import Lib2p2Peer from 'libp2p';
|
||||
// @ts-ignore
|
||||
import { decode, encode } from 'it-length-prefixed';
|
||||
import pipe from 'it-pipe';
|
||||
import * as log from 'loglevel';
|
||||
@ -24,6 +26,7 @@ import { Particle } from './Particle';
|
||||
import { NOISE } from '@chainsafe/libp2p-noise';
|
||||
import PeerId from 'peer-id';
|
||||
import { Multiaddr } from 'multiaddr';
|
||||
// @ts-ignore
|
||||
import { all as allow_all } from 'libp2p-websockets/src/filters';
|
||||
import { Connection } from 'libp2p-interfaces/src/topology';
|
||||
import Buffer from './Buffer';
|
||||
@ -56,13 +59,13 @@ export interface FluenceConnectionOptions {
|
||||
}
|
||||
|
||||
export class FluenceConnection {
|
||||
constructor() {}
|
||||
constructor(private _lib2p2Peer: Lib2p2Peer, private _relayAddress: Multiaddr) {}
|
||||
|
||||
private _connection?: Connection;
|
||||
|
||||
static async createConnection(options: FluenceConnectionOptions): Promise<FluenceConnection> {
|
||||
const res = new FluenceConnection();
|
||||
|
||||
const transportKey = Websockets.prototype[Symbol.toStringTag];
|
||||
res._lib2p2Peer = await Lib2p2Peer.create({
|
||||
const lib2p2Peer = await Lib2p2Peer.create({
|
||||
peerId: options.peerId,
|
||||
modules: {
|
||||
transport: [Websockets],
|
||||
@ -81,7 +84,7 @@ export class FluenceConnection {
|
||||
},
|
||||
});
|
||||
|
||||
res._lib2p2Peer.handle([PROTOCOL_NAME], async ({ connection, stream }) => {
|
||||
lib2p2Peer.handle([PROTOCOL_NAME], async ({ connection, stream }) => {
|
||||
pipe(stream.source, decode(), async (source: AsyncIterable<string>) => {
|
||||
try {
|
||||
for await (const msg of source) {
|
||||
@ -98,22 +101,22 @@ export class FluenceConnection {
|
||||
});
|
||||
});
|
||||
|
||||
res._relayAddress = options.relayAddress;
|
||||
const relayAddress = options.relayAddress;
|
||||
|
||||
return res;
|
||||
return new FluenceConnection(lib2p2Peer, relayAddress);
|
||||
}
|
||||
|
||||
async disconnect() {
|
||||
await this._lib2p2Peer.stop();
|
||||
}
|
||||
|
||||
public async sendParticle(particle: Particle): Promise<void> {
|
||||
async sendParticle(particle: Particle): Promise<void> {
|
||||
particle.logTo('debug', 'sending particle:');
|
||||
|
||||
/*
|
||||
TODO:: find out why this doesn't work and a new connection has to be established each time
|
||||
if (this._connection.streams.length !== 1) {
|
||||
throw 'Incorrect number of streams in FluenceConnection';
|
||||
throw new Error('Incorrect number of streams in FluenceConnection');
|
||||
}
|
||||
|
||||
const sink = this._connection.streams[0].sink;
|
||||
@ -130,25 +133,20 @@ export class FluenceConnection {
|
||||
);
|
||||
}
|
||||
|
||||
public async connect() {
|
||||
async connect() {
|
||||
await this._lib2p2Peer.start();
|
||||
|
||||
log.debug(`dialing to the node with client's address: ` + this._lib2p2Peer.peerId.toB58String());
|
||||
|
||||
try {
|
||||
this._connection = await this._lib2p2Peer.dial(this._relayAddress);
|
||||
} catch (e1) {
|
||||
const e = e1 as any;
|
||||
if (e.name === 'AggregateError' && e._errors.length === 1) {
|
||||
} catch (e: any) {
|
||||
if (e.name === 'AggregateError' && e._errors?.length === 1) {
|
||||
const error = e._errors[0];
|
||||
throw `Error dialing node ${this._relayAddress}:\n${error.code}\n${error.message}`;
|
||||
throw new Error(`Error dialing node ${this._relayAddress}:\n${error.code}\n${error.message}`);
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private _lib2p2Peer: Lib2p2Peer;
|
||||
private _connection: Connection;
|
||||
private _relayAddress: Multiaddr;
|
||||
}
|
||||
|
@ -149,62 +149,68 @@ export interface PeerConfig {
|
||||
/**
|
||||
* Information about Fluence Peer connection
|
||||
*/
|
||||
export interface PeerStatus {
|
||||
/**
|
||||
* Is the peer initialized or not
|
||||
*/
|
||||
isInitialized: Boolean;
|
||||
|
||||
/**
|
||||
* Is the peer connected to network or not
|
||||
*/
|
||||
isConnected: Boolean;
|
||||
|
||||
/**
|
||||
* The Peer's identification in the Fluence network
|
||||
*/
|
||||
peerId: PeerIdB58 | null;
|
||||
|
||||
/**
|
||||
* The relays's peer id to which the peer is connected to
|
||||
*/
|
||||
relayPeerId: PeerIdB58 | null;
|
||||
}
|
||||
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;
|
||||
};
|
||||
|
||||
/**
|
||||
* This class implements the Fluence protocol for javascript-based environments.
|
||||
* It provides all the necessary features to communicate with Fluence network
|
||||
*/
|
||||
export class FluencePeer {
|
||||
/**
|
||||
* Creates a new Fluence Peer instance.
|
||||
*/
|
||||
constructor() {}
|
||||
|
||||
/**
|
||||
* Checks whether the object is instance of FluencePeer class
|
||||
* @param obj - object to check if it is FluencePeer
|
||||
* @returns true if the object is FluencePeer false otherwise
|
||||
*/
|
||||
static isInstance(obj: FluencePeer): boolean {
|
||||
if (obj && obj._isFluenceAwesome) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
static isInstance(obj: unknown): obj is FluencePeer {
|
||||
return obj instanceof FluencePeer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the peer's status
|
||||
*/
|
||||
getStatus(): PeerStatus {
|
||||
const hasKeyPair = this._keyPair !== undefined;
|
||||
// TODO:: use explicit mechanism for peer's state
|
||||
if (this._keyPair === undefined) {
|
||||
return {
|
||||
isInitialized: false,
|
||||
peerId: null,
|
||||
isConnected: false,
|
||||
relayPeerId: null,
|
||||
};
|
||||
}
|
||||
|
||||
if (this._connection === undefined || this._relayPeerId === null) {
|
||||
return {
|
||||
isInitialized: true,
|
||||
peerId: this._keyPair.Libp2pPeerId.toB58String(),
|
||||
isConnected: false,
|
||||
relayPeerId: null,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
// TODO:: use explicit mechanism for peer's state
|
||||
isInitialized: hasKeyPair,
|
||||
isConnected: this._connection !== undefined,
|
||||
peerId: this._keyPair?.Libp2pPeerId?.toB58String() || null,
|
||||
relayPeerId: this._relayPeerId || null,
|
||||
isInitialized: true,
|
||||
peerId: this._keyPair.Libp2pPeerId.toB58String(),
|
||||
isConnected: true,
|
||||
relayPeerId: this._relayPeerId,
|
||||
};
|
||||
}
|
||||
|
||||
@ -216,20 +222,16 @@ export class FluencePeer {
|
||||
async start(config?: PeerConfig): Promise<void> {
|
||||
throwIfNotSupported();
|
||||
|
||||
if (config?.KeyPair) {
|
||||
this._keyPair = config!.KeyPair;
|
||||
} else {
|
||||
this._keyPair = await KeyPair.randomEd25519();
|
||||
}
|
||||
const keyPair = config?.KeyPair ?? (await KeyPair.randomEd25519());
|
||||
this._keyPair = keyPair;
|
||||
|
||||
const peerId = keyPair.Libp2pPeerId.toB58String();
|
||||
|
||||
if (config?.debug?.printParticleId) {
|
||||
this._printParticleId = true;
|
||||
}
|
||||
|
||||
this._defaultTTL =
|
||||
config?.defaultTtlMs !== undefined // don't miss value 0 (zero)
|
||||
? config?.defaultTtlMs
|
||||
: DEFAULT_TTL;
|
||||
this._defaultTTL = config?.defaultTtlMs ?? DEFAULT_TTL;
|
||||
|
||||
if (config?.debug?.marineLogLevel) {
|
||||
this._marineLogLevel = config.debug.marineLogLevel;
|
||||
@ -246,7 +248,7 @@ export class FluencePeer {
|
||||
|
||||
if (config?.connectTo) {
|
||||
let connectToMultiAddr: Multiaddr;
|
||||
let fromNode = (config.connectTo as any).multiaddr;
|
||||
const fromNode = (config.connectTo as any).multiaddr;
|
||||
if (fromNode) {
|
||||
connectToMultiAddr = new Multiaddr(fromNode);
|
||||
} else {
|
||||
@ -274,14 +276,17 @@ export class FluencePeer {
|
||||
this._classServices = {
|
||||
sig: new Sig(this._keyPair),
|
||||
};
|
||||
this._classServices.sig.securityGuard = defaultSigGuard(this.getStatus().peerId);
|
||||
this._classServices.sig.securityGuard = defaultSigGuard(peerId);
|
||||
registerSig(this, this._classServices.sig);
|
||||
registerSig(this, this.getStatus().peerId, this._classServices.sig);
|
||||
registerSig(this, peerId, this._classServices.sig);
|
||||
|
||||
this._startParticleProcessing();
|
||||
}
|
||||
|
||||
getServices() {
|
||||
if (this._classServices === undefined) {
|
||||
throw new Error(`Can't get services: peer is not initialized`);
|
||||
}
|
||||
return {
|
||||
...this._classServices,
|
||||
};
|
||||
@ -297,6 +302,9 @@ export class FluencePeer {
|
||||
* @param serviceId - the service id by which the service can be accessed in aqua
|
||||
*/
|
||||
async registerMarineService(wasm: SharedArrayBuffer | Buffer, serviceId: string): Promise<void> {
|
||||
if (!this._fluenceAppService) {
|
||||
throw new Error("Can't register marine service: peer is not initialized");
|
||||
}
|
||||
if (this._containsService(serviceId)) {
|
||||
throw new Error(`Service with '${serviceId}' id already exists`);
|
||||
}
|
||||
@ -327,6 +335,7 @@ export class FluencePeer {
|
||||
await this._fluenceAppService?.terminate();
|
||||
this._avmRunner = undefined;
|
||||
this._fluenceAppService = undefined;
|
||||
this._classServices = undefined;
|
||||
|
||||
this._particleSpecificHandlers.clear();
|
||||
this._commonHandlers.clear();
|
||||
@ -340,13 +349,23 @@ export class FluencePeer {
|
||||
*/
|
||||
get internals() {
|
||||
return {
|
||||
createNewParticle: (script: string, ttl: number = this._defaultTTL) => {
|
||||
const status = this.getStatus();
|
||||
|
||||
if (!status.isInitialized) {
|
||||
return new Error("Can't create new particle: peer is not initialized");
|
||||
}
|
||||
|
||||
return Particle.createNew(script, ttl, status.peerId);
|
||||
},
|
||||
/**
|
||||
* Initiates a new particle execution starting from local peer
|
||||
* @param particle - particle to start execution of
|
||||
*/
|
||||
initiateParticle: (particle: Particle, onStageChange: (stage: ParticleExecutionStage) => void): void => {
|
||||
if (!this.getStatus().isInitialized) {
|
||||
throw 'Cannot initiate new particle: peer is not initialized';
|
||||
const status = this.getStatus();
|
||||
if (!status.isInitialized) {
|
||||
throw new Error('Cannot initiate new particle: peer is not initialized');
|
||||
}
|
||||
|
||||
if (this._printParticleId) {
|
||||
@ -354,7 +373,7 @@ export class FluencePeer {
|
||||
}
|
||||
|
||||
if (particle.initPeerId === undefined) {
|
||||
particle.initPeerId = this.getStatus().peerId;
|
||||
particle.initPeerId = status.peerId;
|
||||
}
|
||||
|
||||
if (particle.ttl === undefined) {
|
||||
@ -405,21 +424,14 @@ export class FluencePeer {
|
||||
|
||||
// private
|
||||
|
||||
/**
|
||||
* Used in `isInstance` to check if an object is of type FluencePeer. That's a hack to work around corner cases in JS type system
|
||||
*/
|
||||
private _isFluenceAwesome = true;
|
||||
|
||||
// TODO:: make public when full connection\disconnection cycle is implemented properly
|
||||
private async _connect(): Promise<void> {
|
||||
return this._connection?.connect();
|
||||
private _connect(): Promise<void> {
|
||||
return this._connection?.connect() || Promise.resolve();
|
||||
}
|
||||
|
||||
// TODO:: make public when full connection\disconnection cycle is implemented properly
|
||||
private async _disconnect(): Promise<void> {
|
||||
if (this._connection) {
|
||||
return this._connection.disconnect();
|
||||
}
|
||||
private _disconnect(): Promise<void> {
|
||||
return this._connection?.disconnect() || Promise.resolve();
|
||||
}
|
||||
|
||||
// Queues for incoming and outgoing particles
|
||||
@ -434,7 +446,7 @@ export class FluencePeer {
|
||||
private _particleSpecificHandlers = new Map<string, Map<string, GenericCallServiceHandler>>();
|
||||
private _commonHandlers = new Map<string, GenericCallServiceHandler>();
|
||||
|
||||
private _classServices: {
|
||||
private _classServices?: {
|
||||
sig: Sig;
|
||||
};
|
||||
|
||||
@ -444,17 +456,17 @@ export class FluencePeer {
|
||||
|
||||
// Internal peer state
|
||||
|
||||
private _printParticleId: boolean = false;
|
||||
private _defaultTTL: number;
|
||||
private _printParticleId = false;
|
||||
private _defaultTTL: number = DEFAULT_TTL;
|
||||
private _relayPeerId: PeerIdB58 | null = null;
|
||||
private _keyPair: KeyPair;
|
||||
private _connection: FluenceConnection;
|
||||
private _keyPair: KeyPair | undefined;
|
||||
private _connection?: FluenceConnection;
|
||||
|
||||
/**
|
||||
* @deprecated. AVM run through marine-js infrastructure. This field is needed for backward compatibility with the previous API
|
||||
*/
|
||||
private _avmRunner: AvmRunner;
|
||||
private _fluenceAppService: FluenceAppService;
|
||||
private _avmRunner?: AvmRunner;
|
||||
private _fluenceAppService?: FluenceAppService;
|
||||
private _timeouts: Array<NodeJS.Timeout> = [];
|
||||
private _particleQueues = new Map<string, Subject<ParticleQueueItem>>();
|
||||
|
||||
@ -484,7 +496,7 @@ export class FluencePeer {
|
||||
particlesQueue.next(item);
|
||||
});
|
||||
|
||||
this._outgoingParticles.subscribe(async (item) => {
|
||||
this._outgoingParticles.subscribe((item) => {
|
||||
// Do not send particle after the peer has been stopped
|
||||
if (!this.getStatus().isInitialized) {
|
||||
return;
|
||||
@ -495,8 +507,14 @@ export class FluencePeer {
|
||||
item.onStageChange({ stage: 'sendingError' });
|
||||
return;
|
||||
}
|
||||
await this._connection.sendParticle(item.particle);
|
||||
item.onStageChange({ stage: 'sent' });
|
||||
this._connection.sendParticle(item.particle).then(
|
||||
() => {
|
||||
item.onStageChange({ stage: 'sent' });
|
||||
},
|
||||
(e) => {
|
||||
log.error(e);
|
||||
},
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
@ -513,17 +531,17 @@ export class FluencePeer {
|
||||
}
|
||||
|
||||
private _createParticlesProcessingQueue() {
|
||||
let particlesQueue = new Subject<ParticleQueueItem>();
|
||||
const particlesQueue = new Subject<ParticleQueueItem>();
|
||||
let prevData: Uint8Array = Buffer.from([]);
|
||||
|
||||
particlesQueue
|
||||
.pipe(
|
||||
// force new line
|
||||
filterExpiredParticles(this._expireParticle.bind(this)),
|
||||
|
||||
concatMap(async (item) => {
|
||||
// Is `.stop()` was called we need to stop particle processing immediately
|
||||
if (!this.getStatus().isInitialized) {
|
||||
const status = this.getStatus();
|
||||
if (!status.isInitialized || this._avmRunner === undefined) {
|
||||
// If `.stop()` was called return null to stop particle processing immediately
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -532,12 +550,7 @@ export class FluencePeer {
|
||||
// MUST happen sequentially (in a critical section).
|
||||
// Otherwise the race between runner might occur corrupting the prevData
|
||||
|
||||
const result = await runAvmRunner(
|
||||
this.getStatus().peerId,
|
||||
this._avmRunner,
|
||||
item.particle,
|
||||
prevData,
|
||||
);
|
||||
const result = await runAvmRunner(status.peerId, this._avmRunner, item.particle, prevData);
|
||||
const newData = Buffer.from(result.data);
|
||||
prevData = newData;
|
||||
|
||||
@ -548,9 +561,9 @@ export class FluencePeer {
|
||||
};
|
||||
}),
|
||||
)
|
||||
.subscribe(async (item) => {
|
||||
// Is `.stop()` was called we need to stop particle processing immediately
|
||||
if (!this.getStatus().isInitialized) {
|
||||
.subscribe((item) => {
|
||||
// If `.stop()` was called then item will be null and we need to stop particle processing immediately
|
||||
if (item === null || !this.getStatus().isInitialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -574,7 +587,7 @@ export class FluencePeer {
|
||||
// execute call requests if needed
|
||||
// and put particle with the results back to queue
|
||||
if (item.result.callRequests.length > 0) {
|
||||
for (let [key, cr] of item.result.callRequests) {
|
||||
for (const [key, cr] of item.result.callRequests) {
|
||||
const req = {
|
||||
fnName: cr.functionName,
|
||||
args: cr.arguments,
|
||||
@ -617,7 +630,7 @@ export class FluencePeer {
|
||||
log.debug('executing call service handler', jsonify(req));
|
||||
const particleId = req.particleContext.particleId;
|
||||
|
||||
if (this._marineServices.has(req.serviceId)) {
|
||||
if (this._fluenceAppService && this._marineServices.has(req.serviceId)) {
|
||||
const args = JSON.stringify(req.args);
|
||||
const rawResult = await this._fluenceAppService.callService(req.serviceId, req.fnName, args, undefined);
|
||||
|
||||
@ -631,7 +644,9 @@ export class FluencePeer {
|
||||
}
|
||||
|
||||
if (result.result === undefined) {
|
||||
throw 'Call to marine-js returned no error and empty result. Original request: ' + jsonify(req);
|
||||
throw new Error(
|
||||
`Call to marine-js returned no error and empty result. Original request: ${jsonify(req)}`,
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
@ -639,13 +654,13 @@ export class FluencePeer {
|
||||
result: result.result,
|
||||
};
|
||||
} catch (e) {
|
||||
throw 'Call to marine-js. Result parsing error: ' + e + ', original text: ' + rawResult;
|
||||
throw new Error(`Call to marine-js. Result parsing error: ${e}, original text: ${rawResult}`);
|
||||
}
|
||||
}
|
||||
|
||||
const key = serviceFnKey(req.serviceId, req.fnName);
|
||||
const psh = this._particleSpecificHandlers.get(particleId);
|
||||
let handler: GenericCallServiceHandler;
|
||||
let handler: GenericCallServiceHandler | undefined;
|
||||
|
||||
// we should prioritize handler for this particle if there is one
|
||||
// if particle-specific handlers exist for this particle try getting handler there
|
||||
@ -682,9 +697,9 @@ export class FluencePeer {
|
||||
|
||||
private _stopParticleProcessing() {
|
||||
// do not hang if the peer has been stopped while some of the timeouts are still being executed
|
||||
for (let item of this._timeouts) {
|
||||
clearTimeout(item);
|
||||
}
|
||||
this._timeouts.forEach((timeout) => {
|
||||
clearTimeout(timeout);
|
||||
});
|
||||
this._particleQueues.clear();
|
||||
}
|
||||
}
|
||||
@ -698,12 +713,11 @@ function serviceFnKey(serviceId: string, fnName: string) {
|
||||
}
|
||||
|
||||
function registerDefaultServices(peer: FluencePeer) {
|
||||
for (let serviceId in builtInServices) {
|
||||
for (let fnName in builtInServices[serviceId]) {
|
||||
const h = builtInServices[serviceId][fnName];
|
||||
peer.internals.regHandler.common(serviceId, fnName, h);
|
||||
}
|
||||
}
|
||||
Object.entries(builtInServices).forEach(([serviceId, service]) => {
|
||||
Object.entries(service).forEach(([fnName, fn]) => {
|
||||
peer.internals.regHandler.common(serviceId, fnName, fn);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async function runAvmRunner(
|
||||
@ -727,8 +741,7 @@ async function runAvmRunner(
|
||||
particle.callResults,
|
||||
);
|
||||
|
||||
const toLog: any = { ...interpreterResult };
|
||||
toLog.data = dataToString(toLog.data);
|
||||
const toLog = { ...interpreterResult, data: dataToString(interpreterResult.data) };
|
||||
|
||||
if (isInterpretationSuccessful(interpreterResult)) {
|
||||
log.debug('Interpreter result: ', jsonify(toLog));
|
||||
|
@ -23,36 +23,35 @@ import Buffer from './Buffer';
|
||||
import { CallResultsArray, LogLevel } from '@fluencelabs/avm';
|
||||
|
||||
export class Particle {
|
||||
id: string;
|
||||
initPeerId: string;
|
||||
timestamp: number;
|
||||
ttl: number;
|
||||
script: string;
|
||||
signature: string;
|
||||
data: Uint8Array;
|
||||
// TODO: make it not optional (should be added to the constructor)
|
||||
signature?: string;
|
||||
callResults: CallResultsArray = [];
|
||||
|
||||
static createNew(script: string, ttlMs?: number): Particle {
|
||||
const res = new Particle();
|
||||
res.id = genUUID();
|
||||
res.script = script;
|
||||
res.ttl = ttlMs;
|
||||
res.data = Buffer.from([]);
|
||||
res.timestamp = Date.now();
|
||||
constructor(
|
||||
public id: string,
|
||||
public timestamp: number,
|
||||
public script: string,
|
||||
public data: Uint8Array,
|
||||
public ttl: number,
|
||||
public initPeerId: string,
|
||||
) {}
|
||||
|
||||
return res;
|
||||
static createNew(script: string, ttl: number, initPeerId: string): Particle {
|
||||
return new Particle(genUUID(), Date.now(), script, Buffer.from([]), ttl, initPeerId);
|
||||
}
|
||||
|
||||
static fromString(str: string): Particle {
|
||||
const json = JSON.parse(str);
|
||||
const res = new Particle();
|
||||
res.id = json.id;
|
||||
res.initPeerId = json.init_peer_id;
|
||||
res.timestamp = json.timestamp;
|
||||
res.ttl = json.ttl;
|
||||
res.script = json.script;
|
||||
const res = new Particle(
|
||||
json.id,
|
||||
json.timestamp,
|
||||
json.script,
|
||||
toByteArray(json.data),
|
||||
json.ttl,
|
||||
json.init_peer_id,
|
||||
);
|
||||
|
||||
res.signature = json.signature;
|
||||
res.data = toByteArray(json.data);
|
||||
|
||||
return res;
|
||||
}
|
||||
@ -76,38 +75,30 @@ export class Particle {
|
||||
}
|
||||
|
||||
clone(): Particle {
|
||||
const res = new Particle();
|
||||
res.id = this.id;
|
||||
res.initPeerId = this.initPeerId;
|
||||
res.timestamp = this.timestamp;
|
||||
res.ttl = this.ttl;
|
||||
res.script = this.script;
|
||||
const res = new Particle(this.id, this.timestamp, this.script, this.data, this.ttl, this.initPeerId);
|
||||
|
||||
res.signature = this.signature;
|
||||
res.data = this.data;
|
||||
res.callResults = this.callResults;
|
||||
return res;
|
||||
}
|
||||
|
||||
toString(): string {
|
||||
const particle = this;
|
||||
const payload = {
|
||||
return JSON.stringify({
|
||||
action: 'Particle',
|
||||
id: particle.id,
|
||||
init_peer_id: particle.initPeerId,
|
||||
timestamp: particle.timestamp,
|
||||
ttl: particle.ttl,
|
||||
script: particle.script,
|
||||
id: this.id,
|
||||
init_peer_id: this.initPeerId,
|
||||
timestamp: this.timestamp,
|
||||
ttl: this.ttl,
|
||||
script: this.script,
|
||||
// TODO: copy signature from a particle after signatures will be implemented on nodes
|
||||
signature: [],
|
||||
data: fromByteArray(particle.data),
|
||||
};
|
||||
|
||||
return JSON.stringify(payload);
|
||||
data: this.data && fromByteArray(this.data),
|
||||
});
|
||||
}
|
||||
|
||||
logTo(level: LogLevel, message: string) {
|
||||
let fn;
|
||||
let data;
|
||||
let data: string | undefined;
|
||||
switch (level) {
|
||||
case 'debug':
|
||||
fn = log.debug;
|
||||
@ -117,8 +108,6 @@ export class Particle {
|
||||
fn = log.error;
|
||||
break;
|
||||
case 'info':
|
||||
fn = log.info;
|
||||
break;
|
||||
case 'trace':
|
||||
fn = log.info;
|
||||
break;
|
||||
@ -139,7 +128,7 @@ export class Particle {
|
||||
script: this.script,
|
||||
signature: this.signature,
|
||||
callResults: this.callResults,
|
||||
data: data,
|
||||
data,
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
@ -16,10 +16,11 @@
|
||||
|
||||
import { encode, decode } from 'bs58';
|
||||
import { sha256 } from 'multiformats/hashes/sha2';
|
||||
import { ResultCodes } from '../commonTypes';
|
||||
import { CallServiceResult } from '@fluencelabs/avm';
|
||||
|
||||
import { GenericCallServiceHandler, ResultCodes } from '../commonTypes';
|
||||
import { jsonify } from '../utils';
|
||||
import Buffer from '../Buffer';
|
||||
import { CallServiceResult } from '@fluencelabs/avm';
|
||||
|
||||
const success = (result: any): CallServiceResult => {
|
||||
return {
|
||||
@ -39,29 +40,29 @@ const errorNotImpl = (methodName: string) => {
|
||||
return error(`The JS implementation of Peer does not support "${methodName}"`);
|
||||
};
|
||||
|
||||
export const builtInServices = {
|
||||
export const builtInServices: Record<string, Record<string, GenericCallServiceHandler>> = {
|
||||
peer: {
|
||||
identify: (req) => {
|
||||
identify: () => {
|
||||
return errorNotImpl('peer.identify');
|
||||
},
|
||||
|
||||
timestamp_ms: (req) => {
|
||||
timestamp_ms: () => {
|
||||
return success(Date.now());
|
||||
},
|
||||
|
||||
timestamp_sec: (req) => {
|
||||
timestamp_sec: () => {
|
||||
return success(Math.floor(Date.now() / 1000));
|
||||
},
|
||||
|
||||
is_connected: (req) => {
|
||||
is_connected: () => {
|
||||
return errorNotImpl('peer.is_connected');
|
||||
},
|
||||
|
||||
connect: (req) => {
|
||||
connect: () => {
|
||||
return errorNotImpl('peer.connect');
|
||||
},
|
||||
|
||||
get_contact: (req) => {
|
||||
get_contact: () => {
|
||||
return errorNotImpl('peer.get_contact');
|
||||
},
|
||||
|
||||
@ -82,103 +83,103 @@ export const builtInServices = {
|
||||
},
|
||||
|
||||
kad: {
|
||||
neighborhood: (req) => {
|
||||
neighborhood: () => {
|
||||
return errorNotImpl('kad.neighborhood');
|
||||
},
|
||||
|
||||
merge: (req) => {
|
||||
merge: () => {
|
||||
return errorNotImpl('kad.merge');
|
||||
},
|
||||
},
|
||||
|
||||
srv: {
|
||||
list: (req) => {
|
||||
list: () => {
|
||||
return errorNotImpl('srv.list');
|
||||
},
|
||||
|
||||
create: (req) => {
|
||||
create: () => {
|
||||
return errorNotImpl('srv.create');
|
||||
},
|
||||
|
||||
get_interface: (req) => {
|
||||
get_interface: () => {
|
||||
return errorNotImpl('srv.get_interface');
|
||||
},
|
||||
|
||||
resolve_alias: (req) => {
|
||||
resolve_alias: () => {
|
||||
return errorNotImpl('srv.resolve_alias');
|
||||
},
|
||||
|
||||
add_alias: (req) => {
|
||||
add_alias: () => {
|
||||
return errorNotImpl('srv.add_alias');
|
||||
},
|
||||
|
||||
remove: (req) => {
|
||||
remove: () => {
|
||||
return errorNotImpl('srv.remove');
|
||||
},
|
||||
},
|
||||
|
||||
dist: {
|
||||
add_module_from_vault: (req) => {
|
||||
add_module_from_vault: () => {
|
||||
return errorNotImpl('dist.add_module_from_vault');
|
||||
},
|
||||
|
||||
add_module: (req) => {
|
||||
add_module: () => {
|
||||
return errorNotImpl('dist.add_module');
|
||||
},
|
||||
|
||||
add_blueprint: (req) => {
|
||||
add_blueprint: () => {
|
||||
return errorNotImpl('dist.add_blueprint');
|
||||
},
|
||||
|
||||
make_module_config: (req) => {
|
||||
make_module_config: () => {
|
||||
return errorNotImpl('dist.make_module_config');
|
||||
},
|
||||
|
||||
load_module_config: (req) => {
|
||||
load_module_config: () => {
|
||||
return errorNotImpl('dist.load_module_config');
|
||||
},
|
||||
|
||||
default_module_config: (req) => {
|
||||
default_module_config: () => {
|
||||
return errorNotImpl('dist.default_module_config');
|
||||
},
|
||||
|
||||
make_blueprint: (req) => {
|
||||
make_blueprint: () => {
|
||||
return errorNotImpl('dist.make_blueprint');
|
||||
},
|
||||
|
||||
load_blueprint: (req) => {
|
||||
load_blueprint: () => {
|
||||
return errorNotImpl('dist.load_blueprint');
|
||||
},
|
||||
|
||||
list_modules: (req) => {
|
||||
list_modules: () => {
|
||||
return errorNotImpl('dist.list_modules');
|
||||
},
|
||||
|
||||
get_module_interface: (req) => {
|
||||
get_module_interface: () => {
|
||||
return errorNotImpl('dist.get_module_interface');
|
||||
},
|
||||
|
||||
list_blueprints: (req) => {
|
||||
list_blueprints: () => {
|
||||
return errorNotImpl('dist.list_blueprints');
|
||||
},
|
||||
},
|
||||
|
||||
script: {
|
||||
add: (req) => {
|
||||
add: () => {
|
||||
return errorNotImpl('script.add');
|
||||
},
|
||||
|
||||
remove: (req) => {
|
||||
remove: () => {
|
||||
return errorNotImpl('script.remove');
|
||||
},
|
||||
|
||||
list: (req) => {
|
||||
list: () => {
|
||||
return errorNotImpl('script.list');
|
||||
},
|
||||
},
|
||||
|
||||
op: {
|
||||
noop: (req) => {
|
||||
noop: () => {
|
||||
return success({});
|
||||
},
|
||||
|
||||
@ -251,7 +252,7 @@ export const builtInServices = {
|
||||
|
||||
sha256_string: async (req) => {
|
||||
if (req.args.length < 1 || req.args.length > 3) {
|
||||
return error('sha256_string accepts 1-3 arguments, found: ' + req.args.length);
|
||||
return error(`sha256_string accepts 1-3 arguments, found: ${req.args.length}`);
|
||||
} else {
|
||||
const [input, digestOnly, asBytes] = req.args;
|
||||
const inBuffer = Buffer.from(input);
|
||||
@ -414,7 +415,7 @@ export const builtInServices = {
|
||||
return err;
|
||||
}
|
||||
const [xs] = req.args;
|
||||
return success(xs.reduce((agg, cur) => agg + cur, 0));
|
||||
return success(xs.reduce((agg: any, cur: any) => agg + cur, 0));
|
||||
},
|
||||
|
||||
dedup: (req) => {
|
||||
@ -433,7 +434,7 @@ export const builtInServices = {
|
||||
return err;
|
||||
}
|
||||
const [xs, ys] = req.args;
|
||||
const intersection = xs.filter((x) => ys.includes(x));
|
||||
const intersection = xs.filter((x: any) => ys.includes(x));
|
||||
return success(intersection);
|
||||
},
|
||||
|
||||
@ -443,7 +444,7 @@ export const builtInServices = {
|
||||
return err;
|
||||
}
|
||||
const [xs, ys] = req.args;
|
||||
const diff = xs.filter((x) => !ys.includes(x));
|
||||
const diff = xs.filter((x: unknown) => !ys.includes(x));
|
||||
return success(diff);
|
||||
},
|
||||
|
||||
@ -455,15 +456,15 @@ export const builtInServices = {
|
||||
const [xs, ys] = req.args;
|
||||
const sdiff = [
|
||||
// force new line
|
||||
...xs.filter((y) => !ys.includes(y)),
|
||||
...ys.filter((x) => !xs.includes(x)),
|
||||
...xs.filter((y: unknown) => !ys.includes(y)),
|
||||
...ys.filter((x: unknown) => !xs.includes(x)),
|
||||
];
|
||||
return success(sdiff);
|
||||
},
|
||||
},
|
||||
};
|
||||
} as const;
|
||||
|
||||
const checkForArgumentsCount = (req, count: number) => {
|
||||
const checkForArgumentsCount = (req: { args: Array<unknown> }, count: number) => {
|
||||
if (req.args.length !== count) {
|
||||
return error(`Expected ${count} argument(s). Got ${req.args.length}`);
|
||||
}
|
||||
|
@ -49,12 +49,12 @@ export interface CallParams<ArgName extends string | null> {
|
||||
/**
|
||||
* Particle's signature
|
||||
*/
|
||||
signature: string;
|
||||
signature?: string;
|
||||
|
||||
/**
|
||||
* Security tetraplets
|
||||
*/
|
||||
tetraplets: { [key in ArgName]: SecurityTetraplet[] };
|
||||
tetraplets: ArgName extends string ? Record<ArgName, SecurityTetraplet[]> : Record<string, never>;
|
||||
}
|
||||
|
||||
export enum ResultCodes {
|
||||
@ -89,7 +89,7 @@ export interface ParticleContext {
|
||||
/**
|
||||
* Particle's signature
|
||||
*/
|
||||
signature: string;
|
||||
signature?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -123,7 +123,7 @@ export interface CallServiceData {
|
||||
}
|
||||
|
||||
/**
|
||||
* Type for all the possible objects that can be return to the AVM
|
||||
* Type for all the possible objects that can be returned to the AVM
|
||||
*/
|
||||
export type CallServiceResultType = object | boolean | number | string | null;
|
||||
|
||||
|
@ -215,7 +215,11 @@ export function callFunction(rawFnArgs: Array<any>, def: FunctionCallDef, script
|
||||
}
|
||||
|
||||
const promise = new Promise((resolve, reject) => {
|
||||
const particle = Particle.createNew(script, config?.ttl);
|
||||
const particle = peer.internals.createNewParticle(script, config?.ttl);
|
||||
|
||||
if (particle instanceof Error) {
|
||||
return reject(particle.message);
|
||||
}
|
||||
|
||||
for (let i = 0; i < def.argDefs.length; i++) {
|
||||
const argDef = def.argDefs[i];
|
||||
|
@ -35,7 +35,11 @@ export function callFunction(rawFnArgs: Array<any>, def: FunctionCallDef, script
|
||||
}
|
||||
|
||||
const promise = new Promise((resolve, reject) => {
|
||||
const particle = Particle.createNew(script, config?.ttl);
|
||||
const particle = peer.internals.createNewParticle(script, config?.ttl);
|
||||
|
||||
if (particle instanceof Error) {
|
||||
return reject(particle.message);
|
||||
}
|
||||
|
||||
for (let i = 0; i < expectedNumberOfArguments; i++) {
|
||||
const [name, type] = argumentTypes[i];
|
||||
|
@ -9,7 +9,7 @@ import { CallServiceData } from 'src/internal/commonTypes';
|
||||
* @param type - definition of the aqua type
|
||||
* @returns value represented in typescript
|
||||
*/
|
||||
export const aqua2ts = (value: any, type: NonArrowType) => {
|
||||
export const aqua2ts = (value: any, type: NonArrowType): any => {
|
||||
const res = match(type)
|
||||
.with({ tag: 'nil' }, () => {
|
||||
return null;
|
||||
@ -25,7 +25,7 @@ export const aqua2ts = (value: any, type: NonArrowType) => {
|
||||
return value;
|
||||
})
|
||||
.with({ tag: 'array' }, (arr) => {
|
||||
return value.map((y) => aqua2ts(y, arr.type));
|
||||
return value.map((y: any) => aqua2ts(y, arr.type));
|
||||
})
|
||||
.with({ tag: 'struct' }, (x) => {
|
||||
return Object.entries(x.fields).reduce((agg, [key, type]) => {
|
||||
@ -90,7 +90,7 @@ export const aquaArgs2Ts = (req: CallServiceData, arrow: ArrowWithoutCallbacks)
|
||||
* @param type - definition of the aqua type
|
||||
* @returns value represented in aqua
|
||||
*/
|
||||
export const ts2aqua = (value: any, type: NonArrowType) => {
|
||||
export const ts2aqua = (value: any, type: NonArrowType): any => {
|
||||
const res = match(type)
|
||||
.with({ tag: 'nil' }, () => {
|
||||
return null;
|
||||
@ -106,7 +106,7 @@ export const ts2aqua = (value: any, type: NonArrowType) => {
|
||||
return value;
|
||||
})
|
||||
.with({ tag: 'array' }, (arr) => {
|
||||
return value.map((y) => ts2aqua(y, arr.type));
|
||||
return value.map((y: any) => ts2aqua(y, arr.type));
|
||||
})
|
||||
.with({ tag: 'struct' }, (x) => {
|
||||
return Object.entries(x.fields).reduce((agg, [key, type]) => {
|
||||
|
@ -1,14 +1,10 @@
|
||||
import { SecurityTetraplet } from '@fluencelabs/avm';
|
||||
import { Particle } from 'src/internal/Particle';
|
||||
import { match } from 'ts-pattern';
|
||||
import {
|
||||
CallParams,
|
||||
CallServiceData,
|
||||
CallServiceResult,
|
||||
GenericCallServiceHandler,
|
||||
ResultCodes,
|
||||
} from '../../commonTypes';
|
||||
|
||||
import { Particle } from '../../Particle';
|
||||
import { CallParams, CallServiceData, GenericCallServiceHandler, ResultCodes } from '../../commonTypes';
|
||||
import { FluencePeer } from '../../FluencePeer';
|
||||
|
||||
import { aquaArgs2Ts, responseServiceValue2ts, returnType2Aqua, ts2aqua } from './conversions';
|
||||
import { ArrowWithoutCallbacks, FunctionCallConstants, FunctionCallDef, NonArrowType } from './interface';
|
||||
|
||||
@ -25,7 +21,7 @@ export const injectRelayService = (def: FunctionCallDef, peer: FluencePeer) => {
|
||||
return {
|
||||
serviceId: def.names.getDataSrv,
|
||||
fnName: def.names.relay,
|
||||
handler: (req) => {
|
||||
handler: () => {
|
||||
return {
|
||||
retCode: ResultCodes.success,
|
||||
result: peer.getStatus().relayPeerId,
|
||||
@ -41,7 +37,7 @@ export const injectValueService = (serviceId: string, fnName: string, valueType:
|
||||
return {
|
||||
serviceId: serviceId,
|
||||
fnName: fnName,
|
||||
handler: (req) => {
|
||||
handler: () => {
|
||||
return {
|
||||
retCode: ResultCodes.success,
|
||||
result: ts2aqua(value, valueType),
|
||||
@ -57,7 +53,7 @@ export const responseService = (def: FunctionCallDef, resolveCallback: Function)
|
||||
return {
|
||||
serviceId: def.names.responseSrv,
|
||||
fnName: def.names.responseFnName,
|
||||
handler: (req) => {
|
||||
handler: (req: CallServiceData) => {
|
||||
const userFunctionReturn = responseServiceValue2ts(req, def.arrow);
|
||||
|
||||
setTimeout(() => {
|
||||
@ -79,7 +75,7 @@ export const errorHandlingService = (def: FunctionCallDef, rejectCallback: Funct
|
||||
return {
|
||||
serviceId: def.names.errorHandlingSrv,
|
||||
fnName: def.names.errorFnName,
|
||||
handler: (req) => {
|
||||
handler: (req: CallServiceData) => {
|
||||
const [err, _] = req.args;
|
||||
setTimeout(() => {
|
||||
rejectCallback(err);
|
||||
@ -95,12 +91,16 @@ export const errorHandlingService = (def: FunctionCallDef, rejectCallback: Funct
|
||||
/**
|
||||
* Creates a service for user-defined service function handler
|
||||
*/
|
||||
export const userHandlerService = (serviceId: string, arrowType: [string, ArrowWithoutCallbacks], userHandler) => {
|
||||
export const userHandlerService = (
|
||||
serviceId: string,
|
||||
arrowType: [string, ArrowWithoutCallbacks],
|
||||
userHandler: (...args: Array<unknown>) => Promise<unknown>,
|
||||
) => {
|
||||
const [fnName, type] = arrowType;
|
||||
return {
|
||||
serviceId,
|
||||
fnName,
|
||||
handler: async (req) => {
|
||||
handler: async (req: CallServiceData) => {
|
||||
const args = [...aquaArgs2Ts(req, type), extractCallParams(req, type)];
|
||||
const rawResult = await userHandler.apply(null, args);
|
||||
const result = returnType2Aqua(rawResult, type);
|
||||
@ -147,7 +147,7 @@ const extractCallParams = (req: CallServiceData, arrow: ArrowWithoutCallbacks):
|
||||
})
|
||||
.exhaustive();
|
||||
|
||||
let tetraplets: { [key in string]: SecurityTetraplet[] } = {};
|
||||
const tetraplets: Record<string, SecurityTetraplet[]> = {};
|
||||
for (let i = 0; i < req.args.length; i++) {
|
||||
if (names[i]) {
|
||||
tetraplets[names[i]] = req.tetraplets[i];
|
||||
|
@ -15,28 +15,26 @@
|
||||
*/
|
||||
|
||||
import log from 'loglevel';
|
||||
import { CallServiceData, CallServiceResult, CallServiceResultType, ResultCodes } from './commonTypes';
|
||||
import { FluencePeer } from './FluencePeer';
|
||||
import { Particle, ParticleExecutionStage } from './Particle';
|
||||
import Buffer from './Buffer';
|
||||
import platform from 'platform';
|
||||
|
||||
export const MakeServiceCall = (fn: (args: any[]) => CallServiceResultType) => {
|
||||
return (req: CallServiceData): CallServiceResult => {
|
||||
return {
|
||||
retCode: ResultCodes.success,
|
||||
result: fn(req.args),
|
||||
};
|
||||
};
|
||||
};
|
||||
import { CallServiceData, CallServiceResult, CallServiceResultType, ResultCodes } from './commonTypes';
|
||||
import { FluencePeer } from './FluencePeer';
|
||||
import { ParticleExecutionStage } from './Particle';
|
||||
import Buffer from './Buffer';
|
||||
|
||||
export const handleTimeout = (fn: Function) => (stage: ParticleExecutionStage) => {
|
||||
export const MakeServiceCall =
|
||||
(fn: (args: any[]) => CallServiceResultType) =>
|
||||
(req: CallServiceData): CallServiceResult => ({
|
||||
retCode: ResultCodes.success,
|
||||
result: fn(req.args),
|
||||
});
|
||||
|
||||
export const handleTimeout = (fn: () => void) => (stage: ParticleExecutionStage) => {
|
||||
if (stage.stage === 'expired') {
|
||||
fn();
|
||||
}
|
||||
};
|
||||
|
||||
export const doNothing = (stage: ParticleExecutionStage) => {};
|
||||
export const doNothing = (..._args: Array<unknown>) => undefined;
|
||||
|
||||
/**
|
||||
* Checks the network connection by sending a ping-like request to relay node
|
||||
@ -67,7 +65,12 @@ export const checkConnection = async (peer: FluencePeer, ttl?: number): Promise<
|
||||
(call %init_peer_id% ("callback" "error") [%last_error%])
|
||||
)
|
||||
)`;
|
||||
const particle = Particle.createNew(script, ttl);
|
||||
const particle = peer.internals.createNewParticle(script, ttl);
|
||||
|
||||
if (particle instanceof Error) {
|
||||
return reject(particle.message);
|
||||
}
|
||||
|
||||
peer.internals.regHandler.forParticle(
|
||||
particle.id,
|
||||
'load',
|
||||
@ -142,12 +145,12 @@ export function dataToString(data: Uint8Array) {
|
||||
}
|
||||
}
|
||||
|
||||
export function jsonify(obj) {
|
||||
export function jsonify(obj: unknown) {
|
||||
return JSON.stringify(obj, null, 4);
|
||||
}
|
||||
|
||||
export function throwIfNotSupported() {
|
||||
if (platform.name === 'Node.js') {
|
||||
if (platform.name === 'Node.js' && platform.version) {
|
||||
const version = platform.version.split('.').map(Number);
|
||||
const major = version[0];
|
||||
if (major < 16) {
|
||||
|
@ -1,35 +1,22 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"typeRoots": [
|
||||
"./node_modules/@types",
|
||||
"./node_modules/libp2p-ts/types",
|
||||
],
|
||||
"outDir": "./dist/",
|
||||
"baseUrl": ".",
|
||||
"downlevelIteration": true,
|
||||
"sourceMap": true,
|
||||
"inlineSources": true,
|
||||
"strictFunctionTypes": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"resolveJsonModule": true,
|
||||
"pretty": true,
|
||||
"target": "ES5",
|
||||
"module": "commonjs",
|
||||
"moduleResolution": "node",
|
||||
"declaration": true,
|
||||
"esModuleInterop": true,
|
||||
"declarationMap": true,
|
||||
"strict": true,
|
||||
"noImplicitAny": false,
|
||||
"alwaysStrict": true,
|
||||
"noImplicitThis": true,
|
||||
"strictNullChecks": false
|
||||
},
|
||||
"exclude": [
|
||||
"node_modules",
|
||||
"dist",
|
||||
"bundle",
|
||||
"src/__test__"
|
||||
],
|
||||
"include": ["src/**/*"]
|
||||
"compilerOptions": {
|
||||
"typeRoots": ["./node_modules/@types", "./node_modules/libp2p-ts/types"],
|
||||
"outDir": "./dist/",
|
||||
"baseUrl": ".",
|
||||
"downlevelIteration": true,
|
||||
"sourceMap": true,
|
||||
"inlineSources": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"resolveJsonModule": true,
|
||||
"target": "ES5",
|
||||
"module": "commonjs",
|
||||
"moduleResolution": "node",
|
||||
"declaration": true,
|
||||
"esModuleInterop": true,
|
||||
"declarationMap": true,
|
||||
"strict": true,
|
||||
"skipLibCheck": true
|
||||
},
|
||||
"exclude": ["node_modules", "dist", "bundle"],
|
||||
"include": ["src/**/*"]
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user