afp-sdk 0.5.0__tar.gz → 0.5.1__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 (58) hide show
  1. {afp_sdk-0.5.0 → afp_sdk-0.5.1}/CHANGELOG.md +16 -0
  2. {afp_sdk-0.5.0 → afp_sdk-0.5.1}/PKG-INFO +1 -1
  3. afp_sdk-0.5.1/afp/api/admin.py +69 -0
  4. {afp_sdk-0.5.0 → afp_sdk-0.5.1}/afp/api/product.py +35 -7
  5. {afp_sdk-0.5.0 → afp_sdk-0.5.1}/afp/auth.py +1 -1
  6. {afp_sdk-0.5.0 → afp_sdk-0.5.1}/afp/enums.py +6 -0
  7. {afp_sdk-0.5.0 → afp_sdk-0.5.1}/afp/exchange.py +15 -6
  8. {afp_sdk-0.5.0 → afp_sdk-0.5.1}/afp/schemas.py +14 -3
  9. {afp_sdk-0.5.0 → afp_sdk-0.5.1}/examples/create_product.py +5 -5
  10. {afp_sdk-0.5.0 → afp_sdk-0.5.1}/pyproject.toml +1 -1
  11. {afp_sdk-0.5.0 → afp_sdk-0.5.1}/uv.lock +1 -1
  12. afp_sdk-0.5.0/afp/api/admin.py +0 -42
  13. {afp_sdk-0.5.0 → afp_sdk-0.5.1}/.env.template +0 -0
  14. {afp_sdk-0.5.0 → afp_sdk-0.5.1}/.envrc +0 -0
  15. {afp_sdk-0.5.0 → afp_sdk-0.5.1}/LICENSE +0 -0
  16. {afp_sdk-0.5.0 → afp_sdk-0.5.1}/README.md +0 -0
  17. {afp_sdk-0.5.0 → afp_sdk-0.5.1}/afp/__init__.py +0 -0
  18. {afp_sdk-0.5.0 → afp_sdk-0.5.1}/afp/afp.py +0 -0
  19. {afp_sdk-0.5.0 → afp_sdk-0.5.1}/afp/api/__init__.py +0 -0
  20. {afp_sdk-0.5.0 → afp_sdk-0.5.1}/afp/api/base.py +0 -0
  21. {afp_sdk-0.5.0 → afp_sdk-0.5.1}/afp/api/margin_account.py +0 -0
  22. {afp_sdk-0.5.0 → afp_sdk-0.5.1}/afp/api/trading.py +0 -0
  23. {afp_sdk-0.5.0 → afp_sdk-0.5.1}/afp/bindings/__init__.py +0 -0
  24. {afp_sdk-0.5.0 → afp_sdk-0.5.1}/afp/bindings/auctioneer_facet.py +0 -0
  25. {afp_sdk-0.5.0 → afp_sdk-0.5.1}/afp/bindings/bankruptcy_facet.py +0 -0
  26. {afp_sdk-0.5.0 → afp_sdk-0.5.1}/afp/bindings/clearing_facet.py +0 -0
  27. {afp_sdk-0.5.0 → afp_sdk-0.5.1}/afp/bindings/erc20.py +0 -0
  28. {afp_sdk-0.5.0 → afp_sdk-0.5.1}/afp/bindings/facade.py +0 -0
  29. {afp_sdk-0.5.0 → afp_sdk-0.5.1}/afp/bindings/final_settlement_facet.py +0 -0
  30. {afp_sdk-0.5.0 → afp_sdk-0.5.1}/afp/bindings/margin_account.py +0 -0
  31. {afp_sdk-0.5.0 → afp_sdk-0.5.1}/afp/bindings/margin_account_registry.py +0 -0
  32. {afp_sdk-0.5.0 → afp_sdk-0.5.1}/afp/bindings/mark_price_tracker_facet.py +0 -0
  33. {afp_sdk-0.5.0 → afp_sdk-0.5.1}/afp/bindings/oracle_provider.py +0 -0
  34. {afp_sdk-0.5.0 → afp_sdk-0.5.1}/afp/bindings/product_registry.py +0 -0
  35. {afp_sdk-0.5.0 → afp_sdk-0.5.1}/afp/bindings/system_viewer.py +0 -0
  36. {afp_sdk-0.5.0 → afp_sdk-0.5.1}/afp/bindings/trading_protocol.py +0 -0
  37. {afp_sdk-0.5.0 → afp_sdk-0.5.1}/afp/config.py +0 -0
  38. {afp_sdk-0.5.0 → afp_sdk-0.5.1}/afp/constants.py +0 -0
  39. {afp_sdk-0.5.0 → afp_sdk-0.5.1}/afp/decorators.py +0 -0
  40. {afp_sdk-0.5.0 → afp_sdk-0.5.1}/afp/exceptions.py +0 -0
  41. {afp_sdk-0.5.0 → afp_sdk-0.5.1}/afp/hashing.py +0 -0
  42. {afp_sdk-0.5.0 → afp_sdk-0.5.1}/afp/py.typed +0 -0
  43. {afp_sdk-0.5.0 → afp_sdk-0.5.1}/afp/validators.py +0 -0
  44. {afp_sdk-0.5.0 → afp_sdk-0.5.1}/devenv.lock +0 -0
  45. {afp_sdk-0.5.0 → afp_sdk-0.5.1}/devenv.nix +0 -0
  46. {afp_sdk-0.5.0 → afp_sdk-0.5.1}/devenv.yaml +0 -0
  47. {afp_sdk-0.5.0 → afp_sdk-0.5.1}/examples/cancel_order.py +0 -0
  48. {afp_sdk-0.5.0 → afp_sdk-0.5.1}/examples/execute_trade.py +0 -0
  49. {afp_sdk-0.5.0 → afp_sdk-0.5.1}/tests/__init__.py +0 -0
  50. {afp_sdk-0.5.0 → afp_sdk-0.5.1}/tests/assets/test.key +0 -0
  51. {afp_sdk-0.5.0 → afp_sdk-0.5.1}/tests/test_afp.py +0 -0
  52. {afp_sdk-0.5.0 → afp_sdk-0.5.1}/tests/test_base_api.py +0 -0
  53. {afp_sdk-0.5.0 → afp_sdk-0.5.1}/tests/test_decorators.py +0 -0
  54. {afp_sdk-0.5.0 → afp_sdk-0.5.1}/tests/test_exchange_client.py +0 -0
  55. {afp_sdk-0.5.0 → afp_sdk-0.5.1}/tests/test_hashing.py +0 -0
  56. {afp_sdk-0.5.0 → afp_sdk-0.5.1}/tests/test_schemas.py +0 -0
  57. {afp_sdk-0.5.0 → afp_sdk-0.5.1}/tests/test_signing.py +0 -0
  58. {afp_sdk-0.5.0 → afp_sdk-0.5.1}/tests/test_validators.py +0 -0
