@nemoprotocol/points-sdk
Version:
## Table of Contents
956 lines (807 loc) • 22.4 kB
Markdown
# NEMO Protocol SDK Documentation
## Table of Contents
1. [Overview](#overview)
2. [Installation](#installation)
3. [Core Features](#core-features)
4. [API Reference](#api-reference)
5. [Type Definitions](#type-definitions)
---
## Overview
The NEMO Protocol SDK provides core functionality for querying user positions, calculating market values, and managing yield distributions in the NEMO protocol.
### Key Features
- **Position Query**: Query all positions for any Sui address
- **Holder Statistics**: Get PT, YT, LP holder counts and position quantities
- **Market Value Calculation**: Calculate current market values in SUI or underlying assets
- **Yield Management**: Query and claim available yield
- **Pool Information**: Get comprehensive pool statistics and market data
- **Liquidity Management**: Add and remove liquidity positions with transaction execution
---
## Installation
### Package Installation
```bash
npm install @nemoprotocol/contract-sdk
# or
yarn add @nemoprotocol/contract-sdk
# or
pnpm add @nemoprotocol/contract-sdk
```
### Environment Configuration
```bash
# Build-time configuration
API_BASE_URL=https://api.nemoprotocol.com npm run build
# Development configuration (.env file)
API_BASE_URL=https://api.nemoprotocol.com
```
### SDK Initialization
```typescript
import { PositionQuery, PoolQuery, AddLiquidityAction } from '@nemoprotocol/contract-sdk'
import { SuiClient, getFullnodeUrl } from '@mysten/sui/client'
// Initialize query classes
const positionQuery = new PositionQuery({
network: 'mainnet', // or 'testnet', 'devnet', 'localnet'
rpcUrl: 'https://sui-mainnet.mystenlabs.com' // optional
})
const poolQuery = new PoolQuery()
// Initialize action class for transaction execution
const suiClient = new SuiClient({ url: getFullnodeUrl('mainnet') })
const liquidityAction = new AddLiquidityAction({
suiClient,
privateKeyHex: 'your-private-key-hex' // without 0x prefix or with it
})
```
---
## Core Features
### 1. Position Query
Query all positions for a specific Sui address in the NEMO protocol.
#### LP Position Query
```typescript
const lpPositions = await positionQuery.queryLpPositions({
address: '0x...', // user address
positionTypes: [
'0x...::market::LpPosition<0x...::coin::SUI>',
'0x...::market::LpPosition<0x...::coin::USDC>'
],
maturity: '2024-12-31', // optional filter
marketStateId: '0x...' // optional filter
})
// Response format:
// [
// {
// id: { id: '0x...' },
// name: 'LP-SUI-2024-12-31',
// expiry: '2024-12-31',
// lpAmount: '1000000000',
// description: 'LP position for SUI',
// marketStateId: '0x...'
// }
// ]
```
#### PY Position Query
```typescript
const pyPositions = await positionQuery.queryPyPositions({
address: '0x...', // user address
positionTypes: [
'0x...::py_state::PyState<0x...::coin::SUI>',
'0x...::py_state::PyState<0x...::coin::USDC>'
],
maturity: '2024-12-31', // optional filter
pyStateId: '0x...' // optional filter
})
// Response format:
// [
// {
// id: '0x...',
// maturity: '2024-12-31',
// ptBalance: '500000000',
// ytBalance: '300000000',
// pyStateId: '0x...'
// }
// ]
```
### 2. Holder Statistics
Get users holding different asset types (PT, YT, LP) and their position quantities.
#### PT/YT Holder Count
```typescript
const holdersCount = await positionQuery.queryPyPositionHoldersCount({
positionTypes: [
'0x...::py_state::PyState<0x...::coin::SUI>',
'0x...::py_state::PyState<0x...::coin::USDC>'
],
maturity: '2024-12-31',
pyStateId: '0x...',
pageSize: 50 // optional
})
console.log('PT Holders:', holdersCount.ptHolders)
console.log('YT Holders:', holdersCount.ytHolders)
console.log('Total Holders:', holdersCount.totalHolders)
console.log('Holders by Type:', holdersCount.holdersByType)
console.log('Total Positions:', holdersCount.totalPositions)
```
#### LP Holder Count
```typescript
const lpHoldersCount = await positionQuery.queryLpPositionHoldersCount({
positionTypes: [
'0x...::market::LpPosition<0x...::coin::SUI>',
'0x...::market::LpPosition<0x...::coin::USDC>'
],
maturity: '2024-12-31',
marketStateId: '0x...',
pageSize: 50 // optional
})
console.log('LP Holders:', lpHoldersCount.totalHolders)
console.log('Holders by Type:', lpHoldersCount.holdersByType)
console.log('Total Positions:', lpHoldersCount.totalPositions)
```
### 3. Market Value Calculation
Calculate and display current market values of user positions (priced in SUI or underlying assets).
#### Yield Query
```typescript
const yieldResult = await positionQuery.queryYield({
address: '0x...',
ytBalance: '1000000000',
pyPositions: [
{
id: '0x...',
maturity: '2024-12-31',
ptBalance: '500000000',
ytBalance: '300000000',
pyStateId: '0x...'
}
],
receivingType: 'sy', // or 'underlying'
config: {
nemoContractId: '0x...',
version: '1.0.0',
coinType: '0x...::coin::SUI',
pyStateId: '0x...',
syCoinType: '0x...::sy_coin::SyCoin<0x...::coin::SUI>',
yieldFactoryConfigId: '0x...',
marketStateId: '0x...',
underlyingCoinType: '0x...::coin::SUI',
underlyingProtocol: 'Scallop',
priceOracleConfigId: '0x...',
oraclePackageId: '0x...',
oracleTicket: '0x...',
oracleVoucherPackageId: '0x...'
}
})
console.log('Output Value:', yieldResult.outputValue)
console.log('Output Amount:', yieldResult.outputAmount)
```
### 4. Rewards query
Query and claim available yield rewards in the NEMO protocol.
```typescript
// Query rewards for multiple reward metrics
const rewards = await positionQuery.queryRewards({
address: '0x...', // user address
config: {
nemoContractId: '0x...',
version: '0x...',
marketStateId: '0x...',
// other required config fields
},
lpPositions: [
{
id: { id: '0x...' },
name: 'LP-SUI-2024-12-31',
expiry: '2024-12-31',
lpAmount: '1000000000',
description: 'LP position for SUI',
marketStateId: '0x...'
}
],
rewardMetrics: [
{
tokenType: '0x...::coin::SUI',
syCoinType: '0x...::sy_coin::SyCoin<0x...::coin::SUI>',
tokenLogo: 'https://...',
dailyEmission: '1000000000',
tokenPrice: '1.23',
tokenName: 'SUI',
decimal: '9'
},
{
tokenType: '0x...::coin::USDC',
syCoinType: '0x...::sy_coin::SyCoin<0x...::coin::USDC>',
tokenLogo: 'https://...',
dailyEmission: '500000000',
tokenPrice: '1.00',
tokenName: 'USDC',
decimal: '6'
}
]
});
// Response format:
// [
// {
// coinType: '0x...::coin::SUI',
// coinName: 'SUI',
// amount: '1.234567890'
// },
// {
// coinType: '0x...::coin::USDC',
// coinName: 'USDC',
// amount: '100.123456'
// }
// ]
```
### 5. Pool Information
Query basic information and statistics for different pools.
#### Pool Query
```typescript
const pools = await poolQuery.queryPools()
// Response format:
// [
// {
// id: '0x...',
// tvl: '1000000000000',
// tvlRateChange: '5.2',
// coinLogo: 'https://...',
// maturity: '2024-12-31',
// startTime: '2024-01-01',
// coinName: 'SUI',
// coinType: '0x...::coin::SUI',
// ptTokenType: '0x...::pt_coin::PtCoin<0x...::coin::SUI>',
// nemoContractId: '0x...',
// boost: '1.5',
// provider: 'Scallop',
// providerLogo: 'https://...',
// cap: '10000000000000',
// marketStateId: '0x...',
// syCoinType: '0x...::sy_coin::SyCoin<0x...::coin::SUI>',
// underlyingCoinType: '0x...::coin::SUI',
// providerMarket: '0x...',
// providerVersion: '1.0.0',
// priceOracleConfigId: '0x...',
// decimal: '9',
// underlyingApy: '8.5',
// coinPrice: '1.2',
// underlyingPrice: '1.2',
// pyStateId: '0x...',
// syStateId: '0x...',
// conversionRate: '1.0',
// marketFactoryConfigId: '0x...',
// swapFeeForLpHolder: '0.003',
// underlyingCoinName: 'SUI',
// underlyingCoinLogo: 'https://...',
// version: '1.0.0',
// perPoints: '1000000',
// oraclePackageId: '0x...',
// oracleTicket: '0x...',
// oracleVoucherPackageId: '0x...',
// yieldTokenType: '0x...::yt_coin::YtCoin<0x...::coin::SUI>',
// tokenRegistryState: '0x...',
// ptPrice: '0.95',
// ptTvl: '500000000000',
// syTvl: '500000000000',
// marketState: {
// marketCap: '1000000000000',
// totalSy: '500000000000',
// lpSupply: '1000000000000',
// totalPt: '500000000000',
// rewardMetrics: [...]
// },
// scaledPtApy: '12.5',
// scaledUnderlyingApy: '8.5',
// feeApy: '2.0',
// sevenAvgUnderlyingApy: '8.2',
// sevenAvgUnderlyingApyRateChange: '0.3',
// ytPrice: '0.15',
// lpPrice: '1.0',
// ytTokenLogo: 'https://...',
// ptTokenLogo: 'https://...',
// lpTokenLogo: 'https://...',
// ytReward: '150000000',
// underlyingProtocol: 'Scallop',
// yieldFactoryConfigId: '0x...',
// pyPositionTypeList: ['0x...::py_state::PyState<0x...::coin::SUI>'],
// marketPositionTypeList: ['0x...::market::LpPosition<0x...::coin::SUI>'],
// lpPriceRateChange: '2.1',
// ptPriceRateChange: '-1.5',
// ytPriceRateChange: '5.2',
// incentiveApy: '3.0',
// incentives: [...],
// poolApy: '15.5',
// tradeStatus: 'active'
// }
// ]
```
### 6. Liquidity Management
Execute liquidity-related transactions including adding and removing liquidity positions.
#### Add Liquidity
```typescript
// Add liquidity to a pool
const addResult = await liquidityAction.addLiquidity({
decimal: 9,
addType: 'SY', // 'SY' | 'TOKEN' | 'PT'
slippage: '0.01', // 1% slippage
lpValue: '1000000000', // Amount in base units
coinType: '0x...::coin::SUI',
conversionRate: '1.0',
addValue: '1000000000',
tokenType: 0, // 0 for SY, 1 for TOKEN, 2 for PT
action: 'mint', // 'mint' | 'swap'
// Configuration objects
coinConfig: {
nemoContractId: '0x...',
version: '1.0.0',
coinType: '0x...::coin::SUI',
pyStateId: '0x...',
syCoinType: '0x...::sy_coin::SyCoin<0x...::coin::SUI>',
yieldFactoryConfigId: '0x...',
marketStateId: '0x...',
underlyingCoinType: '0x...::coin::SUI',
underlyingProtocol: 'Scallop',
priceOracleConfigId: '0x...',
oraclePackageId: '0x...',
oracleTicket: '0x...',
oracleVoucherPackageId: '0x...'
},
marketStateData: {
// Market state object from pool query
},
coinData: [
{
coinType: '0x...::coin::SUI',
balance: '1000000000',
coinObjectId: '0x...'
}
],
pyPositionData: {
// PY position data object
},
lpPositions: [
{
id: { id: '0x...' },
name: 'LP-SUI-2024-12-31',
expiry: '2024-12-31',
lpAmount: '1000000000',
description: 'LP position for SUI',
marketStateId: '0x...'
}
],
// Optional parameters
vaultId: '0x...', // optional
insufficientBalance: false
})
// Check result
if (addResult.success) {
console.log('Transaction successful:', addResult.transactionHash)
console.log('Transaction data:', addResult.data)
} else {
console.error('Transaction failed:', addResult.error)
}
```
#### Remove Liquidity
```typescript
// Remove liquidity from a position
const removeResult = await liquidityAction.removeLiquidity({
lpAmount: '500000000', // Amount to remove
slippage: '0.01', // 1% slippage
ytBalance: '300000000',
action: 'swap', // 'swap' | 'redeem'
receivingType: 'underlying', // 'underlying' | 'sy'
// Configuration objects
coinConfig: {
nemoContractId: '0x...',
version: '1.0.0',
coinType: '0x...::coin::SUI',
pyStateId: '0x...',
syCoinType: '0x...::sy_coin::SyCoin<0x...::coin::SUI>',
yieldFactoryConfigId: '0x...',
marketStateId: '0x...',
underlyingCoinType: '0x...::coin::SUI',
underlyingProtocol: 'Scallop',
priceOracleConfigId: '0x...',
oraclePackageId: '0x...',
oracleTicket: '0x...',
oracleVoucherPackageId: '0x...'
},
lpPositions: [
{
id: { id: '0x...' },
name: 'LP-SUI-2024-12-31',
expiry: '2024-12-31',
lpAmount: '1000000000',
description: 'LP position for SUI',
marketStateId: '0x...'
}
],
pyPositions: [
{
id: '0x...',
maturity: '2024-12-31',
ptBalance: '500000000',
ytBalance: '300000000',
pyStateId: '0x...'
}
],
marketState: {
marketCap: '1000000000000',
totalSy: '500000000000',
lpSupply: '1000000000000',
totalPt: '500000000000',
rewardMetrics: []
},
// Optional parameters
vaultId: '0x...', // optional
minSyOut: '480000000', // minimum SY output
ptCoins: [
{
coinType: '0x...::pt_coin::PtCoin<0x...::coin::SUI>',
balance: '500000000',
coinObjectId: '0x...'
}
],
minValue: '480000000',
isSwapPt: false
})
// Check result
if (removeResult.success) {
console.log('Transaction successful:', removeResult.transactionHash)
console.log('Transaction data:', removeResult.data)
} else {
console.error('Transaction failed:', removeResult.error)
}
```
#### Error Handling
```typescript
try {
const result = await liquidityAction.addLiquidity(params)
if (!result.success) {
// Handle business logic errors
console.error('Business error:', result.error)
// Common error scenarios:
// - Insufficient balance
// - Slippage too high
// - Invalid parameters
// - Market not active
}
} catch (error) {
// Handle unexpected errors
console.error('Unexpected error:', error)
}
```
#### Utility Methods
```typescript
// Get current wallet address
const walletAddress = liquidityAction.getAddress()
console.log('Wallet address:', walletAddress)
// Get Sui client instance
const client = liquidityAction.getSuiClient()
```
---
## API Reference
### PositionQuery Class
#### Constructor
```typescript
new PositionQuery(config: PositionQueryConfig)
```
**Parameters:**
- `config.network`: Network type ('mainnet' | 'testnet' | 'devnet' | 'localnet')
- `config.rpcUrl`: Custom RPC URL (optional)
#### Methods
##### queryLpPositions()
```typescript
async queryLpPositions(options: {
address: string;
positionTypes: string[];
maturity?: string;
marketStateId?: string;
}): Promise<LpPosition[]>
```
##### queryPyPositions()
```typescript
async queryPyPositions(options: {
address: string;
positionTypes: string[];
maturity?: string;
pyStateId?: string;
}): Promise<PyPosition[]>
```
##### queryPyPositionHoldersCount()
```typescript
async queryPyPositionHoldersCount(options: {
positionTypes: string[];
maturity?: string;
pyStateId?: string;
pageSize?: number;
}): Promise<{
ptHolders: number;
ytHolders: number;
totalHolders: number;
holdersByType: Record<string, { ptHolders: number; ytHolders: number }>;
totalPositions: number;
}>
```
##### queryLpPositionHoldersCount()
```typescript
async queryLpPositionHoldersCount(options: {
positionTypes: string[];
maturity?: string;
marketStateId?: string;
pageSize?: number;
}): Promise<{
totalHolders: number;
holdersByType: Record<string, number>;
totalPositions: number;
}>
```
##### queryYield()
```typescript
async queryYield(params: QueryYieldParams): Promise<{
outputValue: string;
outputAmount: string;
}>
```
### PoolQuery Class
#### Constructor
```typescript
new PoolQuery()
```
#### Methods
##### queryPools()
```typescript
async queryPools(): Promise<PortfolioItem[]>
```
### AddLiquidityAction Class
#### Constructor
```typescript
new AddLiquidityAction(config: AddLiquidityActionConfig)
```
**Parameters:**
- `config.suiClient`: SuiClient instance for blockchain interaction
- `config.privateKeyHex`: Private key in hexadecimal format (with or without 0x prefix)
#### Methods
##### addLiquidity()
```typescript
async addLiquidity(params: AddLiquidityActionParams): Promise<AddLiquidityActionResult>
```
**Parameters:**
- `params.decimal`: Number of decimal places for the token
- `params.addType`: Type of asset to add ('SY' | 'TOKEN' | 'PT')
- `params.slippage`: Maximum slippage tolerance (e.g., '0.01' for 1%)
- `params.lpValue`: LP value amount in base units
- `params.coinType`: Coin type identifier
- `params.conversionRate`: Conversion rate for the operation
- `params.addValue`: Amount to add in base units
- `params.tokenType`: Token type (0 for SY, 1 for TOKEN, 2 for PT)
- `params.action`: Action type ('mint' | 'swap')
- `params.coinConfig`: Coin configuration object
- `params.marketStateData`: Market state data
- `params.coinData`: Array of coin data objects
- `params.pyPositionData`: PY position data
- `params.lpPositions`: Array of LP positions
- `params.vaultId`: Optional vault identifier
- `params.insufficientBalance`: Optional insufficient balance flag
##### removeLiquidity()
```typescript
async removeLiquidity(params: RemoveLiquidityActionParams): Promise<AddLiquidityActionResult>
```
**Parameters:**
- `params.lpAmount`: Amount of LP tokens to remove
- `params.slippage`: Maximum slippage tolerance
- `params.ytBalance`: YT balance amount
- `params.action`: Action type ('swap' | 'redeem')
- `params.receivingType`: Type of asset to receive ('underlying' | 'sy')
- `params.coinConfig`: Coin configuration object
- `params.lpPositions`: Array of LP positions
- `params.pyPositions`: Array of PY positions
- `params.marketState`: Market state object
- `params.vaultId`: Optional vault identifier
- `params.minSyOut`: Optional minimum SY output
- `params.ptCoins`: Optional PT coins array
- `params.minValue`: Optional minimum value
- `params.isSwapPt`: Optional PT swap flag
##### execute()
```typescript
async execute(params: AddLiquidityActionParams): Promise<AddLiquidityActionResult>
```
Alias for `addLiquidity()` method for backward compatibility.
##### getAddress()
```typescript
getAddress(): string
```
Returns the wallet address associated with the private key.
##### getSuiClient()
```typescript
getSuiClient(): SuiClient
```
Returns the SuiClient instance used for blockchain interactions.
---
## Type Definitions
### PositionQueryConfig
```typescript
interface PositionQueryConfig {
network?: 'mainnet' | 'testnet' | 'devnet' | 'localnet';
rpcUrl?: string;
}
```
### LpPosition
```typescript
interface LpPosition {
id: { id: string };
name: string;
expiry: string;
lpAmount: string;
description: string;
marketStateId: string;
}
```
### PyPosition
```typescript
interface PyPosition {
id: string;
maturity: string;
ptBalance: string;
ytBalance: string;
pyStateId: string;
}
```
### PortfolioItem
```typescript
interface PortfolioItem {
id: string;
tvl: string;
tvlRateChange: string;
coinLogo: string;
maturity: string;
startTime: string;
coinName: string;
coinType: string;
ptTokenType: string;
nemoContractId: string;
boost: string;
provider: string;
providerLogo: string;
cap: string;
marketStateId: string;
syCoinType: string;
underlyingCoinType: string;
providerMarket: string;
providerVersion: string;
priceOracleConfigId: string;
decimal: string;
underlyingApy: string;
coinPrice: string;
underlyingPrice: string;
pyStateId: string;
syStateId: string;
conversionRate: string;
marketFactoryConfigId: string;
swapFeeForLpHolder: string;
underlyingCoinName: string;
underlyingCoinLogo: string;
version: string;
perPoints: string;
oraclePackageId: string;
oracleTicket: string;
oracleVoucherPackageId: string;
yieldTokenType: string;
tokenRegistryState: string;
ptPrice: string;
ptTvl: string;
syTvl: string;
marketState: MarketState;
scaledPtApy: string;
scaledUnderlyingApy: string;
feeApy: string;
sevenAvgUnderlyingApy: string;
sevenAvgUnderlyingApyRateChange: string;
ytPrice: string;
lpPrice: string;
ytTokenLogo: string;
ptTokenLogo: string;
lpTokenLogo: string;
ytReward: string;
underlyingProtocol: string;
yieldFactoryConfigId: string;
pyPositionTypeList: string[];
marketPositionTypeList: string[];
lpPriceRateChange: string;
ptPriceRateChange: string;
ytPriceRateChange: string;
incentiveApy: string;
incentives: Incentive[];
poolApy: string;
tradeStatus: string;
}
```
### AddLiquidityActionConfig
```typescript
interface AddLiquidityActionConfig {
suiClient: SuiClient;
privateKeyHex: string; // hexadecimal private key (with or without 0x prefix)
}
```
### AddLiquidityActionParams
```typescript
interface AddLiquidityActionParams {
// Basic parameters
decimal: number;
addType: string;
slippage: string;
lpValue: string;
coinType: string;
conversionRate: string;
addValue: string;
tokenType: number;
action: string; // "mint" | "swap"
// Configuration and data
coinConfig: CoinConfig;
marketStateData: any;
coinData: CoinData[];
pyPositionData: any;
lpPositions: LpPosition[];
// Optional parameters
vaultId?: string;
insufficientBalance?: boolean;
}
```
### RemoveLiquidityActionParams
```typescript
interface RemoveLiquidityActionParams {
lpAmount: string;
slippage: string;
vaultId?: string;
minSyOut?: string;
ytBalance: string;
ptCoins?: CoinData[];
coinConfig: CoinConfig;
action: "swap" | "redeem";
lpPositions: LpPosition[];
pyPositions: any[];
minValue?: string | number;
isSwapPt?: boolean;
receivingType?: "underlying" | "sy";
marketState: MarketState;
}
```
### AddLiquidityActionResult
```typescript
interface AddLiquidityActionResult {
success: boolean;
transactionHash?: string;
error?: string;
data?: any;
}
```
### CoinConfig
```typescript
interface CoinConfig {
nemoContractId: string;
version: string;
coinType: string;
pyStateId: string;
syCoinType: string;
yieldFactoryConfigId: string;
marketStateId: string;
underlyingCoinType: string;
underlyingProtocol: string;
priceOracleConfigId: string;
oraclePackageId: string;
oracleTicket: string;
oracleVoucherPackageId: string;
}
```
### CoinData
```typescript
interface CoinData {
coinType: string;
balance: string;
coinObjectId: string;
}
```
### MarketState
```typescript
interface MarketState {
marketCap: string;
totalSy: string;
lpSupply: string;
totalPt: string;
rewardMetrics: any[];
}
```
---
**Document Version**: 1.1
**Last Updated**: [Date]