@atomiqlabs/lp-lib 11.0.0 → 11.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  export * from "./info/InfoHandler";
2
2
  export * from "./prices/CoinGeckoSwapPrice";
3
3
  export * from "./prices/BinanceSwapPrice";
4
+ export * from "./prices/OKXSwapPrice";
4
5
  export * from "./storage/IIntermediaryStorage";
5
6
  export * from "./storagemanager/StorageManager";
6
7
  export * from "./storagemanager/IntermediaryStorageManager";
package/dist/index.js CHANGED
@@ -17,6 +17,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./info/InfoHandler"), exports);
18
18
  __exportStar(require("./prices/CoinGeckoSwapPrice"), exports);
19
19
  __exportStar(require("./prices/BinanceSwapPrice"), exports);
20
+ __exportStar(require("./prices/OKXSwapPrice"), exports);
20
21
  __exportStar(require("./storage/IIntermediaryStorage"), exports);
21
22
  __exportStar(require("./storagemanager/StorageManager"), exports);
22
23
  __exportStar(require("./storagemanager/IntermediaryStorageManager"), exports);
@@ -0,0 +1,27 @@
1
+ import * as BN from "bn.js";
2
+ import { ISwapPrice } from "../swaps/ISwapPrice";
3
+ export type OKXPriceData = {
4
+ [pair: string]: {
5
+ [chainId: string]: {
6
+ address: string;
7
+ decimals: number;
8
+ };
9
+ };
10
+ };
11
+ export declare class OKXSwapPrice extends ISwapPrice<{
12
+ pair: string;
13
+ decimals: number;
14
+ }> {
15
+ url: string;
16
+ cache: {
17
+ [pair: string]: {
18
+ price: number;
19
+ expiry: number;
20
+ };
21
+ };
22
+ constructor(url: string, coins: OKXPriceData);
23
+ fetchPrice(pair: string): Promise<number>;
24
+ getPrice(tokenData: {
25
+ pair: string;
26
+ }): Promise<BN>;
27
+ }
@@ -0,0 +1,106 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.OKXSwapPrice = void 0;
13
+ const BN = require("bn.js");
14
+ const ISwapPrice_1 = require("../swaps/ISwapPrice");
15
+ const CACHE_DURATION = 15000;
16
+ class OKXSwapPrice extends ISwapPrice_1.ISwapPrice {
17
+ constructor(url, coins) {
18
+ const coinsMap = {};
19
+ for (let pair in coins) {
20
+ const chains = coins[pair];
21
+ for (let chainId in chains) {
22
+ const tokenData = chains[chainId];
23
+ if (coinsMap[chainId] == null)
24
+ coinsMap[chainId] = {};
25
+ coinsMap[chainId][tokenData.address] = {
26
+ pair,
27
+ decimals: tokenData.decimals
28
+ };
29
+ }
30
+ }
31
+ super(coinsMap);
32
+ this.cache = {};
33
+ this.url = url || "https://www.okx.com/api/v5";
34
+ }
35
+ fetchPrice(pair) {
36
+ return __awaiter(this, void 0, void 0, function* () {
37
+ const response = yield fetch(this.url + "/market/index-tickers?instId=" + pair, {
38
+ method: "GET"
39
+ });
40
+ if (response.status !== 200) {
41
+ let resp;
42
+ try {
43
+ resp = yield response.text();
44
+ }
45
+ catch (e) {
46
+ throw new Error(response.statusText);
47
+ }
48
+ throw new Error(resp);
49
+ }
50
+ let jsonBody = yield response.json();
51
+ return parseFloat(jsonBody.data[0].idxPx);
52
+ });
53
+ }
54
+ getPrice(tokenData) {
55
+ return __awaiter(this, void 0, void 0, function* () {
56
+ const pair = tokenData.pair;
57
+ if (pair.startsWith("$fixed-")) {
58
+ const amt = parseFloat(pair.substring(7));
59
+ return new BN(Math.floor(amt * 1000000));
60
+ }
61
+ const arr = pair.split(";");
62
+ const promises = [];
63
+ const cachedValue = this.cache[pair];
64
+ if (cachedValue == null || cachedValue.expiry < Date.now()) {
65
+ let resultPrice = 1;
66
+ for (let pair of arr) {
67
+ let invert = false;
68
+ if (pair.startsWith("!")) {
69
+ invert = true;
70
+ pair = pair.substring(1);
71
+ }
72
+ const cachedValue = this.cache[pair];
73
+ if (cachedValue == null || cachedValue.expiry < Date.now()) {
74
+ promises.push(this.fetchPrice(pair).then(price => {
75
+ this.cache[pair] = {
76
+ price,
77
+ expiry: Date.now() + CACHE_DURATION
78
+ };
79
+ if (invert) {
80
+ resultPrice /= price;
81
+ }
82
+ else {
83
+ resultPrice *= price;
84
+ }
85
+ }));
86
+ }
87
+ else {
88
+ if (invert) {
89
+ resultPrice /= cachedValue.price;
90
+ }
91
+ else {
92
+ resultPrice *= cachedValue.price;
93
+ }
94
+ }
95
+ }
96
+ yield Promise.all(promises);
97
+ this.cache[pair] = {
98
+ price: resultPrice,
99
+ expiry: Date.now() + CACHE_DURATION
100
+ };
101
+ }
102
+ return new BN(Math.floor(this.cache[pair].price * 100000000000000));
103
+ });
104
+ }
105
+ }
106
+ exports.OKXSwapPrice = OKXSwapPrice;
@@ -188,23 +188,42 @@ class FromBtcLnTrusted extends FromBtcLnBaseSwapHandler_1.FromBtcLnBaseSwapHandl
188
188
  }
