UNPKG

@bsv/message-box-client

Version:

A client for P2P messaging and payments

213 lines 9.85 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); /* eslint-env jest */ const PeerPayClient_js_1 = require("../PeerPayClient.js"); const sdk_1 = require("@bsv/sdk"); const globals_1 = require("@jest/globals"); const toArray = (msg, enc) => { if (Array.isArray(msg)) return msg.slice(); if (msg === undefined) return []; if (typeof msg !== 'string') { return Array.from(msg, (item) => item | 0); } switch (enc) { case 'hex': { const matches = msg.match(/.{1,2}/g); return matches != null ? matches.map(byte => parseInt(byte, 16)) : []; } case 'base64': return Array.from(Buffer.from(msg, 'base64')); default: return Array.from(Buffer.from(msg, 'utf8')); } }; // Mock dependencies globals_1.jest.mock('@bsv/sdk', () => { // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion const actualSDK = globals_1.jest.requireActual('@bsv/sdk'); return { ...actualSDK, WalletClient: globals_1.jest.fn().mockImplementation(() => ({ getPublicKey: globals_1.jest.fn(), createAction: globals_1.jest.fn(), internalizeAction: globals_1.jest.fn(), createHmac: globals_1.jest.fn().mockResolvedValue({ hmac: [1, 2, 3, 4, 5] }) })) }; }); describe('PeerPayClient Unit Tests', () => { let peerPayClient; let mockWalletClient; beforeEach(() => { globals_1.jest.clearAllMocks(); mockWalletClient = new sdk_1.WalletClient(); // Ensure a valid compressed public key (33 bytes, hex format) mockWalletClient.getPublicKey.mockResolvedValue({ publicKey: sdk_1.PrivateKey.fromRandom().toPublicKey().toString() }); mockWalletClient.createAction.mockResolvedValue({ tx: toArray('mockedTransaction', 'utf8') }); peerPayClient = new PeerPayClient_js_1.PeerPayClient({ messageBoxHost: 'https://messagebox.babbage.systems', walletClient: mockWalletClient }); }); describe('createPaymentToken', () => { it('should create a valid payment token', async () => { mockWalletClient.getPublicKey.mockResolvedValue({ publicKey: sdk_1.PrivateKey.fromRandom().toPublicKey().toString() }); mockWalletClient.createAction.mockResolvedValue({ tx: toArray('mockedTransaction', 'utf8') }); const payment = { recipient: sdk_1.PrivateKey.fromRandom().toPublicKey().toString(), amount: 5 }; const token = await peerPayClient.createPaymentToken(payment); expect(token).toHaveProperty('amount', 5); expect(mockWalletClient.getPublicKey).toHaveBeenCalledWith(expect.any(Object)); expect(mockWalletClient.createAction).toHaveBeenCalledWith(expect.any(Object)); }); it('should throw an error if recipient public key cannot be derived', async () => { mockWalletClient.getPublicKey.mockResolvedValue({ publicKey: '' }); // Empty key await expect(peerPayClient.createPaymentToken({ recipient: 'invalid', amount: 5 })) .rejects.toThrow('Failed to derive recipient’s public key'); }); it('should throw an error if amount is <= 0', async () => { mockWalletClient.getPublicKey .mockResolvedValue({ publicKey: sdk_1.PrivateKey.fromRandom().toPublicKey().toString() }); await expect(peerPayClient.createPaymentToken({ recipient: sdk_1.PrivateKey.fromRandom().toPublicKey().toString(), amount: 0 })) .rejects.toThrow('Invalid payment details: recipient and valid amount are required'); }); }); // Test: sendPayment describe('sendPayment', () => { it('should call sendMessage with valid payment', async () => { const sendMessageSpy = globals_1.jest.spyOn(peerPayClient, 'sendMessage').mockResolvedValue({ status: 'success', messageId: 'mockedMessageId' }); const payment = { recipient: 'recipientKey', amount: 3 }; console.log('[TEST] Calling sendPayment...'); await peerPayClient.sendPayment(payment); console.log('[TEST] sendPayment finished.'); expect(sendMessageSpy).toHaveBeenCalledWith({ recipient: 'recipientKey', messageBox: 'payment_inbox', body: expect.any(String) }); }, 10000); }); // Test: sendLivePayment describe('sendLivePayment', () => { it('should call createPaymentToken and sendLiveMessage with correct parameters', async () => { globals_1.jest.spyOn(peerPayClient, 'createPaymentToken').mockResolvedValue({ customInstructions: { derivationPrefix: 'prefix', derivationSuffix: 'suffix' }, transaction: Array.from(new Uint8Array([1, 2, 3, 4, 5])), amount: 2 }); globals_1.jest.spyOn(peerPayClient, 'sendLiveMessage').mockResolvedValue({ status: 'success', messageId: 'mockedMessageId' }); const payment = { recipient: 'recipientKey', amount: 2 }; await peerPayClient.sendLivePayment(payment); expect(peerPayClient.createPaymentToken).toHaveBeenCalledWith(payment); expect(peerPayClient.sendLiveMessage).toHaveBeenCalledWith({ recipient: 'recipientKey', messageBox: 'payment_inbox', body: "{\"customInstructions\":{\"derivationPrefix\":\"prefix\",\"derivationSuffix\":\"suffix\"},\"transaction\":[1,2,3,4,5],\"amount\":2}" }); }); }); // Test: acceptPayment describe('acceptPayment', () => { it('should call internalizeAction and acknowledgeMessage', async () => { mockWalletClient.internalizeAction.mockResolvedValue({ accepted: true }); globals_1.jest.spyOn(peerPayClient, 'acknowledgeMessage').mockResolvedValue('acknowledged'); const payment = { messageId: '123', sender: 'senderKey', token: { customInstructions: { derivationPrefix: 'prefix', derivationSuffix: 'suffix' }, transaction: toArray('mockedTransaction', 'utf8'), amount: 6 } }; await peerPayClient.acceptPayment(payment); expect(mockWalletClient.internalizeAction).toHaveBeenCalled(); expect(peerPayClient.acknowledgeMessage).toHaveBeenCalledWith({ messageIds: ['123'] }); }); }); // Test: rejectPayment describe('rejectPayment', () => { it('should refund payment minus fee', async () => { globals_1.jest.spyOn(peerPayClient, 'acceptPayment').mockResolvedValue(undefined); globals_1.jest.spyOn(peerPayClient, 'sendPayment').mockResolvedValue(undefined); globals_1.jest.spyOn(peerPayClient, 'acknowledgeMessage').mockResolvedValue('acknowledged'); const payment = { messageId: '123', sender: 'senderKey', token: { customInstructions: { derivationPrefix: 'prefix', derivationSuffix: 'suffix' }, transaction: toArray('mockedTransaction', 'utf8'), amount: 2000 } }; await peerPayClient.rejectPayment(payment); expect(peerPayClient.acceptPayment).toHaveBeenCalledWith(payment); expect(peerPayClient.sendPayment).toHaveBeenCalledWith({ recipient: 'senderKey', amount: 1000 // Deduct satoshi fee }); expect(peerPayClient.acknowledgeMessage).toHaveBeenCalledWith({ messageIds: ['123'] }); }); }); // Test: listIncomingPayments describe('listIncomingPayments', () => { it('should return parsed payment messages', async () => { globals_1.jest.spyOn(peerPayClient, 'listMessages').mockResolvedValue([ { messageId: '1', sender: 'sender1', created_at: '2025-03-05T12:00:00Z', updated_at: '2025-03-05T12:05:00Z', body: JSON.stringify({ customInstructions: { derivationPrefix: 'prefix1', derivationSuffix: 'suffix1' }, transaction: toArray('mockedTransaction1', 'utf8'), amount: 3 }) }, { messageId: '2', sender: 'sender2', created_at: '2025-03-05T12:10:00Z', updated_at: '2025-03-05T12:15:00Z', body: JSON.stringify({ customInstructions: { derivationPrefix: 'prefix2', derivationSuffix: 'suffix2' }, transaction: toArray('mockedTransaction2', 'utf8'), amount: 9 }) } ]); const payments = await peerPayClient.listIncomingPayments(); expect(payments).toHaveLength(2); expect(payments[0]).toHaveProperty('sender', 'sender1'); expect(payments[0].token.amount).toBe(3); expect(payments[1]).toHaveProperty('sender', 'sender2'); expect(payments[1].token.amount).toBe(9); }); }); }); //# sourceMappingURL=PeerPayClientUnit.test.js.map