corda/docs/build/html/tutorial-clientrpc-api.html

377 lines
23 KiB
HTML
Raw Normal View History

2016-10-11 09:30:55 +00:00
<!DOCTYPE html>
<!--[if IE 8]><html class="no-js lt-ie9" lang="en" > <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="en" > <!--<![endif]-->
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Client RPC API &mdash; R3 Corda latest documentation</title>
<link rel="stylesheet" href="_static/css/custom.css" type="text/css" />
<link rel="top" title="R3 Corda latest documentation" href="index.html"/>
<link rel="next" title="Protocol state machines" href="protocol-state-machines.html"/>
<link rel="prev" title="Writing a contract test" href="tutorial-test-dsl.html"/>
<script src="_static/js/modernizr.min.js"></script>
</head>
<body class="wy-body-for-nav" role="document">
<div class="wy-grid-for-nav">
<nav data-toggle="wy-nav-shift" class="wy-nav-side">
<div class="wy-side-scroll">
<div class="wy-side-nav-search">
<a href="index.html" class="icon icon-home"> R3 Corda
</a>
<div class="version">
latest
</div>
<div role="search">
<form id="rtd-search-form" class="wy-form" action="search.html" method="get">
<input type="text" name="q" placeholder="Search docs" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
</div>
<br>
<a href="api/index.html">API reference</a>
</div>
<div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="main navigation">
<p class="caption"><span class="caption-text">Overview</span></p>
<ul>
<li class="toctree-l1"><a class="reference internal" href="inthebox.html">What&#8217;s included?</a></li>
<li class="toctree-l1"><a class="reference internal" href="getting-set-up.html">Getting set up</a></li>
<li class="toctree-l1"><a class="reference internal" href="data-model.html">Data model</a></li>
<li class="toctree-l1"><a class="reference internal" href="transaction-data-types.html">Data types</a></li>
<li class="toctree-l1"><a class="reference internal" href="consensus.html">Consensus model</a></li>
<li class="toctree-l1"><a class="reference internal" href="messaging.html">Networking and messaging</a></li>
<li class="toctree-l1"><a class="reference internal" href="persistence.html">Persistence</a></li>
<li class="toctree-l1"><a class="reference internal" href="creating-a-cordapp.html">Creating a Cordapp</a></li>
2016-10-12 10:24:11 +00:00
<li class="toctree-l1"><a class="reference internal" href="creating-a-cordapp.html#gradle-plugins-for-cordapps">Gradle Plugins for Cordapps</a></li>
<li class="toctree-l1"><a class="reference internal" href="creating-a-cordapp.html#template-build-gradle">Template build.gradle</a></li>
<li class="toctree-l1"><a class="reference internal" href="creating-a-cordapp.html#cordformation">Cordformation</a></li>
2016-10-11 09:30:55 +00:00
<li class="toctree-l1"><a class="reference internal" href="running-the-demos.html">Running the demos</a></li>
<li class="toctree-l1"><a class="reference internal" href="node-administration.html">Node administration</a></li>
<li class="toctree-l1"><a class="reference internal" href="corda-configuration-files.html">The Corda Configuration File</a></li>
</ul>
<p class="caption"><span class="caption-text">Tutorials</span></p>
<ul class="current">
<li class="toctree-l1"><a class="reference internal" href="where-to-start.html">Where to start</a></li>
<li class="toctree-l1"><a class="reference internal" href="tutorial-contract.html">Writing a contract</a></li>
<li class="toctree-l1"><a class="reference internal" href="tutorial-contract-clauses.html">Writing a contract using clauses</a></li>
<li class="toctree-l1"><a class="reference internal" href="tutorial-test-dsl.html">Writing a contract test</a></li>
<li class="toctree-l1 current"><a class="current reference internal" href="#">Client RPC API</a></li>
<li class="toctree-l1"><a class="reference internal" href="protocol-state-machines.html">Protocol state machines</a></li>
<li class="toctree-l1"><a class="reference internal" href="oracles.html">Writing oracle services</a></li>
<li class="toctree-l1"><a class="reference internal" href="tutorial-attachments.html">Using attachments</a></li>
<li class="toctree-l1"><a class="reference internal" href="event-scheduling.html">Event scheduling</a></li>
<li class="toctree-l1"><a class="reference internal" href="secure-coding-guidelines.html">Secure coding guidelines</a></li>
</ul>
<p class="caption"><span class="caption-text">Contracts</span></p>
<ul>
<li class="toctree-l1"><a class="reference internal" href="contract-catalogue.html">Contract catalogue</a></li>
<li class="toctree-l1"><a class="reference internal" href="contract-irs.html">Interest Rate Swaps</a></li>
</ul>
<p class="caption"><span class="caption-text">Node API</span></p>
<ul>
<li class="toctree-l1"><a class="reference internal" href="clientrpc.html">Client RPC</a></li>
</ul>
<p class="caption"><span class="caption-text">Appendix</span></p>
<ul>
<li class="toctree-l1"><a class="reference internal" href="release-process.html">Release process</a></li>
<li class="toctree-l1"><a class="reference internal" href="release-process.html#steps-to-cut-a-release">Steps to cut a release</a></li>
<li class="toctree-l1"><a class="reference internal" href="release-notes.html">Release notes</a></li>
<li class="toctree-l1"><a class="reference internal" href="network-simulator.html">Network Simulator</a></li>
<li class="toctree-l1"><a class="reference internal" href="codestyle.html">Code style guide</a></li>
<li class="toctree-l1"><a class="reference internal" href="building-the-docs.html">Building the documentation</a></li>
</ul>
</div>
</div>
</nav>
<section data-toggle="wy-nav-shift" class="wy-nav-content-wrap">
<nav class="wy-nav-top" role="navigation" aria-label="top navigation">
<i data-toggle="wy-nav-top" class="fa fa-bars"></i>
<a href="index.html">R3 Corda</a>
</nav>
<div class="wy-nav-content">
<div class="rst-content">
<div role="navigation" aria-label="breadcrumbs navigation">
<ul class="wy-breadcrumbs">
<li><a href="index.html">Docs</a> &raquo;</li>
<li>Client RPC API</li>
<li class="wy-breadcrumbs-aside">
<a href="_sources/tutorial-clientrpc-api.txt" rel="nofollow"> View page source</a>
</li>
</ul>
<hr/>
</div>
<div role="main" class="document" itemscope="itemscope" itemtype="http://schema.org/Article">
<div itemprop="articleBody">
<div class="section" id="client-rpc-api">
<h1>Client RPC API<a class="headerlink" href="#client-rpc-api" title="Permalink to this headline"></a></h1>
<p>In this tutorial we will build a simple command line utility that connects to a node and dumps the transaction graph to
the standard output. We will then put some simple visualisation on top. For an explanation on how the RPC works see
<a class="reference internal" href="clientrpc.html"><span class="doc">Client RPC</span></a>.</p>
<p>We start off by connecting to the node itself. For the purposes of the tutorial we will run the Trader demo on some
local port and connect to the Buyer side. We will pass in the address as a command line argument. To connect to the node
we also need to access the certificates of the node, we will access the node&#8217;s <code class="docutils literal"><span class="pre">certificates</span></code> directory directly.</p>
<div class="highlight-kotlin"><div class="highlight"><pre><span></span><span class="k">enum</span> <span class="k">class</span> <span class="nc">PrintOrVisualise</span> <span class="p">{</span>
<span class="n">Print</span><span class="p">,</span>
<span class="n">Visualise</span>
<span class="p">}</span>
<span class="k">fun</span> <span class="nf">main</span><span class="p">(</span><span class="n">args</span><span class="p">:</span> <span class="n">Array</span><span class="p">&lt;</span><span class="n">String</span><span class="p">&gt;)</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="n">args</span><span class="p">.</span><span class="n">size</span> <span class="p">&lt;</span> <span class="m">2</span><span class="p">)</span> <span class="p">{</span>
<span class="k">throw</span> <span class="n">IllegalArgumentException</span><span class="p">(</span><span class="s">&quot;Usage: &lt;binary&gt; &lt;node address&gt; [Print|Visualise]&quot;</span><span class="p">)</span>
<span class="p">}</span>
<span class="k">val</span> <span class="py">nodeAddress</span> <span class="p">=</span> <span class="n">HostAndPort</span><span class="p">.</span><span class="n">fromString</span><span class="p">(</span><span class="n">args</span><span class="p">[</span><span class="m">0</span><span class="p">])</span>
<span class="k">val</span> <span class="py">printOrVisualise</span> <span class="p">=</span> <span class="n">PrintOrVisualise</span><span class="p">.</span><span class="n">valueOf</span><span class="p">(</span><span class="n">args</span><span class="p">[</span><span class="m">1</span><span class="p">])</span>
<span class="k">val</span> <span class="py">certificatesPath</span> <span class="p">=</span> <span class="n">Paths</span><span class="p">.</span><span class="k">get</span><span class="p">(</span><span class="s">&quot;build/trader-demo/buyer/certificates&quot;</span><span class="p">)</span>
</pre></div>
</div>
<p>Now we can connect to the node itself:</p>
<div class="highlight-kotlin"><div class="highlight"><pre><span></span> <span class="k">val</span> <span class="py">client</span> <span class="p">=</span> <span class="n">CordaRPCClient</span><span class="p">(</span><span class="n">nodeAddress</span><span class="p">,</span> <span class="n">certificatesPath</span><span class="p">)</span>
<span class="n">client</span><span class="p">.</span><span class="n">start</span><span class="p">()</span>
<span class="k">val</span> <span class="py">proxy</span> <span class="p">=</span> <span class="n">client</span><span class="p">.</span><span class="n">proxy</span><span class="p">()</span>
</pre></div>
</div>
<p><code class="docutils literal"><span class="pre">proxy</span></code> now exposes the full RPC interface of the node:</p>
<div class="highlight-kotlin"><div class="highlight"><pre><span></span> <span class="cm">/**</span>
<span class="cm"> * Returns a pair of currently in-progress state machine infos and an observable of future state machine adds/removes.</span>
<span class="cm"> */</span>
<span class="n">@RPCReturnsObservables</span>
<span class="k">fun</span> <span class="nf">stateMachinesAndUpdates</span><span class="p">():</span> <span class="n">Pair</span><span class="p">&lt;</span><span class="n">List</span><span class="p">&lt;</span><span class="n">StateMachineInfo</span><span class="p">&gt;,</span> <span class="n">Observable</span><span class="p">&lt;</span><span class="n">StateMachineUpdate</span><span class="p">&gt;&gt;</span>
<span class="cm">/**</span>
<span class="cm"> * Returns a pair of head states in the vault and an observable of future updates to the vault.</span>
<span class="cm"> */</span>
<span class="n">@RPCReturnsObservables</span>
<span class="k">fun</span> <span class="nf">vaultAndUpdates</span><span class="p">():</span> <span class="n">Pair</span><span class="p">&lt;</span><span class="n">List</span><span class="p">&lt;</span><span class="n">StateAndRef</span><span class="p">&lt;</span><span class="n">ContractState</span><span class="p">&gt;&gt;,</span> <span class="n">Observable</span><span class="p">&lt;</span><span class="n">Vault</span><span class="p">.</span><span class="n">Update</span><span class="p">&gt;&gt;</span>
<span class="cm">/**</span>
<span class="cm"> * Returns a pair of all recorded transactions and an observable of future recorded ones.</span>
<span class="cm"> */</span>
<span class="n">@RPCReturnsObservables</span>
<span class="k">fun</span> <span class="nf">verifiedTransactions</span><span class="p">():</span> <span class="n">Pair</span><span class="p">&lt;</span><span class="n">List</span><span class="p">&lt;</span><span class="n">SignedTransaction</span><span class="p">&gt;,</span> <span class="n">Observable</span><span class="p">&lt;</span><span class="n">SignedTransaction</span><span class="p">&gt;&gt;</span>
<span class="cm">/**</span>
<span class="cm"> * Returns a snapshot list of existing state machine id - recorded transaction hash mappings, and a stream of future</span>
<span class="cm"> * such mappings as well.</span>
<span class="cm"> */</span>
<span class="n">@RPCReturnsObservables</span>
<span class="k">fun</span> <span class="nf">stateMachineRecordedTransactionMapping</span><span class="p">():</span> <span class="n">Pair</span><span class="p">&lt;</span><span class="n">List</span><span class="p">&lt;</span><span class="n">StateMachineTransactionMapping</span><span class="p">&gt;,</span> <span class="n">Observable</span><span class="p">&lt;</span><span class="n">StateMachineTransactionMapping</span><span class="p">&gt;&gt;</span>
<span class="cm">/**</span>
<span class="cm"> * Executes the given command, possibly triggering cash creation etc.</span>
<span class="cm"> * TODO: The signature of this is weird because it&#39;s the remains of an old service call, we should have a call for each command instead.</span>
<span class="cm"> */</span>
<span class="k">fun</span> <span class="nf">executeCommand</span><span class="p">(</span><span class="n">command</span><span class="p">:</span> <span class="n">ClientToServiceCommand</span><span class="p">):</span> <span class="n">TransactionBuildResult</span>
</pre></div>
</div>
<p>The one we need in order to dump the transaction graph is <code class="docutils literal"><span class="pre">verifiedTransactions</span></code>. The type signature tells us that the
RPC will return a list of transactions and an Observable stream. This is a general pattern, we query some data and the
node will return the current snapshot and future updates done to it.</p>
<div class="highlight-kotlin"><div class="highlight"><pre><span></span> val (transactions: List&lt;SignedTransaction&gt;, futureTransactions: Observable&lt;SignedTransaction&gt;) = proxy.verifiedTransactions()
</pre></div>
</div>
<p>The graph will be defined by nodes and edges between them. Each node represents a transaction and edges represent
output-input relations. For now let&#8217;s just print <code class="docutils literal"><span class="pre">NODE</span> <span class="pre">&lt;txhash&gt;</span></code> for the former and <code class="docutils literal"><span class="pre">EDGE</span> <span class="pre">&lt;txhash&gt;</span> <span class="pre">&lt;txhash&gt;</span></code> for the
latter.</p>
<div class="highlight-kotlin"><div class="highlight"><pre><span></span> <span class="k">when</span> <span class="p">(</span><span class="n">printOrVisualise</span><span class="p">)</span> <span class="p">{</span>
<span class="n">PrintOrVisualise</span><span class="p">.</span><span class="n">Print</span> <span class="p">-&gt;</span> <span class="p">{</span>
<span class="n">futureTransactions</span><span class="p">.</span><span class="n">startWith</span><span class="p">(</span><span class="n">transactions</span><span class="p">).</span><span class="n">subscribe</span> <span class="p">{</span> <span class="n">transaction</span> <span class="p">-&gt;</span>
<span class="n">println</span><span class="p">(</span><span class="s">&quot;NODE ${transaction.id}&quot;</span><span class="p">)</span>
<span class="n">transaction</span><span class="p">.</span><span class="n">tx</span><span class="p">.</span><span class="n">inputs</span><span class="p">.</span><span class="n">forEach</span> <span class="p">{</span> <span class="n">input</span> <span class="p">-&gt;</span>
<span class="n">println</span><span class="p">(</span><span class="s">&quot;EDGE ${input.txhash} ${transaction.id}&quot;</span><span class="p">)</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="n">CompletableFuture</span><span class="p">&lt;</span><span class="n">Unit</span><span class="p">&gt;().</span><span class="k">get</span><span class="p">()</span> <span class="c1">// block indefinitely</span>
<span class="p">}</span>
</pre></div>
</div>
<p>Now we can start the trader demo as per described in <a class="reference internal" href="running-the-demos.html"><span class="doc">Running the demos</span></a>:</p>
<div class="highlight-kotlin"><div class="highlight"><pre><span></span># Build the demo
./gradlew installDist
# Start the buyer
./build/install/r3prototyping/bin/trader-demo --role=BUYER
</pre></div>
</div>
<p>In another terminal we can connect to it with our client:</p>
<div class="highlight-kotlin"><div class="highlight"><pre><span></span># Connect to localhost:31337
./docs/source/example-code/build/install/docs/source/example-code/bin/client-rpc-tutorial localhost:31337 Print
</pre></div>
</div>
<p>We should see some <code class="docutils literal"><span class="pre">NODE</span></code>-s printed. This is because the buyer self-issues some cash for the demo.
Unless we ran the seller before we shouldn&#8217;t see any <code class="docutils literal"><span class="pre">EDGE</span></code>-s because the cash hasn&#8217;t been spent yet.</p>
<p>In another terminal we can now start the seller:</p>
<div class="highlight-kotlin"><div class="highlight"><pre><span></span># Start sellers in a loop
for i in {0..9} ; do ./build/install/r3prototyping/bin/trader-demo --role=SELLER ; done
</pre></div>
</div>
<p>We should start seeing new <code class="docutils literal"><span class="pre">NODE</span></code>-s and <code class="docutils literal"><span class="pre">EDGE</span></code>-s appearing.</p>
<p>Now let&#8217;s try to visualise the transaction graph. We will use a graph drawing library called <a class="reference external" href="http://graphstream-project.org/">graphstream</a></p>
<div class="highlight-kotlin"><div class="highlight"><pre><span></span> <span class="n">PrintOrVisualise</span><span class="p">.</span><span class="n">Visualise</span> <span class="p">-&gt;</span> <span class="p">{</span>
<span class="k">val</span> <span class="py">graph</span> <span class="p">=</span> <span class="n">SingleGraph</span><span class="p">(</span><span class="s">&quot;transactions&quot;</span><span class="p">)</span>
<span class="n">transactions</span><span class="p">.</span><span class="n">forEach</span> <span class="p">{</span> <span class="n">transaction</span> <span class="p">-&gt;</span>
<span class="n">graph</span><span class="p">.</span><span class="n">addNode</span><span class="p">&lt;</span><span class="n">Node</span><span class="p">&gt;(</span><span class="s">&quot;${transaction.id}&quot;</span><span class="p">)</span>
<span class="p">}</span>
<span class="n">transactions</span><span class="p">.</span><span class="n">forEach</span> <span class="p">{</span> <span class="n">transaction</span> <span class="p">-&gt;</span>
<span class="n">transaction</span><span class="p">.</span><span class="n">tx</span><span class="p">.</span><span class="n">inputs</span><span class="p">.</span><span class="n">forEach</span> <span class="p">{</span> <span class="n">ref</span> <span class="p">-&gt;</span>
<span class="n">graph</span><span class="p">.</span><span class="n">addEdge</span><span class="p">&lt;</span><span class="n">Edge</span><span class="p">&gt;(</span><span class="s">&quot;$ref&quot;</span><span class="p">,</span> <span class="s">&quot;${ref.txhash}&quot;</span><span class="p">,</span> <span class="s">&quot;${transaction.id}&quot;</span><span class="p">)</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="n">futureTransactions</span><span class="p">.</span><span class="n">subscribe</span> <span class="p">{</span> <span class="n">transaction</span> <span class="p">-&gt;</span>
<span class="n">graph</span><span class="p">.</span><span class="n">addNode</span><span class="p">&lt;</span><span class="n">Node</span><span class="p">&gt;(</span><span class="s">&quot;${transaction.id}&quot;</span><span class="p">)</span>
<span class="n">transaction</span><span class="p">.</span><span class="n">tx</span><span class="p">.</span><span class="n">inputs</span><span class="p">.</span><span class="n">forEach</span> <span class="p">{</span> <span class="n">ref</span> <span class="p">-&gt;</span>
<span class="n">graph</span><span class="p">.</span><span class="n">addEdge</span><span class="p">&lt;</span><span class="n">Edge</span><span class="p">&gt;(</span><span class="s">&quot;${ref}&quot;</span><span class="p">,</span> <span class="s">&quot;${ref.txhash}&quot;</span><span class="p">,</span> <span class="s">&quot;${transaction.id}&quot;</span><span class="p">)</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="n">graph</span><span class="p">.</span><span class="n">display</span><span class="p">()</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
</pre></div>
</div>
<p>If we run the client with <code class="docutils literal"><span class="pre">Visualise</span></code> we should see a simple graph being drawn as new transactions are being created
by the seller runs.</p>
<p>That&#8217;s it! We saw how to connect to the node and stream data from it.</p>
</div>
</div>
</div>
<footer>
<div class="rst-footer-buttons" role="navigation" aria-label="footer navigation">
<a href="protocol-state-machines.html" class="btn btn-neutral float-right" title="Protocol state machines" accesskey="n">Next <span class="fa fa-arrow-circle-right"></span></a>
<a href="tutorial-test-dsl.html" class="btn btn-neutral" title="Writing a contract test" accesskey="p"><span class="fa fa-arrow-circle-left"></span> Previous</a>
</div>
<hr/>
<div role="contentinfo">
<p>
&copy; Copyright 2016, Distributed Ledger Group, LLC.
</p>
</div>
Built with <a href="http://sphinx-doc.org/">Sphinx</a> using a <a href="https://github.com/snide/sphinx_rtd_theme">theme</a> provided by <a href="https://readthedocs.org">Read the Docs</a>.
</footer>
</div>
</div>
</section>
</div>
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT:'./',
VERSION:'latest',
COLLAPSE_INDEX:false,
FILE_SUFFIX:'.html',
HAS_SOURCE: true
};
</script>
<script type="text/javascript" src="_static/jquery.js"></script>
<script type="text/javascript" src="_static/underscore.js"></script>
<script type="text/javascript" src="_static/doctools.js"></script>
<script type="text/javascript" src="_static/js/theme.js"></script>
<script type="text/javascript">
jQuery(function () {
SphinxRtdTheme.StickyNav.enable();
});
</script>
</body>
</html>