Amazon Managed Blockchain + Web3.py Provider
I started using Amazon Managed Blockchain recently to run some ethereum nodes, and was surprised that I couldn't find a good Web3.py provider that plugs into Amazon Managed Blockchain.
I went ahead and wrote one - it's a fairly simple thing to get right; the trickiest part is getting the AWS signatures to work. fortunately, there's a library that helps with that.
The library depends on requests-auth-aws-sigv4 and requests, so pip install those first.
HTTP Provider
Let me know if this is helpful and I can turn it into a python package. I'll also implement a WSS version next.
Also, if you're debugging, be sure to double-check any errors using awscurl.
Update: I think it should be possible to do this by passing the authenticator into the HTTP provider kwargs. Specifically, see this line in the HTTPProvider implementation.
Problem is, you'll still run into the bytes encoding/decoding issue. So perhaps the solution is to make a modification to the signer library, instead of Web3.py.
Websocket Provider
Now with HTTP working, let's get the WebsocketProvider working as well. This one is a little bit easier to implement since we know the hooks and patterns from having done the HTTP Provider.
We'll need to do two things: implement a custom websocket handshake (to account for AWS's authentication), and fix binary encoding in the websocket protocol, since the API gateway doesn't yet support binary transport frames.
Implement Handshake
We need to add some code to the websocket handshake() coroutine so that this HTTP request gets decorated with the amazon signing headers. In the current release of Web3, I couldn't find a way to hook into the handshake() method, so we subclass WebSocketClientProtocol.
Here are the important sections we add to the handshake method. I purposely excluded the rest of the method and have the full implementation below.
We're using the requests library (which Web3.py uses) to take the HTTP request getting assembled in the websocket, decorate it with the AWS headers, and then submitting it.
Again, not the prettiest solution but it works.
Subclass the Provider
If you tried running this the way it is, you would be able to make a request, but the API Gateway that your node sits behind will reject it and you'll get error 1003. Some diligent googling highlights the issue: the API gateway doesn't support binary transport frames.
This part was actually really fun to write. I first thought I had to add a lot more code, but it's just a few additions. Essentially, before you make a request, you have to convert bytes to str, and when parsing a response, str to bytes. That's where the subclassed websocket provider comes into play:
Now:
Success.
Full code below:
Feel free to message me if you have any questions: @omarish.