Esempio n. 1
0
class LightningDaemon(object):
    def __init__(self, daemon_rpc):
        self.rpc = LightningRpc(daemon_rpc)

    def invoice_c_lightning(self, msatoshi, label, description):
        expiry = INVOICE_EXPIRY + random.randint(3, 9)
        try:
            result = self.rpc.invoice(msatoshi, label, description,
                                      expiry=expiry)
            logging.info("invoicing daemon. got: %s" %
                         json.dumps(result, indent=1, sort_keys=True))
            return result
        except:
            return None

    def get_c_lightning_invoices(self):
        try:
            return self.rpc.listinvoices()
        except:
            return None
        #logging.info(json.dumps(result, indent=1, sort_keys=True))

    def _delete(self, label, state="paid"):
        try:
            result = self.rpc.delinvoice(label, state)
            return result
        except IOError:
            # unpaid could have expired in the last split second due
            # to a race, so try again
            if state == "unpaid":
                result = self.rpc.delinvoice(label, "expired")
        return result

    def delete(self, label, state="paid"):
        try:
            return self._delete(label, state=state)
        except:
            return None

    def getinfo(self):
        try:
            return self.rpc.getinfo()
        except:
            return None

    def listfunds(self):
        try:
            return self.rpc.listfunds()
        except:
            return None

    def listnodes(self):
        try:
            return self.rpc.listnodes()
        except:
            return None
Esempio n. 2
0
class Daemon(object):
    def __init__(self):
        self.rpc = LightningRpc(RPC_FILE)

    def _gen_new_label(self):
        label_bytes = uuid.uuid4().bytes
        label_str = b64encode(label_bytes).decode("utf8")
        return label_str

    def invoice(self):
        msatoshis = 12000
        description = "f**k you, pay me"
        label = self._gen_new_label()
        i = self.rpc.invoice(msatoshis, label, description)
        return {'label': label, 'bolt11': i['bolt11']}
Esempio n. 3
0
class CLightningClient(LightningClient):
    """Access a c-lightning instance using the Python API."""
    def __init__(
        self,
        rpc_path: str,
    ) -> None:
        self.rpc_path = rpc_path

    def init(self):
        # Create an instance of the LightningRpc object using the Core Lightning daemon on your computer.
        logger.info('initializing clightning client: {}'.format(self.rpc_path))
        self.lrpc = LightningRpc(self.rpc_path)

    def pay_invoice(self, payment_request: str) -> Payment:
        payment = self.lrpc.pay(payment_request)
        if payment['status'] == 'complete':
            return Payment(
                payment_preimage=bytes.fromhex(payment['payment_preimage']),
                payment_error='',
            )
        else:
            return Payment(
                payment_preimage=b'',
                payment_error='Payment failed.',
            )

    def get_info(self) -> Info:
        info = self.lrpc.getinfo()
        pubkey = info['id']
        binding = info.get('binding')
        uris = []
        if binding:
            for b in binding:
                address = b['address']
                if ':' not in address:  # TODO: Change type of uri to LightningAddress.
                    port = b['port']
                    uri = f"{pubkey}@{address}:{port}"
                    uris.append(uri)
        return Info(uris=uris, )

    def decode_pay_req(self, payment_request: str) -> PayReq:
        pay_req = self.lrpc.decodepay(payment_request)
        return PayReq(
            payment_hash=bytes.fromhex(pay_req['payment_hash']),
            payment_point=b'',  # TODO: Use real payment point.
            num_msat=pay_req['amount_msat'].millisatoshis,
            destination=pay_req['payee'],
            timestamp=int(pay_req['created_at']),
            expiry=int(pay_req['expiry']),
        )

    def create_invoice(self, preimage: bytes, amount_msat: int) -> Invoice:
        created_invoice = self.lrpc.invoice(
            amount_msat,
            label=str(uuid.uuid4()),
            description="Squeaknode invoice",
            preimage=preimage.hex(),
        )
        creation_time = int(time.time())
        expiry = int(created_invoice['expires_at']) - creation_time
        return Invoice(
            r_hash=bytes.fromhex(created_invoice['payment_hash']),
            payment_request=created_invoice['bolt11'],
            value_msat=amount_msat,
            settled=False,
            settle_index=0,
            creation_date=creation_time,
            expiry=expiry,
        )

    def subscribe_invoices(self, settle_index: int) -> InvoiceStream:
        def cancel_fn():
            return None

        def get_invoice_stream():
            try:
                pay_index = settle_index
                while True:
                    payment = self.lrpc.waitanyinvoice(lastpay_index=pay_index)
                    if payment['status'] == 'paid':
                        pay_index = payment.get('pay_index') or 0
                        yield Invoice(
                            r_hash=bytes.fromhex(payment['payment_hash']),
                            payment_request=payment.get('bolt11') or '',
                            value_msat=payment.get('value_msat'),
                            settled=True,
                            settle_index=pay_index,
                            creation_date=0,  # This value is ignored.
                            expiry=payment['expires_at'],
                        )
            except Exception:
                raise InvoiceSubscriptionError()

        return InvoiceStream(
            cancel=cancel_fn,
            result_stream=get_invoice_stream(),
        )
