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 🙏

© 2025 – Pkg Stats / Ryan Hefner

drama-pm-client

v0.3.1

Published

TypeScript client for Drama Prediction Market

Readme

Drama PM Client SDK

TypeScript 客户端 SDK,用于与 Drama 预测市场 Solana 智能合约交互。

特性

  • 完整的类型支持 - 使用 TypeScript 编写,提供完整的类型定义
  • 自动 ATA 管理 - 自动检测和创建关联代币账户 (Associated Token Account)
  • 简洁的 API - 提供简单易用的方法接口
  • 灵活的交易构建 - 支持获取单个指令或完整交易
  • PDA 计算工具 - 导出所有 PDA 派生函数
  • 错误处理 - 完善的错误处理机制

安装

npm install drama-pm-client
# 或
yarn add drama-pm-client

快速开始

import { Connection, PublicKey } from "@solana/web3.js";
import { DramaPmClient } from "drama-pm-client";
import { BN } from "@coral-xyz/anchor";

// 初始化连接和客户端
const connection = new Connection("https://api.devnet.solana.com");
const client = new DramaPmClient(connection);

// 创建市场
const createMarketTx = await client.buildCreateMarketTx({
  admin: adminPublicKey,
  marketId: new BN(1),
  yesPrice: new BN(1_200_000), // 1.2 USDC
  noPrice: new BN(800_000),    // 0.8 USDC
  endTime: new BN(Date.now() / 1000 + 3600), // 1小时后
  bettingToken: usdcMint,
});

// 下注 (自动创建 ATA)
const placeBetTx = await client.buildPlaceBetTx({
  user: userPublicKey,
  admin: adminPublicKey,
  marketId: new BN(1),
  amount: new BN(1_000_000), // 1 USDC
  outcome: "Yes",
  bettingToken: usdcMint,
  createAta: true, // 自动创建 ATA
});

API 文档

DramaPmClient

主客户端类,提供所有合约交互方法。

构造函数

constructor(connection: Connection, wallet?: anchor.Wallet)
  • connection: Solana RPC 连接
  • wallet: (可选) Anchor 钱包,用于读取操作

方法

createMarket()

创建新的预测市场。

async createMarket(params: CreateMarketParams): Promise<TransactionInstruction>

参数:

interface CreateMarketParams {
  admin: PublicKey;           // 市场管理员
  marketId: number | BN;      // 唯一市场 ID
  yesPrice: number | BN;      // YES 选项价格 (原始单位)
  noPrice: number | BN;       // NO 选项价格 (原始单位)
  endTime: number | BN;       // 市场结束时间 (Unix 时间戳)
  bettingToken: PublicKey;    // 投注代币 Mint 地址
}

返回: TransactionInstruction

示例:

const ix = await client.createMarket({
  admin: admin.publicKey,
  marketId: new BN(123),
  yesPrice: new BN(1_200_000),
  noPrice: new BN(800_000),
  endTime: new BN(Math.floor(Date.now() / 1000) + 3600),
  bettingToken: usdcMint,
});
buildCreateMarketTx()

构建完整的创建市场交易。

async buildCreateMarketTx(params: CreateMarketParams): Promise<Transaction>

返回可直接发送的完整交易对象。


placeBet()

创建下注指令 (不包含 ATA 创建)。

async placeBet(params: PlaceBetParams): Promise<TransactionInstruction>

参数:

interface PlaceBetParams {
  user: PublicKey;            // 用户公钥
  admin: PublicKey;           // 市场管理员
  marketId: number | BN;      // 市场 ID
  amount: number | BN;        // 下注金额 (原始单位)
  outcome: "Yes" | "No";      // 下注选项
  bettingToken: PublicKey;    // 投注代币 Mint
  createAta?: boolean;        // (buildPlaceBetTx 专用) 是否自动创建 ATA
}

返回: TransactionInstruction

buildPlaceBetTx()

构建完整的下注交易,支持自动创建 ATA。

async buildPlaceBetTx(params: PlaceBetParams): Promise<Transaction>

特性:

  • 自动检查 ATA 是否存在
  • 如果 createAta: true 且 ATA 不存在,自动添加创建指令
  • 返回完整的交易对象

