importjsonimportosimporttimeimporturllib.requestfromsymbolchain.CryptoTypesimportPrivateKeyfromsymbolchain.facade.NemFacadeimportNemFacadefromsymbolchain.ncimportAmountfromsymbolchain.nem.FeeCalculatorimportcalculate_transaction_feefromsymbolchain.nem.NetworkimportNetworkTimestampNODE_URL=os.getenv('NODE_URL','http://libertalia.nemtest.net:7890')print(f'Using node {NODE_URL}')# Helper function to announce a transactiondefannounce_transaction(payload,label):announce_path='/transaction/announce'print(f'Announcing {label} to {announce_path}')request=urllib.request.Request(f'{NODE_URL}{announce_path}',data=payload.encode(),headers={'Content-Type':'application/json'},method='POST')withurllib.request.urlopen(request)asannounce_response:result=json.loads(announce_response.read().decode())print(f' Result: {result["message"]}')returnresult['message']# Helper function to fetch the current mosaic supplydeffetch_supply(mosaic):supply_path=f'/mosaic/supply?mosaicId={mosaic}'withurllib.request.urlopen(f'{NODE_URL}{supply_path}')assupply_response:supply_info=json.loads(supply_response.read().decode())returnsupply_info['supply']# Helper function to wait for transaction confirmationdefwait_for_confirmation(tx_hash,label):status_path=f'/transaction/get?hash={tx_hash}'print(f'Waiting for {label} confirmation from {status_path}')is_confirmed=Falsefor_inrange(120):try:withurllib.request.urlopen(f'{NODE_URL}{status_path}')asstatus_response:confirmed=json.loads(status_response.read().decode())height=confirmed['meta']['height']print(f'{label} confirmed in block {height}')is_confirmed=Truebreakexcepturllib.error.HTTPError:print(' Transaction status: pending')time.sleep(1)ifnotis_confirmed:print(f'{label} confirmation took too long.')SIGNER_PRIVATE_KEY=os.getenv('SIGNER_PRIVATE_KEY','0000000000000000000000000000000000000000000000000000000000000000')signer_key_pair=NemFacade.KeyPair(PrivateKey(SIGNER_PRIVATE_KEY))facade=NemFacade('testnet')signer_address=facade.network.public_key_to_address(signer_key_pair.public_key)print(f'Signer address: {signer_address}')namespace_name=os.getenv('NAMESPACE','my_namespace')mosaic_name=os.getenv('MOSAIC','token')mosaic_id=f'{namespace_name}:{mosaic_name}'print(f'Mosaic ID: {mosaic_id}')try:# Fetch current network timetime_path='/time-sync/network-time'print(f'Fetching current network time from {time_path}')withurllib.request.urlopen(f'{NODE_URL}{time_path}')asresponse:response_json=json.loads(response.read().decode())network_time=response_json['receiveTimeStamp']//1000print(f' Network time: {network_time} s since the nemesis block')# Derived fields from network timetimestamp=NetworkTimestamp(network_time)deadline=timestamp.add_hours(2)# --- INCREASING SUPPLY (MINTING) ---print('\n--- Increasing supply (minting) ---')print(f'Supply before minting: {fetch_supply(mosaic_id)}')increase_tx=facade.transaction_factory.create({'type':'mosaic_supply_change_transaction_v1','signer_public_key':signer_key_pair.public_key,'timestamp':timestamp.timestamp,'deadline':deadline.timestamp,'mosaic_id':{'namespace_id':{'name':namespace_name},'name':mosaic_name},'action':'increase','delta':500})increase_tx.fee=Amount(calculate_transaction_fee(increase_tx))signature=facade.sign_transaction(signer_key_pair,increase_tx)json_payload=facade.transaction_factory.attach_signature(increase_tx,signature)print('Built supply increase transaction:')print(json.dumps(increase_tx.to_json(),indent=2))if'SUCCESS'==announce_transaction(json_payload,'supply increase'):wait_for_confirmation(facade.hash_transaction(increase_tx),'supply increase')print(f'Supply after minting: {fetch_supply(mosaic_id)}')else:print('Supply increase rejected')# --- DECREASING SUPPLY (BURNING) ---print('\n--- Decreasing supply (burning) ---')decrease_tx=facade.transaction_factory.create({'type':'mosaic_supply_change_transaction_v1','signer_public_key':signer_key_pair.public_key,'timestamp':timestamp.timestamp,'deadline':deadline.timestamp,'mosaic_id':{'namespace_id':{'name':namespace_name},'name':mosaic_name},'action':'decrease','delta':500})decrease_tx.fee=Amount(calculate_transaction_fee(decrease_tx))signature=facade.sign_transaction(signer_key_pair,decrease_tx)json_payload=facade.transaction_factory.attach_signature(decrease_tx,signature)print('Built supply decrease transaction:')print(json.dumps(decrease_tx.to_json(),indent=2))if'SUCCESS'==announce_transaction(json_payload,'supply decrease'):wait_for_confirmation(facade.hash_transaction(decrease_tx),'supply decrease')print(f'Supply after burning: {fetch_supply(mosaic_id)}')else:print('Supply decrease rejected')excepturllib.error.URLErrorase:print(e.reason)
import{PrivateKey}from'symbol-sdk';import{NemFacade,NetworkTimestamp,calculateTransactionFee,models}from'symbol-sdk/nem';constNODE_URL=process.env.NODE_URL||'http://libertalia.nemtest.net:7890';console.log('Using node',NODE_URL);// Helper function to announce a transactionasyncfunctionannounceTransaction(payload,label){constannouncePath='/transaction/announce';console.log(`Announcing ${label} to ${announcePath}`);constannounceResponse=awaitfetch(`${NODE_URL}${announcePath}`,{method:'POST',headers:{'Content-Type':'application/json'},body:payload});constresult=awaitannounceResponse.json();console.log(' Result:',result.message);returnresult.message;}// Helper function to fetch the current mosaic supplyasyncfunctionfetchSupply(mosaic){constsupplyPath=`/mosaic/supply?mosaicId=${mosaic}`;constsupplyResponse=awaitfetch(`${NODE_URL}${supplyPath}`);constsupplyInfo=awaitsupplyResponse.json();returnsupplyInfo.supply;}// Helper function to wait for transaction confirmationasyncfunctionwaitForConfirmation(transactionHash,label){conststatusPath=`/transaction/get?hash=${transactionHash}`;console.log(`Waiting for ${label} confirmation from`,statusPath);letisConfirmed=false;for(letattempt=1;120>=attempt;++attempt){constresponse=awaitfetch(`${NODE_URL}${statusPath}`);if(response.ok){constconfirmed=awaitresponse.json();console.log(`${label} confirmed in block`,confirmed.meta.height);isConfirmed=true;break;}console.log(' Transaction status: pending');awaitnewPromise(resolve=>{setTimeout(resolve,1000);});}if(!isConfirmed)console.warn(`${label} confirmation took too long.`);}constSIGNER_PRIVATE_KEY=process.env.SIGNER_PRIVATE_KEY||'0000000000000000000000000000000000000000000000000000000000000000';constsignerKeyPair=newNemFacade.KeyPair(newPrivateKey(SIGNER_PRIVATE_KEY));constfacade=newNemFacade('testnet');constsignerAddress=facade.network.publicKeyToAddress(signerKeyPair.publicKey);console.log('Signer address:',signerAddress.toString());constnamespaceName=process.env.NAMESPACE||'my_namespace';constmosaicName=process.env.MOSAIC||'token';constmosaicId=`${namespaceName}:${mosaicName}`;console.log('Mosaic ID:',mosaicId);try{// Fetch current network timeconsttimePath='/time-sync/network-time';console.log('Fetching current network time from',timePath);consttimeResponse=awaitfetch(`${NODE_URL}${timePath}`);consttimeJSON=awaittimeResponse.json();constnetworkTime=Math.floor(timeJSON.receiveTimeStamp/1000);console.log(' Network time:',networkTime,'s since the nemesis block');// Derived fields from network timeconsttimestamp=newNetworkTimestamp(networkTime);constdeadline=timestamp.addHours(2);// --- INCREASING SUPPLY (MINTING) ---console.log('\n--- Increasing supply (minting) ---');console.log('Supply before minting:',awaitfetchSupply(mosaicId));constincreaseTx=facade.transactionFactory.create({type:'mosaic_supply_change_transaction_v1',signerPublicKey:signerKeyPair.publicKey.toString(),timestamp:timestamp.timestamp,deadline:deadline.timestamp,mosaicId:{namespaceId:{name:namespaceName},name:mosaicName},action:'increase',delta:500n});increaseTx.fee=newmodels.Amount(calculateTransactionFee(increaseTx));constincreaseSignature=facade.signTransaction(signerKeyPair,increaseTx);constincreasePayload=facade.transactionFactory.static.attachSignature(increaseTx,increaseSignature);console.log('Built supply increase transaction:');console.dir(increaseTx.toJson(),{colors:true});constincreaseResult=awaitannounceTransaction(increasePayload,'supply increase');if('SUCCESS'===increaseResult){awaitwaitForConfirmation(facade.hashTransaction(increaseTx).toString(),'supply increase');console.log('Supply after minting:',awaitfetchSupply(mosaicId));}else{console.log('Supply increase rejected');}// --- DECREASING SUPPLY (BURNING) ---console.log('\n--- Decreasing supply (burning) ---');constdecreaseTx=facade.transactionFactory.create({type:'mosaic_supply_change_transaction_v1',signerPublicKey:signerKeyPair.publicKey.toString(),timestamp:timestamp.timestamp,deadline:deadline.timestamp,mosaicId:{namespaceId:{name:namespaceName},name:mosaicName},action:'decrease',delta:500n});decreaseTx.fee=newmodels.Amount(calculateTransactionFee(decreaseTx));constdecreaseSignature=facade.signTransaction(signerKeyPair,decreaseTx);constdecreasePayload=facade.transactionFactory.static.attachSignature(decreaseTx,decreaseSignature);console.log('Built supply decrease transaction:');console.dir(decreaseTx.toJson(),{colors:true});constdecreaseResult=awaitannounceTransaction(decreasePayload,'supply decrease');if('SUCCESS'===decreaseResult){awaitwaitForConfirmation(facade.hashTransaction(decreaseTx).toString(),'supply decrease');console.log('Supply after burning:',awaitfetchSupply(mosaicId));}else{console.log('Supply decrease rejected');}}catch(e){console.error(e.message,'| Cause:',e.cause?.code??'unknown');}
# Fetch current network timetime_path='/time-sync/network-time'print(f'Fetching current network time from {time_path}')withurllib.request.urlopen(f'{NODE_URL}{time_path}')asresponse:response_json=json.loads(response.read().decode())network_time=response_json['receiveTimeStamp']//1000print(f' Network time: {network_time} s since the nemesis block')# Derived fields from network timetimestamp=NetworkTimestamp(network_time)deadline=timestamp.add_hours(2)
// Fetch current network timeconsttimePath='/time-sync/network-time';console.log('Fetching current network time from',timePath);consttimeResponse=awaitfetch(`${NODE_URL}${timePath}`);consttimeJSON=awaittimeResponse.json();constnetworkTime=Math.floor(timeJSON.receiveTimeStamp/1000);console.log(' Network time:',networkTime,'s since the nemesis block');// Derived fields from network timeconsttimestamp=newNetworkTimestamp(networkTime);constdeadline=timestamp.addHours(2);