def data(self, index, role=Qt.DisplayRole): row, col = index.row(), index.column() txout = self.dustTxOutlist[row] addrStr = script_to_addrStr(txout.getScript()) pyAddr = self.wlt.addrMap[addrStr_to_hash160(addrStr)[1]] chainIndex = pyAddr.chainIndex + 1 if role == Qt.DisplayRole: if col == DUSTCOLS.chainIndex: return QVariant(chainIndex) if col == DUSTCOLS.AddrStr: return QVariant(addrStr) if col == DUSTCOLS.Btc: return QVariant(coin2str(txout.getValue(), maxZeros=8)) elif role == Qt.TextAlignmentRole: if col == DUSTCOLS.chainIndex: return QVariant(int(Qt.AlignLeft | Qt.AlignVCenter)) if col == DUSTCOLS.AddrStr: return QVariant(int(Qt.AlignLeft | Qt.AlignVCenter)) if col == DUSTCOLS.Btc: return QVariant(int(Qt.AlignRight | Qt.AlignVCenter)) elif role == Qt.ForegroundRole: return QVariant(Colors.Foreground) elif role == Qt.FontRole: if col == DUSTCOLS.Btc: return GETFONT('Fixed') return QVariant()
def createLogDisplay(self): logTextDisplay = QTextEdit() logTextDisplay.setFont(GETFONT('Fixed', 8)) w, h = relaxedSizeNChar(logTextDisplay, 68)[0], int(12 * 8.2) logTextDisplay.setMinimumWidth(w) logTextDisplay.setMinimumHeight(h) logTextDisplay.setReadOnly(True) return logTextDisplay
def updateWalletTable(self): numWallets = len(self.main.walletMap) self.wltTable.setRowCount(numWallets) self.wltTable.setColumnCount(4) row = 0 for wltID, wltObj in self.main.walletMap.iteritems(): wltValueBTC = '(...)' wltValueUSD = '(...)' if TheBDM.getState() == BDM_BLOCKCHAIN_READY: convertVal = float(self.lastSellStr.replace(',', '')) wltBal = wltObj.getBalance('Total') wltValueBTC = coin2str(wltBal, maxZeros=2) wltValueUSD = '$' + self.addCommasToPrice( '%0.2f' % (wltBal * convertVal / 1e8)) rowItems = [] rowItems.append(QTableWidgetItem(wltID)) rowItems.append(QTableWidgetItem(wltObj.labelName)) rowItems.append(QTableWidgetItem(wltValueBTC)) rowItems.append(QTableWidgetItem(wltValueUSD)) rowItems[-2].setTextAlignment(Qt.AlignRight) rowItems[-1].setTextAlignment(Qt.AlignRight) rowItems[-2].setFont(GETFONT('Fixed', 10)) rowItems[-1].setFont(GETFONT('Fixed', 10)) for i, item in enumerate(rowItems): self.wltTable.setItem(row, i, item) item.setFlags(Qt.NoItemFlags) self.wltTable.setHorizontalHeaderItem( 0, QTableWidgetItem(tr('Wallet ID'))) self.wltTable.setHorizontalHeaderItem( 1, QTableWidgetItem(tr('Wallet Name'))) self.wltTable.setHorizontalHeaderItem( 2, QTableWidgetItem(tr('BTC Balance'))) self.wltTable.setHorizontalHeaderItem( 3, QTableWidgetItem(tr('USD ($) Value'))) self.wltTable.verticalHeader().hide() row += 1
def data(self, index, role=Qt.DisplayRole): col = index.column() node = self.getNodeItem(index) if role == Qt.DisplayRole: if col == COL_NAME: return QVariant(node.treeNode.getName()) if col == COL_DESCR: try: return QVariant(node.treeNode.getComment()) except: pass if col == COL_VALUE: try: return QVariant( coin2str(node.treeNode.getBalance(), maxZeros=2)) except: pass if col == COL_TXOUTCOUNT: try: return QVariant(node.treeNode.getCount()) except: pass elif role == Qt.CheckStateRole: try: if col == COL_NAME: st = node.treeNode.checked() return st else: return QVariant() except: pass elif role == Qt.BackgroundRole: try: if node.treeNode.checked() != Qt.Unchecked: return QVariant(Colors.SlightBlue) except: pass elif role == Qt.FontRole: try: if node.treeNode.checked() != Qt.Unchecked: return GETFONT('Fixed', bold=True) except: pass return QVariant()
def __init__(self, parent, main): super(QWizard, self).__init__(parent) self.setWizardStyle(QWizard.ClassicStyle) self.parent = parent self.main = main self.setFont(GETFONT('var')) self.setWindowFlags(Qt.Window) # Need to adjust the wizard frame size whenever the page changes. self.connect(self, SIGNAL('currentIdChanged(int)'), self.fitContents) if USE_TESTNET: self.setWindowTitle('Armory - Bitcoin Wallet Management [TESTNET]') self.setWindowIcon(QIcon(':/armory_icon_green_32x32.png')) else: self.setWindowTitle('Armory - Bitcoin Wallet Management') self.setWindowIcon(QIcon(':/armory_icon_32x32.png'))
def data(self, index, role=Qt.DisplayRole): col = index.column() node = self.getNodeItem(index) if role == Qt.DisplayRole: if col == COL_OUTPUT: return QVariant(node.treeNode.getName()) if col == COL_ADDR: try: return QVariant(node.treeNode.getAddress()) except: pass if col == COL_VALUE: try: return QVariant(node.treeNode.getValue()) except: pass elif role == Qt.CheckStateRole: try: if col == COL_OUTPUT: if node.treeNode.isCheckable(): st = node.treeNode.checked() return st else: return QVariant() except: pass elif role == Qt.BackgroundRole: try: if node.treeNode.checked() != Qt.Unchecked: return QVariant(Colors.SlightBlue) except: pass elif role == Qt.FontRole: try: if node.treeNode.checked() != Qt.Unchecked: return GETFONT('Fixed', bold=True) except: pass return QVariant()
def createPrintScene(wallet, amountString, expiresString): scene = SimplePrintableGraphicsScene(None, None) INCH = scene.INCH MARGIN = scene.MARGIN_PIXELS scene.resetCursor() scene.drawPixmapFile(':/armory_logo_h36.png') scene.newLine() scene.drawText('Paper Backup for Armory Wallet', GETFONT('Var', 11)) scene.newLine() scene.drawText('http://www.bitcoinarmory.com') scene.newLine(extra_dy=20) scene.drawHLine() scene.newLine(extra_dy=20) ssType = ' (Unencrypted)' bType = tr('Single-Sheet ' + ssType) colRect, rowHgt = scene.drawColumn(['Wallet Version:', 'Wallet ID:', \ 'Wallet Name:', 'Backup Type:']) scene.moveCursor(15, 0) suf = 'c' colRect, rowHgt = scene.drawColumn(['1.35'+suf, wallet.uniqueIDB58, \ wallet.labelName, bType]) scene.moveCursor(15, colRect.y() + colRect.height(), absolute=True) # Display warning about unprotected key data wrap = 0.9*scene.pageRect().width() container = 'this wallet' warnMsg = tr(""" <font color="#aa0000"><b>WARNING:</b></font> Anyone who has access to this page has access to all the bitcoins in %s! Please keep this page in a safe place.""" % container) scene.newLine() scene.drawText(warnMsg, GETFONT('Var', 9), wrapWidth=wrap) scene.newLine(extra_dy=20) scene.drawHLine() scene.newLine(extra_dy=20) numLine = 'two' descrMsg = tr(""" The following %s lines backup all addresses <i>ever generated</i> by this wallet (previous and future). This can be used to recover your wallet if you forget your passphrase or suffer hardware failure and lose your wallet files. """ % numLine) scene.drawText(descrMsg, GETFONT('var', 8), wrapWidth=wrap) scene.newLine(extra_dy=10) ########################################################################### # Finally, draw the backup information. bottomOfSceneHeader = scene.cursorPos.y() code12 = wallet.addrMap['ROOT'].binPrivKey32_Plain.toBinStr() Lines = [] Prefix = [] Prefix.append('Root Key:') Lines.append(makeSixteenBytesEasy(code12[:16])) Prefix.append('') Lines.append(makeSixteenBytesEasy(code12[16:])) # Draw the prefix origX,origY = scene.getCursorXY() scene.moveCursor(20,0) colRect, rowHgt = scene.drawColumn(['<b>'+l+'</b>' for l in Prefix]) nudgeDown = 2 # because the differing font size makes it look unaligned scene.moveCursor(20, nudgeDown) scene.drawColumn(Lines, font=GETFONT('Fixed', 8, bold=True), \ rowHeight=rowHgt, useHtml=False) scene.moveCursor(MARGIN, colRect.y()-2, absolute=True) width = scene.pageRect().width() - 2*MARGIN scene.drawRect( width, colRect.height()+7, edgeColor=QColor(0,0,0), fillColor=None) scene.newLine(extra_dy=30) scene.drawText( tr(""" The following QR code is for convenience only. It contains the exact same data as the %s lines above. If you copy this backup by hand, you can safely ignore this QR code. """ % numLine), wrapWidth=4*INCH) scene.moveCursor(20,0) x,y = scene.getCursorXY() edgeRgt = scene.pageRect().width() - MARGIN edgeBot = scene.pageRect().height() - MARGIN qrSize = max(1.5*INCH, min(edgeRgt - x, edgeBot - y, 2.0*INCH)) scene.drawQR('\n'.join(Lines), qrSize) scene.newLine(extra_dy=25) scene.drawHLine(7*INCH, 5) scene.newLine(extra_dy=25) scene.drawText(tr(""" <font color="#aa0000"><b>CONGRATULATIONS:</b></font> Thank you for participating in the MIT BitComp. You have received a Bitcoin Armory wallet containing %s You may collect this money by installing Bitcoin Armory from the website shown above. After you install the software move the funds to a new wallet or any address that you own. Do not deposit any bitcoins to this wallet. You don't know who else has access to this wallet! You have until %s to claim your bitcoins. After this date we will remove all remaining bitcoins from this wallet.""" % (amountString, expiresString)), GETFONT('Var', 11), wrapWidth=wrap) scene.newLine(extra_dy=25) return scene
def __init__(self, main): def updateDustLimit(): try: self.dustTableModel.updateDustList( self.getSelectedWlt(), str2coin(self.dustLimitText.text())) self.beGoneDustButton.setEnabled( len(self.dustTableModel.dustTxOutlist) > 0) if self.dustTableModel.wlt: self.lblHeader.setText( tr("""<b>Dust Outputs for Wallet: %s</b>""" % self.dustTableModel.wlt.labelName)) except NegativeValueError: pass except TooMuchPrecisionError: pass except: LOGEXCEPT("Unexpected exception") pass def sendDust(): try: utxiList = [] for utxo in self.dustTableModel.dustTxOutlist: # The PyCreateAndSignTx method require PyTx and PyBtcAddress objects rawTx = TheBDM.getTxByHash(utxo.getTxHash()).serialize() a160 = CheckHash160(utxo.getRecipientScrAddr()) for pyAddr in self.dustTableModel.wlt.addrMap.values(): if a160 == pyAddr.getAddr160(): pubKey = pyAddr.binPublicKey65.toBinStr() txoIdx = utxo.getTxOutIndex() utxiList.append( UnsignedTxInput(rawTx, txoIdx, None, pubKey)) break # Make copies, destroy them in the finally clause privKeyMap = {} for addrObj in self.dustTableModel.wlt.addrMap.values(): scrAddr = SCRADDR_P2PKH_BYTE + addrObj.getAddr160() if self.dustTableModel.wlt.useEncryption and self.dustTableModel.wlt.isLocked: # Target wallet is encrypted... unlockdlg = DlgUnlockWallet(self.dustTableModel.wlt, self.main, self.main, 'Unlock Wallet to Import') if not unlockdlg.exec_(): QMessageBox.critical(self, 'Wallet is Locked', \ 'Cannot send dust without unlocking the wallet!', \ QMessageBox.Ok) return privKeyMap[scrAddr] = addrObj.binPrivKey32_Plain.copy() signedTx = PyCreateAndSignTx( utxiList, [], privKeyMap, SIGHASH_NONE | SIGHASH_ANYONECANPAY) print "-------------" print binary_to_hex(signedTx.serialize()) # sock = socket.create_connection(('dust-b-gone.bitcoin.petertodd.org',80)) # sock.send(signedTx.serialize()) # sock.send(b'\n') # sock.close() except socket.error as err: QMessageBox.critical( self.main, tr('Negative Value'), tr(""" Failed to connect to dust-b-gone server: %s""" % err.strerror), QMessageBox.Ok) except NegativeValueError: QMessageBox.critical( self.main, tr('Negative Value'), tr(""" You must enter a positive value of at least 0.0000 0001 and less than %s for the dust limit.""" % MAX_DUST_LIMIT_STR), QMessageBox.Ok) except TooMuchPrecisionError: QMessageBox.critical( self.main.main, tr('Too much precision'), tr(""" Bitcoins can only be specified down to 8 decimal places. The smallest unit of a Bitcoin is 0.0000 0001 BTC. Please enter a dust limit of at least 0.0000 0001 and less than %s.""" % MAX_DUST_LIMIT_STR), QMessageBox.Ok) finally: for scraddr in privKeyMap: privKeyMap[scraddr].destroy() self.main = main self.lblHeader = QRichLabel( tr("""<b>Dust Outputs for Wallet: None Selected</b>"""), doWrap=False) self.beGoneDustButton = QPushButton("Remove Dust") self.beGoneDustButton.setEnabled(False) self.main.connect(self.beGoneDustButton, SIGNAL('clicked()'), sendDust) topRow = makeHorizFrame([self.lblHeader, 'stretch']) secondRow = makeHorizFrame([self.beGoneDustButton, 'stretch']) self.dustLimitLabel = QLabel("Max Dust Value (BTC): ") self.dustLimitText = QLineEdit() self.dustLimitText.setFont(GETFONT('Fixed')) self.dustLimitText.setMinimumWidth( tightSizeNChar(self.dustLimitText, 6)[0]) self.dustLimitText.setMaximumWidth( tightSizeNChar(self.dustLimitText, 12)[0]) self.dustLimitText.setAlignment(Qt.AlignRight) self.dustLimitText.setText(coin2str(DEFAULT_DUST_LIMIT)) self.main.connect(self.dustLimitText, SIGNAL('textChanged(QString)'), updateDustLimit) limitPanel = makeHorizFrame( [self.dustLimitLabel, self.dustLimitText, 'stretch']) self.dustTableModel = DustDisplayModel() self.dustTableView = QTableView() self.dustTableView.setModel(self.dustTableModel) self.dustTableView.setSelectionMode(QTableView.NoSelection) self.dustTableView.verticalHeader().setDefaultSectionSize(20) self.dustTableView.verticalHeader().hide() h = tightSizeNChar(self.dustTableView, 1)[1] self.dustTableView.setMinimumHeight(2 * (1.3 * h)) self.dustTableView.setMaximumHeight(10 * (1.3 * h)) initialColResize(self.dustTableView, [100, .7, .3]) self.dustTableView.setContextMenuPolicy(Qt.CustomContextMenu) self.lblTxioInfo = QRichLabel('') self.lblTxioInfo.setMinimumWidth( tightSizeNChar(self.lblTxioInfo, 30)[0]) self.main.connect(self.main.walletsView, SIGNAL('clicked(QModelIndex)'), updateDustLimit) self.dustBGoneFrame = makeVertFrame( [topRow, secondRow, limitPanel, self.dustTableView, 'stretch']) # Now set the scrollarea widget to the layout self.tabToDisplay = QScrollArea() self.tabToDisplay.setWidgetResizable(True) self.tabToDisplay.setWidget(self.dustBGoneFrame)
def __init__(self, parent, main, cs_callback, get_csstate): super(FeeSelectionDialog, self).__init__(parent, main) #Button Label self.lblButtonFee = QLabelButton("") #get default values flatFee = self.main.getSettingOrSetDefault("Default_Fee", MIN_TX_FEE) flatFee = coin2str(flatFee, maxZeros=1).strip() fee_byte = str(self.main.getSettingOrSetDefault("Default_FeeByte", MIN_FEE_BYTE)) blocksToConfirm = self.main.getSettingOrSetDefault(\ "Default_FeeByte_BlocksToConfirm", NBLOCKS_TO_CONFIRM) self.coinSelectionCallback = cs_callback self.getCoinSelectionState = get_csstate self.validAutoFee = True try: autoFee_byte = str(estimateFee(blocksToConfirm) / 1000.0) except: autoFee_byte = "N/A" self.validAutoFee = False defaultCheckState = \ self.main.getSettingOrSetDefault("FeeOption", DEFAULT_FEE_TYPE) #flat free def setFlatFee(): def callbck(): return self.selectType('FlatFee') return callbck def updateLbl(): self.updateCoinSelection() self.radioFlatFee = QRadioButton(self.tr("Flat Fee (BTC)")) self.edtFeeAmt = QLineEdit(flatFee) self.edtFeeAmt.setFont(GETFONT('Fixed')) self.edtFeeAmt.setMinimumWidth(tightSizeNChar(self.edtFeeAmt, 6)[0]) self.edtFeeAmt.setMaximumWidth(tightSizeNChar(self.edtFeeAmt, 12)[0]) self.connect(self.radioFlatFee, SIGNAL('clicked()'), setFlatFee()) self.connect(self.edtFeeAmt, SIGNAL('textChanged(QString)'), updateLbl) frmFlatFee = QFrame() frmFlatFee.setFrameStyle(STYLE_RAISED) layoutFlatFee = QGridLayout() layoutFlatFee.addWidget(self.radioFlatFee, 0, 0, 1, 1) layoutFlatFee.addWidget(self.edtFeeAmt, 0, 1, 1, 1) frmFlatFee.setLayout(layoutFlatFee) #fee/byte def setFeeByte(): def callbck(): return self.selectType('FeeByte') return callbck self.radioFeeByte = QRadioButton(self.tr("Fee/Byte (Satoshi/Byte)")) self.edtFeeByte = QLineEdit(fee_byte) self.edtFeeByte.setFont(GETFONT('Fixed')) self.edtFeeByte.setMinimumWidth(tightSizeNChar(self.edtFeeByte, 6)[0]) self.edtFeeByte.setMaximumWidth(tightSizeNChar(self.edtFeeByte, 12)[0]) self.connect(self.radioFeeByte, SIGNAL('clicked()'), setFeeByte()) self.connect(self.edtFeeByte, SIGNAL('textChanged(QString)'), updateLbl) frmFeeByte = QFrame() frmFeeByte.setFrameStyle(STYLE_RAISED) layoutFeeByte = QGridLayout() layoutFeeByte.addWidget(self.radioFeeByte, 0, 0, 1, 1) layoutFeeByte.addWidget(self.edtFeeByte, 0, 1, 1, 1) frmFeeByte.setLayout(layoutFeeByte) #auto fee/byte def setAutoFeeByte(): def callbck(): return self.selectType('Auto') return callbck radioButtonTxt = self.tr("Fee rate from node (sat/Byte): ") if not self.validAutoFee: radioButtonTxt = self.tr("Failed to fetch fee/byte from node") self.radioAutoFeeByte = QRadioButton(radioButtonTxt) self.lblAutoFeeByte = QLabel(autoFee_byte) self.lblAutoFeeByte.setFont(GETFONT('Fixed')) self.lblAutoFeeByte.setMinimumWidth(tightSizeNChar(self.lblAutoFeeByte, 6)[0]) self.lblAutoFeeByte.setMaximumWidth(tightSizeNChar(self.lblAutoFeeByte, 12)[0]) self.sliderAutoFeeByte = QSlider(Qt.Horizontal, self) self.sliderAutoFeeByte.setMinimum(2) self.sliderAutoFeeByte.setMaximum(6) self.sliderAutoFeeByte.setValue(blocksToConfirm) self.lblSlider = QLabel() def getSliderLabelTxt(): return self.tr("Blocks to confirm: %1").arg(\ unicode(self.sliderAutoFeeByte.value())) def updateAutoFeeByte(): blocksToConfirm = self.sliderAutoFeeByte.value() try: autoFee_byte = str(estimateFee(blocksToConfirm) / 1000.0) except: autoFee_byte = "N/A" self.lblSlider.setText(getSliderLabelTxt()) self.lblAutoFeeByte.setText(autoFee_byte) updateLbl() self.lblSlider.setText(getSliderLabelTxt()) self.connect(self.radioAutoFeeByte, SIGNAL('clicked()'), setAutoFeeByte()) self.sliderAutoFeeByte.valueChanged.connect(updateAutoFeeByte) self.sliderAutoFeeByte.setEnabled(False) frmAutoFeeByte = QFrame() frmAutoFeeByte.setFrameStyle(STYLE_RAISED) layoutAutoFeeByte = QGridLayout() layoutAutoFeeByte.addWidget(self.radioAutoFeeByte, 0, 0, 1, 1) layoutAutoFeeByte.addWidget(self.lblAutoFeeByte, 0, 1, 1, 1) layoutAutoFeeByte.addWidget(self.lblSlider, 1, 0, 1, 2) layoutAutoFeeByte.addWidget(self.sliderAutoFeeByte, 2, 0, 1, 2) frmAutoFeeByte.setLayout(layoutAutoFeeByte) if not self.validAutoFee: frmAutoFeeByte.setEnabled(False) #adjust and close self.btnClose = QPushButton(self.tr('Close')) self.connect(self.btnClose, SIGNAL('clicked()'), self.accept) self.checkBoxAdjust = QCheckBox(self.tr('Adjust fee/byte for privacy')) self.checkBoxAdjust.setChecked(\ self.main.getSettingOrSetDefault('AdjustFee', True)) self.connect(self.checkBoxAdjust, SIGNAL('clicked()'), updateLbl) frmClose = makeHorizFrame(\ [self.checkBoxAdjust, 'Stretch', self.btnClose], STYLE_NONE) #main layout layout = QGridLayout() layout.addWidget(frmAutoFeeByte, 0, 0, 1, 4) layout.addWidget(frmFeeByte, 2, 0, 1, 4) layout.addWidget(frmFlatFee, 4, 0, 1, 4) layout.addWidget(frmClose, 5, 0, 1, 4) self.setLayout(layout) self.setWindowTitle(self.tr('Select Fee Type')) self.selectType(defaultCheckState) self.setFocus()
def __init__(self, parent, main, cs_callback, get_csstate): super(FeeSelectionDialog, self).__init__(parent, main) #Button Label self.lblButtonFee = QLabelButton("") #get default values flatFee = self.main.getSettingOrSetDefault("Default_Fee", MIN_TX_FEE) flatFee = coin2str(flatFee, maxZeros=1).strip() fee_byte = str( self.main.getSettingOrSetDefault("Default_FeeByte", MIN_FEE_BYTE)) blocksToConfirm = self.main.getSettingOrSetDefault(\ "Default_FeeByte_BlocksToConfirm", NBLOCKS_TO_CONFIRM) feeStrategy = str(self.main.getSettingOrSetDefault(\ "Default_FeeByte_Strategy", FEEBYTE_CONSERVATIVE)) self.coinSelectionCallback = cs_callback self.getCoinSelectionState = get_csstate self.validAutoFee = True isSmartFee = True try: feeEstimate, isSmartFee, errorMsg = self.getFeeByteFromNode( blocksToConfirm, feeStrategy) except: feeEstimate = "N/A" self.validAutoFee = False defaultCheckState = \ self.main.getSettingOrSetDefault("FeeOption", DEFAULT_FEE_TYPE) #flat free def setFlatFee(): def callbck(): return self.selectType('FlatFee') return callbck def updateLbl(): self.updateCoinSelection() self.radioFlatFee = QRadioButton(self.tr("Flat Fee (BTC)")) self.edtFeeAmt = QLineEdit(flatFee) self.edtFeeAmt.setFont(GETFONT('Fixed')) self.edtFeeAmt.setMinimumWidth(tightSizeNChar(self.edtFeeAmt, 6)[0]) self.edtFeeAmt.setMaximumWidth(tightSizeNChar(self.edtFeeAmt, 12)[0]) self.connect(self.radioFlatFee, SIGNAL('clicked()'), setFlatFee()) self.connect(self.edtFeeAmt, SIGNAL('textChanged(QString)'), updateLbl) frmFlatFee = QFrame() frmFlatFee.setFrameStyle(STYLE_RAISED) layoutFlatFee = QGridLayout() layoutFlatFee.addWidget(self.radioFlatFee, 0, 0, 1, 1) layoutFlatFee.addWidget(self.edtFeeAmt, 0, 1, 1, 1) frmFlatFee.setLayout(layoutFlatFee) #fee/byte def setFeeByte(): def callbck(): return self.selectType('FeeByte') return callbck self.radioFeeByte = QRadioButton(self.tr("Fee/Byte (Satoshi/Byte)")) self.edtFeeByte = QLineEdit(fee_byte) self.edtFeeByte.setFont(GETFONT('Fixed')) self.edtFeeByte.setMinimumWidth(tightSizeNChar(self.edtFeeByte, 6)[0]) self.edtFeeByte.setMaximumWidth(tightSizeNChar(self.edtFeeByte, 12)[0]) self.connect(self.radioFeeByte, SIGNAL('clicked()'), setFeeByte()) self.connect(self.edtFeeByte, SIGNAL('textChanged(QString)'), updateLbl) frmFeeByte = QFrame() frmFeeByte.setFrameStyle(STYLE_RAISED) layoutFeeByte = QGridLayout() layoutFeeByte.addWidget(self.radioFeeByte, 0, 0, 1, 1) layoutFeeByte.addWidget(self.edtFeeByte, 0, 1, 1, 1) frmFeeByte.setLayout(layoutFeeByte) #auto fee/byte if isSmartFee: frmAutoFeeByte = self.setupSmartAutoFeeByteUI(\ feeEstimate, blocksToConfirm, feeStrategy) else: frmAutoFeeByte = self.setupLegacyAutoFeeByteUI(\ feeEstimate, blocksToConfirm) #adjust and close self.btnClose = QPushButton(self.tr('Close')) self.connect(self.btnClose, SIGNAL('clicked()'), self.accept) self.checkBoxAdjust = QCheckBox(self.tr('Adjust fee/byte for privacy')) self.checkBoxAdjust.setChecked(\ self.main.getSettingOrSetDefault('AdjustFee', True)) self.connect(self.checkBoxAdjust, SIGNAL('clicked()'), updateLbl) frmClose = makeHorizFrame(\ [self.checkBoxAdjust, 'Stretch', self.btnClose], STYLE_NONE) #main layout layout = QGridLayout() layout.addWidget(frmAutoFeeByte, 0, 0, 1, 4) layout.addWidget(frmFeeByte, 2, 0, 1, 4) layout.addWidget(frmFlatFee, 4, 0, 1, 4) layout.addWidget(frmClose, 5, 0, 1, 4) self.setLayout(layout) self.setWindowTitle(self.tr('Select Fee Type')) self.selectType(defaultCheckState) self.setFocus()
def setupSmartAutoFeeByteUI(self, feeEstimate, blocksToConfirm, strat): def setAutoFeeByte(): def callbck(): return self.selectType('Auto') return callbck stratList = [FEEBYTE_CONSERVATIVE, FEEBYTE_ECONOMICAL] def updateLbl(): self.updateCoinSelection() def getStrategyString(): try: cbIndex = self.comboStrat.currentIndex() return stratList[cbIndex] except: return FEEBYTE_CONSERVATIVE def feeByteToStr(feeByte): try: self.feeByte = feeByte return "<u>%.1f</u>" % feeByte except: self.feeByte = -1 if isinstance(feeByte, str): return feeByte else: return "N/A" radioButtonTxt = self.tr("Fee rate from node (sat/Byte): ") if not self.validAutoFee: radioButtonTxt = self.tr("Failed to fetch fee/byte from node") self.radioAutoFeeByte = QRadioButton(radioButtonTxt) self.lblAutoFeeByte = QLabel(feeByteToStr(feeEstimate)) self.lblAutoFeeByte.setFont(GETFONT('Fixed')) self.lblAutoFeeByte.setMinimumWidth( tightSizeNChar(self.lblAutoFeeByte, 6)[0]) self.lblAutoFeeByte.setMaximumWidth( tightSizeNChar(self.lblAutoFeeByte, 12)[0]) self.sliderAutoFeeByte = QSlider(Qt.Horizontal, self) self.sliderAutoFeeByte.setMinimum(2) self.sliderAutoFeeByte.setMaximum(100) self.sliderAutoFeeByte.setValue(blocksToConfirm) self.lblSlider = QLabel() self.lblStrat = QLabel(self.tr("Profile:")) self.ttStart = self.main.createToolTipWidget( self.tr(''' <u>Fee Estimation Profiles:</u><br><br> <b>CONSERVATIVE:</b> Short term estimate. More reactive to current changes in the mempool. Use this estimate if you want a high probability of getting your transaction mined quickly. <br><br> <b>ECONOMICAL:</b> Long term estimate. Ignores short term changes to the mempool. Use this profile if you want low fees and can tolerate swings in the projected confirmation window. <br><br> The estimate profiles may not diverge until your node has gathered enough data from the network to refine its predictions. Refer to the \"estimatesmartfee\" section in the Bitcoin Core 0.15 changelog for more informations. ''')) self.comboStrat = QComboBox() currentIndex = 0 for i in range(len(stratList)): self.comboStrat.addItem(stratList[i]) if stratList[i] == strat: currentIndex = i self.comboStrat.setCurrentIndex(currentIndex) def getSliderLabelTxt(): return self.tr("Blocks to confirm: %1").arg(\ unicode(self.sliderAutoFeeByte.value())) def updateAutoFeeByte(): blocksToConfirm = self.sliderAutoFeeByte.value() strategy = getStrategyString() try: feeEstimate, version, err = \ self.getFeeByteFromNode(blocksToConfirm, strategy) except: feeEstimate = "N/A" self.lblSlider.setText(getSliderLabelTxt()) self.lblAutoFeeByte.setText(feeByteToStr(feeEstimate)) updateLbl() def stratComboChange(): updateAutoFeeByte() self.lblSlider.setText(getSliderLabelTxt()) self.connect(self.radioAutoFeeByte, SIGNAL('clicked()'), setAutoFeeByte()) self.sliderAutoFeeByte.valueChanged.connect(updateAutoFeeByte) self.sliderAutoFeeByte.setEnabled(False) self.connect(self.comboStrat, SIGNAL('currentIndexChanged(int)'), stratComboChange) frmAutoFeeByte = QFrame() frmAutoFeeByte.setFrameStyle(STYLE_RAISED) layoutAutoFeeByte = QGridLayout() layoutAutoFeeByte.addWidget(self.radioAutoFeeByte, 0, 0, 1, 2) layoutAutoFeeByte.addWidget(self.lblAutoFeeByte, 0, 2, 1, 2) layoutAutoFeeByte.addWidget(self.lblSlider, 1, 0, 1, 1) layoutAutoFeeByte.addWidget(self.sliderAutoFeeByte, 2, 0, 1, 4) layoutAutoFeeByte.addWidget(self.lblStrat, 3, 0, 1, 1) layoutAutoFeeByte.addWidget(self.comboStrat, 3, 1, 1, 2) layoutAutoFeeByte.addWidget(self.ttStart, 3, 3, 1, 1) frmAutoFeeByte.setLayout(layoutAutoFeeByte) if not self.validAutoFee: frmAutoFeeByte.setEnabled(False) return frmAutoFeeByte
def setupLegacyAutoFeeByteUI(self, feeEstimate, blocksToConfirm): def setAutoFeeByte(): def callbck(): return self.selectType('Auto') return callbck def updateLbl(): self.updateCoinSelection() def feeByteToStr(feeByte): try: self.feeByte = feeByte return "<u>%.1f</u>" % feeByte except: self.feeByte = -1 if isinstance(feeByte, str): return feeByte else: return "N/A" radioButtonTxt = self.tr("Fee rate from node (sat/Byte): ") if not self.validAutoFee: radioButtonTxt = self.tr("Failed to fetch fee/byte from node") self.radioAutoFeeByte = QRadioButton(radioButtonTxt) self.lblAutoFeeByte = QLabel(feeByteToStr(feeEstimate)) self.lblAutoFeeByte.setFont(GETFONT('Fixed')) self.lblAutoFeeByte.setMinimumWidth( tightSizeNChar(self.lblAutoFeeByte, 6)[0]) self.lblAutoFeeByte.setMaximumWidth( tightSizeNChar(self.lblAutoFeeByte, 12)[0]) self.sliderAutoFeeByte = QSlider(Qt.Horizontal, self) self.sliderAutoFeeByte.setMinimum(2) self.sliderAutoFeeByte.setMaximum(6) self.sliderAutoFeeByte.setValue(blocksToConfirm) self.lblSlider = QLabel() def getSliderLabelTxt(): return self.tr("Blocks to confirm: %1").arg(\ unicode(self.sliderAutoFeeByte.value())) def updateAutoFeeByte(): blocksToConfirm = self.sliderAutoFeeByte.value() try: feeEstimate, version, err = \ self.getFeeByteFromNode(blocksToConfirm, FEEBYTE_CONSERVATIVE) except: feeEstimate = "N/A" self.lblSlider.setText(getSliderLabelTxt()) self.lblAutoFeeByte.setText(feeByteToStr(feeEstimate)) updateLbl() self.lblSlider.setText(getSliderLabelTxt()) self.connect(self.radioAutoFeeByte, SIGNAL('clicked()'), setAutoFeeByte()) self.sliderAutoFeeByte.valueChanged.connect(updateAutoFeeByte) self.sliderAutoFeeByte.setEnabled(False) frmAutoFeeByte = QFrame() frmAutoFeeByte.setFrameStyle(STYLE_RAISED) layoutAutoFeeByte = QGridLayout() layoutAutoFeeByte.addWidget(self.radioAutoFeeByte, 0, 0, 1, 1) layoutAutoFeeByte.addWidget(self.lblAutoFeeByte, 0, 1, 1, 1) layoutAutoFeeByte.addWidget(self.lblSlider, 1, 0, 1, 2) layoutAutoFeeByte.addWidget(self.sliderAutoFeeByte, 2, 0, 1, 2) frmAutoFeeByte.setLayout(layoutAutoFeeByte) if not self.validAutoFee: frmAutoFeeByte.setEnabled(False) return frmAutoFeeByte