Skip to content
Merged
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
29 changes: 18 additions & 11 deletions .agent/skills/api-akomo/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,26 +1,28 @@
---
name: api-akomo-docs
description: provides detailed technical documentation and interaction guidelines for the akomo backend api (api.akomo.jodaz.xyz).
description: provides detailed technical documentation and interaction guidelines for the akomo backend api (api.akomo.xyz).
---
# AKomo API Documentation Skill

## When to use this skill
- when a user or another agent needs to interact with the AKomo backend API.
- when exploring the available endpoints for exchange rates and mobile app builds.
- when planning a new application that consumes data from `api.akomo.jodaz.xyz`.
- when planning a new application that consumes data from `api.akomo.xyz`.
- when debugging issues related to fetching BCV, Binance rates, or app builds from the AKomo server.

## Overview
The AKomo API serves as the centralized backend for the AKomo mobile application (market tracking / currency exchange). The root domain is `https://api.akomo.jodaz.xyz/api`. It mainly handles:
The AKomo API serves as the centralized backend for the AKomo mobile application (market tracking / currency exchange). The root domain is `https://api.akomo.xyz/api`. It mainly handles:
1. **Exchange Rates**: Syncing and providing latest currency rates (USD, EUR, USDT) from sources like BCV and Binance P2P.
2. **Builds**: Managing the download URLs and versions of the mobile application across platforms.

Interactive documentation is available via Swagger at: `https://api.akomo.xyz/api/docs`

## Necessary Inputs
None. This skill provides documentation. If making requests, the HTTP client must respect the base URL and standard headers (e.g., `Content-Type: application/json` for POST requests). Standard REST conventions apply. Authentication/Authorization is not explicitly required for standard `GET` requests for rates and builds (they are public), but internal `POST` routes may be protected in deployment (if enforced at a higher level).
None. This skill provides documentation. If making requests, the HTTP client must respect the base URL and standard headers (e.g., `Content-Type: application/json` for POST requests). Standard REST conventions apply. Authentication/Authorization currently relies on environment secrets for protected operations (e.g., Supabase service role), but public `GET` endpoints are open.

## Workflow
1. **Identify the Data Required**: Determine if you need current rates, manual rates update, a specific Binance average, or mobile build information.
2. **Choose the Corresponding Endpoint**: Reference the "Endpoints" section to find the exact path and method.
1. **Identify the Data Required**: Determine if you need current rates, historical data, manual rates update, a specific Binance average, or mobile build information.
2. **Choose the Corresponding Endpoint**: Reference the "Endpoints" section or the Swagger UI to find the exact path and method.
3. **Construct the Request**: Include the proper Query Parameters or JSON Body as defined.
4. **Parse the Response**: Ensure your application can parse the specific output formats provided by the API.

Expand All @@ -47,6 +49,12 @@ Returns the most recently recorded exchange rates for tracked currencies (USD, E
```
*(Note: The `value` is returned as a comma-separated string `36,25` for UI rendering).*

#### `GET /api/exchange-rates/history`
Returns historical exchange rates for the last N days.
- **Query Parameters:**
- `days` (optional, default: `7`): Number of days of history to fetch.
- **Output (JSON):** Returns an array of objects containing symbol, current price, percentage change, and history points.

#### `POST /api/exchange-rates/bcv`
Manually updates the historical BCV record for USD and EUR.
- **Body:**
Expand Down Expand Up @@ -77,13 +85,13 @@ Calculates and returns the average Binance P2P price for a specific asset/fiat p
}
```

*(Note: Standard CRUD routes like `POST /`, `GET /:id`, `PATCH /:id`, and `DELETE /:id` exist under `/api/exchange-rates` but are currently stubbed implementations).*
*(Note: Standard CRUD routes like `POST /`, `GET /:id`, `PATCH /:id`, and `DELETE /:id` exist but are mostly for internal use or administrative manual updates).*

### 2. Builds
Manages the mobile application build references (links to APKs/IPAs).

#### `GET /api/builds`
Returns a list of available app builds, ordered by creation date (newest first).
Returns a list of available app builds.
- **Output (JSON):**
```json
[
Expand All @@ -105,7 +113,6 @@ Registers a newly compiled mobile application build.
"platform": "ios"
}
```
- **Output:** Returns the created database record (JSON).

## Error Handling
If requests fail, standard NestJS HTTP exceptions will be returned in this generic format:
Expand All @@ -116,7 +123,7 @@ If requests fail, standard NestJS HTTP exceptions will be returned in this gener
"error": "Bad Request"
}
```
Validation errors for POST bodies return an array of user-friendly validation messages under the `message` property due to the NestJS global ValidationPipe.
Validation errors for POST bodies return an array of user-friendly validation messages under the `message` property.

## Output Structure when Queried
When another agent queries this skill to understand the API, you must serve these exact endpoint definitions, keeping the expected inputs (Query/Body) and outputs (Responses) explicitly clear.
When another agent queries this skill to understand the API, you must serve these exact endpoint definitions, keeping the expected inputs (Query/Body) and outputs (Responses) explicitly clear. Also point them to the Swagger UI for real-time exploratory testing.
75 changes: 71 additions & 4 deletions mobile/app/(tabs)/history.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,26 @@ import {
} from 'react-native';
import { Text } from '@/components/Themed';
import { useExchangeHistory } from '@/hooks/use-exchange-history';
import { HistoryChart } from '@/components/HistoryChart';
// import { HistoryChart } from '@/components/HistoryChart';
import { GradientBackground } from '@/components/GradientBackground';
import { TopHeader } from '@/components/TopHeader';
import { CreditsFooter } from '@/components/CreditsFooter';
import { ArrowUpRight, ArrowDownRight } from 'lucide-react-native';
import { ArrowUpRight, ArrowDownRight, TrendingUp } from 'lucide-react-native';

export default function HistoryScreen() {
const [days, setDays] = useState(7);
const { data, isLoading } = useExchangeHistory(days);
const { width } = useWindowDimensions();
const isDesktop = Platform.OS === 'web' && width > 768;

// Calculate gaps between USDT and BCV rates
const usdtPrice = data?.find(i => i.symbol.toUpperCase().includes('USDT'))?.currentPrice;
const usdPrice = data?.find(i => i.symbol === 'USD')?.currentPrice;
const eurPrice = data?.find(i => i.symbol === 'EUR')?.currentPrice;

const usdGap = (usdtPrice && usdPrice) ? ((usdtPrice / usdPrice) - 1) * 100 : 0;
const eurGap = (usdtPrice && eurPrice) ? ((usdtPrice / eurPrice) - 1) * 100 : 0;

const renderTab = (value: number, label: string) => {
const isActive = days === value;
return (
Expand Down Expand Up @@ -97,12 +105,36 @@ export default function HistoryScreen() {
{data?.map((item) => renderRateCard(item.symbol, item.currentPrice, item.change))}
</View>

{/* Chart section — card rules: borderRadius 20, padding 24, border */}
{/* Gap Section — Breach Analysis */}
<View style={styles.gapSection}>
<View style={styles.gapHeader}>
<TrendingUp size={18} color="#F1C40F" />
<Text style={styles.gapTitle}>Brecha Cambiaria</Text>
</View>

<View style={styles.gapRow}>
<Text style={styles.gapLabel}>USDT / USD BCV</Text>
<Text style={[styles.gapValue, { color: usdGap >= 0 ? '#F1C40F' : '#14b8a6' }]}>
{usdGap >= 0 ? '+' : ''}{usdGap.toFixed(2)}%
</Text>
</View>

<View style={[styles.gapRow, { borderTopWidth: 1, borderTopColor: 'rgba(68, 138, 68, 0.3)', marginTop: 8, paddingTop: 12 }]}>
<Text style={styles.gapLabel}>USDT / EUR BCV</Text>
<Text style={[styles.gapValue, { color: eurGap >= 0 ? '#F1C40F' : '#14b8a6' }]}>
{eurGap >= 0 ? '+' : ''}{eurGap.toFixed(2)}%
</Text>
</View>
</View>

{/* Chart section hidden per user request */}
{/*
<View style={styles.chartSection}>
<Text style={styles.chartTitle}>Evolución últimos {days} días</Text>
{data && <HistoryChart data={data} days={days} />}
<Text style={styles.dataDaysLabel}>{days} días de datos</Text>
</View>
*/}
</View>

<View style={styles.footer}>
Expand Down Expand Up @@ -214,7 +246,7 @@ const styles = StyleSheet.create({
rateChangeNegative: {
color: '#14b8a6', // teal-accent for negative change
},
// Chart card: borderRadius 20, padding 24, border per guidelines
/*
chartSection: {
backgroundColor: '#1B6B3E',
borderRadius: 20,
Expand All @@ -235,6 +267,41 @@ const styles = StyleSheet.create({
fontSize: 12,
opacity: 0.8,
},
*/
gapSection: {
backgroundColor: '#155230', // dark green for breach analysis
borderRadius: 20,
padding: 20,
marginBottom: 20,
borderWidth: 1,
borderColor: '#448A44',
},
gapHeader: {
flexDirection: 'row',
alignItems: 'center',
gap: 8,
marginBottom: 16,
},
gapTitle: {
color: '#F1C40F',
fontSize: 16,
fontWeight: 'bold',
fontFamily: 'Zain_700Bold',
},
gapRow: {
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
},
gapLabel: {
color: '#FFFFFF',
fontSize: 14,
opacity: 0.8,
},
gapValue: {
fontSize: 20,
fontWeight: 'bold',
},
footer: {
alignItems: 'center',
marginTop: 40,
Expand Down
2 changes: 2 additions & 0 deletions mobile/app/_layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ function RootLayoutNav() {
case '/info': return 'Información';
case '/builds': return 'Descargas';
case '/history': return 'Historial';
case '/calculator': return 'Calculadora';
case '/modal': return 'Detalles';
case '/privacy-policy': return 'Privacidad';
default: return 'Tasas';
Expand Down Expand Up @@ -105,6 +106,7 @@ function RootLayoutNav() {
<Stack.Screen name="builds" options={{ headerShown: false }} />
<Stack.Screen name="privacy-policy" options={{ headerShown: false }} />
<Stack.Screen name="(tabs)/history" options={{ headerShown: false }} />
<Stack.Screen name="calculator" options={{ headerShown: false }} />
<Stack.Screen name="modal" options={{ presentation: 'modal' }} />
</Stack>
</GradientBackground>
Expand Down
Loading