Skip to main content
هذه الصفحة مُترجَمة آليًا بواسطة الذكاء الاصطناعي. النسخة الإنجليزية هي المرجع المعتمد.عرض النسخة الإنجليزية →
تقترن هذه الصفحة بـ products/clmm/accounts (ما هي الحسابات) و products/clmm/math (ما هي الرياضيات). وهي مرجعية للمعاملات وترتيب الحسابات؛ تأتي تخطيطات البايت المحددة من IDL.أعاد ترقية البرنامج 2026-09 بناء CLMM على Anchor 1.0.2 / Solana 3.1.10، وأضاف تعليمات المسؤول CollectExcessLamports، وغيّر ما تكتبه CreateAmmConfig في owner / fund_owner. لم تغيّر أي تعليمات موجهة للمستخدم حساباتها أو معاملات أو رياضيات. انظر إدخال السجل 2026-09-30.

جرد التعليمات

لا توجد تعليمة init-tick-array، ولا حاجة لها. يتم إنشاء مصفوفة علامة داخل OpenPosition* / IncreaseLiquidity* بواسطة TickArrayState::get_or_create_tick_array، يتم دفعها بواسطة payer. مرر PDA مصفوفة العلامة (ربما لا تزال غير مهيأة، مملوكة للنظام) كـ tick_array_lower / tick_array_upper والبرنامج يخصصها إذا كانت مفقودة. OpenLimitOrder يفعل الشيء نفسه لـ tick_array الواحد الخاص به.
معظم التعليمات الخاصة بالمسؤول (CreateAmmConfig، UpdateAmmConfig، UpdatePoolStatus، CreateOperationAccount، UpdateOperationAccount، CloseProtocolPosition) يتم التحكم فيها بواسطة مفتاح admin المشفر بقوة في البرنامج. CreatePermissionPda / ClosePermissionPda تقبل إما مفتاح admin أو مفتاح permission_pda_admin مخصص؛ CreateSupportMintAssociated / CloseSupportMintAssociated تقبل إما مفتاح admin أو مفتاح مالك support-mint مخصص؛ CollectExcessLamports تقبل إما مفتاح admin أو محفظة جمع lamports مخصصة. تعليمات مسؤول تدفق المكافآت (TransferRewardOwner، CollectRemainingRewards) يتم التحكم فيها بواسطة ممول المكافآت، وليس مسؤول البرنامج. لاحقة V2 تعني “يدعم Token-2022 على الأقبية / NFT، يتطلب فتحة امتداد bitmap”. يختار SDK V2 بشكل افتراضي للمجمعات الجديدة.

CreatePool

المعاملات
الحسابات (مختصرة)
الفتحات 10 و 11 هي لكل mint، وليس “SPL Token ثم Token-2022”. كل واحد مقيد بـ mint::token_program على الـ mint المطابق، لذا بالنسبة لمجمع يكون token_mint_0 فيه Token-2022 و token_mint_1 هو SPL كلاسيكي يجب عليك تمرير Token-2022 في الفتحة 10 و SPL Token في الفتحة 11. CreateCustomizablePool و CreatePermissionedPool يستخدمان نفس الفتحتين.
الشروط المسبقة
  • token_mint_0 < token_mint_1 حسب ترتيب البايت.
  • amm_config.disable_create_pool == false.
  • لم يتم رفض الـ mints بواسطة قائمة السماح بامتداد Token-2022.
الشروط اللاحقة
  • pool_state.sqrt_price_x64 = sqrt_price_x64، tick_current = floor(log_{1.0001}(price)).
  • pool_state.liquidity = 0 (لا توجد مراكز حتى الآن).
  • pool_state.fee_on = FromInput (الافتراضي القديم).
  • pool_state.dynamic_fee_info مصفر (الرسوم الديناميكية معطلة).

CreateCustomizablePool

