Skip to main content
هذه الصفحة مُترجَمة آليًا بواسطة الذكاء الاصطناعي. النسخة الإنجليزية هي المرجع المعتمد.عرض النسخة الإنجليزية →
تصف هذه الصفحة التخطيط والدور لكل حساب. البذور (Seeds) موثقة بشكل قانوني في reference/program-addresses. مجمع CLMM يتطلب حسابات أكثر من مجمع CPMM لأن السيولة مخزنة بشكل متفرق عبر نطاق التكات؛ فهم هذا التفرق هو الجزء الأساسي من هذه الصفحة.

جرد الحسابات

يتم وصف مجمع CLMM النشط بعائلات الحسابات التالية. جميعها مملوكة لبرنامج CLMM باستثناء النقودتين (Mints) وخزائنهما.

PoolState

الحالة الحية للمجمع، تُقرأ في كل مبادلة وكل تغيير موضع.
الحقول التي ستلمسها فعليًا:
  • sqrt_price_x64 و tick_current هما حالة سعر المجمع. يتم تحديثهما معًا في كل مبادلة. tick_current هو الحد الأدنى لـ log_{1.0001}(price).
  • liquidity هي السيولة النشطة — مجموع قيم L لجميع المراكز التي يحتوي نطاقها على tick_current. تتغير في كل مرة تعبر مبادلة تك وفي كل مرة يتم فتح/إغلاق/تغيير حجم مركز.
  • fee_growth_global_{0,1}_x64 هي الرسوم المتراكمة المكتسبة لكل وحدة سيولة عبر تاريخ المجمع بالكامل. تقرأ المراكز هذا لحساب ما يُستحق لهم.
  • tick_spacing مقفل على AmmConfig عند التهيئة ولا يتغير أبدًا. يحدد أي مؤشرات تك يُسمح بها فقط أن تكون نقاط نهاية المركز.
  • tick_array_bitmap هي خريطة بت مضمنة تغطي نطاق التكات المستخدم بشكل شائع حول سعر الفائدة. بالنسبة للمجمعات التي تصل مراكزها بعيدًا، يعيش تتبع الفائض في TickArrayBitmapExtension المنفصل.
  • fee_on ثابت عند إنشاء المجمع. 0 (FromInput) يعيد إنتاج السلوك الكلاسيكي لـ Uniswap-V3. 1 و 2 يوجهان رسوم المبادلة إلى جانب واحد من الكتاب — انظر products/clmm/fees للمقارنات.
  • seed_index هو [0, 0] لكل مجمع تم إنشاؤه من خلال CreatePool / CreateCustomizablePool (مجمع قانوني واحد لكل زوج). قيمة غير صفرية تعني أن المجمع تم إنشاؤه عبر CreateCustomizablePoolV2 (سُمي CreatePermissionedPool قبل 2026-10-22) والفهرس جزء من بذور PDA للمجمع، مما يسمح بعدة مجمعات للتعايش لنفس (config, mint0, mint1). لإعادة اشتقاق عنوان مثل هذا المجمع يجب أن تعرف seed_index الخاص به.
  • dynamic_fee_info يحمل حالة التقلب لرسوم الرسوم الديناميكية. عند التفعيل، تعيد كل مبادلة حساب dynamic_fee_component فوق AmmConfig.trade_fee_rate. التخطيط موثق تحت DynamicFeeInfo أدناه؛ المجمعات بدون رسوم ديناميكية تترك البنية بأكملها صفرية.

AmmConfig

منذ ترقية 2026-09، يكتب CreateAmmConfig معرّف protocol_fee_owner::ID المشفر في البرنامج إلى owner و fund_fee_owner::ID إلى fund_owner. قبل ذلك، كان ينسخ مفتاح موقّع المسؤول إلى كليهما. تحتفظ التكوينات الموجودة بأي شيء تم إنشاؤها أو تدويره إليه، لذا اقرأ كلا الحقلين من الحساب. معاملات UpdateAmmConfig 3 / 4 لا تزال تدويرهما. العناوين موجودة في reference/program-addresses. مجموعة نموذجية منشورة من فئات رسوم CLMM (تأكد مقابل GET https://api-v3.raydium.io/main/clmm-config): protocol_fee_rate و fund_fee_rate هما كسور من رسوم التداول؛ نفس الاتفاقية مثل CPMM. انظر products/clmm/fees.

TickArrayState

لا يخزّن CLMM سجلاً واحداً لكل tick. هذا سيتطلب مليارات الحسابات. بدلاً من ذلك، يجمّع TICK_ARRAY_SIZE من ticks المجاورة المهيأة أو غير المهيأة (عادة 60 أو 88 حسب إصدار البرنامج) في TickArrayState يتم إنشاؤه بكسل عند الاستخدام الأول.
الحقول الأربعة لأوامر الحد تكون صفراً على أي tick لم يُستخدم قط لأمر حد. عندما تُفتح أوامر على tick، يتتبع البرنامج سلسلة من المجموعات:
  • order_phase هو معرّف المجموعة. يزداد في كل مرة تنتقل مجموعة من “غير مملوءة بالكامل” إلى “مملوءة جزئياً”.
  • orders_amount هو إجمالي رمز الإدخال للمجموعة الحالية (الأحدث).
  • part_filled_orders_remaining يتتبع المجموعة السابقة التي يتم ملؤها حالياً بواسطة المبادلات الجارية.
  • unfilled_ratio_x64 هو مضروب Q64.64 يُحمل على المجموعة: عندما تملأ مبادلة X% من المجموعة، يُضرب النسبة في (1 − X). كل أمر مفتوح يخزّن لقطة خاصة به من (order_phase, unfilled_ratio_x64) عند وقت الفتح، لذا تقليل رياضيات التسوية إلى مقارنة اللقطات.
القواعد:
  • نقطة نهاية الموضع t يجب أن تحقق t % tick_spacing == 0. يرفض البرنامج المواضع غير المحاذاة.
  • مصفوفة الـ tick موجودة في floor(t / (TICK_ARRAY_SIZE * tick_spacing)) * (TICK_ARRAY_SIZE * tick_spacing).
  • يتم تهيئة مصفوفة tick بكسل: أول موضع أو مبادلة تلمس مصفوفة غير مهيأة تنشئها، مع دفع الإيجار.
  • مصفوفة tick لا تُغلق أبداً بواسطة البرنامج. بمجرد تخصيصها، تستمر طوال حياة المجموعة، حتى بعد عودة كل tick بداخلها إلى liquidity_gross == 0. تعيد المواضع والمبادلات اللاحقة استخدام الحساب الموجود بدون إيجار إضافي. لا توجد مسار تنظيف مدفوع بـ ClosePosition لمصفوفات tick.

TickArrayBitmapExtension

PoolState.tick_array_bitmap (مضمّن) يغطي النطاق “القريب من السعر الفوري” — ±512 مصفوفة tick (TICK_ARRAY_BITMAP_SIZE = 512؛ الحقل [u64; 16] هو 1,024 بت مقسم بالتساوي بين مؤشرات البداية السالبة والموجبة، لذا مؤشرات المصفوفة −512 … +511). خارج هذا النطاق (لقيم tick القصوى)، يحتفظ البرنامج بحساب امتداد:
إذا كان نطاق موضعك “عادياً”، فلن تفكر أبداً في حساب الامتداد. المواضع ذات النطاق الكامل (مثل (MIN_TICK, MAX_TICK)) تتطلبها؛ SDK يحلها لك.

المواضع

موضع CLMM هو حزمة من ثلاثة حسابات بالإضافة إلى mint:

موضع NFT mint

mint SPL Token أو Token-2022 بإمداد 1. موضع NFT في محفظة المالك هو ATA يحمل هذا الرمز الواحد. يربط البرنامج التفويض إلى المالك الحالي لرصيد ATA الخاص بـ NFT، وليس إلى Pubkey مخزّن في الحالة. تعيين mints موضع NFT الجديدة pool_state كسلطة تجميد قبل صك الرمز الواحد وإزالة سلطة mint. تعيين سلطة تجميد لا يجمّد حساب NFT بحد ذاته. يبقى الحساب غير مجمّد وقابل للتحويل ما لم تتحقق كلا الشرطين: يستخدم المتصل OpenPositionV2 أو OpenPositionWithToken22Nft، وتظهر سلطة تجميد mint الخزان الأساسي على الأقل على قائمة المُصدرين المقيدين في CLMM. فقط عندئذ يجمّد CLMM حساب NFT بعد الصك. هذا لا يغيّر أي بايتات PersonalPositionState أو PoolState.

PersonalPositionState

واحد لكل موضع مفتوح. مفتاح من mint NFT.

ProtocolPositionState (مُهمل)

خزّنت إصدارات CLMM الأقدم حسابات إجمالية لكل (pool, tick_lower, tick_upper) في ProtocolPositionState PDA. الإصدارات الأحدث لا تعود تنشئ أو تقرأ هذا الحساب. الفتحة لا تزال تظهر في قوائم حسابات OpenPosition / IncreaseLiquidity / DecreaseLiquidity كـ UncheckedAccount لتوافق ABI، لكن البرنامج لا يكتب إليها. الحسابات الموجودة على السلسلة هي بقايا؛ يمكن للمسؤول استدعاء CloseProtocolPosition لاسترجاع الإيجار لها.يتم اشتقاق حسابات النطاق الإجمالية الآن مباشرة من ticks النقطة النهائية (liquidity_gross، liquidity_net، و fee_growth_outside_* / reward_growths_outside_x64 لكل tick) في TickArrayState. صيغة fee-growth-inside fee_growth_inside = global − outside_lower − outside_upper تستمر في العمل بدون حساب موضع إجمالي.

الملاحظة

يخزّن مخزن مؤقت الملاحظة في CLMM tick تراكمي، وليس سعر تراكمي. يحسب المستهلكون الخارجيون السعر الهندسي المتوسط على فترة زمنية من (tick_cumulative[t1] − tick_cumulative[t0]) / (t1 − t0) ثم price = 1.0001 ** tick. انظر algorithms/clmm-math.

DynamicFeeConfig و DynamicFeeInfo

معاملات الرسوم الديناميكية تعيش في مكانين. القالب القابل لإعادة الاستخدام — DynamicFeeConfig — يُدار من قبل المسؤول ومشترك بين المجموعات التي تختار الاشتراك. حالة وقت التشغيل لكل مجموعة — DynamicFeeInfo — مضمّنة في PoolState وتُحدّث بواسطة كل مبادلة.

DynamicFeeConfig

بذرة PDA: ["dynamic_fee_config", index.to_be_bytes()]. يتم الإنشاء عبر create_dynamic_fee_config (محمي بالمسؤول) والتعديل عبر update_dynamic_fee_config. مجموعة تم إنشاؤها بـ enable_dynamic_fee = true تلتقط معاملات المعايرة الخمسة للإعدادات (filter_period، decay_period، reduction_factor، dynamic_fee_control، max_volatility_accumulator) في DynamicFeeInfo الخاص بها عند وقت الإنشاء؛ التعديلات اللاحقة على DynamicFeeConfig لا تؤثر بأثر رجعي على المجموعات الموجودة.

DynamicFeeInfo (مضمّن في PoolState)

الحقول الأربعة السفلية هي حالة؛ الخمسة العليا هي معايرة مُنسخة من DynamicFeeConfig. رياضيات الرسوم وقواعد الاضمحلال موثقة تحت products/clmm/math و products/clmm/fees. الثوابت المستخدمة بواسطة الصيغة:

LimitOrderState

حساب واحد لكل أمر حد مفتوح.
دورة الحياة:
  1. الفتح — يستدعي المستخدم open_limit_order، يودع total_amount من رمز الإدخال، يُربط الأمر بـ TickState cohort.
  2. (اختياري) الزيادة / الإنقاص — increase_limit_order يضيف إلى total_amount؛ decrease_limit_order يعيد الرموز غير المملوءة (وأي مخرجات مستقرة حتى تلك النقطة).
  3. التسوية — عندما تكون المجموعة مملوءة بالكامل أو جزئياً، يستدعي المالك أو حارس التشغيل settle_limit_order لدفع رموز الإخراج إلى ATA المالك.
  4. الإغلاق — بمجرد unfilled_amount == 0، يكون الحساب قابلاً للإغلاق. الإيجار يعود دائماً إلى owner.
بذرة PDA: [owner.as_ref(), limit_order_nonce.key().as_ref(), limit_order_nonce.order_nonce.to_be_bytes().as_ref()]. ترتيب PDA فريد لكل (owner, nonce_index, order_nonce).

LimitOrderNonce

عداد لكل (wallet, nonce_index) يسمح لمستخدم واحد بتشغيل خطوط أنابيب متعددة متوازية من أوامر الحد الأدنى دون تضارب في عناوين PDA.
بذرة PDA: [user_wallet.as_ref(), &[nonce_index]]. تستخدم معظم العملاء nonce_index = 0 وتترك order_nonce ليحمل العدد الأساسي.

Permission (متقاعد)

تم إزالة حساب Permission في ترقية 2026-10-22. كان يستخدم للتحكم في CreatePermissionedPool، وهي الآن CreateCustomizablePoolV2 بدون إذن. لا يقرأ البرنامج هذه الحسابات أو يغلقها بعد الآن، والتعليمات CreatePermissionPda / ClosePermissionPda اختفت. تبقى عناوين PDA المُنشأة قبل الترقية (["permission", authority]، 280 بايت) على السلسلة كبيانات خاملة؛ تجاهلها عند مسح الحسابات المملوكة لـ CLMM.

اشتقاق حسابات المفاتيح

يجب التحقق دائماً من سلاسل البذور الدقيقة مقابل IDL على السلسلة وreference/program-addresses.

مرجع دورة الحياة السريع

حسابات TickArrayState لا تُغلق أبداً بواسطة البرنامج — تبقى طوال حياة المجموعة. بمجرد تهيئة مصفوفة tick، تبقى على السلسلة حتى عندما يعود كل tick بداخلها إلى liquidity_gross == 0. إعادة استخدام مصفوفة tick موجودة مجاني؛ فقط الموضع الأول الذي يلمس مصفوفة لم تُهيأ أبداً يدفع إيجارها.

ما يجب قراءته أين

المصادر: