npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

zende-sdk

v0.1.3

Published

TypeScript SDK for the Zendetsu escrow protocol on Solana

Readme

zende-sdk

TypeScript SDK for the Zendetsu escrow protocol on Solana.

Trustless escrow for Solana developers. Lock funds, set conditions, release on-chain. No middlemen, no custodians, no trust required.

Install

npm install zende-sdk

Quick Start

import { ZendetsuClient, solToLamports } from "zende-sdk";
import { AnchorProvider } from "@coral-xyz/anchor";

const provider = AnchorProvider.env();

// English error messages (default)
const client = new ZendetsuClient(provider);

// Nigerian Pidgin error messages
const client = new ZendetsuClient(provider, { lang: "pidgin" });

The IDL is bundled inside the SDK. You do not need to fetch or import it separately.

Error Messages

Every method returns a clean, human-readable error message when something goes wrong. Pass lang: "pidgin" to get Nigerian Pidgin error messages instead of English.

// English (default)
const client = new ZendetsuClient(provider);

try {
  await client.confirmRelease(params);
} catch (err) {
  console.error(err.message);
  // "Escrow is frozen due to an active dispute"
}

// Pidgin
const client = new ZendetsuClient(provider, { lang: "pidgin" });

try {
  await client.confirmRelease(params);
} catch (err) {
  console.error(err.message);
  // "The escrow don freeze, dispute dey ground, wait for resolution"
}

Create an Escrow

import BN from "bn.js";

const { escrowId, signature } = await client.createEscrow({
  amount: solToLamports(1),        // 1 SOL to recipient
  feeAmount: solToLamports(0.01),  // 0.01 SOL platform fee
  mode: { simple: {} },
  releaseCondition: { majority: {} },
  speed: { standard: {} },
  recipient: recipientPublicKey,
  treasury: treasuryPublicKey,
});

// Save escrowId — you need it for every subsequent call
console.log("Escrow created:", signature);

Confirm and Release

Both parties call confirmRelease. When both confirm, SOL releases instantly.

// Depositor confirms
await client.confirmRelease({
  escrowId,
  depositor: depositorPublicKey,
  recipient: recipientPublicKey,
  treasury: treasuryPublicKey,
});

// Recipient confirms — triggers instant release
await client.confirmRelease({
  escrowId,
  depositor: depositorPublicKey,
  recipient: recipientPublicKey,
  treasury: treasuryPublicKey,
});

Claim After Timelock

await client.claimRelease({
  escrowId,
  depositor: depositorPublicKey,
  treasury: treasuryPublicKey,
});

Cancel (Before Recipient Joins)

await client.cancelEscrow({
  escrowId,
  recipient: recipientPublicKey,
});

Milestone Escrow

const { escrowId } = await client.createEscrow({
  amount: solToLamports(3),
  feeAmount: solToLamports(0.03),
  mode: { milestone: {} },
  releaseCondition: { majority: {} },
  speed: { standard: {} },
  recipient: recipientPublicKey,
  treasury: treasuryPublicKey,
  milestones: [
    { label: "Design mockups", percentage: 30, deadline: new BN(Math.floor(Date.now() / 1000) + 86400 * 7) },
    { label: "Frontend build", percentage: 40, deadline: new BN(Math.floor(Date.now() / 1000) + 86400 * 21) },
    { label: "Final delivery", percentage: 30, deadline: new BN(Math.floor(Date.now() / 1000) + 86400 * 30) },
  ],
});

// Approve milestone 0 — releases 30% of funds
await client.approveMilestone({
  escrowId,
  depositor: depositorPublicKey,
  recipient: recipientPublicKey,
  treasury: treasuryPublicKey,
  milestoneIndex: 0,
});

// Reject milestone — 3 rejections auto-escalates to dispute
await client.rejectMilestone({
  escrowId,
  depositor: depositorPublicKey,
  milestoneIndex: 1,
});

Timed Release

const releaseAt = new BN(Math.floor(Date.now() / 1000) + 86400 * 30); // 30 days

const { escrowId } = await client.createEscrow({
  amount: solToLamports(2),
  feeAmount: solToLamports(0.02),
  mode: { timed: {} },
  releaseCondition: { majority: {} },
  speed: { standard: {} },
  releaseAt,
  recipient: recipientPublicKey,
  treasury: treasuryPublicKey,
});

Disputes

// Raise a dispute — freezes the escrow
await client.disputeEscrow({
  escrowId,
  depositor: depositorPublicKey,
});

// Authority resolves — full to recipient
await client.resolveDispute({
  escrowId,
  depositor: depositorPublicKey,
  recipient: recipientPublicKey,
  treasury: treasuryPublicKey,
  verdict: { recipient: {} },
});

// Authority resolves — 60% to recipient, 40% back to depositor
await client.resolveDispute({
  escrowId,
  depositor: depositorPublicKey,
  recipient: recipientPublicKey,
  treasury: treasuryPublicKey,
  verdict: { partial: { percentage: 60 } },
});

Keep Alive (Ping)

await client.ping({
  escrowId,
  depositor: depositorPublicKey,
});

Fetch Escrow State

const escrow = await client.fetchEscrow(depositorPublicKey, escrowId);
console.log(escrow.status); // { active: {} }
console.log(escrow.amount); // BN (lamports)

const myEscrows = await client.fetchEscrowsByDepositor(depositorPublicKey);
const incoming  = await client.fetchEscrowsByRecipient(recipientPublicKey);

Utility Functions

import {
  solToLamports,
  lamportsToSol,
  getTimelockForAmount,
  isTimelockExpired,
  isReleaseReady,
  validateMilestones,
  formatTimestamp,
  parseZendetsuError,
  getAllErrorMessages,
} from "zende-sdk";

solToLamports(1.5)                    // BN(1_500_000_000)
lamportsToSol(new BN(1_000_000_000)) // 1

getTimelockForAmount(solToLamports(0.5))  // 3600  (1 hour)
getTimelockForAmount(solToLamports(5))    // 21600 (6 hours)
getTimelockForAmount(solToLamports(50))   // 86400 (24 hours)
getTimelockForAmount(solToLamports(500))  // 259200 (72 hours)

isTimelockExpired(escrow.timelockUntil)  // true / false
isReleaseReady(escrow.releaseAt)         // true / false (Timed mode)
formatTimestamp(escrow.createdAt)        // "4/23/2026, 2:30:00 AM"

// Parse any error manually
parseZendetsuError(err, "pidgin") // "The escrow don freeze, dispute dey ground"

// Get all error messages for a language
getAllErrorMessages("pidgin") // { NotAuthorized: "Na only authorized pesin...", ... }

Escrow Modes

| Mode | How it works | |---|---| | Simple | Both parties confirm and funds release instantly. Timelock protects if one goes silent. | | Milestone | SOL releases in chunks per approved milestone. 3 rejections triggers auto-dispute. | | MultiParty | Multiple signers. Majority or unanimous release depending on releaseCondition. | | Timed | Auto-releases at a unix timestamp. No confirmation needed. |

Timelocks

| Amount | Timelock | |---|---| | Less than 0.0067 SOL | 1 hour | | Less than 0.067 SOL | 6 hours | | Less than 0.67 SOL | 24 hours | | 0.67 SOL and above | 72 hours |

Speed settings (standard, express, instant) let both parties agree to shorten the timelock. One party alone cannot force it.

Program

| | | |---|---| | Program ID | GuDNhDbxfmpAt3zDg9TSPdzAYvARifeFTqUhQRtsmjuC | | Network | Solana Devnet | | Audit | Pending |

License

ISC