diff --git a/README.md b/README.md index ba9e02ab..8652ecb1 100644 --- a/README.md +++ b/README.md @@ -77,30 +77,30 @@ Torq supports a TOML configuration file. The docker compose install script auto You can find an example configuration file at [example-torq.conf](./docker/example-torq.conf) It is also possible not to use any TOML configuration files and use command like parameters or environment variables. The list of parameters are: - - **--lnd.url**: Host:Port of the LND node (example: "127.0.0.1:10009") - - **--lnd.macaroon-path**: Path on disk to LND Macaroon (example: "~/.lnd/admin.macaroon") - - **--lnd.tls-path**: Path on disk to LND TLS file (example: "~/.lnd/tls.cert") - - **--cln.url**: Host:Port of the CLN node (example: "127.0.0.1:17272") - - **--cln.certificate-path**: Path on disk to CLN client certificate file (example: "~/.cln/client.pem") - - **--cln.key-path**: Path on disk to CLN client key file (example: "~/.cln/client-key.pem") - - **--cln.ca-certificate-path**: Path on disk to CLN certificate authority file (example: "~/.cln/ca.pem") - - **--db.name**: Name of the database (default: "torq") - - **--db.user**: Name of the postgres user with access to the database (default: "postgres") - - **--db.password**: Password used to access the database (default: "runningtorq") - - **--db.port**: Port of the database (default: "5432") - - **--db.host**: Host of the database (default: "localhost") + - **--lnd.url**: (optional) Host:Port of the LND node (example: "127.0.0.1:10009") + - **--lnd.macaroon-path**: (optional) Path on disk to LND Macaroon (example: "~/.lnd/admin.macaroon") + - **--lnd.tls-path**: (optional) Path on disk to LND TLS file (example: "~/.lnd/tls.cert") + - **--cln.url**: (optional) Host:Port of the CLN node (example: "127.0.0.1:17272") + - **--cln.certificate-path**: (optional) Path on disk to CLN client certificate file (example: "~/.cln/client.pem") + - **--cln.key-path**: (optional) Path on disk to CLN client key file (example: "~/.cln/client-key.pem") + - **--cln.ca-certificate-path**: (optional) Path on disk to CLN certificate authority file (example: "~/.cln/ca.pem") + - **--db.name**: (optional) Name of the database (default: "torq") + - **--db.user**: (optional) Name of the postgres user with access to the database (default: "postgres") + - **--db.password**: (optional) Password used to access the database (default: "runningtorq") + - **--db.port**: (optional) Port of the database (default: "5432") + - **--db.host**: (optional) Host of the database (default: "localhost") - **--torq.password**: Password used to access the API and frontend (example: "C44y78A4JXHCVziRcFqaJfFij5HpJhF6VwKjz4vR") - - **--torq.network-interface**: The nework interface to serve the HTTP API (default: "0.0.0.0") - - **--torq.port**: Port to serve the HTTP API (default: "8080") - - **--torq.pprof.path**: When pprof path is set then pprof is loaded when Torq boots. (example: ":6060"). **See Note** - - **--torq.prometheus.path**: When prometheus path is set then prometheus is loaded when Torq boots. (example: "localhost:7070"). **See Note** - - **--torq.debuglevel**: Specify different debug levels (panic|fatal|error|warn|info|debug|trace) (default: "info") - - **--torq.vector.url**: Alternative path for alternative vector service implementation (default: "https://vector.ln.capital/") - - **--torq.cookie-path**: Path to auth cookie file - - **--torq.no-sub**: Start the server without subscribing to node data (default: "false") - - **--torq.auto-login**: Allows logging in without a password (default: "false") - - **--customize.mempool.url**: Mempool custom URL (no trailing slash) (default: "https://mempool.space") - - **--customize.fedi**: Enable Fedi mode (default: "false") + - **--torq.network-interface**: (optional) The nework interface to serve the HTTP API (default: "0.0.0.0") + - **--torq.port**: (optional) Port to serve the HTTP API (default: "8080") + - **--torq.pprof.path**: (optional) When pprof path is set then pprof is loaded when Torq boots. (example: ":6060"). **See Note** + - **--torq.prometheus.path**: (optional) When prometheus path is set then prometheus is loaded when Torq boots. (example: "localhost:7070"). **See Note** + - **--torq.debuglevel**: (optional) Specify different debug levels (panic|fatal|error|warn|info|debug|trace) (default: "info") + - **--torq.vector.url**: (optional) Alternative path for alternative vector service implementation (default: "https://vector.ln.capital/") + - **--torq.cookie-path**: (optional) Path to auth cookie file + - **--torq.no-sub**: (optional) Start the server without subscribing to node data (default: "false") + - **--torq.auto-login**: (optional) Allows logging in without a password (default: "false") + - **--customize.mempool.url**: (optional) Mempool custom URL (no trailing slash) (default: "https://mempool.space") + - **--customize.electrum.path**: (optional) Electrum path (example: "localhost:50001") - **--otel.exporter.type**: (optional) OpenTelemetry exporter type: stdout/file/jaeger (default: "stdout") - **--otel.exporter.endpoint**: (optional) OpenTelemetry exporter endpoint - **--otel.exporter.path**: (optional) OpenTelemetry exporter path (default: "traces.txt") @@ -181,11 +181,13 @@ You need to provide these certificates once Torq is running (or as boot paramete ## Compatibility -Torq `v0.22.1` <-> `v1.1.5` are all compatible with `CLN v23.05.*` +Torq `v2.0.0` and up are compatible with `CLN v24.05.*` and `LND v0.18.2+` + +Torq `v1.5.0` <-> `v1.6.1` are compatible with `CLN v23.11.*` Torq `v1.2.0` <-> `v1.4.3` are compatible with `CLN v23.08.1+` -Torq `v1.5.0` and up are compatible with `CLN v23.11.*` +Torq `v0.22.1` <-> `v1.1.5` are all compatible with `CLN v23.05.*` ## Help and feedback diff --git a/docker/example-docker-compose.yml b/docker/example-docker-compose.yml index ab055089..293d3505 100644 --- a/docker/example-docker-compose.yml +++ b/docker/example-docker-compose.yml @@ -11,6 +11,7 @@ services: - start ports: - ":" + - ":" volumes: - :/home/torq/torq.conf extra_hosts: diff --git a/docker/example-torq.conf b/docker/example-torq.conf index abb4a4b7..6d2c77ff 100644 --- a/docker/example-torq.conf +++ b/docker/example-torq.conf @@ -63,8 +63,8 @@ port = "" [customize] # Mempool custom URL (no trailing slash) #mempool.url = "https://mempool.space" -# Enable Fedi mode -#fedi = false +# Electrum path (example: localhost:50001) +#electrum.path = "localhost:50001" [otel] # Type of OpenTelemetry exporter stdout/file/jaeger diff --git a/docker/install.sh b/docker/install.sh index 53acf112..4455bb6f 100755 --- a/docker/install.sh +++ b/docker/install.sh @@ -28,7 +28,6 @@ stty echo printf "\n" # Set web UI port number - printf "\n" echo Please choose a port number for the web UI. echo NB! Umbrel users needs to use a different port than 8080. Try 8081. @@ -39,8 +38,17 @@ while [[ ! $UI_PORT =~ ^[0-9]+$ ]] || [[ $UI_PORT -lt 1 ]] || [[ $UI_PORT -gt 65 read -p "Invalid port number. Please enter a valid port number from 1 through 65535: " UI_PORT done -# Set network type +# Set gRPC port number +printf "\n" +echo Please choose a port number for the Torq gRPC. +read -p "Port number (default: 50051): " GRPC_PORT +eval GRPC_PORT="${GRPC_PORT:=50051}" +while [[ ! $GRPC_PORT =~ ^[0-9]+$ ]] || [[ $GRPC_PORT -lt 1 ]] || [[ $GRPC_PORT -gt 65535 ]]; do + read -p "Invalid port number. Please enter a valid port number from 1 through 65535: " GRPC_PORT +done + +# Set network type printf "\n" echo "Only run with host network when your server has a firewall and doesn't automatically open all port to the internet." echo "You don't want the database to be accessible from the internet!" @@ -76,9 +84,11 @@ sed -i.bak "s||$TORQ_CONFIG|g" $TORQDIR/docker-compose.yml && r if [[ "$NETWORK" == "bridge" ]]; then sed -i.bak "s//db/g" $TORQ_CONFIG && rm $TORQ_CONFIG.bak sed -i.bak "s//$UI_PORT/g" $TORQDIR/docker-compose.yml && rm $TORQDIR/docker-compose.yml.bak + sed -i.bak "s//$GRPC_PORT/g" $TORQDIR/docker-compose.yml && rm $TORQDIR/docker-compose.yml.bak fi sed -i.bak "s//$UIPASSWORD/g" $TORQ_CONFIG && rm $TORQ_CONFIG.bak sed -i.bak "s//$UI_PORT/g" $TORQ_CONFIG && rm $TORQ_CONFIG.bak +sed -i.bak "s//$GRPC_PORT/g" $TORQ_CONFIG && rm $TORQ_CONFIG.bak if [[ "$NETWORK" == "host" ]]; then sed -i.bak "s//localhost/g" $TORQ_CONFIG && rm $TORQ_CONFIG.bak fi @@ -101,6 +111,7 @@ curl --location --silent --output "${TORQDIR}/${DELETE_COMMAND}" https://raw. #start-torq setup sed -i.bak "s//$UI_PORT/g" $TORQDIR/${START_COMMAND} && rm $TORQDIR/start-torq.bak +sed -i.bak "s//$GRPC_PORT/g" $TORQDIR/${START_COMMAND} && rm $TORQDIR/start-torq.bak chmod +x $TORQDIR/$START_COMMAND chmod +x $TORQDIR/$STOP_COMMAND diff --git a/docs/grpc-api/torq.proto b/docs/grpc-api/torq.proto index 66c79f73..127004a2 100644 --- a/docs/grpc-api/torq.proto +++ b/docs/grpc-api/torq.proto @@ -8,7 +8,6 @@ package torq; option go_package = "github.com/lncapital/torq-core/torq"; - // Grpc exposed by Torq service Torq { @@ -31,11 +30,29 @@ service Torq { rpc CreateInvoice (CreateInvoiceRequest) returns (CreateInvoiceResponse) {} + rpc CreateAddress (CreateAddressRequest) returns (CreateAddressResponse) {} + + rpc TagPeer (TagPeerRequest) returns (TagPeerResponse) {} + + rpc TriggerWorkflow (WorkflowRequest) returns (WorkflowResponse) {} + + rpc GetOnChainTransactionsByAddress(GetOnChainTransactionsByAddressRequest) returns (OnChainTransactionsResponse) {} + + // Get on-chain fee estimates using mempool.space + rpc GetOnChainFeeEstimates(OnChainFeeEstimatesRequest) returns (OnChainFeeEstimatesResponse) {} + // Subscribe to single invoice to get status updates - rpc WaitInvoiceSettledByPaymentHash (WaitInvoiceSettledByPaymentHashRequest) returns (stream InvoiceStatusResponse) {} + rpc WaitInvoiceSettledByPaymentHash(WaitInvoiceSettledByPaymentHashRequest) returns (stream InvoiceStatusResponse) {} // Subscribe to all invoices to get status updates, give list of node handles to only return invoices from those nodes - rpc SubscribeInvoiceStatuses (SubscribeInvoiceStatusesRequest) returns (stream InvoiceStatusResponse) {} + rpc SubscribeInvoiceStatuses(SubscribeInvoiceStatusesRequest) returns (stream InvoiceStatusResponse) {} + + // Subscribe to single on-chain address to get transactions + // When the stream initiates it will send the latest confirmed transaction for the address if it exists + rpc WaitOnChainTransactionsByAddress(WaitOnChainTransactionsByAddressRequest) returns (stream OnChainTransaction) {} + + // Subscribe to all on-chain transactions, give list of node handles to only return transactions from those nodes + rpc SubscribeOnChainTransactions(SubscribeOnChainTransactionsRequest) returns (stream OnChainTransaction) {} } @@ -95,6 +112,30 @@ enum InvoiceStatus { InvoiceAccepted = 3; } +enum AddressType { + BECH32 = 0; + P2TR = 1; +} + +enum ChainalysisStatus { + ChainalysisPending = 0; + ChainalysisDisabled = 1; + ChainalysisVerified = 2; + ChainalysisSuspicious = 3; + ChainalysisFraud = 4; +} + +// FeeStatus is the status of the fee for the OnChain transaction +enum FeeStatus { + // Fee is equal or higher than the mempool "high fee" estimate + CorrectFee = 0; + // Fee is equal or higher than the mempool "low fee"/"three blocks" estimate + LowFee = 1; + // Fee is lower than the mempool "low fee" estimate + InsufficientFee = 2; +} + + message GetActiveNodesRequest { // Optional parameter to get only nodes of a specific network optional Network network = 1; @@ -169,8 +210,8 @@ message OpenChannelRequest { string public_key = 3; // Host of the node to open channel with in format of ip:port optional string host = 4; - int64 local_funding_amount = 5; - optional int64 push_amount = 6; + int64 local_funding_amount_sat = 5; + optional int64 push_amount_sat = 6; optional int32 target_conf = 7; optional bool private = 8; optional uint64 min_htlc_msat = 9; @@ -250,6 +291,59 @@ message CreateInvoiceResponse { string payment_address = 4; } +message CreateAddressRequest { + string node_handle = 1; + optional AddressType address_type = 2; +} + +message CreateAddressResponse { + string address = 1; +} + +message TagPeerRequest { + string node_handle = 1; + string tag_name = 2; // case insensitive + string peer_public_key = 3; +} + +message TagPeerResponse { + bool success = 1; +} + +message WorkflowRequest { + string alias = 1; + repeated WorkflowVariable variables = 2; +} + +message WorkflowResponse { + bool success = 1; +} + +message WorkflowVariable { + string name = 1; + optional string text = 2; + optional float number = 3; + optional google.protobuf.Timestamp date = 4; +} + +message GetOnChainTransactionsByAddressRequest { + string address = 1; +} + +message OnChainFeeEstimatesRequest { +} + +message OnChainFeeEstimatesResponse { + // Fee rate that has the highest probability to get into next block (sat/vbyte) + int32 next_block_plus_standard_deviation_fee_rate = 1; + // Fee rate which should be enough for next block (sat/vbyte) + int32 next_block_fee_rate = 2; + // Fee rate which should get in a block in half an hour (sat/vbyte) + int32 three_blocks_fee_rate = 3; + // Fee rate which should get in a block in an hour (sat/vbyte) + int32 six_blocks_fee_rate = 4; +} + message WaitInvoiceSettledByPaymentHashRequest { bytes payment_hash = 1; optional int32 time_out_secs = 2; @@ -269,3 +363,34 @@ message SubscribeInvoiceStatusesRequest { repeated string node_handles = 1; optional google.protobuf.Timestamp start_time = 2; } + +message WaitOnChainTransactionsByAddressRequest { + string address = 1; + optional int32 time_out_secs = 2; + // The transaction will be sent over the stream repeatedly at every confirmation until the amount of confirmations is reached + optional uint32 confirmations = 3; +} + +message SubscribeOnChainTransactionsRequest { + repeated string node_handles = 1; + optional google.protobuf.Timestamp start_time = 2; + // The transaction will be sent over the stream repeatedly at every confirmation until the amount of confirmations is reached + optional uint32 confirmations = 3; +} + +message OnChainTransactionsResponse { + repeated OnChainTransaction transactions = 1; +} + +message OnChainTransaction { + string transaction_hash = 1; + string destination_address = 2; + int64 amount_sat = 3; + int64 total_fees_sat = 4; + optional uint32 block_height = 5; + uint32 current_block_height = 6; + optional google.protobuf.Timestamp settle_date = 7; + string node_handle = 8; + ChainalysisStatus chainalysis_status = 9; + optional FeeStatus fee_status = 10; +}