You are viewing an archive of the Piccadilly Circus Games Competition. Join our Discord for the latest information.

CAX Recipes

import time
import requests
import eth_keys
from eth_account import account, Account
from eth_account.messages import encode_defunct
from web3 import Web3
from web3.middleware import construct_sign_and_send_raw_middleware
from autonity.abi_manager import ABIManager
from autonity import AUTONITY_CONTRACT_ADDRESS

Preliminary

Network constants

RPC_ENDPOINT = "https://rpc1.piccadilly.autonity.org"

Account constants

ACCOUNT = "<YOUR-ACCOUNT-ADDRESS>"
assert Web3.is_checksum_address(ACCOUNT)
KEYFILE = "<YOUR-LOCAL-KEYFILE-ADDRESS>"
PASSPHRASE = "<YOUR-ACCOUNT-PASSPHRASE>"

Generate private key

with open(KEYFILE) as keyfile:
    keyfile_contents = keyfile.read()
PRIVATE_KEY = eth_keys.keys.PrivateKey(
    account.Account.decrypt(keyfile_contents, PASSPHRASE)
)

Create Web3

w3 = Web3(provider=Web3.HTTPProvider(RPC_ENDPOINT))
w3.middleware_onion.add(
    construct_sign_and_send_raw_middleware(Account.from_key(PRIVATE_KEY))
)

Create contract

NTN_CONTRACT = w3.eth.contract(
    address=AUTONITY_CONTRACT_ADDRESS,
    abi=ABIManager.load_abi("IERC20"),
)

USDC_CONTRACT = w3.eth.contract(
    address="0x3a60C03a86eEAe30501ce1af04a6C04Cf0188700",
    abi=ABIManager.load_abi("IERC20"),
)

Generate API key

For CAX account and url, please visit: https://game.autonity.org/getting-started/exchange-cax.html

CAX_ACCOUNT = "<CAX-ACCOUNT-ADDRESS>"
assert Web3.is_checksum_address(CAX_ACCOUNT)
CAX_URL = "https://cax.piccadilly.autonity.org/api"
DEPOSIT_ATN_VALUE = w3.to_wei(1.0, "ether")
DEPOSIT_NTN_VALUE = w3.to_wei(1.0, "ether")
DEPOSIT_USDC_VALUE = 1 * 1000000
WITHDRAW_ATN_VALUE = "1.0"

Deposit ATN to CAX

# Prepare transaction.
transaction = {
    "from": ACCOUNT,
    "to": CAX_ACCOUNT,
    "value": DEPOSIT_ATN_VALUE,
}

# Sent transaction.
tx_hash = w3.eth.send_transaction(transaction)

print(w3.eth.get_transaction(tx_hash))
AttributeDict({'blockHash': None, 'blockNumber': None, 'from': '0x8EaFBab4A209aF9E587B22A4cc43319c20B2e4D3', 'gas': 21000, 'gasPrice': 2500000000, 'maxFeePerGas': 2500000000, 'maxPriorityFeePerGas': 1500000000, 'hash': HexBytes('0x0dd8b6c83919444108f3885dcb667a1b56b17845d15572f21eb83a0d2a9cffc6'), 'input': HexBytes('0x'), 'nonce': 27, 'to': '0x11F62c273dD23dbe4D1713C5629fc35713Aa5a94', 'transactionIndex': None, 'value': 1000000000000000000, 'type': 2, 'accessList': [], 'chainId': 65100003, 'v': 0, 'r': HexBytes('0xdd7e966261fffc9fc81b167d5d0cfddb5f66bb14d0660de2c1d20dda98147ade'), 's': HexBytes('0x5d3d59d7eab17a76084e24e49ba970305fb9103569e744ea21fa2f84b8dd6d28')})

Deposit NTN to CAX

# Prepare function transaction.
function = NTN_CONTRACT.functions.transfer(
    recipient=CAX_ACCOUNT, amount=DEPOSIT_NTN_VALUE
)
function_transaction = function.build_transaction({"from": ACCOUNT})

# Sent transaction.
tx_hash = w3.eth.send_transaction(function_transaction)

