Squash merge remove-dangling-bits into market-implementation-squashed
This commit is contained in:
parent
4bc15cfa2f
commit
2f0024478d
17 changed files with 569 additions and 859 deletions
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue