Solana · Arazzo Workflow

Solana Submit a Transaction and Confirm It

Version 1.0.0

Fetch a blockhash, simulate a signed transaction, send it, poll to finality, and read it back.

1 workflow 1 source API 1 provider
View Spec View on GitHub BlockchainCryptocurrencyWeb3DeFiTransactionsTokensArazzoWorkflows

Provider

solana

Workflows

send-transaction-lifecycle
Simulate, submit, and confirm a signed Solana transaction end to end.
Takes a signed, encoded transaction and carries it through the full submit lifecycle, aborting before submission if the simulation reports an error.
5 steps inputs: encoding, signedTransaction outputs: confirmationStatus, fee, signature, slot
1
fetchBlockhash
getLatestBlockhash
Fetch a recent blockhash and the last block height at which it stays valid. The client signs the transaction against this blockhash, and the expiry height bounds how long confirmation polling is worth attempting.
2
simulate
simulateTransaction
Dry-run the signed transaction against the current bank without broadcasting it. Signature verification is enabled, and the step only succeeds when the simulated result carries no error, so a transaction that would fail on-chain is never submitted.
3
submit
sendTransaction
Relay the signed transaction to the cluster as-is. The node returns the base58 transaction signature, which is the handle used to track confirmation.
4
confirm
getSignatureStatuses
Poll the signature status until the cluster reports it finalized. The step retries on a short interval because a freshly submitted transaction takes several slots to reach finality.
5
fetchTransaction
getTransaction
Read the finalized transaction back in parsed form to capture the slot it landed in, the fee actually charged, and the on-chain log messages.

Source API Descriptions

Arazzo Workflow Specification

Raw ↑
arazzo: 1.0.1
info:
  title: Solana Submit a Transaction and Confirm It
  summary: Fetch a blockhash, simulate a signed transaction, send it, poll to finality, and read it back.
  description: >-
    The canonical Solana write path. The workflow fetches a recent blockhash and
    its last valid block height, dry-runs the signed transaction with
    simulateTransaction so a failing transaction never costs a fee, submits it
    with sendTransaction, polls getSignatureStatuses until the cluster reports
    finality, and finally reads the confirmed transaction back with
    getTransaction. Transaction construction and signing happen client-side with
    an SDK and are not part of the JSON-RPC surface, so the already-signed,
    encoded transaction is supplied as an input, built against the blockhash the
    first step returns. Every step spells out its JSON-RPC request inline so the
    flow can be read and executed without opening the underlying OpenAPI
    description.
  version: 1.0.0
sourceDescriptions:
- name: solanaRpcApi
  url: ../openapi/solana-rpc-api-openapi.yml
  type: openapi
workflows:
- workflowId: send-transaction-lifecycle
  summary: Simulate, submit, and confirm a signed Solana transaction end to end.
  description: >-
    Takes a signed, encoded transaction and carries it through the full submit
    lifecycle, aborting before submission if the simulation reports an error.
  inputs:
    type: object
    required:
    - signedTransaction
    properties:
      signedTransaction:
        type: string
        description: >-
          The signed transaction, already encoded (base64 or base58) by the
          client SDK, built against the blockhash returned by fetchBlockhash.
      encoding:
        type: string
        description: Encoding of the supplied signed transaction.
        enum:
        - base58
        - base64
        default: base64
  steps:
  - stepId: fetchBlockhash
    description: >-
      Fetch a recent blockhash and the last block height at which it stays
      valid. The client signs the transaction against this blockhash, and the
      expiry height bounds how long confirmation polling is worth attempting.
    operationId: getLatestBlockhash
    requestBody:
      contentType: application/json
      payload:
        jsonrpc: "2.0"
        id: 1
        method: getLatestBlockhash
        params:
        - commitment: finalized
    successCriteria:
    - condition: $statusCode == 200
    - context: $response.body
      condition: $.result.value.blockhash
      type: jsonpath
    outputs:
      blockhash: $response.body#/result/value/blockhash
      lastValidBlockHeight: $response.body#/result/value/lastValidBlockHeight
  - stepId: simulate
    description: >-
      Dry-run the signed transaction against the current bank without
      broadcasting it. Signature verification is enabled, and the step only
      succeeds when the simulated result carries no error, so a transaction that
      would fail on-chain is never submitted.
    operationId: simulateTransaction
    requestBody:
      contentType: application/json
      payload:
        jsonrpc: "2.0"
        id: 1
        method: simulateTransaction
        params:
        - $inputs.signedTransaction
        - sigVerify: true
          commitment: finalized
          encoding: $inputs.encoding
    successCriteria:
    - condition: $statusCode == 200
    - context: $response.body
      condition: $.result.value.err == null
      type: jsonpath
    outputs:
      logs: $response.body#/result/value/logs
      unitsConsumed: $response.body#/result/value/unitsConsumed
      simulationError: $response.body#/result/value/err
    onFailure:
    - name: abortOnSimulationError
      type: end
  - stepId: submit
    description: >-
      Relay the signed transaction to the cluster as-is. The node returns the
      base58 transaction signature, which is the handle used to track
      confirmation.
    operationId: sendTransaction
    requestBody:
      contentType: application/json
      payload:
        jsonrpc: "2.0"
        id: 1
        method: sendTransaction
        params:
        - $inputs.signedTransaction
        - encoding: $inputs.encoding
    successCriteria:
    - condition: $statusCode == 200
    - context: $response.body
      condition: $.result
      type: jsonpath
    outputs:
      signature: $response.body#/result
  - stepId: confirm
    description: >-
      Poll the signature status until the cluster reports it finalized. The step
      retries on a short interval because a freshly submitted transaction takes
      several slots to reach finality.
    operationId: getSignatureStatuses
    requestBody:
      contentType: application/json
      payload:
        jsonrpc: "2.0"
        id: 1
        method: getSignatureStatuses
        params:
        - - $steps.submit.outputs.signature
        - searchTransactionHistory: true
    successCriteria:
    - condition: $statusCode == 200
    - context: $response.body
      condition: $.result.value[0].confirmationStatus == 'finalized'
      type: jsonpath
    outputs:
      confirmationStatus: $response.body#/result/value/0/confirmationStatus
      confirmedSlot: $response.body#/result/value/0/slot
      transactionError: $response.body#/result/value/0/err
    onFailure:
    - name: pollUntilFinalized
      type: retry
      retryAfter: 2
      retryLimit: 30
  - stepId: fetchTransaction
    description: >-
      Read the finalized transaction back in parsed form to capture the slot it
      landed in, the fee actually charged, and the on-chain log messages.
    operationId: getTransaction
    requestBody:
      contentType: application/json
      payload:
        jsonrpc: "2.0"
        id: 1
        method: getTransaction
        params:
        - $steps.submit.outputs.signature
        - encoding: jsonParsed
          commitment: finalized
    successCriteria:
    - condition: $statusCode == 200
    - context: $response.body
      condition: $.result.slot
      type: jsonpath
    outputs:
      slot: $response.body#/result/slot
      blockTime: $response.body#/result/blockTime
      fee: $response.body#/result/meta/fee
      logMessages: $response.body#/result/meta/logMessages
  outputs:
    signature: $steps.submit.outputs.signature
    confirmationStatus: $steps.confirm.outputs.confirmationStatus
    slot: $steps.fetchTransaction.outputs.slot
    fee: $steps.fetchTransaction.outputs.fee