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)
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
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
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)