Community

Commerce

BitcoinLink

BitcoinLink turns a limited wallet connection into claimable Lightning links. It is simple on the surface, but the security model is all about NWC permissions, encrypted Nostr events, relay availability and the fact that the link itself carries the key to claim.

BitcoinLink visual
BitcoinLink icon
Commerce Markets and payments Stores, funding, listings, vouchers, services and buyer-seller trust.
Back to Nostr
Commerce

Commerce shelf

Commerce pages cover marketplaces, fundraisers, stores, data vending, payments and the awkward but important edge between social identity and buying things.

Apps All Apps pages 520 pages in this routeApp pages, App categories, Product pages and 3 more shelves Browse pagesClose shelf

App orientation

App categories

App profiles

0xchatadvanced-nostr-searchAegisAlbyAlby GoAlby HubAlby HubAlby SDKAmberAmberAmethystAmethystApp and product researchApplication-specific dataBlossomBlossom spec NIP-B7BookstrBorisBouquetCalendar by FormstrChachiNostr Apps DirectoryCoracleCoracleCorny ChatCreatrDamusDamusDeveloper stack researchDittoDittodiVineDocstrDTANEmojitoFlotillaFlycatFormstrFountainFreeFromFundstrfutrGIF BuddyGittrgo-nostrGossipGossipGrimoireGroups NIP-29HablaHablaHello Nostr — ResourcesHighlighterHiveTalkhomebrew-nostrHORNET StorageHugo2NostrHyperNoteIrisIrisJumblekanbanstrKeys BandListrLNBits NostrmarketLumeLumilumiLUMINAMapstrMarmot Protocolmatrix-nostr-bridgeMeetstrMemestrMindsmonstrmostardMostronaknak — Nostr Army KnifeNalgorithmNarrnashboardNDKNegentropyngitNofluxNosNos Socialnos2xnosbinnosclNostorg Feature MatrixNostr App ManagerNostr Apps Directory GuideNostr clients feature listNostr Compass — ProjectsNostr Developer GuideNostr Development KitNostr Events MonitorNostr MCP ServerNostr NestsNostr PlaygroundNostr Service ProvidersNostr Writernostr-post-checkernostr-protocol/nostrnostr-rubynostr-sdknostr-sdk-ffinostr-sdk-flutternostr-to-rssnostr-toolsNostr.bandnostr.buildnostr.co.uk ClientsNostr.how — Clientsnostr.hsNostrabilityNostrAppsNostrApps category — AudioNostrApps category — CareerNostrApps category — CommunityNostrApps category — CurationNostrApps category — Direct MessageNostrApps category — DiscoveryNostrApps category — File SharingNostrApps category — Group ChatNostrApps category — MeatspaceNostrApps category — OnboardingNostrApps category — SignersNostrApps category — Toolsnostrchecknostrdbnostrdb-rsNostreeNostreonNostriaNostridNostrium / read.nostr.comNostrmoNostrubenoStrudelnoStrudelNostterNosturNosturNotedeckNpub.proNpub.worldnsec.appnsiteNsiteNstart.meObsidian Nostr WriterOlasOpenvibeOracoloOstrich WorkOwn Your PostsP2P BandPazPeridotPhoenixPlebeian MarketPostizPostr / write.nostr.comPrimalPrimalPrimal Article Editor / Reads authoringPrimal Studiopynostrpython-nostrRecommended Application HandlersRelay Toolsrsslayrust-nostrrust-nostr docsSatelliteSatellite EarthSatlantisSatShootShakespeareShopstrSlidestrSnortSnortStemstrswift-nostr-clientTreasuresWavlakeWavlakeWikifreediaWikistrYakiHonneYakiHonneYakiHonne mobile/web app directoryYondar

App pages

Deep dives

Field guides

Awesome Nostr branches

NIP explainer pages

Research and library

Source inventory

