StarkEx Spot Trading Playground tutorial

The StarkEx Spot Playground is a deployment of StarkEx for Spot Trading 5.0 on the Goerli testnet that provides a simple demonstration of the StarkEx scalability solution. You can use the Playground to:

  • easily submit transactions to StarkEx,

  • see these transactions in a StarkEx batch, and

  • watch how the state, including your transactions, is updated on-chain in the StarkEx contract.

If you want to skip a few steps and develop your own application, see the StarkEx SDK and the StarkEx Crypto SDK.

If you have questions, at any step of the way, please contact us at info@starkware.co.

A real StarkEx instance compared with the Playground

Elements of a real StarkEx instance differ from the playground, as described in Table 1, “A real StarkEx instance compared with the Playground”.

The purpose of this Playground is to facilitate manual experimentation, but it is not optimized for, nor is it intended to be used for, automated testing. When you are ready to conduct testing, including automation, contact us at info@starkware.co to set up your own dedicated test instance.

Table 1. A real StarkEx instance compared with the Playground
A real StarkEx instance StarkEx Playground

You are the only operator. You have full control of your StarkEx instance.

There are multiple operators.

You manage the allocation of vault ids as part of your application.

The vault id that you choose for your transaction might already be occupied by someone else.

You are the only one sending transactions, so you shouldn’t call get_first_unused_tx_id.

StarkEx processes transactions sequentially, based on the value of each transaction’s ID, so the ids in your list of transactions must include all integers in the range of values.

For example, for a list of three transactions, the list of transaction ID values cannot be 0,1,3, it must be 0,1,2. The list can also be non-sequential, such as 0,2,1. If the list doesn’t include an integer, StarkEx stops processing when it reaches the missing ID and waits for it to be submitted.

In order to get the next transaction ID, you must query the StarkEx gateway by calling get_first_unused_tx_id, because other Playground users need to sync the next tx_id.

Be aware that StarkEx does not process two transactions with the same ID and does not process a transaction if the transaction with the previous ID has not been processed.

The time for a transaction to appear on-chain after being submitted can be up to 18 hours.

The time for a transaction to appear on-chain after being submitted is approximately five minutes.

Try StarkEx: Deposit, Withdraw, Settle, and Mint

The StarkEx Playground package provides a list of valid, pre-prepared StarkEx transactions, such as deposits, withdrawals, settlements, and mint requests. You also get a Player script that submits these transactions to StarkEx.

Simply run the Player and:

  • observe the transactions as they propagate through StarkEx,

  • query StarkEx to see the latest off-chain batch with your transactions in it, and

  • watch as a new on-chain state is formed in the StarkEx smart contract.

For more information about StarkEx, see the High level overview.

Prerequisites

  • Git.

  • An Infura endpoint link for the Goerli testnet. If you don’t have one, please open an Ethereum account at https://infura.io/ to acquire a link.

  • Docker. To install Docker on Ubuntu Linux or other Debian-based Linux distributions, enter the following command:

    $ sudo apt install -y docker.io
  • A Goerli Eth account with enough Eth to pay for the deposit transaction gas. For your convenience, you can try this faucet.

Preparing the Playground

Procedure
  1. Clone the Git repo at https://github.com/starkware-libs/starkex-playground:

    $ git clone git@github.com:starkware-libs/starkex-playground.git
  2. Change to starkex-playground directory:

    $ cd starkex-playground
  3. Build the Docker image:

    $ docker build -t <MEMORABLE_NAME> . --no-cache

The Playground package includes the following files:

txs.json

A list of on-chain transactions, including deposits, settlements, and withdrawals that are executed from the Vault range that you were assigned. These transactions are valid and signed by pre-defined users with their public Stark key. This allows you to observe a full StarkEx operation cycle without getting into the details of the exact transaction for each operation.

player.py

A python script that checks and submits the list of transactions specified in txs.json to the StarkEx contract and the StarkEx off-chain service. These transactions are then submitted to the on-chain StarkEx service, executed, and added to the batch to be submitted as a new on-chain state.

Running the Playground

Procedure
  1. If necessary, change to the starkex-playground directory.

  2. Run the Docker image:

    $ docker run -it <MEMORABLE_NAME>
    root@f4725d0858d2:/app#

    In the Docker container, you can run the following command for further instructions:

    root@f4725d0858d2:/app# ./player.py --help
  3. Run the Player script by running the following command:

    $ ./player.py --txs txs.json --node_url <your infura node> --funder_private_key <your Goerli private key> --verbose

    You can export your Goerli private key from MetaMask:

    1. select Account Details from the menu next to the account address.

    2. select Export Private Key and provide your MetaMask password.

      This key is required to fund on-chain deposits and will only be used locally to sign the transactions.

Analyzing the output

The output includes two types:

  1. On-chain deposit transactions' description of the StarkEx contract with Etherscan links. See Figure 1, “On-chain transactions”.

  2. Off-chain StarkEx transactions' description containing the transaction type and unique tx_id. See Figure 2, “Off-chain transactions”.

On-chain transactions
Figure 1. On-chain transactions
Off-chain StarkEx transactions
Figure 2. Off-chain transactions

Congratulations! You’ve submitted your first StarkEx transactions. You can see the on-chain state update in a few minutes.

So, what happened here?

Which transactions did I submit?

The file txs.json contains an explicit list of transactions in StarkEx API format.

Let’s look at the following Deposit transaction as an example:

