@dexterai/x402 1.9.0 → 1.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -580,20 +580,113 @@ tiktoken's default encoding works well for most transformer models. Only use a c
580
580
 
581
581
  ---
582
582
 
583
- ## Sponsored Access (v1.7.2)
583
+ ## Sponsored Access (Ads for Agents)
584
584
 
585
- **Server middleware** accepts `sponsoredAccess: true` in its config. When enabled, it reads `extensions["sponsored-access"]` from the facilitator's settlement response and injects `_x402_sponsored` into the JSON response body so agents can see recommendations.
585
+ Sponsored Access delivers targeted resource recommendations through x402 payments. When an agent pays for an API, the facilitator can inject a recommendation for a related tool in the settlement receipt. The agent sees the recommendation and can call it immediately -- the subsequent call is tracked as a conversion with both blockchain transaction hashes as proof.
586
+
587
+ ### Server — Enable Recommendation Injection
588
+
589
+ Add `sponsoredAccess: true` to your middleware config. This reads `extensions["sponsored-access"]` from the facilitator's settlement response and injects `_x402_sponsored` into the JSON response body so the agent's LLM can see the recommendations (headers are invisible to LLMs).
586
590
 
587
591
  ```typescript
588
- app.use(x402Middleware({
589
- facilitatorUrl: "https://x402.dexter.cash",
590
- sponsoredAccess: true, // opt-in to recommendation injection
591
- }));
592
+ import { x402Middleware } from '@dexterai/x402/server';
593
+
594
+ // Default injection: adds _x402_sponsored field to JSON response
595
+ app.get('/api/data',
596
+ x402Middleware({
597
+ payTo: '...', amount: '0.01',
598
+ sponsoredAccess: true,
599
+ }),
600
+ (req, res) => res.json({ data: 'content' })
601
+ );
602
+ // Agent receives: { _x402_sponsored: [{ resourceUrl, description, sponsor }], data: 'content' }
603
+
604
+ // Custom injection: control where recommendations appear
605
+ app.get('/api/data',
606
+ x402Middleware({
607
+ payTo: '...', amount: '0.01',
608
+ sponsoredAccess: {
609
+ inject: (body, recs) => ({ ...body, related_tools: recs }),
610
+ onMatch: (recs, settlement) => {
611
+ console.log(`Matched ${recs.length} recommendations for tx ${settlement.transaction}`);
612
+ },
613
+ },
614
+ }),
615
+ (req, res) => res.json({ data: 'content' })
616
+ );
617
+ ```
618
+
619
+ ### Client — Read Recommendations
620
+
621
+ ```typescript
622
+ import {
623
+ wrapFetch,
624
+ getSponsoredRecommendations,
625
+ fireImpressionBeacon,
626
+ } from '@dexterai/x402/client';
627
+
628
+ const x402Fetch = wrapFetch(fetch, { walletPrivateKey: key });
629
+ const response = await x402Fetch('https://api.example.com/data');
630
+
631
+ // Extract typed recommendations from the payment receipt
632
+ const recs = getSponsoredRecommendations(response);
633
+ if (recs) {
634
+ for (const rec of recs) {
635
+ console.log(`${rec.sponsor}: ${rec.description} -- ${rec.resourceUrl}`);
636
+ }
637
+ // Confirm delivery to the ad network
638
+ await fireImpressionBeacon(response);
639
+ }
640
+ ```
641
+
642
+ ### React — Recommendations in Hooks
643
+
644
+ ```tsx
645
+ import { useX402Payment } from '@dexterai/x402/react';
646
+
647
+ function PayButton() {
648
+ const {
649
+ fetch,
650
+ isLoading,
651
+ sponsoredRecommendations, // auto-populated after payment
652
+ } = useX402Payment({ wallets });
653
+
654
+ return (
655
+ <div>
656
+ <button onClick={() => fetch(url)} disabled={isLoading}>Pay</button>
657
+ {sponsoredRecommendations?.map((rec, i) => (
658
+ <a key={i} href={rec.resourceUrl}>{rec.sponsor}: {rec.description}</a>
659
+ ))}
660
+ </div>
661
+ );
662
+ }
663
+ ```
664
+
665
+ ### Types
666
+
667
+ All types are re-exported from `@dexterai/x402-ads-types`:
668
+
669
+ ```typescript
670
+ import type { SponsoredRecommendation, SponsoredAccessSettlementInfo } from '@dexterai/x402/client';
671
+
672
+ interface SponsoredRecommendation {
673
+ resourceUrl: string; // The URL to call
674
+ description: string; // Agent-readable description
675
+ sponsor: string; // Brand name
676
+ bazaarId?: string; // Bazaar catalog ID
677
+ price?: string; // Cost in atomic units
678
+ currency?: string; // e.g., "USDC"
679
+ }
592
680
  ```
