@buildersgarden/siwa 0.0.3 → 0.0.5

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.
@@ -34,8 +34,8 @@
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 { type WalletClient, type Account, type Chain, type Transport } from 'viem';
38
- export type KeystoreBackend = 'encrypted-file' | 'env' | 'proxy';
37
+ import { type WalletClient, type Account, type Chain, type Transport } from "viem";
38
+ export type KeystoreBackend = "encrypted-file" | "env" | "proxy";
39
39
  export interface KeystoreConfig {
40
40
  backend?: KeystoreBackend;
41
41
  keystorePath?: string;
package/dist/keystore.js CHANGED
@@ -34,20 +34,20 @@
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 { 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';
43
- import * as fs from 'fs';
44
- import * as crypto from 'crypto';
45
- import * as os from 'os';
46
- import { computeHmac } from './proxy-auth.js';
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";
43
+ import * as fs from "fs";
44
+ import * as crypto from "crypto";
45
+ import * as os from "os";
46
+ import { computeHmac } from "./proxy-auth.js";
47
47
  // ---------------------------------------------------------------------------
48
48
  // Constants
49
49
  // ---------------------------------------------------------------------------
50
- const DEFAULT_KEYSTORE_PATH = './agent-keystore.json';
50
+ const DEFAULT_KEYSTORE_PATH = "./agent-keystore.json";
51
51
  function generateUUID() {
52
52
  const bytes = randomBytes(16);
53
53
  bytes[6] = (bytes[6] & 0x0f) | 0x40; // version 4
@@ -65,13 +65,21 @@ async function encryptKeystore(privateKey, password) {
65
65
  const p = 1;
66
66
  const dklen = 32;
67
67
  // Derive key using scrypt
68
- const derivedKey = scrypt(new TextEncoder().encode(password), salt, { N: n, r, p, dkLen: dklen });
68
+ const derivedKey = scrypt(new TextEncoder().encode(password), salt, {
69
+ N: n,
70
+ r,
71
+ p,
72
+ dkLen: dklen,
73
+ });
69
74
  // Encrypt private key with AES-128-CTR
70
75
  const encryptionKey = derivedKey.slice(0, 16);
71
76
  const cipher = ctr(encryptionKey, iv);
72
77
  const ciphertext = cipher.encrypt(privateKeyBytes);
73
78
  // Calculate MAC: keccak256(derivedKey[16:32] + ciphertext)
74
- const macData = concat([toHex(derivedKey.slice(16, 32)), toHex(ciphertext)]);
79
+ const macData = concat([
80
+ toHex(derivedKey.slice(16, 32)),
81
+ toHex(ciphertext),
82
+ ]);
75
83
  const mac = keccak256(macData);
76
84
  // Get address from private key
77
85
  const account = privateKeyToAccount(privateKey);
@@ -82,8 +90,8 @@ async function encryptKeystore(privateKey, password) {
82
90
  crypto: {
83
91
  ciphertext: toHex(ciphertext).slice(2),
84
92
  cipherparams: { iv: toHex(iv).slice(2) },
85
- cipher: 'aes-128-ctr',
86
- kdf: 'scrypt',
93
+ cipher: "aes-128-ctr",
94
+ kdf: "scrypt",
87
95
  kdfparams: {
88
96
  dklen,
89
97
  salt: toHex(salt).slice(2),
@@ -102,10 +110,10 @@ async function decryptKeystore(json, password) {
102
110
  throw new Error(`Unsupported keystore version: ${keystore.version}`);
103
111
  }
104
112
  const { crypto: cryptoData } = keystore;
105
- if (cryptoData.kdf !== 'scrypt') {
113
+ if (cryptoData.kdf !== "scrypt") {
106
114
  throw new Error(`Unsupported KDF: ${cryptoData.kdf}`);
107
115
  }
108
- if (cryptoData.cipher !== 'aes-128-ctr') {
116
+ if (cryptoData.cipher !== "aes-128-ctr") {
109
117
  throw new Error(`Unsupported cipher: ${cryptoData.cipher}`);
110
118
  }
111
119
  const { kdfparams } = cryptoData;
@@ -113,12 +121,20 @@ async function decryptKeystore(json, password) {
113
121
  const iv = toBytes(`0x${cryptoData.cipherparams.iv}`);
114
122
  const ciphertext = toBytes(`0x${cryptoData.ciphertext}`);
115
123
  // 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 });
124
+ const derivedKey = scrypt(new TextEncoder().encode(password), salt, {
125
+ N: kdfparams.n,
126
+ r: kdfparams.r,
127
+ p: kdfparams.p,
128
+ dkLen: kdfparams.dklen,
129
+ });
117
130
  // Verify MAC
118
- const macData = concat([toHex(derivedKey.slice(16, 32)), toHex(ciphertext)]);
131
+ const macData = concat([
132
+ toHex(derivedKey.slice(16, 32)),
133
+ toHex(ciphertext),
134
+ ]);
119
135
  const calculatedMac = keccak256(macData).slice(2);
120
136
  if (calculatedMac.toLowerCase() !== cryptoData.mac.toLowerCase()) {
121
- throw new Error('Invalid password or corrupted keystore');
137
+ throw new Error("Invalid password or corrupted keystore");
122
138
  }
123
139
  // Decrypt private key with AES-128-CTR
124
140
  const encryptionKey = derivedKey.slice(0, 16);
@@ -133,15 +149,15 @@ async function proxyRequest(config, endpoint, body = {}) {
133
149
  const url = config.proxyUrl || process.env.KEYRING_PROXY_URL;
134
150
  const secret = config.proxySecret || process.env.KEYRING_PROXY_SECRET;
135
151
  if (!url)
136
- throw new Error('Proxy backend requires KEYRING_PROXY_URL or config.proxyUrl');
152
+ throw new Error("Proxy backend requires KEYRING_PROXY_URL or config.proxyUrl");
137
153
  if (!secret)
138
- throw new Error('Proxy backend requires KEYRING_PROXY_SECRET or config.proxySecret');
139
- const bodyStr = JSON.stringify(body, (_key, value) => typeof value === 'bigint' ? '0x' + value.toString(16) : value);
140
- const hmacHeaders = computeHmac(secret, 'POST', endpoint, bodyStr);
154
+ throw new Error("Proxy backend requires KEYRING_PROXY_SECRET or config.proxySecret");
155
+ const bodyStr = JSON.stringify(body, (_key, value) => typeof value === "bigint" ? "0x" + value.toString(16) : value);
156
+ const hmacHeaders = computeHmac(secret, "POST", endpoint, bodyStr);
141
157
  const res = await fetch(`${url}${endpoint}`, {
142
- method: 'POST',
158
+ method: "POST",
143
159
  headers: {
144
- 'Content-Type': 'application/json',
160
+ "Content-Type": "application/json",
145
161
  ...hmacHeaders,
146
162
  },
147
163
  body: bodyStr,
@@ -158,16 +174,16 @@ async function proxyRequest(config, endpoint, body = {}) {
158
174
  export async function detectBackend() {
159
175
  // 0. Proxy backend (if URL is set)
160
176
  if (process.env.KEYRING_PROXY_URL)
161
- return 'proxy';
177
+ return "proxy";
162
178
  // 1. Check for existing encrypted keystore file
163
179
  if (fs.existsSync(process.env.KEYSTORE_PATH || DEFAULT_KEYSTORE_PATH)) {
164
- return 'encrypted-file';
180
+ return "encrypted-file";
165
181
  }
166
182
  // 2. Check for env var
167
183
  if (process.env.AGENT_PRIVATE_KEY)
168
- return 'env';
184
+ return "env";
169
185
  // 3. Default to encrypted-file (will be created on first use)
170
- return 'encrypted-file';
186
+ return "encrypted-file";
171
187
  }
172
188
  // ---------------------------------------------------------------------------
173
189
  // Encrypted V3 JSON Keystore backend
@@ -179,7 +195,7 @@ async function encryptedFileStore(privateKey, password, filePath) {
179
195
  async function encryptedFileLoad(password, filePath) {
180
196
  if (!fs.existsSync(filePath))
181
197
  return null;
182
- const json = fs.readFileSync(filePath, 'utf-8');
198
+ const json = fs.readFileSync(filePath, "utf-8");
183
199
  return decryptKeystore(json, password);
184
200
  }
185
201
  function encryptedFileExists(filePath) {
@@ -195,15 +211,12 @@ function encryptedFileExists(filePath) {
195
211
  // ---------------------------------------------------------------------------
196
212
  function deriveMachinePassword() {
197
213
  const factors = [
198
- process.env.USER || process.env.USERNAME || 'agent',
199
- process.env.HOME || process.env.USERPROFILE || '/tmp',
214
+ process.env.USER || process.env.USERNAME || "agent",
215
+ process.env.HOME || process.env.USERPROFILE || "/tmp",
200
216
  os.hostname(),
201
217
  os.platform(),
202
218
  ];
203
- return crypto
204
- .createHash('sha256')
205
- .update(factors.join(':'))
206
- .digest('hex');
219
+ return crypto.createHash("sha256").update(factors.join(":")).digest("hex");
207
220
  }
208
221
  // ---------------------------------------------------------------------------
209
222
  // Public API — the ONLY way external code touches private keys
@@ -213,34 +226,36 @@ function deriveMachinePassword() {
213
226
  * Returns only the public address — NEVER the private key.
214
227
  */
215
228
  export async function createWallet(config = {}) {
216
- const backend = config.backend || await detectBackend();
229
+ const backend = config.backend || (await detectBackend());
217
230
  const keystorePath = config.keystorePath || process.env.KEYSTORE_PATH || DEFAULT_KEYSTORE_PATH;
218
- if (backend === 'proxy') {
219
- const data = await proxyRequest(config, '/create-wallet');
231
+ if (backend === "proxy") {
232
+ const data = await proxyRequest(config, "/create-wallet");
220
233
  return { address: data.address, backend, keystorePath: undefined };
221
234
  }
222
235
  const privateKey = generatePrivateKey();
223
236
  const account = privateKeyToAccount(privateKey);
224
237
  const address = account.address;
225
238
  switch (backend) {
226
- case 'encrypted-file': {
227
- const password = config.password || process.env.KEYSTORE_PASSWORD || deriveMachinePassword();
239
+ case "encrypted-file": {
240
+ const password = config.password ||
241
+ process.env.KEYSTORE_PASSWORD ||
242
+ deriveMachinePassword();
228
243
  await encryptedFileStore(privateKey, password, keystorePath);
229
244
  break;
230
245
  }
231
- case 'env':
246
+ case "env":
232
247
  // For env backend, we print the key ONCE for the operator to capture.
233
248
  // This is the ONLY time the raw key is ever exposed.
234
- console.log('=== ENV BACKEND (testing only) ===');
249
+ console.log("=== ENV BACKEND (testing only) ===");
235
250
  console.log(`Set this in your environment:`);
236
251
  console.log(` export AGENT_PRIVATE_KEY="${privateKey}"`);
237
- console.log('=================================');
252
+ console.log("=================================");
238
253
  break;
239
254
  }
240
255
  return {
241
256
  address,
242
257
  backend,
243
- keystorePath: backend === 'encrypted-file' ? keystorePath : undefined,
258
+ keystorePath: backend === "encrypted-file" ? keystorePath : undefined,
244
259
  };
245
260
  }
246
261
  /**
@@ -249,44 +264,46 @@ export async function createWallet(config = {}) {
249
264
  * Returns only the public address.
250
265
  */
251
266
  export async function importWallet(privateKey, config = {}) {
252
- const backend = config.backend || await detectBackend();
253
- if (backend === 'proxy') {
254
- throw new Error('importWallet() is not supported via proxy. Import the wallet on the proxy server directly.');
267
+ const backend = config.backend || (await detectBackend());
268
+ if (backend === "proxy") {
269
+ throw new Error("importWallet() is not supported via proxy. Import the wallet on the proxy server directly.");
255
270
  }
256
271
  const keystorePath = config.keystorePath || process.env.KEYSTORE_PATH || DEFAULT_KEYSTORE_PATH;
257
- const hexKey = (privateKey.startsWith('0x') ? privateKey : `0x${privateKey}`);
272
+ const hexKey = (privateKey.startsWith("0x") ? privateKey : `0x${privateKey}`);
258
273
  const account = privateKeyToAccount(hexKey);
259
274
  const address = account.address;
260
275
  switch (backend) {
261
- case 'encrypted-file': {
262
- const password = config.password || process.env.KEYSTORE_PASSWORD || deriveMachinePassword();
276
+ case "encrypted-file": {
277
+ const password = config.password ||
278
+ process.env.KEYSTORE_PASSWORD ||
279
+ deriveMachinePassword();
263
280
  await encryptedFileStore(hexKey, password, keystorePath);
264
281
  break;
265
282
  }
266
- case 'env':
283
+ case "env":
267
284
  // Nothing to persist for env backend
268
285
  break;
269
286
  }
270
287
  return {
271
288
  address,
272
289
  backend,
273
- keystorePath: backend === 'encrypted-file' ? keystorePath : undefined,
290
+ keystorePath: backend === "encrypted-file" ? keystorePath : undefined,
274
291
  };
275
292
  }
276
293
  /**
277
294
  * Check if a wallet is available in any backend.
278
295
  */
279
296
  export async function hasWallet(config = {}) {
280
- const backend = config.backend || await detectBackend();
281
- if (backend === 'proxy') {
282
- const data = await proxyRequest(config, '/has-wallet');
297
+ const backend = config.backend || (await detectBackend());
298
+ if (backend === "proxy") {
299
+ const data = await proxyRequest(config, "/has-wallet");
283
300
  return data.hasWallet;
284
301
  }
285
302
  const keystorePath = config.keystorePath || process.env.KEYSTORE_PATH || DEFAULT_KEYSTORE_PATH;
286
303
  switch (backend) {
287
- case 'encrypted-file':
304
+ case "encrypted-file":
288
305
  return encryptedFileExists(keystorePath);
289
- case 'env':
306
+ case "env":
290
307
  return !!process.env.AGENT_PRIVATE_KEY;
291
308
  }
292
309
  }
@@ -294,9 +311,9 @@ export async function hasWallet(config = {}) {
294
311
  * Get the wallet's public address (no private key exposed).
295
312
  */
296
313
  export async function getAddress(config = {}) {
297
- const backend = config.backend || await detectBackend();
298
- if (backend === 'proxy') {
299
- const data = await proxyRequest(config, '/get-address');
314
+ const backend = config.backend || (await detectBackend());
315
+ if (backend === "proxy") {
316
+ const data = await proxyRequest(config, "/get-address");
300
317
  return data.address;
301
318
  }
302
319
  const privateKey = await _loadPrivateKeyInternal(config);
@@ -311,51 +328,101 @@ export async function getAddress(config = {}) {
311
328
  * Only the signature is returned.
312
329
  */
313
330
  export async function signMessage(message, config = {}) {
314
- const backend = config.backend || await detectBackend();
315
- if (backend === 'proxy') {
316
- const data = await proxyRequest(config, '/sign-message', { message });
331
+ const backend = config.backend || (await detectBackend());
332
+ if (backend === "proxy") {
333
+ const data = await proxyRequest(config, "/sign-message", { message });
317
334
  return { signature: data.signature, address: data.address };
318
335
  }
319
336
  const privateKey = await _loadPrivateKeyInternal(config);
320
337
  if (!privateKey)
321
- throw new Error('No wallet found. Run createWallet() first.');
338
+ throw new Error("No wallet found. Run createWallet() first.");
322
339
  const account = privateKeyToAccount(privateKey);
323
340
  const signature = await account.signMessage({ message });
324
341
  return { signature, address: account.address };
325
342
  }
343
+ /**
344
+ * Parse a numeric value from JSON (string/number) to bigint.
345
+ * Returns undefined for null, undefined, or zero values.
346
+ * Zero is returned as undefined so viem encodes it as empty (0x80 in RLP).
347
+ */
348
+ function parseBigIntFromJson(value) {
349
+ if (value === null || value === undefined)
350
+ return undefined;
351
+ let result;
352
+ if (typeof value === "bigint") {
353
+ result = value;
354
+ }
355
+ else if (typeof value === "number") {
356
+ result = BigInt(value);
357
+ }
358
+ else if (typeof value === "string") {
359
+ // Handle hex strings (0x...) and decimal strings
360
+ result = BigInt(value);
361
+ }
362
+ else {
363
+ return undefined;
364
+ }
365
+ // Return undefined for zero so viem encodes it as empty (0x80)
366
+ // instead of 0x00 which is non-canonical RLP
367
+ return result === 0n ? undefined : result;
368
+ }
369
+ /**
370
+ * Parse a numeric value, keeping zero as 0n (for fields like nonce where 0 is valid).
371
+ */
372
+ function parseBigIntKeepZero(value) {
373
+ if (value === null || value === undefined)
374
+ return undefined;
375
+ if (typeof value === "bigint")
376
+ return value;
377
+ if (typeof value === "number")
378
+ return BigInt(value);
379
+ if (typeof value === "string")
380
+ return BigInt(value);
381
+ return undefined;
382
+ }
326
383
  /**
327
384
  * Sign a transaction.
328
385
  * The private key is loaded, used, and immediately discarded.
329
386
  * Only the signed transaction is returned.
330
387
  */
331
388
  export async function signTransaction(tx, config = {}) {
332
- const backend = config.backend || await detectBackend();
333
- if (backend === 'proxy') {
334
- const data = await proxyRequest(config, '/sign-transaction', { tx: tx });
389
+ const backend = config.backend || (await detectBackend());
390
+ if (backend === "proxy") {
391
+ const data = await proxyRequest(config, "/sign-transaction", {
392
+ tx: tx,
393
+ });
335
394
  return { signedTx: data.signedTx, address: data.address };
336
395
  }
337
396
  const privateKey = await _loadPrivateKeyInternal(config);
338
397
  if (!privateKey)
339
- throw new Error('No wallet found. Run createWallet() first.');
398
+ throw new Error("No wallet found. Run createWallet() first.");
340
399
  const account = privateKeyToAccount(privateKey);
400
+ // Parse numeric fields from JSON representation (strings) to bigints.
401
+ // For 'value', zero is converted to undefined so viem encodes it as 0x80 (empty)
402
+ // instead of 0x00, which is non-canonical RLP and rejected by nodes.
403
+ const value = parseBigIntFromJson(tx.value);
404
+ const gas = parseBigIntKeepZero(tx.gasLimit ?? tx.gas);
405
+ const maxFeePerGas = parseBigIntKeepZero(tx.maxFeePerGas);
406
+ const maxPriorityFeePerGas = parseBigIntKeepZero(tx.maxPriorityFeePerGas);
407
+ const gasPrice = parseBigIntKeepZero(tx.gasPrice);
341
408
  // Build transaction request for viem
342
409
  const viemTx = {
343
410
  to: tx.to,
344
411
  data: tx.data,
345
- value: tx.value,
412
+ value,
346
413
  nonce: tx.nonce,
347
414
  chainId: tx.chainId,
348
- gas: tx.gasLimit ?? tx.gas,
415
+ gas,
349
416
  };
350
417
  // Handle EIP-1559 vs legacy transactions
351
418
  if (tx.type === 2 || tx.maxFeePerGas !== undefined) {
352
- viemTx.type = 'eip1559';
353
- viemTx.maxFeePerGas = tx.maxFeePerGas;
354
- viemTx.maxPriorityFeePerGas = tx.maxPriorityFeePerGas;
419
+ viemTx.type = "eip1559";
420
+ viemTx.maxFeePerGas = maxFeePerGas;
421
+ viemTx.maxPriorityFeePerGas = maxPriorityFeePerGas;
355
422
  }
356
423
  else if (tx.gasPrice !== undefined) {
357
- viemTx.type = 'legacy';
358
- viemTx.gasPrice = tx.gasPrice;
424
+ viemTx.type = "legacy";
425
+ viemTx.gasPrice = gasPrice;
359
426
  }
360
427
  if (tx.accessList) {
361
428
  viemTx.accessList = tx.accessList;
@@ -374,14 +441,14 @@ export async function signTransaction(tx, config = {}) {
374
441
  * @returns Signed authorization tuple (address, nonce, chainId, yParity, r, s)
375
442
  */
376
443
  export async function signAuthorization(auth, config = {}) {
377
- const backend = config.backend || await detectBackend();
378
- if (backend === 'proxy') {
379
- const data = await proxyRequest(config, '/sign-authorization', { auth });
444
+ const backend = config.backend || (await detectBackend());
445
+ if (backend === "proxy") {
446
+ const data = await proxyRequest(config, "/sign-authorization", { auth });
380
447
  return data;
381
448
  }
382
449
  const privateKey = await _loadPrivateKeyInternal(config);
383
450
  if (!privateKey)
384
- throw new Error('No wallet found. Run createWallet() first.');
451
+ throw new Error("No wallet found. Run createWallet() first.");
385
452
  const account = privateKeyToAccount(privateKey);
386
453
  // EIP-7702 authorization signing using viem experimental
387
454
  const chainId = auth.chainId ?? 1;
@@ -415,13 +482,13 @@ export async function signAuthorization(auth, config = {}) {
415
482
  * Prefer signMessage() / signTransaction() when possible.
416
483
  */
417
484
  export async function getWalletClient(rpcUrl, config = {}) {
418
- const backend = config.backend || await detectBackend();
419
- if (backend === 'proxy') {
420
- throw new Error('getWalletClient() is not supported via proxy. The private key cannot be serialized over HTTP. Use signMessage() or signTransaction() instead.');
485
+ const backend = config.backend || (await detectBackend());
486
+ if (backend === "proxy") {
487
+ throw new Error("getWalletClient() is not supported via proxy. The private key cannot be serialized over HTTP. Use signMessage() or signTransaction() instead.");
421
488
  }
422
489
  const privateKey = await _loadPrivateKeyInternal(config);
423
490
  if (!privateKey)
424
- throw new Error('No wallet found. Run createWallet() first.');
491
+ throw new Error("No wallet found. Run createWallet() first.");
425
492
  const account = privateKeyToAccount(privateKey);
426
493
  return createWalletClient({
427
494
  account,
@@ -433,20 +500,20 @@ export async function getWalletClient(rpcUrl, config = {}) {
433
500
  * DESTRUCTIVE — the identity is lost if no backup exists.
434
501
  */
435
502
  export async function deleteWallet(config = {}) {
436
- const backend = config.backend || await detectBackend();
437
- if (backend === 'proxy') {
438
- throw new Error('deleteWallet() is not supported via proxy. Delete the wallet on the proxy server directly.');
503
+ const backend = config.backend || (await detectBackend());
504
+ if (backend === "proxy") {
505
+ throw new Error("deleteWallet() is not supported via proxy. Delete the wallet on the proxy server directly.");
439
506
  }
440
507
  const keystorePath = config.keystorePath || process.env.KEYSTORE_PATH || DEFAULT_KEYSTORE_PATH;
441
508
  switch (backend) {
442
- case 'encrypted-file':
509
+ case "encrypted-file":
443
510
  if (fs.existsSync(keystorePath)) {
444
511
  fs.unlinkSync(keystorePath);
445
512
  return true;
446
513
  }
447
514
  return false;
448
- case 'env':
449
- console.warn('Cannot delete env-based wallet. Unset AGENT_PRIVATE_KEY manually.');
515
+ case "env":
516
+ console.warn("Cannot delete env-based wallet. Unset AGENT_PRIVATE_KEY manually.");
450
517
  return false;
451
518
  }
452
519
  }
@@ -454,19 +521,21 @@ export async function deleteWallet(config = {}) {
454
521
  // Internal — loads the private key. NEVER exposed publicly.
455
522
  // ---------------------------------------------------------------------------
456
523
  async function _loadPrivateKeyInternal(config = {}) {
457
- const backend = config.backend || await detectBackend();
524
+ const backend = config.backend || (await detectBackend());
458
525
  const keystorePath = config.keystorePath || process.env.KEYSTORE_PATH || DEFAULT_KEYSTORE_PATH;
459
526
  let privateKey = null;
460
527
  switch (backend) {
461
- case 'encrypted-file': {
462
- const password = config.password || process.env.KEYSTORE_PASSWORD || deriveMachinePassword();
528
+ case "encrypted-file": {
529
+ const password = config.password ||
530
+ process.env.KEYSTORE_PASSWORD ||
531
+ deriveMachinePassword();
463
532
  privateKey = await encryptedFileLoad(password, keystorePath);
464
533
  break;
465
534
  }
466
- case 'env': {
535
+ case "env": {
467
536
  const envKey = process.env.AGENT_PRIVATE_KEY || null;
468
537
  if (envKey) {
469
- privateKey = (envKey.startsWith('0x') ? envKey : `0x${envKey}`);
538
+ privateKey = (envKey.startsWith("0x") ? envKey : `0x${envKey}`);
470
539
  }
471
540
  break;
472
541
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@buildersgarden/siwa",
3
- "version": "0.0.3",
3
+ "version": "0.0.5",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": {
@@ -37,9 +37,18 @@
37
37
  "files": [
38
38
  "dist"
39
39
  ],
40
+ "repository": {
41
+ "type": "git",
42
+ "url": "https://github.com/builders-garden/siwa",
43
+ "directory": "packages/siwa"
44
+ },
40
45
  "publishConfig": {
41
46
  "access": "public"
42
47
  },
48
+ "scripts": {
49
+ "build": "tsc",
50
+ "clean": "rm -rf dist"
51
+ },
43
52
  "dependencies": {
44
53
  "@noble/ciphers": "^0.5.0",
45
54
  "@noble/hashes": "^1.4.0",
@@ -48,9 +57,5 @@
48
57
  "devDependencies": {
49
58
  "@types/node": "^25.2.1",
50
59
  "typescript": "^5.5.0"
51
- },
52
- "scripts": {
53
- "build": "tsc",
54
- "clean": "rm -rf dist"
55
60
  }
56
- }
61
+ }
package/LICENSE DELETED
@@ -1,21 +0,0 @@
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.