app.ts 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. import 'dotenv/config'
  2. import grpc from "grpc"
  3. import express from "express"
  4. import bodyParser from "body-parser"
  5. import basicAuth from "express-basic-auth"
  6. import {
  7. CommandService_v1Client as CommandService,
  8. QueryService_v1Client as QueryService
  9. } from 'iroha-helpers/lib/proto/endpoint_grpc_pb'
  10. import { queries } from 'iroha-helpers'
  11. import util from 'util'
  12. import { exec } from 'child_process'
  13. const app = express();
  14. app.use(bodyParser.json());
  15. app.use(basicAuth({
  16. users: { admin: 'superPasswd' },
  17. challenge: true
  18. }));
  19. const asyncExec = util.promisify(exec);
  20. const IROHA_ADMIN_PRIV = "f101537e319568c765b2cc89698325604991dca57b9716b58016b253506cab70";
  21. const IROHA_ADMIN = "admin@test";
  22. const IROHA_ADDRESS = "localhost:50051";
  23. const commandService = new CommandService(IROHA_ADDRESS, grpc.credentials.createInsecure());
  24. const queryService = new QueryService(IROHA_ADDRESS, grpc.credentials.createInsecure());
  25. const CHAIN4ALL_RASTER_CLIP_SCRIPT_PATH = process.env.CHAIN4ALL_RASTER_CLIP_SCRIPT_PATH || '/home/kunickyd/Documents/chain4all/chain4all_raster_clip.sh';
  26. const CHAIN4ALL_SERVICE_PORT = process.env.CHAIN4ALL_SERVICE_PORT || 3000;
  27. const IROHA_API_HOST = process.env.IROHA_API_HOST || "http://localhost";
  28. const IROHA_API_PORT = process.env.IROHA_API_PORT || 5000;
  29. const IROHA_DOMAIN = process.env.IROHA_DOMAIN || "test";
  30. const IROHA_ASSET = process.env.IROHA_ASSET || "coin";
  31. const DATA_OWNER = process.env.DATA_OWNER || "admin"
  32. const PRICE_MODIFIER: number = parseFloat(process.env.PRICE_MODIFIER || "0.5");
  33. app.get("/", (req, res) => {
  34. res.send("Chain4All Blockchain service");
  35. });
  36. app.post("/price", (req, res) => {
  37. if (req.body && req.body.extent) {
  38. res.send({ price: getPrice(req.body.extent) });
  39. }
  40. else {
  41. res.status(400);
  42. throw Error(JSON.stringify({ error: { name: "Error, request has no body with \"extent\" property!" } }));
  43. }
  44. });
  45. app.post("/buy", async (req, res, next) => {
  46. try {
  47. if (!req.body) {
  48. res.status(400);
  49. throw Error(JSON.stringify({ error: { name: "Error, request has no body!" } }));
  50. }
  51. if (!req.body.txHash) {
  52. res.status(400);
  53. throw Error(JSON.stringify({ error: { name: "Error, request body has no \"txHash\" property!" } }));
  54. }
  55. //TODO load from http headers, or something like that??
  56. if (!req.body.user) {
  57. res.status(400);
  58. throw Error(JSON.stringify({ error: { name: "Error, request body has no \"user\" property!" } }));
  59. }
  60. //TODO validate this properly
  61. let txDetail = await getTransactionDetail(req.body.txHash, req.body.user);
  62. const { stdout, stderr } = await asyncExec(CHAIN4ALL_RASTER_CLIP_SCRIPT_PATH);
  63. if(stderr){
  64. throw(stderr);
  65. }
  66. res.send(stdout);
  67. }
  68. catch (err) {
  69. next(err);
  70. }
  71. });
  72. async function getTransactionDetail(txHash: string, user: string) {
  73. let quer: any = await queries.getAccountTransactions({
  74. privateKey: IROHA_ADMIN_PRIV,
  75. creatorAccountId: IROHA_ADMIN,
  76. queryService,
  77. timeoutLimit: 5000
  78. }, {
  79. accountId: user,
  80. pageSize: 10,
  81. firstTxHash: txHash,
  82. ordering: {
  83. field: undefined,
  84. direction: undefined
  85. },
  86. firstTxTime: undefined,
  87. lastTxTime: undefined,
  88. firstTxHeight: 1,
  89. lastTxHeight: 3
  90. });
  91. //TODO find better way to look for transferAssets command in transaction
  92. return quer.transactionsList[0].payload.reducedPayload.commandsList[0].transferAsset;
  93. }
  94. function getArea(extent: Array<Array<number>>): number {
  95. let y1 = extent[0][1];
  96. let y4 = extent[3][1];
  97. let x1 = extent[0][0];
  98. let x2 = extent[1][0];
  99. let height = Math.abs(y1 - y4);
  100. let width = Math.abs(x1 - x2);
  101. return height * width;
  102. }
  103. function getPrice(extent: Array<Array<number>>): number {
  104. return getArea(extent) * PRICE_MODIFIER;
  105. }
  106. function errorMiddleware(err: any, req: any, res: any, next: any): void { //TODO: add custom Exception class
  107. console.log(err);
  108. res.status(500);
  109. res.send(err.message);
  110. }
  111. app.use(errorMiddleware);
  112. app.listen(CHAIN4ALL_SERVICE_PORT, () => {
  113. console.log(`Listening at http://localhost:${CHAIN4ALL_SERVICE_PORT}`)
  114. });