Deep Research: Clients, apps and product surfacesDeep Research: Developer stack and toolingResearch Map: nostrapps.comResearch Source: 0xchatResearch Source: 0xchat — NostrApps pageResearch Source: advanced-nostr-searchResearch Source: Aegis — NostrApps pageResearch Source: AlbyResearch Source: Alby — NostrApps pageResearch Source: Alby GoResearch Source: Alby HubResearch Source: Alby Hub GitHubResearch Source: Alby SDKResearch Source: AmberResearch Source: Amber — NostrApps pageResearch Source: AmethystResearch Source: Amethyst GitHubResearch Source: Awesome Nostr ResourcesResearch Source: BookstrResearch Source: BorisResearch Source: Boris — NostrApps pageResearch Source: BouquetResearch Source: Bouquet — NostrApps pageResearch Source: Calendar by FormstrResearch Source: ChachiResearch Source: Chachi — NostrApps pageResearch Source: CoracleResearch Source: Coracle — NostrApps pageResearch Source: Corny ChatResearch Source: DamusResearch Source: Damus — NostrApps pageResearch Source: DittoResearch Source: Ditto — NostrApps pageResearch Source: DocstrResearch Source: DTANResearch Source: DTAN — NostrApps pageResearch Source: EmojitoResearch Source: Emojito — NostrApps pageResearch Source: Flotilla — NostrApps pageResearch Source: FlycatResearch Source: FormstrResearch Source: Formstr — NostrApps pageResearch Source: FountainResearch Source: FreeFromResearch Source: FreeFrom — NostrApps pageResearch Source: FundstrResearch Source: futrResearch Source: futr — NostrApps pageResearch Source: GIF BuddyResearch Source: GIF Buddy — NostrApps pageResearch Source: GittrResearch Source: go-nostr GitHubResearch Source: GossipResearch Source: Gossip — NostrApps pageResearch Source: GrimoireResearch Source: Grimoire — NostrApps pageResearch Source: HablaResearch Source: Habla — NostrApps pageResearch Source: Hello Nostr — ResourcesResearch Source: HighlighterResearch Source: HiveTalkResearch Source: HORNET Storage — NostrCompassResearch Source: IrisResearch Source: Iris — NostrApps pageResearch Source: JumbleResearch Source: Jumble — NostrApps pageResearch Source: Keys BandResearch Source: Keys Band — NostrApps pageResearch Source: ListrResearch Source: LNBits NostrmarketResearch Source: LumeResearch Source: LumilumiResearch Source: LUMINAResearch Source: MapstrResearch Source: Marmot ProtocolResearch Source: MeetstrResearch Source: MemestrResearch Source: MindsResearch Source: monstr GitHubResearch Source: mostardResearch Source: MostroResearch Source: my.nostr.comResearch Source: nak — Nostr Army KnifeResearch Source: nak GitHubResearch Source: NalgorithmResearch Source: Narr — NostrApps pageResearch Source: nashboardResearch Source: NDK GitHubResearch Source: NDK NPMResearch Source: NegentropyResearch Source: Noflux — NostrApps pageResearch Source: Nos SocialResearch Source: Nos Social — NostrApps pageResearch Source: nos2xResearch Source: nos2x — NostrApps pageResearch Source: nosbinResearch Source: noscl GitHubResearch Source: Nostorg Feature MatrixResearch Source: Nostr App ManagerResearch Source: Nostr Book — KindsResearch Source: Nostr DesignResearch Source: Nostr Developer GuideResearch Source: Nostr NestsResearch Source: Nostr Nests — NostrApps pageResearch Source: Nostr PlaygroundResearch Source: nostr-post-checkerResearch Source: nostr-protocol/nostr GitHubResearch Source: nostr-sdk crates.ioResearch Source: nostr-sdk-ffi GitHubResearch Source: nostr-tools GitHubResearch Source: nostr-tools NPMResearch Source: Nostr.BandResearch Source: nostr.buildResearch Source: nostr.co.uk ClientsResearch Source: Nostr.howResearch Source: Nostr.how — ClientsResearch Source: Nostr.how — ProtocolResearch Source: Nostr.how — What is Nostr?Research Source: Nostr.orgResearch Source: NostrabilityResearch Source: NostrAppsResearch Source: NostrApps category — AudioResearch Source: NostrApps category — CareerResearch Source: NostrApps category — CommunityResearch Source: NostrApps category — CurationResearch Source: NostrApps category — Direct MessageResearch Source: NostrApps category — DiscoveryResearch Source: NostrApps category — File SharingResearch Source: NostrApps category — Group ChatResearch Source: NostrApps category — MeatspaceResearch Source: NostrApps category — OnboardingResearch Source: NostrApps category — SignersResearch Source: NostrApps category — ToolsResearch Source: nostrcheckResearch Source: nostrdb GitHubResearch Source: NostreeResearch Source: Nostree — NostrApps pageResearch Source: NostriaResearch Source: Nostria — NostrApps pageResearch Source: NostridResearch Source: Nostrmo — NostrApps pageResearch Source: Nostrmo GitHubResearch Source: NostrubeResearch Source: noStrudelResearch Source: noStrudel — NostrApps pageResearch Source: NostterResearch Source: NosturResearch Source: Nostur — NostrApps pageResearch Source: NotedeckResearch Source: Npub.proResearch Source: Npub.worldResearch Source: nsec.appResearch Source: NsiteResearch Source: Nstart.meResearch Source: Nstart.me — NostrApps pageResearch Source: Obsidian Nostr Writer — NostrApps pageResearch Source: OlasResearch Source: Olas — NostrApps pageResearch Source: OpenvibeResearch Source: OracoloResearch Source: Oracolo — NostrApps pageResearch Source: Ostrich WorkResearch Source: P2P BandResearch Source: PazResearch Source: PeridotResearch Source: Peridot — NostrApps pageResearch Source: PhoenixResearch Source: Phoenix — NostrApps pageResearch Source: Plebeian MarketResearch Source: Plebeian Market — NostrApps pageResearch Source: PrimalResearch Source: Primal — NostrApps pageResearch Source: Primal Article Editor / Reads authoringResearch Source: Primal StudioResearch Source: pynostr GitHubResearch Source: python-nostr GitHubResearch Source: Registry of KindsResearch Source: Relay Tools — NostrApps pageResearch Source: rsslayResearch Source: rust-nostr docsResearch Source: rust-nostr GitHubResearch Source: SatelliteResearch Source: SatShootResearch Source: ShakespeareResearch Source: Shakespeare — NostrApps pageResearch Source: ShopstrResearch Source: Shopstr — NostrApps pageResearch Source: SlidestrResearch Source: SnortResearch Source: start.nostr.netResearch Source: StemstrResearch Source: TreasuresResearch Source: WavlakeResearch Source: WikifreediaResearch Source: Wikifreedia — NostrApps pageResearch Source: WikistrResearch Source: Wikistr — NostrApps pageResearch Source: YakiHonne mobile/web app directoryResearch Source: YondarResearch Source: Yondar — NostrApps page
Commerce25 min readSingle-use non-custodial Bitcoin links with Nostr Wallet Connect

