O cartão de pool e o seu JSON
Duas coisas neste site foram feitas para outros sites: um cartão com a faixa sugerida de um pool, que qualquer página pode colocar num frame, e os mesmos números em JSON, que o código de qualquer site pode ler. Nenhuma das duas exige chave ou conta. As duas são descritas aqui como o código as serve, e testes prendem esta página a esse código: cada parâmetro listado é um com que o endereço é lido, e cada campo, um contra o qual a resposta é conferida antes de ser enviada.
O cartão
/embed/pool é uma página pequena escrita à mão, não pelo framework do site. Ela mostra o par com seu protocolo, taxa e rede; a faixa sugerida, com o horizonte e a largura para os quais foi traçada; o preço atual; uma linha dizendo que não é recomendação financeira; e um link de volta para a página do pool aqui, que abre numa nova aba. A faixa é sempre traçada com os padrões do site, 30 dias a 1σ, quaisquer que sejam os ajustes de cada um. Uma nota é acrescentada enquanto o preço atual está fora da faixa, e outra para um pool v4 cujo hook pode mudar quanto custa um swap.
Ela não tem script nem formulário e não carrega nada: sua própria Content-Security-Policy não permite nada além do seu estilo inline. As cores são as do site, claras ou escuras conforme o sistema do leitor está configurado. Ela não enxerga a página ao redor, e não há parâmetro para escolher.
Dê a ela um frame de 360 pixels de largura e 220 de altura, ou 260 de altura para um pool cujo hook pode mudar quanto custa um swap, cujo cartão traz essa linha a mais. É exatamente o que a página de cada pool oferece em "Incorporar este pool", já com a altura certa para aquele pool, e o frame oferecido nunca fica mais largo que a coluna onde é colado.
É a única página deste site que outro site pode colocar num frame. Todo outro endereço, este incluído, é servido com X-Frame-Options: DENY e frame-ancestors 'none'; o cartão é servido sem o primeiro e com frame-ancestors *.
<iframe src="https://liquiditywise.com/embed/pool?address=0x8ad599c3a0ff1de082011efddc58f1908eb6e6d8" title="USDC / WETH on LiquidityWise" width="360" height="220" style="border:0;max-width:100%" loading="lazy"></iframe>Content-Type: text/html; charset=utf-8
Cache-Control: public, max-age=300, s-maxage=300
Content-Security-Policy: default-src 'none'; style-src 'unsafe-inline'; base-uri 'none'; form-action 'none'; frame-ancestors *Parâmetros
O cartão e o JSON recebem os mesmos parâmetros e nomeiam um pool como as próprias páginas do site: um pool v3 pelo seu address, como em /pool, e um pool v4 pelo seu id, como em /v4. É preciso exatamente um dos dois, e qual deles chegou diz qual é o protocolo. Um pool ou uma rede nomeados duas vezes são recusados, em vez de um dos valores ser escolhido, e qualquer parâmetro que não esteja listado aqui é ignorado.
O idioma vem só do endereço, nunca do navegador do leitor nem de um cookie: quem escolhe é o site que coloca o cartão, e o mesmo endereço é a mesma resposta para todos que o carregam, o que permite a um cache guardá-la. O cartão é escrito nos 10 idiomas do site, e em árabe ele corre da direita para a esquerda.
address- Aceita O endereço do contrato de um pool v3:
0xe 40 dígitos hexadecimais, em maiúsculas ou minúsculas. - Senão Qualquer outra coisa não nomeia nenhum pool, nem um pool v3 numa rede em que o v3 não é lido (Unichain):
400, e nada é lido. id- Aceita O id de um pool v4, o hash da sua chave:
0xe 64 dígitos hexadecimais, em maiúsculas ou minúsculas. - Senão Qualquer outra coisa não nomeia nenhum pool:
400, e nada é lido. Nem umidao lado de umaddress. chain- Aceita O identificador curto de uma rede, da tabela abaixo. Sem ele, a rede é a Ethereum.
- Senão Um identificador que o site não lê é recusado, nunca lido como Ethereum:
400. lang- Aceita Um código de idioma da lista abaixo, para as palavras do cartão e o
disclaimerdo JSON; os números são os mesmos em todos os idiomas. Sem ele, inglês. - Senão Qualquer outro valor, ou
langduas vezes, dá inglês. Nunca é recusado.
As redes, pelo identificador que chain aceita:
chain | Rede | pools v3 | pools v4 |
|---|---|---|---|
ethereum | Ethereum | lidos | lidos |
base | Base | lidos | lidos |
arbitrum | Arbitrum One | lidos | lidos |
unichain | Unichain | não lidos | lidos |
optimism | OP Mainnet | lidos | lidos |
polygon | Polygon | lidos | lidos |
Os idiomas, pelo código que lang aceita:
enEnglishtrTürkçedeDeutschesEspañolarالعربيةhiहिन्दीzh中文ruРусскийptPortuguêszh-Hant繁體中文
O JSON
GET /api/embed/pool, com os mesmos parâmetros, responde com os números do cartão em JSON, para um site que prefere desenhá-los ele mesmo: a mesma leitura, guardada pelo mesmo tempo. Cada número é um número JSON, e cada preço vem no sentido em que a página do pool o escreve: quantos price.quote vale um price.base.
Antes de ser enviada, uma resposta é conferida contra o seu esquema, e uma que não o cumpre não é enviada: o pool é respondido como ilegível. Por isso uma resposta com status 200 sempre tem exatamente os campos abaixo, nem mais nem menos.
O script de qualquer site pode lê-la. Toda resposta, erros e recusas incluídos, é servida com Access-Control-Allow-Origin: *. Ela não grava cookie nem exige credencial. Um GET simples não precisa de preflight, e nenhum é respondido, então envie-o sem cabeçalhos próprios.
Content-Type: application/json; charset=utf-8
Cache-Control: public, max-age=300, s-maxage=300
Access-Control-Allow-Origin: *Cada campo de uma resposta 200, com seu tipo JSON:
protocol"v3" | "v4"v3para um pool nomeado poraddress,v4para um nomeado porid.chain.idinteger > 0- O chain id da rede.
chain.slugstring- O identificador curto da rede, como
chaino aceita. chain.namestring- O nome da rede.
poolstring- O endereço (v3) ou o id (v4) do pool, em minúsculas.
pair.token0string- O símbolo do primeiro token do pool, como o contrato dele o declara: é texto de um contrato que qualquer um pode implantar, então escape-o antes de colocá-lo numa página.
pair.token1string- O símbolo do segundo token, do mesmo jeito.
lpFeePpminteger ≥ 0 | null- A taxa que o pool paga aos provedores de liquidez num swap, em milionésimos:
3000é 0,3%.nullquando o hook de um pool v4 define a taxa swap a swap. price.basestring- O token para uma unidade do qual cada preço é dado.
price.quotestring- O token em que cada preço é contado.
price.currentnumber > 0- O preço do pool quando foi lido.
range.lowernumber > 0- A borda inferior da faixa sugerida, como preço.
range.uppernumber > 0- A borda superior.
range.currentInRangeboolean- Se o preço atual está dentro da faixa. Quando não está, o cartão acrescenta uma nota.
range.lowerTruncatedbooleantruequando a grade de ticks do pool não alcança a borda inferior da banda, de modo que a faixa para antes dela.range.upperTruncatedboolean- O mesmo, para a borda superior.
parameters.horizonDaysinteger > 0- O horizonte para o qual a faixa foi traçada, em dias: sempre o padrão, 30.
parameters.standardDeviationMultipliernumber > 0- A largura para a qual foi traçada, em desvios-padrão: sempre o padrão, 1σ.
hookMayAlterSwapsbooleantruepara um pool v4 cujo hook pode mudar quanto custa um swap, lido do endereço do hook;falsepara o v3, para um pool v4 sem hook e para um hook cujas permissões não tocam nos swaps. Onde étrue, o cartão traz uma nota.analysedAtstring (ISO 8601)- Quando o preço foi lido, em UTC, ao milissegundo — não quando esta resposta foi enviada, o que pode ser minutos depois.
poolUrlstring- A página do pool neste site, com o mesmo horizonte e a mesma largura.
disclaimerstring- O que os números são e o que não são, no idioma que
langindica.
{
"protocol": "v3",
"chain": {
"id": 1,
"slug": "ethereum",
"name": "Ethereum"
},
"pool": "0x8ad599c3a0ff1de082011efddc58f1908eb6e6d8",
"pair": {
"token0": "USDC",
"token1": "WETH"
},
"lpFeePpm": 3000,
"price": {
"base": "WETH",
"quote": "USDC",
"current": 3000
},
"range": {
"lower": 2824.2704157479307,
"upper": 3184.336896959513,
"currentInRange": true,
"lowerTruncated": false,
"upperTruncated": false
},
"parameters": {
"horizonDays": 30,
"standardDeviationMultiplier": 1
},
"hookMayAlterSwaps": false,
"analysedAt": "2026-08-21T09:15:00.000Z",
"poolUrl": "https://liquiditywise.com/pool?address=0x8ad599c3a0ff1de082011efddc58f1908eb6e6d8&days=30&sigma=1",
"disclaimer": "For information only, not financial advice. The range is worked out from how far this pool's price moved over the last 30 days: it is not a forecast and not a recommendation."
}Códigos de status e erros
O cartão e o JSON respondem com os mesmos códigos de status. Nenhum dos dois responde nunca com a página de erro do próprio site nem com o que deu errado por dentro: o cartão mostra uma frase e seu link de volta, e o JSON responde com um error que um script pode testar e com disclaimer — exceto uma recusa, que traz a espera no lugar dele.
A resposta do JSON, com por quanto tempo pode ser guardada:
200
Os números: um cartão com eles, ou o JSON acima.
Cache-Control: public, max-age=300, s-maxage=300400 not-a-pool
O endereço não nomeia nenhum pool que o site lê: nem address nem id, ou os dois, ou um malformado ou repetido, uma rede que o site não lê, ou um pool v3 onde só o v4 é lido (Unichain). Nada foi lido, e perguntar de novo não muda a resposta.
Cache-Control: public, max-age=3600, s-maxage=3600
{
"error": "not-a-pool",
"disclaimer": "For information only, not financial advice. The range is worked out from how far this pool's price moved over the last 30 days: it is not a forecast and not a recommendation."
}503 unreadable
Um pool bem nomeado que não pôde ser lido agora: uma fonte não respondeu a tempo, ou não existe esse pool nessa rede. poolUrl continua levando à página dele. Perguntar de novo em um minuto pode encontrá-lo.
Cache-Control: public, max-age=60, s-maxage=60
{
"error": "unreadable",
"poolUrl": "https://liquiditywise.com/pool?address=0x8ad599c3a0ff1de082011efddc58f1908eb6e6d8&days=30&sigma=1",
"disclaimer": "For information only, not financial advice. The range is worked out from how far this pool's price moved over the last 30 days: it is not a forecast and not a recommendation."
}429 rate-limited
Requisições demais de um mesmo cliente: veja o limite abaixo. Retry-After e retryAfterSeconds dizem os dois quantos segundos esperar. O cartão responde com uma página curta que diz isso, no próprio idioma.
Cache-Control: no-store
Retry-After: 42
{
"error": "rate-limited",
"retryAfterSeconds": 42
}Cache e limite de requisições
Toda resposta diz por quanto tempo pode ser guardada, por um navegador e por um cache compartilhado: 300 segundos para os números; 60 segundos para um pool que não pôde ser lido, para que um que volta não apareça como ilegível por muito tempo; 3.600 segundos para um endereço que não nomeia nenhum pool, o que nenhum momento posterior vai mudar. Uma recusa nunca é guardada. Cada resposta é a mesma para todos que perguntam com o mesmo endereço, e é isso que torna seguro guardá-la.
Por trás disso, o servidor guarda os números de cada pool por 300 segundos a partir do momento em que os leu, para o cartão e para o JSON, em todos os idiomas: cada cartão de um pool, em cada página onde estiver, é uma única leitura até ela expirar. Um pool que não pôde ser lido não é guardado, e é consultado de novo na próxima requisição. Por isso o preço numa resposta pode ser mais antigo que a resposta: analysedAt diz quando ele foi lido.
Uma requisição que nomeia um pool bem formado lê esse pool, então conta contra a mesma cota das páginas de pool do próprio site: 10 requisições por cliente numa janela de 60 segundos que começa na primeira requisição do cliente, sendo o cliente o endereço IP de onde a requisição chega ao site. Passado o limite, a resposta é 429, com Retry-After. Conta toda requisição assim que chega ao site, inclusive a respondida com o que o servidor guardou; uma requisição que não nomeia nenhum pool não conta.
Num navegador, um cartão ou um fetch conta contra o leitor que o carrega, não contra o site onde está — então, numa página com mais de 10 cartões, os que passam disso são recusados para cada leitor. Num servidor, todas as suas requisições dividem a única cota desse servidor: guarde cada resposta pelos 300 segundos que ela permite, o que custa pouco, pois na maior parte desse tempo o servidor responderia com a leitura que você já tem. O limite existe para manter baixo o custo de ler pools, e nada aqui promete que ele vá ficar como está.
Exemplos
curl -s "https://liquiditywise.com/api/embed/pool?address=0x8ad599c3a0ff1de082011efddc58f1908eb6e6d8"const response = await fetch(
"https://liquiditywise.com/api/embed/pool?address=0x8ad599c3a0ff1de082011efddc58f1908eb6e6d8",
);
const body = await response.json();
if (response.ok) {
// The range, in body.price.quote per one body.price.base
console.log(body.range.lower, body.range.upper, body.price.quote, body.price.base);
console.log(body.disclaimer);
} else if (response.status === 429) {
console.log(`Asked too often: wait ${body.retryAfterSeconds} seconds`);
} else {
console.log(body.error); // "not-a-pool" or "unreadable"
}<iframe src="https://liquiditywise.com/embed/pool?address=0x8ad599c3a0ff1de082011efddc58f1908eb6e6d8" title="USDC / WETH on LiquidityWise" width="360" height="220" style="border:0;max-width:100%" loading="lazy"></iframe>Um clique seleciona um bloco inteiro, pronto para copiar.
Condições, em palavras simples
Os números são medições, não recomendações. A faixa é calculada a partir de quanto o preço do pool se moveu nos últimos 30 dias: não é uma previsão nem uma recomendação de investimento, e toda resposta diz isso por si mesma, o cartão na própria face e o JSON em disclaimer. Como cada número é obtido, e o que cada um deixa de fora, está em "Como funciona".
O cartão traz seu próprio link de volta, "Analisado por LiquidityWise". O JSON não tem campo de atribuição, e nada no código pede uma; o que ele traz é poolUrl, a página do pool aqui, e disclaimer. Mostrados ao lado dos números, esses dois dizem ao leitor de onde eles vieram e o que são.
Não há número de versão nem chave, nem promessa de que a forma da resposta vá ficar como está ou de que o site esteja no ar num dado momento. O que vale é mais estreito: uma resposta é conferida contra o seu esquema antes de ser enviada, e testes prendem esta página a esse esquema e ao código que lê o endereço, então ela descreve o que é servido agora. Uma mudança em qualquer um dos dois aparece no histórico público do código.
O código é aberto, sob a licença MIT.