Skip to main content

Interacting with Soroban via Stellar

Example SDK Usage

Some (but not all yet) of the Stellar SDKs have functions built-in to handle most of the process of building a Stellar transaction to interact with a Soroban smart contract. Below, we demonstrate in JavaScript and Python how to build and submit a Stellar transaction that will invoke an instance of the increment example smart contract.


The soroban-client JavaScript SDK is a new library that can be used alongside the existing JavaScript SDKs for Stellar. All you need to do is install it using your preferred package manager.

npm install --save soroban-client
(async () => {
const {
} = require("soroban-client");

// The source account will be used to sign and send the transaction.
const sourceKeypair = Keypair.fromSecret(

// Configure SorobanClient to use the `soroban-rpc` instance of your
// choosing.
const server = new Server("");

// Here we will use a deployed instance of the `increment` example contract.
const contractAddress =
const contract = new Contract(contractAddress);

// Transactions require a valid sequence number (which varies from one
// account to another). We fetch this sequence number from the RPC server.
const sourceAccount = await server.getAccount(sourceKeypair.publicKey());

// The transaction begins as pretty standard. The source account, minimum
// fee, and network passphrase are provided.
let builtTransaction = new TransactionBuilder(sourceAccount, {
fee: BASE_FEE,
networkPassphrase: Networks.TESTNET,
// The invocation of the `increment` function of our contract is added
// to the transaction. Note: `increment` doesn't require any parameters,
// but many contract functions do. You would need to provide those here.
// This transaction will be valid for the next 30 seconds

// We use the RPC server to "prepare" the transaction. This simulating the
// transaction, discovering the storage footprint, and updating the
// transaction to include that footprint. If you know the footprint ahead of
// time, you could manually use `addFootprint` and skip this step.
let preparedTransaction = await server.prepareTransaction(builtTransaction);

// Sign the transaction with the source account's keypair.

// Let's see the base64-encoded XDR of the transaction we just built.
`Signed prepared transaction XDR: ${preparedTransaction

// Submit the transaction to the Soroban-RPC server. The RPC server will
// then submit the transaction into the network for us. Then we will have to
// wait, polling `getTransaction` until the transaction completes.
try {
let sendResponse = await server.sendTransaction(preparedTransaction);
console.log(`Sent transaction: ${JSON.stringify(sendResponse)}`);

if (sendResponse.status === "PENDING") {
let getResponse = await server.getTransaction(sendResponse.hash);
// Poll `getTransaction` until the status is not "NOT_FOUND"
while (getResponse.status === "NOT_FOUND") {
console.log("Waiting for transaction confirmation...");
// See if the transaction is complete
getResponse = await server.getTransaction(sendResponse.hash);
// Wait one second
await new Promise((resolve) => setTimeout(resolve, 1000));

console.log(`getTransaction response: ${JSON.stringify(getResponse)}`);

if (getResponse.status === "SUCCESS") {
// Make sure the transaction's resultMetaXDR is not empty
if (!getResponse.resultMetaXdr) {
throw "Empty resultMetaXDR in getTransaction response";
// Find the return value from the contract and return it
let transactionMeta = getResponse.resultMetaXdr;
let returnValue = transactionMeta.v3().sorobanMeta().returnValue();
console.log(`Transaction result: ${returnValue.value()}`);
} else {
throw `Transaction failed: ${getResponse.resultXdr}`;
} else {
throw sendResponse.errorResultXdr;
} catch (err) {
// Catch and report any errors we've thrown
console.log("Sending transaction failed");

XDR Usage

Stellar supports invoking and deploying contracts with a new operation named InvokeHostFunctionOp. The soroban-cli abstracts these details away from the user, but not all SDKs do yet. If you're building a dapp you'll probably find yourself building the XDR transaction to submit to the network.

The InvokeHostFunctionOp can be used to perform the following Soroban operations:

  • Invoke contract functions.
  • Upload Wasm of the new contracts.
  • Deploy new contracts using the uploaded Wasm or built-in implementations (this currently includes only the token contract).

There is only a single InvokeHostFunctionOp allowed per transaction. Contracts should be used to perform multiple actions atomically, for example, to deploy a new contract and initialize it atomically.


The XDR of HostFunction and InvokeHostFunctionOp below can be found here.

union HostFunction switch (HostFunctionType type)
InvokeContractArgs invokeContract;
CreateContractArgs createContract;
opaque wasm<>;

struct InvokeHostFunctionOp
// Host function to invoke.
HostFunction hostFunction;
// Per-address authorizations for this host function.
SorobanAuthorizationEntry auth<>;


The hostFunction in InvokeHostFunctionOp will be executed by the Soroban host environment. The supported functions are:


    • This will invoke a function of the deployed contract with arguments specified in invokeContract struct.
    struct InvokeContractArgs {
    SCAddress contractAddress;
    SCSymbol functionName;
    SCVal args<>;

    contractAddress is the address of the contract to invoke, functionName is the name of the function to invoke and args are the arguments to pass to that function.


    • This will upload the contract Wasm using the provided wasm blob.
    • Uploaded Wasm can be identified by the SHA-256 hash of the uploaded Wasm.

    • This will deploy a contract instance to the network using the specified executable. The 32-byte contract identifier is based on contractIDPreimage value and the network identifier (so every network has a separate contract identifier namespace).
    struct CreateContractArgs
    ContractIDPreimage contractIDPreimage;
    ContractExecutable executable;
    • executable can be either a SHA-256 hash of the previously uploaded Wasm or it can specify that a built-in contract has to be used:
    enum ContractExecutableType

    union ContractExecutable switch (ContractExecutableType type)
    Hash wasm_hash;
    • contractIDPreimage is defined as following:

      union ContractIDPreimage switch (ContractIDPreimageType type)
      SCAddress address;
      uint256 salt;
      } fromAddress;
      Asset fromAsset;
      • The final contract identifier is created by computing SHA-256 of this together with the network identifier as a part of HashIDPreimage:
      union HashIDPreimage switch (EnvelopeType type)
      Hash networkID;
      ContractIDPreimage contractIDPreimage;
      } contractID;
      • CONTRACT_ID_PREIMAGE_FROM_ADDRESS specifies that the contract will be created using the provided address and salt. This operation has to be authorized by address (see the following section for details).
      • CONTRACT_ID_FROM_ASSET specifies that the contract will be created using the Stellar asset. This is only supported when executable == CONTRACT_EXECUTABLE_TOKEN. Note, that the asset doesn't need to exist when this is applied, however the issuer of the asset will be the initial token administrator. Anyone can deploy asset contracts.

Authorization Data

Soroban's authorization framework provides a standardized way for passing authorization data to the contract invocations via SorobanAuthorizationEntry structures.

struct SorobanAuthorizationEntry
SorobanCredentials credentials;
SorobanAuthorizedInvocation rootInvocation;

union SorobanCredentials switch (SorobanCredentialsType type)
SorobanAddressCredentials address;

SorobanAuthorizationEntry contains a tree of invocations with rootInvocation as a root. This tree is authorized by a user specified in credentials.

SorobanAddressCredentials have two options:

  • SOROBAN_CREDENTIALS_SOURCE_ACCOUNT - this simply uses the signature of the transaction (or operation, if any) source account and hence doesn't require any additional payload.
  • SOROBAN_CREDENTIALS_ADDRESS - contains SorobanAddressCredentials with the following structure:
    struct SorobanAddressCredentials
    SCAddress address;
    int64 nonce;
    uint32 signatureExpirationLedger;
    SCVec signatureArgs;
    The fields of this structure have the following semantics:
    • When address is the address that authorizes invocation.
    • signatureExpirationLedger the ledger sequence number on which the signature expires. Signature is still considered valid on signatureExpirationLedger, but it is no longer valid on signatureExpirationLedger + 1. It is recommended to keep this as small as viable, as it makes the transaction cheaper.
    • nonce is an arbitrary value that is unique for all the signatures performed by address until signatureExpirationLedger. A good approach to generating this is to just use a random value.
    • signatureArgs - signature (or multiple signatures) that sign the 32-byte SHA-256 hash of ENVELOPE_TYPE_SOROBAN_AUTHORIZATION preimage (XDR). The signature structure is defined by the account contract corresponding to the Address (see below for the Stellar account signature structure).

SorobanAuthorizedInvocation defines a node in the authorized invocation tree:

struct SorobanAuthorizedInvocation
SorobanAuthorizedFunction function;
SorobanAuthorizedInvocation subInvocations<>;

union SorobanAuthorizedFunction switch (SorobanAuthorizedFunctionType type)
SorobanAuthorizedContractFunction contractFn;
CreateContractArgs createContractHostFn;

struct SorobanAuthorizedContractFunction
SCAddress contractAddress;
SCSymbol functionName;
SCVec args;

SorobanAuthorizedInvocation consists of the function that is being authorized (either contract function or a host function) and the authorized sub-invocations that function performs (if any).

SorobanAuthorizedFunction has two variants:

  • SOROBAN_AUTHORIZED_FUNCTION_TYPE_CONTRACT_FN is a contract function that includes the address of the contract, name of the function being invoked, and arguments of the require_auth/require_auth_for_args call performed on behalf of the address. Note, that if require_auth[_for_args] wasn't called, there shouldn't be a SorobanAuthorizedInvocation entry in the transaction.
  • SOROBAN_AUTHORIZED_FUNCTION_TYPE_CREATE_CONTRACT_HOST_FN is authorization for HOST_FUNCTION_TYPE_CREATE_CONTRACT or for create_contract host function called from a contract. It only contains the CreateContractArgs XDR structure corresponding to the created contract.

Building SorobanAuthorizedInvocation trees may be simplified by using the recording auth mode in Soroban preflight (see the docs for more details).

Stellar Account Signatures

signatureArgs format is user-defined for the custom accounts, but it is protocol-defined for the Stellar accounts.

The signatures for the Stellar account are a vector of the following Soroban structures in the Soroban SDK format:

pub struct AccountEd25519Signature {
pub public_key: BytesN<32>,
pub signature: BytesN<64>,

Transaction resources

Every Soroban transaction has to have a SorobanTransactionData transaction extension populated. This is needed to compute the Soroban resource fee.

The Soroban transaction data is defined as follows:

struct SorobanResources
// The ledger footprint of the transaction.
LedgerFootprint footprint;
// The maximum number of instructions this transaction can use
uint32 instructions;

// The maximum number of bytes this transaction can read from ledger
uint32 readBytes;
// The maximum number of bytes this transaction can write to ledger
uint32 writeBytes;

struct SorobanTransactionData
SorobanResources resources;
// Portion of transaction `fee` allocated to refundable fees.
int64 refundableFee;
ExtensionPoint ext;

This data comprises two parts: Soroban resources and the refundableFee. The refundableFee is the portion of the transaction fee eligible for refund. It includes the fees for the contract events emitted by the transaction, the return value of the host function invocation, and fees for the ledger space rent.

The SorobanResources structure includes the ledger footprint and the resource values, which together determine the resource consumption limit and the resource fee. The footprint must contain the LedgerKeys that will be read and/or written.

The simplest method to determine the values in SorobanResources and refundableFee is to use the transaction simulation with preflight service.