@buildersgarden/siwa 0.0.2 → 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 +21 -0
- package/README.md +1 -1
- package/dist/keystore.d.ts +23 -10
- package/dist/keystore.js +182 -63
- package/dist/proxy-auth.js +2 -2
- package/dist/registry.d.ts +6 -6
- package/dist/registry.js +69 -17
- package/dist/siwa.d.ts +4 -4
- package/dist/siwa.js +34 -19
- package/package.json +43 -15
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
|
-
- **
|
|
67
|
+
- **viem** — wallet management and contract interaction
|
|
68
68
|
- **pnpm** — package manager
|
|
69
69
|
|
|
70
70
|
## References
|
package/dist/keystore.d.ts
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
|
|
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
|
|
22
|
-
* Wallets are standard EOAs created via
|
|
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
|
|
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 {
|
|
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:
|
|
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
|
|
117
|
-
* NOTE: This
|
|
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
|
|
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
|
|
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
|
|
22
|
-
* Wallets are standard EOAs created via
|
|
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
|
|
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,12 @@
|
|
|
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 {
|
|
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';
|
|
40
45
|
import * as os from 'os';
|
|
@@ -43,6 +48,84 @@ import { computeHmac } from './proxy-auth.js';
|
|
|
43
48
|
// Constants
|
|
44
49
|
// ---------------------------------------------------------------------------
|
|
45
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
|
+
}
|
|
46
129
|
// ---------------------------------------------------------------------------
|
|
47
130
|
// Proxy backend — HMAC-authenticated HTTP to a keyring proxy server
|
|
48
131
|
// ---------------------------------------------------------------------------
|
|
@@ -87,20 +170,17 @@ export async function detectBackend() {
|
|
|
87
170
|
return 'encrypted-file';
|
|
88
171
|
}
|
|
89
172
|
// ---------------------------------------------------------------------------
|
|
90
|
-
// Encrypted V3 JSON Keystore backend
|
|
173
|
+
// Encrypted V3 JSON Keystore backend
|
|
91
174
|
// ---------------------------------------------------------------------------
|
|
92
|
-
async function encryptedFileStore(privateKey,
|
|
93
|
-
const
|
|
94
|
-
// ethers v6: encryptKeystoreJsonSync or encryptKeystoreJson
|
|
95
|
-
const json = await ethers.encryptKeystoreJson(account, password);
|
|
175
|
+
async function encryptedFileStore(privateKey, password, filePath) {
|
|
176
|
+
const json = await encryptKeystore(privateKey, password);
|
|
96
177
|
fs.writeFileSync(filePath, json, { mode: 0o600 }); // Owner-only read/write
|
|
97
178
|
}
|
|
98
179
|
async function encryptedFileLoad(password, filePath) {
|
|
99
180
|
if (!fs.existsSync(filePath))
|
|
100
181
|
return null;
|
|
101
182
|
const json = fs.readFileSync(filePath, 'utf-8');
|
|
102
|
-
|
|
103
|
-
return wallet.privateKey;
|
|
183
|
+
return decryptKeystore(json, password);
|
|
104
184
|
}
|
|
105
185
|
function encryptedFileExists(filePath) {
|
|
106
186
|
return fs.existsSync(filePath);
|
|
@@ -139,13 +219,13 @@ export async function createWallet(config = {}) {
|
|
|
139
219
|
const data = await proxyRequest(config, '/create-wallet');
|
|
140
220
|
return { address: data.address, backend, keystorePath: undefined };
|
|
141
221
|
}
|
|
142
|
-
const
|
|
143
|
-
const
|
|
144
|
-
const address =
|
|
222
|
+
const privateKey = generatePrivateKey();
|
|
223
|
+
const account = privateKeyToAccount(privateKey);
|
|
224
|
+
const address = account.address;
|
|
145
225
|
switch (backend) {
|
|
146
226
|
case 'encrypted-file': {
|
|
147
227
|
const password = config.password || process.env.KEYSTORE_PASSWORD || deriveMachinePassword();
|
|
148
|
-
await encryptedFileStore(privateKey,
|
|
228
|
+
await encryptedFileStore(privateKey, password, keystorePath);
|
|
149
229
|
break;
|
|
150
230
|
}
|
|
151
231
|
case 'env':
|
|
@@ -174,12 +254,13 @@ export async function importWallet(privateKey, config = {}) {
|
|
|
174
254
|
throw new Error('importWallet() is not supported via proxy. Import the wallet on the proxy server directly.');
|
|
175
255
|
}
|
|
176
256
|
const keystorePath = config.keystorePath || process.env.KEYSTORE_PATH || DEFAULT_KEYSTORE_PATH;
|
|
177
|
-
const
|
|
178
|
-
const
|
|
257
|
+
const hexKey = (privateKey.startsWith('0x') ? privateKey : `0x${privateKey}`);
|
|
258
|
+
const account = privateKeyToAccount(hexKey);
|
|
259
|
+
const address = account.address;
|
|
179
260
|
switch (backend) {
|
|
180
261
|
case 'encrypted-file': {
|
|
181
262
|
const password = config.password || process.env.KEYSTORE_PASSWORD || deriveMachinePassword();
|
|
182
|
-
await encryptedFileStore(
|
|
263
|
+
await encryptedFileStore(hexKey, password, keystorePath);
|
|
183
264
|
break;
|
|
184
265
|
}
|
|
185
266
|
case 'env':
|
|
@@ -218,12 +299,11 @@ export async function getAddress(config = {}) {
|
|
|
218
299
|
const data = await proxyRequest(config, '/get-address');
|
|
219
300
|
return data.address;
|
|
220
301
|
}
|
|
221
|
-
const
|
|
222
|
-
if (!
|
|
302
|
+
const privateKey = await _loadPrivateKeyInternal(config);
|
|
303
|
+
if (!privateKey)
|
|
223
304
|
return null;
|
|
224
|
-
const
|
|
225
|
-
|
|
226
|
-
return address;
|
|
305
|
+
const account = privateKeyToAccount(privateKey);
|
|
306
|
+
return account.address;
|
|
227
307
|
}
|
|
228
308
|
/**
|
|
229
309
|
* Sign a message (EIP-191 personal_sign).
|
|
@@ -236,13 +316,12 @@ export async function signMessage(message, config = {}) {
|
|
|
236
316
|
const data = await proxyRequest(config, '/sign-message', { message });
|
|
237
317
|
return { signature: data.signature, address: data.address };
|
|
238
318
|
}
|
|
239
|
-
const
|
|
240
|
-
if (!
|
|
319
|
+
const privateKey = await _loadPrivateKeyInternal(config);
|
|
320
|
+
if (!privateKey)
|
|
241
321
|
throw new Error('No wallet found. Run createWallet() first.');
|
|
242
|
-
const
|
|
243
|
-
const
|
|
244
|
-
|
|
245
|
-
return { signature, address };
|
|
322
|
+
const account = privateKeyToAccount(privateKey);
|
|
323
|
+
const signature = await account.signMessage({ message });
|
|
324
|
+
return { signature, address: account.address };
|
|
246
325
|
}
|
|
247
326
|
/**
|
|
248
327
|
* Sign a transaction.
|
|
@@ -255,16 +334,37 @@ export async function signTransaction(tx, config = {}) {
|
|
|
255
334
|
const data = await proxyRequest(config, '/sign-transaction', { tx: tx });
|
|
256
335
|
return { signedTx: data.signedTx, address: data.address };
|
|
257
336
|
}
|
|
258
|
-
const
|
|
259
|
-
if (!
|
|
337
|
+
const privateKey = await _loadPrivateKeyInternal(config);
|
|
338
|
+
if (!privateKey)
|
|
260
339
|
throw new Error('No wallet found. Run createWallet() first.');
|
|
261
|
-
const
|
|
262
|
-
|
|
263
|
-
|
|
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 };
|
|
264
365
|
}
|
|
265
366
|
/**
|
|
266
367
|
* Sign an EIP-7702 authorization for delegating the EOA to a contract.
|
|
267
|
-
* Requires ethers >= 6.14.3.
|
|
268
368
|
*
|
|
269
369
|
* This allows the agent's EOA to temporarily act as a smart contract
|
|
270
370
|
* during a type 4 transaction. The private key is loaded, used, and
|
|
@@ -279,37 +379,54 @@ export async function signAuthorization(auth, config = {}) {
|
|
|
279
379
|
const data = await proxyRequest(config, '/sign-authorization', { auth });
|
|
280
380
|
return data;
|
|
281
381
|
}
|
|
282
|
-
const
|
|
283
|
-
if (!
|
|
382
|
+
const privateKey = await _loadPrivateKeyInternal(config);
|
|
383
|
+
if (!privateKey)
|
|
284
384
|
throw new Error('No wallet found. Run createWallet() first.');
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
const
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
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,
|
|
294
394
|
});
|
|
295
|
-
//
|
|
296
|
-
|
|
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
|
+
};
|
|
297
410
|
}
|
|
298
411
|
/**
|
|
299
|
-
* Get a
|
|
300
|
-
* NOTE: This
|
|
412
|
+
* Get a wallet client for contract interactions.
|
|
413
|
+
* NOTE: This creates a client with the private key in memory.
|
|
301
414
|
* Use only within a narrow scope and discard immediately.
|
|
302
415
|
* Prefer signMessage() / signTransaction() when possible.
|
|
303
416
|
*/
|
|
304
|
-
export async function
|
|
417
|
+
export async function getWalletClient(rpcUrl, config = {}) {
|
|
305
418
|
const backend = config.backend || await detectBackend();
|
|
306
419
|
if (backend === 'proxy') {
|
|
307
|
-
throw new Error('
|
|
420
|
+
throw new Error('getWalletClient() is not supported via proxy. The private key cannot be serialized over HTTP. Use signMessage() or signTransaction() instead.');
|
|
308
421
|
}
|
|
309
|
-
const
|
|
310
|
-
if (!
|
|
422
|
+
const privateKey = await _loadPrivateKeyInternal(config);
|
|
423
|
+
if (!privateKey)
|
|
311
424
|
throw new Error('No wallet found. Run createWallet() first.');
|
|
312
|
-
|
|
425
|
+
const account = privateKeyToAccount(privateKey);
|
|
426
|
+
return createWalletClient({
|
|
427
|
+
account,
|
|
428
|
+
transport: http(rpcUrl),
|
|
429
|
+
});
|
|
313
430
|
}
|
|
314
431
|
/**
|
|
315
432
|
* Delete the stored wallet from the active backend.
|
|
@@ -334,9 +451,9 @@ export async function deleteWallet(config = {}) {
|
|
|
334
451
|
}
|
|
335
452
|
}
|
|
336
453
|
// ---------------------------------------------------------------------------
|
|
337
|
-
// Internal — loads the
|
|
454
|
+
// Internal — loads the private key. NEVER exposed publicly.
|
|
338
455
|
// ---------------------------------------------------------------------------
|
|
339
|
-
async function
|
|
456
|
+
async function _loadPrivateKeyInternal(config = {}) {
|
|
340
457
|
const backend = config.backend || await detectBackend();
|
|
341
458
|
const keystorePath = config.keystorePath || process.env.KEYSTORE_PATH || DEFAULT_KEYSTORE_PATH;
|
|
342
459
|
let privateKey = null;
|
|
@@ -346,11 +463,13 @@ async function _loadWalletInternal(config = {}) {
|
|
|
346
463
|
privateKey = await encryptedFileLoad(password, keystorePath);
|
|
347
464
|
break;
|
|
348
465
|
}
|
|
349
|
-
case 'env':
|
|
350
|
-
|
|
466
|
+
case 'env': {
|
|
467
|
+
const envKey = process.env.AGENT_PRIVATE_KEY || null;
|
|
468
|
+
if (envKey) {
|
|
469
|
+
privateKey = (envKey.startsWith('0x') ? envKey : `0x${envKey}`);
|
|
470
|
+
}
|
|
351
471
|
break;
|
|
472
|
+
}
|
|
352
473
|
}
|
|
353
|
-
|
|
354
|
-
return null;
|
|
355
|
-
return new ethers.Wallet(privateKey);
|
|
474
|
+
return privateKey;
|
|
356
475
|
}
|
package/dist/proxy-auth.js
CHANGED
|
@@ -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
|
}
|
package/dist/registry.d.ts
CHANGED
|
@@ -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
|
|
8
|
+
* npm install viem
|
|
9
9
|
*/
|
|
10
|
-
import {
|
|
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
|
-
|
|
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
|
-
|
|
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,
|
|
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,
|
|
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
|
|
8
|
+
* npm install viem
|
|
9
9
|
*/
|
|
10
|
-
import {
|
|
10
|
+
import { zeroAddress, } from 'viem';
|
|
11
11
|
// ─── ABI Fragments ──────────────────────────────────────────────────
|
|
12
12
|
const IDENTITY_REGISTRY_ABI = [
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
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
|
-
|
|
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,
|
|
85
|
+
* @param options Registry address, client, and optional fetchMetadata flag
|
|
53
86
|
*/
|
|
54
87
|
export async function getAgent(agentId, options) {
|
|
55
|
-
const { registryAddress,
|
|
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
|
-
|
|
59
|
-
|
|
60
|
-
|
|
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 ===
|
|
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,
|
|
126
|
+
* @param options Reputation registry address, client, and optional filters
|
|
80
127
|
*/
|
|
81
128
|
export async function getReputation(agentId, options) {
|
|
82
|
-
const { reputationRegistryAddress,
|
|
83
|
-
const
|
|
84
|
-
|
|
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
|
|
8
|
+
* npm install viem
|
|
9
9
|
*/
|
|
10
|
-
import {
|
|
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
|
|
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>,
|
|
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
|
|
8
|
+
* npm install viem
|
|
9
9
|
*/
|
|
10
|
-
import {
|
|
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
|
|
140
|
-
|
|
141
|
-
|
|
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
|
|
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
|
|
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,
|
|
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
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
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
|
|
201
|
-
|
|
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 =
|
|
217
|
+
const messageHash = hashMessage(message);
|
|
207
218
|
try {
|
|
208
|
-
const
|
|
209
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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,28 +1,56 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@buildersgarden/siwa",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.3",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"exports": {
|
|
6
|
-
".": {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
"./
|
|
11
|
-
|
|
12
|
-
|
|
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
|
+
}
|
|
13
34
|
},
|
|
14
35
|
"main": "./dist/index.js",
|
|
15
36
|
"types": "./dist/index.d.ts",
|
|
16
|
-
"files": [
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
"
|
|
37
|
+
"files": [
|
|
38
|
+
"dist"
|
|
39
|
+
],
|
|
40
|
+
"publishConfig": {
|
|
41
|
+
"access": "public"
|
|
21
42
|
},
|
|
22
43
|
"dependencies": {
|
|
23
|
-
"
|
|
44
|
+
"@noble/ciphers": "^0.5.0",
|
|
45
|
+
"@noble/hashes": "^1.4.0",
|
|
46
|
+
"viem": "^2.21.0"
|
|
24
47
|
},
|
|
25
48
|
"devDependencies": {
|
|
49
|
+
"@types/node": "^25.2.1",
|
|
26
50
|
"typescript": "^5.5.0"
|
|
51
|
+
},
|
|
52
|
+
"scripts": {
|
|
53
|
+
"build": "tsc",
|
|
54
|
+
"clean": "rm -rf dist"
|
|
27
55
|
}
|
|
28
|
-
}
|
|
56
|
+
}
|