{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://lopw.com/docs/schemas/offer-evm.json",
  "title": "Offer (EVM binding)",
  "description": "The seller's signed promise on an EVM network (Solidity: Offer). offerHash is the EIP-712 digest hashTypedDataV4(structHash) under the domain EIP712Domain(name=\"LOPW\", version=\"1\", chainId, verifyingContract=registry). On the wire it travels as SignedOffer, ABI-encoded as 0x-hex, in PaymentRequired.extensions.lopw.info.offer.",
  "type": "object",
  "additionalProperties": false,
  "required": [
    "version",
    "service_id",
    "registry",
    "terms_hash",
    "price",
    "asset",
    "max_claim",
    "valid_until",
    "offer_nonce",
    "key_version"
  ],
  "properties": {
    "version": {
      "type": "integer",
      "minimum": 0,
      "maximum": 4294967295,
      "description": "Protocol version, 1",
      "const": 1
    },
    "service_id": {
      "type": "string",
      "pattern": "^0x[0-9a-f]{64}$",
      "description": "keccak256(abi.encode(address(registry), uint256(counter))), counter starting at 0 per registry"
    },
    "registry": {
      "type": "string",
      "pattern": "^0x[0-9a-fA-F]{40}$",
      "description": "Bond Registry contract that holds the stake; also the EIP-712 verifyingContract"
    },
    "terms_hash": {
      "type": "string",
      "pattern": "^0x[0-9a-f]{64}$",
      "description": "keccak256(abi.encode(terms)) of the registered terms the buyer pays under"
    },
    "price": {
      "type": "string",
      "pattern": "^[0-9]+$",
      "description": "Price of this call in USDC base units"
    },
    "asset": {
      "type": "string",
      "pattern": "^0x[0-9a-fA-F]{40}$",
      "description": "The USDC contract of the payment asset"
    },
    "max_claim": {
      "type": "string",
      "pattern": "^[0-9]+$",
      "description": "Most a single receipt can pay out"
    },
    "valid_until": {
      "type": "integer",
      "minimum": 0,
      "maximum": 18446744073709551615,
      "description": "Unix seconds after which the offer must not be paid"
    },
    "offer_nonce": {
      "type": "string",
      "pattern": "^0x[0-9a-f]{64}$",
      "description": "Random, unique per offer"
    },
    "key_version": {
      "type": "integer",
      "minimum": 0,
      "maximum": 4294967295,
      "description": "Which registered signing key (an address) signed this offer"
    }
  },
  "$defs": {
    "SignedOffer": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "offer",
        "signature"
      ],
      "properties": {
        "offer": {
          "$ref": "#"
        },
        "signature": {
          "type": "string",
          "pattern": "^0x[0-9a-f]{130}$",
          "description": "65-byte secp256k1 signature (r, s, v) as 0x-prefixed hex over the EIP-712 digest"
        }
      },
      "description": "Solidity: SignedOffer { Offer offer; bytes signature }. Verified with ECDSA.recover(offerHash, signature) == registered key, malleable signatures rejected"
    },
    "SignedOfferWire": {
      "type": "string",
      "pattern": "^0x([0-9a-f]{2})+$",
      "description": "abi.encode(SignedOffer) as 0x-prefixed hex: the value of PaymentRequired.extensions.lopw.info.offer on EVM networks (base64 ScVal XDR on Stellar)",
      "title": "SignedOffer on the wire"
    },
    "EIP712Type": {
      "const": "Offer(uint32 version,bytes32 serviceId,address registry,bytes32 termsHash,uint256 price,address asset,uint256 maxClaim,uint64 validUntil,bytes32 offerNonce,uint32 keyVersion)",
      "description": "The exact EIP-712 type string hashed into the struct hash"
    }
  }
}
