### Build and Test with Custom Features Source: https://odra.dev/docs/advanced/building-manually This example demonstrates building a contract in debug mode, running tests against the Casper backend, and enabling a specific project feature ('my-own-allocator') during the process. ```bash # Example: Build my_contract in debug mode with a custom allocator feature and run Casper tests # ODRA_MODULE=my_contract cargo build --target wasm32-unknown-unknown --bin my_project_build_contract --features my-own-allocator # ODRA_BACKEND=casper cargo test --features my-own-allocator ``` -------------------------------- ### Storage Key Generation Example Source: https://odra.dev/docs/advanced/storage-layout Demonstrates the concatenation process for a storage key, where the module prefix, mapping key, and index are combined before hashing. ```text borrowers.balances.get(0x1234abcd) -> 0x0001_0001_1234_abcd ``` -------------------------------- ### Setup Casper Node and Extract Credentials Source: https://odra.dev/docs/tutorials/using-proxy-caller Commands to initialize a local Casper NCTL node via Docker and extract the necessary secret key for contract deployment. ```bash docker run --rm -it --name mynctl -d -p 11101:11101 -p 14101:14101 -p 18101:18101 makesoftware/casper-nctl cargo odra build -c TimeLockWallet docker exec mynctl /bin/bash -c "cat /home/casper/casper-node/utils/nctl/assets/net-1/users/user-1/secret_key.pem" > your/path/secret_key.pem ``` -------------------------------- ### Casper Storage Interface Example Source: https://odra.dev/docs/advanced/storage-layout Illustrates a potential Rust interface for reading and writing data within the Casper VM's storage, using a key-value approach with string keys and byte array values. ```rust pub trait CasperStorage { fn read(key: &str) -> Option>; fn write(key: &str, value: Vec); } ``` -------------------------------- ### Deploy and Upgrade Contracts on Casper Livenet Source: https://odra.dev/docs/tutorials/upgrades This Rust example demonstrates initializing an upgradable contract, performing operations, and upgrading the contract to a new version using the Odra framework's try_upgrade method. ```rust //! This example demonstrates how to deploy and upgrade a contract on the Livenet environment. use odra::casper_types::U256; use odra::host::{Deployer, HostRef, InstallConfig, NoArgs}; use odra_examples::features::upgrade::{CounterV1, CounterV2, CounterV2UpgradeArgs}; fn main() { let env = odra_casper_livenet_env::env(); env.set_gas(500_000_000_000u64); // Contracts can be upgraded let mut counter = CounterV1::deploy_with_cfg(&env, NoArgs, InstallConfig::upgradable::()); env.set_gas(50_000_000_000u64); counter.increment(); assert_eq!(counter.get(), 1); env.set_gas(500_000_000_000u64); let mut counter2 = CounterV2::try_upgrade( &env, counter.contract_address(), CounterV2UpgradeArgs { new_start: None } ).unwrap(); env.set_gas(50_000_000_000u64); counter2.increment(); assert_eq!(counter2.get(), U256::from(2)); env.set_gas(500_000_000_000u64); let mut counter3 = CounterV1::try_upgrade(&env, counter.contract_address(), NoArgs).unwrap(); env.set_gas(50_000_000_000u64); counter3.increment(); assert_eq!(counter3.get(), 2); } ``` -------------------------------- ### Deploy Contract via Casper Client Source: https://odra.dev/docs/backends/casper Example command to deploy a WASM contract to the Casper network using the casper-client, including mandatory Odra configuration arguments and custom constructor parameters. ```shell casper-client put-transaction session \ --node-address [NODE_ADDRESS] \ --chain-name casper-test \ --secret-key [PATH_TO_YOUR_KEY]/secret_key.pem \ --payment-amount 5000000000000 \ --gas-price-tolerance 1 \ --standard-payment true \ --wasm-path ./wasm/counter.wasm \ --session-arg "odra_cfg_package_hash_key_name:string:'counter_package_hash'" \ --session-arg "odra_cfg_allow_key_override:bool:'true'" \ --session-arg "odra_cfg_is_upgradable:bool:'true'" \ --session-arg "odra_cfg_is_upgrade:bool:'false'" \ --session-arg "value:u32:42" ``` -------------------------------- ### Install and Verify Cargo Odra Source: https://odra.dev/docs/getting-started/installation Installs the Cargo Odra CLI tool for project management and verifies the installation by displaying help information. ```bash cargo install cargo-odra --locked cargo odra --help ``` -------------------------------- ### Rust Tests for Ownable Contract Initialization and Ownership Source: https://odra.dev/docs/tutorials/ownable This Rust code demonstrates how to test the Ownable smart contract. It includes setup for the test environment, verification of initial ownership, and tests for changing ownership by the owner and preventing changes by non-owners. It utilizes Odra's testing utilities for environment setup and event emission checks. ```Rust #[cfg(test)]mod tests { use super::*; use odra::host::{Deployer, HostEnv}; fn setup() -> (OwnableHostRef, HostEnv, Address) { let env: HostEnv = odra_test::env(); let init_args = OwnableInitArgs { owner: env.get_account(0) }; (Ownable::deploy(&env, init_args), env.clone(), env.get_account(0)) } #[test] fn initialization_works() { let (ownable, env, owner) = setup(); assert_eq!(ownable.get_owner(), owner); env.emitted_event( &ownable, OwnershipChanged { prev_owner: None, new_owner: owner } ); } #[test] fn owner_can_change_ownership() { let (mut ownable, env, owner) = setup(); let new_owner = env.get_account(1); env.set_caller(owner); ownable.change_ownership(&new_owner); assert_eq!(ownable.get_owner(), new_owner); env.emitted_event( &ownable, OwnershipChanged { prev_owner: Some(owner), new_owner } ); } #[test] fn non_owner_cannot_change_ownership() { let (mut ownable, env, _) = setup(); let new_owner = env.get_account(1); ownable.change_ownership(&new_owner); assert_eq!( ownable.try_change_ownership(&new_owner), Err(Error::NotOwner.into()) ); }} ``` -------------------------------- ### Define Storage Mapping Structure Source: https://odra.dev/docs/advanced/storage-layout Example structure of a Loans module showing how lenders and borrowers are defined with specific prefixes and keys for storage mapping. ```rust Loans { lenders: Token { name: 1, balances: 2 }, borrowers: Token { name: 1, balances: 2 } } ``` -------------------------------- ### Configure Livenet Integration (.env) Source: https://odra.dev/docs/backends/livenet This section details the environment variables required for ODRA's Livenet integration. It covers paths to secret keys, node addresses, event URLs, and chain names. It also explains how to manage multiple .env files for different deployments and provides examples for CSPR.cloud and nctl setups. ```env # .env file used by Livenet integration. You can use multiple .env files to manage deploys on multiple chains# by naming them casper-test.env, casper-livenet.env, etc. and calling the deploy script with the name of the# ennviroment provided in the "ODRA_CASPER_LIVENET_ENV" variable. For example:# ODRA_CASPER_LIVENET_ENV=casper-test cargo run --bin livenet_tests --features livenet# This will load integration.env file first, and then fill the missing values with the values from casper-test.env.# Path to the secret key of the account that will be used to deploy the contracts.# If you are using the nctl, you can use the following command to extract the secret key from the container:# docker exec mynctl /bin/bash -c "cat /home/casper/casper-nctl/assets/net-1/users/user-1/secret_key.pem" > examples/.node-keys/secret_key.pem# docker exec mynctl /bin/bash -c "cat /home/casper/casper-nctl/assets/net-1/users/user-2/secret_key.pem" > examples/.node-keys/secret_key_1.pemODRA_CASPER_LIVENET_SECRET_KEY_PATH=# RPC address of the node that will be used to deploy the contracts.# For CSPR.cloud, you can use the following addresses:# - https://node.cspr.cloud# - https://node.testnet.cspr.cloud# For nctl, default is:# - http://localhost:11101ODRA_CASPER_LIVENET_NODE_ADDRESS=# Events url# For CSPR.cloud, you can use the following addresses:# - https://node.cspr.cloud/events# For nctl, default is:# - http://localhost:18101/eventsODRA_CASPER_LIVENET_EVENTS_URL=# Chain name of the network. The mainnet is "casper" and test net is "casper-test".# The integration network uses the "integration-test" chain name.# For nctl default is "casper-net-1" ODRA_CASPER_LIVENET_CHAIN_NAME=# Optionally, paths to the secret keys of the additional acccounts. Main secret key will be 0th account.# The following will work for nctl if you used the command above to extract the secret keys:# ODRA_CASPER_LIVENET_KEY_1=./keys/secret_key_1.pem#ODRA_CASPER_LIVENET_KEY_1=# If using CSPR.cloud, you can set the auth token here.# CSPR_CLOUD_AUTH_TOKEN=# Optionally, you can set the TTL for the deploys. Default is 5 minutes.# ODRA_CASPER_LIVENET_TTL= ``` -------------------------------- ### Rust: Deploy and Test Dog Contract with Odra Source: https://odra.dev/docs/basics/testing This snippet demonstrates how to deploy a 'DogContract3' using Odra's testing environment and then perform assertions on its state and entrypoints. It utilizes `odra_test::env()` to get a test environment and `DogContract3::deploy` for deployment. It also shows calling contract methods like `walk_the_dog` and asserting values using `assert_eq!`. Dependencies include `odra::prelude::*` and `odra::host::Deployer`. ```rust use odra::prelude::*; #[cfg(test)] mod tests { use super::{DogContract3, DogContract3InitArgs}; use odra::{host::Deployer, prelude::*}; #[test] fn init_test() { let test_env = odra_test::env(); let init_args = DogContract3InitArgs { name: "DogContract".to_string() }; let mut dog_contract = DogContract3::deploy(&test_env, init_args); assert_eq!(dog_contract.walks_amount(), 0); assert_eq!(dog_contract.walks_total_length(), 0); dog_contract.walk_the_dog(5); dog_contract.walk_the_dog(10); assert_eq!(dog_contract.walks_amount(), 2); assert_eq!(dog_contract.walks_total_length(), 15); } } ``` -------------------------------- ### Adding Multiple Contracts to Odra.toml Source: https://odra.dev/docs/basics/odra-toml This example illustrates how to manually add multiple contracts to the Odra.toml file. Each contract requires its own '[[contracts]]' section with a correctly set 'fqn'. This allows for the compilation of several contracts within a single Odra project. ```toml [[contracts]] fqn = "sample::Flipper" [[contracts]] fqn = "sample::Counter" ``` -------------------------------- ### Contract Metadata and Initialization (TypeScript) Source: https://odra.dev/docs/tutorials/build-deploy-read Illustrates the structure of contract metadata and how it might be represented after compilation and execution. This snippet shows an example of a Metadata object with name, description, and prices, along with some numerical values. ```typescript tsc && node target/index.js Metadata { name: 'My Contract', description: 'My Description', prices: [ Price { value: 123n }, Price { value: 321n } ]}666n20n10n ``` -------------------------------- ### Deploy and Deposit via Proxy Caller in TypeScript Source: https://odra.dev/docs/tutorials/using-proxy-caller This snippet demonstrates how to install a smart contract using the Casper JS SDK and how to invoke a payable deposit function through a proxy_caller. It handles the serialization of runtime arguments and the creation of deploy objects for the Casper network. ```typescript import { CLByteArray, CLList, CLU8, CLValueBuilder, CasperClient, Contracts, Keys, RuntimeArgs, csprToMotes, decodeBase16 } from "casper-js-sdk"; import fs from "fs"; const CONTRACT_PATH = "wasm/TimeLockWallet.wasm"; const PROXY_CALLER_PATH = "wasm/proxy_caller.wasm"; const CHAIN_NAME = "casper-net-1"; const GAS = 110; export async function deploy_contract(): Promise { const args = RuntimeArgs.fromMap({ odra_cfg_package_hash_key_name: CLValueBuilder.string("tlw"), odra_cfg_allow_key_override: CLValueBuilder.bool(true), odra_cfg_is_upgradable: CLValueBuilder.bool(true), odra_cfg_is_upgrade: CLValueBuilder.bool(false), lock_duration: CLValueBuilder.u64(60 * 60) }); const wasm = new Uint8Array(fs.readFileSync(CONTRACT_PATH)); const deploy = contract.install(wasm, args, csprToMotes(GAS).toString(), keypair.publicKey, CHAIN_NAME, [keypair]); return casperClient.putDeploy(deploy); } export async function deposit(): Promise { const contractPackageHashBytes = new CLByteArray(decodeBase16(CONTRACT_PACKAGE_HASH)); const args_bytes: Uint8Array = RuntimeArgs.fromMap({}).toBytes().unwrap(); const serialized_args = new CLList(Array.from(args_bytes).map(value => new CLU8(value))); const args = RuntimeArgs.fromMap({ attached_value: CLValueBuilder.u512(DEPOSIT), amount: CLValueBuilder.u512(DEPOSIT), entry_point: CLValueBuilder.string(ENTRY_POINT), contract_package_hash: contractPackageHashBytes, args: serialized_args }); const wasm = new Uint8Array(fs.readFileSync(PROXY_CALLER_PATH)); const deploy = contract.install(wasm, args, csprToMotes(GAS).toString(), keypair.publicKey, CHAIN_NAME, [keypair]); return casperClient.putDeploy(deploy); } ``` -------------------------------- ### Implementing Payable Function in Odra Source: https://odra.dev/docs/advanced/attributes Demonstrates how to use the #[odra(payable)] attribute to allow a function to accept native tokens. The example includes extracting the caller address and attached value, performing state validation, and emitting an event. ```rust #[odra(payable)] pub fn deposit(&mut self) { let caller: Address = self.env().caller(); let amount: U256 = self.env().attached_value(); let current_block_time: u64 = self.env().get_block_time(); if self.balances.get(&caller).is_some() { self.env.revert(Error::CannotLockTwice) } self.balances.set(&caller, amount); self.lock_expiration_map.set(&caller, current_block_time + self.lock_duration()); self.env().emit_event(Deposit { address: caller, amount }); } ``` -------------------------------- ### Implement Odra List for Ordered Collections Source: https://odra.dev/docs/basics/storage-interaction Shows how to use the Odra List type, which internally uses a Mapping and a Var, to store ordered collections. This example demonstrates initializing a contract with a List of u32, adding new entries, and calculating the total number and sum of lengths of walks. ```Rust use odra::prelude::*; #[odra::module] pub struct DogContract3 { name: Var, walks: List, } #[odra::module] impl DogContract3 { pub fn init(&mut self, name: String) { self.name.set(name); } pub fn name(&self) -> String { self.name.get_or_default() } pub fn walks_amount(&self) -> u32 { self.walks.len() } pub fn walks_total_length(&self) -> u32 { self.walks.iter().sum() } pub fn walk_the_dog(&mut self, length: u32) { self.walks.push(length); } } ``` -------------------------------- ### Defining a Smart Contract with Odra Attributes Source: https://odra.dev/docs/basics/casper-contract-schema This example demonstrates how to define a contract module, events, errors, and custom types using Odra's procedural macros. These attributes ensure the contract metadata is correctly captured in the generated Casper Contract Schema. ```rust use odra::prelude::*;#[odra::module(name = "MyContract", version = "0.1.0", events = [Created, Updated], errors = MyErrors)]pub struct MyContract { name: Var, owner: Var
,}#[odra::module]impl MyContract { pub fn init(&mut self, name: String, owner: Address) { self.name.set(name.clone()); self.owner.set(owner.clone()); self.env().emit_event(Created { name }); } pub fn update(&mut self, name: String) { self.name.set(name.clone()); self.env().emit_event(Updated { name }); } pub fn get_data(&self) -> Data { Data { name: self.name.get_or_default(), owner: self.owner.get_or_revert_with(MyErrors::InvalidOwner), } }}#[odra::odra_type]pub struct Data { name: String, owner: Address,}#[odra::odra_error]pub enum MyErrors { InvalidOwner, InvalidName,}#[odra::event]pub struct Updated { name: String,}#[odra::event]pub struct Created { name: String,} ``` -------------------------------- ### Testing Contract Deployment with HostEnv Source: https://odra.dev/docs/basics/testing Demonstrates how to initialize a HostEnv, set different callers using set_caller, and deploy multiple contract instances to verify unique creator addresses. ```rust #[cfg(test)] mod tests { use crate::features::testing::{TestingContract, TestingContractInitArgs}; use odra::{host::{Deployer, HostEnv}, prelude::*}; #[test] fn env() { let test_env: HostEnv = odra_test::env(); test_env.set_caller(test_env.get_account(0)); let init_args = TestingContractInitArgs { name: "MyContract".to_string() }; let testing_contract = TestingContract::deploy(&test_env, init_args); let creator = testing_contract.created_by(); test_env.set_caller(test_env.get_account(1)); let init_args = TestingContractInitArgs { name: "MyContract2".to_string() }; let testing_contract2 = TestingContract::deploy(&test_env, init_args); let creator2 = testing_contract2.created_by(); assert_ne!(creator, creator2); } } ``` -------------------------------- ### Example Contract Schema JSON Output Source: https://odra.dev/docs/basics/casper-contract-schema An example of the JSON schema generated for a smart contract. This schema details the contract's version, toolchain, author information, contract name and version, custom types, defined errors, entry points, and events. ```json { "casper_contract_schema_version": 1, "toolchain": "rustc 1.77.0-nightly (5bd5d214e 2024-01-25)", "authors": [], "repository": null, "homepage": null, "contract_name": "MyContract", "contract_version": "0.1.0", "types": [ { "struct": { "name": "Created", "description": null, "members": [ { "name": "name", "description": null, "ty": "String" } ] } }, { "struct": { "name": "Data", "description": null, "members": [ { "name": "name", "description": null, "ty": "String" }, { "name": "owner", "description": null, "ty": "Key" } ] } }, { "struct": { "name": "Updated", "description": null, "members": [ { "name": "name", "description": null, "ty": "String" } ] } } ], "errors": [ { "name": "InvalidName", "description": "The name is invalid", "discriminant": 1 }, { "name": "InvalidOwner", "description": "The owner is invalid", "discriminant": 0 } ], "entry_points": [ { "name": "update", "description": "Updates the name of the contract and emits an event", "is_mutable": true, "arguments": [ { "name": "name", "description": null, "ty": "String", "optional": false } ], "return_ty": "Unit", "is_contract_context": true, "access": "public" }, { "name": "get_data", "description": "Returns the data of the contract", "is_mutable": false, "arguments": [], "return_ty": "Data", "is_contract_context": true, "access": "public" } ], "events": [ { "name": "Created", "ty": "Created" }, { "name": "Updated", "ty": "Updated" } ], "call": { "wasm_file_name": "MyContract.wasm", "description": "Initializes the contract, sets the name and owner and emits an event", "arguments": [ { "name": "odra_cfg_package_hash_key_name", "description": "The arg name for the package hash key name.", "ty": "String", "optional": false }, { "name": "odra_cfg_allow_key_override", "description": "The arg name for the allow key override.", "ty": "Bool", "optional": false }, { "name": "odra_cfg_is_upgradable", "description": "The arg name for the contract upgradeability setting.", "ty": "Bool", "optional": false }, { "name": "odra_cfg_is_upgrade", "description": "The arg name for the contract upgrade setting.", "ty": "Bool", "optional": false }, { "name": "name", "description": null, "ty": "String", "optional": false }, { "name": "owner", "description": null, "ty": "Key", "optional": false } ] } } ``` -------------------------------- ### Initialize and Test Odra Project Source: https://odra.dev/docs/getting-started/installation Creates a new Odra project and demonstrates how to run tests using the internal OdraVM or a specific backend like CasperVM. ```bash cargo odra new --name my-project && cd my_project cargo odra test cargo odra test -b casper ``` -------------------------------- ### GET /env/delegated_amount Source: https://odra.dev/docs/advanced/delegating-cspr Queries the current delegated amount for a specific delegator and validator. ```APIDOC ## GET /env/delegated_amount ### Description Retrieves the total amount of tokens currently delegated by a specific address to a specific validator. ### Method GET ### Endpoint /env/delegated_amount ### Query Parameters - **delegator** (Address) - Required - The address of the delegator. - **validator** (PublicKey) - Required - The public key of the validator. ### Response #### Success Response (200) - **amount** (U512) - The total delegated amount. ``` -------------------------------- ### Update cargo-odra toolchain Source: https://odra.dev/docs/migrations/to-0.9.0 Command to install or update the cargo-odra toolchain to the latest version required for the migration. ```bash cargo install cargo-odra --force --locked ``` -------------------------------- ### Deploying Contracts with Odra (Rust) Source: https://odra.dev/docs/migrations/to-0.8.0 Demonstrates the updated method for deploying contracts in Odra using `HostRef::deploy()`. It covers both contracts with and without initialization arguments, contrasting with the older `Deployer::init()` method. ```Rust use super::OwnableHostRef; use odra::host::{Deployer, HostEnv, HostRef, NoArgs}; let env: HostEnv = odra_test::env(); let ownable = OwnableHostRef::deploy(&env, NoArgs) ``` ```Rust use super::{Erc20HostRef, Erc20InitArgs}; use odra::host::{Deployer, HostEnv}; let env: HostEnv = odra_test::env(); let init_args = Erc20InitArgs { symbol: SYMBOL.to_string(), name: NAME.to_string(), decimals: DECIMALS, initial_supply: Some(INITIAL_SUPPLY.into()) }; let erc20 = Erc20HostRef::deploy(&env, init_args) ``` ```Rust use super::OwnableDeployer; let ownable = OwnableDeployer::init() ``` ```Rust use super::{Erc20Deployer, Erc20InitArgs}; let erc20 = Erc20Deployer::init( SYMBOL.to_string(), NAME.to_string(), DECIMALS, &Some(INITIAL_SUPPLY.into()) ) ``` -------------------------------- ### Define CEP-18 Token Module Source: https://odra.dev/docs/tutorials/cep18 Example of defining a token struct in Odra that delegates functionality to the built-in Cep18 module. ```rust #[odra::module] pub struct MyToken { token: SubModule, } impl MyToken { // Delegate all Cep18 functions to the token sub-module. delegate! { to self.token { fn name(&self) -> String; fn symbol(&self) -> String; } } } ``` -------------------------------- ### Implement Contract Logic with Var Source: https://odra.dev/docs/basics/storage-interaction Shows how to implement initialization and getter methods for a contract using Var, including handling default values and state updates. ```rust #[odra::module]impl DogContract { pub fn init(&mut self, barks: bool, weight: u32, name: String) { self.barks.set(barks); self.weight.set(weight); self.name.set(name); self.walks.set(Vec::::default()); } pub fn barks(&self) -> bool { self.barks.get_or_default() } pub fn weight(&self) -> u32 { self.weight.get_or_default() } pub fn name(&self) -> String { self.name.get_or_default() } pub fn walks_amount(&self) -> u32 { let walks = self.walks.get_or_default(); walks.len() as u32 } pub fn walks_total_length(&self) -> u32 { let walks = self.walks.get_or_default(); walks.iter().sum() }} ``` -------------------------------- ### Execute Livenet Deployment Command Source: https://odra.dev/docs/tutorials/using-proxy-caller Command to run the compiled binary with the required environment variables for network connectivity. ```bash ODRA_CASPER_LIVENET_SECRET_KEY_PATH=path/to/secret_key.pem \ ODRA_CASPER_LIVENET_NODE_ADDRESS=[NODE_ADDRESS] \ ODRA_CASPER_LIVENET_CHAIN_NAME=casper-test \ ODRA_CASPER_LIVENET_EVENTS_URL=[EVENTS_STREAM_ADDRESS] \ cargo run --bin tlw_on_livenet --features=livenet ``` -------------------------------- ### Initialize Odra Wasm Client and Event Callbacks Source: https://odra.dev/docs/advanced/wasm-client Demonstrates how to initialize the WASM module, configure the OdraWasmClient, and register event listeners for wallet interactions and transaction updates. ```typescript async function run() { await init(); contracts = await Contracts.fromPath('./contracts.json'); client = new OdraWasmClient(RPC_URL, SPECULATIVE_RPC_URL, CHAIN_NAME); counter = new CounterWasmClient(client, contracts.get("Counter").address); CsprClickCallbacks.onSignedIn(async (accountInfo: AccountInfo) => { await onConnect(accountInfo); }); CsprClickCallbacks.onTransactionStatusUpdate((status: TransactionStatus, data: TransactionResult) => { onTransactionStatusUpdate(status, data); }); } run().catch(err => console.error("Failed to initialize:", err)); ``` -------------------------------- ### Contract Deployment Source: https://odra.dev/docs/migrations/to-0.8.0 Demonstrates the new method for deploying contracts using `HostRef::deploy` and `odra_test::env()`, contrasting it with the older `Deployer::init()` method. ```APIDOC ## POST /contracts/deploy ### Description This endpoint details the updated process for deploying smart contracts in Odra. It emphasizes the shift from `{{ModuleName}}Deployer::init()` to `{{ModuleName}}HostRef::deploy(&env, args)`, requiring instantiation of `HostEnv` via `odra_test::env()`. ### Method POST ### Endpoint /contracts/deploy ### Parameters #### Request Body - **module_name** (string) - Required - The name of the module to deploy. - **init_args** (object | null) - Optional - Initialization arguments for the contract. Use `odra::host::NoArgs` if no arguments are needed, or an autogenerated `{{ModuleName}}InitArgs` struct if arguments are present. ### Request Example ```json { "module_name": "Ownable", "init_args": null } ``` ### Request Example (with init args) ```json { "module_name": "Erc20", "init_args": { "symbol": "TKN", "name": "Token", "decimals": 18, "initial_supply": "1000000" } } ``` ### Response #### Success Response (200) - **contract_address** (string) - The address of the newly deployed contract. #### Response Example ```json { "contract_address": "0x1234567890abcdef1234567890abcdef12345678" } ``` ``` -------------------------------- ### Test: Initial Token Deployment and Mint Proposal Source: https://odra.dev/docs/tutorials/cep18 Tests the initial deployment of the OurToken and the proposal of a new mint. It verifies the initial state and the actions taken during the proposal process. ```Rust #[cfg(test)] mod tests { use super::*; use odra::host::Deployer; #[test] fn it_works() { let env = odra_test::env(); let init_args = OurTokenInitArgs { name: "OurToken".to_string(), symbol: "OT".to_string(), decimals: 0, initial_supply: U256::from(1_000u64), }; let mut token = OurToken::deploy(&env, init_args); token.propose_new_mint(env.get_account(1), U256::from(2000)); token.vote(true, U256::from(1000)); assert_eq!(token.balance_of(&env.get_account(0)), U256::zero()); env.advance_block_time(60 * 11 * 1000); token.tally(); } } ``` -------------------------------- ### Transfer Tokens in Host Environment Source: https://odra.dev/docs/basics/native-token Illustrates how to perform native token transfers between accounts in a live network or test environment using the HostEnv interface. ```rust let env = odra_casper_livenet_env::env();let (alice, bob) = (env.get_account(0), env.get_account(1));env.set_caller(alice);let result = env.transfer_tokens(bob, odra::casper_types::U512::from(100)); ``` -------------------------------- ### Custom Odra Type: Unit-Only Enum Example Source: https://odra.dev/docs/basics/storage-interaction Illustrates a unit-only enum definition in Rust that can be used as a custom type in Odra. Such enums are serialized as CLType::U8, providing a compact representation for distinct states or values. ```Rust enum Enum { Foo = 3, Bar = 2, Baz = 1, } ``` -------------------------------- ### Deploy Odra Contract using Casper-Client Source: https://odra.dev/docs/tutorials/build-deploy-read This snippet demonstrates deploying an Odra contract to a local Casper network. It involves setting up the network, compiling the contract, and then using the casper-client to perform the deployment with various session arguments. ```bash docker run --rm -it --name mynctl -d -p 11101:11101 -p 14101:14101 -p 18101:18101 makesoftware/casper-nctl ``` ```bash cargo odra build -c custom_item ``` ```bash casper-client put-transaction session \ --node-address http://localhost:11101 \ --chain-name casper-net-1 \ --secret-key path/to/your/secret_key.pem \ --wasm-path ./wasm/Erc20.wasm \ --payment-amount 450000000000 \ --gas-price-tolerance 1 \ --standard-payment true \ --session-arg "odra_cfg_package_hash_key_name:string:'test_contract_package_hash'" \ --session-arg "odra_cfg_allow_key_override:bool:'true'" \ --session-arg "odra_cfg_is_upgradable:bool:'true'" \ --session-arg "odra_cfg_is_upgrade:bool:'false'" \ --session-arg "name:string='My Name'" \ --session-arg "description:string='My Description'" \ --session-arg "price_1:u256='101'" \ --session-arg "price_2:u256='202'" ``` -------------------------------- ### Get Caller Information with Odra CLI 'whoami' Source: https://odra.dev/docs/tutorials/odra-cli The `whoami` command retrieves and displays the address and public key of the currently configured caller account in the livenet environment. This is crucial for verifying the signing account before executing transactions. ```bash cargo run --bin odra_cli -- whoami 💁 INFO : Address: Account(AccountHash(a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b3)) 💁 INFO : PublicKey::Ed25519(c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4) 💁 INFO : Command executed successfully ``` -------------------------------- ### Implement Contract Logic and Constructor Source: https://odra.dev/docs/basics/flipper-internals Shows how to implement contract entry points and the constructor using the #[odra::module] attribute on an impl block. ```rust #[odra::module] impl Flipper { pub fn init(&mut self) { self.value.set(false); } } ``` -------------------------------- ### Deploy DogContract using Odra CLI Source: https://odra.dev/docs/tutorials/odra-cli This script demonstrates deploying a DogContract using various methods provided by the Odra CLI. It includes setting gas limits, deploying directly, deploying with custom configurations via InstallConfig, and using the DeployerExt trait for conditional deployment. ```rust use odra::host::HostEnv; use odra_cli::{ deploy::DeployScript, DeployerExt, DeployedContractsContainer, }; use odra_examples::features::storage::variable::{DogContract, DogContractInitArgs}; /// Deploys the `DogContract` and adds it to the container. pub struct DeployDogScript; impl DeployScript for DeployDogScript { fn deploy( &self, env: &HostEnv, container: &mut DeployedContractsContainer ) -> Result<(), odra_cli::deploy::Error> { env.set_gas(350_000_000_000); let dog_contract = DogContract::try_deploy( env, DogContractInitArgs { barks: true, weight: 10, name: "Mantus".to_string() } )?; container.add_contract(&dog_contract)?; // By default, a contract is non-upgradeable, you can change it by passing `InstallConfig` _ = DogContract::try_deploy_with_cfg( env, DogContractInitArgs { barks: true, weight: 10, name: "Mantus".to_string() }, InstallConfig::upgradable::() )?; // Alternatively, you can use the `DeployerExt` trait to deploy the contract: _ = DogContract::load_or_deploy( env, DogContractInitArgs { barks: true, weight: 10, name: "Mantus".to_string() }, container, 350_000_000_000 )?; // You can use `load_or_deploy_with_cfg` to deploy the contract with a custom configuration _ = DogContract::load_or_deploy_with_cfg( env, DogContractInitArgs { barks: true, weight: 10, name: "Mantus".to_string() }, InstallConfig::upgradable::(), container, 350_000_000_000 )?; Ok(()) } } ``` -------------------------------- ### Implement MyToken using Erc20 Module Source: https://odra.dev/docs/examples/using-odra-modules Demonstrates how to define a smart contract struct using the Erc20 module as a sub-module and implement token functionality by delegating calls to the sub-module. ```rust use odra::prelude::*;use odra::casper_types::U256;use odra_modules::erc20::Erc20;#[odra::module]pub struct MyToken { erc20: SubModule}#[odra::module]impl OwnedToken { pub fn init(&mut self, initial_supply: U256) { let name = String::from("MyToken"); let symbol = String::from("MT"); let decimals = 9u8; self.erc20.init(name, symbol, decimals, initial_supply); } pub fn name(&self) -> String { self.erc20.name() } pub fn symbol(&self) -> String { self.erc20.symbol() } pub fn decimals(&self) -> u8 { self.erc20.decimals() } pub fn total_supply(&self) -> U256 { self.erc20.total_supply() } pub fn balance_of(&self, address: Address) -> U256 { self.erc20.balance_of(address) } pub fn allowance(&self, owner: Address, spender: Address) -> U256 { self.erc20.allowance(owner, spender) } pub fn transfer(&mut self, recipient: Address, amount: U256) { self.erc20.transfer(recipient, amount); } pub fn transfer_from(&mut self, owner: Address, recipient: Address, amount: U256) { self.erc20.transfer_from(owner, recipient, amount); } pub fn approve(&mut self, spender: Address, amount: U256) { self.erc20.approve(spender, amount); }} ``` -------------------------------- ### Define and Use Odra Mapping for Key-Value Storage Source: https://odra.dev/docs/basics/storage-interaction Demonstrates how to define a Mapping to store key-value pairs, with String keys and u32 values. It shows how to set and get values, incrementing visit counts for friends. Mappings are similar to HashMaps but do not support iteration. ```Rust use odra::prelude::*; #[odra::module] pub struct DogContract2 { name: Var, friends: Mapping, } impl DogContract2 { pub fn visit(&mut self, friend_name: String) { let visits = self.visits(friend_name.clone()); self.friends.set(&friend_name, visits + 1); } pub fn visits(&self, friend_name: String) -> u32 { self.friends.get_or_default(&friend_name) } } ``` -------------------------------- ### Initialize Odra NFT Project Source: https://odra.dev/docs/tutorials/nft Initializes a new Odra project using the CEP-95 template. This command sets up the necessary directory structure and dependencies for NFT development. ```bash cargo odra new --name ticket-office --template cep95 ``` -------------------------------- ### AdvancedStorage Contract with Sequence and Mapping (Rust) Source: https://odra.dev/docs/advanced/advanced-storage An example of an Odra contract utilizing both the Sequence module for managing a single incrementing value and a Mapping for storing Token modules, accessed via composite keys. It shows how to interact with these storage types for contract state management. ```Rust use odra::casper_types::U512; use odra::prelude::*; use crate::modules::Token; #[odra::module] pub struct AdvancedStorage { counter: Sequence, tokens: Mapping<(String, String), Token>, } impl AdvancedStorage { pub fn current_value(&self) -> u32 { self.counter.get_current_value() } pub fn increment_and_get(&mut self) -> u32 { self.counter.next_value() } pub fn balance_of(&mut self, token_name: String, creator: String, address: Address) -> U512 { let token = self.tokens.module(&(token_name, creator)); token.balance_of(&address) } pub fn mint(&self, token_name: String, creator: String, amount: U512, to: Address) { let mut token = self.tokens.module(&(token_name, creator)); token.mint(amount, to); } } ``` -------------------------------- ### Initialize Odra CEP-18 Project Source: https://odra.dev/docs/tutorials/cep18 Command to generate a new Odra project using the CEP-18 template. ```bash cargo odra new --name ourcoin --template cep18 ``` -------------------------------- ### Run Scenarios with Odra CLI Source: https://odra.dev/docs/tutorials/odra-cli The `scenario` command allows execution of registered scenarios within the Odra CLI. It can list available scenarios and run specific ones, like checking contract state. An example demonstrates running a 'check' scenario for contract name verification. ```bash cargo run --bin odra_cli -- scenario Commands for running user-defined scenarios Usage: odra_cli scenario Commands: check Checks if the name of the deployed dog matches the provided name help Print this message or the help of the given subcommand(s) cargo run --bin odra_cli -- scenario check --name Doggy thread 'main' panicked at examples/bin/odra_cli.rs:59:9: assertion `left == right` failed: Dog name mismatch left: "Doggy" right: "Mantus" ``` -------------------------------- ### Delegating Functions with Odra Delegate Macro Source: https://odra.dev/docs/advanced/delegate This example demonstrates how to use the delegate! macro in an Odra module to expose functions from child modules (Erc20 and Ownable) directly within the parent module. This reduces boilerplate by allowing the parent to act as a proxy for child module functionality. ```rust use crate::{erc20::Erc20, ownable::Ownable}; use odra::{casper_types::U256, prelude::*}; #[odra::module] pub struct OwnedToken { ownable: SubModule, erc20: SubModule } #[odra::module] impl OwnedToken { pub fn init(&mut self, name: String, symbol: String, decimals: u8, initial_supply: U256) { let deployer = self.env().caller(); self.ownable.init(deployer); self.erc20.init(name, symbol, decimals, initial_supply); } delegate! { to self.erc20 { fn transfer(&mut self, recipient: Address, amount: U256); fn transfer_from(&mut self, owner: Address, recipient: Address, amount: U256); fn approve(&mut self, spender: Address, amount: U256); fn name(&self) -> String; fn symbol(&self) -> String; fn decimals(&self) -> u8; fn total_supply(&self) -> U256; fn balance_of(&self, owner: Address) -> U256; fn allowance(&self, owner: Address, spender: Address) -> U256; } to self.ownable { fn get_owner(&self) -> Address; fn change_ownership(&mut self, new_owner: Address); } } pub fn mint(&mut self, address: Address, amount: U256) { self.ownable.ensure_ownership(self.env().caller()); self.erc20.mint(address, amount); } } ``` -------------------------------- ### Add Odra CLI to Cargo.toml Source: https://odra.dev/docs/tutorials/odra-cli This snippet shows how to add the `odra-cli` dependency to your project's `Cargo.toml` file. It also configures a new binary target named `odra-cli` that will use the specified path for its source code. This setup is necessary to enable the Odra CLI functionality. ```toml [dependencies] ...odra-cli = "2" [[bin]] name = "odra-cli" path = "bin/odra-cli.rs" ``` -------------------------------- ### Initialize Ownable Module Source: https://odra.dev/docs/tutorials/ownable Demonstrates how to define an Odra module with an initialization constructor, custom error handling, and event emission for ownership changes. ```rust #[odra::module] impl Ownable { pub fn init(&mut self, owner: Address) { if self.owner.get_or_default().is_some() { self.env().revert(Error::OwnerIsAlreadyInitialized) } self.owner.set(Some(owner)); self.env().emit_event(OwnershipChanged { prev_owner: None, new_owner: owner }); } } #[odra::odra_error] pub enum Error { OwnerIsAlreadyInitialized = 1, } #[odra::event] pub struct OwnershipChanged { pub prev_owner: Option
, pub new_owner: Address } ```