189
189
  if (invoiceData.state !== FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.RECEIVED)
190
190
  return;
191
- let unlock = invoiceData.lock(30 * 1000);
191
+ const txns = yield swapContract.txsTransfer(signer.getAddress(), swapContract.getNativeCurrencyAddress(), invoiceData.output, invoiceData.dstAddress);
192
+ let unlock = invoiceData.lock(Infinity);
192
193
  if (unlock == null)
193
194
  return;
194
- const txns = yield swapContract.txsTransfer(signer.getAddress(), swapContract.getNativeCurrencyAddress(), invoiceData.output, invoiceData.dstAddress);
195
- yield swapContract.sendAndConfirm(signer, txns, true, null, false, (txId, rawTx) => __awaiter(this, void 0, void 0, function* () {
195
+ const result = yield swapContract.sendAndConfirm(signer, txns, true, null, false, (txId, rawTx) => __awaiter(this, void 0, void 0, function* () {
196
196
  invoiceData.txIds = { init: txId };
197
197
  invoiceData.scRawTx = rawTx;
198
198
  if (invoiceData.state === FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.RECEIVED) {
199
199
  yield invoiceData.setState(FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.SENT);
200
200
  yield this.storageManager.saveData(invoice.id, null, invoiceData);
201
201
  }
202
- if (unlock != null)
203
- unlock();
204
- unlock = null;
205
- }));
202
+ })).catch(e => console.error(e));
203
+ if (result == null) {
204
+ //Cancel invoice
205
+ yield invoiceData.setState(FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.REFUNDED);
206
+ yield this.storageManager.saveData(invoice.id, null, invoiceData);
207
+ yield this.lightning.cancelHodlInvoice(invoice.id);
208
+ this.unsubscribeInvoice(invoice.id);
209
+ yield this.removeSwapData(invoice.id, null);
210
+ this.swapLogger.info(invoiceData, "htlcReceived(): transaction sending failed, refunding lightning: ", invoiceData.pr);
211
+ throw {
212
+ code: 20002,
213
+ msg: "Transaction sending failed"
214
+ };
215
+ }
216
+ else {
217
+ //Successfully paid
218
+ yield invoiceData.setState(FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.CONFIRMED);
219
+ yield this.storageManager.saveData(invoice.id, null, invoiceData);
220
+ }
221
+ unlock();
222
+ unlock = null;
206
223
  }
