Skip to content

feat: add POST /api/contracts/deploy endpoint (#33)#70

Merged
SudiptaPaul-31 merged 1 commit into
Lumina-eX:mainfrom
patopatrish:feat/contract-deployment-api
Apr 26, 2026
Merged

feat: add POST /api/contracts/deploy endpoint (#33)#70
SudiptaPaul-31 merged 1 commit into
Lumina-eX:mainfrom
patopatrish:feat/contract-deployment-api

Conversation

@patopatrish
Copy link
Copy Markdown
Contributor

Summary

  • DB migration (scripts/006-contracts.sql): adds a contracts table with UNIQUE(job_id) to enforce one contract per job, and idempotently adds a contract_id FK column to the existing milestones table.
  • Soroban service (lib/soroban/deploy.ts): introduces deploySorobanEscrow() with a deterministic stub and a detailed TODO block mapping out the real Stellar SDK steps (WASM upload → contract install → transaction polling).
  • DB store (lib/contracts/store.ts): typed helpers — getJobById, getExistingContract, getUserById, createContract, createMilestones, linkJobToContract.
  • API route (app/api/contracts/deploy/route.ts): POST /api/contracts/deploy protected by the existing withAuth() middleware. Validates all inputs, verifies job ownership, guards against duplicate deployments, calls the Soroban service, persists the contract + milestones, and back-patches jobs.escrow_contract_id.

Error codes

Code | HTTP | Meaning -- | -- | -- INVALID_JOB_ID / INVALID_FREELANCER_ID / INVALID_TOTAL_AMOUNT | 400 | Missing or malformed fields INVALID_MILESTONES | 400 | Milestone array fails per-element validation AUTH_REQUIRED | 401 | Missing / expired access token USER_NOT_FOUND | 401 | Wallet has no platform account FORBIDDEN | 403 | Caller is not the job's client JOB_NOT_FOUND / FREELANCER_NOT_FOUND | 404 | Resource doesn't exist CONTRACT_ALREADY_EXISTS / JOB_NOT_DEPLOYABLE | 409 | Business-rule conflicts DEPLOYMENT_FAILED | 500 | Soroban deployment threw DB_ERROR | 500 | Persistence failure

Test plan

  •  Run scripts/006-contracts.sql against your Neon DB
  •  POST /api/contracts/deploy with a valid JWT, existing jobId owned by the caller, a valid freelancerId, and totalAmount — expect 201 with contractAddress and txHash
  •  Repeat the same request — expect 409 CONTRACT_ALREADY_EXISTS
  •  Send without auth header — expect 401 AUTH_REQUIRED
  •  Send with a jobId belonging to a different client — expect 403 FORBIDDEN
  •  Send missing required fields — expect 400 with the relevant code
  •  Swap deploySorobanEscrow stub for real SDK calls when Soroban integration is ready

Closes #33

- Add scripts/006-contracts.sql migration: contracts table with
  UNIQUE(job_id) guard and idempotent contract_id column on milestones
- Add lib/soroban/deploy.ts: deploySorobanEscrow stub with detailed
  TODO for real Stellar SDK WASM upload + transaction flow
- Add lib/contracts/store.ts: typed DB helpers (getJobById,
  getExistingContract, createContract, createMilestones, linkJobToContract)
- Add app/api/contracts/deploy/route.ts: protected route that validates
  input, verifies job ownership, guards duplicate contracts, calls the
  Soroban service, persists the contract + milestones, and back-patches
  jobs.escrow_contract_id

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@drips-wave
Copy link
Copy Markdown

drips-wave Bot commented Apr 25, 2026

@patopatrish Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

@SudiptaPaul-31 SudiptaPaul-31 merged commit 313acda into Lumina-eX:main Apr 26, 2026
1 check passed
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.

[Feature]: Contract Deployment API Route

2 participants