@ckb-ccc/spore 0.1.0-alpha.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (223) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +61 -0
  3. package/dist/advanced.d.ts +5 -0
  4. package/dist/advanced.d.ts.map +1 -0
  5. package/dist/advanced.js +4 -0
  6. package/dist/cluster/index.d.ts +56 -0
  7. package/dist/cluster/index.d.ts.map +1 -0
  8. package/dist/cluster/index.js +96 -0
  9. package/dist/cobuild/index.d.ts +13 -0
  10. package/dist/cobuild/index.d.ts.map +1 -0
  11. package/dist/cobuild/index.js +168 -0
  12. package/dist/codec/base.d.ts +6 -0
  13. package/dist/codec/base.d.ts.map +1 -0
  14. package/dist/codec/base.js +10 -0
  15. package/dist/codec/cluster.d.ts +41 -0
  16. package/dist/codec/cluster.d.ts.map +1 -0
  17. package/dist/codec/cluster.js +73 -0
  18. package/dist/codec/cobuild/buildingPacket.d.ts +465 -0
  19. package/dist/codec/cobuild/buildingPacket.d.ts.map +1 -0
  20. package/dist/codec/cobuild/buildingPacket.js +44 -0
  21. package/dist/codec/cobuild/index.d.ts +4 -0
  22. package/dist/codec/cobuild/index.d.ts.map +1 -0
  23. package/dist/codec/cobuild/index.js +3 -0
  24. package/dist/codec/cobuild/sporeAction.d.ts +314 -0
  25. package/dist/codec/cobuild/sporeAction.d.ts.map +1 -0
  26. package/dist/codec/cobuild/sporeAction.js +104 -0
  27. package/dist/codec/cobuild/witnessLayout.d.ts +43 -0
  28. package/dist/codec/cobuild/witnessLayout.d.ts.map +1 -0
  29. package/dist/codec/cobuild/witnessLayout.js +27 -0
  30. package/dist/codec/index.d.ts +4 -0
  31. package/dist/codec/index.d.ts.map +1 -0
  32. package/dist/codec/index.js +3 -0
  33. package/dist/codec/spore.d.ts +15 -0
  34. package/dist/codec/spore.d.ts.map +1 -0
  35. package/dist/codec/spore.js +24 -0
  36. package/dist/dob/api/decode.d.ts +6 -0
  37. package/dist/dob/api/decode.d.ts.map +1 -0
  38. package/dist/dob/api/decode.js +44 -0
  39. package/dist/dob/api/encode.d.ts +5 -0
  40. package/dist/dob/api/encode.d.ts.map +1 -0
  41. package/dist/dob/api/encode.js +77 -0
  42. package/dist/dob/api/index.d.ts +3 -0
  43. package/dist/dob/api/index.d.ts.map +1 -0
  44. package/dist/dob/api/index.js +2 -0
  45. package/dist/dob/config/index.d.ts +2 -0
  46. package/dist/dob/config/index.d.ts.map +1 -0
  47. package/dist/dob/config/index.js +1 -0
  48. package/dist/dob/config/predefined.d.ts +8 -0
  49. package/dist/dob/config/predefined.d.ts.map +1 -0
  50. package/dist/dob/config/predefined.js +59 -0
  51. package/dist/dob/helper/check.d.ts +5 -0
  52. package/dist/dob/helper/check.d.ts.map +1 -0
  53. package/dist/dob/helper/check.js +75 -0
  54. package/dist/dob/helper/error.d.ts +2 -0
  55. package/dist/dob/helper/error.d.ts.map +1 -0
  56. package/dist/dob/helper/error.js +40 -0
  57. package/dist/dob/helper/index.d.ts +3 -0
  58. package/dist/dob/helper/index.d.ts.map +1 -0
  59. package/dist/dob/helper/index.js +2 -0
  60. package/dist/dob/helper/object.d.ts +59 -0
  61. package/dist/dob/helper/object.d.ts.map +1 -0
  62. package/dist/dob/helper/object.js +1 -0
  63. package/dist/dob/index.d.ts +4 -0
  64. package/dist/dob/index.d.ts.map +1 -0
  65. package/dist/dob/index.js +3 -0
  66. package/dist/helper/index.d.ts +9 -0
  67. package/dist/helper/index.d.ts.map +1 -0
  68. package/dist/helper/index.js +37 -0
  69. package/dist/index.d.ts +5 -0
  70. package/dist/index.d.ts.map +1 -0
  71. package/dist/index.js +4 -0
  72. package/dist/package.json +3 -0
  73. package/dist/predefined/advanced.d.ts +3 -0
  74. package/dist/predefined/advanced.d.ts.map +1 -0
  75. package/dist/predefined/advanced.js +2 -0
  76. package/dist/predefined/index.d.ts +3 -0
  77. package/dist/predefined/index.d.ts.map +1 -0
  78. package/dist/predefined/index.js +2 -0
  79. package/dist/predefined/mainnet.advanced.d.ts +4 -0
  80. package/dist/predefined/mainnet.advanced.d.ts.map +1 -0
  81. package/dist/predefined/mainnet.advanced.js +61 -0
  82. package/dist/predefined/testnet.advanced.d.ts +4 -0
  83. package/dist/predefined/testnet.advanced.d.ts.map +1 -0
  84. package/dist/predefined/testnet.advanced.js +88 -0
  85. package/dist/predefined/types.d.ts +17 -0
  86. package/dist/predefined/types.d.ts.map +1 -0
  87. package/dist/predefined/types.js +18 -0
  88. package/dist/predefined/utils.d.ts +7 -0
  89. package/dist/predefined/utils.d.ts.map +1 -0
  90. package/dist/predefined/utils.js +26 -0
  91. package/dist/spore/advanced.d.ts +5 -0
  92. package/dist/spore/advanced.d.ts.map +1 -0
  93. package/dist/spore/advanced.js +62 -0
  94. package/dist/spore/index.d.ts +80 -0
  95. package/dist/spore/index.d.ts.map +1 -0
  96. package/dist/spore/index.js +135 -0
  97. package/dist.commonjs/advanced.d.ts +5 -0
  98. package/dist.commonjs/advanced.d.ts.map +1 -0
  99. package/dist.commonjs/advanced.js +20 -0
  100. package/dist.commonjs/cluster/index.d.ts +56 -0
  101. package/dist.commonjs/cluster/index.d.ts.map +1 -0
  102. package/dist.commonjs/cluster/index.js +102 -0
  103. package/dist.commonjs/cobuild/index.d.ts +13 -0
  104. package/dist.commonjs/cobuild/index.d.ts.map +1 -0
  105. package/dist.commonjs/cobuild/index.js +179 -0
  106. package/dist.commonjs/codec/base.d.ts +6 -0
  107. package/dist.commonjs/codec/base.d.ts.map +1 -0
  108. package/dist.commonjs/codec/base.js +13 -0
  109. package/dist.commonjs/codec/cluster.d.ts +41 -0
  110. package/dist.commonjs/codec/cluster.d.ts.map +1 -0
  111. package/dist.commonjs/codec/cluster.js +82 -0
  112. package/dist.commonjs/codec/cobuild/buildingPacket.d.ts +465 -0
  113. package/dist.commonjs/codec/cobuild/buildingPacket.d.ts.map +1 -0
  114. package/dist.commonjs/codec/cobuild/buildingPacket.js +47 -0
  115. package/dist.commonjs/codec/cobuild/index.d.ts +4 -0
  116. package/dist.commonjs/codec/cobuild/index.d.ts.map +1 -0
  117. package/dist.commonjs/codec/cobuild/index.js +19 -0
  118. package/dist.commonjs/codec/cobuild/sporeAction.d.ts +314 -0
  119. package/dist.commonjs/codec/cobuild/sporeAction.d.ts.map +1 -0
  120. package/dist.commonjs/codec/cobuild/sporeAction.js +107 -0
  121. package/dist.commonjs/codec/cobuild/witnessLayout.d.ts +43 -0
  122. package/dist.commonjs/codec/cobuild/witnessLayout.d.ts.map +1 -0
  123. package/dist.commonjs/codec/cobuild/witnessLayout.js +30 -0
  124. package/dist.commonjs/codec/index.d.ts +4 -0
  125. package/dist.commonjs/codec/index.d.ts.map +1 -0
  126. package/dist.commonjs/codec/index.js +19 -0
  127. package/dist.commonjs/codec/spore.d.ts +15 -0
  128. package/dist.commonjs/codec/spore.d.ts.map +1 -0
  129. package/dist.commonjs/codec/spore.js +29 -0
  130. package/dist.commonjs/dob/api/decode.d.ts +6 -0
  131. package/dist.commonjs/dob/api/decode.d.ts.map +1 -0
  132. package/dist.commonjs/dob/api/decode.js +49 -0
  133. package/dist.commonjs/dob/api/encode.d.ts +5 -0
  134. package/dist.commonjs/dob/api/encode.d.ts.map +1 -0
  135. package/dist.commonjs/dob/api/encode.js +82 -0
  136. package/dist.commonjs/dob/api/index.d.ts +3 -0
  137. package/dist.commonjs/dob/api/index.d.ts.map +1 -0
  138. package/dist.commonjs/dob/api/index.js +18 -0
  139. package/dist.commonjs/dob/config/index.d.ts +2 -0
  140. package/dist.commonjs/dob/config/index.d.ts.map +1 -0
  141. package/dist.commonjs/dob/config/index.js +17 -0
  142. package/dist.commonjs/dob/config/predefined.d.ts +8 -0
  143. package/dist.commonjs/dob/config/predefined.d.ts.map +1 -0
  144. package/dist.commonjs/dob/config/predefined.js +63 -0
  145. package/dist.commonjs/dob/helper/check.d.ts +5 -0
  146. package/dist.commonjs/dob/helper/check.d.ts.map +1 -0
  147. package/dist.commonjs/dob/helper/check.js +80 -0
  148. package/dist.commonjs/dob/helper/error.d.ts +2 -0
  149. package/dist.commonjs/dob/helper/error.d.ts.map +1 -0
  150. package/dist.commonjs/dob/helper/error.js +43 -0
  151. package/dist.commonjs/dob/helper/index.d.ts +3 -0
  152. package/dist.commonjs/dob/helper/index.d.ts.map +1 -0
  153. package/dist.commonjs/dob/helper/index.js +18 -0
  154. package/dist.commonjs/dob/helper/object.d.ts +59 -0
  155. package/dist.commonjs/dob/helper/object.d.ts.map +1 -0
  156. package/dist.commonjs/dob/helper/object.js +2 -0
  157. package/dist.commonjs/dob/index.d.ts +4 -0
  158. package/dist.commonjs/dob/index.d.ts.map +1 -0
  159. package/dist.commonjs/dob/index.js +19 -0
  160. package/dist.commonjs/helper/index.d.ts +9 -0
  161. package/dist.commonjs/helper/index.d.ts.map +1 -0
  162. package/dist.commonjs/helper/index.js +42 -0
  163. package/dist.commonjs/index.d.ts +5 -0
  164. package/dist.commonjs/index.d.ts.map +1 -0
  165. package/dist.commonjs/index.js +33 -0
  166. package/dist.commonjs/package.json +3 -0
  167. package/dist.commonjs/predefined/advanced.d.ts +3 -0
  168. package/dist.commonjs/predefined/advanced.d.ts.map +1 -0
  169. package/dist.commonjs/predefined/advanced.js +18 -0
  170. package/dist.commonjs/predefined/index.d.ts +3 -0
  171. package/dist.commonjs/predefined/index.d.ts.map +1 -0
  172. package/dist.commonjs/predefined/index.js +18 -0
  173. package/dist.commonjs/predefined/mainnet.advanced.d.ts +4 -0
  174. package/dist.commonjs/predefined/mainnet.advanced.d.ts.map +1 -0
  175. package/dist.commonjs/predefined/mainnet.advanced.js +64 -0
  176. package/dist.commonjs/predefined/testnet.advanced.d.ts +4 -0
  177. package/dist.commonjs/predefined/testnet.advanced.d.ts.map +1 -0
  178. package/dist.commonjs/predefined/testnet.advanced.js +91 -0
  179. package/dist.commonjs/predefined/types.d.ts +17 -0
  180. package/dist.commonjs/predefined/types.d.ts.map +1 -0
  181. package/dist.commonjs/predefined/types.js +22 -0
  182. package/dist.commonjs/predefined/utils.d.ts +7 -0
  183. package/dist.commonjs/predefined/utils.d.ts.map +1 -0
  184. package/dist.commonjs/predefined/utils.js +32 -0
  185. package/dist.commonjs/spore/advanced.d.ts +5 -0
  186. package/dist.commonjs/spore/advanced.d.ts.map +1 -0
  187. package/dist.commonjs/spore/advanced.js +65 -0
  188. package/dist.commonjs/spore/index.d.ts +80 -0
  189. package/dist.commonjs/spore/index.d.ts.map +1 -0
  190. package/dist.commonjs/spore/index.js +142 -0
  191. package/package.json +52 -0
  192. package/src/advanced.ts +4 -0
  193. package/src/cluster/index.ts +180 -0
  194. package/src/cobuild/index.ts +220 -0
  195. package/src/codec/base.ts +11 -0
  196. package/src/codec/cluster.ts +133 -0
  197. package/src/codec/cobuild/buildingPacket.ts +72 -0
  198. package/src/codec/cobuild/index.ts +3 -0
  199. package/src/codec/cobuild/sporeAction.ts +153 -0
  200. package/src/codec/cobuild/witnessLayout.ts +40 -0
  201. package/src/codec/index.ts +3 -0
  202. package/src/codec/spore.ts +36 -0
  203. package/src/dob/api/decode.ts +61 -0
  204. package/src/dob/api/encode.ts +84 -0
  205. package/src/dob/api/index.ts +2 -0
  206. package/src/dob/config/index.ts +1 -0
  207. package/src/dob/config/predefined.ts +71 -0
  208. package/src/dob/helper/check.ts +107 -0
  209. package/src/dob/helper/error.ts +41 -0
  210. package/src/dob/helper/index.ts +2 -0
  211. package/src/dob/helper/object.ts +66 -0
  212. package/src/dob/index.ts +3 -0
  213. package/src/helper/index.ts +68 -0
  214. package/src/index.ts +4 -0
  215. package/src/predefined/advanced.ts +2 -0
  216. package/src/predefined/index.ts +2 -0
  217. package/src/predefined/mainnet.advanced.ts +76 -0
  218. package/src/predefined/testnet.advanced.ts +107 -0
  219. package/src/predefined/types.ts +37 -0
  220. package/src/predefined/utils.ts +56 -0
  221. package/src/spore/advanced.ts +88 -0
  222. package/src/spore/index.ts +236 -0
  223. package/typedoc.json +6 -0
