Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 9 additions & 12 deletions wallets/client/components/form/hooks.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { isTemplate, isWallet, protocolClientSchema, protocolFields, protocolFor
import { createContext, useContext, useEffect, useMemo, useCallback, useState } from 'react'
import { useWalletProtocolUpsert } from '@/wallets/client/hooks'
import { MultiStepForm, useFormState, useStep } from '@/components/multi-step-form'
import { parseNwcUrl } from '@/wallets/lib/validate'

export const Step = {
SEND: 'send',
Expand Down Expand Up @@ -83,9 +82,9 @@ function useProtocolFormState (protocol) {
}

export function useProtocolForm (protocol) {
const [globalFormState] = useFormState()
const [formState, setFormState] = useProtocolFormState(protocol)
const [complementaryFormState] = useProtocolFormState({ name: protocol.name, send: !protocol.send })
const [nwcSendFormState] = useProtocolFormState({ name: 'NWC', send: true })
const wallet = useWallet()
const lud16Domain = walletLud16Domain(wallet.name)
const fields = protocolFields(protocol)
Expand All @@ -98,16 +97,13 @@ export function useProtocolForm (protocol) {
value = complementaryFormState?.config?.[field.name]
}

if (protocol.name === 'LN_ADDR' && field.name === 'address' && lud16Domain) {
// automatically set lightning addresses from NWC urls if lud16 parameter is present
if (nwcSendFormState?.config?.url) {
const { lud16 } = parseNwcUrl(nwcSendFormState.config.url)
if (lud16?.split('@')[1] === lud16Domain) value = lud16
}
// remove domain part since we will append it automatically if lud16Domain is set
if (lud16Domain && value) {
value = value.split('@')[0]
}
if (!value && field.populate && globalFormState) {
value = field.populate(wallet, globalFormState)
}

if (lud16Domain && value) {
// remove domain part since we will append it automatically on submit if lud16Domain is set
value = value.split('@')[0]
}

return {
Expand All @@ -120,6 +116,7 @@ export function useProtocolForm (protocol) {
if (lud16Domain) {
schema = schema.transform(({ address, ...rest }) => {
return {
// append domain part to pass validation on submit
address: address ? `${address}@${lud16Domain}` : '',
...rest
}
Expand Down
4 changes: 3 additions & 1 deletion wallets/client/components/form/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,8 @@ function WalletProtocolForm () {

// create a copy of values to avoid mutating the original
const onSubmit = useCallback(async ({ ...values }) => {
// the schema transformation already does this to pass validation on submit
// so it would be better to use the transformed values instead of manually appending the domain part again here
const lud16Domain = walletLud16Domain(wallet.name)
if (values.address && lud16Domain) {
values.address = `${values.address}@${lud16Domain}`
Expand Down Expand Up @@ -180,7 +182,7 @@ function WalletProtocolFormField ({ type, ...props }) {
const [protocol] = useProtocol()
const formik = useFormikContext()

function transform ({ validate, encrypt, editable, help, share, ...props }) {
function transform ({ validate, encrypt, editable, help, share, populate, ...props }) {
const [upperHint, bottomHint] = Array.isArray(props.hint) ? props.hint : [null, props.hint]

const parseHelpText = text => Array.isArray(text) ? text.join('\n\n') : text
Expand Down
8 changes: 8 additions & 0 deletions wallets/lib/protocols/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,14 @@ import clinkSuite from './clink'
* @property {string} [hint] - hint text shown below field
* @property {boolean} [share] - whether field can be used to prepopulate field of complementary send/receive protocol
* @property {boolean} [editable] - whether the field is editable after it was saved
* @property {ProtocolFieldPopulate} [populate] - function to populate the field using values from other protocol forms
*/

/**
* @callback ProtocolFieldPopulate
* @param {Object} wallet - the wallet we are configuring
* @param {Object} formState - the current form state across all protocols
* @returns {string|null} - the value to populate the field with, or null if no value is available
*/

/** @type {Protocol[]} */
Expand Down
27 changes: 25 additions & 2 deletions wallets/lib/protocols/lnAddr.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { externalLightningAddressValidator } from '@/wallets/lib/validate'
import { externalLightningAddressValidator, parseNwcUrl } from '@/wallets/lib/validate'
import { protocolFormId, walletLud16Domain } from '../util'

// Lightning Address (LUD-16)
// https://github.com/lnurl/luds/blob/luds/16.md
Expand All @@ -13,8 +14,30 @@ export default {
label: 'address',
type: 'text',
required: true,
validate: externalLightningAddressValidator
validate: externalLightningAddressValidator,
populate: addressPopulate
}
],
relationName: 'walletRecvLightningAddress'
}

function addressPopulate (wallet, formState) {
const nwcFormId = protocolFormId({ name: 'NWC', send: true })
const nwcFormState = formState[nwcFormId]
if (!nwcFormState?.config?.url) {
return null
}

const { lud16: nwcLud16 } = parseNwcUrl(nwcFormState.config.url)
if (!nwcLud16) {
return null
}

const lud16Domain = walletLud16Domain(wallet.name)
const nwcLud16Domain = nwcLud16.split('@')[1]
if (lud16Domain && nwcLud16Domain !== lud16Domain) {
return null
}

return nwcLud16
}