Skip to content
This repository was archived by the owner on Jul 10, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions src/__test__/integration/client.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { checkConnection, createClient, FluenceClient } from '../../FluenceClien
import Multiaddr from 'multiaddr';
import { nodes } from '../connection';
import { RequestFlowBuilder } from '../../internal/RequestFlowBuilder';
import log from 'loglevel';

let client: FluenceClient;

Expand Down Expand Up @@ -245,6 +246,29 @@ describe('Typescript usage suite', () => {
});
});

it('Should not crash if undefined is passed as a variable', async () => {
// arrange
client = await createClient();
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 client.initiateFlow(request);
const [res] = await promise;

// assert
expect(res).toBe(null);
});

it('Should throw correct error when the client tries to send a particle not to the relay', async () => {
// arrange
client = await createClient();
Expand Down
2 changes: 1 addition & 1 deletion src/internal/CallServiceHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ export interface CallServiceData {
/**
* Type for all the possible ovjects that can be return to the AVM
*/
export type CallServiceResultType = object | boolean | number | string;
export type CallServiceResultType = object | boolean | number | string | null;

/**
* Represents the result of the `call` air instruction to be returned into AVM
Expand Down
7 changes: 7 additions & 0 deletions src/internal/ClientImpl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,13 @@ export class ClientImpl implements FluenceClient {
},
});

if (res.result === undefined) {
log.error(
`Call to serviceId=${serviceId} fnName=${fnName} unexpectedly returned undefined result, falling back to null`,
);
res.result = null;
}

return {
ret_code: res.retCode,
result: JSON.stringify(res.result),
Expand Down
10 changes: 6 additions & 4 deletions src/internal/RequestFlowBuilder.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import log from 'loglevel';
import { CallServiceHandler } from './CallServiceHandler';
import { CallServiceHandler, CallServiceResultType } from './CallServiceHandler';
import { DEFAULT_TTL, RequestFlow } from './RequestFlow';

export const loadVariablesService = 'load';
Expand Down Expand Up @@ -100,7 +100,7 @@ export class RequestFlowBuilder {
private shouldInjectRelay: boolean = true;

private ttl: number = DEFAULT_TTL;
private variables = new Map<string, any>();
private variables = new Map<string, CallServiceResultType>();
private handlerConfigs: Array<(handler: CallServiceHandler, request: RequestFlow) => void> = [];
private buildScriptActions: Array<(sb: ScriptBuilder) => void> = [];
private onTimeout: () => void;
Expand Down Expand Up @@ -268,7 +268,7 @@ export class RequestFlowBuilder {
/**
* Adds a variable to the list of injected variables
*/
withVariable(name: string, value: any): RequestFlowBuilder {
withVariable(name: string, value: CallServiceResultType): RequestFlowBuilder {
this.variables.set(name, value);
return this;
}
Expand All @@ -277,7 +277,9 @@ export class RequestFlowBuilder {
* 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, any> | Record<string, any>): RequestFlowBuilder {
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 {
Expand Down