# @floorlaunchpad/carpenter-sdk 中文文档

规范地址：https://npmcn.com/package/%40floorlaunchpad/carpenter-sdk/

版本：0\.1\.1
npm 元数据更新时间：2026-11-01T01:25:55.323Z
中文译文更新时间：2026-11-01T05:04:25.026Z
软件包许可：Apache-2\.0

本文由上游 README 机器翻译，可能存在偏差，请结合原文核对 API、命令与配置。版权与许可归原作者所有。

原始 npm 页面：https://www.npmjs.com/package/%40floorlaunchpad/carpenter-sdk
原文对照：https://npmcn.com/package/%40floorlaunchpad/carpenter-sdk/?lang=original
项目主页：https://github.com/gudtekdonkey/carpenter-sdk/tree/main/packages/sdk#readme
源码仓库：https://github.com/gudtekdonkey/carpenter-sdk

弃用说明：No longer maintained\. Use @floorlaunchpad/sdk\.

## 关键信息（来自 npm 元数据）

- 包体积（解压后）：3.5 MB，767 个文件
- 模块格式：ES Module
- TypeScript 类型：包内自带
- Node.js 要求：\>=20\.18
- 运行依赖：1 个
- peer 依赖：@solana/kit ^8\.3\.0
- 首次发布：2026-10-14T02:21:34.403Z
- 最新版本发布：2026-10-14T03:17:59.736Z
- 已发布版本数：3（近 12 个月 3 个）

## 中文简介

Carpenter， Solana上的AMM: carpenter\_amm IDL和Codama客户端，池/位置/期权数组布局和pda，交换和流动性生成器，查找表，期权数学，协议费用，挂钩接口，纯池报价。

## 安装

```sh
npm install @floorlaunchpad/carpenter-sdk
```

也可以使用：`pnpm add @floorlaunchpad/carpenter-sdk`、`yarn add @floorlaunchpad/carpenter-sdk`、`bun add @floorlaunchpad/carpenter-sdk`

## README

# @floorlaunchpad / carpenter-sdk