BitcoinLink

BitcoinLink turns a limited wallet connection into claimable Lightning links. It is simple on the surface, but the security model is all about NWC permissions, encrypted Nostr events, relay availability and the fact that the link itself carries the key to claim.

The quick readBitcoinLink lets a sender create one or more single-use Bitcoin links that a receiver can claim through Lightning. The live site describes it as non-custodial and built with Nostr, and the open-source repository shows why: the app does not run a traditional database for pending links. It asks the sender to authorize a limited Nostr Wallet Connect relationship, encrypts each link payload into a Nostr gift-wrapped event, publishes that event to selected relays and puts the receiver's private claim key inside the URL. The receiver opens the link, enters a Lightning invoice, LNURL pay endpoint or Lightning Address, and BitcoinLink pays through the sender's NWC budget. After a successful payment, the app publishes a NIP-09 deletion event as the claimed marker. This is clever, but it is not magic. Anyone with the link can try to claim it. The NWC budget and permissions define the maximum damage. Relays must carry the encrypted event and the claimed marker. A deletion marker is useful, but it is not the same thing as an atomic payment lock. Use small amounts, create narrow wallet permissions, keep links private and treat each URL like bearer cash.

BitcoinLink looks almost too simple when you first open it. The live page asks for a number of links, a sats amount per link and a wallet path such as Alby or Mutiny. The promise is familiar: create single-use links that someone else can redeem through Lightning. The interesting part is what the app avoids. It does not ask the sender to deposit into a BitcoinLink account, and the repository describes no server database that owns a balance while links wait to be claimed.

The project solves that problem by making Nostr the storage and coordination layer and Nostr Wallet Connect the spending path. The sender gives the app a limited wallet connection. BitcoinLink creates encrypted Nostr events that contain the NWC URL and amount for each link. The receiver gets a claim URL that can find and decrypt one of those events. When the receiver supplies a payment destination, the app asks the sender's wallet connection to pay.

