ShockWallet shows "Unknown Recipient" when scanning ndebit - Profile lookup protocol mismatch #5

Closed
opened 2026-06-13 21:58:17 +00:00 by padreug · 1 comment
Owner

Migrated from aiolabs/lamassu-next#5 — opened by @padreug on 2026-01-25.\n\n## Summary

When scanning an ndebit with ShockWallet, the app displays "Unknown Recipient" even though the wallet service (Lightning.Pub) has published a valid Kind 0 profile to the relay specified in the ndebit.

Root Cause Analysis

After investigating the ShockWallet codebase (shocknet/wallet), we discovered a protocol mismatch in how profile lookups are performed:

  • ndebit is bech32-encoded with TLV fields:
    • 0: 32-byte wallet service public key
    • 1: Relay URL (recommended relay for finding the wallet service)
    • 2: Optional pointer identifier
  • The relay hint (TLV 1) indicates where to find the wallet service's profile

How Lightning.Pub publishes profiles

  • Publishes standard Nostr Kind 0 profile events to the relay
  • Profile contains: name, display_name, about, picture
  • Profile is correctly published and verifiable on the relay

How ShockWallet looks up profiles

From wallet/app/store/sagas/users.ts:

sockets[normalSocketName] = rifle(
  host,  // <-- Uses ShockWallet's configured Gun RPC host
  `${publicKey}::Profile::on`
)

ShockWallet uses Gun RPC protocol for profile lookups, NOT standard Nostr Kind 0 queries.

It does not respect the relay hint embedded in the ndebit.

Evidence

Profile is correctly published and queryable:

=== NDEBIT DECODED ===
Pubkey: d55818f7bb2ed6d127589fc99fd3bf812ea9574f5b7e4c4297af7733a16e10af
Relay: wss://strfry.shock.network
Pointer: atm

=== PROFILE FOUND ON RELAY ===
Event ID: e14adffc2af551f32a7ee7264bf9d5ba80f723d92fde47f21915e42fbf5ade2c
Pubkey: d55818f7bb2ed6d127589fc99fd3bf812ea9574f5b7e4c4297af7733a16e10af
Content: {"name":"wallet","display_name":"wallet","about":"Lightning.Pub Application","picture":"https://shockwallet.app/icon.png"}

Yet ShockWallet shows "Unknown Recipient" because it queries Gun RPC instead of Nostr.

Affected Components

Component Location Issue
ShockWallet user saga wallet/app/store/sagas/users.ts Uses Gun RPC, ignores relay hint
ShockWallet UI wallet/app/screens/Chats/View.js Falls back to pubkey when profile missing
Lightning.Pub src/services/main/index.ts Publishes Kind 0 (correct), but not Gun RPC

Possible Solutions

Add fallback to query Nostr Kind 0 from the ndebit's relay hint when Gun RPC returns no profile:

// In users saga, after Gun RPC fails:
const relayHint = extractRelayFromNdebit(ndebit);
const profile = await queryNostrKind0(relayHint, pubkey);

Option 2: Modify Lightning.Pub

Make Lightning.Pub also publish profiles via Gun protocol. This is more complex and ties us to Gun infrastructure.

Option 3: Hybrid approach

  • Short term: Accept "Unknown Recipient" (payment flow still works)
  • Long term: Propose CLINK spec update to standardize profile resolution

Workaround (Current)

The CLINK debit flow itself works correctly - payments complete successfully. Only the UI display is affected.

For testing, we can use test-debit.mjs which doesn't require profile resolution.

  • packages/nostr-client/mock-machine.mjs - Mock ATM that works with CLINK
  • packages/nostr-client/test-debit.mjs - Test script proving CLINK flow works
  • Lightning.Pub patch: src/services/main/index.ts - Added Kind 0 profile publishing

References

