diff --git a/docs/grpc/ruby.md b/docs/grpc/ruby.md index 55d0ee5b9..5c3db5fec 100644 --- a/docs/grpc/ruby.md +++ b/docs/grpc/ruby.md @@ -42,7 +42,9 @@ Two files will be generated in the current directory: * `rpc_pb.rb` * `rpc_services_pb.rb` -### Example - Simple client to display wallet balance +### Examples + +#### Simple client to display wallet balance Every time you use the Ruby gRPC you need to require the `rpc_services_pb` file. @@ -58,6 +60,11 @@ $:.unshift(File.dirname(__FILE__)) require 'grpc' require 'rpc_services_pb' +# Due to updated ECDSA generated tls.cert we need to let gprc know that +# we need to use that cipher suite otherwise there will be a handhsake +# error when we communicate with the lnd rpc server. +ENV['GRPC_SSL_CIPHER_SUITES'] = "HIGH+ECDSA" + certificate = File.read(File.expand_path("~/.lnd/tls.cert")) credentials = GRPC::Core::ChannelCredentials.new(certificate) stub = Lnrpc::Lightning::Stub.new('127.0.0.1:10009', credentials) @@ -68,7 +75,7 @@ puts "Total balance: #{response.total_balance}" This will show the `total_balance` of the wallet. -#### Example - Streaming client for invoice payment updates +#### Streaming client for invoice payment updates ```ruby #!/usr/bin/env ruby @@ -78,6 +85,8 @@ $:.unshift(File.dirname(__FILE__)) require 'grpc' require 'rpc_services_pb' +ENV['GRPC_SSL_CIPHER_SUITES'] = "HIGH+ECDSA" + certificate = File.read(File.expand_path("~/.lnd/tls.cert")) credentials = GRPC::Core::ChannelCredentials.new(certificate) stub = Lnrpc::Lightning::Stub.new('127.0.0.1:10009', credentials) @@ -104,3 +113,56 @@ $ lncli sendpayment --pay_req= ``` You should now see the details of the settled invoice appear. + +#### Using Macaroons + +To authenticate using macaroons you need to include the macaroon in the metadata of the request. + +```ruby +# Lnd admin macaroon is at ~/.lnd/admin.macaroon on Linux and +# ~/Library/Application Support/Lnd/admin.macaroon on Mac +macaroon_binary = File.read(File.expand_path("~/.lnd/admin.macaroon")) +macaroon = macaroon_binary.each_byte.map { |b| b.to_s(16).rjust(2,'0') }.join +``` + +The simplest approach to use the macaroon is to include the metadata in each request as shown below. + +```ruby +stub.get_info(Lnrpc::GetInfoRequest.new, metadata: {metadata: macaroon}) +``` + +However, this can get tiresome to do for each request. We can use gRPC interceptors to add this metadata to each request automatically. Our interceptor class would look like this. + +```ruby +class MacaroonInterceptor < GRPC::ClientInterceptor + attr_reader :macaroon + + def initialize(macaroon) + @macaroon = macaroon + super + end + + def request_response(request:, call:, method:, metadata:) + metadata['macaroon'] = macaroon + yield + end +end +``` + +And then we would include it when we create our stub like so. + +```ruby +certificate = File.read(File.expand_path("~/.lnd/tls.cert")) +credentials = GRPC::Core::ChannelCredentials.new(certificate) +macaroon_binary = File.read(File.expand_path("~/.lnd/admin.macaroon")) +macaroon = macaroon_binary.each_byte.map { |b| b.to_s(16).rjust(2,'0') }.join + +stub = Lnrpc::Lightning::Stub.new( + 'localhost:10009', + credentials, + interceptors: [MacaroonInterceptor.new(macaroon)] +) + +# Now we don't need to pass the metadata on a request level +p stub.get_info(Lnrpc::GetInfoRequest.new) +```