eths / 🖊️EthPen-以太之笔.py
Ethscriptions's picture
Add application file
6802a9c
import streamlit as st
import requests
import re
import json
import hashlib
import base64
import sqlite3
import os
infura_api_key_eths = os.environ.get('infura_api_key_eths', '')
# Ethscriptions Mainnet API 的基础 URL
BASE_URL = "https://mainnet-api.ethscriptions.com/api"
# 获取当前文件目录
current_dir = os.path.dirname(os.path.abspath(__file__))
# 构造数据库文件路径
eths_db_file = os.path.join(current_dir, 'data', 'eths_data.db')
# Initialize connection to SQLite database
conn = sqlite3.connect(eths_db_file)
c = conn.cursor()
# Create table to store ETHS data
c.execute('''
CREATE TABLE IF NOT EXISTS eths_data
(date text,
eth_price real,
eths_price real,
eths_market_cap integer,
eths_owners integer,
eths_volume24h real,
eths_totalLocked integer,
eths_stakers integer,
eths_tvl real)
''')
# 查询地址所属代币铭文的 token 列表
token_list = [{'p': 'erc-20', 'tick': 'eths', 'id': 21000, 'amt': '1000'},
{'p': 'erc-20', 'tick': 'gwei', 'id': 21000, 'amt': '1000'},
{'p': 'erc-20', 'tick': 'ercs', 'id': 21000, 'amt': '1000'},
{'p': 'erc-20', 'tick': 'etch', 'id': 21000, 'amt': '1000'},
{'p': 'erc-20', 'tick': 'dumb', 'id': 21000, 'amt': '1000'}]
my_style = '''
<style>
.tag {
display: inline-block;
padding: 2px 6px;
background-color: #f2f2f2; /* 默认的背景颜色 */
border-radius: 5px; /* 圆角效果 */
margin: 0 2px;
transition: background-color 0.3s; /* 平滑的颜色过渡效果 */
}
.tag:hover {
background-color: #cffd51; /* 鼠标经过时的背景颜色 */
}
.tag:active {
background-color: #cffd51; /* 鼠标按下时的背景颜色 */
}
</style>
'''
# 图片Base64
def image_to_base64(img_path):
with open(img_path, "rb") as image_file:
return base64.b64encode(image_file.read()).decode()
# 验证代币铭文函数
def is_valid_eths(data, p, tick, id, amt):
# 构建匹配1到id-1的正则表达式
pattern_range = "|".join([str(i) for i in range(1, id)])
# 使用 f-string 插入参数到正则表达式
pattern = rf'^data:,{{"p":"{p}","op":"mint","tick":"{tick}","id":"({pattern_range}|{id})","amt":"{amt}"}}$'
return bool(re.match(pattern, data))
# 文本转换到十六进制
def text_to_hex(text):
return '0x' + ''.join(format(byte, '02x') for byte in text.encode('utf-8'))
# str SHA256
def sha256(input_string):
sha256 = hashlib.sha256()
sha256.update(input_string.encode('utf-8'))
return sha256.hexdigest()
# 根据 TX 获取 input data
def get_input_data(tx_hash):
endpoint = infura_api_key_eths
headers = {
"Content-Type": "application/json",
}
data = {
"jsonrpc": "2.0",
"id": 1,
"method": "eth_getTransactionByHash",
"params": [tx_hash]
}
eth_transaction = requests.post(endpoint, headers=headers, data=json.dumps(data))
transaction_data = eth_transaction.json()
return transaction_data['result']['input']
# 获取所有的 ethscriptions
def get_all_ethscriptions(page=None, per_page=None, sort_order=None):
endpoint = "/ethscriptions"
params = {
"page": page, # 页码
"per_page": per_page, # 每页的数量
"sort_order": sort_order # 排序顺序
}
response = requests.get(BASE_URL + endpoint, params=params)
return response.json()
# 根据地址获取 ethscriptions
def get_ethscriptions_by_address(address):
all_ethscriptions = []
page = 1
per_page = 100
while True:
endpoint = f"/ethscriptions/owned_by/{address}"
params = {
"page": page,
"per_page": per_page,
"sort_order": 'asc'
}
response = requests.get(BASE_URL + endpoint, params=params)
if response.status_code != 200:
print(f"Error fetching data: {response.text}")
break
ethscriptions = response.json()
all_ethscriptions.extend(ethscriptions)
if len(ethscriptions) < per_page:
break
page += 1
return all_ethscriptions
# 使用ID或数字获取特定的 ethscription
def get_specific_ethscription(ethscription_identifier):
endpoint = f"/ethscriptions/{ethscription_identifier}"
response = requests.get(BASE_URL + endpoint)
return response.json()
# 获取特定 ethscription 的数据
def get_ethscription_data(ethscription_identifier):
endpoint = f"/ethscriptions/{ethscription_identifier}/data"
response = requests.get(BASE_URL + endpoint)
return response.json()
# 使用 SHA256 值检查内容是否已被 ethscribed
def check_content_exists(sha):
endpoint = f"/ethscriptions/exists/{sha}"
response = requests.get(BASE_URL + endpoint)
if response.status_code == 200:
return response.json()
# 确定索引器是否落后
def get_block_status():
endpoint = "/block_status"
response = requests.get(BASE_URL + endpoint)
return response.json()
# 获取 $eths 价格
def get_eths_price():
params = {
'category': 'token',
'collectionName': 'erc-20 eths',
}
response = requests.get(
'https://www.etch.market/api/markets/collections/details',
params=params
)
if response.status_code == 200:
response = response.json()
if response['message'] == 'success':
return response['data']
return {} # 返回一个空字典作为默认值
# 从 etch.market 那里获取用户地址代币余额
def get_etch_token_amt():
params = {
'category': 'token',
'tokenQuery': '',
}
response = requests.get(
'https://www.etch.market/api/markets/ethscriptions/collections/0x59724739940777947c56C4f2f2C9211cd5130FEf',
params=params
)
if response.status_code == 200:
response = response.json()
if response['message'] == 'success':
return response['data']
return {} # 返回一个空字典作为默认值
# 获取 $eths 质押数据
def get_eths_staking():
response = requests.get('https://www.etch.market/api/staking/statistics/erc-20%20eths')
if response.status_code == 200:
response = response.json()
if response['message'] == 'success':
return response['data']
return {} # 返回一个空字典作为默认值
st.set_page_config(page_title="EthPen - 以太之笔", page_icon="🖊", layout='centered', initial_sidebar_state='auto')
# 首页
st.markdown(
f'# <a href="https://ethpen.com" target="_self"><img src="data:image/svg+xml;base64,{image_to_base64(os.path.join("img", "ethpen_logo.svg"))}" alt="Image" width="64px" height="64px" style="border-radius: 8px; box-shadow: 3px 3px 10px rgba(0,0,0,0.1);"/></a> :rainbow[EthPen - 以太之笔]',
unsafe_allow_html=True)
st.subheader('', anchor=False, divider='rainbow')
# 最近新闻
st.markdown(f'### 最近新闻')
st.markdown(
f'<a href="https://twitter.com/dumbnamenumbers/status/1696989307871826137" target="_blank"><img src="data:image/jpeg;base64,{image_to_base64(os.path.join("img", "news.jpeg"))}" alt="Image" style="max-width: 100%; width: 100%; height: auto; border-radius: 10px; display: block; box-shadow: 5px 5px 15px rgba(0,0,0,0.3);"/></a>',
unsafe_allow_html=True)
st.markdown(f'> 3 周前,我们提出了 Ethscriptions 虚拟机的构想——一种通过将其解释为计算机指令来显著增强 Ethscriptions 功能的方法。今天,我们宣布了该虚拟机的首个实现。已在 Goerli 网络上线,并已在 GitHub 上完全开源!👆')
# 广告位图片
st.markdown(f'### 广告位')
# st.markdown(
# f'<a href="https://twitter.com/EtchMarket/status/1694024108672245953" target="_blank"><img src="data:image/jpeg;base64,{image_to_base64(os.path.join("img", "ad.jpg"))}" alt="Image" style="max-width: 100%; width: 100%; height: auto; border-radius: 10px; display: block; box-shadow: 5px 5px 15px rgba(0,0,0,0.3);"/></a>',
# unsafe_allow_html=True)
#
# st.markdown(f'> 拆分方案现在面向所有人推出!让我们一起加入权益挖矿的浪潮,并分享50%的月度服务费。')
st.markdown(f'😭 接不到广告,我太穷了。')
st.markdown(
f'<img src="data:image/jpeg;base64,{image_to_base64(os.path.join("img", "alipay_qrcode.png"))}" alt="Image" style="max-width: 100%; width: 50%; height: auto; border-radius: 10px; display: block; box-shadow: 5px 5px 15px rgba(0,0,0,0.3);"/>',
unsafe_allow_html=True)
st.markdown('')
st.markdown(f'复制 <span class="tag">845076800</span>。 打开支付宝搜索,赏我一个猪脚饭。🥺', unsafe_allow_html=True)
st.markdown(f'### 什么是 Ethscriptions?', unsafe_allow_html=True)
st.markdown(f'{my_style}<span class="tag"><a href="https://ethscriptions.com/" target="_blank" style="text-decoration: none;"><img src="data:image/jpeg;base64,{image_to_base64(os.path.join("img", "ethscriptions_logo_litto.png"))}" alt="Image" width="20px" height="20px" style="border-radius: 3px;"/> Ethscriptions</span></a> 是一种新的在以太坊上创建和分享数字资产的方法,它通过使用交易 calldata 存储数据而不是智能合约来实现,这使其比 NFT 更为经济。它们是完全在链上、无需许可、抗审查的,并且其成本只是 NFT 的一小部分。', unsafe_allow_html=True)
st.markdown(f'<img src="data:image/jpeg;base64,{image_to_base64(os.path.join("img", "input_data.png"))}" alt="Image" style="max-width: 100%; width: 100%; height: auto; border-radius: 10px; display: block; box-shadow: 3px 3px 10px rgba(0,0,0,0.1);"/>', unsafe_allow_html=True)
st.markdown('')
st.markdown('### 谁创造了 Ethscriptions?')
st.markdown(f'首个 [Ethscription](https://ethscriptions.com/ethscriptions/0) 是在 2016 年创建的,但正式的协议是由 Tom Lehman,又名 <span class="tag"><a href="https://twitter.com/dumbnamenumbers" target="_blank" style="text-decoration: none;"><img src="data:image/jpeg;base64,{image_to_base64(os.path.join("img", "Middlemarch.jpg"))}" alt="Image" width="20px" height="20px" style="border-radius: 10px;"/> @Middlemarch</span></a> 开发的。除了比特币的铭文,他还受到了来自 Poly Network 黑客的著名的 “原型 - Ethscription” 的启发,你可以在[这笔交易](https://etherscan.io/tx/0x0ae3d3ce3630b5162484db5f3bdfacdfba33724ffb195ea92a6056beaa169490)中看到它。', unsafe_allow_html=True)
st.markdown(f'- 快来加入 <span class="tag"><a href="https://discord.gg/ethscriptions" target="_blank" style="text-decoration: none;"><img src="data:image/svg+xml;base64,{image_to_base64(os.path.join("img", "discord.svg"))}" alt="Image" width="20px" height="20px" style="border-radius: 3px;" /> @ethscriptions</span></a>,一起讨论 Ethscriptions 的未来!', unsafe_allow_html=True)
st.markdown(f'- 快来关注 <span class="tag"><a href="https://twitter.com/ethscriptions" target="_blank" style="text-decoration: none;"><img src="data:image/svg+xml;base64,{image_to_base64(os.path.join("img", "x.svg"))}" alt="Image" width="20px" height="20px" style="border-radius: 3px;" /> @ethscriptions</span></a>,掌握 Ethscriptions 的最新动态!', unsafe_allow_html=True)
st.markdown('### 如何题写 Ethscriptions?')
st.markdown(f'题写 Ethscriptions 是十分简单的,相当于在发送 ETH 交易时附带一些转账备注,我们就以使用人数最多的 MetaMask 钱包来举例,我们首先打开<span class="tag"><img src="data:image/svg+xml;base64,{image_to_base64(os.path.join("img", "0x.svg"))}" alt="Image" width="20px" height="20px" style="border-radius: 3px;" /> 显示十六进制数据</span>。', unsafe_allow_html=True)
st.markdown(f'1. 打开 <span class="tag"><a href="https://matamask.io" target="_blank" style="text-decoration: none;"><img src="data:image/svg+xml;base64,{image_to_base64(os.path.join("img", "metamask.svg"))}" alt="Image" width="20px" height="20px" style="border-radius: 3px;" /> Metamask</span></a> 钱包(如果已安装);', unsafe_allow_html=True)
st.markdown(f'2. 在右上角点击打开 <span class="tag"><img src="data:image/svg+xml;base64,{image_to_base64(os.path.join("img", "matamask-more.svg"))}" alt="Image" width="20px" height="20px" style="border-radius: 3px;" /> 菜单栏</span>;', unsafe_allow_html=True)
st.markdown(f'3. 点击打开 <span class="tag"><img src="data:image/svg+xml;base64,{image_to_base64(os.path.join("img", "metamask-gear.svg"))}" alt="Image" width="20px" height="20px" style="border-radius: 3px;" /> 设置项</span>;', unsafe_allow_html=True)
st.markdown(f'4. 点击打开 <span class="tag"><img src="data:image/svg+xml;base64,{image_to_base64(os.path.join("img", "metamask-line.svg"))}" alt="Image" width="20px" height="20px" style="border-radius: 3px;" /> 高级设置</span>;', unsafe_allow_html=True)
st.markdown(f'5. 点击打开 <span class="tag"><img src="data:image/svg+xml;base64,{image_to_base64(os.path.join("img", "0x.svg"))}" alt="Image" width="20px" height="20px" style="border-radius: 3px;" /> 显示十六进制数据</span>。', unsafe_allow_html=True)
st.markdown(f'然后让我们构思一下我们心仪的铭文,我们需要把铭文的文本转换成十六进制形式的数据,在下方文本框输入。', unsafe_allow_html=True)
input_ethscriptions_str = st.text_input('默认以 `data:,` 开头,输入需要转换的文本:', key='输入需要转换的文本')
if st.button('转换', key='文本转换到十六进制形式'):
if not input_ethscriptions_str.startswith('data:,'):
input_ethscriptions_str = f'data:,{input_ethscriptions_str}'
input_ethscriptions_hex = text_to_hex(input_ethscriptions_str)
input_ethscriptions_sha = sha256(input_ethscriptions_str)
ethscriptions_data = check_content_exists(input_ethscriptions_sha)
if ethscriptions_data['result']:
st.markdown(f'☹️ :green[{input_ethscriptions_str}] 已经被题写!相关信息如下:')
selected_data = {
'当前拥有者': ethscriptions_data["ethscription"]["current_owner"],
'题写时间': ethscriptions_data["ethscription"]["creation_timestamp"],
'铭文编号': f'#{ethscriptions_data["ethscription"]["ethscription_number"]}',
'铭文完整内容': ethscriptions_data["ethscription"]["content_uri"],
}
st.json(selected_data)
else:
st.markdown(f'😄 :green[{input_ethscriptions_str}] 还没被题写!快复制下方文本前去题写吧。')
st.code(input_ethscriptions_hex[2:], line_numbers=False)
st.markdown(f'好,让我们发送一笔交易吧,这笔交易是自己给自己发送 0ETH 的交易。', unsafe_allow_html=True)
st.markdown(f'1. 点击发送 <span class="tag"><img src="data:image/svg+xml;base64,{image_to_base64(os.path.join("img", "send.svg"))}" alt="Image" width="20px" height="20px" style="border-radius: 3px;" /> 发送交易</span>;', unsafe_allow_html=True)
st.markdown(f'2. 接收地址填写 <span class="tag"><img src="data:image/svg+xml;base64,{image_to_base64(os.path.join("img", "address.svg"))}" alt="Image" width="20px" height="20px" style="border-radius: 3px;" /> 自己的地址</span>,这是铭文接收的地址,然后金额填写为 0ETH;', unsafe_allow_html=True)
st.markdown(f'3. 填写 <span class="tag"><img src="data:image/svg+xml;base64,{image_to_base64(os.path.join("img", "0x.svg"))}" alt="Image" width="20px" height="20px" style="border-radius: 3px;" /> 十六进制数据</span>,也就是我们刚才复制的文本;', unsafe_allow_html=True)
st.markdown(f'4. 检查确认无误后发送交易。', unsafe_allow_html=True)
st.markdown(f'稍等片刻,我们就可以在 <span class="tag"><a href="https://etherscan.io" target="_blank" style="text-decoration: none;"><img src="data:image/svg+xml;base64,{image_to_base64(os.path.join("img", "etherscan-logo.svg"))}" alt="Image" width="20px" height="20px" style="border-radius: 3px;" /> Etherscan</span></a> 区块浏览器看到成功的交易。', unsafe_allow_html=True)
st.markdown(f'<img src="data:image/jpeg;base64,{image_to_base64(os.path.join("img", "etherscan_input_data.png"))}" alt="Image" style="max-width: 100%; width: 100%; height: auto; border-radius: 10px; display: block; box-shadow: 3px 3px 10px rgba(0,0,0,0.1);"/>', unsafe_allow_html=True)
st.markdown('')
st.markdown('我们可以输入铭文文本查询详细的信息,')
col1, col2 = st.columns(2)
ethscriptions_str = col1.text_input('输入完整的铭文文本:', '', label_visibility='collapsed')
search_information = col2.button('🔍 查询', key='查询信息')
if search_information:
if not ethscriptions_str.startswith('data:,'):
ethscriptions_str = f'data:,{ethscriptions_str}'
ethscriptions_all_str = sha256(ethscriptions_str)
ethscriptions_data = check_content_exists(ethscriptions_all_str)
if ethscriptions_data['result']:
st.markdown(f'###### :green[{ethscriptions_str}] 相关信息如下:')
selected_data = {
'当前拥有者': ethscriptions_data["ethscription"]["current_owner"],
'题写时间': ethscriptions_data["ethscription"]["creation_timestamp"],
'铭文编号': f'#{ethscriptions_data["ethscription"]["ethscription_number"]}',
'铭文完整内容': ethscriptions_data["ethscription"]["content_uri"],
}
st.json(selected_data)
else:
st.markdown(f'###### :green[{ethscriptions_str}] 铭文还没被题写!复制下方文本前去题写。')
st.code(f'{text_to_hex(ethscriptions_str)}', line_numbers=False)
st.markdown(f'同时我们也可以前往 <span class="tag"><a href="https://ethscriptions.com/" target="_blank" style="text-decoration: none;"><img src="data:image/jpeg;base64,{image_to_base64(os.path.join("img", "ethscriptions_logo_litto.png"))}" alt="Image" width="20px" height="20px" style="border-radius: 3px;"/> Ethscriptions</span></a> 官方网站查看我们的铭文。', unsafe_allow_html=True)
st.markdown(f'如果你觉得上述的方法步骤繁琐,我们建议你使用 Ethscriptions 官方推荐的 [EthScriber](https://ethscriber.xyz/) 还有 [Etherscan IDM](https://etherscan.io/idm),其他题写工具须在你确保安全的情况下使用,因为你不能确定它要发送什么铭文的交易。', unsafe_allow_html=True)
st.markdown(f'EthPen.com 不仅为你提供优质的工具,还有详尽的教程供你参考。欢迎你前来探索!', unsafe_allow_html=True)
st.markdown(f'🎉 更多功能尽在左上角的 <span class="tag"><img src="data:image/svg+xml;base64,{image_to_base64(os.path.join("img", "greater-than.svg"))}" alt="Image" width="20px" height="20px" style="border-radius: 3px;" /> 菜单栏</span>', unsafe_allow_html=True)
st.markdown('### Ethscriptions 上的龙头代币是?')
st.markdown(
f'毫无疑问,当之无愧,它必须是 Ethscriptions 上第一个代币 <span class="tag"><a href="https://www.etch.market/market/token?category=token&collectionName=erc-20%20eths" target="_blank" style="text-decoration: none;"><img src="data:image/jpeg;base64,{image_to_base64(os.path.join("img", "eths_logo.png"))}" alt="Image" width="20px" height="20px"/> $eths</span></a>',
unsafe_allow_html=True)
# 查询eths_data表中所有数据
c.execute('SELECT * FROM eths_data')
# 获取所有结果
eths_data = c.fetchall()
# 定义卡片样式
eths_card_style = """
<style>
.card {
border: 1px solid #e1e4e8;
padding: 20px;
border-radius: 15px;
margin: -20px 0;
}
.card p {
margin-top: 7px;
margin-bottom: 7px;
}
.card h5 {
margin-top: 10px;
margin-bottom: -10px;
}
.card a.button {
display: inline-block;
padding: 10px 15px;
border: none;
border-radius: 5px;
background-color: #5bc43b;
color: #fff;
text-align: center;
text-decoration: none;
transition: background-color 0.3s;
}
.card a.button:hover {
background-color: #ccfd51;
}
</style>
"""
st.markdown(eths_card_style, unsafe_allow_html=True)
# 创建卡片的HTML内容
eths_card_content = f"""
<div class="card">
<img src="data:image/jpeg;base64,{image_to_base64(os.path.join("img", "eths_logo.jpeg"))}" alt="Image" style="max-width: 100%; width: 100%; height: auto; border-radius: 10px; display: block;"/></a>
<p></p>
<div style="display: flex; align-items: center; gap: 10px;">
<img src="data:image/jpeg;base64,{image_to_base64(os.path.join("img", "eths_logo.png"))}" alt="Image" width="40px" height="40px" />
<div>
<h3 style="margin: 0; margin-bottom: -35px; font-size: 30px;">Ethscriptions eths</h3>
<p style="margin: 0; font-size: 40px;"><strong>${eths_data[0][2]:.2f}</strong></p>
</div>
</div>
<p>市值:<span class="tag">${eths_data[0][3]:,.0f}</span></p>
<p>总量:<span class="tag">21,000,000</span></p>
<p>24h 交易量:<span class="tag">${eths_data[0][5]:,.0f}</span></p>
<p>24h 交易所:<span class="tag"><a href="https://www.etch.market/market/token?category=token&collectionName=erc-20%20eths" target="_blank" style="text-decoration: none;"><img src="data:image/jpeg;base64,{image_to_base64(os.path.join("img", "etch-market.png"))}" alt="Image" width="20px" height="20px"/> Etch Market</span></a></p>
<h5>INFO</h5>
<p>官网:None</p>
<p>浏览器:<span class="tag"><a href="https://ethscriptions.com/" target="_blank" style="text-decoration: none;"><img src="data:image/jpeg;base64,{image_to_base64(os.path.join("img", "ethscriptions_logo_litto.png"))}" alt="Image" width="20px" height="20px" style="border-radius: 3px;"/> Ethscriptions</a></span></p>
<p>Ethscription ID:<span class="tag"><a href="https://ethscriptions.com/ethscriptions/0x4636542d00d8075360d0303eb224c4ffb638169c23d6308aace55249b0bed2e4" target="_blank" style="text-decoration: none;"><img src="data:image/jpeg;base64,{image_to_base64(os.path.join("img", "ethscriptions_logo_litto.png"))}" alt="Image" width="20px" height="20px" style="border-radius: 3px;"/> 0x463654......bed2e4</a></span></p>
<p>部署时间:<span class="tag">2023/06/18 05:46:11</span></p>
<p>公链:<span class="tag">Ethereum Ethscriptions</span></p>
<p>持有人数:<span class="tag">{eths_data[0][4]:,.0f}</span></p>
<p>社交:<span class="tag"><a href="https://twitter.com/ethscriptions" target="_blank" style="text-decoration: none;"><img src="data:image/svg+xml;base64,{image_to_base64(os.path.join("img", "x.svg"))}" alt="Image" width="20px" height="20px" style="border-radius: 3px;" /> @ethscriptions</span></a> <span class="tag"><a href="https://discord.gg/ethscriptions" target="_blank" style="text-decoration: none;"><img src="data:image/svg+xml;base64,{image_to_base64(os.path.join("img", "discord.svg"))}" alt="Image" width="20px" height="20px" style="border-radius: 3px;" /> @ethscriptions</span></a></p>
<h5>Staking</h5>
<p>质押总量:<span class="tag">{eths_data[0][6]:,.0f} $eths</span></p>
<p>质押人数:<span class="tag">{eths_data[0][7]:,.0f}</span></p>
<p>TVL:<span class="tag">${eths_data[0][8]:,.0f}</span></p>
<p><a href="https://www.etch.market/market/token?category=token&collectionName=erc-20%20eths" target="_blank" class="button">立即买入 $eths</a></p>
</div>
"""
st.markdown(eths_card_content, unsafe_allow_html=True)