> _Migrated from [aiolabs/lamassu-next#5](https://git.atitlan.io/aiolabs/lamassu-next/issues/5) — opened by @padreug on 2026-01-25._\n\n## Summary When scanning an ndebit with ShockWallet, the app displays "Unknown Recipient" even though the wallet service (Lightning.Pub) has published a valid Kind 0 profile to the relay specified in the ndebit. ## Root Cause Analysis After investigating the ShockWallet codebase (`shocknet/wallet`), we discovered a **protocol mismatch** in how profile lookups are performed: ### How ndebit works (CLINK spec) - ndebit is bech32-encoded with TLV fields: - `0`: 32-byte wallet service public key - `1`: Relay URL (recommended relay for finding the wallet service) - `2`: Optional pointer identifier - The relay hint (TLV 1) indicates where to find the wallet service's profile ### How Lightning.Pub publishes profiles - Publishes standard **Nostr Kind 0** profile events to the relay - Profile contains: `name`, `display_name`, `about`, `picture` - Profile is correctly published and verifiable on the relay ### How ShockWallet looks up profiles From `wallet/app/store/sagas/users.ts`: ```typescript sockets[normalSocketName] = rifle( host, // <-- Uses ShockWallet's configured Gun RPC host `${publicKey}::Profile::on` ) ``` **ShockWallet uses Gun RPC protocol for profile lookups, NOT standard Nostr Kind 0 queries.** It does not respect the relay hint embedded in the ndebit. ## Evidence Profile is correctly published and queryable: ``` === NDEBIT DECODED === Pubkey: d55818f7bb2ed6d127589fc99fd3bf812ea9574f5b7e4c4297af7733a16e10af Relay: wss://strfry.shock.network Pointer: atm === PROFILE FOUND ON RELAY === Event ID: e14adffc2af551f32a7ee7264bf9d5ba80f723d92fde47f21915e42fbf5ade2c Pubkey: d55818f7bb2ed6d127589fc99fd3bf812ea9574f5b7e4c4297af7733a16e10af Content: {"name":"wallet","display_name":"wallet","about":"Lightning.Pub Application","picture":"https://shockwallet.app/icon.png"} ``` Yet ShockWallet shows "Unknown Recipient" because it queries Gun RPC instead of Nostr. ## Affected Components | Component | Location | Issue | |-----------|----------|-------| | ShockWallet user saga | `wallet/app/store/sagas/users.ts` | Uses Gun RPC, ignores relay hint | | ShockWallet UI | `wallet/app/screens/Chats/View.js` | Falls back to pubkey when profile missing | | Lightning.Pub | `src/services/main/index.ts` | Publishes Kind 0 (correct), but not Gun RPC | ## Possible Solutions ### Option 1: Modify ShockWallet (Recommended) Add fallback to query Nostr Kind 0 from the ndebit's relay hint when Gun RPC returns no profile: ```typescript // In users saga, after Gun RPC fails: const relayHint = extractRelayFromNdebit(ndebit); const profile = await queryNostrKind0(relayHint, pubkey); ``` ### Option 2: Modify Lightning.Pub Make Lightning.Pub also publish profiles via Gun protocol. This is more complex and ties us to Gun infrastructure. ### Option 3: Hybrid approach - Short term: Accept "Unknown Recipient" (payment flow still works) - Long term: Propose CLINK spec update to standardize profile resolution ## Workaround (Current) The CLINK debit flow itself works correctly - payments complete successfully. Only the UI display is affected. For testing, we can use `test-debit.mjs` which doesn't require profile resolution. ## Related Files - `packages/nostr-client/mock-machine.mjs` - Mock ATM that works with CLINK - `packages/nostr-client/test-debit.mjs` - Test script proving CLINK flow works - Lightning.Pub patch: `src/services/main/index.ts` - Added Kind 0 profile publishing ## References - [CLINK Protocol Spec](https://github.com/shocknet/clink) - [ShockWallet Repository](https://github.com/shocknet/wallet) - [NIP-01 (Kind 0 Profile Metadata)](https://github.com/nostr-protocol/nips/blob/master/01.md)
padreug changed title from [reserved] migration number alignment to ShockWallet shows "Unknown Recipient" when scanning ndebit - Profile lookup protocol mismatch 2026-06-14 06:54:38 +00:00
Author
Owner

@padreug commented on 2026-01-25 (lamassu-next#5):

Moved to shock-wallet repo: aiolabs/shock-wallet#3

This issue is specific to ShockWallet's profile lookup implementation and belongs in that repository.

> _@padreug commented on 2026-01-25 ([lamassu-next#5](https://git.atitlan.io/aiolabs/lamassu-next/issues/5#issuecomment-47)):_ **Moved to shock-wallet repo**: https://git.atitlan.io/aiolabs/shock-wallet/issues/3 This issue is specific to ShockWallet's profile lookup implementation and belongs in that repository.
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
aiolabs/bitspire#5
No description provided.