Skip to content

Commit 917b76e

Browse files
A0-1613 Improving Connections (#834)
1 parent 7eda2ba commit 917b76e

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+547
-619
lines changed

aleph-client/Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

aleph-client/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[package]
22
name = "aleph_client"
33
# TODO bump major version when API stablize
4-
version = "2.5.0"
4+
version = "2.6.0"
55
edition = "2021"
66
license = "Apache 2.0"
77

aleph-client/src/connections.rs

Lines changed: 167 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -12,21 +12,72 @@ use subxt::{
1212
SubstrateConfig,
1313
};
1414

15-
use crate::{api, sp_weights::weight_v2::Weight, BlockHash, Call, Client, KeyPair, TxStatus};
15+
use crate::{
16+
api, sp_weights::weight_v2::Weight, AccountId, BlockHash, Call, KeyPair, SubxtClient, TxStatus,
17+
};
1618

1719
#[derive(Clone)]
1820
pub struct Connection {
19-
pub client: Client,
21+
client: SubxtClient,
2022
}
2123

2224
pub struct SignedConnection {
23-
pub connection: Connection,
24-
pub signer: KeyPair,
25+
connection: Connection,
26+
signer: KeyPair,
2527
}
2628

29+
#[derive(Clone)]
2730
pub struct RootConnection {
28-
pub connection: Connection,
29-
pub root: KeyPair,
31+
connection: SignedConnection,
32+
}
33+
34+
pub(crate) trait AsConnection {
35+
fn as_connection(&self) -> &Connection;
36+
}
37+
38+
pub(crate) trait AsSigned {
39+
fn as_signed(&self) -> &SignedConnection;
40+
}
41+
42+
#[async_trait::async_trait]
43+
pub trait ConnectionApi: Sync {
44+
async fn get_storage_entry<T: DecodeWithMetadata + Sync, Defaultable: Sync, Iterable: Sync>(
45+
&self,
46+
addrs: &StaticStorageAddress<T, Yes, Defaultable, Iterable>,
47+
at: Option<BlockHash>,
48+
) -> T::Target;
49+
50+
async fn get_storage_entry_maybe<
51+
T: DecodeWithMetadata + Sync,
52+
Defaultable: Sync,
53+
Iterable: Sync,
54+
>(
55+
&self,
56+
addrs: &StaticStorageAddress<T, Yes, Defaultable, Iterable>,
57+
at: Option<BlockHash>,
58+
) -> Option<T::Target>;
59+
60+
async fn rpc_call<R: Decode>(&self, func_name: String, params: RpcParams) -> anyhow::Result<R>;
61+
}
62+
63+
#[async_trait::async_trait]
64+
pub trait SignedConnectionApi: ConnectionApi {
65+
async fn send_tx<Call: TxPayload + Send + Sync>(
66+
&self,
67+
tx: Call,
68+
status: TxStatus,
69+
) -> anyhow::Result<BlockHash>;
70+
71+
async fn send_tx_with_params<Call: TxPayload + Send + Sync>(
72+
&self,
73+
tx: Call,
74+
params: BaseExtrinsicParamsBuilder<SubstrateConfig, PlainTip>,
75+
status: TxStatus,
76+
) -> anyhow::Result<BlockHash>;
77+
78+
fn account_id(&self) -> &AccountId;
79+
fn signer(&self) -> &KeyPair;
80+
async fn try_as_root(&self) -> anyhow::Result<RootConnection>;
3081
}
3182

3283
#[async_trait::async_trait]
@@ -58,29 +109,42 @@ impl SudoCall for RootConnection {
58109
}
59110
}
60111

