Install WebAssembly (Wasm) bytecode using code
This process uploads the contract code to the Stellar Testnet in a transaction, the uploaded Wasm blob is a contract source, which can be thought of as a 'class' of a contract. Multiple instances of a contract can be deployed which share the same source, but have their own state.
Prerequisites
Before you begin, ensure you have the following installed to compile a smart contract:
- Rust and Cargo (for compiling smart contracts)
- The Stellar CLI
Initialize and build a sample Rust contract
soroban contract init hello-world
cd hello-world
# use rust compiler to compile Rust project into a WebAssembly (Wasm) dynamic library (cdylib).
soroban contract build
# cargo rustc --manifest-path=contracts/hello_world/Cargo.toml --crate-type=cdylib --target=wasm32-unknown-unknown --release
We are initializing the default hello_world
contract in soroban_examples to the directory hello-world
. You may use the -w
option to create with another example like account
.
After building the contract for release, the generated .wasm file is at the path hello-word/target/wasm32-unknown-unknown/release/hello_world.wasm
Upload Wasm to the Stellar blockchain
We can use one of the SDKs, install necessary dependencies for your chosen programming language:
Create a new directory for your project and navigate into it:
mkdir install-wasm
cd install-wasm
Running the install script
Different programming languages can be used to upload the .wasm
file, its SHA256 hash is used for deploying the contract.
- JavaScript
- Python
This guide will walk you through installing the Wasm of the contract using the JavaScript SDK: js-stellar-sdk.
Create a new Node.js project with a JavaScript file, and install necessary dependencies:
touch index.js
npm init es6 -y
npm install @stellar/stellar-sdk fs
Run the script with node index.js
, it reads the Wasm file, gets account details, and uploads the contract in a transaction:
// Import necessary modules in your JavaScript file:
import * as StellarSDK from "@stellar/stellar-sdk";
import fs from "fs";
async function uploadWasm(filePath) {
// reads the compiled Wasm file to buffer
const bytecode = fs.readFileSync(filePath);
// retrieves account details from the network
const account = await server.getAccount(sourceKeypair.publicKey());
// installs the bytecode with a `uploadContractWasm` Stellar operation wrapped in a transaction sent to the network
const operation = StellarSDK.Operation.uploadContractWasm({ wasm: bytecode });
return await buildAndSendTransaction(account, operation);
}
// constructs a transaction, signs it, and submits it to the network, handling any necessary retries for transaction confirmation.
async function buildAndSendTransaction(account, operations) {
const transaction = new StellarSDK.TransactionBuilder(account, {
fee: StellarSDK.BASE_FEE,
networkPassphrase: StellarSDK.Networks.TESTNET,
})
.addOperation(operations)
.setTimeout(30)
.build();
const tx = await server.prepareTransaction(transaction);
tx.sign(sourceKeypair);
console.log("Submitting transaction...");
let response = await server.sendTransaction(tx);
const hash = response.hash;
console.log(`Transaction hash: ${hash}`);
console.log("Awaiting confirmation...");
while (true) {
response = await server.getTransaction(hash);
if (response.status !== "NOT_FOUND") {
break;
}
await new Promise((resolve) => setTimeout(resolve, 1000));
}
if (response.status === "SUCCESS") {
console.log("Transaction successful.");
return response;
} else {
console.log("Transaction failed.");
throw new Error("Transaction failed");
}
}
// Upload contract to the testnet
const server = new StellarSDK.SorobanRpc.Server(
"https://soroban-testnet.stellar.org:443",
);
// Replace `Your_Secret_Key`
const sourceKeypair = StellarSDK.Keypair.fromSecret("Your_Secret_Key");
// Adjust this path as necessary
const wasmFilePath =
"../target/wasm32-unknown-unknown/release/hello_world.wasm";
try {
let uploadResponse = await uploadWasm(wasmFilePath);
const byteArray = uploadResponse.returnValue.bytes();
const wasmHash = byteArray.toString("hex");
console.log(`Wasm hash: ${wasmHash}`);
} catch (error) {
console.error(error);
}
This guide will walk you through installing the Wasm of the contract using the Python SDK: py-stellar-base.
Create a new Python script, and install the necessary dependencies:
touch install.py
pip install stellar-sdk
Run the script with python3 install.py
, it reads the Wasm file, gets account details, and uploads the contract in a transaction:
import asyncio
import time
from stellar_sdk import Keypair, Network, SorobanServer, TransactionBuilder, xdr as stellar_xdr
from stellar_sdk.exceptions import PrepareTransactionException
from stellar_sdk.soroban_rpc import GetTransactionStatus
import hashlib
def print_wasm_hash(wasm_bytes):
# Create a SHA256 hash object
sha256_hash = hashlib.sha256()
# Update the hash object with the WASM bytes
sha256_hash.update(wasm_bytes)
# Get the digest and convert it to a stellar_sdk.xdr.Hash object
hash_bytes = sha256_hash.digest()
xdr_hash = stellar_xdr.Hash(hash_bytes)
hash_hex_str = xdr_hash.hash.hex()
print(f"Wasm Hash: {hash_hex_str}")
async def upload_wasm(file_path):
# Read the compiled Wasm file
with open(file_path, 'rb') as file:
wasm_bytes = file.read()
# Retrieve account details from the network
account = server.load_account(source_keypair.public_key)
# print wasm hash for later deployment
print_wasm_hash(wasm_bytes)
# Install the bytes with an 'uploadContractWasm' Stellar operation
return await build_and_send_transaction(account, wasm_bytes)
async def build_and_send_transaction(account, bytes):
transaction = (
TransactionBuilder(
source_account=account,
network_passphrase=Network.TESTNET_NETWORK_PASSPHRASE,
)
.append_upload_contract_wasm_op(bytes)
.set_timeout(30)
.build()
)
print("Preparing transaction...")
try:
tx = server.prepare_transaction(transaction)
except PrepareTransactionException as e:
print(f"Got exception: {e}")
return None
tx.sign(source_keypair)
print("Submitting transaction...")
response = server.send_transaction(tx)
hash = response.hash
print(f"Transaction hash: {hash}")
print("Awaiting confirmation...")
while True:
response = server.get_transaction(hash)
if response.status != GetTransactionStatus.NOT_FOUND:
break
time.sleep(1)
if response.status == GetTransactionStatus.SUCCESS:
print("Transaction successful.")
return response
else:
print("Transaction failed.")
raise Exception("Transaction failed")
# Upload contract to the testnet
server = SorobanServer("https://soroban-testnet.stellar.org:443")
# Replace 'Your_Secret_Key' with your actual secret key
source_keypair = Keypair.from_secret("Your_Secret_Key")
# Adjust this path as necessary
wasm_file_path = "../target/wasm32-unknown-unknown/release/hello_world.wasm"
async def main():
try:
await upload_wasm(wasm_file_path)
except Exception as error:
print(f"Error: {error}")
# Run the main function
asyncio.run(main())
Replace "Your_Secret_Key"
with your actual secret key.
stellar keys generate --global hello --network testnet
stellar keys show hello
The Stellar CLI can be used to generate identities, e.g. hello
, and show its secret key.
Ensure that you handle secret and private keys securely in production environments and never expose them in your code repositories.
Submitting transaction...
Transaction hash: cef7a63667fe5b0ddcde5562d90e0a40bc04c69616916d1d7fa74a8571bbd82f
Awaiting confirmation...
Transaction successful.
Wasm hash: 275405755441e4be59555bb5c5fd81e84ed21659015d8f3594796c1cf3f380db
The returned upload transaction hash can be viewed with online tools: stellar.expert/explorer/testnet/tx/cef7a63667fe5b0ddcde5562d90e0a40bc04c69616916d1d7fa74a8571bbd82f
Uploaded contracts are stored in ContractCodeEntry ledger entries. These entries are keyed by the hash of the Wasm used to upload them.
You may use the Wasm hash for deployment with the Stellar CLI:
stellar contract deploy \
--source hello \
--network testnet \
--wasm-hash 275405755441e4be59555bb5c5fd81e84ed21659015d8f3594796c1cf3f380db
# CC6NAQE3ZHRQV3NPQB3F3NYEFBAMEABA4KQTM6A2V5V7PBR5H3UEU3MW
View the deployed contract using the returned identifier with online tools: stellar.expert/explorer/testnet/contract/CC6NAQE3ZHRQV3NPQB3F3NYEFBAMEABA4KQTM6A2V5V7PBR5H3UEU3MW
Guides in this category:
📄️ Install and deploy a smart contract with code
Install and deploy a smart contract with code
📄️ Install WebAssembly (Wasm) bytecode using code
Install the Wasm of the contract using js-stellar-sdk
📄️ Invoke a contract function in a Stellar transaction using SDKs
Use the Stellar SDK to create, simulate, and assemble a transaction
📄️ simulateTransaction RPC method guide
simulateTransaction examples and tutorials guide
📄️ Submit a transaction to Soroban RPC using the JavaScript SDK
Use a looping mechanism to submit a transaction to the RPC