Esempio n. 1
0
def pay_cb(n, action):
    assert action == "pay"
    PAYMENT = stub.SendPaymentSync(ln.SendRequest(payment_request=LN_INVOICE))
    if PAYMENT.payment_error:
        notify2.Notification("Lightning Pay", "Transaction to \n{}\nfailed with \n{}".format(DEST,PAYMENT.payment_error),icon=ICON_FAILURE).show()
    else:
        notify2.Notification("Lightning Pay","Transaction to \n{}\nis successful".format(DEST),icon=ICON_SUCCESS).show()
    n.close()
Esempio n. 2
0
def scan_channel(my_channel_id: int, scan_channel_id: int):
    # Grab some initial data and make sure everything came back OK
    node = init_node()
    my_channels = node.ListChannels(ln.ListChannelsRequest()).channels
    my_channel = [c for c in my_channels if c.chan_id == my_channel_id][0]
    channel = node.GetChanInfo(ln.ChanInfoRequest(chan_id=scan_channel_id))

    if not my_channel:
        raise Exception(f'You have no channel with ID "{my_channel_id}"')
    if not channel:
        raise Exception(f'Unknown channel with ID "{scan_channel_id}"')

    # Determine the max we can scan, and who's the "receiver"
    maximum = min(
        int(channel.capacity),
        int(my_channel.local_balance),
        MAX_PAYMENT_SIZE,
    )
    dest_pubkey = channel.node2_pub if my_channel.remote_pubkey == channel.node1_pub else channel.node2_pub

    # Loop send bogus payments until we find the balance
    low = 0
    high = maximum

    print(f'Beginning scan of channel {scan_channel_id}, max scannable {maximum} satoshis...')
    while high - low > 1:
        test_amount = math.ceil((low + high) / 2)
        print(f'Probing with a {test_amount} sat payment...')

        res = node.SendPaymentSync(ln.SendRequest(
            dest_string=dest_pubkey,
            amt=test_amount,
            payment_hash_string=make_random_hash(),
            outgoing_chan_id=my_channel.chan_id,
            final_cltv_delta=144,
        ))
        err = res.payment_error

        # Depending on the error, raise or lower the amount. The route note having
        # enough capacity comes in many shapes and sizes of error, so we have to
        # check for a few types here.
        if 'UnknownPaymentHash' in err:
            print('Amount was too low, raising lower bound...')
            low = test_amount
        elif 'unable to find a path' in err or \
                'insufficient' in err or \
                'TemporaryChannelFailure' in err:
            print('Amount was too high, lowering upper bound...')
            high = test_amount
        else:
            raise Exception(f'Unknown error occured when trying to scan: {err}')

    print(f'Balance for channel ${scan_channel_id} is between {low} and {high} satoshis!')
    if high == maximum:
        print(f'NOTE: The balance exceeds the height we were able to scan, so it may be larger than {maximum} satoshis')
Esempio n. 3
0
 def _pay(self, bolt11):
     try:
         request = ln.SendRequest(payment_request=bolt11)
         response = self.stub.SendPaymentSync(request)
         logging.info(response)
         if response.payment_preimage:
             return "Preimage %s" % MessageToJson(response.payment_preimage)
         else:
             return str(response)
     except grpc.RpcError as e:
         logging.error(e)
         return e.details()
Esempio n. 4
0
 def pay_invoice(self, pay_req):
     invoice_details = self.decode_pay_request(pay_req)
     try:
         request = ln.SendRequest(
             dest_string=invoice_details.destination,
             amt=invoice_details.num_satoshis,
             payment_hash_string=invoice_details.payment_hash,
             final_cltv_delta=144  # final_cltv_delta=144 is default for lnd
         )
         response = self.client.SendPaymentSync(request)
         logger.warning(response)
     except Exception as e:
         logger.exception(e)
Esempio n. 5
0
    def sendPayment(self, invoice, amt=None):
        if amt:
            if amt < 100000:
                feeLimit = 20
            elif amt < 200000:
                feeLimit = 20
            elif amt < 300000:
                feeLimit = 30
            elif amt < 400000:
                feeLimit = 40
            elif amt < 500000:
                feeLimit = 50
            else:
                feeLimit = 50

            request = ln.SendRequest(payment_request=invoice,
                                     fee_limit=ln.FeeLimit(fixed=feeLimit),
                                     amt=amt)
        else:
            request = ln.SendRequest(payment_request=invoice,
                                     fee_limit=ln.FeeLimit(fixed=10))
        return self.stub.SendPaymentSync(request)
