Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,17 @@ coverage/

# Temporary files
tmp/
temp/
temp/

# Python
__pycache__/
*.pyc
*.pyo
*.pyd
.venv/
.env/
venv/
env/

# admin frontend
admin-frontend/
Empty file added CLAUDE.MD
Empty file.
90 changes: 90 additions & 0 deletions docs/oracle-api.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
# Oracle API Documentation

## Mark Contract Ended

Endpoint: `POST /api/oracle/contracts/{contractId}/ended`

This endpoint is used to mark a contract as ended and close betting on the blockchain.

### Request Format

**URL Parameters:**
- `contractId` (string): The contract ID as a numeric string

**Request Body (JSON):**
```json
{
"contractId": 41,
"endedAt": "2025-01-18T22:43:00Z",
"bettingEndTime": 1737238980,
"chainId": 84532
}
```

**Required Fields:**
- `contractId` (number): Must match the contractId in the URL path
- `endedAt` (string): ISO date string when the contract ended
- `bettingEndTime` (number): Unix timestamp in seconds when betting should end
- `chainId` (number): Blockchain chain ID (e.g., 84532 for Base Sepolia)

### Example curl Request

```bash
curl -X POST http://localhost:3001/api/oracle/contracts/41/ended \
-H "Content-Type: application/json" \
-d '{
"contractId": 41,
"endedAt": "2025-01-18T22:43:00Z",
"bettingEndTime": 1737238980,
"chainId": 84532
}'
```

### Response Format

**Success (200 OK):**
```json
{
"success": true,
"data": {
"contractId": "41",
"action": "closed",
"idempotent": false,
"transactionHash": "0x..."
}
}
```

**Validation Error (400 Bad Request):**
```json
{
"success": false,
"error": "Validation failed",
"code": "VALIDATION_ERROR",
"details": [
{
"field": "body.contractId",
"message": "\"body.contractId\" is required"
}
]
}
```

### Error Handling

The endpoint handles blockchain errors gracefully:
- If the smart contract transaction fails, the endpoint continues processing
- Local contract state is updated even if blockchain operations fail
- Detailed error logging provides insight into transaction failures

Common blockchain error reasons:
- Contract already closed (status != 0)
- Oracle address not authorized
- Contract does not exist
- Insufficient gas or network issues

### Notes

- The endpoint is idempotent for the same `contractId` and `bettingEndTime`
- Blockchain failures do not prevent the endpoint from completing successfully
- The oracle continues processing even when smart contract interactions fail
88 changes: 88 additions & 0 deletions docs/oracle-declareWinner-verification.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
# Oracle declareWinner Format Verification

## Expected Smart Contract Format

```solidity
function declareWinner(uint256 _contractId, uint8 _winner) external onlyOracle {
// _winner values:
// 0 = None
// 1 = A
// 2 = B
}
```

## Current Oracle Implementation

### 1. ABI Definition (EthereumService.ts)
```typescript
this.contractABI = [
"function declareWinner(uint256 _contractId, uint8 _winner) external",
// ... other functions
]
```

### 2. Function Call (EthereumService.ts:221)
```typescript
async declareWinner(contractId: string, winner: Choice): Promise<string> {
const contract = new ethers.Contract(contractAddress, this.contractABI, this.wallet);
const tx = await contract.declareWinner(contractId, winner);
// ...
}
```

### 3. Choice Enum Definition (Choice.ts)
```typescript
export enum Choice {
NONE = 0,
A = 1,
B = 2
}
```

## Verification Result: ✅ PERFECT MATCH

The oracle's implementation **exactly matches** the expected smart contract format:

| Aspect | Expected | Actual | Match |
|--------|----------|---------|--------|
| Function Name | `declareWinner` | `declareWinner` | ✅ |
| Parameter 1 Type | `uint256` | `string` → auto-converted to `uint256` by ethers.js | ✅ |
| Parameter 1 Name | `_contractId` | `contractId` | ✅ |
| Parameter 2 Type | `uint8` | `Choice` enum (TypeScript number) | ✅ |
| Parameter 2 Name | `_winner` | `winner` | ✅ |
| Value 0 | None | `Choice.NONE = 0` | ✅ |
| Value 1 | A | `Choice.A = 1` | ✅ |
| Value 2 | B | `Choice.B = 2` | ✅ |

## Technical Details

1. **Type Conversion**: ethers.js automatically handles the conversion:
- `contractId` (string) → `uint256` via BigNumber conversion
- `winner` (Choice enum) → `uint8` (TypeScript enums compile to numbers)

2. **Usage Flow**:
```
DecideWinnerUseCase.execute()
blockchainService.declareWinner(contract.id, winnerChoice)
contract.declareWinner(contractId, winner) // ethers.js call
Smart Contract receives: (uint256, uint8)
```

3. **Example Transaction Data**:
- Contract ID "41" → `0x0000000000000000000000000000000000000000000000000000000000000029`
- Winner Choice.A → `0x01`
- Full calldata: `declareWinner(41, 1)`

## Conclusion

The oracle's smart contract call format is **completely compatible** with the expected schema. No changes are needed as the implementation correctly:

1. Uses the exact function signature expected by the smart contract
2. Maps Choice enum values correctly (0=NONE, 1=A, 2=B)
3. Relies on ethers.js for proper type conversion
4. Maintains consistency throughout the codebase

The current implementation is production-ready and will interact correctly with the deployed smart contract.
Loading