syntax = "proto3"; package arbiter.evm; import "google/protobuf/empty.proto"; import "google/protobuf/timestamp.proto"; import "shared/evm.proto"; enum EvmError { EVM_ERROR_UNSPECIFIED = 0; EVM_ERROR_VAULT_SEALED = 1; EVM_ERROR_INTERNAL = 2; } message WalletEntry { int32 id = 1; bytes address = 2; // 20-byte Ethereum address } message WalletList { repeated WalletEntry wallets = 1; } message WalletCreateResponse { oneof result { WalletEntry wallet = 1; EvmError error = 2; } } message WalletListResponse { oneof result { WalletList wallets = 1; EvmError error = 2; } } // --- Grant types --- message TransactionRateLimit { uint32 count = 1; int64 window_secs = 2; } message VolumeRateLimit { bytes max_volume = 1; // U256 as big-endian bytes int64 window_secs = 2; } message SharedSettings { int32 wallet_access_id = 1; uint64 chain_id = 2; optional google.protobuf.Timestamp valid_from = 3; optional google.protobuf.Timestamp valid_until = 4; optional bytes max_gas_fee_per_gas = 5; // U256 as big-endian bytes optional bytes max_priority_fee_per_gas = 6; // U256 as big-endian bytes optional TransactionRateLimit rate_limit = 7; } message EtherTransferSettings { repeated bytes targets = 1; // list of 20-byte Ethereum addresses VolumeRateLimit limit = 2; } message TokenTransferSettings { bytes token_contract = 1; // 20-byte Ethereum address optional bytes target = 2; // 20-byte Ethereum address; absent means any recipient allowed repeated VolumeRateLimit volume_limits = 3; } message SpecificGrant { oneof grant { EtherTransferSettings ether_transfer = 1; TokenTransferSettings token_transfer = 2; } } // --- UserAgent grant management --- message EvmGrantCreateRequest { SharedSettings shared = 1; SpecificGrant specific = 2; } message EvmGrantCreateResponse { oneof result { int32 grant_id = 1; EvmError error = 2; } } message EvmGrantDeleteRequest { int32 grant_id = 1; } message EvmGrantDeleteResponse { oneof result { google.protobuf.Empty ok = 1; EvmError error = 2; } } // Basic grant info returned in grant listings message GrantEntry { int32 id = 1; int32 wallet_access_id = 2; SharedSettings shared = 3; SpecificGrant specific = 4; } message EvmGrantListRequest { optional int32 wallet_access_id = 1; } message EvmGrantListResponse { oneof result { EvmGrantList grants = 1; EvmError error = 2; } } message EvmGrantList { repeated GrantEntry grants = 1; } // --- Client transaction operations --- message EvmSignTransactionRequest { bytes wallet_address = 1; // 20-byte Ethereum address bytes rlp_transaction = 2; // RLP-encoded EIP-1559 transaction (unsigned) } // oneof because signing and evaluation happen atomically — a signing failure // is always either an eval error or an internal error, never a partial success message EvmSignTransactionResponse { oneof result { bytes signature = 1; // 65-byte signature: r[32] || s[32] || v[1] arbiter.shared.evm.TransactionEvalError eval_error = 2; EvmError error = 3; } } message EvmAnalyzeTransactionRequest { bytes wallet_address = 1; // 20-byte Ethereum address bytes rlp_transaction = 2; // RLP-encoded EIP-1559 transaction } message EvmAnalyzeTransactionResponse { oneof result { arbiter.shared.evm.SpecificMeaning meaning = 1; arbiter.shared.evm.TransactionEvalError eval_error = 2; EvmError error = 3; } }