Getting Started for Publishers

Learn about publishers

Price Publishers for Off-Chain Stork

If you are a data provider that can provide low-latency data to Stork, or a validator familiar with node operation, get in touch via info@stork.network.

Price Publishers for StarkNet

If you're interested in publishing prices, you should get in touch. Publishing is straightforward. At the present time we are prioritizing publishers with a track record of community involvement on StarkNet, unique access to first-party data, or a recognized contribution to other oracles.

Permissions

At present, Stork manages publishing permissions on a per-publisher basis. This will likely change to support more granular permissions.

Data Types

As a publisher, you have the option of publishing data from your own first party data, or by integrating directly with exchanges and price aggregators such as CryptoCompare.

To submit a price for a single asset, use the primary endpoint and submit a PriceTick with a tick type of "tick". To submit an aggregated number, use the "PriceAggregate" data structure. Note that at present, the aggregated datapoint is the same as the price tick, but includes additional metadata such as liquidity.

Providing Liquidity Data

Stork supports a price metadata called liquidity. At present, liquidity data is provided by Dexterity Capital in the PriceAggregate endpoint, but we expect to open this to additional oracles in the future.

Docker

Work is in progress on a docker container that can be used by publishers that wish to simply "plug and play" their data sources into an existing implementation, or use a standard set of data sources. Note that we recommend publishers use their own data sources, as this ensures a more robust data set.

Signing of Data

Presently, authentication is done using accounts. At some point in the future, we may require signature proofs of individual prices (note that StarkNet uses a slightly different ECDSA curve).

Sample Python Publisher Implementation (StarkNet)

# Uses starknet.py
import time
import os
from starknet_py.contract import Contract
from starknet_py.net import Client, AccountClient, KeyPair

ORACLE_NAME = "COMPANY-1"     # Provided by Stork
TICK_TYPE   = "tick"          # Fixed value 
MAX_FEE     = 13*10**13       # Example; use fee estimates for actual application

STARKNET_ADDRESS = os.getenv("STARKNET_ADDRESS")
STARKNET_PRIVATE = os.getenv("STARKNET_PRIVATE")
STARKNET_NET     = os.getenv("STARKNET_NET") # must be testnet

ASSETS = ["BTC/USD", "ETH/USD"] # This is at your discretion, so long as the asset is allowlisted

# 1) Initialize Account - see https://www.cairo-lang.org/docs/hello_starknet/account_setup.html
# 2) Fund your acocunt with Goerli StarkNet ETH – or reach out and Stork can provide 
#    Faucet: https://faucet.goerli.starknet.io, or bridge from L1: 
#   https://goerli.starkgate.starknet.io/

# 3) Share account address with us for allowlisting

# 4) Save account address and key in hex as env variables and initialize an account aclient
account_client = AccountClient(
     address=STARKNET_ADDRESS,
     key_pair=KeyPair.from_private_key(int(STARKNET_PRIVATE[2:],16)),
     chain=StarknetChainId.TESTNET,
     net=STARKNET_NET
 )
 
price_ticks = []
# 5) For each asset, get its median price
for asset in ASSETS:
    median_price     = 1000            # Your Code to calculate price for asset goes here
    asset_resolution = 18              # Resolution code goes here
    timestamp        = int(time.time() # earliest time the data was acquired int(time.time())
    chain_median     = int(median_price * (10**asset_resolution))
	
    price_ticks.append({
        "asset":     asset, 
        "value":     chain_median, 
        "timestamp": timestamp,
        "publisher": ORACLE_NAME,
        "type":      TICK_TYPE
    })

# 5) Submit the data; use submit_single to submit prices individually
# Below code uses _sync for ease of debugging, but should generally be used async
invokation = contract.functions['submit_multiple'].invoke_sync(price_ticks, max_fee=max_fee)
result = invokation.wait_for_acceptance_sync()

Last updated