Beispiel #1
0
    def showTransaction_desc_(self, txraw, desc) -> None:
        tx = Transaction(txraw, sign_schnorr=parent().prefs_use_schnorr)
        tx.deserialize()
        tx_hash, status_, label_, can_broadcast, amount, fee, height, conf, timestamp, exp_n = wallet(
        ).get_tx_info(tx)
        #print("send: status_",status_,"label_",label_,"amount",amount,"conf",conf)
        size = tx.estimated_size()
        conf = 0 if conf is None else conf
        timestamp = time.time() if timestamp is None else timestamp
        status, status_str = (
            status_, _("Unsigned")
        )  #wallet().get_tx_status(tx_hash, height, conf, timestamp)
        doFX = fx() and fx().is_enabled()
        ccy = fx().get_currency() if doFX else None
        fiat_amount_str = str(self.fiat.text) if doFX else None
        #HistoryEntry = namedtuple("HistoryEntry", "tx tx_hash status_str label v_str balance_str date ts conf status value fiat_amount fiat_balance fiat_amount_str fiat_balance_str ccy status_image")
        entry = HistoryEntry(
            tx, tx_hash, status_str, str(desc), self.amt.text, "",
            timestamp_to_datetime(time.time() if conf <= 0 else timestamp),
            timestamp, conf, status, amount, None, None, fiat_amount_str, None,
            ccy, None)

        def newLabel(l):
            self.descDel.text = l

        self.navigationController.pushViewController_animated_(
            txdetail.CreateTxDetailWithEntry(entry, on_label=newLabel), True)
Beispiel #2
0
 def on_qr(self, data):
     from electroncash.bitcoin import base_decode, is_address
     data = data.strip()
     if is_address(data):
         self.set_URI(data)
         return
     if data.startswith('bitcoincash:'):
         self.set_URI(data)
         return
     # try to decode transaction
     from electroncash.transaction import Transaction
     try:
         text = base_decode(data, None, base=43).encode('hex')
         tx = Transaction(text)
         tx.deserialize()
         if self.wallet:
             my_coins = self.wallet.get_spendable_coins(
                 None, self.electrum_config)
             my_outpoints = [
                 vin['prevout_hash'] + ':' + str(vin['prevout_n'])
                 for vin in my_coins
             ]
             for i, txin in enumerate(tx.inputs()):
                 outpoint = txin['prevout_hash'] + ':' + str(
                     txin['prevout_n'])
                 if outpoint in my_outpoints:
                     my_index = my_outpoints.index(outpoint)
                     tx._inputs[i]['value'] = my_coins[my_index]['value']
     except:
         tx = None
     if tx:
         self.tx_dialog(tx)
         return
     # show error
     self.show_error("Unable to decode QR data")
 def tx_from_text(self, txt):
     from electroncash.transaction import tx_from_str
     try:
         txt_tx = tx_from_str(txt)
         tx = Transaction(txt_tx,
                          sign_schnorr=self.wallet.is_schnorr_enabled())
         tx.deserialize()
         if self.wallet:
             my_coins = self.wallet.get_spendable_coins(
                 None, self.main_window.config)
             my_outpoints = [
                 vin['prevout_hash'] + ':' + str(vin['prevout_n'])
                 for vin in my_coins
             ]
             for i, txin in enumerate(tx.inputs()):
                 outpoint = txin['prevout_hash'] + ':' + str(
                     txin['prevout_n'])
                 if outpoint in my_outpoints:
                     my_index = my_outpoints.index(outpoint)
                     tx._inputs[i]['value'] = my_coins[my_index]['value']
         return tx
     except:
         traceback.print_exc(file=sys.stderr)
         self.show_critical(
             _("Electron Cash was unable to parse your transaction"))
         return
