poly-web3 1.0.1__tar.gz → 1.0.2__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.
Files changed (26) hide show
  1. {poly_web3-1.0.1 → poly_web3-1.0.2}/PKG-INFO +92 -22
  2. {poly_web3-1.0.1 → poly_web3-1.0.2}/README.md +91 -21
  3. poly_web3-1.0.2/examples/example_split_merge.py +56 -0
  4. {poly_web3-1.0.1 → poly_web3-1.0.2}/poly_web3/const.py +65 -1
  5. {poly_web3-1.0.1 → poly_web3-1.0.2}/poly_web3/web3_service/base.py +110 -1
  6. poly_web3-1.0.2/poly_web3/web3_service/eoa_service.py +40 -0
  7. {poly_web3-1.0.1 → poly_web3-1.0.2}/poly_web3/web3_service/proxy_service.py +9 -4
  8. {poly_web3-1.0.1 → poly_web3-1.0.2}/poly_web3/web3_service/safe_service.py +7 -2
  9. {poly_web3-1.0.1 → poly_web3-1.0.2}/poly_web3.egg-info/PKG-INFO +92 -22
  10. {poly_web3-1.0.1 → poly_web3-1.0.2}/poly_web3.egg-info/SOURCES.txt +1 -0
  11. {poly_web3-1.0.1 → poly_web3-1.0.2}/pyproject.toml +1 -1
  12. poly_web3-1.0.1/poly_web3/web3_service/eoa_service.py +0 -19
  13. {poly_web3-1.0.1 → poly_web3-1.0.2}/examples/example_redeem.py +0 -0
  14. {poly_web3-1.0.1 → poly_web3-1.0.2}/poly_web3/__init__.py +0 -0
  15. {poly_web3-1.0.1 → poly_web3-1.0.2}/poly_web3/log.py +0 -0
  16. {poly_web3-1.0.1 → poly_web3-1.0.2}/poly_web3/schema.py +0 -0
  17. {poly_web3-1.0.1 → poly_web3-1.0.2}/poly_web3/signature/__init__.py +0 -0
  18. {poly_web3-1.0.1 → poly_web3-1.0.2}/poly_web3/signature/build.py +0 -0
  19. {poly_web3-1.0.1 → poly_web3-1.0.2}/poly_web3/signature/hash_message.py +0 -0
  20. {poly_web3-1.0.1 → poly_web3-1.0.2}/poly_web3/signature/secp256k1.py +0 -0
  21. {poly_web3-1.0.1 → poly_web3-1.0.2}/poly_web3/web3_service/__init__.py +0 -0
  22. {poly_web3-1.0.1 → poly_web3-1.0.2}/poly_web3.egg-info/dependency_links.txt +0 -0
  23. {poly_web3-1.0.1 → poly_web3-1.0.2}/poly_web3.egg-info/requires.txt +0 -0
  24. {poly_web3-1.0.1 → poly_web3-1.0.2}/poly_web3.egg-info/top_level.txt +0 -0
  25. {poly_web3-1.0.1 → poly_web3-1.0.2}/setup.cfg +0 -0
  26. {poly_web3-1.0.1 → poly_web3-1.0.2}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: poly-web3
3
- Version: 1.0.1
3
+ Version: 1.0.2
4
4
  Summary: Polymarket Proxy wallet redeem SDK - Execute redeem operations on Polymarket using proxy wallets
5
5
  Home-page: https://github.com/tosmart01/poly-web3
6
6
  Author: PinBar
@@ -27,11 +27,16 @@ Dynamic: requires-python
27
27
 
28
28
  # poly-web3
29
29
 