موصى به للمجمعات الجديدة. نفس تأثير CreatePool بالإضافة إلى وضع جمع الرسوم لكل مجمع واختيار رسوم ديناميكية اختياري. المعاملات
الحسابات — بالضبط 13 حسابًا معلنًا من CreatePool. dynamic_fee_config ليس حسابًا معلنًا.
عندما enable_dynamic_fee = true، يجب توفير DynamicFeeConfig للالتقاط كـ آخر remaining_account — يقرأ المعالج ctx.remaining_accounts.last(). أي PDAs تجاوز SupportMintAssociated يجب أن تأتي قبله، وإلا يلتقط البرنامج الحساب الخاطئ ويفشل في فك التسلسل. حذف الحساب بينما العلم مضبوط يفشل مع AccountLack.
الشروط المسبقة — نفس CreatePool. إذا كان enable_dynamic_fee = false، لا يلزم remaining_account وأي يتم تمريره يتم فحصه فقط للحصول على سجلات support-mint. الشروط اللاحقة
  • pool_state.fee_on مضبوط على متغير CollectFeeOn المختار.
  • إذا تم تفعيل الرسوم الديناميكية: يتم تهيئة pool_state.dynamic_fee_info من DynamicFeeConfig المزود (خمسة معاملات معايرة مسخوخة؛ حقول الحالة مصفرة).
  • وإلا: pool_state.dynamic_fee_info مصفر (= الرسوم الديناميكية غير نشطة إلى الأبد لهذا المجمع).
يتم تعيين fee_on وبت تفعيل الرسوم الديناميكية فقط عند إنشاء المجمع. لا توجد ترقية في المكان — لا يمكن للمجمعات التي تم إنشاؤها عبر CreatePool القديم أن تكتسب رسوم ديناميكية أو رسوم أحادية الجانب بأثر رجعي. يجب أن تستخدم النشرات الجديدة هذه التعليمة بشكل افتراضي.

CreatePermissionedPool

كل من CreatePool و CreateCustomizablePool يشتقان PDA المجمع من ["pool", amm_config, token_mint_0, token_mint_1]، لذا يوجد بالضبط عنوان مجمع قانوني واحد لكل ثلاثية (config, mint0, mint1) — محاولة init ثانية بنفس البذور تفشل. CreatePermissionedPool يرفع هذا التقييد بطي seed_index: u16 المزود من قبل العميل في بذور PDA المجمع، مما يسمح بـ مجمعات متعددة لنفس الزوج وفئة الرسوم — كل واحد في عنوانه الخاص. لأن عنوان مجمع تعسفي هو قدرة مميزة، يجب أن يحتفظ الدافع بـ PDA Permission يفوضه. كل شيء آخر عن المجمع متطابق مع CreateCustomizablePool: يأخذ نفس CreateCustomizableParams ويدعم الرسوم أحادية الجانب واختيار الرسوم الديناميكية. المعاملات
الحسابات (مختصرة) — نفس CreateCustomizablePool بالإضافة إلى، في الأمام: يتم اشتقاق PDA pool_state من ["pool", amm_config, token_mint_0, token_mint_1, seed_index.to_le_bytes()]. الشروط المسبقة
  • seed_index != 0. seed_index من 0 محجوز للمجمعات القديمة ويتم رفضه هنا؛ مكون البذرة [0, 0] هو ما يجعل عنوان المجمع القديم ينهار إلى الشكل الكلاسيكي ذي البذور الأربع.
  • PDA permission لـ payer موجود (تم إنشاؤه بواسطة مسؤول عبر CreatePermissionPda).
  • نفس قواعد mint / allow-list مثل CreatePool.
الشروط اللاحقة
  • pool_state جديد موجود في عنوان مشتق من seed_index، مع pool_state.seed_index = seed_index.
  • جميع حالات ما بعد الحالة الأخرى تطابق CreateCustomizablePool (وضع الرسوم، الرسوم الديناميكية الاختيارية).
هذه التعليمة لا توسع الوصول العام لإنشاء المجمع — الإنشاء بدون إذن يستمر عبر CreatePool / CreateCustomizablePool، والتي تبقى مجمع واحد لكل زوج. CreatePermissionedPool موجود للحالة المحددة حيث يحتاج مشغل مدرج في القائمة البيضاء إلى عدة مجمعات لنفس الزوج (على سبيل المثال، أسعار أولية مختلفة أو مجموعات إطلاق) ويحتفظ بـ PDA Permission منحه المسؤول.

