Skip to content

Commit

Permalink
chore: type id cell example
Browse files Browse the repository at this point in the history
  • Loading branch information
homura committed Jul 16, 2024
1 parent 58ff5e4 commit ba42416
Showing 1 changed file with 102 additions and 0 deletions.
102 changes: 102 additions & 0 deletions examples/misc/typeid.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
// This example demonstrates how to create a TypeID cell
// You can check a completed transaction here
// https://pudge.explorer.nervos.org/transaction/0x9cd5a253de6a4e2d4b8c46c483154db92b5c35e831e8ddf4ea5674746c03f371

import { Indexer } from "@ckb-lumos/lumos/ckb-indexer";
import { RPC } from "@ckb-lumos/lumos/rpc";
import { generateGenesisScriptConfigs, initializeConfig } from "@ckb-lumos/lumos/config";
import {
cellHelper,
encodeToAddress,
minimalCellCapacity,
sealTransaction,
TransactionSkeleton,
} from "@ckb-lumos/lumos/helpers";
import type { Cell, Script } from "@ckb-lumos/lumos/base";
import { key } from "@ckb-lumos/lumos/hd";
import { generateTypeIdScript } from "@ckb-lumos/lumos/utils";
import {
injectCapacity,
payFeeByFeeRate,
prepareSigningEntries,
setupInputCell,
} from "@ckb-lumos/lumos/common-scripts/common";
import { BI } from "@ckb-lumos/lumos/bi";

const ENDPOINT = "https://testnet.ckb.dev";

const PRIVATE_KEY = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee";

async function main() {
const indexer = new Indexer(ENDPOINT);
const rpc = new RPC(ENDPOINT);

const genesisBlock = await rpc.getBlockByNumber("0x0");
const scriptConfigs = generateGenesisScriptConfigs(genesisBlock);

initializeConfig({ PREFIX: "ckt", SCRIPTS: scriptConfigs });

// Define the transaction skeleton as mutable here for convenient demonstration
const txSkeleton = TransactionSkeleton({ cellProvider: indexer }).asMutable();

const lock: Script = {
codeHash: scriptConfigs.SECP256K1_BLAKE160.CODE_HASH,
hashType: scriptConfigs.SECP256K1_BLAKE160.HASH_TYPE,
args: key.privateKeyToBlake160(PRIVATE_KEY),
};
const address = encodeToAddress(lock);

// tip: the source cell's OutPoint is required to generate the TypeID cell
let sourceCell: Cell | undefined = undefined;
for await (const cell of indexer.collector({ lock, type: "empty", data: "0x" }).collect()) {
sourceCell = cell;
break;
}
if (!sourceCell || !sourceCell.outPoint) {
throw new Error(`Cannot find any cell from the lock`);
}

// 🌟Step 1. Put the TypeID cell to the first output
const typeId = generateTypeIdScript({ previousOutput: sourceCell.outPoint, since: "0x0" });
const typeIdCell = cellHelper.create({ lock, type: typeId });

txSkeleton.update("outputs", (outputs) => outputs.push(typeIdCell));

// 🌟Step 2. Put the source OutPoint into the transaction
await setupInputCell(txSkeleton, sourceCell);

// Step 3. Handle the capacity
const minimalNeededCapacity = minimalCellCapacity(sourceCell) + BigInt(typeIdCell.cellOutput.capacity);
const collectedCapacity = BigInt(sourceCell.cellOutput.capacity);

// if the collected capacity is not enough,
// inject the capacity for the TypeID cell
if (collectedCapacity <= minimalNeededCapacity) {
await injectCapacity(txSkeleton, [address], typeIdCell.cellOutput.capacity);
} else {
// if the collected capacity is enough,
// deduct the capacity from the source cell for the TypeID cell
txSkeleton.update("outputs", (outputs) => {
const outputSourceCell = cellHelper.clone(sourceCell!);
outputSourceCell.cellOutput.capacity = BI.from(outputSourceCell.cellOutput.capacity)
.sub(typeIdCell.cellOutput.capacity)
.toHexString();
return outputs.set(1, outputSourceCell);
});
}

await payFeeByFeeRate(txSkeleton, [address], 1000);
prepareSigningEntries(txSkeleton);

const signatures = txSkeleton
.get("signingEntries")
.map((entry) => key.signRecoverable(entry.message, PRIVATE_KEY))
.toArray();

const signedTx = sealTransaction(txSkeleton, signatures);
const txHash = await rpc.sendTransaction(signedTx);

console.log("txHash:", txHash);
}

main();

0 comments on commit ba42416

Please sign in to comment.