print(w3.eth.get_transaction(tx_hash))
AttributeDict({'blockHash': None, 'blockNumber': None, 'from': '0x8EaFBab4A209aF9E587B22A4cc43319c20B2e4D3', 'gas': 34603, 'gasPrice': 2500000000, 'maxFeePerGas': 2500000000, 'maxPriorityFeePerGas': 1500000000, 'hash': HexBytes('0x35bd2d001a2b7a002788805905ee469632c05f7fb994690fc5ee5be951fa60e0'), 'input': HexBytes('0xa9059cbb00000000000000000000000011f62c273dd23dbe4d1713c5629fc35713aa5a940000000000000000000000000000000000000000000000000de0b6b3a7640000'), 'nonce': 28, 'to': '0xBd770416a3345F91E4B34576cb804a576fa48EB1', 'transactionIndex': None, 'value': 0, 'type': 2, 'accessList': [], 'chainId': 65100003, 'v': 1, 'r': HexBytes('0x65e3e57cf298f8a0183790abbeffdcf871303aac85e22efcac18de31a6f4a1cd'), 's': HexBytes('0x1eef0b80c32dedfaff07a547d6eba863243760aa355ccc2cc306ddd4d91355ba')})

Deposit USDC to CAX

# Prepare function transaction.
function = USDC_CONTRACT.functions.transfer(
    recipient=CAX_ACCOUNT, amount=DEPOSIT_USDC_VALUE
)
function_transaction = function.build_transaction({"from": ACCOUNT})

# Sent transaction.
tx_hash = w3.eth.send_transaction(function_transaction)

print(w3.eth.get_transaction(tx_hash))
AttributeDict({'blockHash': None, 'blockNumber': None, 'from': '0x8EaFBab4A209aF9E587B22A4cc43319c20B2e4D3', 'gas': 45276, 'gasPrice': 2500000000, 'maxFeePerGas': 2500000000, 'maxPriorityFeePerGas': 1500000000, 'hash': HexBytes('0x3363f993cbaa15c0c604dea3c050fc256c442acfd52c15adc70eb340fbe89852'), 'input': HexBytes('0xa9059cbb00000000000000000000000011f62c273dd23dbe4d1713c5629fc35713aa5a9400000000000000000000000000000000000000000000000000000000000f4240'), 'nonce': 29, 'to': '0x3a60C03a86eEAe30501ce1af04a6C04Cf0188700', 'transactionIndex': None, 'value': 0, 'type': 2, 'accessList': [], 'chainId': 65100003, 'v': 1, 'r': HexBytes('0xcbb8106cb3af9e2f0653962c68dc3610a235754ace2c5c9eff73167f7cfd0545'), 's': HexBytes('0x57ba017f5b57fdd74de96bf5ec10e22eec736e6ec32f99a43512e9ed68953469')})

Generate API key

# Generate msgbytes.
account = Account.from_key(PRIVATE_KEY)
nonce = str(time.time_ns())
msgstr = '{"nonce":"' + nonce + '"}'
msgbytes = msgstr.encode("utf-8")

# Generate signature.
sigstr = account.sign_message(encode_defunct(msgbytes)).signature.hex()

# Post request.
response = requests.post(
    CAX_URL + "/apikeys",
    headers={"API-Sig": sigstr},
    data=msgbytes,
)

response_json = response.json()

if "apikey" in response_json:
    API = response.json()["apikey"]
    print("API key generated")
else:
    print("Account not registered on CAX")
API key generated

Interact with CAX (API key not required)

Get orderbooks

response = requests.get(
    CAX_URL + "/orderbooks"
)
print(response.status_code, response.json())
200 [{'pair': 'ATN-USDC', 'base': 'ATN', 'quote': 'USDC', 'min_amount': '0.01', 'tick_size': '0.01'}, {'pair': 'NTN-USDC', 'base': 'NTN', 'quote': 'USDC', 'min_amount': '0.01', 'tick_size': '0.01'}]

Get pair quote

response = requests.get(
    CAX_URL + "/orderbooks/ATN-USDC/quote"
)
print(response.status_code, response.json())
200 {'timestamp': '2024-07-15T08:59:42.454242+00:00', 'bid_price': '1.03', 'bid_amount': '20000.00', 'ask_price': '1.04', 'ask_amount': '26666.67'}

Get pair depth

