@atomiqlabs/lp-lib 10.3.11 → 11.0.0
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 +2 -1
- package/dist/index.js +2 -4
- package/dist/plugins/IPlugin.d.ts +3 -2
- package/dist/plugins/PluginManager.d.ts +3 -2
- package/dist/plugins/PluginManager.js +2 -2
- package/dist/swaps/FromBtcBaseSwap.d.ts +5 -1
- package/dist/swaps/FromBtcBaseSwap.js +20 -0
- package/dist/swaps/FromBtcBaseSwapHandler.d.ts +1 -0
- package/dist/swaps/FromBtcBaseSwapHandler.js +1 -1
- package/dist/swaps/FromBtcLnBaseSwapHandler.d.ts +8 -6
- package/dist/swaps/FromBtcLnBaseSwapHandler.js +7 -5
- package/dist/swaps/SwapHandler.d.ts +1 -4
- package/dist/swaps/SwapHandler.js +1 -2
- package/dist/swaps/SwapHandlerSwap.d.ts +4 -0
- package/dist/swaps/SwapHandlerSwap.js +9 -1
- package/dist/swaps/ToBtcBaseSwap.d.ts +3 -1
- package/dist/swaps/ToBtcBaseSwap.js +8 -2
- package/dist/swaps/ToBtcBaseSwapHandler.d.ts +1 -0
- package/dist/swaps/ToBtcBaseSwapHandler.js +1 -1
- package/dist/swaps/frombtc_abstract/FromBtcAbs.d.ts +3 -5
- package/dist/swaps/frombtc_abstract/FromBtcAbs.js +18 -25
- package/dist/swaps/frombtc_abstract/FromBtcSwapAbs.d.ts +1 -4
- package/dist/swaps/frombtc_abstract/FromBtcSwapAbs.js +3 -16
- package/dist/swaps/frombtc_trusted/FromBtcTrusted.d.ts +6 -9
- package/dist/swaps/frombtc_trusted/FromBtcTrusted.js +238 -137
- package/dist/swaps/frombtc_trusted/FromBtcTrustedSwap.d.ts +9 -6
- package/dist/swaps/frombtc_trusted/FromBtcTrustedSwap.js +15 -10
- package/dist/swaps/frombtcln_abstract/FromBtcLnAbs.d.ts +2 -2
- package/dist/swaps/frombtcln_abstract/FromBtcLnAbs.js +42 -62
- package/dist/swaps/frombtcln_abstract/FromBtcLnSwapAbs.d.ts +1 -6
- package/dist/swaps/frombtcln_abstract/FromBtcLnSwapAbs.js +2 -14
- package/dist/swaps/frombtcln_trusted/FromBtcLnTrusted.d.ts +3 -5
- package/dist/swaps/frombtcln_trusted/FromBtcLnTrusted.js +64 -80
- package/dist/swaps/frombtcln_trusted/FromBtcLnTrustedSwap.d.ts +1 -2
- package/dist/swaps/frombtcln_trusted/FromBtcLnTrustedSwap.js +5 -8
- package/dist/swaps/tobtc_abstract/ToBtcAbs.d.ts +5 -125
- package/dist/swaps/tobtc_abstract/ToBtcAbs.js +41 -334
- package/dist/swaps/tobtc_abstract/ToBtcSwapAbs.d.ts +1 -4
- package/dist/swaps/tobtc_abstract/ToBtcSwapAbs.js +2 -11
- package/dist/swaps/tobtcln_abstract/ToBtcLnAbs.d.ts +5 -55
- package/dist/swaps/tobtcln_abstract/ToBtcLnAbs.js +152 -398
- package/dist/swaps/tobtcln_abstract/ToBtcLnSwapAbs.d.ts +1 -6
- package/dist/swaps/tobtcln_abstract/ToBtcLnSwapAbs.js +2 -15
- package/dist/utils/Utils.d.ts +0 -10
- package/dist/utils/Utils.js +1 -34
- package/dist/wallets/IBitcoinWallet.d.ts +62 -0
- package/dist/wallets/IBitcoinWallet.js +2 -0
- package/dist/wallets/ILightningWallet.d.ts +118 -0
- package/dist/wallets/ILightningWallet.js +37 -0
- package/package.json +4 -9
- package/src/index.ts +3 -5
- package/src/plugins/IPlugin.ts +4 -2
- package/src/plugins/PluginManager.ts +6 -3
- package/src/swaps/FromBtcBaseSwap.ts +24 -1
- package/src/swaps/FromBtcBaseSwapHandler.ts +6 -2
- package/src/swaps/FromBtcLnBaseSwapHandler.ts +22 -6
- package/src/swaps/SwapHandler.ts +1 -8
- package/src/swaps/SwapHandlerSwap.ts +14 -1
- package/src/swaps/ToBtcBaseSwap.ts +12 -3
- package/src/swaps/ToBtcBaseSwapHandler.ts +6 -2
- package/src/swaps/frombtc_abstract/FromBtcAbs.ts +24 -28
- package/src/swaps/frombtc_abstract/FromBtcSwapAbs.ts +3 -18
- package/src/swaps/frombtc_trusted/FromBtcTrusted.ts +260 -159
- package/src/swaps/frombtc_trusted/FromBtcTrustedSwap.ts +22 -15
- package/src/swaps/frombtcln_abstract/FromBtcLnAbs.ts +69 -79
- package/src/swaps/frombtcln_abstract/FromBtcLnSwapAbs.ts +3 -20
- package/src/swaps/frombtcln_trusted/FromBtcLnTrusted.ts +80 -97
- package/src/swaps/frombtcln_trusted/FromBtcLnTrustedSwap.ts +6 -9
- package/src/swaps/tobtc_abstract/ToBtcAbs.ts +52 -410
- package/src/swaps/tobtc_abstract/ToBtcSwapAbs.ts +3 -18
- package/src/swaps/tobtcln_abstract/ToBtcLnAbs.ts +157 -434
- package/src/swaps/tobtcln_abstract/ToBtcLnSwapAbs.ts +3 -20
- package/src/utils/Utils.ts +0 -31
- package/src/wallets/IBitcoinWallet.ts +66 -0
- package/src/wallets/ILightningWallet.ts +179 -0
- package/dist/fees/OneDollarFeeEstimator.d.ts +0 -16
- package/dist/fees/OneDollarFeeEstimator.js +0 -71
- package/dist/utils/coinselect2/accumulative.d.ts +0 -6
- package/dist/utils/coinselect2/accumulative.js +0 -44
- package/dist/utils/coinselect2/blackjack.d.ts +0 -6
- package/dist/utils/coinselect2/blackjack.js +0 -41
- package/dist/utils/coinselect2/index.d.ts +0 -16
- package/dist/utils/coinselect2/index.js +0 -40
- package/dist/utils/coinselect2/utils.d.ts +0 -64
- package/dist/utils/coinselect2/utils.js +0 -121
- package/src/fees/OneDollarFeeEstimator.ts +0 -95
- package/src/utils/coinselect2/accumulative.js +0 -32
- package/src/utils/coinselect2/accumulative.ts +0 -58
- package/src/utils/coinselect2/blackjack.js +0 -29
- package/src/utils/coinselect2/blackjack.ts +0 -54
- package/src/utils/coinselect2/index.js +0 -16
- package/src/utils/coinselect2/index.ts +0 -50
- package/src/utils/coinselect2/utils.js +0 -110
- package/src/utils/coinselect2/utils.ts +0 -183
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import * as BN from "bn.js";
|
|
2
|
-
import * as bolt11 from "@atomiqlabs/bolt11";
|
|
3
2
|
import {SwapData} from "@atomiqlabs/base";
|
|
4
3
|
import {SwapHandlerType} from "../..";
|
|
5
4
|
import {deserializeBN, serializeBN} from "../../utils/Utils";
|
|
@@ -18,31 +17,28 @@ export enum ToBtcLnSwapState {
|
|
|
18
17
|
export class ToBtcLnSwapAbs<T extends SwapData = SwapData> extends ToBtcBaseSwap<T, ToBtcLnSwapState> {
|
|
19
18
|
|
|
20
19
|
readonly pr: string;
|
|
21
|
-
readonly signatureExpiry: BN;
|
|
22
20
|
|
|
23
21
|
secret: string;
|
|
24
22
|
|
|
25
23
|
constructor(
|
|
26
24
|
chainIdentifier: string,
|
|
27
25
|
pr: string,
|
|
26
|
+
amountMtokens: BN,
|
|
28
27
|
swapFee: BN,
|
|
29
28
|
swapFeeInToken: BN,
|
|
30
29
|
quotedNetworkFee: BN,
|
|
31
30
|
quotedNetworkFeeInToken: BN,
|
|
32
|
-
signatureExpiry: BN
|
|
33
31
|
);
|
|
34
32
|
constructor(obj: any);
|
|
35
33
|
|
|
36
|
-
constructor(chainIdOrObj: string | any, pr?: string,
|
|
34
|
+
constructor(chainIdOrObj: string | any, pr?: string, amount?: BN, swapFee?: BN, swapFeeInToken?: BN, quotedNetworkFee?: BN, quotedNetworkFeeInToken?: BN) {
|
|
37
35
|
if(typeof(chainIdOrObj)==="string") {
|
|
38
|
-
super(chainIdOrObj, swapFee, swapFeeInToken, quotedNetworkFee, quotedNetworkFeeInToken);
|
|
36
|
+
super(chainIdOrObj, amount.add(new BN(999)).div(new BN(1000)), swapFee, swapFeeInToken, quotedNetworkFee, quotedNetworkFeeInToken);
|
|
39
37
|
this.state = ToBtcLnSwapState.SAVED;
|
|
40
38
|
this.pr = pr;
|
|
41
|
-
this.signatureExpiry = signatureExpiry;
|
|
42
39
|
} else {
|
|
43
40
|
super(chainIdOrObj);
|
|
44
41
|
this.pr = chainIdOrObj.pr;
|
|
45
|
-
this.signatureExpiry = deserializeBN(chainIdOrObj.signatureExpiry);
|
|
46
42
|
this.secret = chainIdOrObj.secret;
|
|
47
43
|
|
|
48
44
|
//Compatibility with older versions
|
|
@@ -55,19 +51,10 @@ export class ToBtcLnSwapAbs<T extends SwapData = SwapData> extends ToBtcBaseSwap
|
|
|
55
51
|
serialize(): any {
|
|
56
52
|
const partialSerialized = super.serialize();
|
|
57
53
|
partialSerialized.pr = this.pr;
|
|
58
|
-
partialSerialized.signatureExpiry = serializeBN(this.signatureExpiry);
|
|
59
54
|
partialSerialized.secret = this.secret;
|
|
60
55
|
return partialSerialized;
|
|
61
56
|
}
|
|
62
57
|
|
|
63
|
-
getHash(): string {
|
|
64
|
-
return bolt11.decode(this.pr).tagsObject.payment_hash;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
getHashBuffer(): Buffer {
|
|
68
|
-
return Buffer.from(bolt11.decode(this.pr).tagsObject.payment_hash, "hex");
|
|
69
|
-
}
|
|
70
|
-
|
|
71
58
|
isInitiated(): boolean {
|
|
72
59
|
return this.state!==ToBtcLnSwapState.SAVED;
|
|
73
60
|
}
|
|
@@ -80,8 +67,4 @@ export class ToBtcLnSwapAbs<T extends SwapData = SwapData> extends ToBtcBaseSwap
|
|
|
80
67
|
return this.state===ToBtcLnSwapState.CLAIMED;
|
|
81
68
|
}
|
|
82
69
|
|
|
83
|
-
getOutputAmount(): BN {
|
|
84
|
-
return new BN(bolt11.decode(this.pr).millisatoshis).add(new BN(999)).div(new BN(1000));
|
|
85
|
-
}
|
|
86
|
-
|
|
87
70
|
}
|
package/src/utils/Utils.ts
CHANGED
|
@@ -68,22 +68,6 @@ export function getLogger(prefix: string) {
|
|
|
68
68
|
|
|
69
69
|
export const HEX_REGEX = /[0-9a-fA-F]+/;
|
|
70
70
|
|
|
71
|
-
export function shuffle(array: any[]) {
|
|
72
|
-
let currentIndex = array.length;
|
|
73
|
-
|
|
74
|
-
// While there remain elements to shuffle...
|
|
75
|
-
while (currentIndex != 0) {
|
|
76
|
-
|
|
77
|
-
// Pick a remaining element...
|
|
78
|
-
let randomIndex = Math.floor(Math.random() * currentIndex);
|
|
79
|
-
currentIndex--;
|
|
80
|
-
|
|
81
|
-
// And swap it with the current element.
|
|
82
|
-
[array[currentIndex], array[randomIndex]] = [
|
|
83
|
-
array[randomIndex], array[currentIndex]];
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
|
|
87
71
|
export function serializeBN(bn: BN | null): string | null {
|
|
88
72
|
return bn==null ? null : bn.toString(10);
|
|
89
73
|
}
|
|
@@ -91,18 +75,3 @@ export function serializeBN(bn: BN | null): string | null {
|
|
|
91
75
|
export function deserializeBN(str: string | null): BN | null {
|
|
92
76
|
return str==null ? null : new BN(str);
|
|
93
77
|
}
|
|
94
|
-
|
|
95
|
-
/**
|
|
96
|
-
* Handles & throws LND error if the error is:
|
|
97
|
-
* - network error
|
|
98
|
-
* - server side (LND) internal error
|
|
99
|
-
* - malformed input data error
|
|
100
|
-
*
|
|
101
|
-
* @param e
|
|
102
|
-
*/
|
|
103
|
-
export function handleLndError(e: any) {
|
|
104
|
-
if(!Array.isArray(e)) throw e; //Throw errors that are not originating from the SDK
|
|
105
|
-
if(typeof(e[0])!=="number") throw e; //Throw errors that don't have proper format
|
|
106
|
-
if(e[0]>=500 && e[0]<600) throw e; //Throw server errors 5xx
|
|
107
|
-
if(e[0]===400) throw e; //Throw malformed request data errors
|
|
108
|
-
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import BN from "bn.js";
|
|
2
|
+
import {Psbt, Transaction} from "bitcoinjs-lib";
|
|
3
|
+
import {BtcTx} from "@atomiqlabs/base";
|
|
4
|
+
import {Command} from "@atomiqlabs/server-base";
|
|
5
|
+
|
|
6
|
+
export type BitcoinUtxo = {
|
|
7
|
+
address: string,
|
|
8
|
+
type: "p2wpkh" | "p2sh-p2wpkh" | "p2tr",
|
|
9
|
+
confirmations: number,
|
|
10
|
+
outputScript: Buffer,
|
|
11
|
+
value: number,
|
|
12
|
+
txId: string,
|
|
13
|
+
vout: number
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export type SignPsbtResponse = {
|
|
17
|
+
psbt: Psbt,
|
|
18
|
+
tx: Transaction,
|
|
19
|
+
raw: string,
|
|
20
|
+
txId: string,
|
|
21
|
+
networkFee: number
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export interface IBitcoinWallet {
|
|
25
|
+
|
|
26
|
+
init(): Promise<void>;
|
|
27
|
+
|
|
28
|
+
isReady(): boolean;
|
|
29
|
+
getStatus(): string;
|
|
30
|
+
getStatusInfo(): Promise<Record<string, string>>;
|
|
31
|
+
getCommands(): Command<any>[];
|
|
32
|
+
|
|
33
|
+
toOutputScript(address: string): Buffer;
|
|
34
|
+
|
|
35
|
+
getAddressType(): "p2wpkh" | "p2sh-p2wpkh" | "p2tr";
|
|
36
|
+
/**
|
|
37
|
+
* Returns an unused address suitable for receiving
|
|
38
|
+
*/
|
|
39
|
+
getAddress(): Promise<string>;
|
|
40
|
+
/**
|
|
41
|
+
* Adds previously returned address (with getAddress call), to the pool of unused addresses
|
|
42
|
+
* @param address
|
|
43
|
+
*/
|
|
44
|
+
addUnusedAddress(address: string): Promise<void>;
|
|
45
|
+
|
|
46
|
+
getUtxos(): Promise<BitcoinUtxo[]>;
|
|
47
|
+
getBalance(): Promise<{confirmed: number, unconfirmed: number}>;
|
|
48
|
+
/**
|
|
49
|
+
* Returns required reserve amount that needs to be kept in the wallet (for e.g. lightning anchor channels)
|
|
50
|
+
*/
|
|
51
|
+
getRequiredReserve(): Promise<number>;
|
|
52
|
+
getWalletTransactions(startHeight?: number): Promise<BtcTx[]>;
|
|
53
|
+
getWalletTransaction(txId: string): Promise<BtcTx | null>;
|
|
54
|
+
subscribeToWalletTransactions(callback: (tx: BtcTx) => void, abortSignal?: AbortSignal): void;
|
|
55
|
+
|
|
56
|
+
signPsbt(psbt: Psbt): Promise<SignPsbtResponse>;
|
|
57
|
+
sendRawTransaction(tx: string): Promise<void>;
|
|
58
|
+
getSignedTransaction(destination: string, amount: number, feeRate?: number, nonce?: BN, maxAllowedFeeRate?: number): Promise<SignPsbtResponse>;
|
|
59
|
+
estimateFee(destination: string, amount: number, feeRate?: number, feeRateMultiplier?: number): Promise<{satsPerVbyte: number, networkFee: number}>;
|
|
60
|
+
drainAll(destination: string | Buffer, inputs: Omit<BitcoinUtxo, "address">[], feeRate?: number): Promise<SignPsbtResponse>;
|
|
61
|
+
burnAll(inputs: Omit<BitcoinUtxo, "address">[]): Promise<SignPsbtResponse>;
|
|
62
|
+
|
|
63
|
+
getBlockheight(): Promise<number>;
|
|
64
|
+
getFeeRate(): Promise<number>;
|
|
65
|
+
|
|
66
|
+
}
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import * as BN from "bn.js";
|
|
2
|
+
import {Command} from "@atomiqlabs/server-base";
|
|
3
|
+
|
|
4
|
+
export type IncomingLightningNetworkPayment = {
|
|
5
|
+
createdAt: number,
|
|
6
|
+
confirmedAt: number,
|
|
7
|
+
|
|
8
|
+
createdHeight: number,
|
|
9
|
+
timeout: number,
|
|
10
|
+
|
|
11
|
+
status: "held" | "canceled" | "confirmed"
|
|
12
|
+
|
|
13
|
+
mtokens: BN
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export type LightningNetworkInvoice = {
|
|
17
|
+
id: string,
|
|
18
|
+
request: string,
|
|
19
|
+
secret?: string,
|
|
20
|
+
|
|
21
|
+
cltvDelta: number,
|
|
22
|
+
mtokens: BN,
|
|
23
|
+
|
|
24
|
+
createdAt: number,
|
|
25
|
+
expiresAt: number,
|
|
26
|
+
|
|
27
|
+
description: string,
|
|
28
|
+
descriptionHash?: string,
|
|
29
|
+
|
|
30
|
+
payments: IncomingLightningNetworkPayment[],
|
|
31
|
+
|
|
32
|
+
status: "unpaid" | "held" | "canceled" | "confirmed"
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
export type OutgoingLightningNetworkPayment = {
|
|
36
|
+
failedReason?: "insufficient_balance" | "invalid_payment" | "pathfinding_timeout" | "route_not_found",
|
|
37
|
+
status: "confirmed" | "failed" | "pending",
|
|
38
|
+
secret?: string,
|
|
39
|
+
feeMtokens?: BN
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
export type LightningNetworkChannel = {
|
|
43
|
+
id: string,
|
|
44
|
+
capacity: BN,
|
|
45
|
+
isActive: boolean,
|
|
46
|
+
|
|
47
|
+
localBalance: BN,
|
|
48
|
+
localReserve: BN,
|
|
49
|
+
remoteBalance: BN,
|
|
50
|
+
remoteReserve: BN,
|
|
51
|
+
unsettledBalance: BN,
|
|
52
|
+
transactionId: string,
|
|
53
|
+
transactionVout: number
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
export type InvoiceInit = {
|
|
57
|
+
mtokens: BN,
|
|
58
|
+
descriptionHash?: string
|
|
59
|
+
description?: string,
|
|
60
|
+
cltvDelta?: number,
|
|
61
|
+
expiresAt?: number,
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
export type HodlInvoiceInit = {
|
|
65
|
+
description: string,
|
|
66
|
+
cltvDelta: number,
|
|
67
|
+
expiresAt: number,
|
|
68
|
+
id: string,
|
|
69
|
+
mtokens: BN,
|
|
70
|
+
descriptionHash?: string
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
export type LNRoutes = {
|
|
74
|
+
publicKey: string,
|
|
75
|
+
feeRate?: number,
|
|
76
|
+
cltvDelta?: number,
|
|
77
|
+
channel?: string,
|
|
78
|
+
baseFeeMtokens?: BN
|
|
79
|
+
}[][];
|
|
80
|
+
|
|
81
|
+
export type ParsedPaymentRequest = {
|
|
82
|
+
id: string,
|
|
83
|
+
mtokens: BN,
|
|
84
|
+
expiryEpochMillis: number,
|
|
85
|
+
destination: string,
|
|
86
|
+
cltvDelta: number,
|
|
87
|
+
description: string,
|
|
88
|
+
routes: LNRoutes
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
export type LightningPaymentInit = {
|
|
92
|
+
request: string,
|
|
93
|
+
maxFeeMtokens?: BN,
|
|
94
|
+
maxTimeoutHeight?: number
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
export type LightningBalanceResponse = {
|
|
98
|
+
localBalance: BN,
|
|
99
|
+
remoteBalance: BN,
|
|
100
|
+
unsettledBalance: BN
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
export type ProbeAndRouteInit = {
|
|
104
|
+
request: string,
|
|
105
|
+
amountMtokens: BN,
|
|
106
|
+
maxFeeMtokens: BN,
|
|
107
|
+
maxTimeoutHeight: number
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export type ProbeAndRouteResponse = {
|
|
111
|
+
confidence: number,
|
|
112
|
+
feeMtokens: BN,
|
|
113
|
+
destination: string,
|
|
114
|
+
privateRoutes: LNRoutes
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
export function routesMatch(routesA: LNRoutes, routesB: LNRoutes) {
|
|
118
|
+
if(routesA===routesB) return true;
|
|
119
|
+
if(routesA==null || routesB==null) {
|
|
120
|
+
return false;
|
|
121
|
+
}
|
|
122
|
+
if(routesA.length!==routesB.length) return false;
|
|
123
|
+
for(let i=0;i<routesA.length;i++) {
|
|
124
|
+
if(routesA[i]===routesB[i]) continue;
|
|
125
|
+
if(routesA[i]==null || routesB[i]==null) {
|
|
126
|
+
return false;
|
|
127
|
+
}
|
|
128
|
+
if(routesA[i].length!==routesB[i].length) return false;
|
|
129
|
+
for(let e=0;e<routesA[i].length;e++) {
|
|
130
|
+
if(routesA[i][e]===routesB[i][e]) continue;
|
|
131
|
+
if(routesA[i][e]==null || routesB[i][e]==null) {
|
|
132
|
+
return false;
|
|
133
|
+
}
|
|
134
|
+
if(
|
|
135
|
+
routesA[i][e].publicKey!==routesB[i][e].publicKey ||
|
|
136
|
+
!routesA[i][e].baseFeeMtokens.eq(routesB[i][e].baseFeeMtokens) ||
|
|
137
|
+
routesA[i][e].channel!==routesB[i][e].channel ||
|
|
138
|
+
routesA[i][e].cltvDelta!==routesB[i][e].cltvDelta ||
|
|
139
|
+
routesA[i][e].feeRate!==routesB[i][e].feeRate
|
|
140
|
+
) {
|
|
141
|
+
return false;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
return true;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
export interface ILightningWallet {
|
|
150
|
+
|
|
151
|
+
init(): Promise<void>;
|
|
152
|
+
|
|
153
|
+
isReady(): boolean;
|
|
154
|
+
getStatus(): string;
|
|
155
|
+
getStatusInfo(): Promise<Record<string, string>>;
|
|
156
|
+
getCommands(): Command<any>[];
|
|
157
|
+
|
|
158
|
+
createInvoice(init: InvoiceInit): Promise<LightningNetworkInvoice>;
|
|
159
|
+
createHodlInvoice(init: HodlInvoiceInit): Promise<LightningNetworkInvoice>;
|
|
160
|
+
getInvoice(paymentHash: string): Promise<LightningNetworkInvoice | null>;
|
|
161
|
+
cancelHodlInvoice(paymentHash: string): Promise<void>;
|
|
162
|
+
settleHodlInvoice(secret: string): Promise<void>;
|
|
163
|
+
waitForInvoice(paymentHash: string, abortSignal?: AbortSignal): Promise<LightningNetworkInvoice>;
|
|
164
|
+
|
|
165
|
+
pay(init: LightningPaymentInit): Promise<void>;
|
|
166
|
+
getPayment(paymentHash: string): Promise<OutgoingLightningNetworkPayment | null>
|
|
167
|
+
waitForPayment(paymentHash: string, abortSignal?: AbortSignal): Promise<OutgoingLightningNetworkPayment>;
|
|
168
|
+
probe(init: ProbeAndRouteInit): Promise<ProbeAndRouteResponse | null>;
|
|
169
|
+
route(init: ProbeAndRouteInit): Promise<ProbeAndRouteResponse | null>;
|
|
170
|
+
|
|
171
|
+
parsePaymentRequest(request: string): Promise<ParsedPaymentRequest>;
|
|
172
|
+
|
|
173
|
+
getBlockheight(): Promise<number>;
|
|
174
|
+
getChannels(activeOnly?: boolean): Promise<LightningNetworkChannel[]>;
|
|
175
|
+
getLightningBalance(): Promise<LightningBalanceResponse>;
|
|
176
|
+
|
|
177
|
+
getIdentityPublicKey(): Promise<string>;
|
|
178
|
+
|
|
179
|
+
}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { IBtcFeeEstimator } from "./IBtcFeeEstimator";
|
|
2
|
-
export declare class OneDollarFeeEstimator implements IBtcFeeEstimator {
|
|
3
|
-
estimator: any;
|
|
4
|
-
receivedFee: [number, number, number, number];
|
|
5
|
-
iterations: number;
|
|
6
|
-
host: string;
|
|
7
|
-
port: number;
|
|
8
|
-
username: string;
|
|
9
|
-
password: string;
|
|
10
|
-
addFee: number;
|
|
11
|
-
feeMultiplier: number;
|
|
12
|
-
startFeeEstimator(): void;
|
|
13
|
-
constructor(host: string, port: number, username: string, password: string, addFee?: number, feeMultiplier?: number);
|
|
14
|
-
getFee(): number;
|
|
15
|
-
estimateFee(): Promise<number | null>;
|
|
16
|
-
}
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.OneDollarFeeEstimator = void 0;
|
|
4
|
-
const Utils_1 = require("../utils/Utils");
|
|
5
|
-
const dynamicImport = new Function('specifier', 'return import(specifier)');
|
|
6
|
-
const importPromise = dynamicImport('one-dollar-fee-estimator-failover');
|
|
7
|
-
const logger = (0, Utils_1.getLogger)("OneDollarFeeEstimator: ");
|
|
8
|
-
class OneDollarFeeEstimator {
|
|
9
|
-
startFeeEstimator() {
|
|
10
|
-
logger.info("startFeeEstimator(): starting fee estimator worker");
|
|
11
|
-
importPromise.then(({ FeeEstimator }) => {
|
|
12
|
-
this.estimator = new FeeEstimator({
|
|
13
|
-
mode: 'bundles',
|
|
14
|
-
refresh: 30,
|
|
15
|
-
rpcOptions: {
|
|
16
|
-
host: this.host,
|
|
17
|
-
port: this.port,
|
|
18
|
-
username: this.username,
|
|
19
|
-
password: this.password
|
|
20
|
-
}
|
|
21
|
-
});
|
|
22
|
-
this.estimator.on('error', (err) => {
|
|
23
|
-
logger.error("on(error): fee estimator error", err);
|
|
24
|
-
if (err.message.startsWith("FeeEstimator worker stopped")) {
|
|
25
|
-
logger.info("on(error): restarting fee estimator worker");
|
|
26
|
-
this.receivedFee = null;
|
|
27
|
-
this.iterations = 0;
|
|
28
|
-
this.startFeeEstimator();
|
|
29
|
-
}
|
|
30
|
-
});
|
|
31
|
-
// receive live fee rate updates from the FeeEstimator
|
|
32
|
-
this.estimator.on('fees', (fees) => {
|
|
33
|
-
this.receivedFee = fees;
|
|
34
|
-
this.iterations++;
|
|
35
|
-
});
|
|
36
|
-
});
|
|
37
|
-
}
|
|
38
|
-
constructor(host, port, username, password, addFee, feeMultiplier) {
|
|
39
|
-
this.iterations = 0;
|
|
40
|
-
this.host = host;
|
|
41
|
-
this.port = port;
|
|
42
|
-
this.username = username;
|
|
43
|
-
this.password = password;
|
|
44
|
-
this.addFee = addFee;
|
|
45
|
-
this.feeMultiplier = feeMultiplier;
|
|
46
|
-
this.startFeeEstimator();
|
|
47
|
-
process.on('exit', () => {
|
|
48
|
-
logger.info("process(exit): process exiting, stopping estimator");
|
|
49
|
-
if (this.estimator != null)
|
|
50
|
-
this.estimator.stop();
|
|
51
|
-
});
|
|
52
|
-
process.on('SIGINT', () => {
|
|
53
|
-
logger.info("process(SIGINT): process exiting, stopping estimator");
|
|
54
|
-
if (this.estimator != null)
|
|
55
|
-
this.estimator.stop();
|
|
56
|
-
process.exit();
|
|
57
|
-
});
|
|
58
|
-
}
|
|
59
|
-
getFee() {
|
|
60
|
-
let fee = this.receivedFee[3];
|
|
61
|
-
if (this.feeMultiplier != null)
|
|
62
|
-
fee *= this.feeMultiplier;
|
|
63
|
-
if (this.addFee != null)
|
|
64
|
-
fee += this.addFee;
|
|
65
|
-
return fee;
|
|
66
|
-
}
|
|
67
|
-
estimateFee() {
|
|
68
|
-
return Promise.resolve(this.iterations <= 1 ? null : this.getFee());
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
exports.OneDollarFeeEstimator = OneDollarFeeEstimator;
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
import { CoinselectAddressTypes, CoinselectTxInput, CoinselectTxOutput } from "./utils";
|
|
2
|
-
export declare function accumulative(utxos: CoinselectTxInput[], outputs: CoinselectTxOutput[], feeRate: number, type: CoinselectAddressTypes, requiredInputs?: CoinselectTxInput[]): {
|
|
3
|
-
inputs?: CoinselectTxInput[];
|
|
4
|
-
outputs?: CoinselectTxOutput[];
|
|
5
|
-
fee: number;
|
|
6
|
-
};
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.accumulative = void 0;
|
|
4
|
-
const utils_1 = require("./utils");
|
|
5
|
-
// add inputs until we reach or surpass the target value (or deplete)
|
|
6
|
-
// worst-case: O(n)
|
|
7
|
-
function accumulative(utxos, outputs, feeRate, type, requiredInputs) {
|
|
8
|
-
if (!isFinite(utils_1.utils.uintOrNaN(feeRate)))
|
|
9
|
-
return null;
|
|
10
|
-
let bytesAccum = utils_1.utils.transactionBytes([], outputs, type);
|
|
11
|
-
let inAccum = 0;
|
|
12
|
-
const inputs = [];
|
|
13
|
-
if (requiredInputs != null)
|
|
14
|
-
for (let utxo of requiredInputs) {
|
|
15
|
-
const { length: utxoBytes } = utils_1.utils.inputBytes(utxo);
|
|
16
|
-
const utxoValue = utils_1.utils.uintOrNaN(utxo.value);
|
|
17
|
-
bytesAccum += utxoBytes;
|
|
18
|
-
inAccum += utxoValue;
|
|
19
|
-
inputs.push(utxo);
|
|
20
|
-
}
|
|
21
|
-
const outAccum = utils_1.utils.sumOrNaN(outputs);
|
|
22
|
-
for (let i = 0; i < utxos.length; ++i) {
|
|
23
|
-
const utxo = utxos[i];
|
|
24
|
-
const { length: utxoBytes } = utils_1.utils.inputBytes(utxo);
|
|
25
|
-
const utxoFee = feeRate * utxoBytes;
|
|
26
|
-
const utxoValue = utils_1.utils.uintOrNaN(utxo.value);
|
|
27
|
-
// skip detrimental input
|
|
28
|
-
if (utxoFee > utxo.value) {
|
|
29
|
-
if (i === utxos.length - 1)
|
|
30
|
-
return { fee: feeRate * (bytesAccum + utxoBytes) };
|
|
31
|
-
continue;
|
|
32
|
-
}
|
|
33
|
-
bytesAccum += utxoBytes;
|
|
34
|
-
inAccum += utxoValue;
|
|
35
|
-
inputs.push(utxo);
|
|
36
|
-
const fee = feeRate * bytesAccum;
|
|
37
|
-
// go again?
|
|
38
|
-
if (inAccum < outAccum + fee)
|
|
39
|
-
continue;
|
|
40
|
-
return utils_1.utils.finalize(inputs, outputs, feeRate, type);
|
|
41
|
-
}
|
|
42
|
-
return { fee: feeRate * bytesAccum };
|
|
43
|
-
}
|
|
44
|
-
exports.accumulative = accumulative;
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
import { CoinselectAddressTypes, CoinselectTxInput, CoinselectTxOutput } from "./utils";
|
|
2
|
-
export declare function blackjack(utxos: CoinselectTxInput[], outputs: CoinselectTxOutput[], feeRate: number, type: CoinselectAddressTypes, requiredInputs?: CoinselectTxInput[]): {
|
|
3
|
-
inputs?: CoinselectTxInput[];
|
|
4
|
-
outputs?: CoinselectTxOutput[];
|
|
5
|
-
fee: number;
|
|
6
|
-
};
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.blackjack = void 0;
|
|
4
|
-
const utils_1 = require("./utils");
|
|
5
|
-
// add inputs until we reach or surpass the target value (or deplete)
|
|
6
|
-
// worst-case: O(n)
|
|
7
|
-
function blackjack(utxos, outputs, feeRate, type, requiredInputs) {
|
|
8
|
-
if (!isFinite(utils_1.utils.uintOrNaN(feeRate)))
|
|
9
|
-
return null;
|
|
10
|
-
let bytesAccum = utils_1.utils.transactionBytes([], outputs, type);
|
|
11
|
-
let inAccum = 0;
|
|
12
|
-
const inputs = [];
|
|
13
|
-
if (requiredInputs != null)
|
|
14
|
-
for (let utxo of requiredInputs) {
|
|
15
|
-
const { length: utxoBytes } = utils_1.utils.inputBytes(utxo);
|
|
16
|
-
const utxoValue = utils_1.utils.uintOrNaN(utxo.value);
|
|
17
|
-
bytesAccum += utxoBytes;
|
|
18
|
-
inAccum += utxoValue;
|
|
19
|
-
inputs.push(utxo);
|
|
20
|
-
}
|
|
21
|
-
const outAccum = utils_1.utils.sumOrNaN(outputs);
|
|
22
|
-
const threshold = utils_1.utils.dustThreshold({ type });
|
|
23
|
-
for (let i = 0; i < utxos.length; ++i) {
|
|
24
|
-
const input = utxos[i];
|
|
25
|
-
const { length: inputBytes } = utils_1.utils.inputBytes(input);
|
|
26
|
-
const fee = feeRate * (bytesAccum + inputBytes);
|
|
27
|
-
const inputValue = utils_1.utils.uintOrNaN(input.value);
|
|
28
|
-
// would it waste value?
|
|
29
|
-
if ((inAccum + inputValue) > (outAccum + fee + threshold))
|
|
30
|
-
continue;
|
|
31
|
-
bytesAccum += inputBytes;
|
|
32
|
-
inAccum += inputValue;
|
|
33
|
-
inputs.push(input);
|
|
34
|
-
// go again?
|
|
35
|
-
if (inAccum < outAccum + fee)
|
|
36
|
-
continue;
|
|
37
|
-
return utils_1.utils.finalize(inputs, outputs, feeRate, type);
|
|
38
|
-
}
|
|
39
|
-
return { fee: feeRate * bytesAccum };
|
|
40
|
-
}
|
|
41
|
-
exports.blackjack = blackjack;
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { CoinselectAddressTypes, CoinselectTxInput, CoinselectTxOutput } from "./utils";
|
|
2
|
-
/**
|
|
3
|
-
* Runs a coinselection algorithm on given inputs, outputs and fee rate
|
|
4
|
-
*
|
|
5
|
-
* @param utxos Utxo pool to select additional inputs from
|
|
6
|
-
* @param outputs Outputs of the transaction
|
|
7
|
-
* @param feeRate Feerate in sats/vB
|
|
8
|
-
* @param changeType Change address type
|
|
9
|
-
* @param requiredInputs Utxos that need to be included as inputs to the transaction
|
|
10
|
-
* @param randomize Randomize the UTXO order before running the coinselection algorithm
|
|
11
|
-
*/
|
|
12
|
-
export declare function coinSelect(utxos: CoinselectTxInput[], outputs: CoinselectTxOutput[], feeRate: number, changeType: CoinselectAddressTypes, requiredInputs?: CoinselectTxInput[], randomize?: boolean): {
|
|
13
|
-
inputs?: CoinselectTxInput[];
|
|
14
|
-
outputs?: CoinselectTxOutput[];
|
|
15
|
-
fee: number;
|
|
16
|
-
};
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.coinSelect = void 0;
|
|
4
|
-
const accumulative_1 = require("./accumulative");
|
|
5
|
-
const blackjack_1 = require("./blackjack");
|
|
6
|
-
const utils_1 = require("./utils");
|
|
7
|
-
const BN = require("bn.js");
|
|
8
|
-
const Utils_1 = require("../Utils");
|
|
9
|
-
// order by descending value, minus the inputs approximate fee
|
|
10
|
-
function utxoScore(x, feeRate) {
|
|
11
|
-
return x.value - (feeRate * utils_1.utils.inputBytes(x).length);
|
|
12
|
-
}
|
|
13
|
-
function utxoFeePPM(utxo, feeRate) {
|
|
14
|
-
return new BN(utxo.value).mul(new BN(1000000)).div(new BN(Math.ceil(feeRate * utils_1.utils.inputBytes(utxo).length))).toNumber();
|
|
15
|
-
}
|
|
16
|
-
/**
|
|
17
|
-
* Runs a coinselection algorithm on given inputs, outputs and fee rate
|
|
18
|
-
*
|
|
19
|
-
* @param utxos Utxo pool to select additional inputs from
|
|
20
|
-
* @param outputs Outputs of the transaction
|
|
21
|
-
* @param feeRate Feerate in sats/vB
|
|
22
|
-
* @param changeType Change address type
|
|
23
|
-
* @param requiredInputs Utxos that need to be included as inputs to the transaction
|
|
24
|
-
* @param randomize Randomize the UTXO order before running the coinselection algorithm
|
|
25
|
-
*/
|
|
26
|
-
function coinSelect(utxos, outputs, feeRate, changeType, requiredInputs, randomize) {
|
|
27
|
-
if (randomize) {
|
|
28
|
-
(0, Utils_1.shuffle)(utxos);
|
|
29
|
-
}
|
|
30
|
-
else {
|
|
31
|
-
utxos.sort((a, b) => utxoScore(b, feeRate) - utxoScore(a, feeRate));
|
|
32
|
-
}
|
|
33
|
-
// attempt to use the blackjack strategy first (no change output)
|
|
34
|
-
let base = (0, blackjack_1.blackjack)(utxos, outputs, feeRate, changeType, requiredInputs);
|
|
35
|
-
if (base.inputs)
|
|
36
|
-
return base;
|
|
37
|
-
// else, try the accumulative strategy
|
|
38
|
-
return (0, accumulative_1.accumulative)(utxos, outputs, feeRate, changeType, requiredInputs);
|
|
39
|
-
}
|
|
40
|
-
exports.coinSelect = coinSelect;
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
/// <reference types="node" />
|
|
2
|
-
export type CoinselectAddressTypes = "p2sh-p2wpkh" | "p2wpkh" | "p2wsh" | "p2tr" | "p2pkh";
|
|
3
|
-
export type CoinselectTxInput = {
|
|
4
|
-
script?: Buffer;
|
|
5
|
-
witness?: Buffer;
|
|
6
|
-
txId: string;
|
|
7
|
-
vout: number;
|
|
8
|
-
type?: CoinselectAddressTypes;
|
|
9
|
-
value: number;
|
|
10
|
-
outputScript?: Buffer;
|
|
11
|
-
address?: string;
|
|
12
|
-
};
|
|
13
|
-
export type CoinselectTxOutput = {
|
|
14
|
-
script?: Buffer;
|
|
15
|
-
address?: string;
|
|
16
|
-
type?: CoinselectAddressTypes;
|
|
17
|
-
value: number;
|
|
18
|
-
};
|
|
19
|
-
declare function inputBytes(input: {
|
|
20
|
-
script?: Buffer;
|
|
21
|
-
witness?: Buffer;
|
|
22
|
-
type?: CoinselectAddressTypes;
|
|
23
|
-
}): {
|
|
24
|
-
length: number;
|
|
25
|
-
isWitness: boolean;
|
|
26
|
-
};
|
|
27
|
-
declare function outputBytes(output: {
|
|
28
|
-
script?: Buffer;
|
|
29
|
-
type?: CoinselectAddressTypes;
|
|
30
|
-
}): number;
|
|
31
|
-
declare function dustThreshold(output: {
|
|
32
|
-
script?: Buffer;
|
|
33
|
-
type: CoinselectAddressTypes;
|
|
34
|
-
}): number;
|
|
35
|
-
declare function transactionBytes(inputs: {
|
|
36
|
-
script?: Buffer;
|
|
37
|
-
type?: CoinselectAddressTypes;
|
|
38
|
-
}[], outputs: {
|
|
39
|
-
script?: Buffer;
|
|
40
|
-
type?: CoinselectAddressTypes;
|
|
41
|
-
}[], changeType: CoinselectAddressTypes): number;
|
|
42
|
-
declare function uintOrNaN(v: number): number;
|
|
43
|
-
declare function sumForgiving(range: {
|
|
44
|
-
value: number;
|
|
45
|
-
}[]): number;
|
|
46
|
-
declare function sumOrNaN(range: {
|
|
47
|
-
value: number;
|
|
48
|
-
}[]): number;
|
|
49
|
-
declare function finalize(inputs: CoinselectTxInput[], outputs: CoinselectTxOutput[], feeRate: number, changeType: CoinselectAddressTypes): {
|
|
50
|
-
inputs?: CoinselectTxInput[];
|
|
51
|
-
outputs?: CoinselectTxOutput[];
|
|
52
|
-
fee: number;
|
|
53
|
-
};
|
|
54
|
-
export declare const utils: {
|
|
55
|
-
dustThreshold: typeof dustThreshold;
|
|
56
|
-
finalize: typeof finalize;
|
|
57
|
-
inputBytes: typeof inputBytes;
|
|
58
|
-
outputBytes: typeof outputBytes;
|
|
59
|
-
sumOrNaN: typeof sumOrNaN;
|
|
60
|
-
sumForgiving: typeof sumForgiving;
|
|
61
|
-
transactionBytes: typeof transactionBytes;
|
|
62
|
-
uintOrNaN: typeof uintOrNaN;
|
|
63
|
-
};
|
|
64
|
-
export {};
|