بطاقة التجمّع وJSON الخاص بها
في هذا الموقع شيئان معدّان لمواقع أخرى: بطاقة تعرض النطاق المقترح لتجمّع واحد، يجوز لأي صفحة أن تضعها في إطار، والأرقام نفسها بصيغة JSON، يجوز لشيفرة أي موقع أن تقرأها. لا يحتاج أيّ منهما إلى مفتاح أو حساب. كلاهما موصوف هنا كما تقدّمه الشيفرة، وتُلزم الاختباراتُ هذه الصفحةَ بتلك الشيفرة: كل مُعامِل تذكره هو مُعامِل يُقرأ به العنوان فعلًا، وكل حقل هو حقل تُطابَق عليه الإجابة قبل إرسالها.
البطاقة
/embed/pool صفحة صغيرة مكتوبة يدويًا، لا بإطار عمل الموقع. تعرض الزوج مع بروتوكوله ورسومه وشبكته؛ والنطاق المقترح مع الأفق والاتساع اللذين رُسم لهما؛ والسعر الحالي؛ وسطرًا يقول إنها ليست نصيحة مالية؛ ورابطًا يعود إلى صفحة التجمّع هنا، يفتح في علامة تبويب جديدة. يُرسم النطاق دائمًا بالقيم الافتراضية للموقع، 30 يومًا عند 1σ، أيًّا كانت إعدادات أي شخص. وتُضاف ملاحظة ما دام السعر الحالي خارج النطاق، وأخرى لتجمّع v4 قد يغيّر خطّافه تكلفة التبادل.
لا تحتوي على أي برنامج نصي ولا استمارة، ولا تحمّل شيئًا: سياسة Content-Security-Policy الخاصة بها لا تسمح بشيء سوى أسلوبها المضمّن. ألوانها ألوان الموقع، فاتحة أو داكنة بحسب إعداد نظام القارئ. لا ترى الصفحة المحيطة بها، ولا يوجد مُعامِل لاختيار ذلك.
أعطها إطارًا بعرض 360 بكسل وارتفاع 220، أو بارتفاع 260 لتجمّع قد يغيّر خطّافه تكلفة التبادل، إذ تحمل بطاقته سطرًا إضافيًا. هذا بالضبط ما تعرضه صفحة كل تجمّع تحت «تضمين هذا التجمّع»، بالارتفاع المناسب لذلك التجمّع مسبقًا، ولا يصبح الإطار المعروض أعرض من العمود الذي يُلصق فيه أبدًا.
إنها الصفحة الوحيدة في هذا الموقع التي يجوز لموقع آخر أن يضعها في إطار. كل عنوان آخر، ومنه هذا العنوان، يُرسل مع X-Frame-Options: DENY وframe-ancestors 'none'؛ أما البطاقة فتُرسل من دون الأول ومع 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 *المُعامِلات
تأخذ البطاقة وJSON المُعامِلات نفسها، وتسمّيان التجمّع كما تسمّيه صفحات الموقع نفسه: تجمّع v3 بعنوانه address كما في /pool، وتجمّع v4 بمعرّفه id كما في /v4. يلزم واحد منهما بالضبط، وأيّهما وصل يحدّد البروتوكول. التجمّع أو الشبكة المذكوران مرتين يُرفضان بدل أن تُختار إحدى القيمتين، وأي مُعامِل غير مذكور هنا يُتجاهَل.
تأتي اللغة من العنوان وحده، لا من متصفح القارئ ولا من ملف تعريف ارتباط أبدًا: الموقع الذي يضع البطاقة هو من يختارها، والعنوان نفسه هو الإجابة نفسها لكل من يحمّله، وهذا ما يتيح للتخزين المؤقت الاحتفاظ بها. البطاقة مكتوبة بلغات الموقع الـ10 كلها، وبالعربية تُقرأ من اليمين إلى اليسار.
address- يقبل عنوان عقد تجمّع v3:
0xثم 40 رقمًا ست عشريًا، بأحرف كبيرة أو صغيرة. - وإلا أي شيء آخر لا يسمّي تجمّعًا، وكذلك تجمّع v3 على شبكة لا يُقرأ فيها v3 (Unichain):
400، ولا يُقرأ شيء. id- يقبل معرّف تجمّع v4، أي تجزئة مفتاحه:
0xثم 64 رقمًا ست عشريًا، بأحرف كبيرة أو صغيرة. - وإلا أي شيء آخر لا يسمّي تجمّعًا:
400، ولا يُقرأ شيء. وكذلكidإلى جانبaddress. chain- يقبل الاسم المختصر لشبكة من الجدول أدناه. إن غاب، فالشبكة هي Ethereum.
- وإلا الاسم الذي لا يقرأ الموقع شبكته يُرفض، ولا يُقرأ على أنه Ethereum أبدًا:
400. lang- يقبل رمز لغة من القائمة أدناه، لكلمات البطاقة ولحقل
disclaimerفي JSON؛ والأرقام واحدة في كل اللغات. إن غاب، فالإنجليزية. - وإلا أي قيمة أخرى، أو
langمذكورًا مرتين، يعطي الإنجليزية. لا يُرفض أبدًا.
الشبكات، بالاسم المختصر الذي يأخذه chain:
chain | الشبكة | تجمّعات v3 | تجمّعات v4 |
|---|---|---|---|
ethereum | Ethereum | تُقرأ | تُقرأ |
base | Base | تُقرأ | تُقرأ |
arbitrum | Arbitrum One | تُقرأ | تُقرأ |
unichain | Unichain | لا تُقرأ | تُقرأ |
optimism | OP Mainnet | تُقرأ | تُقرأ |
polygon | Polygon | تُقرأ | تُقرأ |
اللغات، بالرمز الذي يأخذه lang:
enEnglishtrTürkçedeDeutschesEspañolarالعربيةhiहिन्दीzh中文ruРусскийptPortuguêszh-Hant繁體中文
صيغة JSON
يجيب GET /api/embed/pool، بالمُعامِلات نفسها، بأرقام البطاقة بصيغة JSON، لموقع يفضّل أن يرسمها بنفسه: القراءة نفسها، محفوظة المدة نفسها. كل رقم فيها رقم JSON، وكل سعر مكتوب بالاتجاه الذي تكتبه به صفحة التجمّع: كم price.quote يساوي price.base واحد.
قبل إرسال الإجابة تُطابَق على مخططها، والإجابة التي لا تطابقه لا تُرسل: يُجاب عن التجمّع بدلًا من ذلك بأنه تعذّرت قراءته. لذلك تحمل الإجابة ذات الحالة 200 دائمًا الحقول أدناه بالضبط، لا أكثر ولا أقل.
يجوز لبرنامج أي موقع أن يقرأها. كل إجابة، ومنها الأخطاء والرفض، تُرسل مع Access-Control-Allow-Origin: *. لا تضع ملف تعريف ارتباط ولا تحتاج إلى بيانات اعتماد. طلب GET بسيط لا يحتاج إلى فحص مسبق (preflight)، ولا يُجاب عن أي فحص مسبق، فأرسله من دون ترويسات خاصة بك.
Content-Type: application/json; charset=utf-8
Cache-Control: public, max-age=300, s-maxage=300
Access-Control-Allow-Origin: *كل حقل في إجابة 200، مع نوعه في JSON:
protocol"v3" | "v4"v3لتجمّع سُمّي بـaddress، وv4لتجمّع سُمّي بـid.chain.idinteger > 0- معرّف السلسلة (chain id) للشبكة.
chain.slugstring- الاسم المختصر للشبكة، كما يأخذه
chain. chain.namestring- اسم الشبكة.
poolstring- عنوان التجمّع (v3) أو معرّفه (v4)، بأحرف صغيرة.
pair.token0string- اسم الرمز الأول في التجمّع كما يعلنه عقده: نصٌّ من عقد يستطيع أي أحد نشره، فاحرص على تهريبه (escape) قبل أن تضعه في صفحة.
pair.token1string- اسم الرمز الثاني، بالطريقة نفسها.
lpFeePpminteger ≥ 0 | null- الرسوم التي يدفعها التجمّع لمزوّدي السيولة عن كل تبادل، بأجزاء من المليون:
3000تعني 0.3%. وتكونnullحين يحدّد خطّاف تجمّع v4 الرسوم تبادلًا بتبادل. price.basestring- الرمز الذي يُعطى كل سعر لوحدة واحدة منه.
price.quotestring- الرمز الذي يُحسب به كل سعر.
price.currentnumber > 0- سعر التجمّع لحظة قراءته.
range.lowernumber > 0- الحد الأدنى للنطاق المقترح، كسعر.
range.uppernumber > 0- حدّه الأعلى.
range.currentInRangeboolean- هل السعر الحالي داخل النطاق. إن لم يكن، تضيف البطاقة ملاحظة.
range.lowerTruncatedbooleantrueحين لا تبلغ شبكة الـ tick في التجمّع الحدَّ الأدنى للحزمة، فيتوقف النطاق قبله.range.upperTruncatedboolean- الشيء نفسه، للحد الأعلى.
parameters.horizonDaysinteger > 0- الأفق الذي رُسم له النطاق، بالأيام: دائمًا القيمة الافتراضية، 30.
parameters.standardDeviationMultipliernumber > 0- الاتساع الذي رُسم له، بالانحرافات المعيارية: دائمًا القيمة الافتراضية، 1σ.
hookMayAlterSwapsbooleantrueلتجمّع v4 قد يغيّر خطّافه تكلفة التبادل، مقروءًا من عنوان الخطّاف؛ وfalseلـ v3، ولتجمّع v4 بلا خطّاف، ولخطّاف لا تمسّ أذوناته التبادل. وحيث تكونtrueتحمل البطاقة ملاحظة.analysedAtstring (ISO 8601)- متى قُرئ السعر، بتوقيت UTC وحتى الجزء من الألف من الثانية — لا متى أُرسلت هذه الإجابة، وقد يكون ذلك بعد دقائق.
poolUrlstring- صفحة التجمّع على هذا الموقع، بالأفق والاتساع نفسيهما.
disclaimerstring- ما هي الأرقام وما ليست هي، باللغة التي يحدّدها
lang.
{
"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."
}رموز الحالة والأخطاء
تجيب البطاقة وJSON برموز الحالة نفسها. ولا يجيب أيّ منهما أبدًا بصفحة الخطأ الخاصة بالموقع أو بما تعطّل في الداخل: تعرض البطاقة جملة واحدة ورابطها للعودة، ويجيب JSON بحقل error يستطيع البرنامج فحصه، ومعه disclaimer — عدا الرفض، الذي يحمل مدة الانتظار بدلًا منه.
إجابة JSON، ومدة جواز الاحتفاظ بها:
200
الأرقام: بطاقة تحملها، أو JSON الموصوف أعلاه.
Cache-Control: public, max-age=300, s-maxage=300400 not-a-pool
العنوان لا يسمّي تجمّعًا يقرؤه الموقع: لا address ولا id، أو كلاهما، أو أحدهما مشوّه أو مكرّر، أو شبكة لا يقرؤها الموقع، أو تجمّع v3 حيث لا يُقرأ إلا v4 (Unichain). لم يُقرأ شيء، وإعادة السؤال لن تغيّر الإجابة.
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
تجمّع سُمّي تسمية صحيحة وتعذّرت قراءته الآن: مصدرٌ لم يُجب في الوقت المحدد، أو لا يوجد تجمّع كهذا على تلك الشبكة. يبقى poolUrl موصلًا إلى صفحته. وقد تجده إعادة السؤال بعد دقيقة.
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
طلبات كثيرة جدًا من عميل واحد: انظر حدّ الطلبات أدناه. يقول كلٌّ من Retry-After وretryAfterSeconds كم ثانية يجب الانتظار. وتجيب البطاقة بصفحة قصيرة تقول ذلك، بلغتها.
Cache-Control: no-store
Retry-After: 42
{
"error": "rate-limited",
"retryAfterSeconds": 42
}التخزين المؤقت وحدّ الطلبات
تقول كل إجابة كم يجوز الاحتفاظ بها، للمتصفح وللتخزين المؤقت المشترك على السواء: 300 ثانية للأرقام؛ و60 ثانية لتجمّع تعذّرت قراءته، كي لا يظهر تجمّع عاد للعمل متعذّرًا طويلًا؛ و3,600 ثانية لعنوان لا يسمّي تجمّعًا، فلن تغيّر ذلك أي لحظة لاحقة. أما الرفض فلا يُحتفظ به أبدًا. وكل إجابة واحدة لكل من يسأل بالعنوان نفسه، وهذا ما يجعل الاحتفاظ بها آمنًا.
ووراء ذلك يحتفظ الخادم بأرقام كل تجمّع 300 ثانية من لحظة قراءتها، للبطاقة ولـ JSON على السواء وبكل اللغات: كل بطاقة لتجمّع واحد، في كل صفحة توضع فيها، هي قراءة واحدة حتى تنتهي مدتها. والتجمّع الذي تعذّرت قراءته لا يُحتفظ به، ويُسأل عنه من جديد في الطلب التالي. لذلك قد يكون السعر في الإجابة أقدم من الإجابة نفسها: يقول analysedAt متى قُرئ.
الطلب الذي يسمّي تجمّعًا صحيح الصيغة يقرأ ذلك التجمّع، ولذلك يُحسب من الحصة نفسها التي تُحسب منها صفحات التجمّعات في الموقع: 10 طلبات لكل عميل في نافذة مدتها 60 ثانية تبدأ مع أول طلب للعميل، والعميل هو عنوان IP الذي يصل منه الطلب إلى الموقع. وبعد تجاوز الحد تكون الإجابة 429 مع Retry-After. ويُحسب كل طلب كهذا يصل إلى الموقع، ومنه ما يُجاب عنه مما يحتفظ به الخادم؛ أما الطلب الذي لا يسمّي تجمّعًا فلا يُحسب.
من المتصفح، تُحسب البطاقة أو fetch على القارئ الذي يحمّلها، لا على الموقع الذي توضع فيه — فالصفحة التي تضع أكثر من 10 بطاقات تُرفض فيها البطاقات الزائدة لكل قارئ. ومن الخادم، تتقاسم كل طلباتك حصة ذلك الخادم الواحدة: احتفظ بكل إجابة طوال الـ300 ثانية التي تسمح بها، وهذا لا يكلّف كثيرًا، لأن الخادم كان سيجيب في معظم تلك المدة بالقراءة التي لديك أصلًا. وُضع الحد لإبقاء كلفة قراءة التجمّعات منخفضة، ولا شيء هنا يَعِد بأنه سيبقى كما هو.
أمثلة
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>نقرة واحدة تحدّد الكتلة كلها، جاهزة للنسخ.
الشروط بكلمات بسيطة
الأرقام قياسات، لا نصيحة. يُحسب النطاق من مقدار تحرّك سعر التجمّع خلال آخر 30 يومًا: ليس تنبؤًا وليس توصية، وكل إجابة تقول ذلك بنفسها، البطاقة على واجهتها وJSON في disclaimer. وكيف يُحسب كل رقم وما الذي يتركه خارجه، تجده في صفحة «كيف يعمل».
تحمل البطاقة رابطها الخاص للعودة، «تحليل LiquidityWise». أما JSON فليس فيه حقل لنسبة المصدر، ولا شيء في الشيفرة يطلب ذلك؛ ما يحمله هو poolUrl، صفحة التجمّع هنا، وdisclaimer. وإذا عُرض هذان بجانب الأرقام، أخبرا القارئ من أين جاءت وما هي.
لا يوجد رقم إصدار ولا مفتاح، ولا وعد بأن يبقى شكل الإجابة كما هو أو بأن يكون الموقع متاحًا في أي لحظة. ما يصحّ أضيق من ذلك: تُطابَق الإجابة على مخططها قبل إرسالها، وتُلزم الاختبارات هذه الصفحة بذلك المخطط وبالشيفرة التي تقرأ العنوان، فهي تصف ما يُقدَّم الآن. وأي تغيير في أيٍّ منهما يظهر في التاريخ العلني للشيفرة.
الشيفرة مفتوحة المصدر، بموجب رخصة MIT.