That is why BitcoinLink belongs with finance and payment tools rather than ordinary social clients. The Nostr part is essential, but the reader's main question is not how to post or follow. The question is whether a link can safely carry spend authority from a sender to a receiver without a hosted balance, and what assumptions must be true for that to work.

What the sender is really authorizing

The sender side starts with a budgeted wallet relationship. In the Alby flow, the code uses the Alby SDK to create a new NWC client secret and request a connection that can pay invoices. The requested maximum amount is based on the number of links multiplied by the sats per link, the permission is not editable in the flow, and the renewal is set to never. That is the right kind of shape for a payment-link app: the connection should be narrow, temporary in spirit and sized to the links being created.

The Mutiny path is different. BitcoinLink builds a nostr+walletauth URI for Nostr Wallet Auth, points it at the Mutiny relay, requests pay_invoice and waits for a response event. When that response arrives, the app decrypts it, extracts the wallet service details and builds an NWC URL. The end result is similar from the claimer's perspective, but the setup path shows that BitcoinLink is not hard-coded to one wallet brand. It is trying to use NWC as a wallet-control interface.

The important reader point is that a BitcoinLink is not funded by BitcoinLink itself. It is funded by the sender's wallet authorization. If the NWC relationship allows pay_invoice up to a certain budget, the link can spend within that limit. If the budget is exhausted, revoked, misconfigured or unreachable, the link cannot pay. That makes the wallet permission the real money boundary.

The claim URL is not just a pretty pointer. It carries the material needed to claim. BitcoinLink encodes a JSON object into a URL-safe base64 slug. That object includes the encrypted event ID, the receiver private key, the relay list and an amount hint. The receiver private key is used to decrypt the gift-wrapped event that contains the real payment payload.

That design keeps the pending link out of a central BitcoinLink account, but it also gives the URL bearer power. If someone forwards the link to the wrong chat, stores it in a shared note, posts it publicly or lets a browser extension leak it, another person can open the claim page and try to redeem. The project can check whether a deletion event says the link was already claimed, but possession of an unclaimed link is still the practical claim right.

Readers should treat BitcoinLink URLs like cash vouchers. They are convenient because there is no account recovery process, no login dance for the receiver and no custodial balance to withdraw from BitcoinLink. They are risky for the same reason. The link must stay private until the intended receiver claims it.

What lives on relays

BitcoinLink uses Nostr relays as the place where pending encrypted links live. The repository defines a default relay set that includes relay.damus.io, relay.nostr.band, nos.lol and nostr.mutinywallet.com. A generated link can also carry relay configuration, so the claim page knows where to look for the encrypted event and the later claimed marker.

The event containing the payment payload is a gift-wrapped event. The content is encrypted; the tests explicitly check that plaintext strings such as the NWC URL and the BitcoinLink marker do not appear in the published event content. That is the right privacy direction. Relays help distribute and retain the pending link event, but they should not learn the NWC URL simply by storing the event.

Relay dependence still matters. If the event is not published, the receiver cannot claim. If relays are down, slow or filtering, the claim page may not find the gift wrap. If a deletion event is missed by a relay, another client might not see that the link was already claimed. Nostr gives BitcoinLink a portable storage layer, not a guarantee that every relay has the same view at the same time.

Why Gift Wrap matters

BitcoinLink's use of NIP-17 style gift wrap is one of the strongest parts of the design. The app creates a receiver keypair for each link, encrypts a direct-message payload to the receiver public key and wraps that message in a kind 1059 event. The receiver private key is then placed in the claim URL. That means the pending payment instruction is public enough to be stored on relays but private enough that relays and ordinary observers cannot read it.

The payload inside the gift wrap is deliberately small. It records that the event is a BitcoinLink payload, carries the NWC URL and sets the amount. The decrypt path rejects the wrong event kind, invalid keys, malformed JSON, missing NWC URLs and invalid amounts. The tests cover wrong keys, truncated keys, zero amounts, very large amounts, unique event IDs, unique receiver private keys and concurrent link creation.

For a reader, gift wrap changes the trust model. You do not have to trust a BitcoinLink database to remember the pending link. You do have to trust the code that creates and decrypts the event, the browser environment that handles the NWC string and claim key, and the relay path that stores the encrypted event until it is claimed.

