← LiquidityWise

La tarjeta de pool y su JSON

Red principal de Ethereum

Dos cosas de este sitio están pensadas para otros sitios: una tarjeta con el rango sugerido de un pool, que cualquier página puede poner en un marco, y las mismas cifras en JSON, que el código de cualquier sitio puede leer. Ninguna de las dos necesita una clave ni una cuenta. Ambas se describen aquí tal como el código las sirve, y unas pruebas mantienen esta página fiel a ese código: cada parámetro que enumera es uno con el que se lee la dirección, y cada campo, uno contra el que se comprueba la respuesta antes de enviarla.

La tarjeta

/embed/pool es una página pequeña escrita a mano, no por el framework del sitio. Muestra el par con su protocolo, su comisión y su red; el rango sugerido, con el horizonte y la amplitud para los que se trazó; el precio actual; una línea que dice que no es asesoramiento financiero; y un enlace de vuelta a la página del pool aquí, que se abre en una pestaña nueva. El rango se traza siempre con los valores predeterminados del sitio, 30 días a 1σ, sean cuales sean los ajustes de cada cual. Se añade una nota mientras el precio actual está fuera del rango, y otra para un pool v4 cuyo hook puede cambiar lo que cuesta un intercambio.

No lleva script ni formulario y no carga nada: su propia Content-Security-Policy no permite más que su estilo en línea. Sus colores son los del sitio, claros u oscuros según tenga configurado el sistema el lector. No puede ver la página que la rodea, y no hay ningún parámetro para elegirlo.

Dele un marco de 360 píxeles de ancho y 220 de alto, o 260 de alto para un pool cuyo hook puede cambiar lo que cuesta un intercambio, cuya tarjeta lleva esa línea más. Es exactamente lo que ofrece la página de cada pool bajo «Insertar este pool», con la altura ya adecuada para ese pool, y el marco que ofrece nunca crece más que la columna en la que se pega.

Es la única página de este sitio que otro sitio puede poner en un marco. Cualquier otra dirección, esta incluida, se sirve con X-Frame-Options: DENY y frame-ancestors 'none'; la tarjeta se sirve sin lo primero y con frame-ancestors *.

El marco para el pool USDC / WETH al 0,3 % en Ethereum, tal como lo ofrece la página de ese pool:
<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>
Con qué se sirve una tarjeta con cifras, además de las cabeceras que lleva cada página:
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

La tarjeta y el JSON aceptan los mismos parámetros y nombran un pool como lo hacen las propias páginas del sitio: un pool v3 por su address, como en /pool, y un pool v4 por su id, como en /v4. Hace falta exactamente uno de los dos, y el que llega dice de qué protocolo se trata. Un pool o una red nombrados dos veces se rechazan en lugar de elegir uno de sus valores, y cualquier parámetro que no figure aquí se ignora.

El idioma sale solo de la dirección, nunca del navegador del lector ni de una cookie: lo elige el sitio que coloca la tarjeta, y la misma dirección es la misma respuesta para todos los que la cargan, que es lo que permite a una caché guardarla. La tarjeta está escrita en los 10 idiomas del sitio, y en árabe se lee de derecha a izquierda.

address
Acepta La dirección del contrato de un pool v3: 0x y 40 dígitos hexadecimales, en mayúsculas o minúsculas.
Si no Cualquier otra cosa no nombra ningún pool, y tampoco un pool v3 en una red donde no se lee v3 (Unichain): 400, y no se lee nada.
id
Acepta El id de un pool v4, el hash de su clave: 0x y 64 dígitos hexadecimales, en mayúsculas o minúsculas.
Si no Cualquier otra cosa no nombra ningún pool: 400, y no se lee nada. Tampoco un id junto a una address.
chain
Acepta El identificador corto de una red, de la tabla de abajo. Si falta, la red es Ethereum.
Si no Un identificador que el sitio no lee se rechaza, nunca se lee como Ethereum: 400.
lang
Acepta Un código de idioma de la lista de abajo, para las palabras de la tarjeta y el disclaimer del JSON; las cifras son las mismas en todos los idiomas. Si falta, inglés.
Si no Cualquier otro valor, o lang dos veces, da inglés. Nunca se rechaza.

Las redes, por el identificador que acepta chain:

chainRedpools v3pools v4
ethereumEthereumse leense leen
baseBasese leense leen
arbitrumArbitrum Onese leense leen
unichainUnichainno se leense leen
optimismOP Mainnetse leense leen
polygonPolygonse leense leen

