Skip to content
2 changes: 1 addition & 1 deletion e2e/nwc-faucet.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ describe("NWC faucet integration", () => {
test(
"creates wallet via faucet and balance is 10_000 sats",
async () => {
const { nwcUrl } = await createTestWallet(EXPECTED_BALANCE_SATS, 3);
const { nwcUrl } = await createTestWallet(EXPECTED_BALANCE_SATS);

const nwc = new NWCClient({ nostrWalletConnectUrl: nwcUrl });
try {
Expand Down
59 changes: 59 additions & 0 deletions e2e/nwc-list-transactions-after-payment.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { NWCClient } from "../src/nwc/NWCClient";
import { createTestWallet } from "./helpers";

/**
* E2E test for list_transactions after a successful invoice payment.
* Requires network access.
*/
describe("NWC list_transactions after pay_invoice", () => {
const AMOUNT_MSATS = 100_000; // 100 sats
const BALANCE_SATS = 10_000;

let sender: { nwcUrl: string };
let receiver: { nwcUrl: string };

beforeAll(async () => {
receiver = await createTestWallet(BALANCE_SATS);
sender = await createTestWallet(BALANCE_SATS);
}, 60_000);

test(
"returns an outgoing settled transaction for the paid invoice",
async () => {
const receiverClient = new NWCClient({
nostrWalletConnectUrl: receiver.nwcUrl,
});
const senderClient = new NWCClient({ nostrWalletConnectUrl: sender.nwcUrl });

try {
const invoiceResult = await receiverClient.makeInvoice({
amount: AMOUNT_MSATS,
description: "E2E list_transactions after payment",
});
expect(invoiceResult.invoice).toBeDefined();

await senderClient.payInvoice({ invoice: invoiceResult.invoice });

const listResult = await senderClient.listTransactions({
limit: 20,
type: "outgoing",
});

expect(Array.isArray(listResult.transactions)).toBe(true);

const matchingTx = listResult.transactions.find(
(tx) => tx.invoice === invoiceResult.invoice,
);

expect(matchingTx).toBeDefined();
expect(matchingTx?.type).toBe("outgoing");
expect(matchingTx?.state).toBe("settled");
expect(matchingTx?.amount).toBe(AMOUNT_MSATS);
} finally {
receiverClient.close();
senderClient.close();
}
},
60_000,
);
});
47 changes: 47 additions & 0 deletions e2e/nwc-lookup-invoice.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { NWCClient } from "../src/nwc/NWCClient";
import { createTestWallet } from "./helpers";

/**
* E2E test for lookup_invoice using the NWC faucet.
* Requires network access.
*/
describe("NWC lookup_invoice", () => {
const AMOUNT_MSATS = 100_000; // 100 sats
const BALANCE_SATS = 10_000;

let sender: { nwcUrl: string };
let receiver: { nwcUrl: string };

beforeAll(async () => {
receiver = await createTestWallet(BALANCE_SATS);
sender = await createTestWallet(BALANCE_SATS);
}, 60_000);

test(
"finds paid invoice by invoice string",
async () => {
const receiverClient = new NWCClient({ nostrWalletConnectUrl: receiver.nwcUrl });
const senderClient = new NWCClient({ nostrWalletConnectUrl: sender.nwcUrl });

try {
const invoiceResult = await receiverClient.makeInvoice({
amount: AMOUNT_MSATS,
description: "E2E lookup test",
});
expect(invoiceResult.invoice).toBeDefined();

await senderClient.payInvoice({ invoice: invoiceResult.invoice });

const lookupResult = await receiverClient.lookupInvoice({
invoice: invoiceResult.invoice,
});
expect(lookupResult.payment_hash).toBeDefined();
expect(lookupResult.invoice).toBe(invoiceResult.invoice);
} finally {
receiverClient.close();
senderClient.close();
}
},
60_000,
);
});
50 changes: 50 additions & 0 deletions e2e/nwc-pay-invoice-insufficient-funds.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { NWCClient } from "../src/nwc/NWCClient";
import { Nip47WalletError } from "../src/nwc/types";
import { createTestWallet } from "./helpers";

/**
* E2E negative test for pay_invoice using the NWC faucet.
* Requires network access.
*/
describe("NWC pay_invoice insufficient funds", () => {
const INVOICE_AMOUNT_MSATS = 1_000_000; // 1_000 sats
const RECEIVER_BALANCE_SATS = 10_000;
const SENDER_BALANCE_SATS = 50;

let sender: { nwcUrl: string };
let receiver: { nwcUrl: string };

beforeAll(async () => {
receiver = await createTestWallet(RECEIVER_BALANCE_SATS);
sender = await createTestWallet(SENDER_BALANCE_SATS);
}, 60_000);

test(
"fails with wallet error when invoice amount exceeds sender balance",
async () => {
const receiverClient = new NWCClient({
nostrWalletConnectUrl: receiver.nwcUrl,
});
const senderClient = new NWCClient({ nostrWalletConnectUrl: sender.nwcUrl });

try {
const invoiceResult = await receiverClient.makeInvoice({
amount: INVOICE_AMOUNT_MSATS,
description: "E2E insufficient funds test",
});

const payInvoicePromise = senderClient.payInvoice({
invoice: invoiceResult.invoice,
});
await expect(payInvoicePromise).rejects.toBeInstanceOf(Nip47WalletError);
await expect(payInvoicePromise).rejects.toMatchObject({
code: "INSUFFICIENT_BALANCE",
});
} finally {
receiverClient.close();
senderClient.close();
}
},
60_000,
);
});
46 changes: 46 additions & 0 deletions e2e/nwc-pay-invoice.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { NWCClient } from "../src/nwc/NWCClient";
import { createTestWallet } from "./helpers";

/**
* E2E test for make_invoice and pay_invoice using the NWC faucet.
* Requires network access.
*/
describe("NWC make_invoice and pay_invoice", () => {
const AMOUNT_MSATS = 100_000; // 100 sats
const BALANCE_SATS = 10_000;

let sender: { nwcUrl: string };
let receiver: { nwcUrl: string };

beforeAll(async () => {
receiver = await createTestWallet(BALANCE_SATS);
sender = await createTestWallet(BALANCE_SATS);
}, 60_000);

test(
"receiver creates invoice, sender pays it",
async () => {
const receiverClient = new NWCClient({ nostrWalletConnectUrl: receiver.nwcUrl });
const senderClient = new NWCClient({ nostrWalletConnectUrl: sender.nwcUrl });

try {
const invoiceResult = await receiverClient.makeInvoice({
amount: AMOUNT_MSATS,
description: "E2E test invoice",
});
expect(invoiceResult.invoice).toBeDefined();
expect(invoiceResult.invoice).toMatch(/^ln/);

const payResult = await senderClient.payInvoice({
invoice: invoiceResult.invoice,
});
expect(payResult.preimage).toBeDefined();
expect(typeof payResult.preimage).toBe("string");
} finally {
receiverClient.close();
senderClient.close();
}
},
60_000,
);
});
43 changes: 43 additions & 0 deletions e2e/nwc-pay-keysend.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { NWCClient } from "../src/nwc/NWCClient";
import { createTestWallet } from "./helpers";

/**
* E2E test for pay_keysend using the NWC faucet.
* Requires network access.
*/
describe("NWC pay_keysend", () => {
const AMOUNT_MSATS = 100_000; // 100 sats
const BALANCE_SATS = 10_000;

let sender: { nwcUrl: string };
let receiver: { nwcUrl: string };

beforeAll(async () => {
receiver = await createTestWallet(BALANCE_SATS);
sender = await createTestWallet(BALANCE_SATS);
}, 60_000);

test(
"sends keysend payment to receiver pubkey",
async () => {
const receiverClient = new NWCClient({ nostrWalletConnectUrl: receiver.nwcUrl });
const senderClient = new NWCClient({ nostrWalletConnectUrl: sender.nwcUrl });

try {
const receiverInfoResult = await receiverClient.getInfo();
expect(receiverInfoResult.pubkey).toBeDefined();

const keysendResult = await senderClient.payKeysend({
amount: AMOUNT_MSATS,
pubkey: receiverInfoResult.pubkey,
});
expect(keysendResult.preimage).toBeDefined();
expect(typeof keysendResult.preimage).toBe("string");
} finally {
receiverClient.close();
senderClient.close();
}
},
60_000,
);
});
1 change: 1 addition & 0 deletions jest.e2e.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ export default {
testEnvironment: 'node',
testMatch: ['<rootDir>/e2e/**/*.test.ts'],
testPathIgnorePatterns: ['/node_modules/', '/e2e/browser'],
maxWorkers: 1, // Run e2e tests serially to avoid faucet rate limiting
};
Loading