DocsConnection Rules
SolStudio

Connection Rules

This document describes every valid connection between node types in Solana Contract Flow. Understanding these rules is essential for building correct flows.


Overview

Connections define relationships between nodes. Each connection goes from an output handle on a source node to an input handle on a target node. The editor enforces type compatibility: only valid connections can be made.


Connection Diagram

bash
                        +-----------+
                        |  Program  |
                        +-----+-----+
                              |
                              | (instruction-out -> instruction-in)
                              v
                        +-----------+
                 +----->| Instruction|
                 |      +--+--+--+--+
                 |         |  |  |  |
        +--------+--+      |  |  |  |
        |   Error   |<-----+  |  |  +-----> +-----------+
        +-----------+  error   |  +-------->|   Event   |
                        |     |            +-----------+
                        |     |
                  account|    |logic
                        |     |
                        v     v
                  +-----------+    +-----------+
                  |  Account  |<---|   Logic   |
                  +--+-----+--+    +--+-----+-+
                     |     ^          |     ^
                     |     |          |     |
              constraint   |state  logic-in  logic-out
                     |     |          |     |
                     v     |          v     |
                  +-----------+    +-----------+
                  | Constraint|    |   Logic   |  (chain)
                  +-----------+    +-----------+
                                        ^
                                        |  (then/else branches)
                                  +-----------+
                                  |  If-Else  |---> child logic nodes
                                  +-----------+

Valid Connections

Program -> Instruction

Source HandleTarget HandleDescription
instruction-out (bottom)instruction-in (top)The instruction belongs to this program

Rules:

  • A Program can connect to multiple Instruction nodes.
  • Every Instruction must be connected to exactly one Program.
  • A flow must have exactly one Program node and at least one Instruction.

Instruction -> Account

Source HandleTarget HandleDescription
account-out (right)account-in (top)This account is used by the instruction

Rules:

  • An Instruction can connect to multiple Account nodes.
  • An Account can be connected to multiple Instructions (shared account).
  • An Instruction with zero accounts generates a warning.

Instruction -> Logic

Source HandleTarget HandleDescription
logic-out (bottom)logic-in (top)This logic operation runs in the instruction body

Rules:

  • An Instruction can connect to multiple Logic nodes.
  • Logic nodes execute in order property sequence (ascending numeric order).

Instruction -> Error

Source HandleTarget HandleDescription
error-out (left)error-in (left)This error variant is used by the instruction

Rules:

  • An Instruction can connect to multiple Error nodes.
  • Error nodes are global: they are collected into a single error enum shared by all instructions.

Instruction -> Event

Source HandleTarget HandleDescription
event-out (left)event-in (left)This event type can be emitted by the instruction

Rules:

  • An Instruction can connect to multiple Event nodes.
  • Event nodes are global: they generate event structs that any instruction can reference.

Instruction -> Custom Code

Source HandleTarget HandleDescription
logic-out (bottom)logic-in (top)Custom code runs in the instruction body

Rules:

  • Custom Code nodes use the same connection pattern as Logic nodes.
  • They are treated as logic operations in the instruction body.

Account -> Constraint

Source HandleTarget HandleDescription
constraint-out (right)constraint-in (left)This constraint applies to the account

Rules:

  • An Account can connect to multiple Constraint nodes.
  • Each constraint adds a validation rule.
  • Constraints are merged: if both a flag (e.g., isMut) and a constraint node of the same type exist, the explicit constraint node takes precedence.

Account -> State

Source HandleTarget HandleDescription
data-in (left)data-out (right)This account stores this state struct

Rules:

  • An Account connects to at most one State node.
  • A State node can connect to multiple Account nodes (the same struct used by different instructions).
  • The State node's name becomes the stateType on the Account, determining the Rust type for the account.

Logic -> Logic (chaining)

Source HandleTarget HandleDescription
logic-out (bottom)logic-in (top)Sequential execution in the instruction body

Rules:

  • Logic nodes chain vertically to define execution order.
  • The order property on each logic node determines final sequencing.
  • All logic nodes connected to an Instruction (directly or through chains) are collected and sorted by order.

Logic -> Logic (if-else branching)

Source HandleTarget HandleDescription
logic-out (bottom, default)logic-in (top)Child logic for the "then" branch
else-out (bottom, variant)logic-in (top)Child logic for the "else" branch

Rules:

  • Only if-else logic nodes have branch handles.
  • Children connected to the default bottom handle form the "then" body.
  • Children connected to the "else-out" handle form the "else" body.
  • Child logic can nest: an if-else child can contain its own if-else.

