web3 event_filter.get_new_entries: ValueError {'code': -32000, 'message': 'filter 0x?????????? not found'} - web3py

pretty stuck here. I am following web3 examples and try to subscribe to smart contract events by calling web3 event_filter.get_new_entries: ValueError {'code': -32000, 'message': 'filter 0x???????????????? not found'}
I specifically want to listen for SINGLE/USDC LP's Swap event
Code
import json
import asyncio
from web3 import Web3
my_wallet_address = "xxx"
my_wallet_address = Web3.toChecksumAddress(my_wallet_address)
node_url = "https://evm.cronos.org/"
single_usdc_contract_address = Web3.toChecksumAddress("0x0fbab8a90cac61b481530aad3a64fe17b322c25d")
single_usdc_contract_abi = json.loads('... ABI json ...')
web3 = Web3(Web3.HTTPProvider(node_url))
contract = web3.eth.contract(address=single_usdc_contract_address, abi=single_usdc_contract_abi)
def handle_event(event):
print(Web3.toJSON(event))
async def log_loop(event_filter, poll_interval):
while True:
for event in event_filter.get_new_entries():
handle_event(event)
await asyncio.sleep(poll_interval)
filter = contract.events.Swap.createFilter(fromBlock='latest')
# filter = web3.eth.filter('latest')
loop = asyncio.get_event_loop()
try:
loop.run_until_complete(
asyncio.gather(
log_loop(filter, 2)))
finally:
loop.close()
Some poor guy fixed by changing from HTTPProvider to RPC. That's less than satisfactory. I worked around the problem by calling "createFilter" from each iteration of the While-loop! But I am not sure if I understand the root of the problem. Some suggests Node keep dropping filters, thus my fix to call "createFilter" every loop worked. But I really don't understand the root of the problem.
Thanks in advance.
References
web3 doc - events
SO reference
SINGLE/USDC
SINGLE/USDC - CRONOS Explorer where you will find ABI
CRONOS integration doc
Example from cryptomarketpool

Related

Falcon - Difference in stream type between unittests and actual API on post

I'm trying to write unittests for my falcon api, and I encountered a really weird issue when I tried reading the body I added to the unittests.
This is my unittest:
class TestDetectionApi(DetectionApiSetUp):
def test_valid_detection(self):
headers = {"Content-Type": "application/x-www-form-urlencoded"}
body = {'test': 'test'}
detection_result = self.simulate_post('/environments/e6ce2a50-f68f-4a7a-8562-ca50822b805d/detectionEvaluations',
body=urlencode(body), headers=headers)
self.assertEqual(detection_result.json, None)
and this is the part in my API that reads the body:
def _get_request_body(request: falcon.Request) -> dict:
request_stream = request.stream.read()
request_body = json.loads(request_stream)
validate(request_body, REQUEST_VALIDATION_SCHEMA)
return request_body
Now for the weird part, my function for reading the body is working without any issue when I run the API, but when I run the unittests the stream type seems to be different which affect the reading of it.
The stream type when running the API is gunicorn.http.body.Body and using unittests: wsgiref.validate.InputWrapper.
So when reading the body from the api all I need to do it request.stream.read() but when using the unittests I need to do request.stream.input.read() which is pretty annoying since I need to change my original code to work with both cases and I don't want to do it.
Is there a way to fix this issue? Thanks!!
It seems like issue was with how I read it. instead of using stream I used bounded_stream which seemed to work, also I removed the headers and just decoded my body.
my unittest:
class TestDetectionApi(DetectionApiSetUp):
def test_valid_detection(self):
body = '''{'test': 'test'}'''
detection_result = self.simulate_post('/environments/e6ce2a50-f68f-4a7a-8562-ca50822b805d/detectionEvaluations',
body=body.encode(), headers=headers)
self.assertEqual(detection_result.json, None)
how I read it:
def _get_request_body(request: falcon.Request) -> dict:
request_stream = request.bounded_stream.read()
request_body = json.loads(request_stream)
validate(request_body, REQUEST_VALIDATION_SCHEMA)
return request_body

Python Telegram Bot ConversationHandler not working with webhook