TypeScript SDK for Carpenter， Solana上的集中流动性AMM，带有uniswasp -v4风格的钩子：由 `(mint0, mint1, fee, tickSpacing, hook)`，外部lp，以及批准的钩程序允许列表。纯TypeScript结束 [`@solana/kit`](https://github.com/anza-xyz/kit) 8.3.0;这里的签收和发送都要带钱包。

它涵盖了阅读、报价和交易：

-   这个 `carpenter_amm` IDL及其 [Codama](https://github.com/codama-idl/codama) 客户端(`carpenterAmm`);
-   帐户布局和解码器(`AmmConfig`， `Pool`， `TickArray`， `Position`（钩子允许列表，引用列表）， pda和读取帮助程序，它们用其插槽标记每个读取(`stateView`);
-   交易生成器：掉期、余额掉期、增加/删除流动性和收取费用(`buildModifyLiquidity`)， 关闭位置，标记数组，初始化池，以及 `planCreatePool` （创建一个池和它的第一个位置）；
-   通过地址查找表发送V0消息，在钱包看到任何内容之前检查1232字节的数据包；
-   `sendSolanaTransactions`：一次操作每笔交易一个钱包提示；
-   通过捆绑的wasm引号标记数学、协议费用算法、事件解码器和纯池引号 （`wasm/carpenter_quote_bg.wasm`（程序自己的引用包编译为wasm）。

治理和管理说明（配置设置、钩子批准、暂停、费用提取）在IDL和 生成的客户端，但这里没有构建器。

## 安装

```sh
npm install @floorlaunchpad/carpenter-sdk @solana/kit@8.3.0
```

`@solana/kit` 是一个对等依赖。

## 读池

```ts
import { createSolanaRpc } from '@solana/kit';
import { deploymentFor, fromKitRpc, MAINNET_CHAIN_KEY, programIdsFromDeployment, stateView } from '@floorlaunchpad/carpenter-sdk';

const rpc = createSolanaRpc('https://api.mainnet-beta.solana.com');
const src = fromKitRpc(rpc);
const ids = programIdsFromDeployment(deploymentFor(MAINNET_CHAIN_KEY)); // DEVNET_CHAIN_KEY for devnet

const { slot, value: pool } = await stateView.getPool(src, poolAddress, ids);
```

程序id来自 `deployments.json` （`deploymentFor`)，从不使用应用中的常量； `DEFAULT_PROGRAM_IDS` 存在 用于测试和脚本。

## 引用和交换一个普通池

```ts
import { readFileSync } from 'node:fs';
import { createRequire } from 'node:module';
import { buildSwap, compileSendable, decodePool, readSwapQuoteAccounts, sendSolanaTransactions, swapTickArrays } from '@floorlaunchpad/carpenter-sdk';
import { initQuote } from '@floorlaunchpad/carpenter-sdk/quote/wasm';
import { getBase64EncodedWireTransaction } from '@solana/kit';

// Node: read the bundled wasm; a browser fetches `@floorlaunchpad/carpenter-sdk/carpenter_quote_bg.wasm` and passes the bytes.
const quoter = await initQuote(readFileSync(createRequire(import.meta.url).resolve('@floorlaunchpad/carpenter-sdk/carpenter_quote_bg.wasm')));
const { value: v } = await readSwapQuoteAccounts(src, poolAddress, { radius: 4, ids });
const q = quoter.quoteSwap({ ...v, zeroForOne: true, amountSpecified: -1_000_000n }); // exact in: negative
const { starts } = await swapTickArrays(poolAddress, q, ids);

const tx = await buildSwap({
  trader, pool: poolAddress, poolState: decodePool(v.pool), zeroForOne: true,
  amountSpecified: -1_000_000n, amountLimit: (q.amountOut * 99n) / 100n, tickArrayStarts: starts, ids,
});
const { value: bh } = await rpc.getLatestBlockhash().send();
const { transaction } = compileSendable('swap', { feePayer: trader, instructions: tx.instructions, lifetime: bh });
await sendSolanaTransactions(wallet, [getBase64EncodedWireTransaction(transaction)], rpc, { lastValidBlockHeight: bh.lastValidBlockHeight });
```

引号是程序自己的引用箱(`carpenter-quote`)编译为wasm并在此包中发布 （`wasm/`， `WASM_SHA256`）; 引用返回的每个数字都是箱子的。它引用了没有交换钩子的池 钩子参与交换被拒绝(`QuoteHookNotQuotable`)，并被其钩子的SDK (`@floorlaunchpad/sdk-solana` 用于 地板池)。暂停的池被拒绝 `PoolPaused`;守护暂停(`Pool.guardianPausedUntil`（Unix时间）不是 从引号判断，上面写着没有时钟：检查 `poolPausedAt(pool, nowUnix)` 针对集群的时钟。 `simulateTransaction` 留下签字前的最后支票。

滑动：一种精确的交换 `amountLimit` 是否有最低限额 `0` 被拒绝，除非 `allowNoMinimum: true`）; 从上面的引用（1%）中得出。 `buildModifyLiquidity` 都拒绝搬迁 `amount0Min` 也不 `amount1Min`，存款上限为 `u64::MAX`，在相同的选择退出下。

计算: `CU_LIMITS` （`swapPlain` 对于普通的交换，90,000)是估计值，而不是交易的度量。 首先进行模拟，然后根据模拟结果设置限制 `unitsConsumed` 重要的时候。

原生SOL：一个wSOL端通过一个临时的wSOL帐户移动，该帐户由构建器创建、资助并关闭 同一交易(`tempWsol`（交易员钥匙下的随机种子）。交易者自己的wSOL账户（如果有的话）两者都不是 未使用，未关闭，因此已保存的wSOL保持原样。指定一个帐户(`traderTokenIn` / `traderTokenOut`， `ownerToken0` / `ownerToken1`)来代替使用它（它为输入充值，永远不会关闭），或者传递 `wrapSol: false` 使用没有包装的wSOL ATA。

一个被钩住的池子需要它的钩子的账户(`hookSlice`)及计算(`cuUnits`)：钩子自己的SDK提供了它们 （`@floorlaunchpad/sdk-solana` 游泳池)。 `readSwapQuoteAccounts` 拒绝一个钩形泳池的名字。

FLOOR池使用四帐户FLOOR钩子切片，这个发布列表中包含主网和开发网部署 （`@floorlaunchpad/sdk-solana` 的同一版本构建它)。固定的钩子`HOOK_FLAGS.SETTLES`)被称为下 `["hook_settle", pool]` Signer，这是它的切片。`findHookSettle`）; 通过 `writableMints` 当它铸造成一个金库 在交换期间。