How a claim actually pays

On the receiver side, the claim page decodes the slug, computes the receiver public key from the private key in the URL and checks whether a NIP-09 deletion event already references the gift-wrap event. If the link appears unclaimed, the page fetches the kind 1059 event by ID, decrypts it with the receiver key and reads the NWC URL and amount from the decrypted payload.

The receiver can enter a BOLT11 invoice, an LNURL pay endpoint or a Lightning Address. For Lightning Address input, the app resolves the well-known lnurlp endpoint, checks the payRequest response, sends the amount in millisatoshis to the callback and receives an invoice. For LNURL input, it follows the pay request flow. For BOLT11 input, it validates that the invoice shape is acceptable before trying to pay.

Once the invoice is ready, BitcoinLink creates an NWC client from the encrypted payload's NWC URL, initializes the connection, calls pay_invoice and expects a preimage. The app disconnects afterward in a finally path. That payment is the moment the sender's wallet budget becomes real money movement. Everything before that is setup, storage and validation.

Deletion events are useful, not magic

After a successful payment, BitcoinLink publishes a NIP-09 deletion event from the receiver key and tags the original gift-wrap event ID. The claim page treats that deletion event as the claimed marker. On later visits, the page can find the marker and show that the link has already been claimed.

That marker is useful because it uses the same Nostr storage layer as the pending link. It also has limits. A deletion request on Nostr is not an atomic database lock. Relays can miss it, reject it, prune it or disagree about whether it exists. The code also treats deletion publication failure after a successful payment as non-fatal, because the payment already happened. That is the right user experience after money moves, but it means the claimed marker is not the same thing as the payment itself.

The safest way to use BitcoinLink is to make the wallet budget match the links you intended to create. If the sender creates ten links of 100 sats each, the NWC budget should not quietly allow far more than 1,000 sats. A deletion marker helps the interface. A tight NWC budget limits damage if a relay view, browser state or claim retry behaves badly.

Alby and Mutiny take different paths

The Alby path is the most straightforward for many readers. BitcoinLink asks Alby to create a scoped NWC relationship and then generates encrypted links from the resulting connection string. Alby is doing the wallet-service work; BitcoinLink is the link generator and claim interface. The sender should still inspect the wallet-side permission, amount and expiration before creating links.

The Mutiny path is more protocol-shaped. BitcoinLink constructs a Nostr Wallet Auth URI with requested commands, budget and relay details, opens that flow and listens for a response event. That response becomes the NWC relationship used by the generated links. The code makes Mutiny support feel native without making the whole app custodial.

Both paths illustrate the same larger idea. NWC lets a web app ask a wallet to perform a narrow payment job without holding the funds. That can be powerful for vouchers, rewards, giveaways, refunds, onboarding links and small social payments. It also means the wallet provider's reliability, permissions, security prompts and revocation controls are part of the product.

Lightning Address, LNURL and BOLT11 receiving

BitcoinLink is friendly to receivers because it does not require them to understand NWC. The receiver can paste a Lightning Address, an LNURL pay value or a BOLT11 invoice. The app then turns that input into the invoice the sender's wallet has to pay. That separation is important. The sender uses NWC to authorize payment, while the receiver uses the Lightning address or invoice format they already have.

Lightning Address support follows the familiar user@domain pattern. The app fetches the LNURL pay metadata from the domain, checks the amount against minSendable and maxSendable and calls the callback with the link amount in millisatoshis. For wallets and services that expose Lightning Address well, this makes a claim feel almost like entering an email address.

The receiver still has responsibility. A wrong Lightning Address sends money to the wrong destination. A malicious LNURL endpoint can return unexpected metadata or fail at the callback. A BOLT11 invoice can expire. BitcoinLink can validate formats and handle errors, but it cannot prove that the receiver intended every destination they paste.

Where the amount is trusted

The claim URL includes an amount field, but the decrypted gift-wrap payload is the stronger source. The tests cover cases where the URL amount is tampered with and the decrypted payload preserves the real amount. That is a useful detail. The link can show an initial amount quickly, but the payment logic should rely on what was encrypted when the link was created.

