From 8c2d2c517573d2c18e3c5698136bdafb20cf5ad0 Mon Sep 17 00:00:00 2001 From: fiatjaf Date: Sat, 21 Dec 2019 16:44:35 -0300 Subject: [PATCH 1/9] decode invoices locally. --- class/lightning-custodian-wallet.js | 55 +++++++++++++++++------------ package.json | 1 + 2 files changed, 34 insertions(+), 22 deletions(-) diff --git a/class/lightning-custodian-wallet.js b/class/lightning-custodian-wallet.js index f4b0fad5c..d93db6004 100644 --- a/class/lightning-custodian-wallet.js +++ b/class/lightning-custodian-wallet.js @@ -1,5 +1,6 @@ import { LegacyWallet } from './legacy-wallet'; import Frisbee from 'frisbee'; +import bolt11 from 'bolt11'; import { BitcoinUnit, Chain } from '../models/bitcoinUnits'; export class LightningCustodianWallet extends LegacyWallet { @@ -515,7 +516,7 @@ export class LightningCustodianWallet extends LegacyWallet { * Example return: * { destination: '03864ef025fde8fb587d989186ce6a4a186895ee44a926bfc370e2c366597a3f8f', * payment_hash: 'faf996300a468b668c58ca0702a12096475a0dd2c3dde8e812f954463966bcf4', - * num_satoshisnum_satoshis: '100', + * num_satoshis: '100', * timestamp: '1535116657', * expiry: '3600', * description: 'hundredSatoshis blitzhub', @@ -527,31 +528,41 @@ export class LightningCustodianWallet extends LegacyWallet { * @param invoice BOLT invoice string * @return {Promise.} */ - async decodeInvoice(invoice) { - await this.checkLogin(); + decodeInvoice(invoice) { + let { payeeNodeKey, tags, satoshis, millisatoshis, timestamp } = bolt11.decode(invoice); - let response = await this._api.get('/decodeinvoice?invoice=' + invoice, { - headers: { - 'Access-Control-Allow-Origin': '*', - 'Content-Type': 'application/json', - Authorization: 'Bearer' + ' ' + this.access_token, - }, - }); + var decoded = { + destination: payeeNodeKey, + num_satoshis: satoshis + ? satoshis.toString() + : millisatoshis.toString(), + timestamp: timestamp.toString(), + fallback_addr: '', + route_hints: [] + }; - let json = response.body; - if (typeof json === 'undefined') { - throw new Error('API failure: ' + response.err + ' ' + JSON.stringify(response.body)); + for (let i = 0; i < tags.length; i++) { + let {tagName, data} = tags[i]; + switch (tagName) { + case 'payment_hash': + decoded.payment_hash = data + break + case 'purpose_commit_hash': + decoded.description_hash = data + break + case 'min_final_cltv_expiry': + decoded.cltv_expiry = data.toString() + break + case 'expire_time': + decoded.expiry = data.toString() + break + case 'description': + decoded.description = data + break + } } - if (json && json.error) { - throw new Error('API error: ' + json.message + ' (code ' + json.code + ')'); - } - - if (!json.payment_hash) { - throw new Error('API unexpected response: ' + JSON.stringify(response.body)); - } - - return (this.decoded_invoice_raw = json); + return (this.decoded_invoice_raw = decoded); } async fetchInfo() { diff --git a/package.json b/package.json index 76619bf9a..24e15322a 100644 --- a/package.json +++ b/package.json @@ -64,6 +64,7 @@ "bip32": "2.0.3", "bip39": "2.5.0", "bitcoinjs-lib": "5.1.6", + "bolt11": "github:fiatjaf/bolt11#740b0516d99bb6a19f20444d1e0d52d3839f2575", "buffer": "5.2.1", "buffer-reverse": "1.0.1", "coinselect": "3.1.11", From 3c0cffc74a8b5aa9c25b7d5804de4e67af8bc4cd Mon Sep 17 00:00:00 2001 From: fiatjaf Date: Wed, 25 Dec 2019 20:44:43 -0300 Subject: [PATCH 2/9] change dependency to bluewallet/bolt11. --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 24e15322a..708df7898 100644 --- a/package.json +++ b/package.json @@ -64,7 +64,7 @@ "bip32": "2.0.3", "bip39": "2.5.0", "bitcoinjs-lib": "5.1.6", - "bolt11": "github:fiatjaf/bolt11#740b0516d99bb6a19f20444d1e0d52d3839f2575", + "bolt11": "github:BlueWallet/bolt11#740b0516d99bb6a19f20444d1e0d52d3839f2575", "buffer": "5.2.1", "buffer-reverse": "1.0.1", "coinselect": "3.1.11", From a4d65faae1edf2121b553397e9eaa24d007d94d7 Mon Sep 17 00:00:00 2001 From: fiatjaf Date: Thu, 26 Dec 2019 16:34:35 -0300 Subject: [PATCH 3/9] non await decodeInvoice. --- screen/lnd/scanLndInvoice.js | 2 +- tests/integration/LightningCustodianWallet.test.js | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/screen/lnd/scanLndInvoice.js b/screen/lnd/scanLndInvoice.js index c10a3952c..01889bb9b 100644 --- a/screen/lnd/scanLndInvoice.js +++ b/screen/lnd/scanLndInvoice.js @@ -122,7 +122,7 @@ export default class ScanLndInvoice extends React.Component { let w = this.state.fromWallet; let decoded; try { - decoded = await w.decodeInvoice(data); + decoded = w.decodeInvoice(data); let expiresIn = (decoded.timestamp * 1 + decoded.expiry * 1) * 1000; // ms if (+new Date() > expiresIn) { diff --git a/tests/integration/LightningCustodianWallet.test.js b/tests/integration/LightningCustodianWallet.test.js index f3e5aee35..7bcec36dc 100644 --- a/tests/integration/LightningCustodianWallet.test.js +++ b/tests/integration/LightningCustodianWallet.test.js @@ -100,7 +100,7 @@ describe('LightningCustodianWallet', () => { let invoice = 'lnbc1u1pdcqpt3pp5ltuevvq2g69kdrzcegrs9gfqjer45rwjc0w736qjl92yvwtxhn6qdp8dp6kuerjv4j9xct5daeks6tnyp3xc6t50f582cscqp2zrkghzl535xjav52ns0rpskcn20takzdr2e02wn4xqretlgdemg596acq5qtfqhjk4jpr7jk8qfuuka2k0lfwjsk9mchwhxcgxzj3tsp09gfpy'; - let decoded = await l2.decodeInvoice(invoice); + let decoded = l2.decodeInvoice(invoice); assert.ok(decoded.payment_hash); assert.ok(decoded.description); @@ -112,7 +112,7 @@ describe('LightningCustodianWallet', () => { invoice = 'gsom'; let error = false; try { - await l2.decodeInvoice(invoice); + l2.decodeInvoice(invoice); } catch (Err) { error = true; } @@ -155,7 +155,7 @@ describe('LightningCustodianWallet', () => { await l2.fetchTransactions(); let txLen = l2.transactions_raw.length; - let decoded = await l2.decodeInvoice(invoice); + let decoded = l2.decodeInvoice(invoice); assert.ok(decoded.payment_hash); assert.ok(decoded.description); @@ -336,7 +336,7 @@ describe('LightningCustodianWallet', () => { let oldBalance = +l2.balance; let txLen = l2.transactions_raw.length; - let decoded = await l2.decodeInvoice(invoice); + let decoded = l2.decodeInvoice(invoice); assert.ok(decoded.payment_hash); assert.ok(decoded.description); assert.strictEqual(+decoded.num_satoshis, 0); @@ -443,7 +443,7 @@ describe('LightningCustodianWallet', () => { let oldBalance = +l2.balance; let txLen = l2.transactions_raw.length; - let decoded = await l2.decodeInvoice(invoice); + let decoded = l2.decodeInvoice(invoice); assert.ok(decoded.payment_hash); assert.ok(decoded.description); assert.strictEqual(+decoded.num_satoshis, 0); From b02fe5c8b1cc4827331e08bbde85c0cc7c575e0c Mon Sep 17 00:00:00 2001 From: fiatjaf Date: Fri, 10 Jan 2020 18:15:04 -0300 Subject: [PATCH 4/9] finally update bolt11 to latest official release. --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 708df7898..73721ac56 100644 --- a/package.json +++ b/package.json @@ -64,7 +64,7 @@ "bip32": "2.0.3", "bip39": "2.5.0", "bitcoinjs-lib": "5.1.6", - "bolt11": "github:BlueWallet/bolt11#740b0516d99bb6a19f20444d1e0d52d3839f2575", + "bolt11": "1.2.7", "buffer": "5.2.1", "buffer-reverse": "1.0.1", "coinselect": "3.1.11", From 8200fc0cf80cf5bb77070b762dddf4f9fe109b32 Mon Sep 17 00:00:00 2001 From: Overtorment Date: Sun, 12 Jan 2020 00:00:33 +0000 Subject: [PATCH 5/9] TST: ln fix --- class/lightning-custodian-wallet.js | 74 +++++++++++++++---- .../LightningCustodianWallet.test.js | 17 +++++ 2 files changed, 75 insertions(+), 16 deletions(-) diff --git a/class/lightning-custodian-wallet.js b/class/lightning-custodian-wallet.js index d93db6004..3b11d93d3 100644 --- a/class/lightning-custodian-wallet.js +++ b/class/lightning-custodian-wallet.js @@ -531,34 +531,33 @@ export class LightningCustodianWallet extends LegacyWallet { decodeInvoice(invoice) { let { payeeNodeKey, tags, satoshis, millisatoshis, timestamp } = bolt11.decode(invoice); - var decoded = { + let decoded = { destination: payeeNodeKey, - num_satoshis: satoshis - ? satoshis.toString() - : millisatoshis.toString(), + num_satoshis: satoshis ? satoshis.toString() : '0', + num_millisatoshis: millisatoshis ? millisatoshis.toString() : '0', timestamp: timestamp.toString(), fallback_addr: '', - route_hints: [] + route_hints: [], }; for (let i = 0; i < tags.length; i++) { - let {tagName, data} = tags[i]; + let { tagName, data } = tags[i]; switch (tagName) { case 'payment_hash': - decoded.payment_hash = data - break + decoded.payment_hash = data; + break; case 'purpose_commit_hash': - decoded.description_hash = data - break + decoded.description_hash = data; + break; case 'min_final_cltv_expiry': - decoded.cltv_expiry = data.toString() - break + decoded.cltv_expiry = data.toString(); + break; case 'expire_time': - decoded.expiry = data.toString() - break + decoded.expiry = data.toString(); + break; case 'description': - decoded.description = data - break + decoded.description = data; + break; } } @@ -613,6 +612,49 @@ export class LightningCustodianWallet extends LegacyWallet { allowReceive() { return true; } + + /** + * Example return: + * { destination: '03864ef025fde8fb587d989186ce6a4a186895ee44a926bfc370e2c366597a3f8f', + * payment_hash: 'faf996300a468b668c58ca0702a12096475a0dd2c3dde8e812f954463966bcf4', + * num_satoshis: '100', + * timestamp: '1535116657', + * expiry: '3600', + * description: 'hundredSatoshis blitzhub', + * description_hash: '', + * fallback_addr: '', + * cltv_expiry: '10', + * route_hints: [] } + * + * @param invoice BOLT invoice string + * @return {Promise.} + */ + async decodeInvoiceRemote(invoice) { + await this.checkLogin(); + + let response = await this._api.get('/decodeinvoice?invoice=' + invoice, { + headers: { + 'Access-Control-Allow-Origin': '*', + 'Content-Type': 'application/json', + Authorization: 'Bearer' + ' ' + this.access_token, + }, + }); + + let json = response.body; + if (typeof json === 'undefined') { + throw new Error('API failure: ' + response.err + ' ' + JSON.stringify(response.body)); + } + + if (json && json.error) { + throw new Error('API error: ' + json.message + ' (code ' + json.code + ')'); + } + + if (!json.payment_hash) { + throw new Error('API unexpected response: ' + JSON.stringify(response.body)); + } + + return (this.decoded_invoice_raw = json); + } } /* diff --git a/tests/integration/LightningCustodianWallet.test.js b/tests/integration/LightningCustodianWallet.test.js index 7bcec36dc..a440078b6 100644 --- a/tests/integration/LightningCustodianWallet.test.js +++ b/tests/integration/LightningCustodianWallet.test.js @@ -105,6 +105,7 @@ describe('LightningCustodianWallet', () => { assert.ok(decoded.payment_hash); assert.ok(decoded.description); assert.ok(decoded.num_satoshis); + assert.strictEqual(parseInt(decoded.num_satoshis) * 1000, parseInt(decoded.num_millisatoshis)); await l2.checkRouteInvoice(invoice); @@ -119,6 +120,22 @@ describe('LightningCustodianWallet', () => { assert.ok(error); }); + it('can decode invoice locally & remotely', async () => { + let l2 = new LightningCustodianWallet(); + l2.setSecret(process.env.BLITZHUB); + await l2.authorize(); + let invoice = + 'lnbc1u1pdcqpt3pp5ltuevvq2g69kdrzcegrs9gfqjer45rwjc0w736qjl92yvwtxhn6qdp8dp6kuerjv4j9xct5daeks6tnyp3xc6t50f582cscqp2zrkghzl535xjav52ns0rpskcn20takzdr2e02wn4xqretlgdemg596acq5qtfqhjk4jpr7jk8qfuuka2k0lfwjsk9mchwhxcgxzj3tsp09gfpy'; + let decodedLocally = l2.decodeInvoice(invoice); + let decodedRemotely = await l2.decodeInvoiceRemote(invoice); + assert.strictEqual(decodedLocally.destination, decodedRemotely.destination); + assert.strictEqual(decodedLocally.num_satoshis, decodedRemotely.num_satoshis); + assert.strictEqual(decodedLocally.timestamp, decodedRemotely.timestamp); + assert.strictEqual(decodedLocally.payment_hash, decodedRemotely.payment_hash); + assert.strictEqual(decodedLocally.description, decodedRemotely.description); + assert.strictEqual(decodedLocally.cltv_expiry, decodedRemotely.cltv_expiry); + }); + it('can pay invoice', async () => { jasmine.DEFAULT_TIMEOUT_INTERVAL = 100 * 1000; if (!process.env.BLITZHUB) { From 5e85dd30105b35239eb75c7b6c641e11a7bbee37 Mon Sep 17 00:00:00 2001 From: Overtorment Date: Sun, 12 Jan 2020 00:02:24 +0000 Subject: [PATCH 6/9] OPS: more strict linter checks. now CI will redflag even minor codestyle issues. run 'npm run lint:fix' manually before commit --- package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 73721ac56..ced16b397 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,8 @@ "postinstall": "./node_modules/.bin/rn-nodeify --install buffer,events,process,stream,util,inherits,fs,path --hack; npm run releasenotes2json; npm run podinstall; npx jetify", "test": "npm run unit && npm run jest && npm run lint", "jest": "node node_modules/jest/bin/jest.js tests/integration/*", - "lint": "./node_modules/.bin/eslint *.js screen/**/*.js screen/ class/ models/ loc/ tests/integration/ --fix", + "lint": "./node_modules/.bin/eslint *.js screen/**/*.js screen/ class/ models/ loc/ tests/integration/", + "lint:fix": "./node_modules/.bin/eslint *.js screen/**/*.js screen/ class/ models/ loc/ tests/integration/ --fix", "unit": "./node_modules/.bin/mocha tests/unit/*" }, "jest": { From db1fa07f375b4ba5f40b15a735e956ee4a037f5d Mon Sep 17 00:00:00 2001 From: Overtorment Date: Sun, 12 Jan 2020 12:01:26 +0000 Subject: [PATCH 7/9] REL: ver bump --- android/app/build.gradle | 2 +- ios/BlueWallet/Info.plist | 2 +- ios/BlueWalletWatch Extension/Info.plist | 2 +- ios/BlueWalletWatch/Info.plist | 2 +- ios/TodayExtension/Info.plist | 2 +- package-lock.json | 2 +- package.json | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index 37ac1334f..79db9d82e 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -119,7 +119,7 @@ android { minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion versionCode 1 - versionName "4.9.1" + versionName "4.9.2" multiDexEnabled true missingDimensionStrategy 'react-native-camera', 'general' } diff --git a/ios/BlueWallet/Info.plist b/ios/BlueWallet/Info.plist index e1375e790..d59ec6472 100644 --- a/ios/BlueWallet/Info.plist +++ b/ios/BlueWallet/Info.plist @@ -19,7 +19,7 @@ CFBundlePackageType APPL CFBundleShortVersionString - 4.9.1 + 4.9.2 CFBundleSignature ???? CFBundleURLTypes diff --git a/ios/BlueWalletWatch Extension/Info.plist b/ios/BlueWalletWatch Extension/Info.plist index 34dedd1e6..d61d66a27 100644 --- a/ios/BlueWalletWatch Extension/Info.plist +++ b/ios/BlueWalletWatch Extension/Info.plist @@ -17,7 +17,7 @@ CFBundlePackageType XPC! CFBundleShortVersionString - 4.9.1 + 4.9.2 CFBundleVersion 239 CLKComplicationPrincipalClass diff --git a/ios/BlueWalletWatch/Info.plist b/ios/BlueWalletWatch/Info.plist index 925b3b3fc..3c7bec49f 100644 --- a/ios/BlueWalletWatch/Info.plist +++ b/ios/BlueWalletWatch/Info.plist @@ -17,7 +17,7 @@ CFBundlePackageType APPL CFBundleShortVersionString - 4.9.1 + 4.9.2 CFBundleVersion 239 UISupportedInterfaceOrientations diff --git a/ios/TodayExtension/Info.plist b/ios/TodayExtension/Info.plist index 3fca81fb5..555e97563 100644 --- a/ios/TodayExtension/Info.plist +++ b/ios/TodayExtension/Info.plist @@ -17,7 +17,7 @@ CFBundlePackageType $(PRODUCT_BUNDLE_PACKAGE_TYPE) CFBundleShortVersionString - 4.9.1 + 4.9.2 CFBundleVersion 1 NSExtension diff --git a/package-lock.json b/package-lock.json index 10c1c0ac1..a6bf2e9ba 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "BlueWallet", - "version": "4.9.1", + "version": "4.9.2", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index ced16b397..0555e7d2f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "BlueWallet", - "version": "4.9.1", + "version": "4.9.2", "devDependencies": { "@babel/core": "^7.5.0", "@babel/runtime": "^7.5.1", From e970cc273be6b9d1a8705facd9b6539efb5d2969 Mon Sep 17 00:00:00 2001 From: Overtorment Date: Sun, 12 Jan 2020 18:08:56 +0000 Subject: [PATCH 8/9] FIX: NaN expiry for ln invoices decoded locally --- class/lightning-custodian-wallet.js | 2 ++ tests/integration/LightningCustodianWallet.test.js | 1 + 2 files changed, 3 insertions(+) diff --git a/class/lightning-custodian-wallet.js b/class/lightning-custodian-wallet.js index 3b11d93d3..14155df8a 100644 --- a/class/lightning-custodian-wallet.js +++ b/class/lightning-custodian-wallet.js @@ -561,6 +561,8 @@ export class LightningCustodianWallet extends LegacyWallet { } } + if (!decoded.expiry) decoded.expiry = '3600'; // default + return (this.decoded_invoice_raw = decoded); } diff --git a/tests/integration/LightningCustodianWallet.test.js b/tests/integration/LightningCustodianWallet.test.js index a440078b6..ee574b76b 100644 --- a/tests/integration/LightningCustodianWallet.test.js +++ b/tests/integration/LightningCustodianWallet.test.js @@ -131,6 +131,7 @@ describe('LightningCustodianWallet', () => { assert.strictEqual(decodedLocally.destination, decodedRemotely.destination); assert.strictEqual(decodedLocally.num_satoshis, decodedRemotely.num_satoshis); assert.strictEqual(decodedLocally.timestamp, decodedRemotely.timestamp); + assert.strictEqual(decodedLocally.expiry, decodedRemotely.expiry); assert.strictEqual(decodedLocally.payment_hash, decodedRemotely.payment_hash); assert.strictEqual(decodedLocally.description, decodedRemotely.description); assert.strictEqual(decodedLocally.cltv_expiry, decodedRemotely.cltv_expiry); From 5d5b55bcf486c9b56b9423088bef7fa26f05d6f7 Mon Sep 17 00:00:00 2001 From: Overtorment Date: Mon, 13 Jan 2020 22:35:48 +0000 Subject: [PATCH 9/9] REL: v4.9.2 --- ios/fastlane/metadata/en-US/release_notes.txt | 43 ++++++++++--------- 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/ios/fastlane/metadata/en-US/release_notes.txt b/ios/fastlane/metadata/en-US/release_notes.txt index 960466d0e..af8a202cc 100644 --- a/ios/fastlane/metadata/en-US/release_notes.txt +++ b/ios/fastlane/metadata/en-US/release_notes.txt @@ -1,3 +1,24 @@ +v4.9.2 +====== + +* ADD: Swipe to Scan +* ADD: Handle clipboard content with both bitcoin: and lightning: +* ADD: Ask user if they have backed up their seed phrase +* ADD: Export screen allows copying to clipboard if its a LNDHub wallet +* ADD: Show LNDHub backup when creating lnd wallet +* ADD: CLP Fiat +* FIX: TX Time visual glitch +* FIX: Show an alert when theres a fetch transactions error +* FIX: TX list uses whole canvas area +* FIX: Don't allow empty wallet labels +* FIX: Wallet type selecion clipping on advanced mode +* FIX: Receive address was not being rendered +* FIX: Don't show wallet export warning if wallet was imported +* REF: Reworked Import wallet flow +* REF: BIP49 to use electrum +* REF: Custom receive + + v4.9.0 ====== @@ -30,24 +51,4 @@ v4.8.0 * FIX: layout for small devices with flexbox * FIX: Dont allow zero invoices to enable create invoice button * FIX: Change create button on Receive LN payment should be create invoice -* FIX: Update for watch - - -v4.7.1 -====== - -* ADD: Lapp browser -* FIX: White screen on boot -* FIX: Lightning wallet was not shown on Watch app -* FIX: crash on PSBT tx broadcast (when using with hardware wallet) -* REF: mnemonic backup screen -* DEL: Auto brightenss - -v4.7.0 -====== - -* ADD: external marketplace link -* FIX: electrum connection -* FIX: Now able to use biometrics with encrypted storage (not for unlocking) -* FIX: LApp marketplace address is now editable -* FIX: single address watch-only wallet Receive button crash \ No newline at end of file +* FIX: Update for watch \ No newline at end of file