包
@ckb-ccc/udt
UDT 与 xUDT 代币 SDK,用于发行和转移用户自定义代币。
@ckb-ccc/udt 提供一套 TypeScript SDK,用于在 CKB 上与用户自定义代币(User-Defined Token,简称 UDT)及 xUDT 标准交互。它构建于 SSRI 协议之上,同时支持符合 SSRI 规范的合约和传统 sUDT / xUDT 代币。
安装
如果你使用的是 @ckb-ccc/shell,udt 命名空间已作为 ccc.udt 内置其中。
npm install @ckb-ccc/udtyarn add @ckb-ccc/udtpnpm add @ckb-ccc/udt导出
| 导出 | 说明 |
|---|---|
Udt | 与 UDT 交互的主类 |
UdtPausable | 支持紧急暂停、合规与风控管理的 UDT 代币扩展类 |
Udt 类
Udt 继承自 ssri.Trait,为所有代币操作提供高级方法。
构造函数
const udt = new Udt(
code, // ccc.OutPointLike——脚本代码 Cell 的 OutPoint
script, // ccc.ScriptLike——标识该代币的 Type Script
config?, // { executor?: ssri.Executor | null }
);读取方法
// 代币元数据
const { res: name } = await udt.name(); // string | undefined
const { res: symbol } = await udt.symbol(); // string | undefined
const { res: decimals } = await udt.decimals(); // ccc.Num | undefined
const { res: icon } = await udt.icon(); // string(data URI)| undefinedtransfer
将代币转移给一个或多个接收方:
async transfer(
signer: ccc.Signer,
transfers: { to: ccc.ScriptLike; amount: ccc.NumLike }[],
tx?: ccc.TransactionLike | null,
): Promise<ssri.ExecutorResponse<ccc.Transaction>>mint
铸造新代币(仅限发行方):
async mint(
signer: ccc.Signer,
mints: { to: ccc.ScriptLike; amount: ccc.NumLike }[],
tx?: ccc.TransactionLike | null,
): Promise<ssri.ExecutorResponse<ccc.Transaction>>completeBy
以 signer 的推荐地址作为找零地址,自动平衡 UDT 的输入/输出:
async completeBy(
tx: ccc.TransactionLike,
from: ccc.Signer,
): Promise<ccc.Transaction>completeChangeToLock
这个方法主要用于 UDT 转账交易中,确保交易的输入和输出 UDT 余额平衡。当输入的 UDT 数量超过输出时,将多余的代币发送到指定的地址。
async completeChangeToLock(
txLike: ccc.TransactionLike,
signer: ccc.Signer,
change: ccc.ScriptLike, // 找零地址
): Promise<ccc.Transaction>使用示例
发行 xUDT
以下示例展示如何使用 CCC 发行 xUDT 代币(来自 CCC 示例应用):
// 获取 Signer 推荐地址的 Lock 脚本,设置代币元数据
const { script } = await signer.getRecommendedAddressObj();
const decimals = "8";
const symbol = "SUS";
const name = "Sample Token";
// 创建交易,包含一个输出
const susTx = ccc.Transaction.from({
outputs: [{ lock: script }],
});
// 自动添加输入以满足容量需求
await susTx.completeInputsByCapacity(signer);
// 自动添加手续费
await susTx.completeFeeBy(signer);
// 签名并广播交易,返回交易哈希
const susTxHash = await signer.sendTransaction(susTx);使用 Type ID 发行 xUDT
// 1. 创建或使用现有 Type ID
const typeId = await ccc.Script.fromKnownScript(
signer.client,
ccc.KnownScript.TypeId,
typeIdArgs,
);
// 2. 创建输出类型代理 Lock
const outputTypeLock = await ccc.Script.fromKnownScript(
signer.client,
ccc.KnownScript.OutputTypeProxyLock,
typeId.hash(),
);
// 3. 创建所有者 Cell
const lockTx = ccc.Transaction.from({
outputs: [{ lock: outputTypeLock }],
});
await lockTx.completeInputsByCapacity(signer);
await lockTx.completeFeeBy(signer);
const lockTxHash = await signer.sendTransaction(lockTx);
// 4. 铸造代币
const mintTx = ccc.Transaction.from({
inputs: [
{ previousOutput: typeIdCell.outPoint },
{ previousOutput: { txHash: lockTxHash, index: 0 } },
],
outputs: [
typeIdCell.cellOutput,
{
lock: script,
type: await ccc.Script.fromKnownScript(
signer.client,
ccc.KnownScript.XUdt,
outputTypeLock.hash(),
),
},
],
});转移代币
import { udt } from "@ckb-ccc/udt";
import { ccc } from "@ckb-ccc/shell";
const myToken = new udt.Udt(
{
txHash: "0x4e2e832e0b1e7b5994681b621b00c1e65f577ee4b440ef95fa07db9bb3d50269",
index: 0,
},
{
codeHash: "0xcc9dc33ef234e14bc788c43a4848556a5fb16401a04662fc55db9bb201987037",
hashType: "type",
args: "0x71fd1985b2971a9903e4d8ed0d59e6710166985217ca0681437883837b86162f",
},
);
const { script: toScript } = await ccc.Address.fromString(
"ckb1qzda0cr08m85hc8jlnfp3gog...",
signer.client,
);
// 构建转账交易
const { res: tx } = await myToken.transfer(signer, [
{ to: toScript, amount: 100n },
]);
// 平衡 UDT 找零与容量
const completedTx = await myToken.completeBy(tx, signer);
await completedTx.completeInputsByCapacity(signer);
await completedTx.completeFeeBy(signer);
const txHash = await signer.sendTransaction(completedTx);读取代币元数据
const { res: name } = await myToken.name();
const { res: symbol } = await myToken.symbol();
const { res: decimals } = await myToken.decimals();
console.log(`${name} (${symbol}), ${decimals} 位小数`);铸造代币
const { res: tx } = await myToken.mint(signer, [
{ to: recipientScript, amount: 1_000_000n },
]);
const completedTx = await myToken.completeBy(tx, signer);
await completedTx.completeInputsByCapacity(signer);
await completedTx.completeFeeBy(signer);
await signer.sendTransaction(completedTx);@ckb-ccc/udt 依赖 @ckb-ccc/ssri。ssri.Executor 为可选参数——不传时,Udt 类会回退到直接构造交易,不从链上查询 SSRI 元数据。
最后更新于