Integration -> Account

Source HandleTarget HandleDescription
account-out (bottom)account-in (top)Plugin integration modifies this account

Complete Connection Matrix

From (source)To (target)Handle PairPurpose
ProgramInstructioninstruction-out -> instruction-inProgram contains this instruction
InstructionAccountaccount-out -> account-inInstruction operates on this account
InstructionLogiclogic-out -> logic-inInstruction executes this logic
InstructionCustom Codelogic-out -> logic-inInstruction executes this custom code
InstructionErrorerror-out -> error-inInstruction references this error
InstructionEventevent-out -> event-inInstruction can emit this event
InstructionIntegrationlogic-in <- logic-outPlugin attaches to instruction
AccountConstraintconstraint-out -> constraint-inConstraint validates this account
StateAccountdata-out -> data-inAccount stores this state struct
LogicLogiclogic-out -> logic-inSequential chaining
Logic (if-else)Logic (then)logic-out -> logic-inThen branch body
Logic (if-else)Logic (else)else-out -> logic-inElse branch body
Custom CodeLogiclogic-out -> logic-inChaining after custom code
IntegrationAccountaccount-out -> account-inPlugin modifies account

Invalid Connections

The following connections are not allowed:

Attempted ConnectionReason
Program -> AccountAccounts must be connected to Instructions, not directly to Programs
Program -> LogicLogic must be connected to Instructions
Program -> StateStates connect to Accounts, not Programs
Constraint -> ConstraintConstraints attach to Accounts only
Constraint -> InstructionConstraints are one-way: Account <- Constraint
Error -> InstructionErrors are referenced, not invoked
Event -> InstructionEvents are emitted, not invoked
State -> InstructionStates connect to Accounts only
State -> StateStates are independent definitions
Error -> ErrorErrors are independent definitions
Event -> EventEvents are independent definitions

Handle Reference by Node Type

Program Node

Handle IDPositionDirectionConnects To
instruction-outBottomOutputInstruction

Instruction Node

Handle IDPositionDirectionConnects To
instruction-inTopInputProgram
account-outRightOutputAccount
logic-outBottomOutputLogic, Custom Code
error-outLeft (top)OutputError
event-outLeft (bottom)OutputEvent

Account Node

Handle IDPositionDirectionConnects To
account-inTopInputInstruction, Integration
constraint-outRightOutputConstraint
data-inLeftInputState

State Node

Handle IDPositionDirectionConnects To
data-outRightOutputAccount

Constraint Node

Handle IDPositionDirectionConnects To
constraint-inLeftInputAccount

Logic Node

Handle IDPositionDirectionConnects To
logic-inTopInputInstruction, Logic
logic-outBottomOutputLogic
account-outRightOutput(reference to accounts)

If-Else Logic Node (additional handles)

Handle IDPositionDirectionConnects To
else-outBottom (variant)OutputLogic (else branch)

Error Node

Handle IDPositionDirectionConnects To
error-inLeftInputInstruction

Event Node

Handle IDPositionDirectionConnects To
event-inLeftInputInstruction

Custom Code Node

Handle IDPositionDirectionConnects To
logic-inTopInputInstruction, Logic
logic-outBottomOutputLogic
data-inLeftInput(variable bindings)
data-outRightOutput(variable bindings)

Integration Node

Handle IDPositionDirectionConnects To
logic-inTopInputInstruction
account-outBottomOutputAccount

Common Patterns

Pattern: Initialize a Data Account

bash
Program
  |
  v
Instruction (initialize)
  |---> Account (payer) [signer, mut]
  |---> Account (new_account) [init, payer=payer, space=auto]
  |       <--- State (MyData { authority, value })
  |---> Account (system_program)
  |---> Logic (set-field: new_account.authority = payer.key())

Pattern: Token Transfer with PDA Authority

bash
Program
  |
  v
Instruction (transfer)
  |---> Account (vault) [seeds=[b"vault"], bump]
  |---> Account (from_token) [token-account]
  |---> Account (to_token) [token-account]
  |---> Account (token_program)
  |---> Logic (transfer-token: from=from_token, to=to_token, authority=vault, signerSeeds=...)

Pattern: Conditional Logic

bash
Program
  |
  v
Instruction (process)
  |---> Account (data) [mut, account]
  |---> Logic (if-else: condition = data.value > 0)
  |       |---> Logic (set-field: data.status = "active")    [then branch]
  |       |---> Logic (return-error: errorCode=InvalidValue)  [else branch]