AssembledTransaction
public final class AssembledTransaction : @unchecked Sendable
The main workhorse of SorobanClient. This class is used to wrap a
transaction-under-construction and provide high-level interfaces to the most
common workflows, while still providing access to low-level stellar-sdk
transaction manipulation.
Most of the time, you will not construct an AssembledTransaction directly,
but instead receive one as the return value of a SorobanClient.buildInvokeMethodTx method.
Let’s look at examples of how to use AssembledTransaction for a variety of
use-cases:
1. Simple read call
Since these only require simulation, you can get the result of the call
right after constructing your AssembledTransaction:
let clientOptions = ClientOptions(sourceAccountKeyPair: sourceAccountKeyPair,
contractId: "C123…",
network: Network.testnet,
rpcUrl: "https://…")
let txOptions = AssembledTransactionOptions(clientOptions: clientOptions,
methodOptions: MethodOptions(),
method: "myReadMethod",
arguments: args)
let tx = try await AssembledTransaction.build(options: txOptions)
let result = try tx.getSimulationData().returnedValue
While that looks pretty complicated, most of the time you will use this in
conjunction with SorobanClient, which simplifies it to:
let result = try await client.invokeMethod(name: "myReadMethod", args: args)
2. Simple write call
For write calls that will be simulated and then sent to the network without further manipulation, only one more step is needed:
let tx = try await AssembledTransaction.build(options: txOptions)
let response = try await tx.signAndSend()
if response.status == GetTransactionResponse.STATUS_SUCCESS {
let result = response.resultValue
}
If you are using it in conjunction with SorobanClient:
let result = try await client.invokeMethod(name: "myWriteMethod", args: args)
3. More fine-grained control over transaction construction
If you need more control over the transaction before simulating it, you can
set various MethodOptions when constructing your
AssembledTransaction. With a SorobanClient, this can be passed as an
argument when calling invokeMethod or buildInvokeMethodTx :
let methodOptions = MethodOptions(fee: 10000,
timeoutInSeconds: 20,
simulate: false)
let tx = try await client.buildInvokeMethodTx(name: "myWriteMethod",
args: args,
methodOptions: methodOptions)
Since we’ve skipped simulation, we can now edit the raw transaction builder and
then manually call simulate:
tx.raw?.setMemo(memo: Memo.text("Hello"))
try await tx.simulate()
If you need to inspect the simulation later, you can access it with
let data = try tx.getSimulationData()
#### 4. Multi-auth workflows
Soroban, and Stellar in general, allows multiple parties to sign a transaction.
Let’s consider an Atomic Swap contract. Alice wants to give some of her Token A tokens to Bob for some of his Token B tokens.
let swapMethodName = "swap"
let amountA = SCValXDR.i128(Int128PartsXDR(hi: 0, lo: 1000))
let minBForA = SCValXDR.i128(Int128PartsXDR(hi: 0, lo: 4500))
let amountB = SCValXDR.i128(Int128PartsXDR(hi: 0, lo: 5000))
let minAForB = SCValXDR.i128(Int128PartsXDR(hi: 0, lo: 950))
let args:[SCValXDR] = [try SCValXDR.address(SCAddressXDR(accountId: aliceId)),
try SCValXDR.address(SCAddressXDR(accountId: bobId)),
try SCValXDR.address(SCAddressXDR(contractId: tokenAContractId)),
try SCValXDR.address(SCAddressXDR(contractId: tokenBContractId)),
amountA,
minBForA,
amountB,
minAForB]
Let’s say Alice is also going to be the one signing the final transaction
envelope, meaning she is the invoker. So your app, she
simulates the swap call:
let tx = try await atomicSwapClient.buildInvokeMethodTx(name: swapMethodName,
args: args)
But your app can’t signAndSend this right away, because Bob needs to sign
it first. You can check this:
let whoElseNeedsToSign = try tx.needsNonInvokerSigningBy()
You can verify that whoElseNeedsToSign is an array of length 1,
containing only Bob’s public key.
If you have Bob’s secret key, you can sign it right away with:
let bobsKeyPair = try KeyPair(secretSeed: "S...")
try await tx.signAuthEntries(signerKeyPair: bobsKeyPair)
But if you don’t have Bob’s private key, and e.g. need to send it to another server for signing, you can provide a callback function for signing the auth entry:
let bobPublicKeyKeypair = try KeyPair(accountId: bobsAccountId)
try await tx.signAuthEntries(signerKeyPair: bobPublicKeyKeypair, authorizeEntryCallback: { (entry, network) async throws in
// You can send it to some other server for signing by encoding it as a base64xdr string
let base64Entry = entry.xdrEncoded!
// send for signing ...
// and on the other server you can decode it:
var entryToSign = try SorobanAuthorizationEntryXDR.init(fromBase64: base64Entry)
// sign it
try entryToSign.sign(signer: bobsSecretKeyPair, network: network)
// encode as a base64xdr string and send it back
let signedBase64Entry = entryToSign.xdrEncoded!
// here you can now decode it and return it
return try SorobanAuthorizationEntryXDR.init(fromBase64: signedBase64Entry)
})
To see an even more complicated example, where Alice swaps with Bob but the transaction is invoked by yet another party, check out in the SorobanClientTest.atomicSwapTest()
-
Unconstructed transaction envelope that can be modified before simulation.
Declaration
Swift
public var raw: Transaction? -
Whether the transaction has been signed by the source account.
Declaration
Swift
public var signed: Transaction? -
Soroban RPC simulation result containing resource costs, events, and return values.
Declaration
Swift
public var simulationResponse: SimulateTransactionResponse? -
Built transaction ready for submission with simulation results and resource limits applied.
Declaration
Swift
public var tx: Transaction? -
Configuration options for transaction assembly including network, contract, and method parameters.
Declaration
Swift
public let options: AssembledTransactionOptions -
Creates a new assembled transaction with specified configuration options.
Declaration
Swift
public init(options: AssembledTransactionOptions) -
build(options:Asynchronous) Builds an assembled transaction for invoking a contract method with automatic simulation.
Declaration
Swift
public static func build(options: AssembledTransactionOptions) async throws -> AssembledTransaction -
buildWithOp(operation:Asynchronousoptions: ) Builds an assembled transaction from a custom invoke host function operation.
Declaration
Swift
public static func buildWithOp(operation: InvokeHostFunctionOperation, options: AssembledTransactionOptions) async throws -> AssembledTransaction -
simulate(restore:Asynchronous) Simulates the transaction to calculate resource requirements and validate execution.
Declaration
Swift
public func simulate(restore: Bool? = nil) async throws -
restoreFootprint(restorePreamble:Asynchronous) Restores expired contract state using the restore preamble from simulation.
Declaration
Swift
public func restoreFootprint(restorePreamble: RestorePreamble) async throws -> GetTransactionResponse -
signAndSend(sourceAccountKeyPair:Asynchronousforce: ) Signs the transaction with source account and submits it to the network.
Declaration
Swift
public func signAndSend(sourceAccountKeyPair: KeyPair? = nil, force: Bool = false) async throws -> GetTransactionResponse -
Signs the transaction envelope with the source account keypair.
Declaration
Swift
public func sign(sourceAccountKeyPair: KeyPair? = nil, force: Bool = false) throws -
send()AsynchronousSubmits the signed transaction to the network and polls until completion. Returns the final transaction status including success/failure and return value.
Declaration
Swift
public func send() async throws -> GetTransactionResponse -
Returns account IDs that need to sign authorization entries for multi-auth workflows.
Declaration
Swift
public func needsNonInvokerSigningBy(includeAlreadySigned: Bool = false) throws -> [String] -
Determines if this is a read-only call requiring no signatures or network submission. Returns true if the call has no auth entries and writes no ledger data.
Declaration
Swift
public func isReadCall() throws -> Bool -
Retrieves parsed simulation data including auth entries and return value. Throws if transaction has not been simulated or simulation failed.
Declaration
Swift
public func getSimulationData() throws -> SimulateHostFunctionResult -
Signs authorization entries for multi-party transactions using keypair or callback.
Declaration
View on GitHub
Install in Dash