61-
impl Connection {
62-
const DEFAULT_RETRIES: u32 = 10;
63-
const RETRY_WAIT_SECS: u64 = 1;
112+
impl Clone for SignedConnection {
113+
fn clone(&self) -> Self {
114+
SignedConnection {
115+
connection: self.connection.clone(),
116+
signer: KeyPair::new(self.signer.signer().clone()),
117+
}
118+
}
119+
}
64120

65-
pub async fn new(address: String) -> Self {
66-
Self::new_with_retries(address, Self::DEFAULT_RETRIES).await
121+
impl AsConnection for Connection {
122+
fn as_connection(&self) -> &Connection {
123+
self
67124
}
125+
}
68126

69-
pub async fn new_with_retries(address: String, mut retries: u32) -> Self {
70-
loop {
71-
let client = Client::from_url(&address).await;
72-
match (retries, client) {
73-
(_, Ok(client)) => return Self { client },
74-
(0, Err(e)) => panic!("{:?}", e),
75-
_ => {
76-
sleep(Duration::from_secs(Self::RETRY_WAIT_SECS));
77-
retries -= 1;
78-
}
79-
}
80-
}
127+
impl<S: AsSigned> AsConnection for S {
128+
fn as_connection(&self) -> &Connection {
129+
&self.as_signed().connection
81130
}
131+
}
132+
133+
impl AsSigned for SignedConnection {
134+
fn as_signed(&self) -> &SignedConnection {
135+
self
136+
}
137+
}
138+
139+
impl AsSigned for RootConnection {
140+
fn as_signed(&self) -> &SignedConnection {
141+
&self.connection
142+
}
143+
}
82144

83-
pub async fn get_storage_entry<T: DecodeWithMetadata, Defaultable, Iterable>(
145+
#[async_trait::async_trait]
146+
impl<C: AsConnection + Sync> ConnectionApi for C {
147+
async fn get_storage_entry<T: DecodeWithMetadata + Sync, Defaultable: Sync, Iterable: Sync>(
84148
&self,
85149
addrs: &StaticStorageAddress<T, Yes, Defaultable, Iterable>,
86150
at: Option<BlockHash>,
@@ -90,41 +154,40 @@ impl Connection {
90154
.expect("There should be a value")
91155
}
92156

93-
pub async fn get_storage_entry_maybe<T: DecodeWithMetadata, Defaultable, Iterable>(
157+
async fn get_storage_entry_maybe<
158+
T: DecodeWithMetadata + Sync,
159+
Defaultable: Sync,
160+
Iterable: Sync,
161+
>(
94162
&self,
95163
addrs: &StaticStorageAddress<T, Yes, Defaultable, Iterable>,
96164
at: Option<BlockHash>,
97165
) -> Option<T::Target> {
98166
info!(target: "aleph-client", "accessing storage at {}::{} at block {:?}", addrs.pallet_name(), addrs.entry_name(), at);
99-
self.client
167+
self.as_connection()
168+
.as_client()
100169
.storage()
101170
.fetch(addrs, at)
102171
.await
103172
.expect("Should access storage")
104173
}
105174

106-
pub async fn rpc_call<R: Decode>(
107-
&self,
108-
func_name: String,
109-
params: RpcParams,
110-
) -> anyhow::Result<R> {
175+
async fn rpc_call<R: Decode>(&self, func_name: String, params: RpcParams) -> anyhow::Result<R> {
111176
info!(target: "aleph-client", "submitting rpc call `{}`, with params {:?}", func_name, params);
112-
let bytes: Bytes = self.client.rpc().request(&func_name, params).await?;
177+
let bytes: Bytes = self
178+
.as_connection()
179+
.as_client()
180+
.rpc()
181+
.request(&func_name, params)
182+
.await?;
113183

114184
Ok(R::decode(&mut bytes.as_ref())?)
115185
}
116186
}
117187

118-
impl SignedConnection {
119-
pub async fn new(address: String, signer: KeyPair) -> Self {
120-
Self::from_connection(Connection::new(address).await, signer)
121-
}
122-
123-
pub fn from_connection(connection: Connection, signer: KeyPair) -> Self {
124-
Self { connection, signer }
125-
}
126-
127-
pub async fn send_tx<Call: TxPayload>(
188+
#[async_trait::async_trait]
189+
impl<S: AsSigned + Sync> SignedConnectionApi for S {
190+
async fn send_tx<Call: TxPayload + Send + Sync>(
128191
&self,
129192
tx: Call,
130193
status: TxStatus,
@@ -133,7 +196,7 @@ impl SignedConnection {
133196
.await
134197
}
135198

136-
pub async fn send_tx_with_params<Call: TxPayload>(
199+
async fn send_tx_with_params<Call: TxPayload + Send + Sync>(
137200
&self,
138201
tx: Call,
139202
params: BaseExtrinsicParamsBuilder<SubstrateConfig, PlainTip>,
@@ -144,10 +207,10 @@ impl SignedConnection {
144207
}
145208

146209
let progress = self
147-
.connection
148-
.client
210+
.as_connection()
211+
.as_client()
149212
.tx()
150-
.sign_and_submit_then_watch(&tx, &self.signer, params)
213+
.sign_and_submit_then_watch(&tx, self.as_signed().signer(), params)
151214
.await
152215
.map_err(|e| anyhow!("Failed to submit transaction: {:?}", e))?;
153216

@@ -161,10 +224,60 @@ impl SignedConnection {
161224

162225
Ok(hash)
163226
}
227+
228+
fn account_id(&self) -> &AccountId {
229+
self.as_signed().signer().account_id()
230+
}
231+
232+
fn signer(&self) -> &KeyPair {
233+
&self.as_signed().signer
234+
}
235+
236+
async fn try_as_root(&self) -> anyhow::Result<RootConnection> {
237+
let temp = self.as_signed().clone();
238+
RootConnection::try_from_connection(temp.connection, temp.signer).await
239+
}
240+
}
241+
242+
impl Connection {
243+
const DEFAULT_RETRIES: u32 = 10;
244+
const RETRY_WAIT_SECS: u64 = 1;
245+
246+
pub async fn new(address: &str) -> Connection {
247+
Self::new_with_retries(address, Self::DEFAULT_RETRIES).await
248+
}
249+
250+
async fn new_with_retries(address: &str, mut retries: u32) -> Connection {
251+
loop {
252+
let client = SubxtClient::from_url(&address).await;
253+
match (retries, client) {
254+
(_, Ok(client)) => return Connection { client },
255+
(0, Err(e)) => panic!("{:?}", e),
256+
_ => {
257+
sleep(Duration::from_secs(Self::RETRY_WAIT_SECS));
258+
retries -= 1;
259+
}
260+
}
261+
}
262+
}
263+
264+
pub(crate) fn as_client(&self) -> &SubxtClient {
265+
&self.client
266+
}
267+
}
268+
269+
impl SignedConnection {
270+
pub async fn new(address: &str, signer: KeyPair) -> Self {
271+
Self::from_connection(Connection::new(address).await, signer)
272+
}
273+
274+
pub fn from_connection(connection: Connection, signer: KeyPair) -> Self {
275+
Self { connection, signer }
276+
}
164277
}
165278

166279
impl RootConnection {
167-
pub async fn new(address: String, root: KeyPair) -> anyhow::Result<Self> {
280+
pub async fn new(address: &str, root: KeyPair) -> anyhow::Result<Self> {
168281
RootConnection::try_from_connection(Connection::new(address).await, root).await
169282
}
170283

@@ -174,7 +287,12 @@ impl RootConnection {
174287
) -> anyhow::Result<Self> {
175288
let root_address = api::storage().sudo().key();
176289

177-
let root = match connection.client.storage().fetch(&root_address, None).await {
290+
let root = match connection
291+
.as_client()
292+
.storage()
293+
.fetch(&root_address, None)
294+
.await
295+
{
178296
Ok(Some(account)) => account,
179297
_ => return Err(anyhow!("Could not read sudo key from chain")),
180298
};
@@ -188,15 +306,7 @@ impl RootConnection {
188306
}
189307

190308
Ok(Self {
191-
connection,
192-
root: signer,
309+
connection: SignedConnection { connection, signer },
193310
})
194311
}
195-
196-
pub fn as_signed(&self) -> SignedConnection {
197-
SignedConnection {
198-
connection: self.connection.clone(),
199-
signer: KeyPair::new(self.root.signer().clone()),
200-
}
201-
}
202312
}

0 commit comments

Comments
 (0)