@atomiqlabs/lp-lib 10.3.11

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.
Files changed (138) hide show
  1. package/LICENSE +201 -0
  2. package/dist/fees/IBtcFeeEstimator.d.ts +3 -0
  3. package/dist/fees/IBtcFeeEstimator.js +2 -0
  4. package/dist/fees/OneDollarFeeEstimator.d.ts +16 -0
  5. package/dist/fees/OneDollarFeeEstimator.js +71 -0
  6. package/dist/index.d.ts +33 -0
  7. package/dist/index.js +52 -0
  8. package/dist/info/InfoHandler.d.ts +17 -0
  9. package/dist/info/InfoHandler.js +70 -0
  10. package/dist/plugins/IPlugin.d.ts +118 -0
  11. package/dist/plugins/IPlugin.js +33 -0
  12. package/dist/plugins/PluginManager.d.ts +89 -0
  13. package/dist/plugins/PluginManager.js +263 -0
  14. package/dist/prices/BinanceSwapPrice.d.ts +27 -0
  15. package/dist/prices/BinanceSwapPrice.js +106 -0
  16. package/dist/prices/CoinGeckoSwapPrice.d.ts +31 -0
  17. package/dist/prices/CoinGeckoSwapPrice.js +76 -0
  18. package/dist/storage/IIntermediaryStorage.d.ts +15 -0
  19. package/dist/storage/IIntermediaryStorage.js +2 -0
  20. package/dist/storagemanager/IntermediaryStorageManager.d.ts +15 -0
  21. package/dist/storagemanager/IntermediaryStorageManager.js +113 -0
  22. package/dist/storagemanager/StorageManager.d.ts +12 -0
  23. package/dist/storagemanager/StorageManager.js +74 -0
  24. package/dist/swaps/FromBtcBaseSwap.d.ts +12 -0
  25. package/dist/swaps/FromBtcBaseSwap.js +16 -0
  26. package/dist/swaps/FromBtcBaseSwapHandler.d.ts +118 -0
  27. package/dist/swaps/FromBtcBaseSwapHandler.js +294 -0
  28. package/dist/swaps/FromBtcLnBaseSwapHandler.d.ts +25 -0
  29. package/dist/swaps/FromBtcLnBaseSwapHandler.js +55 -0
  30. package/dist/swaps/ISwapPrice.d.ts +44 -0
  31. package/dist/swaps/ISwapPrice.js +73 -0
  32. package/dist/swaps/SwapHandler.d.ts +186 -0
  33. package/dist/swaps/SwapHandler.js +292 -0
  34. package/dist/swaps/SwapHandlerSwap.d.ts +75 -0
  35. package/dist/swaps/SwapHandlerSwap.js +72 -0
  36. package/dist/swaps/ToBtcBaseSwap.d.ts +35 -0
  37. package/dist/swaps/ToBtcBaseSwap.js +61 -0
  38. package/dist/swaps/ToBtcBaseSwapHandler.d.ts +94 -0
  39. package/dist/swaps/ToBtcBaseSwapHandler.js +233 -0
  40. package/dist/swaps/frombtc_abstract/FromBtcAbs.d.ts +92 -0
  41. package/dist/swaps/frombtc_abstract/FromBtcAbs.js +386 -0
  42. package/dist/swaps/frombtc_abstract/FromBtcSwapAbs.d.ts +26 -0
  43. package/dist/swaps/frombtc_abstract/FromBtcSwapAbs.js +63 -0
  44. package/dist/swaps/frombtc_trusted/FromBtcTrusted.d.ts +55 -0
  45. package/dist/swaps/frombtc_trusted/FromBtcTrusted.js +586 -0
  46. package/dist/swaps/frombtc_trusted/FromBtcTrustedSwap.d.ts +43 -0
  47. package/dist/swaps/frombtc_trusted/FromBtcTrustedSwap.js +99 -0
  48. package/dist/swaps/frombtcln_abstract/FromBtcLnAbs.d.ts +105 -0
  49. package/dist/swaps/frombtcln_abstract/FromBtcLnAbs.js +731 -0
  50. package/dist/swaps/frombtcln_abstract/FromBtcLnSwapAbs.d.ts +29 -0
  51. package/dist/swaps/frombtcln_abstract/FromBtcLnSwapAbs.js +64 -0
  52. package/dist/swaps/frombtcln_trusted/FromBtcLnTrusted.d.ts +79 -0
  53. package/dist/swaps/frombtcln_trusted/FromBtcLnTrusted.js +514 -0
  54. package/dist/swaps/frombtcln_trusted/FromBtcLnTrustedSwap.d.ts +28 -0
  55. package/dist/swaps/frombtcln_trusted/FromBtcLnTrustedSwap.js +66 -0
  56. package/dist/swaps/tobtc_abstract/ToBtcAbs.d.ts +290 -0
  57. package/dist/swaps/tobtc_abstract/ToBtcAbs.js +1056 -0
  58. package/dist/swaps/tobtc_abstract/ToBtcSwapAbs.d.ts +29 -0
  59. package/dist/swaps/tobtc_abstract/ToBtcSwapAbs.js +70 -0
  60. package/dist/swaps/tobtcln_abstract/ToBtcLnAbs.d.ts +246 -0
  61. package/dist/swaps/tobtcln_abstract/ToBtcLnAbs.js +1169 -0
  62. package/dist/swaps/tobtcln_abstract/ToBtcLnSwapAbs.d.ts +27 -0
  63. package/dist/swaps/tobtcln_abstract/ToBtcLnSwapAbs.js +65 -0
  64. package/dist/utils/Utils.d.ts +32 -0
  65. package/dist/utils/Utils.js +109 -0
  66. package/dist/utils/coinselect2/accumulative.d.ts +6 -0
  67. package/dist/utils/coinselect2/accumulative.js +44 -0
  68. package/dist/utils/coinselect2/blackjack.d.ts +6 -0
  69. package/dist/utils/coinselect2/blackjack.js +41 -0
  70. package/dist/utils/coinselect2/index.d.ts +16 -0
  71. package/dist/utils/coinselect2/index.js +40 -0
  72. package/dist/utils/coinselect2/utils.d.ts +64 -0
  73. package/dist/utils/coinselect2/utils.js +121 -0
  74. package/dist/utils/paramcoders/IParamReader.d.ts +5 -0
  75. package/dist/utils/paramcoders/IParamReader.js +2 -0
  76. package/dist/utils/paramcoders/IParamWriter.d.ts +4 -0
  77. package/dist/utils/paramcoders/IParamWriter.js +2 -0
  78. package/dist/utils/paramcoders/LegacyParamEncoder.d.ts +10 -0
  79. package/dist/utils/paramcoders/LegacyParamEncoder.js +33 -0
  80. package/dist/utils/paramcoders/ParamDecoder.d.ts +25 -0
  81. package/dist/utils/paramcoders/ParamDecoder.js +234 -0
  82. package/dist/utils/paramcoders/ParamEncoder.d.ts +9 -0
  83. package/dist/utils/paramcoders/ParamEncoder.js +22 -0
  84. package/dist/utils/paramcoders/SchemaVerifier.d.ts +22 -0
  85. package/dist/utils/paramcoders/SchemaVerifier.js +85 -0
  86. package/dist/utils/paramcoders/server/ServerParamDecoder.d.ts +8 -0
  87. package/dist/utils/paramcoders/server/ServerParamDecoder.js +105 -0
  88. package/dist/utils/paramcoders/server/ServerParamEncoder.d.ts +11 -0
  89. package/dist/utils/paramcoders/server/ServerParamEncoder.js +76 -0
  90. package/package.json +43 -0
  91. package/src/fees/IBtcFeeEstimator.ts +7 -0
  92. package/src/fees/OneDollarFeeEstimator.ts +95 -0
  93. package/src/index.ts +46 -0
  94. package/src/info/InfoHandler.ts +106 -0
  95. package/src/plugins/IPlugin.ts +155 -0
  96. package/src/plugins/PluginManager.ts +310 -0
  97. package/src/prices/BinanceSwapPrice.ts +114 -0
  98. package/src/prices/CoinGeckoSwapPrice.ts +88 -0
  99. package/src/storage/IIntermediaryStorage.ts +21 -0
  100. package/src/storagemanager/IntermediaryStorageManager.ts +101 -0
  101. package/src/storagemanager/StorageManager.ts +68 -0
  102. package/src/swaps/FromBtcBaseSwap.ts +21 -0
  103. package/src/swaps/FromBtcBaseSwapHandler.ts +375 -0
  104. package/src/swaps/FromBtcLnBaseSwapHandler.ts +48 -0
  105. package/src/swaps/ISwapPrice.ts +94 -0
  106. package/src/swaps/SwapHandler.ts +404 -0
  107. package/src/swaps/SwapHandlerSwap.ts +133 -0
  108. package/src/swaps/ToBtcBaseSwap.ts +76 -0
  109. package/src/swaps/ToBtcBaseSwapHandler.ts +309 -0
  110. package/src/swaps/frombtc_abstract/FromBtcAbs.ts +484 -0
  111. package/src/swaps/frombtc_abstract/FromBtcSwapAbs.ts +77 -0
  112. package/src/swaps/frombtc_trusted/FromBtcTrusted.ts +661 -0
  113. package/src/swaps/frombtc_trusted/FromBtcTrustedSwap.ts +158 -0
  114. package/src/swaps/frombtcln_abstract/FromBtcLnAbs.ts +864 -0
  115. package/src/swaps/frombtcln_abstract/FromBtcLnSwapAbs.ts +82 -0
  116. package/src/swaps/frombtcln_trusted/FromBtcLnTrusted.ts +592 -0
  117. package/src/swaps/frombtcln_trusted/FromBtcLnTrustedSwap.ts +90 -0
  118. package/src/swaps/tobtc_abstract/ToBtcAbs.ts +1249 -0
  119. package/src/swaps/tobtc_abstract/ToBtcSwapAbs.ts +112 -0
  120. package/src/swaps/tobtcln_abstract/ToBtcLnAbs.ts +1422 -0
  121. package/src/swaps/tobtcln_abstract/ToBtcLnSwapAbs.ts +87 -0
  122. package/src/utils/Utils.ts +108 -0
  123. package/src/utils/coinselect2/accumulative.js +32 -0
  124. package/src/utils/coinselect2/accumulative.ts +58 -0
  125. package/src/utils/coinselect2/blackjack.js +29 -0
  126. package/src/utils/coinselect2/blackjack.ts +54 -0
  127. package/src/utils/coinselect2/index.js +16 -0
  128. package/src/utils/coinselect2/index.ts +50 -0
  129. package/src/utils/coinselect2/utils.js +110 -0
  130. package/src/utils/coinselect2/utils.ts +183 -0
  131. package/src/utils/paramcoders/IParamReader.ts +8 -0
  132. package/src/utils/paramcoders/IParamWriter.ts +8 -0
  133. package/src/utils/paramcoders/LegacyParamEncoder.ts +28 -0
  134. package/src/utils/paramcoders/ParamDecoder.ts +219 -0
  135. package/src/utils/paramcoders/ParamEncoder.ts +30 -0
  136. package/src/utils/paramcoders/SchemaVerifier.ts +97 -0
  137. package/src/utils/paramcoders/server/ServerParamDecoder.ts +115 -0
  138. package/src/utils/paramcoders/server/ServerParamEncoder.ts +76 -0