Beispiel #4
0
 def tx_from_text(self, txt):
     from electroncash.transaction import tx_from_str
     try:
         txt_tx = tx_from_str(txt)
         tx = Transaction(txt_tx, sign_schnorr=self.wallet.is_schnorr_enabled())
         tx.deserialize()
         return tx
     except:
         traceback.print_exc(file=sys.stdout)
         self.show_critical(_("Electron Cash was unable to parse your transaction"))
         return
Beispiel #5
0
def _setup_transaction_detail_view(vc : ObjCInstance) -> None:
    entry = utils.nspy_get_byname(vc, 'tx_entry')
    tx, tx_hash, status_str, label, v_str, balance_str, date, ts, conf, status, value, fiat_amount, fiat_balance, fiat_amount_str, fiat_balance_str, ccy, img, *dummy2 = entry
    parent = gui.ElectrumGui.gui
    wallet = parent.wallet
    base_unit = parent.base_unit()
    format_amount = parent.format_amount
    if not wallet:
        utils.NSLog("TxDetail: Wallet not open.. aborting early (tx_hash=%s)",tx_hash)
        return
    if tx is None:
        tx = wallet.transactions.get(tx_hash, None)
        if tx is not None and tx.raw:
            tx = Transaction(tx.raw, sign_schnorr=parent.prefs_use_schnorr)
            tx.deserialize()
    if tx is None:
        utils.NSLog("*** ERROR: Cannot find tx for hash: %s",tx_hash)
        return
    tx_hash, status_, label_, can_broadcast, amount, fee, height, conf, timestamp, exp_n = wallet.get_tx_info(tx)
    size = tx.estimated_size()
    can_sign = not tx.is_complete() and wallet and wallet.can_sign(tx) #and (wallet.can_sign(tx) # or bool(self.main_window.tx_external_keypairs))

    wasNew = False
    if not vc.viewIfLoaded:
        NSBundle.mainBundle.loadNibNamed_owner_options_("TxDetail",vc,None)
        wasNew = True
        if vc.maxTVHeight < 1.0:
            vc.maxTVHeight = vc.inputsTVHeightCS.constant

    # grab all the views
    # Transaction ID:
    txTit = vc.txTit
    txHash =  vc.txHash
    copyBut = vc.cpyBut
    qrBut =  vc.qrBut
    # Description:
    descTit = vc.descTit
    descTf = vc.descTf
    # Status:
    statusTit = vc.statusTit
    statusIV = vc.statusIV
    statusLbl = vc.statusLbl
    # Date:
    dateTit = vc.dateTit
    dateLbl = vc.dateLbl
    # Amount received/sent:
    amtTit = vc.amtTit
    amtLbl = vc.amtLbl
    # Size:
    sizeTit = vc.sizeTit
    sizeLbl = vc.sizeLbl
    # Fee:
    feeTit = vc.feeTit
    feeLbl = vc.feeLbl
    # Locktime:
    lockTit = vc.lockTit
    lockLbl = vc.lockLbl
    # ⓢ Schnorr Signed label
    schnorrLbl = vc.schnorrLbl
    # Inputs
    inputsTV = vc.inputsTV
    # Outputs
    outputsTV = vc.outputsTV

    # Setup data for all the stuff
    txTit.text = _("Transaction ID:").translate({ord(':') : None})
    tx_hash_str = tx_hash if tx_hash is not None and tx_hash != "None" and tx_hash != "Unknown" and tx_hash != _("Unknown") else _('Unknown')
    rbbs = []
    vc.bottomView.setHidden_(True)
    vc.bottomBut.handleControlEvent_withBlock_(UIControlEventPrimaryActionTriggered, None) # clear previous events
    if can_sign:
        vc.noBlkXplo = True
        vc.bottomView.setHidden_(False)
        def fun() -> None: vc.onSign()
        vc.bottomBut.handleControlEvent_withBlock_(UIControlEventPrimaryActionTriggered, fun)
        vc.bottomBut.setTitle_forState_(_('Sign'), UIControlStateNormal)
        if not img:
            img = StatusImages[-1]
    if can_broadcast:
        vc.noBlkXplo = True
        vc.bottomView.setHidden_(False)
        def fun() -> None: vc.onBroadcast()
        vc.bottomBut.handleControlEvent_withBlock_(UIControlEventPrimaryActionTriggered, None) # clear previous events
        vc.bottomBut.handleControlEvent_withBlock_(UIControlEventPrimaryActionTriggered, fun)
        vc.bottomBut.setTitle_forState_(_('Broadcast'), UIControlStateNormal)
        if not img:
            img = StatusImages[-2]

    if tx_hash_str == _("Unknown") or tx_hash is None: #unsigned tx
        copyBut.setHidden_(True)
        qrBut.setHidden_(True)
        txHash.setHidden_(True)
        txHash.userInteractionEnabled = False
        vc.noTxHashView.setHidden_(False)
        vc.noTxHashLbl.text = _("You need to sign this transaction in order for it to get a transaction ID.") if can_sign else _("This transaction is not signed and thus lacks a transaction ID.")
        vc.notsigned = True
        rbbs.append(UIBarButtonItem.alloc().initWithImage_style_target_action_(UIImage.imageNamed_("barbut_actions"), UIBarButtonItemStyleBordered, vc, SEL(b'onShareSave:')).autorelease())
    else:
        copyBut.setHidden_(False)
        qrBut.setHidden_(False)
        txHash.setHidden_(False)
        vc.noTxHashView.setHidden_(True)
        vc.notsigned = False
        txHash.linkText = tx_hash_str
        txHash.userInteractionEnabled = True

        def onTxLinkTap(ll : objc_id) -> None:
            vc.onTxLink_(ObjCInstance(ll).gr)
        txHash.linkTarget = Block(onTxLinkTap)
        rbbs.append(UIBarButtonItem.alloc().initWithImage_style_target_action_(UIImage.imageNamed_("barbut_actions"), UIBarButtonItemStyleBordered, vc, SEL(b'onTxLink:')).autorelease())

    if amount is None: # unrelated to this wallet.. hide the description textfield.. also affects messaging below.. see viewDidLayoutSubviews
        vc.unrelated = True
    else:
        vc.unrelated = False

    vc.navigationItem.rightBarButtonItems = rbbs

    descTit.text = _("Description")
    descTf.text = label
    descTf.placeholder = _("Tap to add a description")
    descTf.clearButtonMode = UITextFieldViewModeWhileEditing
    utils.uitf_redo_attrs(descTf)

    statusTit.setText_withKerning_(_("Status:").translate({ord(':') : None}), utils._kern)
    if not img:
        #try and auto-determine the appropriate image if it has some confirmations and img is still null
        try:
            c = min(int(conf), 6)
            if c >= 0: img = StatusImages[c+3]
        except:
            pass
        if not img: img = UIImage.imageNamed_("empty.png")
    ff = str(status_) #status_str
    vc.canRefresh = False
    try:
        if int(conf) > 0:
           ff = "%s %s"%(str(conf), _('confirmations'))
        vc.canRefresh = conf >= 0 # if we got here means refresh has meaning.. it's not an external tx or if it is, it now is on the network, so enable refreshing
    except:
        pass
    statusLbl.text = _(ff)
    if vc.canRefresh and conf >= 1: img = StatusImages[min(len(StatusImages)-1,3+min(6,conf))]
    statusIV.image = img


    if timestamp or exp_n:
        if timestamp:
            dateTit.setText_withKerning_(_("Date"), utils._kern)
            #dateLbl.text = str(date)
            dateLbl.attributedText = utils.makeFancyDateAttrString(str(date))
        elif exp_n:
            dateTit.setText_withKerning_(_("Expected conf."), utils._kern)
            dateLbl.text = '%d blocks'%(exp_n) if exp_n > 0 else _('unknown (low fee)')
        vc.noBlkXplo = False
        dateTit.alpha = 1.0
        dateLbl.alpha = 1.0
    else:
        # wtf? what to do here?
        dateTit.setText_withKerning_(_("Date"), utils._kern)
        dateLbl.text = ""
        dateTit.alpha = 0.5
        dateLbl.alpha = 0.5

    myAmtStr = ''
    if vc.unrelated:
        amtTit.setText_withKerning_(_("Amount"), utils._kern)
        amtLbl.text = _("Transaction unrelated to your wallet")
    elif amount > 0:
        amtTit.setText_withKerning_(_("Amount received:").translate({ord(':') : None}), utils._kern)
        myAmtStr = ('%s %s%s'%(format_amount(amount),base_unit,
                               (" " + fiat_amount_str + " " + ccy + "") if fiat_amount_str else '',
                               ))
    else:
        amtTit.setText_withKerning_( _("Amount sent:").translate({ord(':') : None}), utils._kern )
        myAmtStr = ('%s %s%s'%(format_amount(-amount),base_unit,
                               (" " + fiat_amount_str.replace('-','') + " " + ccy + "") if fiat_amount_str else '',
                               ))
    if myAmtStr:
        l = myAmtStr.split()
        am = l[0]
        unt = ' ' + l[1] if len(l) else ''
        rest = ' ' + ' '.join(l[2:]) if len(l) > 2 else ''
        ats = NSMutableAttributedString.alloc().initWithString_attributes_(am, {NSFontAttributeName : UIFont.systemFontOfSize_weight_(16.0, UIFontWeightBold)}).autorelease()
        if unt:
            ats.appendAttributedString_(NSAttributedString.alloc().initWithString_attributes_(unt, {NSFontAttributeName : UIFont.systemFontOfSize_weight_(16.0, UIFontWeightBold)}).autorelease())
        if rest:
            ats.appendAttributedString_(NSAttributedString.alloc().initWithString_attributes_(rest, {NSFontAttributeName : UIFont.systemFontOfSize_weight_(14.0, UIFontWeightRegular)}).autorelease())
        amtLbl.attributedText = ats

    sizeTit.setText_withKerning_( _("Size:").translate({ord(':') : None}), utils._kern )
    if size:
        sizeLbl.text = ('%d bytes' % (size))
    else:
        sizeLbl.text = _("Unknown")

    feeTit.setText_withKerning_( _("Fee"), utils._kern )
    fee_str = '%s' % (format_amount(fee) + ' ' + base_unit if fee is not None else _('unknown'))
    if fee is not None:
        fee_str += '  ( %s ) '%  parent.format_fee_rate(fee/size*1000)
    feeLbl.text = fee_str

    lockTit.setText_withKerning_(_("Locktime"), utils._kern)
    if tx.locktime > 0:
        lockLbl.text = str(tx.locktime)
        lockTit.setHidden_(False)
        lockLbl.setHidden_(False)
    else:
        lockTit.setHidden_(True)
        lockLbl.setHidden_(True)

    n_inp, n_outp = len(tx.inputs()), len(tx.outputs())
    # auto-adjust height of table views
    vc.inputsTVHeightCS.constant = min(_TxInputsOutputsHeaderHeight + _TxInputsOutputsCellHeight*n_inp, vc.maxTVHeight)
    vc.outputsTVHeightCS.constant = min(_TxInputsOutputsHeaderHeight + _TxInputsOutputsCellHeight*n_outp, vc.maxTVHeight)

    # refreshes the tableview with data
    if wasNew:
        if ts is None: ts = time.time()
        tvc = CreateTxInputsOutputsTVC(vc, tx, inputsTV, outputsTV, float(ts))
    else:
        inputsTV.reloadData()
        outputsTV.reloadData()

    if any(tx.is_schnorr_signed(i) for i in range(n_inp)):
        schnorrLbl.text = SCHNORR_SIGIL + " " + _('Schnorr Signed')
        schnorrLbl.setHidden_(False)
    else:
        schnorrLbl.setHidden_(True)