full access, freq+bol11

This commit is contained in:
boufni95 2024-10-04 16:47:01 +00:00
parent 1049586646
commit 0dd79eecf6
6 changed files with 57 additions and 27 deletions

7
package-lock.json generated
View file

@ -32,7 +32,7 @@
"grpc-tools": "^1.12.4",
"jsonwebtoken": "^9.0.2",
"lodash": "^4.17.21",
"nostr-tools": "github:shocknet/nostr-tools#ef16463592e2f7b5bf18abc86ff974615d64bb7d",
"nostr-tools": "github:shocknet/nostr-tools#19271c4bcc9ff9bf18f9208e2d9fd6870e5f350c",
"pg": "^8.4.0",
"reflect-metadata": "^0.2.2",
"rimraf": "^3.0.2",
@ -3802,8 +3802,9 @@
},
"node_modules/nostr-tools": {
"version": "2.8.0",
"resolved": "git+ssh://git@github.com/shocknet/nostr-tools.git#ef16463592e2f7b5bf18abc86ff974615d64bb7d",
"integrity": "sha512-PSBLCTv5ruThR2uS4CRIFgqU6kySxPpDWiqit2Lkc3c1RbTeyhKMr9pRnLSoulkdRZGtDYSTgmoBxvqPkqO8XQ==",
"resolved": "git+ssh://git@github.com/shocknet/nostr-tools.git#19271c4bcc9ff9bf18f9208e2d9fd6870e5f350c",
"integrity": "sha512-NWYu4yx9UELd4M333r6Eirg0lKK9vyEiUW/8DDorZtxSlBdH4B9FqH8w7VJrG2LfPJABC89EH6+VNLz7RENCfg==",
"license": "Unlicense",
"dependencies": {
"@noble/ciphers": "^0.5.1",
"@noble/curves": "1.2.0",

View file

@ -49,7 +49,7 @@
"grpc-tools": "^1.12.4",
"jsonwebtoken": "^9.0.2",
"lodash": "^4.17.21",
"nostr-tools": "github:shocknet/nostr-tools#ef16463592e2f7b5bf18abc86ff974615d64bb7d",
"nostr-tools": "github:shocknet/nostr-tools#19271c4bcc9ff9bf18f9208e2d9fd6870e5f350c",
"pg": "^8.4.0",
"reflect-metadata": "^0.2.2",
"rimraf": "^3.0.2",

View file

@ -531,12 +531,14 @@ type DebitRule_rule struct {
type LiveDebitRequest_debit_type string
const (
FREQUENCY LiveDebitRequest_debit_type = "frequency"
INVOICE LiveDebitRequest_debit_type = "invoice"
FREQUENCY LiveDebitRequest_debit_type = "frequency"
FULL_ACCESS LiveDebitRequest_debit_type = "full_access"
INVOICE LiveDebitRequest_debit_type = "invoice"
)
type LiveDebitRequest_debit struct {
Type LiveDebitRequest_debit_type `json:"type"`
Frequency *FrequencyRule `json:"frequency"`
Invoice *string `json:"invoice"`
Type LiveDebitRequest_debit_type `json:"type"`
Frequency *FrequencyRule `json:"frequency"`
Full_access *Empty `json:"full_access"`
Invoice *string `json:"invoice"`
}

View file

@ -2945,6 +2945,7 @@ export const DebitRule_ruleValidate = (o?: DebitRule_rule, opts:DebitRule_ruleOp
}
export enum LiveDebitRequest_debit_type {
FREQUENCY = 'frequency',
FULL_ACCESS = 'full_access',
INVOICE = 'invoice',
}
export const enumCheckLiveDebitRequest_debit_type = (e?: LiveDebitRequest_debit_type): boolean => {
@ -2953,10 +2954,12 @@ export const enumCheckLiveDebitRequest_debit_type = (e?: LiveDebitRequest_debit_
}
export type LiveDebitRequest_debit =
{type:LiveDebitRequest_debit_type.FREQUENCY, frequency:FrequencyRule}|
{type:LiveDebitRequest_debit_type.FULL_ACCESS, full_access:Empty}|
{type:LiveDebitRequest_debit_type.INVOICE, invoice:string}
export type LiveDebitRequest_debitOptions = {
frequency_Options?: FrequencyRuleOptions
full_access_Options?: EmptyOptions
invoice_CustomCheck?: (v: string) => boolean
}
export const LiveDebitRequest_debitValidate = (o?: LiveDebitRequest_debit, opts:LiveDebitRequest_debitOptions = {}, path: string = 'LiveDebitRequest_debit::root.'): Error | null => {
@ -2968,6 +2971,12 @@ export const LiveDebitRequest_debitValidate = (o?: LiveDebitRequest_debit, opts:
if (frequencyErr !== null) return frequencyErr
break
case LiveDebitRequest_debit_type.FULL_ACCESS:
const full_accessErr = EmptyValidate(o.full_access, opts.full_access_Options, `${path}.full_access`)
if (full_accessErr !== null) return full_accessErr
break
case LiveDebitRequest_debit_type.INVOICE:
if (typeof o.invoice !== 'string') return new Error(`${path}.invoice: is not a string`)

View file

@ -536,6 +536,7 @@ message LiveDebitRequest {
oneof debit {
string invoice = 3;
FrequencyRule frequency = 4;
Empty full_access = 5;
}
}

View file

@ -10,10 +10,9 @@ import { Application } from '../storage/entity/Application.js';
import { ApplicationUser } from '../storage/entity/ApplicationUser.js';
import { NostrEvent, NostrSend, SendData, SendInitiator } from '../nostr/handler.js';
import { UnsignedEvent } from 'nostr-tools';
import { BudgetFrequency, NdebitData, NdebitFailure, NdebitSuccess, NdebitSuccessPayment, RecurringDebitTimeUnit } from 'nostr-tools/lib/types/nip68.js';
export const expirationRuleName = 'expiration'
export const frequencyRuleName = 'frequency'
type RecurringDebitTimeUnit = 'day' | 'week' | 'month'
type RecurringDebit = { frequency: { number: number, unit: RecurringDebitTimeUnit } }
const unitToIntervalType = (unit: RecurringDebitTimeUnit) => {
switch (unit) {
case 'day': return Types.IntervalType.DAY
@ -93,11 +92,6 @@ const debitAccessRulesToDebitRules = (rules: DebitAccessRules | null): Types.Deb
}
})
}
export type NdebitData = { pointer?: string, amount_sats: number } & (RecurringDebit | { bolt11: string })
export type NdebitSuccess = { res: 'ok' }
export type NdebitSuccessPayment = { res: 'ok', preimage: string }
export type NdebitFailure = { res: 'GFY', error: string, code: number }
const nip68errs = {
1: "Request Denied Warning",
2: "Temporary Failure",
@ -244,7 +238,7 @@ export class DebitManager {
doNdebit = async (event: NostrEvent, pointerdata: NdebitData): Promise<HandleNdebitRes> => {
const { appId, pub: requestorPub } = event
const { amount_sats, pointer } = pointerdata
const { amount_sats, pointer, bolt11, frequency } = pointerdata
if (!pointer) {
// TODO: debit from app owner balance
return { status: 'fail', debitRes: { res: 'GFY', error: nip68errs[1], code: 1 } }
@ -252,9 +246,14 @@ export class DebitManager {
const appUserId = pointer
const app = await this.storage.applicationStorage.GetApplication(appId)
const appUser = await this.storage.applicationStorage.GetApplicationUser(app, appUserId)
const pointerFreq = pointerdata as RecurringDebit
if (pointerFreq.frequency) {
if (!amount_sats) {
let decodedAmount = null
if (bolt11) {
const decoded = await this.lnd.DecodeInvoice(bolt11)
decodedAmount = decoded.numSatoshis
}
if (frequency) {
const amt = amount_sats || decodedAmount
if (!amt) {
return { status: 'fail', debitRes: { res: 'GFY', error: nip68errs[5], code: 5 } }
}
const debitAccess = await this.storage.debitStorage.GetDebitAccess(appUserId, requestorPub)
@ -266,9 +265,9 @@ export class DebitManager {
debit: {
type: Types.LiveDebitRequest_debit_type.FREQUENCY,
frequency: {
interval: unitToIntervalType(pointerFreq.frequency.unit),
number_of_intervals: pointerFreq.frequency.number,
amount: pointerdata.amount_sats,
interval: unitToIntervalType(frequency.unit),
number_of_intervals: frequency.number,
amount: amt,
}
}
}
@ -278,15 +277,33 @@ export class DebitManager {
}
return { status: 'authOk', debitRes: { res: 'ok' } }
}
const { bolt11 } = pointerdata as { bolt11: string }
if (!bolt11) {
if (!amount_sats) {
const debitAccess = await this.storage.debitStorage.GetDebitAccess(appUserId, requestorPub)
if (!debitAccess) {
return {
status: 'authRequired', app, appUser, liveDebitReq: {
request_id: event.id,
npub: requestorPub,
debit: {
type: Types.LiveDebitRequest_debit_type.FULL_ACCESS,
full_access: {}
}
}
}
} else if (!debitAccess.authorized) {
return { status: 'fail', debitRes: { res: 'GFY', error: nip68errs[1], code: 1 } }
}
return { status: 'authOk', debitRes: { res: 'ok' } }
}
return { status: 'fail', debitRes: { res: 'GFY', error: nip68errs[6], code: 6 } }
}
const decoded = await this.lnd.DecodeInvoice(bolt11)
if (decoded.numSatoshis === 0) {
if (!decodedAmount) {
return { status: 'fail', debitRes: { res: 'GFY', error: nip68errs[6], code: 6 } }
}
if (amount_sats && amount_sats !== decoded.numSatoshis) {
if (amount_sats && amount_sats !== decodedAmount) {
return { status: 'fail', debitRes: { res: 'GFY', error: nip68errs[5], code: 5 } }
}