importjsonimportosimporttimeimporturllib.requestfromsymbolchain.CryptoTypesimportPrivateKeyfromsymbolchain.facade.SymbolFacadeimportSymbolFacadefromsymbolchain.symbol.Restrictionimportmosaic_restriction_generate_keyNODE_URL=os.getenv('NODE_URL','https://reference.symboltest.net:3001')print(f'Using node {NODE_URL}')facade=SymbolFacade('testnet')OWNER_PRIVATE_KEY=os.getenv('OWNER_PRIVATE_KEY','0000000000000000000000000000000000000000000000000000000000000000')owner_key_pair=SymbolFacade.KeyPair(PrivateKey(OWNER_PRIVATE_KEY))owner_address=facade.network.public_key_to_address(owner_key_pair.public_key)print(f'Owner address: {owner_address}')target_address=os.getenv('TARGET_ADDRESS','TB6QOVCUOFRCF5QJSKPIQMLUVWGJS3KYFDETRPA')print(f'Target address: {target_address}')mosaic_id=int(os.getenv('MOSAIC_ID','6A5ACF2376E50D4A'),16)print(f'Mosaic ID: 0x{mosaic_id:016X}')restriction_name=os.getenv('RESTRICTION_NAME','security_level')restriction_key=mosaic_restriction_generate_key(restriction_name)print(f'Restriction name: "{restriction_name}"'f' (key: 0x{restriction_key:016X})')# Helper function to announce a transactiondefannounce_transaction(payload,label):print(f'Announcing {label} to /transactions')request=urllib.request.Request(f'{NODE_URL}/transactions',data=payload.encode(),headers={'Content-Type':'application/json'},method='PUT')withurllib.request.urlopen(request)asannounce_response:print(f' Response: {announce_response.read().decode()}')# Helper function to wait for transaction confirmationdefwait_for_confirmation(tx_hash,label):print(f'Waiting for {label} confirmation...')forattemptinrange(60):time.sleep(1)try:url=f'{NODE_URL}/transactionStatus/{tx_hash}'withurllib.request.urlopen(url)asconfirm_response:status=json.loads(confirm_response.read().decode())print(f" Transaction status: {status['group']}")ifstatus['group']=='confirmed':print(f'{label} confirmed in {attempt} seconds')returnifstatus['group']=='failed':raiseRuntimeError(f"{label} failed: {status['code']}")excepturllib.error.HTTPError:print(' Transaction status: unknown')raiseTimeoutError(f'{label} not confirmed after 60 seconds')# Returns a filtered list of restrictions currently applied to the mosaic# matching the given restriction keydefget_mosaic_restrictions(query,key):restrictions_path=f'/restrictions/mosaic?{query}'print(f' Getting restrictions from {restrictions_path}')res=[]url=f'{NODE_URL}{restrictions_path}'withurllib.request.urlopen(url)asrestr_response:status=json.loads(restr_response.read().decode())data=status['data']iflen(data)>0:# Look at the first returned restrictionrlist=data[0]['mosaicRestrictionEntry']['restrictions']# Filter by keyres=[rforrinrlistifint(r['key'])==key]print(f' Response: {res}')returnresdefget_mosaic_global_restrictions(queried_mosaic_id,key):returnget_mosaic_restrictions(f'mosaicId={queried_mosaic_id:016X}&entryType=1',key)defget_mosaic_address_restrictions(queried_mosaic_id,address,key):returnget_mosaic_restrictions(f'mosaicId={queried_mosaic_id:016X}&'f'entryType=0&targetAddress={address}',key)# Returns a transaction enabling a mosaic's global restrictiondefset_global_restriction_transaction():restr_transaction=facade.create_embedded_transaction_from_descriptor({'type':'mosaic_global_restriction_transaction_v1','mosaic_id':mosaic_id,'reference_mosaic_id':0,'restriction_key':restriction_key,'previous_restriction_type':0,'previous_restriction_value':0,'new_restriction_type':'ge','new_restriction_value':1},owner_key_pair.public_key)print(json.dumps(restr_transaction.to_json(),indent=2))returnrestr_transaction# Returns a transaction setting an address restriction's valuedefaddress_restriction_set_value(previous_value,new_value,address):restr_transaction=facade.create_embedded_transaction_from_descriptor({'type':'mosaic_address_restriction_transaction_v1','mosaic_id':mosaic_id,'restriction_key':restriction_key,'previous_restriction_value':previous_value,'new_restriction_value':new_value,'target_address':address},owner_key_pair.public_key)print(json.dumps(restr_transaction.to_json(),indent=2))returnrestr_transactiontry:# Fetch recommended feesfee_path='/network/fees/transaction'print(f'Fetching recommended fees from {fee_path}')withurllib.request.urlopen(f'{NODE_URL}{fee_path}')asresponse:response_json=json.loads(response.read().decode())median_multiplier=response_json['medianFeeMultiplier']minimum_multiplier=response_json['minFeeMultiplier']fee_multiplier=max(median_multiplier,minimum_multiplier)print(f' Fee multiplier: {fee_multiplier}')# Enable global restriction if requiredtransactions=[]print('Checking if the global restriction is enabled:')global_restrictions=get_mosaic_global_restrictions(mosaic_id,restriction_key)iflen(global_restrictions)==0:# Enable the global restrictionprint('+ Enabling global restriction')transactions.append(set_global_restriction_transaction())# Enable the address restrictionprint('+ Authorizing owner account')transactions.append(address_restriction_set_value(0xFFFFFFFF_FFFFFFFF,1,owner_address))# Toggle target address restrictionprint('Checking if target account is authorized:')address_restrictions=get_mosaic_address_restrictions(mosaic_id,target_address,restriction_key)prev_value=0xFFFFFFFF_FFFFFFFFiflen(address_restrictions)>0:prev_value=int(address_restrictions[0]['value'])ifprev_value!=1:# Enable the address restrictionprint('+ Authorizing target account')transactions.append(address_restriction_set_value(prev_value,1,target_address))else:# Disable the address restrictionprint('+ Deauthorizing target account')transactions.append(address_restriction_set_value(prev_value,0,target_address))# Build an aggregate transactionprint('Bundling',len(transactions),'transaction(s) in an aggregate')aggregate_transaction=facade.create_transaction_from_descriptor({'type':'aggregate_complete_transaction_v3','transactions_hash':facade.hash_embedded_transactions(transactions),'transactions':transactions},owner_key_pair.public_key,fee_multiplier,2*60*60)# Sign, announce and wait for confirmationaggregate_payload=facade.transaction_factory.attach_signature(aggregate_transaction,facade.sign_transaction(owner_key_pair,aggregate_transaction))aggregate_hash=facade.hash_transaction(aggregate_transaction)announce_transaction(aggregate_payload,'aggregate')wait_for_confirmation(aggregate_hash,'aggregate')# Try to transfer the mosaic to the target addresstest_transaction=facade.create_transaction_from_descriptor({'type':'transfer_transaction_v1','recipient_address':target_address,'mosaics':[{'mosaic_id':mosaic_id,'amount':1}]},owner_key_pair.public_key,fee_multiplier,2*60*60)test_payload=facade.transaction_factory.attach_signature(test_transaction,facade.sign_transaction(owner_key_pair,test_transaction))test_hash=facade.hash_transaction(test_transaction)print('\nAttempting transfer to the target account')announce_transaction(test_payload,'test transfer')wait_for_confirmation(test_hash,'test transfer')exceptExceptionase:print(e)
import{PrivateKey}from'symbol-sdk';import{KeyPair,SymbolFacade,SymbolTransactionFactory,descriptors,models,mosaicRestrictionGenerateKey}from'symbol-sdk/symbol';constNODE_URL=process.env.NODE_URL||'https://reference.symboltest.net:3001';console.log('Using node',NODE_URL);constfacade=newSymbolFacade('testnet');constOWNER_PRIVATE_KEY=process.env.OWNER_PRIVATE_KEY||'0000000000000000000000000000000000000000000000000000000000000000';constownerKeyPair=newKeyPair(newPrivateKey(OWNER_PRIVATE_KEY));constownerAddress=facade.network.publicKeyToAddress(ownerKeyPair.publicKey);console.log(`Owner address: ${ownerAddress}`);consttargetAddress=process.env.TARGET_ADDRESS||'TB6QOVCUOFRCF5QJSKPIQMLUVWGJS3KYFDETRPA';console.log(`Target address: ${targetAddress}`);constmosaicId=BigInt(`0x${process.env.MOSAIC_ID||'6A5ACF2376E50D4A'}`);console.log(`Mosaic ID: 0x${mosaicId.toString(16).toUpperCase().padStart(16,'0')}`);constrestrictionName=process.env.RESTRICTION_NAME||'security_level';constrestrictionKey=mosaicRestrictionGenerateKey(restrictionName);console.log(`Restriction name: "${restrictionName}" (key: 0x${restrictionKey.toString(16).toUpperCase().padStart(16,'0')})`);// Helper function to announce a transactionasyncfunctionannounceTransaction(payload,label){console.log(`Announcing ${label} to /transactions`);constresponse=awaitfetch(`${NODE_URL}/transactions`,{method:'PUT',headers:{'Content-Type':'application/json'},body:payload});console.log(' Response:',awaitresponse.text());}// Helper function to wait for transaction confirmationasyncfunctionwaitForConfirmation(transactionHash,label){console.log(`Waiting for ${label} confirmation...`);for(letattempt=0;60>attempt;attempt++){awaitnewPromise(resolve=>{setTimeout(resolve,1000);});constresponse=awaitfetch(`${NODE_URL}/transactionStatus/${transactionHash}`);if(!response.ok){if(404===response.status){console.log(' Transaction status: unknown');continue;}thrownewError(`HTTP ${response.status}`);}conststatus=awaitresponse.json();console.log(' Transaction status:',status.group);if('confirmed'===status.group){console.log(`${label} confirmed in`,attempt,'seconds');return;}if('failed'===status.group)thrownewError(`${label} failed: ${status.code}`);}thrownewError(`${label} not confirmed after 60 seconds`);}// Returns restrictions currently applied to the mosaic// matching the given restriction keyasyncfunctiongetMosaicRestrictions(query,key){constrestrictionsPath=`/restrictions/mosaic?${query}`;console.log(` Getting restrictions from ${restrictionsPath}`);letres=[];constresponse=awaitfetch(`${NODE_URL}${restrictionsPath}`);conststatus=awaitresponse.json();constdata=status.data;if(0<data.length){// Look at the first returned restrictionconstrlist=data[0].mosaicRestrictionEntry.restrictions;// Filter by keyres=rlist.filter(r=>BigInt(r.key)===key);}console.log(' Response:',res);returnres;}functiongetMosaicGlobalRestrictions(queriedMosaicId,key){returngetMosaicRestrictions(`mosaicId=${queriedMosaicId.toString(16).toUpperCase().padStart(16,'0')}`+'&entryType=1',key);}functiongetMosaicAddressRestrictions(queriedMosaicId,address,key){returngetMosaicRestrictions(`mosaicId=${queriedMosaicId.toString(16).toUpperCase().padStart(16,'0')}`+`&entryType=0&targetAddress=${address}`,key);}// Returns a transaction enabling a mosaic's global restrictionfunctionglobalRestrictionEnableTransaction(){consttransaction=facade.createEmbeddedTransactionFromTypedDescriptor(newdescriptors.MosaicGlobalRestrictionTransactionV1Descriptor(newmodels.UnresolvedMosaicId(mosaicId),newmodels.UnresolvedMosaicId(0n),restrictionKey,0n,1n,models.MosaicRestrictionType.NONE,models.MosaicRestrictionType.GE),ownerKeyPair.publicKey);console.dir(transaction.toJson(),{colors:true,depth:null});returntransaction;}// Returns a transaction setting an address restriction's valuefunctionaddressRestrictionSetValue(prevValue,newValue,address){consttransaction=facade.createEmbeddedTransactionFromTypedDescriptor(newdescriptors.MosaicAddressRestrictionTransactionV1Descriptor(newmodels.UnresolvedMosaicId(mosaicId),restrictionKey,prevValue,newValue,newSymbolFacade.Address(address)),ownerKeyPair.publicKey);console.dir(transaction.toJson(),{colors:true,depth:null});returntransaction;}try{// Fetch recommended feesconstfeePath='/network/fees/transaction';console.log('Fetching recommended fees from',feePath);constfeeResponse=awaitfetch(`${NODE_URL}${feePath}`);constfeeJSON=awaitfeeResponse.json();constmedianMultiplier=feeJSON.medianFeeMultiplier;constminimumMultiplier=feeJSON.minFeeMultiplier;constfeeMultiplier=Math.max(medianMultiplier,minimumMultiplier);console.log(' Fee multiplier:',feeMultiplier);// Enable global restriction if requiredconsttransactions=[];console.log('Checking if the global restriction is enabled:');constglobalRestrictions=awaitgetMosaicGlobalRestrictions(mosaicId,restrictionKey);if(0===globalRestrictions.length){// Enable the global restrictionconsole.log('+ Enabling global restriction');transactions.push(globalRestrictionEnableTransaction());// Enable the address restrictionconsole.log('+ Authorizing owner account');transactions.push(addressRestrictionSetValue(0xFFFFFFFFFFFFFFFFn,1n,ownerAddress.toString()));}// Toggle target address restrictionconsole.log('Checking if target account is authorized:');constaddressRestrictions=awaitgetMosaicAddressRestrictions(mosaicId,targetAddress,restrictionKey);letprevValue=0xFFFFFFFFFFFFFFFFn;if(0<addressRestrictions.length)prevValue=BigInt(addressRestrictions[0].value);if(1n!==prevValue){// Enable the address restrictionconsole.log('+ Authorizing target account');transactions.push(addressRestrictionSetValue(prevValue,1n,targetAddress));}else{// Disable the address restrictionconsole.log('+ Deauthorizing target account');transactions.push(addressRestrictionSetValue(prevValue,0n,targetAddress));}// Build an aggregate transactionconsole.log('Bundling',transactions.length,'transaction(s) in an aggregate');constaggregateTransaction=facade.createTransactionFromTypedDescriptor(newdescriptors.AggregateCompleteTransactionV3Descriptor(facade.static.hashEmbeddedTransactions(transactions),transactions,undefined),ownerKeyPair.publicKey,feeMultiplier,2*60*60);// Sign, announce and wait for confirmationconstaggregatePayload=SymbolTransactionFactory.attachSignature(aggregateTransaction,facade.signTransaction(ownerKeyPair,aggregateTransaction));constaggregateHash=facade.hashTransaction(aggregateTransaction).toString();awaitannounceTransaction(aggregatePayload,'aggregate');awaitwaitForConfirmation(aggregateHash,'aggregate');// Try to transfer the mosaic to the target addressconsttestTransaction=facade.createTransactionFromTypedDescriptor(newdescriptors.TransferTransactionV1Descriptor(newSymbolFacade.Address(targetAddress),[newdescriptors.UnresolvedMosaicDescriptor(newmodels.UnresolvedMosaicId(mosaicId),newmodels.Amount(1n))],undefined),ownerKeyPair.publicKey,feeMultiplier,2*60*60);consttestPayload=SymbolTransactionFactory.attachSignature(testTransaction,facade.signTransaction(ownerKeyPair,testTransaction));consttestHash=facade.hashTransaction(testTransaction).toString();console.log('\nAttempting transfer to the target account');awaitannounceTransaction(testPayload,'test transfer');awaitwaitForConfirmation(testHash,'test transfer');}catch(e){console.error(e.message);}
//JAVA 21+//DEPS org.symbol:symbol-sdk:3.3.1importjava.io.IOException;importjava.net.URI;importjava.net.http.HttpClient;importjava.net.http.HttpRequest;importjava.net.http.HttpResponse;importjava.net.http.HttpResponse.BodyHandlers;importjava.util.ArrayList;importjava.util.List;importcom.fasterxml.jackson.databind.JsonNode;importcom.fasterxml.jackson.databind.ObjectMapper;importorg.symbol.sdk.CryptoTypes;importorg.symbol.sdk.facade.SymbolFacade;importorg.symbol.sdk.symbol.Address;importorg.symbol.sdk.symbol.KeyPair;importorg.symbol.sdk.symbol.Restriction;importorg.symbol.sdk.symbol.SymbolTransactionFactory;importorg.symbol.sdk.symbol.descriptors.*;importorg.symbol.sdk.symbol.models.*;publicfinalclassMosaicRestrictions{privatestaticfinalObjectMapperJSON_MAPPER=newObjectMapper();privatestaticfinalHttpClientHTTP_CLIENT=HttpClient.newHttpClient();privatefinalStringnodeUrl=System.getenv().getOrDefault("NODE_URL","https://reference.symboltest.net:3001");privatefinalSymbolFacadefacade=newSymbolFacade("testnet");privateKeyPairownerKeyPair;privateAddressownerAddress;privateAddresstargetAddress;privatelongmosaicId;privatelongrestrictionKey;// Helper function to announce a transactionprivatevoidannounceTransaction(finalStringpayload,finalStringlabel)throwsIOException,InterruptedException{System.out.printf("Announcing %s to /transactions%n",label);finalHttpRequestrequest=HttpRequest.newBuilder(URI.create(nodeUrl+"/transactions")).header("Content-Type","application/json").PUT(HttpRequest.BodyPublishers.ofString(payload)).build();finalHttpResponse<String>response=HTTP_CLIENT.send(request,BodyHandlers.ofString());System.out.printf(" Response: %s%n",response.body());}// Helper function to wait for transaction confirmationprivatevoidwaitForConfirmation(finalStringtransactionHash,finalStringlabel)throwsIOException,InterruptedException{System.out.printf("Waiting for %s confirmation...%n",label);for(intattempt=0;60>attempt;++attempt){Thread.sleep(1000);finalStringstatusPath="/transactionStatus/"+transactionHash;finalHttpRequeststatusRequest=HttpRequest.newBuilder(URI.create(nodeUrl+statusPath)).GET().build();finalHttpResponse<String>statusResponse=HTTP_CLIENT.send(statusRequest,BodyHandlers.ofString());if(404==statusResponse.statusCode()){System.out.println(" Transaction status: unknown");continue;}if(2!=statusResponse.statusCode()/100)thrownewIOException("HTTP "+statusResponse.statusCode());finalJsonNodestatus=JSON_MAPPER.readTree(statusResponse.body());finalStringgroup=status.get("group").asText();System.out.printf(" Transaction status: %s%n",group);if("confirmed".equals(group)){System.out.printf("%s confirmed in %d seconds%n",label,attempt);return;}if("failed".equals(group))thrownewIOException(String.format("%s failed: %s",label,status.get("code").asText()));}thrownewIOException(String.format("%s not confirmed after 60 seconds",label));}// Returns restrictions currently applied to the mosaic// matching the given restriction keyprivateList<JsonNode>getMosaicRestrictions(finalStringquery,finallongkey)throwsIOException,InterruptedException{finalStringrestrictionsPath="/restrictions/mosaic?"+query;System.out.printf(" Getting restrictions from %s%n",restrictionsPath);finalHttpRequestrequest=HttpRequest.newBuilder(URI.create(nodeUrl+restrictionsPath)).GET().build();finalHttpResponse<String>response=HTTP_CLIENT.send(request,BodyHandlers.ofString());finalList<JsonNode>result=newArrayList<>();finalJsonNodedata=JSON_MAPPER.readTree(response.body()).get("data");if(!data.isEmpty()){// Look at the first returned restrictionfinalJsonNoderestrictions=data.get(0).get("mosaicRestrictionEntry").get("restrictions");// Filter by keyfor(finalJsonNoderestriction:restrictions){finallongrestrictionValue=Long.parseUnsignedLong(restriction.get("key").asText());if(restrictionValue==key)result.add(restriction);}}System.out.printf(" Response: %s%n",result);returnresult;}privateList<JsonNode>getMosaicGlobalRestrictions(finallongqueriedMosaicId,finallongkey)throwsIOException,InterruptedException{returngetMosaicRestrictions(String.format("mosaicId=%016X&entryType=1",queriedMosaicId),key);}privateList<JsonNode>getMosaicAddressRestrictions(finallongqueriedMosaicId,finalAddressaddress,finallongkey)throwsIOException,InterruptedException{returngetMosaicRestrictions(String.format("mosaicId=%016X&entryType=0&targetAddress=%s",queriedMosaicId,address),key);}// Returns a transaction enabling a mosaic's global restrictionprivateEmbeddedTransactionsetGlobalRestrictionTransaction()throwsIOException{finalEmbeddedTransactiontransaction=facade.createEmbeddedTransactionFromTypedDescriptor(newMosaicGlobalRestrictionTransactionV1Descriptor(newUnresolvedMosaicId(mosaicId),newUnresolvedMosaicId(0),restrictionKey,0,1,MosaicRestrictionType.NONE,MosaicRestrictionType.GE),ownerKeyPair.getPublicKey());System.out.println(JSON_MAPPER.writerWithDefaultPrettyPrinter().writeValueAsString(transaction.toJson()));returntransaction;}// Returns a transaction setting an address restriction's valueprivateEmbeddedTransactionaddressRestrictionSetValue(finallongpreviousValue,finallongnewValue,finalAddressaddress)throwsIOException{finalEmbeddedTransactiontransaction=facade.createEmbeddedTransactionFromTypedDescriptor(newMosaicAddressRestrictionTransactionV1Descriptor(newUnresolvedMosaicId(mosaicId),restrictionKey,previousValue,newValue,address),ownerKeyPair.getPublicKey());System.out.println(JSON_MAPPER.writerWithDefaultPrettyPrinter().writeValueAsString(transaction.toJson()));returntransaction;}publicstaticvoidmain(finalString[]args){try{newMosaicRestrictions().run();}catch(finalExceptionex){System.out.println(null==ex.getMessage()?ex.toString():ex.getMessage());}}privatevoidrun()throwsIOException,InterruptedException{System.out.printf("Using node %s%n",nodeUrl);finalStringprivateKeyString=System.getenv().getOrDefault("OWNER_PRIVATE_KEY","0".repeat(64));ownerKeyPair=newKeyPair(newCryptoTypes.PrivateKey(privateKeyString));ownerAddress=facade.network.publicKeyToAddress(ownerKeyPair.getPublicKey());System.out.printf("Owner address: %s%n",ownerAddress);targetAddress=newAddress(System.getenv().getOrDefault("TARGET_ADDRESS","TB6QOVCUOFRCF5QJSKPIQMLUVWGJS3KYFDETRPA"));System.out.printf("Target address: %s%n",targetAddress);mosaicId=Long.parseUnsignedLong(System.getenv().getOrDefault("MOSAIC_ID","6A5ACF2376E50D4A"),16);System.out.printf("Mosaic ID: 0x%016X%n",mosaicId);finalStringrestrictionName=System.getenv().getOrDefault("RESTRICTION_NAME","security_level");restrictionKey=Restriction.mosaicRestrictionGenerateKey(restrictionName);System.out.printf("Restriction name: \"%s\" (key: 0x%016X)%n",restrictionName,restrictionKey);// Fetch recommended feesfinalStringfeePath="/network/fees/transaction";System.out.printf("Fetching recommended fees from %s%n",feePath);finalHttpRequestfeeRequest=HttpRequest.newBuilder(URI.create(nodeUrl+feePath)).GET().build();finalHttpResponse<String>feeResponse=HTTP_CLIENT.send(feeRequest,BodyHandlers.ofString());finalJsonNodefeeJson=JSON_MAPPER.readTree(feeResponse.body());finallongfeeMultiplier=Math.max(feeJson.get("medianFeeMultiplier").asLong(),feeJson.get("minFeeMultiplier").asLong());System.out.printf(" Fee multiplier: %d%n",feeMultiplier);// Enable global restriction if requiredfinalList<EmbeddedTransaction>transactions=newArrayList<>();System.out.println("Checking if the global restriction is enabled:");finalList<JsonNode>globalRestrictions=getMosaicGlobalRestrictions(mosaicId,restrictionKey);if(globalRestrictions.isEmpty()){// Enable the global restrictionSystem.out.println("+ Enabling global restriction");transactions.add(setGlobalRestrictionTransaction());// Enable the address restrictionSystem.out.println("+ Authorizing owner account");transactions.add(addressRestrictionSetValue(0xFFFFFFFFFFFFFFFFL,1,ownerAddress));}// Toggle target address restrictionSystem.out.println("Checking if target account is authorized:");finalList<JsonNode>addressRestrictions=getMosaicAddressRestrictions(mosaicId,targetAddress,restrictionKey);longpreviousValue=0xFFFFFFFFFFFFFFFFL;if(!addressRestrictions.isEmpty())previousValue=Long.parseUnsignedLong(addressRestrictions.get(0).get("value").asText());if(1!=previousValue){// Enable the address restrictionSystem.out.println("+ Authorizing target account");transactions.add(addressRestrictionSetValue(previousValue,1,targetAddress));}else{// Disable the address restrictionSystem.out.println("+ Deauthorizing target account");transactions.add(addressRestrictionSetValue(previousValue,0,targetAddress));}// Build an aggregate transactionSystem.out.printf("Bundling %d transaction(s) in an aggregate%n",transactions.size());finalTransactionaggregateTransaction=facade.createTransactionFromTypedDescriptor(newAggregateCompleteTransactionV3Descriptor(SymbolFacade.hashEmbeddedTransactions(transactions),transactions,null),ownerKeyPair.getPublicKey(),feeMultiplier,2*60*60);// Sign, announce and wait for confirmationfinalStringaggregatePayload=SymbolTransactionFactory.attachSignature(aggregateTransaction,facade.signTransaction(ownerKeyPair,aggregateTransaction));finalStringaggregateHash=facade.hashTransaction(aggregateTransaction).toString();announceTransaction(aggregatePayload,"aggregate");waitForConfirmation(aggregateHash,"aggregate");// Try to transfer the mosaic to the target addressfinalTransactiontestTransaction=facade.createTransactionFromTypedDescriptor(newTransferTransactionV1Descriptor(targetAddress,List.of(newUnresolvedMosaicDescriptor(newUnresolvedMosaicId(mosaicId),newAmount(1))),null),ownerKeyPair.getPublicKey(),feeMultiplier,2*60*60);finalStringtestPayload=SymbolTransactionFactory.attachSignature(testTransaction,facade.signTransaction(ownerKeyPair,testTransaction));finalStringtestHash=facade.hashTransaction(testTransaction).toString();System.out.println("\nAttempting transfer to the target account");announceTransaction(testPayload,"test transfer");waitForConfirmation(testHash,"test transfer");}}
# Enable global restriction if requiredtransactions=[]print('Checking if the global restriction is enabled:')global_restrictions=get_mosaic_global_restrictions(mosaic_id,restriction_key)iflen(global_restrictions)==0:# Enable the global restrictionprint('+ Enabling global restriction')transactions.append(set_global_restriction_transaction())# Enable the address restrictionprint('+ Authorizing owner account')transactions.append(address_restriction_set_value(0xFFFFFFFF_FFFFFFFF,1,owner_address))
// Enable global restriction if requiredconsttransactions=[];console.log('Checking if the global restriction is enabled:');constglobalRestrictions=awaitgetMosaicGlobalRestrictions(mosaicId,restrictionKey);if(0===globalRestrictions.length){// Enable the global restrictionconsole.log('+ Enabling global restriction');transactions.push(globalRestrictionEnableTransaction());// Enable the address restrictionconsole.log('+ Authorizing owner account');transactions.push(addressRestrictionSetValue(0xFFFFFFFFFFFFFFFFn,1n,ownerAddress.toString()));}
// Enable global restriction if requiredfinalList<EmbeddedTransaction>transactions=newArrayList<>();System.out.println("Checking if the global restriction is enabled:");finalList<JsonNode>globalRestrictions=getMosaicGlobalRestrictions(mosaicId,restrictionKey);if(globalRestrictions.isEmpty()){// Enable the global restrictionSystem.out.println("+ Enabling global restriction");transactions.add(setGlobalRestrictionTransaction());// Enable the address restrictionSystem.out.println("+ Authorizing owner account");transactions.add(addressRestrictionSetValue(0xFFFFFFFFFFFFFFFFL,1,ownerAddress));}
print('Checking if target account is authorized:')address_restrictions=get_mosaic_address_restrictions(mosaic_id,target_address,restriction_key)prev_value=0xFFFFFFFF_FFFFFFFFiflen(address_restrictions)>0:prev_value=int(address_restrictions[0]['value'])ifprev_value!=1:# Enable the address restrictionprint('+ Authorizing target account')transactions.append(address_restriction_set_value(prev_value,1,target_address))else:# Disable the address restrictionprint('+ Deauthorizing target account')transactions.append(address_restriction_set_value(prev_value,0,target_address))
console.log('Checking if target account is authorized:');constaddressRestrictions=awaitgetMosaicAddressRestrictions(mosaicId,targetAddress,restrictionKey);letprevValue=0xFFFFFFFFFFFFFFFFn;if(0<addressRestrictions.length)prevValue=BigInt(addressRestrictions[0].value);if(1n!==prevValue){// Enable the address restrictionconsole.log('+ Authorizing target account');transactions.push(addressRestrictionSetValue(prevValue,1n,targetAddress));}else{// Disable the address restrictionconsole.log('+ Deauthorizing target account');transactions.push(addressRestrictionSetValue(prevValue,0n,targetAddress));}
System.out.println("Checking if target account is authorized:");finalList<JsonNode>addressRestrictions=getMosaicAddressRestrictions(mosaicId,targetAddress,restrictionKey);longpreviousValue=0xFFFFFFFFFFFFFFFFL;if(!addressRestrictions.isEmpty())previousValue=Long.parseUnsignedLong(addressRestrictions.get(0).get("value").asText());if(1!=previousValue){// Enable the address restrictionSystem.out.println("+ Authorizing target account");transactions.add(addressRestrictionSetValue(previousValue,1,targetAddress));}else{// Disable the address restrictionSystem.out.println("+ Deauthorizing target account");transactions.add(addressRestrictionSetValue(previousValue,0,targetAddress));}
print('Bundling',len(transactions),'transaction(s) in an aggregate')aggregate_transaction=facade.create_transaction_from_descriptor({'type':'aggregate_complete_transaction_v3','transactions_hash':facade.hash_embedded_transactions(transactions),'transactions':transactions},owner_key_pair.public_key,fee_multiplier,2*60*60)
console.log('Bundling',transactions.length,'transaction(s) in an aggregate');constaggregateTransaction=facade.createTransactionFromTypedDescriptor(newdescriptors.AggregateCompleteTransactionV3Descriptor(facade.static.hashEmbeddedTransactions(transactions),transactions,undefined),ownerKeyPair.publicKey,feeMultiplier,2*60*60);
System.out.printf("Bundling %d transaction(s) in an aggregate%n",transactions.size());finalTransactionaggregateTransaction=facade.createTransactionFromTypedDescriptor(newAggregateCompleteTransactionV3Descriptor(SymbolFacade.hashEmbeddedTransactions(transactions),transactions,null),ownerKeyPair.getPublicKey(),feeMultiplier,2*60*60);
test_transaction=facade.create_transaction_from_descriptor({'type':'transfer_transaction_v1','recipient_address':target_address,'mosaics':[{'mosaic_id':mosaic_id,'amount':1}]},owner_key_pair.public_key,fee_multiplier,2*60*60)test_payload=facade.transaction_factory.attach_signature(test_transaction,facade.sign_transaction(owner_key_pair,test_transaction))test_hash=facade.hash_transaction(test_transaction)print('\nAttempting transfer to the target account')announce_transaction(test_payload,'test transfer')wait_for_confirmation(test_hash,'test transfer')
consttestTransaction=facade.createTransactionFromTypedDescriptor(newdescriptors.TransferTransactionV1Descriptor(newSymbolFacade.Address(targetAddress),[newdescriptors.UnresolvedMosaicDescriptor(newmodels.UnresolvedMosaicId(mosaicId),newmodels.Amount(1n))],undefined),ownerKeyPair.publicKey,feeMultiplier,2*60*60);consttestPayload=SymbolTransactionFactory.attachSignature(testTransaction,facade.signTransaction(ownerKeyPair,testTransaction));consttestHash=facade.hashTransaction(testTransaction).toString();console.log('\nAttempting transfer to the target account');awaitannounceTransaction(testPayload,'test transfer');awaitwaitForConfirmation(testHash,'test transfer');
finalTransactiontestTransaction=facade.createTransactionFromTypedDescriptor(newTransferTransactionV1Descriptor(targetAddress,List.of(newUnresolvedMosaicDescriptor(newUnresolvedMosaicId(mosaicId),newAmount(1))),null),ownerKeyPair.getPublicKey(),feeMultiplier,2*60*60);finalStringtestPayload=SymbolTransactionFactory.attachSignature(testTransaction,facade.signTransaction(ownerKeyPair,testTransaction));finalStringtestHash=facade.hashTransaction(testTransaction).toString();System.out.println("\nAttempting transfer to the target account");announceTransaction(testPayload,"test transfer");waitForConfirmation(testHash,"test transfer");
Using node https://reference.symboltest.net:3001
Owner address: TCHBDENCLKEBILBPWP3JPB2XNY64OE7PYHHE32I
Target address: TB6QOVCUOFRCF5QJSKPIQMLUVWGJS3KYFDETRPA
Mosaic ID: 0x6A5ACF2376E50D4A
Restriction name: "security_level" (key: 0xE08F1643881FD0C1)
Fetching recommended fees from /network/fees/transaction
Fee multiplier: 100
Checking if the global restriction is enabled:
Getting restrictions from /restrictions/mosaic?mosaicId=6A5ACF2376E50D4A&entryType=1
Response: [{'key': '16181176465467887809', 'restriction': {'referenceMosaicId': '0000000000000000', 'restrictionValue': '1', 'restrictionType': 6}}]
Checking if target account is authorized:
Getting restrictions from /restrictions/mosaic?mosaicId=6A5ACF2376E50D4A&entryType=0&targetAddress=TB6QOVCUOFRCF5QJSKPIQMLUVWGJS3KYFDETRPA
Response: [{'key': '16181176465467887809', 'value': '1'}]
+ Deauthorizing target account
{
"signer_public_key": "3B6A27BCCEB6A42D62A3A8D02A6F0D73653215771DE243A63AC048A18B59DA29",
"version": 1,
"network": 152,
"type": 16977,
"mosaic_id": "7663665467149847882",
"restriction_key": "16181176465467887809",
"previous_restriction_value": "1",
"new_restriction_value": "0",
"target_address": "987D075454716222F609929E883174AD8C996D5828C938BC"
}
Bundling 1 transaction(s) in an aggregate
Announcing aggregate to /transactions
Response: {"message":"packet 9 was pushed to the network via /transactions"}
Waiting for aggregate confirmation...
Transaction status: unconfirmed
Transaction status: unconfirmed
...
Transaction status: confirmed
aggregate confirmed in 21 seconds
Attempting transfer to the target account
Announcing test transfer to /transactions
Response: {"message":"packet 9 was pushed to the network via /transactions"}
Waiting for test transfer confirmation...
Transaction status: failed
test transfer failed: Failure_RestrictionMosaic_Account_Unauthorized