Skip to content

Conversation

@petersalomonsen
Copy link
Contributor

@petersalomonsen petersalomonsen commented Aug 18, 2025

Add Treasury 1Click API Endpoint

Overview

This PR adds a new endpoint for integrating with the 1Click API to enable treasury swap operations for Sputnik DAOs. The endpoint provides secure quote fetching for token swaps with built-in security validation.

Endpoint

  • Path: /api/treasury/oneclick-quote
  • Method: POST
  • Purpose: Fetches swap quotes from 1Click API and returns formatted proposal payloads for DAO treasury operations

Features

Core Functionality

  • Integrates with 1Click API for cross-chain token swaps
  • Supports both authenticated (with JWT) and unauthenticated requests
  • Returns formatted proposal payloads ready for DAO voting
  • Automatic 7-day deadline calculation for DAO voting period

Security Features

  • Sputnik DAO Validation: Only accepts *.sputnik-dao.near addresses for treasury operations
  • Triple validation: Checks treasuryDaoID, refundTo, and recipient addresses
  • Bearer JWT Authentication: Supports optional JWT authentication for better rates
  • Dynamic API Key Reading: API key is read per request from environment variables

Request Format

{
  "treasuryDaoID": "treasury.sputnik-dao.near",
  "inputToken": {
    "id": "wrap.near",
    "symbol": "wNEAR"
  },
  "outputToken": {
    "id": "nep141:token_address",
    "symbol": "USDC.e",
    "blockchain": "near"
  },
  "amountIn": "1000000000000000000000000",
  "slippageTolerance": "100",
  "networkOut": "near"
}

Response Format

{
  "success": true,
  "proposalPayload": {
    "tokenIn": "wrap.near",
    "tokenInSymbol": "wNEAR",
    "tokenOut": "nep141:token_address",
    "networkOut": "near",
    "amountIn": "1.0",
    "quote": {
      "amountOut": "2640966",
      "amountOutFormatted": "2.640966",
      "depositAddress": "...",
      "signature": "..."
    }
  },
  "quoteRequest": { ... }
}

Testing

Unit Tests

  • Comprehensive test coverage in test/oneclick-treasury.test.ts
  • Tests for validation, error handling, and mocked API responses
  • Validates Sputnik DAO address requirements
  • Tests authentication error scenarios

Integration Tests

  • New integration test file: test/oneclick-treasury.integration.test.ts
  • Makes real API calls to verify functionality
  • Tests include:
    • ✅ Successful quote retrieval without API key (with 0.1% fee)
    • ✅ Error handling for invalid tokens
    • ✅ Authentication error with invalid JWT tokens (401 → 500)
  • Can be skipped in CI with SKIP_INTEGRATION_TESTS=true

Running Tests

# Run all tests
npm test

# Run only unit tests
npm test -- test/oneclick-treasury.test.ts

# Run integration tests
npm test -- test/oneclick-treasury.integration.test.ts

# Skip integration tests in CI
SKIP_INTEGRATION_TESTS=true npm test

Development Environment

GitHub Codespaces / DevContainer Support

  • Added .devcontainer/devcontainer.json configuration
  • Node.js 22 development environment
  • Automatic dependency installation via postCreateCommand.sh
  • PostgreSQL database setup for local development
  • Pre-configured VS Code extensions (ESLint, Prettier, Prisma)
  • Memory optimization: NODE_OPTIONS="--max-old-space-size=4096" for tests

Environment Variables

  • ONECLICK_API_KEY: Optional JWT token for authenticated requests (better rates)
  • ONECLICK_API_URL: Override 1Click API URL (defaults to production)
  • DATABASE_URL: PostgreSQL connection string (auto-configured in devcontainer)

Error Handling

  • 400: Bad Request (invalid tokens, missing parameters)
  • 403: Forbidden (non-Sputnik DAO addresses)
  • 500: Internal Server Error (API authentication failures, unexpected errors)
  • Detailed error messages for debugging
  • Axios error handling with proper status code propagation

API Authentication

  • Without API Key: Works but includes 0.1% fee
  • With Valid JWT: Better rates, no additional fees
  • With Invalid JWT: Returns 401 from 1Click, converted to 500 with clear error message
  • Bearer token format: Authorization: Bearer <JWT_TOKEN>

Changes Summary

  • ✨ New treasury 1Click endpoint with Sputnik DAO validation
  • 🔒 Security-first design with address validation
  • 🧪 Comprehensive unit and integration tests
  • 🐳 DevContainer configuration for easy development
  • 📝 Dynamic API key reading for better testing
  • 🔧 Improved error handling for edge cases