{
   "stark_key": "0xf8c6635f9cfe85f46759dc2eebe71a45b765687e35dbe5e74e8bde347813ef",
   "amount": "35",
   "token_id": "0x2761e6ac2b90cbef6f456a307e1715192da8eff78ceeb316a235e7cea822d71",
   "vault_id": 11454,
   "type": "DepositRequest"
}
  • stark_key is the cryptographic key that lets you sign transactions

  • amount is the value of the transfer

  • token_id is the ERC-20 token StarkEx identifier

  • vault_id is the account number in StarkEx that you are depositing to — this account must be an account that is associated with the specified stark_key

  • type describes the transaction type submitted, in this case, a DepositRequest.

How do I see the on-chain state update?

You can check the state in the StarkEx Playground smart contract at https://goerli.etherscan.io/address/0x921cb8950942F8d4870f3d2EAa922A098B27f582. If your batch is already submitted on-chain (allow about 5 minutes), you will see a state update transaction.

You can also check what happened in the Verifier smart contract, which verifies STARK proofs, at https://goerli.etherscan.io/address/0x8f97970aC5a9aa8D130d35146F5b59c4aef57963. You will see that a new proof was submitted for verification. Once the proof is verified, a new Fact is registered on-chain approving the proof validation. The StarkEx contract checks this Fact before updating the state.

How can I read the off-chain vault balances?

Vault balances derive directly from the history of the transactions that were submitted to StarkEx batches. You can query this information off-chain by using the Feeder Gateway StarkEx API. You must keep track of off-chain vault balances in your application’s state. StarkEx does not provide a direct way to query this information.

You cannot query the last batch until it has been created. So it is recommended to query the last batch only when you can track the on-chain state update.

Procedure
  1. Get the last batch_id, using the Feeder gateway’s get_last_batch_id method:

    root@55ea2d387b6e:/app# wget -nv -q -O- https://gw.playground-v2.starkex.co/feeder_gateway/v2/get_last_batch_id; echo
    <batch_id>
    root@55ea2d387b6e:/app#

    The output of this command is a unique identifier that you should use as the input for the next command.

  2. Get the content of the batch whose ID, <batch_id> was output in the previous step:

    root@55ea2d387b6e:/app# wget -nv -q -O- https://gw.playground-v2.starkex.co/feeder_gateway/v2/get_batch_info?batch_id=<batch_id>; echo
Example

This example demonstrates how to get batch information. You can use this information to keep track of off-chain vault balances.

root@1b001e90ef20:/app# wget -nv -q -O- https://gw.playground-v2.starkex.co/feeder_gateway/v2/get_last_batch_id; echo
150
root@1b001e90ef20:/app# wget -nv -q -O- https://gw.playground-v2.starkex.co/feeder_gateway/v2/get_batch_info?batch_id=150; echo
{
    "prev_batch_id": 149,
    "sequence_number": 5,
    "time_created": 1685529456,
    "txs_info": [
        {
            "alt_txs": [],
            "original_tx": {
                "amount": "1",
                "stark_key": "0x77a3b314db07c45076d11f62b6f9e748a39790441823307743cf00d6597ea43",
                "token_id": "0x5163d8842de4924f0c661d33905ad94558c453068d01fa160525ace0047e06",
                "type": "DepositRequest",
                "vault_id": 9223372038365814290
            },
            "tx_id": 88,
            "was_replaced": true
        },
        {
            "alt_txs": [],
            "original_tx": {
                "amount": "4029557120079369747",
                "stark_key": "0x7c65c1e82e2e662f728b4fa42485e3a0a5d2f346baa9455e3e70682c2094cac",
                "token_id": "0x2dd48fd7a024204f7c1bd874da5e709d4713d60c8a70639eb1167b367a9c378",
                "type": "DepositRequest",
                "vault_id": 1654615998
            },
            "tx_id": 109,
            "was_replaced": true
        },
        {
            "alt_txs": null,
            "original_tx": {
                "amount": "0",
                "stark_key": "0x0",
                "token_id": "0x0",
                "type": "WithdrawalRequest",
                "vault_id": 0
            },
            "tx_id": 110,
            "was_replaced": false
        }
    ]
}

Lines 2-14 provide the information about the order tree root and the vault tree root, which represents the state.

Lines 21 onward display the information about the transactions in the batch.

  • You can see your transactions using the tx_id that you saw in the Player script output, such as in line 27. Pay close attention to the field was_replaced.

  • Invalid transactions get the value true, as per the first and second transactions in lines 28 and 40 of Output of the feeder gateway.

  • Valid transactions are not replaced, and are assigned the value false, as per Output of the feeder gateway continued, line 52.

  • The StarkEx Playground is configured to skip invalid transactions rather than replacing them. However, in practice, this is a good indicator of whether the transaction was executed or not.

Output of the feeder gateway
Figure 3. Output of the feeder gateway
Output of the feeder gateway continued
Figure 4. Output of the feeder gateway continued

This is so cool! How do I submit some of my own transactions?

If you want to take it up a notch, you can modify the list of transactions by yourself or create a new list. To learn more about StarkEx flows, see the following topics:

Additional resources

When you send transactions to the StarkEx Playground, they should be valid according to StarkEx’s business logic, or they will be rejected. For example, an invalid transaction is a deposit transaction with Alice’s public Stark key to a vault that corresponds to Bob’s public Stark key.

I need some more guidance, can you help me?

Sure! Please contact us at info@starkware.co.