diff --git a/lamassu-next/packages/cashu/src/__tests__/index.test.ts b/lamassu-next/packages/cashu/src/__tests__/index.test.ts new file mode 100644 index 0000000..6b40426 --- /dev/null +++ b/lamassu-next/packages/cashu/src/__tests__/index.test.ts @@ -0,0 +1,17 @@ +import { describe, it, expect } from 'vitest' +import { version } from '../index.js' + +describe('@lamassu/cashu', () => { + describe('exports', () => { + it('should export version', () => { + expect(version).toBe('0.1.0') + }) + }) + + // TODO: Add tests when cashu functionality is implemented + describe('placeholder', () => { + it('should pass placeholder test', () => { + expect(true).toBe(true) + }) + }) +}) diff --git a/lamassu-next/packages/clink/src/__tests__/noffer.test.ts b/lamassu-next/packages/clink/src/__tests__/noffer.test.ts index 996320e..a755e9d 100644 --- a/lamassu-next/packages/clink/src/__tests__/noffer.test.ts +++ b/lamassu-next/packages/clink/src/__tests__/noffer.test.ts @@ -22,7 +22,7 @@ describe('noffer encoding/decoding', () => { const offer: CLINKOffer = { ...sampleOffer, priceType: 'fixed', - amountMsat: 1000000, + amountSats: 1000, } const noffer = encodeNoffer(offer) @@ -45,14 +45,14 @@ describe('noffer encoding/decoding', () => { const offer: CLINKOffer = { ...sampleOffer, priceType: 'fixed', - amountMsat: 50000, + amountSats: 50000, } const noffer = encodeNoffer(offer) const decoded = decodeNoffer(noffer) expect(decoded.priceType).toBe('fixed') - expect(decoded.amountMsat).toBe(50000) + expect(decoded.amountSats).toBe(50000) }) it('should throw on invalid prefix', () => { diff --git a/lamassu-next/packages/clink/src/noffer.ts b/lamassu-next/packages/clink/src/noffer.ts index 7ce42e1..886b2fc 100644 --- a/lamassu-next/packages/clink/src/noffer.ts +++ b/lamassu-next/packages/clink/src/noffer.ts @@ -177,9 +177,12 @@ function decodePriceType(byte: number): PriceType { } function encodeUint64BE(value: number): number[] { - const bytes: number[] = [] - for (let i = 7; i >= 0; i--) { - bytes.push((value >> (i * 8)) & 0xff) + // Use division instead of bit shifts because JS bitwise ops only work on 32-bit ints + const bytes: number[] = new Array(8).fill(0) + let remaining = value + for (let i = 7; i >= 0 && remaining > 0; i--) { + bytes[i] = remaining % 256 + remaining = Math.floor(remaining / 256) } return bytes } diff --git a/lamassu-next/packages/lightning/src/__tests__/client.test.ts b/lamassu-next/packages/lightning/src/__tests__/client.test.ts index 764c79b..15c51af 100644 --- a/lamassu-next/packages/lightning/src/__tests__/client.test.ts +++ b/lamassu-next/packages/lightning/src/__tests__/client.test.ts @@ -1,9 +1,8 @@ -import { describe, it, expect, vi } from 'vitest' +import { describe, it, expect } from 'vitest' import { LightningPubClient } from '../client.js' describe('LightningPubClient', () => { const config = { - serviceUrl: 'https://lightning.pub', accountPubkey: 'a'.repeat(64), relays: ['wss://relay.example.com'], } @@ -13,6 +12,15 @@ describe('LightningPubClient', () => { const client = new LightningPubClient(config) expect(client).toBeDefined() }) + + it('should accept optional timeout and appId', () => { + const client = new LightningPubClient({ + ...config, + timeout: 60000, + appId: 'test-app', + }) + expect(client).toBeDefined() + }) }) describe('getExchangeRate', () => { @@ -33,26 +41,47 @@ describe('LightningPubClient', () => { expect(usdRate.satsPerUnit).not.toBe(eurRate.satsPerUnit) }) + + it('should return default rate for unknown currency', async () => { + const client = new LightningPubClient(config) + const rate = await client.getExchangeRate('XYZ') + + expect(rate.currency).toBe('XYZ') + expect(rate.satsPerUnit).toBe(2500) // default rate + }) }) describe('decodeInvoice', () => { - it('should decode a basic invoice', () => { + it('should decode invoice with micro-BTC amount', () => { const client = new LightningPubClient(config) - - // This is a simplified test since we have basic parsing const result = client.decodeInvoice('lnbc100u1...') expect(result).toBeDefined() + expect(result.amountSats).toBe(10000) // 100 micro-BTC = 10000 sats expect(result.expiresAt).toBeGreaterThan(Date.now() / 1000) }) + + it('should decode invoice with milli-BTC amount', () => { + const client = new LightningPubClient(config) + const result = client.decodeInvoice('lnbc1m1...') + + expect(result.amountSats).toBe(100000) // 1 milli-BTC = 100000 sats + }) + + it('should return null amount for invoice without amount', () => { + const client = new LightningPubClient(config) + const result = client.decodeInvoice('lnbcrt1...') + + expect(result.amountSats).toBeNull() + }) }) describe('initialize', () => { - it('should require nostrClient and identity', () => { + it('should require nostrClient and identity', async () => { const client = new LightningPubClient(config) // Without initialization, operations should fail - expect(client.getBalance()).rejects.toThrow('Client not initialized') + await expect(client.getBalance()).rejects.toThrow('Client not initialized') }) }) diff --git a/lamassu-next/packages/ui-shared/src/__tests__/index.test.ts b/lamassu-next/packages/ui-shared/src/__tests__/index.test.ts new file mode 100644 index 0000000..68abb49 --- /dev/null +++ b/lamassu-next/packages/ui-shared/src/__tests__/index.test.ts @@ -0,0 +1,17 @@ +import { describe, it, expect } from 'vitest' +import { version } from '../index.js' + +describe('@lamassu/ui-shared', () => { + describe('exports', () => { + it('should export version', () => { + expect(version).toBe('0.1.0') + }) + }) + + // TODO: Add tests when Vue components are implemented + describe('placeholder', () => { + it('should pass placeholder test', () => { + expect(true).toBe(true) + }) + }) +})