rfc 6570 callback templates and callback bearer tokens

This commit is contained in:
Mothana 2025-07-13 21:17:21 +04:00
parent 144de45075
commit 8005b2a3ff
16 changed files with 222 additions and 84 deletions

View file

@ -31,13 +31,14 @@ import { DebitToPub1727105758354 } from './build/src/services/storage/migrations
import { UserCbUrl1727112281043 } from './build/src/services/storage/migrations/1727112281043-user_cb_url.js' import { UserCbUrl1727112281043 } from './build/src/services/storage/migrations/1727112281043-user_cb_url.js'
import { UserOffer1733502626042 } from './build/src/services/storage/migrations/1733502626042-user_offer.js' import { UserOffer1733502626042 } from './build/src/services/storage/migrations/1733502626042-user_offer.js'
import { ManagementGrant1751307732346 } from './build/src/services/storage/migrations/1751307732346-management_grant.js' import { ManagementGrant1751307732346 } from './build/src/services/storage/migrations/1751307732346-management_grant.js'
import { InvoiceCallbackUrls1752425992291 } from './build/src/services/storage/migrations/1752425992291-invoice_callback_urls.js'
export default new DataSource({ export default new DataSource({
type: "sqlite", type: "sqlite",
database: "db.sqlite", database: "db.sqlite",
// logging: true, // logging: true,
migrations: [Initial1703170309875, LspOrder1718387847693, LiquidityProvider1719335699480, LndNodeInfo1720187506189, CreateInviteTokenTable1721751414878, migrations: [Initial1703170309875, LspOrder1718387847693, LiquidityProvider1719335699480, LndNodeInfo1720187506189, CreateInviteTokenTable1721751414878,
PaymentIndex1721760297610, DebitAccess1726496225078, DebitAccessFixes1726685229264, DebitToPub1727105758354, UserCbUrl1727112281043, PaymentIndex1721760297610, DebitAccess1726496225078, DebitAccessFixes1726685229264, DebitToPub1727105758354, UserCbUrl1727112281043,
UserOffer1733502626042, ManagementGrant1751307732346], UserOffer1733502626042, ManagementGrant1751307732346, InvoiceCallbackUrls1752425992291],
entities: [User, UserReceivingInvoice, UserReceivingAddress, AddressReceivingTransaction, UserInvoicePayment, UserTransactionPayment, entities: [User, UserReceivingInvoice, UserReceivingAddress, AddressReceivingTransaction, UserInvoicePayment, UserTransactionPayment,
UserBasicAuth, UserEphemeralKey, Product, UserToUserPayment, Application, ApplicationUser, UserToUserPayment, LspOrder, LndNodeInfo, TrackedProvider, InviteToken, DebitAccess, UserOffer, ManagementGrant], UserBasicAuth, UserEphemeralKey, Product, UserToUserPayment, Application, ApplicationUser, UserToUserPayment, LspOrder, LndNodeInfo, TrackedProvider, InviteToken, DebitAccess, UserOffer, ManagementGrant],
// synchronize: true, // synchronize: true,

16
package-lock.json generated
View file

@ -44,6 +44,7 @@
"ts-proto": "^1.131.2", "ts-proto": "^1.131.2",
"typeorm": "0.3.15", "typeorm": "0.3.15",
"typescript": "^5.5.4", "typescript": "^5.5.4",
"uri-template": "^2.0.0",
"uuid": "^8.3.2", "uuid": "^8.3.2",
"websocket": "^1.0.35", "websocket": "^1.0.35",
"websocket-polyfill": "^0.0.3", "websocket-polyfill": "^0.0.3",
@ -4744,6 +4745,12 @@
"node": "*" "node": "*"
} }
}, },
"node_modules/pct-encode": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/pct-encode/-/pct-encode-1.0.3.tgz",
"integrity": "sha512-+ojEvSHApoLWF2YYxwnOM4N9DPn5e5fG+j0YJ9drKNaYtrZYOq5M9ESOaBYqOHCXOAALODJJ4wkqHAXEuLpwMw==",
"license": "BSD-2-Clause"
},
"node_modules/performance-now": { "node_modules/performance-now": {
"version": "2.1.0", "version": "2.1.0",
"resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
@ -6486,6 +6493,15 @@
"punycode": "^2.1.0" "punycode": "^2.1.0"
} }
}, },
"node_modules/uri-template": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/uri-template/-/uri-template-2.0.0.tgz",
"integrity": "sha512-r/i44nPoo0ktEZDjx+hxp9PSjQuBBfsd6RgCRuuMqCP0FZEp+YE0SpihThI4UGc5ePqQEFsdyZc7UVlowp+LLw==",
"license": "MIT",
"dependencies": {
"pct-encode": "~1.0.0"
}
},
"node_modules/utf-8-validate": { "node_modules/utf-8-validate": {
"version": "5.0.10", "version": "5.0.10",
"resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.10.tgz", "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.10.tgz",

View file

@ -62,6 +62,7 @@
"ts-proto": "^1.131.2", "ts-proto": "^1.131.2",
"typeorm": "0.3.15", "typeorm": "0.3.15",
"typescript": "^5.5.4", "typescript": "^5.5.4",
"uri-template": "^2.0.0",
"uuid": "^8.3.2", "uuid": "^8.3.2",
"websocket": "^1.0.35", "websocket": "^1.0.35",
"websocket-polyfill": "^0.0.3", "websocket-polyfill": "^0.0.3",

View file

@ -1021,6 +1021,8 @@ The nostr server will send back a message response, and inside the body there wi
- __payer_data__: _[PayerData](#PayerData)_ *this field is optional - __payer_data__: _[PayerData](#PayerData)_ *this field is optional
- __payer_identifier__: _string_ - __payer_identifier__: _string_
- __receiver_identifier__: _string_ - __receiver_identifier__: _string_
- __rejectUnauthorized__: _boolean_ *this field is optional
- __token__: _string_ *this field is optional
### AddAppUserRequest ### AddAppUserRequest
- __balance__: _number_ - __balance__: _number_
@ -1383,12 +1385,16 @@ The nostr server will send back a message response, and inside the body there wi
### OfferConfig ### OfferConfig
- __callback_url__: _string_ - __callback_url__: _string_
- __createdAtUnix__: _number_
- __default_offer__: _boolean_ - __default_offer__: _boolean_
- __expected_data__: MAP with key: _string_ and value: _[OfferDataType](#OfferDataType)_
- __label__: _string_ - __label__: _string_
- __noffer__: _string_ - __noffer__: _string_
- __offer_id__: _string_ - __offer_id__: _string_
- __payer_data__: ARRAY of: _string_
- __price_sats__: _number_ - __price_sats__: _number_
- __rejectUnauthorized__: _boolean_
- __token__: _string_
- __updatedAtUnix__: _number_
### OfferId ### OfferId
- __offer_id__: _string_ - __offer_id__: _string_
@ -1631,9 +1637,6 @@ The nostr server will send back a message response, and inside the body there wi
- __MONTH__ - __MONTH__
- __WEEK__ - __WEEK__
### OfferDataType
- __DATA_STRING__
### OperationType ### OperationType
- __CHAIN_OP__ - __CHAIN_OP__
- __INVOICE_OP__ - __INVOICE_OP__

View file

@ -65,12 +65,6 @@ const (
WEEK IntervalType = "WEEK" WEEK IntervalType = "WEEK"
) )
type OfferDataType string
const (
DATA_STRING OfferDataType = "DATA_STRING"
)
type OperationType string type OperationType string
const ( const (
@ -112,6 +106,8 @@ type AddAppUserInvoiceRequest struct {
Payer_data *PayerData `json:"payer_data"` Payer_data *PayerData `json:"payer_data"`
Payer_identifier string `json:"payer_identifier"` Payer_identifier string `json:"payer_identifier"`
Receiver_identifier string `json:"receiver_identifier"` Receiver_identifier string `json:"receiver_identifier"`
Rejectunauthorized bool `json:"rejectUnauthorized"`
Token string `json:"token"`
} }
type AddAppUserRequest struct { type AddAppUserRequest struct {
Balance int64 `json:"balance"` Balance int64 `json:"balance"`
@ -474,12 +470,16 @@ type NewInvoiceResponse struct {
} }
type OfferConfig struct { type OfferConfig struct {
Callback_url string `json:"callback_url"` Callback_url string `json:"callback_url"`
Createdatunix int64 `json:"createdAtUnix"`
Default_offer bool `json:"default_offer"` Default_offer bool `json:"default_offer"`
Expected_data map[string]OfferDataType `json:"expected_data"`
Label string `json:"label"` Label string `json:"label"`
Noffer string `json:"noffer"` Noffer string `json:"noffer"`
Offer_id string `json:"offer_id"` Offer_id string `json:"offer_id"`
Payer_data []string `json:"payer_data"`
Price_sats int64 `json:"price_sats"` Price_sats int64 `json:"price_sats"`
Rejectunauthorized bool `json:"rejectUnauthorized"`
Token string `json:"token"`
Updatedatunix int64 `json:"updatedAtUnix"`
} }
type OfferId struct { type OfferId struct {
Offer_id string `json:"offer_id"` Offer_id string `json:"offer_id"`

View file

@ -429,13 +429,6 @@ export const enumCheckIntervalType = (e?: IntervalType): boolean => {
for (const v in IntervalType) if (e === v) return true for (const v in IntervalType) if (e === v) return true
return false return false
} }
export enum OfferDataType {
DATA_STRING = 'DATA_STRING',
}
export const enumCheckOfferDataType = (e?: OfferDataType): boolean => {
for (const v in OfferDataType) if (e === v) return true
return false
}
export enum OperationType { export enum OperationType {
CHAIN_OP = 'CHAIN_OP', CHAIN_OP = 'CHAIN_OP',
INVOICE_OP = 'INVOICE_OP', INVOICE_OP = 'INVOICE_OP',
@ -528,9 +521,11 @@ export type AddAppUserInvoiceRequest = {
payer_data?: PayerData payer_data?: PayerData
payer_identifier: string payer_identifier: string
receiver_identifier: string receiver_identifier: string
rejectUnauthorized?: boolean
token?: string
} }
export type AddAppUserInvoiceRequestOptionalField = 'offer_string' | 'payer_data' export type AddAppUserInvoiceRequestOptionalField = 'offer_string' | 'payer_data' | 'rejectUnauthorized' | 'token'
export const AddAppUserInvoiceRequestOptionalFields: AddAppUserInvoiceRequestOptionalField[] = ['offer_string', 'payer_data'] export const AddAppUserInvoiceRequestOptionalFields: AddAppUserInvoiceRequestOptionalField[] = ['offer_string', 'payer_data', 'rejectUnauthorized', 'token']
export type AddAppUserInvoiceRequestOptions = OptionsBaseMessage & { export type AddAppUserInvoiceRequestOptions = OptionsBaseMessage & {
checkOptionalsAreSet?: AddAppUserInvoiceRequestOptionalField[] checkOptionalsAreSet?: AddAppUserInvoiceRequestOptionalField[]
http_callback_url_CustomCheck?: (v: string) => boolean http_callback_url_CustomCheck?: (v: string) => boolean
@ -539,6 +534,8 @@ export type AddAppUserInvoiceRequestOptions = OptionsBaseMessage & {
payer_data_Options?: PayerDataOptions payer_data_Options?: PayerDataOptions
payer_identifier_CustomCheck?: (v: string) => boolean payer_identifier_CustomCheck?: (v: string) => boolean
receiver_identifier_CustomCheck?: (v: string) => boolean receiver_identifier_CustomCheck?: (v: string) => boolean
rejectUnauthorized_CustomCheck?: (v?: boolean) => boolean
token_CustomCheck?: (v?: string) => boolean
} }
export const AddAppUserInvoiceRequestValidate = (o?: AddAppUserInvoiceRequest, opts: AddAppUserInvoiceRequestOptions = {}, path: string = 'AddAppUserInvoiceRequest::root.'): Error | null => { export const AddAppUserInvoiceRequestValidate = (o?: AddAppUserInvoiceRequest, opts: AddAppUserInvoiceRequestOptions = {}, path: string = 'AddAppUserInvoiceRequest::root.'): Error | null => {
if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message') if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message')
@ -566,6 +563,12 @@ export const AddAppUserInvoiceRequestValidate = (o?: AddAppUserInvoiceRequest, o
if (typeof o.receiver_identifier !== 'string') return new Error(`${path}.receiver_identifier: is not a string`) if (typeof o.receiver_identifier !== 'string') return new Error(`${path}.receiver_identifier: is not a string`)
if (opts.receiver_identifier_CustomCheck && !opts.receiver_identifier_CustomCheck(o.receiver_identifier)) return new Error(`${path}.receiver_identifier: custom check failed`) if (opts.receiver_identifier_CustomCheck && !opts.receiver_identifier_CustomCheck(o.receiver_identifier)) return new Error(`${path}.receiver_identifier: custom check failed`)
if ((o.rejectUnauthorized || opts.allOptionalsAreSet || opts.checkOptionalsAreSet?.includes('rejectUnauthorized')) && typeof o.rejectUnauthorized !== 'boolean') return new Error(`${path}.rejectUnauthorized: is not a boolean`)
if (opts.rejectUnauthorized_CustomCheck && !opts.rejectUnauthorized_CustomCheck(o.rejectUnauthorized)) return new Error(`${path}.rejectUnauthorized: custom check failed`)
if ((o.token || opts.allOptionalsAreSet || opts.checkOptionalsAreSet?.includes('token')) && typeof o.token !== 'string') return new Error(`${path}.token: is not a string`)
if (opts.token_CustomCheck && !opts.token_CustomCheck(o.token)) return new Error(`${path}.token: custom check failed`)
return null return null
} }
@ -2754,23 +2757,31 @@ export const NewInvoiceResponseValidate = (o?: NewInvoiceResponse, opts: NewInvo
export type OfferConfig = { export type OfferConfig = {
callback_url: string callback_url: string
createdAtUnix: number
default_offer: boolean default_offer: boolean
expected_data: Record<string, OfferDataType>
label: string label: string
noffer: string noffer: string
offer_id: string offer_id: string
payer_data: string[]
price_sats: number price_sats: number
rejectUnauthorized: boolean
token: string
updatedAtUnix: number
} }
export const OfferConfigOptionalFields: [] = [] export const OfferConfigOptionalFields: [] = []
export type OfferConfigOptions = OptionsBaseMessage & { export type OfferConfigOptions = OptionsBaseMessage & {
checkOptionalsAreSet?: [] checkOptionalsAreSet?: []
callback_url_CustomCheck?: (v: string) => boolean callback_url_CustomCheck?: (v: string) => boolean
createdAtUnix_CustomCheck?: (v: number) => boolean
default_offer_CustomCheck?: (v: boolean) => boolean default_offer_CustomCheck?: (v: boolean) => boolean
expected_data_CustomCheck?: (v: Record<string, OfferDataType>) => boolean
label_CustomCheck?: (v: string) => boolean label_CustomCheck?: (v: string) => boolean
noffer_CustomCheck?: (v: string) => boolean noffer_CustomCheck?: (v: string) => boolean
offer_id_CustomCheck?: (v: string) => boolean offer_id_CustomCheck?: (v: string) => boolean
payer_data_CustomCheck?: (v: string[]) => boolean
price_sats_CustomCheck?: (v: number) => boolean price_sats_CustomCheck?: (v: number) => boolean
rejectUnauthorized_CustomCheck?: (v: boolean) => boolean
token_CustomCheck?: (v: string) => boolean
updatedAtUnix_CustomCheck?: (v: number) => boolean
} }
export const OfferConfigValidate = (o?: OfferConfig, opts: OfferConfigOptions = {}, path: string = 'OfferConfig::root.'): Error | null => { export const OfferConfigValidate = (o?: OfferConfig, opts: OfferConfigOptions = {}, path: string = 'OfferConfig::root.'): Error | null => {
if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message') if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message')
@ -2779,14 +2790,12 @@ export const OfferConfigValidate = (o?: OfferConfig, opts: OfferConfigOptions =
if (typeof o.callback_url !== 'string') return new Error(`${path}.callback_url: is not a string`) if (typeof o.callback_url !== 'string') return new Error(`${path}.callback_url: is not a string`)
if (opts.callback_url_CustomCheck && !opts.callback_url_CustomCheck(o.callback_url)) return new Error(`${path}.callback_url: custom check failed`) if (opts.callback_url_CustomCheck && !opts.callback_url_CustomCheck(o.callback_url)) return new Error(`${path}.callback_url: custom check failed`)
if (typeof o.createdAtUnix !== 'number') return new Error(`${path}.createdAtUnix: is not a number`)
if (opts.createdAtUnix_CustomCheck && !opts.createdAtUnix_CustomCheck(o.createdAtUnix)) return new Error(`${path}.createdAtUnix: custom check failed`)
if (typeof o.default_offer !== 'boolean') return new Error(`${path}.default_offer: is not a boolean`) if (typeof o.default_offer !== 'boolean') return new Error(`${path}.default_offer: is not a boolean`)
if (opts.default_offer_CustomCheck && !opts.default_offer_CustomCheck(o.default_offer)) return new Error(`${path}.default_offer: custom check failed`) if (opts.default_offer_CustomCheck && !opts.default_offer_CustomCheck(o.default_offer)) return new Error(`${path}.default_offer: custom check failed`)
if (typeof o.expected_data !== 'object' || o.expected_data === null) return new Error(`${path}.expected_data: is not an object or is null`)
for (const key in o.expected_data) {
if (!enumCheckOfferDataType(o.expected_data[key])) return new Error(`${path}.expected_data['${key}']: is not a OfferDataType`)
}
if (typeof o.label !== 'string') return new Error(`${path}.label: is not a string`) if (typeof o.label !== 'string') return new Error(`${path}.label: is not a string`)
if (opts.label_CustomCheck && !opts.label_CustomCheck(o.label)) return new Error(`${path}.label: custom check failed`) if (opts.label_CustomCheck && !opts.label_CustomCheck(o.label)) return new Error(`${path}.label: custom check failed`)
@ -2796,9 +2805,24 @@ export const OfferConfigValidate = (o?: OfferConfig, opts: OfferConfigOptions =
if (typeof o.offer_id !== 'string') return new Error(`${path}.offer_id: is not a string`) if (typeof o.offer_id !== 'string') return new Error(`${path}.offer_id: is not a string`)
if (opts.offer_id_CustomCheck && !opts.offer_id_CustomCheck(o.offer_id)) return new Error(`${path}.offer_id: custom check failed`) if (opts.offer_id_CustomCheck && !opts.offer_id_CustomCheck(o.offer_id)) return new Error(`${path}.offer_id: custom check failed`)
if (!Array.isArray(o.payer_data)) return new Error(`${path}.payer_data: is not an array`)
for (let index = 0; index < o.payer_data.length; index++) {
if (typeof o.payer_data[index] !== 'string') return new Error(`${path}.payer_data[${index}]: is not a string`)
}
if (opts.payer_data_CustomCheck && !opts.payer_data_CustomCheck(o.payer_data)) return new Error(`${path}.payer_data: custom check failed`)
if (typeof o.price_sats !== 'number') return new Error(`${path}.price_sats: is not a number`) if (typeof o.price_sats !== 'number') return new Error(`${path}.price_sats: is not a number`)
if (opts.price_sats_CustomCheck && !opts.price_sats_CustomCheck(o.price_sats)) return new Error(`${path}.price_sats: custom check failed`) if (opts.price_sats_CustomCheck && !opts.price_sats_CustomCheck(o.price_sats)) return new Error(`${path}.price_sats: custom check failed`)
if (typeof o.rejectUnauthorized !== 'boolean') return new Error(`${path}.rejectUnauthorized: is not a boolean`)
if (opts.rejectUnauthorized_CustomCheck && !opts.rejectUnauthorized_CustomCheck(o.rejectUnauthorized)) return new Error(`${path}.rejectUnauthorized: custom check failed`)
if (typeof o.token !== 'string') return new Error(`${path}.token: is not a string`)
if (opts.token_CustomCheck && !opts.token_CustomCheck(o.token)) return new Error(`${path}.token: custom check failed`)
if (typeof o.updatedAtUnix !== 'number') return new Error(`${path}.updatedAtUnix: is not a number`)
if (opts.updatedAtUnix_CustomCheck && !opts.updatedAtUnix_CustomCheck(o.updatedAtUnix)) return new Error(`${path}.updatedAtUnix: custom check failed`)
return null return null
} }

View file

@ -377,6 +377,9 @@ message AddAppUserInvoiceRequest {
NewInvoiceRequest invoice_req = 4; NewInvoiceRequest invoice_req = 4;
optional PayerData payer_data = 5; optional PayerData payer_data = 5;
optional string offer_string = 6; optional string offer_string = 6;
optional bool rejectUnauthorized = 7;
optional string token = 8;
} }
message GetAppUserRequest { message GetAppUserRequest {
@ -753,9 +756,6 @@ message DebitResponse {
} }
} }
enum OfferDataType {
DATA_STRING = 0;
}
message OfferId { message OfferId {
string offer_id = 1; string offer_id = 1;
@ -766,9 +766,13 @@ message OfferConfig {
string label = 2; string label = 2;
int64 price_sats = 3; int64 price_sats = 3;
string callback_url = 4; string callback_url = 4;
map<string, OfferDataType> expected_data = 5; repeated string payer_data = 5;
string noffer = 6; string noffer = 6;
bool default_offer = 7; bool default_offer = 7;
string token = 8;
bool rejectUnauthorized = 9;
int64 createdAtUnix = 10;
int64 updatedAtUnix = 11;
} }
message UserOffers { message UserOffers {

View file

@ -193,7 +193,8 @@ export default class {
} }
const opts: InboundOptionals = { const opts: InboundOptionals = {
callbackUrl: cbUrl, expiry: defaultInvoiceExpiry, expectedPayer: payer.user, linkedApplication: app, zapInfo, callbackUrl: cbUrl, expiry: defaultInvoiceExpiry, expectedPayer: payer.user, linkedApplication: app, zapInfo,
offerId: req.offer_string, payerData: req.payer_data?.data offerId: req.offer_string, payerData: req.payer_data?.data, rejectUnauthorized: req.rejectUnauthorized,
token: req.token
} }
const appUserInvoice = await this.paymentManager.NewInvoice(receiver.user.user_id, req.invoice_req, opts) const appUserInvoice = await this.paymentManager.NewInvoice(receiver.user.user_id, req.invoice_req, opts)
return { return {

View file

@ -24,8 +24,10 @@ import { Unlocker } from "./unlocker.js"
import { defaultInvoiceExpiry } from "../storage/paymentStorage.js" import { defaultInvoiceExpiry } from "../storage/paymentStorage.js"
import { DebitManager } from "./debitManager.js" import { DebitManager } from "./debitManager.js"
import { OfferManager } from "./offerManager.js" import { OfferManager } from "./offerManager.js"
import { parse } from "uri-template"
import webRTC from "../webRTC/index.js" import webRTC from "../webRTC/index.js"
import { ManagementManager } from "./managementManager.js" import { ManagementManager } from "./managementManager.js"
import { Agent } from "https"
type UserOperationsSub = { type UserOperationsSub = {
id: string id: string
@ -265,7 +267,7 @@ export default class {
if (fee > 0) { if (fee > 0) {
await this.storage.userStorage.IncrementUserBalance(userInvoice.linkedApplication.owner.user_id, fee, 'fees', tx) await this.storage.userStorage.IncrementUserBalance(userInvoice.linkedApplication.owner.user_id, fee, 'fees', tx)
} }
await this.triggerPaidCallback(log, userInvoice.callbackUrl, { invoice: paymentRequest, amount, other: userInvoice.payer_data }) await this.triggerPaidCallback(log, userInvoice.callbackUrl, { invoice: paymentRequest, amount, payerData: userInvoice.payer_data, token: userInvoice.bearer_token, rejectUnauthorized: userInvoice.rejectUnauthorized })
const operationId = `${Types.UserOperationType.INCOMING_INVOICE}-${userInvoice.serial_id}` const operationId = `${Types.UserOperationType.INCOMING_INVOICE}-${userInvoice.serial_id}`
const op = { amount, paidAtUnix: Date.now() / 1000, inbound: true, type: Types.UserOperationType.INCOMING_INVOICE, identifier: userInvoice.invoice, operationId, network_fee: 0, service_fee: fee, confirmed: true, tx_hash: "", internal } const op = { amount, paidAtUnix: Date.now() / 1000, inbound: true, type: Types.UserOperationType.INCOMING_INVOICE, identifier: userInvoice.invoice, operationId, network_fee: 0, service_fee: fee, confirmed: true, tx_hash: "", internal }
this.sendOperationToNostr(userInvoice.linkedApplication, userInvoice.user.user_id, op) this.sendOperationToNostr(userInvoice.linkedApplication, userInvoice.user.user_id, op)
@ -283,21 +285,67 @@ export default class {
}) })
} }
async triggerPaidCallback(log: PubLogger, url: string, { invoice, amount, other }: { invoice: string, amount: number, other?: Record<string, string> }) { async triggerPaidCallback(log: PubLogger, url: string,
{ invoice, amount, payerData, token, rejectUnauthorized }:
{ invoice: string,
amount: number,
payerData?: Record<string, string>,
token?: string,
rejectUnauthorized?: boolean
}
) {
if (!url) { if (!url) {
return return
} }
let finalUrl = url.replace(`%[invoice]`, invoice).replace(`%[amount]`, amount.toString()) let finalUrl = "";
if (other) { const payerDataToExpand = {
for (const [key, value] of Object.entries(other)) { amount,
finalUrl = finalUrl.replace(`%[${key}]`, value) invoice,
} ...(payerData !== undefined ? payerData : {})
} };
try { try {
const parsed = parse(url);
finalUrl = parsed.expand(payerDataToExpand)
} catch (err: any) {
log(ERROR, "error expanding callback url template for invoice", err?.message || "");
return;
}
const symbol = finalUrl.includes('?') ? "&" : "?" const symbol = finalUrl.includes('?') ? "&" : "?"
finalUrl = finalUrl + symbol + "ok=true" finalUrl = finalUrl + symbol + "ok=true"
/*
* Construct URL to find protocol.
* If it's https we then use an agent
* with the passed rejectUnauthorized
* value.
* If it's http we don't use an agent.
* If it's neither we log error and
* return.
*/
let parsedUrl: URL | null = null;
let agent: Agent | undefined;
try {
parsedUrl = new URL(finalUrl);
} catch (err: any) {
log(ERROR, "error parsing callback url for invoice", err?.message || "");
return;
}
if (parsedUrl.protocol === "https:") {
agent = new Agent({
rejectUnauthorized
})
} else if (parsedUrl.protocol === "http:") {
agent = undefined
} else {
log(ERROR, "callback url's protocol is neither http or https");
return;
}
const headers = {
...(token ? { Authorization: `Bearer ${token}` } : {})
}
try {
log("sending paid callback to", finalUrl) log("sending paid callback to", finalUrl)
await fetch(finalUrl) await fetch(finalUrl, { agent, headers })
} catch (err: any) { } catch (err: any) {
log(ERROR, "error sending paid callback for invoice", err.message || "") log(ERROR, "error sending paid callback for invoice", err.message || "")
} }

View file

@ -150,7 +150,7 @@ export class ManagementManager {
label: offer.label, label: offer.label,
price_sats: offer.price_sats, price_sats: offer.price_sats,
callback_url: offer.callback_url, callback_url: offer.callback_url,
payer_data: Object.keys(offer.expected_data || {}), payer_data: offer.payer_data || [],
noffer: nofferEncode(pointer), noffer: nofferEncode(pointer),
} }
} }
@ -229,15 +229,11 @@ export class ManagementManager {
if (validateResult.state !== 'success') { if (validateResult.state !== 'success') {
return validateResult return validateResult
} }
const dataMap: Record<string, Types.OfferDataType> = {}
nmanageReq.offer.fields.payer_data.forEach(data => {
dataMap[data] = Types.OfferDataType.DATA_STRING
})
const offer = await this.storage.offerStorage.AddUserOffer(appUserId, { const offer = await this.storage.offerStorage.AddUserOffer(appUserId, {
label: nmanageReq.offer.fields.label, label: nmanageReq.offer.fields.label,
callback_url: nmanageReq.offer.fields.callback_url, callback_url: nmanageReq.offer.fields.callback_url,
price_sats: nmanageReq.offer.fields.price_sats, price_sats: nmanageReq.offer.fields.price_sats,
expected_data: dataMap, payer_data: nmanageReq.offer.fields.payer_data,
management_pubkey: requestorPub, management_pubkey: requestorPub,
}) })
return { state: 'success', result: offer } return { state: 'success', result: offer }
@ -288,18 +284,16 @@ export class ManagementManager {
if (validateResult.state !== 'success') { if (validateResult.state !== 'success') {
return validateResult return validateResult
} }
const dataMap: Record<string, Types.OfferDataType> = {}
for (const data of nmanageReq.offer.fields.payer_data || []) { for (const data of nmanageReq.offer.fields.payer_data || []) {
if (typeof data !== 'string') { if (typeof data !== 'string') {
return { state: 'error', err: { res: 'GFY', code: 5, error: 'Invalid Field/Value', field: 'payer_data' } } return { state: 'error', err: { res: 'GFY', code: 5, error: 'Invalid Field/Value', field: 'payer_data' } }
} }
dataMap[data] = Types.OfferDataType.DATA_STRING
} }
await this.storage.offerStorage.UpdateUserOffer(offer.result.app_user_id, nmanageReq.offer.id, { await this.storage.offerStorage.UpdateUserOffer(offer.result.app_user_id, nmanageReq.offer.id, {
label: nmanageReq.offer.fields.label, label: nmanageReq.offer.fields.label,
callback_url: nmanageReq.offer.fields.callback_url, callback_url: nmanageReq.offer.fields.callback_url,
price_sats: nmanageReq.offer.fields.price_sats, price_sats: nmanageReq.offer.fields.price_sats,
expected_data: dataMap, payer_data: nmanageReq.offer.fields.payer_data,
}) })
const updatedOffer = await this.storage.offerStorage.GetOffer(nmanageReq.offer.id) const updatedOffer = await this.storage.offerStorage.GetOffer(nmanageReq.offer.id)
if (!updatedOffer) { if (!updatedOffer) {

View file

@ -12,15 +12,6 @@ import { NofferData, OfferPriceType, nofferEncode } from '@shocknet/clink-sdk';
import { MainSettings } from "./settings.js"; import { MainSettings } from "./settings.js";
const mapToOfferConfig = (appUserId: string, offer: UserOffer, { pubkey, relay }: { pubkey: string, relay: string }): Types.OfferConfig => { const mapToOfferConfig = (appUserId: string, offer: UserOffer, { pubkey, relay }: { pubkey: string, relay: string }): Types.OfferConfig => {
if (offer.expected_data) {
const keys = Object.keys(offer.expected_data)
for (const key of keys) {
const v = offer.expected_data[key] as Types.OfferDataType
if (!Types.OfferDataType[v]) {
offer.expected_data[key] = Types.OfferDataType.DATA_STRING
}
}
}
const offerStr = offer.offer_id const offerStr = offer.offer_id
const priceType: OfferPriceType = offer.price_sats === 0 ? OfferPriceType.Spontaneous : OfferPriceType.Fixed const priceType: OfferPriceType = offer.price_sats === 0 ? OfferPriceType.Spontaneous : OfferPriceType.Fixed
const noffer = nofferEncode({ pubkey, offer: offerStr, priceType, relay, price: offer.price_sats || undefined }) const noffer = nofferEncode({ pubkey, offer: offerStr, priceType, relay, price: offer.price_sats || undefined })
@ -28,10 +19,14 @@ const mapToOfferConfig = (appUserId: string, offer: UserOffer, { pubkey, relay }
label: offer.label, label: offer.label,
price_sats: offer.price_sats, price_sats: offer.price_sats,
callback_url: offer.callback_url, callback_url: offer.callback_url,
expected_data: (offer.expected_data || {}) as Record<string, Types.OfferDataType>, payer_data: offer.payer_data || [],
offer_id: offer.offer_id, offer_id: offer.offer_id,
noffer: noffer, noffer: noffer,
default_offer: appUserId === offer.app_user_id default_offer: appUserId === offer.app_user_id,
createdAtUnix: offer.created_at.getTime(),
updatedAtUnix: offer.updated_at.getTime(),
token: offer.bearer_token,
rejectUnauthorized: offer.rejectUnauthorized
} }
} }
export class OfferManager { export class OfferManager {
@ -66,7 +61,7 @@ export class OfferManager {
async AddUserOffer(ctx: Types.UserContext, req: Types.OfferConfig): Promise<Types.OfferId> { async AddUserOffer(ctx: Types.UserContext, req: Types.OfferConfig): Promise<Types.OfferId> {
const newOffer = await this.storage.offerStorage.AddUserOffer(ctx.app_user_id, { const newOffer = await this.storage.offerStorage.AddUserOffer(ctx.app_user_id, {
expected_data: req.expected_data, payer_data: req.payer_data,
label: req.label, label: req.label,
price_sats: req.price_sats, price_sats: req.price_sats,
callback_url: req.callback_url, callback_url: req.callback_url,
@ -82,7 +77,7 @@ export class OfferManager {
async UpdateUserOffer(ctx: Types.UserContext, req: Types.OfferConfig) { async UpdateUserOffer(ctx: Types.UserContext, req: Types.OfferConfig) {
await this.storage.offerStorage.UpdateUserOffer(ctx.app_user_id, req.offer_id, { await this.storage.offerStorage.UpdateUserOffer(ctx.app_user_id, req.offer_id, {
expected_data: req.expected_data, payer_data: req.payer_data,
label: req.label, label: req.label,
price_sats: req.price_sats, price_sats: req.price_sats,
callback_url: req.callback_url, callback_url: req.callback_url,
@ -139,12 +134,8 @@ export class OfferManager {
} }
ValidateExpectedData(userOffer: UserOffer, payerData: any): { passed: false, validated: undefined } | { passed: true, validated: Record<string, string> } { ValidateExpectedData(userOffer: UserOffer, payerData: any): { passed: false, validated: undefined } | { passed: true, validated: Record<string, string> } {
const expected = userOffer.expected_data const expectedKeys = userOffer.payer_data
if (!expected) { if (!expectedKeys || expectedKeys.length === 0) {
return { passed: true, validated: {} }
}
const expectedKeys = Object.keys(expected)
if (expectedKeys.length === 0) {
return { passed: true, validated: {} } return { passed: true, validated: {} }
} }
if (typeof payerData !== 'object' || payerData === null) { if (typeof payerData !== 'object' || payerData === null) {
@ -193,11 +184,11 @@ export class OfferManager {
return this.HandleDefaultUserOffer(offerReq, appId, remote) return this.HandleDefaultUserOffer(offerReq, appId, remote)
} }
if (userOffer.app_user_id === userOffer.offer_id) { if (userOffer.app_user_id === userOffer.offer_id) {
if (userOffer.price_sats !== 0 || userOffer.expected_data) { if (userOffer.price_sats !== 0 || userOffer.payer_data) {
this.logger("default offer has custom price or expected data, resetting") this.logger("default offer has custom price or expected data, resetting")
await this.storage.offerStorage.UpdateUserOffer(userOffer.app_user_id, userOffer.offer_id, { price_sats: 0, expected_data: null }) await this.storage.offerStorage.UpdateUserOffer(userOffer.app_user_id, userOffer.offer_id, { price_sats: 0, payer_data: null })
userOffer.price_sats = 0 userOffer.price_sats = 0
userOffer.expected_data = null userOffer.payer_data = null
} }
} }
let amt = userOffer.price_sats let amt = userOffer.price_sats
@ -216,7 +207,9 @@ export class OfferManager {
http_callback_url: userOffer.callback_url, payer_identifier: userOffer.app_user_id, receiver_identifier: userOffer.app_user_id, http_callback_url: userOffer.callback_url, payer_identifier: userOffer.app_user_id, receiver_identifier: userOffer.app_user_id,
invoice_req: { amountSats: amt, memo: userOffer.label, zap: offerReq.zap }, invoice_req: { amountSats: amt, memo: userOffer.label, zap: offerReq.zap },
payer_data: validated ? { data: validated } : undefined, payer_data: validated ? { data: validated } : undefined,
offer_string: offer offer_string: offer,
rejectUnauthorized: userOffer.rejectUnauthorized,
token: userOffer.bearer_token
}) })
return { success: true, invoice: res.invoice } return { success: true, invoice: res.invoice }
} }

View file

@ -30,7 +30,14 @@ export class UserOffer {
type: 'simple-json', type: 'simple-json',
default: null default: null
}) })
expected_data: Record<string, string> | null payer_data: string[] | null
@Column({ default: "" })
bearer_token: string
@Column({ default: true })
rejectUnauthorized: boolean
@CreateDateColumn() @CreateDateColumn()
created_at: Date created_at: Date

View file

@ -64,6 +64,13 @@ export class UserReceivingInvoice {
}) })
payer_data?: Record<string, string> payer_data?: Record<string, string>
@Column({ default: true })
rejectUnauthorized: boolean
@Column({ default: "" })
bearer_token: string
@Column({ default: "" }) @Column({ default: "" })
offer_id?: string offer_id?: string

View file

@ -0,0 +1,36 @@
import { MigrationInterface, QueryRunner } from "typeorm";
export class InvoiceCallbackUrls1752425992291 implements MigrationInterface {
name = 'InvoiceCallbackUrls1752425992291'
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`DROP INDEX "IDX_a131e6b58f084f1340538681b5"`);
await queryRunner.query(`CREATE TABLE "temporary_user_receiving_invoice" ("serial_id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "invoice" varchar NOT NULL, "expires_at_unix" integer NOT NULL, "paid_at_unix" integer NOT NULL DEFAULT (0), "internal" boolean NOT NULL DEFAULT (0), "paidByLnd" boolean NOT NULL DEFAULT (0), "callbackUrl" varchar NOT NULL DEFAULT (''), "paid_amount" integer NOT NULL DEFAULT (0), "service_fee" integer NOT NULL DEFAULT (0), "zap_info" text, "created_at" datetime NOT NULL DEFAULT (datetime('now')), "updated_at" datetime NOT NULL DEFAULT (datetime('now')), "userSerialId" integer, "productProductId" varchar, "payerSerialId" integer, "linkedApplicationSerialId" integer, "liquidityProvider" varchar, "payer_data" text, "offer_id" varchar NOT NULL DEFAULT (''), "rejectUnauthorized" boolean NOT NULL DEFAULT (1), "bearer_token" varchar NOT NULL DEFAULT (''), CONSTRAINT "FK_714a8b7d4f89f8a802ca181b789" FOREIGN KEY ("linkedApplicationSerialId") REFERENCES "application" ("serial_id") ON DELETE NO ACTION ON UPDATE NO ACTION, CONSTRAINT "FK_d4bb1e4c60e8a869f1f43ca2e31" FOREIGN KEY ("payerSerialId") REFERENCES "user" ("serial_id") ON DELETE NO ACTION ON UPDATE NO ACTION, CONSTRAINT "FK_5263bde2a519db9ea608b702ec8" FOREIGN KEY ("productProductId") REFERENCES "product" ("product_id") ON DELETE NO ACTION ON UPDATE NO ACTION, CONSTRAINT "FK_2c0dfb3483f3e5e7e3cdd5dc71f" FOREIGN KEY ("userSerialId") REFERENCES "user" ("serial_id") ON DELETE NO ACTION ON UPDATE NO ACTION)`);
await queryRunner.query(`INSERT INTO "temporary_user_receiving_invoice"("serial_id", "invoice", "expires_at_unix", "paid_at_unix", "internal", "paidByLnd", "callbackUrl", "paid_amount", "service_fee", "zap_info", "created_at", "updated_at", "userSerialId", "productProductId", "payerSerialId", "linkedApplicationSerialId", "liquidityProvider", "payer_data", "offer_id") SELECT "serial_id", "invoice", "expires_at_unix", "paid_at_unix", "internal", "paidByLnd", "callbackUrl", "paid_amount", "service_fee", "zap_info", "created_at", "updated_at", "userSerialId", "productProductId", "payerSerialId", "linkedApplicationSerialId", "liquidityProvider", "payer_data", "offer_id" FROM "user_receiving_invoice"`);
await queryRunner.query(`DROP TABLE "user_receiving_invoice"`);
await queryRunner.query(`ALTER TABLE "temporary_user_receiving_invoice" RENAME TO "user_receiving_invoice"`);
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_a131e6b58f084f1340538681b5" ON "user_receiving_invoice" ("invoice") `);
await queryRunner.query(`CREATE TABLE "temporary_user_offer" ("serial_id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "app_user_id" varchar NOT NULL, "offer_id" varchar NOT NULL, "label" varchar NOT NULL, "price_sats" integer NOT NULL DEFAULT (0), "callback_url" varchar NOT NULL DEFAULT (''), "created_at" datetime NOT NULL DEFAULT (datetime('now')), "updated_at" datetime NOT NULL DEFAULT (datetime('now')), "management_pubkey" varchar NOT NULL DEFAULT (''), "payer_data" text, "bearer_token" varchar NOT NULL DEFAULT (''), "rejectUnauthorized" boolean NOT NULL DEFAULT (1), CONSTRAINT "UQ_478f72095abd8a516d3a309a5c5" UNIQUE ("offer_id"))`);
await queryRunner.query(`INSERT INTO "temporary_user_offer"("serial_id", "app_user_id", "offer_id", "label", "price_sats", "callback_url", "created_at", "updated_at", "management_pubkey") SELECT "serial_id", "app_user_id", "offer_id", "label", "price_sats", "callback_url", "created_at", "updated_at", "management_pubkey" FROM "user_offer"`);
await queryRunner.query(`DROP TABLE "user_offer"`);
await queryRunner.query(`ALTER TABLE "temporary_user_offer" RENAME TO "user_offer"`);
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`DROP INDEX "IDX_a131e6b58f084f1340538681b5"`);
await queryRunner.query(`ALTER TABLE "user_receiving_invoice" RENAME TO "temporary_user_receiving_invoice"`);
await queryRunner.query(`CREATE TABLE "user_receiving_invoice" ("serial_id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "invoice" varchar NOT NULL, "expires_at_unix" integer NOT NULL, "paid_at_unix" integer NOT NULL DEFAULT (0), "internal" boolean NOT NULL DEFAULT (0), "paidByLnd" boolean NOT NULL DEFAULT (0), "callbackUrl" varchar NOT NULL DEFAULT (''), "paid_amount" integer NOT NULL DEFAULT (0), "service_fee" integer NOT NULL DEFAULT (0), "zap_info" text, "created_at" datetime NOT NULL DEFAULT (datetime('now')), "updated_at" datetime NOT NULL DEFAULT (datetime('now')), "userSerialId" integer, "productProductId" varchar, "payerSerialId" integer, "linkedApplicationSerialId" integer, "liquidityProvider" varchar, "payer_data" text, "offer_id" varchar NOT NULL DEFAULT (''), CONSTRAINT "FK_714a8b7d4f89f8a802ca181b789" FOREIGN KEY ("linkedApplicationSerialId") REFERENCES "application" ("serial_id") ON DELETE NO ACTION ON UPDATE NO ACTION, CONSTRAINT "FK_d4bb1e4c60e8a869f1f43ca2e31" FOREIGN KEY ("payerSerialId") REFERENCES "user" ("serial_id") ON DELETE NO ACTION ON UPDATE NO ACTION, CONSTRAINT "FK_5263bde2a519db9ea608b702ec8" FOREIGN KEY ("productProductId") REFERENCES "product" ("product_id") ON DELETE NO ACTION ON UPDATE NO ACTION, CONSTRAINT "FK_2c0dfb3483f3e5e7e3cdd5dc71f" FOREIGN KEY ("userSerialId") REFERENCES "user" ("serial_id") ON DELETE NO ACTION ON UPDATE NO ACTION)`);
await queryRunner.query(`INSERT INTO "user_receiving_invoice"("serial_id", "invoice", "expires_at_unix", "paid_at_unix", "internal", "paidByLnd", "callbackUrl", "paid_amount", "service_fee", "zap_info", "created_at", "updated_at", "userSerialId", "productProductId", "payerSerialId", "linkedApplicationSerialId", "liquidityProvider", "payer_data", "offer_id") SELECT "serial_id", "invoice", "expires_at_unix", "paid_at_unix", "internal", "paidByLnd", "callbackUrl", "paid_amount", "service_fee", "zap_info", "created_at", "updated_at", "userSerialId", "productProductId", "payerSerialId", "linkedApplicationSerialId", "liquidityProvider", "payer_data", "offer_id" FROM "temporary_user_receiving_invoice"`);
await queryRunner.query(`DROP TABLE "temporary_user_receiving_invoice"`);
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_a131e6b58f084f1340538681b5" ON "user_receiving_invoice" ("invoice") `);
await queryRunner.query(`ALTER TABLE "user_offer" RENAME TO "temporary_user_offer"`);
await queryRunner.query(`CREATE TABLE "user_offer" ("serial_id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "app_user_id" varchar NOT NULL, "offer_id" varchar NOT NULL, "label" varchar NOT NULL, "price_sats" integer NOT NULL DEFAULT (0), "callback_url" varchar NOT NULL DEFAULT (''), "expected_data" text, "created_at" datetime NOT NULL DEFAULT (datetime('now')), "updated_at" datetime NOT NULL DEFAULT (datetime('now')), "management_pubkey" varchar NOT NULL DEFAULT (''), CONSTRAINT "UQ_478f72095abd8a516d3a309a5c5" UNIQUE ("offer_id"))`);
await queryRunner.query(`INSERT INTO "user_offer"("serial_id", "app_user_id", "offer_id", "label", "price_sats", "callback_url", "created_at", "updated_at", "management_pubkey") SELECT "serial_id", "app_user_id", "offer_id", "label", "price_sats", "callback_url", "created_at", "updated_at", "management_pubkey" FROM "temporary_user_offer"`);
await queryRunner.query(`DROP TABLE "temporary_user_offer"`);
}
}

View file

@ -19,9 +19,10 @@ import { RootOpsTime1745428134124 } from './1745428134124-root_ops_time.js'
import { ChannelEvents1750777346411 } from './1750777346411-channel_events.js' import { ChannelEvents1750777346411 } from './1750777346411-channel_events.js'
import { ManagementGrant1751307732346 } from './1751307732346-management_grant.js' import { ManagementGrant1751307732346 } from './1751307732346-management_grant.js'
import { ManagementGrantBanned1751989251513 } from './1751989251513-management_grant_banned.js' import { ManagementGrantBanned1751989251513 } from './1751989251513-management_grant_banned.js'
import { InvoiceCallbackUrls1752425992291 } from './1752425992291-invoice_callback_urls.js'
export const allMigrations = [Initial1703170309875, LspOrder1718387847693, LiquidityProvider1719335699480, LndNodeInfo1720187506189, export const allMigrations = [Initial1703170309875, LspOrder1718387847693, LiquidityProvider1719335699480, LndNodeInfo1720187506189,
TrackedProvider1720814323679, CreateInviteTokenTable1721751414878, PaymentIndex1721760297610, DebitAccess1726496225078, DebitAccessFixes1726685229264, TrackedProvider1720814323679, CreateInviteTokenTable1721751414878, PaymentIndex1721760297610, DebitAccess1726496225078, DebitAccessFixes1726685229264,
DebitToPub1727105758354, UserCbUrl1727112281043, UserOffer1733502626042, ManagementGrant1751307732346, ManagementGrantBanned1751989251513] DebitToPub1727105758354, UserCbUrl1727112281043, UserOffer1733502626042, ManagementGrant1751307732346, ManagementGrantBanned1751989251513, InvoiceCallbackUrls1752425992291]
export const allMetricsMigrations = [LndMetrics1703170330183, ChannelRouting1709316653538, HtlcCount1724266887195, BalanceEvents1724860966825, RootOps1732566440447, RootOpsTime1745428134124, ChannelEvents1750777346411] export const allMetricsMigrations = [LndMetrics1703170330183, ChannelRouting1709316653538, HtlcCount1724266887195, BalanceEvents1724860966825, RootOps1732566440447, RootOpsTime1745428134124, ChannelEvents1750777346411]
/* export const TypeOrmMigrationRunner = async (log: PubLogger, storageManager: Storage, settings: DbSettings, arg: string | undefined): Promise<boolean> => { /* export const TypeOrmMigrationRunner = async (log: PubLogger, storageManager: Storage, settings: DbSettings, arg: string | undefined): Promise<boolean> => {
await connectAndMigrate(log, storageManager, allMigrations, allMetricsMigrations) await connectAndMigrate(log, storageManager, allMigrations, allMetricsMigrations)

View file

@ -14,7 +14,7 @@ import { Application } from './entity/Application.js';
import TransactionsQueue from "./db/transactionsQueue.js"; import TransactionsQueue from "./db/transactionsQueue.js";
import { LoggedEvent } from './eventsLog.js'; import { LoggedEvent } from './eventsLog.js';
import { StorageInterface } from './db/storageInterface.js'; import { StorageInterface } from './db/storageInterface.js';
export type InboundOptionals = { product?: Product, callbackUrl?: string, expiry: number, expectedPayer?: User, linkedApplication?: Application, zapInfo?: ZapInfo, offerId?: string, payerData?: Record<string, string> } export type InboundOptionals = { product?: Product, callbackUrl?: string, expiry: number, expectedPayer?: User, linkedApplication?: Application, zapInfo?: ZapInfo, offerId?: string, payerData?: Record<string, string> , rejectUnauthorized?: boolean, token?: string}
export const defaultInvoiceExpiry = 60 * 60 export const defaultInvoiceExpiry = 60 * 60
export default class { export default class {
dbs: StorageInterface dbs: StorageInterface
@ -102,6 +102,8 @@ export default class {
liquidityProvider: providerDestination, liquidityProvider: providerDestination,
offer_id: options.offerId, offer_id: options.offerId,
payer_data: options.payerData, payer_data: options.payerData,
rejectUnauthorized: options.rejectUnauthorized,
bearer_token: options.token
}, txId) }, txId)
} }