Exemplo n.º 1
0
def create_tx(from_, to, amount, currency, action="send"):
    log.debug("Creating transaction.. ")
    user = User.query.filter_by(phone_number=from_).first()
    if user is None:
        log.error("User does not exist.")
        return
    if currency is None or currency == "":
        currency = "XLM"
    conn = redis.Redis.from_url(REDIS_URL)
    tx_key = "tx:" + from_
    tx = {
        "from": from_.strip(),
        "to": to.strip(),
        "amount": amount.strip(),
        "currency": currency.strip(),
    }
    conn.hmset(tx_key, tx)
    payment = Payment(
        destination=tx["to"],
        amount=tx["amount"],
        asset=tx["currency"],
        fee="100",
        sender=user,
    )
    db.session.add(payment)
    db.session.commit()
    log.debug(f"Created transaction with key {tx_key} and tx {tx}.")

    return tx_summary(from_, to, amount, currency)
Exemplo n.º 2
0
def process_tx(from_):
    log.debug("Processing transaction.. ")
    conn = redis.Redis.from_url(REDIS_URL)
    tx_key = "tx:" + from_
    tx = conn.hgetall(tx_key)
    user = User.query.filter_by(
        phone_number=tx.get(b"from").decode("utf-8")).first()
    sender_seed = user.keypair_seed
    log.debug("Transaction is ready for submission.")
    # lock tx to ensure only 1 worker is working on the tx at a given time
    # and watch for any changes made to the tx by another process during submission
    lockname = "lock:" + tx_key
    lock = acquire_lock(conn, lockname)
    if not lock:
        # return if unable to get lock, i.e. if another worker process is working on the tx
        return
    pipe = conn.pipeline(True)
    pipe.watch(tx_key)
    if send_payment(sender_seed, tx):
        pipe.multi()
        pipe.delete(tx_key)
        pipe.execute()
    else:
        pipe.unwatch()
    release_lock(conn, lockname, lock)
Exemplo n.º 3
0
def address_lookup(from_, username):
    try:
        user, address = (db.session.query(
            User, Address).filter(User.id == Address.user_id).filter(
                Address.username == username).first())
        return address.address
    except Exception as e:
        log.debug(f"error during address lookup - {e}")
        return None
Exemplo n.º 4
0
def incoming_sms():
    try:
        message = request.values.to_dict()
        log.debug(message)
        resp_body = sms_handler(request.values)
    except Exception as e:
        log.error(e)
        return str(MessagingResponse())
    resp = MessagingResponse()
    resp.message(resp_body)
    return str(resp)
Exemplo n.º 5
0
def sms_handler(message):
    log.debug(f'Received message - {message.get("Body")}')
    body = message.get("Body").strip().lower()
    from_ = message.get("From")
    if tx_pending(from_):
        if body in ["y", "yes"]:
            otp = otp_required(from_)
            if otp:
                return "Incorrect password. Your transaction has been canceled."
            process_tx.delay(from_)
            return "Your transaction has been submitted."
        if check_otp(from_, body):
            process_tx.delay(from_)
            return "Your transaction has been submitted."
        return "Your transaction has been canceled."

    return sms_parser(from_, body)
Exemplo n.º 6
0
def sms_parser(from_, sms):
    log.debug(f"Parsing sms - {sms}")
    match = SEND_PATTERN.match(sms)
    if not match:
        log.debug("sms does not match send pattern regex.")
        return "Invalid transaction. Please try again."
    if len(match.group(2)) == 56:  # stellar address (public key)
        log.debug("sms contains a Stellar address.")
        create_tx.delay(
            from_=from_,
            to=match.group(2),
            amount=match.group(3),
            currency=match.group(4),
        )
        return ""
    address = address_lookup(from_, match.group(2))
    if address:
        log.debug("Address lookup successful.")
        create_tx.delay(from_=from_,
                        to=address,
                        amount=match.group(3),
                        currency=match.group(4))
        return ""
    return "Invalid address. Please try again."
Exemplo n.º 7
0
def send_payment(sender_seed, tx):
    # Generate the sender's Keypair for signing and setting as the source
    sender_kp = Keypair.from_seed(sender_seed)
    tx = {key.decode("utf-8"): val.decode("utf-8") for key, val in tx.items()}
    # Address for the destination
    destination = tx.get("to")

    # create op
    amount = tx.get("amount")
    if tx.get("currency").upper() == "XLM":
        asset = Asset("XLM")
    else:
        raise UnknownIssuerError("Unknown currency and/or issuer.")
        # TODO:
        # Issuer's address
        # ISSUER = tx.get('issuer')
        # asset = Asset(tx.get('currency').upper(), ISSUER)

    op = Payment(
        # Source is also inferred from the transaction source, so it's optional.
        source=sender_kp.address().decode(),
        destination=destination,
        asset=asset,
        amount=amount,
    )

    # create a memo
    msg = TextMemo("Stellar-SMS is dope!!!")

    horizon = horizon_testnet()
    # horizon = horizon_livenet() for LIVENET

    # Get the current sequence of sender
    sequence = horizon.account(
        sender_kp.address().decode("utf-8")).get("sequence")

    # TODO: track sequence locally for better accuracy, speed, and robustness

    # Construct a transaction
    tx = Transaction(
        source=sender_kp.address().decode(),
        sequence=sequence,
        # time_bounds = {'minTime': 1531000000, 'maxTime': 1531234600},
        memo=msg,
        fee=100,  # Can specify a fee or use the default by not specifying it
        operations=[op],
    )

    # Build transaction envelope
    envelope = Te(tx=tx, network_id="TESTNET")  # or 'PUBLIC'

    # Sign the envelope
    envelope.sign(sender_kp)

    # Submit the transaction to Horizon!
    xdr = envelope.xdr()
    response = horizon.submit(xdr)
    log.debug(str(response))
    if response.get("status") not in [None, 200]:
        log.error(
            f"Submission unsuccessful. Horizon retured with error: {response.detail}"
        )
        return
    log.debug("Transaction was successfully submitted to the network.")
    return True