async def r_redeem_wallet(lsat: LSAT, info): tx = await GINO.db.transaction() try: password = token_hex(10) # save to db user = await User.create( key=token_bytes(32), username=token_hex(10), password_hash=ARGON.hash(password), role="USER", created=time(), ) user.password = password # decode b64 to bytes pay_hash = ln.PaymentHash(r_hash=b64decode(lsat.payment_hash.encode("utf-8"))) inv_lookup = await LND.stub.LookupInvoice(pay_hash) # determine if lsat was paid for internally or externally if (invoice := await Invoice.get(lsat.payment_hash)): # invoice was paid by another internal user await invoice.update(payee=user.username).apply() else:
async def run(self, user): """ retrives invoices (payment requests) for current user and returns them with payment state based on gRPC query. Side Effect: adds true lnd invoices as paid in redis Internal invoices are marked as paid on payment send """ statement = DB_Invoice.query.where( or_( and_(DB_Invoice.payee == user.username, self._payee), and_(DB_Invoice.payer == user.username, self._payer), )).order_by(DB_Invoice.timestamp.desc()) if self._limit > 0: statement = statement.limit(self._limit) statement = statement.offset(self._offset) invoices = [] async with GINO.db.transaction(): async for invoice in statement.gino.iterate(): if not invoice.paid: # if not paid check lnd to see if its paid in lnd db req = ln.PaymentHash( r_hash=decode64(invoice.payment_hash.encode("utf-8"))) lookup_info = await LND.stub.LookupInvoice(req) if lookup_info.state == 1: # invoice is paid update state in db await invoice.update( paid=True, paid_at=lookup_info.settle_date).apply() if self._filter(invoice): invoices.append(invoice) # TODO convert to asynchronous generator? return invoices
def is_received(pay_req): # first decode pay_req to get pay_hash request = ln.PayReqString(pay_req=pay_req) response = stub.DecodePayReq(request) pay_hash = response.payment_hash # check if settled request = ln.PaymentHash(r_hash_str=pay_hash) response = stub.LookupInvoice(request) return response.settled
def pay_countdown(): pay_counter.value = int(pay_counter.value) + 1 invoice = stub.LookupInvoice(ln.PaymentHash(r_hash_str=my_hashtext.value)) if invoice.settled: pay_counter.cancel(pay_countdown) pay_counter.after(10, paid) if int(pay_counter.value) > 3000: pay_counter.value = 1 pay_counter.cancel(pay_countdown) pay_counter.after(10, generate_bill)
def main(): # 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 handshake # error when we communicate with the lnd rpc server. os.environ["GRPC_SSL_CIPHER_SUITES"] = 'HIGH+ECDSA' with open('/home/lnd/.lnd/tls.cert', 'rb') as f: cert = f.read() with open('/home/lnd/.lnd/data/chain/bitcoin/mainnet/invoice.macaroon', 'rb') as f: macaroon_bytes = f.read() macaroon = codecs.encode(macaroon_bytes, 'hex') def metadata_callback(context, callback): # for more info see grpc docs callback([('macaroon', macaroon)], None) # build ssl credentials using the cert the same as before cert_creds = grpc.ssl_channel_credentials(cert) # now build meta data credentials auth_creds = grpc.metadata_call_credentials(metadata_callback) # combine the cert credentials and the macaroon auth credentials # such that every call is properly encrypted and authenticated combined_creds = grpc.composite_channel_credentials(cert_creds, auth_creds) # finally pass in the combined credentials when creating a channel channel = grpc.secure_channel('localhost:10009', combined_creds) stub = lnrpc.LightningStub(channel) uri = os.environ.get("REQUEST_URI") match = re.search("[?&]r_hash=([0-9a-f]+)(&.*)?$", uri) if not match: raise ("No Index") rhash = match.group(1) settled = False timeout = time.time() + 60 # 1 minute timeout while not settled and time.time() < timeout: invoice = stub.LookupInvoice(ln.PaymentHash(r_hash_str=rhash)) if invoice.settled: settled = True break time.sleep(1) print("Content-Type: application/json; charset=UTF-8") print("") print('{"settled":%s}' % ("true" if settled else "false"))
def main(): stub = connect() uri = os.environ.get("REQUEST_URI") match = re.search("[?&]r_hash=([0-9a-f]+)(&.*)?$", uri) if not match: raise ValueError("No Index") rhash = match.group(1) settled = False timeout = time.time() + 60 # 1 minute timeout while not settled and time.time() < timeout: invoice = stub.LookupInvoice(ln.PaymentHash(r_hash_str=rhash)) if invoice.settled: settled = True break time.sleep(1) print("Content-Type: application/json; charset=UTF-8") print("") print('{"settled":%s}' % ("true" if settled else "false"))
async def r_add_invoice(user: User, *_, memo: str, amt: int, set_hash: Optional[bytes] = None ) -> Union[Invoice, Error]: if amt <= 0: return Error("InvalidInvoice", f"Invalid amount: {amt}") expiry_time = 3600 * 24 request = ln.Invoice(memo=memo, value=amt, expiry=expiry_time, r_hash=set_hash) inv = await LND.stub.AddInvoice(request) # lookup invoice to get preimage pay_hash = ln.PaymentHash(r_hash=inv.r_hash) inv_lookup = await LND.stub.LookupInvoice(pay_hash) return await Invoice.create( payment_hash=b64encode(inv.r_hash).decode(), payment_request=inv.payment_request.upper(), payment_preimage=b64encode(inv_lookup.r_preimage).decode(), timestamp=inv_lookup.creation_date, expiry=inv_lookup.expiry, memo=inv_lookup.memo, paid=False, amount=inv_lookup.value, # do not set a fee since this invoice has not been paid payee=user.username # do not set a payer since we dont know to whom to invoice is being sent )
def check_invoices(): r_hash = request.data r_hash_base64 = r_hash.encode('utf-8') r_hash_bytes = str(codecs.decode(r_hash_base64, 'base64')) invoice_resp = stub.LookupInvoice(ln.PaymentHash(r_hash=r_hash_bytes)) return str(invoice_resp.settled)
def lookup_invoice(rhash: str, node_url: str, macaroon: str, cert: str): stub = get_stub(node_url, macaroon, cert) request = ln.PaymentHash(r_hash_str=rhash) return stub.LookupInvoice(request, timeout=10)