Skip to content

Commit 541429a

Browse files
committed
[agentic-payment-service/skill/bot/assistant] Updates to the main skill orchestrator. Preparing for the full EIP-3009 signed authorization (ERC-3009, transfer fungible assets via signed authorization).
1 parent 1596967 commit 541429a

1 file changed

Lines changed: 45 additions & 36 deletions

File tree

src/index.ts

Lines changed: 45 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -221,29 +221,28 @@ export async function executePayment(
221221
dryRun,
222222
};
223223
} else if (route.paymentType === "x402") {
224-
const x402Client = new X402Client();
225-
const x402Result = await executeX402ClientPayment(x402Client, intent, walletKeyAlias, tx, dryRun);
224+
const result = await executeX402ClientPayment(intent, walletKeyAlias, tx, dryRun);
226225
return {
227-
success: x402Result.success,
226+
success: result.success,
228227
tx,
229-
txHash: x402Result.txHash,
228+
txHash: result.txHash,
230229
policyResult,
231230
confirmationRequired: policyResult.requiresHumanConfirmation,
232-
error: x402Result.error,
231+
error: result.error,
233232
dryRun,
234233
};
235234
} else if (route.paymentType === "ap2") {
236-
const ap2Client = new AP2Client();
237-
const ap2Result = await executeAP2ClientPayment(ap2Client, intent, walletKeyAlias, tx, dryRun);
235+
const result = await executeAP2ClientPayment(intent, walletKeyAlias, tx, dryRun);
238236
return {
239-
success: ap2Result.success,
237+
success: result.success,
240238
tx,
241239
policyResult,
242240
confirmationRequired: policyResult.requiresHumanConfirmation,
243-
error: ap2Result.error,
241+
error: result.error,
244242
dryRun,
245243
};
246244
} else {
245+
// web2: stripe, paypal, visa, mastercard, googlepay, applepay
247246
const result = await executeWeb2Payment(route.gateway, intent);
248247
updateTransactionStatus(tx.id, "executed", {
249248
tx_hash: result.transaction_id,
@@ -335,15 +334,14 @@ async function executeWeb3Payment(
335334
// ─── x402 Client Execution Helper ───────────────────────────────────────────
336335

337336
async function executeX402ClientPayment(
338-
client: InstanceType<typeof X402Client>,
339337
intent: PaymentIntent,
340-
walletKeyAlias: string,
338+
_walletKeyAlias: string,
341339
tx: TransactionRecord,
342340
dryRun: boolean
343341
): Promise<{ success: boolean; txHash?: string; error?: string }> {
344342
const logger = getLogger();
345343

346-
// In dry-run, simulate the entire flow
344+
// Dry-run: stub the whole flow
347345
if (dryRun) {
348346
const { stubX402Settlement } = await import("./dry-run/stubs");
349347
const result = await stubX402Settlement();
@@ -359,23 +357,29 @@ async function executeX402ClientPayment(
359357
return { success: result.success, txHash: result.txHash, error: result.error };
360358
}
361359

362-
// 1. Discover payment requirements
360+
const client = new X402Client();
361+
362+
// 1. Discover payment requirements from the remote resource
363363
const details = await client.discoverPaymentRequirements(intent.recipient);
364364
if (!details) {
365-
// Resource did not require payment (not 402)
365+
// Resource didn't return 402 — no payment needed
366366
updateTransactionStatus(tx.id, "executed");
367+
logger.info("x402 client: resource accessible without payment", {
368+
resource: intent.recipient,
369+
});
367370
return { success: true };
368371
}
369372

370-
// 2. Build & sign payment (simplified — full EIP-3009 signing omitted for brevity)
371-
// In production, decode the private key and build a signed authorization
372-
logger.info("x402 client: discovered payment requirements", {
373+
logger.info("x402 client: payment required", {
373374
resource: intent.recipient,
374375
amount: details.maxAmountRequired,
375376
asset: details.asset,
377+
network: details.network,
376378
});
377379

378-
// For now, submit an unsigned placeholder — real signing requires EIP-3009 flow
380+
// 2. Build & sign the EIP-3009 authorization
381+
// (Full signing requires the wallet private key + Viem EIP-3009 flow.
382+
// Below is the structural wiring; production signing is TODO.)
379383
const payload = client.buildPaymentPayload(intent, details, "0x0", {
380384
signature: "0x0",
381385
from: "0x0",
@@ -386,14 +390,21 @@ async function executeX402ClientPayment(
386390
nonce: String(Date.now()),
387391
});
388392

389-
// 3. Submit payment
393+
// 3. Submit payment and get the resource + settlement proof
390394
const { settlement } = await client.submitPayment(intent.recipient, payload);
391395

392396
updateTransactionStatus(tx.id, settlement.success ? "executed" : "failed", {
393397
tx_hash: settlement.txHash,
394398
error_message: settlement.error,
395399
});
396400

401+
auditLog(
402+
settlement.success ? "info" : "error",
403+
"payment",
404+
"x402_client_payment_completed",
405+
{ tx_id: tx.id, txHash: settlement.txHash, resource: intent.recipient },
406+
);
407+
397408
return {
398409
success: settlement.success,
399410
txHash: settlement.txHash,
@@ -404,7 +415,6 @@ async function executeX402ClientPayment(
404415
// ─── AP2 Client Execution Helper ────────────────────────────────────────────
405416

406417
async function executeAP2ClientPayment(
407-
client: InstanceType<typeof AP2Client>,
408418
intent: PaymentIntent,
409419
_walletKeyAlias: string,
410420
tx: TransactionRecord,
@@ -413,7 +423,7 @@ async function executeAP2ClientPayment(
413423
const logger = getLogger();
414424
const config = getConfig();
415425

416-
// In dry-run, simulate the entire flow
426+
// Dry-run: stub the whole flow
417427
if (dryRun) {
418428
const { stubAP2Payment } = await import("./dry-run/stubs");
419429
const result = await stubAP2Payment(intent);
@@ -429,30 +439,28 @@ async function executeAP2ClientPayment(
429439
return { success: result.status === "success", error: result.error };
430440
}
431441

432-
// 1. Create mandate
442+
const client = new AP2Client();
443+
444+
// 1. Create mandate from the payment intent
433445
const agentId = config.protocols.ap2.server.agent_id;
434446
const mandate = client.createMandate(intent, agentId);
435447

436-
// 2. Sign mandate
448+
// 2. Sign the mandate via the credential provider
437449
const signedMandate = await client.requestMandateSignature(mandate);
438450

439-
// 3. Get payment credentials
451+
// 3. Get scoped payment credentials
440452
const paymentMethodType =
441453
(intent.metadata?.payment_method_type as string) ?? "stripe";
442454
const credentials = await client.getPaymentCredentials(
443455
signedMandate,
444-
paymentMethodType
456+
paymentMethodType,
445457
);
446458

447-
// 4. Submit payment
459+
// 4. Submit to the merchant's payment processor (or the intent's URL recipient)
448460
const merchantUrl = intent.recipient.startsWith("http")
449461
? intent.recipient
450462
: undefined;
451-
const result = await client.submitPayment(
452-
signedMandate,
453-
credentials,
454-
merchantUrl
455-
);
463+
const result = await client.submitPayment(signedMandate, credentials, merchantUrl);
456464

457465
updateTransactionStatus(tx.id, result.status === "success" ? "executed" : "failed", {
458466
tx_hash: result.transaction_id,
@@ -463,13 +471,14 @@ async function executeAP2ClientPayment(
463471
result.status === "success" ? "info" : "error",
464472
"payment",
465473
"ap2_client_payment_completed",
466-
{
467-
tx_id: tx.id,
468-
mandate_id: result.mandate_id,
469-
status: result.status,
470-
}
474+
{ tx_id: tx.id, mandate_id: result.mandate_id, status: result.status },
471475
);
472476

477+
logger.info("AP2 client: payment completed", {
478+
mandate_id: result.mandate_id,
479+
status: result.status,
480+
});
481+
473482
return { success: result.status === "success", error: result.error };
474483
}
475484

0 commit comments

Comments
 (0)