示例:

// 自动处理 ATA 创建
const tx = await client.buildPlaceBetTx({
  user: user.publicKey,
  admin: admin.publicKey,
  marketId: new BN(123),
  amount: new BN(2_000_000), // 2 USDC
  outcome: "Yes",
  bettingToken: usdcMint,
  createAta: true, // 自动创建 ATA
});

await sendAndConfirmTransaction(connection, tx, [user]);

claimRewards()

创建领取奖励指令。

async claimRewards(params: ClaimRewardsParams): Promise<TransactionInstruction>

参数:

interface ClaimRewardsParams {
  user: PublicKey;              // 用户公钥
  admin: PublicKey;             // 市场管理员
  marketId: number | BN;        // 市场 ID
  bettingToken: PublicKey;      // 投注代币 Mint
  winningOutcome: "Yes" | "No"; // 获胜选项
}
buildClaimRewardsTx()

构建完整的领取奖励交易。

async buildClaimRewardsTx(params: ClaimRewardsParams): Promise<Transaction>

refund()

创建退款指令 (当市场被标记为退款状态时)。

async refund(params: RefundParams): Promise<TransactionInstruction>

参数:

interface RefundParams {
  user: PublicKey;          // 用户公钥
  admin: PublicKey;         // 市场管理员
  marketId: number | BN;    // 市场 ID
  bettingToken: PublicKey;  // 投注代币 Mint
  outcome: "Yes" | "No";    // 要退款的选项
}
buildRefundTx()

构建完整的退款交易。

async buildRefundTx(params: RefundParams): Promise<Transaction>

resolveMarket()

创建决算市场指令 (仅管理员)。

async resolveMarket(
  admin: PublicKey,
  marketId: number | BN,
  winningOutcome: "Yes" | "No" | null
): Promise<TransactionInstruction>

参数:

  • admin: 管理员公钥
  • marketId: 市场 ID
  • winningOutcome: 获胜选项,null 表示退款
buildResolveMarketTx()

构建完整的决算市场交易。

async buildResolveMarketTx(
  admin: PublicKey,
  marketId: number | BN,
  winningOutcome: "Yes" | "No" | null
): Promise<Transaction>

closeMarket()

创建关闭市场指令 (仅管理员)。

async closeMarket(
  admin: PublicKey,
  marketId: number | BN
): Promise<TransactionInstruction>
buildCloseMarketTx()

构建完整的关闭市场交易。

async buildCloseMarketTx(
  admin: PublicKey,
  marketId: number | BN
): Promise<Transaction>

getMarketAccount()

获取市场账户数据。

async getMarketAccount(admin: PublicKey, marketId: number | BN)

返回: 市场账户数据对象

示例:

const market = await client.getMarketAccount(admin.publicKey, new BN(123));
console.log("Status:", market.status);
console.log("Total YES supply:", market.totalYesSupply.toString());
console.log("Total NO supply:", market.totalNoSupply.toString());

ataExists()

检查关联代币账户是否存在。

async ataExists(ata: PublicKey): Promise<boolean>
createAtaInstruction()

创建 ATA 初始化指令。

createAtaInstruction(
  payer: PublicKey,
  owner: PublicKey,
  mint: PublicKey
): TransactionInstruction

工具函数

SDK 导出了所有 PDA 计算函数:

import {
  getMarketPda,
  getYesMintPda,
  getNoMintPda,
  getVaultPda,
  getMarketPdas, // 一次性获取所有 PDA
} from "drama-pm-client";

// 计算单个 PDA
const marketPda = getMarketPda(programId, admin, marketId);

// 一次性获取所有 PDA
const { market, yesMint, noMint, vault } = getMarketPdas(
  programId,
  admin,
  marketId
);

SDK 优化说明

相比初始版本,SDK 进行了以下优化:

1. 接口参数化

  • ✅ 使用 TypeScript 接口定义参数,提高代码可读性
  • ✅ 统一的参数结构,减少函数签名复杂度

2. 自动 ATA 管理

  • buildPlaceBetTx() 支持自动检测和创建 ATA
  • ✅ 提供 ataExists() 检查方法
  • ✅ 提供 createAtaInstruction() 手动创建 ATA

