@buildersgarden/siwa 0.0.1 → 0.0.3

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Builders Garden SRL
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -64,7 +64,7 @@ See [`references/security-model.md`](references/security-model.md) for the full
64
64
  ## Tech Stack
65
65
 
66
66
  - **TypeScript** (ES modules, strict mode)
67
- - **ethers.js** v6 — wallet management and contract interaction
67
+ - **viem** — wallet management and contract interaction
68
68
  - **pnpm** — package manager
69
69
 
70
70
  ## References
@@ -0,0 +1,20 @@
1
+ /**
2
+ * addresses.ts
3
+ *
4
+ * Canonical ERC-8004 contract addresses, chain metadata, and helpers.
5
+ * Published as part of the SDK so consumers don't need to hard-code addresses.
6
+ */
7
+ export declare const REGISTRY_ADDRESSES: Record<number, string>;
8
+ export declare const REPUTATION_ADDRESSES: Record<number, string>;
9
+ export declare const RPC_ENDPOINTS: Record<number, string>;
10
+ export declare const CHAIN_NAMES: Record<number, string>;
11
+ export declare const FAUCETS: Record<number, string>;
12
+ export declare const BLOCK_EXPLORERS: Record<number, string>;
13
+ /**
14
+ * Get the identity registry address for a chain, or throw if unsupported.
15
+ */
16
+ export declare function getRegistryAddress(chainId: number): string;
17
+ /**
18
+ * Get the agent registry string in `eip155:{chainId}:{address}` format.
19
+ */
20
+ export declare function getAgentRegistryString(chainId: number): string;
@@ -0,0 +1,82 @@
1
+ /**
2
+ * addresses.ts
3
+ *
4
+ * Canonical ERC-8004 contract addresses, chain metadata, and helpers.
5
+ * Published as part of the SDK so consumers don't need to hard-code addresses.
6
+ */
7
+ // ---------------------------------------------------------------------------
8
+ // Identity Registries
9
+ // ---------------------------------------------------------------------------
10
+ export const REGISTRY_ADDRESSES = {
11
+ 8453: '0x8004A169FB4a3325136EB29fA0ceB6D2e539a432', // Base
12
+ 84532: '0x8004A818BFB912233c491871b3d84c89A494BD9e', // Base Sepolia
13
+ 11155111: '0x8004a6090Cd10A7288092483047B097295Fb8847', // ETH Sepolia
14
+ 59141: '0x8004aa7C931bCE1233973a0C6A667f73F66282e7', // Linea Sepolia
15
+ 80002: '0x8004ad19E14B9e0654f73353e8a0B600D46C2898', // Polygon Amoy
16
+ };
17
+ // ---------------------------------------------------------------------------
18
+ // Reputation Registries
19
+ // ---------------------------------------------------------------------------
20
+ export const REPUTATION_ADDRESSES = {
21
+ 8453: '0x8004BAa17C55a88189AE136b182e5fdA19dE9b63', // Base
22
+ 84532: '0x8004B663056A597Dffe9eCcC1965A193B7388713', // Base Sepolia
23
+ };
24
+ // ---------------------------------------------------------------------------
25
+ // RPC Endpoints (public, rate-limited)
26
+ // ---------------------------------------------------------------------------
27
+ export const RPC_ENDPOINTS = {
28
+ 8453: 'https://mainnet.base.org',
29
+ 84532: 'https://sepolia.base.org',
30
+ 11155111: 'https://rpc.sepolia.org',
31
+ 59141: 'https://rpc.sepolia.linea.build',
32
+ 80002: 'https://rpc-amoy.polygon.technology',
33
+ };
34
+ // ---------------------------------------------------------------------------
35
+ // Chain Names
36
+ // ---------------------------------------------------------------------------
37
+ export const CHAIN_NAMES = {
38
+ 8453: 'Base',
39
+ 84532: 'Base Sepolia',
40
+ 11155111: 'Ethereum Sepolia',
41
+ 59141: 'Linea Sepolia',
42
+ 80002: 'Polygon Amoy',
43
+ };
44
+ // ---------------------------------------------------------------------------
45
+ // Faucets (testnets only)
46
+ // ---------------------------------------------------------------------------
47
+ export const FAUCETS = {
48
+ 84532: 'https://www.alchemy.com/faucets/base-sepolia',
49
+ 11155111: 'https://www.alchemy.com/faucets/ethereum-sepolia',
50
+ 59141: 'https://faucets.chain.link/linea-sepolia',
51
+ 80002: 'https://faucet.polygon.technology/',
52
+ };
53
+ // ---------------------------------------------------------------------------
54
+ // Block Explorers
55
+ // ---------------------------------------------------------------------------
56
+ export const BLOCK_EXPLORERS = {
57
+ 8453: 'https://basescan.org',
58
+ 84532: 'https://sepolia.basescan.org',
59
+ 11155111: 'https://sepolia.etherscan.io',
60
+ 59141: 'https://sepolia.lineascan.build',
61
+ 80002: 'https://amoy.polygonscan.com',
62
+ };
63
+ // ---------------------------------------------------------------------------
64
+ // Helpers
65
+ // ---------------------------------------------------------------------------
66
+ /**
67
+ * Get the identity registry address for a chain, or throw if unsupported.
68
+ */
69
+ export function getRegistryAddress(chainId) {
70
+ const addr = REGISTRY_ADDRESSES[chainId];
71
+ if (!addr) {
72
+ const supported = Object.keys(REGISTRY_ADDRESSES).join(', ');
73
+ throw new Error(`No identity registry for chainId ${chainId}. Supported: ${supported}`);
74
+ }
75
+ return addr;
76
+ }
77
+ /**
78
+ * Get the agent registry string in `eip155:{chainId}:{address}` format.
79
+ */
80
+ export function getAgentRegistryString(chainId) {
81
+ return `eip155:${chainId}:${getRegistryAddress(chainId)}`;
82
+ }
package/dist/index.d.ts CHANGED
@@ -3,3 +3,4 @@ export * from './siwa.js';
3
3
  export * from './memory.js';
4
4
  export * from './proxy-auth.js';
5
5
  export * from './registry.js';
6
+ export * from './addresses.js';
package/dist/index.js CHANGED
@@ -3,3 +3,4 @@ export * from './siwa.js';
3
3
  export * from './memory.js';
4
4
  export * from './proxy-auth.js';
5
5
  export * from './registry.js';
6
+ export * from './addresses.js';
@@ -5,7 +5,7 @@
5
5
  *
6
6
  * Three backends, in order of preference:
7
7
  * 0. Keyring Proxy (via HMAC-authenticated HTTP) — key never enters agent process
8
- * 1. Ethereum V3 Encrypted JSON Keystore (via ethers.js) — password-encrypted file on disk
8
+ * 1. Ethereum V3 Encrypted JSON Keystore (via @noble/ciphers) — password-encrypted file on disk
9
9
  * 2. Environment variable fallback (AGENT_PRIVATE_KEY) — least secure, for CI/testing only
10
10
  *
11
11
  * The private key NEVER leaves this module as a return value.
@@ -18,15 +18,15 @@
18
18
  * - getAddress() → returns the public address
19
19
  * - hasWallet() → returns boolean
20
20
  *
21
- * EIP-7702 Support (requires ethers >= 6.14.3):
22
- * Wallets are standard EOAs created via ethers.Wallet.createRandom().
21
+ * EIP-7702 Support:
22
+ * Wallets are standard EOAs created via viem's generatePrivateKey().
23
23
  * EIP-7702 allows these EOAs to temporarily delegate to smart contract
24
24
  * implementations via authorization lists in type 4 transactions.
25
25
  * Use signAuthorization() to sign delegation authorizations without
26
26
  * exposing the private key.
27
27
  *
28
28
  * Dependencies:
29
- * npm install ethers
29
+ * npm install viem
30
30
  *
31
31
  * Configuration (via env vars or passed options):
32
32
  * KEYSTORE_BACKEND — "encrypted-file" | "env" | "proxy" (auto-detected if omitted)
@@ -34,7 +34,7 @@
34
34
  * KEYSTORE_PATH — Path to encrypted keystore file (default: ./agent-keystore.json)
35
35
  * AGENT_PRIVATE_KEY — Fallback for env backend only
36
36
  */
37
- import { ethers } from 'ethers';
37
+ import { type WalletClient, type Account, type Chain, type Transport } from 'viem';
38
38
  export type KeystoreBackend = 'encrypted-file' | 'env' | 'proxy';