207
224
  if (invoiceData.state === FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.SENT) {
225
+ if (invoiceData.isLocked())
226
+ return;
208
227
  const txStatus = yield swapContract.getTxStatus(invoiceData.scRawTx);
209
228
  if (txStatus === "not_found") {
210
229
  //Retry
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atomiqlabs/lp-lib",
3
- "version": "11.0.0",
3
+ "version": "11.0.1",
4
4
  "description": "Main functionality implementation for atomiq LP node",
5
5
  "main": "./dist/index.js",
6
6
  "types:": "./dist/index.d.ts",
package/src/index.ts CHANGED
@@ -2,6 +2,7 @@ export * from "./info/InfoHandler";
2
2
 
3
3
  export * from "./prices/CoinGeckoSwapPrice";
4
4
  export * from "./prices/BinanceSwapPrice";
5
+ export * from "./prices/OKXSwapPrice";
5
6
 
6
7
  export * from "./storage/IIntermediaryStorage";
7
8
 
@@ -0,0 +1,114 @@
1
+ import * as BN from "bn.js";
2
+ import {ISwapPrice} from "../swaps/ISwapPrice";
3
+
4
+ const CACHE_DURATION = 15000;
5
+
6
+ export type OKXPriceData = {
7
+ [pair: string]: {
8
+ [chainId: string]: {
9
+ address: string,
10
+ decimals: number
11
+ }
12
+ }
13
+ };
14
+
15
+ export class OKXSwapPrice extends ISwapPrice<{ pair: string, decimals: number }> {
16
+
17
+ url: string;
18
+ cache: {
19
+ [pair: string]: {
20
+ price: number,
21
+ expiry: number
22
+ }
23
+ } = {};
24
+
25
+ constructor(url: string, coins: OKXPriceData) {
26
+ const coinsMap = {};
27
+ for(let pair in coins) {
28
+ const chains = coins[pair];
29
+ for(let chainId in chains) {
30
+ const tokenData = chains[chainId];
31
+ if(coinsMap[chainId]==null) coinsMap[chainId] = {};
32
+ coinsMap[chainId][tokenData.address] = {
33
+ pair,
34
+ decimals: tokenData.decimals
35
+ }
36
+ }
37
+ }
38
+ super(coinsMap);
39
+ this.url = url || "https://www.okx.com/api/v5";
40
+ }
41
+
42
+ async fetchPrice(pair: string) {
43
+ const response: Response = await fetch(this.url+"/market/index-tickers?instId=" + pair, {
44
+ method: "GET"
45
+ });
46
+
47
+ if (response.status !== 200) {
48
+ let resp: string;
49
+ try {
50
+ resp = await response.text();
51
+ } catch (e) {
52
+ throw new Error(response.statusText);
53
+ }
54
+ throw new Error(resp);
55
+ }
56
+
57
+ let jsonBody: any = await response.json();
58
+
59
+ return parseFloat(jsonBody.data[0].idxPx);
60
+ }
61
+
62
+ async getPrice(tokenData: {pair: string}): Promise<BN> {
63
+ const pair = tokenData.pair;
64
+ if(pair.startsWith("$fixed-")) {
65
+ const amt: number = parseFloat(pair.substring(7));
66
+ return new BN(Math.floor(amt*1000000));
67
+ }
68
+
69
+ const arr = pair.split(";");
70
+
71
+ const promises = [];
72
+ const cachedValue = this.cache[pair];
73
+ if(cachedValue==null || cachedValue.expiry<Date.now()) {
74
+ let resultPrice = 1;
75
+ for (let pair of arr) {
76
+ let invert = false
77
+ if (pair.startsWith("!")) {
78
+ invert = true;
79
+ pair = pair.substring(1);
80
+ }
81
+ const cachedValue = this.cache[pair];
82
+ if (cachedValue == null || cachedValue.expiry < Date.now()) {
83
+ promises.push(this.fetchPrice(pair).then(price => {
84
+ this.cache[pair] = {
85
+ price,
86
+ expiry: Date.now() + CACHE_DURATION
87
+ };
88
+
89
+ if (invert) {
90
+ resultPrice /= price;
91
+ } else {
92
+ resultPrice *= price;
93
+ }
94
+ }));
95
+ } else {
96
+ if (invert) {
97
+ resultPrice /= cachedValue.price;
98
+ } else {
99
+ resultPrice *= cachedValue.price;
100
+ }
101
+ }
102
+ }
103
+
104
+ await Promise.all(promises);
105
+
106
+ this.cache[pair] = {
107
+ price: resultPrice,
108
+ expiry: Date.now() + CACHE_DURATION
109
+ };
110
+ }
111
+
112
+ return new BN(Math.floor(this.cache[pair].price*100000000000000));
113
+ }
114
+ }
@@ -217,23 +217,45 @@ export class FromBtcLnTrusted extends FromBtcLnBaseSwapHandler<FromBtcLnTrustedS
217
217
 
218
218
  if(invoiceData.state!==FromBtcLnTrustedSwapState.RECEIVED) return;
219
219
 
220
- let unlock = invoiceData.lock(30*1000);
220
+ const txns = await swapContract.txsTransfer(signer.getAddress(), swapContract.getNativeCurrencyAddress(), invoiceData.output, invoiceData.dstAddress);
221
+
222
+ let unlock = invoiceData.lock(Infinity);
221
223
  if(unlock==null) return;
222
224
 
223
- const txns = await swapContract.txsTransfer(signer.getAddress(), swapContract.getNativeCurrencyAddress(), invoiceData.output, invoiceData.dstAddress);
224
- await swapContract.sendAndConfirm(signer, txns, true, null, false, async (txId: string, rawTx: string) => {
225
+ const result = await swapContract.sendAndConfirm(signer, txns, true, null, false, async (txId: string, rawTx: string) => {
225
226
  invoiceData.txIds = {init: txId};
226
227
  invoiceData.scRawTx = rawTx;
227
228
  if(invoiceData.state===FromBtcLnTrustedSwapState.RECEIVED) {
228
229
  await invoiceData.setState(FromBtcLnTrustedSwapState.SENT);
229
230
  await this.storageManager.saveData(invoice.id, null, invoiceData);
230
231
  }
231
- if(unlock!=null) unlock();
232
- unlock = null;
233
- });
232
+ }).catch(e => console.error(e));
233
+
234
+ if(result==null) {
235
+ //Cancel invoice
236
+ await invoiceData.setState(FromBtcLnTrustedSwapState.REFUNDED);
237
+ await this.storageManager.saveData(invoice.id, null, invoiceData);
238
+ await this.lightning.cancelHodlInvoice(invoice.id);
239
+ this.unsubscribeInvoice(invoice.id);
240
+ await this.removeSwapData(invoice.id, null);
241
+ this.swapLogger.info(invoiceData, "htlcReceived(): transaction sending failed, refunding lightning: ", invoiceData.pr);
242
+ throw {
243
+ code: 20002,
244
+ msg: "Transaction sending failed"
245
+ };
246
+ } else {
247
+ //Successfully paid
248
+ await invoiceData.setState(FromBtcLnTrustedSwapState.CONFIRMED);
249
+ await this.storageManager.saveData(invoice.id, null, invoiceData);
250
+ }
251
+
252
+ unlock();
253
+ unlock = null;
234
254
  }
235
255
 
236
256
  if(invoiceData.state===FromBtcLnTrustedSwapState.SENT) {
257
+ if(invoiceData.isLocked()) return;
258
+
237
259
  const txStatus = await swapContract.getTxStatus(invoiceData.scRawTx);
238
260
  if(txStatus==="not_found") {
239
261
  //Retry