593
681
 
594
- **Client SDK** decodes the `PAYMENT-RESPONSE` header from x402 responses and attaches the full settlement receipt (including extensions) as `response._x402` for programmatic access.
682
+ ### How It Works
595
683
 
596
- **Types:** `SettleResponse` now includes an optional `extensions` field.
684
+ 1. Agent pays for an API via x402
685
+ 2. Facilitator settles payment and calls the ad network's match API
686
+ 3. If a campaign matches (by URL pattern, category, network), a recommendation is injected into `SettlementResponse.extensions["sponsored-access"]`
687
+ 4. Publisher middleware (with `sponsoredAccess: true`) injects it into the JSON response body
688
+ 5. Agent's LLM sees the recommendation and can call the suggested resource
689
+ 6. If the agent calls it, the facilitator records a conversion with both tx hashes as proof
597
690
 
598
691
  ---
599
692
 
@@ -195,7 +195,10 @@ __export(client_exports, {
195
195
  createKeypairWallet: () => createKeypairWallet,
196
196
  createSolanaAdapter: () => createSolanaAdapter,
197
197
  createX402Client: () => createX402Client,
198
+ fireImpressionBeacon: () => fireImpressionBeacon,
198
199
  getPaymentReceipt: () => getPaymentReceipt,
200
+ getSponsoredAccessInfo: () => getSponsoredAccessInfo,
201
+ getSponsoredRecommendations: () => getSponsoredRecommendations,
199
202
  isEvmKeypairWallet: () => isEvmKeypairWallet,
200
203
  isKeypairWallet: () => isKeypairWallet,
201
204
  wrapFetch: () => wrapFetch
@@ -1151,6 +1154,28 @@ function wrapFetch(fetchImpl, options) {
1151
1154
  }
1152
1155
  return clientFetch;
1153
1156
  }
1157
+
1158
+ // src/client/sponsored-access.ts
1159
+ function getSponsoredAccessInfo(response) {
1160
+ const receipt = getPaymentReceipt(response);
1161
+ if (!receipt?.extensions?.["sponsored-access"]) return void 0;
1162
+ return receipt.extensions["sponsored-access"];
1163
+ }
1164
+ function getSponsoredRecommendations(response) {
1165
+ const info = getSponsoredAccessInfo(response);
1166
+ if (!info?.recommendations?.length) return void 0;
1167
+ return info.recommendations;
1168
+ }
1169
+ async function fireImpressionBeacon(response) {
1170
+ const info = getSponsoredAccessInfo(response);
1171
+ const beaconUrl = info?.tracking?.impressionBeacon;
1172
+ if (!beaconUrl) return false;
1173
+ try {
1174
+ await fetch(beaconUrl, { method: "GET" });
1175
+ } catch {
1176
+ }
1177
+ return true;
1178
+ }
1154
1179
  // Annotate the CommonJS export names for ESM import in node:
1155
1180
  0 && (module.exports = {
1156
1181
  BASE_MAINNET,
@@ -1163,7 +1188,10 @@ function wrapFetch(fetchImpl, options) {
1163
1188
  createKeypairWallet,
1164
1189
  createSolanaAdapter,
1165
1190
  createX402Client,
1191
+ fireImpressionBeacon,
1166
1192
  getPaymentReceipt,
1193
+ getSponsoredAccessInfo,
1194
+ getSponsoredRecommendations,
1167
1195
  isEvmKeypairWallet,
1168
1196
  isKeypairWallet,
1169
1197
  wrapFetch