I don't know what happens in my ThreadPoolExecutor - python

I am trying to create an automation to register hosts in Zabbix through its API asynchronously using concurrent.futures.ThreadPoolExecutor as you can see in this piece of code:
def zabbix_create_host(name, ip):
session = get_session()
token = get_token()
print(" "+name+" "+ip)
headers = {'Content-type': 'application/json'}
data = '{"jsonrpc": "2.0","method": "host.create","params": {"host": "'+name+'","interfaces": [{"type": 2,"main": 1,"useip": 1,"ip": "'+ip+'","dns": "","port": "10050"}],"groups": [{"groupid": "5"}],"templates": [],"macros": [{"macro": "{$USER_ID}","value": "123321"}],"inventory_mode": 0,"inventory": {"macaddress_a": "01234","macaddress_b": "56768"}},"auth": "'+token+'","id": 1}'
response = requests.post('http://127.0.0.1/api_jsonrpc.php', headers=headers, data=data)
response = response.json()
def zabbix_create_host_multiple(names, ips):
with concurrent.futures.ThreadPoolExecutor(max_workers=12) as executor:
df = pd.concat(executor,map(zabbix_create_host, names, ips))
return df
NAMES = ['PC1', 'PC2', 'PC3']
IPS = ['1.1.1.1', '2.2.2.2', '3.3.3.3']
zabbix_create_host_multiple(NAMES, IPS)
But when executing the code I get the following error:
File "main.py", line 159, in zabbix_create_hosts
zabbix_create_host_multiple(names, ips)
File "main.py", line 173, in zabbix_create_host_multiple
df = pd.concat(executor,map(zabbix_create_host, names, ips))
File "/home/sacarino/anaconda3/envs/aZabbix/lib/python3.8/site-packages/pandas/core/reshape/concat.py", line 274, in concat
op = _Concatenator(
File "/home/sacarino/anaconda3/envs/aZabbix/lib/python3.8/site-packages/pandas/core/reshape/concat.py", line 328, in __init__
objs = list(objs)
TypeError: 'ThreadPoolExecutor' object is not iterable
Let's see if you can help me, it's the first time I've worked with this

def zabbix_create_host(name, ip):
session = get_session()
token = get_token()
print(" "+name+" "+ip)
headers = {'Content-type': 'application/json'}
data = '{"jsonrpc": "2.0","method": "host.create","params": {"host": "'+name+'","interfaces": [{"type": 2,"main": 1,"useip": 1,"ip": "'+ip+'","dns": "","port": "10050"}],"groups": [{"groupid": "5"}],"templates": [],"macros": [{"macro": "{$USER_ID}","value": "123321"}],"inventory_mode": 0,"inventory": {"macaddress_a": "01234","macaddress_b": "56768"}},"auth": "'+token+'","id": 1}'
response = requests.post('http://127.0.0.1/api_jsonrpc.php', headers=headers, data=data)
response = response.json()
return pd.Series(response)
def zabbix_create_host_multiple(names, ips):
df = pd.DataFrame()
with concurrent.futures.ThreadPoolExecutor(max_workers=12) as executor:
df = df.append(list(map(zabbix_create_host, names, ips)))
return df
NAMES = ['PC1', 'PC2', 'PC3']
IPS = ['1.1.1.1', '2.2.2.2', '3.3.3.3']
zabbix_create_host_multiple(NAMES, IPS)
returning the response in terms of series and appending it to the dataframe

Related

Python, "TypeError: string indices must be integers, not 'str'" while not using any indices

there! Currently trying to code my first program to automate an API, but got stuck at the moment where I transfer 2 arguments from earlier functions to the 3-rd function.
BTW, feel free to leave any suggestions for the whole code, apart for the error.
Here I'm authenticating and extract the cookie token:
import requests
import json
from workfiles import general_http_methods
base_url = 'https://restful-booker.herokuapp.com'
"""Authentication"""
def booker_auth_method():
auth_resource = '/auth'
auth_url = base_url + auth_resource
print(auth_url)
auth_body = {'username': 'admin',
'password': 'password123'}
result_auth_token = general_http_methods.general_post_method(auth_url, auth_body)
json_result_auth_token = result_auth_token.json()
value_of_the_cookie_json_result_auth_token = str(json_result_auth_token.get('token'))
adding_token_to_value = 'token=' + value_of_the_cookie_json_result_auth_token
result_auth_cookie_token = {'Cookie': adding_token_to_value}
print(result_auth_cookie_token)
return result_auth_cookie_token
booker_auth_method_var = booker_auth_method()['Cookie']
Then I create a booking:
"""Creating a booking"""
def booker_create_booking_method():
create_booking_resource = '/booking'
create_booking_body = {
"firstname": 'Python',
"lastname": "Tester",
"totalprice": 111,
"depositpaid": True,
"bookingdates": {
"checkin": "2023-01-01",
"checkout": "2023-01-02"},
"additionalneeds": "Breakfast"}
create_booking_url = base_url + create_booking_resource
print(create_booking_url)
create_booking_result = general_http_methods.general_post_method(create_booking_url, create_booking_body)
json_create_booking_result = create_booking_result.json()
booking_id = json_create_booking_result.get('bookingid')
print(json_create_booking_result)
print(booking_id)
return booking_id
booker_create_booking_method_var = booker_create_booking_method()
Finally, I wanna pass the return values from the 2 previous functions into the function below. To do that, I saved the return values in the variables (booker_auth_method_var, booker_create_booking_method_var) and pass them as arguments into my next function.
"Updating the WHOLE booking"
def booker_update_booking_method(booker_auth_method_var, booker_create_booking_method_var):
update_booking_resource = '/booking/'
update_booking_cookie_token = booker_auth_method_var #
update_booking_id = str(booker_create_booking_method_var) #
update_booking_url = base_url + update_booking_resource + update_booking_id
update_booking_body = {
"firstname": "Python",
"lastname": "QA Engineer",
"totalprice": 777,
"depositpaid": False,
"bookingdates": {
"checkin": "2023-07-08",
"checkout": "2023-07-15"},
"additionalneeds": "ALL INCLUSIVE"}
update_booking_result = general_http_methods.general_put_method(update_booking_url, update_booking_cookie_token, update_booking_body)
print(update_booking_cookie_token)
print(update_booking_url)
print(update_booking_result.text)
return update_booking_result
booker_update_booking_method(booker_auth_method_var, booker_create_booking_method_var)
However, at the result I get the topic error, even though I don't even use any indices:
https://restful-booker.herokuapp.com/auth
{'Cookie': 'token=006b0313b7e7bb1'}
https://restful-booker.herokuapp.com/booking
{'bookingid': 8187, 'booking': {'firstname': 'Python', 'lastname': 'Tester', 'totalprice': 111, 'depositpaid': True, 'bookingdates': {'checkin': '2023-01-01', 'checkout': '2023-01-02'}, 'additionalneeds': 'Breakfast'}}
8187
Traceback (most recent call last):
File "/Users/usr/PycharmProjects/booker_automation/workfiles/booker_http_methods.py", line 80, in <module>
booker_update_booking_method(booker_auth_method_var, booker_create_booking_method_var)
File "/Users/usr/PycharmProjects/booker_automation/workfiles/booker_http_methods.py", line 72, in booker_update_booking_method
update_booking_result = general_http_methods.general_put_method(update_booking_url, update_booking_cookie_token,
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/usr/PycharmProjects/booker_automation/workfiles/general_http_methods.py", line 20, in general_put_method
result = requests.put(url, headers=headers, cookies=cookies, json=body)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/usr/PycharmProjects/autom_udemy_course_smith/lib/python3.11/site-packages/requests/api.py", line 130, in put
return request("put", url, data=data, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/usr/PycharmProjects/autom_udemy_course_smith/lib/python3.11/site-packages/requests/api.py", line 59, in request
return session.request(method=method, url=url, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/usr/PycharmProjects/autom_udemy_course_smith/lib/python3.11/site-packages/requests/sessions.py", line 573, in request
prep = self.prepare_request(req)
^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/usr/PycharmProjects/autom_udemy_course_smith/lib/python3.11/site-packages/requests/sessions.py", line 471, in prepare_request
cookies = cookiejar_from_dict(cookies)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/usr/PycharmProjects/autom_udemy_course_smith/lib/python3.11/site-packages/requests/cookies.py", line 537, in cookiejar_from_dict
cookiejar.set_cookie(create_cookie(name, cookie_dict[name]))
~~~~~~~~~~~^^^^^^
TypeError: string indices must be integers, not 'str'
Process finished with exit code 1
The key issue for me here is how to pass the booking id from func 2 into the resource path in the final function. I need to transform it from int to str to concatenate with base_url and update_booking_resource, but it causes the error.
I have already tried to workaround, but it causes other mistakes like
'int' object is not subscriptable
dict object is not callable
so I believe I have to deal with exactly this mistake but do not understand how
So I finally found out the reason:
In the first block I had to call not the key of the dict from the method, but the method itself as only it could be considered as cookie by the function below from my general_http_methods file:
def general_put_method(url, cookies, body):
result = requests.put(url, headers=headers, cookies=cookies, json=body)
return result
And using it as the parameter in the third method straightly, without passing into update_booking_cookie_token variable.
So the final code looks like this:
"""HTTP-methods for booker API"""
import requests
import json
from workfiles import general_http_methods
base_url = 'https://restful-booker.herokuapp.com'
"""Authentication"""
def booker_auth_method():
auth_resource = '/auth'
auth_url = base_url + auth_resource
print(auth_url)
auth_body = {'username': 'admin',
'password': 'password123'}
result_auth_token = general_http_methods.general_post_method(auth_url, auth_body)
json_result_auth_token = result_auth_token.json()
value_of_the_cookie_json_result_auth_token = str(json_result_auth_token.get('token'))
adding_token_to_auth_token_value = 'token=' + value_of_the_cookie_json_result_auth_token
result_auth_cookie_token = {'Cookie': adding_token_to_auth_token_value}
print(result_auth_cookie_token)
return result_auth_cookie_token
booker_auth_method_var = booker_auth_method()
"""Creating a booking"""
def booker_create_booking_method():
create_booking_resource = '/booking'
create_booking_body = {
"firstname": 'Python',
"lastname": "Tester",
"totalprice": 111,
"depositpaid": True,
"bookingdates": {
"checkin": "2023-01-01",
"checkout": "2023-01-02"},
"additionalneeds": "Breakfast"}
create_booking_url = base_url + create_booking_resource
print(create_booking_url)
create_booking_result = general_http_methods.general_post_method(create_booking_url, create_booking_body)
str_json_create_booking_result = str(create_booking_result.json()['bookingid'])
print(create_booking_result, str_json_create_booking_result)
return str_json_create_booking_result
booker_create_booking_method_var = booker_create_booking_method()
"Updating the WHOLE booking"
def booker_update_booking_method(booker_auth_method_var, booker_create_booking_method_var):
update_booking_resource = '/booking/'
update_booking_url = base_url + update_booking_resource + booker_create_booking_method_var
update_booking_body = {
"firstname": "Python",
"lastname": "QA Engineer",
"totalprice": 777,
"depositpaid": False,
"bookingdates": {
"checkin": "2023-07-08",
"checkout": "2023-07-15"},
"additionalneeds": "ALL INCLUSIVE"}
update_booking_result = general_http_methods.general_put_method(update_booking_url, booker_auth_method_var, update_booking_body)
print(update_booking_url, update_booking_result, update_booking_result.text)
return update_booking_result
booker_update_booking_method(booker_auth_method_var, booker_create_booking_method_var)
And here is code from the general_http_methods file:
"""General HTTP-methods"""
import requests
headers = {
'Content-Type':'application/json',
'Accept':'application/json'}
def general_get_meothod(url):
result = requests.get(url)
return result
def general_post_method(url, body):
result = requests.post(url, headers=headers, json=body)
return result
def general_put_method(url, cookies, body):
result = requests.put(url, headers=headers, cookies=cookies, json=body)
return result
def general_patch_method(url, cookies, body):
result = requests.patch(url, headers=headers, cookies=cookies, json=body)
return result
def general_delete_method(url, cookies, body):
result = requests.patch(url, headers=headers, cookies=cookies, json=body)
return result
How it will help somehow in case you gonna have similar issue.

Data mining inside twitter but getting less data

I would like to get tweets using specific keywords, within specific time, using specific language. I have all credentials from Twitter (Developer Portal-key,token,bearer). I have tried one extraction using this code.
import tweepy
from twitter_authentication import bearer_token
import time
import pandas as pd
client = tweepy.Client(bearer_token, wait_on_rate_limit=True)
frana_tweets = []
for response in tweepy.Paginator(client.search_all_tweets,
query = 'frana OR smottamento OR scivolamento OR crollo OR dissesto lang:it place_country:IT',
user_fields = ['username','public_metrics','description','location','created_at','entities','url','verified'],
tweet_fields = ['created_at','geo','entities','lang','non_public_metrics','public_metrics','source'],
place_fields = ['country','place_type'],
expansions = ['author_id','geo.place_id'],
start_time = '2019-11-01T00:00:00Z',
end_time = '2019-11-30T23:59:59Z',
max_results=500):
time.sleep(1)
frana_tweets.append(response)
result = []
user_dict = {}
place_dict = {}
tweet_dict = {}
# Loop through each response object
for response in frana_tweets:
# Take all of the users, and put them into a dictionary of dictionaries with the info we want to keep
for user in response.includes['users']:
user_dict[user.id] = {'name':user.name,
'username': user.username,
'created_at': user.created_at,
'description': user.description,
'entities': user.entities,
'location': user.location,
'pinned_tweet_id':user.pinned_tweet_id,
'protected':user.protected,
'followers_count': user.public_metrics['followers_count'],
'following_count': user.public_metrics['following_count'],
'tweet_count': user.public_metrics['tweet_count'],
'listed_count': user.public_metrics['listed_count'],
'url':user.url,
'verified':user.verified
}
for place in response.includes['places']:
place_dict[place.id] = {'geo_id':place.id,
'full_name':place.full_name,
'country': place.country,
'place_type': place.place_type
}
for tweet in response.data:
# For each tweet, find the author's information
author_info = user_dict[tweet.author_id]
geo_info = place_dict[place.id]
# Put all of the information we want to keep in a single dictionary for each tweet
result.append({'author_id': tweet.author_id,
'name':author_info['name'],
'username': author_info['username'],
'author_created_at': author_info['created_at'],
'author_description': author_info['description'],
'author_entities': author_info['entities'],
'author_location': author_info['location'],
'pinned_tweet_id':author_info['pinned_tweet_id'],
'protected':author_info['protected'],
'author_followers': author_info['followers_count'],
'author_following':author_info['following_count'],
'author_tweet_count': author_info['tweet_count'],
'author_listed_count': author_info['listed_count'],
'author_url': author_info['url'],
'author_verified': author_info['verified'],
'id_text':tweet.id, #identifica il tweet
'text': tweet.text,
'created_at': tweet.created_at,
'lang':tweet.lang,
'geo':tweet.geo,
'entities':tweet.entities,
'retweets': tweet.public_metrics['retweet_count'],
'replies': tweet.public_metrics['reply_count'],
'likes': tweet.public_metrics['like_count'],
'quote_count': tweet.public_metrics['quote_count'],
'non_public_metrics':tweet.non_public_metrics,
#'in_reply_to_user_id':tweet.in_reply_to_user_id,
'source':tweet.source,
'geo_id':geo_info['geo_id'],
'full_name':geo_info['full_name'],
'country': geo_info['country'],
'place_type': geo_info['place_type']
})
# Change this list of dictionaries into a dataframe
df4 = pd.DataFrame(result)
But it didn't get all data from Twitter. I mean, some tweets haven't been extracted. Why?
I have tried another code, but I have the same problem:
import requests
import os
import json
import twitter_authentication as config
import time
import pandas as pd
# Save your bearer token in a file called twitter_authentication.py in this directory
# Should look like this:
bearer_token = 'name_Bearer_token'
bearer_token = config.bearer_token
query = 'frana OR smottamento OR scivolamento OR crollo OR dissesto lang:it'
out_file = 'raw_tweets.txt'
search_url = "https://api.twitter.com/2/tweets/search/all"
# Optional params: start_time,end_time,since_id,until_id,max_results,next_token,
# expansions,tweet.fields,media.fields,poll.fields,place.fields,user.fields
query_params = {'query': query,
'start_time': '2019-11-01T00:00:00Z',
'end_time':'2019-11-30T23:59:59Z',
'tweet.fields': 'id,text,author_id,in_reply_to_user_id,geo,conversation_id,created_at,lang,public_metrics,referenced_tweets,reply_settings,source',
'user.fields': 'id,name,username,created_at,description,public_metrics,verified',
'expansions': 'author_id,geo.place_id',
'place.fields': 'full_name,id,country,country_code,geo,name,place_type',
'max_results': 500
}
def create_headers(bearer_token):
headers = {"Authorization": "Bearer {}".format(bearer_token)}
return headers
def connect_to_endpoint(url, headers, params, next_token = None):
if next_token:
params['next_token'] = next_token
response = requests.request("GET", search_url, headers=headers, params=params)
time.sleep(3.1)
print(response.status_code)
if response.status_code != 1000:
raise Exception(response.status_code, response.text)
return response.json()
def get_tweets(num_tweets, output_fh):
next_token = None
tweets_stored = 0
while tweets_stored < num_tweets:
headers = create_headers(bearer_token)
json_response = connect_to_endpoint(search_url, headers, query_params, next_token)
if json_response['meta']['result_count'] == 0:
break
author_dict = {x['id']: x['username']
for x in json_response['includes']['users']}
for tweet in json_response['data']:
try:
tweet['username'] = author_dict[tweet['author_id']],
#'username': author_info['username'],
tweet['id']=tweet['entities'],
except KeyError:
print(f"No data for {tweet['author_id']}")
output_fh.write(json.dumps(tweet) + '\n')
tweets_stored += 1
try:
next_token = json_response['meta']['next_token']
except KeyError:
break
return None
def main():
with open(out_file, 'w') as f:
get_tweets(1000, f)
main()
tweets = []
with open(out_file, 'r') as f:
for row in f.readlines():
tweet = json.loads(row)
tweets.append(tweet)
tweets[0]
df4 = pd.DataFrame(tweets)

KeyError: 'name' abi error on web3 Python

I'm trying to buy tokens using the swapExactTokensForTokens() Pancakeswap Router function), web3 imported in Python.
Problem 1: I keep getting an abi KeyError: 'name'. Here's my code and error below. I'm not sure how to handle this error.
problem 2: Is it possible to call the abi of a token without hardcoding it like I did below?
Code:
from web3 import Web3
import json
import key
import time
bsc = "https://bsc-dataseed.binance.org/"
web3 = Web3(Web3.HTTPProvider(bsc))
print(web3.isConnected())
print("Block Number: ", web3.eth.blockNumber)
#My wallet address
sender_address = '0x111111111111111111111111111111111111'
#Pancakeswap router address instantiate and ABI code
panRouterContractAddress = '0x10ED43C718714eb63d5aA57B78B54704E256024E'
panAbi = '[{"inputs":[{"internalType":"address","name":"_factory","type":"address"},{"internalType":"address","name":"_WETH","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"WETH","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"tokenA","type":"address"},{"internalType":"address","name":"tokenB","type":"address"},{"internalType":"uint256","name":"amountADesired","type":"uint256"},{"internalType":"uint256","name":"amountBDesired","type":"uint256"},{"internalType":"uint256","name":"amountAMin","type":"uint256"},{"internalType":"uint256","name":"amountBMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"addLiquidity","outputs":[{"internalType":"uint256","name":"amountA","type":"uint256"},{"internalType":"uint256","name":"amountB","type":"uint256"},{"internalType":"uint256","name":"liquidity","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amountTokenDesired","type":"uint256"},{"internalType":"uint256","name":"amountTokenMin","type":"uint256"},{"internalType":"uint256","name":"amountETHMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"addLiquidityETH","outputs":[{"internalType":"uint256","name":"amountToken","type":"uint256"},{"internalType":"uint256","name":"amountETH","type":"uint256"},{"internalType":"uint256","name":"liquidity","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"factory","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"uint256","name":"reserveIn","type":"uint256"},{"internalType":"uint256","name":"reserveOut","type":"uint256"}],"name":"getAmountIn","outputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"reserveIn","type":"uint256"},{"internalType":"uint256","name":"reserveOut","type":"uint256"}],"name":"getAmountOut","outputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"}],"name":"getAmountsIn","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"}],"name":"getAmountsOut","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountA","type":"uint256"},{"internalType":"uint256","name":"reserveA","type":"uint256"},{"internalType":"uint256","name":"reserveB","type":"uint256"}],"name":"quote","outputs":[{"internalType":"uint256","name":"amountB","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"tokenA","type":"address"},{"internalType":"address","name":"tokenB","type":"address"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"amountAMin","type":"uint256"},{"internalType":"uint256","name":"amountBMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"removeLiquidity","outputs":[{"internalType":"uint256","name":"amountA","type":"uint256"},{"internalType":"uint256","name":"amountB","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"amountTokenMin","type":"uint256"},{"internalType":"uint256","name":"amountETHMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"removeLiquidityETH","outputs":[{"internalType":"uint256","name":"amountToken","type":"uint256"},{"internalType":"uint256","name":"amountETH","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"amountTokenMin","type":"uint256"},{"internalType":"uint256","name":"amountETHMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"removeLiquidityETHSupportingFeeOnTransferTokens","outputs":[{"internalType":"uint256","name":"amountETH","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"amountTokenMin","type":"uint256"},{"internalType":"uint256","name":"amountETHMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bool","name":"approveMax","type":"bool"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"removeLiquidityETHWithPermit","outputs":[{"internalType":"uint256","name":"amountToken","type":"uint256"},{"internalType":"uint256","name":"amountETH","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"amountTokenMin","type":"uint256"},{"internalType":"uint256","name":"amountETHMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bool","name":"approveMax","type":"bool"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"removeLiquidityETHWithPermitSupportingFeeOnTransferTokens","outputs":[{"internalType":"uint256","name":"amountETH","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenA","type":"address"},{"internalType":"address","name":"tokenB","type":"address"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"amountAMin","type":"uint256"},{"internalType":"uint256","name":"amountBMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bool","name":"approveMax","type":"bool"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"removeLiquidityWithPermit","outputs":[{"internalType":"uint256","name":"amountA","type":"uint256"},{"internalType":"uint256","name":"amountB","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapETHForExactTokens","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactETHForTokens","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactETHForTokensSupportingFeeOnTransferTokens","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactTokensForETH","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactTokensForETHSupportingFeeOnTransferTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactTokensForTokens","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactTokensForTokensSupportingFeeOnTransferTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"uint256","name":"amountInMax","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapTokensForExactETH","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"uint256","name":"amountInMax","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapTokensForExactTokens","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"amountOut"}]'
contract = web3.eth.contract(address=panRouterContractAddress, abi=panAbi)
#Spend token instantiate and ABI
tokenToSpend = web3.toChecksumAddress("0xe9e7CEA3DedcA5984780Bafc599bD69ADd087D56") #Contract address for purchase currency (BUSD)
spendAbi = '[{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"constant":true,"inputs":[],"name":"_decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"_name","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"_symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"burn","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"mint","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"renounceOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"}]'
spendTokenContract = web3.eth.contract(tokenToSpend, abi=spendAbi) #Spend token instance
#Contract address of token and amount to purchase
tokenToBuy = web3.toChecksumAddress(input("Enter Token Address to buy: "))
#Input contract address for the token to purchase
amountIn = web3.toWei(input("How much to spend? "), 'ether')
#Amount of purchase currency to spend
#Trade execution (To accomodate fees, use the function: swapExactTokensForTokensSupportingFeeOnTransferTokens)
pancakeswap2_txn = contract.functions.swapExactTokensForTokens(amountIn, 0, [tokenToSpend,tokenToBuy], sender_address, (int(time.time()) + 1000000)).buildTransaction({
'from': sender_address,
'value': amountIn,
'gas': 250000,
'gasPrice': web3.toWei('5','gwei'),
'nonce': web3.eth.get_transaction_count(sender_address),
})
signed_txn = web3.eth.account.sign_transaction(pancakeswap2_txn, private_key=key.private)
tx_token = web3.eth.send_raw_transaction(signed_txn.rawTransaction)
print("Success!: " + web3.toHex(tx_token))
Error:
True
Block Number: 9762322
Enter Token Address to buy: 0x0e09fabb73bd3ade0a17ecc321fd13a19e81ce82
How much BUSD to spend? 1
Traceback (most recent call last):
File "c:/Users/Owner/Documents/BlockchainPy/MyCodes/test.py", line 30, in <module>
pancakeswap2_txn = contract.functions.swapExactTokensForTokens(amountIn, 0, [tokenToSpend,tokenToBuy], sender_address, (int(time.time()) + 1000000)).buildTransaction({
File "C:\Users\Owner\Documents\BlockchainPy\lib\sitepackages\web3\contract.py", line 876, in __call__clone._set_function_info()
File "C:\Users\Owner\Documents\BlockchainPy\lib\sitepackages\web3\contract.py", line 881, in _set_function_info
self.abi = find_matching_fn_abi(
File "C:\Users\Owner\Documents\BlockchainPy\lib\site-packages\web3\_utils\contracts.py", line 127, in find_matching_fn_abi
function_candidates = pipe(abi, name_filter, arg_count_filter, encoding_filter)
File "cytoolz/functoolz.pyx", line 667, in cytoolz.functoolz.pipe
return c_pipe(data, funcs)
File "cytoolz/functoolz.pyx", line 642, in cytoolz.functoolz.c_pipe
data = func(data)
File "C:\Users\Owner\Documents\BlockchainPy\lib\site-packages\web3\_utils\abi.py", line 93, in filter_by_name
return [
File "C:\Users\Owner\Documents\BlockchainPy\lib\sitepackages\web3\_utils\abi.py", line 99, in <listcomp> and abi['name'] == name
KeyError: 'name'
Error shows problem in line 99 in file abi.py with key abi["name"] so I found this file (you have full path in error) and add print() before line 99 to see all abi used in this place
def filter_by_name(name: str, contract_abi: ABI) -> List[Union[ABIFunction, ABIEvent]]:
for abi in contract_abi:
print(abi)
print('---')
# ... rest ...
and it shows me
{'stateMutability': 'payable', 'type': 'amountOut'}
which doesn't have "name": ... and this makes problem.
If you check panAbi = ... then you see this {'stateMutability': ...} at the end.
If I add ie."name": "" in this {'stateMutability': ...} in panAbi then it resolves problem but I don't know what real name it should have.
Problem 2: in general, you don't need to know any ABI, you can ask bscscan to return it for you.
This is the code (use the switch DEBUG to select between testnet and mainnet).
Set your BSC API key in place of bscAPIkey
import requests
import json
def GetABI (Address):
if DEBUG:
url_eth = "https://api-testnet.bscscan.com/api"
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.76 Safari/537.36'} # This is chrome, you can set whatever browser you like
API_ENDPOINT = url_eth+"?module=contract&action=getabi&address="+str(Address)+"&apikey="+bscAPIkey
resp = requests.get(url = API_ENDPOINT, headers=headers)
else:
url_eth = "https://api.bscscan.com/api"
API_ENDPOINT = url_eth+"?module=contract&action=getabi&address="+str(Address)+"&apikey="+bscAPIkey
resp = requests.get(url = API_ENDPOINT)
res = json.loads(resp.text)
status = int(res['status'])
if status:
response = resp.json()
abi=json.loads(response["result"])
return abi
else:
return False
Here's how i fix it:
contract_abi = json.loads('[{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"address","name":"_factory","internalType":"address"},{"type":"address","name":"_WETH","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"WETH","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"uint256","name":"amountA","internalType":"uint256"},{"type":"uint256","name":"amountB","internalType":"uint256"},{"type":"uint256","name":"liquidity","internalType":"uint256"}],"name":"addLiquidity","inputs":[{"type":"address","name":"tokenA","internalType":"address"},{"type":"address","name":"tokenB","internalType":"address"},{"type":"uint256","name":"amountADesired","internalType":"uint256"},{"type":"uint256","name":"amountBDesired","internalType":"uint256"},{"type":"uint256","name":"amountAMin","internalType":"uint256"},{"type":"uint256","name":"amountBMin","internalType":"uint256"},{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"deadline","internalType":"uint256"}]},{"type":"function","stateMutability":"payable","outputs":[{"type":"uint256","name":"amountToken","internalType":"uint256"},{"type":"uint256","name":"amountETH","internalType":"uint256"},{"type":"uint256","name":"liquidity","internalType":"uint256"}],"name":"addLiquidityETH","inputs":[{"type":"address","name":"token","internalType":"address"},{"type":"uint256","name":"amountTokenDesired","internalType":"uint256"},{"type":"uint256","name":"amountTokenMin","internalType":"uint256"},{"type":"uint256","name":"amountETHMin","internalType":"uint256"},{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"deadline","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"factory","inputs":[]},{"type":"function","stateMutability":"pure","outputs":[{"type":"uint256","name":"amountIn","internalType":"uint256"}],"name":"getAmountIn","inputs":[{"type":"uint256","name":"amountOut","internalType":"uint256"},{"type":"uint256","name":"reserveIn","internalType":"uint256"},{"type":"uint256","name":"reserveOut","internalType":"uint256"}]},{"type":"function","stateMutability":"pure","outputs":[{"type":"uint256","name":"amountOut","internalType":"uint256"}],"name":"getAmountOut","inputs":[{"type":"uint256","name":"amountIn","internalType":"uint256"},{"type":"uint256","name":"reserveIn","internalType":"uint256"},{"type":"uint256","name":"reserveOut","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256[]","name":"amounts","internalType":"uint256[]"}],"name":"getAmountsIn","inputs":[{"type":"uint256","name":"amountOut","internalType":"uint256"},{"type":"address[]","name":"path","internalType":"address[]"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256[]","name":"amounts","internalType":"uint256[]"}],"name":"getAmountsOut","inputs":[{"type":"uint256","name":"amountIn","internalType":"uint256"},{"type":"address[]","name":"path","internalType":"address[]"}]},{"type":"function","stateMutability":"pure","outputs":[{"type":"uint256","name":"amountB","internalType":"uint256"}],"name":"quote","inputs":[{"type":"uint256","name":"amountA","internalType":"uint256"},{"type":"uint256","name":"reserveA","internalType":"uint256"},{"type":"uint256","name":"reserveB","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"uint256","name":"amountA","internalType":"uint256"},{"type":"uint256","name":"amountB","internalType":"uint256"}],"name":"removeLiquidity","inputs":[{"type":"address","name":"tokenA","internalType":"address"},{"type":"address","name":"tokenB","internalType":"address"},{"type":"uint256","name":"liquidity","internalType":"uint256"},{"type":"uint256","name":"amountAMin","internalType":"uint256"},{"type":"uint256","name":"amountBMin","internalType":"uint256"},{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"deadline","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"uint256","name":"amountToken","internalType":"uint256"},{"type":"uint256","name":"amountETH","internalType":"uint256"}],"name":"removeLiquidityETH","inputs":[{"type":"address","name":"token","internalType":"address"},{"type":"uint256","name":"liquidity","internalType":"uint256"},{"type":"uint256","name":"amountTokenMin","internalType":"uint256"},{"type":"uint256","name":"amountETHMin","internalType":"uint256"},{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"deadline","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"uint256","name":"amountETH","internalType":"uint256"}],"name":"removeLiquidityETHSupportingFeeOnTransferTokens","inputs":[{"type":"address","name":"token","internalType":"address"},{"type":"uint256","name":"liquidity","internalType":"uint256"},{"type":"uint256","name":"amountTokenMin","internalType":"uint256"},{"type":"uint256","name":"amountETHMin","internalType":"uint256"},{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"deadline","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"uint256","name":"amountToken","internalType":"uint256"},{"type":"uint256","name":"amountETH","internalType":"uint256"}],"name":"removeLiquidityETHWithPermit","inputs":[{"type":"address","name":"token","internalType":"address"},{"type":"uint256","name":"liquidity","internalType":"uint256"},{"type":"uint256","name":"amountTokenMin","internalType":"uint256"},{"type":"uint256","name":"amountETHMin","internalType":"uint256"},{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"deadline","internalType":"uint256"},{"type":"bool","name":"approveMax","internalType":"bool"},{"type":"uint8","name":"v","internalType":"uint8"},{"type":"bytes32","name":"r","internalType":"bytes32"},{"type":"bytes32","name":"s","internalType":"bytes32"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"uint256","name":"amountETH","internalType":"uint256"}],"name":"removeLiquidityETHWithPermitSupportingFeeOnTransferTokens","inputs":[{"type":"address","name":"token","internalType":"address"},{"type":"uint256","name":"liquidity","internalType":"uint256"},{"type":"uint256","name":"amountTokenMin","internalType":"uint256"},{"type":"uint256","name":"amountETHMin","internalType":"uint256"},{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"deadline","internalType":"uint256"},{"type":"bool","name":"approveMax","internalType":"bool"},{"type":"uint8","name":"v","internalType":"uint8"},{"type":"bytes32","name":"r","internalType":"bytes32"},{"type":"bytes32","name":"s","internalType":"bytes32"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"uint256","name":"amountA","internalType":"uint256"},{"type":"uint256","name":"amountB","internalType":"uint256"}],"name":"removeLiquidityWithPermit","inputs":[{"type":"address","name":"tokenA","internalType":"address"},{"type":"address","name":"tokenB","internalType":"address"},{"type":"uint256","name":"liquidity","internalType":"uint256"},{"type":"uint256","name":"amountAMin","internalType":"uint256"},{"type":"uint256","name":"amountBMin","internalType":"uint256"},{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"deadline","internalType":"uint256"},{"type":"bool","name":"approveMax","internalType":"bool"},{"type":"uint8","name":"v","internalType":"uint8"},{"type":"bytes32","name":"r","internalType":"bytes32"},{"type":"bytes32","name":"s","internalType":"bytes32"}]},{"type":"function","stateMutability":"payable","outputs":[{"type":"uint256[]","name":"amounts","internalType":"uint256[]"}],"name":"swapETHForExactTokens","inputs":[{"type":"uint256","name":"amountOut","internalType":"uint256"},{"type":"address[]","name":"path","internalType":"address[]"},{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"deadline","internalType":"uint256"}]},{"type":"function","stateMutability":"payable","outputs":[{"type":"uint256[]","name":"amounts","internalType":"uint256[]"}],"name":"swapExactETHForTokens","inputs":[{"type":"uint256","name":"amountOutMin","internalType":"uint256"},{"type":"address[]","name":"path","internalType":"address[]"},{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"deadline","internalType":"uint256"}]},{"type":"function","stateMutability":"payable","outputs":[],"name":"swapExactETHForTokensSupportingFeeOnTransferTokens","inputs":[{"type":"uint256","name":"amountOutMin","internalType":"uint256"},{"type":"address[]","name":"path","internalType":"address[]"},{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"deadline","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"uint256[]","name":"amounts","internalType":"uint256[]"}],"name":"swapExactTokensForETH","inputs":[{"type":"uint256","name":"amountIn","internalType":"uint256"},{"type":"uint256","name":"amountOutMin","internalType":"uint256"},{"type":"address[]","name":"path","internalType":"address[]"},{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"deadline","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"swapExactTokensForETHSupportingFeeOnTransferTokens","inputs":[{"type":"uint256","name":"amountIn","internalType":"uint256"},{"type":"uint256","name":"amountOutMin","internalType":"uint256"},{"type":"address[]","name":"path","internalType":"address[]"},{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"deadline","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"uint256[]","name":"amounts","internalType":"uint256[]"}],"name":"swapExactTokensForTokens","inputs":[{"type":"uint256","name":"amountIn","internalType":"uint256"},{"type":"uint256","name":"amountOutMin","internalType":"uint256"},{"type":"address[]","name":"path","internalType":"address[]"},{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"deadline","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"swapExactTokensForTokensSupportingFeeOnTransferTokens","inputs":[{"type":"uint256","name":"amountIn","internalType":"uint256"},{"type":"uint256","name":"amountOutMin","internalType":"uint256"},{"type":"address[]","name":"path","internalType":"address[]"},{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"deadline","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"uint256[]","name":"amounts","internalType":"uint256[]"}],"name":"swapTokensForExactETH","inputs":[{"type":"uint256","name":"amountOut","internalType":"uint256"},{"type":"uint256","name":"amountInMax","internalType":"uint256"},{"type":"address[]","name":"path","internalType":"address[]"},{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"deadline","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"uint256[]","name":"amounts","internalType":"uint256[]"}],"name":"swapTokensForExactTokens","inputs":[{"type":"uint256","name":"amountOut","internalType":"uint256"},{"type":"uint256","name":"amountInMax","internalType":"uint256"},{"type":"address[]","name":"path","internalType":"address[]"},{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"deadline","internalType":"uint256"}]},{"type":"receive","stateMutability":"payable"}]')
# Every entry in ABI must have "name" attribute! Otherwise web3.py will fail when you call contract.functions.swapExactETHForTokens(1, [my_wallet_address], my_wallet_address, deadline)
i : int = 0
for entry in contract_abi:
if 'name' not in entry:
entry['name'] = f"dummy_name_{i}"
i = i+1

Error when requesting to transfer/send on coinbase api

I am trying to post a transfer to the coinbase api from one crypto account to another, but just cannot seem to make it happen. The error occurs at the bottom of my code when I attempt a transfer 2 times. The first time, it comes back with "{}", and the second it comes back with the traceback error.
Here is my code:
import hmac, hashlib, time, requests, os
from requests.auth import AuthBase
from coinbase.wallet.client import Client
API_KEY = os.environ.get('API_KEY')
API_SECRET = os.environ.get('API_SECRET')
xrp_acct_id = os.environ.get('XRP_ID')
usdc_acct_id = os.environ.get('USDC_ID')
xrp_destination_tag = os.environ.get('xrp_destination_tag')
xtz_acct_id = os.environ.get('XTZ_ID')
user_id = os.environ.get('Coinbase_User_Id')
# Create custom authentication for Coinbase API
class CoinbaseWalletAuth(AuthBase):
def __init__(self, api_key, secret_key):
self.api_key = api_key
self.secret_key = secret_key
def __call__(self, request):
timestamp = str(int(time.time()))
message = timestamp + request.method + request.path_url + (request.body or b'').decode()
signature = hmac.new(bytes(self.secret_key, 'utf-8'), message.encode('utf-8'), hashlib.sha256).hexdigest()
request.headers.update({
'CB-ACCESS-SIGN': signature,
'CB-ACCESS-TIMESTAMP': timestamp,
'CB-ACCESS-KEY': self.api_key,
'CB-VERSION': '2020-01-18'
})
return request
api_url = 'https://api.coinbase.com/v2/'
auth = CoinbaseWalletAuth(API_KEY, API_SECRET)
client = Client(API_KEY, API_SECRET)
# Get current user:
# r_user = requests.get(api_url + 'user', auth=auth)
# print(r_user.json())
# Get transactions:
# xrp_txs = client.get_transactions(xrp_acct_id)
# Get accounts:
r = requests.get(api_url + 'accounts', auth=auth)
# Get price (XRP-USD):
price = client.get_spot_price(currency_pair='XRP-USD')
# To parse the JSON
accounts_json = r.json()
#
# # Variable to figure out wallet balances
XRP_balance = 0.0
# Dictionary used to store balances and wallet name's
accounts = {}
# Loop to get balances
for i in range(0, len(accounts_json["data"])):
wallet = accounts_json["data"][i]["name"]
amount = accounts_json["data"][i]["balance"]["amount"]
# Switch statement to figure out which index which wallet is
if wallet == "XRP Wallet":
XRP_balance = float(amount) * float(price["amount"])
accounts["XRP_USD"] = XRP_balance
elif wallet == "USDC Wallet":
USDC_amount = amount
accounts["USDC"] = USDC_amount
else:
print()
print(accounts)
txs = {
'type': 'transfer',
'account_id': usdc_acct_id,
'to': xrp_acct_id,
'amount': '10',
'currency': 'USDC'
}
r = requests.post(api_url + 'accounts/' + usdc_acct_id + '/transactions', json=txs, auth=auth)
print(r.json())
###### OUTPUT FROM THIS IS "{}" ##############
tx = client.transfer_money(account_id=usdc_acct_id,
to=xtz_acct_id,
amount='10',
fee='0.99',
currency='USDC')
###### OUTPUT FROM THIS IS "Traceback error" See Below ##############
txs = {
'type': 'send',
'to': xrp_address["address"],
'destination_tag': xrp_destination_tag,
'amount': '10',
'currency': 'XRP'
}
r = requests.post(api_url + 'accounts/' + xtz_acct_id + '/transactions', json=txs, auth=auth)
print(r)
print(r.json())
########## THIS OUTPUT IS FROM AFTER TRACEBACK ERROR ################
Here is the entire output:
{'USDC': '100.000000', 'XRP_USD': 571.5256683544001}
{}
Traceback (most recent call last):
File "/Users/mattaertker/Documents/CryptoExchangeProgram/exchangeMyCurrency.py", line 97, in <module>
tx = client.transfer_money(account_id=usdc_acct_id,
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/coinbase/wallet/client.py", line 339, in transfer_money
response = self._post('accounts', account_id, 'transactions', data=params)
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/coinbase/wallet/client.py", line 132, in _post
return self._request('post', *args, **kwargs)
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/coinbase/wallet/client.py", line 116, in _request
return self._handle_response(response)
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/coinbase/wallet/client.py", line 125, in _handle_response
raise build_api_error(response)
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/coinbase/wallet/error.py", line 49, in build_api_error
blob = blob or response.json()
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/requests/models.py", line 898, in json
return complexjson.loads(self.text, **kwargs)
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/json/__init__.py", line 357, in loads
return _default_decoder.decode(s)
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/json/decoder.py", line 337, in decode
obj, end = self.raw_decode(s, idx=_w(s, 0).end())
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/json/decoder.py", line 355, in raw_decode
raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)
<Response [400]>
{'errors': [{'id': 'validation_error', 'message': 'Please enter a valid email or Tezos address', 'field': 'base'}]}
But hey, at least I can send money from my tezos account to my tezos account:
txs = {
'type': 'send',
'to': xtz_address["address"],
'destination_tag': xrp_destination_tag,
'amount': '10',
'currency': 'XRP'
}
r = requests.post(api_url + 'accounts/' + xtz_acct_id + '/transactions', json=txs, auth=auth)
print(r)
OUTPUT:
<Response [201]>
I check my tezos account, and of course because response is 201, it did send it to itself. I recently found out it doesn't do this when you don't have destination_tag specified, but still BUG!!
If you want to convert your crypto from one currency to another, you don't have to use transfer_money. Watching Coinbase API from webapp that are the endpoints you need to call:
Have to know base_id of crypto that you want to sell and base_id of crypto want to buy. You can know it by calling GET "https://api.coinbase.com/v2/ /assets/prices?base=USD&filter=holdable&resolution=latest" and get from response the "base_id" of your currencies.
Make an order by calling POST "https://api.coinbase.com/v2/trade" with a request body in json like this: { 'amount': [amount that you want to convert], 'amount_asset': [currency of amount that you want to convert], 'amount_from': 'input', 'source_asset': ["base_id" of crypto that you want to sell], 'target_asset': ["base_id" of crypto that you want to buy] }
If previous POST "/trade" response code is 201, you have to get the
"id" value of response's json and do a commit of your order by
calling POST "https://api.coinbase.com/v2/trades/[id of json response of previous https://api.coinbase.com/v2/trade POST"]/commit. If
the response code of this POST commit is 201, your exchange is
started and if there are not error in coinbase, your conversion is
done!

KeyError "id" Python: Why isn't the key in the dictionary?

I wanted to know why this error occurs. I know the key is not in the dictionary but how come? Line 94 is labeled in the code below.
Traceback (most recent call last): File "", line 154, in
cp.add_song_to_playlist()
File "", line 127, in add_song_to_playlist
playlist_id = self.create_playlist()
File "", line 94, in create_playlist
return response_json["id"] KeyError: 'id'
import json
import os
import google_auth_oauthlib.flow
import googleapiclient.discovery
import googleapiclient.errors
import requests
import youtube_dl
from exceptions import ResponseException
from secrets import spotify_token, spotify_user_id
class CreatePlaylist:
def __init__(self):
self.youtube_client = self.get_youtube_client()
self.all_song_info = {}
def get_youtube_client(self):
""" Log Into Youtube, Copied from Youtube Data API """
# Disable OAuthlib's HTTPS verification when running locally.
# *DO NOT* leave this option enabled in production.
os.environ["OAUTHLIB_INSECURE_TRANSPORT"] = "1"
api_service_name = "youtube"
api_version = "v3"
client_secrets_file = "client_secret.json"
# Get credentials and create an API client
scopes = ["https://www.googleapis.com/auth/youtube.readonly"]
flow = google_auth_oauthlib.flow.InstalledAppFlow.from_client_secrets_file(
client_secrets_file, scopes)
credentials = flow.run_console()
# from the Youtube DATA API
youtube_client = googleapiclient.discovery.build(
api_service_name, api_version, credentials=credentials)
return youtube_client
def get_liked_videos(self):
"""Grab Our Liked Videos & Create A Dictionary Of Important Song Information"""
request = self.youtube_client.videos().list(
part="snippet,contentDetails,statistics",
myRating="like"
)
response = request.execute()
# collect each video and get important information
for item in response["items"]:
video_title = item["snippet"]["title"]
youtube_url = "https://www.youtube.com/watch?v={}".format(
item["id"])
# use youtube_dl to collect the song name & artist name
video = youtube_dl.YoutubeDL({}).extract_info(
youtube_url, download=False)
song_name = video["track"]
artist = video["artist"]
if song_name is not None and artist is not None:
# save all important info and skip any missing song and artist
self.all_song_info[video_title] = {
"youtube_url": youtube_url,
"song_name": song_name,
"artist": artist,
# add the uri, easy to get song to put into playlist
"spotify_uri": self.get_spotify_uri(song_name, artist)
}
def create_playlist(self):
"""Create A New Playlist"""
request_body = json.dumps({
"name": "Youtube Liked Vids",
"description": "All Liked Youtube Videos",
"public": True
})
query = "https://api.spotify.com/v1/users/{}/playlists".format(
spotify_user_id)
response = requests.post(
query,
data=request_body,
headers={
"Content-Type": "application/json",
"Authorization": "Bearer {}".format(spotify_token)
}
)
response_json = response.json()
# playlist id
try:
response_json = response.json()
except Exception:
return None
return response_json.get('id', None)
def get_spotify_uri(self, song_name, artist):
"""Search For the Song"""
query = "https://api.spotify.com/v1/search?query=track%3A{}+artist%3A{}&type=track&offset=0&limit=20".format(
song_name,
artist
)
response = requests.get(
query,
headers={
"Content-Type": "application/json",
"Authorization": "Bearer {}".format(spotify_token)
}
)
response_json = response.json()
songs = response_json["tracks"]["items"]
# only use the first song
uri = songs[0]["uri"]
return uri
def add_song_to_playlist(self):
"""Add all liked songs into a new Spotify playlist"""
# populate dictionary with our liked songs
self.get_liked_videos()
# collect all of uri
uris = [info["spotify_uri"]
for song, info in self.all_song_info.items()]
# create a new playlist
playlist_id = self.create_playlist()
# add all songs into new playlist
request_data = json.dumps(uris)
query = "https://api.spotify.com/v1/playlists/{}/tracks".format(
playlist_id)
response = requests.post(
query,
data=request_data,
headers={
"Content-Type": "application/json",
"Authorization": "Bearer {}".format(spotify_token)
}
)
# check for valid response status
if response.status_code != 200:
raise ResponseException(response.status_code)
response_json = response.json()
return response_json
if __name__ == '__main__':
cp = CreatePlaylist()
cp.add_song_to_playlist()
This exception occurs when you try to get undefined keys value with [] from dict. To gently handle this try to use .get('id', None).
try:
response_json = response.json()
except Exception:
return None
return response_json.get('id', None)
it will return None if there is no value for the key 'id'.
You can replace None with any fallback value.

Categories