commit
24fa94824a
29 changed files with 1608 additions and 804 deletions
|
|
@ -15,6 +15,7 @@ message ConfigRequest {
|
||||||
string relay_url = 2;
|
string relay_url = 2;
|
||||||
bool automate_liquidity = 3;
|
bool automate_liquidity = 3;
|
||||||
bool push_backups_to_nostr = 4;
|
bool push_backups_to_nostr = 4;
|
||||||
|
string avatar_url = 5;
|
||||||
}
|
}
|
||||||
message AdminConnectInfoResponse {
|
message AdminConnectInfoResponse {
|
||||||
string nprofile = 1;
|
string nprofile = 1;
|
||||||
|
|
@ -37,4 +38,10 @@ message ServiceStateResponse {
|
||||||
bool watchdog_ok = 6;
|
bool watchdog_ok = 6;
|
||||||
string http_url = 7;
|
string http_url = 7;
|
||||||
string nprofile = 8;
|
string nprofile = 8;
|
||||||
|
string source_name = 9;
|
||||||
|
string relay_url = 10;
|
||||||
|
bool automate_liquidity = 11;
|
||||||
|
bool push_backups_to_nostr = 12;
|
||||||
|
string avatar_url = 13;
|
||||||
|
string app_id = 14;
|
||||||
}
|
}
|
||||||
|
|
@ -24,20 +24,6 @@ The nostr server will send back a message response, and inside the body there wi
|
||||||
## HTTP Methods
|
## HTTP Methods
|
||||||
### These are the http methods the client implements to communicate with the API
|
### These are the http methods the client implements to communicate with the API
|
||||||
|
|
||||||
- WizardState
|
|
||||||
- auth type: __Guest__
|
|
||||||
- http method: __get__
|
|
||||||
- http route: __/wizard/state__
|
|
||||||
- This methods has an __empty__ __request__ body
|
|
||||||
- output: [StateResponse](#StateResponse)
|
|
||||||
|
|
||||||
- WizardConfig
|
|
||||||
- auth type: __Guest__
|
|
||||||
- http method: __post__
|
|
||||||
- http route: __/wizard/config__
|
|
||||||
- input: [ConfigRequest](#ConfigRequest)
|
|
||||||
- This methods has an __empty__ __response__ body
|
|
||||||
|
|
||||||
- GetAdminConnectInfo
|
- GetAdminConnectInfo
|
||||||
- auth type: __Guest__
|
- auth type: __Guest__
|
||||||
- http method: __get__
|
- http method: __get__
|
||||||
|
|
@ -52,40 +38,61 @@ The nostr server will send back a message response, and inside the body there wi
|
||||||
- This methods has an __empty__ __request__ body
|
- This methods has an __empty__ __request__ body
|
||||||
- output: [ServiceStateResponse](#ServiceStateResponse)
|
- output: [ServiceStateResponse](#ServiceStateResponse)
|
||||||
|
|
||||||
|
- WizardConfig
|
||||||
|
- auth type: __Guest__
|
||||||
|
- http method: __post__
|
||||||
|
- http route: __/wizard/config__
|
||||||
|
- input: [ConfigRequest](#ConfigRequest)
|
||||||
|
- This methods has an __empty__ __response__ body
|
||||||
|
|
||||||
|
- WizardState
|
||||||
|
- auth type: __Guest__
|
||||||
|
- http method: __get__
|
||||||
|
- http route: __/wizard/state__
|
||||||
|
- This methods has an __empty__ __request__ body
|
||||||
|
- output: [StateResponse](#StateResponse)
|
||||||
|
|
||||||
# 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
|
||||||
|
|
||||||
### StateResponse
|
### AdminConnectInfoResponse
|
||||||
- __config_sent__: _boolean_
|
- __connect_info__: _[AdminConnectInfoResponse_connect_info](#AdminConnectInfoResponse_connect_info)_
|
||||||
- __admin_linked__: _boolean_
|
- __nprofile__: _string_
|
||||||
|
|
||||||
### ConfigRequest
|
### ConfigRequest
|
||||||
- __source_name__: _string_
|
|
||||||
- __relay_url__: _string_
|
|
||||||
- __automate_liquidity__: _boolean_
|
- __automate_liquidity__: _boolean_
|
||||||
|
- __avatar_url__: _string_
|
||||||
- __push_backups_to_nostr__: _boolean_
|
- __push_backups_to_nostr__: _boolean_
|
||||||
|
- __relay_url__: _string_
|
||||||
### AdminConnectInfoResponse
|
- __source_name__: _string_
|
||||||
- __nprofile__: _string_
|
|
||||||
- __connect_info__: _AdminConnectInfoResponse_connect_info_
|
|
||||||
|
|
||||||
### ServiceStateResponse
|
|
||||||
- __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
|
### Empty
|
||||||
|
|
||||||
|
### ServiceStateResponse
|
||||||
|
- __admin_npub__: _string_
|
||||||
|
- __app_id__: _string_
|
||||||
|
- __automate_liquidity__: _boolean_
|
||||||
|
- __avatar_url__: _string_
|
||||||
|
- __http_url__: _string_
|
||||||
|
- __lnd_state__: _[LndState](#LndState)_
|
||||||
|
- __nprofile__: _string_
|
||||||
|
- __provider_name__: _string_
|
||||||
|
- __push_backups_to_nostr__: _boolean_
|
||||||
|
- __relay_connected__: _boolean_
|
||||||
|
- __relay_url__: _string_
|
||||||
|
- __relays__: ARRAY of: _string_
|
||||||
|
- __source_name__: _string_
|
||||||
|
- __watchdog_ok__: _boolean_
|
||||||
|
|
||||||
|
### StateResponse
|
||||||
|
- __admin_linked__: _boolean_
|
||||||
|
- __config_sent__: _boolean_
|
||||||
## Enums
|
## Enums
|
||||||
### The enumerators used in the messages
|
### The enumerators used in the messages
|
||||||
|
|
||||||
### LndState
|
### LndState
|
||||||
- __OFFLINE__
|
- __OFFLINE__
|
||||||
- __SYNCING__
|
|
||||||
- __ONLINE__
|
- __ONLINE__
|
||||||
|
- __SYNCING__
|
||||||
|
|
|
||||||
|
|
@ -1,61 +1,5 @@
|
||||||
([]*main.Method) (len=4 cap=4) {
|
([]*main.Method) (len=4 cap=4) {
|
||||||
(*main.Method)(0xc00022a280)({
|
(*main.Method)(0xc0002b00f0)({
|
||||||
in: (main.MethodMessage) {
|
|
||||||
name: (string) (len=5) "Empty",
|
|
||||||
hasZeroFields: (bool) true
|
|
||||||
},
|
|
||||||
name: (string) (len=11) "WizardState",
|
|
||||||
out: (main.MethodMessage) {
|
|
||||||
name: (string) (len=13) "StateResponse",
|
|
||||||
hasZeroFields: (bool) false
|
|
||||||
},
|
|
||||||
opts: (*main.methodOptions)(0xc00009a9c0)({
|
|
||||||
authType: (*main.supportedAuth)(0xc0003c9aa0)({
|
|
||||||
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=13) "/wizard/state",
|
|
||||||
params: ([]string) <nil>
|
|
||||||
},
|
|
||||||
query: ([]string) <nil>,
|
|
||||||
nostr: (bool) false,
|
|
||||||
batch: (bool) false
|
|
||||||
}),
|
|
||||||
serverStream: (bool) false
|
|
||||||
}),
|
|
||||||
(*main.Method)(0xc00022a2d0)({
|
|
||||||
in: (main.MethodMessage) {
|
|
||||||
name: (string) (len=13) "ConfigRequest",
|
|
||||||
hasZeroFields: (bool) false
|
|
||||||
},
|
|
||||||
name: (string) (len=12) "WizardConfig",
|
|
||||||
out: (main.MethodMessage) {
|
|
||||||
name: (string) (len=5) "Empty",
|
|
||||||
hasZeroFields: (bool) true
|
|
||||||
},
|
|
||||||
opts: (*main.methodOptions)(0xc00009ab40)({
|
|
||||||
authType: (*main.supportedAuth)(0xc0003c9b60)({
|
|
||||||
id: (string) (len=5) "guest",
|
|
||||||
name: (string) (len=5) "Guest",
|
|
||||||
context: (map[string]string) {
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
method: (string) (len=4) "post",
|
|
||||||
route: (main.decodedRoute) {
|
|
||||||
route: (string) (len=14) "/wizard/config",
|
|
||||||
params: ([]string) <nil>
|
|
||||||
},
|
|
||||||
query: ([]string) <nil>,
|
|
||||||
nostr: (bool) false,
|
|
||||||
batch: (bool) false
|
|
||||||
}),
|
|
||||||
serverStream: (bool) false
|
|
||||||
}),
|
|
||||||
(*main.Method)(0xc00022a640)({
|
|
||||||
in: (main.MethodMessage) {
|
in: (main.MethodMessage) {
|
||||||
name: (string) (len=5) "Empty",
|
name: (string) (len=5) "Empty",
|
||||||
hasZeroFields: (bool) true
|
hasZeroFields: (bool) true
|
||||||
|
|
@ -65,12 +9,11 @@
|
||||||
name: (string) (len=24) "AdminConnectInfoResponse",
|
name: (string) (len=24) "AdminConnectInfoResponse",
|
||||||
hasZeroFields: (bool) false
|
hasZeroFields: (bool) false
|
||||||
},
|
},
|
||||||
opts: (*main.methodOptions)(0xc00009acc0)({
|
opts: (*main.methodOptions)(0xc0006907e0)({
|
||||||
authType: (*main.supportedAuth)(0xc0003c9c20)({
|
authType: (*main.supportedAuth)(0xc000347380)({
|
||||||
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: ([]*main.authContext) <nil>
|
||||||
}
|
|
||||||
}),
|
}),
|
||||||
method: (string) (len=3) "get",
|
method: (string) (len=3) "get",
|
||||||
route: (main.decodedRoute) {
|
route: (main.decodedRoute) {
|
||||||
|
|
@ -83,7 +26,7 @@
|
||||||
}),
|
}),
|
||||||
serverStream: (bool) false
|
serverStream: (bool) false
|
||||||
}),
|
}),
|
||||||
(*main.Method)(0xc00022a690)({
|
(*main.Method)(0xc0002b0140)({
|
||||||
in: (main.MethodMessage) {
|
in: (main.MethodMessage) {
|
||||||
name: (string) (len=5) "Empty",
|
name: (string) (len=5) "Empty",
|
||||||
hasZeroFields: (bool) true
|
hasZeroFields: (bool) true
|
||||||
|
|
@ -93,12 +36,11 @@
|
||||||
name: (string) (len=20) "ServiceStateResponse",
|
name: (string) (len=20) "ServiceStateResponse",
|
||||||
hasZeroFields: (bool) false
|
hasZeroFields: (bool) false
|
||||||
},
|
},
|
||||||
opts: (*main.methodOptions)(0xc00009ae40)({
|
opts: (*main.methodOptions)(0xc000690960)({
|
||||||
authType: (*main.supportedAuth)(0xc0003c9ce0)({
|
authType: (*main.supportedAuth)(0xc000347440)({
|
||||||
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: ([]*main.authContext) <nil>
|
||||||
}
|
|
||||||
}),
|
}),
|
||||||
method: (string) (len=3) "get",
|
method: (string) (len=3) "get",
|
||||||
route: (main.decodedRoute) {
|
route: (main.decodedRoute) {
|
||||||
|
|
@ -110,53 +52,101 @@
|
||||||
batch: (bool) false
|
batch: (bool) false
|
||||||
}),
|
}),
|
||||||
serverStream: (bool) false
|
serverStream: (bool) false
|
||||||
|
}),
|
||||||
|
(*main.Method)(0xc0002b00a0)({
|
||||||
|
in: (main.MethodMessage) {
|
||||||
|
name: (string) (len=13) "ConfigRequest",
|
||||||
|
hasZeroFields: (bool) false
|
||||||
|
},
|
||||||
|
name: (string) (len=12) "WizardConfig",
|
||||||
|
out: (main.MethodMessage) {
|
||||||
|
name: (string) (len=5) "Empty",
|
||||||
|
hasZeroFields: (bool) true
|
||||||
|
},
|
||||||
|
opts: (*main.methodOptions)(0xc000690660)({
|
||||||
|
authType: (*main.supportedAuth)(0xc0003472c0)({
|
||||||
|
id: (string) (len=5) "guest",
|
||||||
|
name: (string) (len=5) "Guest",
|
||||||
|
context: ([]*main.authContext) <nil>
|
||||||
|
}),
|
||||||
|
method: (string) (len=4) "post",
|
||||||
|
route: (main.decodedRoute) {
|
||||||
|
route: (string) (len=14) "/wizard/config",
|
||||||
|
params: ([]string) <nil>
|
||||||
|
},
|
||||||
|
query: ([]string) <nil>,
|
||||||
|
nostr: (bool) false,
|
||||||
|
batch: (bool) false
|
||||||
|
}),
|
||||||
|
serverStream: (bool) false
|
||||||
|
}),
|
||||||
|
(*main.Method)(0xc0002b0050)({
|
||||||
|
in: (main.MethodMessage) {
|
||||||
|
name: (string) (len=5) "Empty",
|
||||||
|
hasZeroFields: (bool) true
|
||||||
|
},
|
||||||
|
name: (string) (len=11) "WizardState",
|
||||||
|
out: (main.MethodMessage) {
|
||||||
|
name: (string) (len=13) "StateResponse",
|
||||||
|
hasZeroFields: (bool) false
|
||||||
|
},
|
||||||
|
opts: (*main.methodOptions)(0xc0006904e0)({
|
||||||
|
authType: (*main.supportedAuth)(0xc000347200)({
|
||||||
|
id: (string) (len=5) "guest",
|
||||||
|
name: (string) (len=5) "Guest",
|
||||||
|
context: ([]*main.authContext) <nil>
|
||||||
|
}),
|
||||||
|
method: (string) (len=3) "get",
|
||||||
|
route: (main.decodedRoute) {
|
||||||
|
route: (string) (len=13) "/wizard/state",
|
||||||
|
params: ([]string) <nil>
|
||||||
|
},
|
||||||
|
query: ([]string) <nil>,
|
||||||
|
nostr: (bool) false,
|
||||||
|
batch: (bool) false
|
||||||
|
}),
|
||||||
|
serverStream: (bool) false
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
([]*main.Enum) (len=1 cap=1) {
|
([]*main.Enum) (len=1 cap=1) {
|
||||||
(*main.Enum)(0xc0003c9680)({
|
(*main.Enum)(0xc000443d40)({
|
||||||
name: (string) (len=8) "LndState",
|
name: (string) (len=8) "LndState",
|
||||||
values: ([]main.EnumValue) (len=3 cap=4) {
|
values: ([]main.EnumValue) (len=3 cap=4) {
|
||||||
(main.EnumValue) {
|
(main.EnumValue) {
|
||||||
number: (int64) 0,
|
number: (int64) 0,
|
||||||
name: (string) (len=7) "OFFLINE"
|
name: (string) (len=7) "OFFLINE"
|
||||||
},
|
},
|
||||||
(main.EnumValue) {
|
|
||||||
number: (int64) 1,
|
|
||||||
name: (string) (len=7) "SYNCING"
|
|
||||||
},
|
|
||||||
(main.EnumValue) {
|
(main.EnumValue) {
|
||||||
number: (int64) 2,
|
number: (int64) 2,
|
||||||
name: (string) (len=6) "ONLINE"
|
name: (string) (len=6) "ONLINE"
|
||||||
|
},
|
||||||
|
(main.EnumValue) {
|
||||||
|
number: (int64) 1,
|
||||||
|
name: (string) (len=7) "SYNCING"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
(map[string]*main.Message) (len=5) {
|
([]*main.SortableMessage) (len=5 cap=8) {
|
||||||
(string) (len=5) "Empty": (*main.Message)(0xc0003c94a0)({
|
(*main.SortableMessage)(0xc0003475c0)({
|
||||||
fullName: (string) (len=5) "Empty",
|
fullName: (string) (len=24) "AdminConnectInfoResponse",
|
||||||
name: (string) (len=5) "Empty",
|
name: (string) (len=24) "AdminConnectInfoResponse",
|
||||||
fields: (map[string]*main.Field) {
|
fields: ([]*main.Field) (len=2 cap=2) {
|
||||||
}
|
(*main.Field)(0xc000347480)({
|
||||||
}),
|
name: (string) (len=12) "connect_info",
|
||||||
(string) (len=13) "StateResponse": (*main.Message)(0xc0003c9500)({
|
kind: (string) (len=37) "AdminConnectInfoResponse_connect_info",
|
||||||
fullName: (string) (len=13) "StateResponse",
|
|
||||||
name: (string) (len=13) "StateResponse",
|
|
||||||
fields: (map[string]*main.Field) (len=2) {
|
|
||||||
(string) (len=11) "config_sent": (*main.Field)(0xc0003ee440)({
|
|
||||||
name: (string) (len=11) "config_sent",
|
|
||||||
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) true,
|
||||||
isOptional: (bool) false,
|
isOptional: (bool) false,
|
||||||
oneOfName: (string) ""
|
oneOfName: (string) (len=12) "connect_info"
|
||||||
}),
|
}),
|
||||||
(string) (len=12) "admin_linked": (*main.Field)(0xc0003ee480)({
|
(*main.Field)(0xc000346bc0)({
|
||||||
name: (string) (len=12) "admin_linked",
|
name: (string) (len=8) "nprofile",
|
||||||
kind: (string) (len=4) "bool",
|
kind: (string) (len=6) "string",
|
||||||
isMap: (bool) false,
|
isMap: (bool) false,
|
||||||
isArray: (bool) false,
|
isArray: (bool) false,
|
||||||
isEnum: (bool) false,
|
isEnum: (bool) false,
|
||||||
|
|
@ -166,21 +156,11 @@
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
(string) (len=13) "ConfigRequest": (*main.Message)(0xc0003c9560)({
|
(*main.SortableMessage)(0xc000347580)({
|
||||||
fullName: (string) (len=13) "ConfigRequest",
|
fullName: (string) (len=13) "ConfigRequest",
|
||||||
name: (string) (len=13) "ConfigRequest",
|
name: (string) (len=13) "ConfigRequest",
|
||||||
fields: (map[string]*main.Field) (len=4) {
|
fields: ([]*main.Field) (len=5 cap=8) {
|
||||||
(string) (len=9) "relay_url": (*main.Field)(0xc0003ee500)({
|
(*main.Field)(0xc000346b00)({
|
||||||
name: (string) (len=9) "relay_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=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,
|
||||||
|
|
@ -190,7 +170,17 @@
|
||||||
isOptional: (bool) false,
|
isOptional: (bool) false,
|
||||||
oneOfName: (string) ""
|
oneOfName: (string) ""
|
||||||
}),
|
}),
|
||||||
(string) (len=21) "push_backups_to_nostr": (*main.Field)(0xc0003ee580)({
|
(*main.Field)(0xc000346b80)({
|
||||||
|
name: (string) (len=10) "avatar_url",
|
||||||
|
kind: (string) (len=6) "string",
|
||||||
|
isMap: (bool) false,
|
||||||
|
isArray: (bool) false,
|
||||||
|
isEnum: (bool) false,
|
||||||
|
isMessage: (bool) false,
|
||||||
|
isOptional: (bool) false,
|
||||||
|
oneOfName: (string) ""
|
||||||
|
}),
|
||||||
|
(*main.Field)(0xc000346b40)({
|
||||||
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,
|
||||||
|
|
@ -200,7 +190,17 @@
|
||||||
isOptional: (bool) false,
|
isOptional: (bool) false,
|
||||||
oneOfName: (string) ""
|
oneOfName: (string) ""
|
||||||
}),
|
}),
|
||||||
(string) (len=11) "source_name": (*main.Field)(0xc0003ee4c0)({
|
(*main.Field)(0xc000346ac0)({
|
||||||
|
name: (string) (len=9) "relay_url",
|
||||||
|
kind: (string) (len=6) "string",
|
||||||
|
isMap: (bool) false,
|
||||||
|
isArray: (bool) false,
|
||||||
|
isEnum: (bool) false,
|
||||||
|
isMessage: (bool) false,
|
||||||
|
isOptional: (bool) false,
|
||||||
|
oneOfName: (string) ""
|
||||||
|
}),
|
||||||
|
(*main.Field)(0xc000346a80)({
|
||||||
name: (string) (len=11) "source_name",
|
name: (string) (len=11) "source_name",
|
||||||
kind: (string) (len=6) "string",
|
kind: (string) (len=6) "string",
|
||||||
isMap: (bool) false,
|
isMap: (bool) false,
|
||||||
|
|
@ -212,37 +212,16 @@
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
(string) (len=24) "AdminConnectInfoResponse": (*main.Message)(0xc0003c95c0)({
|
(*main.SortableMessage)(0xc0003474c0)({
|
||||||
fullName: (string) (len=24) "AdminConnectInfoResponse",
|
fullName: (string) (len=5) "Empty",
|
||||||
name: (string) (len=24) "AdminConnectInfoResponse",
|
name: (string) (len=5) "Empty",
|
||||||
fields: (map[string]*main.Field) (len=2) {
|
fields: ([]*main.Field) <nil>
|
||||||
(string) (len=8) "nprofile": (*main.Field)(0xc0003ee5c0)({
|
|
||||||
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)({
|
(*main.SortableMessage)(0xc000347640)({
|
||||||
fullName: (string) (len=20) "ServiceStateResponse",
|
fullName: (string) (len=20) "ServiceStateResponse",
|
||||||
name: (string) (len=20) "ServiceStateResponse",
|
name: (string) (len=20) "ServiceStateResponse",
|
||||||
fields: (map[string]*main.Field) (len=8) {
|
fields: ([]*main.Field) (len=14 cap=16) {
|
||||||
(string) (len=10) "admin_npub": (*main.Field)(0xc0003ee700)({
|
(*main.Field)(0xc000346d00)({
|
||||||
name: (string) (len=10) "admin_npub",
|
name: (string) (len=10) "admin_npub",
|
||||||
kind: (string) (len=6) "string",
|
kind: (string) (len=6) "string",
|
||||||
isMap: (bool) false,
|
isMap: (bool) false,
|
||||||
|
|
@ -252,8 +231,18 @@
|
||||||
isOptional: (bool) false,
|
isOptional: (bool) false,
|
||||||
oneOfName: (string) ""
|
oneOfName: (string) ""
|
||||||
}),
|
}),
|
||||||
(string) (len=15) "relay_connected": (*main.Field)(0xc0003ee740)({
|
(*main.Field)(0xc000346fc0)({
|
||||||
name: (string) (len=15) "relay_connected",
|
name: (string) (len=6) "app_id",
|
||||||
|
kind: (string) (len=6) "string",
|
||||||
|
isMap: (bool) false,
|
||||||
|
isArray: (bool) false,
|
||||||
|
isEnum: (bool) false,
|
||||||
|
isMessage: (bool) false,
|
||||||
|
isOptional: (bool) false,
|
||||||
|
oneOfName: (string) ""
|
||||||
|
}),
|
||||||
|
(*main.Field)(0xc000346f00)({
|
||||||
|
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,
|
||||||
|
|
@ -262,19 +251,9 @@
|
||||||
isOptional: (bool) false,
|
isOptional: (bool) false,
|
||||||
oneOfName: (string) ""
|
oneOfName: (string) ""
|
||||||
}),
|
}),
|
||||||
(string) (len=9) "lnd_state": (*main.Field)(0xc0003ee780)({
|
(*main.Field)(0xc000346f80)({
|
||||||
name: (string) (len=9) "lnd_state",
|
name: (string) (len=10) "avatar_url",
|
||||||
kind: (string) (len=8) "LndState",
|
kind: (string) (len=6) "string",
|
||||||
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,
|
isMap: (bool) false,
|
||||||
isArray: (bool) false,
|
isArray: (bool) false,
|
||||||
isEnum: (bool) false,
|
isEnum: (bool) false,
|
||||||
|
|
@ -282,7 +261,7 @@
|
||||||
isOptional: (bool) false,
|
isOptional: (bool) false,
|
||||||
oneOfName: (string) ""
|
oneOfName: (string) ""
|
||||||
}),
|
}),
|
||||||
(string) (len=8) "http_url": (*main.Field)(0xc0003ee800)({
|
(*main.Field)(0xc000346e00)({
|
||||||
name: (string) (len=8) "http_url",
|
name: (string) (len=8) "http_url",
|
||||||
kind: (string) (len=6) "string",
|
kind: (string) (len=6) "string",
|
||||||
isMap: (bool) false,
|
isMap: (bool) false,
|
||||||
|
|
@ -292,7 +271,17 @@
|
||||||
isOptional: (bool) false,
|
isOptional: (bool) false,
|
||||||
oneOfName: (string) ""
|
oneOfName: (string) ""
|
||||||
}),
|
}),
|
||||||
(string) (len=8) "nprofile": (*main.Field)(0xc0003ee840)({
|
(*main.Field)(0xc000346d80)({
|
||||||
|
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) ""
|
||||||
|
}),
|
||||||
|
(*main.Field)(0xc000346e40)({
|
||||||
name: (string) (len=8) "nprofile",
|
name: (string) (len=8) "nprofile",
|
||||||
kind: (string) (len=6) "string",
|
kind: (string) (len=6) "string",
|
||||||
isMap: (bool) false,
|
isMap: (bool) false,
|
||||||
|
|
@ -302,7 +291,7 @@
|
||||||
isOptional: (bool) false,
|
isOptional: (bool) false,
|
||||||
oneOfName: (string) ""
|
oneOfName: (string) ""
|
||||||
}),
|
}),
|
||||||
(string) (len=13) "provider_name": (*main.Field)(0xc0003ee680)({
|
(*main.Field)(0xc000346c80)({
|
||||||
name: (string) (len=13) "provider_name",
|
name: (string) (len=13) "provider_name",
|
||||||
kind: (string) (len=6) "string",
|
kind: (string) (len=6) "string",
|
||||||
isMap: (bool) false,
|
isMap: (bool) false,
|
||||||
|
|
@ -312,7 +301,37 @@
|
||||||
isOptional: (bool) false,
|
isOptional: (bool) false,
|
||||||
oneOfName: (string) ""
|
oneOfName: (string) ""
|
||||||
}),
|
}),
|
||||||
(string) (len=6) "relays": (*main.Field)(0xc0003ee6c0)({
|
(*main.Field)(0xc000346f40)({
|
||||||
|
name: (string) (len=21) "push_backups_to_nostr",
|
||||||
|
kind: (string) (len=4) "bool",
|
||||||
|
isMap: (bool) false,
|
||||||
|
isArray: (bool) false,
|
||||||
|
isEnum: (bool) false,
|
||||||
|
isMessage: (bool) false,
|
||||||
|
isOptional: (bool) false,
|
||||||
|
oneOfName: (string) ""
|
||||||
|
}),
|
||||||
|
(*main.Field)(0xc000346d40)({
|
||||||
|
name: (string) (len=15) "relay_connected",
|
||||||
|
kind: (string) (len=4) "bool",
|
||||||
|
isMap: (bool) false,
|
||||||
|
isArray: (bool) false,
|
||||||
|
isEnum: (bool) false,
|
||||||
|
isMessage: (bool) false,
|
||||||
|
isOptional: (bool) false,
|
||||||
|
oneOfName: (string) ""
|
||||||
|
}),
|
||||||
|
(*main.Field)(0xc000346ec0)({
|
||||||
|
name: (string) (len=9) "relay_url",
|
||||||
|
kind: (string) (len=6) "string",
|
||||||
|
isMap: (bool) false,
|
||||||
|
isArray: (bool) false,
|
||||||
|
isEnum: (bool) false,
|
||||||
|
isMessage: (bool) false,
|
||||||
|
isOptional: (bool) false,
|
||||||
|
oneOfName: (string) ""
|
||||||
|
}),
|
||||||
|
(*main.Field)(0xc000346cc0)({
|
||||||
name: (string) (len=6) "relays",
|
name: (string) (len=6) "relays",
|
||||||
kind: (string) (len=6) "string",
|
kind: (string) (len=6) "string",
|
||||||
isMap: (bool) false,
|
isMap: (bool) false,
|
||||||
|
|
@ -321,39 +340,88 @@
|
||||||
isMessage: (bool) false,
|
isMessage: (bool) false,
|
||||||
isOptional: (bool) false,
|
isOptional: (bool) false,
|
||||||
oneOfName: (string) ""
|
oneOfName: (string) ""
|
||||||
|
}),
|
||||||
|
(*main.Field)(0xc000346e80)({
|
||||||
|
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) ""
|
||||||
|
}),
|
||||||
|
(*main.Field)(0xc000346dc0)({
|
||||||
|
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) ""
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
(*main.SortableMessage)(0xc000347500)({
|
||||||
|
fullName: (string) (len=13) "StateResponse",
|
||||||
|
name: (string) (len=13) "StateResponse",
|
||||||
|
fields: ([]*main.Field) (len=2 cap=2) {
|
||||||
|
(*main.Field)(0xc000346a40)({
|
||||||
|
name: (string) (len=12) "admin_linked",
|
||||||
|
kind: (string) (len=4) "bool",
|
||||||
|
isMap: (bool) false,
|
||||||
|
isArray: (bool) false,
|
||||||
|
isEnum: (bool) false,
|
||||||
|
isMessage: (bool) false,
|
||||||
|
isOptional: (bool) false,
|
||||||
|
oneOfName: (string) ""
|
||||||
|
}),
|
||||||
|
(*main.Field)(0xc000346a00)({
|
||||||
|
name: (string) (len=11) "config_sent",
|
||||||
|
kind: (string) (len=4) "bool",
|
||||||
|
isMap: (bool) false,
|
||||||
|
isArray: (bool) false,
|
||||||
|
isEnum: (bool) false,
|
||||||
|
isMessage: (bool) false,
|
||||||
|
isOptional: (bool) false,
|
||||||
|
oneOfName: (string) ""
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
(map[string][]*main.Field) (len=1) {
|
([]*main.OneOf) (len=1 cap=1) {
|
||||||
(string) (len=37) "AdminConnectInfoResponse_connect_info": ([]*main.Field) (len=2 cap=2) {
|
(*main.OneOf)(0xc0000e31a0)({
|
||||||
(*main.Field)(0xc0003ee600)({
|
kind: (string) (len=37) "AdminConnectInfoResponse_connect_info",
|
||||||
name: (string) (len=11) "admin_token",
|
fields: ([]*main.Field) (len=2 cap=2) {
|
||||||
kind: (string) (len=6) "string",
|
(*main.Field)(0xc000346c00)({
|
||||||
isMap: (bool) false,
|
name: (string) (len=11) "admin_token",
|
||||||
isArray: (bool) false,
|
kind: (string) (len=6) "string",
|
||||||
isEnum: (bool) false,
|
isMap: (bool) false,
|
||||||
isMessage: (bool) false,
|
isArray: (bool) false,
|
||||||
isOptional: (bool) false,
|
isEnum: (bool) false,
|
||||||
oneOfName: (string) (len=12) "connect_info"
|
isMessage: (bool) false,
|
||||||
}),
|
isOptional: (bool) false,
|
||||||
(*main.Field)(0xc0003ee640)({
|
oneOfName: (string) (len=12) "connect_info"
|
||||||
name: (string) (len=13) "enrolled_npub",
|
}),
|
||||||
kind: (string) (len=6) "string",
|
(*main.Field)(0xc000346c40)({
|
||||||
isMap: (bool) false,
|
name: (string) (len=13) "enrolled_npub",
|
||||||
isArray: (bool) false,
|
kind: (string) (len=6) "string",
|
||||||
isEnum: (bool) false,
|
isMap: (bool) false,
|
||||||
isMessage: (bool) false,
|
isArray: (bool) false,
|
||||||
isOptional: (bool) false,
|
isEnum: (bool) false,
|
||||||
oneOfName: (string) (len=12) "connect_info"
|
isMessage: (bool) false,
|
||||||
})
|
isOptional: (bool) false,
|
||||||
}
|
oneOfName: (string) (len=12) "connect_info"
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
parsing file: wizard_structs 5
|
parsing file: wizard_structs 5
|
||||||
parsing file: wizard_methods 2
|
parsing file: wizard_methods 2
|
||||||
-> [{guest Guest map[]}]
|
-> [{guest Guest []}]
|
||||||
|
|
||||||
([]interface {}) <nil>
|
([]interface {}) <nil>
|
||||||
|
|
||||||
|
|
|
||||||
151
proto/wizard_service/autogenerated/go/http_client.go
Normal file
151
proto/wizard_service/autogenerated/go/http_client.go
Normal file
|
|
@ -0,0 +1,151 @@
|
||||||
|
// This file was autogenerated from a .proto file, DO NOT EDIT!
|
||||||
|
|
||||||
|
package lightning_pub
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/url"
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func doPostRequest(url string, body []byte, auth string) ([]byte, error) {
|
||||||
|
bodyReader := bytes.NewReader(body)
|
||||||
|
req, err := http.NewRequest(http.MethodPost, url, bodyReader)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
req.Header.Set("authorization", auth)
|
||||||
|
return doRequest(req)
|
||||||
|
}
|
||||||
|
|
||||||
|
func doGetRequest(url string, auth string) ([]byte, error) {
|
||||||
|
req, err := http.NewRequest(http.MethodGet, url, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
req.Header.Set("authorization", auth)
|
||||||
|
return doRequest(req)
|
||||||
|
}
|
||||||
|
|
||||||
|
func doRequest(req *http.Request) ([]byte, error) {
|
||||||
|
res, err := http.DefaultClient.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
resBody, err := io.ReadAll(res.Body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return resBody, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type ClientParams struct {
|
||||||
|
BaseURL string
|
||||||
|
RetrieveGuestAuth func() (string, error)
|
||||||
|
}
|
||||||
|
type Client struct {
|
||||||
|
GetAdminConnectInfo func() (*AdminConnectInfoResponse, error)
|
||||||
|
GetServiceState func() (*ServiceStateResponse, error)
|
||||||
|
WizardConfig func(req ConfigRequest) error
|
||||||
|
WizardState func() (*StateResponse, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewClient(params ClientParams) *Client {
|
||||||
|
return &Client{
|
||||||
|
GetAdminConnectInfo: func() (*AdminConnectInfoResponse, error) {
|
||||||
|
auth, err := params.RetrieveGuestAuth()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
finalRoute := "/wizard/admin_connect_info"
|
||||||
|
resBody, err := doGetRequest(params.BaseURL+finalRoute, auth)
|
||||||
|
result := ResultError{}
|
||||||
|
err = json.Unmarshal(resBody, &result)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if result.Status == "ERROR" {
|
||||||
|
return nil, fmt.Errorf(result.Reason)
|
||||||
|
}
|
||||||
|
res := AdminConnectInfoResponse{}
|
||||||
|
err = json.Unmarshal(resBody, &res)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &res, nil
|
||||||
|
},
|
||||||
|
GetServiceState: func() (*ServiceStateResponse, error) {
|
||||||
|
auth, err := params.RetrieveGuestAuth()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
finalRoute := "/wizard/service_state"
|
||||||
|
resBody, err := doGetRequest(params.BaseURL+finalRoute, auth)
|
||||||
|
result := ResultError{}
|
||||||
|
err = json.Unmarshal(resBody, &result)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if result.Status == "ERROR" {
|
||||||
|
return nil, fmt.Errorf(result.Reason)
|
||||||
|
}
|
||||||
|
res := ServiceStateResponse{}
|
||||||
|
err = json.Unmarshal(resBody, &res)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &res, nil
|
||||||
|
},
|
||||||
|
WizardConfig: func(req ConfigRequest) error {
|
||||||
|
auth, err := params.RetrieveGuestAuth()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
finalRoute := "/wizard/config"
|
||||||
|
body, err := json.Marshal(req)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
resBody, err := doPostRequest(params.BaseURL+finalRoute, body, auth)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
result := ResultError{}
|
||||||
|
err = json.Unmarshal(resBody, &result)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if result.Status == "ERROR" {
|
||||||
|
return fmt.Errorf(result.Reason)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
WizardState: func() (*StateResponse, error) {
|
||||||
|
auth, err := params.RetrieveGuestAuth()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
finalRoute := "/wizard/state"
|
||||||
|
resBody, err := doGetRequest(params.BaseURL+finalRoute, auth)
|
||||||
|
result := ResultError{}
|
||||||
|
err = json.Unmarshal(resBody, &result)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if result.Status == "ERROR" {
|
||||||
|
return nil, fmt.Errorf(result.Reason)
|
||||||
|
}
|
||||||
|
res := StateResponse{}
|
||||||
|
err = json.Unmarshal(resBody, &res)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &res, nil
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
63
proto/wizard_service/autogenerated/go/types.go
Normal file
63
proto/wizard_service/autogenerated/go/types.go
Normal file
|
|
@ -0,0 +1,63 @@
|
||||||
|
// This file was autogenerated from a .proto file, DO NOT EDIT!
|
||||||
|
|
||||||
|
package lightning_pub
|
||||||
|
|
||||||
|
type ResultError struct {
|
||||||
|
Status string `json:"status"`
|
||||||
|
Reason string `json:"reason"`
|
||||||
|
}
|
||||||
|
type GuestContext struct {
|
||||||
|
}
|
||||||
|
type LndState string
|
||||||
|
|
||||||
|
const (
|
||||||
|
OFFLINE LndState = "OFFLINE"
|
||||||
|
ONLINE LndState = "ONLINE"
|
||||||
|
SYNCING LndState = "SYNCING"
|
||||||
|
)
|
||||||
|
|
||||||
|
type AdminConnectInfoResponse struct {
|
||||||
|
Connect_info *AdminConnectInfoResponse_connect_info `json:"connect_info"`
|
||||||
|
Nprofile string `json:"nprofile"`
|
||||||
|
}
|
||||||
|
type ConfigRequest struct {
|
||||||
|
Automate_liquidity bool `json:"automate_liquidity"`
|
||||||
|
Avatar_url string `json:"avatar_url"`
|
||||||
|
Push_backups_to_nostr bool `json:"push_backups_to_nostr"`
|
||||||
|
Relay_url string `json:"relay_url"`
|
||||||
|
Source_name string `json:"source_name"`
|
||||||
|
}
|
||||||
|
type Empty struct {
|
||||||
|
}
|
||||||
|
type ServiceStateResponse struct {
|
||||||
|
Admin_npub string `json:"admin_npub"`
|
||||||
|
App_id string `json:"app_id"`
|
||||||
|
Automate_liquidity bool `json:"automate_liquidity"`
|
||||||
|
Avatar_url string `json:"avatar_url"`
|
||||||
|
Http_url string `json:"http_url"`
|
||||||
|
Lnd_state LndState `json:"lnd_state"`
|
||||||
|
Nprofile string `json:"nprofile"`
|
||||||
|
Provider_name string `json:"provider_name"`
|
||||||
|
Push_backups_to_nostr bool `json:"push_backups_to_nostr"`
|
||||||
|
Relay_connected bool `json:"relay_connected"`
|
||||||
|
Relay_url string `json:"relay_url"`
|
||||||
|
Relays []string `json:"relays"`
|
||||||
|
Source_name string `json:"source_name"`
|
||||||
|
Watchdog_ok bool `json:"watchdog_ok"`
|
||||||
|
}
|
||||||
|
type StateResponse struct {
|
||||||
|
Admin_linked bool `json:"admin_linked"`
|
||||||
|
Config_sent bool `json:"config_sent"`
|
||||||
|
}
|
||||||
|
type AdminConnectInfoResponse_connect_info_type string
|
||||||
|
|
||||||
|
const (
|
||||||
|
ADMIN_TOKEN AdminConnectInfoResponse_connect_info_type = "admin_token"
|
||||||
|
ENROLLED_NPUB AdminConnectInfoResponse_connect_info_type = "enrolled_npub"
|
||||||
|
)
|
||||||
|
|
||||||
|
type AdminConnectInfoResponse_connect_info struct {
|
||||||
|
Type AdminConnectInfoResponse_connect_info_type `json:"type"`
|
||||||
|
Admin_token *string `json:"admin_token"`
|
||||||
|
Enrolled_npub *string `json:"enrolled_npub"`
|
||||||
|
}
|
||||||
|
|
@ -29,47 +29,6 @@ export default (methods: Types.ServerMethods, opts: ServerOptions) => {
|
||||||
app.use(json())
|
app.use(json())
|
||||||
app.use(urlencoded({ extended: true }))
|
app.use(urlencoded({ extended: true }))
|
||||||
if (opts.logMethod) app.use((req, _, next) => { console.log(req.method, req.path); if (opts.logBody) console.log(req.body); next() })
|
if (opts.logMethod) app.use((req, _, next) => { console.log(req.method, req.path); if (opts.logBody) console.log(req.body); next() })
|
||||||
if (!opts.allowNotImplementedMethods && !methods.WizardState) throw new Error('method: WizardState is not implemented')
|
|
||||||
app.get('/wizard/state', async (req, res) => {
|
|
||||||
const info: Types.RequestInfo = { rpcName: 'WizardState', 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.WizardState) throw new Error('method: WizardState 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.WizardState({rpcName:'WizardState', ctx:authContext })
|
|
||||||
stats.handle = process.hrtime.bigint()
|
|
||||||
res.json({status: 'OK', ...response})
|
|
||||||
opts.metricsCallback([{ ...info, ...stats, ...authContext }])
|
|
||||||
} catch (ex) { const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback); if (opts.throwErrors) throw e }
|
|
||||||
})
|
|
||||||
if (!opts.allowNotImplementedMethods && !methods.WizardConfig) throw new Error('method: WizardConfig is not implemented')
|
|
||||||
app.post('/wizard/config', async (req, res) => {
|
|
||||||
const info: Types.RequestInfo = { rpcName: 'WizardConfig', 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.WizardConfig) throw new Error('method: WizardConfig is not implemented')
|
|
||||||
const authContext = await opts.GuestAuthGuard(req.headers['authorization'])
|
|
||||||
authCtx = authContext
|
|
||||||
stats.guard = process.hrtime.bigint()
|
|
||||||
const request = req.body
|
|
||||||
const error = Types.ConfigRequestValidate(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.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')
|
if (!opts.allowNotImplementedMethods && !methods.GetAdminConnectInfo) throw new Error('method: GetAdminConnectInfo is not implemented')
|
||||||
app.get('/wizard/admin_connect_info', async (req, res) => {
|
app.get('/wizard/admin_connect_info', async (req, res) => {
|
||||||
const info: Types.RequestInfo = { rpcName: 'GetAdminConnectInfo', batch: false, nostr: false, batchSize: 0}
|
const info: Types.RequestInfo = { rpcName: 'GetAdminConnectInfo', batch: false, nostr: false, batchSize: 0}
|
||||||
|
|
@ -108,6 +67,47 @@ 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.WizardConfig) throw new Error('method: WizardConfig is not implemented')
|
||||||
|
app.post('/wizard/config', async (req, res) => {
|
||||||
|
const info: Types.RequestInfo = { rpcName: 'WizardConfig', 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.WizardConfig) throw new Error('method: WizardConfig is not implemented')
|
||||||
|
const authContext = await opts.GuestAuthGuard(req.headers['authorization'])
|
||||||
|
authCtx = authContext
|
||||||
|
stats.guard = process.hrtime.bigint()
|
||||||
|
const request = req.body
|
||||||
|
const error = Types.ConfigRequestValidate(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.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.WizardState) throw new Error('method: WizardState is not implemented')
|
||||||
|
app.get('/wizard/state', async (req, res) => {
|
||||||
|
const info: Types.RequestInfo = { rpcName: 'WizardState', 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.WizardState) throw new Error('method: WizardState 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.WizardState({rpcName:'WizardState', ctx:authContext })
|
||||||
|
stats.handle = process.hrtime.bigint()
|
||||||
|
res.json({status: 'OK', ...response})
|
||||||
|
opts.metricsCallback([{ ...info, ...stats, ...authContext }])
|
||||||
|
} catch (ex) { const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback); if (opts.throwErrors) throw e }
|
||||||
|
})
|
||||||
if (opts.staticFiles) {
|
if (opts.staticFiles) {
|
||||||
app.use(express.static(opts.staticFiles))
|
app.use(express.static(opts.staticFiles))
|
||||||
app.get('*', function (_, res) { res.sendFile('index.html', { root: opts.staticFiles })})
|
app.get('*', function (_, res) { res.sendFile('index.html', { root: opts.staticFiles })})
|
||||||
|
|
|
||||||
|
|
@ -12,31 +12,6 @@ export type ClientParams = {
|
||||||
checkResult?: true
|
checkResult?: true
|
||||||
}
|
}
|
||||||
export default (params: ClientParams) => ({
|
export default (params: ClientParams) => ({
|
||||||
WizardState: async (): Promise<ResultError | ({ status: 'OK' }& Types.StateResponse)> => {
|
|
||||||
const auth = await params.retrieveGuestAuth()
|
|
||||||
if (auth === null) throw new Error('retrieveGuestAuth() returned null')
|
|
||||||
let finalRoute = '/wizard/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.StateResponseValidate(result)
|
|
||||||
if (error === null) { return { status: 'OK', ...result } } else return { status: 'ERROR', reason: error.message }
|
|
||||||
}
|
|
||||||
return { status: 'ERROR', reason: 'invalid response' }
|
|
||||||
},
|
|
||||||
WizardConfig: async (request: Types.ConfigRequest): Promise<ResultError | ({ status: 'OK' })> => {
|
|
||||||
const auth = await params.retrieveGuestAuth()
|
|
||||||
if (auth === null) throw new Error('retrieveGuestAuth() returned null')
|
|
||||||
let finalRoute = '/wizard/config'
|
|
||||||
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' }
|
|
||||||
},
|
|
||||||
GetAdminConnectInfo: async (): Promise<ResultError | ({ status: 'OK' }& Types.AdminConnectInfoResponse)> => {
|
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')
|
||||||
|
|
@ -65,4 +40,29 @@ 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' })> => {
|
||||||
|
const auth = await params.retrieveGuestAuth()
|
||||||
|
if (auth === null) throw new Error('retrieveGuestAuth() returned null')
|
||||||
|
let finalRoute = '/wizard/config'
|
||||||
|
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' }
|
||||||
|
},
|
||||||
|
WizardState: async (): Promise<ResultError | ({ status: 'OK' }& Types.StateResponse)> => {
|
||||||
|
const auth = await params.retrieveGuestAuth()
|
||||||
|
if (auth === null) throw new Error('retrieveGuestAuth() returned null')
|
||||||
|
let finalRoute = '/wizard/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.StateResponseValidate(result)
|
||||||
|
if (error === null) { return { status: 'OK', ...result } } else return { status: 'ERROR', reason: error.message }
|
||||||
|
}
|
||||||
|
return { status: 'ERROR', reason: 'invalid response' }
|
||||||
|
},
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -6,33 +6,33 @@ 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 | GetAdminConnectInfo_Input | GetServiceState_Input
|
export type GuestMethodInputs = GetAdminConnectInfo_Input | GetServiceState_Input | WizardConfig_Input | WizardState_Input
|
||||||
export type GuestMethodOutputs = WizardState_Output | WizardConfig_Output | GetAdminConnectInfo_Output | GetServiceState_Output
|
export type GuestMethodOutputs = GetAdminConnectInfo_Output | GetServiceState_Output | WizardConfig_Output | WizardState_Output
|
||||||
export type AuthContext = GuestContext
|
export type AuthContext = GuestContext
|
||||||
|
|
||||||
export type WizardState_Input = {rpcName:'WizardState'}
|
|
||||||
export type WizardState_Output = ResultError | ({ status: 'OK' } & StateResponse)
|
|
||||||
|
|
||||||
export type WizardConfig_Input = {rpcName:'WizardConfig', req: ConfigRequest}
|
|
||||||
export type WizardConfig_Output = ResultError | { status: 'OK' }
|
|
||||||
|
|
||||||
export type GetAdminConnectInfo_Input = {rpcName:'GetAdminConnectInfo'}
|
export type GetAdminConnectInfo_Input = {rpcName:'GetAdminConnectInfo'}
|
||||||
export type GetAdminConnectInfo_Output = ResultError | ({ status: 'OK' } & AdminConnectInfoResponse)
|
export type GetAdminConnectInfo_Output = ResultError | ({ status: 'OK' } & AdminConnectInfoResponse)
|
||||||
|
|
||||||
export type GetServiceState_Input = {rpcName:'GetServiceState'}
|
export type GetServiceState_Input = {rpcName:'GetServiceState'}
|
||||||
export type GetServiceState_Output = ResultError | ({ status: 'OK' } & ServiceStateResponse)
|
export type GetServiceState_Output = ResultError | ({ status: 'OK' } & ServiceStateResponse)
|
||||||
|
|
||||||
|
export type WizardConfig_Input = {rpcName:'WizardConfig', req: ConfigRequest}
|
||||||
|
export type WizardConfig_Output = ResultError | { status: 'OK' }
|
||||||
|
|
||||||
|
export type WizardState_Input = {rpcName:'WizardState'}
|
||||||
|
export type WizardState_Output = ResultError | ({ status: 'OK' } & StateResponse)
|
||||||
|
|
||||||
export type ServerMethods = {
|
export type ServerMethods = {
|
||||||
WizardState?: (req: WizardState_Input & {ctx: GuestContext }) => Promise<StateResponse>
|
|
||||||
WizardConfig?: (req: WizardConfig_Input & {ctx: GuestContext }) => Promise<void>
|
|
||||||
GetAdminConnectInfo?: (req: GetAdminConnectInfo_Input & {ctx: GuestContext }) => Promise<AdminConnectInfoResponse>
|
GetAdminConnectInfo?: (req: GetAdminConnectInfo_Input & {ctx: GuestContext }) => Promise<AdminConnectInfoResponse>
|
||||||
GetServiceState?: (req: GetServiceState_Input & {ctx: GuestContext }) => Promise<ServiceStateResponse>
|
GetServiceState?: (req: GetServiceState_Input & {ctx: GuestContext }) => Promise<ServiceStateResponse>
|
||||||
|
WizardConfig?: (req: WizardConfig_Input & {ctx: GuestContext }) => Promise<void>
|
||||||
|
WizardState?: (req: WizardState_Input & {ctx: GuestContext }) => Promise<StateResponse>
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum LndState {
|
export enum LndState {
|
||||||
OFFLINE = 'OFFLINE',
|
OFFLINE = 'OFFLINE',
|
||||||
SYNCING = 'SYNCING',
|
|
||||||
ONLINE = 'ONLINE',
|
ONLINE = 'ONLINE',
|
||||||
|
SYNCING = 'SYNCING',
|
||||||
}
|
}
|
||||||
export const enumCheckLndState = (e?: LndState): boolean => {
|
export const enumCheckLndState = (e?: LndState): boolean => {
|
||||||
for (const v in LndState) if (e === v) return true
|
for (const v in LndState) if (e === v) return true
|
||||||
|
|
@ -43,6 +43,68 @@ export type OptionsBaseMessage = {
|
||||||
allOptionalsAreSet?: true
|
allOptionalsAreSet?: true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type AdminConnectInfoResponse = {
|
||||||
|
connect_info: AdminConnectInfoResponse_connect_info
|
||||||
|
nprofile: string
|
||||||
|
}
|
||||||
|
export const AdminConnectInfoResponseOptionalFields: [] = []
|
||||||
|
export type AdminConnectInfoResponseOptions = OptionsBaseMessage & {
|
||||||
|
checkOptionalsAreSet?: []
|
||||||
|
connect_info_Options?: AdminConnectInfoResponse_connect_infoOptions
|
||||||
|
nprofile_CustomCheck?: (v: string) => 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')
|
||||||
|
|
||||||
|
const connect_infoErr = AdminConnectInfoResponse_connect_infoValidate(o.connect_info, opts.connect_info_Options, `${path}.connect_info`)
|
||||||
|
if (connect_infoErr !== null) return connect_infoErr
|
||||||
|
|
||||||
|
|
||||||
|
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`)
|
||||||
|
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
export type ConfigRequest = {
|
||||||
|
automate_liquidity: boolean
|
||||||
|
avatar_url: string
|
||||||
|
push_backups_to_nostr: boolean
|
||||||
|
relay_url: string
|
||||||
|
source_name: string
|
||||||
|
}
|
||||||
|
export const ConfigRequestOptionalFields: [] = []
|
||||||
|
export type ConfigRequestOptions = OptionsBaseMessage & {
|
||||||
|
checkOptionalsAreSet?: []
|
||||||
|
automate_liquidity_CustomCheck?: (v: boolean) => boolean
|
||||||
|
avatar_url_CustomCheck?: (v: string) => boolean
|
||||||
|
push_backups_to_nostr_CustomCheck?: (v: boolean) => boolean
|
||||||
|
relay_url_CustomCheck?: (v: string) => boolean
|
||||||
|
source_name_CustomCheck?: (v: string) => boolean
|
||||||
|
}
|
||||||
|
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 (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null')
|
||||||
|
|
||||||
|
if (typeof o.automate_liquidity !== 'boolean') return new Error(`${path}.automate_liquidity: is not a boolean`)
|
||||||
|
if (opts.automate_liquidity_CustomCheck && !opts.automate_liquidity_CustomCheck(o.automate_liquidity)) return new Error(`${path}.automate_liquidity: custom check failed`)
|
||||||
|
|
||||||
|
if (typeof o.avatar_url !== 'string') return new Error(`${path}.avatar_url: is not a string`)
|
||||||
|
if (opts.avatar_url_CustomCheck && !opts.avatar_url_CustomCheck(o.avatar_url)) return new Error(`${path}.avatar_url: custom check failed`)
|
||||||
|
|
||||||
|
if (typeof o.push_backups_to_nostr !== 'boolean') return new Error(`${path}.push_backups_to_nostr: is not a boolean`)
|
||||||
|
if (opts.push_backups_to_nostr_CustomCheck && !opts.push_backups_to_nostr_CustomCheck(o.push_backups_to_nostr)) return new Error(`${path}.push_backups_to_nostr: custom check failed`)
|
||||||
|
|
||||||
|
if (typeof o.relay_url !== 'string') return new Error(`${path}.relay_url: is not a string`)
|
||||||
|
if (opts.relay_url_CustomCheck && !opts.relay_url_CustomCheck(o.relay_url)) return new Error(`${path}.relay_url: custom check failed`)
|
||||||
|
|
||||||
|
if (typeof o.source_name !== 'string') return new Error(`${path}.source_name: is not a string`)
|
||||||
|
if (opts.source_name_CustomCheck && !opts.source_name_CustomCheck(o.source_name)) return new Error(`${path}.source_name: custom check failed`)
|
||||||
|
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
export type Empty = {
|
export type Empty = {
|
||||||
}
|
}
|
||||||
export const EmptyOptionalFields: [] = []
|
export const EmptyOptionalFields: [] = []
|
||||||
|
|
@ -56,138 +118,111 @@ export const EmptyValidate = (o?: Empty, opts: EmptyOptions = {}, path: string =
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
export type StateResponse = {
|
|
||||||
config_sent: boolean
|
|
||||||
admin_linked: boolean
|
|
||||||
}
|
|
||||||
export const StateResponseOptionalFields: [] = []
|
|
||||||
export type StateResponseOptions = OptionsBaseMessage & {
|
|
||||||
checkOptionalsAreSet?: []
|
|
||||||
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 => {
|
|
||||||
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.config_sent !== 'boolean') return new Error(`${path}.config_sent: is not a boolean`)
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
export type ConfigRequest = {
|
|
||||||
source_name: string
|
|
||||||
relay_url: string
|
|
||||||
automate_liquidity: boolean
|
|
||||||
push_backups_to_nostr: boolean
|
|
||||||
}
|
|
||||||
export const ConfigRequestOptionalFields: [] = []
|
|
||||||
export type ConfigRequestOptions = OptionsBaseMessage & {
|
|
||||||
checkOptionalsAreSet?: []
|
|
||||||
push_backups_to_nostr_CustomCheck?: (v: boolean) => boolean
|
|
||||||
source_name_CustomCheck?: (v: string) => boolean
|
|
||||||
relay_url_CustomCheck?: (v: string) => boolean
|
|
||||||
automate_liquidity_CustomCheck?: (v: boolean) => boolean
|
|
||||||
}
|
|
||||||
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 (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null')
|
|
||||||
|
|
||||||
if (typeof o.source_name !== 'string') return new Error(`${path}.source_name: is not a string`)
|
|
||||||
if (opts.source_name_CustomCheck && !opts.source_name_CustomCheck(o.source_name)) return new Error(`${path}.source_name: custom check failed`)
|
|
||||||
|
|
||||||
if (typeof o.relay_url !== 'string') return new Error(`${path}.relay_url: is not a string`)
|
|
||||||
if (opts.relay_url_CustomCheck && !opts.relay_url_CustomCheck(o.relay_url)) return new Error(`${path}.relay_url: custom check failed`)
|
|
||||||
|
|
||||||
if (typeof o.automate_liquidity !== 'boolean') return new Error(`${path}.automate_liquidity: is not a boolean`)
|
|
||||||
if (opts.automate_liquidity_CustomCheck && !opts.automate_liquidity_CustomCheck(o.automate_liquidity)) return new Error(`${path}.automate_liquidity: custom check failed`)
|
|
||||||
|
|
||||||
if (typeof o.push_backups_to_nostr !== 'boolean') return new Error(`${path}.push_backups_to_nostr: is not a boolean`)
|
|
||||||
if (opts.push_backups_to_nostr_CustomCheck && !opts.push_backups_to_nostr_CustomCheck(o.push_backups_to_nostr)) return new Error(`${path}.push_backups_to_nostr: custom check failed`)
|
|
||||||
|
|
||||||
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 = {
|
export type ServiceStateResponse = {
|
||||||
|
admin_npub: string
|
||||||
|
app_id: string
|
||||||
|
automate_liquidity: boolean
|
||||||
|
avatar_url: string
|
||||||
http_url: string
|
http_url: string
|
||||||
|
lnd_state: LndState
|
||||||
nprofile: string
|
nprofile: string
|
||||||
provider_name: string
|
provider_name: string
|
||||||
relays: string[]
|
push_backups_to_nostr: boolean
|
||||||
admin_npub: string
|
|
||||||
relay_connected: boolean
|
relay_connected: boolean
|
||||||
lnd_state: LndState
|
relay_url: string
|
||||||
|
relays: string[]
|
||||||
|
source_name: string
|
||||||
watchdog_ok: boolean
|
watchdog_ok: boolean
|
||||||
}
|
}
|
||||||
export const ServiceStateResponseOptionalFields: [] = []
|
export const ServiceStateResponseOptionalFields: [] = []
|
||||||
export type ServiceStateResponseOptions = OptionsBaseMessage & {
|
export type ServiceStateResponseOptions = OptionsBaseMessage & {
|
||||||
checkOptionalsAreSet?: []
|
checkOptionalsAreSet?: []
|
||||||
|
admin_npub_CustomCheck?: (v: string) => boolean
|
||||||
|
app_id_CustomCheck?: (v: string) => boolean
|
||||||
|
automate_liquidity_CustomCheck?: (v: boolean) => boolean
|
||||||
|
avatar_url_CustomCheck?: (v: string) => boolean
|
||||||
http_url_CustomCheck?: (v: string) => boolean
|
http_url_CustomCheck?: (v: string) => boolean
|
||||||
|
lnd_state_CustomCheck?: (v: LndState) => boolean
|
||||||
nprofile_CustomCheck?: (v: string) => boolean
|
nprofile_CustomCheck?: (v: string) => boolean
|
||||||
provider_name_CustomCheck?: (v: string) => boolean
|
provider_name_CustomCheck?: (v: string) => boolean
|
||||||
relays_CustomCheck?: (v: string[]) => boolean
|
push_backups_to_nostr_CustomCheck?: (v: boolean) => boolean
|
||||||
admin_npub_CustomCheck?: (v: string) => boolean
|
|
||||||
relay_connected_CustomCheck?: (v: boolean) => boolean
|
relay_connected_CustomCheck?: (v: boolean) => boolean
|
||||||
lnd_state_CustomCheck?: (v: LndState) => boolean
|
relay_url_CustomCheck?: (v: string) => boolean
|
||||||
|
relays_CustomCheck?: (v: string[]) => boolean
|
||||||
|
source_name_CustomCheck?: (v: string) => boolean
|
||||||
watchdog_ok_CustomCheck?: (v: boolean) => boolean
|
watchdog_ok_CustomCheck?: (v: boolean) => boolean
|
||||||
}
|
}
|
||||||
export const ServiceStateResponseValidate = (o?: ServiceStateResponse, opts: ServiceStateResponseOptions = {}, path: string = 'ServiceStateResponse::root.'): Error | null => {
|
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 (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.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.app_id !== 'string') return new Error(`${path}.app_id: is not a string`)
|
||||||
|
if (opts.app_id_CustomCheck && !opts.app_id_CustomCheck(o.app_id)) return new Error(`${path}.app_id: custom check failed`)
|
||||||
|
|
||||||
|
if (typeof o.automate_liquidity !== 'boolean') return new Error(`${path}.automate_liquidity: is not a boolean`)
|
||||||
|
if (opts.automate_liquidity_CustomCheck && !opts.automate_liquidity_CustomCheck(o.automate_liquidity)) return new Error(`${path}.automate_liquidity: custom check failed`)
|
||||||
|
|
||||||
|
if (typeof o.avatar_url !== 'string') return new Error(`${path}.avatar_url: is not a string`)
|
||||||
|
if (opts.avatar_url_CustomCheck && !opts.avatar_url_CustomCheck(o.avatar_url)) return new Error(`${path}.avatar_url: 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 (!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.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`)
|
||||||
|
|
||||||
|
if (typeof o.push_backups_to_nostr !== 'boolean') return new Error(`${path}.push_backups_to_nostr: is not a boolean`)
|
||||||
|
if (opts.push_backups_to_nostr_CustomCheck && !opts.push_backups_to_nostr_CustomCheck(o.push_backups_to_nostr)) return new Error(`${path}.push_backups_to_nostr: 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 (typeof o.relay_url !== 'string') return new Error(`${path}.relay_url: is not a string`)
|
||||||
|
if (opts.relay_url_CustomCheck && !opts.relay_url_CustomCheck(o.relay_url)) return new Error(`${path}.relay_url: custom check failed`)
|
||||||
|
|
||||||
if (!Array.isArray(o.relays)) return new Error(`${path}.relays: is not an array`)
|
if (!Array.isArray(o.relays)) return new Error(`${path}.relays: is not an array`)
|
||||||
for (let index = 0; index < o.relays.length; index++) {
|
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 (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 (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 (typeof o.source_name !== 'string') return new Error(`${path}.source_name: 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 (opts.source_name_CustomCheck && !opts.source_name_CustomCheck(o.source_name)) return new Error(`${path}.source_name: 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 (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 (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`)
|
return null
|
||||||
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`)
|
export type StateResponse = {
|
||||||
if (opts.nprofile_CustomCheck && !opts.nprofile_CustomCheck(o.nprofile)) return new Error(`${path}.nprofile: custom check failed`)
|
admin_linked: boolean
|
||||||
|
config_sent: boolean
|
||||||
|
}
|
||||||
|
export const StateResponseOptionalFields: [] = []
|
||||||
|
export type StateResponseOptions = OptionsBaseMessage & {
|
||||||
|
checkOptionalsAreSet?: []
|
||||||
|
admin_linked_CustomCheck?: (v: boolean) => boolean
|
||||||
|
config_sent_CustomCheck?: (v: boolean) => boolean
|
||||||
|
}
|
||||||
|
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 (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null')
|
||||||
|
|
||||||
if (typeof o.provider_name !== 'string') return new Error(`${path}.provider_name: is not a string`)
|
if (typeof o.admin_linked !== 'boolean') return new Error(`${path}.admin_linked: is not a boolean`)
|
||||||
if (opts.provider_name_CustomCheck && !opts.provider_name_CustomCheck(o.provider_name)) return new Error(`${path}.provider_name: custom check failed`)
|
if (opts.admin_linked_CustomCheck && !opts.admin_linked_CustomCheck(o.admin_linked)) return new Error(`${path}.admin_linked: custom check failed`)
|
||||||
|
|
||||||
|
if (typeof o.config_sent !== 'boolean') return new Error(`${path}.config_sent: is not a boolean`)
|
||||||
|
if (opts.config_sent_CustomCheck && !opts.config_sent_CustomCheck(o.config_sent)) return new Error(`${path}.config_sent: custom check failed`)
|
||||||
|
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
@ -196,19 +231,34 @@ export enum AdminConnectInfoResponse_connect_info_type {
|
||||||
ADMIN_TOKEN = 'admin_token',
|
ADMIN_TOKEN = 'admin_token',
|
||||||
ENROLLED_NPUB = 'enrolled_npub',
|
ENROLLED_NPUB = 'enrolled_npub',
|
||||||
}
|
}
|
||||||
|
export const enumCheckAdminConnectInfoResponse_connect_info_type = (e?: AdminConnectInfoResponse_connect_info_type): boolean => {
|
||||||
|
for (const v in AdminConnectInfoResponse_connect_info_type) if (e === v) return true
|
||||||
|
return false
|
||||||
|
}
|
||||||
export type AdminConnectInfoResponse_connect_info =
|
export type AdminConnectInfoResponse_connect_info =
|
||||||
{type:AdminConnectInfoResponse_connect_info_type.ADMIN_TOKEN, admin_token:string}|
|
{type:AdminConnectInfoResponse_connect_info_type.ADMIN_TOKEN, admin_token:string}|
|
||||||
{type:AdminConnectInfoResponse_connect_info_type.ENROLLED_NPUB, enrolled_npub: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 => {
|
export type AdminConnectInfoResponse_connect_infoOptions = {
|
||||||
if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null')
|
admin_token_CustomCheck?: (v: string) => boolean
|
||||||
switch (o.type) {
|
enrolled_npub_CustomCheck?: (v: string) => boolean
|
||||||
case 'admin_token':
|
}
|
||||||
if (typeof o.admin_token !== 'string') return new Error(`${path}.admin_token: is not a string`)
|
export const AdminConnectInfoResponse_connect_infoValidate = (o?: AdminConnectInfoResponse_connect_info, opts:AdminConnectInfoResponse_connect_infoOptions = {}, path: string = 'AdminConnectInfoResponse_connect_info::root.'): Error | null => {
|
||||||
break
|
if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null')
|
||||||
case 'enrolled_npub':
|
const stringType: string = o.type
|
||||||
if (typeof o.enrolled_npub !== 'string') return new Error(`${path}.enrolled_npub: is not a string`)
|
switch (o.type) {
|
||||||
break
|
case AdminConnectInfoResponse_connect_info_type.ADMIN_TOKEN:
|
||||||
}
|
if (typeof o.admin_token !== 'string') return new Error(`${path}.admin_token: is not a string`)
|
||||||
return new Error(path + ': unknown type'+ o.type)
|
if (opts.admin_token_CustomCheck && !opts.admin_token_CustomCheck(o.admin_token)) return new Error(`${path}.admin_token: custom check failed`)
|
||||||
|
|
||||||
|
break
|
||||||
|
case AdminConnectInfoResponse_connect_info_type.ENROLLED_NPUB:
|
||||||
|
if (typeof o.enrolled_npub !== 'string') return new Error(`${path}.enrolled_npub: is not a string`)
|
||||||
|
if (opts.enrolled_npub_CustomCheck && !opts.enrolled_npub_CustomCheck(o.enrolled_npub)) return new Error(`${path}.enrolled_npub: custom check failed`)
|
||||||
|
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
return new Error(path + ': unknown type '+ stringType)
|
||||||
|
}
|
||||||
|
return null
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ log() {
|
||||||
echo -e "$(echo "$message" | sed 's/\\e\[[0-9;]*m//g')" >> "$TMP_LOG_FILE"
|
echo -e "$(echo "$message" | sed 's/\\e\[[0-9;]*m//g')" >> "$TMP_LOG_FILE"
|
||||||
}
|
}
|
||||||
|
|
||||||
SCRIPT_VERSION="0.2.1"
|
SCRIPT_VERSION="0.2.2"
|
||||||
REPO="shocknet/Lightning.Pub"
|
REPO="shocknet/Lightning.Pub"
|
||||||
BRANCH="master"
|
BRANCH="master"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -95,7 +95,11 @@ install_lnd() {
|
||||||
# Check for and add default settings only if the keys are missing.
|
# Check for and add default settings only if the keys are missing.
|
||||||
grep -q "^bitcoin.mainnet=" $USER_HOME/.lnd/lnd.conf || echo "bitcoin.mainnet=true" >> $USER_HOME/.lnd/lnd.conf
|
grep -q "^bitcoin.mainnet=" $USER_HOME/.lnd/lnd.conf || echo "bitcoin.mainnet=true" >> $USER_HOME/.lnd/lnd.conf
|
||||||
grep -q "^bitcoin.node=" $USER_HOME/.lnd/lnd.conf || echo "bitcoin.node=neutrino" >> $USER_HOME/.lnd/lnd.conf
|
grep -q "^bitcoin.node=" $USER_HOME/.lnd/lnd.conf || echo "bitcoin.node=neutrino" >> $USER_HOME/.lnd/lnd.conf
|
||||||
grep -q "^neutrino.addpeer=" $USER_HOME/.lnd/lnd.conf || echo "neutrino.addpeer=neutrino.shock.network" >> $USER_HOME/.lnd/lnd.conf
|
grep -q "^neutrino.addpeer=neutrino.shock.network" $USER_HOME/.lnd/lnd.conf || echo "neutrino.addpeer=neutrino.shock.network" >> $USER_HOME/.lnd/lnd.conf
|
||||||
|
grep -q "^neutrino.addpeer=asia.blixtwallet.com" $USER_HOME/.lnd/lnd.conf || echo "neutrino.addpeer=asia.blixtwallet.com" >> $USER_HOME/.lnd/lnd.conf
|
||||||
|
grep -q "^neutrino.addpeer=europe.blixtwallet.com" $USER_HOME/.lnd/lnd.conf || echo "neutrino.addpeer=europe.blixtwallet.com" >> $USER_HOME/.lnd/lnd.conf
|
||||||
|
grep -q "^neutrino.addpeer=btcd.lnolymp.us" $USER_HOME/.lnd/lnd.conf || echo "neutrino.addpeer=btcd.lnolymp.us" >> $USER_HOME/.lnd/lnd.conf
|
||||||
|
grep -q "^neutrino.addpeer=btcd-mainnet.lightning.computer" $USER_HOME/.lnd/lnd.conf || echo "neutrino.addpeer=btcd-mainnet.lightning.computer" >> $USER_HOME/.lnd/lnd.conf
|
||||||
grep -q "^fee.url=" $USER_HOME/.lnd/lnd.conf || echo "fee.url=https://nodes.lightning.computer/fees/v1/btc-fee-estimates.json" >> $USER_HOME/.lnd/lnd.conf
|
grep -q "^fee.url=" $USER_HOME/.lnd/lnd.conf || echo "fee.url=https://nodes.lightning.computer/fees/v1/btc-fee-estimates.json" >> $USER_HOME/.lnd/lnd.conf
|
||||||
|
|
||||||
chmod 600 $USER_HOME/.lnd/lnd.conf
|
chmod 600 $USER_HOME/.lnd/lnd.conf
|
||||||
|
|
|
||||||
|
|
@ -80,7 +80,10 @@ export default (serverMethods: Types.ServerMethods, mainHandler: Main, nostrSett
|
||||||
}, event.startAtNano, event.startAtMs)
|
}, event.startAtNano, event.startAtMs)
|
||||||
})
|
})
|
||||||
|
|
||||||
return { Stop: () => nostr.Stop, Send: (...args) => nostr.Send(...args), Ping: () => nostr.Ping() }
|
// Mark nostr connected/ready after initial subscription tick
|
||||||
|
mainHandler.adminManager.setNostrConnected(true)
|
||||||
|
|
||||||
|
return { Stop: () => { mainHandler.adminManager.setNostrConnected(false); return nostr.Stop }, Send: (...args) => nostr.Send(...args), Ping: () => nostr.Ping() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ export class AdminManager {
|
||||||
interval: NodeJS.Timer
|
interval: NodeJS.Timer
|
||||||
appNprofile: string
|
appNprofile: string
|
||||||
lnd: LND
|
lnd: LND
|
||||||
|
nostrConnected: boolean = false
|
||||||
constructor(mainSettings: MainSettings, storage: Storage) {
|
constructor(mainSettings: MainSettings, storage: Storage) {
|
||||||
this.storage = storage
|
this.storage = storage
|
||||||
this.dataDir = mainSettings.storageSettings.dataDir
|
this.dataDir = mainSettings.storageSettings.dataDir
|
||||||
|
|
@ -42,6 +43,14 @@ export class AdminManager {
|
||||||
this.lnd = lnd
|
this.lnd = lnd
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setNostrConnected = (connected: boolean) => {
|
||||||
|
this.nostrConnected = connected
|
||||||
|
}
|
||||||
|
|
||||||
|
GetNostrConnected = () => {
|
||||||
|
return this.nostrConnected
|
||||||
|
}
|
||||||
|
|
||||||
setAppNprofile = (nprofile: string) => {
|
setAppNprofile = (nprofile: string) => {
|
||||||
this.appNprofile = nprofile
|
this.appNprofile = nprofile
|
||||||
const enrollToken = this.ReadAdminEnrollToken()
|
const enrollToken = this.ReadAdminEnrollToken()
|
||||||
|
|
|
||||||
|
|
@ -99,7 +99,7 @@ export default class {
|
||||||
|
|
||||||
StartBeacons() {
|
StartBeacons() {
|
||||||
this.applicationManager.StartAppsServiceBeacon(app => {
|
this.applicationManager.StartAppsServiceBeacon(app => {
|
||||||
this.UpdateBeacon(app, { type: 'service', name: app.name })
|
this.UpdateBeacon(app, { type: 'service', name: app.name, avatarUrl: (app as any).avatar_url })
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -386,7 +386,7 @@ export default class {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async UpdateBeacon(app: Application, content: { type: 'service', name: string }) {
|
async UpdateBeacon(app: Application, content: { type: 'service', name: string, avatarUrl?: string }) {
|
||||||
if (!app.nostr_public_key) {
|
if (!app.nostr_public_key) {
|
||||||
getLogger({ appName: app.name })("cannot update beacon, public key not set")
|
getLogger({ appName: app.name })("cannot update beacon, public key not set")
|
||||||
return
|
return
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,9 @@ export class Application {
|
||||||
@Column({ nullable: true, unique: true })
|
@Column({ nullable: true, unique: true })
|
||||||
nostr_public_key?: string
|
nostr_public_key?: string
|
||||||
|
|
||||||
|
@Column({ nullable: true })
|
||||||
|
avatar_url?: string
|
||||||
|
|
||||||
@CreateDateColumn()
|
@CreateDateColumn()
|
||||||
created_at: Date
|
created_at: Date
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
import { MigrationInterface, QueryRunner } from "typeorm";
|
||||||
|
|
||||||
|
export class ApplicationAvatarUrl1761000001000 implements MigrationInterface {
|
||||||
|
name = 'ApplicationAvatarUrl1761000001000'
|
||||||
|
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`ALTER TABLE "application" ADD COLUMN "avatar_url" varchar`);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
// SQLite has limited ALTER TABLE support; we can recreate table if needed, but for now just keep it simple
|
||||||
|
// No-op: dropping a column is non-trivial; leave column in place on downgrade
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -25,12 +25,13 @@ import { OldSomethingLeftover1753106599604 } from './1753106599604-old_something
|
||||||
import { UserReceivingInvoiceIdx1753109184611 } from './1753109184611-user_receiving_invoice_idx.js'
|
import { UserReceivingInvoiceIdx1753109184611 } from './1753109184611-user_receiving_invoice_idx.js'
|
||||||
import { UserAccess1759426050669 } from './1759426050669-user_access.js'
|
import { UserAccess1759426050669 } from './1759426050669-user_access.js'
|
||||||
import { AddBlindToUserOffer1760000000000 } from './1760000000000-add_blind_to_user_offer.js'
|
import { AddBlindToUserOffer1760000000000 } from './1760000000000-add_blind_to_user_offer.js'
|
||||||
|
import { ApplicationAvatarUrl1761000001000 } from './1761000001000-application_avatar_url.js'
|
||||||
|
|
||||||
|
|
||||||
export const allMigrations = [Initial1703170309875, LspOrder1718387847693, LiquidityProvider1719335699480, LndNodeInfo1720187506189,
|
export const allMigrations = [Initial1703170309875, LspOrder1718387847693, LiquidityProvider1719335699480, LndNodeInfo1720187506189,
|
||||||
TrackedProvider1720814323679, CreateInviteTokenTable1721751414878, PaymentIndex1721760297610, DebitAccess1726496225078, DebitAccessFixes1726685229264,
|
TrackedProvider1720814323679, CreateInviteTokenTable1721751414878, PaymentIndex1721760297610, DebitAccess1726496225078, DebitAccessFixes1726685229264,
|
||||||
DebitToPub1727105758354, UserCbUrl1727112281043, UserOffer1733502626042, ManagementGrant1751307732346, ManagementGrantBanned1751989251513,
|
DebitToPub1727105758354, UserCbUrl1727112281043, UserOffer1733502626042, ManagementGrant1751307732346, ManagementGrantBanned1751989251513,
|
||||||
InvoiceCallbackUrls1752425992291, OldSomethingLeftover1753106599604, UserReceivingInvoiceIdx1753109184611, AppUserDevice1753285173175, UserAccess1759426050669, AddBlindToUserOffer1760000000000]
|
InvoiceCallbackUrls1752425992291, OldSomethingLeftover1753106599604, UserReceivingInvoiceIdx1753109184611, AppUserDevice1753285173175, UserAccess1759426050669, AddBlindToUserOffer1760000000000, ApplicationAvatarUrl1761000001000]
|
||||||
|
|
||||||
export const allMetricsMigrations = [LndMetrics1703170330183, ChannelRouting1709316653538, HtlcCount1724266887195, BalanceEvents1724860966825, RootOps1732566440447, RootOpsTime1745428134124, ChannelEvents1750777346411]
|
export const allMetricsMigrations = [LndMetrics1703170330183, ChannelRouting1709316653538, HtlcCount1724266887195, BalanceEvents1724860966825, RootOps1732566440447, RootOpsTime1745428134124, ChannelEvents1750777346411]
|
||||||
/* export const TypeOrmMigrationRunner = async (log: PubLogger, storageManager: Storage, settings: DbSettings, arg: string | undefined): Promise<boolean> => {
|
/* export const TypeOrmMigrationRunner = async (log: PubLogger, storageManager: Storage, settings: DbSettings, arg: string | undefined): Promise<boolean> => {
|
||||||
|
|
|
||||||
|
|
@ -40,19 +40,63 @@ export class Wizard {
|
||||||
}
|
}
|
||||||
|
|
||||||
GetServiceState = async (): Promise<WizardTypes.ServiceStateResponse> => {
|
GetServiceState = async (): Promise<WizardTypes.ServiceStateResponse> => {
|
||||||
const apps = await this.storage.applicationStorage.GetApplications()
|
try {
|
||||||
const appNamesList = apps.map(app => app.name).join(', ')
|
const apps = await this.storage.applicationStorage.GetApplications()
|
||||||
return {
|
const appNamesList = apps.map(app => app.name).join(', ')
|
||||||
admin_npub: this.adminManager.GetAdminNpub(),
|
const relays = this.settings.nostrRelaySettings ? this.settings.nostrRelaySettings.relays : [];
|
||||||
http_url: this.settings.serviceUrl,
|
const relayUrl = (relays && relays.length > 0) ? relays[0] : '';
|
||||||
lnd_state: WizardTypes.LndState.OFFLINE,
|
const defaultApp = apps.find(a => a.name === this.settings.defaultAppName) || apps[0]
|
||||||
nprofile: this.nprofile,
|
// Determine LND state and watchdog
|
||||||
provider_name: appNamesList,
|
let lndState: WizardTypes.LndState = WizardTypes.LndState.OFFLINE
|
||||||
relay_connected: false,
|
let watchdogOk = false
|
||||||
relays: this.relays,
|
try {
|
||||||
watchdog_ok: false
|
const info = await this.adminManager.LndGetInfo()
|
||||||
|
const online = info.synced_to_chain && info.synced_to_graph
|
||||||
|
lndState = online ? WizardTypes.LndState.ONLINE : WizardTypes.LndState.SYNCING
|
||||||
|
watchdogOk = !info.watchdog_barking
|
||||||
|
} catch {
|
||||||
|
lndState = WizardTypes.LndState.OFFLINE
|
||||||
|
watchdogOk = false
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
admin_npub: this.adminManager.GetAdminNpub(),
|
||||||
|
http_url: this.settings.serviceUrl,
|
||||||
|
lnd_state: lndState,
|
||||||
|
nprofile: this.nprofile,
|
||||||
|
provider_name: defaultApp?.name || appNamesList,
|
||||||
|
relay_connected: this.adminManager.GetNostrConnected(),
|
||||||
|
relays: this.relays,
|
||||||
|
watchdog_ok: watchdogOk,
|
||||||
|
source_name: defaultApp?.name || this.settings.defaultAppName || appNamesList,
|
||||||
|
relay_url: relayUrl,
|
||||||
|
automate_liquidity: this.settings.liquiditySettings.liquidityProviderPub !== 'null',
|
||||||
|
push_backups_to_nostr: this.settings.pushBackupsToNostr,
|
||||||
|
avatar_url: defaultApp?.avatar_url || '',
|
||||||
|
app_id: defaultApp?.app_id || ''
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
this.log(`Error in GetServiceState: ${(e as Error).message}`)
|
||||||
|
// Return a default/error state that is still valid JSON to prevent client-side parse errors
|
||||||
|
return {
|
||||||
|
admin_npub: '',
|
||||||
|
http_url: '',
|
||||||
|
lnd_state: WizardTypes.LndState.OFFLINE,
|
||||||
|
nprofile: '',
|
||||||
|
provider_name: 'Error loading state',
|
||||||
|
relay_connected: false,
|
||||||
|
relays: [],
|
||||||
|
watchdog_ok: false,
|
||||||
|
source_name: 'Error',
|
||||||
|
relay_url: '',
|
||||||
|
automate_liquidity: false,
|
||||||
|
push_backups_to_nostr: false,
|
||||||
|
avatar_url: '',
|
||||||
|
app_id: ''
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
WizardState = async (): Promise<WizardTypes.StateResponse> => {
|
WizardState = async (): Promise<WizardTypes.StateResponse> => {
|
||||||
return {
|
return {
|
||||||
config_sent: this.pendingConfig !== null,
|
config_sent: this.pendingConfig !== null,
|
||||||
|
|
@ -118,10 +162,30 @@ export class Wizard {
|
||||||
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) {
|
|
||||||
throw new Error("already initialized")
|
|
||||||
}
|
|
||||||
const 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 }
|
||||||
|
|
||||||
|
// Persist app name/avatar to DB regardless (idempotent behavior)
|
||||||
|
try {
|
||||||
|
const appsList = await this.storage.applicationStorage.GetApplications()
|
||||||
|
const defaultNames = ['wallet', 'wallet-test', this.settings.defaultAppName]
|
||||||
|
const existingDefaultApp = appsList.find(app => defaultNames.includes(app.name)) || appsList[0]
|
||||||
|
if (existingDefaultApp) {
|
||||||
|
await this.storage.applicationStorage.UpdateApplication(existingDefaultApp, { name: req.source_name, avatar_url: (req as any).avatar_url || existingDefaultApp.avatar_url })
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
this.log(`Error updating app info: ${(e as Error).message}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
// If already initialized, treat as idempotent update for env and exit
|
||||||
|
if (this.IsInitialized()) {
|
||||||
|
this.updateEnvFile(pendingConfig)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// First-time configuration flow
|
||||||
|
if (this.pendingConfig !== null) {
|
||||||
|
throw new Error("already initializing")
|
||||||
|
}
|
||||||
this.updateEnvFile(pendingConfig)
|
this.updateEnvFile(pendingConfig)
|
||||||
this.configQueue.forEach(q => q.res(true))
|
this.configQueue.forEach(q => q.res(true))
|
||||||
this.configQueue = []
|
this.configQueue = []
|
||||||
|
|
@ -153,10 +217,16 @@ export class Wizard {
|
||||||
}
|
}
|
||||||
|
|
||||||
const automateLiquidityIndex = envFileContent.findIndex(line => line.startsWith('LIQUIDITY_PROVIDER_PUB'))
|
const automateLiquidityIndex = envFileContent.findIndex(line => line.startsWith('LIQUIDITY_PROVIDER_PUB'))
|
||||||
if (automateLiquidityIndex === -1) {
|
if (pendingConfig.automateLiquidity) {
|
||||||
toMerge.push(`LIQUIDITY_PROVIDER_PUB=${pendingConfig.automateLiquidity ? defaultProviderPub : ""}`)
|
if (automateLiquidityIndex !== -1) {
|
||||||
|
envFileContent.splice(automateLiquidityIndex, 1)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
envFileContent[automateLiquidityIndex] = `LIQUIDITY_PROVIDER_PUB=null`
|
if (automateLiquidityIndex === -1) {
|
||||||
|
toMerge.push(`LIQUIDITY_PROVIDER_PUB=null`)
|
||||||
|
} else {
|
||||||
|
envFileContent[automateLiquidityIndex] = `LIQUIDITY_PROVIDER_PUB=null`
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const pushBackupsToNostrIndex = envFileContent.findIndex(line => line.startsWith('PUSH_BACKUPS_TO_NOSTR'))
|
const pushBackupsToNostrIndex = envFileContent.findIndex(line => line.startsWith('PUSH_BACKUPS_TO_NOSTR'))
|
||||||
|
|
|
||||||
|
|
@ -1,143 +0,0 @@
|
||||||
<!DOCTYPE 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/backup.css" />
|
|
||||||
<!-- HTML Meta Tags -->
|
|
||||||
<title>Lightning.Pub</title>
|
|
||||||
<meta name="description" content="Lightning for Everyone" />
|
|
||||||
<link rel="icon" type="image/png" href="img/pub_logo.png" />
|
|
||||||
<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>
|
|
||||||
<section class="setup-header">
|
|
||||||
<button class="icon-button back-button" onclick="history.back()">
|
|
||||||
<img src="img/back.svg" alt="" />
|
|
||||||
</button>
|
|
||||||
<h2>Choose a Recovery Method</h2>
|
|
||||||
<p class="header-title">
|
|
||||||
<span style="font-weight: bold">New Node! 🎉</span> It's important
|
|
||||||
to backup your keys.
|
|
||||||
</p>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<div class="line"></div>
|
|
||||||
|
|
||||||
<section class="setup-content">
|
|
||||||
<div class="description-box">
|
|
||||||
<div class="description">
|
|
||||||
In addition to your seed phrase, you also need channel details to recover funds should your node experience a
|
|
||||||
hardware failure.
|
|
||||||
</div>
|
|
||||||
<br />
|
|
||||||
<div class="description">
|
|
||||||
It's important always to have the latest version of this file. Fortunately, it's small enough to automatically
|
|
||||||
store on the Nostr relay.
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="warning-text">
|
|
||||||
If you did not choose the developers relay, be sure your relay has
|
|
||||||
adequate storage policies to hold NIP78 events.
|
|
||||||
</div>
|
|
||||||
<div class="checkbox-container">
|
|
||||||
<div class="checkbox" style="margin-top: 12px">
|
|
||||||
<input type="checkbox" id="backup" />
|
|
||||||
<div class="checkbox-shape"></div>
|
|
||||||
<label for="backup">
|
|
||||||
Encrypted Backup to Nostr Relay
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="checkbox-container">
|
|
||||||
<div class="checkbox manual-checkbox" style="margin-top: 12px">
|
|
||||||
<input type="checkbox" id="manual-backup" />
|
|
||||||
<div class="checkbox-shape"></div>
|
|
||||||
<label for="manual-backup">
|
|
||||||
DO NOT store on relay (Manual Backups)
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<p id="errorText" style="color:red"></p>
|
|
||||||
</div>
|
|
||||||
<button class="push-button hidden-button" style="margin-top: 60px;" id="next-button">
|
|
||||||
Next
|
|
||||||
</button>
|
|
||||||
</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 class="line"></div>
|
|
||||||
<a href="https://docs.shock.network" class="marked need-help">Need Help?</a>
|
|
||||||
</footer>
|
|
||||||
|
|
||||||
<script src="js/backup.js"></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) => {
|
|
||||||
const backup = document.getElementById('backup').checked
|
|
||||||
const manual = document.getElementById('manual-backup').checked
|
|
||||||
if (!backup && !manual) {
|
|
||||||
document.getElementById('errorText').innerText = 'Please select an option'
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (backup && manual) {
|
|
||||||
document.getElementById('errorText').innerText = 'Please select only one option'
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (backup) {
|
|
||||||
localStorage.setItem('wizard/backup', 'backup')
|
|
||||||
} else {
|
|
||||||
localStorage.setItem('wizard/backup', 'manual')
|
|
||||||
}
|
|
||||||
sendConfig()
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
|
|
||||||
</html>
|
|
||||||
|
|
@ -19,7 +19,7 @@
|
||||||
<body>
|
<body>
|
||||||
<header>
|
<header>
|
||||||
<img src="img/pub_logo.png" width="38px" height="auto" alt="Lightning Pub logo" />
|
<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" />
|
<img src="img/LightningPub.png" height="26px" alt="Lightning Pub logo" />
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<main>
|
<main>
|
||||||
|
|
@ -48,7 +48,7 @@
|
||||||
<div style="text-align: center; color: #c434e0;" id="click-text">Click to reveal</div>
|
<div style="text-align: center; color: #c434e0;" id="click-text">Click to reveal</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="qrcode"></div>
|
<div id="qrcode"></div>
|
||||||
<div style="color: #a3a3a3; font-size: 11px;">
|
<div style="color: #a3a3a3; font-size: 11px; word-break: break-all; overflow-wrap: anywhere; max-width: 220px; margin: 0 auto;">
|
||||||
<div id="connectString"></div>
|
<div id="connectString"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -104,13 +104,20 @@
|
||||||
height: 157,
|
height: 157,
|
||||||
// correctLevel : QRCode.CorrectLevel.H
|
// correctLevel : QRCode.CorrectLevel.H
|
||||||
});
|
});
|
||||||
document.getElementById('connectString').innerHTML = connectString
|
document.getElementById('connectString').innerText = connectString
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
|
|
||||||
fetchInfo()
|
fetchInfo()
|
||||||
} catch (e) { console.log({ e }) }
|
} catch (e) { console.log({ e }) }
|
||||||
|
// Continue to status
|
||||||
|
const btn = document.createElement('button')
|
||||||
|
btn.className = 'push-button'
|
||||||
|
btn.style.marginTop = '20px'
|
||||||
|
btn.innerText = 'Continue'
|
||||||
|
btn.onclick = () => { location.href = 'status.html' }
|
||||||
|
document.querySelector('.setup-content').appendChild(btn)
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,9 +13,8 @@
|
||||||
display: block;
|
display: block;
|
||||||
position: relative;
|
position: relative;
|
||||||
width: 253px;
|
width: 253px;
|
||||||
height: 241px;
|
min-height: 241px;
|
||||||
-webkit-backdrop-filter: blur(10px);
|
height: auto;
|
||||||
backdrop-filter: blur(10px);
|
|
||||||
margin-top: 10px;
|
margin-top: 10px;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
transition: background-color 0.5s;
|
transition: background-color 0.5s;
|
||||||
|
|
@ -26,6 +25,60 @@
|
||||||
transition: background-color 0.3s;
|
transition: background-color 0.3s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* prevent overlap: hide connect string until revealed; click surface on box */
|
||||||
|
.qrcode-box #connectString { display: none; margin-top: 6px; }
|
||||||
|
.qrcode-box.revealed #connectString { display: block; }
|
||||||
|
.qrcode-box.revealed #connectString {
|
||||||
|
-webkit-user-select: text !important;
|
||||||
|
-moz-user-select: text !important;
|
||||||
|
-ms-user-select: text !important;
|
||||||
|
user-select: text !important;
|
||||||
|
pointer-events: auto !important;
|
||||||
|
position: relative; /* Ensure z-index is respected */
|
||||||
|
z-index: 10; /* Bring to the front */
|
||||||
|
}
|
||||||
|
.qrcode-box { cursor: pointer; }
|
||||||
|
.qrcode-box.revealed { cursor: default; }
|
||||||
|
|
||||||
|
/* QR viewport and veil overlay */
|
||||||
|
.qrcode-viewport {
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
height: 175px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
overflow: hidden;
|
||||||
|
margin-top: 6px;
|
||||||
|
}
|
||||||
|
.qrcode-viewport #qrcode {
|
||||||
|
position: absolute;
|
||||||
|
width: 157px;
|
||||||
|
height: 157px;
|
||||||
|
}
|
||||||
|
/* Remove global QR blur after reveal */
|
||||||
|
.qrcode-box.revealed #qrcode { filter: none !important; }
|
||||||
|
|
||||||
|
.qrcode-viewport .qr-veil {
|
||||||
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
backdrop-filter: blur(7px);
|
||||||
|
-webkit-backdrop-filter: blur(7px);
|
||||||
|
background: rgba(0,0,0,0.25);
|
||||||
|
color: #c434e0;
|
||||||
|
font-size: 12px;
|
||||||
|
pointer-events: none; /* allow clicks to pass through if needed */
|
||||||
|
}
|
||||||
|
.qrcode-box.revealed .qr-veil { display: none; }
|
||||||
|
.qrcode-viewport.revealed .qr-veil { display: none; }
|
||||||
|
.qrcode-box.revealed .qrcode-viewport { backdrop-filter: none !important; -webkit-backdrop-filter: none !important; pointer-events: none; }
|
||||||
|
|
||||||
|
/* hide helper text when revealed to avoid overlap */
|
||||||
|
.qrcode-box.revealed #click-text { display: none; }
|
||||||
|
|
||||||
.qrcode-box-clicked::before {
|
.qrcode-box-clicked::before {
|
||||||
content: "";
|
content: "";
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
|
|
||||||
|
|
@ -133,6 +133,10 @@ a {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.checkbox input[type="radio"] {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
/* Create a new box */
|
/* Create a new box */
|
||||||
.checkbox label {
|
.checkbox label {
|
||||||
padding-left: 32px;
|
padding-left: 32px;
|
||||||
|
|
@ -157,6 +161,31 @@ a {
|
||||||
z-index: -1;
|
z-index: -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.checkbox input[type="radio"] + label::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: 50%;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
border: 1px solid #a3a3a3;
|
||||||
|
border-radius: 50%;
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.checkbox input[type="radio"]:checked + label::after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
left: 5px;
|
||||||
|
top: 50%;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
width: 10px;
|
||||||
|
height: 10px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background-color: #a012c7;
|
||||||
|
}
|
||||||
|
|
||||||
/* Display a checkmark when the checkbox is checked */
|
/* Display a checkmark when the checkbox is checked */
|
||||||
.checkbox input[type="checkbox"]:checked + .checkbox-shape::before {
|
.checkbox input[type="checkbox"]:checked + .checkbox-shape::before {
|
||||||
content: "✓";
|
content: "✓";
|
||||||
|
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 6.1 KiB |
|
|
@ -8,6 +8,10 @@
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<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="https://fonts.googleapis.com/css?family=Montserrat" />
|
||||||
<link rel="stylesheet" href="css/styles.css" />
|
<link rel="stylesheet" href="css/styles.css" />
|
||||||
|
<link rel="stylesheet" href="css/liquidity.css" />
|
||||||
|
<link rel="stylesheet" href="css/backup.css" />
|
||||||
|
<link rel="stylesheet" href="css/connect.css" />
|
||||||
|
<link rel="stylesheet" href="css/status.css" />
|
||||||
<!-- HTML Meta Tags -->
|
<!-- HTML Meta Tags -->
|
||||||
<title>Lightning.Pub</title>
|
<title>Lightning.Pub</title>
|
||||||
<meta name="description" content="Lightning for Everyone" />
|
<meta name="description" content="Lightning for Everyone" />
|
||||||
|
|
@ -17,45 +21,310 @@
|
||||||
<body>
|
<body>
|
||||||
<header>
|
<header>
|
||||||
<img src="img/pub_logo.png" width="38px" height="auto" alt="Lightning Pub logo" />
|
<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" />
|
<img src="img/LightningPub.png" height="26px" alt="Lightning Pub logo" />
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<main>
|
<main>
|
||||||
<section class="setup-header">
|
<section id="page-node">
|
||||||
<h2>Setup your Pub</h2>
|
<div class="setup-header">
|
||||||
<p class="header-title">
|
<h2>Setup your Pub</h2>
|
||||||
</p>
|
<p class="header-title">
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="line"></div>
|
||||||
|
|
||||||
|
<div class="setup-content">
|
||||||
|
<div class="input-group">
|
||||||
|
<span>Give this node a name that wallet users will see:</span>
|
||||||
|
<input type="text" placeholder="Nodey McNodeFace" value="" style="width: 100%" id="nodeName" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="input-group" style="margin-top: 20px">
|
||||||
|
<span>Avatar (shown in wallet):</span>
|
||||||
|
<div style="display:flex; align-items:center; gap:12px; width:100%;">
|
||||||
|
<img id="avatarPreview" src="" alt="avatar" style="width:56px;height:56px;border-radius:6px;object-fit:cover;box-shadow:0 0 2px rgba(0,0,0,1);" />
|
||||||
|
<input type="text" placeholder="" style="flex:1" id="avatarUrl" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="input-group" style="margin-top: 28px">
|
||||||
|
<span>If you want to use a specific Nostr relay, enter it now:</span>
|
||||||
|
<div style="display:flex; flex-direction: column; gap:10px; width:100%;">
|
||||||
|
<input type="text" placeholder="wss://relay.lightning.pub" style="width: 100%" id="relayUrl" />
|
||||||
|
<div class="checkbox" style="margin-top: 0">
|
||||||
|
<input type="checkbox" id="customCheckbox" />
|
||||||
|
<div class="checkbox-shape"></div>
|
||||||
|
<label for="customCheckbox">
|
||||||
|
Use the default managed relay service and auto-pay 1000 sats
|
||||||
|
per month to support developers
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<p id="errorText" style="color:red"></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button class="push-button" style="margin-top: 60px" id="liquidityBtn">
|
||||||
|
Next
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<div class="line"></div>
|
<section id="page-liquidity" style="display: none;">
|
||||||
|
<div class="setup-header">
|
||||||
<section class="setup-content">
|
<button class="icon-button back-button" id="back-to-node">
|
||||||
<div class="input-group">
|
<img src="img/back.svg" alt="" />
|
||||||
<span>Give this node a name that wallet users will see:</span>
|
</button>
|
||||||
<input type="text" placeholder="Nodey McNodeFace" value="" style="width: 100%" id="nodeName" />
|
<h2>Manage Node Liquidity</h2>
|
||||||
|
<p class="header-title">
|
||||||
|
How do you want to manage Lightning channels?
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="input-group" style="margin-top: 38px">
|
<div class="line"></div>
|
||||||
<span>If you want to use a specific Nostr relay, enter it now:</span>
|
|
||||||
<input type="text" placeholder="wss://relay.lightning.pub" style="width: 100%" id="relayUrl" />
|
<div class="setup-content">
|
||||||
|
<div class="checkbox" style="margin-top: 60px">
|
||||||
|
<input type="radio" id="automate" name="service" data-group="service" />
|
||||||
|
<label for="automate" class="automate">
|
||||||
|
Use Automation Service
|
||||||
|
<div class="question-box">
|
||||||
|
<button class="icon-button" id="show-question">
|
||||||
|
<img src="img/question.svg" />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="question-content" id="question-content">
|
||||||
|
Automation helps reduce the fees you pay by trusting peers temporarily until your node balance is sufficient
|
||||||
|
to open a balanced Lightning channel.
|
||||||
|
<button class="icon-button close-button" id="close-question">
|
||||||
|
<img src="img/close.svg" alt="" />
|
||||||
|
</button>
|
||||||
|
<a href="https://docs.shock.network/" target="_blank" class="marked question-more">Learn More</a>
|
||||||
|
</div>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="checkbox" style="margin-top: 30px">
|
||||||
|
<input type="radio" id="manual" name="service" data-group="service" />
|
||||||
|
<label for="manual">Manage my channels manually</label>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<p id="errorTextLiquidity" style="color:red"></p>
|
||||||
|
</div>
|
||||||
|
<button class="push-button" style="margin-top: 60px" id="backupBtn">
|
||||||
|
Next
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section id="page-backup" style="display: none;">
|
||||||
|
<div class="setup-header">
|
||||||
|
<button class="icon-button back-button" id="back-to-liquidity">
|
||||||
|
<img src="img/back.svg" alt="" />
|
||||||
|
</button>
|
||||||
|
<h2>Choose a Recovery Method</h2>
|
||||||
|
<p class="header-title">
|
||||||
|
<span style="font-weight: bold">New Node! 🎉</span> It's important
|
||||||
|
to backup your keys.
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="checkbox" style="margin-top: 12px">
|
<div class="line"></div>
|
||||||
<input type="checkbox" id="customCheckbox" />
|
|
||||||
<div class="checkbox-shape"></div>
|
|
||||||
<label for="customCheckbox">
|
|
||||||
Use the default managed relay service and auto-pay 1000 sats
|
|
||||||
per month to support developers
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
<div class="setup-content">
|
||||||
|
<div class="description-box">
|
||||||
|
<div class="description">
|
||||||
|
In addition to your seed phrase, you also need channel details to recover funds should your node experience a
|
||||||
|
hardware failure.
|
||||||
|
</div>
|
||||||
|
<br />
|
||||||
|
<div class="description">
|
||||||
|
It's important always to have the latest version of this file. Fortunately, it's small enough to automatically
|
||||||
|
store on the Nostr relay.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="warning-text">
|
||||||
|
If you did not choose the developers relay, be sure your relay has
|
||||||
|
adequate storage policies to hold NIP78 events.
|
||||||
|
</div>
|
||||||
|
<div class="checkbox-container">
|
||||||
|
<div class="checkbox" style="margin-top: 12px">
|
||||||
|
<input type="radio" id="backup" name="backup-option" />
|
||||||
|
<label for="backup">
|
||||||
|
Encrypted Backup to Nostr Relay
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="checkbox-container">
|
||||||
|
<div class="checkbox manual-checkbox" style="margin-top: 12px">
|
||||||
|
<input type="radio" id="manual-backup" name="backup-option" />
|
||||||
|
<label for="manual-backup">
|
||||||
|
DO NOT store on relay (Manual Backups)
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<p id="errorTextBackup" style="color:red"></p>
|
||||||
|
</div>
|
||||||
|
<button class="push-button" style="margin-top: 60px;" id="next-button">
|
||||||
|
Finish Setup
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section id="page-connect" style="display: none;">
|
||||||
|
<div class="setup-header">
|
||||||
|
<button class="icon-button back-button" id="back-to-backup">
|
||||||
|
<img src="img/back.svg" alt="" />
|
||||||
|
</button>
|
||||||
|
<h2>Connect</h2>
|
||||||
|
<p class="header-title">You can now manage your node remotely</p>
|
||||||
|
</div>
|
||||||
|
<div class="line"></div>
|
||||||
|
<div class="setup-content">
|
||||||
|
<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" aria-label="Pairing QR and string">
|
||||||
|
<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 class="qrcode-viewport">
|
||||||
|
<div id="qrcode"></div>
|
||||||
|
<div class="qr-veil"><span>Click to reveal</span></div>
|
||||||
|
</div>
|
||||||
|
<div style="color: #a3a3a3; font-size: 11px; word-break: break-all; overflow-wrap: anywhere; max-width: 220px; margin: 0 auto;">
|
||||||
|
<div id="connectString"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<button class="push-button" style="margin-top: 20px" id="to-status">OK, I've connected my wallet</button>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section id="page-status" style="display: none;">
|
||||||
|
<div class="setup-header">
|
||||||
|
<button class="icon-button back-button" id="back-to-connect">
|
||||||
|
<img src="img/back.svg" alt="" />
|
||||||
|
</button>
|
||||||
|
<h2>Node Status</h2>
|
||||||
|
<p class="header-title"></p>
|
||||||
|
</div>
|
||||||
|
<div class="line" style="width: 100%;"></div>
|
||||||
|
<section class="node-status">
|
||||||
<p id="errorText" style="color:red"></p>
|
<p id="errorText" style="color:red"></p>
|
||||||
</div>
|
<div>
|
||||||
|
<div class="status-element" style="margin-top: 15px;">
|
||||||
<button class="push-button" style="margin-top: 60px" id="liquidityBtn">
|
<div style="text-align: left;">Public Node Name:</div>
|
||||||
Next
|
<div class="fc-grey editable-content">
|
||||||
</button>
|
<div class="show-nodey" style="display: flex; flex-direction: column; display: none;">
|
||||||
|
<input type="text" value="" name="show-nodey" placeholder="" />
|
||||||
|
<div style="display: flex;justify-content: end;">
|
||||||
|
<button class="small-btn" id="cancel-show-nodey">Cancel</button>
|
||||||
|
<button class="small-btn" id="save-show-nodey">Save</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="show-nodey-text">Nodey McNodeFace</div>
|
||||||
|
<div class="question-box">
|
||||||
|
<button class="icon-button" id="show-nodey">
|
||||||
|
<img src="img/pencil.svg" style="cursor: pointer;" />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="status-element" style="margin-top: 15px;">
|
||||||
|
<div style="text-align: left;">Nostr Relay:</div>
|
||||||
|
<div class="fc-grey editable-content">
|
||||||
|
<div class="show-nostr" style="display: flex; flex-direction: column; display: none;">
|
||||||
|
<input type="text" value="" name="show-nostr" placeholder="wss://relay.lightning.pub" />
|
||||||
|
<div style="display: flex;justify-content: end;">
|
||||||
|
<button class="small-btn" id="cancel-show-nostr">Cancel</button>
|
||||||
|
<button class="small-btn" id="save-show-nostr">Save</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="show-nostr-text">wss://relay.lightning.pub</div>
|
||||||
|
<div class="question-box">
|
||||||
|
<button class="icon-button" id="show-nostr">
|
||||||
|
<img src="img/pencil.svg" style="cursor: pointer;" />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="status-element" style="margin-top: 15px;">
|
||||||
|
<div>Administrator:</div>
|
||||||
|
<div id="adminNpub" style="line-break: anywhere;">Loading...</div>
|
||||||
|
</div>
|
||||||
|
<div class="status-element" style="margin-top: 15px;">
|
||||||
|
<div style="text-align: left;">Avatar:</div>
|
||||||
|
<div class="fc-grey editable-content">
|
||||||
|
<div class="show-avatar" style="display: flex; flex-direction: column; display: none;">
|
||||||
|
<input type="text" value="" name="show-avatar" placeholder="" />
|
||||||
|
<div style="display: flex;justify-content: end;">
|
||||||
|
<button class="small-btn" id="cancel-show-avatar">Cancel</button>
|
||||||
|
<button class="small-btn" id="save-show-avatar">Save</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div style="display:flex;align-items:center;gap:12px;">
|
||||||
|
<img id="avatarImg" src="" alt="avatar" style="width:48px;height:48px;border-radius:6px;object-fit:cover;box-shadow:0 0 2px rgba(0,0,0,1);" />
|
||||||
|
<div class="question-box">
|
||||||
|
<button class="icon-button" id="show-avatar">
|
||||||
|
<img src="img/pencil.svg" style="cursor: pointer;" />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div style="display: flex; justify-content: end;padding-right: 12px;">
|
||||||
|
<div class="marked" id="show-reset" style="text-decoration: underline; margin-top: 5px;position: relative; display: none;">
|
||||||
|
Reset
|
||||||
|
<div class="watchdog-status">
|
||||||
|
<a href="https://docs.shock.network/pub/watchdog" target="_blank">
|
||||||
|
<button class="icon-button" id="show-question">
|
||||||
|
<img src="img/question.svg" />
|
||||||
|
</button>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="reset-box">
|
||||||
|
<div style="width: 100%;height: 100%;position: relative;">
|
||||||
|
<button class="icon-button close-button" id="close-reset-box">
|
||||||
|
<img src="img/close.svg" alt="">
|
||||||
|
</button>
|
||||||
|
<div class="reset-box-content" id="reset-content"></div>
|
||||||
|
<div class="continue-button-container">
|
||||||
|
<div class="continue-button" id="">Continue</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div style="margin-top: 40px;">
|
||||||
|
<div class="status-element">
|
||||||
|
<div>Relay Status:</div>
|
||||||
|
<div id="relayStatus"><span class="yellow-dot">●</span> Loading...</div>
|
||||||
|
</div>
|
||||||
|
<div class="status-element">
|
||||||
|
<div>Lightning Status:</div>
|
||||||
|
<div id="lndStatus"><span class="yellow-dot">●</span> Loading...</div>
|
||||||
|
</div>
|
||||||
|
<div class="status-element">
|
||||||
|
<div style="position: relative;">Watchdog Status:
|
||||||
|
<div class="watchdog-status">
|
||||||
|
<a href="https://docs.shock.network/pub/watchdog" target="_blank">
|
||||||
|
<button class="icon-button" id="show-question"><img src="img/question.svg" /></button>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="watchdog-status"><span class="green-dot">●</span> Loading...</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div style="margin-top: 20px;">
|
||||||
|
<div style="font-size: 13px; text-align: left;">Guest Invitation Link:</div>
|
||||||
|
<a href="#" target="_blank" style="font-size: 11px;line-break: anywhere;" id="inviteLinkHttp" class="invite-link"></a>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
</section>
|
</section>
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
|
|
@ -71,43 +340,10 @@
|
||||||
<div class="line"></div>
|
<div class="line"></div>
|
||||||
<a href="https://docs.shock.network" class="marked need-help">Need Help?</a>
|
<a href="https://docs.shock.network" class="marked need-help">Need Help?</a>
|
||||||
</footer>
|
</footer>
|
||||||
<script>
|
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
|
||||||
|
<script src="https://cdn.rawgit.com/davidshimjs/qrcodejs/gh-pages/qrcode.min.js"></script>
|
||||||
document.getElementById("liquidityBtn").onclick = (e) => {
|
<script src="js/status.js"></script>
|
||||||
const nodeName = document.getElementById("nodeName").value;
|
<script src="js/wizard.js"></script>
|
||||||
const relayUrl = document.getElementById("relayUrl").value;
|
|
||||||
const checked = document.getElementById("customCheckbox").checked;
|
|
||||||
if (!nodeName) {
|
|
||||||
document.getElementById("errorText").innerText = "Please enter a node name";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!checked && !relayUrl) {
|
|
||||||
document.getElementById("errorText").innerText = "Please enter a relay URL or check the default relay box";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
localStorage.setItem("wizard/nodeName", nodeName);
|
|
||||||
if (checked) {
|
|
||||||
localStorage.setItem("wizard/relayUrl", "wss://relay.lightning.pub");
|
|
||||||
} else {
|
|
||||||
localStorage.setItem("wizard/relayUrl", relayUrl);
|
|
||||||
}
|
|
||||||
location.href = 'liquidity.html'
|
|
||||||
}
|
|
||||||
|
|
||||||
fetch("/wizard/state").then((res) => {
|
|
||||||
if (res.status === 200) {
|
|
||||||
res.json().then((data) => {
|
|
||||||
if (data.admin_linked) {
|
|
||||||
location.href = 'status.html'
|
|
||||||
} else if (data.config_sent) {
|
|
||||||
location.href = 'connect.html'
|
|
||||||
} else {
|
|
||||||
console.log("ready to initialize")
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
|
@ -1,23 +0,0 @@
|
||||||
$(() => {
|
|
||||||
let backup; let manual_backup;
|
|
||||||
$("#backup").click(() => {
|
|
||||||
backup = $("#backup").prop("checked");
|
|
||||||
$('#manual-backup').prop("checked",false);
|
|
||||||
const nextButton = $("#next-button");
|
|
||||||
if (backup) {
|
|
||||||
nextButton.removeClass("hidden-button");
|
|
||||||
} else {
|
|
||||||
nextButton.addClass("hidden-button");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
$("#manual-backup").click(()=>{
|
|
||||||
manual_backup = $('#manual-backup').prop("checked");
|
|
||||||
$("#backup").prop("checked",false);
|
|
||||||
const nextButton = $("#next-button");
|
|
||||||
if(manual_backup) {
|
|
||||||
nextButton.removeClass("hidden-button");
|
|
||||||
} else {
|
|
||||||
nextButton.addClass("hidden-button");
|
|
||||||
};
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
@ -1,19 +0,0 @@
|
||||||
$(() => {
|
|
||||||
$("#show-question").click(() => {
|
|
||||||
$("#question-content").show();
|
|
||||||
});
|
|
||||||
|
|
||||||
$("#close-question").click(() => {
|
|
||||||
$("#question-content").hide();
|
|
||||||
});
|
|
||||||
|
|
||||||
$("#automate").click(() => {
|
|
||||||
$('[data-group="service"]').prop("checked", false);
|
|
||||||
$("#automate").prop("checked", true);
|
|
||||||
});
|
|
||||||
|
|
||||||
$("#manual").click(() => {
|
|
||||||
$('[data-group="service"]').prop("checked", false);
|
|
||||||
$("#manual").prop("checked", true);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
@ -1,4 +1,27 @@
|
||||||
$(() => {
|
$(() => {
|
||||||
|
const postConfig = async (updates) => {
|
||||||
|
try {
|
||||||
|
const stateRes = await fetch('/wizard/service_state')
|
||||||
|
if (stateRes.status !== 200) return false
|
||||||
|
const s = await stateRes.json()
|
||||||
|
const body = {
|
||||||
|
source_name: updates.source_name ?? (s.source_name || s.provider_name || ''),
|
||||||
|
relay_url: updates.relay_url ?? (s.relay_url || (s.relays && s.relays[0]) || ''),
|
||||||
|
automate_liquidity: s.automate_liquidity || false,
|
||||||
|
push_backups_to_nostr: s.push_backups_to_nostr || false,
|
||||||
|
avatar_url: s.avatar_url || ''
|
||||||
|
}
|
||||||
|
const res = await fetch('/wizard/config', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify(body)
|
||||||
|
})
|
||||||
|
if (res.status !== 200) return false
|
||||||
|
const j = await res.json().catch(() => ({}))
|
||||||
|
if (j && j.status && j.status !== 'OK') return false
|
||||||
|
return true
|
||||||
|
} catch { return false }
|
||||||
|
}
|
||||||
$("#show-reset").click(() => {
|
$("#show-reset").click(() => {
|
||||||
$("#reset-content").text('Reset the administrator account if you lost access via the Dashboard.');
|
$("#reset-content").text('Reset the administrator account if you lost access via the Dashboard.');
|
||||||
$("#reset-box").show();
|
$("#reset-box").show();
|
||||||
|
|
@ -11,6 +34,11 @@ $(() => {
|
||||||
$("#reset-box").show();
|
$("#reset-box").show();
|
||||||
$('.continue-button').attr('id', 'set-show-nostr');
|
$('.continue-button').attr('id', 'set-show-nostr');
|
||||||
});
|
});
|
||||||
|
$("#show-avatar").click(() => {
|
||||||
|
$('.show-avatar').show()
|
||||||
|
$('#show-avatar-text').hide()
|
||||||
|
$('input[name="show-avatar"]').focus();
|
||||||
|
});
|
||||||
$("#show-nodey").click(() => {
|
$("#show-nodey").click(() => {
|
||||||
$('.show-nodey').show()
|
$('.show-nodey').show()
|
||||||
$('#show-nodey-text').hide()
|
$('#show-nodey-text').hide()
|
||||||
|
|
@ -18,9 +46,13 @@ $(() => {
|
||||||
});
|
});
|
||||||
$("#save-show-nodey").click(() => {
|
$("#save-show-nodey").click(() => {
|
||||||
var targetInputVal = $('input[name="show-nodey"]').val()
|
var targetInputVal = $('input[name="show-nodey"]').val()
|
||||||
$('#show-nodey-text').text(targetInputVal)
|
postConfig({ source_name: targetInputVal }).then(ok => {
|
||||||
$('.show-nodey').hide()
|
if (ok) {
|
||||||
$('#show-nodey-text').show()
|
$('#show-nodey-text').text(targetInputVal)
|
||||||
|
}
|
||||||
|
$('.show-nodey').hide()
|
||||||
|
$('#show-nodey-text').show()
|
||||||
|
})
|
||||||
})
|
})
|
||||||
$("#cancel-show-nodey").click(() => {
|
$("#cancel-show-nodey").click(() => {
|
||||||
$('.show-nodey').hide()
|
$('.show-nodey').hide()
|
||||||
|
|
@ -38,9 +70,28 @@ $(() => {
|
||||||
});
|
});
|
||||||
$("#save-show-nostr").click(() => {
|
$("#save-show-nostr").click(() => {
|
||||||
var targetInputVal = $('input[name="show-nostr"]').val()
|
var targetInputVal = $('input[name="show-nostr"]').val()
|
||||||
$('#show-nostr-text').text(targetInputVal)
|
postConfig({ relay_url: targetInputVal }).then(ok => {
|
||||||
$('.show-nostr').hide()
|
if (ok) {
|
||||||
$('#show-nostr-text').show()
|
$('#show-nostr-text').text(targetInputVal)
|
||||||
|
}
|
||||||
|
$('.show-nostr').hide()
|
||||||
|
$('#show-nostr-text').show()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
$("#save-show-avatar").click(() => {
|
||||||
|
var targetInputVal = $('input[name="show-avatar"]').val()
|
||||||
|
postConfig({ avatar_url: targetInputVal }).then(ok => {
|
||||||
|
if (ok) {
|
||||||
|
$('#show-avatar-text').text(targetInputVal || '—')
|
||||||
|
if (targetInputVal) { $('#avatarImg').attr('src', targetInputVal) }
|
||||||
|
}
|
||||||
|
$('.show-avatar').hide()
|
||||||
|
$('#show-avatar-text').show()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
$("#cancel-show-avatar").click(() => {
|
||||||
|
$('.show-avatar').hide()
|
||||||
|
$('#show-avatar-text').show()
|
||||||
})
|
})
|
||||||
$("#cancel-show-nostr").click(() => {
|
$("#cancel-show-nostr").click(() => {
|
||||||
$('.show-nostr').hide()
|
$('.show-nostr').hide()
|
||||||
|
|
|
||||||
241
static/js/wizard.js
Normal file
241
static/js/wizard.js
Normal file
|
|
@ -0,0 +1,241 @@
|
||||||
|
$(() => {
|
||||||
|
// Page sections
|
||||||
|
const pages = {
|
||||||
|
node: $('#page-node'),
|
||||||
|
liquidity: $('#page-liquidity'),
|
||||||
|
backup: $('#page-backup'),
|
||||||
|
connect: $('#page-connect'),
|
||||||
|
status: $('#page-status')
|
||||||
|
};
|
||||||
|
|
||||||
|
// Inputs
|
||||||
|
const nodeNameInput = $("#nodeName");
|
||||||
|
const relayUrlInput = $("#relayUrl");
|
||||||
|
const avatarUrlInput = $("#avatarUrl");
|
||||||
|
const avatarPreview = $("#avatarPreview");
|
||||||
|
const customCheckbox = $("#customCheckbox");
|
||||||
|
const automateLiquidityRadio = $("#automate");
|
||||||
|
const manualLiquidityRadio = $("#manual");
|
||||||
|
const backupNostrRadio = $("#backup");
|
||||||
|
const manualBackupRadio = $("#manual-backup");
|
||||||
|
|
||||||
|
// Buttons
|
||||||
|
const toLiquidityBtn = $("#liquidityBtn");
|
||||||
|
const toBackupBtn = $("#backupBtn");
|
||||||
|
const toStatusBtn = $("#to-status");
|
||||||
|
const finishBtn = $("#next-button");
|
||||||
|
const backToNodeBtn = $("#back-to-node");
|
||||||
|
const backToLiquidityBtn = $("#back-to-liquidity");
|
||||||
|
|
||||||
|
// Error text
|
||||||
|
const errorTextNode = $("#errorText");
|
||||||
|
const errorTextLiquidity = $("#errorTextLiquidity");
|
||||||
|
const errorTextBackup = $("#errorTextBackup");
|
||||||
|
|
||||||
|
// Liquidity question mark
|
||||||
|
$("#show-question").click(() => $("#question-content").show());
|
||||||
|
$("#close-question").click(() => $("#question-content").hide());
|
||||||
|
|
||||||
|
const showPage = (pageToShow) => {
|
||||||
|
Object.values(pages).forEach(page => page.hide());
|
||||||
|
pageToShow.show();
|
||||||
|
};
|
||||||
|
|
||||||
|
const populateStatus = async () => {
|
||||||
|
try {
|
||||||
|
const res = await fetch('/wizard/service_state');
|
||||||
|
if (res.status !== 200) return;
|
||||||
|
const s = await res.json();
|
||||||
|
const name = s.source_name || s.provider_name || '';
|
||||||
|
const relay = s.relay_url || (s.relays && s.relays[0]) || '';
|
||||||
|
const admin = s.admin_npub || '';
|
||||||
|
const avatar = s.avatar_url || (s.app_id ? `https://robohash.org/${encodeURIComponent(s.app_id)}.png?size=128x128&set=set3` : '');
|
||||||
|
|
||||||
|
const lndState = s.lnd_state; // 0 OFFLINE, 1 SYNCING, 2 ONLINE (per enum)
|
||||||
|
const watchdogOk = !!s.watchdog_ok;
|
||||||
|
const relayConnected = !!s.relay_connected;
|
||||||
|
|
||||||
|
$('#show-nodey-text').text(name || '—');
|
||||||
|
$('#show-nostr-text').text(relay || '—');
|
||||||
|
$('#adminNpub').text(admin || '—');
|
||||||
|
if (avatar) { $('#avatarImg').attr('src', avatar); }
|
||||||
|
|
||||||
|
const mkDot = (ok) => ok ? '<span class="green-dot">●</span>' : '<span class="yellow-dot">●</span>';
|
||||||
|
const lndTxt = lndState === 2 ? 'Online' : (lndState === 1 ? 'Syncing' : 'Offline');
|
||||||
|
$('#lndStatus').html(`${mkDot(lndState === 2)} ${lndTxt}`);
|
||||||
|
$('#watchdog-status').html(`${mkDot(watchdogOk)} ${watchdogOk ? 'OK' : 'Alert'}`);
|
||||||
|
$('#relayStatus').html(`${mkDot(relayConnected)} ${relayConnected ? 'Connected' : 'Disconnected'}`);
|
||||||
|
} catch { /* noop */ }
|
||||||
|
};
|
||||||
|
|
||||||
|
// Navigation
|
||||||
|
toLiquidityBtn.click(() => {
|
||||||
|
const nodeName = nodeNameInput.val();
|
||||||
|
const relayUrl = relayUrlInput.val();
|
||||||
|
const useDefaultRelay = customCheckbox.prop('checked');
|
||||||
|
if (!nodeName) {
|
||||||
|
errorTextNode.text("Please enter a node name");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!useDefaultRelay && !relayUrl) {
|
||||||
|
errorTextNode.text("Please enter a relay URL or check the default relay box");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
errorTextNode.text("");
|
||||||
|
showPage(pages.liquidity);
|
||||||
|
});
|
||||||
|
|
||||||
|
toBackupBtn.click(() => {
|
||||||
|
if (!automateLiquidityRadio.prop('checked') && !manualLiquidityRadio.prop('checked')) {
|
||||||
|
errorTextLiquidity.text('Please select an option');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
errorTextLiquidity.text("");
|
||||||
|
showPage(pages.backup);
|
||||||
|
});
|
||||||
|
|
||||||
|
backToNodeBtn.click(() => showPage(pages.node));
|
||||||
|
backToLiquidityBtn.click(() => showPage(pages.liquidity));
|
||||||
|
|
||||||
|
// Final submission
|
||||||
|
finishBtn.click(async () => {
|
||||||
|
if (!backupNostrRadio.prop('checked') && !manualBackupRadio.prop('checked')) {
|
||||||
|
errorTextBackup.text('Please select an option');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
errorTextBackup.text("");
|
||||||
|
|
||||||
|
const relayUrl = customCheckbox.prop('checked') ? 'wss://relay.lightning.pub' : relayUrlInput.val();
|
||||||
|
|
||||||
|
const req = {
|
||||||
|
source_name: nodeNameInput.val(),
|
||||||
|
relay_url: relayUrl,
|
||||||
|
automate_liquidity: automateLiquidityRadio.prop('checked'),
|
||||||
|
push_backups_to_nostr: backupNostrRadio.prop('checked'),
|
||||||
|
avatar_url: avatarUrlInput.val()
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
const res = await fetch("/wizard/config", {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify(req)
|
||||||
|
});
|
||||||
|
if (!res.ok) {
|
||||||
|
const j = await res.json();
|
||||||
|
throw new Error(j.reason || "Failed to start service");
|
||||||
|
}
|
||||||
|
// Move to in-page connect step
|
||||||
|
showPage(pages.connect);
|
||||||
|
// fetch and prepare connect info
|
||||||
|
(async () => {
|
||||||
|
const res = await fetch('/wizard/admin_connect_info');
|
||||||
|
if (res.status !== 200) return;
|
||||||
|
const j = await res.json();
|
||||||
|
if (j.connect_info && j.connect_info.enrolled_npub) {
|
||||||
|
showPage(pages.status);
|
||||||
|
await populateStatus();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const connectString = j.nprofile + ':' + j.connect_info.admin_token;
|
||||||
|
const qrElement = document.getElementById('qrcode');
|
||||||
|
const codebox = $('#codebox');
|
||||||
|
const clickText = $('#click-text');
|
||||||
|
const cs = $('#connectString');
|
||||||
|
|
||||||
|
// Reset visual state
|
||||||
|
codebox.removeClass('revealed');
|
||||||
|
cs.text('');
|
||||||
|
codebox.find('.qr-veil').show();
|
||||||
|
clickText.show();
|
||||||
|
if (qrElement) {
|
||||||
|
while (qrElement.firstChild) qrElement.removeChild(qrElement.firstChild);
|
||||||
|
// Pre-generate QR behind veil to entice reveal
|
||||||
|
new QRCode(qrElement, { text: connectString, colorDark: '#000000', colorLight: '#ffffff', width: 157, height: 157 });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reveal on click: show string below and remove veil/heading
|
||||||
|
codebox.off('click').on('click', (e) => {
|
||||||
|
if (!codebox.hasClass('revealed')) {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
cs.text(connectString);
|
||||||
|
codebox.addClass('revealed');
|
||||||
|
|
||||||
|
// Remove the veil from the DOM entirely to kill the blur
|
||||||
|
codebox.find('.qr-veil').remove();
|
||||||
|
|
||||||
|
clickText.hide();
|
||||||
|
|
||||||
|
// Unbind to allow text selection and normal behavior after reveal
|
||||||
|
codebox.off('click');
|
||||||
|
|
||||||
|
// Force text to be selectable on top
|
||||||
|
cs.css({
|
||||||
|
'user-select': 'text',
|
||||||
|
'-webkit-user-select': 'text',
|
||||||
|
'pointer-events': 'auto'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})();
|
||||||
|
} catch (err) {
|
||||||
|
errorTextBackup.text(err.message);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Navigate from connect to status
|
||||||
|
toStatusBtn && toStatusBtn.click(async () => {
|
||||||
|
showPage(pages.status);
|
||||||
|
await populateStatus();
|
||||||
|
})
|
||||||
|
|
||||||
|
const syncRelayState = () => {
|
||||||
|
relayUrlInput.prop('disabled', customCheckbox.prop('checked'));
|
||||||
|
if (customCheckbox.prop('checked')) {
|
||||||
|
relayUrlInput.val('');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
customCheckbox.on('change', syncRelayState);
|
||||||
|
relayUrlInput.on('input', () => {
|
||||||
|
if (relayUrlInput.val()) {
|
||||||
|
customCheckbox.prop('checked', false);
|
||||||
|
syncRelayState();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Initial state load (no redirects; SPA only)
|
||||||
|
console.log('Wizard script version: REVEAL_FIX_3 activated');
|
||||||
|
fetch("/wizard/service_state").then(res => res.json()).then(state => {
|
||||||
|
nodeNameInput.val(state.source_name);
|
||||||
|
if (state.relay_url === 'wss://relay.lightning.pub') {
|
||||||
|
customCheckbox.prop('checked', true);
|
||||||
|
} else {
|
||||||
|
relayUrlInput.val(state.relay_url);
|
||||||
|
}
|
||||||
|
const robo = state.app_id ? `https://robohash.org/${encodeURIComponent(state.app_id)}.png?size=128x128&set=set3` : ''
|
||||||
|
if (state.avatar_url) {
|
||||||
|
avatarUrlInput.val(state.avatar_url);
|
||||||
|
avatarPreview.attr('src', state.avatar_url)
|
||||||
|
} else if (robo) {
|
||||||
|
avatarPreview.attr('src', robo)
|
||||||
|
}
|
||||||
|
if (robo) {
|
||||||
|
avatarUrlInput.attr('placeholder', robo)
|
||||||
|
}
|
||||||
|
syncRelayState();
|
||||||
|
|
||||||
|
if (state.automate_liquidity) {
|
||||||
|
automateLiquidityRadio.prop('checked', true);
|
||||||
|
} else {
|
||||||
|
manualLiquidityRadio.prop('checked', true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state.push_backups_to_nostr) {
|
||||||
|
backupNostrRadio.prop('checked', true);
|
||||||
|
} else {
|
||||||
|
manualBackupRadio.prop('checked', true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
@ -1,109 +0,0 @@
|
||||||
<!DOCTYPE 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/liquidity.css" />
|
|
||||||
<!-- HTML Meta Tags -->
|
|
||||||
<title>Lightning.Pub</title>
|
|
||||||
<meta name="description" content="Lightning for Everyone" />
|
|
||||||
<link rel="icon" type="image/png" href="img/pub_logo.png" />
|
|
||||||
<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>
|
|
||||||
<section class="setup-header">
|
|
||||||
<button class="icon-button back-button" onclick="history.back()">
|
|
||||||
<img src="img/back.svg" alt="" />
|
|
||||||
</button>
|
|
||||||
<h2>Manage Node Liquidity</h2>
|
|
||||||
<p class="header-title">
|
|
||||||
How do you want to manage Lightning channels?
|
|
||||||
</p>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<div class="line"></div>
|
|
||||||
|
|
||||||
<section class="setup-content">
|
|
||||||
<div class="checkbox" style="margin-top: 60px">
|
|
||||||
<input type="checkbox" id="automate" data-group="service" />
|
|
||||||
<div class="checkbox-shape"></div>
|
|
||||||
<label for="automate" class="automate">
|
|
||||||
Use Automation Service
|
|
||||||
<div class="question-box">
|
|
||||||
<button class="icon-button" id="show-question">
|
|
||||||
<img src="img/question.svg" />
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<div class="question-content" id="question-content">
|
|
||||||
Automation helps reduce the fees you pay by trusting peers temporarily until your node balance is sufficient
|
|
||||||
to open a balanced Lightning channel.
|
|
||||||
<button class="icon-button close-button" id="close-question">
|
|
||||||
<img src="img/close.svg" alt="" />
|
|
||||||
</button>
|
|
||||||
<a href="https://docs.shock.network/" target="_blank" class="marked question-more">Learn More</a>
|
|
||||||
</div>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
<div class="checkbox" style="margin-top: 30px">
|
|
||||||
<input type="checkbox" id="manual" data-group="service" />
|
|
||||||
<div class="checkbox-shape"></div>
|
|
||||||
<label for="manual">Manage my channels manually</label>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<p id="errorText" style="color:red"></p>
|
|
||||||
</div>
|
|
||||||
<button class="push-button" style="margin-top: 60px" id="backupBtn">
|
|
||||||
Next
|
|
||||||
</button>
|
|
||||||
</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 class="line"></div>
|
|
||||||
<a href="https://docs.shock.network" class="marked need-help">Need Help?</a>
|
|
||||||
</footer>
|
|
||||||
<script src="js/liquidity.js"></script>
|
|
||||||
<script>
|
|
||||||
document.getElementById("backupBtn").onclick = (e) => {
|
|
||||||
const automate = document.getElementById('automate').checked
|
|
||||||
const manual = document.getElementById('manual').checked
|
|
||||||
if (!automate && !manual) {
|
|
||||||
document.getElementById('errorText').innerText = 'Please select an option'
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (automate && manual) {
|
|
||||||
document.getElementById('errorText').innerText = 'Please select only one option'
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (automate) {
|
|
||||||
localStorage.setItem('wizard/liquidity', 'automate')
|
|
||||||
} else {
|
|
||||||
localStorage.setItem('wizard/liquidity', 'manual')
|
|
||||||
}
|
|
||||||
location.href = 'backup.html'
|
|
||||||
}
|
|
||||||
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
|
|
||||||
</html>
|
|
||||||
|
|
@ -19,7 +19,7 @@
|
||||||
<body>
|
<body>
|
||||||
<header>
|
<header>
|
||||||
<img src="img/pub_logo.png" width="38px" height="auto" alt="Lightning Pub logo" />
|
<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" />
|
<img src="img/LightningPub.png" height="26px" alt="Lightning Pub logo" />
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<main>
|
<main>
|
||||||
|
|
@ -69,6 +69,26 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="status-element" style="margin-top: 15px;">
|
||||||
|
<div style="text-align: left;">Avatar:</div>
|
||||||
|
<div class="fc-grey editable-content">
|
||||||
|
<div class="show-avatar" style="display: flex; flex-direction: column; display: none;">
|
||||||
|
<input type="text" value="" name="show-avatar" placeholder="" />
|
||||||
|
<div style="display: flex;justify-content: end;">
|
||||||
|
<button class="small-btn" id="cancel-show-avatar">Cancel</button>
|
||||||
|
<button class="small-btn" id="save-show-avatar">Save</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div style="display:flex;align-items:center;gap:12px;">
|
||||||
|
<img id="avatarImg" src="" alt="avatar" style="width:48px;height:48px;border-radius:6px;object-fit:cover;box-shadow:0 0 2px rgba(0,0,0,1);" />
|
||||||
|
<div class="question-box">
|
||||||
|
<button class="icon-button" id="show-avatar">
|
||||||
|
<img src="img/pencil.svg" style="cursor: pointer;" />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</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 id="adminNpub" style="line-break: anywhere;">
|
<div id="adminNpub" style="line-break: anywhere;">
|
||||||
|
|
@ -157,20 +177,29 @@
|
||||||
}
|
}
|
||||||
const j = await res.json()
|
const j = await res.json()
|
||||||
console.log(j)
|
console.log(j)
|
||||||
if (j.status !== 'OK') {
|
// Map fields from service state
|
||||||
document.getElementById('errorText').innerText = "failed to get state info" + j.reason
|
const name = j.source_name || j.provider_name || 'Unknown'
|
||||||
return
|
const relayUrl = j.relay_url || (j.relays && j.relays[0]) || ''
|
||||||
}
|
const admin = j.admin_npub || ''
|
||||||
document.getElementById("show-nodey-text").innerHTML = j.provider_name
|
// lnd_state may arrive as enum number or string; normalize to text
|
||||||
document.getElementById("show-nostr-text").innerHTML = j.relays[0]
|
const lndText = (typeof j.lnd_state === 'string')
|
||||||
document.getElementById("adminNpub").innerText = j.admin_npub
|
? j.lnd_state
|
||||||
document.getElementById("relayStatus").innerHTML = `<span class="${j.relay_connected ? 'green-dot' : 'red-dot'}">●</span> ${j.relay_connected ? 'Connected' : 'Disconnected'}`
|
: (j.lnd_state === 2 ? 'ONLINE' : (j.lnd_state === 1 ? 'SYNCING' : 'OFFLINE'))
|
||||||
document.getElementById("lndStatus").innerHTML = `<span class="${j.lnd_state === 'ONLINE' ? 'green-dot' : 'red-dot'}">●</span> ${j.lnd_state}`
|
const lndDot = (lndText === 'ONLINE') ? 'green-dot' : (lndText === 'SYNCING' ? 'yellow-dot' : 'red-dot')
|
||||||
|
// use actual relay_connected flag from backend
|
||||||
|
const relayConnected = !!j.relay_connected
|
||||||
|
const avatar = j.avatar_url || (j.app_id ? `https://robohash.org/${encodeURIComponent(j.app_id)}.png?size=128x128&set=set3` : '')
|
||||||
|
document.getElementById("show-nodey-text").innerHTML = name
|
||||||
|
document.getElementById("show-nostr-text").innerHTML = relayUrl || '—'
|
||||||
|
if (avatar) { document.getElementById("avatarImg").src = avatar }
|
||||||
|
document.getElementById("adminNpub").innerText = admin
|
||||||
|
document.getElementById("relayStatus").innerHTML = `<span class="${relayConnected ? 'green-dot' : 'red-dot'}">●</span> ${relayConnected ? 'Connected' : 'Disconnected'}`
|
||||||
|
document.getElementById("lndStatus").innerHTML = `<span class="${lndDot}">●</span> ${lndText}`
|
||||||
document.getElementById("watchdog-status").innerHTML = `<span class="${j.watchdog_ok ? 'green-dot' : 'red-dot'}">●</span> ${j.watchdog_ok ? 'No Alerts' : 'ALERT!!'}`
|
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/#/sources?addSource=${j.nprofile}`
|
document.getElementById("inviteLinkHttp").href = `https://my.shockwallet.app/#/sources?addSource=${j.nprofile}`
|
||||||
document.getElementById("inviteLinkHttp").innerHTML = `https://my.shockwallet.app/#/sources?addSource=${j.nprofile}`
|
document.getElementById("inviteLinkHttp").innerHTML = `https://my.shockwallet.app/#/sources?addSource=${j.nprofile}`
|
||||||
document.querySelector('input[name="show-nodey"]').placeholder = j.provider_name;
|
document.querySelector('input[name="show-nodey"]').placeholder = name;
|
||||||
document.title = j.provider_name;
|
document.title = name;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
fetchInfo()
|
fetchInfo()
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue