npm package: @ramestta/staking-sdk
Description: Ramestta Staking SDK - Validator staking, delegation, and rewards management
Author: Ramestta Team
Latest version: 1.0.1

# @ramestta/staking-sdk

Official Ramestta Staking SDK for validator staking, delegation, and rewards management.

## Installation

```bash
npm install @ramestta/staking-sdk
# or
yarn add @ramestta/staking-sdk
```

## Quick Start

### Read-Only Client (No Signer Required)

```typescript
import { createStakingClient, formatRama } from '@ramestta/staking-sdk';

// Create client
const client = createStakingClient('https://polygon-rpc.com');

// Get staking stats
const stats = await client.getStakingStats();
console.log('Total Staked:', formatRama(stats.totalStaked), 'RAMA');
console.log('Total Validators:', stats.totalValidators);

// Get all validators
const validators = await client.getValidators();
validators.forEach(v => {
  console.log(`Validator #${v.id}: ${formatRama(v.amount)} RAMA staked`);
});

// Get user's delegations
const delegations = await client.getUserDelegations('0xYourAddress');
delegations.forEach(d => {
  console.log(`Validator #${d.validatorId}: ${formatRama(d.stake)} staked, ${formatRama(d.rewards)} rewards`);
});
```

### With Signer (For Transactions)

```typescript
import { createStakingClientFromPrivateKey, parseRama } from '@ramestta/staking-sdk';

// Create client with private key
const client = createStakingClientFromPrivateKey(
  'your-private-key',
  'https://polygon-rpc.com'
);

// Approve RAMA for staking (one-time)
const approveTx = await client.approveMax();
await approveTx.wait();

// Delegate to validator #1
const amount = parseRama('100'); // 100 RAMA
const delegateTx = await client.delegate(1, amount);
await delegateTx.wait();
console.log('Delegated!', delegateTx.hash);

// Claim rewards
const rewardsTx = await client.claimRewards(1);
await rewardsTx.wait();

// Restake (compound) rewards
const restakeTx = await client.restake(1);
await restakeTx.wait();
```

## API Reference

### StakingClient

#### Constructor

```typescript
const client = new StakingClient({
  provider: ethersProvider,
  signer?: ethersSigner,  // Optional, required for transactions
  network?: 'mainnet' | 'testnet'
});
```

#### Read Methods

| Method | Description |
|--------|-------------|
| `getStakingStats()` | Get overall staking statistics |
| `getValidator(id)` | Get validator info by ID |
| `getValidators(limit?)` | Get list of active validators |
| `getValidatorContractAddress(id)` | Get ValidatorShare contract address |
| `getDelegatorInfo(validatorId, address)` | Get delegation info for a user |
| `getUserDelegations(address)` | Get all delegations for a user |
| `getUnbondInfo(validatorId, address, nonce?)` | Get pending unbond info |
| `getRamaBalance(address)` | Get RAMA token balance |
| `getAllowance(address)` | Get RAMA allowance for StakeManager |
| `isDelegationEnabled(validatorId)` | Check if validator accepts delegations |
| `getCurrentEpoch()` | Get current staking epoch |
| `isUnbondClaimable(validatorId, address, nonce?)` | Check if unbond can be claimed |
| `calculateShares(validatorId, amount)` | Calculate shares for stake amount |
| `calculateStake(validatorId, shares)` | Calculate stake for share amount |

#### Write Methods (Require Signer)

| Method | Description |
|--------|-------------|
| `approve(amount)` | Approve RAMA tokens for staking |
| `approveMax()` | Approve unlimited RAMA tokens |
| `delegate(validatorId, amount, minShares?)` | Delegate RAMA to a validator |
| `unstake(validatorId, amount, maxShares?)` | Initiate unstaking |
| `claimUnstaked(validatorId, unbondNonce)` | Claim unstaked tokens after delay |
| `claimRewards(validatorId)` | Claim accumulated rewards |
| `restake(validatorId)` | Restake (compound) rewards |

### Factory Functions

```typescript
// Read-only client
createStakingClient(providerOrUrl)

