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
125
126
127
128
129
130
131
132
133
134
135
136
137
// Copyright (c) The Diem Core Contributors
// SPDX-License-Identifier: Apache-2.0

use crate::{Coffer, PublicInfo, Result};
use diem_sdk::{
    client::BlockingClient,
    transaction_builder::{Currency, TransactionFactory},
    types::{
        account_address::AccountAddress, chain_id::ChainId,
        transaction::authenticator::AuthenticationKey, LocalAccount,
    },
};

#[derive(Debug)]
pub struct ChainInfo<'t> {
    pub root_account: &'t mut LocalAccount,
    pub treasury_compliance_account: &'t mut LocalAccount,
    pub designated_dealer_account: &'t mut LocalAccount,
    pub json_rpc_url: String,
    pub chain_id: ChainId,
}

impl<'t> ChainInfo<'t> {
    pub fn new(
        root_account: &'t mut LocalAccount,
        treasury_compliance_account: &'t mut LocalAccount,
        designated_dealer_account: &'t mut LocalAccount,
        json_rpc_url: String,
        chain_id: ChainId,
    ) -> Self {
        Self {
            root_account,
            treasury_compliance_account,
            designated_dealer_account,
            json_rpc_url,
            chain_id,
        }
    }

    pub fn designated_dealer_account(&mut self) -> &mut LocalAccount {
        self.designated_dealer_account
    }

    pub fn root_account(&mut self) -> &mut LocalAccount {
        self.root_account
    }

    pub fn treasury_compliance_account(&mut self) -> &mut LocalAccount {
        self.treasury_compliance_account
    }

    pub fn json_rpc(&self) -> &str {
        &self.json_rpc_url
    }

    pub fn json_rpc_client(&self) -> BlockingClient {
        BlockingClient::new(&self.json_rpc_url)
    }

    pub fn chain_id(&self) -> ChainId {
        self.chain_id
    }

    pub fn transaction_factory(&self) -> TransactionFactory {
        TransactionFactory::new(self.chain_id())
    }

    pub fn create_parent_vasp_account(
        &mut self,
        currency: Currency,
        authentication_key: AuthenticationKey,
    ) -> Result<()> {
        let factory = self.transaction_factory();
        let client = self.json_rpc_client();
        let treasury_compliance_account = self.treasury_compliance_account();

        let create_account_txn = treasury_compliance_account.sign_with_transaction_builder(
            factory.create_parent_vasp_account(
                currency,
                0,
                authentication_key,
                &format!("No. {} VASP", treasury_compliance_account.sequence_number()),
                false,
            ),
        );
        client.submit(&create_account_txn)?;
        client.wait_for_signed_transaction(&create_account_txn, None, None)?;
        Ok(())
    }

    pub fn create_designated_dealer_account(
        &mut self,
        currency: Currency,
        authentication_key: AuthenticationKey,
    ) -> Result<()> {
        let factory = self.transaction_factory();
        let client = self.json_rpc_client();
        let treasury_compliance_account = self.treasury_compliance_account();

        let create_account_txn = treasury_compliance_account.sign_with_transaction_builder(
            factory.create_designated_dealer(
                currency,
                0, // sliding_nonce
                authentication_key,
                &format!("No. {} DD", treasury_compliance_account.sequence_number()),
                false, // add all currencies
            ),
        );
        client.submit(&create_account_txn)?;
        client.wait_for_signed_transaction(&create_account_txn, None, None)?;
        Ok(())
    }

    pub fn fund(&mut self, currency: Currency, address: AccountAddress, amount: u64) -> Result<()> {
        let factory = self.transaction_factory();
        let client = self.json_rpc_client();
        let designated_dealer_account = self.designated_dealer_account();
        let fund_account_txn = designated_dealer_account
            .sign_with_transaction_builder(factory.peer_to_peer(currency, address, amount));
        client.submit(&fund_account_txn)?;
        client.wait_for_signed_transaction(&fund_account_txn, None, None)?;
        Ok(())
    }

    pub fn into_public_info(self) -> PublicInfo<'t> {
        PublicInfo::new(
            self.json_rpc_url.clone(),
            self.chain_id,
            Coffer::TreasuryCompliance {
                transaction_factory: TransactionFactory::new(self.chain_id),
                json_rpc_client: BlockingClient::new(self.json_rpc_url),
                treasury_compliance_account: self.treasury_compliance_account,
                designated_dealer_account: self.designated_dealer_account,
            },
        )
    }
}