-
Notifications
You must be signed in to change notification settings - Fork 34
feat: add register ssri method #348
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: releases/udt
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,47 @@ | ||
| import { ccc } from "@ckb-ccc/ccc"; | ||
| import { render, signer } from "@ckb-ccc/playground"; | ||
|
|
||
| // Prepare the UDT trait | ||
| const type = ccc.Script.from({ | ||
| codeHash: | ||
| "0x8b887e59f396f99302996ee8911b31f73fb2e2be4d9cade3104f017a871b8ed3", | ||
| hashType: "type", | ||
| // Equal to the TypeId args of metadata cell, UDT would use it to search metadata cell | ||
| // for extracting the metadata. It can be empty if no metadata cell deployed on the chain. | ||
| args: "0x1e370b8965e12faf572a0f7ca7bf585027404ee23c32a82ef049965d5ebb8ff6", | ||
| }); | ||
|
|
||
| const code = ccc.OutPoint.from({ | ||
| // SSRI-UDT script deployment tx hash on Testnet | ||
| txHash: "0x1fecfac56696b38d76304f9e2dc1db39406679f3a6e517d5ed16bddbd8fdd7ab", | ||
| index: 0, | ||
| }); | ||
|
|
||
| const executor = new ccc.ssri.ExecutorJsonRpc("http://localhost:9090"); // Linking to your native SSRI-Server | ||
| const udt = new ccc.udt.UdtRegister(code, type, { | ||
| executor, | ||
| }); | ||
|
|
||
| // Register the UDT with metadata | ||
| const { tx: registerTx, tokenHash: metadataTypeIdArgs } = await udt.register( | ||
| signer, | ||
| { | ||
| name: "SSRI UDT", | ||
| symbol: "WSS", | ||
| decimals: 8, | ||
| icon: "", | ||
| }, | ||
| ); | ||
|
|
||
| // Get the metadata TypeId args, then you can use it to mint UDT tokens | ||
| console.log("metadataTypeIdArgs =", metadataTypeIdArgs); | ||
|
|
||
| const tx = registerTx.res; | ||
| await render(tx); | ||
|
|
||
| // Complete missing parts: Pay fee | ||
| await tx.completeFeeBy(signer); | ||
| await render(tx); | ||
|
|
||
| const txHash = await signer.sendTransaction(tx); | ||
| console.log("tx hash =", txHash); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,2 +1,3 @@ | ||
| export * from "./udt/index.js"; | ||
| export * from "./udtPausable/index.js"; | ||
| export * from "./udtRegister/index.js"; |
| Original file line number | Diff line number | Diff line change | ||||||
|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,130 @@ | ||||||||
| import { ccc } from "@ckb-ccc/core"; | ||||||||
| import { ssri } from "@ckb-ccc/ssri"; | ||||||||
| import { Udt, UdtConfigLike } from "../udt/index.js"; | ||||||||
|
|
||||||||
| /** | ||||||||
| * The basic metadata of a UDT token. | ||||||||
| * | ||||||||
| * @example | ||||||||
| * ```typescript | ||||||||
| * const metadataMolecule = UdtMetadata.encode({ | ||||||||
| * name: "My UDT", | ||||||||
| * symbol: "MYUDT", | ||||||||
| * decimals: 8, | ||||||||
| * icon: "https://example.com/icon.png", | ||||||||
| * }); | ||||||||
| * ``` | ||||||||
| * | ||||||||
| * @public | ||||||||
| * @category UDT | ||||||||
| */ | ||||||||
| export const UdtMetadata = ccc.mol.table({ | ||||||||
| name: ccc.mol.String, | ||||||||
| symbol: ccc.mol.String, | ||||||||
| decimals: ccc.mol.Uint8, | ||||||||
| icon: ccc.mol.String, | ||||||||
| }); | ||||||||
|
|
||||||||
| /** | ||||||||
| * Represents a UDT (User Defined Token) with separated SSRI metadata functionality. | ||||||||
| * @extends {Udt} This must be a SSRI UDT that does not fallback to xUDT. | ||||||||
| * @public | ||||||||
| */ | ||||||||
| export class UdtRegister extends Udt { | ||||||||
| constructor( | ||||||||
| code: ccc.OutPointLike, | ||||||||
| script: ccc.ScriptLike, | ||||||||
| config: UdtConfigLike & { executor: ssri.Executor }, | ||||||||
| ) { | ||||||||
| super(code, script, config); | ||||||||
| } | ||||||||
|
|
||||||||
| /** | ||||||||
| * Registers (creates) a new UDT with on-chain metadata. | ||||||||
| * This method creates a new unique UDT instance (usually with a TypeId pattern), | ||||||||
| * assigns on-chain metadata (name, symbol, decimals, icon), and returns a transaction | ||||||||
| * to instantiate the new token. Often used by the deployer/owner. | ||||||||
| * | ||||||||
| * @param signer - The signer (owner) who will initialize and own the new UDT | ||||||||
| * @param metadata - Object containing UDT metadata (name, symbol, decimals, icon) | ||||||||
| * @param tx - Optional existing transaction to build upon | ||||||||
| * @returns Promise resolving to `{ tx, tokenHash }`, where `tx` is the deployment transaction, | ||||||||
| * and `tokenHash` is the computed TypeId/Token hash of the new UDT | ||||||||
| * | ||||||||
| * @example | ||||||||
| * ```typescript | ||||||||
| * const udt = new Udt(codeOutPoint, scriptConfig); | ||||||||
| * const { tx, tokenHash } = await udt.register( | ||||||||
| * signer, | ||||||||
| * { name: "My UDT", symbol: "MYT", decimals: 8, icon: "https://..." } | ||||||||
| * ); | ||||||||
| * // Send tx.res or complete tx.res and send the transaction | ||||||||
| * ``` | ||||||||
| * | ||||||||
| * @remarks | ||||||||
| * - Uses SSRI executor if available for advanced/SSRI-compliant registration. | ||||||||
| * - Falls back to legacy registration (TypeId pattern) if no executor is present. | ||||||||
| * - The token hash can be used as the args for the UDT type script. | ||||||||
| */ | ||||||||
| async register( | ||||||||
| signer: ccc.Signer, | ||||||||
| metadata: { | ||||||||
| name: string; | ||||||||
| symbol: string; | ||||||||
| decimals: number; | ||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The
Suggested change
|
||||||||
| icon: string; | ||||||||
| }, | ||||||||
| tx?: ccc.TransactionLike | null, | ||||||||
| ): Promise<{ | ||||||||
| tx: ssri.ExecutorResponse<ccc.Transaction>; | ||||||||
| tokenHash: ccc.Hex; | ||||||||
| }> { | ||||||||
| const owner = await signer.getRecommendedAddressObj(); | ||||||||
| const register = ccc.Transaction.from(tx ?? {}); | ||||||||
| if (register.inputs.length === 0) { | ||||||||
| await register.completeInputsAtLeastOne(signer); // For `TypeId` calcuclation | ||||||||
| } | ||||||||
| const tokenHash = ccc.hashTypeId( | ||||||||
| register.inputs[0], | ||||||||
| register.outputs.length, | ||||||||
| ); | ||||||||
|
|
||||||||
| let resTx; | ||||||||
| if (this.executor) { | ||||||||
| const res = await this.executor.runScriptTry( | ||||||||
| this.code, | ||||||||
| "SSRIUDT.create", | ||||||||
| [ | ||||||||
| register.toBytes(), | ||||||||
| ccc.Script.from(owner.script).toBytes(), | ||||||||
| UdtMetadata.encode(metadata), | ||||||||
| ], | ||||||||
| ); | ||||||||
| if (res) { | ||||||||
| resTx = res.map((res) => ccc.Transaction.fromBytes(res)); | ||||||||
| } | ||||||||
| } | ||||||||
|
Comment on lines
+93
to
+106
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The const res = await this.executor.runScriptTry(
this.code,
"SSRIUDT.create",
[
register.toBytes(),
ccc.Script.from(owner.script).toBytes(),
UdtMetadata.encode(metadata),
],
);
if (res) {
resTx = res.map((res) => ccc.Transaction.fromBytes(res));
} |
||||||||
|
|
||||||||
| // Fallback logic | ||||||||
| if (!resTx) { | ||||||||
| register.addOutput( | ||||||||
| { | ||||||||
| lock: owner.script, | ||||||||
| type: { | ||||||||
| codeHash: | ||||||||
| "00000000000000000000000000000000000000000000000000545950455f4944", | ||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||||||||
| hashType: "type", | ||||||||
| args: tokenHash, | ||||||||
| }, | ||||||||
| }, | ||||||||
| UdtMetadata.encode(metadata), | ||||||||
| ); | ||||||||
| resTx = ssri.ExecutorResponse.new(register); | ||||||||
| } | ||||||||
|
|
||||||||
| return { | ||||||||
| tx: resTx.map((tx) => this.addCellDeps(tx)), | ||||||||
| tokenHash, | ||||||||
| }; | ||||||||
| } | ||||||||
| } | ||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The example is incorrect. It instantiates
Udtinstead ofUdtRegister, but theregistermethod is part of theUdtRegisterclass. Additionally, theUdtRegisterconstructor requires anexecutorin its configuration, which is missing from the example.