def get_raw_unsigned(self, fee_satoshi): """Return raw transaction ready for signing May return a transaction with amount=0 if the input amount is not enough to cover fees """ amount_satoshi = wally.tx_get_output_satoshi(self.tx, self.vout) if fee_satoshi >= amount_satoshi: logging.warning('Insufficient funds to cover fee') logging.warning('txout has value of {}, fee = {}'.format( amount_satoshi, fee_satoshi)) # Calculate adjusted amount = input amount - fee adjusted_amount_satoshi = max(0, amount_satoshi - fee_satoshi) logging.debug('tx amount = amount - fee = {} - {} = {}'.format( amount_satoshi, fee_satoshi, adjusted_amount_satoshi)) assert adjusted_amount_satoshi >= 0 logging.debug("Create tx: {} sat -> {}".format(adjusted_amount_satoshi, self.dest_address)) # Set nlocktime to the current blockheight to discourage 'fee sniping', as per the core # wallet implementation tx = txutil.new(util.get_current_blockcount() or 0, version=1) seq = gaconstants.MAX_BIP125_RBF_SEQUENCE txutil.add_input(tx, self.txhash_bin, self.vout, seq) scriptpubkey = util.scriptpubkey_from_address(self.dest_address) txutil.add_output(tx, adjusted_amount_satoshi, scriptpubkey) return txutil.to_hex(tx)
def output_to_dict(self, i: int) -> Dict: if i > self.num_outputs() - 1: raise InvalidIndexError return { 'scriptpubkey': wally.tx_get_output_script(self.tx, i), 'satoshi': wally.tx_get_output_satoshi(self.tx, i), }
def append_column_data(self, txs, columns, summary_columns): """Iterate through utxos appending column data to column for each Return total in BTC and total number of utxos """ total = 0 total_utxos = 0 for tx_wif in txs: for idx in range(wally.tx_get_num_outputs(tx_wif[0])): values = [ column.value(tx_wif, idx) for column in summary_columns ] for i, value in enumerate(values): columns[i].append(value) total += wally.tx_get_output_satoshi(tx_wif[0], idx) total_utxos += 1 return total, total_utxos
def sign(self): """Return raw signed transaction""" type_map = {'p2wsh': gaconstants.P2SH_P2WSH_FORTIFIED_OUT, 'p2sh': 0} txdata = { 'prevout_scripts': [self.witness.redeem_script_hex], 'prevout_script_types': [type_map[self.witness.type_]], 'prevout_values': [wally.tx_get_output_satoshi(self.tx, self.vout)] } signatories = [ gacommon.ActiveSignatory(key) for key in self.keyset.private_keys ] def sign_(fee): txdata['tx'] = self.get_raw_unsigned(fee) return gacommon.sign( txdata, signatories, ) signed_no_fee = sign_(fee=1000) fee_satoshi = self.get_fee(signed_no_fee) signed_fee = sign_(fee=fee_satoshi) return txutil.to_hex(signed_fee)
def expect_feerate(fee_satoshi_byte, args=None, is_segwit=False, amount=None, too_big=False): """Expect the given feerate Callers typically mock estimatesmartfee before calling this """ if args is None: destination_address = 'mynHfTyTWyGGB76NBFbfUrTnn8YWQkTJVs' args = [ '--mnemonic-file={}'.format(datafile('mnemonic_2.txt')), '--rpcuser=abc', '--rpcpassword=abc', '2of3', '--recovery-mnemonic-file={}'.format(datafile('mnemonic_3.txt')), '--rescan', '--search-subaccounts={}'.format(sub_depth), '--destination-address={}'.format(destination_address), '--key-search-depth=150', '--default-feerate={}'.format(default_feerate), ] # Raw tx if too_big: stdout, ofiles = get_output_ex(args) summary = parse_summary(stdout) assert len(summary) == 1 assert summary[0]['total out'] == '0.0 BTC' assert summary[0]['coin value'] == '0.0 BTC' csv = parse_csv(ofiles[garecovery.clargs.DEFAULT_OFILE]) csv = [row for row in csv] assert len(csv) == 1 assert csv[0]['raw tx'] == '** dust **' return output = get_output(args).strip() output_tx = txutil.from_hex(output) assert wally.tx_get_num_outputs(output_tx) == 1 if is_segwit: assert wally.tx_get_witness_count(output_tx) > 0 else: assert wally.tx_get_witness_count(output_tx) == 0 # Calculate the expected fee expected_fee = decimal.Decimal(fee_satoshi_byte * wally.tx_get_vsize(output_tx)) # The amount of our test tx is a well known value if amount is None: amount = decimal.Decimal(111110000) expected_amount = amount - expected_fee actual_amount = wally.tx_get_output_satoshi(output_tx, 0) if expected_amount <= 0: # If expected amount is negative then the fee exceeds the amount # In this case the amount should be small, but not zero assert actual_amount > 0 assert actual_amount < 10 else: # Expect the resultant tx to have a single output with expected amount # Calculating the fee is not exact so allow a tolerance tolerance = decimal.Decimal(0.001) assert actual_amount < (expected_amount * (1 + tolerance)) assert actual_amount > (expected_amount * (1 - tolerance))
def get_coin_value(tx_wif, idx): if gacommon.is_liquid(clargs.args.network): return '-' return btc(wally.tx_get_output_satoshi(tx_wif[0], idx), units)
def get_coin_value(tx_wif, idx): return btc(wally.tx_get_output_satoshi(tx_wif[0], idx), units)