response = requests.get(
    CAX_URL + "/orderbooks/ATN-USDC/depth"
)
pair_depth = response.json()
print(response.status_code, pair_depth)
200 {'timestamp': '2024-07-15T08:59:42.771494+00:00', 'bids': [{'price': '1.03', 'amount': '20000.00'}, {'price': '1.02', 'amount': '60000.00'}, {'price': '1.01', 'amount': '60000.00'}, {'price': '0.99', 'amount': '6666.67'}, {'price': '0.98', 'amount': '23333.33'}, {'price': '0.97', 'amount': '20000.00'}, {'price': '0.96', 'amount': '26666.67'}, {'price': '0.95', 'amount': '33333.33'}, {'price': '0.75', 'amount': '4.70'}], 'asks': [{'price': '1.04', 'amount': '26666.67'}, {'price': '1.05', 'amount': '33333.33'}, {'price': '1.06', 'amount': '36666.67'}, {'price': '1.07', 'amount': '13333.33'}, {'price': '1.08', 'amount': '20000.00'}, {'price': '1.10', 'amount': '3.00'}, {'price': '1.20', 'amount': '1.00'}, {'price': '1.25', 'amount': '8.70'}, {'price': '1.30', 'amount': '1.00'}, {'price': '1.50', 'amount': '1.00'}]}

Calculate mid price

bid_prices = [float(bid["price"]) for bid in pair_depth["bids"]]
ask_prices = [float(ask["price"]) for ask in pair_depth["asks"]]
mid_price = (min(ask_prices) + max(bid_prices)) / 2
print(mid_price)
1.0350000000000001

Get trades

response = requests.get(
    CAX_URL + f"/orderbooks/ATN-USDC/trades"
)
print(response.status_code, response.json()[:10])
200 [{'timestamp': '2024-07-14T20:00:11.686288', 'price': '0.99', 'amount': '3334.33'}, {'timestamp': '2024-07-14T20:01:02.885963', 'price': '1.01', 'amount': '6665.67'}, {'timestamp': '2024-07-14T20:01:02.885963', 'price': '1.02', 'amount': '13333.33'}, {'timestamp': '2024-07-14T20:01:02.885963', 'price': '1.03', 'amount': '10001.00'}, {'timestamp': '2024-07-15T04:56:53.642616', 'price': '1.01', 'amount': '6666.67'}, {'timestamp': '2024-07-15T04:59:37.569318', 'price': '1.02', 'amount': '13333.33'}, {'timestamp': '2024-07-15T05:00:14.146210', 'price': '1.03', 'amount': '9999.00'}]

Interact with CAX (API key required)

Please make sure Account is registered on CAX and a valid API key is generated. API key is hidden in this example.

Check balances

response = requests.get(
    CAX_URL + "/balances",
    headers={"API-Key": API},
)
print(response.status_code)
200

Submit an order

response = requests.post(
    CAX_URL + "/orders",
    headers={"API-Key": API},
    json={
        "pair": "ATN-USDC",
        "side": "bid",
        "price": "0.9",
        "amount": "100.0",
    },
)
print(response.status_code, response.json())

# Record order_id.
order_id = response.json()["order_id"]
201 {'order_id': 340759, 'timestamp': '2024-07-15T08:59:44.151290+00:00', 'status': 'pending', 'pair': 'ATN-USDC', 'type': 'limit', 'side': 'bid', 'price': '0.90', 'amount': '100.00', 'remain': '100.00'}

Check order status

response = requests.get(
    CAX_URL + f"/orders/{order_id}", headers={"API-Key": API}
)
print(response.status_code, response.json()["status"])
200 open

Cancel an order

response = response = requests.delete(
    CAX_URL + f"/orders/{order_id}", headers={"API-Key": API}
)
print(response.status_code, response.json())
202 {'order_id': 340759, 'timestamp': '2024-07-15T08:59:44.151290', 'status': 'open', 'pair': 'ATN-USDC', 'type': 'limit', 'side': 'bid', 'price': '0.90', 'amount': '100.00', 'remain': '100.00'}

Re-check order status

response = requests.get(
    CAX_URL + f"/orders/{order_id}", headers={"API-Key": API}
)
print(response.status_code, response.json()["status"])
200 cancelled

Make a withdraw

response = requests.post(
    CAX_URL + "/withdraws",
    headers={"API-Key": API},
    json={
        "symbol": "ATN",
        "amount": WITHDRAW_ATN_VALUE,
    },
)
print(response.status_code, response.json())
202 {'txid': 683, 'timestamp': '2024-07-15T08:59:48.042482+00:00', 'status': 'accepted', 'symbol': 'ATN', 'account': '0x8EaFBab4A209aF9E587B22A4cc43319c20B2e4D3', 'amount': '1.000000000000000000', 'txhash': None}