@@ -1,3 +1,18 @@
1
+ ## [v0.5.1] - 2025-09-23
2
+
3
+ ### Added
4
+
5
+ - Add `Admin.list_product()` and `Admin.reveal_product()` methods for the new 2-stage product listing process ([#28](https://github.com/autonity/afp-sdk/pull/28))
6
+ - Add `Product.create()`, `Product.register()` and `Product.state()` as short aliases for existing methods ([#27](https://github.com/autonity/afp-sdk/pull/27))
7
+
8
+ ### Changed
9
+
10
+ - Flag `Product.create_product()`, `Product.register_product()` and `Product.product_state()` methods for deprecation ([#27](https://github.com/autonity/afp-sdk/pull/27))
11
+
12
+ ### Removed
13
+
14
+ - Remove `Admin.approve_product()` method ([#28](https://github.com/autonity/afp-sdk/pull/28))
15
+
1
16
  ## [v0.5.0] - 2025-09-18
2
17
 
3
18
  ### Added
@@ -23,6 +38,7 @@
23
38
 
24
39
  _First public release for Forecastathon._
25
40
 
41
+ [v0.5.1]: https://github.com/autonity/afp-sdk/releases/tag/v0.5.1
26
42
  [v0.5.0]: https://github.com/autonity/afp-sdk/releases/tag/v0.5.0
27
43
  [v0.4.0]: https://github.com/autonity/afp-sdk/releases/tag/v0.4.0
28
44
  [v0.3.0]: https://github.com/autonity/afp-sdk/releases/tag/v0.3.0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: afp-sdk
3
- Version: 0.5.0
3
+ Version: 0.5.1
4
4
  Summary: Autonomous Futures Protocol Python SDK
5
5
  Keywords: autonity,web3,trading,crypto,prediction,forecast,markets
6
6
  License-Expression: MIT
@@ -0,0 +1,69 @@
1
+ from .. import validators
2
+ from ..decorators import refresh_token_on_expiry
3
+ from ..enums import ListingState
4
+ from ..schemas import ExchangeProductListingSubmission, ExchangeProductUpdateSubmission
5
+ from .base import ExchangeAPI
6
+
7
+
8
+ class Admin(ExchangeAPI):
9
+ """API for AutEx administration, restricted to AutEx admins."""
10
+
11
+ @refresh_token_on_expiry
12
+ def list_product(self, product_id: str) -> None:
13
+ """Lists a product on the exchange.
14
+
15
+ The product is in private state after listing until it is revealed to the public.
16
+
17
+ Parameters
18
+ ----------
19
+ product_id : str
20
+
21
+ Raises
22
+ ------
23
+ afp.exceptions.AuthorizationError
24
+ If the configured account is not an exchange administrator.
25
+ """
26
+ product_listing = ExchangeProductListingSubmission(id=product_id)
27
+ self._exchange.list_product(product_listing)
28
+
29
+ @refresh_token_on_expiry
30
+ def reveal_product(self, product_id: str) -> None:
31
+ """Makes a product publicly available for trading on the exchange.
32
+
33
+ Parameters
34
+ ----------
35
+ product_id : str
36
+
37
+ Raises
38
+ ------
39
+ afp.exceptions.AuthorizationError
40
+ If the configured account is not an exchange administrator.
41
+ """
42
+ product_update = ExchangeProductUpdateSubmission(
43
+ listing_state=ListingState.PUBLIC
44
+ )
45
+ self._exchange.update_product_listing(
46
+ validators.validate_hexstr32(product_id), product_update
47
+ )
48
+
49
+ @refresh_token_on_expiry
50
+ def delist_product(self, product_id: str) -> None:
51
+ """Delists a product from the exchange.
52
+
53
+ New order submissions of this product will be rejected.
54
+
55
+ Parameters
56
+ ----------
57
+ product_id : str
58
+
59
+ Raises
60
+ ------
61
+ afp.exceptions.AuthorizationError
62
+ If the configured account is not an exchange administrator.
63
+ """
64
+ product_update = ExchangeProductUpdateSubmission(
65
+ listing_state=ListingState.DELISTED
66
+ )
67
+ self._exchange.update_product_listing(
68
+ validators.validate_hexstr32(product_id), product_update
69
+ )
@@ -1,6 +1,7 @@
1
+ import warnings
1
2
  from datetime import datetime
2
3
  from decimal import Decimal
3
- from typing import cast
4
+ from typing import Any, cast
4
5
 
5
6
  from eth_typing.evm import ChecksumAddress
6
7
  from hexbytes import HexBytes
@@ -29,7 +30,7 @@ class Product(ClearingSystemAPI):
29
30
  ### Factories ###
30
31
 
31
32
  @convert_web3_error()
32
- def create_product(
33
+ def create(
33
34
  self,
34
35
  *,
35
36
  symbol: str,
@@ -117,15 +118,24 @@ class Product(ClearingSystemAPI):
117
118
  extended_metadata=extended_metadata,
118
119
  )
119
120
 
121
+ def create_product(self, **kwargs: Any) -> ProductSpecification:
122
+ """Deprecated alias of `Product.create`."""
123
+ warnings.warn(
124
+ "Product.create_product() is deprecated. Use Product.create() instead.",
125
+ DeprecationWarning,
126
+ stacklevel=2,
127
+ )
128
+ return self.create(**kwargs)
129
+
120
130
  ### Transactions ###
121
131
 
122
132
  @convert_web3_error(PRODUCT_REGISTRY_ABI)
123
- def register_product(self, product: ProductSpecification) -> Transaction:
133
+ def register(self, product_specification: ProductSpecification) -> Transaction:
124
134
  """Submits a product specification to the clearing system.
125
135
 
126
136
  Parameters
127
137
  ----------
128
- product : afp.schemas.ProductSpecification
138
+ product_specification : afp.schemas.ProductSpecification
129
139
 
130
140
  Returns
131
141
  -------
@@ -133,7 +143,7 @@ class Product(ClearingSystemAPI):
133
143
  Transaction parameters.
134
144
  """
135
145
  erc20_contract = ERC20(
136
- self._w3, cast(ChecksumAddress, product.collateral_asset)
146
+ self._w3, cast(ChecksumAddress, product_specification.collateral_asset)
137
147
  )
138
148
  decimals = erc20_contract.decimals()
139
149
 
@@ -142,10 +152,19 @@ class Product(ClearingSystemAPI):
142
152
  )
143
153
  return self._transact(
144
154
  product_registry_contract.register(
145
- self._convert_product_specification(product, decimals)
155
+ self._convert_product_specification(product_specification, decimals)
146
156
  )
147
157
  )
148
158
 
159
+ def register_product(self, product: ProductSpecification) -> Transaction:
160
+ """Deprecated alias of `Product.register`."""
161
+ warnings.warn(
162
+ "Product.register_product() is deprecated. Use Product.register() instead.",
163
+ DeprecationWarning,
164
+ stacklevel=2,
165
+ )
166
+ return self.register(product)
167
+
149
168
  @convert_web3_error(CLEARING_DIAMOND_ABI)
150
169
  def initiate_final_settlement(
151
170
  self, product_id: str, accounts: list[str]
@@ -181,7 +200,7 @@ class Product(ClearingSystemAPI):
181
200
  ### Views ###
182
201
 
183
202
  @convert_web3_error(PRODUCT_REGISTRY_ABI)
184
- def product_state(self, product_id: str) -> str:
203
+ def state(self, product_id: str) -> str:
185
204
  """Returns the current state of a product.
186
205
 
187
206
  Parameters
@@ -200,6 +219,15 @@ class Product(ClearingSystemAPI):
200
219
  state = product_registry_contract.state(HexBytes(product_id))
201
220
  return state.name
202
221
 
222
+ def product_state(self, product_id: str) -> str:
223
+ """Deprecated alias of `Product.state`."""
224
+ warnings.warn(
225
+ "Product.product_state() is deprecated. Use Product.state() instead.",
226
+ DeprecationWarning,
227
+ stacklevel=2,
228
+ )
229
+ return self.state(product_id)
230
+
203
231
  @convert_web3_error(PRODUCT_REGISTRY_ABI)
204
232
  def collateral_asset(self, product_id: str) -> str:
205
233
  """Returns the collateral asset of a product.
@@ -52,7 +52,7 @@ class KeyfileAuthenticator(PrivateKeyAuthenticator):
52
52
 
53
53
  Parameters
54
54
  ----------
55
- keyfile : str
55
+ key_file : str
56
56
  The path to the keyfile.
57
57
  password : str
58
58
  The password for decrypting the keyfile.
@@ -1,6 +1,12 @@
1
1
  from enum import StrEnum
2
2
 
3
3
 
4
+ class ListingState(StrEnum):
5
+ PRIVATE = "PRIVATE"
6
+ PUBLIC = "PUBLIC"
7
+ DELISTED = "DELISTED"
8
+
9
+
4
10
  class OrderType(StrEnum):
5
11
  LIMIT_ORDER = "LIMIT_ORDER"
6
12
  CANCEL_ORDER = "CANCEL_ORDER"
@@ -16,7 +16,8 @@ from .exceptions import (
16
16
  from .schemas import (
17
17
  ExchangeParameters,
18
18
  ExchangeProduct,
19
- ExchangeProductSubmission,
19
+ ExchangeProductListingSubmission,
20
+ ExchangeProductUpdateSubmission,
20
21
  LoginSubmission,
21
22
  MarketDepthData,
22
23
  Order,
@@ -60,14 +61,22 @@ class ExchangeClient:
60
61
  return ExchangeProduct(**response.json())
61
62
 
62
63
  # POST /products
63
- def approve_product(self, product_submission: ExchangeProductSubmission) -> None:
64
+ def list_product(
65
+ self, listing_submission: ExchangeProductListingSubmission
66
+ ) -> None:
64
67
  self._send_request(
65
- "POST", "/products", data=product_submission.model_dump_json()
68
+ "POST", "/products", data=listing_submission.model_dump_json()
66
69
  )
67
70
 
68
- # DELETE /products
69
- def delist_product(self, product_id: str) -> None:
70
- self._send_request("DELETE", f"/products/{product_id}")
71
+ # PATCH /products
72
+ def update_product_listing(
73
+ self, product_id: str, update_submission: ExchangeProductUpdateSubmission
74
+ ) -> None:
75
+ self._send_request(
76
+ "PATCH",
77
+ f"/products/{product_id}",
78
+ data=update_submission.model_dump_json(),
79
+ )
71
80
 
72
81
  # POST /orders
73
82
  def submit_order(self, order_submission: OrderSubmission) -> Order:
@@ -15,7 +15,7 @@ from pydantic import (
15
15
  )
16
16
 
17
17
  from . import validators
18
- from .enums import OrderSide, OrderState, OrderType, TradeState
18
+ from .enums import ListingState, OrderSide, OrderState, OrderType, TradeState
19
19
 
20
20
 
21
21
  # Use datetime internally but UNIX timestamp in client-server communication
@@ -53,18 +53,26 @@ class ExchangeParameters(Model):
53
53
  trading_fee_rate: Decimal
54
54
 
55
55
 
56
- # Trading API
56
+ # Admin API
57
57
 
58
58
 
59
- class ExchangeProductSubmission(Model):
59
+ class ExchangeProductListingSubmission(Model):
60
60
  id: Annotated[str, AfterValidator(validators.validate_hexstr32)]
61
61
 
62
62
 
63
+ class ExchangeProductUpdateSubmission(Model):
64
+ listing_state: ListingState
65
+
66
+
67
+ # Trading API
68
+
69
+
63
70
  class ExchangeProduct(Model):
64
71
  id: str
65
72
  symbol: str
66
73
  tick_size: int
67
74
  collateral_asset: str
75
+ listing_state: ListingState
68
76
 
69
77
  def __str__(self) -> str:
70
78
  return self.id
@@ -197,6 +205,9 @@ class ProductSpecification(Model):
197
205
  tradeout_interval: Annotated[int, Field(ge=0)]
198
206
  extended_metadata: str
199
207
 
208
+ def __str__(self) -> str:
209
+ return self.id
210
+
200
211
 
201
212
  # Liquidation API
202
213
 
@@ -14,9 +14,9 @@ def main():
14
14
  app = afp.AFP(
15
15
  rpc_url=AUTONITY_RPC_URL, authenticator=afp.PrivateKeyAuthenticator(PRIVATE_KEY)
16
16
  )
17
- product_api = app.Product()
17
+ product = app.Product()
18
18
 
19
- product = product_api.create_product(
19
+ specification = product.create(
20
20
  symbol="SDK-TEST-1",
21
21
  description="Test Product 1",
22
22
  oracle_address="0xd8A8C5A492Fc2448cFcF980218c0F7D2De4d6FB3",
@@ -35,10 +35,10 @@ def main():
35
35
  tradeout_interval=3600,
36
36
  extended_metadata="QmPK1s3pNYLi9ERiq3BDxKa4XosgWwFRQUydHUtz4YgpqB",
37
37
  )
38
- pprint(product.model_dump())
38
+ pprint(specification.model_dump())
39
39
 
40
- product_api.register_product(product)
41
- print(product_api.product_state(product.id))
40
+ product.register(specification)
41
+ print(product.state(specification.id))
42
42
 
43
43
 
44
44
  if __name__ == "__main__":
@@ -4,7 +4,7 @@ build-backend = "uv_build"
4
4
 
5
5
  [project]
6
6
  name = "afp-sdk"
7
- version = "0.5.0"
7
+ version = "0.5.1"
8
8
  description = "Autonomous Futures Protocol Python SDK"
9
9
  readme = "README.md"
10
10
  license = "MIT"
@@ -13,7 +13,7 @@ wheels = [
13
13
 
14
14
  [[package]]
15
15
  name = "afp-sdk"
16
- version = "0.5.0"
16
+ version = "0.5.1"
17
17
  source = { editable = "." }
18
18
  dependencies = [
19
19
  { name = "decorator" },
@@ -1,42 +0,0 @@
1
- from .. import validators
2
- from ..decorators import refresh_token_on_expiry
3
- from ..schemas import ExchangeProductSubmission
4
- from .base import ExchangeAPI
5
-
6
-
7
- class Admin(ExchangeAPI):
8
- """API for AutEx administration, restricted to AutEx admins."""
9
-
10
- @refresh_token_on_expiry
11
- def approve_product(self, product_id: str) -> None:
12
- """Approves a product for trading on the exchange.
13
-
14
- Parameters
15
- ----------
16
- product_id : str
17
-
18
- Raises
19
- ------
20
- afp.exceptions.AuthorizationError
21
- If the configured account is not an exchange administrator.
22
- """
23
- product = ExchangeProductSubmission(id=product_id)
24
- self._exchange.approve_product(product)
25
-
26
- @refresh_token_on_expiry
27
- def delist_product(self, product_id: str) -> None:
28
- """Delists a product from the exchange.
29
-
30
- New order submissions of this product will be rejected.
31
-
32
- Parameters
33
- ----------
34
- product_id : str
35
-
36
- Raises
37
- ------
38
- afp.exceptions.AuthorizationError
39
- If the configured account is not an exchange administrator.
40
- """
41
- value = validators.validate_hexstr32(product_id)
42
- self._exchange.delist_product(value)
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