diff --git a/components/LayerBalances/LightningSwipeableRow.tsx b/components/LayerBalances/LightningSwipeableRow.tsx index 873b6e398..e15e0a704 100644 --- a/components/LayerBalances/LightningSwipeableRow.tsx +++ b/components/LayerBalances/LightningSwipeableRow.tsx @@ -27,6 +27,7 @@ import Send from './../../assets/images/SVG/Send.svg'; interface LightningSwipeableRowProps { navigation: StackNavigationProp; lightning?: string; + offer?: string; locked?: boolean; } @@ -192,8 +193,15 @@ export default class LightningSwipeableRow extends Component< }; private fetchLnInvoice = () => { - const { lightning } = this.props; - if (lightning?.toLowerCase().startsWith('lnurl')) { + const { lightning, offer } = this.props; + if (offer) { + this.props.navigation.navigate('Send', { + destination: offer, + bolt12: offer, + transactionType: 'BOLT 12', + isValid: true + }); + } else if (lightning?.toLowerCase().startsWith('lnurl')) { return getlnurlParams(lightning) .then((params: any) => { if ( @@ -243,8 +251,8 @@ export default class LightningSwipeableRow extends Component< }; render() { - const { children, lightning, locked } = this.props; - if (locked && lightning) { + const { children, lightning, offer, locked } = this.props; + if (locked && (lightning || offer)) { return ( this.fetchLnInvoice()} @@ -266,7 +274,7 @@ export default class LightningSwipeableRow extends Component< > - lightning ? this.fetchLnInvoice() : this.open() + lightning || offer ? this.fetchLnInvoice() : this.open() } activeOpacity={1} > diff --git a/components/LayerBalances/index.tsx b/components/LayerBalances/index.tsx index 3fae7f65b..62342605c 100644 --- a/components/LayerBalances/index.tsx +++ b/components/LayerBalances/index.tsx @@ -43,6 +43,7 @@ interface LayerBalancesProps { value?: string; amount?: string; lightning?: string; + offer?: string; locked?: boolean; consolidated?: boolean; editMode?: boolean; @@ -160,6 +161,7 @@ const SwipeableRow = ({ value, amount, lightning, + offer, locked, editMode }: { @@ -170,6 +172,7 @@ const SwipeableRow = ({ value?: string; amount?: string; lightning?: string; + offer?: string; locked?: boolean; editMode?: boolean; }) => { @@ -178,6 +181,7 @@ const SwipeableRow = ({ @@ -259,6 +263,7 @@ export default class LayerBalances extends Component { value, amount, lightning, + offer, onRefresh, locked, consolidated, @@ -340,6 +345,7 @@ export default class LayerBalances extends Component { value={value} amount={amount} lightning={lightning} + offer={offer} locked={locked || editMode} editMode={editMode} /> diff --git a/utils/AddressUtils.test.ts b/utils/AddressUtils.test.ts index 19ea8e611..c33d23ab4 100644 --- a/utils/AddressUtils.test.ts +++ b/utils/AddressUtils.test.ts @@ -148,8 +148,7 @@ describe('AddressUtils', () => { ) ).toEqual({ value: '', - lightning: - 'lno1pgqpvggr3l9u9ppv79mzn7g9v98cf8zw900skucuz53zr5vvjss454zrnyes' + offer: 'lno1pgqpvggr3l9u9ppv79mzn7g9v98cf8zw900skucuz53zr5vvjss454zrnyes' }); expect( AddressUtils.processSendAddress( @@ -157,8 +156,7 @@ describe('AddressUtils', () => { ) ).toEqual({ value: '', - lightning: - 'lno1pgqpvggr3l9u9ppv79mzn7g9v98cf8zw900skucuz53zr5vvjss454zrnyes' + offer: 'lno1pgqpvggr3l9u9ppv79mzn7g9v98cf8zw900skucuz53zr5vvjss454zrnyes' }); expect( AddressUtils.processSendAddress( @@ -166,8 +164,7 @@ describe('AddressUtils', () => { ) ).toEqual({ value: '', - lightning: - 'lno1pgqpvggr3l9u9ppv79mzn7g9v98cf8zw900skucuz53zr5vvjss454zrnyes' + offer: 'lno1pgqpvggr3l9u9ppv79mzn7g9v98cf8zw900skucuz53zr5vvjss454zrnyes' }); }); diff --git a/utils/AddressUtils.ts b/utils/AddressUtils.ts index d71dc17a1..e74f77d2d 100644 --- a/utils/AddressUtils.ts +++ b/utils/AddressUtils.ts @@ -70,7 +70,7 @@ export const CUSTODIAL_LNDHUBS = [ ]; const bitcoinQrParser = (input: string, prefix: string) => { - let amount, lightning; + let amount, lightning, offer; const btcAddressAndParams = input.split(prefix)[1]; const [btcAddress, params] = btcAddressAndParams.split('?'); @@ -89,25 +89,27 @@ const bitcoinQrParser = (input: string, prefix: string) => { amount = amount.toString(); } - if (result.lightning || result.LIGHTNING || result.lno || result.LNO) { - console.log('result', result.lno); - lightning = - result.lightning || result.LIGHTNING || result.lno || result.LNO; + if (result.lightning || result.LIGHTNING) { + lightning = result.lightning || result.LIGHTNING; } - return [value, amount, lightning]; + if (result.lno || result.LNO) { + offer = result.lno || result.LNO; + } + + return [value, amount, lightning, offer]; }; class AddressUtils { processSendAddress = (input: string) => { - let value, amount, lightning; + let value, amount, lightning, offer; // handle addresses prefixed with 'bitcoin:' and // payment requests prefixed with 'lightning:' // handle BTCPay invoices with amounts embedded if (input.includes('bitcoin:') || input.includes('BITCOIN:')) { - const [parsedValue, parsedAmount, parsedLightning] = + const [parsedValue, parsedAmount, parsedLightning, parsedOffer] = bitcoinQrParser( input, input.includes('BITCOIN:') ? 'BITCOIN:' : 'bitcoin:' @@ -121,6 +123,10 @@ class AddressUtils { if (parsedLightning) { lightning = parsedLightning; } + + if (parsedOffer) { + offer = parsedOffer; + } } else if (input.includes('lightning:')) { value = input.split('lightning:')[1]; } else if (input.includes('LIGHTNING:')) { @@ -131,7 +137,7 @@ class AddressUtils { value = input; } - return { value, amount, lightning }; + return { value, amount, lightning, offer }; }; processLNDHubAddress = (input: string) => { diff --git a/utils/handleAnything.ts b/utils/handleAnything.ts index fcc8f3022..e403f5421 100644 --- a/utils/handleAnything.ts +++ b/utils/handleAnything.ts @@ -332,10 +332,26 @@ const handleAnything = async ( bolt12 = bolt12.replace(/("|\\)/g, ''); bolt12 = bolt12.replace(/bitcoin:b12=/, ''); + const { value, amount, lightning, offer }: any = + AddressUtils.processSendAddress(bolt12); + + if (value) { + return [ + 'Accounts', + { + value, + amount, + lightning, + offer, + locked: true + } + ]; + } + return [ 'Send', { - destination: value, + destination: value || offer, bolt12, transactionType: 'BOLT 12', isValid: true diff --git a/views/Accounts/Accounts.tsx b/views/Accounts/Accounts.tsx index 9898492b2..aa6c9c575 100644 --- a/views/Accounts/Accounts.tsx +++ b/views/Accounts/Accounts.tsx @@ -31,7 +31,13 @@ interface AccountsProps { SettingsStore: SettingsStore; route: Route< 'Accounts', - { value: string; amount: string; lightning: string; locked: boolean } + { + value: string; + amount: string; + lightning: string; + offer: string; + locked: boolean; + } >; } @@ -39,6 +45,7 @@ interface AccountsState { value: string; amount: string; lightning: string; + offer: string; locked: boolean; editMode: boolean; } @@ -53,6 +60,7 @@ export default class Accounts extends React.Component< value: '', amount: '', lightning: '', + offer: '', locked: false, editMode: false }; @@ -64,7 +72,7 @@ export default class Accounts extends React.Component< componentDidMount() { const { route } = this.props; - const { value, amount, lightning, locked } = route.params ?? {}; + const { value, amount, lightning, offer, locked } = route.params ?? {}; if (value) { this.setState({ value }); @@ -78,6 +86,10 @@ export default class Accounts extends React.Component< this.setState({ lightning }); } + if (offer) { + this.setState({ offer }); + } + if (locked) { this.setState({ locked }); } @@ -91,7 +103,8 @@ export default class Accounts extends React.Component< SettingsStore, navigation } = this.props; - const { value, amount, lightning, locked, editMode } = this.state; + const { value, amount, lightning, offer, locked, editMode } = + this.state; const { loadingAccounts, accounts } = UTXOsStore; const FilterButton = () => ( @@ -173,6 +186,7 @@ export default class Accounts extends React.Component< value={value} amount={amount} lightning={lightning} + offer={offer} locked={locked} editMode={editMode} />