Skip to content

Commit 4e9f621

Browse files
committed
migrate factory from using workspaces to sandbox
1 parent ebfa785 commit 4e9f621

2 files changed

Lines changed: 191 additions & 128 deletions

File tree

factory/Cargo.toml

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,20 @@ crate-type = ["cdylib", "rlib"]
1313

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

1818
[dev-dependencies]
19-
near-sdk = { version = "5.23.0", features = ["unit-testing"] }
20-
near-workspaces = { version = "0.22.0", features = ["unstable"] }
19+
near-sdk = { version = "5.24.0", features = ["unit-testing"] }
20+
near-sandbox = "0.3"
21+
near-api = "0.8"
22+
cargo-near-build = "0.10"
2123
tokio = { version = "1.12.0", features = ["full"] }
2224
serde_json = "1"
23-
chrono = "0.4.38"
25+
testresult = "0.4.1"
26+
# 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)
27+
cargo-platform = "=0.3.1"
28+
darling = "=0.20.11"
29+
bon = "=3.8.1"
2430

2531
[profile.release]
2632
codegen-units = 1

factory/tests/tests_basics.rs

Lines changed: 181 additions & 124 deletions
Original file line numberDiff line numberDiff line change
@@ -1,189 +1,246 @@
1-
use chrono::Utc;
2-
use near_sdk::{json_types::U128, NearToken};
3-
use near_sdk::{near, AccountId, Gas};
4-
use near_workspaces::result::ExecutionFinalResult;
5-
use near_workspaces::{Account, Contract};
6-
use serde_json::json;
7-
8-
const TEN_NEAR: NearToken = NearToken::from_near(10);
1+
use near_api::{AccountId, NearGas, NearToken};
2+
use near_sdk::json_types::U128;
3+
use near_sdk::serde_json::json;
4+
95
const FT_WASM_FILEPATH: &str = "./tests/fungible_token.wasm";
106

11-
#[near(serializers = [json])]
7+
#[derive(near_sdk::serde::Deserialize)]
8+
#[serde(crate = "near_sdk::serde")]
129
pub struct Bid {
1310
pub bidder: AccountId,
1411
pub bid: U128,
1512
}
1613

1714
#[tokio::test]
1815

19-
async fn test_contract_is_operational() -> Result<(), Box<dyn std::error::Error>> {
20-
let sandbox = near_workspaces::sandbox().await?;
21-
22-
let root: near_workspaces::Account = sandbox.root_account()?;
23-
24-
// Create accounts
25-
let alice = create_subaccount(&root, "alice").await?;
26-
let auctioneer = create_subaccount(&root, "auctioneer").await?;
27-
let contract_account = create_subaccount(&root, "contract").await?;
28-
let nft_account = create_subaccount(&root, "nft").await?;
16+
async fn test_contract_is_operational() -> testresult::TestResult<()> {
17+
// Build the contract wasm file
18+
let contract_wasm_path = cargo_near_build::build_with_cli(Default::default())?;
19+
let contract_wasm = std::fs::read(contract_wasm_path)?;
2920

21+
// Read the FT wasm file
3022
let ft_wasm = std::fs::read(FT_WASM_FILEPATH)?;
31-
let ft_contract = sandbox.dev_deploy(&ft_wasm).await?;
32-
33-
// Initialize FT contract
34-
let res = ft_contract
35-
.call("new_default_meta")
36-
.args_json(serde_json::json!({
37-
"owner_id": root.id(),
38-
"total_supply": U128(1_000_000),
39-
}))
40-
.transact()
41-
.await?;
4223

43-
assert!(res.is_success());
24+
// Initialize the sandbox
25+
let sandbox = near_sandbox::Sandbox::start_sandbox().await?;
26+
let sandbox_network =
27+
near_api::NetworkConfig::from_rpc_url("sandbox", sandbox.rpc_addr.parse()?);
28+
29+
// Create accounts
30+
let alice = create_subaccount(&sandbox, "alice.sandbox").await?;
31+
let auctioneer = create_subaccount(&sandbox, "auctioneer.sandbox").await?;
32+
let nft_contract = create_subaccount(&sandbox, "nft-contract.sandbox")
33+
.await?
34+
.as_contract();
35+
let ft_contract = create_subaccount(&sandbox, "ft-contract.sandbox")
36+
.await?
37+
.as_contract();
38+
let contract = create_subaccount(&sandbox, "contract.sandbox")
39+
.await?
40+
.as_contract();
41+
42+
// Initialize signer for the contract deployment
43+
let signer = near_api::Signer::from_secret_key(
44+
near_sandbox::config::DEFAULT_GENESIS_ACCOUNT_PRIVATE_KEY
45+
.parse()
46+
.unwrap(),
47+
)?;
48+
49+
// Deploy the FT contract
50+
near_api::Contract::deploy(ft_contract.account_id().clone())
51+
.use_code(ft_wasm)
52+
.with_init_call(
53+
"new_default_meta",
54+
json!({"owner_id": ft_contract.account_id(), "total_supply": U128(1_000_000)}),
55+
)?
56+
.with_signer(signer.clone())
57+
.send_to(&sandbox_network)
58+
.await?
59+
.assert_success();
4460

4561
// Skip creating NFT contract as we are are only going to test making a bid to the auction
4662

4763
// Deploy factory contract
48-
let contract_wasm = near_workspaces::compile_project("./").await?;
49-
let contract = contract_account.deploy(&contract_wasm).await?.unwrap();
64+
near_api::Contract::deploy(contract.account_id().clone())
65+
.use_code(contract_wasm)
66+
.without_init_call()
67+
.with_signer(signer.clone())
68+
.send_to(&sandbox_network)
69+
.await?
70+
.assert_success();
5071

5172
// Create auction by calling factory contract
52-
let now = Utc::now().timestamp();
73+
let now = std::time::SystemTime::now()
74+
.duration_since(std::time::SystemTime::UNIX_EPOCH)?
75+
.as_secs();
5376
let a_minute_from_now = (now + 60) * 1000000000;
5477
let starting_price = U128(10_000);
5578

56-
let deploy_new_auction: ExecutionFinalResult = alice
57-
.call(contract.id(), "deploy_new_auction")
58-
.args_json(
59-
json!({"name": "new-auction", "end_time": a_minute_from_now.to_string(),"auctioneer": auctioneer.id(),"ft_contract": ft_contract.id(),"nft_contract": nft_account.id(),"token_id":"1", "starting_price":starting_price }),
60-
)
61-
.max_gas()
79+
contract
80+
.call_function("deploy_new_auction", json!({"name": "new-auction", "end_time": a_minute_from_now.to_string(),"auctioneer": auctioneer.account_id(),"ft_contract": ft_contract.account_id(),"nft_contract": nft_contract.account_id(),"token_id":"1", "starting_price":starting_price }),)
81+
.transaction()
6282
.deposit(NearToken::from_millinear(1600))
63-
.transact()
64-
.await?;
65-
66-
assert!(deploy_new_auction.is_success());
83+
.with_signer(alice.account_id().clone(), signer.clone())
84+
.send_to(&sandbox_network)
85+
.await?
86+
.assert_success();
6787

68-
let auction_account_id: AccountId = format!("new-auction.{}", contract.id()).parse().unwrap();
88+
let auction_account_id: AccountId = format!("new-auction.{}", contract.account_id())
89+
.parse()
90+
.unwrap();
91+
sandbox
92+
.import_account(
93+
sandbox.rpc_addr.to_string(),
94+
format!("new-auction.{}", contract.account_id())
95+
.parse()
96+
.unwrap(),
97+
)
98+
.send()
99+
.await?;
100+
let auction_account = near_api::Account(auction_account_id.clone()).as_contract();
69101

70102
// Register accounts
71-
for account_id in [alice.id().clone(), auction_account_id.clone()].iter() {
72-
let register = ft_contract
73-
.call("storage_deposit")
74-
.args_json(serde_json::json!({ "account_id": account_id }))
103+
for account_id in [alice.account_id().clone(), auction_account_id.clone()].iter() {
104+
ft_contract
105+
.call_function(
106+
"storage_deposit",
107+
serde_json::json!({ "account_id": account_id }),
108+
)
109+
.transaction()
75110
.deposit(NearToken::from_yoctonear(8000000000000000000000))
76-
.transact()
77-
.await?;
78-
79-
assert!(register.is_success());
111+
.with_signer(alice.account_id().clone(), signer.clone())
112+
.send_to(&sandbox_network)
113+
.await?
114+
.assert_success();
80115
}
81116

82-
// Transfer FTs
117+
// Transfer FTs to Alice and Bob to top up their balances
83118
let transfer_amount = U128(150_000);
84119

85-
let root_transfer_alice =
86-
ft_transfer(&root, alice.clone(), ft_contract.clone(), transfer_amount).await?;
87-
assert!(root_transfer_alice.is_success());
120+
ft_transfer(
121+
&ft_contract,
122+
&ft_contract.account_id(),
123+
alice.account_id(),
124+
transfer_amount,
125+
&signer,
126+
&sandbox_network,
127+
)
128+
.await?;
88129

89130
// Alice makes a bid
90-
let alice_bid = ft_transfer_call(
91-
alice.clone(),
92-
ft_contract.id(),
131+
ft_transfer_call(
132+
&ft_contract,
133+
&alice,
93134
&auction_account_id,
94135
U128(50_000),
136+
&signer,
137+
&sandbox_network,
95138
)
96139
.await?;
97140

98-
assert!(alice_bid.is_success());
99-
100-
let highest_bid_alice: Bid = alice
101-
.view(&auction_account_id, "get_highest_bid")
102-
.args_json({})
141+
let highest_bid: Bid = auction_account
142+
.call_function("get_highest_bid", ())
143+
.read_only()
144+
.fetch_from(&sandbox_network)
103145
.await?
104-
.json()?;
105-
assert_eq!(highest_bid_alice.bid, U128(50_000));
106-
assert_eq!(highest_bid_alice.bidder, *alice.id());
146+
.data;
147+
assert_eq!(highest_bid.bid, U128(50_000));
148+
assert_eq!(&highest_bid.bidder, alice.account_id());
149+
150+
// Contract balance has increased
151+
let auction_contract_balance: U128 =
152+
ft_balance_of(&ft_contract, auction_account.account_id(), &sandbox_network).await?;
153+
assert_eq!(auction_contract_balance, U128(50_000));
107154

108-
let contract_account_balance: U128 = ft_balance_of(&ft_contract, &auction_account_id).await?;
109-
assert_eq!(contract_account_balance, U128(50_000));
110-
let alice_balance_after_bid: U128 = ft_balance_of(&ft_contract, alice.id()).await?;
111-
assert_eq!(alice_balance_after_bid, U128(100_000));
155+
// Alice balance has decreased
156+
let alice_balance: U128 =
157+
ft_balance_of(&ft_contract, alice.account_id(), &sandbox_network).await?;
158+
assert_eq!(alice_balance, U128(100_000));
112159

113160
// Try to launch a new auction with insufficient deposit
114-
let deploy_new_auction: ExecutionFinalResult = alice
115-
.call(contract.id(), "deploy_new_auction")
116-
.args_json(
117-
json!({"name": "new-auction", "end_time": a_minute_from_now.to_string(),"auctioneer": auctioneer.id(),"ft_contract": ft_contract.id(),"nft_contract": nft_account.id(),"token_id":"1", "starting_price":starting_price }),
118-
)
119-
.max_gas()
161+
contract
162+
.call_function("deploy_new_auction", json!({"name": "new-auction", "end_time": a_minute_from_now.to_string(),"auctioneer": auctioneer.account_id(),"ft_contract": ft_contract.account_id(),"nft_contract": nft_contract.account_id(),"token_id":"1", "starting_price":starting_price }),)
163+
.transaction()
120164
.deposit(NearToken::from_millinear(1400))
121-
.transact()
122-
.await?;
123-
124-
assert!(deploy_new_auction.is_failure());
165+
.with_signer(alice.account_id().clone(), signer.clone())
166+
.send_to(&sandbox_network)
167+
.await?
168+
.assert_failure();
125169

126170
Ok(())
127171
}
128172

129173
async fn create_subaccount(
130-
root: &near_workspaces::Account,
174+
sandbox: &near_sandbox::Sandbox,
131175
name: &str,
132-
) -> Result<near_workspaces::Account, Box<dyn std::error::Error>> {
133-
let subaccount = root
134-
.create_subaccount(name)
135-
.initial_balance(TEN_NEAR)
136-
.transact()
137-
.await?
138-
.unwrap();
139-
140-
Ok(subaccount)
176+
) -> testresult::TestResult<near_api::Account> {
177+
let account_id: AccountId = name.parse().unwrap();
178+
sandbox
179+
.create_account(account_id.clone())
180+
.initial_balance(NearToken::from_near(10))
181+
.send()
182+
.await?;
183+
Ok(near_api::Account(account_id))
141184
}
142185

143186
async fn ft_transfer(
144-
root: &near_workspaces::Account,
145-
account: Account,
146-
ft_contract: Contract,
147-
transfer_amount: U128,
148-
) -> Result<ExecutionFinalResult, Box<dyn std::error::Error>> {
149-
let transfer = root
150-
.call(ft_contract.id(), "ft_transfer")
151-
.args_json(serde_json::json!({
152-
"receiver_id": account.id(),
153-
"amount": transfer_amount
154-
}))
187+
ft_contract: &near_api::Contract,
188+
from: &AccountId,
189+
to: &AccountId,
190+
amount: U128,
191+
signer: &std::sync::Arc<near_api::Signer>,
192+
network: &near_api::NetworkConfig,
193+
) -> testresult::TestResult<()> {
194+
ft_contract
195+
.call_function(
196+
"ft_transfer",
197+
serde_json::json!({"receiver_id": to, "amount": amount}),
198+
)
199+
.transaction()
155200
.deposit(NearToken::from_yoctonear(1))
156-
.transact()
157-
.await?;
158-
Ok(transfer)
201+
.with_signer(from.clone(), signer.clone())
202+
.send_to(network)
203+
.await?
204+
.assert_success();
205+
Ok(())
159206
}
160207

161208
async fn ft_balance_of(
162-
ft_contract: &Contract,
209+
ft_contract: &near_api::Contract,
163210
account_id: &AccountId,
164-
) -> Result<U128, Box<dyn std::error::Error>> {
165-
let result = ft_contract
166-
.view("ft_balance_of")
167-
.args_json(json!({"account_id": account_id}))
211+
network: &near_api::NetworkConfig,
212+
) -> testresult::TestResult<U128> {
213+
let result: U128 = ft_contract
214+
.call_function(
215+
"ft_balance_of",
216+
serde_json::json!({"account_id": account_id}),
217+
)
218+
.read_only()
219+
.fetch_from(network)
168220
.await?
169-
.json()?;
170-
221+
.data;
171222
Ok(result)
172223
}
173224

174225
async fn ft_transfer_call(
175-
account: Account,
176-
ft_contract_id: &AccountId,
226+
ft_contract: &near_api::Contract,
227+
account: &near_api::Account,
177228
receiver_id: &AccountId,
178229
amount: U128,
179-
) -> Result<ExecutionFinalResult, Box<dyn std::error::Error>> {
180-
let transfer = account
181-
.call(ft_contract_id, "ft_transfer_call")
182-
.args_json(serde_json::json!({
183-
"receiver_id": receiver_id, "amount":amount, "msg": "0" }))
230+
signer: &std::sync::Arc<near_api::Signer>,
231+
network: &near_api::NetworkConfig,
232+
) -> testresult::TestResult<()> {
233+
let _ = ft_contract
234+
.call_function(
235+
"ft_transfer_call",
236+
serde_json::json!({"receiver_id": receiver_id, "amount": amount, "msg": "0"}),
237+
)
238+
.transaction()
184239
.deposit(NearToken::from_yoctonear(1))
185-
.gas(Gas::from_tgas(300))
186-
.transact()
187-
.await?;
188-
Ok(transfer)
240+
.gas(NearGas::from_tgas(300))
241+
.with_signer(account.account_id().clone(), signer.clone())
242+
.send_to(network)
243+
.await?
244+
.assert_success();
245+
Ok(())
189246
}

0 commit comments

Comments
 (0)