Esempio n. 6
0
def pay_invoice(invoice):
    send_req = ln.SendRequest(payment_request=invoice)
    sent_payment = stub.SendPaymentSync(send_req)
    if "unable to find a path to destination" in sent_payment.payment_error:
        return sent_payment.payment_error
    return invoice
Esempio n. 7
0
        raise e
    logger.debug(decode_payreq)
    satoshis = decode_payreq.num_satoshis
    destination = decode_payreq.destination

    if satoshis > db.get_balance(session, user):
        update.message.reply_text("Insufficient funds")
        return

    logger.info("{} initiating payment of {}".format(user, payment_request))
    update.message.reply_text("Sending payment...")

    # XXX: This is a synchonous command, will block until GRPC_TIMEOUT
    try:
        ret = stub.SendPaymentSync(
            ln.SendRequest(payment_request=payment_request),
            timeout=GRPC_TIMEOUT)
    except Exception, e:
        update.message.reply_markdown(messages.exception(e))
        raise e

    if ret.payment_route \
        and ret.payment_route.total_amt > 0:
        # Payment successfully went through
        sent_amount = ret.payment_route.total_amt
        num_hops = len(ret.payment_route.hops)
        fee_amount = sent_amount - satoshis
        logger.info("{} sent payment of {} satoshis to {}".format(
            user, sent_amount, destination))
        db.add_transaction(session, user, -sent_amount, payment_request)
        session.commit()
Esempio n. 8
0
def send_payment(pay_req):
    request = ln.SendRequest(payment_request=pay_req)
    response = stub.SendPaymentSync(request)
    return True
Esempio n. 9
0
 def send(self, bolt11):
     req = lnrpc.SendRequest(payment_request=bolt11)
     res = self.rpc.stub.SendPaymentSync(req)
     if res.payment_error:
         raise ValueError(res.payment_error)
     return hexlify(res.payment_preimage)
Esempio n. 10
0
 def send(self, req):
     req = lnrpc.SendRequest(payment_request=req)
     res = self.rpc.stub.SendPaymentSync(req)
     return hexlify(res.payment_preimage)
Esempio n. 11
0
        notify2.init("LN-Pay")
        notify2.Notification("Invalid Lightning Network invoice").show()
        sys.exit(1)


MBTC = DECODED_PAYREQ.num_satoshis/100000
DEST = DECODED_PAYREQ.destination
DESC = DECODED_PAYREQ.description
BALANCE = stub.ChannelBalance(ln.ChannelBalanceRequest()).balance * 100000


if sys.stdout.isatty():
    print("{} mBTC in Lightning Network".format(BALANCE))
    if DEST in whitelist and MBTC <= MAX_AUTOPAY_AMT and BALANCE >= MIN_AUTOPAY_BALANCE :
        print("Paying to {} for {} with {}".format(DEST,DESC,MBTC))
        PAYMENT = stub.SendPaymentSync(ln.SendRequest(payment_request=LN_INVOICE))
        if PAYMENT.payment_error:
            _ = input("Transaction to {} failed with {}, press any key to exit".format(DEST,PAYMENT.payment_error))
        else:
            print("Transaction to {} is successful".format(DEST))
            sleep(1)
    else:
        CMD = input("Pay to {} for {} with {} mBTC y/n: ".format(DEST,DESC,MBTC))
        if CMD == 'y':
            PAYMENT = stub.SendPaymentSync(ln.SendRequest(payment_request=LN_INVOICE))
            if PAYMENT.payment_error:
                _ = input("Transaction to {} failed with {}, press any key to exit".format(DEST,PAYMENT.payment_error))
            else:
                print("Transaction to {} is successful".format(DEST))
                sleep(1)
