uvd-x402-sdk 2.33.0 → 2.35.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/README.md CHANGED
@@ -12,6 +12,7 @@ Users sign a message or transaction, and the Ultravioleta facilitator handles on
12
12
  - **Gasless**: Facilitator pays all network fees
13
13
  - **Type-Safe**: Full TypeScript support
14
14
  - **React & Wagmi**: First-class integrations
15
+ - **Signing Wallet Adapters**: EnvKeyAdapter (server/CLI), OWSWalletAdapter (Open Wallet Standard), or bring your own
15
16
  - **ERC-8004 Trustless Agents**: On-chain reputation and identity (EVM + Solana)
16
17
  - **Escrow & Refunds**: Hold payments with dispute resolution
17
18
  - **`/accepts` Negotiation**: Discover facilitator capabilities before constructing payments
@@ -476,6 +477,80 @@ function PayButton() {
476
477
  }
477
478
  ```
478
479
 
480
+ ## Signing Wallet Adapters
481
+
482
+ Low-level signing primitives for server-side agents, CLI tools, and Open Wallet Standard wallets. These adapters implement EIP-191, EIP-712, and EIP-3009 (gasless USDC transfers).
483
+
484
+ ### EnvKeyAdapter (Server / CLI / Agents)
485
+
486
+ Signs with a raw private key from the environment or constructor. **Never use in browser contexts.**
487
+
488
+ ```typescript
489
+ import { EnvKeyAdapter } from 'uvd-x402-sdk';
490
+
491
+ // Option 1: Reads process.env.WALLET_PRIVATE_KEY
492
+ const wallet = new EnvKeyAdapter();
493
+
494
+ // Option 2: Explicit key
495
+ const wallet = new EnvKeyAdapter(process.env.MY_AGENT_KEY!);
496
+
497
+ console.log(wallet.getAddress()); // 0x...
498
+
499
+ // Sign EIP-3009 gasless USDC transfer
500
+ const auth = await wallet.signEIP3009({
501
+ to: '0xRecipient...',
502
+ amountUsdc: 1.00,
503
+ network: 'base',
504
+ });
505
+ // auth contains: from, to, value, nonce, v, r, s, signature
506
+
507
+ // Sign arbitrary message (EIP-191)
508
+ const sig = await wallet.signMessage('Hello x402');
509
+
510
+ // Sign EIP-712 typed data
511
+ const result = await wallet.signTypedData(JSON.stringify({
512
+ domain: { name: 'MyApp', version: '1', chainId: 8453 },
513
+ types: { Order: [{ name: 'id', type: 'uint256' }] },
514
+ primaryType: 'Order',
515
+ message: { id: 42 },
516
+ }));
517
+ ```
518
+
519
+ ### OWSWalletAdapter (Open Wallet Standard)
520
+
521
+ Delegates signing to any wallet that implements the [Open Wallet Standard](https://github.com/open-wallet-standard/open-wallet-standard). Works with browser wallets, agent vaults, and hardware-backed signers.
522
+
523
+ ```bash
524
+ npm install @open-wallet-standard/core # optional peer dependency
525
+ ```
526
+
527
+ ```typescript
528
+ import { OWSWalletAdapter } from 'uvd-x402-sdk';
529
+
530
+ const wallet = new OWSWalletAdapter(owsWalletInstance);
531
+
532
+ const auth = await wallet.signEIP3009({
533
+ to: '0xRecipient...',
534
+ amountUsdc: 0.50,
535
+ network: 'base',
536
+ });
537
+ ```
538
+
539
+ ### Custom Adapter
540
+
541
+ Implement the `SigningWalletAdapter` interface for your own signer:
542
+
543
+ ```typescript
544
+ import type { SigningWalletAdapter, EIP3009Params, EIP3009Authorization } from 'uvd-x402-sdk';
545
+
546
+ class MyAdapter implements SigningWalletAdapter {
547
+ getAddress(): string { /* ... */ }
548
+ async signMessage(message: string): Promise<string> { /* ... */ }
549
+ async signTypedData(typedData: string): Promise<{ signature: string; v: number; r: string; s: string }> { /* ... */ }
550
+ async signEIP3009(params: EIP3009Params): Promise<EIP3009Authorization> { /* ... */ }
551
+ }
552
+ ```
553
+
479
554
  ## Multi-Stablecoin (EVM)
480
555
 
481
556
  ```typescript
@@ -1,4 +1,5 @@
1
1
  import { L as X402Version, k as PaymentResult } from '../index-MNVg3WMv.mjs';
