app metrics
This commit is contained in:
parent
f0dd9a08ac
commit
7e1157caa4
16 changed files with 3056 additions and 2462 deletions
|
|
@ -141,13 +141,20 @@ The nostr server will send back a message response, and inside the body there wi
|
||||||
- input: [AuthAppRequest](#AuthAppRequest)
|
- input: [AuthAppRequest](#AuthAppRequest)
|
||||||
- output: [AuthApp](#AuthApp)
|
- output: [AuthApp](#AuthApp)
|
||||||
|
|
||||||
- GetMetrics
|
- GetUsageMetrics
|
||||||
- auth type: __Admin__
|
- auth type: __Admin__
|
||||||
- http method: __post__
|
- http method: __post__
|
||||||
- http route: __/api/admin/metrics__
|
- http route: __/api/admin/metrics/usage__
|
||||||
- This methods has an __empty__ __request__ body
|
- This methods has an __empty__ __request__ body
|
||||||
- output: [UsageMetrics](#UsageMetrics)
|
- output: [UsageMetrics](#UsageMetrics)
|
||||||
|
|
||||||
|
- GetAppsMetrics
|
||||||
|
- auth type: __Admin__
|
||||||
|
- http method: __post__
|
||||||
|
- http route: __/api/admin/metrics/apps__
|
||||||
|
- input: [AppsMetricsRequest](#AppsMetricsRequest)
|
||||||
|
- output: [AppsMetrics](#AppsMetrics)
|
||||||
|
|
||||||
- Health
|
- Health
|
||||||
- auth type: __Guest__
|
- auth type: __Guest__
|
||||||
- http method: __get__
|
- http method: __get__
|
||||||
|
|
@ -414,105 +421,7 @@ The nostr server will send back a message response, and inside the body there wi
|
||||||
## Messages
|
## Messages
|
||||||
### The content of requests and response from the methods
|
### The content of requests and response from the methods
|
||||||
|
|
||||||
### NewAddressRequest
|
### PayInvoiceRequest
|
||||||
- __addressType__: _[AddressType](#AddressType)_
|
|
||||||
|
|
||||||
### DecodeInvoiceResponse
|
|
||||||
- __amount__: _number_
|
|
||||||
|
|
||||||
### Product
|
|
||||||
- __id__: _string_
|
|
||||||
- __name__: _string_
|
|
||||||
- __price_sats__: _number_
|
|
||||||
|
|
||||||
### MigrationUpdate
|
|
||||||
- __closure__: _[ClosureMigration](#ClosureMigration)_ *this field is optional
|
|
||||||
- __relays__: _[RelaysMigration](#RelaysMigration)_ *this field is optional
|
|
||||||
|
|
||||||
### AuthAppRequest
|
|
||||||
- __name__: _string_
|
|
||||||
- __allow_user_creation__: _boolean_ *this field is optional
|
|
||||||
|
|
||||||
### LnurlWithdrawInfoResponse
|
|
||||||
- __tag__: _string_
|
|
||||||
- __callback__: _string_
|
|
||||||
- __k1__: _string_
|
|
||||||
- __defaultDescription__: _string_
|
|
||||||
- __minWithdrawable__: _number_
|
|
||||||
- __maxWithdrawable__: _number_
|
|
||||||
- __balanceCheck__: _string_
|
|
||||||
- __payLink__: _string_
|
|
||||||
|
|
||||||
### ClosureMigration
|
|
||||||
- __closes_at_unix__: _number_
|
|
||||||
|
|
||||||
### SetMockAppBalanceRequest
|
|
||||||
- __amount__: _number_
|
|
||||||
|
|
||||||
### SendAppUserToAppPaymentRequest
|
|
||||||
- __from_user_identifier__: _string_
|
|
||||||
- __amount__: _number_
|
|
||||||
|
|
||||||
### NewInvoiceResponse
|
|
||||||
- __invoice__: _string_
|
|
||||||
|
|
||||||
### LnurlLinkResponse
|
|
||||||
- __lnurl__: _string_
|
|
||||||
- __k1__: _string_
|
|
||||||
|
|
||||||
### AddProductRequest
|
|
||||||
- __name__: _string_
|
|
||||||
- __price_sats__: _number_
|
|
||||||
|
|
||||||
### AddAppInvoiceRequest
|
|
||||||
- __payer_identifier__: _string_
|
|
||||||
- __http_callback_url__: _string_
|
|
||||||
- __invoice_req__: _[NewInvoiceRequest](#NewInvoiceRequest)_
|
|
||||||
|
|
||||||
### AddAppRequest
|
|
||||||
- __name__: _string_
|
|
||||||
- __allow_user_creation__: _boolean_
|
|
||||||
|
|
||||||
### PayAddressRequest
|
|
||||||
- __address__: _string_
|
|
||||||
- __amoutSats__: _number_
|
|
||||||
- __satsPerVByte__: _number_
|
|
||||||
|
|
||||||
### PayInvoiceResponse
|
|
||||||
- __preimage__: _string_
|
|
||||||
- __amount_paid__: _number_
|
|
||||||
- __operation_id__: _string_
|
|
||||||
- __service_fee__: _number_
|
|
||||||
- __network_fee__: _number_
|
|
||||||
|
|
||||||
### OpenChannelRequest
|
|
||||||
- __destination__: _string_
|
|
||||||
- __fundingAmount__: _number_
|
|
||||||
- __pushAmount__: _number_
|
|
||||||
- __closeAddress__: _string_
|
|
||||||
|
|
||||||
### LnurlPayInfoResponse
|
|
||||||
- __tag__: _string_
|
|
||||||
- __callback__: _string_
|
|
||||||
- __maxSendable__: _number_
|
|
||||||
- __minSendable__: _number_
|
|
||||||
- __metadata__: _string_
|
|
||||||
- __allowsNostr__: _boolean_
|
|
||||||
- __nostrPubkey__: _string_
|
|
||||||
|
|
||||||
### HandleLnurlPayResponse
|
|
||||||
- __pr__: _string_
|
|
||||||
- __routes__: ARRAY of: _[Empty](#Empty)_
|
|
||||||
|
|
||||||
### GetUserOperationsRequest
|
|
||||||
- __latestIncomingInvoice__: _number_
|
|
||||||
- __latestOutgoingInvoice__: _number_
|
|
||||||
- __latestIncomingTx__: _number_
|
|
||||||
- __latestOutgoingTx__: _number_
|
|
||||||
- __latestIncomingUserToUserPayment__: _number_
|
|
||||||
- __latestOutgoingUserToUserPayment__: _number_
|
|
||||||
|
|
||||||
### SetMockInvoiceAsPaidRequest
|
|
||||||
- __invoice__: _string_
|
- __invoice__: _string_
|
||||||
- __amount__: _number_
|
- __amount__: _number_
|
||||||
|
|
||||||
|
|
@ -527,49 +436,124 @@ The nostr server will send back a message response, and inside the body there wi
|
||||||
- __network_fee__: _number_
|
- __network_fee__: _number_
|
||||||
- __confirmed__: _boolean_
|
- __confirmed__: _boolean_
|
||||||
|
|
||||||
### OpenChannelResponse
|
|
||||||
- __channelId__: _string_
|
|
||||||
|
|
||||||
### UserOperations
|
### UserOperations
|
||||||
- __fromIndex__: _number_
|
- __fromIndex__: _number_
|
||||||
- __toIndex__: _number_
|
- __toIndex__: _number_
|
||||||
- __operations__: ARRAY of: _[UserOperation](#UserOperation)_
|
- __operations__: ARRAY of: _[UserOperation](#UserOperation)_
|
||||||
|
|
||||||
### AuthApp
|
### RelaysMigration
|
||||||
- __app__: _[Application](#Application)_
|
- __relays__: ARRAY of: _string_
|
||||||
- __auth_token__: _string_
|
|
||||||
|
|
||||||
### UsageMetrics
|
### AddAppRequest
|
||||||
- __metrics__: ARRAY of: _[UsageMetric](#UsageMetric)_
|
|
||||||
|
|
||||||
### Application
|
|
||||||
- __name__: _string_
|
- __name__: _string_
|
||||||
- __id__: _string_
|
- __allow_user_creation__: _boolean_
|
||||||
- __balance__: _number_
|
|
||||||
- __npub__: _string_
|
|
||||||
|
|
||||||
### AddAppUserRequest
|
### AddAppUserRequest
|
||||||
- __identifier__: _string_
|
- __identifier__: _string_
|
||||||
- __fail_if_exists__: _boolean_
|
- __fail_if_exists__: _boolean_
|
||||||
- __balance__: _number_
|
- __balance__: _number_
|
||||||
|
|
||||||
### AddAppUserInvoiceRequest
|
### OpenChannelResponse
|
||||||
- __receiver_identifier__: _string_
|
- __channelId__: _string_
|
||||||
- __payer_identifier__: _string_
|
|
||||||
- __http_callback_url__: _string_
|
|
||||||
- __invoice_req__: _[NewInvoiceRequest](#NewInvoiceRequest)_
|
|
||||||
|
|
||||||
### GetAppUserRequest
|
### SetMockInvoiceAsPaidRequest
|
||||||
|
- __invoice__: _string_
|
||||||
|
- __amount__: _number_
|
||||||
|
|
||||||
|
### AuthApp
|
||||||
|
- __app__: _[Application](#Application)_
|
||||||
|
- __auth_token__: _string_
|
||||||
|
|
||||||
|
### GetAppUserLNURLInfoRequest
|
||||||
- __user_identifier__: _string_
|
- __user_identifier__: _string_
|
||||||
|
- __base_url_override__: _string_
|
||||||
|
|
||||||
|
### PayAddressRequest
|
||||||
|
- __address__: _string_
|
||||||
|
- __amoutSats__: _number_
|
||||||
|
- __satsPerVByte__: _number_
|
||||||
|
|
||||||
|
### NewAddressResponse
|
||||||
|
- __address__: _string_
|
||||||
|
|
||||||
|
### PayAddressResponse
|
||||||
|
- __txId__: _string_
|
||||||
|
- __operation_id__: _string_
|
||||||
|
- __service_fee__: _number_
|
||||||
|
- __network_fee__: _number_
|
||||||
|
|
||||||
|
### DecodeInvoiceRequest
|
||||||
|
- __invoice__: _string_
|
||||||
|
|
||||||
|
### LnurlWithdrawInfoResponse
|
||||||
|
- __tag__: _string_
|
||||||
|
- __callback__: _string_
|
||||||
|
- __k1__: _string_
|
||||||
|
- __defaultDescription__: _string_
|
||||||
|
- __minWithdrawable__: _number_
|
||||||
|
- __maxWithdrawable__: _number_
|
||||||
|
- __balanceCheck__: _string_
|
||||||
|
- __payLink__: _string_
|
||||||
|
|
||||||
|
### MigrationUpdate
|
||||||
|
- __closure__: _[ClosureMigration](#ClosureMigration)_ *this field is optional
|
||||||
|
- __relays__: _[RelaysMigration](#RelaysMigration)_ *this field is optional
|
||||||
|
|
||||||
|
### UsageMetrics
|
||||||
|
- __metrics__: ARRAY of: _[UsageMetric](#UsageMetric)_
|
||||||
|
|
||||||
|
### AppsMetricsRequest
|
||||||
|
- __from_unix__: _number_ *this field is optional
|
||||||
|
- __to_unix__: _number_ *this field is optional
|
||||||
|
- __big_user_sats__: _number_ *this field is optional
|
||||||
|
- __huge_user_sats__: _number_ *this field is optional
|
||||||
|
- __include_operations__: _boolean_ *this field is optional
|
||||||
|
|
||||||
### SendAppUserToAppUserPaymentRequest
|
### SendAppUserToAppUserPaymentRequest
|
||||||
- __from_user_identifier__: _string_
|
- __from_user_identifier__: _string_
|
||||||
- __to_user_identifier__: _string_
|
- __to_user_identifier__: _string_
|
||||||
- __amount__: _number_
|
- __amount__: _number_
|
||||||
|
|
||||||
### GetAppUserLNURLInfoRequest
|
### LnurlPayInfoResponse
|
||||||
|
- __tag__: _string_
|
||||||
|
- __callback__: _string_
|
||||||
|
- __maxSendable__: _number_
|
||||||
|
- __minSendable__: _number_
|
||||||
|
- __metadata__: _string_
|
||||||
|
- __allowsNostr__: _boolean_
|
||||||
|
- __nostrPubkey__: _string_
|
||||||
|
|
||||||
|
### AppMetrics
|
||||||
|
- __app_name__: _string_
|
||||||
|
- __app_id__: _string_
|
||||||
|
- __app_npub__: _string_
|
||||||
|
- __app_balance__: _number_
|
||||||
|
- __total_received__: _number_
|
||||||
|
- __total_spent__: _number_
|
||||||
|
- __total_available__: _number_
|
||||||
|
- __total_users__: _number_
|
||||||
|
- __total_big_users__: _number_
|
||||||
|
- __total_huge_users__: _number_
|
||||||
|
- __unpaid_invoices__: _number_
|
||||||
|
- __unpaid_addresses__: _number_
|
||||||
|
- __operations__: ARRAY of: _[UserOperation](#UserOperation)_
|
||||||
|
|
||||||
|
### PayAppUserInvoiceRequest
|
||||||
- __user_identifier__: _string_
|
- __user_identifier__: _string_
|
||||||
- __base_url_override__: _string_
|
- __invoice__: _string_
|
||||||
|
- __amount__: _number_
|
||||||
|
|
||||||
|
### LiveUserOperation
|
||||||
|
- __operation__: _[UserOperation](#UserOperation)_
|
||||||
|
|
||||||
|
### NewInvoiceRequest
|
||||||
|
- __amountSats__: _number_
|
||||||
|
- __memo__: _string_
|
||||||
|
|
||||||
|
### Product
|
||||||
|
- __id__: _string_
|
||||||
|
- __name__: _string_
|
||||||
|
- __price_sats__: _number_
|
||||||
|
|
||||||
### UsageMetric
|
### UsageMetric
|
||||||
- __processed_at_nano__: _string_
|
- __processed_at_nano__: _string_
|
||||||
|
|
@ -581,17 +565,97 @@ The nostr server will send back a message response, and inside the body there wi
|
||||||
- __batch__: _boolean_
|
- __batch__: _boolean_
|
||||||
- __nostr__: _boolean_
|
- __nostr__: _boolean_
|
||||||
- __batch_size__: _number_
|
- __batch_size__: _number_
|
||||||
- __success__: _boolean_
|
|
||||||
- __app_id__: _string_
|
|
||||||
|
|
||||||
### PayAddressResponse
|
### AppsMetrics
|
||||||
- __txId__: _string_
|
- __apps__: ARRAY of: _[AppMetrics](#AppMetrics)_
|
||||||
|
|
||||||
|
### Application
|
||||||
|
- __name__: _string_
|
||||||
|
- __id__: _string_
|
||||||
|
- __balance__: _number_
|
||||||
|
- __npub__: _string_
|
||||||
|
|
||||||
|
### LndGetInfoRequest
|
||||||
|
- __nodeId__: _number_
|
||||||
|
|
||||||
|
### SendAppUserToAppPaymentRequest
|
||||||
|
- __from_user_identifier__: _string_
|
||||||
|
- __amount__: _number_
|
||||||
|
|
||||||
|
### NewInvoiceResponse
|
||||||
|
- __invoice__: _string_
|
||||||
|
|
||||||
|
### HandleLnurlPayResponse
|
||||||
|
- __pr__: _string_
|
||||||
|
- __routes__: ARRAY of: _[Empty](#Empty)_
|
||||||
|
|
||||||
|
### LndGetInfoResponse
|
||||||
|
- __alias__: _string_
|
||||||
|
|
||||||
|
### Empty
|
||||||
|
|
||||||
|
### AuthAppRequest
|
||||||
|
- __name__: _string_
|
||||||
|
- __allow_user_creation__: _boolean_ *this field is optional
|
||||||
|
|
||||||
|
### AddProductRequest
|
||||||
|
- __name__: _string_
|
||||||
|
- __price_sats__: _number_
|
||||||
|
|
||||||
|
### LnurlLinkResponse
|
||||||
|
- __lnurl__: _string_
|
||||||
|
- __k1__: _string_
|
||||||
|
|
||||||
|
### UserInfo
|
||||||
|
- __userId__: _string_
|
||||||
|
- __balance__: _number_
|
||||||
|
- __max_withdrawable__: _number_
|
||||||
|
|
||||||
|
### ClosureMigration
|
||||||
|
- __closes_at_unix__: _number_
|
||||||
|
|
||||||
|
### GetAppUserRequest
|
||||||
|
- __user_identifier__: _string_
|
||||||
|
|
||||||
|
### DecodeInvoiceResponse
|
||||||
|
- __amount__: _number_
|
||||||
|
|
||||||
|
### SetMockAppBalanceRequest
|
||||||
|
- __amount__: _number_
|
||||||
|
|
||||||
|
### EncryptionExchangeRequest
|
||||||
|
- __publicKey__: _string_
|
||||||
|
- __deviceId__: _string_
|
||||||
|
|
||||||
|
### AddAppUserInvoiceRequest
|
||||||
|
- __receiver_identifier__: _string_
|
||||||
|
- __payer_identifier__: _string_
|
||||||
|
- __http_callback_url__: _string_
|
||||||
|
- __invoice_req__: _[NewInvoiceRequest](#NewInvoiceRequest)_
|
||||||
|
|
||||||
|
### PayInvoiceResponse
|
||||||
|
- __preimage__: _string_
|
||||||
|
- __amount_paid__: _number_
|
||||||
- __operation_id__: _string_
|
- __operation_id__: _string_
|
||||||
- __service_fee__: _number_
|
- __service_fee__: _number_
|
||||||
- __network_fee__: _number_
|
- __network_fee__: _number_
|
||||||
|
|
||||||
### DecodeInvoiceRequest
|
### GetUserOperationsRequest
|
||||||
- __invoice__: _string_
|
- __latestIncomingInvoice__: _number_
|
||||||
|
- __latestOutgoingInvoice__: _number_
|
||||||
|
- __latestIncomingTx__: _number_
|
||||||
|
- __latestOutgoingTx__: _number_
|
||||||
|
- __latestIncomingUserToUserPayment__: _number_
|
||||||
|
- __latestOutgoingUserToUserPayment__: _number_
|
||||||
|
|
||||||
|
### NewAddressRequest
|
||||||
|
- __addressType__: _[AddressType](#AddressType)_
|
||||||
|
|
||||||
|
### OpenChannelRequest
|
||||||
|
- __destination__: _string_
|
||||||
|
- __fundingAmount__: _number_
|
||||||
|
- __pushAmount__: _number_
|
||||||
|
- __closeAddress__: _string_
|
||||||
|
|
||||||
### GetUserOperationsResponse
|
### GetUserOperationsResponse
|
||||||
- __latestOutgoingInvoiceOperations__: _[UserOperations](#UserOperations)_
|
- __latestOutgoingInvoiceOperations__: _[UserOperations](#UserOperations)_
|
||||||
|
|
@ -601,56 +665,22 @@ The nostr server will send back a message response, and inside the body there wi
|
||||||
- __latestOutgoingUserToUserPayemnts__: _[UserOperations](#UserOperations)_
|
- __latestOutgoingUserToUserPayemnts__: _[UserOperations](#UserOperations)_
|
||||||
- __latestIncomingUserToUserPayemnts__: _[UserOperations](#UserOperations)_
|
- __latestIncomingUserToUserPayemnts__: _[UserOperations](#UserOperations)_
|
||||||
|
|
||||||
### NewAddressResponse
|
|
||||||
- __address__: _string_
|
|
||||||
|
|
||||||
### PayAppUserInvoiceRequest
|
|
||||||
- __user_identifier__: _string_
|
|
||||||
- __invoice__: _string_
|
|
||||||
- __amount__: _number_
|
|
||||||
|
|
||||||
### SetMockAppUserBalanceRequest
|
|
||||||
- __user_identifier__: _string_
|
|
||||||
- __amount__: _number_
|
|
||||||
|
|
||||||
### NewInvoiceRequest
|
|
||||||
- __amountSats__: _number_
|
|
||||||
- __memo__: _string_
|
|
||||||
|
|
||||||
### GetProductBuyLinkResponse
|
### GetProductBuyLinkResponse
|
||||||
- __link__: _string_
|
- __link__: _string_
|
||||||
|
|
||||||
### Empty
|
|
||||||
|
|
||||||
### LndGetInfoRequest
|
|
||||||
- __nodeId__: _number_
|
|
||||||
|
|
||||||
### LndGetInfoResponse
|
|
||||||
- __alias__: _string_
|
|
||||||
|
|
||||||
### AppUser
|
### AppUser
|
||||||
- __identifier__: _string_
|
- __identifier__: _string_
|
||||||
- __info__: _[UserInfo](#UserInfo)_
|
- __info__: _[UserInfo](#UserInfo)_
|
||||||
- __max_withdrawable__: _number_
|
- __max_withdrawable__: _number_
|
||||||
|
|
||||||
### PayInvoiceRequest
|
### AddAppInvoiceRequest
|
||||||
- __invoice__: _string_
|
- __payer_identifier__: _string_
|
||||||
|
- __http_callback_url__: _string_
|
||||||
|
- __invoice_req__: _[NewInvoiceRequest](#NewInvoiceRequest)_
|
||||||
|
|
||||||
|
### SetMockAppUserBalanceRequest
|
||||||
|
- __user_identifier__: _string_
|
||||||
- __amount__: _number_
|
- __amount__: _number_
|
||||||
|
|
||||||
### UserInfo
|
|
||||||
- __userId__: _string_
|
|
||||||
- __balance__: _number_
|
|
||||||
- __max_withdrawable__: _number_
|
|
||||||
|
|
||||||
### LiveUserOperation
|
|
||||||
- __operation__: _[UserOperation](#UserOperation)_
|
|
||||||
|
|
||||||
### RelaysMigration
|
|
||||||
- __relays__: ARRAY of: _string_
|
|
||||||
|
|
||||||
### EncryptionExchangeRequest
|
|
||||||
- __publicKey__: _string_
|
|
||||||
- __deviceId__: _string_
|
|
||||||
## Enums
|
## Enums
|
||||||
### The enumerators used in the messages
|
### The enumerators used in the messages
|
||||||
|
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -98,20 +98,42 @@ export default (methods: Types.ServerMethods, opts: ServerOptions) => {
|
||||||
opts.metricsCallback([{ ...info, ...stats, ...authContext }])
|
opts.metricsCallback([{ ...info, ...stats, ...authContext }])
|
||||||
} catch (ex) { const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback); if (opts.throwErrors) throw e }
|
} catch (ex) { const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback); if (opts.throwErrors) throw e }
|
||||||
})
|
})
|
||||||
if (!opts.allowNotImplementedMethods && !methods.GetMetrics) throw new Error('method: GetMetrics is not implemented')
|
if (!opts.allowNotImplementedMethods && !methods.GetUsageMetrics) throw new Error('method: GetUsageMetrics is not implemented')
|
||||||
app.post('/api/admin/metrics', async (req, res) => {
|
app.post('/api/admin/metrics/usage', async (req, res) => {
|
||||||
const info: Types.RequestInfo = { rpcName: 'GetMetrics', batch: false, nostr: false, batchSize: 0}
|
const info: Types.RequestInfo = { rpcName: 'GetUsageMetrics', batch: false, nostr: false, batchSize: 0}
|
||||||
const stats: Types.RequestStats = { start:req.startTime || 0n, parse: process.hrtime.bigint(), guard: 0n, validate: 0n, handle: 0n }
|
const stats: Types.RequestStats = { start:req.startTime || 0n, parse: process.hrtime.bigint(), guard: 0n, validate: 0n, handle: 0n }
|
||||||
let authCtx: Types.AuthContext = {}
|
let authCtx: Types.AuthContext = {}
|
||||||
try {
|
try {
|
||||||
if (!methods.GetMetrics) throw new Error('method: GetMetrics is not implemented')
|
if (!methods.GetUsageMetrics) throw new Error('method: GetUsageMetrics is not implemented')
|
||||||
const authContext = await opts.AdminAuthGuard(req.headers['authorization'])
|
const authContext = await opts.AdminAuthGuard(req.headers['authorization'])
|
||||||
authCtx = authContext
|
authCtx = authContext
|
||||||
stats.guard = process.hrtime.bigint()
|
stats.guard = process.hrtime.bigint()
|
||||||
stats.validate = stats.guard
|
stats.validate = stats.guard
|
||||||
const query = req.query
|
const query = req.query
|
||||||
const params = req.params
|
const params = req.params
|
||||||
const response = await methods.GetMetrics({rpcName:'GetMetrics', ctx:authContext })
|
const response = await methods.GetUsageMetrics({rpcName:'GetUsageMetrics', ctx:authContext })
|
||||||
|
stats.handle = process.hrtime.bigint()
|
||||||
|
res.json({status: 'OK', ...response})
|
||||||
|
opts.metricsCallback([{ ...info, ...stats, ...authContext }])
|
||||||
|
} catch (ex) { const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback); if (opts.throwErrors) throw e }
|
||||||
|
})
|
||||||
|
if (!opts.allowNotImplementedMethods && !methods.GetAppsMetrics) throw new Error('method: GetAppsMetrics is not implemented')
|
||||||
|
app.post('/api/admin/metrics/apps', async (req, res) => {
|
||||||
|
const info: Types.RequestInfo = { rpcName: 'GetAppsMetrics', batch: false, nostr: false, batchSize: 0}
|
||||||
|
const stats: Types.RequestStats = { start:req.startTime || 0n, parse: process.hrtime.bigint(), guard: 0n, validate: 0n, handle: 0n }
|
||||||
|
let authCtx: Types.AuthContext = {}
|
||||||
|
try {
|
||||||
|
if (!methods.GetAppsMetrics) throw new Error('method: GetAppsMetrics is not implemented')
|
||||||
|
const authContext = await opts.AdminAuthGuard(req.headers['authorization'])
|
||||||
|
authCtx = authContext
|
||||||
|
stats.guard = process.hrtime.bigint()
|
||||||
|
const request = req.body
|
||||||
|
const error = Types.AppsMetricsRequestValidate(request)
|
||||||
|
stats.validate = process.hrtime.bigint()
|
||||||
|
if (error !== null) return logErrorAndReturnResponse(error, 'invalid request body', res, logger, { ...info, ...stats, ...authContext }, opts.metricsCallback)
|
||||||
|
const query = req.query
|
||||||
|
const params = req.params
|
||||||
|
const response = await methods.GetAppsMetrics({rpcName:'GetAppsMetrics', ctx:authContext , req: request})
|
||||||
stats.handle = process.hrtime.bigint()
|
stats.handle = process.hrtime.bigint()
|
||||||
res.json({status: 'OK', ...response})
|
res.json({status: 'OK', ...response})
|
||||||
opts.metricsCallback([{ ...info, ...stats, ...authContext }])
|
opts.metricsCallback([{ ...info, ...stats, ...authContext }])
|
||||||
|
|
|
||||||
|
|
@ -57,10 +57,10 @@ export default (params: ClientParams) => ({
|
||||||
}
|
}
|
||||||
return { status: 'ERROR', reason: 'invalid response' }
|
return { status: 'ERROR', reason: 'invalid response' }
|
||||||
},
|
},
|
||||||
GetMetrics: async (): Promise<ResultError | ({ status: 'OK' }& Types.UsageMetrics)> => {
|
GetUsageMetrics: async (): Promise<ResultError | ({ status: 'OK' }& Types.UsageMetrics)> => {
|
||||||
const auth = await params.retrieveAdminAuth()
|
const auth = await params.retrieveAdminAuth()
|
||||||
if (auth === null) throw new Error('retrieveAdminAuth() returned null')
|
if (auth === null) throw new Error('retrieveAdminAuth() returned null')
|
||||||
let finalRoute = '/api/admin/metrics'
|
let finalRoute = '/api/admin/metrics/usage'
|
||||||
const { data } = await axios.post(params.baseUrl + finalRoute, {}, { headers: { 'authorization': auth } })
|
const { data } = await axios.post(params.baseUrl + finalRoute, {}, { headers: { 'authorization': auth } })
|
||||||
if (data.status === 'ERROR' && typeof data.reason === 'string') return data
|
if (data.status === 'ERROR' && typeof data.reason === 'string') return data
|
||||||
if (data.status === 'OK') {
|
if (data.status === 'OK') {
|
||||||
|
|
@ -71,6 +71,20 @@ export default (params: ClientParams) => ({
|
||||||
}
|
}
|
||||||
return { status: 'ERROR', reason: 'invalid response' }
|
return { status: 'ERROR', reason: 'invalid response' }
|
||||||
},
|
},
|
||||||
|
GetAppsMetrics: async (request: Types.AppsMetricsRequest): Promise<ResultError | ({ status: 'OK' }& Types.AppsMetrics)> => {
|
||||||
|
const auth = await params.retrieveAdminAuth()
|
||||||
|
if (auth === null) throw new Error('retrieveAdminAuth() returned null')
|
||||||
|
let finalRoute = '/api/admin/metrics/apps'
|
||||||
|
const { data } = await axios.post(params.baseUrl + finalRoute, request, { headers: { 'authorization': auth } })
|
||||||
|
if (data.status === 'ERROR' && typeof data.reason === 'string') return data
|
||||||
|
if (data.status === 'OK') {
|
||||||
|
const result = data
|
||||||
|
if(!params.checkResult) return { status: 'OK', ...result }
|
||||||
|
const error = Types.AppsMetricsValidate(result)
|
||||||
|
if (error === null) { return { status: 'OK', ...result } } else return { status: 'ERROR', reason: error.message }
|
||||||
|
}
|
||||||
|
return { status: 'ERROR', reason: 'invalid response' }
|
||||||
|
},
|
||||||
Health: async (): Promise<ResultError | ({ status: 'OK' })> => {
|
Health: async (): Promise<ResultError | ({ status: 'OK' })> => {
|
||||||
const auth = await params.retrieveGuestAuth()
|
const auth = await params.retrieveGuestAuth()
|
||||||
if (auth === null) throw new Error('retrieveGuestAuth() returned null')
|
if (auth === null) throw new Error('retrieveGuestAuth() returned null')
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -97,10 +97,16 @@ service LightningPub {
|
||||||
option (http_route) = "/api/admin/app/auth";
|
option (http_route) = "/api/admin/app/auth";
|
||||||
}
|
}
|
||||||
|
|
||||||
rpc GetMetrics(structs.Empty) returns (structs.UsageMetrics) {
|
rpc GetUsageMetrics(structs.Empty) returns (structs.UsageMetrics) {
|
||||||
option (auth_type) = "Admin";
|
option (auth_type) = "Admin";
|
||||||
option (http_method) = "post";
|
option (http_method) = "post";
|
||||||
option (http_route) = "/api/admin/metrics";
|
option (http_route) = "/api/admin/metrics/usage";
|
||||||
|
}
|
||||||
|
|
||||||
|
rpc GetAppsMetrics(structs.AppsMetricsRequest) returns (structs.AppsMetrics) {
|
||||||
|
option (auth_type) = "Admin";
|
||||||
|
option (http_method) = "post";
|
||||||
|
option (http_route) = "/api/admin/metrics/apps";
|
||||||
}
|
}
|
||||||
// </Admin>
|
// </Admin>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,14 +22,44 @@ message UsageMetric {
|
||||||
bool batch = 7;
|
bool batch = 7;
|
||||||
bool nostr = 8;
|
bool nostr = 8;
|
||||||
int64 batch_size = 9;
|
int64 batch_size = 9;
|
||||||
bool success = 10;
|
|
||||||
string app_id = 11;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
message UsageMetrics {
|
message UsageMetrics {
|
||||||
repeated UsageMetric metrics = 1;
|
repeated UsageMetric metrics = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message AppsMetricsRequest {
|
||||||
|
optional int64 from_unix = 1;
|
||||||
|
optional int64 to_unix = 2;
|
||||||
|
optional int64 big_user_sats = 3;
|
||||||
|
optional int64 huge_user_sats = 4;
|
||||||
|
optional bool include_operations = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
message AppMetrics {
|
||||||
|
string app_name = 1;
|
||||||
|
string app_id = 2;
|
||||||
|
string app_npub = 3;
|
||||||
|
int64 app_balance = 4;
|
||||||
|
|
||||||
|
int64 total_received = 5;
|
||||||
|
int64 total_spent = 6;
|
||||||
|
int64 total_available = 7;
|
||||||
|
|
||||||
|
int64 total_users = 8;
|
||||||
|
int64 total_big_users = 9;
|
||||||
|
int64 total_huge_users = 10;
|
||||||
|
|
||||||
|
int64 unpaid_invoices = 11;
|
||||||
|
int64 unpaid_addresses = 12;
|
||||||
|
|
||||||
|
repeated UserOperation operations = 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
message AppsMetrics {
|
||||||
|
repeated AppMetrics apps = 1;
|
||||||
|
}
|
||||||
|
|
||||||
message LndGetInfoRequest {
|
message LndGetInfoRequest {
|
||||||
int64 nodeId = 1;
|
int64 nodeId = 1;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -58,7 +58,7 @@ export default class {
|
||||||
constructor(settings: MainSettings) {
|
constructor(settings: MainSettings) {
|
||||||
this.settings = settings
|
this.settings = settings
|
||||||
this.storage = new Storage(settings.storageSettings)
|
this.storage = new Storage(settings.storageSettings)
|
||||||
this.metricsManager = new MetricsManager()
|
this.metricsManager = new MetricsManager(this.storage)
|
||||||
this.lnd = NewLightningHandler(settings.lndSettings, this.addressPaidCb, this.invoicePaidCb, this.newBlockCb)
|
this.lnd = NewLightningHandler(settings.lndSettings, this.addressPaidCb, this.invoicePaidCb, this.newBlockCb)
|
||||||
|
|
||||||
this.paymentManager = new PaymentManager(this.storage, this.lnd, this.settings, this.addressPaidCb, this.invoicePaidCb)
|
this.paymentManager = new PaymentManager(this.storage, this.lnd, this.settings, this.addressPaidCb, this.invoicePaidCb)
|
||||||
|
|
|
||||||
|
|
@ -90,11 +90,13 @@ export default class {
|
||||||
|
|
||||||
async NewAddress(ctx: Types.UserContext, req: Types.NewAddressRequest): Promise<Types.NewAddressResponse> {
|
async NewAddress(ctx: Types.UserContext, req: Types.NewAddressRequest): Promise<Types.NewAddressResponse> {
|
||||||
const app = await this.storage.applicationStorage.GetApplication(ctx.app_id)
|
const app = await this.storage.applicationStorage.GetApplication(ctx.app_id)
|
||||||
|
const existingAddress = await this.storage.paymentStorage.GetExistingUserAddress(ctx.user_id, app)
|
||||||
|
if (existingAddress) {
|
||||||
|
return { address: existingAddress.address }
|
||||||
|
}
|
||||||
const res = await this.lnd.NewAddress(req.addressType)
|
const res = await this.lnd.NewAddress(req.addressType)
|
||||||
const userAddress = await this.storage.paymentStorage.AddUserAddress(ctx.user_id, res.address, { linkedApplication: app })
|
const userAddress = await this.storage.paymentStorage.AddUserAddress(ctx.user_id, res.address, { linkedApplication: app })
|
||||||
return {
|
return { address: userAddress.address }
|
||||||
address: userAddress.address
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async NewInvoice(userId: string, req: Types.NewInvoiceRequest, options: InboundOptionals = { expiry: defaultInvoiceExpiry }): Promise<Types.NewInvoiceResponse> {
|
async NewInvoice(userId: string, req: Types.NewInvoiceRequest, options: InboundOptionals = { expiry: defaultInvoiceExpiry }): Promise<Types.NewInvoiceResponse> {
|
||||||
|
|
@ -172,7 +174,7 @@ export default class {
|
||||||
await this.storage.userStorage.IncrementUserBalance(linkedApplication.owner.user_id, serviceFee)
|
await this.storage.userStorage.IncrementUserBalance(linkedApplication.owner.user_id, serviceFee)
|
||||||
}
|
}
|
||||||
const routingFees = payment ? payment.feeSat : 0
|
const routingFees = payment ? payment.feeSat : 0
|
||||||
const newPayment = await this.storage.paymentStorage.AddUserInvoicePayment(userId, req.invoice, payAmount, routingFees, serviceFee, !!internalInvoice)
|
const newPayment = await this.storage.paymentStorage.AddUserInvoicePayment(userId, req.invoice, payAmount, routingFees, serviceFee, !!internalInvoice, linkedApplication)
|
||||||
return {
|
return {
|
||||||
preimage: payment ? payment.paymentPreimage : "",
|
preimage: payment ? payment.paymentPreimage : "",
|
||||||
amount_paid: payment ? Number(payment.valueSat) : payAmount,
|
amount_paid: payment ? Number(payment.valueSat) : payAmount,
|
||||||
|
|
@ -215,7 +217,7 @@ export default class {
|
||||||
await this.storage.userStorage.IncrementUserBalance(app.owner.user_id, serviceFee)
|
await this.storage.userStorage.IncrementUserBalance(app.owner.user_id, serviceFee)
|
||||||
}
|
}
|
||||||
|
|
||||||
const newTx = await this.storage.paymentStorage.AddUserTransactionPayment(ctx.user_id, req.address, txId, 0, req.amoutSats, chainFees, serviceFee, !!internalAddress, blockHeight)
|
const newTx = await this.storage.paymentStorage.AddUserTransactionPayment(ctx.user_id, req.address, txId, 0, req.amoutSats, chainFees, serviceFee, !!internalAddress, blockHeight, app)
|
||||||
return {
|
return {
|
||||||
txId: txId,
|
txId: txId,
|
||||||
operation_id: `${Types.UserOperationType.OUTGOING_TX}-${newTx.serial_id}`,
|
operation_id: `${Types.UserOperationType.OUTGOING_TX}-${newTx.serial_id}`,
|
||||||
|
|
@ -471,7 +473,7 @@ export default class {
|
||||||
const toIncrement = amount - fee
|
const toIncrement = amount - fee
|
||||||
await this.storage.userStorage.DecrementUserBalance(fromUser.user_id, amount, tx)
|
await this.storage.userStorage.DecrementUserBalance(fromUser.user_id, amount, tx)
|
||||||
await this.storage.userStorage.IncrementUserBalance(toUser.user_id, toIncrement, tx)
|
await this.storage.userStorage.IncrementUserBalance(toUser.user_id, toIncrement, tx)
|
||||||
await this.storage.paymentStorage.AddUserToUserPayment(fromUserId, toUserId, amount, fee)
|
await this.storage.paymentStorage.AddUserToUserPayment(fromUserId, toUserId, amount, fee, linkedApplication)
|
||||||
if (isAppUserPayment && fee > 0) {
|
if (isAppUserPayment && fee > 0) {
|
||||||
await this.storage.userStorage.IncrementUserBalance(linkedApplication.owner.user_id, fee)
|
await this.storage.userStorage.IncrementUserBalance(linkedApplication.owner.user_id, fee)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,13 @@
|
||||||
import * as Types from '../../../proto/autogenerated/ts/types'
|
import Storage from '../storage/index.js'
|
||||||
|
import * as Types from '../../../proto/autogenerated/ts/types.js'
|
||||||
|
import { Application } from '../storage/entity/Application.js'
|
||||||
const maxEvents = 100_000
|
const maxEvents = 100_000
|
||||||
export default class Handler {
|
export default class Handler {
|
||||||
|
storage: Storage
|
||||||
metrics: Types.UsageMetric[] = []
|
metrics: Types.UsageMetric[] = []
|
||||||
|
constructor(storage: Storage) {
|
||||||
|
this.storage = storage
|
||||||
|
}
|
||||||
AddMetrics(newMetrics: (Types.RequestMetric & { app_id?: string })[]) {
|
AddMetrics(newMetrics: (Types.RequestMetric & { app_id?: string })[]) {
|
||||||
const parsed: Types.UsageMetric[] = newMetrics.map(m => ({
|
const parsed: Types.UsageMetric[] = newMetrics.map(m => ({
|
||||||
rpc_name: m.rpcName,
|
rpc_name: m.rpcName,
|
||||||
|
|
@ -21,9 +27,95 @@ export default class Handler {
|
||||||
this.metrics.splice(0, len - maxEvents)
|
this.metrics.splice(0, len - maxEvents)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
async GetMetrics(): Promise<Types.UsageMetrics> {
|
async GetUsageMetrics(): Promise<Types.UsageMetrics> {
|
||||||
return {
|
return {
|
||||||
metrics: this.metrics
|
metrics: this.metrics
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
async GetAppsMetrics(req: Types.AppsMetricsRequest): Promise<Types.AppsMetrics> {
|
||||||
|
const dbApps = await this.storage.applicationStorage.GetApplications()
|
||||||
|
const apps = await Promise.all(dbApps.map(app => this.GetAppMetrics(req, app)))
|
||||||
|
const unlinked = await this.GetAppMetrics(req, null)
|
||||||
|
apps.push(unlinked)
|
||||||
|
return {
|
||||||
|
apps
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async GetAppMetrics(req: Types.AppsMetricsRequest, app: Application | null): Promise<Types.AppMetrics> {
|
||||||
|
const { receivingInvoices, receivingTransactions, outgoingInvoices, outgoingTransactions, receivingAddresses, userToUser } = await this.storage.paymentStorage.GetAppOperations(app, { from: req.from_unix, to: req.to_unix })
|
||||||
|
const bigUser = req.big_user_sats ? req.big_user_sats : 10_000
|
||||||
|
const hugeUser = req.big_user_sats ? req.big_user_sats : 500_000
|
||||||
|
let totalReceived = 0
|
||||||
|
let totalSpent = 0
|
||||||
|
let totalAvailable = 0
|
||||||
|
let totalBigUsers = 0
|
||||||
|
let totalHugeUsers = 0
|
||||||
|
let unpaidInvoices = 0
|
||||||
|
let paidAddresses = 0
|
||||||
|
const operations: Types.UserOperation[] = []
|
||||||
|
receivingInvoices.forEach(i => {
|
||||||
|
if (i.paid_at_unix > 0) {
|
||||||
|
totalReceived += i.paid_amount
|
||||||
|
operations.push({ type: Types.UserOperationType.INCOMING_INVOICE, amount: i.paid_amount, inbound: true, paidAtUnix: i.paid_at_unix, confirmed: true, service_fee: i.service_fee, network_fee: 0, identifier: "", operationId: "" })
|
||||||
|
} else {
|
||||||
|
unpaidInvoices++
|
||||||
|
}
|
||||||
|
})
|
||||||
|
receivingTransactions.forEach(txs => {
|
||||||
|
if (txs.length > 0) {
|
||||||
|
paidAddresses++
|
||||||
|
} else {
|
||||||
|
txs.forEach(tx => {
|
||||||
|
operations.push({ type: Types.UserOperationType.INCOMING_TX, amount: tx.paid_amount, inbound: true, paidAtUnix: tx.paid_at_unix, confirmed: tx.confs > 1, service_fee: tx.service_fee, network_fee: 0, identifier: "", operationId: "" })
|
||||||
|
if (tx.confs > 1) {
|
||||||
|
totalReceived += tx.paid_amount
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
outgoingInvoices.forEach(i => {
|
||||||
|
operations.push({ type: Types.UserOperationType.OUTGOING_INVOICE, amount: i.paid_amount, inbound: false, paidAtUnix: i.paid_at_unix, confirmed: true, service_fee: i.service_fees, network_fee: i.routing_fees, identifier: "", operationId: "" })
|
||||||
|
totalSpent += i.paid_amount
|
||||||
|
})
|
||||||
|
outgoingTransactions.forEach(tx => {
|
||||||
|
operations.push({ type: Types.UserOperationType.OUTGOING_TX, amount: tx.paid_amount, inbound: false, paidAtUnix: tx.paid_at_unix, confirmed: tx.confs > 1, service_fee: tx.service_fees, network_fee: tx.chain_fees, identifier: "", operationId: "" })
|
||||||
|
totalSpent += tx.paid_amount
|
||||||
|
})
|
||||||
|
|
||||||
|
userToUser.forEach(op => {
|
||||||
|
operations.push({ type: Types.UserOperationType.INCOMING_USER_TO_USER, amount: op.paid_amount, inbound: true, paidAtUnix: op.paid_at_unix, confirmed: true, service_fee: op.service_fees, network_fee: 0, identifier: "", operationId: "" })
|
||||||
|
})
|
||||||
|
|
||||||
|
const users = await this.storage.applicationStorage.GetApplicationUsers(app, { from: req.from_unix, to: req.to_unix })
|
||||||
|
|
||||||
|
users.forEach(u => {
|
||||||
|
totalAvailable += u.user.balance_sats
|
||||||
|
if (u.user.balance_sats > bigUser) {
|
||||||
|
totalBigUsers++
|
||||||
|
}
|
||||||
|
if (u.user.balance_sats > hugeUser) {
|
||||||
|
totalHugeUsers++
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return {
|
||||||
|
app_name: app ? app.name : "unlinked to app",
|
||||||
|
app_id: app ? app.app_id : "unlinked",
|
||||||
|
app_npub: app ? (app.nostr_public_key || "") : "",
|
||||||
|
app_balance: app ? app.owner.balance_sats : 0,
|
||||||
|
|
||||||
|
total_received: totalReceived,
|
||||||
|
total_spent: totalSpent,
|
||||||
|
total_available: totalAvailable,
|
||||||
|
|
||||||
|
total_users: users.length,
|
||||||
|
total_big_users: totalBigUsers,
|
||||||
|
total_huge_users: totalHugeUsers,
|
||||||
|
|
||||||
|
unpaid_invoices: unpaidInvoices,
|
||||||
|
unpaid_addresses: receivingAddresses.length - paidAddresses,
|
||||||
|
|
||||||
|
operations
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -4,8 +4,11 @@ import main from '../main/index.js'
|
||||||
import Main from '../main/index.js'
|
import Main from '../main/index.js'
|
||||||
export default (mainHandler: Main): Types.ServerMethods => {
|
export default (mainHandler: Main): Types.ServerMethods => {
|
||||||
return {
|
return {
|
||||||
GetMetrics: async ({ ctx }) => {
|
GetUsageMetrics: async ({ ctx }) => {
|
||||||
return mainHandler.metricsManager.GetMetrics()
|
return mainHandler.metricsManager.GetUsageMetrics()
|
||||||
|
},
|
||||||
|
GetAppsMetrics: async ({ ctx, req }) => {
|
||||||
|
return mainHandler.metricsManager.GetAppsMetrics(req)
|
||||||
},
|
},
|
||||||
EncryptionExchange: async () => { },
|
EncryptionExchange: async () => { },
|
||||||
Health: async () => { await mainHandler.lnd.Health() },
|
Health: async () => { await mainHandler.lnd.Health() },
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import crypto from 'crypto';
|
import crypto from 'crypto';
|
||||||
import { DataSource, EntityManager } from "typeorm"
|
import { Between, DataSource, EntityManager, FindOperator, IsNull, LessThanOrEqual, MoreThanOrEqual } from "typeorm"
|
||||||
import { generatePrivateKey, getPublicKey } from 'nostr-tools';
|
import { generatePrivateKey, getPublicKey } from 'nostr-tools';
|
||||||
import { Application } from "./entity/Application.js"
|
import { Application } from "./entity/Application.js"
|
||||||
import UserStorage from './userStorage.js';
|
import UserStorage from './userStorage.js';
|
||||||
|
|
@ -123,6 +123,19 @@ export default class {
|
||||||
return found
|
return found
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async GetApplicationUsers(application: Application | null, { from, to }: { from?: number, to?: number }, entityManager = this.DB) {
|
||||||
|
const q = application ? { app_id: application.app_id } : IsNull()
|
||||||
|
let time: { created_at?: FindOperator<Date> } = {}
|
||||||
|
if (!!from && !!to) {
|
||||||
|
time.created_at = Between<Date>(new Date(from * 1000), new Date(to * 1000))
|
||||||
|
} else if (!!from) {
|
||||||
|
time.created_at = MoreThanOrEqual<Date>(new Date(from * 1000))
|
||||||
|
} else if (!!to) {
|
||||||
|
time.created_at = LessThanOrEqual<Date>(new Date(to * 1000))
|
||||||
|
}
|
||||||
|
return entityManager.getRepository(ApplicationUser).find({ where: { application: q, ...time } })
|
||||||
|
}
|
||||||
|
|
||||||
async GetAppUserFromUser(application: Application, userId: string, entityManager = this.DB): Promise<ApplicationUser | null> {
|
async GetAppUserFromUser(application: Application, userId: string, entityManager = this.DB): Promise<ApplicationUser | null> {
|
||||||
return await entityManager.getRepository(ApplicationUser).findOne({ where: { user: { user_id: userId }, application: { app_id: application.app_id } } })
|
return await entityManager.getRepository(ApplicationUser).findOne({ where: { user: { user_id: userId }, application: { app_id: application.app_id } } })
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import { Entity, PrimaryGeneratedColumn, Column, Index, Check, ManyToOne, JoinColumn, CreateDateColumn, UpdateDateColumn } from "typeorm"
|
import { Entity, PrimaryGeneratedColumn, Column, Index, Check, ManyToOne, JoinColumn, CreateDateColumn, UpdateDateColumn } from "typeorm"
|
||||||
import { User } from "./User.js"
|
import { User } from "./User.js"
|
||||||
|
import { Application } from "./Application.js"
|
||||||
|
|
||||||
@Entity()
|
@Entity()
|
||||||
export class UserInvoicePayment {
|
export class UserInvoicePayment {
|
||||||
|
|
@ -30,6 +31,9 @@ export class UserInvoicePayment {
|
||||||
@Column({ default: false })
|
@Column({ default: false })
|
||||||
internal: boolean
|
internal: boolean
|
||||||
|
|
||||||
|
@ManyToOne(type => Application, { eager: true })
|
||||||
|
linkedApplication: Application | null
|
||||||
|
|
||||||
@CreateDateColumn()
|
@CreateDateColumn()
|
||||||
created_at: Date
|
created_at: Date
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import { Entity, PrimaryGeneratedColumn, Column, Index, Check, ManyToOne, JoinColumn, CreateDateColumn, UpdateDateColumn } from "typeorm"
|
import { Entity, PrimaryGeneratedColumn, Column, Index, Check, ManyToOne, JoinColumn, CreateDateColumn, UpdateDateColumn } from "typeorm"
|
||||||
import { User } from "./User.js"
|
import { User } from "./User.js"
|
||||||
|
import { Application } from "./Application.js"
|
||||||
|
|
||||||
@Entity()
|
@Entity()
|
||||||
export class UserToUserPayment {
|
export class UserToUserPayment {
|
||||||
|
|
@ -24,6 +25,9 @@ export class UserToUserPayment {
|
||||||
@Column()
|
@Column()
|
||||||
paid_at_unix: number
|
paid_at_unix: number
|
||||||
|
|
||||||
|
@ManyToOne(type => Application, { eager: true })
|
||||||
|
linkedApplication: Application | null
|
||||||
|
|
||||||
@CreateDateColumn()
|
@CreateDateColumn()
|
||||||
created_at: Date
|
created_at: Date
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import { Entity, PrimaryGeneratedColumn, Column, Index, Check, ManyToOne, JoinColumn, CreateDateColumn, UpdateDateColumn } from "typeorm"
|
import { Entity, PrimaryGeneratedColumn, Column, Index, Check, ManyToOne, JoinColumn, CreateDateColumn, UpdateDateColumn } from "typeorm"
|
||||||
import { User } from "./User.js"
|
import { User } from "./User.js"
|
||||||
|
import { Application } from "./Application.js"
|
||||||
|
|
||||||
@Entity()
|
@Entity()
|
||||||
@Index("user_transaction_unique", ["tx_hash", "output_index"], { unique: true })
|
@Index("user_transaction_unique", ["tx_hash", "output_index"], { unique: true })
|
||||||
|
|
@ -42,6 +43,9 @@ export class UserTransactionPayment {
|
||||||
@Column({ default: 0 })
|
@Column({ default: 0 })
|
||||||
broadcast_height: number
|
broadcast_height: number
|
||||||
|
|
||||||
|
@ManyToOne(type => Application, { eager: true })
|
||||||
|
linkedApplication: Application | null
|
||||||
|
|
||||||
@CreateDateColumn()
|
@CreateDateColumn()
|
||||||
created_at: Date
|
created_at: Date
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import crypto from 'crypto';
|
import crypto from 'crypto';
|
||||||
import { DataSource, EntityManager, MoreThan, MoreThanOrEqual } from "typeorm"
|
import { Between, DataSource, EntityManager, FindOperator, IsNull, LessThanOrEqual, MoreThan, MoreThanOrEqual } from "typeorm"
|
||||||
import { User } from './entity/User.js';
|
import { User } from './entity/User.js';
|
||||||
import { UserTransactionPayment } from './entity/UserTransactionPayment.js';
|
import { UserTransactionPayment } from './entity/UserTransactionPayment.js';
|
||||||
import { EphemeralKeyType, UserEphemeralKey } from './entity/UserEphemeralKey.js';
|
import { EphemeralKeyType, UserEphemeralKey } from './entity/UserEphemeralKey.js';
|
||||||
|
|
@ -48,7 +48,9 @@ export default class {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async GetExistingUserAddress(userId: string, linkedApplication: Application, entityManager = this.DB) {
|
||||||
|
return entityManager.getRepository(UserReceivingAddress).findOne({ where: { user: { user_id: userId }, linkedApplication: { app_id: linkedApplication.app_id } } })
|
||||||
|
}
|
||||||
|
|
||||||
async AddUserAddress(userId: string, address: string, opts: { callbackUrl?: string, linkedApplication?: Application } = {}, entityManager = this.DB): Promise<UserReceivingAddress> {
|
async AddUserAddress(userId: string, address: string, opts: { callbackUrl?: string, linkedApplication?: Application } = {}, entityManager = this.DB): Promise<UserReceivingAddress> {
|
||||||
const newUserAddress = entityManager.getRepository(UserReceivingAddress).create({
|
const newUserAddress = entityManager.getRepository(UserReceivingAddress).create({
|
||||||
|
|
@ -113,7 +115,7 @@ export default class {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async AddUserInvoicePayment(userId: string, invoice: string, amount: number, routingFees: number, serviceFees: number, internal: boolean, entityManager = this.DB): Promise<UserInvoicePayment> {
|
async AddUserInvoicePayment(userId: string, invoice: string, amount: number, routingFees: number, serviceFees: number, internal: boolean, linkedApplication: Application, entityManager = this.DB): Promise<UserInvoicePayment> {
|
||||||
const newPayment = entityManager.getRepository(UserInvoicePayment).create({
|
const newPayment = entityManager.getRepository(UserInvoicePayment).create({
|
||||||
user: await this.userStorage.GetUser(userId),
|
user: await this.userStorage.GetUser(userId),
|
||||||
paid_amount: amount,
|
paid_amount: amount,
|
||||||
|
|
@ -121,7 +123,8 @@ export default class {
|
||||||
routing_fees: routingFees,
|
routing_fees: routingFees,
|
||||||
service_fees: serviceFees,
|
service_fees: serviceFees,
|
||||||
paid_at_unix: Math.floor(Date.now() / 1000),
|
paid_at_unix: Math.floor(Date.now() / 1000),
|
||||||
internal
|
internal,
|
||||||
|
linkedApplication
|
||||||
})
|
})
|
||||||
return entityManager.getRepository(UserInvoicePayment).save(newPayment)
|
return entityManager.getRepository(UserInvoicePayment).save(newPayment)
|
||||||
}
|
}
|
||||||
|
|
@ -141,7 +144,7 @@ export default class {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async AddUserTransactionPayment(userId: string, address: string, txHash: string, txOutput: number, amount: number, chainFees: number, serviceFees: number, internal: boolean, height: number, entityManager = this.DB): Promise<UserTransactionPayment> {
|
async AddUserTransactionPayment(userId: string, address: string, txHash: string, txOutput: number, amount: number, chainFees: number, serviceFees: number, internal: boolean, height: number, linkedApplication: Application, entityManager = this.DB): Promise<UserTransactionPayment> {
|
||||||
const newTx = entityManager.getRepository(UserTransactionPayment).create({
|
const newTx = entityManager.getRepository(UserTransactionPayment).create({
|
||||||
user: await this.userStorage.GetUser(userId),
|
user: await this.userStorage.GetUser(userId),
|
||||||
address,
|
address,
|
||||||
|
|
@ -153,7 +156,8 @@ export default class {
|
||||||
paid_at_unix: Math.floor(Date.now() / 1000),
|
paid_at_unix: Math.floor(Date.now() / 1000),
|
||||||
internal,
|
internal,
|
||||||
broadcast_height: height,
|
broadcast_height: height,
|
||||||
confs: internal ? 10 : 0
|
confs: internal ? 10 : 0,
|
||||||
|
linkedApplication
|
||||||
})
|
})
|
||||||
return entityManager.getRepository(UserTransactionPayment).save(newTx)
|
return entityManager.getRepository(UserTransactionPayment).save(newTx)
|
||||||
}
|
}
|
||||||
|
|
@ -217,13 +221,14 @@ export default class {
|
||||||
return found
|
return found
|
||||||
}
|
}
|
||||||
|
|
||||||
async AddUserToUserPayment(fromUserId: string, toUserId: string, amount: number, fee: number, entityManager = this.DB) {
|
async AddUserToUserPayment(fromUserId: string, toUserId: string, amount: number, fee: number, linkedApplication: Application, entityManager = this.DB) {
|
||||||
const newKey = entityManager.getRepository(UserToUserPayment).create({
|
const newKey = entityManager.getRepository(UserToUserPayment).create({
|
||||||
from_user: await this.userStorage.GetUser(fromUserId, entityManager),
|
from_user: await this.userStorage.GetUser(fromUserId, entityManager),
|
||||||
to_user: await this.userStorage.GetUser(toUserId, entityManager),
|
to_user: await this.userStorage.GetUser(toUserId, entityManager),
|
||||||
paid_at_unix: Math.floor(Date.now() / 1000),
|
paid_at_unix: Math.floor(Date.now() / 1000),
|
||||||
paid_amount: amount,
|
paid_amount: amount,
|
||||||
service_fees: fee
|
service_fees: fee,
|
||||||
|
linkedApplication
|
||||||
})
|
})
|
||||||
return entityManager.getRepository(UserToUserPayment).save(newKey)
|
return entityManager.getRepository(UserToUserPayment).save(newKey)
|
||||||
}
|
}
|
||||||
|
|
@ -258,4 +263,30 @@ export default class {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async GetAppOperations(application: Application | null, { from, to }: { from?: number, to?: number }, entityManager = this.DB) {
|
||||||
|
const q = application ? { app_id: application.app_id } : IsNull()
|
||||||
|
let time: { created_at?: FindOperator<Date> } = {}
|
||||||
|
if (!!from && !!to) {
|
||||||
|
time.created_at = Between<Date>(new Date(from * 1000), new Date(to * 1000))
|
||||||
|
} else if (!!from) {
|
||||||
|
time.created_at = MoreThanOrEqual<Date>(new Date(from * 1000))
|
||||||
|
} else if (!!to) {
|
||||||
|
time.created_at = LessThanOrEqual<Date>(new Date(to * 1000))
|
||||||
|
}
|
||||||
|
|
||||||
|
const [receivingInvoices, receivingAddresses, outgoingInvoices, outgoingTransactions, userToUser] = await Promise.all([
|
||||||
|
entityManager.getRepository(UserReceivingInvoice).find({ where: { linkedApplication: q, ...time } }),
|
||||||
|
entityManager.getRepository(UserReceivingAddress).find({ where: { linkedApplication: q, ...time } }),
|
||||||
|
entityManager.getRepository(UserInvoicePayment).find({ where: { linkedApplication: q, ...time } }),
|
||||||
|
entityManager.getRepository(UserTransactionPayment).find({ where: { linkedApplication: q, ...time } }),
|
||||||
|
entityManager.getRepository(UserToUserPayment).find({ where: { linkedApplication: q, ...time } })
|
||||||
|
])
|
||||||
|
const receivingTransactions = await Promise.all(receivingAddresses.map(addr => entityManager.getRepository(AddressReceivingTransaction).find({ where: { user_address: { serial_id: addr.serial_id } } })))
|
||||||
|
return {
|
||||||
|
receivingInvoices, receivingAddresses, receivingTransactions,
|
||||||
|
outgoingInvoices, outgoingTransactions,
|
||||||
|
userToUser
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue