1+ package com .example .server ;
2+
3+ import com .example .flow .ExampleFlow ;
4+ import com .example .state .IOUState ;
5+ import com .fasterxml .jackson .databind .ObjectMapper ;
6+ import net .corda .client .jackson .JacksonSupport ;
7+ import net .corda .core .contracts .*;
8+ import net .corda .core .identity .CordaX500Name ;
9+ import net .corda .core .identity .Party ;
10+ import net .corda .core .messaging .CordaRPCOps ;
11+ import net .corda .core .node .NodeInfo ;
12+ import net .corda .core .transactions .SignedTransaction ;
13+
14+ import java .time .LocalDateTime ;
15+ import java .time .ZoneId ;
16+ import java .util .*;
17+ import org .bouncycastle .asn1 .x500 .X500Name ;
18+ import org .bouncycastle .asn1 .x500 .style .BCStyle ;
19+ import org .slf4j .Logger ;
20+ import org .slf4j .LoggerFactory ;
21+ import org .springframework .context .annotation .Bean ;
22+ import org .springframework .context .annotation .Configuration ;
23+ import org .springframework .http .HttpStatus ;
24+ import org .springframework .http .ResponseEntity ;
25+ import org .springframework .web .bind .annotation .*;
26+
27+ import javax .servlet .http .HttpServletRequest ;
28+ import java .util .stream .Collectors ;
29+ import java .util .stream .Stream ;
30+
31+ import static org .springframework .http .MediaType .APPLICATION_JSON_VALUE ;
32+ import static org .springframework .http .MediaType .TEXT_PLAIN_VALUE ;
33+
34+ /**
35+ * Define your API endpoints here.
36+ */
37+ @ RestController
38+ @ RequestMapping ("/api/example/" ) // The paths for HTTP requests are relative to this base path.
39+ public class MainController {
40+ private static final Logger logger = LoggerFactory .getLogger (RestController .class );
41+ private final CordaRPCOps proxy ;
42+ private final CordaX500Name me ;
43+
44+ public MainController (NodeRPCConnection rpc ) {
45+ this .proxy = rpc .getProxy ();
46+ this .me = proxy .nodeInfo ().getLegalIdentities ().get (0 ).getName ();
47+
48+ }
49+
50+ /** Helpers for filtering the network map cache. */
51+ public String toDisplayString (X500Name name ){
52+ return BCStyle .INSTANCE .toString (name );
53+ }
54+
55+ private boolean isNotary (NodeInfo nodeInfo ) {
56+ return !proxy .notaryIdentities ()
57+ .stream ().filter (el -> nodeInfo .isLegalIdentity (el ))
58+ .collect (Collectors .toList ()).isEmpty ();
59+ }
60+
61+ private boolean isMe (NodeInfo nodeInfo ){
62+ return nodeInfo .getLegalIdentities ().get (0 ).getName ().equals (me );
63+ }
64+
65+ private boolean isNetworkMap (NodeInfo nodeInfo ){
66+ return nodeInfo .getLegalIdentities ().get (0 ).getName ().getOrganisation ().equals ("Network Map Service" );
67+ }
68+
69+ @ Configuration
70+ class Plugin {
71+ @ Bean
72+ public ObjectMapper registerModule () {
73+ return JacksonSupport .createNonRpcMapper ();
74+ }
75+ }
76+
77+ @ GetMapping (value = "/status" , produces = TEXT_PLAIN_VALUE )
78+ private String status () {
79+ return "200" ;
80+ }
81+
82+ @ GetMapping (value = "/servertime" , produces = TEXT_PLAIN_VALUE )
83+ private String serverTime () {
84+ return (LocalDateTime .ofInstant (proxy .currentNodeTime (), ZoneId .of ("UTC" ))).toString ();
85+ }
86+
87+ @ GetMapping (value = "/addresses" , produces = TEXT_PLAIN_VALUE )
88+ private String addresses () {
89+ return proxy .nodeInfo ().getAddresses ().toString ();
90+ }
91+
92+ @ GetMapping (value = "/identities" , produces = TEXT_PLAIN_VALUE )
93+ private String identities () {
94+ return proxy .nodeInfo ().getLegalIdentities ().toString ();
95+ }
96+
97+ @ GetMapping (value = "/platformversion" , produces = TEXT_PLAIN_VALUE )
98+ private String platformVersion () {
99+ return Integer .toString (proxy .nodeInfo ().getPlatformVersion ());
100+ }
101+
102+ @ GetMapping (value = "/peers" , produces = APPLICATION_JSON_VALUE )
103+ public HashMap <String , List <String >> getPeers () {
104+ HashMap <String , List <String >> myMap = new HashMap <>();
105+
106+ // Find all nodes that are not notaries, ourself, or the network map.
107+ Stream <NodeInfo > filteredNodes = proxy .networkMapSnapshot ().stream ()
108+ .filter (el -> !isNotary (el ) && !isMe (el ) && !isNetworkMap (el ));
109+ // Get their names as strings
110+ List <String > nodeNames = filteredNodes .map (el -> el .getLegalIdentities ().get (0 ).getName ().toString ())
111+ .collect (Collectors .toList ());
112+
113+ myMap .put ("peers" , nodeNames );
114+ return myMap ;
115+ }
116+
117+ @ GetMapping (value = "/notaries" , produces = TEXT_PLAIN_VALUE )
118+ private String notaries () {
119+ return proxy .notaryIdentities ().toString ();
120+ }
121+
122+ @ GetMapping (value = "/flows" , produces = TEXT_PLAIN_VALUE )
123+ private String flows () {
124+ return proxy .registeredFlows ().toString ();
125+ }
126+
127+ @ GetMapping (value = "/states" , produces = TEXT_PLAIN_VALUE )
128+ private String states () {
129+ return proxy .vaultQuery (ContractState .class ).getStates ().toString ();
130+ }
131+
132+ @ GetMapping (value = "/me" ,produces = APPLICATION_JSON_VALUE )
133+ private HashMap <String , String > whoami (){
134+ HashMap <String , String > myMap = new HashMap <>();
135+ myMap .put ("me" , me .toString ());
136+ return myMap ;
137+ }
138+ @ GetMapping (value = "/ious" ,produces = APPLICATION_JSON_VALUE )
139+ public List <StateAndRef <IOUState >> getIOUs () {
140+ // Filter by state type: IOU.
141+ return proxy .vaultQuery (IOUState .class ).getStates ();
142+ }
143+
144+ @ PostMapping (value = "create-iou" , produces = TEXT_PLAIN_VALUE , headers = "Content-Type=application/x-www-form-urlencoded" )
145+ public ResponseEntity <String > issueIOU (HttpServletRequest request ) throws IllegalArgumentException {
146+
147+ int amount = Integer . valueOf (request .getParameter ("iouValue" ));
148+ String party = request .getParameter ("partyName" );
149+ // Get party objects for myself and the counterparty.
150+
151+ CordaX500Name partyX500Name = CordaX500Name .parse (party );
152+ Party otherParty = proxy .wellKnownPartyFromX500Name (partyX500Name );
153+
154+ // Create a new IOU state using the parameters given.
155+ try {
156+ // Start the IOUIssueFlow. We block and waits for the flow to return.
157+ SignedTransaction result = proxy .startTrackedFlowDynamic (ExampleFlow .Initiator .class , amount ,otherParty ).getReturnValue ().get ();
158+ // Return the response.
159+ return ResponseEntity
160+ .status (HttpStatus .CREATED )
161+ .body ("Transaction id " + result .getId () +" committed to ledger.\n " + result .getTx ().getOutput (0 ));
162+ // For the purposes of this demo app, we do not differentiate by exception type.
163+ } catch (Exception e ) {
164+ return ResponseEntity
165+ .status (HttpStatus .BAD_REQUEST )
166+ .body (e .getMessage ());
167+ }
168+ }
169+ /**
170+ * Displays all IOU states that only this node has been involved in.
171+ */
172+ @ GetMapping (value = "my-ious" ,produces = APPLICATION_JSON_VALUE )
173+ public ResponseEntity <List <StateAndRef <IOUState >>> getMyIOUs () {
174+ List <StateAndRef <IOUState >> myious = proxy .vaultQuery (IOUState .class ).getStates ().stream ().filter (
175+ it -> it .getState ().getData ().getLender ().equals (proxy .nodeInfo ().getLegalIdentities ().get (0 ))).collect (Collectors .toList ());
176+ return ResponseEntity .ok (myious );
177+ }
178+
179+
180+ }
0 commit comments