Objectives
After generating some unique Kanji, the last step is to sell them on OpenSea. it is pain in the neck uploading thousand of images one by one. I found automation code that uploads my images to the OpenSea. I will use that code to upload my images on the OpenSea.
If you haven't checked Part 1 yet, Go to 【Part1】
Version
- python 3.8
- Pillow 8.4.0
Create OpenSea Account and Connected to Your Wallet
OpenSea is one of the largest peer-to-peer NFT marketplaces. To sign up and sell NFTs, you need...
- Create a cryptocurrency wallet (MetaMask) and Buy cryptocurrency (ETH)
- (Optional) Exchange ETH to polygon ← Recommended
- Create an OpenSea account
- Sell your image!
1. Create Cryptocurrency Wallet and Buy Ethereum
To create cryptocurrency wallet, use MetaMask; a Chrome extension that help us on the cryptocurrency transaction. After you download MetaMask to your Chrome, a Fox icon will show up on the top right of your browser. While creating a MetaMask account, they will give you 12 words. It's like your passcode for your bank account, DO NOT SHARE WITH ANYONE.
Once click the fox and you will see this little window. Use this window to add money, or make a smart contract. On the below window, click buy or 購入. Chose how you would like to add ETH. Since buying ETH is simple, we won't go into details.
2. (Optional) Exchange ETH to Polygon
Polygon is a decentralised Ethereum scaling platform that enables developers to build scalable user-friendly dApps with low transaction fees without ever sacrificing on security. - Polygon . In other words, Polygon is like raffle tickets that help us to pay a small gas fee on the transaction. After the transaction is done, you need to transfer Polygon to ETH. To transfer ETH to polygon, click here.
3. Create OpenSea Account
It's very simple! You can do it ! How to Create an Account. Make sure you connected to your MetaMask on your Chrome.
###4. Sell Your Image!
You can manually upload your image on OpenSea, but it's a pain in the neck to upload 1000+ images one by one. So most NFT artists create the automation script to upload the images. Thanks to Petko Aleksandrov for sharing his automation code. He also uploads a YouTube video to explain how to run the code. I would say just follow what he has done on his video. The only thing that you need to do is to make sure the code is updated to the latest version of OpenSea image upload flow. I had to fix some code because the timing of the popup window showing up was changed on my version of OpenSea. Here is my final automation code. (2022/2/16)
import tkinter
import subprocess
from tkinter import *
from tkinter import filedialog
import os
import sys
import pickle
import time
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.support import expected_conditions as ExpectedConditions
from selenium.webdriver.support.ui import Select
root = Tk()
root.geometry('500x400')
root.title("NFTs Upload to OpenSea ")
input_save_list = ["NFTs folder :", 0, 0, 0, 0, 0, 0, 0, 0]
main_directory = os.path.join(sys.path[0])
is_polygon = BooleanVar()
is_polygon.set(False)
def open_chrome_profile():
subprocess.Popen(
[
"start",
"chrome",
"--remote-debugging-port=8989",
"--user-data-dir=" + main_directory + "/chrome_profile",
],
shell=True,
)
def save_file_path():
return os.path.join(sys.path[0], "Save_file.cloud")
# ask for directory on clicking button, changes button name.
def upload_folder_input():
global upload_path
upload_path = filedialog.askdirectory()
Name_change_img_folder_button(upload_path)
def Name_change_img_folder_button(upload_folder_input):
upload_folder_input_button["text"] = upload_folder_input
class InputField:
def __init__(self, label, row_io, column_io, pos, master=root):
self.master = master
self.input_field = Entry(self.master)
self.input_field.label = Label(master, text=label)
self.input_field.label.grid(row=row_io, column=column_io)
self.input_field.grid(row=row_io, column=column_io + 1)
try:
with open(save_file_path(), "rb") as infile:
new_dict = pickle.load(infile)
self.insert_text(new_dict[pos])
except FileNotFoundError:
pass
def insert_text(self, text):
self.input_field.delete(0, "end")
self.input_field.insert(0, text)
def save_inputs(self, pos):
input_save_list.insert(pos, self.input_field.get())
with open(save_file_path(), "wb") as outfile:
pickle.dump(input_save_list, outfile)
###input objects###
collection_link_input = InputField("OpenSea Collection Link:", 2, 0, 1)
start_num_input = InputField("Start Number:", 3, 0, 2)
end_num_input = InputField("End Number:", 4, 0, 3)
price = InputField("Price:", 5, 0, 4)
title = InputField("Title:", 6, 0, 5)
description = InputField("Description:", 7, 0, 6)
file_format = InputField("NFT Image Format:", 8, 0, 7)
external_link = InputField("External link:", 9, 0, 8)
###save inputs###
def save():
input_save_list.insert(0, upload_path)
collection_link_input.save_inputs(1)
start_num_input.save_inputs(2)
end_num_input.save_inputs(3)
price.save_inputs(4)
title.save_inputs(5)
description.save_inputs(6)
file_format.save_inputs(7)
external_link.save_inputs(8)
# _____MAIN_CODE_____
def main_program_loop():
###START###
project_path = main_directory
file_path = upload_path
collection_link = collection_link_input.input_field.get()
start_num = int(start_num_input.input_field.get())
end_num = int(end_num_input.input_field.get())
loop_price = float(price.input_field.get())
loop_title = title.input_field.get()
loop_file_format = file_format.input_field.get()
loop_external_link = str(external_link.input_field.get())
loop_description = description.input_field.get()
##chromeoptions
opt = Options()
opt.add_experimental_option("debuggerAddress", "localhost:8989")
driver = webdriver.Chrome(
executable_path=project_path + "/chromedriver.exe",
chrome_options=opt,
)
wait = WebDriverWait(driver, 300)
###wait for methods
def wait_css_selector(code):
wait.until(
ExpectedConditions.presence_of_element_located((By.CSS_SELECTOR, code))
)
def wait_css_selectorTest(code):
wait.until(
ExpectedConditions.elementToBeClickable((By.CSS_SELECTOR, code))
)
def wait_xpath(code):
wait.until(ExpectedConditions.presence_of_element_located((By.XPATH, code)))
while end_num >= start_num:
print("Start creating NFT " + loop_title + str(start_num))
driver.get(collection_link)
time.sleep(3)
wait_xpath('//*[@id="__next"]/div[1]/main/div/div/div[1]/span/a')
additem = driver.find_element_by_xpath('//*[@id="__next"]/div[1]/main/div/div/div[1]/span/a')
additem.click()
time.sleep(1)
wait_xpath('//*[@id="media"]')
imageUpload = driver.find_element_by_xpath('//*[@id="media"]')
imagePath = os.path.abspath(file_path + "\\" + str(start_num) + "." + loop_file_format) # change folder here
imageUpload.send_keys(imagePath)
name = driver.find_element_by_xpath('//*[@id="name"]')
name.send_keys(loop_title + str(start_num)) # +1000 for other folders #change name before "#"
time.sleep(1)
ext_link = driver.find_element_by_xpath('//*[@id="external_link"]')
ext_link.send_keys(loop_external_link)
time.sleep(1)
desc = driver.find_element_by_xpath('//*[@id="description"]')
desc.send_keys(loop_description)
time.sleep(1)
# Select Polygon blockchain if applicable
if is_polygon.get():
blockchain_button = driver.find_element(By.XPATH, '//*[@id="__next"]/div[1]/main/div/div/section/div/form/div[7]/div/div[2]')
blockchain_button.click()
# polygon_button_location = '//span[normalize-space() = "Mumbai"]'
# polygon_button_location
wait_css_selector("input[value='Polygon']")
listing = driver.find_element_by_css_selector("button[value='Polygon']")
listing.click()
time.sleep(7)
create = driver.find_element_by_xpath('//*[@id="__next"]/div[1]/main/div/div/section/div[2]/form/div/div[1]/span/button')
driver.execute_script("arguments[0].click();", create)
time.sleep(1)
wait_css_selector("i[aria-label='Close']")
cross = driver.find_element_by_css_selector("i[aria-label='Close']")
cross.click()
time.sleep(1)
main_page = driver.current_window_handle
wait_xpath('//*[@id="__next"]/div[1]/main/div/div/div[1]/div/span[2]/a')
sell = driver.find_element_by_xpath('//*[@id="__next"]/div[1]/main/div/div/div[1]/div/span[2]/a')
sell.click()
time.sleep(1)
wait_css_selector("input[placeholder='Amount']")
amount = driver.find_element_by_css_selector("input[placeholder='Amount']")
amount.send_keys(str(loop_price))
time.sleep(1)
wait_css_selector("button[type='submit']")
listing = driver.find_element_by_css_selector("button[type='submit']")
listing.click()
time.sleep(1)
wait_css_selector("button[class='Blockreact__Block-sc-1xf18x6-0 Buttonreact__StyledButton-sc-glfma3-0 bhqEJb fzwDgL']")
listing = driver.find_element_by_css_selector("button[class='Blockreact__Block-sc-1xf18x6-0 Buttonreact__StyledButton-sc-glfma3-0 bhqEJb fzwDgL']")
listing.click()
time.sleep(3)
for handle in driver.window_handles:
if handle != main_page:
login_page = handle
# change the control to signin page
driver.switch_to.window(login_page)
wait_css_selector("button[data-testid='request-signature__sign']")
sign = driver.find_element_by_css_selector("button[data-testid='request-signature__sign']")
sign.click()
time.sleep(5)
driver.switch_to.window(main_page)
start_num = start_num + 1
print('NFT creation completed!')
#####BUTTON ZONE#######
button_save = tkinter.Button(root, width=20, text="Save Form", command=save)
button_save.grid(row=23, column=1)
button_start = tkinter.Button(root, width=20, bg="green", fg="white", text="Start", command=main_program_loop)
button_start.grid(row=25, column=1)
isPolygon = tkinter.Checkbutton(root, text='Polygon Blockchain', var=is_polygon)
isPolygon.grid(row=20, column=0)
open_browser = tkinter.Button(root, width=20, text="Open Chrome Browser", command=open_chrome_profile)
open_browser.grid(row=22, column=1)
upload_folder_input_button = tkinter.Button(root, width=20, text="Add NFTs Upload Folder", command=upload_folder_input)
upload_folder_input_button.grid(row=21, column=1)
try:
with open(save_file_path(), "rb") as infile:
new_dict = pickle.load(infile)
global upload_path
Name_change_img_folder_button(new_dict[0])
upload_path = new_dict[0]
except FileNotFoundError:
pass
#####BUTTON ZONE END#######
root.mainloop()
Chrome Driver Error
=> Download recent version of Chrome Driver. Or I have to change my OS from Mac to Window. I think the problem is something to do with your python does not open right Chrome with Chrome Driver.
Conclusion
Congratulations! Let's Get Rich!
References
- https://metamask.io/
- https://polygon.technology/
- https://support.opensea.io/hc/en-us/articles/1500012881642-How-do-I-transfer-ETH-from-Ethereum-to-Polygon-
- https://support.opensea.io/hc/en-us/articles/360063498313-How-do-I-create-an-NFT-
- https://github.com/nftdevs/NFTs-Upload-to-OpenSea/
- https://www.youtube.com/watch?v=dk_N53vnJiY