{"action":"created","comment":{"url":"https://api.github.com/repos/buckie/juno/pulls/comments/59457272","id":59457272,"diff_hunk":"@@ -0,0 +1,125 @@\n+{-# LANGUAGE OverloadedStrings #-}\n+\n+module Apps.Juno.ApiHandlers (\n+                            createAccount\n+                           ,adjustAccount\n+                           ,transactAPI\n+                           ,ledgerQueryAPI\n+                           ,cmdBatch\n+                           ) where\n+\n+import           Control.Concurrent.Chan.Unagi\n+import           Control.Monad.IO.Class (liftIO)\n+\n+import qualified Data.ByteString.Lazy.Char8 as BLC\n+import qualified Data.ByteString.Char8 as BSC\n+import qualified Data.Text as T\n+import           Data.Maybe (catMaybes)\n+\n+import           Snap.Core\n+import           Data.Aeson (encode)\n+import qualified Data.Aeson as JSON\n+\n+import           Apps.Juno.JsonTypes\n+import           Juno.Runtime.Types hiding (CommandBatch)\n+import           Juno.Consensus.ByzRaft.Client (\n+                                                CommandMVarMap\n+                                               ,setNextCmdRequestId\n+                                               )\n+\n+\n+import           Apps.Juno.Ledger\n+\n+apiWrapper :: InChan (RequestId, [CommandEntry]) -> CommandMVarMap ->  (BLC.ByteString -> Either BLC.ByteString [CommandEntry]) -> Snap ()\n+apiWrapper toCommands cmdStatusMap requestHandler = do\n+   modifyResponse $ setHeader \"Content-Type\" \"application/json\"\n+   reqBytes <- (readRequestBody 1000000)\n+   case (requestHandler reqBytes) of\n+     Right cmdEntries -> do\n+         reqestId@(RequestId rId) <- liftIO $ setNextCmdRequestId cmdStatusMap\n+         liftIO $ writeChan toCommands (reqestId, cmdEntries)\n+         (writeBS . BLC.toStrict . JSON.encode) $ commandResponseSuccess ((T.pack . show) rId) \"\"\n+     Left err -> (writeBS . BLC.toStrict) $ err\n+\n+-- create an account returns cmdId see: juno/jmeter/juno_API_jmeter_test.jmx\n+createAccount :: InChan (RequestId, [CommandEntry]) -> CommandMVarMap -> Snap ()\n+createAccount toCommands cmdStatusMap =\n+    apiWrapper toCommands cmdStatusMap createAccountReqHandler\n+\n+-- Adjusts Account (negative, positive) returns cmdIds: juno/jmeter/juno_API_jmeter_test.jmx\n+adjustAccount :: InChan (RequestId, [CommandEntry]) -> CommandMVarMap -> Snap ()\n+adjustAccount toCommands cmdStatusMap =\n+    apiWrapper toCommands cmdStatusMap adjustAccoutReqHandler\n+\n+-- juno/jmeter/juno_API_jmeter_test.jmx\n+-- accept hopercommands transfer(000->100->101->102->103->003, 100%1)\n+transactAPI :: InChan (RequestId, [CommandEntry]) -> CommandMVarMap -> Snap ()\n+transactAPI toCommands cmdStatusMap =\n+   apiWrapper toCommands cmdStatusMap transactReqHandler\n+\n+ledgerQueryAPI :: InChan (RequestId, [CommandEntry]) -> CommandMVarMap -> Snap ()\n+ledgerQueryAPI toCommands cmdStatusMap =\n+    apiWrapper toCommands cmdStatusMap ledgerQueryReqHandler\n+\n+-- receives a list of commands\n+-- {\"payload\":{\"cmds\": [\"{\\\"account\\\":\\\"WATER\\\"}\", \"{\\\"account\\\":\\\"TSLA\\\"}\"},\"digest\":{\"hash\":\"hashy\",\"key\":\"mykey\"}}\n+cmdBatch :: InChan (RequestId, [CommandEntry]) -> CommandMVarMap -> Snap ()\n+cmdBatch toCommands cmdStatusMap =\n+    apiWrapper toCommands cmdStatusMap cmdBatchHandler\n+\n+\n+-- | Handlers to deal with the incomming request bytes and either create the correct\n+--   [ComandEntry] ByteString or the JSON error message ByteString\n+createAccountReqHandler :: BLC.ByteString -> Either BLC.ByteString [CommandEntry]\n+createAccountReqHandler bs =\n+     case (JSON.decode bs) of\n+       Just (CreateAccountRequest (AccountPayload acct) _) ->\n+           Right [CommandEntry $ createAccountBS' $ T.unpack acct]\n+       Nothing ->\n+           Left $ (JSON.encode $ commandResponseFailure \"\" \"Malformed input, could not decode input JSON.\")\n+ where\n+   createAccountBS' acct = BSC.pack $ \"CreateAccount \" ++ acct\n+\n+adjustAccoutReqHandler :: BLC.ByteString -> Either BLC.ByteString [CommandEntry]\n+adjustAccoutReqHandler bs =\n+  case (JSON.decode bs) of\n+     Just (AccountAdjustRequest (AccountAdjustPayload acct amt) _) ->\n+         Right [CommandEntry $ adjustAccountBS acct amt]\n+     Nothing ->\n+         Left $ (JSON.encode $ commandResponseFailure \"\" \"Malformed input, could not decode input JSON.\")\n+ where\n+  adjustAccountBS acct amt = BSC.pack $ \"AdjustAccount \" ++ T.unpack acct ++ \" \" ++ show (toRational amt)\n+\n+transactReqHandler :: BLC.ByteString -> Either BLC.ByteString [CommandEntry]\n+transactReqHandler bs =\n+    case (JSON.decode bs) of\n+      Just (TransactRequest (TransactBody code body) _) ->\n+          Right [CommandEntry $ BSC.pack $ T.unpack code]\n+      Nothing ->\n+          Left $ (JSON.encode $ commandResponseFailure \"\" \"Malformed input, could not decode input JSON.\")\n+\n+ledgerQueryReqHandler :: BLC.ByteString -> Either BLC.ByteString [CommandEntry]\n+ledgerQueryReqHandler bs =\n+    case (JSON.decode bs) of\n+      Just (LedgerQueryRequest (LedgerQueryBody (QueryJson acct tx sender receiver)) _) -> do\n+         let mByBoth = (ByAcctName Both) <$> acct\n+         let mSwiftId =  BySwiftId <$> tx\n+         let mBySender = (ByAcctName Sender) <$> sender\n+         let mByReceiver = (ByAcctName Receiver) <$> receiver\n+         let query = And $ catMaybes [ mSwiftId, mBySender, mByReceiver, mByBoth ]\n+         Right $[CommandEntry $ BLC.toStrict $ encode query]","path":"src/Apps/Juno/ApiHandlers.hs","position":110,"original_position":110,"commit_id":"38ae98b51f79ce727b23c7cfbe6ecf6f44b38cf0","original_commit_id":"38ae98b51f79ce727b23c7cfbe6ecf6f44b38cf0","user":{"login":"buckie","id":1953196,"avatar_url":"https://avatars.githubusercontent.com/u/1953196?v=3","gravatar_id":"","url":"https://api.github.com/users/buckie","html_url":"https://github.com/buckie","followers_url":"https://api.github.com/users/buckie/followers","following_url":"https://api.github.com/users/buckie/following{/other_user}","gists_url":"https://api.github.com/users/buckie/gists{/gist_id}","starred_url":"https://api.github.com/users/buckie/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/buckie/subscriptions","organizations_url":"https://api.github.com/users/buckie/orgs","repos_url":"https://api.github.com/users/buckie/repos","events_url":"https://api.github.com/users/buckie/events{/privacy}","received_events_url":"https://api.github.com/users/buckie/received_events","type":"User","site_admin":false},"body":"redundant `$`","created_at":"2016-04-12T21:28:57Z","updated_at":"2016-04-12T21:28:57Z","html_url":"https://github.com/buckie/juno/pull/6#discussion_r59457272","pull_request_url":"https://api.github.com/repos/buckie/juno/pulls/6","_links":{"self":{"href":"https://api.github.com/repos/buckie/juno/pulls/comments/59457272"},"html":{"href":"https://github.com/buckie/juno/pull/6#discussion_r59457272"},"pull_request":{"href":"https://api.github.com/repos/buckie/juno/pulls/6"}}},"pull_request":{"url":"https://api.github.com/repos/buckie/juno/pulls/6","id":66221653,"html_url":"https://github.com/buckie/juno/pull/6","diff_url":"https://github.com/buckie/juno/pull/6.diff","patch_url":"https://github.com/buckie/juno/pull/6.patch","issue_url":"https://api.github.com/repos/buckie/juno/issues/6","number":6,"state":"open","locked":false,"title":"API cleanup: v1/cmd/batch endpoint.","user":{"login":"libby","id":755198,"avatar_url":"https://avatars.githubusercontent.com/u/755198?v=3","gravatar_id":"","url":"https://api.github.com/users/libby","html_url":"https://github.com/libby","followers_url":"https://api.github.com/users/libby/followers","following_url":"https://api.github.com/users/libby/following{/other_user}","gists_url":"https://api.github.com/users/libby/gists{/gist_id}","starred_url":"https://api.github.com/users/libby/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/libby/subscriptions","organizations_url":"https://api.github.com/users/libby/orgs","repos_url":"https://api.github.com/users/libby/repos","events_url":"https://api.github.com/users/libby/events{/privacy}","received_events_url":"https://api.github.com/users/libby/received_events","type":"User","site_admin":false},"body":"Adding a transact endpoint to support a list of commands, and breaking out API functions into their own module, adding an API wrapper function to encapsulate repeated code request handling.","created_at":"2016-04-12T20:23:06Z","updated_at":"2016-04-12T21:28:57Z","closed_at":null,"merged_at":null,"merge_commit_sha":"dc609fc8d24250c9e0bad76ca53766cf1f210050","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/buckie/juno/pulls/6/commits","review_comments_url":"https://api.github.com/repos/buckie/juno/pulls/6/comments","review_comment_url":"https://api.github.com/repos/buckie/juno/pulls/comments{/number}","comments_url":"https://api.github.com/repos/buckie/juno/issues/6/comments","statuses_url":"https://api.github.com/repos/buckie/juno/statuses/38ae98b51f79ce727b23c7cfbe6ecf6f44b38cf0","head":{"label":"buckie:api-cleanup","ref":"api-cleanup","sha":"38ae98b51f79ce727b23c7cfbe6ecf6f44b38cf0","user":{"login":"buckie","id":1953196,"avatar_url":"https://avatars.githubusercontent.com/u/1953196?v=3","gravatar_id":"","url":"https://api.github.com/users/buckie","html_url":"https://github.com/buckie","followers_url":"https://api.github.com/users/buckie/followers","following_url":"https://api.github.com/users/buckie/following{/other_user}","gists_url":"https://api.github.com/users/buckie/gists{/gist_id}","starred_url":"https://api.github.com/users/buckie/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/buckie/subscriptions","organizations_url":"https://api.github.com/users/buckie/orgs","repos_url":"https://api.github.com/users/buckie/repos","events_url":"https://api.github.com/users/buckie/events{/privacy}","received_events_url":"https://api.github.com/users/buckie/received_events","type":"User","site_admin":false},"repo":{"id":52640293,"name":"juno","full_name":"buckie/juno","owner":{"login":"buckie","id":1953196,"avatar_url":"https://avatars.githubusercontent.com/u/1953196?v=3","gravatar_id":"","url":"https://api.github.com/users/buckie","html_url":"https://github.com/buckie","followers_url":"https://api.github.com/users/buckie/followers","following_url":"https://api.github.com/users/buckie/following{/other_user}","gists_url":"https://api.github.com/users/buckie/gists{/gist_id}","starred_url":"https://api.github.com/users/buckie/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/buckie/subscriptions","organizations_url":"https://api.github.com/users/buckie/orgs","repos_url":"https://api.github.com/users/buckie/repos","events_url":"https://api.github.com/users/buckie/events{/privacy}","received_events_url":"https://api.github.com/users/buckie/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/buckie/juno","description":"Smart Contracts Running on a BFT Hardened Raft","fork":false,"url":"https://api.github.com/repos/buckie/juno","forks_url":"https://api.github.com/repos/buckie/juno/forks","keys_url":"https://api.github.com/repos/buckie/juno/keys{/key_id}","collaborators_url":"https://api.github.com/repos/buckie/juno/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/buckie/juno/teams","hooks_url":"https://api.github.com/repos/buckie/juno/hooks","issue_events_url":"https://api.github.com/repos/buckie/juno/issues/events{/number}","events_url":"https://api.github.com/repos/buckie/juno/events","assignees_url":"https://api.github.com/repos/buckie/juno/assignees{/user}","branches_url":"https://api.github.com/repos/buckie/juno/branches{/branch}","tags_url":"https://api.github.com/repos/buckie/juno/tags","blobs_url":"https://api.github.com/repos/buckie/juno/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/buckie/juno/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/buckie/juno/git/refs{/sha}","trees_url":"https://api.github.com/repos/buckie/juno/git/trees{/sha}","statuses_url":"https://api.github.com/repos/buckie/juno/statuses/{sha}","languages_url":"https://api.github.com/repos/buckie/juno/languages","stargazers_url":"https://api.github.com/repos/buckie/juno/stargazers","contributors_url":"https://api.github.com/repos/buckie/juno/contributors","subscribers_url":"https://api.github.com/repos/buckie/juno/subscribers","subscription_url":"https://api.github.com/repos/buckie/juno/subscription","commits_url":"https://api.github.com/repos/buckie/juno/commits{/sha}","git_commits_url":"https://api.github.com/repos/buckie/juno/git/commits{/sha}","comments_url":"https://api.github.com/repos/buckie/juno/comments{/number}","issue_comment_url":"https://api.github.com/repos/buckie/juno/issues/comments{/number}","contents_url":"https://api.github.com/repos/buckie/juno/contents/{+path}","compare_url":"https://api.github.com/repos/buckie/juno/compare/{base}...{head}","merges_url":"https://api.github.com/repos/buckie/juno/merges","archive_url":"https://api.github.com/repos/buckie/juno/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/buckie/juno/downloads","issues_url":"https://api.github.com/repos/buckie/juno/issues{/number}","pulls_url":"https://api.github.com/repos/buckie/juno/pulls{/number}","milestones_url":"https://api.github.com/repos/buckie/juno/milestones{/number}","notifications_url":"https://api.github.com/repos/buckie/juno/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/buckie/juno/labels{/name}","releases_url":"https://api.github.com/repos/buckie/juno/releases{/id}","deployments_url":"https://api.github.com/repos/buckie/juno/deployments","created_at":"2016-02-26T23:46:40Z","updated_at":"2016-04-08T14:01:15Z","pushed_at":"2016-04-12T20:23:06Z","git_url":"git://github.com/buckie/juno.git","ssh_url":"git@github.com:buckie/juno.git","clone_url":"https://github.com/buckie/juno.git","svn_url":"https://github.com/buckie/juno","homepage":null,"size":1803,"stargazers_count":231,"watchers_count":231,"language":"Haskell","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":20,"mirror_url":null,"open_issues_count":3,"forks":20,"open_issues":3,"watchers":231,"default_branch":"master"}},"base":{"label":"buckie:develop","ref":"develop","sha":"d91e370b485cfbcce4b2e2f7e89a7a6359ad042e","user":{"login":"buckie","id":1953196,"avatar_url":"https://avatars.githubusercontent.com/u/1953196?v=3","gravatar_id":"","url":"https://api.github.com/users/buckie","html_url":"https://github.com/buckie","followers_url":"https://api.github.com/users/buckie/followers","following_url":"https://api.github.com/users/buckie/following{/other_user}","gists_url":"https://api.github.com/users/buckie/gists{/gist_id}","starred_url":"https://api.github.com/users/buckie/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/buckie/subscriptions","organizations_url":"https://api.github.com/users/buckie/orgs","repos_url":"https://api.github.com/users/buckie/repos","events_url":"https://api.github.com/users/buckie/events{/privacy}","received_events_url":"https://api.github.com/users/buckie/received_events","type":"User","site_admin":false},"repo":{"id":52640293,"name":"juno","full_name":"buckie/juno","owner":{"login":"buckie","id":1953196,"avatar_url":"https://avatars.githubusercontent.com/u/1953196?v=3","gravatar_id":"","url":"https://api.github.com/users/buckie","html_url":"https://github.com/buckie","followers_url":"https://api.github.com/users/buckie/followers","following_url":"https://api.github.com/users/buckie/following{/other_user}","gists_url":"https://api.github.com/users/buckie/gists{/gist_id}","starred_url":"https://api.github.com/users/buckie/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/buckie/subscriptions","organizations_url":"https://api.github.com/users/buckie/orgs","repos_url":"https://api.github.com/users/buckie/repos","events_url":"https://api.github.com/users/buckie/events{/privacy}","received_events_url":"https://api.github.com/users/buckie/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/buckie/juno","description":"Smart Contracts Running on a BFT Hardened Raft","fork":false,"url":"https://api.github.com/repos/buckie/juno","forks_url":"https://api.github.com/repos/buckie/juno/forks","keys_url":"https://api.github.com/repos/buckie/juno/keys{/key_id}","collaborators_url":"https://api.github.com/repos/buckie/juno/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/buckie/juno/teams","hooks_url":"https://api.github.com/repos/buckie/juno/hooks","issue_events_url":"https://api.github.com/repos/buckie/juno/issues/events{/number}","events_url":"https://api.github.com/repos/buckie/juno/events","assignees_url":"https://api.github.com/repos/buckie/juno/assignees{/user}","branches_url":"https://api.github.com/repos/buckie/juno/branches{/branch}","tags_url":"https://api.github.com/repos/buckie/juno/tags","blobs_url":"https://api.github.com/repos/buckie/juno/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/buckie/juno/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/buckie/juno/git/refs{/sha}","trees_url":"https://api.github.com/repos/buckie/juno/git/trees{/sha}","statuses_url":"https://api.github.com/repos/buckie/juno/statuses/{sha}","languages_url":"https://api.github.com/repos/buckie/juno/languages","stargazers_url":"https://api.github.com/repos/buckie/juno/stargazers","contributors_url":"https://api.github.com/repos/buckie/juno/contributors","subscribers_url":"https://api.github.com/repos/buckie/juno/subscribers","subscription_url":"https://api.github.com/repos/buckie/juno/subscription","commits_url":"https://api.github.com/repos/buckie/juno/commits{/sha}","git_commits_url":"https://api.github.com/repos/buckie/juno/git/commits{/sha}","comments_url":"https://api.github.com/repos/buckie/juno/comments{/number}","issue_comment_url":"https://api.github.com/repos/buckie/juno/issues/comments{/number}","contents_url":"https://api.github.com/repos/buckie/juno/contents/{+path}","compare_url":"https://api.github.com/repos/buckie/juno/compare/{base}...{head}","merges_url":"https://api.github.com/repos/buckie/juno/merges","archive_url":"https://api.github.com/repos/buckie/juno/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/buckie/juno/downloads","issues_url":"https://api.github.com/repos/buckie/juno/issues{/number}","pulls_url":"https://api.github.com/repos/buckie/juno/pulls{/number}","milestones_url":"https://api.github.com/repos/buckie/juno/milestones{/number}","notifications_url":"https://api.github.com/repos/buckie/juno/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/buckie/juno/labels{/name}","releases_url":"https://api.github.com/repos/buckie/juno/releases{/id}","deployments_url":"https://api.github.com/repos/buckie/juno/deployments","created_at":"2016-02-26T23:46:40Z","updated_at":"2016-04-08T14:01:15Z","pushed_at":"2016-04-12T20:23:06Z","git_url":"git://github.com/buckie/juno.git","ssh_url":"git@github.com:buckie/juno.git","clone_url":"https://github.com/buckie/juno.git","svn_url":"https://github.com/buckie/juno","homepage":null,"size":1803,"stargazers_count":231,"watchers_count":231,"language":"Haskell","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":20,"mirror_url":null,"open_issues_count":3,"forks":20,"open_issues":3,"watchers":231,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/buckie/juno/pulls/6"},"html":{"href":"https://github.com/buckie/juno/pull/6"},"issue":{"href":"https://api.github.com/repos/buckie/juno/issues/6"},"comments":{"href":"https://api.github.com/repos/buckie/juno/issues/6/comments"},"review_comments":{"href":"https://api.github.com/repos/buckie/juno/pulls/6/comments"},"review_comment":{"href":"https://api.github.com/repos/buckie/juno/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/buckie/juno/pulls/6/commits"},"statuses":{"href":"https://api.github.com/repos/buckie/juno/statuses/38ae98b51f79ce727b23c7cfbe6ecf6f44b38cf0"}}}}