Skip to content
This repository has been archived by the owner on Sep 2, 2024. It is now read-only.

Commit

Permalink
Merge branch 'master' into feat/breez-redeem-onchain-funds
Browse files Browse the repository at this point in the history
# Conflicts:
#	ldk.go
#	models/api/api.go
  • Loading branch information
rdmitr committed Mar 18, 2024
2 parents 714f417 + 75b007b commit b0e292b
Show file tree
Hide file tree
Showing 28 changed files with 483 additions and 130 deletions.
14 changes: 12 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

This is a self-sovereign, self-custodial, single-user rewrite of NWC currently in an experimental phase development. **❗This version is not backwards compatible with NWC - it requires a fresh database and connections to be re-added**

This application allows you to control your Lightning node or wallet over Nostr.
Connect applications like [Damus](https://damus.io/) or [Amethyst](https://linktr.ee/amethyst.social) to your node. There are many more apps available on https://nwc.dev/.
This application allows you to control your Lightning node or wallet from any other application that supports [NWC](https://nwc.dev/).
Connect apps like [Damus](https://damus.io/) or [Amethyst](https://linktr.ee/amethyst.social) to your node. There are many more available on https://nwc.dev/.

**Specification**: [NIP-47](https://github.com/nostr-protocol/nips/blob/master/47.md)

Expand Down Expand Up @@ -248,6 +248,16 @@ Run NWC on your own node!

- run `fly deploy`

#### View logs

Main application logs

- `fly logs`

LDK logs:

- `fly machine exec "tail -100 data/ldk/logs/ldk_node_latest.log"`

### Custom Ubuntu VM

- install go (using snap)
Expand Down
7 changes: 7 additions & 0 deletions api.go
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,13 @@ func (api *API) OpenChannel(openChannelRequest *models.OpenChannelRequest) (*mod
return api.svc.lnClient.OpenChannel(api.svc.ctx, openChannelRequest)
}

func (api *API) CloseChannel(closeChannelRequest *models.CloseChannelRequest) (*models.CloseChannelResponse, error) {
if api.svc.lnClient == nil {
return nil, errors.New("LNClient not started")
}
return api.svc.lnClient.CloseChannel(api.svc.ctx, closeChannelRequest)
}

func (api *API) GetNewOnchainAddress() (*models.NewOnchainAddressResponse, error) {
if api.svc.lnClient == nil {
return nil, errors.New("LNClient not started")
Expand Down
8 changes: 4 additions & 4 deletions breez.go
Original file line number Diff line number Diff line change
Expand Up @@ -197,10 +197,6 @@ func (bs *BreezService) LookupInvoice(ctx context.Context, paymentHash string) (
func (bs *BreezService) ListTransactions(ctx context.Context, from, until, limit, offset uint64, unpaid bool, invoiceType string) (transactions []Nip47Transaction, err error) {

request := breez_sdk.ListPaymentsRequest{}
if limit == 0 {
// make sure a sensible limit is passed
limit = 100
}
if limit > 0 {
limit32 := uint32(limit)
request.Limit = &limit32
Expand Down Expand Up @@ -265,6 +261,10 @@ func (bs *BreezService) OpenChannel(ctx context.Context, openChannelRequest *lnc
return nil, nil
}

func (bs *BreezService) CloseChannel(ctx context.Context, closeChannelRequest *lnclient.CloseChannelRequest) (*lnclient.CloseChannelResponse, error) {
return nil, nil
}

func breezPaymentToTransaction(payment *breez_sdk.Payment) (*Nip47Transaction, error) {
var lnDetails breez_sdk.PaymentDetailsLn
if payment.Details != nil {
Expand Down
23 changes: 13 additions & 10 deletions config.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,19 @@ const (
)

type AppConfig struct {
Relay string `envconfig:"RELAY" default:"wss://relay.getalby.com/v1"`
LNBackendType string `envconfig:"LN_BACKEND_TYPE"`
LNDAddress string `envconfig:"LND_ADDRESS"`
LNDCertFile string `envconfig:"LND_CERT_FILE"`
LNDMacaroonFile string `envconfig:"LND_MACAROON_FILE"`
Workdir string `envconfig:"WORK_DIR" default:".data"`
Port string `envconfig:"PORT" default:"8080"`
DatabaseUri string `envconfig:"DATABASE_URI" default:".data/nwc.db"`
CookieSecret string `envconfig:"COOKIE_SECRET"`
LogLevel string `envconfig:"LOG_LEVEL"`
Relay string `envconfig:"RELAY" default:"wss://relay.getalby.com/v1"`
LNBackendType string `envconfig:"LN_BACKEND_TYPE"`
LNDAddress string `envconfig:"LND_ADDRESS"`
LNDCertFile string `envconfig:"LND_CERT_FILE"`
LNDMacaroonFile string `envconfig:"LND_MACAROON_FILE"`
Workdir string `envconfig:"WORK_DIR" default:".data"`
Port string `envconfig:"PORT" default:"8080"`
DatabaseUri string `envconfig:"DATABASE_URI" default:".data/nwc.db"`
CookieSecret string `envconfig:"COOKIE_SECRET"`
LogLevel string `envconfig:"LOG_LEVEL"`
LDKNetwork string `envconfig:"LDK_NETWORK" default:"bitcoin"`
LDKEsploraServer string `envconfig:"LDK_ESPLORA_SERVER" default:"https://blockstream.info/api"`
LDKGossipSource string `envconfig:"LDK_GOSSIP_SOURCE" default:"https://rapidsync.lightningdevkit.org/snapshot"`
LDKLogLevel string `envconfig:"LDK_LOG_LEVEL"`
}

Expand Down
83 changes: 81 additions & 2 deletions frontend/src/screens/channels/Channels.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,16 @@ import { Link, useNavigate } from "react-router-dom";
import { useChannels } from "src/hooks/useChannels";
import { useInfo } from "src/hooks/useInfo";
import { useOnchainBalance } from "src/hooks/useOnchainBalance";
import { Node } from "src/types";
import { CloseChannelRequest, CloseChannelResponse, Node } from "src/types";
import { request } from "src/utils/request";
import { useCSRF } from "../../hooks/useCSRF.ts";

export default function Channels() {
const { data: channels } = useChannels();
const { data: channels, mutate: reloadChannels } = useChannels();
const { data: onchainBalance } = useOnchainBalance();
const [nodes, setNodes] = React.useState<Node[]>([]);
const { data: info } = useInfo();
const { data: csrf } = useCSRF();
const navigate = useNavigate();

React.useEffect(() => {
Expand Down Expand Up @@ -48,6 +50,66 @@ export default function Channels() {
?.map((channel) => channel.localBalance)
.reduce((a, b) => a + b, 0);

async function closeChannel(
channelId: string,
nodeId: string,
isActive: boolean
) {
try {
if (!csrf) {
throw new Error("csrf not loaded");
}
if (!isActive) {
if (
!confirm(
`This channel is inactive. Some channels require up to 6 onchain confirmations before they are usable. If you really want to continue, click OK.`
)
) {
return;
}
}
if (
!confirm(
`Are you sure you want to close the channel with ${
nodes.find((node) => node.public_key === nodeId)?.alias ||
"Unknown Node"
}?\n\nNode ID: ${nodeId}\n\nChannel ID: ${channelId}`
)
) {
return;
}

console.log(`🎬 Closing channel with ${nodeId}`);

const closeChannelRequest: CloseChannelRequest = {
channelId: channelId,
nodeId: nodeId,
};
const closeChannelResponse = await request<CloseChannelResponse>(
"/api/channels/close",
{
method: "POST",
headers: {
"X-CSRF-Token": csrf,
"Content-Type": "application/json",
},
body: JSON.stringify(closeChannelRequest),
}
);

if (!closeChannelResponse) {
throw new Error("Error closing channel");
}

await reloadChannels();

alert(`🎉 Channel closed`);
} catch (error) {
console.error(error);
alert("Something went wrong: " + error);
}
}

return (
<div>
<div className="grid gap-6 mb-8 md:grid-cols-3 xl:grid-cols-3">
Expand Down Expand Up @@ -171,6 +233,7 @@ export default function Channels() {
>
Local / Remote
</th>
<th></th>
</tr>
</thead>
<tbody className="bg-white divide-y divide-gray-200 dark:bg-gray-800 dark:divide-gray-700">
Expand Down Expand Up @@ -224,6 +287,9 @@ export default function Channels() {
{alias} ({channel.remotePubkey.substring(0, 10)}
...)
</a>
<span className="mx-4 uppercase text-xs border-2 py-0.5 px-1 rounded-lg">
{channel.public ? "Public" : "Private"}
</span>
</td>
<td className="py-4 px-6 text-sm font-medium text-gray-500 whitespace-nowrap dark:text-white">
{formatAmount(capacity)}
Expand All @@ -249,6 +315,19 @@ export default function Channels() {
></div>
</div>
</td>
<td>
<button
onClick={() =>
closeChannel(
channel.id,
channel.remotePubkey,
channel.active
)
}
>
</button>
</td>
</tr>
);
})}
Expand Down
10 changes: 9 additions & 1 deletion frontend/src/screens/channels/NewCustomChannel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export default function NewCustomChannel() {
const [loading, setLoading] = React.useState(false);
const [localAmount, setLocalAmount] = React.useState("");
const [nodeDetails, setNodeDetails] = React.useState<Node | undefined>();
const [isPublic, setPublic] = React.useState(true);
const [isPublic, setPublic] = React.useState(false);

const [searchParams] = useSearchParams();
const [pubkey, setPubkey] = React.useState(searchParams.get("pubkey") || "");
Expand Down Expand Up @@ -72,6 +72,14 @@ export default function NewCustomChannel() {
if (!csrf) {
throw new Error("csrf not loaded");
}
if (
isPublic &&
!confirm(
`Are you sure you want to open a public channel? in most cases a private channel is recommended.`
)
) {
return;
}
if (
!confirm(
`Are you sure you want to peer with ${nodeDetails?.alias || pubkey}?`
Expand Down
8 changes: 8 additions & 0 deletions frontend/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ export type Channel = {
remotePubkey: string;
id: string;
active: boolean;
public: boolean;
};

export type NodeConnectionInfo = {
Expand All @@ -118,6 +119,13 @@ export type OpenChannelResponse = {
fundingTxId: string;
};

export type CloseChannelRequest = {
channelId: string;
nodeId: string;
};

export type CloseChannelResponse = {};

export type GetOnchainAddressResponse = {
address: string;
};
Expand Down
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ toolchain go1.21.1
require (
github.com/breez/breez-sdk-go v0.3.4
github.com/davrux/echo-logrus/v4 v4.0.3
github.com/getAlby/glalby v0.1.0
github.com/getAlby/ldk-node-go v0.0.0-20240229204502-d0a06786e8c2
github.com/getAlby/glalby-go v0.0.0-20240307093106-aab6d05591b4
github.com/getAlby/ldk-node-go v0.0.0-20240307093012-74bfe9fd6146
github.com/go-gormigrate/gormigrate/v2 v2.1.1
github.com/gorilla/sessions v1.2.1
github.com/labstack/echo-contrib v0.14.1
Expand Down
8 changes: 4 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -227,10 +227,10 @@ github.com/frankban/quicktest v1.13.0/go.mod h1:qLE0fzW0VuyUAJgPU19zByoIr0HtCHN/
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/getAlby/glalby v0.1.0 h1:vJkGYM4I6eajWEGisXMqH6puc8QzV6/quCDDEQHQqj0=
github.com/getAlby/glalby v0.1.0/go.mod h1:JiWFguAzff5K771myoDISYOjRB6uRoA+DI0+pJkksno=
github.com/getAlby/ldk-node-go v0.0.0-20240229204502-d0a06786e8c2 h1:c7BoCz8vKkEtjPc8p3OcKsJYIamHJIsVYa0ts3uPBW4=
github.com/getAlby/ldk-node-go v0.0.0-20240229204502-d0a06786e8c2/go.mod h1:8BRjtKcz8E0RyYTPEbMS8VIdgredcGSLne8vHDtcRLg=
github.com/getAlby/glalby-go v0.0.0-20240307093106-aab6d05591b4 h1:Kzx3NNzSGtMwo9+YdvzG6ISwFq7TmqGBhz3pXnBZ4X0=
github.com/getAlby/glalby-go v0.0.0-20240307093106-aab6d05591b4/go.mod h1:ViyJvjlvv0GCesTJ7mb3fBo4G+/qsujDAFN90xZ7a9U=
github.com/getAlby/ldk-node-go v0.0.0-20240307093012-74bfe9fd6146 h1:t+hp3xxy7BzQF0Guvu6L9AsHLa509MHXsjt/PhK+684=
github.com/getAlby/ldk-node-go v0.0.0-20240307093012-74bfe9fd6146/go.mod h1:8BRjtKcz8E0RyYTPEbMS8VIdgredcGSLne8vHDtcRLg=
github.com/getsentry/raven-go v0.2.0 h1:no+xWJRb5ZI7eE8TWgIq1jLulQiIoLG0IfYxv5JYMGs=
github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
Expand Down
7 changes: 6 additions & 1 deletion greenlight.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import (

//"github.com/getAlby/nostr-wallet-connect/glalby" // for local development only

"github.com/getAlby/glalby/glalby"
"github.com/getAlby/glalby-go/glalby"
decodepay "github.com/nbd-wtf/ln-decodepay"
"github.com/sirupsen/logrus"

Expand Down Expand Up @@ -380,6 +380,7 @@ func (gs *GreenlightService) ListChannels(ctx context.Context) ([]lnclient.Chann
RemotePubkey: glChannel.PeerId,
Id: *glChannel.ChannelId,
Active: glChannel.State == 2,
// TODO: add Public property
})
}

Expand Down Expand Up @@ -438,6 +439,10 @@ func (gs *GreenlightService) OpenChannel(ctx context.Context, openChannelRequest
}, nil
}

func (gs *GreenlightService) CloseChannel(ctx context.Context, closeChannelRequest *lnclient.CloseChannelRequest) (*lnclient.CloseChannelResponse, error) {
return nil, nil
}

func (gs *GreenlightService) GetNewOnchainAddress(ctx context.Context) (string, error) {

newAddressResponse, err := gs.client.NewAddress(glalby.NewAddressRequest{})
Expand Down
3 changes: 1 addition & 2 deletions handle_balance_request.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package main

import (
"context"
"fmt"

"github.com/sirupsen/logrus"
)
Expand Down Expand Up @@ -44,7 +43,7 @@ func (svc *Service) HandleGetBalanceEvent(ctx context.Context, request *Nip47Req
ResultType: request.Method,
Error: &Nip47Error{
Code: NIP_47_ERROR_INTERNAL,
Message: fmt.Sprintf("Something went wrong while fetching balance: %s", err.Error()),
Message: err.Error(),
},
}, nil
}
Expand Down
3 changes: 1 addition & 2 deletions handle_info_request.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package main

import (
"context"
"fmt"

"github.com/sirupsen/logrus"
)
Expand Down Expand Up @@ -40,7 +39,7 @@ func (svc *Service) HandleGetInfoEvent(ctx context.Context, request *Nip47Reques
ResultType: request.Method,
Error: &Nip47Error{
Code: NIP_47_ERROR_INTERNAL,
Message: fmt.Sprintf("Something went wrong while fetching node info: %s", err.Error()),
Message: err.Error(),
},
}, nil
}
Expand Down
11 changes: 8 additions & 3 deletions handle_list_transactions_request.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package main
import (
"context"
"encoding/json"
"fmt"

"github.com/sirupsen/logrus"
)
Expand Down Expand Up @@ -43,7 +42,13 @@ func (svc *Service) HandleListTransactionsEvent(ctx context.Context, request *Ni
"appId": app.ID,
}).Info("Fetching transactions")

transactions, err := svc.lnClient.ListTransactions(ctx, listParams.From, listParams.Until, listParams.Limit, listParams.Offset, listParams.Unpaid, listParams.Type)
limit := listParams.Limit
maxLimit := uint64(50)
if limit == 0 || limit > maxLimit {
// make sure a sensible limit is passed
limit = maxLimit
}
transactions, err := svc.lnClient.ListTransactions(ctx, listParams.From, listParams.Until, limit, listParams.Offset, listParams.Unpaid, listParams.Type)
if err != nil {
svc.Logger.WithFields(logrus.Fields{
// TODO: log request fields from listParams
Expand All @@ -54,7 +59,7 @@ func (svc *Service) HandleListTransactionsEvent(ctx context.Context, request *Ni
ResultType: request.Method,
Error: &Nip47Error{
Code: NIP_47_ERROR_INTERNAL,
Message: fmt.Sprintf("Something went wrong while fetching transactions: %s", err.Error()),
Message: err.Error(),
},
}, nil
}
Expand Down
2 changes: 1 addition & 1 deletion handle_lookup_invoice_request.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ func (svc *Service) HandleLookupInvoiceEvent(ctx context.Context, request *Nip47
ResultType: request.Method,
Error: &Nip47Error{
Code: NIP_47_ERROR_INTERNAL,
Message: fmt.Sprintf("Something went wrong while looking up invoice: %s", err.Error()),
Message: err.Error(),
},
}, nil
}
Expand Down
Loading

0 comments on commit b0e292b

Please sign in to comment.