Receive a Lightning payment

2 min read
Guides
Web SDK

Create a Lightning invoice

receive() from useWalletReceive() triggers a receive swap: the Ark server sets up a Lightning payment path that deposits into your VTXO once the payer settles. Pass amountSat and an optional memo for the invoice.

The returned ReceiveResult.invoice is a standard BOLT11 string that any compatible wallet can pay. Display it as a QR code alongside the raw string so the payer has both options.

receive.tsx
import { useState } from 'react';
import { useWalletReceive } from '@lightninglabs/wavelength-react';
function CreateInvoice() {
const { receive, receivePending } = useWalletReceive();
const [invoice, setInvoice] = useState<string | null>(null);
const generate = async () => {
const result = await receive({
amountSat: 10_000,
memo: 'Coffee',
});
setInvoice(result.invoice);
};
return (
<div>
<button onClick={generate} disabled={receivePending}>
Generate invoice
</button>
{invoice && <pre>{invoice}</pre>}
</div>
);
}

Wait for settlement

useWalletActivity() returns the live activity array and streams updates in place. Match the entry by invoice string in entry.request?.lightningInvoice and watch its status field: the entry appears as 'pending' as soon as the invoice is created, stays 'pending' through payment and settlement, and switches to 'complete' once the receive swap round completes. Like any entry, a receive swap can also terminate as 'failed', so handle that branch too.

Because status alone cannot distinguish “nobody has paid yet” from “payment in flight”, keep the pending copy neutral, or read entry.progress?.phase when you want that distinction (see the note below the sample).

receive.tsx
import { useWalletActivity } from '@lightninglabs/wavelength-react';
function InvoiceStatus({ bolt11 }: { bolt11: string }) {
const activity = useWalletActivity();
const payment = activity.find(
entry =>
entry.kind === 'receive' &&
entry.request?.lightningInvoice === bolt11,
);
if (!payment) return <p>Preparing invoice...</p>;
if (payment.status === 'pending') return <p>Waiting for payment...</p>;
if (payment.status === 'failed') {
return <p>Payment failed: {payment.failureReason}</p>;
}
return <p>Settled: +{payment.amountSat} sats</p>;
}

For finer-grained progress than the top-level status field offers (for example, distinguishing “waiting for payment” from “settling” while a receive swap is still 'pending'), see entry.progress?.phase in Handle phases and errors. This guide sticks to the simpler status field for clarity.