lnrpc+lncli: adds required reserve rpc & cli

This commit is contained in:
priyanshiiit 2022-06-20 18:43:29 +05:30
parent 8578433b3d
commit 3befeadaf3
11 changed files with 992 additions and 558 deletions

View File

@ -66,6 +66,7 @@ func walletCommands() []cli.Command {
listLeasesCommand,
psbtCommand,
accountsCommand,
requiredReserveCommand,
},
},
}
@ -1083,6 +1084,53 @@ func listAccounts(ctx *cli.Context) error {
return nil
}
var requiredReserveCommand = cli.Command{
Name: "requiredreserve",
Usage: "Returns the wallet reserve.",
Description: `
Returns the minimum amount of satoshis that should be kept in the
wallet in order to fee bump anchor channels if necessary. The value
scales with the number of public anchor channels but is capped at
a maximum.
Use the flag --additional_channels to get the reserve value based
on the additional channels you would like to open.
`,
Flags: []cli.Flag{
cli.Uint64Flag{
Name: "additional_channels",
Usage: "(optional) specify the additional public channels " +
"that you would like to open",
},
},
Action: actionDecorator(requiredReserve),
}
func requiredReserve(ctx *cli.Context) error {
ctxc := getContext()
// Display the command's help message if we do not have the expected
// number of arguments/flags.
if ctx.NArg() > 0 || ctx.NumFlags() > 1 {
return cli.ShowCommandHelp(ctx, "requiredreserve")
}
walletClient, cleanUp := getWalletClient(ctx)
defer cleanUp()
req := &walletrpc.RequiredReserveRequest{
AdditionalPublicChannels: uint32(ctx.Uint64("additional_channels")),
}
resp, err := walletClient.RequiredReserve(ctxc, req)
if err != nil {
return err
}
printRespJSON(resp)
return nil
}
var importAccountCommand = cli.Command{
Name: "import",
Usage: "Import an on-chain account into the wallet through its " +

View File

@ -67,4 +67,8 @@ type Config struct {
// ChainParams are the parameters of the wallet's backing chain.
ChainParams *chaincfg.Params
// CurrentNumAnchorChans returns the current number of non-private
// anchor channels the wallet should be ready to fee bump if needed.
CurrentNumAnchorChans func() (int, error)
}

File diff suppressed because it is too large Load Diff

View File

@ -290,6 +290,42 @@ func local_request_WalletKit_ListAccounts_0(ctx context.Context, marshaler runti
}
var (
filter_WalletKit_RequiredReserve_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)}
)
func request_WalletKit_RequiredReserve_0(ctx context.Context, marshaler runtime.Marshaler, client WalletKitClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq RequiredReserveRequest
var metadata runtime.ServerMetadata
if err := req.ParseForm(); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_WalletKit_RequiredReserve_0); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
msg, err := client.RequiredReserve(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return msg, metadata, err
}
func local_request_WalletKit_RequiredReserve_0(ctx context.Context, marshaler runtime.Marshaler, server WalletKitServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq RequiredReserveRequest
var metadata runtime.ServerMetadata
if err := req.ParseForm(); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_WalletKit_RequiredReserve_0); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
msg, err := server.RequiredReserve(ctx, &protoReq)
return msg, metadata, err
}
func request_WalletKit_ImportAccount_0(ctx context.Context, marshaler runtime.Marshaler, client WalletKitClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq ImportAccountRequest
var metadata runtime.ServerMetadata
@ -892,6 +928,29 @@ func RegisterWalletKitHandlerServer(ctx context.Context, mux *runtime.ServeMux,
})
mux.Handle("GET", pattern_WalletKit_RequiredReserve_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
var stream runtime.ServerTransportStream
ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/walletrpc.WalletKit/RequiredReserve", runtime.WithHTTPPathPattern("/v2/wallet/reserve"))
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := local_request_WalletKit_RequiredReserve_0(rctx, inboundMarshaler, server, req, pathParams)
md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_WalletKit_RequiredReserve_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle("POST", pattern_WalletKit_ImportAccount_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
@ -1369,6 +1428,26 @@ func RegisterWalletKitHandlerClient(ctx context.Context, mux *runtime.ServeMux,
})
mux.Handle("GET", pattern_WalletKit_RequiredReserve_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateContext(ctx, mux, req, "/walletrpc.WalletKit/RequiredReserve", runtime.WithHTTPPathPattern("/v2/wallet/reserve"))
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := request_WalletKit_RequiredReserve_0(rctx, inboundMarshaler, client, req, pathParams)
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_WalletKit_RequiredReserve_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle("POST", pattern_WalletKit_ImportAccount_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
@ -1629,6 +1708,8 @@ var (
pattern_WalletKit_ListAccounts_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v2", "wallet", "accounts"}, ""))
pattern_WalletKit_RequiredReserve_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v2", "wallet", "reserve"}, ""))
pattern_WalletKit_ImportAccount_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"v2", "wallet", "accounts", "import"}, ""))
pattern_WalletKit_ImportPublicKey_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"v2", "wallet", "key", "import"}, ""))
@ -1671,6 +1752,8 @@ var (
forward_WalletKit_ListAccounts_0 = runtime.ForwardResponseMessage
forward_WalletKit_RequiredReserve_0 = runtime.ForwardResponseMessage
forward_WalletKit_ImportAccount_0 = runtime.ForwardResponseMessage
forward_WalletKit_ImportPublicKey_0 = runtime.ForwardResponseMessage

View File

@ -224,6 +224,31 @@ func RegisterWalletKitJSONCallbacks(registry map[string]func(ctx context.Context
callback(string(respBytes), nil)
}
registry["walletrpc.WalletKit.RequiredReserve"] = func(ctx context.Context,
conn *grpc.ClientConn, reqJSON string, callback func(string, error)) {
req := &RequiredReserveRequest{}
err := marshaler.Unmarshal([]byte(reqJSON), req)
if err != nil {
callback("", err)
return
}
client := NewWalletKitClient(conn)
resp, err := client.RequiredReserve(ctx, req)
if err != nil {
callback("", err)
return
}
respBytes, err := marshaler.Marshal(resp)
if err != nil {
callback("", err)
return
}
callback(string(respBytes), nil)
}
registry["walletrpc.WalletKit.ImportAccount"] = func(ctx context.Context,
conn *grpc.ClientConn, reqJSON string, callback func(string, error)) {

View File

@ -64,6 +64,14 @@ service WalletKit {
*/
rpc ListAccounts (ListAccountsRequest) returns (ListAccountsResponse);
/*
RequiredReserve returns the minimum amount of satoshis that should be kept
in the wallet in order to fee bump anchor channels if necessary. The value
scales with the number of public anchor channels but is capped at a maximum.
*/
rpc RequiredReserve (RequiredReserveRequest)
returns (RequiredReserveResponse);
/*
ImportAccount imports an account backed by an account extended public key.
The master key fingerprint denotes the fingerprint of the root key
@ -400,6 +408,16 @@ message ListAccountsResponse {
repeated Account accounts = 1;
}
message RequiredReserveRequest {
// The number of additional channels the user would like to open.
uint32 additional_public_channels = 1;
}
message RequiredReserveResponse {
// The amount of reserve required.
int64 required_reserve = 1;
}
message ImportAccountRequest {
// A name to identify the account with.
string name = 1;

View File

@ -399,6 +399,39 @@
]
}
},
"/v2/wallet/reserve": {
"get": {
"summary": "RequiredReserve returns the minimum amount of satoshis that should be kept\nin the wallet in order to fee bump anchor channels if necessary. The value\nscales with the number of public anchor channels but is capped at a maximum.",
"operationId": "WalletKit_RequiredReserve",
"responses": {
"200": {
"description": "A successful response.",
"schema": {
"$ref": "#/definitions/walletrpcRequiredReserveResponse"
}
},
"default": {
"description": "An unexpected error response.",
"schema": {
"$ref": "#/definitions/rpcStatus"
}
}
},
"parameters": [
{
"name": "additional_public_channels",
"description": "The number of additional channels the user would like to open.",
"in": "query",
"required": false,
"type": "integer",
"format": "int64"
}
],
"tags": [
"WalletKit"
]
}
},
"/v2/wallet/send": {
"post": {
"summary": "SendOutputs is similar to the existing sendmany call in Bitcoind, and\nallows the caller to create a transaction that sends to several outputs at\nonce. This is ideal when wanting to batch create a set of transactions.",
@ -1467,6 +1500,16 @@
"walletrpcReleaseOutputResponse": {
"type": "object"
},
"walletrpcRequiredReserveResponse": {
"type": "object",
"properties": {
"required_reserve": {
"type": "string",
"format": "int64",
"description": "The amount of reserve required."
}
}
},
"walletrpcSendOutputsRequest": {
"type": "object",
"properties": {

View File

@ -55,6 +55,8 @@ http:
body: "*"
- selector: walletrpc.WalletKit.ListAccounts
get: "/v2/wallet/accounts"
- selector: walletrpc.WalletKit.RequiredReserve
get: "/v2/wallet/reserve"
- selector: walletrpc.WalletKit.ImportAccount
post: "/v2/wallet/accounts/import"
body: "*"

View File

@ -58,6 +58,11 @@ type WalletKitClient interface {
//wallet accounts and return only those matching.
ListAccounts(ctx context.Context, in *ListAccountsRequest, opts ...grpc.CallOption) (*ListAccountsResponse, error)
//
//RequiredReserve returns the minimum amount of satoshis that should be kept
//in the wallet in order to fee bump anchor channels if necessary. The value
//scales with the number of public anchor channels but is capped at a maximum.
RequiredReserve(ctx context.Context, in *RequiredReserveRequest, opts ...grpc.CallOption) (*RequiredReserveResponse, error)
//
//ImportAccount imports an account backed by an account extended public key.
//The master key fingerprint denotes the fingerprint of the root key
//corresponding to the account public key (also known as the key with
@ -281,6 +286,15 @@ func (c *walletKitClient) ListAccounts(ctx context.Context, in *ListAccountsRequ
return out, nil
}
func (c *walletKitClient) RequiredReserve(ctx context.Context, in *RequiredReserveRequest, opts ...grpc.CallOption) (*RequiredReserveResponse, error) {
out := new(RequiredReserveResponse)
err := c.cc.Invoke(ctx, "/walletrpc.WalletKit/RequiredReserve", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *walletKitClient) ImportAccount(ctx context.Context, in *ImportAccountRequest, opts ...grpc.CallOption) (*ImportAccountResponse, error) {
out := new(ImportAccountResponse)
err := c.cc.Invoke(ctx, "/walletrpc.WalletKit/ImportAccount", in, out, opts...)
@ -432,6 +446,11 @@ type WalletKitServer interface {
//wallet accounts and return only those matching.
ListAccounts(context.Context, *ListAccountsRequest) (*ListAccountsResponse, error)
//
//RequiredReserve returns the minimum amount of satoshis that should be kept
//in the wallet in order to fee bump anchor channels if necessary. The value
//scales with the number of public anchor channels but is capped at a maximum.
RequiredReserve(context.Context, *RequiredReserveRequest) (*RequiredReserveResponse, error)
//
//ImportAccount imports an account backed by an account extended public key.
//The master key fingerprint denotes the fingerprint of the root key
//corresponding to the account public key (also known as the key with
@ -604,6 +623,9 @@ func (UnimplementedWalletKitServer) NextAddr(context.Context, *AddrRequest) (*Ad
func (UnimplementedWalletKitServer) ListAccounts(context.Context, *ListAccountsRequest) (*ListAccountsResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method ListAccounts not implemented")
}
func (UnimplementedWalletKitServer) RequiredReserve(context.Context, *RequiredReserveRequest) (*RequiredReserveResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method RequiredReserve not implemented")
}
func (UnimplementedWalletKitServer) ImportAccount(context.Context, *ImportAccountRequest) (*ImportAccountResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method ImportAccount not implemented")
}
@ -797,6 +819,24 @@ func _WalletKit_ListAccounts_Handler(srv interface{}, ctx context.Context, dec f
return interceptor(ctx, in, info, handler)
}
func _WalletKit_RequiredReserve_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(RequiredReserveRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(WalletKitServer).RequiredReserve(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/walletrpc.WalletKit/RequiredReserve",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(WalletKitServer).RequiredReserve(ctx, req.(*RequiredReserveRequest))
}
return interceptor(ctx, in, info, handler)
}
func _WalletKit_ImportAccount_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(ImportAccountRequest)
if err := dec(in); err != nil {
@ -1052,6 +1092,10 @@ var WalletKit_ServiceDesc = grpc.ServiceDesc{
MethodName: "ListAccounts",
Handler: _WalletKit_ListAccounts_Handler,
},
{
MethodName: "RequiredReserve",
Handler: _WalletKit_RequiredReserve_Handler,
},
{
MethodName: "ImportAccount",
Handler: _WalletKit_ImportAccount_Handler,

View File

@ -136,6 +136,10 @@ var (
Entity: "onchain",
Action: "read",
}},
"/walletrpc.WalletKit/RequiredReserve": {{
Entity: "onchain",
Action: "read",
}},
"/walletrpc.WalletKit/ImportAccount": {{
Entity: "onchain",
Action: "write",
@ -1468,6 +1472,27 @@ func (w *WalletKit) ListAccounts(ctx context.Context,
return &ListAccountsResponse{Accounts: rpcAccounts}, nil
}
// RequiredReserve returns the minimum amount of satoshis that should be
// kept in the wallet in order to fee bump anchor channels if necessary.
// The value scales with the number of public anchor channels but is
// capped at a maximum.
func (w *WalletKit) RequiredReserve(ctx context.Context,
req *RequiredReserveRequest) (*RequiredReserveResponse, error) {
numAnchorChans, err := w.cfg.CurrentNumAnchorChans()
if err != nil {
return nil, err
}
additionalChans := req.AdditionalPublicChannels
totalChans := uint32(numAnchorChans) + additionalChans
reserved := w.cfg.Wallet.RequiredReserve(totalChans)
return &RequiredReserveResponse{
RequiredReserve: int64(reserved),
}, nil
}
// parseAddrType parses an address type from its RPC representation to a
// *waddrmgr.AddressType.
func parseAddrType(addrType AddressType,

View File

@ -193,6 +193,9 @@ func (s *subRPCServerConfigs) PopulateDependencies(cfg *Config,
subCfgValue.FieldByName("ChainParams").Set(
reflect.ValueOf(activeNetParams),
)
subCfgValue.FieldByName("CurrentNumAnchorChans").Set(
reflect.ValueOf(cc.Wallet.CurrentNumAnchorChans),
)
case *autopilotrpc.Config:
subCfgValue := extractReflectValue(subCfg)