- Create /api/treasury/oneclick-quote endpoint for secure quote generation
- Validate only sputnik-dao.near addresses can use the endpoint
- Prevent abuse by restricting refund and recipient addresses
- Pass through actual quotes from 1Click API with API key
- Return formatted proposal payload for treasury DAOs
- Add comprehensive tests for security validation
- Document implementation in docs/ONECLICK_TREASURY_API.md

This endpoint ensures secure quote generation for treasury DAOs while
preventing potential abuse of the 1Click API key.

🤖 Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
petersalomonsen and others added 3 commits August 22, 2025 18:25
- Apply consistent code formatting to oneclick-treasury.ts
- Apply consistent code formatting to test file
- No functional changes

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Configure Node.js 22 development environment
- Add postCreateCommand script for automatic setup
- Install dependencies and set up environment on container creation

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
…ved error handling

- Change from x-api-key to Bearer JWT authorization header
- Improve error handling to support both error and message fields in API responses
- Update tests with realistic mock responses matching actual 1Click API
- Add NODE_OPTIONS to devcontainer for increased memory allocation
- Format code with prettier

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
@petersalomonsen
Copy link
Contributor Author

@race-of-sloths include

@race-of-sloths
Copy link

race-of-sloths commented Aug 24, 2025

@petersalomonsen Thank you for your contribution! Your pull request is now a part of the Race of Sloths!

Shows inviting banner with latest news.

Shows profile picture for the author of the PR

Current status: executed
Reviewer Score
@Megha-Dev-19 8

Your contribution is much appreciated with a final score of 8!
You have received 150 (80 base + 45 weekly bonus + 20% lifetime bonus) Sloth points for this contribution

@Megha-Dev-19 received 25 Sloth Points for reviewing and scoring this pull request.

Another weekly streak completed, well done @petersalomonsen! To keep your weekly streak and get another bonus make pull request next week! Looking forward to see you in race-of-sloths

What is the Race of Sloths

Race of Sloths is a friendly competition where you can participate in challenges and compete with other open-source contributors within your normal workflow

For contributors:

  • Tag @race-of-sloths inside your pull requests
  • Wait for the maintainer to review and score your pull request
  • Check out your position in the Leaderboard
  • Keep weekly and monthly streaks to reach higher positions
  • Boast your contributions with a dynamic picture of your Profile

For maintainers:

  • Score pull requests that participate in the Race of Sloths and receive a reward
  • Engage contributors with fair scoring and fast responses so they keep their streaks
  • Promote the Race to the point where the Race starts promoting you
  • Grow the community of your contributors

Feel free to check our website for additional details!

Bot commands
  • For contributors
    • Include a PR: @race-of-sloths include to enter the Race with your PR
  • For maintainers:
    • Invite contributor @race-of-sloths invite to invite the contributor to participate in a race or include it, if it's already a runner.
    • Assign points: @race-of-sloths score [1/2/3/5/8/13] to award points based on your assessment.
    • Reject this PR: @race-of-sloths exclude to send this PR back to the drawing board.
    • Exclude repo: @race-of-sloths pause to stop bot activity in this repo until @race-of-sloths unpause command is called

petersalomonsen and others added 3 commits August 24, 2025 10:55
- Add separate integration test file for real API calls
- Test successful quote retrieval without API key
- Test error handling for invalid tokens
- Test authentication error with invalid JWT token
- Update API key reading to be dynamic (read from env per request)
- Improve error handling for undefined responses

Tests verify:
- API works without auth (with 0.1% fee)
- Invalid tokens return proper errors
- Invalid JWT tokens trigger 401 authentication errors

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Increase axios default timeout from 10s to 30s
- Add 30s timeout specifically for transactions-transfer-history tests
- These tests were timing out in CI after 5 seconds

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
@petersalomonsen petersalomonsen marked this pull request as ready for review August 24, 2025 12:12
@Megha-Dev-19
Copy link
Collaborator

@race-of-sloths score 8

petersalomonsen and others added 2 commits August 28, 2025 19:47
- Add axios keepAlive:false configuration to integration tests
- Replace require() with ES module imports in test files
- Fix unused variable warning with underscore prefix
- Align axios configuration with production tests

