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

جرد الحسابات

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

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 (مجمع قانوني واحد لكل زوج). قيمة غير صفرية تعني أن المجمع تم إنشاؤه عبر CreatePermissionedPool والفهرس جزء من بذور PDA للمجمع، مما يسمح بعدة مجمعات بالتعايش لنفس (config, mint0, mint1). لإعادة اشتقاق عنوان مثل هذا المجمع يجب أن تعرف seed_index.
  • dynamic_fee_info يحمل حالة التقلب لرسوم الرسوم الديناميكية. عند التفعيل، تعيد كل مبادلة حساب dynamic_fee_component فوق AmmConfig.trade_fee_rate. التخطيط موثق تحت DynamicFeeInfo أدناه؛ المجمعات بدون رسوم ديناميكية تترك البنية بأكملها صفرية.

AmmConfig

مجموعة نموذجية منشورة من فئات رسوم CLMM (تأكد مقابل GET https://api-v3.raydium.io/main/clmm-config): protocol_fee_rate و fund_fee_rate هما كسور من رسوم التداول؛ نفس الاتفاقية مثل CPMM. انظر products/clmm/fees.

TickArrayState

CLMM لا يخزن سجل واحد لكل تكة. سيكون ذلك مليارات الحسابات. بدلاً من ذلك، يجمع TICK_ARRAY_SIZE تكات متجاورة مهيأة أم لا (عادة 60 أو 88 حسب إصدار البرنامج) في TickArrayState يتم إنشاؤه بكسل عند الاستخدام الأول.
الحقول الأربعة لأوامر الحد هي صفر على أي تكة لم تُستخدم أبدًا لأمر حد. عندما تُفتح أوامر على تكة، يتتبعها البرنامج كسلسلة من المجموعات:
  • 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. يرفض البرنامج المواضع خارج التباعد.
  • مصفوفة التكة موجودة في floor(t / (TICK_ARRAY_SIZE * tick_spacing)) * (TICK_ARRAY_SIZE * tick_spacing).
  • يتم تهيئة مصفوفة التكات بكسل: الموضع الأول أو المبادلة التي تلمس مصفوفة غير مهيأة تنشئها، وتدفع الإيجار.
  • مصفوفة التكات لا تُغلق أبدًا من قبل البرنامج. بمجرد تخصيصها تستمر طوال حياة المجمع، حتى بعد أن تعود كل تكة بداخلها إلى liquidity_gross == 0. تعيد المواضع والمبادلات اللاحقة استخدام الحساب الموجود بدون إيجار إضافي. لا توجد مسار تنظيف مدفوع بـ ClosePosition لمصفوفات التكات.

TickArrayBitmapExtension

PoolState.tick_array_bitmap (مضمنة) تغطي نطاق “قريب من السوق” — ±1,024 مصفوفة تكات. خارج هذا النطاق (لقيم التكات القصوى)، يحتفظ البرنامج بحساب امتداد:
إذا كان نطاق موضعك “عاديًا”، فأنت لا تفكر أبدًا في حساب الامتداد. المواضع ذات النطاق الكامل (مثل (MIN_TICK, MAX_TICK)) تتطلبها؛ SDK يحلها لك.

المواضع

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

NFT mint للموضع

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

PersonalPositionState

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

ProtocolPositionState (مهجور)

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

الملاحظة

يخزن مخزن مؤقت الملاحظة في CLMM تكة تراكمية، وليس سعر تراكمي. يحسب المستهلكون الخارجيون السعر الهندسي المتوسط على فترة من (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.
  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) يسمح لمستخدم واحد بتشغيل خطوط أنابيب متوازية متعددة من أوامر الحد بدون تصادم على PDAs.
بذرة PDA: [user_wallet.as_ref(), &[nonce_index]]. معظم العملاء يستخدمون nonce_index = 0 ويتركون order_nonce يحمل الأساسية.

Permission

حساب قدرة وجوده هو المنحة: إذا تم اشتقاق PDA Permission لسلطة معينة، قد تستدعي تلك السلطة CreatePermissionedPool. لا يخزن شيئًا بعيدًا عن السلطة التي تم إنشاؤها لها.
بذرة PDA: ["permission", authority.as_ref()]. تُنشأ من قبل مسؤول عبر CreatePermissionPda وتُفكك عبر ClosePermissionPda (الإيجار يعود إلى المستدعي). كلا التعليمات الإدارية تقبل إما برنامج admin أو مفتاح permission_pda_admin مخصص. إغلاق PDA يلغي المنحة — لا يمكن للسلطة بعد الآن إنشاء مجمعات إضافية، لكن المجمعات التي أنشأتها بالفعل لم تتأثر.

اشتقاق الحسابات الرئيسية

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

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

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

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

المصادر: