synapse-filecoin-sdk 0.1.0__py3-none-any.whl
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.
- pynapse/__init__.py +6 -0
- pynapse/_version.py +1 -0
- pynapse/contracts/__init__.py +34 -0
- pynapse/contracts/abi_registry.py +11 -0
- pynapse/contracts/addresses.json +30 -0
- pynapse/contracts/erc20_abi.json +92 -0
- pynapse/contracts/errorsAbi.json +933 -0
- pynapse/contracts/filecoinPayV1Abi.json +2424 -0
- pynapse/contracts/filecoinWarmStorageServiceAbi.json +2363 -0
- pynapse/contracts/filecoinWarmStorageServiceStateViewAbi.json +651 -0
- pynapse/contracts/generated.py +35 -0
- pynapse/contracts/payments_abi.json +205 -0
- pynapse/contracts/pdpVerifierAbi.json +1266 -0
- pynapse/contracts/providerIdSetAbi.json +161 -0
- pynapse/contracts/serviceProviderRegistryAbi.json +1479 -0
- pynapse/contracts/sessionKeyRegistryAbi.json +147 -0
- pynapse/core/__init__.py +68 -0
- pynapse/core/abis.py +25 -0
- pynapse/core/chains.py +97 -0
- pynapse/core/constants.py +27 -0
- pynapse/core/errors.py +22 -0
- pynapse/core/piece.py +263 -0
- pynapse/core/rand.py +14 -0
- pynapse/core/typed_data.py +320 -0
- pynapse/core/utils.py +30 -0
- pynapse/evm/__init__.py +3 -0
- pynapse/evm/client.py +26 -0
- pynapse/filbeam/__init__.py +3 -0
- pynapse/filbeam/service.py +39 -0
- pynapse/payments/__init__.py +17 -0
- pynapse/payments/service.py +826 -0
- pynapse/pdp/__init__.py +21 -0
- pynapse/pdp/server.py +331 -0
- pynapse/pdp/types.py +38 -0
- pynapse/pdp/verifier.py +82 -0
- pynapse/retriever/__init__.py +12 -0
- pynapse/retriever/async_chain.py +227 -0
- pynapse/retriever/chain.py +209 -0
- pynapse/session/__init__.py +12 -0
- pynapse/session/key.py +30 -0
- pynapse/session/permissions.py +57 -0
- pynapse/session/registry.py +90 -0
- pynapse/sp_registry/__init__.py +11 -0
- pynapse/sp_registry/capabilities.py +25 -0
- pynapse/sp_registry/pdp_capabilities.py +102 -0
- pynapse/sp_registry/service.py +446 -0
- pynapse/sp_registry/types.py +52 -0
- pynapse/storage/__init__.py +57 -0
- pynapse/storage/async_context.py +682 -0
- pynapse/storage/async_manager.py +757 -0
- pynapse/storage/context.py +680 -0
- pynapse/storage/manager.py +758 -0
- pynapse/synapse.py +191 -0
- pynapse/utils/__init__.py +25 -0
- pynapse/utils/constants.py +25 -0
- pynapse/utils/errors.py +3 -0
- pynapse/utils/metadata.py +35 -0
- pynapse/utils/piece_url.py +16 -0
- pynapse/warm_storage/__init__.py +13 -0
- pynapse/warm_storage/service.py +513 -0
- synapse_filecoin_sdk-0.1.0.dist-info/METADATA +74 -0
- synapse_filecoin_sdk-0.1.0.dist-info/RECORD +64 -0
- synapse_filecoin_sdk-0.1.0.dist-info/WHEEL +4 -0
- synapse_filecoin_sdk-0.1.0.dist-info/licenses/LICENSE.md +228 -0
pynapse/synapse.py
ADDED
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
from typing import Optional
|
|
5
|
+
|
|
6
|
+
from eth_account import Account
|
|
7
|
+
from web3 import AsyncWeb3, Web3
|
|
8
|
+
|
|
9
|
+
from pynapse.core.chains import CALIBRATION, MAINNET, Chain, as_chain
|
|
10
|
+
from pynapse.evm import AsyncEVMClient, SyncEVMClient
|
|
11
|
+
from pynapse.payments import AsyncPaymentsService, SyncPaymentsService
|
|
12
|
+
from pynapse.filbeam import FilBeamService
|
|
13
|
+
from pynapse.retriever import ChainRetriever, AsyncChainRetriever
|
|
14
|
+
from pynapse.session import AsyncSessionKeyRegistry, SyncSessionKeyRegistry
|
|
15
|
+
from pynapse.storage import StorageManager, AsyncStorageManager
|
|
16
|
+
from pynapse.sp_registry import AsyncSPRegistryService, SyncSPRegistryService
|
|
17
|
+
from pynapse.warm_storage import AsyncWarmStorageService, SyncWarmStorageService
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class Synapse:
|
|
21
|
+
def __init__(self, web3: Web3, chain: Chain, account_address: str, private_key: Optional[str] = None) -> None:
|
|
22
|
+
self._web3 = web3
|
|
23
|
+
self._chain = chain
|
|
24
|
+
self._account = account_address
|
|
25
|
+
self._private_key = private_key
|
|
26
|
+
self._payments = SyncPaymentsService(web3, chain, account_address, private_key)
|
|
27
|
+
self._providers = SyncSPRegistryService(web3, chain, private_key)
|
|
28
|
+
self._warm_storage = SyncWarmStorageService(web3, chain, private_key)
|
|
29
|
+
# Create retriever for SP-agnostic downloads
|
|
30
|
+
self._retriever = ChainRetriever(self._warm_storage, self._providers)
|
|
31
|
+
# Wire up storage manager with warm_storage, sp_registry, and retriever
|
|
32
|
+
self._storage = StorageManager(
|
|
33
|
+
chain=chain,
|
|
34
|
+
private_key=private_key,
|
|
35
|
+
sp_registry=self._providers,
|
|
36
|
+
warm_storage=self._warm_storage,
|
|
37
|
+
retriever=self._retriever,
|
|
38
|
+
)
|
|
39
|
+
self._session_registry = SyncSessionKeyRegistry(web3, chain, private_key)
|
|
40
|
+
self._filbeam = FilBeamService(chain)
|
|
41
|
+
|
|
42
|
+
@classmethod
|
|
43
|
+
def create(cls, rpc_url: str, chain: Chain | str | int = CALIBRATION, private_key: Optional[str] = None) -> "Synapse":
|
|
44
|
+
client = SyncEVMClient.from_rpc_url(rpc_url)
|
|
45
|
+
chain_obj = as_chain(chain)
|
|
46
|
+
if private_key is None:
|
|
47
|
+
raise ValueError("private_key required to create Synapse")
|
|
48
|
+
account = Account.from_key(private_key)
|
|
49
|
+
return cls(client.web3, chain_obj, account.address, private_key)
|
|
50
|
+
|
|
51
|
+
@property
|
|
52
|
+
def web3(self) -> Web3:
|
|
53
|
+
return self._web3
|
|
54
|
+
|
|
55
|
+
@property
|
|
56
|
+
def chain(self) -> Chain:
|
|
57
|
+
return self._chain
|
|
58
|
+
|
|
59
|
+
@property
|
|
60
|
+
def account(self) -> str:
|
|
61
|
+
return self._account
|
|
62
|
+
|
|
63
|
+
@property
|
|
64
|
+
def payments(self) -> SyncPaymentsService:
|
|
65
|
+
return self._payments
|
|
66
|
+
|
|
67
|
+
@property
|
|
68
|
+
def providers(self) -> SyncSPRegistryService:
|
|
69
|
+
return self._providers
|
|
70
|
+
|
|
71
|
+
@property
|
|
72
|
+
def warm_storage(self) -> SyncWarmStorageService:
|
|
73
|
+
return self._warm_storage
|
|
74
|
+
|
|
75
|
+
@property
|
|
76
|
+
def storage(self) -> StorageManager:
|
|
77
|
+
return self._storage
|
|
78
|
+
|
|
79
|
+
@property
|
|
80
|
+
def session_registry(self) -> SyncSessionKeyRegistry:
|
|
81
|
+
return self._session_registry
|
|
82
|
+
|
|
83
|
+
@property
|
|
84
|
+
def filbeam(self) -> FilBeamService:
|
|
85
|
+
return self._filbeam
|
|
86
|
+
|
|
87
|
+
@property
|
|
88
|
+
def retriever(self) -> ChainRetriever:
|
|
89
|
+
return self._retriever
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
class AsyncSynapse:
|
|
93
|
+
"""
|
|
94
|
+
Async Synapse client for Filecoin Onchain Cloud.
|
|
95
|
+
|
|
96
|
+
Provides full async/await support for Python async applications.
|
|
97
|
+
|
|
98
|
+
Example:
|
|
99
|
+
synapse = await AsyncSynapse.create(rpc_url, chain, private_key)
|
|
100
|
+
|
|
101
|
+
# Upload data
|
|
102
|
+
result = await synapse.storage.upload(data)
|
|
103
|
+
|
|
104
|
+
# Download data
|
|
105
|
+
data = await synapse.storage.download(piece_cid)
|
|
106
|
+
"""
|
|
107
|
+
|
|
108
|
+
def __init__(self, web3: AsyncWeb3, chain: Chain, account_address: str, private_key: Optional[str] = None) -> None:
|
|
109
|
+
self._web3 = web3
|
|
110
|
+
self._chain = chain
|
|
111
|
+
self._account = account_address
|
|
112
|
+
self._private_key = private_key
|
|
113
|
+
self._payments = AsyncPaymentsService(web3, chain, account_address, private_key)
|
|
114
|
+
self._providers = AsyncSPRegistryService(web3, chain, private_key)
|
|
115
|
+
self._warm_storage = AsyncWarmStorageService(web3, chain, private_key)
|
|
116
|
+
# Create async retriever for SP-agnostic downloads
|
|
117
|
+
self._retriever = AsyncChainRetriever(self._warm_storage, self._providers)
|
|
118
|
+
# Wire up async storage manager with warm_storage, sp_registry, and retriever
|
|
119
|
+
self._storage = AsyncStorageManager(
|
|
120
|
+
chain=chain,
|
|
121
|
+
private_key=private_key,
|
|
122
|
+
sp_registry=self._providers,
|
|
123
|
+
warm_storage=self._warm_storage,
|
|
124
|
+
retriever=self._retriever,
|
|
125
|
+
)
|
|
126
|
+
self._session_registry = AsyncSessionKeyRegistry(web3, chain, private_key)
|
|
127
|
+
self._filbeam = FilBeamService(chain)
|
|
128
|
+
|
|
129
|
+
@classmethod
|
|
130
|
+
async def create(
|
|
131
|
+
cls, rpc_url: str, chain: Chain | str | int = CALIBRATION, private_key: Optional[str] = None
|
|
132
|
+
) -> "AsyncSynapse":
|
|
133
|
+
"""
|
|
134
|
+
Create an async Synapse client.
|
|
135
|
+
|
|
136
|
+
Args:
|
|
137
|
+
rpc_url: RPC URL for the Filecoin chain
|
|
138
|
+
chain: Chain configuration (CALIBRATION, MAINNET, or chain ID)
|
|
139
|
+
private_key: Private key for signing transactions
|
|
140
|
+
|
|
141
|
+
Returns:
|
|
142
|
+
Configured AsyncSynapse instance
|
|
143
|
+
"""
|
|
144
|
+
client = AsyncEVMClient.from_rpc_url(rpc_url)
|
|
145
|
+
chain_obj = as_chain(chain)
|
|
146
|
+
if private_key is None:
|
|
147
|
+
raise ValueError("private_key required to create AsyncSynapse")
|
|
148
|
+
account = Account.from_key(private_key)
|
|
149
|
+
return cls(client.web3, chain_obj, account.address, private_key)
|
|
150
|
+
|
|
151
|
+
@property
|
|
152
|
+
def web3(self) -> AsyncWeb3:
|
|
153
|
+
return self._web3
|
|
154
|
+
|
|
155
|
+
@property
|
|
156
|
+
def chain(self) -> Chain:
|
|
157
|
+
return self._chain
|
|
158
|
+
|
|
159
|
+
@property
|
|
160
|
+
def account(self) -> str:
|
|
161
|
+
return self._account
|
|
162
|
+
|
|
163
|
+
@property
|
|
164
|
+
def payments(self) -> AsyncPaymentsService:
|
|
165
|
+
return self._payments
|
|
166
|
+
|
|
167
|
+
@property
|
|
168
|
+
def providers(self) -> AsyncSPRegistryService:
|
|
169
|
+
return self._providers
|
|
170
|
+
|
|
171
|
+
@property
|
|
172
|
+
def warm_storage(self) -> AsyncWarmStorageService:
|
|
173
|
+
return self._warm_storage
|
|
174
|
+
|
|
175
|
+
@property
|
|
176
|
+
def storage(self) -> AsyncStorageManager:
|
|
177
|
+
"""Get the async storage manager for upload/download operations."""
|
|
178
|
+
return self._storage
|
|
179
|
+
|
|
180
|
+
@property
|
|
181
|
+
def session_registry(self) -> AsyncSessionKeyRegistry:
|
|
182
|
+
return self._session_registry
|
|
183
|
+
|
|
184
|
+
@property
|
|
185
|
+
def filbeam(self) -> FilBeamService:
|
|
186
|
+
return self._filbeam
|
|
187
|
+
|
|
188
|
+
@property
|
|
189
|
+
def retriever(self) -> AsyncChainRetriever:
|
|
190
|
+
"""Get the async retriever for SP-agnostic downloads."""
|
|
191
|
+
return self._retriever
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
from .constants import METADATA_KEYS, SIZE_CONSTANTS, TIME_CONSTANTS, TIMING_CONSTANTS, TOKENS
|
|
2
|
+
from .errors import SynapseError, create_error
|
|
3
|
+
from .metadata import (
|
|
4
|
+
combine_metadata,
|
|
5
|
+
metadata_array_to_object,
|
|
6
|
+
metadata_matches,
|
|
7
|
+
metadata_object_to_entries,
|
|
8
|
+
)
|
|
9
|
+
from .piece_url import create_piece_url, create_piece_url_pdp
|
|
10
|
+
|
|
11
|
+
__all__ = [
|
|
12
|
+
"METADATA_KEYS",
|
|
13
|
+
"SIZE_CONSTANTS",
|
|
14
|
+
"TIME_CONSTANTS",
|
|
15
|
+
"TIMING_CONSTANTS",
|
|
16
|
+
"TOKENS",
|
|
17
|
+
"SynapseError",
|
|
18
|
+
"create_error",
|
|
19
|
+
"combine_metadata",
|
|
20
|
+
"metadata_matches",
|
|
21
|
+
"metadata_array_to_object",
|
|
22
|
+
"metadata_object_to_entries",
|
|
23
|
+
"create_piece_url",
|
|
24
|
+
"create_piece_url_pdp",
|
|
25
|
+
]
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
from pynapse.core.constants import SIZE_CONSTANTS, TIME_CONSTANTS
|
|
2
|
+
|
|
3
|
+
TOKENS = {
|
|
4
|
+
"USDFC": "USDFC",
|
|
5
|
+
"FIL": "FIL",
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
METADATA_KEYS = {
|
|
9
|
+
"WITH_CDN": "withCDN",
|
|
10
|
+
"WITH_IPFS_INDEXING": "withIPFSIndexing",
|
|
11
|
+
"IPFS_ROOT_CID": "ipfsRootCID",
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
TIMING_CONSTANTS = {
|
|
15
|
+
"TRANSACTION_PROPAGATION_TIMEOUT_MS": 180000,
|
|
16
|
+
"TRANSACTION_PROPAGATION_POLL_INTERVAL_MS": 2000,
|
|
17
|
+
"DATA_SET_CREATION_TIMEOUT_MS": 7 * 60 * 1000,
|
|
18
|
+
"DATA_SET_CREATION_POLL_INTERVAL_MS": 2000,
|
|
19
|
+
"PIECE_PARKING_TIMEOUT_MS": 7 * 60 * 1000,
|
|
20
|
+
"PIECE_PARKING_POLL_INTERVAL_MS": 5000,
|
|
21
|
+
"TRANSACTION_CONFIRMATIONS": 1,
|
|
22
|
+
"PERMIT_DEADLINE_DURATION": 3600,
|
|
23
|
+
"PIECE_ADDITION_TIMEOUT_MS": 7 * 60 * 1000,
|
|
24
|
+
"PIECE_ADDITION_POLL_INTERVAL_MS": 1000,
|
|
25
|
+
}
|
pynapse/utils/errors.py
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import Dict
|
|
4
|
+
|
|
5
|
+
from .constants import METADATA_KEYS
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def metadata_matches(data_set_metadata: Dict[str, str], requested_metadata: Dict[str, str]) -> bool:
|
|
9
|
+
if len(data_set_metadata) != len(requested_metadata):
|
|
10
|
+
return False
|
|
11
|
+
if not requested_metadata:
|
|
12
|
+
return True
|
|
13
|
+
for key, value in requested_metadata.items():
|
|
14
|
+
if data_set_metadata.get(key) != value:
|
|
15
|
+
return False
|
|
16
|
+
return True
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def combine_metadata(metadata: Dict[str, str] | None = None, with_cdn: bool | None = None) -> Dict[str, str]:
|
|
20
|
+
metadata = metadata or {}
|
|
21
|
+
if with_cdn is None or METADATA_KEYS["WITH_CDN"] in metadata:
|
|
22
|
+
return metadata
|
|
23
|
+
if with_cdn:
|
|
24
|
+
combined = dict(metadata)
|
|
25
|
+
combined[METADATA_KEYS["WITH_CDN"]] = ""
|
|
26
|
+
return combined
|
|
27
|
+
return metadata
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def metadata_array_to_object(entries: list[tuple[str, str]]) -> Dict[str, str]:
|
|
31
|
+
return {key: value for key, value in entries}
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def metadata_object_to_entries(metadata: Dict[str, str]) -> list[dict[str, str]]:
|
|
35
|
+
return [{"key": key, "value": value} for key, value in metadata.items()]
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from urllib.parse import urljoin
|
|
4
|
+
|
|
5
|
+
from pynapse.core.chains import Chain
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def create_piece_url_pdp(cid: str, pdp_url: str) -> str:
|
|
9
|
+
return urljoin(pdp_url.rstrip("/") + "/", f"piece/{cid}")
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def create_piece_url(cid: str, cdn: bool, address: str, chain: Chain, pdp_url: str) -> str:
|
|
13
|
+
if cdn and chain.filbeam_domain:
|
|
14
|
+
endpoint = f"https://{address}.{chain.filbeam_domain}"
|
|
15
|
+
return urljoin(endpoint + "/", cid)
|
|
16
|
+
return create_piece_url_pdp(cid, pdp_url)
|