Los idiomas, por el código que acepta lang:

  • enEnglish
  • trTürkçe
  • deDeutsch
  • esEspañol
  • arالعربية
  • hiहिन्दी
  • zh中文
  • ruРусский
  • ptPortuguês
  • zh-Hant繁體中文

El JSON

GET /api/embed/pool, con los mismos parámetros, responde con las cifras de la tarjeta en JSON, para un sitio que prefiere dibujarlas por su cuenta: la misma lectura, guardada el mismo tiempo. Cada cifra es un número JSON, y cada precio va en el sentido en que lo escribe la página del pool: cuántos price.quote vale un price.base.

Antes de enviarse, una respuesta se comprueba contra su esquema, y la que no lo cumple no se envía: el pool se responde como ilegible. Así que una respuesta con estado 200 tiene siempre exactamente los campos de abajo, ni más ni menos.

El script de cualquier sitio puede leerla. Cada respuesta, errores y rechazos incluidos, se sirve con Access-Control-Allow-Origin: *. No deja cookies ni necesita credenciales. Un GET sencillo no necesita preflight, y no se responde a ninguno, así que envíelo sin cabeceras propias.

Con qué se sirve una respuesta con cifras, además de las cabeceras que lleva cada página:
Content-Type: application/json; charset=utf-8
Cache-Control: public, max-age=300, s-maxage=300
Access-Control-Allow-Origin: *

Cada campo de una respuesta 200, con su tipo JSON:

