استخدام WebSockets
هذا دليل تمهيدي لاستخدام WebSockets لإجراء طلبات إلى سلسلة كتل إيثيريوم. تستخدم الأمثلة طرق JSON-RPC القياسية، لذا فهي تعمل مع أي عقدة أو مزود عقدة يوفر نقطة نهاية WebSocket، بما في ذلك Alchemy.
(يفتح في علامة تبويب جديدة)WebSockets مقابل HTTP
على عكس HTTP، مع WebSockets، لا تحتاج إلى إجراء طلبات باستمرار عندما تريد معلومات محددة. تحافظ WebSockets على اتصال شبكة لك (إذا تم إجراؤه بشكل صحيح) وتستمع إلى التغييرات.
كما هو الحال مع أي اتصال شبكة، يجب ألا تفترض أن WebSocket سيظل مفتوحًا إلى الأبد دون انقطاع، ولكن التعامل الصحيح مع الاتصالات المقطوعة وإعادة الاتصال يدويًا قد يكون من الصعب إجراؤه بشكل صحيح. الجانب السلبي الآخر لـ WebSockets هو أنك لا تحصل على رموز حالة HTTP في الاستجابة، بل تحصل فقط على رسالة الخطأ.
يمكن لمكتبات العميل التعامل مع هذا نيابة عنك. على سبيل المثال، يقوم نقل WebSocket الخاص بـ Viem (يفتح في علامة تبويب جديدة) بإعادة الاتصال عند فشل المقبس ويرسل إشارات البقاء على قيد الحياة افتراضيًا.
جربها
تحتاج إلى عنوان URL لـ WebSocket لعقدة إيثيريوم. يمنحك مزودو العقدة واحدًا عند إنشاء مفتاح واجهة برمجة التطبيقات (API)، عادةً في شكل wss://<provider-host>/<your-api-key>. على سبيل المثال، يبدو عنوان URL لشبكة إيثيريوم الرئيسية من Alchemy مثل wss://eth-mainnet.g.alchemy.com/v2/<your-api-key> (قم بالتسجيل للحصول على حساب Alchemy مجاني (يفتح في علامة تبويب جديدة)). راجع العقد كخدمة لمزودين آخرين، أو استخدم نقطة نهاية WebSocket الخاصة بـ عقدتك الخاصة. تعمل نقاط النهاية العامة مثل wss://ethereum-rpc.publicnode.com أيضًا للتجارب السريعة، ولكنها محدودة المعدل وقد لا تدعم كل نوع اشتراك.
أسهل طريقة لاختبار WebSockets هي تثبيت أداة سطر أوامر لإجراء طلبات WebSocket مثل wscat (يفتح في علامة تبويب جديدة). باستخدام wscat، يمكنك إرسال الطلبات على النحو التالي:
npx wscat -c wss://<provider-host>/<your-api-key>
> {"jsonrpc": "2.0", "id": 0, "method": "eth_gasPrice"}
< {"jsonrpc": "2.0", "result": "0x41f9de2", "id": 0}
الأسطر التي تبدأ بـ > هي ما تكتبه، والأسطر التي تبدأ بـ < هي ما ترسله العقدة مرة أخرى.
كيفية استخدام WebSockets
للبدء، افتح WebSocket باستخدام عنوان URL لـ WebSocket الخاص بمزودك. مع Alchemy، يمكنك العثور عليه عن طريق فتح تطبيقك في لوحة المعلومات (يفتح في علامة تبويب جديدة) وعرض مفتاح واجهة برمجة التطبيقات (API) الخاص به. لاحظ أن عنوان URL لـ WebSockets (wss://) يختلف عن عنوان URL لطلبات HTTP (https://)، على الرغم من أن معظم المزودين يستخدمون نفس مفتاح واجهة برمجة التطبيقات (API) لكليهما.
يمكن استخدام أي من طرق JSON-RPC التي يدعمها مزودك عبر WebSocket. للقيام بذلك، استخدم نفس الحمولة التي سيتم إرسالها كجسم لطلب HTTP POST، ولكن بدلاً من ذلك أرسل تلك الحمولة من خلال WebSocket.
مع Web3
الانتقال إلى WebSockets أثناء استخدام مكتبة عميل مثل Viem (يفتح في علامة تبويب جديدة) أمر بسيط. استخدم نقل webSocket مع عنوان URL لـ WebSocket الخاص بك بدلاً من نقل http. على سبيل المثال، بعد npm install viem، احفظ هذا كـ index.mjs وقم بتشغيل node index.mjs:
import { createPublicClient, webSocket } from "viem"
import { mainnet } from "viem/chains"
const client = createPublicClient({
chain: mainnet,
transport: webSocket("wss://<provider-host>/<your-api-key>"),
})
console.log(await client.getBlockNumber()) // -> 26243602n
// الاشتراك في كتل جديدة عبر نفس WebSocket
const unwatch = client.watchBlocks({
onBlock: (block) => {
console.log(block.number, block.hash)
unwatch()
process.exit(0)
},
})
API الاشتراك
عند الاتصال من خلال WebSocket، يمكنك استخدام طريقتين إضافيتين: eth_subscribe وeth_unsubscribe. ستسمح لك هذه الطرق بالاستماع إلى أحداث معينة وإعلامك على الفور.
eth_subscribe
ينشئ اشتراكًا جديدًا لأحداث محددة. تعرف على المزيد حول eth_subscribe (يفتح في علامة تبويب جديدة).
المعلمات
- أنواع الاشتراك
- معلمات اختيارية
تحدد الوسيطة الأولى نوع الحدث الذي يجب الاستماع إليه. تحتوي الوسيطة الثانية على خيارات إضافية تعتمد على الوسيطة الأولى. يتم وصف أنواع الوصف المختلفة وخياراتها وحمولات أحداثها أدناه.
المخرجات
معرف الاشتراك: سيتم إرفاق هذا المعرف بأي أحداث مستلمة، ويمكن استخدامه أيضًا لإلغاء الاشتراك باستخدام eth_unsubscribe.
أحداث الاشتراك
أثناء تنشيط الاشتراك، ستتلقى أحداثًا عبارة عن كائنات تحتوي على الحقول التالية:
jsonrpc: دائمًا "2.0"method: دائمًا "eth_subscription"params: كائن يحتوي على الحقول التالية:subscription: معرف الاشتراك الذي تم إرجاعه بواسطة استدعاءeth_subscribeالذي أنشأ هذا الاشتراك.result: كائن تختلف محتوياته بناءً على نوع الاشتراك.
أنواع الاشتراك
newHeads
يصدر حدثًا في أي وقت تتم فيه إضافة ترويسة جديدة إلى السلسلة، بما في ذلك أثناء إعادة تنظيم السلسلة.
عند حدوث إعادة تنظيم للسلسلة، سيصدر هذا الاشتراك حدثًا يحتوي على جميع الترويسات الجديدة للسلسلة الجديدة. على وجه الخصوص، هذا يعني أنك قد ترى ترويسات متعددة صادرة بنفس الارتفاع، وعندما يحدث هذا، يجب اعتبار الترويسة اللاحقة هي الترويسة الصحيحة بعد إعادة التنظيم.
مثال:
> {"jsonrpc": "2.0", "id": 1, "method": "eth_subscribe", "params": ["newHeads"]}
< {"jsonrpc":"2.0","result":"0xe0d4abf5caf333fbf94c5f02182e6469","id":1}
< {
"jsonrpc": "2.0",
"method": "eth_subscription",
"params": {
"result": {
"baseFeePerGas": "0x41f9de2",
"blobGasUsed": "0xc0000",
"difficulty": "0x0",
"excessBlobGas": "0xa88af38",
"extraData": "0xe29ca82051756173617220287175617361722e77696e2920e29ca8",
"gasLimit": "0x3938700",
"gasUsed": "0x1a17224",
"hash": "0xedc43a71b7ff13880bdbe7b748a225b91a11a91e79173fe28011363c10acaea5",
"logsBloom": "0x4beaef4e7dbb1bfdb3df673fab6cdf1cf9fc0e7f743d672c761551767b7dad953d79cf86e56e6195ae1b57dff20a0fd46e57c545af166ff49394df3839e269a6ff877b6baf9d899fd9666c58b7dfa7add4febf78b466e7f71af2dcbad53fdcfa3f7277d2fbfffcff953f9ef37b3af8fffb296a3adb94dc463ff0d6d5173f1beda0fd662d77eaedb34ff99f3eeed38a77e7d0cd63e917d4efbdfcb7d0d19437f98ff60773d0effbfbdfdbef9ebbf6a2c35efedd677a795d3ccd777e127eeb657f6a8dffaf64f3b8d998b516c78e661ef77fded57fb66d687fab17739b3ef5aa2765777d8cce0ef59a9ceebeceabbb7f76ed7fc65df7e8bccf7938eb3fb7de57f7",
"miner": "0x396343362be2a4da1ce0c1c210945346fb82aa49",
"mixHash": "0xa72c9201f502df607d0d7551ccc171ce37a5146747f04c6c495b0aebecb045c7",
"nonce": "0x0000000000000000",
"number": "0x1907212",
"parentBeaconBlockRoot": "0x34f3f289459913dd80ec9c20aa535866cd2bd310ac26e47570601e263d593735",
"parentHash": "0xe62c150ffbbd04e95343f945b70fa53756aba6c0bf96c0440d1ae354fa007a7c",
"receiptsRoot": "0x94951d882544da76e30b145b26a39b126e8acfba9db929351b84b2f4c847e3ed",
"requestsHash": "0xe3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
"size": "0x1f4bc",
"stateRoot": "0x12771ea73858277034cf6604aee0abbf889c15091ab8ef9be81bf7258458a036",
"timestamp": "0x6ad92b47",
"transactionsRoot": "0xbd58ebe5c8c5519e458266a7db3ad049a7bffa106dc9a14f2fe6edb3f8ad5d70",
"withdrawalsRoot": "0x56a083b6140663c9e98c30167ee90a1ffb157505ba89cb584583b71cba100d2a"
},
"subscription": "0xe0d4abf5caf333fbf94c5f02182e6469"
}
}
logs
يصدر السجلات التي تعد جزءًا من الكتل المضافة حديثًا والتي تتطابق مع معايير التصفية المحددة.
عند حدوث إعادة تنظيم للسلسلة، سيتم إصدار السجلات التي تعد جزءًا من الكتل الموجودة على السلسلة القديمة مرة أخرى مع تعيين الخاصية removed إلى true. علاوة على ذلك، يتم إصدار السجلات التي تعد جزءًا من الكتل الموجودة على السلسلة الجديدة، مما يعني أنه من الممكن رؤية سجلات لنفس المعاملة عدة مرات في حالة إعادة التنظيم.
المعلمات
- كائن يحتوي على الحقول التالية:
address(اختياري): إما سلسلة نصية تمثل عنوانًا أو مصفوفة من هذه السلاسل النصية.- سيتم إصدار السجلات التي تم إنشاؤها من أحد هذه العناوين فقط.
topics: مصفوفة من محددات المواضيع.- كل محدد موضوع هو إما
null، أو سلسلة نصية تمثل موضوعًا، أو مصفوفة من السلاسل النصية. - كل موضع في المصفوفة ليس
nullيقيد السجلات الصادرة بتلك التي تحتوي على أحد المواضيع المحددة في ذلك الموضع فقط.
- كل محدد موضوع هو إما
بعض الأمثلة على مواصفات المواضيع:
[]: يُسمح بأي مواضيع.[A]: A في الموضع الأول (وأي شيء بعده).[null, B]: أي شيء في الموضع الأول و B في الموضع الثاني (وأي شيء بعده).[A, B]: A في الموضع الأول و B في الموضع الثاني (وأي شيء بعده).[[A, B], [A, B]]: (A أو B) في الموضع الأول و (A أو B) في الموضع الثاني (وأي شيء بعده).
مثال:
يستمع هذا المثال إلى أحداث Deposit من عقد إيثر مغلف (WETH) (يفتح في علامة تبويب جديدة) على شبكة إيثيريوم الرئيسية:
> {"jsonrpc": "2.0", "id": 1, "method": "eth_subscribe", "params": ["logs", {"address": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", "topics": ["0xe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c"]}]}
< {"jsonrpc":"2.0","result":"0x69a0e61ae8e3d61a93479858e8f1b43a","id":1}
< {
"jsonrpc": "2.0",
"method": "eth_subscription",
"params": {
"result": {
"address": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
"blockHash": "0x168e06e5733df993078bb635cb9925f80ff39d12a36bd301052c44d7bf6b6068",
"blockNumber": "0x190720e",
"blockTimestamp": "0x6ad92b17",
"data": "0x000000000000000000000000000000000000000000000000039ed0c3d7848a1c",
"logIndex": "0x11",
"removed": false,
"topics": [
"0xe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c",
"0x00000000000000000000000023617e59a5925b2a4bf75d73ff6711cd0b29de85"
],
"transactionHash": "0xc956e7012c2af8ff87db88e059336842ee872bfc93de1eac9760510d0bd801be",
"transactionIndex": "0xb"
},
"subscription": "0x69a0e61ae8e3d61a93479858e8f1b43a"
}
}
newPendingTransactions
يصدر تجزئة كل معاملة تتم إضافتها إلى الحالة المعلقة للعقدة (مجمع الذاكرة الخاص بها).
مثال:
> {"jsonrpc": "2.0", "id": 1, "method": "eth_subscribe", "params": ["newPendingTransactions"]}
< {"jsonrpc":"2.0","result":"0x1c2365b029179adf1e84b9e327315249","id":1}
< {"jsonrpc":"2.0","method":"eth_subscription","params":{"result":"0x4a62d0ad7c8868fbbfa10604e68638e637c6fc6f64fd1fb4ca042dcd0158c992","subscription":"0x1c2365b029179adf1e84b9e327315249"}}
يقدم بعض المزودين أيضًا أنواع اشتراك خاصة بهم. على سبيل المثال، يصدر alchemy_pendingTransactions (يفتح في علامة تبويب جديدة) الخاص بـ Alchemy كائنات معاملة كاملة بدلاً من مجرد تجزئات، ويقبل عوامل تصفية fromAddress وtoAddress وhashesOnly الاختيارية. هذه ليست جزءًا من واجهة برمجة التطبيقات (API) القياسية لـ JSON-RPC، لذا فهي تعمل فقط مع ذلك المزود.
eth_unsubscribe
يلغي اشتراكًا حاليًا بحيث لا يتم إرسال أي أحداث أخرى.
المعلمات
- معرف الاشتراك، كما تم إرجاعه مسبقًا من استدعاء
eth_subscribe.
المخرجات
true إذا تم إلغاء الاشتراك بنجاح، أو false إذا لم يكن هناك اشتراك بالمعرف المحدد.
يوجد الاشتراك فقط على اتصال WebSocket الذي أنشأه، لذا يجب إرسال eth_unsubscribe عبر نفس الاتصال. لا يمكن إرساله كطلب HTTP منفصل. يؤدي إغلاق الاتصال أيضًا إلى إلغاء جميع اشتراكاته.
مثال:
> {"jsonrpc": "2.0", "id": 2, "method": "eth_unsubscribe", "params": ["0xe0d4abf5caf333fbf94c5f02182e6469"]}
< {"jsonrpc":"2.0","result":true,"id":2}
سجل مع Alchemy (يفتح في علامة تبويب جديدة) مجانًا، وتحقق من وثائق Alchemy (يفتح في علامة تبويب جديدة)، وللحصول على أحدث الأخبار، تابع Alchemy على تويتر (يفتح في علامة تبويب جديدة).