Skip to content

Private Deliverable Memo Content#154

Open
schoibs-virtuals wants to merge 21 commits intomainfrom
sdk-upgrade-auth-priv-memo
Open

Private Deliverable Memo Content#154
schoibs-virtuals wants to merge 21 commits intomainfrom
sdk-upgrade-auth-priv-memo

Conversation

@schoibs-virtuals
Copy link
Contributor

@schoibs-virtuals schoibs-virtuals commented Feb 27, 2026

Overview

This PR adds wallet-based authentication for the ACP API and Socket.IO, makes deliverable content private (fetched via API when needed), and updates chain configs and contract client APIs. 19 files changed (~500 additions, ~206 deletions).


1. Authentication (API + Socket)

  • New ACPApiClient in virtuals_acp/client.py:
    • Optional auth via require_auth.
    • Bearer token auth: BearerAuth uses a callable to get access tokens and attaches them to requests.
    • Challenge/verify flow: get_auth_challenge() → sign with contract client → verify_auth_challenge() → receive accessToken.
    • Token refresh: Uses PyJWT (signature not verified) to check expiry; refreshes when within 5 minutes of expiry; retries once on 401 after clearing token.
  • Socket.IO:
    • Connection now uses auth: walletAddress + accessToken from get_access_token().
    • Headers: x-sdk-version, x-sdk-language, x-contract-address.
    • Socket setup moved into init(); optional skip_socket_connection to avoid connecting (e.g. for polling-only usage).
  • Dependency: PyJWT (^2.0.0) added in pyproject.toml.

2. Contract clients & signing

  • Base contract client (base_contract_client.py):
    • Added: get_asset_manager_address() (abstract), sign_typed_data(typed_data: dict) (abstract).
    • get_job_id signature: argument renamed from receipt to response.
  • V1 and V2 contract clients (contract_client.py, contract_client_v2.py):
    • sign_typed_data implemented: EIP-712 style — hash challenge, wrap in replay-safe typed data (domain uses SINGLE_SIGNER_VALIDATION_MODULE_ADDRESS, salt from agent wallet), sign, then _pack_1271_eoa_signature (prefix + entity_id + separator + EOA type + signature bytes).
    • get_asset_manager_address: V1 raises “Not Supported”; V2 returns memo manager’s assetManager().

3. VirtualsACP client API and init

  • Renames (backward-incompatible):
    • contract_clientacp_contract_client (property).
    • agent_wallet_addresswallet_address (checksummed).
  • New constructor options:
    • custom_rpc_url (optional).
    • skip_socket_connection: if True, no Socket.IO connection; caller can use init() later.
  • Internal: Uses ACPApiClient with auth for API calls and no_auth_acp_client where auth isn’t required; acp_url and wallet_address come from the first contract client.

4. Job model & deliverable (private memo content)

  • ACPJob (virtuals_acp/job.py):
    • deliverable: Now an optional field (e.g. DeliverablePayload or reference); no longer derived from memos. Completed memo content is no longer exposed directly; fetching is done via API when needed.
    • get_deliverable() added: returns deliverable; if it’s a string matching api/memo-contents/([0-9]+)$, fetches content via acp_client.get_memo_content(deliverable) and parses JSON or returns raw string.
    • deliver() and deliver_payable(): Phase check — both raise ACPError("Job is not in transaction phase") when job.phase != ACPJobPhase.TRANSACTION.
    • References updated: acp_client.contract_clientacp_client.acp_contract_client, and _base_fare from acp_contract_client.config.base_fare.
  • _get_memo_by_id: Argument type annotated as memo_id: int.

5. Chain configs

  • virtuals_acp/configs/configs.py:
    • TESTNET_CHAINS: Base Sepolia (chain_id 84532) and optional commented chains (Sepolia, Polygon Amoy, etc.).
    • MAINNET_CHAINS: Base mainnet (8453) and optional commented chains.
    • All existing configs (BASE_SEPOLIA_, BASE_MAINNET_, including X402 variants) get a chains argument set to either TESTNET_CHAINS or MAINNET_CHAINS.

6. Examples

  • Deliverable usage: All buyer/evaluator examples now use job.get_deliverable() instead of job.deliverable (cross_chain_transfer_service, prediction_market, trading, polling_mode, skip_evaluation).
  • Agent address: All references to acp_client.agent_address changed to acp_client.wallet_address (polling_mode buyer, evaluator, seller).

7. Tests

  • Unit (test_client.py, test_job.py):
    • contract_clientacp_contract_client, agent_wallet_addresswallet_address.
    • Job payload mocks: memo objects get "state": 1 where applicable.
    • Fare / config: Fare and config mocks get chain_id=8453; client mock uses acp_contract_client and contract_client_by_address.return_value for config.
    • Deliver / deliver_payable: Phase validation tests updated — expect ACPError("Job is not in transaction phase") when not in TRANSACTION; previous “No transaction memo found” / ValueError tests removed or replaced.
    • Deliverable: Tests that asserted on job.deliverable are commented out with a TODO to align with get_deliverable().
    • Evaluate: Job phase set to ACPJobPhase.TRANSACTION where needed; memo mocks get type = MemoType.MESSAGE.
  • Integration (test_client_integration.py): agent_addresswallet_address in assertions and get_agent calls.

8. Other

  • virtuals_acp/web3.py: Comment added: “TODO: implement wrapper methods in base_contract_client”.

Breaking changes (for callers)

Before After
acp_client.contract_client acp_client.acp_contract_client
acp_client.agent_wallet_address / agent_address acp_client.wallet_address
job.deliverable (property from memo) job.get_deliverable() (may call API for memo content)
deliver() / deliver_payable() only checked memo phase Must be in ACPJobPhase.TRANSACTION or raise ACPError

@Ang-dot Ang-dot force-pushed the sdk-upgrade-auth-priv-memo branch from 312b79b to e897a4e Compare March 2, 2026 10:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants