def __init__(self, account, posting_key=None, active_key=None, nodes=None, db=None, probability_dimensions=None, min_age_to_vote=None, max_age_to_vote=None, minimum_vp_to_vote=None, vote_price=None): self.db = db self.nodes = nodes or ["https://api.steemit.com"] self.account = account self.client = Client(loglevel=logging.INFO) self.vote_client = Client(keys=[ posting_key, ], nodes=nodes) self.refund_client = Client(keys=[ active_key, ], nodes=nodes) self.min_age_to_vote = min_age_to_vote or 300 self.max_age_to_vote = max_age_to_vote or 43200 self.minimum_vp_to_vote = minimum_vp_to_vote or 80 self.vote_percent = VotePercent( probability_dimensions=probability_dimensions) self.vote_price = Amount(vote_price) or Amount("1.000 STEEM")
def update_info(self, steem_per_mvest=None, account_detail=None): c = Client(nodes=["https://api.hivekings.com"]) if not steem_per_mvest: # get chain properties dygp = c.get_dynamic_global_properties() steem_per_mvest = ( float(Amount(dygp["total_vesting_fund_steem"]).amount) / (float(Amount(dygp["total_vesting_shares"]).amount) / 1e6)) # get account detail if not account_detail: account_detail = c.get_accounts([self.username])[0] vests = float(Amount(account_detail["vesting_shares"])) # calculate account age t = parse(account_detail["created"]) if t.tzinfo is None: utc_time = pytz.timezone('UTC') t = utc_time.localize(t) # account reputation acc = Account(c) acc.raw_data = account_detail self.reputation = acc.reputation(precision=4) self.sp = vests / 1e6 * steem_per_mvest self.vests = vests self.account_age = (timezone.now() - t).total_seconds() / 86400 self.post_count = account_detail["post_count"] self.save() return self
def upsert(table, delegation): """ Inserts or updates the delegation information to the database. If there is already a delegation registered from delegator to delegatee, it updates the row instead of creating a new one. :param table: table object of Dataset :param delegation: Delegation row from the steemd :return: None """ query = dict( delegator=delegation["delegator"], delegatee=delegation["delegatee"], ) amount_in_vests = float(Amount.from_asset( delegation["vesting_shares"]).amount) delegation_object = dict( delegator=delegation["delegator"], delegatee=delegation["delegatee"], vests=amount_in_vests, created_at=delegation["min_delegation_time"] ) if table.find_one(**query): table.update(delegation_object, ['delegator', 'delegatee']) else: table.insert(delegation_object)
def handle(self, *args, **options): client = Client() acc = client.account(settings.CURATION_BOT_ACCOUNT) for index, transaction in acc.history( filter=["delegate_vesting_shares"], order="asc", only_operation_data=False, ): op = transaction["op"][1] if op.get("delegator") == settings.CURATION_BOT_ACCOUNT: continue if op.get("delegator") in BLACKLIST: continue try: sponsor = Sponsor.objects.get(username=op.get("delegator")) sponsor.delegation_modified_at = add_tz_info( parse(transaction["timestamp"])) except Sponsor.DoesNotExist: sponsor = Sponsor( username=op.get("delegator"), ) sponsor.delegation_created_at = add_tz_info( parse(transaction["timestamp"])) sponsor.delegation_amount = Amount(op.get("vesting_shares")).amount sponsor.save() print(f"Delegation of {op['delegator']}:" f" {op['vesting_shares']} is saved.")
def test_asset_dict_output(self): amount = Amount('0.010 STEEM') asset_dict = amount.asset self.assertEqual({ "amount": "10", "precision": 3, "nai": "@@000000021" }, asset_dict)
def test_asset_dict_input(self): amount = Amount.from_asset({ 'amount': '1029141630', 'precision': 6, 'nai': '@@000000037' }) self.assertEqual(float('1029.141630'), float(amount.amount)) self.assertEqual('VESTS', amount.symbol)
def handle(self, *args, **options): users = User.objects.all() c = LightsteemClient(nodes=["https://hived.emre.sh"]) dygp = c.get_dynamic_global_properties() steem_per_mvest = ( float(Amount(dygp["total_vesting_fund_hive"]).amount) / (float(Amount(dygp["total_vesting_shares"]).amount) / 1e6)) c = LightsteemClient(nodes=["https://hived.emre.sh"]) for chunk in chunks(users, 500): account_details = c.get_accounts([c.username for c in chunk]) for account_detail in account_details: try: related_user = User.objects.get( username=account_detail["name"]) except User.DoesNotExist: print(f"{account_detail['name']} is not found. Skipping.") continue print("updating", related_user) related_user.update_info( steem_per_mvest=steem_per_mvest, account_detail=account_detail, )
def get_cost(self, operation): preffered_api_type = self.client.api_type keys = self.client.keys if not len(keys): # add a dummy key self.client.keys = [ "5KQwrPbwdL6PhXujxW37FSSQZ1JiwsST4cqQzDeyXtP79zkvFD3" ] try: tx = self.client.broadcast(operation, dry_run=True) signed_tx_hex = self.client.get_transaction_hex(tx) tx_size = len(bytes.fromhex(signed_tx_hex)) self.client('condenser_api').get_dynamic_global_properties( batch=True) self.client('rc_api').get_resource_params(batch=True) self.client('rc_api').get_resource_pool(batch=True) chain_props, resource_params, resource_pool = self.client.\ process_batch() resource_pool = resource_pool["resource_pool"] total_vesting_shares = int( Amount(chain_props["total_vesting_shares"]).amount) rc_regen = total_vesting_shares // (STEEM_RC_REGEN_TIME // STEEM_BLOCK_INTERVAL) model = RCModel(resource_params=resource_params, resource_pool=resource_pool, rc_regen=rc_regen) tx_cost = model.get_transaction_rc_cost(tx, tx_size) total_cost = sum(tx_cost["cost"].values()) return total_cost finally: self.client.api_type = preffered_api_type self.client.keys = keys
def handle(self, *args, **options): active_key = getpass.getpass( f"Active key of f{settings.SPONSORS_ACCOUNT}") client = Client(keys=[active_key, ], nodes=["https://api.hivekings.com"]) account = client.account(settings.SPONSORS_ACCOUNT) one_week_ago = now() - timedelta(days=7) sponsors = Sponsor.objects.filter( delegation_created_at__lt=one_week_ago, delegation_amount__gt=0, opt_in_to_rewards=True, ) print(f"{sponsors.count()} sponsors found.") total_shares = Sponsor.objects.aggregate( total=Sum("delegation_amount"))["total"] print(f"{total_shares} VESTS delegated.") liquid_funds = Amount(account.raw_data["balance"]) print(f"dpoll.sponsors has {liquid_funds}.") one_percent_share = liquid_funds.amount / 100 transfers = [] for sponsor in sponsors: shares_in_percent = Decimal( sponsor.delegation_amount * 100 / total_shares) amount = "%.3f" % (one_percent_share * shares_in_percent) transfers.append({ "from": settings.SPONSORS_ACCOUNT, "to": sponsor.username, "amount": f"{amount} STEEM", "memo": f"Greetings {sponsor.username}," " Thank you for supporting dPoll. " "Here is your weekly rewards." }) op_list = [Operation('transfer', op) for op in transfers] client.broadcast(op_list) print("Rewards are sent!")
def steem_per_mvests(): c = Client() info = c.get_dynamic_global_properties() return (float(Amount(info["total_vesting_fund_steem"]).amount) / (float(Amount(info["total_vesting_shares"]).amount) / 1e6))
def handle(self, *args, **options): """Entry point for the Django management command""" client = Client(keys=[ settings.PROMOTION_ACCOUNT_ACTIVE_KEY, ], nodes=["https://api.hivekings.com"]) acc = client.account(settings.PROMOTION_ACCOUNT) for _, transaction in acc.history( filter=["transfer"], only_operation_data=False, ): op = transaction["op"][1] # only process incoming transactions if op["from"] == settings.PROMOTION_ACCOUNT: continue try: promotion_transaction = PromotionTransaction.objects.get( trx_id=transaction["trx_id"]) # if transaction already exists, means what we already # processed it. so, we can skip it safely. print(f"This transaction is already processed." f"Skipping. ({transaction['trx_id']})") continue except PromotionTransaction.DoesNotExist: amount = Amount(op["amount"]) promotion_amount = '%.3f' % float(amount.amount) # create a base transaction first promotion_transaction = PromotionTransaction( trx_id=transaction["trx_id"], from_user=op["from"], amount=promotion_amount, memo=op["memo"], ) promotion_transaction.save() # check if the asset is valid if amount.symbol == "STEEM": print(f"Invalid Asset. Refunding. ({op['amount']})") self.refund(client, op["from"], op["amount"], "Only SBD is accepted.") continue # check if the memo is valid memo = op["memo"] try: author = memo.split("@")[1].split("/")[0] permlink = memo.split("@")[1].split("/")[1] except IndexError as e: print(f"Invalid URL. Refunding. ({memo})") self.refund(client, op["from"], op["amount"], "Invalid URL") continue # check if the poll exists try: question = Question.objects.get(username=author, permlink=permlink) except Question.DoesNotExist: print(f"Invalid poll. Refunding. ({memo})") self.refund(client, op["from"], op["amount"], "Invalid poll.") continue # if the poll is closed, don't mind promoting it. if question.expire_at < timezone.now(): print(f"Expired poll. Refunding. ({memo})") self.refund(client, op["from"], op["amount"], "Expired poll.") continue promotion_transaction.author = author promotion_transaction.permlink = permlink promotion_transaction.save() # update the related poll's promotion amount if not question.promotion_amount: question.promotion_amount = float(amount.amount) else: question.promotion_amount += float(amount.amount) question.save() print(f"{author}/{permlink} promoted with " f"{promotion_amount} STEEM.")
def process_transfer(self, transaction_data): op = transaction_data["op"][1] amount = Amount(op["amount"]) # check if transaction is already registered in the database if self.db.is_transfer_already_registered(transaction_data["trx_id"]): logger.info( "Transaction is already registered. Skipping. (TRX: %s)", transaction_data["trx_id"]) return # register the transaction into db self.db.register_incoming_transaction( op["from"], op["memo"], transaction_data["block"], transaction_data["trx_id"], ) # check if the asset is valid if amount.symbol != "STEEM": logger.info( "Invalid asset. Refunding %s with %s. (TRX: %s)", op["from"], amount, transaction_data["trx_id"], ) self.refund( op["from"], op["amount"], RefundReason.INVALID_ASSET.value, transaction_data["trx_id"], ) return # check if the VP is suitable # Check the VP acc = self.client.account(self.account) if acc.vp() < self.minimum_vp_to_vote: print(acc.vp(), self.minimum_vp_to_vote) logger.info("Rando is sleeping. Refunding. (TRX: %s)", transaction_data["trx_id"]) self.refund( op["from"], op["amount"], RefundReason.SLEEP_MODE.value, transaction_data["trx_id"], ) return # check vote price if amount.amount != self.vote_price.amount: logger.info("Invalid amount. Refunding. (TRX: %s)", transaction_data["trx_id"]) self.refund( op["from"], op["amount"], "Invalid amount. You need to send %s" % self.vote_price, transaction_data["trx_id"], ) return # check if the sender is in a blacklist if self.in_global_blacklist(op["from"]): logger.info("Sender is in blacklist. Refunding. (TRX: %s)", transaction_data["trx_id"]) self.refund( op["from"], op["amount"], RefundReason.SENDER_IN_BLACKLIST.value, transaction_data["trx_id"], ) return # check if the memo is valid memo = op["memo"] try: author = memo.split("@")[1].split("/")[0] permlink = memo.split("@")[1].split("/")[1] except IndexError as e: logger.info("Invalid URL. Refunding. Memo: %s", memo) self.refund( op["from"], op["amount"], RefundReason.INVALID_URL.value, transaction_data["trx_id"], ) return # check if the author is in a blacklist if self.in_global_blacklist(author): logger.info("Author is in blacklist. Refunding. (TRX: %s)", transaction_data["trx_id"]) self.refund( op["from"], op["amount"], RefundReason.AUTHOR_IN_BLACKLIST.value, transaction_data["trx_id"], ) return # check is the Comment is a valid Comment comment_content = self.get_content(author, permlink) if comment_content["id"] == 0: logger.info("Invalid post. Refunding. (TRX id: %s)", transaction_data["trx_id"]) self.refund( op["from"], op["amount"], RefundReason.INVALID_URL.value, transaction_data["trx_id"], ) return # check comment is valid if comment_content.get("parent_author"): logger.info("Not a main post. Refunding. (TRX id: %s)", transaction_data["trx_id"]) self.refund( op["from"], op["amount"], RefundReason.INVALID_URL.value, transaction_data["trx_id"], ) return # check if we've already voted for that post active_voters = self.get_active_votes(author, permlink) if self.account in active_voters: logger.info("Already voted. Refunding. (TRX id: %s)", transaction_data["trx_id"]) self.refund( op["from"], op["amount"], RefundReason.POST_IS_ALREADY_VOTED.value, transaction_data["trx_id"], ) return # check if the Comment age is suitable created = parse(comment_content["created"]) comment_age = (datetime.now() - created).total_seconds() if not (self.min_age_to_vote < comment_age < self.max_age_to_vote): self.refund( op["from"], op["amount"], f"Post age must be between {self.min_age_to_vote} and" f" {self.max_age_to_vote} seconds", transaction_data["trx_id"], ) logger.info("Post age is invalid. Refunding. (TRX id: %s)", transaction_data["trx_id"]) return # vote self.vote(author, permlink, amount, transaction_data)
def steem_per_mvests(): c = Client(nodes=["https://api.hivekings.com"]) info = c.get_dynamic_global_properties() return (float(Amount(info["total_vesting_fund_steem"]).amount) / (float(Amount(info["total_vesting_shares"]).amount) / 1e6))
def test_standard_input(self): amount = Amount('1.942 SBD') self.assertEqual(float(1.942), float(amount.amount)) self.assertEqual('SBD', amount.symbol)