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.- JavaScript
- Python
- Java
XDR Usage
Stellar supports invoking and deploying contracts with a new operation namedInvokeHostFunctionOp. The stellar-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).
InvokeHostFunctionOp allowed per transaction. Contracts should be used to perform multiple actions atomically, for example, to deploy a new contract and initialize it atomically.
Additionally, Soroban transactions containing InvokeHostFunctionOp have the following restrictions:
- The transaction cannot include a memo — the memo must be set to
MEMO_NONE. - The transaction source account cannot be a muxed account.
- The operation source account, if set, cannot be a muxed account.
InvokeHostFunctionOp
The XDR ofHostFunction and InvokeHostFunctionOp below can be found here.
Function
ThehostFunction in InvokeHostFunctionOp will be executed by the Soroban host environment. The supported functions are:
-
HOST_FUNCTION_TYPE_INVOKE_CONTRACT- This will invoke a function of the deployed contract with arguments specified in
invokeContractstruct.
contractAddressis the address of the contract to invoke,functionNameis the name of the function to invoke andargsare the arguments to pass to that function. - This will invoke a function of the deployed contract with arguments specified in
-
HOST_FUNCTION_TYPE_UPLOAD_CONTRACT_WASM- This will upload the contract Wasm using the provided
wasmblob. - Uploaded Wasm can be identified by the SHA-256 hash of the uploaded Wasm.
- This will upload the contract Wasm using the provided
-
HOST_FUNCTION_TYPE_CREATE_CONTRACT- This will deploy a contract instance to the network using the specified
executable. The 32-byte contract identifier is based oncontractIDPreimagevalue and the network identifier (so every network has a separate contract identifier namespace).
executablecan be either a SHA-256 hash of the previously uploaded Wasm or it can specify that a built-in contract has to be used:
-
contractIDPreimageis defined as following:- The final contract identifier is created by computing SHA-256 of this together with the network identifier as a part of
HashIDPreimage:
CONTRACT_ID_PREIMAGE_FROM_ADDRESSspecifies that the contract will be created using the provided address and salt. This operation has to be authorized byaddress(see the following section for details).CONTRACT_ID_PREIMAGE_FROM_ASSETspecifies that the contract will be created using the Stellar asset. This is only supported whenexecutable == CONTRACT_EXECUTABLE_STELLAR_ASSET. 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.
- The final contract identifier is created by computing SHA-256 of this together with the network identifier as a part of
- This will deploy a contract instance to the network using the specified
JavaScript Usage
Each of these variations of host function invocation has convenience methods in the JavaScript SDK:Operation.invokeHostFunctionis the lowest-level method that corresponds directly to the XDR.Operation.invokeContractFunctionis an abstraction to invoke the method of a particular contract, similar toContract.call.Operation.createStellarAssetContractandOperation.createCustomContractare abstractions to instantiate contracts: the former is for wrapping an existing Stellar asset into a smart contract and the latter is for deploying your own contract.Operation.uploadContractWasmcorresponds to the aboveHOST_FUNCTION_TYPE_UPLOAD_CONTRACT_WASMvariant, letting you upload the raw WASM buffer to the ledger.
Authorization Data
Soroban’s authorization framework provides a standardized way for passing authorization data to the contract invocations viaSorobanAuthorizationEntry structures.
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- containsSorobanAddressCredentialswith the following structure:The fields of this structure have the following semantics:- When
addressis the address that authorizes invocation. signatureExpirationLedgerthe ledger sequence number on which the signature expires. Signature is still considered valid onsignatureExpirationLedger, but it is no longer valid onsignatureExpirationLedger + 1. It is recommended to keep this as small as viable, as it makes the transaction cheaper.nonceis an arbitrary value that is unique for all the signatures performed byaddressuntilsignatureExpirationLedger. A good approach to generating this is to just use a random value.signatureis a structure containing the signature (or multiple signatures) that signed the 32-byte, SHA-256 hash of theENVELOPE_TYPE_SOROBAN_AUTHORIZATIONpreimage (XDR). The signature structure is defined by the account contract corresponding to theAddress(see below for the Stellar account signature structure).
- When
SorobanAuthorizedInvocation defines a node in the authorized invocation tree:
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_FNis a contract function that includes the address of the contract, name of the function being invoked, and arguments of therequire_auth/require_auth_for_argscall performed on behalf of the address. Note, that ifrequire_auth[_for_args]wasn’t called, there shouldn’t be aSorobanAuthorizedInvocationentry in the transaction.SOROBAN_AUTHORIZED_FUNCTION_TYPE_CREATE_CONTRACT_HOST_FNis authorization forHOST_FUNCTION_TYPE_CREATE_CONTRACTor forcreate_contracthost function called from a contract. It only contains theCreateContractArgsXDR structure corresponding to the created contract.
SorobanAuthorizedInvocation trees may be simplified by using the recording auth mode in Soroban’s simulateTransaction mechanism (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:
JavaScript Usage
There are a couple of helpful methods in the SDK to make dealing with authorization easier:- Once you’ve gotten the authorization entries from
simulateTransaction, you can use theauthorizeEntryhelper to “fill out” the empty entry accordingly. You will, of course, need the appropriate signer for each of the entries if you are in a multi-party situation.
- If you, instead, want to build an authorization entry from scratch rather than relying on simulation, you can use
authorizeInvocation, which will build the structure with the appropriate fields.
Transaction resources
Every Soroban transaction has to have aSorobanTransactionData transaction extension populated. This is needed to compute the Soroban resource fee.
The Soroban transaction data is defined as follows:
resources and the resourceFee. The resourceFee is the portion of the transaction fee allocated to Soroban resource fees. It has a non-refundable part (fees for instructions, ledger I/O, and transaction size) and a refundable part that is charged based on actual consumption of refundable resources: the contract events emitted by the transaction, the return value of the host function invocation, and 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 resourceFee is to use the simulateTransaction mechanism.
JavaScript Usage
You can use theSorobanDataBuilder to leverage the builder pattern and get/set all of the above resources accordingly. Then, you call .build() and pass the resulting structure to the setSorobanData method of the corresponding TransactionBuilder.