agentsclimarketplace

Cdpm user sdk

Skill RandyPen/cdpm/skills/cdpm-user-sdk

TypeScript SDK guide for CDPM (Cetus DLMM Position Manager) end-users. Provides PTB construction patterns for creating positions, managing liquidity, authorizing agents, collecting fees, and supplying/redeeming idle funds via Scallop lending or Kai SAV lending. Use when users need to interact with CDPM contract through TypeScript SDK.From its SKILL.md

Install
npx -y skills add RandyPen/cdpm --skill cdpm-user-sdk

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

2 things to look at

  • no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
  • 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

SKILL.md

6.2 KB, ~1.6k tokens by cl100k_base, as published. Nobody here has run it

CDPM User SDK Guide

Overview

CDPM (Cetus DLMM Position Manager) is a proxy contract for managing Cetus DLMM positions with support for user self-management, agent delegation, protocol-managed operations, and two optional lending integrations for idle funds: Scallop (single-generic <T> market coin) and Kai SAV (two-generic <T, YT> strategy-aggregating vault). Both integrations share pm.lending: Bag and a single fee_house.fee_rate knob.

Package Address: 0x573584cc4698e82fd85f2b54e64ad4cd901c42b768f7628ec167bf2d24aa2aa7 (only-dep-upgrades digest: F5kVa3YDSHoBvJvYJFH9y5dANCJScEdyZoxZLLy6qd15cdpm.move bytecode is locked; only dependency-version upgrades are allowed). Other shared object IDs live in reference/constants.md.

The PositionManager struct contains a lending: Bag holding both Scallop ScallopVault<T> entries (keyed by type_name<T>) and Kai SAV KaiVault<T, YT> entries (keyed by type_name<YT>) — both can coexist on a single PM. See Scallop Lending and Kai SAV Lending for end-user PTB recipes.

Quick Start

Installation

bun add @mysten/sui

Initialize Client

import { SuiGrpcClient } from '@mysten/sui/grpc';
import { Transaction } from '@mysten/sui/transactions';

const client = new SuiGrpcClient({
  baseUrl: 'https://fullnode.mainnet.sui.io:443',
  network: 'mainnet',
});
const CDPM_PACKAGE = '0x573584cc4698e82fd85f2b54e64ad4cd901c42b768f7628ec167bf2d24aa2aa7';

Topics

Core Operations

Agent & Fee Management

Scallop Lending (Idle Funds)

  • Scallop Lending - Single MoveCall scallop_supply<T> / scallop_redeem<T> against Scallop Market; yield-fee math on the interest portion; exit only via scallop_redeem<T>.

Kai SAV Lending (Idle Funds)

  • Kai SAV Lending - Single MoveCall kai_supply<T, YT> / kai_redeem<T, ST, YT> against Kai Vault<T, YT>; shared yield-fee math; exit only via kai_redeem<T, ST, YT>.

Web Development & Queries

Reference

  • Constants - Package IDs, object IDs, token addresses

Calculations

For liquidity calculations, bin price math, position management, and fee calculations, use the cdpm-calculation skill with the Cetus DLMM SDK:

import { BinUtils, FeeUtils } from '@cetusprotocol/dlmm-sdk/utils'

// Common calculations
const qPrice = BinUtils.getQPriceFromId(binId, binStep)
const liquidity = BinUtils.getLiquidity(amountA, amountB, qPrice)
const binId = BinUtils.getBinIdFromPrice(price, binStep, true, decimalA, decimalB)

See cdpm-calculation skill for complete reference with formulas, examples, and best practices.

Security Checklist

Before authorizing an agent:

async function securityChecklist(
  client: SuiGrpcClient,
  pmId: string,
  agentAddress: string
) {
  // 1. Verify you are the owner
  const { response: pm } = await client.getObject({ id: pmId, include: { content: true } });
  const owner = pm?.content?.fields?.owner;

  // 2. Check agent is not already authorized
  const agents = await getAuthorizedAgents(client, pmId);
  const isAuthorized = agents.includes(agentAddress);

  return { owner, isAuthorized };
}

Error Handling

Common errors and solutions:

try {
  const result = await createPositionSmart(/* ... */);
} catch (e) {
  if (e.message.includes('ENotOwner')) {              // 1001
    console.error('Only the owner can perform this operation');
  } else if (e.message.includes('ENotAllow')) {       // 1002
    console.error('Caller not authorized (not owner / agent / whitelisted protocol with no agents set)');
  } else if (e.message.includes('EInvalidFeeRate')) { // 1003
    console.error('Invalid fee rate configuration (cap is 50% / 5000 bp)');
  } else if (e.message.includes('ELendingNotEmpty')) {// 1004
    console.error('pm.lending is non-empty — redeem every Scallop AND Kai vault entry before user_close_pm');
  } else if (e.message.includes('ENoSuchVault')) {    // 1005
    console.error('No ScallopVault<T> or KaiVault<T, YT> entry in pm.lending for the requested key');
  } else if (e.message.includes('ENoSuchBalance')) {  // 1006
    console.error('withdraw_from_balance / withdraw_from_fee called for an absent type key');
  } else if (e.message.includes('EPositionHasRewards')) { // 1007
    console.error('user_close_pm aborted: collect every reward type on the pool with user_collect_reward<A,B,R> first');
  } else if (e.message.includes('EBalanceNotEmpty')) { // 1008
    console.error('user_close_pm aborted: drain every pm.balance[T] with user_remove_liquidity_from_balance<T>(u64::MAX)');
  } else if (e.message.includes('EFeeNotEmpty')) {    // 1009
    console.error('user_close_pm aborted: drain every pm.fee[T] with user_withdraw_fee<T>(u64::MAX)');
  } else {
    console.error('Transaction failed:', e);
  }
}

End-to-End Workflow

For the full close-PM flow (collect rewards → redeem every lending entry → drain pm.balance / pm.fee → batched transferObjectsuser_close_pm), see reference/workflows.md § Close Position Safely.

What ships with it: 9 files

63.4 KB alongside SKILL.md

Keep looking

Skills are one crate of 325,949. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.