3. 双层 API 设计

  • ✅ 指令级方法: createMarket(), placeBet()
  • ✅ 交易级方法: buildCreateMarketTx(), buildPlaceBetTx()
  • ✅ 灵活满足不同使用场景

4. PDA 工具优化

  • ✅ 提供 getMarketPdas() 一次性获取所有 PDA
  • ✅ 导出所有 PDA 计算函数供外部使用
  • ✅ 内部使用 PDA 缓存减少重复计算

5. 错误处理改进

  • ✅ 使用 accountsPartial() 替代 accounts(),更安全
  • ✅ ATA 存在性检查,避免重复创建错误
  • ✅ 完整的 TypeScript 类型检查

6. 对齐测试代码

  • ✅ 参数顺序和命名与测试代码一致
  • ✅ ATA 创建模式与测试代码相同
  • ✅ 支持与测试代码相同的使用模式

使用模式对比

模式 1: 完整交易构建 (推荐)

// SDK 自动处理 ATA 创建
const tx = await client.buildPlaceBetTx({
  user: user.publicKey,
  admin: admin.publicKey,
  marketId: new BN(1),
  amount: new BN(1_000_000),
  outcome: "Yes",
  bettingToken: usdcMint,
  createAta: true,
});

await sendAndConfirmTransaction(connection, tx, [user]);

模式 2: 手动组合指令

import { Transaction } from "@solana/web3.js";
import { getAssociatedTokenAddressSync } from "@solana/spl-token";

const tx = new Transaction();
const pdas = getMarketPdas(programId, admin.publicKey, marketId);
const userOutcomeToken = getAssociatedTokenAddressSync(
  pdas.yesMint,
  user.publicKey
);

// 检查并创建 ATA
if (!(await client.ataExists(userOutcomeToken))) {
  const createAtaIx = client.createAtaInstruction(
    user.publicKey,
    user.publicKey,
    pdas.yesMint
  );
  tx.add(createAtaIx);
}

// 添加下注指令
const placeBetIx = await client.placeBet({
  user: user.publicKey,
  admin: admin.publicKey,
  marketId: new BN(1),
  amount: new BN(1_000_000),
  outcome: "Yes",
  bettingToken: usdcMint,
});
tx.add(placeBetIx);

await sendAndConfirmTransaction(connection, tx, [user]);

模式 3: 仅获取指令

// 适用于需要自定义交易构建的场景
const ix = await client.placeBet({
  user: user.publicKey,
  admin: admin.publicKey,
  marketId: new BN(1),
  amount: new BN(1_000_000),
  outcome: "Yes",
  bettingToken: usdcMint,
});

// 添加到自定义交易
const customTx = new Transaction();
customTx.add(someOtherIx);
customTx.add(ix);
customTx.add(anotherIx);

完整示例

查看 app/ 目录下的完整 demo 应用,展示了:

  • ✅ 市场创建
  • ✅ 多用户下注
  • ✅ 市场关闭和决算
  • ✅ 奖励领取
  • ✅ 完整的错误处理

运行 demo:

cd app
npm install
npm run dev

类型定义

export type Outcome = "Yes" | "No";

export interface CreateMarketParams {
  admin: PublicKey;
  marketId: number | BN;
  yesPrice: number | BN;
  noPrice: number | BN;
  endTime: number | BN;
  bettingToken: PublicKey;
}

export interface PlaceBetParams {
  user: PublicKey;
  admin: PublicKey;
  marketId: number | BN;
  amount: number | BN;
  outcome: Outcome;
  bettingToken: PublicKey;
  createAta?: boolean;
}

export interface ClaimRewardsParams {
  user: PublicKey;
  admin: PublicKey;
  marketId: number | BN;
  bettingToken: PublicKey;
  winningOutcome: Outcome;
}

export interface RefundParams {
  user: PublicKey;
  admin: PublicKey;
  marketId: number | BN;
  bettingToken: PublicKey;
  outcome: Outcome;
}

许可证

MIT

贡献

欢迎提交 Issue 和 Pull Request!