afp-sdk 0.2.2__tar.gz → 0.3.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.
- {afp_sdk-0.2.2 → afp_sdk-0.3.0}/CHANGELOG.md +11 -0
- {afp_sdk-0.2.2 → afp_sdk-0.3.0}/PKG-INFO +20 -4
- {afp_sdk-0.2.2 → afp_sdk-0.3.0}/README.md +19 -3
- {afp_sdk-0.2.2 → afp_sdk-0.3.0}/afp/bindings/final_settlement_facet.py +54 -0
- {afp_sdk-0.2.2 → afp_sdk-0.3.0}/afp/config.py +8 -7
- {afp_sdk-0.2.2 → afp_sdk-0.3.0}/afp/exchange.py +11 -2
- {afp_sdk-0.2.2 → afp_sdk-0.3.0}/pyproject.toml +1 -1
- afp_sdk-0.3.0/tests/test_exchange_client.py +24 -0
- {afp_sdk-0.2.2 → afp_sdk-0.3.0}/uv.lock +1 -1
- {afp_sdk-0.2.2 → afp_sdk-0.3.0}/.env.template +0 -0
- {afp_sdk-0.2.2 → afp_sdk-0.3.0}/.envrc +0 -0
- {afp_sdk-0.2.2 → afp_sdk-0.3.0}/LICENSE +0 -0
- {afp_sdk-0.2.2 → afp_sdk-0.3.0}/afp/__init__.py +0 -0
- {afp_sdk-0.2.2 → afp_sdk-0.3.0}/afp/api/__init__.py +0 -0
- {afp_sdk-0.2.2 → afp_sdk-0.3.0}/afp/api/admin.py +0 -0
- {afp_sdk-0.2.2 → afp_sdk-0.3.0}/afp/api/base.py +0 -0
- {afp_sdk-0.2.2 → afp_sdk-0.3.0}/afp/api/builder.py +0 -0
- {afp_sdk-0.2.2 → afp_sdk-0.3.0}/afp/api/clearing.py +0 -0
- {afp_sdk-0.2.2 → afp_sdk-0.3.0}/afp/api/liquidation.py +0 -0
- {afp_sdk-0.2.2 → afp_sdk-0.3.0}/afp/api/trading.py +0 -0
- {afp_sdk-0.2.2 → afp_sdk-0.3.0}/afp/bindings/__init__.py +0 -0
- {afp_sdk-0.2.2 → afp_sdk-0.3.0}/afp/bindings/auctioneer_facet.py +0 -0
- {afp_sdk-0.2.2 → afp_sdk-0.3.0}/afp/bindings/bankruptcy_facet.py +0 -0
- {afp_sdk-0.2.2 → afp_sdk-0.3.0}/afp/bindings/clearing_facet.py +0 -0
- {afp_sdk-0.2.2 → afp_sdk-0.3.0}/afp/bindings/erc20.py +0 -0
- {afp_sdk-0.2.2 → afp_sdk-0.3.0}/afp/bindings/facade.py +0 -0
- {afp_sdk-0.2.2 → afp_sdk-0.3.0}/afp/bindings/margin_account.py +0 -0
- {afp_sdk-0.2.2 → afp_sdk-0.3.0}/afp/bindings/margin_account_registry.py +0 -0
- {afp_sdk-0.2.2 → afp_sdk-0.3.0}/afp/bindings/mark_price_tracker_facet.py +0 -0
- {afp_sdk-0.2.2 → afp_sdk-0.3.0}/afp/bindings/oracle_provider.py +0 -0
- {afp_sdk-0.2.2 → afp_sdk-0.3.0}/afp/bindings/product_registry.py +0 -0
- {afp_sdk-0.2.2 → afp_sdk-0.3.0}/afp/bindings/system_viewer.py +0 -0
- {afp_sdk-0.2.2 → afp_sdk-0.3.0}/afp/bindings/trading_protocol.py +0 -0
- {afp_sdk-0.2.2 → afp_sdk-0.3.0}/afp/decorators.py +0 -0
- {afp_sdk-0.2.2 → afp_sdk-0.3.0}/afp/enums.py +0 -0
- {afp_sdk-0.2.2 → afp_sdk-0.3.0}/afp/exceptions.py +0 -0
- {afp_sdk-0.2.2 → afp_sdk-0.3.0}/afp/py.typed +0 -0
- {afp_sdk-0.2.2 → afp_sdk-0.3.0}/afp/schemas.py +0 -0
- {afp_sdk-0.2.2 → afp_sdk-0.3.0}/afp/signing.py +0 -0
- {afp_sdk-0.2.2 → afp_sdk-0.3.0}/afp/validators.py +0 -0
- {afp_sdk-0.2.2 → afp_sdk-0.3.0}/devenv.lock +0 -0
- {afp_sdk-0.2.2 → afp_sdk-0.3.0}/devenv.nix +0 -0
- {afp_sdk-0.2.2 → afp_sdk-0.3.0}/devenv.yaml +0 -0
- {afp_sdk-0.2.2 → afp_sdk-0.3.0}/examples/cancel_order.py +0 -0
- {afp_sdk-0.2.2 → afp_sdk-0.3.0}/examples/create_product.py +0 -0
- {afp_sdk-0.2.2 → afp_sdk-0.3.0}/examples/execute_trade.py +0 -0
- {afp_sdk-0.2.2 → afp_sdk-0.3.0}/tests/__init__.py +0 -0
- {afp_sdk-0.2.2 → afp_sdk-0.3.0}/tests/test_decorators.py +0 -0
- {afp_sdk-0.2.2 → afp_sdk-0.3.0}/tests/test_hashing.py +0 -0
- {afp_sdk-0.2.2 → afp_sdk-0.3.0}/tests/test_login.py +0 -0
- {afp_sdk-0.2.2 → afp_sdk-0.3.0}/tests/test_schemas.py +0 -0
- {afp_sdk-0.2.2 → afp_sdk-0.3.0}/tests/test_validators.py +0 -0
|
@@ -1,3 +1,13 @@
|
|
|
1
|
+
## [v0.3.0] - 2025-09-05
|
|
2
|
+
|
|
3
|
+
_First public release for Forecastathon._
|
|
4
|
+
|
|
5
|
+
### Changed
|
|
6
|
+
|
|
7
|
+
- Update the interface with the AutEx exchange ([#17](https://github.com/autonity/afp-sdk/pull/17))
|
|
8
|
+
- Update the contract bindings ([#18](https://github.com/autonity/afp-sdk/pull/18))
|
|
9
|
+
- Update Clearing System parameters for Autonity Mainnet ([#19](https://github.com/autonity/afp-sdk/pull/19))
|
|
10
|
+
|
|
1
11
|
## [v0.2.2] - 2025-09-03
|
|
2
12
|
|
|
3
13
|
### Added
|
|
@@ -45,6 +55,7 @@
|
|
|
45
55
|
|
|
46
56
|
_First release._
|
|
47
57
|
|
|
58
|
+
[v0.3.0]: https://github.com/autonity/afp-sdk/releases/tag/v0.3.0
|
|
48
59
|
[v0.2.2]: https://github.com/autonity/afp-sdk/releases/tag/v0.2.2
|
|
49
60
|
[v0.2.1]: https://github.com/autonity/afp-sdk/releases/tag/v0.2.1
|
|
50
61
|
[v0.2.0]: https://github.com/autonity/afp-sdk/releases/tag/v0.2.0
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: afp-sdk
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Summary: Autonomous Futures Protocol Python SDK
|
|
5
5
|
Keywords: autonity,web3,trading,crypto,prediction,forecast,markets
|
|
6
6
|
License-Expression: MIT
|
|
@@ -38,7 +38,7 @@ pip install afp-sdk
|
|
|
38
38
|
|
|
39
39
|
The `afp` package consists of the following:
|
|
40
40
|
|
|
41
|
-
- `afp` top-level module: High-level API for interacting with the Clearing
|
|
41
|
+
- `afp` top-level module: High-level API for interacting with the AFP Clearing
|
|
42
42
|
System and the AutEx exchange.
|
|
43
43
|
- `afp.bindings` submodule: Low-level API that provides typed Python bindings
|
|
44
44
|
for the Clearing System smart contracts.
|
|
@@ -47,7 +47,7 @@ The `afp` package consists of the following:
|
|
|
47
47
|
|
|
48
48
|
### Preparation
|
|
49
49
|
|
|
50
|
-
In order to
|
|
50
|
+
In order to trade in the AFP system, traders need to prepare the following:
|
|
51
51
|
|
|
52
52
|
- The ID of a product to be traded.
|
|
53
53
|
- The address of the product's collateral token.
|
|
@@ -55,7 +55,7 @@ In order to use the AFP system, traders need to prepare the following:
|
|
|
55
55
|
balance in ATN (for paying gas fee) and in the product's collateral token.
|
|
56
56
|
- An Autonity account for signing intents. The two accounts can be the same.
|
|
57
57
|
- The address of an Autonity RPC provider. They can be found on
|
|
58
|
-
[Chainlist](https://chainlist.org/?search=autonity
|
|
58
|
+
[Chainlist](https://chainlist.org/?search=autonity).
|
|
59
59
|
|
|
60
60
|
We can store those in the following constants (using random example IDs):
|
|
61
61
|
|
|
@@ -169,6 +169,22 @@ print(fills)
|
|
|
169
169
|
|
|
170
170
|
See further code examples in the [examples](./examples/) directory.
|
|
171
171
|
|
|
172
|
+
## Configuration
|
|
173
|
+
|
|
174
|
+
By default the SDK communicates with the AFP Clearing System contracts on
|
|
175
|
+
Autonity Mainnet, and the AutEx Exchange. Connection parameters can be
|
|
176
|
+
overridden with the following environment variables:
|
|
177
|
+
|
|
178
|
+
```sh
|
|
179
|
+
AFP_EXCHANGE_URL=
|
|
180
|
+
AFP_CHAIN_ID=
|
|
181
|
+
AFP_CLEARING_DIAMOND_ADDRESS=
|
|
182
|
+
AFP_MARGIN_ACCOUNT_REGISTRY_ADDRESS=
|
|
183
|
+
AFP_ORACLE_PROVIDER_ADDRESS=
|
|
184
|
+
AFP_PRODUCT_REGISTRY_ADDRESS=
|
|
185
|
+
AFP_SYSTEM_VIEWER_ADDRESS=
|
|
186
|
+
```
|
|
187
|
+
|
|
172
188
|
## Development
|
|
173
189
|
|
|
174
190
|
The package uses [`uv`](https://docs.astral.sh/uv/) as project manager.
|
|
@@ -13,7 +13,7 @@ pip install afp-sdk
|
|
|
13
13
|
|
|
14
14
|
The `afp` package consists of the following:
|
|
15
15
|
|
|
16
|
-
- `afp` top-level module: High-level API for interacting with the Clearing
|
|
16
|
+
- `afp` top-level module: High-level API for interacting with the AFP Clearing
|
|
17
17
|
System and the AutEx exchange.
|
|
18
18
|
- `afp.bindings` submodule: Low-level API that provides typed Python bindings
|
|
19
19
|
for the Clearing System smart contracts.
|
|
@@ -22,7 +22,7 @@ The `afp` package consists of the following:
|
|
|
22
22
|
|
|
23
23
|
### Preparation
|
|
24
24
|
|
|
25
|
-
In order to
|
|
25
|
+
In order to trade in the AFP system, traders need to prepare the following:
|
|
26
26
|
|
|
27
27
|
- The ID of a product to be traded.
|
|
28
28
|
- The address of the product's collateral token.
|
|
@@ -30,7 +30,7 @@ In order to use the AFP system, traders need to prepare the following:
|
|
|
30
30
|
balance in ATN (for paying gas fee) and in the product's collateral token.
|
|
31
31
|
- An Autonity account for signing intents. The two accounts can be the same.
|
|
32
32
|
- The address of an Autonity RPC provider. They can be found on
|
|
33
|
-
[Chainlist](https://chainlist.org/?search=autonity
|
|
33
|
+
[Chainlist](https://chainlist.org/?search=autonity).
|
|
34
34
|
|
|
35
35
|
We can store those in the following constants (using random example IDs):
|
|
36
36
|
|
|
@@ -144,6 +144,22 @@ print(fills)
|
|
|
144
144
|
|
|
145
145
|
See further code examples in the [examples](./examples/) directory.
|
|
146
146
|
|
|
147
|
+
## Configuration
|
|
148
|
+
|
|
149
|
+
By default the SDK communicates with the AFP Clearing System contracts on
|
|
150
|
+
Autonity Mainnet, and the AutEx Exchange. Connection parameters can be
|
|
151
|
+
overridden with the following environment variables:
|
|
152
|
+
|
|
153
|
+
```sh
|
|
154
|
+
AFP_EXCHANGE_URL=
|
|
155
|
+
AFP_CHAIN_ID=
|
|
156
|
+
AFP_CLEARING_DIAMOND_ADDRESS=
|
|
157
|
+
AFP_MARGIN_ACCOUNT_REGISTRY_ADDRESS=
|
|
158
|
+
AFP_ORACLE_PROVIDER_ADDRESS=
|
|
159
|
+
AFP_PRODUCT_REGISTRY_ADDRESS=
|
|
160
|
+
AFP_SYSTEM_VIEWER_ADDRESS=
|
|
161
|
+
```
|
|
162
|
+
|
|
147
163
|
## Development
|
|
148
164
|
|
|
149
165
|
The package uses [`uv`](https://docs.astral.sh/uv/) as project manager.
|
|
@@ -32,6 +32,16 @@ class FinalSettlementFacet:
|
|
|
32
32
|
abi=ABI,
|
|
33
33
|
)
|
|
34
34
|
|
|
35
|
+
@property
|
|
36
|
+
def FSPFinalized(self) -> contract.ContractEvent:
|
|
37
|
+
"""Binding for `event FSPFinalized` on the FinalSettlementFacet contract."""
|
|
38
|
+
return self._contract.events.FSPFinalized
|
|
39
|
+
|
|
40
|
+
@property
|
|
41
|
+
def FinalSettlementCloseout(self) -> contract.ContractEvent:
|
|
42
|
+
"""Binding for `event FinalSettlementCloseout` on the FinalSettlementFacet contract."""
|
|
43
|
+
return self._contract.events.FinalSettlementCloseout
|
|
44
|
+
|
|
35
45
|
def closeout_fee_rate(
|
|
36
46
|
self,
|
|
37
47
|
) -> int:
|
|
@@ -210,6 +220,50 @@ ABI = typing.cast(
|
|
|
210
220
|
"name": "ProductNotInFinalSettlement",
|
|
211
221
|
"type": "error",
|
|
212
222
|
},
|
|
223
|
+
{
|
|
224
|
+
"anonymous": False,
|
|
225
|
+
"inputs": [
|
|
226
|
+
{
|
|
227
|
+
"indexed": True,
|
|
228
|
+
"internalType": "bytes32",
|
|
229
|
+
"name": "productID",
|
|
230
|
+
"type": "bytes32",
|
|
231
|
+
},
|
|
232
|
+
{
|
|
233
|
+
"indexed": False,
|
|
234
|
+
"internalType": "uint256",
|
|
235
|
+
"name": "fsp",
|
|
236
|
+
"type": "uint256",
|
|
237
|
+
},
|
|
238
|
+
],
|
|
239
|
+
"name": "FSPFinalized",
|
|
240
|
+
"type": "event",
|
|
241
|
+
},
|
|
242
|
+
{
|
|
243
|
+
"anonymous": False,
|
|
244
|
+
"inputs": [
|
|
245
|
+
{
|
|
246
|
+
"indexed": True,
|
|
247
|
+
"internalType": "bytes32",
|
|
248
|
+
"name": "productID",
|
|
249
|
+
"type": "bytes32",
|
|
250
|
+
},
|
|
251
|
+
{
|
|
252
|
+
"indexed": False,
|
|
253
|
+
"internalType": "uint256",
|
|
254
|
+
"name": "accountLength",
|
|
255
|
+
"type": "uint256",
|
|
256
|
+
},
|
|
257
|
+
{
|
|
258
|
+
"indexed": False,
|
|
259
|
+
"internalType": "address",
|
|
260
|
+
"name": "closedBy",
|
|
261
|
+
"type": "address",
|
|
262
|
+
},
|
|
263
|
+
],
|
|
264
|
+
"name": "FinalSettlementCloseout",
|
|
265
|
+
"type": "event",
|
|
266
|
+
},
|
|
213
267
|
{
|
|
214
268
|
"inputs": [],
|
|
215
269
|
"name": "CLOSEOUT_FEE_RATE",
|
|
@@ -9,33 +9,34 @@ FEE_RATE_MULTIPLIER = 10**6
|
|
|
9
9
|
FULL_PRECISION_MULTIPLIER = 10**18
|
|
10
10
|
|
|
11
11
|
USER_AGENT = "afp-sdk"
|
|
12
|
+
DEFAULT_EXCHANGE_API_VERSION = 1
|
|
12
13
|
EXCHANGE_URL = os.getenv(
|
|
13
|
-
"AFP_EXCHANGE_URL", "https://afp-exchange-
|
|
14
|
+
"AFP_EXCHANGE_URL", "https://afp-exchange-stable.up.railway.app"
|
|
14
15
|
)
|
|
15
16
|
|
|
16
|
-
CHAIN_ID = int(os.getenv("AFP_CHAIN_ID",
|
|
17
|
+
CHAIN_ID = int(os.getenv("AFP_CHAIN_ID", 65000000))
|
|
17
18
|
|
|
18
19
|
CLEARING_DIAMOND_ADDRESS = Web3.to_checksum_address(
|
|
19
20
|
os.getenv(
|
|
20
|
-
"AFP_CLEARING_DIAMOND_ADDRESS", "
|
|
21
|
+
"AFP_CLEARING_DIAMOND_ADDRESS", "0x5B5411F1548254d25360d71FE40cFc1cC983B2A2"
|
|
21
22
|
)
|
|
22
23
|
)
|
|
23
24
|
MARGIN_ACCOUNT_REGISTRY_ADDRESS = Web3.to_checksum_address(
|
|
24
25
|
os.getenv(
|
|
25
26
|
"AFP_MARGIN_ACCOUNT_REGISTRY_ADDRESS",
|
|
26
|
-
"
|
|
27
|
+
"0x99f4FA9Cdce7AD227eB84907936a8FeF2095D846",
|
|
27
28
|
)
|
|
28
29
|
)
|
|
29
30
|
ORACLE_PROVIDER_ADDRESS = Web3.to_checksum_address(
|
|
30
31
|
os.getenv(
|
|
31
|
-
"AFP_ORACLE_PROVIDER_ADDRESS", "
|
|
32
|
+
"AFP_ORACLE_PROVIDER_ADDRESS", "0xF2A2A27da33D30B4BF38D7e186E7B0b1e964e55c"
|
|
32
33
|
)
|
|
33
34
|
)
|
|
34
35
|
PRODUCT_REGISTRY_ADDRESS = Web3.to_checksum_address(
|
|
35
36
|
os.getenv(
|
|
36
|
-
"AFP_PRODUCT_REGISTRY_ADDRESS", "
|
|
37
|
+
"AFP_PRODUCT_REGISTRY_ADDRESS", "0x86B3829471929B115367DA0958f56A6AB844b08e"
|
|
37
38
|
)
|
|
38
39
|
)
|
|
39
40
|
SYSTEM_VIEWER_ADDRESS = Web3.to_checksum_address(
|
|
40
|
-
os.getenv("AFP_SYSTEM_VIEWER_ADDRESS", "
|
|
41
|
+
os.getenv("AFP_SYSTEM_VIEWER_ADDRESS", "0xfF2DFcC44a95cce96E03EfC33C65c8Be671Bae5B")
|
|
41
42
|
)
|
|
@@ -116,7 +116,13 @@ class ExchangeClient:
|
|
|
116
116
|
yield MarketDepthData.model_validate_json(line)
|
|
117
117
|
|
|
118
118
|
def _send_request(
|
|
119
|
-
self,
|
|
119
|
+
self,
|
|
120
|
+
method: str,
|
|
121
|
+
endpoint: str,
|
|
122
|
+
*,
|
|
123
|
+
stream: bool = False,
|
|
124
|
+
api_version: int = config.DEFAULT_EXCHANGE_API_VERSION,
|
|
125
|
+
**kwargs: Any,
|
|
120
126
|
) -> Response:
|
|
121
127
|
kwargs["headers"] = {
|
|
122
128
|
"Content-Type": "application/json",
|
|
@@ -126,7 +132,10 @@ class ExchangeClient:
|
|
|
126
132
|
|
|
127
133
|
try:
|
|
128
134
|
response = self._session.request(
|
|
129
|
-
method,
|
|
135
|
+
method,
|
|
136
|
+
f"{config.EXCHANGE_URL}/v{api_version}{endpoint}",
|
|
137
|
+
stream=stream,
|
|
138
|
+
**kwargs,
|
|
130
139
|
)
|
|
131
140
|
except requests.exceptions.RequestException as request_exception:
|
|
132
141
|
raise ExchangeError(
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
from unittest.mock import Mock
|
|
2
|
+
|
|
3
|
+
from requests import Response
|
|
4
|
+
from requests.adapters import HTTPAdapter
|
|
5
|
+
|
|
6
|
+
from afp import config
|
|
7
|
+
from afp.exchange import ExchangeClient
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def test_send_request(monkeypatch):
|
|
11
|
+
fake_response = Response()
|
|
12
|
+
fake_response.status_code = 200
|
|
13
|
+
mock_send = Mock(return_value=fake_response)
|
|
14
|
+
monkeypatch.setattr(HTTPAdapter, "send", mock_send)
|
|
15
|
+
monkeypatch.setattr(config, "EXCHANGE_URL", "https://foobar.com")
|
|
16
|
+
|
|
17
|
+
client = ExchangeClient()
|
|
18
|
+
client._send_request("POST", "/orders", api_version=2, data="hello")
|
|
19
|
+
|
|
20
|
+
mock_send.assert_called_once()
|
|
21
|
+
request = mock_send.call_args_list[0].args[0]
|
|
22
|
+
assert request.method == "POST"
|
|
23
|
+
assert request.url == "https://foobar.com/v2/orders"
|
|
24
|
+
assert request.body == "hello"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|