## 创建一个池并增加流动性

```ts
import { fromKitRpc, planCreatePool, sendSolanaTransactions, NO_HOOK } from '@floorlaunchpad/carpenter-sdk';

const plan = await planCreatePool({
  payer, mintA, mintB, tokenProgramA, tokenProgramB, decimalsA: 6, decimalsB: 9,
  fee: 3_000, tickSpacing: 60, hook: NO_HOOK, sqrtPriceX64,
  position: { tickLower: -600, tickUpper: 600, liquidity, amountAMax, amountBMax },
  lifetime: bh, ids,
});
await sendSolanaTransactions(wallet, plan.transactions, rpc, {
  steps: plan.stepNames,
  lastValidBlockHeight: bh.lastValidBlockHeight,
  beforeSend: plan.beforeSend(fromKitRpc(rpc)), // stop if the new pool's price moved before the deposit
});
```

`plan.transactions` 是 `[initializePool, addLiquidity]`：两个交易（它们加在一起不适合一个包），签名 一次提示并按顺序发送。一个钱包签名两个，所以位置的所有者是付款人(`owner` / `initializer` 除了 `payer` 是拒绝)。

在这两个步骤之间，池存在并且是空的，任何人都可以免费移动空池的价格。 `plan.beforeSend(src, { maxPriceMoveBps })` 在发送存款之前读取池并停止运行（原因） `guard`， `PoolPriceMovedError`)，当其价格从初始化价格移动超过 `maxPriceMoveBps` （默认0：精确）。价格还可以在阅读和押金之间浮动，所以 `amountAMax` / `amountBMax` 是 存款是唯一的硬性限制：将它们设置为初始价格加上您接受的滑点所需要的头寸， 从来没有更大的。

## 每次操作的钱包提示

`sendSolanaTransactions(wallet, steps, rpc, opts?)` 将一个操作的每个交易签名在一起，然后发送它们 订单，等待每一个确认前的下一个；第一个失败停止运行并命名步骤 （`SolanaSendError`： `index`， `step`， `reason`（落地的签名）。

