StarkEx Perpetual Trading Playground tutorial
The StarkEx Perpetual Trading Playground is a deployment of StarkEx for Perpetual Trading 2.0 on the Sepolia testnet that provides a simple demonstration of the StarkEx scalability solution. You can use the Playground to learn StarkEx hands-on and start developing your own application on the Sepolia testnet.
On the playground, you can perform the following flows, which represent a limited collection of the Perpetual system’s full API:
-
Deposit -
Inserting collateral assets from an onchain wallet to an offchain position. -
Transfer -
Transferring assets between two offchain positions. -
Trade -
Issuing a trade between two users offchain: Trading synthetic assets, or trading collateral for synthetic assets. -
Withdrawal -
Reclaiming assets from an offchain position to receive them onchain.
For a detailed breakdown of these flows, see the Gateway API in the StarkEx API Reference.
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. |
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 position ids as part of your application. |
The position 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 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 |
In order to get the next transaction ID, you must query the StarkEx gateway by calling 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 onchain after being submitted can be up to 18 hours. |
The time for a transaction to appear onchain after being submitted is approximately five minutes. |
StarkEx for Perpetual Trading |
|
You must implement funding ticks. |
Funding ticks are not necessary. |
Running the Playground
The Playground is a StarkEx test environment running on the Sepolia testnet. Use the curl
command to issue requests to the Playground’s gateway.
Use the following URLs to interact with the test environment via the StarkEx API:
-
Gateway:
https://perpetual-playground-sepolia-v2.starkex.co/gateway
-
Feeder gateway:
https://perpetual-playground-sepolia-v2.starkex.co/feeder_gateway
Prerequisites
-
An Infura endpoint link for Sepolia. If you don’t have one, please open an Ethereum account at https://infura.io/ to acquire a link.
-
A Sepolia ETH account with enough ETH to pay for the deposit transaction gas fees. For your convenience, you can try this faucet to obtain Sepolia ETH.
-
curl
is installed.
Conducting transactions in the Playground
-
Generate a Stark key pair using the Creating a Stark key process, detailed in the Hands-on demonstration below.
In order to send your own transactions, you must sign transactions with a STARK signature, which requires your own Stark key pair. You can use the StarkEx Crypto SDK or the Python Crypto Library.
-
Make a deposit to the positions you want to play with:
-
Send a deposit transaction onchain to the StarkEx perpetual contract.
-
Send a deposit transaction offchain.
-
Now, you can perform any of the following transaction flows:
These are all explained in Hands-on demonstration, below.
For more information, on the corresponding APIs, see the StarkEx Perpetual Trading API Reference.
|
Hands-on demonstration
The following is a hands-on guide for newcomers to the StarkEx Perpetual Trading system, which leads you step-by-step from the initial starting point of generating your own Stark key pair, up to the point where you issue a trade offchain. If you are familiar with the workings on the Perpetual system, or simply wish to skip this section and explore the system on your own, see General configuration.
-
Generate a Stark key pair via the Key derivation process:
In order to interact with the offchain system, a user must have a dedicated Stark key.
The Stark key pair consists of the private Stark key, which is used to sign transactions the owner wishes to execute, and a public Stark key, which represents the user’s address/identity offchain.
Generate a Stark key pair using either the StarkEx Crypto SDK or the Python Crypto Library.
-
To generate a Stark key pair using the StarkEx Crypto SDK:
keyGen = require('./src/js/key_derivation.js') starkKey = keyGen.privateToStarkKey("3c1e9550e66958296d11b60f8e8e7a7ad990d07fa65d5f7652c4a6c87d4e3cc")
This example uses a pre-generated private Stark key example, but you can generate your own by randomizing a 62 character hex-string.
-
To generate a Stark key using the Python Crypto Library:
from starkware.crypto.signature.signature import * private_stark_key = get_random_private_key() stark_key = private_key_to_ec_point_on_stark_curve(priv_key)[0]
-
-
Mint collateral and approve the StarkEx contract as a spender via the: mock ERC-20 contract.
This is a precursor to the deposit phase and allows you to deposit the simulated collateral asset that the playground supports.
-
Navigate to the Contract tab, and under that to Write Contract.
-
Connect your Metamask wallet so you are able to invoke the contract’s functions.
-
Use the
selfMint
function to add 10000000000000 tokens to your wallet (to send the transaction via Metamask click the Write button):
-
Use the
approve
function to authorize StarkEx to spend your collateral onchain. Set the StarkEx contract address (0xE616885fe8c64bB7D07a932916b7fD93cdd40a35
) as the spender, and set the amount at10000000000000
:
-
-
Issue a deposit to the StarkEx contract onchain, here: https://sepolia.etherscan.io/address/0xE616885fe8c64bB7D07a932916b7fD93cdd40a35#writeContract
This is the first in a 2-phase deposit process that gives you access to the collateral asset offchain.
-
Go to the Write Contract tab on this contract and connect your Metamask wallet as in the previous step.
-
Issue a deposit of collateral tokens using the
deposit
function:The function receives as input:
-
Your public Stark key (generated in step 1), represented as an integer.
-
The collateral asset ID offchain (given as the integer
1462689598990563437242498716673917341065799132144045992877344104815146517955
) -
A
vault_id
of your choosing, an integer representing a position to occupy offchain (should be selected at random). -
An amount to deposit, in this case
241535140800
-
-
-
Send a deposit request to the StarkEx gateway (perpetual deposit documentation):
Any user can issue a deposit to the onchain contract (as demonstrated in the previous step), thereby locking the desired amount of funds for use offchain.
It is only when a subsequent deposit request is sent to the gateway that the deposit event onchain is processed and (if the transaction passes the validation checks) the balance of the target position offchain is updated accordingly.
A deposit request to the StarkEx gateway must always be preceded by a valid onchain deposit.
-
Get the first_unused_tx_id:
curl https://perpetual-playground-sepolia-v2.starkex.co/gateway/get_first_unused_tx_id; echo
-
Note the response, which serves as the transaction ID,
tx_id
, in the following transaction.-
Transactions sent to the StarkEx gateway must be serialized.
-
The above method allows us to get the next available transaction ID which we can assign to our following deposit request.
-
-
Run the following command to send a deposit request to the StarkEx gateway:
curl -d '{"tx_id":<tx_id>,"tx":{"position_id":"<vault_id>","public_key":"<stark_key (in hex format)>","amount":"241535140800","type":"DEPOSIT"}}' https://perpetual-playground-sepolia-v2.starkex.co/gateway/add_transaction; echo
The fields in this transaction should match those filled in the previous step (issuing a deposit to the onchain contract).
-
Note that the
position_id
is equal to thevault_id
chosen in the previous step. -
The
tx_id
is received usingget_first_unused_tx_id
and is then incremented for following transactions. -
The
public_key
is your public Stark key, given as a hex string.
-
-
Note the response from the gateway - you should see
\{"code": "TRANSACTION_RECEIVED"}
to indicate the gateway has received your transaction.
-
-
Verify your deposit transaction is being processed. For more information, see the Feeder Gateway in the StarkEx Perpetual v2.0 REST API Reference:
-
A transaction received by the gateway isn’t guaranteed to be processed.
-
A number of validation checks are run before a transaction is included in the next batch, and failing these validations causes the Perpetual playground to disregard this transaction
-
As a future-operator, you have control over the policy regarding failed transactions.
-
Query the feeder-gateway for the latest batch ID:
curl https://perpetual-playground-sepolia-v2.starkex.co/feeder_gateway/get_last_batch_id; echo
This query gives you the most recent batch ID that is being processed by the system, which should include your previous transaction.
-
Use the latest batch ID to get the batch info from the feeder-gateway:
curl https://perpetual-playground-sepolia-v2.starkex.co/feeder_gateway/get_batch_info?batch_id=<latest batch_id>; echo
-
Look for your deposit in the list of recorded transactions (identified by its uniquely assigned
tx_id
). -
If the transaction isn’t in the list you may try querying a previous batch ID (if all transactions in the batch you are currently reviewing have a greater
tx_id
than your transaction. -
If your transaction doesn’t appear and there is a different transaction occupying the
tx_id
you assigned this may be an indication your transaction has failed. In this case go back to step 3 and retry. -
If your transaction appears in the batch then this means you should now already have an offchain balance in your selected position to interact with.
-
-
-
Send some collateral to another position using an offchain transfer transaction (perpetual transfer doc):
-
Transfers in the Perpetual StarkEx system allow to move collateral (and only collateral) assets between positions.
-
This example transfers collateral to some predetermined position
-
First we need to generate a signature for our desired transfer message:
-
Using
perpetual_messages.py
:# Generate message hash to sign. transfer_msg_hash = get_transfer_msg( asset_id= 1462689598990563437242498716673917341065799132144045992877344104815146517955, asset_id_fee=0, receiver_public_key= 2825868930652315540133093693348064822157481518754303749560050236804923333506, sender_position_id=<insert position_id>, receiver_position_id=4, src_fee_position_id=<insert position_id>, nonce=0, amount=3, max_amount_fee=0, expiration_timestamp=20000000) # Sign message with previously generated private key. r, s = sign( msg_hash=transfer_msg_hash, priv_key=priv_key) # Verify signature matches message and public Stark key. verify( msg_hash=transfer_msg_hash, r=r, s=s, public_key=stark_key) # Display signature components as hex. hex(r) hex(s)
-
Using
perpetual_messages.js
:# Generate message hash to sign. const perpetualMsgs = require('./perpetual_messages.js') msgHash = perpetualMsgs.getPerpetualTransferMessage("1462689598990563437242498716673917341065799132144045992877344104815146517955"/*assetId*/, "0"/*assetIdFee*/, "2825868930652315540133093693348064822157481518754303749560050236804923333506"/*receiverPublicKey*/, "<insert position_id>"/*senderPositionId*/, "4"/*receiverPositionId*/, "<insert position_id>"/*srcFeePositionId*/, "0"/*nonce*/, "3"/*amount*/, "0"/*maxAmountFee*/, "20000000"/*expirationTimestamp*/) # Sign message with previously generated private key. const sigLib = require('./src/js/signature.js'); sig = sigLib.sign(keyPair, msgHash) # Verify signature matches message and public Stark key. sigLib.verify(keyPair, msgHash, sig)
-
-
Send an
add_transaction
request to the StarkEx gateway, providing our transfer message payload with the signature represented by the componentsr
ands
(remember to use an updatedtx_id
):curl -d '{"tx_id":tx_id,"tx":{"amount":"3","asset_id":"0xa21edc9d9997b1b1956f542fe95922518a9e28ace11b7b2972a1974bf5971f","expiration_timestamp":"20000000","nonce":"0","receiver_position_id":"4","receiver_public_key":"0x63f62982fa598ad7c4e469870b3a1c23316ba8fb717aa2b1ee3114283fb1b82","sender_position_id":"<your position_id>","sender_public_key":"<your public stark_key>","signature":{"r":"<your r>","s":"<your s>"}, "type":"TRANSFER"}}' https://perpetual-playground-sepolia-v2.starkex.co/gateway/add_transaction; echo
-
As with the deposit request submission, verify your transfer is being processed via the feeder gateway.
-
Congratulations, you have officially successfully transmitted a dedicated offchain transaction in the Perpetual Playground system. You may now use the remaining funds you deposited in the previous steps to play around freely with the system - send more transfers, execute trades, and learn by experiment!
Analyzing the output
The output includes two types:
-
Onchain deposit transactions' description of the StarkEx contract with Etherscan links.
-
offchain StarkEx transactions' description containing the transaction type and unique tx_id.
How do I see the onchain state update?
-
You can check the state in the StarkEx Perpetual Playground smart contract at https://sepolia.etherscan.io/address/0xE616885fe8c64bB7D07a932916b7fD93cdd40a35#writeContract. If your batch is already submitted onchain (allow about 5 minutes), you should see a
StateUpdate
transaction. -
You can check what happened in the Verifier smart contract, which verifies STARK proofs, at https://sepolia.etherscan.io/address/0x07ec0D28e50322Eb0C159B9090ecF3aeA8346DFe.
You should see that a new proof is submitted for verification. Once the proof is verified, a new Fact is registered onchain approving the proof validation. The StarkEx contract checks this Fact before updating the state.
How can I read the offchain position balances?
Position balances derive directly from the history of the transactions that were submitted to StarkEx batches. You can query this information offchain by using the Feeder Gateway StarkEx Perpetual Trading API.
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 onchain state update. |
General configuration
The playground consists of the following components:
-
Collateral asset
Name: SelfService
ERC20 Address: 0xd44BB808bfE43095dBb94c83077766382D63952a
Asset_id: '0xa21edc9d9997b1b1956f542fe95922518a9e28ace11b7b2972a1974bf5971f'
Resolution: 106
-
Three synthetic assets
-
'0x4254432d3130000000000000000000'
Name: BTC
Resolution: 1010
Risk factor: This asset’s risk factor has only this one segment:
risk: 214748365
upper_bound: 340282366920938463463374607431768211455
External price: 56236.782298457914212352
Internal price: 24153514080
-
'0x4554482d3800000000000000000000'
Name: ETH
Resolution: 108
Risk factor: This asset’s risk factor has only this one segment:
risk: 322122548
upper_bound: 340282366920938463463374607431768211455
External price: 245.752267153034510336
Internal price: 10554979503
-
'0x4c494e4b2d37000000000000000000'
Name : LINK
Resolution: 107
Risk factor: This asset’s risk factor has only this one segment:
risk: 429496730
upper_bound: 340282366920938463463374607431768211455
External price: 93.785511767155703808
Internal price: 40280570588
-
asset_id: '0xa21edc9d9997b1b1956f542fe95922518a9e28ace11b7b2972a1974bf5971f'
resolution: '0xf4240'
fee_position_info:
position_id: '123456'
public_key:
'0x811921ddf8b35b688ede6d94a16293bddabb2362'
orders_tree_height: 64
positions_tree_height: 64
synthetic_assets_info:
'0x4254432d3130000000000000000000':
resolution: '0x2540be400'
risk_factor: '214748365'
'0x4554482d3800000000000000000000':
resolution: '0x5f5e100'
risk_factor: '322122548'
'0x4c494e4b2d37000000000000000000':
resolution: '0x989680'
risk_factor: '429496730'
In a real StarkEx instance the general configuration includes more details regarding the oracle and funding tick. |
Oracle price tick
{
"tx_id":1,
"tx":{
"type":"ORACLE_PRICES_TICK",
"oracle_prices":{
"0x4254432d3130000000000000000000":{
"signed_prices":{
"0x60de32cdaf78bdab488d87f7720d5f3898f16d1461203621731f80fa85c35ff":{
"timestamped_signature":{
"timestamp":"1597468993",
"signature":{
"r":"0x7612fff3397a4b1f8ca578613c5540b46e308d948009d88a0bed9f7192997e8",
"s":"0x5974522f5844b7f010b0a21772ad77aef59582fb3cb2f263650e60baa844fdf"
}
},
"external_asset_id":"0x425443555344000000000000000000004d616b6572",
"price":"56236782298457914212352"
}
},
"price":"24153514080"
},
"0x4554482d3800000000000000000000":{
"signed_prices":{
"0x793e9f602abba40f00411d6320287fb4d180c06c99f768d3cf91b613f3c8810":{
"timestamped_signature":{
"timestamp":"1511954808",
"signature":{
"r":"0x1ba6a1601eacfe82c195cc234d4f0e6100afb66265b8b768907aacaf63c42b3",
"s":"0x3c6b4e4ca06a6d733e2d83d4857bab85c06b4e52fcaf1b2264a0ca01cbf1a0e"
}
},
"external_asset_id":"0x455448555344000000000000000000004d616b6572",
"price":"245752267153034510336"
}
},
"price":"10554979503"
},
"0x4c494e4b2d37000000000000000000":{
"signed_prices":{
"0x636b2c4f887da6f50dee35f21d0582b4944fe8dd1e83f61e63dabeff3e4846f":{
"timestamped_signature":{
"timestamp":"1480980993",
"signature":{
"r":"0x7f1887fba5d66e13aba37c8859531cc1f90dd59fc06479f86fab6e57ca4615c",
"s":"0x776545d06ae5fdf4102a07366efe43775f4977ba8d89cea9612ce6e9b7c2ca8"
}
},
"external_asset_id":"0x4c494e4b5553440000000000000000004d616b6572",
"price":"93785511767155703808"
}
},
"price":"40280570588"
}
},
"timestamp":"1667993252"
}
}
Additional resources
-
Gateway API in the StarkEx Perpetual Trading REST API Reference
-
Feeder Gateway API in the StarkEx Perpetual Trading REST API Reference
I need some more guidance, can you help me?
Sure! Please contact us at info@starkware.co.