agentsclimarketplace

Cdpm user sdk

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

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.

What its author says it does

Copied from the file, not written here

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.

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 328,083. 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.