This commit is contained in:
boufni95 2024-09-04 15:23:32 +00:00
parent ee5f3c2743
commit 0b27757f72
3 changed files with 23 additions and 20 deletions

View file

@ -20,9 +20,9 @@ export type CustomProfilePointer = {
export type OfferPointer = {
pubkey: string,
relays?: string[],
relay: string,
offer: string
priceType: 'fixed' | 'spontaneous' | 'variable',
priceType: PriceType,
price?: number
}
enum PriceType {
@ -68,17 +68,16 @@ export const encodeNprofile = (profile: CustomProfilePointer): string => {
}
export const encodeNoffer = (offer: OfferPointer): string => {
let relays = offer.relays
if (!relays) {
let relay = offer.relay
if (!relay) {
const settings = LoadNosrtSettingsFromEnv()
relays = settings.relays
relay = settings.relays[0]
}
const typeAsNum = Number(PriceType[offer.priceType])
const o: TLV = {
0: [hexToBytes(offer.pubkey)],
1: (relays).map(url => utf8Encoder.encode(url)),
1: [utf8Encoder.encode(relay)],
2: [utf8Encoder.encode(offer.offer)],
3: [new Uint8Array([typeAsNum])],
3: [new Uint8Array([Number(offer.priceType)])],
}
if (offer.price) {
o[4] = [new Uint8Array(new BigUint64Array([BigInt(offer.price)]).buffer)]
@ -113,11 +112,15 @@ export const decodeNoffer = (noffer: string): OfferPointer => {
const tlv = parseTLV(data);
if (!tlv[0]?.[0]) throw new Error('missing TLV 0 for noffer')
if (tlv[0][0].length !== 32) throw new Error('TLV 0 should be 32 bytes')
if (!tlv[1]?.[0]) throw new Error('missing TLV 1 for noffer')
if (!tlv[2]?.[0]) throw new Error('missing TLV 2 for noffer')
if (!tlv[3]?.[0]) throw new Error('missing TLV 3 for noffer')
return {
pubkey: bytesToHex(tlv[0][0]),
relays: tlv[1] ? tlv[1].map(d => utf8Decoder.decode(d)) : [],
bridge: tlv[2] ? tlv[2].map(d => utf8Decoder.decode(d)) : []
relay: utf8Decoder.decode(tlv[1][0]),
offer: utf8Decoder.decode(tlv[2][0]),
priceType: tlv[3][0][0],
price: tlv[4] ? Number(new BigUint64Array(tlv[4][0])[0]) : undefined
}
}

View file

@ -1,4 +1,4 @@
import Main from "./services/main/index.js"
import Main, { NofferData } from "./services/main/index.js"
import Nostr from "./services/nostr/index.js"
import { NostrEvent, NostrSend, NostrSettings } from "./services/nostr/handler.js"
import * as Types from '../proto/autogenerated/ts/types.js'
@ -7,7 +7,7 @@ import { ERROR, getLogger } from "./services/helpers/logger.js";
import { UnsignedEvent } from "./services/nostr/tools/event.js";
import { defaultInvoiceExpiry } from "./services/storage/paymentStorage.js";
import { Application } from "./services/storage/entity/Application.js";
type NofferData = { offer: string, amount?: number }
export default (serverMethods: Types.ServerMethods, mainHandler: Main, nostrSettings: NostrSettings, onClientEvent: (e: { requestId: string }, fromPub: string) => void): { Stop: () => void, Send: NostrSend } => {
const log = getLogger({})
const nostrTransport = NewNostrTransport(serverMethods, {

View file

@ -31,7 +31,7 @@ type UserOperationsSub = {
newOutgoingTx: (operation: Types.UserOperation) => void
}
const appTag = "Lightning.Pub"
export type NofferData = { offer: string, amount?: number }
export default class {
storage: Storage
lnd: LND
@ -275,14 +275,14 @@ export default class {
this.nostrSend({ type: 'app', appId: invoice.linkedApplication.app_id }, { type: 'event', event })
}
async getNofferInvoice(offerReq: { offer: string, amount?: number }, appId: string): Promise<{ success: true, invoice: string } | { success: false, code: number }> {
async getNofferInvoice(offerReq: NofferData, appId: string): Promise<{ success: true, invoice: string } | { success: false, code: number, max: number }> {
try {
const { remote } = await this.lnd.ChannelBalance()
const { offer, amount } = offerReq
const split = offer.split(':')
if (split.length === 1) {
if (!amount || isNaN(amount) || amount < 10 || amount > remote) {
return { success: false, code: 5 }
return { success: false, code: 5, max: remote }
}
const res = await this.applicationManager.AddAppUserInvoice(appId, {
http_callback_url: "", payer_identifier: split[0], receiver_identifier: split[0],
@ -293,19 +293,19 @@ export default class {
const product = await this.productManager.NewProductInvoice(split[1])
return { success: true, invoice: product.invoice }
} else {
return { success: false, code: 1 }
return { success: false, code: 1, max: remote }
}
} catch (e: any) {
getLogger({ component: "noffer" })(ERROR, e.message || e)
return { success: false, code: 1 }
return { success: false, code: 1, max: 0 }
}
}
async handleNip69Noffer(offerReq: { offer: string }, event: NostrEvent) {
async handleNip69Noffer(offerReq: NofferData, event: NostrEvent) {
const offerInvoice = await this.getNofferInvoice(offerReq, event.appId)
if (!offerInvoice.success) {
const code = offerInvoice.code
const e = newNofferResponse(JSON.stringify({ code, message: codeToMessage(code) }), event)
const e = newNofferResponse(JSON.stringify({ code, error: codeToMessage(code), range: { min: 10, max: offerInvoice.max } }), event)
this.nostrSend({ type: 'app', appId: event.appId }, { type: 'event', event: e, encrypt: { toPub: event.pub } })
return
}