// Client with signer
createStakingClientWithSigner(signer, provider?)

// Client from private key
createStakingClientFromPrivateKey(privateKey, providerOrUrl?)
```

### Utility Functions

```typescript
// Format BigNumber to RAMA string
formatRama(amount: BigNumber): string

// Parse RAMA string to BigNumber
parseRama(amount: string): BigNumber

// Calculate APY from rewards
calculateAPY(rewards, stake, daysElapsed): number
```

## Types

```typescript
interface ValidatorInfo {
  id: number;
  owner: string;
  signer: string;
  commissionRate: number;
  amount: BigNumber;
  activationEpoch: number;
  deactivationEpoch: number;
  jailTime: number;
  status: ValidatorStatus;
  contractAddress: string;
  delegatedAmount: BigNumber;
  selfStake: BigNumber;
}

interface DelegatorInfo {
  validatorId: number;
  shares: BigNumber;
  stake: BigNumber;
  rewards: BigNumber;
  unbondNonce: number;
}

interface StakingStats {
  totalStaked: BigNumber;
  totalValidators: number;
  activeValidators: number;
  currentEpoch: number;
  withdrawalDelay: number;
}

enum ValidatorStatus {
  Active = 'Active',
  Locked = 'Locked',
  Unstaking = 'Unstaking',
  Unstaked = 'Unstaked',
}
```

## Example: Full Staking Flow

```typescript
import { 
  createStakingClientFromPrivateKey, 
  parseRama, 
  formatRama 
} from '@ramestta/staking-sdk';

async function stakingExample() {
  const client = createStakingClientFromPrivateKey(
    process.env.PRIVATE_KEY!,
    'https://polygon-rpc.com'
  );

  const myAddress = '0x...';
  const validatorId = 1;

  // 1. Check balance
  const balance = await client.getRamaBalance(myAddress);
  console.log('Balance:', formatRama(balance), 'RAMA');

  // 2. Approve tokens (if needed)
  const allowance = await client.getAllowance(myAddress);
  if (allowance.lt(parseRama('1000'))) {
    console.log('Approving RAMA...');
    const tx = await client.approveMax();
    await tx.wait();
  }

  // 3. Delegate
  console.log('Delegating...');
  const delegateTx = await client.delegate(validatorId, parseRama('100'));
  await delegateTx.wait();

  // 4. Check delegation
  const delegation = await client.getDelegatorInfo(validatorId, myAddress);
  console.log('Staked:', formatRama(delegation.stake));
  console.log('Rewards:', formatRama(delegation.rewards));

  // 5. Claim rewards (after some time)
  if (delegation.rewards.gt(0)) {
    const claimTx = await client.claimRewards(validatorId);
    await claimTx.wait();
    console.log('Rewards claimed!');
  }

  // 6. Unstake (when ready to exit)
  const unstakeTx = await client.unstake(validatorId, parseRama('50'));
  await unstakeTx.wait();
  console.log('Unstaking initiated...');

  // 7. Wait for withdrawal delay (~80 epochs)
  // Then claim unstaked tokens
  const unbondNonce = delegation.unbondNonce + 1;
  const isClaimable = await client.isUnbondClaimable(validatorId, myAddress, unbondNonce);
  
  if (isClaimable) {
    const claimUnstakedTx = await client.claimUnstaked(validatorId, unbondNonce);
    await claimUnstakedTx.wait();
    console.log('Unstaked tokens claimed!');
  }
}
```

## Contract Addresses

The SDK uses these contract addresses on Polygon (L2):

| Contract | Address |
|----------|---------|
| StakeManager | `0xc032E6C4D196CBf4CceddbA1d18661F7DD57f659` |
| StakingInfo | `0x06FB27902B00a4CCF3850783dAB763364BF8654A` |
| StakingNFT | `0x108E6890F660Dbe4f3554DC43769B4D734555981` |
| RamaToken | `0x55a5CC06801bBa4C030568f1A7ee1c753FDcbe36` |

## License

MIT © Ramestta Team