def __new__(cls, value=0, context=None): """ Initialize a new Size object. Must pass a bytes or a spec value for size. The bytes value is a numerical value for the size this object represents, in bytes. The spec value is a string specification of the size using any of the size specifiers in the _decimalPrefixes or _binaryPrefixes lists combined with a 'b' or 'B'. For example, to specify 640 kilobytes, you could pass any of these spec parameters: "640kb" "640 kb" "640KB" "640 KB" "640 kilobytes" If you want to use a spec value to represent a bytes value, you can use the letter 'b' or 'B' or omit the size specifier. """ if isinstance(value, (unicode, str)): size = _parseSpec(value) elif isinstance(value, (int, long, float, Decimal)): size = Decimal(value) elif isinstance(value, Size): size = Decimal(value.convertTo("b")) else: raise ValueError("invalid value %s for size" % value) # drop any partial byte size = size.to_integral_value(rounding=ROUND_DOWN) self = Decimal.__new__(cls, value=size) return self
def value_of(self, currency, volume=1): """Returns the amount that would be yielded if the trade volume, denominated in `currency`, were executed. Does not handle volumes that exceed the top order's volume at the moment, as such functionality is not yet necessary for our purposes. Args: volume - The amount of the given currency to remove from the top. currency - The currency denomination of the volume. """ if volume == 0: return 0 depth = self.get_depth() if depth["asks"][0]["price"] == 0: return 0 volume = self.add_fee(volume) if currency == self.amount_currency: gross = Decimal(str(volume)) * Decimal(str(depth["bids"][0]["price"])) elif currency == self.price_currency: gross = Decimal(str(volume)) / Decimal(str(depth["asks"][0]["price"])) else: self._raise_currency_exception(currency) return float(gross.quantize(Decimal('1.00000000')))
def dorefund(request, error_url, success_url, template = "paypal/dorefund.html"): if request.POST: # normalize the given amount amount = request.POST.get("amount") trans_id = request.POST.get("transactionid") try: amount = Decimal(amount) amount = str(amount.quantize(Decimal(".01"), rounding = ROUND_UP)) except: if request.user.is_authenticated(): request.user.message_set.create(message = _("No given valid amount. Please check the amount that will be charged.")) return HttpResponseRedirect(error_url) response_obj = get_object_or_404(PayPalResponse, trans_id = trans_id) # charge from PayPal result, response = process_refund_request(response_obj, amount) # process the result if not result: # show the error message (comes from PayPal API) and redirect user to the error page if request.user.is_authenticated(): request.user.message_set.create(message = _("Amount %s has not been charged, server error is '%s'" % (amount, response.error))) return HttpResponseRedirect(error_url) # Now we are gone, redirect user to success page if request.user.is_authenticated(): request.user.message_set.create(message = _("Amount %s has been successfully refunded, your transaction id is '%s'" % (amount, response.trans_id))) return HttpResponseRedirect(success_url) return render_to_response(template, {'error_url': error_url, 'success_url': success_url, }, context_instance = RequestContext(request))
def r_value_of(self, currency, volume = 1): """Returns the amount of currency necessary to return the given volume of the given currency. Useful for working backwards to the amount of money that needs to go into the system after working out the maximum trade volume across market order books. Does not handle volumes that exceed the top order's volume at the moment, as such functionality is not yet necessary for our purposes. Args: volume - The amount of the given currency to remove from the top. currency - The currency denomination of the volume. """ if volume == 0: return 0 depth = self.get_depth() if depth["bids"][0]["price"] == 0: return 0 volume = self.remove_fee(volume) if currency == self.amount_currency: gross = Decimal(str(volume)) * Decimal(str(depth["asks"][0]["price"])) elif currency == self.price_currency: gross = Decimal(str(volume)) / Decimal(str(depth["bids"][0]["price"])) else: self._raise_currency_exception(currency) return float(gross.quantize(Decimal('1.00000000')))
def html_scientific_notation_rate(rate): """Helper for convert decimal rate using scientific notation. For example we want to show the very detail value of fatality rate because it might be a very small number. :param rate: Rate value :type rate: float :return: Rate value with html tag to show the exponent :rtype: str """ precision = '%.3f' if rate * 100 > 0: decimal_rate = Decimal(precision % (rate * 100)) if decimal_rate == Decimal((precision % 0)): decimal_rate = Decimal(str(rate * 100)) else: decimal_rate = Decimal(str(rate * 100)) if decimal_rate.as_tuple().exponent >= -3: rate_percentage = str(decimal_rate) else: rate = '%.2E' % decimal_rate html_rate = rate.split('E') # we use html tag to show exponent html_rate[1] = '10<sup>{exponent}</sup>'.format( exponent=html_rate[1]) html_rate.insert(1, 'x') rate_percentage = ''.join(html_rate) return rate_percentage
def format_price(price, currency, decimal_pos=None): if not currency: return price if decimal_pos is None: decimal_pos = currency.decimal_places d = Decimal(str(price)) if decimal_pos == 0: exp = Decimal(1) else: exp = Decimal('1.0') / (Decimal(10)**abs(decimal_pos)) formatted_price = numberformat.format( u'%s' % str(d.quantize(exp, ROUND_HALF_UP)), currency.decimal_separator, abs(decimal_pos), grouping=3, thousand_sep=currency.thousand_separator) if currency.symbol_preceeds: params = (currency.symbol, formatted_price) else: params = (formatted_price, currency.symbol) return u'%s %s' % params
def corpo_IX_observacoes_contribuinte(self): infCpl = self.root.findtext('./infCFe/infAdic/infCpl') vCFeLei12741 = Decimal( self.root.findtext('./infCFe/total/vCFeLei12741') or 0) if infCpl or not vCFeLei12741.is_zero(): self.normal() self.esquerda() self.separador() self.negrito() self.texto(u'OBSERVAÇÕES DO CONTRIBUINTE') self.negrito() if infCpl: self.condensado() self.quebrar(infCpl) self.condensado() if not vCFeLei12741.is_zero(): self.condensado() self.quebrar(u'Valor aproximado dos tributos deste cupom') self.bordas( u'(Lei Fed. 12.741/2012) R$', '{:n}'.format(vCFeLei12741)) self.condensado()
def get_custom_balance(cls, accounts, name): balances = {} for account in accounts: balance = Decimal() if account.is_current_capital == True: balance = account.get_difference_between_childs() elif account.is_recommended_capital == True: balance = account.get_recommended_capital() elif account.is_cash == True: balance = account.get_cash() elif account.is_current_liability == True: balance = account.get_current_liability() elif account.is_current_asset == True: balance = account.get_current_asset() elif account.is_revenue == True: balance = account.get_revenues() elif account.is_expense == True: balance = account.get_expenses() elif account.type == 'root': balance = account.get_difference_between_childs() if account.display_balance == 'credit-debit' and balance: balance *= -1 exp = Decimal(str(10.0 ** -account.currency_digits)) balances[account.id] = balance.quantize(exp) return balances
def chakra(N): b = Decimal(1) k = Decimal(0) while not issquare(k + N): k = k + 1 l = Decimal(0) while not issquare(l + N): l = l - 1 if abs(l) < abs(k): k = l a = Decimal(k + N).sqrt() while k != 1 or (not isnatural(a) or not isnatural(b)): #print a, b, k d = [a, b, k] if k.copy_abs() == 4: [a, b, k] = [a / 2, b / 2, k / 4] continue if k == 1: while not isnatural(a) or not isnatural(b): [a, b, k] = compose([a, b, k], d, N) continue if k == -1: [a, b, k] = compose(d, d, N) while not isnatural(a) or not isnatural(b): [a, b, k] = compose([a, b, k], d, N) continue if k.copy_abs() == 2: [a, b, k] = compose(d, d, N) continue m = findm(a, b, k, N) [a, b, k] = [(a * m + N * b) / k.copy_abs(), (a + m * b) / k.copy_abs(), (m ** 2 - N) / k] return a, b, k
def get_int_exp(str_n): # makes int from fractional by multiplying by 10 # as much time as needed to get int n = Decimal(str_n) sign, digits, exp = n.as_tuple() int_n = int(n*10**(-exp)) return (abs(int_n), exp)
def _create_cache_key(lat, lng): key_parts = [] for float_num in lat, lng: decimal_num = Decimal(float_num) decimal_num = decimal_num.quantize(Decimal('1.0')) key_parts.append(str(decimal_num)) return ';'.join(key_parts)
def charge(self, amount): """ Charges the users credit card, with he passed $amount, if they are in the vault. Returns the payment_log instance or None (if charge fails etc.) """ # TODO: refactor! This is not how such operations should be done. amount = Decimal(amount) try: result = Transaction.sale( { 'amount': amount.quantize(Decimal('.01')), 'customer_id': self.vault_id, 'options': { 'submit_for_settlement': True } } ) if result.is_success: # create a payment log payment_log = PaymentLog.objects.create(user=self.user, amount=amount, transaction_id=result.transaction.id) return payment_log else: logging.error("Bad braintree response %s" % result) raise Exception("Logical error in CC transaction") except Exception, e: logging.error("Failed to charge $%s to user:"******" %s with vault_id: %s error was %s" % (amount, self.user, self.vault_id, e)) return None
def __setitem__(self, key, value): try: key = key.upper() except AttributeError: raise AttributeError('Keys stored as upper-case strings: %s unsuitable' % (key)) value = Decimal(value) if key in self.keys() and not 'CURRENT' in key: # Validate choosing more detailed value for variable existing_exp = self[key].as_tuple().exponent # 0.1111 --> -4 candidate_exp = value.as_tuple().exponent if existing_exp > candidate_exp: # candidate has more digits places = Decimal(10) ** (existing_exp + 1) # exp+1 permits slack in rounding best_value = value else: # existing has more digits places = Decimal(10) ** (candidate_exp + 1) best_value = self[key] # Validate values are the same places = max(places, Decimal('1E-11')) # for computed psivars #print('FLOOR: ', self[key].quantize(places, rounding=ROUND_FLOOR) - value.quantize(places, rounding=ROUND_FLOOR)) #print('CEIL: ', self[key].quantize(places, rounding=ROUND_CEILING) - value.quantize(places, rounding=ROUND_CEILING)) if (self[key].quantize(places, rounding=ROUND_CEILING).compare(value.quantize(places, rounding=ROUND_CEILING)) != 0) and \ (self[key].quantize(places, rounding=ROUND_FLOOR).compare(value.quantize(places, rounding=ROUND_FLOOR)) != 0): raise ParsingValidationError( """Output file yielded both %s and %s as values for quantity %s.""" % (self[key].to_eng_string(), value.to_eng_string(), key)) #print 'Resetting variable %s to %s' % (key, best_value.to_eng_string()) else: best_value = value #print 'Setting variable %s to %s' % (key, best_value.to_eng_string()) super(PreservingDict, self).__setitem__(key, best_value)
def PHI2(n=2): ''' PHI(int) -> Decimal -- returns (1+√5)/2 to int precision, increasing the precision of Decimal if required''' from decimal import Context,Decimal dot100 = Context(prec=n) d5 = Decimal(5) s5 = d5.sqrt(dot100) return (1 + s5)/2
def _tipo_para_string(valor, tipo, obrigatorio, dec_min): if (not obrigatorio) and (not valor): return '', '' decimais = '' # Cuidado!!! # Aqui não dá pra usar a função strftime pois em alguns # casos a data retornada é 01/01/0001 00:00:00 # e a função strftime só aceita data com anos a partir de 1900 if (tipo in ('d', 'h', 'dh')) and isinstance(valor, (datetime, date, time,)): valor = formata_datahora(valor, tipo) elif (tipo == 'n') and isinstance(valor, (int, long, float, Decimal)): if isinstance(valor, (int, long, float)): valor = Decimal(unicode(valor)) valor = unicode(valor).strip() if '.' in valor: decimais = valor.split('.')[1] if dec_min: decimais = decimais.ljust(dec_min, '0') if '.' in valor: valor = valor.split('.')[0] valor += '.' + decimais return valor, decimais
def format_amount(self, satoshis): if self.amount_format == 'satoshis': return str(satoshis) elif self.amount_format == 'coins': amount = Decimal(satoshis) / pow(10, 8) amount = amount.quantize(Decimal('0.00000001'), rounding=decimal.ROUND_DOWN) return '{:f}'.format(amount)
def get_pending_amount(cls, agents, name): pool = Pool() Commission = pool.get('commission') commission = Commission.__table__() cursor = Transaction().connection.cursor() ids = [a.id for a in agents] amounts = dict.fromkeys(ids, None) for sub_ids in grouped_slice(ids): where = reduce_ids(commission.agent, sub_ids) where &= commission.invoice_line == Null query = commission.select(commission.agent, Sum(commission.amount), where=where, group_by=commission.agent) cursor.execute(*query) amounts.update(dict(cursor.fetchall())) digits = cls.pending_amount.digits exp = Decimal(str(10.0 ** -digits[1])) for agent_id, amount in amounts.items(): if amount: # SQLite uses float for SUM if not isinstance(amount, Decimal): amount = Decimal(str(amount)) amounts[agent_id] = amount.quantize(exp) return amounts
def redondear(formato, clave, valor): from formato_txt import A, N, I # corregir redondeo (aparentemente sqlite no guarda correctamente los decimal) import decimal try: long = [fmt[1] for fmt in formato if fmt[0]==clave] tipo = [fmt[2] for fmt in formato if fmt[0]==clave] if not tipo: return valor tipo = tipo[0] if DEBUG: print "tipo", tipo, clave, valor, long if valor is None: return None if valor == "": return "" if tipo == A: return valor if tipo == N: return int(valor) if isinstance(valor, (int, float)): valor = str(valor) if isinstance(valor, basestring): valor = Decimal(valor) if long and isinstance(long[0], (tuple, list)): decimales = Decimal('1') / Decimal(10**(long[0][1])) else: decimales = Decimal('.01') valor1 = valor.quantize(decimales, rounding=decimal.ROUND_DOWN) if valor != valor1 and DEBUG: print "REDONDEANDO ", clave, decimales, valor, valor1 return valor1 except Exception as e: print "IMPOSIBLE REDONDEAR:", clave, valor, e
def decode(data): """From a string formatted as specified in the RFC2616, it builds a data structure which provides a high level interface to implement language negotiation. """ data = data.strip() if not data: return AcceptLanguage({}) accept = {} for language in data.lower().split(','): language = language.strip() if ';' in language: language, quality = language.split(';') # Get the number (remove "q=") quality = Decimal(quality.strip()[2:]) else: quality = one if language == '*': language = '' accept[language] = quality return AcceptLanguage(accept)
def moneyfmt( value, places=2, curr='', sep=',', dp='.', pos='', neg='-', trailneg='' ): """Convert Decimal to a money formatted string. places: required number of places after the decimal point curr: optional currency symbol before the sign (may be blank) sep: optional grouping separator (comma, period, space, or blank) dp: decimal point indicator (comma or period) only specify as blank when places is zero pos: optional sign for positive numbers: '+', space or blank neg: optional sign for negative numbers: '-', '(', space or blank trailneg:optional trailing minus indicator: '-', ')', space or blank >>> d = Decimal('-1234567.8901') >>> moneyfmt(d, curr='$') '-$1,234,567.89' >>> moneyfmt(d, places=0, sep='.', dp='', neg='', trailneg='-') '1.234.568-' >>> moneyfmt(d, curr='$', neg='(', trailneg=')') '($1,234,567.89)' >>> moneyfmt(Decimal(123456789), sep=' ') '123 456 789.00' >>> moneyfmt(Decimal('-0.02'), neg='<', trailneg='>') '<0.02>' From: https://docs.python.org/3/library/decimal.html#recipes """ if type(value) != Decimal: value = Decimal(value) q = Decimal(10) ** -places # 2 places --> '0.01' sign, digits, exp = value.quantize(q).as_tuple() result = [] digits = list(map(str, digits)) build, next = result.append, digits.pop if sign: build(trailneg) for i in range(places): build(next() if digits else '0') if places: build(dp) if not digits: build('0') i = 0 while digits: build(next()) i += 1 if i == 3 and digits: i = 0 build(sep) build(curr) build(neg if sign else pos) return ''.join(reversed(result))
def test_floats_in_tiny_interval_within_bounds(data, center): assume(not (math.isinf(next_down(center)) or math.isinf(next_up(center)))) lo = Decimal.from_float(next_down(center)).next_plus() hi = Decimal.from_float(next_up(center)).next_minus() assert float(lo) < lo < center < hi < float(hi) val = data.draw(st.floats(lo, hi)) assert lo < val < hi
def __eq__(self, other): if isinstance(other, Money): return Decimal.__eq__(self, other) elif isinstance(other, six.integer_types + (float, Decimal)): return Decimal.__eq__(self, self._sanitize(other)) else: return False
def decimal_places(arg): """ Returns the number of decimal places in the given number Parameters ---------- arg: Numeric or string A number to determine the number of decimal places Returns ------- Number of decimal places found. Raises ------ IllegalArgumentException if argument is not numeric. """ if not is_number(str(arg)): raise IllegalArgumentException("[{0}] is not a number".format(arg)) dec = Decimal(str(arg)) exp = dec.as_tuple().exponent result = -exp return result
def export_attr_edits(cls, attrs): edits_iter = iter_attr_edits(cls, attrs) maxes = dict.fromkeys(attrs, 0) totals = dict.fromkeys(attrs, 0) count = 0 for pk, attr_times in edits_iter: for a in attrs: maxes[a] = max(maxes[a], len(attr_times[a])) totals[a] += len(attr_times[a]) count += 1 edits = OrderedDict() for a in attrs: if count == 0: edits[a] = { 'max': 0, 'avg': Decimal('0.00'), } else: avg = Decimal(totals[a]) / count edits[a] = { 'max': maxes[a], 'avg': avg.quantize(Decimal('0.01')), } return edits
def money_format(value, places=2, curr='$', sep=',', dp='.', pos='', neg='-', trailneg=''): try: value = Decimal(value) except: raise Exception("Failed to convert '{}' to Decimal".format(value)) q = Decimal(10) ** -places # 2 places --> '0.01' sign, digits, exp = value.quantize(q).as_tuple() result = [] digits = map(str, digits) build, next = result.append, digits.pop if sign: build(trailneg) for i in range(places): build(next() if digits else '0') build(dp) if not digits: build('0') i = 0 while digits: build(next()) i += 1 if i == 3 and digits: i = 0 build(sep) build(curr) build(neg if sign else pos) return ''.join(reversed(result))
def round_decimal(raw_val, decimals=1, track_significance=False): ''' Round to the specified decimals @param track_significance if True then remove trailing zeros @return Decimal representing the rounded raw_val as a decimal ''' assert decimals >= 0, 'decimals must be >= 0' if raw_val is None: return None val = Decimal(raw_val) logger.debug('convert_decimal: %r, %r, %r, %r', raw_val, decimals, track_significance) # Convert the decimal argument to a Decimal value decimals = Decimal('1e-%d'%int(decimals)) # Quantize: Return a value equal to the first operand after rounding and # having the exponent of the second operand. (see python doc) val = val.quantize(decimals, decimal.ROUND_HALF_UP) if track_significance is False: val = remove_exponent(val) return val
def set_content(self, addr, label, amount, currency): self.address = addr address_text = "<span style='font-size: 18pt'>%s</span>" % addr if addr else "" self.address_label.setText(address_text) if currency == 'BTC': currency = None amount_text = '' if amount: if currency: self.amount = Decimal(amount) / self.exchanger.exchange(1, currency) if currency else amount else: self.amount = Decimal(amount) self.amount = self.amount.quantize(Decimal('1.0000')) if currency: amount_text += "<span style='font-size: 18pt'>%s %s</span><br/>" % (amount, currency) amount_text += "<span style='font-size: 21pt'>%s</span> <span style='font-size: 16pt'>BTC</span> " % str(self.amount) self.amount_label.setText(amount_text) self.label = label label_text = "<span style='font-size: 21pt'>%s</span>" % label if label else "" self.label_label.setText(label_text) msg = 'bitcoin:'+self.address if self.amount is not None: msg += '?amount=%s'%(str( self.amount)) if self.label is not None: msg += '&label=%s'%(self.label) elif self.label is not None: msg += '?label=%s'%(self.label) self.qrw.set_addr( msg )
def staffdiscount(tablenumber,item): if tablenumber!=1234: return zero discount=item.price*Decimal("0.4") if discount>Decimal("3.00"): discount=Decimal("3.00") discount=discount.quantize(Decimal("0.1"),rounding=ROUND_UP) discount=discount.quantize(penny) return discount
def print_si_unit(raw_val, default_unit, symbol, decimals=1, multiplier=1, track_significance=False): if raw_val is None: return None val = Decimal(raw_val) if multiplier is not None: # get the scale (exponent) of the multiplier multiplier = Decimal(str(multiplier)).adjusted() val = val.scaleb(multiplier) # NOTE: convert to string to avoid float numeric errors default_unit = Decimal(str(default_unit)) if val >= default_unit: return '{} {}{}'.format( convert_decimal( val,default_unit, decimals, track_significance=track_significance), get_siunit_symbol(default_unit), symbol) else: (unit_symbol,default_unit) = get_siunit(val) return '{} {}{}'.format( convert_decimal( val,default_unit, decimals, track_significance=track_significance), unit_symbol, symbol)
def calculate_tax(table_name, table_type, value): """ Calculate the tax based on the table name and the table type. :param table_name: this is the name of the table, federal/state. :param table_type: this is the type of the table, 'single', 'married', etc. :param value: value of income to calculate the tax for. :return: """ current_tax = Decimal('0.0') previous_maximum = Decimal('0.0') table = _tax_tables.get(table_name, dict()).get(table_type, None) if table is None: raise AttributeError('Unknown table type: %s' % table_type) for tax_bracket in table: max_value = Decimal('0.0') if 'maximum' in tax_bracket: if previous_maximum < value: max_value = min(value - previous_maximum, tax_bracket['maximum'] - previous_maximum) previous_maximum = tax_bracket['maximum'] else: if previous_maximum < value: max_value = value - previous_maximum current_tax += tax_bracket['rate'] * max_value current_tax = current_tax.to_integral_value('ROUND_HALF_UP') return current_tax
def test_get_total_penalty(self): method = PaymentMethod.get_by_name(self.store, u'check') # Test for a group in a sale # On sale's group, total value should return # sum(inpayments.penalty) - sum(outpayments.penalty) sale = self.create_sale() group = sale.group self.assertEqual(group.get_total_value(), 0) p = method.create_payment(Payment.TYPE_IN, group, sale.branch, Decimal(10)) p.penalty = Decimal(10) self.assertEqual(group.get_total_penalty(), Decimal(10)) p = method.create_payment(Payment.TYPE_IN, group, sale.branch, Decimal(10)) p.penalty = Decimal(20) self.assertEqual(group.get_total_penalty(), Decimal(30)) p = method.create_payment(Payment.TYPE_OUT, group, sale.branch, Decimal(10)) p.penalty = Decimal(10) self.assertEqual(group.get_total_penalty(), Decimal(20)) # Test for a group in a purchase # On purchase's group, total value should return # sum(inpayments.penalty) - sum(outpayments.penalty) purchase = self.create_purchase_order() group = purchase.group self.assertEqual(group.get_total_value(), 0) p = method.create_payment(Payment.TYPE_OUT, group, purchase.branch, Decimal(10)) p.penalty = Decimal(10) self.assertEqual(group.get_total_penalty(), Decimal(10)) p = method.create_payment(Payment.TYPE_OUT, group, purchase.branch, Decimal(10)) p.penalty = Decimal(20) self.assertEqual(group.get_total_penalty(), Decimal(30)) p = method.create_payment(Payment.TYPE_IN, group, purchase.branch, Decimal(10)) p.penalty = Decimal(10) self.assertEqual(group.get_total_penalty(), Decimal(20))
class OrderLine(models.Model): order = models.ForeignKey( Order, related_name="lines", editable=False, on_delete=models.CASCADE ) variant = models.ForeignKey( "product.ProductVariant", related_name="order_lines", on_delete=models.SET_NULL, blank=True, null=True, ) # max_length is as produced by ProductVariant's display_product method product_name = models.CharField(max_length=386) variant_name = models.CharField(max_length=255, default="", blank=True) translated_product_name = models.CharField(max_length=386, default="", blank=True) translated_variant_name = models.CharField(max_length=255, default="", blank=True) product_sku = models.CharField(max_length=255, null=True, blank=True) # str with GraphQL ID used as fallback when product SKU is not available product_variant_id = models.CharField(max_length=255, null=True, blank=True) is_shipping_required = models.BooleanField() is_gift_card = models.BooleanField() quantity = models.IntegerField(validators=[MinValueValidator(1)]) quantity_fulfilled = models.IntegerField( validators=[MinValueValidator(0)], default=0 ) currency = models.CharField( max_length=settings.DEFAULT_CURRENCY_CODE_LENGTH, ) unit_discount_amount = models.DecimalField( max_digits=settings.DEFAULT_MAX_DIGITS, decimal_places=settings.DEFAULT_DECIMAL_PLACES, default=0, ) unit_discount = MoneyField( amount_field="unit_discount_amount", currency_field="currency" ) unit_discount_type = models.CharField( max_length=10, choices=DiscountValueType.CHOICES, default=DiscountValueType.FIXED, ) unit_discount_reason = models.TextField(blank=True, null=True) unit_price_net_amount = models.DecimalField( max_digits=settings.DEFAULT_MAX_DIGITS, decimal_places=settings.DEFAULT_DECIMAL_PLACES, ) # stores the value of the applied discount. Like 20 of % unit_discount_value = models.DecimalField( max_digits=settings.DEFAULT_MAX_DIGITS, decimal_places=settings.DEFAULT_DECIMAL_PLACES, default=0, ) unit_price_net = MoneyField( amount_field="unit_price_net_amount", currency_field="currency" ) unit_price_gross_amount = models.DecimalField( max_digits=settings.DEFAULT_MAX_DIGITS, decimal_places=settings.DEFAULT_DECIMAL_PLACES, ) unit_price_gross = MoneyField( amount_field="unit_price_gross_amount", currency_field="currency" ) unit_price = TaxedMoneyField( net_amount_field="unit_price_net_amount", gross_amount_field="unit_price_gross_amount", currency="currency", ) total_price_net_amount = models.DecimalField( max_digits=settings.DEFAULT_MAX_DIGITS, decimal_places=settings.DEFAULT_DECIMAL_PLACES, ) total_price_net = MoneyField( amount_field="total_price_net_amount", currency_field="currency", ) total_price_gross_amount = models.DecimalField( max_digits=settings.DEFAULT_MAX_DIGITS, decimal_places=settings.DEFAULT_DECIMAL_PLACES, ) total_price_gross = MoneyField( amount_field="total_price_gross_amount", currency_field="currency", ) total_price = TaxedMoneyField( net_amount_field="total_price_net_amount", gross_amount_field="total_price_gross_amount", currency="currency", ) undiscounted_unit_price_gross_amount = models.DecimalField( max_digits=settings.DEFAULT_MAX_DIGITS, decimal_places=settings.DEFAULT_DECIMAL_PLACES, default=0, ) undiscounted_unit_price_net_amount = models.DecimalField( max_digits=settings.DEFAULT_MAX_DIGITS, decimal_places=settings.DEFAULT_DECIMAL_PLACES, default=0, ) undiscounted_unit_price = TaxedMoneyField( net_amount_field="undiscounted_unit_price_net_amount", gross_amount_field="undiscounted_unit_price_gross_amount", currency="currency", ) undiscounted_total_price_gross_amount = models.DecimalField( max_digits=settings.DEFAULT_MAX_DIGITS, decimal_places=settings.DEFAULT_DECIMAL_PLACES, default=0, ) undiscounted_total_price_net_amount = models.DecimalField( max_digits=settings.DEFAULT_MAX_DIGITS, decimal_places=settings.DEFAULT_DECIMAL_PLACES, default=0, ) undiscounted_total_price = TaxedMoneyField( net_amount_field="undiscounted_total_price_net_amount", gross_amount_field="undiscounted_total_price_gross_amount", currency="currency", ) tax_rate = models.DecimalField( max_digits=5, decimal_places=4, default=Decimal("0.0") ) # Fulfilled when voucher code was used for product in the line voucher_code = models.CharField(max_length=255, null=True, blank=True) # Fulfilled when sale was applied to product in the line sale_id = models.CharField(max_length=255, null=True, blank=True) objects = models.Manager.from_queryset(OrderLineQueryset)() class Meta: ordering = ("pk",) def __str__(self): return ( f"{self.product_name} ({self.variant_name})" if self.variant_name else self.product_name ) @property def quantity_unfulfilled(self): return self.quantity - self.quantity_fulfilled @property def is_digital(self) -> Optional[bool]: """Check if a variant is digital and contains digital content.""" if not self.variant: return None is_digital = self.variant.is_digital() has_digital = hasattr(self.variant, "digital_content") return is_digital and has_digital
import sys import copy from decimal import Decimal, ROUND_DOWN from colorama import Fore from ...config import config from ..out_record import TransactionOutRecord from ..dataparser import DataParser from ..exceptions import DataRowError, UnexpectedTypeError WALLET = "Hotbit" PRECISION = Decimal('0.00000000') MAKER_FEE = Decimal(0.0005) TAKER_FEE = Decimal(0.002) def parse_hotbit_orders_v3(data_rows, parser, **kwargs): parse_hotbit_orders_v1(data_rows, parser, type_str='Side', amount_str='Volume', **kwargs) def parse_hotbit_orders_v2(data_rows, parser, **kwargs): parse_hotbit_orders_v1(data_rows, parser, type_str='Side', amount_str='Amount', **kwargs) def parse_hotbit_orders_v1(data_rows, parser, **kwargs): if kwargs.get('type_str'): type_str = kwargs['type_str'] else: type_str = 'Type'
solution.solution('77') Output: 4208 Input: solution.solution('5') Output: 19 FOR PYTHON 2.7 """ from decimal import Decimal, getcontext getcontext().prec = 101 r = Decimal(2).sqrt() p = r - 1 def solution(str_n): n = long(str_n) def beatty_sequence(n): if n == 1: return 1 if n < 1: return 0 m = long(p*n) return n*m + (n*(n+1))//2 - (m*(m+1))//2 - beatty_sequence(m) return str(ans)
def run_test(self): #prepare some coins for multiple *rawtransaction commands self.nodes[2].generate(1) self.sync_all() self.nodes[0].generate(101) self.sync_all() self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(),1.5); self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(),1.0); self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(),5.0); self.sync_all() self.nodes[0].generate(5) self.sync_all() ######################################### # sendrawtransaction with missing input # ######################################### inputs = [ {'txid' : "1d1d4e24ed99057e84c3f80fd8fbec79ed9e1acee37da269356ecea000000000", 'vout' : 1}] #won't exists outputs = { self.nodes[0].getnewaddress() : 4.998 } rawtx = self.nodes[2].createrawtransaction(inputs, outputs) rawtx = self.nodes[2].signrawtransaction(rawtx) errorString = "" try: rawtx = self.nodes[2].sendrawtransaction(rawtx['hex']) except JSONRPCException as e: errorString = e.error['message'] assert_equal("Missing inputs" in errorString, True); ##################################### # getrawtransaction with block hash # ##################################### # make a tx by sending then generate 2 blocks; block1 has the tx in it tx = self.nodes[2].sendtoaddress(self.nodes[1].getnewaddress(), 1) block1, block2 = self.nodes[2].generate(2) self.sync_all() # We should be able to get the raw transaction by providing the correct block gottx = self.nodes[0].getrawtransaction(tx, 1, block1) assert_equal(gottx['txid'], tx) assert_equal(gottx['in_active_chain'], True) # We should not have the 'in_active_chain' flag when we don't provide a block gottx = self.nodes[0].getrawtransaction(tx, 1) assert_equal(gottx['txid'], tx) assert 'in_active_chain' not in gottx # We should have hex for the transaction from the getblock and getrawtransaction calls. blk = self.nodes[0].getblock(block1, 2) assert_equal(gottx['hex'], blk['tx'][1]['hex']) # We should not get the tx if we provide an unrelated block assert_raises(JSONRPCException, self.nodes[0].getrawtransaction, tx, 1, block2) # An invalid block hash should raise errors assert_raises(JSONRPCException, self.nodes[0].getrawtransaction, tx, 1, True) assert_raises(JSONRPCException, self.nodes[0].getrawtransaction, tx, 1, "foobar") assert_raises(JSONRPCException, self.nodes[0].getrawtransaction, tx, 1, "abcd1234") assert_raises(JSONRPCException, self.nodes[0].getrawtransaction, tx, 1, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa") ######################### # RAW TX MULTISIG TESTS # ######################### # 2of2 test addr1 = self.nodes[2].getnewaddress() addr2 = self.nodes[2].getnewaddress() addr1Obj = self.nodes[2].validateaddress(addr1) addr2Obj = self.nodes[2].validateaddress(addr2) mSigObj = self.nodes[2].addmultisigaddress(2, [addr1Obj['pubkey'], addr2Obj['pubkey']]) mSigObjValid = self.nodes[2].validateaddress(mSigObj) #use balance deltas instead of absolute values bal = self.nodes[2].getbalance() # send 1.2 BTC to msig adr txId = self.nodes[0].sendtoaddress(mSigObj, 1.2); self.sync_all() self.nodes[0].generate(1) self.sync_all() assert_equal(self.nodes[2].getbalance(), bal+Decimal('1.20000000')) #node2 has both keys of the 2of2 ms addr., tx should affect the balance # 2of3 test from different nodes bal = self.nodes[2].getbalance() addr1 = self.nodes[1].getnewaddress() addr2 = self.nodes[2].getnewaddress() addr3 = self.nodes[2].getnewaddress() addr1Obj = self.nodes[1].validateaddress(addr1) addr2Obj = self.nodes[2].validateaddress(addr2) addr3Obj = self.nodes[2].validateaddress(addr3) mSigObj = self.nodes[2].addmultisigaddress(2, [addr1Obj['pubkey'], addr2Obj['pubkey'], addr3Obj['pubkey']]) mSigObjValid = self.nodes[2].validateaddress(mSigObj) assert_equal(mSigObjValid['isvalid'], True) txId = self.nodes[0].sendtoaddress(mSigObj, 2.2); decTx = self.nodes[0].gettransaction(txId) rawTx = self.nodes[0].decoderawtransaction(decTx['hex']) sPK = rawTx['vout'][0]['scriptPubKey']['hex'] [sPK] # hush pyflakes self.sync_all() self.nodes[0].generate(1) self.sync_all() # THIS IS A INCOMPLETE FEATURE # NODE2 HAS TWO OF THREE KEY AND THE FUNDS SHOULD BE SPENDABLE AND COUNT AT BALANCE CALCULATION assert_equal(self.nodes[2].getbalance(), bal) # for now, assume the funds of a 2of3 multisig tx are not marked as spendable txDetails = self.nodes[0].gettransaction(txId, True) rawTx = self.nodes[0].decoderawtransaction(txDetails['hex']) vout = False for outpoint in rawTx['vout']: if outpoint['value'] == Decimal('2.20000000'): vout = outpoint break; bal = self.nodes[0].getbalance() inputs = [{ "txid" : txId, "vout" : vout['n'], "scriptPubKey" : vout['scriptPubKey']['hex'], "amount" : vout['value']}] outputs = { self.nodes[0].getnewaddress() : 2.199 } rawTx = self.nodes[2].createrawtransaction(inputs, outputs) rawTxPartialSigned = self.nodes[1].signrawtransaction(rawTx, inputs) assert_equal(rawTxPartialSigned['complete'], False) # node1 only has one key, can't comp. sign the tx rawTxSigned = self.nodes[2].signrawtransaction(rawTx, inputs) assert_equal(rawTxSigned['complete'], True) # node2 can sign the tx compl., own two of three keys self.nodes[2].sendrawtransaction(rawTxSigned['hex']) rawTx = self.nodes[0].decoderawtransaction(rawTxSigned['hex']) self.sync_all() self.nodes[0].generate(1) self.sync_all() assert_equal(self.nodes[0].getbalance(), bal+Decimal('97.00000000')+Decimal('2.19900000')) #block reward + tx inputs = [ {'txid' : "1d1d4e24ed99057e84c3f80fd8fbec79ed9e1acee37da269356ecea000000000", 'vout' : 1, 'sequence' : 1000}] outputs = { self.nodes[0].getnewaddress() : 1 } rawtx = self.nodes[0].createrawtransaction(inputs, outputs) decrawtx= self.nodes[0].decoderawtransaction(rawtx) assert_equal(decrawtx['vin'][0]['sequence'], 1000)
response = authorized_client.get(url) assert product in response.context_data["products"][0] @patch("saleor.product.thumbnails.create_thumbnails") def test_create_product_thumbnails(mock_create_thumbnails, product_with_image): product_image = product_with_image.images.first() create_product_thumbnails(product_image.pk) assert mock_create_thumbnails.called_once_with( product_image.pk, models.ProductImage, "products" ) @pytest.mark.parametrize( "expected_price, include_discounts", [(Decimal("10.00"), True), (Decimal("15.0"), False)], ) def test_get_price( product_type, category, sale, expected_price, include_discounts, site_settings, discount_info, ): product = models.Product.objects.create( product_type=product_type, category=category, price=Money(Decimal("15.00"), "USD"), )
class Order(ModelWithMetadata): created = models.DateTimeField(default=now, editable=False) status = models.CharField( max_length=32, default=OrderStatus.UNFULFILLED, choices=OrderStatus.CHOICES ) user = models.ForeignKey( settings.AUTH_USER_MODEL, blank=True, null=True, related_name="orders", on_delete=models.SET_NULL, ) language_code = models.CharField( max_length=35, choices=settings.LANGUAGES, default=settings.LANGUAGE_CODE ) tracking_client_id = models.CharField(max_length=36, blank=True, editable=False) billing_address = models.ForeignKey( "account.Address", related_name="+", editable=False, null=True, on_delete=models.SET_NULL, ) shipping_address = models.ForeignKey( "account.Address", related_name="+", editable=False, null=True, on_delete=models.SET_NULL, ) user_email = models.EmailField(blank=True, default="") original = models.ForeignKey( "self", null=True, blank=True, on_delete=models.SET_NULL ) origin = models.CharField(max_length=32, choices=OrderOrigin.CHOICES) currency = models.CharField( max_length=settings.DEFAULT_CURRENCY_CODE_LENGTH, ) shipping_method = models.ForeignKey( ShippingMethod, blank=True, null=True, related_name="orders", on_delete=models.SET_NULL, ) collection_point = models.ForeignKey( "warehouse.Warehouse", blank=True, null=True, related_name="orders", on_delete=models.SET_NULL, ) shipping_method_name = models.CharField( max_length=255, null=True, default=None, blank=True, editable=False ) collection_point_name = models.CharField( max_length=255, null=True, default=None, blank=True, editable=False ) channel = models.ForeignKey( Channel, related_name="orders", on_delete=models.PROTECT, ) shipping_price_net_amount = models.DecimalField( max_digits=settings.DEFAULT_MAX_DIGITS, decimal_places=settings.DEFAULT_DECIMAL_PLACES, default=0, editable=False, ) shipping_price_net = MoneyField( amount_field="shipping_price_net_amount", currency_field="currency" ) shipping_price_gross_amount = models.DecimalField( max_digits=settings.DEFAULT_MAX_DIGITS, decimal_places=settings.DEFAULT_DECIMAL_PLACES, default=0, editable=False, ) shipping_price_gross = MoneyField( amount_field="shipping_price_gross_amount", currency_field="currency" ) shipping_price = TaxedMoneyField( net_amount_field="shipping_price_net_amount", gross_amount_field="shipping_price_gross_amount", currency_field="currency", ) shipping_tax_rate = models.DecimalField( max_digits=5, decimal_places=4, default=Decimal("0.0") ) token = models.CharField(max_length=36, unique=True, blank=True) # Token of a checkout instance that this order was created from checkout_token = models.CharField(max_length=36, blank=True) total_net_amount = models.DecimalField( max_digits=settings.DEFAULT_MAX_DIGITS, decimal_places=settings.DEFAULT_DECIMAL_PLACES, default=0, ) undiscounted_total_net_amount = models.DecimalField( max_digits=settings.DEFAULT_MAX_DIGITS, decimal_places=settings.DEFAULT_DECIMAL_PLACES, default=0, ) total_net = MoneyField(amount_field="total_net_amount", currency_field="currency") undiscounted_total_net = MoneyField( amount_field="undiscounted_total_net_amount", currency_field="currency" ) total_gross_amount = models.DecimalField( max_digits=settings.DEFAULT_MAX_DIGITS, decimal_places=settings.DEFAULT_DECIMAL_PLACES, default=0, ) undiscounted_total_gross_amount = models.DecimalField( max_digits=settings.DEFAULT_MAX_DIGITS, decimal_places=settings.DEFAULT_DECIMAL_PLACES, default=0, ) total_gross = MoneyField( amount_field="total_gross_amount", currency_field="currency" ) undiscounted_total_gross = MoneyField( amount_field="undiscounted_total_gross_amount", currency_field="currency" ) total = TaxedMoneyField( net_amount_field="total_net_amount", gross_amount_field="total_gross_amount", currency_field="currency", ) undiscounted_total = TaxedMoneyField( net_amount_field="undiscounted_total_net_amount", gross_amount_field="undiscounted_total_gross_amount", currency_field="currency", ) total_paid_amount = models.DecimalField( max_digits=settings.DEFAULT_MAX_DIGITS, decimal_places=settings.DEFAULT_DECIMAL_PLACES, default=0, ) total_paid = MoneyField(amount_field="total_paid_amount", currency_field="currency") voucher = models.ForeignKey( Voucher, blank=True, null=True, related_name="+", on_delete=models.SET_NULL ) gift_cards = models.ManyToManyField(GiftCard, blank=True, related_name="orders") display_gross_prices = models.BooleanField(default=True) customer_note = models.TextField(blank=True, default="") weight = MeasurementField( measurement=Weight, unit_choices=WeightUnits.CHOICES, # type: ignore default=zero_weight, ) redirect_url = models.URLField(blank=True, null=True) search_document = models.TextField(blank=True, default="") objects = models.Manager.from_queryset(OrderQueryset)() class Meta: ordering = ("-pk",) permissions = ((OrderPermissions.MANAGE_ORDERS.codename, "Manage orders."),) indexes = [ *ModelWithMetadata.Meta.indexes, GinIndex( name="order_search_gin", # `opclasses` and `fields` should be the same length fields=["search_document"], opclasses=["gin_trgm_ops"], ), GinIndex( name="order_email_search_gin", # `opclasses` and `fields` should be the same length fields=["user_email"], opclasses=["gin_trgm_ops"], ), ] def save(self, *args, **kwargs): if not self.token: self.token = str(uuid4()) return super().save(*args, **kwargs) def is_fully_paid(self): return self.total_paid >= self.total.gross def is_partly_paid(self): return self.total_paid_amount > 0 def get_customer_email(self): return self.user.email if self.user else self.user_email def update_total_paid(self): self.total_paid_amount = ( sum(self.payments.values_list("captured_amount", flat=True)) or 0 ) self.save(update_fields=["total_paid_amount"]) def _index_billing_phone(self): return self.billing_address.phone def _index_shipping_phone(self): return self.shipping_address.phone def __repr__(self): return "<Order #%r>" % (self.id,) def __str__(self): return "#%d" % (self.id,) def get_last_payment(self): # Skipping a partial payment is a temporary workaround for storing a basic data # about partial payment from Adyen plugin. This is something that will removed # in 3.1 by introducing a partial payments feature. payments = [payment for payment in self.payments.all() if not payment.partial] return max(payments, default=None, key=attrgetter("pk")) def is_pre_authorized(self): return ( self.payments.filter( is_active=True, transactions__kind=TransactionKind.AUTH, transactions__action_required=False, ) .filter(transactions__is_success=True) .exists() ) def is_captured(self): return ( self.payments.filter( is_active=True, transactions__kind=TransactionKind.CAPTURE, transactions__action_required=False, ) .filter(transactions__is_success=True) .exists() ) def is_shipping_required(self): return any(line.is_shipping_required for line in self.lines.all()) def get_subtotal(self): return get_subtotal(self.lines.all(), self.currency) def get_total_quantity(self): return sum([line.quantity for line in self.lines.all()]) def is_draft(self): return self.status == OrderStatus.DRAFT def is_unconfirmed(self): return self.status == OrderStatus.UNCONFIRMED def is_open(self): statuses = {OrderStatus.UNFULFILLED, OrderStatus.PARTIALLY_FULFILLED} return self.status in statuses def can_cancel(self): statuses_allowed_to_cancel = [ FulfillmentStatus.CANCELED, FulfillmentStatus.REFUNDED, FulfillmentStatus.REPLACED, FulfillmentStatus.REFUNDED_AND_RETURNED, FulfillmentStatus.RETURNED, ] return ( not self.fulfillments.exclude( status__in=statuses_allowed_to_cancel ).exists() ) and self.status not in {OrderStatus.CANCELED, OrderStatus.DRAFT} def can_capture(self, payment=None): if not payment: payment = self.get_last_payment() if not payment: return False order_status_ok = self.status not in {OrderStatus.DRAFT, OrderStatus.CANCELED} return payment.can_capture() and order_status_ok def can_void(self, payment=None): if not payment: payment = self.get_last_payment() if not payment: return False return payment.can_void() def can_refund(self, payment=None): if not payment: payment = self.get_last_payment() if not payment: return False return payment.can_refund() def can_mark_as_paid(self, payments=None): if not payments: payments = self.payments.all() return len(payments) == 0 @property def total_authorized(self): return get_total_authorized(self.payments.all(), self.currency) @property def total_captured(self): return self.total_paid @property def total_balance(self): return self.total_captured - self.total.gross def get_total_weight(self, *_args): return self.weight
def collect_and_write_to_csv(currency_from, currency_to, interval, api_key, file_name): # Setup url = "https://www.alphavantage.co/query?function=FX_INTRADAY&" # url = "https://www.alphavantage.co/query?function=FX_DAILY&" url += "from_symbol={}&".format(currency_from) url += "to_symbol={}&".format(currency_to) url += "interval={}&".format(interval) url += "outputsize=full&apikey={}".format(api_key) decimal_places = Decimal(10) ** -8 # Collect response = get(url).json() # Write to file with open(file_name, "w", newline="") as csvfile: field_names = ["Timestamp", "Open", "High", "Low", "Close", "Difference", "Stagnated", "Increased", "Decreased", "Trending Up", "Trending Down"] writer = DictWriter(csvfile, fieldnames=field_names) writer.writeheader() timeseries = response["Time Series FX ({})".format(interval)] for tick in timeseries.items(): timestamp = tick[0] values = tick[1] open_value = Decimal(values["1. open"]).quantize(decimal_places) high_value = Decimal(values["2. high"]).quantize(decimal_places) low_value = Decimal(values["3. low"]).quantize(decimal_places) close_value = Decimal(values["4. close"]).quantize(decimal_places) difference = (close_value - open_value).quantize(decimal_places) if close_value == open_value: difference = 0 increased = 0 if close_value > open_value: increased = 1 decreased = 0 if close_value < open_value: decreased = 1 stagnated = 0 if (increased + decreased) == 0: stagnated = 1 trend_up = 0 trend_down = 0 if determine_trend(open_value, close_value, high_value, low_value): trend_up = 1 else: trend_down = 1 writer.writerow({"Timestamp": timestamp, "Open": open_value, "High": high_value, "Low": low_value, "Close": close_value, "Difference": difference, "Stagnated": stagnated, "Increased": increased, "Decreased": decreased, "Trending Up": trend_up, "Trending Down": trend_down})
def satoshis(amount): # satoshi conversion must not be performed by the parser return int(COIN * Decimal(amount)) if amount not in ['!', None] else amount
def run_test(self): # Create and fund a raw tx for sending 10 XUEZ psbtx1 = self.nodes[0].walletcreatefundedpsbt([], {self.nodes[2].getnewaddress():10})['psbt'] # If inputs are specified, do not automatically add more: utxo1 = self.nodes[0].listunspent()[0] assert_raises_rpc_error(-4, "Insufficient funds", self.nodes[0].walletcreatefundedpsbt, [{"txid": utxo1['txid'], "vout": utxo1['vout']}], {self.nodes[2].getnewaddress():90}) psbtx1 = self.nodes[0].walletcreatefundedpsbt([{"txid": utxo1['txid'], "vout": utxo1['vout']}], {self.nodes[2].getnewaddress():90}, 0, {"add_inputs": True})['psbt'] assert_equal(len(self.nodes[0].decodepsbt(psbtx1)['tx']['vin']), 2) # Inputs argument can be null self.nodes[0].walletcreatefundedpsbt(None, {self.nodes[2].getnewaddress():10}) # Node 1 should not be able to add anything to it but still return the psbtx same as before psbtx = self.nodes[1].walletprocesspsbt(psbtx1)['psbt'] assert_equal(psbtx1, psbtx) # Sign the transaction and send signed_tx = self.nodes[0].walletprocesspsbt(psbtx)['psbt'] final_tx = self.nodes[0].finalizepsbt(signed_tx)['hex'] self.nodes[0].sendrawtransaction(final_tx) # Manually selected inputs can be locked: assert_equal(len(self.nodes[0].listlockunspent()), 0) utxo1 = self.nodes[0].listunspent()[0] psbtx1 = self.nodes[0].walletcreatefundedpsbt([{"txid": utxo1['txid'], "vout": utxo1['vout']}], {self.nodes[2].getnewaddress():1}, 0,{"lockUnspents": True})["psbt"] assert_equal(len(self.nodes[0].listlockunspent()), 1) # Locks are ignored for manually selected inputs self.nodes[0].walletcreatefundedpsbt([{"txid": utxo1['txid'], "vout": utxo1['vout']}], {self.nodes[2].getnewaddress():1}, 0) # Create p2sh, p2wpkh, and p2wsh addresses pubkey0 = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress())['pubkey'] pubkey1 = self.nodes[1].getaddressinfo(self.nodes[1].getnewaddress())['pubkey'] pubkey2 = self.nodes[2].getaddressinfo(self.nodes[2].getnewaddress())['pubkey'] # Setup watchonly wallets self.nodes[2].createwallet(wallet_name='wmulti', disable_private_keys=True) wmulti = self.nodes[2].get_wallet_rpc('wmulti') # Create all the addresses p2sh = wmulti.addmultisigaddress(2, [pubkey0, pubkey1, pubkey2], "", "legacy")['address'] p2wsh = wmulti.addmultisigaddress(2, [pubkey0, pubkey1, pubkey2], "", "bech32")['address'] p2sh_p2wsh = wmulti.addmultisigaddress(2, [pubkey0, pubkey1, pubkey2], "", "p2sh-segwit")['address'] if not self.options.descriptors: wmulti.importaddress(p2sh) wmulti.importaddress(p2wsh) wmulti.importaddress(p2sh_p2wsh) p2wpkh = self.nodes[1].getnewaddress("", "bech32") p2pkh = self.nodes[1].getnewaddress("", "legacy") p2sh_p2wpkh = self.nodes[1].getnewaddress("", "p2sh-segwit") # fund those addresses rawtx = self.nodes[0].createrawtransaction([], {p2sh:10, p2wsh:10, p2wpkh:10, p2sh_p2wsh:10, p2sh_p2wpkh:10, p2pkh:10}) rawtx = self.nodes[0].fundrawtransaction(rawtx, {"changePosition":3}) signed_tx = self.nodes[0].signrawtransactionwithwallet(rawtx['hex'])['hex'] txid = self.nodes[0].sendrawtransaction(signed_tx) self.nodes[0].generate(6) self.sync_all() # Find the output pos p2sh_pos = -1 p2wsh_pos = -1 p2wpkh_pos = -1 p2pkh_pos = -1 p2sh_p2wsh_pos = -1 p2sh_p2wpkh_pos = -1 decoded = self.nodes[0].decoderawtransaction(signed_tx) for out in decoded['vout']: if out['scriptPubKey']['addresses'][0] == p2sh: p2sh_pos = out['n'] elif out['scriptPubKey']['addresses'][0] == p2wsh: p2wsh_pos = out['n'] elif out['scriptPubKey']['addresses'][0] == p2wpkh: p2wpkh_pos = out['n'] elif out['scriptPubKey']['addresses'][0] == p2sh_p2wsh: p2sh_p2wsh_pos = out['n'] elif out['scriptPubKey']['addresses'][0] == p2sh_p2wpkh: p2sh_p2wpkh_pos = out['n'] elif out['scriptPubKey']['addresses'][0] == p2pkh: p2pkh_pos = out['n'] inputs = [{"txid": txid, "vout": p2wpkh_pos}, {"txid": txid, "vout": p2sh_p2wpkh_pos}, {"txid": txid, "vout": p2pkh_pos}] outputs = [{self.nodes[1].getnewaddress(): 29.99}] # spend single key from node 1 created_psbt = self.nodes[1].walletcreatefundedpsbt(inputs, outputs) walletprocesspsbt_out = self.nodes[1].walletprocesspsbt(created_psbt['psbt']) # Make sure it has both types of UTXOs decoded = self.nodes[1].decodepsbt(walletprocesspsbt_out['psbt']) assert 'non_witness_utxo' in decoded['inputs'][0] assert 'witness_utxo' in decoded['inputs'][0] # Check decodepsbt fee calculation (input values shall only be counted once per UTXO) assert_equal(decoded['fee'], created_psbt['fee']) assert_equal(walletprocesspsbt_out['complete'], True) self.nodes[1].sendrawtransaction(self.nodes[1].finalizepsbt(walletprocesspsbt_out['psbt'])['hex']) self.log.info("Test walletcreatefundedpsbt fee rate of 10000 sat/vB and 0.1 XUEZ/kvB produces a total fee at or slightly below -maxtxfee (~0.05290000)") res1 = self.nodes[1].walletcreatefundedpsbt(inputs, outputs, 0, {"fee_rate": 10000, "add_inputs": True}) assert_approx(res1["fee"], 0.055, 0.005) res2 = self.nodes[1].walletcreatefundedpsbt(inputs, outputs, 0, {"feeRate": "0.1", "add_inputs": True}) assert_approx(res2["fee"], 0.055, 0.005) self.log.info("Test min fee rate checks with walletcreatefundedpsbt are bypassed, e.g. a fee_rate under 1 sat/vB is allowed") res3 = self.nodes[1].walletcreatefundedpsbt(inputs, outputs, 0, {"fee_rate": "0.99999999", "add_inputs": True}) assert_approx(res3["fee"], 0.00000381, 0.0000001) res4 = self.nodes[1].walletcreatefundedpsbt(inputs, outputs, 0, {"feeRate": 0.00000999, "add_inputs": True}) assert_approx(res4["fee"], 0.00000381, 0.0000001) self.log.info("Test min fee rate checks with walletcreatefundedpsbt are bypassed and that funding non-standard 'zero-fee' transactions is valid") for param in ["fee_rate", "feeRate"]: assert_equal(self.nodes[1].walletcreatefundedpsbt(inputs, outputs, 0, {param: 0, "add_inputs": True})["fee"], 0) self.log.info("Test invalid fee rate settings") for param, value in {("fee_rate", 100000), ("feeRate", 1)}: assert_raises_rpc_error(-4, "Fee exceeds maximum configured by user (e.g. -maxtxfee, maxfeerate)", self.nodes[1].walletcreatefundedpsbt, inputs, outputs, 0, {param: value, "add_inputs": True}) assert_raises_rpc_error(-3, "Amount out of range", self.nodes[1].walletcreatefundedpsbt, inputs, outputs, 0, {param: -1, "add_inputs": True}) assert_raises_rpc_error(-3, "Amount is not a number or string", self.nodes[1].walletcreatefundedpsbt, inputs, outputs, 0, {param: {"foo": "bar"}, "add_inputs": True}) assert_raises_rpc_error(-3, "Invalid amount", self.nodes[1].walletcreatefundedpsbt, inputs, outputs, 0, {param: "", "add_inputs": True}) self.log.info("- raises RPC error if both feeRate and fee_rate are passed") assert_raises_rpc_error(-8, "Cannot specify both fee_rate (sat/vB) and feeRate (XUEZ/kvB)", self.nodes[1].walletcreatefundedpsbt, inputs, outputs, 0, {"fee_rate": 0.1, "feeRate": 0.1, "add_inputs": True}) self.log.info("- raises RPC error if both feeRate and estimate_mode passed") assert_raises_rpc_error(-8, "Cannot specify both estimate_mode and feeRate", self.nodes[1].walletcreatefundedpsbt, inputs, outputs, 0, {"estimate_mode": "economical", "feeRate": 0.1, "add_inputs": True}) for param in ["feeRate", "fee_rate"]: self.log.info("- raises RPC error if both {} and conf_target are passed".format(param)) assert_raises_rpc_error(-8, "Cannot specify both conf_target and {}. Please provide either a confirmation " "target in blocks for automatic fee estimation, or an explicit fee rate.".format(param), self.nodes[1].walletcreatefundedpsbt ,inputs, outputs, 0, {param: 1, "conf_target": 1, "add_inputs": True}) self.log.info("- raises RPC error if both fee_rate and estimate_mode are passed") assert_raises_rpc_error(-8, "Cannot specify both estimate_mode and fee_rate", self.nodes[1].walletcreatefundedpsbt ,inputs, outputs, 0, {"fee_rate": 1, "estimate_mode": "economical", "add_inputs": True}) self.log.info("- raises RPC error with invalid estimate_mode settings") for k, v in {"number": 42, "object": {"foo": "bar"}}.items(): assert_raises_rpc_error(-3, "Expected type string for estimate_mode, got {}".format(k), self.nodes[1].walletcreatefundedpsbt, inputs, outputs, 0, {"estimate_mode": v, "conf_target": 0.1, "add_inputs": True}) for mode in ["", "foo", Decimal("3.141592")]: assert_raises_rpc_error(-8, 'Invalid estimate_mode parameter, must be one of: "unset", "economical", "conservative"', self.nodes[1].walletcreatefundedpsbt, inputs, outputs, 0, {"estimate_mode": mode, "conf_target": 0.1, "add_inputs": True}) self.log.info("- raises RPC error with invalid conf_target settings") for mode in ["unset", "economical", "conservative"]: self.log.debug("{}".format(mode)) for k, v in {"string": "", "object": {"foo": "bar"}}.items(): assert_raises_rpc_error(-3, "Expected type number for conf_target, got {}".format(k), self.nodes[1].walletcreatefundedpsbt, inputs, outputs, 0, {"estimate_mode": mode, "conf_target": v, "add_inputs": True}) for n in [-1, 0, 1009]: assert_raises_rpc_error(-8, "Invalid conf_target, must be between 1 and 1008", # max value of 1008 per src/policy/fees.h self.nodes[1].walletcreatefundedpsbt, inputs, outputs, 0, {"estimate_mode": mode, "conf_target": n, "add_inputs": True}) self.log.info("Test walletcreatefundedpsbt with too-high fee rate produces total fee well above -maxtxfee and raises RPC error") # previously this was silently capped at -maxtxfee for bool_add, outputs_array in {True: outputs, False: [{self.nodes[1].getnewaddress(): 1}]}.items(): msg = "Fee exceeds maximum configured by user (e.g. -maxtxfee, maxfeerate)" assert_raises_rpc_error(-4, msg, self.nodes[1].walletcreatefundedpsbt, inputs, outputs_array, 0, {"fee_rate": 1000000, "add_inputs": bool_add}) assert_raises_rpc_error(-4, msg, self.nodes[1].walletcreatefundedpsbt, inputs, outputs_array, 0, {"feeRate": 1, "add_inputs": bool_add}) self.log.info("Test various PSBT operations") # partially sign multisig things with node 1 psbtx = wmulti.walletcreatefundedpsbt(inputs=[{"txid":txid,"vout":p2wsh_pos},{"txid":txid,"vout":p2sh_pos},{"txid":txid,"vout":p2sh_p2wsh_pos}], outputs={self.nodes[1].getnewaddress():29.99}, options={'changeAddress': self.nodes[1].getrawchangeaddress()})['psbt'] walletprocesspsbt_out = self.nodes[1].walletprocesspsbt(psbtx) psbtx = walletprocesspsbt_out['psbt'] assert_equal(walletprocesspsbt_out['complete'], False) # Unload wmulti, we don't need it anymore wmulti.unloadwallet() # partially sign with node 2. This should be complete and sendable walletprocesspsbt_out = self.nodes[2].walletprocesspsbt(psbtx) assert_equal(walletprocesspsbt_out['complete'], True) self.nodes[2].sendrawtransaction(self.nodes[2].finalizepsbt(walletprocesspsbt_out['psbt'])['hex']) # check that walletprocesspsbt fails to decode a non-psbt rawtx = self.nodes[1].createrawtransaction([{"txid":txid,"vout":p2wpkh_pos}], {self.nodes[1].getnewaddress():9.99}) assert_raises_rpc_error(-22, "TX decode failed", self.nodes[1].walletprocesspsbt, rawtx) # Convert a non-psbt to psbt and make sure we can decode it rawtx = self.nodes[0].createrawtransaction([], {self.nodes[1].getnewaddress():10}) rawtx = self.nodes[0].fundrawtransaction(rawtx) new_psbt = self.nodes[0].converttopsbt(rawtx['hex']) self.nodes[0].decodepsbt(new_psbt) # Make sure that a non-psbt with signatures cannot be converted # Error could be either "TX decode failed" (segwit inputs causes parsing to fail) or "Inputs must not have scriptSigs and scriptWitnesses" # We must set iswitness=True because the serialized transaction has inputs and is therefore a witness transaction signedtx = self.nodes[0].signrawtransactionwithwallet(rawtx['hex']) assert_raises_rpc_error(-22, "", self.nodes[0].converttopsbt, hexstring=signedtx['hex'], iswitness=True) assert_raises_rpc_error(-22, "", self.nodes[0].converttopsbt, hexstring=signedtx['hex'], permitsigdata=False, iswitness=True) # Unless we allow it to convert and strip signatures self.nodes[0].converttopsbt(signedtx['hex'], True) # Explicitly allow converting non-empty txs new_psbt = self.nodes[0].converttopsbt(rawtx['hex']) self.nodes[0].decodepsbt(new_psbt) # Create outputs to nodes 1 and 2 node1_addr = self.nodes[1].getnewaddress() node2_addr = self.nodes[2].getnewaddress() txid1 = self.nodes[0].sendtoaddress(node1_addr, 13) txid2 = self.nodes[0].sendtoaddress(node2_addr, 13) blockhash = self.nodes[0].generate(6)[0] self.sync_all() vout1 = find_output(self.nodes[1], txid1, 13, blockhash=blockhash) vout2 = find_output(self.nodes[2], txid2, 13, blockhash=blockhash) # Create a psbt spending outputs from nodes 1 and 2 psbt_orig = self.nodes[0].createpsbt([{"txid":txid1, "vout":vout1}, {"txid":txid2, "vout":vout2}], {self.nodes[0].getnewaddress():25.999}) # Update psbts, should only have data for one input and not the other psbt1 = self.nodes[1].walletprocesspsbt(psbt_orig, False, "ALL")['psbt'] psbt1_decoded = self.nodes[0].decodepsbt(psbt1) assert psbt1_decoded['inputs'][0] and not psbt1_decoded['inputs'][1] # Check that BIP32 path was added assert "bip32_derivs" in psbt1_decoded['inputs'][0] psbt2 = self.nodes[2].walletprocesspsbt(psbt_orig, False, "ALL", False)['psbt'] psbt2_decoded = self.nodes[0].decodepsbt(psbt2) assert not psbt2_decoded['inputs'][0] and psbt2_decoded['inputs'][1] # Check that BIP32 paths were not added assert "bip32_derivs" not in psbt2_decoded['inputs'][1] # Sign PSBTs (workaround issue #18039) psbt1 = self.nodes[1].walletprocesspsbt(psbt_orig)['psbt'] psbt2 = self.nodes[2].walletprocesspsbt(psbt_orig)['psbt'] # Combine, finalize, and send the psbts combined = self.nodes[0].combinepsbt([psbt1, psbt2]) finalized = self.nodes[0].finalizepsbt(combined)['hex'] self.nodes[0].sendrawtransaction(finalized) self.nodes[0].generate(6) self.sync_all() # Test additional args in walletcreatepsbt # Make sure both pre-included and funded inputs # have the correct sequence numbers based on # replaceable arg block_height = self.nodes[0].getblockcount() unspent = self.nodes[0].listunspent()[0] psbtx_info = self.nodes[0].walletcreatefundedpsbt([{"txid":unspent["txid"], "vout":unspent["vout"]}], [{self.nodes[2].getnewaddress():unspent["amount"]+1}], block_height+2, {"replaceable": False, "add_inputs": True}, False) decoded_psbt = self.nodes[0].decodepsbt(psbtx_info["psbt"]) for tx_in, psbt_in in zip(decoded_psbt["tx"]["vin"], decoded_psbt["inputs"]): assert_greater_than(tx_in["sequence"], MAX_BIP125_RBF_SEQUENCE) assert "bip32_derivs" not in psbt_in assert_equal(decoded_psbt["tx"]["locktime"], block_height+2) # Same construction with only locktime set and RBF explicitly enabled psbtx_info = self.nodes[0].walletcreatefundedpsbt([{"txid":unspent["txid"], "vout":unspent["vout"]}], [{self.nodes[2].getnewaddress():unspent["amount"]+1}], block_height, {"replaceable": True, "add_inputs": True}, True) decoded_psbt = self.nodes[0].decodepsbt(psbtx_info["psbt"]) for tx_in, psbt_in in zip(decoded_psbt["tx"]["vin"], decoded_psbt["inputs"]): assert_equal(tx_in["sequence"], MAX_BIP125_RBF_SEQUENCE) assert "bip32_derivs" in psbt_in assert_equal(decoded_psbt["tx"]["locktime"], block_height) # Same construction without optional arguments psbtx_info = self.nodes[0].walletcreatefundedpsbt([], [{self.nodes[2].getnewaddress():unspent["amount"]+1}]) decoded_psbt = self.nodes[0].decodepsbt(psbtx_info["psbt"]) for tx_in, psbt_in in zip(decoded_psbt["tx"]["vin"], decoded_psbt["inputs"]): assert_equal(tx_in["sequence"], MAX_BIP125_RBF_SEQUENCE) assert "bip32_derivs" in psbt_in assert_equal(decoded_psbt["tx"]["locktime"], 0) # Same construction without optional arguments, for a node with -walletrbf=0 unspent1 = self.nodes[1].listunspent()[0] psbtx_info = self.nodes[1].walletcreatefundedpsbt([{"txid":unspent1["txid"], "vout":unspent1["vout"]}], [{self.nodes[2].getnewaddress():unspent1["amount"]+1}], block_height, {"add_inputs": True}) decoded_psbt = self.nodes[1].decodepsbt(psbtx_info["psbt"]) for tx_in, psbt_in in zip(decoded_psbt["tx"]["vin"], decoded_psbt["inputs"]): assert_greater_than(tx_in["sequence"], MAX_BIP125_RBF_SEQUENCE) assert "bip32_derivs" in psbt_in # Make sure change address wallet does not have P2SH innerscript access to results in success # when attempting BnB coin selection self.nodes[0].walletcreatefundedpsbt([], [{self.nodes[2].getnewaddress():unspent["amount"]+1}], block_height+2, {"changeAddress":self.nodes[1].getnewaddress()}, False) # Make sure the wallet's change type is respected by default small_output = {self.nodes[0].getnewaddress():0.1} psbtx_native = self.nodes[0].walletcreatefundedpsbt([], [small_output]) self.assert_change_type(psbtx_native, "witness_v0_keyhash") psbtx_legacy = self.nodes[1].walletcreatefundedpsbt([], [small_output]) self.assert_change_type(psbtx_legacy, "pubkeyhash") # Make sure the change type of the wallet can also be overwritten psbtx_np2wkh = self.nodes[1].walletcreatefundedpsbt([], [small_output], 0, {"change_type":"p2sh-segwit"}) self.assert_change_type(psbtx_np2wkh, "scripthash") # Make sure the change type cannot be specified if a change address is given invalid_options = {"change_type":"legacy","changeAddress":self.nodes[0].getnewaddress()} assert_raises_rpc_error(-8, "both change address and address type options", self.nodes[0].walletcreatefundedpsbt, [], [small_output], 0, invalid_options) # Regression test for 14473 (mishandling of already-signed witness transaction): psbtx_info = self.nodes[0].walletcreatefundedpsbt([{"txid":unspent["txid"], "vout":unspent["vout"]}], [{self.nodes[2].getnewaddress():unspent["amount"]+1}], 0, {"add_inputs": True}) complete_psbt = self.nodes[0].walletprocesspsbt(psbtx_info["psbt"]) double_processed_psbt = self.nodes[0].walletprocesspsbt(complete_psbt["psbt"]) assert_equal(complete_psbt, double_processed_psbt) # We don't care about the decode result, but decoding must succeed. self.nodes[0].decodepsbt(double_processed_psbt["psbt"]) # BIP 174 Test Vectors # Check that unknown values are just passed through unknown_psbt = "cHNidP8BAD8CAAAAAf//////////////////////////////////////////AAAAAAD/////AQAAAAAAAAAAA2oBAAAAAAAACg8BAgMEBQYHCAkPAQIDBAUGBwgJCgsMDQ4PAAA=" unknown_out = self.nodes[0].walletprocesspsbt(unknown_psbt)['psbt'] assert_equal(unknown_psbt, unknown_out) # Open the data file with open(os.path.join(os.path.dirname(os.path.realpath(__file__)), 'data/rpc_psbt.json'), encoding='utf-8') as f: d = json.load(f) invalids = d['invalid'] valids = d['valid'] creators = d['creator'] signers = d['signer'] combiners = d['combiner'] finalizers = d['finalizer'] extractors = d['extractor'] # Invalid PSBTs for invalid in invalids: assert_raises_rpc_error(-22, "TX decode failed", self.nodes[0].decodepsbt, invalid) # Valid PSBTs for valid in valids: self.nodes[0].decodepsbt(valid) # Creator Tests for creator in creators: created_tx = self.nodes[0].createpsbt(creator['inputs'], creator['outputs']) assert_equal(created_tx, creator['result']) # Signer tests for i, signer in enumerate(signers): self.nodes[2].createwallet(wallet_name="wallet{}".format(i)) wrpc = self.nodes[2].get_wallet_rpc("wallet{}".format(i)) for key in signer['privkeys']: wrpc.importprivkey(key) signed_tx = wrpc.walletprocesspsbt(signer['psbt'])['psbt'] assert_equal(signed_tx, signer['result']) # Combiner test for combiner in combiners: combined = self.nodes[2].combinepsbt(combiner['combine']) assert_equal(combined, combiner['result']) # Empty combiner test assert_raises_rpc_error(-8, "Parameter 'txs' cannot be empty", self.nodes[0].combinepsbt, []) # Finalizer test for finalizer in finalizers: finalized = self.nodes[2].finalizepsbt(finalizer['finalize'], False)['psbt'] assert_equal(finalized, finalizer['result']) # Extractor test for extractor in extractors: extracted = self.nodes[2].finalizepsbt(extractor['extract'], True)['hex'] assert_equal(extracted, extractor['result']) # Unload extra wallets for i, signer in enumerate(signers): self.nodes[2].unloadwallet("wallet{}".format(i)) # TODO: Re-enable this for segwit v1 # self.test_utxo_conversion() # Test that psbts with p2pkh outputs are created properly p2pkh = self.nodes[0].getnewaddress(address_type='legacy') psbt = self.nodes[1].walletcreatefundedpsbt([], [{p2pkh : 1}], 0, {"includeWatching" : True}, True) self.nodes[0].decodepsbt(psbt['psbt']) # Test decoding error: invalid base64 assert_raises_rpc_error(-22, "TX decode failed invalid base64", self.nodes[0].decodepsbt, ";definitely not base64;") # Send to all types of addresses addr1 = self.nodes[1].getnewaddress("", "bech32") txid1 = self.nodes[0].sendtoaddress(addr1, 11) vout1 = find_output(self.nodes[0], txid1, 11) addr2 = self.nodes[1].getnewaddress("", "legacy") txid2 = self.nodes[0].sendtoaddress(addr2, 11) vout2 = find_output(self.nodes[0], txid2, 11) addr3 = self.nodes[1].getnewaddress("", "p2sh-segwit") txid3 = self.nodes[0].sendtoaddress(addr3, 11) vout3 = find_output(self.nodes[0], txid3, 11) self.sync_all() def test_psbt_input_keys(psbt_input, keys): """Check that the psbt input has only the expected keys.""" assert_equal(set(keys), set(psbt_input.keys())) # Create a PSBT. None of the inputs are filled initially psbt = self.nodes[1].createpsbt([{"txid":txid1, "vout":vout1},{"txid":txid2, "vout":vout2},{"txid":txid3, "vout":vout3}], {self.nodes[0].getnewaddress():32.999}) decoded = self.nodes[1].decodepsbt(psbt) test_psbt_input_keys(decoded['inputs'][0], []) test_psbt_input_keys(decoded['inputs'][1], []) test_psbt_input_keys(decoded['inputs'][2], []) # Update a PSBT with UTXOs from the node # Bech32 inputs should be filled with witness UTXO. Other inputs should not be filled because they are non-witness updated = self.nodes[1].utxoupdatepsbt(psbt) decoded = self.nodes[1].decodepsbt(updated) test_psbt_input_keys(decoded['inputs'][0], ['witness_utxo']) test_psbt_input_keys(decoded['inputs'][1], []) test_psbt_input_keys(decoded['inputs'][2], []) # Try again, now while providing descriptors, making P2SH-segwit work, and causing bip32_derivs and redeem_script to be filled in descs = [self.nodes[1].getaddressinfo(addr)['desc'] for addr in [addr1,addr2,addr3]] updated = self.nodes[1].utxoupdatepsbt(psbt=psbt, descriptors=descs) decoded = self.nodes[1].decodepsbt(updated) test_psbt_input_keys(decoded['inputs'][0], ['witness_utxo', 'bip32_derivs']) test_psbt_input_keys(decoded['inputs'][1], []) test_psbt_input_keys(decoded['inputs'][2], ['witness_utxo', 'bip32_derivs', 'redeem_script']) # Two PSBTs with a common input should not be joinable psbt1 = self.nodes[1].createpsbt([{"txid":txid1, "vout":vout1}], {self.nodes[0].getnewaddress():Decimal('10.999')}) assert_raises_rpc_error(-8, "exists in multiple PSBTs", self.nodes[1].joinpsbts, [psbt1, updated]) # Join two distinct PSBTs addr4 = self.nodes[1].getnewaddress("", "p2sh-segwit") txid4 = self.nodes[0].sendtoaddress(addr4, 5) vout4 = find_output(self.nodes[0], txid4, 5) self.nodes[0].generate(6) self.sync_all() psbt2 = self.nodes[1].createpsbt([{"txid":txid4, "vout":vout4}], {self.nodes[0].getnewaddress():Decimal('4.999')}) psbt2 = self.nodes[1].walletprocesspsbt(psbt2)['psbt'] psbt2_decoded = self.nodes[0].decodepsbt(psbt2) assert "final_scriptwitness" in psbt2_decoded['inputs'][0] and "final_scriptSig" in psbt2_decoded['inputs'][0] joined = self.nodes[0].joinpsbts([psbt, psbt2]) joined_decoded = self.nodes[0].decodepsbt(joined) assert len(joined_decoded['inputs']) == 4 and len(joined_decoded['outputs']) == 2 and "final_scriptwitness" not in joined_decoded['inputs'][3] and "final_scriptSig" not in joined_decoded['inputs'][3] # Check that joining shuffles the inputs and outputs # 10 attempts should be enough to get a shuffled join shuffled = False for _ in range(10): shuffled_joined = self.nodes[0].joinpsbts([psbt, psbt2]) shuffled |= joined != shuffled_joined if shuffled: break assert shuffled # Newly created PSBT needs UTXOs and updating addr = self.nodes[1].getnewaddress("", "p2sh-segwit") txid = self.nodes[0].sendtoaddress(addr, 7) addrinfo = self.nodes[1].getaddressinfo(addr) blockhash = self.nodes[0].generate(6)[0] self.sync_all() vout = find_output(self.nodes[0], txid, 7, blockhash=blockhash) psbt = self.nodes[1].createpsbt([{"txid":txid, "vout":vout}], {self.nodes[0].getnewaddress("", "p2sh-segwit"):Decimal('6.999')}) analyzed = self.nodes[0].analyzepsbt(psbt) assert not analyzed['inputs'][0]['has_utxo'] and not analyzed['inputs'][0]['is_final'] and analyzed['inputs'][0]['next'] == 'updater' and analyzed['next'] == 'updater' # After update with wallet, only needs signing updated = self.nodes[1].walletprocesspsbt(psbt, False, 'ALL', True)['psbt'] analyzed = self.nodes[0].analyzepsbt(updated) assert analyzed['inputs'][0]['has_utxo'] and not analyzed['inputs'][0]['is_final'] and analyzed['inputs'][0]['next'] == 'signer' and analyzed['next'] == 'signer' and analyzed['inputs'][0]['missing']['signatures'][0] == addrinfo['embedded']['witness_program'] # Check fee and size things assert analyzed['fee'] == Decimal('0.001') and analyzed['estimated_vsize'] == 134 and analyzed['estimated_feerate'] == Decimal('0.00746268') # After signing and finalizing, needs extracting signed = self.nodes[1].walletprocesspsbt(updated)['psbt'] analyzed = self.nodes[0].analyzepsbt(signed) assert analyzed['inputs'][0]['has_utxo'] and analyzed['inputs'][0]['is_final'] and analyzed['next'] == 'extractor' self.log.info("PSBT spending unspendable outputs should have error message and Creator as next") analysis = self.nodes[0].analyzepsbt('cHNidP8BAJoCAAAAAljoeiG1ba8MI76OcHBFbDNvfLqlyHV5JPVFiHuyq911AAAAAAD/////g40EJ9DsZQpoqka7CwmK6kQiwHGyyng1Kgd5WdB86h0BAAAAAP////8CcKrwCAAAAAAWAEHYXCtx0AYLCcmIauuBXlCZHdoSTQDh9QUAAAAAFv8/wADXYP/7//////8JxOh0LR2HAI8AAAAAAAEBIADC6wsAAAAAF2oUt/X69ELjeX2nTof+fZ10l+OyAokDAQcJAwEHEAABAACAAAEBIADC6wsAAAAAF2oUt/X69ELjeX2nTof+fZ10l+OyAokDAQcJAwEHENkMak8AAAAA') assert_equal(analysis['next'], 'creator') assert_equal(analysis['error'], 'PSBT is not valid. Input 0 spends unspendable output') self.log.info("PSBT with invalid values should have error message and Creator as next") analysis = self.nodes[0].analyzepsbt('cHNidP8BAHECAAAAAfA00BFgAm6tp86RowwH6BMImQNL5zXUcTT97XoLGz0BAAAAAAD/////AgD5ApUAAAAAFgAUKNw0x8HRctAgmvoevm4u1SbN7XL87QKVAAAAABYAFPck4gF7iL4NL4wtfRAKgQbghiTUAAAAAAABAR8AgIFq49AHABYAFJUDtxf2PHo641HEOBOAIvFMNTr2AAAA') assert_equal(analysis['next'], 'creator') assert_equal(analysis['error'], 'PSBT is not valid. Input 0 has invalid value') self.log.info("PSBT with signed, but not finalized, inputs should have Finalizer as next") analysis = self.nodes[0].analyzepsbt('cHNidP8BAHECAAAAAZYezcxdnbXoQCmrD79t/LzDgtUo9ERqixk8wgioAobrAAAAAAD9////AlDDAAAAAAAAFgAUy/UxxZuzZswcmFnN/E9DGSiHLUsuGPUFAAAAABYAFLsH5o0R38wXx+X2cCosTMCZnQ4baAAAAAABAR8A4fUFAAAAABYAFOBI2h5thf3+Lflb2LGCsVSZwsltIgIC/i4dtVARCRWtROG0HHoGcaVklzJUcwo5homgGkSNAnJHMEQCIGx7zKcMIGr7cEES9BR4Kdt/pzPTK3fKWcGyCJXb7MVnAiALOBgqlMH4GbC1HDh/HmylmO54fyEy4lKde7/BT/PWxwEBAwQBAAAAIgYC/i4dtVARCRWtROG0HHoGcaVklzJUcwo5homgGkSNAnIYDwVpQ1QAAIABAACAAAAAgAAAAAAAAAAAAAAiAgL+CIiB59NSCssOJRGiMYQK1chahgAaaJpIXE41Cyir+xgPBWlDVAAAgAEAAIAAAACAAQAAAAAAAAAA') assert_equal(analysis['next'], 'finalizer') analysis = self.nodes[0].analyzepsbt('cHNidP8BAHECAAAAAfA00BFgAm6tp86RowwH6BMImQNL5zXUcTT97XoLGz0BAAAAAAD/////AgCAgWrj0AcAFgAUKNw0x8HRctAgmvoevm4u1SbN7XL87QKVAAAAABYAFPck4gF7iL4NL4wtfRAKgQbghiTUAAAAAAABAR8A8gUqAQAAABYAFJUDtxf2PHo641HEOBOAIvFMNTr2AAAA') assert_equal(analysis['next'], 'creator') assert_equal(analysis['error'], 'PSBT is not valid. Output amount invalid') analysis = self.nodes[0].analyzepsbt('cHNidP8BAJoCAAAAAkvEW8NnDtdNtDpsmze+Ht2LH35IJcKv00jKAlUs21RrAwAAAAD/////S8Rbw2cO1020OmybN74e3Ysffkglwq/TSMoCVSzbVGsBAAAAAP7///8CwLYClQAAAAAWABSNJKzjaUb3uOxixsvh1GGE3fW7zQD5ApUAAAAAFgAUKNw0x8HRctAgmvoevm4u1SbN7XIAAAAAAAEAnQIAAAACczMa321tVHuN4GKWKRncycI22aX3uXgwSFUKM2orjRsBAAAAAP7///9zMxrfbW1Ue43gYpYpGdzJwjbZpfe5eDBIVQozaiuNGwAAAAAA/v///wIA+QKVAAAAABl2qRT9zXUVA8Ls5iVqynLHe5/vSe1XyYisQM0ClQAAAAAWABRmWQUcjSjghQ8/uH4Bn/zkakwLtAAAAAAAAQEfQM0ClQAAAAAWABRmWQUcjSjghQ8/uH4Bn/zkakwLtAAAAA==') assert_equal(analysis['next'], 'creator') assert_equal(analysis['error'], 'PSBT is not valid. Input 0 specifies invalid prevout') assert_raises_rpc_error(-25, 'Inputs missing or spent', self.nodes[0].walletprocesspsbt, 'cHNidP8BAJoCAAAAAkvEW8NnDtdNtDpsmze+Ht2LH35IJcKv00jKAlUs21RrAwAAAAD/////S8Rbw2cO1020OmybN74e3Ysffkglwq/TSMoCVSzbVGsBAAAAAP7///8CwLYClQAAAAAWABSNJKzjaUb3uOxixsvh1GGE3fW7zQD5ApUAAAAAFgAUKNw0x8HRctAgmvoevm4u1SbN7XIAAAAAAAEAnQIAAAACczMa321tVHuN4GKWKRncycI22aX3uXgwSFUKM2orjRsBAAAAAP7///9zMxrfbW1Ue43gYpYpGdzJwjbZpfe5eDBIVQozaiuNGwAAAAAA/v///wIA+QKVAAAAABl2qRT9zXUVA8Ls5iVqynLHe5/vSe1XyYisQM0ClQAAAAAWABRmWQUcjSjghQ8/uH4Bn/zkakwLtAAAAAAAAQEfQM0ClQAAAAAWABRmWQUcjSjghQ8/uH4Bn/zkakwLtAAAAA==')
def extract_price2uk(number): """ Extracts price from string. Formats number in UK format without commas. Accepts string with any characters. Filters them and returns number in UK format >>> extract_price2uk("123,45") Decimal('123.45') >>> extract_price2uk('1.233,45') Decimal('1233.45') >>> extract_price2uk('1,233.45') Decimal('1233.45') """ if type(number) == unicode: number = number.encode('ascii', 'ignore') number = re.sub('\s+', '', number) m = re.search(r'[\d][\d,.]*[\d]*', number, re.UNICODE) if m is None: return Decimal(0) number = m.group(0) # check if number in UK format m = re.search(r'^([\d,]+\.{1}[\d]{1,2})$', number, re.UNICODE) if not m is None: number = m.group(1) if number is None: number = m.group(2) number = number.replace(",", "") try: return Decimal(number.replace(',', '')) except (ValueError, InvalidOperation): return Decimal(0) # UK format without decimal part m = re.search(r'^([\d,]*,[\d]{3})$', number, re.UNICODE) if not m is None: number = m.group(1) if number is None: number = m.group(2) number = number.replace(",", "") try: return Decimal(number.replace(',', '')) except (ValueError, InvalidOperation): return Decimal(0) # standard format m = re.search(r'^([\d\.\s]+,{1}[\d]{1,2})$', number, re.UNICODE) if not m is None: number = m.group(1) if number is None: number = m.group(2) number = number.replace(".", "") number = number.replace(",", ".") try: return Decimal(number.replace(',', '')) except (ValueError, InvalidOperation): return Decimal(0) # standard without decimal part m = re.search(r'^([\d.\s]*\.[\d]{3})$', number, re.UNICODE) if not m is None: number = m.group(1) if number is None: number = m.group(2) number = number.replace(".", "") number = number.replace(",", ".") try: return Decimal(number.replace(',', '')) except (ValueError, InvalidOperation): return Decimal(0) # without comma/period m = re.search(r'([\d\s]+)', number, re.UNICODE) if not m is None: number = m.group(0) number = number.replace(".", "") number = number.replace(",", ".") try: return Decimal(number.replace(',', '')) except (ValueError, InvalidOperation): return Decimal(0) return Decimal(0)
def test_map_decimal(self, string_series): from decimal import Decimal result = string_series.map(lambda x: Decimal(str(x))) assert result.dtype == np.object_ assert isinstance(result[0], Decimal)
def satoshi_round(amount): return Decimal(amount).quantize(Decimal('0.00000001'), rounding=ROUND_DOWN)
'domain': ("-D", "List of addresses"), 'memo': ("-m", "Description of the request"), 'expiration': (None, "Time in seconds"), 'timeout': (None, "Timeout in seconds"), 'force': (None, "Create new address beyond gap limit, if no more addresses are available." ), 'pending': (None, "Show only pending requests."), 'expired': (None, "Show only expired requests."), 'paid': (None, "Show only paid requests."), } # don't use floats because of rounding errors from .transaction import tx_from_str json_loads = lambda x: json.loads(x, parse_float=lambda x: str(Decimal(x))) arg_types = { 'num': int, 'nbits': int, 'imax': int, 'tx': tx_from_str, 'pubkeys': json_loads, 'jsontx': json_loads, 'inputs': json_loads, 'outputs': json_loads, 'fee': lambda x: str(Decimal(x)) if x is not None else None, 'amount': lambda x: str(Decimal(x)) if x != '!' else '!', 'locktime': int, } config_variables = {
def times_scalar(self, c): new_coordinate = [Decimal(c) * x for x in self.coordinates] return Vector(new_coordinate)
expected_comprehension="a", expected_types={}, ) CASE_LIST_INT = TypeExpressionTest( type_expression=List[int], serialized_data=[1, 2, 3, 4], expected_result=[1, 2, 3, 4], expected_comprehension="[b for b in a]", expected_types={}, ) CASE_LIST_DECIMAL = TypeExpressionTest( type_expression=List[Decimal], serialized_data=[ str(Decimal("1.12")), str(Decimal("2.23")), str(Decimal("3.34")), str(Decimal("4.45")), ], expected_result=[ Decimal("1.12"), Decimal("2.23"), Decimal("3.34"), Decimal("4.45"), ], expected_comprehension="[_Decimal_(b) for b in a]", expected_types={NodeType.DECIMAL: {Decimal}}, ) CASE_MAPPING_KEY_DATETIME_VALUE_OPTIONAL_LIST_DATETIME = TypeExpressionTest(
def parse_coinbase(data_row, parser, fiat_values): (spot_price_ccy, subtotal, total_ccy, fees) = fiat_values row_dict = data_row.row_dict if row_dict['Transaction Type'] == "Receive": if "Coinbase Referral" in row_dict['Notes']: # We can calculate the exact buy_value from the spot price data_row.t_record = TransactionOutRecord(TransactionOutRecord.TYPE_GIFT_RECEIVED, data_row.timestamp, buy_quantity=row_dict['Quantity Transacted'], buy_asset=row_dict['Asset'], buy_value=spot_price_ccy * \ Decimal(row_dict['Quantity Transacted']), wallet=WALLET) else: data_row.t_record = TransactionOutRecord(TransactionOutRecord.TYPE_DEPOSIT, data_row.timestamp, buy_quantity=row_dict['Quantity Transacted'], buy_asset=row_dict['Asset'], wallet=WALLET) elif row_dict['Transaction Type'] in ("Coinbase Earn", "Rewards Income"): data_row.t_record = TransactionOutRecord(TransactionOutRecord.TYPE_INCOME, data_row.timestamp, buy_quantity=row_dict['Quantity Transacted'], buy_asset=row_dict['Asset'], buy_value=total_ccy, wallet=WALLET) elif row_dict['Transaction Type'] == "Send": data_row.t_record = TransactionOutRecord(TransactionOutRecord.TYPE_WITHDRAWAL, data_row.timestamp, sell_quantity=row_dict['Quantity Transacted'], sell_asset=row_dict['Asset'], wallet=WALLET) elif row_dict['Transaction Type'] == "Buy": currency = get_currency(row_dict['Notes']) if currency is None: raise UnexpectedContentError(parser.in_header.index('Notes'), 'Notes', row_dict['Notes']) if config.coinbase_zero_fees_are_gifts and Decimal(fees) == 0: # Zero fees "may" indicate an early referral reward, or airdrop data_row.t_record = TransactionOutRecord(TransactionOutRecord.TYPE_GIFT_RECEIVED, data_row.timestamp, buy_quantity=row_dict['Quantity Transacted'], buy_asset=row_dict['Asset'], buy_value=total_ccy if total_ccy > 0 else None, wallet=WALLET) else: data_row.t_record = TransactionOutRecord(TransactionOutRecord.TYPE_TRADE, data_row.timestamp, buy_quantity=row_dict['Quantity Transacted'], buy_asset=row_dict['Asset'], sell_quantity=subtotal, sell_asset=currency, fee_quantity=fees, fee_asset=currency, wallet=WALLET) elif row_dict['Transaction Type'] == "Sell": currency = get_currency(row_dict['Notes']) if currency is None: raise UnexpectedContentError(parser.in_header.index('Notes'), 'Notes', row_dict['Notes']) data_row.t_record = TransactionOutRecord(TransactionOutRecord.TYPE_TRADE, data_row.timestamp, buy_quantity=subtotal, buy_asset=currency, sell_quantity=row_dict['Quantity Transacted'], sell_asset=row_dict['Asset'], fee_quantity=fees, fee_asset=currency, wallet=WALLET) elif row_dict['Transaction Type'] == "Convert": convert_info = get_convert_info(row_dict['Notes']) if convert_info is None: raise UnexpectedContentError(parser.in_header.index('Notes'), 'Notes', row_dict['Notes']) buy_quantity = convert_info[2] buy_asset = convert_info[3] data_row.t_record = TransactionOutRecord(TransactionOutRecord.TYPE_TRADE, data_row.timestamp, buy_quantity=buy_quantity, buy_asset=buy_asset, buy_value=total_ccy, sell_quantity=row_dict['Quantity Transacted'], sell_asset=row_dict['Asset'], sell_value=total_ccy, wallet=WALLET) else: raise UnexpectedTypeError(parser.in_header.index('Transaction Type'), 'Transaction Type', row_dict['Transaction Type'])
def check_json_precision(): """Make sure json library being used does not lose precision converting BTC values""" n = Decimal("20000000.00000003") satoshis = int(json.loads(json.dumps(float(n))) * 1.0e8) if satoshis != 2000000000000003: raise RuntimeError("JSON encode/decode loses precision")
first_unspent = rpc_connection.listunspent(0)[-1] print(first_unspent) address = first_unspent.get("address") scriptPubKey = first_unspent.get("scriptPubKey") redeemScript = first_unspent.get("redeemScript") txid = first_unspent.get("txid") vout = first_unspent.get("vout") print(txid) print(vout) first_unspent_amount = Decimal(first_unspent.get("amount")) print(first_unspent_amount) raw_change_address = rpc_connection.getrawchangeaddress() new_bitcoin_address = rpc_connection.getnewaddress() print(raw_change_address) print(new_bitcoin_address) fee_obj = rpc_connection.estimatesmartfee(6) fee = fee_obj.get("feerate") print(fee) send_amount = first_unspent_amount / 2
def area_of_triangle_with(self, v): return self.area_of_parallelogram_with(v) / Decimal('2.0')
def lambda_handler(event, context): url = 'https://voyagesarabais.com/recherche-sud/getpricedetails?search%5Bgateway%5D=YUL&search%5BdateDep%5D=2019-12-15&search%5Bduration%5D=7day%2C8day&search%5BdestDep%5D=o&search%5BnoHotel%5D=p7&search%5Broom1%5D=a%3A4%3A%7Bi%3A0%3Bs%3A2%3A%2240%22%3Bi%3A1%3Bs%3A2%3A%2240%22%3Bi%3A2%3Bs%3A1%3A%223%22%3Bi%3A3%3Bs%3A1%3A%221%22%3B%7D&search%5Broom2%5D=&search%5Broom3%5D=&search%5Broom4%5D=&search%5Broom5%5D=&search%5Broom6%5D=&search%5Bflex%5D=N&search%5Bflexhigh%5D=3&search%5Bflexlow%5D=3&search%5Broomcallgroup%5D=%5B%7B%22_priority%22%3A9%2C%22nb_rooms%22%3A1%2C%22nb_adults%22%3A2%2C%22non_adults%22%3A%5B%223%22%2C%221%22%5D%7D%5D&search%5Bpricemax%5D=9000&search%5Bpricemin%5D=1&search%5Ballinclusive%5D=Y&search%5Bbeach%5D=&search%5Bcasino%5D=&search%5Bfamily%5D=&search%5Bgolf%5D=&search%5Bkitchenette%5D=&search%5Boceanview%5D=&search%5Bminiclub%5D=&search%5Bspa%5D=&search%5Bwedding%5D=&search%5Badultonly%5D=&search%5Bnoextrasingle%5D=&search%5Bvilla%5D=&search%5Bstar%5D=4.5&search%5Bstarmax%5D=4.5&search%5Bdirectflight%5D=&search%5Btourtodisplay%5D=CAH%2CVAT%2CVAC%2CVAX%2CSGN%2CSQV%2CSWG%2CWJV&search%5Buuid%5D=&search%5BnbRoomsMax%5D=&search%5BhotelDistanceMax%5D=' payload = 'data=QXjaDVS1EqNQAPyXaymCS4l7cL1cAQQn8ILD11%2F6ndlZ%2FfMX%2FufEXTaHeV6sCyracChEFTl8XHzw9NfD8TjxcBJOrgXgabDpEkZOeyGaNsfYlfsXoxaj57LBWgZjpB2mpeDKsJ0iUmI5VVjv9eCeA34db0A8ASRklG9DJjZAVk8j%2BK58ctfscX7FxXppW62OhAMznyYwpeGqU9FoU%2F71SDiO7fk5Dz99S3CAd5RDB9lKTvzmSahBld5gdaz9vfedPConEhM4dpuBiIxpZ6fKZK7O1BDnBvU9Ba%2FHZJXiRNuFCNhRlvZh1lH4WrciCbh5GUW8r4vsjq6xDRJzTvsb3EGJM%2BplJMNkBcma09TrMezjOqFNtOCZ3EHBE8rwpbzA%2Bnp43SKN3No4fVcGdg1hSW1er0e8zHKV7qNEleUPVGcJ4YniN6lPWIA%2BfixcisbTUpO8HgR78ue3i0dZlwJXGyhYhxfWoz5wCrQL5JbnZadk2pILWEdT4RKiXbKcxemTi4mF7paMniWP190lJHXy8eZgV7QqaTnvx%2BwQYGNWsd5jPomwNojiNgn3zh%2B1E2XIxO7ri%2FfN7PXIehG2oplT9oHbTGqkNtPKtiQq9UsjliPEktUIbyc0%2Be8RqapxzPExGO%2BP8Qts0dbCnm7UJ3A15plV51xQq1Y6d07xJjZ4BhGiIHKw9uosLjWpHmidnaEsg%2Fle4JjPGvaZT3tgFAS6cjix2u53EIB4JwwyuGLJSxGCYa8HTz7Tm8WL741X0NfeAcIkpt6ssUJHChKkaf96kAMEG0PDxHs%2B7wDQs%2F2FQgVRsDful59Uhdw7UAWKp4yiQU25FNUlpGoG%2F1nlZGD7lDW2fb7RviM%2FQjpny6Hcxmd6JoeYuHtGOa6VdW3dcMVAxir5FXtwqb2fog0PfNydAw9EuBQwiAbzivCMaLJTr2f%2BXt4SMOadF6fZ29rn66FBIYemXUNzpHDqUoX4FlcaXO9ucgZAisAS66Mbh5xeEK7V0r33Z8oMzAnFHUeen8hoDtq2ahi3JY%2FQC5DqhEiB0eRNkC7bGPaGKXIAoq%2F1ToN4sHN8BpgKd56efidkDlK%2FyJtTid7itoGQUcLMrT0feaY455Znrfb28az3t9C8B9k63ya8BRcaX3QMkDIvsQHxciv33ROC4cA3WhqqcuUkPxRSuz9xACrzlEvXLM4QP0qBFEOvB7qeKyBXqppLE1DFLEPhc0zRyiWY30YwlgSpcQhzmmifBd8wXgLAYpouOFpYn%2BTqDEweseIKO3G2c3gbFJC5yOPGgTVLBsG7KYk%2BkCJpEW984kihzE6lTENZ32CHseFA%2FXCTZUG5FZ3M12VmtH2hKXC1IZ2UAQ4foyB1Qdi35QQJv9Ef235UyPN4c%2FeOeKR9eIlGlL9GiWhogoOEpUnE%2BDdTnKQXFWwgRRHGNXaonLog6ZNhoLCluUWOc8j6a%2BZ793ZojmWm39gkBnx0YWPFstDXoQSkIsIlwr4oN%2F8%2BhfU6N%2F%2Bd0J%2F%2Fb5zoDz0%3D&type=packageplus' headers = { 'Cookie': 'Cookie: _gcl_au=1.1.596656575.1560126807; _ga=GA1.2.1347033583.1560126807; _fbp=fb.1.1560126807161.1014257493; _gaexp=GAX1.2.NFE8cllqRy-hy2p_zsZ_9A.18143.0; G_ENABLED_IDPS=google; is_all_inclusive_checked=1; PHPSESSID=0odjk0bsqoalhh20ijg3hgcqs2; _hjid=d29cb0cd-017e-4453-a112-b8ae863dbb89; _gid=GA1.2.1378798265.1565464684; _gac_UA-6397631-1=1.1565464692.CjwKCAjw1rnqBRAAEiwAr29II9bpU1twn6ZPzisvGTap3gofl973SwBnRO6CkYdpJF4F3qEYN9FTDBoCPRwQAvD_BwE; _gat_UA-6397631-1=1', 'Origin': 'https://voyagesarabais.com', 'Accept-Encoding': 'gzip, deflate, br' , 'Accept-Language': 'en-US,en;q=0.9,fr;q=0.8' , 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36' , 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' , 'Accept': '*/*' , 'Referer': 'https://voyagesarabais.com/recherche-sud?gateway=YUL&dateDep=2019-12-15&duration=7day,8day&destDep=o&noHotel=p7&allinclusive=Y&beach=&casino=&family=&golf=&kitchenette=&oceanview=&miniclub=&spa=&weeding=&adultonly=&noextrasingle=&villa=&directflight=&tourtodisplay=CAH,VAT,VAC,VAX,SGN,SQV,SWG,WJV&uuid=&nbRoomsMax=&hotelDistanceMax=&star=4.5&starmax=4.5&pricemin=1&pricemax=9000&flex=N&&bedrooms[0][0]=40&bedrooms[0][1]=40&bedrooms[0][2]=3&bedrooms[0][3]=1', 'X-Requested-With': 'XMLHttpRequest', 'Connection': 'keep-alive' } r = requests.post(url, data=payload, headers=headers) rr = json.loads(r.text) #We sometime get cookies denied, so we have to update the data and cookies above. if 'totalprice' not in rr.keys(): SUBJECT = "Voyage en Rabais - DATA UNAVAILABLE" BODY_TEXT = ( "Update the key bastard!") client = boto3.client('ses',region_name=AWS_REGION) # Try to send the email. try: #Provide the contents of the email. response = client.send_email( Destination={ 'ToAddresses': [ RECIPIENT, ], }, Message={ 'Body': { 'Text': { 'Charset': CHARSET, 'Data': BODY_TEXT, }, }, 'Subject': { 'Charset': CHARSET, 'Data': SUBJECT, }, }, Source=SENDER, ) except ClientError as e: print(e.response['Error']['Message']) else: print("Email sent! Message ID:"), print(response['MessageId']) return(-1) #get pricing totalPrice = rr['totalprice'] dd = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") #load it into dynamodb table.put_item( Item={ 'time': dd, 'total_price': Decimal(round(totalPrice, 2)) }) # Store it into a S3 file string = 'time,total_price\n{},{}'.format(dd, Decimal(round(totalPrice, 2))) encoded_string = string.encode("utf-8") bucket_name = "trip-price" file_name = datetime.datetime.now().strftime('%s')+'.csv' s3_path = "data/" + file_name s3 = boto3.resource("s3") s3.Bucket(bucket_name).put_object(Key=s3_path, Body=encoded_string) # If price goes below 4000 I want a mail if Decimal(round(totalPrice, 2)) < 4000: SUBJECT = "Voyage en Rabais !!" BODY_TEXT = ( "Le prix du voyage est de: " + str(int(totalPrice)) + "$") # Create a new SES resource and specify a region. client = boto3.client('ses',region_name=AWS_REGION) # Try to send the email. try: #Provide the contents of the email. response = client.send_email( Destination={ 'ToAddresses': [ RECIPIENT, ], }, Message={ 'Body': { 'Text': { 'Charset': CHARSET, 'Data': BODY_TEXT, }, }, 'Subject': { 'Charset': CHARSET, 'Data': SUBJECT, }, }, Source=SENDER, ) # Display an error if something goes wrong. except ClientError as e: print(e.response['Error']['Message']) else: print("Email sent! Message ID:"), print(response['MessageId']) return str(Decimal(totalPrice))
def parse_coinbase_transactions(data_row, _parser, **_kwargs): row_dict = data_row.row_dict data_row.timestamp = DataParser.parse_timestamp(row_dict['Timestamp']) if data_row.row[21] != "": # Hash so must be external crypto deposit or withdrawal if Decimal(row_dict['Amount']) < 0: data_row.t_record = TransactionOutRecord(TransactionOutRecord.TYPE_WITHDRAWAL, data_row.timestamp, sell_quantity=abs(Decimal(row_dict['Amount'])), sell_asset=row_dict['Currency'], wallet=WALLET) else: data_row.t_record = TransactionOutRecord(TransactionOutRecord.TYPE_DEPOSIT, data_row.timestamp, buy_quantity=row_dict['Amount'], buy_asset=row_dict['Currency'], wallet=WALLET) elif row_dict['Transfer ID'] != "": # Transfer ID so could be a trade or external fiat deposit/withdrawal if row_dict['Currency'] != row_dict['Transfer Total Currency']: # Currencies are different so must be a trade if Decimal(row_dict['Amount']) < 0: data_row.t_record = TransactionOutRecord(TransactionOutRecord.TYPE_TRADE, data_row.timestamp, buy_quantity= \ Decimal(row_dict['Transfer Total']) + \ Decimal(row_dict['Transfer Fee']), buy_asset=row_dict['Transfer Total Currency'], sell_quantity=abs(Decimal(row_dict['Amount'])), sell_asset=row_dict['Currency'], fee_quantity=row_dict['Transfer Fee'], fee_asset=row_dict['Transfer Fee Currency'], wallet=WALLET) else: data_row.t_record = TransactionOutRecord(TransactionOutRecord.TYPE_TRADE, data_row.timestamp, buy_quantity=row_dict['Amount'], buy_asset=row_dict['Currency'], sell_quantity= Decimal(row_dict['Transfer Total']) - \ Decimal(row_dict['Transfer Fee']), sell_asset=row_dict['Transfer Total Currency'], fee_quantity=row_dict['Transfer Fee'], fee_asset=row_dict['Transfer Fee Currency'], wallet=WALLET) else: if Decimal(row_dict['Amount']) < 0: data_row.t_record = TransactionOutRecord(TransactionOutRecord.TYPE_WITHDRAWAL, data_row.timestamp, sell_quantity=row_dict['Transfer Total'], sell_asset=row_dict['Currency'], fee_quantity=row_dict['Transfer Fee'], fee_asset=row_dict['Transfer Fee Currency'], wallet=WALLET) else: data_row.t_record = TransactionOutRecord(TransactionOutRecord.TYPE_DEPOSIT, data_row.timestamp, buy_quantity=row_dict['Transfer Total'], buy_asset=row_dict['Currency'], fee_quantity=row_dict['Transfer Fee'], fee_asset=row_dict['Transfer Fee Currency'], wallet=WALLET) else: # Could be a referral bonus or deposit/withdrawal to/from Coinbase Pro if row_dict['Notes'] != "" and row_dict['Currency'] == "BTC": # Bonus is always in BTC data_row.t_record = TransactionOutRecord(TransactionOutRecord.TYPE_GIFT_RECEIVED, data_row.timestamp, buy_quantity=row_dict['Amount'], buy_asset=row_dict['Currency'], wallet=WALLET) elif row_dict['Notes'] != "" and row_dict['Currency'] != "BTC": # Special case, flag as duplicate entry, trade will be in BTC Wallet Transactions Report if Decimal(row_dict['Amount']) < 0: data_row.t_record = TransactionOutRecord(DUPLICATE, data_row.timestamp, sell_quantity=abs(Decimal(row_dict['Amount'])), sell_asset=row_dict['Currency'], wallet=WALLET) else: data_row.t_record = TransactionOutRecord(DUPLICATE, data_row.timestamp, buy_quantity=row_dict['Amount'], buy_asset=row_dict['Currency'], wallet=WALLET) elif Decimal(row_dict['Amount']) < 0: data_row.t_record = TransactionOutRecord(TransactionOutRecord.TYPE_WITHDRAWAL, data_row.timestamp, sell_quantity=abs(Decimal(row_dict['Amount'])), sell_asset=row_dict['Currency'], wallet=WALLET) else: data_row.t_record = TransactionOutRecord(TransactionOutRecord.TYPE_DEPOSIT, data_row.timestamp, buy_quantity=row_dict['Amount'], buy_asset=row_dict['Currency'], wallet=WALLET)
class ImageInfo: DPI_PREC = Decimal('1.000') def __init__(self, *, name='', pdfimage=None, inline=None, shorthand=None): self._name = str(name) self._shorthand = shorthand if inline is not None: self._origin = 'inline' pim = inline.iimage elif pdfimage is not None: self._origin = 'xobject' pim = pikepdf.PdfImage(pdfimage) self._width = pim.width self._height = pim.height # If /ImageMask is true, then this image is a stencil mask # (Images that draw with this stencil mask will have a reference to # it in their /Mask, but we don't actually need that information) if pim.image_mask: self._type = 'stencil' else: self._type = 'image' self._bpc = int(pim.bits_per_component) try: self._enc = FRIENDLY_ENCODING.get(pim.filters[0], 'image') except IndexError: self._enc = '?' try: self._color = FRIENDLY_COLORSPACE.get(pim.colorspace, '?') except NotImplementedError: self._color = '?' if self._enc == Encoding.jpeg2000: self._color = Colorspace.jpeg2000 self._comp = FRIENDLY_COMP.get(self._color, '?') # Bit of a hack... infer grayscale if component count is uncertain # but encoding must be monochrome. This happens if a monochrome image # has an ICC profile attached. Better solution would be to examine # the ICC profile. if self._comp == '?' and self._enc in (Encoding.ccitt, 'jbig2'): self._comp = FRIENDLY_COMP[Colorspace.gray] @property def name(self): return self._name @property def type_(self): return self._type @property def width(self): return self._width @property def height(self): return self._height @property def bpc(self): return self._bpc @property def color(self): return self._color @property def comp(self): return self._comp @property def enc(self): return self._enc @property def xres(self): return _get_dpi(self._shorthand, (self._width, self._height))[0] @property def yres(self): return _get_dpi(self._shorthand, (self._width, self._height))[1] def __repr__(self): class_locals = { attr: getattr(self, attr, None) for attr in dir(self) if not attr.startswith('_') } return ("<ImageInfo '{name}' {type_} {width}x{height} {color} " "{comp} {bpc} {enc} {xres}x{yres}>").format(**class_locals)
def run_test(self): self.log.info('prepare some coins for multiple *rawtransaction commands') self.nodes[2].generate(1) self.sync_all() self.nodes[0].generate(101) self.sync_all() self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(),1.5) self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(),1.0) self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(),5.0) self.sync_all() self.nodes[0].generate(5) self.sync_all() self.log.info('Test getrawtransaction on genesis block coinbase returns an error') block = self.nodes[0].getblock(self.nodes[0].getblockhash(0)) assert_raises_rpc_error(-5, "The genesis block coinbase is not considered an ordinary transaction", self.nodes[0].getrawtransaction, block['merkleroot']) self.log.info('Check parameter types and required parameters of createrawtransaction') # Test `createrawtransaction` required parameters assert_raises_rpc_error(-1, "createrawtransaction", self.nodes[0].createrawtransaction) assert_raises_rpc_error(-1, "createrawtransaction", self.nodes[0].createrawtransaction, []) # Test `createrawtransaction` invalid extra parameters assert_raises_rpc_error(-1, "createrawtransaction", self.nodes[0].createrawtransaction, [], {}, 0, False, 'foo') # Test `createrawtransaction` invalid `inputs` txid = '1d1d4e24ed99057e84c3f80fd8fbec79ed9e1acee37da269356ecea000000000' assert_raises_rpc_error(-3, "Expected type array", self.nodes[0].createrawtransaction, 'foo', {}) assert_raises_rpc_error(-1, "JSON value is not an object as expected", self.nodes[0].createrawtransaction, ['foo'], {}) assert_raises_rpc_error(-1, "JSON value is not a string as expected", self.nodes[0].createrawtransaction, [{}], {}) assert_raises_rpc_error(-8, "txid must be of length 64 (not 3, for 'foo')", self.nodes[0].createrawtransaction, [{'txid': 'foo'}], {}) assert_raises_rpc_error(-8, "txid must be hexadecimal string (not 'ZZZ7bb8b1697ea987f3b223ba7819250cae33efacb068d23dc24859824a77844')", self.nodes[0].createrawtransaction, [{'txid': 'ZZZ7bb8b1697ea987f3b223ba7819250cae33efacb068d23dc24859824a77844'}], {}) assert_raises_rpc_error(-8, "Invalid parameter, missing vout key", self.nodes[0].createrawtransaction, [{'txid': txid}], {}) assert_raises_rpc_error(-8, "Invalid parameter, missing vout key", self.nodes[0].createrawtransaction, [{'txid': txid, 'vout': 'foo'}], {}) assert_raises_rpc_error(-8, "Invalid parameter, vout must be positive", self.nodes[0].createrawtransaction, [{'txid': txid, 'vout': -1}], {}) assert_raises_rpc_error(-8, "Invalid parameter, sequence number is out of range", self.nodes[0].createrawtransaction, [{'txid': txid, 'vout': 0, 'sequence': -1}], {}) # Test `createrawtransaction` invalid `outputs` address = self.nodes[0].getnewaddress() address2 = self.nodes[0].getnewaddress() assert_raises_rpc_error(-1, "JSON value is not an array as expected", self.nodes[0].createrawtransaction, [], 'foo') self.nodes[0].createrawtransaction(inputs=[], outputs={}) # Should not throw for backwards compatibility self.nodes[0].createrawtransaction(inputs=[], outputs=[]) assert_raises_rpc_error(-8, "Data must be hexadecimal string", self.nodes[0].createrawtransaction, [], {'data': 'foo'}) assert_raises_rpc_error(-5, "Invalid CounosH address", self.nodes[0].createrawtransaction, [], {'foo': 0}) assert_raises_rpc_error(-3, "Invalid amount", self.nodes[0].createrawtransaction, [], {address: 'foo'}) assert_raises_rpc_error(-3, "Amount out of range", self.nodes[0].createrawtransaction, [], {address: -1}) assert_raises_rpc_error(-8, "Invalid parameter, duplicated address: %s" % address, self.nodes[0].createrawtransaction, [], multidict([(address, 1), (address, 1)])) assert_raises_rpc_error(-8, "Invalid parameter, duplicated address: %s" % address, self.nodes[0].createrawtransaction, [], [{address: 1}, {address: 1}]) assert_raises_rpc_error(-8, "Invalid parameter, duplicate key: data", self.nodes[0].createrawtransaction, [], [{"data": 'aa'}, {"data": "bb"}]) assert_raises_rpc_error(-8, "Invalid parameter, duplicate key: data", self.nodes[0].createrawtransaction, [], multidict([("data", 'aa'), ("data", "bb")])) assert_raises_rpc_error(-8, "Invalid parameter, key-value pair must contain exactly one key", self.nodes[0].createrawtransaction, [], [{'a': 1, 'b': 2}]) assert_raises_rpc_error(-8, "Invalid parameter, key-value pair not an object as expected", self.nodes[0].createrawtransaction, [], [['key-value pair1'], ['2']]) # Test `createrawtransaction` invalid `locktime` assert_raises_rpc_error(-3, "Expected type number", self.nodes[0].createrawtransaction, [], {}, 'foo') assert_raises_rpc_error(-8, "Invalid parameter, locktime out of range", self.nodes[0].createrawtransaction, [], {}, -1) assert_raises_rpc_error(-8, "Invalid parameter, locktime out of range", self.nodes[0].createrawtransaction, [], {}, 4294967296) # Test `createrawtransaction` invalid `replaceable` assert_raises_rpc_error(-3, "Expected type bool", self.nodes[0].createrawtransaction, [], {}, 0, 'foo') self.log.info('Check that createrawtransaction accepts an array and object as outputs') tx = CTransaction() # One output tx.deserialize(BytesIO(hex_str_to_bytes(self.nodes[2].createrawtransaction(inputs=[{'txid': txid, 'vout': 9}], outputs={address: 99})))) assert_equal(len(tx.vout), 1) assert_equal( tx.serialize().hex(), self.nodes[2].createrawtransaction(inputs=[{'txid': txid, 'vout': 9}], outputs=[{address: 99}]), ) # Two outputs tx.deserialize(BytesIO(hex_str_to_bytes(self.nodes[2].createrawtransaction(inputs=[{'txid': txid, 'vout': 9}], outputs=OrderedDict([(address, 99), (address2, 99)]))))) assert_equal(len(tx.vout), 2) assert_equal( tx.serialize().hex(), self.nodes[2].createrawtransaction(inputs=[{'txid': txid, 'vout': 9}], outputs=[{address: 99}, {address2: 99}]), ) # Multiple mixed outputs tx.deserialize(BytesIO(hex_str_to_bytes(self.nodes[2].createrawtransaction(inputs=[{'txid': txid, 'vout': 9}], outputs=multidict([(address, 99), (address2, 99), ('data', '99')]))))) assert_equal(len(tx.vout), 3) assert_equal( tx.serialize().hex(), self.nodes[2].createrawtransaction(inputs=[{'txid': txid, 'vout': 9}], outputs=[{address: 99}, {address2: 99}, {'data': '99'}]), ) for type in ["bech32", "p2sh-segwit", "legacy"]: addr = self.nodes[0].getnewaddress("", type) addrinfo = self.nodes[0].getaddressinfo(addr) pubkey = addrinfo["scriptPubKey"] self.log.info('sendrawtransaction with missing prevtx info (%s)' %(type)) # Test `signrawtransactionwithwallet` invalid `prevtxs` inputs = [ {'txid' : txid, 'vout' : 3, 'sequence' : 1000}] outputs = { self.nodes[0].getnewaddress() : 1 } rawtx = self.nodes[0].createrawtransaction(inputs, outputs) prevtx = dict(txid=txid, scriptPubKey=pubkey, vout=3, amount=1) succ = self.nodes[0].signrawtransactionwithwallet(rawtx, [prevtx]) assert succ["complete"] if type == "legacy": del prevtx["amount"] succ = self.nodes[0].signrawtransactionwithwallet(rawtx, [prevtx]) assert succ["complete"] if type != "legacy": assert_raises_rpc_error(-3, "Missing amount", self.nodes[0].signrawtransactionwithwallet, rawtx, [ { "txid": txid, "scriptPubKey": pubkey, "vout": 3, } ]) assert_raises_rpc_error(-3, "Missing vout", self.nodes[0].signrawtransactionwithwallet, rawtx, [ { "txid": txid, "scriptPubKey": pubkey, "amount": 1, } ]) assert_raises_rpc_error(-3, "Missing txid", self.nodes[0].signrawtransactionwithwallet, rawtx, [ { "scriptPubKey": pubkey, "vout": 3, "amount": 1, } ]) assert_raises_rpc_error(-3, "Missing scriptPubKey", self.nodes[0].signrawtransactionwithwallet, rawtx, [ { "txid": txid, "vout": 3, "amount": 1 } ]) ######################################### # sendrawtransaction with missing input # ######################################### self.log.info('sendrawtransaction with missing input') inputs = [ {'txid' : "1d1d4e24ed99057e84c3f80fd8fbec79ed9e1acee37da269356ecea000000000", 'vout' : 1}] #won't exists outputs = { self.nodes[0].getnewaddress() : 4.998 } rawtx = self.nodes[2].createrawtransaction(inputs, outputs) rawtx = self.nodes[2].signrawtransactionwithwallet(rawtx) # This will raise an exception since there are missing inputs assert_raises_rpc_error(-25, "bad-txns-inputs-missingorspent", self.nodes[2].sendrawtransaction, rawtx['hex']) ##################################### # getrawtransaction with block hash # ##################################### # make a tx by sending then generate 2 blocks; block1 has the tx in it tx = self.nodes[2].sendtoaddress(self.nodes[1].getnewaddress(), 1) block1, block2 = self.nodes[2].generate(2) self.sync_all() # We should be able to get the raw transaction by providing the correct block gottx = self.nodes[0].getrawtransaction(tx, True, block1) assert_equal(gottx['txid'], tx) assert_equal(gottx['in_active_chain'], True) # We should not have the 'in_active_chain' flag when we don't provide a block gottx = self.nodes[0].getrawtransaction(tx, True) assert_equal(gottx['txid'], tx) assert 'in_active_chain' not in gottx # We should not get the tx if we provide an unrelated block assert_raises_rpc_error(-5, "No such transaction found", self.nodes[0].getrawtransaction, tx, True, block2) # An invalid block hash should raise the correct errors assert_raises_rpc_error(-1, "JSON value is not a string as expected", self.nodes[0].getrawtransaction, tx, True, True) assert_raises_rpc_error(-8, "parameter 3 must be of length 64 (not 6, for 'foobar')", self.nodes[0].getrawtransaction, tx, True, "foobar") assert_raises_rpc_error(-8, "parameter 3 must be of length 64 (not 8, for 'abcd1234')", self.nodes[0].getrawtransaction, tx, True, "abcd1234") assert_raises_rpc_error(-8, "parameter 3 must be hexadecimal string (not 'ZZZ0000000000000000000000000000000000000000000000000000000000000')", self.nodes[0].getrawtransaction, tx, True, "ZZZ0000000000000000000000000000000000000000000000000000000000000") assert_raises_rpc_error(-5, "Block hash not found", self.nodes[0].getrawtransaction, tx, True, "0000000000000000000000000000000000000000000000000000000000000000") # Undo the blocks and check in_active_chain self.nodes[0].invalidateblock(block1) gottx = self.nodes[0].getrawtransaction(txid=tx, verbose=True, blockhash=block1) assert_equal(gottx['in_active_chain'], False) self.nodes[0].reconsiderblock(block1) assert_equal(self.nodes[0].getbestblockhash(), block2) ######################### # RAW TX MULTISIG TESTS # ######################### # 2of2 test addr1 = self.nodes[2].getnewaddress() addr2 = self.nodes[2].getnewaddress() addr1Obj = self.nodes[2].getaddressinfo(addr1) addr2Obj = self.nodes[2].getaddressinfo(addr2) # Tests for createmultisig and addmultisigaddress assert_raises_rpc_error(-5, "Invalid public key", self.nodes[0].createmultisig, 1, ["01020304"]) self.nodes[0].createmultisig(2, [addr1Obj['pubkey'], addr2Obj['pubkey']]) # createmultisig can only take public keys assert_raises_rpc_error(-5, "Invalid public key", self.nodes[0].createmultisig, 2, [addr1Obj['pubkey'], addr1]) # addmultisigaddress can take both pubkeys and addresses so long as they are in the wallet, which is tested here. mSigObj = self.nodes[2].addmultisigaddress(2, [addr1Obj['pubkey'], addr1])['address'] #use balance deltas instead of absolute values bal = self.nodes[2].getbalance() # send 1.2 CCH to msig adr txId = self.nodes[0].sendtoaddress(mSigObj, 1.2) self.sync_all() self.nodes[0].generate(1) self.sync_all() assert_equal(self.nodes[2].getbalance(), bal+Decimal('1.20000000')) #node2 has both keys of the 2of2 ms addr., tx should affect the balance # 2of3 test from different nodes bal = self.nodes[2].getbalance() addr1 = self.nodes[1].getnewaddress() addr2 = self.nodes[2].getnewaddress() addr3 = self.nodes[2].getnewaddress() addr1Obj = self.nodes[1].getaddressinfo(addr1) addr2Obj = self.nodes[2].getaddressinfo(addr2) addr3Obj = self.nodes[2].getaddressinfo(addr3) mSigObj = self.nodes[2].addmultisigaddress(2, [addr1Obj['pubkey'], addr2Obj['pubkey'], addr3Obj['pubkey']])['address'] txId = self.nodes[0].sendtoaddress(mSigObj, 2.2) decTx = self.nodes[0].gettransaction(txId) rawTx = self.nodes[0].decoderawtransaction(decTx['hex']) self.sync_all() self.nodes[0].generate(1) self.sync_all() #THIS IS AN INCOMPLETE FEATURE #NODE2 HAS TWO OF THREE KEY AND THE FUNDS SHOULD BE SPENDABLE AND COUNT AT BALANCE CALCULATION assert_equal(self.nodes[2].getbalance(), bal) #for now, assume the funds of a 2of3 multisig tx are not marked as spendable txDetails = self.nodes[0].gettransaction(txId, True) rawTx = self.nodes[0].decoderawtransaction(txDetails['hex']) vout = next(o for o in rawTx['vout'] if o['value'] == Decimal('2.20000000')) bal = self.nodes[0].getbalance() inputs = [{ "txid" : txId, "vout" : vout['n'], "scriptPubKey" : vout['scriptPubKey']['hex'], "amount" : vout['value']}] outputs = { self.nodes[0].getnewaddress() : 2.19 } rawTx = self.nodes[2].createrawtransaction(inputs, outputs) rawTxPartialSigned = self.nodes[1].signrawtransactionwithwallet(rawTx, inputs) assert_equal(rawTxPartialSigned['complete'], False) #node1 only has one key, can't comp. sign the tx rawTxSigned = self.nodes[2].signrawtransactionwithwallet(rawTx, inputs) assert_equal(rawTxSigned['complete'], True) #node2 can sign the tx compl., own two of three keys self.nodes[2].sendrawtransaction(rawTxSigned['hex']) rawTx = self.nodes[0].decoderawtransaction(rawTxSigned['hex']) self.sync_all() self.nodes[0].generate(1) self.sync_all() assert_equal(self.nodes[0].getbalance(), bal+Decimal('50.00000000')+Decimal('2.19000000')) #block reward + tx # 2of2 test for combining transactions bal = self.nodes[2].getbalance() addr1 = self.nodes[1].getnewaddress() addr2 = self.nodes[2].getnewaddress() addr1Obj = self.nodes[1].getaddressinfo(addr1) addr2Obj = self.nodes[2].getaddressinfo(addr2) self.nodes[1].addmultisigaddress(2, [addr1Obj['pubkey'], addr2Obj['pubkey']])['address'] mSigObj = self.nodes[2].addmultisigaddress(2, [addr1Obj['pubkey'], addr2Obj['pubkey']])['address'] mSigObjValid = self.nodes[2].getaddressinfo(mSigObj) txId = self.nodes[0].sendtoaddress(mSigObj, 2.2) decTx = self.nodes[0].gettransaction(txId) rawTx2 = self.nodes[0].decoderawtransaction(decTx['hex']) self.sync_all() self.nodes[0].generate(1) self.sync_all() assert_equal(self.nodes[2].getbalance(), bal) # the funds of a 2of2 multisig tx should not be marked as spendable txDetails = self.nodes[0].gettransaction(txId, True) rawTx2 = self.nodes[0].decoderawtransaction(txDetails['hex']) vout = next(o for o in rawTx2['vout'] if o['value'] == Decimal('2.20000000')) bal = self.nodes[0].getbalance() inputs = [{ "txid" : txId, "vout" : vout['n'], "scriptPubKey" : vout['scriptPubKey']['hex'], "redeemScript" : mSigObjValid['hex'], "amount" : vout['value']}] outputs = { self.nodes[0].getnewaddress() : 2.19 } rawTx2 = self.nodes[2].createrawtransaction(inputs, outputs) rawTxPartialSigned1 = self.nodes[1].signrawtransactionwithwallet(rawTx2, inputs) self.log.debug(rawTxPartialSigned1) assert_equal(rawTxPartialSigned1['complete'], False) #node1 only has one key, can't comp. sign the tx rawTxPartialSigned2 = self.nodes[2].signrawtransactionwithwallet(rawTx2, inputs) self.log.debug(rawTxPartialSigned2) assert_equal(rawTxPartialSigned2['complete'], False) #node2 only has one key, can't comp. sign the tx rawTxComb = self.nodes[2].combinerawtransaction([rawTxPartialSigned1['hex'], rawTxPartialSigned2['hex']]) self.log.debug(rawTxComb) self.nodes[2].sendrawtransaction(rawTxComb) rawTx2 = self.nodes[0].decoderawtransaction(rawTxComb) self.sync_all() self.nodes[0].generate(1) self.sync_all() assert_equal(self.nodes[0].getbalance(), bal+Decimal('50.00000000')+Decimal('2.19000000')) #block reward + tx # decoderawtransaction tests # witness transaction encrawtx = "010000000001010000000000000072c1a6a246ae63f74f931e8365e15a089c68d61900000000000000000000ffffffff0100e1f50500000000000102616100000000" decrawtx = self.nodes[0].decoderawtransaction(encrawtx, True) # decode as witness transaction assert_equal(decrawtx['vout'][0]['value'], Decimal('1.00000000')) assert_raises_rpc_error(-22, 'TX decode failed', self.nodes[0].decoderawtransaction, encrawtx, False) # force decode as non-witness transaction # non-witness transaction encrawtx = "01000000010000000000000072c1a6a246ae63f74f931e8365e15a089c68d61900000000000000000000ffffffff0100e1f505000000000000000000" decrawtx = self.nodes[0].decoderawtransaction(encrawtx, False) # decode as non-witness transaction assert_equal(decrawtx['vout'][0]['value'], Decimal('1.00000000')) # getrawtransaction tests # 1. valid parameters - only supply txid txId = rawTx["txid"] assert_equal(self.nodes[0].getrawtransaction(txId), rawTxSigned['hex']) # 2. valid parameters - supply txid and 0 for non-verbose assert_equal(self.nodes[0].getrawtransaction(txId, 0), rawTxSigned['hex']) # 3. valid parameters - supply txid and False for non-verbose assert_equal(self.nodes[0].getrawtransaction(txId, False), rawTxSigned['hex']) # 4. valid parameters - supply txid and 1 for verbose. # We only check the "hex" field of the output so we don't need to update this test every time the output format changes. assert_equal(self.nodes[0].getrawtransaction(txId, 1)["hex"], rawTxSigned['hex']) # 5. valid parameters - supply txid and True for non-verbose assert_equal(self.nodes[0].getrawtransaction(txId, True)["hex"], rawTxSigned['hex']) # 6. invalid parameters - supply txid and string "Flase" assert_raises_rpc_error(-1, "not a boolean", self.nodes[0].getrawtransaction, txId, "Flase") # 7. invalid parameters - supply txid and empty array assert_raises_rpc_error(-1, "not a boolean", self.nodes[0].getrawtransaction, txId, []) # 8. invalid parameters - supply txid and empty dict assert_raises_rpc_error(-1, "not a boolean", self.nodes[0].getrawtransaction, txId, {}) inputs = [ {'txid' : "1d1d4e24ed99057e84c3f80fd8fbec79ed9e1acee37da269356ecea000000000", 'vout' : 1, 'sequence' : 1000}] outputs = { self.nodes[0].getnewaddress() : 1 } rawtx = self.nodes[0].createrawtransaction(inputs, outputs) decrawtx= self.nodes[0].decoderawtransaction(rawtx) assert_equal(decrawtx['vin'][0]['sequence'], 1000) # 9. invalid parameters - sequence number out of range inputs = [ {'txid' : "1d1d4e24ed99057e84c3f80fd8fbec79ed9e1acee37da269356ecea000000000", 'vout' : 1, 'sequence' : -1}] outputs = { self.nodes[0].getnewaddress() : 1 } assert_raises_rpc_error(-8, 'Invalid parameter, sequence number is out of range', self.nodes[0].createrawtransaction, inputs, outputs) # 10. invalid parameters - sequence number out of range inputs = [ {'txid' : "1d1d4e24ed99057e84c3f80fd8fbec79ed9e1acee37da269356ecea000000000", 'vout' : 1, 'sequence' : 4294967296}] outputs = { self.nodes[0].getnewaddress() : 1 } assert_raises_rpc_error(-8, 'Invalid parameter, sequence number is out of range', self.nodes[0].createrawtransaction, inputs, outputs) inputs = [ {'txid' : "1d1d4e24ed99057e84c3f80fd8fbec79ed9e1acee37da269356ecea000000000", 'vout' : 1, 'sequence' : 4294967294}] outputs = { self.nodes[0].getnewaddress() : 1 } rawtx = self.nodes[0].createrawtransaction(inputs, outputs) decrawtx= self.nodes[0].decoderawtransaction(rawtx) assert_equal(decrawtx['vin'][0]['sequence'], 4294967294) #################################### # TRANSACTION VERSION NUMBER TESTS # #################################### # Test the minimum transaction version number that fits in a signed 32-bit integer. tx = CTransaction() tx.nVersion = -0x80000000 rawtx = ToHex(tx) decrawtx = self.nodes[0].decoderawtransaction(rawtx) assert_equal(decrawtx['version'], -0x80000000) # Test the maximum transaction version number that fits in a signed 32-bit integer. tx = CTransaction() tx.nVersion = 0x7fffffff rawtx = ToHex(tx) decrawtx = self.nodes[0].decoderawtransaction(rawtx) assert_equal(decrawtx['version'], 0x7fffffff) self.log.info('sendrawtransaction/testmempoolaccept with maxfeerate') # Test a transaction with a small fee. txId = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 1.0) rawTx = self.nodes[0].getrawtransaction(txId, True) vout = next(o for o in rawTx['vout'] if o['value'] == Decimal('1.00000000')) self.sync_all() inputs = [{ "txid" : txId, "vout" : vout['n'] }] # Fee 10,000 satoshis, (1 - (10000 sat * 0.00000001 CCH/sat)) = 0.9999 outputs = { self.nodes[0].getnewaddress() : Decimal("0.99990000") } rawTx = self.nodes[2].createrawtransaction(inputs, outputs) rawTxSigned = self.nodes[2].signrawtransactionwithwallet(rawTx) assert_equal(rawTxSigned['complete'], True) # Fee 10,000 satoshis, ~100 b transaction, fee rate should land around 100 sat/byte = 0.00100000 CCH/kB # Thus, testmempoolaccept should reject testres = self.nodes[2].testmempoolaccept([rawTxSigned['hex']], 0.00001000)[0] assert_equal(testres['allowed'], False) assert_equal(testres['reject-reason'], 'absurdly-high-fee') # and sendrawtransaction should throw assert_raises_rpc_error(-26, "absurdly-high-fee", self.nodes[2].sendrawtransaction, rawTxSigned['hex'], 0.00001000) # and the following calls should both succeed testres = self.nodes[2].testmempoolaccept(rawtxs=[rawTxSigned['hex']])[0] assert_equal(testres['allowed'], True) self.nodes[2].sendrawtransaction(hexstring=rawTxSigned['hex']) # Test a transaction with a large fee. txId = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 1.0) rawTx = self.nodes[0].getrawtransaction(txId, True) vout = next(o for o in rawTx['vout'] if o['value'] == Decimal('1.00000000')) self.sync_all() inputs = [{ "txid" : txId, "vout" : vout['n'] }] # Fee 2,000,000 satoshis, (1 - (2000000 sat * 0.00000001 CCH/sat)) = 0.98 outputs = { self.nodes[0].getnewaddress() : Decimal("0.98000000") } rawTx = self.nodes[2].createrawtransaction(inputs, outputs) rawTxSigned = self.nodes[2].signrawtransactionwithwallet(rawTx) assert_equal(rawTxSigned['complete'], True) # Fee 2,000,000 satoshis, ~100 b transaction, fee rate should land around 20,000 sat/byte = 0.20000000 CCH/kB # Thus, testmempoolaccept should reject testres = self.nodes[2].testmempoolaccept([rawTxSigned['hex']])[0] assert_equal(testres['allowed'], False) assert_equal(testres['reject-reason'], 'absurdly-high-fee') # and sendrawtransaction should throw assert_raises_rpc_error(-26, "absurdly-high-fee", self.nodes[2].sendrawtransaction, rawTxSigned['hex']) # and the following calls should both succeed testres = self.nodes[2].testmempoolaccept(rawtxs=[rawTxSigned['hex']], maxfeerate='0.20000000')[0] assert_equal(testres['allowed'], True) self.nodes[2].sendrawtransaction(hexstring=rawTxSigned['hex'], maxfeerate='0.20000000')
def setCODPaymentMethod(self, CODextracost): self.cod_charge = Decimal(CODextracost*float(self.calculated_price)) self.final_price += self.cod_charge self.save()
def _get_taxable_total(self): total = Decimal("0.0") for li in self.lineitems.all(): if li.taxable: total += li.total return total.quantize(Decimal("0.01"), rounding=ROUND_HALF_UP)
def test_can_insert_model_with_all_column_types(self): """ Test for inserting all column types into a Model test_can_insert_model_with_all_column_types tests that each cqlengine column type can be inserted into a Model. It first creates a Model that has each cqlengine column type. It then creates a Model instance where all the fields have corresponding data, which performs the insert into the Cassandra table. Finally, it verifies that each column read from the Model from Cassandra is the same as the input parameters. @since 2.6.0 @jira_ticket PYTHON-246 @expected_result The Model is inserted with each column type, and the resulting read yields proper data for each column. @test_category data_types:primitive """ class AllDatatypesModel(Model): id = columns.Integer(primary_key=True) a = columns.Ascii() b = columns.BigInt() c = columns.Blob() d = columns.Boolean() e = columns.DateTime() f = columns.Decimal() g = columns.Double() h = columns.Float() i = columns.Inet() j = columns.Integer() k = columns.Text() l = columns.TimeUUID() m = columns.UUID() n = columns.VarInt() o = columns.Duration() sync_table(AllDatatypesModel) input = [ 'ascii', 2**63 - 1, bytearray(b'hello world'), True, datetime.utcfromtimestamp(872835240), Decimal('12.3E+7'), 2.39, 3.4028234663852886e+38, '123.123.123.123', 2147483647, 'text', UUID('FE2B4360-28C6-11E2-81C1-0800200C9A66'), UUID('067e6162-3b6f-4ae2-a171-2470b63dff00'), int(str(2147483647) + '000') ] AllDatatypesModel.create( id=0, a='ascii', b=2**63 - 1, c=bytearray(b'hello world'), d=True, e=datetime.utcfromtimestamp(872835240), f=Decimal('12.3E+7'), g=2.39, h=3.4028234663852886e+38, i='123.123.123.123', j=2147483647, k='text', l=UUID('FE2B4360-28C6-11E2-81C1-0800200C9A66'), m=UUID('067e6162-3b6f-4ae2-a171-2470b63dff00'), n=int(str(2147483647) + '000'), o=Duration(2, 3, 4)) self.assertEqual(1, AllDatatypesModel.objects.count()) output = AllDatatypesModel.objects.first() for i, i_char in enumerate(range(ord('a'), ord('a') + 14)): self.assertEqual(input[i], output[chr(i_char)])
def _get_sub_total(self): total = Decimal("0.0") for li in self.lineitems.all(): total += Decimal(li.unit_price * li.quantity) return total.quantize(Decimal("0.01"), rounding=ROUND_HALF_UP)
except ValueError: print("Please try again with a numeral input") s0input = input("Input initial infected population: ") try: I0 = int(s0input) except ValueError: print("Please try again with a numeral input") S0 = N - I0 k0input = input( "What is your first guess for infection rate? (Usually a decimal from 0 to 10) " ) try: k0 = Decimal(k0input) print("Accepted") except ValueError: print("Please try again with a numeral input") tinput = input( "Input a timepoint at which you would like to predict the total infected population: " ) try: timepoint = int(tinput) print( "Accepted. Calculating total infected population and adjusted infection rate... " ) except ValueError: print("Please try again with a numeral input")
def report_to_list(self, queryset, display_fields, user=None, property_filters=[], preview=False): """ Create list from a report with all data filtering. queryset: initial queryset to generate results display_fields: list of field references or DisplayField models user: requesting user. If left as None - there will be no permission check property_filters: ??? preview: return only first 50 rows Returns list, message in case of issues. """ model_class = queryset.model def can_change_or_view(model): """ Return True iff `user` has either change or view permission for `model`. """ if user is None: return True model_name = model._meta.model_name app_label = model._meta.app_label can_change = user.has_perm(app_label + '.change_' + model_name) can_view = user.has_perm(app_label + '.view_' + model_name) return can_change or can_view if not can_change_or_view(model_class): return [], 'Permission Denied' if isinstance(display_fields, list): # Convert list of strings to DisplayField objects. new_display_fields = [] for display_field in display_fields: field_list = display_field.split('__') field = field_list[-1] path = '__'.join(field_list[:-1]) if path: path += '__' # Legacy format to append a __ here. new_model = get_model_from_path_string(model_class, path) model_field = new_model._meta.get_field_by_name(field)[0] choices = model_field.choices new_display_fields.append(DisplayField( path, '', field, '', '', None, None, choices, '' )) display_fields = new_display_fields # Build group-by field list. group = [df.path + df.field for df in display_fields if df.group] # To support group-by with multiple fields, we turn all the other # fields into aggregations. The default aggregation is `Max`. if group: for field in display_fields: if (not field.group) and (not field.aggregate): field.aggregate = 'Max' message = "" objects = self.add_aggregates(queryset, display_fields) # Display Values display_field_paths = [] property_list = {} custom_list = {} display_totals = {} for i, display_field in enumerate(display_fields): model = get_model_from_path_string(model_class, display_field.path) if display_field.field_type == "Invalid": continue if not model or can_change_or_view(model): display_field_key = display_field.path + display_field.field if display_field.field_type == "Property": property_list[i] = display_field_key elif display_field.field_type == "Custom Field": custom_list[i] = display_field_key elif display_field.aggregate == "Avg": display_field_key += '__avg' elif display_field.aggregate == "Max": display_field_key += '__max' elif display_field.aggregate == "Min": display_field_key += '__min' elif display_field.aggregate == "Count": display_field_key += '__count' elif display_field.aggregate == "Sum": display_field_key += '__sum' if display_field.field_type not in ('Property', 'Custom Field'): display_field_paths.append(display_field_key) if display_field.total: display_totals[display_field_key] = Decimal(0) else: message += 'Error: Permission denied on access to {0}.'.format( display_field.name ) def increment_total(display_field_key, val): """ Increment display total by `val` if given `display_field_key` in `display_totals`. """ if display_field_key in display_totals: if isinstance(val, bool): # True: 1, False: 0 display_totals[display_field_key] += Decimal(val) elif isinstance(val, Number): display_totals[display_field_key] += Decimal(str(val)) elif val: display_totals[display_field_key] += Decimal(1) # Select pk for primary and m2m relations in order to retrieve objects # for adding properties to report rows. Group-by queries do not support # Property nor Custom Field filters. if not group: display_field_paths.insert(0, 'pk') m2m_relations = [] for position, property_path in property_list.items(): property_root = property_path.split('__')[0] root_class = model_class try: property_root_class = getattr(root_class, property_root) except AttributeError: # django-hstore schema compatibility continue if type(property_root_class) == ManyToManyDescriptor: display_field_paths.insert(1, '%s__pk' % property_root) m2m_relations.append(property_root) if group: values = objects.values(*group) values = self.add_aggregates(values, display_fields) filtered_report_rows = [ [row[field] for field in display_field_paths] for row in values ] for row in filtered_report_rows: for pos, field in enumerate(display_field_paths): increment_total(field, row[pos]) else: filtered_report_rows = [] values_and_properties_list = [] values_list = objects.values_list(*display_field_paths) for row in values_list: row = list(row) values_and_properties_list.append(row[1:]) obj = None # we will get this only if needed for more complex processing # related_objects remove_row = False # filter properties (remove rows with excluded properties) for property_filter in property_filters: if not obj: obj = model_class.objects.get(pk=row.pop(0)) root_relation = property_filter.path.split('__')[0] if root_relation in m2m_relations: pk = row[0] if pk is not None: # a related object exists m2m_obj = getattr(obj, root_relation).get(pk=pk) val = reduce(getattr, [property_filter.field], m2m_obj) else: val = None else: if property_filter.field_type == 'Custom Field': for relation in property_filter.path.split('__'): if hasattr(obj, root_relation): obj = getattr(obj, root_relation) val = obj.get_custom_value(property_filter.field) else: val = reduce(getattr, (property_filter.path + property_filter.field).split('__'), obj) if property_filter.filter_property(val): remove_row = True values_and_properties_list.pop() break if not remove_row: for i, field in enumerate(display_field_paths[1:]): increment_total(field, row[i + 1]) for position, display_property in property_list.items(): if not obj: obj = model_class.objects.get(pk=row.pop(0)) relations = display_property.split('__') root_relation = relations[0] if root_relation in m2m_relations: pk = row.pop(0) if pk is not None: # a related object exists m2m_obj = getattr(obj, root_relation).get(pk=pk) val = reduce(getattr, relations[1:], m2m_obj) else: val = None else: # Could error if a related field doesn't exist try: val = reduce(getattr, relations, obj) except AttributeError: val = None values_and_properties_list[-1].insert(position, val) increment_total(display_property, val) for position, display_custom in custom_list.items(): if not obj: obj = model_class.objects.get(pk=row.pop(0)) val = obj.get_custom_value(display_custom) values_and_properties_list[-1].insert(position, val) increment_total(display_custom, val) filtered_report_rows.append(values_and_properties_list[-1]) if preview and len(filtered_report_rows) == 50: break # Sort results if requested. if hasattr(display_fields, 'filter'): defaults = { None: text_type, datetime.date: lambda: datetime.date(datetime.MINYEAR, 1, 1), datetime.datetime: lambda: datetime.datetime(datetime.MINYEAR, 1, 1), } # Order sort fields in reverse order so that ascending, descending # sort orders work together (based on Python's stable sort). See # http://stackoverflow.com/questions/6666748/ for details. sort_fields = display_fields.filter(sort__gt=0).order_by('-sort') sort_values = sort_fields.values_list('position', 'sort_reverse') for pos, reverse in sort_values: column = (row[pos] for row in filtered_report_rows) type_col = (type(val) for val in column if val is not None) field_type = next(type_col, None) default = defaults.get(field_type, field_type)() filtered_report_rows = sorted( filtered_report_rows, key=lambda row: self.sort_helper(row[pos], default), reverse=reverse, ) values_and_properties_list = filtered_report_rows # Build mapping from display field position to choices list. choice_lists = {} for df in display_fields: if df.choices and hasattr(df, 'choices_dict'): df_choices = df.choices_dict # Insert blank and None as valid choices. df_choices[''] = '' df_choices[None] = '' choice_lists[df.position] = df_choices # Build mapping from display field position to format. display_formats = {} for df in display_fields: if hasattr(df, 'display_format') and df.display_format: display_formats[df.position] = df.display_format def formatter(value, style): # Convert value to Decimal to apply numeric formats. try: value = Decimal(value) except Exception: pass try: return style.string.format(value) except ValueError: return value # Iterate rows and convert values by choice lists and field formats. final_list = [] for row in values_and_properties_list: row = list(row) for position, choice_list in choice_lists.items(): try: row[position] = text_type(choice_list[row[position]]) except Exception: row[position] = text_type(row[position]) for pos, style in display_formats.items(): row[pos] = formatter(row[pos], style) final_list.append(row) values_and_properties_list = final_list if display_totals: display_totals_row = [] fields_and_properties = list(display_field_paths[0 if group else 1:]) for position, value in property_list.items(): fields_and_properties.insert(position, value) for field in fields_and_properties: display_totals_row.append(display_totals.get(field, '')) # Add formatting to display totals. for pos, style in display_formats.items(): display_totals_row[pos] = formatter(display_totals_row[pos], style) values_and_properties_list.append( ['TOTALS'] + (len(fields_and_properties) - 1) * [''] ) values_and_properties_list.append(display_totals_row) return values_and_properties_list, message