I want to make a ConversationHandler in my bot that is using a webhook, the ConversationHandler only runs the function at the entry point, after that neither does it run the state function, nor does it run the fallback function. This CommandHandler runs fine when bot is run by polling.
ConversationHandler:
conv_handler = ConversationHandler(
entry_points=[CommandHandler("start", start)],
states={
NEW_PROJECT: [CallbackQueryHandler(project_name)],
PROJECT_NAME: [MessageHandler(Filters.regex(".*"), store_name_maybe_project_type)],
PROJECT_TYPE: [CallbackQueryHandler(store_type_maybe_admin)]
},
fallbacks=[CommandHandler('cancel', cancel)],
)
All the required functions:
def start(update, context):
# Gives button of add project
# We can use for loop to display buttons
keyboard = [
[InlineKeyboardButton("Add Project", callback_data="add_project")],
]
reply_markup = InlineKeyboardMarkup(keyboard)
update.message.reply_text("You have no projects right now.", reply_markup=reply_markup)
# if existing project then PROJECT or else NEW_PROJECT
return NEW_PROJECT
def project_name(update, context):
# asks for project name
query = update.callback_query
update.message.reply_text(text="Okay, Please enter your project name:")
return PROJECT_NAME
def store_name_maybe_project_type(update, context):
# stores project name and conditionally asks for project type
print(update.message.text)
keyboard = [
[InlineKeyboardButton("Telegram Group", callback_data="group")],
[InlineKeyboardButton("Telegram Channel", callback_data="channel")]
]
reply_markup = InlineKeyboardMarkup(keyboard)
update.message.reply_text("What do you want to make?", reply_markup=reply_markup)
return PROJECT_TYPE
def store_type_maybe_admin(update, context):
# stores project type and conditonally asks for making admin
print(update.message.text)
keyboard = [[InlineKeyboardButton("Done", callback_data="done")]]
reply_markup = InlineKeyboardMarkup(keyboard)
update.message.reply_text(f"Make a private {update.message.text} and make this bot the admin", reply_markup=reply_markup)
return ConversationHandler.END
def cancel(update, context):
update.message.reply_text("Awww, that's too bad")
return ConversationHandler.END
This is how I set up the webhook(I think the problem is here somewhere):
#app.route(f"/{TOKEN}", methods=["POST"])
def respond():
"""Run the bot."""
update = telegram.Update.de_json(request.get_json(force=True), bot)
dispatcher = setup(bot, update)
dispatcher.process_update(update)
return "ok"
The setup function
def setup(bot, update):
# Create bot, update queue and dispatcher instances
dispatcher = Dispatcher(bot, None, workers=0)
##### Register handlers here #####
bot_handlers = initialize_bot(update)
for handler in bot_handlers:
dispatcher.add_handler(handler)
return dispatcher
And then I manually setup the webhook by using this route:
#app.route("/setwebhook", methods=["GET", "POST"])
def set_webhook():
s = bot.setWebhook(f"{URL}{TOKEN}")
if s:
return "webhook setup ok"
else:
return "webhook setup failed"
The add project button doesn't do anything.
ConversationHandler stores the current state in memory, so it's lost once the conv_handler reaches the end of it's lifetime (i.e. the variable is deleted or the process is shut down). Now your snippets don't show where you initialize the ConversationHandler, but I have the feeling that you create it anew for every incoming update - and every new instance doesn't have the knowledge of the previous one.
I have that feeling, because you create a new Dispatcher for every update as well. That's not necessary and in fact I'd strongly advise against it. Not only does it take time to initialize the Dispatcher, which you could save, but also if you're using chat/user/bot_data, the data get's lost every time you create a new instance.
The initialize_bot function is called in setup, where you create the new Dispatcher, which is why my guess would be that you create a new ConversationHandler for every update. Also it seems odd to me that the return value of that function seems to be dependent on the update - the handlers used by your dispatcher should be fixed ...
Disclaimer: I'm currently the maintainer of python-telegram-bot

Pika SelectConnection adapter 'Unresolved attribute reference'

I have a problem with connection to RabbitMQ using pika.SelectConnection adapter. I am using Pika 1.1.0 and Python 3.7.9, development using PyCharm Community.
Below snapshot of my code showing how I am creating connection.
import pika
def on_done():
connect.channel()
print("Open Callback")
if __name__ == '__main__':
account = "user"
password = "password"
server = "172.17.0.5"
credentials = pika.PlainCredentials(account, password)
parameters = pika.ConnectionParameters(host=server, port=15672, credentials=credentials, socket_timeout=10)
connect = pika.SelectConnection(parameters, on_open_callback=on_done)
connect.ioloop.start()
RabbitMQ is running, I have checked connection and messaging using pika.BlockingConnection adapter.
My IDE (PyCharm) is highliting start() function as "Unresolved attribute reference 'start' for class 'object'". When I run this code, there is no error. On admin webpage I don't see that connection is opened.
Has somebody meet similar problem? Something is wrong with my IDE?
Thank you for answer.
Just had the same warning, but in the AsyncPublisher-Example and I also wanted to get rid of it.
The problem is that the IOLoop is not specifically defined by pika, even though it should.
If you work with pika, the type of IOLoop you are looking for is:
pika.adapters.select_connection.IOLoop
In your case it would be the easiest to cast your IOLoop and then use this one to start.
io_loop = cast(pika.adapters.select_connection.IOLoop, connect.ioloop)
io_loop.start()
For the more complex AsyncPublisher I did pretty much the same thing:
def __init__(self, amqp_url: str, queues: List[str], interval: float):
self._ioloop: Optional[pika.adapters.select_connection.IOLoop] = None
And after the connection is established:
def run(self):
"""Run the example code by connecting and then starting the IOLoop.
"""
while not self._stopping:
self._connection = None
self._deliveries = []
self._ack = 0
self._not_ack = 0
self._message_number = 0
try:
self._connection = self.connect()
self._ioloop = cast(pika.adapters.select_connection.IOLoop, self._connection.ioloop)
self._ioloop.start()

