Data de elaboração | 9 de maio de 2024 |
Implementação | 13 de maio de 2024 - 12 de julho de 2024 |
Descrição | Desenvolva integração DEXScreener de código aberto |
Autores | Sourabh Niyogi e Matthias Funke |
Dexscreener é uma interface de usuário líder para traders ativos, resumindo a atividade recente de DEX. Atualmente, DEXScreener representa Stellaswap (no Moonbeam), mas por outro lado tem cobertura insuficiente do ecossistema Polkadot. Esta proposta diz respeito ao desenvolvimento do Dexscreener nos próximos 60 dias para:
Espera-se que outros parachains defi Polkadot possam usar o ponto final deste para implementar indexação DEX semelhante para sua cadeia.
A implementação será feita com um contêiner Docker totalmente independente, com um indexador baseado em Node.js usando backend MySQL, seguindo a especificação Dexscreener. Um pequeno número de tabelas block
, asset
, pair
, event
será usado para indexação e suporte aos 4 endpoints a seguir
GET /latest-block
Retorna o último bloco onde os dados de /events
estarão disponíveis
{
"block": {
"blockNumber": 12341234,
"blockTimestamp": 1698126147
}
}
blockTimestamp
é de set.timestamp
GET /asset?id=:string
Retorna informações sobre um ativo no parachain específico. Usamos o id
da paleta assets
no AssetHub (por exemplo, 1984 para USDT) ou da paleta assetRegistry
no HydraDX (por exemplo, 26 para NODL)
Como informamos ao dexscreener quais ativos possuímos? Esse é um endpoint separado?
{
"asset": {
"id": "1000019",
"name": "DED",
"symbol": "DED",
"totalSupply": 10000000,
"circulatingSupply": 900000,
"coinGeckoId": "moonbeam"
}
}
assetRegistry.assets
e xyk.poolAssets
(precisamos juntar alguns metadados fora da cadeia, por exemplo, símbolo e coinGeckoId)Quais campos são opcionais? Pode não haver um coinGeckoId para todos os ativos ou o fornecimento em circulação pode não ser conhecido.
assets.asset
e poolassets.asset
GET /pair?id=:string
Concordamos que os IDs serão sempre classificados em ordem crescente (usando números, não strings), portanto podemos usar uma string como 5-100019
para o par de ativos com IDs 5 e 100019.
O outro par não existe.
{
"pair": {
"id": "5-100019",
"dexKey": "hydradx",
"asset0Id": "5",
"asset1Id": "100019",
"feeBps": 30
}
}
id
será de xyk.poolAssets
ou poolassets.asset
, com asset0Id
e asset1ID
resolvíveisfeeBps
para Hydradx GET /events?fromBlock=:number&toBlock=:number
Retorna eventos de Swap (eventType = swap) e eventos de adição/remoção de liquidez do Pool
{
"events": [
{
"block": {
"blockNumber": 12344321,
"blockTimestamp": 1673319600
},
"eventType": "swap",
"txnId": "0x1118d6bde171a4df1238f5eb69c4b9fff4d4e0169c91268dfa3661d6571faea9",
"txnIndex": 3,
"eventIndex": "12344321-5",
"maker": "7KjNuVyjY5Jv3znWGXSBBHt7Ls6Uwm1LmhswrGGDSYNUAwKW",
"pairId": "5-100019",
"asset0In": 10000,
"asset1Out": 20000,
"priceNative": 2,
"reserves": { "asset0": 100, "asset1": 50 }
},
...
]
}
txnID
é o ExtrinsicHashtxnIndex
é o ExtrinsicIDmaker
é o endereço ss58 do signatário do extrínseco (DISCUTIR: tecnicamente o signatário é o tomador)pairId
corresponde ao pair
asset0In
e asset1Out
são retirados diretamente do evento. (NÃO: precisamos mapear o swap roteado para o par)reserves
e eventos de adição/remoção de pool no omnipool Hydradx? Nossa expectativa é que o Dexscreener conecte os usuários diretamente a uma interface de troca:
e para piscinas:
Pergunta : Este ponto de contato está correto? Acreditamos que isso tem implicações sobre o que o assetid e o pairid deveriam ser e restringe diretamente a seguinte questão.
A suposição é que a maioria das pessoas que usam o dexScreener são degens ou arbitradores. Eles não podem comprar LRNA, portanto podemos fingir que o LRNA não existe? O único problema é que algumas transações serão censuradas, mas há situações em que os LPs são pagos em LRNA e o LRNA é então trocado por outra coisa.
Pergunta: Como as negociações complexas devem ser mapeadas para os eventos?
Precisamos calcular o mapeamento de uma troca roteada para um ou mais pares, implementados no indexador dexscreener. Matthias recomenda que criemos os pares dinamicamente com base em algum limite de volume; nesse caso, é uma questão de quais pares criar "virtualmente".
iBTC para USDT pode ser assim:
... Se alguém realmente tiver tokens de 2 ou 4 pools, nós os mapeamos da seguinte forma:
Exemplos de HydraDX:
https://hydradx.subscan.io/extrinsic/5081726-2
Deve ser ingerido como: 450,391786 USDT -> 0,15 WETH
https://hydradx.subscan.io/extrinsic/5081141-2
Deve ser ingerido como: 500 USDT -> 0,00808666 WBTC
https://hydradx.subscan.io/extrinsic/5080488-0
80.9981538781 vDOT > 51616.002281331759 HDX
https://hydradx.subscan.io/extrinsic/4589219-2?event=4589219-13
Deve mostrar: 10799.9040616235 INTR -> 772.6816006249018 4-Pool (força mapeada para USDT*)
Comentário: neste caso o usuário realmente queria possuir 4 pools.
https://hydradx.subscan.io/extrinsic/4705161-3?event=4705161-37
Deve mostrar: 8899.9696696365 INTR -> 38.8922321335 vDOT