{"action":"created","comment":{"url":"https://api.github.com/repos/ripple/ripple-lib/pulls/comments/37367121","id":37367121,"diff_hunk":"@@ -28,25 +28,47 @@ function hashLedgerHeader(ledgerHeader) {\n   return common.core.Ledger.calculateLedgerHash(header);\n }\n \n-function computeLedgerHash(ledgerHeader: Object, transactions: Array<Object>\n-): string {\n-  if (transactions) {\n-    const txs = _.map(transactions, tx => {\n-      const mergeTx = _.assign({}, _.omit(tx, 'tx'), tx.tx || {});\n-      const renameMeta = _.assign({}, _.omit(mergeTx, 'meta'),\n-        tx.meta ? {metaData: tx.meta} : {});\n-      return renameMeta;\n-    });\n-    const ledger = common.core.Ledger.from_json({transactions: txs});\n-    const transactionHash = ledger.calc_tx_hash().to_hex();\n-    if (ledgerHeader.transaction_hash !== undefined\n-        && ledgerHeader.transaction_hash !== transactionHash) {\n-      throw new common.errors.ValidationError('transaction_hash in header'\n-        + ' does not match computed hash of transactions');\n-    }\n-    return hashLedgerHeader(_.assign({}, ledgerHeader, {transactionHash}));\n+function computeTransactionHash(ledger) {\n+  if (ledger.rawTransactions === undefined) {\n+    return ledger.transactionHash;\n   }\n-  return hashLedgerHeader(ledgerHeader);\n+  const transactions = JSON.parse(ledger.rawTransactions);\n+  const txs = _.map(transactions, tx => {\n+    const mergeTx = _.assign({}, _.omit(tx, 'tx'), tx.tx || {});\n+    const renameMeta = _.assign({}, _.omit(mergeTx, 'meta'),\n+      tx.meta ? {metaData: tx.meta} : {});\n+    return renameMeta;\n+  });\n+  const ledgerObject = common.core.Ledger.from_json({transactions: txs});\n+  const transactionHash = ledgerObject.calc_tx_hash().to_hex();\n+  if (ledger.transactionHash !== undefined\n+      && ledger.transactionHash !== transactionHash) {\n+    throw new common.errors.ValidationError('transactionHash in header'\n+      + ' does not match computed hash of transactions');\n+  }\n+  return transactionHash;\n+}\n+\n+function computeStateHash(ledger) {\n+  if (ledger.rawState === undefined) {\n+    return ledger.stateHash;\n+  }\n+  const state = JSON.parse(ledger.rawState);\n+  const ledgerObject = common.core.Ledger.from_json({accountState: state});\n+  const stateHash = ledgerObject.calc_account_hash().to_hex();\n+  if (ledger.stateHash !== undefined && ledger.stateHash !== stateHash) {\n+    throw new common.errors.ValidationError('stateHash in header'\n+      + ' does not match computed hash of state');\n+  }\n+  return stateHash;\n+}\n+\n+function computeLedgerHash(ledger: Object): string {","path":"src/api/offline/ledgerhash.js","position":66,"original_position":66,"commit_id":"1f54b3a0cf1511b4732c7e23110b0bad31199898","original_commit_id":"1f54b3a0cf1511b4732c7e23110b0bad31199898","user":{"login":"sublimator","id":525211,"avatar_url":"https://avatars.githubusercontent.com/u/525211?v=3","gravatar_id":"","url":"https://api.github.com/users/sublimator","html_url":"https://github.com/sublimator","followers_url":"https://api.github.com/users/sublimator/followers","following_url":"https://api.github.com/users/sublimator/following{/other_user}","gists_url":"https://api.github.com/users/sublimator/gists{/gist_id}","starred_url":"https://api.github.com/users/sublimator/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/sublimator/subscriptions","organizations_url":"https://api.github.com/users/sublimator/orgs","repos_url":"https://api.github.com/users/sublimator/repos","events_url":"https://api.github.com/users/sublimator/events{/privacy}","received_events_url":"https://api.github.com/users/sublimator/received_events","type":"User","site_admin":false},"body":"What I'm trying to get at is that there's this new ripple api which which\nhas a request/response interface speaking json primitives for parameters\nand return values that would allow it to be easily exported from an RPC\nserver.\n\nThere's exports like generateWallet, where the analogous rippled command\n\"wallet_create\" will only serve to local connections. computeLedgerHash\nseems somewhat in the same class. Both could feasibly be seen to be\nexported from a rippled (or a satellite app if rippled became p2p txn\nprocessing only) served json rpc API.\n\nBut there's little guys like isConnected, connect, disconnect which are\nclearly `client` routines.\n\nTake for example the getTransactions api, where it's conceivable people may\nwant an event handler to be executed for each page of transactions as they\ncome in to allow them to update a UI. They might build a wrapper around the\ngetTransactions service. That would be a `client` routine.\n\nAnd `errors`?\n\nI think if say in the src/api/index.js what are server and what are client\nroutines were clearly marked out, it would help communicate the ultimate\nintent of some of these apis one day being accessed via RPC which unless I\ngot confused somewhere is the goal?\n\nIt's getting a little weird to see things like\nRippleAPI.prototype.isValidAddress, (which would likely not be exported\nfrom a json rpc) sort of tacked on as a method, seemingly only because\nRippleAPI is currently the only namespace exported.\n","created_at":"2015-08-18T23:47:25Z","updated_at":"2015-08-18T23:47:25Z","html_url":"https://github.com/ripple/ripple-lib/pull/504#discussion_r37367121","pull_request_url":"https://api.github.com/repos/ripple/ripple-lib/pulls/504","_links":{"self":{"href":"https://api.github.com/repos/ripple/ripple-lib/pulls/comments/37367121"},"html":{"href":"https://github.com/ripple/ripple-lib/pull/504#discussion_r37367121"},"pull_request":{"href":"https://api.github.com/repos/ripple/ripple-lib/pulls/504"}}},"pull_request":{"url":"https://api.github.com/repos/ripple/ripple-lib/pulls/504","id":42505311,"html_url":"https://github.com/ripple/ripple-lib/pull/504","diff_url":"https://github.com/ripple/ripple-lib/pull/504.diff","patch_url":"https://github.com/ripple/ripple-lib/pull/504.patch","issue_url":"https://api.github.com/repos/ripple/ripple-lib/issues/504","number":504,"state":"closed","locked":false,"title":"Add getLedger method, remove getLedgerHeader method","user":{"login":"clark800","id":1238722,"avatar_url":"https://avatars.githubusercontent.com/u/1238722?v=3","gravatar_id":"","url":"https://api.github.com/users/clark800","html_url":"https://github.com/clark800","followers_url":"https://api.github.com/users/clark800/followers","following_url":"https://api.github.com/users/clark800/following{/other_user}","gists_url":"https://api.github.com/users/clark800/gists{/gist_id}","starred_url":"https://api.github.com/users/clark800/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/clark800/subscriptions","organizations_url":"https://api.github.com/users/clark800/orgs","repos_url":"https://api.github.com/users/clark800/repos","events_url":"https://api.github.com/users/clark800/events{/privacy}","received_events_url":"https://api.github.com/users/clark800/received_events","type":"User","site_admin":false},"body":"","created_at":"2015-08-14T22:51:31Z","updated_at":"2015-08-18T23:47:25Z","closed_at":"2015-08-18T17:01:23Z","merged_at":"2015-08-18T17:01:23Z","merge_commit_sha":"53dee34ac0091135d7eab04f7151a85a159cd1a6","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/ripple/ripple-lib/pulls/504/commits","review_comments_url":"https://api.github.com/repos/ripple/ripple-lib/pulls/504/comments","review_comment_url":"https://api.github.com/repos/ripple/ripple-lib/pulls/comments{/number}","comments_url":"https://api.github.com/repos/ripple/ripple-lib/issues/504/comments","statuses_url":"https://api.github.com/repos/ripple/ripple-lib/statuses/1f54b3a0cf1511b4732c7e23110b0bad31199898","head":{"label":"clark800:get-ledger","ref":"get-ledger","sha":"1f54b3a0cf1511b4732c7e23110b0bad31199898","user":{"login":"clark800","id":1238722,"avatar_url":"https://avatars.githubusercontent.com/u/1238722?v=3","gravatar_id":"","url":"https://api.github.com/users/clark800","html_url":"https://github.com/clark800","followers_url":"https://api.github.com/users/clark800/followers","following_url":"https://api.github.com/users/clark800/following{/other_user}","gists_url":"https://api.github.com/users/clark800/gists{/gist_id}","starred_url":"https://api.github.com/users/clark800/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/clark800/subscriptions","organizations_url":"https://api.github.com/users/clark800/orgs","repos_url":"https://api.github.com/users/clark800/repos","events_url":"https://api.github.com/users/clark800/events{/privacy}","received_events_url":"https://api.github.com/users/clark800/received_events","type":"User","site_admin":false},"repo":{"id":27850085,"name":"ripple-lib","full_name":"clark800/ripple-lib","owner":{"login":"clark800","id":1238722,"avatar_url":"https://avatars.githubusercontent.com/u/1238722?v=3","gravatar_id":"","url":"https://api.github.com/users/clark800","html_url":"https://github.com/clark800","followers_url":"https://api.github.com/users/clark800/followers","following_url":"https://api.github.com/users/clark800/following{/other_user}","gists_url":"https://api.github.com/users/clark800/gists{/gist_id}","starred_url":"https://api.github.com/users/clark800/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/clark800/subscriptions","organizations_url":"https://api.github.com/users/clark800/orgs","repos_url":"https://api.github.com/users/clark800/repos","events_url":"https://api.github.com/users/clark800/events{/privacy}","received_events_url":"https://api.github.com/users/clark800/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/clark800/ripple-lib","description":"A JavaScript API for interacting with Ripple in Node.js and the browser","fork":true,"url":"https://api.github.com/repos/clark800/ripple-lib","forks_url":"https://api.github.com/repos/clark800/ripple-lib/forks","keys_url":"https://api.github.com/repos/clark800/ripple-lib/keys{/key_id}","collaborators_url":"https://api.github.com/repos/clark800/ripple-lib/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/clark800/ripple-lib/teams","hooks_url":"https://api.github.com/repos/clark800/ripple-lib/hooks","issue_events_url":"https://api.github.com/repos/clark800/ripple-lib/issues/events{/number}","events_url":"https://api.github.com/repos/clark800/ripple-lib/events","assignees_url":"https://api.github.com/repos/clark800/ripple-lib/assignees{/user}","branches_url":"https://api.github.com/repos/clark800/ripple-lib/branches{/branch}","tags_url":"https://api.github.com/repos/clark800/ripple-lib/tags","blobs_url":"https://api.github.com/repos/clark800/ripple-lib/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/clark800/ripple-lib/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/clark800/ripple-lib/git/refs{/sha}","trees_url":"https://api.github.com/repos/clark800/ripple-lib/git/trees{/sha}","statuses_url":"https://api.github.com/repos/clark800/ripple-lib/statuses/{sha}","languages_url":"https://api.github.com/repos/clark800/ripple-lib/languages","stargazers_url":"https://api.github.com/repos/clark800/ripple-lib/stargazers","contributors_url":"https://api.github.com/repos/clark800/ripple-lib/contributors","subscribers_url":"https://api.github.com/repos/clark800/ripple-lib/subscribers","subscription_url":"https://api.github.com/repos/clark800/ripple-lib/subscription","commits_url":"https://api.github.com/repos/clark800/ripple-lib/commits{/sha}","git_commits_url":"https://api.github.com/repos/clark800/ripple-lib/git/commits{/sha}","comments_url":"https://api.github.com/repos/clark800/ripple-lib/comments{/number}","issue_comment_url":"https://api.github.com/repos/clark800/ripple-lib/issues/comments{/number}","contents_url":"https://api.github.com/repos/clark800/ripple-lib/contents/{+path}","compare_url":"https://api.github.com/repos/clark800/ripple-lib/compare/{base}...{head}","merges_url":"https://api.github.com/repos/clark800/ripple-lib/merges","archive_url":"https://api.github.com/repos/clark800/ripple-lib/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/clark800/ripple-lib/downloads","issues_url":"https://api.github.com/repos/clark800/ripple-lib/issues{/number}","pulls_url":"https://api.github.com/repos/clark800/ripple-lib/pulls{/number}","milestones_url":"https://api.github.com/repos/clark800/ripple-lib/milestones{/number}","notifications_url":"https://api.github.com/repos/clark800/ripple-lib/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/clark800/ripple-lib/labels{/name}","releases_url":"https://api.github.com/repos/clark800/ripple-lib/releases{/id}","created_at":"2014-12-11T02:21:32Z","updated_at":"2015-04-10T19:57:06Z","pushed_at":"2015-08-18T21:46:22Z","git_url":"git://github.com/clark800/ripple-lib.git","ssh_url":"git@github.com:clark800/ripple-lib.git","clone_url":"https://github.com/clark800/ripple-lib.git","svn_url":"https://github.com/clark800/ripple-lib","homepage":"","size":12936,"stargazers_count":0,"watchers_count":0,"language":"JavaScript","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"develop"}},"base":{"label":"ripple:develop","ref":"develop","sha":"d624923cd8d6e64030cabbff8961be71172038b0","user":{"login":"ripple","id":3165523,"avatar_url":"https://avatars.githubusercontent.com/u/3165523?v=3","gravatar_id":"","url":"https://api.github.com/users/ripple","html_url":"https://github.com/ripple","followers_url":"https://api.github.com/users/ripple/followers","following_url":"https://api.github.com/users/ripple/following{/other_user}","gists_url":"https://api.github.com/users/ripple/gists{/gist_id}","starred_url":"https://api.github.com/users/ripple/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ripple/subscriptions","organizations_url":"https://api.github.com/users/ripple/orgs","repos_url":"https://api.github.com/users/ripple/repos","events_url":"https://api.github.com/users/ripple/events{/privacy}","received_events_url":"https://api.github.com/users/ripple/received_events","type":"Organization","site_admin":false},"repo":{"id":9681561,"name":"ripple-lib","full_name":"ripple/ripple-lib","owner":{"login":"ripple","id":3165523,"avatar_url":"https://avatars.githubusercontent.com/u/3165523?v=3","gravatar_id":"","url":"https://api.github.com/users/ripple","html_url":"https://github.com/ripple","followers_url":"https://api.github.com/users/ripple/followers","following_url":"https://api.github.com/users/ripple/following{/other_user}","gists_url":"https://api.github.com/users/ripple/gists{/gist_id}","starred_url":"https://api.github.com/users/ripple/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ripple/subscriptions","organizations_url":"https://api.github.com/users/ripple/orgs","repos_url":"https://api.github.com/users/ripple/repos","events_url":"https://api.github.com/users/ripple/events{/privacy}","received_events_url":"https://api.github.com/users/ripple/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/ripple/ripple-lib","description":"A JavaScript API for interacting with Ripple in Node.js and the browser","fork":false,"url":"https://api.github.com/repos/ripple/ripple-lib","forks_url":"https://api.github.com/repos/ripple/ripple-lib/forks","keys_url":"https://api.github.com/repos/ripple/ripple-lib/keys{/key_id}","collaborators_url":"https://api.github.com/repos/ripple/ripple-lib/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/ripple/ripple-lib/teams","hooks_url":"https://api.github.com/repos/ripple/ripple-lib/hooks","issue_events_url":"https://api.github.com/repos/ripple/ripple-lib/issues/events{/number}","events_url":"https://api.github.com/repos/ripple/ripple-lib/events","assignees_url":"https://api.github.com/repos/ripple/ripple-lib/assignees{/user}","branches_url":"https://api.github.com/repos/ripple/ripple-lib/branches{/branch}","tags_url":"https://api.github.com/repos/ripple/ripple-lib/tags","blobs_url":"https://api.github.com/repos/ripple/ripple-lib/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/ripple/ripple-lib/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/ripple/ripple-lib/git/refs{/sha}","trees_url":"https://api.github.com/repos/ripple/ripple-lib/git/trees{/sha}","statuses_url":"https://api.github.com/repos/ripple/ripple-lib/statuses/{sha}","languages_url":"https://api.github.com/repos/ripple/ripple-lib/languages","stargazers_url":"https://api.github.com/repos/ripple/ripple-lib/stargazers","contributors_url":"https://api.github.com/repos/ripple/ripple-lib/contributors","subscribers_url":"https://api.github.com/repos/ripple/ripple-lib/subscribers","subscription_url":"https://api.github.com/repos/ripple/ripple-lib/subscription","commits_url":"https://api.github.com/repos/ripple/ripple-lib/commits{/sha}","git_commits_url":"https://api.github.com/repos/ripple/ripple-lib/git/commits{/sha}","comments_url":"https://api.github.com/repos/ripple/ripple-lib/comments{/number}","issue_comment_url":"https://api.github.com/repos/ripple/ripple-lib/issues/comments{/number}","contents_url":"https://api.github.com/repos/ripple/ripple-lib/contents/{+path}","compare_url":"https://api.github.com/repos/ripple/ripple-lib/compare/{base}...{head}","merges_url":"https://api.github.com/repos/ripple/ripple-lib/merges","archive_url":"https://api.github.com/repos/ripple/ripple-lib/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/ripple/ripple-lib/downloads","issues_url":"https://api.github.com/repos/ripple/ripple-lib/issues{/number}","pulls_url":"https://api.github.com/repos/ripple/ripple-lib/pulls{/number}","milestones_url":"https://api.github.com/repos/ripple/ripple-lib/milestones{/number}","notifications_url":"https://api.github.com/repos/ripple/ripple-lib/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/ripple/ripple-lib/labels{/name}","releases_url":"https://api.github.com/repos/ripple/ripple-lib/releases{/id}","created_at":"2013-04-25T21:17:19Z","updated_at":"2015-08-12T06:19:37Z","pushed_at":"2015-08-18T21:54:14Z","git_url":"git://github.com/ripple/ripple-lib.git","ssh_url":"git@github.com:ripple/ripple-lib.git","clone_url":"https://github.com/ripple/ripple-lib.git","svn_url":"https://github.com/ripple/ripple-lib","homepage":"","size":18826,"stargazers_count":419,"watchers_count":419,"language":"JavaScript","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":147,"mirror_url":null,"open_issues_count":19,"forks":147,"open_issues":19,"watchers":419,"default_branch":"develop"}},"_links":{"self":{"href":"https://api.github.com/repos/ripple/ripple-lib/pulls/504"},"html":{"href":"https://github.com/ripple/ripple-lib/pull/504"},"issue":{"href":"https://api.github.com/repos/ripple/ripple-lib/issues/504"},"comments":{"href":"https://api.github.com/repos/ripple/ripple-lib/issues/504/comments"},"review_comments":{"href":"https://api.github.com/repos/ripple/ripple-lib/pulls/504/comments"},"review_comment":{"href":"https://api.github.com/repos/ripple/ripple-lib/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/ripple/ripple-lib/pulls/504/commits"},"statuses":{"href":"https://api.github.com/repos/ripple/ripple-lib/statuses/1f54b3a0cf1511b4732c7e23110b0bad31199898"}}}}