← LiquidityWise

Die Pool-Karte und ihr JSON

Ethereum-Mainnet

Zwei Dinge auf dieser Website sind für andere Websites gedacht: eine Karte mit dem vorgeschlagenen Bereich eines Pools, die jede Seite in einen Frame setzen darf, und dieselben Zahlen als JSON, die der Code jeder Website lesen darf. Keines von beiden braucht einen Schlüssel oder ein Konto. Beide sind hier so beschrieben, wie der Code sie ausliefert, und Tests halten diese Seite an diesen Code: Jeder Parameter, den sie nennt, ist einer, mit dem die Adresse gelesen wird, und jedes Feld eines, gegen das die Antwort vor dem Senden geprüft wird.

Die Karte

/embed/pool ist eine kleine Seite, von Hand geschrieben statt vom Framework der Website. Sie zeigt das Paar mit Protokoll, Gebühr und Netzwerk; den vorgeschlagenen Bereich mit dem Horizont und der Breite, für die er gezeichnet wurde; den aktuellen Preis; eine Zeile, dass dies keine Finanzberatung ist; und einen Link zurück zur Seite des Pools hier, der sich in einem neuen Tab öffnet. Der Bereich wird immer für die Voreinstellungen der Website gezeichnet, 30 Tage bei 1σ, ganz gleich, wie jemand selbst eingestellt hat. Eine Notiz kommt hinzu, solange der aktuelle Preis außerhalb des Bereichs liegt, und eine weitere bei einem v4-Pool, dessen Hook ändern kann, was ein Tausch kostet.

Sie enthält kein Skript und kein Formular und lädt nichts: Ihre eigene Content-Security-Policy erlaubt nichts außer ihrem Inline-Stil. Ihre Farben sind die der Website, hell oder dunkel, je nachdem, wie das System des Lesers eingestellt ist. Die Seite um sie herum sieht sie nicht, und es gibt keinen Parameter, um das zu wählen.

Geben Sie ihr einen Frame von 360 Pixeln Breite und 220 Pixeln Höhe, oder 260 Pixel Höhe bei einem Pool, dessen Hook ändern kann, was ein Tausch kostet — dessen Karte trägt eine Zeile mehr. Genau das bietet die Seite jedes Pools unter „Diesen Pool einbetten“ an, mit der für diesen Pool schon passenden Höhe, und der angebotene Frame wird nie breiter als die Spalte, in die er eingefügt wird.

Sie ist die einzige Seite dieser Website, die eine andere Website in einen Frame setzen darf. Jede andere Adresse, diese eingeschlossen, wird mit X-Frame-Options: DENY und frame-ancestors 'none' ausgeliefert; die Karte ohne das Erste und mit frame-ancestors *.

Der Frame für den USDC / WETH-Pool mit 0,3 % auf Ethereum, so wie die Seite dieses Pools ihn anbietet:
<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>
Womit eine Karte mit Zahlen ausgeliefert wird, neben den Headern, die jede Seite trägt:
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 *

Parameter

Die Karte und das JSON nehmen dieselben Parameter und benennen einen Pool so wie die Seiten der Website selbst: einen v3-Pool mit seiner address wie auf /pool, einen v4-Pool mit seiner id wie auf /v4. Genau einer der beiden wird gebraucht, und welcher ankommt, sagt, welches Protokoll es ist. Ein zweimal genannter Pool oder ein zweimal genanntes Netzwerk wird abgelehnt, statt dass einer der Werte gewählt wird, und jeder hier nicht aufgeführte Parameter wird ignoriert.

Die Sprache kommt allein aus der Adresse, nie aus dem Browser des Lesers oder aus einem Cookie: Die Website, die die Karte einbindet, wählt sie, und dieselbe Adresse ist für alle, die sie laden, dieselbe Antwort — erst das erlaubt einem Cache, sie aufzubewahren. Die Karte gibt es in allen 10 Sprachen der Website, und auf Arabisch läuft sie von rechts nach links.