Esempio n. 12
0
async def r_pay_invoice(user: User,
                        *_,
                        invoice: str,
                        amt: Optional[int] = None):
    # determine true invoice amount
    pay_string = ln.PayReqString(pay_req=invoice.replace("lightning:", ""))
    try:
        decoded = await LND.stub.DecodePayReq(pay_string)
    except GRPCError as e:
        return Error("PaymentError", str(e))

    if amt is not None and decoded.num_satoshis != amt and decoded.num_satoshis > 0:
        return Error("PaymentError",
                     "Payment amount does not match invoice amount")

    if decoded.num_satoshis == 0 and not amt:
        return Error("PaymentError",
                     "You must specify an amount for this tip invoice")

    payment_amt = amt or decoded.num_satoshis
    fee_limit = ceil(payment_amt * 0.01)

    # convert decoded hex to string b64
    b64_payment_hash = b64encode(b16decode(decoded.payment_hash,
                                           casefold=True)).decode()

    # lock payer's db row before determining balance
    async with GINO.db.transaction():
        # potentially user.query.with_for..
        await user.query.with_for_update().gino.status()  # obtain lock
        user_balance = await user.balance()
        if payment_amt + fee_limit > user_balance:
            return Error(
                "InsufficientFunds",
                f"""Attempting to pay {payment_amt} sat
                with fee limit {fee_limit} sat
                with only {user_balance} sat""",
            )

        # determine if external node invoice
        if LND.id_pubkey != decoded.destination:

            req = ln.SendRequest(
                payment_request=invoice,
                amt=payment_amt,
                fee_limit=ln.FeeLimit(fixed=fee_limit),
            )

            invoice_obj = Invoice(
                payment_hash=b64_payment_hash,
                payment_request=invoice,
                timestamp=decoded.timestamp,
                expiry=decoded.expiry,
                memo=decoded.description,
                paid=False,  # not yet paid
                amount=decoded.num_satoshis,
                payer=user.username,
            )

            payment_res = await LND.stub.SendPaymentSync(req)
            if payment_res.payment_error or not payment_res.payment_preimage:
                return Error("PaymentError", payment_res.payment_error)

            invoice_obj.payment_preimage = b64encode(
                payment_res.payment_preimage).decode()
            # impose maximum fee
            invoice_obj.fee = max(fee_limit,
                                  payment_res.payment_route.total_fees)
            invoice_obj.paid = True
            invoice_obj.paid_at = int(time())

            return await invoice_obj.create()

        # determine if internal user invoice
        elif LND.id_pubkey == decoded.destination and (
                invoice_obj := await Invoice.get(b64_payment_hash)):
            if invoice_obj.paid:
                return Error("PaymentError",
                             "This invoice has already been paid")
            # internal invoice, get payee from db
            if not (payee := await User.get(invoice_obj.payee)):
                # could not find the invoice payee in the db
                return Error("PaymentError", "This invoice is invalid")

            await invoice_obj.update(paid=True,
                                     payer=user.username,
                                     fee=fee_limit,
                                     paid_at=time()).apply()

            # check if there are clients in the subscribe channel for this invoice
            if payee.username in PUBSUB.keys():
                # clients are listening, push to all open clients
                for client in PUBSUB[payee.username]:
                    await client.put(invoice_obj)

            return invoice_obj