OpenPositionV2 / OpenPositionWithToken22Nft

إنشاء مركز جديد داخل مجمع موجود. المعاملات
الحسابات — المتغيران لهما قوائم حسابات مختلفة. OpenPositionV2 يعلن 22؛ OpenPositionWithToken22Nft يعلن 20. OpenPositionV2، بالترتيب: OpenPositionWithToken22Nft هي نفس القائمة مع metadata_account (5) و metadata_program (19) محذوفة — تكتب بيانات وصفية المركز عبر امتداد البيانات الوصفية Token-2022 على NFT mint بدلاً من ذلك — مما يعطي 20 حسابًا. position_nft_mint الخاص به هو Signer عادي و position_nft_account هو UncheckedAccount.
tick_array_bitmap_extension ليس حسابًا معلنًا على أي متغير. عندما يقع نطاق المركز خارج tick_array_bitmap المضمن للمجمع (±512 مصفوفة علامة)، أضف PDA TickArrayBitmapExtension في البذور ["pool_tick_array_bitmap_extension", pool_state] كـ remaining_accounts[0].
الرياضيات — انظر products/clmm/math. بالنظر إلى base_flag، يحل البرنامج إما liquidity أو (amount_0_max, amount_1_max) إلى L الفعلي والمبالغ الفعلية للرموز المستهلكة. الشروط المسبقة
  • tick_lower < tick_upper، كلاهما مضاعفات pool.tick_spacing، ضمن [MIN_TICK, MAX_TICK].
  • يتم تمرير PDA مصفوفتي العلامة. لا يجب أن تكون موجودة بالفعل — get_or_create_tick_array يخصص واحدة مفقودة على حساب payer داخل هذه التعليمة. لا توجد تعليمة init-tick-array منفصلة.
  • يحتوي المستخدم على ما لا يقل عن amount_0_max و amount_1_max في ATAs المصدر.
الشروط اللاحقة
  • personal_position موجود، liquidity مضبوط، fee_growth_inside_last مأخوذ لقطة.
  • تم تحديث إدخالات مصفوفة العلامة في tick_lower و tick_upper (liquidity_gross += L، liquidity_net ± L، لقطات نمو الرسوم المحفوظة).
  • pool_state.liquidity += L إذا كان المركز في النطاق (tick_lower ≤ tick_current < tick_upper).
  • يسجل NFT mint pool_state كسلطة تجميد. يتم إزالة سلطة الـ mint بعد صك NFT الواحد. تسجيل سلطة التجميد لا يغير حالة حساب رمز NFT.
  • يبقى حساب رمز NFT غير مجمد ما لم تكن التعليمة OpenPositionV2 أو OpenPositionWithToken22Nft و تطابق سلطة تجميد أي vault mint قائمة المُصدر المقيد لـ CLMM. فقط مسار V2 المطابق هذا يجمد الحساب. OpenPosition V1 لا يجمد.
الأخطاء الشائعة — TickInvalidOrder (tick_lower >= tick_upper)، TickAndSpacingNotMatch (نقطة نهاية ليست مضاعفة tick_spacing)، InvalidTickIndex (خارج [MIN_TICK, MAX_TICK])، MissingTickArrayBitmapExtensionAccount (النطاق خارج bitmap المضمن والامتداد لم يتم إلحاقه)، NotApproved (pool_state.status يمنع الفتح)، ZeroAmountSpecified.
تجميد المركز لا يضيف حسابات تعليمات معلنة أو معاملات. يمكن للعملاء فتح هذه المراكز بتخطيطات V2 الموجودة. يتم اختيار السلوك على السلسلة من vault_0_mint و vault_1_mint.

IncreaseLiquidityV2