2
+ export { b as EnvKeyAdapter, O as OWSWallet, c as OWSWalletAdapter } from '../ows-BkQHp_45.mjs';
2
3
 
3
4
  /**
4
5
  * uvd-x402-sdk - Wagmi/Viem Adapter
@@ -1,4 +1,5 @@
1
1
  import { L as X402Version, k as PaymentResult } from '../index-MNVg3WMv.js';
2
+ export { b as EnvKeyAdapter, O as OWSWallet, c as OWSWalletAdapter } from '../ows-BkQHp_45.js';
2
3
 
3
4
  /**
4
5
  * uvd-x402-sdk - Wagmi/Viem Adapter
@@ -1,5 +1,7 @@
1
1
  'use strict';
2
2
 
3
+ var ethers = require('ethers');
4
+
3
5
  // src/chains/index.ts
4
6
  var DEFAULT_FACILITATOR_URL = "https://facilitator.ultravioletadao.xyz";
5
7
  var SUPPORTED_CHAINS = {
@@ -1077,7 +1079,303 @@ function useX402Wagmi(walletClient) {
1077
1079
  createPaymentFull
1078
1080
  };
1079
1081
  }
1082
+ var EnvKeyAdapter = class {
1083
+ wallet;
1084
+ /**
1085
+ * Create an EnvKeyAdapter.
1086
+ *
1087
+ * @param privateKey - Hex-encoded private key (with or without 0x prefix).
1088
+ * If omitted, reads from `process.env.WALLET_PRIVATE_KEY`.
1089
+ * @throws {X402Error} if no private key is available
1090
+ */
1091
+ constructor(privateKey) {
1092
+ const key = privateKey || (typeof process !== "undefined" ? process.env.WALLET_PRIVATE_KEY : void 0);
1093
+ if (!key) {
1094
+ throw new X402Error(
1095
+ "No private key provided. Pass it to the constructor or set WALLET_PRIVATE_KEY env var.",
1096
+ "WALLET_NOT_CONNECTED"
1097
+ );
1098
+ }
1099
+ this.wallet = new ethers.ethers.Wallet(key);
1100
+ }
1101
+ /**
1102
+ * Get the checksummed EVM wallet address.
1103
+ */
1104
+ getAddress() {
1105
+ return this.wallet.address;
1106
+ }
1107
+ /**
1108
+ * Sign a message using EIP-191 personal_sign.
1109
+ *
1110
+ * @param message - The message string to sign
1111
+ * @returns Hex-encoded signature
1112
+ */
1113
+ async signMessage(message) {
1114
+ return this.wallet.signMessage(message);
1115
+ }
1116
+ /**
1117
+ * Sign EIP-712 typed structured data.
1118
+ *
1119
+ * @param typedData - JSON string with `domain`, `types`, `primaryType`, and `message` fields
1120
+ * @returns Object with signature and v/r/s components
1121
+ */
1122
+ async signTypedData(typedData) {
1123
+ const parsed = JSON.parse(typedData);
1124
+ const { domain, types, message } = parsed;
1125
+ const cleanTypes = { ...types };
1126
+ delete cleanTypes["EIP712Domain"];
1127
+ const signature = await this.wallet.signTypedData(domain, cleanTypes, message);
1128
+ const sig = ethers.ethers.Signature.from(signature);
1129
+ return {
1130
+ signature,
1131
+ v: sig.v,
1132
+ r: sig.r,
1133
+ s: sig.s
1134
+ };
1135
+ }
1136
+ /**
1137
+ * Sign an EIP-3009 ReceiveWithAuthorization for USDC.
1138
+ *
1139
+ * @param params - EIP-3009 parameters
1140
+ * @returns Signed authorization ready for facilitator relay
1141
+ */
1142
+ async signEIP3009(params) {
1143
+ const chain = getChainByName(params.network);
1144
+ if (!chain) {
1145
+ throw new X402Error(`Unsupported network: ${params.network}`, "CHAIN_NOT_SUPPORTED");
1146
+ }
1147
+ if (chain.networkType !== "evm") {
1148
+ throw new X402Error(
1149
+ `EIP-3009 is only supported on EVM chains. ${params.network} is ${chain.networkType}.`,
1150
+ "CHAIN_NOT_SUPPORTED"
1151
+ );
1152
+ }
1153
+ const chainId = params.chainId ?? chain.chainId;
1154
+ const usdcAddress = params.usdcContract ?? chain.usdc.address;
1155
+ const from = this.wallet.address;
1156
+ const to = ethers.ethers.getAddress(params.to);
1157
+ const value = ethers.ethers.parseUnits(params.amountUsdc.toString(), chain.usdc.decimals);
1158
+ const validAfter = params.validAfter ?? 0;
1159
+ const validBefore = params.validBefore ?? Math.floor(Date.now() / 1e3) + 300;
1160
+ const nonce = ethers.ethers.hexlify(ethers.ethers.randomBytes(32));
1161
+ const domain = {
1162
+ name: chain.usdc.name,
1163
+ version: chain.usdc.version,
1164
+ chainId,
1165
+ verifyingContract: usdcAddress
1166
+ };
1167
+ const types = {
1168
+ TransferWithAuthorization: [
1169
+ { name: "from", type: "address" },
1170
+ { name: "to", type: "address" },
1171
+ { name: "value", type: "uint256" },
1172
+ { name: "validAfter", type: "uint256" },
1173
+ { name: "validBefore", type: "uint256" },
1174
+ { name: "nonce", type: "bytes32" }
1175
+ ]
1176
+ };
1177
+ const message = {
1178
+ from,
1179
+ to,
1180
+ value,
1181
+ validAfter,
1182
+ validBefore,
1183
+ nonce
1184
+ };
1185
+ let signature;
1186
+ try {
1187
+ signature = await this.wallet.signTypedData(domain, types, message);
1188
+ } catch (error) {
1189
+ throw new X402Error(
1190
+ `Failed to sign EIP-3009 authorization: ${error instanceof Error ? error.message : "Unknown error"}`,
1191
+ "PAYMENT_FAILED",
1192
+ error
1193
+ );
1194
+ }
1195
+ const sig = ethers.ethers.Signature.from(signature);
1196
+ return {
1197
+ from,
1198
+ to,
1199
+ value: value.toString(),
1200
+ validAfter: validAfter.toString(),
1201
+ validBefore: validBefore.toString(),
1202
+ nonce,
1203
+ v: sig.v,
1204
+ r: sig.r,
1205
+ s: sig.s,
1206
+ signature
1207
+ };
1208
+ }
1209
+ };
1210
+ var OWSWalletAdapter = class {
1211
+ owsWallet;
1212
+ address;
1213
+ /**
1214
+ * Create an OWSWalletAdapter.
1215
+ *
1216
+ * @param owsWallet - An object implementing the OWSWallet interface
1217
+ * (typically from @open-wallet-standard/core or a compatible provider)
1218
+ * @param accountIndex - Which account to use if the wallet has multiple (default: 0)
1219
+ * @throws {X402Error} if the wallet has no accounts
1220
+ */
1221
+ constructor(owsWallet, accountIndex = 0) {
1222
+ if (!owsWallet || !owsWallet.accounts || owsWallet.accounts.length === 0) {
1223
+ throw new X402Error(
1224
+ "OWS wallet has no accounts. Create or import a wallet first.",
1225
+ "WALLET_NOT_CONNECTED"
1226
+ );
1227
+ }
1228
+ const account = owsWallet.accounts[accountIndex];
1229
+ if (!account) {
1230
+ throw new X402Error(
1231
+ `OWS wallet account index ${accountIndex} does not exist. Wallet has ${owsWallet.accounts.length} account(s).`,
1232
+ "WALLET_NOT_CONNECTED"
1233
+ );
1234
+ }
1235
+ this.owsWallet = owsWallet;
1236
+ this.address = ethers.ethers.getAddress(account.address);
1237
+ }
1238
+ /**
1239
+ * Get the checksummed EVM wallet address.
1240
+ */
1241
+ getAddress() {
1242
+ return this.address;
1243
+ }
1244
+ /**
1245
+ * Sign a message using EIP-191 personal_sign.
1246
+ *
1247
+ * @param message - The message string to sign
1248
+ * @returns Hex-encoded signature
1249
+ */
1250
+ async signMessage(message) {
1251
+ try {
1252
+ const result = await this.owsWallet.signMessage({
1253
+ account: { address: this.address },
1254
+ message
1255
+ });
1256
+ return result.signature;
1257
+ } catch (error) {
1258
+ throw new X402Error(
1259
+ `OWS signMessage failed: ${error instanceof Error ? error.message : "Unknown error"}`,
1260
+ "PAYMENT_FAILED",
1261
+ error
1262
+ );
1263
+ }
1264
+ }
1265
+ /**
1266
+ * Sign EIP-712 typed structured data.
1267
+ *
1268
+ * @param typedData - JSON string with `domain`, `types`, `primaryType`, and `message` fields
1269
+ * @returns Object with signature and v/r/s components
1270
+ */
1271
+ async signTypedData(typedData) {
1272
+ const parsed = JSON.parse(typedData);
1273
+ try {
1274
+ const result = await this.owsWallet.signTypedData({
1275
+ account: { address: this.address },
1276
+ domain: parsed.domain,
1277
+ types: parsed.types,
1278
+ primaryType: parsed.primaryType,
1279
+ message: parsed.message
1280
+ });
1281
+ const sig = ethers.ethers.Signature.from(result.signature);
1282
+ return {
1283
+ signature: result.signature,
1284
+ v: sig.v,
1285
+ r: sig.r,
1286
+ s: sig.s
1287
+ };
1288
+ } catch (error) {
1289
+ throw new X402Error(
1290
+ `OWS signTypedData failed: ${error instanceof Error ? error.message : "Unknown error"}`,
1291
+ "PAYMENT_FAILED",
1292
+ error
1293
+ );
1294
+ }
1295
+ }
1296
+ /**
1297
+ * Sign an EIP-3009 ReceiveWithAuthorization for USDC.
1298
+ *
1299
+ * @param params - EIP-3009 parameters
1300
+ * @returns Signed authorization ready for facilitator relay
1301
+ */
1302
+ async signEIP3009(params) {
1303
+ const chain = getChainByName(params.network);
1304
+ if (!chain) {
1305
+ throw new X402Error(`Unsupported network: ${params.network}`, "CHAIN_NOT_SUPPORTED");
1306
+ }
1307
+ if (chain.networkType !== "evm") {
1308
+ throw new X402Error(
1309
+ `EIP-3009 is only supported on EVM chains. ${params.network} is ${chain.networkType}.`,
1310
+ "CHAIN_NOT_SUPPORTED"
1311
+ );
1312
+ }
1313
+ const chainId = params.chainId ?? chain.chainId;
1314
+ const usdcAddress = params.usdcContract ?? chain.usdc.address;
1315
+ const from = this.address;
1316
+ const to = ethers.ethers.getAddress(params.to);
1317
+ const value = ethers.ethers.parseUnits(params.amountUsdc.toString(), chain.usdc.decimals);
1318
+ const validAfter = params.validAfter ?? 0;
1319
+ const validBefore = params.validBefore ?? Math.floor(Date.now() / 1e3) + 300;
1320
+ const nonce = ethers.ethers.hexlify(ethers.ethers.randomBytes(32));
1321
+ const domain = {
1322
+ name: chain.usdc.name,
1323
+ version: chain.usdc.version,
1324
+ chainId,
1325
+ verifyingContract: usdcAddress
1326
+ };
1327
+ const types = {
1328
+ TransferWithAuthorization: [
1329
+ { name: "from", type: "address" },
1330
+ { name: "to", type: "address" },
1331
+ { name: "value", type: "uint256" },
1332
+ { name: "validAfter", type: "uint256" },
1333
+ { name: "validBefore", type: "uint256" },
1334
+ { name: "nonce", type: "bytes32" }
1335
+ ]
1336
+ };
1337
+ const message = {
1338
+ from,
1339
+ to,
1340
+ value: value.toString(),
1341
+ validAfter: validAfter.toString(),
1342
+ validBefore: validBefore.toString(),
1343
+ nonce
1344
+ };
1345
+ let signatureResult;
1346
+ try {
1347
+ signatureResult = await this.owsWallet.signTypedData({
1348
+ account: { address: this.address },
1349
+ domain,
1350
+ types,
1351
+ primaryType: "TransferWithAuthorization",
1352
+ message
1353
+ });
1354
+ } catch (error) {
1355
+ throw new X402Error(
1356
+ `OWS signEIP3009 failed: ${error instanceof Error ? error.message : "Unknown error"}`,
1357
+ "PAYMENT_FAILED",
1358
+ error
1359
+ );
1360
+ }
1361
+ const sig = ethers.ethers.Signature.from(signatureResult.signature);
1362
+ return {
1363
+ from,
1364
+ to,
1365
+ value: value.toString(),
1366
+ validAfter: validAfter.toString(),
1367
+ validBefore: validBefore.toString(),
1368
+ nonce,
1369
+ v: sig.v,
1370
+ r: sig.r,
1371
+ s: sig.s,
1372
+ signature: signatureResult.signature
1373
+ };
1374
+ }
1375
+ };
1080
1376
 
1377
+ exports.EnvKeyAdapter = EnvKeyAdapter;
1378
+ exports.OWSWalletAdapter = OWSWalletAdapter;
1081
1379
  exports.createPaymentFromWalletClient = createPaymentFromWalletClient;
1082
1380
  exports.createPaymentWithResult = createPaymentWithResult;
1083
1381
  exports.useX402Wagmi = useX402Wagmi;