weil-wallet 0.1.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.
@@ -0,0 +1,11 @@
1
+ Metadata-Version: 2.4
2
+ Name: weil-wallet
3
+ Version: 0.1.0
4
+ Summary: Python SDK for building clients that interact with smart contracts on WeilChain
5
+ Requires-Python: >=3.9
6
+ Requires-Dist: httpx>=0.27.0
7
+ Requires-Dist: coincurve>=21.0.0
8
+ Requires-Dist: bip_utils>=2.9.0
9
+ Requires-Dist: eth-hash[pycryptodome]>=0.5.0
10
+ Provides-Extra: agents
11
+ Requires-Dist: langchain>=0.1.0; extra == "agents"
@@ -0,0 +1,52 @@
1
+ """Weil Wallet SDK for Python — initialize wallet and sign transactions on WeilChain."""
2
+
3
+ from .client import WeilClient, WeilContractClient
4
+ from .constants import (
5
+ AUDIT_APPLET_SVC_NAME,
6
+ IDENTITY_APPLET_SVC_PREFIX,
7
+ PENSIEVE_APPLET_SVC_NAME,
8
+ PUBLISHER_APPLET_SVC_NAME,
9
+ )
10
+ from .contract import ContractId, contract_id_from_str
11
+ from .derived_wallet import (
12
+ MnemonicWallet,
13
+ WalletAccount,
14
+ create_wallet,
15
+ load_wallet,
16
+ pubkey_to_derived_address,
17
+ )
18
+ from .errors import InvalidContractIdError, WalletNotPermittedError
19
+ from .pensieve import Pensieve
20
+ from .streaming import ByteStream
21
+ from .transaction import BaseTransaction, TransactionResult, TransactionStatus, TransactionHeader
22
+ from .wallet import OrgInfo, OrgMembership, SelectedAccount, Wallet
23
+ from .secure_wallet import harden_process
24
+
25
+ __all__ = [
26
+ "WeilClient",
27
+ "WeilContractClient",
28
+ "ContractId",
29
+ "contract_id_from_str",
30
+ "InvalidContractIdError",
31
+ "WalletNotPermittedError",
32
+ "Pensieve",
33
+ "PENSIEVE_APPLET_SVC_NAME",
34
+ "AUDIT_APPLET_SVC_NAME",
35
+ "IDENTITY_APPLET_SVC_PREFIX",
36
+ "PUBLISHER_APPLET_SVC_NAME",
37
+ "ByteStream",
38
+ "BaseTransaction",
39
+ "TransactionResult",
40
+ "TransactionStatus",
41
+ "TransactionHeader",
42
+ "OrgInfo",
43
+ "OrgMembership",
44
+ "SelectedAccount",
45
+ "Wallet",
46
+ "harden_process",
47
+ "MnemonicWallet",
48
+ "WalletAccount",
49
+ "create_wallet",
50
+ "load_wallet",
51
+ "pubkey_to_derived_address",
52
+ ]
@@ -0,0 +1,6 @@
1
+ """API layer for submitting transactions to the platform."""
2
+
3
+ from .platform_api import PlatformApi
4
+ from .request import SubmitTxnRequest
5
+
6
+ __all__ = ["PlatformApi", "SubmitTxnRequest"]
@@ -0,0 +1,75 @@
1
+ """Platform API: submit transaction (normal and streaming)."""
2
+
3
+ from typing import AsyncIterator
4
+
5
+ import httpx
6
+
7
+ from ..transaction import TransactionResult
8
+ from ..utils import compress
9
+ from .request import SubmitTxnRequest
10
+
11
+
12
+ class PlatformApi:
13
+ """Submit transactions to the WeilChain platform."""
14
+
15
+ @staticmethod
16
+ async def _submit_transaction_inner(
17
+ payload: SubmitTxnRequest,
18
+ client: httpx.AsyncClient,
19
+ *,
20
+ is_non_blocking: bool,
21
+ ) -> httpx.Response:
22
+ """GZIP-compress and POST the transaction payload; raise on HTTP error."""
23
+ payload_dict = payload.to_payload_dict()
24
+ tx_payload = compress(payload_dict)
25
+
26
+ files = {
27
+ "transaction": ("transaction_data", tx_payload, "application/octet-stream")
28
+ }
29
+
30
+ headers = {}
31
+
32
+ if is_non_blocking:
33
+ headers["x-non-blocking"] = "true"
34
+
35
+ response = await client.post(
36
+ "/contracts/execute_smartcontract", files=files, headers=headers
37
+ )
38
+
39
+ if not response.is_success:
40
+ body = response.text[:500] if response.text else ""
41
+
42
+ raise RuntimeError(
43
+ f"failed to submit the transaction: HTTP {response.status_code} {body}"
44
+ )
45
+
46
+ return response
47
+
48
+ @staticmethod
49
+ async def submit_transaction(
50
+ payload: SubmitTxnRequest,
51
+ client: httpx.AsyncClient,
52
+ *,
53
+ is_non_blocking: bool = False,
54
+ ) -> TransactionResult:
55
+ """Submit and return the parsed TransactionResult."""
56
+ response = await PlatformApi._submit_transaction_inner(
57
+ payload, client, is_non_blocking=is_non_blocking
58
+ )
59
+ data = response.json()
60
+ return TransactionResult.from_dict(data)
61
+
62
+ @staticmethod
63
+ async def submit_transaction_with_streaming(
64
+ payload: SubmitTxnRequest,
65
+ client: httpx.AsyncClient,
66
+ *,
67
+ is_non_blocking: bool = False,
68
+ ) -> AsyncIterator[bytes]:
69
+ """Submit and return an async iterator of response body chunks."""
70
+ response = await PlatformApi._submit_transaction_inner(
71
+ payload, client, is_non_blocking=is_non_blocking
72
+ )
73
+ async for chunk in response.aiter_bytes():
74
+ if chunk:
75
+ yield chunk
@@ -0,0 +1,76 @@
1
+ """Request types for the platform API (submit transaction)."""
2
+
3
+ from dataclasses import dataclass
4
+ from typing import Any, Optional
5
+
6
+ from ..contract import ContractId
7
+ from ..transaction import TransactionHeader
8
+
9
+
10
+ @dataclass
11
+ class Verifier:
12
+ """Signature verifier strategy tag sent with every transaction."""
13
+
14
+ ty: str = "DefaultVerifier"
15
+
16
+
17
+ @dataclass
18
+ class UserTransaction:
19
+ """The user-visible part of a transaction: which contract method to call and with what args."""
20
+
21
+ ty: str = "SmartContractExecutor"
22
+ contract_address: Optional[ContractId] = None
23
+ contract_method: str = ""
24
+ contract_input_bytes: Optional[str] = None
25
+ should_hide_args: bool = True
26
+
27
+
28
+ @dataclass
29
+ class Transaction:
30
+ """Full transaction envelope: header, verifier, and user payload."""
31
+
32
+ is_xpod: bool = False
33
+ txn_header: Optional[TransactionHeader] = None
34
+ verifier: Optional[Verifier] = None
35
+ user_txn: Optional[UserTransaction] = None
36
+
37
+
38
+ @dataclass
39
+ class SubmitTxnRequest:
40
+ """Top-level request wrapper submitted to the platform API."""
41
+
42
+ transaction: Optional[Transaction] = None
43
+
44
+ def to_payload_dict(self) -> dict[str, Any]:
45
+ """Build the JSON-serializable payload (with 'type' for serde compatibility)."""
46
+ txn = self.transaction
47
+ if not txn or not txn.txn_header or not txn.verifier or not txn.user_txn:
48
+ raise ValueError("incomplete transaction")
49
+ h = txn.txn_header
50
+ return {
51
+ "transaction": {
52
+ "is_xpod": txn.is_xpod,
53
+ "txn_header": {
54
+ "nonce": h.nonce,
55
+ "public_key": h.public_key,
56
+ "from_addr": h.from_addr,
57
+ "to_addr": h.to_addr,
58
+ "signature": h.signature,
59
+ "weilpod_counter": h.weilpod_counter,
60
+ "creation_time": h.creation_time,
61
+ "salt": h.salt,
62
+ # Covered by the signature -- the node rebuilds the digest
63
+ # from what actually arrives, so omitting this would make
64
+ # every org-bearing transaction fail verification.
65
+ "org": h.org.to_dict() if h.org else None,
66
+ },
67
+ "verifier": {"type": txn.verifier.ty},
68
+ "user_txn": {
69
+ "type": txn.user_txn.ty,
70
+ "contract_address": str(txn.user_txn.contract_address),
71
+ "contract_method": txn.user_txn.contract_method,
72
+ "contract_input_bytes": txn.user_txn.contract_input_bytes,
73
+ "should_hide_args": txn.user_txn.should_hide_args,
74
+ },
75
+ }
76
+ }