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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
use exonum::{
api::{self, ServiceApiBuilder, ServiceApiState},
blockchain::{self, BlockProof, TransactionMessage},
crypto::{Hash, PublicKey},
explorer::BlockchainExplorer,
helpers::Height,
storage::{ListProof, MapProof},
};
use crate::{wallet::Wallet, Schema, CRYPTOCURRENCY_SERVICE_ID};
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq)]
pub struct WalletQuery {
pub pub_key: PublicKey,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct WalletProof {
pub to_table: MapProof<Hash, Hash>,
pub to_wallet: MapProof<PublicKey, Wallet>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct WalletHistory {
pub proof: ListProof<Hash>,
pub transactions: Vec<TransactionMessage>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct WalletInfo {
pub block_proof: BlockProof,
pub wallet_proof: WalletProof,
pub wallet_history: Option<WalletHistory>,
}
#[derive(Debug, Clone, Copy)]
pub struct PublicApi;
impl PublicApi {
pub fn wallet_info(state: &ServiceApiState, query: WalletQuery) -> api::Result<WalletInfo> {
let snapshot = state.snapshot();
let general_schema = blockchain::Schema::new(&snapshot);
let currency_schema = Schema::new(&snapshot);
let max_height = general_schema.block_hashes_by_height().len() - 1;
let block_proof = general_schema
.block_and_precommits(Height(max_height))
.unwrap();
let to_table: MapProof<Hash, Hash> =
general_schema.get_proof_to_service_table(CRYPTOCURRENCY_SERVICE_ID, 0);
let to_wallet: MapProof<PublicKey, Wallet> =
currency_schema.wallets().get_proof(query.pub_key);
let wallet_proof = WalletProof {
to_table,
to_wallet,
};
let wallet = currency_schema.wallet(&query.pub_key);
let explorer = BlockchainExplorer::new(state.blockchain());
let wallet_history = wallet.map(|_| {
let history = currency_schema.wallet_history(&query.pub_key);
let proof = history.get_range_proof(0, history.len());
let transactions = history
.iter()
.map(|record| explorer.transaction_without_proof(&record).unwrap())
.collect::<Vec<_>>();
WalletHistory {
proof,
transactions,
}
});
Ok(WalletInfo {
block_proof,
wallet_proof,
wallet_history,
})
}
pub fn wire(builder: &mut ServiceApiBuilder) {
builder
.public_scope()
.endpoint("v1/wallets/info", Self::wallet_info);
}
}