From 45fa1a8d936436b8a144090a28a1109b167b30e3 Mon Sep 17 00:00:00 2001 From: Rafael Taranto Date: Thu, 29 Feb 2024 13:23:49 +0000 Subject: [PATCH] feat: lnurl support --- lib/logger.js | 2 +- lib/plugins/wallet/galoy/galoy.js | 32 ++++++++++++++++++++--- package-lock.json | 42 ++++++++++++++++--------------- package.json | 2 +- 4 files changed, 52 insertions(+), 26 deletions(-) diff --git a/lib/logger.js b/lib/logger.js index 65298e64..3fa0f242 100644 --- a/lib/logger.js +++ b/lib/logger.js @@ -21,7 +21,7 @@ const logger = new winston.Logger({ }) ], rewriters: [ - (...[,, meta]) => meta instanceof Error ? { message: meta.message, stack: meta.stack } : meta + (...[,, meta]) => meta instanceof Error ? { message: meta.message, stack: meta.stack, meta } : meta ], exitOnError: false }) diff --git a/lib/plugins/wallet/galoy/galoy.js b/lib/plugins/wallet/galoy/galoy.js index dd75f4b2..e0eeee63 100644 --- a/lib/plugins/wallet/galoy/galoy.js +++ b/lib/plugins/wallet/galoy/galoy.js @@ -92,8 +92,12 @@ function getGaloyWallet (token, endpoint, walletId) { }) } -function isLightning (address) { - return address.substr(0, 2) === 'ln' +function isLnInvoice (address) { + return address.startsWith('lnbc') +} + +function isLnurl (address) { + return address.startsWith('lnurl') } function sendFundsOnChain (walletId, address, cryptoAtoms, token, endpoint) { @@ -116,6 +120,23 @@ function sendFundsOnChain (walletId, address, cryptoAtoms, token, endpoint) { }) } +function sendFundsLNURL (walletId, lnurl, cryptoAtoms, token, endpoint) { + const sendLnNoAmount = { + 'operationName': 'lnurlPaymentSend', + 'query': `mutation lnurlPaymentSend($input: LnurlPaymentSendInput!) { + lnurlPaymentSend(input: $input) { + errors { + message + path + } + status + } + }`, + 'variables': { 'input': { 'lnurl': `${lnurl}`, 'walletId': `${walletId}`, 'amount': `${cryptoAtoms}` } } + } + return request(sendLnNoAmount, token, endpoint).then(result => result.data.lnurlPaymentSend) +} + function sendFundsLN (walletId, invoice, cryptoAtoms, token, endpoint) { const sendLnNoAmount = { 'operationName': 'lnNoAmountInvoicePaymentSend', @@ -155,9 +176,12 @@ function sendCoins (account, tx, settings, operatorId) { return checkCryptoCode(cryptoCode) .then(() => getGaloyWallet(account.apiSecret, account.endpoint, account.walletId)) .then(wallet => { - if (isLightning(toAddress)) { + if (isLnInvoice(toAddress)) { return sendFundsLN(wallet.id, toAddress, cryptoAtoms, account.apiSecret, account.endpoint) } + if (isLnurl(toAddress)) { + return sendFundsLNURL(wallet.id, toAddress, cryptoAtoms, account.apiSecret, account.endpoint) + } return sendFundsOnChain(wallet.id, toAddress, cryptoAtoms, account.apiSecret, account.endpoint) }) .then(result => { @@ -272,7 +296,7 @@ function getStatus (account, tx, requested, settings, operatorId) { return checkCryptoCode(cryptoCode) .then(() => { const address = coinUtils.parseUrl(cryptoCode, account.environment, toAddress, false) - if (isLightning(address)) { + if (isLnInvoice(address)) { return getInvoiceStatus(account.apiSecret, account.endpoint, address) .then(it => { const isPaid = it === 'PAID' diff --git a/package-lock.json b/package-lock.json index 5f9bd74e..7f79dc8e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1078,6 +1078,25 @@ "fastpriorityqueue": "^0.7.1", "typeforce": "^1.11.3", "varuint-bitcoin": "^1.1.2" + }, + "dependencies": { + "bitcoinjs-lib": { + "version": "npm:@bitgo-forks/bitcoinjs-lib@7.1.0-master.7", + "resolved": "https://registry.npmjs.org/@bitgo-forks/bitcoinjs-lib/-/bitcoinjs-lib-7.1.0-master.7.tgz", + "integrity": "sha512-FZle7954KnbbVXFCc5uYGtjq+0PFOnFxVchNwt3Kcv2nVusezTp29aeQwDi2Y+lM1dCoup2gJGXMkkREenY7KQ==", + "requires": { + "bech32": "^2.0.0", + "bip174": "npm:@bitgo-forks/bip174@3.1.0-master.4", + "bs58check": "^2.1.2", + "create-hash": "^1.1.0", + "fastpriorityqueue": "^0.7.1", + "json5": "^2.2.3", + "ripemd160": "^2.0.2", + "typeforce": "^1.11.3", + "varuint-bitcoin": "^1.1.2", + "wif": "^2.0.1" + } + } } }, "@bitgo/utxo-ord": { @@ -2132,9 +2151,9 @@ } }, "@lamassu/coins": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/@lamassu/coins/-/coins-1.4.3.tgz", - "integrity": "sha512-29XRlhYZcKYQeUWUohBLvjdvhkIYUe+TAxWYN+crw/JXSd8Bz3yId88v+n6+F3eTAN6iCDtHnTTiYRhYD4DQ/Q==", + "version": "1.4.9", + "resolved": "https://registry.npmjs.org/@lamassu/coins/-/coins-1.4.9.tgz", + "integrity": "sha512-psOTHCGJBaIP7mnMSY3zmAsX3k9m6PffnL1Kq9SE4waMyTX4fQu/heEkmWk/OACk2CSonahA4FbLNKc284cizg==", "requires": { "@lamassu/bolt11": "1.5.1", "bech32": "2.0.0", @@ -4393,23 +4412,6 @@ "resolved": "https://registry.npmjs.org/bitcoind-rpc/-/bitcoind-rpc-0.7.2.tgz", "integrity": "sha512-3alq5pH4/mAdEscucew98ls0s7BEaDvKTuYW34nSkTsmTC7G9R7Xh+ABXOxeVBfG/+rKfyQLmFAm2aRq92tJqw==" }, - "bitcoinjs-lib": { - "version": "npm:@bitgo-forks/bitcoinjs-lib@7.1.0-master.7", - "resolved": "https://registry.npmjs.org/@bitgo-forks/bitcoinjs-lib/-/bitcoinjs-lib-7.1.0-master.7.tgz", - "integrity": "sha512-FZle7954KnbbVXFCc5uYGtjq+0PFOnFxVchNwt3Kcv2nVusezTp29aeQwDi2Y+lM1dCoup2gJGXMkkREenY7KQ==", - "requires": { - "bech32": "^2.0.0", - "bip174": "npm:@bitgo-forks/bip174@3.1.0-master.4", - "bs58check": "^2.1.2", - "create-hash": "^1.1.0", - "fastpriorityqueue": "^0.7.1", - "json5": "^2.2.3", - "ripemd160": "^2.0.2", - "typeforce": "^1.11.3", - "varuint-bitcoin": "^1.1.2", - "wif": "^2.0.1" - } - }, "bitcoinjs-message": { "version": "npm:@bitgo-forks/bitcoinjs-message@1.0.0-master.2", "resolved": "https://registry.npmjs.org/@bitgo-forks/bitcoinjs-message/-/bitcoinjs-message-1.0.0-master.2.tgz", diff --git a/package.json b/package.json index 731cf246..3c3f4aeb 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,7 @@ "@ethereumjs/common": "^2.6.4", "@ethereumjs/tx": "^3.5.1", "@graphql-tools/merge": "^6.2.5", - "@lamassu/coins": "v1.4.3", + "@lamassu/coins": "v1.4.9", "@simplewebauthn/server": "^3.0.0", "@vonage/auth": "^1.5.0", "@vonage/sms": "^1.7.0",