---
title: Language & Syntax
description: Use the txtx DSL to describe the deployments that surfpool manages.
---

This is the documentation for the txtx language. Runbook files that you write
describe which blockchains and networks to use, what data to retrieve, and what
transactions to broadcast. The txtx language also lets you define dependencies
between resources and create multiple similar constructs from a single block.

## Syntax

Runbooks contain a series of code blocks that look something like this:

```hcl
variable "query_path" {
  description = "An input that can be edited in the web UI!"
  value = "details"
  editable = true
}

action "http_query" "std::send_http_request" {
  description = "This action will make a GET request to the specified URL!"
  url = "https://example.com/${variable.my_var.query_path}"
}

output "status_code" {
  description = "This output will be displayed in the Outputs section of the web UI!"
  value = action.http_query.status_code
}
```

Each block has a command type (in this example `variable`, `action`, and
`output`), a reference name (`"query_path"`, `"http_query"`, and
`"status_code"`), and the inner data of the block (everything between the
`{ ... }`). Some command types also require that a command is specified
(`"std::send_http_request"`). The inner data of the block is dictated by the
command type and command that are specified.

### Command References

One command can reference the outputs of another command to build a chain of
dependent commands. When you execute a Runbook, surfpool creates a graph of all
the commands to ensure they are always executed in the correct order. This does
mean that dependency cycles need to be avoided when creating a Runbook.

Another command's output can be referenced in a block using
`command_type.ref_name.output_name`. Here are some examples:

```hcl
variable "my_var" {
  description = variable.another_var.value // references the `value` output of a `variable` named `another_var`
  value = action.my_action.data // references the `data` output of an `action` named `my_action`
}
```

### Functions

The [standard library](/docs/tools/surfpool/iac/std/functions) provides some
functions that can be written in-line, as opposed to writing full command blocks
with named arguments. These functions can be extended via addons.

These functions can look like explicit function calls (e.g. `add_uint(1, 3)`),
or they can look like in-line arithmetic operations (e.g. `1 + 3`). Functions
can reference other command outputs, or they can be stored in new command
outputs. Here's an example using a few functions:

```hcl
variable "one" {
  value = 1
}
variable "two" {
  value = 2
}
variable "addem_up" {
  value = variable.one + variable.two
}
output "add_some_more" {
  value = add_uint(variable.addem_up + variable.one, variable.two)
}
```

## Manifest & CLI Inputs

Inputs can be provided to the Runbook by passing them in as a CLI input, or by
specifying them in a `txtx.yml` manifest file. If the same input is provided
both in the CLI and in a manifest, the CLI input will take precedence. To see
information on how to use the CLI, check out the
[CLI documentation](/docs/tools/surfpool/toolchain/cli). In the manifest, these
inputs can be grouped by an environment key, making it easy to use the same
Runbook across multiple environments.

Here is an example config with environment variables:

```yaml
---
name: protocol-deployment
runbooks:
  - name: Deploy Protocol
    description: This runbook deploys the protocol.
    location: ./deployment
environments:
  development:
    network_id: localnet
    rpc_api_url: http://localhost:8899
  devnet:
    network_id: devnet
    rpc_api_url: https://api.devnet.solana.com
  mainnet:
    network_id: mainnet
    rpc_api_url: https://api.mainnet-beta.solana.com
```

In any of the `.tx` files loaded by this runbook, the inputs `input.network_id`
and `input.rpc_api_url` will be available in the global scope. When the Web UI
loads this runbook, the first action item will allow you to select which
environment to load. Selecting a new environment will reload the current runbook
with the new environment variables being injected into the execution.

### State Management

Surfpool can manage state across Runbook executions. When running contract
deployments, the state management can be used to detect any changes to the
contract code and Runbook inputs to determine if the Runbook needs to be
re-executed. Surfpool will prevent a re-execution of a Runbook if there aren't
any changes to the contract code or Runbook inputs.

