logs and fixies
This commit is contained in:
parent
c02fcc549a
commit
62e1d0c099
3 changed files with 47 additions and 34 deletions
|
|
@ -10,7 +10,7 @@ import { NostrEvent, NostrSend, SendData, SendInitiator } from '../nostr/handler
|
||||||
import { UnsignedEvent } from 'nostr-tools';
|
import { UnsignedEvent } from 'nostr-tools';
|
||||||
import { Ndebit, NdebitData, NdebitFailure, NdebitSuccess, RecurringDebitTimeUnit } from "@shocknet/clink-sdk";
|
import { Ndebit, NdebitData, NdebitFailure, NdebitSuccess, RecurringDebitTimeUnit } from "@shocknet/clink-sdk";
|
||||||
import { debitAccessRulesToDebitRules, newNdebitResponse,debitRulesToDebitAccessRules,
|
import { debitAccessRulesToDebitRules, newNdebitResponse,debitRulesToDebitAccessRules,
|
||||||
nip68errs, AuthRequiredRes, HandleNdebitRes, expirationRuleName,
|
nofferErrors, AuthRequiredRes, HandleNdebitRes, expirationRuleName,
|
||||||
frequencyRuleName,IntervalTypeToSeconds,unitToIntervalType } from "./debitTypes.js";
|
frequencyRuleName,IntervalTypeToSeconds,unitToIntervalType } from "./debitTypes.js";
|
||||||
|
|
||||||
export class DebitManager {
|
export class DebitManager {
|
||||||
|
|
@ -39,23 +39,6 @@ export class DebitManager {
|
||||||
this._nostrSend(initiator, data, relays)
|
this._nostrSend(initiator, data, relays)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* AuthorizeDebit = async (ctx: Types.UserContext, req: Types.DebitAuthorizationRequest): Promise<Types.DebitAuthorization> => {
|
|
||||||
const access = await this.storage.debitStorage.AddDebitAccess(ctx.app_user_id, {
|
|
||||||
authorize: true,
|
|
||||||
npub: req.authorize_npub,
|
|
||||||
rules: debitRulesToDebitAccessRules(req.rules)
|
|
||||||
})
|
|
||||||
if (req.request_id) {
|
|
||||||
this.sendDebitResponse({ res: 'ok' }, { pub: req.authorize_npub, id: req.request_id, appId: ctx.app_id })
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
debit_id: access.serial_id.toString(),
|
|
||||||
npub: req.authorize_npub,
|
|
||||||
authorized: true,
|
|
||||||
rules: req.rules
|
|
||||||
}
|
|
||||||
} */
|
|
||||||
|
|
||||||
GetDebitAuthorizations = async (ctx: Types.UserContext): Promise<Types.DebitAuthorizations> => {
|
GetDebitAuthorizations = async (ctx: Types.UserContext): Promise<Types.DebitAuthorizations> => {
|
||||||
const allDebitsAccesses = await this.storage.debitStorage.GetAllUserDebitAccess(ctx.app_user_id)
|
const allDebitsAccesses = await this.storage.debitStorage.GetAllUserDebitAccess(ctx.app_user_id)
|
||||||
const debits: Types.DebitAuthorization[] = allDebitsAccesses.map(access => ({
|
const debits: Types.DebitAuthorization[] = allDebitsAccesses.map(access => ({
|
||||||
|
|
@ -85,7 +68,8 @@ export class DebitManager {
|
||||||
RespondToDebit = async (ctx: Types.UserContext, req: Types.DebitResponse): Promise<void> => {
|
RespondToDebit = async (ctx: Types.UserContext, req: Types.DebitResponse): Promise<void> => {
|
||||||
switch (req.response.type) {
|
switch (req.response.type) {
|
||||||
case Types.DebitResponse_response_type.DENIED:
|
case Types.DebitResponse_response_type.DENIED:
|
||||||
this.sendDebitResponse({ res: 'GFY', error: nip68errs[1], code: 1 }, { pub: req.npub, id: req.request_id, appId: ctx.app_id })
|
this.logger("🔍 [DEBIT REQUEST] Sending denied response")
|
||||||
|
this.sendDebitResponse({ res: 'GFY', error: nofferErrors[1], code: 1 }, { pub: req.npub, id: req.request_id, appId: ctx.app_id })
|
||||||
return
|
return
|
||||||
case Types.DebitResponse_response_type.INVOICE:
|
case Types.DebitResponse_response_type.INVOICE:
|
||||||
await this.paySingleInvoice(ctx, {invoice: req.response.invoice, npub: req.npub, request_id: req.request_id})
|
await this.paySingleInvoice(ctx, {invoice: req.response.invoice, npub: req.npub, request_id: req.request_id})
|
||||||
|
|
@ -100,19 +84,25 @@ export class DebitManager {
|
||||||
|
|
||||||
paySingleInvoice = async (ctx: Types.UserContext, {invoice,npub,request_id}:{invoice:string, npub:string, request_id:string}) => {
|
paySingleInvoice = async (ctx: Types.UserContext, {invoice,npub,request_id}:{invoice:string, npub:string, request_id:string}) => {
|
||||||
try {
|
try {
|
||||||
|
this.logger("🔍 [DEBIT REQUEST] Paying single invoice")
|
||||||
const app = await this.storage.applicationStorage.GetApplication(ctx.app_id)
|
const app = await this.storage.applicationStorage.GetApplication(ctx.app_id)
|
||||||
const appUser = await this.storage.applicationStorage.GetApplicationUser(app, ctx.app_user_id)
|
const appUser = await this.storage.applicationStorage.GetApplicationUser(app, ctx.app_user_id)
|
||||||
const { op, payment } = await this.sendDebitPayment(ctx.app_id, ctx.app_user_id, npub, invoice)
|
const { op, payment } = await this.sendDebitPayment(ctx.app_id, ctx.app_user_id, npub, invoice)
|
||||||
const debitRes: NdebitSuccess = { res: 'ok', preimage: payment.preimage }
|
const debitRes: NdebitSuccess = { res: 'ok', preimage: payment.preimage }
|
||||||
this.notifyPaymentSuccess(appUser, debitRes, op, { appId: ctx.app_id, pub: npub, id: request_id })
|
this.notifyPaymentSuccess(appUser, debitRes, op, { appId: ctx.app_id, pub: npub, id: request_id })
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
this.sendDebitResponse({ res: 'GFY', error: nip68errs[1], code: 1 }, { pub: npub, id: request_id, appId: ctx.app_id })
|
this.logger("❌ [DEBIT REQUEST] Error in single invoice payment")
|
||||||
|
this.sendDebitResponse({ res: 'GFY', error: nofferErrors[1], code: 1 }, { pub: npub, id: request_id, appId: ctx.app_id })
|
||||||
throw e
|
throw e
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
handleAuthorization = async(ctx: Types.UserContext,debit:Types.DebitToAuthorize, {npub,request_id}:{ npub:string, request_id:string})=>{
|
handleAuthorization = async (ctx: Types.UserContext,debit:Types.DebitToAuthorize, {npub,request_id}:{ npub:string, request_id:string})=>{
|
||||||
|
this.logger("🔍 [DEBIT REQUEST] Handling authorization", {
|
||||||
|
npub,
|
||||||
|
request_id,
|
||||||
|
debit
|
||||||
|
})
|
||||||
const access = await this.storage.debitStorage.AddDebitAccess(ctx.app_user_id, {
|
const access = await this.storage.debitStorage.AddDebitAccess(ctx.app_user_id, {
|
||||||
authorize: true,
|
authorize: true,
|
||||||
npub,
|
npub,
|
||||||
|
|
@ -123,6 +113,7 @@ export class DebitManager {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (!invoice) {
|
if (!invoice) {
|
||||||
|
this.logger("🔍 [DEBIT REQUEST] Sending ok response")
|
||||||
this.sendDebitResponse({ res: 'ok' }, { pub: npub, id: request_id, appId: ctx.app_id })
|
this.sendDebitResponse({ res: 'ok' }, { pub: npub, id: request_id, appId: ctx.app_id })
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -130,11 +121,13 @@ export class DebitManager {
|
||||||
const app = await this.storage.applicationStorage.GetApplication(ctx.app_id)
|
const app = await this.storage.applicationStorage.GetApplication(ctx.app_id)
|
||||||
const appUser = await this.storage.applicationStorage.GetApplicationUser(app, ctx.app_user_id)
|
const appUser = await this.storage.applicationStorage.GetApplicationUser(app, ctx.app_user_id)
|
||||||
this.validateAccessRules(access, app, appUser)
|
this.validateAccessRules(access, app, appUser)
|
||||||
|
this.logger("🔍 [DEBIT REQUEST] Sending debit payment")
|
||||||
const { op, payment } = await this.sendDebitPayment(ctx.app_id, ctx.app_user_id, npub, invoice)
|
const { op, payment } = await this.sendDebitPayment(ctx.app_id, ctx.app_user_id, npub, invoice)
|
||||||
const debitRes: NdebitSuccess = { res: 'ok', preimage: payment.preimage }
|
const debitRes: NdebitSuccess = { res: 'ok', preimage: payment.preimage }
|
||||||
this.notifyPaymentSuccess(appUser, debitRes, op, { appId: ctx.app_id, pub: npub, id: request_id })
|
this.notifyPaymentSuccess(appUser, debitRes, op, { appId: ctx.app_id, pub: npub, id: request_id })
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
this.sendDebitResponse({ res: 'GFY', error: nip68errs[1], code: 1 }, { pub: npub, id: request_id, appId: ctx.app_id })
|
this.logger("❌ [DEBIT REQUEST] Error in debit authorization")
|
||||||
|
this.sendDebitResponse({ res: 'GFY', error: nofferErrors[1], code: 1 }, { pub: npub, id: request_id, appId: ctx.app_id })
|
||||||
throw e
|
throw e
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -144,7 +137,14 @@ export class DebitManager {
|
||||||
if (!this._nostrSend) {
|
if (!this._nostrSend) {
|
||||||
throw new Error("No nostrSend attached")
|
throw new Error("No nostrSend attached")
|
||||||
}
|
}
|
||||||
|
this.logger("📥 [DEBIT REQUEST] Received debit request", {
|
||||||
|
fromPub: event.pub,
|
||||||
|
appId: event.appId,
|
||||||
|
eventId: event.id,
|
||||||
|
pointerdata
|
||||||
|
})
|
||||||
const res = await this.payNdebitInvoice(event, pointerdata)
|
const res = await this.payNdebitInvoice(event, pointerdata)
|
||||||
|
this.logger("🔍 [DEBIT REQUEST] Sending ",res.status," response")
|
||||||
if (res.status === 'fail' || res.status === 'authOk') {
|
if (res.status === 'fail' || res.status === 'authOk') {
|
||||||
const e = newNdebitResponse(JSON.stringify(res.debitRes), event)
|
const e = newNdebitResponse(JSON.stringify(res.debitRes), event)
|
||||||
this.nostrSend({ type: 'app', appId: event.appId }, { type: 'event', event: e, encrypt: { toPub: event.pub } })
|
this.nostrSend({ type: 'app', appId: event.appId }, { type: 'event', event: e, encrypt: { toPub: event.pub } })
|
||||||
|
|
@ -161,7 +161,7 @@ export class DebitManager {
|
||||||
|
|
||||||
handleAuthRequired = (data:NdebitData, event: NostrEvent, res: AuthRequiredRes) => {
|
handleAuthRequired = (data:NdebitData, event: NostrEvent, res: AuthRequiredRes) => {
|
||||||
if (!res.appUser.nostr_public_key) {
|
if (!res.appUser.nostr_public_key) {
|
||||||
this.sendDebitResponse({ res: 'GFY', error: nip68errs[1], code: 1 }, { pub: event.pub, id: event.id, appId: event.appId })
|
this.sendDebitResponse({ res: 'GFY', error: nofferErrors[1], code: 1 }, { pub: event.pub, id: event.id, appId: event.appId })
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
const message: Types.LiveDebitRequest & { requestId: string, status: 'OK' } = { ...res.liveDebitReq, requestId: "GetLiveDebitRequests", status: 'OK' }
|
const message: Types.LiveDebitRequest & { requestId: string, status: 'OK' } = { ...res.liveDebitReq, requestId: "GetLiveDebitRequests", status: 'OK' }
|
||||||
|
|
@ -185,8 +185,9 @@ export class DebitManager {
|
||||||
try {
|
try {
|
||||||
return await this.doNdebit(event, pointerdata)
|
return await this.doNdebit(event, pointerdata)
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
|
this.logger("❌ [DEBIT ERROR] Error in debit request")
|
||||||
this.logger(ERROR, e.message || e)
|
this.logger(ERROR, e.message || e)
|
||||||
return { status: 'fail', debitRes: { res: 'GFY', error: nip68errs[1], code: 1 } }
|
return { status: 'fail', debitRes: { res: 'GFY', error: nofferErrors[1], code: 1 } }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -195,21 +196,24 @@ export class DebitManager {
|
||||||
const { amount_sats, pointer, bolt11, frequency } = pointerdata
|
const { amount_sats, pointer, bolt11, frequency } = pointerdata
|
||||||
if (!pointer) {
|
if (!pointer) {
|
||||||
// TODO: debit from app owner balance
|
// TODO: debit from app owner balance
|
||||||
return { status: 'fail', debitRes: { res: 'GFY', error: nip68errs[1], code: 1 } }
|
return { status: 'fail', debitRes: { res: 'GFY', error: nofferErrors[1], code: 1 } }
|
||||||
}
|
}
|
||||||
const appUserId = pointer
|
const appUserId = pointer
|
||||||
const app = await this.storage.applicationStorage.GetApplication(appId)
|
const app = await this.storage.applicationStorage.GetApplication(appId)
|
||||||
const appUser = await this.storage.applicationStorage.GetApplicationUser(app, appUserId)
|
const appUser = await this.storage.applicationStorage.GetApplicationUser(app, appUserId)
|
||||||
let decodedAmount = null
|
let decodedAmount = null
|
||||||
if (bolt11) {
|
if (bolt11) {
|
||||||
|
this.logger("🔍 [DEBIT REQUEST] Decoding invoice")
|
||||||
const decoded = await this.lnd.DecodeInvoice(bolt11)
|
const decoded = await this.lnd.DecodeInvoice(bolt11)
|
||||||
decodedAmount = decoded.numSatoshis
|
decodedAmount = decoded.numSatoshis
|
||||||
}
|
}
|
||||||
if (frequency) {
|
if (frequency) {
|
||||||
|
this.logger("🔍 [DEBIT REQUEST] Checking frequency")
|
||||||
const amt = amount_sats || decodedAmount
|
const amt = amount_sats || decodedAmount
|
||||||
if (!amt) {
|
if (!amt) {
|
||||||
return { status: 'fail', debitRes: { res: 'GFY', error: nip68errs[5], code: 5 } }
|
return { status: 'fail', debitRes: { res: 'GFY', error: nofferErrors[5], code: 5 } }
|
||||||
}
|
}
|
||||||
|
|
||||||
const debitAccess = await this.storage.debitStorage.GetDebitAccess(appUserId, requestorPub)
|
const debitAccess = await this.storage.debitStorage.GetDebitAccess(appUserId, requestorPub)
|
||||||
if (!debitAccess) {
|
if (!debitAccess) {
|
||||||
return {
|
return {
|
||||||
|
|
@ -227,13 +231,14 @@ export class DebitManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (!debitAccess.authorized) {
|
} else if (!debitAccess.authorized) {
|
||||||
return { status: 'fail', debitRes: { res: 'GFY', error: nip68errs[1], code: 1 } }
|
return { status: 'fail', debitRes: { res: 'GFY', error: nofferErrors[1], code: 1 } }
|
||||||
}
|
}
|
||||||
return { status: 'authOk', debitRes: { res: 'ok' } }
|
return { status: 'authOk', debitRes: { res: 'ok' } }
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!bolt11) {
|
if (!bolt11) {
|
||||||
if (!amount_sats) {
|
if (!amount_sats) {
|
||||||
|
this.logger("🔍 [DEBIT REQUEST] Checking full access")
|
||||||
const debitAccess = await this.storage.debitStorage.GetDebitAccess(appUserId, requestorPub)
|
const debitAccess = await this.storage.debitStorage.GetDebitAccess(appUserId, requestorPub)
|
||||||
if (!debitAccess) {
|
if (!debitAccess) {
|
||||||
return {
|
return {
|
||||||
|
|
@ -247,20 +252,22 @@ export class DebitManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (!debitAccess.authorized) {
|
} else if (!debitAccess.authorized) {
|
||||||
return { status: 'fail', debitRes: { res: 'GFY', error: nip68errs[1], code: 1 } }
|
return { status: 'fail', debitRes: { res: 'GFY', error: nofferErrors[1], code: 1 } }
|
||||||
}
|
}
|
||||||
return { status: 'authOk', debitRes: { res: 'ok' } }
|
return { status: 'authOk', debitRes: { res: 'ok' } }
|
||||||
}
|
}
|
||||||
return { status: 'fail', debitRes: { res: 'GFY', error: nip68errs[6], code: 6 } }
|
return { status: 'fail', debitRes: { res: 'GFY', error: nofferErrors[6], code: 6 } }
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!decodedAmount) {
|
if (!decodedAmount) {
|
||||||
return { status: 'fail', debitRes: { res: 'GFY', error: nip68errs[6], code: 6 } }
|
return { status: 'fail', debitRes: { res: 'GFY', error: nofferErrors[6], code: 6 } }
|
||||||
}
|
}
|
||||||
if (amount_sats && amount_sats !== decodedAmount) {
|
if (amount_sats && amount_sats !== decodedAmount) {
|
||||||
return { status: 'fail', debitRes: { res: 'GFY', error: nip68errs[5], code: 5 } }
|
return { status: 'fail', debitRes: { res: 'GFY', error: nofferErrors[5], code: 5 } }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.logger("🔍 [DEBIT REQUEST] Checking authorization")
|
||||||
|
|
||||||
const authorization = await this.storage.debitStorage.GetDebitAccess(appUserId, requestorPub)
|
const authorization = await this.storage.debitStorage.GetDebitAccess(appUserId, requestorPub)
|
||||||
if (!authorization) {
|
if (!authorization) {
|
||||||
return {
|
return {
|
||||||
|
|
@ -275,9 +282,10 @@ export class DebitManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!authorization.authorized) {
|
if (!authorization.authorized) {
|
||||||
return { status: 'fail', debitRes: { res: 'GFY', error: nip68errs[1], code: 1 } }
|
return { status: 'fail', debitRes: { res: 'GFY', error: nofferErrors[1], code: 1 } }
|
||||||
}
|
}
|
||||||
await this.validateAccessRules(authorization, app, appUser)
|
await this.validateAccessRules(authorization, app, appUser)
|
||||||
|
this.logger("🔍 [DEBIT REQUEST] Sending requested debit payment")
|
||||||
const { op, payment } = await this.sendDebitPayment(appId, appUserId, requestorPub, bolt11)
|
const { op, payment } = await this.sendDebitPayment(appId, appUserId, requestorPub, bolt11)
|
||||||
return { status: 'invoicePaid', op, app, appUser, debitRes: { res: 'ok', preimage: payment.preimage } }
|
return { status: 'invoicePaid', op, app, appUser, debitRes: { res: 'ok', preimage: payment.preimage } }
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -86,7 +86,7 @@ export const debitAccessRulesToDebitRules = (rules: DebitAccessRules | null): Ty
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
export const nip68errs = {
|
export const nofferErrors = {
|
||||||
1: "Request Denied Warning",
|
1: "Request Denied Warning",
|
||||||
2: "Temporary Failure",
|
2: "Temporary Failure",
|
||||||
3: "Expired Request",
|
3: "Expired Request",
|
||||||
|
|
|
||||||
|
|
@ -387,6 +387,11 @@ export default (mainHandler: Main): Types.ServerMethods => {
|
||||||
return mainHandler.debitManager.EditDebit(ctx, req);
|
return mainHandler.debitManager.EditDebit(ctx, req);
|
||||||
},
|
},
|
||||||
RespondToDebit: async ({ ctx, req }) => {
|
RespondToDebit: async ({ ctx, req }) => {
|
||||||
|
const err = Types.DebitResponseValidate(req, {
|
||||||
|
npub_CustomCheck: pub => pub !== '',
|
||||||
|
request_id_CustomCheck: id => id !== '',
|
||||||
|
})
|
||||||
|
if (err != null) throw new Error(err.message)
|
||||||
return mainHandler.debitManager.RespondToDebit(ctx, req);
|
return mainHandler.debitManager.RespondToDebit(ctx, req);
|
||||||
},
|
},
|
||||||
AddUserOffer: async ({ ctx, req }) => {
|
AddUserOffer: async ({ ctx, req }) => {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue