@buildersgarden/siwa 0.0.4 → 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,14 +328,14 @@ 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 };
@@ -332,13 +349,13 @@ function parseBigIntFromJson(value) {
332
349
  if (value === null || value === undefined)
333
350
  return undefined;
334
351
  let result;
335
- if (typeof value === 'bigint') {
352
+ if (typeof value === "bigint") {
336
353
  result = value;
337
354
  }
338
- else if (typeof value === 'number') {
355
+ else if (typeof value === "number") {
339
356
  result = BigInt(value);
340
357
  }
341
- else if (typeof value === 'string') {
358
+ else if (typeof value === "string") {
342
359
  // Handle hex strings (0x...) and decimal strings
343
360
  result = BigInt(value);
344
361
  }
@@ -355,11 +372,11 @@ function parseBigIntFromJson(value) {
355
372
  function parseBigIntKeepZero(value) {
356
373
  if (value === null || value === undefined)
357
374
  return undefined;
358
- if (typeof value === 'bigint')
375
+ if (typeof value === "bigint")
359
376
  return value;
360
- if (typeof value === 'number')
377
+ if (typeof value === "number")
361
378
  return BigInt(value);
362
- if (typeof value === 'string')
379
+ if (typeof value === "string")
363
380
  return BigInt(value);
364
381
  return undefined;
365
382
  }
@@ -369,14 +386,16 @@ function parseBigIntKeepZero(value) {
369
386
  * Only the signed transaction is returned.
370
387
  */
371
388
  export async function signTransaction(tx, config = {}) {
372
- const backend = config.backend || await detectBackend();
373
- if (backend === 'proxy') {
374
- 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
+ });
375
394
  return { signedTx: data.signedTx, address: data.address };
376
395
  }
377
396
  const privateKey = await _loadPrivateKeyInternal(config);
378
397
  if (!privateKey)
379
- throw new Error('No wallet found. Run createWallet() first.');
398
+ throw new Error("No wallet found. Run createWallet() first.");
380
399
  const account = privateKeyToAccount(privateKey);
381
400
  // Parse numeric fields from JSON representation (strings) to bigints.
382
401
  // For 'value', zero is converted to undefined so viem encodes it as 0x80 (empty)
@@ -397,12 +416,12 @@ export async function signTransaction(tx, config = {}) {
397
416
  };
398
417
  // Handle EIP-1559 vs legacy transactions
399
418
  if (tx.type === 2 || tx.maxFeePerGas !== undefined) {
400
- viemTx.type = 'eip1559';
419
+ viemTx.type = "eip1559";
401
420
  viemTx.maxFeePerGas = maxFeePerGas;
402
421
  viemTx.maxPriorityFeePerGas = maxPriorityFeePerGas;
403
422
  }
404
423
  else if (tx.gasPrice !== undefined) {
405
- viemTx.type = 'legacy';
424
+ viemTx.type = "legacy";
406
425
  viemTx.gasPrice = gasPrice;
407
426
  }
408
427
  if (tx.accessList) {
@@ -422,14 +441,14 @@ export async function signTransaction(tx, config = {}) {
422
441
  * @returns Signed authorization tuple (address, nonce, chainId, yParity, r, s)
423
442
  */
424
443
  export async function signAuthorization(auth, config = {}) {
425
- const backend = config.backend || await detectBackend();
426
- if (backend === 'proxy') {
427
- 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 });
428
447
  return data;
429
448
  }
430
449
  const privateKey = await _loadPrivateKeyInternal(config);
431
450
  if (!privateKey)
432
- throw new Error('No wallet found. Run createWallet() first.');
451
+ throw new Error("No wallet found. Run createWallet() first.");
433
452
  const account = privateKeyToAccount(privateKey);
434
453
  // EIP-7702 authorization signing using viem experimental
435
454
  const chainId = auth.chainId ?? 1;
@@ -463,13 +482,13 @@ export async function signAuthorization(auth, config = {}) {
463
482
  * Prefer signMessage() / signTransaction() when possible.
464
483
  */
465
484
  export async function getWalletClient(rpcUrl, config = {}) {
466
- const backend = config.backend || await detectBackend();
467
- if (backend === 'proxy') {
468
- 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.");
469
488
  }
470
489
  const privateKey = await _loadPrivateKeyInternal(config);
471
490
  if (!privateKey)
472
- throw new Error('No wallet found. Run createWallet() first.');
491
+ throw new Error("No wallet found. Run createWallet() first.");
473
492
  const account = privateKeyToAccount(privateKey);
474
493
  return createWalletClient({
475
494
  account,
@@ -481,20 +500,20 @@ export async function getWalletClient(rpcUrl, config = {}) {
481
500
  * DESTRUCTIVE — the identity is lost if no backup exists.
482
501
  */
483
502
  export async function deleteWallet(config = {}) {
484
- const backend = config.backend || await detectBackend();
485
- if (backend === 'proxy') {
486
- 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.");
487
506
  }
488
507
  const keystorePath = config.keystorePath || process.env.KEYSTORE_PATH || DEFAULT_KEYSTORE_PATH;
489
508
  switch (backend) {
490
- case 'encrypted-file':
509
+ case "encrypted-file":
491
510
  if (fs.existsSync(keystorePath)) {
492
511
  fs.unlinkSync(keystorePath);
493
512
  return true;
494
513
  }
495
514
  return false;
496
- case 'env':
497
- 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.");
498
517
  return false;
499
518
  }
500
519
  }
@@ -502,19 +521,21 @@ export async function deleteWallet(config = {}) {
502
521
  // Internal — loads the private key. NEVER exposed publicly.
503
522
  // ---------------------------------------------------------------------------
504
523
  async function _loadPrivateKeyInternal(config = {}) {
505
- const backend = config.backend || await detectBackend();
524
+ const backend = config.backend || (await detectBackend());
506
525
  const keystorePath = config.keystorePath || process.env.KEYSTORE_PATH || DEFAULT_KEYSTORE_PATH;
507
526
  let privateKey = null;
508
527
  switch (backend) {
509
- case 'encrypted-file': {
510
- 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();
511
532
  privateKey = await encryptedFileLoad(password, keystorePath);
512
533
  break;
513
534
  }
514
- case 'env': {
535
+ case "env": {
515
536
  const envKey = process.env.AGENT_PRIVATE_KEY || null;
516
537
  if (envKey) {
517
- privateKey = (envKey.startsWith('0x') ? envKey : `0x${envKey}`);
538
+ privateKey = (envKey.startsWith("0x") ? envKey : `0x${envKey}`);
518
539
  }
519
540
  break;
520
541
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@buildersgarden/siwa",
3
- "version": "0.0.4",
3
+ "version": "0.0.5",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": {