@bitgo-beta/abstract-lightning 1.0.1-beta.152 → 1.0.1-beta.1521
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/src/abstractLightningCoin.d.ts +11 -6
- package/dist/src/abstractLightningCoin.d.ts.map +1 -1
- package/dist/src/abstractLightningCoin.js +79 -8
- package/dist/src/codecs/api/backup.d.ts +15 -0
- package/dist/src/codecs/api/backup.d.ts.map +1 -0
- package/dist/src/codecs/api/backup.js +47 -0
- package/dist/src/codecs/api/balance.d.ts +156 -0
- package/dist/src/codecs/api/balance.d.ts.map +1 -0
- package/dist/src/codecs/api/balance.js +107 -0
- package/dist/src/codecs/api/index.d.ts +8 -0
- package/dist/src/codecs/api/index.d.ts.map +1 -0
- package/dist/src/codecs/api/index.js +24 -0
- package/dist/src/codecs/api/invoice.d.ts +68 -0
- package/dist/src/codecs/api/invoice.d.ts.map +1 -0
- package/dist/src/codecs/api/invoice.js +102 -0
- package/dist/src/codecs/api/payment.d.ts +107 -0
- package/dist/src/codecs/api/payment.d.ts.map +1 -0
- package/dist/src/codecs/api/payment.js +153 -0
- package/dist/src/codecs/api/transaction.d.ts +141 -0
- package/dist/src/codecs/api/transaction.d.ts.map +1 -0
- package/dist/src/codecs/api/transaction.js +123 -0
- package/dist/src/codecs/api/wallet.d.ts +100 -0
- package/dist/src/codecs/api/wallet.d.ts.map +1 -0
- package/dist/src/codecs/api/wallet.js +104 -0
- package/dist/src/codecs/api/withdraw.d.ts +92 -0
- package/dist/src/codecs/api/withdraw.d.ts.map +1 -0
- package/dist/src/codecs/api/withdraw.js +92 -0
- package/dist/src/codecs/index.d.ts +3 -0
- package/dist/src/codecs/index.d.ts.map +1 -0
- package/dist/src/codecs/index.js +19 -0
- package/dist/src/codecs/shared.d.ts +7 -0
- package/dist/src/codecs/shared.d.ts.map +1 -0
- package/dist/src/codecs/shared.js +42 -0
- package/dist/src/index.d.ts +3 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +4 -1
- package/dist/src/lightning/index.d.ts +5 -0
- package/dist/src/lightning/index.d.ts.map +1 -0
- package/dist/src/lightning/index.js +21 -0
- package/dist/src/lightning/lightningUtils.d.ts +90 -0
- package/dist/src/lightning/lightningUtils.d.ts.map +1 -0
- package/dist/src/lightning/lightningUtils.js +290 -0
- package/dist/src/lightning/parseWithdrawPsbt.d.ts +11 -0
- package/dist/src/lightning/parseWithdrawPsbt.d.ts.map +1 -0
- package/dist/src/lightning/parseWithdrawPsbt.js +163 -0
- package/dist/src/lightning/signableJson.d.ts +17 -0
- package/dist/src/lightning/signableJson.d.ts.map +1 -0
- package/dist/src/lightning/signableJson.js +29 -0
- package/dist/src/lightning/signature.d.ts +22 -0
- package/dist/src/lightning/signature.d.ts.map +1 -0
- package/dist/src/lightning/signature.js +69 -0
- package/dist/src/wallet/custodialLightning.d.ts +7 -0
- package/dist/src/wallet/custodialLightning.d.ts.map +1 -0
- package/dist/src/wallet/custodialLightning.js +14 -0
- package/dist/src/wallet/index.d.ts +5 -0
- package/dist/src/wallet/index.d.ts.map +1 -0
- package/dist/src/wallet/index.js +21 -0
- package/dist/src/wallet/lightning.d.ts +141 -0
- package/dist/src/wallet/lightning.d.ts.map +1 -0
- package/dist/src/wallet/lightning.js +288 -0
- package/dist/src/wallet/selfCustodialLightning.d.ts +32 -0
- package/dist/src/wallet/selfCustodialLightning.d.ts.map +1 -0
- package/dist/src/wallet/selfCustodialLightning.js +134 -0
- package/dist/src/wallet/wallet.d.ts +7 -0
- package/dist/src/wallet/wallet.d.ts.map +1 -0
- package/dist/src/wallet/wallet.js +22 -0
- package/dist/test/unit/lightning/codecs.d.ts +2 -0
- package/dist/test/unit/lightning/codecs.d.ts.map +1 -0
- package/dist/test/unit/lightning/codecs.js +151 -0
- package/dist/test/unit/lightning/createPsbt.d.ts +27 -0
- package/dist/test/unit/lightning/createPsbt.d.ts.map +1 -0
- package/dist/test/unit/lightning/createPsbt.js +162 -0
- package/dist/test/unit/lightning/createWatchOnlyFixture.d.ts +4 -0
- package/dist/test/unit/lightning/createWatchOnlyFixture.d.ts.map +1 -0
- package/dist/test/unit/lightning/createWatchOnlyFixture.js +1561 -0
- package/dist/test/unit/lightning/lightningUtils.d.ts +2 -0
- package/dist/test/unit/lightning/lightningUtils.d.ts.map +1 -0
- package/dist/test/unit/lightning/lightningUtils.js +123 -0
- package/dist/test/unit/lightning/parseWithdrawPsbt.d.ts +2 -0
- package/dist/test/unit/lightning/parseWithdrawPsbt.d.ts.map +1 -0
- package/dist/test/unit/lightning/parseWithdrawPsbt.js +478 -0
- package/dist/test/unit/lightning/signableJson.d.ts +2 -0
- package/dist/test/unit/lightning/signableJson.d.ts.map +1 -0
- package/dist/test/unit/lightning/signableJson.js +52 -0
- package/dist/test/unit/lightning/signature.d.ts +2 -0
- package/dist/test/unit/lightning/signature.d.ts.map +1 -0
- package/dist/test/unit/lightning/signature.js +91 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +19 -6
- package/.eslintignore +0 -5
- package/.mocharc.yml +0 -8
- package/CHANGELOG.md +0 -100
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.parsePsbtOutputs = parsePsbtOutputs;
|
|
37
|
+
exports.verifyChangeAddress = verifyChangeAddress;
|
|
38
|
+
exports.validatePsbtForWithdraw = validatePsbtForWithdraw;
|
|
39
|
+
const utxolib = __importStar(require("@bitgo-beta/utxo-lib"));
|
|
40
|
+
const utxo_lib_1 = require("@bitgo-beta/utxo-lib");
|
|
41
|
+
const lightningUtils_1 = require("./lightningUtils");
|
|
42
|
+
function parseDerivationPath(derivationPath) {
|
|
43
|
+
const pathSegments = derivationPath.split('/');
|
|
44
|
+
// Paths may or may not include the 'm/' prefix depending on how they were created:
|
|
45
|
+
// bip174 binary deserialization omits it (e.g. "84'/0'/0'/1/6"),
|
|
46
|
+
// while manually constructed paths typically include it (e.g. "m/84'/0'/0'/1/6").
|
|
47
|
+
const offset = pathSegments[0] === 'm' ? 1 : 0;
|
|
48
|
+
const purpose = Number(pathSegments[offset].replace(/'/g, ''));
|
|
49
|
+
const change = Number(pathSegments[pathSegments.length - 2]);
|
|
50
|
+
const addressIndex = Number(pathSegments[pathSegments.length - 1]);
|
|
51
|
+
if (purpose !== lightningUtils_1.PURPOSE_WRAPPED_P2WKH && purpose !== lightningUtils_1.PURPOSE_P2WKH && purpose !== lightningUtils_1.PURPOSE_P2TR) {
|
|
52
|
+
throw new Error(`Unsupported purpose in derivation path: ${purpose}`);
|
|
53
|
+
}
|
|
54
|
+
return { purpose, change, addressIndex };
|
|
55
|
+
}
|
|
56
|
+
function parsePsbtOutputs(psbt, network) {
|
|
57
|
+
const parsedOutputs = [];
|
|
58
|
+
let bip32Derivation;
|
|
59
|
+
for (let i = 0; i < psbt.data.outputs.length; i++) {
|
|
60
|
+
const output = psbt.data.outputs[i];
|
|
61
|
+
const txOutput = psbt.txOutputs[i];
|
|
62
|
+
let address = '';
|
|
63
|
+
const value = txOutput.value;
|
|
64
|
+
let isChange = false;
|
|
65
|
+
if (output.bip32Derivation && output.bip32Derivation.length > 0) {
|
|
66
|
+
isChange = true;
|
|
67
|
+
bip32Derivation = output.bip32Derivation[0];
|
|
68
|
+
}
|
|
69
|
+
if (txOutput.script) {
|
|
70
|
+
address = utxolib.address.fromOutputScript(txOutput.script, network);
|
|
71
|
+
}
|
|
72
|
+
const valueBigInt = BigInt(value);
|
|
73
|
+
parsedOutputs.push({
|
|
74
|
+
address,
|
|
75
|
+
value: valueBigInt,
|
|
76
|
+
change: isChange,
|
|
77
|
+
bip32Derivation,
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
return parsedOutputs;
|
|
81
|
+
}
|
|
82
|
+
function verifyChangeAddress(output, accounts, network) {
|
|
83
|
+
if (!output.bip32Derivation || !output.bip32Derivation.path) {
|
|
84
|
+
throw new Error(`bip32Derivation path not found for change address`);
|
|
85
|
+
}
|
|
86
|
+
// derivation path example: m/84'/0'/0'/1/0
|
|
87
|
+
const { purpose, change, addressIndex } = parseDerivationPath(output.bip32Derivation.path);
|
|
88
|
+
// Find the corresponding account using the purpose
|
|
89
|
+
const account = accounts.find((acc) => acc.purpose === purpose);
|
|
90
|
+
if (!account) {
|
|
91
|
+
throw new Error(`Account not found for purpose: ${purpose}`);
|
|
92
|
+
}
|
|
93
|
+
// convert upub, vpub, etc prefixes to xpub as utxolib doesn't support these
|
|
94
|
+
const convertedXpub = (0, lightningUtils_1.revertXpubPrefix)(account.xpub, purpose, (0, utxo_lib_1.isMainnet)(network));
|
|
95
|
+
// Create a BIP32 node from the xpub
|
|
96
|
+
const xpubNode = utxolib.bip32.fromBase58(convertedXpub, network);
|
|
97
|
+
// Derive the public key from the xpub using the change and address index
|
|
98
|
+
const derivedPubkey = xpubNode.derive(change).derive(addressIndex).publicKey;
|
|
99
|
+
if (derivedPubkey.toString('hex') !== output.bip32Derivation.pubkey.toString('hex')) {
|
|
100
|
+
throw new Error(`Derived pubkey does not match for address: ${output.address}, derived: ${derivedPubkey.toString('hex')}, expected: ${output.bip32Derivation.pubkey.toString('hex')}`);
|
|
101
|
+
}
|
|
102
|
+
// Determine the correct payment type based on the purpose
|
|
103
|
+
let derivedAddress;
|
|
104
|
+
switch (purpose) {
|
|
105
|
+
case 49: // P2SH-P2WPKH (Nested SegWit)
|
|
106
|
+
derivedAddress = utxolib.payments.p2sh({
|
|
107
|
+
redeem: utxolib.payments.p2wpkh({
|
|
108
|
+
pubkey: derivedPubkey,
|
|
109
|
+
network,
|
|
110
|
+
}),
|
|
111
|
+
network,
|
|
112
|
+
}).address;
|
|
113
|
+
break;
|
|
114
|
+
case 84: // P2WPKH (Native SegWit)
|
|
115
|
+
derivedAddress = utxolib.payments.p2wpkh({
|
|
116
|
+
pubkey: derivedPubkey,
|
|
117
|
+
network,
|
|
118
|
+
}).address;
|
|
119
|
+
break;
|
|
120
|
+
case 86: // P2TR (Taproot)
|
|
121
|
+
// P2TR requires x-only pubkey (32 bytes)
|
|
122
|
+
const xOnlyPubkey = derivedPubkey.length === 33 ? derivedPubkey.subarray(1, 33) : derivedPubkey;
|
|
123
|
+
derivedAddress = utxolib.payments.p2tr({
|
|
124
|
+
pubkey: xOnlyPubkey,
|
|
125
|
+
network,
|
|
126
|
+
}, { eccLib: utxolib.ecc }).address;
|
|
127
|
+
break;
|
|
128
|
+
default:
|
|
129
|
+
throw new Error(`Unsupported purpose: ${purpose}`);
|
|
130
|
+
}
|
|
131
|
+
if (derivedAddress !== output.address) {
|
|
132
|
+
throw new Error(`invalid change address: expected ${derivedAddress}, got ${output.address}`);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Validates the funded psbt before creating the signatures for withdraw.
|
|
137
|
+
*/
|
|
138
|
+
function validatePsbtForWithdraw(psbtHex, network, recipients, accounts) {
|
|
139
|
+
const parsedPsbt = utxo_lib_1.Psbt.fromHex(psbtHex, { network: network });
|
|
140
|
+
const outputs = parsePsbtOutputs(parsedPsbt, network);
|
|
141
|
+
outputs.forEach((output) => {
|
|
142
|
+
if (output.change) {
|
|
143
|
+
try {
|
|
144
|
+
verifyChangeAddress(output, accounts, network);
|
|
145
|
+
}
|
|
146
|
+
catch (e) {
|
|
147
|
+
throw new Error(`Unable to verify change address: ${e}`);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
else {
|
|
151
|
+
let match = false;
|
|
152
|
+
recipients.forEach((recipient) => {
|
|
153
|
+
if (recipient.address === output.address && BigInt(recipient.amountSat) === output.value) {
|
|
154
|
+
match = true;
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
if (!match) {
|
|
158
|
+
throw new Error(`PSBT output ${output.address} with value ${output.value} does not match any recipient`);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGFyc2VXaXRoZHJhd1BzYnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvbGlnaHRuaW5nL3BhcnNlV2l0aGRyYXdQc2J0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBZ0NBLDRDQThCQztBQUVELGtEQXFFQztBQUtELDBEQTJCQztBQXJLRCw4REFBZ0Q7QUFDaEQsbURBQXVEO0FBSXZELHFEQU0wQjtBQUUxQixTQUFTLG1CQUFtQixDQUFDLGNBQXNCO0lBS2pELE1BQU0sWUFBWSxHQUFHLGNBQWMsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDL0MsbUZBQW1GO0lBQ25GLGlFQUFpRTtJQUNqRSxrRkFBa0Y7SUFDbEYsTUFBTSxNQUFNLEdBQUcsWUFBWSxDQUFDLENBQUMsQ0FBQyxLQUFLLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDL0MsTUFBTSxPQUFPLEdBQUcsTUFBTSxDQUFDLFlBQVksQ0FBQyxNQUFNLENBQUMsQ0FBQyxPQUFPLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDL0QsTUFBTSxNQUFNLEdBQUcsTUFBTSxDQUFDLFlBQVksQ0FBQyxZQUFZLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDN0QsTUFBTSxZQUFZLEdBQUcsTUFBTSxDQUFDLFlBQVksQ0FBQyxZQUFZLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDbkUsSUFBSSxPQUFPLEtBQUssc0NBQXFCLElBQUksT0FBTyxLQUFLLDhCQUFhLElBQUksT0FBTyxLQUFLLDZCQUFZLEVBQUUsQ0FBQztRQUMvRixNQUFNLElBQUksS0FBSyxDQUFDLDJDQUEyQyxPQUFPLEVBQUUsQ0FBQyxDQUFDO0lBQ3hFLENBQUM7SUFDRCxPQUFPLEVBQUUsT0FBTyxFQUFFLE1B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LENBQUMsU0FBUyxDQUFDLEtBQUssTUFBTSxDQUFDLEtBQUssRUFBRSxDQUFDO29CQUN6RixLQUFLLEdBQUcsSUFBSSxDQUFDO2dCQUNmLENBQUM7WUFDSCxDQUFDLENBQUMsQ0FBQztZQUNILElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQztnQkFDWCxNQUFNLElBQUksS0FBSyxDQUFDLGVBQWUsTUFBTSxDQUFDLE9BQU8sZUFBZSxNQUFNLENBQUMsS0FBSywrQkFBK0IsQ0FBQyxDQUFDO1lBQzNHLENBQUM7UUFDSCxDQUFDO0lBQ0gsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0ICogYXMgdXR4b2xpYiBmcm9tICdAYml0Z28tYmV0YS91dHhvLWxpYic7XG5pbXBvcnQgeyBpc01haW5uZXQsIFBzYnQgfSBmcm9tICdAYml0Z28tYmV0YS91dHhvLWxpYic7XG5pbXBvcnQgeyBXYXRjaE9ubHlBY2NvdW50LCBXaXRoZHJhd0Jhc2VPdXRwdXRVVFhPIH0gZnJvbSAnLi4vY29kZWNzJztcbmltcG9ydCB7IExpZ2h0bmluZ09uY2hhaW5SZWNpcGllbnQgfSBmcm9tICdAYml0Z28vcHVibGljLXR5cGVzJztcbmltcG9ydCB7IEJpcDMyRGVyaXZhdGlvbiB9IGZyb20gJ2JpcDE3NC9zcmMvbGliL2ludGVyZmFjZXMnO1xuaW1wb3J0IHtcbiAgRXh0ZW5kZWRLZXlBZGRyZXNzUHVycG9zZSxcbiAgUFVSUE9TRV9QMlRSLFxuICBQVVJQT1NFX1AyV0tILFxuICBQVVJQT1NFX1dSQVBQRURfUDJXS0gsXG4gIHJldmVydFhwdWJQcmVmaXgsXG59IGZyb20gJy4vbGlnaHRuaW5nVXRpbHMnO1xuXG5mdW5jdGlvbiBwYXJzZURlcml2YXRpb25QYXRoKGRlcml2YXRpb25QYXRoOiBzdHJpbmcpOiB7XG4gIHB1cnBvc2U6IEV4dGVuZGVkS2V5QWRkcmVzc1B1cnBvc2U7XG4gIGNoYW5nZTogbnVtYmVyO1xuICBhZGRyZXNzSW5kZXg6IG51bWJlcjtcbn0ge1xuICBjb25zdCBwYXRoU2VnbWVudHMgPSBkZXJpdmF0aW9uUGF0aC5zcGxpdCgnLycpO1xuICAvLyBQYXRocyBtYXkgb3IgbWF5IG5vdCBpbmNsdWRlIHRoZSAnbS8nIHByZWZpeCBkZXBlbmRpbmcgb24gaG93IHRoZXkgd2VyZSBjcmVhdGVkOlxuICAvLyBiaXAxNzQgYmluYXJ5IGRlc2VyaWFsaXphdGlvbiBvbWl0cyBpdCAoZS5nLiBcIjg0Jy8wJy8wJy8xLzZcIiksXG4gIC8vIHdoaWxlIG1hbnVhbGx5IGNvbnN0cnVjdGVkIHBhdGhzIHR5cGljYWxseSBpbmNsdWRlIGl0IChlLmcuIFwibS84NCcvMCcvMCcvMS82XCIpLlxuICBjb25zdCBvZmZzZXQgPSBwYXRoU2VnbWVudHNbMF0gPT09ICdtJyA/IDEgOiAwO1xuICBjb25zdCBwdXJwb3NlID0gTnVtYmVyKHBhdGhTZWdtZW50c1tvZmZzZXRdLnJlcGxhY2UoLycvZywgJycpKTtcbiAgY29uc3QgY2hhbmdlID0gTnVtYmVyKHBhdGhTZWdtZW50c1twYXRoU2VnbWVudHMubGVuZ3RoIC0gMl0pO1xuICBjb25zdCBhZGRyZXNzSW5kZXggPSBOdW1iZXIocGF0aFNlZ21lbnRzW3BhdGhTZWdtZW50cy5sZW5ndGggLSAxXSk7XG4gIGlmIChwdXJwb3NlICE9PSBQVVJQT1NFX1dSQVBQRURfUDJXS0ggJiYgcHVycG9zZSAhPT0gUFVSUE9TRV9QMldLSCAmJiBwdXJwb3NlICE9PSBQVVJQT1NFX1AyVFIpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYFVuc3VwcG9ydGVkIHB1cnBvc2UgaW4gZGVyaXZhdGlvbiBwYXRoOiAke3B1cnBvc2V9YCk7XG4gIH1cbiAgcmV0dXJuIHsgcHVycG9zZSwgY2hhbmdlLCBhZGRyZXNzSW5kZXggfTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHBhcnNlUHNidE91dHB1dHMocHNidDogUHNidCwgbmV0d29yazogdXR4b2xpYi5OZXR3b3JrKTogV2l0aGRyYXdCYXNlT3V0cHV0VVRYTzxiaWdpbnQ+W10ge1xuICBjb25zdCBwYXJzZWRPdXRwdXRzOiBXaXRoZHJhd0Jhc2VPdXRwdXRVVFhPPGJpZ2ludD5bXSA9IFtdO1xuICBsZXQgYmlwMzJEZXJpdmF0aW9uOiBCaXAzMkRlcml2YXRpb24gfCB1bmRlZmluZWQ7XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBwc2J0LmRhdGEub3V0cHV0cy5sZW5ndGg7IGkrKykge1xuICAgIGNvbnN0IG91dHB1dCA9IHBzYnQuZGF0YS5vdXRwdXRzW2ldO1xuICAgIGNvbnN0IHR4T3V0cHV0ID0gcHNidC50eE91dHB1dHNbaV07XG5cbiAgICBsZXQgYWRkcmVzcyA9ICcnO1xuICAgIGNvbnN0IHZhbHVlID0gdHhPdXRwdXQudmFsdWU7XG4gICAgbGV0IGlzQ2hhbmdlID0gZmFsc2U7XG5cbiAgICBpZiAob3V0cHV0LmJpcDMyRGVyaXZhdGlvbiAmJiBvdXRwdXQuYmlwMzJEZXJpdmF0aW9uLmxlbmd0aCA+IDApIHtcbiAgICAgIGlzQ2hhbmdlID0gdHJ1ZTtcbiAgICAgIGJpcDMyRGVyaXZhdGlvbiA9IG91dHB1dC5iaXAzMkRlcml2YXRpb25bMF07XG4gICAgfVxuICAgIGlmICh0eE91dHB1dC5zY3JpcHQpIHtcbiAgICAgIGFkZHJlc3MgPSB1dHhvbGliLmFkZHJlc3MuZnJvbU91dHB1dFNjcmlwdCh0eE91dHB1dC5zY3JpcHQsIG5ldHdvcmspO1xuICAgIH1cbiAgICBjb25zdCB2YWx1ZUJpZ0ludCA9IEJpZ0ludCh2YWx1ZSk7XG5cbiAgICBwYXJzZWRPdXRwdXRzLnB1c2goe1xuICAgICAgYWRkcmVzcyxcbiAgICAgIHZhbHVlOiB2YWx1ZUJpZ0ludCxcbiAgICAgIGNoYW5nZTogaXNDaGFuZ2UsXG4gICAgICBiaXAzMkRlcml2YXRpb24sXG4gICAgfSk7XG4gIH1cblxuICByZXR1cm4gcGFyc2VkT3V0cHV0cztcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHZlcmlmeUNoYW5nZUFkZHJlc3MoXG4gIG91dHB1dDogV2l0aGRyYXdCYXNlT3V0cHV0VVRYTzxiaWdpbnQ+LFxuICBhY2NvdW50czogV2F0Y2hPbmx5QWNjb3VudFtdLFxuICBuZXR3b3JrOiB1dHhvbGliLk5ldHdvcmtcbik6IHZvaWQge1xuICBpZiAoIW91dHB1dC5iaXAzMkRlcml2YXRpb24gfHwgIW91dHB1dC5iaXAzMkRlcml2YXRpb24ucGF0aCkge1xuICAgIHRocm93IG5ldyBFcnJvcihgYmlwMzJEZXJpdmF0aW9uIHBhdGggbm90IGZvdW5kIGZvciBjaGFuZ2UgYWRkcmVzc2ApO1xuICB9XG4gIC8vIGRlcml2YXRpb24gcGF0aCBleGFtcGxlOiBtLzg0Jy8wJy8wJy8xLzBcbiAgY29uc3QgeyBwdXJwb3NlLCBjaGFuZ2UsIGFkZHJlc3NJbmRleCB9ID0gcGFyc2VEZXJpdmF0aW9uUGF0aChvdXRwdXQuYmlwMzJEZXJpdmF0aW9uLnBhdGgpO1xuXG4gIC8vIEZpbmQgdGhlIGNvcnJlc3BvbmRpbmcgYWNjb3VudCB1c2luZyB0aGUgcHVycG9zZVxuICBjb25zdCBhY2NvdW50ID0gYWNjb3VudHMuZmluZCgoYWNjKSA9PiBhY2MucHVycG9zZSA9PT0gcHVycG9zZSk7XG4gIGlmICghYWNjb3VudCkge1xuICAgIHRocm93IG5ldyBFcnJvcihgQWNjb3VudCBub3QgZm91bmQgZm9yIHB1cnBvc2U6ICR7cHVycG9zZX1gKTtcbiAgfVxuXG4gIC8vIGNvbnZlcnQgdXB1YiwgdnB1YiwgZXRjIHByZWZpeGVzIHRvIHhwdWIgYXMgdXR4b2xpYiBkb2Vzbid0IHN1cHBvcnQgdGhlc2VcbiAgY29uc3QgY29udmVydGVkWHB1YiA9IHJldmVydFhwdWJQcmVmaXgoYWNjb3VudC54cHViLCBwdXJwb3NlLCBpc01haW5uZXQobmV0d29yaykpO1xuICAvLyBDcmVhdGUgYSBCSVAzMiBub2RlIGZyb20gdGhlIHhwdWJcbiAgY29uc3QgeHB1Yk5vZGUgPSB1dHhvbGliLmJpcDMyLmZyb21CYXNlNTgoY29udmVydGVkWHB1YiwgbmV0d29yayk7XG5cbiAgLy8gRGVyaXZlIHRoZSBwdWJsaWMga2V5IGZyb20gdGhlIHhwdWIgdXNpbmcgdGhlIGNoYW5nZSBhbmQgYWRkcmVzcyBpbmRleFxuICBjb25zdCBkZXJpdmVkUHVia2V5ID0geHB1Yk5vZGUuZGVyaXZlKGNoYW5nZSkuZGVyaXZlKGFkZHJlc3NJbmRleCkucHVibGljS2V5O1xuXG4gIGlmIChkZXJpdmVkUHVia2V5LnRvU3RyaW5nKCdoZXgnKSAhPT0gb3V0cHV0LmJpcDMyRGVyaXZhdGlvbi5wdWJrZXkudG9TdHJpbmcoJ2hleCcpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgYERlcml2ZWQgcHVia2V5IGRvZXMgbm90IG1hdGNoIGZvciBhZGRyZXNzOiAke291dHB1dC5hZGRyZXNzfSwgZGVyaXZlZDogJHtkZXJpdmVkUHVia2V5LnRvU3RyaW5nKFxuICAgICAgICAnaGV4J1xuICAgICAgKX0sIGV4cGVjdGVkOiAke291dHB1dC5iaXAzMkRlcml2YXRpb24ucHVia2V5LnRvU3RyaW5nKCdoZXgnKX1gXG4gICAgKTtcbiAgfVxuXG4gIC8vIERldGVybWluZSB0aGUgY29ycmVjdCBwYXltZW50IHR5cGUgYmFzZWQgb24gdGhlIHB1cnBvc2VcbiAgbGV0IGRlcml2ZWRBZGRyZXNzOiBzdHJpbmcgfCB1bmRlZmluZWQ7XG4gIHN3aXRjaCAocHVycG9zZSkge1xuICAgIGNhc2UgNDk6IC8vIFAyU0gtUDJXUEtIIChOZXN0ZWQgU2VnV2l0KVxuICAgICAgZGVyaXZlZEFkZHJlc3MgPSB1dHhvbGliLnBheW1lbnRzLnAyc2goe1xuICAgICAgICByZWRlZW06IHV0eG9saWIucGF5bWVudHMucDJ3cGtoKHtcbiAgICAgICAgICBwdWJrZXk6IGRlcml2ZWRQdWJrZXksXG4gICAgICAgICAgbmV0d29yayxcbiAgICAgICAgfSksXG4gICAgICAgIG5ldHdvcmssXG4gICAgICB9KS5hZGRyZXNzO1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSA4NDogLy8gUDJXUEtIIChOYXRpdmUgU2VnV2l0KVxuICAgICAgZGVyaXZlZEFkZHJlc3MgPSB1dHhvbGliLnBheW1lbnRzLnAyd3BraCh7XG4gICAgICAgIHB1YmtleTogZGVyaXZlZFB1YmtleSxcbiAgICAgICAgbmV0d29yayxcbiAgICAgIH0pLmFkZHJlc3M7XG4gICAgICBicmVhaztcbiAgICBjYXNlIDg2OiAvLyBQMlRSIChUYXByb290KVxuICAgICAgLy8gUDJUUiByZXF1aXJlcyB4LW9ubHkgcHVia2V5ICgzMiBieXRlcylcbiAgICAgIGNvbnN0IHhPbmx5UHVia2V5ID0gZGVyaXZlZFB1YmtleS5sZW5ndGggPT09IDMzID8gZGVyaXZlZFB1YmtleS5zdWJhcnJheSgxLCAzMykgOiBkZXJpdmVkUHVia2V5O1xuICAgICAgZGVyaXZlZEFkZHJlc3MgPSB1dHhvbGliLnBheW1lbnRzLnAydHIoXG4gICAgICAgIHtcbiAgICAgICAgICBwdWJrZXk6IHhPbmx5UHVia2V5LFxuICAgICAgICAgIG5ldHdvcmssXG4gICAgICAgIH0sXG4gICAgICAgIHsgZWNjTGliOiB1dHhvbGliLmVjYyB9XG4gICAgICApLmFkZHJlc3M7XG4gICAgICBicmVhaztcbiAgICBkZWZhdWx0OlxuICAgICAgdGhyb3cgbmV3IEVycm9yKGBVbnN1cHBvcnRlZCBwdXJwb3NlOiAke3B1cnBvc2V9YCk7XG4gIH1cblxuICBpZiAoZGVyaXZlZEFkZHJlc3MgIT09IG91dHB1dC5hZGRyZXNzKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBpbnZhbGlkIGNoYW5nZSBhZGRyZXNzOiBleHBlY3RlZCAke2Rlcml2ZWRBZGRyZXNzfSwgZ290ICR7b3V0cHV0LmFkZHJlc3N9YCk7XG4gIH1cbn1cblxuLyoqXG4gKiBWYWxpZGF0ZXMgdGhlIGZ1bmRlZCBwc2J0IGJlZm9yZSBjcmVhdGluZyB0aGUgc2lnbmF0dXJlcyBmb3Igd2l0aGRyYXcuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB2YWxpZGF0ZVBzYnRGb3JXaXRoZHJhdyhcbiAgcHNidEhleDogc3RyaW5nLFxuICBuZXR3b3JrOiB1dHhvbGliLk5ldHdvcmssXG4gIHJlY2lwaWVudHM6IExpZ2h0bmluZ09uY2hhaW5SZWNpcGllbnRbXSxcbiAgYWNjb3VudHM6IFdhdGNoT25seUFjY291bnRbXVxuKTogdm9pZCB7XG4gIGNvbnN0IHBhcnNlZFBzYnQgPSBQc2J0LmZyb21IZXgocHNidEhleCwgeyBuZXR3b3JrOiBuZXR3b3JrIH0pO1xuICBjb25zdCBvdXRwdXRzID0gcGFyc2VQc2J0T3V0cHV0cyhwYXJzZWRQc2J0LCBuZXR3b3JrKTtcbiAgb3V0cHV0cy5mb3JFYWNoKChvdXRwdXQpID0+IHtcbiAgICBpZiAob3V0cHV0LmNoYW5nZSkge1xuICAgICAgdHJ5IHtcbiAgICAgICAgdmVyaWZ5Q2hhbmdlQWRkcmVzcyhvdXRwdXQsIGFjY291bnRzLCBuZXR3b3JrKTtcbiAgICAgIH0gY2F0Y2ggKGU6IGFueSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFVuYWJsZSB0byB2ZXJpZnkgY2hhbmdlIGFkZHJlc3M6ICR7ZX1gKTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgbGV0IG1hdGNoID0gZmFsc2U7XG4gICAgICByZWNpcGllbnRzLmZvckVhY2goKHJlY2lwaWVudCkgPT4ge1xuICAgICAgICBpZiAocmVjaXBpZW50LmFkZHJlc3MgPT09IG91dHB1dC5hZGRyZXNzICYmIEJpZ0ludChyZWNpcGllbnQuYW1vdW50U2F0KSA9PT0gb3V0cHV0LnZhbHVlKSB7XG4gICAgICAgICAgbWF0Y2ggPSB0cnVlO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIGlmICghbWF0Y2gpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBQU0JUIG91dHB1dCAke291dHB1dC5hZGRyZXNzfSB3aXRoIHZhbHVlICR7b3V0cHV0LnZhbHVlfSBkb2VzIG5vdCBtYXRjaCBhbnkgcmVjaXBpZW50YCk7XG4gICAgICB9XG4gICAgfVxuICB9KTtcbn1cbiJdfQ==
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export type Signable = boolean | number | string | SignableRecord | SignableArray;
|
|
2
|
+
export interface SignableRecord {
|
|
3
|
+
[key: string]: Signable;
|
|
4
|
+
}
|
|
5
|
+
export interface SignableArray {
|
|
6
|
+
[key: number]: Signable;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Recursively canonicalizes an object by sorting its keys.
|
|
10
|
+
*
|
|
11
|
+
* @param obj - The object to be canonicalized. It can be a boolean, number, string,
|
|
12
|
+
* a record of signable values, or an array of signable values.
|
|
13
|
+
* @returns The canonicalized object with sorted keys.
|
|
14
|
+
* @throws Will throw an error if the object type is invalid.
|
|
15
|
+
*/
|
|
16
|
+
export declare function canonicalizeObject(obj: Signable): Signable;
|
|
17
|
+
//# sourceMappingURL=signableJson.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"signableJson.d.ts","sourceRoot":"","sources":["../../../src/lightning/signableJson.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,cAAc,GAAG,aAAa,CAAC;AAElF,MAAM,WAAW,cAAc;IAC7B,CAAC,GAAG,EAAE,MAAM,GAAG,QAAQ,CAAC;CACzB;AAED,MAAM,WAAW,aAAa;IAC5B,CAAC,GAAG,EAAE,MAAM,GAAG,QAAQ,CAAC;CACzB;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,QAAQ,GAAG,QAAQ,CAmB1D"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.canonicalizeObject = canonicalizeObject;
|
|
4
|
+
/**
|
|
5
|
+
* Recursively canonicalizes an object by sorting its keys.
|
|
6
|
+
*
|
|
7
|
+
* @param obj - The object to be canonicalized. It can be a boolean, number, string,
|
|
8
|
+
* a record of signable values, or an array of signable values.
|
|
9
|
+
* @returns The canonicalized object with sorted keys.
|
|
10
|
+
* @throws Will throw an error if the object type is invalid.
|
|
11
|
+
*/
|
|
12
|
+
function canonicalizeObject(obj) {
|
|
13
|
+
if (typeof obj === 'boolean' || typeof obj === 'number' || typeof obj === 'string') {
|
|
14
|
+
return obj;
|
|
15
|
+
}
|
|
16
|
+
if (Array.isArray(obj)) {
|
|
17
|
+
return obj.map(canonicalizeObject);
|
|
18
|
+
}
|
|
19
|
+
if (obj !== null && typeof obj === 'object') {
|
|
20
|
+
return Object.keys(obj)
|
|
21
|
+
.sort()
|
|
22
|
+
.reduce((result, key) => {
|
|
23
|
+
result[key] = canonicalizeObject(obj[key]);
|
|
24
|
+
return result;
|
|
25
|
+
}, {});
|
|
26
|
+
}
|
|
27
|
+
throw new Error('Invalid object type');
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2lnbmFibGVKc29uLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2xpZ2h0bmluZy9zaWduYWJsZUpzb24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFrQkEsZ0RBbUJDO0FBM0JEOzs7Ozs7O0dBT0c7QUFDSCxTQUFnQixrQkFBa0IsQ0FBQyxHQUFhO0lBQzlDLElBQUksT0FBTyxHQUFHLEtBQUssU0FBUyxJQUFJLE9BQU8sR0FBRyxLQUFLLFFBQVEsSUFBSSxPQUFPLEdBQUcsS0FBSyxRQUFRLEVBQUUsQ0FBQztRQUNuRixPQUFPLEdBQUcsQ0FBQztJQUNiLENBQUM7SUFFRCxJQUFJLEtBQUssQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQztRQUN2QixPQUFPLEdBQUcsQ0FBQyxHQUFHLENBQUMsa0JBQWtCLENBQUMsQ0FBQztJQUNyQyxDQUFDO0lBRUQsSUFBSSxHQUFHLEtBQUssSUFBSSxJQUFJLE9BQU8sR0FBRyxLQUFLLFFBQVEsRUFBRSxDQUFDO1FBQzVDLE9BQU8sTUFBTSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUM7YUFDcEIsSUFBSSxFQUFFO2FBQ04sTUFBTSxDQUFDLENBQUMsTUFBZ0MsRUFBRSxHQUFHLEVBQUUsRUFBRTtZQUNoRCxNQUFNLENBQUMsR0FBRyxDQUFDLEdBQUcsa0JBQWtCLENBQUUsR0FBbUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO1lBQzVFLE9BQU8sTUFBTSxDQUFDO1FBQ2hCLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQztJQUNYLENBQUM7SUFFRCxNQUFNLElBQUksS0FBSyxDQUFDLHFCQUFxQixDQUFDLENBQUM7QUFDekMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImV4cG9ydCB0eXBlIFNpZ25hYmxlID0gYm9vbGVhbiB8IG51bWJlciB8IHN0cmluZyB8IFNpZ25hYmxlUmVjb3JkIHwgU2lnbmFibGVBcnJheTtcblxuZXhwb3J0IGludGVyZmFjZSBTaWduYWJsZVJlY29yZCB7XG4gIFtrZXk6IHN0cmluZ106IFNpZ25hYmxlO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFNpZ25hYmxlQXJyYXkge1xuICBba2V5OiBudW1iZXJdOiBTaWduYWJsZTtcbn1cblxuLyoqXG4gKiBSZWN1cnNpdmVseSBjYW5vbmljYWxpemVzIGFuIG9iamVjdCBieSBzb3J0aW5nIGl0cyBrZXlzLlxuICpcbiAqIEBwYXJhbSBvYmogLSBUaGUgb2JqZWN0IHRvIGJlIGNhbm9uaWNhbGl6ZWQuIEl0IGNhbiBiZSBhIGJvb2xlYW4sIG51bWJlciwgc3RyaW5nLFxuICogICAgICAgICAgICAgIGEgcmVjb3JkIG9mIHNpZ25hYmxlIHZhbHVlcywgb3IgYW4gYXJyYXkgb2Ygc2lnbmFibGUgdmFsdWVzLlxuICogQHJldHVybnMgVGhlIGNhbm9uaWNhbGl6ZWQgb2JqZWN0IHdpdGggc29ydGVkIGtleXMuXG4gKiBAdGhyb3dzIFdpbGwgdGhyb3cgYW4gZXJyb3IgaWYgdGhlIG9iamVjdCB0eXBlIGlzIGludmFsaWQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjYW5vbmljYWxpemVPYmplY3Qob2JqOiBTaWduYWJsZSk6IFNpZ25hYmxlIHtcbiAgaWYgKHR5cGVvZiBvYmogPT09ICdib29sZWFuJyB8fCB0eXBlb2Ygb2JqID09PSAnbnVtYmVyJyB8fCB0eXBlb2Ygb2JqID09PSAnc3RyaW5nJykge1xuICAgIHJldHVybiBvYmo7XG4gIH1cblxuICBpZiAoQXJyYXkuaXNBcnJheShvYmopKSB7XG4gICAgcmV0dXJuIG9iai5tYXAoY2Fub25pY2FsaXplT2JqZWN0KTtcbiAgfVxuXG4gIGlmIChvYmogIT09IG51bGwgJiYgdHlwZW9mIG9iaiA9PT0gJ29iamVjdCcpIHtcbiAgICByZXR1cm4gT2JqZWN0LmtleXMob2JqKVxuICAgICAgLnNvcnQoKVxuICAgICAgLnJlZHVjZSgocmVzdWx0OiBSZWNvcmQ8c3RyaW5nLCBTaWduYWJsZT4sIGtleSkgPT4ge1xuICAgICAgICByZXN1bHRba2V5XSA9IGNhbm9uaWNhbGl6ZU9iamVjdCgob2JqIGFzIHsgW2tleTogc3RyaW5nXTogU2lnbmFibGUgfSlba2V5XSk7XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICB9LCB7fSk7XG4gIH1cblxuICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgb2JqZWN0IHR5cGUnKTtcbn1cbiJdfQ==
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import * as utxolib from '@bitgo-beta/utxo-lib';
|
|
2
|
+
import { Signable } from './signableJson';
|
|
3
|
+
/**
|
|
4
|
+
* Verifies a signature for a given message.
|
|
5
|
+
*
|
|
6
|
+
* @param {Signable} message - The message to verify.
|
|
7
|
+
* @param {string} signature - The signature to verify, in hexadecimal format.
|
|
8
|
+
* @param {string} pub - The public key in BIP32 format.
|
|
9
|
+
* @param {utxolib.Network} network - The network to use for verification.
|
|
10
|
+
* @returns {boolean} - Returns true if the signature is valid, false otherwise.
|
|
11
|
+
*/
|
|
12
|
+
export declare function verifyMessageSignature(message: Signable, signature: string, pub: string, network?: utxolib.Network): boolean;
|
|
13
|
+
/**
|
|
14
|
+
* Creates a signature for a given message.
|
|
15
|
+
*
|
|
16
|
+
* @param {Signable} message - The message to sign.
|
|
17
|
+
* @param {string} prv - The private key in BIP32 format.
|
|
18
|
+
* @param {utxolib.Network} network - The network to use for signing.
|
|
19
|
+
* @returns {string} - Returns the signature in hexadecimal format.
|
|
20
|
+
*/
|
|
21
|
+
export declare function createMessageSignature(message: Signable, xprv: string, network?: utxolib.Network): string;
|
|
22
|
+
//# sourceMappingURL=signature.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"signature.d.ts","sourceRoot":"","sources":["../../../src/lightning/signature.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,OAAO,MAAM,sBAAsB,CAAC;AAEhD,OAAO,EAAsB,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAE9D;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,QAAQ,EACjB,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,OAAO,CAAC,OAAkC,GAClD,OAAO,CAKT;AAED;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,QAAQ,EACjB,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE,OAAO,CAAC,OAAkC,GAClD,MAAM,CAIR"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.verifyMessageSignature = verifyMessageSignature;
|
|
37
|
+
exports.createMessageSignature = createMessageSignature;
|
|
38
|
+
const utxolib = __importStar(require("@bitgo-beta/utxo-lib"));
|
|
39
|
+
const sdkcore = __importStar(require("@bitgo-beta/sdk-core"));
|
|
40
|
+
const signableJson_1 = require("./signableJson");
|
|
41
|
+
/**
|
|
42
|
+
* Verifies a signature for a given message.
|
|
43
|
+
*
|
|
44
|
+
* @param {Signable} message - The message to verify.
|
|
45
|
+
* @param {string} signature - The signature to verify, in hexadecimal format.
|
|
46
|
+
* @param {string} pub - The public key in BIP32 format.
|
|
47
|
+
* @param {utxolib.Network} network - The network to use for verification.
|
|
48
|
+
* @returns {boolean} - Returns true if the signature is valid, false otherwise.
|
|
49
|
+
*/
|
|
50
|
+
function verifyMessageSignature(message, signature, pub, network = utxolib.networks.bitcoin) {
|
|
51
|
+
const messageString = JSON.stringify((0, signableJson_1.canonicalizeObject)(message));
|
|
52
|
+
const pubKey = utxolib.bip32.fromBase58(pub, network).publicKey;
|
|
53
|
+
const signatureBuffer = Buffer.from(signature, 'hex');
|
|
54
|
+
return sdkcore.verifyMessage(messageString, pubKey, signatureBuffer, network);
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Creates a signature for a given message.
|
|
58
|
+
*
|
|
59
|
+
* @param {Signable} message - The message to sign.
|
|
60
|
+
* @param {string} prv - The private key in BIP32 format.
|
|
61
|
+
* @param {utxolib.Network} network - The network to use for signing.
|
|
62
|
+
* @returns {string} - Returns the signature in hexadecimal format.
|
|
63
|
+
*/
|
|
64
|
+
function createMessageSignature(message, xprv, network = utxolib.networks.bitcoin) {
|
|
65
|
+
const requestString = JSON.stringify((0, signableJson_1.canonicalizeObject)(message));
|
|
66
|
+
const prvKey = utxolib.bip32.fromBase58(xprv, network);
|
|
67
|
+
return sdkcore.signMessage(requestString, prvKey, network).toString('hex');
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2lnbmF0dXJlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2xpZ2h0bmluZy9zaWduYXR1cmUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFhQSx3REFVQztBQVVELHdEQVFDO0FBekNELDhEQUFnRDtBQUNoRCw4REFBZ0Q7QUFDaEQsaURBQThEO0FBRTlEOzs7Ozs7OztHQVFHO0FBQ0gsU0FBZ0Isc0JBQXNCLENBQ3BDLE9BQWlCLEVBQ2pCLFNBQWlCLEVBQ2pCLEdBQVcsRUFDWCxVQUEyQixPQUFPLENBQUMsUUFBUSxDQUFDLE9BQU87SUFFbkQsTUFBTSxhQUFhLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFBLGlDQUFrQixFQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUM7SUFDbEUsTUFBTSxNQUFNLEdBQUcsT0FBTyxDQUFDLEtBQUssQ0FBQyxVQUFVLENBQUMsR0FBRyxFQUFFLE9BQU8sQ0FBQyxDQUFDLFNBQVMsQ0FBQztJQUNoRSxNQUFNLGVBQWUsR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBRSxLQUFLLENBQUMsQ0FBQztJQUN0RCxPQUFPLE9BQU8sQ0FBQyxhQUFhLENBQUMsYUFBYSxFQUFFLE1BQU0sRUFBRSxlQUFlLEVBQUUsT0FBTyxDQUFDLENBQUM7QUFDaEYsQ0FBQztBQUVEOzs7Ozs7O0dBT0c7QUFDSCxTQUFnQixzQkFBc0IsQ0FDcEMsT0FBaUIsRUFDakIsSUFBWSxFQUNaLFVBQTJCLE9BQU8sQ0FBQyxRQUFRLENBQUMsT0FBTztJQUVuRCxNQUFNLGFBQWEsR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUEsaUNBQWtCLEVBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQztJQUNsRSxNQUFNLE1BQU0sR0FBRyxPQUFPLENBQUMsS0FBSyxDQUFDLFVBQVUsQ0FBQyxJQUFJLEVBQUUsT0FBTyxDQUFDLENBQUM7SUFDdkQsT0FBTyxPQUFPLENBQUMsV0FBVyxDQUFDLGFBQWEsRUFBRSxNQUFNLEVBQUUsT0FBTyxDQUFDLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxDQUFDO0FBQzdFLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyB1dHhvbGliIGZyb20gJ0BiaXRnby1iZXRhL3V0eG8tbGliJztcbmltcG9ydCAqIGFzIHNka2NvcmUgZnJvbSAnQGJpdGdvLWJldGEvc2RrLWNvcmUnO1xuaW1wb3J0IHsgY2Fub25pY2FsaXplT2JqZWN0LCBTaWduYWJsZSB9IGZyb20gJy4vc2lnbmFibGVKc29uJztcblxuLyoqXG4gKiBWZXJpZmllcyBhIHNpZ25hdHVyZSBmb3IgYSBnaXZlbiBtZXNzYWdlLlxuICpcbiAqIEBwYXJhbSB7U2lnbmFibGV9IG1lc3NhZ2UgLSBUaGUgbWVzc2FnZSB0byB2ZXJpZnkuXG4gKiBAcGFyYW0ge3N0cmluZ30gc2lnbmF0dXJlIC0gVGhlIHNpZ25hdHVyZSB0byB2ZXJpZnksIGluIGhleGFkZWNpbWFsIGZvcm1hdC5cbiAqIEBwYXJhbSB7c3RyaW5nfSBwdWIgLSBUaGUgcHVibGljIGtleSBpbiBCSVAzMiBmb3JtYXQuXG4gKiBAcGFyYW0ge3V0eG9saWIuTmV0d29ya30gbmV0d29yayAtIFRoZSBuZXR3b3JrIHRvIHVzZSBmb3IgdmVyaWZpY2F0aW9uLlxuICogQHJldHVybnMge2Jvb2xlYW59IC0gUmV0dXJucyB0cnVlIGlmIHRoZSBzaWduYXR1cmUgaXMgdmFsaWQsIGZhbHNlIG90aGVyd2lzZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHZlcmlmeU1lc3NhZ2VTaWduYXR1cmUoXG4gIG1lc3NhZ2U6IFNpZ25hYmxlLFxuICBzaWduYXR1cmU6IHN0cmluZyxcbiAgcHViOiBzdHJpbmcsXG4gIG5ldHdvcms6IHV0eG9saWIuTmV0d29yayA9IHV0eG9saWIubmV0d29ya3MuYml0Y29pblxuKTogYm9vbGVhbiB7XG4gIGNvbnN0IG1lc3NhZ2VTdHJpbmcgPSBKU09OLnN0cmluZ2lmeShjYW5vbmljYWxpemVPYmplY3QobWVzc2FnZSkpO1xuICBjb25zdCBwdWJLZXkgPSB1dHhvbGliLmJpcDMyLmZyb21CYXNlNTgocHViLCBuZXR3b3JrKS5wdWJsaWNLZXk7XG4gIGNvbnN0IHNpZ25hdHVyZUJ1ZmZlciA9IEJ1ZmZlci5mcm9tKHNpZ25hdHVyZSwgJ2hleCcpO1xuICByZXR1cm4gc2RrY29yZS52ZXJpZnlNZXNzYWdlKG1lc3NhZ2VTdHJpbmcsIHB1YktleSwgc2lnbmF0dXJlQnVmZmVyLCBuZXR3b3JrKTtcbn1cblxuLyoqXG4gKiBDcmVhdGVzIGEgc2lnbmF0dXJlIGZvciBhIGdpdmVuIG1lc3NhZ2UuXG4gKlxuICogQHBhcmFtIHtTaWduYWJsZX0gbWVzc2FnZSAtIFRoZSBtZXNzYWdlIHRvIHNpZ24uXG4gKiBAcGFyYW0ge3N0cmluZ30gcHJ2IC0gVGhlIHByaXZhdGUga2V5IGluIEJJUDMyIGZvcm1hdC5cbiAqIEBwYXJhbSB7dXR4b2xpYi5OZXR3b3JrfSBuZXR3b3JrIC0gVGhlIG5ldHdvcmsgdG8gdXNlIGZvciBzaWduaW5nLlxuICogQHJldHVybnMge3N0cmluZ30gLSBSZXR1cm5zIHRoZSBzaWduYXR1cmUgaW4gaGV4YWRlY2ltYWwgZm9ybWF0LlxuICovXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlTWVzc2FnZVNpZ25hdHVyZShcbiAgbWVzc2FnZTogU2lnbmFibGUsXG4gIHhwcnY6IHN0cmluZyxcbiAgbmV0d29yazogdXR4b2xpYi5OZXR3b3JrID0gdXR4b2xpYi5uZXR3b3Jrcy5iaXRjb2luXG4pOiBzdHJpbmcge1xuICBjb25zdCByZXF1ZXN0U3RyaW5nID0gSlNPTi5zdHJpbmdpZnkoY2Fub25pY2FsaXplT2JqZWN0KG1lc3NhZ2UpKTtcbiAgY29uc3QgcHJ2S2V5ID0gdXR4b2xpYi5iaXAzMi5mcm9tQmFzZTU4KHhwcnYsIG5ldHdvcmspO1xuICByZXR1cm4gc2RrY29yZS5zaWduTWVzc2FnZShyZXF1ZXN0U3RyaW5nLCBwcnZLZXksIG5ldHdvcmspLnRvU3RyaW5nKCdoZXgnKTtcbn1cbiJdfQ==
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { ILightningWallet, LightningWallet } from './lightning';
|
|
2
|
+
import * as sdkcore from '@bitgo-beta/sdk-core';
|
|
3
|
+
export type ICustodialLightningWallet = ILightningWallet;
|
|
4
|
+
export declare class CustodialLightningWallet extends LightningWallet implements ICustodialLightningWallet {
|
|
5
|
+
constructor(wallet: sdkcore.IWallet);
|
|
6
|
+
}
|
|
7
|
+
//# sourceMappingURL=custodialLightning.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"custodialLightning.d.ts","sourceRoot":"","sources":["../../../src/wallet/custodialLightning.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAChE,OAAO,KAAK,OAAO,MAAM,sBAAsB,CAAC;AAEhD,MAAM,MAAM,yBAAyB,GAAG,gBAAgB,CAAC;AAEzD,qBAAa,wBAAyB,SAAQ,eAAgB,YAAW,yBAAyB;gBACpF,MAAM,EAAE,OAAO,CAAC,OAAO;CAMpC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CustodialLightningWallet = void 0;
|
|
4
|
+
const lightning_1 = require("./lightning");
|
|
5
|
+
class CustodialLightningWallet extends lightning_1.LightningWallet {
|
|
6
|
+
constructor(wallet) {
|
|
7
|
+
super(wallet);
|
|
8
|
+
if (wallet.subType() !== 'lightningCustody') {
|
|
9
|
+
throw new Error(`Invalid lightning wallet type for custodial lightning: ${wallet.subType()}`);
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
exports.CustodialLightningWallet = CustodialLightningWallet;
|
|
14
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY3VzdG9kaWFsTGlnaHRuaW5nLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3dhbGxldC9jdXN0b2RpYWxMaWdodG5pbmcudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsMkNBQWdFO0FBS2hFLE1BQWEsd0JBQXlCLFNBQVEsMkJBQWU7SUFDM0QsWUFBWSxNQUF1QjtRQUNqQyxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDZCxJQUFJLE1BQU0sQ0FBQyxPQUFPLEVBQUUsS0FBSyxrQkFBa0IsRUFBRSxDQUFDO1lBQzVDLE1BQU0sSUFBSSxLQUFLLENBQUMsMERBQTBELE1BQU0sQ0FBQyxPQUFPLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFDaEcsQ0FBQztJQUNILENBQUM7Q0FDRjtBQVBELDREQU9DIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSUxpZ2h0bmluZ1dhbGxldCwgTGlnaHRuaW5nV2FsbGV0IH0gZnJvbSAnLi9saWdodG5pbmcnO1xuaW1wb3J0ICogYXMgc2RrY29yZSBmcm9tICdAYml0Z28tYmV0YS9zZGstY29yZSc7XG5cbmV4cG9ydCB0eXBlIElDdXN0b2RpYWxMaWdodG5pbmdXYWxsZXQgPSBJTGlnaHRuaW5nV2FsbGV0O1xuXG5leHBvcnQgY2xhc3MgQ3VzdG9kaWFsTGlnaHRuaW5nV2FsbGV0IGV4dGVuZHMgTGlnaHRuaW5nV2FsbGV0IGltcGxlbWVudHMgSUN1c3RvZGlhbExpZ2h0bmluZ1dhbGxldCB7XG4gIGNvbnN0cnVjdG9yKHdhbGxldDogc2RrY29yZS5JV2FsbGV0KSB7XG4gICAgc3VwZXIod2FsbGV0KTtcbiAgICBpZiAod2FsbGV0LnN1YlR5cGUoKSAhPT0gJ2xpZ2h0bmluZ0N1c3RvZHknKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEludmFsaWQgbGlnaHRuaW5nIHdhbGxldCB0eXBlIGZvciBjdXN0b2RpYWwgbGlnaHRuaW5nOiAke3dhbGxldC5zdWJUeXBlKCl9YCk7XG4gICAgfVxuICB9XG59XG4iXX0=
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/wallet/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,sBAAsB,CAAC;AACrC,cAAc,0BAA0B,CAAC;AACzC,cAAc,UAAU,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./lightning"), exports);
|
|
18
|
+
__exportStar(require("./custodialLightning"), exports);
|
|
19
|
+
__exportStar(require("./selfCustodialLightning"), exports);
|
|
20
|
+
__exportStar(require("./wallet"), exports);
|
|
21
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvd2FsbGV0L2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQSw4Q0FBNEI7QUFDNUIsdURBQXFDO0FBQ3JDLDJEQUF5QztBQUN6QywyQ0FBeUIiLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgKiBmcm9tICcuL2xpZ2h0bmluZyc7XG5leHBvcnQgKiBmcm9tICcuL2N1c3RvZGlhbExpZ2h0bmluZyc7XG5leHBvcnQgKiBmcm9tICcuL3NlbGZDdXN0b2RpYWxMaWdodG5pbmcnO1xuZXhwb3J0ICogZnJvbSAnLi93YWxsZXQnO1xuIl19
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import * as sdkcore from '@bitgo-beta/sdk-core';
|
|
2
|
+
import { PendingApprovalData, TxRequestState } from '@bitgo-beta/sdk-core';
|
|
3
|
+
import { CreateInvoiceBody, Invoice, InvoiceQuery, LightningAuthKeychain, LightningKeychain, LndCreatePaymentResponse, SubmitPaymentParams, Transaction, TransactionQuery, ListTransactionsResponse, PaymentInfo, PaymentQuery, LightningOnchainWithdrawParams, LightningOnchainWithdrawResponse, ListInvoicesResponse, ListPaymentsResponse } from '../codecs';
|
|
4
|
+
export type PayInvoiceResponse = {
|
|
5
|
+
/**
|
|
6
|
+
* Unique identifier for the payment request submitted to BitGo.
|
|
7
|
+
*/
|
|
8
|
+
txRequestId: string;
|
|
9
|
+
/**
|
|
10
|
+
* Status of the payment request submission to BitGo.
|
|
11
|
+
* - `'delivered'`: Successfully received by BitGo, but may or may not have been sent to the Lightning Network yet.
|
|
12
|
+
* - For the actual payment status, refer to `paymentStatus` and track `transfer`.
|
|
13
|
+
*/
|
|
14
|
+
txRequestState: TxRequestState;
|
|
15
|
+
/**
|
|
16
|
+
* Pending approval details, if applicable.
|
|
17
|
+
* - If present, the payment has not been initiated yet.
|
|
18
|
+
*/
|
|
19
|
+
pendingApproval?: PendingApprovalData;
|
|
20
|
+
/**
|
|
21
|
+
* Current snapshot of payment status (if available).
|
|
22
|
+
* - **`'in_flight'`**: Payment is in progress.
|
|
23
|
+
* - **`'settled'`**: Payment was successfully completed.
|
|
24
|
+
* - **`'failed'`**: Payment failed.
|
|
25
|
+
* This field is absent if approval is required before processing.
|
|
26
|
+
*/
|
|
27
|
+
paymentStatus?: LndCreatePaymentResponse;
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* Get the lightning keychain for the given wallet.
|
|
31
|
+
*/
|
|
32
|
+
export declare function getLightningKeychain(wallet: sdkcore.IWallet): Promise<LightningKeychain>;
|
|
33
|
+
/**
|
|
34
|
+
* Get the lightning auth keychains for the given wallet.
|
|
35
|
+
*/
|
|
36
|
+
export declare function getLightningAuthKeychains(wallet: sdkcore.IWallet): Promise<{
|
|
37
|
+
userAuthKey: LightningAuthKeychain;
|
|
38
|
+
nodeAuthKey: LightningAuthKeychain;
|
|
39
|
+
}>;
|
|
40
|
+
export interface ILightningWallet {
|
|
41
|
+
/**
|
|
42
|
+
* Creates a lightning invoice
|
|
43
|
+
* @param {object} params Invoice parameters
|
|
44
|
+
* @param {bigint} params.valueMsat The value of the invoice in millisatoshis
|
|
45
|
+
* @param {string} [params.memo] A memo or description for the invoice
|
|
46
|
+
* @param {number} [params.expiry] The expiry time of the invoice in seconds
|
|
47
|
+
* @returns {Promise<Invoice>} A promise that resolves to the created invoice
|
|
48
|
+
*/
|
|
49
|
+
createInvoice(params: CreateInvoiceBody): Promise<Invoice>;
|
|
50
|
+
/**
|
|
51
|
+
* Get invoice details by payment hash
|
|
52
|
+
* @param {string} paymentHash - Payment hash to lookup
|
|
53
|
+
* @returns {Promise<Invoice>} Invoice details
|
|
54
|
+
* @throws {InvalidPaymentHash} When payment hash is not valid
|
|
55
|
+
*/
|
|
56
|
+
getInvoice(paymentHash: string): Promise<Invoice>;
|
|
57
|
+
/**
|
|
58
|
+
* Lists current lightning invoices
|
|
59
|
+
* @param {InvoiceQuery} params Query parameters for filtering invoices
|
|
60
|
+
* @param {string} [params.status] The status of the invoice (open, settled, canceled)
|
|
61
|
+
* @param {bigint} [params.limit] The maximum number of invoices to return
|
|
62
|
+
* @param {Date} [params.startDate] The start date for the query
|
|
63
|
+
* @param {Date} [params.endDate] The end date for the query
|
|
64
|
+
* @param {string} [params.prevId] Continue iterating (provided by nextBatchPrevId in the previous list)
|
|
65
|
+
* @returns {Promise<ListInvoicesResponse>} List of invoices and nextBatchPrevId
|
|
66
|
+
*/
|
|
67
|
+
listInvoices(params: InvoiceQuery): Promise<ListInvoicesResponse>;
|
|
68
|
+
/**
|
|
69
|
+
* Pay a lightning invoice
|
|
70
|
+
* @param {SubmitPaymentParams} params - Payment parameters
|
|
71
|
+
* @param {string} params.invoice - The invoice to pay
|
|
72
|
+
* @param {string} params.amountMsat - The amount to pay in millisatoshis
|
|
73
|
+
* @param {string} params.passphrase - The wallet passphrase
|
|
74
|
+
* @param {string} [params.sequenceId] - Optional sequence ID for the respective payment transfer
|
|
75
|
+
* @param {string} [params.comment] - Optional comment for the respective payment transfer
|
|
76
|
+
* @returns {Promise<PayInvoiceResponse>} Payment result containing transaction request details and payment status
|
|
77
|
+
*/
|
|
78
|
+
payInvoice(params: SubmitPaymentParams): Promise<PayInvoiceResponse>;
|
|
79
|
+
/**
|
|
80
|
+
* On chain withdrawal
|
|
81
|
+
* @param {LightningOnchainWithdrawParams} params - Withdraw parameters
|
|
82
|
+
* @param {LightningOnchainRecipient[]} params.recipients - The recipients to pay
|
|
83
|
+
* @param {bigint} [params.satsPerVbyte] - Optional value for sats per virtual byte. If not present, it will be estimated.
|
|
84
|
+
* @param {number} [params.numBlocks] - Target blocks for the transaction to be confirmed
|
|
85
|
+
* @param {string} params.passphrase - The wallet passphrase
|
|
86
|
+
* @param {string} [params.sequenceId] - Optional sequence ID for the respective withdraw transfer
|
|
87
|
+
* @param {string} [params.comment] - Optional comment for the respective withdraw transfer
|
|
88
|
+
* @returns {Promise<LightningOnchainWithdrawResponse>} Withdraw result containing transaction request details and status
|
|
89
|
+
*/
|
|
90
|
+
withdrawOnchain(params: LightningOnchainWithdrawParams): Promise<LightningOnchainWithdrawResponse>;
|
|
91
|
+
/**
|
|
92
|
+
* Get payment details by payment id
|
|
93
|
+
* @param {string} paymentId - Payment id to lookup
|
|
94
|
+
* @returns {Promise<PaymentInfo>} Payment details
|
|
95
|
+
* @throws {InvalidPaymentId} When payment id is not valid
|
|
96
|
+
*/
|
|
97
|
+
getPayment(paymentId: string): Promise<PaymentInfo>;
|
|
98
|
+
/**
|
|
99
|
+
* List payments for a wallet with optional filtering
|
|
100
|
+
* @param {PaymentQuery} params Query parameters for filtering payments
|
|
101
|
+
* @param {string} [params.status] The status of the payment
|
|
102
|
+
* @param {bigint} [params.limit] The maximum number of payments to return
|
|
103
|
+
* @param {Date} [params.startDate] The start date for the query
|
|
104
|
+
* @param {Date} [params.endDate] The end date for the query
|
|
105
|
+
* @param {string} [params.paymentHash] The payment hash of the payments
|
|
106
|
+
* @param {string} [params.prevId] Continue iterating (provided by nextBatchPrevId in the previous list)
|
|
107
|
+
* @returns {Promise<ListPaymentsResponse>} List of payments and nextBatchPrevId
|
|
108
|
+
*/
|
|
109
|
+
listPayments(params: PaymentQuery): Promise<ListPaymentsResponse>;
|
|
110
|
+
/**
|
|
111
|
+
* Get transaction details by ID
|
|
112
|
+
* @param {string} txId - Transaction ID to lookup
|
|
113
|
+
* @returns {Promise<Transaction>} Transaction details
|
|
114
|
+
* @throws {InvalidTxId} When transaction ID is not valid
|
|
115
|
+
*/
|
|
116
|
+
getTransaction(txId: string): Promise<Transaction>;
|
|
117
|
+
/**
|
|
118
|
+
* List transactions for a wallet with optional filtering and cursor-based pagination
|
|
119
|
+
* @param {TransactionQuery} params Query parameters for filtering transactions
|
|
120
|
+
* @param {bigint} [params.limit] The maximum number of transactions to return
|
|
121
|
+
* @param {Date} [params.startDate] The start date for the query
|
|
122
|
+
* @param {Date} [params.endDate] The end date for the query
|
|
123
|
+
* @param {string} [params.prevId] Transaction ID for cursor-based pagination (from nextBatchPrevId)
|
|
124
|
+
* @returns {Promise<ListTransactionsResponse>} List of transactions with pagination info
|
|
125
|
+
*/
|
|
126
|
+
listTransactions(params: TransactionQuery): Promise<ListTransactionsResponse>;
|
|
127
|
+
}
|
|
128
|
+
export declare class LightningWallet implements ILightningWallet {
|
|
129
|
+
wallet: sdkcore.IWallet;
|
|
130
|
+
constructor(wallet: sdkcore.IWallet);
|
|
131
|
+
createInvoice(params: CreateInvoiceBody): Promise<Invoice>;
|
|
132
|
+
getInvoice(paymentHash: string): Promise<Invoice>;
|
|
133
|
+
listInvoices(params: InvoiceQuery): Promise<ListInvoicesResponse>;
|
|
134
|
+
payInvoice(params: SubmitPaymentParams): Promise<PayInvoiceResponse>;
|
|
135
|
+
withdrawOnchain(params: LightningOnchainWithdrawParams): Promise<LightningOnchainWithdrawResponse>;
|
|
136
|
+
getPayment(paymentId: string): Promise<PaymentInfo>;
|
|
137
|
+
listPayments(params: PaymentQuery): Promise<ListPaymentsResponse>;
|
|
138
|
+
getTransaction(txId: string): Promise<Transaction>;
|
|
139
|
+
listTransactions(params: TransactionQuery): Promise<ListTransactionsResponse>;
|
|
140
|
+
}
|
|
141
|
+
//# sourceMappingURL=lightning.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lightning.d.ts","sourceRoot":"","sources":["../../../src/wallet/lightning.ts"],"names":[],"mappings":"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"}
|