Contracts / Client
contract.AssembledTransaction
The main workhorse of Client. 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 Client method. If
you’re familiar with the libraries generated by soroban-cli’s
contract bindings typescript command, these also wraps Client and return
AssembledTransaction instances.
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:
const { result } = await AssembledTransaction.build({ method: 'myReadMethod', args: spec.funcArgsToScVals('myReadMethod', { args: 'for', my: 'method', ... }), contractId: 'C123…', networkPassphrase: '…', rpcUrl: 'https://…', publicKey: undefined, // irrelevant, for simulation-only read calls parseResultXdr: (result: xdr.ScVal) => spec.funcResToNative('myReadMethod', result),})While that looks pretty complicated, most of the time you will use this in
conjunction with Client, which simplifies it to:
const { result } = await client.myReadMethod({ args: 'for', my: 'method', ...})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:
const assembledTx = await client.myWriteMethod({ args: 'for', my: 'method', ...})const sentTx = await assembledTx.signAndSend()Here we’re assuming that you’re using a Client, rather than
constructing AssembledTransaction’s directly.
Note that sentTx, the return value of signAndSend, is a
SentTransaction. SentTransaction is similar to
AssembledTransaction, but is missing many of the methods and fields that
are only relevant while assembling a transaction. It also has a few extra
methods and fields that are only relevant after the transaction has been
sent to the network.
Like AssembledTransaction, SentTransaction also has a result getter,
which contains the parsed final return value of the contract call. Most of
the time, you may only be interested in this, so rather than getting the
whole sentTx you may just want to:
const tx = await client.myWriteMethod({ args: 'for', my: 'method', ... })const { result } = await tx.signAndSend()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 Client, this is passed as a
second object after the arguments (or the only object, if the method takes
no arguments):
const tx = await client.myWriteMethod( { args: 'for', my: 'method', ... }, { fee: '10000', // default: {@link BASE_FEE} simulate: false, timeoutInSeconds: 20, // default: {@link DEFAULT_TIMEOUT} })Since we’ve skipped simulation, we can now edit the raw transaction and
then manually call simulate:
tx.raw.addMemo(Memo.text('Nice memo, friend!'))await tx.simulate()If you need to inspect the simulation later, you can access it with
tx.simulation.
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 10 of her Token A tokens to Bob for 5 of his Token B tokens.
const ALICE = 'G123...'const BOB = 'G456...'const TOKEN_A = 'C123…'const TOKEN_B = 'C456…'const AMOUNT_A = 10nconst AMOUNT_B = 5nLet’s say Alice is also going to be the one signing the final transaction
envelope, meaning she is the invoker. So your app, from Alice’s browser,
simulates the swap call:
const tx = await swapClient.swap({ a: ALICE, b: BOB, token_a: TOKEN_A, token_b: TOKEN_B, amount_a: AMOUNT_A, amount_b: AMOUNT_B,})But your app can’t signAndSend this right away, because Bob needs to sign
it first. You can check this:
const whoElseNeedsToSign = tx.needsNonInvokerSigningBy()You can verify that whoElseNeedsToSign is an array of length 1,
containing only Bob’s public key.
Then, still on Alice’s machine, you can serialize the transaction-under-assembly:
const json = tx.toJSON()And now you need to send it to Bob’s browser. How you do this depends on your app. Maybe you send it to a server first, maybe you use WebSockets, or maybe you have Alice text the JSON blob to Bob and have him paste it into your app in his browser (note: this option might be error-prone 😄).
Once you get the JSON blob into your app on Bob’s machine, you can deserialize it:
const tx = swapClient.txFromJSON(json)Or, if you’re using a client generated with
soroban contract bindings typescript, this deserialization will look like:
const tx = swapClient.fromJSON.swap(json)Then you can have Bob sign it. What Bob will actually need to sign is some auth entries within the transaction, not the transaction itself or the transaction envelope. Your app can verify that Bob has the correct wallet selected, then:
await tx.signAuthEntries()Under the hood, this uses signAuthEntry, which you either need to inject
during initial construction of the Client/AssembledTransaction,
or which you can pass directly to signAuthEntries.
Now Bob can again serialize the transaction and send back to Alice, where
she can finally call signAndSend().
To see an even more complicated example, where Alice swaps with Bob but the transaction is invoked by yet another party, check out test-swap.js.
class AssembledTransaction<T> { static Errors: { ExpiredState: typeof ExpiredStateError; ExternalServiceError: typeof ExternalServiceError; FakeAccount: typeof FakeAccountError; InternalWalletError: typeof InternalWalletError; InvalidClientRequest: typeof InvalidClientRequestError; NeedsMoreSignatures: typeof NeedsMoreSignaturesError; NoSignatureNeeded: typeof NoSignatureNeededError; NoSigner: typeof NoSignerError; NotYetSimulated: typeof NotYetSimulatedError; NoUnsignedNonInvokerAuthEntries: typeof NoUnsignedNonInvokerAuthEntriesError; RestorationFailure: typeof RestoreFailureError; SimulationFailed: typeof SimulationFailedError; UserRejected: typeof UserRejectedError }; static build<T>(options: AssembledTransactionOptions<T>): Promise<AssembledTransaction<T>>; static buildWithOp<T>(operation: Operation2, options: AssembledTransactionOptions<T>): Promise<AssembledTransaction<T>>; static fromJSON<T>(options: Omit<AssembledTransactionOptions<T>, "args">, __namedParameters: { simulationResult: { auth: string[]; retval: string }; simulationTransactionData: string; tx: string }): AssembledTransaction<T>; static fromXDR<T>(options: Omit<AssembledTransactionOptions<T>, "args" | "method" | "parseResultXdr">, encodedXDR: string, spec: Spec): AssembledTransaction<T>; built?: Transaction; options: AssembledTransactionOptions<T>; raw?: TransactionBuilder; signed?: Transaction; simulation?: SimulateTransactionResponse; readonly isReadCall: boolean; readonly result: T; readonly simulationData: { result: SimulateHostFunctionResult; transactionData: SorobanTransactionData }; needsNonInvokerSigningBy(__namedParameters: { includeAlreadySigned?: boolean } = {}): string[]; restoreFootprint(restorePreamble: { minResourceFee: string; transactionData: SorobanDataBuilder }, account?: Account): Promise<GetTransactionResponse>; send(watcher?: Watcher): Promise<SentTransaction<T>>; sign(__namedParameters: { force?: boolean; signTransaction?: SignTransactionLike } = {}): Promise<void>; signAndSend(__namedParameters: { force?: boolean; signTransaction?: SignTransactionLike; watcher?: Watcher } = {}): Promise<SentTransaction<T>>; signAuthEntries(__namedParameters: { address?: string; authorizeEntry?: (entry: SorobanAuthorizationEntry, signer: Keypair | SigningCallback, validUntilLedgerSeq: number, networkPassphrase: string, forAddress?: string) => Promise<SorobanAuthorizationEntry>; expiration?: number | Promise<number>; signAuthEntry?: SignAuthEntryLike } = {}): Promise<void>; simulate(__namedParameters: { restore?: boolean; useUpgradedAuth?: boolean } = {}): Promise<AssembledTransaction<T>>; toJSON(): string; toXDR(): string;}Source: src/contract/assembled_transaction.ts:261
AssembledTransaction.Errors
A list of the most important errors that various AssembledTransaction methods can throw. Feel free to catch specific errors in your application logic.
static Errors: { ExpiredState: typeof ExpiredStateError; ExternalServiceError: typeof ExternalServiceError; FakeAccount: typeof FakeAccountError; InternalWalletError: typeof InternalWalletError; InvalidClientRequest: typeof InvalidClientRequestError; NeedsMoreSignatures: typeof NeedsMoreSignaturesError; NoSignatureNeeded: typeof NoSignatureNeededError; NoSigner: typeof NoSignerError; NotYetSimulated: typeof NotYetSimulatedError; NoUnsignedNonInvokerAuthEntries: typeof NoUnsignedNonInvokerAuthEntriesError; RestorationFailure: typeof RestoreFailureError; SimulationFailed: typeof SimulationFailedError; UserRejected: typeof UserRejectedError };Source: src/contract/assembled_transaction.ts:342
AssembledTransaction.build(options)
Construct a new AssembledTransaction. This is the main way to create a new AssembledTransaction; the constructor is private.
This is an asynchronous constructor for two reasons:
- It needs to fetch the account from the network to get the current sequence number.
- It needs to simulate the transaction to get the expected fee.
If you don’t want to simulate the transaction, you can set simulate to
false in the options.
If you need to create an operation other than invokeHostFunction, you
can use AssembledTransaction.buildWithOp instead.
static build<T>(options: AssembledTransactionOptions<T>): Promise<AssembledTransaction<T>>;Parameters
options—AssembledTransactionOptions<T>(required)
Example
const tx = await AssembledTransaction.build({ ..., simulate: false,})Source: src/contract/assembled_transaction.ts:576
AssembledTransaction.buildWithOp(operation, options)
Construct a new AssembledTransaction, specifying an Operation other than
invokeHostFunction (the default used by AssembledTransaction.build).
Note: AssembledTransaction currently assumes these operations can be
simulated. This is not true for classic operations; only for those used by
Soroban Smart Contracts like invokeHostFunction and createCustomContract.
static buildWithOp<T>(operation: Operation2, options: AssembledTransactionOptions<T>): Promise<AssembledTransaction<T>>;Parameters
operation—Operation2(required)options—AssembledTransactionOptions<T>(required)
Example
const tx = await AssembledTransaction.buildWithOp( Operation.createCustomContract({ ... }); { ..., simulate: false, })Source: src/contract/assembled_transaction.ts:605
AssembledTransaction.fromJSON(options, __namedParameters)
static fromJSON<T>(options: Omit<AssembledTransactionOptions<T>, "args">, __namedParameters: { simulationResult: { auth: string[]; retval: string }; simulationTransactionData: string; tx: string }): AssembledTransaction<T>;Parameters
options—Omit<AssembledTransactionOptions<T>, "args">(required)__namedParameters—{ simulationResult: { auth: string[]; retval: string }; simulationTransactionData: string; tx: string }(required)
Source: src/contract/assembled_transaction.ts:437
AssembledTransaction.fromXDR(options, encodedXDR, spec)
Deserialize the AssembledTransaction from a base64-encoded XDR string.
static fromXDR<T>(options: Omit<AssembledTransactionOptions<T>, "args" | "method" | "parseResultXdr">, encodedXDR: string, spec: Spec): AssembledTransaction<T>;Parameters
options—Omit<AssembledTransactionOptions<T>, "args" | "method" | "parseResultXdr">(required)encodedXDR—string(required)spec—Spec(required)
Source: src/contract/assembled_transaction.ts:496
assembledTransaction.built
The Transaction as it was built with raw.build() right before
simulation. Once this is set, modifying raw will have no effect unless
you call tx.simulate() again.
built?: Transaction;Source: src/contract/assembled_transaction.ts:289
assembledTransaction.options
options: AssembledTransactionOptions<T>;Source: src/contract/assembled_transaction.ts:546
assembledTransaction.raw
The TransactionBuilder as constructed in
AssembledTransaction.build. Feel free set simulate: false to modify
this object before calling tx.simulate() manually. Example:
const tx = await myContract.myMethod( { args: 'for', my: 'method', ... }, { simulate: false });tx.raw.addMemo(Memo.text('Nice memo, friend!'))await tx.simulate();raw?: TransactionBuilder;Source: src/contract/assembled_transaction.ts:276
assembledTransaction.signed
The signed transaction.
signed?: Transaction;Source: src/contract/assembled_transaction.ts:335
assembledTransaction.simulation
The result of the transaction simulation. This is set after the first call
to simulate. It is difficult to serialize and deserialize, so it is not
included in the toJSON and fromJSON methods. See simulationData
cached, serializable access to the data needed by AssembledTransaction
logic.
simulation?: SimulateTransactionResponse;Source: src/contract/assembled_transaction.ts:298
assembledTransaction.isReadCall
Whether this transaction is a read call. This is determined by the
simulation result and the transaction data. If the transaction is a read
call, it will not need to be signed and sent to the network. If this
returns false, then you need to call signAndSend on this transaction.
readonly isReadCall: boolean;Source: src/contract/assembled_transaction.ts:1118
assembledTransaction.result
readonly result: T;Source: src/contract/assembled_transaction.ts:751
assembledTransaction.simulationData
readonly simulationData: { result: SimulateHostFunctionResult; transactionData: SorobanTransactionData };Source: src/contract/assembled_transaction.ts:708
assembledTransaction.needsNonInvokerSigningBy(__namedParameters)
Get a list of accounts, other than the invoker of the simulation, that need to sign auth entries in this transaction.
Soroban allows multiple people to sign a transaction. Someone needs to sign the final transaction envelope; this person/account is called the invoker, or source. Other accounts might need to sign individual auth entries in the transaction, if they’re not also the invoker.
This function returns a list of accounts that need to sign auth entries, assuming that the same invoker/source account will sign the final transaction envelope as signed the initial simulation.
One at a time, for each public key in this array, you will need to
serialize this transaction with toJSON, send to the owner of that key,
deserialize the transaction with txFromJson, and call
AssembledTransaction.signAuthEntries. Then re-serialize and send to
the next account in this list.
needsNonInvokerSigningBy(__namedParameters: { includeAlreadySigned?: boolean } = {}): string[];Parameters
__namedParameters—{ includeAlreadySigned?: boolean }(optional) (default:{})
Source: src/contract/assembled_transaction.ts:944
assembledTransaction.restoreFootprint(restorePreamble, account)
Restores the footprint (resource ledger entries that can be read or written) of an expired transaction.
The method will:
- Build a new transaction aimed at restoring the necessary resources.
- Sign this new transaction if a
signTransactionhandler is provided. - Send the signed transaction to the network.
- Await and return the response from the network.
Preconditions:
- A
signTransactionfunction must be provided during the Client initialization. - The provided
restorePreambleshould include a minimum resource fee and valid transaction data.
restoreFootprint(restorePreamble: { minResourceFee: string; transactionData: SorobanDataBuilder }, account?: Account): Promise<GetTransactionResponse>;Parameters
restorePreamble—{ minResourceFee: string; transactionData: SorobanDataBuilder }(required) — The preamble object containing data required to build the restore transaction.account—Account(optional) — The account that is executing the footprint restore operation. If omitted, will use the account from the AssembledTransaction.
Throws
-
- Throws an error if no
signTransactionfunction is provided during Client initialization.
- Throws an error if no
-
- Throws a custom error if the restore transaction fails, providing the details of the failure.
Source: src/contract/assembled_transaction.ts:1147
assembledTransaction.send(watcher)
Sends the transaction to the network to return a SentTransaction that
keeps track of all the attempts to fetch the transaction. Optionally pass
a Watcher that allows you to keep track of the progress as the
transaction is sent and processed.
send(watcher?: Watcher): Promise<SentTransaction<T>>;Parameters
watcher—Watcher(optional)
Source: src/contract/assembled_transaction.ts:869
assembledTransaction.sign(__namedParameters)
Sign the transaction with the signTransaction function included previously. If you did not previously include one, you need to include one now.
sign(__namedParameters: { force?: boolean; signTransaction?: SignTransactionLike } = {}): Promise<void>;Parameters
__namedParameters—{ force?: boolean; signTransaction?: SignTransactionLike }(optional) (default:{})
Source: src/contract/assembled_transaction.ts:779
assembledTransaction.signAndSend(__namedParameters)
Sign the transaction with the signTransaction function included previously.
If you did not previously include one, you need to include one now.
After signing, this method will send the transaction to the network and
return a SentTransaction that keeps track of all the attempts to fetch
the transaction. You may pass a Watcher to keep
track of this progress.
signAndSend(__namedParameters: { force?: boolean; signTransaction?: SignTransactionLike; watcher?: Watcher } = {}): Promise<SentTransaction<T>>;Parameters
__namedParameters—{ force?: boolean; signTransaction?: SignTransactionLike; watcher?: Watcher }(optional) (default:{})
Source: src/contract/assembled_transaction.ts:887
assembledTransaction.signAuthEntries(__namedParameters)
If AssembledTransaction.needsNonInvokerSigningBy returns a
non-empty list, you can serialize the transaction with toJSON, send it to
the owner of one of the public keys in the map, deserialize with
txFromJSON, and call this method on their machine. Internally, this will
use signAuthEntry function from connected wallet for each.
Then, re-serialize the transaction and either send to the next
needsNonInvokerSigningBy owner, or send it back to the original account
who simulated the transaction so they can AssembledTransaction.sign
the transaction envelope and AssembledTransaction.send it to the
network.
Sending to all needsNonInvokerSigningBy owners in parallel is not
currently supported!
signAuthEntries(__namedParameters: { address?: string; authorizeEntry?: (entry: SorobanAuthorizationEntry, signer: Keypair | SigningCallback, validUntilLedgerSeq: number, networkPassphrase: string, forAddress?: string) => Promise<SorobanAuthorizationEntry>; expiration?: number | Promise<number>; signAuthEntry?: SignAuthEntryLike } = {}): Promise<void>;Parameters
__namedParameters—{ address?: string; authorizeEntry?: (entry: SorobanAuthorizationEntry, signer: Keypair | SigningCallback, validUntilLedgerSeq: number, networkPassphrase: string, forAddress?: string) => Promise<SorobanAuthorizationEntry>; expiration?: number | Promise<number>; signAuthEntry?: SignAuthEntryLike }(optional) (default:{})
Source: src/contract/assembled_transaction.ts:1005
assembledTransaction.simulate(__namedParameters)
simulate(__namedParameters: { restore?: boolean; useUpgradedAuth?: boolean } = {}): Promise<AssembledTransaction<T>>;Parameters
__namedParameters—{ restore?: boolean; useUpgradedAuth?: boolean }(optional) (default:{})
Source: src/contract/assembled_transaction.ts:646
assembledTransaction.toJSON()
Serialize the AssembledTransaction to a JSON string. This is useful for
saving the transaction to a database or sending it over the wire for
multi-auth workflows. fromJSON can be used to deserialize the
transaction. This only works with transactions that have been simulated.
toJSON(): string;Source: src/contract/assembled_transaction.ts:364
assembledTransaction.toXDR()
Serialize the AssembledTransaction to a base64-encoded XDR string.
toXDR(): string;Source: src/contract/assembled_transaction.ts:484
contract.Client
Generate a class from the contract spec that where each contract method gets included with an identical name.
Each method returns an AssembledTransaction that can
be used to modify, simulate, decode results, and possibly sign, & submit the
transaction.
class Client { constructor(spec: Spec, options: ClientOptions); static deploy<T = Client>(args: Record<string, any> | null, options: MethodOptions & Omit<ClientOptions, "contractId"> & { address?: string; format?: "base64" | "hex"; salt?: Uint8Array<ArrayBufferLike> | Buffer<ArrayBufferLike>; wasmHash: string | Buffer<ArrayBufferLike> }): Promise<AssembledTransaction<T>>; static from<T = unknown>(options: ClientOptions): Promise<Client & T>; static fromWasm<T = unknown>(wasm: Buffer, options: ClientOptions): Promise<Client & T>; static fromWasmHash<T = unknown>(wasmHash: string | Buffer<ArrayBufferLike>, options: ClientOptions, format: "base64" | "hex" = "hex"): Promise<Client & T>; readonly options: ClientOptions; readonly spec: Spec; txFromJSON<T>(json: string): AssembledTransaction<T>; txFromXDR<T>(xdrBase64: string): AssembledTransaction<T>;}Source: src/contract/client.ts:37
new Client(spec, options)
constructor(spec: Spec, options: ClientOptions);Parameters
spec—Spec(required)options—ClientOptions(required)
Source: src/contract/client.ts:92
Client.deploy(args, options)
static deploy<T = Client>(args: Record<string, any> | null, options: MethodOptions & Omit<ClientOptions, "contractId"> & { address?: string; format?: "base64" | "hex"; salt?: Uint8Array<ArrayBufferLike> | Buffer<ArrayBufferLike>; wasmHash: string | Buffer<ArrayBufferLike> }): Promise<AssembledTransaction<T>>;Parameters
args—Record<string, any> | null(required) — Constructor/Initialization Args for the contract’s__constructormethodoptions—MethodOptions & Omit<ClientOptions, "contractId"> & { address?: string; format?: "base64" | "hex"; salt?: Uint8Array<ArrayBufferLike> | Buffer<ArrayBufferLike>; wasmHash: string | Buffer<ArrayBufferLike> }(required) — Options for initializing a Client as well as for calling a method, with extras specific to deploying.
Source: src/contract/client.ts:38
Client.from(options)
Generates a Client instance from the provided ClientOptions, which must include the contractId and rpcUrl.
If the contract is a built-in Stellar Asset Contract (SAC), the embedded SAC spec is used instead of downloading Wasm, since a SAC has no Wasm executable on-chain.
static from<T = unknown>(options: ClientOptions): Promise<Client & T>;Parameters
options—ClientOptions(required) — The ClientOptions object containing the necessary configuration, including the contractId and rpcUrl.
Returns
A Promise that resolves to a Client instance.
Throws
- If the provided options object does not contain both rpcUrl and contractId.
Example
interface MyContract { increment: (opts?: MethodOptions) => Promise<AssembledTransaction<number>>;}const client = await contract.Client.from<MyContract>(options);const tx = await client.increment(); // typedSource: src/contract/client.ts:237
Client.fromWasm(wasm, options)
Generates a Client instance from the provided ClientOptions and the contract’s wasm binary.
static fromWasm<T = unknown>(wasm: Buffer, options: ClientOptions): Promise<Client & T>;Parameters
wasm—Buffer(required) — The contract’s wasm binary as a Buffer.options—ClientOptions(required) — The ClientOptions object containing the necessary configuration.
Returns
A Promise that resolves to a Client instance.
Throws
- If the contract spec cannot be obtained from the provided wasm binary.
Example
interface MyContract { increment: (opts?: MethodOptions) => Promise<AssembledTransaction<number>>;}const client = await contract.Client.fromWasm<MyContract>(wasm, options);const tx = await client.increment(); // typedSource: src/contract/client.ts:204
Client.fromWasmHash(wasmHash, options, format)
Generates a Client instance from the provided ClientOptions and the contract’s wasm hash. The wasmHash can be provided in either hex or base64 format.
static fromWasmHash<T = unknown>(wasmHash: string | Buffer<ArrayBufferLike>, options: ClientOptions, format: "base64" | "hex" = "hex"): Promise<Client & T>;Parameters
wasmHash—string | Buffer<ArrayBufferLike>(required) — The hash of the contract’s wasm binary, in either hex or base64 format.options—ClientOptions(required) — The ClientOptions object containing the necessary configuration, including the rpcUrl.format—"base64" | "hex"(optional) (default:"hex") — (optional) The format of the provided wasmHash, either “hex” or “base64”. Defaults to “hex”.
Returns
A Promise that resolves to a Client instance.
Throws
- If the provided options object does not contain an rpcUrl.
Example
interface MyContract { increment: (opts?: MethodOptions) => Promise<AssembledTransaction<number>>;}const client = await contract.Client.fromWasmHash<MyContract>(hash, options);const tx = await client.increment(); // typedSource: src/contract/client.ts:162
client.options
readonly options: ClientOptions;Source: src/contract/client.ts:94
client.spec
readonly spec: Spec;Source: src/contract/client.ts:93
client.txFromJSON(json)
txFromJSON<T>(json: string): AssembledTransaction<T>;Parameters
json—string(required)
Source: src/contract/client.ts:269
client.txFromXDR(xdrBase64)
txFromXDR<T>(xdrBase64: string): AssembledTransaction<T>;Parameters
xdrBase64—string(required)
Source: src/contract/client.ts:282
contract.DEFAULT_TIMEOUT
The default timebounds, in seconds, during which a transaction will be valid. This is attached to the transaction before transaction simulation (it is needed for simulation to succeed). It is also re-calculated and re-added before transaction signing.
const DEFAULT_TIMEOUT: numberSource: src/contract/types.ts:311
contract.KeypairSigner
A Signer backed by a local Keypair.
Suitable for Node applications, scripts, and tests — anywhere the secret key
lives in the same process. For browser applications, use the SEP-43 wallet’s
own signTransaction, or wrap it in an object satisfying Signer.
class KeypairSigner implements Signer { constructor(keypair: Keypair, networkPassphrase: string); readonly address: string; signAuthEntry: SignAuthEntry; signTransaction: SignTransaction;}Example
import { Keypair } from "@stellar/stellar-sdk";import { Client, KeypairSigner } from "@stellar/stellar-sdk/contract";
const keypair = Keypair.fromSecret(secret);const client = await Client.from({ contractId, networkPassphrase, rpcUrl, publicKey: keypair.publicKey(), signTransaction: new KeypairSigner(keypair, networkPassphrase),});Source: src/contract/signer.ts:58
new KeypairSigner(keypair, networkPassphrase)
constructor(keypair: Keypair, networkPassphrase: string);Parameters
keypair—Keypair(required) — theKeypairto sign with. Signing throwscannot sign: no secret key availableif it holds only a public key.networkPassphrase—string(required) — passphrase of the network to sign for, used whenever the caller does not pass one at signing time
Source: src/contract/signer.ts:70
keypairSigner.address
The keypair’s Ed25519 account address (G…), always keypair.publicKey().
readonly address: string;Source: src/contract/signer.ts:62
keypairSigner.signAuthEntry
Signs an auth entry preimage. Matches signAuthEntry from Freighter.
signAuthEntry: SignAuthEntry;Source: src/contract/signer.ts:103
keypairSigner.signTransaction
Signs a transaction envelope. Matches signTransaction from Freighter.
signTransaction: SignTransaction;Source: src/contract/signer.ts:88
contract.NULL_ACCOUNT
An impossible account on the Stellar network
const NULL_ACCOUNT: "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWHF"Source: src/contract/types.ts:317
contract.SentTransaction
A transaction that has been sent to the Soroban network. This happens in two steps:
sendTransaction: initial submission of the transaction to the network. If this step runs into problems, the attempt to sign and send will be aborted. You can see the result of this call in thesendTransactionResponsegetter.getTransaction: once the transaction has been submitted to the network successfully, you need to wait for it to finalize to get the result of the transaction. This will be retried with exponential backoff forMethodOptions.timeoutInSecondsseconds. See all attempts ingetTransactionResponseAlland the most recent attempt ingetTransactionResponse.
class SentTransaction<T> { constructor(assembled: AssembledTransaction<T>); static Errors: { SendFailed: typeof SendFailedError; SendResultOnly: typeof SendResultOnlyError; TransactionStillPending: typeof TransactionStillPendingError }; static init<U>(assembled: AssembledTransaction<U>, watcher?: Watcher): Promise<SentTransaction<U>>; assembled: AssembledTransaction<T>; getTransactionResponse?: GetTransactionResponse; getTransactionResponseAll?: GetTransactionResponse[]; sendTransactionResponse?: SendTransactionResponse; server: RpcServer; readonly result: T;}Source: src/contract/sent_transaction.ts:28
new SentTransaction(assembled)
constructor(assembled: AssembledTransaction<T>);Parameters
assembled—AssembledTransaction<T>(required)
Source: src/contract/sent_transaction.ts:57
SentTransaction.Errors
static Errors: { SendFailed: typeof SendFailedError; SendResultOnly: typeof SendResultOnlyError; TransactionStillPending: typeof TransactionStillPendingError };Source: src/contract/sent_transaction.ts:51
SentTransaction.init(assembled, watcher)
Initialize a SentTransaction from AssembledTransaction
assembled, passing an optional Watcher watcher. This will also
send the transaction to the network.
static init<U>(assembled: AssembledTransaction<U>, watcher?: Watcher): Promise<SentTransaction<U>>;Parameters
assembled—AssembledTransaction<U>(required) —AssembledTransactionfrom which this SentTransaction was initializedwatcher—Watcher(optional)
Source: src/contract/sent_transaction.ts:67
sentTransaction.assembled
assembled: AssembledTransaction<T>;Source: src/contract/sent_transaction.ts:57
sentTransaction.getTransactionResponse
The most recent result of calling getTransaction, from the
getTransactionResponseAll array.
getTransactionResponse?: GetTransactionResponse;Source: src/contract/sent_transaction.ts:49
sentTransaction.getTransactionResponseAll
If sendTransaction completes successfully (which means it has status: 'PENDING'),
then getTransaction will be called in a loop for
MethodOptions.timeoutInSeconds seconds. This array contains all
the results of those calls.
getTransactionResponseAll?: GetTransactionResponse[];Source: src/contract/sent_transaction.ts:43
sentTransaction.sendTransactionResponse
The result of calling sendTransaction to broadcast the transaction to the
network.
sendTransactionResponse?: SendTransactionResponse;Source: src/contract/sent_transaction.ts:35
sentTransaction.server
server: RpcServer;Source: src/contract/sent_transaction.ts:29
sentTransaction.result
readonly result: T;Source: src/contract/sent_transaction.ts:132
contract.Spec
Provides a ContractSpec class which can contains the XDR types defined by the contract.
This allows the class to be used to convert between native and raw xdr.ScVals.
Constructs a new ContractSpec from an array of XDR spec entries.
class Spec { constructor(entries: string | string[] | Buffer<ArrayBufferLike> | ScSpecEntry[]); static fromWasm(wasm: Buffer): Spec; entries: ScSpecEntry[]; errorCases(): ScSpecUdtErrorEnumCaseV0[]; events(): ScSpecEventV0[]; eventTopicFilter(name: string, topicValues?: Record<string, any>, occurrence?: number): string[]; findEntry(name: string): ScSpecEntry; findEvent(name: string, occurrence?: number): ScSpecEventV0 | undefined; funcArgsToScVals(name: string, args: object): ScVal[]; funcResToNative(name: string, val_or_base64: string | ScVal): any; funcs(): ScSpecFunctionV0[]; getFunc(name: string): ScSpecFunctionV0; jsonSchema(funcName?: string): JSONSchema7; nativeToScVal(val: any, ty: ScSpecTypeDef): ScVal; parseEvent(topics: string[] | ScVal[], data: string | ScVal): ParsedEvent | undefined; scValStrToNative<T>(scv: string, typeDef: ScSpecTypeDef): T; scValToNative<T>(scv: ScVal, typeDef: ScSpecTypeDef): T;}Example
const specEntries = [...]; // XDR spec entries of a smart contractconst contractSpec = new ContractSpec(specEntries);
// Convert native value to ScValconst args = { arg1: 'value1', arg2: 1234};const scArgs = contractSpec.funcArgsToScVals('funcName', args);
// Call contractconst resultScv = await callContract(contractId, 'funcName', scArgs);
// Convert result ScVal back to native valueconst result = contractSpec.funcResToNative('funcName', resultScv);
console.log(result); // {success: true}Source: src/contract/spec.ts:502
new Spec(entries)
Generates a Spec instance from contract specs in any of the following forms:
- An XDR encoded stream of xdr.ScSpecEntry entries, the format of the spec stored inside Wasm files.
- A base64 XDR encoded stream of xdr.ScSpecEntry entries.
- An array of xdr.ScSpecEntry.
- An array of base64 XDR encoded xdr.ScSpecEntry.
constructor(entries: string | string[] | Buffer<ArrayBufferLike> | ScSpecEntry[]);Parameters
entries—string | string[] | Buffer<ArrayBufferLike> | ScSpecEntry[](required)
Returns
A Promise that resolves to a Client instance.
Throws
- If the contract spec cannot be obtained from the provided wasm binary.
Source: src/contract/spec.ts:531
Spec.fromWasm(wasm)
Generates a Spec instance from the contract’s wasm binary.
static fromWasm(wasm: Buffer): Spec;Parameters
wasm—Buffer(required) — The contract’s wasm binary as a Buffer.
Returns
A Promise that resolves to a Spec instance.
Throws
- If the contract spec cannot be obtained from the provided wasm binary.
Source: src/contract/spec.ts:515
spec.entries
The XDR spec entries.
entries: ScSpecEntry[];Source: src/contract/spec.ts:506
spec.errorCases()
Gets the XDR error cases from the spec.
errorCases(): ScSpecUdtErrorEnumCaseV0[];Returns
all contract functions
Source: src/contract/spec.ts:1209
spec.events()
Gets the SEP-48 event spec entries from the spec.
events(): ScSpecEventV0[];Returns
all contract events
Source: src/contract/spec.ts:1224
spec.eventTopicFilter(name, topicValues, occurrence)
Builds a getEvents topic filter (a single row of Api.EventFilter.topics)
for the named event: base64-encoded scvSymbols for the event’s prefix
topics, followed by one entry per topic-list param — either the
base64-encoded ScVal for a value supplied in topicValues, or the
wildcard "*".
eventTopicFilter(name: string, topicValues?: Record<string, any>, occurrence?: number): string[];Parameters
name—string(required) — the name of the eventtopicValues—Record<string, any>(optional) — (optional) native values for topic-list params, keyed by param nameoccurrence—number(optional) — (optional) 0-based index among same-named events, in declaration order, for contracts that declare the same event name more than once (defaults to the first)
Returns
a single topic filter row
Throws
- if no event with the given name (at the given occurrence) exists,
or if
occurrenceis not a non-negative integer
Example
const topics = contractSpec.eventTopicFilter('transfer', { to: someAddress });Source: src/contract/spec.ts:1312
spec.findEntry(name)
Finds the XDR spec entry for the given name.
findEntry(name: string): ScSpecEntry;Parameters
name—string(required) — the name to find
Returns
the entry
Throws
- if no entry with the given name exists
Source: src/contract/spec.ts:658
spec.findEvent(name, occurrence)
Finds the XDR event spec for the given event name.
Unlike Spec.findEntry, a missing event is not an error: this
returns undefined so callers can probe a contract for an event without
wrapping the call in a try.
findEvent(name: string, occurrence?: number): ScSpecEventV0 | undefined;Parameters
name—string(required) — the name of the eventoccurrence—number(optional) — (optional) 0-based index among same-named events, in declaration order, for contracts that declare the same event name more than once (defaults to the first)
Returns
the event spec, or undefined if the contract declares no event
with that name (at that occurrence)
Throws
- if
occurrenceis not a non-negative integer
Example
if (contractSpec.findEvent("transfer")) { // the contract declares a "transfer" event}Source: src/contract/spec.ts:1251
spec.funcArgsToScVals(name, args)
Converts native JS arguments to ScVals for calling a contract function.
funcArgsToScVals(name: string, args: object): ScVal[];Parameters
name—string(required) — the name of the functionargs—object(required) — the arguments object
Returns
the converted arguments
Throws
- if argument is missing or incorrect type
Example
const args = { arg1: 'value1', arg2: 1234};const scArgs = contractSpec.funcArgsToScVals('funcName', args);Source: src/contract/spec.ts:601
spec.funcResToNative(name, val_or_base64)
Converts the result ScVal of a function call to a native JS value.
funcResToNative(name: string, val_or_base64: string | ScVal): any;Parameters
name—string(required) — the name of the functionval_or_base64—string | ScVal(required) — the result ScVal or base64 encoded string
Returns
the converted native value
Throws
- if return type mismatch or invalid input
Example
const resultScv = 'AAA=='; // Base64 encoded ScValconst result = contractSpec.funcResToNative('funcName', resultScv);Source: src/contract/spec.ts:623
spec.funcs()
Gets the XDR functions from the spec.
funcs(): ScSpecFunctionV0[];Returns
all contract functions
Source: src/contract/spec.ts:555
spec.getFunc(name)
Gets the XDR function spec for the given function name.
getFunc(name: string): ScSpecFunctionV0;Parameters
name—string(required) — the name of the function
Returns
the function spec
Throws
- if no function with the given name exists
Source: src/contract/spec.ts:573
spec.jsonSchema(funcName)
Converts the contract spec to a JSON schema.
If funcName is provided, the schema will be a reference to the function schema.
jsonSchema(funcName?: string): JSONSchema7;Parameters
funcName—string(optional) — (optional) the name of the function to convert
Returns
the converted JSON schema
Throws
- if the contract spec is invalid
Source: src/contract/spec.ts:1336
spec.nativeToScVal(val, ty)
Converts a native JS value to an ScVal based on the given type.
nativeToScVal(val: any, ty: ScSpecTypeDef): ScVal;Parameters
val—any(required) — the native JS valuety—ScSpecTypeDef(required) — (optional) the expected type
Returns
the converted ScVal
Throws
- if value cannot be converted to the given type
Source: src/contract/spec.ts:677
spec.parseEvent(topics, data)
Attempts to parse an emitted contract event (its topics and data) using the event specs (SEP-48) declared in this contract’s spec.
An event’s topics are [...prefixTopics, ...topicListParamValues] (in
that order), and its data is decoded according to the event’s
dataFormat (singleValue, vec, or map).
parseEvent(topics: string[] | ScVal[], data: string | ScVal): ParsedEvent | undefined;Parameters
topics—string[] | ScVal[](required) — the event’s topics, asxdr.ScVal[]or base64 XDR stringsdata—string | ScVal(required) — the event’s data, as anxdr.ScValor a base64 XDR string
Returns
the parsed event (its name plus all decoded params — topic-list
and data-located alike — merged into data), or undefined if
no event spec matches (e.g. when filtering a mixed stream of
events from multiple contracts/specs)
Note that matching compares only the prefix topics and the topic count; if two event specs share both (in particular, events with no prefix topics match on arity alone), the first declared spec whose values decode successfully wins.
Example
const parsed = contractSpec.parseEvent(response.topic, response.value);if (parsed) { console.log(parsed.name, parsed.data);}Source: src/contract/spec.ts:1283
spec.scValStrToNative(scv, typeDef)
Converts an base64 encoded ScVal back to a native JS value based on the given type.
scValStrToNative<T>(scv: string, typeDef: ScSpecTypeDef): T;Parameters
scv—string(required) — the base64 encoded ScValtypeDef—ScSpecTypeDef(required) — the expected type
Returns
the converted native JS value
Throws
- if ScVal cannot be converted to the given type
Source: src/contract/spec.ts:994
spec.scValToNative(scv, typeDef)
Converts an ScVal back to a native JS value based on the given type.
scValToNative<T>(scv: ScVal, typeDef: ScSpecTypeDef): T;Parameters
scv—ScVal(required) — the ScValtypeDef—ScSpecTypeDef(required) — the expected type
Returns
the converted native JS value
Throws
- if ScVal cannot be converted to the given type
Source: src/contract/spec.ts:1007
contract.Watcher
class Watcher { constructor(); onProgress(response?: GetTransactionResponse): void; onSubmitted(response?: SendTransactionResponse): void;}Source: src/contract/sent_transaction.ts:167
new Watcher()
constructor();watcher.onProgress(response)
Function to call every time the submitted transaction’s status is checked while awaiting its full inclusion in the ledger
onProgress(response?: GetTransactionResponse): void;Parameters
response—GetTransactionResponse(optional)
Source: src/contract/sent_transaction.ts:178
watcher.onSubmitted(response)
Function to call after transaction has been submitted successfully to the network for processing
onSubmitted(response?: SendTransactionResponse): void;Parameters
response—SendTransactionResponse(optional)
Source: src/contract/sent_transaction.ts:172
contract.basicNodeSigner
For use with Client and contract.AssembledTransaction.
Implements signTransaction and signAuthEntry with signatures expected by
those classes. This is useful for testing and maybe some simple Node
applications. Feel free to use this as a starting point for your own
Wallet/TransactionSigner implementation.
Prefer KeypairSigner, which does the same thing and also carries the
signer’s address, so you can pass one object instead of spreading two
functions. You can also pass a Keypair directly as signTransaction.
basicNodeSigner(keypair: Keypair, networkPassphrase: string): { signAuthEntry: SignAuthEntry; signTransaction: SignTransaction }Parameters
keypair—Keypair(required) —Keypairto use to sign the transaction or auth entrynetworkPassphrase—string(required) — passphrase of network to sign for
Source: src/contract/basic_node_signer.ts:20
Types
contract.AssembledTransactionOptions
type AssembledTransactionOptions<T = string> = MethodOptions & ClientOptions & { address?: string; args?: any[]; method: string; parseResultXdr: (xdr: xdr.ScVal) => T; submit?: boolean; submitUrl?: string }Source: src/contract/types.ts:279
contract.ClientOptions
Options for a smart contract client.
type ClientOptions = { allowHttp?: boolean; contractId: string; errorTypes?: Record<number, { message: string }>; headers?: Record<string, string>; networkPassphrase: string; publicKey?: string; rpcUrl: string; server?: Server; signAuthEntry?: SignAuthEntryLike; signTransaction?: SignTransactionLike }Source: src/contract/types.ts:129
contract.Duration
An unsigned 64-bit integer.
type Duration = bigintSource: src/contract/types.ts:55
contract.ErrorMessage
Error interface containing the error message. Matches Rust’s implementation.
Part of implementing Result, a minimal
implementation of Rust’s Result type. Used for contract methods that return
Results, to maintain their distinction from methods that simply either return
a value or throw.
interface ErrorMessage { message: string;}Source: src/contract/rust_result.ts:51
errorMessage.message
message: string;Source: src/contract/rust_result.ts:52
contract.MethodOptions
Options for a smart contract method invocation.
type MethodOptions = { fee?: string; publicKey?: string; restore?: boolean; signAuthEntry?: SignAuthEntryLike; signTransaction?: SignTransactionLike; simulate?: boolean; timeoutInSeconds?: number; useUpgradedAuth?: boolean }Source: src/contract/types.ts:207
contract.Option
type Option<T> = T | undefinedSource: src/contract/types.ts:43
contract.ParsedEvent
The result of successfully matching an emitted contract event against one
of the event specs (xdr.ScSpecEventV0) defined in a Spec.
interface ParsedEvent { data: Record<string, any>; name: string;}See also
- Spec.parseEvent
Source: src/contract/event_spec.ts:10
parsedEvent.data
All decoded event params, keyed by param name — both the
topicList-located params and the data-located ones. Once an event is
parsed, where a param was carried (topic vs data) no longer matters;
the topic list is just a way to mark which fields are indexed.
data: Record<string, any>;Source: src/contract/event_spec.ts:19
parsedEvent.name
The name of the matched event (the event spec’s declared name).
name: string;Source: src/contract/event_spec.ts:12
contract.Result
A minimal implementation of Rust’s Result type. Used for contract
methods that return Results, to maintain their distinction from methods
that simply either return a value or throw.
Why is this needed?
This is used by ContractSpec and
AssembledTransaction when
parsing values return by contracts.
Contract methods can be implemented to return simple values, in which case
they can also throw errors. This matches JavaScript’s most idiomatic
workflow, using try...catch blocks.
But Rust also gives the flexibility of returning Result types. And Soroban
contracts further support this with the #[contracterror] macro. Should
JavaScript calls to such methods ignore all of that, and just flatten this
extra info down to the same try...catch flow as other methods? We’re not
sure.
For now, we’ve added this minimal implementation of Rust’s Result logic,
which exports the Result interface and its associated implementations,
Ok and Err. This allows ContractSpec and AssembledTransaction to
work together to duplicate the contract’s Rust logic, always returning
Result types for contract methods that are implemented to do so.
In the future, if this feels too un-idiomatic for JavaScript, we can always
remove this and flatten all JS calls to try...catch. Easier to remove this
logic later than it would be to add it.
interface Result<T, E extends ErrorMessage = ErrorMessage> { isErr(): boolean; isOk(): boolean; unwrap(): T; unwrapErr(): E;}Source: src/contract/rust_result.ts:36
result.isErr()
isErr(): boolean;Source: src/contract/rust_result.ts:40
result.isOk()
isOk(): boolean;Source: src/contract/rust_result.ts:39
result.unwrap()
unwrap(): T;Source: src/contract/rust_result.ts:37
result.unwrapErr()
unwrapErr(): E;Source: src/contract/rust_result.ts:38
contract.SignAuthEntry
A function to request a wallet to sign an authorization entry preimage.
Similar to signing a transaction, this function takes an authorization entry preimage provided by the requester and applies a signature to it. It returns a signed hash of the same authorization entry and the signer address back to the requester.
type SignAuthEntry = (authEntry: string, opts?: { address?: string; networkPassphrase?: string }) => Promise<{ signedAuthEntry: string; signerAddress?: string } & { error?: WalletError }>Source: src/contract/types.ts:113
contract.SignAuthEntryLike
Anything accepted where a signAuthEntry callback is expected: the raw
SEP-43 callback, a Signer, or a Keypair.
type SignAuthEntryLike = SignAuthEntry | Signer | KeypairSource: src/contract/signer.ts:125
contract.SignTransaction
A function to request a wallet to sign a built transaction
This function takes an XDR provided by the requester and applies a signature to it. It returns a base64-encoded string XDR-encoded Transaction Envelope with Decorated Signatures and the signer address back to the requester.
type SignTransaction = (xdr: string, opts?: { address?: string; networkPassphrase?: string; submit?: boolean; submitUrl?: string }) => Promise<{ signedTxXdr: string; signerAddress?: string } & { error?: WalletError }>Source: src/contract/types.ts:84
contract.SignTransactionLike
Anything accepted where a signTransaction callback is expected: the raw
SEP-43 callback, a Signer, or a Keypair.
type SignTransactionLike = SignTransaction | Signer | KeypairSource: src/contract/signer.ts:119
contract.Signer
A signing identity: something that can sign, and that knows who it is.
A bare SignTransaction callback carries no identity, so callers have
to pass the signer’s address alongside it and keep the two in sync. A
Signer bundles them.
address is deliberately a plain string rather than an Ed25519 public key:
it is a G… account address for keypair-backed signers, but may be a C…
contract address for smart accounts, whose signatures are not Ed25519 at all.
signTransaction and signAuthEntry keep the exact shapes the SDK already
accepts (those of SEP-43 wallets such as Freighter), so an existing wallet
object becomes a Signer by gaining an address.
signAuthEntry is optional because not every wallet implements it; it is
only needed for multi-party (non-invoker) auth entry signing.
Accepted wherever the SDK takes a signing callback: the signTransaction and
signAuthEntry options on ClientOptions and MethodOptions, and the
per-call overrides on AssembledTransaction’s sign, signAndSend, and
signAuthEntries.
interface Signer { readonly address: string; signAuthEntry?: SignAuthEntry; signTransaction: SignTransaction;}Source: src/contract/signer.ts:27
signer.address
The address this signer signs as: G… for accounts, C… for contracts.
readonly address: string;Source: src/contract/signer.ts:29
signer.signAuthEntry
Signs an auth entry preimage. Matches signAuthEntry from Freighter.
signAuthEntry?: SignAuthEntry;Source: src/contract/signer.ts:33
signer.signTransaction
Signs a transaction envelope. Matches signTransaction from Freighter.
signTransaction: SignTransaction;Source: src/contract/signer.ts:31
contract.Timepoint
An unsigned 64-bit integer.
type Timepoint = bigintSource: src/contract/types.ts:51
contract.Tx
A “regular” transaction, as opposed to a FeeBumpTransaction.
type Tx = TransactionSource: src/contract/types.ts:60
contract.Typepoint
Deprecated. Use Timepoint instead.
type Typepoint = bigintSource: src/contract/types.ts:47
contract.Union
interface Union<T> { tag: string; values?: T;}Source: src/contract/spec.ts:25
union.tag
tag: string;Source: src/contract/spec.ts:26
union.values
values?: T;Source: src/contract/spec.ts:27
contract.WalletError
interface WalletError { code: number; ext?: string[]; message: string;}Source: src/contract/types.ts:62
walletError.code
code: number;Source: src/contract/types.ts:64
walletError.ext
ext?: string[];Source: src/contract/types.ts:65
walletError.message
message: string;Source: src/contract/types.ts:63
contract.XDR_BASE64
type XDR_BASE64 = stringSource: src/contract/types.ts:10
contract.i128
A signed 128-bit integer.
type i128 = bigintSource: src/contract/types.ts:34
contract.i256
A signed 256-bit integer.
type i256 = bigintSource: src/contract/types.ts:42
contract.i32
A signed 32-bit integer.
type i32 = numberSource: src/contract/types.ts:18
contract.i64
A signed 64-bit integer.
type i64 = bigintSource: src/contract/types.ts:26
contract.u128
An unsigned 128-bit integer.
type u128 = bigintSource: src/contract/types.ts:30
contract.u256
An unsigned 256-bit integer.
type u256 = bigintSource: src/contract/types.ts:38
contract.u32
An unsigned 32-bit integer.
type u32 = numberSource: src/contract/types.ts:14
contract.u64
An unsigned 64-bit integer.
type u64 = bigintSource: src/contract/types.ts:22