99 Inputs ,
1010 Transactions as TransactionsConstructor ,
1111 TransactionBlock as ProgrammingTransactionBlockBuilder ,
12+ TransactionArgument ,
1213} from './mystenlab/builder' ;
1314import utils from './utils' ;
1415import { MAX_COMMAND_ARGS , MAX_GAS_OBJECTS } from './constants' ;
@@ -88,6 +89,10 @@ export class TransferBuilder extends TransactionBuilder<TransferProgrammableTran
8889 this . sender ( txData . sender ) ;
8990 this . gasData ( txData . gasData ) ;
9091
92+ if ( txData . inputObjects ) {
93+ this . inputObjects ( txData . inputObjects ) ;
94+ }
95+
9196 const recipients = utils . getRecipients ( tx . suiTransaction ) ;
9297 this . send ( recipients ) ;
9398 }
@@ -104,6 +109,11 @@ export class TransferBuilder extends TransactionBuilder<TransferProgrammableTran
104109 ) ;
105110 assert ( this . _gasData , new BuildTransactionError ( 'gasData is required before building' ) ) ;
106111 this . validateGasData ( this . _gasData ) ;
112+
113+ // If inputObjects are provided, validate them
114+ if ( this . _inputObjects && this . _inputObjects . length > 0 ) {
115+ this . validateInputObjectsBase ( this . _inputObjects ) ;
116+ }
107117 }
108118
109119 /**
@@ -115,47 +125,73 @@ export class TransferBuilder extends TransactionBuilder<TransferProgrammableTran
115125 this . validateTransactionFields ( ) ;
116126 const programmableTxBuilder = new ProgrammingTransactionBlockBuilder ( ) ;
117127
118- // number of objects passed as gas payment should be strictly less than `MAX_GAS_OBJECTS`. When the transaction
119- // requires a larger number of inputs we use the merge command to merge the rest of the objects into the gasCoin
120- if ( this . _gasData . payment . length >= MAX_GAS_OBJECTS ) {
121- const gasPaymentObjects = this . _gasData . payment
122- . slice ( MAX_GAS_OBJECTS - 1 )
123- . map ( ( object ) => Inputs . ObjectRef ( object ) ) ;
124-
125- // limit for total number of `args: CallArg[]` for a single command is MAX_COMMAND_ARGS so the max length of
126- // `sources[]` for a `mergeCoins(destination, sources[])` command is MAX_COMMAND_ARGS - 1 (1 used up for
127- // `destination`). We need to create a total of `gasPaymentObjects/(MAX_COMMAND_ARGS - 1)` merge commands to
128- // merge all the objects
129- while ( gasPaymentObjects . length > 0 ) {
130- programmableTxBuilder . mergeCoins (
131- programmableTxBuilder . gas ,
132- gasPaymentObjects . splice ( 0 , MAX_COMMAND_ARGS - 1 ) . map ( ( object ) => programmableTxBuilder . object ( object ) )
133- ) ;
128+ if ( this . _sender !== this . _gasData . owner && this . _inputObjects && this . _inputObjects . length > 0 ) {
129+ const inputObjects = this . _inputObjects . map ( ( object ) => programmableTxBuilder . object ( Inputs . ObjectRef ( object ) ) ) ;
130+ const mergedObject = inputObjects . shift ( ) as TransactionArgument ;
131+ if ( inputObjects . length > 0 ) {
132+ programmableTxBuilder . mergeCoins ( mergedObject , inputObjects ) ;
134133 }
135- }
136-
137- this . _recipients . forEach ( ( recipient ) => {
138- const coin = programmableTxBuilder . add (
139- TransactionsConstructor . SplitCoins ( programmableTxBuilder . gas , [
134+ this . _recipients . forEach ( ( recipient ) => {
135+ const splitObject = programmableTxBuilder . splitCoins ( mergedObject , [
140136 programmableTxBuilder . pure ( Number ( recipient . amount ) ) ,
141- ] )
142- ) ;
143- programmableTxBuilder . add (
144- TransactionsConstructor . TransferObjects ( [ coin ] , programmableTxBuilder . object ( recipient . address ) )
145- ) ;
146- } ) ;
147- const txData = programmableTxBuilder . blockData ;
148- return {
149- type : this . _type ,
150- sender : this . _sender ,
151- tx : {
152- inputs : [ ...txData . inputs ] ,
153- transactions : [ ...txData . transactions ] ,
154- } ,
155- gasData : {
156- ...this . _gasData ,
157- payment : this . _gasData . payment . slice ( 0 , MAX_GAS_OBJECTS - 1 ) ,
158- } ,
159- } ;
137+ ] ) ;
138+ programmableTxBuilder . transferObjects ( [ splitObject ] , programmableTxBuilder . object ( recipient . address ) ) ;
139+ } ) ;
140+ const txData = programmableTxBuilder . blockData ;
141+ return {
142+ type : this . _type ,
143+ sender : this . _sender ,
144+ tx : {
145+ inputs : [ ...txData . inputs ] ,
146+ transactions : [ ...txData . transactions ] ,
147+ } ,
148+ gasData : {
149+ ...this . _gasData ,
150+ } ,
151+ } ;
152+ } else {
153+ // number of objects passed as gas payment should be strictly less than `MAX_GAS_OBJECTS`. When the transaction
154+ // requires a larger number of inputs we use the merge command to merge the rest of the objects into the gasCoin
155+ if ( this . _gasData . payment . length >= MAX_GAS_OBJECTS ) {
156+ const gasPaymentObjects = this . _gasData . payment
157+ . slice ( MAX_GAS_OBJECTS - 1 )
158+ . map ( ( object ) => Inputs . ObjectRef ( object ) ) ;
159+
160+ // limit for total number of `args: CallArg[]` for a single command is MAX_COMMAND_ARGS so the max length of
161+ // `sources[]` for a `mergeCoins(destination, sources[])` command is MAX_COMMAND_ARGS - 1 (1 used up for
162+ // `destination`). We need to create a total of `gasPaymentObjects/(MAX_COMMAND_ARGS - 1)` merge commands to
163+ // merge all the objects
164+ while ( gasPaymentObjects . length > 0 ) {
165+ programmableTxBuilder . mergeCoins (
166+ programmableTxBuilder . gas ,
167+ gasPaymentObjects . splice ( 0 , MAX_COMMAND_ARGS - 1 ) . map ( ( object ) => programmableTxBuilder . object ( object ) )
168+ ) ;
169+ }
170+ }
171+
172+ this . _recipients . forEach ( ( recipient ) => {
173+ const coin = programmableTxBuilder . add (
174+ TransactionsConstructor . SplitCoins ( programmableTxBuilder . gas , [
175+ programmableTxBuilder . pure ( Number ( recipient . amount ) ) ,
176+ ] )
177+ ) ;
178+ programmableTxBuilder . add (
179+ TransactionsConstructor . TransferObjects ( [ coin ] , programmableTxBuilder . object ( recipient . address ) )
180+ ) ;
181+ } ) ;
182+ const txData = programmableTxBuilder . blockData ;
183+ return {
184+ type : this . _type ,
185+ sender : this . _sender ,
186+ tx : {
187+ inputs : [ ...txData . inputs ] ,
188+ transactions : [ ...txData . transactions ] ,
189+ } ,
190+ gasData : {
191+ ...this . _gasData ,
192+ payment : this . _gasData . payment . slice ( 0 , MAX_GAS_OBJECTS - 1 ) ,
193+ } ,
194+ } ;
195+ }
160196 }
161197}
0 commit comments