Amount handling is also where budgets and invoices meet. The sender chooses a sats amount per link. The wallet connection is requested with a total budget. The receiver's Lightning Address or LNURL endpoint must accept the amount in millisatoshis. The NWC wallet must then pay an invoice for that amount. Several systems have to agree before a link settles.

If a claim fails, the reason may be outside BitcoinLink. The wallet budget may be insufficient. The Lightning Address may have min or max limits. The invoice may be invalid. The wallet service may be offline. A relay may not return the gift wrap. The practical debugging path is to check the link event, the receiver destination and the sender wallet permission separately.

The security model in plain language

BitcoinLink's security model is easiest to state plainly. The sender should assume the NWC URL can spend within its allowed permission and budget. The receiver should assume the claim URL is a secret. Relays should be treated as public storage for encrypted events and claimed markers, not as trusted payment servers. The browser should be treated as the place where sensitive material is briefly assembled.

That model is reasonable for small links, demos, rewards and social payments. It is not the same as a regulated voucher system, a bank transfer, a withdrawal queue or an escrow contract. BitcoinLink does not make a third party guarantee a claim. It gives the sender and receiver a Nostr-native way to coordinate a limited wallet payment.

The biggest practical risks are over-permissioned NWC connections, leaked claim URLs, stale relay state and user confusion after partial success. A good first test is tiny: create one link for a few sats, claim it to your own Lightning Address, reload the claim page, verify the claimed state, inspect the source wallet history and revoke the wallet connection.

What the tests say about edge cases

The repository has a strong test surface for a small app. The test files cover gift-wrap creation, link generation, claim flow, NWC payment calls, BOLT11 helpers and many failure paths. The tests check wrong keys, truncated keys, special characters, long NWC URLs, amount boundaries, tampered URL data, relay configuration, concurrent link creation and multiple links using the same NWC URL.

The NWC payment tests mock the wallet client and check success with a preimage, disconnect behavior, missing preimage errors, initialization failure, insufficient budget, payment timeout and disconnect errors. That is exactly where a payment-link app should be defensive. A pretty link generator is easy. A link generator that admits wallet and relay failures is more useful.

Tests are not the same as a security audit, but they tell you what the maintainer knows can go wrong. BitcoinLink's tests show awareness of the right categories: encryption, secret leakage, amount tampering, concurrency, wallet failure and relay configuration. If you plan to use it beyond casual amounts, read those tests before trusting the interface.

What to verify before using it

Start with the official site and repository. The live app is at bitcoinlink.app and the source is in Austin Kelsay's GitHub repository. Check that the app you are using points to the expected domain, then read the README and the source paths for link generation, gift wrap, claim handling and NWC payments. A payment-link app should not be evaluated from screenshots alone.

Then check the wallet connection. Which wallet created it? Which commands are allowed? What is the budget? Can you revoke it? Does the wallet show pending permissions clearly? If the NWC connection can pay more than the links require, shrink it before creating links. If the wallet does not show you what was authorized, use a different wallet path for testing.

Finally, decide the right use case. BitcoinLink is well suited for small rewards, conference handouts, private gifts, onboarding experiments and Nostr-native payment demos. It is less suited for large transfers, public giveaways with no abuse limits or situations where the receiver must have formal redemption guarantees. The product is clever because it keeps custody out of the app. That same design asks the sender and receiver to handle links, wallet permissions and relay assumptions carefully.

Sources worth opening

Open the live app, the repository, the README, the claim flow, gift-wrap code, NWC client, tests and the Nostr and LNURL specifications together. BitcoinLink is easiest to understand when the pleasant link surface is read beside the exact event and wallet calls.

Back to the Crays Nostr page
Apps route visual cue 1
Apps route visual cue 2
Apps route visual cue 3
Apps route visual cue 4
Apps route visual cue 5

How to use this page

Find the product surface first.

Search clients, signers, product categories or developer tools when you need a specific app, source file or comparison clue.

AppsThe full Apps route stays open520 pages in this routeProducts, categories, builder notes and signer context.Browse pages
Apps route visual cue 1
Apps route visual cue 2
Apps route visual cue 3
Apps route visual cue 4
Apps route visual cue 5

Bring something back

Ask, suggest, submit or nominate.

Ask a question, send a source, suggest a fix, submit a project or nominate a public Nostr account. The page stays stable; your contribution gets reviewed beside it.