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

Commit 21f97e3

Browse files
committed
withdrawal example
1 parent 4171fab commit 21f97e3

File tree

5 files changed

+272
-53
lines changed

5 files changed

+272
-53
lines changed

devenv/integration/bin/test

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,12 @@ ENTRYPOINT_PATH="./integration/docker/entrypoint"
55
CONFIG_PATH="./sbtc/docker/config.json"
66

77
project_name() {
8-
local input="$1"
8+
local input="$@"
99
local filter="${input//[![:alnum:]]/_}"
1010
echo "$filter"
1111
}
1212

13-
filters=("test(deposit)" "test(withdrawal)")
13+
filters=("test(deposit) or test(withdrawal)")
1414
filter_union=""
1515
ids=()
1616
projects=()
Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
use std::{io::Cursor, time::Duration};
2+
3+
use bdk::{
4+
bitcoin::{psbt::serialize::Serialize, PrivateKey},
5+
blockchain::{
6+
ConfigurableBlockchain, ElectrumBlockchain, ElectrumBlockchainConfig,
7+
},
8+
database::MemoryDatabase,
9+
template::P2Wpkh,
10+
SyncOptions, Wallet,
11+
};
12+
use blockstack_lib::{
13+
codec::StacksMessageCodec,
14+
util::hash::hex_bytes,
15+
vm::{
16+
types::{QualifiedContractIdentifier, StandardPrincipalData},
17+
Value,
18+
},
19+
};
20+
use romeo::{config::Config, stacks_client::StacksClient};
21+
use sbtc_cli::commands::{
22+
broadcast::{broadcast_tx, BroadcastArgs},
23+
deposit::{build_deposit_tx, DepositArgs},
24+
withdraw::{build_withdrawal_tx, WithdrawalArgs},
25+
};
26+
use stacks_core::address::StacksAddress;
27+
use tokio::time::sleep;
28+
use url::Url;
29+
30+
/// Wait until all your services are ready before running.
31+
/// Don't forget to fund W0 (deployer) and W1 (recipient).
32+
#[tokio::main]
33+
async fn main() {
34+
let mut config =
35+
Config::from_path("./devenv/sbtc/docker/config.json").unwrap();
36+
config.stacks_node_url = "http://localhost:3999".parse().unwrap();
37+
config.bitcoin_node_url = "http://localhost:18443".parse().unwrap();
38+
config.electrum_node_url = "tcp://localhost:60401".parse().unwrap();
39+
40+
let blockchain =
41+
ElectrumBlockchain::from_config(&ElectrumBlockchainConfig {
42+
url: config.electrum_node_url.clone().into(),
43+
socks5: None,
44+
retry: 3,
45+
timeout: Some(10),
46+
stop_gap: 10,
47+
validate_domain: false,
48+
})
49+
.unwrap();
50+
51+
let recipient_p2wpkh_wif =
52+
"cNcXK2r8bNdWJQymtAW8tGS7QHNtFFvG5CdXqhhT752u29WspXRM";
53+
54+
// W1
55+
let wallet = {
56+
let private_key = PrivateKey::from_wif(recipient_p2wpkh_wif).unwrap();
57+
58+
Wallet::new(
59+
P2Wpkh(private_key),
60+
Some(P2Wpkh(private_key)),
61+
bdk::bitcoin::Network::Regtest,
62+
MemoryDatabase::default(),
63+
)
64+
.unwrap()
65+
};
66+
67+
loop {
68+
wallet.sync(&blockchain, SyncOptions::default()).unwrap();
69+
let balance = wallet.get_balance().unwrap().confirmed;
70+
println!("recipient's btc: {balance}");
71+
if balance != 0 {
72+
break;
73+
}
74+
sleep(Duration::from_secs(1)).await;
75+
}
76+
77+
let recipient = "ST2ST2H80NP5C9SPR4ENJ1Z9CDM9PKAJVPYWPQZ50";
78+
let amount = 1000;
79+
80+
// deposit
81+
{
82+
let electrum_url =
83+
Url::parse(config.electrum_node_url.as_str()).unwrap();
84+
let tx = {
85+
let args = DepositArgs {
86+
node_url: electrum_url.clone(),
87+
wif: recipient_p2wpkh_wif.into(),
88+
network: bdk::bitcoin::Network::Regtest,
89+
recipient:recipient.into(),
90+
amount,
91+
sbtc_wallet: "bcrt1pte5zmd7qzj4hdu45lh9mmdm0nwq3z35pwnxmzkwld6y0a8g83nnqhj6vc0".into(),
92+
};
93+
94+
build_deposit_tx(&args).unwrap()
95+
};
96+
97+
broadcast_tx(&BroadcastArgs {
98+
node_url: electrum_url,
99+
tx: hex::encode(tx.serialize()),
100+
})
101+
.unwrap();
102+
}
103+
104+
let deployer = "ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM";
105+
let deployer_address = StacksAddress::transmute_stacks_address(deployer);
106+
let recipient_address = StacksAddress::transmute_stacks_address(recipient);
107+
108+
let stacks_client =
109+
StacksClient::new(config.clone(), reqwest::Client::new());
110+
111+
println!("Waiting on sBTC mint");
112+
// request token balance from the asset contract.
113+
while {
114+
let res: serde_json::Value = stacks_client
115+
.call_read_only_fn(
116+
QualifiedContractIdentifier::new(
117+
StandardPrincipalData::from(deployer_address),
118+
config.contract_name.clone(),
119+
),
120+
"get-balance",
121+
recipient_address.to_string().as_str(),
122+
vec![StandardPrincipalData::from(recipient_address).into()],
123+
)
124+
.await
125+
.unwrap();
126+
127+
assert!(res["okay"].as_bool().unwrap());
128+
let bytes =
129+
hex_bytes(res["result"].as_str().unwrap().trim_start_matches("0x"))
130+
.unwrap();
131+
132+
let mut cursor = Cursor::new(&bytes);
133+
Value::consensus_deserialize(&mut cursor)
134+
.unwrap()
135+
.expect_result_ok()
136+
.expect_u128()
137+
} < amount as u128
138+
{
139+
sleep(Duration::from_secs(2)).await;
140+
}
141+
142+
let fee = 2000;
143+
// withdraw
144+
let args = WithdrawalArgs {
145+
node_url: config.electrum_node_url.clone(),
146+
network: bdk::bitcoin::Network::Regtest,
147+
// p2wpkh
148+
wif: "cNcXK2r8bNdWJQymtAW8tGS7QHNtFFvG5CdXqhhT752u29WspXRM".into(),
149+
// Stacks
150+
drawee_wif: "cR9hENRFiuHzKpj9B3QCTBrt19c5ZCJKHJwYcqj5dfB6aKyf6ndm"
151+
.into(),
152+
payee_address: "bcrt1q3zl64vadtuh3vnsuhdgv6pm93n82ye8q6cr4ch".into(),
153+
amount,
154+
fulfillment_fee: fee,
155+
sbtc_wallet:
156+
"bcrt1pte5zmd7qzj4hdu45lh9mmdm0nwq3z35pwnxmzkwld6y0a8g83nnqhj6vc0"
157+
.into(),
158+
};
159+
160+
let tx = build_withdrawal_tx(&args).unwrap();
161+
162+
wallet.sync(&blockchain, SyncOptions::default()).unwrap();
163+
let balance = wallet.get_balance().unwrap().confirmed;
164+
165+
broadcast_tx(&BroadcastArgs {
166+
node_url: config.electrum_node_url.clone(),
167+
tx: hex::encode(tx.serialize()),
168+
})
169+
.unwrap();
170+
171+
println!("Waiting on fulfillment");
172+
loop {
173+
wallet.sync(&blockchain, SyncOptions::default()).unwrap();
174+
let current = wallet.get_balance().unwrap().confirmed;
175+
// will fail if tx_fees is not an upper bound for real fees.
176+
let tx_fees = 400;
177+
if balance - fee - tx_fees < current {
178+
break;
179+
}
180+
sleep(Duration::from_secs(2)).await;
181+
}
182+
}