package/package.json ADDED
@@ -0,0 +1,52 @@
1
+ {
2
+ "name": "@ckb-ccc/spore",
3
+ "version": "0.1.0-alpha.2",
4
+ "description": "CCC - CKBer's Codebase. Common Chains Connector's support for Spore protocol",
5
+ "author": "ashuralyk <ashuralyk@live.com>",
6
+ "license": "MIT",
7
+ "private": false,
8
+ "homepage": "https://github.com/ckb-ecofund/ccc",
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "git://github.com/ckb-ecofund/ccc.git"
12
+ },
13
+ "main": "dist.commonjs/index.js",
14
+ "module": "dist/index.js",
15
+ "exports": {
16
+ ".": {
17
+ "import": "./dist/index.js",
18
+ "default": "./dist.commonjs/index.js"
19
+ },
20
+ "./advanced": {
21
+ "import": "./dist/advanced.js",
22
+ "default": "./dist.commonjs/advanced.js"
23
+ }
24
+ },
25
+ "devDependencies": {
26
+ "@eslint/js": "^9.1.1",
27
+ "copyfiles": "^2.4.1",
28
+ "eslint": "^9.1.0",
29
+ "eslint-config-prettier": "^9.1.0",
30
+ "eslint-plugin-prettier": "^5.1.3",
31
+ "prettier": "^3.2.5",
32
+ "prettier-plugin-organize-imports": "^3.2.4",
33
+ "rimraf": "^5.0.5",
34
+ "typescript": "^5.4.5",
35
+ "typescript-eslint": "^7.7.0",
36
+ "dotenv": "^16.4.5"
37
+ },
38
+ "publishConfig": {
39
+ "access": "public"
40
+ },
41
+ "dependencies": {
42
+ "@ckb-lumos/base": "^0.24.0-next.1",
43
+ "@ckb-lumos/codec": "^0.24.0-next.1",
44
+ "axios": "^1.7.7",
45
+ "@ckb-ccc/core": "0.1.0-alpha.4"
46
+ },
47
+ "scripts": {
48
+ "build": "rimraf ./dist && rimraf ./dist.commonjs && tsc && tsc --project tsconfig.commonjs.json && copyfiles -u 2 misc/basedirs/**/* .",
49
+ "lint": "eslint ./src",
50
+ "format": "prettier --write . && eslint --fix ./src"
51
+ }
52
+ }
@@ -0,0 +1,4 @@
1
+ export * from "./cobuild/index.js";
2
+ export * from "./codec/index.js";
3
+ export * from "./predefined/advanced.js";
4
+ export * from "./spore/advanced.js";
@@ -0,0 +1,180 @@
1
+ import { ccc } from "@ckb-ccc/core";
2
+ import {
3
+ assembleCreateClusterAction,
4
+ assembleTransferClusterAction,
5
+ prepareSporeTransaction,
6
+ } from "../advanced.js";
7
+ import { ClusterData, packRawClusterData } from "../codec/index.js";
8
+ import {
9
+ findSingletonCellByArgs,
10
+ injectOneCapacityCell,
11
+ } from "../helper/index.js";
12
+ import {
13
+ SporeScriptInfo,
14
+ SporeScriptInfoLike,
15
+ getClusterScriptInfo,
16
+ getClusterScriptInfos,
17
+ } from "../predefined/index.js";
18
+
19
+ export async function findCluster(
20
+ client: ccc.Client,
21
+ args: ccc.HexLike,
22
+ scripts?: SporeScriptInfoLike[],
23
+ ): Promise<
24
+ | {
25
+ cell: ccc.Cell;
26
+ scriptInfo: SporeScriptInfo;
27
+ }
28
+ | undefined
29
+ > {
30
+ return findSingletonCellByArgs(
31
+ client,
32
+ args,
33
+ scripts ?? Object.values(getClusterScriptInfos(client)),
34
+ );
35
+ }
36
+
37
+ export async function assertCluster(
38
+ client: ccc.Client,
39
+ args: ccc.HexLike,
40
+ scripts?: SporeScriptInfoLike[],
41
+ ): Promise<{
42
+ cell: ccc.Cell;
43
+ scriptInfo: SporeScriptInfo;
44
+ }> {
45
+ const res = await findCluster(client, args, scripts);
46
+
47
+ if (!res) {
48
+ throw new Error(`Cluster ${ccc.hexFrom(args)} not found`);
49
+ }
50
+
51
+ return res;
52
+ }
53
+
54
+ /**
55
+ * Create a new Cluster cell
56
+ *
57
+ * @param signer who takes the responsibility to balance and sign the transaction
58
+ * @param data specific format of data required by Cluster protocol
59
+ * @param to the owner of the Cluster cell, which will be replaced with signer if not provided
60
+ * @param tx the transaction skeleton, if not provided, a new one will be created
61
+ * @param scriptInfo the script info of new cluster, default spore version if undefined
62
+ * @param scriptInfoHash the script info hash used in cobuild
63
+ * @returns
64
+ * - **tx**: a new transaction that contains created Cluster cell
65
+ * - **id**: the id of the created Cluster cell
66
+ */
67
+ export async function createSporeCluster(params: {
68
+ signer: ccc.Signer;
69
+ data: ClusterData;
70
+ to?: ccc.ScriptLike;
71
+ tx?: ccc.TransactionLike;
72
+ scriptInfo?: SporeScriptInfoLike;
73
+ scriptInfoHash?: ccc.HexLike;
74
+ }): Promise<{
75
+ tx: ccc.Transaction;
76
+ id: ccc.Hex;
77
+ }> {
78
+ const { signer, data, to, scriptInfoHash } = params;
79
+ const scriptInfo = params.scriptInfo ?? getClusterScriptInfo(signer.client);
80
+
81
+ // prepare transaction
82
+ const tx = ccc.Transaction.from(params.tx ?? {});
83
+ if (tx.inputs.length === 0) {
84
+ await injectOneCapacityCell(signer, tx);
85
+ }
86
+
87
+ // build cluster cell
88
+ const id = ccc.hashTypeId(tx.inputs[0], tx.outputs.length);
89
+ const packedClusterData = packRawClusterData(data);
90
+ tx.addOutput(
91
+ {
92
+ lock: to ?? (await signer.getRecommendedAddressObj()).script,
93
+ type: {
94
+ ...scriptInfo,
95
+ args: id,
96
+ },
97
+ },
98
+ packedClusterData,
99
+ );
100
+
101
+ // complete cellDeps
102
+ await tx.addCellDepInfos(signer.client, scriptInfo.cellDeps);
103
+
104
+ // generate cobuild action
105
+ const actions = scriptInfo.cobuild
106
+ ? [
107
+ assembleCreateClusterAction(
108
+ tx.outputs[tx.outputs.length - 1],
109
+ packedClusterData,
110
+ scriptInfoHash,
111
+ ),
112
+ ]
113
+ : [];
114
+
115
+ return {
116
+ tx: await prepareSporeTransaction(signer, tx, actions),
117
+ id,
118
+ };
119
+ }
120
+
121
+ /**
122
+ * Transfer a Cluster cell
123
+ *
124
+ * @param signer who takes the responsibility to balance and sign the transaction
125
+ * @param id the id of the Cluster cell to be transferred
126
+ * @param to the new owner of the Cluster cell
127
+ * @param tx the transaction skeleton, if not provided, a new one will be created
128
+ * @param scriptInfoHash the script info hash used in cobuild
129
+ * @returns
130
+ * - **tx**: a new transaction that contains transferred Cluster cell
131
+ */
132
+ export async function transferSporeCluster(params: {
133
+ signer: ccc.Signer;
134
+ id: ccc.HexLike;
135
+ to: ccc.ScriptLike;
136
+ tx?: ccc.TransactionLike;
137
+ scriptInfoHash?: ccc.HexLike;
138
+ }): Promise<{
139
+ tx: ccc.Transaction;
140
+ }> {
141
+ const { signer, id, to, scriptInfoHash } = params;
142
+
143
+ // prepare transaction
144
+ const tx = ccc.Transaction.from(params.tx ?? {});
145
+
146
+ // build cluster cell
147
+ const { cell: cluster, scriptInfo } = await assertCluster(signer.client, id);
148
+
149
+ tx.inputs.push(
150
+ ccc.CellInput.from({
151
+ previousOutput: cluster.outPoint,
152
+ ...cluster,
153
+ }),
154
+ );
155
+ tx.addOutput(
156
+ {
157
+ lock: to,
158
+ type: cluster.cellOutput.type,
159
+ },
160
+ cluster.outputData,
161
+ );
162
+
163
+ // complete cellDeps
164
+ await tx.addCellDepInfos(signer.client, scriptInfo.cellDeps);
165
+
166
+ // generate cobuild action
167
+ const actions = scriptInfo.cobuild
168
+ ? [
169
+ assembleTransferClusterAction(
170
+ cluster.cellOutput,
171
+ tx.outputs[tx.outputs.length - 1],
172
+ scriptInfoHash,
173
+ ),
174
+ ]
175
+ : [];
176
+
177
+ return {
178
+ tx: await prepareSporeTransaction(signer, tx, actions),
179
+ };
180
+ }
@@ -0,0 +1,220 @@
1
+ import { ccc } from "@ckb-ccc/core";
2
+ import { UnpackResult } from "@ckb-lumos/codec";
3
+ import {
4
+ Action,
5
+ ActionVec,
6
+ SporeAction,
7
+ WitnessLayout,
8
+ } from "../codec/index.js";
9
+ import { DEFAULT_COBUILD_INFO_HASH } from "../predefined/index.js";
10
+
11
+ export function assembleCreateSporeAction(
12
+ sporeOutput: ccc.CellOutputLike,
13
+ sporeData: ccc.BytesLike,
14
+ scriptInfoHash: ccc.HexLike = DEFAULT_COBUILD_INFO_HASH,
15
+ ): UnpackResult<typeof Action> {
16
+ if (!sporeOutput.type) {
17
+ throw new Error("Spore cell must have a type script");
18
+ }
19
+ const sporeType = ccc.Script.from(sporeOutput.type);
20
+ const sporeTypeHash = sporeType.hash();
21
+ const actionData = SporeAction.pack({
22
+ type: "CreateSpore",
23
+ value: {
24
+ sporeId: sporeType.args,
25
+ dataHash: ccc.hashCkb(sporeData),
26
+ to: {
27
+ type: "Script",
28
+ value: ccc.Script.from(sporeOutput.lock),
29
+ },
30
+ },
31
+ });
32
+ return {
33
+ scriptInfoHash: ccc.hexFrom(scriptInfoHash),
34
+ scriptHash: sporeTypeHash,
35
+ data: ccc.hexFrom(actionData),
36
+ };
37
+ }
38
+
39
+ export function assembleTransferSporeAction(
40
+ sporeInput: ccc.CellOutputLike,
41
+ sporeOutput: ccc.CellOutputLike,
42
+ scriptInfoHash: ccc.HexLike = DEFAULT_COBUILD_INFO_HASH,
43
+ ): UnpackResult<typeof Action> {
44
+ if (!sporeInput.type || !sporeOutput.type) {
45
+ throw new Error("Spore cell must have a type script");
46
+ }
47
+
48
+ const sporeType = ccc.Script.from(sporeOutput.type);
49
+ const sporeTypeHash = sporeType.hash();
50
+ const actionData = SporeAction.pack({
51
+ type: "TransferSpore",
52
+ value: {
53
+ sporeId: sporeType.args,
54
+ from: {
55
+ type: "Script",
56
+ value: ccc.Script.from(sporeInput.lock),
57
+ },
58
+ to: {
59
+ type: "Script",
60
+ value: ccc.Script.from(sporeOutput.lock),
61
+ },
62
+ },
63
+ });
64
+ return {
65
+ scriptInfoHash: ccc.hexFrom(scriptInfoHash),
66
+ scriptHash: sporeTypeHash,
67
+ data: ccc.hexFrom(actionData),
68
+ };
69
+ }
70
+
71
+ export function assembleMeltSporeAction(
72
+ sporeInput: ccc.CellOutputLike,
73
+ scriptInfoHash: ccc.HexLike = DEFAULT_COBUILD_INFO_HASH,
74
+ ): UnpackResult<typeof Action> {
75
+ if (!sporeInput.type) {
76
+ throw new Error("Spore cell must have a type script");
77
+ }
78
+ const sporeType = ccc.Script.from(sporeInput.type);
79
+ const sporeTypeHash = sporeType.hash();
80
+ const actionData = SporeAction.pack({
81
+ type: "MeltSpore",
82
+ value: {
83
+ sporeId: sporeType.args,
84
+ from: {
85
+ type: "Script",
86
+ value: ccc.Script.from(sporeInput.lock),
87
+ },
88
+ },
89
+ });
90
+ return {
91
+ scriptInfoHash: ccc.hexFrom(scriptInfoHash),
92
+ scriptHash: sporeTypeHash,
93
+ data: ccc.hexFrom(actionData),
94
+ };
95
+ }
96
+
97
+ export function assembleCreateClusterAction(
98
+ clusterOutput: ccc.CellOutputLike,
99
+ clusterData: ccc.BytesLike,
100
+ scriptInfoHash: ccc.HexLike = DEFAULT_COBUILD_INFO_HASH,
101
+ ): UnpackResult<typeof Action> {
102
+ if (!clusterOutput.type) {
103
+ throw new Error("Cluster cell must have a type script");
104
+ }
105
+ const clusterType = ccc.Script.from(clusterOutput.type);
106
+ const clusterTypeHash = clusterType.hash();
107
+ const actionData = SporeAction.pack({
108
+ type: "CreateCluster",
109
+ value: {
110
+ clusterId: clusterType.args,
111
+ dataHash: ccc.hashCkb(clusterData),
112
+ to: {
113
+ type: "Script",
114
+ value: ccc.Script.from(clusterOutput.lock),
115
+ },
116
+ },
117
+ });
118
+ return {
119
+ scriptInfoHash: ccc.hexFrom(scriptInfoHash),
120
+ scriptHash: clusterTypeHash,
121
+ data: ccc.hexFrom(actionData),
122
+ };
123
+ }
124
+
125
+ export function assembleTransferClusterAction(
126
+ clusterInput: ccc.CellOutputLike,
127
+ clusterOutput: ccc.CellOutputLike,
128
+ scriptInfoHash: ccc.HexLike = DEFAULT_COBUILD_INFO_HASH,
129
+ ): UnpackResult<typeof Action> {
130
+ if (!clusterInput.type || !clusterOutput.type) {
131
+ throw new Error("Cluster cell must have a type script");
132
+ }
133
+ const clusterType = ccc.Script.from(clusterOutput.type);
134
+ const clusterTypeHash = clusterType.hash();
135
+ const actionData = SporeAction.pack({
136
+ type: "TransferCluster",
137
+ value: {
138
+ clusterId: clusterType.args,
139
+ from: {
140
+ type: "Script",
141
+ value: ccc.Script.from(clusterInput.lock),
142
+ },
143
+ to: {
144
+ type: "Script",
145
+ value: ccc.Script.from(clusterOutput.lock),
146
+ },
147
+ },
148
+ });
149
+ return {
150
+ scriptInfoHash: ccc.hexFrom(scriptInfoHash),
151
+ scriptHash: clusterTypeHash,
152
+ data: ccc.hexFrom(actionData),
153
+ };
154
+ }
155
+
156
+ export async function prepareSporeTransaction(
157
+ signer: ccc.Signer,
158
+ txLike: ccc.TransactionLike,
159
+ actions: UnpackResult<typeof ActionVec>,
160
+ ): Promise<ccc.Transaction> {
161
+ let tx = ccc.Transaction.from(txLike);
162
+
163
+ if (actions.length === 0) {
164
+ return signer.prepareTransaction(tx);
165
+ }
166
+
167
+ const existedActions = extractCobuildActionsFromTx(tx);
168
+ tx = await signer.prepareTransaction(tx);
169
+ injectCobuild(tx, [...existedActions, ...actions]);
170
+ return tx;
171
+ }
172
+
173
+ export function unpackCommonCobuildProof(
174
+ data: ccc.HexLike,
175
+ ): UnpackResult<typeof WitnessLayout> | undefined {
176
+ try {
177
+ return WitnessLayout.unpack(ccc.bytesFrom(data));
178
+ } catch {
179
+ return;
180
+ }
181
+ }
182
+
183
+ export function extractCobuildActionsFromTx(
184
+ tx: ccc.Transaction,
185
+ ): UnpackResult<typeof ActionVec> {
186
+ if (tx.witnesses.length === 0) {
187
+ return [];
188
+ }
189
+ const witnessLayout = unpackCommonCobuildProof(
190
+ tx.witnesses[tx.witnesses.length - 1],
191
+ );
192
+ if (!witnessLayout) {
193
+ return [];
194
+ }
195
+ if (witnessLayout.type !== "SighashAll") {
196
+ throw new Error("Invalid cobuild proof type: " + witnessLayout.type);
197
+ }
198
+
199
+ // Remove existed cobuild witness
200
+ tx.witnesses.pop();
201
+ return witnessLayout.value.message.actions;
202
+ }
203
+
204
+ export function injectCobuild(
205
+ tx: ccc.Transaction,
206
+ actions: UnpackResult<typeof ActionVec>,
207
+ ): void {
208
+ const witnessLayout = ccc.hexFrom(
209
+ WitnessLayout.pack({
210
+ type: "SighashAll",
211
+ value: {
212
+ seal: "0x",
213
+ message: {
214
+ actions,
215
+ },
216
+ },
217
+ }),
218
+ );
219
+ tx.witnesses.push(ccc.hexFrom(witnessLayout));
220
+ }
@@ -0,0 +1,11 @@
1
+ import { ccc } from "@ckb-ccc/core";
2
+ import { molecule } from "@ckb-lumos/codec";
3
+
4
+ /**
5
+ * The codec for packing/unpacking UTF-8 raw strings.
6
+ * Should be packed like so: String.pack('something')
7
+ */
8
+ export const RawString = molecule.byteVecOf({
9
+ pack: (packable: string) => ccc.bytesFrom(packable, "utf8"),
10
+ unpack: (unpackable: ccc.BytesLike) => ccc.bytesTo(unpackable, "utf8"),
11
+ });
@@ -0,0 +1,133 @@
1
+ import { ccc } from "@ckb-ccc/core";
2
+ import { blockchain } from "@ckb-lumos/base";
3
+ import { molecule } from "@ckb-lumos/codec";
4
+ import { RawString } from "./base.js";
5
+
6
+ export const MolClusterDataV1 = molecule.table(
7
+ {
8
+ name: RawString,
9
+ description: RawString,
10
+ },
11
+ ["name", "description"],
12
+ );
13
+ export const MolClusterDataV2 = molecule.table(
14
+ {
15
+ name: RawString,
16
+ description: RawString,
17
+ mutantId: blockchain.BytesOpt,
18
+ },
19
+ ["name", "description", "mutantId"],
20
+ );
21
+
22
+ export interface ClusterDataV1 {
23
+ name: string;
24
+ description: string;
25
+ }
26
+ export interface ClusterDataV2 {
27
+ name: string;
28
+ description: string;
29
+ mutantId?: ccc.HexLike;
30
+ }
31
+ export type ClusterData = ClusterDataV2;
32
+
33
+ export type ClusterDataVersion = "v1" | "v2";
34
+
35
+ /**
36
+ * Pack RawClusterData to Uint8Array.
37
+ * Pass an optional "version" field to select a specific packing version.
38
+ */
39
+ export function packRawClusterData(packable: ClusterData): Uint8Array;
40
+ export function packRawClusterData(
41
+ packable: ClusterDataV1,
42
+ version: "v1",
43
+ ): Uint8Array;
44
+ export function packRawClusterData(
45
+ packable: ClusterDataV2,
46
+ version: "v2",
47
+ ): Uint8Array;
48
+ export function packRawClusterData(
49
+ packable: ClusterDataV1 | ClusterDataV2,
50
+ version?: ClusterDataVersion,
51
+ ): Uint8Array {
52
+ if (!version) {
53
+ return packRawClusterDataV2(packable);
54
+ }
55
+
56
+ switch (version) {
57
+ case "v1":
58
+ return packRawClusterDataV1(packable);
59
+ case "v2":
60
+ return packRawClusterDataV2(packable);
61
+ }
62
+ }
63
+ export function packRawClusterDataV1(packable: ClusterDataV1): Uint8Array {
64
+ return MolClusterDataV1.pack({
65
+ name: packable.name,
66
+ description: packable.description,
67
+ });
68
+ }
69
+ export function packRawClusterDataV2(packable: ClusterDataV2): Uint8Array {
70
+ return MolClusterDataV2.pack({
71
+ name: packable.name,
72
+ description: packable.description,
73
+ mutantId: packable.mutantId,
74
+ });
75
+ }
76
+
77
+ /**
78
+ * Unpack Hex/Bytes to RawClusterData.
79
+ * Pass an optional "version" field to select a specific unpacking version.
80
+ */
81
+ export function unpackToRawClusterData(unpackable: ccc.BytesLike): ClusterData;
82
+ export function unpackToRawClusterData(
83
+ unpackable: ccc.BytesLike,
84
+ version: "v1",
85
+ ): ClusterDataV1;
86
+ export function unpackToRawClusterData(
87
+ unpackable: ccc.BytesLike,
88
+ version: "v2",
89
+ ): ClusterDataV2;
90
+ export function unpackToRawClusterData(
91
+ unpackable: ccc.BytesLike,
92
+ version?: ClusterDataVersion,
93
+ ): unknown {
94
+ if (version) {
95
+ switch (version) {
96
+ case "v1":
97
+ return unpackToRawClusterDataV1(unpackable);
98
+ case "v2":
99
+ return unpackToRawClusterDataV2(unpackable);
100
+ }
101
+ }
102
+
103
+ try {
104
+ return unpackToRawClusterDataV2(unpackable);
105
+ } catch {
106
+ try {
107
+ return unpackToRawClusterDataV1(unpackable);
108
+ } catch {
109
+ throw new Error(
110
+ `Cannot unpack ClusterData, no matching molecule: ${ccc.hexFrom(unpackable)}`,
111
+ );
112
+ }
113
+ }
114
+ }
115
+ export function unpackToRawClusterDataV1(
116
+ unpackable: ccc.BytesLike,
117
+ ): ClusterDataV1 {
118
+ const decoded = MolClusterDataV1.unpack(unpackable);
119
+ return {
120
+ name: decoded.name,
121
+ description: decoded.description,
122
+ };
123
+ }
124
+ export function unpackToRawClusterDataV2(
125
+ unpackable: ccc.BytesLike,
126
+ ): ClusterDataV2 {
127
+ const decoded = MolClusterDataV2.unpack(unpackable);
128
+ return {
129
+ name: decoded.name,
130
+ description: decoded.description,
131
+ mutantId: ccc.apply(ccc.hexFrom, decoded.mutantId),
132
+ };
133
+ }
@@ -0,0 +1,72 @@
1
+ import { blockchain } from "@ckb-lumos/base";
2
+ import { molecule, number } from "@ckb-lumos/codec";
3
+ import { RawString } from "../base.js";
4
+
5
+ const Uint32Opt = molecule.option(number.Uint32LE);
6
+
7
+ const Hash = blockchain.Byte32;
8
+
9
+ export const Action = molecule.table(
10
+ {
11
+ scriptInfoHash: Hash,
12
+ scriptHash: Hash,
13
+ data: blockchain.Bytes,
14
+ },
15
+ ["scriptInfoHash", "scriptHash", "data"],
16
+ );
17
+
18
+ export const ActionVec = molecule.vector(Action);
19
+
20
+ export const Message = molecule.table(
21
+ {
22
+ actions: ActionVec,
23
+ },
24
+ ["actions"],
25
+ );
26
+
27
+ export const ResolvedInputs = molecule.table(
28
+ {
29
+ outputs: blockchain.CellOutputVec,
30
+ outputsData: blockchain.BytesVec,
31
+ },
32
+ ["outputs", "outputsData"],
33
+ );
34
+
35
+ export const ScriptInfo = molecule.table(
36
+ {
37
+ name: RawString,
38
+ url: RawString,
39
+ scriptHash: Hash,
40
+ schema: RawString,
41
+ messageType: RawString,
42
+ },
43
+ ["name", "url", "scriptHash", "schema", "messageType"],
44
+ );
45
+
46
+ export const ScriptInfoVec = molecule.vector(ScriptInfo);
47
+
48
+ export const BuildingPacketV1 = molecule.table(
49
+ {
50
+ message: Message,
51
+ payload: blockchain.Transaction,
52
+ resolvedInputs: ResolvedInputs,
53
+ changeOutput: Uint32Opt,
54
+ scriptInfos: ScriptInfoVec,
55
+ lockActions: ActionVec,
56
+ },
57
+ [
58
+ "message",
59
+ "payload",
60
+ "resolvedInputs",
61
+ "changeOutput",
62
+ "scriptInfos",
63
+ "lockActions",
64
+ ],
65
+ );
66
+
67
+ export const BuildingPacket = molecule.union(
68
+ {
69
+ BuildingPacketV1,
70
+ },
71
+ ["BuildingPacketV1"],
72
+ );
@@ -0,0 +1,3 @@
1
+ export * from "./buildingPacket.js";
2
+ export * from "./sporeAction.js";
3
+ export * from "./witnessLayout.js";