Looking for memecoins on Stonfi in TON or is there life beyond Notcoin
Ivan Romanovich 🧐
Posted on June 10, 2024
Memcoins along with NFT are some of my least favorite crypto trends, no technology, just marketing. But the explosive growth in Q1 2024 draws attention to the memecoin narrative. (According to coingecko, this is the most profitable narrative of Q1 2024, but there are questions about the methodology). Therefore, I suggest trying to find memecoins on TON blockchain by trying to put together a simple memecoin dashboard.
In the article, I want to figure out why memecoin analytical platforms look like a live feed of purchases of these very memecoins. Run through the new Stonfi APIs, the data from this DEX is now displayed on Dexscreener, and separate open APIs have appeared for this, which greatly affects the availability of data (and this is a problem in TON). And thirdly, look at some of your statistical hypotheses regarding pools.
What are we going to look for?
If you google the definition of memecoins, the definitions will vary from the pyramids of our time to the digital meme currency, a new word in the field of social tech. Therefore, within the framework of this article, I offer my definition: Memcoin is a dynamically growing token without an initial utility, using Fomo mechanisms to ensure growth. This definition allows me to formulate a hypothesis: Memcoins are fast-growing small projects, which means you can first cut off large projects by the volume of their pools (Total Value Locked), and then consider small projects by the number of swaps for the last, for example, day.
Building a TVL diagram for Stonfi pools - looking for the threshold beyond which memecoins
Let's start with TVL. Stonfi has two APIs v1/pools - returning the current state of pools and v1/stats/pools - statistics on pools for the period. Let's use v1/pools, we need the pool address, the addresses of the tokens that make up the pool and lp_total_supply_usd - the total supply of lp tokens in the pool. Lp tokens are automatically generated by DEX and credited to the liquidity provider for contributing assets to the liquidity pool. These tokens represent a share of the commissions earned by the liquidity pool. Accordingly, their supply in dollar terms will reflect the TVL.
import requests
r = requests.get('https://api.ston.fi/v1/pools')
result = r.json()['pool_list']
temp_pool_list = [{'pool_address': pool['address'], 'token0_address': pool['token0_address'], 'token1_address': pool['token1_address'], 'tvl': round(float(pool['lp_total_supply_usd']),2)} for pool in result]
# Let's sort
sorted_pool_list = sorted(temp_pool_list, key=lambda d: d['tvl'],reverse=True)
sorted_pool_list[0:5]
After sorting we get:
It is easier to perceive information visually, so let's plot a graph:
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
pool_addresses = [d['pool_address'][-4:] for d in sorted_pool_list]
tvl_values = [d['tvl'] for d in sorted_pool_list]
plt.bar(pool_addresses, tvl_values, color='skyblue',log=True)
plt.xlabel('Pool Address')
plt.ylabel('TVL')
plt.title('TVL for Pools')
plt.xticks(color='w')
plt.tight_layout()
Result:
This graphic clearly shows that the first couple of pools cover all the others in volume, it is also clear that there are plateaus, and the volume of locked funds allows to classify tokens into certain leagues, from small change to simply huge pools.
To play with hypotheses, let's make a pie chart, dividing all the pools by a certain threshold, and put the number of pools in the name, then it will be very clear, for example, that the first three pools in volume contain more than half of the locked liquidity.
threshold = 10000000
big_pools = sum(item['tvl'] for item in sorted_pool_list if item['tvl']>=threshold)
small_pools = sum(item['tvl'] for item in sorted_pool_list if item['tvl']<threshold)
big_pools_count = len([item['tvl'] for item in sorted_pool_list if item['tvl']>=threshold])
small_pools_count = len([item['tvl'] for item in sorted_pool_list if item['tvl']<threshold])
labels = 'Big pools', 'Small pools'
sizes = [big_pools, small_pools]
fig, ax = plt.subplots()
ax.pie(sizes, labels=labels)
ax.set_title("Big pools count:{}, Small pools count {} ".format(big_pools_count,small_pools_count))
Result:
There is a pump fun launchpad on the Solana blockchain, it has a limit of 69k dollars, i.e. you can launch your token, but as soon as it grows above 69k dollars it will “go” to a large exchange, let's try this threshold:
But there are some nuances here, pools can contain pairs of any jettons (the standard of tokens on TON) or TON. But for the most part, these are pools:
- jetton - TON
- jetton - stablecoin
- jetton - Notcoin
Notcoin can be called the largest TON memecoin, so our simple dashboard should start with the dominance of Notcoin. Let's check the diagram:
Notcoin = 'EQAvlWFDxGF2lXm67y4yzC17wYKD9A0guwPkMs1gOsM__NOT'
not_pools = sum(item['tvl'] for item in sorted_pool_list if item['token0_address']==Notcoin or item['token1_address']==Notcoin )
notnot_pools = sum(item['tvl'] for item in sorted_pool_list if item['token0_address']!=Notcoin or item['token1_address']!=Notcoin )
not_count = len([item['tvl'] for item in sorted_pool_list if item['token0_address']==Notcoin or item['token1_address']==Notcoin])
notnot_count = len([item['tvl'] for item in sorted_pool_list if item['token0_address']!=Notcoin or item['token1_address']!=Notcoin])
labels = 'Notcoin pools', 'Other pools count'
sizes = [not_pools, notnot_pools]
fig, ax = plt.subplots()
ax.pie(sizes, labels=labels)
ax.set_title("Notcoin pools count:{}, Other pools count {} ".format(not_count,notnot_count))
Result:
As you can see, compared to other tokens, Notcoin is huge and its dominance is worth considering when reviewing the TON memecoin market.
Liquidity problem
Okay, let's say you've chosen some TVL threshold and looked at Notcoin dominance, but there's no point in looking at TVL any further. Small pools suffer from a liquidity problem - they simply don't have enough swaps. And the liquidity locked in them doesn't allow you to compare them.
That's why memecoin analytics platforms often look like a live feed. Applications scan blocks for swaps in small pools. This allows you to see in about a minute which memecoin is currently growing. To make it clearer what it looks like, I've put together something similar for Stonfi pools:
tonhotshot.fun
First, pools are scanned and the largest pool up to 69k TVL is found - the king of the hill
Then each block is scanned for transactions in Stonfi in pools up to 69k.
And the data is taken from the publicly available Stonfi APIs that I mentioned earlier. Let's try to build our own dashboard on this data.
Ranking Memcoins on Stonfi
We will take data on swaps from the new API created for Dexscreener, this is the Events API (export/dexscreener/v1/events). This API returns all DEX Stonfi events between two blocks. Let's say we select a period of a day for our dashboard, where can we get the current block to start from? There are two options:
The first option is to use the neighboring handle export/dexscreener/v1/latest-block, it will return the last block processed by the exchange backend, which indexes the blockchain and allows us to get data in an aggregated form. The advantage of this approach is that we will get the last block processed by the indexer, the disadvantage is that the handle works on average 10 seconds and this is not always convenient.
ltb = requests.get('https://api.ston.fi/v1/screener/latest-block')
lastest_block = ltb.json()['block']['blockNumber']
The second option is to simply take the last block from the blockchain, yes, the last block in the blockchain is not equal to the last block processed by the exchange indexer, but it is fast, one of the options for how to do this:
# RPS 1 sec
ltb = requests.get('https://toncenter.com/api/v3/masterchainInfo')
return ltb.json()['last']['seqno']
Let's say we take all the events, how do we remove large blocks? Just like we did at the beginning - get all the pools and remove those we don't need:
def get_block_list(sorted_pool_list,threshold):
Notcoin = 'EQAvlWFDxGF2lXm67y4yzC17wYKD9A0guwPkMs1gOsM__NOT'
return [item['pool_address'] for item in sorted_pool_list if item['tvl']>=threshold or item['token0_address'] == Notcoin or item['token1_address'] == Notcoin]
We will also immediately remove pools with notcoin, since we are looking for new memecoins.
After collecting events, we will immediately count the number using Counter:
def count_swap_events(sorted_pool_list,threshold):
blocker = get_block_list(sorted_pool_list,threshold)
ltb = requests.get('https://api.ston.fi/v1/screener/latest-block')
lastest_block = ltb.json()['block']['blockNumber']
start_block=lastest_block - int(86400/5) # TON "sync" block every 5 second, in a day 86400 second
payload = {'fromBlock': start_block, 'toBlock': lastest_block}
r = requests.get('https://api.ston.fi/export/dexscreener/v1/events', params=payload)
count_arr=[]
for item in r.json()['events']:
if(item['eventType']=='swap'):
if(item["pairId"] not in blocker):
count_arr.append(item)
c = Counter()
for event in count_arr:
c[event["pairId"]] += 1
To grab a couple more handles, we will enrich our data using only the pool address, for this we will use /export/dexscreener/v1/pair/ to get the token addresses and use /v1/assets/ to get the token names or TON.
def pool_pair(pool_addr):
p = requests.get('https://api.ston.fi/export/dexscreener/v1/pair/{}'.format(pool_addr))
try:
pair=p.json()['pool']
return jetton_name(pair['asset0Id']) +"-"+ jetton_name(pair['asset1Id'])
except:
return pool_addr
Here I will note that this is just a tutorial and all the code is written as primitively as possible so that you can read it diagonally. Let's enrich our Counter and sort it:
def count_swap_events(sorted_pool_list,threshold):
blocker = get_block_list(sorted_pool_list,threshold)
ltb = requests.get('https://api.ston.fi/v1/screener/latest-block')
lastest_block = ltb.json()['block']['blockNumber']
start_block=lastest_block - int(86400/5) # TON "обновляет" блоки каждые 5 секунд в дне 86400 секунд
payload = {'fromBlock': start_block, 'toBlock': lastest_block}
r = requests.get('https://api.ston.fi/export/dexscreener/v1/events', params=payload)
count_arr=[]
for item in r.json()['events']:
if(item['eventType']=='swap'):
if(item["pairId"] not in blocker):
count_arr.append(item)
c = Counter()
for event in count_arr:
c[event["pairId"]] += 1
enriched_arr=[]
for pool in sorted(list(c.items()), key=lambda d: d[1],reverse=True)[0:30]:
enriched_arr.append({"pool": pool_pair(pool[0]),'24h_swaps':pool[1]})
return enriched_arr
Result is something like this:
Of course, there is much that can be improved, but I suggest the reader to complete the dashboard himself, all Stonfi APIs can be viewed here - https://api.ston.fi/swagger-ui/
Conclusion
I admire the TON blockchain for its technical elegance, at least it is not another copy of Ethereum, which is accelerated with the help of large capital without looking back, and in general why does the user need it. If you want to learn more about the TON blockchain, I have open source lessons, thanks to which you will learn how to create full-fledged applications on TON.
https://github.com/romanovichim/TonFunClessons_ENG
I throw new tutorials and data analytics here
Posted on June 10, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.