romeo/tests/tests/bitcoin_client.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use std::{io::Cursor, 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},
@@ -14,6 +14,7 @@ use blockstack_lib::{
1414
},
1515
};
1616
use romeo::stacks_client::StacksClient;
17+
use tokio::time::sleep;
1718
use url::Url;
1819

1920
/// devenv's service url
@@ -40,7 +41,7 @@ pub fn mine_blocks(
4041
.unwrap()
4142
}
4243

43-
pub fn wait_for_tx_confirmation(
44+
pub async fn wait_for_tx_confirmation(
4445
b_client: &BClient,
4546
txid: &Txid,
4647
confirmations: i32,
@@ -58,7 +59,7 @@ pub fn wait_for_tx_confirmation(
5859
}
5960
}
6061

61-
sleep(Duration::from_secs(1));
62+
sleep(Duration::from_secs(1)).await;
6263
}
6364
}
6465

romeo/tests/tests/deposit.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,12 @@ use super::{
2424
bitcoin_url, client_new, electrs_url, mine_blocks, sbtc_balance,
2525
wait_for_tx_confirmation,
2626
},
27-
KeyType::{self, *},
27+
KeyType::*,
2828
WALLETS,
2929
};
3030

3131
#[tokio::test]
32+
/// preceeds withdrawal
3233
async fn broadcast_deposit() -> Result<()> {
3334
let b_client = client_new(bitcoin_url().as_str(), "devnet", "devnet");
3435

@@ -82,8 +83,8 @@ async fn broadcast_deposit() -> Result<()> {
8283
}
8384

8485
let amount = 10_000;
85-
let deployer_stacks_address = WALLETS[0][KeyType::Stacks].address;
86-
let recipient_stacks_address = WALLETS[1][KeyType::Stacks].address;
86+
let deployer_stacks_address = WALLETS[0][Stacks].address;
87+
let recipient_stacks_address = WALLETS[1][Stacks].address;
8788

8889
let tx = {
8990
let args = DepositArgs {
@@ -131,7 +132,7 @@ async fn broadcast_deposit() -> Result<()> {
131132

132133
let txid = tx.txid();
133134

134-
wait_for_tx_confirmation(&b_client, &txid, 1);
135+
wait_for_tx_confirmation(&b_client, &txid, 1).await;
135136
}
136137

137138
// assert on new sbtc token balance

0 commit comments

Comments
 (0)