mirror of
https://github.com/fluencelabs/fluence-js.git
synced 2024-12-05 02:10:18 +00:00
Integrate async AquaVM into fluence-js (#88)
This commit is contained in:
parent
727d59fb61
commit
fe52648103
File diff suppressed because one or more lines are too long
@ -121,7 +121,7 @@
|
||||
<li class="tsd-description">
|
||||
<aside class="tsd-sources">
|
||||
<ul>
|
||||
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/c0acd41/src/internal/FluencePeer.ts#L107">internal/FluencePeer.ts:107</a></li>
|
||||
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/9f81458/src/internal/FluencePeer.ts#L132">internal/FluencePeer.ts:132</a></li>
|
||||
</ul>
|
||||
</aside>
|
||||
<div class="tsd-comment tsd-typography">
|
||||
@ -140,13 +140,13 @@
|
||||
<a name="internals" class="tsd-anchor"></a>
|
||||
<h3>internals</h3>
|
||||
<ul class="tsd-signatures tsd-kind-get-signature tsd-parent-kind-class">
|
||||
<li class="tsd-signature tsd-kind-icon"><span class="tsd-signature-symbol">get</span> internals<span class="tsd-signature-symbol">(</span><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol">: </span><span class="tsd-signature-symbol">{ </span>callServiceHandler<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">CallServiceHandler</span><span class="tsd-signature-symbol">; </span>initiateFlow<span class="tsd-signature-symbol">: </span><span class="tsd-signature-symbol">(</span>request<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">RequestFlow</span><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol"> => </span><span class="tsd-signature-type">Promise</span><span class="tsd-signature-symbol"><</span><span class="tsd-signature-type">void</span><span class="tsd-signature-symbol">></span><span class="tsd-signature-symbol"> }</span></li>
|
||||
<li class="tsd-signature tsd-kind-icon"><span class="tsd-signature-symbol">get</span> internals<span class="tsd-signature-symbol">(</span><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol">: </span><span class="tsd-signature-symbol">{ </span>callServiceHandler<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">CallServiceHandler</span><span class="tsd-signature-symbol">; </span>initiateFlow<span class="tsd-signature-symbol">: </span><span class="tsd-signature-symbol">(</span>request<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">RequestFlow</span><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol"> => </span><span class="tsd-signature-type">void</span><span class="tsd-signature-symbol">; </span>initiateParticle<span class="tsd-signature-symbol">: </span><span class="tsd-signature-symbol">(</span>particle<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">Particle</span><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol"> => </span><span class="tsd-signature-type">void</span><span class="tsd-signature-symbol">; </span>regHandler<span class="tsd-signature-symbol">: </span><span class="tsd-signature-symbol">{ </span>common<span class="tsd-signature-symbol">: </span><span class="tsd-signature-symbol">(</span>serviceId<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">string</span>, fnName<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">string</span>, handler<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">GenericCallServiceHandler</span><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol"> => </span><span class="tsd-signature-type">void</span><span class="tsd-signature-symbol">; </span>forParticle<span class="tsd-signature-symbol">: </span><span class="tsd-signature-symbol">(</span>particleId<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">string</span>, serviceId<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">string</span>, fnName<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">string</span>, handler<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">GenericCallServiceHandler</span><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol"> => </span><span class="tsd-signature-type">void</span><span class="tsd-signature-symbol">; </span>timeout<span class="tsd-signature-symbol">: </span><span class="tsd-signature-symbol">(</span>particleId<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">string</span>, handler<span class="tsd-signature-symbol">: </span><span class="tsd-signature-symbol">(</span><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol"> => </span><span class="tsd-signature-type">void</span><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol"> => </span><span class="tsd-signature-type">void</span><span class="tsd-signature-symbol"> }</span><span class="tsd-signature-symbol"> }</span></li>
|
||||
</ul>
|
||||
<ul class="tsd-descriptions">
|
||||
<li class="tsd-description">
|
||||
<aside class="tsd-sources">
|
||||
<ul>
|
||||
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/c0acd41/src/internal/FluencePeer.ts#L182">internal/FluencePeer.ts:182</a></li>
|
||||
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/9f81458/src/internal/FluencePeer.ts#L225">internal/FluencePeer.ts:225</a></li>
|
||||
</ul>
|
||||
</aside>
|
||||
<div class="tsd-comment tsd-typography">
|
||||
@ -154,27 +154,175 @@
|
||||
<p>Is not intended to be used manually. Subject to change</p>
|
||||
</div>
|
||||
</div>
|
||||
<h4 class="tsd-returns-title">Returns <span class="tsd-signature-symbol">{ </span>callServiceHandler<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">CallServiceHandler</span><span class="tsd-signature-symbol">; </span>initiateFlow<span class="tsd-signature-symbol">: </span><span class="tsd-signature-symbol">(</span>request<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">RequestFlow</span><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol"> => </span><span class="tsd-signature-type">Promise</span><span class="tsd-signature-symbol"><</span><span class="tsd-signature-type">void</span><span class="tsd-signature-symbol">></span><span class="tsd-signature-symbol"> }</span></h4>
|
||||
<h4 class="tsd-returns-title">Returns <span class="tsd-signature-symbol">{ </span>callServiceHandler<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">CallServiceHandler</span><span class="tsd-signature-symbol">; </span>initiateFlow<span class="tsd-signature-symbol">: </span><span class="tsd-signature-symbol">(</span>request<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">RequestFlow</span><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol"> => </span><span class="tsd-signature-type">void</span><span class="tsd-signature-symbol">; </span>initiateParticle<span class="tsd-signature-symbol">: </span><span class="tsd-signature-symbol">(</span>particle<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">Particle</span><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol"> => </span><span class="tsd-signature-type">void</span><span class="tsd-signature-symbol">; </span>regHandler<span class="tsd-signature-symbol">: </span><span class="tsd-signature-symbol">{ </span>common<span class="tsd-signature-symbol">: </span><span class="tsd-signature-symbol">(</span>serviceId<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">string</span>, fnName<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">string</span>, handler<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">GenericCallServiceHandler</span><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol"> => </span><span class="tsd-signature-type">void</span><span class="tsd-signature-symbol">; </span>forParticle<span class="tsd-signature-symbol">: </span><span class="tsd-signature-symbol">(</span>particleId<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">string</span>, serviceId<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">string</span>, fnName<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">string</span>, handler<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">GenericCallServiceHandler</span><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol"> => </span><span class="tsd-signature-type">void</span><span class="tsd-signature-symbol">; </span>timeout<span class="tsd-signature-symbol">: </span><span class="tsd-signature-symbol">(</span>particleId<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">string</span>, handler<span class="tsd-signature-symbol">: </span><span class="tsd-signature-symbol">(</span><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol"> => </span><span class="tsd-signature-type">void</span><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol"> => </span><span class="tsd-signature-type">void</span><span class="tsd-signature-symbol"> }</span><span class="tsd-signature-symbol"> }</span></h4>
|
||||
<ul class="tsd-parameters">
|
||||
<li class="tsd-parameter">
|
||||
<h5>call<wbr>Service<wbr>Handler<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">CallServiceHandler</span></h5>
|
||||
</li>
|
||||
<li class="tsd-parameter">
|
||||
<h5>initiate<wbr>Flow<span class="tsd-signature-symbol">: </span><span class="tsd-signature-symbol">(</span>request<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">RequestFlow</span><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol"> => </span><span class="tsd-signature-type">Promise</span><span class="tsd-signature-symbol"><</span><span class="tsd-signature-type">void</span><span class="tsd-signature-symbol">></span></h5>
|
||||
<h5>initiate<wbr>Flow<span class="tsd-signature-symbol">: </span><span class="tsd-signature-symbol">(</span>request<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">RequestFlow</span><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol"> => </span><span class="tsd-signature-type">void</span></h5>
|
||||
<ul class="tsd-parameters">
|
||||
<li class="tsd-parameter-signature">
|
||||
<ul class="tsd-signatures tsd-kind-type-literal tsd-parent-kind-type-literal">
|
||||
<li class="tsd-signature tsd-kind-icon"><span class="tsd-signature-symbol">(</span>request<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">RequestFlow</span><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">Promise</span><span class="tsd-signature-symbol"><</span><span class="tsd-signature-type">void</span><span class="tsd-signature-symbol">></span></li>
|
||||
<li class="tsd-signature tsd-kind-icon"><span class="tsd-signature-symbol">(</span>request<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">RequestFlow</span><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">void</span></li>
|
||||
</ul>
|
||||
<ul class="tsd-descriptions">
|
||||
<li class="tsd-description">
|
||||
<div class="tsd-comment tsd-typography">
|
||||
<dl class="tsd-comment-tags">
|
||||
<dt>deprecated</dt>
|
||||
<dd></dd>
|
||||
</dl>
|
||||
</div>
|
||||
<h4 class="tsd-parameters-title">Parameters</h4>
|
||||
<ul class="tsd-parameters">
|
||||
<li>
|
||||
<h5>request: <span class="tsd-signature-type">RequestFlow</span></h5>
|
||||
</li>
|
||||
</ul>
|
||||
<h4 class="tsd-returns-title">Returns <span class="tsd-signature-type">Promise</span><span class="tsd-signature-symbol"><</span><span class="tsd-signature-type">void</span><span class="tsd-signature-symbol">></span></h4>
|
||||
<h4 class="tsd-returns-title">Returns <span class="tsd-signature-type">void</span></h4>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="tsd-parameter">
|
||||
<h5>initiate<wbr>Particle<span class="tsd-signature-symbol">: </span><span class="tsd-signature-symbol">(</span>particle<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">Particle</span><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol"> => </span><span class="tsd-signature-type">void</span></h5>
|
||||
<ul class="tsd-parameters">
|
||||
<li class="tsd-parameter-signature">
|
||||
<ul class="tsd-signatures tsd-kind-type-literal tsd-parent-kind-type-literal">
|
||||
<li class="tsd-signature tsd-kind-icon"><span class="tsd-signature-symbol">(</span>particle<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">Particle</span><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">void</span></li>
|
||||
</ul>
|
||||
<ul class="tsd-descriptions">
|
||||
<li class="tsd-description">
|
||||
<div class="tsd-comment tsd-typography">
|
||||
<div class="lead">
|
||||
<p>Initiates a new particle execution starting from local peer</p>
|
||||
</div>
|
||||
</div>
|
||||
<h4 class="tsd-parameters-title">Parameters</h4>
|
||||
<ul class="tsd-parameters">
|
||||
<li>
|
||||
<h5>particle: <span class="tsd-signature-type">Particle</span></h5>
|
||||
<div class="tsd-comment tsd-typography">
|
||||
<p>particle to start execution of</p>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
<h4 class="tsd-returns-title">Returns <span class="tsd-signature-type">void</span></h4>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="tsd-parameter">
|
||||
<h5>reg<wbr>Handler<span class="tsd-signature-symbol">: </span><span class="tsd-signature-symbol">{ </span>common<span class="tsd-signature-symbol">: </span><span class="tsd-signature-symbol">(</span>serviceId<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">string</span>, fnName<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">string</span>, handler<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">GenericCallServiceHandler</span><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol"> => </span><span class="tsd-signature-type">void</span><span class="tsd-signature-symbol">; </span>forParticle<span class="tsd-signature-symbol">: </span><span class="tsd-signature-symbol">(</span>particleId<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">string</span>, serviceId<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">string</span>, fnName<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">string</span>, handler<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">GenericCallServiceHandler</span><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol"> => </span><span class="tsd-signature-type">void</span><span class="tsd-signature-symbol">; </span>timeout<span class="tsd-signature-symbol">: </span><span class="tsd-signature-symbol">(</span>particleId<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">string</span>, handler<span class="tsd-signature-symbol">: </span><span class="tsd-signature-symbol">(</span><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol"> => </span><span class="tsd-signature-type">void</span><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol"> => </span><span class="tsd-signature-type">void</span><span class="tsd-signature-symbol"> }</span></h5>
|
||||
<ul class="tsd-parameters">
|
||||
<li class="tsd-parameter">
|
||||
<h5>common<span class="tsd-signature-symbol">: </span><span class="tsd-signature-symbol">(</span>serviceId<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">string</span>, fnName<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">string</span>, handler<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">GenericCallServiceHandler</span><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol"> => </span><span class="tsd-signature-type">void</span></h5>
|
||||
<ul class="tsd-parameters">
|
||||
<li class="tsd-parameter-signature">
|
||||
<ul class="tsd-signatures tsd-kind-type-literal tsd-parent-kind-type-literal">
|
||||
<li class="tsd-signature tsd-kind-icon"><span class="tsd-signature-symbol">(</span>serviceId<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">string</span>, fnName<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">string</span>, handler<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">GenericCallServiceHandler</span><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">void</span></li>
|
||||
</ul>
|
||||
<ul class="tsd-descriptions">
|
||||
<li class="tsd-description">
|
||||
<div class="tsd-comment tsd-typography">
|
||||
<div class="lead">
|
||||
<p>Register handler for all particles</p>
|
||||
</div>
|
||||
</div>
|
||||
<h4 class="tsd-parameters-title">Parameters</h4>
|
||||
<ul class="tsd-parameters">
|
||||
<li>
|
||||
<h5>serviceId: <span class="tsd-signature-type">string</span></h5>
|
||||
</li>
|
||||
<li>
|
||||
<h5>fnName: <span class="tsd-signature-type">string</span></h5>
|
||||
</li>
|
||||
<li>
|
||||
<h5>handler: <span class="tsd-signature-type">GenericCallServiceHandler</span></h5>
|
||||
</li>
|
||||
</ul>
|
||||
<h4 class="tsd-returns-title">Returns <span class="tsd-signature-type">void</span></h4>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="tsd-parameter">
|
||||
<h5>for<wbr>Particle<span class="tsd-signature-symbol">: </span><span class="tsd-signature-symbol">(</span>particleId<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">string</span>, serviceId<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">string</span>, fnName<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">string</span>, handler<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">GenericCallServiceHandler</span><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol"> => </span><span class="tsd-signature-type">void</span></h5>
|
||||
<ul class="tsd-parameters">
|
||||
<li class="tsd-parameter-signature">
|
||||
<ul class="tsd-signatures tsd-kind-type-literal tsd-parent-kind-type-literal">
|
||||
<li class="tsd-signature tsd-kind-icon"><span class="tsd-signature-symbol">(</span>particleId<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">string</span>, serviceId<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">string</span>, fnName<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">string</span>, handler<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">GenericCallServiceHandler</span><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">void</span></li>
|
||||
</ul>
|
||||
<ul class="tsd-descriptions">
|
||||
<li class="tsd-description">
|
||||
<div class="tsd-comment tsd-typography">
|
||||
<div class="lead">
|
||||
<p>Register handler which will be called only for particle with the specific id</p>
|
||||
</div>
|
||||
</div>
|
||||
<h4 class="tsd-parameters-title">Parameters</h4>
|
||||
<ul class="tsd-parameters">
|
||||
<li>
|
||||
<h5>particleId: <span class="tsd-signature-type">string</span></h5>
|
||||
</li>
|
||||
<li>
|
||||
<h5>serviceId: <span class="tsd-signature-type">string</span></h5>
|
||||
</li>
|
||||
<li>
|
||||
<h5>fnName: <span class="tsd-signature-type">string</span></h5>
|
||||
</li>
|
||||
<li>
|
||||
<h5>handler: <span class="tsd-signature-type">GenericCallServiceHandler</span></h5>
|
||||
</li>
|
||||
</ul>
|
||||
<h4 class="tsd-returns-title">Returns <span class="tsd-signature-type">void</span></h4>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="tsd-parameter">
|
||||
<h5>timeout<span class="tsd-signature-symbol">: </span><span class="tsd-signature-symbol">(</span>particleId<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">string</span>, handler<span class="tsd-signature-symbol">: </span><span class="tsd-signature-symbol">(</span><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol"> => </span><span class="tsd-signature-type">void</span><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol"> => </span><span class="tsd-signature-type">void</span></h5>
|
||||
<ul class="tsd-parameters">
|
||||
<li class="tsd-parameter-signature">
|
||||
<ul class="tsd-signatures tsd-kind-type-literal tsd-parent-kind-type-literal">
|
||||
<li class="tsd-signature tsd-kind-icon"><span class="tsd-signature-symbol">(</span>particleId<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">string</span>, handler<span class="tsd-signature-symbol">: </span><span class="tsd-signature-symbol">(</span><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol"> => </span><span class="tsd-signature-type">void</span><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">void</span></li>
|
||||
</ul>
|
||||
<ul class="tsd-descriptions">
|
||||
<li class="tsd-description">
|
||||
<div class="tsd-comment tsd-typography">
|
||||
<div class="lead">
|
||||
<p>Register handler which will be called upon particle timeout</p>
|
||||
</div>
|
||||
</div>
|
||||
<h4 class="tsd-parameters-title">Parameters</h4>
|
||||
<ul class="tsd-parameters">
|
||||
<li>
|
||||
<h5>particleId: <span class="tsd-signature-type">string</span></h5>
|
||||
</li>
|
||||
<li>
|
||||
<h5>handler: <span class="tsd-signature-symbol">(</span><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol"> => </span><span class="tsd-signature-type">void</span></h5>
|
||||
<ul class="tsd-parameters">
|
||||
<li class="tsd-parameter-signature">
|
||||
<ul class="tsd-signatures tsd-kind-type-literal">
|
||||
<li class="tsd-signature tsd-kind-icon"><span class="tsd-signature-symbol">(</span><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">void</span></li>
|
||||
</ul>
|
||||
<ul class="tsd-descriptions">
|
||||
<li class="tsd-description">
|
||||
<h4 class="tsd-returns-title">Returns <span class="tsd-signature-type">void</span></h4>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
<h4 class="tsd-returns-title">Returns <span class="tsd-signature-type">void</span></h4>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
@ -197,7 +345,7 @@
|
||||
<li class="tsd-description">
|
||||
<aside class="tsd-sources">
|
||||
<ul>
|
||||
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/c0acd41/src/internal/FluencePeer.ts#L125">internal/FluencePeer.ts:125</a></li>
|
||||
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/9f81458/src/internal/FluencePeer.ts#L150">internal/FluencePeer.ts:150</a></li>
|
||||
</ul>
|
||||
</aside>
|
||||
<div class="tsd-comment tsd-typography">
|
||||
@ -219,7 +367,7 @@
|
||||
<li class="tsd-description">
|
||||
<aside class="tsd-sources">
|
||||
<ul>
|
||||
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/c0acd41/src/internal/FluencePeer.ts#L144">internal/FluencePeer.ts:144</a></li>
|
||||
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/9f81458/src/internal/FluencePeer.ts#L165">internal/FluencePeer.ts:165</a></li>
|
||||
</ul>
|
||||
</aside>
|
||||
<div class="tsd-comment tsd-typography">
|
||||
@ -251,12 +399,12 @@
|
||||
<li class="tsd-description">
|
||||
<aside class="tsd-sources">
|
||||
<ul>
|
||||
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/c0acd41/src/internal/FluencePeer.ts#L172">internal/FluencePeer.ts:172</a></li>
|
||||
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/9f81458/src/internal/FluencePeer.ts#L209">internal/FluencePeer.ts:209</a></li>
|
||||
</ul>
|
||||
</aside>
|
||||
<div class="tsd-comment tsd-typography">
|
||||
<div class="lead">
|
||||
<p>Uninitializes the peer: stops all the underltying workflows, stops the Aqua VM
|
||||
<p>Un-initializes the peer: stops all the underlying workflows, stops the Aqua VM
|
||||
and disconnects from the Fluence network</p>
|
||||
</div>
|
||||
</div>
|
||||
@ -274,7 +422,7 @@
|
||||
<li class="tsd-description">
|
||||
<aside class="tsd-sources">
|
||||
<ul>
|
||||
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/c0acd41/src/internal/FluencePeer.ts#L114">internal/FluencePeer.ts:114</a></li>
|
||||
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/9f81458/src/internal/FluencePeer.ts#L139">internal/FluencePeer.ts:139</a></li>
|
||||
</ul>
|
||||
</aside>
|
||||
<div class="tsd-comment tsd-typography">
|
||||
|
@ -112,7 +112,7 @@
|
||||
<li class="tsd-description">
|
||||
<aside class="tsd-sources">
|
||||
<ul>
|
||||
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/c0acd41/src/internal/KeyPair.ts#L27">internal/KeyPair.ts:27</a></li>
|
||||
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/9f81458/src/internal/KeyPair.ts#L26">internal/KeyPair.ts:26</a></li>
|
||||
</ul>
|
||||
</aside>
|
||||
<h4 class="tsd-parameters-title">Parameters</h4>
|
||||
@ -134,7 +134,7 @@
|
||||
<div class="tsd-signature tsd-kind-icon">Libp2p<wbr>Peer<wbr>Id<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">PeerId</span></div>
|
||||
<aside class="tsd-sources">
|
||||
<ul>
|
||||
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/c0acd41/src/internal/KeyPair.ts#L25">internal/KeyPair.ts:25</a></li>
|
||||
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/9f81458/src/internal/KeyPair.ts#L24">internal/KeyPair.ts:24</a></li>
|
||||
</ul>
|
||||
</aside>
|
||||
<div class="tsd-comment tsd-typography">
|
||||
@ -156,7 +156,7 @@
|
||||
<li class="tsd-description">
|
||||
<aside class="tsd-sources">
|
||||
<ul>
|
||||
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/c0acd41/src/internal/KeyPair.ts#L55">internal/KeyPair.ts:55</a></li>
|
||||
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/9f81458/src/internal/KeyPair.ts#L54">internal/KeyPair.ts:54</a></li>
|
||||
</ul>
|
||||
</aside>
|
||||
<h4 class="tsd-returns-title">Returns <span class="tsd-signature-type">Uint8Array</span></h4>
|
||||
@ -174,7 +174,7 @@
|
||||
<li class="tsd-description">
|
||||
<aside class="tsd-sources">
|
||||
<ul>
|
||||
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/c0acd41/src/internal/KeyPair.ts#L36">internal/KeyPair.ts:36</a></li>
|
||||
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/9f81458/src/internal/KeyPair.ts#L35">internal/KeyPair.ts:35</a></li>
|
||||
</ul>
|
||||
</aside>
|
||||
<div class="tsd-comment tsd-typography">
|
||||
@ -205,7 +205,7 @@
|
||||
<li class="tsd-description">
|
||||
<aside class="tsd-sources">
|
||||
<ul>
|
||||
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/c0acd41/src/internal/KeyPair.ts#L47">internal/KeyPair.ts:47</a></li>
|
||||
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/9f81458/src/internal/KeyPair.ts#L46">internal/KeyPair.ts:46</a></li>
|
||||
</ul>
|
||||
</aside>
|
||||
<div class="tsd-comment tsd-typography">
|
||||
|
@ -103,7 +103,7 @@
|
||||
<li class="tsd-kind-property tsd-parent-kind-interface"><a href="CallParams.html#particleId" class="tsd-kind-icon">particle<wbr>Id</a></li>
|
||||
<li class="tsd-kind-property tsd-parent-kind-interface"><a href="CallParams.html#signature" class="tsd-kind-icon">signature</a></li>
|
||||
<li class="tsd-kind-property tsd-parent-kind-interface"><a href="CallParams.html#tetraplets" class="tsd-kind-icon">tetraplets</a></li>
|
||||
<li class="tsd-kind-property tsd-parent-kind-interface"><a href="CallParams.html#timeStamp" class="tsd-kind-icon">time<wbr>Stamp</a></li>
|
||||
<li class="tsd-kind-property tsd-parent-kind-interface"><a href="CallParams.html#timestamp" class="tsd-kind-icon">timestamp</a></li>
|
||||
<li class="tsd-kind-property tsd-parent-kind-interface"><a href="CallParams.html#ttl" class="tsd-kind-icon">ttl</a></li>
|
||||
</ul>
|
||||
</section>
|
||||
@ -118,7 +118,7 @@
|
||||
<div class="tsd-signature tsd-kind-icon">init<wbr>Peer<wbr>Id<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span></div>
|
||||
<aside class="tsd-sources">
|
||||
<ul>
|
||||
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/c0acd41/src/internal/commonTypes.ts#L37">internal/commonTypes.ts:37</a></li>
|
||||
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/9f81458/src/internal/commonTypes.ts#L37">internal/commonTypes.ts:37</a></li>
|
||||
</ul>
|
||||
</aside>
|
||||
<div class="tsd-comment tsd-typography">
|
||||
@ -133,7 +133,7 @@
|
||||
<div class="tsd-signature tsd-kind-icon">particle<wbr>Id<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span></div>
|
||||
<aside class="tsd-sources">
|
||||
<ul>
|
||||
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/c0acd41/src/internal/commonTypes.ts#L32">internal/commonTypes.ts:32</a></li>
|
||||
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/9f81458/src/internal/commonTypes.ts#L32">internal/commonTypes.ts:32</a></li>
|
||||
</ul>
|
||||
</aside>
|
||||
<div class="tsd-comment tsd-typography">
|
||||
@ -148,7 +148,7 @@
|
||||
<div class="tsd-signature tsd-kind-icon">signature<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span></div>
|
||||
<aside class="tsd-sources">
|
||||
<ul>
|
||||
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/c0acd41/src/internal/commonTypes.ts#L52">internal/commonTypes.ts:52</a></li>
|
||||
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/9f81458/src/internal/commonTypes.ts#L52">internal/commonTypes.ts:52</a></li>
|
||||
</ul>
|
||||
</aside>
|
||||
<div class="tsd-comment tsd-typography">
|
||||
@ -163,7 +163,7 @@
|
||||
<div class="tsd-signature tsd-kind-icon">tetraplets<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-symbol">{</span><span class="tsd-signature-symbol">[ </span><span class="tsd-signature-type">key</span><span class="tsd-signature-symbol"> in </span><span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">]</span><span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">SecurityTetraplet</span><span class="tsd-signature-symbol">[]</span><span class="tsd-signature-symbol"> }</span></div>
|
||||
<aside class="tsd-sources">
|
||||
<ul>
|
||||
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/c0acd41/src/internal/commonTypes.ts#L57">internal/commonTypes.ts:57</a></li>
|
||||
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/9f81458/src/internal/commonTypes.ts#L57">internal/commonTypes.ts:57</a></li>
|
||||
</ul>
|
||||
</aside>
|
||||
<div class="tsd-comment tsd-typography">
|
||||
@ -173,12 +173,12 @@
|
||||
</div>
|
||||
</section>
|
||||
<section class="tsd-panel tsd-member tsd-kind-property tsd-parent-kind-interface">
|
||||
<a name="timeStamp" class="tsd-anchor"></a>
|
||||
<h3>time<wbr>Stamp</h3>
|
||||
<div class="tsd-signature tsd-kind-icon">time<wbr>Stamp<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">number</span></div>
|
||||
<a name="timestamp" class="tsd-anchor"></a>
|
||||
<h3>timestamp</h3>
|
||||
<div class="tsd-signature tsd-kind-icon">timestamp<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">number</span></div>
|
||||
<aside class="tsd-sources">
|
||||
<ul>
|
||||
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/c0acd41/src/internal/commonTypes.ts#L42">internal/commonTypes.ts:42</a></li>
|
||||
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/9f81458/src/internal/commonTypes.ts#L42">internal/commonTypes.ts:42</a></li>
|
||||
</ul>
|
||||
</aside>
|
||||
<div class="tsd-comment tsd-typography">
|
||||
@ -193,7 +193,7 @@
|
||||
<div class="tsd-signature tsd-kind-icon">ttl<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">number</span></div>
|
||||
<aside class="tsd-sources">
|
||||
<ul>
|
||||
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/c0acd41/src/internal/commonTypes.ts#L47">internal/commonTypes.ts:47</a></li>
|
||||
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/9f81458/src/internal/commonTypes.ts#L47">internal/commonTypes.ts:47</a></li>
|
||||
</ul>
|
||||
</aside>
|
||||
<div class="tsd-comment tsd-typography">
|
||||
@ -238,7 +238,7 @@
|
||||
<a href="CallParams.html#tetraplets" class="tsd-kind-icon">tetraplets</a>
|
||||
</li>
|
||||
<li class=" tsd-kind-property tsd-parent-kind-interface">
|
||||
<a href="CallParams.html#timeStamp" class="tsd-kind-icon">time<wbr>Stamp</a>
|
||||
<a href="CallParams.html#timestamp" class="tsd-kind-icon">timestamp</a>
|
||||
</li>
|
||||
<li class=" tsd-kind-property tsd-parent-kind-interface">
|
||||
<a href="CallParams.html#ttl" class="tsd-kind-icon">ttl</a>
|
||||
|
@ -104,7 +104,7 @@
|
||||
<div class="tsd-signature tsd-kind-icon">is<wbr>Connected<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">Boolean</span></div>
|
||||
<aside class="tsd-sources">
|
||||
<ul>
|
||||
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/c0acd41/src/internal/FluencePeer.ts#L86">internal/FluencePeer.ts:86</a></li>
|
||||
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/9f81458/src/internal/FluencePeer.ts#L111">internal/FluencePeer.ts:111</a></li>
|
||||
</ul>
|
||||
</aside>
|
||||
<div class="tsd-comment tsd-typography">
|
||||
@ -119,7 +119,7 @@
|
||||
<div class="tsd-signature tsd-kind-icon">is<wbr>Initialized<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">Boolean</span></div>
|
||||
<aside class="tsd-sources">
|
||||
<ul>
|
||||
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/c0acd41/src/internal/FluencePeer.ts#L81">internal/FluencePeer.ts:81</a></li>
|
||||
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/9f81458/src/internal/FluencePeer.ts#L106">internal/FluencePeer.ts:106</a></li>
|
||||
</ul>
|
||||
</aside>
|
||||
<div class="tsd-comment tsd-typography">
|
||||
@ -134,7 +134,7 @@
|
||||
<div class="tsd-signature tsd-kind-icon">peer<wbr>Id<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span></div>
|
||||
<aside class="tsd-sources">
|
||||
<ul>
|
||||
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/c0acd41/src/internal/FluencePeer.ts#L91">internal/FluencePeer.ts:91</a></li>
|
||||
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/9f81458/src/internal/FluencePeer.ts#L116">internal/FluencePeer.ts:116</a></li>
|
||||
</ul>
|
||||
</aside>
|
||||
<div class="tsd-comment tsd-typography">
|
||||
@ -149,7 +149,7 @@
|
||||
<div class="tsd-signature tsd-kind-icon">relay<wbr>Peer<wbr>Id<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span></div>
|
||||
<aside class="tsd-sources">
|
||||
<ul>
|
||||
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/c0acd41/src/internal/FluencePeer.ts#L96">internal/FluencePeer.ts:96</a></li>
|
||||
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/9f81458/src/internal/FluencePeer.ts#L121">internal/FluencePeer.ts:121</a></li>
|
||||
</ul>
|
||||
</aside>
|
||||
<div class="tsd-comment tsd-typography">
|
||||
|
@ -105,7 +105,7 @@
|
||||
<div class="tsd-signature tsd-kind-icon">Avm<wbr>Loglevel<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">LogLevel</span></div>
|
||||
<aside class="tsd-sources">
|
||||
<ul>
|
||||
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/c0acd41/src/internal/FluencePeer.ts#L27">internal/FluencePeer.ts:27</a></li>
|
||||
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/9f81458/src/internal/FluencePeer.ts#L50">internal/FluencePeer.ts:50</a></li>
|
||||
</ul>
|
||||
</aside>
|
||||
<div class="tsd-comment tsd-typography">
|
||||
@ -121,7 +121,7 @@
|
||||
<div class="tsd-signature tsd-kind-icon">Peer<wbr>IdB58<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span></div>
|
||||
<aside class="tsd-sources">
|
||||
<ul>
|
||||
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/c0acd41/src/internal/commonTypes.ts#L22">internal/commonTypes.ts:22</a></li>
|
||||
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/9f81458/src/internal/commonTypes.ts#L22">internal/commonTypes.ts:22</a></li>
|
||||
</ul>
|
||||
</aside>
|
||||
<div class="tsd-comment tsd-typography">
|
||||
@ -139,7 +139,7 @@
|
||||
<div class="tsd-signature tsd-kind-icon">Fluence<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-symbol">{ </span>getPeer<span class="tsd-signature-symbol">: </span><span class="tsd-signature-symbol">(</span><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol"> => </span><a href="classes/FluencePeer.html" class="tsd-signature-type" data-tsd-kind="Class">FluencePeer</a><span class="tsd-signature-symbol">; </span>getStatus<span class="tsd-signature-symbol">: </span><span class="tsd-signature-symbol">(</span><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol"> => </span><a href="interfaces/PeerStatus.html" class="tsd-signature-type" data-tsd-kind="Interface">PeerStatus</a><span class="tsd-signature-symbol">; </span>start<span class="tsd-signature-symbol">: </span><span class="tsd-signature-symbol">(</span>config<span class="tsd-signature-symbol">?: </span><span class="tsd-signature-type">PeerConfig</span><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol"> => </span><span class="tsd-signature-type">Promise</span><span class="tsd-signature-symbol"><</span><span class="tsd-signature-type">void</span><span class="tsd-signature-symbol">></span><span class="tsd-signature-symbol">; </span>stop<span class="tsd-signature-symbol">: </span><span class="tsd-signature-symbol">(</span><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol"> => </span><span class="tsd-signature-type">Promise</span><span class="tsd-signature-symbol"><</span><span class="tsd-signature-type">void</span><span class="tsd-signature-symbol">></span><span class="tsd-signature-symbol"> }</span><span class="tsd-signature-symbol"> = ...</span></div>
|
||||
<aside class="tsd-sources">
|
||||
<ul>
|
||||
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/c0acd41/src/index.ts#L36">index.ts:36</a></li>
|
||||
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/9f81458/src/index.ts#L36">index.ts:36</a></li>
|
||||
</ul>
|
||||
</aside>
|
||||
<div class="tsd-comment tsd-typography">
|
||||
@ -259,7 +259,7 @@
|
||||
<li class="tsd-description">
|
||||
<aside class="tsd-sources">
|
||||
<ul>
|
||||
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/c0acd41/src/index.ts#L25">index.ts:25</a></li>
|
||||
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/9f81458/src/index.ts#L25">index.ts:25</a></li>
|
||||
</ul>
|
||||
</aside>
|
||||
<h4 class="tsd-parameters-title">Parameters</h4>
|
||||
|
352
package-lock.json
generated
352
package-lock.json
generated
@ -10,7 +10,7 @@
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@chainsafe/libp2p-noise": "4.0.0",
|
||||
"@fluencelabs/avm": "0.14.4",
|
||||
"@fluencelabs/avm": "0.15.4",
|
||||
"async": "3.2.0",
|
||||
"base64-js": "1.5.1",
|
||||
"bs58": "4.0.1",
|
||||
@ -24,6 +24,8 @@
|
||||
"loglevel": "1.7.0",
|
||||
"multiaddr": "10.0.0",
|
||||
"peer-id": "0.15.3",
|
||||
"rxjs": "^7.3.0",
|
||||
"ts-pattern": "^3.3.3",
|
||||
"uuid": "8.3.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
@ -617,16 +619,6 @@
|
||||
"uint8arrays": "^2.0.5"
|
||||
}
|
||||
},
|
||||
"node_modules/@chainsafe/libp2p-noise/node_modules/bl": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/bl/-/bl-5.0.0.tgz",
|
||||
"integrity": "sha512-8vxFNZ0pflFfi0WXA3WQXlj6CaMEwsmh63I1CNp0q+wWv8sD0ARx1KovSQd0l2GkwrMIOyedq0EF1FxI+RCZLQ==",
|
||||
"dependencies": {
|
||||
"buffer": "^6.0.3",
|
||||
"inherits": "^2.0.4",
|
||||
"readable-stream": "^3.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@chainsafe/libp2p-noise/node_modules/it-length-prefixed": {
|
||||
"version": "5.0.3",
|
||||
"resolved": "https://registry.npmjs.org/it-length-prefixed/-/it-length-prefixed-5.0.3.tgz",
|
||||
@ -654,9 +646,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@fluencelabs/avm": {
|
||||
"version": "0.14.4",
|
||||
"resolved": "https://registry.npmjs.org/@fluencelabs/avm/-/avm-0.14.4.tgz",
|
||||
"integrity": "sha512-XyR+1H5k0CAc+mDHOkl81viX8XeW1Yqbw793xbsfUfju5bUb/hqk+gHv3q8lAFdbrCG5P45gdOT08a5RNODZaQ==",
|
||||
"version": "0.15.4",
|
||||
"resolved": "https://registry.npmjs.org/@fluencelabs/avm/-/avm-0.15.4.tgz",
|
||||
"integrity": "sha512-NLZDq83ocJ1Helm0D8kPMSSkjxH0y+Tujg0px773zjIShbh3jgiJOjAW1xCYgTt9K0LqepjP0bWX4/8nUZfr7g==",
|
||||
"dependencies": {
|
||||
"base64-js": "1.5.1"
|
||||
}
|
||||
@ -1796,6 +1788,16 @@
|
||||
"file-uri-to-path": "1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/bl": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/bl/-/bl-5.0.0.tgz",
|
||||
"integrity": "sha512-8vxFNZ0pflFfi0WXA3WQXlj6CaMEwsmh63I1CNp0q+wWv8sD0ARx1KovSQd0l2GkwrMIOyedq0EF1FxI+RCZLQ==",
|
||||
"dependencies": {
|
||||
"buffer": "^6.0.3",
|
||||
"inherits": "^2.0.4",
|
||||
"readable-stream": "^3.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/bn.js": {
|
||||
"version": "4.12.0",
|
||||
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz",
|
||||
@ -1834,14 +1836,14 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/browserslist": {
|
||||
"version": "4.17.0",
|
||||
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.17.0.tgz",
|
||||
"integrity": "sha512-g2BJ2a0nEYvEFQC208q8mVAhfNwpZ5Mu8BwgtCdZKO3qx98HChmeg448fPdUzld8aFmfLgVh7yymqV+q1lJZ5g==",
|
||||
"version": "4.16.8",
|
||||
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.8.tgz",
|
||||
"integrity": "sha512-sc2m9ohR/49sWEbPj14ZSSZqp+kbi16aLao42Hmn3Z8FpjuMaq2xCA2l4zl9ITfyzvnvyE0hcg62YkIGKxgaNQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"caniuse-lite": "^1.0.30001254",
|
||||
"caniuse-lite": "^1.0.30001251",
|
||||
"colorette": "^1.3.0",
|
||||
"electron-to-chromium": "^1.3.830",
|
||||
"electron-to-chromium": "^1.3.811",
|
||||
"escalade": "^3.1.1",
|
||||
"node-releases": "^1.1.75"
|
||||
},
|
||||
@ -1953,9 +1955,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/caniuse-lite": {
|
||||
"version": "1.0.30001255",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001255.tgz",
|
||||
"integrity": "sha512-F+A3N9jTZL882f/fg/WWVnKSu6IOo3ueLz4zwaOPbPYHNmM/ZaDUyzyJwS1mZhX7Ex5jqTyW599Gdelh5PDYLQ==",
|
||||
"version": "1.0.30001252",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001252.tgz",
|
||||
"integrity": "sha512-I56jhWDGMtdILQORdusxBOH+Nl/KgQSdDmpJezYddnAkVOmnoU8zwjTV9xAjMIYxr0iPreEAVylCGcmHCjfaOw==",
|
||||
"dev": true,
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
@ -2155,9 +2157,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/colorette": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/colorette/-/colorette-1.4.0.tgz",
|
||||
"integrity": "sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g==",
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/colorette/-/colorette-1.3.0.tgz",
|
||||
"integrity": "sha512-ecORCqbSFP7Wm8Y6lyqMJjexBQqXSF7SSeaTyGGphogUjBlFP9m9o08wy86HL2uB7fMTxtOUzLMk7ogKcxMg1w==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/combined-stream": {
|
||||
@ -2468,9 +2470,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/electron-to-chromium": {
|
||||
"version": "1.3.832",
|
||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.832.tgz",
|
||||
"integrity": "sha512-x7lO8tGoW0CyV53qON4Lb5Rok9ipDelNdBIAiYUZ03dqy4u9vohMM1qV047+s/hiyJiqUWX/3PNwkX3kexX5ig==",
|
||||
"version": "1.3.822",
|
||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.822.tgz",
|
||||
"integrity": "sha512-k7jG5oYYHxF4jx6PcqwHX3JVME/OjzolqOZiIogi9xtsfsmTjTdie4x88OakYFPEa8euciTgCCzvVNwvmjHb1Q==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/elliptic": {
|
||||
@ -3477,54 +3479,6 @@
|
||||
"stream-to-it": "^0.2.2"
|
||||
}
|
||||
},
|
||||
"node_modules/ipfs-utils/node_modules/buffer": {
|
||||
"version": "6.0.3",
|
||||
"resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz",
|
||||
"integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/feross"
|
||||
},
|
||||
{
|
||||
"type": "patreon",
|
||||
"url": "https://www.patreon.com/feross"
|
||||
},
|
||||
{
|
||||
"type": "consulting",
|
||||
"url": "https://feross.org/support"
|
||||
}
|
||||
],
|
||||
"dependencies": {
|
||||
"base64-js": "^1.3.1",
|
||||
"ieee754": "^1.2.1"
|
||||
}
|
||||
},
|
||||
"node_modules/ipfs-utils/node_modules/ieee754": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
|
||||
"integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/feross"
|
||||
},
|
||||
{
|
||||
"type": "patreon",
|
||||
"url": "https://www.patreon.com/feross"
|
||||
},
|
||||
{
|
||||
"type": "consulting",
|
||||
"url": "https://feross.org/support"
|
||||
}
|
||||
]
|
||||
},
|
||||
"node_modules/ipfs-utils/node_modules/node-fetch": {
|
||||
"name": "@achingbrain/node-fetch",
|
||||
"version": "2.6.7",
|
||||
"resolved": "https://registry.npmjs.org/@achingbrain/node-fetch/-/node-fetch-2.6.7.tgz",
|
||||
"integrity": "sha512-iTASGs+HTFK5E4ZqcMsHmeJ4zodyq8L38lZV33jwqcBJYoUt3HjN4+ot+O9/0b+ke8ddE7UgOtVuZN/OkV19/g=="
|
||||
},
|
||||
"node_modules/is-accessor-descriptor": {
|
||||
"version": "0.1.6",
|
||||
"resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz",
|
||||
@ -3921,16 +3875,6 @@
|
||||
"buffer": "^6.0.3"
|
||||
}
|
||||
},
|
||||
"node_modules/it-buffer/node_modules/bl": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/bl/-/bl-5.0.0.tgz",
|
||||
"integrity": "sha512-8vxFNZ0pflFfi0WXA3WQXlj6CaMEwsmh63I1CNp0q+wWv8sD0ARx1KovSQd0l2GkwrMIOyedq0EF1FxI+RCZLQ==",
|
||||
"dependencies": {
|
||||
"buffer": "^6.0.3",
|
||||
"inherits": "^2.0.4",
|
||||
"readable-stream": "^3.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/it-drain": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/it-drain/-/it-drain-1.0.4.tgz",
|
||||
@ -4085,16 +4029,6 @@
|
||||
"bl": "^5.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/it-reader/node_modules/bl": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/bl/-/bl-5.0.0.tgz",
|
||||
"integrity": "sha512-8vxFNZ0pflFfi0WXA3WQXlj6CaMEwsmh63I1CNp0q+wWv8sD0ARx1KovSQd0l2GkwrMIOyedq0EF1FxI+RCZLQ==",
|
||||
"dependencies": {
|
||||
"buffer": "^6.0.3",
|
||||
"inherits": "^2.0.4",
|
||||
"readable-stream": "^3.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/it-take": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/it-take/-/it-take-1.0.1.tgz",
|
||||
@ -5048,16 +4982,6 @@
|
||||
"uint8arrays": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/libp2p-interfaces/node_modules/bl": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/bl/-/bl-5.0.0.tgz",
|
||||
"integrity": "sha512-8vxFNZ0pflFfi0WXA3WQXlj6CaMEwsmh63I1CNp0q+wWv8sD0ARx1KovSQd0l2GkwrMIOyedq0EF1FxI+RCZLQ==",
|
||||
"dependencies": {
|
||||
"buffer": "^6.0.3",
|
||||
"inherits": "^2.0.4",
|
||||
"readable-stream": "^3.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/libp2p-interfaces/node_modules/it-length-prefixed": {
|
||||
"version": "5.0.3",
|
||||
"resolved": "https://registry.npmjs.org/it-length-prefixed/-/it-length-prefixed-5.0.3.tgz",
|
||||
@ -5091,16 +5015,6 @@
|
||||
"varint": "^6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/libp2p-mplex/node_modules/bl": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/bl/-/bl-5.0.0.tgz",
|
||||
"integrity": "sha512-8vxFNZ0pflFfi0WXA3WQXlj6CaMEwsmh63I1CNp0q+wWv8sD0ARx1KovSQd0l2GkwrMIOyedq0EF1FxI+RCZLQ==",
|
||||
"dependencies": {
|
||||
"buffer": "^6.0.3",
|
||||
"inherits": "^2.0.4",
|
||||
"readable-stream": "^3.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/libp2p-utils": {
|
||||
"version": "0.4.1",
|
||||
"resolved": "https://registry.npmjs.org/libp2p-utils/-/libp2p-utils-0.4.1.tgz",
|
||||
@ -5134,16 +5048,6 @@
|
||||
"p-timeout": "^4.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/libp2p/node_modules/bl": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/bl/-/bl-5.0.0.tgz",
|
||||
"integrity": "sha512-8vxFNZ0pflFfi0WXA3WQXlj6CaMEwsmh63I1CNp0q+wWv8sD0ARx1KovSQd0l2GkwrMIOyedq0EF1FxI+RCZLQ==",
|
||||
"dependencies": {
|
||||
"buffer": "^6.0.3",
|
||||
"inherits": "^2.0.4",
|
||||
"readable-stream": "^3.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/libp2p/node_modules/it-length-prefixed": {
|
||||
"version": "5.0.3",
|
||||
"resolved": "https://registry.npmjs.org/it-length-prefixed/-/it-length-prefixed-5.0.3.tgz",
|
||||
@ -5560,16 +5464,6 @@
|
||||
"uint8arrays": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/multistream-select/node_modules/bl": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/bl/-/bl-5.0.0.tgz",
|
||||
"integrity": "sha512-8vxFNZ0pflFfi0WXA3WQXlj6CaMEwsmh63I1CNp0q+wWv8sD0ARx1KovSQd0l2GkwrMIOyedq0EF1FxI+RCZLQ==",
|
||||
"dependencies": {
|
||||
"buffer": "^6.0.3",
|
||||
"inherits": "^2.0.4",
|
||||
"readable-stream": "^3.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/multistream-select/node_modules/it-length-prefixed": {
|
||||
"version": "5.0.3",
|
||||
"resolved": "https://registry.npmjs.org/it-length-prefixed/-/it-length-prefixed-5.0.3.tgz",
|
||||
@ -5682,6 +5576,12 @@
|
||||
"resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-2.0.2.tgz",
|
||||
"integrity": "sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA=="
|
||||
},
|
||||
"node_modules/node-fetch": {
|
||||
"name": "@achingbrain/node-fetch",
|
||||
"version": "2.6.7",
|
||||
"resolved": "https://registry.npmjs.org/@achingbrain/node-fetch/-/node-fetch-2.6.7.tgz",
|
||||
"integrity": "sha512-iTASGs+HTFK5E4ZqcMsHmeJ4zodyq8L38lZV33jwqcBJYoUt3HjN4+ot+O9/0b+ke8ddE7UgOtVuZN/OkV19/g=="
|
||||
},
|
||||
"node_modules/node-forge": {
|
||||
"version": "0.10.0",
|
||||
"resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.10.0.tgz",
|
||||
@ -6614,6 +6514,14 @@
|
||||
"node": "6.* || >= 7.*"
|
||||
}
|
||||
},
|
||||
"node_modules/rxjs": {
|
||||
"version": "7.3.0",
|
||||
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.3.0.tgz",
|
||||
"integrity": "sha512-p2yuGIg9S1epc3vrjKf6iVb3RCaAYjYskkO+jHIaV0IjOPlJop4UnodOoFb2xeNwlguqLYvGw1b1McillYb5Gw==",
|
||||
"dependencies": {
|
||||
"tslib": "~2.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/safe-buffer": {
|
||||
"version": "5.2.1",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
|
||||
@ -7725,6 +7633,16 @@
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/ts-pattern": {
|
||||
"version": "3.3.3",
|
||||
"resolved": "https://registry.npmjs.org/ts-pattern/-/ts-pattern-3.3.3.tgz",
|
||||
"integrity": "sha512-Z5EFi6g6wyX3uDFHqxF5W5c5h663oZg9O6aOiAT7fqNu0HPSfCxtHzrQ7SblTy738Mrg2Ezorky8H5aUOm8Pvg=="
|
||||
},
|
||||
"node_modules/tslib": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.1.0.tgz",
|
||||
"integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A=="
|
||||
},
|
||||
"node_modules/tunnel-agent": {
|
||||
"version": "0.6.0",
|
||||
"resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
|
||||
@ -8748,16 +8666,6 @@
|
||||
"uint8arrays": "^2.0.5"
|
||||
},
|
||||
"dependencies": {
|
||||
"bl": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/bl/-/bl-5.0.0.tgz",
|
||||
"integrity": "sha512-8vxFNZ0pflFfi0WXA3WQXlj6CaMEwsmh63I1CNp0q+wWv8sD0ARx1KovSQd0l2GkwrMIOyedq0EF1FxI+RCZLQ==",
|
||||
"requires": {
|
||||
"buffer": "^6.0.3",
|
||||
"inherits": "^2.0.4",
|
||||
"readable-stream": "^3.4.0"
|
||||
}
|
||||
},
|
||||
"it-length-prefixed": {
|
||||
"version": "5.0.3",
|
||||
"resolved": "https://registry.npmjs.org/it-length-prefixed/-/it-length-prefixed-5.0.3.tgz",
|
||||
@ -8781,9 +8689,9 @@
|
||||
}
|
||||
},
|
||||
"@fluencelabs/avm": {
|
||||
"version": "0.14.4",
|
||||
"resolved": "https://registry.npmjs.org/@fluencelabs/avm/-/avm-0.14.4.tgz",
|
||||
"integrity": "sha512-XyR+1H5k0CAc+mDHOkl81viX8XeW1Yqbw793xbsfUfju5bUb/hqk+gHv3q8lAFdbrCG5P45gdOT08a5RNODZaQ==",
|
||||
"version": "0.15.4",
|
||||
"resolved": "https://registry.npmjs.org/@fluencelabs/avm/-/avm-0.15.4.tgz",
|
||||
"integrity": "sha512-NLZDq83ocJ1Helm0D8kPMSSkjxH0y+Tujg0px773zjIShbh3jgiJOjAW1xCYgTt9K0LqepjP0bWX4/8nUZfr7g==",
|
||||
"requires": {
|
||||
"base64-js": "1.5.1"
|
||||
}
|
||||
@ -9752,6 +9660,16 @@
|
||||
"file-uri-to-path": "1.0.0"
|
||||
}
|
||||
},
|
||||
"bl": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/bl/-/bl-5.0.0.tgz",
|
||||
"integrity": "sha512-8vxFNZ0pflFfi0WXA3WQXlj6CaMEwsmh63I1CNp0q+wWv8sD0ARx1KovSQd0l2GkwrMIOyedq0EF1FxI+RCZLQ==",
|
||||
"requires": {
|
||||
"buffer": "^6.0.3",
|
||||
"inherits": "^2.0.4",
|
||||
"readable-stream": "^3.4.0"
|
||||
}
|
||||
},
|
||||
"bn.js": {
|
||||
"version": "4.12.0",
|
||||
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz",
|
||||
@ -9787,14 +9705,14 @@
|
||||
"dev": true
|
||||
},
|
||||
"browserslist": {
|
||||
"version": "4.17.0",
|
||||
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.17.0.tgz",
|
||||
"integrity": "sha512-g2BJ2a0nEYvEFQC208q8mVAhfNwpZ5Mu8BwgtCdZKO3qx98HChmeg448fPdUzld8aFmfLgVh7yymqV+q1lJZ5g==",
|
||||
"version": "4.16.8",
|
||||
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.8.tgz",
|
||||
"integrity": "sha512-sc2m9ohR/49sWEbPj14ZSSZqp+kbi16aLao42Hmn3Z8FpjuMaq2xCA2l4zl9ITfyzvnvyE0hcg62YkIGKxgaNQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"caniuse-lite": "^1.0.30001254",
|
||||
"caniuse-lite": "^1.0.30001251",
|
||||
"colorette": "^1.3.0",
|
||||
"electron-to-chromium": "^1.3.830",
|
||||
"electron-to-chromium": "^1.3.811",
|
||||
"escalade": "^3.1.1",
|
||||
"node-releases": "^1.1.75"
|
||||
}
|
||||
@ -9870,9 +9788,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"caniuse-lite": {
|
||||
"version": "1.0.30001255",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001255.tgz",
|
||||
"integrity": "sha512-F+A3N9jTZL882f/fg/WWVnKSu6IOo3ueLz4zwaOPbPYHNmM/ZaDUyzyJwS1mZhX7Ex5jqTyW599Gdelh5PDYLQ==",
|
||||
"version": "1.0.30001252",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001252.tgz",
|
||||
"integrity": "sha512-I56jhWDGMtdILQORdusxBOH+Nl/KgQSdDmpJezYddnAkVOmnoU8zwjTV9xAjMIYxr0iPreEAVylCGcmHCjfaOw==",
|
||||
"dev": true
|
||||
},
|
||||
"capture-exit": {
|
||||
@ -10022,9 +9940,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"colorette": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/colorette/-/colorette-1.4.0.tgz",
|
||||
"integrity": "sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g==",
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/colorette/-/colorette-1.3.0.tgz",
|
||||
"integrity": "sha512-ecORCqbSFP7Wm8Y6lyqMJjexBQqXSF7SSeaTyGGphogUjBlFP9m9o08wy86HL2uB7fMTxtOUzLMk7ogKcxMg1w==",
|
||||
"dev": true
|
||||
},
|
||||
"combined-stream": {
|
||||
@ -10275,9 +10193,9 @@
|
||||
}
|
||||
},
|
||||
"electron-to-chromium": {
|
||||
"version": "1.3.832",
|
||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.832.tgz",
|
||||
"integrity": "sha512-x7lO8tGoW0CyV53qON4Lb5Rok9ipDelNdBIAiYUZ03dqy4u9vohMM1qV047+s/hiyJiqUWX/3PNwkX3kexX5ig==",
|
||||
"version": "1.3.822",
|
||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.822.tgz",
|
||||
"integrity": "sha512-k7jG5oYYHxF4jx6PcqwHX3JVME/OjzolqOZiIogi9xtsfsmTjTdie4x88OakYFPEa8euciTgCCzvVNwvmjHb1Q==",
|
||||
"dev": true
|
||||
},
|
||||
"elliptic": {
|
||||
@ -11069,26 +10987,6 @@
|
||||
"node-fetch": "https://registry.npmjs.org/@achingbrain/node-fetch/-/node-fetch-2.6.7.tgz",
|
||||
"react-native-fetch-api": "^2.0.0",
|
||||
"stream-to-it": "^0.2.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"buffer": {
|
||||
"version": "6.0.3",
|
||||
"resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz",
|
||||
"integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==",
|
||||
"requires": {
|
||||
"base64-js": "^1.3.1",
|
||||
"ieee754": "^1.2.1"
|
||||
}
|
||||
},
|
||||
"ieee754": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
|
||||
"integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="
|
||||
},
|
||||
"node-fetch": {
|
||||
"version": "https://registry.npmjs.org/@achingbrain/node-fetch/-/node-fetch-2.6.7.tgz",
|
||||
"integrity": "sha512-iTASGs+HTFK5E4ZqcMsHmeJ4zodyq8L38lZV33jwqcBJYoUt3HjN4+ot+O9/0b+ke8ddE7UgOtVuZN/OkV19/g=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"is-accessor-descriptor": {
|
||||
@ -11384,18 +11282,6 @@
|
||||
"requires": {
|
||||
"bl": "^5.0.0",
|
||||
"buffer": "^6.0.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"bl": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/bl/-/bl-5.0.0.tgz",
|
||||
"integrity": "sha512-8vxFNZ0pflFfi0WXA3WQXlj6CaMEwsmh63I1CNp0q+wWv8sD0ARx1KovSQd0l2GkwrMIOyedq0EF1FxI+RCZLQ==",
|
||||
"requires": {
|
||||
"buffer": "^6.0.3",
|
||||
"inherits": "^2.0.4",
|
||||
"readable-stream": "^3.4.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"it-drain": {
|
||||
@ -11540,18 +11426,6 @@
|
||||
"integrity": "sha512-NxR40odATeaBmSefn6Xn43DplYvn2KtEKQzn4jrTRuPYXMky5M4e+KQ7aTJh0k0vkytLyeenGO1I1GXlGm4laQ==",
|
||||
"requires": {
|
||||
"bl": "^5.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"bl": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/bl/-/bl-5.0.0.tgz",
|
||||
"integrity": "sha512-8vxFNZ0pflFfi0WXA3WQXlj6CaMEwsmh63I1CNp0q+wWv8sD0ARx1KovSQd0l2GkwrMIOyedq0EF1FxI+RCZLQ==",
|
||||
"requires": {
|
||||
"buffer": "^6.0.3",
|
||||
"inherits": "^2.0.4",
|
||||
"readable-stream": "^3.4.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"it-take": {
|
||||
@ -12281,16 +12155,6 @@
|
||||
"xsalsa20": "^1.1.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"bl": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/bl/-/bl-5.0.0.tgz",
|
||||
"integrity": "sha512-8vxFNZ0pflFfi0WXA3WQXlj6CaMEwsmh63I1CNp0q+wWv8sD0ARx1KovSQd0l2GkwrMIOyedq0EF1FxI+RCZLQ==",
|
||||
"requires": {
|
||||
"buffer": "^6.0.3",
|
||||
"inherits": "^2.0.4",
|
||||
"readable-stream": "^3.4.0"
|
||||
}
|
||||
},
|
||||
"it-length-prefixed": {
|
||||
"version": "5.0.3",
|
||||
"resolved": "https://registry.npmjs.org/it-length-prefixed/-/it-length-prefixed-5.0.3.tgz",
|
||||
@ -12351,16 +12215,6 @@
|
||||
"uint8arrays": "^3.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"bl": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/bl/-/bl-5.0.0.tgz",
|
||||
"integrity": "sha512-8vxFNZ0pflFfi0WXA3WQXlj6CaMEwsmh63I1CNp0q+wWv8sD0ARx1KovSQd0l2GkwrMIOyedq0EF1FxI+RCZLQ==",
|
||||
"requires": {
|
||||
"buffer": "^6.0.3",
|
||||
"inherits": "^2.0.4",
|
||||
"readable-stream": "^3.4.0"
|
||||
}
|
||||
},
|
||||
"it-length-prefixed": {
|
||||
"version": "5.0.3",
|
||||
"resolved": "https://registry.npmjs.org/it-length-prefixed/-/it-length-prefixed-5.0.3.tgz",
|
||||
@ -12394,18 +12248,6 @@
|
||||
"it-pipe": "^1.1.0",
|
||||
"it-pushable": "^1.4.1",
|
||||
"varint": "^6.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"bl": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/bl/-/bl-5.0.0.tgz",
|
||||
"integrity": "sha512-8vxFNZ0pflFfi0WXA3WQXlj6CaMEwsmh63I1CNp0q+wWv8sD0ARx1KovSQd0l2GkwrMIOyedq0EF1FxI+RCZLQ==",
|
||||
"requires": {
|
||||
"buffer": "^6.0.3",
|
||||
"inherits": "^2.0.4",
|
||||
"readable-stream": "^3.4.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"libp2p-utils": {
|
||||
@ -12750,16 +12592,6 @@
|
||||
"uint8arrays": "^3.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"bl": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/bl/-/bl-5.0.0.tgz",
|
||||
"integrity": "sha512-8vxFNZ0pflFfi0WXA3WQXlj6CaMEwsmh63I1CNp0q+wWv8sD0ARx1KovSQd0l2GkwrMIOyedq0EF1FxI+RCZLQ==",
|
||||
"requires": {
|
||||
"buffer": "^6.0.3",
|
||||
"inherits": "^2.0.4",
|
||||
"readable-stream": "^3.4.0"
|
||||
}
|
||||
},
|
||||
"it-length-prefixed": {
|
||||
"version": "5.0.3",
|
||||
"resolved": "https://registry.npmjs.org/it-length-prefixed/-/it-length-prefixed-5.0.3.tgz",
|
||||
@ -12854,6 +12686,10 @@
|
||||
"resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-2.0.2.tgz",
|
||||
"integrity": "sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA=="
|
||||
},
|
||||
"node-fetch": {
|
||||
"version": "https://registry.npmjs.org/@achingbrain/node-fetch/-/node-fetch-2.6.7.tgz",
|
||||
"integrity": "sha512-iTASGs+HTFK5E4ZqcMsHmeJ4zodyq8L38lZV33jwqcBJYoUt3HjN4+ot+O9/0b+ke8ddE7UgOtVuZN/OkV19/g=="
|
||||
},
|
||||
"node-forge": {
|
||||
"version": "0.10.0",
|
||||
"resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.10.0.tgz",
|
||||
@ -13565,6 +13401,14 @@
|
||||
"integrity": "sha512-nfMOlASu9OnRJo1mbEk2cz0D56a1MBNrJ7orjRZQG10XDyuvwksKbuXNp6qa+kbn839HwjwhBzhFmdsaEAfauA==",
|
||||
"dev": true
|
||||
},
|
||||
"rxjs": {
|
||||
"version": "7.3.0",
|
||||
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.3.0.tgz",
|
||||
"integrity": "sha512-p2yuGIg9S1epc3vrjKf6iVb3RCaAYjYskkO+jHIaV0IjOPlJop4UnodOoFb2xeNwlguqLYvGw1b1McillYb5Gw==",
|
||||
"requires": {
|
||||
"tslib": "~2.1.0"
|
||||
}
|
||||
},
|
||||
"safe-buffer": {
|
||||
"version": "5.2.1",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
|
||||
@ -14464,6 +14308,16 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"ts-pattern": {
|
||||
"version": "3.3.3",
|
||||
"resolved": "https://registry.npmjs.org/ts-pattern/-/ts-pattern-3.3.3.tgz",
|
||||
"integrity": "sha512-Z5EFi6g6wyX3uDFHqxF5W5c5h663oZg9O6aOiAT7fqNu0HPSfCxtHzrQ7SblTy738Mrg2Ezorky8H5aUOm8Pvg=="
|
||||
},
|
||||
"tslib": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.1.0.tgz",
|
||||
"integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A=="
|
||||
},
|
||||
"tunnel-agent": {
|
||||
"version": "0.6.0",
|
||||
"resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
|
||||
|
@ -21,7 +21,7 @@
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@chainsafe/libp2p-noise": "4.0.0",
|
||||
"@fluencelabs/avm": "0.14.4",
|
||||
"@fluencelabs/avm": "0.15.4",
|
||||
"async": "3.2.0",
|
||||
"base64-js": "1.5.1",
|
||||
"bs58": "4.0.1",
|
||||
@ -35,6 +35,8 @@
|
||||
"loglevel": "1.7.0",
|
||||
"multiaddr": "10.0.0",
|
||||
"peer-id": "0.15.3",
|
||||
"rxjs": "^7.3.0",
|
||||
"ts-pattern": "^3.3.3",
|
||||
"uuid": "8.3.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
File diff suppressed because one or more lines are too long
@ -1,25 +1,48 @@
|
||||
import { Fluence, FluencePeer } from '../../index';
|
||||
import { RequestFlowBuilder } from '../../internal/RequestFlowBuilder';
|
||||
|
||||
const anotherPeer = new FluencePeer();
|
||||
import { FluencePeer } from '../../index';
|
||||
import { Particle } from '../../internal/Particle';
|
||||
import { registerHandlersHelper } from '../util';
|
||||
|
||||
describe('Avm spec', () => {
|
||||
afterEach(async () => {
|
||||
if (anotherPeer) {
|
||||
await anotherPeer.stop();
|
||||
}
|
||||
it('Simple call', async () => {
|
||||
// arrange
|
||||
const peer = new FluencePeer();
|
||||
await peer.start();
|
||||
|
||||
// act
|
||||
const promise = new Promise<string[]>((resolve, reject) => {
|
||||
const script = `
|
||||
(call %init_peer_id% ("print" "print") ["1"])
|
||||
`;
|
||||
const particle = Particle.createNew(script);
|
||||
registerHandlersHelper(peer, particle, {
|
||||
print: {
|
||||
print: async (args) => {
|
||||
const [res] = args;
|
||||
resolve(res);
|
||||
},
|
||||
},
|
||||
_timeout: reject,
|
||||
});
|
||||
|
||||
peer.internals.initiateParticle(particle);
|
||||
});
|
||||
|
||||
// assert
|
||||
const res = await promise;
|
||||
expect(res).toBe('1');
|
||||
|
||||
await peer.stop();
|
||||
});
|
||||
|
||||
it('Par execution should work', async () => {
|
||||
it('Par call', async () => {
|
||||
// arrange
|
||||
await Fluence.start();
|
||||
const peer = new FluencePeer();
|
||||
await peer.start();
|
||||
|
||||
let request;
|
||||
const promise = new Promise<string[]>((resolve) => {
|
||||
// act
|
||||
const promise = new Promise<string[]>((resolve, reject) => {
|
||||
let res = [];
|
||||
request = new RequestFlowBuilder()
|
||||
.withRawScript(
|
||||
`
|
||||
const script = `
|
||||
(seq
|
||||
(par
|
||||
(call %init_peer_id% ("print" "print") ["1"])
|
||||
@ -27,24 +50,27 @@ describe('Avm spec', () => {
|
||||
)
|
||||
(call %init_peer_id% ("print" "print") ["2"])
|
||||
)
|
||||
`,
|
||||
)
|
||||
.configHandler((h) => {
|
||||
h.onEvent('print', 'print', async (args) => {
|
||||
`;
|
||||
const particle = Particle.createNew(script);
|
||||
registerHandlersHelper(peer, particle, {
|
||||
print: {
|
||||
print: (args) => {
|
||||
res.push(args[0]);
|
||||
if (res.length == 2) {
|
||||
resolve(res);
|
||||
}
|
||||
});
|
||||
})
|
||||
.build();
|
||||
},
|
||||
},
|
||||
_timeout: reject,
|
||||
});
|
||||
|
||||
peer.internals.initiateParticle(particle);
|
||||
});
|
||||
|
||||
// act
|
||||
await Fluence.getPeer().internals.initiateFlow(request);
|
||||
const res = await promise;
|
||||
|
||||
// assert
|
||||
const res = await promise;
|
||||
expect(res).toStrictEqual(['1', '2']);
|
||||
|
||||
await peer.stop();
|
||||
});
|
||||
});
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { Fluence, FluencePeer } from '../../..';
|
||||
import { RequestFlowBuilder } from '../../../internal/RequestFlowBuilder';
|
||||
import { Particle } from '../../../internal/Particle';
|
||||
import { registerHandlersHelper } from '../../util';
|
||||
import { callMeBack, registerHelloWorld } from './gen1';
|
||||
|
||||
describe('Compiler support infrastructure tests', () => {
|
||||
@ -50,7 +51,7 @@ describe('Compiler support infrastructure tests', () => {
|
||||
const helloPromise = new Promise((resolve) => {
|
||||
registerHelloWorld('hello_world', {
|
||||
sayHello: (s, params) => {
|
||||
const tetrapelt = params.tetraplets.s; // completion should work here
|
||||
const tetraplet = params.tetraplets.s; // completion should work here
|
||||
resolve(s);
|
||||
},
|
||||
getNumber: (params) => {
|
||||
@ -60,23 +61,32 @@ describe('Compiler support infrastructure tests', () => {
|
||||
});
|
||||
});
|
||||
|
||||
const [request, getNumberPromise] = new RequestFlowBuilder()
|
||||
.withRawScript(
|
||||
`(seq
|
||||
(seq
|
||||
(call %init_peer_id% ("hello_world" "sayHello") ["hello world!"])
|
||||
(call %init_peer_id% ("hello_world" "getNumber") [] result)
|
||||
)
|
||||
(call %init_peer_id% ("callback" "callback") [result])
|
||||
)`,
|
||||
)
|
||||
.buildAsFetch<[string]>('callback', 'callback');
|
||||
await Fluence.getPeer().internals.initiateFlow(request);
|
||||
const getNumberPromise = new Promise<string>((resolve, reject) => {
|
||||
const script = `
|
||||
(seq
|
||||
(seq
|
||||
(call %init_peer_id% ("hello_world" "sayHello") ["hello world!"])
|
||||
(call %init_peer_id% ("hello_world" "getNumber") [] result)
|
||||
)
|
||||
(call %init_peer_id% ("callback" "callback") [result])
|
||||
)`;
|
||||
const particle = Particle.createNew(script);
|
||||
registerHandlersHelper(Fluence.getPeer(), particle, {
|
||||
callback: {
|
||||
callback: (args) => {
|
||||
const [val] = args;
|
||||
resolve(val);
|
||||
},
|
||||
},
|
||||
_timeout: reject,
|
||||
});
|
||||
|
||||
Fluence.getPeer().internals.initiateParticle(particle);
|
||||
});
|
||||
|
||||
// assert
|
||||
expect(await helloPromise).toBe('hello world!');
|
||||
expect(await getNumberPromise).toStrictEqual([42]);
|
||||
|
||||
expect(await getNumberPromise).toBe(42);
|
||||
await Fluence.stop();
|
||||
});
|
||||
|
||||
@ -122,14 +132,14 @@ describe('Compiler support infrastructure tests', () => {
|
||||
|
||||
it('Compiled code for service should work another peer', async () => {
|
||||
// arrange
|
||||
const peer = new FluencePeer();
|
||||
await peer.start();
|
||||
const anotherPeer = new FluencePeer();
|
||||
await anotherPeer.start();
|
||||
|
||||
// act
|
||||
const helloPromise = new Promise((resolve) => {
|
||||
registerHelloWorld(peer, 'hello_world', {
|
||||
registerHelloWorld(anotherPeer, 'hello_world', {
|
||||
sayHello: (s, params) => {
|
||||
const tetrapelt = params.tetraplets.s; // completion should work here
|
||||
const tetraplet = params.tetraplets.s; // completion should work here
|
||||
resolve(s);
|
||||
},
|
||||
getNumber: (params) => {
|
||||
@ -139,23 +149,32 @@ describe('Compiler support infrastructure tests', () => {
|
||||
});
|
||||
});
|
||||
|
||||
const [request, getNumberPromise] = new RequestFlowBuilder()
|
||||
.withRawScript(
|
||||
`(seq
|
||||
(seq
|
||||
(call %init_peer_id% ("hello_world" "sayHello") ["hello world!"])
|
||||
(call %init_peer_id% ("hello_world" "getNumber") [] result)
|
||||
)
|
||||
(call %init_peer_id% ("callback" "callback") [result])
|
||||
)`,
|
||||
)
|
||||
.buildAsFetch<[string]>('callback', 'callback');
|
||||
await peer.internals.initiateFlow(request);
|
||||
const getNumberPromise = new Promise<string>((resolve, reject) => {
|
||||
const script = `
|
||||
(seq
|
||||
(seq
|
||||
(call %init_peer_id% ("hello_world" "sayHello") ["hello world!"])
|
||||
(call %init_peer_id% ("hello_world" "getNumber") [] result)
|
||||
)
|
||||
(call %init_peer_id% ("callback" "callback") [result])
|
||||
)`;
|
||||
const particle = Particle.createNew(script);
|
||||
registerHandlersHelper(anotherPeer, particle, {
|
||||
callback: {
|
||||
callback: (args) => {
|
||||
const [val] = args;
|
||||
resolve(val);
|
||||
},
|
||||
},
|
||||
_timeout: reject,
|
||||
});
|
||||
anotherPeer.internals.initiateParticle(particle);
|
||||
});
|
||||
|
||||
// assert
|
||||
expect(await helloPromise).toBe('hello world!');
|
||||
expect(await getNumberPromise).toStrictEqual([42]);
|
||||
expect(await getNumberPromise).toBe(42);
|
||||
|
||||
await peer.stop();
|
||||
await anotherPeer.stop();
|
||||
});
|
||||
});
|
||||
|
@ -19,10 +19,14 @@ func callMeBack(callback: string, i32 -> ()):
|
||||
* This file is auto-generated. Do not edit manually: changes may be erased.
|
||||
* Generated by Aqua compiler: https://github.com/fluencelabs/aqua/.
|
||||
* If you find any bugs, please write an issue on GitHub: https://github.com/fluencelabs/aqua/issues
|
||||
* Aqua version: 0.2.2-SNAPSHOT
|
||||
* Aqua version: 0.3.1-231
|
||||
*
|
||||
*/
|
||||
|
||||
function missingFields(obj: any, fields: string[]): string[] {
|
||||
return fields.filter((f) => !(f in obj));
|
||||
}
|
||||
|
||||
// Services
|
||||
|
||||
export interface HelloWorldDef {
|
||||
@ -34,11 +38,11 @@ export function registerHelloWorld(service: HelloWorldDef): void;
|
||||
export function registerHelloWorld(serviceId: string, service: HelloWorldDef): void;
|
||||
export function registerHelloWorld(peer: FluencePeer, service: HelloWorldDef): void;
|
||||
export function registerHelloWorld(peer: FluencePeer, serviceId: string, service: HelloWorldDef): void;
|
||||
export function registerHelloWorld(...args) {
|
||||
export function registerHelloWorld(...args: any) {
|
||||
let peer: FluencePeer;
|
||||
let serviceId;
|
||||
let service;
|
||||
if (args[0] instanceof FluencePeer) {
|
||||
let serviceId: any;
|
||||
let service: any;
|
||||
if (FluencePeer.isInstance(args[0])) {
|
||||
peer = args[0];
|
||||
} else {
|
||||
peer = Fluence.getPeer();
|
||||
@ -52,7 +56,12 @@ export function registerHelloWorld(...args) {
|
||||
serviceId = 'default';
|
||||
}
|
||||
|
||||
if (!(args[0] instanceof FluencePeer) && typeof args[0] === 'object') {
|
||||
// Figuring out which overload is the service.
|
||||
// If the first argument is not Fluence Peer and it is an object, then it can only be the service def
|
||||
// If the first argument is peer, we are checking further. The second argument might either be
|
||||
// an object, that it must be the service object
|
||||
// or a string, which is the service id. In that case the service is the third argument
|
||||
if (!FluencePeer.isInstance(args[0]) && typeof args[0] === 'object') {
|
||||
service = args[0];
|
||||
} else if (typeof args[1] === 'object') {
|
||||
service = args[1];
|
||||
@ -60,6 +69,14 @@ export function registerHelloWorld(...args) {
|
||||
service = args[2];
|
||||
}
|
||||
|
||||
const incorrectServiceDefinitions = missingFields(service, ['getNumber', 'sayHello']);
|
||||
if (!!incorrectServiceDefinitions.length) {
|
||||
throw new Error(
|
||||
'Error registering service HelloWorld: missing functions: ' +
|
||||
incorrectServiceDefinitions.map((d) => "'" + d + "'").join(', '),
|
||||
);
|
||||
}
|
||||
|
||||
peer.internals.callServiceHandler.use((req, resp, next) => {
|
||||
if (req.serviceId !== serviceId) {
|
||||
next();
|
||||
@ -102,11 +119,11 @@ export function callMeBack(
|
||||
callback: (arg0: string, arg1: number, callParams: CallParams<'arg0' | 'arg1'>) => void,
|
||||
config?: { ttl?: number },
|
||||
): Promise<void>;
|
||||
export function callMeBack(...args) {
|
||||
export function callMeBack(...args: any) {
|
||||
let peer: FluencePeer;
|
||||
let callback;
|
||||
let config;
|
||||
if (args[0] instanceof FluencePeer) {
|
||||
let callback: any;
|
||||
let config: any;
|
||||
if (FluencePeer.isInstance(args[0])) {
|
||||
peer = args[0];
|
||||
callback = args[1];
|
||||
config = args[2];
|
||||
@ -122,24 +139,22 @@ export function callMeBack(...args) {
|
||||
.disableInjections()
|
||||
.withRawScript(
|
||||
`
|
||||
(xor
|
||||
(seq
|
||||
(call %init_peer_id% ("getDataSrv" "-relay-") [] -relay-)
|
||||
(xor
|
||||
(call %init_peer_id% ("callbackSrv" "callback") ["hello, world" 42])
|
||||
(call %init_peer_id% ("errorHandlingSrv" "error") [%last_error% 1])
|
||||
)
|
||||
)
|
||||
(call %init_peer_id% ("errorHandlingSrv" "error") [%last_error% 2])
|
||||
)
|
||||
|
||||
`,
|
||||
(xor
|
||||
(seq
|
||||
(call %init_peer_id% ("getDataSrv" "-relay-") [] -relay-)
|
||||
(xor
|
||||
(call %init_peer_id% ("callbackSrv" "callback") ["hello, world" 42])
|
||||
(call %init_peer_id% ("errorHandlingSrv" "error") [%last_error% 1])
|
||||
)
|
||||
)
|
||||
(call %init_peer_id% ("errorHandlingSrv" "error") [%last_error% 2])
|
||||
)
|
||||
`,
|
||||
)
|
||||
.configHandler((h) => {
|
||||
h.on('getDataSrv', '-relay-', () => {
|
||||
return peer.getStatus().relayPeerId || null;
|
||||
return peer.getStatus().relayPeerId;
|
||||
});
|
||||
|
||||
h.use((req, resp, next) => {
|
||||
if (req.serviceId === 'callbackSrv' && req.fnName === 'callback') {
|
||||
const callParams = {
|
||||
@ -157,7 +172,6 @@ export function callMeBack(...args) {
|
||||
});
|
||||
|
||||
h.onEvent('callbackSrv', 'response', (args) => {});
|
||||
|
||||
h.onEvent('errorHandlingSrv', 'error', (args) => {
|
||||
const [err] = args;
|
||||
reject(err);
|
||||
@ -167,9 +181,11 @@ export function callMeBack(...args) {
|
||||
.handleTimeout(() => {
|
||||
reject('Request timed out for callMeBack');
|
||||
});
|
||||
|
||||
if (config && config.ttl) {
|
||||
r.withTTL(config.ttl);
|
||||
}
|
||||
|
||||
request = r.build();
|
||||
});
|
||||
peer.internals.initiateFlow(request!);
|
||||
|
519
src/__test__/integration/compiler/gen2.ts
Normal file
519
src/__test__/integration/compiler/gen2.ts
Normal file
@ -0,0 +1,519 @@
|
||||
import { CallParams, registerService, callFunction } from '../../../internal/compilerSupport/v2';
|
||||
import { FluencePeer } from '../../../index';
|
||||
|
||||
/*
|
||||
|
||||
-- file to generate functions below from
|
||||
|
||||
service ServiceWithDefaultId("defaultId"):
|
||||
hello(s: string)
|
||||
|
||||
service ServiceWithOUTDefaultId:
|
||||
hello(s: string)
|
||||
|
||||
service MoreMembers:
|
||||
member1()
|
||||
member2(s1: string)
|
||||
member3(s1: string, s2: string)
|
||||
member4(s1: string, s2: string, i: i32) -> i32
|
||||
member5(s1: string, s2: string, i: i32) -> i32
|
||||
|
||||
func f1(callback: string, i32 -> ()):
|
||||
callback("hello, world", 42)
|
||||
|
||||
func f2(num: i32, callback: string, i32 -> ()):
|
||||
callback("hello, world", 42)
|
||||
|
||||
func f3(num: i32, callback: string, i32 -> ()) -> string:
|
||||
callback("hello, world", 42)
|
||||
<- "hello world"
|
||||
|
||||
func callBackZeroArgs(callback: -> ()):
|
||||
callback()
|
||||
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
* This file is auto-generated. Do not edit manually: changes may be erased.
|
||||
* Generated by Aqua compiler: https://github.com/fluencelabs/aqua/.
|
||||
* If you find any bugs, please write an issue on GitHub: https://github.com/fluencelabs/aqua/issues
|
||||
* Aqua version: 0.3.1-231
|
||||
*
|
||||
*/
|
||||
|
||||
// Services
|
||||
|
||||
export interface ServiceWithDefaultIdDef {
|
||||
hello: (s: string, callParams: CallParams<'s'>) => void;
|
||||
}
|
||||
export function registerServiceWithDefaultId(service: ServiceWithDefaultIdDef): void;
|
||||
export function registerServiceWithDefaultId(serviceId: string, service: ServiceWithDefaultIdDef): void;
|
||||
export function registerServiceWithDefaultId(peer: FluencePeer, service: ServiceWithDefaultIdDef): void;
|
||||
export function registerServiceWithDefaultId(
|
||||
peer: FluencePeer,
|
||||
serviceId: string,
|
||||
service: ServiceWithDefaultIdDef,
|
||||
): void;
|
||||
|
||||
export function registerServiceWithDefaultId(...args: any) {
|
||||
registerService(args, {
|
||||
defaultServiceId: 'defaultId',
|
||||
functions: [
|
||||
{
|
||||
functionName: 'hello',
|
||||
argDefs: [
|
||||
{
|
||||
name: 's',
|
||||
argType: {
|
||||
tag: 'primitive',
|
||||
},
|
||||
},
|
||||
],
|
||||
returnType: {
|
||||
tag: 'void',
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
export interface ServiceWithOUTDefaultIdDef {
|
||||
hello: (s: string, callParams: CallParams<'s'>) => void;
|
||||
}
|
||||
export function registerServiceWithOUTDefaultId(serviceId: string, service: ServiceWithOUTDefaultIdDef): void;
|
||||
export function registerServiceWithOUTDefaultId(
|
||||
peer: FluencePeer,
|
||||
serviceId: string,
|
||||
service: ServiceWithOUTDefaultIdDef,
|
||||
): void;
|
||||
|
||||
export function registerServiceWithOUTDefaultId(...args: any) {
|
||||
registerService(args, {
|
||||
defaultServiceId: null,
|
||||
functions: [
|
||||
{
|
||||
functionName: 'hello',
|
||||
argDefs: [
|
||||
{
|
||||
name: 's',
|
||||
argType: {
|
||||
tag: 'primitive',
|
||||
},
|
||||
},
|
||||
],
|
||||
returnType: {
|
||||
tag: 'void',
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
export interface MoreMembersDef {
|
||||
member1: (callParams: CallParams<null>) => void;
|
||||
member2: (s1: string, callParams: CallParams<'s1'>) => void;
|
||||
member3: (s1: string, s2: string, callParams: CallParams<'s1' | 's2'>) => void;
|
||||
member4: (s1: string, s2: string, i: number, callParams: CallParams<'s1' | 's2' | 'i'>) => number;
|
||||
member5: (s1: string, s2: string, i: number, callParams: CallParams<'s1' | 's2' | 'i'>) => number;
|
||||
}
|
||||
export function registerMoreMembers(serviceId: string, service: MoreMembersDef): void;
|
||||
export function registerMoreMembers(peer: FluencePeer, serviceId: string, service: MoreMembersDef): void;
|
||||
|
||||
export function registerMoreMembers(...args: any) {
|
||||
registerService(args, {
|
||||
defaultServiceId: null,
|
||||
functions: [
|
||||
{
|
||||
functionName: 'member1',
|
||||
argDefs: [],
|
||||
returnType: {
|
||||
tag: 'void',
|
||||
},
|
||||
},
|
||||
{
|
||||
functionName: 'member2',
|
||||
argDefs: [
|
||||
{
|
||||
name: 's1',
|
||||
argType: {
|
||||
tag: 'primitive',
|
||||
},
|
||||
},
|
||||
],
|
||||
returnType: {
|
||||
tag: 'void',
|
||||
},
|
||||
},
|
||||
{
|
||||
functionName: 'member3',
|
||||
argDefs: [
|
||||
{
|
||||
name: 's1',
|
||||
argType: {
|
||||
tag: 'primitive',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 's2',
|
||||
argType: {
|
||||
tag: 'primitive',
|
||||
},
|
||||
},
|
||||
],
|
||||
returnType: {
|
||||
tag: 'void',
|
||||
},
|
||||
},
|
||||
{
|
||||
functionName: 'member4',
|
||||
argDefs: [
|
||||
{
|
||||
name: 's1',
|
||||
argType: {
|
||||
tag: 'primitive',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 's2',
|
||||
argType: {
|
||||
tag: 'primitive',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'i',
|
||||
argType: {
|
||||
tag: 'primitive',
|
||||
},
|
||||
},
|
||||
],
|
||||
returnType: {
|
||||
tag: 'primitive',
|
||||
},
|
||||
},
|
||||
{
|
||||
functionName: 'member5',
|
||||
argDefs: [
|
||||
{
|
||||
name: 's1',
|
||||
argType: {
|
||||
tag: 'primitive',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 's2',
|
||||
argType: {
|
||||
tag: 'primitive',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'i',
|
||||
argType: {
|
||||
tag: 'primitive',
|
||||
},
|
||||
},
|
||||
],
|
||||
returnType: {
|
||||
tag: 'primitive',
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
// Functions
|
||||
|
||||
export function f1(
|
||||
callback: (arg0: string, arg1: number, callParams: CallParams<'arg0' | 'arg1'>) => void,
|
||||
config?: { ttl?: number },
|
||||
): Promise<void>;
|
||||
export function f1(
|
||||
peer: FluencePeer,
|
||||
callback: (arg0: string, arg1: number, callParams: CallParams<'arg0' | 'arg1'>) => void,
|
||||
config?: { ttl?: number },
|
||||
): Promise<void>;
|
||||
export function f1(...args: any) {
|
||||
let script = `
|
||||
(xor
|
||||
(seq
|
||||
(call %init_peer_id% ("getDataSrv" "-relay-") [] -relay-)
|
||||
(xor
|
||||
(call %init_peer_id% ("callbackSrv" "callback") ["hello, world" 42])
|
||||
(call %init_peer_id% ("errorHandlingSrv" "error") [%last_error% 1])
|
||||
)
|
||||
)
|
||||
(call %init_peer_id% ("errorHandlingSrv" "error") [%last_error% 2])
|
||||
)
|
||||
`;
|
||||
return callFunction(
|
||||
args,
|
||||
{
|
||||
functionName: 'f1',
|
||||
returnType: {
|
||||
tag: 'void',
|
||||
},
|
||||
argDefs: [
|
||||
{
|
||||
name: 'callback',
|
||||
argType: {
|
||||
tag: 'callback',
|
||||
callback: {
|
||||
argDefs: [
|
||||
{
|
||||
name: 'arg0',
|
||||
argType: {
|
||||
tag: 'primitive',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'arg1',
|
||||
argType: {
|
||||
tag: 'primitive',
|
||||
},
|
||||
},
|
||||
],
|
||||
returnType: {
|
||||
tag: 'void',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
names: {
|
||||
relay: '-relay-',
|
||||
getDataSrv: 'getDataSrv',
|
||||
callbackSrv: 'callbackSrv',
|
||||
responseSrv: 'callbackSrv',
|
||||
responseFnName: 'response',
|
||||
errorHandlingSrv: 'errorHandlingSrv',
|
||||
errorFnName: 'error',
|
||||
},
|
||||
},
|
||||
script,
|
||||
);
|
||||
}
|
||||
|
||||
export function f2(
|
||||
num: number,
|
||||
callback: (arg0: string, arg1: number, callParams: CallParams<'arg0' | 'arg1'>) => void,
|
||||
config?: { ttl?: number },
|
||||
): Promise<void>;
|
||||
export function f2(
|
||||
peer: FluencePeer,
|
||||
num: number,
|
||||
callback: (arg0: string, arg1: number, callParams: CallParams<'arg0' | 'arg1'>) => void,
|
||||
config?: { ttl?: number },
|
||||
): Promise<void>;
|
||||
export function f2(...args: any) {
|
||||
let script = `
|
||||
(xor
|
||||
(seq
|
||||
(seq
|
||||
(call %init_peer_id% ("getDataSrv" "-relay-") [] -relay-)
|
||||
(call %init_peer_id% ("getDataSrv" "num") [] num)
|
||||
)
|
||||
(xor
|
||||
(call %init_peer_id% ("callbackSrv" "callback") ["hello, world" 42])
|
||||
(call %init_peer_id% ("errorHandlingSrv" "error") [%last_error% 1])
|
||||
)
|
||||
)
|
||||
(call %init_peer_id% ("errorHandlingSrv" "error") [%last_error% 2])
|
||||
)
|
||||
`;
|
||||
return callFunction(
|
||||
args,
|
||||
{
|
||||
functionName: 'f2',
|
||||
returnType: {
|
||||
tag: 'void',
|
||||
},
|
||||
argDefs: [
|
||||
{
|
||||
name: 'num',
|
||||
argType: {
|
||||
tag: 'primitive',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'callback',
|
||||
argType: {
|
||||
tag: 'callback',
|
||||
callback: {
|
||||
argDefs: [
|
||||
{
|
||||
name: 'arg0',
|
||||
argType: {
|
||||
tag: 'primitive',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'arg1',
|
||||
argType: {
|
||||
tag: 'primitive',
|
||||
},
|
||||
},
|
||||
],
|
||||
returnType: {
|
||||
tag: 'void',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
names: {
|
||||
relay: '-relay-',
|
||||
getDataSrv: 'getDataSrv',
|
||||
callbackSrv: 'callbackSrv',
|
||||
responseSrv: 'callbackSrv',
|
||||
responseFnName: 'response',
|
||||
errorHandlingSrv: 'errorHandlingSrv',
|
||||
errorFnName: 'error',
|
||||
},
|
||||
},
|
||||
script,
|
||||
);
|
||||
}
|
||||
|
||||
export function f3(
|
||||
num: number,
|
||||
callback: (arg0: string, arg1: number, callParams: CallParams<'arg0' | 'arg1'>) => void,
|
||||
config?: { ttl?: number },
|
||||
): Promise<string>;
|
||||
export function f3(
|
||||
peer: FluencePeer,
|
||||
num: number,
|
||||
callback: (arg0: string, arg1: number, callParams: CallParams<'arg0' | 'arg1'>) => void,
|
||||
config?: { ttl?: number },
|
||||
): Promise<string>;
|
||||
export function f3(...args: any) {
|
||||
let script = `
|
||||
(xor
|
||||
(seq
|
||||
(seq
|
||||
(seq
|
||||
(call %init_peer_id% ("getDataSrv" "-relay-") [] -relay-)
|
||||
(call %init_peer_id% ("getDataSrv" "num") [] num)
|
||||
)
|
||||
(xor
|
||||
(call %init_peer_id% ("callbackSrv" "callback") ["hello, world" 42])
|
||||
(call %init_peer_id% ("errorHandlingSrv" "error") [%last_error% 1])
|
||||
)
|
||||
)
|
||||
(xor
|
||||
(call %init_peer_id% ("callbackSrv" "response") ["hello world"])
|
||||
(call %init_peer_id% ("errorHandlingSrv" "error") [%last_error% 2])
|
||||
)
|
||||
)
|
||||
(call %init_peer_id% ("errorHandlingSrv" "error") [%last_error% 3])
|
||||
)
|
||||
`;
|
||||
return callFunction(
|
||||
args,
|
||||
{
|
||||
functionName: 'f3',
|
||||
returnType: {
|
||||
tag: 'primitive',
|
||||
},
|
||||
argDefs: [
|
||||
{
|
||||
name: 'num',
|
||||
argType: {
|
||||
tag: 'primitive',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'callback',
|
||||
argType: {
|
||||
tag: 'callback',
|
||||
callback: {
|
||||
argDefs: [
|
||||
{
|
||||
name: 'arg0',
|
||||
argType: {
|
||||
tag: 'primitive',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'arg1',
|
||||
argType: {
|
||||
tag: 'primitive',
|
||||
},
|
||||
},
|
||||
],
|
||||
returnType: {
|
||||
tag: 'void',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
names: {
|
||||
relay: '-relay-',
|
||||
getDataSrv: 'getDataSrv',
|
||||
callbackSrv: 'callbackSrv',
|
||||
responseSrv: 'callbackSrv',
|
||||
responseFnName: 'response',
|
||||
errorHandlingSrv: 'errorHandlingSrv',
|
||||
errorFnName: 'error',
|
||||
},
|
||||
},
|
||||
script,
|
||||
);
|
||||
}
|
||||
|
||||
export function callBackZeroArgs(
|
||||
callback: (callParams: CallParams<null>) => void,
|
||||
config?: { ttl?: number },
|
||||
): Promise<void>;
|
||||
export function callBackZeroArgs(
|
||||
peer: FluencePeer,
|
||||
callback: (callParams: CallParams<null>) => void,
|
||||
config?: { ttl?: number },
|
||||
): Promise<void>;
|
||||
export function callBackZeroArgs(...args: any) {
|
||||
let script = `
|
||||
(xor
|
||||
(seq
|
||||
(call %init_peer_id% ("getDataSrv" "-relay-") [] -relay-)
|
||||
(xor
|
||||
(call %init_peer_id% ("callbackSrv" "callback") [])
|
||||
(call %init_peer_id% ("errorHandlingSrv" "error") [%last_error% 1])
|
||||
)
|
||||
)
|
||||
(call %init_peer_id% ("errorHandlingSrv" "error") [%last_error% 2])
|
||||
)
|
||||
`;
|
||||
return callFunction(
|
||||
args,
|
||||
{
|
||||
functionName: 'callBackZeroArgs',
|
||||
returnType: {
|
||||
tag: 'void',
|
||||
},
|
||||
argDefs: [
|
||||
{
|
||||
name: 'callback',
|
||||
argType: {
|
||||
tag: 'callback',
|
||||
callback: {
|
||||
argDefs: [],
|
||||
returnType: {
|
||||
tag: 'void',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
names: {
|
||||
relay: '-relay-',
|
||||
getDataSrv: 'getDataSrv',
|
||||
callbackSrv: 'callbackSrv',
|
||||
responseSrv: 'callbackSrv',
|
||||
responseFnName: 'response',
|
||||
errorHandlingSrv: 'errorHandlingSrv',
|
||||
errorFnName: 'error',
|
||||
},
|
||||
},
|
||||
script,
|
||||
);
|
||||
}
|
@ -1,9 +1,9 @@
|
||||
import { Multiaddr } from 'multiaddr';
|
||||
import { nodes } from '../connection';
|
||||
import { RequestFlowBuilder } from '../../internal/RequestFlowBuilder';
|
||||
import log from 'loglevel';
|
||||
import { Fluence, FluencePeer } from '../../index';
|
||||
import { Fluence, FluencePeer, setLogLevel } from '../../index';
|
||||
import { checkConnection } from '../../internal/utils';
|
||||
import { Particle } from '../../internal/Particle';
|
||||
import { registerHandlersHelper } from '../util';
|
||||
|
||||
const anotherPeer = new FluencePeer();
|
||||
|
||||
@ -67,7 +67,7 @@ describe('Typescript usage suite', () => {
|
||||
});
|
||||
|
||||
it('Should expose correct status for connected peer', async () => {
|
||||
// arrnge
|
||||
// arrange
|
||||
const peer = new FluencePeer();
|
||||
await peer.start({ connectTo: nodes[0] });
|
||||
|
||||
@ -89,18 +89,46 @@ describe('Typescript usage suite', () => {
|
||||
await anotherPeer.start({ connectTo: nodes[0] });
|
||||
|
||||
// act
|
||||
const [request, promise] = new RequestFlowBuilder()
|
||||
.withRawScript(
|
||||
`(seq
|
||||
(call init_relay ("op" "identity") ["hello world!"] result)
|
||||
(call %init_peer_id% ("callback" "callback") [result])
|
||||
)`,
|
||||
const promise = new Promise<string[]>((resolve, reject) => {
|
||||
const script = `
|
||||
(xor
|
||||
(seq
|
||||
(call %init_peer_id% ("load" "relay") [] init_relay)
|
||||
(seq
|
||||
(call init_relay ("op" "identity") ["hello world!"] result)
|
||||
(call %init_peer_id% ("callback" "callback") [result])
|
||||
)
|
||||
.buildAsFetch<[string]>('callback', 'callback');
|
||||
await anotherPeer.internals.initiateFlow(request);
|
||||
)
|
||||
(seq
|
||||
(call init_relay ("op" "identity") [])
|
||||
(call %init_peer_id% ("callback" "error") [%last_error%])
|
||||
)
|
||||
)`;
|
||||
const particle = Particle.createNew(script);
|
||||
registerHandlersHelper(anotherPeer, particle, {
|
||||
load: {
|
||||
relay: (args) => {
|
||||
return anotherPeer.getStatus().relayPeerId;
|
||||
},
|
||||
},
|
||||
callback: {
|
||||
callback: (args) => {
|
||||
const [val] = args;
|
||||
resolve(val);
|
||||
},
|
||||
error: (args) => {
|
||||
const [error] = args;
|
||||
reject(error);
|
||||
},
|
||||
},
|
||||
_timeout: reject,
|
||||
});
|
||||
|
||||
anotherPeer.internals.initiateParticle(particle);
|
||||
});
|
||||
|
||||
// assert
|
||||
const [result] = await promise;
|
||||
const result = await promise;
|
||||
expect(result).toBe('hello world!');
|
||||
});
|
||||
|
||||
@ -127,30 +155,25 @@ describe('Typescript usage suite', () => {
|
||||
const peer2 = new FluencePeer();
|
||||
await peer2.start({ connectTo: nodes[0] });
|
||||
|
||||
let resMakingPromise = new Promise((resolve) => {
|
||||
// act
|
||||
const resMakingPromise = new Promise((resolve) => {
|
||||
peer2.internals.callServiceHandler.onEvent('test', 'test', (args, _) => {
|
||||
resolve([...args]);
|
||||
return {};
|
||||
resolve(args[0]);
|
||||
});
|
||||
});
|
||||
|
||||
let script = `
|
||||
const script = `
|
||||
(seq
|
||||
(call "${peer1.getStatus().relayPeerId}" ("op" "identity") [])
|
||||
(call "${peer2.getStatus().peerId}" ("test" "test") [a b c d])
|
||||
(call "${peer2.getStatus().peerId}" ("test" "test") ["test"])
|
||||
)
|
||||
`;
|
||||
const particle = Particle.createNew(script);
|
||||
await peer1.internals.initiateParticle(particle);
|
||||
|
||||
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');
|
||||
|
||||
await peer1.internals.initiateFlow(new RequestFlowBuilder().withRawScript(script).withVariables(data).build());
|
||||
|
||||
let res = await resMakingPromise;
|
||||
expect(res).toEqual(['some a', 'some b', 'some c', 'some d']);
|
||||
// assert
|
||||
const res = await resMakingPromise;
|
||||
expect(res).toEqual('test');
|
||||
|
||||
await peer1.stop();
|
||||
await peer2.stop();
|
||||
@ -254,103 +277,161 @@ describe('Typescript usage suite', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('xor handling should work with connected client', async function () {
|
||||
it('Should successfully call identity on local peer', async function () {
|
||||
// arrange
|
||||
const [request, promise] = new RequestFlowBuilder()
|
||||
.withRawScript(
|
||||
`
|
||||
await anotherPeer.start();
|
||||
|
||||
// act
|
||||
const promise = new Promise<string>((resolve, reject) => {
|
||||
const script = `
|
||||
(seq
|
||||
(call init_relay ("op" "identity") [])
|
||||
(call init_relay ("incorrect" "service") ["incorrect_arg"])
|
||||
(call %init_peer_id% ("op" "identity") ["test"] res)
|
||||
(call %init_peer_id% ("callback" "callback") [res])
|
||||
)
|
||||
`,
|
||||
)
|
||||
.buildWithErrorHandling();
|
||||
`;
|
||||
const particle = Particle.createNew(script);
|
||||
registerHandlersHelper(anotherPeer, particle, {
|
||||
callback: {
|
||||
callback: async (args) => {
|
||||
const [res] = args;
|
||||
resolve(res);
|
||||
},
|
||||
},
|
||||
// op: {
|
||||
// identity: (req) => {},
|
||||
// },
|
||||
_timeout: reject,
|
||||
});
|
||||
|
||||
// act
|
||||
await anotherPeer.start({ connectTo: nodes[0] });
|
||||
await anotherPeer.internals.initiateFlow(request);
|
||||
|
||||
// assert
|
||||
await expect(promise).rejects.toMatchObject({
|
||||
msg: expect.stringContaining("Service with id 'incorrect' not found"),
|
||||
instruction: expect.stringContaining('incorrect'),
|
||||
anotherPeer.internals.initiateParticle(particle);
|
||||
});
|
||||
});
|
||||
|
||||
it('xor handling should work with local client', async function () {
|
||||
// arrange
|
||||
const [request, promise] = new RequestFlowBuilder()
|
||||
.withRawScript(
|
||||
`
|
||||
(call %init_peer_id% ("service" "fails") [])
|
||||
`,
|
||||
)
|
||||
.configHandler((h) => {
|
||||
h.use((req, res, _) => {
|
||||
res.retCode = 1;
|
||||
res.result = 'service failed internally';
|
||||
});
|
||||
})
|
||||
.buildWithErrorHandling();
|
||||
|
||||
// act
|
||||
await anotherPeer.start();
|
||||
await anotherPeer.internals.initiateFlow(request);
|
||||
|
||||
// assert
|
||||
await expect(promise).rejects.toMatch('service failed internally');
|
||||
const res = await promise;
|
||||
expect(res).toBe('test');
|
||||
});
|
||||
|
||||
it.skip('Should throw correct message when calling non existing local service', async function () {
|
||||
it('Should throw correct message when calling non existing local service', async function () {
|
||||
// arrange
|
||||
await anotherPeer.start();
|
||||
await anotherPeer.start({ connectTo: nodes[0] });
|
||||
|
||||
// act
|
||||
const res = callIdentifyOnInitPeerId(anotherPeer);
|
||||
const res = callIncorrectService(anotherPeer);
|
||||
|
||||
// assert
|
||||
await expect(res).rejects.toMatchObject({
|
||||
msg: expect.stringContaining(
|
||||
`The handler did not set any result. Make sure you are calling the right peer and the handler has been registered. Original request data was: serviceId='peer' fnName='identify' args=''\"'`,
|
||||
`No handler has been registered for serviceId='incorrect' fnName='incorrect' args=''\"'`,
|
||||
),
|
||||
instruction: 'call %init_peer_id% ("peer" "identify") [] res',
|
||||
instruction: 'call %init_peer_id% ("incorrect" "incorrect") [] res',
|
||||
});
|
||||
});
|
||||
|
||||
it('Should not crash if undefined is passed as a variable', async () => {
|
||||
// arrange
|
||||
// arrange;
|
||||
await anotherPeer.start();
|
||||
const [request, promise] = new RequestFlowBuilder()
|
||||
.withRawScript(
|
||||
`
|
||||
(seq
|
||||
(call %init_peer_id% ("op" "identity") [arg] res)
|
||||
(call %init_peer_id% ("return" "return") [res])
|
||||
)
|
||||
`,
|
||||
)
|
||||
.withVariable('arg', undefined as any)
|
||||
.buildAsFetch<any[]>('return', 'return');
|
||||
|
||||
// act
|
||||
await anotherPeer.internals.initiateFlow(request);
|
||||
const [res] = await promise;
|
||||
const promise = new Promise<any>((resolve, reject) => {
|
||||
const script = `
|
||||
(seq
|
||||
(call %init_peer_id% ("load" "arg") [] arg)
|
||||
(seq
|
||||
(call %init_peer_id% ("op" "identity") [arg] res)
|
||||
(call %init_peer_id% ("callback" "callback") [res])
|
||||
)
|
||||
)`;
|
||||
const particle = Particle.createNew(script);
|
||||
|
||||
registerHandlersHelper(anotherPeer, particle, {
|
||||
load: {
|
||||
arg: (args) => {
|
||||
return undefined;
|
||||
},
|
||||
},
|
||||
callback: {
|
||||
callback: (args) => {
|
||||
const [val] = args;
|
||||
resolve(val);
|
||||
},
|
||||
error: (args) => {
|
||||
const [error] = args;
|
||||
reject(error);
|
||||
},
|
||||
},
|
||||
_timeout: reject,
|
||||
});
|
||||
|
||||
anotherPeer.internals.initiateParticle(particle);
|
||||
});
|
||||
|
||||
// assert
|
||||
const res = await promise;
|
||||
expect(res).toBe(null);
|
||||
});
|
||||
|
||||
it('Should throw correct error when the client tries to send a particle not to the relay', async () => {
|
||||
// arrange
|
||||
it('Should not crash if an error ocurred in user-defined handler', async () => {
|
||||
// arrange;
|
||||
setLogLevel('trace');
|
||||
await anotherPeer.start();
|
||||
|
||||
// act
|
||||
const [req, promise] = new RequestFlowBuilder()
|
||||
.withRawScript('(call "incorrect_peer_id" ("any" "service") [])')
|
||||
.buildWithErrorHandling();
|
||||
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);
|
||||
|
||||
await anotherPeer.internals.initiateFlow(req);
|
||||
registerHandlersHelper(anotherPeer, particle, {
|
||||
load: {
|
||||
arg: (args) => {
|
||||
throw 'my super custom error message';
|
||||
},
|
||||
},
|
||||
callback: {
|
||||
error: (args) => {
|
||||
const [error] = args;
|
||||
reject(error);
|
||||
},
|
||||
},
|
||||
_timeout: reject,
|
||||
});
|
||||
|
||||
anotherPeer.internals.initiateParticle(particle);
|
||||
});
|
||||
|
||||
// assert
|
||||
await expect(promise).rejects.toMatchObject({
|
||||
msg: expect.stringContaining('my super custom error message'),
|
||||
});
|
||||
});
|
||||
|
||||
it.skip('Should throw correct error when the client tries to send a particle not to the relay', async () => {
|
||||
// arrange;
|
||||
await anotherPeer.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);
|
||||
|
||||
registerHandlersHelper(anotherPeer, particle, {
|
||||
callback: {
|
||||
error: (args) => {
|
||||
const [error] = args;
|
||||
reject(error);
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
anotherPeer.internals.initiateParticle(particle);
|
||||
});
|
||||
|
||||
// assert
|
||||
await expect(promise).rejects.toMatch(
|
||||
@ -359,18 +440,30 @@ describe('Typescript usage suite', () => {
|
||||
});
|
||||
});
|
||||
|
||||
async function callIdentifyOnInitPeerId(peer: FluencePeer): Promise<string[]> {
|
||||
let request;
|
||||
const promise = new Promise<string[]>((resolve, reject) => {
|
||||
request = new RequestFlowBuilder()
|
||||
.withRawScript(
|
||||
`
|
||||
(call %init_peer_id% ("peer" "identify") [] res)
|
||||
`,
|
||||
)
|
||||
.handleScriptError(reject)
|
||||
.build();
|
||||
async function callIncorrectService(peer: FluencePeer): Promise<string[]> {
|
||||
const promise = 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);
|
||||
|
||||
registerHandlersHelper(peer, particle, {
|
||||
callback: {
|
||||
callback: (args) => {
|
||||
resolve(args);
|
||||
},
|
||||
error: (args) => {
|
||||
const [error] = args;
|
||||
reject(error);
|
||||
},
|
||||
},
|
||||
_timeout: reject,
|
||||
});
|
||||
|
||||
peer.internals.initiateParticle(particle);
|
||||
});
|
||||
await peer.internals.initiateFlow(request);
|
||||
|
||||
return promise;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { CallServiceData, CallServiceHandler, ResultCodes } from '../../internal/CallServiceHandler';
|
||||
import { errorHandler } from '../../internal/defaultMiddlewares';
|
||||
import { CallServiceData, ResultCodes } from '../../internal/commonTypes';
|
||||
import { CallServiceHandler } from '../../internal/compilerSupport/LegacyCallServiceHandler';
|
||||
|
||||
const req = (): CallServiceData => ({
|
||||
serviceId: 'service',
|
||||
@ -92,25 +92,6 @@ describe('Call service handler tests', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('Should work with provided error handling middleware', () => {
|
||||
// arrange
|
||||
const handler = new CallServiceHandler();
|
||||
|
||||
handler.use(errorHandler);
|
||||
handler.use((req, res, next) => {
|
||||
throw new Error('some error');
|
||||
});
|
||||
|
||||
// act
|
||||
const res = handler.execute(req());
|
||||
|
||||
// assert
|
||||
expect(res).toMatchObject({
|
||||
retCode: ResultCodes.exceptionInHandler,
|
||||
result: 'Handler failed. fnName="fn name" serviceId="service" error: Error: some error',
|
||||
});
|
||||
});
|
||||
|
||||
describe('Service handler tests', () => {
|
||||
it('Should register service function', () => {
|
||||
// arrange
|
||||
@ -134,28 +115,6 @@ describe('Call service handler tests', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('Should UNregister service function', () => {
|
||||
// arrange
|
||||
const handler = new CallServiceHandler();
|
||||
const unreg = handler.on('service', 'function', (args) => {
|
||||
return { called: args };
|
||||
});
|
||||
unreg();
|
||||
|
||||
// act
|
||||
const res = handler.execute({
|
||||
...req(),
|
||||
serviceId: 'service',
|
||||
fnName: 'function',
|
||||
args: ['hello', 'world'],
|
||||
});
|
||||
|
||||
// assert
|
||||
expect(res).toMatchObject({
|
||||
retCode: ResultCodes.unkownError,
|
||||
});
|
||||
});
|
||||
|
||||
it('Should register event', async () => {
|
||||
// arrange
|
||||
const handler = new CallServiceHandler();
|
||||
@ -180,28 +139,6 @@ describe('Call service handler tests', () => {
|
||||
await expect(returnPromise).resolves.toMatchObject({ called: ['hello', 'world'] });
|
||||
});
|
||||
|
||||
it('Should UNregister event', () => {
|
||||
// arrange
|
||||
const handler = new CallServiceHandler();
|
||||
const unreg = handler.onEvent('service', 'function', (args) => {
|
||||
// don't care
|
||||
});
|
||||
unreg();
|
||||
|
||||
// act
|
||||
const res = handler.execute({
|
||||
...req(),
|
||||
serviceId: 'service',
|
||||
fnName: 'function',
|
||||
args: ['hello', 'world'],
|
||||
});
|
||||
|
||||
// assert
|
||||
expect(res).toMatchObject({
|
||||
retCode: ResultCodes.unkownError,
|
||||
});
|
||||
});
|
||||
|
||||
it('Should register multiple service functions', () => {
|
||||
// arrange
|
||||
const handler = new CallServiceHandler();
|
||||
|
@ -1,31 +0,0 @@
|
||||
import { KeyPair } from '../../internal/KeyPair';
|
||||
import { RequestFlow } from '../../internal/RequestFlow';
|
||||
import * as base64 from 'base64-js';
|
||||
|
||||
describe('Request flow tests', () => {
|
||||
it('particle initiation should work', async () => {
|
||||
// arrange
|
||||
jest.useFakeTimers();
|
||||
const sk = 'z1x3cVXhk9nJKE1pZaX9KxccUBzxu3aGlaUjDdAB2oY=';
|
||||
const skBytes = base64.toByteArray(sk);
|
||||
const mockDate = new Date(Date.UTC(2021, 2, 14)).valueOf();
|
||||
Date.now = jest.fn(() => mockDate);
|
||||
|
||||
const request = RequestFlow.createLocal('(null)', 10000);
|
||||
const peerId = await (await KeyPair.fromEd25519SK(skBytes)).Libp2pPeerId;
|
||||
|
||||
// act
|
||||
await request.initState(peerId);
|
||||
|
||||
// assert
|
||||
const particle = request.getParticle();
|
||||
expect(particle).toMatchObject({
|
||||
init_peer_id: peerId.toB58String(),
|
||||
script: '(null)',
|
||||
signature: '',
|
||||
timestamp: mockDate,
|
||||
ttl: 10000,
|
||||
});
|
||||
expect(setTimeout).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
@ -1,24 +0,0 @@
|
||||
import { FluenceConnection } from '../../internal/FluenceConnection';
|
||||
import Peer from 'libp2p';
|
||||
import { Multiaddr } from 'multiaddr';
|
||||
import { KeyPair } from '../../internal/KeyPair';
|
||||
|
||||
describe('Ws Transport', () => {
|
||||
// TODO:: fix test
|
||||
test.skip('Should work with ws schema', async () => {
|
||||
// arrange
|
||||
let multiaddr = new Multiaddr(
|
||||
'/ip4/127.0.0.1/tcp/1234/ws/p2p/12D3KooWMJ78GJrtCxVUpjLEedbPtnLDxkFQJ2wuefEdrxq6zwSs',
|
||||
);
|
||||
let peerId = (await KeyPair.randomEd25519()).Libp2pPeerId;
|
||||
const connection = new FluenceConnection(multiaddr, peerId, peerId, (_) => {});
|
||||
await (connection as any).createPeer();
|
||||
let node = (connection as any).node as Peer;
|
||||
|
||||
// act
|
||||
let transport = node.transportManager.transportForMultiaddr(multiaddr);
|
||||
|
||||
// assert
|
||||
expect(transport).toBeDefined();
|
||||
});
|
||||
});
|
@ -1,6 +1,6 @@
|
||||
import each from 'jest-each';
|
||||
import { CallServiceData } from '../../internal/CallServiceHandler';
|
||||
import makeDefaultClientHandler from '../../internal/defaultClientHandler';
|
||||
import { CallServiceData } from '../../internal/commonTypes';
|
||||
import { defaultServices } from '../../internal/defaultServices';
|
||||
|
||||
describe('Tests for default handler', () => {
|
||||
// prettier-ignore
|
||||
@ -34,7 +34,7 @@ describe('Tests for default handler', () => {
|
||||
`.test(
|
||||
//
|
||||
'$fnName with $args expected retcode: $retCode and result: $result',
|
||||
({ fnName, args, retCode, result }) => {
|
||||
async ({ fnName, args, retCode, result }) => {
|
||||
// arrange
|
||||
const req: CallServiceData = {
|
||||
serviceId: 'op',
|
||||
@ -51,14 +51,41 @@ describe('Tests for default handler', () => {
|
||||
};
|
||||
|
||||
// act
|
||||
const res = makeDefaultClientHandler().execute(req);
|
||||
const fn = defaultServices[req.serviceId][req.fnName];
|
||||
const res = await fn(req);
|
||||
|
||||
// assert
|
||||
expect(res).toMatchObject({
|
||||
retCode: retCode,
|
||||
result: result,
|
||||
});
|
||||
const handler = makeDefaultClientHandler();
|
||||
},
|
||||
);
|
||||
|
||||
it('should return correct error message for identiy service', async () => {
|
||||
// arrange
|
||||
const req: CallServiceData = {
|
||||
serviceId: 'peer',
|
||||
fnName: 'identify',
|
||||
args: [],
|
||||
tetraplets: [],
|
||||
particleContext: {
|
||||
particleId: 'some',
|
||||
initPeerId: 'init peer id',
|
||||
timestamp: 595951200,
|
||||
ttl: 595961200,
|
||||
signature: 'sig',
|
||||
},
|
||||
};
|
||||
|
||||
// act
|
||||
const fn = defaultServices[req.serviceId][req.fnName];
|
||||
const res = await fn(req);
|
||||
|
||||
// assert
|
||||
expect(res).toMatchObject({
|
||||
retCode: 1,
|
||||
result: 'The JS implementation of Peer does not support identify',
|
||||
});
|
||||
});
|
||||
});
|
||||
|
17
src/__test__/util.ts
Normal file
17
src/__test__/util.ts
Normal file
@ -0,0 +1,17 @@
|
||||
import { FluencePeer } from '../index';
|
||||
import { Particle } from '../internal/Particle';
|
||||
import { MakeServiceCall } from '../internal/utils';
|
||||
|
||||
export const registerHandlersHelper = (peer: FluencePeer, particle: Particle, handlers) => {
|
||||
const { _timeout, ...rest } = handlers;
|
||||
if (_timeout) {
|
||||
peer.internals.regHandler.timeout(particle.id, _timeout);
|
||||
}
|
||||
for (let serviceId in rest) {
|
||||
for (let fnName in rest[serviceId]) {
|
||||
// of type [args] => result
|
||||
const h = rest[serviceId][fnName];
|
||||
peer.internals.regHandler.forParticle(particle.id, serviceId, fnName, MakeServiceCall(h));
|
||||
}
|
||||
}
|
||||
};
|
@ -16,82 +16,53 @@
|
||||
|
||||
import Websockets from 'libp2p-websockets';
|
||||
import Mplex from 'libp2p-mplex';
|
||||
import Peer from 'libp2p';
|
||||
import Lib2p2Peer from 'libp2p';
|
||||
import { decode, encode } from 'it-length-prefixed';
|
||||
import pipe from 'it-pipe';
|
||||
import * as log from 'loglevel';
|
||||
import { logParticle, parseParticle, Particle, toPayload } from './particle';
|
||||
import { Particle } from './Particle';
|
||||
import { NOISE } from '@chainsafe/libp2p-noise';
|
||||
import PeerId from 'peer-id';
|
||||
import { Multiaddr } from 'multiaddr';
|
||||
import { all as allow_all } from 'libp2p-websockets/src/filters';
|
||||
import { Connection } from 'libp2p-interfaces/src/topology';
|
||||
|
||||
export const PROTOCOL_NAME = '/fluence/particle/2.0.0';
|
||||
|
||||
enum Status {
|
||||
Initializing = 'Initializing',
|
||||
Connected = 'Connected',
|
||||
Disconnected = 'Disconnected',
|
||||
}
|
||||
|
||||
/**
|
||||
* Options to configure fluence connection
|
||||
*/
|
||||
export interface FluenceConnectionOptions {
|
||||
/**
|
||||
* @property {number} [checkConnectionTTL] - TTL for the check connection request in ms
|
||||
* Peer id of the Fluence Peer
|
||||
*/
|
||||
checkConnectionTTL?: number;
|
||||
peerId: PeerId;
|
||||
|
||||
/**
|
||||
* @property {number} [checkConnectionTTL] - set to true to skip check connection request completely
|
||||
* Multiaddress of the relay to make connection to
|
||||
*/
|
||||
skipCheckConnection?: boolean;
|
||||
relayAddress: Multiaddr;
|
||||
|
||||
/**
|
||||
* @property {number} [dialTimeout] - How long a dial attempt is allowed to take.
|
||||
* The dialing timeout in milliseconds
|
||||
*/
|
||||
dialTimeout?: number;
|
||||
dialTimeoutMs?: number;
|
||||
|
||||
/**
|
||||
* Handler for incoming particles from the connection
|
||||
*/
|
||||
onIncomingParticle: (p: Particle) => void;
|
||||
}
|
||||
|
||||
export class FluenceConnection {
|
||||
private readonly selfPeerId: PeerId;
|
||||
private node: Peer;
|
||||
private readonly address: Multiaddr;
|
||||
readonly nodePeerId: PeerId;
|
||||
private readonly selfPeerIdStr: string;
|
||||
private readonly handleParticle: (call: Particle) => void;
|
||||
constructor() {}
|
||||
|
||||
constructor(
|
||||
multiaddr: Multiaddr,
|
||||
hostPeerId: PeerId,
|
||||
selfPeerId: PeerId,
|
||||
handleParticle: (call: Particle) => void,
|
||||
) {
|
||||
this.selfPeerId = selfPeerId;
|
||||
this.handleParticle = handleParticle;
|
||||
this.selfPeerIdStr = selfPeerId.toB58String();
|
||||
this.address = multiaddr;
|
||||
this.nodePeerId = hostPeerId;
|
||||
}
|
||||
static async createConnection(options: FluenceConnectionOptions): Promise<FluenceConnection> {
|
||||
const res = new FluenceConnection();
|
||||
|
||||
async connect(options?: FluenceConnectionOptions) {
|
||||
await this.createPeer(options);
|
||||
await this.startReceiving();
|
||||
}
|
||||
|
||||
isConnected() {
|
||||
return this.status === Status.Connected;
|
||||
}
|
||||
|
||||
// connection status. If `Disconnected`, it cannot be reconnected
|
||||
private status: Status = Status.Initializing;
|
||||
|
||||
private async createPeer(options?: FluenceConnectionOptions) {
|
||||
const peerInfo = this.selfPeerId;
|
||||
const transportKey = Websockets.prototype[Symbol.toStringTag];
|
||||
this.node = await Peer.create({
|
||||
peerId: peerInfo,
|
||||
res._lib2p2Peer = await Lib2p2Peer.create({
|
||||
peerId: options.peerId,
|
||||
modules: {
|
||||
transport: [Websockets],
|
||||
streamMuxer: [Mplex],
|
||||
@ -105,78 +76,74 @@ export class FluenceConnection {
|
||||
},
|
||||
},
|
||||
dialer: {
|
||||
dialTimeout: options?.dialTimeout,
|
||||
dialTimeout: options?.dialTimeoutMs,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
private async startReceiving() {
|
||||
if (this.status === Status.Initializing) {
|
||||
await this.node.start();
|
||||
|
||||
log.debug(`dialing to the node with client's address: ` + this.node.peerId.toB58String());
|
||||
|
||||
try {
|
||||
await this.node.dial(this.address);
|
||||
} catch (e1) {
|
||||
const e = e1 as any;
|
||||
if (e.name === 'AggregateError' && e._errors.length === 1) {
|
||||
const error = e._errors[0];
|
||||
throw `Error dialing node ${this.address}:\n${error.code}\n${error.message}`;
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
this.node.handle([PROTOCOL_NAME], async ({ connection, stream }) => {
|
||||
pipe(stream.source, decode(), async (source: AsyncIterable<string>) => {
|
||||
for await (const msg of source) {
|
||||
try {
|
||||
const particle = parseParticle(msg);
|
||||
logParticle(log.debug, 'Particle is received:', particle);
|
||||
this.handleParticle(particle);
|
||||
} catch (e) {
|
||||
log.error('error on handling a new incoming message: ' + e);
|
||||
}
|
||||
res._lib2p2Peer.handle([PROTOCOL_NAME], async ({ connection, stream }) => {
|
||||
pipe(stream.source, decode(), async (source: AsyncIterable<string>) => {
|
||||
for await (const msg of source) {
|
||||
try {
|
||||
const particle = Particle.fromString(msg);
|
||||
options.onIncomingParticle(particle);
|
||||
} catch (e) {
|
||||
log.error('error on handling a new incoming message: ' + e);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
this.status = Status.Connected;
|
||||
} else {
|
||||
throw Error(`can't start receiving. Status: ${this.status}`);
|
||||
}
|
||||
}
|
||||
res._relayAddress = options.relayAddress;
|
||||
|
||||
private checkConnectedOrThrow() {
|
||||
if (this.status !== Status.Connected) {
|
||||
throw Error(`connection is in ${this.status} state`);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
async disconnect() {
|
||||
await this.node.stop();
|
||||
this.status = Status.Disconnected;
|
||||
await this._lib2p2Peer.stop();
|
||||
}
|
||||
|
||||
async sendParticle(particle: Particle): Promise<void> {
|
||||
this.checkConnectedOrThrow();
|
||||
public async sendParticle(particle: Particle): Promise<void> {
|
||||
particle.logTo('debug', 'sending particle:');
|
||||
|
||||
let action = toPayload(particle);
|
||||
let particleStr = JSON.stringify(action);
|
||||
logParticle(log.debug, 'send particle: \n', 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';
|
||||
}
|
||||
|
||||
// create outgoing substream
|
||||
const conn = (await this.node.dialProtocol(this.address, PROTOCOL_NAME)) as {
|
||||
stream;
|
||||
protocol: string;
|
||||
};
|
||||
const sink = this._connection.streams[0].sink;
|
||||
*/
|
||||
|
||||
const conn = await this._lib2p2Peer.dialProtocol(this._relayAddress, PROTOCOL_NAME);
|
||||
const sink = conn.stream.sink;
|
||||
|
||||
pipe(
|
||||
[Buffer.from(particleStr, 'utf8')],
|
||||
// at first, make a message varint
|
||||
// force new line
|
||||
[Buffer.from(particle.toString(), 'utf8')],
|
||||
encode(),
|
||||
conn.stream.sink,
|
||||
sink,
|
||||
);
|
||||
}
|
||||
|
||||
public 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) {
|
||||
const error = e._errors[0];
|
||||
throw `Error dialing node ${this._relayAddress}:\n${error.code}\n${error.message}`;
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private _lib2p2Peer: Lib2p2Peer;
|
||||
private _connection: Connection;
|
||||
private _relayAddress: Multiaddr;
|
||||
}
|
||||
|
@ -1,19 +1,42 @@
|
||||
import { AirInterpreter, CallServiceResult, LogLevel, ParticleHandler, SecurityTetraplet } from '@fluencelabs/avm';
|
||||
import log from 'loglevel';
|
||||
/*
|
||||
* Copyright 2021 Fluence Labs Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import {
|
||||
AirInterpreter,
|
||||
CallRequestsArray,
|
||||
CallResultsArray,
|
||||
InterpreterResult,
|
||||
LogLevel,
|
||||
CallServiceResult as AvmCallServiceResult,
|
||||
} from '@fluencelabs/avm';
|
||||
import { Multiaddr } from 'multiaddr';
|
||||
import PeerId from 'peer-id';
|
||||
import { CallServiceHandler } from './CallServiceHandler';
|
||||
import { CallServiceData, CallServiceResult, GenericCallServiceHandler, ResultCodes } from './commonTypes';
|
||||
import { CallServiceHandler as LegacyCallServiceHandler } from './compilerSupport/LegacyCallServiceHandler';
|
||||
import { PeerIdB58 } from './commonTypes';
|
||||
import makeDefaultClientHandler from './defaultClientHandler';
|
||||
import { FluenceConnection, FluenceConnectionOptions } from './FluenceConnection';
|
||||
import { logParticle, Particle } from './particle';
|
||||
import { FluenceConnection } from './FluenceConnection';
|
||||
import { Particle } from './Particle';
|
||||
import { KeyPair } from './KeyPair';
|
||||
import { RequestFlow } from './RequestFlow';
|
||||
import { loadRelayFn, loadVariablesService } from './RequestFlowBuilder';
|
||||
import { createInterpreter } from './utils';
|
||||
import { createInterpreter, dataToString } from './utils';
|
||||
import { filter, pipe, Subject, tap } from 'rxjs';
|
||||
import { RequestFlow } from './compilerSupport/v1';
|
||||
import log from 'loglevel';
|
||||
import { defaultServices } from './defaultServices';
|
||||
|
||||
/**
|
||||
* Node of the Fluence detwork specified as a pair of node's multiaddr and it's peer id
|
||||
* Node of the Fluence network specified as a pair of node's multiaddr and it's peer id
|
||||
*/
|
||||
type Node = {
|
||||
peerId: PeerIdB58;
|
||||
@ -26,6 +49,8 @@ type Node = {
|
||||
*/
|
||||
export type AvmLoglevel = LogLevel;
|
||||
|
||||
const DEFAULT_TTL = 7000;
|
||||
|
||||
/**
|
||||
* Configuration used when initiating Fluence Peer
|
||||
*/
|
||||
@ -123,15 +148,11 @@ export class FluencePeer {
|
||||
* Get the peer's status
|
||||
*/
|
||||
getStatus(): PeerStatus {
|
||||
let isConnected = false;
|
||||
if (this._connection) {
|
||||
isConnected = this._connection?.isConnected();
|
||||
}
|
||||
const hasKeyPair = this._keyPair !== undefined;
|
||||
return {
|
||||
isInitialized: hasKeyPair,
|
||||
isConnected: isConnected,
|
||||
peerId: this._selfPeerId,
|
||||
isConnected: this._connection !== undefined,
|
||||
peerId: this._keyPair?.Libp2pPeerId?.toB58String() || null,
|
||||
relayPeerId: this._relayPeerId || null,
|
||||
};
|
||||
}
|
||||
@ -148,30 +169,52 @@ export class FluencePeer {
|
||||
this._keyPair = await KeyPair.randomEd25519();
|
||||
}
|
||||
|
||||
await this._initAirInterpreter(config?.avmLogLevel || 'off');
|
||||
|
||||
this._callServiceHandler = makeDefaultClientHandler();
|
||||
this._interpreter = await createInterpreter(config?.avmLogLevel || 'off');
|
||||
|
||||
if (config?.connectTo) {
|
||||
let theAddress: Multiaddr;
|
||||
let connectToMultiAddr: Multiaddr;
|
||||
let fromNode = (config.connectTo as any).multiaddr;
|
||||
if (fromNode) {
|
||||
theAddress = new Multiaddr(fromNode);
|
||||
connectToMultiAddr = new Multiaddr(fromNode);
|
||||
} else {
|
||||
theAddress = new Multiaddr(config.connectTo as string);
|
||||
connectToMultiAddr = new Multiaddr(config.connectTo as string);
|
||||
}
|
||||
|
||||
await this._connect(theAddress);
|
||||
this._relayPeerId = connectToMultiAddr.getPeerId();
|
||||
|
||||
if (this._connection) {
|
||||
await this._connection.disconnect();
|
||||
}
|
||||
|
||||
this._connection = await FluenceConnection.createConnection({
|
||||
peerId: this._keyPair.Libp2pPeerId,
|
||||
relayAddress: connectToMultiAddr,
|
||||
dialTimeoutMs: config.dialTimeoutMs,
|
||||
onIncomingParticle: (p) => this._incomingParticles.next(p),
|
||||
});
|
||||
|
||||
await this._connect();
|
||||
}
|
||||
|
||||
this._legacyCallServiceHandler = new LegacyCallServiceHandler();
|
||||
registerDefaultServices(this);
|
||||
|
||||
this._startParticleProcessing();
|
||||
}
|
||||
|
||||
/**
|
||||
* Uninitializes the peer: stops all the underltying workflows, stops the Aqua VM
|
||||
* Un-initializes the peer: stops all the underlying workflows, stops the Aqua VM
|
||||
* and disconnects from the Fluence network
|
||||
*/
|
||||
async stop() {
|
||||
this._stopParticleProcessing();
|
||||
await this._disconnect();
|
||||
this._callServiceHandler = null;
|
||||
this._relayPeerId = null;
|
||||
this._legacyCallServiceHandler = null;
|
||||
|
||||
this._particleSpecificHandlers.clear();
|
||||
this._commonHandlers.clear();
|
||||
this._timeoutHandlers.clear();
|
||||
}
|
||||
|
||||
// internal api
|
||||
@ -181,8 +224,80 @@ export class FluencePeer {
|
||||
*/
|
||||
get internals() {
|
||||
return {
|
||||
initiateFlow: this._initiateFlow.bind(this),
|
||||
callServiceHandler: this._callServiceHandler,
|
||||
/**
|
||||
* Initiates a new particle execution starting from local peer
|
||||
* @param particle - particle to start execution of
|
||||
*/
|
||||
initiateParticle: (particle: Particle): void => {
|
||||
if (particle.initPeerId === undefined) {
|
||||
particle.initPeerId = this.getStatus().peerId;
|
||||
}
|
||||
|
||||
if (particle.ttl === undefined) {
|
||||
particle.ttl = DEFAULT_TTL;
|
||||
}
|
||||
|
||||
this._incomingParticles.next(particle);
|
||||
},
|
||||
/**
|
||||
* Register Call Service handler functions
|
||||
*/
|
||||
regHandler: {
|
||||
/**
|
||||
* Register handler for all particles
|
||||
*/
|
||||
common: (
|
||||
// force new line
|
||||
serviceId: string,
|
||||
fnName: string,
|
||||
handler: GenericCallServiceHandler,
|
||||
) => {
|
||||
this._commonHandlers.set(serviceFnKey(serviceId, fnName), handler);
|
||||
},
|
||||
/**
|
||||
* Register handler which will be called only for particle with the specific id
|
||||
*/
|
||||
forParticle: (
|
||||
particleId: string,
|
||||
serviceId: string,
|
||||
fnName: string,
|
||||
handler: GenericCallServiceHandler,
|
||||
) => {
|
||||
let psh = this._particleSpecificHandlers.get(particleId);
|
||||
if (psh === undefined) {
|
||||
psh = new Map<string, GenericCallServiceHandler>();
|
||||
this._particleSpecificHandlers.set(particleId, psh);
|
||||
}
|
||||
|
||||
psh.set(serviceFnKey(serviceId, fnName), handler);
|
||||
},
|
||||
/**
|
||||
* Register handler which will be called upon particle timeout
|
||||
*/
|
||||
timeout: (particleId: string, handler: () => void) => {
|
||||
this._timeoutHandlers.set(particleId, handler);
|
||||
},
|
||||
},
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
initiateFlow: (request: RequestFlow): void => {
|
||||
const particle = request.particle;
|
||||
|
||||
this._legacyParticleSpecificHandlers.set(particle.id, {
|
||||
handler: request.handler,
|
||||
error: request.error,
|
||||
timeout: request.timeout,
|
||||
});
|
||||
|
||||
this.internals.initiateParticle(particle);
|
||||
},
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
callServiceHandler: this._legacyCallServiceHandler,
|
||||
};
|
||||
}
|
||||
|
||||
@ -193,153 +308,274 @@ export class FluencePeer {
|
||||
*/
|
||||
private _isFluenceAwesome = true;
|
||||
|
||||
private async _initiateFlow(request: RequestFlow): Promise<void> {
|
||||
// setting `relayVariableName` here. If the client is not connected (i.e it is created as local) then there is no relay
|
||||
request.handler.on(loadVariablesService, loadRelayFn, () => {
|
||||
return this._relayPeerId || '';
|
||||
});
|
||||
await request.initState(this._keyPair.Libp2pPeerId);
|
||||
|
||||
logParticle(log.debug, 'executing local particle', request.getParticle());
|
||||
request.handler.combineWith(this._callServiceHandler);
|
||||
this._requests.set(request.id, request);
|
||||
|
||||
this._processRequest(request);
|
||||
}
|
||||
|
||||
private _callServiceHandler: CallServiceHandler;
|
||||
|
||||
private _keyPair: KeyPair;
|
||||
private _requests: Map<string, RequestFlow> = new Map();
|
||||
private _currentRequestId: string | null = null;
|
||||
private _watchdog;
|
||||
|
||||
private _connection: FluenceConnection;
|
||||
private _interpreter: AirInterpreter;
|
||||
|
||||
private async _initAirInterpreter(logLevel: AvmLoglevel): Promise<void> {
|
||||
this._interpreter = await createInterpreter(this._interpreterCallback.bind(this), this._selfPeerId, logLevel);
|
||||
}
|
||||
|
||||
private async _connect(multiaddr: Multiaddr, options?: FluenceConnectionOptions): Promise<void> {
|
||||
const nodePeerId = multiaddr.getPeerId();
|
||||
if (!nodePeerId) {
|
||||
throw Error("'multiaddr' did not contain a valid peer id");
|
||||
}
|
||||
|
||||
if (this._connection) {
|
||||
await this._connection.disconnect();
|
||||
}
|
||||
|
||||
const node = PeerId.createFromB58String(nodePeerId);
|
||||
const connection = new FluenceConnection(
|
||||
multiaddr,
|
||||
node,
|
||||
this._keyPair.Libp2pPeerId,
|
||||
this._executeIncomingParticle.bind(this),
|
||||
);
|
||||
await connection.connect(options);
|
||||
this._connection = connection;
|
||||
this._initWatchDog();
|
||||
// TODO:: make public when full connection\disconnection cycle is implemented properly
|
||||
private async _connect(): Promise<void> {
|
||||
return this._connection?.connect();
|
||||
}
|
||||
|
||||
// TODO:: make public when full connection\disconnection cycle is implemented properly
|
||||
private async _disconnect(): Promise<void> {
|
||||
if (this._connection) {
|
||||
await this._connection.disconnect();
|
||||
return this._connection.disconnect();
|
||||
}
|
||||
this._clearWathcDog();
|
||||
this._requests.forEach((r) => {
|
||||
r.cancel();
|
||||
}
|
||||
|
||||
// Queues for incoming and outgoing particles
|
||||
|
||||
private _incomingParticles = new Subject<Particle>();
|
||||
private _outgoingParticles = new Subject<Particle>();
|
||||
|
||||
// Call service handler
|
||||
|
||||
private _particleSpecificHandlers = new Map<string, Map<string, GenericCallServiceHandler>>();
|
||||
private _commonHandlers = new Map<string, GenericCallServiceHandler>();
|
||||
private _timeoutHandlers = new Map<string, () => void>();
|
||||
|
||||
// Internal peer state
|
||||
|
||||
private _relayPeerId: PeerIdB58 | null = null;
|
||||
private _keyPair: KeyPair;
|
||||
private _connection: FluenceConnection;
|
||||
private _interpreter: AirInterpreter;
|
||||
private _timeouts: Array<NodeJS.Timeout> = [];
|
||||
|
||||
private _startParticleProcessing() {
|
||||
const particleQueues = new Map<string, Subject<Particle>>();
|
||||
|
||||
this._incomingParticles
|
||||
.pipe(
|
||||
tap((x) => x.logTo('debug', 'particle received:')),
|
||||
filterExpiredParticles(),
|
||||
)
|
||||
.subscribe((p) => {
|
||||
let particlesQueue = particleQueues.get(p.id);
|
||||
|
||||
if (!particlesQueue) {
|
||||
particlesQueue = this._createParticlesProcessingQueue();
|
||||
particleQueues.set(p.id, particlesQueue);
|
||||
|
||||
const timeout = setTimeout(() => {
|
||||
log.debug(`particle ${p.id} has expired. Deleting particle-related queues and handlers`);
|
||||
|
||||
particleQueues.delete(p.id);
|
||||
const timeoutHandler = this._timeoutHandlers.get(p.id);
|
||||
if (timeoutHandler) {
|
||||
timeoutHandler();
|
||||
}
|
||||
this._particleSpecificHandlers.delete(p.id);
|
||||
this._timeoutHandlers.delete(p.id);
|
||||
}, p.actualTtl());
|
||||
|
||||
this._timeouts.push(timeout);
|
||||
}
|
||||
|
||||
particlesQueue.next(p);
|
||||
});
|
||||
|
||||
this._outgoingParticles.subscribe((p) => {
|
||||
this._connection.sendParticle(p);
|
||||
});
|
||||
}
|
||||
|
||||
private get _selfPeerId(): PeerIdB58 | null {
|
||||
return this._keyPair?.Libp2pPeerId?.toB58String() || null;
|
||||
private _createParticlesProcessingQueue() {
|
||||
let particlesQueue = new Subject<Particle>();
|
||||
let prevData: Uint8Array = Buffer.from([]);
|
||||
|
||||
particlesQueue
|
||||
.pipe(
|
||||
// force new line
|
||||
filterExpiredParticles(),
|
||||
)
|
||||
.subscribe((x) => {
|
||||
const result = runInterpreter(this.getStatus().peerId, this._interpreter, x, prevData);
|
||||
|
||||
prevData = Buffer.from(result.data);
|
||||
|
||||
// send particle further if requested
|
||||
if (result.nextPeerPks.length > 0) {
|
||||
const newParticle = x.clone();
|
||||
newParticle.data = prevData;
|
||||
this._outgoingParticles.next(newParticle);
|
||||
}
|
||||
|
||||
// execute call requests if needed
|
||||
// and put particle with the results back to queue
|
||||
if (result.callRequests.length > 0) {
|
||||
this._execCallRequests(x, result.callRequests).then((callResults) => {
|
||||
const newParticle = x.clone();
|
||||
newParticle.callResults = callResults;
|
||||
newParticle.data = Buffer.from([]);
|
||||
|
||||
particlesQueue.next(newParticle);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return particlesQueue;
|
||||
}
|
||||
|
||||
private get _relayPeerId(): PeerIdB58 | null {
|
||||
return this._connection?.nodePeerId?.toB58String() || null;
|
||||
}
|
||||
private async _execCallRequests(p: Particle, callRequests: CallRequestsArray): Promise<CallResultsArray> {
|
||||
// execute all requests asynchronously
|
||||
const promises = callRequests.map(([key, callRequest]) => {
|
||||
const req = {
|
||||
fnName: callRequest.functionName,
|
||||
args: callRequest.arguments,
|
||||
serviceId: callRequest.serviceId,
|
||||
tetraplets: callRequest.tetraplets,
|
||||
particleContext: p.getParticleContext(),
|
||||
};
|
||||
|
||||
private async _executeIncomingParticle(particle: Particle) {
|
||||
logParticle(log.debug, 'incoming particle received', particle);
|
||||
// execute single requests and catch possible errors
|
||||
const promise = this._execSingleCallRequest(req)
|
||||
.catch(
|
||||
(err): CallServiceResult => ({
|
||||
retCode: ResultCodes.exceptionInHandler,
|
||||
result: `Handler failed. fnName="${req.fnName}" serviceId="${
|
||||
req.serviceId
|
||||
}" error: ${err.toString()}`,
|
||||
}),
|
||||
)
|
||||
.then(
|
||||
(res): AvmCallServiceResult => ({
|
||||
result: JSON.stringify(res.result),
|
||||
retCode: res.retCode,
|
||||
}),
|
||||
)
|
||||
.then((res): [key: number, res: AvmCallServiceResult] => [key, res]);
|
||||
|
||||
let request = this._requests.get(particle.id);
|
||||
if (request) {
|
||||
await request.receiveUpdate(particle);
|
||||
} else {
|
||||
request = RequestFlow.createExternal(particle);
|
||||
request.handler.combineWith(this._callServiceHandler);
|
||||
}
|
||||
this._requests.set(request.id, request);
|
||||
|
||||
await this._processRequest(request);
|
||||
}
|
||||
|
||||
private _processRequest(request: RequestFlow) {
|
||||
try {
|
||||
this._currentRequestId = request.id;
|
||||
request.execute(this._interpreter, this._connection, this._relayPeerId);
|
||||
} catch (err) {
|
||||
log.error('particle processing failed: ' + err);
|
||||
} finally {
|
||||
this._currentRequestId = null;
|
||||
}
|
||||
}
|
||||
|
||||
private _interpreterCallback: ParticleHandler = (
|
||||
serviceId: string,
|
||||
fnName: string,
|
||||
args: any[],
|
||||
tetraplets: SecurityTetraplet[][],
|
||||
): CallServiceResult => {
|
||||
if (this._currentRequestId === null) {
|
||||
throw Error('current request can`t be null here');
|
||||
}
|
||||
|
||||
const request = this._requests.get(this._currentRequestId);
|
||||
const particle = request.getParticle();
|
||||
if (particle === null) {
|
||||
throw new Error("particle can't be null here, current request id: " + this._currentRequestId);
|
||||
}
|
||||
const res = request.handler.execute({
|
||||
serviceId,
|
||||
fnName,
|
||||
args,
|
||||
tetraplets,
|
||||
particleContext: {
|
||||
particleId: request.id,
|
||||
initPeerId: particle.init_peer_id,
|
||||
timestamp: particle.timestamp,
|
||||
ttl: particle.ttl,
|
||||
signature: particle.signature,
|
||||
},
|
||||
return promise;
|
||||
});
|
||||
// don't block
|
||||
const res = await Promise.all(promises);
|
||||
log.debug(`Executed call service for particle id=${p.id}, Call service results: `, res);
|
||||
return res;
|
||||
}
|
||||
|
||||
private async _execSingleCallRequest(req: CallServiceData): Promise<CallServiceResult> {
|
||||
const particleId = req.particleContext.particleId;
|
||||
|
||||
// trying particle-specific handler
|
||||
const lh = this._legacyParticleSpecificHandlers.get(particleId);
|
||||
let res: CallServiceResult = {
|
||||
result: undefined,
|
||||
retCode: undefined,
|
||||
};
|
||||
if (lh !== undefined) {
|
||||
res = lh.handler.execute(req);
|
||||
}
|
||||
|
||||
// if it didn't return any result trying to run the common handler
|
||||
if (res?.result === undefined) {
|
||||
res = this._legacyCallServiceHandler.execute(req);
|
||||
}
|
||||
|
||||
// No result from legacy handler.
|
||||
// Trying to execute async handler
|
||||
if (res.retCode === undefined) {
|
||||
const key = serviceFnKey(req.serviceId, req.fnName);
|
||||
const psh = this._particleSpecificHandlers.get(particleId);
|
||||
let handler: GenericCallServiceHandler;
|
||||
|
||||
// we should prioritize handler for this particle if there is one
|
||||
// if particle-specific handlers exist for this particle try getting handler there
|
||||
if (psh !== undefined) {
|
||||
handler = psh.get(key);
|
||||
}
|
||||
|
||||
// then try to find a common handler for all particles with this service-fn key
|
||||
// if there is no particle-specific handler, get one from common map
|
||||
if (handler === undefined) {
|
||||
handler = this._commonHandlers.get(key);
|
||||
}
|
||||
|
||||
// if we found a handler, execute it
|
||||
// otherwise return useful error message to AVM
|
||||
res = handler
|
||||
? await handler(req)
|
||||
: {
|
||||
retCode: ResultCodes.unknownError,
|
||||
result: `No handler has been registered for serviceId='${req.serviceId}' fnName='${req.fnName}' args='${req.args}'`,
|
||||
};
|
||||
}
|
||||
|
||||
if (res.result === undefined) {
|
||||
log.error(
|
||||
`Call to serviceId=${serviceId} fnName=${fnName} unexpectedly returned undefined result, falling back to null. Particle id=${request.id}`,
|
||||
);
|
||||
res.result = null;
|
||||
}
|
||||
|
||||
return {
|
||||
ret_code: res.retCode,
|
||||
result: JSON.stringify(res.result),
|
||||
};
|
||||
};
|
||||
|
||||
private _initWatchDog() {
|
||||
this._watchdog = setInterval(() => {
|
||||
for (let key in this._requests.keys) {
|
||||
if (this._requests.get(key).hasExpired()) {
|
||||
this._requests.delete(key);
|
||||
}
|
||||
}
|
||||
}, 5000); // TODO: make configurable
|
||||
return res;
|
||||
}
|
||||
|
||||
private _clearWathcDog() {
|
||||
clearInterval(this._watchdog);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
private _legacyParticleSpecificHandlers = new Map<
|
||||
string,
|
||||
{
|
||||
handler: LegacyCallServiceHandler;
|
||||
timeout?: () => void;
|
||||
error?: (reason?: any) => void;
|
||||
}
|
||||
>();
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
private _legacyCallServiceHandler: LegacyCallServiceHandler;
|
||||
}
|
||||
|
||||
function serviceFnKey(serviceId: string, fnName: string) {
|
||||
return `${serviceId}/${fnName}`;
|
||||
}
|
||||
|
||||
function registerDefaultServices(peer: FluencePeer) {
|
||||
for (let serviceId in defaultServices) {
|
||||
for (let fnName in defaultServices[serviceId]) {
|
||||
const h = defaultServices[serviceId][fnName];
|
||||
peer.internals.regHandler.common(serviceId, fnName, h);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function runInterpreter(
|
||||
currentPeerId: PeerIdB58,
|
||||
interpreter: AirInterpreter,
|
||||
particle: Particle,
|
||||
prevData: Uint8Array,
|
||||
): InterpreterResult {
|
||||
particle.logTo('debug', 'Sending particle to interpreter');
|
||||
log.debug('prevData: ', dataToString(prevData));
|
||||
log.debug('data: ', dataToString(particle.data));
|
||||
const interpreterResult = interpreter.invoke(
|
||||
particle.script,
|
||||
prevData,
|
||||
particle.data,
|
||||
{
|
||||
initPeerId: particle.initPeerId,
|
||||
currentPeerId: currentPeerId,
|
||||
},
|
||||
particle.callResults,
|
||||
);
|
||||
|
||||
const toLog: any = { ...interpreterResult };
|
||||
toLog.data = dataToString(toLog.data);
|
||||
log.debug('Interpreter result: ', toLog);
|
||||
return interpreterResult;
|
||||
}
|
||||
|
||||
function filterExpiredParticles() {
|
||||
return pipe(
|
||||
tap((p: Particle) => {
|
||||
if (p.hasExpired) {
|
||||
log.debug(`particle ${p.id} has expired`);
|
||||
}
|
||||
}),
|
||||
filter((x: Particle) => !x.hasExpired()),
|
||||
);
|
||||
}
|
||||
|
@ -15,7 +15,6 @@
|
||||
*/
|
||||
|
||||
import * as PeerId from 'peer-id';
|
||||
import * as base64 from 'base64-js';
|
||||
import { keys } from 'libp2p-crypto';
|
||||
|
||||
export class KeyPair {
|
||||
|
147
src/internal/Particle.ts
Normal file
147
src/internal/Particle.ts
Normal file
@ -0,0 +1,147 @@
|
||||
/*
|
||||
* Copyright 2020 Fluence Labs Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import { fromByteArray, toByteArray } from 'base64-js';
|
||||
import { CallResultsArray, LogLevel } from '@fluencelabs/avm';
|
||||
import log from 'loglevel';
|
||||
import { ParticleContext } from './commonTypes';
|
||||
import { dataToString } from './utils';
|
||||
|
||||
const DefaultTTL = 7000;
|
||||
|
||||
export class Particle {
|
||||
id: string;
|
||||
initPeerId: string;
|
||||
timestamp: number;
|
||||
ttl: number;
|
||||
script: string;
|
||||
signature: string;
|
||||
data: Uint8Array;
|
||||
callResults: CallResultsArray = [];
|
||||
|
||||
static createNew(script: string, ttlMs?: number): Particle {
|
||||
const res = new Particle();
|
||||
res.id = genUUID();
|
||||
res.script = script;
|
||||
res.ttl = ttlMs || DefaultTTL;
|
||||
res.data = Buffer.from([]);
|
||||
res.timestamp = Date.now();
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
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;
|
||||
res.signature = json.signature;
|
||||
res.data = toByteArray(json.data);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
getParticleContext(): ParticleContext {
|
||||
return {
|
||||
particleId: this.id,
|
||||
initPeerId: this.initPeerId,
|
||||
timestamp: this.timestamp,
|
||||
ttl: this.ttl,
|
||||
signature: this.signature,
|
||||
};
|
||||
}
|
||||
|
||||
actualTtl(): number {
|
||||
return this.timestamp + this.ttl - Date.now();
|
||||
}
|
||||
|
||||
hasExpired(): boolean {
|
||||
return this.actualTtl() <= 0;
|
||||
}
|
||||
|
||||
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;
|
||||
res.signature = this.signature;
|
||||
res.data = this.data;
|
||||
res.callResults = this.callResults;
|
||||
return res;
|
||||
}
|
||||
|
||||
toString(): string {
|
||||
const particle = this;
|
||||
const payload = {
|
||||
action: 'Particle',
|
||||
id: particle.id,
|
||||
init_peer_id: particle.initPeerId,
|
||||
timestamp: particle.timestamp,
|
||||
ttl: particle.ttl,
|
||||
script: particle.script,
|
||||
// TODO: copy signature from a particle after signatures will be implemented on nodes
|
||||
signature: [],
|
||||
data: fromByteArray(particle.data),
|
||||
};
|
||||
|
||||
return JSON.stringify(payload);
|
||||
}
|
||||
|
||||
logTo(level: LogLevel, message: string) {
|
||||
let fn;
|
||||
let data;
|
||||
switch (level) {
|
||||
case 'debug':
|
||||
fn = log.debug;
|
||||
data = dataToString(this.data);
|
||||
break;
|
||||
case 'error':
|
||||
fn = log.error;
|
||||
break;
|
||||
case 'info':
|
||||
fn = log.info;
|
||||
break;
|
||||
case 'trace':
|
||||
fn = log.trace;
|
||||
break;
|
||||
case 'warn':
|
||||
fn = log.warn;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
fn(message, {
|
||||
id: this.id,
|
||||
init_peer_id: this.initPeerId,
|
||||
timestamp: this.timestamp,
|
||||
ttl: this.ttl,
|
||||
script: this.script,
|
||||
signature: this.signature,
|
||||
data: data,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function genUUID() {
|
||||
return uuidv4();
|
||||
}
|
@ -1,201 +0,0 @@
|
||||
import log, { trace } from 'loglevel';
|
||||
import PeerId from 'peer-id';
|
||||
import { AirInterpreter } from '@fluencelabs/avm';
|
||||
import { CallServiceHandler } from './CallServiceHandler';
|
||||
import { PeerIdB58 } from './commonTypes';
|
||||
import { FluenceConnection } from './FluenceConnection';
|
||||
import { Particle, genUUID, logParticle } from './particle';
|
||||
import { ParticleDataToString } from './utils';
|
||||
|
||||
export const DEFAULT_TTL = 7000;
|
||||
|
||||
interface InterpreterOutcome {
|
||||
ret_code: number;
|
||||
data: Uint8Array;
|
||||
next_peer_pks: string[];
|
||||
error_message: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* The class represents the current view (and state) of distributed the particle execution process from client's point of view.
|
||||
* It stores the intermediate particles state during the process. RequestFlow is identified by the id of the particle that is executed during the flow.
|
||||
* Each RequestFlow contains a separate (unique to the current flow) CallServiceHandler where the handling of `call` AIR instruction takes place
|
||||
* Please note, that RequestFlow's is handler is combined with the handler from client before the execution occures.
|
||||
* After the combination middlewares from RequestFlow are executed before client handler's middlewares.
|
||||
*/
|
||||
export class RequestFlow {
|
||||
private state: Particle;
|
||||
private prevData: Uint8Array = Buffer.from([]);
|
||||
private onTimeoutHandlers = [];
|
||||
private onErrorHandlers = [];
|
||||
private timeoutHandle?: NodeJS.Timeout;
|
||||
|
||||
readonly id: string;
|
||||
readonly isExternal: boolean;
|
||||
readonly script: string;
|
||||
readonly handler = new CallServiceHandler();
|
||||
|
||||
ttl: number = DEFAULT_TTL;
|
||||
relayPeerId?: PeerIdB58;
|
||||
|
||||
static createExternal(particle: Particle): RequestFlow {
|
||||
const res = new RequestFlow(true, particle.id, particle.script);
|
||||
res.ttl = particle.ttl;
|
||||
res.state = particle;
|
||||
res.timeoutHandle = setTimeout(res.raiseTimeout.bind(res), particle.ttl);
|
||||
return res;
|
||||
}
|
||||
|
||||
static createLocal(script: string, ttl?: number): RequestFlow {
|
||||
const res = new RequestFlow(false, genUUID(), script);
|
||||
res.ttl = ttl ?? DEFAULT_TTL;
|
||||
return res;
|
||||
}
|
||||
|
||||
constructor(isExternal: boolean, id: string, script: string) {
|
||||
this.isExternal = isExternal;
|
||||
this.id = id;
|
||||
this.script = script;
|
||||
}
|
||||
|
||||
onTimeout(handler: () => void) {
|
||||
this.onTimeoutHandlers.push(handler);
|
||||
}
|
||||
|
||||
onError(handler: (error) => void) {
|
||||
this.onErrorHandlers.push(handler);
|
||||
}
|
||||
|
||||
async execute(interpreter: AirInterpreter, connection: FluenceConnection, relayPeerId?: PeerIdB58) {
|
||||
if (this.hasExpired()) {
|
||||
return;
|
||||
}
|
||||
|
||||
logParticle(log.debug, 'interpreter executing particle', this.getParticle());
|
||||
const interpreterOutcome = this.runInterpreter(interpreter);
|
||||
|
||||
log.debug('inner interpreter outcome:', {
|
||||
particleId: this.getParticle()?.id,
|
||||
ret_code: interpreterOutcome.ret_code,
|
||||
error_message: interpreterOutcome.error_message,
|
||||
next_peer_pks: interpreterOutcome.next_peer_pks,
|
||||
});
|
||||
|
||||
if (interpreterOutcome.ret_code !== 0) {
|
||||
this.raiseError(
|
||||
`Interpreter failed with code=${interpreterOutcome.ret_code} message=${interpreterOutcome.error_message}`,
|
||||
);
|
||||
}
|
||||
|
||||
const nextPeers = interpreterOutcome.next_peer_pks;
|
||||
|
||||
// do nothing if there are no peers to send particle further
|
||||
if (nextPeers.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// we only expect a single possible peer id to send particle further
|
||||
if (nextPeers.length > 1) {
|
||||
this.throwIncorrectNextPeerPks(nextPeers);
|
||||
}
|
||||
|
||||
// this peer id must be the relay, the client is connected to
|
||||
if (!relayPeerId || nextPeers[0] !== relayPeerId) {
|
||||
this.throwIncorrectNextPeerPks(nextPeers);
|
||||
}
|
||||
|
||||
if (!connection) {
|
||||
this.raiseError('Cannot send particle: non connected');
|
||||
return;
|
||||
}
|
||||
|
||||
this.sendIntoConnection(connection);
|
||||
}
|
||||
|
||||
public cancel() {
|
||||
if (this.timeoutHandle) {
|
||||
clearTimeout(this.timeoutHandle);
|
||||
}
|
||||
}
|
||||
|
||||
private throwIncorrectNextPeerPks(nextPeers: PeerIdB58[]) {
|
||||
this.raiseError(
|
||||
`Particle is expected to be sent to only the single peer (relay which client is connected to).
|
||||
particle id: ${this.getParticle()?.id}
|
||||
next peers: ${nextPeers.join(' ')}
|
||||
relay peer id: ${this.relayPeerId}
|
||||
`,
|
||||
);
|
||||
}
|
||||
|
||||
async initState(peerId: PeerId): Promise<void> {
|
||||
const id = this.id;
|
||||
let currentTime = Date.now();
|
||||
|
||||
const particle: Particle = {
|
||||
id: id,
|
||||
init_peer_id: peerId.toB58String(),
|
||||
timestamp: currentTime,
|
||||
ttl: this.ttl,
|
||||
script: this.script,
|
||||
signature: '',
|
||||
data: Buffer.from([]),
|
||||
};
|
||||
|
||||
this.state = particle;
|
||||
this.timeoutHandle = setTimeout(this.raiseTimeout.bind(this), particle.ttl);
|
||||
}
|
||||
|
||||
receiveUpdate(particle: Particle) {
|
||||
// TODO:: keep the history of particle data mb?
|
||||
this.prevData = this.state.data;
|
||||
this.state.data = particle.data;
|
||||
}
|
||||
|
||||
async sendIntoConnection(connection: FluenceConnection): Promise<void> {
|
||||
const particle = this.state;
|
||||
try {
|
||||
await connection.sendParticle(particle);
|
||||
} catch (err) {
|
||||
log.error(`Error on sending particle with id ${particle.id}: ${err}`);
|
||||
}
|
||||
}
|
||||
|
||||
runInterpreter(interpreter: AirInterpreter) {
|
||||
const interpreterOutcomeStr = interpreter.invoke(
|
||||
this.state.init_peer_id,
|
||||
this.state.script,
|
||||
this.prevData,
|
||||
this.state.data,
|
||||
);
|
||||
const interpreterOutcome: InterpreterOutcome = JSON.parse(interpreterOutcomeStr);
|
||||
// TODO:: keep the history of particle data mb?
|
||||
this.state.data = interpreterOutcome.data;
|
||||
return interpreterOutcome;
|
||||
}
|
||||
|
||||
getParticle = () => this.state;
|
||||
|
||||
hasExpired(): boolean {
|
||||
let now = Date.now();
|
||||
const particle = this.getParticle();
|
||||
let actualTtl = particle.timestamp + particle.ttl - now;
|
||||
return actualTtl <= 0;
|
||||
}
|
||||
|
||||
raiseError(error) {
|
||||
for (const h of this.onErrorHandlers) {
|
||||
h(error);
|
||||
}
|
||||
}
|
||||
|
||||
private raiseTimeout() {
|
||||
const now = Date.now();
|
||||
const particle = this.state;
|
||||
log.info(`Particle expired. Now: ${now}, ttl: ${particle?.ttl}, ts: ${particle?.timestamp}`);
|
||||
|
||||
for (const h of this.onTimeoutHandlers) {
|
||||
h();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,333 +0,0 @@
|
||||
import log from 'loglevel';
|
||||
import { CallServiceHandler, CallServiceResultType } from './CallServiceHandler';
|
||||
import { DEFAULT_TTL, RequestFlow } from './RequestFlow';
|
||||
|
||||
export const loadVariablesService = 'load';
|
||||
const loadVariablesFn = 'load_variable';
|
||||
export const loadRelayFn = 'load_relay';
|
||||
const xorHandleService = '__magic';
|
||||
const xorHandleFn = 'handle_xor';
|
||||
export const relayVariableName = 'init_relay';
|
||||
|
||||
const wrapWithXor = (script: string): string => {
|
||||
return `
|
||||
(xor
|
||||
${script}
|
||||
(xor
|
||||
(match ${relayVariableName} ""
|
||||
(call %init_peer_id% ("${xorHandleService}" "${xorHandleFn}") [%last_error%])
|
||||
)
|
||||
(seq
|
||||
(call ${relayVariableName} ("op" "identity") [])
|
||||
(call %init_peer_id% ("${xorHandleService}" "${xorHandleFn}") [%last_error%])
|
||||
)
|
||||
)
|
||||
)`;
|
||||
};
|
||||
|
||||
class ScriptBuilder {
|
||||
private script: string;
|
||||
private isXorInjected: boolean;
|
||||
private shouldInjectRelay: boolean;
|
||||
private variables: string[] = [];
|
||||
|
||||
constructor() {
|
||||
this.isXorInjected = false;
|
||||
this.shouldInjectRelay = false;
|
||||
}
|
||||
|
||||
raw(script: string): ScriptBuilder {
|
||||
this.script = script;
|
||||
return this;
|
||||
}
|
||||
|
||||
withInjectedVariables(fields: string[]): ScriptBuilder {
|
||||
this.variables = [...this.variables, ...fields];
|
||||
return this;
|
||||
}
|
||||
|
||||
wrappedWithXor(): ScriptBuilder {
|
||||
this.isXorInjected = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
withInjectedRelay(): ScriptBuilder {
|
||||
this.shouldInjectRelay = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
build(): string {
|
||||
let script = this.script;
|
||||
if (this.withInjectedVariables && this.withInjectedVariables.length > 0) {
|
||||
script = wrapWithVariableInjectionScript(script, this.variables);
|
||||
}
|
||||
if (this.isXorInjected) {
|
||||
script = wrapWithXor(script);
|
||||
}
|
||||
if (this.shouldInjectRelay) {
|
||||
script = wrapWithInjectRelayScript(script);
|
||||
}
|
||||
return script;
|
||||
}
|
||||
}
|
||||
|
||||
const wrapWithVariableInjectionScript = (script: string, fields: string[]): string => {
|
||||
fields.forEach((v) => {
|
||||
script = `
|
||||
(seq
|
||||
(call %init_peer_id% ("${loadVariablesService}" "${loadVariablesFn}") ["${v}"] ${v})
|
||||
${script}
|
||||
)`;
|
||||
});
|
||||
|
||||
return script;
|
||||
};
|
||||
|
||||
const wrapWithInjectRelayScript = (script: string): string => {
|
||||
return `
|
||||
(seq
|
||||
(call %init_peer_id% ("${loadVariablesService}" "${loadRelayFn}") [] ${relayVariableName})
|
||||
${script}
|
||||
)`;
|
||||
};
|
||||
|
||||
/**
|
||||
* Builder class for configuring and creating Request Flows
|
||||
*/
|
||||
export class RequestFlowBuilder {
|
||||
private shouldInjectVariables: boolean = true;
|
||||
private shouldInjectErrorHandling: boolean = true;
|
||||
private shouldInjectRelay: boolean = true;
|
||||
|
||||
private ttl: number = DEFAULT_TTL;
|
||||
private variables = new Map<string, CallServiceResultType>();
|
||||
private handlerConfigs: Array<(handler: CallServiceHandler, request: RequestFlow) => void> = [];
|
||||
private buildScriptActions: Array<(sb: ScriptBuilder) => void> = [];
|
||||
private onTimeout: () => void;
|
||||
private onError: (error: any) => void;
|
||||
|
||||
/**
|
||||
* Builds the Request flow with current configuration
|
||||
*/
|
||||
build() {
|
||||
if (this.shouldInjectRelay) {
|
||||
this.injectRelay();
|
||||
}
|
||||
if (this.shouldInjectVariables) {
|
||||
this.injectVariables();
|
||||
}
|
||||
if (this.shouldInjectErrorHandling) {
|
||||
this.wrapWithXor();
|
||||
}
|
||||
|
||||
const sb = new ScriptBuilder();
|
||||
for (let action of this.buildScriptActions) {
|
||||
action(sb);
|
||||
}
|
||||
let script = sb.build();
|
||||
|
||||
const res = RequestFlow.createLocal(script, this.ttl);
|
||||
|
||||
for (let h of this.handlerConfigs) {
|
||||
h(res.handler, res);
|
||||
}
|
||||
|
||||
if (this.onTimeout) {
|
||||
res.onTimeout(this.onTimeout);
|
||||
}
|
||||
if (this.onError) {
|
||||
res.onError(this.onError);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes necessary defaults when building requests by hand without the Aqua language compiler
|
||||
* Removed features include: relay and variable injection, error handling with top-level xor wrap
|
||||
*/
|
||||
disableInjections(): RequestFlowBuilder {
|
||||
this.shouldInjectRelay = false;
|
||||
this.shouldInjectVariables = false;
|
||||
this.shouldInjectErrorHandling = false;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Injects `init_relay` variable into the script
|
||||
*/
|
||||
injectRelay(): RequestFlowBuilder {
|
||||
this.configureScript((sb) => {
|
||||
sb.withInjectedRelay();
|
||||
});
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers services for variable injection. Required for variables registration to work
|
||||
*/
|
||||
injectVariables(): RequestFlowBuilder {
|
||||
this.configureScript((sb) => {
|
||||
sb.withInjectedVariables(Array.from(this.variables.keys()));
|
||||
});
|
||||
|
||||
this.configHandler((h) => {
|
||||
h.on(loadVariablesService, loadVariablesFn, (args, _) => {
|
||||
if (this.variables.has(args[0])) {
|
||||
return this.variables.get(args[0]);
|
||||
}
|
||||
|
||||
throw new Error(`failed to inject variable: ${args[0]}`);
|
||||
});
|
||||
});
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps the script with top-level error handling with xor instruction. Will raise error in the Request Flow in xor catches any error
|
||||
*/
|
||||
wrapWithXor(): RequestFlowBuilder {
|
||||
this.configureScript((sb) => {
|
||||
sb.wrappedWithXor();
|
||||
});
|
||||
|
||||
this.configHandler((h, request) => {
|
||||
h.onEvent(xorHandleService, xorHandleFn, (args) => {
|
||||
if (args[0] === undefined) {
|
||||
log.error(
|
||||
'Request flow error handler recieved unexpected argument, value of %last_error% is undefined',
|
||||
);
|
||||
}
|
||||
|
||||
try {
|
||||
request.raiseError(args[0]);
|
||||
} catch (e) {
|
||||
log.error('Error handling script executed with error', e);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Use ScriptBuilder provided by action in argument to configure script of the Request Flow
|
||||
*/
|
||||
configureScript(action: (sb: ScriptBuilder) => void): RequestFlowBuilder {
|
||||
this.buildScriptActions.push(action);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Use raw text as script for the Request Flow
|
||||
*/
|
||||
withRawScript(script: string): RequestFlowBuilder {
|
||||
this.buildScriptActions.push((sb) => {
|
||||
sb.raw(script);
|
||||
});
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify time to live for the request
|
||||
*/
|
||||
withTTL(ttl?: number): RequestFlowBuilder {
|
||||
if (ttl) {
|
||||
this.ttl = ttl;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure local call handler for the Request Flow
|
||||
*/
|
||||
configHandler(config: (handler: CallServiceHandler, request: RequestFlow) => void): RequestFlowBuilder {
|
||||
this.handlerConfigs.push(config);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies handler for the particle timeout event
|
||||
*/
|
||||
handleTimeout(handler: () => void): RequestFlowBuilder {
|
||||
this.onTimeout = handler;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies handler for any script errors
|
||||
*/
|
||||
handleScriptError(handler: (error) => void): RequestFlowBuilder {
|
||||
this.onError = handler;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a variable to the list of injected variables
|
||||
*/
|
||||
withVariable(name: string, value: CallServiceResultType): RequestFlowBuilder {
|
||||
this.variables.set(name, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a multiple variable to the list of injected variables.
|
||||
* Variables can be specified in form of either object or a map where keys correspond to variable names
|
||||
*/
|
||||
withVariables(
|
||||
data: Map<string, CallServiceResultType> | Record<string, CallServiceResultType>,
|
||||
): RequestFlowBuilder {
|
||||
if (data instanceof Map) {
|
||||
this.variables = new Map([...Array.from(this.variables.entries()), ...Array.from(data.entries())]);
|
||||
} else {
|
||||
for (let k in data) {
|
||||
this.variables.set(k, data[k]);
|
||||
}
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the Request flow with current configuration with a fetch-single-result semantics
|
||||
* returns a tuple of [RequestFlow, promise] where promise is a fetch-like promise resolved when
|
||||
* the execution hits callback service and rejected when particle times out or any error happens
|
||||
*/
|
||||
buildAsFetch<T>(
|
||||
callbackServiceId: string = 'callback',
|
||||
callbackFnName: string = 'callback',
|
||||
): [RequestFlow, Promise<T>] {
|
||||
const fetchPromise = new Promise<T>((resolve, reject) => {
|
||||
this.handlerConfigs.push((h) => {
|
||||
h.onEvent(callbackServiceId, callbackFnName, (args, _) => {
|
||||
resolve(args as any);
|
||||
});
|
||||
});
|
||||
|
||||
this.handleTimeout(() => {
|
||||
reject(`Timed out after ${this.ttl}ms`);
|
||||
});
|
||||
|
||||
this.handleScriptError((e) => {
|
||||
reject(e);
|
||||
});
|
||||
});
|
||||
|
||||
return [this.build(), fetchPromise];
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the Request flow with current configuration with error handling
|
||||
* returns a tuple of [RequestFlow, promise]. The promise is never resolved and rejected in case of any error in the script
|
||||
*/
|
||||
buildWithErrorHandling(): [RequestFlow, Promise<void>] {
|
||||
const promise = new Promise<void>((resolve, reject) => {
|
||||
this.handleScriptError(reject);
|
||||
});
|
||||
|
||||
return [this.build(), promise];
|
||||
}
|
||||
}
|
@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { SecurityTetraplet } from '@fluencelabs/avm';
|
||||
import { CallRequest, SecurityTetraplet } from '@fluencelabs/avm';
|
||||
|
||||
/**
|
||||
* Peer ID's id as a base58 string (multihash/CIDv0).
|
||||
@ -39,7 +39,7 @@ export interface CallParams<ArgName extends string | null> {
|
||||
/**
|
||||
* Particle's timestamp when it was created
|
||||
*/
|
||||
timeStamp: number;
|
||||
timestamp: number;
|
||||
|
||||
/**
|
||||
* Time to live in milliseconds. The time after the particle should be expired
|
||||
@ -56,3 +56,78 @@ export interface CallParams<ArgName extends string | null> {
|
||||
*/
|
||||
tetraplets: { [key in ArgName]: SecurityTetraplet[] };
|
||||
}
|
||||
|
||||
export enum ResultCodes {
|
||||
success = 0,
|
||||
unknownError = 1,
|
||||
exceptionInHandler = 2,
|
||||
}
|
||||
|
||||
/**
|
||||
* Particle context. Contains additional information about particle which triggered `call` air instruction from AVM
|
||||
*/
|
||||
export interface ParticleContext {
|
||||
/**
|
||||
* The particle ID
|
||||
*/
|
||||
particleId: string;
|
||||
initPeerId: PeerIdB58;
|
||||
timestamp: number;
|
||||
ttl: number;
|
||||
signature: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the information passed from AVM when a `call` air instruction is executed on the local peer
|
||||
*/
|
||||
export interface CallServiceData {
|
||||
/**
|
||||
* Service ID as specified in `call` air instruction
|
||||
*/
|
||||
serviceId: string;
|
||||
|
||||
/**
|
||||
* Function name as specified in `call` air instruction
|
||||
*/
|
||||
fnName: string;
|
||||
|
||||
/**
|
||||
* Arguments as specified in `call` air instruction
|
||||
*/
|
||||
args: any[];
|
||||
|
||||
/**
|
||||
* Security Tetraplets received from AVM
|
||||
*/
|
||||
tetraplets: SecurityTetraplet[][];
|
||||
|
||||
/**
|
||||
* Particle context, @see {@link ParticleContext}
|
||||
*/
|
||||
particleContext: ParticleContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Type for all the possible objects that can be return to the AVM
|
||||
*/
|
||||
export type CallServiceResultType = object | boolean | number | string | null;
|
||||
|
||||
/**
|
||||
* Generic call service handler
|
||||
*/
|
||||
export type GenericCallServiceHandler = (req: CallServiceData) => CallServiceResult | Promise<CallServiceResult>;
|
||||
|
||||
/**
|
||||
* Represents the result of the `call` air instruction to be returned into AVM
|
||||
*/
|
||||
export interface CallServiceResult {
|
||||
/**
|
||||
* Return code to be returned to AVM
|
||||
*/
|
||||
retCode: ResultCodes;
|
||||
|
||||
/**
|
||||
* Result object to be returned to AVM
|
||||
*/
|
||||
result: CallServiceResultType;
|
||||
}
|
||||
|
@ -1,82 +1,58 @@
|
||||
import { SecurityTetraplet } from '@fluencelabs/avm';
|
||||
import { PeerIdB58 } from './commonTypes';
|
||||
|
||||
export enum ResultCodes {
|
||||
success = 0,
|
||||
unkownError = 1,
|
||||
exceptionInHandler = 2,
|
||||
}
|
||||
|
||||
/**
|
||||
* Particle context. Contains additional information about particle which triggered `call` air instruction from AVM
|
||||
/*
|
||||
* Copyright 2021 Fluence Labs Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
interface ParticleContext {
|
||||
/**
|
||||
* The particle ID
|
||||
*/
|
||||
particleId: string;
|
||||
initPeerId: PeerIdB58;
|
||||
timestamp: number;
|
||||
ttl: number;
|
||||
signature: string;
|
||||
}
|
||||
|
||||
import { CallServiceData, CallServiceResult, CallServiceResultType, ResultCodes } from '../commonTypes';
|
||||
|
||||
/**
|
||||
* Represents the information passed from AVM when a `call` air instruction is executed on the local peer
|
||||
* @deprecated This class exists to glue legacy RequestFlowBuilder api with restructured async FluencePeer.
|
||||
* v2 version of compiler support should be used instead
|
||||
*/
|
||||
export interface CallServiceData {
|
||||
/**
|
||||
* Service ID as specified in `call` air instruction
|
||||
*/
|
||||
serviceId: string;
|
||||
export const callLegacyCallServiceHandler = (
|
||||
req: CallServiceData,
|
||||
commonHandler: CallServiceHandler,
|
||||
particleSpecificHandler?: CallServiceHandler,
|
||||
): CallServiceResult => {
|
||||
// trying particle-specific handler
|
||||
if (particleSpecificHandler !== undefined) {
|
||||
var res = particleSpecificHandler.execute(req);
|
||||
}
|
||||
|
||||
/**
|
||||
* Function name as specified in `call` air instruction
|
||||
*/
|
||||
fnName: string;
|
||||
if (res?.result === undefined) {
|
||||
// if it didn't return any result trying to run the common handler
|
||||
res = commonHandler.execute(req);
|
||||
}
|
||||
|
||||
/**
|
||||
* Arguments as specified in `call` air instruction
|
||||
*/
|
||||
args: any[];
|
||||
if (res.retCode === undefined) {
|
||||
res = {
|
||||
retCode: ResultCodes.unknownError,
|
||||
result: `The handler did not set any result. Make sure you are calling the right peer and the handler has been registered. Original request data was: serviceId='${req.serviceId}' fnName='${req.fnName}' args='${req.args}'`,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Security Tetraplets recieved from AVM
|
||||
*/
|
||||
tetraplets: SecurityTetraplet[][];
|
||||
if (res.result === undefined) {
|
||||
res.result = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Particle context, @see {@link ParticleContext}
|
||||
*/
|
||||
particleContext: ParticleContext;
|
||||
|
||||
[x: string]: any;
|
||||
}
|
||||
|
||||
/**
|
||||
* Type for all the possible ovjects that can be return to the AVM
|
||||
*/
|
||||
export type CallServiceResultType = object | boolean | number | string | null;
|
||||
|
||||
/**
|
||||
* Represents the result of the `call` air instruction to be returned into AVM
|
||||
*/
|
||||
export interface CallServiceResult {
|
||||
/**
|
||||
* Return code to be returned to AVM
|
||||
*/
|
||||
retCode: ResultCodes;
|
||||
|
||||
/**
|
||||
* Result object to be returned to AVM
|
||||
*/
|
||||
result: CallServiceResultType;
|
||||
[x: string]: any;
|
||||
}
|
||||
return res;
|
||||
};
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
* Type for the middleware used in CallServiceHandler middleware chain.
|
||||
* In a nutshell middelware is a function of request, response and function to trigger the next middleware in chain.
|
||||
* In a nutshell middleware is a function of request, response and function to trigger the next middleware in chain.
|
||||
* Each middleware is free to write additional properties to either request or response object.
|
||||
* When the chain finishes the response is passed back to AVM
|
||||
* @param { CallServiceData } req - information about the air `call` instruction
|
||||
@ -85,22 +61,14 @@ export interface CallServiceResult {
|
||||
*/
|
||||
export type Middleware = (req: CallServiceData, resp: CallServiceResult, next: Function) => void;
|
||||
|
||||
export class CallServiceArg<T> {
|
||||
val: T;
|
||||
tetraplet: SecurityTetraplet[];
|
||||
|
||||
constructor(val: T, tetraplet: SecurityTetraplet[]) {
|
||||
this.val = val;
|
||||
this.tetraplet = tetraplet;
|
||||
}
|
||||
}
|
||||
|
||||
type CallParams = ParticleContext & {
|
||||
wrappedArgs: CallServiceArg<any>[];
|
||||
};
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
type CallParams = any;
|
||||
|
||||
/**
|
||||
* Convenience middleware factory. Registeres a handler for a pair of 'serviceId/fnName'.
|
||||
* @deprecated
|
||||
* Convenience middleware factory. Registers a handler for a pair of 'serviceId/fnName'.
|
||||
* The return value of the handler is passed back to AVM
|
||||
* @param { string } serviceId - The identifier of service which would be used to make calls from AVM
|
||||
* @param { string } fnName - The identifier of function which would be used to make calls from AVM
|
||||
@ -113,7 +81,7 @@ export const fnHandler = (
|
||||
) => {
|
||||
return (req: CallServiceData, resp: CallServiceResult, next: Function): void => {
|
||||
if (req.fnName === fnName && req.serviceId === serviceId) {
|
||||
const res = handler(req.args, { ...req.particleContext, wrappedArgs: req.wrappedArgs });
|
||||
const res = handler(req.args, req.particleContext);
|
||||
resp.retCode = ResultCodes.success;
|
||||
resp.result = res;
|
||||
}
|
||||
@ -122,7 +90,8 @@ export const fnHandler = (
|
||||
};
|
||||
|
||||
/**
|
||||
* Convenience middleware factory. Registeres a handler for a pair of 'serviceId/fnName'.
|
||||
* @deprecated
|
||||
* Convenience middleware factory. Registers a handler for a pair of 'serviceId/fnName'.
|
||||
* Similar to @see { @link fnHandler } but instead returns and empty object immediately runs the handler asynchronously
|
||||
* @param { string } serviceId - The identifier of service which would be used to make calls from AVM
|
||||
* @param { string } fnName - The identifier of function which would be used to make calls from AVM
|
||||
@ -136,7 +105,7 @@ export const fnAsEventHandler = (
|
||||
return (req: CallServiceData, resp: CallServiceResult, next: Function): void => {
|
||||
if (req.fnName === fnName && req.serviceId === serviceId) {
|
||||
setTimeout(() => {
|
||||
handler(req.args, { ...req.particleContext, wrappedArgs: req.wrappedArgs });
|
||||
handler(req.args, req.particleContext);
|
||||
}, 0);
|
||||
|
||||
resp.retCode = ResultCodes.success;
|
||||
@ -146,10 +115,14 @@ export const fnAsEventHandler = (
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
type CallServiceFunction = (req: CallServiceData, resp: CallServiceResult) => void;
|
||||
|
||||
/**
|
||||
* Class defines the handling of a `call` air intruction executed by AVM on the local peer.
|
||||
* @deprecated
|
||||
* Class defines the handling of a `call` air instruction executed by AVM on the local peer.
|
||||
* All the execution process is defined by the chain of middlewares - architecture popular among backend web frameworks.
|
||||
* Each middleware has the form of `(req: Call, resp: CallServiceResult, next: Function) => void;`
|
||||
* A handler starts with an empty middleware chain and does nothing.
|
||||
@ -180,7 +153,7 @@ export class CallServiceHandler {
|
||||
}
|
||||
|
||||
/**
|
||||
* Combine handler with another one. Combintaion is done by copying middleware chain from the argument's handler into current one.
|
||||
* Combine handler with another one. Combination is done by copying middleware chain from the argument's handler into current one.
|
||||
* Please note, that current handler's middlewares take precedence over the ones from handler to be combined with
|
||||
* @param { CallServiceHandler } other - CallServiceHandler to be combined with
|
||||
*/
|
||||
@ -190,7 +163,7 @@ export class CallServiceHandler {
|
||||
}
|
||||
|
||||
/**
|
||||
* Convinience method for registring @see { @link fnHandler } middleware
|
||||
* Convenience method for registering @see { @link fnHandler } middleware
|
||||
*/
|
||||
on(
|
||||
serviceId: string, // force format
|
||||
@ -205,7 +178,7 @@ export class CallServiceHandler {
|
||||
}
|
||||
|
||||
/**
|
||||
* Convinience method for registring @see { @link fnAsEventHandler } middleware
|
||||
* Convenience method for registering @see { @link fnAsEventHandler } middleware
|
||||
*/
|
||||
onEvent(
|
||||
serviceId: string, // force format
|
||||
@ -240,8 +213,8 @@ export class CallServiceHandler {
|
||||
*/
|
||||
execute(req: CallServiceData): CallServiceResult {
|
||||
const res: CallServiceResult = {
|
||||
retCode: ResultCodes.unkownError,
|
||||
result: `The handler did not set any result. Make sure you are calling the right peer and the handler has been registered. Original request data was: serviceId='${req.serviceId}' fnName='${req.fnName}' args='${req.args}'`,
|
||||
retCode: undefined,
|
||||
result: undefined,
|
||||
};
|
||||
this.buildFunction()(req, res);
|
||||
return res;
|
@ -1,5 +1,87 @@
|
||||
/*
|
||||
* Copyright 2021 Fluence Labs Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { CallServiceHandler } from './LegacyCallServiceHandler';
|
||||
import { Particle } from '../Particle';
|
||||
|
||||
export { FluencePeer } from '../FluencePeer';
|
||||
export { ResultCodes } from '../../internal/CallServiceHandler';
|
||||
export { RequestFlow } from '../../internal/RequestFlow';
|
||||
export { RequestFlowBuilder } from '../../internal/RequestFlowBuilder';
|
||||
export { CallParams } from '../commonTypes';
|
||||
export { CallParams, ResultCodes } from '../commonTypes';
|
||||
|
||||
/**
|
||||
* @deprecated This class exists to glue legacy RequestFlowBuilder api with restructured async FluencePeer.
|
||||
* v2 version of compiler support should be used instead
|
||||
*/
|
||||
export interface RequestFlow {
|
||||
particle: Particle;
|
||||
handler: CallServiceHandler;
|
||||
timeout?: () => void;
|
||||
error?: (reason?: any) => void;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated This class exists to glue legacy RequestFlowBuilder api with restructured async FluencePeer.
|
||||
* v2 version of compiler support should be used instead
|
||||
*/
|
||||
export class RequestFlowBuilder {
|
||||
private _ttl?: number;
|
||||
private _script?: string;
|
||||
private _configs: any = [];
|
||||
private _error: (reason?: any) => void = () => {};
|
||||
private _timeout: () => void = () => {};
|
||||
|
||||
build(): RequestFlow {
|
||||
let h = new CallServiceHandler();
|
||||
for (let c of this._configs) {
|
||||
c(h);
|
||||
}
|
||||
|
||||
return {
|
||||
particle: Particle.createNew(this._script!, this._ttl),
|
||||
handler: h,
|
||||
timeout: this._timeout,
|
||||
error: this._error,
|
||||
};
|
||||
}
|
||||
|
||||
withTTL(ttl: number): RequestFlowBuilder {
|
||||
this._ttl = ttl;
|
||||
return this;
|
||||
}
|
||||
|
||||
handleTimeout(timeout: () => void): RequestFlowBuilder {
|
||||
this._timeout = timeout;
|
||||
return this;
|
||||
}
|
||||
|
||||
handleScriptError(reject: (reason?: any) => void): RequestFlowBuilder {
|
||||
this._error = reject;
|
||||
return this;
|
||||
}
|
||||
|
||||
withRawScript(script: string): RequestFlowBuilder {
|
||||
this._script = script;
|
||||
return this;
|
||||
}
|
||||
|
||||
disableInjections(): RequestFlowBuilder {
|
||||
return this;
|
||||
}
|
||||
|
||||
configHandler(h: (handler: CallServiceHandler) => void) {
|
||||
this._configs.push(h);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
518
src/internal/compilerSupport/v2.ts
Normal file
518
src/internal/compilerSupport/v2.ts
Normal file
@ -0,0 +1,518 @@
|
||||
/*
|
||||
* Copyright 2021 Fluence Labs Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { SecurityTetraplet } from '@fluencelabs/avm';
|
||||
import { match } from 'ts-pattern';
|
||||
import { CallParams, Fluence, FluencePeer } from '../../index';
|
||||
import { CallServiceData, GenericCallServiceHandler, CallServiceResult, ResultCodes } from '../commonTypes';
|
||||
import { Particle } from '../Particle';
|
||||
|
||||
export { FluencePeer } from '../FluencePeer';
|
||||
export { CallParams } from '../commonTypes';
|
||||
|
||||
/**
|
||||
* Represents the Aqua Option type
|
||||
*/
|
||||
type OptionalType = {
|
||||
/**
|
||||
* Type descriptor. Used for pattern-matching
|
||||
*/
|
||||
tag: 'optional';
|
||||
};
|
||||
|
||||
/**
|
||||
* Represents the void type for functions and callbacks with no return value
|
||||
*/
|
||||
type VoidType = {
|
||||
/**
|
||||
* Type descriptor. Used for pattern-matching
|
||||
*/
|
||||
tag: 'void';
|
||||
};
|
||||
|
||||
/**
|
||||
* Represents all types other than Optional, Void, Callback and MultiReturn
|
||||
*/
|
||||
type PrimitiveType = {
|
||||
/**
|
||||
* Type descriptor. Used for pattern-matching
|
||||
*/
|
||||
tag: 'primitive';
|
||||
};
|
||||
|
||||
/**
|
||||
* Represents callbacks used in Aqua function arguments (`func` instruction)
|
||||
*/
|
||||
type CallbackType = {
|
||||
/**
|
||||
* Type descriptor. Used for pattern-matching
|
||||
*/
|
||||
tag: 'callback';
|
||||
|
||||
/**
|
||||
* Callback definition
|
||||
*/
|
||||
callback: CallbackDef<OptionalType | PrimitiveType, VoidType | OptionalType | PrimitiveType>;
|
||||
};
|
||||
|
||||
/**
|
||||
* Represents the return type for functions which return multiple values
|
||||
*/
|
||||
type MultiReturnType = {
|
||||
/**
|
||||
* Type descriptor. Used for pattern-matching
|
||||
*/
|
||||
tag: 'multiReturn';
|
||||
|
||||
/**
|
||||
* The description of types of the return values: Array of either primitive or optional types
|
||||
*/
|
||||
returnItems: Array<OptionalType | PrimitiveType>;
|
||||
};
|
||||
|
||||
interface ArgDef<ArgType> {
|
||||
/**
|
||||
* The name of the argument in Aqua language
|
||||
*/
|
||||
name: string;
|
||||
|
||||
/**
|
||||
* The type of the argument
|
||||
*/
|
||||
argType: ArgType;
|
||||
}
|
||||
|
||||
interface CallbackDef<ArgType, ReturnType> {
|
||||
/**
|
||||
* Callback argument definitions: the list of ArgDefs
|
||||
*/
|
||||
argDefs: Array<ArgDef<ArgType>>;
|
||||
|
||||
/**
|
||||
* Definition of the return type of callback
|
||||
*/
|
||||
returnType: ReturnType;
|
||||
}
|
||||
|
||||
interface FunctionBodyDef
|
||||
extends CallbackDef<
|
||||
// force new line
|
||||
OptionalType | PrimitiveType,
|
||||
VoidType | OptionalType | PrimitiveType
|
||||
> {
|
||||
/**
|
||||
* The name of the function in Aqua language
|
||||
*/
|
||||
functionName: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Definition of function (`func` instruction) generated by the Aqua compiler
|
||||
*/
|
||||
interface FunctionCallDef
|
||||
extends CallbackDef<
|
||||
OptionalType | PrimitiveType | CallbackType,
|
||||
VoidType | OptionalType | PrimitiveType | MultiReturnType
|
||||
> {
|
||||
/**
|
||||
* The name of the function in Aqua language
|
||||
*/
|
||||
functionName: string;
|
||||
|
||||
/**
|
||||
* Names of the different entities used in generated air script
|
||||
*/
|
||||
names: {
|
||||
/**
|
||||
* The name of the relay variable
|
||||
*/
|
||||
relay: string;
|
||||
|
||||
/**
|
||||
* The name of the serviceId used load variables at the beginning of the script
|
||||
*/
|
||||
getDataSrv: string;
|
||||
|
||||
/**
|
||||
* The name of serviceId is used to execute callbacks for the current particle
|
||||
*/
|
||||
callbackSrv: string;
|
||||
|
||||
/**
|
||||
* The name of the serviceId which is called to propagate return value to the generated function caller
|
||||
*/
|
||||
responseSrv: string;
|
||||
|
||||
/**
|
||||
* The name of the functionName which is called to propagate return value to the generated function caller
|
||||
*/
|
||||
responseFnName: string;
|
||||
|
||||
/**
|
||||
* The name of the serviceId which is called to report errors to the generated function caller
|
||||
*/
|
||||
errorHandlingSrv: string;
|
||||
|
||||
/**
|
||||
* The name of the functionName which is called to report errors to the generated function caller
|
||||
*/
|
||||
errorFnName: string;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Definition of service registration function (`service` instruction) generated by the Aqua compiler
|
||||
*/
|
||||
interface ServiceDef {
|
||||
/**
|
||||
* Default service id. If the service has no default id the value should be undefined
|
||||
*/
|
||||
defaultServiceId?: string;
|
||||
|
||||
/**
|
||||
* List of functions which the service consists of
|
||||
*/
|
||||
functions: Array<FunctionBodyDef>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience function to support Aqua `func` generation backend
|
||||
* The compiler only need to generate a call the function and provide the corresponding definitions and the air script
|
||||
*
|
||||
* @param rawFnArgs - raw arguments passed by user to the generated function
|
||||
* @param def - function definition generated by the Aqua compiler
|
||||
* @param script - air script with function execution logic generated by the Aqua compiler
|
||||
*/
|
||||
export function callFunction(rawFnArgs: Array<any>, def: FunctionCallDef, script: string) {
|
||||
const { args, peer, config } = extractFunctionArgs(rawFnArgs, def.argDefs.length);
|
||||
|
||||
if (args.length !== def.argDefs.length) {
|
||||
throw new Error('Incorrect number of arguments. Expecting ${def.argDefs.length}');
|
||||
}
|
||||
|
||||
const promise = new Promise((resolve, reject) => {
|
||||
const particle = Particle.createNew(script, config?.ttl);
|
||||
|
||||
for (let i = 0; i < def.argDefs.length; i++) {
|
||||
const argDef = def.argDefs[i];
|
||||
const arg = args[i];
|
||||
|
||||
const [serviceId, fnName, cb] = match(argDef.argType)
|
||||
// for callback arguments we are registering particle-specific callback which executes the passed function
|
||||
.with({ tag: 'callback' }, (callbackDef) => {
|
||||
const fn = async (req: CallServiceData): Promise<CallServiceResult> => {
|
||||
const args = convertArgsFromReqToUserCall(req, callbackDef.callback.argDefs);
|
||||
// arg is function at this point
|
||||
const result = await arg.apply(null, args);
|
||||
let res;
|
||||
switch (callbackDef.callback.returnType.tag) {
|
||||
case 'void':
|
||||
res = {};
|
||||
break;
|
||||
case 'primitive':
|
||||
res = result;
|
||||
break;
|
||||
case 'optional':
|
||||
res = tsToAquaOpt(result);
|
||||
break;
|
||||
}
|
||||
return {
|
||||
retCode: ResultCodes.success,
|
||||
result: res,
|
||||
};
|
||||
};
|
||||
return [def.names.callbackSrv, argDef.name, fn] as const;
|
||||
})
|
||||
// for optional types we are converting value to array representation in air
|
||||
.with({ tag: 'optional' }, () => {
|
||||
const fn = (req: CallServiceData): CallServiceResult => {
|
||||
// arg is optional at this point
|
||||
const res = tsToAquaOpt(arg);
|
||||
return {
|
||||
retCode: ResultCodes.success,
|
||||
result: res,
|
||||
};
|
||||
};
|
||||
return [def.names.getDataSrv, argDef.name, fn] as const;
|
||||
})
|
||||
// for primitive types wre are simply passing the value
|
||||
.with({ tag: 'primitive' }, () => {
|
||||
// arg is primitive at this point
|
||||
const fn = (req: CallServiceData): CallServiceResult => ({
|
||||
retCode: ResultCodes.success,
|
||||
result: arg,
|
||||
});
|
||||
return [def.names.getDataSrv, argDef.name, fn] as const;
|
||||
})
|
||||
.exhaustive();
|
||||
|
||||
// registering handlers for every argument of the function
|
||||
peer.internals.regHandler.forParticle(particle.id, serviceId, fnName, cb);
|
||||
}
|
||||
|
||||
// registering handler for function response
|
||||
peer.internals.regHandler.forParticle(particle.id, def.names.responseSrv, def.names.responseFnName, (req) => {
|
||||
const userFunctionReturn = match(def.returnType)
|
||||
.with({ tag: 'primitive' }, () => req.args[0])
|
||||
.with({ tag: 'optional' }, () => aquaOptToTs(req.args[0]))
|
||||
.with({ tag: 'void' }, () => undefined)
|
||||
.with({ tag: 'multiReturn' }, (mr) => {
|
||||
return mr.returnItems.map((x, index) => {
|
||||
return match(x)
|
||||
.with({ tag: 'optional' }, () => aquaOptToTs(req.args[index]))
|
||||
.with({ tag: 'primitive' }, () => req.args[index])
|
||||
.exhaustive();
|
||||
});
|
||||
})
|
||||
.exhaustive();
|
||||
|
||||
setTimeout(() => {
|
||||
resolve(userFunctionReturn);
|
||||
}, 0);
|
||||
|
||||
return {
|
||||
retCode: ResultCodes.success,
|
||||
result: {},
|
||||
};
|
||||
});
|
||||
|
||||
// registering handler for injecting relay variable
|
||||
peer.internals.regHandler.forParticle(particle.id, def.names.getDataSrv, def.names.relay, (req) => {
|
||||
return {
|
||||
retCode: ResultCodes.success,
|
||||
result: peer.getStatus().relayPeerId,
|
||||
};
|
||||
});
|
||||
|
||||
// registering handler for error reporting
|
||||
peer.internals.regHandler.forParticle(particle.id, def.names.errorHandlingSrv, def.names.errorFnName, (req) => {
|
||||
const [err, _] = req.args;
|
||||
setTimeout(() => {
|
||||
reject(err);
|
||||
}, 0);
|
||||
return {
|
||||
retCode: ResultCodes.success,
|
||||
result: {},
|
||||
};
|
||||
});
|
||||
|
||||
// registering handler for particle timeout
|
||||
peer.internals.regHandler.timeout(particle.id, () => {
|
||||
reject(`Request timed out for ${def.functionName}`);
|
||||
});
|
||||
|
||||
peer.internals.initiateParticle(particle);
|
||||
});
|
||||
|
||||
// if the function has void type we should resolve immediately for API symmetry with non-void types
|
||||
// to help with debugging we are returning a promise which can be used to track particle errors
|
||||
// we cannot return a bare promise because JS will lift it, so returning an array with the promise
|
||||
if (def.returnType.tag === 'void') {
|
||||
return Promise.resolve([promise]);
|
||||
} else {
|
||||
return promise;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience function to support Aqua `service` generation backend
|
||||
* The compiler only need to generate a call the function and provide the corresponding definitions and the air script
|
||||
*
|
||||
* @param args - raw arguments passed by user to the generated function
|
||||
* @param def - service definition generated by the Aqua compiler
|
||||
*/
|
||||
export function registerService(args: any[], def: ServiceDef) {
|
||||
const { peer, service, serviceId } = extractRegisterServiceArgs(args, def.defaultServiceId);
|
||||
|
||||
// Checking for missing keys
|
||||
const requiredKeys = def.functions.map((x) => x.functionName);
|
||||
const incorrectServiceDefinitions = Object.keys(service).filter((f) => !(f in requiredKeys));
|
||||
if (!!incorrectServiceDefinitions.length) {
|
||||
throw new Error(
|
||||
`Error registering service ${serviceId}: missing functions: ` +
|
||||
incorrectServiceDefinitions.map((d) => "'" + d + "'").join(', '),
|
||||
);
|
||||
}
|
||||
|
||||
for (let singleFunction of def.functions) {
|
||||
// The function has type of (arg1, arg2, arg3, ... , callParams) => CallServiceResultType | void
|
||||
const userDefinedHandler = service[singleFunction.functionName];
|
||||
|
||||
peer.internals.regHandler.common(serviceId, singleFunction.functionName, async (req) => {
|
||||
const args = convertArgsFromReqToUserCall(req, singleFunction.argDefs);
|
||||
const rawResult = await userDefinedHandler.apply(null, args);
|
||||
const result = match(singleFunction.returnType)
|
||||
.with({ tag: 'primitive' }, () => rawResult)
|
||||
.with({ tag: 'optional' }, () => tsToAquaOpt(rawResult))
|
||||
.with({ tag: 'void' }, () => ({}))
|
||||
.exhaustive();
|
||||
|
||||
return {
|
||||
retCode: ResultCodes.success,
|
||||
result: result,
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts argument from ts representation (value | null) to air representation ([value] | [])
|
||||
*/
|
||||
const tsToAquaOpt = (arg: unknown | null): any => {
|
||||
return arg === null || arg === undefined ? [] : [arg];
|
||||
};
|
||||
|
||||
/**
|
||||
* Converts argument from air representation ([value] | []) to ts representation (value | null)
|
||||
*/
|
||||
const aquaOptToTs = (opt: Array<unknown>) => {
|
||||
return opt.length === 0 ? null : opt[0];
|
||||
};
|
||||
|
||||
/**
|
||||
* Converts raw arguments which may contain optional types from air representation to ts representation
|
||||
*/
|
||||
const convertArgsFromReqToUserCall = (req: CallServiceData, argDefs: Array<ArgDef<OptionalType | PrimitiveType>>) => {
|
||||
if (req.args.length !== argDefs.length) {
|
||||
throwForReq(req, `incorrect number of arguments, expected ${argDefs.length}`);
|
||||
}
|
||||
|
||||
const argsAccountedForOptional = req.args.map((x, index) => {
|
||||
return match(argDefs[index].argType)
|
||||
.with({ tag: 'optional' }, () => aquaOptToTs(x))
|
||||
.with({ tag: 'primitive' }, () => x)
|
||||
.exhaustive();
|
||||
});
|
||||
|
||||
return [...argsAccountedForOptional, extractCallParams(req, argDefs)];
|
||||
};
|
||||
|
||||
/**
|
||||
* Extracts Call Params from CallServiceData and forms tetraplets according to generated function definition
|
||||
*/
|
||||
const extractCallParams = (
|
||||
req: CallServiceData,
|
||||
argDefs: Array<ArgDef<OptionalType | PrimitiveType>>,
|
||||
): CallParams<any> => {
|
||||
let tetraplets: { [key in string]: SecurityTetraplet[] } = {};
|
||||
for (let i = 0; i < req.args.length; i++) {
|
||||
if (argDefs[i]) {
|
||||
tetraplets[argDefs[i].name] = req.tetraplets[i];
|
||||
}
|
||||
}
|
||||
|
||||
const callParams = {
|
||||
...req.particleContext,
|
||||
tetraplets,
|
||||
};
|
||||
|
||||
return callParams;
|
||||
};
|
||||
|
||||
/**
|
||||
* Arguments could be passed in one these configurations:
|
||||
* [...actualArgs]
|
||||
* [peer, ...actualArgs]
|
||||
* [...actualArgs, config]
|
||||
* [peer, ...actualArgs, config]
|
||||
*
|
||||
* This function select the appropriate configuration and returns
|
||||
* arguments in a structured way of: { peer, config, args }
|
||||
*/
|
||||
const extractFunctionArgs = (
|
||||
args: any[],
|
||||
numberOfExpectedArgs: number,
|
||||
): {
|
||||
peer: FluencePeer;
|
||||
config?: { ttl?: number };
|
||||
args: any[];
|
||||
} => {
|
||||
let peer: FluencePeer;
|
||||
let structuredArgs: any[];
|
||||
let config: any;
|
||||
if (FluencePeer.isInstance(args[0])) {
|
||||
peer = args[0];
|
||||
structuredArgs = args.slice(1, numberOfExpectedArgs + 1);
|
||||
config = args[numberOfExpectedArgs + 2];
|
||||
} else {
|
||||
peer = Fluence.getPeer();
|
||||
structuredArgs = args.slice(0, numberOfExpectedArgs);
|
||||
config = args[numberOfExpectedArgs + 1];
|
||||
}
|
||||
|
||||
return {
|
||||
peer: peer,
|
||||
config: config,
|
||||
args: structuredArgs,
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Arguments could be passed in one these configurations:
|
||||
* [serviceObject]
|
||||
* [peer, serviceObject]
|
||||
* [defaultId, serviceObject]
|
||||
* [peer, defaultId, serviceObject]
|
||||
*
|
||||
* Where serviceObject is the raw object with function definitions passed by user
|
||||
*
|
||||
* This function select the appropriate configuration and returns
|
||||
* arguments in a structured way of: { peer, serviceId, service }
|
||||
*/
|
||||
const extractRegisterServiceArgs = (
|
||||
args: any[],
|
||||
defaultServiceId?: string,
|
||||
): { peer: FluencePeer; serviceId: string; service: any } => {
|
||||
let peer: FluencePeer;
|
||||
let serviceId: any;
|
||||
let service: any;
|
||||
if (FluencePeer.isInstance(args[0])) {
|
||||
peer = args[0];
|
||||
} else {
|
||||
peer = Fluence.getPeer();
|
||||
}
|
||||
|
||||
if (typeof args[0] === 'string') {
|
||||
serviceId = args[0];
|
||||
} else if (typeof args[1] === 'string') {
|
||||
serviceId = args[1];
|
||||
} else {
|
||||
serviceId = defaultServiceId;
|
||||
}
|
||||
|
||||
// Figuring out which overload is the service.
|
||||
// If the first argument is not Fluence Peer and it is an object, then it can only be the service def
|
||||
// If the first argument is peer, we are checking further. The second argument might either be
|
||||
// an object, that it must be the service object
|
||||
// or a string, which is the service id. In that case the service is the third argument
|
||||
if (!FluencePeer.isInstance(args[0]) && typeof args[0] === 'object') {
|
||||
service = args[0];
|
||||
} else if (typeof args[1] === 'object') {
|
||||
service = args[1];
|
||||
} else {
|
||||
service = args[2];
|
||||
}
|
||||
|
||||
return {
|
||||
peer: peer,
|
||||
serviceId: serviceId,
|
||||
service: service,
|
||||
};
|
||||
};
|
||||
|
||||
function throwForReq(req: CallServiceData, message: string) {
|
||||
throw new Error(`${message}, serviceId='${req.serviceId}' fnName='${req.fnName}' args='${req.args}'`);
|
||||
}
|
@ -1,97 +0,0 @@
|
||||
import { encode, decode } from 'bs58';
|
||||
import {
|
||||
CallServiceData,
|
||||
CallServiceHandler,
|
||||
CallServiceResult,
|
||||
CallServiceResultType,
|
||||
Middleware,
|
||||
} from './CallServiceHandler';
|
||||
import { errorHandler } from './defaultMiddlewares';
|
||||
|
||||
const makeDefaultClientHandler = (): CallServiceHandler => {
|
||||
const success = (resp: CallServiceResult, result: CallServiceResultType) => {
|
||||
resp.retCode = 0;
|
||||
resp.result = result;
|
||||
};
|
||||
const error = (resp: CallServiceResult, errorMsg: string) => {
|
||||
resp.retCode = 1;
|
||||
resp.result = errorMsg;
|
||||
};
|
||||
const mw: Middleware = (req: CallServiceData, resp: CallServiceResult, next: Function) => {
|
||||
if (req.serviceId === 'op') {
|
||||
switch (req.fnName) {
|
||||
case 'noop':
|
||||
success(resp, {});
|
||||
return;
|
||||
|
||||
case 'array':
|
||||
success(resp, req.args);
|
||||
return;
|
||||
|
||||
case 'identity':
|
||||
if (req.args.length > 1) {
|
||||
error(resp, `identity accepts up to 1 arguments, received ${req.args.length} arguments`);
|
||||
} else {
|
||||
success(resp, req.args.length === 0 ? {} : req.args[0]);
|
||||
}
|
||||
return;
|
||||
|
||||
case 'concat':
|
||||
const incorrectArgIndices = req.args //
|
||||
.map((x, i) => [Array.isArray(x), i])
|
||||
.filter(([isArray, _]) => !isArray)
|
||||
.map(([_, index]) => index);
|
||||
|
||||
if (incorrectArgIndices.length > 0) {
|
||||
const str = incorrectArgIndices.join(', ');
|
||||
error(resp, `All arguments of 'concat' must be arrays: arguments ${str} are not`);
|
||||
} else {
|
||||
success(resp, [].concat.apply([], req.args));
|
||||
}
|
||||
return;
|
||||
|
||||
case 'string_to_b58':
|
||||
if (req.args.length !== 1) {
|
||||
error(resp, 'string_to_b58 accepts only one string argument');
|
||||
} else {
|
||||
success(resp, encode(new TextEncoder().encode(req.args[0])));
|
||||
}
|
||||
return;
|
||||
|
||||
case 'string_from_b58':
|
||||
if (req.args.length !== 1) {
|
||||
error(resp, 'string_from_b58 accepts only one string argument');
|
||||
} else {
|
||||
success(resp, new TextDecoder().decode(decode(req.args[0])));
|
||||
}
|
||||
return;
|
||||
|
||||
case 'bytes_to_b58':
|
||||
if (req.args.length !== 1 || !Array.isArray(req.args[0])) {
|
||||
error(resp, 'bytes_to_b58 accepts only single argument: array of numbers');
|
||||
} else {
|
||||
const argumentArray = req.args[0] as number[];
|
||||
success(resp, encode(new Uint8Array(argumentArray)));
|
||||
}
|
||||
return;
|
||||
|
||||
case 'bytes_from_b58':
|
||||
if (req.args.length !== 1) {
|
||||
error(resp, 'bytes_from_b58 accepts only one string argument');
|
||||
} else {
|
||||
success(resp, Array.from(decode(req.args[0])));
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
next();
|
||||
};
|
||||
|
||||
const res = new CallServiceHandler();
|
||||
res.use(errorHandler);
|
||||
res.use(mw);
|
||||
return res;
|
||||
};
|
||||
|
||||
export default makeDefaultClientHandler;
|
@ -1,14 +0,0 @@
|
||||
import { CallServiceArg, CallServiceData, CallServiceResult, Middleware, ResultCodes } from './CallServiceHandler';
|
||||
|
||||
/**
|
||||
* Error catching middleware
|
||||
*/
|
||||
export const errorHandler: Middleware = (req: CallServiceData, resp: CallServiceResult, next: Function): void => {
|
||||
try {
|
||||
next();
|
||||
} catch (e) {
|
||||
resp.retCode = ResultCodes.exceptionInHandler;
|
||||
resp.result = `Handler failed. fnName="${req.fnName}" serviceId="${req.serviceId}" error: ${e.toString()}`;
|
||||
}
|
||||
};
|
||||
1;
|
106
src/internal/defaultServices.ts
Normal file
106
src/internal/defaultServices.ts
Normal file
@ -0,0 +1,106 @@
|
||||
/*
|
||||
* Copyright 2021 Fluence Labs Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { CallServiceResult } from '@fluencelabs/avm';
|
||||
import { encode, decode } from 'bs58';
|
||||
import { GenericCallServiceHandler, ResultCodes } from './commonTypes';
|
||||
|
||||
const success = (result: any): CallServiceResult => {
|
||||
return {
|
||||
result: result,
|
||||
retCode: ResultCodes.success,
|
||||
};
|
||||
};
|
||||
|
||||
const error = (error: string): CallServiceResult => {
|
||||
return {
|
||||
result: error,
|
||||
retCode: ResultCodes.unknownError,
|
||||
};
|
||||
};
|
||||
|
||||
export const defaultServices: { [serviceId in string]: { [fnName in string]: GenericCallServiceHandler } } = {
|
||||
op: {
|
||||
noop: (req) => {
|
||||
return success({});
|
||||
},
|
||||
|
||||
array: (req) => {
|
||||
return success(req.args);
|
||||
},
|
||||
|
||||
identity: (req) => {
|
||||
if (req.args.length > 1) {
|
||||
return error(`identity accepts up to 1 arguments, received ${req.args.length} arguments`);
|
||||
} else {
|
||||
return success(req.args.length === 0 ? {} : req.args[0]);
|
||||
}
|
||||
},
|
||||
|
||||
concat: (req) => {
|
||||
const incorrectArgIndices = req.args //
|
||||
.map((x, i) => [Array.isArray(x), i])
|
||||
.filter(([isArray, _]) => !isArray)
|
||||
.map(([_, index]) => index);
|
||||
|
||||
if (incorrectArgIndices.length > 0) {
|
||||
const str = incorrectArgIndices.join(', ');
|
||||
return error(`All arguments of 'concat' must be arrays: arguments ${str} are not`);
|
||||
} else {
|
||||
return success([].concat.apply([], req.args));
|
||||
}
|
||||
},
|
||||
|
||||
string_to_b58: (req) => {
|
||||
if (req.args.length !== 1) {
|
||||
return error('string_to_b58 accepts only one string argument');
|
||||
} else {
|
||||
return success(encode(new TextEncoder().encode(req.args[0])));
|
||||
}
|
||||
},
|
||||
|
||||
string_from_b58: (req) => {
|
||||
if (req.args.length !== 1) {
|
||||
return error('string_from_b58 accepts only one string argument');
|
||||
} else {
|
||||
return success(new TextDecoder().decode(decode(req.args[0])));
|
||||
}
|
||||
},
|
||||
|
||||
bytes_to_b58: (req) => {
|
||||
if (req.args.length !== 1 || !Array.isArray(req.args[0])) {
|
||||
return error('bytes_to_b58 accepts only single argument: array of numbers');
|
||||
} else {
|
||||
const argumentArray = req.args[0] as number[];
|
||||
return success(encode(new Uint8Array(argumentArray)));
|
||||
}
|
||||
},
|
||||
|
||||
bytes_from_b58: (req) => {
|
||||
if (req.args.length !== 1) {
|
||||
return error('bytes_from_b58 accepts only one string argument');
|
||||
} else {
|
||||
return success(Array.from(decode(req.args[0])));
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
peer: {
|
||||
identify: (req) => {
|
||||
return error('The JS implementation of Peer does not support identify');
|
||||
},
|
||||
},
|
||||
};
|
@ -1,29 +0,0 @@
|
||||
/*
|
||||
* Copyright 2020 Fluence Labs Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
export interface ModuleConfig {
|
||||
name: string;
|
||||
mem_pages_count?: number;
|
||||
logger_enabled?: boolean;
|
||||
wasi?: Wasi;
|
||||
mounted_binaries?: object;
|
||||
}
|
||||
|
||||
export interface Wasi {
|
||||
envs?: object;
|
||||
preopened_files?: string[];
|
||||
mapped_dirs?: object;
|
||||
}
|
@ -1,87 +0,0 @@
|
||||
/*
|
||||
* Copyright 2020 Fluence Labs Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import { fromByteArray, toByteArray } from 'base64-js';
|
||||
import PeerId from 'peer-id';
|
||||
import { encode } from 'bs58';
|
||||
import log, { LogLevel } from 'loglevel';
|
||||
|
||||
export interface Particle {
|
||||
id: string;
|
||||
init_peer_id: string;
|
||||
timestamp: number;
|
||||
ttl: number;
|
||||
script: string;
|
||||
// sign upper fields
|
||||
signature: string;
|
||||
data: Uint8Array;
|
||||
}
|
||||
|
||||
export const logParticle = (fn: Function, message: string, particle: Particle) => {
|
||||
const toLog = { ...particle };
|
||||
delete toLog.data;
|
||||
fn(message, toLog);
|
||||
};
|
||||
|
||||
/**
|
||||
* Represents particle action to send to a node
|
||||
*/
|
||||
interface ParticlePayload {
|
||||
action: 'Particle';
|
||||
id: string;
|
||||
init_peer_id: string;
|
||||
timestamp: number;
|
||||
ttl: number;
|
||||
script: string;
|
||||
signature: number[];
|
||||
data: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an action to send to a node.
|
||||
*/
|
||||
export function toPayload(particle: Particle): ParticlePayload {
|
||||
return {
|
||||
action: 'Particle',
|
||||
id: particle.id,
|
||||
init_peer_id: particle.init_peer_id,
|
||||
timestamp: particle.timestamp,
|
||||
ttl: particle.ttl,
|
||||
script: particle.script,
|
||||
// TODO: copy signature from a particle after signatures will be implemented on nodes
|
||||
signature: [],
|
||||
data: fromByteArray(particle.data),
|
||||
};
|
||||
}
|
||||
|
||||
export function parseParticle(str: string): Particle {
|
||||
let json = JSON.parse(str);
|
||||
|
||||
return {
|
||||
id: json.id,
|
||||
init_peer_id: json.init_peer_id,
|
||||
timestamp: json.timestamp,
|
||||
ttl: json.ttl,
|
||||
script: json.script,
|
||||
signature: json.signature,
|
||||
data: toByteArray(json.data),
|
||||
};
|
||||
}
|
||||
|
||||
export function genUUID() {
|
||||
return uuidv4();
|
||||
}
|
@ -1,9 +1,26 @@
|
||||
/*
|
||||
* Copyright 2021 Fluence Labs Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { AirInterpreter, LogLevel as AvmLogLevel } from '@fluencelabs/avm';
|
||||
import log from 'loglevel';
|
||||
import { CallServiceData, CallServiceResult, CallServiceResultType, ResultCodes } from './commonTypes';
|
||||
import { AvmLoglevel, FluencePeer } from './FluencePeer';
|
||||
import { RequestFlowBuilder } from './RequestFlowBuilder';
|
||||
import { Particle } from './Particle';
|
||||
|
||||
export const createInterpreter = (handler, peerId, logLevel: AvmLoglevel): Promise<AirInterpreter> => {
|
||||
export const createInterpreter = (logLevel: AvmLoglevel): Promise<AirInterpreter> => {
|
||||
const logFn = (level: AvmLogLevel, msg: string) => {
|
||||
switch (level) {
|
||||
case 'error':
|
||||
@ -24,7 +41,16 @@ export const createInterpreter = (handler, peerId, logLevel: AvmLoglevel): Promi
|
||||
break;
|
||||
}
|
||||
};
|
||||
return AirInterpreter.create(handler, peerId, logLevel, logFn);
|
||||
return AirInterpreter.create(logLevel, logFn);
|
||||
};
|
||||
|
||||
export const MakeServiceCall = (fn: (args: any[]) => CallServiceResultType) => {
|
||||
return (req: CallServiceData): CallServiceResult => {
|
||||
return {
|
||||
retCode: ResultCodes.success,
|
||||
result: fn(req.args),
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
@ -37,23 +63,72 @@ export const checkConnection = async (peer: FluencePeer, ttl?: number): Promise<
|
||||
}
|
||||
|
||||
const msg = Math.random().toString(36).substring(7);
|
||||
const callbackFn = 'checkConnection';
|
||||
const callbackService = '_callback';
|
||||
|
||||
const [request, promise] = new RequestFlowBuilder()
|
||||
.withRawScript(
|
||||
`(seq
|
||||
(call init_relay ("op" "identity") [msg] result)
|
||||
(call %init_peer_id% ("${callbackService}" "${callbackFn}") [result])
|
||||
)`,
|
||||
const promise = new Promise<string>((resolve, reject) => {
|
||||
const script = `
|
||||
(xor
|
||||
(seq
|
||||
(call %init_peer_id% ("load" "relay") [] init_relay)
|
||||
(seq
|
||||
(call %init_peer_id% ("load" "msg") [] msg)
|
||||
(seq
|
||||
(call init_relay ("op" "identity") [msg] result)
|
||||
(call %init_peer_id% ("callback" "callback") [result])
|
||||
)
|
||||
)
|
||||
)
|
||||
.withTTL(ttl)
|
||||
.withVariables({
|
||||
msg,
|
||||
})
|
||||
.buildAsFetch<[string]>(callbackService, callbackFn);
|
||||
(seq
|
||||
(call init_relay ("op" "identity") [])
|
||||
(call %init_peer_id% ("callback" "error") [%last_error%])
|
||||
)
|
||||
)`;
|
||||
const particle = Particle.createNew(script, ttl);
|
||||
peer.internals.regHandler.forParticle(
|
||||
particle.id,
|
||||
'load',
|
||||
'relay',
|
||||
MakeServiceCall(() => {
|
||||
return peer.getStatus().relayPeerId;
|
||||
}),
|
||||
);
|
||||
|
||||
await peer.internals.initiateFlow(request);
|
||||
peer.internals.regHandler.forParticle(
|
||||
particle.id,
|
||||
'load',
|
||||
'msg',
|
||||
MakeServiceCall(() => {
|
||||
return msg;
|
||||
}),
|
||||
);
|
||||
|
||||
peer.internals.regHandler.forParticle(
|
||||
particle.id,
|
||||
'callback',
|
||||
'callback',
|
||||
MakeServiceCall((args) => {
|
||||
const [val] = args;
|
||||
setTimeout(() => {
|
||||
resolve(val);
|
||||
}, 0);
|
||||
return {};
|
||||
}),
|
||||
);
|
||||
|
||||
peer.internals.regHandler.forParticle(
|
||||
particle.id,
|
||||
'callback',
|
||||
'error',
|
||||
MakeServiceCall((args) => {
|
||||
const [error] = args;
|
||||
setTimeout(() => {
|
||||
reject(error);
|
||||
}, 0);
|
||||
return {};
|
||||
}),
|
||||
);
|
||||
|
||||
peer.internals.initiateParticle(particle);
|
||||
});
|
||||
|
||||
try {
|
||||
const [result] = await promise;
|
||||
@ -67,6 +142,6 @@ export const checkConnection = async (peer: FluencePeer, ttl?: number): Promise<
|
||||
}
|
||||
};
|
||||
|
||||
export const ParticleDataToString = (data: Uint8Array): string => {
|
||||
export function dataToString(data: Uint8Array) {
|
||||
return new TextDecoder().decode(Buffer.from(data));
|
||||
};
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user