# JackpotBridgeManager

Enables cross-chain ticket purchases and winnings claims using EIP-712 signatures. Acts as custodian for tickets purchased from other chains.

> **Important:** Ticket recipient addresses must be EOAs (Externally Owned Accounts), not smart contract addresses. Using a smart contract address as a recipient may result in lost tickets or winnings.

## State Variables

| Variable           | Type                                          | Description                                 |
| ------------------ | --------------------------------------------- | ------------------------------------------- |
| `jackpot`          | `IJackpot`                                    | Immutable reference to Jackpot contract     |
| `jackpotTicketNFT` | `IJackpotTicketNFT`                           | Immutable reference to ticket NFT contract  |
| `usdc`             | `IERC20`                                      | Immutable USDC token reference              |
| `relayDepository`  | `IRelayDepository`                            | Bridge depository for cross-chain transfers |
| `ticketOwner`      | `mapping(uint256 => address)`                 | Ticket ID → owner address                   |
| `userTickets`      | `mapping(address => mapping(uint256 => Set))` | User → drawing → ticket IDs                 |

## Structs

### ClaimWinningsData

```solidity
struct ClaimWinningsData {
    uint256[] ticketIds;       // Tickets to claim
    RelayTxData bridgeDetails; // Bridge transaction info
}
```

### RelayTxData

```solidity
struct RelayTxData {
    bytes32 bridgeId;  // Bridge transaction identifier
    uint256 amount;    // Amount to bridge
}
```

## Constants

```solidity
bytes32 CLAIM_WINNINGS_TYPEHASH = keccak256(
    "ClaimWinningsData(uint256[] ticketIds,RelayTxData bridgeDetails)RelayTxData(bytes32 bridgeId,uint256 amount)"
);

bytes32 CLAIM_TICKET_TYPEHASH = keccak256(
    "ClaimTicketData(uint256[] ticketIds,address recipient)"
);

bytes32 RELAY_TYPEHASH = keccak256("RelayTxData(bytes32 bridgeId,uint256 amount)");
```

## Events

### TicketsBought

```solidity
event TicketsBought(
    address indexed _recipient,
    uint256 indexed _drawingId,
    uint256[] _ticketIds
);
```

### WinningsClaimed

```solidity
event WinningsClaimed(
    address indexed _winner,
    uint256[] _ticketIds,
    uint256 _amount
);
```

### FundsBridged

```solidity
event FundsBridged(bytes32 indexed _bridgeId, uint256 _amount);
```

## Functions

### buyTickets

Purchase tickets on behalf of a cross-chain user.

> **Important:** The `_recipient` address must be an EOA (Externally Owned Account), not a smart contract address. Using a smart contract address may result in lost tickets or winnings.

```solidity
function buyTickets(
    IJackpot.Ticket[] memory _tickets,
    address _recipient,
    address[] memory _referrers,
    uint256[] memory _referralSplitBps,
    bytes32 _source
) external returns (uint256[] memory)
```

**Parameters:**

| Name                | Type        | Description                                     |
| ------------------- | ----------- | ----------------------------------------------- |
| `_tickets`          | `Ticket[]`  | Array of tickets to purchase                    |
| `_recipient`        | `address`   | Address that owns the tickets (on origin chain) |
| `_referrers`        | `address[]` | Referrer addresses for fee sharing              |
| `_referralSplitBps` | `uint256[]` | PRECISE\_UNIT-scaled weights                    |
| `_source`           | `bytes32`   | Source identifier for tracking                  |

**Returns:**

| Type        | Description                |
| ----------- | -------------------------- |
| `uint256[]` | Array of minted ticket IDs |

**Example:**

```solidity
// Relayer purchases tickets for cross-chain user
IJackpot.Ticket[] memory tickets = new IJackpot.Ticket[](1);
tickets[0] = IJackpot.Ticket({
    normals: [1, 2, 3, 4, 5],
    bonusball: 10
});

uint256 ticketCost = jackpot.getDrawingState(jackpot.currentDrawingId()).ticketPrice;
usdc.approve(address(bridgeManager), ticketCost);

uint256[] memory ticketIds = bridgeManager.buyTickets(
    tickets,
    crossChainUserAddress,
    new address[](0),
    new uint256[](0),
    bytes32("bridge-source")
);
```