This prevents TLSWRAP open handle warnings when running tests.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
Increased axios default timeout from 30s to 60s to provide more
headroom for slower CI environments and API responses.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
@Megha-Dev-19 Megha-Dev-19 merged commit d3aec3c into NEAR-DevHub:main Sep 1, 2025
2 checks passed
petersalomonsen added a commit to NEAR-DevHub/neardevhub-treasury-dashboard that referenced this pull request Sep 1, 2025
…API (#666)

## Summary

This PR implements auto-fetching of quotes and backend integration for
the 1Click API feature, building on top of the existing 1Click swap
interface already in staging.



https://github.com/user-attachments/assets/ed96d3f7-f393-454a-ba10-ef69afb65f75



https://github.com/user-attachments/assets/b3213a6b-7f47-4e85-9281-e16267cc2db0


## What's New in This PR

### ✨ Auto-Fetch Quotes
- **Automatic quote fetching**: Quotes now fetch automatically when form
fields change (500ms debounce)
- **Removed "Get Quote" button**: No longer needed - quotes appear
automatically as users fill the form
- **Better UX**: Users see quotes immediately without extra clicks

### 🔒 Backend Security Integration
- **Custom backend endpoint**: `/api/treasury/oneclick-quote` for secure
API calls
- **Dual-path architecture**:
- Preview quotes (`dry: true`) → Direct to 1Click API (no API key
needed)
  - Actual proposals → Through our backend (API key protected)
- **DAO validation**: Backend validates that only sputnik-dao.near
addresses can create proposals
- **API key protection**: Key stored securely on backend, never exposed
to frontend

### 🐛 Bug Fixes & Improvements
- Fixed test to scroll quote display into view before screenshots
- Updated tests to expect "Create Proposal" button instead of "Get
Quote"
- Added proper timeout handling for auto-fetch debouncing
- Ensure deadline from request is included in formatted quotes

## Changes Made

### Code Changes
- Added `useEffect` hook for auto-fetching quotes with 500ms debounce
- Modified quote fetching to support both dry (preview) and real quotes
- Updated form to work without manual quote button
- Added backend endpoint integration for secure proposal creation

### Test Updates
- Updated all test references from "Get Quote" to "Create Proposal"
button
- Added `scrollIntoViewIfNeeded()` before taking screenshots
- Fixed test expectations to match auto-fetch behavior

## Testing

Run the tests:
```bash
npm test -- playwright-tests/tests/intents/oneclick-exchange-form.spec.js --project=treasury-testing
```

## Related PRs

- Backend implementation:
NEAR-DevHub/ref-sdk-api#20
- Original 1Click feature (already in staging): #628

## Deployment Requirements

1. Deploy [backend
PR](NEAR-DevHub/ref-sdk-api#20) first with
`ONECLICK_API_KEY` environment variable
2. Deploy this frontend PR
3. The auto-fetch feature gracefully falls back if backend is
unavailable

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>

---

## Latest Updates (Test Infrastructure Improvements)

### 🔧 RPC Proxy Enhancements (`playwright-tests/server/rpcproxy.js`)
- **Request Queueing**: Implemented sequential request processing to
prevent overwhelming RPC endpoints
- **Response Caching**: Added 1-second TTL cache for identical POST
bodies to reduce redundant requests
- **429 Error Handling**: Automatic blacklisting of rate-limited nodes
for 30 seconds
- **Removed Incompatible Endpoint**: Removed `near.drpc.org` which
doesn't support the "query" method

### 🐛 Route Handling Fix (`playwright-tests/util/rpcmock.js`)
- Added `await` statements to `route.fulfill()` and `route.fallback()`
calls
- Fixes "Route already handled" errors that were causing test failures

### ✅ Bulk Import Test Fixes
(`playwright-tests/tests/payments/create-bulk-import-request.spec.js`)
- Added `mockNearBalances` to mock sufficient account balance (10 NEAR)
- Prevents "Insufficient Funds" modal from blocking test execution
- All CSV validation tests now passing (comma-separated, tab-separated,
quoted fields)

### 🛠️ Development Server Fixes (`playwright-tests/server/devserver.js`)
- **Fixed startup failures**: Removed `cacheCDN` import that caused
conflicts with test hooks
- **Simplified RPC connection**: Switched from local RPC proxy to
fastnear.com mainnet RPC for improved reliability
- **Documentation**: Added comprehensive README documentation for
devserver usage and storage state configuration

### Test Results After Latest Changes
✅ All OneClick exchange form tests passing
✅ All bulk import CSV validation tests passing
✅ Payment request tests passing with improved stability
✅ Development server starts reliably without dependencies

### Impact
These changes significantly improve test reliability by:
- Preventing RPC rate limiting issues during test runs
- Ensuring proper route handling in Playwright tests
- Eliminating false test failures due to insufficient balance modals
- Reducing test flakiness from concurrent RPC requests
- Enabling reliable local development with preserved authentication
state

---------

Co-authored-by: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants