Skip to content

Commit 9034dde

Browse files
committed
Update documentation with Product API instructions
1 parent 7b3cfcf commit 9034dde

File tree

3 files changed

+117
-34
lines changed

3 files changed

+117
-34
lines changed

DEVELOPMENT.md

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# Development
2+
3+
The package uses [`uv`](https://docs.astral.sh/uv/) as project manager.
4+
5+
- Install dependencies with the `uv sync` command.
6+
- Execute linters with the `uv run poe lint` command.
7+
- Run tests with the `uv run poe test` command.
8+
- Check distributions before release with the `uv run poe check-dist` command.
9+
- Generate markdown API documentation with the `uv run poe doc-gen` command.
10+
11+
## Product Specification
12+
13+
A product specification is represented as a single JSON object, but it is stored
14+
at two different places:
15+
16+
- The object under the `product` attribute is uploaded to the Product Registry contract.
17+
- The other nested objects constitute the extended metadata and are uploaded to IPFS.
18+
- The `extendedMetadata` property of the on-chain product specification stores
19+
the root CID of the IPFS DAG.
20+
21+
### Updating Extended Metadata Schemas
22+
23+
Extended metadata schemas are versioned and an IPFS CID is associated with each
24+
version of each schema. For each schema there is also a matching Pydantic model
25+
in the `afp.schemas` module.
26+
27+
When extended metadata schemas are updated, the related model updates should be
28+
backwards-compatible to make sure existing products that use old schemas can be still
29+
be downloaded from IPFS and parsed.
30+
31+
To modify models in backwards-compatible way, e.g. when the `OracleFallback` schema
32+
is updated from v0.2.0 to v0.2.1, do the following:
33+
34+
- Make a private duplicate of the Pydantic model that needs to be updated, e.g.
35+
duplicate `OracleFallback` as `_OracleFallbackV020`.
36+
- Modify the fields of the public model (`OracleFallback`) to match the updated
37+
schema.
38+
- Update `OracleFallback.SCHEMA_CID` to the CID of the updated schema. Keep the
39+
old CID in `_OracleFallbackV020.SCHEMA_CID`.
40+
41+
With the above changes, if a product is downloaded that still uses the old
42+
`OracleFallback` schema then it will be parsed using the `_OracleFallbackV020`
43+
model, however users will see the updated `OracleFallback` schema as part of the
44+
public API.

README.md

Lines changed: 58 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -162,49 +162,73 @@ fills = trading.order_fills(product_id=PRODUCT_ID)
162162
print(fills)
163163
```
164164

165-
See further code examples in the [examples](./examples/) directory.
165+
### Product API
166166

167-
## Development
167+
Use the `Product` session object to validate a product schema, pin the
168+
specification to IPFS, and register it on-chain.
169+
170+
In order to use the product API for product building, connection parameters of
171+
an IPFS pinning service like [Filebase](https://filebase.com/) should be
172+
included in the `AFP` constructor parameters.
173+
174+
```py
175+
IPFS_API_URL = "https://rpc.filebase.io"
176+
IPFS_API_KEY = os.environ["IPFS_API_KEY"]
177+
178+
app = afp.AFP(
179+
rpc_url=AUTONITY_RPC_URL,
180+
authenticator=afp.PrivateKeyAuthenticator(PRIVATE_KEY),
181+
ipfs_api_url=IPFS_API_URL,
182+
ipfs_api_key=IPFS_API_KEY,
183+
)
184+
185+
product = app.Product()
186+
```
168187

169-
The package uses [`uv`](https://docs.astral.sh/uv/) as project manager.
188+
A JSON product specification can be parsed and validated with
189+
`product.validate_json()`.
170190

171-
- Install dependencies with the `uv sync` command.
172-
- Execute linters with the `uv run poe lint` command.
173-
- Run tests with the `uv run poe test` command.
174-
- Check distributions before release with the `uv run poe check-dist` command.
175-
- Generate markdown API documentation with the `uv run poe doc-gen` command.
191+
```py
192+
with open("product-spec.json") as spec_file:
193+
specification = product.validate_json(spec_file.read())
194+
```
195+
196+
Alternatively, it can also be validated from a Python dictionary.
176197

177-
## Product Specification
198+
```py
199+
spec_dict = {
200+
"product": {...},
201+
"outcome_space": {...},
202+
"outcome_point": {...},
203+
"oracle_config": {...},
204+
"oracle_fallback": {...},
205+
}
206+
specification = product.validate(spec_dict)
207+
```
178208

179-
A product specification is represented as a single JSON object, but it is stored
180-
at two different places:
209+
Product specifications are stored at two different places, the `PredictionProductV1`
210+
object is stored on-chain in the Product Registry contract, while the rest of the
211+
product specification is referred to as _extended metadata_ and it is uploaded to IPFS.
181212

182-
- The object under the `product` attribute is uploaded to the Product Registry contract.
183-
- The other nested objects constitute the extended metadata and are uploaded to IPFS.
184-
- The `extendedMetadata` property of the on-chain product specification stores
185-
the root CID of the IPFS DAG.
213+
The first step therefore is to upload the extended metadata of the product to
214+
IPFS and to pin the root node of the DAG. `product.pin()` returns a modified
215+
copy of the specification that incudes the extended metadata CID.
186216

187-
### Updating Extended Metadata Schemas
217+
```py
218+
pinned_specification = product.pin(specification)
219+
```
188220

189-
Extended metadata schemas are versioned and an IPFS CID is associated with each
190-
version of each schema. For each schema there is also a matching Pydantic model
191-
in the `afp.schemas` module.
221+
The product can then be registered with the Product Registry contract via a
222+
blockchain transaction.
192223

193-
When extended metadata schemas are updated, the related model updates should be
194-
backwards-compatible to make sure existing products that use old schemas can be still
195-
be downloaded from IPFS and parsed.
224+
```
225+
tx = product.register(
226+
pinned_specification, initial_builder_stake=Decimal("10")
227+
)
228+
```
196229

197-
To modify models in backwards-compatible way, e.g. when the `OracleFallback` schema
198-
is updated from v0.2.0 to v0.2.1, do the following:
230+
See further code examples in the [examples](./examples/) directory.
199231

200-
- Make a private duplicate of the Pydantic model that needs to be updated, e.g.
201-
duplicate `OracleFallback` as `_OracleFallbackV020`.
202-
- Modify the fields of the public model (`OracleFallback`) to match the updated
203-
schema.
204-
- Update `OracleFallback.SCHEMA_CID` to the CID of the updated schema. Keep the
205-
old CID in `_OracleFallbackV020.SCHEMA_CID`.
232+
## Development
206233

207-
With the above changes, if a product is downloaded that still uses the old
208-
`OracleFallback` schema then it will be parsed using the `_OracleFallbackV020`
209-
model, however users will see the updated `OracleFallback` schema as part of the
210-
public API.
234+
See [DEVELOPMENT.md](./DEVELOPMENT.md) for developer documentation.

afp/api/product.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,11 @@ def validate(self, product_dict: dict[str, Any]) -> PredictionProduct:
5858
Returns
5959
-------
6060
afp.schemas.PredictionProduct
61+
62+
Raises
63+
------
64+
ValueError, afp.exceptions.ValidationError
65+
If the product specification fails validation.
6166
"""
6267
return self._verify_product_spec(PredictionProduct.model_validate(product_dict))
6368

@@ -74,6 +79,11 @@ def validate_json(self, product_json: str) -> PredictionProduct:
7479
Returns
7580
-------
7681
afp.schemas.PredictionProduct
82+
83+
Raises
84+
------
85+
ValueError, afp.exceptions.ValidationError
86+
If the product specification fails validation.
7787
"""
7888
return self._verify_product_spec(
7989
PredictionProduct.model_validate_json(product_json)
@@ -147,6 +157,11 @@ def pin(self, product_spec: PredictionProduct) -> PredictionProduct:
147157
-------
148158
afp.schemas.PredictionProduct
149159
The product specification with extended metadata CID included.
160+
161+
Raises
162+
------
163+
afp.exceptions.IPFSError
164+
If there is an error uploading to the IPFS node.
150165
"""
151166
extended_metadata_cid = self._ipfs_client.upload_extended_metadata(
152167
ExtendedMetadata(

0 commit comments

Comments
 (0)