def list_asset_balance(wallet_file, asset, issuer, domain=None, test_mode=False, trezor_mode=False): network_settings = get_network_settings(test_mode=test_mode) if not trezor_mode: (private_key, public_key) = load_wallet(wallet_file=wallet_file) k = Keypair.from_secret(secret=private_key) else: public_key = get_trezor_public_key() k = Keypair.from_public_key(public_key=public_key) server = Server(network_settings.get("horizon_url")) response = server.accounts().account_id(account_id=k.public_key).call() balances = response.get("balances") for b in balances: balance = b.get("balance") asset_code = b.get("asset_code") asset_issuer = b.get("asset_issuer") if asset_code == asset and asset_issuer == issuer: if asset_code is None and asset_issuer is None: print("{} XLM".format(balance)) else: if domain is None: print("{} {} issued by {}".format(balance, asset_code, asset_issuer)) else: print("{} {}@{} issued by {}".format( balance, asset_code, domain, asset_issuer))
def list_balances(wallet_file, test_mode=True, trezor_mode=False): network_settings = get_network_settings(test_mode=test_mode) if not trezor_mode: (private_key, public_key) = load_wallet(wallet_file=wallet_file) k = Keypair.from_secret(secret=private_key) else: public_key = get_trezor_public_key() k = Keypair.from_public_key(public_key=public_key) server = Server(network_settings.get("horizon_url")) response = server.accounts().account_id(account_id=k.public_key).call() balances = response.get("balances") print(json.dumps(balances, indent=4))
def assetsActivo(self, direccionEmisor, codigo): pLlave = self.pLlave try: server = Server(horizon_url=self.Horizon_url) cuenta = server.accounts().account_id(pLlave).call() resultado = False for balance in cuenta['balances']: if balance['asset_type'] != 'native': if balance['asset_code'] == codigo and balance[ 'asset_issuer'] == direccionEmisor: resultado = True except exceptions.NotFoundError: return resultado return resultado
def get_balance(public_key, asset=0, public=False): if public: server = Server(horizon_url="https://horizon.stellar.org") else: server = Server(horizon_url="https://horizon-testnet.stellar.org") account = server.accounts().account_id(public_key).call() if asset: for b in account['balances']: if b['asset_code'] == asset[0] and b['asset_issuer'] == asset[ 1]: balance = float(b['balance']) break else: for b in account['balances']: if b['asset_type'] == 'native': balance = float(b['balance']) return balance
def informacionAssets(self): pLlave = self.pLlave try: texto = "Assets\n➖➖➖➖➖➖➖➖➖➖➖➖➖➖\n" #asset_issuer="" server = Server(horizon_url=self.Horizon_url) cuenta = server.accounts().account_id(pLlave).call() for i in cuenta['balances']: if i['asset_type'] != "native": asset_issuer = i['asset_issuer'] texto += ("Asset Code:" + i['asset_code'] + "\n") texto += ("Limit:" + i['limit'] + "\n") Assets = server.assets().for_code( i['asset_code']).for_issuer(asset_issuer).call() for e in Assets['_embedded']['records']: texto += ("Amount:" + str(e['amount'])) texto += ("\nNum Accounts:" + str(e['num_accounts'])) texto += ("\n➖➖➖➖➖➖➖➖➖➖➖➖➖➖\n") return texto except: return "Sorry you have not created any assets, please click the button (Create Assets)"
def balance(self): pLlave = self.pLlave try: server = Server(horizon_url=self.Horizon_url) cuenta = server.accounts().account_id(pLlave).call() resultado = [] texto = "Balances:\n" if len(cuenta['balances']) > 1: for balance in cuenta['balances']: if balance['asset_type'] == 'native': texto += ("XML = " + str(balance['balance'])) else: texto += (str(balance['asset_code']) + " = " + str(balance['balance']) + "\n") else: texto += "XLM =" + str(cuenta['balances'][0]['balance']) resultado.append(True) resultado.append(texto) return resultado except exceptions.NotFoundError: texto = "su cuenta no esta activa" return [False, texto]
def assetsPosibles(self): pLlave = self.pLlave try: AssetsPosibles = [] server = Server(horizon_url=self.Horizon_url) cuenta = server.accounts().account_id(pLlave).call() #Assets no creados por el for i in cuenta['balances']: if i['asset_type'] != 'native': AssetsPosibles.append((i['asset_code'], i['asset_issuer'])) # Assets no creados por el try: Assets = server.assets().for_issuer(pLlave).call() for e in Assets['_embedded']['records']: if not self.busqueda(AssetsPosibles, e['asset_code'], e['asset_issuer']): AssetsPosibles.append( (e['asset_code'], e['asset_issuer'])) except: pass texto = md.text( md.bold("Seleccione un numero Assets:")) + "\n➖➖➖➖➖➖➖➖➖➖➖➖➖➖\n" contador = 0 for i in AssetsPosibles: texto += (md.text(md.bold(str(contador))) + ". Assets Code: " + md.text(md.code(str(i[0]))) + "\n Asset Issuer:" + md.text(md.code(str(i[1]))) + "\n") texto += ("\n➖➖➖➖➖➖➖➖➖➖➖➖➖➖\n") contador += 1 return [texto, AssetsPosibles, contador] except: print("error") return []
class Command(BaseCommand): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.reset_parser = None self.issue_parser = None self.server = Server("https://horizon-testnet.stellar.org") self.http = urllib3.PoolManager() def add_arguments(self, parser): subparsers = parser.add_subparsers(dest="subcommands", required=True) self.reset_parser = subparsers.add_parser( "reset", help="a sub-command for testnet resets" ) self.issue_parser = subparsers.add_parser( "issue", help="a sub-command for issuing assets on testnet" ) self.issue_parser.add_argument( "--asset", "-a", help="the code of the asset issued" ) self.issue_parser.add_argument( "--issuer-seed", "-i", help="the issuer's secret key" ) self.issue_parser.add_argument( "--distribution-seed", "-d", help="the distribution account's secret key" ) self.issue_parser.add_argument( "--client-seed", "-c", help="the client account's secret key" ) self.issue_parser.add_argument( "--issue-amount", type=Decimal, help="the amount sent to distribution account. Also the limit for the trustline.", ) self.issue_parser.add_argument( "--client-amount", type=Decimal, help="the amount sent to client account. Also the limit for the trustline.", ) def handle(self, *_args, **options): if options.get("subcommands") == "reset": self.reset(**options) elif options.get("subcommands") == "issue": self.issue(**options) def reset(self, **options): """ Perform any necessary functions to ensure the anchor is in a valid state after a testnet reset. Currently this involves the following: - re-issuing every Asset object in the DB - moves all `pending_trust` Transactions to `error` - setting the most-recently streamed Transaction object's `paging_token` attribute to None. This signals to watch_transactions to stream using the `"now"` keyword. """ print("\nResetting each asset's most recent paging token") for asset in Asset.objects.filter(distribution_seed__isnull=False): transaction = ( Transaction.objects.filter( Q(kind=Transaction.KIND.withdrawal) | Q(kind=Transaction.KIND.send), receiving_anchor_account=asset.distribution_account, status=Transaction.STATUS.completed, ) .order_by("-completed_at") .first() ) if transaction: transaction.paging_token = None transaction.save() print("\nPlacing all pending_trust transactions into error status") Transaction.objects.filter(status=Transaction.STATUS.pending_trust).update( status=Transaction.STATUS.error ) for asset in Asset.objects.filter(issuer__isnull=False): print(f"\nIssuing {asset.code}") issuer_seed = input(f"Seed for {asset.code} issuer: ") try: Keypair.from_secret(issuer_seed) except Ed25519SecretSeedInvalidError: raise CommandError("Bad seed string for issuer account") distribution_seed = asset.distribution_seed if not distribution_seed: distribution_seed = input( f"Seed for {asset.code} distribution account: " ) try: Keypair.from_secret(distribution_seed) except Ed25519SecretSeedInvalidError: raise CommandError("Bad seed string for distribution account") self.issue( **{ "asset": asset.code, "issuer_seed": issuer_seed, "distribution_seed": distribution_seed, "issue_amount": Decimal(10000000), } ) def issue(self, **options): """ Issue the asset specified using the `options` passed to the subcommand or function call. The code here is a port of the following project: https://github.com/stellar/create-stellar-token Users can setup distribution and client accounts for the asset being issued as well. """ code = options.get("asset") or "TEST" issuer = Keypair.from_secret( options.get("issuer_seed") or Keypair.random().secret ) distributor = Keypair.from_secret( options.get("distribution_seed") or Keypair.random().secret ) client, client_amount = None, None if options.get("client_seed") or options.get("client_amount"): client = Keypair.from_secret( options.get("client_seed") or Keypair.random().secret ) client_amount = options.get("client_amount") or Decimal(1000) issue_amount = options.get("issue_amount") or Decimal(100000) print("\nIssuer account public and private keys:") print(f"public key: {issuer.public_key}") print(f"secret key: {issuer.secret}\n") print("Distribution account public and private keys:") print(f"public key: {distributor.public_key}") print(f"secret key: {distributor.secret}\n") print(f"Issuing {issue_amount} {code} to the distribution account") if client: print("\nClient account public and private keys:") print(f"public key: {client.public_key}") print(f"secret key: {client.secret}\n") print(f"Sending {client_amount} to the client account\n") accounts = {} for kp in [issuer, distributor, client]: if not kp: continue try: accounts[kp.public_key] = ( self.server.accounts().account_id(kp.public_key).call() ) except NotFoundError: print(f"Funding {kp.public_key} ...") self.http.request( "GET", f"https://friendbot.stellar.org?addr={kp.public_key}" ) accounts[kp.public_key] = ( self.server.accounts().account_id(kp.public_key).call() ) self.add_balance(code, issue_amount, accounts, distributor, issuer, issuer) if client: self.add_balance(code, client_amount, accounts, client, distributor, issuer) home_domain = input("Home domain for the issuing account (optional): ") if home_domain: self.set_home_domain(issuer, home_domain) def set_home_domain(self, issuer: Keypair, home_domain: str): envelope = ( TransactionBuilder( self.server.load_account(issuer.public_key), base_fee=settings.MAX_TRANSACTION_FEE_STROOPS or settings.HORIZON_SERVER.fetch_base_fee(), network_passphrase="Test SDF Network ; September 2015", ) .append_set_options_op(home_domain=home_domain) .set_timeout(30) .build() ) envelope.sign(issuer) try: self.server.submit_transaction(envelope) except BaseHorizonError as e: print( f"Failed to set {home_domain} as home_domain for {issuer.public_key}." f"Result codes: {e.extras.get('result_codes')}" ) else: print("Success!") def add_balance(self, code, amount, accounts, dest, src, issuer): tb = TransactionBuilder( self.account_from_json(accounts[src.public_key]), base_fee=settings.MAX_TRANSACTION_FEE_STROOPS or settings.HORIZON_SERVER.fetch_base_fee(), network_passphrase="Test SDF Network ; September 2015", ) balance = self.get_balance(code, accounts[dest.public_key]) if not balance: print(f"\nCreating {code} trustline for {dest.public_key}") if settings.MAX_TRANSACTION_FEE_STROOPS: # halve the base_fee because there are 2 operations tb.base_fee = tb.base_fee // 2 tb.append_change_trust_op( asset_code=code, asset_issuer=issuer.public_key, source=dest.public_key ) payment_amount = amount elif Decimal(balance) < amount: print(f"\nReplenishing {code} balance to {amount} for {dest.public_key}") payment_amount = amount - Decimal(balance) else: print( "Destination account already has more than the amount " "specified, skipping\n" ) return print(f"Sending {code} payment of {payment_amount} to {dest.public_key}") tb.append_payment_op( destination=dest.public_key, amount=payment_amount, asset_code=code, asset_issuer=issuer.public_key, source=src.public_key, ) envelope = tb.set_timeout(30).build() if len(tb.operations) == 2: # add destination's signature if we're adding a trustline envelope.sign(dest) envelope.sign(src) try: self.server.submit_transaction(envelope) except BaseHorizonError as e: print( f"Failed to send {code} payment to {dest.public_key}. " f"Result codes: {e.extras.get('result_codes')}" ) else: print("Success!") def account_from_json(self, json): sequence = int(json["sequence"]) thresholds = Thresholds( json["thresholds"]["low_threshold"], json["thresholds"]["med_threshold"], json["thresholds"]["high_threshold"], ) account = Account(account_id=json["id"], sequence=sequence) account.signers = json["signers"] account.thresholds = thresholds return account def get_balance(self, code, json) -> Optional[str]: for balance_obj in json["balances"]: if balance_obj.get("asset_code") == code: return balance_obj["balance"]
# # # asset -> this is the asset we are interested in viewing the total holders of # # exceptions -> these are accounts we'd like to exclude for being outliers # # # asset=['ARST','GB7TAYRUZGE6TVT7NHP5SMIZRNQA6PLM423EYISAOAP3MKYIQMVYP2JO'] # asset=['BRLT','GB7TAYRUZGE6TVT7NHP5SMIZRNQA6PLM423EYISAOAP3MKYIQMVYP2JO'] # # exceptions =['GDMSN2PQ3EB32LZY5JVACI4H7GUVQ3YUWOM4437IDTVQHHWHYG7CGA5Z', 'GB34PTUQQPYKN7XPWFZCIP77X5ZAEQEB3IN227EHIZFGLUUDS2Y2JVRW', 'GDEFAUQUISB3NLEKFXNVUARIO6MRXI2SD2GLGPIM6TJHR4ZRYOYEBHLW', 'GBKBU7E7TZFV6RPVV5FLXISAICNQKBINW7IDKS7IO5E26P6NQFMWILQL'] # # server = Server(horizon_url="https://horizon-testnet.stellar.org") asset_obj = Asset(code=asset[0],issuer=asset[1]) accounts_call_builder = ( server.accounts().for_asset(asset_obj).limit(15) ) # # def holder_amount(page_records,asset,exceptions): acnt_amnt = [] for r in page_records: if r['account_id'] in exceptions: pass else: for b in r['balances']: if b['asset_code'] == asset[0]: acnt_amnt.append([r['account_id'],b['balance']]) break; return acnt_amnt ################################################################################
class stellarWrapper: def __init__(self, network='test'): if network == 'test': self.server = Server("https://horizon-testnet.stellar.org") @staticmethod def create_account(): kp = Keypair.random() print("Public Key is " + kp.public_key) print("Secret Seed is " + kp.secret) return kp @staticmethod def fund_test_account(publicKey): url = 'https://friendbot.stellar.org' res = requests.get(url, params={'addr': publicKey}) print(res) def load_account(self, publicKey): account = self.server.load_account(publicKey) print(account) return account def load_server_account(self, publicKey): accountDetails = self.server.accounts().account_id(publicKey).call() print(accountDetails) return accountDetails def get_threshold(self, publicKey): accountDetails = self.load_server_account(publicKey) return accountDetails['thresholds'] def get_native_balance(self, publicKey): accountDetails = self.load_server_account(publicKey) for x in accountDetails['balances']: if x['asset_type'] == 'native': return x['balance'] def get_sequence(self, publicKey): accountDetails = self.load_server_account(publicKey) return accountDetails['sequence'] def create_transaction(self, sourceAccountPublicKey, operationList): sourceAccount = self.load_account(sourceAccountPublicKey) transactionBuilder = TransactionBuilder( source_account=sourceAccount, network_passphrase=Network.TESTNET_NETWORK_PASSPHRASE) #for operation in operationList: # transactionBuilder.append_operation(operation) txnEnv = transactionBuilder.build() return txnEnv.to_xdr() @staticmethod def signTransaction(txnXdr, signature): txnEnv = TransactionEnvelope.from_xdr(txnXdr) txnEnv.sign(signature) txnEnv.to_xdr() def submitTransaction(self, txnXdr): txnEnv = Transaction.from_xdr(txnXdr) res = self.server.submit_transaction(txnEnv) print(res) return res
class HorizonProvider(StellarProvider): """ Horizon is a software that allows you to query nodes via http. This should be the only thing we need since horizon also indexes the data it holds. """ def __init__(self, horizon_url='https://horizon-testnet.stellar.org/'): self.server = Server(horizon_url=horizon_url) def _make_request(self, fun, *args, **kwargs): """ Used to make the request to the horizon server. It will catch the library specific exceptions and raise the exceptions used in this project. :param fun: api call to make :param args: args for the api call :param kwargs: args for the api call :return: response form the api call """ try: return fun(*args, **kwargs) except stellar_sdk.exceptions.ConnectionError: raise ConnectionException('Could not connect to the server') except stellar_sdk.exceptions.NotFoundError as e: # This exception is used by the check_account_created function if fun == self.server.load_account: raise e raise RequestException('Check the request params, the resource could not be found') except stellar_sdk.exceptions.BadRequestError as e: raise RequestException('Your request had an error') except stellar_sdk.exceptions.BadResponseError: raise RequestException('The server response had an error') def submit_transaction(self, tx): return self._make_request(self.server.submit_transaction, tx)['hash'] def get_balance(self, address): # We only care about the native token right now. return self._make_request(self.server.accounts().account_id(address).call)['balances'][0]['balance'] def get_transactions(self, address): response = self._make_request( self.server.transactions().for_account(address).limit(200).include_failed(True).call) transactions = response['_embedded']['records'] return self._normalize_transactions(transactions) def _normalize_transactions(self, transactions): """ Transform a list of Transactions from the api into the format used in this project :param transactions: List of transactions from the api :return: A list of Transaction objects """ transactions_to_return = [] for tx in transactions: transactions_to_return.append(self._normalize_transaction(tx)) return transactions_to_return def _normalize_transaction(self, tx) -> Transaction: """ Transform a transaction from the api into a transaction object this project uses. :param tx: transaction from api :return: Transaction object """ max_time_bound_string = tx.get('valid_before') # the date we get from the api ends with z to indicate utc we have to remove this to parse it max_time_bound = None if max_time_bound_string is None else datetime.fromisoformat(max_time_bound_string[:-1]) min_time_bound_string = tx.get('valid_after') min_time_bound = None if min_time_bound_string is None else datetime.fromisoformat(min_time_bound_string[:-1]) return Transaction( hash=tx['hash'], date_time=datetime.fromisoformat(tx['created_at'][:-1]), fee=int(tx['fee_charged']), operation_count=tx['operation_count'], source_account=tx['source_account'], succeeded=tx['successful'], sequence_number=tx['source_account_sequence'], transaction_envelope=tx['envelope_xdr'], ledger_nr=tx['ledger'], min_time_bound=min_time_bound, max_time_bound=max_time_bound ) def get_base_fee(self): return self._make_request(self.server.fetch_base_fee) def get_ledger_height(self): response = self._make_request(self.server.ledgers().limit(1).order().call) return response['_embedded']['records'][0]['sequence'] def get_account_sequence(self, address): return int(self._make_request(self.server.accounts().account_id(address).call)["sequence"]) def check_account_created(self, address) -> bool: try: self._make_request(self.server.load_account, address) except NotFoundError: return False return True
class StellarWallet: """ Stellar Hot Wallet Handler on chain for live net use self.server = Server(horizon_url="https://horizon.stellar.org") # Live network """ def __init__(self, horizon_url: str, integrated_coins): helpers = Helpers() secret_details = helpers.read_json_file(file_name="walletSecrets.json") # Load Stellar wallet secrets public_details = helpers.read_json_file(file_name="hotWallets.json") # Load hot wallet details self.integrated_coins = integrated_coins self.public_key = public_details["xlm"] self.dev_key = public_details["xlmDev"] self.private_key = secret_details['stellar'] self.root_keypair = Keypair.from_secret(self.private_key) self.root_account = Account(account_id=self.root_keypair.public_key, sequence=1) self.server = Server(horizon_url=horizon_url) # Testnet # Decide network type if horizon_url == "https://horizon-testnet.stellar.org": self.network_phrase = Network.TESTNET_NETWORK_PASSPHRASE self.network_type = 'testnet' else: self.network_phrase = Network.PUBLIC_NETWORK_PASSPHRASE self.network_type = 'pub-net' def create_stellar_account(self): """ Creates inactive stellar account which needs to be activated by depositing lumens """ try: key_pair = Keypair.random() public_key = key_pair.public_key private_key = key_pair.secret return {f'address': f'{public_key}', f'secret': f'{private_key}', "network": f'{self.network_type}'} except NotFoundError: return {} def generate_uri(self, address: str, memo: str): """ Returns Transaction as envelope """ return stellar_uri.PayStellarUri(destination=address, memo=TextMemo(text=memo), asset=Asset.native(), network_passphrase=self.network_phrase, message='Deposit to Discord', ).to_uri() @staticmethod def __filter_error(result_code): if 'op_no_trust' in result_code: return 'no trust' elif 'op_no_source_account' in result_code: return 'No source account provided' else: return result_code def check_if_account_activate(self, address): "Try to load account on the network" try: self.server.load_account(account_id=address) return True except NotFoundError: return False def get_stellar_hot_wallet_details(self): """ Return the stellar hot wallet balance :return: """ data = self.server.accounts().account_id(account_id=self.public_key).call() if 'status' not in data: data.pop('_links') data.pop('data') data.pop('flags') data.pop('last_modified_ledger') data.pop('sequence') data.pop('subentry_count') data.pop('thresholds') data.pop('signers') data.pop('id') data.pop('paging_token') return data else: return {} def decode_transaction_envelope(self, envelope_xdr): """ Decode envelope and get details Credits to overcat : https://stellar.stackexchange.com/questions/3022/how-can-i-get-the-value-of-the-stellar-transaction/3025#3025 :param envelope_xdr: Xdr envelope from stellar network :return: Decoded transaction details """ te = TransactionEnvelope.from_xdr(envelope_xdr, self.network_phrase) operations = te.transaction.operations # TODO make multiple payments inside one transaction for op in operations: if isinstance(op, Payment): asset = op.asset.to_dict() if asset.get('type') == 'native': asset['code'] = 'XLM' # Appending XLM code to asset incase if native asset["amount"] = op.to_xdr_amount(op.amount) # TODO count all deposits return asset def get_incoming_transactions(self, pag=None): """ Gets all incoming transactions and removes certain values :return: List of incoming transfers """ data = self.server.transactions().for_account(account_id=self.public_key).include_failed(False).order( desc=False).cursor(cursor=pag).limit(200).call() to_process = list() for tx in data['_embedded']['records']: # Get transaction envelope if tx['source_account'] != self.public_key and tx['successful'] is True: # Get only incoming transactions tx.pop('_links') tx.pop('fee_charged') tx.pop('id') tx.pop('fee_account') tx.pop('fee_meta_xdr') tx.pop('ledger') tx.pop('max_fee') tx.pop('operation_count') tx.pop('result_meta_xdr') tx.pop('result_xdr') tx.pop('signatures') tx['asset_type'] = self.decode_transaction_envelope(envelope_xdr=tx['envelope_xdr']) tx.pop('envelope_xdr') to_process.append(tx) return to_process @staticmethod def check_if_memo(memo): """ Check if memo has been provided :param memo: :return: """ if memo != 'none': return True else: return False def token_withdrawal(self, address, token, amount: str): """ Amount as full """ if token != 'xlm': asset_issuer = self.integrated_coins[token.lower()]["assetIssuer"] else: asset_issuer = None source_account = self.server.load_account(self.public_key) tx = TransactionBuilder( source_account=source_account, network_passphrase=self.network_phrase, base_fee=self.server.fetch_base_fee()).append_payment_op( asset_issuer=asset_issuer, destination=address, asset_code=token.upper(), amount=amount).set_timeout(30).build() tx.sign(self.root_keypair) try: resp = self.server.submit_transaction(tx) details = self.decode_transaction_envelope(envelope_xdr=resp['envelope_xdr']) end_details = { "asset": details['code'], "explorer": resp['_links']['transaction']['href'], "hash": resp['hash'], "ledger": resp['ledger'], "destination": address, "amount": details['amount'] } return end_details except exceptions.BadRequestError as e: # get operation from result_codes to be processed error = self.__filter_error(result_code=e.extras["result_codes"]['operations']) return { "error": f'{error} with {token.upper()} issuer' } def establish_trust(self, private_key, token): """ Amount as full """ # Load user secret and get account user_key_pair = Keypair.from_secret(private_key) root_account = Account(account_id=user_key_pair.public_key, sequence=1) public_key = root_account.account_id asset_issuer = self.integrated_coins[token.lower()]["assetIssuer"] try: source_account = self.server.load_account(public_key) tx = TransactionBuilder( source_account=source_account, network_passphrase=self.network_phrase, base_fee=self.server.fetch_base_fee()).append_change_trust_op(asset_code=f'{token.upper()}', asset_issuer=asset_issuer).set_timeout( 30).build() tx.sign(private_key) self.server.submit_transaction(tx) return True except exceptions.NotFoundError: return False
def balance(): server = Server("https://horizon-testnet.stellar.org") public_key = "GD4NB2FLQAN5JO7PKPGZJMNBDYQXVSNVC7DEIZMOL5WSNSBLEBUTEF5Q" #SUBSTITUTE WITH MONGODB INFO account = server.accounts().account_id(public_key).call() for balance in account['balances']: print(f"Type: {balance['asset_type']}, Balance: {balance['balance']}")
def get_percent_holders(asset_arr, exceptions, public=False): if public: server = Server(horizon_url="https://horizon.stellar.org") else: server = Server(horizon_url="https://horizon-testnet.stellar.org") data_arr = [] data_dict = {"account_id": {'asset_code': 'balance'}} for i in range(len(asset_arr)): data_arr.append([]) asset = Asset(code=asset_arr[i][0], issuer=asset_arr[i][1]) accounts = server.accounts().for_asset(asset).limit(200).call() while len(accounts['_embedded']['records']) > 0: for r in accounts['_embedded']['records']: if r['account_id'] in exceptions: pass else: for b in r['balances']: if b['asset_code'] == asset_arr[i][0] and b[ 'asset_issuer'] == asset_arr[i][1]: if float(b['balance']) >= 1: try: data_dict[r['account_id']][ asset_arr[i][0]] = b['balance'] except: data_dict[r['account_id']] = {} data_dict[r['account_id']][ asset_arr[i][0]] = b['balance'] data_arr[i].append( [r['account_id'], b['balance']]) break find_cursor_arr = accounts['_links']['next']['href'].split("&") for n in find_cursor_arr: if ("cursor" in n) and len(n) > 7: cursor = n[7:] accounts = server.accounts().for_asset(asset).cursor( cursor).limit(200).call() member_arr = [] for i in range(len(data_arr)): # member_arr.append([]) for j in range(len(data_arr[i])): if data_arr[i][j][0] in member_arr: pass else: member_arr.append(data_arr[i][j][0]) holders_totals = [['account_id']] for a in asset_arr: holders_totals[0].append(a[0]) holders_totals[0].append("STAKED") holders_totals[0].append("MULTIPLIER") for member in member_arr: staking_tracker = [] for a in asset_arr: staking_tracker.append(0) for i in range(len(data_arr)): for account in data_arr[i]: if member in account: staking_tracker[i] = 1 Multiplier = 1 + 0.05 * (sum(staking_tracker) - 1) held_arr = [member] summation = 0 for a in asset_arr: try: amnt = data_dict[member][a[0]] summation += float(amnt) held_arr.append(amnt) except: held_arr.append(0) held_arr.append(summation) held_arr.append(summation * Multiplier) holders_totals.append(held_arr) total_arr = ['Total:'] summation = 0 for i in range(len(data_arr)): temp_tot = 0 for j in range(len(holders_totals) - 1): amt = holders_totals[j + 1][i + 1] temp_tot += float(amt) summation += temp_tot total_arr.append(temp_tot) total_arr.append(summation) summation = 0 for i in range(len(member_arr)): summation += holders_totals[i + 1][len(holders_totals[i]) - 1] total_arr.append(summation) holders_totals.append(total_arr) # df = DF(holders_totals) # print(df) percent_stakes = [] for i in range(len(holders_totals)): new_row = [] for j in range(len(holders_totals[i])): if i == 0 or j == 0: new_row.append(holders_totals[i][j]) else: new_row.append( str( round( 100 * float(holders_totals[i][j]) / total_arr[j], 6)) + "%") percent_stakes.append(new_row) return holders_totals, percent_stakes