address
Akzeptiert Die Vertragsadresse eines v3-Pools: 0x und 40 Hexadezimalziffern, in Groß- oder Kleinbuchstaben.
Sonst Alles andere benennt keinen Pool, ebenso ein v3-Pool auf einem Netzwerk, auf dem v3 nicht gelesen wird (Unichain): 400, und nichts wird gelesen.
id
Akzeptiert Die ID eines v4-Pools, der Hash seines Schlüssels: 0x und 64 Hexadezimalziffern, in Groß- oder Kleinbuchstaben.
Sonst Alles andere benennt keinen Pool: 400, und nichts wird gelesen. Ebenso eine id neben einer address.
chain
Akzeptiert Das Kürzel eines Netzwerks aus der Tabelle unten. Fehlt es, ist das Netzwerk Ethereum.
Sonst Ein Kürzel, das die Website nicht liest, wird abgelehnt, nie als Ethereum gelesen: 400.
lang
Akzeptiert Ein Sprachcode aus der Liste unten, für die Worte der Karte und das disclaimer des JSON; die Zahlen sind in jeder Sprache dieselben. Fehlt er, Englisch.
Sonst Jeder andere Wert, oder lang zweimal, ergibt Englisch. Abgelehnt wird nie.

Die Netzwerke, nach dem Kürzel, das chain nimmt:

chainNetzwerkv3-Poolsv4-Pools
ethereumEthereumgelesengelesen
baseBasegelesengelesen
arbitrumArbitrum Onegelesengelesen
unichainUnichainnicht gelesengelesen
optimismOP Mainnetgelesengelesen
polygonPolygongelesengelesen

Die Sprachen, nach dem Code, den lang nimmt:

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

Das JSON

GET /api/embed/pool beantwortet mit denselben Parametern die Zahlen der Karte als JSON, für eine Website, die sie lieber selbst zeichnet: dieselbe Lesung, genauso lange aufbewahrt. Jede Zahl ist eine JSON-Zahl, und jeder Preis steht so herum, wie die Seite des Pools ihn schreibt — wie viele price.quote ein price.base wert ist.

Bevor eine Antwort gesendet wird, wird sie gegen ihr Schema geprüft, und eine, die es nicht erfüllt, wird nicht gesendet: Der Pool wird stattdessen als nicht lesbar beantwortet. Eine Antwort mit Status 200 hat also immer genau die Felder unten, nicht mehr und nicht weniger.

Das Skript jeder Website darf sie lesen. Jede Antwort, Fehler und Ablehnungen eingeschlossen, wird mit Access-Control-Allow-Origin: * ausgeliefert. Sie setzt kein Cookie und braucht keine Anmeldedaten. Ein schlichtes GET braucht keinen Preflight, und keiner wird beantwortet — senden Sie es also ohne eigene Header.

Womit eine Antwort mit Zahlen ausgeliefert wird, neben den Headern, die jede Seite trägt:
Content-Type: application/json; charset=utf-8
Cache-Control: public, max-age=300, s-maxage=300
Access-Control-Allow-Origin: *

Jedes Feld einer 200-Antwort, mit seinem JSON-Typ:

protocol"v3" | "v4"
v3 für einen mit address benannten Pool, v4 für einen mit id benannten.
chain.idinteger > 0
Die Chain-ID des Netzwerks.
chain.slugstring
Das Kürzel des Netzwerks, so wie chain es nimmt.
chain.namestring
Der Name des Netzwerks.
poolstring
Die Adresse (v3) oder ID (v4) des Pools, in Kleinbuchstaben.
pair.token0string
Das Symbol des ersten Tokens des Pools, so wie sein Vertrag es angibt: Text aus einem Vertrag, den jeder deployen kann — escapen Sie ihn also, bevor Sie ihn in eine Seite setzen.
pair.token1string
Das Symbol des zweiten Tokens, ebenso.
lpFeePpminteger ≥ 0 | null
Die Gebühr, die der Pool den Liquiditätsanbietern bei einem Tausch zahlt, in Millionsteln: 3000 sind 0,3 %. null, wenn der Hook eines v4-Pools die Gebühr Tausch für Tausch festlegt.
price.basestring
Der Token, für dessen eine Einheit jeder Preis gilt.
price.quotestring
Der Token, in dem jeder Preis gezählt wird.
price.currentnumber > 0
Der Preis des Pools, als er gelesen wurde.
range.lowernumber > 0
Die untere Grenze des vorgeschlagenen Bereichs, als Preis.
range.uppernumber > 0
Seine obere Grenze.
range.currentInRangeboolean
Ob der aktuelle Preis im Bereich liegt. Wenn nicht, setzt die Karte eine Notiz hinzu.
range.lowerTruncatedboolean
true, wenn das Tick-Raster des Pools nicht bis zur unteren Grenze des Bandes reicht, sodass der Bereich davor endet.
range.upperTruncatedboolean
Dasselbe für die obere Grenze.
parameters.horizonDaysinteger > 0
Der Horizont, für den der Bereich gezeichnet wurde, in Tagen: immer die Voreinstellung, 30.
parameters.standardDeviationMultipliernumber > 0
Die Breite, für die er gezeichnet wurde, in Standardabweichungen: immer die Voreinstellung, 1σ.
hookMayAlterSwapsboolean
true für einen v4-Pool, dessen Hook ändern kann, was ein Tausch kostet, gelesen aus der Adresse des Hooks; false für v3, für einen v4-Pool ohne Hook und für einen Hook, dessen Berechtigungen Tausche unberührt lassen. Wo es true ist, trägt die Karte eine Notiz.
analysedAtstring (ISO 8601)
Wann der Preis gelesen wurde, in UTC und auf die Millisekunde — nicht, wann diese Antwort gesendet wurde; das kann Minuten später sein.
poolUrlstring
Die Seite des Pools auf dieser Website, mit demselben Horizont und derselben Breite.
disclaimerstring
Was die Zahlen sind und was nicht, in der Sprache, die lang nennt.
Eine Antwort für den Pool aus den Beispielen. Ihre Zahlen sind ein Beispiel: vom Code der Website aus einem Beispielmonat von Preisen berechnet, nicht aus dem Pool gelesen — und ein Test prüft, dass der Code für diesen Monat noch genau das antwortet:
{
  "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."
}

Statuscodes und Fehler

Die Karte und das JSON antworten mit denselben Statuscodes. Keines von beiden antwortet je mit der eigenen Fehlerseite der Website oder damit, was intern schiefging: Die Karte zeigt einen Satz und ihren Link zurück, das JSON antwortet mit einem error, den ein Skript prüfen kann, und mit disclaimer — außer bei einer Ablehnung, die stattdessen die Wartezeit trägt.

Die Antwort des JSON, mit der Dauer, die sie aufbewahrt werden darf:

200

Die Zahlen: eine Karte mit ihnen oder das JSON oben.

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

400 not-a-pool

Die Adresse benennt keinen Pool, den die Website liest: weder address noch id, oder beide, oder einer fehlerhaft oder doppelt, ein Netzwerk, das die Website nicht liest, oder ein v3-Pool, wo nur v4 gelesen wird (Unichain). Nichts wurde gelesen, und erneutes Fragen ändert die Antwort nicht.

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

Ein korrekt benannter Pool, der gerade nicht gelesen werden konnte: Eine Quelle hat nicht rechtzeitig geantwortet, oder auf diesem Netzwerk gibt es keinen solchen Pool. poolUrl führt trotzdem zu seiner Seite. In einer Minute erneut zu fragen kann ihn finden.

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

Zu viele Anfragen von einem Client: siehe das Anfragelimit unten. Retry-After und retryAfterSeconds sagen beide, wie viele Sekunden zu warten ist. Die Karte antwortet mit einer kurzen Seite, die das sagt, in ihrer eigenen Sprache.

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

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

Caching und das Anfragelimit

Jede Antwort sagt, wie lange sie aufbewahrt werden darf, von einem Browser wie von einem gemeinsamen Cache: 300 Sekunden für die Zahlen; 60 Sekunden für einen Pool, der nicht gelesen werden konnte, damit einer, der wieder antwortet, nicht lange als unlesbar erscheint; 3.600 Sekunden für eine Adresse, die keinen Pool benennt, was kein späterer Moment ändert. Eine Ablehnung wird nie aufbewahrt. Jede Antwort ist für alle, die mit derselben Adresse fragen, dieselbe — das macht das Aufbewahren sicher.

