{"_id":"@cgentai/cgent-contracts","name":"@cgentai/cgent-contracts","dist-tags":{"latest":"1.0.0"},"versions":{"1.0.0":{"name":"@cgentai/cgent-contracts","version":"1.0.0","description":"SDK for interacting with Cgent.AI Solidity contracts","main":"dist/src/index.js","types":"dist/src/index.d.ts","exports":{".":{"types":"./dist/src/index.d.ts","import":"./dist/src/index.js","require":"./dist/src/index.js"},"./typechain-types/*":{"types":"./dist/typechain-types/*.d.ts","import":"./dist/typechain-types/*.js","require":"./dist/typechain-types/*.js"}},"scripts":{"compile-contracts":"npx hardhat compile --force","prebuild":"npm run compile-contracts","test-wallet":"npx ts-node test/test-wallet.ts","deploy:p2p-escrow":"npx ts-node test/deploy/deploy-p2p-escrow.ts --params test/deploy/p2p-escrow-params.json","test:p2p-escrow-trade":"npx ts-node test/p2p-escrow-trade.ts","build":"npx tsc","prepare":"npm run build","prepublishOnly":"npm run build && npm run verify-package","verify-package":"node -e \"console.log('Verifying package...'); const fs = require('fs'); ['dist/src/index.js', 'dist/src/index.d.ts', 'LICENSE', 'README.md'].forEach(f => { if (!fs.existsSync(f)) throw new Error('Missing: ' + f); }); console.log('✓ All required files present');\"","dev":"npx tsc --watch"},"keywords":["base","blockchain","solidity","sdk","typescript","escrow","p2p","web3","ethereum"],"author":"","license":"MIT","engines":{"node":">=16.0.0"},"devDependencies":{"@nomicfoundation/hardhat-toolbox":"^4.0.0","@types/node":"^20.0.0","hardhat":"^2.19.0","hardhat-dependency-compiler":"^1.2.1","typescript":"^5.0.0"},"dependencies":{"@openzeppelin/contracts":"^5.4.0"},"peerDependencies":{"ethers":"^6.0.0"},"_id":"@cgentai/cgent-contracts@1.0.0","gitHead":"3151779653bb2854470edffe365e0c32df52d351","_nodeVersion":"22.20.0","_npmVersion":"10.9.3","dist":{"integrity":"sha512-t26KZcElOF4KXiwDt1kFGvEYbK1TN6HhyiYXGTP49B+i6BSLHnRktA6yxwsRABV9ZTIHWi84tSfkzD6dfpnZhw==","shasum":"d07eec25b2fcfe5f969c9b6acc1f4b4bdd337c6e","tarball":"https://registry.npmjs.org/@cgentai/cgent-contracts/-/cgent-contracts-1.0.0.tgz","fileCount":35,"unpackedSize":184192,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIB3iIZu5crqANskVqulgRBvDXDcNQfdYXRK/P82qtBu4AiAy00jqeMCh85IP9mw+DrFwww7+0AB09w6MlAYnm6wYvw=="}]},"_npmUser":{"name":"mackieq","email":"mutou151@gmail.com"},"directories":{},"maintainers":[{"name":"mackieq","email":"mutou151@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/cgent-contracts_1.0.0_1768378211905_0.4100157749728317"},"_hasShrinkwrap":false}},"time":{"created":"2026-01-14T08:10:11.791Z","1.0.0":"2026-01-14T08:10:12.107Z","modified":"2026-01-14T08:10:12.360Z"},"maintainers":[{"name":"mackieq","email":"mutou151@gmail.com"}],"description":"SDK for interacting with Cgent.AI Solidity contracts","keywords":["base","blockchain","solidity","sdk","typescript","escrow","p2p","web3","ethereum"],"license":"MIT","readme":"## P2P Escrow SDK 文档\n\n本仓库提供一个用于点对点电商场景的资金托管合约 `P2PEscrow.sol` 以及与之配套的 TypeScript SDK，帮助买卖双方在交易过程中安全地锁定和释放资金。本文档覆盖以下内容：\n\n- 合约设计概览与角色职责\n- 订单生命周期及状态机\n- 合约公开方法与事件说明\n- 常量、费用与错误类型\n- SDK 安装、初始化及常用调用示例\n- 浏览器环境辅助方法\n\n> 合约源码位置：`contracts/P2PEscrow.sol`\n>\n> SDK 入口：`src/index.ts`（导出常量、类型与 `P2PEscrowClient`）\n\n---\n\n### 1. 合约概览\n\n`P2PEscrow` 合约主要面向买家（buyer）、卖家（seller）与仲裁者（arbitrator）三个角色：\n\n- **买家**：发起订单并预付代币；在没有争议时可以确认收货或撤回资金。\n- **卖家**：在确认收到款项后锁定订单；可在必要时退款或在锁定期后请求释放资金。\n- **仲裁者**：当订单进入争议流程时，负责裁定资金归属。\n- **合约拥有者（owner）**：配置手续费接收地址、仲裁者和可用代币列表。\n\n资金在订单创建时从买家转入合约，直至订单根据流程释放或退款。合约支持多个 ERC-20 代币，通过白名单管理支持的代币地址。\n\n手续费设定为 **1%**（`FEE_BPS = 100`，基础为 `10_000`）。手续费统一转入 `feeRecipient` 地址，其余金额发放给卖家。\n\n---\n\n### 2. 订单状态机\n\n合约使用 `OrderStatus` 枚举区分订单生命周期：\n\n| 数值 | 状态名 | 说明 |\n| --- | --- | --- |\n| 0 | `None` | 默认状态（订单不存在）。 |\n| 1 | `BuyerPaid` | 买家支付成功，订单已在合约中锁仓。 |\n| 2 | `SellerLocked` | 卖家确认并锁定订单，开始计算锁定期（30 天）。 |\n| 3 | `SellerRefunded` | 卖家将资金原路退回买家。 |\n| 4 | `SellerReleased` | 订单释放给卖家（扣除手续费）。 |\n| 5 | `BuyerWithdrawn` | 买家在卖家锁定前撤回资金。 |\n| 6 | `ArbitrationPending` | 仲裁者介入，等待裁决。 |\n| 7 | `ArbitrationBuyer` | 仲裁判定资金退回买家。 |\n| 8 | `ArbitrationSeller` | 仲裁判定资金释放给卖家（扣除手续费）。 |\n\n锁定期（`LOCK_DURATION = 30 days`）从卖家调用 `lockOrder` 时开始计算。锁定期届满后，卖家可调用 `sellerRelease` 将资金解锁给自己。\n\n---\n\n### 3. 合约方法\n\n#### 3.1 配置与查看\n\n- `feeRecipient() -> address`：查看手续费接收地址。\n- `arbitrator() -> address`：查看当前仲裁者地址。\n- `owner() -> address`：查看合约拥有者。\n- `supportedTokens(address token) -> bool`：查询代币是否在支持列表。\n- `getOrderId(address buyer, address seller, uint256 orderId) -> bytes32`：计算订单唯一 key。\n- `getOrder(address buyer, address seller, uint256 orderId) -> Order`：获取订单结构体。\n- `orders(bytes32 orderKey) -> Order`：通过订单 key 读取原始存储。\n\n#### 3.2 订单生命周期\n\n- `createOrder(address buyer, address seller, uint256 orderId, uint256 amount, address token)`\n  - 仅买家调用；检查代币是否支持、金额>0、卖家非零地址；将 `amount` 转入合约并创建订单。\n\n- `lockOrder(address buyer, uint256 orderId)`\n  - 仅卖家调用；要求状态为 `BuyerPaid`；锁定期开始计时，状态改为 `SellerLocked`。\n\n- `buyerWithdraw(address seller, uint256 orderId)`\n  - 买家在卖家锁定前随时撤回资金，状态变为 `BuyerWithdrawn`。\n\n- `sellerRefund(address buyer, uint256 orderId)`\n  - 卖家在 `BuyerPaid` 或 `SellerLocked` 状态下可主动退款给买家，状态为 `SellerRefunded`。\n\n- `buyerConfirmReceipt(address seller, uint256 orderId)`\n  - 买家在订单锁定后确认收货，触发 `_releaseToSeller`，将金额按费率拆分给卖家和手续费地址，状态变为 `SellerReleased`。\n\n- `sellerRelease(address buyer, uint256 orderId)`\n  - 卖家在锁定期已结束后自助释放资金给自己；状态要求 `SellerLocked` 且当前时间超过 `lockedUntil`。\n\n#### 3.3 仲裁流程\n\n- `setArbitrationPending(address buyer, address seller, uint256 orderId)`\n  - 仅仲裁者调用；在 `BuyerPaid` 或 `SellerLocked` 状态下进入仲裁，记录上一个状态。\n\n- `cancelArbitration(address buyer, address seller, uint256 orderId)`\n  - 仲裁者撤消仲裁，将状态还原至进入仲裁前的状态。\n\n- `arbitrate(address buyer, address seller, uint256 orderId, bool releaseToSeller)`\n  - 仲裁者最终裁决。`releaseToSeller = true` 时拆分手续费后转给卖家；否则原额退回买家。状态分别变更为 `ArbitrationSeller` 或 `ArbitrationBuyer`。\n\n#### 3.4 管理员操作\n\n- `setFeeRecipient(address newRecipient)`：合约拥有者更新手续费地址。\n- `setArbitrator(address newArbitrator)`：合约拥有者更新仲裁者。\n- `addSupportedToken(address token)` / `removeSupportedToken(address token)`：增删支持代币。\n- `transferOwnership(address newOwner)` / `renounceOwnership()`：标准 Ownable 权限管理。\n\n#### 3.5 内部逻辑\n\n- `_releaseToSeller(Order storage order, bytes32 orderKey)`：私有函数，用于统一执行释放逻辑，计算手续费并发放资金。\n\n---\n\n### 4. 事件\n\n合约定义的主要事件如下：\n\n- `OrderCreated(orderKey, buyer, seller, orderId, token, amount)`\n- `OrderLocked(orderKey, lockedUntil)`\n- `BuyerWithdrawn(orderKey)`\n- `SellerRefunded(orderKey)`\n- `SellerReleased(orderKey, sellerAmount, feeAmount)`\n- `ArbitrationPendingSet(orderKey)`\n- `ArbitrationResolved(orderKey, releasedToSeller, amount, feeAmount)`\n- `ArbitrationCancelled(orderKey, restoredStatus)`\n- `FeeRecipientUpdated(newRecipient)`\n- `ArbitratorUpdated(newArbitrator)`\n- `SupportedTokenAdded(token)` / `SupportedTokenRemoved(token)`\n\nSDK 提供的 `P2PEscrowClient` 支持通过 `on/once/off/removeAllListeners` 订阅这些事件。\n\n---\n\n### 5. 常量与错误\n\n- `LOCK_DURATION_SECONDS = 30 * 24 * 60 * 60`：卖家锁定后需等待的秒数。\n- `FEE_BPS = 100 (1%)`，`BPS_DENOMINATOR = 10_000`：手续费计算使用 `amount * FEE_BPS / BPS_DENOMINATOR`。\n- 关键错误：\n  - `InvalidToken(address)`：代币或地址无效。\n  - `InvalidAmount()`：金额为零。\n  - `OrderAlreadyExists()`：同一订单重复创建。\n  - `Unauthorized()`：调用方角色不匹配。\n  - `InvalidStatus()`：当前订单状态不允许执行操作。\n  - `LockPeriodActive(uint256)`：卖家释放时锁定期尚未到期。\n  - `NothingToRelease()`：订单金额为零。\n\n---\n\n### 6. SDK 使用指南\n\nSDK 基于 `ethers@^6`，在 Node.js、浏览器或任意支持 ESM/CJS 的环境中均可使用。\n\n#### 6.1 安装\n\n```bash\nnpm install @cgentai/cgent-contracts ethers\n# 或者使用 pnpm / yarn\n```\n\n#### 6.2 初始化客户端\n\n```ts\nimport { JsonRpcProvider } from \"ethers\";\nimport { P2PEscrowClient } from \"@cgentai/cgent-contracts\";\n\nconst provider = new JsonRpcProvider(\"https://rpc.sepolia.linea.build\");\nconst signer = await provider.getSigner(); // 也可以用 wallet.connect(provider)\n\nconst escrow = new P2PEscrowClient({\n  address: \"0xEscrowAddress\",\n  runner: signer,\n});\n\nconsole.log(await escrow.getFeeRecipient());\n```\n\n`P2PEscrowClient.connect(address, runner)` 提供了便捷的静态初始化方法。\n\n#### 6.3 浏览器环境\n\n```ts\nimport { createP2PEscrowClientFromBrowser } from \"@cgentai/cgent-contracts\";\n\nconst escrow = await createP2PEscrowClientFromBrowser({\n  provider: window.ethereum,\n  address: \"0xEscrowAddress\",\n  accountIndex: 0, // 可选，默认 0\n});\n\nconst account = await escrow.getRunnerAddress();\n```\n\n#### 6.4 创建订单\n\n```ts\nconst buyerAddress = await escrow.getRunnerAddress();\n\nawait escrow.createOrder({\n  buyer: buyerAddress!,\n  seller: \"0xSellerAddress\",\n  orderId: 1n,\n  amount: 1000n * 10n ** 6n, // 以最小单位传值\n  token: \"0xUSDC\",\n});\n```\n\n在调用前确保买家钱包已对合约执行 `ERC20.approve` 授权。\n\n#### 6.5 卖家操作\n\n```ts\n// 卖家确认锁定\nawait escrow.withRunner(sellerSigner).lockOrder({\n  buyer: buyerAddress!,\n  orderId: 1n,\n});\n\n// 卖家等待锁定期结束后释放\nawait escrow.withRunner(sellerSigner).sellerRelease({\n  buyer: buyerAddress!,\n  orderId: 1n,\n});\n\n// 或者在需要时退款\nawait escrow.withRunner(sellerSigner).sellerRefund({\n  buyer: buyerAddress!,\n  orderId: 1n,\n});\n```\n\n#### 6.6 买家确认或撤回\n\n```ts\n// 买家确认收货\nawait escrow.withRunner(buyerSigner).buyerConfirmReceipt({\n  seller: \"0xSellerAddress\",\n  orderId: 1n,\n});\n\n// 买家在卖家锁定前撤回\nawait escrow.withRunner(buyerSigner).buyerWithdraw({\n  seller: \"0xSellerAddress\",\n  orderId: 1n,\n});\n```\n\n#### 6.7 仲裁流程\n\n```ts\n// 仲裁者设置仲裁中\nawait escrow.withRunner(arbitratorSigner).setArbitrationPending({\n  buyer: buyerAddress!,\n  seller: \"0xSellerAddress\",\n  orderId: 1n,\n});\n\n// 最终裁决：true 释放给卖家（扣除手续费），false 退给买家\nawait escrow.withRunner(arbitratorSigner).arbitrate({\n  buyer: buyerAddress!,\n  seller: \"0xSellerAddress\",\n  orderId: 1n,\n  releaseToSeller: true,\n});\n```\n\n#### 6.8 查询订单与辅助函数\n\n```ts\nconst order = await escrow.getOrder({\n  buyer: buyerAddress!,\n  seller: \"0xSellerAddress\",\n  orderId: 1n,\n});\n\nconsole.log(order.status); // OrderStatus 枚举值\n\nconst { feeAmount, sellerAmount } = P2PEscrowClient.calculateFee(order.amount);\n```\n\nSDK 返回的 `ResolvedOrder` 将合约中的 `uint256` 转换为 `bigint`，可直接参与 JS/TS 计算。\n\n---\n\n### 7. 事件监听\n\n`P2PEscrowClient` 继承了 TypeChain 的事件类型，可在 TypeScript 中获得强类型支持：\n\n```ts\nimport type { P2PEscrow } from \"@cgentai/cgent-contracts/typechain-types\";\n\nescrow.on(escrow.contract.filters.OrderCreated(), (orderKey, buyer, seller, orderId) => {\n  console.log(\"New order\", { orderKey, buyer, seller, orderId: orderId.toString() });\n});\n\n// 取消监听\nescrow.removeAllListeners(escrow.contract.filters.OrderCreated());\n```\n\n---\n\n### 8. 部署与网络\n\n`deployments/` 目录中存放了示例部署信息（例如 `P2PEscrow-84532.json` 对应于 Linea Sepolia 测试网）。使用 SDK 时请根据实际网络配置合约地址与 RPC 节点。\n\n---\n\n### 9. 开发与测试\n\n- 本仓库基于 Hardhat，测试脚本位于 `test/` 目录，可运行 `pnpm test` 或 `npx hardhat test`。\n- 若需自建环境，可使用 `pnpm deploy`（具体脚本请参考 `package.json`）。\n- 修改合约或 SDK 后，请重新编译生成 TypeChain 类型：`pnpm build`。\n\n---\n\n如需更多帮助或功能扩展，欢迎提交 Issue 或 PR。\n\n\n","readmeFilename":"README.md","_rev":"1-6db0aae88d6b3ff546d0399f820be143"}