Esempio n. 4
0
class clightning:
    def __init__(self, node_config):
        from pyln.client import LightningRpc

        self.config = node_config
        self.is_onchain = False

        for i in range(config.connection_attempts):
            try:
                if config.tunnel_host is None:
                    rpc_file = self.config['clightning_rpc_file']
                else:
                    rpc_file = "lightning-rpc"

                logging.info(
                    "Attempting to connect to clightning with unix domain socket: {}"
                    .format(rpc_file))
                self.clightning = LightningRpc(rpc_file)

                logging.info("Getting clightning info...")
                info = self.clightning.getinfo()
                logging.info(info)

                logging.info("Successfully connected to clightning.")
                break

            except Exception as e:
                logging.error(e)
                if i < 5:
                    time.sleep(2)
                else:
                    time.sleep(60)
                logging.info("Attempting again... {}/{}...".format(
                    i + 1, config.connection_attempts))
        else:
            raise Exception(
                "Could not connect to clightning. Check your port tunneling settings and try again."
            )

        logging.info("Ready for payments requests.")
        return

    def create_qr(self, uuid, address, value):
        qr_str = "{}".format(address.upper())
        img = qrcode.make(qr_str)
        img.save("static/qr_codes/{}.png".format(uuid))
        return

    def get_info(self):
        return self.clightning.getinfo()

    def get_uri(self):
        info = self.get_info()
        address = info["address"][0]
        return info["id"] + "@" + address["address"] + ":" + str(
            address["port"])

    # Create lightning invoice
    def create_clightning_invoice(self, btc_amount, label, expiry):
        # Multiplying by 10^8 to convert to satoshi units
        msats_amount = int(float(btc_amount) * 10**(3 + 8))
        lnd_invoice = self.clightning.invoice(msats_amount, label,
                                              "SatSale-{}".format(label),
                                              expiry)
        return lnd_invoice["bolt11"], lnd_invoice["payment_hash"]

    def get_address(self, amount, label, expiry):
        address, r_hash = self.create_clightning_invoice(amount, label, expiry)
        return address, r_hash

    # Check whether the payment has been paid
    def check_payment(self, uuid):
        invoices = self.clightning.listinvoices(uuid)["invoices"]

        if len(invoices) == 0:
            logging.error("Could not find invoice on node. Something's wrong.")
            return 0, 0

        invoice = invoices[0]

        if invoice["status"] != "paid":
            conf_paid = 0
            unconf_paid = 0
        else:
            # Store amount paid and convert to BTC units
            conf_paid = int(invoice["msatoshi_received"]) / 10**(3 + 8)
            unconf_paid = 0

        return conf_paid, unconf_paid