importjsonimportosimporturllib.requestNODE_URL=os.getenv('NODE_URL','https://reference.symboltest.net:3001')print(f'Using node {NODE_URL}')defget_account_info(account_identifier):""" Fetch account information by address or public key. Args: account_identifier: The account address or public key Returns: Dictionary containing the account information """account_path=f'/accounts/{account_identifier}'try:withurllib.request.urlopen(f'{NODE_URL}{account_path}')asresponse:account_info=json.loads(response.read().decode())returnaccount_info['account']excepturllib.error.HTTPErrorase:ife.status==404:print(f'Address does not exist: {e}')elife.status==409:print(f'Address is not properly formatted: {e}')else:print(f'Unexpected error: {e}')raiseSystemExit(1)defget_mosaic_names(mosaic_ids):""" Fetch friendly names for a set of mosaics. Args: mosaic_ids: List of mosaic IDs as integers Returns: Dictionary mapping mosaic IDs to their namespace names """mosaic_ids_hex=[f'{mosaic_id:016X}'formosaic_idinmosaic_ids]request_body=json.dumps({'mosaicIds':mosaic_ids_hex}).encode()request=urllib.request.Request(f'{NODE_URL}/namespaces/mosaic/names',data=request_body,headers={'Content-Type':'application/json'})withurllib.request.urlopen(request)asresponse:names_info=json.loads(response.read().decode())# Build a dictionary mapping mosaic IDs to their namesnames_map={}forentryinnames_info['mosaicNames']:mosaic_id=int(entry['mosaicId'],16)names_map[mosaic_id]=entry['names']returnnames_mapdefget_mosaics_info(mosaic_ids):""" Fetch information for multiple mosaics in a single request. Args: mosaic_ids: List of mosaic IDs as integers Returns: Dictionary mapping mosaic IDs to their properties """mosaic_ids_hex=[f'{mosaic_id:016X}'formosaic_idinmosaic_ids]request_body=json.dumps({'mosaicIds':mosaic_ids_hex}).encode()request=urllib.request.Request(f'{NODE_URL}/mosaics',data=request_body,headers={'Content-Type':'application/json'})withurllib.request.urlopen(request)asresponse:mosaics_info=json.loads(response.read().decode())# Build a dictionary mapping mosaic IDs to their propertiesmosaics_map={}forentryinmosaics_info:mosaic_id=int(entry['mosaic']['id'],16)mosaics_map[mosaic_id]=entry['mosaic']returnmosaics_mapdefformat_amount(amount,divisibility):""" Format an atomic amount with decimal places. Args: amount: The atomic amount as an integer divisibility: Number of decimal places Returns: Formatted amount as a string """ifdivisibility==0:returnstr(amount)whole_part=amount//(10**divisibility)fractional_part=amount%(10**divisibility)returnf'{whole_part}.{fractional_part:0{divisibility}d}'# The account address to queryADDRESS=os.getenv('ADDRESS','TBIL6D6RURP45YQRWV6Q7YVWIIPLQGLZQFHWFEQ')print(f'Fetching account information from {ADDRESS}')# Get account informationaccount=get_account_info(ADDRESS)# Display balances for all mosaics the account holdsaccount_mosaics=account['mosaics']ifnotaccount_mosaics:print('Account holds no mosaics')else:print(f'Account holds {len(account_mosaics)} mosaic(s):')# Fetch mosaic properties and names for all mosaicsmosaic_ids=[int(m['id'],16)forminaccount_mosaics]mosaic_names=get_mosaic_names(mosaic_ids)mosaics_info=get_mosaics_info(mosaic_ids)formosaic_entryinaccount_mosaics:mosaic_id=int(mosaic_entry['id'],16)balance=int(mosaic_entry['amount'])# Get mosaic propertiesinfo=mosaics_info[mosaic_id]divisibility=info['divisibility']# Format and display the balanceformatted_balance=format_amount(balance,divisibility)mosaic_id_hex=f'0x{mosaic_id:016X}'# Display mosaic ID and names (if available)names=mosaic_names.get(mosaic_id,[])ifnames:names_str=', '.join(names)print(f'- Mosaic {mosaic_id_hex} ({names_str})')else:print(f'- Mosaic {mosaic_id_hex}')print(f' Balance: {formatted_balance}')print(f' Balance (atomic): {balance}')print(f' Divisibility: {divisibility}')
constNODE_URL=process.env.NODE_URL||'https://reference.symboltest.net:3001';console.log('Using node',NODE_URL);/** * Fetch account information by address or public key. * * @param {string} accountIdentifier - Account address or public key * @returns {Promise<Object>} The account information */asyncfunctiongetAccountInfo(accountIdentifier){constaccountPath=`/accounts/${accountIdentifier}`;constaccountResponse=awaitfetch(`${NODE_URL}${accountPath}`);if(!accountResponse.ok){if(accountResponse.status===404){console.error('Address does not exist:',accountResponse.statusText);}elseif(accountResponse.status===409){console.error('Address is not properly formatted:',accountResponse.statusText);}else{console.error('Unexpected error:',accountResponse.statusText);}process.exit(1);}constaccountInfo=awaitaccountResponse.json();returnaccountInfo.account;}/** * Fetch friendly names for a set of mosaics. * * @param {bigint[]} mosaicIds - Array of mosaic IDs * @returns {Promise<Map>} Map of mosaic IDs to their namespace names */asyncfunctiongetMosaicNames(mosaicIds){constmosaicIdsHex=mosaicIds.map(id=>id.toString(16).toUpperCase().padStart(16,'0'));constresponse=awaitfetch(`${NODE_URL}/namespaces/mosaic/names`,{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({mosaicIds:mosaicIdsHex})});constnamesInfo=awaitresponse.json();// Build a map from mosaic IDs to their namesconstnamesMap=newMap();for(constentryofnamesInfo.mosaicNames){constmosaicId=BigInt(`0x${entry.mosaicId}`);namesMap.set(mosaicId,entry.names);}returnnamesMap;}/** * Fetch information for multiple mosaics in a single request. * * @param {bigint[]} mosaicIds - Array of mosaic IDs * @returns {Promise<Map>} Map of mosaic IDs to their properties */asyncfunctiongetMosaicsInfo(mosaicIds){constmosaicIdsHex=mosaicIds.map(id=>id.toString(16).toUpperCase().padStart(16,'0'));constresponse=awaitfetch(`${NODE_URL}/mosaics`,{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({mosaicIds:mosaicIdsHex})});constmosaicsInfo=awaitresponse.json();// Build a map from mosaic IDs to their propertiesconstmosaicsMap=newMap();for(constentryofmosaicsInfo){constmosaicId=BigInt(`0x${entry.mosaic.id}`);mosaicsMap.set(mosaicId,entry.mosaic);}returnmosaicsMap;}/** * Format an atomic amount with decimal places. * * @param {bigint} amount - The atomic amount * @param {number} divisibility - Number of decimal places * @returns {string} The formatted amount */functionformatAmount(amount,divisibility){if(divisibility===0){returnamount.toString();}constdivisor=10n**BigInt(divisibility);constwholePart=amount/divisor;constfractionalPart=amount%divisor;constfractionalStr=fractionalPart.toString().padStart(divisibility,'0');return`${wholePart}.${fractionalStr}`;}// The account address to queryconstADDRESS=process.env.ADDRESS||'TBIL6D6RURP45YQRWV6Q7YVWIIPLQGLZQFHWFEQ';console.log('Fetching account information from',ADDRESS);// Get account informationconstaccount=awaitgetAccountInfo(ADDRESS);// Display balances for all mosaics the account holdsconstaccountMosaics=account.mosaics;if(accountMosaics.length===0){console.log('Account holds no mosaics');}else{console.log(`Account holds ${accountMosaics.length} mosaic(s):`);// Fetch mosaic properties and names for all mosaicsconstmosaicIds=accountMosaics.map(m=>BigInt(`0x${m.id}`));constmosaicNames=awaitgetMosaicNames(mosaicIds);constmosaicsInfo=awaitgetMosaicsInfo(mosaicIds);for(constmosaicEntryofaccountMosaics){constmosaicId=BigInt(`0x${mosaicEntry.id}`);constbalance=BigInt(mosaicEntry.amount);// Get mosaic propertiesconstinfo=mosaicsInfo.get(mosaicId);constdivisibility=info.divisibility;// Format and display the balanceconstformattedBalance=formatAmount(balance,divisibility);constmosaicIdHex=`0x${mosaicId.toString(16).toUpperCase().padStart(16,'0')}`;// Display mosaic ID and names (if available)constnames=mosaicNames.get(mosaicId)||[];if(names.length>0){console.log(`- Mosaic ${mosaicIdHex} (${names.join(', ')})`);}else{console.log(`- Mosaic ${mosaicIdHex}`);}console.log(` Balance: ${formattedBalance}`);console.log(` Balance (atomic): ${balance.toString()}`);console.log(` Divisibility: ${divisibility}`);}}
defget_account_info(account_identifier):""" Fetch account information by address or public key. Args: account_identifier: The account address or public key Returns: Dictionary containing the account information """account_path=f'/accounts/{account_identifier}'try:withurllib.request.urlopen(f'{NODE_URL}{account_path}')asresponse:account_info=json.loads(response.read().decode())returnaccount_info['account']excepturllib.error.HTTPErrorase:ife.status==404:print(f'Address does not exist: {e}')elife.status==409:print(f'Address is not properly formatted: {e}')else:print(f'Unexpected error: {e}')raiseSystemExit(1)
/** * Fetch account information by address or public key. * * @param {string} accountIdentifier - Account address or public key * @returns {Promise<Object>} The account information */asyncfunctiongetAccountInfo(accountIdentifier){constaccountPath=`/accounts/${accountIdentifier}`;constaccountResponse=awaitfetch(`${NODE_URL}${accountPath}`);if(!accountResponse.ok){if(accountResponse.status===404){console.error('Address does not exist:',accountResponse.statusText);}elseif(accountResponse.status===409){console.error('Address is not properly formatted:',accountResponse.statusText);}else{console.error('Unexpected error:',accountResponse.statusText);}process.exit(1);}constaccountInfo=awaitaccountResponse.json();returnaccountInfo.account;}
defget_mosaic_names(mosaic_ids):""" Fetch friendly names for a set of mosaics. Args: mosaic_ids: List of mosaic IDs as integers Returns: Dictionary mapping mosaic IDs to their namespace names """mosaic_ids_hex=[f'{mosaic_id:016X}'formosaic_idinmosaic_ids]request_body=json.dumps({'mosaicIds':mosaic_ids_hex}).encode()request=urllib.request.Request(f'{NODE_URL}/namespaces/mosaic/names',data=request_body,headers={'Content-Type':'application/json'})withurllib.request.urlopen(request)asresponse:names_info=json.loads(response.read().decode())# Build a dictionary mapping mosaic IDs to their namesnames_map={}forentryinnames_info['mosaicNames']:mosaic_id=int(entry['mosaicId'],16)names_map[mosaic_id]=entry['names']returnnames_map
/** * Fetch friendly names for a set of mosaics. * * @param {bigint[]} mosaicIds - Array of mosaic IDs * @returns {Promise<Map>} Map of mosaic IDs to their namespace names */asyncfunctiongetMosaicNames(mosaicIds){constmosaicIdsHex=mosaicIds.map(id=>id.toString(16).toUpperCase().padStart(16,'0'));constresponse=awaitfetch(`${NODE_URL}/namespaces/mosaic/names`,{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({mosaicIds:mosaicIdsHex})});constnamesInfo=awaitresponse.json();// Build a map from mosaic IDs to their namesconstnamesMap=newMap();for(constentryofnamesInfo.mosaicNames){constmosaicId=BigInt(`0x${entry.mosaicId}`);namesMap.set(mosaicId,entry.names);}returnnamesMap;}
モザイクは64ビットの数値である モザイク ID によって識別されますが、これは読みにくく覚えにくい場合があります。
利便性を高めるために、モザイクを人間が読み取り可能な ネームスペース エイリアスにリンクさせることができます。
defget_mosaics_info(mosaic_ids):""" Fetch information for multiple mosaics in a single request. Args: mosaic_ids: List of mosaic IDs as integers Returns: Dictionary mapping mosaic IDs to their properties """mosaic_ids_hex=[f'{mosaic_id:016X}'formosaic_idinmosaic_ids]request_body=json.dumps({'mosaicIds':mosaic_ids_hex}).encode()request=urllib.request.Request(f'{NODE_URL}/mosaics',data=request_body,headers={'Content-Type':'application/json'})withurllib.request.urlopen(request)asresponse:mosaics_info=json.loads(response.read().decode())# Build a dictionary mapping mosaic IDs to their propertiesmosaics_map={}forentryinmosaics_info:mosaic_id=int(entry['mosaic']['id'],16)mosaics_map[mosaic_id]=entry['mosaic']returnmosaics_map
/** * Fetch information for multiple mosaics in a single request. * * @param {bigint[]} mosaicIds - Array of mosaic IDs * @returns {Promise<Map>} Map of mosaic IDs to their properties */asyncfunctiongetMosaicsInfo(mosaicIds){constmosaicIdsHex=mosaicIds.map(id=>id.toString(16).toUpperCase().padStart(16,'0'));constresponse=awaitfetch(`${NODE_URL}/mosaics`,{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({mosaicIds:mosaicIdsHex})});constmosaicsInfo=awaitresponse.json();// Build a map from mosaic IDs to their propertiesconstmosaicsMap=newMap();for(constentryofmosaicsInfo){constmosaicId=BigInt(`0x${entry.mosaic.id}`);mosaicsMap.set(mosaicId,entry.mosaic);}returnmosaicsMap;}
defformat_amount(amount,divisibility):""" Format an atomic amount with decimal places. Args: amount: The atomic amount as an integer divisibility: Number of decimal places Returns: Formatted amount as a string """ifdivisibility==0:returnstr(amount)whole_part=amount//(10**divisibility)fractional_part=amount%(10**divisibility)returnf'{whole_part}.{fractional_part:0{divisibility}d}'
/** * Format an atomic amount with decimal places. * * @param {bigint} amount - The atomic amount * @param {number} divisibility - Number of decimal places * @returns {string} The formatted amount */functionformatAmount(amount,divisibility){if(divisibility===0){returnamount.toString();}constdivisor=10n**BigInt(divisibility);constwholePart=amount/divisor;constfractionalPart=amount%divisor;constfractionalStr=fractionalPart.toString().padStart(divisibility,'0');return`${wholePart}.${fractionalStr}`;}
# The account address to queryADDRESS=os.getenv('ADDRESS','TBIL6D6RURP45YQRWV6Q7YVWIIPLQGLZQFHWFEQ')print(f'Fetching account information from {ADDRESS}')# Get account informationaccount=get_account_info(ADDRESS)# Display balances for all mosaics the account holdsaccount_mosaics=account['mosaics']ifnotaccount_mosaics:print('Account holds no mosaics')else:print(f'Account holds {len(account_mosaics)} mosaic(s):')# Fetch mosaic properties and names for all mosaicsmosaic_ids=[int(m['id'],16)forminaccount_mosaics]mosaic_names=get_mosaic_names(mosaic_ids)mosaics_info=get_mosaics_info(mosaic_ids)formosaic_entryinaccount_mosaics:mosaic_id=int(mosaic_entry['id'],16)balance=int(mosaic_entry['amount'])# Get mosaic propertiesinfo=mosaics_info[mosaic_id]divisibility=info['divisibility']# Format and display the balanceformatted_balance=format_amount(balance,divisibility)mosaic_id_hex=f'0x{mosaic_id:016X}'# Display mosaic ID and names (if available)names=mosaic_names.get(mosaic_id,[])ifnames:names_str=', '.join(names)print(f'- Mosaic {mosaic_id_hex} ({names_str})')else:print(f'- Mosaic {mosaic_id_hex}')print(f' Balance: {formatted_balance}')print(f' Balance (atomic): {balance}')print(f' Divisibility: {divisibility}')
// The account address to queryconstADDRESS=process.env.ADDRESS||'TBIL6D6RURP45YQRWV6Q7YVWIIPLQGLZQFHWFEQ';console.log('Fetching account information from',ADDRESS);// Get account informationconstaccount=awaitgetAccountInfo(ADDRESS);// Display balances for all mosaics the account holdsconstaccountMosaics=account.mosaics;if(accountMosaics.length===0){console.log('Account holds no mosaics');}else{console.log(`Account holds ${accountMosaics.length} mosaic(s):`);// Fetch mosaic properties and names for all mosaicsconstmosaicIds=accountMosaics.map(m=>BigInt(`0x${m.id}`));constmosaicNames=awaitgetMosaicNames(mosaicIds);constmosaicsInfo=awaitgetMosaicsInfo(mosaicIds);for(constmosaicEntryofaccountMosaics){constmosaicId=BigInt(`0x${mosaicEntry.id}`);constbalance=BigInt(mosaicEntry.amount);// Get mosaic propertiesconstinfo=mosaicsInfo.get(mosaicId);constdivisibility=info.divisibility;// Format and display the balanceconstformattedBalance=formatAmount(balance,divisibility);constmosaicIdHex=`0x${mosaicId.toString(16).toUpperCase().padStart(16,'0')}`;// Display mosaic ID and names (if available)constnames=mosaicNames.get(mosaicId)||[];if(names.length>0){console.log(`- Mosaic ${mosaicIdHex} (${names.join(', ')})`);}else{console.log(`- Mosaic ${mosaicIdHex}`);}console.log(` Balance: ${formattedBalance}`);console.log(` Balance (atomic): ${balance.toString()}`);console.log(` Divisibility: ${divisibility}`);}}