@buildersgarden/siwa 0.0.11 → 0.0.12
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/README.md +2 -2
- package/dist/erc8128.d.ts +38 -10
- package/dist/erc8128.js +51 -19
- package/dist/express.d.ts +3 -0
- package/dist/express.js +1 -0
- package/dist/identity.d.ts +7 -7
- package/dist/identity.js +8 -8
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/keystore.d.ts +17 -57
- package/dist/keystore.js +20 -54
- package/dist/next.d.ts +3 -0
- package/dist/next.js +1 -0
- package/dist/receipt.d.ts +2 -0
- package/dist/registry.d.ts +22 -3
- package/dist/registry.js +20 -9
- package/dist/signer.d.ts +145 -0
- package/dist/signer.js +179 -0
- package/dist/siwa.d.ts +33 -8
- package/dist/siwa.js +52 -39
- package/dist/tba.d.ts +82 -0
- package/dist/tba.js +113 -0
- package/package.json +9 -1
package/README.md
CHANGED
|
@@ -13,7 +13,7 @@ A Claude Code skill for registering AI agents on the [ERC-8004 (Trustless Agents
|
|
|
13
13
|
```
|
|
14
14
|
src/ Core SDK modules
|
|
15
15
|
keystore.ts Proxy-only keystore (signing delegated over HMAC-authenticated HTTP)
|
|
16
|
-
identity.ts
|
|
16
|
+
identity.ts SIWA_IDENTITY.md read/write helpers
|
|
17
17
|
siwa.ts SIWA message building, signing, verification
|
|
18
18
|
proxy-auth.ts HMAC-SHA256 authentication utilities
|
|
19
19
|
registry.ts Onchain agent profile & reputation lookups
|
|
@@ -26,7 +26,7 @@ references/ Protocol documentation
|
|
|
26
26
|
security-model.md Threat model and keystore architecture
|
|
27
27
|
|
|
28
28
|
assets/ Templates
|
|
29
|
-
|
|
29
|
+
SIWA_IDENTITY.template.md
|
|
30
30
|
|
|
31
31
|
```
|
|
32
32
|
|
package/dist/erc8128.d.ts
CHANGED
|
@@ -9,14 +9,16 @@
|
|
|
9
9
|
*
|
|
10
10
|
* These are the two main entry points. Everything else is internal.
|
|
11
11
|
*/
|
|
12
|
-
import type { PublicClient } from 'viem';
|
|
13
|
-
import { type EthHttpSigner } from '@slicekit/erc8128';
|
|
14
|
-
import {
|
|
12
|
+
import type { Address, PublicClient } from 'viem';
|
|
13
|
+
import { type EthHttpSigner, type NonceStore } from '@slicekit/erc8128';
|
|
14
|
+
import type { Signer, SignerType } from './signer.js';
|
|
15
15
|
export interface VerifyOptions {
|
|
16
16
|
receiptSecret: string;
|
|
17
17
|
rpcUrl?: string;
|
|
18
18
|
verifyOnchain?: boolean;
|
|
19
19
|
publicClient?: PublicClient;
|
|
20
|
+
nonceStore?: NonceStore;
|
|
21
|
+
allowedSignerTypes?: SignerType[];
|
|
20
22
|
}
|
|
21
23
|
/** Verified agent identity returned from a successful auth check. */
|
|
22
24
|
export interface SiwaAgent {
|
|
@@ -24,6 +26,7 @@ export interface SiwaAgent {
|
|
|
24
26
|
agentId: number;
|
|
25
27
|
agentRegistry: string;
|
|
26
28
|
chainId: number;
|
|
29
|
+
signerType?: SignerType;
|
|
27
30
|
}
|
|
28
31
|
export type AuthResult = {
|
|
29
32
|
valid: true;
|
|
@@ -41,13 +44,19 @@ export declare function resolveReceiptSecret(explicit?: string): string;
|
|
|
41
44
|
/** Header name for the verification receipt */
|
|
42
45
|
export declare const RECEIPT_HEADER = "X-SIWA-Receipt";
|
|
43
46
|
/**
|
|
44
|
-
* Create an ERC-8128 signer
|
|
47
|
+
* Create an ERC-8128 HTTP signer from a SIWA Signer.
|
|
45
48
|
*
|
|
46
49
|
* The `signMessage` callback converts the RFC 9421 signature base
|
|
47
|
-
* (Uint8Array) to a hex string and delegates to the
|
|
48
|
-
*
|
|
50
|
+
* (Uint8Array) to a hex string and delegates to the signer.
|
|
51
|
+
*
|
|
52
|
+
* @param signer - A SIWA Signer (createKeyringProxySigner, createLocalAccountSigner, etc.)
|
|
53
|
+
* @param chainId - Chain ID for the ERC-8128 keyid
|
|
54
|
+
* @param options - Optional overrides (e.g. signerAddress for TBA identity)
|
|
55
|
+
* @returns An EthHttpSigner for use with @slicekit/erc8128
|
|
49
56
|
*/
|
|
50
|
-
export declare function
|
|
57
|
+
export declare function createErc8128Signer(signer: Signer, chainId: number, options?: {
|
|
58
|
+
signerAddress?: Address;
|
|
59
|
+
}): Promise<EthHttpSigner>;
|
|
51
60
|
/**
|
|
52
61
|
* Attach a verification receipt to a request.
|
|
53
62
|
*
|
|
@@ -60,16 +69,35 @@ export declare function attachReceipt(request: Request, receipt: string): Reques
|
|
|
60
69
|
* This is the main function platform developers use on the agent side.
|
|
61
70
|
* One call does everything:
|
|
62
71
|
* 1. Attaches the receipt header
|
|
63
|
-
* 2. Creates
|
|
72
|
+
* 2. Creates an ERC-8128 signer from the SIWA signer
|
|
64
73
|
* 3. Signs the request with HTTP Message Signatures (RFC 9421)
|
|
65
74
|
*
|
|
66
75
|
* @param request The outgoing Request object
|
|
67
76
|
* @param receipt Verification receipt from SIWA sign-in
|
|
68
|
-
* @param
|
|
77
|
+
* @param signer A SIWA Signer (createKeyringProxySigner, createLocalAccountSigner, etc.)
|
|
69
78
|
* @param chainId Chain ID for the ERC-8128 keyid
|
|
79
|
+
* @param options Optional overrides (e.g. signerAddress for TBA identity)
|
|
70
80
|
* @returns A new Request with Signature, Signature-Input, Content-Digest, and X-SIWA-Receipt headers
|
|
81
|
+
*
|
|
82
|
+
* @example
|
|
83
|
+
* ```typescript
|
|
84
|
+
* import { signAuthenticatedRequest, createLocalAccountSigner } from '@buildersgarden/siwa';
|
|
85
|
+
* import { privateKeyToAccount } from 'viem/accounts';
|
|
86
|
+
*
|
|
87
|
+
* const account = privateKeyToAccount('0x...');
|
|
88
|
+
* const signer = createLocalAccountSigner(account);
|
|
89
|
+
*
|
|
90
|
+
* const signedRequest = await signAuthenticatedRequest(
|
|
91
|
+
* new Request('https://api.example.com/data'),
|
|
92
|
+
* receipt,
|
|
93
|
+
* signer,
|
|
94
|
+
* 84532
|
|
95
|
+
* );
|
|
96
|
+
* ```
|
|
71
97
|
*/
|
|
72
|
-
export declare function signAuthenticatedRequest(request: Request, receipt: string,
|
|
98
|
+
export declare function signAuthenticatedRequest(request: Request, receipt: string, signer: Signer, chainId: number, options?: {
|
|
99
|
+
signerAddress?: Address;
|
|
100
|
+
}): Promise<Request>;
|
|
73
101
|
/**
|
|
74
102
|
* Verify an authenticated request: ERC-8128 signature + receipt + optional onchain check.
|
|
75
103
|
*
|
package/dist/erc8128.js
CHANGED
|
@@ -10,7 +10,6 @@
|
|
|
10
10
|
* These are the two main entry points. Everything else is internal.
|
|
11
11
|
*/
|
|
12
12
|
import { signRequest, verifyRequest, } from '@slicekit/erc8128';
|
|
13
|
-
import { signRawMessage, getAddress } from './keystore.js';
|
|
14
13
|
import { verifyReceipt } from './receipt.js';
|
|
15
14
|
/**
|
|
16
15
|
* Resolve the receipt secret from an explicit value or environment variables.
|
|
@@ -30,23 +29,29 @@ export const RECEIPT_HEADER = 'X-SIWA-Receipt';
|
|
|
30
29
|
// Agent-side: signer creation
|
|
31
30
|
// ---------------------------------------------------------------------------
|
|
32
31
|
/**
|
|
33
|
-
* Create an ERC-8128 signer
|
|
32
|
+
* Create an ERC-8128 HTTP signer from a SIWA Signer.
|
|
34
33
|
*
|
|
35
34
|
* The `signMessage` callback converts the RFC 9421 signature base
|
|
36
|
-
* (Uint8Array) to a hex string and delegates to the
|
|
37
|
-
*
|
|
35
|
+
* (Uint8Array) to a hex string and delegates to the signer.
|
|
36
|
+
*
|
|
37
|
+
* @param signer - A SIWA Signer (createKeyringProxySigner, createLocalAccountSigner, etc.)
|
|
38
|
+
* @param chainId - Chain ID for the ERC-8128 keyid
|
|
39
|
+
* @param options - Optional overrides (e.g. signerAddress for TBA identity)
|
|
40
|
+
* @returns An EthHttpSigner for use with @slicekit/erc8128
|
|
38
41
|
*/
|
|
39
|
-
export async function
|
|
40
|
-
const address = await getAddress(
|
|
41
|
-
if (!address)
|
|
42
|
-
throw new Error('No wallet found in keystore');
|
|
42
|
+
export async function createErc8128Signer(signer, chainId, options) {
|
|
43
|
+
const address = options?.signerAddress ?? await signer.getAddress();
|
|
43
44
|
return {
|
|
44
|
-
address
|
|
45
|
+
address,
|
|
45
46
|
chainId,
|
|
46
47
|
signMessage: async (message) => {
|
|
47
48
|
const hex = ('0x' + Array.from(message).map(b => b.toString(16).padStart(2, '0')).join(''));
|
|
48
|
-
|
|
49
|
-
|
|
49
|
+
// Use signRawMessage if available (preferred for raw bytes)
|
|
50
|
+
if (signer.signRawMessage) {
|
|
51
|
+
return signer.signRawMessage(hex);
|
|
52
|
+
}
|
|
53
|
+
// Fallback to signMessage for signers without signRawMessage
|
|
54
|
+
return signer.signMessage(hex);
|
|
50
55
|
},
|
|
51
56
|
};
|
|
52
57
|
}
|
|
@@ -69,22 +74,41 @@ export function attachReceipt(request, receipt) {
|
|
|
69
74
|
* This is the main function platform developers use on the agent side.
|
|
70
75
|
* One call does everything:
|
|
71
76
|
* 1. Attaches the receipt header
|
|
72
|
-
* 2. Creates
|
|
77
|
+
* 2. Creates an ERC-8128 signer from the SIWA signer
|
|
73
78
|
* 3. Signs the request with HTTP Message Signatures (RFC 9421)
|
|
74
79
|
*
|
|
75
80
|
* @param request The outgoing Request object
|
|
76
81
|
* @param receipt Verification receipt from SIWA sign-in
|
|
77
|
-
* @param
|
|
82
|
+
* @param signer A SIWA Signer (createKeyringProxySigner, createLocalAccountSigner, etc.)
|
|
78
83
|
* @param chainId Chain ID for the ERC-8128 keyid
|
|
84
|
+
* @param options Optional overrides (e.g. signerAddress for TBA identity)
|
|
79
85
|
* @returns A new Request with Signature, Signature-Input, Content-Digest, and X-SIWA-Receipt headers
|
|
86
|
+
*
|
|
87
|
+
* @example
|
|
88
|
+
* ```typescript
|
|
89
|
+
* import { signAuthenticatedRequest, createLocalAccountSigner } from '@buildersgarden/siwa';
|
|
90
|
+
* import { privateKeyToAccount } from 'viem/accounts';
|
|
91
|
+
*
|
|
92
|
+
* const account = privateKeyToAccount('0x...');
|
|
93
|
+
* const signer = createLocalAccountSigner(account);
|
|
94
|
+
*
|
|
95
|
+
* const signedRequest = await signAuthenticatedRequest(
|
|
96
|
+
* new Request('https://api.example.com/data'),
|
|
97
|
+
* receipt,
|
|
98
|
+
* signer,
|
|
99
|
+
* 84532
|
|
100
|
+
* );
|
|
101
|
+
* ```
|
|
80
102
|
*/
|
|
81
|
-
export async function signAuthenticatedRequest(request, receipt,
|
|
103
|
+
export async function signAuthenticatedRequest(request, receipt, signer, chainId, options) {
|
|
82
104
|
// 1. Attach receipt header
|
|
83
105
|
const withReceipt = attachReceipt(request, receipt);
|
|
84
|
-
// 2. Create
|
|
85
|
-
const
|
|
86
|
-
// 3. Sign with ERC-8128 (includes Content-Digest for bodies)
|
|
87
|
-
return signRequest(withReceipt,
|
|
106
|
+
// 2. Create ERC-8128 signer from SIWA signer
|
|
107
|
+
const erc8128Signer = await createErc8128Signer(signer, chainId, options);
|
|
108
|
+
// 3. Sign with ERC-8128 (includes Content-Digest for bodies and receipt header)
|
|
109
|
+
return signRequest(withReceipt, erc8128Signer, {
|
|
110
|
+
components: [RECEIPT_HEADER],
|
|
111
|
+
});
|
|
88
112
|
}
|
|
89
113
|
// ---------------------------------------------------------------------------
|
|
90
114
|
// Server-side: high-level request verification
|
|
@@ -138,6 +162,10 @@ export async function verifyAuthenticatedRequest(request, options) {
|
|
|
138
162
|
if (!receipt) {
|
|
139
163
|
return { valid: false, error: 'Invalid or expired receipt' };
|
|
140
164
|
}
|
|
165
|
+
// 1b. Enforce signer type policy
|
|
166
|
+
if (options.allowedSignerTypes?.length && !options.allowedSignerTypes.includes(receipt.signerType)) {
|
|
167
|
+
return { valid: false, error: `Signer type '${receipt.signerType || 'unknown'}' is not in allowed types [${options.allowedSignerTypes.join(', ')}]` };
|
|
168
|
+
}
|
|
141
169
|
// 2. Verify ERC-8128 signature
|
|
142
170
|
const { verifyMessage } = await import('viem');
|
|
143
171
|
const verifyResult = await verifyRequest(request, async (args) => {
|
|
@@ -155,7 +183,10 @@ export async function verifyAuthenticatedRequest(request, options) {
|
|
|
155
183
|
message: args.message,
|
|
156
184
|
signature: args.signature,
|
|
157
185
|
});
|
|
158
|
-
}, nonceStore
|
|
186
|
+
}, options.nonceStore ?? nonceStore, {
|
|
187
|
+
additionalRequestBoundComponents: [RECEIPT_HEADER],
|
|
188
|
+
classBoundPolicies: [RECEIPT_HEADER]
|
|
189
|
+
});
|
|
159
190
|
if (!verifyResult.ok) {
|
|
160
191
|
return { valid: false, error: `ERC-8128 verification failed: ${verifyResult.reason}${verifyResult.detail ? ` (${verifyResult.detail})` : ''}` };
|
|
161
192
|
}
|
|
@@ -202,6 +233,7 @@ export async function verifyAuthenticatedRequest(request, options) {
|
|
|
202
233
|
agentId: receipt.agentId,
|
|
203
234
|
agentRegistry: receipt.agentRegistry,
|
|
204
235
|
chainId: receipt.chainId,
|
|
236
|
+
...(receipt.signerType ? { signerType: receipt.signerType } : {}),
|
|
205
237
|
},
|
|
206
238
|
};
|
|
207
239
|
}
|
package/dist/express.d.ts
CHANGED
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
*/
|
|
17
17
|
import type { RequestHandler } from 'express';
|
|
18
18
|
import { type SiwaAgent, type VerifyOptions } from './erc8128.js';
|
|
19
|
+
import type { SignerType } from './signer.js';
|
|
19
20
|
export type { SiwaAgent };
|
|
20
21
|
declare global {
|
|
21
22
|
namespace Express {
|
|
@@ -34,6 +35,8 @@ export interface SiwaMiddlewareOptions {
|
|
|
34
35
|
verifyOnchain?: boolean;
|
|
35
36
|
/** Public client for ERC-1271 or onchain checks. */
|
|
36
37
|
publicClient?: VerifyOptions['publicClient'];
|
|
38
|
+
/** Allowed signer types. Omit to accept all. */
|
|
39
|
+
allowedSignerTypes?: SignerType[];
|
|
37
40
|
}
|
|
38
41
|
export interface SiwaCorsOptions {
|
|
39
42
|
/** Allowed origin(s). Defaults to "*". */
|
package/dist/express.js
CHANGED
|
@@ -78,6 +78,7 @@ export function siwaMiddleware(options) {
|
|
|
78
78
|
rpcUrl: options?.rpcUrl,
|
|
79
79
|
verifyOnchain: options?.verifyOnchain,
|
|
80
80
|
publicClient: options?.publicClient,
|
|
81
|
+
allowedSignerTypes: options?.allowedSignerTypes,
|
|
81
82
|
});
|
|
82
83
|
if (!result.valid) {
|
|
83
84
|
res.status(401).json({ error: result.error });
|
package/dist/identity.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* identity.ts
|
|
3
3
|
*
|
|
4
|
-
* Read/write helpers for the agent's
|
|
4
|
+
* Read/write helpers for the agent's SIWA_IDENTITY.md file.
|
|
5
5
|
* Minimal 4-field identity: Address, Agent ID, Agent Registry, Chain ID.
|
|
6
6
|
*
|
|
7
|
-
*
|
|
7
|
+
* SIWA_IDENTITY.md uses the pattern: - **Key**: `value`
|
|
8
8
|
*
|
|
9
9
|
* Registration checks are done onchain via ownerOf() when a PublicClient
|
|
10
10
|
* is provided, otherwise the local file is used as a cache.
|
|
@@ -19,26 +19,26 @@ export interface AgentIdentity {
|
|
|
19
19
|
chainId?: number;
|
|
20
20
|
}
|
|
21
21
|
/**
|
|
22
|
-
* Ensure
|
|
22
|
+
* Ensure SIWA_IDENTITY.md exists. If not, copy from template or create minimal.
|
|
23
23
|
*/
|
|
24
24
|
export declare function ensureIdentityExists(identityPath?: string, templatePath?: string): void;
|
|
25
25
|
/**
|
|
26
|
-
* Read the agent identity from
|
|
26
|
+
* Read the agent identity from SIWA_IDENTITY.md.
|
|
27
27
|
* Returns typed AgentIdentity with parsed values.
|
|
28
28
|
*/
|
|
29
29
|
export declare function readIdentity(identityPath?: string): AgentIdentity;
|
|
30
30
|
/**
|
|
31
|
-
* Write a single field value in
|
|
31
|
+
* Write a single field value in SIWA_IDENTITY.md.
|
|
32
32
|
*/
|
|
33
33
|
export declare function writeIdentityField(key: string, value: string, identityPath?: string): void;
|
|
34
34
|
/**
|
|
35
|
-
* Check if the agent has a wallet address recorded in
|
|
35
|
+
* Check if the agent has a wallet address recorded in SIWA_IDENTITY.md.
|
|
36
36
|
*/
|
|
37
37
|
export declare function hasWalletRecord(identityPath?: string): boolean;
|
|
38
38
|
/**
|
|
39
39
|
* Check if the agent is registered.
|
|
40
40
|
*
|
|
41
|
-
* Without a client: returns true if
|
|
41
|
+
* Without a client: returns true if SIWA_IDENTITY.md has an Agent ID and Agent Registry (local cache).
|
|
42
42
|
* With a client: performs an onchain ownerOf(agentId) check on the registry contract.
|
|
43
43
|
*/
|
|
44
44
|
export declare function isRegistered(options?: {
|
package/dist/identity.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* identity.ts
|
|
3
3
|
*
|
|
4
|
-
* Read/write helpers for the agent's
|
|
4
|
+
* Read/write helpers for the agent's SIWA_IDENTITY.md file.
|
|
5
5
|
* Minimal 4-field identity: Address, Agent ID, Agent Registry, Chain ID.
|
|
6
6
|
*
|
|
7
|
-
*
|
|
7
|
+
* SIWA_IDENTITY.md uses the pattern: - **Key**: `value`
|
|
8
8
|
*
|
|
9
9
|
* Registration checks are done onchain via ownerOf() when a PublicClient
|
|
10
10
|
* is provided, otherwise the local file is used as a cache.
|
|
@@ -12,12 +12,12 @@
|
|
|
12
12
|
* Dependencies: fs (Node built-in), viem (optional for onchain checks)
|
|
13
13
|
*/
|
|
14
14
|
import * as fs from 'fs';
|
|
15
|
-
const DEFAULT_IDENTITY_PATH = './
|
|
15
|
+
const DEFAULT_IDENTITY_PATH = './SIWA_IDENTITY.md';
|
|
16
16
|
// ---------------------------------------------------------------------------
|
|
17
17
|
// File Operations
|
|
18
18
|
// ---------------------------------------------------------------------------
|
|
19
19
|
/**
|
|
20
|
-
* Ensure
|
|
20
|
+
* Ensure SIWA_IDENTITY.md exists. If not, copy from template or create minimal.
|
|
21
21
|
*/
|
|
22
22
|
export function ensureIdentityExists(identityPath = DEFAULT_IDENTITY_PATH, templatePath) {
|
|
23
23
|
if (fs.existsSync(identityPath))
|
|
@@ -36,7 +36,7 @@ export function ensureIdentityExists(identityPath = DEFAULT_IDENTITY_PATH, templ
|
|
|
36
36
|
}
|
|
37
37
|
}
|
|
38
38
|
/**
|
|
39
|
-
* Read the agent identity from
|
|
39
|
+
* Read the agent identity from SIWA_IDENTITY.md.
|
|
40
40
|
* Returns typed AgentIdentity with parsed values.
|
|
41
41
|
*/
|
|
42
42
|
export function readIdentity(identityPath = DEFAULT_IDENTITY_PATH) {
|
|
@@ -62,7 +62,7 @@ export function readIdentity(identityPath = DEFAULT_IDENTITY_PATH) {
|
|
|
62
62
|
return identity;
|
|
63
63
|
}
|
|
64
64
|
/**
|
|
65
|
-
* Write a single field value in
|
|
65
|
+
* Write a single field value in SIWA_IDENTITY.md.
|
|
66
66
|
*/
|
|
67
67
|
export function writeIdentityField(key, value, identityPath = DEFAULT_IDENTITY_PATH) {
|
|
68
68
|
let content = fs.readFileSync(identityPath, 'utf-8');
|
|
@@ -77,7 +77,7 @@ export function writeIdentityField(key, value, identityPath = DEFAULT_IDENTITY_P
|
|
|
77
77
|
fs.writeFileSync(identityPath, content);
|
|
78
78
|
}
|
|
79
79
|
/**
|
|
80
|
-
* Check if the agent has a wallet address recorded in
|
|
80
|
+
* Check if the agent has a wallet address recorded in SIWA_IDENTITY.md.
|
|
81
81
|
*/
|
|
82
82
|
export function hasWalletRecord(identityPath = DEFAULT_IDENTITY_PATH) {
|
|
83
83
|
const identity = readIdentity(identityPath);
|
|
@@ -86,7 +86,7 @@ export function hasWalletRecord(identityPath = DEFAULT_IDENTITY_PATH) {
|
|
|
86
86
|
/**
|
|
87
87
|
* Check if the agent is registered.
|
|
88
88
|
*
|
|
89
|
-
* Without a client: returns true if
|
|
89
|
+
* Without a client: returns true if SIWA_IDENTITY.md has an Agent ID and Agent Registry (local cache).
|
|
90
90
|
* With a client: performs an onchain ownerOf(agentId) check on the registry contract.
|
|
91
91
|
*/
|
|
92
92
|
export async function isRegistered(options) {
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export * from './signer.js';
|
|
1
2
|
export * from './keystore.js';
|
|
2
3
|
export * from './siwa.js';
|
|
3
4
|
export * from './identity.js';
|
|
@@ -6,3 +7,4 @@ export * from './registry.js';
|
|
|
6
7
|
export * from './addresses.js';
|
|
7
8
|
export * from './receipt.js';
|
|
8
9
|
export * from './erc8128.js';
|
|
10
|
+
export * from './tba.js';
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export * from './signer.js';
|
|
1
2
|
export * from './keystore.js';
|
|
2
3
|
export * from './siwa.js';
|
|
3
4
|
export * from './identity.js';
|
|
@@ -6,3 +7,4 @@ export * from './registry.js';
|
|
|
6
7
|
export * from './addresses.js';
|
|
7
8
|
export * from './receipt.js';
|
|
8
9
|
export * from './erc8128.js';
|
|
10
|
+
export * from './tba.js';
|
package/dist/keystore.d.ts
CHANGED
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* keystore.ts
|
|
3
3
|
*
|
|
4
|
-
*
|
|
4
|
+
* Keyring proxy administrative operations.
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
6
|
+
* This module provides admin functions for the keyring proxy server:
|
|
7
|
+
* - createWallet() - Create a new wallet
|
|
8
|
+
* - hasWallet() - Check if a wallet exists
|
|
9
|
+
* - signAuthorization() - Sign EIP-7702 authorizations
|
|
9
10
|
*
|
|
10
|
-
*
|
|
11
|
-
* - createWallet() → returns { address } (no private key)
|
|
12
|
-
* - signMessage(msg) → returns { signature, address }
|
|
13
|
-
* - signTransaction(tx) → returns { signedTx, address }
|
|
14
|
-
* - signAuthorization(auth) → returns signed EIP-7702 authorization
|
|
15
|
-
* - getAddress() → returns the public address
|
|
16
|
-
* - hasWallet() → returns boolean
|
|
11
|
+
* For signing operations, use the Signer API instead:
|
|
17
12
|
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
13
|
+
* ```typescript
|
|
14
|
+
* import { createKeyringProxySigner } from '@buildersgarden/siwa/signer';
|
|
15
|
+
*
|
|
16
|
+
* const signer = createKeyringProxySigner({ proxyUrl, proxySecret });
|
|
17
|
+
* const address = await signer.getAddress();
|
|
18
|
+
* const signature = await signer.signMessage(message);
|
|
19
|
+
* const signedTx = await signer.signTransaction(tx);
|
|
20
|
+
* ```
|
|
21
21
|
*/
|
|
22
22
|
export interface KeystoreConfig {
|
|
23
23
|
proxyUrl?: string;
|
|
@@ -26,10 +26,6 @@ export interface KeystoreConfig {
|
|
|
26
26
|
export interface WalletInfo {
|
|
27
27
|
address: string;
|
|
28
28
|
}
|
|
29
|
-
export interface SignResult {
|
|
30
|
-
signature: string;
|
|
31
|
-
address: string;
|
|
32
|
-
}
|
|
33
29
|
export interface AuthorizationRequest {
|
|
34
30
|
address: string;
|
|
35
31
|
chainId?: number;
|
|
@@ -43,23 +39,9 @@ export interface SignedAuthorization {
|
|
|
43
39
|
r: string;
|
|
44
40
|
s: string;
|
|
45
41
|
}
|
|
46
|
-
export interface TransactionLike {
|
|
47
|
-
to?: string;
|
|
48
|
-
data?: string;
|
|
49
|
-
value?: bigint;
|
|
50
|
-
nonce?: number;
|
|
51
|
-
chainId?: number;
|
|
52
|
-
type?: number;
|
|
53
|
-
maxFeePerGas?: bigint | null;
|
|
54
|
-
maxPriorityFeePerGas?: bigint | null;
|
|
55
|
-
gasLimit?: bigint;
|
|
56
|
-
gas?: bigint;
|
|
57
|
-
gasPrice?: bigint | null;
|
|
58
|
-
accessList?: any[];
|
|
59
|
-
}
|
|
60
42
|
/**
|
|
61
43
|
* Create a new random wallet via the keyring proxy.
|
|
62
|
-
* Returns only the public address
|
|
44
|
+
* Returns only the public address.
|
|
63
45
|
*/
|
|
64
46
|
export declare function createWallet(config?: KeystoreConfig): Promise<WalletInfo>;
|
|
65
47
|
/**
|
|
@@ -67,35 +49,13 @@ export declare function createWallet(config?: KeystoreConfig): Promise<WalletInf
|
|
|
67
49
|
*/
|
|
68
50
|
export declare function hasWallet(config?: KeystoreConfig): Promise<boolean>;
|
|
69
51
|
/**
|
|
70
|
-
* Get the wallet's public address
|
|
52
|
+
* Get the wallet's public address from the keyring proxy.
|
|
71
53
|
*/
|
|
72
54
|
export declare function getAddress(config?: KeystoreConfig): Promise<string | null>;
|
|
73
|
-
/**
|
|
74
|
-
* Sign a message (EIP-191 personal_sign) via the keyring proxy.
|
|
75
|
-
* Only the signature is returned.
|
|
76
|
-
*/
|
|
77
|
-
export declare function signMessage(message: string, config?: KeystoreConfig): Promise<SignResult>;
|
|
78
|
-
/**
|
|
79
|
-
* Sign a raw hex message via the keyring proxy.
|
|
80
|
-
*
|
|
81
|
-
* Used internally by the ERC-8128 signer — the signature base bytes are
|
|
82
|
-
* passed as a hex string and signed with `{ raw: true }` so the proxy
|
|
83
|
-
* interprets them as raw bytes (not UTF-8). Note: the proxy still applies
|
|
84
|
-
* EIP-191 personal_sign wrapping (viem `signMessage({ message: { raw } })`).
|
|
85
|
-
*/
|
|
86
|
-
export declare function signRawMessage(rawHex: string, config?: KeystoreConfig): Promise<SignResult>;
|
|
87
|
-
/**
|
|
88
|
-
* Sign a transaction via the keyring proxy.
|
|
89
|
-
* Only the signed transaction is returned.
|
|
90
|
-
*/
|
|
91
|
-
export declare function signTransaction(tx: TransactionLike, config?: KeystoreConfig): Promise<{
|
|
92
|
-
signedTx: string;
|
|
93
|
-
address: string;
|
|
94
|
-
}>;
|
|
95
55
|
/**
|
|
96
56
|
* Sign an EIP-7702 authorization for delegating the EOA to a contract.
|
|
97
57
|
*
|
|
98
58
|
* This allows the agent's EOA to temporarily act as a smart contract
|
|
99
|
-
* during a type 4 transaction.
|
|
59
|
+
* during a type 4 transaction.
|
|
100
60
|
*/
|
|
101
61
|
export declare function signAuthorization(auth: AuthorizationRequest, config?: KeystoreConfig): Promise<SignedAuthorization>;
|
package/dist/keystore.js
CHANGED
|
@@ -1,35 +1,35 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* keystore.ts
|
|
3
3
|
*
|
|
4
|
-
*
|
|
4
|
+
* Keyring proxy administrative operations.
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
6
|
+
* This module provides admin functions for the keyring proxy server:
|
|
7
|
+
* - createWallet() - Create a new wallet
|
|
8
|
+
* - hasWallet() - Check if a wallet exists
|
|
9
|
+
* - signAuthorization() - Sign EIP-7702 authorizations
|
|
9
10
|
*
|
|
10
|
-
*
|
|
11
|
-
* - createWallet() → returns { address } (no private key)
|
|
12
|
-
* - signMessage(msg) → returns { signature, address }
|
|
13
|
-
* - signTransaction(tx) → returns { signedTx, address }
|
|
14
|
-
* - signAuthorization(auth) → returns signed EIP-7702 authorization
|
|
15
|
-
* - getAddress() → returns the public address
|
|
16
|
-
* - hasWallet() → returns boolean
|
|
11
|
+
* For signing operations, use the Signer API instead:
|
|
17
12
|
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
13
|
+
* ```typescript
|
|
14
|
+
* import { createKeyringProxySigner } from '@buildersgarden/siwa/signer';
|
|
15
|
+
*
|
|
16
|
+
* const signer = createKeyringProxySigner({ proxyUrl, proxySecret });
|
|
17
|
+
* const address = await signer.getAddress();
|
|
18
|
+
* const signature = await signer.signMessage(message);
|
|
19
|
+
* const signedTx = await signer.signTransaction(tx);
|
|
20
|
+
* ```
|
|
21
21
|
*/
|
|
22
22
|
import { computeHmac } from "./proxy-auth.js";
|
|
23
23
|
// ---------------------------------------------------------------------------
|
|
24
|
-
// Proxy backend
|
|
24
|
+
// Proxy backend
|
|
25
25
|
// ---------------------------------------------------------------------------
|
|
26
26
|
async function proxyRequest(config, endpoint, body = {}) {
|
|
27
27
|
const url = config.proxyUrl || process.env.KEYRING_PROXY_URL;
|
|
28
28
|
const secret = config.proxySecret || process.env.KEYRING_PROXY_SECRET;
|
|
29
29
|
if (!url)
|
|
30
|
-
throw new Error("
|
|
30
|
+
throw new Error("Keyring proxy requires KEYRING_PROXY_URL or config.proxyUrl");
|
|
31
31
|
if (!secret)
|
|
32
|
-
throw new Error("
|
|
32
|
+
throw new Error("Keyring proxy requires KEYRING_PROXY_SECRET or config.proxySecret");
|
|
33
33
|
const bodyStr = JSON.stringify(body, (_key, value) => typeof value === "bigint" ? "0x" + value.toString(16) : value);
|
|
34
34
|
const hmacHeaders = computeHmac(secret, "POST", endpoint, bodyStr);
|
|
35
35
|
const res = await fetch(`${url}${endpoint}`, {
|
|
@@ -51,7 +51,7 @@ async function proxyRequest(config, endpoint, body = {}) {
|
|
|
51
51
|
// ---------------------------------------------------------------------------
|
|
52
52
|
/**
|
|
53
53
|
* Create a new random wallet via the keyring proxy.
|
|
54
|
-
* Returns only the public address
|
|
54
|
+
* Returns only the public address.
|
|
55
55
|
*/
|
|
56
56
|
export async function createWallet(config = {}) {
|
|
57
57
|
const data = await proxyRequest(config, "/create-wallet");
|
|
@@ -65,51 +65,17 @@ export async function hasWallet(config = {}) {
|
|
|
65
65
|
return data.hasWallet;
|
|
66
66
|
}
|
|
67
67
|
/**
|
|
68
|
-
* Get the wallet's public address
|
|
68
|
+
* Get the wallet's public address from the keyring proxy.
|
|
69
69
|
*/
|
|
70
70
|
export async function getAddress(config = {}) {
|
|
71
71
|
const data = await proxyRequest(config, "/get-address");
|
|
72
72
|
return data.address;
|
|
73
73
|
}
|
|
74
|
-
/**
|
|
75
|
-
* Sign a message (EIP-191 personal_sign) via the keyring proxy.
|
|
76
|
-
* Only the signature is returned.
|
|
77
|
-
*/
|
|
78
|
-
export async function signMessage(message, config = {}) {
|
|
79
|
-
const msg = typeof message === "string" ? message : String(message ?? "");
|
|
80
|
-
const data = await proxyRequest(config, "/sign-message", { message: msg });
|
|
81
|
-
return { signature: data.signature, address: data.address };
|
|
82
|
-
}
|
|
83
|
-
/**
|
|
84
|
-
* Sign a raw hex message via the keyring proxy.
|
|
85
|
-
*
|
|
86
|
-
* Used internally by the ERC-8128 signer — the signature base bytes are
|
|
87
|
-
* passed as a hex string and signed with `{ raw: true }` so the proxy
|
|
88
|
-
* interprets them as raw bytes (not UTF-8). Note: the proxy still applies
|
|
89
|
-
* EIP-191 personal_sign wrapping (viem `signMessage({ message: { raw } })`).
|
|
90
|
-
*/
|
|
91
|
-
export async function signRawMessage(rawHex, config = {}) {
|
|
92
|
-
const data = await proxyRequest(config, "/sign-message", {
|
|
93
|
-
message: rawHex,
|
|
94
|
-
raw: true,
|
|
95
|
-
});
|
|
96
|
-
return { signature: data.signature, address: data.address };
|
|
97
|
-
}
|
|
98
|
-
/**
|
|
99
|
-
* Sign a transaction via the keyring proxy.
|
|
100
|
-
* Only the signed transaction is returned.
|
|
101
|
-
*/
|
|
102
|
-
export async function signTransaction(tx, config = {}) {
|
|
103
|
-
const data = await proxyRequest(config, "/sign-transaction", {
|
|
104
|
-
tx: tx,
|
|
105
|
-
});
|
|
106
|
-
return { signedTx: data.signedTx, address: data.address };
|
|
107
|
-
}
|
|
108
74
|
/**
|
|
109
75
|
* Sign an EIP-7702 authorization for delegating the EOA to a contract.
|
|
110
76
|
*
|
|
111
77
|
* This allows the agent's EOA to temporarily act as a smart contract
|
|
112
|
-
* during a type 4 transaction.
|
|
78
|
+
* during a type 4 transaction.
|
|
113
79
|
*/
|
|
114
80
|
export async function signAuthorization(auth, config = {}) {
|
|
115
81
|
const data = await proxyRequest(config, "/sign-authorization", { auth });
|
package/dist/next.d.ts
CHANGED
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
* ```
|
|
18
18
|
*/
|
|
19
19
|
import { type SiwaAgent } from './erc8128.js';
|
|
20
|
+
import type { SignerType } from './signer.js';
|
|
20
21
|
export type { SiwaAgent };
|
|
21
22
|
export interface WithSiwaOptions {
|
|
22
23
|
/** HMAC secret for receipt verification. Defaults to RECEIPT_SECRET or SIWA_SECRET env. */
|
|
@@ -25,6 +26,8 @@ export interface WithSiwaOptions {
|
|
|
25
26
|
rpcUrl?: string;
|
|
26
27
|
/** Enable onchain ownerOf check. */
|
|
27
28
|
verifyOnchain?: boolean;
|
|
29
|
+
/** Allowed signer types. Omit to accept all. */
|
|
30
|
+
allowedSignerTypes?: SignerType[];
|
|
28
31
|
}
|
|
29
32
|
/** CORS headers required by SIWA-authenticated requests. */
|
|
30
33
|
export declare function corsHeaders(): Record<string, string>;
|
package/dist/next.js
CHANGED
|
@@ -60,6 +60,7 @@ export function withSiwa(handler, options) {
|
|
|
60
60
|
receiptSecret: secret,
|
|
61
61
|
rpcUrl: options?.rpcUrl,
|
|
62
62
|
verifyOnchain: options?.verifyOnchain,
|
|
63
|
+
allowedSignerTypes: options?.allowedSignerTypes,
|
|
63
64
|
};
|
|
64
65
|
const result = await verifyAuthenticatedRequest(nextjsToFetchRequest(verifyReq), verifyOptions);
|
|
65
66
|
if (!result.valid) {
|
package/dist/receipt.d.ts
CHANGED
|
@@ -14,12 +14,14 @@
|
|
|
14
14
|
* Format: base64url(json).base64url(hmac-sha256)
|
|
15
15
|
* Same token format as nonce tokens in siwa.ts.
|
|
16
16
|
*/
|
|
17
|
+
import type { SignerType } from './signer.js';
|
|
17
18
|
export interface ReceiptPayload {
|
|
18
19
|
address: string;
|
|
19
20
|
agentId: number;
|
|
20
21
|
agentRegistry: string;
|
|
21
22
|
chainId: number;
|
|
22
23
|
verified: 'offline' | 'onchain';
|
|
24
|
+
signerType?: SignerType;
|
|
23
25
|
iat: number;
|
|
24
26
|
exp: number;
|
|
25
27
|
}
|