| 行动 | 交易 | 提示（批量签名钱包） |
| --- | --- | --- |
| 交换 | 1 | 1 |
| 增加/移除流动性，收取费用 | 1 | 1 |
| 用它的第一个位置创建一个池(`planCreatePool`） | 2 | 1 |

钱包是如何被问到的，按照偏好顺序：钱包标准 `solana:signTransaction` 每一个特性 一次调用的事务(`wallet.standard`)，遗产 `signAllTransactions`,否则 `signTransaction` 每一步一次。这个 结果表明哪个(`path`)，以及需要多少提示。

警告:

-   逐个签署交易需要一个提示符；没有批处理调用的钱包就会退回到这种情况。
-   在发送任何东西之前，钱包返回的每笔交易都要进行检查：消息字节必须等于计划的字节 消息，以及每个所需的签名(预期签名者包括： `opts.signer`，否则就是钱包标准 帐户，否则付款人)必须核实。其他任何事情都能合理地阻止逃亡 `sign`.
-   一个步骤不会发送两次。发送错误而没有预拒绝（超时，断开连接）可能有 交付事务，因此步骤继续等待其签名。一个步骤只有在其过期时才算作过期 签名不存在，区块高度已经超过了区块散列的高度 `lastValidBlockHeight` (传递它，或者发送者要求 节点)，又通过了两个块，a `searchTransactionHistory` 重新检查仍然一无所获，节点调用 blockhash无效。“未找到区块散列”本身并不过期。
-   失败后，从链状态重新计划：登陆的步骤改变了它。一个 `timeout` 可能还会着陆：检查一下 `signature` 在再次行动之前。
-   这些交易共享一个最近的区块散列，有效期约为60-90秒。通过 `opts.replan` 重建步骤 到期时还没有登陆的（再提示一次）；没有它，奔跑会因理性而停止 `expired`.
-   在签名之前模拟每笔交易的钱包无法模拟依赖于之前帐户的步骤 步骤创建池 `planCreatePool`（查找表）：它将该步骤显示为失败，并且它在 之前的步骤。

## 开发

`idl/carpenter_amm.json` 该程序的锚IDL与每个 `docs` 字段已删除，并出现一些错误 `msg` 字符串 缩短（错误名称和代码不变）：发货的IDL，和 从它生成的客户端构建，不携带文档注释。 `IDL_SHA256` 是该文件的散列。

```sh
npm run generate   # idl/ + deployments.json → src/generated/ (Codama client)
npx tsc -p tsconfig.json --noEmit
npx vitest run
npm run build      # dist/
npm run sync-wasm  # dist/wasm (from `bash wasm/build.sh` at the repository root) → wasm/ and WASM_SHA256
```

这个峡谷是由 `wasm/carpenter-quote-wasm` 由 `wasm/build.sh` 在存储库根目录：rustc 1.98.1 （`wasm32-unknown-unknown`), wasm-bindgen-cli 0.2.128， `--target web`，在固定路径上的源副本上 路径被重新映射，crate的文档注释被删除，所以相同的源给出相同的字节。 `test/wasm.test.ts` 回放 `fixtures/quote-vectors/plain.json` 和 `parity-plain.json` 通过运输的水路。

这些程序可以通过主网-测试版上的时间锁升级（10分钟的延迟只能由部署者提出），也可以通过部署者直接在devnet上升级，并且可以由部署者暂停；这个包没有声明它们是经过审计的或不可变的。

## 许可证

apache - 2.0。

## 常见问题

### @floorlaunchpad/carpenter-sdk 是什么？

Carpenter， Solana上的AMM: carpenter\_amm IDL和Codama客户端，池/位置/期权数组布局和pda，交换和流动性生成器，查找表，期权数学，协议费用，挂钩接口，纯池报价。注意：该包已被作者标记为弃用——No longer maintained\. Use @floorlaunchpad/sdk\.

### 如何安装 @floorlaunchpad/carpenter-sdk？

在项目目录运行 npm install @floorlaunchpad/carpenter-sdk，或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖：@solana/kit（^8\.3\.0）。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖，Yarn 需要手动安装。

### @floorlaunchpad/carpenter-sdk 支持 TypeScript 吗？

支持。包内自带 TypeScript 类型声明（package\.json 声明了 types 入口），安装后即可获得类型提示，无需再安装 @types 包。

### @floorlaunchpad/carpenter-sdk 支持 ESM 还是 CommonJS？

以 ES Module 形式发布，推荐使用 import 引入。在 CommonJS 项目中，Node\.js 20\.19\+ / 22\.12\+ 可以直接 require\(\) 不含顶层 await 的 ES Module，更早的版本需要改用动态 import\(\)。

### @floorlaunchpad/carpenter-sdk 需要什么版本的 Node\.js？

package\.json 的 engines 字段要求 Node\.js \>=20\.18。版本不符时 npm 默认只给出警告，开启 engine-strict 后会拒绝安装。

### @floorlaunchpad/carpenter-sdk 可以商用吗？

@floorlaunchpad/carpenter-sdk 使用 Apache-2\.0 许可。宽松许可：允许商业使用、修改和再分发，并附带明确的专利授权；分发时需保留许可与 NOTICE 文件，修改过的文件要注明改动。以上为概括，不构成法律意见，请以许可原文为准。

### @floorlaunchpad/carpenter-sdk 还在维护吗？

最新版本 0\.1\.1 发布于 2026/10/14（20 天前）；至今共发布 3 个版本，其中过去 12 个月发布了 3 个；首次发布于 2026/10/14。作者已将其标记为弃用，新项目建议寻找替代方案。

