1
// Copyright (C) Moondance Labs Ltd.
2
// This file is part of Tanssi.
3

            
4
// Tanssi is free software: you can redistribute it and/or modify
5
// it under the terms of the GNU General Public License as published by
6
// the Free Software Foundation, either version 3 of the License, or
7
// (at your option) any later version.
8

            
9
// Tanssi is distributed in the hope that it will be useful,
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
// GNU General Public License for more details.
13

            
14
// You should have received a copy of the GNU General Public License
15
// along with Tanssi.  If not, see <http://www.gnu.org/licenses/>
16

            
17
//! A collection of node-specific RPC methods.
18
//! Substrate provides the `sc-rpc` crate, which defines the core RPC layer
19
//! used by Substrate nodes. This file extends those RPC definitions with
20
//! capabilities that are specific to this project's runtime configuration.
21

            
22
#![warn(missing_docs)]
23

            
24
pub use sc_rpc::DenyUnsafe;
25
use {
26
    cumulus_primitives_core::ParaId,
27
    dancebox_runtime::{opaque::Block, AccountId, Index as Nonce},
28
    manual_xcm_rpc::{ManualXcm, ManualXcmApiServer},
29
    polkadot_primitives::Hash,
30
    sc_client_api::{AuxStore, UsageProvider},
31
    sc_consensus_manual_seal::{
32
        rpc::{ManualSeal, ManualSealApiServer},
33
        EngineCommand,
34
    },
35
    sc_transaction_pool_api::TransactionPool,
36
    services_payment_rpc::{
37
        ServicesPayment, ServicesPaymentApiServer as _, ServicesPaymentRuntimeApi,
38
    },
39
    sp_api::ProvideRuntimeApi,
40
    sp_block_builder::BlockBuilder,
41
    sp_blockchain::{Error as BlockChainError, HeaderBackend, HeaderMetadata},
42
    std::sync::Arc,
43
    stream_payment_rpc::{StreamPayment, StreamPaymentApiServer as _, StreamPaymentRuntimeApi},
44
};
45

            
46
/// A type representing all RPC extensions.
47
pub type RpcExtension = jsonrpsee::RpcModule<()>;
48

            
49
/// Full client dependencies
50
pub struct FullDeps<C, P> {
51
    /// The client instance to use.
52
    pub client: Arc<C>,
53
    /// Transaction pool instance.
54
    pub pool: Arc<P>,
55
    /// Whether to deny unsafe calls
56
    pub deny_unsafe: DenyUnsafe,
57
    /// Manual seal command sink
58
    pub command_sink: Option<futures::channel::mpsc::Sender<EngineCommand<Hash>>>,
59
    /// Channels for manual xcm messages (downward, hrmp)
60
    pub xcm_senders: Option<(flume::Sender<Vec<u8>>, flume::Sender<(ParaId, Vec<u8>)>)>,
61
}
62

            
63
/// Instantiate all RPC extensions.
64
356
pub fn create_full<C, P>(
65
356
    deps: FullDeps<C, P>,
66
356
) -> Result<RpcExtension, Box<dyn std::error::Error + Send + Sync>>
67
356
where
68
356
    C: ProvideRuntimeApi<Block>
69
356
        + HeaderBackend<Block>
70
356
        + AuxStore
71
356
        + HeaderMetadata<Block, Error = BlockChainError>
72
356
        + Send
73
356
        + Sync
74
356
        + UsageProvider<Block>
75
356
        + 'static,
76
356
    C::Api: substrate_frame_rpc_system::AccountNonceApi<Block, AccountId, Nonce>,
77
356
    C::Api: BlockBuilder<Block>,
78
356
    C::Api: StreamPaymentRuntimeApi<Block, u64, u128, u128>,
79
356
    C::Api: ServicesPaymentRuntimeApi<Block, u128, ParaId>,
80
356
    P: TransactionPool + Sync + Send + 'static,
81
356
{
82
    use substrate_frame_rpc_system::{System, SystemApiServer};
83

            
84
356
    let mut module = RpcExtension::new(());
85
356
    let FullDeps {
86
356
        client,
87
356
        pool,
88
356
        deny_unsafe,
89
356
        command_sink,
90
356
        xcm_senders,
91
356
    } = deps;
92
356

            
93
356
    module.merge(System::new(client.clone(), pool, deny_unsafe).into_rpc())?;
94
356
    module.merge(StreamPayment::<_, Block>::new(client.clone()).into_rpc())?;
95
356
    module.merge(ServicesPayment::<_, Block>::new(client).into_rpc())?;
96

            
97
356
    if let Some(command_sink) = command_sink {
98
324
        module.merge(
99
324
            // We provide the rpc handler with the sending end of the channel to allow the rpc
100
324
            // send EngineCommands to the background block authorship task.
101
324
            ManualSeal::new(command_sink).into_rpc(),
102
324
        )?;
103
32
    };
104

            
105
356
    if let Some((downward_message_channel, hrmp_message_channel)) = xcm_senders {
106
356
        module.merge(
107
356
            ManualXcm {
108
356
                downward_message_channel,
109
356
                hrmp_message_channel,
110
356
            }
111
356
            .into_rpc(),
112
356
        )?;
113
    }
114

            
115
356
    Ok(module)
116
356
}