# BatchPurchaseFacilitator

**Contract Address:** [`0x01774B531591b286b9f02C6Bc02ab3fD9526Aa76`](https://basescan.org/address/0x01774B531591b286b9f02C6Bc02ab3fD9526Aa76)

Enables bulk ticket purchases with a mix of user-defined static tickets and randomly-generated dynamic tickets. Orders are prepaid and executed by keepers.

## State Variables

| Variable             | Type                             | Description                             |
| -------------------- | -------------------------------- | --------------------------------------- |
| `jackpot`            | `IJackpot`                       | Immutable reference to Jackpot contract |
| `usdc`               | `IERC20`                         | Immutable USDC token reference          |
| `batchOrders`        | `mapping(address => BatchOrder)` | Active batch orders per user            |
| `staticTickets`      | `mapping(address => Ticket[])`   | Static tickets per user                 |
| `minimumTicketCount` | `uint256`                        | Minimum tickets required per order      |
| `executionNonce`     | `uint256`                        | Nonce for dynamic ticket generation     |

## Structs

### BatchOrder

```solidity
struct BatchOrder {
    uint256 orderDrawingId;      // Drawing this order was created for
    uint64 remainingUSDC;        // USDC balance for remaining tickets
    uint64 remainingTickets;     // Tickets still to be purchased
    uint64 totalTicketsOrdered;  // Original total ticket count
    uint64 dynamicTicketCount;   // Number of dynamic (random) tickets
    address[] referrers;         // Referrer addresses
    uint256[] referralSplit;     // PRECISE_UNIT-scaled weights
}
```

### BatchOrderInfo

```solidity
struct BatchOrderInfo {
    BatchOrder batchOrder;       // Order details
    IJackpot.Ticket[] staticTickets;  // User's static tickets
}
```

## Enums

### ExecutionAction

```solidity
enum ExecutionAction {
    EXECUTE_PARTIAL,           // Execute some tickets, order continues
    EXECUTE_FINAL,             // Execute remaining tickets, order completed
    CANCEL_WRONG_DRAWING,      // Order is for different drawing
    CANCEL_DRAWING_LOCKED,     // Drawing locked, auto-cancelled
    CANCEL_TOO_MANY_REFERRERS, // Too many referrers, auto-cancelled
    CANCEL_USER_REQUESTED      // User requested cancellation
}
```

## Events

### BatchOrderCreated

```solidity
event BatchOrderCreated(
    address indexed payer,
    address indexed recipient,
    uint256 indexed drawingId,
    uint256 totalCost,
    uint256 dynamicTicketCount,
    uint256 staticTicketCount
);
```

### BatchOrderCancelled

```solidity
event BatchOrderCancelled(
    address indexed recipient,
    ExecutionAction indexed executionAction,
    uint256 refundAmount
);
```

### BatchOrderExecuted

```solidity
event BatchOrderExecuted(
    address indexed user,
    uint256 indexed drawingId,
    uint256[] ticketIds,
    uint256 ticketsExecuted,
    uint256 remainingTickets,
    uint256 remainingUSDC
);
```

## Functions

### createBatchOrder

Create a prepaid batch order for the current drawing.

```solidity
function createBatchOrder(
    address _recipient,
    uint64 _dynamicTicketCount,
    IJackpot.Ticket[] calldata _userStaticTickets,
    address[] calldata _referrers,
    uint256[] calldata _referralSplit
) external
```

**Parameters:**

| Name                  | Type        | Description                                |
| --------------------- | ----------- | ------------------------------------------ |
| `_recipient`          | `address`   | Address to receive ticket NFTs             |
| `_dynamicTicketCount` | `uint64`    | Number of random tickets to generate       |
| `_userStaticTickets`  | `Ticket[]`  | User-defined static tickets                |
| `_referrers`          | `address[]` | Referrer addresses for fee sharing         |
| `_referralSplit`      | `uint256[]` | PRECISE\_UNIT-scaled weights (sum to 1e18) |

**Requirements:**

* Jackpot must be initialized and not locked
* Recipient must not have an active order
* Total tickets (dynamic + static) >= `minimumTicketCount`
* Each static ticket must have valid numbers
* Caller must have approved sufficient USDC

**Example:**

```solidity
// Create 100 tickets: 90 random + 10 specific
uint64 dynamicCount = 90;

IJackpot.Ticket[] memory staticTickets = new IJackpot.Ticket[](10);
for (uint256 i = 0; i < 10; i++) {
    staticTickets[i] = IJackpot.Ticket({
        normals: myFavoriteNumbers[i],
        bonusball: myBonusBall
    });
}

// Calculate cost
uint256 ticketPrice = jackpot.getDrawingState(jackpot.currentDrawingId()).ticketPrice;
uint256 totalCost = 100 * ticketPrice;

// Approve and create order
usdc.approve(address(batchFacilitator), totalCost);
batchFacilitator.createBatchOrder(
    msg.sender,           // recipient
    dynamicCount,         // dynamic tickets
    staticTickets,        // static tickets
    new address[](0),     // no referrers
    new uint256[](0)      // no splits
);
```

***

### cancelBatchOrder

Cancel your active batch order and receive a refund.

```solidity
function cancelBatchOrder() external
```

**Requirements:**

* Caller must have an active batch order

**Example:**

```solidity
// Cancel order and get remaining USDC back
batchFacilitator.cancelBatchOrder();
```

***

### getBatchOrderInfo

Get batch order details for a user.

```solidity
function getBatchOrderInfo(address _recipient) external view returns (BatchOrderInfo memory)
```

**Parameters:**

| Name         | Type      | Description      |
| ------------ | --------- | ---------------- |
| `_recipient` | `address` | Address to query |

**Returns:**

| Type             | Description                      |
| ---------------- | -------------------------------- |
| `BatchOrderInfo` | Order details and static tickets |

**Example:**

```solidity
IBatchPurchaseFacilitator.BatchOrderInfo memory info =
    batchFacilitator.getBatchOrderInfo(msg.sender);

uint256 remainingTickets = info.batchOrder.remainingTickets;
uint256 remainingUSDC = info.batchOrder.remainingUSDC;
```

***

### hasActiveBatchOrder

Check if a recipient has an active batch order.

```solidity
function hasActiveBatchOrder(address _recipient) external view returns (bool)
```

**Parameters:**

| Name         | Type      | Description      |
| ------------ | --------- | ---------------- |
| `_recipient` | `address` | Address to check |

**Returns:**

| Type   | Description                 |
| ------ | --------------------------- |
| `bool` | True if active order exists |

**Example:**

```solidity
if (batchFacilitator.hasActiveBatchOrder(msg.sender)) {
    // User already has an active order
    revert("Cancel existing order first");
}
```

***

### getBatchOrderActions

Get recommended actions for a batch of users (for keepers).

```solidity
function getBatchOrderActions(
    address[] calldata _recipients,
    uint256 _maxTicketsPerBatch
) external view returns (ExecutionAction[] memory)
```

**Parameters:**

| Name                  | Type        | Description                    |
| --------------------- | ----------- | ------------------------------ |
| `_recipients`         | `address[]` | Addresses to evaluate          |
| `_maxTicketsPerBatch` | `uint256`   | Max tickets per execution call |

**Returns:**

| Type                | Description                            |
| ------------------- | -------------------------------------- |
| `ExecutionAction[]` | Recommended actions for each recipient |

## Batch Order Flow

1. **Create Order**: User approves USDC and calls `createBatchOrder`
2. **Keeper Execution**: Keepers call `executeBatchOrder` to process tickets
3. **Partial Execution**: Large orders may be executed across multiple transactions
4. **Completion/Cancellation**: Order completes when all tickets are bought or is cancelled

### Cancellation Scenarios

Orders are automatically cancelled with full refund when:

* Drawing is locked (drawing in progress)
* Order was created for a previous drawing
* Too many referrers (exceeds max allowed)

Users can manually cancel at any time before execution completes.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.megapot.io/developers/contract-overview/batch-purchase.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
