Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 10 additions & 4 deletions contract-rs/01-basic-auction/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,20 @@ crate-type = ["cdylib", "rlib"]

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
near-sdk = "5.23.0"
near-sdk = "5.24.0"

[dev-dependencies]
near-sdk = { version = "5.23.0", features = ["unit-testing"] }
near-workspaces = { version = "0.22.0", features = ["unstable"] }
near-sdk = { version = "5.24.0", features = ["unit-testing"] }
near-sandbox = "0.3"
near-api = "0.8"
cargo-near-build = "0.10"
tokio = { version = "1.12.0", features = ["full"] }
serde_json = "1"
chrono = "0.4.38"
testresult = "0.4.1"
# This is temporary fix for the build error since those crates with a higher version require a higher version of Rust compiler (1.88.0)
cargo-platform = "=0.3.1"
darling = "=0.20.11"
bon = "=3.8.1"

[profile.release]
codegen-units = 1
Expand Down
237 changes: 139 additions & 98 deletions contract-rs/01-basic-auction/tests/test_basics.rs
Original file line number Diff line number Diff line change
@@ -1,148 +1,189 @@
use chrono::Utc;
use near_sdk::near;
use near_workspaces::types::{AccountId, Gas, NearToken};
use serde_json::json;
use near_api::{AccountId, NearGas, NearToken};
use near_sdk::serde_json::json;

#[near(serializers = [json])]
#[derive(Clone)]
#[derive(near_sdk::serde::Deserialize)]
#[serde(crate = "near_sdk::serde")]
pub struct Bid {
pub bidder: AccountId,
pub bid: NearToken,
}

const TEN_NEAR: NearToken = NearToken::from_near(10);

