Skip to content

Commit 0f70bcd

Browse files
authored
Merge branch 'main' into main
2 parents d7647a7 + 6ae1218 commit 0f70bcd

1,814 files changed

Lines changed: 88085 additions & 2489 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.env.example

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
2+
# Soroban Configuration
3+
SOROBAN_RPC_URL=https://soroban-testnet.stellar.org

.eslintignore

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
node_modules/
2+
build/
3+
dist/
4+
coverage/
5+
tests/
6+
contracts/
7+
contract/
8+
vite.config.js
9+
playwright.config.js
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
# feat: #691 #692 #693 #694 — Escrow migration, invocation logging, vesting, integration tests
2+
3+
## Summary
4+
5+
Resolves four issues in a single cohesive PR. All changes touch the escrow contract, reward-token contract, and the backend Stellar utility layer.
6+
7+
---
8+
9+
### #691 — Escrow contract migration v1 → v2 schema
10+
11+
**File:** `contracts/escrow/src/lib.rs`
12+
13+
- Added `EscrowRecord` v1 struct so the upgraded contract can deserialise legacy on-chain entries that have no `status` field.
14+
- Added `migrate(order_ids: Vec<u64>, fallback_token: Address) -> Result<u32, EscrowError>` (admin-only, idempotent):
15+
- Reads each order ID from persistent storage.
16+
- Skips entries that already deserialise as the v2 `Escrow` struct (safe to re-run).
17+
- Rewrites `EscrowRecord` entries as `Escrow` with `EscrowStatus::Active` (`released=false`) or `EscrowStatus::Released` (`released=true`), using `fallback_token` for the token address field that v1 lacked.
18+
- Extends TTL on each migrated entry and emits an `("escrow", "migrated", order_id)` event.
19+
- Returns the count of entries actually rewritten.
20+
- Fixed duplicate error discriminant clash (`InvalidToken` moved from 8 → 10, added `MigrationFailed = 11`).
21+
- Deduplicated the duplicate `use` declarations at the top of the file.
22+
23+
---
24+
25+
### #692 — Add contract invocation logging to backend
26+
27+
**File:** `backend/src/utils/stellar.js`
28+
29+
- Added `hashArgs(args)` — SHA-256 hashes the JSON-serialised call arguments (first 32 hex chars stored in the `result` column for quick lookup).
30+
- Added `logEscrowInvocation({ contractId, method, args, txHash, success, error, userId })` — inserts a row into the `contract_invocations` table (migration 013) with method name, args hash, tx hash, success flag, and error message. Non-fatal: a logging failure never breaks the escrow flow.
31+
- Wrapped `invokeEscrowContract()` to log on every outcome: success, submission error, contract failure, and confirmation timeout.
32+
- Added optional `userId` parameter to `invokeEscrowContract` for the audit trail.
33+
- Imported Node.js built-in `crypto` and `../db/schema`.
34+
35+
---
36+
37+
### #693 — RewardToken vesting schedule
38+
39+
**File:** `contract/reward-token/src/lib.rs`
40+
41+
- Added `VestingEntry { locked_amount, unlock_ledger }` struct.
42+
- Added `DataKey::Vesting(Address, u32)` (keyed by address + mint ledger sequence) and `DataKey::VestingPeriod`.
43+
- Updated `mint()` to record a `VestingEntry` when `vesting_period > 0`; `unlock_ledger = current_ledger + vesting_period`. TTL is extended to cover the full lock window plus a 10 000-ledger buffer.
44+
- Added `set_vesting_period(ledgers)` — admin-only, pass 0 to disable vesting.
45+
- Added `vesting_period()` — read-only accessor.
46+
- Added `vested_balance(id, mint_ledgers)` — returns `total_balance − Σ locked_amount` for all unexpired vesting entries.
47+
- Added `transfer_vested(from, to, amount, mint_ledgers)` — enforces the vesting lock; panics with `"transfer amount exceeds vested balance"` if `amount > vested_balance`.
48+
- Removed stale `Symbol` constants and unused `token` import.
49+
50+
---
51+
52+
### #694 — Escrow contract integration test with local Stellar node
53+
54+
**File:** `backend/src/__tests__/escrow.contracts.test.js`
55+
56+
Full rewrite of the integration test suite covering the complete deposit → release flow:
57+
58+
| Group | Tests |
59+
|---|---|
60+
| Deployment | Contract has a valid address after deploy |
61+
| `deposit` | Success; duplicate `order_id` rejected; zero amount rejected |
62+
| `get_escrow` | Returns data after deposit; returns `None` for unknown order |
63+
| `release` | Buyer releases funds (0 bps fee); double-release rejected |
64+
| Full flow | 5-step: deposit → read → release (250 bps) → double-release rejected → refund-after-release rejected |
65+
| Refund flow | Deposit with past timeout → claim refund → double-refund rejected |
66+
67+
- Helper functions `depositArgs`, `releaseArgs`, `refundArgs`, `getEscrowArgs` keep test bodies clean.
68+
- Funds buyer, farmer, and admin keypairs via local Friendbot.
69+
- All tests skip gracefully when `SKIP_CONTRACT_TESTS=true` (CI without Docker).
70+
- Suite timeout: 180 s; per-test timeout: 30 s.
71+
72+
---
73+
74+
## How to test
75+
76+
```bash
77+
# Rust unit tests
78+
cargo test --manifest-path contracts/escrow/Cargo.toml
79+
cargo test --manifest-path contract/reward-token/Cargo.toml
80+
81+
# Backend unit tests (contract tests skipped by default)
82+
cd backend && npm test
83+
84+
# Integration tests (requires local Stellar Quickstart node via Docker)
85+
docker-compose -f docker-compose.test.yml up -d
86+
cd backend && npm run test:contracts
87+
```
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
name: Backend Tests
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
8+
jobs:
9+
test:
10+
runs-on: ubuntu-latest
11+
12+
defaults:
13+
run:
14+
working-directory: backend
15+
16+
env:
17+
NODE_ENV: test
18+
PORT: 4000
19+
JWT_SECRET: ci-test-secret
20+
STELLAR_NETWORK: testnet
21+
SMTP_HOST: ""
22+
SKIP_CONTRACT_TESTS: 'true'
23+
24+
steps:
25+
- uses: actions/checkout@v4
26+
27+
- uses: actions/setup-node@v4
28+
with:
29+
node-version: 22
30+
31+
- name: Cache node_modules
32+
uses: actions/cache@v4
33+
with:
34+
path: backend/node_modules
35+
key: ${{ runner.os }}-backend-${{ hashFiles('backend/package-lock.json') }}
36+
restore-keys: ${{ runner.os }}-backend-
37+
node-version: 20
38+
39+
- name: Install dependencies
40+
run: npm install
41+
42+
- name: Run tests with coverage
43+
run: npm run test:coverage
Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
name: Browser Compatibility Tests
2+
3+
on:
4+
push:
5+
branches: [main, master]
6+
pull_request:
7+
branches: [main, master]
8+
9+
jobs:
10+
# ── Build the frontend once, then fan out to browser matrix ────────────────
11+
build:
12+
name: Build Frontend
13+
runs-on: ubuntu-latest
14+
defaults:
15+
run:
16+
working-directory: frontend
17+
steps:
18+
- uses: actions/checkout@v4
19+
20+
- uses: actions/setup-node@v4
21+
with:
22+
node-version: 22
23+
24+
- name: Cache node_modules
25+
uses: actions/cache@v4
26+
with:
27+
path: frontend/node_modules
28+
key: ${{ runner.os }}-frontend-${{ hashFiles('frontend/package-lock.json') }}
29+
restore-keys: ${{ runner.os }}-frontend-
30+
31+
- name: Install dependencies
32+
run: npm ci --legacy-peer-deps
33+
34+
- name: Build
35+
run: npm run build
36+
37+
- name: Upload build artifact
38+
uses: actions/upload-artifact@v4
39+
with:
40+
name: frontend-dist
41+
path: frontend/dist
42+
retention-days: 1
43+
44+
# ── Browser test matrix ────────────────────────────────────────────────────
45+
browser-tests:
46+
name: E2E — ${{ matrix.browser }}
47+
needs: build
48+
runs-on: ${{ matrix.os }}
49+
timeout-minutes: 20
50+
51+
strategy:
52+
fail-fast: false # run all browsers even if one fails
53+
matrix:
54+
include:
55+
# Desktop browsers
56+
- browser: chromium
57+
os: ubuntu-latest
58+
project: chromium
59+
- browser: firefox
60+
os: ubuntu-latest
61+
project: firefox
62+
- browser: webkit
63+
os: ubuntu-latest
64+
project: webkit
65+
# Mobile emulation (runs on ubuntu via Playwright device emulation)
66+
- browser: mobile-chrome-android
67+
os: ubuntu-latest
68+
project: mobile-chrome-android
69+
- browser: mobile-safari-ios
70+
os: ubuntu-latest
71+
project: mobile-safari-ios
72+
- browser: mobile-safari-ipad
73+
os: ubuntu-latest
74+
project: mobile-safari-ipad
75+
76+
defaults:
77+
run:
78+
working-directory: frontend
79+
80+
steps:
81+
- uses: actions/checkout@v4
82+
83+
- uses: actions/setup-node@v4
84+
with:
85+
node-version: 22
86+
87+
- name: Cache node_modules
88+
uses: actions/cache@v4
89+
with:
90+
path: frontend/node_modules
91+
key: ${{ runner.os }}-frontend-${{ hashFiles('frontend/package-lock.json') }}
92+
restore-keys: ${{ runner.os }}-frontend-
93+
94+
- name: Install dependencies
95+
run: npm ci --legacy-peer-deps
96+
97+
- name: Install Playwright browsers
98+
run: npx playwright install --with-deps ${{ matrix.browser == 'mobile-chrome-android' && 'chromium' || matrix.browser == 'mobile-safari-ios' && 'webkit' || matrix.browser == 'mobile-safari-ipad' && 'webkit' || matrix.browser }}
99+
100+
- name: Download build artifact
101+
uses: actions/download-artifact@v4
102+
with:
103+
name: frontend-dist
104+
path: frontend/dist
105+
106+
- name: Start preview server
107+
run: npx vite preview --port 3000 &
108+
env:
109+
VITE_API_URL: http://localhost:4000
110+
111+
- name: Wait for server
112+
run: npx wait-on http://localhost:3000 --timeout 30000
113+
114+
- name: Run Playwright tests — ${{ matrix.browser }}
115+
run: npx playwright test --project=${{ matrix.project }}
116+
env:
117+
PLAYWRIGHT_BASE_URL: http://localhost:3000
118+
CI: true
119+
120+
- name: Upload test report
121+
if: always()
122+
uses: actions/upload-artifact@v4
123+
with:
124+
name: playwright-report-${{ matrix.browser }}
125+
path: frontend/playwright-report/
126+
retention-days: 7
127+
128+
# ── Merge reports into a single summary ────────────────────────────────────
129+
report:
130+
name: Merge Browser Test Reports
131+
needs: browser-tests
132+
runs-on: ubuntu-latest
133+
if: always()
134+
steps:
135+
- uses: actions/checkout@v4
136+
137+
- uses: actions/setup-node@v4
138+
with:
139+
node-version: 22
140+
141+
- name: Download all reports
142+
uses: actions/download-artifact@v4
143+
with:
144+
pattern: playwright-report-*
145+
path: all-reports
146+
merge-multiple: true
147+
148+
- name: Merge JUnit results
149+
run: |
150+
echo "Browser test reports collected:"
151+
find all-reports -name "*.xml" | head -20

0 commit comments

Comments
 (0)