Upload your node with "Add Deno node" button in /dashboard/nodes page, need 2 files:
Node definition (.json)
Source code
Documentation
Code requirements
Your code MUST export a default class that implements CommandTrait. The class name doesn't matter.
CommandTrait is defined in , it has 3 methods, one is required:
export interface CommandTrait {
/**
* Deserialize each inputs from `Value` to the type of your choice.
* This function will be called before passing inputs to `run()`.
* If not implemented, `Value.toJSObject()` will be called for each inputs.
*/
deserializeInputs?(inputs: Record<string, Value>): Record<string, any>;
/**
* Serialize each output to a `Value`.
* This function will be called after each `run()`.
* If not implemented, `new Value(output)` will be called for each outputs.
*/
serializeOutputs?(outputs: Record<string, any>): Record<string, Value>;
/**
* This function will be called every time the command is run.
* @param ctx Context
* @param params Map of input_name => input_value.
*/
run(ctx: Context, params: Record<string, any>): Promise<Record<string, any>>;
}
run() will be called every time the node is run.
Input parameters:
params: Record<string, any> : Input values, this is a map of input_name => value
Return type: run() should return a map of output_name => output_value on success, and throw an exception on errors.
Using BaseCommand class
We also provide a BaseCommand class that will convert input and output values based on node definition. All you have to do is extends it:
Bundling a node allows you to combine the instructions with other nodes to create a single transaction. All nodes in a flow will be bundled and the user will sign one for one transaction. The flow will build the message and submit the transaction.
import * as lib from "jsr:@space-operator/flow-lib";
import * as web3 from "npm:@solana/web3.js";
import { Instructions } from "jsr:@space-operator/flow-lib/context";
interface Inputs {
from: web3.PublicKey;
to: web3.PublicKey;
amount: number;
}
export default class TransferSol extends lib.BaseCommand {
async run(
ctx: lib.Context,
params: Inputs,
): Promise<Record<string, any>> {
const result = await ctx.execute(
new Instructions(
params.from,
[params.from],
[
web3.SystemProgram.transfer({
fromPubkey: params.from,
toPubkey: params.to,
lamports: params.amount,
}),
]
),
{}
);
return {
signature: result.signature!,
};
}
}
Note, when bundling a node, you must update the Node Definition to specify if and how a command would output Solana instructions, and the order with which it will return its outputs:
before: list of output names returned before instructions are sent.
signature: name of the signature's output port.
after: list of output names returned after instructions are sent.
You can manually build a message, request signature, and submit a transaction. The flow will not collect the instructions from this node and will execute it as an independent node.