Esempio n. 13
0
def makepayment():
     try:
        rpc_connect = AuthServiceProxy("http://{}:{}@{}:{}".format(rpc_user,rpc_password,allowed_ip,rpc_port))
        current_block_height = rpc_connect.getblockcount()
        onchain_peers = rpc_connect.getconnectioncount()
        chain_type = rpc_connect.getblockchaininfo()['chain']
        onchain_balance = rpc_connect.getbalance()
        fasttx = rpc_connect.estimatesmartfee(2)
        medtx = rpc_connect.estimatesmartfee(6)
        slowtx = rpc_connect.estimatesmartfee(12)

        newaddress = rpc_connect.getnewaddress()
        packqraddr = pyqrcode.create(newaddress)
        packqraddr.svg("app/static/img/newaddress.svg", scale=8)

        if chain_type == "main":
            fasttxrate = u"~₿ " + str(fasttx['feerate'])
            medtxrate = u"~₿ " + str(medtx['feerate'])
            slowtxrate = u"~₿ " + str(slowtx['feerate'])
        else:
            fasttxrate = u"~t₿ " + str(fasttx['feerate'])
            medtxrate = u"~t₿ " + str(medtx['feerate'])
            slowtxrate = u"~t₿ " + str(slowtx['feerate'])

        if onchain_balance > 0 and chain_type == "main":
            onchain_balance = u"₿ " + str(onchain_balance)
        elif onchain_balance == 0:
            onchain_balance = u"₿ " + str(0)
        elif onchain_balance > 0 and chain_type == "test":
            onchain_balance = u"t₿ " + str(onchain_balance)        
        else:
            onchain_balance = u"t₿ " + str(0)
        if chain_type == "test":
            chaintype_ln = "testnet"
        else:
            chaintype_ln = "mainnet"

        conn = True
     except:
        onchain_balance = "Offline!"
        fasttxrate, medtxrate, slowtxrate = "", "", ""
        conn = False

     try:
      os.environ["GRPC_SSL_CIPHER_SUITES"] = 'HIGH+ECDSA'
      with open(os.path.expanduser(lnd_dir_location + 'data/chain/bitcoin/{}/admin.macaroon'.format(chaintype_ln)), 'rb') as f:
        macaroon_bytes = f.read()
        macaroon = codecs.encode(macaroon_bytes, 'hex')
      cert = open(os.path.expanduser(lnd_dir_location + 'tls.cert'), 'rb').read()
      creds = grpc.ssl_channel_credentials(cert)
      channel = grpc.secure_channel('localhost:10009', creds)
      stub = lnrpc.LightningStub(channel)

      satbalance = stub.ChannelBalance(ln.ChannelBalanceRequest(), metadata=[('macaroon', macaroon)])
      offchain_balance = u"ş " + str(format(satbalance.balance,','))

      lninvoice = (stub.AddInvoice(ln.Invoice(), metadata=[('macaroon', macaroon)])).payment_request
      packlnaddr = pyqrcode.create(lninvoice)
      packqraddr.svg("app/static/img/lninvoice.svg", scale=8)

     except:
      offchain_balance = "Offline!"

     if conn == True:
      if request.method == 'POST':
        if request.form['action'] == "sendbutton":
          if request.form['fee'] == "medfee":
            try:
              txid = rpc_connect.sendtoaddress(request.form['address'], request.form['amt'], "", "", False, True, medtx['blocks'])

              return render_template('makepayment.html', onchain_balance=onchain_balance, fasttxrate=fasttxrate, medtxrate=medtxrate, slowtxrate=slowtxrate, successfultx=True, txid=txid, offchain_balance=offchain_balance, newaddress=newaddress, lninvoice=lninvoice)
            except:

              return render_template('makepayment.html', onchain_balance=onchain_balance, fasttxrate=fasttxrate, medtxrate=medtxrate, slowtxrate=slowtxrate, successfultx=False, offchain_balance=offchain_balance, newaddress=newaddress, lninvoice=lninvoice)

          elif request.form['fee'] == "highfee":
            try:
              txid = rpc_connect.sendtoaddress(request.form['address'], request.form['amt'], "", "", False, True, fasttx['blocks'])

              return render_template('makepayment.html', onchain_balance=onchain_balance, fasttxrate=fasttxrate, medtxrate=medtxrate, slowtxrate=slowtxrate, successfultx=True, txid=txid, offchain_balance=offchain_balance, newaddress=newaddress, lninvoice=lninvoice)
            except:

              return render_template('makepayment.html', onchain_balance=onchain_balance, fasttxrate=fasttxrate, medtxrate=medtxrate, slowtxrate=slowtxrate, successfultx=False, offchain_balance=offchain_balance, newaddress=newaddress, lninvoice=lninvoice) 
          elif request.form['fee'] == "lowfee":
            try:
              txid = rpc_connect.sendtoaddress(request.form['address'], request.form['amt'], "", "", False, True, slowtx['blocks'])

              return render_template('makepayment.html', onchain_balance=onchain_balance, fasttxrate=fasttxrate, medtxrate=medtxrate, slowtxrate=slowtxrate, successfultx=True, txid=txid, offchain_balance=offchain_balance, newaddress=newaddress, lninvoice=lninvoice)
            except:
              return render_template('makepayment.html', onchain_balance=onchain_balance, fasttxrate=fasttxrate, medtxrate=medtxrate, slowtxrate=slowtxrate, successfultx=False, offchain_balance=offchain_balance, newaddress=newaddress, lninvoice=lninvoice)

        if request.form['action'] == "decodereq":
            try:
              os.environ["GRPC_SSL_CIPHER_SUITES"] = 'HIGH+ECDSA'
              with open(os.path.expanduser(lnd_dir_location + 'data/chain/bitcoin/{}/admin.macaroon'.format(chaintype_ln)), 'rb') as f:
                macaroon_bytes = f.read()
                macaroon = codecs.encode(macaroon_bytes, 'hex')
              cert = open(os.path.expanduser(lnd_dir_location + 'tls.cert'), 'rb').read()
              creds = grpc.ssl_channel_credentials(cert)
              channel = grpc.secure_channel('localhost:10009', creds)
              stub = lnrpc.LightningStub(channel)
              if len(request.form['reqtext']) > 20:
                req_whole = request.form['reqtext']
                decoded_req = stub.DecodePayReq(ln.PayReqString(pay_req=req_whole), metadata=[('macaroon', macaroon)])
                req_desc = decoded_req.description
                req_amt = u"ş " + str(format(decoded_req.num_satoshis,','))
                req_to = decoded_req.destination
                with open("invoice.txt",'wb') as invoicefile:
                 invoicefile.write(req_whole)
                 invoicefile.close()
                return render_template('makepayment.html', onchain_balance=onchain_balance, fasttxrate=fasttxrate, medtxrate=medtxrate, slowtxrate=slowtxrate, successfultx="N/A", req_desc=req_desc, req_amt=req_amt, req_to=req_to, switch=True, offchain_balance=offchain_balance, req_whole=req_whole, newaddress=newaddress, lninvoice=lninvoice)
              else:
                return render_template('makepayment.html', onchain_balance=onchain_balance, fasttxrate=fasttxrate, medtxrate=medtxrate, slowtxrate=slowtxrate, successfultx="N/A", switch=False, offchain_balance=offchain_balance, newaddress=newaddress, lninvoice=lninvoice)
            except:
              return render_template('makepayment.html', onchain_balance=onchain_balance, fasttxrate=fasttxrate, medtxrate=medtxrate, slowtxrate=slowtxrate, successfultx="N/A", switch=False, offchain_balance=offchain_balance, newaddress=newaddress, lninvoice=lninvoice)
        if request.form['action'] == "confirmbutton":
            try:
              os.environ["GRPC_SSL_CIPHER_SUITES"] = 'HIGH+ECDSA'
              with open(os.path.expanduser(lnd_dir_location + 'data/chain/bitcoin/{}/admin.macaroon'.format(chaintype_ln)), 'rb') as f:
                macaroon_bytes = f.read()
                macaroon = codecs.encode(macaroon_bytes, 'hex')
              cert = open(os.path.expanduser(lnd_dir_location + 'tls.cert'), 'rb').read()
              creds = grpc.ssl_channel_credentials(cert)
              channel = grpc.secure_channel('localhost:10009', creds)
              stub = lnrpc.LightningStub(channel)
              with open("invoice.txt",'r') as invoicefile:
                invoice_confirmed = invoicefile.read()    

              try:
               result = stub.SendPaymentSync(ln.SendRequest(payment_request=str(invoice_confirmed)), metadata=[('macaroon', macaroon)])
               if result.payment_error:
                 return render_template('makepayment.html', onchain_balance=onchain_balance, fasttxrate=fasttxrate, medtxrate=medtxrate, slowtxrate=slowtxrate, successfultx="N/A", offchain_balance=offchain_balance, successln=False, error=result.payment_error, newaddress=newaddress, lninvoice=lninvoice)
               else:
                return render_template('makepayment.html', onchain_balance=onchain_balance, fasttxrate=fasttxrate, medtxrate=medtxrate, slowtxrate=slowtxrate, successfultx="N/A", offchain_balance=offchain_balance, successln=True, preimage=hexlify(result.payment_preimage), newaddress=newaddress, lninvoice=lninvoice)
              except:
                return render_template('makepayment.html', onchain_balance=onchain_balance, fasttxrate=fasttxrate, medtxrate=medtxrate, slowtxrate=slowtxrate, successfultx=False, offchain_balance=offchain_balance, newaddress=newaddress, lninvoice=lninvoice)
            except:
                return render_template('makepayment.html', onchain_balance=onchain_balance, fasttxrate=fasttxrate, medtxrate=medtxrate, slowtxrate=slowtxrate, successfultx=False, offchain_balance=offchain_balance, newaddress=newaddress, lninvoice=lninvoice)
        
      else:
        return render_template('makepayment.html', onchain_balance=onchain_balance, fasttxrate=fasttxrate, medtxrate=medtxrate, slowtxrate=slowtxrate, successfultx="N/A", offchain_balance=offchain_balance, newaddress=newaddress, lninvoice=lninvoice)
     return render_template('makepayment.html', onchain_balance=onchain_balance, fasttxrate=fasttxrate, medtxrate=medtxrate, slowtxrate=slowtxrate, successfultx="N/A", offchain_balance=offchain_balance)