***

### claimWinnings

Claim winnings and bridge funds to destination chain via signature.

```solidity
function claimWinnings(
    uint256[] memory _userTicketIds,
    RelayTxData memory _bridgeDetails,
    bytes memory _signature
) external
```

**Parameters:**

| Name             | Type          | Description                         |
| ---------------- | ------------- | ----------------------------------- |
| `_userTicketIds` | `uint256[]`   | Ticket IDs to claim                 |
| `_bridgeDetails` | `RelayTxData` | Bridge transaction details          |
| `_signature`     | `bytes`       | EIP-712 signature from ticket owner |

**Requirements:**

* At least one ticket ID must be provided
* Signature must be valid and from ticket owner
* Tickets must have claimable winnings
* Bridge amount must match claimed amount

**Example:**

```solidity
// On the origin chain, user signs the claim message
uint256[] memory ticketIds = [ticketId1, ticketId2];
RelayTxData memory bridgeDetails = RelayTxData({
    bridgeId: bytes32("unique-bridge-id"),
    amount: expectedWinnings
});

bytes32 hash = bridgeManager.createClaimWinningsEIP712Hash(ticketIds, bridgeDetails);
bytes memory signature = signMessage(hash, userPrivateKey);

// Relayer executes on destination chain
bridgeManager.claimWinnings(ticketIds, bridgeDetails, signature);
```

***

### claimTickets

Transfer ticket NFTs to local chain custody via signature.

```solidity
function claimTickets(
    uint256[] memory _ticketIds,
    address _recipient,
    bytes memory _signature
) external
```

**Parameters:**

| Name         | Type        | Description                         |
| ------------ | ----------- | ----------------------------------- |
| `_ticketIds` | `uint256[]` | Ticket IDs to transfer              |
| `_recipient` | `address`   | Address to receive the NFTs         |
| `_signature` | `bytes`     | EIP-712 signature from ticket owner |

**Requirements:**

* Recipient must not be zero address
* Recipient must not be the bridge manager
* Signature must be valid and from ticket owner

**Example:**

```solidity
// User wants to move tickets to local custody
uint256[] memory ticketIds = [ticketId1];
address recipient = localWalletAddress;

bytes32 hash = bridgeManager.createClaimTicketEIP712Hash(ticketIds, recipient);
bytes memory signature = signMessage(hash, userPrivateKey);

bridgeManager.claimTickets(ticketIds, recipient, signature);
// NFTs now owned by recipient
```

***

### getUserTickets

Get all ticket IDs owned by a user for a specific drawing.

```solidity
function getUserTickets(
    address _user,
    uint256 _drawingId
) external view returns (uint256[] memory)
```

**Parameters:**

| Name         | Type      | Description                 |
| ------------ | --------- | --------------------------- |
| `_user`      | `address` | Address of the ticket owner |
| `_drawingId` | `uint256` | Drawing to query            |

**Returns:**

| Type        | Description         |
| ----------- | ------------------- |
| `uint256[]` | Array of ticket IDs |

***

### createClaimWinningsEIP712Hash

Create EIP-712 hash for claiming winnings.

```solidity
function createClaimWinningsEIP712Hash(
    uint256[] memory _userTicketIds,
    RelayTxData memory _bridgeDetails
) public view returns (bytes32)
```

***

### createClaimTicketEIP712Hash

Create EIP-712 hash for claiming tickets.

```solidity
function createClaimTicketEIP712Hash(
    uint256[] memory _ticketIds,
    address _recipient
) public view returns (bytes32)
```

## Cross-Chain Flow

### Buying Tickets from Another Chain

1. User initiates purchase on origin chain
2. Relayer receives message and calls `buyTickets` on Base
3. Bridge manager holds NFTs as custodian
4. Ownership tracked via `ticketOwner` mapping

### Claiming Winnings Cross-Chain

1. Drawing completes on Base
2. User creates EIP-712 signed message on origin chain
3. Relayer calls `claimWinnings` with signature
4. Winnings are bridged back via Relay depository

### Moving Tickets to Local Custody

1. User signs ticket claim message
2. Relayer executes `claimTickets`
3. NFTs transferred from bridge manager to recipient
4. User can now interact directly with tickets