protocol"v3" | "v4"
v3 para un pool nombrado por address, v4 para uno nombrado por id.
chain.idinteger > 0
El chain id de la red.
chain.slugstring
El identificador corto de la red, tal como lo acepta chain.
chain.namestring
El nombre de la red.
poolstring
La dirección (v3) o el id (v4) del pool, en minúsculas.
pair.token0string
El símbolo del primer token del pool, tal como lo declara su contrato: es texto de un contrato que cualquiera puede desplegar, así que escápelo antes de ponerlo en una página.
pair.token1string
El símbolo del segundo token, igual.
lpFeePpminteger ≥ 0 | null
La comisión que el pool paga a los proveedores de liquidez en un intercambio, en millonésimas: 3000 es un 0,3 %. null cuando el hook de un pool v4 fija la comisión intercambio a intercambio.
price.basestring
El token por cada unidad del cual se da cada precio.
price.quotestring
El token en el que se cuenta cada precio.
price.currentnumber > 0
El precio del pool cuando se leyó.
range.lowernumber > 0
El borde inferior del rango sugerido, como precio.
range.uppernumber > 0
Su borde superior.
range.currentInRangeboolean
Si el precio actual está dentro del rango. Si no lo está, la tarjeta añade una nota.
range.lowerTruncatedboolean
true cuando la cuadrícula de ticks del pool no llega hasta el borde inferior de la banda, así que el rango se queda antes.
range.upperTruncatedboolean
Lo mismo, para el borde superior.
parameters.horizonDaysinteger > 0
El horizonte para el que se trazó el rango, en días: siempre el predeterminado, 30.
parameters.standardDeviationMultipliernumber > 0
La amplitud para la que se trazó, en desviaciones estándar: siempre la predeterminada, 1σ.
hookMayAlterSwapsboolean
true para un pool v4 cuyo hook puede cambiar lo que cuesta un intercambio, leído de la dirección del hook; false para v3, para un pool v4 sin hook y para un hook cuyos permisos no tocan los intercambios. Donde es true, la tarjeta lleva una nota.
analysedAtstring (ISO 8601)
Cuándo se leyó el precio, en UTC y al milisegundo; no cuándo se envió esta respuesta, que puede ser minutos después.
poolUrlstring
La página del pool en este sitio, con el mismo horizonte y la misma amplitud.
disclaimerstring
Qué son las cifras y qué no, en el idioma que indica lang.
Una respuesta para el pool de los ejemplos. Sus cifras son un ejemplo: las calcula el propio código del sitio a partir de un mes de precios de muestra, no se leen del pool, y una prueba comprueba que el código sigue respondiendo exactamente esto para ese mes:
{
  "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 estado y errores

La tarjeta y el JSON responden con los mismos códigos de estado. Ninguno responde nunca con la página de error del propio sitio ni con lo que falló por dentro: la tarjeta muestra una frase y su enlace de vuelta, y el JSON responde con un error que un script puede comprobar y con disclaimer, salvo un rechazo, que lleva en su lugar la espera.

La respuesta del JSON, con cuánto tiempo se puede guardar:

200

Las cifras: una tarjeta con ellas, o el JSON de arriba.

Cache-Control: public, max-age=300, s-maxage=300

400 not-a-pool

La dirección no nombra ningún pool que el sitio lea: ni address ni id, o los dos, o uno mal formado o repetido, una red que el sitio no lee, o un pool v3 donde solo se lee v4 (Unichain). No se leyó nada, y volver a preguntar no cambiará la respuesta.

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

Un pool bien nombrado que no se pudo leer ahora mismo: una fuente no respondió a tiempo, o no existe ese pool en esa red. poolUrl sigue llevando a su página. Preguntar de nuevo en un minuto puede encontrarlo.

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

Demasiadas peticiones de un mismo cliente: vea el límite más abajo. Retry-After y retryAfterSeconds dicen los dos cuántos segundos esperar. La tarjeta responde con una página corta que lo dice, en su propio idioma.

Cache-Control: no-store
Retry-After: 42

{
  "error": "rate-limited",
  "retryAfterSeconds": 42
}

Caché y límite de peticiones

Cada respuesta dice cuánto tiempo se puede guardar, tanto en un navegador como en una caché compartida: 300 segundos las cifras; 60 segundos un pool que no se pudo leer, para que uno que vuelve no se muestre como ilegible durante mucho tiempo; 3600 segundos una dirección que no nombra ningún pool, cosa que ningún momento posterior cambiará. Un rechazo no se guarda nunca. Cada respuesta es la misma para todos los que preguntan con la misma dirección, y eso es lo que hace seguro guardarla.

Detrás de eso, el servidor guarda las cifras de cada pool 300 segundos desde el momento en que las leyó, igual para la tarjeta que para el JSON y en todos los idiomas: cada tarjeta de un pool, en cada página donde esté, es una sola lectura hasta que caduca. Un pool que no se pudo leer no se guarda, y se vuelve a preguntar en la siguiente petición. Así que el precio de una respuesta puede ser más antiguo que la respuesta: analysedAt dice cuándo se leyó.

Una petición que nombra un pool bien formado lee ese pool, así que cuenta contra la misma asignación que las páginas de pools del propio sitio: 10 peticiones por cliente en una ventana de 60 segundos que empieza con la primera petición del cliente, siendo el cliente la dirección IP desde la que la petición llega al sitio. Pasado ese límite, la respuesta es 429, con Retry-After. Cuenta cada petición así que llega al sitio, incluida la que se responde con lo que guarda el servidor; una petición que no nombra ningún pool no cuenta.

Desde un navegador, una tarjeta o un fetch cuenta contra el lector que lo carga, no contra el sitio donde está, así que en una página con más de 10 tarjetas las que pasan de ese número se rechazan para cada lector. Desde un servidor, todas sus peticiones comparten la única asignación de ese servidor: guarde cada respuesta los 300 segundos que permite, lo que cuesta poco, porque durante la mayor parte de ese tiempo el servidor respondería con la lectura que usted ya tiene. El límite existe para que leer pools cueste poco, y nada aquí promete que vaya a seguir igual.

Ejemplos

Las cifras, desde una terminal:
curl -s "https://liquiditywise.com/api/embed/pool?address=0x8ad599c3a0ff1de082011efddc58f1908eb6e6d8"
Desde el propio script de una página, o desde un servidor, con cada respuesta tratada:
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"
}
La tarjeta, en una página:
<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>

Un clic selecciona todo un bloque, listo para copiar.

Condiciones, en palabras sencillas

Las cifras son mediciones, no asesoramiento. El rango se calcula a partir de cuánto se movió el precio del pool en los últimos 30 días: no es una previsión ni una recomendación, y cada respuesta lo dice por sí misma, la tarjeta a la vista y el JSON en disclaimer. Cómo se obtiene cada cifra, y qué deja fuera cada una, está en «Cómo funciona».

La tarjeta lleva su propio enlace de vuelta, «Analizado por LiquidityWise». El JSON no tiene ningún campo de atribución, y nada en el código la pide; lo que lleva es poolUrl, la página del pool aquí, y disclaimer. Mostrados junto a las cifras, esos dos le dicen al lector de dónde salen y qué son.

No hay número de versión ni clave, ni ninguna promesa de que la forma de la respuesta siga como está o de que el sitio esté disponible en un momento dado. Lo que se cumple es más estrecho: una respuesta se comprueba contra su esquema antes de enviarse, y unas pruebas mantienen esta página fiel a ese esquema y al código que lee la dirección, así que describe lo que se sirve ahora. Un cambio en cualquiera de los dos queda a la vista en el historial público del código.

El código es abierto, bajo la licencia MIT.

Cómo funcionaEl código, en GitHubLa licencia MIT