mirror of
https://github.com/BlueWallet/BlueWallet.git
synced 2025-03-04 12:18:10 +01:00
ADD: lightning address send support (closes #3690)
This commit is contained in:
parent
6df18b0805
commit
b2276e1e3b
6 changed files with 111 additions and 7 deletions
|
@ -153,6 +153,18 @@ class DeeplinkSchemaMatch {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
} else if (Lnurl.isLightningAddress(event.url)) {
|
||||||
|
// this might be not just an email but a lightning addres
|
||||||
|
// @see https://lightningaddress.com
|
||||||
|
completionHandler([
|
||||||
|
'ScanLndInvoiceRoot',
|
||||||
|
{
|
||||||
|
screen: 'ScanLndInvoice',
|
||||||
|
params: {
|
||||||
|
uri: event.url,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]);
|
||||||
} else if (DeeplinkSchemaMatch.isSafelloRedirect(event)) {
|
} else if (DeeplinkSchemaMatch.isSafelloRedirect(event)) {
|
||||||
const urlObject = url.parse(event.url, true); // eslint-disable-line node/no-deprecated-api
|
const urlObject = url.parse(event.url, true); // eslint-disable-line node/no-deprecated-api
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,15 @@ export default class Lnurl {
|
||||||
|
|
||||||
static getUrlFromLnurl(lnurlExample) {
|
static getUrlFromLnurl(lnurlExample) {
|
||||||
const found = Lnurl.findlnurl(lnurlExample);
|
const found = Lnurl.findlnurl(lnurlExample);
|
||||||
if (!found) return false;
|
if (!found) {
|
||||||
|
if (Lnurl.isLightningAddress(lnurlExample)) {
|
||||||
|
const username = lnurlExample.split('@')[0].trim();
|
||||||
|
const host = lnurlExample.split('@')[1].trim();
|
||||||
|
return `https://${host}/.well-known/lnurlp/${username}`;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const decoded = bech32.decode(found, 10000);
|
const decoded = bech32.decode(found, 10000);
|
||||||
return Buffer.from(bech32.fromWords(decoded.words)).toString();
|
return Buffer.from(bech32.fromWords(decoded.words)).toString();
|
||||||
|
@ -256,4 +264,11 @@ export default class Lnurl {
|
||||||
getCommentAllowed() {
|
getCommentAllowed() {
|
||||||
return this?._lnurlPayServicePayload?.commentAllowed ? parseInt(this._lnurlPayServicePayload.commentAllowed) : false;
|
return this?._lnurlPayServicePayload?.commentAllowed ? parseInt(this._lnurlPayServicePayload.commentAllowed) : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static isLightningAddress(address) {
|
||||||
|
// ensure only 1 `@` present:
|
||||||
|
if (address.split('@').length !== 2) return false;
|
||||||
|
const splitted = address.split('@');
|
||||||
|
return !!splitted[0].trim() && !!splitted[1].trim();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,11 +56,16 @@ const LnurlPay = () => {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (lnurl) {
|
if (lnurl) {
|
||||||
const ln = new Lnurl(lnurl, AsyncStorage);
|
const ln = new Lnurl(lnurl, AsyncStorage);
|
||||||
ln.callLnurlPayService().then(setPayload);
|
ln.callLnurlPayService()
|
||||||
|
.then(setPayload)
|
||||||
|
.catch(error => {
|
||||||
|
alert(error.message);
|
||||||
|
pop();
|
||||||
|
});
|
||||||
setLN(ln);
|
setLN(ln);
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
}
|
}
|
||||||
}, [lnurl]);
|
}, [lnurl, pop]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setPayButtonDisabled(isLoading);
|
setPayButtonDisabled(isLoading);
|
||||||
|
|
|
@ -92,6 +92,9 @@ const ScanLndInvoice = () => {
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (wallet && uri) {
|
if (wallet && uri) {
|
||||||
|
if (Lnurl.isLnurl(uri)) return processLnurlPay(uri);
|
||||||
|
if (Lnurl.isLightningAddress(uri)) return processLnurlPay(uri);
|
||||||
|
|
||||||
let data = uri;
|
let data = uri;
|
||||||
// handling BIP21 w/BOLT11 support
|
// handling BIP21 w/BOLT11 support
|
||||||
const ind = data.indexOf('lightning=');
|
const ind = data.indexOf('lightning=');
|
||||||
|
@ -102,9 +105,6 @@ const ScanLndInvoice = () => {
|
||||||
data = data.replace('LIGHTNING:', '').replace('lightning:', '');
|
data = data.replace('LIGHTNING:', '').replace('lightning:', '');
|
||||||
console.log(data);
|
console.log(data);
|
||||||
|
|
||||||
/**
|
|
||||||
* @type {LightningCustodianWallet}
|
|
||||||
*/
|
|
||||||
let decoded;
|
let decoded;
|
||||||
try {
|
try {
|
||||||
decoded = wallet.decodeInvoice(data);
|
decoded = wallet.decodeInvoice(data);
|
||||||
|
@ -144,6 +144,7 @@ const ScanLndInvoice = () => {
|
||||||
|
|
||||||
const processInvoice = data => {
|
const processInvoice = data => {
|
||||||
if (Lnurl.isLnurl(data)) return processLnurlPay(data);
|
if (Lnurl.isLnurl(data)) return processLnurlPay(data);
|
||||||
|
if (Lnurl.isLightningAddress(data)) return processLnurlPay(data);
|
||||||
setParams({ uri: data });
|
setParams({ uri: data });
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -216,7 +217,12 @@ const ScanLndInvoice = () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const processTextForInvoice = text => {
|
const processTextForInvoice = text => {
|
||||||
if (text.toLowerCase().startsWith('lnb') || text.toLowerCase().startsWith('lightning:lnb') || Lnurl.isLnurl(text)) {
|
if (
|
||||||
|
text.toLowerCase().startsWith('lnb') ||
|
||||||
|
text.toLowerCase().startsWith('lightning:lnb') ||
|
||||||
|
Lnurl.isLnurl(text) ||
|
||||||
|
Lnurl.isLightningAddress(text)
|
||||||
|
) {
|
||||||
processInvoice(text);
|
processInvoice(text);
|
||||||
} else {
|
} else {
|
||||||
setDecoded(undefined);
|
setDecoded(undefined);
|
||||||
|
|
|
@ -202,6 +202,20 @@ describe('unit - DeepLinkSchemaMatch', function () {
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
argument: {
|
||||||
|
url: 'lnaddress@zbd.gg',
|
||||||
|
},
|
||||||
|
expected: [
|
||||||
|
'ScanLndInvoiceRoot',
|
||||||
|
{
|
||||||
|
screen: 'ScanLndInvoice',
|
||||||
|
params: {
|
||||||
|
uri: 'lnaddress@zbd.gg',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
argument: {
|
argument: {
|
||||||
url: require('fs').readFileSync('./tests/unit/fixtures/skeleton-cobo.txt', 'ascii'),
|
url: require('fs').readFileSync('./tests/unit/fixtures/skeleton-cobo.txt', 'ascii'),
|
||||||
|
|
|
@ -164,3 +164,55 @@ describe('LNURL', function () {
|
||||||
assert.strictEqual(Lnurl.decipherAES(ciphertext, preimage, iv), '1234');
|
assert.strictEqual(Lnurl.decipherAES(ciphertext, preimage, iv), '1234');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('lightning address', function () {
|
||||||
|
it('can getUrlFromLnurl()', () => {
|
||||||
|
assert.strictEqual(Lnurl.getUrlFromLnurl('lnaddress@zbd.gg'), 'https://zbd.gg/.well-known/lnurlp/lnaddress');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can detect', async () => {
|
||||||
|
assert.ok(Lnurl.isLightningAddress('lnaddress@zbd.gg'));
|
||||||
|
assert.ok(Lnurl.isLightningAddress(' lnaddress@zbd.gg '));
|
||||||
|
assert.ok(Lnurl.isLightningAddress(' lnaddress@zbd.gg '));
|
||||||
|
assert.ok(Lnurl.isLightningAddress(' lnaddress@8.8.8.8 '));
|
||||||
|
assert.ok(Lnurl.isLightningAddress(' lnaddress@hidden.onion '));
|
||||||
|
assert.ok(!Lnurl.isLightningAddress(' bla bla '));
|
||||||
|
assert.ok(!Lnurl.isLightningAddress(''));
|
||||||
|
assert.ok(!Lnurl.isLightningAddress('@'));
|
||||||
|
assert.ok(!Lnurl.isLightningAddress('@a'));
|
||||||
|
assert.ok(!Lnurl.isLightningAddress('a@'));
|
||||||
|
|
||||||
|
const LN = new Lnurl('lnaddress@zbd.gg');
|
||||||
|
|
||||||
|
// poor-man's mock:
|
||||||
|
LN._fetchGet = LN.fetchGet;
|
||||||
|
let requestedUri = -1;
|
||||||
|
LN.fetchGet = actuallyRequestedUri => {
|
||||||
|
requestedUri = actuallyRequestedUri;
|
||||||
|
return {
|
||||||
|
minSendable: 1000,
|
||||||
|
maxSendable: 45000000,
|
||||||
|
commentAllowed: 150,
|
||||||
|
tag: 'payRequest',
|
||||||
|
metadata: '[["text/plain","lnaddress - lightningaddress.com"],["text/identifier","lnaddress@zbd.gg"],["image/png;base64","img"]]',
|
||||||
|
callback: 'https://api.zebedee.io/v0/process-static-charges/9a44621d-0665-44eb-96af-e06534311be5',
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const lnurlpayPayload = await LN.callLnurlPayService();
|
||||||
|
assert.deepStrictEqual(lnurlpayPayload, {
|
||||||
|
amount: 1,
|
||||||
|
callback: 'https://api.zebedee.io/v0/process-static-charges/9a44621d-0665-44eb-96af-e06534311be5',
|
||||||
|
commentAllowed: 150,
|
||||||
|
description: 'lnaddress - lightningaddress.com',
|
||||||
|
domain: 'api.zebedee.io',
|
||||||
|
fixed: false,
|
||||||
|
image: 'data:image/png;base64,img',
|
||||||
|
max: 45000,
|
||||||
|
metadata: '[["text/plain","lnaddress - lightningaddress.com"],["text/identifier","lnaddress@zbd.gg"],["image/png;base64","img"]]',
|
||||||
|
min: 1,
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.strictEqual(requestedUri, 'https://zbd.gg/.well-known/lnurlp/lnaddress');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
Loading…
Add table
Reference in a new issue