@lucid-agents/opencode-x402-plugin 0.1.0

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/dist/utils.js ADDED
@@ -0,0 +1,227 @@
1
+ /**
2
+ * Utility functions for x402 auth plugin
3
+ * Exported separately for testing
4
+ */
5
+ import { createWalletClient, http, } from "viem";
6
+ import { privateKeyToAccount } from "viem/accounts";
7
+ import { base, baseSepolia, mainnet } from "viem/chains";
8
+ // ============================================================================
9
+ // Constants
10
+ // ============================================================================
11
+ /** USDC contract addresses by network */
12
+ export const USDC_ADDRESSES = {
13
+ "eip155:8453": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", // Base Mainnet
14
+ "eip155:84532": "0x036CbD53842c5426634e7929541eC2318f3dCF7e", // Base Sepolia
15
+ "eip155:1": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", // Ethereum Mainnet
16
+ };
17
+ /** Chain configs by CAIP-2 identifier */
18
+ export const CHAINS = {
19
+ "eip155:8453": base,
20
+ "eip155:84532": baseSepolia,
21
+ "eip155:1": mainnet,
22
+ };
23
+ /** Default permit cap in token units ($0.10 USDC = 100,000 with 6 decimals) */
24
+ export const DEFAULT_PERMIT_CAP = "100000";
25
+ /** Default permit validity (1 hour) */
26
+ export const DEFAULT_VALIDITY_SECONDS = 3600;
27
+ // ============================================================================
28
+ // EIP-712 Signing
29
+ // ============================================================================
30
+ /**
31
+ * EIP-712 domain for ERC-2612 Permit
32
+ */
33
+ export function getPermitDomain(tokenName, tokenVersion, chainId, verifyingContract) {
34
+ return {
35
+ name: tokenName,
36
+ version: tokenVersion,
37
+ chainId,
38
+ verifyingContract,
39
+ };
40
+ }
41
+ /**
42
+ * EIP-712 types for ERC-2612 Permit
43
+ */
44
+ export const PERMIT_TYPES = {
45
+ Permit: [
46
+ { name: "owner", type: "address" },
47
+ { name: "spender", type: "address" },
48
+ { name: "value", type: "uint256" },
49
+ { name: "nonce", type: "uint256" },
50
+ { name: "deadline", type: "uint256" },
51
+ ],
52
+ };
53
+ /**
54
+ * Generate a random nonce for the permit
55
+ */
56
+ export function generateNonce() {
57
+ const randomBytes = new Uint8Array(32);
58
+ crypto.getRandomValues(randomBytes);
59
+ // Use first 8 bytes as a numeric nonce (sufficient uniqueness)
60
+ const view = new DataView(randomBytes.buffer);
61
+ return view.getBigUint64(0, false).toString();
62
+ }
63
+ /**
64
+ * Sign an ERC-2612 permit using the wallet
65
+ */
66
+ export async function signPermit(wallet, account, config, permitCap) {
67
+ const chainId = parseInt(config.network.split(":")[1]);
68
+ const deadline = Math.floor(Date.now() / 1000) + DEFAULT_VALIDITY_SECONDS;
69
+ const nonce = generateNonce();
70
+ const domain = getPermitDomain(config.tokenName, config.tokenVersion, chainId, config.asset);
71
+ const message = {
72
+ owner: account.address,
73
+ spender: config.facilitatorSigner,
74
+ value: BigInt(permitCap),
75
+ nonce: BigInt(nonce),
76
+ deadline: BigInt(deadline),
77
+ };
78
+ const signature = await wallet.signTypedData({
79
+ account,
80
+ domain,
81
+ types: PERMIT_TYPES,
82
+ primaryType: "Permit",
83
+ message,
84
+ });
85
+ return {
86
+ signature,
87
+ nonce,
88
+ deadline: deadline.toString(),
89
+ };
90
+ }
91
+ /**
92
+ * Create a complete x402 payment payload
93
+ */
94
+ export async function createPaymentPayload(wallet, account, config, permitCap) {
95
+ const { signature, nonce, deadline } = await signPermit(wallet, account, config, permitCap);
96
+ const payload = {
97
+ x402Version: 2,
98
+ accepted: {
99
+ scheme: "upto",
100
+ network: config.network,
101
+ asset: config.asset,
102
+ payTo: config.payTo,
103
+ extra: {
104
+ name: config.tokenName,
105
+ version: config.tokenVersion,
106
+ },
107
+ },
108
+ payload: {
109
+ authorization: {
110
+ from: account.address,
111
+ to: config.facilitatorSigner,
112
+ value: permitCap,
113
+ validBefore: deadline,
114
+ nonce,
115
+ },
116
+ signature,
117
+ },
118
+ };
119
+ // Base64 encode for the header
120
+ return btoa(JSON.stringify(payload));
121
+ }
122
+ /**
123
+ * Decode a payment payload from base64
124
+ */
125
+ export function decodePaymentPayload(encoded) {
126
+ return JSON.parse(atob(encoded));
127
+ }
128
+ // ============================================================================
129
+ // Router Configuration
130
+ // ============================================================================
131
+ /** Cached router config */
132
+ let cachedRouterConfig = null;
133
+ let cachedRouterUrl = null;
134
+ /**
135
+ * Clear the router config cache (for testing)
136
+ */
137
+ export function clearRouterConfigCache() {
138
+ cachedRouterConfig = null;
139
+ cachedRouterUrl = null;
140
+ }
141
+ /**
142
+ * Parse router config response into RouterConfig
143
+ */
144
+ export function parseRouterConfigResponse(data) {
145
+ const network = data.networks?.[0];
146
+ const eip712 = data.eip712_config;
147
+ return {
148
+ network: network?.network_id || "eip155:8453",
149
+ asset: network?.asset?.address || USDC_ADDRESSES["eip155:8453"],
150
+ payTo: network?.pay_to || "",
151
+ facilitatorSigner: network?.pay_to || "",
152
+ tokenName: eip712?.domain_name || "USD Coin",
153
+ tokenVersion: eip712?.domain_version || "2",
154
+ };
155
+ }
156
+ /**
157
+ * Fetch router configuration from /v1/config endpoint
158
+ */
159
+ export async function fetchRouterConfig(routerUrl) {
160
+ // Return cached config if URL hasn't changed
161
+ if (cachedRouterConfig && cachedRouterUrl === routerUrl) {
162
+ return cachedRouterConfig;
163
+ }
164
+ const response = await fetch(`${routerUrl}/v1/config`);
165
+ if (!response.ok) {
166
+ throw new Error(`Failed to fetch router config: ${response.status}`);
167
+ }
168
+ const data = (await response.json());
169
+ const config = parseRouterConfigResponse(data);
170
+ cachedRouterConfig = config;
171
+ cachedRouterUrl = routerUrl;
172
+ return config;
173
+ }
174
+ /**
175
+ * Get default router config for a network (fallback)
176
+ */
177
+ export function getDefaultConfig(network) {
178
+ return {
179
+ network,
180
+ asset: USDC_ADDRESSES[network] || USDC_ADDRESSES["eip155:8453"],
181
+ payTo: "",
182
+ facilitatorSigner: "",
183
+ tokenName: "USD Coin",
184
+ tokenVersion: "2",
185
+ };
186
+ }
187
+ // ============================================================================
188
+ // Wallet Utilities
189
+ // ============================================================================
190
+ /**
191
+ * Validate a private key format
192
+ */
193
+ export function isValidPrivateKey(privateKey) {
194
+ if (!privateKey.startsWith("0x"))
195
+ return false;
196
+ if (privateKey.length !== 66)
197
+ return false;
198
+ // Check if it's valid hex
199
+ const hexPart = privateKey.slice(2);
200
+ return /^[0-9a-fA-F]+$/.test(hexPart);
201
+ }
202
+ /**
203
+ * Create a wallet client from a private key
204
+ */
205
+ export function createWalletFromPrivateKey(privateKey, network = "eip155:8453") {
206
+ const account = privateKeyToAccount(privateKey);
207
+ const chain = CHAINS[network] || base;
208
+ const wallet = createWalletClient({
209
+ account,
210
+ chain,
211
+ transport: http(),
212
+ });
213
+ return { wallet, account };
214
+ }
215
+ /**
216
+ * Convert USDC amount to token units (6 decimals)
217
+ */
218
+ export function usdcToUnits(amount) {
219
+ return Math.floor(amount * 1_000_000).toString();
220
+ }
221
+ /**
222
+ * Convert token units to USDC amount
223
+ */
224
+ export function unitsToUsdc(units) {
225
+ return parseInt(units) / 1_000_000;
226
+ }
227
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,72 @@
1
+ {
2
+ "name": "@lucid-agents/opencode-x402-plugin",
3
+ "version": "0.1.0",
4
+ "description": "OpenCode auth plugin for x402 payment protocol - sign permits with your wallet",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "import": "./dist/index.js",
11
+ "types": "./dist/index.d.ts"
12
+ }
13
+ },
14
+ "sideEffects": false,
15
+ "files": [
16
+ "dist",
17
+ "README.md",
18
+ "LICENSE"
19
+ ],
20
+ "scripts": {
21
+ "build": "tsc",
22
+ "dev": "tsc --watch",
23
+ "test": "vitest run",
24
+ "test:watch": "vitest",
25
+ "prepublishOnly": "npm run build"
26
+ },
27
+ "keywords": [
28
+ "opencode",
29
+ "x402",
30
+ "auth",
31
+ "plugin",
32
+ "wallet",
33
+ "crypto",
34
+ "permit",
35
+ "eip-712",
36
+ "erc-2612"
37
+ ],
38
+ "author": "Daydreams AI",
39
+ "license": "MIT",
40
+ "dependencies": {
41
+ "viem": "^2.44.4"
42
+ },
43
+ "devDependencies": {
44
+ "@types/node": "^25.0.10",
45
+ "msw": "2",
46
+ "typescript": "^5.9.3",
47
+ "vitest": "^2.1.0"
48
+ },
49
+ "peerDependencies": {
50
+ "@opencode-ai/plugin": "*"
51
+ },
52
+ "peerDependenciesMeta": {
53
+ "@opencode-ai/plugin": {
54
+ "optional": true
55
+ }
56
+ },
57
+ "engines": {
58
+ "node": ">=18.0.0"
59
+ },
60
+ "repository": {
61
+ "type": "git",
62
+ "url": "git+https://github.com/daydreamsai/router.git",
63
+ "directory": "packages/opencode-x402-auth"
64
+ },
65
+ "bugs": {
66
+ "url": "https://github.com/daydreamsai/router/issues"
67
+ },
68
+ "homepage": "https://github.com/daydreamsai/router/tree/master/packages/opencode-x402-auth",
69
+ "publishConfig": {
70
+ "access": "public"
71
+ }
72
+ }