UNPKG

8.5 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3const Service_1 = require("frontblock-generic/Service");
4const PaymentService_1 = require("./PaymentService");
5const Types_1 = require("./Types");
6const bsock = require('bsock');
7const fetch = require("node-fetch");
8const uuid = require("uuid/v4");
9exports.CryptocompareDollarValueProvider = async (coins) => {
10 const ret = new Map();
11 const request = await fetch("https://min-api.cryptocompare.com/data/pricemultifull?fsyms=" + coins.join(",") + "&tsyms=USD");
12 const result = await request.json();
13 const values = result["RAW"];
14 Types_1.CoinList.forEach(coin => {
15 ret.set(coin, values[coin]["USD"]["PRICE"]);
16 });
17 return ret;
18};
19class Frontblock {
20 constructor(conf) {
21 this.subscriptionUIDs = new Map();
22 this.payments = new Map();
23 this.paymentStreams = new Map();
24 this.dollarValues = new Map();
25 this.dollarValueProvider = exports.CryptocompareDollarValueProvider;
26 this.apikey = "";
27 this.io = bsock.createServer();
28 this.conf = conf;
29 if (conf.apiKey != null)
30 this.apikey = conf.apiKey;
31 if (conf.dollarValueProvider != null)
32 this.dollarValueProvider = conf.dollarValueProvider;
33 this.socket = bsock.connect(conf.apiPort, conf.apiHost, conf.tls != null ? conf.tls : false);
34 }
35 updateSubscribers(payment) {
36 const p = this.payments.get(payment.paymentID);
37 if (p != null)
38 this.paymentStreams.forEach(sub => sub(p));
39 }
40 updateModifyDate(payment) {
41 const p = this.payments.get(payment.paymentID);
42 if (p == null)
43 return;
44 p.updatedAt = new Date();
45 this.payments.set(p.paymentID, p);
46 }
47 handlePayment(payment, transaction) {
48 const p = this.payments.get(payment.paymentID);
49 if (p == null)
50 return;
51 p.addTransaction(transaction);
52 p.received += transaction.amount;
53 if (p.currency != transaction.currency) {
54 p.status = "Other (See error field)";
55 p.error = "Currency mismatch. Expected `" + p.currency + "`" + " but got `" + transaction.currency + "`";
56 }
57 else if (p.received == p.amount)
58 p.status = "Completed";
59 else if (p.received < p.amount)
60 p.status = "Underpaid";
61 else if (p.received > p.amount)
62 p.status = "Overpaid";
63 this.payments.set(p.paymentID, p);
64 this.updateModifyDate(p);
65 this.updateSubscribers(p);
66 }
67 async updateDollarValue() {
68 this.dollarValues = await this.dollarValueProvider(Types_1.CoinList);
69 }
70 async createUsdValuePayment(currency, amount) {
71 await this.updateDollarValue();
72 const accountProvider = this.conf[currency];
73 if (accountProvider == null)
74 return new Service_1.ErrorResponse("Unable to generate account. Please specifiy an AccountProvider for `" + currency + "`");
75 const dollarValue = this.dollarValues.get(currency);
76 if (dollarValue == null)
77 return new Service_1.ErrorResponse("Unable to get dollar value of `" + currency + "`");
78 const account = accountProvider();
79 const payment = new PaymentService_1.Payment(amount, amount / dollarValue, currency, account);
80 const res = await this.subscribe(this.apikey, currency, account, (tx) => this.handlePayment(payment, tx));
81 if (res instanceof Service_1.ErrorResponse)
82 return res;
83 this.payments.set(payment.paymentID, payment);
84 this.subscriptionUIDs.set(payment.paymentID, res.uid);
85 this.updateSubscribers(payment);
86 return payment;
87 }
88 async createCryptoPayment(currency, amount) {
89 await this.updateDollarValue();
90 const accountProvider = this.conf[currency];
91 if (accountProvider == null)
92 return new Service_1.ErrorResponse("Unable to generate account. Please specifiy an AccountProvider for `" + currency + "`");
93 const dollarValue = this.dollarValues.get(currency);
94 if (dollarValue == null)
95 return new Service_1.ErrorResponse("Unable to get dollar value of " + currency);
96 const account = accountProvider();
97 const payment = new PaymentService_1.Payment(dollarValue * amount, amount, currency, account);
98 const res = await this.subscribe(this.apikey, currency, account, (tx) => this.handlePayment(payment, tx));
99 if (res instanceof Service_1.ErrorResponse)
100 return res;
101 this.subscriptionUIDs.set(payment.paymentID, res.uid);
102 this.payments.set(payment.paymentID, payment);
103 this.updateSubscribers(payment);
104 return payment;
105 }
106 async getPayment(paymentID) {
107 if (typeof paymentID != "string") {
108 if (paymentID.paymentID == null)
109 return new Service_1.ErrorResponse("Malformed paymentID");
110 paymentID = paymentID.paymentID;
111 }
112 const payment = this.payments.get(paymentID);
113 if (payment == null)
114 return new Service_1.ErrorResponse("Unknown payment");
115 return payment;
116 }
117 async cancelPayment(paymentID) {
118 if (typeof paymentID != "string") {
119 if (paymentID.paymentID == null)
120 return new Service_1.ErrorResponse("Malformed paymentID");
121 paymentID = paymentID.paymentID;
122 }
123 const payment = this.payments.get(paymentID);
124 if (payment == null)
125 return new Service_1.ErrorResponse("Unknown payment");
126 payment.status = "Canceled";
127 this.payments.set(payment.paymentID, payment);
128 this.updateModifyDate(payment);
129 this.updateSubscribers(payment);
130 return new Service_1.SuccessResponse();
131 }
132 async resolvePayment(paymentID) {
133 if (typeof paymentID != "string") {
134 if (paymentID.paymentID == null)
135 return new Service_1.ErrorResponse("Malformed paymentID");
136 paymentID = paymentID.paymentID;
137 }
138 const payment = this.payments.get(paymentID);
139 if (payment == null)
140 return new Service_1.ErrorResponse("Unknown payment");
141 payment.status = "Resolved";
142 this.payments.set(payment.paymentID, payment);
143 this.updateModifyDate(payment);
144 this.updateSubscribers(payment);
145 return new Service_1.SuccessResponse();
146 }
147 async finalizePayment(paymentID) {
148 if (typeof paymentID != "string") {
149 if (paymentID.paymentID == null)
150 return new Service_1.ErrorResponse("Malformed paymentID");
151 paymentID = paymentID.paymentID;
152 }
153 const payment = this.payments.get(paymentID);
154 if (payment == null)
155 return new Service_1.ErrorResponse("Unknown payment");
156 if (payment.status != "Completed" && payment.status != "Canceled") {
157 return new Service_1.ErrorResponse("Unable to finalize a payment with status " + payment.status);
158 }
159 payment.status = "Finalized";
160 this.updateModifyDate(payment);
161 this.updateSubscribers(payment);
162 const sub = this.subscriptionUIDs.get(payment.paymentID);
163 if (sub != null)
164 this.unsubscribe(this.apikey, sub);
165 return new Service_1.SuccessResponse();
166 }
167 async cancelStream(uid) {
168 if (typeof uid != "string") {
169 if (uid.uid == null)
170 return new Service_1.ErrorResponse("Malformed subscription identifier");
171 uid = uid.uid;
172 }
173 if (!this.paymentStreams.has(uid))
174 return new Service_1.ErrorResponse("Unknown stream");
175 this.paymentStreams.delete(uid);
176 return new Service_1.SuccessResponse();
177 }
178 async streamPayments(callback) {
179 const uid = uuid();
180 this.paymentStreams.set(uid, callback);
181 return new Service_1.SubscriptionResponse(uid);
182 }
183 async subscribe(apikey, coin, account, callback) {
184 const r = await this.socket.call(apikey, coin, account);
185 const res = Service_1.parseSubResponse(r);
186 if (res instanceof Service_1.SubscriptionResponse) {
187 this.socket.hook(res.uid, callback);
188 }
189 return res;
190 }
191 async unsubscribe(apikey, uid) {
192 const res = await this.socket.call('unsubscribe', apikey, uid);
193 return Service_1.parseResponse(res);
194 }
195}
196exports.Frontblock = Frontblock;