11import { BaseCoin as CoinConfig } from '@bitgo/statics' ;
2- import { TransactionType } from '@bitgo/sdk-core' ;
2+ import { BuildTransactionError , SolTransactionVersion , SolV1TransactionConfig , TransactionType } from '@bitgo/sdk-core' ;
3+ import { PublicKey , Transaction as SolTransaction , TransactionInstruction } from '@solana/web3.js' ;
4+ import nacl from 'tweetnacl' ;
35import { Transaction } from './transaction' ;
46import { TransactionBuilder } from './transactionBuilder' ;
57import { InstructionBuilderTypes } from './constants' ;
@@ -10,11 +12,15 @@ import {
1012 ConfidentialWithdraw ,
1113 ConfigureConfidentialTransferAccount ,
1214 InstructionParams ,
15+ Memo ,
1316 VerifyEqualityProof ,
1417 VerifyPubkeyValidity ,
1518 VerifyRangeProof ,
1619 VerifyValidityProof ,
1720} from './iface' ;
21+ import { compileV1Message } from './v1/compileV1Message' ;
22+ import { serializeV1Transaction } from './v1/serializeV1Transaction' ;
23+ import { solInstructionFactory } from './solInstructionFactory' ;
1824import assert from 'assert' ;
1925
2026/**
@@ -43,6 +49,8 @@ import assert from 'assert';
4349 */
4450export class ConfidentialTransferBuilder extends TransactionBuilder {
4551 private _ctInstructions : InstructionParams [ ] = [ ] ;
52+ private _version ?: SolTransactionVersion ;
53+ private _v1TransactionConfig ?: SolV1TransactionConfig ;
4654
4755 constructor ( _coinConfig : Readonly < CoinConfig > ) {
4856 super ( _coinConfig ) ;
@@ -53,6 +61,35 @@ export class ConfidentialTransferBuilder extends TransactionBuilder {
5361 return TransactionType . ConfidentialTransfer ;
5462 }
5563
64+ /**
65+ * Set the Solana transaction version.
66+ *
67+ * Defaults to legacy until set. When set to `1`, the builder assembles a v1
68+ * (SIMD-0296/0385) transaction: version byte `0x81`, an inline `transactionConfig`
69+ * instead of ComputeBudget instructions, no address lookup tables, and a
70+ * message-first wire format with signatures appended.
71+ *
72+ * @param version - the transaction version (0 = v0, 1 = v1)
73+ * @returns {this } This builder
74+ */
75+ version ( version : SolTransactionVersion ) : this {
76+ this . _version = version ;
77+ return this ;
78+ }
79+
80+ /**
81+ * Set the v1 transaction config (compute unit limit, heap size, loaded accounts
82+ * data size limit, and priority fee as total lamports). Required when
83+ * `version(1)` is set.
84+ *
85+ * @param config - the v1 transaction config
86+ * @returns {this } This builder
87+ */
88+ transactionConfig ( config : SolV1TransactionConfig ) : this {
89+ this . _v1TransactionConfig = config ;
90+ return this ;
91+ }
92+
5693 /**
5794 * Override the zk-elgamal-proof program id.
5895 *
@@ -232,8 +269,79 @@ export class ConfidentialTransferBuilder extends TransactionBuilder {
232269 protected async buildImplementation ( ) : Promise < Transaction > {
233270 assert ( this . _ctInstructions . length > 0 , 'At least one confidential transfer instruction must be specified' ) ;
234271
272+ if ( this . _version === 1 ) {
273+ return this . buildV1 ( ) ;
274+ }
275+
235276 this . _instructionsData = [ ...this . _ctInstructions ] ;
236277
237278 return await super . buildImplementation ( ) ;
238279 }
280+
281+ /**
282+ * Build a v1 (SIMD-0296/0385) confidential transfer transaction.
283+ *
284+ * Assembles the CT instructions via the shared instruction factory, compiles
285+ * and serializes a v1 message with the inline transaction config, signs the
286+ * message bytes with the builder's signers, and stores the resulting wire
287+ * bytes for broadcast. Also populates a metadata-only SolTransaction so the
288+ * transaction JSON and input/output extraction remain usable.
289+ *
290+ * @returns {Transaction } The built transaction holding the v1 wire bytes
291+ */
292+ private buildV1 ( ) : Transaction {
293+ assert ( this . _sender , new BuildTransactionError ( 'sender is required before building' ) ) ;
294+ assert ( this . _recentBlockhash , new BuildTransactionError ( 'recent blockhash is required before building' ) ) ;
295+ assert ( this . _v1TransactionConfig , 'transactionConfig is required to build a v1 confidential transfer transaction' ) ;
296+
297+ const instructions : TransactionInstruction [ ] = [ ] ;
298+ for ( const instruction of this . _ctInstructions ) {
299+ instructions . push ( ...solInstructionFactory ( instruction , this . _zkProofProgramId ) ) ;
300+ }
301+
302+ if ( this . _memo ) {
303+ const memoData : Memo = {
304+ type : InstructionBuilderTypes . Memo ,
305+ params : { memo : this . _memo } ,
306+ } ;
307+ this . _ctInstructions . push ( memoData ) ;
308+ instructions . push ( ...solInstructionFactory ( memoData ) ) ;
309+ }
310+
311+ const feePayer = this . _feePayer ? new PublicKey ( this . _feePayer ) : new PublicKey ( this . _sender ) ;
312+ const messageBytes = compileV1Message ( {
313+ instructions,
314+ feePayer,
315+ recentBlockhash : this . _recentBlockhash ,
316+ transactionConfig : this . _v1TransactionConfig ,
317+ } ) ;
318+
319+ const signatures : Uint8Array [ ] = [ ] ;
320+ for ( const signer of this . _signers ) {
321+ const secretKey = signer . getKeys ( true ) . prv ;
322+ assert ( secretKey instanceof Uint8Array , 'Missing private key' ) ;
323+ signatures . push ( nacl . sign . detached ( messageBytes , secretKey ) ) ;
324+ }
325+ for ( const signature of this . getAdditionalSignatures ( ) ) {
326+ signatures . push ( new Uint8Array ( signature . signature ) ) ;
327+ }
328+
329+ const v1Wire = serializeV1Transaction ( messageBytes , signatures ) ;
330+
331+ this . _transaction . v1TransactionBytes = v1Wire ;
332+ this . _transaction . v1MessageBytes = messageBytes ;
333+
334+ // Populate a metadata-only SolTransaction so toJson / loadInputsAndOutputs work.
335+ const metaTx = new SolTransaction ( ) ;
336+ metaTx . feePayer = feePayer ;
337+ metaTx . recentBlockhash = this . _recentBlockhash ;
338+ metaTx . add ( ...instructions ) ;
339+ this . _transaction . solTransaction = metaTx ;
340+
341+ this . _transaction . setTransactionType ( this . transactionType ) ;
342+ this . _transaction . setInstructionsData ( this . _ctInstructions ) ;
343+ this . _transaction . loadInputsAndOutputs ( ) ;
344+
345+ return this . _transaction ;
346+ }
239347}
0 commit comments