إضافة السيولة إلى مركز مفتوح بالفعل. المعاملات
الحسابات — 15، و ليست مشتقة من OpenPosition: لا توجد rent، لا system_program، لا associated_token_program ولا حساب بيانات وصفية. أضف PDA TickArrayBitmapExtension في البداية كـ remaining_accounts[0] عندما يكون نطاق المركز خارج bitmap المضمن. التأثير
  • ينقل amount_0_actual / amount_1_actual من المستخدم → الأقبية.
  • يزيد personal_position.liquidity و pool_state.liquidity (إذا كان في النطاق)، وإدخالات العلامة النهائية liquidity_gross / liquidity_net وفقًا لذلك.
  • يجمع الرسوم والمكافآت المستحقة منذ آخر لمسة ويعتمدها على token_fees_owed_{0,1} / reward_amount_owed. يتم دفعها فقط على DecreaseLiquidity / DecreaseLiquidityV2، وليس على الزيادة — لا توجد تعليمة جمع مستقلة.

DecreaseLiquidityV2

إزالة السيولة من مركز. المعاملات
الحسابات — 16، و ليست نفس الشكل أو الترتيب مثل IncreaseLiquidityV2: personal_position و pool_state مبدلان، الأقبية تأتي قبل مصفوفات العلامة، حسابات جانب المستخدم مسماة recipient_token_account_*، وهناك memo_program إضافي. الحسابات المتبقية — ثلاثة لكل مكافأة نشطة يتم جمعها، بالترتيب reward_token_vault(W)، recipient_token_account(W)، reward_vault_mint. أضف PDA TickArrayBitmapExtension عندما يكون نطاق المركز خارج bitmap المضمن.
هذا هو أيضًا الطريقة الوحيدة لجمع الرسوم والمكافآت. لجمع بدون تغيير المركز، استدعه مع liquidity = 0، amount_0_min = 0، amount_1_min = 0.
التأثير
  • يحسب (amount_0, amount_1) للـ L المزال بالنظر إلى sqrt_price_x64 الحالي.
  • يسوي الرسوم/المكافآت المتراكمة منذ آخر لمسة، نفس IncreaseLiquidity.
  • ينقل amount_0 + fees_owed_0 و amount_1 + fees_owed_1 خارج الأقبية إلى المستخدم.
  • ينقص عدادات السيولة؛ إذا كان personal_position.liquidity == 0 الجديد، يكون المركز مؤهلاً لـ ClosePosition.
الانزلاق — amount_0_min و amount_1_min هما الحد الأدنى الذي يقبله المستخدم بعد خصم رسوم نقل Token-2022 على جانب الإخراج.

ClosePosition

حرق NFT المركز وإغلاق PersonalPositionState. الحسابات المعلنة الحسابات المتبقية
  • NFT غير مجمد: لا يلزم أي شيء؛ حساب مجمع إضافي غير ضار لأن المعالج لا يقرأه.
  • NFT مجمد: أضف personal_position.pool_id كأول حساب متبقي. يحمل البرنامج كـ PoolState ويستخدم بذور PDA الخاصة به للتوقيع على الإذابة.
الشروط المسبقة
  • personal_position.liquidity == 0.
  • tokens_fees_owed_{0,1} == 0.
  • جميع عدادات المكافآت reward_amount_owed == 0.
(أي، جمع كل شيء وتقليل إلى صفر أولاً.) التأثير
  • إذا كان حساب رمز NFT مجمدًا، تحقق من أن أول حساب متبقي يساوي personal_position.pool_id، ثم أذبه مع PDA المجمع.
  • حرق NFT.
  • أغلق حساب رمز NFT و personal_position، مسترجعًا الإيجار إلى nft_owner. إذا كان NFT المركز يستخدم Token-2022، فإنه يغلق أيضًا NFT mint؛ لا يمكن إغلاق mints SPL Token الكلاسيكية وتبقى بإمداد صفر.
الإذابة والحرق والإغلاق ذريون. لا يمكن لـ NFT أن يصبح قابلاً للنقل بين تلك الخطوات. فاصل العميل الشرطي — تخطيط IDL المعلن لم يتغير، لذا يستمر العملاء القدامى في إغلاق المراكز الموجودة وغير المجمدة. منشئ قديم يحذف حساب المجمع المتبقي يفشل مع AccountLack عند إغلاق مركز مجمد. تمرير المجمع لكل إغلاق هي أبسط استراتيجية متوافقة.

