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
26 changes: 26 additions & 0 deletions agents/airdrop-distributor/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# ── PayPol Community Agent Configuration ──────────────────
#
# Copy this file to .env and fill in your values:
# cp .env.example .env

# Your agent's public port (default: 3002)
AGENT_PORT=3002

# Your wallet address (receives AlphaUSD payments via NexusV2 escrow)
OWNER_WALLET=0xYourWalletAddress

# Your GitHub username (shown on marketplace)
GITHUB_HANDLE=your-github-username

# PayPol marketplace URL (default: http://localhost:3000)
PAYPOL_MARKETPLACE_URL=http://localhost:3000

# Your agent's publicly reachable URL (for marketplace webhook calls)
# In local dev, use ngrok or similar tunneling service
AGENT_WEBHOOK_URL=http://localhost:3002

# Optional: Tempo RPC for on-chain operations
TEMPO_RPC_URL=https://rpc.moderato.tempo.xyz

# Optional: Private key for on-chain transactions (NEVER commit this!)
# DAEMON_PRIVATE_KEY=0x...
219 changes: 219 additions & 0 deletions agents/airdrop-distributor/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,219 @@
# Airdrop Distribution Agent

Automates token airdrops using the PayPol MultisendVaultV2 contract on Tempo L1.

## Features

- ✅ Batch distribution to up to 100 recipients per transaction
- ✅ Address validation (checksummed, non-zero)
- ✅ Balance checking before execution
- ✅ Detailed per-recipient receipts
- ✅ Dry-run mode for cost estimation
- ✅ CSV and JSON input formats
- ✅ Multi-token support (AlphaUSD, pathUSD, etc.)
- ✅ Graceful error handling with detailed validation messages

## Quick Start

```bash
# Install dependencies
npm install

# Configure environment
cp .env.example .env
# Edit .env with your DAEMON_PRIVATE_KEY and GITHUB_HANDLE

# Start the agent
npm run dev

# Test locally
curl -X POST http://localhost:3002/execute \
-H "Content-Type: application/json" \
-d @test-payload.json
```

## Usage

### JSON Format

```json
{
"prompt": "Distribute 1000 AlphaUSD to community members",
"payload": {
"token": "AlphaUSD",
"recipients": [
{"address": "0xabc...", "amount": "500"},
{"address": "0xdef...", "amount": "300"},
{"address": "0x123...", "amount": "200"}
],
"dryRun": false
}
}
```

### CSV Format

```json
{
"prompt": "Airdrop from CSV",
"payload": {
"token": "AlphaUSD",
"csv": "address,amount\n0xabc...,500\n0xdef...,300\n0x123...,200",
"dryRun": false
}
}
```

## Parameters

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `token` | string | No | Token name or address (default: AlphaUSD) |
| `recipients` | array | Yes* | Array of {address, amount} objects |
| `csv` | string | Yes* | CSV string with header (address,amount) |
| `dryRun` | boolean | No | If true, validates and estimates without executing |

*Either `recipients` or `csv` must be provided.

## Supported Tokens

- AlphaUSD (0x20c0000000000000000000000000000000000001)
- pathUSD
- BetaUSD
- ThetaUSD
- Custom ERC20 tokens (provide contract address)

## Response Format

### Success (Dry Run)

```json
{
"status": "success",
"result": {
"action": "airdrop_dry_run",
"token": "AlphaUSD",
"totalRecipients": 3,
"totalAmount": "1000",
"vaultBalance": "5000",
"recipients": [...],
"estimatedGas": "~500,000",
"message": "Dry run complete. Set dryRun: false to execute."
}
}
```

### Success (Executed)

```json
{
"status": "success",
"result": {
"action": "airdrop_executed",
"onChain": true,
"txHash": "0x...",
"explorerUrl": "https://explore.tempo.xyz/tx/0x...",
"batchId": "0x...",
"token": "AlphaUSD",
"totalRecipients": 3,
"totalAmount": "1000",
"gasUsed": 487234,
"blockNumber": 12345,
"recipients": [
{"index": 0, "address": "0xabc...", "amount": "500", "status": "success"},
{"index": 1, "address": "0xdef...", "amount": "300", "status": "success"},
{"index": 2, "address": "0x123...", "amount": "200", "status": "success"}
],
"message": "Successfully distributed 1000 AlphaUSD to 3 recipients."
}
}
```

### Error

```json
{
"status": "error",
"error": "Validation failed:\nRecipient 0: Invalid address 0xinvalid\nRecipient 2: Invalid amount -10"
}
```

## Validation Rules

1. **Address Validation**
- Must be valid Ethereum address
- Must be checksummed
- Cannot be zero address (0x0000...0000)

2. **Amount Validation**
- Must be positive number
- Must be valid decimal string

3. **Batch Limits**
- Maximum 100 recipients per batch
- Total amount must not exceed vault balance

4. **Balance Check**
- Vault must have sufficient token balance
- Check performed before execution

## Error Handling

The agent handles errors gracefully:

- **Validation errors**: Returns detailed list of invalid recipients
- **Insufficient balance**: Shows required vs available amounts
- **Transaction failures**: Returns error message with context
- **Partial failures**: Individual transfer status in receipt

## Contract Integration

Uses PayPol MultisendVaultV2 at `0x6A467Cd4156093bB528e448C04366586a1052Fab`:

```solidity
function executeMultiTokenBatch(
address token,
address[] calldata recipients,
uint256[] calldata amounts,
bytes32 batchId
) external;
```

## Network Info

- **Chain**: Tempo Moderato (Chain ID: 42431)
- **RPC**: https://rpc.moderato.tempo.xyz
- **Explorer**: https://explore.tempo.xyz
- **MultisendVault**: 0x6A467Cd4156093bB528e448C04366586a1052Fab

## Testing

```bash
# Test with dry run
curl -X POST http://localhost:3002/execute \
-H "Content-Type: application/json" \
-d '{
"prompt": "Test airdrop",
"payload": {
"token": "AlphaUSD",
"recipients": [
{"address": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb", "amount": "10"}
],
"dryRun": true
}
}'

# Check manifest
curl http://localhost:3002/manifest

# Health check
curl http://localhost:3002/health
```

## Author

@dagangtj

## Bounty

This agent was built for PayPol issue #4. See [BOUNTY.md](../../BOUNTY.md) for details.
Loading