library LibTraderInternal {
    using SafeMath96 for uint96;
    using SafeMath for uint256;
    using SafeERC20 for IERC20;

    event DDXRewardIssued(address trader, uint96 amount);

    /**
     * @notice This function creates a new DDX wallet for a trader.
     * @param _trader Trader address.
     */
    function createDDXWallet(address _trader) internal {
        LibDiamondStorageTrader.DiamondStorageTrader storage dsTrader = LibDiamondStorageTrader.diamondStorageTrader();

        // Leveraging the minimal proxy contract/clone factory pattern
        // as described here (https://eips.ethereum.org/EIPS/eip-1167)
        IDDXWalletCloneable ddxWallet = IDDXWalletCloneable(LibClone.createClone(address(dsTrader.ddxWalletCloneable)));

        LibDiamondStorageDerivaDEX.DiamondStorageDerivaDEX storage dsDerivaDEX =
            LibDiamondStorageDerivaDEX.diamondStorageDerivaDEX();

        // Cloneable contracts have no constructor, so instead we use
        // an initialize function. This initialize delegates this
        // on-chain DDX wallet back to the trader and sets the allowance
        // for the DerivaDEX Proxy contract to be unlimited.
        ddxWallet.initialize(_trader, dsDerivaDEX.ddxToken, address(this));

        // Store the on-chain wallet address in the trader's storage
        dsTrader.traders[_trader].ddxWalletContract = address(ddxWallet);
    }

    /**
     * @notice This function issues DDX rewards to a trader. It can be
     *         called by any facet part of the diamond.
     * @param _amount DDX tokens to be rewarded.
     * @param _trader Trader address.
     */
    function issueDDXReward(uint96 _amount, address _trader) internal {
        LibDiamondStorageTrader.DiamondStorageTrader storage dsTrader = LibDiamondStorageTrader.diamondStorageTrader();

        TraderDefs.Trader storage trader = dsTrader.traders[_trader];

        // If trader does not have a DDX on-chain wallet yet, create one
        if (trader.ddxWalletContract == address(0)) {
            createDDXWallet(_trader);
        }

        LibDiamondStorageDerivaDEX.DiamondStorageDerivaDEX storage dsDerivaDEX =
            LibDiamondStorageDerivaDEX.diamondStorageDerivaDEX();

        // Add trader's DDX balance in the contract
        trader.ddxBalance = trader.ddxBalance.add96(_amount);

        // Transfer DDX from trader to trader's on-chain wallet
        dsDerivaDEX.ddxToken.mint(trader.ddxWalletContract, _amount);

        emit DDXRewardIssued(_trader, _amount);
    }
}
/**
 * @title TraderInternalLib
 * @author DerivaDEX
 * @notice This is a library of internal functions mainly defined in
 *         the Trader facet, but used in other facets.
 */
function createDDXWallet(address _trader) internal {
    LibDiamondStorageTrader.DiamondStorageTrader storage dsTrader = LibDiamondStorageTrader.diamondStorageTrader();

    // Leveraging the minimal proxy contract/clone factory pattern
    // as described here (https://eips.ethereum.org/EIPS/eip-1167)
    IDDXWalletCloneable ddxWallet = IDDXWalletCloneable(LibClone.createClone(address(dsTrader.ddxWalletCloneable)));

    LibDiamondStorageDerivaDEX.DiamondStorageDerivaDEX storage dsDerivaDEX =
        LibDiamondStorageDerivaDEX.diamondStorageDerivaDEX();

    // Cloneable contracts have no constructor, so instead we use
    // an initialize function. This initialize delegates this
    // on-chain DDX wallet back to the trader and sets the allowance
    // for the DerivaDEX Proxy contract to be unlimited.
    ddxWallet.initialize(_trader, dsDerivaDEX.ddxToken, address(this));

    // Store the on-chain wallet address in the trader's storage
    dsTrader.traders[_trader].ddxWalletContract = address(ddxWallet);
}

/**
 * @notice This function creates a new DDX wallet for a trader.
 * @param _trader Trader address.
 */