importasyncioimportjsonimportosimporturllib.requestfromsymbolchain.CryptoTypesimportPrivateKeyfromsymbolchain.facade.SymbolFacadeimportSymbolFacadefromsymbolchain.symbol.NetworkimportNetworkTimestampfromsymbolchain.scimportAmountfromwebsocketsimportconnectNODE_URL=os.getenv('NODE_URL','https://reference.symboltest.net:3001')WS_URL=NODE_URL.replace('http','ws',1)+'/ws'print(f'Using node {NODE_URL}')MONITOR_ADDRESS=os.getenv('MONITOR_ADDRESS','TCHBDENCLKEBILBPWP3JPB2XNY64OE7PYHHE32I')print(f'Monitoring address: {MONITOR_ADDRESS}')SIGNER_PRIVATE_KEY=os.getenv('SIGNER_PRIVATE_KEY','0000000000000000000000000000000000000000000000000000000000000000')facade=SymbolFacade('testnet')signer_key_pair=SymbolFacade.KeyPair(PrivateKey(SIGNER_PRIVATE_KEY))asyncdefmain():asyncwithconnect(WS_URL)aswebsocket:# Connect to WebSocketresponse=json.loads(awaitwebsocket.recv())uid=response['uid']print(f'Connected to {WS_URL} with uid {uid}')# Subscribe to transaction channelschannels=[f'unconfirmedAdded/{MONITOR_ADDRESS}',f'unconfirmedRemoved/{MONITOR_ADDRESS}',f'confirmedAdded/{MONITOR_ADDRESS}',]forchannelinchannels:awaitwebsocket.send(json.dumps({'uid':uid,'subscribe':channel}))name=channel.split('/')[0]print(f'Subscribed to {name} channel')# Build and announce a transfer transactionwithurllib.request.urlopen(f'{NODE_URL}/node/time')asresp:time_json=json.loads(resp.read().decode())timestamp=NetworkTimestamp(int(time_json['communicationTimestamps']['receiveTimestamp']))withurllib.request.urlopen(f'{NODE_URL}/network/fees/transaction')asresp:fee_json=json.loads(resp.read().decode())fee_mult=max(fee_json['medianFeeMultiplier'],fee_json['minFeeMultiplier'])transaction=facade.transaction_factory.create({'type':'transfer_transaction_v1','signer_public_key':signer_key_pair.public_key,'deadline':timestamp.add_hours(2).timestamp,'recipient_address':MONITOR_ADDRESS,})transaction.fee=Amount(fee_mult*transaction.size)signature=facade.sign_transaction(signer_key_pair,transaction)json_payload=facade.transaction_factory.attach_signature(transaction,signature)transaction_hash=str(facade.hash_transaction(transaction))announce_request=urllib.request.Request(f'{NODE_URL}/transactions',data=json_payload.encode(),headers={'Content-Type':'application/json'},method='PUT')withurllib.request.urlopen(announce_request)asresp:resp.read()print(f'Announced transaction {transaction_hash[:16]}...')# Wait for confirmation via WebSocketasyncforraw_messageinwebsocket:message=json.loads(raw_message)topic=message['topic']message_hash=message['data']['meta']['hash']name=topic.split('/')[0]print(f'{name}: hash={message_hash[:16]}...')if(name=='confirmedAdded'andmessage_hash==transaction_hash):print(f'Transaction {transaction_hash[:16]}... confirmed')break# Unsubscribe before closingforchannelinchannels:awaitwebsocket.send(json.dumps({'uid':uid,'unsubscribe':channel}))print('Unsubscribed from all channels')try:asyncio.run(main())exceptExceptionaserror:print(error)
import{PrivateKey}from'symbol-sdk';import{SymbolFacade,NetworkTimestamp,models}from'symbol-sdk/symbol';constNODE_URL=process.env.NODE_URL||'https://reference.symboltest.net:3001';constWS_URL=NODE_URL.replace('http','ws')+'/ws';console.log(`Using node ${NODE_URL}`);constMONITOR_ADDRESS=process.env.MONITOR_ADDRESS||'TCHBDENCLKEBILBPWP3JPB2XNY64OE7PYHHE32I';console.log(`Monitoring address: ${MONITOR_ADDRESS}`);constSIGNER_PRIVATE_KEY=process.env.SIGNER_PRIVATE_KEY||'0000000000000000000000000000000000000000000000000000000000000000';constfacade=newSymbolFacade('testnet');constsignerKeyPair=newSymbolFacade.KeyPair(newPrivateKey(SIGNER_PRIVATE_KEY));try{// Connect to WebSocketconstwebsocket=newWebSocket(WS_URL);constuid=awaitnewPromise((resolve)=>{websocket.addEventListener('message',(event)=>{constmessage=JSON.parse(event.data);resolve(message.uid);},{once:true});});console.log(`Connected to ${WS_URL} with uid ${uid}`);// Subscribe to transaction channelsconstchannels=[`unconfirmedAdded/${MONITOR_ADDRESS}`,`unconfirmedRemoved/${MONITOR_ADDRESS}`,`confirmedAdded/${MONITOR_ADDRESS}`,];for(constchannelofchannels){websocket.send(JSON.stringify({uid,subscribe:channel}));constname=channel.split('/')[0];console.log(`Subscribed to ${name} channel`);}// Build and announce a transfer transactionconsttimeResponse=awaitfetch(`${NODE_URL}/node/time`);consttimeJSON=awaittimeResponse.json();consttimestamp=newNetworkTimestamp(timeJSON.communicationTimestamps.receiveTimestamp);constfeeResponse=awaitfetch(`${NODE_URL}/network/fees/transaction`);constfeeJSON=awaitfeeResponse.json();constfeeMult=Math.max(feeJSON.medianFeeMultiplier,feeJSON.minFeeMultiplier);consttransaction=facade.transactionFactory.create({type:'transfer_transaction_v1',signerPublicKey:signerKeyPair.publicKey.toString(),deadline:timestamp.addHours(2).timestamp,recipientAddress:MONITOR_ADDRESS,});transaction.fee=newmodels.Amount(feeMult*transaction.size);constsignature=facade.signTransaction(signerKeyPair,transaction);constjsonPayload=facade.transactionFactory.static.attachSignature(transaction,signature);consttransactionHash=facade.hashTransaction(transaction).toString();constconfirmed=newPromise((resolve)=>{websocket.addEventListener('message',(event)=>{constmessage=JSON.parse(event.data);consttopic=message.topic;constmessageHash=message.data.meta.hash;constname=topic.split('/')[0];console.log(`${name}: hash=${messageHash.substring(0,16)}...`);if(name==='confirmedAdded'&&messageHash===transactionHash){console.log(`Transaction ${transactionHash.substring(0,16)}`+'... confirmed');resolve();}});});awaitfetch(`${NODE_URL}/transactions`,{method:'PUT',headers:{'Content-Type':'application/json'},body:jsonPayload});console.log('Announced transaction '+`${transactionHash.substring(0,16)}...`);// Wait for confirmation via WebSocketawaitconfirmed;// Unsubscribe before closingfor(constchannelofchannels){websocket.send(JSON.stringify({uid,unsubscribe:channel}));}console.log('Unsubscribed from all channels');websocket.close();}catch(error){console.error(error);}
asyncwithconnect(WS_URL)aswebsocket:# Connect to WebSocketresponse=json.loads(awaitwebsocket.recv())uid=response['uid']print(f'Connected to {WS_URL} with uid {uid}')
// Connect to WebSocketconstwebsocket=newWebSocket(WS_URL);constuid=awaitnewPromise((resolve)=>{websocket.addEventListener('message',(event)=>{constmessage=JSON.parse(event.data);resolve(message.uid);},{once:true});});console.log(`Connected to ${WS_URL} with uid ${uid}`);
# Subscribe to transaction channelschannels=[f'unconfirmedAdded/{MONITOR_ADDRESS}',f'unconfirmedRemoved/{MONITOR_ADDRESS}',f'confirmedAdded/{MONITOR_ADDRESS}',]forchannelinchannels:awaitwebsocket.send(json.dumps({'uid':uid,'subscribe':channel}))name=channel.split('/')[0]print(f'Subscribed to {name} channel')
// Subscribe to transaction channelsconstchannels=[`unconfirmedAdded/${MONITOR_ADDRESS}`,`unconfirmedRemoved/${MONITOR_ADDRESS}`,`confirmedAdded/${MONITOR_ADDRESS}`,];for(constchannelofchannels){websocket.send(JSON.stringify({uid,subscribe:channel}));constname=channel.split('/')[0];console.log(`Subscribed to ${name} channel`);}
# Build and announce a transfer transactionwithurllib.request.urlopen(f'{NODE_URL}/node/time')asresp:time_json=json.loads(resp.read().decode())timestamp=NetworkTimestamp(int(time_json['communicationTimestamps']['receiveTimestamp']))withurllib.request.urlopen(f'{NODE_URL}/network/fees/transaction')asresp:fee_json=json.loads(resp.read().decode())fee_mult=max(fee_json['medianFeeMultiplier'],fee_json['minFeeMultiplier'])transaction=facade.transaction_factory.create({'type':'transfer_transaction_v1','signer_public_key':signer_key_pair.public_key,'deadline':timestamp.add_hours(2).timestamp,'recipient_address':MONITOR_ADDRESS,})transaction.fee=Amount(fee_mult*transaction.size)signature=facade.sign_transaction(signer_key_pair,transaction)json_payload=facade.transaction_factory.attach_signature(transaction,signature)transaction_hash=str(facade.hash_transaction(transaction))
// Build and announce a transfer transactionconsttimeResponse=awaitfetch(`${NODE_URL}/node/time`);consttimeJSON=awaittimeResponse.json();consttimestamp=newNetworkTimestamp(timeJSON.communicationTimestamps.receiveTimestamp);constfeeResponse=awaitfetch(`${NODE_URL}/network/fees/transaction`);constfeeJSON=awaitfeeResponse.json();constfeeMult=Math.max(feeJSON.medianFeeMultiplier,feeJSON.minFeeMultiplier);consttransaction=facade.transactionFactory.create({type:'transfer_transaction_v1',signerPublicKey:signerKeyPair.publicKey.toString(),deadline:timestamp.addHours(2).timestamp,recipientAddress:MONITOR_ADDRESS,});transaction.fee=newmodels.Amount(feeMult*transaction.size);constsignature=facade.signTransaction(signerKeyPair,transaction);constjsonPayload=facade.transactionFactory.static.attachSignature(transaction,signature);consttransactionHash=facade.hashTransaction(transaction).toString();
# Unsubscribe before closingforchannelinchannels:awaitwebsocket.send(json.dumps({'uid':uid,'unsubscribe':channel}))print('Unsubscribed from all channels')
// Unsubscribe before closingfor(constchannelofchannels){websocket.send(JSON.stringify({uid,unsubscribe:channel}));}console.log('Unsubscribed from all channels');websocket.close();
Using node https://reference.symboltest.net:3001
Monitoring address: TCHBDENCLKEBILBPWP3JPB2XNY64OE7PYHHE32I
Connected to wss://reference.symboltest.net:3001/ws with uid Hj3kL9mN2pQr5tVw=
Subscribed to unconfirmedAdded channel
Subscribed to unconfirmedRemoved channel
Subscribed to confirmedAdded channel
Announced transaction 7A3F1B9E4C2D8A65...
unconfirmedAdded: hash=7A3F1B9E4C2D8A65...
unconfirmedRemoved: hash=7A3F1B9E4C2D8A65...
confirmedAdded: hash=7A3F1B9E4C2D8A65...
Transaction 7A3F1B9E4C2D8A65... confirmed
Unsubscribed from all channels