feat: clink: support noffer in contacts (add, display, tap to pay)

This commit is contained in:
Evan Kaloudis
2026-05-27 16:20:49 -04:00
parent a2ab4e00ce
commit 18905f33b6
5 changed files with 77 additions and 0 deletions
+1
View File
@@ -1933,6 +1933,7 @@
"views.PayCodes.noPayCodes": "No pay codes created yet",
"views.Settings.Bolt12Address": "BOLT 12 address",
"views.Settings.Bolt12Offer": "BOLT 12 offer",
"views.Settings.Noffer": "CLINK noffer",
"views.Settings.Bolt12Address.requestButton": "Request Paycode",
"views.Settings.Bolt12Address.changeButton": "Change Paycode",
"views.Settings.Bolt12Address.handle": "Your handle",
+17
View File
@@ -11,6 +11,7 @@ export default class Contact extends BaseModel {
public lnAddress: Array<string>;
public bolt12Address: Array<string>;
public bolt12Offer: Array<string>;
public noffer: Array<string>;
public onchainAddress: Array<string>;
public pubkey: Array<string>;
public cashuPubkey: Array<string>;
@@ -50,6 +51,7 @@ export default class Contact extends BaseModel {
activeTypes.push('bolt12Address');
if (!this.isAddressArrayEmpty(this.bolt12Offer))
activeTypes.push('bolt12Offer');
if (!this.isAddressArrayEmpty(this.noffer)) activeTypes.push('noffer');
if (!this.isAddressArrayEmpty(this.onchainAddress))
activeTypes.push('onchainAddress');
if (!this.isAddressArrayEmpty(this.pubkey)) activeTypes.push('pubkey');
@@ -85,6 +87,13 @@ export default class Contact extends BaseModel {
);
}
@computed public get isSingleNoffer(): boolean {
return (
this.isAddressArraySingle(this.noffer) &&
this.isSingleAddressType('noffer')
);
}
@computed public get isSingleOnchainAddress(): boolean {
return (
this.isAddressArraySingle(this.onchainAddress) &&
@@ -118,6 +127,10 @@ export default class Contact extends BaseModel {
return !this.isAddressArrayEmpty(this.bolt12Offer);
}
@computed public get hasNoffer(): boolean {
return !this.isAddressArrayEmpty(this.noffer);
}
@computed public get hasOnchainAddress(): boolean {
return !this.isAddressArrayEmpty(this.onchainAddress);
}
@@ -136,6 +149,7 @@ export default class Contact extends BaseModel {
!this.hasLnAddress &&
!this.hasBolt12Address &&
!this.hasBolt12Offer &&
!this.hasNoffer &&
!this.hasOnchainAddress &&
!this.hasPubkey &&
!this.hasNip05 &&
@@ -154,6 +168,9 @@ export default class Contact extends BaseModel {
this.bolt12Offer?.forEach((address) => {
if (address && address !== '') count++;
});
this.noffer?.forEach((address) => {
if (address && address !== '') count++;
});
this.onchainAddress.forEach((address) => {
if (address && address !== '') count++;
});
+1
View File
@@ -134,6 +134,7 @@ export default class ContactStore {
lnAddress: prefillContact.lnAddress || [],
bolt12Address: prefillContact.bolt12Address || [],
bolt12Offer: prefillContact.bolt12Offer || [],
noffer: prefillContact.noffer || [],
pubkey: prefillContact.pubkey || [],
cashuPubkey: prefillContact.cashuPubkey || [],
onchainAddress: prefillContact.onchainAddress || [],
+15
View File
@@ -529,6 +529,21 @@ export default class ContactDetails extends React.Component<
)
)}
{!fromCashuLockSettings &&
contact.hasNoffer &&
contact.noffer.map(
(address: string, index: number) => (
<AddressRow
key={`noffer-${index}`}
address={address}
onPress={() =>
this.sendAddress(address)
}
icon={<LightningBolt />}
/>
)
)}
{!fromCashuLockSettings &&
contact.hasPubkey &&
contact.pubkey.map(
+43
View File
@@ -66,6 +66,7 @@ interface Contact {
lnAddress: string[];
bolt12Address: string[];
bolt12Offer: string[];
noffer: string[];
onchainAddress: string[];
nip05: string[];
nostrNpub: string[];
@@ -83,6 +84,7 @@ interface AddContactState {
lnAddress: string[];
bolt12Address: string[];
bolt12Offer: string[];
noffer: string[];
onchainAddress: string[];
nip05: string[];
nostrNpub: string[];
@@ -96,6 +98,7 @@ interface AddContactState {
isValidLightningAddress: boolean[];
isValidBolt12Address: boolean[];
isValidBolt12Offer: boolean[];
isValidNoffer: boolean[];
isValidPubkey: boolean[];
isValidCashuPubkey: boolean[];
isValidOnchainAddress: boolean[];
@@ -174,6 +177,7 @@ export default class AddContact extends React.Component<
lnAddress: [],
bolt12Address: [],
bolt12Offer: [],
noffer: [],
onchainAddress: [],
nip05: [],
nostrNpub: [],
@@ -187,6 +191,7 @@ export default class AddContact extends React.Component<
isValidLightningAddress: [],
isValidBolt12Address: [],
isValidBolt12Offer: [],
isValidNoffer: [],
isValidPubkey: [],
isValidCashuPubkey: [],
isValidOnchainAddress: [],
@@ -352,6 +357,16 @@ export default class AddContact extends React.Component<
}));
};
onChangeNoffer = (text: string, index: number) => {
const isValid = AddressUtils.isValidNoffer(text);
this.setState((prevState) => ({
isValidNoffer: Object.assign([...prevState.isValidNoffer], {
[index]: isValid
})
}));
};
onChangePubkey = (text: string, index: number) => {
const isValid = AddressUtils.isValidLightningPubKey(text);
@@ -449,6 +464,9 @@ export default class AddContact extends React.Component<
isValidBolt12Offer: Array(
ContactStore.prefillContact.bolt12Offer?.length || 1
).fill(true),
isValidNoffer: Array(
ContactStore.prefillContact.noffer?.length || 1
).fill(true),
isValidPubkey: Array(
ContactStore.prefillContact.pubkey?.length || 1
).fill(true),
@@ -572,6 +590,7 @@ export default class AddContact extends React.Component<
lnAddress,
bolt12Address,
bolt12Offer,
noffer,
onchainAddress,
nip05,
nostrNpub,
@@ -580,6 +599,7 @@ export default class AddContact extends React.Component<
isValidLightningAddress,
isValidBolt12Address,
isValidBolt12Offer,
isValidNoffer,
isValidPubkey,
isValidCashuPubkey,
isValidOnchainAddress,
@@ -614,6 +634,16 @@ export default class AddContact extends React.Component<
localeString('views.Settings.Bolt12Offer')
);
}
if (noffer?.length > 0) {
addFieldsToArray(
noffer,
'noffer',
<LightningBolt />,
isValidNoffer,
this.onChangeNoffer,
localeString('views.Settings.Noffer')
);
}
if (pubkey?.length > 0) {
addFieldsToArray(
pubkey,
@@ -674,6 +704,7 @@ export default class AddContact extends React.Component<
lnAddress,
bolt12Address,
bolt12Offer,
noffer,
onchainAddress,
nip05,
nostrNpub,
@@ -686,6 +717,7 @@ export default class AddContact extends React.Component<
isValidLightningAddress,
isValidBolt12Address,
isValidBolt12Offer,
isValidNoffer,
isValidNIP05,
isValidNpub,
isValidPubkey,
@@ -742,6 +774,12 @@ export default class AddContact extends React.Component<
value: 'bolt12Offer',
icon: <LightningBolt />
},
{
key: 'CLINK noffer',
translateKey: 'views.Settings.Noffer',
value: 'noffer',
icon: <LightningBolt />
},
{
key: 'Public key',
translateKey: 'views.NodeInfo.pubkey',
@@ -1055,6 +1093,8 @@ export default class AddContact extends React.Component<
isValidBolt12Address.includes(false)) ||
(bolt12Offer.length > 0 &&
isValidBolt12Offer.includes(false)) ||
(noffer.length > 0 &&
isValidNoffer.includes(false)) ||
(pubkey.length > 0 &&
isValidPubkey.includes(false)) ||
(cashuPubkey.length > 0 &&
@@ -1075,6 +1115,9 @@ export default class AddContact extends React.Component<
(bolt12Offer.length > 0 &&
bolt12Offer[0] &&
isValidBolt12Offer[0]) ||
(noffer.length > 0 &&
noffer[0] &&
isValidNoffer[0]) ||
(onchainAddress.length > 0 &&
onchainAddress[0] &&
isValidOnchainAddress[0]) ||