@ckb-ccc/coin 0.0.0-canary-20260713182150

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.
package/CHANGELOG.md ADDED
@@ -0,0 +1,15 @@
1
+ # @ckb-ccc/coin
2
+
3
+ ## 0.0.0-canary-20260713182150
4
+ ### Minor Changes
5
+
6
+
7
+
8
+ - [`fa522ad`](https://github.com/ckb-devrel/ccc/commit/fa522adb9de09d56d62f51414bba2c5fb7125b6b) Thanks [@Hanssen0](https://github.com/Hanssen0)! - feat(coin): new coin package
9
+
10
+
11
+ ### Patch Changes
12
+
13
+ - Updated dependencies [[`eb806a1`](https://github.com/ckb-devrel/ccc/commit/eb806a171356a35200fccb46667da5574b350609), [`584a1eb`](https://github.com/ckb-devrel/ccc/commit/584a1ebeeb083904e5c2851208bc8491914b3d34), [`81ca371`](https://github.com/ckb-devrel/ccc/commit/81ca3713edd3c74968e391e48e9a36978435c45f), [`3dd2aea`](https://github.com/ckb-devrel/ccc/commit/3dd2aea90ce235fdcc1b0b3d1e4282391ea944fe), [`235676f`](https://github.com/ckb-devrel/ccc/commit/235676f5a7edb0ed95a0909bf530767e35952ffa), [`5ebe6b6`](https://github.com/ckb-devrel/ccc/commit/5ebe6b61e2823cbb6fdbf776bdb16ef4ab83b2f6), [`81ca371`](https://github.com/ckb-devrel/ccc/commit/81ca3713edd3c74968e391e48e9a36978435c45f), [`ec643ac`](https://github.com/ckb-devrel/ccc/commit/ec643ac6bbfeacd3e444ccf5970ea070a30fce8f), [`23110d2`](https://github.com/ckb-devrel/ccc/commit/23110d2f0c90ccaf334bd4736c3e374d07913d72), [`2a8f542`](https://github.com/ckb-devrel/ccc/commit/2a8f542ac2aa1f117991d5737a64da90ef3b138a), [`5e1f8d2`](https://github.com/ckb-devrel/ccc/commit/5e1f8d2d3e6ee26002e323ff0bcd1fcf54240f0b)]:
14
+ - @ckb-ccc/core@0.0.0-canary-20260713182150
15
+ - @ckb-ccc/co-build@0.0.0-canary-20260713182150
package/README.md ADDED
@@ -0,0 +1,144 @@
1
+ <p align="center">
2
+ <a href="https://app.ckbccc.com/">
3
+ <img alt="Logo" src="https://raw.githubusercontent.com/ckb-devrel/ccc/master/assets/logoAndText.svg" style="height: 8rem; max-width: 90%; padding: 0.5rem 0;" />
4
+ </a>
5
+ </p>
6
+
7
+ <h1 align="center" style="font-size: 48px;">
8
+ CCC's Support for Coin
9
+ </h1>
10
+
11
+ <p align="center">
12
+ <a href="https://www.npmjs.com/package/@ckb-ccc/coin"><img
13
+ alt="NPM Version" src="https://img.shields.io/npm/v/%40ckb-ccc%2Fcoin"
14
+ /></a>
15
+ <img alt="GitHub commit activity" src="https://img.shields.io/github/commit-activity/m/ckb-devrel/ccc" />
16
+ <img alt="GitHub last commit" src="https://img.shields.io/github/last-commit/ckb-devrel/ccc/master" />
17
+ <img alt="GitHub branch check runs" src="https://img.shields.io/github/check-runs/ckb-devrel/ccc/master" />
18
+ <a href="https://live.ckbccc.com/"><img
19
+ alt="Playground" src="https://img.shields.io/website?url=https%3A%2F%2Flive.ckbccc.com%2F&label=Playground"
20
+ /></a>
21
+ <a href="https://app.ckbccc.com/"><img
22
+ alt="App" src="https://img.shields.io/website?url=https%3A%2F%2Fapp.ckbccc.com%2F&label=App"
23
+ /></a>
24
+ <a href="https://docs.ckbccc.com/"><img
25
+ alt="Docs" src="https://img.shields.io/website?url=https%3A%2F%2Fdocs.ckbccc.com%2F&label=Docs"
26
+ /></a>
27
+ </p>
28
+
29
+ <p align="center">
30
+ CCC - CKBers' Codebase is a one-stop solution for your CKB JS/TS ecosystem development.
31
+ <br />
32
+ Empower yourself with CCC to discover the unlimited potential of CKB.
33
+ <br />
34
+ Interoperate with wallets from different chain ecosystems.
35
+ <br />
36
+ Fully enabling CKB's Turing completeness and cryptographic freedom power.
37
+ </p>
38
+
39
+ ## Quick Start
40
+
41
+ `Coin` from `@ckb-ccc/coin` is a generic helper for on-chain fungible tokens identified by a CKB type script.
42
+
43
+ ### Instantiate
44
+
45
+ ```ts
46
+ import { Coin } from "@ckb-ccc/coin";
47
+ import { ccc } from "@ckb-ccc/core";
48
+
49
+ // Classic instantiation with explicit script and cellDeps
50
+ const coin = new Coin({
51
+ script: {
52
+ codeHash: "0x...",
53
+ hashType: "type",
54
+ args: "0x...",
55
+ },
56
+ client,
57
+ cellDeps: [{ outPoint: codeOutPoint, depType: "code" }],
58
+ });
59
+
60
+ // Instantiation via knownScript (e.g., sUDT)
61
+ const sUdt = new Coin({
62
+ knownScript: ccc.KnownScript.SUdt,
63
+ script: {
64
+ args: ownerLock.hash(),
65
+ },
66
+ signer,
67
+ });
68
+
69
+ // Instantiation of xUDT via CoinXUdt with ownerScriptHash and flags
70
+ import { CoinXUdt, CoinXUdtFlags } from "@ckb-ccc/coin";
71
+
72
+ const xUdt = new CoinXUdt({
73
+ xUdtArgs: {
74
+ ownerScriptHash: ownerLock.hash(),
75
+ flags: CoinXUdtFlags.ownerModeOutputType,
76
+ },
77
+ signer,
78
+ });
79
+ ```
80
+
81
+ ### Query balance
82
+
83
+ ```ts
84
+ // Total balance across all cells of the signer
85
+ const balance = await coin.calculateBalance(signer);
86
+ console.log(`Balance: ${balance}`);
87
+
88
+ // Full info: Balance + CKB capacity + cell count
89
+ const info = await coin.calculateInfo(signer);
90
+ console.log(`Balance: ${info.amount}, Cells: ${info.count}`);
91
+ ```
92
+
93
+ ### Send
94
+
95
+ Build the transaction manually, then use `completeBy` to add Coin inputs and a change output:
96
+
97
+ ```ts
98
+ const coin = new Coin({
99
+ knownScript: ccc.KnownScript.SUdt,
100
+ script: {
101
+ args: ownerLock.hash(),
102
+ },
103
+ signer, // It's necessary to construct the Coin class with a signer to use complete* methods.
104
+ });
105
+
106
+ const { script: to } = await signer.getRecommendedAddressObj();
107
+
108
+ // Build outputs
109
+ const { tx } = await coin.transfer(ccc.Transaction.from({}), [
110
+ { to, amount: 1000n },
111
+ ]);
112
+
113
+ // Add Coin inputs + change (change goes back to signer)
114
+ const { tx: completedTx } = await coin.completeBy(tx);
115
+
116
+ // Cover CKB capacity and fee
117
+ await completedTx.completeInputsByCapacity(signer);
118
+ await completedTx.completeFeeBy(signer);
119
+
120
+ const txHash = await signer.sendTransaction(completedTx);
121
+ ```
122
+
123
+ ### Change to a specific address
124
+
125
+ ```ts
126
+ const { script: changeLock } = await signer.getRecommendedAddressObj();
127
+ const { tx: completedTx } = await coin.completeChangeToLock(tx, changeLock);
128
+ ```
129
+
130
+ ## Extensible UDT (xUDT) Support
131
+
132
+ `CoinXUdt` extends `Coin` to provide specialized support for RFC 52 extensible UDT (xUDT).
133
+
134
+ - **Args Encoding/Decoding**: Provides `CoinXUdtArgs` to correctly build and parse xUDT type script arguments, supporting owner-mode flags.
135
+ - **Default Known Script**: When `knownScript` is omitted, `CoinXUdt` uses `ccc.KnownScript.XUdt`. A complete `script` with `codeHash` and `hashType` takes priority over this shorthand. Pass `script.args` to use existing xUDT args, or pass `xUdtArgs` to build args from `ownerScriptHash` and `flags`.
136
+ - **Underlying Coin Compatibility**: Inherits all query, transfer, and transaction completion methods of the generic `Coin` class.
137
+
138
+ ## Learn More?
139
+
140
+ Check the [package documentation](https://docs.ckbccc.com/docs/packages/protocol-sdks/coin) and [API reference](https://api.ckbccc.com/classes/_ckb-ccc_coin.coin) for more details.
141
+
142
+ <h3 align="center">
143
+ Read more about CCC on <a href="https://docs.ckbccc.com">our website</a> or <a href="https://github.com/ckb-devrel/ccc">GitHub Repo</a>.
144
+ </h3>
@@ -0,0 +1,2 @@
1
+ import{t as e}from"./rolldown-runtime-DK3Fl9T5.mjs";import{ccc as t,mol as n}from"@ckb-ccc/core";import{coBuild as r}from"@ckb-ccc/co-build";function i(e,t,n,r){var i=arguments.length,a=i<3?t:r===null?r=Object.getOwnPropertyDescriptor(t,n):r,o;if(typeof Reflect==`object`&&typeof Reflect.decorate==`function`)a=Reflect.decorate(e,t,n,r);else for(var s=e.length-1;s>=0;s--)(o=e[s])&&(a=(i<3?o(a):i>3?o(t,n,a):o(t,n))||a);return i>3&&a&&Object.defineProperty(t,n,a),a}const a=n.table({amount:n.Uint128,to:t.ScriptOpt});let o=class extends t.Entity.Base(){constructor({amount:e,to:t}){super(),this.amount=e,this.to=t}};o=i([t.codec(a)],o);const s=n.table({amount:n.Uint128});let c=class extends t.Entity.Base(){constructor({amount:e}){super(),this.amount=e}};c=i([t.codec(s)],c);const l=n.table({amount:n.Uint128,to:t.ScriptOpt});let u=class extends t.Entity.Base(){constructor({amount:e,to:t}){super(),this.amount=e,this.to=t}};u=i([t.codec(l)],u);const d=n.union({Mint:o,Burn:c,Transfer:u});let f=class extends t.Entity.BaseUnion(){};f=i([t.codec(d)],f);var p=class e{constructor(e,t,n){this.amount=e,this.capacity=t,this.count=n}static from(n){return n instanceof e?n:new e(t.numFrom(n?.amount??t.Zero),t.numFrom(n?.capacity??t.Zero),n?.count??0)}static default(){return e.from()}clone(){return new e(this.amount,this.capacity,this.count)}addAssign(t){let n=e.from(t);return this.amount+=n.amount,this.capacity+=n.capacity,this.count+=n.count,this}add(e){return this.clone().addAssign(e)}subAssign(t){let n=e.from(t);return this.amount-=n.amount,this.capacity-=n.capacity,this.count-=n.count,this}sub(e){return this.clone().subAssign(e)}},m=class extends Error{constructor(e){let n=t.numFrom(e.amount),r=t.Script.from(e.type);super(`Insufficient coin, ${e.reason??`need ${n} extra coin`}`),this.amount=n,this.type=r}},h=class e{get signer(){if(!this._signer)throw Error(`Coin was constructed without a signer. Pass signer to use this method.`);return this._signer}constructor(e){let{outputTransformer:n,signer:i,knownScript:a,script:o,cellDeps:s}=e;this.outputTransformer=n,this._signer=i??void 0;let c=e.signer==null?e.client:e.client??e.signer.client;if(this.client=c,a==null&&(o.codeHash==null||o.hashType==null))throw Error(`Either knownScript or script.codeHash and script.hashType must be provided for Coin`);let l=(async()=>{if(o.codeHash!=null&&o.hashType!=null)return[o,s??[]];let e=await c.getKnownScript(a);return[{codeHash:e.codeHash,hashType:e.hashType,args:o.args},(await c.getCellDeps(e.cellDeps)).concat(s?.map(t.CellDep.from)??[])]})();this.script=l.then(([e])=>t.Script.from(e)),this.cellDeps=l.then(([e,n])=>n.map(t.CellDep.from));let u=this.script;this.filter=(async()=>t.ClientIndexerSearchKeyFilter.from(e.filter??{script:await u,outputDataLenRange:[16,`0xffffffff`]}))(),this.coBuild=Promise.all([this.script]).then(([t])=>new r.CoBuild(t,e.scriptInfo))}static amountFromUnsafe(e){let n=t.bytesFrom(e).slice(0,16);return n.length<16?t.Zero:t.numLeFromBytes(n)}async infoFrom(n,r){return t.reduceAsync(n,async(n,r)=>{let i=t.CellAny.from(r);if(await this.isCoin(i))return n.addAssign({amount:e.amountFromUnsafe(i.outputData),capacity:i.cellOutput.capacity,count:1})},p.from(r).clone())}async amountFrom(e,t){return(await this.infoFrom(e,{amount:t})).amount}async calculateInfo(e,t){let n=e??this.signer,r=(t?.source??`chain`)===`local`,i=await this.filter,a=r?n.findCells(i):n.findCellsOnChain(i);return this.infoFrom(a)}async calculateBalance(e,t){return(await this.calculateInfo(e,t)).amount}async isCoin(e){let n=t.CellAny.from(e);return(n.cellOutput.type?.eq(await this.script)??!1)&&t.bytesFrom(n.outputData).length>=16}async getInputsInfo(e){let n=t.Transaction.from(e),r=this.client;return this.infoFrom((async function*(){for(let e of n.inputs)yield await e.getCell(r)})())}async getInputsAmount(e){return(await this.getInputsInfo(e)).amount}async getOutputsInfo(e){let n=t.Transaction.from(e);return this.infoFrom(Array.from(n.outputCells))}async getOutputsAmount(e){return(await this.getOutputsInfo(e)).amount}async getInfoBurned(e){let n=t.Transaction.from(e);return(await this.getInputsInfo(n)).sub(await this.getOutputsInfo(n))}async getAmountBurned(e){return(await this.getInfoBurned(e)).amount}async getIntendedAmountBurned(e){let n=t.Transaction.from(e);return(await this.coBuild).findActions(n,await this.script).reduce((e,n)=>{try{let r=f.fromBytes(n.data,{isExtraFieldIgnored:!0});e+=r.match({Mint:e=>-e.amount,Burn:e=>e.amount,_:()=>t.Zero})}catch{}return e},t.Zero)}async completeInputs(e,n,r){let i=t.Transaction.from(e);return i.addCellDeps(await this.cellDeps),{...await i.completeInputs(this.signer,await this.filter,async(e,t)=>n(e,t,await this.infoFrom(t)),r),tx:i}}async completeInputsByAmount(e,n,r){let i=t.Transaction.from(e);i.addCellDeps(await this.cellDeps);let{amount:a,capacity:o}=await this.getInputsInfo(i),{amount:s,capacity:c}=await this.getOutputsInfo(i),l=a-s-t.numFrom(n??0)-await this.getIntendedAmountBurned(i),u=t.numMin(o-c,await i.getFee(this.client))-t.numFrom(r??0);if(l>=t.Zero&&u>=t.Zero)return{addedCount:0,tx:i};let{tx:d,addedCount:f,accumulated:h}=await this.completeInputs(i,(e,n,r)=>{let i=e.add(r);return i.amount>=t.Zero&&i.capacity>=t.Zero?void 0:i},p.from({amount:l,capacity:u}));if(h===void 0||h.amount>=t.Zero)return{tx:d,addedCount:f};throw new m({amount:-h.amount,type:await this.script})}async completeInputsAll(e){let n=t.Transaction.from(e),{tx:r,addedCount:i}=await this.completeInputs(n,(e,t,n)=>e.addAssign(n),p.default());return{tx:r,addedCount:i}}async complete(e,n,r){let i=t.Transaction.from(e);i.addCellDeps(await this.cellDeps);let a=0;if(r?.shouldAddInputs??!0){let e=await this.completeInputsByAmount(i);i=e.tx,a+=e.addedCount}let o=await this.getAmountBurned(i)-await this.getIntendedAmountBurned(i);if(o<t.Zero)throw new m({amount:-o,type:await this.script});if(o===t.Zero)return{tx:i,addedInputs:a,hasChanged:!1,changeIndex:void 0};if(!(r?.shouldAddInputs??!0))return await Promise.resolve(n(i,o)),{tx:i,addedInputs:a,hasChanged:!0,changeIndex:void 0};let s=i.clone(),c=i.getOutputsCapacity();await Promise.resolve(n(s,o));let l=s.getOutputsCapacity()-c,u=await this.completeInputsByAmount(i,t.Zero,l);return i=u.tx,a+=u.addedCount,await Promise.resolve(n(i,await this.getAmountBurned(i)-await this.getIntendedAmountBurned(i))),{tx:i,addedInputs:a,hasChanged:!0,changeIndex:void 0}}async completeChangeToOutput(e,n,r){let i=t.Transaction.from(e),a=Number(t.numFrom(n)),o=i.outputs[a];if(!o)throw Error(`Output at index ${a} does not exist`);let s=t.CellAny.from({cellOutput:o.clone(),outputData:i.outputsData[a]});if(!await this.isCoin(s))throw Error(`Change output must be a Coin`);let c=await this.complete(i,async(e,n)=>{let r=t.numLeToBytes(await this.amountFrom(s,n),16),i=t.CellAny.from({cellOutput:s.cellOutput.clone(),outputData:t.hexFrom(t.bytesConcat(r,t.bytesFrom(s.outputData).slice(16)))});this.outputTransformer&&(i=t.CellAny.from(await this.outputTransformer(i))),e.outputs[a]=i.cellOutput,e.outputsData[a]=i.outputData},r);return{...c,changeIndex:c.hasChanged?a:void 0}}async completeChangeToLock(e,n,r){let i=t.Script.from(n),a,{tx:o,addedInputs:s,hasChanged:c}=await this.complete(e,async(e,n)=>{let r=t.CellAny.from({cellOutput:{lock:i,type:await this.script},outputData:t.numLeToBytes(n,16)});this.outputTransformer&&(r=t.CellAny.from(await this.outputTransformer(r))),a=e.outputs.length,e.addOutput(r.cellOutput,r.outputData)},r);return{tx:o,addedInputs:s,hasChanged:c,changeIndex:a}}async completeBy(e,t){let{script:n}=await this.signer.getRecommendedAddressObj();return this.completeChangeToLock(e,n,t)}async transfer(e,n){let r=t.Transaction.from(e),i=[];for(let{to:e,amount:a}of n){let n=t.CellAny.from({cellOutput:{lock:e,type:await this.script},outputData:t.numLeToBytes(t.numFrom(a),16)});this.outputTransformer&&(n=t.CellAny.from(await this.outputTransformer(n))),i.push(r.addOutput(n.cellOutput,n.outputData)-1)}return{...await(await this.coBuild).appendActions(r,n.map(e=>u.from(e))),outputIndexes:i}}async mint(e,n){let r=t.Transaction.from(e),i=[];for(let{to:e,amount:a}of n){let n=t.CellAny.from({cellOutput:{lock:e,type:await this.script},outputData:t.numLeToBytes(t.numFrom(a),16)});this.outputTransformer&&(n=t.CellAny.from(await this.outputTransformer(n))),i.push(r.addOutput(n.cellOutput,n.outputData)-1)}return{...await(await this.coBuild).appendActions(r,n.map(e=>o.from(e))),outputIndexes:i}}async burn(e,t){return(await this.coBuild).appendActions(e,c.from({amount:t}))}},g;let _=function(e){return e[e.ownerModeInputLockDisabled=536870912]=`ownerModeInputLockDisabled`,e[e.ownerModeOutputType=1073741824]=`ownerModeOutputType`,e[e.ownerModeInputType=2147483648]=`ownerModeInputType`,e}({});const v=t.Codec.from({encode(e){let n=y.from(e),r=t.bytesFrom(n.ownerScriptHash);return n.flags===0?r:t.bytesConcat(r,t.numLeToBytes(n.flags,4))},decode(e){let n=t.bytesFrom(e);if(n.length===32)return{ownerScriptHash:t.hexFrom(n),flags:0};if(n.length>=36)return{ownerScriptHash:t.hexFrom(n.slice(0,32)),flags:Number(t.numLeFromBytes(n.slice(32,36)))};throw Error(`Invalid xUDT args length: expected 32 or at least 36 bytes, got ${n.length}`)},from(e){return y.from(e)}});let y=g=class extends t.Entity.Base(){constructor({ownerScriptHash:e,flags:t}){super(),this.ownerScriptHash=e,this.flags=t}static from(e){let n=t.bytesFrom(e.ownerScriptHash);if(n.length!==32)throw Error(`Invalid owner script hash length: expected 32 bytes, got ${n.length}`);return new g({ownerScriptHash:t.hexFrom(n),flags:e.flags??0})}};y=g=i([t.codec(v)],y);var b=class extends h{constructor(e){let n;if(e.xUdtArgs!=null)n=y.from(e.xUdtArgs);else if(e.script?.args!=null)n=y.fromBytes(e.script.args);else throw Error(`Either xUdtArgs or script.args must be provided for CoinXUdt`);super({...e,script:{...e.script??{},args:n.toBytes()},knownScript:e.knownScript??t.KnownScript.XUdt}),this.args=n}},x=e({BurnAction:()=>c,Coin:()=>h,CoinAction:()=>f,CoinInfo:()=>p,CoinXUdt:()=>b,CoinXUdtArgs:()=>y,CoinXUdtFlags:()=>_,ErrorCoinInsufficient:()=>m,MintAction:()=>o,TransferAction:()=>u});export{h as a,c,u as d,_ as i,f as l,b as n,m as o,y as r,p as s,x as t,o as u};
2
+ //# sourceMappingURL=barrel-CYxAJVpH.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"barrel-CYxAJVpH.mjs","names":[],"sources":["../src/coBuild.ts","../src/coin/coinInfo.ts","../src/coin/error.ts","../src/coin/coin.ts","../src/xUdt/args.ts","../src/xUdt/coinXUdt.ts","../src/barrel.ts"],"sourcesContent":["import { ccc, mol } from \"@ckb-ccc/core\";\n\nconst MintActionCodec = mol.table({\n amount: mol.Uint128,\n to: ccc.ScriptOpt,\n});\n\nexport type MintActionLike = ccc.EncodableType<typeof MintActionCodec>;\n\n@ccc.codec(MintActionCodec)\nexport class MintAction extends ccc.Entity.Base<MintActionLike, MintAction>() {\n public amount: ccc.Num;\n public to?: ccc.Script;\n\n constructor({ amount, to }: ccc.DecodedType<typeof MintActionCodec>) {\n super();\n\n this.amount = amount;\n this.to = to;\n }\n}\n\nconst BurnActionCodec = mol.table({\n amount: mol.Uint128,\n});\n\nexport type BurnActionLike = ccc.EncodableType<typeof BurnActionCodec>;\n\n@ccc.codec(BurnActionCodec)\nexport class BurnAction extends ccc.Entity.Base<BurnActionLike, BurnAction>() {\n public amount: ccc.Num;\n\n constructor({ amount }: ccc.DecodedType<typeof BurnActionCodec>) {\n super();\n\n this.amount = amount;\n }\n}\n\nconst TransferActionCodec = mol.table({\n amount: mol.Uint128,\n to: ccc.ScriptOpt,\n});\n\nexport type TransferActionLike = ccc.EncodableType<typeof TransferActionCodec>;\n\n@ccc.codec(TransferActionCodec)\nexport class TransferAction extends ccc.Entity.Base<\n TransferActionLike,\n TransferAction\n>() {\n public amount: ccc.Num;\n public to?: ccc.Script;\n\n constructor({ amount, to }: ccc.DecodedType<typeof TransferActionCodec>) {\n super();\n\n this.amount = amount;\n this.to = to;\n }\n}\n\nconst CoinActionCodec = mol.union({\n Mint: MintAction,\n Burn: BurnAction,\n Transfer: TransferAction,\n});\n\nexport type CoinActionLike = ccc.EncodableType<typeof CoinActionCodec>;\n\n@ccc.codec(CoinActionCodec)\nexport class CoinAction extends ccc.Entity.BaseUnion<\n typeof CoinActionCodec,\n CoinActionLike,\n CoinAction\n>() {}\n","import { ccc } from \"@ckb-ccc/core\";\n\n/**\n * Represents a Coin information-like object.\n * This is used as a flexible input for creating `CoinInfo` instances.\n *\n * @public\n * @category Coin\n */\nexport type CoinInfoLike =\n | {\n /** The Coin amount. */\n amount?: ccc.NumLike | null;\n /** The total CKB capacity of the Coins. */\n capacity?: ccc.NumLike | null;\n /** The number of Coins. */\n count?: number | null;\n }\n | undefined\n | null;\n\n/**\n * Represents aggregated information about a set of Coins.\n * This class encapsulates the total amount, total CKB capacity, and the number of cells.\n *\n * @public\n * @category Coin\n */\nexport class CoinInfo {\n /**\n * Creates an instance of CoinInfo.\n *\n * @param amount - The total Coin amount.\n * @param capacity - The total CKB capacity of the Coins.\n * @param count - The number of Coins.\n */\n constructor(\n public amount: ccc.Num,\n public capacity: ccc.Num,\n public count: number,\n ) {}\n\n /**\n * Creates a `CoinInfo` instance from a `CoinInfoLike` object.\n *\n * @param infoLike - A `CoinInfoLike` object or an instance of `CoinInfo`.\n * @returns A new `CoinInfo` instance.\n */\n static from(infoLike?: CoinInfoLike) {\n if (infoLike instanceof CoinInfo) {\n return infoLike;\n }\n\n return new CoinInfo(\n ccc.numFrom(infoLike?.amount ?? ccc.Zero),\n ccc.numFrom(infoLike?.capacity ?? ccc.Zero),\n infoLike?.count ?? 0,\n );\n }\n\n /**\n * Creates a default `CoinInfo` instance with all values set to zero.\n * @returns A new `CoinInfo` instance with zero amount, capacity, and count.\n */\n static default() {\n return CoinInfo.from();\n }\n\n /**\n * Clones the `CoinInfo` instance.\n * @returns A new `CoinInfo` instance that is a copy of the current one.\n */\n clone() {\n return new CoinInfo(this.amount, this.capacity, this.count);\n }\n\n /**\n * Adds the values from another `CoinInfoLike` object to this instance (in-place).\n *\n * @param infoLike - The `CoinInfoLike` object to add.\n * @returns The current, modified `CoinInfo` instance.\n */\n addAssign(infoLike: CoinInfoLike) {\n const info = CoinInfo.from(infoLike);\n\n this.amount += info.amount;\n this.capacity += info.capacity;\n this.count += info.count;\n\n return this;\n }\n\n /**\n * Creates a new `CoinInfo` instance by adding the values from another `CoinInfoLike` object to the current one.\n * This method is not in-place.\n *\n * @param infoLike - The `CoinInfoLike` object to add.\n * @returns A new `CoinInfo` instance with the summed values.\n */\n add(infoLike: CoinInfoLike) {\n return this.clone().addAssign(infoLike);\n }\n\n /**\n * Subtracts the values from another `CoinInfoLike` object from this instance (in-place).\n *\n * @param infoLike - The `CoinInfoLike` object to subtract.\n * @returns The current, modified `CoinInfo` instance.\n */\n subAssign(infoLike: CoinInfoLike) {\n const info = CoinInfo.from(infoLike);\n\n this.amount -= info.amount;\n this.capacity -= info.capacity;\n this.count -= info.count;\n\n return this;\n }\n\n /**\n * Creates a new `CoinInfo` instance by subtracting the values of another `CoinInfoLike` object from the current one.\n * This method is not in-place.\n *\n * @param infoLike - The `CoinInfoLike` object to subtract.\n * @returns A new `CoinInfo` instance with the subtracted values.\n */\n sub(infoLike: CoinInfoLike) {\n return this.clone().subAssign(infoLike);\n }\n}\n","import { ccc } from \"@ckb-ccc/core\";\n\n/**\n * Error thrown when there are insufficient Coin to complete a transaction.\n * This error provides detailed information about the shortfall, including the\n * exact amount needed, the Coin type script, and an optional custom reason.\n *\n * @public\n * @category Error\n * @category Coin\n *\n * @example\n * ```typescript\n * // This error is typically thrown automatically by Coin methods\n * try {\n * await coin.completeInputsByAmount(tx);\n * } catch (error) {\n * if (error instanceof ErrorCoinInsufficient) {\n * console.log(`Error: ${error.message}`);\n * console.log(`Shortfall: ${error.amount} Coin tokens`);\n * console.log(`Coin type script: ${error.type.toHex()}`);\n * }\n * }\n * ```\n */\nexport class ErrorCoinInsufficient extends Error {\n /**\n * The amount of Coin that is insufficient (shortfall amount).\n * This represents how many more Coin tokens are needed to complete the operation.\n */\n public readonly amount: ccc.Num;\n\n /**\n * The type script of the Coin that has insufficient amount.\n * This identifies which specific Coin token is lacking sufficient funds.\n */\n public readonly type: ccc.Script;\n\n /**\n * Creates a new ErrorCoinInsufficient instance.\n *\n * @param info - Configuration object for the error\n * @param info.amount - The amount of Coin that is insufficient (shortfall amount)\n * @param info.type - The type script of the Coin that has insufficient amount\n * @param info.reason - Optional custom reason message. If not provided, a default message will be generated\n *\n * @example\n * ```typescript\n * // Manual creation (typically not needed as the error is thrown automatically)\n * const error = new ErrorCoinInsufficient({\n * amount: ccc.numFrom(1000),\n * type: coinScript,\n * reason: \"Custom insufficient amount message\"\n * });\n *\n * // More commonly, catch the error when it's thrown by Coin methods\n * try {\n * const result = await coin.completeInputsByAmount(tx);\n * } catch (error) {\n * if (error instanceof ErrorCoinInsufficient) {\n * // Handle the insufficient amount error\n * console.error(`Insufficient Coin: need ${error.amount} more tokens`);\n * }\n * }\n * ```\n *\n * @remarks\n * The error message format depends on whether a custom reason is provided:\n * - With custom reason: \"Insufficient coin, {custom reason}\"\n * - Without custom reason: \"Insufficient coin, need {amount} extra coin\"\n */\n constructor(info: {\n amount: ccc.NumLike;\n type: ccc.ScriptLike;\n reason?: string;\n }) {\n const amount = ccc.numFrom(info.amount);\n const type = ccc.Script.from(info.type);\n super(`Insufficient coin, ${info.reason ?? `need ${amount} extra coin`}`);\n this.amount = amount;\n this.type = type;\n }\n}\n","import { coBuild } from \"@ckb-ccc/co-build\";\nimport { ccc } from \"@ckb-ccc/core\";\nimport {\n BurnAction,\n CoinAction,\n MintAction,\n TransferAction,\n} from \"../coBuild.js\";\nimport { CoinInfo, CoinInfoLike } from \"./coinInfo.js\";\nimport { ErrorCoinInsufficient } from \"./error.js\";\n\n/**\n * Return type for all `complete*` methods on {@link Coin}.\n *\n * @public\n */\nexport type CoinCompleteResponse = {\n /** The completed transaction. */\n tx: ccc.Transaction;\n /** Number of Coin inputs added to the transaction. */\n addedInputs: number;\n /** Whether a change output was written. `false` when inputs and outputs were already balanced. */\n hasChanged: boolean;\n /**\n * Index of the change output in `tx.outputs`.\n * `undefined` when `hasChanged` is `false`.\n */\n changeIndex: number | undefined;\n};\n\n/**\n * Client configurations for {@link Coin}.\n * @public\n */\nexport type CoinOptionsClient =\n | {\n client: ccc.Client;\n signer?: null;\n }\n | {\n client?: ccc.Client | null;\n signer: ccc.Signer;\n };\n\n/**\n * Script configurations for {@link Coin}.\n * @public\n */\nexport type CoinOptionsScript = {\n knownScript?: ccc.KnownScript | null;\n script: {\n codeHash?: ccc.HexLike | null;\n hashType?: ccc.HashTypeLike | null;\n args: ccc.BytesLike;\n };\n cellDeps?: ccc.CellDepLike[] | null;\n};\n\n/**\n * Behavior configurations for {@link Coin}.\n * @public\n */\nexport type CoinOptionsBehavior = {\n filter?: ccc.ClientIndexerSearchKeyFilterLike | null;\n outputTransformer?:\n ((cell: ccc.CellAny) => ccc.CellAnyLike | Promise<ccc.CellAnyLike>) | null;\n scriptInfo?: coBuild.ScriptInfoLike | null;\n};\n\n/**\n * Options for creating a {@link Coin} instance.\n * @public\n */\nexport type CoinOptions = CoinOptionsBehavior &\n CoinOptionsScript &\n CoinOptionsClient;\n\n/**\n * A generic on-chain Coin (fungible token) identified by a CKB type script.\n *\n * Provides helpers for querying balances and building/completing transactions.\n * Asset identity is defined by the complete type script `(codeHash, hashType, args)` —\n * only cells with an identical type script belong to the same Coin.\n *\n * @public\n * @category Blockchain\n * @category Token\n */\nexport class Coin {\n /** Type script that identifies this Coin. @public */\n public readonly script: Promise<ccc.Script>;\n\n private readonly _signer: ccc.Signer | undefined;\n\n /** Output transformer for Coin outputs. @public */\n public readonly outputTransformer?:\n ((cell: ccc.CellAny) => ccc.CellAnyLike | Promise<ccc.CellAnyLike>) | null;\n\n /** CoBuild instance for this Coin. @public */\n public readonly coBuild: Promise<coBuild.CoBuild>;\n\n /**\n * Signer used for all input sourcing and transaction completion.\n * @throws if the `Coin` was constructed without a `signer`.\n * @public\n */\n get signer(): ccc.Signer {\n if (!this._signer) {\n throw new Error(\n \"Coin was constructed without a signer. Pass signer to use this method.\",\n );\n }\n return this._signer;\n }\n\n /** Client for network requests. @public */\n public readonly client: ccc.Client;\n\n /**\n * Indexer search filter used to find Coin cells.\n * Defaults to cells with this type script and `outputDataLenRange: [16, ∞)`.\n *\n * @public\n */\n public readonly filter: Promise<ccc.ClientIndexerSearchKeyFilter>;\n\n /** Cell deps required by the type script, added to every built transaction. @public */\n public readonly cellDeps: Promise<ccc.CellDep[]>;\n\n /**\n * @param options.knownScript - Optional known script standard (e.g., `ccc.KnownScript.SUdt`) to dynamically resolve `codeHash`, `hashType`, and `cellDeps`.\n * Used only when `script.codeHash` or `script.hashType` is not provided.\n * @param options.script - Type script that identifies this Coin asset. A complete script with `codeHash` and `hashType`\n * takes priority over `knownScript`; otherwise `knownScript` is used as shorthand and only `args` is required.\n * @param options.signer - Signer used for input sourcing and transaction completion.\n * Required for `complete*` methods.\n * @param options.client - Client for network requests. Takes priority over the signer's client if both are provided.\n * At least one of `signer` or `client` must be supplied.\n * @param options.filter - Custom indexer filter. Defaults to cells with this type script\n * and `outputDataLenRange: [16, ∞)`.\n * @param options.cellDeps - Cell deps automatically added to every built transaction. If the known script shorthand is used, these custom cell deps are appended after the resolved default cell deps of the known script.\n * @param options.outputTransformer - Optional callback to further modify generated Coin cells after the\n * amount has been written into `outputData[0..16)`. Any capacity below the data minimum is raised automatically;\n * capacity above the minimum is preserved as-is.\n *\n * @example\n * ```typescript\n * const coin = new Coin({\n * script: { codeHash: \"0x...\", hashType: \"type\", args: \"0x...\" },\n * signer,\n * cellDeps: [{ outPoint: codeOutPoint, depType: \"code\" }],\n * });\n * ```\n *\n * @example\n * ```typescript\n * const coin = new Coin({\n * knownScript: ccc.KnownScript.SUdt,\n * script: { args: ownerLock.hash() },\n * signer,\n * outputTransformer: async (cell) => ({\n * ...cell,\n * outputData: ccc.hexFrom(ccc.bytesConcat(ccc.bytesFrom(cell.outputData), extraData)),\n * }),\n * });\n * ```\n */\n constructor(options: CoinOptions) {\n const { outputTransformer, signer, knownScript, script, cellDeps } =\n options;\n\n this.outputTransformer = outputTransformer;\n this._signer = signer ?? undefined;\n const client =\n options.signer == undefined\n ? options.client\n : (options.client ?? options.signer.client);\n this.client = client;\n\n if (\n knownScript == null &&\n (script.codeHash == null || script.hashType == null)\n ) {\n throw new Error(\n \"Either knownScript or script.codeHash and script.hashType must be provided for Coin\",\n );\n }\n const resolved = (async (): Promise<\n [ccc.ScriptLike, ccc.CellDepLike[]]\n > => {\n if (script.codeHash != null && script.hashType != null) {\n return [script as ccc.ScriptLike, cellDeps ?? []];\n }\n\n const scriptInfo = await client.getKnownScript(\n knownScript as ccc.KnownScript,\n );\n return [\n {\n codeHash: scriptInfo.codeHash,\n hashType: scriptInfo.hashType,\n args: script.args,\n },\n (await client.getCellDeps(scriptInfo.cellDeps)).concat(\n cellDeps?.map(ccc.CellDep.from) ?? [],\n ),\n ];\n })();\n\n this.script = resolved.then(([script]) => ccc.Script.from(script));\n this.cellDeps = resolved.then(([_, cellDeps]) =>\n cellDeps.map(ccc.CellDep.from),\n );\n\n const scriptRes = this.script;\n this.filter = (async () => {\n return ccc.ClientIndexerSearchKeyFilter.from(\n options.filter ?? {\n script: await scriptRes,\n outputDataLenRange: [16, \"0xffffffff\"],\n },\n );\n })();\n\n this.coBuild = Promise.all([this.script]).then(\n ([script]) => new coBuild.CoBuild(script, options.scriptInfo),\n );\n }\n\n /**\n * Reads the Coin amount from raw output data without verifying the type script.\n * Returns `0` if the data is shorter than 16 bytes.\n *\n * ⚠️ The caller must ensure the data belongs to a valid Coin cell.\n * For safe extraction from an arbitrary cell use `amountFrom`.\n */\n static amountFromUnsafe(outputData: ccc.HexLike): ccc.Num {\n const data = ccc.bytesFrom(outputData).slice(0, 16);\n return data.length < 16 ? ccc.Zero : ccc.numLeFromBytes(data);\n }\n\n /**\n * Aggregates Coin info (amount, capacity, count) from cells, skipping non-Coins.\n * Accepts a single cell, a sync iterable, or an async iterable.\n */\n async infoFrom(\n cells:\n | ccc.CellAnyLike\n | Iterable<ccc.CellAnyLike>\n | AsyncIterable<ccc.CellAnyLike>,\n acc?: CoinInfoLike | null,\n ): Promise<CoinInfo> {\n return ccc.reduceAsync(\n cells,\n async (acc, cellLike) => {\n const cell = ccc.CellAny.from(cellLike);\n if (!(await this.isCoin(cell))) {\n return;\n }\n\n return acc.addAssign({\n amount: Coin.amountFromUnsafe(cell.outputData),\n capacity: cell.cellOutput.capacity,\n count: 1,\n });\n },\n CoinInfo.from(acc).clone(),\n );\n }\n\n /** Convenience wrapper around `infoFrom` that returns only the amount. */\n async amountFrom(\n cells:\n | ccc.CellAnyLike\n | Iterable<ccc.CellAnyLike>\n | AsyncIterable<ccc.CellAnyLike>,\n acc?: ccc.NumLike | null,\n ): Promise<ccc.Num> {\n return (await this.infoFrom(cells, { amount: acc })).amount;\n }\n\n /**\n * Scans all Coins owned by the signer and returns aggregated info.\n *\n * @param options.source - `\"chain\"` (default) queries on-chain state; `\"local\"` uses the\n * local indexer cache which is faster but may be stale.\n *\n * ⚠️ Expensive — scales linearly with the number of Coin cells.\n */\n async calculateInfo(\n signer?: ccc.Signer | null,\n options?: { source?: \"chain\" | \"local\" | null },\n ): Promise<CoinInfo> {\n const s = signer ?? this.signer;\n const isFromLocal = (options?.source ?? \"chain\") === \"local\";\n const filter = await this.filter;\n const cells = isFromLocal\n ? s.findCells(filter)\n : s.findCellsOnChain(filter);\n\n return this.infoFrom(cells);\n }\n\n /**\n * Convenience wrapper around `calculateInfo` that returns only the balance.\n *\n * ⚠️ Expensive — scans all Coin cells owned by the signer.\n */\n async calculateBalance(\n signer?: ccc.Signer | null,\n options?: { source?: \"chain\" | \"local\" | null },\n ): Promise<ccc.Num> {\n return (await this.calculateInfo(signer, options)).amount;\n }\n\n /**\n * Returns whether the cell is a valid Coin for this token.\n * Subclasses may override this to apply additional validation rules.\n */\n async isCoin(cellLike: ccc.CellAnyLike): Promise<boolean> {\n const cell = ccc.CellAny.from(cellLike);\n return (\n (cell.cellOutput.type?.eq(await this.script) ?? false) &&\n ccc.bytesFrom(cell.outputData).length >= 16\n );\n }\n\n /** Returns aggregated Coin info (amount, capacity, count) for all Coin inputs in the transaction. */\n async getInputsInfo(txLike: ccc.TransactionLike): Promise<CoinInfo> {\n const tx = ccc.Transaction.from(txLike);\n const client = this.client;\n return this.infoFrom(\n (async function* () {\n for (const input of tx.inputs) {\n yield await input.getCell(client);\n }\n })(),\n );\n }\n\n /** Convenience wrapper around `getInputsInfo` that returns only the amount. */\n async getInputsAmount(txLike: ccc.TransactionLike): Promise<ccc.Num> {\n return (await this.getInputsInfo(txLike)).amount;\n }\n\n /** Returns aggregated Coin info (amount, capacity, count) for all Coin outputs in the transaction. */\n async getOutputsInfo(txLike: ccc.TransactionLike): Promise<CoinInfo> {\n const tx = ccc.Transaction.from(txLike);\n return this.infoFrom(Array.from(tx.outputCells));\n }\n\n /** Convenience wrapper around `getOutputsInfo` that returns only the amount. */\n async getOutputsAmount(txLike: ccc.TransactionLike): Promise<ccc.Num> {\n return (await this.getOutputsInfo(txLike)).amount;\n }\n\n /**\n * Returns inputs minus outputs as a `CoinInfo`. Positive amount means tokens are burned;\n * positive capacity means Coins provide surplus CKB.\n */\n async getInfoBurned(txLike: ccc.TransactionLike): Promise<CoinInfo> {\n const tx = ccc.Transaction.from(txLike);\n return (await this.getInputsInfo(tx)).sub(await this.getOutputsInfo(tx));\n }\n\n /** Convenience wrapper around `getInfoBurned` that returns only the amount (inputs − outputs). */\n async getAmountBurned(txLike: ccc.TransactionLike): Promise<ccc.Num> {\n return (await this.getInfoBurned(txLike)).amount;\n }\n\n async getIntendedAmountBurned(txLike: ccc.TransactionLike): Promise<ccc.Num> {\n const tx = ccc.Transaction.from(txLike);\n\n return (await this.coBuild)\n .findActions(tx, await this.script)\n .reduce((acc, action) => {\n try {\n const coinAction = CoinAction.fromBytes(action.data, {\n isExtraFieldIgnored: true,\n });\n acc += coinAction.match({\n Mint: (mint) => -mint.amount,\n Burn: (burn) => burn.amount,\n _: () => ccc.Zero,\n });\n } catch (_) {}\n return acc;\n }, ccc.Zero);\n }\n\n /**\n * Low-level input selector driven by a custom accumulator.\n * For each candidate Coin cell the `accumulator` receives `(state, cell, coinInfo)` and\n * returns the next state to keep going, or `undefined` to stop.\n *\n * @returns `accumulated` is `undefined` if the target was reached before all cells were visited.\n *\n * @example\n * ```typescript\n * // Collect inputs until amount reaches a target\n * const { tx } = await coin.completeInputs(\n * tx,\n * (acc, _cell, coinInfo) => {\n * const next = acc + coinInfo.amount;\n * return next >= target ? undefined : next;\n * },\n * ccc.Zero,\n * );\n * ```\n */\n async completeInputs<T>(\n txLike: ccc.TransactionLike,\n accumulator: (\n acc: T,\n cell: ccc.Cell,\n coinInfo: CoinInfo,\n ) => Promise<T | undefined> | T | undefined,\n init: T,\n ): Promise<{\n tx: ccc.Transaction;\n addedCount: number;\n accumulated?: T;\n }> {\n const tx = ccc.Transaction.from(txLike);\n tx.addCellDeps(await this.cellDeps);\n\n const res = await tx.completeInputs(\n this.signer,\n await this.filter,\n async (acc, cell) => accumulator(acc, cell, await this.infoFrom(cell)),\n init,\n );\n\n return {\n ...res,\n tx,\n };\n }\n\n /**\n * Adds Coin inputs until the Coin amount gap is covered, also attempting to cover the\n * CKB capacity gap on a best-effort basis (capacity may still be negative if Coin inputs\n * are exhausted before it is satisfied).\n *\n * @param amountTweak - Extra Coin amount to require beyond what outputs consume.\n * @param capacityTweak - Extra CKB capacity to require beyond what outputs consume.\n *\n * @throws {ErrorCoinInsufficient} if the signer has insufficient Coin amount.\n *\n * @example\n * ```typescript\n * const { tx: completedTx } = await coin.completeInputsByAmount(tx);\n * ```\n */\n async completeInputsByAmount(\n txLike: ccc.TransactionLike,\n amountTweak?: ccc.NumLike | null,\n capacityTweak?: ccc.NumLike | null,\n ): Promise<{\n addedCount: number;\n tx: ccc.Transaction;\n }> {\n const tx = ccc.Transaction.from(txLike);\n tx.addCellDeps(await this.cellDeps);\n\n const { amount: inAmount, capacity: inCapacity } =\n await this.getInputsInfo(tx);\n const { amount: outAmount, capacity: outCapacity } =\n await this.getOutputsInfo(tx);\n\n const amountExcess =\n inAmount -\n outAmount -\n ccc.numFrom(amountTweak ?? 0) -\n (await this.getIntendedAmountBurned(tx));\n // Try to let Coin inputs absorb the tx fee so no extra CKB capacity cell is needed.\n // Cap at the current fee: we never ask Coins to cover more than what the tx owes.\n const capacityExcess =\n ccc.numMin(inCapacity - outCapacity, await tx.getFee(this.client)) -\n ccc.numFrom(capacityTweak ?? 0);\n\n if (amountExcess >= ccc.Zero && capacityExcess >= ccc.Zero) {\n return { addedCount: 0, tx };\n }\n\n const {\n tx: txRes,\n addedCount,\n accumulated,\n } = await this.completeInputs(\n tx,\n (acc, _cell, coinInfo) => {\n const info = acc.add(coinInfo);\n\n // Try to provide enough capacity with Coins to avoid extra occupation\n return info.amount >= ccc.Zero && info.capacity >= ccc.Zero\n ? undefined\n : info;\n },\n CoinInfo.from({ amount: amountExcess, capacity: capacityExcess }),\n );\n\n if (accumulated === undefined || accumulated.amount >= ccc.Zero) {\n return { tx: txRes, addedCount };\n }\n\n throw new ErrorCoinInsufficient({\n amount: -accumulated.amount,\n type: await this.script,\n });\n }\n\n /**\n * Adds ALL available Coins from the signer as inputs. Useful for consolidation or full sweeps.\n */\n async completeInputsAll(txLike: ccc.TransactionLike): Promise<{\n addedCount: number;\n tx: ccc.Transaction;\n }> {\n const tx = ccc.Transaction.from(txLike);\n\n const { tx: txRes, addedCount } = await this.completeInputs(\n tx,\n (acc, _cell, coinInfo) => acc.addAssign(coinInfo),\n CoinInfo.default(),\n );\n\n return { tx: txRes, addedCount };\n }\n\n /**\n * Low-level completion primitive. Adds Coin inputs, then calls `change(tx, amount)` to\n * write the change output.\n *\n * `complete` never manages CKB capacity on its own — it only opportunistically uses any\n * capacity gap between inputs and outputs to merge Coin cells (reducing the number of\n * Coin inputs added), on a best-effort basis. It does not guarantee `tx` has enough\n * capacity afterwards; follow up with `tx.completeBy` (or similar) to complete capacity.\n *\n * @param change - Callback that receives the transaction and the excess Coin amount, and\n * should write the change output in place. Must be side-effect-free beyond modifying `tx`,\n * as it may be invoked more than once (e.g. speculatively on a clone) before being applied\n * to the final transaction.\n * @param options.shouldAddInputs - When `false`, skips input sourcing entirely; the caller\n * is responsible for ensuring `tx` already has enough Coin inputs. Defaults to `true`.\n *\n * @example\n * ```typescript\n * const { tx: completedTx } = await coin.complete(tx, async (tx, amount) => {\n * tx.addOutput({ lock: changeLock, type: await coin.script }, ccc.numLeToBytes(amount, 16));\n * });\n * ```\n */\n async complete(\n txLike: ccc.TransactionLike,\n change: (tx: ccc.Transaction, amount: ccc.Num) => Promise<void> | void,\n options?: { shouldAddInputs?: boolean | null },\n ): Promise<CoinCompleteResponse> {\n let tx = ccc.Transaction.from(txLike);\n tx.addCellDeps(await this.cellDeps);\n let addedInputs = 0;\n\n /* === Figure out the amount to change === */\n if (options?.shouldAddInputs ?? true) {\n const res = await this.completeInputsByAmount(tx);\n tx = res.tx;\n addedInputs += res.addedCount;\n }\n\n const amountExcess =\n (await this.getAmountBurned(tx)) -\n (await this.getIntendedAmountBurned(tx));\n\n if (amountExcess < ccc.Zero) {\n throw new ErrorCoinInsufficient({\n amount: -amountExcess,\n type: await this.script,\n });\n } else if (amountExcess === ccc.Zero) {\n // No change needed — inputs and outputs are perfectly balanced\n return { tx, addedInputs, hasChanged: false, changeIndex: undefined };\n }\n /* === Some amount need to change === */\n\n if (!(options?.shouldAddInputs ?? true)) {\n // Caller manages inputs manually; apply change with current amount as-is\n await Promise.resolve(change(tx, amountExcess));\n return { tx, addedInputs, hasChanged: true, changeIndex: undefined };\n }\n\n // Clone the transaction and apply change to measure the extra output capacity\n // the change cell requires, then source inputs, and finally apply change to\n // the real transaction with the correct final amount.\n const cloned = tx.clone();\n const capacityBefore = tx.getOutputsCapacity();\n await Promise.resolve(change(cloned, amountExcess));\n const extraCapacity = cloned.getOutputsCapacity() - capacityBefore;\n\n const res2 = await this.completeInputsByAmount(tx, ccc.Zero, extraCapacity);\n tx = res2.tx;\n addedInputs += res2.addedCount;\n\n await Promise.resolve(\n change(\n tx,\n (await this.getAmountBurned(tx)) -\n (await this.getIntendedAmountBurned(tx)),\n ),\n );\n\n return { tx, addedInputs, hasChanged: true, changeIndex: undefined };\n }\n\n /**\n * Completes the transaction by writing the excess Coin amount into the existing output at\n * `index`. The output must already be a valid Coin cell with this type script.\n *\n * @throws {Error} If the output at `index` does not exist or is not a valid Coin.\n *\n * @example\n * ```typescript\n * // Change goes into output 1 of the transaction\n * const { tx: completedTx } = await coin.completeChangeToOutput(tx, 1);\n * ```\n */\n async completeChangeToOutput(\n txLike: ccc.TransactionLike,\n indexLike: ccc.NumLike,\n options?: {\n shouldAddInputs?: boolean | null;\n },\n ) {\n const tx = ccc.Transaction.from(txLike);\n const index = Number(ccc.numFrom(indexLike));\n\n const cellOutput = tx.outputs[index];\n if (!cellOutput) {\n throw new Error(`Output at index ${index} does not exist`);\n }\n\n const output = ccc.CellAny.from({\n cellOutput: cellOutput.clone(),\n outputData: tx.outputsData[index],\n });\n\n if (!(await this.isCoin(output))) {\n throw new Error(\"Change output must be a Coin\");\n }\n\n const result = await this.complete(\n tx,\n async (tx, amount) => {\n const amountData = ccc.numLeToBytes(\n await this.amountFrom(output, amount),\n 16,\n );\n\n let cell = ccc.CellAny.from({\n cellOutput: output.cellOutput.clone(),\n outputData: ccc.hexFrom(\n ccc.bytesConcat(\n amountData,\n ccc.bytesFrom(output.outputData).slice(16),\n ),\n ),\n });\n\n if (this.outputTransformer) {\n cell = ccc.CellAny.from(await this.outputTransformer(cell));\n }\n\n tx.outputs[index] = cell.cellOutput;\n tx.outputsData[index] = cell.outputData;\n },\n options,\n );\n\n return { ...result, changeIndex: result.hasChanged ? index : undefined };\n }\n\n /**\n * Completes the transaction by creating a new change output locked to `changeLike`.\n *\n * @example\n * ```typescript\n * const { script: changeLock } = await coin.signer.getRecommendedAddressObj();\n * const { tx: completedTx, changeIndex } = await coin.completeChangeToLock(tx, changeLock);\n * ```\n */\n async completeChangeToLock(\n txLike: ccc.TransactionLike,\n changeLike: ccc.ScriptLike,\n options?: {\n shouldAddInputs?: boolean | null;\n },\n ): Promise<CoinCompleteResponse> {\n const change = ccc.Script.from(changeLike);\n let changeIndex: number | undefined;\n\n const { tx, addedInputs, hasChanged } = await this.complete(\n txLike,\n async (tx, amount) => {\n let cell = ccc.CellAny.from({\n cellOutput: { lock: change, type: await this.script },\n outputData: ccc.numLeToBytes(amount, 16),\n });\n\n if (this.outputTransformer) {\n cell = ccc.CellAny.from(await this.outputTransformer(cell));\n }\n\n changeIndex = tx.outputs.length;\n tx.addOutput(cell.cellOutput, cell.outputData);\n },\n options,\n );\n\n return { tx, addedInputs, hasChanged, changeIndex };\n }\n\n /**\n * Convenience wrapper around `completeChangeToLock` using the signer's recommended address.\n *\n * @example\n * ```typescript\n * const { tx: completedTx } = await coin.completeBy(tx);\n * await completedTx.completeFeeBy(coin.signer);\n * await coin.signer.sendTransaction(completedTx);\n * ```\n *\n * @see {@link completeChangeToLock} for more control over the change destination.\n */\n async completeBy(\n tx: ccc.TransactionLike,\n options?: {\n shouldAddInputs?: boolean | null;\n },\n ) {\n const { script } = await this.signer.getRecommendedAddressObj();\n\n return this.completeChangeToLock(tx, script, options);\n }\n\n /**\n * Make the transaction perform transfer actions to the specified recipients.\n *\n * @returns An object containing:\n * - `tx`: The updated transaction with added transfer outputs and CoBuild actions.\n * - `outputIndexes`: The indexes of the newly added Coin outputs in `tx.outputs`.\n * - `witnessIndex`: The index of the witness where CoBuild actions were appended.\n *\n * @example\n * ```typescript\n * const { tx } = await coin.transfer(ccc.Transaction.from({}), [\n * { to: recipientLock, amount: 100n },\n * ]);\n * const { tx: completedTx } = await coin.completeBy(tx);\n * await completedTx.completeFeeBy(coin.signer);\n * await coin.signer.sendTransaction(completedTx);\n * ```\n */\n async transfer(\n txLike: ccc.TransactionLike,\n transfers: {\n to: ccc.ScriptLike;\n amount: ccc.NumLike;\n }[],\n ): Promise<{\n tx: ccc.Transaction;\n outputIndexes: number[];\n witnessIndex: number;\n }> {\n const tx = ccc.Transaction.from(txLike);\n const outputIndexes = [];\n\n for (const { to, amount } of transfers) {\n let cell = ccc.CellAny.from({\n cellOutput: { lock: to, type: await this.script },\n outputData: ccc.numLeToBytes(ccc.numFrom(amount), 16),\n });\n\n if (this.outputTransformer) {\n cell = ccc.CellAny.from(await this.outputTransformer(cell));\n }\n\n outputIndexes.push(tx.addOutput(cell.cellOutput, cell.outputData) - 1);\n }\n\n return {\n ...(await (\n await this.coBuild\n ).appendActions(\n tx,\n transfers.map((transfer) => TransferAction.from(transfer)),\n )),\n outputIndexes,\n };\n }\n\n /**\n * Make the transaction perform mint actions to the specified recipients.\n *\n * @returns An object containing:\n * - `tx`: The updated transaction with added mint outputs and CoBuild actions.\n * - `outputIndexes`: The indexes of the newly added Coin outputs in `tx.outputs`.\n * - `witnessIndex`: The index of the witness where CoBuild actions were appended.\n *\n * @example\n * ```typescript\n * const { tx } = await coin.mint(ccc.Transaction.from({}), [\n * { to: recipientLock, amount: 100n },\n * ]);\n * const { tx: completedTx } = await coin.completeBy(tx);\n * await completedTx.completeFeeBy(coin.signer);\n * await coin.signer.sendTransaction(completedTx);\n * ```\n */\n async mint(\n txLike: ccc.TransactionLike,\n mints: {\n to: ccc.ScriptLike;\n amount: ccc.NumLike;\n }[],\n ): Promise<{\n tx: ccc.Transaction;\n outputIndexes: number[];\n witnessIndex: number;\n }> {\n const tx = ccc.Transaction.from(txLike);\n const outputIndexes = [];\n\n for (const { to, amount } of mints) {\n let cell = ccc.CellAny.from({\n cellOutput: { lock: to, type: await this.script },\n outputData: ccc.numLeToBytes(ccc.numFrom(amount), 16),\n });\n\n if (this.outputTransformer) {\n cell = ccc.CellAny.from(await this.outputTransformer(cell));\n }\n\n outputIndexes.push(tx.addOutput(cell.cellOutput, cell.outputData) - 1);\n }\n\n return {\n ...(await (\n await this.coBuild\n ).appendActions(\n tx,\n mints.map((mint) => MintAction.from(mint)),\n )),\n outputIndexes,\n };\n }\n\n /**\n * Make the transaction perform burn actions for the specified amount.\n *\n * @returns An object containing:\n * - `tx`: The updated transaction with appended CoBuild actions.\n * - `witnessIndex`: The index of the witness where CoBuild actions were appended.\n *\n * @example\n * ```typescript\n * const { tx } = await coin.burn(ccc.Transaction.from({}), 100n);\n * const { tx: completedTx } = await coin.completeBy(tx);\n * await completedTx.completeFeeBy(coin.signer);\n * await coin.signer.sendTransaction(completedTx);\n * ```\n */\n async burn(\n txLike: ccc.TransactionLike,\n amount: ccc.NumLike,\n ): Promise<{\n tx: ccc.Transaction;\n witnessIndex: number;\n }> {\n return (await this.coBuild).appendActions(\n txLike,\n BurnAction.from({ amount }),\n );\n }\n}\n","import { ccc } from \"@ckb-ccc/core\";\n\n/**\n * Owner-mode flags encoded in xUDT type script args.\n *\n * These values occupy the high bits of the 4-byte flags field after the\n * 32-byte owner script hash. Lower bits are preserved by this package but are\n * not interpreted.\n *\n * @see {@link CoinXUdtArgs}\n * @public\n */\nexport enum CoinXUdtFlags {\n /** Disable input lock owner-mode validation. @public */\n ownerModeInputLockDisabled = 0x20000000,\n\n /** Enable owner-mode validation through an output type script. @public */\n ownerModeOutputType = 0x40000000,\n\n /** Enable owner-mode validation through an input type script. @public */\n ownerModeInputType = 0x80000000,\n}\n\n/**\n * Object-like representation of xUDT type script args.\n *\n * xUDT args are encoded as a 32-byte owner script hash followed by an optional\n * little-endian uint32 flags field. When `flags` is omitted or `0`, encoding\n * uses only the owner script hash.\n *\n * @public\n */\nexport type CoinXUdtArgsLike = {\n /**\n * The 32-byte hash of the owner script.\n *\n * This value identifies the xUDT's owner authority and is the first 32 bytes\n * of the xUDT type script args.\n */\n ownerScriptHash: ccc.HexLike;\n\n /**\n * Optional xUDT flags encoded as a little-endian uint32.\n *\n * Defaults to `0`. Use {@link CoinXUdtFlags} for the standard owner-mode\n * flags. Lower bits are accepted and preserved without local interpretation.\n */\n flags?: number | null;\n};\n\nconst CoinXUdtArgsCodec = ccc.Codec.from({\n encode(value) {\n const args = CoinXUdtArgs.from(value);\n const ownerScriptHash = ccc.bytesFrom(args.ownerScriptHash);\n\n if (args.flags === 0) {\n return ownerScriptHash;\n }\n\n return ccc.bytesConcat(ownerScriptHash, ccc.numLeToBytes(args.flags, 4));\n },\n decode(value) {\n const argsBytes = ccc.bytesFrom(value);\n if (argsBytes.length === 32) {\n return {\n ownerScriptHash: ccc.hexFrom(argsBytes),\n flags: 0,\n };\n }\n\n if (argsBytes.length >= 36) {\n return {\n ownerScriptHash: ccc.hexFrom(argsBytes.slice(0, 32)),\n flags: Number(ccc.numLeFromBytes(argsBytes.slice(32, 36))),\n };\n }\n\n throw new Error(\n `Invalid xUDT args length: expected 32 or at least 36 bytes, got ${argsBytes.length}`,\n );\n },\n from(value: CoinXUdtArgsLike) {\n return CoinXUdtArgs.from(value);\n },\n});\n\n/**\n * Encoded xUDT type script arguments.\n *\n * The binary layout is:\n *\n * - 32 bytes: owner script hash\n * - optional 4 bytes: little-endian flags\n * - optional trailing extension data, accepted by decoding but ignored when\n * re-encoding\n *\n * @example\n * ```ts\n * const args = CoinXUdtArgs.from({\n * ownerScriptHash: ownerLock.hash(),\n * flags: CoinXUdtFlags.ownerModeOutputType,\n * });\n * const typeArgs = args.toHex();\n * ```\n *\n * @public\n */\n@ccc.codec(CoinXUdtArgsCodec)\nexport class CoinXUdtArgs extends ccc.Entity.Base<\n CoinXUdtArgsLike,\n CoinXUdtArgs\n>() {\n /** The normalized 32-byte owner script hash. @public */\n public ownerScriptHash: ccc.Hex;\n\n /** The parsed xUDT flags. @public */\n public flags: number;\n\n /**\n * Creates a normalized xUDT args entity.\n *\n * Prefer {@link CoinXUdtArgs.from} for object input or `fromBytes` from the\n * codec-enabled entity API for raw type args.\n *\n * @public\n */\n constructor({\n ownerScriptHash,\n flags,\n }: ccc.DecodedType<typeof CoinXUdtArgsCodec>) {\n super();\n\n this.ownerScriptHash = ownerScriptHash;\n this.flags = flags;\n }\n\n /**\n * Normalizes an object-like xUDT args value.\n *\n * @throws if `ownerScriptHash` is not exactly 32 bytes.\n * @public\n */\n static from(value: CoinXUdtArgsLike): CoinXUdtArgs {\n const ownerScriptHash = ccc.bytesFrom(value.ownerScriptHash);\n if (ownerScriptHash.length !== 32) {\n throw new Error(\n `Invalid owner script hash length: expected 32 bytes, got ${ownerScriptHash.length}`,\n );\n }\n\n return new CoinXUdtArgs({\n ownerScriptHash: ccc.hexFrom(ownerScriptHash),\n flags: value.flags ?? 0,\n });\n }\n}\n","import { ccc } from \"@ckb-ccc/core\";\nimport {\n Coin,\n CoinOptionsBehavior,\n CoinOptionsClient,\n CoinOptionsScript,\n} from \"../coin/coin.js\";\nimport { CoinXUdtArgs, CoinXUdtArgsLike } from \"./args.js\";\n\n/**\n * Script configurations for {@link CoinXUdt}.\n *\n * `CoinXUdt` accepts either existing xUDT type args through `script.args`, or\n * structured args through `xUdtArgs`. When both are provided, `xUdtArgs` is\n * used to build the final `script.args`.\n *\n * A complete `script` with `codeHash` and `hashType` takes priority over\n * `knownScript`. If the script is incomplete, `knownScript` is used as\n * shorthand and defaults to {@link ccc.KnownScript.XUdt}.\n *\n * @public\n */\nexport type CoinXUdtOptionsScript = Omit<CoinOptionsScript, \"script\"> & {\n /**\n * Optional xUDT type script fields.\n *\n * Provide `args` to reuse existing xUDT args. Provide `codeHash` and\n * `hashType` to use an explicit deployment instead of the known xUDT script\n * shorthand.\n */\n script?: Partial<ccc.ScriptLike> | null;\n\n /**\n * Structured xUDT args.\n *\n * When provided, this value is encoded with {@link CoinXUdtArgs} and\n * overrides `script.args`.\n */\n xUdtArgs?: CoinXUdtArgsLike | null;\n};\n\n/**\n * Options for creating a {@link CoinXUdt} instance.\n *\n * Requires either `xUdtArgs` or `script.args` so the xUDT token identity can be\n * determined. Also requires either a `signer` or `client`, following\n * {@link Coin}'s construction rules.\n *\n * @public\n */\nexport type CoinXUdtOptions = CoinOptionsBehavior &\n CoinXUdtOptionsScript &\n CoinOptionsClient;\n\n/**\n * An extensible UDT (xUDT) Coin implementation.\n *\n * `CoinXUdt` is a small specialization of {@link Coin} that understands the\n * xUDT type args layout from [RFC 52](https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0052-extensible-udt/0052-extensible-udt.md).\n * It keeps the generic balance, transfer, and transaction completion\n * behavior from `Coin`, while exposing the parsed xUDT args via {@link CoinXUdt.args}.\n *\n * @example\n * ```ts\n * const xUdt = new CoinXUdt({\n * xUdtArgs: {\n * ownerScriptHash: ownerLock.hash(),\n * flags: CoinXUdtFlags.ownerModeOutputType,\n * },\n * signer,\n * });\n * ```\n *\n * @public\n */\nexport class CoinXUdt extends Coin {\n /**\n * Parsed and normalized xUDT type args.\n *\n * If `xUdtArgs` was provided, this is the normalized form of that value. If\n * only `script.args` was provided, this is parsed from the existing args.\n *\n * @public\n */\n public readonly args: CoinXUdtArgs;\n\n /**\n * Creates an xUDT coin helper.\n *\n * `xUdtArgs` takes priority over `script.args` for the final type script args.\n * A complete `script` takes priority over `knownScript`; otherwise the known\n * script shorthand defaults to {@link ccc.KnownScript.XUdt}.\n *\n * @throws if neither `xUdtArgs` nor `script.args` is provided.\n * @throws if the selected args cannot be parsed as xUDT args.\n * @public\n */\n constructor(options: CoinXUdtOptions) {\n let args;\n if (options.xUdtArgs != null) {\n args = CoinXUdtArgs.from(options.xUdtArgs);\n } else if (options.script?.args != null) {\n args = CoinXUdtArgs.fromBytes(options.script.args);\n } else {\n throw new Error(\n \"Either xUdtArgs or script.args must be provided for CoinXUdt\",\n );\n }\n\n super({\n ...options,\n script: {\n ...(options.script ?? {}),\n args: args.toBytes(),\n },\n knownScript: options.knownScript ?? ccc.KnownScript.XUdt,\n });\n\n this.args = args;\n }\n}\n","export * from \"./coBuild.js\";\nexport * from \"./coin/index.js\";\nexport * from \"./xUdt/index.js\";\n"],"mappings":"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"}