SwapV2

المشي على منحنى السيولة؛ إدخال دقيق أو إخراج دقيق حسب is_base_input. المعاملات
الحسابات (مختصرة) يمرر المتصلون قائمة مرتبة من مصفوفات العلامة التي تغطي مشي المبادلة المتوقع؛ يستخدم البرنامج ما يحتاجه. يحسب SDK هذه القائمة عبر PoolUtils.computeAmountOutFormat أو نقطة نهاية الاقتباس في API. الشروط المسبقة
  • pool_state.status يسمح بالمبادلة.
  • now >= open_time.
  • sqrt_price_limit_x64 على الجانب الصحيح من sqrt_price_x64 للاتجاه.
الأخطاء الشائعة — TooLittleOutputReceived (انزلاق إدخال دقيق)، TooMuchInputPaid (انزلاق إخراج دقيق)، SqrtPriceLimitOverflow، NotEnoughTickArrayAccount، InvalidFirstTickArrayAccount، MissingTickArrayBitmapExtensionAccount، LiquidityInsufficient، NotApproved (بت المبادلة مضبوط على pool_state.status). CLMM ليس لديه متغير ExceededSlippage — هذا الاسم خاص بـ CPMM — ولا TickArrayNotFound. ما الذي يفعله SwapV2 داخليًا والذي يجب أن يعرفه المتصلون (بعد إصدار 2025):
  1. رسوم ديناميكية إضافية — إذا كان pool.dynamic_fee_info غير صفري، يحدّث البرنامج مراكم التقلب باستخدام مسافة العلامة المقطوعة منذ آخر مبادلة (مع قواعد التصفية/الاضمحلال من products/clmm/fees) ويضيف dynamic_fee_component على رأس AmmConfig.trade_fee_rate. إجمالي الرسوم مغطى بـ 10% (MAX_FEE_RATE_NUMERATOR / 1_000_000).
  2. مطابقة أوامر الحد — عندما يعبر مشي السعر علامة تحتفظ بأوامر حد مفتوحة، يملأ البرنامج أولاً سيولة أوامر الحد المتاحة في تلك العلامة (FIFO حسب order_phase)، ثم يمضي على منحنى سيولة LP. تحدّث المبالغ المملوءة tick.unfilled_ratio_x64 و tick.part_filled_orders_remaining للتسوية لاحقًا؛ تبقى الأوامر نفسها غير منفقة حتى يستدعي مالكها SettleLimitOrder.
  3. توجيه الرسوم أحادي الجانب — عندما pool.fee_on = Token0Only أو Token1Only، تحسب خطوة المبادلة نفس إدخال-إخراج التجارة؛ يتم بعد ذلك توجيه الرسوم إلى الجانب المكون. بالنسبة للاتجاهات حيث جانب الرسوم المكون هو الإخراج، يتم خصم الرسوم من إخراج المبادلة (يتلقى المستخدم out − fee)؛ بالنسبة للاتجاهات حيث يكون الإدخال، السلوك يطابق FromInput. انظر is_fee_on_input(zero_for_one) و is_fee_on_token0(zero_for_one) على PoolState.
Swap (V1) ينفذ نفس الرسوم الديناميكية وتوجيه الرسوم أحادي الجانب ومطابقة أوامر الحد مثل SwapV2؛ الميزة الوحيدة التي ينقصها هي دعم Token-2022 — يجب أن تكون كلا الأقبية SPL Token كلاسيكية. يجب مبادلة المجمعات التي تحتوي على أي mint Token-2022 عبر SwapV2. يفضل المجمع والـ SDK بالفعل V2 لكل ساق CLMM لذا لا يضطر المتصلون إلى الفرع على نوع mint.

OpenLimitOrder

