@elizaos/plugin-wallet 2.0.0-beta.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.
Files changed (200) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +64 -0
  3. package/auto-enable.ts +76 -0
  4. package/dist/LpManagementService-BWrQ5-cO.mjs +353 -0
  5. package/dist/MockLpService-D_Apn4Fd.mjs +99 -0
  6. package/dist/aerodrome-CfnESC32.mjs +890 -0
  7. package/dist/chunk-hT5z_Zn9.mjs +35 -0
  8. package/dist/index.d.mts +34727 -0
  9. package/dist/index.mjs +21590 -0
  10. package/dist/lib/server-wallet-trade.d.mts +34 -0
  11. package/dist/lib/server-wallet-trade.mjs +306 -0
  12. package/dist/meteora-BPX39hZo.mjs +22640 -0
  13. package/dist/orca-Bybp1HXO.mjs +249 -0
  14. package/dist/pancakeswp-CkEXlXti.mjs +604 -0
  15. package/dist/plugin-ZO_MTyd0.mjs +529 -0
  16. package/dist/raydium-rfaM9yEf.mjs +539 -0
  17. package/dist/sdk/index.d.mts +32492 -0
  18. package/dist/sdk/index.mjs +6415 -0
  19. package/dist/types-D5252NZk.mjs +487 -0
  20. package/dist/uniswap-CReXgXVN.mjs +573 -0
  21. package/dist/wallet-action.d.mts +6 -0
  22. package/dist/wallet-action.mjs +820 -0
  23. package/package.json +152 -0
  24. package/src/actions/failure-codes.ts +79 -0
  25. package/src/actions/index.ts +1 -0
  26. package/src/analytics/birdeye/actions/wallet-search-address.ts +9 -0
  27. package/src/analytics/birdeye/birdeye-task.ts +175 -0
  28. package/src/analytics/birdeye/birdeye.ts +813 -0
  29. package/src/analytics/birdeye/constants.ts +74 -0
  30. package/src/analytics/birdeye/providers/agent-portfolio-provider.ts +18 -0
  31. package/src/analytics/birdeye/providers/market.ts +227 -0
  32. package/src/analytics/birdeye/providers/portfolio-factory.test.ts +138 -0
  33. package/src/analytics/birdeye/providers/portfolio-factory.ts +252 -0
  34. package/src/analytics/birdeye/providers/trending.ts +365 -0
  35. package/src/analytics/birdeye/providers/wallet.ts +14 -0
  36. package/src/analytics/birdeye/search-category.test.ts +207 -0
  37. package/src/analytics/birdeye/search-category.ts +506 -0
  38. package/src/analytics/birdeye/service.ts +992 -0
  39. package/src/analytics/birdeye/tasks/birdeye.ts +232 -0
  40. package/src/analytics/birdeye/types/api/common.ts +305 -0
  41. package/src/analytics/birdeye/types/api/defi.ts +220 -0
  42. package/src/analytics/birdeye/types/api/pair.ts +200 -0
  43. package/src/analytics/birdeye/types/api/search.ts +86 -0
  44. package/src/analytics/birdeye/types/api/token.ts +635 -0
  45. package/src/analytics/birdeye/types/api/trader.ts +76 -0
  46. package/src/analytics/birdeye/types/api/wallet.ts +181 -0
  47. package/src/analytics/birdeye/types/shared.ts +106 -0
  48. package/src/analytics/birdeye/utils.ts +700 -0
  49. package/src/analytics/dexscreener/errors.ts +28 -0
  50. package/src/analytics/dexscreener/index.ts +3 -0
  51. package/src/analytics/dexscreener/search-category.test.ts +49 -0
  52. package/src/analytics/dexscreener/search-category.ts +42 -0
  53. package/src/analytics/dexscreener/service.ts +595 -0
  54. package/src/analytics/dexscreener/types.ts +128 -0
  55. package/src/analytics/lpinfo/index.d.ts +7 -0
  56. package/src/analytics/lpinfo/index.ts +52 -0
  57. package/src/analytics/lpinfo/kamino/README.md +102 -0
  58. package/src/analytics/lpinfo/kamino/index.ts +24 -0
  59. package/src/analytics/lpinfo/kamino/providers/kaminoLiquidityProvider.ts +422 -0
  60. package/src/analytics/lpinfo/kamino/providers/kaminoPoolProvider.ts +365 -0
  61. package/src/analytics/lpinfo/kamino/providers/kaminoProvider.ts +496 -0
  62. package/src/analytics/lpinfo/kamino/services/kaminoLiquidityService.ts +1123 -0
  63. package/src/analytics/lpinfo/kamino/services/kaminoService.ts +758 -0
  64. package/src/analytics/lpinfo/steer/README.md +169 -0
  65. package/src/analytics/lpinfo/steer/index.ts +23 -0
  66. package/src/analytics/lpinfo/steer/providers/steerLiquidityProvider.ts +544 -0
  67. package/src/analytics/lpinfo/steer/services/steerLiquidityService.ts +1690 -0
  68. package/src/analytics/lpinfo/steer/steer-display-types.ts +99 -0
  69. package/src/analytics/news/index.ts +52 -0
  70. package/src/analytics/news/interfaces/types.ts +222 -0
  71. package/src/analytics/news/providers/defiNewsProvider.ts +734 -0
  72. package/src/analytics/news/services/newsDataService.ts +332 -0
  73. package/src/analytics/news/utils/formatters.ts +151 -0
  74. package/src/analytics/token-info/action.ts +240 -0
  75. package/src/analytics/token-info/index.ts +3 -0
  76. package/src/analytics/token-info/params.ts +215 -0
  77. package/src/analytics/token-info/providers.ts +681 -0
  78. package/src/analytics/token-info/service.ts +168 -0
  79. package/src/analytics/token-info/types.ts +74 -0
  80. package/src/audit/audit-log.ts +45 -0
  81. package/src/browser-shim/build-shim.ts +123 -0
  82. package/src/browser-shim/index.ts +5 -0
  83. package/src/browser-shim/shim.template.js +563 -0
  84. package/src/chains/evm/.github/workflows/npm-deploy.yml +112 -0
  85. package/src/chains/evm/LICENSE +21 -0
  86. package/src/chains/evm/README.md +106 -0
  87. package/src/chains/evm/actions/helpers.ts +147 -0
  88. package/src/chains/evm/actions/swap.ts +839 -0
  89. package/src/chains/evm/actions/transfer.ts +254 -0
  90. package/src/chains/evm/biome.json +61 -0
  91. package/src/chains/evm/bridge-router.ts +660 -0
  92. package/src/chains/evm/build.ts +89 -0
  93. package/src/chains/evm/chain-handler.ts +416 -0
  94. package/src/chains/evm/constants.ts +23 -0
  95. package/src/chains/evm/contracts/artifacts/OZGovernor.json +1707 -0
  96. package/src/chains/evm/contracts/artifacts/TimelockController.json +1007 -0
  97. package/src/chains/evm/contracts/artifacts/VoteToken.json +895 -0
  98. package/src/chains/evm/dex/aerodrome/index.ts +34 -0
  99. package/src/chains/evm/dex/aerodrome/services/AerodromeLpService.ts +558 -0
  100. package/src/chains/evm/dex/aerodrome/types.ts +318 -0
  101. package/src/chains/evm/dex/pancakeswp/index.ts +35 -0
  102. package/src/chains/evm/dex/pancakeswp/services/PancakeSwapV3LpService.ts +743 -0
  103. package/src/chains/evm/dex/pancakeswp/types.ts +65 -0
  104. package/src/chains/evm/dex/uniswap/index.ts +35 -0
  105. package/src/chains/evm/dex/uniswap/services/UniswapV3LpService.ts +759 -0
  106. package/src/chains/evm/dex/uniswap/types.ts +390 -0
  107. package/src/chains/evm/generated/specs/spec-helpers.ts +73 -0
  108. package/src/chains/evm/generated/specs/specs.ts +151 -0
  109. package/src/chains/evm/gov-router.ts +250 -0
  110. package/src/chains/evm/index.browser.ts +16 -0
  111. package/src/chains/evm/index.ts +31 -0
  112. package/src/chains/evm/prompts.ts +193 -0
  113. package/src/chains/evm/providers/get-balance.ts +123 -0
  114. package/src/chains/evm/providers/wallet.ts +715 -0
  115. package/src/chains/evm/routes/sign.ts +333 -0
  116. package/src/chains/evm/rpc-providers.ts +410 -0
  117. package/src/chains/evm/service.ts +140 -0
  118. package/src/chains/evm/templates/index.ts +10 -0
  119. package/src/chains/evm/types/index.ts +432 -0
  120. package/src/chains/evm/vitest.config.ts +18 -0
  121. package/src/chains/registry.ts +668 -0
  122. package/src/chains/solana/README.md +367 -0
  123. package/src/chains/wallet-action.ts +533 -0
  124. package/src/chains/wallet-router.test.ts +296 -0
  125. package/src/contracts.ts +65 -0
  126. package/src/core-augmentation.ts +10 -0
  127. package/src/index.ts +71 -0
  128. package/src/lib/server-wallet-trade.ts +192 -0
  129. package/src/lib/wallet-export-guard.ts +330 -0
  130. package/src/lp/actions/liquidity.ts +827 -0
  131. package/src/lp/e2e/real-token-tests.ts +428 -0
  132. package/src/lp/e2e/scenarios.ts +470 -0
  133. package/src/lp/e2e/test-utils.ts +145 -0
  134. package/src/lp/lp-manager-entry.ts +303 -0
  135. package/src/lp/services/ConcentratedLiquidityService.ts +120 -0
  136. package/src/lp/services/DexInteractionService.ts +226 -0
  137. package/src/lp/services/LpManagementService.test.ts +148 -0
  138. package/src/lp/services/LpManagementService.ts +632 -0
  139. package/src/lp/services/UserLpProfileService.ts +163 -0
  140. package/src/lp/services/VaultService.ts +153 -0
  141. package/src/lp/services/YieldOptimizationService.ts +344 -0
  142. package/src/lp/services/__tests__/MockLpService.ts +146 -0
  143. package/src/lp/tasks/LpAutoRebalanceTask.ts +117 -0
  144. package/src/lp/tasks/__tests__/LpAutoRebalanceTask.test.ts +370 -0
  145. package/src/lp/types.ts +582 -0
  146. package/src/lp/utils/solanaClient.ts +143 -0
  147. package/src/plugin.ts +125 -0
  148. package/src/policy/policy.ts +19 -0
  149. package/src/providers/canonical-provider.ts +27 -0
  150. package/src/providers/unified-wallet-provider.ts +79 -0
  151. package/src/register-routes.ts +11 -0
  152. package/src/routes/plugin.ts +47 -0
  153. package/src/routes/wallet-market-overview-route.ts +869 -0
  154. package/src/sdk/abi.ts +258 -0
  155. package/src/sdk/bridge/abis.ts +126 -0
  156. package/src/sdk/bridge/client.ts +518 -0
  157. package/src/sdk/bridge/index.ts +56 -0
  158. package/src/sdk/bridge/solana.ts +604 -0
  159. package/src/sdk/bridge/types.ts +202 -0
  160. package/src/sdk/convenience.ts +347 -0
  161. package/src/sdk/escrow/MutualStakeEscrow.ts +480 -0
  162. package/src/sdk/escrow/types.ts +64 -0
  163. package/src/sdk/escrow/verifiers.ts +73 -0
  164. package/src/sdk/identity/erc8004.ts +692 -0
  165. package/src/sdk/identity/reputation.ts +449 -0
  166. package/src/sdk/identity/uaid.ts +497 -0
  167. package/src/sdk/identity/validation.ts +372 -0
  168. package/src/sdk/index.ts +763 -0
  169. package/src/sdk/policy/SpendingPolicy.ts +260 -0
  170. package/src/sdk/policy/UptoBillingPolicy.ts +320 -0
  171. package/src/sdk/router/PaymentRouter.ts +215 -0
  172. package/src/sdk/router/index.ts +8 -0
  173. package/src/sdk/swap/SwapModule.ts +310 -0
  174. package/src/sdk/swap/abi.ts +117 -0
  175. package/src/sdk/swap/index.ts +34 -0
  176. package/src/sdk/swap/types.ts +135 -0
  177. package/src/sdk/tokens/decimals.ts +140 -0
  178. package/src/sdk/tokens/registry.ts +911 -0
  179. package/src/sdk/tokens/solana.ts +419 -0
  180. package/src/sdk/tokens/transfers.ts +327 -0
  181. package/src/sdk/types.ts +158 -0
  182. package/src/sdk/wallet-core.ts +115 -0
  183. package/src/sdk/x402/budget.ts +168 -0
  184. package/src/sdk/x402/chains/abstract/index.ts +280 -0
  185. package/src/sdk/x402/client.ts +320 -0
  186. package/src/sdk/x402/index.ts +46 -0
  187. package/src/sdk/x402/middleware.ts +92 -0
  188. package/src/sdk/x402/multi-asset.ts +144 -0
  189. package/src/sdk/x402/types.ts +156 -0
  190. package/src/services/wallet-backend-service.ts +328 -0
  191. package/src/types/wallet-router.ts +227 -0
  192. package/src/utils/intent-trajectory.ts +106 -0
  193. package/src/wallet/backend.ts +62 -0
  194. package/src/wallet/errors.ts +49 -0
  195. package/src/wallet/index.ts +27 -0
  196. package/src/wallet/local-eoa-backend.ts +201 -0
  197. package/src/wallet/pending.ts +60 -0
  198. package/src/wallet/select-backend.ts +47 -0
  199. package/src/wallet/steward-backend.ts +161 -0
  200. package/src/wallet-action.ts +1 -0
@@ -0,0 +1,168 @@
1
+ // [MAX-ADDED] x402 Budget Controls — per-service spending caps and transaction logging
2
+ // viem types imported on-demand within class methods
3
+ import type {
4
+ X402ClientConfig,
5
+ X402ServiceBudget,
6
+ X402TransactionLog,
7
+ } from "./types.js";
8
+
9
+ /**
10
+ * [MAX-ADDED] In-memory budget tracker for x402 payments.
11
+ * Enforces per-service caps, daily limits, and per-request maximums.
12
+ * On-chain spend limits are ALSO enforced by the AgentWallet contract —
13
+ * this is an additional client-side layer for granular service-level control.
14
+ */
15
+ export class X402BudgetTracker {
16
+ private serviceBudgets: Map<string, X402ServiceBudget> = new Map();
17
+ private dailySpend: Map<string, bigint> = new Map(); // service -> today's total
18
+ private globalDailySpend: bigint = 0n;
19
+ private dailyResetTimestamp: number;
20
+ private transactionLog: X402TransactionLog[] = [];
21
+
22
+ private globalDailyLimit: bigint;
23
+ private globalPerRequestMax: bigint;
24
+
25
+ constructor(config: X402ClientConfig = {}) {
26
+ this.globalDailyLimit =
27
+ config.globalDailyLimit ?? BigInt("0xFFFFFFFFFFFFFFFFFFFFFFFF"); // effectively unlimited
28
+ this.globalPerRequestMax =
29
+ config.globalPerRequestMax ?? BigInt("0xFFFFFFFFFFFFFFFFFFFFFFFF");
30
+ this.dailyResetTimestamp = this.startOfDay();
31
+
32
+ if (config.serviceBudgets) {
33
+ for (const budget of config.serviceBudgets) {
34
+ this.serviceBudgets.set(budget.service, budget);
35
+ }
36
+ }
37
+ }
38
+
39
+ /**
40
+ * Check if a payment is within budget limits.
41
+ * Returns { allowed: true } or { allowed: false, reason: string }.
42
+ */
43
+ checkBudget(
44
+ service: string,
45
+ amount: bigint,
46
+ ): { allowed: boolean; reason?: string } {
47
+ this.maybeResetDaily();
48
+
49
+ // Global per-request check
50
+ if (amount > this.globalPerRequestMax) {
51
+ return {
52
+ allowed: false,
53
+ reason: `Amount ${amount} exceeds global per-request max ${this.globalPerRequestMax}`,
54
+ };
55
+ }
56
+
57
+ // Global daily check
58
+ if (this.globalDailySpend + amount > this.globalDailyLimit) {
59
+ return {
60
+ allowed: false,
61
+ reason: `Would exceed global daily limit ${this.globalDailyLimit}`,
62
+ };
63
+ }
64
+
65
+ // Service-specific checks
66
+ const budget = this.findServiceBudget(service);
67
+ if (budget) {
68
+ if (amount > budget.maxPerRequest) {
69
+ return {
70
+ allowed: false,
71
+ reason: `Amount ${amount} exceeds service per-request max ${budget.maxPerRequest} for ${service}`,
72
+ };
73
+ }
74
+ const serviceDailySpend = this.dailySpend.get(service) ?? 0n;
75
+ if (serviceDailySpend + amount > budget.dailyLimit) {
76
+ return {
77
+ allowed: false,
78
+ reason: `Would exceed daily limit ${budget.dailyLimit} for ${service}`,
79
+ };
80
+ }
81
+ }
82
+
83
+ return { allowed: true };
84
+ }
85
+
86
+ /**
87
+ * Record a completed payment.
88
+ */
89
+ recordPayment(log: X402TransactionLog): void {
90
+ this.maybeResetDaily();
91
+ this.transactionLog.push(log);
92
+
93
+ if (log.success) {
94
+ const service = log.service;
95
+ this.dailySpend.set(
96
+ service,
97
+ (this.dailySpend.get(service) ?? 0n) + log.amount,
98
+ );
99
+ this.globalDailySpend += log.amount;
100
+ }
101
+ }
102
+
103
+ /**
104
+ * Get transaction history, optionally filtered.
105
+ */
106
+ getTransactionLog(filter?: {
107
+ service?: string;
108
+ since?: number;
109
+ }): X402TransactionLog[] {
110
+ let logs = this.transactionLog;
111
+ if (filter?.service) {
112
+ logs = logs.filter((l) => l.service === filter.service);
113
+ }
114
+ if (filter?.since !== undefined) {
115
+ const since = filter.since;
116
+ logs = logs.filter((l) => l.timestamp >= since);
117
+ }
118
+ return logs;
119
+ }
120
+
121
+ /**
122
+ * Get current daily spend summary.
123
+ */
124
+ getDailySpendSummary(): {
125
+ global: bigint;
126
+ byService: Record<string, bigint>;
127
+ resetsAt: number;
128
+ } {
129
+ this.maybeResetDaily();
130
+ const byService: Record<string, bigint> = {};
131
+ for (const [service, amount] of this.dailySpend) {
132
+ byService[service] = amount;
133
+ }
134
+ return {
135
+ global: this.globalDailySpend,
136
+ byService,
137
+ resetsAt: this.dailyResetTimestamp + 86400,
138
+ };
139
+ }
140
+
141
+ /**
142
+ * Add or update a service budget at runtime.
143
+ */
144
+ setServiceBudget(budget: X402ServiceBudget): void {
145
+ this.serviceBudgets.set(budget.service, budget);
146
+ }
147
+
148
+ // ─── Internals ───
149
+
150
+ private findServiceBudget(service: string): X402ServiceBudget | undefined {
151
+ // Exact match first, then wildcard
152
+ return this.serviceBudgets.get(service) ?? this.serviceBudgets.get("*");
153
+ }
154
+
155
+ private maybeResetDaily(): void {
156
+ const now = this.startOfDay();
157
+ if (now > this.dailyResetTimestamp) {
158
+ this.dailySpend.clear();
159
+ this.globalDailySpend = 0n;
160
+ this.dailyResetTimestamp = now;
161
+ }
162
+ }
163
+
164
+ private startOfDay(): number {
165
+ const now = Math.floor(Date.now() / 1000);
166
+ return now - (now % 86400);
167
+ }
168
+ }
@@ -0,0 +1,280 @@
1
+ /**
2
+ * Abstract x402 Delegated Payment Facilitator Adapter
3
+ *
4
+ * Abstract's x402 implementation uses a delegated facilitator pattern:
5
+ * 1. The agent wallet does NOT sign the payment tx directly
6
+ * 2. A "payment facilitator" contract is designated per-merchant
7
+ * 3. The agent's wallet delegates authorization via a signed EIP-712 permit
8
+ * 4. The facilitator executes the actual chain transaction
9
+ *
10
+ * Chain IDs:
11
+ * - Abstract Mainnet: 2741
12
+ * - Abstract Testnet: 11124
13
+ */
14
+
15
+ import type { Address, Hex, WalletClient } from "viem";
16
+ import { encodeAbiParameters, parseAbiParameters } from "viem";
17
+
18
+ // ─── Abstract Chain Constants ────────────────────────────────────────────────
19
+
20
+ export const ABSTRACT_CHAIN_IDS = {
21
+ mainnet: 2741,
22
+ testnet: 11124,
23
+ } as const;
24
+
25
+ /** USDC on Abstract Mainnet (official Bridged USDC) */
26
+ export const ABSTRACT_USDC: Record<number, Address> = {
27
+ 2741: "0x84A71ccD554Cc1b02749b35d22F684CC8ec987e1", // Abstract Mainnet USDC
28
+ 11124: "0x3eBdeaA0DB3FfDe96E7a0DBBAFEC961FC50F725f", // Abstract Testnet USDC
29
+ };
30
+
31
+ /** Abstract's approved payment facilitator contracts */
32
+ export const ABSTRACT_APPROVED_FACILITATORS: Address[] = [
33
+ "0x5FbDB2315678afecb367f032d93F642f64180aa3", // Abstract official facilitator (mainnet)
34
+ ];
35
+
36
+ // ─── EIP-712 Types for Abstract Delegated Payment ───────────────────────────
37
+
38
+ const ABSTRACT_PERMIT_DOMAIN = {
39
+ name: "AbstractDelegatedPayment",
40
+ version: "1",
41
+ chainId: ABSTRACT_CHAIN_IDS.mainnet,
42
+ } as const;
43
+
44
+ const ABSTRACT_PERMIT_TYPES = {
45
+ DelegatedPaymentPermit: [
46
+ { name: "facilitator", type: "address" },
47
+ { name: "token", type: "address" },
48
+ { name: "amount", type: "uint256" },
49
+ { name: "payTo", type: "address" },
50
+ { name: "nonce", type: "uint256" },
51
+ { name: "deadline", type: "uint256" },
52
+ { name: "resource", type: "string" },
53
+ ],
54
+ } as const;
55
+
56
+ // ─── Types ────────────────────────────────────────────────────────────────────
57
+
58
+ export interface AbstractDelegatedPaymentConfig {
59
+ /** The facilitator contract address (must be on approved list or user-allowlisted) */
60
+ facilitatorAddress: Address;
61
+ /** Token to pay with (default: USDC on Abstract) */
62
+ token?: Address;
63
+ /** Permit deadline in seconds from now (default: 300 = 5 min) */
64
+ deadlineSeconds?: number;
65
+ /** User-allowlisted facilitator addresses (extends the approved list) */
66
+ userAllowlist?: Address[];
67
+ }
68
+
69
+ export interface DelegatedPaymentPermit {
70
+ facilitator: Address;
71
+ token: Address;
72
+ amount: bigint;
73
+ payTo: Address;
74
+ nonce: bigint;
75
+ deadline: bigint;
76
+ resource: string;
77
+ }
78
+
79
+ export interface AbstractPaymentResult {
80
+ /** EIP-712 signature for the facilitator permit */
81
+ permitSignature: Hex;
82
+ /** Encoded permit data to submit to the facilitator contract */
83
+ permitData: Hex;
84
+ /** The permit fields for verification */
85
+ permit: DelegatedPaymentPermit;
86
+ /** Chain ID this payment is valid on */
87
+ chainId: number;
88
+ }
89
+
90
+ // ─── AbstractDelegatedFacilitatorAdapter ─────────────────────────────────────
91
+
92
+ /**
93
+ * Adapter for Abstract's delegated payment facilitator x402 model.
94
+ *
95
+ * Instead of signing a direct payment transaction, the agent signs an EIP-712
96
+ * permit authorizing a facilitator contract to execute the payment on its behalf.
97
+ * This is Abstract's model — the agent's keys never touch the chain directly.
98
+ *
99
+ * @example
100
+ * ```typescript
101
+ * const adapter = new AbstractDelegatedFacilitatorAdapter(walletClient, {
102
+ * facilitatorAddress: '0x5FbDB2315678afecb367f032d93F642f64180aa3',
103
+ * });
104
+ *
105
+ * const result = await adapter.signPaymentPermit({
106
+ * amount: 1_000_000n, // 1 USDC (6 decimals)
107
+ * payTo: '0xmerchant...',
108
+ * nonce: 0n,
109
+ * resource: 'https://api.example.com/resource',
110
+ * });
111
+ * ```
112
+ */
113
+ export class AbstractDelegatedFacilitatorAdapter {
114
+ private walletClient: WalletClient;
115
+ private config: Required<AbstractDelegatedPaymentConfig>;
116
+ private chainId: number;
117
+
118
+ constructor(
119
+ walletClient: WalletClient,
120
+ config: AbstractDelegatedPaymentConfig,
121
+ chainId: number = ABSTRACT_CHAIN_IDS.mainnet,
122
+ ) {
123
+ this.walletClient = walletClient;
124
+ this.chainId = chainId;
125
+
126
+ // Validate facilitator
127
+ const approved = [
128
+ ...ABSTRACT_APPROVED_FACILITATORS,
129
+ ...(config.userAllowlist ?? []),
130
+ ];
131
+ const isApproved = approved.some(
132
+ (a) => a.toLowerCase() === config.facilitatorAddress.toLowerCase(),
133
+ );
134
+ if (!isApproved) {
135
+ throw new Error(
136
+ `Facilitator ${config.facilitatorAddress} is not on the Abstract approved list. ` +
137
+ `Pass it in userAllowlist to explicitly allow it.`,
138
+ );
139
+ }
140
+
141
+ this.config = {
142
+ facilitatorAddress: config.facilitatorAddress,
143
+ token:
144
+ config.token ??
145
+ ABSTRACT_USDC[chainId] ??
146
+ ABSTRACT_USDC[ABSTRACT_CHAIN_IDS.mainnet],
147
+ deadlineSeconds: config.deadlineSeconds ?? 300,
148
+ userAllowlist: config.userAllowlist ?? [],
149
+ };
150
+ }
151
+
152
+ /**
153
+ * Sign an EIP-712 delegated payment permit for the Abstract facilitator.
154
+ * This replaces direct tx signing — the permit is submitted to the facilitator contract.
155
+ */
156
+ async signPaymentPermit(params: {
157
+ amount: bigint;
158
+ payTo: Address;
159
+ nonce: bigint;
160
+ resource: string;
161
+ }): Promise<AbstractPaymentResult> {
162
+ const deadline = BigInt(
163
+ Math.floor(Date.now() / 1000) + this.config.deadlineSeconds,
164
+ );
165
+
166
+ const permit: DelegatedPaymentPermit = {
167
+ facilitator: this.config.facilitatorAddress,
168
+ token: this.config.token,
169
+ amount: params.amount,
170
+ payTo: params.payTo,
171
+ nonce: params.nonce,
172
+ deadline,
173
+ resource: params.resource,
174
+ };
175
+
176
+ const domain = {
177
+ ...ABSTRACT_PERMIT_DOMAIN,
178
+ chainId: this.chainId,
179
+ };
180
+
181
+ const account = this.walletClient.account;
182
+ if (!account) throw new Error("WalletClient has no account attached");
183
+
184
+ const signature = await this.walletClient.signTypedData({
185
+ account,
186
+ domain,
187
+ types: ABSTRACT_PERMIT_TYPES,
188
+ primaryType: "DelegatedPaymentPermit",
189
+ message: permit,
190
+ });
191
+
192
+ // Encode the permit for submission to the facilitator contract
193
+ const permitData = encodeAbiParameters(
194
+ parseAbiParameters(
195
+ "address facilitator, address token, uint256 amount, address payTo, uint256 nonce, uint256 deadline, string resource, bytes signature",
196
+ ),
197
+ [
198
+ permit.facilitator,
199
+ permit.token,
200
+ permit.amount,
201
+ permit.payTo,
202
+ permit.nonce,
203
+ permit.deadline,
204
+ permit.resource,
205
+ signature,
206
+ ],
207
+ );
208
+
209
+ return {
210
+ permitSignature: signature,
211
+ permitData,
212
+ permit,
213
+ chainId: this.chainId,
214
+ };
215
+ }
216
+
217
+ /**
218
+ * Build the x402 payment payload for Abstract's delegated facilitator model.
219
+ * This payload replaces the standard txHash payload in the X-PAYMENT header.
220
+ */
221
+ async buildX402Payload(params: {
222
+ amount: bigint;
223
+ payTo: Address;
224
+ nonce: bigint;
225
+ resource: string;
226
+ }): Promise<Record<string, unknown>> {
227
+ const result = await this.signPaymentPermit(params);
228
+
229
+ return {
230
+ scheme: "abstract-delegated",
231
+ chainId: result.chainId,
232
+ facilitator: result.permit.facilitator,
233
+ token: result.permit.token,
234
+ amount: result.permit.amount.toString(),
235
+ payTo: result.permit.payTo,
236
+ nonce: result.permit.nonce.toString(),
237
+ deadline: result.permit.deadline.toString(),
238
+ resource: result.permit.resource,
239
+ permitSignature: result.permitSignature,
240
+ permitData: result.permitData,
241
+ };
242
+ }
243
+
244
+ /** Check if a chain ID is an Abstract chain */
245
+ static isAbstractChain(chainId: number): boolean {
246
+ return Object.values(ABSTRACT_CHAIN_IDS).includes(chainId as 2741 | 11124);
247
+ }
248
+
249
+ /** Get the network string for x402 payment requirements (e.g. "abstract:2741") */
250
+ static getNetworkString(chainId: number): string {
251
+ return `abstract:${chainId}`;
252
+ }
253
+ }
254
+
255
+ // ─── SUPPORTED_CHAINS Extension ──────────────────────────────────────────────
256
+
257
+ /**
258
+ * Abstract chain IDs to add to SUPPORTED_CHAINS in the main SDK.
259
+ * These route through AbstractDelegatedFacilitatorAdapter for x402 payments.
260
+ */
261
+ export const ABSTRACT_SUPPORTED_CHAINS = {
262
+ "abstract:2741": {
263
+ chainId: ABSTRACT_CHAIN_IDS.mainnet,
264
+ name: "Abstract Mainnet",
265
+ rpcUrl: "https://api.mainnet.abs.xyz",
266
+ nativeCurrency: { name: "Ether", symbol: "ETH", decimals: 18 },
267
+ blockExplorer: "https://explorer.mainnet.abs.xyz",
268
+ x402Model: "delegated-facilitator" as const,
269
+ usdc: ABSTRACT_USDC[ABSTRACT_CHAIN_IDS.mainnet],
270
+ },
271
+ "abstract-testnet:11124": {
272
+ chainId: ABSTRACT_CHAIN_IDS.testnet,
273
+ name: "Abstract Testnet",
274
+ rpcUrl: "https://api.testnet.abs.xyz",
275
+ nativeCurrency: { name: "Ether", symbol: "ETH", decimals: 18 },
276
+ blockExplorer: "https://explorer.testnet.abs.xyz",
277
+ x402Model: "delegated-facilitator" as const,
278
+ usdc: ABSTRACT_USDC[ABSTRACT_CHAIN_IDS.testnet],
279
+ },
280
+ } as const;