Skip to content

Commit

Permalink
Merge pull request #2183 from shubhamkmr04/shubham/send-nostr-lookup
Browse files Browse the repository at this point in the history
Send: Lookup nostr contacts
  • Loading branch information
kaloudis authored May 24, 2024
2 parents 18b8d4b + 766f50f commit f72bfc2
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 5 deletions.
2 changes: 2 additions & 0 deletions locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -988,6 +988,8 @@
"utils.handleAnything.lnurlAuthNotSupported": "LnurlAuth not supported by your node implementation",
"utils.handleAnything.unsupportedLnurlType": "Unsupported lnurl type",
"utils.handleAnything.invalidLnurlParams": "Could not parse lnurl params",
"utils.handleAnything.nostrProfileError": "Error fetching Nostr profile",
"utils.handleAnything.addressError": "Error fetching address",
"stores.InvoicesStore.errorCreatingInvoice": "Error creating invoice",
"stores.InvoicesStore.errorGeneratingAddress": "Error generating new address",
"stores.InvoicesStore.zeroAmountLndhub": "LNDHub instance might not support zero-amount invoices",
Expand Down
2 changes: 2 additions & 0 deletions utils/handleAnything.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ jest.mock('../stores/Stores', () => ({
invoicesStore: { getPayReq: jest.fn() }
}));
jest.mock('react-native-blob-util', () => ({}));
jest.mock('react-native-encrypted-storage', () => ({}));
jest.mock('react-native-fs', () => ({}));
jest.mock('js-lnurl', () => ({
getParams: () => mockGetLnurlParams
}));
Expand Down
88 changes: 86 additions & 2 deletions utils/handleAnything.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,85 @@ import NodeUriUtils from './NodeUriUtils';
import { localeString } from './LocaleUtils';
import BackendUtils from './BackendUtils';

// Nostr
import { DEFAULT_NOSTR_RELAYS } from '../stores/SettingsStore';
import { relayInit, nip05, nip19 } from 'nostr-tools';
import ContactUtils from './ContactUtils';

const { nodeInfoStore, invoicesStore, unitsStore, settingsStore } = stores;

const isClipboardValue = (data: string) =>
handleAnything(data, undefined, true);

const attemptNip05Lookup = async (data: string) => {
try {
const lookup: any = await nip05.queryProfile(data);
const pubkey = lookup.pubkey;
return await nostrProfileLookup(pubkey);
} catch (e) {
throw new Error(localeString('utils.handleAnything.addressError'));
}
};

const nostrProfileLookup = async (data: string) => {
let profile: any;

const pubkey = data;
const profilesEventsPromises = DEFAULT_NOSTR_RELAYS.map(
async (relayItem) => {
try {
const relay = relayInit(relayItem);
relay.on('connect', () => {
console.log(`connected to ${relay.url}`);
});
relay.on('error', (): any => {
console.log(`failed to connect to ${relay.url}`);
});

await relay.connect();
return relay.list([
{
authors: [pubkey],
kinds: [0]
}
]);
} catch (e) {}
}
);

await Promise.all(profilesEventsPromises).then((profilesEventsArrays) => {
const profileEvents = profilesEventsArrays
.flat()
.filter((event) => event !== undefined);

profileEvents.forEach((item: any) => {
try {
const content = JSON.parse(item.content);
if (!profile || item.created_at > profile.timestamp) {
profile = {
content,
timestamp: item.created_at
};
}
} catch (error: any) {
throw new Error(
`Error parsing JSON for item with ID ${item.id}: ${error.message}`
);
}
});
});

return [
'ContactDetails',
{
nostrContact: await ContactUtils.transformContactData(
profile.content
),
isNostrContact: true
}
];
};

const handleAnything = async (
data: string,
setAmount?: string,
Expand Down Expand Up @@ -263,8 +337,8 @@ const handleAnything = async (
throw new Error(error);
}
})
.catch(() => {
throw new Error(error);
.catch(async () => {
return await attemptNip05Lookup(data);
});
}
} else if (value.includes('config=') && value.includes('lnd.config')) {
Expand Down Expand Up @@ -398,6 +472,16 @@ const handleAnything = async (
localeString('utils.handleAnything.invalidLnurlParams')
);
});
} else if (AddressUtils.isValidNpub(data)) {
try {
const decoded = nip19.decode(data);
const pubkey = decoded.data.toString();
return await nostrProfileLookup(pubkey);
} catch (e) {
throw new Error(
localeString('utils.handleAnything.nostrProfileError')
);
}
} else if (data.startsWith('zeuscontact:')) {
const zeusContactData = data.replace('zeuscontact:', '');
const contact = JSON.parse(zeusContactData);
Expand Down
18 changes: 15 additions & 3 deletions views/ContactDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,10 @@ export default class ContactDetails extends React.Component<
const contactsString = await EncryptedStorage.getItem(
'zeus-contacts'
);
const isNostrContact = this.props.navigation.getParam(
'isNostrContact',
null
);

if (contactsString && contactId) {
const existingContact = JSON.parse(contactsString);
Expand All @@ -105,9 +109,17 @@ export default class ContactDetails extends React.Component<
);

// Store the found contact in the component's state
this.setState({ contact, isLoading: false });
this.setState({
contact,
isNostrContact,
isLoading: false
});
} else {
this.setState({ contact: nostrContact, isLoading: false });
this.setState({
contact: nostrContact,
isNostrContact,
isLoading: false
});
}
} catch (error) {
console.log('Error fetching contact:', error);
Expand Down Expand Up @@ -314,7 +326,7 @@ export default class ContactDetails extends React.Component<
}
rightComponent={
<Row>
<StarButton />
{!isNostrContact && <StarButton />}
<QRButton />
</Row>
}
Expand Down

0 comments on commit f72bfc2

Please sign in to comment.