ضع أمر بيع في علامة محددة. يجلس الأمر في مجموعة FIFO لكل علامة ويملأ عندما يمشي السعر بجانبه. المعاملات
الحسابات (مختصرة) الحسابات المتبقية — [0] tick_array_bitmap_extension، مطلوب فقط عند تهيئة مصفوفة علامة يقع فهرس البداية الخاص بها خارج bitmap المضمن للمجمع. لا تمرر أي شيء وإلا.
لا يوجد حساب rent: ينتهي الهيكل في system_program، 13 حسابًا معلنًا. rent ضائع في الموضع 14 يهبط بالضبط حيث يتم قراءة امتداد bitmap الاختياري، لذا يبدو الأمر أنه يعمل حتى المرة الأولى التي يجب فيها إنشاء مصفوفة علامة خارج bitmap المضمن — ثم يفشل.
تغيير قائمة الحسابات (إصدار 2026-07). OpenLimitOrder يأخذ الآن أيضًا حسابات جانب الإخراج — output_token_account، output_vault، و output_vault_mint — بالإضافة إلى جانب الإدخال. يتم استخدامها فقط للتحقق: يرفض البرنامج الأمر إذا كان حساب رمز الإدخال أو الإخراج للمالك مجمدًا. هذا يضمن أن الملء يمكن فعلاً تسويته إلى ATA الإخراج للمالك، وهو مهم لـ mints Token-2022 المسموح بها / المجمدة بشكل افتراضي (على سبيل المثال، الرموز المرخصة) حيث قد لا يكون الحساب قد تم إذابته بعد. يجب على العملاء المبنيين مقابل قائمة الحسابات أحادية الجانب الأقدم إضافة الحسابات الثلاثة للإخراج.
الشروط المسبقة
  • لا input_token_account ولا output_token_account مجمد (وإلا NotApproved).
  • pool_state.status يسمح بعمليات المبادلة (بت 4) وأوامر الحد (بت 5) (وإلا NotApproved).
  • tick_index % pool.tick_spacing == 0 وضمن [MIN_TICK, MAX_TICK].
  • tick_index على الجانب الأيمن من pool.tick_current للاتجاه المختار (بيع token0 → يجب أن تكون العلامة فوق الحالية، والعكس صحيح). البيع عند علامة تم عبورها بالفعل سيتم مطابقته فورًا ويتم رفضه.
الشروط اللاحقة
  • limit_order موجود، لقطة tick.order_phase و tick.unfilled_ratio_x64 عند وقت الفتح.
  • tick.orders_amount += amount (في المجموعة الحالية).
  • limit_order_nonce.order_nonce += 1.
  • OpenLimitOrderEvent مُصدر.
الأخطاء الشائعة — NotApproved (حساب رمز الإدخال أو الإخراج مجمد، أو المجمع لديه مبادلة / أوامر حد معطلة)، ZeroAmountSpecified (amount == 0 بعد رسوم نقل جانب الإدخال)، InvalidLimitOrderAmount (المبلغ سينتج إخراجًا أقل من 1 وحدة أساسية في تلك العلامة، أو تجاوز u64)، InvalidTickIndex (خارج [MIN_TICK, MAX_TICK]، أو على الجانب الخاطئ من tick_current للاتجاه المختار)، TickAndSpacingNotMatch (tick_index % pool.tick_spacing != 0)، OrderPhaseSaturated.

IncreaseLimitOrder

إضافة إلى أمر مفتوح موجود. قابل للاستدعاء فقط من قبل owner الأمر. المعاملات
الحسابات — 8، جانب الإدخال فقط. يسقط حساب nonce، جميع حسابات جانب الإخراج الثلاثة و system_program. الشروط المسبقة
  • limit_order.owner == signer.
  • الأمر لا يزال في نفس المجموعة (tick.order_phase == limit_order.order_phase). إذا بدأت المجموعة بالفعل بالملء، يتم تسوية الأمر جزئيًا — يجب على المتصل استدعاء DecreaseLimitOrder أو SettleLimitOrder أولاً للمضي قدمًا.
التأثير
  • ينقل amount من ATA المالك إلى input_vault.
  • limit_order.total_amount += amount؛ tick.orders_amount += amount.

DecreaseLimitOrder

تقليل أو إلغاء كامل أمر مفتوح. يدفع الباقي غير المملوء مرة أخرى إلى المالك، بالإضاف