Spaces:
Sleeping
Sleeping
import streamlit as st | |
import requests | |
import re | |
import json | |
import hashlib | |
import pandas as pd | |
import base64 | |
import sqlite3 | |
import os | |
infura_api_key = "9bbc614b8a1d49d59869e97d0ee3bf61" | |
# 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'}] | |
ethscrptions_logo = """<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="-0.53 -2.18 14.000028839170737 20.067148724063962" style="enable-background:new 0 0 100 16.4081;" xml:space="preserve" width="19" height="25" xmlns:svgjs="http://svgjs.dev/svgjs"> | |
<g> | |
<path d="M11.6219,5.1455c-0.0003-0.0017-0.0012-0.0032-0.0015-0.0048c-0.0033-0.0173-0.0083-0.0343-0.0161-0.0502 		c-0.0086-0.0175-0.0199-0.034-0.0338-0.0487c-0.0053-0.0055-0.0119-0.0088-0.0176-0.0136 		c-0.0246-0.0207-0.0525-0.0365-0.0832-0.0431c-0.0378-0.0083-0.078-0.0056-0.1153,0.0093L8.399,6.1767 		C8.3763,6.1858,8.3568,6.1999,8.3393,6.216C8.3361,6.219,8.3329,6.2215,8.3299,6.2246c-0.0158,0.0166-0.0284,0.0357-0.0376,0.057 		c-0.0008,0.0018-0.0024,0.003-0.0032,0.0048l-0.5395,1.349L6.4982,1.1993c-0.002-0.0102-0.007-0.0192-0.0104-0.0288L6.3012,0.2141 		C6.2857,0.1355,6.2244,0.074,6.1459,0.0585C6.0681,0.0434,5.9871,0.0767,5.9433,0.1434l-4.9257,7.487 		c-0.011,0.0167-0.0187,0.0347-0.0241,0.0533c-0.0002,0.0007-0.0008,0.0012-0.001,0.002c-0.0007,0.0024,0,0.0049-0.0005,0.0072 		C0.9871,7.713,0.9859,7.7333,0.9875,7.7538c0.0005,0.0061,0.0009,0.0118,0.0019,0.0178c0.0039,0.0229,0.0104,0.0454,0.0224,0.0662 		L2.046,9.6167L0.3277,8.494C0.2674,8.4544,0.1902,8.4511,0.1269,8.4852c-0.0635,0.0341-0.1033,0.1001-0.104,0.172L0,11.2824 		c-0.0002,0.0267,0.0066,0.0516,0.0162,0.0753c0.0024,0.0058,0.0048,0.011,0.0077,0.0166c0.0118,0.0227,0.0266,0.0438,0.0464,0.0605 		c0.0003,0.0002,0.0003,0.0006,0.0007,0.0008l5.9106,4.9268c0.0031,0.0026,0.007,0.0035,0.0102,0.0058 		C6,16.3744,6.0082,16.3805,6.0173,16.3852c0.0028,0.0014,0.0053,0.003,0.0082,0.0043c0.0027,0.0012,0.0055,0.0016,0.0083,0.0028 		c0.0047,0.0019,0.0091,0.0037,0.0139,0.0053c0.0066,0.0022,0.0133,0.0039,0.0202,0.0053c0.003,0.0006,0.0055,0.0022,0.0085,0.0027 		c0.0104,0.0017,0.021,0.0025,0.0313,0.0025c0.0001,0,0.0001,0,0.0002,0c0.0001,0,0.0001-0.0001,0.0002-0.0001 		c0.0093,0,0.0186-0.0005,0.0279-0.0021c0.002-0.0003,0.0036-0.0017,0.0056-0.002c0.0068-0.0012,0.0137-0.0022,0.0203-0.0041 		c0.0051-0.0015,0.0098-0.0037,0.0148-0.0056c0.0024-0.0009,0.0049-0.0005,0.0072-0.0014c0.002-0.0008,0.0032-0.0025,0.0051-0.0034 		c0.0066-0.003,0.0131-0.0062,0.0193-0.01c0.0028-0.0016,0.0053-0.0032,0.0079-0.0049c0.002-0.0013,0.0042-0.0017,0.0061-0.0031 		c0.0022-0.0015,0.0032-0.0039,0.0053-0.0055c0.0049-0.0037,0.0099-0.0069,0.0144-0.0111c0.0025-0.0024,0.0042-0.0052,0.0066-0.0077 		c0.0081-0.0084,0.0164-0.0167,0.023-0.0267l0.0014-0.0022c0.0001,0,0.0001,0,0.0001-0.0001l1.1807-1.771l1.5889-2.3833 		l0.7754-1.1632c0.0443-0.0663,0.0441-0.153-0.0004-0.2191c-0.0446-0.0662-0.1239-0.0981-0.2028-0.0833l-0.5723,0.1161L11.6064,5.26 		c0.0038-0.0083,0.0048-0.0171,0.0074-0.0256c0.0032-0.0103,0.0076-0.0204,0.0089-0.031c0.0004-0.003-0.0003-0.006-0.0001-0.009 		C11.6241,5.178,11.6245,5.1616,11.6219,5.1455z M0.4138,9.021l0.2456,0.1605l0.2141,1.193l-0.4754,0.4488L0.4138,9.021z 		 M0.4938,11.2751l0.5787-0.5465l3.2682,3.7531L0.4938,11.2751z M2.8047,10.1374L1.4545,7.8151l1.8657-1.0145l0.268,0.9764 		l1.9285,7.0254L2.8047,10.1374z M3.299,6.3636L1.7791,7.19l4.2278-6.4264l0.0874,0.4481L3.299,6.3636z M9.2254,11.1793 		L8.813,11.7979l-0.738-0.3853l0.6649-0.1348c0.0001,0,0.0001,0,0.0003,0L9.2254,11.1793z M7.7577,10.2479L7.8786,8.374 		l0.6604-1.651l0.5335,0.5794L7.7577,10.2479z M10.7687,6.1234l-0.3365,0.2091L9.3397,7.0111l-0.529-0.5746l2.2278-0.8912 		L10.7687,6.1234z"/> | |
<g> | |
<polygon points="14.6965,13.7003 21.6177,13.7003 21.6177,11.5939 17.3105,11.5939 17.3105,9.9388 21.2789,9.9388 21.2789,7.8323 			17.3105,7.8323 17.3105,6.1773 21.636,6.1773 21.636,4.0719 14.6965,4.0719 		"/> | |
<path d="M26.4696,11.8007c-0.1051,0.0194-0.1966,0.0291-0.2748,0.0291c-0.1131,0-0.2058-0.0172-0.2774-0.0495 			c-0.0722-0.0334-0.1255-0.083-0.16-0.1509c-0.0345-0.0668-0.0518-0.1509-0.0518-0.251V8.3593h1.2413V6.479h-1.2413V4.7486h-2.5951 			V6.479h-0.9218v1.8803h0.9218v3.2637c-0.0065,0.5042,0.0921,0.9244,0.2957,1.2596c0.2037,0.3351,0.508,0.5807,0.9121,0.7359 			c0.4046,0.1552,0.9046,0.2166,1.4999,0.1853c0.2947-0.0162,0.5495-0.0485,0.7644-0.0991 			c0.2144-0.0496,0.3798-0.0916,0.4957-0.1261l-0.3761-1.8242C26.6522,11.7663,26.5747,11.7824,26.4696,11.8007z"/> | |
<path d="M33.9108,6.7322c-0.3777-0.2316-0.8222-0.348-1.3329-0.348c-0.5328,0-0.9891,0.1293-1.3684,0.3879 			c-0.3793,0.2586-0.6503,0.6185-0.8135,1.0797h-0.0749V4.0719h-2.5014v9.6284h2.5951V9.6382 			c0.0032-0.2382,0.0479-0.4429,0.1342-0.6131c0.0862-0.1713,0.2085-0.3028,0.3669-0.3955c0.1578-0.0927,0.3421-0.139,0.5522-0.139 			c0.3325,0,0.5884,0.1024,0.7688,0.306c0.1805,0.2037,0.2688,0.4838,0.2656,0.8415v4.0621h2.5956V9.093 			c0.0027-0.5269-0.0996-0.9935-0.3082-1.4007C34.5815,7.2839,34.2884,6.965,33.9108,6.7322z"/> | |
<path d="M40.6348,9.3559L39.1678,9.093c-0.2758-0.0506-0.4617-0.1207-0.5571-0.2112c-0.0959-0.0916-0.1423-0.1896-0.139-0.2963 			c-0.0033-0.1509,0.0754-0.2672,0.2349-0.348c0.16-0.0819,0.3513-0.1228,0.5738-0.1228c0.1724,0,0.3297,0.0291,0.4725,0.0872 			c0.1427,0.0582,0.2602,0.1401,0.3507,0.2468c0.0905,0.1067,0.1422,0.2338,0.1551,0.3815h2.3877 			c-0.0312-0.765-0.348-1.3641-0.9514-1.7962c-0.6034-0.4332-1.4277-0.6498-2.4712-0.6498c-0.6864,0-1.2796,0.0927-1.7795,0.2759 			c-0.4999,0.1832-0.8841,0.4493-1.1518,0.7995c-0.2678,0.3491-0.4003,0.7747-0.3971,1.2757 			c-0.0032,0.5679,0.1783,1.0312,0.5452,1.3921c0.3669,0.3599,0.9186,0.6044,1.655,0.7338l1.279,0.2252 			c0.2818,0.0506,0.4898,0.1163,0.6234,0.1972c0.1325,0.0819,0.2004,0.1918,0.2047,0.3297c-0.0043,0.1497-0.083,0.2661-0.2382,0.348 			c-0.1551,0.0808-0.3518,0.1218-0.5899,0.1218c-0.2947,0-0.5387-0.0614-0.7311-0.1853c-0.1928-0.1239-0.3065-0.3006-0.341-0.529 			h-2.5768c0.0722,0.7391,0.4192,1.335,1.0414,1.7865c0.6222,0.4515,1.4853,0.6767,2.5887,0.6767 			c0.6681,0,1.2628-0.1024,1.7844-0.3071c0.5215-0.2058,0.9342-0.4967,1.2369-0.8749c0.3017-0.3782,0.4547-0.8232,0.4579-1.3372 			c-0.0032-0.5334-0.1853-0.959-0.5474-1.2769C41.9256,9.718,41.374,9.4906,40.6348,9.3559z"/> | |
<path d="M46.4252,8.5166c0.1692-0.1293,0.3664-0.1951,0.5926-0.1951c0.2888,0,0.5237,0.1002,0.7079,0.2985 			c0.1832,0.1993,0.292,0.4881,0.3265,0.8674h2.4071c-0.0032-0.626-0.1476-1.1723-0.4321-1.6378 			c-0.2855-0.4655-0.6874-0.8264-1.2068-1.0818c-0.5183-0.2554-1.1324-0.3836-1.8403-0.3836c-0.7833,0-1.4546,0.1562-2.0127,0.4687 			c-0.5571,0.3114-0.9859,0.7467-1.2833,1.307c-0.2974,0.5592-0.4461,1.2089-0.4461,1.9481c0,0.7402,0.1487,1.39,0.4461,1.9491 			c0.2974,0.5592,0.7262,0.9956,1.2833,1.307c0.5581,0.3114,1.2294,0.4676,2.0127,0.4676c0.7144,0,1.3296-0.1283,1.8457-0.3847 			c0.5151-0.2575,0.9137-0.6217,1.196-1.0937c0.2824-0.4719,0.4278-1.0257,0.4375-1.6615h-2.4071 			c-0.0194,0.25-0.0743,0.4622-0.167,0.6368c-0.0926,0.1735-0.2122,0.3049-0.3599,0.3943 			c-0.1476,0.0895-0.3168,0.1347-0.5075,0.1347c-0.2263,0-0.4234-0.0657-0.5926-0.195c-0.1691-0.1304-0.3006-0.3265-0.3943-0.5883 			c-0.0948-0.2618-0.1411-0.5894-0.1411-0.9848c0-0.3955,0.0463-0.723,0.1411-0.9849C46.1246,8.8431,46.2561,8.6469,46.4252,8.5166z 			"/> | |
<path d="M55.4319,6.3842c-0.3857,0-0.7219,0.1186-1.0085,0.3534c-0.2866,0.2349-0.4957,0.6067-0.6271,1.1142h-0.0755V6.479 			h-2.5202v7.2213h2.5957V9.9388c0-0.2759,0.0571-0.5161,0.1735-0.7208c0.1164-0.2058,0.2747-0.3653,0.4773-0.4806 			c0.2026-0.1142,0.4299-0.1714,0.6842-0.1714c0.1347,0,0.2963,0.0108,0.4838,0.0334c0.1886,0.0215,0.3469,0.055,0.4752,0.0981 			V6.4833c-0.1034-0.0313-0.2112-0.056-0.3222-0.0733C55.6571,6.3928,55.5451,6.3842,55.4319,6.3842z"/> | |
<path d="M57.908,5.7269c0.3501,0,0.6507-0.1164,0.8997-0.348c0.25-0.2322,0.3739-0.5112,0.3739-0.8372 			c0-0.3259-0.1239-0.605-0.3739-0.8367c-0.2489-0.2322-0.5506-0.348-0.9051-0.348c-0.3513,0-0.6519,0.1159-0.903,0.348 			c-0.25,0.2317-0.3761,0.5108-0.3761,0.8367c0,0.326,0.1261,0.605,0.3761,0.8372C57.2507,5.6105,57.5535,5.7269,57.908,5.7269z"/> | |
<rect x="56.6053" y="6.479" width="2.5957" height="7.2213"/> | |
<path d="M66.2111,6.7656c-0.431-0.2543-0.8846-0.3815-1.3609-0.3815c-0.3577,0-0.6713,0.0625-0.9407,0.1865 			c-0.2694,0.1239-0.4957,0.2877-0.6767,0.4934c-0.1821,0.2058-0.32,0.4299-0.4138,0.6745h-0.0571V6.479h-2.5762v9.929h2.5956 			v-3.8919h0.0377c0.1002,0.2446,0.2435,0.4622,0.4299,0.6551c0.1864,0.1929,0.4116,0.3448,0.6767,0.4569 			c0.2651,0.111,0.5667,0.1659,0.9051,0.1659c0.514,0,0.987-0.1346,1.418-0.4041c0.431-0.2693,0.7758-0.6788,1.0344-1.2272 			c0.2586-0.5485,0.3879-1.2392,0.3879-2.0731c0-0.8717-0.1358-1.5796-0.4073-2.1248C66.9934,7.4186,66.6421,7.0199,66.2111,6.7656z 			 M64.8664,11.0088c-0.0895,0.2554-0.2177,0.4514-0.3857,0.5883c-0.1681,0.1358-0.3707,0.2036-0.6088,0.2036 			c-0.2382,0-0.4429-0.0689-0.6131-0.209c-0.1714-0.139-0.3028-0.3373-0.3955-0.5926c-0.0927-0.2554-0.139-0.5581-0.139-0.9094 			c0-0.3578,0.0463-0.6637,0.139-0.9191c0.0927-0.2554,0.2241-0.4515,0.3955-0.5883c0.1702-0.1358,0.375-0.2037,0.6131-0.2037 			c0.2381,0,0.4406,0.0678,0.6088,0.2037c0.1681,0.1368,0.2963,0.3329,0.3857,0.5883C64.9558,9.4259,65,9.7319,65,10.0897 			C65,10.4474,64.9558,10.7534,64.8664,11.0088z"/> | |
<path d="M72.2601,11.8007c-0.1046,0.0194-0.1972,0.0291-0.2748,0.0291c-0.1131,0-0.2058-0.0172-0.2779-0.0495 			c-0.0722-0.0334-0.125-0.083-0.1595-0.1509c-0.0345-0.0668-0.0518-0.1509-0.0518-0.251V8.3593h1.2413V6.479h-1.2413V4.7486 			h-2.5956V6.479h-0.9213v1.8803h0.9213v3.2637c-0.0065,0.5042,0.0926,0.9244,0.2963,1.2596 			c0.2037,0.3351,0.5075,0.5807,0.9126,0.7359c0.4041,0.1552,0.9041,0.2166,1.4999,0.1853 			c0.2941-0.0162,0.5495-0.0485,0.7639-0.0991c0.2144-0.0496,0.3803-0.0916,0.4957-0.1261l-0.3761-1.8242 			C72.4433,11.7663,72.3657,11.7824,72.2601,11.8007z"/> | |
<path d="M74.762,5.7269c0.3502,0,0.6508-0.1164,0.8997-0.348c0.25-0.2322,0.3738-0.5112,0.3738-0.8372 			c0-0.3259-0.1239-0.605-0.3738-0.8367c-0.2489-0.2322-0.5507-0.348-0.9051-0.348c-0.3512,0-0.6519,0.1159-0.903,0.348 			c-0.25,0.2317-0.376,0.5108-0.376,0.8367c0,0.326,0.126,0.605,0.376,0.8372C74.1048,5.6105,74.4076,5.7269,74.762,5.7269z"/> | |
<rect x="73.4594" y="6.479" width="2.5957" height="7.2213"/> | |
<path d="M82.5318,6.8529c-0.5581-0.3125-1.2294-0.4687-2.0127-0.4687c-0.7834,0-1.4546,0.1562-2.0127,0.4687 			c-0.5571,0.3114-0.9859,0.7467-1.2833,1.307c-0.2974,0.5592-0.4461,1.2089-0.4461,1.9481c0,0.7402,0.1487,1.39,0.4461,1.9491 			c0.2974,0.5592,0.7262,0.9956,1.2833,1.307c0.5581,0.3114,1.2294,0.4676,2.0127,0.4676c0.7833,0,1.4546-0.1562,2.0127-0.4676 			c0.5571-0.3114,0.9848-0.7478,1.2833-1.307c0.2974-0.5592,0.4461-1.2089,0.4461-1.9491c0-0.7392-0.1487-1.3889-0.4461-1.9481 			C83.5166,7.5996,83.0888,7.1643,82.5318,6.8529z M81.478,11.0627c-0.0873,0.2726-0.2112,0.4827-0.3717,0.6303 			c-0.1595,0.1476-0.3491,0.2209-0.5689,0.2209c-0.2317,0-0.431-0.0733-0.597-0.2209c-0.1659-0.1476-0.2931-0.3578-0.3803-0.6303 			c-0.0883-0.2726-0.1314-0.597-0.1314-0.973c0-0.3793,0.0431-0.7047,0.1314-0.9751c0.0873-0.2715,0.2144-0.4806,0.3803-0.6282 			c0.166-0.1476,0.3653-0.2209,0.597-0.2209c0.2198,0,0.4094,0.0733,0.5689,0.2209c0.1606,0.1476,0.2845,0.3567,0.3717,0.6282 			c0.0883,0.2705,0.1314,0.5958,0.1314,0.9751C81.6094,10.4657,81.5663,10.79,81.478,11.0627z"/> | |
<path d="M91.0752,6.7355c-0.3782-0.2338-0.8221-0.3513-1.3329-0.3513c-0.5301,0-0.9934,0.1304-1.39,0.3912 			c-0.3965,0.2596-0.6723,0.6184-0.8297,1.0764h-0.0754V6.479h-2.4632v7.2213h2.5957V9.6382 			c0.0022-0.2382,0.0463-0.4429,0.1314-0.6131c0.0841-0.1713,0.2058-0.3028,0.3642-0.3955c0.1584-0.0927,0.3438-0.139,0.5571-0.139 			c0.3265,0,0.5807,0.1024,0.7639,0.306c0.1832,0.2037,0.2737,0.4838,0.2705,0.8415v4.0621h2.5957V9.093 			c0.0032-0.5237-0.1002-0.9891-0.3082-1.3965C91.7454,7.2893,91.4534,6.9682,91.0752,6.7355z"/> | |
</g> | |
<path d="M99.4526,10.0358c-0.362-0.3178-0.9137-0.5452-1.6529-0.6798L96.3322,9.093c-0.2758-0.0506-0.4612-0.1207-0.5571-0.2112 		c-0.0959-0.0916-0.1411-0.1896-0.1379-0.2963c-0.0032-0.1509,0.0743-0.2672,0.2349-0.348 		c0.1595-0.0819,0.3502-0.1228,0.5732-0.1228c0.1723,0,0.3297,0.0291,0.473,0.0872c0.1422,0.0582,0.2586,0.1401,0.3501,0.2468 		c0.0905,0.1067,0.1423,0.2338,0.1552,0.3815h2.3877c-0.0313-0.765-0.348-1.3641-0.9514-1.7962 		c-0.6034-0.4332-1.4277-0.6498-2.4707-0.6498c-0.6863,0-1.28,0.0927-1.78,0.2759s-0.8836,0.4493-1.1519,0.7995 		c-0.2683,0.3491-0.4008,0.7747-0.3976,1.2757c-0.0032,0.5679,0.1788,1.0312,0.5452,1.3921 		c0.3674,0.3599,0.9191,0.6044,1.655,0.7338l1.279,0.2252c0.2823,0.0506,0.4902,0.1163,0.6239,0.1972 		c0.1325,0.0819,0.2004,0.1918,0.2036,0.3297c-0.0032,0.1497-0.0819,0.2661-0.237,0.348c-0.1551,0.0808-0.3524,0.1218-0.5905,0.1218 		c-0.2942,0-0.5377-0.0614-0.7305-0.1853c-0.1929-0.1239-0.3071-0.3006-0.3416-0.529h-2.5762 		c0.0722,0.7391,0.4192,1.335,1.0419,1.7865c0.6217,0.4515,1.4848,0.6767,2.5881,0.6767c0.668,0,1.2628-0.1024,1.7843-0.3071 		c0.5215-0.2058,0.9342-0.4967,1.237-0.8749c0.3017-0.3782,0.4547-0.8232,0.4579-1.3372 		C99.9968,10.7793,99.8147,10.3537,99.4526,10.0358z"/> | |
</g> | |
</svg> | |
""" | |
python_token_code = r""" | |
# ethpen.com | |
# 最后更新日期:2023 年 8 月 18 日 | |
# 在使用之前,敬请仔细阅读说明,感谢您的配合。 | |
# 请务必访问 ethpen.com 官方网站。您可以确保这里的代码无恶意,安全地复制。 | |
# 你只需要掌握一些 python 相关的基础。 | |
# 在使用过程中,请根据规定准确填写信息,以确保程序顺畅运行。 | |
# 我们建议您使用备用账号,并避免在账号中存放大额资金。 | |
# 若您对此代码存有疑虑,建议您利用如 ChetGPT、Bard 或 Claude 等知名 AI 平台进行查询,以判断是否含有恶意代码。 | |
# 如果你在使用的过程中发现 BUG 或者有什么想法和建议,欢迎与我联系。 | |
# 导入运行代码所需要的库 | |
from web3 import Web3 # 与以太坊交互的库,安装的命令是 pip install web3 | |
import hashlib # 用于数据哈希,安装的命令是 pip install hashlib | |
import requests # 用于发送网络请求,安装的命令是 pip install requests | |
import re # 用于正则表达式 | |
import time # 用于时间相关 | |
# ---------- 以下是基础配置 ---------- | |
# 填写你的多个 ETH 地址及私钥,建议填写新建的钱包,用英文逗号分隔(,),如下:地址,私钥。 | |
accounts_str = ''' | |
0xa62C8d0bB4F4530b9B68a14DaF8A949Cb01dB986,4de9b2812d51ba0ebbe7c990947b12544f7926a7aa1ebac084d42f6c7c8afbc1 | |
0x71D10cc20Abe0af4EC16170C502a4319DE0e40B4,377f4a19719337b63d8280f0a52769a42b534343de1eccab4f6d204d1ca04815 | |
0xBe169Ae4AD317B5632DE6Ae0e1EfeF0b22B1f91e,24fdf2ed0b820307582b06e1ed0b2047b4371e9d682e0b32455d310e08baafc5 | |
''' | |
# 需要题写的代币铭文内容,变动的部分文本如 id 请用 "@#" 代替,例如:'data:,{"p":"erc-20","op":"mint","tick":"eths","id":"@#","amt":"1000"}' | |
ethscription = 'data:,{"p":"erc-20","op":"mint","tick":"eths","id":"@#","amt":"1000"}' | |
# 设置代币铭文 id 的起始和结束范围 | |
min_id = 100 # 开始的整数 | |
max_id = 888 # 结束的整数 | |
# 决定是否在题写铭文之前检查该铭文有没有被题写过,如果需要检查就填写 Ture 如果不需要就填 False | |
check = False | |
# 每次交易成功后暂停 N 秒,0 为不暂停 | |
sleep_sec = 0 | |
# 这里配置 Ethereum PRC URL,如果你没有,请到 infura.io 或者 alchemy.com 申请一个免费的 API | |
w3 = Web3(Web3.HTTPProvider('https://sepolia.infura.io/v3/eab7f935b9af45e1a54f7d7ed06c5206')) | |
# 连接的网络 ID。比如说,1 代表 Mainnet,5 代表 Goerli 测试网络,11155111 代表 Sepolia 测试网络,如果你不放心,可以先用测试网试试。 | |
chain_id = 11155111 | |
# ---------- 以上是基础配置 ---------- | |
# 检查 ETH 地址是否有效 | |
def is_valid_eth_address(address): | |
if re.match("^0x[0-9a-fA-F]{40}$", address): | |
return True | |
return False | |
# 检查 Ethereum 私钥是否有效 | |
def is_valid_eth_private_key(private_key): | |
if re.match("^[0-9a-fA-F]{64}$", private_key): | |
return True | |
return False | |
# 验证输入的铭文文本是否含有空格和换行符,而且字母全部为小写 | |
def validate_input(data_str): | |
if re.search(r'[A-Z\s\n]', data_str): # 查找大写字母、空格或换行符 | |
return False | |
return True | |
# 把文字转换成 16 进制 | |
def text_to_hex(text): | |
return ''.join(format(ord(char), '02x') for char in text) | |
# 使用sha256算法计算哈希 | |
def sha256(input_string): | |
sha256 = hashlib.sha256() | |
sha256.update(input_string.encode('utf-8')) | |
return sha256.hexdigest() | |
# 使用 Ethscriptions API(主网)检查某个铭文是否已题写 | |
def check_content_exists(sha): | |
# 定义请求的网址 | |
endpoint = f"/ethscriptions/exists/{sha}" | |
response = requests.get('https://mainnet-api.ethscriptions.com/api' + endpoint) | |
# 如果返回状态码是200,说明请求成功,然后返回结果(Ture or False) | |
if response.status_code == 200: | |
return response.json()['result'] | |
# 发送自己到自己 0ETH 的交易 | |
def send_transaction(w3, account_address, private_key, chain_id, gas_price, input_data, current_nonce): | |
# 设置交易的相关信息 | |
tx = { | |
'chainId': chain_id, # 网络 ID | |
'gas': 25000, # 如果交易 gas 过低,可适当调高 | |
'gasPrice': gas_price, # gas 的价格 | |
'nonce': current_nonce, # 账户的交易数 | |
'to': account_address, # 接收地址为自己 | |
'value': 0, # 金额为 0ETH | |
'data': text_to_hex(input_data), # 铭文内容 | |
} | |
# 用私钥签名这个交易 | |
signed_tx = w3.eth.account.sign_transaction(tx, private_key) | |
# 发送签名后的交易并获取交易哈希 | |
tx_hash = w3.eth.send_raw_transaction(signed_tx.rawTransaction) | |
# 打印结果信息 | |
print(f'{account_address} | {input_data} | Transaction Hash: {tx_hash.hex()}') | |
# 初始化当前账户索引为 0 | |
current_account_index = 0 | |
# 创建账户列表 | |
accounts = [] | |
# 使用字典来跟踪每个地址的nonce | |
nonces = {} | |
if accounts_str: # 如果账户列表有内容 | |
for line in accounts_str.strip().split('\n'): # 先去掉首尾的空白,然后根据换行符划分账户 | |
if ',' in line: # 检查是否包含逗号 | |
address, key = line.split(',') # 分开地址和私钥 | |
if is_valid_eth_address(address) and is_valid_eth_private_key(key): # 验证地址和私钥 | |
current_nonce = w3.eth.get_transaction_count(address) # 获取地址的 nonce | |
nonces[address] = current_nonce # 记录地址的 nonce | |
accounts.append((address.strip(), key.strip())) # 保存地址和私钥还有 nonce | |
else: | |
print(f"地址 {address} 或私钥 {key} 无效,请检查!") | |
exit() | |
else: | |
print(f"输入格式错误,请确保每行包含一个地址和一个私钥,并使用英文逗号分隔(,)。错误行:**{line}**") | |
exit() | |
# 判断铭文文本里是否包含空格、换行符,而且所有的字母都必须为小写。 | |
if not validate_input(ethscription): | |
print("请注意:通常代币铭文文本里不能包含空格、换行符,而且所有的字母都必须为小写。") | |
# 检查是否留空 | |
if not accounts or not ethscription: | |
print('请正确谨慎地填写内容,每一项都不应留空。') | |
exit() | |
else: | |
print('看起来你输入的内容均无没有问题!') | |
# 认真检查铭文内容,如果发现错误,输入 1 结束 | |
print(f'铭文文本:\033[44m{ethscription}\033[m,题写 id 范围为:{min_id} - {max_id}。') | |
if input('请预览铭文,输入任意内容继续,输入 1 退出程序:') == '1': | |
exit() | |
print(f'开始任务,需要题写的铭文总量为:{max_id - min_id + 1}') | |
# 对代币铭文 id 进行循环 | |
for the_id in range(min_id, max_id + 1): | |
# 使用当前账户发送交易 | |
address, key = accounts[current_account_index] | |
# 得到完整的铭文文本 | |
input_data = ethscription.replace('@#', str(the_id)) | |
# 获取 gas | |
gas_price = w3.eth.gas_price | |
# 根据是否检查的开关进行 | |
if check: | |
# 这里是开了检查后请求 Ethscriptions API | |
if check_content_exists(sha256(input_data)): | |
# 返回数据为 Ture,说明该铭文已经被题写,打印信息 | |
print(f'{input_data} 已经被题写!') | |
else: | |
# 返回数据为 False,说明该铭文还没被题写,发送交易 | |
# 使用 current_nonce 发送交易 | |
send_transaction(w3, address, key, chain_id, gas_price, input_data, nonces[address]) | |
# 交易成功后,手动增加 nonce 值 | |
nonces[address] += 1 | |
else: | |
# 这里是未开检查后直接发送交易 | |
# 使用 current_nonce 发送交易 | |
send_transaction(w3, address, key, chain_id, gas_price, input_data, nonces[address]) | |
# 交易成功后,手动增加 nonce 值 | |
nonces[address] += 1 | |
# 更新当前账户索引,确保索引始终在账户列表的范围内 | |
current_account_index = (current_account_index + 1) % len(accounts) | |
# 暂停 sleep_sec 秒 | |
time.sleep(sleep_sec) | |
print(f'所有任务已经完成。') | |
""" | |
python_name_code = r""" | |
# ethpen.com | |
# 最后更新日期:2023 年 8 月 18 日 | |
# 在使用之前,敬请仔细阅读说明,感谢您的配合。 | |
# 请务必访问 ethpen.com 官方网站。您可以确保这里的代码无恶意,安全地复制。 | |
# 你只需要掌握一些 python 相关的基础。 | |
# 在使用过程中,请根据规定准确填写信息,以确保程序顺畅运行。 | |
# 我们建议您使用备用账号,并避免在账号中存放大额资金。 | |
# 若您对此代码存有疑虑,建议您利用如 ChetGPT、Bard 或 Claude 等知名 AI 平台进行查询,以判断是否含有恶意代码。 | |
# 如果你在使用的过程中发现 BUG 或者有什么想法和建议,欢迎与我联系。 | |
# 导入运行代码所需要的库 | |
from web3 import Web3 # 与以太坊交互的库,安装的命令是 pip install web3 | |
import hashlib # 用于数据哈希,安装的命令是 pip install hashlib | |
import requests # 用于发送网络请求,安装的命令是 pip install requests | |
import re # 用于正则表达式 | |
import time # 用于时间相关 | |
# ---------- 以下是基础配置 ---------- | |
# 填写你的多个 ETH 地址及私钥,建议填写新建的钱包,用英文逗号分隔(,),如下:地址,私钥。 | |
accounts_str = ''' | |
0xa62C8d0bB4F4530b9B68a14DaF8A949Cb01dB986,4de9b2812d51ba0ebbe7c990947b12544f7926a7aa1ebac084d42f6c7c8afbc1 | |
0x71D10cc20Abe0af4EC16170C502a4319DE0e40B4,377f4a19719337b63d8280f0a52769a42b534343de1eccab4f6d204d1ca04815 | |
0xBe169Ae4AD317B5632DE6Ae0e1EfeF0b22B1f91e,24fdf2ed0b820307582b06e1ed0b2047b4371e9d682e0b32455d310e08baafc5 | |
''' | |
# 需要题写的铭文内容,在三个单引号内输入多个域名铭文,可以用空格、换行符、英文逗号(,)分开,不要带 data:, 开头 | |
# 不要带 data:, 开头 | |
# 不要带 data:, 开头 | |
ethscription = ''' | |
123 | |
12313131 | |
2131 21313 | |
12313 32313 | |
423213v ethpen.com | |
''' | |
# 你希望添加的后缀 | |
suffix = '.eths' | |
# 以空格、换行符、英文逗号分隔文本,并加上后缀 | |
ethscription_list = [item.strip() + suffix for item in re.split(r'[\s,]+', ethscription) if item] | |
# 决定是否在题写铭文之前检查该铭文有没有被题写过,如果需要检查就填写 Ture 如果不需要就填 False | |
check = False | |
# 每次交易成功后暂停 N 秒,0 为不暂停 | |
sleep_sec = 0 | |
# 这里配置 Ethereum PRC URL,如果你没有,请到 infura.io 或者 alchemy.com 申请一个免费的 API | |
w3 = Web3(Web3.HTTPProvider('https://sepolia.infura.io/v3/eab7f935b9af45e1a54f7d7ed06c5206')) | |
# 连接的网络 ID。比如说,1 代表 Mainnet,5 代表 Goerli 测试网络,11155111 代表 Sepolia 测试网络,如果你不放心,可以先用测试网试试。 | |
chain_id = 11155111 | |
# ---------- 以上是基础配置 ---------- | |
# 检查 ETH 地址是否有效 | |
def is_valid_eth_address(address): | |
if re.match("^0x[0-9a-fA-F]{40}$", address): | |
return True | |
return False | |
# 检查 Ethereum 私钥是否有效 | |
def is_valid_eth_private_key(private_key): | |
if re.match("^[0-9a-fA-F]{64}$", private_key): | |
return True | |
return False | |
# 验证输入的铭文文本是否含有空格和换行符,而且字母全部为小写 | |
def validate_input(data_str): | |
if re.search(r'[A-Z\s\n]', data_str): # 查找大写字母、空格或换行符 | |
return False | |
return True | |
# 把文字转换成 16 进制 | |
def text_to_hex(text): | |
return ''.join(format(ord(char), '02x') for char in text) | |
# 使用sha256算法计算哈希 | |
def sha256(input_string): | |
sha256 = hashlib.sha256() | |
sha256.update(input_string.encode('utf-8')) | |
return sha256.hexdigest() | |
# 使用 Ethscriptions API(主网)检查某个铭文是否已存在 | |
def check_content_exists(sha): | |
# 定义请求的网址 | |
endpoint = f"/ethscriptions/exists/{sha}" | |
response = requests.get('https://mainnet-api.ethscriptions.com/api' + endpoint) | |
# 如果返回状态码是200,说明请求成功,然后返回结果(Ture or False) | |
if response.status_code == 200: | |
return response.json()['result'] | |
# 发送自己到自己 0ETH 的交易 | |
def send_transaction(w3, account_address, private_key, chain_id, gas_price, input_data, current_nonce): | |
# 设置交易的相关信息 | |
tx = { | |
'chainId': chain_id, # 网络 ID | |
'gas': 25000, # 如果交易 gas 过低,可适当调高 | |
'gasPrice': gas_price, # gas 的价格 | |
'nonce': current_nonce, # 账户的交易数 | |
'to': account_address, # 接收地址为自己 | |
'value': 0, # 金额为 0ETH | |
'data': text_to_hex(input_data), # 铭文内容 | |
} | |
# 用私钥签名这个交易 | |
signed_tx = w3.eth.account.sign_transaction(tx, private_key) | |
# 发送签名后的交易并获取交易哈希 | |
tx_hash = w3.eth.send_raw_transaction(signed_tx.rawTransaction) | |
# 打印结果信息 | |
print(f'{account_address} | {input_data} | Transaction Hash: {tx_hash.hex()}') | |
# 初始化当前账户索引为 0 | |
current_account_index = 0 | |
# 创建账户列表 | |
accounts = [] | |
# 使用字典来跟踪每个地址的nonce | |
nonces = {} | |
if accounts_str: # 如果账户列表有内容 | |
for line in accounts_str.strip().split('\n'): # 先去掉首尾的空白,然后根据换行符划分账户 | |
if ',' in line: # 检查是否包含逗号 | |
address, key = line.split(',') # 分开地址和私钥 | |
if is_valid_eth_address(address) and is_valid_eth_private_key(key): # 验证地址和私钥 | |
current_nonce = w3.eth.get_transaction_count(address) # 获取地址的 nonce | |
nonces[address] = current_nonce # 记录地址的 nonce | |
accounts.append((address.strip(), key.strip())) # 保存地址和私钥还有 nonce | |
else: | |
print(f"地址 {address} 或私钥 {key} 无效,请检查!") | |
exit() | |
else: | |
print(f"输入格式错误,请确保每行包含一个地址和一个私钥,并使用英文逗号分隔(,)。错误行:**{line}**") | |
exit() | |
# 判断铭文文本里是否包含空格、换行符,而且所有的字母都必须为小写。 | |
if not validate_input(ethscription): | |
print("请注意:通常代币铭文文本里不能包含空格、换行符,而且所有的字母都必须为小写。") | |
# 检查是否留空 | |
if not accounts or not ethscription: | |
print('请正确谨慎地填写内容,每一项都不应留空。') | |
exit() | |
else: | |
print('看起来你输入的内容均无没有问题!') | |
# 认真检查铭文内容,如果发现错误,输入 1 结束 | |
for i in ethscription_list: | |
print(f'\033[44m{i}\033[m') | |
if input('请预览铭文,输入任意内容继续,输入 1 退出程序:') == '1': | |
exit() | |
print(f'开始任务,需要题写的铭文总量为:{len(ethscription_list)}') | |
# 对代币铭文 id 进行循环 | |
for name_str in ethscription_list: | |
# 使用当前账户发送交易 | |
address, key = accounts[current_account_index] | |
# 得到完整的铭文文本 | |
if not name_str.startswith('data:,'): | |
input_data = f'data:,{name_str}' | |
else: | |
input_data = name_str | |
# 获取 gas | |
gas_price = w3.eth.gas_price | |
# 根据是否检查的开关进行 | |
if check: | |
# 这里是开了检查后请求 Ethscriptions API | |
if check_content_exists(sha256(input_data)): | |
# 返回数据为 Ture,说明该铭文已经被题写,打印信息 | |
print(f'{input_data} 已经被题写!') | |
else: | |
# 返回数据为 False,说明该铭文还没被题写,发送交易 | |
# 使用 current_nonce 发送交易 | |
send_transaction(w3, address, key, chain_id, gas_price, input_data, nonces[address]) | |
# 交易成功后,手动增加 nonce 值 | |
nonces[address] += 1 | |
else: | |
# 这里是未开检查后直接发送交易 | |
# 使用 current_nonce 发送交易 | |
send_transaction(w3, address, key, chain_id, gas_price, input_data, nonces[address]) | |
# 交易成功后,手动增加 nonce 值 | |
nonces[address] += 1 | |
# 更新当前账户索引,确保索引始终在账户列表的范围内 | |
current_account_index = (current_account_index + 1) % len(accounts) | |
# 暂停 sleep_sec 秒 | |
time.sleep(sleep_sec) | |
print(f'所有任务已经完成。') | |
""" | |
hf_token_code = r""" | |
# ethpen.com | |
# 最后更新日期:2023 年 8 月 18 日 | |
# 在使用之前,敬请仔细阅读说明,感谢您的配合。 | |
# 请务必访问 ethpen.com 官方网站。您可以确保这里的代码无恶意,安全地复制。 | |
# 你只需要拥有一个 HuggingFace.co 账户。 | |
# 在使用过程中,请根据规定准确填写信息,以确保程序顺畅运行。 | |
# 我们建议您使用备用账号,并避免在账号中存放大额资金。 | |
# 若您对此代码存有疑虑,建议您利用如 ChetGPT、Bard 或 Claude 等知名 AI 平台进行查询,以判断是否含有恶意代码。 | |
# 请查看我们的例子 https://ethscriptions-name.hf.space。 | |
# 导入运行代码所需要的库 | |
import streamlit as st # streamlit app | |
from web3 import Web3 # 与以太坊交互的库 | |
import hashlib # 用于数据哈希 | |
import requests # 用于发送网络请求 | |
import re # 用于正则表达式 | |
import time # 用于时间相关 | |
# 检查 ETH 地址是否有效 | |
def is_valid_eth_address(address): | |
if re.match("^0x[0-9a-fA-F]{40}$", address): | |
return True | |
return False | |
# 检查 Ethereum 私钥是否有效 | |
def is_valid_eth_private_key(private_key): | |
if re.match("^[0-9a-fA-F]{64}$", private_key): | |
return True | |
return False | |
# 验证输入的铭文文本是否含有空格和换行符,而且字母全部为小写 | |
def validate_input(data_str): | |
if re.search(r'[A-Z\s\n]', data_str): # 查找大写字母、空格或换行符 | |
return False | |
return True | |
# 把文字转换成 16 进制 | |
def text_to_hex(text): | |
return ''.join(format(ord(char), '02x') for char in text) | |
# 使用sha256算法计算哈希 | |
def sha256(input_string): | |
sha256 = hashlib.sha256() | |
sha256.update(input_string.encode('utf-8')) | |
return sha256.hexdigest() | |
# 使用 Ethscriptions API(主网)检查某个铭文是否已题写 | |
def check_content_exists(sha): | |
# 定义请求的网址 | |
endpoint = f"/ethscriptions/exists/{sha}" | |
response = requests.get('https://mainnet-api.ethscriptions.com/api' + endpoint) | |
# 如果返回状态码是200,说明请求成功,然后返回结果(Ture or False) | |
if response.status_code == 200: | |
return response.json()['result'] | |
# 发送自己到自己 0ETH 的交易 | |
def send_transaction(w3, account_address, private_key, chain_id, gas_price, input_data, current_nonce): | |
# 设置交易的相关信息 | |
tx = { | |
'chainId': chain_id, # 网络 ID | |
'gas': 25000, # 如果交易 gas 过低,可适当调高 | |
'gasPrice': gas_price, # gas 的价格 | |
'nonce': current_nonce, | |
'to': account_address, # 接收地址为自己 | |
'value': 0, # 金额为 0ETH | |
'data': text_to_hex(input_data), # 铭文内容 | |
} | |
# 用私钥签名这个交易 | |
signed_tx = w3.eth.account.sign_transaction(tx, private_key) | |
# 发送签名后的交易并获取交易哈希 | |
tx_hash = w3.eth.send_raw_transaction(signed_tx.rawTransaction) | |
# 打印结果信息 | |
st.toast(f'{input_data}', icon='✅') | |
# 返回铭文还有交易哈希 | |
return input_data, tx_hash.hex() | |
# 网页前端显示 | |
# 网页标题 | |
st.markdown('# [ethpen.com](https://ethpen.com) 代币铭文批量题写') | |
# 提醒 | |
st.info('''在使用之前,敬请仔细阅读说明,感谢您的配合。 | |
- 请务必访问 **[ethpen.com](https://ethpen.com)** 官方网站。您可以确保这里的代码无恶意,安全地复制。 | |
- 在使用过程中,请根据规定准确填写信息,以确保程序顺畅运行。 | |
- 我们建议您使用备用账号,并避免在账号中存放大额资金。 | |
- 若您对此代码存有疑虑,建议您利用如 [ChetGPT](https://chat.openai.com/)、[Bard](https://bard.google.com/) 或 [Claude](https://claude.ai/) 等知名 AI 平台进行查询,以判断是否含有恶意代码。 | |
''') | |
# 连接的网络 ID。比如说,1 代表 Mainnet,5 代表 Goerli 测试网络,11155111 代表 Sepolia 测试网络,如果你不放心,可以先用测试网试试。 | |
net_options = { | |
'1': 'Mainnet', | |
'5': 'Goerli', | |
'11155111': 'Sepolia' | |
} | |
selected_option = st.selectbox( | |
'**网络 ID**', | |
list(net_options.keys()), | |
format_func=lambda x: f"{x} ({net_options[x]})" | |
) | |
chain_id = int(selected_option) | |
# 这里配置 Ethereum PRC URL,如果你没有,请到 infura.io 或者 alchemy.com 申请一个免费的 API | |
token_eth_prc_url = st.text_input( | |
f'**Ethereum PRC 链接**:选填,你可以去 [infura.io](https://app.infura.io/) 或者 [alchemy.com](https://alchemy.com/) 免费申请一个', | |
f'https://{net_options[str(chain_id)]}.infura.io/v3/eab7f935b9af45e1a54f7d7ed06c5206') | |
w3 = Web3(Web3.HTTPProvider(f'{token_eth_prc_url}')) | |
# 初始化当前账户索引为 0 | |
current_account_index = 0 | |
# 收集和显示所有交易的结果 | |
transaction_results = [] | |
# 创建账户列表 | |
accounts = [] | |
# 使用字典来跟踪每个地址的nonce | |
nonces = {} | |
# 启用多账户操作 | |
if st.checkbox(f'启用**多账户**操作'): | |
# 多账户的文本框 | |
account_list = st.text_area(f'输入多个 **ETH 地址及其对应的私钥**,用英文逗号分隔(,),如下:地址,私钥') | |
if account_list: # 如果账户列表有内容 | |
for line in account_list.split('\n'): # 根据换行符划分账户 | |
if ',' in line: # 检查是否包含逗号 | |
address, key = line.split(',') # 分开地址和私钥 | |
if is_valid_eth_address(address) and is_valid_eth_private_key(key): # 验证地址和私钥 | |
current_nonce = w3.eth.get_transaction_count(address) # 获取地址的 nonce | |
nonces[address] = current_nonce # 记录地址的 nonce | |
accounts.append((address.strip(), key.strip())) # 保存地址和私钥还有 nonce | |
else: | |
st.error(f"地址 {address} 或私钥 {key} 无效,请检查!") | |
st.stop() | |
else: | |
st.error(f"输入格式错误,请确保每行包含一个地址和一个私钥,并使用英文逗号分隔(,)。错误行:**{line}**") | |
st.stop() | |
else: | |
account_address = st.text_input('填写你的 **ETH 地址**:') | |
private_key = st.text_input('填写你的 **ETH 地址对应的私钥**:', type="password") | |
if account_address and private_key: # 如果地址和私钥有内容 | |
if is_valid_eth_address(account_address) and is_valid_eth_private_key(private_key): # 验证地址和私钥 | |
current_nonce = w3.eth.get_transaction_count(account_address) # 获取地址的 nonce | |
nonces[account_address] = current_nonce # 记录地址的 nonce | |
accounts.append((account_address.strip(), private_key.strip())) # 保存地址和私钥还有 nonce | |
else: | |
st.error("地址或私钥无效,请检查!") | |
st.stop() | |
# 配置铭文文本 | |
token_protocol = st.text_input('填写需要题写代币铭文协议 **Protocol(p)**:', 'erc-20') | |
token_operation = st.text_input('填写需要题写代币铭文操作 **Operation(op)**:', 'mint') | |
token_ticker = st.text_input('填写需要题写代币铭文简称 **Ticker(tick)**:') | |
token_min_id = st.number_input('填写需要题写代币铭文范围的**最小 ID(id)**:', min_value=1, value=1, step=1) | |
token_max_id = st.number_input('填写需要题写代币铭文范围的**最大 ID(id)**:', value=21000, step=1) | |
token_amount = st.number_input('填写需要题写代币铭文数量 **Amount(amt)**:', min_value=1, value=1000, step=1) | |
st.markdown('###### 预览你需要题写的代币铭文:') | |
st.code( | |
f'data:,{{"p":"{token_protocol}","op":"{token_operation}","tick":"{token_ticker}","id":"{token_min_id}","amt":"{token_amount}"}}', | |
language="json", line_numbers=False) | |
# 判断铭文文本里是否包含空格、换行符,而且所有的字母都必须为小写。 | |
if not validate_input( | |
f'data:,{{"p":"{token_protocol}","op":"{token_operation}","tick":"{token_ticker}","id":"{token_min_id}","amt":"{token_amount}"}}'): | |
st.warning("**请注意**:通常代币铭文文本里不能包含空格、换行符,而且所有的字母都必须为小写。") | |
# 题写铭文之前检查该铭文有没有被题写 | |
if st.checkbox(f'题写铭文之前**检查该铭文有没有被题写**'): | |
token_check = True | |
else: | |
token_check = False | |
# 每次交易成功后暂停 3 秒 | |
if st.checkbox(f'每次交易完成后暂停 3 秒'): | |
sleep_3s = True | |
else: | |
sleep_3s = False | |
# 点击发送交易开始 | |
if st.button(f'开始**发送交易**'): | |
if not accounts or not token_protocol or not token_operation or not token_ticker: # 检查是否留空 | |
st.error(f'请正确谨慎地填写内容,每一项都**不应留空**。') | |
st.stop() | |
else: | |
st.toast('看起来你输入的内容均无没有问题!', icon='🥳') | |
st.toast(f'开始任务,需要题写的铭文总量为:{token_max_id - token_min_id + 1}', icon='😎') | |
# 对代币铭文 id 进行循环 | |
for the_id in range(token_min_id, token_max_id + 1): | |
# 使用当前账户发送交易,获取当前账户的 nonce | |
address, key = accounts[current_account_index] | |
# 得到完整的铭文文本 | |
input_data = f'data:,{{"p":"{token_protocol}","op":"{token_operation}","tick":"{token_ticker}","id":"{the_id}","amt":"{token_amount}"}}' | |
# 获取 gas | |
gas_price = w3.eth.gas_price | |
# 根据是否检查的开关进行 | |
if token_check: | |
# 这里是开了检查后请求 Ethscriptions API | |
if check_content_exists(sha256(input_data)): | |
# 返回数据为 Ture,说明该铭文已经被题写,打印信息 | |
st.toast(f'{input_data} 已经被题写!', icon='☹️') | |
else: | |
# 返回数据为 False,说明该铭文还没被题写,发送交易 | |
# 使用 current_nonce 发送交易 | |
data, tx_hash = send_transaction(w3, address, key, chain_id, gas_price, input_data, nonces[address]) | |
# 记录最后输出的结果 | |
transaction_results.append(f"{address} | {data} | Transaction Hash: {tx_hash}") | |
# 交易成功后,手动增加 nonce 值 | |
nonces[address] += 1 | |
else: | |
# 这里是未开检查后直接发送交易 | |
# 使用 current_nonce 发送交易 | |
data, tx_hash = send_transaction(w3, address, key, chain_id, gas_price, input_data, nonces[address]) | |
# 记录最后输出的结果 | |
transaction_results.append(f"{address} | {data} | Transaction Hash: {tx_hash}") | |
# 交易成功后,手动增加 nonce 值 | |
nonces[address] += 1 | |
# 更新当前账户索引,确保索引始终在账户列表的范围内 | |
current_account_index = (current_account_index + 1) % len(accounts) | |
# 暂停 3 秒 | |
if sleep_3s: | |
time.sleep(3) # 暂停三秒 | |
st.toast(f'所有任务已经完成。', icon='🎉') | |
# 庆祝动画 | |
st.balloons() | |
# 显示所有交易的结果 | |
st.code('\n'.join(transaction_results)) | |
""" | |
hf_name_code = r""" | |
# ethpen.com | |
# 最后更新日期:2023 年 8 月 18 日 | |
# 在使用之前,敬请仔细阅读说明,感谢您的配合。 | |
# 请务必访问 ethpen.com 官方网站。您可以确保这里的代码无恶意,安全地复制。 | |
# 你只需要拥有一个 HuggingFace.co 账户。 | |
# 在使用过程中,请根据规定准确填写信息,以确保程序顺畅运行。 | |
# 我们建议您使用备用账号,并避免在账号中存放大额资金。 | |
# 若您对此代码存有疑虑,建议您利用如 ChetGPT、Bard 或 Claude 等知名 AI 平台进行查询,以判断是否含有恶意代码。 | |
# 请查看我们的例子 https://ethscriptions-name.hf.space。 | |
# 导入运行代码所需要的库 | |
import streamlit as st # streamlit app | |
from web3 import Web3 # 与以太坊交互的库 | |
import hashlib # 用于数据哈希 | |
import requests # 用于发送网络请求 | |
import re # 用于正则表达式 | |
import time # 用于时间相关 | |
# 检查 ETH 地址是否有效 | |
def is_valid_eth_address(address): | |
if re.match("^0x[0-9a-fA-F]{40}$", address): | |
return True | |
return False | |
# 检查 Ethereum 私钥是否有效 | |
def is_valid_eth_private_key(private_key): | |
if re.match("^[0-9a-fA-F]{64}$", private_key): | |
return True | |
return False | |
# 验证输入的铭文文本是否含有空格和换行符,而且字母全部为小写 | |
def validate_input(data_str): | |
if re.search(r'[A-Z\s\n]', data_str): # 查找大写字母、空格或换行符 | |
return False | |
return True | |
# 分隔文本函数 | |
def split_and_append(ethscriptions_str, name_selected_option): | |
separators = [' ', '\n', ','] | |
split_texts = [ethscriptions_str] # 初始时只有一个完整文本 | |
for sep in separators: | |
pieces = [] | |
for text in split_texts: | |
pieces.extend(text.split(sep)) | |
split_texts = pieces | |
# 移除空字符串 | |
split_texts = [text.strip() + name_selected_option for text in split_texts if text.strip() != ''] | |
return split_texts | |
# 把文字转换成 16 进制 | |
def text_to_hex(text): | |
return ''.join(format(ord(char), '02x') for char in text) | |
# 使用sha256算法计算哈希 | |
def sha256(input_string): | |
sha256 = hashlib.sha256() | |
sha256.update(input_string.encode('utf-8')) | |
return sha256.hexdigest() | |
# 使用 Ethscriptions API(主网)检查某个铭文是否已题写 | |
def check_content_exists(sha): | |
# 定义请求的网址 | |
endpoint = f"/ethscriptions/exists/{sha}" | |
response = requests.get('https://mainnet-api.ethscriptions.com/api' + endpoint) | |
# 如果返回状态码是200,说明请求成功,然后返回结果(Ture or False) | |
if response.status_code == 200: | |
return response.json()['result'] | |
# 发送自己到自己 0ETH 的交易 | |
def send_transaction(w3, account_address, private_key, chain_id, gas_price, input_data, current_nonce): | |
# 设置交易的相关信息 | |
tx = { | |
'chainId': chain_id, # 网络 ID | |
'gas': 25000, # 如果交易 gas 过低,可适当调高 | |
'gasPrice': gas_price, # gas 的价格 | |
'nonce': current_nonce, | |
'to': account_address, # 接收地址为自己 | |
'value': 0, # 金额为 0ETH | |
'data': text_to_hex(input_data), # 铭文内容 | |
} | |
# 用私钥签名这个交易 | |
signed_tx = w3.eth.account.sign_transaction(tx, private_key) | |
# 发送签名后的交易并获取交易哈希 | |
tx_hash = w3.eth.send_raw_transaction(signed_tx.rawTransaction) | |
# 打印结果信息 | |
st.toast(f'{input_data}', icon='✅') | |
# 返回铭文还有交易哈希 | |
return input_data, tx_hash.hex() | |
# 网页前端显示 | |
# 网页标题 | |
st.markdown('# [ethpen.com](https://ethpen.com) 域名铭文批量题写') | |
# 提醒 | |
st.info('''在使用之前,敬请仔细阅读说明,感谢您的配合。 | |
- 请务必访问 **[ethpen.com](https://ethpen.com)** 官方网站。您可以确保这里的代码无恶意,安全地复制。 | |
- 在使用过程中,请根据规定准确填写信息,以确保程序顺畅运行。 | |
- 我们建议您使用备用账号,并避免在账号中存放大额资金。 | |
- 若您对此代码存有疑虑,建议您利用如 [ChetGPT](https://chat.openai.com/)、[Bard](https://bard.google.com/) 或 [Claude](https://claude.ai/) 等知名 AI 平台进行查询,以判断是否含有恶意代码。 | |
''') | |
# 连接的网络 ID。比如说,1 代表主网络,5 代表 Goerli 测试网络,11155111 代表 Sepolia 测试网络,如果你不放心,可以先用测试网试试。 | |
net_options = { | |
'1': 'Mainnet', | |
'5': 'Goerli', | |
'11155111': 'Sepolia' | |
} | |
selected_option = st.selectbox( | |
'**网络 ID**', | |
list(net_options.keys()), | |
format_func=lambda x: f"{x} ({net_options[x]})" | |
) | |
chain_id = int(selected_option) | |
# 这里配置 Ethereum PRC URL,如果你没有,请到 infura.io 或者 alchemy.com 申请一个免费的 API | |
token_eth_prc_url = st.text_input( | |
f'**Ethereum PRC 链接**:选填,你可以去 [infura.io](https://app.infura.io/) 或者 [alchemy.com](https://alchemy.com/) 免费申请一个', | |
f'https://{net_options[str(chain_id)]}.infura.io/v3/eab7f935b9af45e1a54f7d7ed06c5206') | |
w3 = Web3(Web3.HTTPProvider(f'{token_eth_prc_url}')) | |
# 初始化当前账户索引为 0 | |
current_account_index = 0 | |
# 收集和显示所有交易的结果 | |
transaction_results = [] | |
# 创建账户列表 | |
accounts = [] | |
# 使用字典来跟踪每个地址的nonce | |
nonces = {} | |
# 启用多账户操作 | |
if st.checkbox(f'启用**多账户**操作'): | |
# 多账户的文本框 | |
account_list = st.text_area(f'输入多个 **ETH 地址及其对应的私钥**,用英文逗号分隔(,),如下:地址,私钥') | |
if account_list: # 如果账户列表有内容 | |
for line in account_list.split('\n'): # 根据换行符划分账户 | |
if ',' in line: # 检查是否包含逗号 | |
address, key = line.split(',') # 分开地址和私钥 | |
if is_valid_eth_address(address) and is_valid_eth_private_key(key): # 验证地址和私钥 | |
current_nonce = w3.eth.get_transaction_count(address) # 获取地址的 nonce | |
nonces[address] = current_nonce # 记录地址的 nonce | |
accounts.append((address.strip(), key.strip())) # 保存地址和私钥还有 nonce | |
else: | |
st.error(f"地址 {address} 或私钥 {key} 无效,请检查!") | |
st.stop() | |
else: | |
st.error(f"输入格式错误,请确保每行包含一个地址和一个私钥,并使用英文逗号分隔(,)。错误行:**{line}**") | |
st.stop() | |
else: | |
account_address = st.text_input('填写你的 **ETH 地址**:') | |
private_key = st.text_input('填写你的 **ETH 地址对应的私钥**:', type="password") | |
if account_address and private_key: # 如果地址和私钥有内容 | |
if is_valid_eth_address(account_address) and is_valid_eth_private_key(private_key): # 验证地址和私钥 | |
current_nonce = w3.eth.get_transaction_count(account_address) # 获取地址的 nonce | |
nonces[account_address] = current_nonce # 记录地址的 nonce | |
accounts.append((account_address.strip(), private_key.strip())) # 保存地址和私钥还有 nonce | |
else: | |
st.error("地址或私钥无效,请检查!") | |
st.stop() | |
# 配置铭文文本 | |
ethscriptions_str = st.text_area(f'输入**多个域名铭文或其他**,可以用空格、换行符、英文逗号(,)分开,不要带 data:, 前缀,不要带域名后缀') | |
name_options = ["自定义", ".eth", ".eths", ".tree", ".honk", ".etch"] | |
name_selected_option = st.selectbox(f'选择**域名后缀**', name_options) | |
if name_selected_option == '自定义': | |
name_selected_option = st.text_input('输入**自定义的域名**:') | |
# 以空格、换行符、英文逗号分隔文本并加上后缀 | |
ethscription_list = split_and_append(ethscriptions_str, name_selected_option) | |
# 判断铭文文本里是否包含空格、换行符,而且所有的字母都必须为小写。 | |
if not validate_input(''.join(ethscription_list)): | |
st.warning("**请注意**:通常代币铭文文本里不能包含空格、换行符,而且所有的字母都必须为小写。") | |
# 题写铭文之前检查该铭文有没有被题写 | |
if st.checkbox(f'题写铭文之前**检查该铭文有没有被题写**'): | |
token_check = True | |
else: | |
token_check = False | |
# 每次交易成功后暂停 3 秒 | |
if st.checkbox(f'每次交易完成后暂停 3 秒'): | |
sleep_3s = True | |
else: | |
sleep_3s = False | |
# 点击发送交易开始 | |
if st.button(f'开始**发送交易**'): | |
if not accounts or not ethscriptions_str or not name_selected_option: # 检查是否留空 | |
st.error(f'请正确谨慎地填写内容,每一项都**不应留空**。') | |
st.stop() | |
else: | |
st.toast('看起来你输入的内容均无没有问题!', icon='🥳') | |
st.toast(f'开始任务,需要题写的铭文总量为:{len(ethscription_list)}', icon='😎') | |
# 对代币铭文 id 进行循环 | |
for name_str in ethscription_list: | |
# 使用当前账户发送交易,获取当前账户的 nonce | |
address, key = accounts[current_account_index] | |
# 获取 gas | |
gas_price = w3.eth.gas_price | |
# 得到完整的铭文文本 | |
if not name_str.startswith('data:,'): | |
input_data = f'data:,{name_str}' | |
# 根据是否检查的开关进行 | |
if token_check: | |
# 这里是开了检查后请求 Ethscriptions API | |
if check_content_exists(sha256(input_data)): | |
# 返回数据为 Ture,说明该铭文已经被题写,打印信息 | |
st.toast(f'{input_data} 已经被题写!', icon='☹️') | |
else: | |
# 返回数据为 False,说明该铭文还没被题写,发送交易 | |
# 使用 current_nonce 发送交易 | |
data, tx_hash = send_transaction(w3, address, key, chain_id, gas_price, input_data, nonces[address]) | |
# 记录最后输出的结果 | |
transaction_results.append(f"{address} | {data} | Transaction Hash: {tx_hash}") | |
# 交易成功后,手动增加 nonce 值 | |
nonces[address] += 1 | |
else: | |
# 这里是未开检查后直接发送交易 | |
# 使用 current_nonce 发送交易 | |
data, tx_hash = send_transaction(w3, address, key, chain_id, gas_price, input_data, nonces[address]) | |
# 记录最后输出的结果 | |
transaction_results.append(f"{address} | {data} | Transaction Hash: {tx_hash}") | |
# 交易成功后,手动增加 nonce 值 | |
nonces[address] += 1 | |
# 更新当前账户索引,确保索引始终在账户列表的范围内 | |
current_account_index = (current_account_index + 1) % len(accounts) | |
# 暂停 3 秒 | |
if sleep_3s: | |
time.sleep(3) # 暂停三秒 | |
st.toast(f'所有任务已经完成。', icon='🎉') | |
# 庆祝动画 | |
st.balloons() | |
# 显示所有交易的结果 | |
st.code('\n'.join(transaction_results)) | |
""" | |
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 ''.join(format(ord(char), '02x') for char in text) | |
# 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 = f"https://mainnet.infura.io/v3/{infura_api_key}" | |
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='wide', initial_sidebar_state='expanded') | |
# 首页 | |
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;"/></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;"/></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;"/></a>', | |
unsafe_allow_html=True) | |
st.markdown(f'> 拆分方案现在面向所有人推出!让我们一起加入权益挖矿的浪潮,并分享50%的月度服务费。') | |
st.markdown("### 功能专区") | |
# st.expander | |
search_rune_expander = st.expander("查询 Ethscriptions") | |
create_rune_expander = st.expander("题写 Ethscriptions") | |
token_no_code_expander = st.expander("一键式铭文批量题写,无需编码知识!") | |
trend_expander = st.expander("潮流动态") | |
help_expander = st.expander("教程帮助") | |
st.markdown("🎉 更多功能尽在菜单栏,请点击左上角的 >") | |
# 查询铭文页面 | |
search_rune_expander.info( | |
f"铭文数据来自 [Ethscriptions](https://ethscriptions.com/) 官方网站,当前索引器状态落后: {get_block_status()['blocks_behind']} 个区块。") | |
search_rune_expander.markdown("##### 查询 ETH 地址所属铭文") | |
user_address = search_rune_expander.text_input('输入 ETH 地址:', '') | |
if search_rune_expander.button('🔍 查询', key='查询铭文'): | |
# 检查ETH地址 | |
pattern = "^0x[a-fA-F0-9]{40}$" | |
if re.match(pattern, user_address): | |
data = get_ethscriptions_by_address(user_address) | |
if not data: | |
search_rune_expander.info( | |
"该地址没有任何铭文,或许是区块暂时没同步过来,如果你不确定,请前往 Ethscriptions 官网再次查询!") | |
else: | |
token_total = 0 | |
for token in token_list: | |
for ethscriptions in data: | |
if is_valid_eths(ethscriptions['content_uri'], token['p'], token['tick'], token['id'], | |
token['amt']): | |
input_data_str = json.loads(ethscriptions['content_uri'][6:]) | |
token_total = token_total + int(input_data_str['amt']) | |
search_rune_expander.success(f"${token['tick']} 有效总量为:{token_total}") | |
token_total = 0 | |
search_rune_expander.warning( | |
f"只统计 etch.market 流动性较高的资产,etch.market 上架的代币不计算在内,详细更多的信息请点击[这里](https://ethscriptions.com/{user_address})") | |
else: | |
search_rune_expander.error("输入的 ETH 地址不正确!") | |
search_rune_expander.markdown("##### 查询铭文的完整信息") | |
ethscriptions_str = search_rune_expander.text_input('输入完整的铭文文本:', '') | |
if search_rune_expander.button('🔍 查询', key='查询信息'): | |
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']: | |
search_rune_expander.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"], | |
} | |
search_rune_expander.json(selected_data) | |
else: | |
search_rune_expander.markdown(f'###### :green[{ethscriptions_str}] 铭文还没被题写!复制下方文本前去题写。') | |
search_rune_expander.code(f'{text_to_hex(ethscriptions_str)}', line_numbers=False) | |
# 批量查询铭文是否被存在 | |
runes = [] | |
search_rune_expander.markdown("##### 批量查询铭文是否被题写") | |
search_rune_expander.markdown(r''' | |
1. **查域名**:可以用空格和换行符还有英文逗号(,)分开,不要带前缀 data:, | |
2. **查代币**:需要查询的代币铭文内容变动的部分文本如 id 请用 "@#" 代替,例如:`data:,{"p":"erc-20","op":"mint","tick":"eths","id":"@#","amt":"1000"}` | |
3. **查纯文本**:可任意填写,用空格和换行符还有英文逗号(,)分开''') | |
input_content = search_rune_expander.text_area(f'输入铭文文本:') | |
search_type = search_rune_expander.radio('选择查询类型:', ['查域名', '查代币', '查纯文本'], | |
label_visibility="collapsed", horizontal=True, index=2) | |
if search_type == '查域名': | |
search_dotname = search_rune_expander.text_input('填写域名后缀:') | |
elif search_type == '查代币': | |
search_token_min_id = search_rune_expander.number_input(f'填写代币铭文范围的**最小 ID(id)**:', min_value=1, value=1, | |
step=1) | |
search_token_max_id = search_rune_expander.number_input(f'填写代币铭文范围的**最大 ID(id)**:', value=10, step=1) | |
if search_rune_expander.button('🔍 查询', key='批量查询铭文'): | |
runes = re.split(r'[\s,]+', input_content) | |
# 过滤掉空或仅包含空白字符的项 | |
runes = [r for r in runes if r.strip() != ''] | |
if search_type == '查域名': | |
runes = [r + search_dotname for r in runes] | |
elif search_type == '查代币': | |
token_runes = [] | |
if len(runes) != 1 and '@#' in input_content: | |
for the_id in range(search_token_min_id, search_token_max_id + 1): | |
token_runes.append(input_content.replace('@#', str(the_id))) | |
else: | |
st.stop() | |
runes = token_runes | |
# 创建一个空的结果列表 | |
results = [] | |
# 循环遍历每一个铭文并查询其存在状态 | |
for rune in runes: | |
if not rune.startswith('data:,'): | |
rune = f'data:,{rune}' | |
sha_value = sha256(rune) | |
response_data = check_content_exists(sha_value) | |
# 根据返回的result,得到真或者假 | |
exists = "已题写" if response_data['result'] else "未题写" | |
results.append([rune, exists]) | |
# 使用 st.table 显示结果 | |
table_data = pd.DataFrame(results, columns=['铭文', '状态']) | |
# 根据状态生成一个辅助排序列 | |
table_data['sort_helper'] = table_data['状态'].apply(lambda x: 0 if x == "未题写" else 1) | |
# 使用辅助列进行排序 | |
table_data.sort_values(by='sort_helper', ascending=True, inplace=True) | |
# 删除辅助排序列 | |
table_data.drop(columns=['sort_helper'], inplace=True) | |
# 定义样式和生成带有专门类名的HTML表格 | |
table_style = """ | |
<style> | |
.styled_table { | |
width: 100%; | |
border-collapse: collapse; | |
border-radius: 8px; | |
overflow: hidden; /* Ensures border-radius applies to table */ | |
} | |
.styled_table th, .styled_table td { | |
border: 1px solid #ddd; | |
padding: 8px; | |
text-align: left; | |
} | |
.styled_table th { | |
background-color: #f2f2f2; | |
color: black; | |
} | |
.styled_table tr:hover { | |
background-color: #f5f5f5; | |
} | |
.styled_table td[status="已题写"] { | |
background-color: #f2dede; /* Reddish */ | |
} | |
.styled_table td[status="未题写"] { | |
background-color: #dff0d8; /* Greenish */ | |
} | |
</style> | |
""" | |
search_rune_expander.markdown(table_style, unsafe_allow_html=True) | |
table_html = table_data.to_html(index=False, classes='styled_table', border=0, escape=False, | |
formatters=dict(状态=lambda x: f'<td status="{x}">{x}</td>')) | |
# 生成HTML表格但不为状态列添加特殊格式 | |
table_html = table_data.to_html(index=False, classes='styled_table', border=0, escape=False) | |
# 使用字符串替换为状态列添加特定属性 | |
table_html = table_html.replace('<td>已题写</td>', '<td status="已题写">已题写</td>') | |
table_html = table_html.replace('<td>未题写</td>', '<td status="未题写">未题写</td>') | |
# 使用st.write输出带样式的HTML表格 | |
search_rune_expander.write(table_html, unsafe_allow_html=True) | |
search_rune_expander.markdown('') | |
# 题写铭文页面 | |
create_rune_expander.markdown("##### 文本转换到十六进制") | |
input_ethscriptions_str = create_rune_expander.text_input( | |
'输入需要转换的文本,默认以 "data:," 开头,换行和回车字符不应出现。', '') | |
if create_rune_expander.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) | |
create_rune_expander.markdown(f':green[{input_ethscriptions_str}] 转换到十六进制:') | |
create_rune_expander.code(input_ethscriptions_hex, line_numbers=False) | |
input_ethscriptions_sha = sha256(input_ethscriptions_str) | |
ethscriptions_data = check_content_exists(input_ethscriptions_sha) | |
if ethscriptions_data['result']: | |
create_rune_expander.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"], | |
} | |
create_rune_expander.json(selected_data) | |
else: | |
create_rune_expander.markdown(f'###### :green[{input_ethscriptions_str}] 铭文还没被题写!快前去题写吧。') | |
create_rune_expander.markdown("##### 批量自动题写铭文") | |
create_rune_expander.info("""在使用之前,敬请仔细阅读说明,感谢您的配合。 | |
1. 请务必访问 **[ethpen.com](https://ethpen.com)** 官方网站。您可以确保这里的代码无恶意,安全地复制。 | |
2. 你只需要掌握一些 python 相关的基础。 | |
3. 在使用过程中,请根据规定准确填写信息,以确保程序顺畅运行。 | |
4. 我们建议您使用备用账号,并避免在账号中存放大额资金。 | |
5. 若您对此代码存有疑虑,建议您利用如 [ChetGPT](https://chat.openai.com/)、[Bard](https://bard.google.com/) 或 [Claude](https://claude.ai/) 等知名 AI 平台进行查询,以判断是否含有恶意代码。 | |
6. 如果你在使用的过程中发现 BUG 或者有什么想法和建议,欢迎与我联系。 | |
""") | |
if create_rune_expander.button('🖨 打印代币代码', key='输出代币铭文 Python 代码'): | |
create_rune_expander.code(python_token_code, 'python', line_numbers=False) | |
if create_rune_expander.button('🖨 打印域名代码', key='输出域名铭文 Python 代码'): | |
create_rune_expander.code(python_name_code, 'python', line_numbers=False) | |
# 全新不用懂代码的铭文批量题写页面 | |
token_no_code_expander.markdown("##### 安全的简易的批量自动题写铭文") | |
token_no_code_expander.info("""在使用之前,敬请仔细阅读说明,感谢您的配合。 | |
1. 请务必访问 **[ethpen.com](https://ethpen.com)** 官方网站。您可以确保这里的代码无恶意,安全地复制。 | |
2. 你只需要拥有一个 [HuggingFace.co](https://huggingface.co) 账户。 | |
3. 在使用过程中,请根据规定准确填写信息,以确保程序顺畅运行。 | |
4. 我们建议您使用备用账号,并避免在账号中存放大额资金。 | |
5. 若您对此代码存有疑虑,建议您利用如 [ChetGPT](https://chat.openai.com/)、[Bard](https://bard.google.com/) 或 [Claude](https://claude.ai/) 等知名 AI 平台进行查询,以判断是否含有恶意代码。 | |
6. 请查看我们的例子 [token-example](https://huggingface.co/spaces/Ethscriptions/token) / [name-example](https://huggingface.co/spaces/Ethscriptions/name)。 | |
""") | |
if token_no_code_expander.button('🖨️ 打印代币代码', key='输出 Token 铭文 Python 代码'): | |
token_no_code_expander.markdown( | |
f'**为 [HuggingFace.co](https://huggingface.co) 平台与 [Streamlit.io](https://streamlit.io/) 框架量身打造的代币铭文专业 Python 代码(app.py):**') | |
token_no_code_expander.code(hf_token_code, 'python', line_numbers=False) | |
token_no_code_expander.markdown(f"**依赖包清单(requirements.txt):**") | |
token_no_code_expander.code(''' | |
Requests | |
streamlit | |
web3 | |
''') | |
if token_no_code_expander.button('🖨️ 打印域名代码', key='输出 Name 铭文 Python 代码'): | |
token_no_code_expander.markdown( | |
f'**为 [HuggingFace.co](https://huggingface.co) 平台与 [Streamlit.io](https://streamlit.io/) 框架量身打造的域名铭文专业 Python 代码(app.py):**') | |
token_no_code_expander.code(hf_name_code, 'python', line_numbers=False) | |
token_no_code_expander.markdown(f"**依赖包清单(requirements.txt):**") | |
token_no_code_expander.code(''' | |
Requests | |
streamlit | |
web3 | |
''') | |
# 潮流动态页面 | |
trend_expander.markdown("##### 开发中...") | |
# 教程帮助页面 | |
help_expander.markdown('##### 我不懂代码,怎么做到批量题写铭文?') | |
# help_expander.markdown('##### 如何用 Metamask 题写 Ethscriptions 铭文?') | |
# help_expander.markdown('##### 如何用 Metamask 在 etch.market 上购买 $eths?') | |
# help_expander.markdown('##### 如何运行批量自动题写铭文 python 代码?') | |
# help_expander.markdown(f'<iframe src="//player.bilibili.com/player.html?aid=787389115&bvid=BV1J14y1i7ap&cid=1237586207&page=1" scrolling="no" border="0" frameborder="no" framespacing="0" allowfullscreen="true"> </iframe>', unsafe_allow_html=True) | |
# 嵌入式SVG文本(以下只是示例,替换为你的SVG文本) | |
twitter_svg = """ | |
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24"><path fill="currentColor" d="M8 2H1l8.26 11.014L1.45 22H4.1l6.388-7.349L16 22h7l-8.608-11.478L21.8 2h-2.65l-5.986 6.886L8 2Zm9 18L5 4h2l12 16h-2Z"/></svg> | |
""" | |
twitter_encoded_svg = base64.b64encode(twitter_svg.encode('utf-8')).decode('utf-8') | |
telegram_svg = """ | |
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 256 256"><defs><linearGradient id="logosTelegram0" x1="50%" x2="50%" y1="0%" y2="100%"><stop offset="0%" stop-color="#2AABEE"/><stop offset="100%" stop-color="#229ED9"/></linearGradient></defs><path fill="url(#logosTelegram0)" d="M128 0C94.06 0 61.48 13.494 37.5 37.49A128.038 128.038 0 0 0 0 128c0 33.934 13.5 66.514 37.5 90.51C61.48 242.506 94.06 256 128 256s66.52-13.494 90.5-37.49c24-23.996 37.5-56.576 37.5-90.51c0-33.934-13.5-66.514-37.5-90.51C194.52 13.494 161.94 0 128 0Z"/><path fill="#FFF" d="M57.94 126.648c37.32-16.256 62.2-26.974 74.64-32.152c35.56-14.786 42.94-17.354 47.76-17.441c1.06-.017 3.42.245 4.96 1.49c1.28 1.05 1.64 2.47 1.82 3.467c.16.996.38 3.266.2 5.038c-1.92 20.24-10.26 69.356-14.5 92.026c-1.78 9.592-5.32 12.808-8.74 13.122c-7.44.684-13.08-4.912-20.28-9.63c-11.26-7.386-17.62-11.982-28.56-19.188c-12.64-8.328-4.44-12.906 2.76-20.386c1.88-1.958 34.64-31.748 35.26-34.45c.08-.338.16-1.598-.6-2.262c-.74-.666-1.84-.438-2.64-.258c-1.14.256-19.12 12.152-54 35.686c-5.1 3.508-9.72 5.218-13.88 5.128c-4.56-.098-13.36-2.584-19.9-4.708c-8-2.606-14.38-3.984-13.82-8.41c.28-2.304 3.46-4.662 9.52-7.072Z"/></svg> | |
""" | |
telegram_encoded_svg = base64.b64encode(telegram_svg.encode('utf-8')).decode('utf-8') | |
discord_svg = """ | |
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 256 256"><g fill="none"><rect width="256" height="256" fill="#5865F2" rx="60"/><g clip-path="url(#skillIconsDiscord0)"><path fill="#fff" d="M197.308 64.797a164.918 164.918 0 0 0-40.709-12.627a.618.618 0 0 0-.654.31c-1.758 3.126-3.706 7.206-5.069 10.412c-15.373-2.302-30.666-2.302-45.723 0c-1.364-3.278-3.382-7.286-5.148-10.412a.643.643 0 0 0-.655-.31a164.472 164.472 0 0 0-40.709 12.627a.583.583 0 0 0-.268.23c-25.928 38.736-33.03 76.52-29.546 113.836a.685.685 0 0 0 .26.468c17.106 12.563 33.677 20.19 49.94 25.245a.648.648 0 0 0 .702-.23c3.847-5.254 7.276-10.793 10.217-16.618a.633.633 0 0 0-.347-.881c-5.44-2.064-10.619-4.579-15.601-7.436a.642.642 0 0 1-.063-1.064a86.364 86.364 0 0 0 3.098-2.428a.618.618 0 0 1 .646-.088c32.732 14.944 68.167 14.944 100.512 0a.617.617 0 0 1 .655.08a79.613 79.613 0 0 0 3.106 2.436a.642.642 0 0 1-.055 1.064a102.622 102.622 0 0 1-15.609 7.428a.638.638 0 0 0-.339.889a133.075 133.075 0 0 0 10.208 16.61a.636.636 0 0 0 .702.238c16.342-5.055 32.913-12.682 50.02-25.245a.646.646 0 0 0 .26-.46c4.17-43.141-6.985-80.616-29.571-113.836a.506.506 0 0 0-.26-.238ZM94.834 156.142c-9.855 0-17.975-9.047-17.975-20.158s7.963-20.158 17.975-20.158c10.09 0 18.131 9.127 17.973 20.158c0 11.111-7.962 20.158-17.974 20.158Zm66.456 0c-9.855 0-17.974-9.047-17.974-20.158s7.962-20.158 17.974-20.158c10.09 0 18.131 9.127 17.974 20.158c0 11.111-7.884 20.158-17.974 20.158Z"/></g><defs><clipPath id="skillIconsDiscord0"><path fill="#fff" d="M28 51h200v154.93H28z"/></clipPath></defs></g></svg> | |
""" | |
discord_encoded_svg = base64.b64encode(discord_svg.encode('utf-8')).decode('utf-8') | |
# 实际的社交链接 | |
twitter_link = "https://twitter.com/pztuya" | |
telegram_link = "https://t.me/NervosCKB" | |
discord_link = "https://discord.gg/ethscriptions" | |
# 关于页面 | |
eths_price_data = get_eths_price() | |
st.markdown("### 关于") | |
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('') | |
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,{discord_encoded_svg}" /> @ethscriptions</span></a>,与 Ethscriptions 一起成长!', | |
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> | |
<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,{twitter_encoded_svg}" /> @ethscriptions</a></span><span class="tag"><a href="https://discord.gg/ethscriptions" target="_blank" style="text-decoration: none";><img src="data:image/svg+xml;base64,{discord_encoded_svg}" /> @ethscriptions</a></span></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) | |
st.markdown('') | |
st.markdown('##### 关于 ethpen.com') | |
st.markdown( | |
f'欢迎踏足 EthPen - 以太之笔!这里汇聚了一系列关于 Ethscriptions 的精细工具集,无论是单一查询、铭文题写,还是批量检索、编码题写,乃至深入的教程导引,以太之笔都将助您铭文题写如飞。我们立志推广 Ethscriptions 的宏大理念,期望 $eths 翱翔于星空,与月相伴!若您携手建议或创意,我们热切期待您的声音。', | |
unsafe_allow_html=True) | |
st.markdown('对了,我叫 pztuya,期待你们和我多多交流😊~') | |
st.markdown(f''' | |
<span class="tag"><a href="https://twitter.com/pztuya" target="_blank" style="text-decoration: none;"><img src="data:image/svg+xml;base64,{twitter_encoded_svg}" /> @pztuya</a></span> | |
<span class="tag"><a href="https://t.me/NervosCKB" target="_blank" style="text-decoration: none;"><img src="data:image/svg+xml;base64,{telegram_encoded_svg}" /> @NervosCKB</a></span> | |
''', unsafe_allow_html=True) | |