From eb5839a3825378fa4970ab3f7af0c1b347c4d352 Mon Sep 17 00:00:00 2001 From: homura Date: Wed, 15 May 2024 14:40:56 +0900 Subject: [PATCH] feat(helpers): refresh txSkeleton cell deps (#687) --- .changeset/modern-panthers-thank.md | 5 +++ packages/helpers/src/index.ts | 28 ++++++++++++--- packages/helpers/src/refresh.ts | 26 ++++++++++++++ packages/helpers/tests/refresh.test.ts | 48 ++++++++++++++++++++++++++ packages/lumos/src/helpers.ts | 1 + 5 files changed, 103 insertions(+), 5 deletions(-) create mode 100644 .changeset/modern-panthers-thank.md create mode 100644 packages/helpers/src/refresh.ts create mode 100644 packages/helpers/tests/refresh.test.ts diff --git a/.changeset/modern-panthers-thank.md b/.changeset/modern-panthers-thank.md new file mode 100644 index 000000000..52abdce30 --- /dev/null +++ b/.changeset/modern-panthers-thank.md @@ -0,0 +1,5 @@ +--- +"@ckb-lumos/helpers": minor +--- + +feat: refreshTypeIdCellDeps to refresh typeid cell deps diff --git a/packages/helpers/src/index.ts b/packages/helpers/src/index.ts index 65cd071f3..c15d61e6d 100644 --- a/packages/helpers/src/index.ts +++ b/packages/helpers/src/index.ts @@ -40,6 +40,8 @@ export function minimalScriptCapacity( return BigInt(result.toString()); } +const ONE_CKB = 100_000_000; + export function minimalScriptCapacityCompatible( script: Script, { validate = true }: { validate?: boolean } = {} @@ -54,7 +56,7 @@ export function minimalScriptCapacityCompatible( // hash_type field bytes += 1; - return BI.from(bytes).mul(100000000); + return BI.from(bytes).mul(ONE_CKB); } export function minimalCellCapacity( @@ -86,7 +88,7 @@ export function minimalCellCapacityCompatible( if (fullCell.data) { bytes += bytify(fullCell.data).length; } - return BI.from(bytes).mul(100000000); + return BI.from(bytes).mul(ONE_CKB); } export function locateCellDep( @@ -113,6 +115,16 @@ export function locateCellDep( let HAS_WARNED_FOR_DEPRECATED_ADDRESS = false; +// |format type|description | +// |-----------|----------------------------------------------------------| +// |0x00 |full version identifies the hash_type | +// |0x01 |short version for locks with popular code_hash, deprecated| +// |0x02 |full version with hash_type = "Data", deprecated | +// |0x04 |full version with hash_type = "Type", deprecated | + +const CKB2019_ADDRESS_FORMAT_TYPE_DATA = 0x02; +const CKB2019_ADDRESS_FORMAT_TYPE_TYPE = 0x04; + /** * @deprecated please migrate to {@link encodeToAddress}, the short format address will be removed in the future * @param script @@ -141,9 +153,13 @@ export function generateAddress( data.push(1, scriptTemplate.SHORT_ID); data.push(...hexToByteArray(script.args)); } else { - if (script.hashType === "type") data.push(0x04); - else if (script.hashType === "data") data.push(0x02); - else throw new Error(`Invalid hashType ${script.hashType}`); + if (script.hashType === "type") { + data.push(CKB2019_ADDRESS_FORMAT_TYPE_TYPE); + } else if (script.hashType === "data") { + data.push(CKB2019_ADDRESS_FORMAT_TYPE_DATA); + } else { + throw new Error(`Invalid hashType ${script.hashType}`); + } data.push(...hexToByteArray(script.codeHash)); data.push(...hexToByteArray(script.args)); @@ -514,3 +530,5 @@ export function objectToTransactionSkeleton( }); return txSkeleton; } + +export { refreshTypeIdCellDeps } from "./refresh"; diff --git a/packages/helpers/src/refresh.ts b/packages/helpers/src/refresh.ts new file mode 100644 index 000000000..78fc9a6b0 --- /dev/null +++ b/packages/helpers/src/refresh.ts @@ -0,0 +1,26 @@ +import { TransactionSkeletonType } from "./"; +import type { ResolveLatestOutPointsOfTypeIds } from "@ckb-lumos/config-manager/lib/refresh"; + +/** + * Refresh cellDeps of txSkeleton + * @example + * const resolve = createRpcResolver(rpc) + * // refresh the cell deps + * let txSkeleton = await refreshTypeIdCellDeps(txSkeleton, { resolve }) + * @param txSkeleton + * @param resolve + */ +export async function refreshTypeIdCellDeps( + txSkeleton: TransactionSkeletonType, + { resolve }: { resolve: ResolveLatestOutPointsOfTypeIds } +): Promise { + const outPoints = txSkeleton.cellDeps + .map(({ outPoint }) => outPoint) + .toArray(); + + const latestOutPoints = await resolve(outPoints); + + return txSkeleton.update("cellDeps", (cellDeps) => + cellDeps.map((cellDep, i) => ({ ...cellDep, outPoint: latestOutPoints[i] })) + ); +} diff --git a/packages/helpers/tests/refresh.test.ts b/packages/helpers/tests/refresh.test.ts new file mode 100644 index 000000000..6371c8121 --- /dev/null +++ b/packages/helpers/tests/refresh.test.ts @@ -0,0 +1,48 @@ +import test from "ava"; +import { refreshTypeIdCellDeps } from "../src/refresh"; +import { TransactionSkeleton } from "../src"; +import { CellDep } from "@ckb-lumos/base"; +import { bytes } from "@ckb-lumos/codec"; +import { randomBytes } from "node:crypto"; + +test("refreshTypeIdCellDeps", async (t) => { + const outdatedCellDep: CellDep = { + outPoint: { index: "0x0", txHash: bytes.hexify(randomBytes(32)) }, + depType: "code", + }; + const latestCellDep: CellDep = { + outPoint: { index: "0x0", txHash: bytes.hexify(randomBytes(32)) }, + depType: "code", + }; + + const normalCellDep: CellDep = { + outPoint: { index: "0x0", txHash: bytes.hexify(randomBytes(32)) }, + depType: "code", + }; + + const txSkeleton = TransactionSkeleton({}).asMutable(); + txSkeleton.update("cellDeps", (cellDeps) => + cellDeps.push(outdatedCellDep, normalCellDep) + ); + await refreshTypeIdCellDeps(txSkeleton, { + resolve: (outPoints) => + outPoints.map((outPoint) => { + if (outPoint.txHash === outdatedCellDep.outPoint.txHash) { + return latestCellDep.outPoint; + } + return outPoint; + }), + }); + + t.is( + txSkeleton.cellDeps.get(0)?.outPoint.txHash, + latestCellDep.outPoint.txHash + ); + + t.is( + txSkeleton.cellDeps.get(1)?.outPoint.txHash, + normalCellDep.outPoint.txHash + ); + + t.is(txSkeleton.cellDeps.size, 2); +}); diff --git a/packages/lumos/src/helpers.ts b/packages/lumos/src/helpers.ts index 5f0c0f34e..5febeb098 100644 --- a/packages/lumos/src/helpers.ts +++ b/packages/lumos/src/helpers.ts @@ -13,6 +13,7 @@ export { createTransactionFromSkeleton, sealTransaction, TransactionSkeleton, + refreshTypeIdCellDeps, type TransactionSkeletonType, type TransactionSkeletonInterface, type TransactionSkeletonObject,