@@ -0,0 +1,29 @@
1
+ import * as BN from "bn.js";
2
+ import { SwapData } from "@atomiqlabs/base";
3
+ import { FromBtcBaseSwap } from "../FromBtcBaseSwap";
4
+ export declare enum FromBtcLnSwapState {
5
+ REFUNDED = -2,
6
+ CANCELED = -1,
7
+ CREATED = 0,
8
+ RECEIVED = 1,
9
+ COMMITED = 2,
10
+ CLAIMED = 3,
11
+ SETTLED = 4
12
+ }
13
+ export declare class FromBtcLnSwapAbs<T extends SwapData = SwapData> extends FromBtcBaseSwap<T, FromBtcLnSwapState> {
14
+ readonly pr: string;
15
+ nonce: number;
16
+ prefix: string;
17
+ timeout: string;
18
+ signature: string;
19
+ feeRate: string;
20
+ secret: string;
21
+ constructor(chainIdentifier: string, pr: string, swapFee: BN, swapFeeInToken: BN);
22
+ constructor(obj: any);
23
+ serialize(): any;
24
+ getSequence(): BN;
25
+ isInitiated(): boolean;
26
+ isFailed(): boolean;
27
+ isSuccess(): boolean;
28
+ getTotalInputAmount(): BN;
29
+ }
@@ -0,0 +1,64 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.FromBtcLnSwapAbs = exports.FromBtcLnSwapState = void 0;
4
+ const BN = require("bn.js");
5
+ const __1 = require("../..");
6
+ const bolt11 = require("@atomiqlabs/bolt11");
7
+ const FromBtcBaseSwap_1 = require("../FromBtcBaseSwap");
8
+ var FromBtcLnSwapState;
9
+ (function (FromBtcLnSwapState) {
10
+ FromBtcLnSwapState[FromBtcLnSwapState["REFUNDED"] = -2] = "REFUNDED";
11
+ FromBtcLnSwapState[FromBtcLnSwapState["CANCELED"] = -1] = "CANCELED";
12
+ FromBtcLnSwapState[FromBtcLnSwapState["CREATED"] = 0] = "CREATED";
13
+ FromBtcLnSwapState[FromBtcLnSwapState["RECEIVED"] = 1] = "RECEIVED";
14
+ FromBtcLnSwapState[FromBtcLnSwapState["COMMITED"] = 2] = "COMMITED";
15
+ FromBtcLnSwapState[FromBtcLnSwapState["CLAIMED"] = 3] = "CLAIMED";
16
+ FromBtcLnSwapState[FromBtcLnSwapState["SETTLED"] = 4] = "SETTLED";
17
+ })(FromBtcLnSwapState = exports.FromBtcLnSwapState || (exports.FromBtcLnSwapState = {}));
18
+ class FromBtcLnSwapAbs extends FromBtcBaseSwap_1.FromBtcBaseSwap {
19
+ constructor(chainIdOrObj, pr, swapFee, swapFeeInToken) {
20
+ if (typeof (chainIdOrObj) === "string") {
21
+ super(chainIdOrObj, swapFee, swapFeeInToken);
22
+ this.state = FromBtcLnSwapState.CREATED;
23
+ this.pr = pr;
24
+ }
25
+ else {
26
+ super(chainIdOrObj);
27
+ this.pr = chainIdOrObj.pr;
28
+ this.secret = chainIdOrObj.secret;
29
+ this.nonce = chainIdOrObj.nonce;
30
+ this.prefix = chainIdOrObj.prefix;
31
+ this.timeout = chainIdOrObj.timeout;
32
+ this.signature = chainIdOrObj.signature;
33
+ this.feeRate = chainIdOrObj.feeRate;
34
+ }
35
+ this.type = __1.SwapHandlerType.FROM_BTCLN;
36
+ }
37
+ serialize() {
38
+ const partialSerialized = super.serialize();
39
+ partialSerialized.pr = this.pr;
40
+ partialSerialized.secret = this.secret;
41
+ partialSerialized.nonce = this.nonce;
42
+ partialSerialized.prefix = this.prefix;
43
+ partialSerialized.timeout = this.timeout;
44
+ partialSerialized.signature = this.signature;
45
+ partialSerialized.feeRate = this.feeRate;
46
+ return partialSerialized;
47
+ }
48
+ getSequence() {
49
+ return null;
50
+ }
51
+ isInitiated() {
52
+ return this.state !== FromBtcLnSwapState.CREATED;
53
+ }
54
+ isFailed() {
55
+ return this.state === FromBtcLnSwapState.CANCELED || this.state === FromBtcLnSwapState.REFUNDED;
56
+ }
57
+ isSuccess() {
58
+ return this.state === FromBtcLnSwapState.SETTLED;
59
+ }
60
+ getTotalInputAmount() {
61
+ return new BN(bolt11.decode(this.pr).millisatoshis).add(new BN(999)).div(new BN(1000));
62
+ }
63
+ }
64
+ exports.FromBtcLnSwapAbs = FromBtcLnSwapAbs;
@@ -0,0 +1,79 @@
1
+ /// <reference types="node" />
2
+ import * as BN from "bn.js";
3
+ import { Express } from "express";
4
+ import { ClaimEvent, InitializeEvent, RefundEvent, SwapData } from "@atomiqlabs/base";
5
+ import { AuthenticatedLnd } from "lightning";
6
+ import { FromBtcLnTrustedSwap, FromBtcLnTrustedSwapState } from "./FromBtcLnTrustedSwap";
7
+ import { FromBtcBaseConfig } from "../FromBtcBaseSwapHandler";
8
+ import { ISwapPrice } from "../ISwapPrice";
9
+ import { MultichainData, SwapHandlerType } from "../SwapHandler";
10
+ import { IIntermediaryStorage } from "../../storage/IIntermediaryStorage";
11
+ import { FromBtcLnBaseSwapHandler } from "../FromBtcLnBaseSwapHandler";
12
+ import EventEmitter from "node:events";
13
+ export type SwapForGasServerConfig = FromBtcBaseConfig & {
14
+ minCltv: BN;
15
+ invoiceTimeoutSeconds?: number;
16
+ };
17
+ export type FromBtcLnTrustedRequestType = {
18
+ address: string;
19
+ amount: BN;
20
+ exactOut?: boolean;
21
+ };
22
+ /**
23
+ * Swap handler handling from BTCLN swaps using submarine swaps
24
+ */
25
+ export declare class FromBtcLnTrusted extends FromBtcLnBaseSwapHandler<FromBtcLnTrustedSwap, FromBtcLnTrustedSwapState> {
26
+ readonly type: SwapHandlerType;
27
+ activeSubscriptions: Map<string, EventEmitter>;
28
+ processedTxIds: Map<string, string>;
29
+ readonly config: SwapForGasServerConfig;
30
+ constructor(storageDirectory: IIntermediaryStorage<FromBtcLnTrustedSwap>, path: string, chains: MultichainData, lnd: AuthenticatedLnd, swapPricing: ISwapPrice, config: SwapForGasServerConfig);
31
+ /**
32
+ * Unsubscribe from the pending lightning network invoice
33
+ *
34
+ * @param paymentHash
35
+ * @private
36
+ */
37
+ private unsubscribeInvoice;
38
+ /**
39
+ * Subscribe to a pending lightning network invoice
40
+ *
41
+ * @param invoiceData
42
+ */
43
+ private subscribeToInvoice;
44
+ /**
45
+ *
46
+ * @param swap
47
+ * @protected
48
+ * @returns {Promise<boolean>} Whether the invoice should be cancelled
49
+ */
50
+ protected processPastSwap(swap: FromBtcLnTrustedSwap): Promise<boolean>;
51
+ protected cancelInvoices(swaps: FromBtcLnTrustedSwap[]): Promise<void>;
52
+ /**
53
+ * Checks past swaps, refunds and deletes ones that are already expired.
54
+ */
55
+ protected processPastSwaps(): Promise<void>;
56
+ private cancelSwapAndInvoice;
57
+ /**
58
+ * Saves the state of received HTLC of the lightning payment
59
+ *
60
+ * @param invoiceData
61
+ * @param invoice
62
+ */
63
+ private htlcReceived;
64
+ /**
65
+ *
66
+ * Checks if the lightning invoice is in HELD state (htlcs received but yet unclaimed)
67
+ *
68
+ * @param paymentHash
69
+ * @throws {DefinedRuntimeError} Will throw if the lightning invoice is not found, or if it isn't in the HELD state
70
+ * @returns the fetched lightning invoice
71
+ */
72
+ private checkInvoiceStatus;
73
+ startRestServer(restServer: Express): void;
74
+ init(): Promise<void>;
75
+ getInfoData(): any;
76
+ protected processClaimEvent(chainIdentifier: string, event: ClaimEvent<SwapData>): Promise<void>;
77
+ protected processInitializeEvent(chainIdentifier: string, event: InitializeEvent<SwapData>): Promise<void>;
78
+ protected processRefundEvent(chainIdentifier: string, event: RefundEvent<SwapData>): Promise<void>;
79
+ }
@@ -0,0 +1,514 @@
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.FromBtcLnTrusted = void 0;
13
+ const BN = require("bn.js");
14
+ const crypto_1 = require("crypto");
15
+ const bolt11 = require("@atomiqlabs/bolt11");
16
+ const lightning_1 = require("lightning");
17
+ const FromBtcLnTrustedSwap_1 = require("./FromBtcLnTrustedSwap");
18
+ const SwapHandler_1 = require("../SwapHandler");
19
+ const Utils_1 = require("../../utils/Utils");
20
+ const SchemaVerifier_1 = require("../../utils/paramcoders/SchemaVerifier");
21
+ const PluginManager_1 = require("../../plugins/PluginManager");
22
+ const FromBtcLnBaseSwapHandler_1 = require("../FromBtcLnBaseSwapHandler");
23
+ const ServerParamDecoder_1 = require("../../utils/paramcoders/server/ServerParamDecoder");
24
+ /**
25
+ * Swap handler handling from BTCLN swaps using submarine swaps
26
+ */
27
+ class FromBtcLnTrusted extends FromBtcLnBaseSwapHandler_1.FromBtcLnBaseSwapHandler {
28
+ constructor(storageDirectory, path, chains, lnd, swapPricing, config) {
29
+ super(storageDirectory, path, chains, lnd, swapPricing);
30
+ this.type = SwapHandler_1.SwapHandlerType.FROM_BTCLN_TRUSTED;
31
+ this.activeSubscriptions = new Map();
32
+ this.processedTxIds = new Map();
33
+ this.config = config;
34
+ this.config.invoiceTimeoutSeconds = this.config.invoiceTimeoutSeconds || 90;
35
+ for (let chainId in chains.chains) {
36
+ this.allowedTokens[chainId] = new Set([chains.chains[chainId].swapContract.getNativeCurrencyAddress()]);
37
+ }
38
+ }
39
+ /**
40
+ * Unsubscribe from the pending lightning network invoice
41
+ *
42
+ * @param paymentHash
43
+ * @private
44
+ */
45
+ unsubscribeInvoice(paymentHash) {
46
+ const sub = this.activeSubscriptions.get(paymentHash);
47
+ if (sub == null)
48
+ return false;
49
+ sub.removeAllListeners();
50
+ this.activeSubscriptions.delete(paymentHash);
51
+ return true;
52
+ }
53
+ /**
54
+ * Subscribe to a pending lightning network invoice
55
+ *
56
+ * @param invoiceData
57
+ */
58
+ subscribeToInvoice(invoiceData) {
59
+ const hash = invoiceData.getHash();
60
+ //Already subscribed
61
+ if (this.activeSubscriptions.has(invoiceData.getHash()))
62
+ return;
63
+ const sub = (0, lightning_1.subscribeToInvoice)({ id: hash, lnd: this.LND });
64
+ this.swapLogger.debug(invoiceData, "subscribeToInvoice(): Subscribed to invoice payment");
65
+ sub.on('invoice_updated', (invoice) => {
66
+ this.swapLogger.debug(invoiceData, "subscribeToInvoice(): invoice_updated: ", invoice);
67
+ if (!invoice.is_held)
68
+ return;
69
+ this.htlcReceived(invoiceData, invoice).catch(e => console.error(e));
70
+ sub.removeAllListeners();
71
+ this.activeSubscriptions.delete(hash);
72
+ });
73
+ this.activeSubscriptions.set(hash, sub);
74
+ }
75
+ /**
76
+ *
77
+ * @param swap
78
+ * @protected
79
+ * @returns {Promise<boolean>} Whether the invoice should be cancelled
80
+ */
81
+ processPastSwap(swap) {
82
+ return __awaiter(this, void 0, void 0, function* () {
83
+ if (swap.state === FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.CANCELED)
84
+ return true;
85
+ if (swap.state === FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.REFUNDED)
86
+ return true;
87
+ const parsedPR = bolt11.decode(swap.pr);
88
+ const invoice = yield (0, lightning_1.getInvoice)({
89
+ id: parsedPR.tagsObject.payment_hash,
90
+ lnd: this.LND
91
+ });
92
+ if (invoice.is_held) {
93
+ //Adjust the state of the swap and expiry
94
+ try {
95
+ yield this.htlcReceived(swap, invoice);
96
+ //Result is either FromBtcLnTrustedSwapState.RECEIVED or FromBtcLnTrustedSwapState.CANCELED
97
+ }
98
+ catch (e) {
99
+ console.error(e);
100
+ }
101
+ }
102
+ else if (!invoice.is_confirmed) {
103
+ //Not paid
104
+ const isInvoiceExpired = parsedPR.timeExpireDate < Date.now() / 1000;
105
+ if (isInvoiceExpired) {
106
+ yield swap.setState(FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.CANCELED);
107
+ return true;
108
+ }
109
+ this.subscribeToInvoice(swap);
110
+ }
111
+ return false;
112
+ });
113
+ }
114
+ cancelInvoices(swaps) {
115
+ return __awaiter(this, void 0, void 0, function* () {
116
+ for (let swap of swaps) {
117
+ //Cancel invoices
118
+ try {
119
+ const paymentHash = swap.getHash();
120
+ yield (0, lightning_1.cancelHodlInvoice)({
121
+ lnd: this.LND,
122
+ id: paymentHash
123
+ });
124
+ this.unsubscribeInvoice(paymentHash);
125
+ this.swapLogger.info(swap, "cancelInvoices(): invoice cancelled!");
126
+ yield this.removeSwapData(swap);
127
+ }
128
+ catch (e) {
129
+ this.swapLogger.error(swap, "cancelInvoices(): cannot cancel hodl invoice id", e);
130
+ }
131
+ }
132
+ });
133
+ }
134
+ /**
135
+ * Checks past swaps, refunds and deletes ones that are already expired.
136
+ */
137
+ processPastSwaps() {
138
+ return __awaiter(this, void 0, void 0, function* () {
139
+ const cancelInvoices = [];
140
+ const queriedData = yield this.storageManager.query([
141
+ {
142
+ key: "state",
143
+ value: [
144
+ FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.CREATED,
145
+ FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.RECEIVED,
146
+ FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.SENT,
147
+ FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.CONFIRMED,
148
+ FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.CANCELED,
149
+ FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.REFUNDED,
150
+ ]
151
+ }
152
+ ]);
153
+ for (let swap of queriedData) {
154
+ if (yield this.processPastSwap(swap))
155
+ cancelInvoices.push(swap);
156
+ }
157
+ yield this.cancelInvoices(cancelInvoices);
158
+ });
159
+ }
160
+ cancelSwapAndInvoice(swap) {
161
+ return __awaiter(this, void 0, void 0, function* () {
162
+ if (swap.state !== FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.RECEIVED)
163
+ return;
164
+ yield swap.setState(FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.CANCELED);
165
+ const paymentHash = swap.getHash();
166
+ yield (0, lightning_1.cancelHodlInvoice)({
167
+ id: paymentHash,
168
+ lnd: this.LND
169
+ });
170
+ this.unsubscribeInvoice(paymentHash);
171
+ yield this.removeSwapData(swap);
172
+ this.swapLogger.info(swap, "cancelSwapAndInvoice(): swap removed & invoice cancelled, invoice: ", swap.pr);
173
+ });
174
+ }
175
+ /**
176
+ * Saves the state of received HTLC of the lightning payment
177
+ *
178
+ * @param invoiceData
179
+ * @param invoice
180
+ */
181
+ htlcReceived(invoiceData, invoice) {
182
+ return __awaiter(this, void 0, void 0, function* () {
183
+ const { swapContract, signer } = this.getChain(invoiceData.chainIdentifier);
184
+ //Important to prevent race condition and issuing 2 signed init messages at the same time
185
+ if (invoiceData.state === FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.CREATED) {
186
+ if (invoiceData.metadata != null)
187
+ invoiceData.metadata.times.htlcReceived = Date.now();
188
+ yield invoiceData.setState(FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.RECEIVED);
189
+ yield this.storageManager.saveData(invoice.id, null, invoiceData);
190
+ }
191
+ if (invoiceData.state === FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.RECEIVED) {
192
+ const balance = swapContract.getBalance(signer.getAddress(), swapContract.getNativeCurrencyAddress(), false);
193
+ try {
194
+ yield this.checkBalance(invoiceData.output, balance, null);
195
+ if (invoiceData.metadata != null)
196
+ invoiceData.metadata.times.htlcBalanceChecked = Date.now();
197
+ }
198
+ catch (e) {
199
+ yield this.cancelSwapAndInvoice(invoiceData);
200
+ throw e;
201
+ }
202
+ if (invoiceData.state !== FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.RECEIVED)
203
+ return;
204
+ let unlock = invoiceData.lock(30 * 1000);
205
+ if (unlock == null)
206
+ return;
207
+ const txns = yield swapContract.txsTransfer(signer.getAddress(), swapContract.getNativeCurrencyAddress(), invoiceData.output, invoiceData.dstAddress);
208
+ yield swapContract.sendAndConfirm(signer, txns, true, null, false, (txId, rawTx) => __awaiter(this, void 0, void 0, function* () {
209
+ invoiceData.txIds = { init: txId };
210
+ invoiceData.scRawTx = rawTx;
211
+ if (invoiceData.state === FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.RECEIVED) {
212
+ yield invoiceData.setState(FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.SENT);
213
+ yield this.storageManager.saveData(invoice.id, null, invoiceData);
214
+ }
215
+ if (unlock != null)
216
+ unlock();
217
+ unlock = null;
218
+ }));
219
+ }
220
+ if (invoiceData.state === FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.SENT) {
221
+ const txStatus = yield swapContract.getTxStatus(invoiceData.scRawTx);
222
+ if (txStatus === "not_found") {
223
+ //Retry
224
+ invoiceData.txIds = { init: null };
225
+ invoiceData.scRawTx = null;
226
+ yield invoiceData.setState(FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.RECEIVED);
227
+ yield this.storageManager.saveData(invoice.id, null, invoiceData);
228
+ }
229
+ if (txStatus === "reverted") {
230
+ //Cancel invoice
231
+ yield invoiceData.setState(FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.REFUNDED);
232
+ yield this.storageManager.saveData(invoice.id, null, invoiceData);
233
+ yield (0, lightning_1.cancelHodlInvoice)({
234
+ id: invoice.id,
235
+ lnd: this.LND
236
+ });
237
+ this.unsubscribeInvoice(invoice.id);
238
+ yield this.removeSwapData(invoice.id, null);
239
+ this.swapLogger.info(invoiceData, "htlcReceived(): transaction reverted, refunding lightning: ", invoiceData.pr);
240
+ throw {
241
+ code: 20002,
242
+ msg: "Transaction reverted"
243
+ };
244
+ }
245
+ if (txStatus === "success") {
246
+ //Successfully paid
247
+ yield invoiceData.setState(FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.CONFIRMED);
248
+ yield this.storageManager.saveData(invoice.id, null, invoiceData);
249
+ }
250
+ }
251
+ if (invoiceData.state === FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.CONFIRMED) {
252
+ yield (0, lightning_1.settleHodlInvoice)({
253
+ lnd: this.LND,
254
+ secret: invoiceData.secret
255
+ });
256
+ if (invoiceData.metadata != null)
257
+ invoiceData.metadata.times.htlcSettled = Date.now();
258
+ const paymentHash = invoiceData.getHash();
259
+ this.processedTxIds.set(paymentHash, invoiceData.txIds.init);
260
+ yield invoiceData.setState(FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.SETTLED);
261
+ this.unsubscribeInvoice(paymentHash);
262
+ this.swapLogger.info(invoiceData, "htlcReceived(): invoice settled, invoice: " + invoiceData.pr + " scTxId: " + invoiceData.txIds.init);
263
+ yield this.removeSwapData(invoiceData);
264
+ }
265
+ });
266
+ }
267
+ /**
268
+ *
269
+ * Checks if the lightning invoice is in HELD state (htlcs received but yet unclaimed)
270
+ *
271
+ * @param paymentHash
272
+ * @throws {DefinedRuntimeError} Will throw if the lightning invoice is not found, or if it isn't in the HELD state
273
+ * @returns the fetched lightning invoice
274
+ */
275
+ checkInvoiceStatus(paymentHash) {
276
+ return __awaiter(this, void 0, void 0, function* () {
277
+ const invoice = yield (0, lightning_1.getInvoice)({
278
+ id: paymentHash,
279
+ lnd: this.LND
280
+ });
281
+ const isInvoiceFound = invoice != null;
282
+ if (!isInvoiceFound)
283
+ throw {
284
+ _httpStatus: 200,
285
+ code: 10001,
286
+ msg: "Invoice expired/canceled"
287
+ };
288
+ const arr = invoice.description.split("-");
289
+ let chainIdentifier;
290
+ let address;
291
+ if (arr.length > 2 && arr[1] === "GAS") {
292
+ chainIdentifier = arr[0];
293
+ address = arr[2];
294
+ }
295
+ else {
296
+ chainIdentifier = this.chains.default;
297
+ address = invoice.description;
298
+ }
299
+ const { swapContract } = this.getChain(chainIdentifier);
300
+ if (!swapContract.isValidAddress(address))
301
+ throw {
302
+ _httpStatus: 200,
303
+ code: 10001,
304
+ msg: "Invoice expired/canceled"
305
+ };
306
+ const isBeingPaid = invoice.is_held;
307
+ if (!isBeingPaid) {
308
+ if (invoice.is_canceled)
309
+ throw {
310
+ _httpStatus: 200,
311
+ code: 10001,
312
+ msg: "Invoice expired/canceled"
313
+ };
314
+ if (invoice.is_confirmed) {
315
+ const scTxId = this.processedTxIds.get(paymentHash);
316
+ throw {
317
+ _httpStatus: 200,
318
+ code: 10000,
319
+ msg: "Invoice already paid",
320
+ data: {
321
+ txId: scTxId
322
+ }
323
+ };
324
+ }
325
+ throw {
326
+ _httpStatus: 200,
327
+ code: 10010,
328
+ msg: "Invoice yet unpaid"
329
+ };
330
+ }
331
+ return invoice;
332
+ });
333
+ }
334
+ startRestServer(restServer) {
335
+ const createInvoice = (0, Utils_1.expressHandlerWrapper)((req, res) => __awaiter(this, void 0, void 0, function* () {
336
+ var _a;
337
+ const metadata = { request: {}, times: {} };
338
+ const chainIdentifier = (_a = req.query.chain) !== null && _a !== void 0 ? _a : this.chains.default;
339
+ const { swapContract, signer } = this.getChain(chainIdentifier);
340
+ metadata.times.requestReceived = Date.now();
341
+ /**
342
+ * address: string solana address of the recipient
343
+ * amount: string amount (in lamports/smart chain base units) of the invoice
344
+ */
345
+ const parsedBody = yield req.paramReader.getParams({
346
+ address: (val) => val != null &&
347
+ typeof (val) === "string" &&
348
+ swapContract.isValidAddress(val) ? val : null,
349
+ amount: SchemaVerifier_1.FieldTypeEnum.BN,
350
+ exactOut: SchemaVerifier_1.FieldTypeEnum.BooleanOptional
351
+ });
352
+ if (parsedBody == null)
353
+ throw {
354
+ code: 20100,
355
+ msg: "Invalid request body"
356
+ };
357
+ metadata.request = parsedBody;
358
+ const requestedAmount = { input: !parsedBody.exactOut, amount: parsedBody.amount };
359
+ const request = {
360
+ chainIdentifier,
361
+ raw: req,
362
+ parsed: parsedBody,
363
+ metadata
364
+ };
365
+ const useToken = swapContract.getNativeCurrencyAddress();
366
+ //Check request params
367
+ const fees = yield this.preCheckAmounts(request, requestedAmount, useToken);
368
+ metadata.times.requestChecked = Date.now();
369
+ //Create abortController for parallel prefetches
370
+ const responseStream = res.responseStream;
371
+ const abortController = this.getAbortController(responseStream);
372
+ //Pre-fetch data
373
+ const { pricePrefetchPromise } = this.getFromBtcPricePrefetches(chainIdentifier, useToken, abortController);
374
+ const balancePrefetch = swapContract.getBalance(signer.getAddress(), useToken, false).catch(e => {
375
+ this.logger.error("getBalancePrefetch(): balancePrefetch error: ", e);
376
+ abortController.abort(e);
377
+ return null;
378
+ });
379
+ const channelsPrefetch = this.getChannelsPrefetch(abortController);
380
+ //Check valid amount specified (min/max)
381
+ const { amountBD, swapFee, swapFeeInToken, totalInToken } = yield this.checkFromBtcAmount(request, requestedAmount, fees, useToken, abortController.signal, pricePrefetchPromise);
382
+ metadata.times.priceCalculated = Date.now();
383
+ //Check if we have enough funds to honor the request
384
+ yield this.checkBalance(totalInToken, balancePrefetch, abortController.signal);
385
+ yield this.checkInboundLiquidity(amountBD, channelsPrefetch, abortController.signal);
386
+ metadata.times.balanceChecked = Date.now();
387
+ const secret = (0, crypto_1.randomBytes)(32);
388
+ const hash = (0, crypto_1.createHash)("sha256").update(secret).digest();
389
+ const hodlInvoiceObj = {
390
+ description: chainIdentifier + "-GAS-" + parsedBody.address,
391
+ cltv_delta: this.config.minCltv.add(new BN(5)).toNumber(),
392
+ expires_at: new Date(Date.now() + (this.config.invoiceTimeoutSeconds * 1000)).toISOString(),
393
+ id: hash.toString("hex"),
394
+ mtokens: amountBD.mul(new BN(1000)).toString(10),
395
+ lnd: null
396
+ };
397
+ metadata.invoiceRequest = Object.assign({}, hodlInvoiceObj);
398
+ hodlInvoiceObj.lnd = this.LND;
399
+ const hodlInvoice = yield (0, lightning_1.createHodlInvoice)(hodlInvoiceObj);
400
+ abortController.signal.throwIfAborted();
401
+ metadata.times.invoiceCreated = Date.now();
402
+ metadata.invoiceResponse = Object.assign({}, hodlInvoice);
403
+ console.log("[From BTC-LN: REST.CreateInvoice] hodl invoice created: ", hodlInvoice);
404
+ const createdSwap = new FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwap(chainIdentifier, hodlInvoice.request, swapFee, swapFeeInToken, totalInToken, secret.toString("hex"), parsedBody.address);
405
+ metadata.times.swapCreated = Date.now();
406
+ createdSwap.metadata = metadata;
407
+ yield PluginManager_1.PluginManager.swapCreate(createdSwap);
408
+ yield this.storageManager.saveData(hash.toString("hex"), null, createdSwap);
409
+ this.subscribeToInvoice(createdSwap);
410
+ this.swapLogger.info(createdSwap, "REST: /createInvoice: Created swap invoice: " + hodlInvoice.request + " amount: " + amountBD.toString(10));
411
+ yield responseStream.writeParamsAndEnd({
412
+ msg: "Success",
413
+ code: 10000,
414
+ data: {
415
+ pr: hodlInvoice.request,
416
+ swapFee: swapFeeInToken.toString(10),
417
+ total: totalInToken.toString(10),
418
+ intermediaryKey: signer.getAddress()
419
+ }
420
+ });
421
+ }));
422
+ restServer.use(this.path + "/createInvoice", (0, ServerParamDecoder_1.serverParamDecoder)(10 * 1000));
423
+ restServer.post(this.path + "/createInvoice", createInvoice);
424
+ const getInvoiceStatus = (0, Utils_1.expressHandlerWrapper)((req, res) => __awaiter(this, void 0, void 0, function* () {
425
+ /**
426
+ * paymentHash: string payment hash of the invoice
427
+ */
428
+ const parsedBody = (0, SchemaVerifier_1.verifySchema)(Object.assign(Object.assign({}, req.body), req.query), {
429
+ paymentHash: (val) => val != null &&
430
+ typeof (val) === "string" &&
431
+ val.length === 64 &&
432
+ Utils_1.HEX_REGEX.test(val) ? val : null,
433
+ });
434
+ yield this.checkInvoiceStatus(parsedBody.paymentHash);
435
+ const invoiceData = yield this.storageManager.getData(parsedBody.paymentHash, null);
436
+ if (invoiceData == null)
437
+ throw {
438
+ _httpStatus: 200,
439
+ code: 10001,
440
+ msg: "Invoice expired/canceled"
441
+ };
442
+ if (invoiceData.state === FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.CANCELED ||
443
+ invoiceData.state === FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.REFUNDED)
444
+ throw {
445
+ _httpStatus: 200,
446
+ code: 10001,
447
+ msg: "Invoice expired/canceled"
448
+ };
449
+ if (invoiceData.state === FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.CREATED)
450
+ throw {
451
+ _httpStatus: 200,
452
+ code: 10010,
453
+ msg: "Invoice yet unpaid"
454
+ };
455
+ if (invoiceData.state === FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.RECEIVED)
456
+ throw {
457
+ _httpStatus: 200,
458
+ code: 10011,
459
+ msg: "Invoice received, payment processing"
460
+ };
461
+ if (invoiceData.state === FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.SENT)
462
+ throw {
463
+ _httpStatus: 200,
464
+ code: 10012,
465
+ msg: "Tx sent",
466
+ data: {
467
+ txId: invoiceData.txIds.init
468
+ }
469
+ };
470
+ if (invoiceData.state === FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.CONFIRMED)
471
+ throw {
472
+ _httpStatus: 200,
473
+ code: 10000,
474
+ msg: "Success, tx confirmed",
475
+ data: {
476
+ txId: invoiceData.txIds.init
477
+ }
478
+ };
479
+ if (invoiceData.state === FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.SETTLED)
480
+ throw {
481
+ _httpStatus: 200,
482
+ code: 10000,
483
+ msg: "Success, tx confirmed - invoice settled",
484
+ data: {
485
+ txId: invoiceData.txIds.init
486
+ }
487
+ };
488
+ }));
489
+ restServer.post(this.path + "/getInvoiceStatus", getInvoiceStatus);
490
+ restServer.get(this.path + "/getInvoiceStatus", getInvoiceStatus);
491
+ this.logger.info("started at path: ", this.path);
492
+ }
493
+ init() {
494
+ return __awaiter(this, void 0, void 0, function* () {
495
+ yield this.storageManager.loadData(FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwap);
496
+ yield PluginManager_1.PluginManager.serviceInitialize(this);
497
+ });
498
+ }
499
+ getInfoData() {
500
+ return {
501
+ minCltv: this.config.minCltv.toNumber()
502
+ };
503
+ }
504
+ processClaimEvent(chainIdentifier, event) {
505
+ return Promise.resolve();
506
+ }
507
+ processInitializeEvent(chainIdentifier, event) {
508
+ return Promise.resolve();
509
+ }
510
+ processRefundEvent(chainIdentifier, event) {
511
+ return Promise.resolve();
512
+ }
513
+ }
514
+ exports.FromBtcLnTrusted = FromBtcLnTrusted;