@@ -11,7 +11,6 @@ import {
1111 xprvToRawPrv ,
1212 xpubToCompressedPub ,
1313} from '@bitgo/sdk-core' ;
14- import * as utxolib from '@bitgo/utxo-lib' ;
1514import {
1615 createPsbtForSingleInscriptionPassingTransaction ,
1716 DefaultInscriptionConstraints ,
@@ -23,13 +22,39 @@ import {
2322 findOutputLayoutForWalletUnspents ,
2423 MAX_UNSPENTS_FOR_OUTPUT_LAYOUT ,
2524 SatPoint ,
25+ WalletUnspent ,
26+ type TapLeafScript ,
2627} from '@bitgo/utxo-ord' ;
28+ import { fixedScriptWallet , type CoinName } from '@bitgo/wasm-utxo' ;
2729
28- import { AbstractUtxoCoin , RootWalletKeys } from '../../abstractUtxoCoin' ;
29- import { getWalletKeys } from '../../recovery/crossChainRecovery' ;
30+ import { AbstractUtxoCoin } from '../../abstractUtxoCoin' ;
31+
32+ /** Key identifier for signing */
33+ type SignerKey = 'user' | 'backup' | 'bitgo' ;
34+
35+ /** Unspent from wallet API (value may be number or bigint) */
36+ type WalletUnspentLike = {
37+ id : string ;
38+ value : number | bigint ;
39+ chain : number ;
40+ index : number ;
41+ } ;
42+
43+ const { RootWalletKeys : WasmRootWalletKeys } = fixedScriptWallet ;
3044
3145const SUPPLEMENTARY_UNSPENTS_MIN_VALUE_SATS = [ 0 , 20_000 , 200_000 ] ;
3246
47+ /** Map coin chain to CoinName for wasm-utxo */
48+ function getCoinName ( coin : AbstractUtxoCoin ) : CoinName {
49+ const chain = coin . getChain ( ) ;
50+ // CoinName matches the chain name for Bitcoin
51+ const validCoins : CoinName [ ] = [ 'btc' , 'tbtc' , 'tbtc4' , 'tbtcsig' , 'tbtcbgsig' ] ;
52+ if ( validCoins . includes ( chain as CoinName ) ) {
53+ return chain as CoinName ;
54+ }
55+ throw new Error ( `Unsupported coin for inscriptions: ${ chain } ` ) ;
56+ }
57+
3358export class InscriptionBuilder implements IInscriptionBuilder {
3459 private readonly wallet : IWallet ;
3560 private readonly coin : AbstractUtxoCoin ;
@@ -45,9 +70,21 @@ export class InscriptionBuilder implements IInscriptionBuilder {
4570
4671 const derived = this . coin . deriveKeyWithSeed ( { key : user . pub , seed : inscriptionData . toString ( ) } ) ;
4772 const compressedPublicKey = xpubToCompressedPub ( derived . key ) ;
48- const xOnlyPublicKey = utxolib . bitgo . outputScripts . toXOnlyPublicKey ( Buffer . from ( compressedPublicKey , 'hex' ) ) ;
73+ const xOnlyPublicKey = Buffer . from ( compressedPublicKey , 'hex' ) . subarray ( 1 ) ; // Remove parity byte
4974
50- return inscriptions . createInscriptionRevealData ( xOnlyPublicKey , contentType , inscriptionData , this . coin . network ) ;
75+ const coinName = getCoinName ( this . coin ) ;
76+ const result = inscriptions . createInscriptionRevealData ( xOnlyPublicKey , contentType , inscriptionData , coinName ) ;
77+
78+ // Convert TapLeafScript to utxolib format for backwards compatibility
79+ return {
80+ address : result . address ,
81+ revealTransactionVSize : result . revealTransactionVSize ,
82+ tapLeafScript : {
83+ controlBlock : Buffer . from ( result . tapLeafScript . controlBlock ) ,
84+ script : Buffer . from ( result . tapLeafScript . script ) ,
85+ leafVersion : result . tapLeafScript . leafVersion ,
86+ } ,
87+ } ;
5188 }
5289
5390 private async prepareTransferWithExtraInputs (
@@ -59,36 +96,42 @@ export class InscriptionBuilder implements IInscriptionBuilder {
5996 inscriptionConstraints,
6097 txFormat,
6198 } : {
62- signer : utxolib . bitgo . KeyName ;
63- cosigner : utxolib . bitgo . KeyName ;
99+ signer : SignerKey ;
100+ cosigner : SignerKey ;
64101 inscriptionConstraints : {
65102 minChangeOutput ?: bigint ;
66103 minInscriptionOutput ?: bigint ;
67104 maxInscriptionOutput ?: bigint ;
68105 } ;
69106 txFormat ?: 'psbt' | 'legacy' ;
70107 } ,
71- rootWalletKeys : RootWalletKeys ,
108+ rootWalletKeys : fixedScriptWallet . RootWalletKeys ,
72109 outputs : InscriptionOutputs ,
73- inscriptionUnspents : utxolib . bitgo . WalletUnspent < bigint > [ ] ,
110+ inscriptionUnspents : WalletUnspent [ ] ,
74111 supplementaryUnspentsMinValue : number
75112 ) : Promise < PrebuildTransactionResult > {
76- let supplementaryUnspents : utxolib . bitgo . WalletUnspent < bigint > [ ] = [ ] ;
113+ let supplementaryUnspents : WalletUnspent [ ] = [ ] ;
77114 if ( supplementaryUnspentsMinValue > 0 ) {
78115 const response = await this . wallet . unspents ( {
79116 minValue : supplementaryUnspentsMinValue ,
80117 } ) ;
81118 // Filter out the inscription unspent from the supplementary unspents
82119 supplementaryUnspents = response . unspents
83- . filter ( ( unspent ) => unspent . id !== inscriptionUnspents [ 0 ] . id )
120+ . filter ( ( unspent : { id : string } ) => unspent . id !== inscriptionUnspents [ 0 ] . id )
84121 . slice ( 0 , MAX_UNSPENTS_FOR_OUTPUT_LAYOUT - 1 )
85- . map ( ( unspent ) => {
86- unspent . value = BigInt ( unspent . value ) ;
87- return unspent ;
88- } ) ;
122+ . map (
123+ ( unspent : WalletUnspentLike ) : WalletUnspent => ( {
124+ id : unspent . id ,
125+ value : BigInt ( unspent . value ) ,
126+ chain : unspent . chain ,
127+ index : unspent . index ,
128+ } )
129+ ) ;
89130 }
131+
132+ const coinName = getCoinName ( this . coin ) ;
90133 const psbt = createPsbtForSingleInscriptionPassingTransaction (
91- this . coin . network ,
134+ coinName ,
92135 {
93136 walletKeys : rootWalletKeys ,
94137 signer,
@@ -117,7 +160,7 @@ export class InscriptionBuilder implements IInscriptionBuilder {
117160 }
118161 return {
119162 walletId : this . wallet . id ( ) ,
120- txHex : txFormat === 'psbt' ? psbt . toHex ( ) : psbt . getUnsignedTx ( ) . toHex ( ) ,
163+ txHex : Buffer . from ( psbt . serialize ( ) ) . toString ( 'hex' ) ,
121164 txInfo : { unspents : allUnspents } ,
122165 feeInfo : { fee : Number ( outputLayout . layout . feeOutput ) , feeString : outputLayout . layout . feeOutput . toString ( ) } ,
123166 } ;
@@ -146,27 +189,36 @@ export class InscriptionBuilder implements IInscriptionBuilder {
146189 changeAddressType = 'p2wsh' ,
147190 txFormat = 'psbt' ,
148191 } : {
149- signer ?: utxolib . bitgo . KeyName ;
150- cosigner ?: utxolib . bitgo . KeyName ;
192+ signer ?: SignerKey ;
193+ cosigner ?: SignerKey ;
151194 inscriptionConstraints ?: {
152195 minChangeOutput ?: bigint ;
153196 minInscriptionOutput ?: bigint ;
154197 maxInscriptionOutput ?: bigint ;
155198 } ;
156- changeAddressType ?: utxolib . bitgo . outputScripts . ScriptType2Of3 ;
199+ changeAddressType ?: 'p2sh' | 'p2shP2wsh' | 'p2wsh' | 'p2tr' | 'p2trMusig2' ;
157200 txFormat ?: 'psbt' | 'legacy' ;
158201 }
159202 ) : Promise < PrebuildTransactionResult > {
160203 assert ( isSatPoint ( satPoint ) ) ;
161204
162- const rootWalletKeys = await getWalletKeys ( this . coin , this . wallet ) ;
205+ const rootWalletKeys = await this . getWasmWalletKeys ( ) ;
163206 const parsedSatPoint = parseSatPoint ( satPoint ) ;
164207 const transaction = await this . wallet . getTransaction ( { txHash : parsedSatPoint . txid } ) ;
165- const unspents : utxolib . bitgo . WalletUnspent < bigint > [ ] = [ transaction . outputs [ parsedSatPoint . vout ] ] ;
166- unspents [ 0 ] . value = BigInt ( unspents [ 0 ] . value ) ;
208+ const output = transaction . outputs [ parsedSatPoint . vout ] ;
209+ const unspents : WalletUnspent [ ] = [
210+ {
211+ id : `${ parsedSatPoint . txid } :${ parsedSatPoint . vout } ` ,
212+ value : BigInt ( output . value ) ,
213+ chain : output . chain ,
214+ index : output . index ,
215+ } ,
216+ ] ;
217+
218+ const changeChain = fixedScriptWallet . ChainCode . value ( changeAddressType , 'internal' ) ;
167219
168220 const changeAddress = await this . wallet . createAddress ( {
169- chain : utxolib . bitgo . getInternalChainCode ( changeAddressType ) ,
221+ chain : changeChain ,
170222 } ) ;
171223 const outputs : InscriptionOutputs = {
172224 inscriptionRecipient : recipient ,
@@ -197,6 +249,22 @@ export class InscriptionBuilder implements IInscriptionBuilder {
197249 throw new Error ( 'Fee too high for the selected unspent with this fee rate' ) ; // Exhausted all tries to supplement
198250 }
199251
252+ /**
253+ * Get wallet keys as wasm-utxo RootWalletKeys
254+ */
255+ private async getWasmWalletKeys ( ) : Promise < fixedScriptWallet . RootWalletKeys > {
256+ const keychainIds = this . wallet . keyIds ( ) ;
257+ const [ user , backup , bitgo ] = await Promise . all ( [
258+ this . wallet . baseCoin . keychains ( ) . get ( { id : keychainIds [ KeyIndices . USER ] } ) ,
259+ this . wallet . baseCoin . keychains ( ) . get ( { id : keychainIds [ KeyIndices . BACKUP ] } ) ,
260+ this . wallet . baseCoin . keychains ( ) . get ( { id : keychainIds [ KeyIndices . BITGO ] } ) ,
261+ ] ) ;
262+
263+ assert ( user . pub && backup . pub && bitgo . pub , 'Missing wallet public keys' ) ;
264+
265+ return WasmRootWalletKeys . from ( [ user . pub , backup . pub , bitgo . pub ] ) ;
266+ }
267+
200268 /**
201269 *
202270 * @param walletPassphrase
@@ -209,10 +277,10 @@ export class InscriptionBuilder implements IInscriptionBuilder {
209277 */
210278 async signAndSendReveal (
211279 walletPassphrase : string ,
212- tapLeafScript : utxolib . bitgo . TapLeafScript ,
280+ tapLeafScript : TapLeafScript ,
213281 commitAddress : string ,
214282 unsignedCommitTx : Buffer ,
215- commitTransactionUnspents : utxolib . bitgo . WalletUnspent [ ] ,
283+ commitTransactionUnspents : WalletUnspentLike [ ] ,
216284 recipientAddress : string ,
217285 inscriptionData : Buffer
218286 ) : Promise < SubmitTransactionResponse > {
@@ -230,19 +298,20 @@ export class InscriptionBuilder implements IInscriptionBuilder {
230298 const derived = this . coin . deriveKeyWithSeed ( { key : xprv , seed : inscriptionData . toString ( ) } ) ;
231299 const prv = xprvToRawPrv ( derived . key ) ;
232300
233- const fullySignedRevealTransaction = await inscriptions . signRevealTransaction (
301+ const coinName = getCoinName ( this . coin ) ;
302+ const fullySignedRevealTransaction = inscriptions . signRevealTransaction (
234303 Buffer . from ( prv , 'hex' ) ,
235304 tapLeafScript ,
236305 commitAddress ,
237306 recipientAddress ,
238307 Buffer . from ( halfSignedCommitTransaction . txHex , 'hex' ) ,
239- this . coin . network
308+ coinName
240309 ) ;
241310
242311 return this . wallet . submitTransaction ( {
243312 halfSigned : {
244313 txHex : halfSignedCommitTransaction . txHex ,
245- signedChildPsbt : fullySignedRevealTransaction . toHex ( ) ,
314+ signedChildPsbt : Buffer . from ( fullySignedRevealTransaction ) . toString ( 'hex' ) ,
246315 } ,
247316 } ) ;
248317 }
0 commit comments