mppi-protocol 0.1.2__tar.gz → 0.1.4__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.
- mppi_protocol-0.1.4/PKG-INFO +114 -0
- mppi_protocol-0.1.4/README.md +99 -0
- {mppi_protocol-0.1.2 → mppi_protocol-0.1.4}/pyproject.toml +1 -1
- {mppi_protocol-0.1.2 → mppi_protocol-0.1.4}/src/mppi_protocol/capabilities.py +36 -0
- mppi_protocol-0.1.4/src/mppi_protocol/chain.py +1809 -0
- mppi_protocol-0.1.4/src/mppi_protocol/circle.py +1089 -0
- {mppi_protocol-0.1.2 → mppi_protocol-0.1.4}/src/mppi_protocol/contract.py +10 -0
- {mppi_protocol-0.1.2 → mppi_protocol-0.1.4}/src/mppi_protocol/discovery.py +9 -3
- mppi_protocol-0.1.4/src/mppi_protocol/follower.py +623 -0
- mppi_protocol-0.1.4/src/mppi_protocol/http.py +295 -0
- {mppi_protocol-0.1.2 → mppi_protocol-0.1.4}/src/mppi_protocol/local_state.py +28 -2
- {mppi_protocol-0.1.2 → mppi_protocol-0.1.4}/src/mppi_protocol/operations.py +31 -11
- {mppi_protocol-0.1.2 → mppi_protocol-0.1.4}/src/mppi_protocol/signing.py +49 -0
- {mppi_protocol-0.1.2 → mppi_protocol-0.1.4}/src/mppi_protocol/types.py +10 -1
- mppi_protocol-0.1.4/tests/test_chain.py +1973 -0
- {mppi_protocol-0.1.2 → mppi_protocol-0.1.4}/tests/test_checkpoint.py +31 -0
- mppi_protocol-0.1.4/tests/test_circle.py +1649 -0
- {mppi_protocol-0.1.2 → mppi_protocol-0.1.4}/tests/test_circle_activation.py +26 -41
- {mppi_protocol-0.1.2 → mppi_protocol-0.1.4}/tests/test_deployment.py +9 -0
- mppi_protocol-0.1.4/tests/test_follower.py +1031 -0
- mppi_protocol-0.1.4/tests/test_funding_check.py +221 -0
- mppi_protocol-0.1.4/tests/test_http_transport.py +694 -0
- {mppi_protocol-0.1.2 → mppi_protocol-0.1.4}/tests/test_operations.py +33 -0
- mppi_protocol-0.1.2/PKG-INFO +0 -41
- mppi_protocol-0.1.2/README.md +0 -26
- mppi_protocol-0.1.2/src/mppi_protocol/chain.py +0 -835
- mppi_protocol-0.1.2/src/mppi_protocol/circle.py +0 -749
- mppi_protocol-0.1.2/src/mppi_protocol/follower.py +0 -323
- mppi_protocol-0.1.2/src/mppi_protocol/http.py +0 -126
- mppi_protocol-0.1.2/tests/test_chain.py +0 -1058
- mppi_protocol-0.1.2/tests/test_circle.py +0 -618
- mppi_protocol-0.1.2/tests/test_follower.py +0 -358
- mppi_protocol-0.1.2/tests/test_http_transport.py +0 -298
- {mppi_protocol-0.1.2 → mppi_protocol-0.1.4}/.gitignore +0 -0
- {mppi_protocol-0.1.2 → mppi_protocol-0.1.4}/LICENSE +0 -0
- {mppi_protocol-0.1.2 → mppi_protocol-0.1.4}/src/mppi/__init__.py +0 -0
- {mppi_protocol-0.1.2 → mppi_protocol-0.1.4}/src/mppi/py.typed +0 -0
- {mppi_protocol-0.1.2 → mppi_protocol-0.1.4}/src/mppi/v1/__init__.py +0 -0
- {mppi_protocol-0.1.2 → mppi_protocol-0.1.4}/src/mppi/v1/mppi_pb2.py +0 -0
- {mppi_protocol-0.1.2 → mppi_protocol-0.1.4}/src/mppi/v1/mppi_pb2.pyi +0 -0
- {mppi_protocol-0.1.2 → mppi_protocol-0.1.4}/src/mppi/v1/mppi_pb2_grpc.py +0 -0
- {mppi_protocol-0.1.2 → mppi_protocol-0.1.4}/src/mppi_protocol/__init__.py +0 -0
- {mppi_protocol-0.1.2 → mppi_protocol-0.1.4}/src/mppi_protocol/_observers.py +0 -0
- {mppi_protocol-0.1.2 → mppi_protocol-0.1.4}/src/mppi_protocol/accounting.py +0 -0
- {mppi_protocol-0.1.2 → mppi_protocol-0.1.4}/src/mppi_protocol/amounts.py +0 -0
- {mppi_protocol-0.1.2 → mppi_protocol-0.1.4}/src/mppi_protocol/catalog.py +0 -0
- {mppi_protocol-0.1.2 → mppi_protocol-0.1.4}/src/mppi_protocol/contract_abi.json +0 -0
- {mppi_protocol-0.1.2 → mppi_protocol-0.1.4}/src/mppi_protocol/deployment.py +0 -0
- {mppi_protocol-0.1.2 → mppi_protocol-0.1.4}/src/mppi_protocol/errors.py +0 -0
- {mppi_protocol-0.1.2 → mppi_protocol-0.1.4}/src/mppi_protocol/py.typed +0 -0
- {mppi_protocol-0.1.2 → mppi_protocol-0.1.4}/src/mppi_protocol/registry.py +0 -0
- {mppi_protocol-0.1.2 → mppi_protocol-0.1.4}/src/mppi_protocol/wire.py +0 -0
- {mppi_protocol-0.1.2 → mppi_protocol-0.1.4}/tests/test_accounting.py +0 -0
- {mppi_protocol-0.1.2 → mppi_protocol-0.1.4}/tests/test_amounts.py +0 -0
- {mppi_protocol-0.1.2 → mppi_protocol-0.1.4}/tests/test_catalog.py +0 -0
- {mppi_protocol-0.1.2 → mppi_protocol-0.1.4}/tests/test_contract_calls.py +0 -0
- {mppi_protocol-0.1.2 → mppi_protocol-0.1.4}/tests/test_discovery_validation.py +0 -0
- {mppi_protocol-0.1.2 → mppi_protocol-0.1.4}/tests/test_fixture_schema.py +0 -0
- {mppi_protocol-0.1.2 → mppi_protocol-0.1.4}/tests/test_observers.py +0 -0
- {mppi_protocol-0.1.2 → mppi_protocol-0.1.4}/tests/test_registry.py +0 -0
- {mppi_protocol-0.1.2 → mppi_protocol-0.1.4}/tests/test_runtime_wire.py +0 -0
- {mppi_protocol-0.1.2 → mppi_protocol-0.1.4}/tests/test_signing.py +0 -0
- {mppi_protocol-0.1.2 → mppi_protocol-0.1.4}/tests/test_signing_vectors.py +0 -0
- {mppi_protocol-0.1.2 → mppi_protocol-0.1.4}/tests/test_value_types.py +0 -0
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: mppi-protocol
|
|
3
|
+
Version: 0.1.4
|
|
4
|
+
Summary: Shared MPPI wire bindings and exact payment primitives
|
|
5
|
+
License-Expression: Apache-2.0
|
|
6
|
+
License-File: LICENSE
|
|
7
|
+
Requires-Python: >=3.12
|
|
8
|
+
Requires-Dist: eth-abi==6.0.0
|
|
9
|
+
Requires-Dist: eth-account==0.14.0
|
|
10
|
+
Requires-Dist: googleapis-common-protos==1.75.4
|
|
11
|
+
Requires-Dist: grpcio==1.84.0
|
|
12
|
+
Requires-Dist: protobuf==7.36.2
|
|
13
|
+
Requires-Dist: pycryptodome==3.23.0
|
|
14
|
+
Description-Content-Type: text/markdown
|
|
15
|
+
|
|
16
|
+
# MPPI Python protocol support
|
|
17
|
+
|
|
18
|
+
Internal shared distribution for the agent and provider SDKs. It contains the
|
|
19
|
+
generated `mppi.v1` wire bindings and `mppi_protocol` exact payment primitives.
|
|
20
|
+
It is not another role SDK.
|
|
21
|
+
|
|
22
|
+
The implementation validates catalogs and report transitions, computes exact
|
|
23
|
+
amounts, signs and verifies fixed-session proofs, prepares contract calls and
|
|
24
|
+
checks canonical receipt evidence. Version `0.1.1` also supplies shared discovery
|
|
25
|
+
validation and the Circle Agent Wallet adapter used by both Python roles.
|
|
26
|
+
Version `0.1.4`, used by `mppi-agent` 0.1.6 and `mppi-provider` 0.2.0, adds:
|
|
27
|
+
|
|
28
|
+
- `ChainFollower.unwatch_session`, which stops reading a session and drops the
|
|
29
|
+
block that proved it;
|
|
30
|
+
- `ChainFollower.follow(funding=(agent_id, wallet))` and `unwatch_funding`: each
|
|
31
|
+
refresh also reads the registry's funding wallet for that agent id and the
|
|
32
|
+
wallet's code (`ChainSnapshot.funding`, a `FundingState`) at no extra round
|
|
33
|
+
trip, and `ChainReader.funding_signature` checks a funding signature at that
|
|
34
|
+
block in one;
|
|
35
|
+
- `ChainReader.opening_transaction`, one `eth_getLogs` naming the transaction
|
|
36
|
+
of a session's `SessionOpened`, a lead to prove by its receipt;
|
|
37
|
+
- `ChainFollower.confirm(..., observation)`: a refresh behind the block that
|
|
38
|
+
proved a confirmed state is lag (`ChainLagError`), not a contradiction. Once
|
|
39
|
+
refreshes have stayed behind it for longer than `max_age_ms`,
|
|
40
|
+
`confirmed_readiness` reports that session `STATE_UNAVAILABLE` until one
|
|
41
|
+
reaches it;
|
|
42
|
+
- `TransportError.retry_after`. A transient read is repeated after a random
|
|
43
|
+
share of its wait and after any `Retry-After` that fits the existing bound,
|
|
44
|
+
and a batch repeats only its refused entries;
|
|
45
|
+
- `CircleAgentWallet.retire(operation_refs=..., at=...)` and `near_capacity`.
|
|
46
|
+
A journal record keeps its call's digest instead of the call, and only the
|
|
47
|
+
16 MiB bound limits the journal; `retire` marks records, in the journal,
|
|
48
|
+
with the time from which they are forgotten once they hold a transaction
|
|
49
|
+
hash. A failed command's error names the CLI's listed error code and an
|
|
50
|
+
unknown result carries its cause. An execute checks the CLI and wallet first
|
|
51
|
+
unless a check began within 60 seconds, and after any failed command the next
|
|
52
|
+
execute or signature checks again. The journal's lock is held only while the
|
|
53
|
+
journal is read or replaced, never across a Circle command; within one
|
|
54
|
+
process the adapter runs one operation at a time, CLI commands included. An
|
|
55
|
+
execute or reconcile waits for the lock up to `timeout_seconds`, and one that
|
|
56
|
+
cannot then
|
|
57
|
+
record Circle's answer returns `UNKNOWN` with its transaction id and hash,
|
|
58
|
+
written into the journal at the next journal step; a failed save keeps them
|
|
59
|
+
in memory and does not fail that step. A reconcile withdraws a
|
|
60
|
+
record's retirement mark. An execute refused for an invalid reference, or
|
|
61
|
+
once the journal shows no record of its reference, raises
|
|
62
|
+
`CircleNotSubmittedError`;
|
|
63
|
+
- local records wait up to one second for a lock that a spawned child process
|
|
64
|
+
still holds, or as long as `Checkpoint(..., lock_wait=...)` gives;
|
|
65
|
+
- `ChainFollower.watch_session`: watches that wait behind a refresh are read
|
|
66
|
+
together by the next one, so many sessions watched at once, as a provider's
|
|
67
|
+
recoveries at startup watch theirs, take a few refreshes rather than one each;
|
|
68
|
+
- a snapshot splits its views across Multicall3 calls of at most 512 views, each
|
|
69
|
+
anchored to the snapshot's block, and `HttpJsonRpc` keeps each request within
|
|
70
|
+
1 MiB, so a large watch set takes more round trips instead of failing every
|
|
71
|
+
refresh; a backend that still has not imported a block (-32014) once the
|
|
72
|
+
repeats are spent is `ChainLagError`.
|
|
73
|
+
|
|
74
|
+
Every interface change is additive. One behaviour narrows: `HttpTransport.request`
|
|
75
|
+
refuses a request body over 1 MiB before sending it, as the Rust transport does.
|
|
76
|
+
One exception changes: for an invalid reference, or a call for another network
|
|
77
|
+
or over 60 KiB, `CircleAgentWallet.execute` raises `CircleNotSubmittedError`,
|
|
78
|
+
which is not a `ValidationError`, where `0.1.3` raised `ValidationError`.
|
|
79
|
+
Earlier releases refuse a Circle journal this one has saved, so do not
|
|
80
|
+
downgrade over it.
|
|
81
|
+
Version `0.1.3`, used by `mppi-agent` 0.1.4, 0.1.4.1 and 0.1.5, keeps HTTP connections
|
|
82
|
+
alive and sends a step's reads as one JSON-RPC batch (`HttpJsonRpc.call_many`),
|
|
83
|
+
and treats a read timeout as transient. It adds:
|
|
84
|
+
|
|
85
|
+
- `ChainReader.latest`, a one-request snapshot through Multicall3, and the
|
|
86
|
+
batched steps `observe` and `session_at`; on final networks
|
|
87
|
+
(`DeploymentProfile.instant_finality`) receipts alone prove operations;
|
|
88
|
+
- `ChainReader.funding`, which checks a funding signature as USDC does;
|
|
89
|
+
- `ChainFollower.follow`, `refresh_at`, `confirm`, `confirmed_readiness` and
|
|
90
|
+
`on_refresh_failure`, for requests that read no chain;
|
|
91
|
+
- `NotSubmittedError` and `OperationResult.cause`.
|
|
92
|
+
|
|
93
|
+
Three changes are not additive. `OpeningEvidence` and `ClosingEvidence` carry the
|
|
94
|
+
proving `observation` instead of a `Block`, and `ChainReader.agent_wallet` takes
|
|
95
|
+
that observation. The Circle adapter pins no account code:
|
|
96
|
+
`CircleAgentWallet(chain=..., address=..., checkpoint_path=...)` replaces the
|
|
97
|
+
`wallet` and `implementation` pins, and its journal is format 2 (format 1 still
|
|
98
|
+
loads).
|
|
99
|
+
Version `0.1.2`, used by `mppi-agent` 0.1.3, adds bounded repeats of transient
|
|
100
|
+
read-only JSON-RPC calls, lag-tolerant chain following
|
|
101
|
+
(`ChainLagError`, `last_refresh_failure`), `HookError.detail` and
|
|
102
|
+
`TransportError.transient`, and accepts checkpoint format 2; every change is
|
|
103
|
+
additive.
|
|
104
|
+
These building blocks do not authorize inference or store provider state.
|
|
105
|
+
|
|
106
|
+
See [the SDK interfaces](../../docs/sdk-interfaces.md) for the implemented surface
|
|
107
|
+
and runtime integration boundaries.
|
|
108
|
+
|
|
109
|
+
The [runtime reference](../../docs/python-runtime.md) describes the implemented
|
|
110
|
+
trust boundaries, dependency adapters and evidence limitations.
|
|
111
|
+
|
|
112
|
+
## License
|
|
113
|
+
|
|
114
|
+
Copyright 2026 MPPI contributors. Licensed under the [Apache License, Version 2.0](LICENSE).
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# MPPI Python protocol support
|
|
2
|
+
|
|
3
|
+
Internal shared distribution for the agent and provider SDKs. It contains the
|
|
4
|
+
generated `mppi.v1` wire bindings and `mppi_protocol` exact payment primitives.
|
|
5
|
+
It is not another role SDK.
|
|
6
|
+
|
|
7
|
+
The implementation validates catalogs and report transitions, computes exact
|
|
8
|
+
amounts, signs and verifies fixed-session proofs, prepares contract calls and
|
|
9
|
+
checks canonical receipt evidence. Version `0.1.1` also supplies shared discovery
|
|
10
|
+
validation and the Circle Agent Wallet adapter used by both Python roles.
|
|
11
|
+
Version `0.1.4`, used by `mppi-agent` 0.1.6 and `mppi-provider` 0.2.0, adds:
|
|
12
|
+
|
|
13
|
+
- `ChainFollower.unwatch_session`, which stops reading a session and drops the
|
|
14
|
+
block that proved it;
|
|
15
|
+
- `ChainFollower.follow(funding=(agent_id, wallet))` and `unwatch_funding`: each
|
|
16
|
+
refresh also reads the registry's funding wallet for that agent id and the
|
|
17
|
+
wallet's code (`ChainSnapshot.funding`, a `FundingState`) at no extra round
|
|
18
|
+
trip, and `ChainReader.funding_signature` checks a funding signature at that
|
|
19
|
+
block in one;
|
|
20
|
+
- `ChainReader.opening_transaction`, one `eth_getLogs` naming the transaction
|
|
21
|
+
of a session's `SessionOpened`, a lead to prove by its receipt;
|
|
22
|
+
- `ChainFollower.confirm(..., observation)`: a refresh behind the block that
|
|
23
|
+
proved a confirmed state is lag (`ChainLagError`), not a contradiction. Once
|
|
24
|
+
refreshes have stayed behind it for longer than `max_age_ms`,
|
|
25
|
+
`confirmed_readiness` reports that session `STATE_UNAVAILABLE` until one
|
|
26
|
+
reaches it;
|
|
27
|
+
- `TransportError.retry_after`. A transient read is repeated after a random
|
|
28
|
+
share of its wait and after any `Retry-After` that fits the existing bound,
|
|
29
|
+
and a batch repeats only its refused entries;
|
|
30
|
+
- `CircleAgentWallet.retire(operation_refs=..., at=...)` and `near_capacity`.
|
|
31
|
+
A journal record keeps its call's digest instead of the call, and only the
|
|
32
|
+
16 MiB bound limits the journal; `retire` marks records, in the journal,
|
|
33
|
+
with the time from which they are forgotten once they hold a transaction
|
|
34
|
+
hash. A failed command's error names the CLI's listed error code and an
|
|
35
|
+
unknown result carries its cause. An execute checks the CLI and wallet first
|
|
36
|
+
unless a check began within 60 seconds, and after any failed command the next
|
|
37
|
+
execute or signature checks again. The journal's lock is held only while the
|
|
38
|
+
journal is read or replaced, never across a Circle command; within one
|
|
39
|
+
process the adapter runs one operation at a time, CLI commands included. An
|
|
40
|
+
execute or reconcile waits for the lock up to `timeout_seconds`, and one that
|
|
41
|
+
cannot then
|
|
42
|
+
record Circle's answer returns `UNKNOWN` with its transaction id and hash,
|
|
43
|
+
written into the journal at the next journal step; a failed save keeps them
|
|
44
|
+
in memory and does not fail that step. A reconcile withdraws a
|
|
45
|
+
record's retirement mark. An execute refused for an invalid reference, or
|
|
46
|
+
once the journal shows no record of its reference, raises
|
|
47
|
+
`CircleNotSubmittedError`;
|
|
48
|
+
- local records wait up to one second for a lock that a spawned child process
|
|
49
|
+
still holds, or as long as `Checkpoint(..., lock_wait=...)` gives;
|
|
50
|
+
- `ChainFollower.watch_session`: watches that wait behind a refresh are read
|
|
51
|
+
together by the next one, so many sessions watched at once, as a provider's
|
|
52
|
+
recoveries at startup watch theirs, take a few refreshes rather than one each;
|
|
53
|
+
- a snapshot splits its views across Multicall3 calls of at most 512 views, each
|
|
54
|
+
anchored to the snapshot's block, and `HttpJsonRpc` keeps each request within
|
|
55
|
+
1 MiB, so a large watch set takes more round trips instead of failing every
|
|
56
|
+
refresh; a backend that still has not imported a block (-32014) once the
|
|
57
|
+
repeats are spent is `ChainLagError`.
|
|
58
|
+
|
|
59
|
+
Every interface change is additive. One behaviour narrows: `HttpTransport.request`
|
|
60
|
+
refuses a request body over 1 MiB before sending it, as the Rust transport does.
|
|
61
|
+
One exception changes: for an invalid reference, or a call for another network
|
|
62
|
+
or over 60 KiB, `CircleAgentWallet.execute` raises `CircleNotSubmittedError`,
|
|
63
|
+
which is not a `ValidationError`, where `0.1.3` raised `ValidationError`.
|
|
64
|
+
Earlier releases refuse a Circle journal this one has saved, so do not
|
|
65
|
+
downgrade over it.
|
|
66
|
+
Version `0.1.3`, used by `mppi-agent` 0.1.4, 0.1.4.1 and 0.1.5, keeps HTTP connections
|
|
67
|
+
alive and sends a step's reads as one JSON-RPC batch (`HttpJsonRpc.call_many`),
|
|
68
|
+
and treats a read timeout as transient. It adds:
|
|
69
|
+
|
|
70
|
+
- `ChainReader.latest`, a one-request snapshot through Multicall3, and the
|
|
71
|
+
batched steps `observe` and `session_at`; on final networks
|
|
72
|
+
(`DeploymentProfile.instant_finality`) receipts alone prove operations;
|
|
73
|
+
- `ChainReader.funding`, which checks a funding signature as USDC does;
|
|
74
|
+
- `ChainFollower.follow`, `refresh_at`, `confirm`, `confirmed_readiness` and
|
|
75
|
+
`on_refresh_failure`, for requests that read no chain;
|
|
76
|
+
- `NotSubmittedError` and `OperationResult.cause`.
|
|
77
|
+
|
|
78
|
+
Three changes are not additive. `OpeningEvidence` and `ClosingEvidence` carry the
|
|
79
|
+
proving `observation` instead of a `Block`, and `ChainReader.agent_wallet` takes
|
|
80
|
+
that observation. The Circle adapter pins no account code:
|
|
81
|
+
`CircleAgentWallet(chain=..., address=..., checkpoint_path=...)` replaces the
|
|
82
|
+
`wallet` and `implementation` pins, and its journal is format 2 (format 1 still
|
|
83
|
+
loads).
|
|
84
|
+
Version `0.1.2`, used by `mppi-agent` 0.1.3, adds bounded repeats of transient
|
|
85
|
+
read-only JSON-RPC calls, lag-tolerant chain following
|
|
86
|
+
(`ChainLagError`, `last_refresh_failure`), `HookError.detail` and
|
|
87
|
+
`TransportError.transient`, and accepts checkpoint format 2; every change is
|
|
88
|
+
additive.
|
|
89
|
+
These building blocks do not authorize inference or store provider state.
|
|
90
|
+
|
|
91
|
+
See [the SDK interfaces](../../docs/sdk-interfaces.md) for the implemented surface
|
|
92
|
+
and runtime integration boundaries.
|
|
93
|
+
|
|
94
|
+
The [runtime reference](../../docs/python-runtime.md) describes the implemented
|
|
95
|
+
trust boundaries, dependency adapters and evidence limitations.
|
|
96
|
+
|
|
97
|
+
## License
|
|
98
|
+
|
|
99
|
+
Copyright 2026 MPPI contributors. Licensed under the [Apache License, Version 2.0](LICENSE).
|
|
@@ -51,7 +51,27 @@ class FundingAuthorization:
|
|
|
51
51
|
)
|
|
52
52
|
|
|
53
53
|
|
|
54
|
+
class NotSubmittedError(RuntimeError):
|
|
55
|
+
"""A wallet adapter's own durable record proves the call never reached the
|
|
56
|
+
wallet service: nothing was submitted and the reference binds nothing, so
|
|
57
|
+
it may be sent again, with this call or another.
|
|
58
|
+
|
|
59
|
+
Raise it only with that proof. Any other failure leaves the outcome unknown.
|
|
60
|
+
"""
|
|
61
|
+
|
|
62
|
+
|
|
54
63
|
class TransactionWallet(Protocol):
|
|
64
|
+
"""A wallet adapter's transactions. ``execute`` sends ``call`` once from
|
|
65
|
+
``address`` with zero native value and durably binds ``operation_ref`` to
|
|
66
|
+
it first; ``reconcile`` reports that same submission and never sends.
|
|
67
|
+
|
|
68
|
+
The runtimes may call ``execute`` and ``reconcile`` for different
|
|
69
|
+
operations, or the same one, at once, from several threads (a recovery
|
|
70
|
+
reads before taking the runtime's locks), so an adapter serializes access
|
|
71
|
+
to its own records, as ``CircleAgentWallet`` does.
|
|
72
|
+
Every requirement is in docs/sdk-interfaces.md, Wallet requirements.
|
|
73
|
+
"""
|
|
74
|
+
|
|
55
75
|
@property
|
|
56
76
|
def address(self) -> bytes: ...
|
|
57
77
|
|
|
@@ -61,6 +81,22 @@ class TransactionWallet(Protocol):
|
|
|
61
81
|
|
|
62
82
|
|
|
63
83
|
class FundingWallet(TransactionWallet, Protocol):
|
|
84
|
+
"""An agent's funding wallet from any provider, behind a thin adapter.
|
|
85
|
+
|
|
86
|
+
``sign_funding_authorization`` returns bytes USDC accepts for exactly that
|
|
87
|
+
authorization from ``address``: an ECDSA signature for an account without
|
|
88
|
+
code, or bytes its ERC-1271 isValidSignature accepts. Before submitting
|
|
89
|
+
an opening, the agent checks them and that its ERC-8004 agent id binds
|
|
90
|
+
``address``. No wallet implementation or version is pinned.
|
|
91
|
+
|
|
92
|
+
A wallet whose service creates the signature when it executes declares an
|
|
93
|
+
optional ``signs_at_execute = True``: ``sign_funding_authorization`` then
|
|
94
|
+
returns a placeholder that ``execute`` replaces. The agent neither verifies
|
|
95
|
+
nor simulates the placeholder; it still checks the agent-id binding, and
|
|
96
|
+
USDC verifies the real signature on chain.
|
|
97
|
+
Every requirement is in docs/sdk-interfaces.md, Wallet requirements.
|
|
98
|
+
"""
|
|
99
|
+
|
|
64
100
|
def sign_funding_authorization(self, authorization: FundingAuthorization) -> bytes: ...
|
|
65
101
|
|
|
66
102
|
|