The Rust/Wasm SDK allows developers and users to interact with the Casper Blockchain using Rust or TypeScript. It provides a way to embed the casper-client-rs into another application without the CLI interface. The SDK exposes a list of types and methods from a subset of the Casper client.
You can use the Casper Rust/Wasm SDK in two ways:
- In a Rust application by importing the SDK crate.
- In a Typescript application by importing the SDK Wasm file and the Typescript interfaces.
This page covers different examples of using the SDK.
Rust Project
Add the SDK as a dependency of your project:
Cargo.toml
casper-rust-wasm-sdk = { version = "2.0.0", git = "https://github.com/casper-ecosystem/rustSDK.git" }
main.rs
use casper_rust_wasm_sdk::{types::verbosity::Verbosity, SDK};
let sdk = SDK::new(
Some("https://rpc.testnet.casperlabs.io".to_string()),
Some(Verbosity::High)
);
Typescript Project
You can directly use the content of the pkg folder for a browser project or pkg-nodejs for a Node project.
Or you can use the [TODO]npm package
If you want to compile the Wasm package from Rust you may need to install wasm-pack
for ease of use.
curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
$ make prepare
$ make pack
This will create a pkg
and pkg-nodejs
containing the Typescript interfaces. You can find more details about building the SDK for Javascript with wasm-pack
in the wasm-pack documention.
This folder contains a Wasm binary, a JS wrapper file, Typescript types definitions, and a package.json file that you can load in your project.
$ tree pkg
pkg
├── casper_rust_wasm_sdk_bg.wasm
├── casper_rust_wasm_sdk_bg.wasm.d.ts
├── casper_rust_wasm_sdk.d.ts
├── casper_rust_wasm_sdk.js
├── LICENSE
├── package.json
└── README.md
React
package.json
{
"name": "my-react-app",
"dependencies": {
// This path is relative
"casper-sdk": "file:pkg", // [TODO] Npm package
...
}
The React app needs to load the Wasm file through a dedicated init()
method as per this example:
App.tsx
import init, {
SDK,
Verbosity,
} from 'casper-sdk';
const node_address = 'https://rpc.testnet.casperlabs.io';
const verbosity = Verbosity.High;
function App() {
const [wasm, setWasm] = useState(false);
const fetchWasm = async () => {
await init();
setWasm(true);
};
useEffect(() => {
initApp(); // take care here to initiate app only once and not on every effect
}, []);
const initApp = async () => {
if (!wasm) {
await fetchWasm();
};
const sdk = new SDK(node_address, verbosity);
console.log(sdk);
...
}
You can look at a very basic example of usage in the React example app.
$ cd ./examples/frontend/react
$ npm install
$ npm start
Angular
package.json
{
"name": "my-angular-app",
"dependencies": {
// This path is relative
"casper-sdk": "file:pkg", // [TODO] Npm package
...
}
The Angular app needs to load the Wasm file through a dedicated init()
method as per this example. You can import it into a component through a service but it is advised to import it through a factory with the injection token APP_INITIALIZER.
wasm.factory.ts
import init, { SDK, Verbosity } from 'casper-sdk';
export const SDK_TOKEN = new InjectionToken() < SDK > 'SDK';
export const WASM_ASSET_PATH =
new InjectionToken() < string > 'wasm_asset_path';
export const NODE_ADDRESS = new InjectionToken() < string > 'node_address';
export const VERBOSITY = new InjectionToken() < Verbosity > 'verbosity';
type Params = {
wasm_asset_path: string,
node_address: string,
verbosity: Verbosity,
};
export const fetchWasmFactory = async (params: Params): Promise<SDK> => {
const wasm = await init(params.wasm_asset_path);
return new SDK(params.node_address, params.verbosity);
};
wasm.module.ts
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { SDK_TOKEN, fetchWasmFactory, provideSafeAsync } from './wasm.factory';
const providers = provideSafeAsync(SDK_TOKEN, fetchWasmFactory);
@NgModule({
imports: [CommonModule],
providers,
})
export class WasmModule {}
You can look at a basic example of factory usage in the Angular example app.
Add the SDK Wasm file to the assets of your project with the path parameter being wasm_asset_path:'assets/casper_rust_wasm_sdk_bg.wasm'
, Angular will then copy the file from pkg
in assets
on build making it available for the fetch Wasm factory.
project.json
"assets": [
...,
{
"input": "pkg",
"glob": "casper_rust_wasm_sdk_bg.wasm",
"output": "assets"
}
]
You can look at a more advanced example of usage in the Angular example app.
$ cd ./examples/frontend/angular
$ npm install
$ npm start
$ npm build
Node
package.json
{
"name": "my-node-app",
"dependencies": {
// This path is relative
"casper-sdk": "file:pkg-nodejs", // [TODO] Npm package
...
}
The Node app loads the SDK with require()
. You can find more details about building the SDK for Node with wasm-pack.
Note that this method requires a version of Node.js with WebAssembly support, which is currently Node 8 and above.
index.ts
// with require
const casper_sdk = require('casper-sdk');
const { SDK } = casper_sdk;
// or with import
import { SDK } from 'casper-sdk';
const node_address = 'https://rpc.integration.casperlabs.io';
const sdk = new SDK(node_address);
console.log(sdk);
You can look at a very basic example of usage in the Node example app.
$ cd ./examples/desktop/node
$ npm install
$ npm start
Rust
You can find all RPC methods on the RPC doc. Below are several examples of RPC methods intended for use on Testnet.
use casper_rust_wasm_sdk::types::{
transaction::Transaction, hash::transaction_hash::TransactionHash,
};
let transaction_hash =
TransactionHash::new("a8778b2e4bd1ad02c168329a1f6f3674513f4d350da1b5f078e058a3422ad0b9")
.unwrap();
let finalized_approvals = true;
let get_transaction = sdk
.get_transaction(transaction_hash, Some(finalized_approvals), None, None)
.await;
let transaction: Transaction = get_transaction.unwrap().result.transaction.into();
let timestamp = transaction.timestamp();
let hash = transaction.hash();
println!("{timestamp} {hash}");
use casper_rust_wasm_sdk::types::hash::deploy_hash::DeployHash;
let deploy_hash =
DeployHash::new("a8778b2e4bd1ad02c168329a1f6f3674513f4d350da1b5f078e058a3422ad0b9")
.unwrap();
let finalized_approvals = true;
let get_deploy = sdk
.get_deploy(deploy_hash, Some(finalized_approvals), None, None)
.await;
let deploy = get_deploy.unwrap().result.deploy;
let deploy_header = deploy.header();
let timestamp = deploy_header.timestamp();
println!("{timestamp}");
let get_auction_info = sdk.get_auction_info(None, None, None).await;
let auction_state = get_auction_info.unwrap().result.auction_state;
let state_root_hash = auction_state.state_root_hash();
println!("{:?}", state_root_hash);
let block_height = auction_state.block_height();
println!("{block_height}");
let get_peers = sdk.get_peers(None, None).await;
let peers = get_peers.unwrap().result.peers;
for peer in &peers {
println!("{:?}", peer)
}
let get_block = sdk.get_block(None, None, None).await;
let get_block = sdk.get_block(None, None, None).await;
let block = get_block
.unwrap()
.result
.block_with_signatures
.unwrap()
.block;
let block_hash = block.hash();
println!("{:?}", block_hash);
println!("{:?}", block_hash);
You can find more examples by reading Rust integration tests.
Typescript
You can find all RPC methods on the RPC doc. Below are several examples of RPC methods intended for use on Testnet.
import { Transaction } from 'casper-sdk';
const transaction_hash_as_string =
'94b3e6253a4448138fb8b637bd0ca0604270d2f5664f7c221d67eae568fcd668';
const finalized_approvals = true;
const get_transaction_options = sdk.get_transaction_options({
transaction_hash_as_string,
finalized_approvals,
});
const transaction_result = await sdk.get_transaction(get_transaction_options);
const transaction: Transaction = transaction_result.transaction;
const timestamp = transaction.timestamp;
const hash = transaction.hash.toString();
console.log(timestamp, hash);
const deploy_hash_as_string =
'a8778b2e4bd1ad02c168329a1f6f3674513f4d350da1b5f078e058a3422ad0b9';
const finalized_approvals = true;
const get_deploy_options = sdk.get_deploy_options({
deploy_hash_as_string,
finalized_approvals,
});
const deploy_result = await sdk.get_deploy(get_deploy_options);
const deploy = deploy_result.deploy;
const timestamp = deploy.timestamp();
const header = deploy.toJson().header; // DeployHeader type not being exposed right now by the SDK you can convert every type to JSON
const hash = deploy.hash.toString();
console.log(timestamp, header, hash);
const get_auction_info = await sdk.get_auction_info();
const auction_state = get_auction_info.auction_state;
const state_root_hash = auction_state.state_root_hash.toString();
const block_height = auction_state.block_height.toString();
console.log(state_root_hash, block_height);
const get_peers = await sdk.get_peers();
const peers = get_peers.peers;
peers.forEach((peer) => {
console.log(peer);
});
const get_block = await sdk.get_block();
let block = get_block.block;
let block_hash = block.hash;
console.log(block_hash);
You can find more examples in NodeJs examples or in the Angular example app or in the React example app or by reading Puppeteer e2e tests.
Transactions and Transfers
Making a Transfer transaction
use casper_rust_wasm_sdk::types::transaction_params::transaction_str_params::TransactionStrParams;
pub const CHAIN_NAME: &str = "integration-test";
pub const PUBLIC_KEY: &str =
"0169d8d607f3ba04c578140398ceb1bd5296c653f965256bd7097982b9026c5129";
pub const PAYMENT_AMOUNT: &str = "100000000";
pub const TRANSFER_AMOUNT: &str = "2500000000";
pub const TTL: &str = "1h";
pub const TARGET_ACCOUNT: &str =
"01868e06026ba9c8695f6f3bb10d44782004dbc144ff65017cf484436f9cf7b0f6";
let transaction_params = TransactionStrParams::default();
transaction_params.set_chain_name(CHAIN_NAME);
transaction_params.set_initiator_addr(PUBLIC_KEY);
transaction_params.set_ttl(Some(TTL.to_string()));
transaction_params.set_payment_amount(PAYMENT_AMOUNT);
let make_transfer_transaction = sdk
.make_transfer_transaction(
None, // optional maybe_source
TARGET_ACCOUNT,
TRANSFER_AMOUNT,
transaction_params,
None, // optional transfer_id
)
.unwrap();
println!("{:?}", make_transfer_transaction.timestamp());
import { TransactionStrParams } from 'casper-sdk';
const chain_name = 'integration-test';
const public_key =
'0169d8d607f3ba04c578140398ceb1bd5296c653f965256bd7097982b9026c5129';
const secret_key = undefined;
const timestamp = getTimestamp(); // or Date.now().toString(); // or undefined
const ttl = '1h'; // or undefined
const payment_amount = '100000000';
const transfer_amount = '2500000000';
const target_account =
'0187adb3e0f60a983ecc2ddb48d32b3deaa09388ad3bc41e14aeb19959ecc60b54';
const transaction_params = new TransactionStrParams(
chain_name,
public_key,
secret_key,
timestamp,
ttl
);
transaction_params.payment_amount = payment_amount;
const make_transfer_transaction = sdk.make_transfer_transaction(
undefined, // Optional maybe_source
target_account,
transfer_amount,
transaction_params
);
const make_transfer_transaction_as_json = make_transfer_transaction.toJson();
console.log(make_transfer_transaction_as_json);
Sending a Transfer transaction (alias for: make + put)
Sends a [Transfer Transaction
] to the network for execution. (Alias for make_transfer_transaction + put_transaction)
use casper_rust_wasm_sdk::types::transaction_params::transaction_str_params::TransactionStrParams;
pub const CHAIN_NAME: &str = "integration-test";
pub const PUBLIC_KEY: &str =
"0169d8d607f3ba04c578140398ceb1bd5296c653f965256bd7097982b9026c5129";
pub const SECRET_KEY: &str = r#"-----BEGIN PRIVATE KEY-----
-----END PRIVATE KEY-----"#;
pub const PAYMENT_AMOUNT: &str = "100000000";
pub const TRANSFER_AMOUNT: &str = "2500000000";
pub const TTL: &str = "1h";
pub const TARGET_ACCOUNT: &str =
"01868e06026ba9c8695f6f3bb10d44782004dbc144ff65017cf484436f9cf7b0f6";
let transaction_params = TransactionStrParams::default();
transaction_params.set_chain_name(CHAIN_NAME);
transaction_params.set_secret_key(SECRET_KEY);
transaction_params.set_ttl(Some(TTL.to_string()));
transaction_params.set_payment_amount(PAYMENT_AMOUNT);
let transfer = sdk
.transfer_transaction(
None, // optional maybe_source
TARGET_ACCOUNT,
TRANSFER_AMOUNT,
transaction_params,
None, // optional transfer_id
None,
None,
)
.await;
println!("{:?}", transfer.as_ref().unwrap().result.transaction_hash.to_hex_string());
import { TransactionStrParams, getTimestamp } from 'casper-sdk';
const chain_name = 'casper-net-1';
const public_key =
'0169d8d607f3ba04c578140398ceb1bd5296c653f965256bd7097982b9026c5129';
const secret_key = `-----BEGIN PRIVATE KEY-----
-----END PRIVATE KEY-----`;
const timestamp = getTimestamp(); // or Date.now().toString(); // or undefined
const ttl = '1h'; // or undefined
const payment_amount = '100000000';
const transfer_amount = '2500000000';
const target_account =
'0187adb3e0f60a983ecc2ddb48d32b3deaa09388ad3bc41e14aeb19959ecc60b54';
const transaction_params = new TransactionStrParams(
chain_name,
public_key,
secret_key,
timestamp,
ttl
);
transaction_params.payment_amount = payment_amount;
const transfer_transaction_result = await sdk.transfer_transaction(
undefined, // Optional maybe_source
target_account,
transfer_amount,
transaction_params
);
const transfer_transaction_result_as_json =
transfer_transaction_result.toJson();
console.log(transfer_transaction_result_as_json);
const transaction_hash =
transfer_transaction_result.transaction_hash.toString();
console.log(transaction_hash);
Making a Session transaction
use casper_rust_wasm_sdk::types::{
addr::entity_addr::EntityAddr,
hash::addressable_entity_hash::AddressableEntityHash,
transaction_params::{
transaction_builder_params::TransactionBuilderParams,
transaction_str_params::TransactionStrParams,
},
};
pub const CHAIN_NAME: &str = "integration-test";
pub const PUBLIC_KEY: &str =
"0169d8d607f3ba04c578140398ceb1bd5296c653f965256bd7097982b9026c5129";
pub const PAYMENT_AMOUNT: &str = "5000000000";
pub const ENTITY_ADDR: &str =
"entity-contract-5be5b0ef09a7016e11292848d77f539e55791cb07a7012fbc336b1f92a4fe743";
pub const ENTRY_POINT: &str = "set_variables";
pub const TTL: &str = "1h";
let transaction_params = TransactionStrParams::default();
transaction_params.set_chain_name(CHAIN_NAME);
transaction_params.set_initiator_addr(PUBLIC_KEY);
transaction_params.set_ttl(Some(TTL.to_string()));
transaction_params.set_payment_amount(PAYMENT_AMOUNT);
let entity_addr = EntityAddr::from_formatted_str(ENTITY_ADDR).unwrap();
let builder_params = TransactionBuilderParams::new_invocable_entity(entity_addr.into(), ENTRY_POINT);
let transaction = sdk
.make_transaction(builder_params, transaction_params)
.unwrap();
println!("{:?}", transaction.timestamp());
import {
TransactionStrParams,
TransactionBuilderParams,
AddressableEntityHash,
} from 'casper-sdk';
const chain_name = 'integration-test';
const public_key =
'0169d8d607f3ba04c578140398ceb1bd5296c653f965256bd7097982b9026c5129';
const payment_amount = '5000000000';
const entity_hash_hex_string =
'5be5b0ef09a7016e11292848d77f539e55791cb07a7012fbc336b1f92a4fe743';
const entry_point = 'set_variables';
const transaction_params = new TransactionStrParams(chain_name, public_key);
transaction_params.payment_amount = payment_amount;
let entity_hash = new AddressableEntityHash(entity_hash_formatted_string);
let builder_params = TransactionBuilderParams.newInvocableEntity(
entity_hash,
entry_point
);
const transaction = sdk.make_transaction(builder_params, transaction_params);
const transaction_as_json = transaction.toJson();
console.log(transaction_as_json);
Sending a Session transaction (alias for: make + put)
Sends a [Transaction
] to the network for execution. (Alias for make_transaction + put_transaction)
let sdk = SDK::new(
Some("http://127.0.0.1:11101".to_string()),
Some(Verbosity::High),
);
use casper_rust_wasm_sdk::types::{
hash::addressable_entity_hash::AddressableEntityHash,
transaction_params::{
transaction_builder_params::TransactionBuilderParams,
transaction_str_params::TransactionStrParams,
},
};
pub const CHAIN_NAME: &str = "casper-net-1";
pub const PUBLIC_KEY: &str =
"0169d8d607f3ba04c578140398ceb1bd5296c653f965256bd7097982b9026c5129";
pub const SECRET_KEY: &str = r#"-----BEGIN PRIVATE KEY-----
-----END PRIVATE KEY-----"#;
pub const PAYMENT_AMOUNT: &str = "5000000000";
pub const ENTITY_ADDR: &str =
"entity-contract-5be5b0ef09a7016e11292848d77f539e55791cb07a7012fbc336b1f92a4fe743";
pub const ENTRY_POINT: &str = "set_variables";
pub const TTL: &str = "1h";
let transaction_params = TransactionStrParams::default();
transaction_params.set_chain_name(CHAIN_NAME);
transaction_params.set_initiator_addr(PUBLIC_KEY);
transaction_params.set_secret_key(SECRET_KEY);
transaction_params.set_ttl(Some(TTL.to_string()));
transaction_params.set_payment_amount(PAYMENT_AMOUNT);
let entity_addr = EntityAddr::from_formatted_str(ENTITY_ADDR).unwrap();
let builder_params = TransactionBuilderParams::new_invocable_entity(entity_addr.into(), ENTRY_POINT);
let transaction = sdk.transaction(builder_params, transaction_params, None, None).await;
println!(
"{:?}",
transaction.as_ref().unwrap().result.transaction_hash
);
import {
TransactionStrParams,
TransactionBuilderParams,
AddressableEntityHash,
} from 'casper-sdk';
const chain_name = 'casper-net-1';
const public_key =
'0169d8d607f3ba04c578140398ceb1bd5296c653f965256bd7097982b9026c5129';
const secret_key = `-----BEGIN PRIVATE KEY-----
-----END PRIVATE KEY-----`;
const payment_amount = '5000000000';
const entity_hash_hex_string =
'5be5b0ef09a7016e11292848d77f539e55791cb07a7012fbc336b1f92a4fe743';
const entry_point = 'set_variables';
const transaction_params = new TransactionStrParams(
chain_name,
public_key,
secret_key
);
transaction_params.payment_amount = payment_amount;
let entity_hash = new AddressableEntityHash(entity_hash_hex_string);
let builder_params = TransactionBuilderParams.newInvocableEntity(
entity_hash,
entry_point
);
const transaction_result = await sdk.transaction(
builder_params,
transaction_params
);
const transaction_result_as_json = transaction_result.toJson();
console.log(transaction_result_as_json);
Put Transaction
Puts a [Transaction
] to the network for execution.
use casper_rust_wasm_sdk::types::{
hash::addressable_entity_hash::AddressableEntityHash,
transaction_params::{
transaction_builder_params::TransactionBuilderParams,
transaction_str_params::TransactionStrParams,
},
};
pub const CHAIN_NAME: &str = "casper-net-1";
pub const SECRET_KEY: &str = r#"-----BEGIN PRIVATE KEY-----
-----END PRIVATE KEY-----"#;
let initiator_addr: &str = &public_key_from_secret_key(SECRET_KEY).unwrap();
pub const PAYMENT_AMOUNT: &str = "5000000000";
pub const ENTITY_ADDR: &str =
"entity-contract-5be5b0ef09a7016e11292848d77f539e55791cb07a7012fbc336b1f92a4fe743";
pub const ENTRY_POINT: &str = "set_variables";
pub const TTL: &str = "1h";
let transaction_params = TransactionStrParams::default();
transaction_params.set_chain_name(CHAIN_NAME);
transaction_params.set_initiator_addr(initiator_addr); // sender account
transaction_params.set_secret_key(SECRET_KEY);
transaction_params.set_ttl(Some(TTL.to_string())); // optional TTL
transaction_params.set_payment_amount(PAYMENT_AMOUNT);
let entity_addr = EntityAddr::from_formatted_str(ENTITY_ADDR).unwrap();
let builder_params = TransactionBuilderParams::new_invocable_entity(entity_addr.into(), ENTRY_POINT);
let transaction = Transaction::new_session(builder_params, transaction_params).unwrap();
let put_transaction = sdk.put_transaction(transaction, None, None).await;
println!(
"{:?}",
put_transaction.as_ref().unwrap().result.transaction_hash
);
Puts a [Transfer Transaction
] to the network for execution.
use casper_rust_wasm_sdk::types::transaction_params::transaction_str_params::TransactionStrParams;
pub const CHAIN_NAME: &str = "casper-net-1";
pub const SECRET_KEY: &str = r#"-----BEGIN PRIVATE KEY-----
-----END PRIVATE KEY-----"#;
let initiator_addr: &str = &public_key_from_secret_key(SECRET_KEY).unwrap();
pub const PAYMENT_AMOUNT: &str = "100000000";
pub const TRANSFER_AMOUNT: &str = "2500000000";
pub const TARGET_ACCOUNT: &str =
"01868e06026ba9c8695f6f3bb10d44782004dbc144ff65017cf484436f9cf7b0f6";
pub const TTL: &str = "1h";
let transaction_params = TransactionStrParams::default();
transaction_params.set_chain_name(CHAIN_NAME);
transaction_params.set_initiator_addr(initiator_addr);
transaction_params.set_secret_key(SECRET_KEY);
transaction_params.set_payment_amount(PAYMENT_AMOUNT);
transaction_params.set_ttl(Some(TTL.to_string()));
let transfer_transaction = Transaction::new_transfer(
None,
TARGET_ACCOUNT,
TRANSFER_AMOUNT,
transaction_params,
None,
)
.unwrap();
let put_transaction = sdk.put_transaction(transfer_transaction, None, None).await;
println!(
"{:?}",
put_transaction.as_ref().unwrap().result.transaction_hash
);
Puts a [Transaction
] to the network for execution.
import {
TransactionStrParams,
TransactionBuilderParams,
AddressableEntityHash,
} from 'casper-sdk';
const chain_name = 'casper-net-1';
const public_key =
'0169d8d607f3ba04c578140398ceb1bd5296c653f965256bd7097982b9026c5129';
const secret_key = `-----BEGIN PRIVATE KEY-----
-----END PRIVATE KEY-----`;
const payment_amount = '5000000000';
const entity_hash_formatted_string =
'addressable-entity-5be5b0ef09a7016e11292848d77f539e55791cb07a7012fbc336b1f92a4fe743';
const entry_point = 'set_variables';
const transaction_params = new TransactionStrParams(
chain_name,
public_key,
secret_key
);
transaction_params.payment_amount = payment_amount;
let entity_hash = AddressableEntityHash.fromFormattedStr(
entity_hash_formatted_string
);
let builder_params = TransactionBuilderParams.newInvocableEntity(
entity_hash,
entry_point
);
const transaction = Transaction.newSession(builder_params, transaction_params);
const put_transaction_result = await sdk.put_transaction(transaction);
const put_transaction_result_as_json = put_transaction_result.toJson();
console.log(put_transaction_result_as_json);
Puts a [Transfer Transaction
] to the network for execution.
import { Transaction, TransactionStrParams } from 'casper-sdk';
const chain_name = 'casper-net-1';
const public_key =
'0169d8d607f3ba04c578140398ceb1bd5296c653f965256bd7097982b9026c5129';
const secret_key = `-----BEGIN PRIVATE KEY-----
-----END PRIVATE KEY-----`;
const payment_amount = '100000000';
const transfer_amount = '2500000000';
const target_account =
'0187adb3e0f60a983ecc2ddb48d32b3deaa09388ad3bc41e14aeb19959ecc60b54';
const transfer_params = new TransactionStrParams(
chain_name,
public_key,
secret_key
);
transfer_params.payment_amount = payment_amount;
const transfer_transaction = Transaction.newTransfer(
undefined, // optional maybe_source
target_account,
transfer_amount,
transfer_params
);
const put_transaction_result = await sdk.put_transaction(transfer_transaction);
const put_transaction_result_as_json = put_transaction_result.toJson();
console.log(put_transaction_result_as_json);
Sign Transaction
pub const SECRET_KEY: &str = "MC4CAQAwBQYDK2VwBCIEII8ULlk1CJ12ZQ+bScjBt/IxMAZNggClWqK56D1/7CbI";
... // same code as 'Making a Session/Transfer Transaction' example
let unsigned_transaction = sdk.make_transaction(builder_params, transaction_params).unwrap();
let signed_transaction = unsigned_transaction.sign(SECRET_KEY);
const secret_key = 'MC4CAQAwBQYDK2VwBCIEII8ULlk1CJ12ZQ+bScjBt/IxMAZNggClWqK56D1/7CbI';
... // same code as 'Making a Session/Transfer Transaction' example
const unsigned_transaction = sdk.make_transaction(builder_params, transaction_params);
const signed_transaction = unsigned_transaction.sign(secret_key);
Wait Transaction
Developers using Rust can utilize the wait_transaction function to wait for a specific transaction event. This is achieved by providing the desired event URL, transaction hash, and an optional timeout duration. Once the transaction is processed, the resulting data, such as the transaction's cost, can be easily accessed and utilized in subsequent logic.
pub const DEFAULT_EVENT_ADDRESS: &str = "http://127.0.0.1:18101/events";
let transaction_hash = "c94ff7a9f86592681e69c1d8c2d7d2fed89fd1a922faa0ae74481f8458af2ee4";
let timeout_duration = None; // Some(30000) for 30s instead of default timeout duration of 60s
// Wait for transaction
let event_parse_result = sdk
.wait_transaction(DEFAULT_EVENT_ADDRESS, &transaction_hash, timeout_duration)
.await
.unwrap();
let transaction_processed = event_parse_result.body.unwrap().get_transaction_processed();
println!("{:?}", transaction_processed);
In TypeScript, the waitTransaction function provides a similar capability to wait for a specific transaction event. Developers can leverage this function by specifying the event address, transaction hash, and an optional timeout duration. The received EventParseResult object can then be processed to extract valuable information, such as the cost of the transaction.
const events_address = 'http://127.0.0.1:18101/events';
const transaction_hash =
'c94ff7a9f86592681e69c1d8c2d7d2fed89fd1a922faa0ae74481f8458af2ee4';
const timeout_duration = undefined; // 30000 for 30s instead of default timeout duration of 60s
// Wait for transaction
const eventParseResult: EventParseResult = await sdk.waitTransaction(
events_address,
transaction_hash,
timeout_duration
);
console.log(eventParseResult.body.transaction_processed);
const cost =
eventParseResult.body?.transaction_processed?.execution_result.Success?.cost;
console.log(`transaction cost ${cost}`);
Watch Transaction
The watch_transaction functionality facilitates actively monitoring transaction events. By creating a transaction watcher, developers can subscribe to specific transaction hashes and define custom callback functions to handle these events. The watcher is then started, and as transaction events occur, the specified callback functions are executed. This mechanism enables real-time responsiveness to transaction events within Rust applications.
use casper_rust_wasm_sdk::watcher::{
Subscription, EventHandlerFn,
};
pub const DEFAULT_EVENT_ADDRESS: &str = "http://127.0.0.1:18101/events";
let transaction_hash = "c94ff7a9f86592681e69c1d8c2d7d2fed89fd1a922faa0ae74481f8458af2ee4";
let timeout_duration = None; // Some(30000) for 30s instead of default timeout duration of 60s
// Creates a watcher instance
let mut watcher = sdk.watch_transaction(DEFAULT_EVENT_ADDRESS, timeout_duration);
// Create a callback function handler of your design
let event_handler_fn = get_event_handler_fn(transaction_hash.to_string());
let mut subscriptions: Vec<Subscription> = vec![];
subscriptions.push(Subscription::new(
transaction_hash.to_string(),
EventHandlerFn::new(event_handler_fn),
));
// Subscribe and start watching
let _ = watcher.subscribe(subscriptions);
let results = watcher.start().await;
watcher.stop();
println!("{:?}", results);
Similarly, TypeScript developers can utilize the watchTransaction function to actively watch for transaction events on the Casper blockchain. By creating a transaction watcher and defining callback functions, developers can subscribe to specific transaction hashes and respond dynamically as events unfold.
import { EventParseResult, Subscription } from 'casper-sdk';
const events_address = 'http://127.0.0.1:18101/events';
const transaction_hash =
'c94ff7a9f86592681e69c1d8c2d7d2fed89fd1a922faa0ae74481f8458af2ee4';
// Creates a watcher instance
const watcher = sdk.watchTransaction(events_address);
// Create a callback function handler of your design
const getEventHandlerFn = (transactionHash: string) => {
const eventHandlerFn = (eventParseResult: EventParseResult) => {
console.log(`callback for ${transactionHash}`);
if (eventParseResult.err) {
return false;
} else if (
eventParseResult.body?.transaction_processed?.execution_result.Success
) {
console.log(
eventParseResult.body?.transaction_processed?.execution_result.Success
);
return true;
} else {
console.error(
eventParseResult.body?.transaction_processed?.execution_result.Failure
);
return false;
}
};
return eventHandlerFn;
};
const eventHandlerFn = getEventHandlerFn(transaction_hash);
const subscription: Subscription = new Subscription(
transaction_hash,
eventHandlerFn
);
const subscriptions: Subscription[] = [subscription];
// Subscribe and start watching
watcher.subscribe(subscriptions);
const results = await watcher.start();
watcher.stop();
console.log(results);
CEP-78
- Rust
use casper_rust_wasm_sdk::{
helpers::json_pretty_print,
types::{
hash::transaction_hash::TransactionHash,
transaction_params::transaction_str_params::TransactionStrParams,
},
};
use std::{time, time::Duration};
pub const CHAIN_NAME: &str = "casper-net-1";
pub const PUBLIC_KEY: &str =
"0169d8d607f3ba04c578140398ceb1bd5296c653f965256bd7097982b9026c5129";
pub const SECRET_KEY: &str = r#"-----BEGIN PRIVATE KEY-----
-----END PRIVATE KEY-----"#;
pub const ARGS_JSON: &str = r#"[
{"name": "collection_name", "type": "String", "value": "enhanced-nft-1"},
{"name": "collection_symbol", "type": "String", "value": "ENFT-1"},
{"name": "total_token_supply", "type": "U64", "value": 10},
{"name": "ownership_mode", "type": "U8", "value": 0},
{"name": "nft_kind", "type": "U8", "value": 1},
{"name": "allow_minting", "type": "Bool", "value": true},
{"name": "owner_reverse_lookup_mode", "type": "U8", "value": 0},
{"name": "nft_metadata_kind", "type": "U8", "value": 2},
{"name": "identifier_mode", "type": "U8", "value": 0},
{"name": "metadata_mutability", "type": "U8", "value": 0},
{"name": "events_mode", "type": "U8", "value": 1}
]"#;
pub const PAYMENT_AMOUNT_CONTRACT_CEP78: &str = "500000000000";
pub const CEP78_CONTRACT: &str = "cep78.wasm";
pub const DEPLOY_TIME: Duration = time::Duration::from_millis(45000);
pub const DEFAULT_EVENT_ADDRESS: &str = "http://127.0.0.1:18101/events";
let transaction_params = TransactionStrParams::default();
transaction_params.set_chain_name(CHAIN_NAME);
transaction_params.set_initiator_addr(PUBLIC_KEY);
transaction_params.set_secret_key(SECRET_KEY);
transaction_params.set_session_args_json(ARGS_JSON);
transaction_params.set_payment_amount(PAYMENT_AMOUNT_CONTRACT_CEP78);
let file_path = CEP78_CONTRACT;
let transaction_bytes = match read_wasm_file(file_path) {
Ok(transaction_bytes) => transaction_bytes,
Err(err) => {
vec![]
// return Err(format!("Error reading file {}: {:?}", file_path, err));
}
};
let install = sdk
.install(transaction_params, transaction_bytes.into(), None)
.await;
let transaction_hash = install.as_ref().unwrap().result.transaction_hash;
println!("{:?}", transaction_hash);
let transaction_hash_as_string = transaction_hash.to_hex_string();
println!("wait transaction_hash {}", transaction_hash_as_string);
let event_parse_result: EventParseResult = sdk
.wait_transaction(DEFAULT_EVENT_ADDRESS, &transaction_hash_as_string, None)
.await
.unwrap();
println!("{:?}", event_parse_result);
let finalized_approvals = true;
let get_transaction = sdk
.get_transaction(
transaction_hash.into(),
Some(finalized_approvals),
None,
None,
)
.await
.unwrap();
let result = json_pretty_print(
get_transaction.result.transaction.approvals(),
Some(Verbosity::Low),
).unwrap();
println!("approvals {result}");
let result = transaction_hash.to_hex_string();
println!("processed transaction hash {result}");
with
fn read_wasm_file(file_path: &str) -> Result<Vec<u8>, io::Error> {
let root_path = Path::new("./wasm/");
let path = root_path.join(file_path);
let mut file = File::open(path)?;
let mut buffer = Vec::new();
file.read_to_end(&mut buffer)?;
Ok(buffer)
}
- Typescript
import {
...
TransactionStrParams,
publicKeyFromSecretKey,
Bytes,
} from 'casper-sdk';
const chain_name = 'casper-net-1';
const secret_key = `-----BEGIN PRIVATE KEY-----
-----END PRIVATE KEY-----`;
const initiator_addr = publicKeyFromSecretKey(secret_key);
const transaction_params = new TransactionStrParams(chain_name, initiator_addr, secret_key);
transaction_params.session_args_json = JSON.stringify([
{"name": "collection_name", "type": "String", "value": "enhanced-nft-1"},
{"name": "collection_symbol", "type": "String", "value": "ENFT-1"},
{"name": "total_token_supply", "type": "U64", "value": 10},
{"name": "ownership_mode", "type": "U8", "value": 0},
{"name": "nft_kind", "type": "U8", "value": 1},
{"name": "allow_minting", "type": "Bool", "value": true},
{"name": "owner_reverse_lookup_mode", "type": "U8", "value": 0},
{"name": "nft_metadata_kind", "type": "U8", "value": 2},
{"name": "identifier_mode", "type": "U8", "value": 0},
{"name": "metadata_mutability", "type": "U8", "value": 0},
{"name": "events_mode", "type": "U8", "value": 1}
]);
transaction_params.payment_amount = '500000000000';
const buffer = await loadFile();
const wasm = buffer && new Uint8Array(buffer);
const wasmBuffer = wasm?.buffer;
if (!wasmBuffer) {
console.error('Failed to read wasm file.');
return;
}
const install_result = await sdk.install(
transaction_params,
Bytes.fromUint8Array(wasm)
);
const install_result_as_json = install_result.toJson();
console.log(install_result_as_json);
const transaction_hash = install_result.transaction_hash.toString();
console.log(transaction_hash);
with
async function loadFile() {
try {
const fileBuffer = await fs.readFile('cep78.wasm');
return fileBuffer.buffer; // Returns an ArrayBuffer
} catch (error) {
throw new Error('Error reading file: ' + error.message);
}
}
- Rust
use casper_rust_wasm_sdk::types::{
hash::addressable_entity_hash::AddressableEntityHash,
transaction_params::{
transaction_builder_params::TransactionBuilderParams,
transaction_str_params::TransactionStrParams,
},
};
pub const CHAIN_NAME: &str = "casper-net-1";
pub const PUBLIC_KEY: &str =
"0169d8d607f3ba04c578140398ceb1bd5296c653f965256bd7097982b9026c5129";
pub const SECRET_KEY: &str = r#"-----BEGIN PRIVATE KEY-----
-----END PRIVATE KEY-----"#;
pub const ENTITY_ADDR: &str =
"entity-contract-5be5b0ef09a7016e11292848d77f539e55791cb07a7012fbc336b1f92a4fe743";
pub const ENTRYPOINT_MINT: &str = "mint";
pub const TOKEN_OWNER: &str =
"account-hash-878985c8c07064e09e67cc349dd21219b8e41942a0adc4bfa378cf0eace32611";
pub const PAYMENT_AMOUNT: &str = "5000000000";
let mut transaction_params = TransactionStrParams::default();
transaction_params.set_chain_name(CHAIN_NAME);
transaction_params.set_initiator_addr(PUBLIC_KEY);
transaction_params.set_secret_key(SECRET_KEY);
transaction_params.set_payment_amount(PAYMENT_AMOUNT);
let args = Vec::from([
"token_meta_data:String='test_meta_data'".to_string(),
format!("token_owner:Key='{TOKEN_OWNER}'").to_string(),
]);
transaction_params.set_session_args_simple(args);
let entity_addr = EntityAddr::from_formatted_str(ENTITY_ADDR).unwrap();
let builder_params =
TransactionBuilderParams::new_invocable_entity(entity_addr.into(), ENTRYPOINT_MINT);
let call_entrypoint = sdk
.call_entrypoint(builder_params, transaction_params, None)
.await;
let transaction_hash_result = call_entrypoint
.as_ref()
.unwrap()
.result
.transaction_hash;
let transaction_hash = transaction_hash_result.to_hex_string();
println!("watch transaction_hash {transaction_hash}");
- Typescript
import {
...
TransactionStrParams,
publicKeyFromSecretKey,
Bytes,
AddressableEntityHash,
} from 'casper-sdk';
const chain_name = 'casper-net-1';
const secret_key = '';
const initiator_addr = publicKeyFromSecretKey(secret_key);
const entity_hash_formatted_string =
'addressable-entity-5be5b0ef09a7016e11292848d77f539e55791cb07a7012fbc336b1f92a4fe743';
const entry_point = 'mint';
const payment_amount = '5000000000';
const token_owner = 'account-hash-878985c8c07064e09e67cc349dd21219b8e41942a0adc4bfa378cf0eace32611';
const transaction_params = new TransactionStrParams(chain_name, initiator_addr, secret_key);
transaction_params.session_args_simple = ["token_meta_data:String='test_meta_data'", `token_owner:Key='${token_owner}'`];
transaction_params.payment_amount = payment_amount;
let entity_hash = AddressableEntityHash.fromFormattedStr(entity_hash_formatted_string);
let builder_params = TransactionBuilderParams.newInvocableEntity(entity_hash, entry_point);
const call_entrypoint_result = await sdk.call_entrypoint(
builder_params,
transaction_params
);
const call_entrypoint_result_as_json = call_entrypoint_result.toJson();
console.log(call_entrypoint_result_as_json);
const transaction_hash = call_entrypoint_result.transaction_hash.toString();
console.log(transaction_hash);
Deploys and Transfers (Legacy)
Making a Transfer
use casper_rust_wasm_sdk::types::deploy_params::{
deploy_str_params::DeployStrParams, payment_str_params::PaymentStrParams,
};
pub const CHAIN_NAME: &str = "integration-test";
pub const PUBLIC_KEY: &str =
"0169d8d607f3ba04c578140398ceb1bd5296c653f965256bd7097982b9026c5129";
pub const PAYMENT_AMOUNT: &str = "100000000";
pub const TRANSFER_AMOUNT: &str = "2500000000";
pub const TTL: &str = "1h";
pub const TARGET_ACCOUNT: &str =
"01868e06026ba9c8695f6f3bb10d44782004dbc144ff65017cf484436f9cf7b0f6";
let deploy_params = DeployStrParams::new(
CHAIN_NAME,
PUBLIC_KEY, // sender account
None, // optional secret key to sign transfer deploy
None, // optional timestamp
Some(TTL.to_string()), // optional TTL
);
let payment_params = PaymentStrParams::default();
payment_params.set_payment_amount(PAYMENT_AMOUNT);
let make_transfer = sdk
.make_transfer(
TRANSFER_AMOUNT,
TARGET_ACCOUNT, // target account
None, // optional transfer_id
deploy_params,
payment_params,
)
.unwrap();
println!("{:?}", make_transfer.header().timestamp());
import { DeployStrParams, PaymentStrParams, getTimestamp } from 'casper-sdk';
const chain_name = 'integration-test';
const public_key =
'0169d8d607f3ba04c578140398ceb1bd5296c653f965256bd7097982b9026c5129';
const secret_key = undefined;
const timestamp = getTimestamp(); // or Date.now().toString(); // or undefined
const ttl = '1h'; // or undefined
const payment_amount = '100000000';
const transfer_amount = '2500000000';
const target_account =
'0187adb3e0f60a983ecc2ddb48d32b3deaa09388ad3bc41e14aeb19959ecc60b54';
const deploy_params = new DeployStrParams(
chain_name,
public_key,
secret_key,
timestamp,
ttl
);
const payment_params = new PaymentStrParams(payment_amount);
const transfer_deploy = sdk.make_transfer(
transfer_amount,
target_account,
undefined, // transfer_id
deploy_params,
payment_params
);
const transfer_deploy_as_json = transfer_deploy.toJson();
console.log(transfer_deploy_as_json);
Transfer
Sends a [Transfer Deploy
] to the network for execution. (Alias for make_transfer + put_deploy)
use casper_rust_wasm_sdk::types::deploy_params::{
deploy_str_params::DeployStrParams, payment_str_params::PaymentStrParams,
};
pub const CHAIN_NAME: &str = "integration-test";
pub const PUBLIC_KEY: &str =
"0169d8d607f3ba04c578140398ceb1bd5296c653f965256bd7097982b9026c5129";
pub const SECRET_KEY: &str = r#"-----BEGIN PRIVATE KEY-----
-----END PRIVATE KEY-----"#;
pub const PAYMENT_AMOUNT: &str = "100000000";
pub const TRANSFER_AMOUNT: &str = "2500000000";
pub const TTL: &str = "1h";
pub const TARGET_ACCOUNT: &str =
"01868e06026ba9c8695f6f3bb10d44782004dbc144ff65017cf484436f9cf7b0f6";
let deploy_params = DeployStrParams::new(
CHAIN_NAME,
PUBLIC_KEY, // sender account
Some(SECRET_KEY.to_string()),
None, // optional timestamp
Some(TTL.to_string()), // optional TTL
);
let payment_params = PaymentStrParams::default();
payment_params.set_payment_amount(PAYMENT_AMOUNT);
let transfer = sdk
.transfer(
TRANSFER_AMOUNT,
TARGET_ACCOUNT,
None, // optional transfer_id
deploy_params,
payment_params,
None,
None,
)
.await;
println!("{:?}", transfer.as_ref().unwrap().result.deploy_hash.to_hex_string());
import { DeployStrParams, PaymentStrParams, getTimestamp } from 'casper-sdk';
const chain_name = 'casper-net-1';
const public_key =
'0169d8d607f3ba04c578140398ceb1bd5296c653f965256bd7097982b9026c5129';
const secret_key = `-----BEGIN PRIVATE KEY-----
-----END PRIVATE KEY-----`;
const timestamp = getTimestamp(); // or Date.now().toString(); // or undefined
const ttl = '1h'; // or undefined
const payment_amount = '100000000';
const transfer_amount = '2500000000';
const target_account =
'0187adb3e0f60a983ecc2ddb48d32b3deaa09388ad3bc41e14aeb19959ecc60b54';
const deploy_params = new DeployStrParams(
chain_name,
public_key,
secret_key,
timestamp,
ttl
);
const payment_params = new PaymentStrParams(payment_amount);
const transfer_result = await sdk.transfer(
transfer_amount,
target_account,
undefined, // transfer_id
deploy_params,
payment_params
);
const transfer_result_as_json = transfer_result.toJson();
console.log(transfer_result_as_json);
console.log(transfer_result.deploy_hash.toString());
Making a Deploy
use casper_rust_wasm_sdk::types::deploy_params::{
deploy_str_params::DeployStrParams, payment_str_params::PaymentStrParams,
session_str_params::SessionStrParams,
};
pub const CHAIN_NAME: &str = "integration-test";
pub const PUBLIC_KEY: &str =
"0169d8d607f3ba04c578140398ceb1bd5296c653f965256bd7097982b9026c5129";
pub const PAYMENT_AMOUNT: &str = "5000000000";
pub const CONTRACT_HASH: &str =
"hash-5be5b0ef09a7016e11292848d77f539e55791cb07a7012fbc336b1f92a4fe743";
pub const ENTRY_POINT: &str = "set_variables";
pub const TTL: &str = "1h";
let deploy_params = DeployStrParams::new(
CHAIN_NAME,
PUBLIC_KEY, // sender account
None, // optional secret key to sign deploy
None, // optional timestamp
Some(TTL.to_string()), // optional TTL
);
let session_params = SessionStrParams::default();
session_params.set_session_hash(CONTRACT_HASH);
session_params.set_session_entry_point(ENTRY_POINT);
let payment_params = PaymentStrParams::default();
payment_params.set_payment_amount(PAYMENT_AMOUNT);
let deploy = awaitsdk
.make_deploy(deploy_params, session_params, payment_params)
.unwrap();
println!("{:?}", deploy.header().timestamp());
import {
DeployStrParams,
PaymentStrParams,
SessionStrParams,
} from 'casper-sdk';
const chain_name = 'integration-test';
const public_key =
'0169d8d607f3ba04c578140398ceb1bd5296c653f965256bd7097982b9026c5129';
const payment_amount = '5000000000';
const contract_hash =
'hash-5be5b0ef09a7016e11292848d77f539e55791cb07a7012fbc336b1f92a4fe743';
const deploy_params = new DeployStrParams(chain_name, public_key);
const session_params = new SessionStrParams();
session_params.session_hash = contract_hash;
session_params.session_entry_point = 'set_variables';
const payment_params = new PaymentStrParams(payment_amount);
const deploy = sdk.make_deploy(deploy_params, session_params, payment_params);
const deploy_as_json = deploy.toJson();
console.log(deploy_as_json);
Deploy
Sends a [Deploy
] to the network for execution. (Alias for make_deploy + put_deploy)
let sdk = SDK::new(
Some("http://127.0.0.1:11101".to_string()),
Some(Verbosity::High),
);
use casper_rust_wasm_sdk::types::deploy_params::{
deploy_str_params::DeployStrParams, payment_str_params::PaymentStrParams,
session_str_params::SessionStrParams,
};
pub const CHAIN_NAME: &str = "casper-net-1";
pub const PUBLIC_KEY: &str =
"0169d8d607f3ba04c578140398ceb1bd5296c653f965256bd7097982b9026c5129";
pub const SECRET_KEY: &str = r#"-----BEGIN PRIVATE KEY-----
-----END PRIVATE KEY-----"#;
pub const PAYMENT_AMOUNT: &str = "5000000000";
pub const CONTRACT_HASH: &str =
"hash-6646c99b3327954b47035bbc31343d9d96a833a9fc9c8c6d809b29f2482b0abf";
pub const ENTRY_POINT: &str = "set_variables";
pub const TTL: &str = "1h";
let deploy_params = DeployStrParams::new(
CHAIN_NAME,
PUBLIC_KEY, // sender account
Some(SECRET_KEY.to_string()),
None, // optional timestamp
Some(TTL.to_string()), // optional TTL
);
let session_params = SessionStrParams::default();
session_params.set_session_hash(CONTRACT_HASH);
session_params.set_session_entry_point(ENTRY_POINT);
let payment_params = PaymentStrParams::default();
payment_params.set_payment_amount(PAYMENT_AMOUNT);
let deploy = sdk
.deploy(deploy_params, session_params, payment_params, None, None)
.await;
println!("{:?}", deploy.as_ref().unwrap().result.deploy_hash);
import {
DeployStrParams,
PaymentStrParams,
SessionStrParams,
} from 'casper-sdk';
const chain_name = 'casper-net-1';
const public_key =
'0169d8d607f3ba04c578140398ceb1bd5296c653f965256bd7097982b9026c5129';
const secret_key = `-----BEGIN PRIVATE KEY-----
-----END PRIVATE KEY-----`;
const payment_amount = '5000000000';
const contract_hash =
'hash-5be5b0ef09a7016e11292848d77f539e55791cb07a7012fbc336b1f92a4fe743';
const deploy_params = new DeployStrParams(chain_name, public_key, secret_key);
const session_params = new SessionStrParams();
session_params.session_hash = contract_hash;
session_params.session_entry_point = 'set_variables';
const payment_params = new PaymentStrParams(payment_amount);
const deploy_result = await sdk.deploy(
deploy_params,
session_params,
payment_params
);
const deploy_result_as_json = deploy_result.toJson();
console.log(deploy_result_as_json);
Put Deploy
Puts a [Deploy
] to the network for execution.
use casper_rust_wasm_sdk::types::{
deploy::Deploy,
deploy_params::{
deploy_str_params::DeployStrParams, payment_str_params::PaymentStrParams,
session_str_params::SessionStrParams,
},
};
pub const CHAIN_NAME: &str = "casper-net-1";
pub const PUBLIC_KEY: &str =
"0169d8d607f3ba04c578140398ceb1bd5296c653f965256bd7097982b9026c5129";
pub const SECRET_KEY: &str = r#"-----BEGIN PRIVATE KEY-----
-----END PRIVATE KEY-----"#;
pub const PAYMENT_AMOUNT: &str = "5000000000";
pub const CONTRACT_HASH: &str =
"hash-6646c99b3327954b47035bbc31343d9d96a833a9fc9c8c6d809b29f2482b0abf";
pub const ENTRY_POINT: &str = "set_variables";
pub const TTL: &str = "1h";
let deploy_params = DeployStrParams::new(
CHAIN_NAME,
PUBLIC_KEY, // sender account
Some(SECRET_KEY.to_string()),
None, // optional timestamp
Some(TTL.to_string()), // optional TTL
);
let session_params = SessionStrParams::default();
session_params.set_session_hash(CONTRACT_HASH);
session_params.set_session_entry_point(ENTRY_POINT);
let payment_params = PaymentStrParams::default();
payment_params.set_payment_amount(PAYMENT_AMOUNT);
let deploy =
Deploy::with_payment_and_session(deploy_params, session_params, payment_params).unwrap();
let put_deploy = sdk.put_deploy(deploy, None, None).await;
println!("{:?}", put_deploy.as_ref().unwrap().result.deploy_hash);
Puts a [Transfer Deploy
] to the network for execution.
use casper_rust_wasm_sdk::types::{
deploy::Deploy,
deploy_params::{deploy_str_params::DeployStrParams, payment_str_params::PaymentStrParams},
};
pub const CHAIN_NAME: &str = "casper-net-1";
pub const PUBLIC_KEY: &str =
"0169d8d607f3ba04c578140398ceb1bd5296c653f965256bd7097982b9026c5129";
pub const SECRET_KEY: &str = r#"-----BEGIN PRIVATE KEY-----
-----END PRIVATE KEY-----"#;
pub const PAYMENT_AMOUNT: &str = "100000000";
pub const TRANSFER_AMOUNT: &str = "2500000000";
pub const TARGET_ACCOUNT: &str =
"01868e06026ba9c8695f6f3bb10d44782004dbc144ff65017cf484436f9cf7b0f6";
pub const TTL: &str = "1h";
let deploy_params = DeployStrParams::new(
CHAIN_NAME,
PUBLIC_KEY, // sender account
Some(SECRET_KEY.to_string()),
None, // optional timestamp
Some(TTL.to_string()), // optional TTL
);
let payment_params = PaymentStrParams::default();
payment_params.set_payment_amount(PAYMENT_AMOUNT);
let transfer_deploy = Deploy::with_transfer(
TRANSFER_AMOUNT,
TARGET_ACCOUNT,
None,
deploy_params,
payment_params,
)
.unwrap();
let put_deploy = sdk.put_deploy(transfer_deploy, None, None).await;
println!("{:?}", put_deploy.as_ref().unwrap().result.deploy_hash);
Puts a [Deploy
] to the network for execution.
import {
Deploy,
DeployStrParams,
PaymentStrParams,
SessionStrParams,
} from 'casper-sdk';
const chain_name = 'casper-net-1';
const public_key =
'0169d8d607f3ba04c578140398ceb1bd5296c653f965256bd7097982b9026c5129';
const secret_key = `-----BEGIN PRIVATE KEY-----
-----END PRIVATE KEY-----`;
const payment_amount = '5000000000';
const contract_hash =
'hash-5be5b0ef09a7016e11292848d77f539e55791cb07a7012fbc336b1f92a4fe743';
const entry_point = 'set_variables';
const deploy_params = new DeployStrParams(chain_name, public_key, secret_key);
const session_params = new SessionStrParams();
session_params.session_hash = contract_hash;
session_params.session_entry_point = entry_point;
const payment_params = new PaymentStrParams(payment_amount);
const deploy = Deploy.withPaymentAndSession(
deploy_params,
session_params,
payment_params
);
const put_deploy_result = await sdk.put_deploy(deploy);
const put_deploy_result_as_json = put_deploy_result.toJson();
console.log(put_deploy_result_as_json);
Puts a [Transfer Deploy
] to the network for execution.
import {
Deploy,
DeployStrParams,
PaymentStrParams,
SessionStrParams,
} from 'casper-sdk';
const chain_name = 'casper-net-1';
const public_key =
'0169d8d607f3ba04c578140398ceb1bd5296c653f965256bd7097982b9026c5129';
const secret_key = `-----BEGIN PRIVATE KEY-----
-----END PRIVATE KEY-----`;
const payment_amount = '100000000';
const transfer_amount = '2500000000';
const target_account =
'0187adb3e0f60a983ecc2ddb48d32b3deaa09388ad3bc41e14aeb19959ecc60b54';
const deploy_params = new DeployStrParams(chain_name, public_key, secret_key);
const payment_params = new PaymentStrParams(payment_amount);
const transfer_deploy = Deploy.withTransfer(
transfer_amount,
target_account,
undefined, // transfer_id
deploy_params,
payment_params
);
const put_deploy_result = await sdk.put_deploy(transfer_deploy);
const put_deploy_result_as_json = put_deploy_result.toJson();
console.log(put_deploy_result_as_json);
Sign Deploy
pub const SECRET_KEY: &str = "MC4CAQAwBQYDK2VwBCIEII8ULlk1CJ12ZQ+bScjBt/IxMAZNggClWqK56D1/7CbI";
... // same code as 'Making a Deploy' example
let unsigned_deploy = sdk.make_deploy(deploy_params, session_params, payment_params).unwrap();
let signed_deploy = sdk.sign_deploy(unsigned_deploy, SECRET_KEY);
const secret_key = 'MC4CAQAwBQYDK2VwBCIEII8ULlk1CJ12ZQ+bScjBt/IxMAZNggClWqK56D1/7CbI';
... // same code as 'Making a Deploy' example
const unsigned_deploy = sdk.make_deploy(deploy_params, session_params, payment_params);
const signed_deploy = unsigned_deploy.sign(secret_key);
Wait Deploy
Developers using Rust can utilize the wait_deploy function to wait for a specific deploy event. This is achieved by providing the desired event URL, deploy hash, and an optional timeout duration. Once the deploy is processed, the resulting data, such as the deploy's cost, can be easily accessed and utilized in subsequent logic.
pub const DEFAULT_EVENT_ADDRESS: &str = "http://127.0.0.1:18101/events/main";
let deploy_hash = "c94ff7a9f86592681e69c1d8c2d7d2fed89fd1a922faa0ae74481f8458af2ee4";
let timeout_duration = None; // Some(30000) for 30s instead of default timeout duration of 60s
// Wait for deploy
let event_parse_result = sdk
.wait_deploy(DEFAULT_EVENT_ADDRESS, &deploy_hash, timeout_duration)
.await
.unwrap();
let deploy_processed = event_parse_result.body.unwrap().deploy_processed.unwrap();
println!("{:?}", deploy_processed);
In TypeScript, the waitDeploy function provides a similar capability to wait for a specific deploy event. Developers can leverage this function by specifying the event address, deploy hash, and an optional timeout duration. The received EventParseResult object can then be processed to extract valuable information, such as the cost of the deploy.
const events_address = 'http://127.0.0.1:18101/events/main';
const deploy_hash =
'c94ff7a9f86592681e69c1d8c2d7d2fed89fd1a922faa0ae74481f8458af2ee4';
const timeout_duration = undefined; // 30000 for 30s instead of default timeout duration of 60s
// Wait for deploy
const eventParseResult: EventParseResult = await sdk.waitDeploy(
events_address,
install_result_as_json.deploy_hash,
timeout_duration
);
console.log(eventParseResult.body.DeployProcessed);
const cost =
eventParseResult.body?.DeployProcessed?.execution_result.Success?.cost;
console.log(`deploy cost ${cost}`);
Watch Deploy
The watch_deploy functionality facilitates actively monitoring deploy events. By creating a deploy watcher, developers can subscribe to specific deploy hashes and define custom callback functions to handle these events. The watcher is then started, and as deploy events occur, the specified callback functions are executed. This mechanism enables real-time responsiveness to deploy events within Rust applications.
use casper_rust_wasm_sdk::deploy_watcher::watcher::{
Subscription, EventHandlerFn,
};
pub const DEFAULT_EVENT_ADDRESS: &str = "http://127.0.0.1:18101/events/main";
let deploy_hash = "c94ff7a9f86592681e69c1d8c2d7d2fed89fd1a922faa0ae74481f8458af2ee4";
let timeout_duration = None; // Some(30000) for 30s instead of default timeout duration of 60s
// Creates a watcher instance
let mut watcher = sdk.watch_deploy(DEFAULT_EVENT_ADDRESS, timeout_duration);
// Create a callback function handler of your design
let event_handler_fn = get_event_handler_fn(deploy_hash.to_string());
let mut subscriptions: Vec<Subscription> = vec![];
subscriptions.push(Subscription::new(
deploy_hash.to_string(),
EventHandlerFn::new(event_handler_fn),
));
// Subscribe and start watching
let _ = watcher.subscribe(subscriptions);
let results = watcher.start().await;
watcher.stop();
println!("{:?}", results);
Similarly, TypeScript developers can utilize the watchDeploy function to actively watch for deploy events on the Casper blockchain. By creating a deploy watcher and defining callback functions, developers can subscribe to specific deploy hashes and respond dynamically as events unfold.
import { EventParseResult, Subscription } from 'casper-sdk';
const events_address = 'http://127.0.0.1:18101/events/main';
const deploy_hash =
'c94ff7a9f86592681e69c1d8c2d7d2fed89fd1a922faa0ae74481f8458af2ee4';
// Creates a watcher instance
const watcher = sdk.watchDeploy(events_address);
// Create a callback function handler of your design
const getEventHandlerFn = (deployHash: string) => {
const eventHandlerFn = (eventParseResult: EventParseResult) => {
console.log(`callback for ${deployHash}`);
if (eventParseResult.err) {
return false;
} else if (
eventParseResult.body?.DeployProcessed?.execution_result.Success
) {
console.log(
eventParseResult.body?.DeployProcessed?.execution_result.Success
);
return true;
} else {
console.error(
eventParseResult.body?.DeployProcessed?.execution_result.Failure
);
return false;
}
};
return eventHandlerFn;
};
const eventHandlerFn = getEventHandlerFn(deploy_hash);
const subscription: Subscription = new Subscription(
deploy_hash,
eventHandlerFn
);
const subscriptions: Subscription[] = [subscription];
// Subscribe and start watching
watcher.subscribe(subscriptions);
const results = await watcher.start();
watcher.stop();
console.log(results);
CEP-78 (Legacy)
- Rust
use casper_rust_wasm_sdk::{
helpers::json_pretty_print,
types::{
hash::deploy_hash::DeployHash,
deploy_params::{
deploy_str_params::DeployStrParams, payment_str_params::PaymentStrParams,
session_str_params::SessionStrParams,
},
},
};
use std::{time, time::Duration};
pub const CHAIN_NAME: &str = "casper-net-1";
pub const PUBLIC_KEY: &str =
"0169d8d607f3ba04c578140398ceb1bd5296c653f965256bd7097982b9026c5129";
pub const SECRET_KEY: &str = r#"-----BEGIN PRIVATE KEY-----
-----END PRIVATE KEY-----"#;
pub const ARGS_JSON: &str = r#"[
{"name": "collection_name", "type": "String", "value": "enhanced-nft-1"},
{"name": "collection_symbol", "type": "String", "value": "ENFT-1"},
{"name": "total_token_supply", "type": "U64", "value": 10},
{"name": "ownership_mode", "type": "U8", "value": 0},
{"name": "nft_kind", "type": "U8", "value": 1},
{"name": "allow_minting", "type": "Bool", "value": true},
{"name": "owner_reverse_lookup_mode", "type": "U8", "value": 0},
{"name": "nft_metadata_kind", "type": "U8", "value": 2},
{"name": "identifier_mode", "type": "U8", "value": 0},
{"name": "metadata_mutability", "type": "U8", "value": 0},
{"name": "events_mode", "type": "U8", "value": 1}
]"#;
pub const PAYMENT_AMOUNT_CONTRACT_CEP78: &str = "500000000000";
pub const CEP78_CONTRACT: &str = "cep78.wasm";
pub const DEPLOY_TIME: Duration = time::Duration::from_millis(45000);
let deploy_params = DeployStrParams::new(
CHAIN_NAME,
PUBLIC_KEY,
Some(SECRET_KEY.to_string()),
None,
None,
);
let session_params = SessionStrParams::default();
session_params.set_session_args_json(ARGS_JSON);
let file_path = CEP78_CONTRACT;
let module_bytes = match read_wasm_file(file_path) {
Ok(module_bytes) => module_bytes,
Err(err) => {
return Err(format!("Error reading file {}: {:?}", file_path, err));
}
};
session_params.set_session_bytes(module_bytes.into());
let install = sdk
.install_deploy(deploy_params, session_params, PAYMENT_AMOUNT_CONTRACT_CEP78, None)
.await;
let deploy_hash = install.as_ref().unwrap().result.deploy_hash;
let deploy_hash_string = deploy_hash.to_hex_string();
println!("{:?}", deploy_hash_string);
let event_parse_result = sdk
.wait_deploy(DEFAULT_EVENT_ADDRESS, &deploy_hash_string)
.await
.unwrap();
let deploy_processed = event_parse_result.body.unwrap().deploy_processed.unwrap();
println!("{:?}", deploy_processed);
let finalized_approvals = true;
let get_deploy = sdk
.get_deploy(deploy_hash.into(), Some(finalized_approvals), None, None)
.await;
let get_deploy = get_deploy.unwrap();
let result = &get_deploy.result.execution_results.get(0).unwrap().result;
println!("{}", json_pretty_print(result, Some(Verbosity::High)).unwrap());
with
fn read_wasm_file(file_path: &str) -> Result<Vec<u8>, io::Error> {
let root_path = Path::new("./wasm/");
let path = root_path.join(file_path);
let mut file = File::open(path)?;
let mut buffer = Vec::new();
file.read_to_end(&mut buffer)?;
Ok(buffer)
}
- Typescript
import {
...
DeployStrParams,
SessionStrParams,
PaymentStrParams,
publicKeyFromSecretKey,
Bytes,
} from 'casper-sdk';
const chain_name = 'casper-net-1';
const secret_key = `-----BEGIN PRIVATE KEY-----
-----END PRIVATE KEY-----`;
const public_key = publicKeyFromSecretKey(secret_key);
const deploy_params = new DeployStrParams(chain_name, public_key, secret_key);
const session_params = new SessionStrParams();
session_params.session_args_json = JSON.stringify([
{"name": "collection_name", "type": "String", "value": "enhanced-nft-1"},
{"name": "collection_symbol", "type": "String", "value": "ENFT-1"},
{"name": "total_token_supply", "type": "U64", "value": 10},
{"name": "ownership_mode", "type": "U8", "value": 0},
{"name": "nft_kind", "type": "U8", "value": 1},
{"name": "allow_minting", "type": "Bool", "value": true},
{"name": "owner_reverse_lookup_mode", "type": "U8", "value": 0},
{"name": "nft_metadata_kind", "type": "U8", "value": 2},
{"name": "identifier_mode", "type": "U8", "value": 0},
{"name": "metadata_mutability", "type": "U8", "value": 0},
{"name": "events_mode", "type": "U8", "value": 1}
]);
const payment_amount = '500000000000';
const buffer = await loadFile();
const wasm = buffer && new Uint8Array(buffer);
const wasmBuffer = wasm?.buffer;
if (!wasmBuffer) {
console.error('Failed to read wasm file.');
return;
}
session_params.session_bytes = Bytes.fromUint8Array(wasm);
const install_result = await sdk.install_deploy(
deploy_params,
session_params,
payment_amount
);
const install_result_as_json = install_result.toJson();
console.log(install_result_as_json);
const deploy_hash = install_result.deploy_hash.toString();
console.log(deploy_hash);
with
async function loadFile() {
try {
const fileBuffer = await fs.readFile('cep78.wasm');
return fileBuffer.buffer; // Returns an ArrayBuffer
} catch (error) {
throw new Error('Error reading file: ' + error.message);
}
}
- Rust
use casper_rust_wasm_sdk::types::{
hash::deploy_hash::DeployHash,
deploy_params::{
deploy_str_params::DeployStrParams, payment_str_params::PaymentStrParams,
session_str_params::SessionStrParams,
},
};
pub const CHAIN_NAME: &str = "casper-net-1";
pub const PUBLIC_KEY: &str =
"0169d8d607f3ba04c578140398ceb1bd5296c653f965256bd7097982b9026c5129";
pub const SECRET_KEY: &str = r#"-----BEGIN PRIVATE KEY-----
-----END PRIVATE KEY-----"#;
pub const CONTRACT_HASH: &str =
"hash-c12808431d490e2c463c2f968d0a4eaa0f9d57842508d9041aa42e2bd21eb96c";
pub const ENTRYPOINT_MINT: &str = "mint";
pub const TOKEN_OWNER: &str =
"account-hash-878985c8c07064e09e67cc349dd21219b8e41942a0adc4bfa378cf0eace32611";
pub const PAYMENT_AMOUNT: &str = "5000000000";
let deploy_params = DeployStrParams::new(
CHAIN_NAME,
PUBLIC_KEY,
Some(SECRET_KEY.to_string()),
None,
None,
);
let mut session_params = SessionStrParams::default();
session_params.set_session_hash(CONTRACT_HASH);
session_params.set_session_entry_point(ENTRYPOINT_MINT);
let args = Vec::from([
"token_meta_data:String='test_meta_data'".to_string(),
format!("token_owner:Key='{TOKEN_OWNER}'").to_string(),
]);
session_params.set_session_args(args);
let payment_params = PaymentStrParams::default();
payment_params.set_payment_amount(PAYMENT_AMOUNT);
let call_entrypoint = sdk
.call_entrypoint_deploy(deploy_params, session_params, payment_params, None)
.await;
let deploy_hash_result = call_entrypoint.as_ref().unwrap().result.deploy_hash;
println!("{:?}", deploy_hash_result);
- Typescript
import {
...
DeployStrParams,
SessionStrParams,
PaymentStrParams,
publicKeyFromSecretKey,
Bytes,
} from 'casper-sdk';
const chain_name = 'casper-net-1';
const secret_key = '';
const public_key = publicKeyFromSecretKey(secret_key);
const contract_hash =
'hash-5be5b0ef09a7016e11292848d77f539e55791cb07a7012fbc336b1f92a4fe743';
const entry_point = 'mint';
const token_owner = 'account-hash-878985c8c07064e09e67cc349dd21219b8e41942a0adc4bfa378cf0eace32611';
const deploy_params = new DeployStrParams(chain_name, public_key, secret_key);
const session_params = new SessionStrParams();
session_params.session_hash = contract_hash;
session_params.session_entry_point = entry_point;
session_params.session_args_simple = ["token_meta_data:String='test_meta_data'", `token_owner:Key='${token_owner}'`];
const call_entrypoint_result = await sdk.call_entrypoint_deploy(
deploy_params,
session_params,
payment_amount
);
const call_entrypoint_result_as_json = call_entrypoint_result.toJson();
console.log(call_entrypoint_result_as_json);
const deploy_hash = call_entrypoint_result.deploy_hash.toString();
console.log(deploy_hash);
Example of usage of the SDK in a Desktop application
The Electron based demo app loads the Angular example build. You can use this app on your computer to test every action the SDK can take.
$ cd ./examples/desktop/electron
$ npm install
$ npm start
$ npm build
You can download an alpha version of the app illustrating the SDK here:
- Microsoft Windows
- GNU/Linux AppImage
- GNU/Linux Snap
- [Mac][TODO]
In Typescript the window.CasperWalletProvider
is wrapped into CasperWallet
Class.
Two ways to sign a transaction, either signTransaction
transaction = await wallet.signTransaction(transaction, public_key); // public_key can be undefined for current active address in the wallet
or signTransactionHash and adding signature to the transaction
const public_key = await wallet.getActivePublicKey();
const signature = await wallet.signTransactionHash(
transaction.hash.toString(),
public_key
);
signature && (transaction = transaction.addSignature(public_key, signature));
Tests are run against NCTL by default. Alternately, you may configure another network in corresponding configuration. Tests assume a secret_key.pem
will be located in the root tests
directory, or one level higher at ../NCTL/casper-node/utils/nctl/assets/net-1/users/user-1/
. This path can be changed in the configuration or .env file.
(Rust tests must be run with --test-threads=1
)
- Unit tests can be run at root folder with
make test
configured with .env or configured in module
- Rust Integration tests can be run with
make integration-test
- Jest/Puppeteer E2E tests can be run with
cd tests/e2e/puppeteer
npm install
then
make e2e-test
configured with .env or puppeteer config
SECRET_KEY_NCTL_PATH
(alternative is direct keys SECRET_KEY_USER_1
and SECRET_KEY_USER_2
from casper-node-launcher-js )
Example of .env
SECRET_KEY_NCTL_PATH=/casper/casper-nctl-2-docker/assets/users/user-1/
# SECRET_KEY_USER_1 = MC4CAQAwBQYDK2VwBCIEII8ULlk1CJ12ZQ+bScjBt/IxMAZNggClWqK56D1/7CbI
# SECRET_KEY_USER_2 = MC4CAQAwBQYDK2VwBCIEIJTD9IlUYzuMHbvAiFel/uqd6V7vUtUD19IEQlo6SAFC
# NODE_ADDRESS=http://localhost:7777
# EVENT_ADDRESS=http://localhost:9999/events/main
# SPECULATIVE_ADDRESS=http://localhost:7778
# CHAIN_NAME=casper-net-1
# SECRET_KEY_NAME=secret_key.pem
- Expose more CL Types and Casper Client result Types
- EventStream
- Wallet connect