importasyncioimportjsonimportosimportrandomimporturllib.requestimportuuidimportstomperfromsymbolchain.CryptoTypesimportPrivateKeyfromsymbolchain.facade.NemFacadeimportNemFacadefromsymbolchain.ncimportAmountfromsymbolchain.nem.FeeCalculatorimportcalculate_transaction_feefromwebsocketsimportconnectNODE_URL=os.getenv('NODE_URL','http://libertalia.nemtest.net:7890')WS_URL=NODE_URL.replace(':7890',':7778')print(f'Using node {NODE_URL}')defannounce_transaction(payload,endpoint,label):request=urllib.request.Request(f'{NODE_URL}{endpoint}',data=payload.encode(),headers={'Content-Type':'application/json'},method='POST')withurllib.request.urlopen(request)asresponse:result=json.loads(response.read().decode())if'SUCCESS'==result['message']:print(label)returnresult['message']# SockJS has no Python client library.# These helpers wrap the raw WebSocket transport to mirror a STOMP client.defsockjs_url(endpoint_url):# SockJS raw WebSocket transport adds a random server and session idserver=random.randint(100,999)session=uuid.uuid4().hexws_base=endpoint_url.replace('http','ws',1)returnf'{ws_base}/{server}/{session}/websocket'asyncdefsend_frame(websocket,frame):# SockJS wraps each client payload as a JSON array of frame stringsawaitwebsocket.send(json.dumps([frame]))asyncdefstomp_connect(websocket):awaitwebsocket.recv()# consume the SockJS open frameawaitsend_frame(websocket,stomper.connect('','',NODE_URL,heartbeats=(0,0)))asyncdefstomp_subscribe(websocket,destination,sub_id):awaitsend_frame(websocket,stomper.subscribe(destination,sub_id))asyncdefstomp_send(websocket,destination,body):awaitsend_frame(websocket,stomper.send(destination,body))asyncdefstomp_unsubscribe(websocket,sub_id):awaitsend_frame(websocket,stomper.unsubscribe(sub_id))asyncdefstomp_disconnect(websocket):awaitsend_frame(websocket,stomper.disconnect())defstomp_messages(raw_frame):# Yield each STOMP MESSAGE frame in a SockJS data frameif'a'!=raw_frame[0]:# skip 'o' open, 'h' heartbeat, 'c' closereturnforpayloadinjson.loads(raw_frame[1:]):frame=stomper.unpack_frame(payload)if'MESSAGE'==frame['cmd']:yieldframeasyncdefstomp_frames(websocket):# Yield each STOMP MESSAGE frame as it arrivesasyncforraw_frameinwebsocket:forframeinstomp_messages(raw_frame):yieldframe# Set up the monitored address and signerMONITOR_ADDRESS=os.getenv('MONITOR_ADDRESS','TBULEAUG2CZQISUR442HWA6UAKGWIXHDABJVIPS4')print(f'Monitoring address: {MONITOR_ADDRESS}')SIGNER_PRIVATE_KEY=os.getenv('SIGNER_PRIVATE_KEY','0000000000000000000000000000000000000000000000000000000000000000')facade=NemFacade('testnet')signer_key_pair=NemFacade.KeyPair(PrivateKey(SIGNER_PRIVATE_KEY))asyncdefmain():# Build and sign a transfer to the monitored addresstransaction=facade.create_transaction_from_descriptor({'type':'transfer_transaction_v2','recipient_address':MONITOR_ADDRESS,'amount':0,},signer_key_pair.public_key,0,2*60*60)transaction.fee=Amount(calculate_transaction_fee(transaction))signature=facade.sign_transaction(signer_key_pair,transaction)json_payload=facade.transaction_factory.attach_signature(transaction,signature)transaction_hash=str(facade.hash_transaction(transaction)).upper()# Connect to the WebSocketendpoint=f'{WS_URL}/w/messages'asyncwithconnect(sockjs_url(endpoint))aswebsocket:awaitstomp_connect(websocket)print(f'Connected to {WS_URL}')frames=stomp_frames(websocket)# Subscribe to the account and transaction channelsaccount_channel=f'/account/{MONITOR_ADDRESS}'channels={account_channel:'id-0',f'/unconfirmed/{MONITOR_ADDRESS}':'id-1',f'/transactions/{MONITOR_ADDRESS}':'id-2',}forchannel,sub_idinchannels.items():awaitstomp_subscribe(websocket,channel,sub_id)print(f'Subscribed to {channel} channel')# Register the account and confirm it is activeawaitstomp_send(websocket,'/w/api/account/get',json.dumps({'account':MONITOR_ADDRESS}))asyncforframeinframes:ifaccount_channel==frame['headers']['destination']:balance=json.loads(frame['body'])['account']['balance']print(f'Account update: balance={balance}')breakprint('Account registered')# Announce the transactionannounce_result=announce_transaction(json_payload,'/transaction/announce',f'Announcing transaction {transaction_hash[:16]}...')# Wait for the transaction to confirmif'SUCCESS'==announce_result:confirmed=Falseasyncforframeinframes:destination=frame['headers']['destination']body=json.loads(frame['body'])ifaccount_channel==destination:balance=body['account']['balance']print(f'Account update: balance={balance}')ifconfirmed:breakelif'/transactions/'indestination:message_hash=body['meta']['hash']['data']print(f'confirmed: hash={message_hash[:16]}...')ifmessage_hash.upper()==transaction_hash:short_hash=transaction_hash[:16]print(f'Transaction {short_hash}... confirmed')confirmed=Trueelse:message_hash=body['meta']['hash']['data']ifmessage_hash.upper()==transaction_hash:print(f'unconfirmed: hash={message_hash[:16]}...')else:print(f'Transaction rejected: {announce_result}')# Unsubscribe before closingforsub_idinchannels.values():awaitstomp_unsubscribe(websocket,sub_id)print('Unsubscribed from all channels')awaitstomp_disconnect(websocket)try:asyncio.run(main())exceptExceptionaserror:print(error)
import{Client}from'@stomp/stompjs';importSockJSfrom'sockjs-client';import{PrivateKey}from'symbol-sdk';import{Address,NemFacade,calculateTransactionFee,descriptors,models}from'symbol-sdk/nem';constNODE_URL=process.env.NODE_URL||'http://libertalia.nemtest.net:7890';constWS_URL=NODE_URL.replace(':7890',':7778');console.log(`Using node ${NODE_URL}`);asyncfunctionannounceTransaction(payload,endpoint,label){constresponse=awaitfetch(`${NODE_URL}${endpoint}`,{method:'POST',headers:{'Content-Type':'application/json'},body:payload});if(!response.ok)thrownewError(`HTTP ${response.status}`);constresult=awaitresponse.json();if('SUCCESS'===result.message)console.log(label);returnresult.message;}// Set up the monitored address and signerconstMONITOR_ADDRESS=process.env.MONITOR_ADDRESS||'TBULEAUG2CZQISUR442HWA6UAKGWIXHDABJVIPS4';console.log(`Monitoring address: ${MONITOR_ADDRESS}`);constSIGNER_PRIVATE_KEY=process.env.SIGNER_PRIVATE_KEY||'0000000000000000000000000000000000000000000000000000000000000000';constfacade=newNemFacade('testnet');constsignerKeyPair=newNemFacade.KeyPair(newPrivateKey(SIGNER_PRIVATE_KEY));try{// Build and sign a transfer to the monitored addressconsttransaction=facade.createTransactionFromTypedDescriptor(newdescriptors.TransferTransactionV2Descriptor(newAddress(MONITOR_ADDRESS),newmodels.Amount(0n)),signerKeyPair.publicKey,0n,2*60*60);transaction.fee=newmodels.Amount(calculateTransactionFee(transaction));constsignature=facade.signTransaction(signerKeyPair,transaction);constjsonPayload=facade.transactionFactory.static.attachSignature(transaction,signature);consttransactionHash=facade.hashTransaction(transaction).toString().toUpperCase();constshortHash=transactionHash.substring(0,16);// Connect to the WebSocketconstclient=newClient({webSocketFactory:()=>newSockJS(`${WS_URL}/w/messages`)});awaitnewPromise(resolve=>{client.onConnect=resolve;client.activate();});console.log(`Connected to ${WS_URL}`);// Wait for the transaction to confirmletconfirmed=false;letresolveRegistered;letresolveDone;constregistered=newPromise(resolve=>{resolveRegistered=resolve;});constdone=newPromise(resolve=>{resolveDone=resolve;});constonUnconfirmed=message=>{constmessageHash=JSON.parse(message.body).meta.hash.data;if(messageHash.toUpperCase()===transactionHash){console.log(`unconfirmed: hash=${messageHash.substring(0,16)}...`);}};constonConfirmed=message=>{constmessageHash=JSON.parse(message.body).meta.hash.data;console.log(`confirmed: hash=${messageHash.substring(0,16)}...`);if(messageHash.toUpperCase()===transactionHash){console.log(`Transaction ${shortHash}... confirmed`);confirmed=true;}};constonAccountUpdate=message=>{const{balance}=JSON.parse(message.body).account;console.log(`Account update: balance=${balance}`);resolveRegistered();if(confirmed)resolveDone();};// Subscribe to the account and transaction channelsconstaccountChannel=`/account/${MONITOR_ADDRESS}`;constsubscriptions=[{channel:accountChannel,handler:onAccountUpdate,id:'id-0'},{channel:`/unconfirmed/${MONITOR_ADDRESS}`,handler:onUnconfirmed,id:'id-1'},{channel:`/transactions/${MONITOR_ADDRESS}`,handler:onConfirmed,id:'id-2'}];for(const{channel,handler,id}ofsubscriptions){client.subscribe(channel,handler,{id});console.log(`Subscribed to ${channel} channel`);}// Register the account and confirm it is activeclient.publish({destination:'/w/api/account/get',body:JSON.stringify({account:MONITOR_ADDRESS})});awaitregistered;console.log('Account registered');// Announce the transactionconstannounceResult=awaitannounceTransaction(jsonPayload,'/transaction/announce',`Announcing transaction ${shortHash}...`);// Wait for the transaction to confirmif('SUCCESS'===announceResult)awaitdone;elseconsole.log(`Transaction rejected: ${announceResult}`);// Unsubscribe before closingfor(const{id}ofsubscriptions)client.unsubscribe(id);console.log('Unsubscribed from all channels');client.deactivate();}catch(error){console.error(error);}
//JAVA 21+//DEPS org.symbol:symbol-sdk:3.3.3//DEPS org.glassfish.tyrus.bundles:tyrus-standalone-client:2.2.0importjava.io.IOException;importjava.net.URI;importjava.net.http.HttpClient;importjava.net.http.HttpRequest;importjava.net.http.HttpResponse;importjava.net.http.HttpResponse.BodyHandlers;importjava.util.HashMap;importjava.util.List;importjava.util.Map;importjava.util.UUID;importjava.util.concurrent.BlockingQueue;importjava.util.concurrent.LinkedBlockingQueue;importjava.util.concurrent.ThreadLocalRandom;importcom.fasterxml.jackson.databind.JsonNode;importcom.fasterxml.jackson.databind.ObjectMapper;importcom.fasterxml.jackson.databind.node.ArrayNode;importjakarta.websocket.ClientEndpoint;importjakarta.websocket.ContainerProvider;importjakarta.websocket.OnMessage;importjakarta.websocket.RemoteEndpoint;importjakarta.websocket.Session;importorg.symbol.sdk.CryptoTypes;importorg.symbol.sdk.facade.NemFacade;importorg.symbol.sdk.nem.Address;importorg.symbol.sdk.nem.FeeCalculator;importorg.symbol.sdk.nem.KeyPair;importorg.symbol.sdk.nem.NemTransactionFactory;importorg.symbol.sdk.nem.descriptors.TransferTransactionV2Descriptor;importorg.symbol.sdk.nem.models.Amount;importorg.symbol.sdk.nem.models.Transaction;@ClientEndpointpublicfinalclassListenTransactionFlow{privatestaticfinalObjectMapperJSON_MAPPER=newObjectMapper();privatestaticfinalHttpClientHTTP_CLIENT=HttpClient.newHttpClient();privatefinalBlockingQueue<String>rawFrames=newLinkedBlockingQueue<>();privatefinalStringnodeUrl=System.getenv().getOrDefault("NODE_URL","http://libertalia.nemtest.net:7890");privatefinalStringwsUrl=nodeUrl.replace(":7890",":7778");privatefinalNemFacadefacade=newNemFacade("testnet");privateStringannounceTransaction(finalStringpayload,finalStringendpoint,finalStringlabel)throwsIOException,InterruptedException{finalHttpRequestrequest=HttpRequest.newBuilder(URI.create(nodeUrl+endpoint)).header("Content-Type","application/json").POST(HttpRequest.BodyPublishers.ofString(payload)).build();finalHttpResponse<String>response=HTTP_CLIENT.send(request,BodyHandlers.ofString());if(2!=response.statusCode()/100)thrownewIOException("HTTP "+response.statusCode());finalStringresult=JSON_MAPPER.readTree(response.body()).get("message").asText();if("SUCCESS".equals(result))System.out.println(label);returnresult;}publicstaticvoidmain(finalString[]args){try{newListenTransactionFlow().run();}catch(finalExceptionex){System.out.println(null==ex.getMessage()?ex.toString():ex.getMessage());}}privatevoidrun()throwsException{System.out.printf("Using node %s%n",nodeUrl);// Set up the monitored address and signerfinalStringmonitorAddress=System.getenv().getOrDefault("MONITOR_ADDRESS","TBULEAUG2CZQISUR442HWA6UAKGWIXHDABJVIPS4");System.out.printf("Monitoring address: %s%n",monitorAddress);finalStringprivateKey=System.getenv().getOrDefault("SIGNER_PRIVATE_KEY","0".repeat(64));finalKeyPairsignerKeyPair=newKeyPair(newCryptoTypes.PrivateKey(privateKey));// Build and sign a transfer to the monitored addressfinalTransactiontransaction=facade.createTransactionFromTypedDescriptor(newTransferTransactionV2Descriptor(newAddress(monitorAddress),newAmount(0),null,List.of()),signerKeyPair.getPublicKey(),0,2*60*60);transaction.setFee(newAmount(FeeCalculator.calculateTransactionFee(transaction)));finalStringpayload=NemTransactionFactory.attachSignature(transaction,facade.signTransaction(signerKeyPair,transaction));finalStringtransactionHash=facade.hashTransaction(transaction).toString().toUpperCase();// Connect to the WebSocketfinalSessionsession=ContainerProvider.getWebSocketContainer().connectToServer(this,URI.create(sockJsUrl(wsUrl+"/w/messages")));finalRemoteEndpoint.Basicremote=session.getBasicRemote();rawFrames.take();// consume the SockJS open framesendFrame(remote,"CONNECT\naccept-version:1.1,1.0\n"+"heart-beat:0,0\nhost:"+nodeUrl+"\n\n\0");System.out.printf("Connected to %s%n",wsUrl);// Subscribe to the account and transaction channelsfinalStringaccountChannel="/account/"+monitorAddress;finalMap<String,String>channels=newHashMap<>();channels.put(accountChannel,"id-0");channels.put("/unconfirmed/"+monitorAddress,"id-1");channels.put("/transactions/"+monitorAddress,"id-2");for(finalMap.Entry<String,String>channel:channels.entrySet()){subscribe(remote,channel.getKey(),channel.getValue());System.out.printf("Subscribed to %s channel%n",channel.getKey());}// Register the account and confirm it is activesend(remote,"/w/api/account/get",JSON_MAPPER.createObjectNode().put("account",monitorAddress).toString());while(true){finalStompMessagemessage=nextMessage();if(accountChannel.equals(message.destination())){finalStringbalance=JSON_MAPPER.readTree(message.body()).get("account").get("balance").asText();System.out.printf("Account update: balance=%s%n",balance);break;}}System.out.println("Account registered");// Announce the transactionfinalStringresult=announceTransaction(payload,"/transaction/announce","Announcing transaction "+transactionHash.substring(0,16)+"...");// Wait for the transaction to confirmif("SUCCESS".equals(result)){booleanconfirmed=false;while(true){finalStompMessagemessage=nextMessage();finalJsonNodebody=JSON_MAPPER.readTree(message.body());if(accountChannel.equals(message.destination())){System.out.printf("Account update: balance=%s%n",body.get("account").get("balance").asText());if(confirmed)break;}else{finalStringhash=body.get("meta").get("hash").get("data").asText();if(message.destination().contains("/transactions/")){System.out.printf("confirmed: hash=%s...%n",hash.substring(0,16));if(hash.equalsIgnoreCase(transactionHash)){System.out.printf("Transaction %s... confirmed%n",transactionHash.substring(0,16));confirmed=true;}}elseif(hash.equalsIgnoreCase(transactionHash)){System.out.printf("unconfirmed: hash=%s...%n",hash.substring(0,16));}}}}else{System.out.printf("Transaction rejected: %s%n",result);}// Unsubscribe before closingfor(finalStringid:channels.values())sendFrame(remote,"UNSUBSCRIBE\nid:"+id+"\n\n\0");System.out.println("Unsubscribed from all channels");sendFrame(remote,"DISCONNECT\n\n\0");session.close();}@OnMessagepublicvoidonMessage(finalStringframe){rawFrames.add(frame);}privateStompMessagenextMessage()throwsException{while(true){finalStringraw=rawFrames.take();if(!raw.startsWith("a"))continue;for(finalJsonNodeitem:JSON_MAPPER.readTree(raw.substring(1))){finalStringframe=item.asText();if(!frame.startsWith("MESSAGE\n"))continue;finalintseparator=frame.indexOf("\n\n");finalStringheaders=frame.substring(0,separator);Stringdestination="";for(finalStringline:headers.split("\n"))if(line.startsWith("destination:"))destination=line.substring(12);finalStringbody=frame.substring(separator+2).replace("\0","");returnnewStompMessage(destination,body);}}}privatestaticStringsockJsUrl(finalStringendpoint){finalintserver=ThreadLocalRandom.current().nextInt(100,1000);returnendpoint.replaceFirst("http","ws")+"/"+server+"/"+UUID.randomUUID().toString().replace("-","")+"/websocket";}privatestaticvoidsubscribe(finalRemoteEndpoint.Basicremote,finalStringdestination,finalStringid)throwsIOException{sendFrame(remote,"SUBSCRIBE\nid:"+id+"\ndestination:"+destination+"\nack:auto\n\n\0");}privatestaticvoidsend(finalRemoteEndpoint.Basicremote,finalStringdestination,finalStringbody)throwsIOException{sendFrame(remote,"SEND\ndestination:"+destination+"\ncontent-type:application/json\ncontent-length:"+body.length()+"\n\n"+body+"\0");}privatestaticvoidsendFrame(finalRemoteEndpoint.Basicremote,finalStringframe)throwsIOException{finalArrayNodepayload=JSON_MAPPER.createArrayNode();payload.add(frame);remote.sendText(payload.toString());}privaterecordStompMessage(Stringdestination,Stringbody){}}
# Set up the monitored address and signerMONITOR_ADDRESS=os.getenv('MONITOR_ADDRESS','TBULEAUG2CZQISUR442HWA6UAKGWIXHDABJVIPS4')print(f'Monitoring address: {MONITOR_ADDRESS}')SIGNER_PRIVATE_KEY=os.getenv('SIGNER_PRIVATE_KEY','0000000000000000000000000000000000000000000000000000000000000000')facade=NemFacade('testnet')signer_key_pair=NemFacade.KeyPair(PrivateKey(SIGNER_PRIVATE_KEY))
// Set up the monitored address and signerconstMONITOR_ADDRESS=process.env.MONITOR_ADDRESS||'TBULEAUG2CZQISUR442HWA6UAKGWIXHDABJVIPS4';console.log(`Monitoring address: ${MONITOR_ADDRESS}`);constSIGNER_PRIVATE_KEY=process.env.SIGNER_PRIVATE_KEY||'0000000000000000000000000000000000000000000000000000000000000000';constfacade=newNemFacade('testnet');constsignerKeyPair=newNemFacade.KeyPair(newPrivateKey(SIGNER_PRIVATE_KEY));
// Set up the monitored address and signerfinalStringmonitorAddress=System.getenv().getOrDefault("MONITOR_ADDRESS","TBULEAUG2CZQISUR442HWA6UAKGWIXHDABJVIPS4");System.out.printf("Monitoring address: %s%n",monitorAddress);finalStringprivateKey=System.getenv().getOrDefault("SIGNER_PRIVATE_KEY","0".repeat(64));finalKeyPairsignerKeyPair=newKeyPair(newCryptoTypes.PrivateKey(privateKey));
この手順では、監視するアドレスと、そこへ送金するアカウントをセットアップします。
MONITOR_ADDRESS は監視するアドレスです。
このチュートリアルがサブスクライブするチャネルはこのアドレスに対応付けられ、送金の送信者や受取人など、トランザクションに関係するたびに通知します。
WebSocket API では、アドレスを大文字かつハイフンなしで指定します。
# Build and sign a transfer to the monitored addresstransaction=facade.create_transaction_from_descriptor({'type':'transfer_transaction_v2','recipient_address':MONITOR_ADDRESS,'amount':0,},signer_key_pair.public_key,0,2*60*60)transaction.fee=Amount(calculate_transaction_fee(transaction))signature=facade.sign_transaction(signer_key_pair,transaction)json_payload=facade.transaction_factory.attach_signature(transaction,signature)transaction_hash=str(facade.hash_transaction(transaction)).upper()
// Build and sign a transfer to the monitored addressconsttransaction=facade.createTransactionFromTypedDescriptor(newdescriptors.TransferTransactionV2Descriptor(newAddress(MONITOR_ADDRESS),newmodels.Amount(0n)),signerKeyPair.publicKey,0n,2*60*60);transaction.fee=newmodels.Amount(calculateTransactionFee(transaction));constsignature=facade.signTransaction(signerKeyPair,transaction);constjsonPayload=facade.transactionFactory.static.attachSignature(transaction,signature);consttransactionHash=facade.hashTransaction(transaction).toString().toUpperCase();constshortHash=transactionHash.substring(0,16);
// Build and sign a transfer to the monitored addressfinalTransactiontransaction=facade.createTransactionFromTypedDescriptor(newTransferTransactionV2Descriptor(newAddress(monitorAddress),newAmount(0),null,List.of()),signerKeyPair.getPublicKey(),0,2*60*60);transaction.setFee(newAmount(FeeCalculator.calculateTransactionFee(transaction)));finalStringpayload=NemTransactionFactory.attachSignature(transaction,facade.signTransaction(signerKeyPair,transaction));finalStringtransactionHash=facade.hashTransaction(transaction).toString().toUpperCase();
# Connect to the WebSocketendpoint=f'{WS_URL}/w/messages'asyncwithconnect(sockjs_url(endpoint))aswebsocket:awaitstomp_connect(websocket)print(f'Connected to {WS_URL}')frames=stomp_frames(websocket)
// Connect to the WebSocketconstclient=newClient({webSocketFactory:()=>newSockJS(`${WS_URL}/w/messages`)});awaitnewPromise(resolve=>{client.onConnect=resolve;client.activate();});console.log(`Connected to ${WS_URL}`);
// Connect to the WebSocketfinalSessionsession=ContainerProvider.getWebSocketContainer().connectToServer(this,URI.create(sockJsUrl(wsUrl+"/w/messages")));finalRemoteEndpoint.Basicremote=session.getBasicRemote();rawFrames.take();// consume the SockJS open framesendFrame(remote,"CONNECT\naccept-version:1.1,1.0\n"+"heart-beat:0,0\nhost:"+nodeUrl+"\n\n\0");System.out.printf("Connected to %s%n",wsUrl);
# Subscribe to the account and transaction channelsaccount_channel=f'/account/{MONITOR_ADDRESS}'channels={account_channel:'id-0',f'/unconfirmed/{MONITOR_ADDRESS}':'id-1',f'/transactions/{MONITOR_ADDRESS}':'id-2',}forchannel,sub_idinchannels.items():awaitstomp_subscribe(websocket,channel,sub_id)print(f'Subscribed to {channel} channel')
// Subscribe to the account and transaction channelsconstaccountChannel=`/account/${MONITOR_ADDRESS}`;constsubscriptions=[{channel:accountChannel,handler:onAccountUpdate,id:'id-0'},{channel:`/unconfirmed/${MONITOR_ADDRESS}`,handler:onUnconfirmed,id:'id-1'},{channel:`/transactions/${MONITOR_ADDRESS}`,handler:onConfirmed,id:'id-2'}];for(const{channel,handler,id}ofsubscriptions){client.subscribe(channel,handler,{id});console.log(`Subscribed to ${channel} channel`);}
// Subscribe to the account and transaction channelsfinalStringaccountChannel="/account/"+monitorAddress;finalMap<String,String>channels=newHashMap<>();channels.put(accountChannel,"id-0");channels.put("/unconfirmed/"+monitorAddress,"id-1");channels.put("/transactions/"+monitorAddress,"id-2");for(finalMap.Entry<String,String>channel:channels.entrySet()){subscribe(remote,channel.getKey(),channel.getValue());System.out.printf("Subscribed to %s channel%n",channel.getKey());}
# Register the account and confirm it is activeawaitstomp_send(websocket,'/w/api/account/get',json.dumps({'account':MONITOR_ADDRESS}))asyncforframeinframes:ifaccount_channel==frame['headers']['destination']:balance=json.loads(frame['body'])['account']['balance']print(f'Account update: balance={balance}')breakprint('Account registered')
// Register the account and confirm it is activeclient.publish({destination:'/w/api/account/get',body:JSON.stringify({account:MONITOR_ADDRESS})});awaitregistered;console.log('Account registered');
// Register the account and confirm it is activesend(remote,"/w/api/account/get",JSON_MAPPER.createObjectNode().put("account",monitorAddress).toString());while(true){finalStompMessagemessage=nextMessage();if(accountChannel.equals(message.destination())){finalStringbalance=JSON_MAPPER.readTree(message.body()).get("account").get("balance").asText();System.out.printf("Account update: balance=%s%n",balance);break;}}System.out.println("Account registered");
# Wait for the transaction to confirmif'SUCCESS'==announce_result:confirmed=Falseasyncforframeinframes:destination=frame['headers']['destination']body=json.loads(frame['body'])ifaccount_channel==destination:balance=body['account']['balance']print(f'Account update: balance={balance}')ifconfirmed:breakelif'/transactions/'indestination:message_hash=body['meta']['hash']['data']print(f'confirmed: hash={message_hash[:16]}...')ifmessage_hash.upper()==transaction_hash:short_hash=transaction_hash[:16]print(f'Transaction {short_hash}... confirmed')confirmed=Trueelse:message_hash=body['meta']['hash']['data']ifmessage_hash.upper()==transaction_hash:print(f'unconfirmed: hash={message_hash[:16]}...')else:print(f'Transaction rejected: {announce_result}')
// Wait for the transaction to confirmletconfirmed=false;letresolveRegistered;letresolveDone;constregistered=newPromise(resolve=>{resolveRegistered=resolve;});constdone=newPromise(resolve=>{resolveDone=resolve;});constonUnconfirmed=message=>{constmessageHash=JSON.parse(message.body).meta.hash.data;if(messageHash.toUpperCase()===transactionHash){console.log(`unconfirmed: hash=${messageHash.substring(0,16)}...`);}};constonConfirmed=message=>{constmessageHash=JSON.parse(message.body).meta.hash.data;console.log(`confirmed: hash=${messageHash.substring(0,16)}...`);if(messageHash.toUpperCase()===transactionHash){console.log(`Transaction ${shortHash}... confirmed`);confirmed=true;}};constonAccountUpdate=message=>{const{balance}=JSON.parse(message.body).account;console.log(`Account update: balance=${balance}`);resolveRegistered();if(confirmed)resolveDone();};
// Wait for the transaction to confirmif("SUCCESS".equals(result)){booleanconfirmed=false;while(true){finalStompMessagemessage=nextMessage();finalJsonNodebody=JSON_MAPPER.readTree(message.body());if(accountChannel.equals(message.destination())){System.out.printf("Account update: balance=%s%n",body.get("account").get("balance").asText());if(confirmed)break;}else{finalStringhash=body.get("meta").get("hash").get("data").asText();if(message.destination().contains("/transactions/")){System.out.printf("confirmed: hash=%s...%n",hash.substring(0,16));if(hash.equalsIgnoreCase(transactionHash)){System.out.printf("Transaction %s... confirmed%n",transactionHash.substring(0,16));confirmed=true;}}elseif(hash.equalsIgnoreCase(transactionHash)){System.out.printf("unconfirmed: hash=%s...%n",hash.substring(0,16));}}}}else{System.out.printf("Transaction rejected: %s%n",result);}
# Unsubscribe before closingforsub_idinchannels.values():awaitstomp_unsubscribe(websocket,sub_id)print('Unsubscribed from all channels')awaitstomp_disconnect(websocket)
// Unsubscribe before closingfor(finalStringid:channels.values())sendFrame(remote,"UNSUBSCRIBE\nid:"+id+"\n\n\0");System.out.println("Unsubscribed from all channels");sendFrame(remote,"DISCONNECT\n\n\0");session.close();