importjsonimportosimporttimeimporturllib.errorimporturllib.requestfrombinasciiimporthexlifyfromsymbolchain.CryptoTypesimportPrivateKey,PublicKeyfromsymbolchain.facade.NemFacadeimportNemFacadefromsymbolchain.ncimportAmount,Message,MessageTypefromsymbolchain.nem.FeeCalculatorimportcalculate_transaction_feefromsymbolchain.nem.MessageEncoderimportMessageEncoderfromsymbolchain.nem.NetworkimportNetworkTimestamp# ConfigurationNODE_URL=os.getenv('NODE_URL','http://libertalia.nemtest.net:7890')print(f'Using node {NODE_URL}')# Helper function to poll for confirmed transactiondefretrieve_confirmed_transaction(hash_value,label):print(f'Polling for {label} confirmation...')attempts=0max_attempts=120whileattempts<max_attempts:try:url=f'{NODE_URL}/transaction/get?hash={hash_value}'withurllib.request.urlopen(url)astransaction_confirmed:print(f' {label} confirmed!')returnjson.loads(transaction_confirmed.read().decode())excepturllib.error.HTTPError:# Transaction not yet confirmedpassattempts+=1time.sleep(2)raiseTimeoutError(f'{label} not confirmed after {max_attempts} attempts')# Set up sender and recipient accountsfacade=NemFacade('testnet')sender_private_key_string=os.getenv('SENDER_PRIVATE_KEY','0000000000000000000000000000000000000000000000000000000000000000',)sender_key_pair=NemFacade.KeyPair(PrivateKey(sender_private_key_string))sender_address=facade.network.public_key_to_address(sender_key_pair.public_key)recipient_private_key_string=os.getenv('RECIPIENT_PRIVATE_KEY','1111111111111111111111111111111111111111111111111111111111111111',)recipient_key_pair=NemFacade.KeyPair(PrivateKey(recipient_private_key_string))recipient_address=facade.network.public_key_to_address(recipient_key_pair.public_key)print(f'Sender address: {sender_address}')print(f'Recipient address: {recipient_address}\n')# 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']//1000timestamp=NetworkTimestamp(network_time)deadline=timestamp.add_hours(2)print(f' Network time: {network_time} s since the nemesis block\n')# ===== PLAIN TEXT MESSAGE =====print('==> Sending Plain Text Message')# Create a plain text messageplain_message='Hello, NEM!'.encode('utf-8')print(f'Plain message: {plain_message.decode("utf-8")}')# Build transfer transaction with plain messageplain_transaction=facade.transaction_factory.create({'type':'transfer_transaction_v2','signer_public_key':sender_key_pair.public_key,'timestamp':timestamp.timestamp,'deadline':deadline.timestamp,'recipient_address':recipient_address,'amount':0,'message':{'message_type':'plain','message':plain_message,},})plain_transaction.fee=Amount(calculate_transaction_fee(plain_transaction))# Sign and announce the transactionplain_signature=facade.sign_transaction(sender_key_pair,plain_transaction)plain_json_payload=facade.transaction_factory.attach_signature(plain_transaction,plain_signature)plain_transaction_hash=facade.hash_transaction(plain_transaction)print(f'Transaction hash: {plain_transaction_hash}')plain_announce_request=urllib.request.Request(f'{NODE_URL}/transaction/announce',data=plain_json_payload.encode('utf-8'),headers={'Content-Type':'application/json'},method='POST',)withurllib.request.urlopen(plain_announce_request)asresponse:print('Plain message transaction announced\n')# ===== RECEIVING PLAIN TEXT MESSAGE =====print('<== Receiving Plain Text Message')# Wait for confirmationplain_tx_data=retrieve_confirmed_transaction(plain_transaction_hash,'Plain message transaction')# Decode plain message from confirmed transactionreceived_plain_message=bytes.fromhex(plain_tx_data['transaction']['message']['payload'])print(f'Received plain message: {received_plain_message.decode("utf-8")}\n')# ===== ENCRYPTED MESSAGE =====print('==> Sending Encrypted Message')# Create a message encoder with sender's key pairsender_message_encoder=MessageEncoder(sender_key_pair)# Encrypt the message using recipient's public keysecret_message='This is a secret message!'.encode('utf-8')encrypted_message=sender_message_encoder.encode(recipient_key_pair.public_key,secret_message)print(f'Original message: {secret_message.decode("utf-8")}')encrypted_payload=hexlify(encrypted_message.message).decode('utf-8')print(f'Encrypted payload: {encrypted_payload}')# Build transfer transaction with encrypted messageencrypted_transaction=facade.transaction_factory.create({'type':'transfer_transaction_v2','signer_public_key':sender_key_pair.public_key,'timestamp':timestamp.timestamp,'deadline':deadline.timestamp,'recipient_address':recipient_address,'amount':0,'message':{'message_type':'encrypted','message':encrypted_message.message,},})encrypted_transaction.fee=Amount(calculate_transaction_fee(encrypted_transaction))# Sign and announce the transactionencrypted_signature=facade.sign_transaction(sender_key_pair,encrypted_transaction)encrypted_json_payload=facade.transaction_factory.attach_signature(encrypted_transaction,encrypted_signature)encrypted_transaction_hash=facade.hash_transaction(encrypted_transaction)print(f'Transaction hash: {encrypted_transaction_hash}')encrypted_announce_request=urllib.request.Request(f'{NODE_URL}/transaction/announce',data=encrypted_json_payload.encode('utf-8'),headers={'Content-Type':'application/json'},method='POST',)withurllib.request.urlopen(encrypted_announce_request)asresponse:print('Encrypted message transaction announced\n')# ===== RECEIVING ENCRYPTED MESSAGE =====print('<== Receiving Encrypted Message')# Wait for confirmationencrypted_tx_data=retrieve_confirmed_transaction(encrypted_transaction_hash,'Encrypted message transaction')# Decode encrypted message using recipient's private keyrecipient_message_encoder=MessageEncoder(recipient_key_pair)received_encrypted_message=Message()received_encrypted_message.message_type=MessageType.ENCRYPTEDreceived_encrypted_message.message=bytes.fromhex(encrypted_tx_data['transaction']['message']['payload'])# Get sender's public key from the transactionsender_public_key_from_tx=PublicKey(encrypted_tx_data['transaction']['signer'])(is_decoded,decrypted_message)=recipient_message_encoder.try_decode(sender_public_key_from_tx,received_encrypted_message)ifis_decoded:message_text=decrypted_message.decode('utf-8')print(f'Recipient decrypted message: {message_text}')else:print('Recipient failed to decrypt message')
import{PrivateKey,PublicKey}from'symbol-sdk';import{MessageEncoder,NemFacade,NetworkTimestamp,calculateTransactionFee,models}from'symbol-sdk/nem';// ConfigurationconstNODE_URL=process.env.NODE_URL||'http://libertalia.nemtest.net:7890';console.log('Using node',NODE_URL);// Helper function to poll for confirmed transactionasyncfunctionretrieveConfirmedTransaction(hash,label){console.log(`Polling for ${label} confirmation...`);letattempts=0;constmaxAttempts=120;while(attempts<maxAttempts){constresponse=awaitfetch(`${NODE_URL}/transaction/get?hash=${hash}`);if(response.ok){console.log(` ${label} confirmed!`);returnresponse.json();}attempts++;awaitnewPromise(resolve=>{setTimeout(resolve,2000);});}thrownewError(`${label} not confirmed after ${maxAttempts} attempts`);}// Set up sender and recipient accountsconstfacade=newNemFacade('testnet');constsenderPrivateKeyString=process.env.SENDER_PRIVATE_KEY||'0000000000000000000000000000000000000000000000000000000000000000';constsenderKeyPair=newNemFacade.KeyPair(newPrivateKey(senderPrivateKeyString));constsenderAddress=facade.network.publicKeyToAddress(senderKeyPair.publicKey);constrecipientPrivateKeyString=process.env.RECIPIENT_PRIVATE_KEY||'1111111111111111111111111111111111111111111111111111111111111111';constrecipientKeyPair=newNemFacade.KeyPair(newPrivateKey(recipientPrivateKeyString));constrecipientAddress=facade.network.publicKeyToAddress(recipientKeyPair.publicKey);console.log('Sender address:',senderAddress.toString());console.log('Recipient address:',recipientAddress.toString(),'\n');// 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);consttimestamp=newNetworkTimestamp(networkTime);constdeadline=timestamp.addHours(2);console.log(' Network time:',networkTime,'s since the nemesis block','\n');// ===== PLAIN TEXT MESSAGE =====console.log('==> Sending Plain Text Message');// Create a plain text messageconstplainMessage=newTextEncoder().encode('Hello, NEM!');console.log('Plain message:',newTextDecoder().decode(plainMessage));// Build transfer transaction with plain messageconstplainTransaction=facade.transactionFactory.create({type:'transfer_transaction_v2',signerPublicKey:senderKeyPair.publicKey.toString(),timestamp:timestamp.timestamp,deadline:deadline.timestamp,recipientAddress:recipientAddress.toString(),amount:0n,message:{messageType:'plain',message:plainMessage}});plainTransaction.fee=newmodels.Amount(calculateTransactionFee(plainTransaction));// Sign and announce the transactionconstplainSignature=facade.signTransaction(senderKeyPair,plainTransaction);constplainJsonPayload=facade.transactionFactory.static.attachSignature(plainTransaction,plainSignature);constplainTransactionHash=facade.hashTransaction(plainTransaction).toString();console.log('Transaction hash:',plainTransactionHash);awaitfetch(`${NODE_URL}/transaction/announce`,{method:'POST',headers:{'Content-Type':'application/json'},body:plainJsonPayload});console.log('Plain message transaction announced\n');// ===== RECEIVING PLAIN TEXT MESSAGE =====console.log('<== Receiving Plain Text Message');// Wait for confirmationconstplainTxData=awaitretrieveConfirmedTransaction(plainTransactionHash,'Plain message transaction');// Decode plain message from confirmed transactionconstreceivedPlainMessage=Buffer.from(plainTxData.transaction.message.payload,'hex');console.log('Received plain message:',newTextDecoder().decode(receivedPlainMessage),'\n');// ===== ENCRYPTED MESSAGE =====console.log('==> Sending Encrypted Message');// Create a message encoder with sender's key pairconstsenderMessageEncoder=newMessageEncoder(senderKeyPair);// Encrypt the message using recipient's public keyconstsecretMessage=newTextEncoder().encode('This is a secret message!');constencryptedMessage=senderMessageEncoder.encode(recipientKeyPair.publicKey,secretMessage);console.log('Original message:',newTextDecoder().decode(secretMessage));console.log('Encrypted payload:',Buffer.from(encryptedMessage.message).toString('hex'));// Build transfer transaction with encrypted messageconstencryptedTransaction=facade.transactionFactory.create({type:'transfer_transaction_v2',signerPublicKey:senderKeyPair.publicKey.toString(),timestamp:timestamp.timestamp,deadline:deadline.timestamp,recipientAddress:recipientAddress.toString(),amount:0n,message:{messageType:'encrypted',message:encryptedMessage.message}});encryptedTransaction.fee=newmodels.Amount(calculateTransactionFee(encryptedTransaction));// Sign and announce the transactionconstencryptedSignature=facade.signTransaction(senderKeyPair,encryptedTransaction);constencryptedJsonPayload=facade.transactionFactory.static.attachSignature(encryptedTransaction,encryptedSignature);constencryptedTransactionHash=facade.hashTransaction(encryptedTransaction).toString();console.log('Transaction hash:',encryptedTransactionHash);awaitfetch(`${NODE_URL}/transaction/announce`,{method:'POST',headers:{'Content-Type':'application/json'},body:encryptedJsonPayload});console.log('Encrypted message transaction announced\n');// ===== RECEIVING ENCRYPTED MESSAGE =====console.log('<== Receiving Encrypted Message');// Wait for confirmationconstencryptedTxData=awaitretrieveConfirmedTransaction(encryptedTransactionHash,'Encrypted message transaction');// Decode encrypted message using recipient's private keyconstrecipientMessageEncoder=newMessageEncoder(recipientKeyPair);constreceivedEncryptedMessage=newmodels.Message();receivedEncryptedMessage.messageType=models.MessageType.ENCRYPTED;receivedEncryptedMessage.message=Buffer.from(encryptedTxData.transaction.message.payload,'hex');// Get sender's public key from the transactionconstsenderPublicKeyFromTx=newPublicKey(encryptedTxData.transaction.signer);constresult=recipientMessageEncoder.tryDecode(senderPublicKeyFromTx,receivedEncryptedMessage);if(result.isDecoded){console.log('Recipient decrypted message:',newTextDecoder().decode(result.message));}else{console.log('Recipient failed to decrypt message');}
# Set up sender and recipient accountsfacade=NemFacade('testnet')sender_private_key_string=os.getenv('SENDER_PRIVATE_KEY','0000000000000000000000000000000000000000000000000000000000000000',)sender_key_pair=NemFacade.KeyPair(PrivateKey(sender_private_key_string))sender_address=facade.network.public_key_to_address(sender_key_pair.public_key)recipient_private_key_string=os.getenv('RECIPIENT_PRIVATE_KEY','1111111111111111111111111111111111111111111111111111111111111111',)recipient_key_pair=NemFacade.KeyPair(PrivateKey(recipient_private_key_string))recipient_address=facade.network.public_key_to_address(recipient_key_pair.public_key)print(f'Sender address: {sender_address}')print(f'Recipient address: {recipient_address}\n')
// Set up sender and recipient accountsconstfacade=newNemFacade('testnet');constsenderPrivateKeyString=process.env.SENDER_PRIVATE_KEY||'0000000000000000000000000000000000000000000000000000000000000000';constsenderKeyPair=newNemFacade.KeyPair(newPrivateKey(senderPrivateKeyString));constsenderAddress=facade.network.publicKeyToAddress(senderKeyPair.publicKey);constrecipientPrivateKeyString=process.env.RECIPIENT_PRIVATE_KEY||'1111111111111111111111111111111111111111111111111111111111111111';constrecipientKeyPair=newNemFacade.KeyPair(newPrivateKey(recipientPrivateKeyString));constrecipientAddress=facade.network.publicKeyToAddress(recipientKeyPair.publicKey);console.log('Sender address:',senderAddress.toString());console.log('Recipient address:',recipientAddress.toString(),'\n');
print('==> Sending Plain Text Message')# Create a plain text messageplain_message='Hello, NEM!'.encode('utf-8')print(f'Plain message: {plain_message.decode("utf-8")}')# Build transfer transaction with plain messageplain_transaction=facade.transaction_factory.create({'type':'transfer_transaction_v2','signer_public_key':sender_key_pair.public_key,'timestamp':timestamp.timestamp,'deadline':deadline.timestamp,'recipient_address':recipient_address,'amount':0,'message':{'message_type':'plain','message':plain_message,},})
console.log('==> Sending Plain Text Message');// Create a plain text messageconstplainMessage=newTextEncoder().encode('Hello, NEM!');console.log('Plain message:',newTextDecoder().decode(plainMessage));// Build transfer transaction with plain messageconstplainTransaction=facade.transactionFactory.create({type:'transfer_transaction_v2',signerPublicKey:senderKeyPair.publicKey.toString(),timestamp:timestamp.timestamp,deadline:deadline.timestamp,recipientAddress:recipientAddress.toString(),amount:0n,message:{messageType:'plain',message:plainMessage}});
print('==> Sending Encrypted Message')# Create a message encoder with sender's key pairsender_message_encoder=MessageEncoder(sender_key_pair)# Encrypt the message using recipient's public keysecret_message='This is a secret message!'.encode('utf-8')encrypted_message=sender_message_encoder.encode(recipient_key_pair.public_key,secret_message)print(f'Original message: {secret_message.decode("utf-8")}')encrypted_payload=hexlify(encrypted_message.message).decode('utf-8')print(f'Encrypted payload: {encrypted_payload}')# Build transfer transaction with encrypted messageencrypted_transaction=facade.transaction_factory.create({'type':'transfer_transaction_v2','signer_public_key':sender_key_pair.public_key,'timestamp':timestamp.timestamp,'deadline':deadline.timestamp,'recipient_address':recipient_address,'amount':0,'message':{'message_type':'encrypted','message':encrypted_message.message,},})
console.log('==> Sending Encrypted Message');// Create a message encoder with sender's key pairconstsenderMessageEncoder=newMessageEncoder(senderKeyPair);// Encrypt the message using recipient's public keyconstsecretMessage=newTextEncoder().encode('This is a secret message!');constencryptedMessage=senderMessageEncoder.encode(recipientKeyPair.publicKey,secretMessage);console.log('Original message:',newTextDecoder().decode(secretMessage));console.log('Encrypted payload:',Buffer.from(encryptedMessage.message).toString('hex'));// Build transfer transaction with encrypted messageconstencryptedTransaction=facade.transactionFactory.create({type:'transfer_transaction_v2',signerPublicKey:senderKeyPair.publicKey.toString(),timestamp:timestamp.timestamp,deadline:deadline.timestamp,recipientAddress:recipientAddress.toString(),amount:0n,message:{messageType:'encrypted',message:encryptedMessage.message}});
print('<== Receiving Encrypted Message')# Wait for confirmationencrypted_tx_data=retrieve_confirmed_transaction(encrypted_transaction_hash,'Encrypted message transaction')# Decode encrypted message using recipient's private keyrecipient_message_encoder=MessageEncoder(recipient_key_pair)received_encrypted_message=Message()received_encrypted_message.message_type=MessageType.ENCRYPTEDreceived_encrypted_message.message=bytes.fromhex(encrypted_tx_data['transaction']['message']['payload'])# Get sender's public key from the transactionsender_public_key_from_tx=PublicKey(encrypted_tx_data['transaction']['signer'])(is_decoded,decrypted_message)=recipient_message_encoder.try_decode(sender_public_key_from_tx,received_encrypted_message)ifis_decoded:message_text=decrypted_message.decode('utf-8')print(f'Recipient decrypted message: {message_text}')else:print('Recipient failed to decrypt message')
console.log('<== Receiving Encrypted Message');// Wait for confirmationconstencryptedTxData=awaitretrieveConfirmedTransaction(encryptedTransactionHash,'Encrypted message transaction');// Decode encrypted message using recipient's private keyconstrecipientMessageEncoder=newMessageEncoder(recipientKeyPair);constreceivedEncryptedMessage=newmodels.Message();receivedEncryptedMessage.messageType=models.MessageType.ENCRYPTED;receivedEncryptedMessage.message=Buffer.from(encryptedTxData.transaction.message.payload,'hex');// Get sender's public key from the transactionconstsenderPublicKeyFromTx=newPublicKey(encryptedTxData.transaction.signer);constresult=recipientMessageEncoder.tryDecode(senderPublicKeyFromTx,receivedEncryptedMessage);if(result.isDecoded){console.log('Recipient decrypted message:',newTextDecoder().decode(result.message));}else{console.log('Recipient failed to decrypt message');}
Using node http://libertalia.nemtest.net:7890
Sender address: TBONKWCOWBZYZB2I5JD3LSDBQVBYHB757VN3SKPP
Recipient address: TBULEAUG2CZQISUR442HWA6UAKGWIXHDABJVIPS4
Fetching current network time from /time-sync/network-time
Network time: 355248540 s since the nemesis block
==> Sending Plain Text Message
Plain message: Hello, NEM!
Transaction hash: 2F8F20CAF8F6FA42ADE05ED85FED0B4D1DA88051972405C4AE2D181B01FB69C3
Plain message transaction announced
<== Receiving Plain Text Message
Polling for Plain message transaction confirmation...
Plain message transaction confirmed!
Received plain message: Hello, NEM!
==> Sending Encrypted Message
Original message: This is a secret message!
Encrypted payload: 3fefcf6e4f1e5e2165f941a5c15ea66778f82eded50cfbde5fc27eba24f4580ff72fb9d0b45061747be0324a120dc357dd11351c09
Transaction hash: 76604471D5A345E6F5CE20C65D618BC6F9A600F1DF515A696B2152E0E2D0B427
Encrypted message transaction announced
<== Receiving Encrypted Message
Polling for Encrypted message transaction confirmation...
Encrypted message transaction confirmed!
Recipient decrypted message: This is a secret message!