هذه الصفحة مُترجَمة آليًا بواسطة الذكاء الاصطناعي. النسخة الإنجليزية هي المرجع المعتمد.عرض النسخة الإنجليزية →
الإعداد
raydium-sdk-V2-demo/src/clmm، ويظهر رابط GitHub بجوار كل قسم. تُهيَّأ البيئة وفق ملف config.ts.template في مستودع الأمثلة (المصدر)، ويُنصح بضبط disableFeatureCheck: true في أي تكامل غير بسيط:
إنشاء CLMM pool
المصدر:src/clmm/createPool.ts
- يرتّب
mint1وmint2حسب ترتيب البايتات قبل الاشتقاق. - يحسب
sqrt_price_x64 = floor(sqrt(initialPrice × 10^(dB−dA)) × 2^64). - ينشئ حسابي
observationوtick_array_bitmap_extension. - يدفع رسوم إنشاء الـ pool المحددة في
ammConfig.
فتح position ضمن نطاق مختار
المصدر:src/clmm/createPosition.ts
OpenPosition* يخصّص الـ tick array المفقودة بنفسه على حساب الدافع.
زيادة السيولة في position موجود
المصدر:src/clmm/increaseLiquidity.ts
تقليل السيولة (وجمع الرسوم في الوقت نفسه)
المصدر:src/clmm/decreaseLiquidity.ts وsrc/clmm/closePosition.ts
decreaseLiquidity بقيمة liquidity = new BN(0). أثر هذه التعليمة هو تسوية token_fees_owed_{0,1} وreward_amount_owed ونقلها إلى الخارج، وهذه هي الطريقة الوحيدة لجمع أيٍّ منهما.
ولإغلاق الـ position نهائيًا بعد تصفير السيولة والرسوم، مرّر ownerInfo: { closePosition: true } في الاستدعاء الأخير لـ decreaseLiquidity. عندها يُلحق الـ SDK تعليمة ClosePosition ويحرق الـ NFT.
بالنسبة إلى عميل Anchor مباشر، أبقِ الحسابات المعلنة دون تغيير، وأضف الـ pool في النهاية:
poolId في كل عملية إغلاق. لا يقرؤه CLMM إلا عندما يكون positionNftAccount مجمّدًا، ما يُبقي مسار عميل واحد متوافقًا مع المراكز القديمة والجديدة.
جمع المكافأة (المكافآت)
المصدر:src/clmm/harvestAllRewards.ts
harvestAllRewards على كل position في كل pool تُمرَّر إليه، ويجمّع استدعاءات DecreaseLiquidity ذات السيولة الصفرية التي تسوّي الرسوم والمكافآت (إضافةً إلى أي UpdateRewardInfos)، ثم يوزّعها على عدة معاملات عند الحاجة.
المبادلة (Swap)
المصدر:src/clmm/swap.ts
يعكس هذا المثال الملف src/clmm/swap.ts، إذ يحاكي العملية باستخدام swapInternal بدلًا من PoolUtils.computeAmountOutFormat.
amountCalculated) إضافةً إلى قائمة الحسابات الدقيقة التي ستلمسها عملية المبادلة (accounts).
مرِّر دائمًا remainingAccounts التي تُعيدها المحاكاة: إذا كانت الحسابات أقل من المطلوب فستفشل المبادلة في منتصف المسار مع NotEnoughTickArrayAccount، أما الحسابات الزائدة أو القديمة فتستهلك وحدات الحوسبة دون فائدة.
ما زال
PoolUtils.computeAmountOutFormat موجودًا، لكنه يتطلب ComputeClmmPoolInfo (وهو computePoolInfo القادم من getPoolInfoFromRpc، وليس كائن pool من الـ API)، إضافةً إلى معاملين إلزاميين آخرين هما tickarrayBitmapExtension وblockTimestamp. كما أنه لا توجد طريقة raydium.clmm.fetchTickArrays، فـ fetchTickArrays دالة مستقلة، والمساعدات على مستوى الوحدة هي PoolUtils.fetchMultiplePoolTickArrays والـ tickData / tickArrays التي يُعيدها getPoolInfoFromRpc.إنشاء مجمّع CLMM قابل للتخصيص
createCustomizablePool هي نقطة الدخول التي تتيح تفعيل الرسوم الديناميكية ورسوم الجانب الواحد عند إنشاء المجمّع. تأخذ الشكل نفسه الذي تأخذه createPool، مع إضافتين:
createPool تعمل للمسار ذي الرسوم الافتراضية دون رسوم ديناميكية. استخدم createCustomizablePool متى احتجت أيًّا من الخيارين. راجع products/clmm/instructions للاطلاع على قائمة الحسابات على السلسلة.
أوامر الحدّ (Limit orders)
أمر الحدّ يحجز مدخلات المستخدم عند tick واحد، ويُنفَّذ وفق مبدأ FIFO عندما تعبر عملية مبادلة ذلك الـ tick. تُرسَل المخرجات إلى ATA المالك عند التسوية، ولا يلزم أن يكون المالك متصلًا كي يُنفَّذ أمره.فتح أمر حدّ
لا يوجد حساب إعدادات لأوامر الحدّ لكل مجمّع، ولا دالةgetClmmLimitOrderConfigs() — الأوامر مُفهرسة حسب الـ tick.
LimitOrderState من (owner, nonce PDA, order nonce)، ويرفع LimitOrderNonce الخاص بكل محفظة، ويُدرج الأمر في طابور FIFO عند ذلك الـ tick.
زيادة / تقليل أمر مفتوح
decreaseLimitOrder أن يقتطع إلا من الجزء غير المنفَّذ من الأمر، أما الجزء المنفَّذ فيبقى مقفلًا حتى التسوية. وتفشل كلتا التعليمتين بالخطأ InvalidOrderPhase إذا كان الأمر منفَّذًا بالكامل.
تسوية أمر منفَّذ
settleLimitOrder القيمة unfilled_ratio_x64 الخاصة بالأمر مقارنةً بمتتبّع الطابور، وتحسب المخرجات المنفَّذة، ثم تحوّلها إلى ATA المالك. يستطيع المالك استدعاء هذه الدالة بنفسه، كما يستطيع limit_order_admin (وهو مشغّل تشغيلي خارج السلسلة) استدعاءها نيابةً عنه، وتبقى المخرجات من نصيب المالك في كل الأحوال.
لإغلاق الأوامر المسوّاة بالكامل واسترداد الإيجار (rent)، استخدم closeLimitOrder (لأمر واحد) أو closeAllLimitOrder (دفعةً واحدة). ولتسوية عدد كبير من الأوامر دفعةً واحدة، تقوم settleAllLimitOrder بتجميع أكبر عدد ممكن من استدعاءات SettleLimitOrder في معاملة v0 واحدة.
عرض الأوامر المعلّقة لمحفظة (خارج السلسلة)
totalAmount وfilledAmount وpendingSettle بين المراحل). أما سجل الأوامر المغلقة فيُستخرج من /limit-order/history/order/list-by-user?wallet=… (لكل محفظة، مع ترقيم الصفحات عبر nextPageId)، وأما سجل الأحداث الكامل لأمر بعينه فيُستخرج من /limit-order/history/event/list-by-pda?pda=….
هيكل استدعاء CPI بلغة Rust
SwapV2:
المزالق الشائعة
- نقاط نهاية الـtick غير متوافقة مع الـspacing →
TickAndSpacingNotMatch. استخدم دائمًاTickUtil.getPriceAndTickللتقريب (بصيغة المفردTickUtil). - عدم كفاية مصفوفات الـtick المُمرَّرة في
SwapV2→NotEnoughTickArrayAccount. اجلب القائمة منswapInternal(...).accounts. - position بنطاق كامل دون امتداد الـbitmap → يجب أن يكون PDA الخاص بالامتداد قابلاً للكتابة، ويتولى الـSDK ذلك تلقائيًا.
- الخلط بين
sqrt_price_x64وprice→ الخطأ بعامل 2 هنا مؤلم بشكل خاص. عند الشك، دع الـSDK يحسب القيمة انطلاقًا من سعر مقروء للإنسان. - جمع المكافآت بإفراط → كل عملية جمع هي
DecreaseLiquidityبسيولة صفرية وتكلّف معاملة واحدة. اجمعها دفعة واحدة عبرharvestAllRewardsعلى عدة positions، وتذكّر أنexecuteالخاص بها يحتاج إلى{ sequentially: true }. - إغلاق حسابات الـNFT يدويًا →
ClosePositionيحرق الـNFT ويغلق الـATA الخاص به. كما يغلق mint الخاص بـNFT من نوع Token-2022، أما mint من نوع SPL Token الكلاسيكي فيبقى بعرض صفري لأن ذلك البرنامج لا يستطيع إغلاق الـmints. لا تغلق الحسابات المدعومة بشكل منفصل، وإلا فستفشل التعليمة وتتراجع. - فتح أمر حد عند tick غير متوافق مع الـspacing →
TickAndSpacingNotMatch. قرِّب القيمة دائمًا عبر دالة المساعدة المصدَّرةgetOrderTick. - استدعاء
decreaseLimitOrderعلى أمر مُنفَّذ بالكامل →InvalidOrderPhase. استخدمsettleLimitOrderثمcloseLimitOrderبدلًا من ذلك. - توقّع علامة
enableDynamicFee→ لا وجود لها. حذفdynamicFeeConfigينشئ ببساطة pool برسوم ثابتة، بصمت ودون أي خطأ. إن أردت رسومًا ديناميكية، فمرِّر الـPublicKeyالخاص بحساب الإعدادات، واختره من/main/clmm-dynamic-config.
إلى أين تذهب بعد ذلك
sdk-api/typescript-sdk— واجهة الـSDK الكاملة.sdk-api/rest-api— نقاط نهاية عروض الأسعار وبيانات الـpool.user-flows/create-clmm-pool— شرح بدون كود خطوة بخطوة.integration-guides/aggregator— توجيه CLMM ضمن مسار التبادل.

