Merge pull request #5833 from paritytech/pubsub-docs

Docs for Pub-Sub, optional parameter for parity_subscribe
This commit is contained in:
Robert Habermeier 2017-06-22 20:17:02 +02:00 committed by GitHub
commit b6fd18a9ca
14 changed files with 186 additions and 34 deletions

18
Cargo.lock generated
View File

@ -1048,7 +1048,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "jsonrpc-core"
version = "7.0.0"
source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7#87db29043826f152cce171351fa34fada287764d"
source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7#d8dae528860d7fe976a8e3ec060a792e2496573b"
dependencies = [
"futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1060,7 +1060,7 @@ dependencies = [
[[package]]
name = "jsonrpc-http-server"
version = "7.0.0"
source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7#87db29043826f152cce171351fa34fada287764d"
source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7#d8dae528860d7fe976a8e3ec060a792e2496573b"
dependencies = [
"hyper 0.10.0-a.0 (git+https://github.com/paritytech/hyper)",
"jsonrpc-core 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)",
@ -1073,7 +1073,7 @@ dependencies = [
[[package]]
name = "jsonrpc-ipc-server"
version = "7.0.0"
source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7#87db29043826f152cce171351fa34fada287764d"
source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7#d8dae528860d7fe976a8e3ec060a792e2496573b"
dependencies = [
"bytes 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
"jsonrpc-core 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)",
@ -1086,7 +1086,7 @@ dependencies = [
[[package]]
name = "jsonrpc-macros"
version = "7.0.0"
source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7#87db29043826f152cce171351fa34fada287764d"
source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7#d8dae528860d7fe976a8e3ec060a792e2496573b"
dependencies = [
"jsonrpc-core 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)",
"jsonrpc-pubsub 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)",
@ -1096,7 +1096,7 @@ dependencies = [
[[package]]
name = "jsonrpc-minihttp-server"
version = "7.0.0"
source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7#87db29043826f152cce171351fa34fada287764d"
source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7#d8dae528860d7fe976a8e3ec060a792e2496573b"
dependencies = [
"jsonrpc-core 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)",
"jsonrpc-server-utils 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)",
@ -1110,7 +1110,7 @@ dependencies = [
[[package]]
name = "jsonrpc-pubsub"
version = "7.0.0"
source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7#87db29043826f152cce171351fa34fada287764d"
source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7#d8dae528860d7fe976a8e3ec060a792e2496573b"
dependencies = [
"jsonrpc-core 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)",
"log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1120,7 +1120,7 @@ dependencies = [
[[package]]
name = "jsonrpc-server-utils"
version = "7.0.0"
source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7#87db29043826f152cce171351fa34fada287764d"
source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7#d8dae528860d7fe976a8e3ec060a792e2496573b"
dependencies = [
"globset 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
"jsonrpc-core 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)",
@ -1132,7 +1132,7 @@ dependencies = [
[[package]]
name = "jsonrpc-tcp-server"
version = "7.0.0"
source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7#87db29043826f152cce171351fa34fada287764d"
source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7#d8dae528860d7fe976a8e3ec060a792e2496573b"
dependencies = [
"bytes 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
"jsonrpc-core 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)",
@ -1146,7 +1146,7 @@ dependencies = [
[[package]]
name = "jsonrpc-ws-server"
version = "7.0.0"
source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7#87db29043826f152cce171351fa34fada287764d"
source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7#d8dae528860d7fe976a8e3ec060a792e2496573b"
dependencies = [
"jsonrpc-core 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)",
"jsonrpc-server-utils 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)",

View File

@ -36,12 +36,19 @@ describe('api/Api', () => {
describe('interface', () => {
const api = new Api(new Api.Transport.Http(TEST_HTTP_URL, -1));
const ignored = [
'eth_subscribe', 'eth_unsubscribe',
'parity_subscribe', 'parity_unsubscribe',
'signer_subscribePending', 'signer_unsubscribePending'
];
Object.keys(ethereumRpc).sort().forEach((endpoint) => {
describe(endpoint, () => {
Object.keys(ethereumRpc[endpoint]).sort().forEach((method) => {
endpointTest(api, endpoint, method);
});
Object.keys(ethereumRpc[endpoint]).sort()
.filter(method => ignored.indexOf(method) !== -1)
.forEach((method) => {
endpointTest(api, endpoint, method);
});
});
});
});

View File

@ -17,6 +17,8 @@
import { Address, BlockNumber, Data, Hash, Quantity, CallRequest, TransactionRequest } from '../types';
import { withPreamble, fromDecimal, withComment, Dummy } from '../helpers';
const SUBDOC_PUBSUB = 'pubsub';
export default withPreamble(`
## The default block parameter
@ -1192,5 +1194,60 @@ The following options are possible for the \`defaultBlock\` parameter:
type: Boolean,
desc: 'whether the call was successful'
}
},
// Pub-Sub
subscribe: {
subdoc: SUBDOC_PUBSUB,
desc: `
Starts a subscription (on WebSockets / IPC / TCP transports) to a particular event. For every event that
matches the subscription a JSON-RPC notification with event details and subscription ID will be sent to a client.
An example notification received by subscribing to \`newHeads\` event:
\`\`\`
{"jsonrpc":"2.0","method":"eth_subscription","params":{"subscription":"0x416d77337e24399d","result":{"difficulty":"0xd9263f42a87",<...>,
"uncles":[]}}}
\`\`\`
You can unsubscribe using \`eth_unsubscribe\` RPC method. Subscriptions are also tied to a transport
connection, disconnecting causes all subscriptions to be canceled.
`,
params: [
{
type: String,
desc: 'Subscription type: one of `newHeads`, `logs`',
example: 'newHeads'
},
{
type: Object,
desc: `
Subscription type-specific parameters. It must be left empty for
\`newHeads\` and must contain filter object for \`logs\`.
`,
example: {
fromBlock: 'latest',
toBlock: 'latest'
}
}
],
returns: {
type: String,
desc: 'Assigned subscription ID',
example: '0x416d77337e24399d'
}
},
unsubscribe: {
subdoc: SUBDOC_PUBSUB,
desc: 'Unsubscribes from a subscription.',
params: [{
type: String,
desc: 'Subscription ID',
example: '0x416d77337e24399d'
}],
returns: {
type: Boolean,
desc: 'whether the call was successful',
example: true
}
}
});

View File

@ -26,6 +26,7 @@ const SECTION_VAULT = 'Account Vaults';
const SUBDOC_SET = 'set';
const SUBDOC_ACCOUNTS = 'accounts';
const SUBDOC_PUBSUB = 'pubsub';
export default {
accountsInfo: {
@ -2005,6 +2006,54 @@ export default {
desc: 'Base58 encoded CID',
example: 'QmSbFjqjd6nFwNHqsBCC7SK8GShGcayLUEtysJjNGhZAnC'
}
},
// Pub-Sub
subscribe: {
subdoc: SUBDOC_PUBSUB,
desc: `
Starts a subscription (on WebSockets / IPC / TCP transports) to results of calling some other RPC method.
For every change in returned value of that RPC call a JSON-RPC notification with result and subscription ID will be sent to a client.
An example notification received by subscribing to \`eth_accounts\` RPC method:
\`\`\`
{"jsonrpc":"2.0","method":"parity_subscription","params":{"subscription":"0x416d77337e24399d","result":["0xcd2a3d9f938e13cd947ec05abc7fe734df8dd826"]}}
\`\`\`
You can unsubscribe using \`parity_unsubscribe\` RPC method. Subscriptions are also tied to a transport
connection, disconnecting causes all subscriptions to be canceled.
`,
params: [
{
type: String,
desc: 'RPC method name',
example: 'eth_getBalance'
},
{
type: Array,
desc: 'Parameters passed to RPC method. (Optional, defaults to no parameters)',
example: ['0xcd2a3d9f938e13cd947ec05abc7fe734df8dd826', 'latest']
}
],
returns: {
type: String,
desc: 'Assigned subscription ID',
example: '0x416d77337e24399d'
}
},
unsubscribe: {
subdoc: SUBDOC_PUBSUB,
desc: 'Unsubscribes from a subscription.',
params: [{
type: String,
desc: 'Subscription ID',
example: '0x416d77337e24399d'
}],
returns: {
type: Boolean,
desc: 'whether the call was successful',
example: true
}
}
};

View File

@ -198,5 +198,40 @@ export default {
desc: '`true` when enabled, `false` when disabled.',
example: true
}
},
// Pub-Sub
subscribePending: {
desc: `
Starts a subscription for transactions in the confirmation queue.
Each event contains all transactions currently in the queue.
An example notification received by subscribing to this event:
\`\`\`
{"jsonrpc":"2.0","method":"signer_pending","params":{"subscription":"0x416d77337e24399d","result":[]}}
\`\`\`
You can unsubscribe using \`signer_unsubscribePending\` RPC method. Subscriptions are also tied to a transport
connection, disconnecting causes all subscriptions to be canceled.
`,
params: [],
returns: {
type: String,
desc: 'Assigned subscription ID',
example: '0x416d77337e24399d'
}
},
unsubscribePending: {
desc: 'Unsubscribes from pending transactions subscription.',
params: [{
type: String,
desc: 'Subscription ID',
example: '0x416d77337e24399d'
}],
returns: {
type: Boolean,
desc: 'whether the call was successful',
example: true
}
}
};

View File

@ -162,7 +162,7 @@ impl LightFetch {
let (sync, on_demand, client) = (self.sync.clone(), self.on_demand.clone(), self.client.clone());
let req: CallRequestHelper = req.into();
let id = num.0.into();
let id = num.unwrap_or_default().into();
let from = req.from.unwrap_or(Address::zero());
let nonce_fut = match req.nonce {

View File

@ -361,7 +361,7 @@ impl<C, SN: ?Sized, S: ?Sized, M, EM> Eth for EthClient<C, SN, S, M, EM> where
fn balance(&self, address: RpcH160, num: Trailing<BlockNumber>) -> BoxFuture<RpcU256, Error> {
let address = address.into();
let res = match num.0.clone() {
let res = match num.unwrap_or_default() {
BlockNumber::Pending => {
match self.miner.balance(&*self.client, &address) {
Some(balance) => Ok(balance.into()),
@ -384,7 +384,7 @@ impl<C, SN: ?Sized, S: ?Sized, M, EM> Eth for EthClient<C, SN, S, M, EM> where
let address: Address = RpcH160::into(address);
let position: U256 = RpcU256::into(pos);
let res = match num.0.clone() {
let res = match num.unwrap_or_default() {
BlockNumber::Pending => {
match self.miner.storage_at(&*self.client, &address, &H256::from(position)) {
Some(s) => Ok(s.into()),
@ -406,7 +406,7 @@ impl<C, SN: ?Sized, S: ?Sized, M, EM> Eth for EthClient<C, SN, S, M, EM> where
fn transaction_count(&self, address: RpcH160, num: Trailing<BlockNumber>) -> BoxFuture<RpcU256, Error> {
let address: Address = RpcH160::into(address);
let res = match num.0.clone() {
let res = match num.unwrap_or_default() {
BlockNumber::Pending if self.options.pending_nonce_from_queue => {
let nonce = self.miner.last_nonce(&address)
.map(|n| n + 1.into())
@ -468,7 +468,7 @@ impl<C, SN: ?Sized, S: ?Sized, M, EM> Eth for EthClient<C, SN, S, M, EM> where
fn code_at(&self, address: RpcH160, num: Trailing<BlockNumber>) -> BoxFuture<Bytes, Error> {
let address: Address = RpcH160::into(address);
let res = match num.0.clone() {
let res = match num.unwrap_or_default() {
BlockNumber::Pending => {
match self.miner.code(&*self.client, &address) {
Some(code) => Ok(code.map_or_else(Bytes::default, Bytes::new)),
@ -553,7 +553,7 @@ impl<C, SN: ?Sized, S: ?Sized, M, EM> Eth for EthClient<C, SN, S, M, EM> where
}
fn work(&self, no_new_work_timeout: Trailing<u64>) -> Result<Work, Error> {
let no_new_work_timeout = no_new_work_timeout.0;
let no_new_work_timeout = no_new_work_timeout.unwrap_or_default();
// check if we're still syncing and return empty strings in that case
{
@ -638,7 +638,7 @@ impl<C, SN: ?Sized, S: ?Sized, M, EM> Eth for EthClient<C, SN, S, M, EM> where
Err(e) => return future::err(e).boxed(),
};
let result = match num.0 {
let result = match num.unwrap_or_default() {
BlockNumber::Pending => self.miner.call(&*self.client, &signed, Default::default()),
num => self.client.call(&signed, num.into(), Default::default()),
};
@ -655,7 +655,7 @@ impl<C, SN: ?Sized, S: ?Sized, M, EM> Eth for EthClient<C, SN, S, M, EM> where
Ok(signed) => signed,
Err(e) => return future::err(e).boxed(),
};
future::done(self.client.estimate_gas(&signed, num.0.into())
future::done(self.client.estimate_gas(&signed, num.unwrap_or_default().into())
.map(Into::into)
.map_err(errors::from_call_error)
).boxed()

View File

@ -144,8 +144,9 @@ impl<C: Send + Sync + 'static> EthPubSub for EthPubSubClient<C> {
kind: pubsub::Kind,
params: Trailing<pubsub::Params>,
) {
match (kind, params.0) {
(pubsub::Kind::NewHeads, pubsub::Params::None) => {
let params: Option<pubsub::Params> = params.into();
match (kind, params) {
(pubsub::Kind::NewHeads, None) => {
self.heads_subscribers.lock().push(subscriber)
},
_ => {

View File

@ -270,7 +270,7 @@ impl Eth for EthClient {
}
fn balance(&self, address: RpcH160, num: Trailing<BlockNumber>) -> BoxFuture<RpcU256, Error> {
self.fetcher().account(address.into(), num.0.into())
self.fetcher().account(address.into(), num.unwrap_or_default().into())
.map(|acc| acc.map_or(0.into(), |a| a.balance).into()).boxed()
}
@ -287,7 +287,7 @@ impl Eth for EthClient {
}
fn transaction_count(&self, address: RpcH160, num: Trailing<BlockNumber>) -> BoxFuture<RpcU256, Error> {
self.fetcher().account(address.into(), num.0.into())
self.fetcher().account(address.into(), num.unwrap_or_default().into())
.map(|acc| acc.map_or(0.into(), |a| a.nonce).into()).boxed()
}

View File

@ -98,7 +98,7 @@ impl Parity for ParityClient {
type Metadata = Metadata;
fn accounts_info(&self, dapp: Trailing<DappId>) -> Result<BTreeMap<H160, AccountInfo>, Error> {
let dapp = dapp.0;
let dapp = dapp.unwrap_or_default();
let store = &self.accounts;
let dapp_accounts = store
@ -383,7 +383,7 @@ impl Parity for ParityClient {
}
};
self.fetcher().header(number.0.into()).map(from_encoded).boxed()
self.fetcher().header(number.unwrap_or_default().into()).map(from_encoded).boxed()
}
fn ipfs_cid(&self, content: Bytes) -> Result<String, Error> {

View File

@ -124,7 +124,7 @@ impl<C, M, S: ?Sized, U> Parity for ParityClient<C, M, S, U> where
type Metadata = Metadata;
fn accounts_info(&self, dapp: Trailing<DappId>) -> Result<BTreeMap<H160, AccountInfo>, Error> {
let dapp = dapp.0;
let dapp = dapp.unwrap_or_default();
let store = self.account_provider()?;
let dapp_accounts = store
@ -272,13 +272,13 @@ impl<C, M, S: ?Sized, U> Parity for ParityClient<C, M, S, U> where
fn list_accounts(&self, count: u64, after: Option<H160>, block_number: Trailing<BlockNumber>) -> Result<Option<Vec<H160>>, Error> {
Ok(self.client
.list_accounts(block_number.0.into(), after.map(Into::into).as_ref(), count)
.list_accounts(block_number.unwrap_or_default().into(), after.map(Into::into).as_ref(), count)
.map(|a| a.into_iter().map(Into::into).collect()))
}
fn list_storage_keys(&self, address: H160, count: u64, after: Option<H256>, block_number: Trailing<BlockNumber>) -> Result<Option<Vec<H256>>, Error> {
Ok(self.client
.list_storage(block_number.0.into(), &address.into(), after.map(Into::into).as_ref(), count)
.list_storage(block_number.unwrap_or_default().into(), &address.into(), after.map(Into::into).as_ref(), count)
.map(|a| a.into_iter().map(Into::into).collect()))
}
@ -394,7 +394,7 @@ impl<C, M, S: ?Sized, U> Parity for ParityClient<C, M, S, U> where
fn block_header(&self, number: Trailing<BlockNumber>) -> BoxFuture<RichHeader, Error> {
const EXTRA_INFO_PROOF: &'static str = "Object exists in in blockchain (fetched earlier), extra_info is always available if object exists; qed";
let id: BlockId = number.0.into();
let id: BlockId = number.unwrap_or_default().into();
let encoded = match self.client.block_header(id.clone()) {
Some(encoded) => encoded,
None => return future::err(errors::unknown_block()).boxed(),

View File

@ -22,6 +22,7 @@ use util::RwLock;
use futures::{self, BoxFuture, Future, Stream, Sink};
use jsonrpc_core::{self as core, Error, MetaIoHandler};
use jsonrpc_macros::Trailing;
use jsonrpc_macros::pubsub::Subscriber;
use jsonrpc_pubsub::SubscriptionId;
use tokio_timer;
@ -74,7 +75,8 @@ impl PubSubClient<core::NoopMiddleware> {
impl<S: core::Middleware<Metadata>> PubSub for PubSubClient<S> {
type Metadata = Metadata;
fn parity_subscribe(&self, mut meta: Metadata, subscriber: Subscriber<core::Value>, method: String, params: core::Params) {
fn parity_subscribe(&self, mut meta: Metadata, subscriber: Subscriber<core::Value>, method: String, params: Trailing<core::Params>) {
let params = params.unwrap_or(core::Params::Array(vec![]));
// Make sure to get rid of PubSub session otherwise it will never be dropped.
meta.session = None;

View File

@ -80,7 +80,7 @@ impl<C, M> Traces for TracesClient<C, M> where C: MiningBlockChainClient + 'stat
}
fn call(&self, request: CallRequest, flags: Vec<String>, block: Trailing<BlockNumber>) -> Result<TraceResults, Error> {
let block = block.0;
let block = block.unwrap_or_default();
let request = CallRequest::into(request);
let signed = fake_sign::sign_call(&self.client, &self.miner, request)?;
@ -91,7 +91,7 @@ impl<C, M> Traces for TracesClient<C, M> where C: MiningBlockChainClient + 'stat
}
fn raw_transaction(&self, raw_transaction: Bytes, flags: Vec<String>, block: Trailing<BlockNumber>) -> Result<TraceResults, Error> {
let block = block.0;
let block = block.unwrap_or_default();
let tx = UntrustedRlp::new(&raw_transaction.into_vec()).as_val().map_err(|e| errors::invalid_params("Transaction is not valid RLP", e))?;
let signed = SignedTransaction::new(tx).map_err(errors::from_transaction_error)?;

View File

@ -18,6 +18,7 @@
use jsonrpc_core::{Error, Value, Params};
use jsonrpc_pubsub::SubscriptionId;
use jsonrpc_macros::Trailing;
use jsonrpc_macros::pubsub::Subscriber;
use futures::BoxFuture;
@ -29,7 +30,7 @@ build_rpc_trait! {
#[pubsub(name = "parity_subscription")] {
/// Subscribe to changes of any RPC method in Parity.
#[rpc(name = "parity_subscribe")]
fn parity_subscribe(&self, Self::Metadata, Subscriber<Value>, String, Params);
fn parity_subscribe(&self, Self::Metadata, Subscriber<Value>, String, Trailing<Params>);
/// Unsubscribe from existing Parity subscription.
#[rpc(name = "parity_unsubscribe")]