1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
use async_trait::async_trait;
use bitcoincore_rpc::RpcApi;
use jsonrpc::Error as JsonRpcError;
use crate::btc;
#[derive(Debug, Copy, Clone, PartialEq)]
pub enum TransactionStatus {
Unknown,
Mempool,
Committed(u32),
}
impl TransactionStatus {
pub fn is_known(self) -> bool {
self != TransactionStatus::Unknown
}
pub fn confirmations(self) -> Option<u32> {
if let TransactionStatus::Committed(confirmations) = self {
Some(confirmations)
} else {
None
}
}
}
#[async_trait]
pub trait BitcoinRelay {
type Error;
async fn send_transaction(
&self,
transaction: &btc::Transaction,
) -> Result<btc::Sha256d, Self::Error>;
async fn transaction_status(&self, id: btc::Sha256d) -> Result<TransactionStatus, Self::Error>;
}
#[async_trait]
impl BitcoinRelay for bitcoincore_rpc::Client {
type Error = bitcoincore_rpc::Error;
async fn send_transaction(
&self,
transaction: &btc::Transaction,
) -> Result<btc::Sha256d, Self::Error> {
self.send_raw_transaction(transaction.to_string())
.map(|txid| btc::Sha256d(txid.into()))
}
async fn transaction_status(&self, id: btc::Sha256d) -> Result<TransactionStatus, Self::Error> {
match self.get_raw_transaction_verbose(&id.into(), None) {
Ok(info) => {
let status = match info.confirmations {
None => TransactionStatus::Mempool,
Some(num) => TransactionStatus::Committed(num),
};
Ok(status)
}
Err(bitcoincore_rpc::Error::JsonRpc(JsonRpcError::Rpc(_))) => {
Ok(TransactionStatus::Unknown)
}
Err(e) => Err(e),
}
}
}