#[tokio::test]
async fn test_contract_is_operational() -> Result<(), Box<dyn std::error::Error>> {
let sandbox = near_workspaces::sandbox().await?;
async fn test_contract_is_operational() -> testresult::TestResult<()> {
// Build the contract wasm file
let contract_wasm_path = cargo_near_build::build_with_cli(Default::default())?;
let contract_wasm = std::fs::read(contract_wasm_path)?;

let root = sandbox.root_account()?;
// Initialize the sandbox
let sandbox = near_sandbox::Sandbox::start_sandbox().await?;
let sandbox_network =
near_api::NetworkConfig::from_rpc_url("sandbox", sandbox.rpc_addr.parse()?);

// Create accounts
let alice = create_subaccount(&root, "alice").await?;
let bob = create_subaccount(&root, "bob").await?;
let auctioneer = create_subaccount(&root, "auctioneer").await?;
let contract_account = create_subaccount(&root, "contract").await?;

// Deploy and initialize contract
let contract_wasm = near_workspaces::compile_project("./").await?;
let contract = contract_account.deploy(&contract_wasm).await?.unwrap();

let now = Utc::now().timestamp();
let alice = create_subaccount(&sandbox, "alice.sandbox").await?;
let bob = create_subaccount(&sandbox, "bob.sandbox").await?;
let auctioneer = create_subaccount(&sandbox, "auctioneer.sandbox").await?;
let contract = create_subaccount(&sandbox, "contract.sandbox")
.await?
.as_contract();

// Initialize signer for the contract deployment
let signer = near_api::Signer::from_secret_key(
near_sandbox::config::DEFAULT_GENESIS_ACCOUNT_PRIVATE_KEY
.parse()
.unwrap(),
)?;

// Calculate the end time for the auction as a parameter for the init function
let now = std::time::SystemTime::now()
.duration_since(std::time::SystemTime::UNIX_EPOCH)?
.as_secs();
let a_minute_from_now = (now + 60) * 1000000000;

let init = contract
.call("init")
.args_json(json!({"end_time": a_minute_from_now.to_string(),"auctioneer":auctioneer.id()}))
.transact()
.await?;

assert!(init.is_success());
// Deploy the contract with the init call
near_api::Contract::deploy(contract.account_id().clone())
.use_code(contract_wasm)
.with_init_call(
"init",
json!({"end_time": a_minute_from_now.to_string(), "auctioneer": auctioneer.account_id()}),
)?
.with_signer(signer.clone())
.send_to(&sandbox_network)
.await?
.assert_success();

// Alice makes first bid
let alice_bid = alice
.call(contract.id(), "bid")
contract
.call_function("bid", ())
.transaction()
.deposit(NearToken::from_near(1))
.transact()
.await?;

assert!(alice_bid.is_success());
.with_signer(alice.account_id().clone(), signer.clone())
.send_to(&sandbox_network)
.await?
.assert_success();

let highest_bid_json = contract.view("get_highest_bid").await?;
let highest_bid: Bid = highest_bid_json.json::<Bid>()?;
// For now, the highest bid is the Alice's bid
let highest_bid: Bid = contract
.call_function("get_highest_bid", ())
.read_only()
.fetch_from(&sandbox_network)
.await?
.data;
assert_eq!(highest_bid.bid, NearToken::from_near(1));
assert_eq!(highest_bid.bidder, *alice.id());
assert_eq!(&highest_bid.bidder, alice.account_id());

let alice_balance = alice.view_account().await?.balance;
let alice_balance = alice
.tokens()
.near_balance()
.fetch_from(&sandbox_network)
.await?
.total;

// Bob makes a higher bid
let bob_bid = bob
.call(contract.id(), "bid")
// Now, Bob makes a higher bid
contract
.call_function("bid", ())
.transaction()
.deposit(NearToken::from_near(2))
.transact()
.await?;

assert!(bob_bid.is_success());
.with_signer(bob.account_id().clone(), signer.clone())
.send_to(&sandbox_network)
.await?
.assert_success();

let highest_bid_json = contract.view("get_highest_bid").await?;
let highest_bid: Bid = highest_bid_json.json::<Bid>()?;
// Now, the highest bid is the Bob's bid
let highest_bid: Bid = contract
.call_function("get_highest_bid", ())
.read_only()
.fetch_from(&sandbox_network)
.await?
.data;
assert_eq!(highest_bid.bid, NearToken::from_near(2));
assert_eq!(highest_bid.bidder, *bob.id());
assert_eq!(&highest_bid.bidder, bob.account_id());

// Check that Alice was returned her bid
let new_alice_balance = alice.view_account().await?.balance;
// Check that Alice was refunded her bid
let new_alice_balance = alice
.tokens()
.near_balance()
.fetch_from(&sandbox_network)
.await?
.total;
assert!(new_alice_balance == alice_balance.saturating_add(NearToken::from_near(1)));

// Alice tries to make a bid with less NEAR than the previous
let alice_bid = alice
.call(contract.id(), "bid")
contract
.call_function("bid", ())
.transaction()
.deposit(NearToken::from_near(1))
.transact()
.await?;

assert!(alice_bid.is_failure());
.with_signer(alice.account_id().clone(), signer.clone())
.send_to(&sandbox_network)
.await?
.assert_failure();

// Auctioneer claims auction but did not finish
let auctioneer_claim = auctioneer
.call(contract_account.id(), "claim")
.args_json(json!({}))
.gas(Gas::from_tgas(300))
.transact()
.await?;

assert!(auctioneer_claim.is_failure());
contract
.call_function("claim", ())
.transaction()
.gas(NearGas::from_tgas(30))
.with_signer(auctioneer.account_id().clone(), signer.clone())
.send_to(&sandbox_network)
.await?
.assert_failure();

// Fast forward 200 blocks
let blocks_to_advance = 200;
sandbox.fast_forward(blocks_to_advance).await?;

// Auctioneer claims the auction
let auctioneer_claim = auctioneer
.call(contract_account.id(), "claim")
.args_json(json!({}))
.gas(Gas::from_tgas(300))
.transact()
.await?;

assert!(auctioneer_claim.is_success());
contract
.call_function("claim", ())
.transaction()
.gas(NearGas::from_tgas(30))
.with_signer(auctioneer.account_id().clone(), signer.clone())
.send_to(&sandbox_network)
.await?
.assert_success();

// Checks the auctioneer has the correct balance
let auctioneer_balance = auctioneer.view_account().await?.balance;
let auctioneer_balance = auctioneer
.tokens()
.near_balance()
.fetch_from(&sandbox_network)
.await?
.total;
assert!(auctioneer_balance <= NearToken::from_near(12));
assert!(auctioneer_balance > NearToken::from_millinear(11990));

// Auctioneer tries to claim the auction again
let auctioneer_claim = auctioneer
.call(contract_account.id(), "claim")
.args_json(json!({}))
.gas(Gas::from_tgas(300))
.transact()
.await?;

assert!(auctioneer_claim.is_failure());
contract
.call_function("claim", ())
.transaction()
.gas(NearGas::from_tgas(30))
.with_signer(auctioneer.account_id().clone(), signer.clone())
.send_to(&sandbox_network)
.await?
.assert_failure();

// Alice tries to make a bid when the auction is over
let alice_bid = alice
.call(contract.id(), "bid")
.deposit(NearToken::from_near(3))
.transact()
.await?;

assert!(alice_bid.is_failure());
contract
.call_function("bid", ())
.transaction()
.deposit(NearToken::from_near(1))
.with_signer(alice.account_id().clone(), signer.clone())
.send_to(&sandbox_network)
.await?
.assert_failure();

Ok(())
}

async fn create_subaccount(
root: &near_workspaces::Account,
sandbox: &near_sandbox::Sandbox,
name: &str,
) -> Result<near_workspaces::Account, Box<dyn std::error::Error>> {
let subaccount = root
.create_subaccount(name)
.initial_balance(TEN_NEAR)
.transact()
.await?
.unwrap();

Ok(subaccount)
) -> testresult::TestResult<near_api::Account> {
let account_id: AccountId = name.parse().unwrap();
sandbox
.create_account(account_id.clone())
.initial_balance(NearToken::from_near(10))
.send()
.await?;
Ok(near_api::Account(account_id))
}
14 changes: 10 additions & 4 deletions contract-rs/02-winner-gets-nft/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,20 @@ crate-type = ["cdylib", "rlib"]

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
near-sdk = "5.23.0"
near-sdk = "5.24.0"

[dev-dependencies]
near-sdk = { version = "5.23.0", features = ["unit-testing"] }
near-workspaces = { version = "0.22.0", features = ["unstable"] }
near-sdk = { version = "5.24.0", features = ["unit-testing"] }
near-sandbox = "0.3"
near-api = "0.8"
cargo-near-build = "0.10"
testresult = "0.4.1"
tokio = { version = "1.12.0", features = ["full"] }
serde_json = "1"
chrono = "0.4.38"
# This is temporary fix for the build error since those crates with a higher version require a higher version of Rust compiler (1.88.0)
cargo-platform = "=0.3.1"
darling = "=0.20.11"
bon = "=3.8.1"

[profile.release]
codegen-units = 1
Expand Down
Loading