Use of RabbitTemplate.convertSendAndReceive with org.springframework.messaging.Message

I have successfully used the following to send an org.springframework.amqp.core.Message and receive a byte []
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageBuilder;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
Message message =
MessageBuilder.withBody(payload)..setCorrelationIdString(id).build();
byte [] response = (byte[]) rabbitTemplate.convertSendAndReceive(message,m -> {
m.getMessageProperties().setCorrelationIdString(id);
This works fine if the queues are set up to handle the message correctly for Message<?>. But I have a series of queues that use the message type org.springframework.messaging.Message specifically Message<String>.
Is there a way I can use rabbitTemplate.convertSendAndReceive to send the org.springframework.messaging.Message Message< String>. Such that the following would work.
import org.springframework.messaging.Message;
import org.springframework.integration.support.MessageBuilder;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
Message<String> message =
MessageBuilder.withPayload(payload).setCorrelationId(id).build();
Object returnObject = rabbitTemplate.convertSendAndReceive(message);
I have looked at the MessageConverter but I am unsure if I can use that.
Alternatively, should I use org.springframework.messaging.core.GenericMessagingTemplate.convertSendAndReceive
UPDATE.
I can make it work if I change what I have on the queues from
#Transformer(inputChannel = Processor.INPUT, outputChannel = Processor.OUTPUT)
public Message<String> transform(Message<String> inMessage) {
to
#Transformer(inputChannel = Processor.INPUT, outputChannel = Processor.OUTPUT)
public Message<String> transform(Message<?> inMessage) { GenericMessage<?>
genericMessage = (GenericMessage<?>)inMessage.getPayload();
String payload = (String)genericMessage.getPayload();
but I would rather not have to change the transformers to make this work as the code in question is for integration tests and existing code already works with what I already have.
END UPDATE
I think I have given enough information but please let me know if more details are required. Ideally, I am looking for a code example or to point me to the documentation that answers my question.
Use the RabbitMessagingTemplate documentation here.
public Message<?> sendAndReceive(String exchange, String routingKey, Message<?> requestMessage)

How to test a helper Grok view that makes a redirect

I have a content type that needs to be modified in some way after calling a helper Grok view that checks some condition, makes some changes, sets a message and redirects to the original object.
my helper view only has a render method and I want to write some tests for it but I have no idea how to handle this.
I would like to check for an error message when some condition is not met, and for an info message when everything goes fine.
my code looks like this:
class MyHelperView(grok.View):
grok.context(IMyType)
grok.layer(IMyLayer)
grok.name('helper-view')
grok.require('my.permission')
def render(self):
variable = self.request.form.get('variable', None)
if not variable:
msg = _(u'Required input is missing.')
api.portal.show_message(message=msg, request=self.request, type='error')
else:
do_something()
msg = _(u'Information processed.')
api.portal.show_message(message=msg, request=self.request)
self.request.response.redirect(self.context.absolute_url())
when I call the view obviously I ended with a None object, as the view returns nothing. I don't know where to look for messages... request? response? any hint?
I would avoid using transaction commits in test code. The test framework is specifically designed to roll back the transactions at the end of each test. Your setUp override goes against this.
To check status messages in a unit test you should be able to do something like:
from Products.statusmessages.interfaces import IStatusMessage
IStatusMessage(request).show()
This is an adapter that adapts the request.
I ended up with test with a layer based on FunctionalTesting:
....
from plone.app.testing import TEST_USER_NAME
from plone.app.testing import TEST_USER_PASSWORD
from plone.testing.z2 import Browser
....
import transaction
...
class HelperViewTestCase(unittest.TestCase):
layer = FUNCTIONAL_TESTING
def setUp(self):
self.app = self.layer['app']
self.portal = self.layer['portal']
self.request = self.layer['request']
directlyProvides(self.request, IMyLayer)
with api.env.adopt_roles(['Manager']):
self.foo = api.content.create(self.portal, 'MyType', 'foo')
transaction.commit()
def test_response(self):
browser = Browser(self.app)
browser.handleErrors = False
browser.addHeader(
'Authorization',
'Basic {0}:{1}'.format(TEST_USER_NAME, TEST_USER_PASSWORD)
)
browser.open(self.foo.absolute_url())
browser.getControl('Do Something').click()
self.assertIn(
'Required input is missing.', browser.contents)
two things you need to check that make me spent some time debugging:
you must use transaction.commit() to reflect object creation on the ZODB
you must add an authorization header before trying to open the page
everything else is working.