@@ -11,11 +11,11 @@ use std::{
1111use iota_crypto:: IotaSigner ;
1212use iota_graphql_client:: {
1313 Client , DryRunResult ,
14- query_types:: { ObjectRef , TransactionMetadata } ,
14+ query_types:: { ObjectFilter , ObjectRef , TransactionMetadata } ,
1515} ;
1616use iota_types:: {
1717 Address , GasPayment , Identifier , ObjectId , ObjectReference , Owner , ProgrammableTransaction ,
18- Transaction , TransactionEffects , TransactionExpiration , TypeTag ,
18+ StructTag , Transaction , TransactionEffects , TransactionExpiration , TypeTag ,
1919} ;
2020use serde:: Serialize ;
2121
@@ -73,10 +73,21 @@ pub struct TransactionBuildData {
7373
7474impl TransactionBuildData {
7575 fn set_input ( & mut self , kind : InputKind , is_gas : bool ) -> Argument {
76- if let Some ( ( i, input) ) = self . inputs . iter_mut ( ) . find ( |( _, input) | input. kind == kind) {
76+ if let Some ( ( i, input) ) = self . inputs . iter_mut ( ) . find ( |( _, input) | {
77+ match ( kind. object_id ( ) , input. kind . object_id ( ) ) {
78+ ( Some ( id1) , Some ( id2) ) => id1 == id2,
79+ ( None , None ) => kind == input. kind ,
80+ _ => false ,
81+ }
82+ } ) {
7783 if is_gas {
7884 input. is_gas = true ;
7985 }
86+ // If the new input is already resolved, replace the old one in case it was
87+ // unresolved
88+ if let new_kind @ InputKind :: Input ( _) = kind {
89+ input. kind = new_kind;
90+ }
8091 return Argument :: Input ( * i as _ ) ;
8192 }
8293 let idx = self
@@ -698,10 +709,31 @@ impl<L> TransactionBuilder<Client, L> {
698709 } )
699710 }
700711
701- async fn resolve_ptb ( & mut self ) -> Result < Transaction , Error > {
712+ async fn resolve_ptb ( & mut self , default_gas : bool ) -> Result < Transaction , Error > {
702713 let mut inputs = Vec :: new ( ) ;
703714 let mut gas = Vec :: new ( ) ;
704715 let mut input_map = HashMap :: new ( ) ;
716+ if default_gas && !self . data . inputs . values ( ) . any ( |i| i. is_gas ) {
717+ for coin in self
718+ . client
719+ . objects (
720+ ObjectFilter {
721+ type_ : Some ( StructTag :: gas_coin ( ) . to_string ( ) ) ,
722+ owner : Some ( self . data . sender ) ,
723+ ..Default :: default ( )
724+ } ,
725+ Default :: default ( ) ,
726+ )
727+ . await
728+ . map_err ( Error :: Client ) ?
729+ . data
730+ {
731+ self . set_input (
732+ InputKind :: Input ( iota_types:: Input :: ImmutableOrOwned ( coin. object_ref ( ) ) ) ,
733+ true ,
734+ ) ;
735+ }
736+ }
705737 for ( id, input) in std:: mem:: take ( & mut self . data . inputs ) {
706738 match input. kind {
707739 InputKind :: ImmutableOrOwned ( object_id) | InputKind :: Receiving ( object_id) => {
@@ -815,7 +847,7 @@ impl<L> TransactionBuilder<Client, L> {
815847
816848 /// Convert this builder into a transaction.
817849 pub async fn finish ( mut self ) -> Result < Transaction , Error > {
818- let mut txn = self . resolve_ptb ( ) . await ?;
850+ let mut txn = self . resolve_ptb ( true ) . await ?;
819851 if self . data . gas_budget . is_none ( ) {
820852 let res = self
821853 . client
@@ -837,7 +869,7 @@ impl<L> TransactionBuilder<Client, L> {
837869
838870 /// Dry run the transaction.
839871 pub async fn dry_run ( mut self , skip_checks : bool ) -> Result < DryRunResult , Error > {
840- let txn = self . resolve_ptb ( ) . await ?;
872+ let txn = self . resolve_ptb ( false ) . await ?;
841873 if !txn. gas_payment . objects . is_empty ( ) && txn. gas_payment . budget == 0 {
842874 return Err ( Error :: DryRun (
843875 "gas coins were provided without a gas budget" . to_owned ( ) ,
0 commit comments