Skip to content

Execute a Transaction Synchronously

Executes inner instructions out of a vault in a single transaction — no stored transaction, proposal, or voting lifecycle. The outer transaction must carry enough co-signatures to reach the threshold; the program then signs the inner instructions as the vault PDA via CPI.

Use this when the signers are all available at once and you don't need an on-chain proposal record. For the full propose → vote → execute flow, use create_transaction and friends. The vault is a message signer but a PDA, so it is never passed as a transaction signer.

Program method — execute_transaction_sync

Signs with payer + each of signers, then sends.

ParameterTypeRequiredDefaultDescription
payerKeypairyesPays the fee; co-signs.
settings#to_syesThe settings account address.
smart_account#to_syesThe vault PDA the inner instructions spend from.
signersArray<#to_s · Keypair>yesCo-signers proving threshold consensus; must sign.
instructionsArray<Composers::Base>yesInner instruction composers.
account_indexIntegerno0Vault index the smart_account was derived with.

Plus the shared sign: / execute: controls and Solace::Transaction return — see Conventions.

ruby
recipient = Solace::Keypair.generate

program.execute_transaction_sync(
  payer:         creator,
  settings:      identity.settings_address,
  smart_account: identity.smart_account_address,
  signers:       [creator],
  instructions:  [
    Solace::Composers::SystemProgramTransferComposer.new(
      from:     identity.smart_account_address,
      to:       recipient.address,
      lamports: 250_000_000
    )
  ]
)

Composer — SquadsSmartAccountsExecuteTransactionSyncComposer

ParameterTypeRequiredDefaultDescription
settings#to_syesThe settings account address.
smart_account#to_syesThe vault PDA the inner instructions spend from.
signersArray<#to_s>yesCo-signer pubkeys, exactly enough to reach the threshold.
instructionsArray<Composers::Base>yesInner instruction composers.
account_indexIntegerno0Vault index the smart_account was derived with.
ruby
composer = Solace::Composers::SquadsSmartAccountsExecuteTransactionSyncComposer.new(
  settings:      identity.settings_address,
  smart_account: identity.smart_account_address,
  signers:       [creator.address],
  instructions:  [
    Solace::Composers::SystemProgramTransferComposer.new(
      from:     identity.smart_account_address,
      to:       recipient.address,
      lamports: 250_000_000
    )
  ]
)

tx = Solace::TransactionComposer.new(connection:)
                                .add_instruction(composer)
                                .set_fee_payer(creator)
                                .compose_transaction

tx.sign(creator)
connection.send_transaction(tx.serialize)

Low-level instruction (advanced)

  • Discriminator: [43, 102, 248, 89, 231, 97, 104, 134]
  • Encodes (data): account_index + num_signers + bytes(compiled_instructions) (the inner instructions serialized as a SmallVec, embedded as a Borsh bytes field)
ParameterTypeRequiredDefaultDescription
account_indexIntegeryesVault index.
num_signersIntegeryesNumber of co-signers.
instructionsArray<Solace::Instruction>yesCompiled inner instructions (resolved against the full remaining-accounts context).
settings_indexIntegeryesIndex of the settings account.
program_indexIntegeryesIndex of the Squads program.
signer_indicesArray<Integer>yesIndices of the co-signers (the leading remaining accounts).
remaining_account_indicesArray<Integer>yesIndices of the inner-instruction accounts (after the signers).

Built on Solace