-
Notifications
You must be signed in to change notification settings - Fork 41
X402 Credit Spend with Echo Balance #614
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| -- CreateTable | ||
| CREATE TABLE "x402_transaction_metadata" ( | ||
| "id" UUID NOT NULL, | ||
| "resourcePath" TEXT NOT NULL, | ||
| "resourceArgs" JSONB NOT NULL, | ||
| "resourceResponse" JSONB NOT NULL, | ||
| "resourceError" JSONB NOT NULL, | ||
| "createdAt" TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP, | ||
| "updatedAt" TIMESTAMPTZ NOT NULL, | ||
|
|
||
| CONSTRAINT "x402_transaction_metadata_pkey" PRIMARY KEY ("id") | ||
| ); | ||
|
|
||
| -- AddForeignKey | ||
| ALTER TABLE "transactions" ADD CONSTRAINT "transactions_id_fkey" FOREIGN KEY ("id") REFERENCES "x402_transaction_metadata"("id") ON DELETE CASCADE ON UPDATE CASCADE; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| -- DropForeignKey | ||
| ALTER TABLE "public"."transactions" DROP CONSTRAINT "transactions_id_fkey"; | ||
|
|
||
| -- AlterTable | ||
| ALTER TABLE "transactions" ADD COLUMN "x402TransactionMetadataId" UUID; | ||
|
|
||
| -- AlterTable | ||
| ALTER TABLE "x402_transaction_metadata" ALTER COLUMN "resourceArgs" SET DEFAULT '{}', | ||
| ALTER COLUMN "resourceResponse" SET DEFAULT '{}', | ||
| ALTER COLUMN "resourceError" SET DEFAULT '{}'; | ||
|
|
||
| -- AddForeignKey | ||
| ALTER TABLE "transactions" ADD CONSTRAINT "transactions_x402TransactionMetadataId_fkey" FOREIGN KEY ("x402TransactionMetadataId") REFERENCES "x402_transaction_metadata"("id") ON DELETE CASCADE ON UPDATE CASCADE; |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,79 @@ | ||||||||||||||||||||||||||||||||||||||
| import dotenv from 'dotenv'; | ||||||||||||||||||||||||||||||||||||||
| dotenv.config(); | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| const TRUECAST_URL = 'https://true-cast-agent.vercel.app/api/trueCast'; | ||||||||||||||||||||||||||||||||||||||
| const GLORIA_URL = 'https://api.itsgloria.ai/news'; | ||||||||||||||||||||||||||||||||||||||
| const ECHO_ROUTER_BASE_URL = | ||||||||||||||||||||||||||||||||||||||
| process.env.ECHO_ROUTER_BASE_URL || 'http://localhost:3070'; | ||||||||||||||||||||||||||||||||||||||
| const ECHO_API_KEY = process.env.ECHO_API_KEY; | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| interface TrueCastRequest { | ||||||||||||||||||||||||||||||||||||||
| prompt: string; | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
| interface GloriaNewsParams { | ||||||||||||||||||||||||||||||||||||||
| feed_categories?: string; | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
| export async function postTrueCastRequest( | ||||||||||||||||||||||||||||||||||||||
| prompt: string, | ||||||||||||||||||||||||||||||||||||||
| apiKey?: string | ||||||||||||||||||||||||||||||||||||||
| ): Promise<string> { | ||||||||||||||||||||||||||||||||||||||
| const key = apiKey || ECHO_API_KEY; | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| if (!key) { | ||||||||||||||||||||||||||||||||||||||
| throw new Error('ECHO_API_KEY is required'); | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| const trueCastBody: TrueCastRequest = { prompt }; | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| const response = await fetch( | ||||||||||||||||||||||||||||||||||||||
| `${ECHO_ROUTER_BASE_URL}/x402?proxy=${encodeURIComponent(TRUECAST_URL)}`, | ||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||
| method: 'POST', | ||||||||||||||||||||||||||||||||||||||
| headers: { | ||||||||||||||||||||||||||||||||||||||
| 'Content-Type': 'application/json', | ||||||||||||||||||||||||||||||||||||||
| Authorization: `Bearer ${key}`, | ||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||
| body: JSON.stringify(trueCastBody), | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||
| console.log('response', response.status); | ||||||||||||||||||||||||||||||||||||||
| const data = await response.json(); | ||||||||||||||||||||||||||||||||||||||
| console.log('data', data); | ||||||||||||||||||||||||||||||||||||||
| return data; | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| export async function getGloriaNews( | ||||||||||||||||||||||||||||||||||||||
| params: GloriaNewsParams = { feed_categories: 'base' }, | ||||||||||||||||||||||||||||||||||||||
| apiKey?: string | ||||||||||||||||||||||||||||||||||||||
| ): Promise<string> { | ||||||||||||||||||||||||||||||||||||||
| const key = apiKey || ECHO_API_KEY; | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| if (!key) { | ||||||||||||||||||||||||||||||||||||||
| throw new Error('ECHO_API_KEY is required'); | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| const queryParams = new URLSearchParams( | ||||||||||||||||||||||||||||||||||||||
| params as Record<string, string> | ||||||||||||||||||||||||||||||||||||||
| ).toString(); | ||||||||||||||||||||||||||||||||||||||
| const gloriaUrlWithParams = `${GLORIA_URL}?${queryParams}`; | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| const response = await fetch( | ||||||||||||||||||||||||||||||||||||||
| `${ECHO_ROUTER_BASE_URL}/x402?proxy=${encodeURIComponent(gloriaUrlWithParams)}`, | ||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||
| method: 'GET', | ||||||||||||||||||||||||||||||||||||||
| headers: { | ||||||||||||||||||||||||||||||||||||||
| Authorization: `Bearer ${key}`, | ||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| console.log('response', response.status); | ||||||||||||||||||||||||||||||||||||||
| const data = await response.json(); | ||||||||||||||||||||||||||||||||||||||
| console.log('data', data); | ||||||||||||||||||||||||||||||||||||||
| return data; | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
| getGloriaNews({ feed_categories: 'base' }, ECHO_API_KEY); | ||||||||||||||||||||||||||||||||||||||
| postTrueCastRequest( | ||||||||||||||||||||||||||||||||||||||
| 'Was donald trump the first president of the united states?', | ||||||||||||||||||||||||||||||||||||||
| ECHO_API_KEY | ||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+75
to
+79
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
The module-level code at the end of the file executes async functions without awaiting them, which will cause unhandled promise rejections if these functions fail and cannot be debugged properly. View DetailsAnalysisUnhandled promise rejections in echo-credit-client.ts module-level codeWhat fails: Module-level async function calls getGloriaNews() and postTrueCastRequest() at lines 75-79 in packages/app/server/src/clients/echo-credit-client.ts cause unhandled promise rejections when ECHO_API_KEY environment variable is missing How to reproduce: # Import module without ECHO_API_KEY set:
cd packages/app/server && pnpm exec tsx -e "import('./src/clients/echo-credit-client.ts')"Result: Process crashes with "UNHANDLED PROMISE REJECTION DETECTED: Error: ECHO_API_KEY is required" - both functions throw but have no .catch() handlers Expected: Errors should be caught and handled gracefully like all other client files in the same directory, which use .then().catch() patterns for module-level async calls |
||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The
postTrueCastRequestfunction is declared to returnPromise<string>but actually returns the parsed JSON response object, not a string. The same issue exists ingetGloriaNewson line 45.View Details
📝 Patch Details
Analysis
Type mismatch in postTrueCastRequest() and getGloriaNews() return types
What fails: Functions
postTrueCastRequest()andgetGloriaNews()inpackages/app/server/src/clients/echo-credit-client.tsdeclare return typePromise<string>but actually returnPromise<any>(parsed JSON objects)How to reproduce:
Result: TypeScript type checker allows incorrect type assumptions. Calling code expecting strings would receive objects at runtime.
Expected: Return type should be
Promise<any>to match actual behavior per TypeScript fetch documentation -response.json()returnsPromise<any>