library DydxActionBuilder {

    function Deposit(uint positionIndex, uint marketId, uint amount, address from)
    internal
    pure
    returns (DydxActions.ActionArgs memory depositAction)
    {
        depositAction.actionType = DydxActions.ActionType.Deposit;
        depositAction.accountId = positionIndex;
        depositAction.primaryMarketId = marketId;
        depositAction.otherAddress = from;
        depositAction.amount = DydxTypes.AssetAmount({
            sign : true,
            denomination : DydxTypes.AssetDenomination.Wei,
            ref : DydxTypes.AssetReference.Delta,
            value : amount
            });
    }

    // The only way to deposit a variable amount into dYdX during the execution of an "operate" call is
    // to perform a "sell" action sending 0 wei and then the implementor of IExchangeWrapper returns the amount that
    // will be deposited. The 1 wei is an unfortunate side effect, however it is a very negligible amount. If, in a
    // future version of dYdX a DepositAll action is added, this would remove the need for this weird mechanic.
    function DepositAll(uint positionIndex, uint marketId, uint burnMarketId, address controller, bytes32 orderHash)
    internal
    pure
    returns (DydxActions.ActionArgs memory action)
    {
        action.actionType = DydxActions.ActionType.Sell;
        action.accountId = positionIndex;
        action.otherAddress = controller;
        action.data = abi.encode(orderHash);
        action.primaryMarketId = burnMarketId;
        action.secondaryMarketId = marketId;
        action.amount = DydxTypes.AssetAmount({
            sign : false,
            denomination : DydxTypes.AssetDenomination.Wei,
            ref : DydxTypes.AssetReference.Delta,
            value : 0
            });
    }

    // ---------------------------------

    function Withdraw(uint positionIndex, uint marketId, uint amount, address to)
    internal
    pure
    returns (DydxActions.ActionArgs memory withdrawAction)
    {
        withdrawAction.actionType = DydxActions.ActionType.Withdraw;
        withdrawAction.accountId = positionIndex;
        withdrawAction.primaryMarketId = marketId;
        withdrawAction.otherAddress = to;
        withdrawAction.amount = DydxTypes.AssetAmount({
            sign : false,
            denomination : DydxTypes.AssetDenomination.Wei,
            ref : DydxTypes.AssetReference.Delta,
            value : amount
            });
    }

    function WithdrawAll(uint positionIndex, uint marketId, address to)
    internal
    pure
    returns (DydxActions.ActionArgs memory withdrawAction)
    {
        withdrawAction.actionType = DydxActions.ActionType.Withdraw;
        withdrawAction.accountId = positionIndex;
        withdrawAction.primaryMarketId = marketId;
        withdrawAction.otherAddress = to;
        withdrawAction.amount = DydxTypes.AssetAmount({
            sign : true,
            denomination : DydxTypes.AssetDenomination.Wei,
            ref : DydxTypes.AssetReference.Target,
            value : 0
            });
    }

    // ---------------------------------

    // function Liquidation() {

    // }

    // ---------------------------------

    function SetExpiry(uint positionIndex, address expiry, uint marketId, uint expiryTime)
    internal
    pure
    returns (DydxActions.ActionArgs memory)
    {
        return ExternalCall({
            positionIndex : positionIndex,
            callee : expiry,
            data : abi.encode(marketId, expiryTime)
            });
    }

    function LoopringSettlement(
        bytes memory settlementData,
        address settlementCaller,
        uint positionIndex
    )
    internal
    pure
    returns (DydxActions.ActionArgs memory)
    {
        return ExternalCall({
            positionIndex : positionIndex,
            callee : settlementCaller,
            data : settlementData
            });
    }

    function ExternalCall(uint positionIndex, address callee, bytes memory data)
    internal
    pure
    returns (DydxActions.ActionArgs memory callAction)
    {
        callAction.actionType = DydxActions.ActionType.Call;
        callAction.accountId = positionIndex;
        callAction.otherAddress = callee;
        callAction.data = data;
    }
}
function Withdraw(uint positionIndex, uint marketId, uint amount, address to)
internal
pure
returns (DydxActions.ActionArgs memory withdrawAction)
{
    withdrawAction.actionType = DydxActions.ActionType.Withdraw;
    withdrawAction.accountId = positionIndex;
    withdrawAction.primaryMarketId = marketId;
    withdrawAction.otherAddress = to;
    withdrawAction.amount = DydxTypes.AssetAmount({
        sign : false,
        denomination : DydxTypes.AssetDenomination.Wei,
        ref : DydxTypes.AssetReference.Delta,
        value : amount
        });
}

// ---------------------------------