I'm trying to get limit orders working using the 0x reference:
<https://docs.0x.org/market-makers/guides/0x-v4-rfq-orders-code-examples>

looking to swap some WETH for some ZRX via placing a limit order.

I'm getting the error:

```
500
{'reason': "Cannot read properties of undefined (reading 'data')"}

```

here is my request:

```
{
  "makerToken": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
  "takerToken": "0xe41d2489571d322189246dafa5ebde1f4699f498",
  "makerAmount": "50000000000000000",
  "takerAmount": "220000000000000000000",
  "takerTokenFeeAmount": "0",
  "maker": "0xMYADDRESSS",
  "taker": "0x0000000000000000000000000000000000000000",
  "sender": "0x0000000000000000000000000000000000000000",
  "feeRecipient": "0x0000000000000000000000000000000000000000",
  "pool": "0x0000000000000000000000000000000000000000000000000000000000000000",
  "expiry": "1648687063",
  "salt": "1648686703",
  "chainId": 1,
  "verifyingContract": "0xDef1C0ded9bec7F1a1670819833240f027b25EfF",
  "signature": {
    "signatureType": 3,
    "v": 27,
    "r": "0xbec1e45ecba34aa17158ebfd672d6c6fdd418cc4ba576efe23aad24af35d85d6",
    "s": "0x7cbd78a796c3fad5b87e75cc96c6e5f2963dd78265724e700e30049af41cd927"
  }
}

```

I'm posting it to:

```
https://api.0x.org/orderbook/v1/order

```

below is the full code, sorry its long, this is the only way I can figure out without wrapper classes:

```
import eth_abi
import web3
from eth_utils import keccak, remove_0x_prefix, to_bytes

import hashlib
from bitcoin import ecdsa_raw_sign
from typing import NamedTuple, Tuple

import time
import os

import personal

# Create 2 private keys. These keys have been funded with some Ropsten ETH. For these scripts to work, the accounts below need to have some Ropsten ETH
private_key_maker = web3.Web3.toBytes(hexstr=personal.MY_PK)
private_key_maker_address = personal.MY_ETH_ADY

# Fetch the RPC URL and the Exchange Proxy address
MAIN_URL = personal.MYINFURA
ZERO_EX_EP = '0xdef1c0ded9bec7f1a1670819833240f027b25eff'
ZERO_EX_EP_CS = web3.Web3.toChecksumAddress('0xdef1c0ded9bec7f1a1670819833240f027b25eff')

TOKEN_A = web3.Web3.toChecksumAddress('0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2') #WETH
TOKEN_B = web3.Web3.toChecksumAddress('0xe41d2489571d322189246dafa5ebde1f4699f498') #ZRX

print(TOKEN_A)

provider = web3.HTTPProvider(MAIN_URL)
client = web3.Web3(provider)
print(f"Latest block is: {client.eth.getBlock('latest')['number']}")

import sha3

private_key_address = web3.Web3.toChecksumAddress(personal.MY_ETH_ADY)
private_key = personal.MY_PK

null_eth_address = '0x0000000000000000000000000000000000000000'

ORDER_URL = 'https://api.0x.org/orderbook/v1/order'

from eip712_structs import EIP712Struct, Address, String, Bytes, Address, Uint
from eip712_structs import Bytes

def pad_20_bytes_to_32(twenty_bytes: bytes):
    return bytes(12) + twenty_bytes

def int_to_32_big_endian_bytes(i: int):
    return i.to_bytes(32, byteorder="big")

order_field_types = [
    "address",
    "address",
    "uint128",
    "uint128",
    "uint128",
    "address",
    "address",
    "address",
    "address",
    "bytes32",
    "uint64",
    "uint256",
]

class LimitOrder(NamedTuple):
    makerToken: str
    takerToken: str
    makerAmount: int
    takerAmount: int
    takerTokenFeeAmount: int
    maker: str
    taker: str
    sender: str
    feeRecipient: str
    pool: int
    expiry: int
    salt: int

order = LimitOrder(
    makerToken= TOKEN_A.lower(),
    takerToken= TOKEN_B.lower(),
    makerAmount= int(0.05 * 1e18),
    takerAmount= int(220 * 1e18),
    takerTokenFeeAmount = 0,
    maker= private_key_maker_address,
    taker= null_eth_address,
    sender = null_eth_address,
    feeRecipient = null_eth_address,
    pool = 0,
    expiry=int(time.time() + 360), #6 mins
    salt=int(time.time())
)

eip191_header = b"\x19\x01"

eip712_domain_separator_schema_hash = client.keccak(
    b"EIP712Domain("
    + b"string name,"
    + b"string version,"
    + b"uint256 chainId,"
    + b"address verifyingContract"
    + b")"
)

eip712_order_schema_hash = client.keccak(
    b"LimitOrder("
    + b"address makerToken,"
    + b"address takerToken,"
    + b"uint128 makerAmount,"
    + b"uint128 takerAmount,"
    + b"uint128 takerTokenFeeAmount,"
    + b"address maker,"
    + b"address taker,"
    + b"address sender,"
    + b"address feeRecipient,"
    + b"bytes32 pool,"
    + b"uint64 expiry,"
    + b"uint256 salt"
    + b")"
)

def pad_20_bytes_to_32(twenty_bytes: bytes):
    return bytes(12) + twenty_bytes

def int_to_32_big_endian_bytes(i: int):
    return i.to_bytes(32, byteorder="big")

def make_eip712_domain_struct_header_hash(chain_id: int, verifying_contract: str) -> str:
    return keccak(
        eip712_domain_separator_schema_hash
        + keccak(b"ZeroEx")
        + keccak(b"1.0.0")
        + int_to_32_big_endian_bytes(int(chain_id))
        + pad_20_bytes_to_32(to_bytes(hexstr=verifying_contract))
    )

def get_order_hash_0xv4(order: LimitOrder, chain_id: int, exchange_proxy_address: str):
    """
    Returns an order hash for a given LIMIT order. The order hash will not contain the `0x` prefix.
    :params order: a RFQ order
    :params chain_id: the Chain ID. Ropsten is 3, while Mainnet is 1
    :params exchange_proxy_address: the address of the Exchange Proxy. This address must be checksummed.
    """
    order_struct = eip712_order_schema_hash + pad_20_bytes_to_32(to_bytes(hexstr=order.makerToken)) + pad_20_bytes_to_32(to_bytes(hexstr=order.takerToken))+ int_to_32_big_endian_bytes(int(order.makerAmount))+ int_to_32_big_endian_bytes(int(order.takerAmount))+ int_to_32_big_endian_bytes(int(order.takerTokenFeeAmount))+ pad_20_bytes_to_32(to_bytes(hexstr=order.maker))+ pad_20_bytes_to_32(to_bytes(hexstr=order.taker))+ pad_20_bytes_to_32(to_bytes(hexstr=order.sender))+ pad_20_bytes_to_32(to_bytes(hexstr=order.feeRecipient))+ int_to_32_big_endian_bytes(int(order.pool))+ int_to_32_big_endian_bytes(int(order.expiry))+ int_to_32_big_endian_bytes(int(order.salt))

    eip712_order_struct_hash = client.keccak(order_struct)

    eip712_domain_struct_hash = make_eip712_domain_struct_header_hash(
        chain_id=chain_id,
        verifying_contract=exchange_proxy_address
    )

    #print(f"Domain hash: {eip712_domain_struct_hash.hex()}")
    #print(f"Order schema hash: {eip712_order_schema_hash.hex()}")

    return keccak(
        eip191_header
        + eip712_domain_struct_hash
        + eip712_order_struct_hash
    )

def get_order_info(order: LimitOrder) -> Tuple[bytes, int, int]:
    function_signature = web3.Web3.keccak(text=f'getLimitOrderInfo(({",".join(order_field_types)}))').hex()[:10]
    encoded_args = eth_abi.encode_abi(order_field_types, [
        order.makerToken,
        order.takerToken,
        order.makerAmount,
        order.takerAmount,
        order.takerTokenFeeAmount,
        order.maker,
        order.taker,
        order.sender,
        order.feeRecipient,
        int_to_32_big_endian_bytes(order.pool),    # Pool is represented as an unsigned integer, however it is encoded as a `bytes32`
        order.expiry,
        order.salt
    ])
    calldata = function_signature + encoded_args.hex()
    tx = {
        "to": client.toChecksumAddress(ZERO_EX_EP),
        "data": calldata,
    }

    # Perform an `eth_call` to read the transaction data result. The response structure can be found here:
    # https://0xprotocol.readthedocs.io/en/latest/basics/functions.htbml#getrfqorderinfo
    response = client.eth.call(tx)
    on_chain_order_hash, fillable_status, amount_filled = eth_abi.decode_abi(['bytes32', 'uint8', 'uint128'], bytes.fromhex(response.hex()[2:]))

    print(f"ONLINE Hash hex: {on_chain_order_hash.hex()}")
    #print(f"Fillable status: {fillable_status}")
    #print(f"Amount filled: {amount_filled / 1e18}")
    return on_chain_order_hash, fillable_status, amount_filled

import json

def order_to_sra(order: LimitOrder, chain_id: int, verifying_contract: str, v: int, r: bytes, s: bytes):
    obj = {
        "makerToken": order.makerToken,
        "takerToken": order.takerToken,
        "makerAmount": str(order.makerAmount),
        "takerAmount": str(order.takerAmount),
        "takerTokenFeeAmount": str(order.takerTokenFeeAmount),
        "maker": order.maker,
        "taker": order.taker,
        "sender": order.sender,
        "feeRecipient": order.feeRecipient,
        "pool": '0x' + order.pool.to_bytes(32, 'big').hex(),
        "expiry": str(order.expiry),
        "salt": str(order.salt),
        "chainId": int(chain_id),
        "verifyingContract": str(verifying_contract),
        "signature": {
            "signatureType": 3,
            "v": v,
            "r": f"0x{r.hex()}",
            "s": f"0x{s.hex()}",
        }
    }
    return json.dumps(obj, indent=4)    # Indent is added simply for prettifying

def SignHashNew(hash_bytesArray, privateKey):
    from eth_account.messages import encode_defunct
    message = encode_defunct(hash_bytesArray)
    signed_message = client.eth.account.sign_message(message, private_key=privateKey)
    return (
        signed_message.v,
        '0x' + signed_message.r.to_bytes(length=32, byteorder='big').hex(),
        '0x' + signed_message.s.to_bytes(length=32, byteorder='big').hex()
    )

off_chain_order_hash = get_order_hash_0xv4(order, 1, ZERO_EX_EP)
off_chain_order_hash.hex()

print('OFFCHAIN Hash hex: ', off_chain_order_hash.hex())

on_chain_order_hash = get_order_info(order)

v, r, s = SignHashNew(off_chain_order_hash, private_key_maker)
r = bytes.fromhex(r[2:])
s = bytes.fromhex(s[2:])

json_order = order_to_sra(order=order, chain_id=1, verifying_contract=ZERO_EX_EP_CS, v=v, r=r, s=s)
json_order = json.loads(json_order)

print(json_order)

import requests

response = requests.post(
            url=ORDER_URL,
            json=json_order,
            headers = {
              "Content-Type": "application/json"
            }
        )

if response.status_code != 200:
    try:
        print(response.status_code)
        response_json = response.json()
        print(response_json)
    except:
        print('error getting response')

```