@startuml

title HOLD: Main operations

autonumber

box "Wallets" #LightBlue
    actor ORI as "Origin" #red
    actor TAR as "Target" #green
end box

box "System Agents" #LightGreen
    actor OPE as "Operator" #blue
    actor NOT as "Notary" #purple
end box
database DLT as "Blockchain"

ORI -> OPE: Request a new hold with the TAR and the amount
activate OPE
OPE --> DLT: holdFrom(holdId, wallet, origin, amount)
deactivate OPE
activate DLT

alt The hold id is not repeated

    DLT --> OPE: emit HoldOrdered(holdId, wallet, origin, amount, operator, expiration)
    activate OPE
    OPE --> ORI: Notify that the hold was ordered.
    deactivate OPE
    DLT --> NOT: emit HoldOrdered(holdId, wallet, origin, amount, operator, expiration)
    DLT --> TAR: emit HoldOrdered(holdId, wallet, origin, amount, operator, expiration)


    alt The hold is checked by the NOT and it is OK
        NOT --> DLT: releaseHold(holdId)
        activate DLT
        DLT --> OPE: emit HoldReleased(holdId, NOT.address, wallet, origin, amount, operator)
        activate OPE
        OPE --> ORI: Notify that the hold was released
        deactivate OPE
        DLT --> TAR: emit HoldReleased(holdId, NOT.address, wallet, origin, amount, operator)
        deactivate DLT

    else The hold time was expired

        autonumber 7
        OPE --> DLT: revokeByExpiration(holdId)
        activate DLT
        DLT --> OPE: emit HoldRevoked( holdId, NOT.address, wallet, origin, amount, operator, REVOKED_BY_EXPIRATION)
        activate OPE
        OPE --> ORI: Notify that the hold was revoked by expiration
        deactivate OPE
        DLT --> NOT: emit HoldRevoked( holdId, NOT.address, wallet, origin, amount, operator, REVOKED_BY_EXPIRATION)
        DLT --> TAR: emit HoldRevoked( holdId, NOT.address, wallet, origin, amount, operator, REVOKED_BY_EXPIRATION)
        deactivate DLT

    else The NOT revoke the operation

        autonumber 7
        NOT --> DLT: revokeByNOT(holdId)
        activate  DLT
        DLT --> OPE: emit HoldRevoked( holdId, NOT.address, wallet, origin, amount, operator, REVOKED_BY_NOT)
        activate OPE
        OPE --> ORI: Notify that the hold was revoked by expiration
        deactivate OPE
        DLT --> NOT: emit HoldRevoked( holdId, NOT.address, wallet, origin, amount, operator, REVOKED_BY_NOT)
        DLT --> TAR: emit HoldRevoked( holdId, NOT.address, wallet, origin, amount, operator, REVOKED_BY_NOT)
        deactivate DLT

    else The TAR do not accept the operation

        autonumber 7
        TAR --> DLT: revokeByTAR(holdId)
        activate DLT
        DLT --> OPE: emit HoldRevoked( holdId, NOT.address, wallet, origin, amount, operator, REVOKED_BY_TAR)
        activate OPE
        OPE --> ORI: Notify that the hold was revoked by the Target
        deactivate OPE
        DLT --> NOT: emit HoldRevoked( holdId, NOT.address, wallet, origin, amount, operator, REVOKED_BY_TAR)
        DLT --> TAR: emit HoldRevoked( holdId, NOT.address, wallet, origin, amount, operator, REVOKED_BY_TAR)
        deactivate DLT

    end


else the hold id exists
    autonumber 3
    DLT --> OPE: emit HoldIdExits(holdId)
    deactivate DLT
    activate OPE
    OPE --> ORI: Notify that the hold was not ordered.
    deactivate OPE

end

@enduml