Dahinter bewahrt der Server die Zahlen jedes Pools 300 Sekunden ab dem Moment auf, in dem er sie gelesen hat, für die Karte und das JSON gleichermaßen und in jeder Sprache: Jede Karte eines Pools ist, auf jeder Seite, auf der sie steht, eine einzige Lesung, bis diese abläuft. Ein Pool, der nicht gelesen werden konnte, wird nicht aufbewahrt und bei der nächsten Anfrage erneut gefragt. Der Preis in einer Antwort kann also älter sein als die Antwort: analysedAt sagt, wann er gelesen wurde.

Eine Anfrage, die einen korrekt benannten Pool nennt, liest diesen Pool und wird deshalb gegen dasselbe Kontingent gezählt wie die Pool-Seiten der Website: 10 Anfragen pro Client in einem Fenster von 60 Sekunden, das mit der ersten Anfrage des Clients beginnt; ein Client ist die IP-Adresse, von der die Anfrage die Website erreicht. Darüber hinaus lautet die Antwort 429, mit Retry-After. Jede solche Anfrage, die die Website erreicht, zählt, auch eine, die aus dem Speicher des Servers beantwortet wird; eine Anfrage, die keinen Pool nennt, zählt nicht.

Aus einem Browser zählt eine Karte oder ein fetch gegen den Leser, der sie lädt, nicht gegen die Website, auf der sie steht — eine Seite mit mehr als 10 Karten bekommt die darüber hinaus also für jeden Leser abgelehnt. Von einem Server aus teilen sich alle Ihre Anfragen das eine Kontingent dieses Servers: Bewahren Sie jede Antwort die 300 Sekunden auf, die sie erlaubt — das kostet wenig, denn den größten Teil dieser Zeit würde der Server ohnehin mit der Lesung antworten, die Sie schon haben. Das Limit hält die Kosten für das Lesen von Pools niedrig, und nichts hier verspricht, dass es so bleibt.

Beispiele

Die Zahlen, aus einem Terminal:
curl -s "https://liquiditywise.com/api/embed/pool?address=0x8ad599c3a0ff1de082011efddc58f1908eb6e6d8"
Aus dem eigenen Skript einer Seite oder von einem Server, mit jeder Antwort behandelt:
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"
}
Die Karte, auf einer Seite:
<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>

Ein Klick markiert einen ganzen Block, bereit zum Kopieren.

Bedingungen, in einfachen Worten

Die Zahlen sind Messungen, keine Beratung. Der Bereich wird daraus berechnet, wie weit sich der Preis des Pools in den letzten 30 Tagen bewegt hat: Er ist keine Prognose und keine Empfehlung, und jede Antwort sagt das selbst, die Karte auf ihrer Vorderseite, das JSON in disclaimer. Wie jede Zahl entsteht und was sie auslässt, steht unter „So funktioniert es“.

Die Karte trägt ihren eigenen Link zurück, „Analysiert von LiquidityWise“. Das JSON hat kein Feld für eine Namensnennung, und nichts im Code verlangt eine; was es trägt, sind poolUrl, die Seite des Pools hier, und disclaimer. Neben den Zahlen gezeigt, sagen diese beiden einem Leser, woher die Zahlen kommen und was sie sind.

Es gibt keine Versionsnummer und keinen Schlüssel, und kein Versprechen, dass die Form der Antwort so bleibt oder dass die Website zu einem bestimmten Zeitpunkt erreichbar ist. Was gilt, ist enger: Eine Antwort wird vor dem Senden gegen ihr Schema geprüft, und Tests halten diese Seite an dieses Schema und an den Code, der die Adresse liest — sie beschreibt also, was jetzt ausgeliefert wird. Eine Änderung an einem von beiden zeigt sich in der öffentlichen Geschichte des Codes.

Der Code ist Open Source, unter der MIT-Lizenz.

So funktioniert esDer Code, auf GitHubDie MIT-Lizenz