Stellar JS SDK
repository·main·Indexed 20 days ago
https://github.com/stellar/js-stellar-sdkA JavaScript library for interacting with the Stellar network, providing tools for building and signing transactions, querying network history, and communicating with Horizon (REST) and Soroban RPC (JSON-RPC) servers. Supports Node.js, browser, and mobile environments, and includes a CLI tool for generating TypeScript bindings from Stellar smart contracts.
What's inside @stellar/stellar-sdk
- The Contracts Client is a high-level interface designed for interacting with Soroban smart contracts. It provides a streamlined workflow to assemble transaction payloads, simulate them to predict outcomes, sign them, and finally submit them to the network. This abstraction manages the complexities of constructing the specific transaction types required for contract invocations.
Understand SimulateTransactionResponse types
mainThe
rpc.Api.SimulateTransactionResponseis a union type that simplifies the raw simulation response into three distinct interfaces based on the outcome of the simulation. This allows you to handle different scenarios (success, restoration needed, or error) using type guards or checking for specific fields.SimulateTransactionSuccessResponse: Returned when the simulation succeeds. IncludesminResourceFee,transactionData, and optionallyresult(if an invocation was simulated) andstateChanges.SimulateTransactionRestoreResponse: Returned when an expiration error occurs, indicating that a restoration is necessary before submission. It includes arestorePreamblecontaining theminResourceFeeandtransactionDatarequired to make the simulation succeed.SimulateTransactionErrorResponse: Returned for all other errors. Includes theerrorstring andevents.
How Horizon's CallFunction and CallCollectionFunction work
mainThe Horizon
ServerApiuses two primary patterns for retrieving data from the network:CallFunction<T>: Used to fetch a single resource of typeT. It returns aPromise<T>.CallCollectionFunction<T>: Used to fetch a paginated collection of resources of typeT. It returns aPromise<CollectionPage<T>>.
When calling a collection function, you can pass
CallFunctionTemplateOptionsto control the results.// Example of using CallFunctionTemplateOptions with a collection const collection = await horizonApi.someCollection({ cursor: 'some_token', limit: 10, order: 'desc' });Understand the InvocationTree structure
mainAn
InvocationTreerepresents the call stack of Soroban operations. Each node in the tree has atypeof eithercreateorexecute.createtype: UsesCreateInvocationdetails. This can be a custom contract (type: 'wasm') or a Stellar Asset Contract (type: 'sac').- For
wasm: RequiresWasmCreateDetails(address, hash, salt, and optional constructor arguments). - For
sac: Requires anassetstring.
- For
executetype: UsesExecuteInvocationdetails, specifying the contractsource, thefunctionname, and theargsarray.
Each node can contain a list of
invocations(sub-invocations) that occur as a result of that node's execution, forming a tree structure.Use the Signer interface for identity-aware signing
mainA
Signerbundles a signing function with a specific identity (address). This is preferred over bare signing callbacks because it ensures the SDK knows which address is performing the signature. Theaddresscan be aG...account address or aC...contract address for smart accounts.An interface implementing
Signermust provide:address: The string address of the signer.signTransaction: A function to sign a transaction envelope (matches SEP-43/Freighter shape).signAuthEntry(optional): A function to sign an authorization entry preimage (required for multi-party auth).
interface Signer { readonly address: string; signAuthEntry?: SignAuthEntry; signTransaction: SignTransaction; }Understand the role of AssembledTransaction
mainThe
AssembledTransactionclass is the primary tool for managing transactions under construction in theClient. It wraps a transaction and provides high-level interfaces for common workflows (like reading or writing to a contract) while allowing low-level access to the underlyingstellar-sdktransaction via the.rawproperty.Most developers interact with
AssembledTransactionindirectly by calling methods on aClientinstance, which returns anAssembledTransactionautomatically.Protocol 27: Use AddressV2 for Soroban Authorization
mainProtocol 27 introduces
AddressV2andAddressWithDelegates. While the SDK is forward-compatible, you can opt-in toADDRESS_V2credentials by passingauthV2: truetoauthorizeInvocation.// Opt-in to AddressV2 const entry = await authorizeInvocation({ signer, validUntilLedgerSeq, invocation, networkPassphrase, authV2: true, }) // Read the V2 address const addr = entry.credentials().addressV2()Understand Horizon TradeRecord types
mainA
TradeRecordin the Horizon API represents a trading pair and can be one of two types:Orderbook: A traditional order book for a trading pair.LiquidityPool: A liquidity pool record used in Stellar's Automated Market Maker (AMM) functionality.
type TradeRecord = TradeRecord.Orderbook | TradeRecord.LiquidityPoolDifference between Envelope and Authorization signatures
mainAn invoke transaction involves two distinct types of signatures:
Feature Envelope signature Authorization-entry signature Purpose Authorizes the source to submit the transaction and pay fees. Authorizes specific contract calls via require_auth().Who signs The transaction source (and classic multisig signers). Each address required by the contract (if not the source). What it signs The entire transaction hash. A specific invocation payload per address. SDK API tx.sign/signTransactionsignAuthEntries,authorizeEntryAddressV2 Impact Unchanged. Payload becomes address-bound. Note: If the account being authorized is the transaction source, the envelope signature already covers it, and no separate authorization signature is required.
Understand FeeBump and InnerTransaction responses
mainThe Horizon API uses specific response shapes for transaction-related operations:
FeeBumpTransactionResponse: Returned when bumping a transaction fee. It contains the transactionhashand an array ofsignatures.InnerTransactionResponse: Used for inner transactions, containing thehash,max_fee, andsignatures.
interface FeeBumpTransactionResponse { hash: string; signatures: string[]; } interface InnerTransactionResponse { hash: string; max_fee: string; signatures: string[]; }How the Keypair class works
mainThe
Keypairclass represents the public and (optionally) secret keys of a Stellar account. It is currently used fored25519signature systems. AKeypaircan either be a public-only key (used for verification) or a full keypair containing a secret key (used for signing).Key capabilities include:
- Generation: Creating new keys via
random(),fromSecret(), orfromPublicKey(). - Signing: Generating signatures for raw data, decorated signatures for transaction envelopes, or SEP-53 compliant messages.
- Verification: Verifying signatures against data using the public key.
- Encoding: Exporting keys to Stellar
strkeyformat, rawBufferbytes, or XDR representations.
// Example of creating a random keypair and getting its public key const keypair = Keypair.random(); console.log(keypair.publicKey()); // e.g., 'GB3KJ...' // Example of signing data (requires a secret key) if (keypair.canSign()) { const signature = keypair.sign(Buffer.from('some data')); }- Generation: Creating new keys via
Use Horizon.AccountResponse to retrieve account information
mainThe
Horizon.AccountResponseclass provides detailed information and links for a single Stellar account. It includes balances (including trust lines), account flags, thresholds, and sequence numbers. It also implements theTransactionSourceinterface, meaning it can be passed directly to aTransactionBuilderto use its data as a source for new transactions.Important: Do not instantiate this class directly using
new AccountResponse(). Instead, useHorizon.Server#loadAccountto retrieve an instance.// Correct way to get an AccountResponse const account = await server.loadAccount(accountId); // Use it in a transaction builder const transaction = new TransactionBuilder(account, network) .addOperation(operation) .build();