fusorlabs-sdk 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,79 @@
1
+ node_modules/
2
+ .turbo/
3
+ # .next-* 也要盖住:NEXT_DIST_DIR 会另起 dist 目录(.next-probe / .next-dev …),
4
+ # 每个都带完整 standalone 产物(实测 835MB)。只写 .next/ 匹配不到它们。
5
+ .next/
6
+ **/.next-*/
7
+ dist/
8
+ out/
9
+ coverage/
10
+ *.tsbuildinfo
11
+
12
+ # Foundry
13
+ cache/
14
+ broadcast/
15
+ !broadcast/**/run-latest.json
16
+
17
+ # 环境变量
18
+ # ⚠️ `.env` 这一条只匹配**文件名恰好是 `.env`** 的,匹配不到 `.env.deploy`
19
+ # —— 而那个文件里放的是部署者私钥。所以下面用 `.env.*` 兜住所有变体,
20
+ # 再单独把 *.example 放出来(那些是要进版本库的模板)。
21
+ # 负向规则必须写在 `.env.*` 之后,否则会被后面的规则覆盖掉。
22
+ .env
23
+ .env.*
24
+ !.env.example
25
+ !.env.*.example
26
+
27
+ # 系统
28
+ .DS_Store
29
+ *.log
30
+
31
+ # SDD 工作区(临时产物,不入库)
32
+ .superpowers/
33
+ out/
34
+ out-v4/
35
+ out-fork/
36
+ # 每个 foundry profile 一个产物目录(见 packages/contracts/foundry.toml 的注释:
37
+ # 刻意分开,避免两棵源码树的同名 artifact 互相覆盖)
38
+ out-fusor/
39
+ out-fusor-v4/
40
+ out-split/
41
+ out-deploy/
42
+ cache/
43
+ .image-cache/
44
+ packages/contracts/lib/
45
+
46
+ # Python SDK
47
+ __pycache__/
48
+ *.py[cod]
49
+ .pytest_cache/
50
+ *.egg-info/
51
+
52
+ # ── 部署记录必须进版本库(这几条要放在**最后**)──
53
+ # .gitignore 里有两条 `out/`(第 5、30 行),而 `out/` 匹配任何层级名叫 out 的目录,
54
+ # 于是 packages/contracts/deploy/out/ 被连带忽略。那里放的是部署记录
55
+ # (oracle-registry.json 是阶段 1 的 stockRegistry 来源,launchpad.json 是 SDK 的输入),
56
+ # 丢了等于丢掉「我们部署在哪」这个事实。
57
+ # 负向规则必须写在所有 `out/` 之后,否则会被后面的规则重新盖掉(踩过)。
58
+ # 目录本身要先放出来,不然 git 根本不会往里走。
59
+ !packages/contracts/deploy/out/
60
+ !packages/contracts/deploy/out/*.json
61
+ # 但 fork 演练产生的临时记录不要进
62
+ packages/contracts/deploy/out/*.anvil.json
63
+
64
+ # 部署密钥:绝不进版本库,也绝不进构建上下文
65
+ secrets/
66
+ deploy.env
67
+
68
+ # 备份集:scripts/backup.sh 的产物。单次就有 190MB+
69
+ # (postgres.dump + images.tar.gz + caddy-data.tar.gz),而且里面有库的全量数据
70
+ # 与 TLS 私钥 —— 既不能进版本库,也不能进构建上下文(.dockerignore 同理)。
71
+ # 异地存放的做法见 docs/ops/ingress-and-backup.md。
72
+ backups/
73
+ .vercel
74
+ .env*.local
75
+
76
+ # 发布凭据(npm / PyPI token)。放在仓库内本来就不该,但如果放了,
77
+ # 至少不能被提交。发布完请立刻删除 —— 见 PROGRESS.md 的「发布」一节。
78
+ sdks/.publish-npmrc
79
+ sdks/.publish-pypirc
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Fusor Labs
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE, OR IN CONNECTION WITH THE SOFTWARE
21
+ OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,203 @@
1
+ Metadata-Version: 2.5
2
+ Name: fusorlabs-sdk
3
+ Version: 0.1.0
4
+ Summary: One-line token launches on Fusor — bring your own private key
5
+ Project-URL: Homepage, https://fusor.fun/docs
6
+ Author: Fusor Labs
7
+ License: MIT
8
+ License-File: LICENSE
9
+ Keywords: evm,fusor,launch,token,web3
10
+ Requires-Python: >=3.11
11
+ Requires-Dist: web3<8,>=7
12
+ Provides-Extra: dev
13
+ Requires-Dist: pytest>=8; extra == 'dev'
14
+ Description-Content-Type: text/markdown
15
+
16
+ # fusorlabs-sdk
17
+
18
+ One-line token launches on Fusor. Bring your own private key.
19
+
20
+ ```bash
21
+ pip install fusorlabs-sdk
22
+ ```
23
+
24
+ Requires Python 3.11+.
25
+
26
+ ## 一行发币
27
+
28
+ ```python
29
+ import os
30
+ from fusor import FusorClient
31
+
32
+ fusor = FusorClient(
33
+ private_key=os.environ["PRIVATE_KEY"],
34
+ )
35
+
36
+ result = fusor.launch_token(
37
+ name="My Token",
38
+ symbol="MTK",
39
+ markets=["AAPL"],
40
+ metadata_uri="https://example.com/metadata.json",
41
+ )
42
+ print(result.token_address, result.explorer_url)
43
+ ```
44
+
45
+ 这一次调用内部完成 7 步:链上前置检查 → 解析并校验报价市场 → 预言机新鲜度 →
46
+ 元数据 → 构造参数 → 模拟 → 签名发送并等回执。
47
+
48
+ ## 先试一下,不花钱
49
+
50
+ ```python
51
+ preview = fusor.launch_token(..., dry_run=True)
52
+ print(preview.token_address) # 预测地址
53
+ print(preview.estimated_gas)
54
+ print(preview.launch_fee_wei) # 实读的发射费
55
+ print(preview.params) # 实际会编码的参数
56
+ ```
57
+
58
+ `dry_run` 停在模拟:参数错、市场没启用、预言机陈旧都会在这里报出来,一笔交易都不发。
59
+
60
+ ⚠️ `dry_run` 返回的 `token_address` 是**预测**地址(按 launchpad 当前 nonce 算的
61
+ CREATE 地址)。真发时如果有别人抢先落一笔,实际地址会不同 —— 所以不要拿它去预注册。
62
+ 真发时 `token_address` 来自回执的 `MultiPairLaunchCreated` 事件,是权威值。
63
+
64
+ ## 报价市场
65
+
66
+ 1 到 5 个。可以混用符号与地址:
67
+
68
+ ```python
69
+ markets=["AAPL"] # 单个 → 100%
70
+ markets=["AAPL", "TSLA"] # 两个 → 各 50%
71
+ markets=["AAPL", "TSLA", "NVDA"] # 三个 → 3334/3333/3333
72
+ markets=[("AAPL", 6000), ("0xaf3d…", 4000)] # 显式权重,必须合计 10000
73
+ ```
74
+
75
+ 不给权重就按数量均分(余数加在第一个上,保证合计精确等于 10000 —— 3333×3 = 9999
76
+ 会 revert `WeightsNotOneHundredPercent`)。要么全部给权重,要么全部不给,混用会报错。
77
+
78
+ 看有哪些符号可用:
79
+
80
+ ```python
81
+ fusor.list_quote_markets() # (QuoteAsset(symbol='AAPL', token='0xaf3d…', decimals=18), …)
82
+ ```
83
+
84
+ 符号表是内置的(股票代币注册表没有枚举接口,链上问不出来)。传地址则完全不依赖这张
85
+ 表 —— 每个地址都会实读 `registry.getConfig()` 校验 `enabled` / `decimals`。
86
+
87
+ ## 元数据
88
+
89
+ 两条路径。**传 `metadata_uri` 时 SDK 一次 HTTP 请求都不发**,只需要一个 RPC:
90
+
91
+ ```python
92
+ fusor.launch_token(..., metadata_uri="https://example.com/metadata.json")
93
+ ```
94
+
95
+ 或者让 SDK 上传(需要配 `api_base_url`):
96
+
97
+ ```python
98
+ from fusor import TokenMetadata
99
+
100
+ fusor = FusorClient(private_key=..., launchpad=..., api_base_url="https://api.example.com")
101
+
102
+ fusor.launch_token(
103
+ name="My Token",
104
+ symbol="MTK",
105
+ markets=["AAPL"],
106
+ metadata=TokenMetadata(
107
+ description="…",
108
+ image="data:image/png;base64,…", # 或一个已能公开访问的 http(s) URL
109
+ twitter="https://x.com/…",
110
+ website="https://…",
111
+ ),
112
+ )
113
+ ```
114
+
115
+ `metadata_hash` 是那段规范 JSON 字节的 keccak256(算的是我们提交的内容,不是服务端
116
+ 回给我们的哈希),所以链上的哈希永远对应实际提交的元数据。**规范 JSON 与 TS
117
+ 两个 SDK 逐字节一致** —— 同一份元数据在三个语言里得到同一个哈希。
118
+
119
+ ## 配置
120
+
121
+ ```python
122
+ FusorClient(
123
+ private_key="0x…", # 或 account=任意 eth_account LocalAccount(KMS / 硬件)
124
+ launchpad="0x…", # 部署脚本产出折进 SDK 后可省略
125
+ chain_id=4663, # 默认 Robinhood Chain
126
+ rpc_url="https://…", # 覆盖默认 RPC(公共 RPC 有限流)
127
+ rpc_headers={...}, # 有的提供商用请求头鉴权
128
+ api_base_url="https://…",# 只有让 SDK 上传元数据时才需要
129
+ )
130
+ ```
131
+
132
+ `launchpad` **可以省略**(2026-09-06 起)—— 部署记录已经进了 spec 的 `deployments`,
133
+ SDK 会按 `chain_id` 自动取。显式传入仍然优先,用于指向另一套部署。
134
+
135
+ 如果某条链在 spec 里没有部署记录,SDK 会**报错要求你显式传**,而不是去猜 ——
136
+ 更不会退回到别人的部署上。同一条链上就有别人的 launchpad,猜错的后果是把币
137
+ 发到不属于我们的合约里,而且不会有任何报错。
138
+
139
+ ## 错误处理
140
+
141
+ 失败会解成 32 个链上 custom error 之一。用 `error_name` 做程序化分支,**不要匹配文案**:
142
+
143
+ ```python
144
+ from fusor import FusorConfigError, FusorPreflightError, FusorLaunchError
145
+
146
+ try:
147
+ fusor.launch_token(...)
148
+ except FusorConfigError:
149
+ pass # 参数问题,一个请求都没发出去
150
+ except FusorPreflightError as err:
151
+ pass # 链上前置条件不满足,交易从未发出(预言机陈旧、市场没启用…)
152
+ except FusorLaunchError as err:
153
+ if err.error_name == "StaleOracle":
154
+ pass # 等 keeper 更新后重试
155
+ ```
156
+
157
+ 各语言 SDK 共用同一份错误文案,所以同一次 revert 在 TS 与 Python 里得到
158
+ 完全一样的报错。
159
+
160
+ ## 自己编排(KMS / 多签)
161
+
162
+ 每一步都单独导出,需要把交易交给外部签名器时可以自己拼:
163
+
164
+ ```python
165
+ from fusor import preflight, resolve_markets, build_launch_params, simulate_launch, token_address_from_receipt
166
+
167
+ pre = preflight(w3, launchpad)
168
+ markets = resolve_markets(w3, pre.stock_registry, ["AAPL"])
169
+ params = build_launch_params(..., markets=markets, creator=addr, deadline=...)
170
+ sim = simulate_launch(w3, launchpad=launchpad, account=addr, params=params, launch_fee_wei=pre.launch_fee_wei)
171
+ # → 自己构造并签名交易,回执用 token_address_from_receipt 解析
172
+ ```
173
+
174
+ ## 第一期不支持 developer buy
175
+
176
+ 发币同时用自己的钱买入(dev buy)需要移植定点 bonding-curve 数学并保证三个语言逐 wei
177
+ 一致,第一期不做。不带 dev buy 时发币是**单笔交易**。
178
+
179
+ ## 设计说明
180
+
181
+ `launch_fee_wei` 与 `max_oracle_age` 是**部署期参数**,SDK 每次实读,不当常量。
182
+ 实现地址也**不 pin** —— 代理会升级,pin 地址会让所有用户在升级那一刻同时失效;
183
+ SDK 改成扫实现字节码的 PUSH4 选择器做行为校验。
184
+
185
+ 完整设计记录见仓库的 `sdks/README.md`。
186
+
187
+ ## 测试
188
+
189
+ ```bash
190
+ python -m venv .venv && .venv/bin/pip install -e '.[dev]'
191
+ .venv/bin/python -m pytest # 离线单测
192
+ .venv/bin/python -m pytest tests_integration # 对主网发**只读** RPC
193
+ ```
194
+
195
+ 两者刻意分开:`pyproject.toml` 的 `testpaths` 只指向 `tests`,所以集成测试默认
196
+ 不跑。它验证的是「SDK 内置的 spec 与我们**实际部署**的合约一致」—— 这类问题
197
+ 不会让任何离线测试变红。
198
+
199
+ 集成测试只发 `eth_call` / `eth_getCode`,**不发交易、不花钱**。传输层错误
200
+ (限流、超时)一律 skip 而不是 fail —— 那说明的是端点状况,不是代码问题。
201
+
202
+ 可选:`FUSOR_RPC_URL` 换 RPC;`FUSOR_IT_FULL_SWEEP=1` 核对全部 60 个报价资产
203
+ (默认只抽查 5 个,避免把公共 RPC 打到限流)。
@@ -0,0 +1,188 @@
1
+ # fusorlabs-sdk
2
+
3
+ One-line token launches on Fusor. Bring your own private key.
4
+
5
+ ```bash
6
+ pip install fusorlabs-sdk
7
+ ```
8
+
9
+ Requires Python 3.11+.
10
+
11
+ ## 一行发币
12
+
13
+ ```python
14
+ import os
15
+ from fusor import FusorClient
16
+
17
+ fusor = FusorClient(
18
+ private_key=os.environ["PRIVATE_KEY"],
19
+ )
20
+
21
+ result = fusor.launch_token(
22
+ name="My Token",
23
+ symbol="MTK",
24
+ markets=["AAPL"],
25
+ metadata_uri="https://example.com/metadata.json",
26
+ )
27
+ print(result.token_address, result.explorer_url)
28
+ ```
29
+
30
+ 这一次调用内部完成 7 步:链上前置检查 → 解析并校验报价市场 → 预言机新鲜度 →
31
+ 元数据 → 构造参数 → 模拟 → 签名发送并等回执。
32
+
33
+ ## 先试一下,不花钱
34
+
35
+ ```python
36
+ preview = fusor.launch_token(..., dry_run=True)
37
+ print(preview.token_address) # 预测地址
38
+ print(preview.estimated_gas)
39
+ print(preview.launch_fee_wei) # 实读的发射费
40
+ print(preview.params) # 实际会编码的参数
41
+ ```
42
+
43
+ `dry_run` 停在模拟:参数错、市场没启用、预言机陈旧都会在这里报出来,一笔交易都不发。
44
+
45
+ ⚠️ `dry_run` 返回的 `token_address` 是**预测**地址(按 launchpad 当前 nonce 算的
46
+ CREATE 地址)。真发时如果有别人抢先落一笔,实际地址会不同 —— 所以不要拿它去预注册。
47
+ 真发时 `token_address` 来自回执的 `MultiPairLaunchCreated` 事件,是权威值。
48
+
49
+ ## 报价市场
50
+
51
+ 1 到 5 个。可以混用符号与地址:
52
+
53
+ ```python
54
+ markets=["AAPL"] # 单个 → 100%
55
+ markets=["AAPL", "TSLA"] # 两个 → 各 50%
56
+ markets=["AAPL", "TSLA", "NVDA"] # 三个 → 3334/3333/3333
57
+ markets=[("AAPL", 6000), ("0xaf3d…", 4000)] # 显式权重,必须合计 10000
58
+ ```
59
+
60
+ 不给权重就按数量均分(余数加在第一个上,保证合计精确等于 10000 —— 3333×3 = 9999
61
+ 会 revert `WeightsNotOneHundredPercent`)。要么全部给权重,要么全部不给,混用会报错。
62
+
63
+ 看有哪些符号可用:
64
+
65
+ ```python
66
+ fusor.list_quote_markets() # (QuoteAsset(symbol='AAPL', token='0xaf3d…', decimals=18), …)
67
+ ```
68
+
69
+ 符号表是内置的(股票代币注册表没有枚举接口,链上问不出来)。传地址则完全不依赖这张
70
+ 表 —— 每个地址都会实读 `registry.getConfig()` 校验 `enabled` / `decimals`。
71
+
72
+ ## 元数据
73
+
74
+ 两条路径。**传 `metadata_uri` 时 SDK 一次 HTTP 请求都不发**,只需要一个 RPC:
75
+
76
+ ```python
77
+ fusor.launch_token(..., metadata_uri="https://example.com/metadata.json")
78
+ ```
79
+
80
+ 或者让 SDK 上传(需要配 `api_base_url`):
81
+
82
+ ```python
83
+ from fusor import TokenMetadata
84
+
85
+ fusor = FusorClient(private_key=..., launchpad=..., api_base_url="https://api.example.com")
86
+
87
+ fusor.launch_token(
88
+ name="My Token",
89
+ symbol="MTK",
90
+ markets=["AAPL"],
91
+ metadata=TokenMetadata(
92
+ description="…",
93
+ image="data:image/png;base64,…", # 或一个已能公开访问的 http(s) URL
94
+ twitter="https://x.com/…",
95
+ website="https://…",
96
+ ),
97
+ )
98
+ ```
99
+
100
+ `metadata_hash` 是那段规范 JSON 字节的 keccak256(算的是我们提交的内容,不是服务端
101
+ 回给我们的哈希),所以链上的哈希永远对应实际提交的元数据。**规范 JSON 与 TS
102
+ 两个 SDK 逐字节一致** —— 同一份元数据在三个语言里得到同一个哈希。
103
+
104
+ ## 配置
105
+
106
+ ```python
107
+ FusorClient(
108
+ private_key="0x…", # 或 account=任意 eth_account LocalAccount(KMS / 硬件)
109
+ launchpad="0x…", # 部署脚本产出折进 SDK 后可省略
110
+ chain_id=4663, # 默认 Robinhood Chain
111
+ rpc_url="https://…", # 覆盖默认 RPC(公共 RPC 有限流)
112
+ rpc_headers={...}, # 有的提供商用请求头鉴权
113
+ api_base_url="https://…",# 只有让 SDK 上传元数据时才需要
114
+ )
115
+ ```
116
+
117
+ `launchpad` **可以省略**(2026-09-06 起)—— 部署记录已经进了 spec 的 `deployments`,
118
+ SDK 会按 `chain_id` 自动取。显式传入仍然优先,用于指向另一套部署。
119
+
120
+ 如果某条链在 spec 里没有部署记录,SDK 会**报错要求你显式传**,而不是去猜 ——
121
+ 更不会退回到别人的部署上。同一条链上就有别人的 launchpad,猜错的后果是把币
122
+ 发到不属于我们的合约里,而且不会有任何报错。
123
+
124
+ ## 错误处理
125
+
126
+ 失败会解成 32 个链上 custom error 之一。用 `error_name` 做程序化分支,**不要匹配文案**:
127
+
128
+ ```python
129
+ from fusor import FusorConfigError, FusorPreflightError, FusorLaunchError
130
+
131
+ try:
132
+ fusor.launch_token(...)
133
+ except FusorConfigError:
134
+ pass # 参数问题,一个请求都没发出去
135
+ except FusorPreflightError as err:
136
+ pass # 链上前置条件不满足,交易从未发出(预言机陈旧、市场没启用…)
137
+ except FusorLaunchError as err:
138
+ if err.error_name == "StaleOracle":
139
+ pass # 等 keeper 更新后重试
140
+ ```
141
+
142
+ 各语言 SDK 共用同一份错误文案,所以同一次 revert 在 TS 与 Python 里得到
143
+ 完全一样的报错。
144
+
145
+ ## 自己编排(KMS / 多签)
146
+
147
+ 每一步都单独导出,需要把交易交给外部签名器时可以自己拼:
148
+
149
+ ```python
150
+ from fusor import preflight, resolve_markets, build_launch_params, simulate_launch, token_address_from_receipt
151
+
152
+ pre = preflight(w3, launchpad)
153
+ markets = resolve_markets(w3, pre.stock_registry, ["AAPL"])
154
+ params = build_launch_params(..., markets=markets, creator=addr, deadline=...)
155
+ sim = simulate_launch(w3, launchpad=launchpad, account=addr, params=params, launch_fee_wei=pre.launch_fee_wei)
156
+ # → 自己构造并签名交易,回执用 token_address_from_receipt 解析
157
+ ```
158
+
159
+ ## 第一期不支持 developer buy
160
+
161
+ 发币同时用自己的钱买入(dev buy)需要移植定点 bonding-curve 数学并保证三个语言逐 wei
162
+ 一致,第一期不做。不带 dev buy 时发币是**单笔交易**。
163
+
164
+ ## 设计说明
165
+
166
+ `launch_fee_wei` 与 `max_oracle_age` 是**部署期参数**,SDK 每次实读,不当常量。
167
+ 实现地址也**不 pin** —— 代理会升级,pin 地址会让所有用户在升级那一刻同时失效;
168
+ SDK 改成扫实现字节码的 PUSH4 选择器做行为校验。
169
+
170
+ 完整设计记录见仓库的 `sdks/README.md`。
171
+
172
+ ## 测试
173
+
174
+ ```bash
175
+ python -m venv .venv && .venv/bin/pip install -e '.[dev]'
176
+ .venv/bin/python -m pytest # 离线单测
177
+ .venv/bin/python -m pytest tests_integration # 对主网发**只读** RPC
178
+ ```
179
+
180
+ 两者刻意分开:`pyproject.toml` 的 `testpaths` 只指向 `tests`,所以集成测试默认
181
+ 不跑。它验证的是「SDK 内置的 spec 与我们**实际部署**的合约一致」—— 这类问题
182
+ 不会让任何离线测试变红。
183
+
184
+ 集成测试只发 `eth_call` / `eth_getCode`,**不发交易、不花钱**。传输层错误
185
+ (限流、超时)一律 skip 而不是 fail —— 那说明的是端点状况,不是代码问题。
186
+
187
+ 可选:`FUSOR_RPC_URL` 换 RPC;`FUSOR_IT_FULL_SWEEP=1` 核对全部 60 个报价资产
188
+ (默认只抽查 5 个,避免把公共 RPC 打到限流)。
@@ -0,0 +1,112 @@
1
+ """``fusor`` —— 一行发币。
2
+
3
+ .. code-block:: python
4
+
5
+ import os
6
+ from fusor import FusorClient
7
+
8
+ fusor = FusorClient(private_key=os.environ["PRIVATE_KEY"], launchpad="0x…")
9
+ result = fusor.launch_token(
10
+ name="My Token",
11
+ symbol="MTK",
12
+ markets=["AAPL"],
13
+ metadata_uri="https://example.com/metadata.json",
14
+ )
15
+ print(result.token_address, result.explorer_url)
16
+
17
+ 高层就 ``FusorClient`` 一个类。下面还导出了每一步的独立函数
18
+ (``preflight``、``resolve_markets``、``build_launch_params``…),给需要自己
19
+ 编排的用法 —— 比如把交易交给 KMS 或多签去签。
20
+ """
21
+
22
+ from .client import DEFAULT_CHAIN_ID, DEFAULT_DEADLINE_SECONDS, FusorClient, LaunchResult
23
+ from .errors import (
24
+ FusorConfigError,
25
+ FusorError,
26
+ FusorLaunchError,
27
+ FusorPreflightError,
28
+ decode_launch_error,
29
+ )
30
+ from .launch import (
31
+ LegacyLaunchParams,
32
+ SimulatedLaunch,
33
+ build_launch_params,
34
+ simulate_launch,
35
+ token_address_from_receipt,
36
+ )
37
+ from .markets import (
38
+ MarketInput,
39
+ ResolvedMarket,
40
+ decode_bytes32_symbol,
41
+ normalize_markets,
42
+ resolve_markets,
43
+ )
44
+ from .metadata import (
45
+ ResolvedMetadata,
46
+ TokenMetadata,
47
+ canonical_metadata_json,
48
+ hash_metadata,
49
+ resolve_metadata,
50
+ )
51
+ from .oracle import PriceReading, check_oracle_freshness, classify_price_reading
52
+ from .preflight import Preflight, onchain_selectors, preflight
53
+ from .spec import (
54
+ CHAINS,
55
+ CONSTANTS,
56
+ DEPLOYMENTS,
57
+ ERROR_MESSAGES,
58
+ FEED_ABI,
59
+ LAUNCH_SELECTOR,
60
+ LAUNCHPAD_ABI,
61
+ QUOTE_ASSETS,
62
+ REGISTRY_ABI,
63
+ QuoteAsset,
64
+ quote_asset_by_symbol,
65
+ )
66
+
67
+ __version__ = "0.1.0"
68
+
69
+ __all__ = [
70
+ "FusorClient",
71
+ "LaunchResult",
72
+ "DEFAULT_CHAIN_ID",
73
+ "DEFAULT_DEADLINE_SECONDS",
74
+ "FusorError",
75
+ "FusorConfigError",
76
+ "FusorPreflightError",
77
+ "FusorLaunchError",
78
+ "decode_launch_error",
79
+ "Preflight",
80
+ "preflight",
81
+ "onchain_selectors",
82
+ "MarketInput",
83
+ "ResolvedMarket",
84
+ "resolve_markets",
85
+ "normalize_markets",
86
+ "decode_bytes32_symbol",
87
+ "PriceReading",
88
+ "check_oracle_freshness",
89
+ "classify_price_reading",
90
+ "TokenMetadata",
91
+ "ResolvedMetadata",
92
+ "resolve_metadata",
93
+ "canonical_metadata_json",
94
+ "hash_metadata",
95
+ "LegacyLaunchParams",
96
+ "SimulatedLaunch",
97
+ "build_launch_params",
98
+ "simulate_launch",
99
+ "token_address_from_receipt",
100
+ "CONSTANTS",
101
+ "CHAINS",
102
+ "DEPLOYMENTS",
103
+ "QUOTE_ASSETS",
104
+ "QuoteAsset",
105
+ "quote_asset_by_symbol",
106
+ "LAUNCH_SELECTOR",
107
+ "LAUNCHPAD_ABI",
108
+ "REGISTRY_ABI",
109
+ "FEED_ABI",
110
+ "ERROR_MESSAGES",
111
+ "__version__",
112
+ ]