package Ġcom . r 3 . cord a . sdk . token . workflow . selection Ċ Ċ import Ġco . parallel universe . fib ers . Suspend able Ċ import Ġcom . r 3 . cord a . sdk . token . contracts . commands . Move Token Command Ċ import Ġcom . r 3 . cord a . sdk . token . contracts . commands . Re deem Token Command Ċ import Ġcom . r 3 . cord a . sdk . token . contracts . states . F ung ible Token Ċ import Ġcom . r 3 . cord a . sdk . token . contracts . types . Iss ued TokenType Ċ import Ġcom . r 3 . cord a . sdk . token . contracts . types . TokenType Ċ import Ġcom . r 3 . cord a . sdk . token . contracts . utilities . iss ued By Ċ import Ġcom . r 3 . cord a . sdk . token . contracts . utilities . sum Token State And Refs Ċ import Ġcom . r 3 . cord a . sdk . token . contracts . utilities . with Not ary Ċ import Ġcom . r 3 . cord a . sdk . token . workflow . types . Party And Amount Ċ import Ġcom . r 3 . cord a . sdk . token . workflow . utilities . owned Token Amount Criteria Ċ import Ġcom . r 3 . cord a . sdk . token . workflow . utilities . sortBy State Ref Ascending Ċ import Ġnet . cord a . core . contracts . Amount Ċ import Ġnet . cord a . core . contracts . Amount . Companion . sum OrThrow Ċ import Ġnet . cord a . core . contracts . State And Ref Ċ import Ġnet . cord a . core . contracts . Transaction State Ċ import Ġnet . cord a . core . flows . Flow Logic Ċ import Ġnet . cord a . core . identity . Abstract Party Ċ import Ġnet . cord a . core . node . Service Hub Ċ import Ġnet . cord a . core . node . services . Vault Ċ import Ġnet . cord a . core . node . services . query By Ċ import Ġnet . cord a . core . node . services . vault . Query Criteria Ċ import Ġnet . cord a . core . node . services . vault . Sort Ċ import Ġnet . cord a . core . transactions . Transaction Builder Ċ import Ġnet . cord a . core . utilities . context Logger Ċ import Ġnet . cord a . core . utilities . millis Ċ import Ġnet . cord a . core . utilities . to Non Empty Set Ċ import Ġjava . security . PublicKey Ċ import Ġjava . util .* Ċ Ċ /** Ċ Ġ* ĠTokenType Ġselection Ġusing ĠHibernate . ĠIt Ġuses Ġroughly Ġthe Ġsame Ġlogic Ġthat Ġthe Ġcoin Ġselection Ġalgorithm Ġused Ġin Ċ Ġ* ĠAbstract Coin Selection Ġwithin Ġthe Ġfin ance Ġmodule . ĠThe Ġonly Ġdifference Ġis Ġthat Ġnow Ġthere Ġare Ġnot Ġspecific Ġdatabase Ċ Ġ* Ġimplementations , Ġinstead Ġhi bernate Ġis Ġused Ġfor Ġan Ġag nost ic Ġapproach . Ċ Ġ* Ċ Ġ* ĠWhen Ġcalling Ġ[ attempt S pend ] Ġthere Ġis Ġthe Ġoption Ġto Ġpass Ġin Ġa Ġcustom Ġ[ Query Criteria ] Ġand Ġ[ Sort ]. ĠThe Ġdefault Ġbehaviour Ċ Ġ* Ġis Ġto Ġorder Ġall Ġstates Ġby Ġ[ State Ref ] Ġand Ġquery Ġfor Ġa Ġspecific Ġtoken Ġtype . ĠThe Ġdefault Ġbehaviour Ġis Ġprobably Ġnot Ġvery Ċ Ġ* Ġefficient Ġbut Ġthe Ġbehaviour Ġcan Ġbe Ġcustom ised Ġif Ġnecessary . Ċ Ġ* Ċ Ġ* ĠThis Ġis Ġonly Ġreally Ġhere Ġas Ġa Ġstop gap Ġsolution Ġuntil Ġin - memory Ġtoken Ġselection Ġis Ġimplemented . Ċ Ġ* Ċ Ġ* Ġ@ param Ġservices Ġfor Ġperforming Ġvault Ġqueries . Ċ Ġ*/ Ċ class ĠToken Selection ( val Ġservices : ĠService Hub , Ġprivate Ġval Ġmax Retries : ĠInt Ġ= Ġ 8 , Ġprivate Ġval Ġretry Sleep : ĠInt Ġ= Ġ 1 0 0 , Ġprivate Ġval Ġretry Cap : ĠInt Ġ= Ġ 2 0 0 0 ) Ġ{ ĊĊĠĠĠ Ġcompanion Ġobject Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġlogger Ġ= Ġcontext Logger () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĠQueries Ġfor Ġowned Ġtoken Ġamounts Ġwith Ġthe Ġspecified Ġtoken Ġto Ġthe Ġspecified Ġrequired Amount . Ġ*/ ĊĠĠĠ Ġprivate Ġfun Ġ< T Ġ: ĠTokenType > Ġexecute Query ( ĊĠĠĠĠĠĠĠĠĠĠĠ Ġrequired Amount : ĠAmount < T >, ĊĠĠĠĠĠĠĠĠĠĠĠ Ġlock Id : ĠUUID , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġadditional Criteria : ĠQuery Criteria , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġsort er : ĠSort , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġstate And Refs : ĠMutable List < State And Ref < F ung ible Token < T >>> ĊĠĠĠ Ġ): ĠBoolean Ġ{ ĊĠĠĠĠĠĠĠ Ġ// ĠDid n 't Ġneed Ġto Ġselect Ġany Ġtokens . ĊĠĠĠĠĠĠĠ Ġif Ġ( required Amount . quantity Ġ== Ġ 0 L ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġfalse ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġ// ĠEn rich ĠQuery Criteria Ġwith Ġadditional Ġdefault Ġattributes Ġ( such Ġas Ġsoft Ġlocks ). ĊĠĠĠĠĠĠĠ Ġ// ĠWe Ġonly Ġwant Ġto Ġreturn ĠRE LE V ANT Ġstates Ġhere . ĊĠĠĠĠĠĠĠ Ġval Ġbase Criteria Ġ= ĠQuery Criteria . Vault Query Criteria ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcontract State Types Ġ= Ġset Of ( F ung ible Token :: class . java ), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġsoft Lock ing Condition Ġ= ĠQuery Criteria . Soft Lock ing Condition ( Query Criteria . Soft Lock ing Type . UNLOCK ED _ AND _ SPECIFIED , ĠlistOf ( lock Id )), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġre lev ancy Status Ġ= ĠVault . Re lev ancy Status . RE LE V ANT , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġstatus Ġ= ĠVault . State Status . UN CON SU MED ĊĠĠĠĠĠĠĠ Ġ) ĊĊĠĠĠĠĠĠĠ Ġ// ĠTODO : ĠAdd Ġpaging Ġin Ġcase Ġthere Ġare Ġnot Ġenough Ġstates Ġin Ġone Ġpage Ġto Ġfill Ġthe Ġrequired Ġrequired Amount . ĠE . g . ĠD ust . ĊĠĠĠĠĠĠĠ Ġval Ġresults : ĠVault . Page < F ung ible Token < T >> Ġ= Ġservices . vault Service . query By ( base Criteria . and ( additional Criteria ), Ġsort er ) ĊĊĠĠĠĠĠĠĠ Ġvar Ġclaimed Amount Ġ= Ġ 0 L ĊĠĠĠĠĠĠĠ Ġfor Ġ( state Ġin Ġresults . states ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġstate And Refs Ġ+= Ġstate ĊĠĠĠĠĠĠĠĠĠĠĠ Ġclaimed Amount Ġ+= Ġstate . state . data . amount . quantity ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( claimed Amount Ġ>= Ġrequired Amount . quantity ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġbreak ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġval Ġclaimed Amount With Token Ġ= ĠAmount ( claimed Amount , Ġrequired Amount . token ) ĊĠĠĠĠĠĠĠ Ġ// ĠNo Ġtokens Ġavailable . ĊĠĠĠĠĠĠĠ Ġif Ġ( state And Refs . isEmpty ()) Ġreturn Ġfalse ĊĠĠĠĠĠĠĠ Ġ// ĠThere Ġwere Ġnot Ġenough Ġtokens Ġavailable . ĊĠĠĠĠĠĠĠ Ġif Ġ( claimed Amount With Token Ġ< Ġrequired Amount ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġlogger . trace (" TokenType Ġselection Ġrequested Ġ$ required Amount Ġbut Ġretrieved Ġ$ claimed Amount With Token Ġwith Ġstate Ġrefs : Ġ${ state And Refs . map Ġ{ Ġit . ref Ġ}} ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġfalse ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġ// ĠWe Ġpicked Ġenough Ġtokens , Ġso Ġsoft lock Ġand Ġgo . ĊĠĠĠĠĠĠĠ Ġlogger . trace (" TokenType Ġselection Ġfor Ġ$ required Amount Ġretrieved Ġ${ state And Refs . count ()} Ġstates Ġtot all ing Ġ$ claimed Amount With Token : Ġ$ state And Refs ") ĊĠĠĠĠĠĠĠ Ġservices . vault Service . soft Lock Reserve ( lock Id , Ġstate And Refs . map Ġ{ Ġit . ref Ġ}. to Non Empty Set ()) ĊĠĠĠĠĠĠĠ Ġreturn Ġtrue ĊĠĠĠ Ġ} ĊĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠAttempt Ġspend Ġof Ġ[ required Amount ] Ġof Ġ[ F ung ible Token ] ĠT . ĠReturns Ġstates Ġthat Ġcover Ġgiven Ġamount . ĠNotice Ġthat Ġthis Ġfunction ĊĠĠĠĠ Ġ* Ġdoesn 't Ġcalculate Ġchange . ĠIf Ġquery Ġcriteria Ġis Ġnot Ġspecified Ġthen Ġonly Ġowned Ġtoken Ġamounts Ġare Ġused . ĊĠĠĠĠ Ġ* ĠUse Ġ[ Query Utilities . token Amount With Issuer Criteria ] Ġto Ġspecify Ġissuer . ĊĠĠĠĠ Ġ* ĊĠĠĠĠ Ġ* Ġ@ return ĠList Ġof Ġ[ F ung ible Token ] s Ġthat Ġsatisfy Ġthe Ġamount Ġto Ġspend , Ġempty Ġlist Ġif Ġnone Ġfound . ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġ@ Suspend able ĊĠĠĠ Ġfun Ġ< T Ġ: ĠTokenType > Ġattempt S pend ( ĊĠĠĠĠĠĠĠĠĠĠĠ Ġrequired Amount : ĠAmount < T >, ĊĠĠĠĠĠĠĠĠĠĠĠ Ġlock Id : ĠUUID , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġadditional Criteria : ĠQuery Criteria Ġ= Ġowned Token Amount Criteria ( required Amount . token ), ĊĠĠĠĠĠĠĠĠĠĠĠ Ġsort er : ĠSort Ġ= ĠsortBy State Ref Ascending () ĊĠĠĠ Ġ): ĠList < State And Ref < F ung ible Token < T >>> Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġstate And Refs Ġ= Ġmutable ListOf < State And Ref < F ung ible Token < T >> >() ĊĠĠĠĠĠĠĠ Ġfor Ġ( retry Count Ġin Ġ 1 .. max Retries ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠTODO : ĠNeed Ġto Ġspecify Ġexactly Ġwhy Ġit Ġfails . ĠLocked Ġstates Ġor Ġliter ally Ġ_ no _ Ġstates ! ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠNo Ġpoint Ġin Ġretry ing Ġif Ġthere Ġwill Ġnever Ġbe Ġenough ... ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ(! executeQuery ( required Amount , Ġlock Id , Ġadditional Criteria , Ġsort er , Ġstate And Refs )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlogger . warn (" TokenType Ġselection Ġfailed Ġon Ġattempt Ġ$ retry Count .") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠTODO : Ġre visit Ġthe Ġback Ġoff Ġstrategy Ġfor Ġcont ended Ġs pending . ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( retry Count Ġ!= Ġmax Retries ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġstate And Refs . clear () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġduration Millis Ġ= Ġ( min Of ( retry Sleep . sh l ( retry Count ), Ġretry Cap Ġ/ Ġ 2 ) Ġ* Ġ( 1 . 0 Ġ+ ĠMath . random ())). toInt () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠFlow Logic . sleep ( duration Millis . millis ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlogger . warn (" Ins ufficient Ġspend able Ġstates Ġidentified Ġfor Ġ$ required Amount .") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠTODO : ĠCreate Ġnew Ġexception Ġtype . ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġthrow ĠIllegalStateException (" Ins ufficient Ġspend able Ġstates Ġidentified Ġfor Ġ$ required Amount .") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġbreak ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġreturn Ġstate And Refs . toList () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠGenerate Ġmove Ġof Ġcertain Ġamount Ġof Ġ[ F ung ible Token ] ĠT Ġto Ġthe Ġ[ recipient ]. ĠThis Ġfunction Ġmut ates Ġ[ builder ] Ġprovided Ġas Ġparameter . ĊĠĠĠĠ Ġ* ĠIf Ġ[ change Owner ] Ġis Ġprovided , Ġthen Ġthe Ġchange Ġoutputs Ġ( if Ġpresent ) Ġwill Ġbe Ġreturned Ġback Ġto Ġthis Ġidentity . ĠIf Ġnot , ĊĠĠĠĠ Ġ* Ġthen Ġfresh Ġconf idential Ġidentity Ġfor Ġthe Ġcaller Ġwill Ġbe Ġcreated . ĊĠĠĠĠ Ġ* ĊĠĠĠĠ Ġ* Ġ@ return Ġ[ Transaction Builder ] Ġand Ġlist Ġof Ġall Ġowner Ġkeys Ġused Ġin Ġthe Ġinput Ġstates Ġthat Ġare Ġgoing Ġto Ġbe Ġmoved . ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġ@ Suspend able ĊĠĠĠ Ġfun Ġ< T Ġ: ĠTokenType > Ġgenerate Move ( ĊĠĠĠĠĠĠĠĠĠĠĠ Ġbuilder : ĠTransaction Builder , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġamount : ĠAmount < T >, ĊĠĠĠĠĠĠĠĠĠĠĠ Ġrecipient : ĠAbstract Party , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġquery Criteria : ĠQuery Criteria ? Ġ= Ġnull , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġchange Owner : ĠAbstract Party ? Ġ= Ġnull ĊĠĠĠ Ġ): ĠPair < Transaction Builder , ĠList < PublicKey >> Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġgenerate Move ( builder , ĠlistOf ( Party And Amount ( recipient , Ġamount )), Ġquery Criteria , Ġchange Owner ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠGenerate Ġmove Ġof Ġ[ F ung ible Token ] ĠT Ġto Ġparties Ġspecified Ġin Ġ[ Party And Amount ]. ĠEach Ġparty Ġwill Ġreceive Ġamount Ġdefined ĊĠĠĠĠ Ġ* Ġby Ġ[ party And Amount s ]. ĠIf Ġquery Ġcriteria Ġis Ġnot Ġspecified Ġthen Ġonly Ġowned Ġtoken Ġamounts Ġare Ġused . ĠUse Ġ[ Query Utilities . token Amount With Issuer Criteria ] ĊĠĠĠĠ Ġ* Ġto Ġspecify Ġissuer . ĠThis Ġfunction Ġmut ates Ġ[ builder ] Ġprovided Ġas Ġparameter . ĊĠĠĠĠ Ġ* ĠIf Ġ[ change Owner ] Ġis Ġprovided , Ġthen Ġthe Ġchange Ġoutputs Ġ( if Ġpresent ) Ġwill Ġbe Ġreturned Ġback Ġto Ġthis Ġidentity . ĠIf Ġnot , ĊĠĠĠĠ Ġ* Ġthen Ġfresh Ġconf idential Ġidentity Ġfor Ġthe Ġcaller Ġwill Ġbe Ġcreated . ĊĠĠĠĠ Ġ* ĊĠĠĠĠ Ġ* Ġ@ return Ġ[ Transaction Builder ] Ġand Ġlist Ġof Ġall Ġowner Ġkeys Ġused Ġin Ġthe Ġinput Ġstates Ġthat Ġare Ġgoing Ġto Ġbe Ġmoved . ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġ@ Suspend able ĊĠĠĠ Ġfun Ġ< T Ġ: ĠTokenType > Ġgenerate Move ( ĊĠĠĠĠĠĠĠĠĠĠĠ Ġbuilder : ĠTransaction Builder , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġparty And Amount s : ĠList < Party And Amount < T >>, ĊĠĠĠĠĠĠĠĠĠĠĠ Ġquery Criteria : ĠQuery Criteria ? Ġ= Ġnull , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġchange Owner : ĠAbstract Party ? Ġ= Ġnull ĊĠĠĠ Ġ): ĠPair < Transaction Builder , ĠList < PublicKey >> Ġ{ ĊĠĠĠĠĠĠĠ Ġ// ĠGrab Ġsome Ġtokens Ġfrom Ġthe Ġvault Ġand Ġsoft - lock . ĊĠĠĠĠĠĠĠ Ġ// ĠOnly Ġsupports Ġmoves Ġof Ġthe Ġsame Ġtoken Ġinstance Ġcurrently . ĊĠĠĠĠĠĠĠ Ġ// ĠTODO ĠSupport Ġsp ends Ġfor Ġdifferent Ġtoken Ġtypes , Ġdifferent Ġinstances Ġof Ġthe Ġsame Ġtype . ĊĠĠĠĠĠĠĠ Ġ// ĠThe Ġway Ġto Ġdo Ġthis Ġwill Ġbe Ġto Ġperform Ġa Ġquery Ġfor Ġeach Ġtoken Ġtype . ĠIf Ġthere Ġare Ġmultiple Ġtoken Ġtypes Ġthen ĊĠĠĠĠĠĠĠ Ġ// Ġjust Ġdo Ġall Ġthe Ġbelow Ġhowever Ġmany Ġtimes Ġis Ġnecessary . ĊĠĠĠĠĠĠĠ Ġval Ġtotal Required Ġ= Ġparty And Amount s . map Ġ{ Ġit . amount Ġ}. sum OrThrow () ĊĠĠĠĠĠĠĠ Ġval Ġadditional Criteria Ġ= Ġquery Criteria Ġ?: Ġowned Token Amount Criteria ( total Required . token ) ĊĠĠĠĠĠĠĠ Ġval Ġacceptable States Ġ= Ġattempt S pend ( total Required , Ġbuilder . lock Id , Ġadditional Criteria ) ĊĠĠĠĠĠĠĠ Ġrequire ( accept able States . isNotEmpty ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ" No Ġstates Ġmatching Ġgiven Ġcriteria Ġto Ġgenerate Ġmove ." ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ// ĠProvide Ġa Ġkey Ġto Ġsend Ġany Ġchange Ġto . ĠCurrently Ġtoken Ġselection Ġis Ġdone Ġonly Ġfor Ġthe Ġnode Ġoperator . ĊĠĠĠĠĠĠĠ Ġ// ĠTODO : ĠGeneral ise Ġthis Ġso Ġit Ġcan Ġbe Ġdone Ġfor Ġany Ġ" account ". ĊĠĠĠĠĠĠĠ Ġval Ġnode Identity Ġ= Ġservices . my Info . legal Id entities And Certs . first () ĊĠĠĠĠĠĠĠ Ġval Ġchange Party Ġ= Ġif Ġ( change Owner Ġ== Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠTODO ĠThis Ġapproach Ġis Ġclearly Ġtaken Ġfrom Ġcore . ĠRe visit Ġit . ĊĠĠĠĠĠĠĠĠĠĠĠ Ġservices . key Management Service . fresh Key And Cert ( node Identity , Ġrev ocation Enabled Ġ= Ġfalse ). party . anon ym ise () ĊĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠCheck Ġthat Ġthis Ġidentity Ġbelongs Ġto Ġthe Ġnode Ġthat Ġcalled Ġgenerate Move . ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġowner Id Ġ= Ġservices . identity Service . well Known Party From Anonymous ( change Owner ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġcheck ( owner Id Ġ!= Ġnull Ġ&& Ġservices . my Info . is Legal Identity ( owner Id )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" Owner Ġof Ġthe Ġchange : Ġ$ change Owner Ġis Ġnot Ġthe Ġidentity Ġthat Ġbelongs Ġto Ġthe Ġnode ." ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġchange Owner ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġ// ĠSet Ġthe Ġtransaction Ġnot ary . ĠCurrently , Ġthe Ġassumption Ġis Ġthat Ġall Ġstates Ġare Ġon Ġthe Ġsame Ġnot ary . ĊĠĠĠĠĠĠĠ Ġ// ĠTODO ĠGeneral ise Ġthis Ġto Ġdeal Ġwith Ġmultiple Ġnot aries Ġin Ġthe Ġfuture . ĊĠĠĠĠĠĠĠ Ġval Ġnot ary Ġ= Ġacceptable States . map Ġ{ Ġit . state . not ary Ġ}. toSet (). single () ĊĠĠĠĠĠĠĠ Ġbuilder . not ary Ġ= Ġnot ary ĊĊĠĠĠĠĠĠĠ Ġ// ĠNow Ġcalculate Ġthe Ġoutput Ġstates . ĠThis Ġis Ġcomplicated Ġby Ġthe Ġfact Ġthat Ġa Ġsingle Ġpayment Ġmay Ġrequire ĊĠĠĠĠĠĠĠ Ġ// Ġmultiple Ġoutput Ġstates , Ġdue Ġto Ġthe Ġneed Ġto Ġkeep Ġstates Ġseparated Ġby Ġissuer . ĠWe Ġstart Ġby Ġfig uring Ġout ĊĠĠĠĠĠĠĠ Ġ// Ġhow Ġmuch Ġwe 've Ġgather ed Ġfor Ġeach Ġissuer : Ġthis Ġmap Ġwill Ġkeep Ġtrack Ġof Ġhow Ġmuch Ġwe 've Ġused Ġfrom Ġeach ĊĠĠĠĠĠĠĠ Ġ// Ġas Ġwe Ġwork Ġour Ġway Ġthrough Ġthe Ġpayments . ĊĠĠĠĠĠĠĠ Ġval Ġtokens Group edBy Issuer : ĠMap < Iss ued TokenType < T >, ĠList < State And Ref < F ung ible Token < T >>>> Ġ= Ġacceptable States . groupBy Ġ{ Ġit . state . data . amount . token Ġ} ĊĠĠĠĠĠĠĠ Ġval Ġremaining Tokens From Each Issuer Ġ= Ġtokens Group edBy Issuer . map Values Ġ{ Ġ(_, Ġvalue ) Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġvalue . map Ġ{ Ġ( state ) Ġ-> Ġstate . data . amount Ġ}. sum OrThrow () ĊĠĠĠĠĠĠĠ Ġ}. toList (). to Mutable List () ĊĊĠĠĠĠĠĠĠ Ġ// ĠCalculate Ġthe Ġlist Ġof Ġoutput Ġstates Ġmaking Ġsure Ġthat Ġthe ĊĠĠĠĠĠĠĠ Ġval Ġoutput States Ġ= Ġmutable ListOf < Transaction State < F ung ible Token < T >> >() ĊĠĠĠĠĠĠĠ Ġfor Ġ(( party , Ġpayment Amount ) Ġin Ġparty And Amount s ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġvar Ġremaining To Pay Ġ= Ġpayment Amount . quantity ĊĠĠĠĠĠĠĠĠĠĠĠ Ġwhile Ġ( remaining To Pay Ġ> Ġ 0 ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġ( token , Ġremaining From Current Issuer ) Ġ= Ġremaining Tokens From Each Issuer . last () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġdelta Ġ= Ġremaining From Current Issuer . quantity Ġ- Ġremaining To Pay ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwhen Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġdelta Ġ> Ġ 0 Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠThe Ġstates Ġfrom Ġthe Ġcurrent Ġissuer Ġmore Ġthan Ġcovers Ġthis Ġpayment . ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġoutput States Ġ+= ĠF ung ible Token ( Amount ( remaining To Pay , Ġtoken ), Ġparty ) Ġwith Not ary Ġnot ary ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġremaining Tokens From Each Issuer [ remaining Tokens From Each Issuer . last Index ] Ġ= ĠPair ( token , ĠAmount ( delta , Ġtoken )) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġremaining To Pay Ġ= Ġ 0 ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġdelta Ġ== Ġ 0 L Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠThe Ġstates Ġfrom Ġthe Ġcurrent Ġissuer Ġexactly Ġcovers Ġthis Ġpayment . ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġoutput States Ġ+= ĠF ung ible Token ( Amount ( remaining To Pay , Ġtoken ), Ġparty ) Ġwith Not ary Ġnot ary ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġremaining Tokens From Each Issuer . remove At ( remaining Tokens From Each Issuer . last Index ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġremaining To Pay Ġ= Ġ 0 ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġdelta Ġ< Ġ 0 Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠThe Ġstates Ġfrom Ġthe Ġcurrent Ġissuer Ġdon 't Ġcover Ġthis Ġpayment , Ġso Ġwe 'll Ġhave Ġto Ġuse Ġ> 1 Ġoutput ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġstate Ġto Ġcover Ġthis Ġpayment . ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġoutput States Ġ+= ĠF ung ible Token ( remaining From Current Issuer , Ġparty ) Ġwith Not ary Ġnot ary ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġremaining Tokens From Each Issuer . remove At ( remaining Tokens From Each Issuer . last Index ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġremaining To Pay Ġ-= Ġremaining From Current Issuer . quantity ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġ// ĠGenerate Ġthe Ġchange Ġstates . ĊĠĠĠĠĠĠĠ Ġremaining Tokens From Each Issuer . forEach Ġ{ Ġ(_, Ġamount ) Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġoutput States Ġ+= ĠF ung ible Token ( amount , Ġchange Party ) Ġwith Not ary Ġnot ary ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġ// ĠCreate Ġa Ġmove Ġcommand Ġfor Ġeach Ġgroup . ĊĠĠĠĠĠĠĠ Ġtokens Group edBy Issuer . map Ġ{ Ġ( key , Ġvalue ) Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġkeys Ġ= Ġvalue . map Ġ{ Ġit . state . data . holder . own ing Key Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġbuilder . add Command ( Move Token Command ( key ), Ġkeys ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġfor Ġ( state Ġin Ġacceptable States ) Ġbuilder . add Input State ( state ) ĊĠĠĠĠĠĠĠ Ġfor Ġ( state Ġin Ġoutput States ) Ġbuilder . add Output State ( state ) ĊĊĠĠĠĠĠĠĠ Ġ// ĠWhat Ġif Ġwe Ġalready Ġhave Ġa Ġmove Ġcommand Ġwith Ġthe Ġright Ġkeys ? ĠFilter Ġit Ġout Ġhere Ġor Ġin Ġplatform Ġcode ? ĊĊĠĠĠĠĠĠĠ Ġval Ġall Keys Used Ġ= Ġacceptable States . map Ġ{ Ġit . state . data . holder . own ing Key Ġ} ĊĠĠĠĠĠĠĠ Ġreturn ĠPair ( builder , Ġall Keys Used ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ// ĠMod ifies Ġbuilder Ġin Ġplace . ĠAll Ġchecks Ġfor Ġexit Ġstates Ġshould Ġhave Ġbeen Ġdone Ġbefore . ĊĠĠĠ Ġ// ĠFor Ġexample Ġwe Ġassume Ġthat Ġexist States Ġhave Ġsame Ġissuer . ĊĠĠĠ Ġ@ Suspend able ĊĠĠĠ Ġfun Ġ< T Ġ: ĠTokenType > Ġgenerate Exit ( ĊĠĠĠĠĠĠĠĠĠĠĠ Ġbuilder : ĠTransaction Builder , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġexit States : ĠList < State And Ref < F ung ible Token < T >> >, ĊĠĠĠĠĠĠĠĠĠĠĠ Ġamount : ĠAmount < T >, ĊĠĠĠĠĠĠĠĠĠĠĠ Ġchange Owner : ĠAbstract Party ĊĠĠĠ Ġ) Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġfirst State Ġ= Ġexit States . first (). state . data ĊĠĠĠĠĠĠĠ Ġ// ĠChoose Ġstates Ġto Ġcover Ġamount Ġ- Ġreturn Ġones Ġused , Ġand Ġchange Ġoutput ĊĠĠĠĠĠĠĠ Ġval Ġchange Output Ġ= Ġchange ( exit States , Ġamount , Ġchange Owner ) ĊĠĠĠĠĠĠĠ Ġval Ġmove Key Ġ= Ġfirst State . holder . own ing Key ĊĠĠĠĠĠĠĠ Ġval Ġissuer Key Ġ= Ġfirst State . amount . token . issuer . own ing Key ĊĠĠĠĠĠĠĠ Ġval Ġrede em Command Ġ= ĠRe deem Token Command ( first State . amount . token ) ĊĠĠĠĠĠĠĠ Ġbuilder . apply Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġexit States . forEach Ġ{ Ġadd Input State ( it ) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( change Output Ġ!= Ġnull ) Ġadd Output State ( change Output ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġadd Command ( re deem Command , Ġissuer Key , Ġmove Key ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġ< T Ġ: ĠTokenType > Ġchange ( exit States : ĠList < State And Ref < F ung ible Token < T >> >, Ġamount : ĠAmount < T >, Ġchange Owner : ĠAbstract Party ): ĠF ung ible Token < T >? Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġassets Sum Ġ= Ġexit States . sum Token State And Refs () ĊĠĠĠĠĠĠĠ Ġval Ġdifference Ġ= Ġassets Sum Ġ- Ġamount . iss ued By ( exit States . first (). state . data . amount . token . issuer ) ĊĠĠĠĠĠĠĠ Ġcheck ( difference . quantity Ġ>= Ġ 0 ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ" Sum Ġof Ġexit Ġstates Ġshould Ġbe Ġqual Ġor Ġgreater Ġthan Ġthe Ġamount Ġto Ġexit ." ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġreturn Ġif Ġ( difference . quantity Ġ== Ġ 0 L ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġnull ĊĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠF ung ible Token ( difference , Ġchange Owner ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} Ċ }