The Piccadilly Circus Games have now finished.

This site is an archive. Visit forecastathon.ai for the current Autonity Competition!

Join the Autonity Discord to take part in the community.

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}