wire localhost screens
This commit is contained in:
parent
c2cab40a2e
commit
a8d447110f
36 changed files with 6075 additions and 4966 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
|
@ -14,3 +14,5 @@ logs
|
||||||
data/
|
data/
|
||||||
.wallet_secret
|
.wallet_secret
|
||||||
.wallet_password
|
.wallet_password
|
||||||
|
.admin_enroll
|
||||||
|
admin.npub
|
||||||
|
|
@ -13,11 +13,51 @@ The nostr server will send back a message response, and inside the body there wi
|
||||||
## NOSTR Methods
|
## NOSTR Methods
|
||||||
### These are the nostr methods the client implements to communicate with the API via nostr
|
### These are the nostr methods the client implements to communicate with the API via nostr
|
||||||
|
|
||||||
|
- LndGetInfo
|
||||||
|
- auth type: __Admin__
|
||||||
|
- input: [LndGetInfoRequest](#LndGetInfoRequest)
|
||||||
|
- output: [LndGetInfoResponse](#LndGetInfoResponse)
|
||||||
|
|
||||||
|
- AddApp
|
||||||
|
- auth type: __Admin__
|
||||||
|
- input: [AddAppRequest](#AddAppRequest)
|
||||||
|
- output: [AuthApp](#AuthApp)
|
||||||
|
|
||||||
|
- AuthApp
|
||||||
|
- auth type: __Admin__
|
||||||
|
- input: [AuthAppRequest](#AuthAppRequest)
|
||||||
|
- output: [AuthApp](#AuthApp)
|
||||||
|
|
||||||
|
- BanUser
|
||||||
|
- auth type: __Admin__
|
||||||
|
- input: [BanUserRequest](#BanUserRequest)
|
||||||
|
- output: [BanUserResponse](#BanUserResponse)
|
||||||
|
|
||||||
|
- GetUsageMetrics
|
||||||
|
- auth type: __Metrics__
|
||||||
|
- This methods has an __empty__ __request__ body
|
||||||
|
- output: [UsageMetrics](#UsageMetrics)
|
||||||
|
|
||||||
|
- GetAppsMetrics
|
||||||
|
- auth type: __Metrics__
|
||||||
|
- input: [AppsMetricsRequest](#AppsMetricsRequest)
|
||||||
|
- output: [AppsMetrics](#AppsMetrics)
|
||||||
|
|
||||||
|
- GetLndMetrics
|
||||||
|
- auth type: __Metrics__
|
||||||
|
- input: [LndMetricsRequest](#LndMetricsRequest)
|
||||||
|
- output: [LndMetrics](#LndMetrics)
|
||||||
|
|
||||||
- LinkNPubThroughToken
|
- LinkNPubThroughToken
|
||||||
- auth type: __User__
|
- auth type: __User__
|
||||||
- input: [LinkNPubThroughTokenRequest](#LinkNPubThroughTokenRequest)
|
- input: [LinkNPubThroughTokenRequest](#LinkNPubThroughTokenRequest)
|
||||||
- This methods has an __empty__ __response__ body
|
- This methods has an __empty__ __response__ body
|
||||||
|
|
||||||
|
- EnrollAdminToken
|
||||||
|
- auth type: __User__
|
||||||
|
- input: [EnrollAdminTokenRequest](#EnrollAdminTokenRequest)
|
||||||
|
- This methods has an __empty__ __response__ body
|
||||||
|
|
||||||
- UserHealth
|
- UserHealth
|
||||||
- auth type: __User__
|
- auth type: __User__
|
||||||
- This methods has an __empty__ __request__ body
|
- This methods has an __empty__ __request__ body
|
||||||
|
|
@ -120,9 +160,9 @@ The nostr server will send back a message response, and inside the body there wi
|
||||||
|
|
||||||
- __User__:
|
- __User__:
|
||||||
- expected context content
|
- expected context content
|
||||||
|
- __user_id__: _string_
|
||||||
- __app_id__: _string_
|
- __app_id__: _string_
|
||||||
- __app_user_id__: _string_
|
- __app_user_id__: _string_
|
||||||
- __user_id__: _string_
|
|
||||||
|
|
||||||
- __Admin__:
|
- __Admin__:
|
||||||
- expected context content
|
- expected context content
|
||||||
|
|
@ -265,6 +305,13 @@ The nostr server will send back a message response, and inside the body there wi
|
||||||
- input: [LinkNPubThroughTokenRequest](#LinkNPubThroughTokenRequest)
|
- input: [LinkNPubThroughTokenRequest](#LinkNPubThroughTokenRequest)
|
||||||
- This methods has an __empty__ __response__ body
|
- This methods has an __empty__ __response__ body
|
||||||
|
|
||||||
|
- EnrollAdminToken
|
||||||
|
- auth type: __User__
|
||||||
|
- http method: __post__
|
||||||
|
- http route: __/api/guest/npub/enroll/admin__
|
||||||
|
- input: [EnrollAdminTokenRequest](#EnrollAdminTokenRequest)
|
||||||
|
- This methods has an __empty__ __response__ body
|
||||||
|
|
||||||
- GetApp
|
- GetApp
|
||||||
- auth type: __App__
|
- auth type: __App__
|
||||||
- http method: __post__
|
- http method: __post__
|
||||||
|
|
@ -482,47 +529,36 @@ 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
|
||||||
|
|
||||||
### LnurlLinkResponse
|
### Empty
|
||||||
- __lnurl__: _string_
|
|
||||||
- __k1__: _string_
|
|
||||||
|
|
||||||
### RelaysMigration
|
### LndMetricsRequest
|
||||||
- __relays__: ARRAY of: _string_
|
- __from_unix__: _number_ *this field is optional
|
||||||
|
- __to_unix__: _number_ *this field is optional
|
||||||
### RequestNPubLinkingTokenResponse
|
|
||||||
- __token__: _string_
|
|
||||||
|
|
||||||
### BannedAppUser
|
|
||||||
- __app_name__: _string_
|
|
||||||
- __app_id__: _string_
|
|
||||||
- __user_identifier__: _string_
|
|
||||||
- __nostr_pub__: _string_
|
|
||||||
|
|
||||||
### Application
|
|
||||||
- __name__: _string_
|
|
||||||
- __id__: _string_
|
|
||||||
- __balance__: _number_
|
|
||||||
- __npub__: _string_
|
|
||||||
|
|
||||||
### PayInvoiceResponse
|
|
||||||
- __preimage__: _string_
|
|
||||||
- __amount_paid__: _number_
|
|
||||||
- __operation_id__: _string_
|
|
||||||
- __service_fee__: _number_
|
|
||||||
- __network_fee__: _number_
|
|
||||||
|
|
||||||
### OpenChannelRequest
|
|
||||||
- __destination__: _string_
|
|
||||||
- __fundingAmount__: _number_
|
|
||||||
- __pushAmount__: _number_
|
|
||||||
- __closeAddress__: _string_
|
|
||||||
|
|
||||||
### LndMetrics
|
|
||||||
- __nodes__: ARRAY of: _[LndNodeMetrics](#LndNodeMetrics)_
|
|
||||||
|
|
||||||
### LndGetInfoResponse
|
### LndGetInfoResponse
|
||||||
- __alias__: _string_
|
- __alias__: _string_
|
||||||
|
|
||||||
|
### PayAppUserInvoiceRequest
|
||||||
|
- __user_identifier__: _string_
|
||||||
|
- __invoice__: _string_
|
||||||
|
- __amount__: _number_
|
||||||
|
|
||||||
|
### Product
|
||||||
|
- __id__: _string_
|
||||||
|
- __name__: _string_
|
||||||
|
- __price_sats__: _number_
|
||||||
|
|
||||||
|
### LndGetInfoRequest
|
||||||
|
- __nodeId__: _number_
|
||||||
|
|
||||||
|
### BanUserResponse
|
||||||
|
- __balance_sats__: _number_
|
||||||
|
- __banned_app_users__: ARRAY of: _[BannedAppUser](#BannedAppUser)_
|
||||||
|
|
||||||
|
### AuthAppRequest
|
||||||
|
- __name__: _string_
|
||||||
|
- __allow_user_creation__: _boolean_ *this field is optional
|
||||||
|
|
||||||
### PayAddressRequest
|
### PayAddressRequest
|
||||||
- __address__: _string_
|
- __address__: _string_
|
||||||
- __amoutSats__: _number_
|
- __amoutSats__: _number_
|
||||||
|
|
@ -533,69 +569,94 @@ The nostr server will send back a message response, and inside the body there wi
|
||||||
- __to_unix__: _number_ *this field is optional
|
- __to_unix__: _number_ *this field is optional
|
||||||
- __include_operations__: _boolean_ *this field is optional
|
- __include_operations__: _boolean_ *this field is optional
|
||||||
|
|
||||||
|
### AppsMetrics
|
||||||
|
- __apps__: ARRAY of: _[AppMetrics](#AppMetrics)_
|
||||||
|
|
||||||
### RoutingEvent
|
### RoutingEvent
|
||||||
|
- __timestamp_ns__: _number_
|
||||||
|
- __event_type__: _string_
|
||||||
|
- __settled__: _boolean_
|
||||||
|
- __offchain__: _boolean_
|
||||||
- __incoming_channel_id__: _number_
|
- __incoming_channel_id__: _number_
|
||||||
- __incoming_htlc_id__: _number_
|
- __incoming_htlc_id__: _number_
|
||||||
- __outgoing_channel_id__: _number_
|
- __outgoing_channel_id__: _number_
|
||||||
- __outgoing_htlc_id__: _number_
|
- __outgoing_htlc_id__: _number_
|
||||||
- __timestamp_ns__: _number_
|
- __forward_fail_event__: _boolean_
|
||||||
- __event_type__: _string_
|
|
||||||
- __incoming_amt_msat__: _number_
|
- __incoming_amt_msat__: _number_
|
||||||
- __outgoing_amt_msat__: _number_
|
- __outgoing_amt_msat__: _number_
|
||||||
- __failure_string__: _string_
|
- __failure_string__: _string_
|
||||||
- __settled__: _boolean_
|
|
||||||
- __offchain__: _boolean_
|
|
||||||
- __forward_fail_event__: _boolean_
|
|
||||||
|
|
||||||
### ClosedChannel
|
### BannedAppUser
|
||||||
- __channel_id__: _string_
|
- __app_name__: _string_
|
||||||
- __capacity__: _number_
|
- __app_id__: _string_
|
||||||
- __closed_height__: _number_
|
- __user_identifier__: _string_
|
||||||
|
- __nostr_pub__: _string_
|
||||||
|
|
||||||
### AddAppRequest
|
### GetUserOperationsResponse
|
||||||
|
- __latestOutgoingTxOperations__: _[UserOperations](#UserOperations)_
|
||||||
|
- __latestIncomingTxOperations__: _[UserOperations](#UserOperations)_
|
||||||
|
- __latestOutgoingUserToUserPayemnts__: _[UserOperations](#UserOperations)_
|
||||||
|
- __latestIncomingUserToUserPayemnts__: _[UserOperations](#UserOperations)_
|
||||||
|
- __latestOutgoingInvoiceOperations__: _[UserOperations](#UserOperations)_
|
||||||
|
- __latestIncomingInvoiceOperations__: _[UserOperations](#UserOperations)_
|
||||||
|
|
||||||
|
### RequestNPubLinkingTokenResponse
|
||||||
|
- __token__: _string_
|
||||||
|
|
||||||
|
### UsageMetric
|
||||||
|
- __processed_at_ms__: _number_
|
||||||
|
- __auth_in_nano__: _number_
|
||||||
|
- __rpc_name__: _string_
|
||||||
|
- __nostr__: _boolean_
|
||||||
|
- __batch_size__: _number_
|
||||||
|
- __parsed_in_nano__: _number_
|
||||||
|
- __validate_in_nano__: _number_
|
||||||
|
- __handle_in_nano__: _number_
|
||||||
|
- __batch__: _boolean_
|
||||||
|
|
||||||
|
### NewInvoiceRequest
|
||||||
|
- __amountSats__: _number_
|
||||||
|
- __memo__: _string_
|
||||||
|
|
||||||
|
### OpenChannelRequest
|
||||||
|
- __destination__: _string_
|
||||||
|
- __fundingAmount__: _number_
|
||||||
|
- __pushAmount__: _number_
|
||||||
|
- __closeAddress__: _string_
|
||||||
|
|
||||||
|
### ChainBalanceEvent
|
||||||
|
- __block_height__: _number_
|
||||||
|
- __confirmed_balance__: _number_
|
||||||
|
- __unconfirmed_balance__: _number_
|
||||||
|
- __total_balance__: _number_
|
||||||
|
|
||||||
|
### GetAppUserRequest
|
||||||
|
- __user_identifier__: _string_
|
||||||
|
|
||||||
|
### NewAddressResponse
|
||||||
|
- __address__: _string_
|
||||||
|
|
||||||
|
### PayInvoiceResponse
|
||||||
|
- __preimage__: _string_
|
||||||
|
- __amount_paid__: _number_
|
||||||
|
- __operation_id__: _string_
|
||||||
|
- __service_fee__: _number_
|
||||||
|
- __network_fee__: _number_
|
||||||
|
|
||||||
|
### AddProductRequest
|
||||||
- __name__: _string_
|
- __name__: _string_
|
||||||
- __allow_user_creation__: _boolean_
|
- __price_sats__: _number_
|
||||||
|
|
||||||
|
### MigrationUpdate
|
||||||
|
- __closure__: _[ClosureMigration](#ClosureMigration)_ *this field is optional
|
||||||
|
- __relays__: _[RelaysMigration](#RelaysMigration)_ *this field is optional
|
||||||
|
|
||||||
### ClosureMigration
|
### ClosureMigration
|
||||||
- __closes_at_unix__: _number_
|
- __closes_at_unix__: _number_
|
||||||
|
|
||||||
### BanUserResponse
|
### EncryptionExchangeRequest
|
||||||
- __balance_sats__: _number_
|
- __publicKey__: _string_
|
||||||
- __banned_app_users__: ARRAY of: _[BannedAppUser](#BannedAppUser)_
|
- __deviceId__: _string_
|
||||||
|
|
||||||
### AddAppUserRequest
|
|
||||||
- __identifier__: _string_
|
|
||||||
- __fail_if_exists__: _boolean_
|
|
||||||
- __balance__: _number_
|
|
||||||
|
|
||||||
### SetMockAppUserBalanceRequest
|
|
||||||
- __user_identifier__: _string_
|
|
||||||
- __amount__: _number_
|
|
||||||
|
|
||||||
### PayInvoiceRequest
|
|
||||||
- __invoice__: _string_
|
|
||||||
- __amount__: _number_
|
|
||||||
|
|
||||||
### LnurlWithdrawInfoResponse
|
|
||||||
- __tag__: _string_
|
|
||||||
- __callback__: _string_
|
|
||||||
- __k1__: _string_
|
|
||||||
- __defaultDescription__: _string_
|
|
||||||
- __minWithdrawable__: _number_
|
|
||||||
- __maxWithdrawable__: _number_
|
|
||||||
- __balanceCheck__: _string_
|
|
||||||
- __payLink__: _string_
|
|
||||||
|
|
||||||
### UsageMetric
|
|
||||||
- __processed_at_ms__: _number_
|
|
||||||
- __parsed_in_nano__: _number_
|
|
||||||
- __auth_in_nano__: _number_
|
|
||||||
- __validate_in_nano__: _number_
|
|
||||||
- __handle_in_nano__: _number_
|
|
||||||
- __rpc_name__: _string_
|
|
||||||
- __batch__: _boolean_
|
|
||||||
- __nostr__: _boolean_
|
|
||||||
- __batch_size__: _number_
|
|
||||||
|
|
||||||
### UsersInfo
|
### UsersInfo
|
||||||
- __total__: _number_
|
- __total__: _number_
|
||||||
|
|
@ -605,207 +666,70 @@ The nostr server will send back a message response, and inside the body there wi
|
||||||
- __balance_avg__: _number_
|
- __balance_avg__: _number_
|
||||||
- __balance_median__: _number_
|
- __balance_median__: _number_
|
||||||
|
|
||||||
### BanUserRequest
|
|
||||||
- __user_id__: _string_
|
|
||||||
|
|
||||||
### UserOperations
|
|
||||||
- __fromIndex__: _number_
|
|
||||||
- __toIndex__: _number_
|
|
||||||
- __operations__: ARRAY of: _[UserOperation](#UserOperation)_
|
|
||||||
|
|
||||||
### RequestNPubLinkingTokenRequest
|
|
||||||
- __user_identifier__: _string_
|
|
||||||
|
|
||||||
### UserOperation
|
|
||||||
- __paidAtUnix__: _number_
|
|
||||||
- __type__: _[UserOperationType](#UserOperationType)_
|
|
||||||
- __inbound__: _boolean_
|
|
||||||
- __amount__: _number_
|
|
||||||
- __identifier__: _string_
|
|
||||||
- __operationId__: _string_
|
|
||||||
- __service_fee__: _number_
|
|
||||||
- __network_fee__: _number_
|
|
||||||
- __confirmed__: _boolean_
|
|
||||||
- __tx_hash__: _string_
|
|
||||||
- __internal__: _boolean_
|
|
||||||
|
|
||||||
### Product
|
|
||||||
- __id__: _string_
|
|
||||||
- __name__: _string_
|
|
||||||
- __price_sats__: _number_
|
|
||||||
|
|
||||||
### LinkNPubThroughTokenRequest
|
|
||||||
- __token__: _string_
|
|
||||||
- __nostr_pub__: _string_
|
|
||||||
|
|
||||||
### EncryptionExchangeRequest
|
|
||||||
- __publicKey__: _string_
|
|
||||||
- __deviceId__: _string_
|
|
||||||
|
|
||||||
### PayAppUserInvoiceRequest
|
|
||||||
- __user_identifier__: _string_
|
|
||||||
- __invoice__: _string_
|
|
||||||
- __amount__: _number_
|
|
||||||
|
|
||||||
### SendAppUserToAppPaymentRequest
|
|
||||||
- __from_user_identifier__: _string_
|
|
||||||
- __amount__: _number_
|
|
||||||
|
|
||||||
### SendAppUserToAppUserPaymentRequest
|
|
||||||
- __from_user_identifier__: _string_
|
|
||||||
- __to_user_identifier__: _string_
|
|
||||||
- __amount__: _number_
|
|
||||||
|
|
||||||
### NewInvoiceRequest
|
|
||||||
- __amountSats__: _number_
|
|
||||||
- __memo__: _string_
|
|
||||||
|
|
||||||
### MigrationUpdate
|
|
||||||
- __closure__: _[ClosureMigration](#ClosureMigration)_ *this field is optional
|
|
||||||
- __relays__: _[RelaysMigration](#RelaysMigration)_ *this field is optional
|
|
||||||
|
|
||||||
### GetUserOperationsResponse
|
|
||||||
- __latestOutgoingInvoiceOperations__: _[UserOperations](#UserOperations)_
|
|
||||||
- __latestIncomingInvoiceOperations__: _[UserOperations](#UserOperations)_
|
|
||||||
- __latestOutgoingTxOperations__: _[UserOperations](#UserOperations)_
|
|
||||||
- __latestIncomingTxOperations__: _[UserOperations](#UserOperations)_
|
|
||||||
- __latestOutgoingUserToUserPayemnts__: _[UserOperations](#UserOperations)_
|
|
||||||
- __latestIncomingUserToUserPayemnts__: _[UserOperations](#UserOperations)_
|
|
||||||
|
|
||||||
### AddAppUserInvoiceRequest
|
|
||||||
- __receiver_identifier__: _string_
|
|
||||||
- __payer_identifier__: _string_
|
|
||||||
- __http_callback_url__: _string_
|
|
||||||
- __invoice_req__: _[NewInvoiceRequest](#NewInvoiceRequest)_
|
|
||||||
|
|
||||||
### DecodeInvoiceRequest
|
|
||||||
- __invoice__: _string_
|
|
||||||
|
|
||||||
### UserInfo
|
|
||||||
- __userId__: _string_
|
|
||||||
- __balance__: _number_
|
|
||||||
- __max_withdrawable__: _number_
|
|
||||||
- __user_identifier__: _string_
|
|
||||||
- __service_fee_bps__: _number_
|
|
||||||
- __network_max_fee_bps__: _number_
|
|
||||||
- __network_max_fee_fixed__: _number_
|
|
||||||
|
|
||||||
### DecodeInvoiceResponse
|
|
||||||
- __amount__: _number_
|
|
||||||
|
|
||||||
### OpenChannelResponse
|
|
||||||
- __channelId__: _string_
|
|
||||||
|
|
||||||
### LiveUserOperation
|
|
||||||
- __operation__: _[UserOperation](#UserOperation)_
|
|
||||||
|
|
||||||
### UsageMetrics
|
|
||||||
- __metrics__: ARRAY of: _[UsageMetric](#UsageMetric)_
|
|
||||||
|
|
||||||
### AuthApp
|
|
||||||
- __app__: _[Application](#Application)_
|
|
||||||
- __auth_token__: _string_
|
|
||||||
|
|
||||||
### AddAppInvoiceRequest
|
|
||||||
- __payer_identifier__: _string_
|
|
||||||
- __http_callback_url__: _string_
|
|
||||||
- __invoice_req__: _[NewInvoiceRequest](#NewInvoiceRequest)_
|
|
||||||
|
|
||||||
### HandleLnurlPayResponse
|
|
||||||
- __pr__: _string_
|
|
||||||
- __routes__: ARRAY of: _[Empty](#Empty)_
|
|
||||||
|
|
||||||
### Empty
|
|
||||||
|
|
||||||
### ChannelBalanceEvent
|
### ChannelBalanceEvent
|
||||||
- __block_height__: _number_
|
- __block_height__: _number_
|
||||||
- __channel_id__: _string_
|
- __channel_id__: _string_
|
||||||
- __local_balance_sats__: _number_
|
- __local_balance_sats__: _number_
|
||||||
- __remote_balance_sats__: _number_
|
- __remote_balance_sats__: _number_
|
||||||
|
|
||||||
### GetAppUserRequest
|
### ChannelRouting
|
||||||
- __user_identifier__: _string_
|
- __receive_errors__: _number_
|
||||||
|
- __forward_errors_as_output__: _number_
|
||||||
|
- __missed_forward_fee_as_output__: _number_
|
||||||
|
- __events_number__: _number_
|
||||||
|
- __channel_id__: _string_
|
||||||
|
- __forward_errors_as_input__: _number_
|
||||||
|
- __missed_forward_fee_as_input__: _number_
|
||||||
|
- __forward_fee_as_input__: _number_
|
||||||
|
- __forward_fee_as_output__: _number_
|
||||||
|
- __send_errors__: _number_
|
||||||
|
|
||||||
### AddProductRequest
|
### SendAppUserToAppPaymentRequest
|
||||||
- __name__: _string_
|
- __from_user_identifier__: _string_
|
||||||
- __price_sats__: _number_
|
- __amount__: _number_
|
||||||
|
|
||||||
### AppUser
|
|
||||||
- __identifier__: _string_
|
|
||||||
- __info__: _[UserInfo](#UserInfo)_
|
|
||||||
- __max_withdrawable__: _number_
|
|
||||||
|
|
||||||
### GetAppUserLNURLInfoRequest
|
|
||||||
- __user_identifier__: _string_
|
|
||||||
- __base_url_override__: _string_
|
|
||||||
|
|
||||||
### SetMockAppBalanceRequest
|
### SetMockAppBalanceRequest
|
||||||
- __amount__: _number_
|
- __amount__: _number_
|
||||||
|
|
||||||
### NewAddressRequest
|
|
||||||
- __addressType__: _[AddressType](#AddressType)_
|
|
||||||
|
|
||||||
### GetProductBuyLinkResponse
|
|
||||||
- __link__: _string_
|
|
||||||
|
|
||||||
### HttpCreds
|
### HttpCreds
|
||||||
- __url__: _string_
|
- __url__: _string_
|
||||||
- __token__: _string_
|
- __token__: _string_
|
||||||
|
|
||||||
### AppMetrics
|
### ClosedChannel
|
||||||
- __app__: _[Application](#Application)_
|
- __channel_id__: _string_
|
||||||
- __users__: _[UsersInfo](#UsersInfo)_
|
- __capacity__: _number_
|
||||||
- __received__: _number_
|
- __closed_height__: _number_
|
||||||
- __spent__: _number_
|
|
||||||
- __available__: _number_
|
|
||||||
- __fees__: _number_
|
|
||||||
- __invoices__: _number_
|
|
||||||
- __total_fees__: _number_
|
|
||||||
- __operations__: ARRAY of: _[UserOperation](#UserOperation)_
|
|
||||||
|
|
||||||
### ChainBalanceEvent
|
### Application
|
||||||
- __block_height__: _number_
|
- __id__: _string_
|
||||||
- __confirmed_balance__: _number_
|
- __balance__: _number_
|
||||||
- __unconfirmed_balance__: _number_
|
- __npub__: _string_
|
||||||
- __total_balance__: _number_
|
- __name__: _string_
|
||||||
|
|
||||||
### SetMockInvoiceAsPaidRequest
|
### AddAppUserRequest
|
||||||
- __invoice__: _string_
|
- __balance__: _number_
|
||||||
|
- __identifier__: _string_
|
||||||
|
- __fail_if_exists__: _boolean_
|
||||||
|
|
||||||
|
### SetMockAppUserBalanceRequest
|
||||||
|
- __user_identifier__: _string_
|
||||||
- __amount__: _number_
|
- __amount__: _number_
|
||||||
|
|
||||||
### LndGetInfoRequest
|
|
||||||
- __nodeId__: _number_
|
|
||||||
|
|
||||||
### NewAddressResponse
|
|
||||||
- __address__: _string_
|
|
||||||
|
|
||||||
### PayAddressResponse
|
### PayAddressResponse
|
||||||
- __txId__: _string_
|
|
||||||
- __operation_id__: _string_
|
- __operation_id__: _string_
|
||||||
- __service_fee__: _number_
|
- __service_fee__: _number_
|
||||||
- __network_fee__: _number_
|
- __network_fee__: _number_
|
||||||
|
- __txId__: _string_
|
||||||
|
|
||||||
### AppsMetrics
|
### NewInvoiceResponse
|
||||||
- __apps__: ARRAY of: _[AppMetrics](#AppMetrics)_
|
- __invoice__: _string_
|
||||||
|
|
||||||
### LndNodeMetrics
|
### RequestNPubLinkingTokenRequest
|
||||||
- __channels_balance_events__: ARRAY of: _[ChannelBalanceEvent](#ChannelBalanceEvent)_
|
- __user_identifier__: _string_
|
||||||
- __chain_balance_events__: ARRAY of: _[ChainBalanceEvent](#ChainBalanceEvent)_
|
|
||||||
- __offline_channels__: _number_
|
|
||||||
- __online_channels__: _number_
|
|
||||||
- __pending_channels__: _number_
|
|
||||||
- __closing_channels__: _number_
|
|
||||||
- __open_channels__: ARRAY of: _[OpenChannel](#OpenChannel)_
|
|
||||||
- __closed_channels__: ARRAY of: _[ClosedChannel](#ClosedChannel)_
|
|
||||||
- __channel_routing__: ARRAY of: _[ChannelRouting](#ChannelRouting)_
|
|
||||||
|
|
||||||
### AuthAppRequest
|
### LinkNPubThroughTokenRequest
|
||||||
- __name__: _string_
|
- __token__: _string_
|
||||||
- __allow_user_creation__: _boolean_ *this field is optional
|
- __nostr_pub__: _string_
|
||||||
|
|
||||||
### LndMetricsRequest
|
|
||||||
- __from_unix__: _number_ *this field is optional
|
|
||||||
- __to_unix__: _number_ *this field is optional
|
|
||||||
|
|
||||||
### OpenChannel
|
### OpenChannel
|
||||||
- __channel_id__: _string_
|
- __channel_id__: _string_
|
||||||
|
|
@ -815,38 +739,164 @@ The nostr server will send back a message response, and inside the body there wi
|
||||||
- __local_balance__: _number_
|
- __local_balance__: _number_
|
||||||
- __remote_balance__: _number_
|
- __remote_balance__: _number_
|
||||||
|
|
||||||
### NewInvoiceResponse
|
### SetMockInvoiceAsPaidRequest
|
||||||
|
- __invoice__: _string_
|
||||||
|
- __amount__: _number_
|
||||||
|
|
||||||
|
### AddAppUserInvoiceRequest
|
||||||
|
- __receiver_identifier__: _string_
|
||||||
|
- __payer_identifier__: _string_
|
||||||
|
- __http_callback_url__: _string_
|
||||||
|
- __invoice_req__: _[NewInvoiceRequest](#NewInvoiceRequest)_
|
||||||
|
|
||||||
|
### DecodeInvoiceResponse
|
||||||
|
- __amount__: _number_
|
||||||
|
|
||||||
|
### OpenChannelResponse
|
||||||
|
- __channelId__: _string_
|
||||||
|
|
||||||
|
### RelaysMigration
|
||||||
|
- __relays__: ARRAY of: _string_
|
||||||
|
|
||||||
|
### LndMetrics
|
||||||
|
- __nodes__: ARRAY of: _[LndNodeMetrics](#LndNodeMetrics)_
|
||||||
|
|
||||||
|
### AppUser
|
||||||
|
- __identifier__: _string_
|
||||||
|
- __info__: _[UserInfo](#UserInfo)_
|
||||||
|
- __max_withdrawable__: _number_
|
||||||
|
|
||||||
|
### AddAppInvoiceRequest
|
||||||
|
- __payer_identifier__: _string_
|
||||||
|
- __http_callback_url__: _string_
|
||||||
|
- __invoice_req__: _[NewInvoiceRequest](#NewInvoiceRequest)_
|
||||||
|
|
||||||
|
### UserOperations
|
||||||
|
- __fromIndex__: _number_
|
||||||
|
- __toIndex__: _number_
|
||||||
|
- __operations__: ARRAY of: _[UserOperation](#UserOperation)_
|
||||||
|
|
||||||
|
### BanUserRequest
|
||||||
|
- __user_id__: _string_
|
||||||
|
|
||||||
|
### NewAddressRequest
|
||||||
|
- __addressType__: _[AddressType](#AddressType)_
|
||||||
|
|
||||||
|
### DecodeInvoiceRequest
|
||||||
- __invoice__: _string_
|
- __invoice__: _string_
|
||||||
|
|
||||||
### ChannelRouting
|
### LnurlWithdrawInfoResponse
|
||||||
- __channel_id__: _string_
|
|
||||||
- __send_errors__: _number_
|
|
||||||
- __receive_errors__: _number_
|
|
||||||
- __forward_errors_as_input__: _number_
|
|
||||||
- __forward_errors_as_output__: _number_
|
|
||||||
- __missed_forward_fee_as_input__: _number_
|
|
||||||
- __missed_forward_fee_as_output__: _number_
|
|
||||||
- __forward_fee_as_input__: _number_
|
|
||||||
- __forward_fee_as_output__: _number_
|
|
||||||
- __events_number__: _number_
|
|
||||||
|
|
||||||
### LnurlPayInfoResponse
|
|
||||||
- __tag__: _string_
|
|
||||||
- __callback__: _string_
|
- __callback__: _string_
|
||||||
- __maxSendable__: _number_
|
- __k1__: _string_
|
||||||
- __minSendable__: _number_
|
- __defaultDescription__: _string_
|
||||||
- __metadata__: _string_
|
- __minWithdrawable__: _number_
|
||||||
- __allowsNostr__: _boolean_
|
- __maxWithdrawable__: _number_
|
||||||
- __nostrPubkey__: _string_
|
- __balanceCheck__: _string_
|
||||||
|
- __payLink__: _string_
|
||||||
|
- __tag__: _string_
|
||||||
|
|
||||||
### GetUserOperationsRequest
|
### GetUserOperationsRequest
|
||||||
- __latestIncomingInvoice__: _number_
|
|
||||||
- __latestOutgoingInvoice__: _number_
|
- __latestOutgoingInvoice__: _number_
|
||||||
- __latestIncomingTx__: _number_
|
- __latestIncomingTx__: _number_
|
||||||
- __latestOutgoingTx__: _number_
|
- __latestOutgoingTx__: _number_
|
||||||
- __latestIncomingUserToUserPayment__: _number_
|
- __latestIncomingUserToUserPayment__: _number_
|
||||||
- __latestOutgoingUserToUserPayment__: _number_
|
- __latestOutgoingUserToUserPayment__: _number_
|
||||||
- __max_size__: _number_
|
- __max_size__: _number_
|
||||||
|
- __latestIncomingInvoice__: _number_
|
||||||
|
|
||||||
|
### AppMetrics
|
||||||
|
- __spent__: _number_
|
||||||
|
- __available__: _number_
|
||||||
|
- __fees__: _number_
|
||||||
|
- __invoices__: _number_
|
||||||
|
- __total_fees__: _number_
|
||||||
|
- __app__: _[Application](#Application)_
|
||||||
|
- __users__: _[UsersInfo](#UsersInfo)_
|
||||||
|
- __received__: _number_
|
||||||
|
- __operations__: ARRAY of: _[UserOperation](#UserOperation)_
|
||||||
|
|
||||||
|
### AddAppRequest
|
||||||
|
- __name__: _string_
|
||||||
|
- __allow_user_creation__: _boolean_
|
||||||
|
|
||||||
|
### SendAppUserToAppUserPaymentRequest
|
||||||
|
- __amount__: _number_
|
||||||
|
- __from_user_identifier__: _string_
|
||||||
|
- __to_user_identifier__: _string_
|
||||||
|
|
||||||
|
### LnurlPayInfoResponse
|
||||||
|
- __callback__: _string_
|
||||||
|
- __maxSendable__: _number_
|
||||||
|
- __minSendable__: _number_
|
||||||
|
- __metadata__: _string_
|
||||||
|
- __allowsNostr__: _boolean_
|
||||||
|
- __nostrPubkey__: _string_
|
||||||
|
- __tag__: _string_
|
||||||
|
|
||||||
|
### HandleLnurlPayResponse
|
||||||
|
- __pr__: _string_
|
||||||
|
- __routes__: ARRAY of: _[Empty](#Empty)_
|
||||||
|
|
||||||
|
### EnrollAdminTokenRequest
|
||||||
|
- __admin_token__: _string_
|
||||||
|
|
||||||
|
### UsageMetrics
|
||||||
|
- __metrics__: ARRAY of: _[UsageMetric](#UsageMetric)_
|
||||||
|
|
||||||
|
### LnurlLinkResponse
|
||||||
|
- __k1__: _string_
|
||||||
|
- __lnurl__: _string_
|
||||||
|
|
||||||
|
### LiveUserOperation
|
||||||
|
- __operation__: _[UserOperation](#UserOperation)_
|
||||||
|
|
||||||
|
### PayInvoiceRequest
|
||||||
|
- __invoice__: _string_
|
||||||
|
- __amount__: _number_
|
||||||
|
|
||||||
|
### GetProductBuyLinkResponse
|
||||||
|
- __link__: _string_
|
||||||
|
|
||||||
|
### LndNodeMetrics
|
||||||
|
- __chain_balance_events__: ARRAY of: _[ChainBalanceEvent](#ChainBalanceEvent)_
|
||||||
|
- __online_channels__: _number_
|
||||||
|
- __closing_channels__: _number_
|
||||||
|
- __channels_balance_events__: ARRAY of: _[ChannelBalanceEvent](#ChannelBalanceEvent)_
|
||||||
|
- __pending_channels__: _number_
|
||||||
|
- __open_channels__: ARRAY of: _[OpenChannel](#OpenChannel)_
|
||||||
|
- __closed_channels__: ARRAY of: _[ClosedChannel](#ClosedChannel)_
|
||||||
|
- __channel_routing__: ARRAY of: _[ChannelRouting](#ChannelRouting)_
|
||||||
|
- __offline_channels__: _number_
|
||||||
|
|
||||||
|
### AuthApp
|
||||||
|
- __app__: _[Application](#Application)_
|
||||||
|
- __auth_token__: _string_
|
||||||
|
|
||||||
|
### GetAppUserLNURLInfoRequest
|
||||||
|
- __user_identifier__: _string_
|
||||||
|
- __base_url_override__: _string_
|
||||||
|
|
||||||
|
### UserInfo
|
||||||
|
- __network_max_fee_fixed__: _number_
|
||||||
|
- __userId__: _string_
|
||||||
|
- __balance__: _number_
|
||||||
|
- __max_withdrawable__: _number_
|
||||||
|
- __user_identifier__: _string_
|
||||||
|
- __service_fee_bps__: _number_
|
||||||
|
- __network_max_fee_bps__: _number_
|
||||||
|
|
||||||
|
### UserOperation
|
||||||
|
- __paidAtUnix__: _number_
|
||||||
|
- __service_fee__: _number_
|
||||||
|
- __confirmed__: _boolean_
|
||||||
|
- __tx_hash__: _string_
|
||||||
|
- __internal__: _boolean_
|
||||||
|
- __network_fee__: _number_
|
||||||
|
- __type__: _[UserOperationType](#UserOperationType)_
|
||||||
|
- __inbound__: _boolean_
|
||||||
|
- __amount__: _number_
|
||||||
|
- __identifier__: _string_
|
||||||
|
- __operationId__: _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
|
|
@ -364,6 +364,28 @@ 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.EnrollAdminToken) throw new Error('method: EnrollAdminToken is not implemented')
|
||||||
|
app.post('/api/guest/npub/enroll/admin', async (req, res) => {
|
||||||
|
const info: Types.RequestInfo = { rpcName: 'EnrollAdminToken', batch: false, nostr: false, batchSize: 0}
|
||||||
|
const stats: Types.RequestStats = { startMs:req.startTimeMs || 0, start:req.startTime || 0n, parse: process.hrtime.bigint(), guard: 0n, validate: 0n, handle: 0n }
|
||||||
|
let authCtx: Types.AuthContext = {}
|
||||||
|
try {
|
||||||
|
if (!methods.EnrollAdminToken) throw new Error('method: EnrollAdminToken is not implemented')
|
||||||
|
const authContext = await opts.UserAuthGuard(req.headers['authorization'])
|
||||||
|
authCtx = authContext
|
||||||
|
stats.guard = process.hrtime.bigint()
|
||||||
|
const request = req.body
|
||||||
|
const error = Types.EnrollAdminTokenRequestValidate(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
|
||||||
|
await methods.EnrollAdminToken({rpcName:'EnrollAdminToken', ctx:authContext , req: request})
|
||||||
|
stats.handle = process.hrtime.bigint()
|
||||||
|
res.json({status: 'OK'})
|
||||||
|
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.GetApp) throw new Error('method: GetApp is not implemented')
|
if (!opts.allowNotImplementedMethods && !methods.GetApp) throw new Error('method: GetApp is not implemented')
|
||||||
app.post('/api/app/get', async (req, res) => {
|
app.post('/api/app/get', async (req, res) => {
|
||||||
const info: Types.RequestInfo = { rpcName: 'GetApp', batch: false, nostr: false, batchSize: 0}
|
const info: Types.RequestInfo = { rpcName: 'GetApp', batch: false, nostr: false, batchSize: 0}
|
||||||
|
|
@ -948,6 +970,18 @@ export default (methods: Types.ServerMethods, opts: ServerOptions) => {
|
||||||
callsMetrics.push({ ...opInfo, ...opStats, ...ctx })
|
callsMetrics.push({ ...opInfo, ...opStats, ...ctx })
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
|
case 'EnrollAdminToken':
|
||||||
|
if (!methods.EnrollAdminToken) {
|
||||||
|
throw new Error('method EnrollAdminToken not found' )
|
||||||
|
} else {
|
||||||
|
const error = Types.EnrollAdminTokenRequestValidate(operation.req)
|
||||||
|
opStats.validate = process.hrtime.bigint()
|
||||||
|
if (error !== null) throw error
|
||||||
|
await methods.EnrollAdminToken({...operation, ctx}); responses.push({ status: 'OK' })
|
||||||
|
opStats.handle = process.hrtime.bigint()
|
||||||
|
callsMetrics.push({ ...opInfo, ...opStats, ...ctx })
|
||||||
|
}
|
||||||
|
break
|
||||||
case 'UserHealth':
|
case 'UserHealth':
|
||||||
if (!methods.UserHealth) {
|
if (!methods.UserHealth) {
|
||||||
throw new Error('method UserHealth not found' )
|
throw new Error('method UserHealth not found' )
|
||||||
|
|
@ -1121,6 +1155,6 @@ export default (methods: Types.ServerMethods, opts: ServerOptions) => {
|
||||||
var server: { close: () => void } | undefined
|
var server: { close: () => void } | undefined
|
||||||
return {
|
return {
|
||||||
Close: () => { if (!server) { throw new Error('tried closing server before starting') } else server.close() },
|
Close: () => { if (!server) { throw new Error('tried closing server before starting') } else server.close() },
|
||||||
Listen: (port: number) => { server = app.listen(port, () => logger.log('Example app listening on port ' + port)) }
|
Listen: (port: number) => { server = app.listen(port, () => logger.log('LightningPub listening on port ' + port)) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -234,6 +234,17 @@ export default (params: ClientParams) => ({
|
||||||
}
|
}
|
||||||
return { status: 'ERROR', reason: 'invalid response' }
|
return { status: 'ERROR', reason: 'invalid response' }
|
||||||
},
|
},
|
||||||
|
EnrollAdminToken: async (request: Types.EnrollAdminTokenRequest): Promise<ResultError | ({ status: 'OK' })> => {
|
||||||
|
const auth = await params.retrieveUserAuth()
|
||||||
|
if (auth === null) throw new Error('retrieveUserAuth() returned null')
|
||||||
|
let finalRoute = '/api/guest/npub/enroll/admin'
|
||||||
|
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') {
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
return { status: 'ERROR', reason: 'invalid response' }
|
||||||
|
},
|
||||||
GetApp: async (): Promise<ResultError | ({ status: 'OK' }& Types.Application)> => {
|
GetApp: async (): Promise<ResultError | ({ status: 'OK' }& Types.Application)> => {
|
||||||
const auth = await params.retrieveAppAuth()
|
const auth = await params.retrieveAppAuth()
|
||||||
if (auth === null) throw new Error('retrieveAppAuth() returned null')
|
if (auth === null) throw new Error('retrieveAppAuth() returned null')
|
||||||
|
|
|
||||||
|
|
@ -5,10 +5,116 @@ export type ResultError = { status: 'ERROR', reason: string }
|
||||||
|
|
||||||
export type NostrClientParams = {
|
export type NostrClientParams = {
|
||||||
pubDestination: string
|
pubDestination: string
|
||||||
|
retrieveNostrAdminAuth: () => Promise<string | null>
|
||||||
|
retrieveNostrMetricsAuth: () => Promise<string | null>
|
||||||
retrieveNostrUserAuth: () => Promise<string | null>
|
retrieveNostrUserAuth: () => Promise<string | null>
|
||||||
checkResult?: true
|
checkResult?: true
|
||||||
}
|
}
|
||||||
export default (params: NostrClientParams, send: (to:string, message: NostrRequest) => Promise<any>, subscribe: (to:string, message: NostrRequest, cb:(res:any)=> void) => void) => ({
|
export default (params: NostrClientParams, send: (to:string, message: NostrRequest) => Promise<any>, subscribe: (to:string, message: NostrRequest, cb:(res:any)=> void) => void) => ({
|
||||||
|
LndGetInfo: async (request: Types.LndGetInfoRequest): Promise<ResultError | ({ status: 'OK' }& Types.LndGetInfoResponse)> => {
|
||||||
|
const auth = await params.retrieveNostrAdminAuth()
|
||||||
|
if (auth === null) throw new Error('retrieveNostrAdminAuth() returned null')
|
||||||
|
const nostrRequest: NostrRequest = {}
|
||||||
|
nostrRequest.body = request
|
||||||
|
const data = await send(params.pubDestination, {rpcName:'LndGetInfo',authIdentifier:auth, ...nostrRequest })
|
||||||
|
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.LndGetInfoResponseValidate(result)
|
||||||
|
if (error === null) { return { status: 'OK', ...result } } else return { status: 'ERROR', reason: error.message }
|
||||||
|
}
|
||||||
|
return { status: 'ERROR', reason: 'invalid response' }
|
||||||
|
},
|
||||||
|
AddApp: async (request: Types.AddAppRequest): Promise<ResultError | ({ status: 'OK' }& Types.AuthApp)> => {
|
||||||
|
const auth = await params.retrieveNostrAdminAuth()
|
||||||
|
if (auth === null) throw new Error('retrieveNostrAdminAuth() returned null')
|
||||||
|
const nostrRequest: NostrRequest = {}
|
||||||
|
nostrRequest.body = request
|
||||||
|
const data = await send(params.pubDestination, {rpcName:'AddApp',authIdentifier:auth, ...nostrRequest })
|
||||||
|
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.AuthAppValidate(result)
|
||||||
|
if (error === null) { return { status: 'OK', ...result } } else return { status: 'ERROR', reason: error.message }
|
||||||
|
}
|
||||||
|
return { status: 'ERROR', reason: 'invalid response' }
|
||||||
|
},
|
||||||
|
AuthApp: async (request: Types.AuthAppRequest): Promise<ResultError | ({ status: 'OK' }& Types.AuthApp)> => {
|
||||||
|
const auth = await params.retrieveNostrAdminAuth()
|
||||||
|
if (auth === null) throw new Error('retrieveNostrAdminAuth() returned null')
|
||||||
|
const nostrRequest: NostrRequest = {}
|
||||||
|
nostrRequest.body = request
|
||||||
|
const data = await send(params.pubDestination, {rpcName:'AuthApp',authIdentifier:auth, ...nostrRequest })
|
||||||
|
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.AuthAppValidate(result)
|
||||||
|
if (error === null) { return { status: 'OK', ...result } } else return { status: 'ERROR', reason: error.message }
|
||||||
|
}
|
||||||
|
return { status: 'ERROR', reason: 'invalid response' }
|
||||||
|
},
|
||||||
|
BanUser: async (request: Types.BanUserRequest): Promise<ResultError | ({ status: 'OK' }& Types.BanUserResponse)> => {
|
||||||
|
const auth = await params.retrieveNostrAdminAuth()
|
||||||
|
if (auth === null) throw new Error('retrieveNostrAdminAuth() returned null')
|
||||||
|
const nostrRequest: NostrRequest = {}
|
||||||
|
nostrRequest.body = request
|
||||||
|
const data = await send(params.pubDestination, {rpcName:'BanUser',authIdentifier:auth, ...nostrRequest })
|
||||||
|
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.BanUserResponseValidate(result)
|
||||||
|
if (error === null) { return { status: 'OK', ...result } } else return { status: 'ERROR', reason: error.message }
|
||||||
|
}
|
||||||
|
return { status: 'ERROR', reason: 'invalid response' }
|
||||||
|
},
|
||||||
|
GetUsageMetrics: async (): Promise<ResultError | ({ status: 'OK' }& Types.UsageMetrics)> => {
|
||||||
|
const auth = await params.retrieveNostrMetricsAuth()
|
||||||
|
if (auth === null) throw new Error('retrieveNostrMetricsAuth() returned null')
|
||||||
|
const nostrRequest: NostrRequest = {}
|
||||||
|
const data = await send(params.pubDestination, {rpcName:'GetUsageMetrics',authIdentifier:auth, ...nostrRequest })
|
||||||
|
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.UsageMetricsValidate(result)
|
||||||
|
if (error === null) { return { status: 'OK', ...result } } else return { status: 'ERROR', reason: error.message }
|
||||||
|
}
|
||||||
|
return { status: 'ERROR', reason: 'invalid response' }
|
||||||
|
},
|
||||||
|
GetAppsMetrics: async (request: Types.AppsMetricsRequest): Promise<ResultError | ({ status: 'OK' }& Types.AppsMetrics)> => {
|
||||||
|
const auth = await params.retrieveNostrMetricsAuth()
|
||||||
|
if (auth === null) throw new Error('retrieveNostrMetricsAuth() returned null')
|
||||||
|
const nostrRequest: NostrRequest = {}
|
||||||
|
nostrRequest.body = request
|
||||||
|
const data = await send(params.pubDestination, {rpcName:'GetAppsMetrics',authIdentifier:auth, ...nostrRequest })
|
||||||
|
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' }
|
||||||
|
},
|
||||||
|
GetLndMetrics: async (request: Types.LndMetricsRequest): Promise<ResultError | ({ status: 'OK' }& Types.LndMetrics)> => {
|
||||||
|
const auth = await params.retrieveNostrMetricsAuth()
|
||||||
|
if (auth === null) throw new Error('retrieveNostrMetricsAuth() returned null')
|
||||||
|
const nostrRequest: NostrRequest = {}
|
||||||
|
nostrRequest.body = request
|
||||||
|
const data = await send(params.pubDestination, {rpcName:'GetLndMetrics',authIdentifier:auth, ...nostrRequest })
|
||||||
|
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.LndMetricsValidate(result)
|
||||||
|
if (error === null) { return { status: 'OK', ...result } } else return { status: 'ERROR', reason: error.message }
|
||||||
|
}
|
||||||
|
return { status: 'ERROR', reason: 'invalid response' }
|
||||||
|
},
|
||||||
LinkNPubThroughToken: async (request: Types.LinkNPubThroughTokenRequest): Promise<ResultError | ({ status: 'OK' })> => {
|
LinkNPubThroughToken: async (request: Types.LinkNPubThroughTokenRequest): Promise<ResultError | ({ status: 'OK' })> => {
|
||||||
const auth = await params.retrieveNostrUserAuth()
|
const auth = await params.retrieveNostrUserAuth()
|
||||||
if (auth === null) throw new Error('retrieveNostrUserAuth() returned null')
|
if (auth === null) throw new Error('retrieveNostrUserAuth() returned null')
|
||||||
|
|
@ -21,6 +127,18 @@ export default (params: NostrClientParams, send: (to:string, message: NostrRequ
|
||||||
}
|
}
|
||||||
return { status: 'ERROR', reason: 'invalid response' }
|
return { status: 'ERROR', reason: 'invalid response' }
|
||||||
},
|
},
|
||||||
|
EnrollAdminToken: async (request: Types.EnrollAdminTokenRequest): Promise<ResultError | ({ status: 'OK' })> => {
|
||||||
|
const auth = await params.retrieveNostrUserAuth()
|
||||||
|
if (auth === null) throw new Error('retrieveNostrUserAuth() returned null')
|
||||||
|
const nostrRequest: NostrRequest = {}
|
||||||
|
nostrRequest.body = request
|
||||||
|
const data = await send(params.pubDestination, {rpcName:'EnrollAdminToken',authIdentifier:auth, ...nostrRequest })
|
||||||
|
if (data.status === 'ERROR' && typeof data.reason === 'string') return data
|
||||||
|
if (data.status === 'OK') {
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
return { status: 'ERROR', reason: 'invalid response' }
|
||||||
|
},
|
||||||
UserHealth: async (): Promise<ResultError | ({ status: 'OK' })> => {
|
UserHealth: async (): Promise<ResultError | ({ status: 'OK' })> => {
|
||||||
const auth = await params.retrieveNostrUserAuth()
|
const auth = await params.retrieveNostrUserAuth()
|
||||||
if (auth === null) throw new Error('retrieveNostrUserAuth() returned null')
|
if (auth === null) throw new Error('retrieveNostrUserAuth() returned null')
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,8 @@ export type NostrOptions = {
|
||||||
logger?: Logger
|
logger?: Logger
|
||||||
throwErrors?: true
|
throwErrors?: true
|
||||||
metricsCallback: (metrics: Types.RequestMetric[]) => void
|
metricsCallback: (metrics: Types.RequestMetric[]) => void
|
||||||
|
NostrAdminAuthGuard: (appId?:string, identifier?: string) => Promise<Types.AdminContext>
|
||||||
|
NostrMetricsAuthGuard: (appId?:string, identifier?: string) => Promise<Types.MetricsContext>
|
||||||
NostrUserAuthGuard: (appId?:string, identifier?: string) => Promise<Types.UserContext>
|
NostrUserAuthGuard: (appId?:string, identifier?: string) => Promise<Types.UserContext>
|
||||||
}
|
}
|
||||||
const logErrorAndReturnResponse = (error: Error, response: string, res: NostrResponse, logger: Logger, metric: Types.RequestMetric, metricsCallback: (metrics: Types.RequestMetric[]) => void) => {
|
const logErrorAndReturnResponse = (error: Error, response: string, res: NostrResponse, logger: Logger, metric: Types.RequestMetric, metricsCallback: (metrics: Types.RequestMetric[]) => void) => {
|
||||||
|
|
@ -29,6 +31,115 @@ export default (methods: Types.ServerMethods, opts: NostrOptions) => {
|
||||||
const stats: Types.RequestStats = { startMs, start: startTime, parse: process.hrtime.bigint(), guard: 0n, validate: 0n, handle: 0n }
|
const stats: Types.RequestStats = { startMs, start: startTime, parse: process.hrtime.bigint(), guard: 0n, validate: 0n, handle: 0n }
|
||||||
let authCtx: Types.AuthContext = {}
|
let authCtx: Types.AuthContext = {}
|
||||||
switch (req.rpcName) {
|
switch (req.rpcName) {
|
||||||
|
case 'LndGetInfo':
|
||||||
|
try {
|
||||||
|
if (!methods.LndGetInfo) throw new Error('method: LndGetInfo is not implemented')
|
||||||
|
const authContext = await opts.NostrAdminAuthGuard(req.appId, req.authIdentifier)
|
||||||
|
stats.guard = process.hrtime.bigint()
|
||||||
|
authCtx = authContext
|
||||||
|
const request = req.body
|
||||||
|
const error = Types.LndGetInfoRequestValidate(request)
|
||||||
|
stats.validate = process.hrtime.bigint()
|
||||||
|
if (error !== null) return logErrorAndReturnResponse(error, 'invalid request body', res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback)
|
||||||
|
const response = await methods.LndGetInfo({rpcName:'LndGetInfo', ctx:authContext , req: request})
|
||||||
|
stats.handle = process.hrtime.bigint()
|
||||||
|
res({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 }
|
||||||
|
break
|
||||||
|
case 'AddApp':
|
||||||
|
try {
|
||||||
|
if (!methods.AddApp) throw new Error('method: AddApp is not implemented')
|
||||||
|
const authContext = await opts.NostrAdminAuthGuard(req.appId, req.authIdentifier)
|
||||||
|
stats.guard = process.hrtime.bigint()
|
||||||
|
authCtx = authContext
|
||||||
|
const request = req.body
|
||||||
|
const error = Types.AddAppRequestValidate(request)
|
||||||
|
stats.validate = process.hrtime.bigint()
|
||||||
|
if (error !== null) return logErrorAndReturnResponse(error, 'invalid request body', res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback)
|
||||||
|
const response = await methods.AddApp({rpcName:'AddApp', ctx:authContext , req: request})
|
||||||
|
stats.handle = process.hrtime.bigint()
|
||||||
|
res({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 }
|
||||||
|
break
|
||||||
|
case 'AuthApp':
|
||||||
|
try {
|
||||||
|
if (!methods.AuthApp) throw new Error('method: AuthApp is not implemented')
|
||||||
|
const authContext = await opts.NostrAdminAuthGuard(req.appId, req.authIdentifier)
|
||||||
|
stats.guard = process.hrtime.bigint()
|
||||||
|
authCtx = authContext
|
||||||
|
const request = req.body
|
||||||
|
const error = Types.AuthAppRequestValidate(request)
|
||||||
|
stats.validate = process.hrtime.bigint()
|
||||||
|
if (error !== null) return logErrorAndReturnResponse(error, 'invalid request body', res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback)
|
||||||
|
const response = await methods.AuthApp({rpcName:'AuthApp', ctx:authContext , req: request})
|
||||||
|
stats.handle = process.hrtime.bigint()
|
||||||
|
res({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 }
|
||||||
|
break
|
||||||
|
case 'BanUser':
|
||||||
|
try {
|
||||||
|
if (!methods.BanUser) throw new Error('method: BanUser is not implemented')
|
||||||
|
const authContext = await opts.NostrAdminAuthGuard(req.appId, req.authIdentifier)
|
||||||
|
stats.guard = process.hrtime.bigint()
|
||||||
|
authCtx = authContext
|
||||||
|
const request = req.body
|
||||||
|
const error = Types.BanUserRequestValidate(request)
|
||||||
|
stats.validate = process.hrtime.bigint()
|
||||||
|
if (error !== null) return logErrorAndReturnResponse(error, 'invalid request body', res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback)
|
||||||
|
const response = await methods.BanUser({rpcName:'BanUser', ctx:authContext , req: request})
|
||||||
|
stats.handle = process.hrtime.bigint()
|
||||||
|
res({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 }
|
||||||
|
break
|
||||||
|
case 'GetUsageMetrics':
|
||||||
|
try {
|
||||||
|
if (!methods.GetUsageMetrics) throw new Error('method: GetUsageMetrics is not implemented')
|
||||||
|
const authContext = await opts.NostrMetricsAuthGuard(req.appId, req.authIdentifier)
|
||||||
|
stats.guard = process.hrtime.bigint()
|
||||||
|
authCtx = authContext
|
||||||
|
stats.validate = stats.guard
|
||||||
|
const response = await methods.GetUsageMetrics({rpcName:'GetUsageMetrics', ctx:authContext })
|
||||||
|
stats.handle = process.hrtime.bigint()
|
||||||
|
res({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 }
|
||||||
|
break
|
||||||
|
case 'GetAppsMetrics':
|
||||||
|
try {
|
||||||
|
if (!methods.GetAppsMetrics) throw new Error('method: GetAppsMetrics is not implemented')
|
||||||
|
const authContext = await opts.NostrMetricsAuthGuard(req.appId, req.authIdentifier)
|
||||||
|
stats.guard = process.hrtime.bigint()
|
||||||
|
authCtx = authContext
|
||||||
|
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, ...authCtx }, opts.metricsCallback)
|
||||||
|
const response = await methods.GetAppsMetrics({rpcName:'GetAppsMetrics', ctx:authContext , req: request})
|
||||||
|
stats.handle = process.hrtime.bigint()
|
||||||
|
res({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 }
|
||||||
|
break
|
||||||
|
case 'GetLndMetrics':
|
||||||
|
try {
|
||||||
|
if (!methods.GetLndMetrics) throw new Error('method: GetLndMetrics is not implemented')
|
||||||
|
const authContext = await opts.NostrMetricsAuthGuard(req.appId, req.authIdentifier)
|
||||||
|
stats.guard = process.hrtime.bigint()
|
||||||
|
authCtx = authContext
|
||||||
|
const request = req.body
|
||||||
|
const error = Types.LndMetricsRequestValidate(request)
|
||||||
|
stats.validate = process.hrtime.bigint()
|
||||||
|
if (error !== null) return logErrorAndReturnResponse(error, 'invalid request body', res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback)
|
||||||
|
const response = await methods.GetLndMetrics({rpcName:'GetLndMetrics', ctx:authContext , req: request})
|
||||||
|
stats.handle = process.hrtime.bigint()
|
||||||
|
res({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 }
|
||||||
|
break
|
||||||
case 'LinkNPubThroughToken':
|
case 'LinkNPubThroughToken':
|
||||||
try {
|
try {
|
||||||
if (!methods.LinkNPubThroughToken) throw new Error('method: LinkNPubThroughToken is not implemented')
|
if (!methods.LinkNPubThroughToken) throw new Error('method: LinkNPubThroughToken is not implemented')
|
||||||
|
|
@ -45,6 +156,22 @@ export default (methods: Types.ServerMethods, opts: NostrOptions) => {
|
||||||
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 }
|
||||||
break
|
break
|
||||||
|
case 'EnrollAdminToken':
|
||||||
|
try {
|
||||||
|
if (!methods.EnrollAdminToken) throw new Error('method: EnrollAdminToken is not implemented')
|
||||||
|
const authContext = await opts.NostrUserAuthGuard(req.appId, req.authIdentifier)
|
||||||
|
stats.guard = process.hrtime.bigint()
|
||||||
|
authCtx = authContext
|
||||||
|
const request = req.body
|
||||||
|
const error = Types.EnrollAdminTokenRequestValidate(request)
|
||||||
|
stats.validate = process.hrtime.bigint()
|
||||||
|
if (error !== null) return logErrorAndReturnResponse(error, 'invalid request body', res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback)
|
||||||
|
await methods.EnrollAdminToken({rpcName:'EnrollAdminToken', ctx:authContext , req: request})
|
||||||
|
stats.handle = process.hrtime.bigint()
|
||||||
|
res({status: 'OK'})
|
||||||
|
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 }
|
||||||
|
break
|
||||||
case 'UserHealth':
|
case 'UserHealth':
|
||||||
try {
|
try {
|
||||||
if (!methods.UserHealth) throw new Error('method: UserHealth is not implemented')
|
if (!methods.UserHealth) throw new Error('method: UserHealth is not implemented')
|
||||||
|
|
@ -321,6 +448,18 @@ export default (methods: Types.ServerMethods, opts: NostrOptions) => {
|
||||||
callsMetrics.push({ ...opInfo, ...opStats, ...ctx })
|
callsMetrics.push({ ...opInfo, ...opStats, ...ctx })
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
|
case 'EnrollAdminToken':
|
||||||
|
if (!methods.EnrollAdminToken) {
|
||||||
|
throw new Error('method not defined: EnrollAdminToken')
|
||||||
|
} else {
|
||||||
|
const error = Types.EnrollAdminTokenRequestValidate(operation.req)
|
||||||
|
opStats.validate = process.hrtime.bigint()
|
||||||
|
if (error !== null) throw error
|
||||||
|
await methods.EnrollAdminToken({...operation, ctx}); responses.push({ status: 'OK' })
|
||||||
|
opStats.handle = process.hrtime.bigint()
|
||||||
|
callsMetrics.push({ ...opInfo, ...opStats, ...ctx })
|
||||||
|
}
|
||||||
|
break
|
||||||
case 'UserHealth':
|
case 'UserHealth':
|
||||||
if (!methods.UserHealth) {
|
if (!methods.UserHealth) {
|
||||||
throw new Error('method not defined: UserHealth')
|
throw new Error('method not defined: UserHealth')
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
Binary file not shown.
BIN
proto/protoc-gen-pub_old
Executable file
BIN
proto/protoc-gen-pub_old
Executable file
Binary file not shown.
|
|
@ -92,42 +92,49 @@ service LightningPub {
|
||||||
option (auth_type) = "Admin";
|
option (auth_type) = "Admin";
|
||||||
option (http_method) = "post";
|
option (http_method) = "post";
|
||||||
option (http_route) = "/api/admin/lnd/getinfo";
|
option (http_route) = "/api/admin/lnd/getinfo";
|
||||||
|
option (nostr) = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
rpc AddApp(structs.AddAppRequest) returns (structs.AuthApp) {
|
rpc AddApp(structs.AddAppRequest) returns (structs.AuthApp) {
|
||||||
option (auth_type) = "Admin";
|
option (auth_type) = "Admin";
|
||||||
option (http_method) = "post";
|
option (http_method) = "post";
|
||||||
option (http_route) = "/api/admin/app/add";
|
option (http_route) = "/api/admin/app/add";
|
||||||
|
option (nostr) = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
rpc AuthApp(structs.AuthAppRequest) returns (structs.AuthApp) {
|
rpc AuthApp(structs.AuthAppRequest) returns (structs.AuthApp) {
|
||||||
option (auth_type) = "Admin";
|
option (auth_type) = "Admin";
|
||||||
option (http_method) = "post";
|
option (http_method) = "post";
|
||||||
option (http_route) = "/api/admin/app/auth";
|
option (http_route) = "/api/admin/app/auth";
|
||||||
|
option (nostr) = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
rpc BanUser(structs.BanUserRequest) returns (structs.BanUserResponse) {
|
rpc BanUser(structs.BanUserRequest) returns (structs.BanUserResponse) {
|
||||||
option (auth_type) = "Admin";
|
option (auth_type) = "Admin";
|
||||||
option (http_method) = "post";
|
option (http_method) = "post";
|
||||||
option (http_route) = "/api/admin/user/ban";
|
option (http_route) = "/api/admin/user/ban";
|
||||||
|
option (nostr) = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
rpc GetUsageMetrics(structs.Empty) returns (structs.UsageMetrics) {
|
rpc GetUsageMetrics(structs.Empty) returns (structs.UsageMetrics) {
|
||||||
option (auth_type) = "Metrics";
|
option (auth_type) = "Metrics";
|
||||||
option (http_method) = "post";
|
option (http_method) = "post";
|
||||||
option (http_route) = "/api/reports/usage";
|
option (http_route) = "/api/reports/usage";
|
||||||
|
option (nostr) = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
rpc GetAppsMetrics(structs.AppsMetricsRequest) returns (structs.AppsMetrics) {
|
rpc GetAppsMetrics(structs.AppsMetricsRequest) returns (structs.AppsMetrics) {
|
||||||
option (auth_type) = "Metrics";
|
option (auth_type) = "Metrics";
|
||||||
option (http_method) = "post";
|
option (http_method) = "post";
|
||||||
option (http_route) = "/api/reports/apps";
|
option (http_route) = "/api/reports/apps";
|
||||||
|
option (nostr) = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
rpc GetLndMetrics(structs.LndMetricsRequest) returns (structs.LndMetrics) {
|
rpc GetLndMetrics(structs.LndMetricsRequest) returns (structs.LndMetrics) {
|
||||||
option (auth_type) = "Metrics";
|
option (auth_type) = "Metrics";
|
||||||
option (http_method) = "post";
|
option (http_method) = "post";
|
||||||
option (http_route) = "/api/reports/lnd";
|
option (http_route) = "/api/reports/lnd";
|
||||||
|
option (nostr) = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -182,10 +189,16 @@ service LightningPub {
|
||||||
|
|
||||||
rpc LinkNPubThroughToken(structs.LinkNPubThroughTokenRequest) returns (structs.Empty) {
|
rpc LinkNPubThroughToken(structs.LinkNPubThroughTokenRequest) returns (structs.Empty) {
|
||||||
option (auth_type) = "User";
|
option (auth_type) = "User";
|
||||||
option(http_method) = "post";
|
option (http_method) = "post";
|
||||||
option (http_route) = "/api/guest/npub/link";
|
option (http_route) = "/api/guest/npub/link";
|
||||||
option (nostr) = true;
|
option (nostr) = true;
|
||||||
}
|
}
|
||||||
|
rpc EnrollAdminToken(structs.EnrollAdminTokenRequest) returns (structs.Empty) {
|
||||||
|
option (auth_type) = "User";
|
||||||
|
option (http_method) = "post";
|
||||||
|
option (http_route) = "/api/guest/npub/enroll/admin";
|
||||||
|
option (nostr) = true;
|
||||||
|
}
|
||||||
//</Guest>
|
//</Guest>
|
||||||
|
|
||||||
// <App>
|
// <App>
|
||||||
|
|
|
||||||
|
|
@ -450,3 +450,7 @@ message HttpCreds {
|
||||||
string url = 1;
|
string url = 1;
|
||||||
string token = 2;
|
string token = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message EnrollAdminTokenRequest {
|
||||||
|
string admin_token = 1;
|
||||||
|
}
|
||||||
|
|
@ -51,15 +51,20 @@ service Wizard {
|
||||||
option (http_method) = "get";
|
option (http_method) = "get";
|
||||||
option (http_route) = "/wizard/state";
|
option (http_route) = "/wizard/state";
|
||||||
};
|
};
|
||||||
rpc WizardConfig(wizard_structs.ConfigRequest) returns (wizard_structs.ConfigResponse){
|
rpc WizardConfig(wizard_structs.ConfigRequest) returns (wizard_structs.Empty){
|
||||||
option (auth_type) = "Guest";
|
option (auth_type) = "Guest";
|
||||||
option (http_method) = "post";
|
option (http_method) = "post";
|
||||||
option (http_route) = "/wizard/config";
|
option (http_route) = "/wizard/config";
|
||||||
};
|
};
|
||||||
rpc WizardConfirm(wizard_structs.ConfirmRequest) returns (wizard_structs.ConfirmResponse){
|
rpc GetAdminConnectInfo(wizard_structs.Empty) returns (wizard_structs.AdminConnectInfoResponse){
|
||||||
option (auth_type) = "Guest";
|
option (auth_type) = "Guest";
|
||||||
option (http_method) = "post";
|
option (http_method) = "get";
|
||||||
option (http_route) = "/wizard/confirm";
|
option (http_route) = "/wizard/admin_connect_info";
|
||||||
|
};
|
||||||
|
rpc GetServiceState(wizard_structs.Empty) returns (wizard_structs.ServiceStateResponse){
|
||||||
|
option (auth_type) = "Guest";
|
||||||
|
option (http_method) = "get";
|
||||||
|
option (http_route) = "/wizard/service_state";
|
||||||
};
|
};
|
||||||
// </Guest>
|
// </Guest>
|
||||||
}
|
}
|
||||||
|
|
@ -7,7 +7,8 @@ option go_package = "github.com/shocknet/lightning.pub";
|
||||||
message Empty {}
|
message Empty {}
|
||||||
|
|
||||||
message StateResponse {
|
message StateResponse {
|
||||||
bool already_initialized = 1;
|
bool config_sent = 1;
|
||||||
|
bool admin_linked = 2;
|
||||||
}
|
}
|
||||||
message ConfigRequest {
|
message ConfigRequest {
|
||||||
string source_name = 1;
|
string source_name = 1;
|
||||||
|
|
@ -15,18 +16,25 @@ message ConfigRequest {
|
||||||
bool automate_liquidity = 3;
|
bool automate_liquidity = 3;
|
||||||
bool push_backups_to_nostr = 4;
|
bool push_backups_to_nostr = 4;
|
||||||
}
|
}
|
||||||
|
message AdminConnectInfoResponse {
|
||||||
|
string nprofile = 1;
|
||||||
message ConfigResponse {
|
oneof connect_info {
|
||||||
bool already_initialized = 1;
|
string admin_token = 2;
|
||||||
repeated string seed = 2;
|
string enrolled_npub = 3;
|
||||||
string confirmation_id = 3;
|
}
|
||||||
}
|
}
|
||||||
|
enum LndState {
|
||||||
message ConfirmRequest {
|
OFFLINE = 0;
|
||||||
string confirmation_id = 1;
|
SYNCING = 1;
|
||||||
|
ONLINE = 2;
|
||||||
}
|
}
|
||||||
|
message ServiceStateResponse {
|
||||||
message ConfirmResponse {
|
string provider_name = 1;
|
||||||
string admin_key = 1;
|
repeated string relays = 2;
|
||||||
|
string admin_npub = 3;
|
||||||
|
bool relay_connected = 4;
|
||||||
|
LndState lnd_state = 5;
|
||||||
|
bool watchdog_ok = 6;
|
||||||
|
string http_url = 7;
|
||||||
|
string nprofile = 8;
|
||||||
}
|
}
|
||||||
|
|
@ -36,27 +36,30 @@ The nostr server will send back a message response, and inside the body there wi
|
||||||
- http method: __post__
|
- http method: __post__
|
||||||
- http route: __/wizard/config__
|
- http route: __/wizard/config__
|
||||||
- input: [ConfigRequest](#ConfigRequest)
|
- input: [ConfigRequest](#ConfigRequest)
|
||||||
- output: [ConfigResponse](#ConfigResponse)
|
- This methods has an __empty__ __response__ body
|
||||||
|
|
||||||
- WizardConfirm
|
- GetAdminConnectInfo
|
||||||
- auth type: __Guest__
|
- auth type: __Guest__
|
||||||
- http method: __post__
|
- http method: __get__
|
||||||
- http route: __/wizard/confirm__
|
- http route: __/wizard/admin_connect_info__
|
||||||
- input: [ConfirmRequest](#ConfirmRequest)
|
- This methods has an __empty__ __request__ body
|
||||||
- output: [ConfirmResponse](#ConfirmResponse)
|
- output: [AdminConnectInfoResponse](#AdminConnectInfoResponse)
|
||||||
|
|
||||||
|
- GetServiceState
|
||||||
|
- auth type: __Guest__
|
||||||
|
- http method: __get__
|
||||||
|
- http route: __/wizard/service_state__
|
||||||
|
- This methods has an __empty__ __request__ body
|
||||||
|
- output: [ServiceStateResponse](#ServiceStateResponse)
|
||||||
|
|
||||||
# INPUTS AND OUTPUTS
|
# INPUTS AND OUTPUTS
|
||||||
|
|
||||||
## Messages
|
## Messages
|
||||||
### The content of requests and response from the methods
|
### The content of requests and response from the methods
|
||||||
|
|
||||||
### ConfirmResponse
|
|
||||||
- __admin_key__: _string_
|
|
||||||
|
|
||||||
### Empty
|
|
||||||
|
|
||||||
### StateResponse
|
### StateResponse
|
||||||
- __already_initialized__: _boolean_
|
- __config_sent__: _boolean_
|
||||||
|
- __admin_linked__: _boolean_
|
||||||
|
|
||||||
### ConfigRequest
|
### ConfigRequest
|
||||||
- __source_name__: _string_
|
- __source_name__: _string_
|
||||||
|
|
@ -64,12 +67,25 @@ The nostr server will send back a message response, and inside the body there wi
|
||||||
- __automate_liquidity__: _boolean_
|
- __automate_liquidity__: _boolean_
|
||||||
- __push_backups_to_nostr__: _boolean_
|
- __push_backups_to_nostr__: _boolean_
|
||||||
|
|
||||||
### ConfigResponse
|
### AdminConnectInfoResponse
|
||||||
- __already_initialized__: _boolean_
|
- __nprofile__: _string_
|
||||||
- __seed__: ARRAY of: _string_
|
- __connect_info__: _AdminConnectInfoResponse_connect_info_
|
||||||
- __confirmation_id__: _string_
|
|
||||||
|
|
||||||
### ConfirmRequest
|
### ServiceStateResponse
|
||||||
- __confirmation_id__: _string_
|
- __http_url__: _string_
|
||||||
|
- __nprofile__: _string_
|
||||||
|
- __provider_name__: _string_
|
||||||
|
- __relays__: ARRAY of: _string_
|
||||||
|
- __admin_npub__: _string_
|
||||||
|
- __relay_connected__: _boolean_
|
||||||
|
- __lnd_state__: _[LndState](#LndState)_
|
||||||
|
- __watchdog_ok__: _boolean_
|
||||||
|
|
||||||
|
### Empty
|
||||||
## Enums
|
## Enums
|
||||||
### The enumerators used in the messages
|
### The enumerators used in the messages
|
||||||
|
|
||||||
|
### LndState
|
||||||
|
- __OFFLINE__
|
||||||
|
- __SYNCING__
|
||||||
|
- __ONLINE__
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
([]*main.Method) (len=3 cap=4) {
|
([]*main.Method) (len=4 cap=4) {
|
||||||
(*main.Method)(0xc0002221e0)({
|
(*main.Method)(0xc00022a280)({
|
||||||
in: (main.MethodMessage) {
|
in: (main.MethodMessage) {
|
||||||
name: (string) (len=5) "Empty",
|
name: (string) (len=5) "Empty",
|
||||||
hasZeroFields: (bool) true
|
hasZeroFields: (bool) true
|
||||||
|
|
@ -9,8 +9,8 @@
|
||||||
name: (string) (len=13) "StateResponse",
|
name: (string) (len=13) "StateResponse",
|
||||||
hasZeroFields: (bool) false
|
hasZeroFields: (bool) false
|
||||||
},
|
},
|
||||||
opts: (*main.methodOptions)(0xc00009e6c0)({
|
opts: (*main.methodOptions)(0xc00009a9c0)({
|
||||||
authType: (*main.supportedAuth)(0xc0003bd290)({
|
authType: (*main.supportedAuth)(0xc0003c9aa0)({
|
||||||
id: (string) (len=5) "guest",
|
id: (string) (len=5) "guest",
|
||||||
name: (string) (len=5) "Guest",
|
name: (string) (len=5) "Guest",
|
||||||
context: (map[string]string) {
|
context: (map[string]string) {
|
||||||
|
|
@ -27,18 +27,18 @@
|
||||||
}),
|
}),
|
||||||
serverStream: (bool) false
|
serverStream: (bool) false
|
||||||
}),
|
}),
|
||||||
(*main.Method)(0xc000222230)({
|
(*main.Method)(0xc00022a2d0)({
|
||||||
in: (main.MethodMessage) {
|
in: (main.MethodMessage) {
|
||||||
name: (string) (len=13) "ConfigRequest",
|
name: (string) (len=13) "ConfigRequest",
|
||||||
hasZeroFields: (bool) false
|
hasZeroFields: (bool) false
|
||||||
},
|
},
|
||||||
name: (string) (len=12) "WizardConfig",
|
name: (string) (len=12) "WizardConfig",
|
||||||
out: (main.MethodMessage) {
|
out: (main.MethodMessage) {
|
||||||
name: (string) (len=14) "ConfigResponse",
|
name: (string) (len=5) "Empty",
|
||||||
hasZeroFields: (bool) false
|
hasZeroFields: (bool) true
|
||||||
},
|
},
|
||||||
opts: (*main.methodOptions)(0xc00009e840)({
|
opts: (*main.methodOptions)(0xc00009ab40)({
|
||||||
authType: (*main.supportedAuth)(0xc0003bd350)({
|
authType: (*main.supportedAuth)(0xc0003c9b60)({
|
||||||
id: (string) (len=5) "guest",
|
id: (string) (len=5) "guest",
|
||||||
name: (string) (len=5) "Guest",
|
name: (string) (len=5) "Guest",
|
||||||
context: (map[string]string) {
|
context: (map[string]string) {
|
||||||
|
|
@ -55,26 +55,54 @@
|
||||||
}),
|
}),
|
||||||
serverStream: (bool) false
|
serverStream: (bool) false
|
||||||
}),
|
}),
|
||||||
(*main.Method)(0xc0002225a0)({
|
(*main.Method)(0xc00022a640)({
|
||||||
in: (main.MethodMessage) {
|
in: (main.MethodMessage) {
|
||||||
name: (string) (len=14) "ConfirmRequest",
|
name: (string) (len=5) "Empty",
|
||||||
hasZeroFields: (bool) false
|
hasZeroFields: (bool) true
|
||||||
},
|
},
|
||||||
name: (string) (len=13) "WizardConfirm",
|
name: (string) (len=19) "GetAdminConnectInfo",
|
||||||
out: (main.MethodMessage) {
|
out: (main.MethodMessage) {
|
||||||
name: (string) (len=15) "ConfirmResponse",
|
name: (string) (len=24) "AdminConnectInfoResponse",
|
||||||
hasZeroFields: (bool) false
|
hasZeroFields: (bool) false
|
||||||
},
|
},
|
||||||
opts: (*main.methodOptions)(0xc00009e9c0)({
|
opts: (*main.methodOptions)(0xc00009acc0)({
|
||||||
authType: (*main.supportedAuth)(0xc0003bd410)({
|
authType: (*main.supportedAuth)(0xc0003c9c20)({
|
||||||
id: (string) (len=5) "guest",
|
id: (string) (len=5) "guest",
|
||||||
name: (string) (len=5) "Guest",
|
name: (string) (len=5) "Guest",
|
||||||
context: (map[string]string) {
|
context: (map[string]string) {
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
method: (string) (len=4) "post",
|
method: (string) (len=3) "get",
|
||||||
route: (main.decodedRoute) {
|
route: (main.decodedRoute) {
|
||||||
route: (string) (len=15) "/wizard/confirm",
|
route: (string) (len=26) "/wizard/admin_connect_info",
|
||||||
|
params: ([]string) <nil>
|
||||||
|
},
|
||||||
|
query: ([]string) <nil>,
|
||||||
|
nostr: (bool) false,
|
||||||
|
batch: (bool) false
|
||||||
|
}),
|
||||||
|
serverStream: (bool) false
|
||||||
|
}),
|
||||||
|
(*main.Method)(0xc00022a690)({
|
||||||
|
in: (main.MethodMessage) {
|
||||||
|
name: (string) (len=5) "Empty",
|
||||||
|
hasZeroFields: (bool) true
|
||||||
|
},
|
||||||
|
name: (string) (len=15) "GetServiceState",
|
||||||
|
out: (main.MethodMessage) {
|
||||||
|
name: (string) (len=20) "ServiceStateResponse",
|
||||||
|
hasZeroFields: (bool) false
|
||||||
|
},
|
||||||
|
opts: (*main.methodOptions)(0xc00009ae40)({
|
||||||
|
authType: (*main.supportedAuth)(0xc0003c9ce0)({
|
||||||
|
id: (string) (len=5) "guest",
|
||||||
|
name: (string) (len=5) "Guest",
|
||||||
|
context: (map[string]string) {
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
method: (string) (len=3) "get",
|
||||||
|
route: (main.decodedRoute) {
|
||||||
|
route: (string) (len=21) "/wizard/service_state",
|
||||||
params: ([]string) <nil>
|
params: ([]string) <nil>
|
||||||
},
|
},
|
||||||
query: ([]string) <nil>,
|
query: ([]string) <nil>,
|
||||||
|
|
@ -85,137 +113,247 @@
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
([]*main.Enum) <nil>
|
([]*main.Enum) (len=1 cap=1) {
|
||||||
|
(*main.Enum)(0xc0003c9680)({
|
||||||
|
name: (string) (len=8) "LndState",
|
||||||
|
values: ([]main.EnumValue) (len=3 cap=4) {
|
||||||
|
(main.EnumValue) {
|
||||||
|
number: (int64) 0,
|
||||||
|
name: (string) (len=7) "OFFLINE"
|
||||||
|
},
|
||||||
|
(main.EnumValue) {
|
||||||
|
number: (int64) 1,
|
||||||
|
name: (string) (len=7) "SYNCING"
|
||||||
|
},
|
||||||
|
(main.EnumValue) {
|
||||||
|
number: (int64) 2,
|
||||||
|
name: (string) (len=6) "ONLINE"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
(map[string]*main.Message) (len=6) {
|
(map[string]*main.Message) (len=5) {
|
||||||
(string) (len=13) "StateResponse": (*main.Message)(0xc0003ee1c0)({
|
(string) (len=5) "Empty": (*main.Message)(0xc0003c94a0)({
|
||||||
|
fullName: (string) (len=5) "Empty",
|
||||||
|
name: (string) (len=5) "Empty",
|
||||||
|
fields: (map[string]*main.Field) {
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
(string) (len=13) "StateResponse": (*main.Message)(0xc0003c9500)({
|
||||||
fullName: (string) (len=13) "StateResponse",
|
fullName: (string) (len=13) "StateResponse",
|
||||||
name: (string) (len=13) "StateResponse",
|
name: (string) (len=13) "StateResponse",
|
||||||
fields: ([]*main.Field) (len=1 cap=1) {
|
fields: (map[string]*main.Field) (len=2) {
|
||||||
(*main.Field)(0xc0003bccc0)({
|
(string) (len=11) "config_sent": (*main.Field)(0xc0003ee440)({
|
||||||
name: (string) (len=19) "already_initialized",
|
name: (string) (len=11) "config_sent",
|
||||||
kind: (string) (len=4) "bool",
|
kind: (string) (len=4) "bool",
|
||||||
isMap: (bool) false,
|
isMap: (bool) false,
|
||||||
isArray: (bool) false,
|
isArray: (bool) false,
|
||||||
isEnum: (bool) false,
|
isEnum: (bool) false,
|
||||||
isMessage: (bool) false,
|
isMessage: (bool) false,
|
||||||
isOptional: (bool) false
|
isOptional: (bool) false,
|
||||||
})
|
oneOfName: (string) ""
|
||||||
}
|
}),
|
||||||
}),
|
(string) (len=12) "admin_linked": (*main.Field)(0xc0003ee480)({
|
||||||
(string) (len=13) "ConfigRequest": (*main.Message)(0xc0003ee200)({
|
name: (string) (len=12) "admin_linked",
|
||||||
fullName: (string) (len=13) "ConfigRequest",
|
kind: (string) (len=4) "bool",
|
||||||
name: (string) (len=13) "ConfigRequest",
|
|
||||||
fields: ([]*main.Field) (len=4 cap=4) {
|
|
||||||
(*main.Field)(0xc0003bccf0)({
|
|
||||||
name: (string) (len=11) "source_name",
|
|
||||||
kind: (string) (len=6) "string",
|
|
||||||
isMap: (bool) false,
|
isMap: (bool) false,
|
||||||
isArray: (bool) false,
|
isArray: (bool) false,
|
||||||
isEnum: (bool) false,
|
isEnum: (bool) false,
|
||||||
isMessage: (bool) false,
|
isMessage: (bool) false,
|
||||||
isOptional: (bool) false
|
isOptional: (bool) false,
|
||||||
}),
|
oneOfName: (string) ""
|
||||||
(*main.Field)(0xc0003bcd20)({
|
})
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
(string) (len=13) "ConfigRequest": (*main.Message)(0xc0003c9560)({
|
||||||
|
fullName: (string) (len=13) "ConfigRequest",
|
||||||
|
name: (string) (len=13) "ConfigRequest",
|
||||||
|
fields: (map[string]*main.Field) (len=4) {
|
||||||
|
(string) (len=9) "relay_url": (*main.Field)(0xc0003ee500)({
|
||||||
name: (string) (len=9) "relay_url",
|
name: (string) (len=9) "relay_url",
|
||||||
kind: (string) (len=6) "string",
|
kind: (string) (len=6) "string",
|
||||||
isMap: (bool) false,
|
isMap: (bool) false,
|
||||||
isArray: (bool) false,
|
isArray: (bool) false,
|
||||||
isEnum: (bool) false,
|
isEnum: (bool) false,
|
||||||
isMessage: (bool) false,
|
isMessage: (bool) false,
|
||||||
isOptional: (bool) false
|
isOptional: (bool) false,
|
||||||
|
oneOfName: (string) ""
|
||||||
}),
|
}),
|
||||||
(*main.Field)(0xc0003bcd50)({
|
(string) (len=18) "automate_liquidity": (*main.Field)(0xc0003ee540)({
|
||||||
name: (string) (len=18) "automate_liquidity",
|
name: (string) (len=18) "automate_liquidity",
|
||||||
kind: (string) (len=4) "bool",
|
kind: (string) (len=4) "bool",
|
||||||
isMap: (bool) false,
|
isMap: (bool) false,
|
||||||
isArray: (bool) false,
|
isArray: (bool) false,
|
||||||
isEnum: (bool) false,
|
isEnum: (bool) false,
|
||||||
isMessage: (bool) false,
|
isMessage: (bool) false,
|
||||||
isOptional: (bool) false
|
isOptional: (bool) false,
|
||||||
|
oneOfName: (string) ""
|
||||||
}),
|
}),
|
||||||
(*main.Field)(0xc0003bcd80)({
|
(string) (len=21) "push_backups_to_nostr": (*main.Field)(0xc0003ee580)({
|
||||||
name: (string) (len=21) "push_backups_to_nostr",
|
name: (string) (len=21) "push_backups_to_nostr",
|
||||||
kind: (string) (len=4) "bool",
|
kind: (string) (len=4) "bool",
|
||||||
isMap: (bool) false,
|
isMap: (bool) false,
|
||||||
isArray: (bool) false,
|
isArray: (bool) false,
|
||||||
isEnum: (bool) false,
|
isEnum: (bool) false,
|
||||||
isMessage: (bool) false,
|
isMessage: (bool) false,
|
||||||
isOptional: (bool) false
|
isOptional: (bool) false,
|
||||||
|
oneOfName: (string) ""
|
||||||
|
}),
|
||||||
|
(string) (len=11) "source_name": (*main.Field)(0xc0003ee4c0)({
|
||||||
|
name: (string) (len=11) "source_name",
|
||||||
|
kind: (string) (len=6) "string",
|
||||||
|
isMap: (bool) false,
|
||||||
|
isArray: (bool) false,
|
||||||
|
isEnum: (bool) false,
|
||||||
|
isMessage: (bool) false,
|
||||||
|
isOptional: (bool) false,
|
||||||
|
oneOfName: (string) ""
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
(string) (len=14) "ConfigResponse": (*main.Message)(0xc0003ee240)({
|
(string) (len=24) "AdminConnectInfoResponse": (*main.Message)(0xc0003c95c0)({
|
||||||
fullName: (string) (len=14) "ConfigResponse",
|
fullName: (string) (len=24) "AdminConnectInfoResponse",
|
||||||
name: (string) (len=14) "ConfigResponse",
|
name: (string) (len=24) "AdminConnectInfoResponse",
|
||||||
fields: ([]*main.Field) (len=3 cap=4) {
|
fields: (map[string]*main.Field) (len=2) {
|
||||||
(*main.Field)(0xc0003bcdb0)({
|
(string) (len=8) "nprofile": (*main.Field)(0xc0003ee5c0)({
|
||||||
name: (string) (len=19) "already_initialized",
|
name: (string) (len=8) "nprofile",
|
||||||
|
kind: (string) (len=6) "string",
|
||||||
|
isMap: (bool) false,
|
||||||
|
isArray: (bool) false,
|
||||||
|
isEnum: (bool) false,
|
||||||
|
isMessage: (bool) false,
|
||||||
|
isOptional: (bool) false,
|
||||||
|
oneOfName: (string) ""
|
||||||
|
}),
|
||||||
|
(string) (len=37) "AdminConnectInfoResponse_connect_info": (*main.Field)(0xc0003eea80)({
|
||||||
|
name: (string) (len=12) "connect_info",
|
||||||
|
kind: (string) (len=37) "AdminConnectInfoResponse_connect_info",
|
||||||
|
isMap: (bool) false,
|
||||||
|
isArray: (bool) false,
|
||||||
|
isEnum: (bool) false,
|
||||||
|
isMessage: (bool) false,
|
||||||
|
isOptional: (bool) false,
|
||||||
|
oneOfName: (string) (len=12) "connect_info"
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
(string) (len=20) "ServiceStateResponse": (*main.Message)(0xc0003c9620)({
|
||||||
|
fullName: (string) (len=20) "ServiceStateResponse",
|
||||||
|
name: (string) (len=20) "ServiceStateResponse",
|
||||||
|
fields: (map[string]*main.Field) (len=8) {
|
||||||
|
(string) (len=10) "admin_npub": (*main.Field)(0xc0003ee700)({
|
||||||
|
name: (string) (len=10) "admin_npub",
|
||||||
|
kind: (string) (len=6) "string",
|
||||||
|
isMap: (bool) false,
|
||||||
|
isArray: (bool) false,
|
||||||
|
isEnum: (bool) false,
|
||||||
|
isMessage: (bool) false,
|
||||||
|
isOptional: (bool) false,
|
||||||
|
oneOfName: (string) ""
|
||||||
|
}),
|
||||||
|
(string) (len=15) "relay_connected": (*main.Field)(0xc0003ee740)({
|
||||||
|
name: (string) (len=15) "relay_connected",
|
||||||
kind: (string) (len=4) "bool",
|
kind: (string) (len=4) "bool",
|
||||||
isMap: (bool) false,
|
isMap: (bool) false,
|
||||||
isArray: (bool) false,
|
isArray: (bool) false,
|
||||||
isEnum: (bool) false,
|
isEnum: (bool) false,
|
||||||
isMessage: (bool) false,
|
isMessage: (bool) false,
|
||||||
isOptional: (bool) false
|
isOptional: (bool) false,
|
||||||
|
oneOfName: (string) ""
|
||||||
}),
|
}),
|
||||||
(*main.Field)(0xc0003bcde0)({
|
(string) (len=9) "lnd_state": (*main.Field)(0xc0003ee780)({
|
||||||
name: (string) (len=4) "seed",
|
name: (string) (len=9) "lnd_state",
|
||||||
|
kind: (string) (len=8) "LndState",
|
||||||
|
isMap: (bool) false,
|
||||||
|
isArray: (bool) false,
|
||||||
|
isEnum: (bool) true,
|
||||||
|
isMessage: (bool) false,
|
||||||
|
isOptional: (bool) false,
|
||||||
|
oneOfName: (string) ""
|
||||||
|
}),
|
||||||
|
(string) (len=11) "watchdog_ok": (*main.Field)(0xc0003ee7c0)({
|
||||||
|
name: (string) (len=11) "watchdog_ok",
|
||||||
|
kind: (string) (len=4) "bool",
|
||||||
|
isMap: (bool) false,
|
||||||
|
isArray: (bool) false,
|
||||||
|
isEnum: (bool) false,
|
||||||
|
isMessage: (bool) false,
|
||||||
|
isOptional: (bool) false,
|
||||||
|
oneOfName: (string) ""
|
||||||
|
}),
|
||||||
|
(string) (len=8) "http_url": (*main.Field)(0xc0003ee800)({
|
||||||
|
name: (string) (len=8) "http_url",
|
||||||
|
kind: (string) (len=6) "string",
|
||||||
|
isMap: (bool) false,
|
||||||
|
isArray: (bool) false,
|
||||||
|
isEnum: (bool) false,
|
||||||
|
isMessage: (bool) false,
|
||||||
|
isOptional: (bool) false,
|
||||||
|
oneOfName: (string) ""
|
||||||
|
}),
|
||||||
|
(string) (len=8) "nprofile": (*main.Field)(0xc0003ee840)({
|
||||||
|
name: (string) (len=8) "nprofile",
|
||||||
|
kind: (string) (len=6) "string",
|
||||||
|
isMap: (bool) false,
|
||||||
|
isArray: (bool) false,
|
||||||
|
isEnum: (bool) false,
|
||||||
|
isMessage: (bool) false,
|
||||||
|
isOptional: (bool) false,
|
||||||
|
oneOfName: (string) ""
|
||||||
|
}),
|
||||||
|
(string) (len=13) "provider_name": (*main.Field)(0xc0003ee680)({
|
||||||
|
name: (string) (len=13) "provider_name",
|
||||||
|
kind: (string) (len=6) "string",
|
||||||
|
isMap: (bool) false,
|
||||||
|
isArray: (bool) false,
|
||||||
|
isEnum: (bool) false,
|
||||||
|
isMessage: (bool) false,
|
||||||
|
isOptional: (bool) false,
|
||||||
|
oneOfName: (string) ""
|
||||||
|
}),
|
||||||
|
(string) (len=6) "relays": (*main.Field)(0xc0003ee6c0)({
|
||||||
|
name: (string) (len=6) "relays",
|
||||||
kind: (string) (len=6) "string",
|
kind: (string) (len=6) "string",
|
||||||
isMap: (bool) false,
|
isMap: (bool) false,
|
||||||
isArray: (bool) true,
|
isArray: (bool) true,
|
||||||
isEnum: (bool) false,
|
isEnum: (bool) false,
|
||||||
isMessage: (bool) false,
|
isMessage: (bool) false,
|
||||||
isOptional: (bool) false
|
isOptional: (bool) false,
|
||||||
}),
|
oneOfName: (string) ""
|
||||||
(*main.Field)(0xc0003bce10)({
|
|
||||||
name: (string) (len=15) "confirmation_id",
|
|
||||||
kind: (string) (len=6) "string",
|
|
||||||
isMap: (bool) false,
|
|
||||||
isArray: (bool) false,
|
|
||||||
isEnum: (bool) false,
|
|
||||||
isMessage: (bool) false,
|
|
||||||
isOptional: (bool) false
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}),
|
|
||||||
(string) (len=14) "ConfirmRequest": (*main.Message)(0xc0003ee280)({
|
|
||||||
fullName: (string) (len=14) "ConfirmRequest",
|
|
||||||
name: (string) (len=14) "ConfirmRequest",
|
|
||||||
fields: ([]*main.Field) (len=1 cap=1) {
|
|
||||||
(*main.Field)(0xc0003bce40)({
|
|
||||||
name: (string) (len=15) "confirmation_id",
|
|
||||||
kind: (string) (len=6) "string",
|
|
||||||
isMap: (bool) false,
|
|
||||||
isArray: (bool) false,
|
|
||||||
isEnum: (bool) false,
|
|
||||||
isMessage: (bool) false,
|
|
||||||
isOptional: (bool) false
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
(string) (len=15) "ConfirmResponse": (*main.Message)(0xc0003ee2c0)({
|
|
||||||
fullName: (string) (len=15) "ConfirmResponse",
|
|
||||||
name: (string) (len=15) "ConfirmResponse",
|
|
||||||
fields: ([]*main.Field) (len=1 cap=1) {
|
|
||||||
(*main.Field)(0xc0003bce70)({
|
|
||||||
name: (string) (len=9) "admin_key",
|
|
||||||
kind: (string) (len=6) "string",
|
|
||||||
isMap: (bool) false,
|
|
||||||
isArray: (bool) false,
|
|
||||||
isEnum: (bool) false,
|
|
||||||
isMessage: (bool) false,
|
|
||||||
isOptional: (bool) false
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
(string) (len=5) "Empty": (*main.Message)(0xc0003ee080)({
|
|
||||||
fullName: (string) (len=5) "Empty",
|
|
||||||
name: (string) (len=5) "Empty",
|
|
||||||
fields: ([]*main.Field) <nil>
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
parsing file: wizard_structs 6
|
(map[string][]*main.Field) (len=1) {
|
||||||
|
(string) (len=37) "AdminConnectInfoResponse_connect_info": ([]*main.Field) (len=2 cap=2) {
|
||||||
|
(*main.Field)(0xc0003ee600)({
|
||||||
|
name: (string) (len=11) "admin_token",
|
||||||
|
kind: (string) (len=6) "string",
|
||||||
|
isMap: (bool) false,
|
||||||
|
isArray: (bool) false,
|
||||||
|
isEnum: (bool) false,
|
||||||
|
isMessage: (bool) false,
|
||||||
|
isOptional: (bool) false,
|
||||||
|
oneOfName: (string) (len=12) "connect_info"
|
||||||
|
}),
|
||||||
|
(*main.Field)(0xc0003ee640)({
|
||||||
|
name: (string) (len=13) "enrolled_npub",
|
||||||
|
kind: (string) (len=6) "string",
|
||||||
|
isMap: (bool) false,
|
||||||
|
isArray: (bool) false,
|
||||||
|
isEnum: (bool) false,
|
||||||
|
isMessage: (bool) false,
|
||||||
|
isOptional: (bool) false,
|
||||||
|
oneOfName: (string) (len=12) "connect_info"
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
parsing file: wizard_structs 5
|
||||||
parsing file: wizard_methods 2
|
parsing file: wizard_methods 2
|
||||||
-> [{guest Guest map[]}]
|
-> [{guest Guest map[]}]
|
||||||
|
|
||||||
|
([]interface {}) <nil>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -64,29 +64,45 @@ export default (methods: Types.ServerMethods, opts: ServerOptions) => {
|
||||||
if (error !== null) return logErrorAndReturnResponse(error, 'invalid request body', res, logger, { ...info, ...stats, ...authContext }, opts.metricsCallback)
|
if (error !== null) return logErrorAndReturnResponse(error, 'invalid request body', res, logger, { ...info, ...stats, ...authContext }, opts.metricsCallback)
|
||||||
const query = req.query
|
const query = req.query
|
||||||
const params = req.params
|
const params = req.params
|
||||||
const response = await methods.WizardConfig({rpcName:'WizardConfig', ctx:authContext , req: request})
|
await methods.WizardConfig({rpcName:'WizardConfig', ctx:authContext , req: request})
|
||||||
|
stats.handle = process.hrtime.bigint()
|
||||||
|
res.json({status: 'OK'})
|
||||||
|
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.GetAdminConnectInfo) throw new Error('method: GetAdminConnectInfo is not implemented')
|
||||||
|
app.get('/wizard/admin_connect_info', async (req, res) => {
|
||||||
|
const info: Types.RequestInfo = { rpcName: 'GetAdminConnectInfo', batch: false, nostr: false, batchSize: 0}
|
||||||
|
const stats: Types.RequestStats = { startMs:req.startTimeMs || 0, start:req.startTime || 0n, parse: process.hrtime.bigint(), guard: 0n, validate: 0n, handle: 0n }
|
||||||
|
let authCtx: Types.AuthContext = {}
|
||||||
|
try {
|
||||||
|
if (!methods.GetAdminConnectInfo) throw new Error('method: GetAdminConnectInfo is not implemented')
|
||||||
|
const authContext = await opts.GuestAuthGuard(req.headers['authorization'])
|
||||||
|
authCtx = authContext
|
||||||
|
stats.guard = process.hrtime.bigint()
|
||||||
|
stats.validate = stats.guard
|
||||||
|
const query = req.query
|
||||||
|
const params = req.params
|
||||||
|
const response = await methods.GetAdminConnectInfo({rpcName:'GetAdminConnectInfo', ctx:authContext })
|
||||||
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 }])
|
||||||
} 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.WizardConfirm) throw new Error('method: WizardConfirm is not implemented')
|
if (!opts.allowNotImplementedMethods && !methods.GetServiceState) throw new Error('method: GetServiceState is not implemented')
|
||||||
app.post('/wizard/confirm', async (req, res) => {
|
app.get('/wizard/service_state', async (req, res) => {
|
||||||
const info: Types.RequestInfo = { rpcName: 'WizardConfirm', batch: false, nostr: false, batchSize: 0}
|
const info: Types.RequestInfo = { rpcName: 'GetServiceState', batch: false, nostr: false, batchSize: 0}
|
||||||
const stats: Types.RequestStats = { startMs:req.startTimeMs || 0, start:req.startTime || 0n, parse: process.hrtime.bigint(), guard: 0n, validate: 0n, handle: 0n }
|
const stats: Types.RequestStats = { startMs:req.startTimeMs || 0, 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.WizardConfirm) throw new Error('method: WizardConfirm is not implemented')
|
if (!methods.GetServiceState) throw new Error('method: GetServiceState is not implemented')
|
||||||
const authContext = await opts.GuestAuthGuard(req.headers['authorization'])
|
const authContext = await opts.GuestAuthGuard(req.headers['authorization'])
|
||||||
authCtx = authContext
|
authCtx = authContext
|
||||||
stats.guard = process.hrtime.bigint()
|
stats.guard = process.hrtime.bigint()
|
||||||
const request = req.body
|
stats.validate = stats.guard
|
||||||
const error = Types.ConfirmRequestValidate(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 query = req.query
|
||||||
const params = req.params
|
const params = req.params
|
||||||
const response = await methods.WizardConfirm({rpcName:'WizardConfirm', ctx:authContext , req: request})
|
const response = await methods.GetServiceState({rpcName:'GetServiceState', ctx:authContext })
|
||||||
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 }])
|
||||||
|
|
@ -99,6 +115,6 @@ export default (methods: Types.ServerMethods, opts: ServerOptions) => {
|
||||||
var server: { close: () => void } | undefined
|
var server: { close: () => void } | undefined
|
||||||
return {
|
return {
|
||||||
Close: () => { if (!server) { throw new Error('tried closing server before starting') } else server.close() },
|
Close: () => { if (!server) { throw new Error('tried closing server before starting') } else server.close() },
|
||||||
Listen: (port: number) => { server = app.listen(port, () => logger.log('Example app listening on port ' + port)) }
|
Listen: (port: number) => { server = app.listen(port, () => logger.log('Wizard listening on port ' + port)) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,30 +26,41 @@ export default (params: ClientParams) => ({
|
||||||
}
|
}
|
||||||
return { status: 'ERROR', reason: 'invalid response' }
|
return { status: 'ERROR', reason: 'invalid response' }
|
||||||
},
|
},
|
||||||
WizardConfig: async (request: Types.ConfigRequest): Promise<ResultError | ({ status: 'OK' }& Types.ConfigResponse)> => {
|
WizardConfig: async (request: Types.ConfigRequest): 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')
|
||||||
let finalRoute = '/wizard/config'
|
let finalRoute = '/wizard/config'
|
||||||
const { data } = await axios.post(params.baseUrl + finalRoute, request, { headers: { 'authorization': auth } })
|
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 === 'ERROR' && typeof data.reason === 'string') return data
|
||||||
if (data.status === 'OK') {
|
if (data.status === 'OK') {
|
||||||
const result = data
|
return data
|
||||||
if(!params.checkResult) return { status: 'OK', ...result }
|
|
||||||
const error = Types.ConfigResponseValidate(result)
|
|
||||||
if (error === null) { return { status: 'OK', ...result } } else return { status: 'ERROR', reason: error.message }
|
|
||||||
}
|
}
|
||||||
return { status: 'ERROR', reason: 'invalid response' }
|
return { status: 'ERROR', reason: 'invalid response' }
|
||||||
},
|
},
|
||||||
WizardConfirm: async (request: Types.ConfirmRequest): Promise<ResultError | ({ status: 'OK' }& Types.ConfirmResponse)> => {
|
GetAdminConnectInfo: async (): Promise<ResultError | ({ status: 'OK' }& Types.AdminConnectInfoResponse)> => {
|
||||||
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')
|
||||||
let finalRoute = '/wizard/confirm'
|
let finalRoute = '/wizard/admin_connect_info'
|
||||||
const { data } = await axios.post(params.baseUrl + finalRoute, request, { headers: { 'authorization': auth } })
|
const { data } = await axios.get(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') {
|
||||||
const result = data
|
const result = data
|
||||||
if(!params.checkResult) return { status: 'OK', ...result }
|
if(!params.checkResult) return { status: 'OK', ...result }
|
||||||
const error = Types.ConfirmResponseValidate(result)
|
const error = Types.AdminConnectInfoResponseValidate(result)
|
||||||
|
if (error === null) { return { status: 'OK', ...result } } else return { status: 'ERROR', reason: error.message }
|
||||||
|
}
|
||||||
|
return { status: 'ERROR', reason: 'invalid response' }
|
||||||
|
},
|
||||||
|
GetServiceState: async (): Promise<ResultError | ({ status: 'OK' }& Types.ServiceStateResponse)> => {
|
||||||
|
const auth = await params.retrieveGuestAuth()
|
||||||
|
if (auth === null) throw new Error('retrieveGuestAuth() returned null')
|
||||||
|
let finalRoute = '/wizard/service_state'
|
||||||
|
const { data } = await axios.get(params.baseUrl + finalRoute, { 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.ServiceStateResponseValidate(result)
|
||||||
if (error === null) { return { status: 'OK', ...result } } else return { status: 'ERROR', reason: error.message }
|
if (error === null) { return { status: 'OK', ...result } } else return { status: 'ERROR', reason: error.message }
|
||||||
}
|
}
|
||||||
return { status: 'ERROR', reason: 'invalid response' }
|
return { status: 'ERROR', reason: 'invalid response' }
|
||||||
|
|
|
||||||
|
|
@ -6,97 +6,43 @@ export type RequestStats = { startMs:number, start:bigint, parse: bigint, guard:
|
||||||
export type RequestMetric = AuthContext & RequestInfo & RequestStats & { error?: string }
|
export type RequestMetric = AuthContext & RequestInfo & RequestStats & { error?: string }
|
||||||
export type GuestContext = {
|
export type GuestContext = {
|
||||||
}
|
}
|
||||||
export type GuestMethodInputs = WizardState_Input | WizardConfig_Input | WizardConfirm_Input
|
export type GuestMethodInputs = WizardState_Input | WizardConfig_Input | GetAdminConnectInfo_Input | GetServiceState_Input
|
||||||
export type GuestMethodOutputs = WizardState_Output | WizardConfig_Output | WizardConfirm_Output
|
export type GuestMethodOutputs = WizardState_Output | WizardConfig_Output | GetAdminConnectInfo_Output | GetServiceState_Output
|
||||||
export type AuthContext = GuestContext
|
export type AuthContext = GuestContext
|
||||||
|
|
||||||
export type WizardState_Input = {rpcName:'WizardState'}
|
export type WizardState_Input = {rpcName:'WizardState'}
|
||||||
export type WizardState_Output = ResultError | ({ status: 'OK' } & StateResponse)
|
export type WizardState_Output = ResultError | ({ status: 'OK' } & StateResponse)
|
||||||
|
|
||||||
export type WizardConfig_Input = {rpcName:'WizardConfig', req: ConfigRequest}
|
export type WizardConfig_Input = {rpcName:'WizardConfig', req: ConfigRequest}
|
||||||
export type WizardConfig_Output = ResultError | ({ status: 'OK' } & ConfigResponse)
|
export type WizardConfig_Output = ResultError | { status: 'OK' }
|
||||||
|
|
||||||
export type WizardConfirm_Input = {rpcName:'WizardConfirm', req: ConfirmRequest}
|
export type GetAdminConnectInfo_Input = {rpcName:'GetAdminConnectInfo'}
|
||||||
export type WizardConfirm_Output = ResultError | ({ status: 'OK' } & ConfirmResponse)
|
export type GetAdminConnectInfo_Output = ResultError | ({ status: 'OK' } & AdminConnectInfoResponse)
|
||||||
|
|
||||||
|
export type GetServiceState_Input = {rpcName:'GetServiceState'}
|
||||||
|
export type GetServiceState_Output = ResultError | ({ status: 'OK' } & ServiceStateResponse)
|
||||||
|
|
||||||
export type ServerMethods = {
|
export type ServerMethods = {
|
||||||
WizardState?: (req: WizardState_Input & {ctx: GuestContext }) => Promise<StateResponse>
|
WizardState?: (req: WizardState_Input & {ctx: GuestContext }) => Promise<StateResponse>
|
||||||
WizardConfig?: (req: WizardConfig_Input & {ctx: GuestContext }) => Promise<ConfigResponse>
|
WizardConfig?: (req: WizardConfig_Input & {ctx: GuestContext }) => Promise<void>
|
||||||
WizardConfirm?: (req: WizardConfirm_Input & {ctx: GuestContext }) => Promise<ConfirmResponse>
|
GetAdminConnectInfo?: (req: GetAdminConnectInfo_Input & {ctx: GuestContext }) => Promise<AdminConnectInfoResponse>
|
||||||
|
GetServiceState?: (req: GetServiceState_Input & {ctx: GuestContext }) => Promise<ServiceStateResponse>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum LndState {
|
||||||
|
OFFLINE = 'OFFLINE',
|
||||||
|
SYNCING = 'SYNCING',
|
||||||
|
ONLINE = 'ONLINE',
|
||||||
|
}
|
||||||
|
export const enumCheckLndState = (e?: LndState): boolean => {
|
||||||
|
for (const v in LndState) if (e === v) return true
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
export type OptionsBaseMessage = {
|
export type OptionsBaseMessage = {
|
||||||
allOptionalsAreSet?: true
|
allOptionalsAreSet?: true
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ConfigResponse = {
|
|
||||||
already_initialized: boolean
|
|
||||||
seed: string[]
|
|
||||||
confirmation_id: string
|
|
||||||
}
|
|
||||||
export const ConfigResponseOptionalFields: [] = []
|
|
||||||
export type ConfigResponseOptions = OptionsBaseMessage & {
|
|
||||||
checkOptionalsAreSet?: []
|
|
||||||
already_initialized_CustomCheck?: (v: boolean) => boolean
|
|
||||||
seed_CustomCheck?: (v: string[]) => boolean
|
|
||||||
confirmation_id_CustomCheck?: (v: string) => boolean
|
|
||||||
}
|
|
||||||
export const ConfigResponseValidate = (o?: ConfigResponse, opts: ConfigResponseOptions = {}, path: string = 'ConfigResponse::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 (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null')
|
|
||||||
|
|
||||||
if (typeof o.already_initialized !== 'boolean') return new Error(`${path}.already_initialized: is not a boolean`)
|
|
||||||
if (opts.already_initialized_CustomCheck && !opts.already_initialized_CustomCheck(o.already_initialized)) return new Error(`${path}.already_initialized: custom check failed`)
|
|
||||||
|
|
||||||
if (!Array.isArray(o.seed)) return new Error(`${path}.seed: is not an array`)
|
|
||||||
for (let index = 0; index < o.seed.length; index++) {
|
|
||||||
if (typeof o.seed[index] !== 'string') return new Error(`${path}.seed[${index}]: is not a string`)
|
|
||||||
}
|
|
||||||
if (opts.seed_CustomCheck && !opts.seed_CustomCheck(o.seed)) return new Error(`${path}.seed: custom check failed`)
|
|
||||||
|
|
||||||
if (typeof o.confirmation_id !== 'string') return new Error(`${path}.confirmation_id: is not a string`)
|
|
||||||
if (opts.confirmation_id_CustomCheck && !opts.confirmation_id_CustomCheck(o.confirmation_id)) return new Error(`${path}.confirmation_id: custom check failed`)
|
|
||||||
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
export type ConfirmRequest = {
|
|
||||||
confirmation_id: string
|
|
||||||
}
|
|
||||||
export const ConfirmRequestOptionalFields: [] = []
|
|
||||||
export type ConfirmRequestOptions = OptionsBaseMessage & {
|
|
||||||
checkOptionalsAreSet?: []
|
|
||||||
confirmation_id_CustomCheck?: (v: string) => boolean
|
|
||||||
}
|
|
||||||
export const ConfirmRequestValidate = (o?: ConfirmRequest, opts: ConfirmRequestOptions = {}, path: string = 'ConfirmRequest::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 (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null')
|
|
||||||
|
|
||||||
if (typeof o.confirmation_id !== 'string') return new Error(`${path}.confirmation_id: is not a string`)
|
|
||||||
if (opts.confirmation_id_CustomCheck && !opts.confirmation_id_CustomCheck(o.confirmation_id)) return new Error(`${path}.confirmation_id: custom check failed`)
|
|
||||||
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
export type ConfirmResponse = {
|
|
||||||
admin_key: string
|
|
||||||
}
|
|
||||||
export const ConfirmResponseOptionalFields: [] = []
|
|
||||||
export type ConfirmResponseOptions = OptionsBaseMessage & {
|
|
||||||
checkOptionalsAreSet?: []
|
|
||||||
admin_key_CustomCheck?: (v: string) => boolean
|
|
||||||
}
|
|
||||||
export const ConfirmResponseValidate = (o?: ConfirmResponse, opts: ConfirmResponseOptions = {}, path: string = 'ConfirmResponse::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 (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null')
|
|
||||||
|
|
||||||
if (typeof o.admin_key !== 'string') return new Error(`${path}.admin_key: is not a string`)
|
|
||||||
if (opts.admin_key_CustomCheck && !opts.admin_key_CustomCheck(o.admin_key)) return new Error(`${path}.admin_key: custom check failed`)
|
|
||||||
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
export type Empty = {
|
export type Empty = {
|
||||||
}
|
}
|
||||||
export const EmptyOptionalFields: [] = []
|
export const EmptyOptionalFields: [] = []
|
||||||
|
|
@ -111,19 +57,24 @@ export const EmptyValidate = (o?: Empty, opts: EmptyOptions = {}, path: string =
|
||||||
}
|
}
|
||||||
|
|
||||||
export type StateResponse = {
|
export type StateResponse = {
|
||||||
already_initialized: boolean
|
config_sent: boolean
|
||||||
|
admin_linked: boolean
|
||||||
}
|
}
|
||||||
export const StateResponseOptionalFields: [] = []
|
export const StateResponseOptionalFields: [] = []
|
||||||
export type StateResponseOptions = OptionsBaseMessage & {
|
export type StateResponseOptions = OptionsBaseMessage & {
|
||||||
checkOptionalsAreSet?: []
|
checkOptionalsAreSet?: []
|
||||||
already_initialized_CustomCheck?: (v: boolean) => boolean
|
config_sent_CustomCheck?: (v: boolean) => boolean
|
||||||
|
admin_linked_CustomCheck?: (v: boolean) => boolean
|
||||||
}
|
}
|
||||||
export const StateResponseValidate = (o?: StateResponse, opts: StateResponseOptions = {}, path: string = 'StateResponse::root.'): Error | null => {
|
export const StateResponseValidate = (o?: StateResponse, opts: StateResponseOptions = {}, path: string = 'StateResponse::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')
|
||||||
if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null')
|
if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null')
|
||||||
|
|
||||||
if (typeof o.already_initialized !== 'boolean') return new Error(`${path}.already_initialized: is not a boolean`)
|
if (typeof o.config_sent !== 'boolean') return new Error(`${path}.config_sent: is not a boolean`)
|
||||||
if (opts.already_initialized_CustomCheck && !opts.already_initialized_CustomCheck(o.already_initialized)) return new Error(`${path}.already_initialized: custom check failed`)
|
if (opts.config_sent_CustomCheck && !opts.config_sent_CustomCheck(o.config_sent)) return new Error(`${path}.config_sent: custom check failed`)
|
||||||
|
|
||||||
|
if (typeof o.admin_linked !== 'boolean') return new Error(`${path}.admin_linked: is not a boolean`)
|
||||||
|
if (opts.admin_linked_CustomCheck && !opts.admin_linked_CustomCheck(o.admin_linked)) return new Error(`${path}.admin_linked: custom check failed`)
|
||||||
|
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
@ -137,10 +88,10 @@ export type ConfigRequest = {
|
||||||
export const ConfigRequestOptionalFields: [] = []
|
export const ConfigRequestOptionalFields: [] = []
|
||||||
export type ConfigRequestOptions = OptionsBaseMessage & {
|
export type ConfigRequestOptions = OptionsBaseMessage & {
|
||||||
checkOptionalsAreSet?: []
|
checkOptionalsAreSet?: []
|
||||||
|
push_backups_to_nostr_CustomCheck?: (v: boolean) => boolean
|
||||||
source_name_CustomCheck?: (v: string) => boolean
|
source_name_CustomCheck?: (v: string) => boolean
|
||||||
relay_url_CustomCheck?: (v: string) => boolean
|
relay_url_CustomCheck?: (v: string) => boolean
|
||||||
automate_liquidity_CustomCheck?: (v: boolean) => boolean
|
automate_liquidity_CustomCheck?: (v: boolean) => boolean
|
||||||
push_backups_to_nostr_CustomCheck?: (v: boolean) => boolean
|
|
||||||
}
|
}
|
||||||
export const ConfigRequestValidate = (o?: ConfigRequest, opts: ConfigRequestOptions = {}, path: string = 'ConfigRequest::root.'): Error | null => {
|
export const ConfigRequestValidate = (o?: ConfigRequest, opts: ConfigRequestOptions = {}, path: string = 'ConfigRequest::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')
|
||||||
|
|
@ -161,3 +112,103 @@ export const ConfigRequestValidate = (o?: ConfigRequest, opts: ConfigRequestOpti
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type AdminConnectInfoResponse = {
|
||||||
|
nprofile: string
|
||||||
|
connect_info: AdminConnectInfoResponse_connect_info
|
||||||
|
}
|
||||||
|
export const AdminConnectInfoResponseOptionalFields: [] = []
|
||||||
|
export type AdminConnectInfoResponseOptions = OptionsBaseMessage & {
|
||||||
|
checkOptionalsAreSet?: []
|
||||||
|
nprofile_CustomCheck?: (v: string) => boolean
|
||||||
|
connect_info_CustomCheck?: (v: AdminConnectInfoResponse_connect_info) => boolean
|
||||||
|
}
|
||||||
|
export const AdminConnectInfoResponseValidate = (o?: AdminConnectInfoResponse, opts: AdminConnectInfoResponseOptions = {}, path: string = 'AdminConnectInfoResponse::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 (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null')
|
||||||
|
|
||||||
|
if (typeof o.nprofile !== 'string') return new Error(`${path}.nprofile: is not a string`)
|
||||||
|
if (opts.nprofile_CustomCheck && !opts.nprofile_CustomCheck(o.nprofile)) return new Error(`${path}.nprofile: custom check failed`)
|
||||||
|
|
||||||
|
const connect_infoErr = AdminConnectInfoResponse_connect_infoValidate(o.connect_info,{}, `${path}.connect_info`)
|
||||||
|
if (connect_infoErr !== null) return connect_infoErr
|
||||||
|
|
||||||
|
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
export type ServiceStateResponse = {
|
||||||
|
http_url: string
|
||||||
|
nprofile: string
|
||||||
|
provider_name: string
|
||||||
|
relays: string[]
|
||||||
|
admin_npub: string
|
||||||
|
relay_connected: boolean
|
||||||
|
lnd_state: LndState
|
||||||
|
watchdog_ok: boolean
|
||||||
|
}
|
||||||
|
export const ServiceStateResponseOptionalFields: [] = []
|
||||||
|
export type ServiceStateResponseOptions = OptionsBaseMessage & {
|
||||||
|
checkOptionalsAreSet?: []
|
||||||
|
http_url_CustomCheck?: (v: string) => boolean
|
||||||
|
nprofile_CustomCheck?: (v: string) => boolean
|
||||||
|
provider_name_CustomCheck?: (v: string) => boolean
|
||||||
|
relays_CustomCheck?: (v: string[]) => boolean
|
||||||
|
admin_npub_CustomCheck?: (v: string) => boolean
|
||||||
|
relay_connected_CustomCheck?: (v: boolean) => boolean
|
||||||
|
lnd_state_CustomCheck?: (v: LndState) => boolean
|
||||||
|
watchdog_ok_CustomCheck?: (v: boolean) => boolean
|
||||||
|
}
|
||||||
|
export const ServiceStateResponseValidate = (o?: ServiceStateResponse, opts: ServiceStateResponseOptions = {}, path: string = 'ServiceStateResponse::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 (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null')
|
||||||
|
|
||||||
|
if (!Array.isArray(o.relays)) return new Error(`${path}.relays: is not an array`)
|
||||||
|
for (let index = 0; index < o.relays.length; index++) {
|
||||||
|
if (typeof o.relays[index] !== 'string') return new Error(`${path}.relays[${index}]: is not a string`)
|
||||||
|
}
|
||||||
|
if (opts.relays_CustomCheck && !opts.relays_CustomCheck(o.relays)) return new Error(`${path}.relays: custom check failed`)
|
||||||
|
|
||||||
|
if (typeof o.admin_npub !== 'string') return new Error(`${path}.admin_npub: is not a string`)
|
||||||
|
if (opts.admin_npub_CustomCheck && !opts.admin_npub_CustomCheck(o.admin_npub)) return new Error(`${path}.admin_npub: custom check failed`)
|
||||||
|
|
||||||
|
if (typeof o.relay_connected !== 'boolean') return new Error(`${path}.relay_connected: is not a boolean`)
|
||||||
|
if (opts.relay_connected_CustomCheck && !opts.relay_connected_CustomCheck(o.relay_connected)) return new Error(`${path}.relay_connected: custom check failed`)
|
||||||
|
|
||||||
|
if (!enumCheckLndState(o.lnd_state)) return new Error(`${path}.lnd_state: is not a valid LndState`)
|
||||||
|
if (opts.lnd_state_CustomCheck && !opts.lnd_state_CustomCheck(o.lnd_state)) return new Error(`${path}.lnd_state: custom check failed`)
|
||||||
|
|
||||||
|
if (typeof o.watchdog_ok !== 'boolean') return new Error(`${path}.watchdog_ok: is not a boolean`)
|
||||||
|
if (opts.watchdog_ok_CustomCheck && !opts.watchdog_ok_CustomCheck(o.watchdog_ok)) return new Error(`${path}.watchdog_ok: custom check failed`)
|
||||||
|
|
||||||
|
if (typeof o.http_url !== 'string') return new Error(`${path}.http_url: is not a string`)
|
||||||
|
if (opts.http_url_CustomCheck && !opts.http_url_CustomCheck(o.http_url)) return new Error(`${path}.http_url: custom check failed`)
|
||||||
|
|
||||||
|
if (typeof o.nprofile !== 'string') return new Error(`${path}.nprofile: is not a string`)
|
||||||
|
if (opts.nprofile_CustomCheck && !opts.nprofile_CustomCheck(o.nprofile)) return new Error(`${path}.nprofile: custom check failed`)
|
||||||
|
|
||||||
|
if (typeof o.provider_name !== 'string') return new Error(`${path}.provider_name: is not a string`)
|
||||||
|
if (opts.provider_name_CustomCheck && !opts.provider_name_CustomCheck(o.provider_name)) return new Error(`${path}.provider_name: custom check failed`)
|
||||||
|
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum AdminConnectInfoResponse_connect_info_type {
|
||||||
|
ADMIN_TOKEN = 'admin_token',
|
||||||
|
ENROLLED_NPUB = 'enrolled_npub',
|
||||||
|
}
|
||||||
|
export type AdminConnectInfoResponse_connect_info =
|
||||||
|
{type:AdminConnectInfoResponse_connect_info_type.ADMIN_TOKEN, admin_token:string}|
|
||||||
|
{type:AdminConnectInfoResponse_connect_info_type.ENROLLED_NPUB, enrolled_npub:string}
|
||||||
|
|
||||||
|
export const AdminConnectInfoResponse_connect_infoValidate = (o?: AdminConnectInfoResponse_connect_info, opts = {}, path: string = 'AdminConnectInfoResponse_connect_info::root.'): Error | null => {
|
||||||
|
if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null')
|
||||||
|
switch (o.type) {
|
||||||
|
case 'admin_token':
|
||||||
|
if (typeof o.admin_token !== 'string') return new Error(`${path}.admin_token: is not a string`)
|
||||||
|
break
|
||||||
|
case 'enrolled_npub':
|
||||||
|
if (typeof o.enrolled_npub !== 'string') return new Error(`${path}.enrolled_npub: is not a string`)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
return new Error(path + ': unknown type'+ o.type)
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ import nostrMiddleware from './nostrMiddleware.js'
|
||||||
import { getLogger } from './services/helpers/logger.js';
|
import { getLogger } from './services/helpers/logger.js';
|
||||||
import { initMainHandler } from './services/main/init.js';
|
import { initMainHandler } from './services/main/init.js';
|
||||||
import { LoadMainSettingsFromEnv } from './services/main/settings.js';
|
import { LoadMainSettingsFromEnv } from './services/main/settings.js';
|
||||||
|
import { encodeNprofile } from './custom-nip19.js';
|
||||||
|
|
||||||
const start = async () => {
|
const start = async () => {
|
||||||
const log = getLogger({})
|
const log = getLogger({})
|
||||||
|
|
@ -16,7 +17,7 @@ const start = async () => {
|
||||||
log("manual process ended")
|
log("manual process ended")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
const { apps, mainHandler, liquidityProviderInfo } = keepOn
|
const { apps, mainHandler, liquidityProviderInfo, wizard } = keepOn
|
||||||
const serverMethods = GetServerMethods(mainHandler)
|
const serverMethods = GetServerMethods(mainHandler)
|
||||||
const nostrSettings = LoadNosrtSettingsFromEnv()
|
const nostrSettings = LoadNosrtSettingsFromEnv()
|
||||||
log("initializing nostr middleware")
|
log("initializing nostr middleware")
|
||||||
|
|
@ -27,6 +28,9 @@ const start = async () => {
|
||||||
log("starting server")
|
log("starting server")
|
||||||
mainHandler.attachNostrSend(Send)
|
mainHandler.attachNostrSend(Send)
|
||||||
mainHandler.StartBeacons()
|
mainHandler.StartBeacons()
|
||||||
|
if (wizard) {
|
||||||
|
wizard.AddConnectInfo(encodeNprofile({ pubkey: liquidityProviderInfo.publicKey, relays: nostrSettings.relays }), nostrSettings.relays)
|
||||||
|
}
|
||||||
const Server = NewServer(serverMethods, serverOptions(mainHandler))
|
const Server = NewServer(serverMethods, serverOptions(mainHandler))
|
||||||
Server.Listen(mainSettings.servicePort)
|
Server.Listen(mainSettings.servicePort)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,20 @@ export default (serverMethods: Types.ServerMethods, mainHandler: Main, nostrSett
|
||||||
const nostrUser = await mainHandler.storage.applicationStorage.GetOrCreateNostrAppUser(app, pub || "")
|
const nostrUser = await mainHandler.storage.applicationStorage.GetOrCreateNostrAppUser(app, pub || "")
|
||||||
return { user_id: nostrUser.user.user_id, app_user_id: nostrUser.identifier, app_id: appId || "" }
|
return { user_id: nostrUser.user.user_id, app_user_id: nostrUser.identifier, app_id: appId || "" }
|
||||||
},
|
},
|
||||||
|
NostrAdminAuthGuard: async (appId, pub) => {
|
||||||
|
const adminNpub = mainHandler.adminManager.GetAdminNpub()
|
||||||
|
if (!adminNpub) { throw new Error("admin access not configured") }
|
||||||
|
if (pub !== adminNpub) { throw new Error("admin access denied") }
|
||||||
|
log("admin access from", pub)
|
||||||
|
return { admin_id: pub }
|
||||||
|
},
|
||||||
|
NostrMetricsAuthGuard: async (appId, pub) => {
|
||||||
|
const adminNpub = mainHandler.adminManager.GetAdminNpub()
|
||||||
|
if (!adminNpub) { throw new Error("admin access not configured") }
|
||||||
|
if (pub !== adminNpub) { throw new Error("admin access denied") }
|
||||||
|
log("operator access from", pub)
|
||||||
|
return { operator_id: pub }
|
||||||
|
},
|
||||||
metricsCallback: metrics => mainHandler.settings.recordPerformance ? mainHandler.metricsManager.AddMetrics(metrics) : null,
|
metricsCallback: metrics => mainHandler.settings.recordPerformance ? mainHandler.metricsManager.AddMetrics(metrics) : null,
|
||||||
logger: { log: console.log, error: err => log(ERROR, err) }
|
logger: { log: console.log, error: err => log(ERROR, err) }
|
||||||
})
|
})
|
||||||
|
|
|
||||||
97
src/services/main/adminManager.ts
Normal file
97
src/services/main/adminManager.ts
Normal file
|
|
@ -0,0 +1,97 @@
|
||||||
|
import fs, { watchFile } from "fs";
|
||||||
|
import crypto from 'crypto'
|
||||||
|
import { getLogger } from "../helpers/logger.js";
|
||||||
|
import { MainSettings, getDataPath } from "./settings.js";
|
||||||
|
import Storage from "../storage/index.js";
|
||||||
|
export class AdminManager {
|
||||||
|
storage: Storage
|
||||||
|
log = getLogger({ component: "adminManager" })
|
||||||
|
adminNpub = ""
|
||||||
|
dataDir: string
|
||||||
|
adminNpubPath: string
|
||||||
|
adminEnrollTokenPath: string
|
||||||
|
interval: NodeJS.Timer
|
||||||
|
constructor(mainSettings: MainSettings, storage: Storage) {
|
||||||
|
this.storage = storage
|
||||||
|
this.dataDir = mainSettings.storageSettings.dataDir
|
||||||
|
this.adminNpubPath = getDataPath(this.dataDir, 'admin.npub')
|
||||||
|
this.adminEnrollTokenPath = getDataPath(this.dataDir, '.admin_enroll')
|
||||||
|
this.start()
|
||||||
|
}
|
||||||
|
Stop = () => {
|
||||||
|
clearInterval(this.interval)
|
||||||
|
}
|
||||||
|
|
||||||
|
GenerateAdminEnrollToken = async () => {
|
||||||
|
const token = crypto.randomBytes(32).toString('hex')
|
||||||
|
fs.writeFileSync(this.adminEnrollTokenPath, token)
|
||||||
|
return token
|
||||||
|
}
|
||||||
|
|
||||||
|
start = () => {
|
||||||
|
const adminNpub = this.ReadAdminNpub()
|
||||||
|
if (adminNpub) {
|
||||||
|
this.adminNpub = adminNpub
|
||||||
|
} else if (!fs.existsSync(this.adminEnrollTokenPath)) {
|
||||||
|
this.GenerateAdminEnrollToken()
|
||||||
|
}
|
||||||
|
this.interval = setInterval(() => {
|
||||||
|
if (!this.adminNpub) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const deleted = !fs.existsSync(this.adminNpubPath)
|
||||||
|
if (deleted) {
|
||||||
|
this.adminNpub = ""
|
||||||
|
this.log("admin npub file deleted")
|
||||||
|
this.GenerateAdminEnrollToken()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
ReadAdminEnrollToken = () => {
|
||||||
|
try {
|
||||||
|
return fs.readFileSync(this.adminEnrollTokenPath, 'utf8').trim()
|
||||||
|
} catch (err: any) {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ReadAdminNpub = () => {
|
||||||
|
try {
|
||||||
|
return fs.readFileSync(this.adminNpubPath, 'utf8').trim()
|
||||||
|
} catch (err: any) {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GetAdminNpub = () => {
|
||||||
|
return this.adminNpub
|
||||||
|
}
|
||||||
|
|
||||||
|
ClearExistingAdmin = () => {
|
||||||
|
try {
|
||||||
|
fs.unlinkSync(this.adminNpubPath)
|
||||||
|
} catch (err: any) { }
|
||||||
|
}
|
||||||
|
|
||||||
|
PromoteUserToAdmin = async (appId: string, appUserId: string, token: string) => {
|
||||||
|
const app = await this.storage.applicationStorage.GetApplication(appId)
|
||||||
|
const appUser = await this.storage.applicationStorage.GetApplicationUser(app, appUserId)
|
||||||
|
const npub = appUser.nostr_public_key
|
||||||
|
if (!npub) {
|
||||||
|
throw new Error("no npub found for user")
|
||||||
|
}
|
||||||
|
let actualToken
|
||||||
|
try {
|
||||||
|
actualToken = fs.readFileSync(this.adminEnrollTokenPath, 'utf8').trim()
|
||||||
|
} catch (err: any) {
|
||||||
|
throw new Error("invalid enroll token")
|
||||||
|
}
|
||||||
|
if (token !== actualToken) {
|
||||||
|
throw new Error("invalid enroll token")
|
||||||
|
}
|
||||||
|
fs.writeFileSync(this.adminNpubPath, npub)
|
||||||
|
fs.unlinkSync(this.adminEnrollTokenPath)
|
||||||
|
this.adminNpub = npub
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -19,6 +19,7 @@ import { LiquidityProvider } from "./liquidityProvider.js"
|
||||||
import { LiquidityManager } from "./liquidityManager.js"
|
import { LiquidityManager } from "./liquidityManager.js"
|
||||||
import { Utils } from "../helpers/utilsWrapper.js"
|
import { Utils } from "../helpers/utilsWrapper.js"
|
||||||
import { RugPullTracker } from "./rugPullTracker.js"
|
import { RugPullTracker } from "./rugPullTracker.js"
|
||||||
|
import { AdminManager } from "./adminManager.js"
|
||||||
|
|
||||||
type UserOperationsSub = {
|
type UserOperationsSub = {
|
||||||
id: string
|
id: string
|
||||||
|
|
@ -33,21 +34,23 @@ export default class {
|
||||||
lnd: LND
|
lnd: LND
|
||||||
settings: MainSettings
|
settings: MainSettings
|
||||||
userOperationsSub: UserOperationsSub | null = null
|
userOperationsSub: UserOperationsSub | null = null
|
||||||
|
adminManager: AdminManager
|
||||||
productManager: ProductManager
|
productManager: ProductManager
|
||||||
applicationManager: ApplicationManager
|
applicationManager: ApplicationManager
|
||||||
appUserManager: AppUserManager
|
appUserManager: AppUserManager
|
||||||
paymentManager: PaymentManager
|
paymentManager: PaymentManager
|
||||||
paymentSubs: Record<string, ((op: Types.UserOperation) => void) | null> = {}
|
paymentSubs: Record<string, ((op: Types.UserOperation) => void) | null> = {}
|
||||||
metricsManager: MetricsManager
|
metricsManager: MetricsManager
|
||||||
liquidityProvider: LiquidityProvider
|
|
||||||
liquidityManager: LiquidityManager
|
liquidityManager: LiquidityManager
|
||||||
|
liquidityProvider: LiquidityProvider
|
||||||
utils: Utils
|
utils: Utils
|
||||||
rugPullTracker: RugPullTracker
|
rugPullTracker: RugPullTracker
|
||||||
nostrSend: NostrSend = () => { getLogger({})("nostr send not initialized yet") }
|
nostrSend: NostrSend = () => { getLogger({})("nostr send not initialized yet") }
|
||||||
constructor(settings: MainSettings, storage: Storage, utils: Utils) {
|
constructor(settings: MainSettings, storage: Storage, adminManager: AdminManager, utils: Utils) {
|
||||||
this.settings = settings
|
this.settings = settings
|
||||||
this.storage = storage
|
this.storage = storage
|
||||||
this.utils = utils
|
this.utils = utils
|
||||||
|
this.adminManager = adminManager
|
||||||
const updateProviderBalance = (b: number) => this.storage.liquidityStorage.IncrementTrackedProviderBalance('lnPub', settings.liquiditySettings.liquidityProviderPub, b)
|
const updateProviderBalance = (b: number) => this.storage.liquidityStorage.IncrementTrackedProviderBalance('lnPub', settings.liquiditySettings.liquidityProviderPub, b)
|
||||||
this.liquidityProvider = new LiquidityProvider(settings.liquiditySettings.liquidityProviderPub, this.utils, this.invoicePaidCb, updateProviderBalance)
|
this.liquidityProvider = new LiquidityProvider(settings.liquiditySettings.liquidityProviderPub, this.utils, this.invoicePaidCb, updateProviderBalance)
|
||||||
this.rugPullTracker = new RugPullTracker(this.storage, this.liquidityProvider)
|
this.rugPullTracker = new RugPullTracker(this.storage, this.liquidityProvider)
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,8 @@ import SanityChecker from "./sanityChecker.js"
|
||||||
import { LoadMainSettingsFromEnv, MainSettings } from "./settings.js"
|
import { LoadMainSettingsFromEnv, MainSettings } from "./settings.js"
|
||||||
import { Utils } from "../helpers/utilsWrapper.js"
|
import { Utils } from "../helpers/utilsWrapper.js"
|
||||||
import { Wizard } from "../wizard/index.js"
|
import { Wizard } from "../wizard/index.js"
|
||||||
|
import { AdminManager } from "./adminManager.js"
|
||||||
|
import { encodeNprofile } from "../../custom-nip19.js"
|
||||||
export type AppData = {
|
export type AppData = {
|
||||||
privateKey: string;
|
privateKey: string;
|
||||||
publicKey: string;
|
publicKey: string;
|
||||||
|
|
@ -21,19 +23,20 @@ export const initMainHandler = async (log: PubLogger, mainSettings: MainSettings
|
||||||
if (manualMigration) {
|
if (manualMigration) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
const unlocker = new Unlocker(mainSettings, storageManager)
|
||||||
|
await unlocker.Unlock()
|
||||||
|
const adminManager = new AdminManager(mainSettings, storageManager)
|
||||||
let reloadedSettings = mainSettings
|
let reloadedSettings = mainSettings
|
||||||
|
let wizard: Wizard | null = null
|
||||||
if (mainSettings.wizard) {
|
if (mainSettings.wizard) {
|
||||||
const wizard = new Wizard(mainSettings, storageManager)
|
wizard = new Wizard(mainSettings, storageManager, adminManager)
|
||||||
const reload = await wizard.WaitUntilConfigured()
|
const reload = await wizard.Configure()
|
||||||
if (reload) {
|
if (reload) {
|
||||||
reloadedSettings = LoadMainSettingsFromEnv()
|
reloadedSettings = LoadMainSettingsFromEnv()
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
const unlocker = new Unlocker(mainSettings, storageManager)
|
|
||||||
await unlocker.Unlock()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const mainHandler = new Main(reloadedSettings, storageManager, utils)
|
const mainHandler = new Main(reloadedSettings, storageManager, adminManager, utils)
|
||||||
await mainHandler.lnd.Warmup()
|
await mainHandler.lnd.Warmup()
|
||||||
if (!reloadedSettings.skipSanityCheck) {
|
if (!reloadedSettings.skipSanityCheck) {
|
||||||
const sanityChecker = new SanityChecker(storageManager, mainHandler.lnd)
|
const sanityChecker = new SanityChecker(storageManager, mainHandler.lnd)
|
||||||
|
|
@ -70,7 +73,7 @@ export const initMainHandler = async (log: PubLogger, mainSettings: MainSettings
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
mainHandler.paymentManager.watchDog.Start()
|
mainHandler.paymentManager.watchDog.Start()
|
||||||
return { mainHandler, apps, liquidityProviderInfo, liquidityProviderApp }
|
return { mainHandler, apps, liquidityProviderInfo, liquidityProviderApp, wizard }
|
||||||
}
|
}
|
||||||
|
|
||||||
const processArgs = async (mainHandler: Main) => {
|
const processArgs = async (mainHandler: Main) => {
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,11 @@ export class LiquidityManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
onNewBlock = async () => {
|
onNewBlock = async () => {
|
||||||
await this.shouldDrainProvider()
|
try {
|
||||||
|
await this.shouldDrainProvider()
|
||||||
|
} catch (err: any) {
|
||||||
|
this.log("error in onNewBlock", err.message || err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
beforeInvoiceCreation = async (amount: number): Promise<'lnd' | 'provider'> => {
|
beforeInvoiceCreation = async (amount: number): Promise<'lnd' | 'provider'> => {
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,8 @@ export class LiquidityProvider {
|
||||||
this.client = newNostrClient({
|
this.client = newNostrClient({
|
||||||
pubDestination: this.pubDestination,
|
pubDestination: this.pubDestination,
|
||||||
retrieveNostrUserAuth: async () => this.myPub,
|
retrieveNostrUserAuth: async () => this.myPub,
|
||||||
|
retrieveNostrAdminAuth: async () => this.myPub,
|
||||||
|
retrieveNostrMetricsAuth: async () => this.myPub,
|
||||||
}, this.clientSend, this.clientSub)
|
}, this.clientSend, this.clientSub)
|
||||||
|
|
||||||
this.configuredInterval = setInterval(() => {
|
this.configuredInterval = setInterval(() => {
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ import { getLogger } from '../helpers/logger.js'
|
||||||
import fs from 'fs'
|
import fs from 'fs'
|
||||||
import crypto from 'crypto';
|
import crypto from 'crypto';
|
||||||
import { LiquiditySettings, LoadLiquiditySettingsFromEnv } from './liquidityManager.js'
|
import { LiquiditySettings, LoadLiquiditySettingsFromEnv } from './liquidityManager.js'
|
||||||
|
|
||||||
export type MainSettings = {
|
export type MainSettings = {
|
||||||
storageSettings: StorageSettings,
|
storageSettings: StorageSettings,
|
||||||
lndSettings: LndSettings,
|
lndSettings: LndSettings,
|
||||||
|
|
@ -44,6 +45,7 @@ export type TestSettings = MainSettings & { lndSettings: { otherNode: NodeSettin
|
||||||
export const LoadMainSettingsFromEnv = (): MainSettings => {
|
export const LoadMainSettingsFromEnv = (): MainSettings => {
|
||||||
const storageSettings = LoadStorageSettingsFromEnv()
|
const storageSettings = LoadStorageSettingsFromEnv()
|
||||||
const outgoingAppUserInvoiceFeeBps = EnvCanBeInteger("OUTGOING_INVOICE_FEE_USER_BPS", 0)
|
const outgoingAppUserInvoiceFeeBps = EnvCanBeInteger("OUTGOING_INVOICE_FEE_USER_BPS", 0)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
watchDogSettings: LoadWatchdogSettingsFromEnv(),
|
watchDogSettings: LoadWatchdogSettingsFromEnv(),
|
||||||
lndSettings: LoadLndSettingsFromEnv(),
|
lndSettings: LoadLndSettingsFromEnv(),
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ export class Unlocker {
|
||||||
settings: MainSettings
|
settings: MainSettings
|
||||||
storage: Storage
|
storage: Storage
|
||||||
abortController = new AbortController()
|
abortController = new AbortController()
|
||||||
pendingSeed: Record<string, EncryptedData> = {}
|
subbedToBackups = false
|
||||||
log = getLogger({ component: "unlocker" })
|
log = getLogger({ component: "unlocker" })
|
||||||
constructor(settings: MainSettings, storage: Storage) {
|
constructor(settings: MainSettings, storage: Storage) {
|
||||||
this.settings = settings
|
this.settings = settings
|
||||||
|
|
@ -46,55 +46,29 @@ export class Unlocker {
|
||||||
return { lndCert, macaroon }
|
return { lndCert, macaroon }
|
||||||
}
|
}
|
||||||
|
|
||||||
IsInitialized = async () => {
|
IsInitialized = () => {
|
||||||
const { macaroon } = await this.getCreds()
|
const { macaroon } = this.getCreds()
|
||||||
return macaroon !== ''
|
return macaroon !== ''
|
||||||
}
|
}
|
||||||
|
|
||||||
InitInteractive = async (): Promise<{ alreadyInitizialized: true } | { alreadyInitizialized: false, seed: string[], confirmationId: string }> => {
|
Unlock = async (): Promise<'created' | 'unlocked' | 'noaction'> => {
|
||||||
const { lndCert, macaroon } = await this.getCreds()
|
const { lndCert, macaroon } = this.getCreds()
|
||||||
if (macaroon !== '') {
|
if (macaroon === "") {
|
||||||
const { ln, pub } = await this.UnlockFlow(lndCert, macaroon)
|
const { ln, pub } = await this.InitFlow(lndCert)
|
||||||
this.subscribeToBackups(ln, pub)
|
this.subscribeToBackups(ln, pub)
|
||||||
return { alreadyInitizialized: true }
|
return 'created'
|
||||||
}
|
}
|
||||||
const unlocker = this.GetUnlockerClient(lndCert)
|
const { ln, pub, action } = await this.UnlockFlow(lndCert, macaroon)
|
||||||
const seed = await this.genSeed(unlocker)
|
|
||||||
const confirmationId = crypto.randomBytes(32).toString('hex')
|
|
||||||
this.pendingSeed[confirmationId] = seed.encryptedSeed
|
|
||||||
return { alreadyInitizialized: false, seed: seed.plaintextSeed, confirmationId }
|
|
||||||
}
|
|
||||||
|
|
||||||
ConfirmInitInteractive = async (confirmationId: string) => {
|
|
||||||
const { lndCert, macaroon } = await this.getCreds()
|
|
||||||
if (macaroon !== '') {
|
|
||||||
const { ln, pub } = await this.UnlockFlow(lndCert, macaroon)
|
|
||||||
this.subscribeToBackups(ln, pub)
|
|
||||||
return { alreadyInitizialized: true }
|
|
||||||
}
|
|
||||||
const seed = this.pendingSeed[confirmationId]
|
|
||||||
if (!seed) {
|
|
||||||
throw new Error("seed not found")
|
|
||||||
}
|
|
||||||
delete this.pendingSeed[confirmationId]
|
|
||||||
const plaintextSeed = this.DecryptWalletSeed(seed)
|
|
||||||
const unlocker = this.GetUnlockerClient(lndCert)
|
|
||||||
const { ln, pub } = await this.initWallet(lndCert, unlocker, { plaintextSeed, encryptedSeed: seed })
|
|
||||||
this.subscribeToBackups(ln, pub)
|
this.subscribeToBackups(ln, pub)
|
||||||
|
return action
|
||||||
}
|
}
|
||||||
|
|
||||||
Unlock = async () => {
|
UnlockFlow = async (lndCert: Buffer, macaroon: string): Promise<{ ln: LightningClient, pub: string, action: 'unlocked' | 'noaction' }> => {
|
||||||
const { lndCert, macaroon } = await this.getCreds()
|
|
||||||
const { ln, pub } = macaroon === "" ? await this.InitFlow(lndCert) : await this.UnlockFlow(lndCert, macaroon)
|
|
||||||
this.subscribeToBackups(ln, pub)
|
|
||||||
}
|
|
||||||
|
|
||||||
UnlockFlow = async (lndCert: Buffer, macaroon: string) => {
|
|
||||||
const ln = this.GetLightningClient(lndCert, macaroon)
|
const ln = this.GetLightningClient(lndCert, macaroon)
|
||||||
const info = await this.GetLndInfo(ln)
|
const info = await this.GetLndInfo(ln)
|
||||||
if (info.ok) {
|
if (info.ok) {
|
||||||
this.log("the wallet is already unlocked with pub:", info.pub)
|
this.log("the wallet is already unlocked with pub:", info.pub)
|
||||||
return { ln, pub: info.pub }
|
return { ln, pub: info.pub, action: 'noaction' }
|
||||||
}
|
}
|
||||||
if (info.failure !== 'locked') {
|
if (info.failure !== 'locked') {
|
||||||
throw new Error("failed to get lnd info for reason: " + info.failure)
|
throw new Error("failed to get lnd info for reason: " + info.failure)
|
||||||
|
|
@ -108,7 +82,7 @@ export class Unlocker {
|
||||||
throw new Error("failed to unlock lnd wallet " + infoAfter.failure)
|
throw new Error("failed to unlock lnd wallet " + infoAfter.failure)
|
||||||
}
|
}
|
||||||
this.log("unlocked wallet with pub:", infoAfter.pub)
|
this.log("unlocked wallet with pub:", infoAfter.pub)
|
||||||
return { ln, pub: infoAfter.pub }
|
return { ln, pub: infoAfter.pub, action: 'unlocked' }
|
||||||
}
|
}
|
||||||
|
|
||||||
InitFlow = async (lndCert: Buffer) => {
|
InitFlow = async (lndCert: Buffer) => {
|
||||||
|
|
@ -254,6 +228,10 @@ export class Unlocker {
|
||||||
}
|
}
|
||||||
|
|
||||||
subscribeToBackups = async (ln: LightningClient, pub: string) => {
|
subscribeToBackups = async (ln: LightningClient, pub: string) => {
|
||||||
|
if (this.subbedToBackups) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.subbedToBackups = true
|
||||||
this.log("subscribing to channel backups for: ", pub)
|
this.log("subscribing to channel backups for: ", pub)
|
||||||
const stream = ln.subscribeChannelBackups({}, { abort: this.abortController.signal })
|
const stream = ln.subscribeChannelBackups({}, { abort: this.abortController.signal })
|
||||||
stream.responses.onMessage(async (msg) => {
|
stream.responses.onMessage(async (msg) => {
|
||||||
|
|
|
||||||
|
|
@ -194,6 +194,7 @@ export default class Handler {
|
||||||
await p
|
await p
|
||||||
sent = true
|
sent = true
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
|
console.log(e)
|
||||||
log(e)
|
log(e)
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
|
|
|
||||||
|
|
@ -214,6 +214,13 @@ export default (mainHandler: Main): Types.ServerMethods => {
|
||||||
})
|
})
|
||||||
if (err != null) throw new Error(err.message)
|
if (err != null) throw new Error(err.message)
|
||||||
return mainHandler.applicationManager.LinkNpubThroughToken(ctx, req)
|
return mainHandler.applicationManager.LinkNpubThroughToken(ctx, req)
|
||||||
}
|
},
|
||||||
|
EnrollAdminToken: async ({ ctx, req }) => {
|
||||||
|
const err = Types.EnrollAdminTokenRequestValidate(req, {
|
||||||
|
admin_token_CustomCheck: token => token !== ''
|
||||||
|
})
|
||||||
|
if (err != null) throw new Error(err.message)
|
||||||
|
return mainHandler.adminManager.PromoteUserToAdmin(ctx.app_id, ctx.app_user_id, req.admin_token)
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -7,6 +7,7 @@ import * as WizardTypes from "../../../proto/wizard_service/autogenerated/ts/typ
|
||||||
import { MainSettings } from "../main/settings.js"
|
import { MainSettings } from "../main/settings.js"
|
||||||
import Storage from '../storage/index.js'
|
import Storage from '../storage/index.js'
|
||||||
import { Unlocker } from "../main/unlocker.js"
|
import { Unlocker } from "../main/unlocker.js"
|
||||||
|
import { AdminManager } from '../main/adminManager.js';
|
||||||
export type WizardSettings = {
|
export type WizardSettings = {
|
||||||
sourceName: string
|
sourceName: string
|
||||||
relayUrl: string
|
relayUrl: string
|
||||||
|
|
@ -17,31 +18,92 @@ const defaultProviderPub = ""
|
||||||
export class Wizard {
|
export class Wizard {
|
||||||
log = getLogger({ component: "wizard" })
|
log = getLogger({ component: "wizard" })
|
||||||
settings: MainSettings
|
settings: MainSettings
|
||||||
unlocker: Unlocker
|
adminManager: AdminManager
|
||||||
initialized = false
|
storage: Storage
|
||||||
configQueue: { res: (reload: boolean) => void }[] = []
|
configQueue: { res: (reload: boolean) => void }[] = []
|
||||||
pendingConfig: WizardSettings | null = null
|
pendingConfig: WizardSettings | null = null
|
||||||
constructor(mainSettings: MainSettings, storage: Storage) {
|
awaitingNprofile: { res: (nprofile: string) => void }[] = []
|
||||||
|
nprofile = ""
|
||||||
|
relays: string[] = []
|
||||||
|
constructor(mainSettings: MainSettings, storage: Storage, adminManager: AdminManager) {
|
||||||
this.settings = mainSettings
|
this.settings = mainSettings
|
||||||
|
this.adminManager = adminManager
|
||||||
|
this.storage = storage
|
||||||
this.log('Starting wizard...')
|
this.log('Starting wizard...')
|
||||||
this.unlocker = new Unlocker(mainSettings, storage)
|
|
||||||
const wizardServer = NewWizardServer({
|
const wizardServer = NewWizardServer({
|
||||||
WizardState: async () => { return { already_initialized: await this.IsInitialized() } },
|
WizardState: async () => { return this.WizardState() },
|
||||||
WizardConfig: async ({ req }) => { return this.wizardConfig(req) },
|
WizardConfig: async ({ req }) => { return this.wizardConfig(req) },
|
||||||
WizardConfirm: async ({ req }) => { return this.wizardConfirm(req) },
|
GetAdminConnectInfo: async () => { return this.GetAdminConnectInfo() },
|
||||||
|
GetServiceState: async () => { return this.GetServiceState() }
|
||||||
}, { GuestAuthGuard: async () => "", metricsCallback: () => { }, staticFiles: 'static' })
|
}, { GuestAuthGuard: async () => "", metricsCallback: () => { }, staticFiles: 'static' })
|
||||||
wizardServer.Listen(mainSettings.servicePort + 1)
|
wizardServer.Listen(mainSettings.servicePort + 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
IsInitialized = () => {
|
GetServiceState = async (): Promise<WizardTypes.ServiceStateResponse> => {
|
||||||
if (this.initialized) {
|
const apps = await this.storage.applicationStorage.GetApplications()
|
||||||
return true
|
const appNamesList = apps.map(app => app.name).join(', ')
|
||||||
|
return {
|
||||||
|
admin_npub: this.adminManager.GetAdminNpub(),
|
||||||
|
http_url: this.settings.serviceUrl,
|
||||||
|
lnd_state: WizardTypes.LndState.OFFLINE,
|
||||||
|
nprofile: this.nprofile,
|
||||||
|
provider_name: appNamesList,
|
||||||
|
relay_connected: false,
|
||||||
|
relays: this.relays,
|
||||||
|
watchdog_ok: false
|
||||||
}
|
}
|
||||||
return this.unlocker.IsInitialized()
|
}
|
||||||
|
WizardState = async (): Promise<WizardTypes.StateResponse> => {
|
||||||
|
return {
|
||||||
|
config_sent: this.pendingConfig !== null,
|
||||||
|
admin_linked: this.adminManager.GetAdminNpub() !== "",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
IsInitialized = () => {
|
||||||
|
return !!this.adminManager.GetAdminNpub()
|
||||||
}
|
}
|
||||||
|
|
||||||
WaitUntilConfigured = async (): Promise<boolean> => {
|
GetAdminConnectInfo = async (): Promise<WizardTypes.AdminConnectInfoResponse> => {
|
||||||
if (this.initialized) {
|
const nprofile = await this.getNprofile()
|
||||||
|
const enrolledAdmin = this.adminManager.GetAdminNpub()
|
||||||
|
if (enrolledAdmin !== "") {
|
||||||
|
return {
|
||||||
|
nprofile, connect_info: {
|
||||||
|
type: WizardTypes.AdminConnectInfoResponse_connect_info_type.ENROLLED_NPUB,
|
||||||
|
enrolled_npub: enrolledAdmin
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const adminEnroll = this.adminManager.ReadAdminEnrollToken()
|
||||||
|
if (adminEnroll !== "") {
|
||||||
|
return {
|
||||||
|
nprofile, connect_info: {
|
||||||
|
type: WizardTypes.AdminConnectInfoResponse_connect_info_type.ADMIN_TOKEN,
|
||||||
|
admin_token: adminEnroll
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new Error("something went wrong initializing admin creds")
|
||||||
|
}
|
||||||
|
|
||||||
|
getNprofile = async (): Promise<string> => {
|
||||||
|
if (this.nprofile !== "") {
|
||||||
|
return this.nprofile
|
||||||
|
}
|
||||||
|
console.log("waiting for nprofile")
|
||||||
|
return new Promise((res) => {
|
||||||
|
this.awaitingNprofile.push({ res })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
AddConnectInfo = (nprofile: string, relays: string[]) => {
|
||||||
|
this.nprofile = nprofile
|
||||||
|
this.awaitingNprofile.forEach(q => q.res(nprofile))
|
||||||
|
this.awaitingNprofile = []
|
||||||
|
}
|
||||||
|
|
||||||
|
Configure = async (): Promise<boolean> => {
|
||||||
|
if (this.IsInitialized() || this.pendingConfig !== null) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return new Promise((res) => {
|
return new Promise((res) => {
|
||||||
|
|
@ -49,80 +111,58 @@ export class Wizard {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
wizardConfig = async (req: WizardTypes.ConfigRequest): Promise<WizardTypes.ConfigResponse> => {
|
wizardConfig = async (req: WizardTypes.ConfigRequest): Promise<void> => {
|
||||||
const err = WizardTypes.ConfigRequestValidate(req, {
|
const err = WizardTypes.ConfigRequestValidate(req, {
|
||||||
source_name_CustomCheck: source => source !== '',
|
source_name_CustomCheck: source => source !== '',
|
||||||
relay_url_CustomCheck: relay => relay !== '',
|
relay_url_CustomCheck: relay => relay !== '',
|
||||||
})
|
})
|
||||||
if (err != null) { throw new Error(err.message) }
|
if (err != null) { throw new Error(err.message) }
|
||||||
|
if (this.IsInitialized() || this.pendingConfig !== null) {
|
||||||
const res = await this.unlocker.InitInteractive()
|
throw new Error("already initialized")
|
||||||
if (res.alreadyInitizialized) {
|
|
||||||
this.initialized = true
|
|
||||||
this.configQueue.forEach(q => q.res(false))
|
|
||||||
return { already_initialized: true, confirmation_id: "", seed: [] }
|
|
||||||
}
|
}
|
||||||
this.pendingConfig = { sourceName: req.source_name, relayUrl: req.relay_url, automateLiquidity: req.automate_liquidity, pushBackupsToNostr: req.push_backups_to_nostr }
|
const pendingConfig = { sourceName: req.source_name, relayUrl: req.relay_url, automateLiquidity: req.automate_liquidity, pushBackupsToNostr: req.push_backups_to_nostr }
|
||||||
return { already_initialized: false, confirmation_id: res.confirmationId, seed: res.seed }
|
this.updateEnvFile(pendingConfig)
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
wizardConfirm = async (req: WizardTypes.ConfirmRequest): Promise<WizardTypes.ConfirmResponse> => {
|
|
||||||
const err = WizardTypes.ConfirmRequestValidate(req, {
|
|
||||||
confirmation_id_CustomCheck: conf => conf !== '',
|
|
||||||
})
|
|
||||||
if (err != null) { throw new Error(err.message) }
|
|
||||||
|
|
||||||
const res = await this.unlocker.ConfirmInitInteractive(req.confirmation_id)
|
|
||||||
if (res?.alreadyInitizialized) {
|
|
||||||
this.initialized = true
|
|
||||||
this.configQueue.forEach(q => q.res(false))
|
|
||||||
return { admin_key: "" }
|
|
||||||
}
|
|
||||||
this.initialized = true
|
|
||||||
this.updateEnvFile()
|
|
||||||
this.configQueue.forEach(q => q.res(true))
|
this.configQueue.forEach(q => q.res(true))
|
||||||
return { admin_key: process.env.ADMIN_TOKEN || "" }
|
this.configQueue = []
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
updateEnvFile = () => {
|
updateEnvFile = (pendingConfig: WizardSettings) => {
|
||||||
if (!this.pendingConfig) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
let envFileContent: string[] = []
|
let envFileContent: string[] = []
|
||||||
try {
|
try {
|
||||||
envFileContent = fs.readFileSync('.env', 'utf-8').split('\n')
|
envFileContent = fs.readFileSync('.env', 'utf-8').split('\n')
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
if (err.code !== 'ENOENT') {
|
if (err.code !== 'ENOENT') {
|
||||||
|
throw err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const toMerge: string[] = []
|
const toMerge: string[] = []
|
||||||
const sourceNameIndex = envFileContent.findIndex(line => line.startsWith('DEFAULT_APP_NAME'))
|
const sourceNameIndex = envFileContent.findIndex(line => line.startsWith('DEFAULT_APP_NAME'))
|
||||||
if (sourceNameIndex === -1) {
|
if (sourceNameIndex === -1) {
|
||||||
toMerge.push(`DEFAULT_APP_NAME=${this.pendingConfig.sourceName}`)
|
toMerge.push(`DEFAULT_APP_NAME=${pendingConfig.sourceName}`)
|
||||||
} else {
|
} else {
|
||||||
envFileContent[sourceNameIndex] = `DEFAULT_APP_NAME=${this.pendingConfig.sourceName}`
|
envFileContent[sourceNameIndex] = `DEFAULT_APP_NAME=${pendingConfig.sourceName}`
|
||||||
}
|
}
|
||||||
const relayUrlIndex = envFileContent.findIndex(line => line.startsWith('RELAY_URL'))
|
const relayUrlIndex = envFileContent.findIndex(line => line.startsWith('RELAY_URL'))
|
||||||
if (relayUrlIndex === -1) {
|
if (relayUrlIndex === -1) {
|
||||||
toMerge.push(`RELAY_URL=${this.pendingConfig.relayUrl}`)
|
toMerge.push(`RELAY_URL=${pendingConfig.relayUrl}`)
|
||||||
} else {
|
} else {
|
||||||
envFileContent[relayUrlIndex] = `RELAY_URL=${this.pendingConfig.relayUrl}`
|
envFileContent[relayUrlIndex] = `RELAY_URL=${pendingConfig.relayUrl}`
|
||||||
}
|
}
|
||||||
|
|
||||||
const automateLiquidityIndex = envFileContent.findIndex(line => line.startsWith('LIQUIDITY_PROVIDER_PUB'))
|
const automateLiquidityIndex = envFileContent.findIndex(line => line.startsWith('LIQUIDITY_PROVIDER_PUB'))
|
||||||
if (automateLiquidityIndex === -1) {
|
if (automateLiquidityIndex === -1) {
|
||||||
toMerge.push(`LIQUIDITY_PROVIDER_PUB=${this.pendingConfig.automateLiquidity ? defaultProviderPub : ""}`)
|
toMerge.push(`LIQUIDITY_PROVIDER_PUB=${pendingConfig.automateLiquidity ? defaultProviderPub : ""}`)
|
||||||
} else {
|
} else {
|
||||||
envFileContent[automateLiquidityIndex] = `LIQUIDITY_PROVIDER_PUB=`
|
envFileContent[automateLiquidityIndex] = `LIQUIDITY_PROVIDER_PUB=`
|
||||||
}
|
}
|
||||||
|
|
||||||
const pushBackupsToNostrIndex = envFileContent.findIndex(line => line.startsWith('PUSH_BACKUPS_TO_NOSTR'))
|
const pushBackupsToNostrIndex = envFileContent.findIndex(line => line.startsWith('PUSH_BACKUPS_TO_NOSTR'))
|
||||||
if (pushBackupsToNostrIndex === -1) {
|
if (pushBackupsToNostrIndex === -1) {
|
||||||
toMerge.push(`PUSH_BACKUPS_TO_NOSTR=${this.pendingConfig.pushBackupsToNostr ? 'true' : 'false'}`)
|
toMerge.push(`PUSH_BACKUPS_TO_NOSTR=${pendingConfig.pushBackupsToNostr ? 'true' : 'false'}`)
|
||||||
} else {
|
} else {
|
||||||
envFileContent[pushBackupsToNostrIndex] = `PUSH_BACKUPS_TO_NOSTR=${this.pendingConfig.pushBackupsToNostr ? 'true' : 'false'}`
|
envFileContent[pushBackupsToNostrIndex] = `PUSH_BACKUPS_TO_NOSTR=${pendingConfig.pushBackupsToNostr ? 'true' : 'false'}`
|
||||||
}
|
}
|
||||||
const merged = [...envFileContent, ...toMerge].join('\n')
|
const merged = [...envFileContent, ...toMerge].join('\n')
|
||||||
fs.writeFileSync('.env', merged)
|
fs.writeFileSync('.env', merged)
|
||||||
|
|
|
||||||
|
|
@ -93,6 +93,31 @@
|
||||||
|
|
||||||
<script src="js/backup.js"></script>
|
<script src="js/backup.js"></script>
|
||||||
<script>
|
<script>
|
||||||
|
const sendConfig = async () => {
|
||||||
|
const req = {
|
||||||
|
source_name: localStorage.getItem("wizard/nodeName"),
|
||||||
|
relay_url: localStorage.getItem("wizard/relayUrl"),
|
||||||
|
automate_liquidity: localStorage.getItem("wizard/liquidity") === 'automate',
|
||||||
|
push_backups_to_nostr: localStorage.getItem("wizard/backup") === 'backup',
|
||||||
|
}
|
||||||
|
const res = await fetch("/wizard/config", {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
body: JSON.stringify(req)
|
||||||
|
})
|
||||||
|
if (res.status !== 200) {
|
||||||
|
document.getElementById('errorText').innerText = "failed to start service"
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const j = await res.json()
|
||||||
|
if (j.status !== 'OK') {
|
||||||
|
document.getElementById('errorText').innerText = "failed to start service" + j.reason
|
||||||
|
return
|
||||||
|
}
|
||||||
|
location.href = 'connect.html'
|
||||||
|
}
|
||||||
document.getElementById("next-button").onclick = (e) => {
|
document.getElementById("next-button").onclick = (e) => {
|
||||||
const backup = document.getElementById('backup').checked
|
const backup = document.getElementById('backup').checked
|
||||||
const manual = document.getElementById('manual-backup').checked
|
const manual = document.getElementById('manual-backup').checked
|
||||||
|
|
@ -109,7 +134,7 @@
|
||||||
} else {
|
} else {
|
||||||
localStorage.setItem('wizard/backup', 'manual')
|
localStorage.setItem('wizard/backup', 'manual')
|
||||||
}
|
}
|
||||||
location.href = 'seed.html'
|
sendConfig()
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
|
|
|
||||||
|
|
@ -1,80 +1,116 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8" />
|
|
||||||
<title></title>
|
|
||||||
<meta charset="UTF-8" />
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
||||||
<link
|
|
||||||
rel="stylesheet"
|
|
||||||
href="https://fonts.googleapis.com/css?family=Montserrat"
|
|
||||||
/>
|
|
||||||
<link rel="stylesheet" href="css/styles.css" />
|
|
||||||
<link rel="stylesheet" href="css/connect.css" />
|
|
||||||
<!-- HTML Meta Tags -->
|
|
||||||
<title>Lightning.Pub</title>
|
|
||||||
<meta name="description" content="Lightning for Everyone" />
|
|
||||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<header>
|
|
||||||
<img
|
|
||||||
src="img/pub_logo.png"
|
|
||||||
width="38px"
|
|
||||||
height="auto"
|
|
||||||
alt="Lightning Pub logo"
|
|
||||||
/>
|
|
||||||
<img src="img/LightningPub.png" height="33px" alt="Lightning Pub logo" />
|
|
||||||
</header>
|
|
||||||
|
|
||||||
<main>
|
<head>
|
||||||
<section class="setup-header">
|
<meta charset="UTF-8" />
|
||||||
<button class="icon-button back-button" onclick="history.back()">
|
<title></title>
|
||||||
<img src="img/back.svg" alt="" />
|
<meta charset="UTF-8" />
|
||||||
</button>
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<h2>Connect</h2>
|
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Montserrat" />
|
||||||
<p class="header-title">
|
<link rel="stylesheet" href="css/styles.css" />
|
||||||
You can now manage your node remotely
|
<link rel="stylesheet" href="css/connect.css" />
|
||||||
</p>
|
<!-- HTML Meta Tags -->
|
||||||
</section>
|
<title>Lightning.Pub</title>
|
||||||
|
<meta name="description" content="Lightning for Everyone" />
|
||||||
|
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
|
||||||
|
</head>
|
||||||
|
|
||||||
<div class="line"></div>
|
<body>
|
||||||
|
<header>
|
||||||
|
<img src="img/pub_logo.png" width="38px" height="auto" alt="Lightning Pub logo" />
|
||||||
|
<img src="img/LightningPub.png" height="33px" alt="Lightning Pub logo" />
|
||||||
|
</header>
|
||||||
|
|
||||||
<section class="setup-content">
|
<main>
|
||||||
<div>For dashboard access, use <a href="https://preview.uxpin.com/ae6e6372ab26cd13438d486d4d1ac9d184ec8e82#/pages/164889267" style="color: #2aabe9;" target="_blank">ShockWallet</a> and tap the logo 3 times.</div>
|
<section class="setup-header">
|
||||||
<div style="font-size: 13px; margin-top: 5px;">Scan the QR or Copy-Paste the string to establish the connection.</div>
|
<button class="icon-button back-button" onclick="history.back()">
|
||||||
<div style="display: flex; justify-content: center;">
|
<img src="img/back.svg" alt="" />
|
||||||
<div class="qrcode-box" id="codebox">
|
</button>
|
||||||
<div style="font-size: 11px;">
|
<h2>Connect</h2>
|
||||||
<div style="text-align: center; color: #a3a3a3;">Code contains a one-time pairing secret</div>
|
<p class="header-title">
|
||||||
<div style="text-align: center; color: #c434e0;" id="click-text">Click to reveal</div>
|
You can now manage your node remotely
|
||||||
</div>
|
</p>
|
||||||
<div id="qrcode"></div>
|
</section>
|
||||||
<div style="color: #a3a3a3; font-size: 11px;">
|
|
||||||
<div>npub123abcdefghhhhhhhhhhhhhhh</div>
|
<div class="line"></div>
|
||||||
<div>relay.lightning.pub</div>
|
|
||||||
</div>
|
<section class="setup-content">
|
||||||
|
<div>For dashboard access, use <a
|
||||||
|
href="https://preview.uxpin.com/ae6e6372ab26cd13438d486d4d1ac9d184ec8e82#/pages/164889267"
|
||||||
|
style="color: #2aabe9;" target="_blank">ShockWallet</a> and tap the logo 3 times.</div>
|
||||||
|
<div style="font-size: 13px; margin-top: 5px;">Scan the QR or Copy-Paste the string to establish the connection.
|
||||||
|
</div>
|
||||||
|
<div style="display: flex; justify-content: center;">
|
||||||
|
<div class="qrcode-box" id="codebox">
|
||||||
|
<div style="font-size: 11px;">
|
||||||
|
<div style="text-align: center; color: #a3a3a3;">Code contains a one-time pairing secret</div>
|
||||||
|
<div style="text-align: center; color: #c434e0;" id="click-text">Click to reveal</div>
|
||||||
|
</div>
|
||||||
|
<div id="qrcode"></div>
|
||||||
|
<div style="color: #a3a3a3; font-size: 11px;">
|
||||||
|
<div id="connectString"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
|
||||||
</main>
|
|
||||||
|
|
||||||
<footer>
|
|
||||||
<div class="footer-text">
|
|
||||||
<div>By proceeding you acknowledge that this is</div>
|
|
||||||
<div>bleeding-edge software, and agree to the providers</div>
|
|
||||||
<div>
|
|
||||||
<span style="color: #c434e0">terms</span> regarding any services
|
|
||||||
herein.
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="line"></div>
|
</section>
|
||||||
<a href="https://docs.shock.network" class="marked need-help">Need Help?</a>
|
</main>
|
||||||
</footer>
|
<p class="errorText" style="color:red"></p>
|
||||||
|
<footer>
|
||||||
|
<div class="footer-text">
|
||||||
|
<div>By proceeding you acknowledge that this is</div>
|
||||||
|
<div>bleeding-edge software, and agree to the providers</div>
|
||||||
|
<div>
|
||||||
|
<span style="color: #c434e0">terms</span> regarding any services
|
||||||
|
herein.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="line"></div>
|
||||||
|
<a href="https://docs.shock.network" class="marked need-help">Need Help?</a>
|
||||||
|
</footer>
|
||||||
|
|
||||||
<script src="https://cdn.rawgit.com/davidshimjs/qrcodejs/gh-pages/qrcode.min.js"></script>
|
<script src="https://cdn.rawgit.com/davidshimjs/qrcodejs/gh-pages/qrcode.min.js"></script>
|
||||||
|
|
||||||
|
<script src="js/connect.js"></script>
|
||||||
|
<script>
|
||||||
|
const fetchInfo = async () => {
|
||||||
|
console.log("fewtching...")
|
||||||
|
const res = await fetch("/wizard/admin_connect_info")
|
||||||
|
console.log(res)
|
||||||
|
if (res.status !== 200) {
|
||||||
|
document.getElementById('errorText').innerText = "failed to get connection info"
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const j = await res.json()
|
||||||
|
console.log(j)
|
||||||
|
if (j.status !== 'OK') {
|
||||||
|
document.getElementById('errorText').innerText = "failed to get connection info" + j.reason
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (j.connect_info.enrolled_npub) {
|
||||||
|
location.href = 'status.html'
|
||||||
|
} else {
|
||||||
|
const connectString = j.nprofile + ":" + j.connect_info.admin_token
|
||||||
|
console.log({ connectString })
|
||||||
|
const qrElement = document.getElementById("qrcode")
|
||||||
|
qrElement.onclick = () => {
|
||||||
|
document.navigator.clipboard.writeText(connectString)
|
||||||
|
}
|
||||||
|
const qrcode = new QRCode(qrElement, {
|
||||||
|
text: connectString,
|
||||||
|
colorDark: "#000000",
|
||||||
|
colorLight: "#ffffff",
|
||||||
|
width: 157,
|
||||||
|
height: 157,
|
||||||
|
// correctLevel : QRCode.CorrectLevel.H
|
||||||
|
});
|
||||||
|
document.getElementById('connectString').innerHTML = connectString
|
||||||
|
}
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
|
||||||
|
fetchInfo()
|
||||||
|
} catch (e) { console.log({ e }) }
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
|
||||||
<script src="js/script.js"></script>
|
|
||||||
<script src="js/connect.js"></script>
|
|
||||||
</body>
|
|
||||||
</html>
|
</html>
|
||||||
|
|
@ -96,9 +96,10 @@
|
||||||
fetch("/wizard/state").then((res) => {
|
fetch("/wizard/state").then((res) => {
|
||||||
if (res.status === 200) {
|
if (res.status === 200) {
|
||||||
res.json().then((data) => {
|
res.json().then((data) => {
|
||||||
if (data.already_initialized) {
|
if (data.admin_linked) {
|
||||||
location.href = 'status.html'
|
location.href = 'status.html'
|
||||||
console.log("already init")
|
} else if (data.config_sent) {
|
||||||
|
location.href = 'connect.html'
|
||||||
} else {
|
} else {
|
||||||
console.log("ready to initialize")
|
console.log("ready to initialize")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -69,60 +69,6 @@
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
<script src="js/seed.js"></script>
|
<script src="js/seed.js"></script>
|
||||||
<script>
|
|
||||||
let latestConfirmationId = ""
|
|
||||||
document.getElementById("next-button").onclick = (e) => {
|
|
||||||
if (!latestConfirmationId) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
fetch("/wizard/confirm", {
|
|
||||||
method: 'POST',
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
},
|
|
||||||
body: JSON.stringify({
|
|
||||||
confirmation_id: latestConfirmationId,
|
|
||||||
})
|
|
||||||
}).then((res) => {
|
|
||||||
if (res.status === 200) {
|
|
||||||
location.href = 'connect.html'
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
fetch("/wizard/config", {
|
|
||||||
method: 'POST',
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
},
|
|
||||||
body: JSON.stringify({
|
|
||||||
source_name: localStorage.getItem("wizard/nodeName"),
|
|
||||||
relay_url: localStorage.getItem("wizard/relayUrl"),
|
|
||||||
automate_liquidity: localStorage.getItem("wizard/liquidity") === 'automate',
|
|
||||||
push_backups_to_nostr: localStorage.getItem("wizard/backup") === 'backup',
|
|
||||||
})
|
|
||||||
}).then((res) => {
|
|
||||||
if (res.status === 200) {
|
|
||||||
res.json().then((data) => {
|
|
||||||
if (data.already_initialized) {
|
|
||||||
location.href = 'status.html'
|
|
||||||
return
|
|
||||||
}
|
|
||||||
const seedContainer = document.getElementById("seed-box-container")
|
|
||||||
latestConfirmationId = data.confirmation_id
|
|
||||||
console.log(latestConfirmationId)
|
|
||||||
data.seed.forEach((word, index) => {
|
|
||||||
const seedBox = document.createElement('div')
|
|
||||||
seedBox.classList.add('seed-box')
|
|
||||||
seedBox.innerHTML = `
|
|
||||||
<span>${index + 1}</span>
|
|
||||||
<span>${word}</span>
|
|
||||||
`
|
|
||||||
seedContainer.appendChild(seedBox)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
|
@ -30,6 +30,7 @@
|
||||||
<div class="line" style="width: 100%;"></div>
|
<div class="line" style="width: 100%;"></div>
|
||||||
|
|
||||||
<section class="node-status">
|
<section class="node-status">
|
||||||
|
<p id="errorText" style="color:red"></p>
|
||||||
<div>
|
<div>
|
||||||
<div class="status-element" style="margin-top: 15px;">
|
<div class="status-element" style="margin-top: 15px;">
|
||||||
<div style="text-align: left;">Public Node Name:</div>
|
<div style="text-align: left;">Public Node Name:</div>
|
||||||
|
|
@ -69,8 +70,8 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="status-element" style="margin-top: 15px;">
|
<div class="status-element" style="margin-top: 15px;">
|
||||||
<div>Administrator:</div>
|
<div>Administrator:</div>
|
||||||
<div>
|
<div id="adminNpub" style="line-break: anywhere;">
|
||||||
npub12334556677889990
|
Loading...
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -99,14 +100,14 @@
|
||||||
<div style="margin-top: 40px;">
|
<div style="margin-top: 40px;">
|
||||||
<div class="status-element">
|
<div class="status-element">
|
||||||
<div>Relay Status:</div>
|
<div>Relay Status:</div>
|
||||||
<div>
|
<div id="relayStatus">
|
||||||
<span class="green-dot">●</span> Connected
|
<span class="yellow-dot">●</span> Loading...
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="status-element">
|
<div class="status-element">
|
||||||
<div>Lightning Status:</div>
|
<div>Lightning Status:</div>
|
||||||
<div>
|
<div id="lndStatus">
|
||||||
<span class="yellow-dot">●</span> Syncing
|
<span class="yellow-dot">●</span> Loading...
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="status-element">
|
<div class="status-element">
|
||||||
|
|
@ -118,15 +119,15 @@
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div id="watchdog-status">
|
||||||
<span class="green-dot">●</span> No Alarms
|
<span class="green-dot">●</span> Loading...
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div style="margin-top: 20px;">
|
<div style="margin-top: 20px;">
|
||||||
<div style="font-size: 13px; text-align: left;">Guest Invitation Link:</div>
|
<div style="font-size: 13px; text-align: left;">Guest Invitation Link:</div>
|
||||||
<a href="https://my.shockwallet.app/invite/nprofile12345678899988" target="_blank" style="font-size: 11px;"
|
<a href="https://my.shockwallet.app/invite/nprofile12345678899988" target="_blank"
|
||||||
class="invite-link">
|
style="font-size: 11px;line-break: anywhere;" id="inviteLinkHttp" class="invite-link">
|
||||||
https://my.shockwallet.app/invite/nprofile12345678899988
|
https://my.shockwallet.app/invite/nprofile12345678899988
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -140,6 +141,34 @@
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
<script src="js/status.js"></script>
|
<script src="js/status.js"></script>
|
||||||
|
<script>
|
||||||
|
const fetchInfo = async () => {
|
||||||
|
console.log("fewtching...")
|
||||||
|
const res = await fetch("/wizard/service_state")
|
||||||
|
console.log(res)
|
||||||
|
if (res.status !== 200) {
|
||||||
|
document.getElementById('errorText').innerText = "failed to get state info"
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const j = await res.json()
|
||||||
|
console.log(j)
|
||||||
|
if (j.status !== 'OK') {
|
||||||
|
document.getElementById('errorText').innerText = "failed to get state info" + j.reason
|
||||||
|
return
|
||||||
|
}
|
||||||
|
document.getElementById("show-nodey-text").innerHTML = j.provider_name
|
||||||
|
document.getElementById("show-nostr-text").innerHTML = j.relays[0]
|
||||||
|
document.getElementById("adminNpub").innerText = j.admin_npub
|
||||||
|
document.getElementById("relayStatus").innerHTML = `<span class="${j.relay_connected ? 'green-dot' : 'red-dot'}">●</span> ${j.relay_connected ? 'Connected' : 'Disconnected'}`
|
||||||
|
document.getElementById("lndStatus").innerHTML = `<span class="${j.lnd_state === 'ONLINE' ? 'green-dot' : 'red-dot'}">●</span> ${j.lnd_state}`
|
||||||
|
document.getElementById("watchdog-status").innerHTML = `<span class="${j.watchdog_ok ? 'green-dot' : 'red-dot'}">●</span> ${j.watchdog_ok ? 'No Alerts' : 'ALERT!!'}`
|
||||||
|
document.getElementById("inviteLinkHttp").href = `https://my.shockwallet.app/invite/${j.nprofile}`
|
||||||
|
document.getElementById("inviteLinkHttp").innerHTML = `https://my.shockwallet.app/invite/${j.nprofile}`
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
fetchInfo()
|
||||||
|
} catch (e) { console.log({ e }) }
|
||||||
|
</script>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
Loading…
Add table
Add a link
Reference in a new issue