app.js 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. import fetch from "node-fetch"
  2. import express from "express"
  3. import bodyParser from "body-parser"
  4. const app = express();
  5. app.use(bodyParser.json());
  6. const CHAIN4ALL_SERVICE_PORT = process.env.CHAIN4ALL_SERVICE_PORT || 3000;
  7. const IROHA_API_HOST = process.env.IROHA_API_HOST || "http://localhost";
  8. const IROHA_API_PORT = process.env.IROHA_API_PORT || 5000;
  9. const IROHA_DOMAIN = process.env.IROHA_DOMAIN || "test";
  10. const IROHA_ASSET = process.env.IROHA_ASSET || "coin";
  11. const DATA_OWNER = process.env.DATA_OWNER || "admin"
  12. const PRICE_MODIFIER = process.env.PRICE_MODIFIER || 0.5;
  13. app.get("/", (req, res) => {
  14. res.send("Chain4All Blockchain service");
  15. });
  16. app.post("/price", (req, res) => {
  17. if (req.body && req.body.extent) {
  18. res.send({ price: getPrice(req.body.extent) });
  19. }
  20. else {
  21. res.status(400);
  22. throw Error(JSON.stringify({ error: { name: "Error, request has no body with \"extent\" property!" } }));
  23. }
  24. });
  25. app.get("/users/:userId/assets", async (req, res) => {
  26. let irohaResponse = await fetchUsersAssets(req.params.userId);
  27. res.status(irohaResponse.status);
  28. if (irohaResponse.headers.get("content-length") < 1) {
  29. res.send();
  30. }
  31. else {
  32. res.send(await irohaResponse.json());
  33. }
  34. });
  35. app.get("/users/:userId/assets/:assetId", async (req, res) => {
  36. let assets = (await fetchUsersAssets(req.params.userId)).assets;
  37. let parsedAssetName = "";
  38. let i = 0;
  39. for (i; i < assets.length; i++) {
  40. parsedAssetName = assets[i].assetId.split('#')[0];
  41. if (parsedAssetName === req.params.assetId) {
  42. res.status(200);
  43. res.send(assets[i]);
  44. return;
  45. }
  46. }
  47. res.status(204);
  48. res.send();
  49. });
  50. app.post("/buy", async (req, res) => {
  51. if (!req.body) {
  52. res.status(400);
  53. throw Error(JSON.stringify({ error: { name: "Error, request has no body!" } }));
  54. }
  55. if (!req.body.extent) {
  56. res.status(400);
  57. throw Error(JSON.stringify({ error: { name: "Error, request body has no \"extent\" property!" } }));
  58. }
  59. if (!req.body.user) {
  60. res.status(400);
  61. throw Error(JSON.stringify({ error: { name: "Error, request body has no \"user\" property!" } }));
  62. }
  63. if (!req.body.privateKey) {
  64. res.status(400);
  65. throw Error(JSON.stringify({ error: { name: "Error, user must provide \"privateKey\" to sign transaction!" } }));
  66. }
  67. let price = getPrice(req.body.extent);
  68. let irohaResponse = await forwardBuyRequest(
  69. {
  70. privateKey: req.body.privateKey,
  71. transfers: [
  72. {
  73. asset: IROHA_ASSET + "#" + IROHA_DOMAIN,
  74. source: req.body.user + "@" + IROHA_DOMAIN,
  75. destination: DATA_OWNER + "@" + IROHA_DOMAIN,
  76. description: "test", //TODO: compose uniform description
  77. amount: price
  78. }
  79. ]
  80. }
  81. );
  82. let data = "test - to be implemented"; //TODO implement data extraction
  83. res.status(irohaResponse.status);
  84. if (!irohaResponse.ok) {
  85. res.send(await irohaResponse.json());
  86. return;
  87. }
  88. let irohaResponseJson = await irohaResponse.json();
  89. console.log("tx hash: " + irohaResponseJson.transactionHash);
  90. res.send({
  91. data : data,
  92. transactionHash : irohaResponseJson.transactionHash
  93. });
  94. });
  95. async function forwardBuyRequest(body) {
  96. return await fetch(IROHA_API_HOST + ':' + IROHA_API_PORT + '/assets/transfer/',
  97. {
  98. method: 'POST',
  99. body: JSON.stringify(body),
  100. headers: { 'Content-Type': 'application/json' }
  101. }
  102. );
  103. }
  104. async function fetchUsersAssets(userId) {
  105. return await fetch(IROHA_API_HOST + ':' + IROHA_API_PORT + '/accounts/' + userId + '@' + IROHA_DOMAIN + '/assets/');
  106. }
  107. function getArea(extent) {
  108. let y1 = extent[0][1];
  109. let y4 = extent[3][1];
  110. let x1 = extent[0][0];
  111. let x2 = extent[1][0];
  112. let height = Math.abs(y1 - y4);
  113. let width = Math.abs(x1 - x2);
  114. return height * width;
  115. }
  116. function getPrice(extent) {
  117. return getArea(extent) * PRICE_MODIFIER;
  118. }
  119. function error(err, req, res, next) { //TODO: add custom Exception class
  120. console.log(err);
  121. res.status(500);
  122. res.send(err.message);
  123. }
  124. app.use(error);
  125. app.listen(CHAIN4ALL_SERVICE_PORT, () => {
  126. console.log(`Listening at http://localhost:${CHAIN4ALL_SERVICE_PORT}`)
  127. });