@agether/sdk 1.8.0 → 1.9.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/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
- import { Signer } from 'ethers';
1
+ import { Signer, ethers } from 'ethers';
2
+ import { WalletClient } from 'viem';
2
3
 
3
4
  /**
4
5
  * Agether SDK Types
@@ -186,10 +187,20 @@ declare class AgetherClient {
186
187
  * - supplyCollateral: [ERC20.approve, Morpho.supplyCollateral]
187
188
  *
188
189
  * Market discovery via Morpho GraphQL API (https://api.morpho.org/graphql)
190
+ *
191
+ * Supports two signing modes:
192
+ * - `privateKey`: SDK manages wallet lifecycle (existing behavior)
193
+ * - `signer`: external signer (Bankr, Privy, Turnkey, MetaMask, etc.)
189
194
  */
190
195
 
191
- interface MorphoClientConfig {
192
- privateKey: string;
196
+ /**
197
+ * Convenience type alias for any ethers-compatible signer.
198
+ * Use this when declaring variables or parameters that accept
199
+ * ethers.Wallet, Privy signer, Bankr signer, Turnkey signer, etc.
200
+ */
201
+ type AgetherSigner = ethers.AbstractSigner;
202
+ /** Base configuration fields shared by both signing modes. */
203
+ interface MorphoClientBaseConfig {
193
204
  rpcUrl: string;
194
205
  agentId?: string;
195
206
  chainId?: ChainId;
@@ -201,6 +212,44 @@ interface MorphoClientConfig {
201
212
  identityRegistry: string;
202
213
  }>;
203
214
  }
215
+ /**
216
+ * MorphoClient configuration.
217
+ *
218
+ * Provide **either** `privateKey` (SDK manages wallet) **or** `signer`
219
+ * (external custody provider). The two fields are mutually exclusive.
220
+ *
221
+ * @example
222
+ * ```ts
223
+ * // Private key (existing behavior — fully backward compatible):
224
+ * new MorphoClient({ privateKey: '0x...', rpcUrl, agentId: '42' })
225
+ *
226
+ * // External signer (Bankr, Privy, Turnkey, MetaMask, etc.):
227
+ * new MorphoClient({ signer: privySigner, rpcUrl, agentId: '42' })
228
+ * ```
229
+ */
230
+ type MorphoClientConfig = MorphoClientBaseConfig & ({
231
+ /** Raw private key hex string. SDK creates an ethers.Wallet internally. */
232
+ privateKey: string;
233
+ signer?: never;
234
+ } | {
235
+ /**
236
+ * Any `ethers.AbstractSigner` instance for transaction signing.
237
+ *
238
+ * Accepts:
239
+ * - `ethers.Wallet` (local key)
240
+ * - Privy embedded wallet signer
241
+ * - Bankr custodial signer
242
+ * - Turnkey / MPC wallet signer
243
+ * - Hardware wallet adapter (Ledger, Trezor)
244
+ * - MetaMask `BrowserProvider.getSigner()`
245
+ * - Any object implementing `ethers.AbstractSigner`
246
+ *
247
+ * The signer is treated as **immutable** by the SDK — it will never be
248
+ * recreated or reconnected. Nonce management is the caller's responsibility.
249
+ */
250
+ signer: ethers.AbstractSigner;
251
+ privateKey?: never;
252
+ });
204
253
  interface BalancesResult {
205
254
  agentId: string;
206
255
  address: string;
@@ -219,6 +268,8 @@ interface RegisterResult {
219
268
  address: string;
220
269
  agentAccount: string;
221
270
  alreadyRegistered: boolean;
271
+ /** Whether the KYA (code verification) gate is active on this factory */
272
+ kyaRequired: boolean;
222
273
  tx?: string;
223
274
  }
224
275
  interface PositionResult {
@@ -272,12 +323,14 @@ interface FundResult {
272
323
  agentAccount: string;
273
324
  }
274
325
  declare class MorphoClient {
275
- private wallet;
326
+ private _signer;
276
327
  private provider;
277
328
  private config;
278
329
  private agentId;
279
330
  private _rpcUrl;
280
- private _privateKey;
331
+ private _privateKey?;
332
+ private _useExternalSigner;
333
+ private _eoaAddress?;
281
334
  private accountFactory;
282
335
  private morphoBlue;
283
336
  private agentReputation;
@@ -287,10 +340,28 @@ declare class MorphoClient {
287
340
  private _discoveredMarkets?;
288
341
  private _discoveredAt;
289
342
  constructor(config: MorphoClientConfig);
343
+ /**
344
+ * Check whether the KYA (Know Your Agent) code verification gate is active.
345
+ * When validationRegistry is address(0), KYA is disabled — agents can use
346
+ * execute/executeBatch without prior code approval.
347
+ */
348
+ isKyaRequired(): Promise<boolean>;
290
349
  /** Resolve the AgentAccount address (cached). */
291
350
  getAccountAddress(): Promise<string>;
292
351
  getAgentId(): string;
352
+ /**
353
+ * Get the EOA wallet address (synchronous, best-effort).
354
+ *
355
+ * For the `privateKey` path this always works. For the `signer` path
356
+ * it works if the signer exposes `.address` synchronously (e.g. ethers.Wallet).
357
+ * If the address has not been resolved yet, throws — call `getSignerAddress()` first.
358
+ */
293
359
  getWalletAddress(): string;
360
+ /**
361
+ * Resolve the EOA signer address (async, works with all signer types).
362
+ * Result is cached after the first call.
363
+ */
364
+ getSignerAddress(): Promise<string>;
294
365
  /** Mint a new ERC-8004 identity and return the agentId. */
295
366
  private _mintNewIdentity;
296
367
  /**
@@ -450,9 +521,17 @@ declare class MorphoClient {
450
521
  age: bigint;
451
522
  }>;
452
523
  /**
453
- * Recreate provider + wallet so the next tx fetches a fresh nonce from chain.
454
- * Anvil (and some RPC providers) return a stale `eth_getTransactionCount`
455
- * right after a block is mined, causing "nonce too low" on the follow-up tx.
524
+ * Refresh the signer and re-bind contract instances.
525
+ *
526
+ * For the **privateKey** path: recreates provider + wallet so the next tx
527
+ * fetches a fresh nonce from chain. Anvil (and some RPC providers) return a
528
+ * stale `eth_getTransactionCount` right after a block is mined, causing
529
+ * "nonce too low" on the follow-up tx.
530
+ *
531
+ * For the **external signer** path: the signer is immutable and owned by the
532
+ * caller (e.g. custody provider). We only re-bind contract instances to
533
+ * ensure they reference the current signer. Nonce management is the caller's
534
+ * responsibility.
456
535
  */
457
536
  private _refreshSigner;
458
537
  /**
@@ -491,8 +570,15 @@ declare class MorphoClient {
491
570
  *
492
571
  * Chain support: Base (8453), Base Sepolia (84532), Ethereum (1).
493
572
  */
494
- interface X402Config {
495
- privateKey: string;
573
+
574
+ /**
575
+ * Convenience type alias for any viem-compatible WalletClient.
576
+ * Use this when declaring variables or parameters that accept
577
+ * viem WalletClient instances from Privy, Turnkey, MetaMask, etc.
578
+ */
579
+ type AgetherViemWallet = WalletClient;
580
+ /** Base configuration fields shared by both signing modes. */
581
+ interface X402BaseConfig {
496
582
  rpcUrl: string;
497
583
  backendUrl: string;
498
584
  agentId?: string;
@@ -519,6 +605,29 @@ interface X402Config {
519
605
  */
520
606
  autoDrawBuffer?: string;
521
607
  }
608
+ /** Config with SDK-managed private key (existing behavior). */
609
+ interface X402PrivateKeyConfig extends X402BaseConfig {
610
+ /** Raw hex private key (with or without '0x' prefix). SDK creates the wallet internally. */
611
+ privateKey: string;
612
+ walletClient?: never;
613
+ }
614
+ /** Config with caller-provided viem WalletClient (custody-agnostic). */
615
+ interface X402WalletClientConfig extends X402BaseConfig {
616
+ /**
617
+ * A viem WalletClient with an attached account (e.g. from Privy, Turnkey, MetaMask).
618
+ * The client **must** have an `account` property set. The SDK will use it for
619
+ * EIP-712 typed-data signing and will never recreate or reconnect the client.
620
+ */
621
+ walletClient: WalletClient;
622
+ privateKey?: never;
623
+ }
624
+ /**
625
+ * X402Client configuration.
626
+ *
627
+ * Provide **either** `privateKey` (SDK manages wallet) **or** `walletClient`
628
+ * (external custody provider). The two fields are mutually exclusive.
629
+ */
630
+ type X402Config = X402PrivateKeyConfig | X402WalletClientConfig;
522
631
  interface X402Response<T = unknown> {
523
632
  success: boolean;
524
633
  data?: T;
@@ -954,4 +1063,4 @@ declare function getDefaultConfig(chainId: ChainId): AgetherConfig;
954
1063
  */
955
1064
  declare function createConfig(chainId: ChainId, options?: Partial<AgetherConfig>): AgetherConfig;
956
1065
 
957
- export { ACCOUNT_FACTORY_ABI, AGENT_ACCOUNT_ABI, AGENT_REPUTATION_ABI, AgentIdentityClient, type AgentIdentityClientOptions, AgentNotApprovedError, AgetherClient, type AgetherClientOptions, type AgetherConfig, AgetherError, type BalancesResult, type BorrowResult, ChainId, type ContractAddresses, type DepositAndBorrowResult, type DepositResult, ERC20_ABI, type FundResult, IDENTITY_REGISTRY_ABI, InsufficientBalanceError, MORPHO_BLUE_ABI, MorphoClient, type MorphoClientConfig, type MorphoMarketInfo, type MorphoMarketParams, type MorphoPosition, type PaymentRequirements, type PositionResult, type RegisterResult, type RepayResult, type ScoreAttestation, type ScoreResult, ScoringClient, type ScoringClientConfig, ScoringRejectedError, type SpendingTracker, type StatusResult, type TransactionResult, VALIDATION_REGISTRY_ABI, type WithdrawResult, X402Client, type X402Config, type X402PaymentRequest, type X402PaymentResult, type X402Response, bpsToRate, createConfig, formatAPR, formatAddress, formatHealthFactor, formatPercent, formatTimestamp, formatUSD, formatUnits, getDefaultConfig, parseUnits, rateToBps };
1066
+ export { ACCOUNT_FACTORY_ABI, AGENT_ACCOUNT_ABI, AGENT_REPUTATION_ABI, AgentIdentityClient, type AgentIdentityClientOptions, AgentNotApprovedError, AgetherClient, type AgetherClientOptions, type AgetherConfig, AgetherError, type AgetherSigner, type AgetherViemWallet, type BalancesResult, type BorrowResult, ChainId, type ContractAddresses, type DepositAndBorrowResult, type DepositResult, ERC20_ABI, type FundResult, IDENTITY_REGISTRY_ABI, InsufficientBalanceError, MORPHO_BLUE_ABI, MorphoClient, type MorphoClientConfig, type MorphoMarketInfo, type MorphoMarketParams, type MorphoPosition, type PaymentRequirements, type PositionResult, type RegisterResult, type RepayResult, type ScoreAttestation, type ScoreResult, ScoringClient, type ScoringClientConfig, ScoringRejectedError, type SpendingTracker, type StatusResult, type TransactionResult, VALIDATION_REGISTRY_ABI, type WithdrawResult, X402Client, type X402Config, type X402PaymentRequest, type X402PaymentResult, type X402Response, bpsToRate, createConfig, formatAPR, formatAddress, formatHealthFactor, formatPercent, formatTimestamp, formatUSD, formatUnits, getDefaultConfig, parseUnits, rateToBps };
package/dist/index.js CHANGED
@@ -126,7 +126,10 @@ var ACCOUNT_FACTORY_ABI = [
126
126
  "function totalAccounts() view returns (uint256)",
127
127
  "function getAgentId(address account) view returns (uint256)",
128
128
  "function createAccount(uint256 agentId) returns (address account)",
129
- "event AccountCreated(uint256 indexed agentId, address indexed account, address indexed owner)"
129
+ "function validationRegistry() view returns (address)",
130
+ "function setValidationRegistry(address newRegistry)",
131
+ "event AccountCreated(uint256 indexed agentId, address indexed account, address indexed owner)",
132
+ "event ValidationRegistryUpdated(address indexed oldRegistry, address indexed newRegistry)"
130
133
  ];
131
134
  var AGENT_ACCOUNT_ABI = [
132
135
  "function agentId() view returns (uint256)",
@@ -463,14 +466,44 @@ var MorphoClient = class {
463
466
  this.config = defaultCfg;
464
467
  this.agentId = config.agentId;
465
468
  this._rpcUrl = config.rpcUrl || defaultCfg.rpcUrl;
466
- this._privateKey = config.privateKey;
467
- this.provider = new import_ethers2.ethers.JsonRpcProvider(this._rpcUrl);
468
- this.wallet = new import_ethers2.ethers.Wallet(this._privateKey, this.provider);
469
+ if ("signer" in config && config.signer) {
470
+ this._useExternalSigner = true;
471
+ const signerProvider = config.signer.provider;
472
+ if (signerProvider) {
473
+ this.provider = signerProvider;
474
+ this._signer = config.signer;
475
+ } else {
476
+ this.provider = new import_ethers2.ethers.JsonRpcProvider(this._rpcUrl);
477
+ this._signer = config.signer.connect(this.provider);
478
+ }
479
+ if ("address" in config.signer && typeof config.signer.address === "string") {
480
+ this._eoaAddress = config.signer.address;
481
+ }
482
+ } else {
483
+ this._privateKey = config.privateKey;
484
+ this._useExternalSigner = false;
485
+ this.provider = new import_ethers2.ethers.JsonRpcProvider(this._rpcUrl);
486
+ const wallet = new import_ethers2.ethers.Wallet(this._privateKey, this.provider);
487
+ this._signer = wallet;
488
+ this._eoaAddress = wallet.address;
489
+ }
469
490
  const addrs = { ...defaultCfg.contracts, ...config.contracts };
470
- this.accountFactory = new import_ethers2.Contract(addrs.accountFactory, ACCOUNT_FACTORY_ABI, this.wallet);
491
+ this.accountFactory = new import_ethers2.Contract(addrs.accountFactory, ACCOUNT_FACTORY_ABI, this._signer);
471
492
  this.morphoBlue = new import_ethers2.Contract(addrs.morphoBlue, MORPHO_BLUE_ABI, this.provider);
472
- this.agentReputation = new import_ethers2.Contract(addrs.agentReputation, AGENT_REPUTATION_ABI, this.wallet);
473
- this.identityRegistry = new import_ethers2.Contract(addrs.identityRegistry, IDENTITY_REGISTRY_ABI, this.wallet);
493
+ this.agentReputation = new import_ethers2.Contract(addrs.agentReputation, AGENT_REPUTATION_ABI, this._signer);
494
+ this.identityRegistry = new import_ethers2.Contract(addrs.identityRegistry, IDENTITY_REGISTRY_ABI, this._signer);
495
+ }
496
+ // ════════════════════════════════════════════════════════
497
+ // KYA Gate Check
498
+ // ════════════════════════════════════════════════════════
499
+ /**
500
+ * Check whether the KYA (Know Your Agent) code verification gate is active.
501
+ * When validationRegistry is address(0), KYA is disabled — agents can use
502
+ * execute/executeBatch without prior code approval.
503
+ */
504
+ async isKyaRequired() {
505
+ const registryAddr = await this.accountFactory.validationRegistry();
506
+ return registryAddr !== import_ethers2.ethers.ZeroAddress;
474
507
  }
475
508
  // ════════════════════════════════════════════════════════
476
509
  // Account Management
@@ -490,8 +523,35 @@ var MorphoClient = class {
490
523
  if (!this.agentId) throw new AgetherError("agentId not set", "NO_AGENT_ID");
491
524
  return this.agentId;
492
525
  }
526
+ /**
527
+ * Get the EOA wallet address (synchronous, best-effort).
528
+ *
529
+ * For the `privateKey` path this always works. For the `signer` path
530
+ * it works if the signer exposes `.address` synchronously (e.g. ethers.Wallet).
531
+ * If the address has not been resolved yet, throws — call `getSignerAddress()` first.
532
+ */
493
533
  getWalletAddress() {
494
- return this.wallet.address;
534
+ if (this._eoaAddress) return this._eoaAddress;
535
+ const signer = this._signer;
536
+ if (signer.address && typeof signer.address === "string") {
537
+ const addr = signer.address;
538
+ this._eoaAddress = addr;
539
+ return addr;
540
+ }
541
+ throw new AgetherError(
542
+ "EOA address not yet resolved. Call getSignerAddress() (async) first, or use a signer that exposes .address synchronously.",
543
+ "ADDRESS_NOT_RESOLVED"
544
+ );
545
+ }
546
+ /**
547
+ * Resolve the EOA signer address (async, works with all signer types).
548
+ * Result is cached after the first call.
549
+ */
550
+ async getSignerAddress() {
551
+ if (!this._eoaAddress) {
552
+ this._eoaAddress = await this._signer.getAddress();
553
+ }
554
+ return this._eoaAddress;
495
555
  }
496
556
  /** Mint a new ERC-8004 identity and return the agentId. */
497
557
  async _mintNewIdentity() {
@@ -518,13 +578,14 @@ var MorphoClient = class {
518
578
  * If already registered, returns existing state.
519
579
  */
520
580
  async register(_name) {
521
- const eoaAddr = this.wallet.address;
581
+ const eoaAddr = await this.getSignerAddress();
522
582
  if (this.agentId) {
523
583
  const exists = await this.accountFactory.accountExists(BigInt(this.agentId));
524
584
  if (exists) {
525
585
  const acct = await this.accountFactory.getAccount(BigInt(this.agentId));
526
586
  this._accountAddress = acct;
527
- return { agentId: this.agentId, address: eoaAddr, agentAccount: acct, alreadyRegistered: true };
587
+ const kyaRequired2 = await this.isKyaRequired();
588
+ return { agentId: this.agentId, address: eoaAddr, agentAccount: acct, alreadyRegistered: true, kyaRequired: kyaRequired2 };
528
589
  }
529
590
  }
530
591
  let agentId;
@@ -549,17 +610,19 @@ var MorphoClient = class {
549
610
  }
550
611
  const acctAddr = await this.accountFactory.getAccount(agentId);
551
612
  this._accountAddress = acctAddr;
613
+ const kyaRequired = await this.isKyaRequired();
552
614
  return {
553
615
  agentId: this.agentId,
554
616
  address: eoaAddr,
555
617
  agentAccount: acctAddr,
556
618
  alreadyRegistered: acctExists,
619
+ kyaRequired,
557
620
  tx: txHash
558
621
  };
559
622
  }
560
623
  /** Get ETH / USDC / collateral balances for EOA and AgentAccount. */
561
624
  async getBalances() {
562
- const eoaAddr = this.wallet.address;
625
+ const eoaAddr = await this.getSignerAddress();
563
626
  const usdc = new import_ethers2.Contract(this.config.contracts.usdc, ERC20_ABI, this.provider);
564
627
  const ethBal = await this.provider.getBalance(eoaAddr);
565
628
  const usdcBal = await usdc.balanceOf(eoaAddr);
@@ -607,7 +670,7 @@ var MorphoClient = class {
607
670
  /** Transfer USDC from EOA to AgentAccount. */
608
671
  async fundAccount(usdcAmount) {
609
672
  const acctAddr = await this.getAccountAddress();
610
- const usdc = new import_ethers2.Contract(this.config.contracts.usdc, ERC20_ABI, this.wallet);
673
+ const usdc = new import_ethers2.Contract(this.config.contracts.usdc, ERC20_ABI, this._signer);
611
674
  const amount = import_ethers2.ethers.parseUnits(usdcAmount, 6);
612
675
  const tx = await usdc.transfer(acctAddr, amount);
613
676
  const receipt = await tx.wait();
@@ -955,7 +1018,7 @@ var MorphoClient = class {
955
1018
  const params = marketParams ?? await this.findMarketForCollateral(tokenSymbol);
956
1019
  const weiAmount = import_ethers2.ethers.parseUnits(amount, colInfo.decimals);
957
1020
  const morphoAddr = this.config.contracts.morphoBlue;
958
- const colToken = new import_ethers2.Contract(colInfo.address, ERC20_ABI, this.wallet);
1021
+ const colToken = new import_ethers2.Contract(colInfo.address, ERC20_ABI, this._signer);
959
1022
  const transferTx = await colToken.transfer(acctAddr, weiAmount);
960
1023
  await transferTx.wait();
961
1024
  this._refreshSigner();
@@ -1032,7 +1095,7 @@ var MorphoClient = class {
1032
1095
  const colWei = import_ethers2.ethers.parseUnits(collateralAmount, colInfo.decimals);
1033
1096
  const borrowWei = import_ethers2.ethers.parseUnits(borrowUsdcAmount, 6);
1034
1097
  const morphoAddr = this.config.contracts.morphoBlue;
1035
- const colToken = new import_ethers2.Contract(colInfo.address, ERC20_ABI, this.wallet);
1098
+ const colToken = new import_ethers2.Contract(colInfo.address, ERC20_ABI, this._signer);
1036
1099
  const transferTx = await colToken.transfer(acctAddr, colWei);
1037
1100
  await transferTx.wait();
1038
1101
  this._refreshSigner();
@@ -1162,7 +1225,7 @@ var MorphoClient = class {
1162
1225
  if (!colInfo) throw new AgetherError(`Unknown collateral: ${tokenSymbol}`, "UNKNOWN_COLLATERAL");
1163
1226
  const params = marketParams ?? await this.findMarketForCollateral(tokenSymbol);
1164
1227
  const morphoAddr = this.config.contracts.morphoBlue;
1165
- const dest = receiver || this.wallet.address;
1228
+ const dest = receiver || await this.getSignerAddress();
1166
1229
  let weiAmount;
1167
1230
  if (amount === "all") {
1168
1231
  const markets = await this.getMarkets();
@@ -1220,7 +1283,7 @@ var MorphoClient = class {
1220
1283
  throw new AgetherError("Provide agentId or address", "INVALID_TARGET");
1221
1284
  }
1222
1285
  const weiAmount = import_ethers2.ethers.parseUnits(amount, colInfo.decimals);
1223
- const colToken = new import_ethers2.Contract(colInfo.address, ERC20_ABI, this.wallet);
1286
+ const colToken = new import_ethers2.Contract(colInfo.address, ERC20_ABI, this._signer);
1224
1287
  const tx = await colToken.transfer(targetAddr, weiAmount);
1225
1288
  const receipt = await tx.wait();
1226
1289
  this._refreshSigner();
@@ -1252,24 +1315,41 @@ var MorphoClient = class {
1252
1315
  // Internal Helpers
1253
1316
  // ════════════════════════════════════════════════════════
1254
1317
  /**
1255
- * Recreate provider + wallet so the next tx fetches a fresh nonce from chain.
1256
- * Anvil (and some RPC providers) return a stale `eth_getTransactionCount`
1257
- * right after a block is mined, causing "nonce too low" on the follow-up tx.
1318
+ * Refresh the signer and re-bind contract instances.
1319
+ *
1320
+ * For the **privateKey** path: recreates provider + wallet so the next tx
1321
+ * fetches a fresh nonce from chain. Anvil (and some RPC providers) return a
1322
+ * stale `eth_getTransactionCount` right after a block is mined, causing
1323
+ * "nonce too low" on the follow-up tx.
1324
+ *
1325
+ * For the **external signer** path: the signer is immutable and owned by the
1326
+ * caller (e.g. custody provider). We only re-bind contract instances to
1327
+ * ensure they reference the current signer. Nonce management is the caller's
1328
+ * responsibility.
1258
1329
  */
1259
1330
  _refreshSigner() {
1260
- this.provider = new import_ethers2.ethers.JsonRpcProvider(this._rpcUrl);
1261
- this.wallet = new import_ethers2.ethers.Wallet(this._privateKey, this.provider);
1262
- const addrs = this.config.contracts;
1263
- this.accountFactory = new import_ethers2.Contract(addrs.accountFactory, ACCOUNT_FACTORY_ABI, this.wallet);
1264
- this.agentReputation = new import_ethers2.Contract(addrs.agentReputation, AGENT_REPUTATION_ABI, this.wallet);
1265
- this.identityRegistry = new import_ethers2.Contract(addrs.identityRegistry, IDENTITY_REGISTRY_ABI, this.wallet);
1331
+ if (this._useExternalSigner) {
1332
+ const addrs = this.config.contracts;
1333
+ this.accountFactory = new import_ethers2.Contract(addrs.accountFactory, ACCOUNT_FACTORY_ABI, this._signer);
1334
+ this.agentReputation = new import_ethers2.Contract(addrs.agentReputation, AGENT_REPUTATION_ABI, this._signer);
1335
+ this.identityRegistry = new import_ethers2.Contract(addrs.identityRegistry, IDENTITY_REGISTRY_ABI, this._signer);
1336
+ } else {
1337
+ this.provider = new import_ethers2.ethers.JsonRpcProvider(this._rpcUrl);
1338
+ const wallet = new import_ethers2.ethers.Wallet(this._privateKey, this.provider);
1339
+ this._signer = wallet;
1340
+ this._eoaAddress = wallet.address;
1341
+ const addrs = this.config.contracts;
1342
+ this.accountFactory = new import_ethers2.Contract(addrs.accountFactory, ACCOUNT_FACTORY_ABI, this._signer);
1343
+ this.agentReputation = new import_ethers2.Contract(addrs.agentReputation, AGENT_REPUTATION_ABI, this._signer);
1344
+ this.identityRegistry = new import_ethers2.Contract(addrs.identityRegistry, IDENTITY_REGISTRY_ABI, this._signer);
1345
+ }
1266
1346
  }
1267
1347
  /**
1268
1348
  * Execute a single call via AgentAccount.execute.
1269
1349
  */
1270
1350
  async exec(target, data, value = 0n) {
1271
1351
  const acctAddr = await this.getAccountAddress();
1272
- const account = new import_ethers2.Contract(acctAddr, AGENT_ACCOUNT_ABI, this.wallet);
1352
+ const account = new import_ethers2.Contract(acctAddr, AGENT_ACCOUNT_ABI, this._signer);
1273
1353
  let gasLimit;
1274
1354
  try {
1275
1355
  const estimate = await account.execute.estimateGas(target, value, data);
@@ -1287,7 +1367,7 @@ var MorphoClient = class {
1287
1367
  */
1288
1368
  async batch(targets, values, datas) {
1289
1369
  const acctAddr = await this.getAccountAddress();
1290
- const account = new import_ethers2.Contract(acctAddr, AGENT_ACCOUNT_ABI, this.wallet);
1370
+ const account = new import_ethers2.Contract(acctAddr, AGENT_ACCOUNT_ABI, this._signer);
1291
1371
  let gasLimit;
1292
1372
  try {
1293
1373
  const estimate = await account.executeBatch.estimateGas(targets, values, datas);
@@ -1344,28 +1424,62 @@ var import_accounts = require("viem/accounts");
1344
1424
  var X402Client = class {
1345
1425
  constructor(config) {
1346
1426
  this.config = config;
1347
- const privateKey = config.privateKey.startsWith("0x") ? config.privateKey : `0x${config.privateKey}`;
1348
- const eoaSigner = (0, import_accounts.privateKeyToAccount)(privateKey);
1427
+ let baseSigner;
1428
+ if ("walletClient" in config && config.walletClient) {
1429
+ const wc = config.walletClient;
1430
+ const account = wc.account;
1431
+ if (!account) {
1432
+ throw new Error(
1433
+ "X402Client: walletClient must have an attached account. Pass an account when creating the WalletClient or use privateKey mode instead."
1434
+ );
1435
+ }
1436
+ this.address = account.address;
1437
+ baseSigner = {
1438
+ address: account.address,
1439
+ signTypedData: (msg) => wc.signTypedData({
1440
+ account,
1441
+ domain: msg.domain,
1442
+ types: msg.types,
1443
+ primaryType: msg.primaryType,
1444
+ message: msg.message
1445
+ })
1446
+ };
1447
+ } else if ("privateKey" in config && config.privateKey) {
1448
+ const privateKey = config.privateKey.startsWith("0x") ? config.privateKey : `0x${config.privateKey}`;
1449
+ const account = (0, import_accounts.privateKeyToAccount)(privateKey);
1450
+ this.address = account.address;
1451
+ baseSigner = account;
1452
+ } else {
1453
+ throw new Error(
1454
+ "X402Client: provide either privateKey or walletClient in config."
1455
+ );
1456
+ }
1349
1457
  let signer;
1350
1458
  if (config.accountAddress) {
1351
1459
  const accountAddr = config.accountAddress;
1460
+ const inner = baseSigner;
1352
1461
  signer = (0, import_accounts.toAccount)({
1353
1462
  address: accountAddr,
1354
1463
  async signMessage({ message }) {
1355
- return eoaSigner.signMessage({ message });
1464
+ if ("signMessage" in inner && typeof inner.signMessage === "function") {
1465
+ return inner.signMessage({ message });
1466
+ }
1467
+ throw new Error("signMessage not supported by underlying signer");
1356
1468
  },
1357
1469
  async signTransaction(tx) {
1358
- return eoaSigner.signTransaction(tx);
1470
+ if ("signTransaction" in inner && typeof inner.signTransaction === "function") {
1471
+ return inner.signTransaction(tx);
1472
+ }
1473
+ throw new Error("signTransaction not supported by underlying signer");
1359
1474
  },
1360
1475
  async signTypedData(typedData) {
1361
- const sig = await eoaSigner.signTypedData(typedData);
1476
+ const sig = await inner.signTypedData(typedData);
1362
1477
  return `${sig}00`;
1363
1478
  }
1364
1479
  });
1365
1480
  this.address = accountAddr;
1366
1481
  } else {
1367
- signer = eoaSigner;
1368
- this.address = eoaSigner.address;
1482
+ signer = baseSigner;
1369
1483
  }
1370
1484
  const client = new import_client.x402Client();
1371
1485
  (0, import_client2.registerExactEvmScheme)(client, { signer });