├── .gitignore ├── .vscode └── launch.json ├── 00-前期的准备工作.md ├── 01-数据结构.md ├── 02-函数与流程控制.md ├── 03-模块的使用.md ├── 04-文件处理.md ├── 05-第一阶段总结.md ├── 06-pandas.md ├── 07-Web3开发最小原子基础知识点.md ├── 08-web3py.md ├── 09-PyAutoGUI.md ├── 10-tampermonkey.md ├── 11-区块浏览器.md ├── LICENSE ├── README.md ├── file.py ├── hello.py ├── module.py ├── portfolio.py ├── requirements.txt ├── scroll.py ├── sybil.py ├── test.csv └── test.json /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | share/python-wheels/ 24 | *.egg-info/ 25 | .installed.cfg 26 | *.egg 27 | MANIFEST 28 | 29 | # PyInstaller 30 | # Usually these files are written by a python script from a template 31 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 32 | *.manifest 33 | *.spec 34 | 35 | # Installer logs 36 | pip-log.txt 37 | pip-delete-this-directory.txt 38 | 39 | # Unit test / coverage reports 40 | htmlcov/ 41 | .tox/ 42 | .nox/ 43 | .coverage 44 | .coverage.* 45 | .cache 46 | nosetests.xml 47 | coverage.xml 48 | *.cover 49 | *.py,cover 50 | .hypothesis/ 51 | .pytest_cache/ 52 | cover/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | *.log 60 | local_settings.py 61 | db.sqlite3 62 | db.sqlite3-journal 63 | 64 | # Flask stuff: 65 | instance/ 66 | .webassets-cache 67 | 68 | # Scrapy stuff: 69 | .scrapy 70 | 71 | # Sphinx documentation 72 | docs/_build/ 73 | 74 | # PyBuilder 75 | .pybuilder/ 76 | target/ 77 | 78 | # Jupyter Notebook 79 | .ipynb_checkpoints 80 | 81 | # IPython 82 | profile_default/ 83 | ipython_config.py 84 | 85 | # pyenv 86 | # For a library or package, you might want to ignore these files since the code is 87 | # intended to run in multiple environments; otherwise, check them in: 88 | # .python-version 89 | 90 | # pipenv 91 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 92 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 93 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 94 | # install all needed dependencies. 95 | #Pipfile.lock 96 | 97 | # poetry 98 | # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. 99 | # This is especially recommended for binary packages to ensure reproducibility, and is more 100 | # commonly ignored for libraries. 101 | # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control 102 | #poetry.lock 103 | 104 | # pdm 105 | # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. 106 | #pdm.lock 107 | # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it 108 | # in version control. 109 | # https://pdm.fming.dev/latest/usage/project/#working-with-version-control 110 | .pdm.toml 111 | .pdm-python 112 | .pdm-build/ 113 | 114 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm 115 | __pypackages__/ 116 | 117 | # Celery stuff 118 | celerybeat-schedule 119 | celerybeat.pid 120 | 121 | # SageMath parsed files 122 | *.sage.py 123 | 124 | # Environments 125 | .env 126 | .venv 127 | env/ 128 | venv/ 129 | ENV/ 130 | env.bak/ 131 | venv.bak/ 132 | 133 | # Spyder project settings 134 | .spyderproject 135 | .spyproject 136 | 137 | # Rope project settings 138 | .ropeproject 139 | 140 | # mkdocs documentation 141 | /site 142 | 143 | # mypy 144 | .mypy_cache/ 145 | .dmypy.json 146 | dmypy.json 147 | 148 | # Pyre type checker 149 | .pyre/ 150 | 151 | # pytype static type analyzer 152 | .pytype/ 153 | 154 | # Cython debug symbols 155 | cython_debug/ 156 | 157 | # PyCharm 158 | # JetBrains specific template is maintained in a separate JetBrains.gitignore that can 159 | # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore 160 | # and can be added to the global gitignore or merged into this file. For a more nuclear 161 | # option (not recommended) you can uncomment the following to ignore the entire idea folder. 162 | #.idea/ 163 | 164 | *.csv -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "name": "Python Debugger: Current File", 9 | "type": "debugpy", 10 | "request": "launch", 11 | "program": "${file}", 12 | "console": "integratedTerminal" 13 | } 14 | ] 15 | } -------------------------------------------------------------------------------- /00-前期的准备工作.md: -------------------------------------------------------------------------------- 1 | 这篇课程完全是为脚本准备的,所以,不要担心,小白也可以学。 2 | 3 | **请按照我的步骤,实操,不需要探究原理,因为我们是为了使用,不是做产品。** 4 | 5 | > 统一使用 Python3 6 | 7 | ## 第一步:安装 Python 8 | 9 | - [https://www.python.org/downloads/](https://www.python.org/downloads/) 10 | 11 | Windows || Mac OS 用户可以在上述的链接中下载 Python 的安装包。(**推荐大部分小白使用这个方式**) 12 | 13 | > 之后不用了,直接卸载,或从环境变量中移除配置,如果某一天想用,再重新安装即可。 14 | 15 | 非安装包可以使用 homebrew 来安装: 16 | 17 | - [https://brew.sh/](https://brew.sh/) 18 | 19 | ```bash 20 | > /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" 21 | ``` 22 | 23 | 在 `.zshrc` 文件中配置 `export PATH=/opt/homebrew/bin:$PATH` 24 | 25 | - [https://docs.brew.sh/Homebrew-and-Python](https://docs.brew.sh/Homebrew-and-Python) 26 | 27 | ```bash 28 | > brew update 29 | > brew install python3 30 | ``` 31 | 32 | > 因为 brew 是默认安装,无法切换版本,如果你有切换版本的需求,可以使用 pyenv 来安装 Python 并管理它的版本 33 | 34 | ## 第二步:安装 VSCode 和 Cursor 35 | 36 | [https://code.visualstudio.com/](https://code.visualstudio.com/) 下载安装 37 | 38 | 在 VSCode 里安装下列插件: 39 | 40 | - SQLite Viewer 查询结构化的 SQLite 数据 41 | - Python 对 Python 在 VSCode 上的语言支持 42 | - Python Debugger Debug 调试器 43 | 44 | **Cursor 是真正编写脚本的时候用** 45 | 46 | [https://www.cursor.com/](https://www.cursor.com/) 下载安装 47 | 48 | ## 第三步:保存好两个网页 49 | 50 | - [https://remix.ethereum.org/](https://remix.ethereum.org/) Solidity 开发工具 51 | - [https://programiz.pro/ide/python](https://programiz.pro/ide/python) Python Playground 52 | 53 | 之后,我们大部分 Python 语言学习,都在 Playground 中进行,其他部分在 VSCode 里,只有在合约调合约的时候,我们才会用到 Remix,anyway 请写下你的 Say Hello ! 54 | 55 | `print("Hello icepy.eth!")` ,点击 Run 按钮,查看一下输出结果吧! -------------------------------------------------------------------------------- /01-数据结构.md: -------------------------------------------------------------------------------- 1 | 上一篇我们写下了 Say Hello `print("Hello icepy.eth!")` 打印在控制台中,这仅是单行字符串,如果我们想写下多行字符串,该怎么办? 2 | 3 | ```python 4 | print("""Hello icepy.eth! 5 | Hello x.com 6 | """) 7 | ``` 8 | 9 | 使用三个双引号将要输出的内容包裹起来,这种方式易于在处理多行信息输出时有用。 10 | 11 | 在程序中,变量是一切数据的载体,当我们编写了很长的输出,可是我想在别的地方使用,这时候就需要变量这个载体来承接你的输出。 12 | 13 | ```python 14 | info = "Hello icepy.eth" 15 | print(f"{info}") 16 | ``` 17 | 18 | `f` 是 format 的意思,我们需要使用大括号将变量包裹起来。 19 | 20 | 那既有数据,那自然就有不同的类型,现在我们使用 `type` 来判断一下 info 的类型 21 | 22 | ```python 23 | info = "Hello icepy.eth" 24 | info_type = type(info) 25 | print(f"{info_type}") 26 | ``` 27 | 28 | 你能看见在控制台中打印的是 `str`,是的,我们即将要用到的数据结构,基本上是字符串,数值,布尔,列表和字典,特别是列表和字典,对于组织和处理结构化的数据,有很大的帮助。 29 | 30 | **不要问,记住下列的操作方式即可** 31 | 32 | ```python 33 | tel = {'jack': 4098, 'sape': 4139} 34 | jack = tel['jack'] # 取值 35 | tel['sape'] = 5892 # 赋值 36 | del tel['sape'] # 删除 37 | ``` 38 | 39 | 字典使用大括号以键值对的形式出现,在上面的案例里 `{'jack': 4098, 'sape': 4139}`,'jack' 是键,4098 是值,使用 tel 这个变量来承载这一段字典,使用 tel['jack'] 来取值,使用 tel['sape'] = 5892 来赋值,使用 del tel[sape] 将这个键删除。 40 | 41 | ```python 42 | stack = [3, 4, 5] 43 | ``` 44 | 45 | 列表使用下标的方式来取值,如 `stack[0]` 取出来的值是 3,列表的操作依赖于一些特定的方法,如: 46 | 47 | - append(x) 将项添加到列表的末尾 48 | - remove(x) 从列表中删除第一个值等于 x 的项 49 | - pop([i]) 删除列表给定位置的项并将其返回 50 | - clear 清空列表 51 | - index(x[, start[, end]]) 返回列表中第一个值等于 x 的项目的从零开始的索引 52 | - count(x) 返回 x 在列表中出现的次数 53 | 54 | [https://docs.python.org/3/tutorial/datastructures.html](https://docs.python.org/3/tutorial/datastructures.html) 更多的方法可以在此处查略 -------------------------------------------------------------------------------- /02-函数与流程控制.md: -------------------------------------------------------------------------------- 1 | 程序是从上到下的一个执行过程,但为了程序可控,我们可以将一些重复的执行抽象出来变成一个函数,在这个场景下,从 A 到 D 的执行过程,就简化成了调用 A 处理完成之后调用 B ,以此类推到 D,大部分脚本,都可以单向的理解为,它是一个线性的执行过程。在 Python 中函数可是一等公民,所以函数是我们会经常面对的一份代码块。 2 | 3 | 4 | [https://docs.python.org/3/tutorial/controlflow.html#defining-functions](https://docs.python.org/3/tutorial/controlflow.html#defining-functions) 5 | 6 | 在 Python 中定义一个函数,很简单实用 `def` 关键字: 7 | 8 | ```python 9 | def fib(n): # write Fibonacci series up to n 10 | """Print a Fibonacci series up to n.""" 11 | a, b = 0, 1 12 | while a < n: 13 | print(a, end=' ') 14 | a, b = b, a+b 15 | print() 16 | 17 | # Now call the function we just defined: 18 | fib(2000) 19 | ``` 20 | 21 | 而我们要明白的是,函数名,参数,返回值,当然在参数上 Python 有很多不同的行为,比如给参数写上默认值,任意参数列表,但这些不重要,你要明白的是上面的这个例子,我们用 def 来定义函数,fib 是函数名,n 是参数,它没有返回值,如果要有返回值,则使用 `return`,你看,你可以写一个更简单的: 22 | 23 | ```python 24 | def say(name): 25 | print(f'Hello {name}') 26 | 27 | say('icepy.eth') 28 | ``` 29 | 30 | 所谓的流程控制,理解起来,就像是一道逻辑题,它可是非黑即白的,只有对与错,两个结果。今天你骑着摩托车去加油,你兜里钱不够,怎么办? 31 | 32 | ```python 33 | money = 100 34 | 35 | if money < 200: 36 | print('加油失败') 37 | else: 38 | print('加油成功') 39 | 40 | ``` 41 | 42 | 你可以想象一下,我们的撸毛脚本,是不是同样是这样的逻辑,使用 A 完成 B 这个动作,得到 C,像我们可以直接写大段的 if else 来筛选条件,还是用上面的例子来说: 43 | 44 | ```python 45 | money = 100 46 | 47 | if money = 200: 48 | print('加油,买水') 49 | elif money = 100: 50 | print('加油') 51 | else: 52 | print('钱不够啊!') 53 | ``` 54 | 55 | 另外对于前面我们学习到的列表和字典,可以使用 for 来顺序迭代,在这一部分,我们只需要了解它是怎么用的,以及有哪些关键字可以停止: 56 | 57 | ```python 58 | words = ['cat', 'window', 'defenestrate'] 59 | for w in words: 60 | print(w, len(w)) 61 | ``` 62 | 63 | ```python 64 | active_users = {} 65 | for user, status in users.items(): 66 | if status == 'active': 67 | active_users[user] = status 68 | ``` 69 | 70 | 都是使用 `for in` 关键字,那你说除了 for in 之外,有没有别的循环方式?有,就是 `while` ,在它们的循环体内,都可以使用 break 来跳出循环(你的 break 写在哪个循环体内,就跳出哪个循环体),可以使用 continue 来跳过,通常情况下,break 是用的最多的。 71 | 72 | 现在!我们将前面的几个知识点都串起来,做一个完整的定义: 73 | 74 | ```python 75 | cex_markets = {'BTC': 60000, 'ETH': 2400} 76 | dex_markets = [59888, 59990, 60200] 77 | 78 | def get_price(token_name): 79 | price = cex_markets[token_name] 80 | return price 81 | 82 | def arbitrage(price): 83 | spread = 0 84 | for tic in dex_markets: 85 | if tic < price: 86 | continue 87 | else: 88 | spread = tic - price 89 | break 90 | 91 | print(f'利差:{spread}') 92 | 93 | 94 | cex_price = get_price('BTC') 95 | arbitrage(cex_price) 96 | 97 | ``` 98 | 99 | `cex_markets` 定义的是中心化交易所的交易价格,`dex_markets` 定义的是去中心化交易所不同平台的交易价格,在这里我们定义了两个函数 `get_price` 和 `arbitrage`,通过 BTC 符号在 get_price 拿到中心化交易所的比特币价格(这里用的是字典),然后以参数的方式传递给 arbitrage 函数来计算利差,在 arbitrage 函数内,我们循环 dex_markets 这个列表,然后用流程控制的方式,得到利差。 100 | -------------------------------------------------------------------------------- /03-模块的使用.md: -------------------------------------------------------------------------------- 1 | 对于模块,不得不提一句作用域和路径,前者程序在执行过程中寻址的路径,后者是模块载入寻址的路径,对于我们写脚本,我的推荐是不要去划分目录,模块都写在同一级目录中,这样就避免了很多你要了解的知识点,对于代码,我们不要写全局变量,直接写在函数体内,用函数体来限制作用域的范围,因为这样可以避免在同名的情况下,程序执行时得到错误的结果,避免了作用域污染。 2 | 3 | [https://docs.python.org/3/tutorial/modules.html](https://docs.python.org/3/tutorial/modules.html) 4 | 5 | Python 的模块分为三种:内置模块,第三方模块和自己编写的模块,这是我们接下来写脚本时会经常要用到的。 6 | 7 | 导入模块,我的推荐是全量导入,即:import test ,这种导入是将这个模块内所有可用的功能都导入到了使用的文件内。 8 | 9 | 但是!我们要了解一下区域导入,即 from ... import ... ,这对于阅读代码是有易的,但我们自己写的代码,全量导入即可。 10 | 11 | ```python 12 | from fib import fibonacci 13 | ``` 14 | 导入模块 fib 的 fibonacci 函数。 15 | 16 | Python 的内置模块,可以查阅 [https://docs.python.org/3/py-modindex.html](https://docs.python.org/3/py-modindex.html) 17 | 18 | 对于第三方模块,这里需要使用 pip 来安装,你可以输入: 19 | 20 | ```bash 21 | > py -m pip --version 22 | ``` 23 | 24 | 查询一下自带的 pip 版本,然后正常安装 [https://pypi.org/project/requests/](https://pypi.org/project/requests/) 模块。 25 | 26 | ```bash 27 | > py -m pip install requests 28 | ``` 29 | 30 | 需要说明一下,如果你是使用 homebrew 安装的 Python3 需要安装一下 pipx 来管理虚拟环境,当然你也可以使用 `--break-system-packages` 来恢复 pip 的安装行为,因为它主要遵循的是 PEP 668,原理性的内容,就不多讲了,主要是为了防止系统内在冲突的。 31 | 32 | [https://peps.python.org/pep-0668/#marking-an-interpreter-as-using-an-external-package-manager](https://peps.python.org/pep-0668/#marking-an-interpreter-as-using-an-external-package-manager) 33 | 34 | 由于我推荐大家的是直接下载 Python 安装包,直接安装,因此没有上述的问题。 35 | 36 | 不过对于使用 homebrew 安装 Python,我的推荐是为我们的 VSCode 配置虚拟环境,然后在这个虚拟环境里安装模块,并且也能用于 requirements.txt ,requirements.txt 是一个包含项目所需的软件包或库列表的文件,这些软件包或库都可以通过该文件安装,有时候我们在 Github 上使用别人的代码时,常常能见到它。 37 | 38 | [https://code.visualstudio.com/docs/python/environments](https://code.visualstudio.com/docs/python/environments) 39 | 40 | > 由于程序是在虚拟环境中,因此运行的时候,不能在终端直接运行,这是会报错的,找不到 requests 模块,需要在 VSCode 里来运行 41 | 42 | 现在,我们写一段代码,通过币安的 API 获取 ETH 的价格: 43 | 44 | ```python 45 | import requests 46 | 47 | 48 | r = requests.get('https://api1.binance.com/api/v3/ticker/price?symbol=ETHUSDT') 49 | j = r.json() 50 | 51 | 52 | print(f'{j}') 53 | ``` -------------------------------------------------------------------------------- /04-文件处理.md: -------------------------------------------------------------------------------- 1 | 处理路径其实是一件很头疼的事情,乐观的情况在于我们只需要面对自己的系统环境,不需要提供给第三方使用,因此,节省了很多处理的细节。 2 | 3 | 你的程序在运行的目录即可视为搜寻文件的起始目录,如果你要读写的文件在别的目录下,怎么办?我的推荐是直接搞绝对路径,因为路径是我们已知的,反而绝对路径是更轻松,但我的另外一个推荐是将要读写的文件都放在程序所在的目录,这样处理起来,也方便查找。 4 | 5 | > 另外提一句如果你想处理不同的路径,需要使用 os 模块 6 | 7 | 在 Python 里使用 `open` 函数来处理读写文件,大部分情况下,我们主要是用它的两个参数,第一个参数是文件的路径,第二个参数是模式,可用 `r` 读取,`w` 写入 8 | 9 | ```python 10 | f = open('./test.json', 'r') 11 | j = f.read() 12 | f.close() 13 | 14 | w = open('./test.txt', 'w') 15 | w.write('icepy.eth') 16 | w.close() 17 | ``` 18 | 对于我们撸毛脚本来说,很多时候都在处理 JSON 和 CSV,除了内置 JSON 模块外,这里我们要使用的是 pandas ,一个专门处理结构化数据的第三方模块,非常强大的数据分析能力。 19 | 20 | JSON 是一种数据交换格式,通常在请求里会比较常见,而 CSV 是一种存储表格数据的文本,它通常用于项目方发空投时候提供的资格和数量列表。 21 | 22 | [https://pandas.pydata.org/docs/user_guide/index.html](https://pandas.pydata.org/docs/user_guide/index.html) 23 | 24 | ```python 25 | import pandas 26 | data = pandas.read_csv('./test.csv') 27 | 28 | print(f'{data.columns}') 29 | print(f'{data.head(10)}') 30 | 31 | ``` 32 | 33 | 一些简单的用法,比如使用 head 查看前 10 行的数据,columns 查看有哪些列等。 -------------------------------------------------------------------------------- /05-第一阶段总结.md: -------------------------------------------------------------------------------- 1 | 在学了这么多知识点后,我们需要实践一下,开发两个有用的小工具,以夯实我们学习的知识。 2 | 3 | 第一个工具是使用币安的 API 计算我们投资组合的价值 4 | 第二个工具是使用hop的女巫列表,查询一下你的地址是否在女巫列表里 5 | 6 | [https://developers.binance.com/docs/binance-spot-api-docs](https://developers.binance.com/docs/binance-spot-api-docs) 7 | 8 | 女巫列表在这里下载:[https://github.com/hop-protocol/hop-airdrop/blob/master/src/data/eliminatedSybilAttackers.csv](https://github.com/hop-protocol/hop-airdrop/blob/master/src/data/eliminatedSybilAttackers.csv) 9 | 10 | 假设我们的投资组合是 BTC ETH SOL ,分别的数量是 1 10 100 11 | 12 | ```python 13 | import requests 14 | 15 | def get_my_portfolio(): 16 | return {'BTC': 1, 'ETH': 10, 'SOL': 100} 17 | 18 | def statistics(): 19 | my_portfoli = get_my_portfolio() 20 | tickers = ['BTCUSDT', 'ETHUSDT', 'SOLUSDT'] 21 | portfolio = {'BTC': 0, 'ETH': 0, 'SOL': 0} 22 | 23 | for ticker in tickers: 24 | url = 'https://api1.binance.com/api/v3/ticker/price?symbol=' + ticker 25 | print(f'{url}') 26 | r = requests.get(url) 27 | j = r.json() 28 | price = float(j['price']) 29 | if ticker == 'BTCUSDT': 30 | btc = my_portfoli['BTC'] * price 31 | portfolio['BTC'] = btc 32 | elif ticker == 'ETHUSDT': 33 | eth = my_portfoli['ETH'] * price 34 | portfolio['ETH'] = eth 35 | else: 36 | sol = my_portfoli['SOL'] * price 37 | portfolio['SOL'] = sol 38 | 39 | print(f'{portfolio}') 40 | 41 | statistics() 42 | ``` 43 | 44 | 在这里我们用了函数,列表,字典,并且使用了第三方模块来发起请求 45 | 46 | 我从 hop 的女巫列表里随便拿了一个地址,做我们的测试地址用 47 | 48 | 0x00035ab46994cda43f150b2be16bb7ca423171c7 49 | 50 | ```python 51 | import pandas 52 | 53 | addresses = [ 54 | '0x00035ab46994cda43f150b2be16bb7ca423171c7' 55 | ] 56 | 57 | data = pandas.read_csv('./eliminatedSybilAttackers.csv') 58 | result = data['address'].isin(addresses) 59 | 60 | if result.any(): 61 | print('在女巫列表') 62 | else: 63 | print('不在女巫列表') 64 | ``` 65 | 66 | 这里我们用了 pandas 模块和流程判断 -------------------------------------------------------------------------------- /06-pandas.md: -------------------------------------------------------------------------------- 1 | 前面的篇章有写 pandas 是一个强大的数据分析工具,可能大家对这个工具的实践会有一些懵,这里我用一个例子来给大家讲解一下它的用例,这样可能会更直观,为什么我们要学习它。 2 | 3 | 对 Scroll Marks 的分布进行数据分析,用数据验证一下对收益的预期和行为的策略选择,链下的数据比较难用 dune 等平台,我先假定,用一个笨办法,使用 https://scrollscan.com 把区块数据同步下来,并且模拟请求后,将 marks 和 address 都一一对应保存在 CSV 文件里了,以 address, marks 为 header。 4 | 5 | 6 | ```python 7 | import pandas 8 | import numpy 9 | 10 | data = pandas.read_csv('./scrollMarks.csv') 11 | 12 | 13 | b = data['marks'].sum() 14 | c = data['marks'].median() 15 | ``` 16 | 17 | 在这里先计算一下总量和中位数,后续,我将用中位数做基准,做一次分类,为什么要分类,因为这个分类数据可以跟空投预期数据进行推导,比如拿 zkSync 的比例做基准,60多万地址,17.5% 的份额,大概率,在这个比例的基础上,你可以设置一个区间,10%-25%,拿这个区间,去套分类做推导,如果空投是 10% ,均分,每个地址是多少,如果按档位分,每个地址是多少,最后用估值和代币总量来算单个代币的价格,乘一下,就能得到一个地址,大概的收益。 18 | 19 | ```python 20 | d = data[data['marks'] < c] 21 | ``` 22 | 23 | 小于中位数的地址 24 | 25 | ```python 26 | e = data[data['marks'] > c] 27 | ``` 28 | 29 | 大于中位数的地址 30 | 31 | 接下来,我准备对数据进行再次分类 32 | 33 | ```python 34 | g = data[data['marks'] < 100] 35 | ``` 36 | 37 | 小于 100 marks 的地址 38 | 39 | ```python 40 | h = data[data['marks'].map(lambda x: x > 100 and x < c)] 41 | ``` 42 | 43 | 大于 100 且小于中位数的地址 44 | 45 | 你看,你可以以此类推,做出来几个档位,小于 100 marks 的地址有多少,大于 100 marks 且小于中位数的地址有多少,大于中位数且小于 1000 的地址有多少。 46 | 47 | 后续,比如我们分成了四个档位,我先假定一下,它们的分类有一个比例 4:3:2:1,是这样的比例(比例从小于 100 开始),我们按分档计算的时候,就是倒过来,比如假定 Scroll 的空投总量是 10亿,40%的地址是小于 100 marks 的,所以,我们拿 10亿 * 10% 分给这 40%,因为我们不知道具体的分配规则,所以假定的就是倒置,数量越多的地址群分配 10亿 * 10%(数量最少的地址百分比)。 48 | 49 | 基本上,在这个数据的基础上,我们就可以对 Scroll Marks 的分布和预期,有一个决策依据,这就是为什么我们要学习 pandas 的原因。 -------------------------------------------------------------------------------- /07-Web3开发最小原子基础知识点.md: -------------------------------------------------------------------------------- 1 | 在学习如何写 Web3 代码之前,我们需要花一些时间,理解我提炼出来的最小原子基础知识点,毕竟区块链这个技术体系,方方面面的知识太多了,我们不需要去关注那么多,而是以脚本的视角来明确最小原子基础知识点。 2 | 3 | 网络,就涉及到通信,通信就涉及到数据的交换格式,而 JSON-RPC 就是所有执行客户端实现的标准方法集合,而我们写的代码,实际上就是在通过与网络的通信来交换数据,简单来说,我们可以理解为读写模式,使用一套 JSON 描述我们的行为,将这段 JSON 广播出去,拥有执行客户端的人根据这段 JSON 来完成读取或写入的操作。 4 | 5 | [https://github.com/ethereum/execution-apis](https://github.com/ethereum/execution-apis) 6 | 7 | 我们需要了解两个定语:Provider 和 Signer ,同时忽略复杂的加密概念,在我们与合约交互时用语言来描述,它的行为,就是,如果你只是读取,使用 Provider ,直接调用 JSON-RPC APIs 即可 ,这些方法在前端的库中有对应的实现,但它的背后,实际是将你要调用的方法,用 JSON 来描述,将这一段 JSON 广播了出去。 8 | 9 | ```json 10 | { 11 | "id":1 12 | "jsonrpc":"2.0" 13 | "method":"debug_getBadBlocks" 14 | "params":[] 15 | } 16 | ``` 17 | 18 | ```json 19 | { 20 | "id":1 21 | "jsonrpc":"2.0" 22 | "result":[] 23 | } 24 | ``` 25 | 26 | 这些读取,是不需要验证你的控制权的。 27 | 28 | 你可以想象一下,我们在推特上写内容,就好比,我们通过 JSON-RPC 将内容发送出去,写入推特这个平台(假装一下它是以太坊区块链),但如果不能验证你是你,那岂不是乱套了?任何人都可以把内容发送到你的推文里,正常来说只有验证了你是你,你才能把内容发送到你的推文里。 29 | 30 | Signer 干的就是这个事情,这里牵扯到一个非对称加密的概念(我觉得你可以忽略,只需简单的理解),在生成钱包的时候有两把钥匙,一把钥匙是公开的,一把钥匙仅自己有,有一天我们用仅自己有的钥匙对内容进行了签名,然后将签名广播出去了,这个时候任何知道你公开钥匙的人(客户端),都可以对这个签名进行验证,证明这个内容是不是你的钥匙签的。 31 | 32 | 这就解决了,你是你的问题,同时将你签名的这一段 JSON 描述广播了出去。 33 | 34 | [https://ethereum.github.io/execution-apis/api-documentation/](https://ethereum.github.io/execution-apis/api-documentation/) 35 | 36 | 对于写脚本,我们要理解的就是这个,接下来,你才能知道,怎么玩。 -------------------------------------------------------------------------------- /08-web3py.md: -------------------------------------------------------------------------------- 1 | 请把 web3py 当 SDK 来使用,不要被它复杂的概念所迷惑,虽然它依赖与以太坊节点的连接才能与其交互。 2 | 3 | [https://web3py.readthedocs.io/en/stable/quickstart.html#](https://web3py.readthedocs.io/en/stable/quickstart.html#) 4 | 5 | 6 | 我推荐使用下面两个 RPC 服务。 7 | 8 | [https://app.infura.io/](https://app.infura.io/) 9 | [https://www.alchemy.com/](https://www.alchemy.com/) 10 | 11 | 大部分场景,我们都使用 HTTP 12 | 13 | ```python 14 | from web3 import Web3 15 | 16 | w3 = Web3(Web3.HTTPProvider('https://mainnet.infura.io/v3/xxx')) 17 | ``` 18 | 19 | 我将不需要私钥即可与以太坊节点交互,获得一些数据的 API 都归类于此-读取,我们比较常用的,如查询地址的余额,查询最后一个 block 信息等等 20 | 21 | ```python 22 | w3.eth.get_block('latest') 23 | w3.eth.get_balance('0x...') 24 | ``` 25 | 26 | 我将需要私钥与以太坊节点交互的 API 都归类于此-写入,比如发送 ETH 27 | 28 | ```python 29 | pk = os.environ.get('PRIVATE_KEY') 30 | acct2 = w3.eth.account.from_key(pk) 31 | w3.eth.send_transaction({ 32 | "from": '0x...', 33 | "value": w3.to_wei(3, 'ether'), 34 | "to": acct2.address 35 | }) 36 | ``` 37 | 38 | 交互合约不分读写,因为都有可能,首先我们需要知道合约地址 和 ABI 39 | 40 | ```python 41 | address = '0x...' 42 | abi = '[{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"address","name":"minter_","type":"address"},' 43 | contract_instance = w3.eth.contract(address, abi) 44 | 45 | contract_instance.functions.storedValue().call() 46 | tx_hash = contract_instance.functions.updateValue(43).transact() 47 | ``` 48 | 49 | 不要担心,ABI 就是一段描述,描述方法名,参数名,参数类型。 -------------------------------------------------------------------------------- /09-PyAutoGUI.md: -------------------------------------------------------------------------------- 1 | 先说一下为什么要用 PyAutoGUI,这是一个可以模拟鼠标,键盘的工具,这就意味着可以在桌面上,自动的对某些软件点点来完成交互。 2 | 3 | 它的实现逻辑比较简单,在屏幕上的位置用 x 和 y 坐标来实现,x 是横向的,y 是纵向的,x 从左侧 0 位置开始,一直向右侧增加,y 从顶部 0 位置开始,一直向下增加,举一个例子比如你的屏幕分辨率是 1920 x 1080,则右下角的坐标为(1919,1079),这是因为坐标系都是从 0 开始,而不是从 1 开始。 4 | 5 | [https://pyautogui.readthedocs.io/en/latest/](https://pyautogui.readthedocs.io/en/latest/) 6 | 7 | 整体的 python 代码不难,安装完模块后,都是使用 APIs 来完成你想自动化的步骤。 8 | 9 | 比如,举一个小例子,将鼠标自动的移动 10 | 11 | ```python 12 | x = 200 13 | y = 200 14 | num_seconds = 1 15 | 16 | pyautogui.moveTo(x,y,duration=num_seconds) 17 | ``` 18 | 19 | 在 1 秒内将鼠标移动到 x y 的位置 20 | 21 | ```python 22 | pyautogui.click(x=moveToX, y=moveToY, clicks=num_of_clicks, interval=secs_between_clicks, button='left') 23 | ``` 24 | 25 | 使用左键单击一次鼠标 26 | 27 | 你看,其实这些代码都很简单,你要明白,这个模块可以做什么事情,比去明白代码要重要的多。 -------------------------------------------------------------------------------- /10-tampermonkey.md: -------------------------------------------------------------------------------- 1 | 先说明一下啊!使用 tampermonkey 请不要安装别人的代码,这很容易泄露你的敏感信息,网页对 UserScript 是透明的。 2 | 3 | tampermonkey 是一个可以将 UserScript 注入到网页中的 chrome 插件,为什么我要写它? 4 | 5 | 我举一个场景,你就明白它有什么用了。 6 | 7 | 很多朋友是专门做零撸测试网的,如果你的号很多,领水就很不方便,但是你注入 UserScript 并且结合 metamask 的 多 wallet 的 event 就能快速半自动的给不同的钱包完成领水的工作。 8 | 9 | 当然,不止领水,还有很多有意思的事情,你可以探索一下。 10 | 11 | 我说一个我想到的思路,由于 metamask 注入了 ethereum 对象,你可以在切换地址时候发出事件,在 UserScript 里监听,然后配合你做好的一套自动登录,签名的流程,再配合 Proxy SwitchyOmega 来管理的网络,大部分场景都能完成,只需要一点点手动,比如签名会调起来 metamask 的界面,你要手动的点一下。 12 | 13 | [https://chromewebstore.google.com/detail/%E7%AF%A1%E6%94%B9%E7%8C%B4/dhdgffkkebhmkfjojejmpbldmpobfkfo?hl=zh-CN&utm_source=ext_sidebar](https://chromewebstore.google.com/detail/%E7%AF%A1%E6%94%B9%E7%8C%B4/dhdgffkkebhmkfjojejmpbldmpobfkfo?hl=zh-CN&utm_source=ext_sidebar) 14 | 15 | 16 | [https://developer.chrome.com/docs/extensions/reference/api/userScripts](https://developer.chrome.com/docs/extensions/reference/api/userScripts) -------------------------------------------------------------------------------- /11-区块浏览器.md: -------------------------------------------------------------------------------- 1 | 对于区块浏览器除了可以浏览交易信息外,在这里还有很多工具和APIs可以使用,可以为我们在某些场景下,提供快速解决问题的方法。工具大多数都是跟合约开发相关,APIs 则是可以用它来分析区块数据。 2 | 3 | 我使用比较多的区块浏览器: 4 | 5 | 1. https://mempool.space/zh/ 6 | 2. https://www.ethernow.xyz/mempool/all 7 | 3. https://beaconcha.in/ 8 | 4. https://rantom.app/ 9 | 5. https://www.mintscan.io/ 10 | 6. https://voyager.online/ 11 | 7. 各家 L2 etherscan 出品的区块浏览器 12 | 13 | 因为每个区块浏览器细节不同,很难全部讲明白,需要你自己去研究,我就拿今天我遇到 layerzero 领取空投时无法领取该怎么解决这个问题来举例。 14 | 15 | 理论性的内容不详细说了,我就简单说一下,我们调合约,大部分时候都是一个写入的操作,你要传递你想写入的内容,这个内容时放置在 input data 这个参数里的,我们在区块浏览器上人不可读,是因为它已经被转换成了字节码,这个时候,我们要让它变成人类可读的,所以需要解码这个动作。 16 | 17 | https://arbiscan.io/inputdatadecoder 18 | 19 | 大部分区块浏览器都提供了类似的工具,当然除了解码外,还有别的工具,都是可以辅助开发者对数据做一些处理。 20 | 21 | 比如 layerzero 这个在 arb 上的领取错误,是因为在前端数值不一致导致的,而我们要做的,就是把 input data 拿出来,到上述的工具里解码后变成人类可读的参数值,然后使用它的合约,在合约上手动的调用领取的动作。 22 | 23 | https://arbiscan.io/address/0xb09f16f625b363875e39ada56c03682088471523#writeContract 24 | 25 | 如果你安装的是 Chrome ,右键点击检查,把 Chrome Dev tools 的界面调出来,然后你在 layerzero 的前端界面上点击领取,这个时候程序会报错,在控制台里,能看到抛出来的一个错误,这个错误给你组织了一个可读的结构,如:reason="execution reverted", method="", data="", 然后我们找到 data="",把 data 等于的值复制出来,在解码器中选择 without ABI 后再输入进去点击解码,你就能得到你要调合约的参数名和值。 26 | 27 | 接着,我们在领取合约上,先连接钱包,然后点击 donateAndClaim 方法,这时候在界面上会让你输入参数,我们把解码的参数名和值,在这里一一对应把值输入进去,最后再点击调用合约。 28 | 29 | 你看,区块浏览器,其中一个小工具,就为我们解决了,如果在前端调用合约不可用时,我们可以直接在合约上调用,达到解决问题的目的。 -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Mozilla Public License Version 2.0 2 | ================================== 3 | 4 | 1. Definitions 5 | -------------- 6 | 7 | 1.1. "Contributor" 8 | means each individual or legal entity that creates, contributes to 9 | the creation of, or owns Covered Software. 10 | 11 | 1.2. "Contributor Version" 12 | means the combination of the Contributions of others (if any) used 13 | by a Contributor and that particular Contributor's Contribution. 14 | 15 | 1.3. "Contribution" 16 | means Covered Software of a particular Contributor. 17 | 18 | 1.4. "Covered Software" 19 | means Source Code Form to which the initial Contributor has attached 20 | the notice in Exhibit A, the Executable Form of such Source Code 21 | Form, and Modifications of such Source Code Form, in each case 22 | including portions thereof. 23 | 24 | 1.5. "Incompatible With Secondary Licenses" 25 | means 26 | 27 | (a) that the initial Contributor has attached the notice described 28 | in Exhibit B to the Covered Software; or 29 | 30 | (b) that the Covered Software was made available under the terms of 31 | version 1.1 or earlier of the License, but not also under the 32 | terms of a Secondary License. 33 | 34 | 1.6. "Executable Form" 35 | means any form of the work other than Source Code Form. 36 | 37 | 1.7. "Larger Work" 38 | means a work that combines Covered Software with other material, in 39 | a separate file or files, that is not Covered Software. 40 | 41 | 1.8. "License" 42 | means this document. 43 | 44 | 1.9. "Licensable" 45 | means having the right to grant, to the maximum extent possible, 46 | whether at the time of the initial grant or subsequently, any and 47 | all of the rights conveyed by this License. 48 | 49 | 1.10. "Modifications" 50 | means any of the following: 51 | 52 | (a) any file in Source Code Form that results from an addition to, 53 | deletion from, or modification of the contents of Covered 54 | Software; or 55 | 56 | (b) any new file in Source Code Form that contains any Covered 57 | Software. 58 | 59 | 1.11. "Patent Claims" of a Contributor 60 | means any patent claim(s), including without limitation, method, 61 | process, and apparatus claims, in any patent Licensable by such 62 | Contributor that would be infringed, but for the grant of the 63 | License, by the making, using, selling, offering for sale, having 64 | made, import, or transfer of either its Contributions or its 65 | Contributor Version. 66 | 67 | 1.12. "Secondary License" 68 | means either the GNU General Public License, Version 2.0, the GNU 69 | Lesser General Public License, Version 2.1, the GNU Affero General 70 | Public License, Version 3.0, or any later versions of those 71 | licenses. 72 | 73 | 1.13. "Source Code Form" 74 | means the form of the work preferred for making modifications. 75 | 76 | 1.14. "You" (or "Your") 77 | means an individual or a legal entity exercising rights under this 78 | License. For legal entities, "You" includes any entity that 79 | controls, is controlled by, or is under common control with You. For 80 | purposes of this definition, "control" means (a) the power, direct 81 | or indirect, to cause the direction or management of such entity, 82 | whether by contract or otherwise, or (b) ownership of more than 83 | fifty percent (50%) of the outstanding shares or beneficial 84 | ownership of such entity. 85 | 86 | 2. License Grants and Conditions 87 | -------------------------------- 88 | 89 | 2.1. Grants 90 | 91 | Each Contributor hereby grants You a world-wide, royalty-free, 92 | non-exclusive license: 93 | 94 | (a) under intellectual property rights (other than patent or trademark) 95 | Licensable by such Contributor to use, reproduce, make available, 96 | modify, display, perform, distribute, and otherwise exploit its 97 | Contributions, either on an unmodified basis, with Modifications, or 98 | as part of a Larger Work; and 99 | 100 | (b) under Patent Claims of such Contributor to make, use, sell, offer 101 | for sale, have made, import, and otherwise transfer either its 102 | Contributions or its Contributor Version. 103 | 104 | 2.2. Effective Date 105 | 106 | The licenses granted in Section 2.1 with respect to any Contribution 107 | become effective for each Contribution on the date the Contributor first 108 | distributes such Contribution. 109 | 110 | 2.3. Limitations on Grant Scope 111 | 112 | The licenses granted in this Section 2 are the only rights granted under 113 | this License. No additional rights or licenses will be implied from the 114 | distribution or licensing of Covered Software under this License. 115 | Notwithstanding Section 2.1(b) above, no patent license is granted by a 116 | Contributor: 117 | 118 | (a) for any code that a Contributor has removed from Covered Software; 119 | or 120 | 121 | (b) for infringements caused by: (i) Your and any other third party's 122 | modifications of Covered Software, or (ii) the combination of its 123 | Contributions with other software (except as part of its Contributor 124 | Version); or 125 | 126 | (c) under Patent Claims infringed by Covered Software in the absence of 127 | its Contributions. 128 | 129 | This License does not grant any rights in the trademarks, service marks, 130 | or logos of any Contributor (except as may be necessary to comply with 131 | the notice requirements in Section 3.4). 132 | 133 | 2.4. Subsequent Licenses 134 | 135 | No Contributor makes additional grants as a result of Your choice to 136 | distribute the Covered Software under a subsequent version of this 137 | License (see Section 10.2) or under the terms of a Secondary License (if 138 | permitted under the terms of Section 3.3). 139 | 140 | 2.5. Representation 141 | 142 | Each Contributor represents that the Contributor believes its 143 | Contributions are its original creation(s) or it has sufficient rights 144 | to grant the rights to its Contributions conveyed by this License. 145 | 146 | 2.6. Fair Use 147 | 148 | This License is not intended to limit any rights You have under 149 | applicable copyright doctrines of fair use, fair dealing, or other 150 | equivalents. 151 | 152 | 2.7. Conditions 153 | 154 | Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted 155 | in Section 2.1. 156 | 157 | 3. Responsibilities 158 | ------------------- 159 | 160 | 3.1. Distribution of Source Form 161 | 162 | All distribution of Covered Software in Source Code Form, including any 163 | Modifications that You create or to which You contribute, must be under 164 | the terms of this License. You must inform recipients that the Source 165 | Code Form of the Covered Software is governed by the terms of this 166 | License, and how they can obtain a copy of this License. You may not 167 | attempt to alter or restrict the recipients' rights in the Source Code 168 | Form. 169 | 170 | 3.2. Distribution of Executable Form 171 | 172 | If You distribute Covered Software in Executable Form then: 173 | 174 | (a) such Covered Software must also be made available in Source Code 175 | Form, as described in Section 3.1, and You must inform recipients of 176 | the Executable Form how they can obtain a copy of such Source Code 177 | Form by reasonable means in a timely manner, at a charge no more 178 | than the cost of distribution to the recipient; and 179 | 180 | (b) You may distribute such Executable Form under the terms of this 181 | License, or sublicense it under different terms, provided that the 182 | license for the Executable Form does not attempt to limit or alter 183 | the recipients' rights in the Source Code Form under this License. 184 | 185 | 3.3. Distribution of a Larger Work 186 | 187 | You may create and distribute a Larger Work under terms of Your choice, 188 | provided that You also comply with the requirements of this License for 189 | the Covered Software. If the Larger Work is a combination of Covered 190 | Software with a work governed by one or more Secondary Licenses, and the 191 | Covered Software is not Incompatible With Secondary Licenses, this 192 | License permits You to additionally distribute such Covered Software 193 | under the terms of such Secondary License(s), so that the recipient of 194 | the Larger Work may, at their option, further distribute the Covered 195 | Software under the terms of either this License or such Secondary 196 | License(s). 197 | 198 | 3.4. Notices 199 | 200 | You may not remove or alter the substance of any license notices 201 | (including copyright notices, patent notices, disclaimers of warranty, 202 | or limitations of liability) contained within the Source Code Form of 203 | the Covered Software, except that You may alter any license notices to 204 | the extent required to remedy known factual inaccuracies. 205 | 206 | 3.5. Application of Additional Terms 207 | 208 | You may choose to offer, and to charge a fee for, warranty, support, 209 | indemnity or liability obligations to one or more recipients of Covered 210 | Software. However, You may do so only on Your own behalf, and not on 211 | behalf of any Contributor. You must make it absolutely clear that any 212 | such warranty, support, indemnity, or liability obligation is offered by 213 | You alone, and You hereby agree to indemnify every Contributor for any 214 | liability incurred by such Contributor as a result of warranty, support, 215 | indemnity or liability terms You offer. You may include additional 216 | disclaimers of warranty and limitations of liability specific to any 217 | jurisdiction. 218 | 219 | 4. Inability to Comply Due to Statute or Regulation 220 | --------------------------------------------------- 221 | 222 | If it is impossible for You to comply with any of the terms of this 223 | License with respect to some or all of the Covered Software due to 224 | statute, judicial order, or regulation then You must: (a) comply with 225 | the terms of this License to the maximum extent possible; and (b) 226 | describe the limitations and the code they affect. Such description must 227 | be placed in a text file included with all distributions of the Covered 228 | Software under this License. Except to the extent prohibited by statute 229 | or regulation, such description must be sufficiently detailed for a 230 | recipient of ordinary skill to be able to understand it. 231 | 232 | 5. Termination 233 | -------------- 234 | 235 | 5.1. The rights granted under this License will terminate automatically 236 | if You fail to comply with any of its terms. However, if You become 237 | compliant, then the rights granted under this License from a particular 238 | Contributor are reinstated (a) provisionally, unless and until such 239 | Contributor explicitly and finally terminates Your grants, and (b) on an 240 | ongoing basis, if such Contributor fails to notify You of the 241 | non-compliance by some reasonable means prior to 60 days after You have 242 | come back into compliance. Moreover, Your grants from a particular 243 | Contributor are reinstated on an ongoing basis if such Contributor 244 | notifies You of the non-compliance by some reasonable means, this is the 245 | first time You have received notice of non-compliance with this License 246 | from such Contributor, and You become compliant prior to 30 days after 247 | Your receipt of the notice. 248 | 249 | 5.2. If You initiate litigation against any entity by asserting a patent 250 | infringement claim (excluding declaratory judgment actions, 251 | counter-claims, and cross-claims) alleging that a Contributor Version 252 | directly or indirectly infringes any patent, then the rights granted to 253 | You by any and all Contributors for the Covered Software under Section 254 | 2.1 of this License shall terminate. 255 | 256 | 5.3. In the event of termination under Sections 5.1 or 5.2 above, all 257 | end user license agreements (excluding distributors and resellers) which 258 | have been validly granted by You or Your distributors under this License 259 | prior to termination shall survive termination. 260 | 261 | ************************************************************************ 262 | * * 263 | * 6. Disclaimer of Warranty * 264 | * ------------------------- * 265 | * * 266 | * Covered Software is provided under this License on an "as is" * 267 | * basis, without warranty of any kind, either expressed, implied, or * 268 | * statutory, including, without limitation, warranties that the * 269 | * Covered Software is free of defects, merchantable, fit for a * 270 | * particular purpose or non-infringing. The entire risk as to the * 271 | * quality and performance of the Covered Software is with You. * 272 | * Should any Covered Software prove defective in any respect, You * 273 | * (not any Contributor) assume the cost of any necessary servicing, * 274 | * repair, or correction. This disclaimer of warranty constitutes an * 275 | * essential part of this License. No use of any Covered Software is * 276 | * authorized under this License except under this disclaimer. * 277 | * * 278 | ************************************************************************ 279 | 280 | ************************************************************************ 281 | * * 282 | * 7. Limitation of Liability * 283 | * -------------------------- * 284 | * * 285 | * Under no circumstances and under no legal theory, whether tort * 286 | * (including negligence), contract, or otherwise, shall any * 287 | * Contributor, or anyone who distributes Covered Software as * 288 | * permitted above, be liable to You for any direct, indirect, * 289 | * special, incidental, or consequential damages of any character * 290 | * including, without limitation, damages for lost profits, loss of * 291 | * goodwill, work stoppage, computer failure or malfunction, or any * 292 | * and all other commercial damages or losses, even if such party * 293 | * shall have been informed of the possibility of such damages. This * 294 | * limitation of liability shall not apply to liability for death or * 295 | * personal injury resulting from such party's negligence to the * 296 | * extent applicable law prohibits such limitation. Some * 297 | * jurisdictions do not allow the exclusion or limitation of * 298 | * incidental or consequential damages, so this exclusion and * 299 | * limitation may not apply to You. * 300 | * * 301 | ************************************************************************ 302 | 303 | 8. Litigation 304 | ------------- 305 | 306 | Any litigation relating to this License may be brought only in the 307 | courts of a jurisdiction where the defendant maintains its principal 308 | place of business and such litigation shall be governed by laws of that 309 | jurisdiction, without reference to its conflict-of-law provisions. 310 | Nothing in this Section shall prevent a party's ability to bring 311 | cross-claims or counter-claims. 312 | 313 | 9. Miscellaneous 314 | ---------------- 315 | 316 | This License represents the complete agreement concerning the subject 317 | matter hereof. If any provision of this License is held to be 318 | unenforceable, such provision shall be reformed only to the extent 319 | necessary to make it enforceable. Any law or regulation which provides 320 | that the language of a contract shall be construed against the drafter 321 | shall not be used to construe this License against a Contributor. 322 | 323 | 10. Versions of the License 324 | --------------------------- 325 | 326 | 10.1. New Versions 327 | 328 | Mozilla Foundation is the license steward. Except as provided in Section 329 | 10.3, no one other than the license steward has the right to modify or 330 | publish new versions of this License. Each version will be given a 331 | distinguishing version number. 332 | 333 | 10.2. Effect of New Versions 334 | 335 | You may distribute the Covered Software under the terms of the version 336 | of the License under which You originally received the Covered Software, 337 | or under the terms of any subsequent version published by the license 338 | steward. 339 | 340 | 10.3. Modified Versions 341 | 342 | If you create software not governed by this License, and you want to 343 | create a new license for such software, you may create and use a 344 | modified version of this License if you rename the license and remove 345 | any references to the name of the license steward (except to note that 346 | such modified license differs from this License). 347 | 348 | 10.4. Distributing Source Code Form that is Incompatible With Secondary 349 | Licenses 350 | 351 | If You choose to distribute Source Code Form that is Incompatible With 352 | Secondary Licenses under the terms of this version of the License, the 353 | notice described in Exhibit B of this License must be attached. 354 | 355 | Exhibit A - Source Code Form License Notice 356 | ------------------------------------------- 357 | 358 | This Source Code Form is subject to the terms of the Mozilla Public 359 | License, v. 2.0. If a copy of the MPL was not distributed with this 360 | file, You can obtain one at http://mozilla.org/MPL/2.0/. 361 | 362 | If it is not possible or desirable to put the notice in a particular 363 | file, then You may include the notice in a location (such as a LICENSE 364 | file in a relevant directory) where a recipient would be likely to look 365 | for such a notice. 366 | 367 | You may add additional accurate notices of copyright ownership. 368 | 369 | Exhibit B - "Incompatible With Secondary Licenses" Notice 370 | --------------------------------------------------------- 371 | 372 | This Source Code Form is "Incompatible With Secondary Licenses", as 373 | defined by the Mozilla Public License, v. 2.0. 374 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 0x-Python 2 | 3 | 面向 Web 3 的撸毛,自动化脚本课程 4 | 5 | - [00-前期的准备工作](./00-前期的准备工作.md) 6 | - [01-数据结构](./01-数据结构.md) 7 | - [02-函数与流程控制](./02-函数与流程控制.md) 8 | - [03-模块的使用](./03-模块的使用.md) 9 | - [04-文件处理](./04-文件处理.md) 10 | - [05-第一阶段总结](./05-第一阶段总结.md) 11 | - [06-pandas](./06-pandas.md) 12 | - [07-Web3开发最小原子基础知识点](./07-Web3开发最小原子基础知识点.md) 13 | - [08-web3py](./08-web3py.md) 14 | - [09-PyAutoGUI](./09-PyAutoGUI.md) 15 | - [10-tampermonkey](./10-tampermonkey.md) 16 | - [11-区块浏览器](./11-区块浏览器.md) -------------------------------------------------------------------------------- /file.py: -------------------------------------------------------------------------------- 1 | import os 2 | import json 3 | import pandas 4 | 5 | # print(f'{__file__}') 6 | # print(f'{__doc__}') 7 | # print(f'{__name__}') 8 | 9 | # cur_path = os.path.dirname(__file__) 10 | 11 | # print(f'{cur_path}') 12 | 13 | # f = open('./test.json', 'r') 14 | # j = f.read() 15 | # f.close() 16 | 17 | # print(f'{j}') 18 | 19 | # t = json.loads(j) 20 | # name = t['name'] 21 | 22 | # print(f'{name}') 23 | 24 | # t['price'] = 12000 25 | 26 | # text = json.dumps(t) 27 | 28 | # w = open('./test.json', 'w') 29 | # w.write(text) 30 | # w.close() 31 | 32 | data = pandas.read_csv('./test.csv') 33 | 34 | print(f'{data.columns}') 35 | print(f'{data.head(10)}') 36 | -------------------------------------------------------------------------------- /hello.py: -------------------------------------------------------------------------------- 1 | print("Hello icepy.eth") 2 | 3 | cex_markets = {'BTC': 60000, 'ETH': 2400} 4 | dex_markets = [59888, 59990, 60200] 5 | 6 | def get_price(token_name): 7 | price = cex_markets[token_name] 8 | return price 9 | 10 | def arbitrage(price): 11 | spread = 0 12 | for tic in dex_markets: 13 | if tic < price: 14 | continue 15 | else: 16 | spread = tic - price 17 | break 18 | 19 | print(f'利差:{spread}') 20 | 21 | 22 | cex_price = get_price('BTC') 23 | arbitrage(cex_price) 24 | -------------------------------------------------------------------------------- /module.py: -------------------------------------------------------------------------------- 1 | import requests 2 | 3 | 4 | r = requests.get('https://api1.binance.com/api/v3/ticker/price?symbol=ETHUSDT') 5 | j = r.json() 6 | 7 | 8 | print(f'{j}') -------------------------------------------------------------------------------- /portfolio.py: -------------------------------------------------------------------------------- 1 | import requests 2 | 3 | def get_my_portfolio(): 4 | return {'BTC': 1, 'ETH': 10, 'SOL': 100} 5 | 6 | def statistics(): 7 | my_portfoli = get_my_portfolio() 8 | tickers = ['BTCUSDT', 'ETHUSDT', 'SOLUSDT'] 9 | portfolio = {'BTC': 0, 'ETH': 0, 'SOL': 0} 10 | 11 | for ticker in tickers: 12 | url = 'https://api1.binance.com/api/v3/ticker/price?symbol=' + ticker 13 | print(f'{url}') 14 | r = requests.get(url) 15 | j = r.json() 16 | price = float(j['price']) 17 | if ticker == 'BTCUSDT': 18 | btc = my_portfoli['BTC'] * price 19 | portfolio['BTC'] = btc 20 | elif ticker == 'ETHUSDT': 21 | eth = my_portfoli['ETH'] * price 22 | portfolio['ETH'] = eth 23 | else: 24 | sol = my_portfoli['SOL'] * price 25 | portfolio['SOL'] = sol 26 | 27 | print(f'{portfolio}') 28 | 29 | statistics() -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | certifi==2024.8.30 2 | charset-normalizer==3.3.2 3 | idna==3.10 4 | requests==2.32.3 5 | urllib3==2.2.3 6 | wheel @ file:///opt/homebrew/Cellar/python%403.12/3.12.5/libexec/wheel-0.44.0-py3-none-any.whl#sha256=8d8a590e50bda8422000110e90bc730ebfcd8363d2de80793ac819b7f252e97d 7 | -------------------------------------------------------------------------------- /scroll.py: -------------------------------------------------------------------------------- 1 | import pandas 2 | import numpy 3 | 4 | data = pandas.read_csv('./scrollMarks.csv') 5 | 6 | 7 | b = data['marks'].sum() 8 | c = data['marks'].median() 9 | 10 | # marks 的总量 11 | # print(f'{b}') 12 | 13 | # marks 的中位数 14 | # print(f'{c}') 15 | 16 | d = data[data['marks'] < c] 17 | 18 | # marks 小于中位数的地址 19 | # print(f'{d}') 20 | 21 | e = data[data['marks'] > c] 22 | # marks 大于中位数的地址 23 | # print(f'{e}') 24 | 25 | g = data[data['marks'] < 100] 26 | 27 | # marks 小于 100 的地址 28 | # print(f'{g}') 29 | 30 | h = data[data['marks'].map(lambda x: x > 100 and x < c)] 31 | # marks 大于 100 和小于中位数的地址 32 | print(f'{h}') -------------------------------------------------------------------------------- /sybil.py: -------------------------------------------------------------------------------- 1 | import pandas 2 | 3 | addresses = [ 4 | '0x00035ab46994cda43f150b2be16bb7ca423171c7' 5 | ] 6 | 7 | data = pandas.read_csv('./eliminatedSybilAttackers.csv') 8 | result = data['address'].isin(addresses) 9 | 10 | if result.any(): 11 | print('在女巫列表') 12 | else: 13 | print('不在女巫列表') -------------------------------------------------------------------------------- /test.csv: -------------------------------------------------------------------------------- 1 | key, value 2 | BTC, 60000 3 | ETH, 2250 -------------------------------------------------------------------------------- /test.json: -------------------------------------------------------------------------------- 1 | {"name": "BTC", "price": 12000} --------------------------------------------------------------------------------