39
39
  export interface KeystoreConfig {
40
40
  backend?: KeystoreBackend;
@@ -65,6 +65,20 @@ export interface SignedAuthorization {
65
65
  r: string;
66
66
  s: string;
67
67
  }
68
+ export interface TransactionLike {
69
+ to?: string;
70
+ data?: string;
71
+ value?: bigint;
72
+ nonce?: number;
73
+ chainId?: number;
74
+ type?: number;
75
+ maxFeePerGas?: bigint | null;
76
+ maxPriorityFeePerGas?: bigint | null;
77
+ gasLimit?: bigint;
78
+ gas?: bigint;
79
+ gasPrice?: bigint | null;
80
+ accessList?: any[];
81
+ }
68
82
  export declare function detectBackend(): Promise<KeystoreBackend>;
69
83
  /**
70
84
  * Create a new random wallet and store it securely.
@@ -96,13 +110,12 @@ export declare function signMessage(message: string, config?: KeystoreConfig): P
96
110
  * The private key is loaded, used, and immediately discarded.
97
111
  * Only the signed transaction is returned.
98
112
  */
99
- export declare function signTransaction(tx: ethers.TransactionRequest, config?: KeystoreConfig): Promise<{
113
+ export declare function signTransaction(tx: TransactionLike, config?: KeystoreConfig): Promise<{
100
114
  signedTx: string;
101
115
  address: string;
102
116
  }>;
103
117
  /**
104
118
  * Sign an EIP-7702 authorization for delegating the EOA to a contract.
105
- * Requires ethers >= 6.14.3.
106
119
  *
107
120
  * This allows the agent's EOA to temporarily act as a smart contract
108
121
  * during a type 4 transaction. The private key is loaded, used, and
@@ -113,12 +126,12 @@ export declare function signTransaction(tx: ethers.TransactionRequest, config?:
113
126
  */
114
127
  export declare function signAuthorization(auth: AuthorizationRequest, config?: KeystoreConfig): Promise<SignedAuthorization>;
115
128
  /**
116
- * Get a connected signer (for contract interactions).
117
- * NOTE: This returns a signer with the private key in memory.
129
+ * Get a wallet client for contract interactions.
130
+ * NOTE: This creates a client with the private key in memory.
118
131
  * Use only within a narrow scope and discard immediately.
119
132
  * Prefer signMessage() / signTransaction() when possible.
120
133
  */
121
- export declare function getSigner(provider: ethers.Provider, config?: KeystoreConfig): Promise<ethers.Wallet>;
134
+ export declare function getWalletClient(rpcUrl: string, config?: KeystoreConfig): Promise<WalletClient<Transport, Chain | undefined, Account>>;
122
135
  /**
123
136
  * Delete the stored wallet from the active backend.
124
137
  * DESTRUCTIVE — the identity is lost if no backup exists.
package/dist/keystore.js CHANGED
@@ -5,7 +5,7 @@
5
5
  *
6
6
  * Three backends, in order of preference:
7
7
  * 0. Keyring Proxy (via HMAC-authenticated HTTP) — key never enters agent process
8
- * 1. Ethereum V3 Encrypted JSON Keystore (via ethers.js) — password-encrypted file on disk
8
+ * 1. Ethereum V3 Encrypted JSON Keystore (via @noble/ciphers) — password-encrypted file on disk
9
9
  * 2. Environment variable fallback (AGENT_PRIVATE_KEY) — least secure, for CI/testing only
10
10
  *
11
11
  * The private key NEVER leaves this module as a return value.
@@ -18,15 +18,15 @@
18
18
  * - getAddress() → returns the public address
19
19
  * - hasWallet() → returns boolean
20
20
  *
21
- * EIP-7702 Support (requires ethers >= 6.14.3):
22
- * Wallets are standard EOAs created via ethers.Wallet.createRandom().
21
+ * EIP-7702 Support:
22
+ * Wallets are standard EOAs created via viem's generatePrivateKey().
23
23
  * EIP-7702 allows these EOAs to temporarily delegate to smart contract
24
24
  * implementations via authorization lists in type 4 transactions.
25
25
  * Use signAuthorization() to sign delegation authorizations without
26
26
  * exposing the private key.
27
27
  *
28
28
  * Dependencies:
29
- * npm install ethers
29
+ * npm install viem
30
30
  *
31
31
  * Configuration (via env vars or passed options):
32
32
  * KEYSTORE_BACKEND — "encrypted-file" | "env" | "proxy" (auto-detected if omitted)
@@ -34,14 +34,98 @@
34
34
  * KEYSTORE_PATH — Path to encrypted keystore file (default: ./agent-keystore.json)
35
35
  * AGENT_PRIVATE_KEY — Fallback for env backend only
36
36
  */
37
- import { ethers } from 'ethers';
37
+ import { createWalletClient, http, keccak256, toBytes, toHex, concat, } from 'viem';
38
+ import { privateKeyToAccount, generatePrivateKey } from 'viem/accounts';
39
+ import { hashAuthorization } from 'viem/experimental';
40
+ import { scrypt } from '@noble/hashes/scrypt';
41
+ import { randomBytes } from '@noble/hashes/utils';
42
+ import { ctr } from '@noble/ciphers/aes';
38
43
  import * as fs from 'fs';
39
44
  import * as crypto from 'crypto';
45
+ import * as os from 'os';
40
46
  import { computeHmac } from './proxy-auth.js';
41
47
  // ---------------------------------------------------------------------------
42
48
  // Constants
43
49
  // ---------------------------------------------------------------------------
44
50
  const DEFAULT_KEYSTORE_PATH = './agent-keystore.json';
51
+ function generateUUID() {
52
+ const bytes = randomBytes(16);
53
+ bytes[6] = (bytes[6] & 0x0f) | 0x40; // version 4
54
+ bytes[8] = (bytes[8] & 0x3f) | 0x80; // variant
55
+ const hex = toHex(bytes).slice(2);
56
+ return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20, 32)}`;
57
+ }
58
+ async function encryptKeystore(privateKey, password) {
59
+ const privateKeyBytes = toBytes(privateKey);
60
+ const salt = randomBytes(32);
61
+ const iv = randomBytes(16);
62
+ // Scrypt parameters (standard for V3 keystores)
63
+ const n = 262144; // 2^18
64
+ const r = 8;
65
+ const p = 1;
66
+ const dklen = 32;
67
+ // Derive key using scrypt
68
+ const derivedKey = scrypt(new TextEncoder().encode(password), salt, { N: n, r, p, dkLen: dklen });
69
+ // Encrypt private key with AES-128-CTR
70
+ const encryptionKey = derivedKey.slice(0, 16);
71
+ const cipher = ctr(encryptionKey, iv);
72
+ const ciphertext = cipher.encrypt(privateKeyBytes);
73
+ // Calculate MAC: keccak256(derivedKey[16:32] + ciphertext)
74
+ const macData = concat([toHex(derivedKey.slice(16, 32)), toHex(ciphertext)]);
75
+ const mac = keccak256(macData);
76
+ // Get address from private key
77
+ const account = privateKeyToAccount(privateKey);
78
+ const keystore = {
79
+ version: 3,
80
+ id: generateUUID(),
81
+ address: account.address.toLowerCase().slice(2),
82
+ crypto: {
83
+ ciphertext: toHex(ciphertext).slice(2),
84
+ cipherparams: { iv: toHex(iv).slice(2) },
85
+ cipher: 'aes-128-ctr',
86
+ kdf: 'scrypt',
87
+ kdfparams: {
88
+ dklen,
89
+ salt: toHex(salt).slice(2),
90
+ n,
91
+ r,
92
+ p,
93
+ },
94
+ mac: mac.slice(2),
95
+ },
96
+ };
97
+ return JSON.stringify(keystore);
98
+ }
99
+ async function decryptKeystore(json, password) {
100
+ const keystore = JSON.parse(json);
101
+ if (keystore.version !== 3) {
102
+ throw new Error(`Unsupported keystore version: ${keystore.version}`);
103
+ }
104
+ const { crypto: cryptoData } = keystore;
105
+ if (cryptoData.kdf !== 'scrypt') {
106
+ throw new Error(`Unsupported KDF: ${cryptoData.kdf}`);
107
+ }
108
+ if (cryptoData.cipher !== 'aes-128-ctr') {
109
+ throw new Error(`Unsupported cipher: ${cryptoData.cipher}`);
110
+ }
111
+ const { kdfparams } = cryptoData;
112
+ const salt = toBytes(`0x${kdfparams.salt}`);
113
+ const iv = toBytes(`0x${cryptoData.cipherparams.iv}`);
114
+ const ciphertext = toBytes(`0x${cryptoData.ciphertext}`);
115
+ // Derive key using scrypt
116
+ const derivedKey = scrypt(new TextEncoder().encode(password), salt, { N: kdfparams.n, r: kdfparams.r, p: kdfparams.p, dkLen: kdfparams.dklen });
117
+ // Verify MAC
118
+ const macData = concat([toHex(derivedKey.slice(16, 32)), toHex(ciphertext)]);
119
+ const calculatedMac = keccak256(macData).slice(2);
120
+ if (calculatedMac.toLowerCase() !== cryptoData.mac.toLowerCase()) {
121
+ throw new Error('Invalid password or corrupted keystore');
122
+ }
123
+ // Decrypt private key with AES-128-CTR
124
+ const encryptionKey = derivedKey.slice(0, 16);
125
+ const cipher = ctr(encryptionKey, iv);
126
+ const privateKeyBytes = cipher.decrypt(ciphertext);
127
+ return toHex(privateKeyBytes);
128
+ }
45
129
  // ---------------------------------------------------------------------------
46
130
  // Proxy backend — HMAC-authenticated HTTP to a keyring proxy server
47
131
  // ---------------------------------------------------------------------------
@@ -86,20 +170,17 @@ export async function detectBackend() {
86
170
  return 'encrypted-file';
87
171
  }
88
172
  // ---------------------------------------------------------------------------
89
- // Encrypted V3 JSON Keystore backend (ethers.js built-in)
173
+ // Encrypted V3 JSON Keystore backend
90
174
  // ---------------------------------------------------------------------------
91
- async function encryptedFileStore(privateKey, address, password, filePath) {
92
- const account = { address, privateKey };
93
- // ethers v6: encryptKeystoreJsonSync or encryptKeystoreJson
94
- const json = await ethers.encryptKeystoreJson(account, password);
175
+ async function encryptedFileStore(privateKey, password, filePath) {
176
+ const json = await encryptKeystore(privateKey, password);
95
177
  fs.writeFileSync(filePath, json, { mode: 0o600 }); // Owner-only read/write
96
178
  }
97
179
  async function encryptedFileLoad(password, filePath) {
98
180
  if (!fs.existsSync(filePath))
99
181
  return null;
100
182
  const json = fs.readFileSync(filePath, 'utf-8');
101
- const wallet = await ethers.Wallet.fromEncryptedJson(json, password);
102
- return wallet.privateKey;
183
+ return decryptKeystore(json, password);
103
184
  }
104
185
  function encryptedFileExists(filePath) {
105
186
  return fs.existsSync(filePath);
@@ -116,8 +197,8 @@ function deriveMachinePassword() {
116
197
  const factors = [
117
198
  process.env.USER || process.env.USERNAME || 'agent',
118
199
  process.env.HOME || process.env.USERPROFILE || '/tmp',
119
- require('os').hostname(),
120
- require('os').platform(),
200
+ os.hostname(),
201
+ os.platform(),
121
202
  ];
122
203
  return crypto
123
204
  .createHash('sha256')
@@ -138,13 +219,13 @@ export async function createWallet(config = {}) {
138
219
  const data = await proxyRequest(config, '/create-wallet');
139
220
  return { address: data.address, backend, keystorePath: undefined };
140
221
  }
141
- const wallet = ethers.Wallet.createRandom();
142
- const privateKey = wallet.privateKey;
143
- const address = wallet.address;
222
+ const privateKey = generatePrivateKey();
223
+ const account = privateKeyToAccount(privateKey);
224
+ const address = account.address;
144
225
  switch (backend) {
145
226
  case 'encrypted-file': {
146
227
  const password = config.password || process.env.KEYSTORE_PASSWORD || deriveMachinePassword();
147
- await encryptedFileStore(privateKey, address, password, keystorePath);
228
+ await encryptedFileStore(privateKey, password, keystorePath);
148
229
  break;
149
230
  }
150
231
  case 'env':
@@ -173,12 +254,13 @@ export async function importWallet(privateKey, config = {}) {
173
254
  throw new Error('importWallet() is not supported via proxy. Import the wallet on the proxy server directly.');
174
255
  }
175
256
  const keystorePath = config.keystorePath || process.env.KEYSTORE_PATH || DEFAULT_KEYSTORE_PATH;
176
- const wallet = new ethers.Wallet(privateKey);
177
- const address = wallet.address;
257
+ const hexKey = (privateKey.startsWith('0x') ? privateKey : `0x${privateKey}`);
258
+ const account = privateKeyToAccount(hexKey);
259
+ const address = account.address;
178
260
  switch (backend) {
179
261
  case 'encrypted-file': {
180
262
  const password = config.password || process.env.KEYSTORE_PASSWORD || deriveMachinePassword();
181
- await encryptedFileStore(privateKey, address, password, keystorePath);
263
+ await encryptedFileStore(hexKey, password, keystorePath);
182
264
  break;
183
265
  }
184
266
  case 'env':
@@ -217,12 +299,11 @@ export async function getAddress(config = {}) {
217
299
  const data = await proxyRequest(config, '/get-address');
218
300
  return data.address;
219
301
  }
220
- const wallet = await _loadWalletInternal(config);
221
- if (!wallet)
302
+ const privateKey = await _loadPrivateKeyInternal(config);
303
+ if (!privateKey)
222
304
  return null;
223
- const address = wallet.address;
224
- // wallet goes out of scope and is GC'd — private key not returned
225
- return address;
305
+ const account = privateKeyToAccount(privateKey);
306
+ return account.address;
226
307
  }
227
308
  /**
228
309
  * Sign a message (EIP-191 personal_sign).
@@ -235,13 +316,12 @@ export async function signMessage(message, config = {}) {
235
316
  const data = await proxyRequest(config, '/sign-message', { message });
236
317
  return { signature: data.signature, address: data.address };
237
318
  }
238
- const wallet = await _loadWalletInternal(config);
239
- if (!wallet)
319
+ const privateKey = await _loadPrivateKeyInternal(config);
320
+ if (!privateKey)
240
321
  throw new Error('No wallet found. Run createWallet() first.');
241
- const signature = await wallet.signMessage(message);
242
- const address = wallet.address;
243
- // wallet goes out of scope — private key discarded
244
- return { signature, address };
322
+ const account = privateKeyToAccount(privateKey);
323
+ const signature = await account.signMessage({ message });
324
+ return { signature, address: account.address };
245
325
  }
246
326
  /**
247
327
  * Sign a transaction.
@@ -254,16 +334,37 @@ export async function signTransaction(tx, config = {}) {
254
334
  const data = await proxyRequest(config, '/sign-transaction', { tx: tx });
255
335
  return { signedTx: data.signedTx, address: data.address };
256
336
  }
257
- const wallet = await _loadWalletInternal(config);
258
- if (!wallet)
337
+ const privateKey = await _loadPrivateKeyInternal(config);
338
+ if (!privateKey)
259
339
  throw new Error('No wallet found. Run createWallet() first.');
260
- const signedTx = await wallet.signTransaction(tx);
261
- const address = wallet.address;
262
- return { signedTx, address };
340
+ const account = privateKeyToAccount(privateKey);
341
+ // Build transaction request for viem
342
+ const viemTx = {
343
+ to: tx.to,
344
+ data: tx.data,
345
+ value: tx.value,
346
+ nonce: tx.nonce,
347
+ chainId: tx.chainId,
348
+ gas: tx.gasLimit ?? tx.gas,
349
+ };
350
+ // Handle EIP-1559 vs legacy transactions
351
+ if (tx.type === 2 || tx.maxFeePerGas !== undefined) {
352
+ viemTx.type = 'eip1559';
353
+ viemTx.maxFeePerGas = tx.maxFeePerGas;
354
+ viemTx.maxPriorityFeePerGas = tx.maxPriorityFeePerGas;
355
+ }
356
+ else if (tx.gasPrice !== undefined) {
357
+ viemTx.type = 'legacy';
358
+ viemTx.gasPrice = tx.gasPrice;
359
+ }
360
+ if (tx.accessList) {
361
+ viemTx.accessList = tx.accessList;
362
+ }
363
+ const signedTx = await account.signTransaction(viemTx);
364
+ return { signedTx, address: account.address };
263
365
  }
264
366
  /**
265
367
  * Sign an EIP-7702 authorization for delegating the EOA to a contract.
266
- * Requires ethers >= 6.14.3.
267
368
  *
268
369
  * This allows the agent's EOA to temporarily act as a smart contract
269
370
  * during a type 4 transaction. The private key is loaded, used, and
@@ -278,37 +379,54 @@ export async function signAuthorization(auth, config = {}) {
278
379
  const data = await proxyRequest(config, '/sign-authorization', { auth });
279
380
  return data;
280
381
  }
281
- const wallet = await _loadWalletInternal(config);
282
- if (!wallet)
382
+ const privateKey = await _loadPrivateKeyInternal(config);
383
+ if (!privateKey)
283
384
  throw new Error('No wallet found. Run createWallet() first.');
284
- // ethers v6.14.3+ exposes wallet.authorize()
285
- if (typeof wallet.authorize !== 'function') {
286
- throw new Error('wallet.authorize() not available. EIP-7702 requires ethers >= 6.14.3. ' +
287
- 'Run: pnpm add ethers@latest');
288
- }
289
- const authorization = await wallet.authorize({
290
- address: auth.address,
291
- ...(auth.chainId !== undefined && { chainId: auth.chainId }),
292
- ...(auth.nonce !== undefined && { nonce: auth.nonce }),
385
+ const account = privateKeyToAccount(privateKey);
386
+ // EIP-7702 authorization signing using viem experimental
387
+ const chainId = auth.chainId ?? 1;
388
+ const nonce = auth.nonce ?? 0;
389
+ // Hash the authorization struct according to EIP-7702
390
+ const authHash = hashAuthorization({
391
+ contractAddress: auth.address,
392
+ chainId,
393
+ nonce,
293
394
  });
294
- // wallet goes out of scope — private key discarded
295
- return authorization;
395
+ // Sign the authorization hash
396
+ const signature = await account.sign({ hash: authHash });
397
+ // Parse signature into r, s, yParity
398
+ const r = signature.slice(0, 66);
399
+ const s = `0x${signature.slice(66, 130)}`;
400
+ const v = parseInt(signature.slice(130, 132), 16);
401
+ const yParity = v - 27; // Convert v to yParity (0 or 1)
402
+ return {
403
+ address: auth.address,
404
+ nonce,
405
+ chainId,
406
+ yParity,
407
+ r,
408
+ s,
409
+ };
296
410
  }
297
411
  /**
298
- * Get a connected signer (for contract interactions).
299
- * NOTE: This returns a signer with the private key in memory.
412
+ * Get a wallet client for contract interactions.
413
+ * NOTE: This creates a client with the private key in memory.
300
414
  * Use only within a narrow scope and discard immediately.
301
415
  * Prefer signMessage() / signTransaction() when possible.
302
416
  */
303
- export async function getSigner(provider, config = {}) {
417
+ export async function getWalletClient(rpcUrl, config = {}) {
304
418
  const backend = config.backend || await detectBackend();
305
419
  if (backend === 'proxy') {
306
- throw new Error('getSigner() is not supported via proxy. The private key cannot be serialized over HTTP. Use signMessage() or signTransaction() instead.');
420
+ throw new Error('getWalletClient() is not supported via proxy. The private key cannot be serialized over HTTP. Use signMessage() or signTransaction() instead.');
307
421
  }
308
- const wallet = await _loadWalletInternal(config);
309
- if (!wallet)
422
+ const privateKey = await _loadPrivateKeyInternal(config);
423
+ if (!privateKey)
310
424
  throw new Error('No wallet found. Run createWallet() first.');
311
- return wallet.connect(provider);
425
+ const account = privateKeyToAccount(privateKey);
426
+ return createWalletClient({
427
+ account,
428
+ transport: http(rpcUrl),
429
+ });
312
430
  }
313
431
  /**
314
432
  * Delete the stored wallet from the active backend.
@@ -333,9 +451,9 @@ export async function deleteWallet(config = {}) {
333
451
  }
334
452
  }
335
453
  // ---------------------------------------------------------------------------
336
- // Internal — loads the wallet. NEVER exposed publicly.
454
+ // Internal — loads the private key. NEVER exposed publicly.
337
455
  // ---------------------------------------------------------------------------
338
- async function _loadWalletInternal(config = {}) {
456
+ async function _loadPrivateKeyInternal(config = {}) {
339
457
  const backend = config.backend || await detectBackend();
340
458
  const keystorePath = config.keystorePath || process.env.KEYSTORE_PATH || DEFAULT_KEYSTORE_PATH;
341
459
  let privateKey = null;
@@ -345,11 +463,13 @@ async function _loadWalletInternal(config = {}) {
345
463
  privateKey = await encryptedFileLoad(password, keystorePath);
346
464
  break;
347
465
  }
348
- case 'env':
349
- privateKey = process.env.AGENT_PRIVATE_KEY || null;
466
+ case 'env': {
467
+ const envKey = process.env.AGENT_PRIVATE_KEY || null;
468
+ if (envKey) {
469
+ privateKey = (envKey.startsWith('0x') ? envKey : `0x${envKey}`);
470
+ }
350
471
  break;
472
+ }
351
473
  }
352
- if (!privateKey)
353
- return null;
354
- return new ethers.Wallet(privateKey);
474
+ return privateKey;
355
475
  }
@@ -10,8 +10,8 @@
10
10
  * - Constant-time comparison via crypto.timingSafeEqual
11
11
  */
12
12
  export interface HmacHeaders {
13
- 'X-Proxy-Timestamp': string;
14
- 'X-Proxy-Signature': string;
13
+ 'X-Keyring-Timestamp': string;
14
+ 'X-Keyring-Signature': string;
15
15
  }
16
16
  /**
17
17
  * Compute HMAC-SHA256 headers for an outgoing request.
@@ -22,8 +22,8 @@ export function computeHmac(secret, method, path, body) {
22
22
  .update(payload)
23
23
  .digest('hex');
24
24
  return {
25
- 'X-Proxy-Timestamp': timestamp,
26
- 'X-Proxy-Signature': signature,
25
+ 'X-Keyring-Timestamp': timestamp,
26
+ 'X-Keyring-Signature': signature,
27
27
  };
28
28
  }
29
29
  /**
@@ -46,8 +46,8 @@ export function verifyHmac(secret, method, path, body, timestamp, signature) {
46
46
  .update(payload)
47
47
  .digest('hex');
48
48
  // Constant-time comparison
49
- const sigBuf = Buffer.from(signature, 'utf-8');
50
- const expBuf = Buffer.from(expected, 'utf-8');
49
+ const sigBuf = new Uint8Array(Buffer.from(signature, 'utf-8'));
50
+ const expBuf = new Uint8Array(Buffer.from(expected, 'utf-8'));
51
51
  if (sigBuf.length !== expBuf.length) {
52
52
  return { valid: false, error: 'Signature mismatch' };
53
53
  }
@@ -5,9 +5,9 @@
5
5
  * Provides functions to read agent profiles and reputation from on-chain registries.
6
6
  *
7
7
  * Dependencies:
8
- * npm install ethers
8
+ * npm install viem
9
9
  */
10
- import { ethers } from 'ethers';
10
+ import { type PublicClient } from 'viem';
11
11
  /** Service endpoint types defined in ERC-8004 */
12
12
  export type ServiceType = 'web' | 'A2A' | 'MCP' | 'OASF' | 'ENS' | 'DID' | 'email';
13
13
  /** Trust models defined in ERC-8004 */
@@ -42,7 +42,7 @@ export interface AgentProfile {
42
42
  }
43
43
  export interface GetAgentOptions {
44
44
  registryAddress: string;
45
- provider: ethers.Provider;
45
+ client: PublicClient;
46
46
  fetchMetadata?: boolean;
47
47
  }
48
48
  export interface ReputationSummary {
@@ -53,7 +53,7 @@ export interface ReputationSummary {
53
53
  }
54
54
  export interface GetReputationOptions {
55
55
  reputationRegistryAddress: string;
56
- provider: ethers.Provider;
56
+ client: PublicClient;
57
57
  clients?: string[];
58
58
  tag1?: ReputationTag | (string & {});
59
59
  tag2?: string;
@@ -62,13 +62,13 @@ export interface GetReputationOptions {
62
62
  * Read an agent from the Identity Registry and parse its profile.
63
63
  *
64
64
  * @param agentId The on-chain agent token ID
65
- * @param options Registry address, provider, and optional fetchMetadata flag
65
+ * @param options Registry address, client, and optional fetchMetadata flag
66
66
  */
67
67
  export declare function getAgent(agentId: number, options: GetAgentOptions): Promise<AgentProfile>;
68
68
  /**
69
69
  * Read an agent's reputation summary from the Reputation Registry.
70
70
  *
71
71
  * @param agentId The on-chain agent token ID
72
- * @param options Reputation registry address, provider, and optional filters
72
+ * @param options Reputation registry address, client, and optional filters
73
73
  */
74
74
  export declare function getReputation(agentId: number, options: GetReputationOptions): Promise<ReputationSummary>;
package/dist/registry.js CHANGED
@@ -5,17 +5,50 @@
5
5
  * Provides functions to read agent profiles and reputation from on-chain registries.
6
6
  *
7
7
  * Dependencies:
8
- * npm install ethers
8
+ * npm install viem
9
9
  */
10
- import { ethers } from 'ethers';
10
+ import { zeroAddress, } from 'viem';
11
11
  // ─── ABI Fragments ──────────────────────────────────────────────────
12
12
  const IDENTITY_REGISTRY_ABI = [
13
- 'function ownerOf(uint256 tokenId) view returns (address)',
14
- 'function tokenURI(uint256 tokenId) view returns (string)',
15
- 'function getAgentWallet(uint256 agentId) view returns (address)',
13
+ {
14
+ name: 'ownerOf',
15
+ type: 'function',
16
+ stateMutability: 'view',
17
+ inputs: [{ name: 'tokenId', type: 'uint256' }],
18
+ outputs: [{ name: '', type: 'address' }],
19
+ },
20
+ {
21
+ name: 'tokenURI',
22
+ type: 'function',
23
+ stateMutability: 'view',
24
+ inputs: [{ name: 'tokenId', type: 'uint256' }],
25
+ outputs: [{ name: '', type: 'string' }],
26
+ },
27
+ {
28
+ name: 'getAgentWallet',
29
+ type: 'function',
30
+ stateMutability: 'view',
31
+ inputs: [{ name: 'agentId', type: 'uint256' }],
32
+ outputs: [{ name: '', type: 'address' }],
33
+ },
16
34
  ];
17
35
  const REPUTATION_REGISTRY_ABI = [
18
- 'function getSummary(uint256 agentId, address[] clients, string tag1, string tag2) view returns (uint64 count, int128 summaryValue, uint8 valueDecimals)',
36
+ {
37
+ name: 'getSummary',
38
+ type: 'function',
39
+ stateMutability: 'view',
40
+ inputs: [
41
+ { name: 'agentId', type: 'uint256' },
42
+ { name: 'clients', type: 'address[]' },
43
+ { name: 'tag1', type: 'string' },
44
+ { name: 'tag2', type: 'string' },
45
+ ],
46
+ outputs: [
47
+ { name: 'count', type: 'uint64' },
48
+ { name: 'summaryValue', type: 'int128' },
49
+ { name: 'valueDecimals', type: 'uint8' },
50
+ ],
51
+ },
19
52
  ];
20
53
  // ─── Internal Helpers ───────────────────────────────────────────────
21
54
  const IPFS_GATEWAY = 'https://gateway.pinata.cloud/ipfs/';
@@ -49,17 +82,31 @@ async function resolveURI(uri) {
49
82
  * Read an agent from the Identity Registry and parse its profile.
50
83
  *
51
84
  * @param agentId The on-chain agent token ID
52
- * @param options Registry address, provider, and optional fetchMetadata flag
85
+ * @param options Registry address, client, and optional fetchMetadata flag
53
86
  */
54
87
  export async function getAgent(agentId, options) {
55
- const { registryAddress, provider, fetchMetadata = true } = options;
56
- const registry = new ethers.Contract(registryAddress, IDENTITY_REGISTRY_ABI, provider);
88
+ const { registryAddress, client, fetchMetadata = true } = options;
57
89
  const [owner, uri, walletAddr] = await Promise.all([
58
- registry.ownerOf(agentId),
59
- registry.tokenURI(agentId),
60
- registry.getAgentWallet(agentId),
90
+ client.readContract({
91
+ address: registryAddress,
92
+ abi: IDENTITY_REGISTRY_ABI,
93
+ functionName: 'ownerOf',
94
+ args: [BigInt(agentId)],
95
+ }),
96
+ client.readContract({
97
+ address: registryAddress,
98
+ abi: IDENTITY_REGISTRY_ABI,
99
+ functionName: 'tokenURI',
100
+ args: [BigInt(agentId)],
101
+ }),
102
+ client.readContract({
103
+ address: registryAddress,
104
+ abi: IDENTITY_REGISTRY_ABI,
105
+ functionName: 'getAgentWallet',
106
+ args: [BigInt(agentId)],
107
+ }),
61
108
  ]);
62
- const agentWallet = walletAddr === ethers.ZeroAddress ? null : walletAddr;
109
+ const agentWallet = walletAddr === zeroAddress ? null : walletAddr;
63
110
  let metadata = null;
64
111
  if (fetchMetadata) {
65
112
  try {
@@ -76,12 +123,17 @@ export async function getAgent(agentId, options) {
76
123
  * Read an agent's reputation summary from the Reputation Registry.
77
124
  *
78
125
  * @param agentId The on-chain agent token ID
79
- * @param options Reputation registry address, provider, and optional filters
126
+ * @param options Reputation registry address, client, and optional filters
80
127
  */
81
128
  export async function getReputation(agentId, options) {
82
- const { reputationRegistryAddress, provider, clients = [], tag1 = '', tag2 = '', } = options;
83
- const reputation = new ethers.Contract(reputationRegistryAddress, REPUTATION_REGISTRY_ABI, provider);
84
- const [count, summaryValue, valueDecimals] = await reputation.getSummary(agentId, clients, tag1, tag2);
129
+ const { reputationRegistryAddress, client, clients = [], tag1 = '', tag2 = '', } = options;
130
+ const result = await client.readContract({
131
+ address: reputationRegistryAddress,
132
+ abi: REPUTATION_REGISTRY_ABI,
133
+ functionName: 'getSummary',
134
+ args: [BigInt(agentId), clients, tag1, tag2],
135
+ });
136
+ const [count, summaryValue, valueDecimals] = result;
85
137
  const decimals = Number(valueDecimals);
86
138
  const rawValue = BigInt(summaryValue);
87
139
  const score = Number(rawValue) / 10 ** decimals;
package/dist/siwa.d.ts CHANGED
@@ -5,9 +5,9 @@
5
5
  * Provides message building, signing (agent-side), and verification (server-side).
6
6
  *
7
7
  * Dependencies:
8
- * npm install ethers
8
+ * npm install viem
9
9
  */
10
- import { ethers } from 'ethers';
10
+ import { type PublicClient } from 'viem';
11
11
  import { AgentProfile, ServiceType, TrustModel } from './registry.js';
12
12
  export interface SIWAMessageFields {
13
13
  domain: string;
@@ -93,7 +93,7 @@ export declare function signSIWAMessageUnsafe(privateKey: string, fields: SIWAMe
93
93
  * @param signature EIP-191 signature hex string
94
94
  * @param expectedDomain The server's domain (for domain binding)
95
95
  * @param nonceValid Callback that returns true if the nonce is valid and unconsumed
96
- * @param provider ethers Provider for onchain verification
96
+ * @param client viem PublicClient for onchain verification
97
97
  * @param criteria Optional criteria to validate agent profile/reputation after ownership check
98
98
  */
99
- export declare function verifySIWA(message: string, signature: string, expectedDomain: string, nonceValid: (nonce: string) => boolean | Promise<boolean>, provider: ethers.Provider, criteria?: SIWAVerifyCriteria): Promise<SIWAVerificationResult>;
99
+ export declare function verifySIWA(message: string, signature: string, expectedDomain: string, nonceValid: (nonce: string) => boolean | Promise<boolean>, client: PublicClient, criteria?: SIWAVerifyCriteria): Promise<SIWAVerificationResult>;
package/dist/siwa.js CHANGED
@@ -5,9 +5,10 @@
5
5
  * Provides message building, signing (agent-side), and verification (server-side).
6
6
  *
7
7
  * Dependencies:
8
- * npm install ethers
8
+ * npm install viem
9
9
  */
10
- import { ethers } from 'ethers';
10
+ import { verifyMessage, hashMessage, } from 'viem';
11
+ import { privateKeyToAccount } from 'viem/accounts';
11
12
  import * as crypto from 'crypto';
12
13
  import { getAgent, getReputation } from './registry.js';
13
14
  // ─── Message Construction ────────────────────────────────────────────
@@ -136,12 +137,13 @@ export async function signSIWAMessage(fields, keystoreConfig) {
136
137
  * Kept only for server-side testing or environments without keystore.
137
138
  */
138
139
  export async function signSIWAMessageUnsafe(privateKey, fields) {
139
- const wallet = new ethers.Wallet(privateKey);
140
- if (wallet.address.toLowerCase() !== fields.address.toLowerCase()) {
141
- throw new Error(`Address mismatch: wallet is ${wallet.address}, message says ${fields.address}`);
140
+ const hexKey = (privateKey.startsWith('0x') ? privateKey : `0x${privateKey}`);
141
+ const account = privateKeyToAccount(hexKey);
142
+ if (account.address.toLowerCase() !== fields.address.toLowerCase()) {
143
+ throw new Error(`Address mismatch: wallet is ${account.address}, message says ${fields.address}`);
142
144
  }
143
145
  const message = buildSIWAMessage(fields);
144
- const signature = await wallet.signMessage(message);
146
+ const signature = await account.signMessage({ message });
145
147
  return { message, signature };
146
148
  }
147
149
  // ─── Server-Side Verification ────────────────────────────────────────
@@ -161,19 +163,24 @@ export async function signSIWAMessageUnsafe(privateKey, fields) {
161
163
  * @param signature EIP-191 signature hex string
162
164
  * @param expectedDomain The server's domain (for domain binding)
163
165
  * @param nonceValid Callback that returns true if the nonce is valid and unconsumed
164
- * @param provider ethers Provider for onchain verification
166
+ * @param client viem PublicClient for onchain verification
165
167
  * @param criteria Optional criteria to validate agent profile/reputation after ownership check
166
168
  */
167
- export async function verifySIWA(message, signature, expectedDomain, nonceValid, provider, criteria) {
169
+ export async function verifySIWA(message, signature, expectedDomain, nonceValid, client, criteria) {
168
170
  try {
169
171
  // 1. Parse
170
172
  const fields = parseSIWAMessage(message);
171
173
  // 2. Recover signer
172
- const recovered = ethers.verifyMessage(message, signature);
173
- // 3. Address match
174
- if (recovered.toLowerCase() !== fields.address.toLowerCase()) {
175
- return { valid: false, address: recovered, agentId: fields.agentId, agentRegistry: fields.agentRegistry, chainId: fields.chainId, error: 'Recovered address does not match message address' };
174
+ const isValid = await verifyMessage({
175
+ address: fields.address,
176
+ message,
177
+ signature: signature,
178
+ });
179
+ if (!isValid) {
180
+ return { valid: false, address: fields.address, agentId: fields.agentId, agentRegistry: fields.agentRegistry, chainId: fields.chainId, error: 'Invalid signature' };
176
181
  }
182
+ const recovered = fields.address;
183
+ // 3. Address match is implicit in verifyMessage (it checks against the address)
177
184
  // 4. Domain binding
178
185
  if (fields.domain !== expectedDomain) {
179
186
  return { valid: false, address: recovered, agentId: fields.agentId, agentRegistry: fields.agentRegistry, chainId: fields.chainId, error: `Domain mismatch: expected ${expectedDomain}, got ${fields.domain}` };
@@ -197,16 +204,24 @@ export async function verifySIWA(message, signature, expectedDomain, nonceValid,
197
204
  return { valid: false, address: recovered, agentId: fields.agentId, agentRegistry: fields.agentRegistry, chainId: fields.chainId, error: 'Invalid agentRegistry format' };
198
205
  }
199
206
  const registryAddress = registryParts[2];
200
- const registry = new ethers.Contract(registryAddress, ['function ownerOf(uint256) view returns (address)'], provider);
201
- const owner = await registry.ownerOf(fields.agentId);
207
+ const owner = await client.readContract({
208
+ address: registryAddress,
209
+ abi: [{ name: 'ownerOf', type: 'function', stateMutability: 'view', inputs: [{ name: 'tokenId', type: 'uint256' }], outputs: [{ name: '', type: 'address' }] }],
210
+ functionName: 'ownerOf',
211
+ args: [BigInt(fields.agentId)],
212
+ });
202
213
  if (owner.toLowerCase() !== recovered.toLowerCase()) {
203
214
  // 7b. ERC-1271 fallback for smart contract wallets / EIP-7702 delegated accounts.
204
215
  // If ecrecover doesn't match the NFT owner, the owner may be a contract
205
216
  // that validates signatures via isValidSignature (ERC-1271).
206
- const messageHash = ethers.hashMessage(message);
217
+ const messageHash = hashMessage(message);
207
218
  try {
208
- const ownerContract = new ethers.Contract(owner, ['function isValidSignature(bytes32, bytes) view returns (bytes4)'], provider);
209
- const magicValue = await ownerContract.isValidSignature(messageHash, signature);
219
+ const magicValue = await client.readContract({
220
+ address: owner,
221
+ abi: [{ name: 'isValidSignature', type: 'function', stateMutability: 'view', inputs: [{ name: 'hash', type: 'bytes32' }, { name: 'signature', type: 'bytes' }], outputs: [{ name: '', type: 'bytes4' }] }],
222
+ functionName: 'isValidSignature',
223
+ args: [messageHash, signature],
224
+ });
210
225
  // ERC-1271 magic value: 0x1626ba7e
211
226
  if (magicValue !== '0x1626ba7e') {
212
227
  return { valid: false, address: recovered, agentId: fields.agentId, agentRegistry: fields.agentRegistry, chainId: fields.chainId, error: 'Signer is not the owner of this agent NFT (ERC-1271 check also failed)' };
@@ -230,7 +245,7 @@ export async function verifySIWA(message, signature, expectedDomain, nonceValid,
230
245
  return baseResult;
231
246
  const agent = await getAgent(fields.agentId, {
232
247
  registryAddress: registryAddress,
233
- provider,
248
+ client,
234
249
  fetchMetadata: true,
235
250
  });
236
251
  baseResult.agent = agent;
@@ -261,7 +276,7 @@ export async function verifySIWA(message, signature, expectedDomain, nonceValid,
261
276
  }
262
277
  const rep = await getReputation(fields.agentId, {
263
278
  reputationRegistryAddress: criteria.reputationRegistryAddress,
264
- provider,
279
+ client,
265
280
  });
266
281
  if (criteria.minFeedbackCount !== undefined && rep.count < criteria.minFeedbackCount) {
267
282
  return { ...baseResult, valid: false, error: `Agent feedback count ${rep.count} below minimum ${criteria.minFeedbackCount}` };
package/package.json CHANGED
@@ -1,27 +1,56 @@
1
1
  {
2
2
  "name": "@buildersgarden/siwa",
3
- "version": "0.0.1",
3
+ "version": "0.0.3",
4
4
  "type": "module",
5
5
  "exports": {
6
- ".": { "types": "./dist/index.d.ts", "default": "./dist/index.js" },
7
- "./keystore": { "types": "./dist/keystore.d.ts", "default": "./dist/keystore.js" },
8
- "./siwa": { "types": "./dist/siwa.d.ts", "default": "./dist/siwa.js" },
9
- "./memory": { "types": "./dist/memory.d.ts", "default": "./dist/memory.js" },
10
- "./proxy-auth": { "types": "./dist/proxy-auth.d.ts", "default": "./dist/proxy-auth.js" },
11
- "./registry": { "types": "./dist/registry.d.ts", "default": "./dist/registry.js" }
6
+ ".": {
7
+ "types": "./dist/index.d.ts",
8
+ "default": "./dist/index.js"
9
+ },
10
+ "./keystore": {
11
+ "types": "./dist/keystore.d.ts",
12
+ "default": "./dist/keystore.js"
13
+ },
14
+ "./siwa": {
15
+ "types": "./dist/siwa.d.ts",
16
+ "default": "./dist/siwa.js"
17
+ },
18
+ "./memory": {
19
+ "types": "./dist/memory.d.ts",
20
+ "default": "./dist/memory.js"
21
+ },
22
+ "./proxy-auth": {
23
+ "types": "./dist/proxy-auth.d.ts",
24
+ "default": "./dist/proxy-auth.js"
25
+ },
26
+ "./registry": {
27
+ "types": "./dist/registry.d.ts",
28
+ "default": "./dist/registry.js"
29
+ },
30
+ "./addresses": {
31
+ "types": "./dist/addresses.d.ts",
32
+ "default": "./dist/addresses.js"
33
+ }
12
34
  },
13
35
  "main": "./dist/index.js",
14
36
  "types": "./dist/index.d.ts",
15
- "files": ["dist"],
16
- "publishConfig": { "access": "public" },
17
- "scripts": {
18
- "build": "tsc",
19
- "clean": "rm -rf dist"
37
+ "files": [
38
+ "dist"
39
+ ],
40
+ "publishConfig": {
41
+ "access": "public"
20
42
  },
21
43
  "dependencies": {
22
- "ethers": "^6.14.3"
44
+ "@noble/ciphers": "^0.5.0",
45
+ "@noble/hashes": "^1.4.0",
46
+ "viem": "^2.21.0"
23
47
  },
24
48
  "devDependencies": {
49
+ "@types/node": "^25.2.1",
25
50
  "typescript": "^5.5.0"
51
+ },
52
+ "scripts": {
53
+ "build": "tsc",
54
+ "clean": "rm -rf dist"
26
55
  }
27
- }
56
+ }