To enable state management, provide the `state` value and a `location` to store
the state file in the `txtx.yml`:

```yaml
runbooks:
  - name: Deploy Protocol
    location: ./deployment
    state:
      location: states
```

## Variables

Variables can be used to store values that can be used by other constructs and
that can be edited by users in the Web UI. If the variables's `editable` field
is unspecified or set to `false`, the variable will appear on the Web UI in the
`Variables Review` section as a readonly value that can be verified. If the
`editable` field is set to `true`, however, the variable will appear as an
editable field in the Web UI. The optional `description` field can be provided
to add additional context to the variable. Here is an example variable:

```hcl
variable "my_var" {
  description = "Enter your birthday"
  value = "MM/DD/YYYY"
  editable = true
}
```

## Addons & Defaults

Addon blocks allow you to specify what addons will be used by the Runbook. Any
fields declared inside the addon block can be referenced by any actions that are
part of that addon. This will allow you to omit fields when using custom actions
from that addon. The following example declares the `svm` addon and sets the
`network_id` and `rpc_api_url` fields as defaults:

```hcl
addon "svm" {
  network_id = input.network_id
  rpc_api_url = input.rpc_api_url
}
```

With this default added to a `.tx` file, any actions from the SVM addon can omit
both the `network_id` and `rpc_api_url` fields.

## Flows

Flows allow you to execute a Runbook multiple times with different inputs for
each execution. Any fields specified in the flow block can be referenced by any
actions that are part of that flow via `flow.field_name`. This can be used in
conjunction with the `addon` block in helpful ways:

```hcl
// declare some flows
flow "solana" {
  rpc_api_url "https://api.mainnet-beta.solana.com"
}
flow "eclipse" {
  rpc_api_url "https://mainnetbeta-rpc.eclipse.xyz"
}
// declare the evm addon with
addon "svm" {
  network_id = "mainnet"
  rpc_api_url = flow.rpc_api_url
}
// the rest of the runbook can now use the svm addon without specifying chain_id or rpc_api_url,
// and will be executed once for each flow
```

## Signers

Addons can define signers that provide various ways to sign transactions when
using surfpool. These signers can be used to sign transactions via a mnemonic or
secret key, to prompt users to connect their web wallet and sign in the Surfpool
Web UI, to sign transactions asynchronously via secure enclave, to define
multisig wallets, and more. Each addon signer implementation will have its own
use cases and documentation.

Here is an example of a signer in use:

```hcl
signer "alice" "svm::web_wallet" {
  expected_address = input.expected_address
}

action "my_tx" "svm::process_instructions" {
  ... instruction data
  signers = [signer.alice]
}
```

This example defines a signer named `alice`, which uses the `svm::web_wallet`
signer. This signer definition will generate a prompt in the Web UI to connect a
wallet, provide a public key via message signature, and to sign all transactions
using this wallet as a signer.

## Actions

Actions are multi-purpose constructs that are defined by addons and by the
[standard library](/docs/tools/surfpool/iac/std/actions). Each action defines
its own set of inputs (some optional and some required) that can be supplied to
the action, what happens during each call to the action, and what outputs are
created by the action, which can be referenced by subsequent commands.

Some examples of types of actions include making http requests and outputting
the result, encoding transaction data to match a given chain's codec, signing a
transaction with a wallet and outputting the signed transaction bytes, or
broadcasting a transaction to a network.

Here is an example action:

```hcl
action "deploy_hello_world" "svm::deploy_program" {
    description = "Deploy the hello_world program"
    program = svm::get_program_from_anchor_project("hello_world")
    authority = signer.authority
    payer = signer.payer
}
output "signature" {
  value = action.deploy_hello_world.signature
}
```

## Modules

Coming soon.

## Outputs

The output command can be used to display data at the end of the runbook
execution. Here is an example of the output command:

```hcl
output "my_output" {
  description = "An example output. I hope it equals 8."
  value = 4 + 4
}
```
