diff --git a/polkadot/api/src/full.rs b/polkadot/api/src/full.rs
new file mode 100644
index 0000000000..68c79819e5
--- /dev/null
+++ b/polkadot/api/src/full.rs
@@ -0,0 +1,352 @@
+// Copyright 2017 Parity Technologies (UK) Ltd.
+// This file is part of Polkadot.
+
+// Polkadot is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// Polkadot is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Polkadot. If not, see .
+
+//! Strongly typed API for full Polkadot client.
+
+use client::backend::{Backend, LocalBackend};
+use client::{self, Client, LocalCallExecutor};
+use polkadot_executor::Executor as LocalDispatch;
+use substrate_executor::{NativeExecutionDispatch, NativeExecutor};
+use state_machine::{self, OverlayedChanges};
+
+use primitives::{AccountId, BlockId, Hash, Index, SessionKey, Timestamp};
+use primitives::parachain::{DutyRoster, CandidateReceipt, Id as ParaId};
+use runtime::{self, Block, Header, UncheckedExtrinsic, Extrinsic, Call, TimestampCall, ParachainsCall};
+
+use {CheckedBlockId, BlockBuilder, PolkadotApi, LocalPolkadotApi, ErrorKind, Error, Result};
+
+/// A checked block ID used for the substrate-client implementation of CheckedBlockId;
+#[derive(Debug, Clone, Copy)]
+pub struct CheckedId(pub BlockId);
+
+impl CheckedBlockId for CheckedId {
+ fn block_id(&self) -> &BlockId {
+ &self.0
+ }
+}
+
+// set up the necessary scaffolding to execute a set of calls to the runtime.
+// this creates a new block on top of the given ID and initialises it.
+macro_rules! with_runtime {
+ ($client: ident, $at: expr, $exec: expr) => {{
+ let parent = $at.block_id();
+ let header = Header {
+ parent_hash: $client.block_hash_from_id(parent)?.ok_or(ErrorKind::UnknownBlock(*parent))?,
+ number: $client.block_number_from_id(parent)?.ok_or(ErrorKind::UnknownBlock(*parent))? + 1,
+ state_root: Default::default(),
+ extrinsics_root: Default::default(),
+ digest: Default::default(),
+ };
+
+ $client.state_at(parent).map_err(Error::from).and_then(|state| {
+ let mut changes = Default::default();
+ let mut ext = state_machine::Ext::new(&mut changes, &state);
+
+ ::substrate_executor::with_native_environment(&mut ext, || {
+ ::runtime::Executive::initialise_block(&header);
+ ($exec)()
+ }).map_err(Into::into)
+ })
+ }}
+}
+
+/// A polkadot block builder.
+#[derive(Debug, Clone)]
+pub struct ClientBlockBuilder {
+ parent: BlockId,
+ changes: OverlayedChanges,
+ state: S,
+ header: Header,
+ timestamp: Timestamp,
+ extrinsics: Vec,
+}
+
+impl ClientBlockBuilder
+ where S::Error: Into
+{
+ // initialises a block, ready to allow extrinsics to be applied.
+ fn initialise_block(&mut self) -> Result<()> {
+ let result = {
+ let mut ext = state_machine::Ext::new(&mut self.changes, &self.state);
+ let h = self.header.clone();
+
+ ::substrate_executor::with_native_environment(
+ &mut ext,
+ || runtime::Executive::initialise_block(&h),
+ ).map_err(Into::into)
+ };
+
+ match result {
+ Ok(_) => {
+ self.changes.commit_prospective();
+ Ok(())
+ }
+ Err(e) => {
+ self.changes.discard_prospective();
+ Err(e)
+ }
+ }
+ }
+
+ // executes a extrinsic, inherent or otherwise, without appending to the list.
+ fn apply_extrinsic(&mut self, extrinsic: UncheckedExtrinsic) -> Result<()> {
+ let result = {
+ let mut ext = state_machine::Ext::new(&mut self.changes, &self.state);
+
+ ::substrate_executor::with_native_environment(
+ &mut ext,
+ move || runtime::Executive::apply_extrinsic(extrinsic),
+ ).map_err(Into::into)
+ };
+
+ match result {
+ Ok(_) => {
+ self.changes.commit_prospective();
+ Ok(())
+ }
+ Err(e) => {
+ self.changes.discard_prospective();
+ Err(e)
+ }
+ }
+ }
+}
+
+impl BlockBuilder for ClientBlockBuilder
+ where S::Error: Into
+{
+ fn push_extrinsic(&mut self, extrinsic: UncheckedExtrinsic) -> Result<()> {
+ // Check that this is not an "inherent" extrinsic.
+ if extrinsic.signature == Default::default() {
+ bail!(ErrorKind::PushedInherentTransaction(extrinsic));
+ } else {
+ self.apply_extrinsic(extrinsic.clone())?;
+ self.extrinsics.push(extrinsic);
+ Ok(())
+ }
+ }
+
+ fn bake(mut self) -> Block {
+ let mut ext = state_machine::Ext::new(&mut self.changes, &self.state);
+
+ let final_header = ::substrate_executor::with_native_environment(
+ &mut ext,
+ move || runtime::Executive::finalise_block()
+ ).expect("all inherent extrinsics pushed; all other extrinsics executed correctly; qed");
+ Block {
+ header: final_header,
+ extrinsics: self.extrinsics,
+ }
+ }
+}
+
+impl PolkadotApi for Client>>
+ where ::client::error::Error: From<<::State as state_machine::backend::Backend>::Error>
+{
+ type CheckedBlockId = CheckedId;
+ type BlockBuilder = ClientBlockBuilder;
+
+ fn check_id(&self, id: BlockId) -> Result {
+ // bail if the code is not the same as the natively linked.
+ if self.code_at(&id)? != LocalDispatch::native_equivalent() {
+ bail!("This node is out of date. Block authoring may not work correctly. Bailing.")
+ }
+
+ Ok(CheckedId(id))
+ }
+
+ fn session_keys(&self, at: &CheckedId) -> Result> {
+ with_runtime!(self, at, ::runtime::Consensus::authorities)
+ }
+
+ fn validators(&self, at: &CheckedId) -> Result> {
+ with_runtime!(self, at, ::runtime::Session::validators)
+ }
+
+ fn random_seed(&self, at: &CheckedId) -> Result {
+ with_runtime!(self, at, ::runtime::System::random_seed)
+ }
+
+ fn duty_roster(&self, at: &CheckedId) -> Result {
+ with_runtime!(self, at, ::runtime::Parachains::calculate_duty_roster)
+ }
+
+ fn timestamp(&self, at: &CheckedId) -> Result {
+ with_runtime!(self, at, ::runtime::Timestamp::now)
+ }
+
+ fn evaluate_block(&self, at: &CheckedId, block: Block) -> Result {
+ use substrate_executor::error::ErrorKind as ExecErrorKind;
+
+ let res = with_runtime!(self, at, || ::runtime::Executive::execute_block(block));
+ match res {
+ Ok(()) => Ok(true),
+ Err(err) => match err.kind() {
+ &ErrorKind::Executor(ExecErrorKind::Runtime) => Ok(false),
+ _ => Err(err)
+ }
+ }
+ }
+
+ fn index(&self, at: &CheckedId, account: AccountId) -> Result {
+ with_runtime!(self, at, || ::runtime::System::account_index(account))
+ }
+
+ fn active_parachains(&self, at: &CheckedId) -> Result> {
+ with_runtime!(self, at, ::runtime::Parachains::active_parachains)
+ }
+
+ fn parachain_code(&self, at: &CheckedId, parachain: ParaId) -> Result