importasyncioimportjsonimportosimporturllib.requestfromsymbolchain.CryptoTypesimportPrivateKeyfromsymbolchain.facade.SymbolFacadeimportSymbolFacadefromsymbolchain.symbol.IdGeneratorimportgenerate_mosaic_alias_idfromsymbolchain.symbol.NetworkimportAddressfromwebsocketsimportconnectNODE_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}')defannounce_transaction(payload,endpoint,label):announce_request=urllib.request.Request(f'{NODE_URL}{endpoint}',data=payload.encode(),headers={'Content-Type':'application/json'},method='PUT')withurllib.request.urlopen(announce_request)asresponse:response.read()print(label)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 status channelchannel=f'status/{MONITOR_ADDRESS}'awaitwebsocket.send(json.dumps({'uid':uid,'subscribe':channel}))print('Subscribed to status channel')# Build a transfer transaction with a non-existent mosaicwithurllib.request.urlopen(f'{NODE_URL}/network/fees/transaction')asresp:fee_json=json.loads(resp.read().decode())fee_multiplier=max(fee_json['medianFeeMultiplier'],fee_json['minFeeMultiplier'])transaction=facade.create_transaction_from_descriptor({'type':'transfer_transaction_v1','recipient_address':Address(MONITOR_ADDRESS),'mosaics':[{'mosaic_id':generate_mosaic_alias_id('symbol.unknown'),'amount':1}]},signer_key_pair.public_key,fee_multiplier,2*60*60)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_transaction(json_payload,'/transactions',f'Announced transaction {transaction_hash[:16]}...')# Wait for error via WebSocketasyncforraw_messageinwebsocket:msg=json.loads(raw_message)tx_hash=msg['data']['hash']code=msg['data']['code']print(f'Transaction {tx_hash[:16]}... 'f'rejected with code: {code}')iftx_hash==transaction_hash:break# Unsubscribe before closingawaitwebsocket.send(json.dumps({'uid':uid,'unsubscribe':channel}))print('Unsubscribed from status channel')try:asyncio.run(main())exceptExceptionaserror:print(error)
import{PrivateKey}from'symbol-sdk';import{SymbolFacade,descriptors,generateMosaicAliasId,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}`);asyncfunctionannounceTransaction(payload,endpoint,label){awaitfetch(`${NODE_URL}${endpoint}`,{method:'PUT',headers:{'Content-Type':'application/json'},body:payload});console.log(label);}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 status channelconstchannel=`status/${MONITOR_ADDRESS}`;websocket.send(JSON.stringify({uid,subscribe:channel}));console.log('Subscribed to status channel');// Build a transfer transaction with a non-existent mosaicconstfeeResponse=awaitfetch(`${NODE_URL}/network/fees/transaction`);constfeeJSON=awaitfeeResponse.json();constfeeMultiplier=Math.max(feeJSON.medianFeeMultiplier,feeJSON.minFeeMultiplier);consttransaction=facade.createTransactionFromTypedDescriptor(newdescriptors.TransferTransactionV1Descriptor(newSymbolFacade.Address(MONITOR_ADDRESS),[newdescriptors.UnresolvedMosaicDescriptor(generateMosaicAliasId('symbol.unknown'),newmodels.Amount(1n))],undefined),signerKeyPair.publicKey,feeMultiplier,2*60*60);constsignature=facade.signTransaction(signerKeyPair,transaction);constjsonPayload=facade.transactionFactory.static.attachSignature(transaction,signature);consttransactionHash=facade.hashTransaction(transaction).toString();constrejected=newPromise(resolve=>{websocket.addEventListener('message',event=>{constmsg=JSON.parse(event.data);consttxHash=msg.data.hash;constcode=msg.data.code;console.log(`Transaction ${txHash.substring(0,16)}... `+`rejected with code: ${code}`);if(txHash===transactionHash)resolve();});});awaitannounceTransaction(jsonPayload,'/transactions',`Announced transaction ${transactionHash.substring(0,16)}...`);// Wait for error via WebSocketawaitrejected;// Unsubscribe before closingwebsocket.send(JSON.stringify({uid,unsubscribe:channel}));console.log('Unsubscribed from status channel');websocket.close();}catch(error){console.error(error);}
//JAVA 21+//DEPS org.symbol:symbol-sdk:3.3.1//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.List;importjava.util.concurrent.CompletableFuture;importcom.fasterxml.jackson.databind.JsonNode;importcom.fasterxml.jackson.databind.ObjectMapper;importjakarta.websocket.ClientEndpoint;importjakarta.websocket.ContainerProvider;importjakarta.websocket.OnMessage;importjakarta.websocket.RemoteEndpoint;importjakarta.websocket.Session;importjakarta.websocket.WebSocketContainer;importorg.symbol.sdk.CryptoTypes;importorg.symbol.sdk.facade.SymbolFacade;importorg.symbol.sdk.symbol.Address;importorg.symbol.sdk.symbol.IdGenerator;importorg.symbol.sdk.symbol.KeyPair;importorg.symbol.sdk.symbol.SymbolTransactionFactory;importorg.symbol.sdk.symbol.descriptors.*;importorg.symbol.sdk.symbol.models.*;@ClientEndpointpublicfinalclassListenTransactionError{privatestaticfinalObjectMapperJSON_MAPPER=newObjectMapper();privatestaticfinalHttpClientHTTP_CLIENT=HttpClient.newHttpClient();privatefinalCompletableFuture<String>uidFuture=newCompletableFuture<>();privatefinalCompletableFuture<Void>rejected=newCompletableFuture<>();privatefinalStringnodeUrl=System.getenv().getOrDefault("NODE_URL","https://reference.symboltest.net:3001");privatefinalStringwsUrl=nodeUrl.replaceFirst("http","ws")+"/ws";privatefinalSymbolFacadefacade=newSymbolFacade("testnet");privateStringtransactionHash;publicstaticvoidmain(finalString[]args){try{newListenTransactionError().run();}catch(finalExceptionex){System.out.println(null==ex.getMessage()?ex.toString():ex.getMessage());}}privatevoidrun()throwsException{System.out.printf("Using node %s%n",nodeUrl);finalStringmonitorAddress=System.getenv().getOrDefault("MONITOR_ADDRESS","TCHBDENCLKEBILBPWP3JPB2XNY64OE7PYHHE32I");System.out.printf("Monitoring address: %s%n",monitorAddress);finalStringsignerPrivateKey=System.getenv().getOrDefault("SIGNER_PRIVATE_KEY","0".repeat(64));finalKeyPairsignerKeyPair=newKeyPair(newCryptoTypes.PrivateKey(signerPrivateKey));// Connect to WebSocketfinalWebSocketContainercontainer=ContainerProvider.getWebSocketContainer();finalSessionsession=container.connectToServer(this,URI.create(wsUrl));finalRemoteEndpoint.Basicremote=session.getBasicRemote();finalStringuid=uidFuture.join();System.out.printf("Connected to %s with uid %s%n",wsUrl,uid);// Subscribe to status channelfinalStringchannel="status/"+monitorAddress;remote.sendText(JSON_MAPPER.createObjectNode().put("uid",uid).put("subscribe",channel).toString());System.out.println("Subscribed to status channel");// Build a transfer transaction with a non-existent mosaicfinalJsonNodefeeJSON=getJson("/network/fees/transaction");finallongfeeMultiplier=Math.max(feeJSON.get("medianFeeMultiplier").asLong(),feeJSON.get("minFeeMultiplier").asLong());finalTransactiontransaction=facade.createTransactionFromTypedDescriptor(newTransferTransactionV1Descriptor(newAddress(monitorAddress),List.of(newUnresolvedMosaicDescriptor(newUnresolvedMosaicId(IdGenerator.generateMosaicAliasId("symbol.unknown")),newAmount(1))),null),signerKeyPair.getPublicKey(),feeMultiplier,2*60*60);finalCryptoTypes.Signaturesignature=facade.signTransaction(signerKeyPair,transaction);finalStringjsonPayload=SymbolTransactionFactory.attachSignature(transaction,signature);transactionHash=facade.hashTransaction(transaction).toString();announceTransaction(jsonPayload,"/transactions","Announced transaction "+transactionHash.substring(0,16)+"...");// Wait for error via WebSocketrejected.join();// Unsubscribe before closingremote.sendText(JSON_MAPPER.createObjectNode().put("uid",uid).put("unsubscribe",channel).toString());System.out.println("Unsubscribed from status channel");session.close();}privateJsonNodegetJson(finalStringpath)throwsIOException,InterruptedException{finalHttpRequestrequest=HttpRequest.newBuilder(URI.create(nodeUrl+path)).GET().build();finalHttpResponse<String>response=HTTP_CLIENT.send(request,BodyHandlers.ofString());returnJSON_MAPPER.readTree(response.body());}privatevoidannounceTransaction(finalStringpayload,finalStringendpoint,finalStringlabel)throwsIOException,InterruptedException{finalHttpRequestrequest=HttpRequest.newBuilder(URI.create(nodeUrl+endpoint)).header("Content-Type","application/json").PUT(HttpRequest.BodyPublishers.ofString(payload)).build();HTTP_CLIENT.send(request,BodyHandlers.ofString());System.out.println(label);}// Handle incoming messages@OnMessagepublicvoidonMessage(finalStringpayload)throwsIOException{finalJsonNodemessage=JSON_MAPPER.readTree(payload);// Special case for the initial handshake messageif(message.has("uid")){uidFuture.complete(message.get("uid").asText());return;}finalStringtxHash=message.get("data").get("hash").asText();finalStringcode=message.get("data").get("code").asText();System.out.printf("Transaction %s... rejected with code: %s%n",txHash.substring(0,16),code);if(txHash.equals(transactionHash))rejected.complete(null);}}
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}`);
// Connect to WebSocketfinalWebSocketContainercontainer=ContainerProvider.getWebSocketContainer();finalSessionsession=container.connectToServer(this,URI.create(wsUrl));finalRemoteEndpoint.Basicremote=session.getBasicRemote();finalStringuid=uidFuture.join();System.out.printf("Connected to %s with uid %s%n",wsUrl,uid);
# Subscribe to status channelchannel=f'status/{MONITOR_ADDRESS}'awaitwebsocket.send(json.dumps({'uid':uid,'subscribe':channel}))print('Subscribed to status channel')
// Subscribe to status channelconstchannel=`status/${MONITOR_ADDRESS}`;websocket.send(JSON.stringify({uid,subscribe:channel}));console.log('Subscribed to status channel');
// Subscribe to status channelfinalStringchannel="status/"+monitorAddress;remote.sendText(JSON_MAPPER.createObjectNode().put("uid",uid).put("subscribe",channel).toString());System.out.println("Subscribed to status channel");
# Build a transfer transaction with a non-existent mosaicwithurllib.request.urlopen(f'{NODE_URL}/network/fees/transaction')asresp:fee_json=json.loads(resp.read().decode())fee_multiplier=max(fee_json['medianFeeMultiplier'],fee_json['minFeeMultiplier'])transaction=facade.create_transaction_from_descriptor({'type':'transfer_transaction_v1','recipient_address':Address(MONITOR_ADDRESS),'mosaics':[{'mosaic_id':generate_mosaic_alias_id('symbol.unknown'),'amount':1}]},signer_key_pair.public_key,fee_multiplier,2*60*60)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 a transfer transaction with a non-existent mosaicconstfeeResponse=awaitfetch(`${NODE_URL}/network/fees/transaction`);constfeeJSON=awaitfeeResponse.json();constfeeMultiplier=Math.max(feeJSON.medianFeeMultiplier,feeJSON.minFeeMultiplier);consttransaction=facade.createTransactionFromTypedDescriptor(newdescriptors.TransferTransactionV1Descriptor(newSymbolFacade.Address(MONITOR_ADDRESS),[newdescriptors.UnresolvedMosaicDescriptor(generateMosaicAliasId('symbol.unknown'),newmodels.Amount(1n))],undefined),signerKeyPair.publicKey,feeMultiplier,2*60*60);constsignature=facade.signTransaction(signerKeyPair,transaction);constjsonPayload=facade.transactionFactory.static.attachSignature(transaction,signature);consttransactionHash=facade.hashTransaction(transaction).toString();
// Build a transfer transaction with a non-existent mosaicfinalJsonNodefeeJSON=getJson("/network/fees/transaction");finallongfeeMultiplier=Math.max(feeJSON.get("medianFeeMultiplier").asLong(),feeJSON.get("minFeeMultiplier").asLong());finalTransactiontransaction=facade.createTransactionFromTypedDescriptor(newTransferTransactionV1Descriptor(newAddress(monitorAddress),List.of(newUnresolvedMosaicDescriptor(newUnresolvedMosaicId(IdGenerator.generateMosaicAliasId("symbol.unknown")),newAmount(1))),null),signerKeyPair.getPublicKey(),feeMultiplier,2*60*60);finalCryptoTypes.Signaturesignature=facade.signTransaction(signerKeyPair,transaction);finalStringjsonPayload=SymbolTransactionFactory.attachSignature(transaction,signature);transactionHash=facade.hashTransaction(transaction).toString();
announce_transaction(json_payload,'/transactions',f'Announced transaction {transaction_hash[:16]}...')# Wait for error via WebSocketasyncforraw_messageinwebsocket:msg=json.loads(raw_message)tx_hash=msg['data']['hash']code=msg['data']['code']print(f'Transaction {tx_hash[:16]}... 'f'rejected with code: {code}')iftx_hash==transaction_hash:break
constrejected=newPromise(resolve=>{websocket.addEventListener('message',event=>{constmsg=JSON.parse(event.data);consttxHash=msg.data.hash;constcode=msg.data.code;console.log(`Transaction ${txHash.substring(0,16)}... `+`rejected with code: ${code}`);if(txHash===transactionHash)resolve();});});awaitannounceTransaction(jsonPayload,'/transactions',`Announced transaction ${transactionHash.substring(0,16)}...`);// Wait for error via WebSocketawaitrejected;
// Handle incoming messages@OnMessagepublicvoidonMessage(finalStringpayload)throwsIOException{finalJsonNodemessage=JSON_MAPPER.readTree(payload);// Special case for the initial handshake messageif(message.has("uid")){uidFuture.complete(message.get("uid").asText());return;}finalStringtxHash=message.get("data").get("hash").asText();finalStringcode=message.get("data").get("code").asText();System.out.printf("Transaction %s... rejected with code: %s%n",txHash.substring(0,16),code);if(txHash.equals(transactionHash))rejected.complete(null);}
// Unsubscribe before closingwebsocket.send(JSON.stringify({uid,unsubscribe:channel}));console.log('Unsubscribed from status channel');websocket.close();
// Unsubscribe before closingremote.sendText(JSON_MAPPER.createObjectNode().put("uid",uid).put("unsubscribe",channel).toString());System.out.println("Unsubscribed from status channel");session.close();
Using node https://reference.symboltest.net:3001
Monitoring address: TCHBDENCLKEBILBPWP3JPB2XNY64OE7PYHHE32I
Connected to wss://reference.symboltest.net:3001/ws with uid jI0YhF0bJflDsIO915kmWUlZZew=
Subscribed to status channel
Announced transaction E14B012D3D254EF2...
Transaction E14B012D3D254EF2... rejected with code: Failure_Core_Insufficient_Balance
Unsubscribed from status channel