Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add the foundation for the Python port of the batch-settlement payment scheme: contract addresses, EIP-712 type definitions, and ABI declarations, mirroring the TypeScript SDK introduced in [#2061](https://github.com/x402-foundation/x402/pull/2061). Types, encoding, signer protocol, utilities, and EIP-712 cross-language fixtures land in subsequent stacked PRs.
111 changes: 111 additions & 0 deletions python/x402/mechanisms/evm/batch_settlement/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
"""x402 batch-settlement mechanism (Python port).

Mirrors ``typescript/packages/mechanisms/evm/src/batch-settlement/``.

This package is being introduced incrementally; PR1 lands the foundation
(constants, ABI, types, encoding helpers, signer protocol). Client,
facilitator, server, storage, and recovery follow in stacked PRs (see
``docs/x402/batch-settlement/plan.md`` in the project tracker).
"""

from .abi import (
batch_settlement_abi,
channel_config_components,
erc20_balance_of_abi,
)
from .constants import (
BATCH_SETTLEMENT_ADDRESS,
BATCH_SETTLEMENT_DOMAIN,
BATCH_SETTLEMENT_SCHEME,
CHANNEL_CONFIG_TYPEHASH,
ERC3009_DEPOSIT_COLLECTOR_ADDRESS,
MAX_WITHDRAW_DELAY,
MIN_WITHDRAW_DELAY,
PERMIT2_DEPOSIT_COLLECTOR_ADDRESS,
batch_permit2_witness_types,
channel_config_types,
claim_batch_types,
receive_authorization_types,
refund_types,
voucher_types,
)
from .types import (
BatchSettlementAssetTransferMethod,
BatchSettlementChannelStateExtra,
BatchSettlementClaimPayload,
BatchSettlementDepositAuthorization,
BatchSettlementDepositPayload,
BatchSettlementEnrichedRefundPayload,
BatchSettlementErc3009Authorization,
BatchSettlementFacilitatorSettlePayload,
BatchSettlementPayload,
BatchSettlementPaymentRequirementsExtra,
BatchSettlementPaymentResponseExtra,
BatchSettlementPermit2Authorization,
BatchSettlementPermit2Permitted,
BatchSettlementPermit2Witness,
BatchSettlementRefundPayload,
BatchSettlementSettlePayload,
BatchSettlementVoucherClaim,
BatchSettlementVoucherFields,
BatchSettlementVoucherPayload,
BatchSettlementVoucherStateExtra,
ChannelConfig,
ChannelState,
parse_facilitator_payload,
parse_payload,
)

__all__ = [
# Constants
"BATCH_SETTLEMENT_SCHEME",
"BATCH_SETTLEMENT_ADDRESS",
"ERC3009_DEPOSIT_COLLECTOR_ADDRESS",
"PERMIT2_DEPOSIT_COLLECTOR_ADDRESS",
"MIN_WITHDRAW_DELAY",
"MAX_WITHDRAW_DELAY",
"BATCH_SETTLEMENT_DOMAIN",
"CHANNEL_CONFIG_TYPEHASH",
"channel_config_types",
"voucher_types",
"refund_types",
"claim_batch_types",
"receive_authorization_types",
"batch_permit2_witness_types",
# ABI
"channel_config_components",
"batch_settlement_abi",
"erc20_balance_of_abi",
# Types — inner state
"ChannelState",
# Types — wire structs
"ChannelConfig",
"BatchSettlementErc3009Authorization",
"BatchSettlementPermit2Permitted",
"BatchSettlementPermit2Witness",
"BatchSettlementPermit2Authorization",
"BatchSettlementVoucherFields",
"BatchSettlementDepositAuthorization",
"BatchSettlementAssetTransferMethod",
# Types — voucher claim
"BatchSettlementVoucherClaim",
# Types — extras
"BatchSettlementChannelStateExtra",
"BatchSettlementVoucherStateExtra",
"BatchSettlementPaymentRequirementsExtra",
"BatchSettlementPaymentResponseExtra",
# Types — payloads (client)
"BatchSettlementDepositPayload",
"BatchSettlementVoucherPayload",
"BatchSettlementRefundPayload",
# Types — payloads (facilitator)
"BatchSettlementClaimPayload",
"BatchSettlementSettlePayload",
"BatchSettlementEnrichedRefundPayload",
# Types — union aliases
"BatchSettlementPayload",
"BatchSettlementFacilitatorSettlePayload",
# Types — parsers
"parse_payload",
"parse_facilitator_payload",
]
235 changes: 235 additions & 0 deletions python/x402/mechanisms/evm/batch_settlement/abi.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,235 @@
"""ABI definitions for the x402 batch-settlement contracts.

Mirrors ``typescript/packages/mechanisms/evm/src/batch-settlement/abi.ts``.
Compatible with ``eth_abi`` for ABI encoding/decoding and ``web3.py`` for
contract calls. Module-level lists and dicts are normative; do not mutate
at runtime (``Final`` only prevents name rebinding, not container mutation).
"""

from typing import Any, Final

channel_config_components: Final[list[dict[str, str]]] = [
{"name": "payer", "type": "address"},
{"name": "payerAuthorizer", "type": "address"},
{"name": "receiver", "type": "address"},
{"name": "receiverAuthorizer", "type": "address"},
{"name": "token", "type": "address"},
{"name": "withdrawDelay", "type": "uint40"},
{"name": "salt", "type": "bytes32"},
]

_voucher_claim_components: Final[list[dict[str, Any]]] = [
{
"name": "voucher",
"type": "tuple",
"components": [
{
"name": "channel",
"type": "tuple",
"components": channel_config_components,
},
{"name": "maxClaimableAmount", "type": "uint128"},
],
},
{"name": "signature", "type": "bytes"},
{"name": "totalClaimed", "type": "uint128"},
]

batch_settlement_abi: Final[list[dict[str, Any]]] = [
{
"type": "function",
"name": "multicall",
"inputs": [{"name": "data", "type": "bytes[]"}],
"outputs": [{"name": "results", "type": "bytes[]"}],
"stateMutability": "nonpayable",
},
{
"type": "function",
"name": "deposit",
"inputs": [
{"name": "config", "type": "tuple", "components": channel_config_components},
{"name": "amount", "type": "uint128"},
{"name": "collector", "type": "address"},
{"name": "collectorData", "type": "bytes"},
],
"outputs": [],
"stateMutability": "nonpayable",
},
{
"type": "function",
"name": "claim",
"inputs": [
{"name": "voucherClaims", "type": "tuple[]", "components": _voucher_claim_components},
],
"outputs": [],
"stateMutability": "nonpayable",
},
{
"type": "function",
"name": "claimWithSignature",
"inputs": [
{"name": "voucherClaims", "type": "tuple[]", "components": _voucher_claim_components},
{"name": "authorizerSignature", "type": "bytes"},
],
"outputs": [],
"stateMutability": "nonpayable",
},
{
"type": "function",
"name": "settle",
"inputs": [
{"name": "receiver", "type": "address"},
{"name": "token", "type": "address"},
],
"outputs": [],
"stateMutability": "nonpayable",
},
{
"type": "function",
"name": "initiateWithdraw",
"inputs": [
{"name": "config", "type": "tuple", "components": channel_config_components},
{"name": "amount", "type": "uint128"},
],
"outputs": [],
"stateMutability": "nonpayable",
},
{
"type": "function",
"name": "finalizeWithdraw",
"inputs": [
{"name": "config", "type": "tuple", "components": channel_config_components},
],
"outputs": [],
"stateMutability": "nonpayable",
},
{
"type": "function",
"name": "refund",
"inputs": [
{"name": "config", "type": "tuple", "components": channel_config_components},
{"name": "amount", "type": "uint128"},
],
"outputs": [],
"stateMutability": "nonpayable",
},
{
"type": "function",
"name": "refundWithSignature",
"inputs": [
{"name": "config", "type": "tuple", "components": channel_config_components},
{"name": "amount", "type": "uint128"},
{"name": "nonce", "type": "uint256"},
{"name": "receiverAuthorizerSignature", "type": "bytes"},
],
"outputs": [],
"stateMutability": "nonpayable",
},
{
"type": "function",
"name": "getChannelId",
"inputs": [
{"name": "config", "type": "tuple", "components": channel_config_components},
],
"outputs": [{"name": "", "type": "bytes32"}],
"stateMutability": "view",
},
{
"type": "function",
"name": "CHANNEL_CONFIG_TYPEHASH",
"inputs": [],
"outputs": [{"name": "", "type": "bytes32"}],
"stateMutability": "view",
},
{
"type": "function",
"name": "channels",
"inputs": [{"name": "channelId", "type": "bytes32"}],
"outputs": [
{"name": "balance", "type": "uint128"},
{"name": "totalClaimed", "type": "uint128"},
],
"stateMutability": "view",
},
{
"type": "function",
"name": "pendingWithdrawals",
"inputs": [{"name": "channelId", "type": "bytes32"}],
"outputs": [
{"name": "amount", "type": "uint128"},
{"name": "initiatedAt", "type": "uint40"},
],
"stateMutability": "view",
},
{
"type": "function",
"name": "receivers",
"inputs": [
{"name": "receiver", "type": "address"},
{"name": "token", "type": "address"},
],
"outputs": [
{"name": "totalClaimed", "type": "uint128"},
{"name": "totalSettled", "type": "uint128"},
],
"stateMutability": "view",
},
{
"type": "function",
"name": "getVoucherDigest",
"inputs": [
{"name": "channelId", "type": "bytes32"},
{"name": "maxClaimableAmount", "type": "uint128"},
],
"outputs": [{"name": "", "type": "bytes32"}],
"stateMutability": "view",
},
{
"type": "function",
"name": "getRefundDigest",
"inputs": [
{"name": "channelId", "type": "bytes32"},
{"name": "nonce", "type": "uint256"},
{"name": "amount", "type": "uint128"},
],
"outputs": [{"name": "", "type": "bytes32"}],
"stateMutability": "view",
},
{
"type": "function",
"name": "refundNonce",
"inputs": [{"name": "channelId", "type": "bytes32"}],
"outputs": [{"name": "", "type": "uint256"}],
"stateMutability": "view",
},
{
"type": "function",
"name": "getClaimBatchDigest",
"inputs": [
{"name": "voucherClaims", "type": "tuple[]", "components": _voucher_claim_components},
],
"outputs": [{"name": "", "type": "bytes32"}],
"stateMutability": "view",
},
{
"type": "event",
"name": "Settled",
"inputs": [
{"name": "receiver", "type": "address", "indexed": True},
{"name": "token", "type": "address", "indexed": True},
{"name": "sender", "type": "address", "indexed": True},
{"name": "amount", "type": "uint128", "indexed": False},
],
"anonymous": False,
},
]

erc20_balance_of_abi: Final[list[dict[str, Any]]] = [
{
"type": "function",
"name": "balanceOf",
"inputs": [{"name": "account", "type": "address"}],
"outputs": [{"name": "", "type": "uint256"}],
"stateMutability": "view",
},
]
Loading
Loading