Skip to content
This repository was archived by the owner on Dec 4, 2024. It is now read-only.

Commit 6eabc2b

Browse files
committed
assert on balances
1 parent 4276756 commit 6eabc2b

File tree

11 files changed

+248
-68
lines changed

11 files changed

+248
-68
lines changed

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,4 @@ tracing = "0.1.37"
3535
tracing-subscriber = { version = "0.3.17", features = ["env-filter"] }
3636
url = "2.4.1"
3737
wsts = "1.2"
38+
blockstack-core = { git = "https://github.com/stacks-network/stacks-blockchain/", branch = "master" }

devenv/integration/bin/test

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
set -ueo >/dev/null
33

44
ENTRYPOINT_PATH="./integration/docker/entrypoint"
5+
CONFIG_PATH="./sbtc/docker/config.json"
56

67
project_name() {
78
local input="$1"
@@ -23,7 +24,7 @@ for filter in "${filters[@]}"; do
2324
./integration/bin/up docker-compose.yml $project
2425

2526
network=${project}_default
26-
id=$(docker run -td --network $network -v $ENTRYPOINT_PATH:/usr/local/bin/entrypoint -e PROJECT_NAME=$project testbed "$filter")
27+
id=$(docker run -td --network $network -v $ENTRYPOINT_PATH:/usr/local/bin/entrypoint -v $CONFIG_PATH:"/romeo/config.json" -e PROJECT_NAME=$project testbed "$filter")
2728
ids+=($id)
2829
echo with container id: $id
2930

romeo/Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ edition = "2021"
77
anyhow.workspace = true
88
backoff = { workspace = true, features = ["tokio"] }
99
bdk = { workspace = true, features = ["rpc", "esplora", "use-esplora-async"] }
10-
blockstack-core = { git = "https://github.com/stacks-network/stacks-blockchain/", branch = "master" }
10+
blockstack-core.workspace = true
1111
clap = { workspace = true, features = ["derive"] }
1212
derivative = { workspace = true }
1313
futures.workspace = true
@@ -27,3 +27,4 @@ rs_merkle.workspace = true
2727
[dev-dependencies]
2828
reqwest = { workspace = true, features = ["json", "blocking"] }
2929
sbtc-cli = { path = "../sbtc-cli" }
30+
stacks-core = { path = "../stacks-core", features = ["test-utils"] }

romeo/src/stacks_client.rs

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use blockstack_lib::{
1212
codec::StacksMessageCodec,
1313
core::CHAIN_ID_TESTNET,
1414
types::chainstate::StacksPrivateKey,
15+
util::hash::bytes_to_hex,
1516
vm::{
1617
types::{QualifiedContractIdentifier, StandardPrincipalData},
1718
ContractName,
@@ -21,7 +22,7 @@ use futures::Future;
2122
use rand::{distributions::Alphanumeric, thread_rng, Rng};
2223
use reqwest::{Request, RequestBuilder, Response, StatusCode};
2324
use serde::de::DeserializeOwned;
24-
use serde_json::Value;
25+
use serde_json::{json, Value};
2526
use stacks_core::{codec::Codec, uint::Uint256};
2627
use tokio::{
2728
sync::{Mutex, MutexGuard},
@@ -463,6 +464,46 @@ impl StacksClient {
463464
}
464465
}
465466

467+
impl StacksClient {
468+
/// Call read-only functions from smart contracts
469+
pub async fn call_read_only_fn<R>(
470+
&self,
471+
contract: QualifiedContractIdentifier,
472+
method: &str,
473+
sender: &str,
474+
args: Vec<blockstack_lib::vm::Value>,
475+
) -> anyhow::Result<R>
476+
where
477+
R: DeserializeOwned,
478+
{
479+
Ok(self
480+
.http_client
481+
.post(
482+
self.config
483+
.stacks_node_url
484+
.join(
485+
format!(
486+
"/v2/contracts/call-read/{}/{}/{}",
487+
contract.issuer, contract.name, method
488+
)
489+
.as_str(),
490+
)
491+
.unwrap(),
492+
)
493+
.json(&json!({
494+
"sender": sender,
495+
"arguments": args
496+
.iter()
497+
.map(|a| bytes_to_hex(&a.serialize_to_vec()))
498+
.collect::<Vec<_>>() }
499+
))
500+
.send()
501+
.await?
502+
.json()
503+
.await?)
504+
}
505+
}
506+
466507
#[derive(serde::Deserialize)]
467508
struct NonceInfo {
468509
possible_next_nonce: u64,

romeo/tests/tests/bitcoin_client.rs

Lines changed: 48 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,28 @@
1-
use std::{str::FromStr, thread::sleep, time::Duration};
1+
use std::{io::Cursor, str::FromStr, time::Duration};
22

33
use bdk::{
44
bitcoin::{hash_types::Txid, Address, BlockHash},
55
bitcoincore_rpc::{Auth, Client as BClient, RpcApi},
66
};
7+
use blockstack_lib::{
8+
codec::StacksMessageCodec,
9+
types::chainstate::StacksAddress,
10+
util::hash::hex_bytes,
11+
vm::{
12+
types::{QualifiedContractIdentifier, StandardPrincipalData},
13+
ContractName, Value,
14+
},
15+
};
16+
use romeo::stacks_client::StacksClient;
17+
use tokio::time::sleep;
718
use url::Url;
819

20+
/// devenv's service url
921
pub fn bitcoin_url() -> Url {
1022
Url::parse("http://bitcoin:18443").unwrap()
1123
}
1224

25+
/// devenv's service url
1326
pub fn electrs_url() -> Url {
1427
Url::parse("tcp://electrs:60401").unwrap()
1528
}
@@ -28,7 +41,7 @@ pub fn mine_blocks(
2841
.unwrap()
2942
}
3043

31-
pub fn wait_for_tx_confirmation(
44+
pub async fn wait_for_tx_confirmation(
3245
b_client: &BClient,
3346
txid: &Txid,
3447
confirmations: i32,
@@ -46,6 +59,38 @@ pub fn wait_for_tx_confirmation(
4659
}
4760
}
4861

49-
sleep(Duration::from_secs(1));
62+
sleep(Duration::from_secs(1)).await;
5063
}
5164
}
65+
66+
pub async fn sbtc_balance(
67+
stacks_client: &StacksClient,
68+
deployer_address: StacksAddress,
69+
recipient_address: StacksAddress,
70+
contract_name: ContractName,
71+
) -> u128 {
72+
let res: serde_json::Value = stacks_client
73+
.call_read_only_fn(
74+
QualifiedContractIdentifier::new(
75+
StandardPrincipalData::from(deployer_address),
76+
contract_name,
77+
),
78+
"get-balance",
79+
recipient_address.to_string().as_str(),
80+
vec![StandardPrincipalData::from(recipient_address).into()],
81+
)
82+
.await
83+
.unwrap();
84+
85+
assert!(res["okay"].as_bool().unwrap());
86+
// request token balance from the asset contract.
87+
let bytes =
88+
hex_bytes(res["result"].as_str().unwrap().trim_start_matches("0x"))
89+
.unwrap();
90+
91+
let mut cursor = Cursor::new(&bytes);
92+
Value::consensus_deserialize(&mut cursor)
93+
.unwrap()
94+
.expect_result_ok()
95+
.expect_u128()
96+
}

romeo/tests/tests/deposit.rs

Lines changed: 57 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use std::{str::FromStr, thread::sleep, time::Duration};
1+
use std::{str::FromStr, time::Duration};
22

33
use anyhow::Result;
44
use bdk::{
@@ -11,22 +11,26 @@ use bdk::{
1111
template::P2Wpkh,
1212
SyncOptions, Wallet,
1313
};
14+
use romeo::{config::Config, stacks_client::StacksClient};
1415
use sbtc_cli::commands::{
1516
broadcast::{broadcast_tx, BroadcastArgs},
1617
deposit::{build_deposit_tx, DepositArgs},
1718
};
19+
use stacks_core::address::StacksAddress;
20+
use tokio::time::sleep;
1821

1922
use super::{
2023
bitcoin_client::{
21-
bitcoin_url, client_new, electrs_url, mine_blocks,
24+
bitcoin_url, client_new, electrs_url, mine_blocks, sbtc_balance,
2225
wait_for_tx_confirmation,
2326
},
2427
KeyType::*,
2528
WALLETS,
2629
};
2730

28-
#[test]
29-
fn broadcast_deposit() -> Result<()> {
31+
#[tokio::test]
32+
/// preceeds withdrawal
33+
async fn broadcast_deposit() -> Result<()> {
3034
let b_client = client_new(bitcoin_url().as_str(), "devnet", "devnet");
3135

3236
b_client
@@ -46,8 +50,6 @@ fn broadcast_deposit() -> Result<()> {
4650

4751
let electrum_url = electrs_url();
4852

49-
// suboptimal, replace once we have better events.
50-
// replace with b_client balance?
5153
{
5254
let blockchain =
5355
ElectrumBlockchain::from_config(&ElectrumBlockchainConfig {
@@ -76,34 +78,74 @@ fn broadcast_deposit() -> Result<()> {
7678
if balance.confirmed != 0 {
7779
break;
7880
}
79-
sleep(Duration::from_millis(1_000));
81+
sleep(Duration::from_millis(1_000)).await;
8082
}
8183
}
8284

8385
let amount = 10_000;
86+
let deployer_stacks_address = WALLETS[0][Stacks].address;
87+
let recipient_stacks_address = WALLETS[1][Stacks].address;
8488

8589
let tx = {
8690
let args = DepositArgs {
8791
node_url: electrum_url.clone(),
8892
wif: WALLETS[1][P2wpkh].wif.into(),
8993
network: bdk::bitcoin::Network::Regtest,
90-
recipient: WALLETS[1][Stacks].address.into(),
94+
recipient: recipient_stacks_address.into(),
9195
amount,
9296
sbtc_wallet: WALLETS[0][P2tr].address.into(),
9397
};
9498

9599
build_deposit_tx(&args).unwrap()
96100
};
97101

98-
broadcast_tx(&BroadcastArgs {
99-
node_url: electrum_url,
100-
tx: hex::encode(tx.serialize()),
101-
})
102-
.unwrap();
102+
let config = Config::from_path("config.json").unwrap();
103103

104-
let txid = tx.txid();
104+
// make sure config urls match devenv.
105+
let stacks_client =
106+
StacksClient::new(config.clone(), reqwest::Client::new());
105107

106-
wait_for_tx_confirmation(&b_client, &txid, 1);
108+
let deployer_address =
109+
StacksAddress::transmute_stacks_address(deployer_stacks_address);
110+
let recipient_address =
111+
StacksAddress::transmute_stacks_address(recipient_stacks_address);
112+
113+
// prior balance
114+
assert_eq!(
115+
sbtc_balance(
116+
&stacks_client,
117+
deployer_address,
118+
recipient_address,
119+
config.contract_name.clone()
120+
)
121+
.await,
122+
0
123+
);
124+
125+
// Sign, send and wait for confirmation.
126+
{
127+
broadcast_tx(&BroadcastArgs {
128+
node_url: electrum_url,
129+
tx: hex::encode(tx.serialize()),
130+
})
131+
.unwrap();
132+
133+
let txid = tx.txid();
134+
135+
wait_for_tx_confirmation(&b_client, &txid, 1).await;
136+
}
137+
138+
// assert on new sbtc token balance
139+
while sbtc_balance(
140+
&stacks_client,
141+
deployer_address,
142+
recipient_address,
143+
config.contract_name.clone(),
144+
)
145+
.await != amount as u128
146+
{
147+
sleep(Duration::from_secs(2)).await
148+
}
107149

108150
Ok(())
109151
}

0 commit comments

Comments
 (0)