Squash merge remove-dangling-bits into market-implementation-squashed

This commit is contained in:
padreug 2025-09-04 22:26:38 +02:00
parent 4bc15cfa2f
commit 2f0024478d
17 changed files with 569 additions and 859 deletions

View file

@ -1,18 +0,0 @@
// Helper function to convert bech32 to hex
export function bech32ToHex(bech32Key: string): string {
if (bech32Key.startsWith('npub1') || bech32Key.startsWith('nsec1')) {
// Import bech32 conversion dynamically to avoid bundling issues
const { bech32Decode, convertbits } = require('bech32')
const [, data] = bech32Decode(bech32Key)
if (!data) {
throw new Error(`Invalid bech32 key: ${bech32Key}`)
}
const converted = convertbits(data, 5, 8, false)
if (!converted) {
throw new Error(`Failed to convert bech32 key: ${bech32Key}`)
}
return Buffer.from(converted).toString('hex')
}
// Already hex format
return bech32Key
}

View file

@ -82,7 +82,7 @@ class InvoiceService {
amount: order.total,
unit: 'sat',
memo: `Order ${order.id} - ${order.items.length} items`,
expiry: 3600, // 1 hour
expiry: extra?.expiry || 3600, // Allow configurable expiry, default 1 hour
extra: {
tag: 'nostrmarket', // Use nostrmarket tag for compatibility
order_id: extra?.order_id || order.id, // Use passed order_id or fallback to order.id
@ -113,6 +113,8 @@ class InvoiceService {
console.log('Full LNBits response:', response)
console.log('Response type:', typeof response)
console.log('Response keys:', Object.keys(response))
console.log('Response expiry field:', response.expiry)
console.log('Response created_at field:', response.created_at)
// Check if we have the expected fields
if (!response.bolt11) {

View file

@ -2,7 +2,6 @@ import { finalizeEvent, type EventTemplate, nip04 } from 'nostr-tools'
import { relayHub } from '@/lib/nostr/relayHub'
import { auth } from '@/composables/useAuth'
import type { Stall, Product, Order } from '@/stores/market'
import { bech32ToHex } from '@/lib/utils/bech32'
export interface NostrmarketStall {
id: string
@ -69,24 +68,49 @@ export interface NostrmarketOrderStatus {
}
export class NostrmarketService {
/**
* Convert hex string to Uint8Array (browser-compatible)
*/
private hexToUint8Array(hex: string): Uint8Array {
const bytes = new Uint8Array(hex.length / 2)
for (let i = 0; i < hex.length; i += 2) {
bytes[i / 2] = parseInt(hex.substr(i, 2), 16)
}
return bytes
}
private getAuth() {
if (!auth.isAuthenticated.value || !auth.currentUser.value?.prvkey) {
throw new Error('User not authenticated or private key not available')
}
// Convert bech32 keys to hex format if needed
const originalPubkey = auth.currentUser.value.pubkey
const originalPrvkey = auth.currentUser.value.prvkey
const pubkey = bech32ToHex(originalPubkey)
const prvkey = bech32ToHex(originalPrvkey)
const pubkey = auth.currentUser.value.pubkey
const prvkey = auth.currentUser.value.prvkey
console.log('🔑 Key conversion debug:', {
originalPubkey: originalPubkey?.substring(0, 10) + '...',
originalPrvkey: originalPrvkey?.substring(0, 10) + '...',
convertedPubkey: pubkey.substring(0, 10) + '...',
convertedPrvkey: prvkey.substring(0, 10) + '...',
if (!pubkey || !prvkey) {
throw new Error('Public key or private key is missing')
}
// Validate that we have proper hex strings
if (!/^[0-9a-fA-F]{64}$/.test(pubkey)) {
throw new Error(`Invalid public key format: ${pubkey.substring(0, 10)}...`)
}
if (!/^[0-9a-fA-F]{64}$/.test(prvkey)) {
throw new Error(`Invalid private key format: ${prvkey.substring(0, 10)}...`)
}
console.log('🔑 Key debug:', {
pubkey: pubkey.substring(0, 10) + '...',
prvkey: prvkey.substring(0, 10) + '...',
pubkeyIsHex: /^[0-9a-fA-F]{64}$/.test(pubkey),
prvkeyIsHex: /^[0-9a-fA-F]{64}$/.test(prvkey)
prvkeyIsHex: /^[0-9a-fA-F]{64}$/.test(prvkey),
pubkeyLength: pubkey.length,
prvkeyLength: prvkey.length,
pubkeyType: typeof pubkey,
prvkeyType: typeof prvkey,
pubkeyIsString: typeof pubkey === 'string',
prvkeyIsString: typeof prvkey === 'string'
})
return {
@ -99,7 +123,7 @@ export class NostrmarketService {
* Publish a stall event (kind 30017) to Nostr
*/
async publishStall(stall: Stall): Promise<string> {
const { pubkey, prvkey } = this.getAuth()
const { prvkey } = this.getAuth()
const stallData: NostrmarketStall = {
id: stall.id,
@ -124,23 +148,24 @@ export class NostrmarketService {
created_at: Math.floor(Date.now() / 1000)
}
const event = finalizeEvent(eventTemplate, prvkey)
const eventId = await relayHub.publishEvent(event)
const prvkeyBytes = this.hexToUint8Array(prvkey)
const event = finalizeEvent(eventTemplate, prvkeyBytes)
const result = await relayHub.publishEvent(event)
console.log('Stall published to nostrmarket:', {
stallId: stall.id,
eventId: eventId,
eventId: result,
content: stallData
})
return eventId
return result.success.toString()
}
/**
* Publish a product event (kind 30018) to Nostr
*/
async publishProduct(product: Product): Promise<string> {
const { pubkey, prvkey } = this.getAuth()
const { prvkey } = this.getAuth()
const productData: NostrmarketProduct = {
id: product.id,
@ -166,23 +191,24 @@ export class NostrmarketService {
created_at: Math.floor(Date.now() / 1000)
}
const event = finalizeEvent(eventTemplate, prvkey)
const eventId = await relayHub.publishEvent(event)
const prvkeyBytes = this.hexToUint8Array(prvkey)
const event = finalizeEvent(eventTemplate, prvkeyBytes)
const result = await relayHub.publishEvent(event)
console.log('Product published to nostrmarket:', {
productId: product.id,
eventId: eventId,
eventId: result,
content: productData
})
return eventId
return result.success.toString()
}
/**
* Publish an order event (kind 4 encrypted DM) to nostrmarket
*/
async publishOrder(order: Order, merchantPubkey: string): Promise<string> {
const { pubkey, prvkey } = this.getAuth()
const { prvkey } = this.getAuth()
// Convert order to nostrmarket format - exactly matching the specification
const orderData = {
@ -205,7 +231,27 @@ export class NostrmarketService {
}
// Encrypt the message using NIP-04
const encryptedContent = await nip04.encrypt(prvkey, merchantPubkey, JSON.stringify(orderData))
console.log('🔐 NIP-04 encryption debug:', {
prvkeyType: typeof prvkey,
prvkeyIsString: typeof prvkey === 'string',
prvkeyLength: prvkey.length,
prvkeySample: prvkey.substring(0, 10) + '...',
merchantPubkeyType: typeof merchantPubkey,
merchantPubkeyLength: merchantPubkey.length,
orderDataString: JSON.stringify(orderData).substring(0, 50) + '...'
})
let encryptedContent: string
try {
encryptedContent = await nip04.encrypt(prvkey, merchantPubkey, JSON.stringify(orderData))
console.log('🔐 NIP-04 encryption successful:', {
encryptedContentLength: encryptedContent.length,
encryptedContentSample: encryptedContent.substring(0, 50) + '...'
})
} catch (error) {
console.error('🔐 NIP-04 encryption failed:', error)
throw error
}
const eventTemplate: EventTemplate = {
kind: 4, // Encrypted DM
@ -214,18 +260,36 @@ export class NostrmarketService {
created_at: Math.floor(Date.now() / 1000)
}
const event = finalizeEvent(eventTemplate, prvkey)
const eventId = await relayHub.publishEvent(event)
console.log('🔧 finalizeEvent debug:', {
prvkeyType: typeof prvkey,
prvkeyIsString: typeof prvkey === 'string',
prvkeyLength: prvkey.length,
prvkeySample: prvkey.substring(0, 10) + '...',
encodedPrvkeyType: typeof new TextEncoder().encode(prvkey),
encodedPrvkeyLength: new TextEncoder().encode(prvkey).length,
eventTemplate
})
// Convert hex string to Uint8Array properly
const prvkeyBytes = this.hexToUint8Array(prvkey)
console.log('🔧 prvkeyBytes debug:', {
prvkeyBytesType: typeof prvkeyBytes,
prvkeyBytesLength: prvkeyBytes.length,
prvkeyBytesIsUint8Array: prvkeyBytes instanceof Uint8Array
})
const event = finalizeEvent(eventTemplate, prvkeyBytes)
const result = await relayHub.publishEvent(event)
console.log('Order published to nostrmarket:', {
orderId: order.id,
eventId: eventId,
eventId: result,
merchantPubkey,
content: orderData,
encryptedContent: encryptedContent.substring(0, 50) + '...'
})
return eventId
return result.success.toString()
}
/**

View file

@ -1,11 +0,0 @@
import { nip19 } from 'nostr-tools'
// Helper function to convert bech32 to hex using nostr-tools
export function bech32ToHex(bech32Key: string): string {
if (bech32Key.startsWith('npub1') || bech32Key.startsWith('nsec1')) {
const { type, data } = nip19.decode(bech32Key)
return data as string
}
// Already hex format
return bech32Key
}