ic_solidity_bindgen/
context.rs

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
use crate::Web3Provider;
use ic_web3_rs::api::Eth;
use ic_web3_rs::transports::ICHttp;
use ic_web3_rs::types::Address;
use ic_web3_rs::Web3;
use std::sync::Arc;

/// Common data associated with multiple contracts.
#[derive(Clone)]
pub struct Web3Context(Arc<Web3ContextInner>);

pub trait Context {
    type Provider;
    fn provider(&self, contract: Address, abi: &[u8]) -> Self::Provider;
}

struct Web3ContextInner {
    from: Address,
    // We are not expecting to interact with the chain frequently,
    // and the websocket transport has problems with ping.
    // So, the Http transport seems like the best choice.
    eth: Eth<ICHttp>,
    chain_id: u64,
    key_name: String,
}

impl Web3Context {
    pub fn new(
        url: &str,
        from: Address,
        chain_id: u64,
        key_name: String,
    ) -> Result<Self, ic_web3_rs::error::Error> {
        let transport = ICHttp::new(url, None)?;
        let web3 = Web3::new(transport);
        let eth = web3.eth();
        let inner = Web3ContextInner {
            eth,
            from,
            chain_id,
            key_name,
        };
        Ok(Self(Arc::new(inner)))
    }

    pub fn from(&self) -> Address {
        self.0.from
    }

    pub(crate) fn eth(&self) -> Eth<ICHttp> {
        self.0.eth.clone()
    }
    pub fn chain_id(&self) -> u64 {
        self.0.chain_id
    }

    pub fn key_name(&self) -> &str {
        &self.0.key_name
    }
}

impl Context for Web3Context {
    type Provider = Web3Provider;
    fn provider(&self, contract: Address, json_abi: &[u8]) -> Self::Provider {
        Web3Provider::new(contract, self, json_abi)
    }
}