30
- Python SDK for redeeming Polymarket positions via Proxy/Safe wallets (gas-free).
30
+ ![PyPI](https://img.shields.io/pypi/v/poly-web3)
31
+ ![Python](https://img.shields.io/pypi/pyversions/poly-web3)
32
+ ![License](https://img.shields.io/github/license/tosmart01/poly-web3)
33
+
34
+ Python SDK for redeeming and splitting/merging Polymarket positions via Proxy/Safe wallets (gas-free).
31
35
 
32
36
  [English](README.md) | [中文](README.zh.md)
33
37
 
34
38
  ```bash
39
+ Python >= 3.11
35
40
  pip install poly-web3
36
41
  ```
37
42
 
@@ -44,7 +49,11 @@ service = PolyWeb3Service(
44
49
  )
45
50
 
46
51
  # Redeem all redeemable positions for the current account.
47
- service.redeem_all(batch_size=20)
52
+ service.redeem_all(batch_size=10)
53
+
54
+ # Split/Merge for binary markets (amount in human USDC units).
55
+ service.split("0x...", 10)
56
+ service.merge("0x...", 10)
48
57
  ```
49
58
 
50
59
  [See the full example](#quick-start)
@@ -54,18 +63,25 @@ service.redeem_all(batch_size=20)
54
63
  - Redeemable positions are fetched via the official Positions API, which typically has ~1 minute latency.
55
64
  - `redeem_all` returns an empty list if there are no redeemable positions. If the returned list contains `None`, the redeem failed and should be retried.
56
65
 
57
- ## Troubleshooting
66
+ ## Split/Merge Notes
67
+
68
+ - `split`/`merge` are designed for binary markets (Yes/No) and use the default partition internally.
69
+ - `amount` is in human units (USDC), and is converted to base units internally.
70
+
71
+ ## FAQ
58
72
 
59
73
  1. **UI shows redeemable, but `redeem_all` returns `[]`**: The official Positions API can be delayed by 1–3 minutes. Wait a bit and retry.
60
74
  2. **RPC error during redeem**: Switch RPC endpoints by setting `rpc_url` when instantiating `PolyWeb3Service`.
61
75
  3. **Redeem stuck in `execute`**: The official relayer may be congested. Stop redeeming for 1 hour to avoid nonce looping from repeated submissions.
76
+ 4. **Relayer client returns 403**: You need to apply for Builder API access and use a valid key. Reference: Polymarket Builders — Introduction: https://docs.polymarket.com/developers/builders/builder-intro
77
+ 5. **Relayer daily limit**: The official relayer typically limits to 100 requests per day. Prefer batch redeem (`batch_size`) to reduce the number of requests and avoid hitting the limit.
62
78
 
63
79
  ## About the Project
64
80
 
65
81
  This project is a Python rewrite of Polymarket's official TypeScript implementation of `builder-relayer-client`, designed to provide Python developers with a convenient tool for executing Proxy and Safe wallet redeem operations on Polymarket.
66
82
 
67
83
  **Important Notes:**
68
- - This project **only implements the official redeem functionality**, focusing on Conditional Token Fund (CTF) redeem operations
84
+ - This project implements official CTF redeem plus binary split/merge operations
69
85
  - Other features (such as trading, order placement, etc.) are not within the scope of this project
70
86
 
71
87
  **Some Polymarket-related redeem or write operations implemented in this project depend on access granted through Polymarket's Builder program. To perform real redeem operations against Polymarket, you must apply for and obtain a Builder key/credentials via Polymarket's official Builder application process. After approval you will receive the credentials required to use the Builder API—only then will the redeem flows in this repository work against the live service. For local development or automated tests, use mocks or testnet setups instead of real keys to avoid exposing production credentials.**
@@ -74,8 +90,8 @@ Reference:
74
90
  - Polymarket Builders — Introduction: https://docs.polymarket.com/developers/builders/builder-intro
75
91
 
76
92
  **Current Status:**
77
- - ✅ **Proxy Wallet** - Fully supported for redeem functionality
78
- - ✅ **Safe Wallet** - Fully supported for redeem functionality
93
+ - ✅ **Proxy Wallet** - Fully supported for redeem/split/merge
94
+ - ✅ **Safe Wallet** - Fully supported for redeem/split/merge
79
95
  - 🚧 **EOA Wallet** - Under development
80
96
 
81
97
  We welcome community contributions! If you'd like to help implement EOA wallet redeem functionality, or have other improvement suggestions, please feel free to submit a Pull Request.
@@ -153,21 +169,41 @@ service = PolyWeb3Service(
153
169
  )
154
170
 
155
171
 
172
+ # Redeem all positions that are currently redeemable
173
+ redeem_all_result = service.redeem_all(batch_size=10)
174
+ print(f"Redeem all result: {redeem_all_result}")
175
+ # If redeem_all_result contains None, refer to README FAQ and retry.
176
+ if redeem_all_result and any(item is None for item in redeem_all_result):
177
+ print("Redeem failed for some items; please retry.")
178
+
156
179
  # Execute redeem operation (batch)
157
180
  condition_ids = [
158
181
  "0xc3df016175463c44f9c9f98bddaa3bf3daaabb14b069fb7869621cffe73ddd1c",
159
182
  "0x31fb435a9506d14f00b9de5e5e4491cf2223b6d40a2525d9afa8b620b61b50e2",
160
183
  ]
161
- redeem_batch_result = service.redeem(condition_ids, batch_size=20)
184
+ redeem_batch_result = service.redeem(condition_ids, batch_size=10)
162
185
  print(f"Redeem batch result: {redeem_batch_result}")
163
-
164
- # Redeem all positions that are currently redeemable
165
- redeem_all_result = service.redeem_all(batch_size=20)
166
- print(f"Redeem all result: {redeem_all_result}")
167
186
  if redeem_all_result and any(item is None for item in redeem_all_result):
168
187
  print("Redeem failed for some items; please retry.")
169
188
  ```
170
189
 
190
+ ### Basic Usage - Split/Merge (Binary Markets)
191
+
192
+ ```python
193
+ # amount is in human units (USDC)
194
+ split_result = service.split(
195
+ "0x31fb435a9506d14f00b9de5e5e4491cf2223b6d40a2525d9afa8b620b61b50e2",
196
+ 1.5,
197
+ )
198
+ print(f"Split result: {split_result}")
199
+
200
+ merge_result = service.merge(
201
+ "0x31fb435a9506d14f00b9de5e5e4491cf2223b6d40a2525d9afa8b620b61b50e2",
202
+ 1.5,
203
+ )
204
+ print(f"Merge result: {merge_result}")
205
+ ```
206
+
171
207
  ## API Documentation
172
208
 
173
209
  ### PolyWeb3Service
@@ -191,7 +227,7 @@ Execute redeem operation.
191
227
 
192
228
  ```python
193
229
  # Batch redeem
194
- result = service.redeem(["0x...", "0x..."], batch_size=20)
230
+ result = service.redeem(["0x...", "0x..."], batch_size=10)
195
231
  ```
196
232
 
197
233
  ##### `redeem_all(batch_size: int = 20) -> list[dict]`
@@ -205,7 +241,41 @@ Redeem all positions that are currently redeemable for the authenticated account
205
241
 
206
242
  ```python
207
243
  # Redeem all positions that can be redeemed
208
- service.redeem_all(batch_size=20)
244
+ service.redeem_all(batch_size=10)
245
+ ```
246
+
247
+ ##### `split(condition_id: str, amount: int | float | str)`
248
+
249
+ Split a binary (Yes/No) position. `amount` is in human USDC units.
250
+
251
+ **Parameters:**
252
+ - `condition_id` (str): Condition ID
253
+ - `amount` (int | float | str): Amount in USDC
254
+
255
+ **Returns:**
256
+ - `dict | None`: Transaction result
257
+
258
+ **Examples:**
259
+
260
+ ```python
261
+ result = service.split("0x...", 1.25)
262
+ ```
263
+
264
+ ##### `merge(condition_id: str, amount: int | float | str)`
265
+
266
+ Merge a binary (Yes/No) position. `amount` is in human USDC units.
267
+
268
+ **Parameters:**
269
+ - `condition_id` (str): Condition ID
270
+ - `amount` (int | float | str): Amount in USDC
271
+
272
+ **Returns:**
273
+ - `dict | None`: Transaction result
274
+
275
+ **Examples:**
276
+
277
+ ```python
278
+ result = service.merge("0x...", 1.25)
209
279
  ```
210
280
 
211
281
  #### Optional APIs
@@ -281,7 +351,7 @@ poly_web3/
281
351
 
282
352
  1. **Environment Variable Security**: Make sure `.env` file is added to `.gitignore`, do not commit sensitive information to the code repository
283
353
  2. **Network Support**: Currently mainly supports Polygon mainnet (chain_id: 137), Amoy testnet may have limited functionality
284
- 3. **Wallet Type**: Proxy (signature_type: 1) and Safe (signature_type: 2) are supported; EOA wallet redeem functionality is under development
354
+ 3. **Wallet Type**: Proxy (signature_type: 1) and Safe (signature_type: 2) are supported; EOA wallet operations are under development
285
355
  4. **Gas Fees**: Transactions are executed through Relayer, gas fees are handled by the Relayer
286
356
 
287
357
  ## Development
@@ -296,18 +366,18 @@ uv pip install -e ".[dev]"
296
366
 
297
367
  ```bash
298
368
  python examples/example_redeem.py
369
+ python examples/example_split_merge.py
299
370
  ```
300
371
 
301
372
  ### Contributing
302
373
 
303
- We welcome all forms of contributions! If you'd like to:
304
-
305
- - Implement EOA wallet support
306
- - Fix bugs or improve existing functionality
307
- - Add new features or improve documentation
308
- - Make suggestions or report issues
374
+ Simple contribution flow:
309
375
 
310
- Please feel free to submit an Issue or Pull Request. Your contributions will help make this project better!
376
+ 1. Open an Issue to describe the change (bug/feature/doc).
377
+ 2. Fork and create a branch: `feat/xxx` or `fix/xxx`.
378
+ 3. Make changes and update/add docs if needed.
379
+ 4. Run: `uv run python -m examples.example_redeem` or `uv run python -m examples.example_split_merge` (if applicable).
380
+ 5. Open a Pull Request and link the Issue.
311
381
 
312
382
  ## License
313
383
 
@@ -1,10 +1,15 @@
1
1
  # poly-web3
2
2
 
3
- Python SDK for redeeming Polymarket positions via Proxy/Safe wallets (gas-free).
3
+ ![PyPI](https://img.shields.io/pypi/v/poly-web3)
4
+ ![Python](https://img.shields.io/pypi/pyversions/poly-web3)
5
+ ![License](https://img.shields.io/github/license/tosmart01/poly-web3)
6
+
7
+ Python SDK for redeeming and splitting/merging Polymarket positions via Proxy/Safe wallets (gas-free).
4
8
 
5
9
  [English](README.md) | [中文](README.zh.md)
6
10
 
7
11
  ```bash
12
+ Python >= 3.11
8
13
  pip install poly-web3
9
14
  ```
10
15
 
@@ -17,7 +22,11 @@ service = PolyWeb3Service(
17
22
  )
18
23
 
19
24
  # Redeem all redeemable positions for the current account.
20
- service.redeem_all(batch_size=20)
25
+ service.redeem_all(batch_size=10)
26
+
27
+ # Split/Merge for binary markets (amount in human USDC units).
28
+ service.split("0x...", 10)
29
+ service.merge("0x...", 10)
21
30
  ```
22
31
 
23
32
  [See the full example](#quick-start)
@@ -27,18 +36,25 @@ service.redeem_all(batch_size=20)
27
36
  - Redeemable positions are fetched via the official Positions API, which typically has ~1 minute latency.
28
37
  - `redeem_all` returns an empty list if there are no redeemable positions. If the returned list contains `None`, the redeem failed and should be retried.
29
38
 
30
- ## Troubleshooting
39
+ ## Split/Merge Notes
40
+
41
+ - `split`/`merge` are designed for binary markets (Yes/No) and use the default partition internally.
42
+ - `amount` is in human units (USDC), and is converted to base units internally.
43
+
44
+ ## FAQ
31
45
 
32
46
  1. **UI shows redeemable, but `redeem_all` returns `[]`**: The official Positions API can be delayed by 1–3 minutes. Wait a bit and retry.
33
47
  2. **RPC error during redeem**: Switch RPC endpoints by setting `rpc_url` when instantiating `PolyWeb3Service`.
34
48
  3. **Redeem stuck in `execute`**: The official relayer may be congested. Stop redeeming for 1 hour to avoid nonce looping from repeated submissions.
49
+ 4. **Relayer client returns 403**: You need to apply for Builder API access and use a valid key. Reference: Polymarket Builders — Introduction: https://docs.polymarket.com/developers/builders/builder-intro
50
+ 5. **Relayer daily limit**: The official relayer typically limits to 100 requests per day. Prefer batch redeem (`batch_size`) to reduce the number of requests and avoid hitting the limit.
35
51
 
36
52
  ## About the Project
37
53
 
38
54
  This project is a Python rewrite of Polymarket's official TypeScript implementation of `builder-relayer-client`, designed to provide Python developers with a convenient tool for executing Proxy and Safe wallet redeem operations on Polymarket.
39
55
 
40
56
  **Important Notes:**
41
- - This project **only implements the official redeem functionality**, focusing on Conditional Token Fund (CTF) redeem operations
57
+ - This project implements official CTF redeem plus binary split/merge operations
42
58
  - Other features (such as trading, order placement, etc.) are not within the scope of this project
43
59
 
44
60
  **Some Polymarket-related redeem or write operations implemented in this project depend on access granted through Polymarket's Builder program. To perform real redeem operations against Polymarket, you must apply for and obtain a Builder key/credentials via Polymarket's official Builder application process. After approval you will receive the credentials required to use the Builder API—only then will the redeem flows in this repository work against the live service. For local development or automated tests, use mocks or testnet setups instead of real keys to avoid exposing production credentials.**
@@ -47,8 +63,8 @@ Reference:
47
63
  - Polymarket Builders — Introduction: https://docs.polymarket.com/developers/builders/builder-intro
48
64
 
49
65
  **Current Status:**
50
- - ✅ **Proxy Wallet** - Fully supported for redeem functionality
51
- - ✅ **Safe Wallet** - Fully supported for redeem functionality
66
+ - ✅ **Proxy Wallet** - Fully supported for redeem/split/merge
67
+ - ✅ **Safe Wallet** - Fully supported for redeem/split/merge
52
68
  - 🚧 **EOA Wallet** - Under development
53
69
 
54
70
  We welcome community contributions! If you'd like to help implement EOA wallet redeem functionality, or have other improvement suggestions, please feel free to submit a Pull Request.
@@ -126,21 +142,41 @@ service = PolyWeb3Service(
126
142
  )
127
143
 
128
144
 
145
+ # Redeem all positions that are currently redeemable
146
+ redeem_all_result = service.redeem_all(batch_size=10)
147
+ print(f"Redeem all result: {redeem_all_result}")
148
+ # If redeem_all_result contains None, refer to README FAQ and retry.
149
+ if redeem_all_result and any(item is None for item in redeem_all_result):
150
+ print("Redeem failed for some items; please retry.")
151
+
129
152
  # Execute redeem operation (batch)
130
153
  condition_ids = [
131
154
  "0xc3df016175463c44f9c9f98bddaa3bf3daaabb14b069fb7869621cffe73ddd1c",
132
155
  "0x31fb435a9506d14f00b9de5e5e4491cf2223b6d40a2525d9afa8b620b61b50e2",
133
156
  ]
134
- redeem_batch_result = service.redeem(condition_ids, batch_size=20)
157
+ redeem_batch_result = service.redeem(condition_ids, batch_size=10)
135
158
  print(f"Redeem batch result: {redeem_batch_result}")
136
-
137
- # Redeem all positions that are currently redeemable
138
- redeem_all_result = service.redeem_all(batch_size=20)
139
- print(f"Redeem all result: {redeem_all_result}")
140
159
  if redeem_all_result and any(item is None for item in redeem_all_result):
141
160
  print("Redeem failed for some items; please retry.")
142
161
  ```
143
162
 
163
+ ### Basic Usage - Split/Merge (Binary Markets)
164
+
165
+ ```python
166
+ # amount is in human units (USDC)
167
+ split_result = service.split(
168
+ "0x31fb435a9506d14f00b9de5e5e4491cf2223b6d40a2525d9afa8b620b61b50e2",
169
+ 1.5,
170
+ )
171
+ print(f"Split result: {split_result}")
172
+
173
+ merge_result = service.merge(
174
+ "0x31fb435a9506d14f00b9de5e5e4491cf2223b6d40a2525d9afa8b620b61b50e2",
175
+ 1.5,
176
+ )
177
+ print(f"Merge result: {merge_result}")
178
+ ```
179
+
144
180
  ## API Documentation
145
181
 
146
182
  ### PolyWeb3Service
@@ -164,7 +200,7 @@ Execute redeem operation.
164
200
 
165
201
  ```python
166
202
  # Batch redeem
167
- result = service.redeem(["0x...", "0x..."], batch_size=20)
203
+ result = service.redeem(["0x...", "0x..."], batch_size=10)
168
204
  ```
169
205
 
170
206
  ##### `redeem_all(batch_size: int = 20) -> list[dict]`
@@ -178,7 +214,41 @@ Redeem all positions that are currently redeemable for the authenticated account
178
214
 
179
215
  ```python
180
216
  # Redeem all positions that can be redeemed
181
- service.redeem_all(batch_size=20)
217
+ service.redeem_all(batch_size=10)
218
+ ```
219
+
220
+ ##### `split(condition_id: str, amount: int | float | str)`
221
+
222
+ Split a binary (Yes/No) position. `amount` is in human USDC units.
223
+
224
+ **Parameters:**
225
+ - `condition_id` (str): Condition ID
226
+ - `amount` (int | float | str): Amount in USDC
227
+
228
+ **Returns:**
229
+ - `dict | None`: Transaction result
230
+
231
+ **Examples:**
232
+
233
+ ```python
234
+ result = service.split("0x...", 1.25)
235
+ ```
236
+
237
+ ##### `merge(condition_id: str, amount: int | float | str)`
238
+
239
+ Merge a binary (Yes/No) position. `amount` is in human USDC units.
240
+
241
+ **Parameters:**
242
+ - `condition_id` (str): Condition ID
243
+ - `amount` (int | float | str): Amount in USDC
244
+
245
+ **Returns:**
246
+ - `dict | None`: Transaction result
247
+
248
+ **Examples:**
249
+
250
+ ```python
251
+ result = service.merge("0x...", 1.25)
182
252
  ```
183
253
 
184
254
  #### Optional APIs
@@ -254,7 +324,7 @@ poly_web3/
254
324
 
255
325
  1. **Environment Variable Security**: Make sure `.env` file is added to `.gitignore`, do not commit sensitive information to the code repository
256
326
  2. **Network Support**: Currently mainly supports Polygon mainnet (chain_id: 137), Amoy testnet may have limited functionality
257
- 3. **Wallet Type**: Proxy (signature_type: 1) and Safe (signature_type: 2) are supported; EOA wallet redeem functionality is under development
327
+ 3. **Wallet Type**: Proxy (signature_type: 1) and Safe (signature_type: 2) are supported; EOA wallet operations are under development
258
328
  4. **Gas Fees**: Transactions are executed through Relayer, gas fees are handled by the Relayer
259
329
 
260
330
  ## Development
@@ -269,18 +339,18 @@ uv pip install -e ".[dev]"
269
339
 
270
340
  ```bash
271
341
  python examples/example_redeem.py
342
+ python examples/example_split_merge.py
272
343
  ```
273
344
 
274
345
  ### Contributing
275
346
 
276
- We welcome all forms of contributions! If you'd like to:
277
-
278
- - Implement EOA wallet support
279
- - Fix bugs or improve existing functionality
280
- - Add new features or improve documentation
281
- - Make suggestions or report issues
347
+ Simple contribution flow:
282
348
 
283
- Please feel free to submit an Issue or Pull Request. Your contributions will help make this project better!
349
+ 1. Open an Issue to describe the change (bug/feature/doc).
350
+ 2. Fork and create a branch: `feat/xxx` or `fix/xxx`.
351
+ 3. Make changes and update/add docs if needed.
352
+ 4. Run: `uv run python -m examples.example_redeem` or `uv run python -m examples.example_split_merge` (if applicable).
353
+ 5. Open a Pull Request and link the Issue.
284
354
 
285
355
  ## License
286
356
 
@@ -0,0 +1,56 @@
1
+ # -*- coding = utf-8 -*-
2
+ # @Time: 2025-12-30 12:00:00
3
+ # @Author: PinBar
4
+ # @Site:
5
+ # @File: example_split_merge.py
6
+ # @Software: PyCharm
7
+ import os
8
+
9
+ import dotenv
10
+ from py_builder_relayer_client.client import RelayClient
11
+ from py_builder_signing_sdk.config import BuilderConfig
12
+ from py_builder_signing_sdk.sdk_types import BuilderApiKeyCreds
13
+ from py_clob_client.client import ClobClient
14
+
15
+ from poly_web3 import RELAYER_URL, PolyWeb3Service
16
+
17
+ dotenv.load_dotenv()
18
+
19
+ if __name__ == "__main__":
20
+ host: str = "https://clob.polymarket.com"
21
+ chain_id: int = 137 # No need to adjust this
22
+ client = ClobClient(
23
+ host,
24
+ key=os.getenv("POLY_API_KEY"),
25
+ chain_id=chain_id,
26
+ signature_type=1, # signature_type=2 for Safe
27
+ funder=os.getenv("POLYMARKET_PROXY_ADDRESS"),
28
+ )
29
+ creds = client.create_or_derive_api_creds()
30
+ client.set_api_creds(creds)
31
+ relayer_client = RelayClient(
32
+ RELAYER_URL,
33
+ chain_id,
34
+ os.getenv("POLY_API_KEY"),
35
+ BuilderConfig(
36
+ local_builder_creds=BuilderApiKeyCreds(
37
+ key=os.getenv("BUILDER_KEY"),
38
+ secret=os.getenv("BUILDER_SECRET"),
39
+ passphrase=os.getenv("BUILDER_PASSPHRASE"),
40
+ )
41
+ ),
42
+ )
43
+ service = PolyWeb3Service(
44
+ clob_client=client,
45
+ relayer_client=relayer_client,
46
+ rpc_url="https://polygon-bor.publicnode.com",
47
+ )
48
+
49
+ condition_id = "0x58ec217262554683a6c1fa2de9d87addef26dd3348367824d6890c68a98809b0"
50
+ amount = 10 # amount in human USDC units
51
+
52
+ split_result = service.split(condition_id, amount)
53
+ print(split_result)
54
+
55
+ merge_result = service.merge(condition_id, amount)
56
+ print(merge_result)
@@ -15,7 +15,7 @@ GET_DEPLOYED = "/deployed"
15
15
  RPC_URL = "https://polygon-bor.publicnode.com" # "https://polygon-rpc.com"
16
16
  RELAYER_URL = "https://relayer-v2.polymarket.com"
17
17
 
18
- STATE_NEW = ("STATE_NEW",)
18
+ STATE_NEW = "STATE_NEW"
19
19
  STATE_EXECUTED = "STATE_EXECUTED"
20
20
  STATE_MINED = "STATE_MINED"
21
21
  STATE_INVALID = "STATE_INVALID"
@@ -78,6 +78,70 @@ CTF_ABI_REDEEM = [
78
78
  }
79
79
  ]
80
80
 
81
+ CTF_ABI_SPLIT = [
82
+ {
83
+ "name": "splitPosition",
84
+ "type": "function",
85
+ "stateMutability": "nonpayable",
86
+ "inputs": [
87
+ {"name": "collateralToken", "type": "address"},
88
+ {"name": "parentCollectionId", "type": "bytes32"},
89
+ {"name": "conditionId", "type": "bytes32"},
90
+ {"name": "partition", "type": "uint256[]"},
91
+ {"name": "amount", "type": "uint256"},
92
+ ],
93
+ "outputs": [],
94
+ }
95
+ ]
96
+
97
+ CTF_ABI_MERGE = [
98
+ {
99
+ "name": "mergePositions",
100
+ "type": "function",
101
+ "stateMutability": "nonpayable",
102
+ "inputs": [
103
+ {"name": "collateralToken", "type": "address"},
104
+ {"name": "parentCollectionId", "type": "bytes32"},
105
+ {"name": "conditionId", "type": "bytes32"},
106
+ {"name": "partition", "type": "uint256[]"},
107
+ {"name": "amount", "type": "uint256"},
108
+ ],
109
+ "outputs": [],
110
+ }
111
+ ]
112
+
113
+ CTF_ABI_SPLIT = [
114
+ {
115
+ "name": "splitPosition",
116
+ "type": "function",
117
+ "stateMutability": "nonpayable",
118
+ "inputs": [
119
+ {"name": "collateralToken", "type": "address"},
120
+ {"name": "parentCollectionId", "type": "bytes32"},
121
+ {"name": "conditionId", "type": "bytes32"},
122
+ {"name": "partition", "type": "uint256[]"},
123
+ {"name": "amount", "type": "uint256"},
124
+ ],
125
+ "outputs": [],
126
+ }
127
+ ]
128
+
129
+ CTF_ABI_MERGE = [
130
+ {
131
+ "name": "mergePositions",
132
+ "type": "function",
133
+ "stateMutability": "nonpayable",
134
+ "inputs": [
135
+ {"name": "collateralToken", "type": "address"},
136
+ {"name": "parentCollectionId", "type": "bytes32"},
137
+ {"name": "conditionId", "type": "bytes32"},
138
+ {"name": "partition", "type": "uint256[]"},
139
+ {"name": "amount", "type": "uint256"},
140
+ ],
141
+ "outputs": [],
142
+ }
143
+ ]
144
+
81
145
  NEG_RISK_ADAPTER_ABI_REDEEM = [
82
146
  {
83
147
  "name": "redeemPositions",
@@ -5,6 +5,7 @@
5
5
  # @File: base.py
6
6
  # @Software: PyCharm
7
7
  from typing import Any
8
+ from decimal import Decimal, InvalidOperation, ROUND_DOWN
8
9
 
9
10
  from py_builder_relayer_client.client import RelayClient
10
11
  from py_clob_client.client import ClobClient
@@ -19,6 +20,8 @@ from poly_web3.const import (
19
20
  ZERO_BYTES32,
20
21
  USDC_POLYGON,
21
22
  CTF_ABI_REDEEM,
23
+ CTF_ABI_SPLIT,
24
+ CTF_ABI_MERGE,
22
25
  NEG_RISK_ADAPTER_ADDRESS,
23
26
  RELAYER_URL,
24
27
  POL,
@@ -157,6 +160,40 @@ class BaseWeb3Service:
157
160
  [1, 2],
158
161
  )._encode_transaction_data()
159
162
 
163
+ def build_ctf_split_tx_data(
164
+ self,
165
+ condition_id: str,
166
+ partition: list[int],
167
+ amount: int,
168
+ collateral_token: str = USDC_POLYGON,
169
+ parent_collection_id: str = ZERO_BYTES32,
170
+ ) -> str:
171
+ ctf = self.w3.eth.contract(address=CTF_ADDRESS, abi=CTF_ABI_SPLIT)
172
+ return ctf.functions.splitPosition(
173
+ collateral_token,
174
+ parent_collection_id,
175
+ condition_id,
176
+ partition,
177
+ amount,
178
+ )._encode_transaction_data()
179
+
180
+ def build_ctf_merge_tx_data(
181
+ self,
182
+ condition_id: str,
183
+ partition: list[int],
184
+ amount: int,
185
+ collateral_token: str = USDC_POLYGON,
186
+ parent_collection_id: str = ZERO_BYTES32,
187
+ ) -> str:
188
+ ctf = self.w3.eth.contract(address=CTF_ADDRESS, abi=CTF_ABI_MERGE)
189
+ return ctf.functions.mergePositions(
190
+ collateral_token,
191
+ parent_collection_id,
192
+ condition_id,
193
+ partition,
194
+ amount,
195
+ )._encode_transaction_data()
196
+
160
197
  def build_neg_risk_redeem_tx_data(
161
198
  self, condition_id: str, redeem_amounts: list[int]
162
199
  ) -> str:
@@ -171,6 +208,9 @@ class BaseWeb3Service:
171
208
  def _build_redeem_tx(self, to: str, data: str) -> Any:
172
209
  raise NotImplementedError("redeem tx builder not implemented")
173
210
 
211
+ def _build_ctf_tx(self, to: str, data: str) -> Any:
212
+ return self._build_redeem_tx(to, data)
213
+
174
214
  def _build_redeem_txs_from_positions(self, positions: list[dict]) -> list[Any]:
175
215
  neg_amounts_by_condition: dict[str, list[float]] = {}
176
216
  normal_conditions: set[str] = set()
@@ -207,8 +247,11 @@ class BaseWeb3Service:
207
247
  )
208
248
  return txs
209
249
 
250
+ def _submit_transactions(self, txs: list[Any], metadata: str) -> dict | None:
251
+ raise NotImplementedError("transaction submit not implemented")
252
+
210
253
  def _submit_redeem(self, txs: list[Any]) -> dict | None:
211
- raise NotImplementedError("redeem submit not implemented")
254
+ return self._submit_transactions(txs, "redeem")
212
255
 
213
256
  def _redeem_batch(self, condition_ids: list[str], batch_size: int) -> list[dict]:
214
257
  """
@@ -312,6 +355,26 @@ class BaseWeb3Service:
312
355
  for i in range(0, len(condition_ids), batch_size)
313
356
  ]
314
357
 
358
+ @staticmethod
359
+ def _to_usdc_base_units(amount: int | float | str | Decimal) -> int:
360
+ try:
361
+ if isinstance(amount, Decimal):
362
+ human = amount
363
+ elif isinstance(amount, int):
364
+ human = Decimal(amount)
365
+ else:
366
+ human = Decimal(str(amount))
367
+ except (InvalidOperation, ValueError) as exc:
368
+ raise Exception(f"invalid amount: {amount}") from exc
369
+ if human <= 0:
370
+ raise Exception("amount must be greater than 0")
371
+ base_units = (human * Decimal("1000000")).quantize(
372
+ Decimal("1"), rounding=ROUND_DOWN
373
+ )
374
+ if base_units <= 0:
375
+ raise Exception("amount too small after conversion")
376
+ return int(base_units)
377
+
315
378
  def redeem(
316
379
  self,
317
380
  condition_ids: str | list[str],
@@ -330,3 +393,49 @@ class BaseWeb3Service:
330
393
  """
331
394
  positions = self.fetch_positions(user_address=self._resolve_user_address())
332
395
  return self._redeem_from_positions(positions, batch_size)
396
+
397
+ def split(
398
+ self,
399
+ condition_id: str,
400
+ amount: int | float | str | Decimal,
401
+ collateral_token: str = USDC_POLYGON,
402
+ parent_collection_id: str = ZERO_BYTES32,
403
+ ) -> dict | None:
404
+ """
405
+ Split a position for binary markets (Yes/No), amount in human units.
406
+ """
407
+ amount_base_units = self._to_usdc_base_units(amount)
408
+ tx = self._build_ctf_tx(
409
+ CTF_ADDRESS,
410
+ self.build_ctf_split_tx_data(
411
+ condition_id=condition_id,
412
+ partition=[1, 2],
413
+ amount=amount_base_units,
414
+ collateral_token=collateral_token,
415
+ parent_collection_id=parent_collection_id,
416
+ ),
417
+ )
418
+ return self._submit_transactions([tx], "split")
419
+
420
+ def merge(
421
+ self,
422
+ condition_id: str,
423
+ amount: int | float | str | Decimal,
424
+ collateral_token: str = USDC_POLYGON,
425
+ parent_collection_id: str = ZERO_BYTES32,
426
+ ) -> dict | None:
427
+ """
428
+ Merge binary positions (Yes/No) back into a single position, amount in human units.
429
+ """
430
+ amount_base_units = self._to_usdc_base_units(amount)
431
+ tx = self._build_ctf_tx(
432
+ CTF_ADDRESS,
433
+ self.build_ctf_merge_tx_data(
434
+ condition_id=condition_id,
435
+ partition=[1, 2],
436
+ amount=amount_base_units,
437
+ collateral_token=collateral_token,
438
+ parent_collection_id=parent_collection_id,
439
+ ),
440
+ )
441
+ return self._submit_transactions([tx], "merge")
@@ -0,0 +1,40 @@
1
+ # -*- coding = utf-8 -*-
2
+ # @Time: 2025-12-27 16:01:09
3
+ # @Author: PinBar
4
+ # @Site:
5
+ # @File: eoa_service.py
6
+ # @Software: PyCharm
7
+ from decimal import Decimal
8
+
9
+ from poly_web3.const import USDC_POLYGON, ZERO_BYTES32
10
+ from poly_web3.web3_service.base import BaseWeb3Service
11
+
12
+
13
+ class EOAWeb3Service(BaseWeb3Service):
14
+ def redeem(
15
+ self,
16
+ condition_ids: str | list[str],
17
+ batch_size: int = 10,
18
+ ):
19
+ raise ImportError("EOA wallet redeem not supported")
20
+
21
+ def redeem_all(self, batch_size: int = 10) -> list[dict]:
22
+ raise ImportError("EOA wallet redeem not supported")
23
+
24
+ def split(
25
+ self,
26
+ condition_id: str,
27
+ amount: int | float | str | Decimal,
28
+ collateral_token: str = USDC_POLYGON,
29
+ parent_collection_id: str = ZERO_BYTES32,
30
+ ) -> dict | None:
31
+ raise ImportError("EOA wallet split not supported")
32
+
33
+ def merge(
34
+ self,
35
+ condition_id: str,
36
+ amount: int | float | str | Decimal,
37
+ collateral_token: str = USDC_POLYGON,
38
+ parent_collection_id: str = ZERO_BYTES32,
39
+ ) -> dict | None:
40
+ raise ImportError("EOA wallet merge not supported")
@@ -32,7 +32,9 @@ class ProxyWeb3Service(BaseWeb3Service):
32
32
  "typeCode": 1,
33
33
  }
34
34
 
35
- def build_proxy_transaction_request(self, args: dict) -> dict:
35
+ def build_proxy_transaction_request(
36
+ self, args: dict, metadata: str = "redeem"
37
+ ) -> dict:
36
38
  proxy_contract_config = self.get_contract_config()["ProxyContracts"]
37
39
  to = proxy_contract_config["ProxyFactory"]
38
40
  proxy = derive_proxy_wallet(args["from"], to, PROXY_INIT_CODE_HASH)
@@ -80,7 +82,7 @@ class ProxyWeb3Service(BaseWeb3Service):
80
82
  "signature": final_sig,
81
83
  "signatureParams": sig_params,
82
84
  "type": self.wallet_type.value,
83
- "metadata": "redeem",
85
+ "metadata": metadata,
84
86
  }
85
87
  return req
86
88
 
@@ -96,7 +98,7 @@ class ProxyWeb3Service(BaseWeb3Service):
96
98
  # Encode function data (compatible with web3 6/7)
97
99
  return contract.functions.proxy(calls_data)._encode_transaction_data()
98
100
 
99
- def _submit_redeem(self, txs: list[dict]) -> dict:
101
+ def _submit_transactions(self, txs: list[dict], metadata: str) -> dict:
100
102
  if self.clob_client is None:
101
103
  raise Exception("signer not found")
102
104
  _from = to_checksum_address(self.clob_client.get_address())
@@ -108,7 +110,7 @@ class ProxyWeb3Service(BaseWeb3Service):
108
110
  "relay": rp["address"],
109
111
  "nonce": rp["nonce"],
110
112
  }
111
- req = self.build_proxy_transaction_request(args)
113
+ req = self.build_proxy_transaction_request(args, metadata=metadata)
112
114
  headers = self.relayer_client._generate_builder_headers(
113
115
  "POST", SUBMIT_TRANSACTION, req
114
116
  )
@@ -122,3 +124,6 @@ class ProxyWeb3Service(BaseWeb3Service):
122
124
  max_polls=100,
123
125
  )
124
126
  return redeem_res
127
+
128
+ def _submit_redeem(self, txs: list[dict]) -> dict:
129
+ return self._submit_transactions(txs, "redeem")
@@ -17,8 +17,13 @@ class SafeWeb3Service(BaseWeb3Service):
17
17
  operation=OperationType.Call,
18
18
  )
19
19
 
20
- def _submit_redeem(self, txs: list[SafeTransaction]) -> dict | None:
20
+ def _submit_transactions(
21
+ self, txs: list[SafeTransaction], metadata: str
22
+ ) -> dict | None:
21
23
  if self.relayer_client is None:
22
24
  raise Exception("relayer_client not found")
23
- resp = self.relayer_client.execute(txs, "redeem")
25
+ resp = self.relayer_client.execute(txs, metadata)
24
26
  return resp.wait()
27
+
28
+ def _submit_redeem(self, txs: list[SafeTransaction]) -> dict | None:
29
+ return self._submit_transactions(txs, "redeem")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: poly-web3
3
- Version: 1.0.1
3
+ Version: 1.0.2
4
4
  Summary: Polymarket Proxy wallet redeem SDK - Execute redeem operations on Polymarket using proxy wallets
5
5
  Home-page: https://github.com/tosmart01/poly-web3
6
6
  Author: PinBar
@@ -27,11 +27,16 @@ Dynamic: requires-python
27
27
 
28
28
  # poly-web3
29
29
 
30
- Python SDK for redeeming Polymarket positions via Proxy/Safe wallets (gas-free).
30
+ ![PyPI](https://img.shields.io/pypi/v/poly-web3)
31
+ ![Python](https://img.shields.io/pypi/pyversions/poly-web3)
32
+ ![License](https://img.shields.io/github/license/tosmart01/poly-web3)
33
+
34
+ Python SDK for redeeming and splitting/merging Polymarket positions via Proxy/Safe wallets (gas-free).
31
35
 
32
36
  [English](README.md) | [中文](README.zh.md)
33
37
 
34
38
  ```bash
39
+ Python >= 3.11
35
40
  pip install poly-web3
36
41
  ```
37
42
 
@@ -44,7 +49,11 @@ service = PolyWeb3Service(
44
49
  )
45
50
 
46
51
  # Redeem all redeemable positions for the current account.
47
- service.redeem_all(batch_size=20)
52
+ service.redeem_all(batch_size=10)
53
+
54
+ # Split/Merge for binary markets (amount in human USDC units).
55
+ service.split("0x...", 10)
56
+ service.merge("0x...", 10)
48
57
  ```
49
58
 
50
59
  [See the full example](#quick-start)
@@ -54,18 +63,25 @@ service.redeem_all(batch_size=20)
54
63
  - Redeemable positions are fetched via the official Positions API, which typically has ~1 minute latency.
55
64
  - `redeem_all` returns an empty list if there are no redeemable positions. If the returned list contains `None`, the redeem failed and should be retried.
56
65
 
57
- ## Troubleshooting
66
+ ## Split/Merge Notes
67
+
68
+ - `split`/`merge` are designed for binary markets (Yes/No) and use the default partition internally.
69
+ - `amount` is in human units (USDC), and is converted to base units internally.
70
+
71
+ ## FAQ
58
72
 
59
73
  1. **UI shows redeemable, but `redeem_all` returns `[]`**: The official Positions API can be delayed by 1–3 minutes. Wait a bit and retry.
60
74
  2. **RPC error during redeem**: Switch RPC endpoints by setting `rpc_url` when instantiating `PolyWeb3Service`.
61
75
  3. **Redeem stuck in `execute`**: The official relayer may be congested. Stop redeeming for 1 hour to avoid nonce looping from repeated submissions.
76
+ 4. **Relayer client returns 403**: You need to apply for Builder API access and use a valid key. Reference: Polymarket Builders — Introduction: https://docs.polymarket.com/developers/builders/builder-intro
77
+ 5. **Relayer daily limit**: The official relayer typically limits to 100 requests per day. Prefer batch redeem (`batch_size`) to reduce the number of requests and avoid hitting the limit.
62
78
 
63
79
  ## About the Project
64
80
 
65
81
  This project is a Python rewrite of Polymarket's official TypeScript implementation of `builder-relayer-client`, designed to provide Python developers with a convenient tool for executing Proxy and Safe wallet redeem operations on Polymarket.
66
82
 
67
83
  **Important Notes:**
68
- - This project **only implements the official redeem functionality**, focusing on Conditional Token Fund (CTF) redeem operations
84
+ - This project implements official CTF redeem plus binary split/merge operations
69
85
  - Other features (such as trading, order placement, etc.) are not within the scope of this project
70
86
 
71
87
  **Some Polymarket-related redeem or write operations implemented in this project depend on access granted through Polymarket's Builder program. To perform real redeem operations against Polymarket, you must apply for and obtain a Builder key/credentials via Polymarket's official Builder application process. After approval you will receive the credentials required to use the Builder API—only then will the redeem flows in this repository work against the live service. For local development or automated tests, use mocks or testnet setups instead of real keys to avoid exposing production credentials.**
@@ -74,8 +90,8 @@ Reference:
74
90
  - Polymarket Builders — Introduction: https://docs.polymarket.com/developers/builders/builder-intro
75
91
 
76
92
  **Current Status:**
77
- - ✅ **Proxy Wallet** - Fully supported for redeem functionality
78
- - ✅ **Safe Wallet** - Fully supported for redeem functionality
93
+ - ✅ **Proxy Wallet** - Fully supported for redeem/split/merge
94
+ - ✅ **Safe Wallet** - Fully supported for redeem/split/merge
79
95
  - 🚧 **EOA Wallet** - Under development
80
96
 
81
97
  We welcome community contributions! If you'd like to help implement EOA wallet redeem functionality, or have other improvement suggestions, please feel free to submit a Pull Request.
@@ -153,21 +169,41 @@ service = PolyWeb3Service(
153
169
  )
154
170
 
155
171
 
172
+ # Redeem all positions that are currently redeemable
173
+ redeem_all_result = service.redeem_all(batch_size=10)
174
+ print(f"Redeem all result: {redeem_all_result}")
175
+ # If redeem_all_result contains None, refer to README FAQ and retry.
176
+ if redeem_all_result and any(item is None for item in redeem_all_result):
177
+ print("Redeem failed for some items; please retry.")
178
+
156
179
  # Execute redeem operation (batch)
157
180
  condition_ids = [
158
181
  "0xc3df016175463c44f9c9f98bddaa3bf3daaabb14b069fb7869621cffe73ddd1c",
159
182
  "0x31fb435a9506d14f00b9de5e5e4491cf2223b6d40a2525d9afa8b620b61b50e2",
160
183
  ]
161
- redeem_batch_result = service.redeem(condition_ids, batch_size=20)
184
+ redeem_batch_result = service.redeem(condition_ids, batch_size=10)
162
185
  print(f"Redeem batch result: {redeem_batch_result}")
163
-
164
- # Redeem all positions that are currently redeemable
165
- redeem_all_result = service.redeem_all(batch_size=20)
166
- print(f"Redeem all result: {redeem_all_result}")
167
186
  if redeem_all_result and any(item is None for item in redeem_all_result):
168
187
  print("Redeem failed for some items; please retry.")
169
188
  ```
170
189
 
190
+ ### Basic Usage - Split/Merge (Binary Markets)
191
+
192
+ ```python
193
+ # amount is in human units (USDC)
194
+ split_result = service.split(
195
+ "0x31fb435a9506d14f00b9de5e5e4491cf2223b6d40a2525d9afa8b620b61b50e2",
196
+ 1.5,
197
+ )
198
+ print(f"Split result: {split_result}")
199
+
200
+ merge_result = service.merge(
201
+ "0x31fb435a9506d14f00b9de5e5e4491cf2223b6d40a2525d9afa8b620b61b50e2",
202
+ 1.5,
203
+ )
204
+ print(f"Merge result: {merge_result}")
205
+ ```
206
+
171
207
  ## API Documentation
172
208
 
173
209
  ### PolyWeb3Service
@@ -191,7 +227,7 @@ Execute redeem operation.
191
227
 
192
228
  ```python
193
229
  # Batch redeem
194
- result = service.redeem(["0x...", "0x..."], batch_size=20)
230
+ result = service.redeem(["0x...", "0x..."], batch_size=10)
195
231
  ```
196
232
 
197
233
  ##### `redeem_all(batch_size: int = 20) -> list[dict]`
@@ -205,7 +241,41 @@ Redeem all positions that are currently redeemable for the authenticated account
205
241
 
206
242
  ```python
207
243
  # Redeem all positions that can be redeemed
208
- service.redeem_all(batch_size=20)
244
+ service.redeem_all(batch_size=10)
245
+ ```
246
+
247
+ ##### `split(condition_id: str, amount: int | float | str)`
248
+
249
+ Split a binary (Yes/No) position. `amount` is in human USDC units.
250
+
251
+ **Parameters:**
252
+ - `condition_id` (str): Condition ID
253
+ - `amount` (int | float | str): Amount in USDC
254
+
255
+ **Returns:**
256
+ - `dict | None`: Transaction result
257
+
258
+ **Examples:**
259
+
260
+ ```python
261
+ result = service.split("0x...", 1.25)
262
+ ```
263
+
264
+ ##### `merge(condition_id: str, amount: int | float | str)`
265
+
266
+ Merge a binary (Yes/No) position. `amount` is in human USDC units.
267
+
268
+ **Parameters:**
269
+ - `condition_id` (str): Condition ID
270
+ - `amount` (int | float | str): Amount in USDC
271
+
272
+ **Returns:**
273
+ - `dict | None`: Transaction result
274
+
275
+ **Examples:**
276
+
277
+ ```python
278
+ result = service.merge("0x...", 1.25)
209
279
  ```
210
280
 
211
281
  #### Optional APIs
@@ -281,7 +351,7 @@ poly_web3/
281
351
 
282
352
  1. **Environment Variable Security**: Make sure `.env` file is added to `.gitignore`, do not commit sensitive information to the code repository
283
353
  2. **Network Support**: Currently mainly supports Polygon mainnet (chain_id: 137), Amoy testnet may have limited functionality
284
- 3. **Wallet Type**: Proxy (signature_type: 1) and Safe (signature_type: 2) are supported; EOA wallet redeem functionality is under development
354
+ 3. **Wallet Type**: Proxy (signature_type: 1) and Safe (signature_type: 2) are supported; EOA wallet operations are under development
285
355
  4. **Gas Fees**: Transactions are executed through Relayer, gas fees are handled by the Relayer
286
356
 
287
357
  ## Development
@@ -296,18 +366,18 @@ uv pip install -e ".[dev]"
296
366
 
297
367
  ```bash
298
368
  python examples/example_redeem.py
369
+ python examples/example_split_merge.py
299
370
  ```
300
371
 
301
372
  ### Contributing
302
373
 
303
- We welcome all forms of contributions! If you'd like to:
304
-
305
- - Implement EOA wallet support
306
- - Fix bugs or improve existing functionality
307
- - Add new features or improve documentation
308
- - Make suggestions or report issues
374
+ Simple contribution flow:
309
375
 
310
- Please feel free to submit an Issue or Pull Request. Your contributions will help make this project better!
376
+ 1. Open an Issue to describe the change (bug/feature/doc).
377
+ 2. Fork and create a branch: `feat/xxx` or `fix/xxx`.
378
+ 3. Make changes and update/add docs if needed.
379
+ 4. Run: `uv run python -m examples.example_redeem` or `uv run python -m examples.example_split_merge` (if applicable).
380
+ 5. Open a Pull Request and link the Issue.
311
381
 
312
382
  ## License
313
383
 
@@ -2,6 +2,7 @@ README.md
2
2
  pyproject.toml
3
3
  setup.py
4
4
  examples/example_redeem.py
5
+ examples/example_split_merge.py
5
6
  poly_web3/__init__.py
6
7
  poly_web3/const.py
7
8
  poly_web3/log.py
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "poly-web3"
3
- version = "1.0.1"
3
+ version = "1.0.2"
4
4
  description = "Polymarket Proxy wallet redeem SDK - Execute redeem operations on Polymarket using proxy wallets"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.11"
@@ -1,19 +0,0 @@
1
- # -*- coding = utf-8 -*-
2
- # @Time: 2025-12-27 16:01:09
3
- # @Author: PinBar
4
- # @Site:
5
- # @File: eoa_service.py
6
- # @Software: PyCharm
7
- from poly_web3.web3_service.base import BaseWeb3Service
8
-
9
-
10
- class EOAWeb3Service(BaseWeb3Service):
11
- def redeem(
12
- self,
13
- condition_ids: str | list[str],
14
- batch_size: int = 10,
15
- ):
16
- raise ImportError("EOA wallet redeem not supported")
17
-
18
- def redeem_all(self, batch_size: int = 10) -> list[dict]:
19
- raise ImportError("EOA wallet redeem not supported")
File without changes
File without changes
File without changes
File without changes