This update to the JavaScript SDK brings a lot of significant changes:
- Support for Protocol 20, which introduces the Soroban smart contract platform to the Stellar network.
- Support for Soroban RPC, a new web service unrelated to Horizon built around smart contract interactions.
- A build system overhaul to Webpack 5 and ES6, meaning downstream systems will need to either transpile the library or update their build systems in turn in order to support the new bundles.
- Tons of security fixes and performance optimizations that were enabled by the above, namely through updating all of the dependencies to their latest and greatest versions.
Traditionally, this SDK was a way to do two things:
- Build Stellar transactions, and
- interact with Horizon.
Because there is a new web service to interact with, there has been a significant overhaul in the structure of the modules in the SDK to properly support both Horizon and Soroban RPC. So now, we have:
- In
stellar-sdk
's default import, you can build Stellar transactions, and - In
stellar-sdk
'sHorizon
namespace (or instellar-sdk/horizon
), you can interact with Horizon. - In
stellar-sdk
'sSorobanRpc
namespace (or instellar-sdk/soroban
), you can interact with Soroban RPC.
There are now three primary namespaces in the SDK, each of which differs in responsibility depending on what you want to achieve:
- If you want to build operations, deal with accounts, or touch the XDR in any way (i.e. the fundamental building blocks of the Stellar protocol), you can use the package directly:
import * as StellarSdk from '@stellar/stellar-sdk';
In StellarSdk
, you will find the Account
and MuxedAccount
objects, the TransactionBuilder
, the SorobanDataBuilder
, and all of the other "shared" concepts that simply define the Stellar protocol.
(If you've ever imported and used stellar-base
directly, then this distinction should be clear: anything found in stellar-base
lives in the top-level module.)
- If you want to interact with Horizon by querying its endpoints or submitting transactions, you will need to dig deeper into the module:
import { Horizon } from '@stellar/stellar-sdk';
In Horizon
, you will find Server
and all of the related "call builder" objects for its various endpoints. If you are interested in the API definitions themselves, then these will be in Horizon.HorizonApi
or Horizon.ServerApi
.
- If you want to interact with Soroban RPC, you will also need to dig deeper into the module in a very similar way:
import { SorobanRpc } from '@stellar/stellar-sdk';
This contains a different Server
object which will let you execute various RPC endpoints. It also contains API schema definitions under the SorobanRpc.Api
namespace, and misc. helpers for dealing with transaction simulation (e.g. SorobanRpc.assembleTransaction
).
If you are upgrading from the latest stable version of the stellar-sdk
package, you'll need to update your imports accordingly:
- The package now lives under the
@stellar/
npm namespace. - There is no longer a default export, so if you had
import StellarSdk from 'stellar-sdk';
, you will now need to writeimport * as StellarSdk from '@stellar/stellar-sdk';
.- However, we highly recommend only importing the specific functionality that you need in order to keep your bundle sizes reasonable, e.g.
import { TransactionBuilder, Account, Horizon } from '@stellar/stellar-sdk';
.
- However, we highly recommend only importing the specific functionality that you need in order to keep your bundle sizes reasonable, e.g.
Server
now lives under theHorizon
submodule, so you can eitherimport { Horizon } from '@stellar/stellar-sdk';
orconst { Server } = StellarSdk.Horizon;
.- The API definitions are also under the
Horizon
submodule, so update your references accordingly. - Anything related to SEP-10 that used to live under the
Utils
namespace now lives under theWebAuth
module. So if, before, you didStellarSdk.Utils.verifyTxSignedBy(...)
you would nowimport { WebAuth } from '@stellar/stellar-sdk';
and callWebAuth.verifyTxSignedBy(...)
. Alternatively, you can grab members from the top-level module, e.g.const { verifyTxSignedBy } = StellarSdk.WebAuth;
. - The TOML resolver and federation server have also moved under a separate module:
StellarSdk.StellarToml
contains aResolver
andStellarSdk.Federation
contains aServer
, respectively.
Future versions of the SDK are likely to move these latter two bullet points into separate packages to avoid bloating the bundle with features that most people do not need.
Here's an example before-and-after set of scripts:
Before:
import StellarSdk from 'stellar-sdk';
const s = StellarSdk.Server('https://horizon-testnet.stellar.org');
const kp = StellarSdk.Keypair.random();
async function main() {
return s.loadAccount(kp.publicKey()).then(account => {
const tx = new StellarSdk.TransactionBuilder(account, { fee: BASE_FEE })
.addOperation(StellarSdk.Operation.payment({ /* etc. */ }))
.setNetworkPassphrase(StellarSdk.Networks.TESTNET)
.setTimeout(30)
.build();
tx.sign(kp);
return s.submitTransaction(tx);
});
}
After:
import {
Keypair,
Networks,
TransactionBuilder,
Operation,
Horizon
} from '@stellar/stellar-sdk';
const s = Horizon.Server('https://horizon-testnet.stellar.org');
const kp = Keypair.random();
async function main() {
return s.loadAccount(kp.publicKey()).then(account => {
const tx = new TransactionBuilder(account, { fee: BASE_FEE })
.addOperation(Operation.payment({ /* etc. */ }))
.setNetworkPassphrase(Networks.TESTNET)
.setTimeout(30)
.build();
tx.sign(kp);
return s.submitTransaction(tx);
});
}
If you are coming from soroban-client
and want to adapt your codebase to this library (or perhaps you want to leverage Horizon in your app, as well), then you will need to identify where you are interacting with the RPC server vs. just interacting with the Stellar protocol. Namely,
Server
now lives under theSorobanRpc
submodule- Soroban helpers such as
assembleTransaction
also live under this submodule - The API definitions now live in the
SorobanRpc.Api
submodule - Helpers that are "shared" and have nothing to do with the RPC (like
TransactionBuilder
andContractSpec
) are still in the top level
Here's an example before-and-after set of scripts:
Before:
import * as SorobanClient from 'soroban-client';
const s = SorobanClient.Server('https://rpc-testnet.stellar.org');
const kp = SorobanClient.Keypair.random();
const c = new Contract("C...");
async function main() {
return s.getAccount(kp.publicKey()).then(account => {
const tx = new SorobanClient.TransactionBuilder(account, {
fee: BASE_FEE
})
.addOperation(c.call("hello", SorobanClient.scValToNative("world")))
.setNetworkPassphrase(SorobanClient.Networks.FUTURENET)
.setTimeout(30)
.build();
let sim: SorobanClient.SorobanRpc.SimulateTransactionResult;
sim = await s.simulateTransaction(tx);
const readyTx = SorobanClient.assembleTransaction(tx, sim);
readyTx.sign(kp);
return s.submitTransaction(readyTx);
});
}
After:
import {
Keypair,
Networks,
TransactionBuilder,
Operation,
scValToNative,
SorobanRpc
} from '@stellar/stellar-sdk';
const { Api, assembleTransaction } = SorobanRpc;
const s = SorobanRpc.Server('https://soroban-testnet.stellar.org');
const kp = Keypair.random();
async function main() {
return s.getAccount(kp.publicKey()).then(account => {
const tx = new TransactionBuilder(account, { fee: BASE_FEE })
.addOperation(c.call("hello", scValToNative("world")))
.setNetworkPassphrase(Networks.TESTNET)
.setTimeout(30)
.build();
let sim: Api.SimulateTransactionResult;
sim = await s.simulateTransaction(tx);
const readyTx = assembleTransaction(tx, sim);
readyTx.sign(kp);
return s.submitTransaction(readyTx);
});
}
Second one should be "you can interact with [SorobanRpc]"