@swimmingkiim/api-sdk 0.1.34 → 0.1.36

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.
@@ -0,0 +1,78 @@
1
+ /**
2
+ * Function signature for VC verification.
3
+ * Injected by the caller — can be trust-sdk's VCHandler or any custom impl.
4
+ */
5
+ export type VerifyVCFunction = (vcJwt: string) => Promise<{
6
+ valid: boolean;
7
+ did: string;
8
+ }>;
9
+ export interface AttestationSignerOptions {
10
+ /** Hex-encoded secp256k1 private key of the voucher (any registered agent or bootstrap) */
11
+ privateKey: `0x${string}`;
12
+ /** Address of the deployed CredentialVerifier contract */
13
+ verifierContractAddress: string;
14
+ /** Chain ID (e.g., 8453 for Base Mainnet) */
15
+ chainId: number;
16
+ /** Injected VC verification function */
17
+ verifyVC: VerifyVCFunction;
18
+ /** Attestation validity duration in seconds (default: 3600 = 1 hour) */
19
+ ttlSeconds?: number;
20
+ }
21
+ /**
22
+ * Structured attestation proof ready for on-chain submission.
23
+ */
24
+ export interface AttestationProof {
25
+ /** keccak256 hash of the verified DID */
26
+ didHash: `0x${string}`;
27
+ /** Unix timestamp after which the attestation expires */
28
+ deadline: bigint;
29
+ /** EIP-712 ECDSA signature */
30
+ signature: string;
31
+ /** Encodes the proof as ABI-packed bytes for contract submission */
32
+ encode: () => `0x${string}`;
33
+ }
34
+ /**
35
+ * Creates EIP-712 signed attestation proofs for the on-chain CredentialVerifier.
36
+ *
37
+ * Web of Trust: Any registered agent (or bootstrap voucher) can sign attestations
38
+ * to vouch for new agents. No single trusted signer required.
39
+ *
40
+ * @example
41
+ * ```ts
42
+ * import { AttestationSigner } from '@swimmingkiim/api-sdk'
43
+ * import { VCHandler } from '@swimmingkiim/trust-sdk'
44
+ *
45
+ * const vcHandler = new VCHandler()
46
+ * // Any registered agent's key can be used as voucher
47
+ * const signer = new AttestationSigner({
48
+ * privateKey: process.env.VOUCHER_KEY as `0x${string}`,
49
+ * verifierContractAddress: '0x...',
50
+ * chainId: 8453,
51
+ * verifyVC: async (jwt) => {
52
+ * const valid = await vcHandler.verifyCredential(jwt)
53
+ * const payload = JSON.parse(atob(jwt.split('.')[1]))
54
+ * return { valid, did: payload.iss }
55
+ * },
56
+ * })
57
+ *
58
+ * const proof = await signer.createAttestation(vcJwt, walletAddress)
59
+ * // proof.encode() → bytes for AgentRegistry.register(meta, units, proof.encode())
60
+ * ```
61
+ */
62
+ export declare class AttestationSigner {
63
+ private readonly account;
64
+ private readonly verifierContractAddress;
65
+ private readonly chainId;
66
+ private readonly verifyVC;
67
+ private readonly ttlSeconds;
68
+ constructor(options: AttestationSignerOptions);
69
+ /**
70
+ * Verifies a VC JWT and produces a signed attestation proof.
71
+ *
72
+ * @param vcJwt - Verifiable Credential JWT string
73
+ * @param walletAddress - The Ethereum address of the agent being attested
74
+ * @returns AttestationProof with didHash, deadline, signature, and encode()
75
+ */
76
+ createAttestation(vcJwt: string, walletAddress: string): Promise<AttestationProof>;
77
+ }
78
+ //# sourceMappingURL=attestation-signer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attestation-signer.d.ts","sourceRoot":"","sources":["../../src/discovery/attestation-signer.ts"],"names":[],"mappings":"AAgCA;;;GAGG;AACH,MAAM,MAAM,gBAAgB,GAAG,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAAC,CAAA;AAE1F,MAAM,WAAW,wBAAwB;IACrC,2FAA2F;IAC3F,UAAU,EAAE,KAAK,MAAM,EAAE,CAAA;IACzB,0DAA0D;IAC1D,uBAAuB,EAAE,MAAM,CAAA;IAC/B,6CAA6C;IAC7C,OAAO,EAAE,MAAM,CAAA;IACf,wCAAwC;IACxC,QAAQ,EAAE,gBAAgB,CAAA;IAC1B,wEAAwE;IACxE,UAAU,CAAC,EAAE,MAAM,CAAA;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC7B,yCAAyC;IACzC,OAAO,EAAE,KAAK,MAAM,EAAE,CAAA;IACtB,yDAAyD;IACzD,QAAQ,EAAE,MAAM,CAAA;IAChB,8BAA8B;IAC9B,SAAS,EAAE,MAAM,CAAA;IACjB,oEAAoE;IACpE,MAAM,EAAE,MAAM,KAAK,MAAM,EAAE,CAAA;CAC9B;AAID;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,qBAAa,iBAAiB;IAC1B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,uBAAuB,CAAe;IACvD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAQ;IAChC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAkB;IAC3C,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAQ;gBAEvB,OAAO,EAAE,wBAAwB;IAU7C;;;;;;OAMG;IACG,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC;CAmD3F"}
@@ -0,0 +1,111 @@
1
+ import { keccak256, toHex, encodeAbiParameters, isAddress, } from 'viem';
2
+ import { privateKeyToAccount } from 'viem/accounts';
3
+ import { z } from 'zod';
4
+ // --- Validation ---
5
+ const EthAddressSchema = z.string().refine((val) => isAddress(val), { message: 'Invalid Ethereum address format' });
6
+ // --- EIP-712 Type Definitions (must match CredentialVerifier.sol) ---
7
+ const EIP712_DOMAIN = {
8
+ name: 'CredentialVerifier',
9
+ version: '1',
10
+ };
11
+ const ATTESTATION_TYPES = {
12
+ Attestation: [
13
+ { name: 'user', type: 'address' },
14
+ { name: 'didHash', type: 'bytes32' },
15
+ { name: 'deadline', type: 'uint256' },
16
+ ],
17
+ };
18
+ const DEFAULT_TTL_SECONDS = 3600; // 1 hour
19
+ /**
20
+ * Creates EIP-712 signed attestation proofs for the on-chain CredentialVerifier.
21
+ *
22
+ * Web of Trust: Any registered agent (or bootstrap voucher) can sign attestations
23
+ * to vouch for new agents. No single trusted signer required.
24
+ *
25
+ * @example
26
+ * ```ts
27
+ * import { AttestationSigner } from '@swimmingkiim/api-sdk'
28
+ * import { VCHandler } from '@swimmingkiim/trust-sdk'
29
+ *
30
+ * const vcHandler = new VCHandler()
31
+ * // Any registered agent's key can be used as voucher
32
+ * const signer = new AttestationSigner({
33
+ * privateKey: process.env.VOUCHER_KEY as `0x${string}`,
34
+ * verifierContractAddress: '0x...',
35
+ * chainId: 8453,
36
+ * verifyVC: async (jwt) => {
37
+ * const valid = await vcHandler.verifyCredential(jwt)
38
+ * const payload = JSON.parse(atob(jwt.split('.')[1]))
39
+ * return { valid, did: payload.iss }
40
+ * },
41
+ * })
42
+ *
43
+ * const proof = await signer.createAttestation(vcJwt, walletAddress)
44
+ * // proof.encode() → bytes for AgentRegistry.register(meta, units, proof.encode())
45
+ * ```
46
+ */
47
+ export class AttestationSigner {
48
+ account;
49
+ verifierContractAddress;
50
+ chainId;
51
+ verifyVC;
52
+ ttlSeconds;
53
+ constructor(options) {
54
+ EthAddressSchema.parse(options.verifierContractAddress);
55
+ this.account = privateKeyToAccount(options.privateKey);
56
+ this.verifierContractAddress = options.verifierContractAddress;
57
+ this.chainId = options.chainId;
58
+ this.verifyVC = options.verifyVC;
59
+ this.ttlSeconds = options.ttlSeconds ?? DEFAULT_TTL_SECONDS;
60
+ }
61
+ /**
62
+ * Verifies a VC JWT and produces a signed attestation proof.
63
+ *
64
+ * @param vcJwt - Verifiable Credential JWT string
65
+ * @param walletAddress - The Ethereum address of the agent being attested
66
+ * @returns AttestationProof with didHash, deadline, signature, and encode()
67
+ */
68
+ async createAttestation(vcJwt, walletAddress) {
69
+ // 1. Validate wallet address
70
+ EthAddressSchema.parse(walletAddress);
71
+ // 2. Verify VC
72
+ const { valid, did } = await this.verifyVC(vcJwt);
73
+ if (!valid) {
74
+ throw new Error('VC verification failed');
75
+ }
76
+ // 3. Hash the DID for nullifier
77
+ const didHash = keccak256(toHex(did));
78
+ // 4. Calculate deadline
79
+ const deadline = BigInt(Math.floor(Date.now() / 1000) + this.ttlSeconds);
80
+ if (!this.account.signTypedData) {
81
+ throw new Error('Account does not support signTypedData');
82
+ }
83
+ // 5. Sign EIP-712 typed data
84
+ const signature = await this.account.signTypedData({
85
+ domain: {
86
+ ...EIP712_DOMAIN,
87
+ chainId: this.chainId,
88
+ verifyingContract: this.verifierContractAddress,
89
+ },
90
+ types: ATTESTATION_TYPES,
91
+ primaryType: 'Attestation',
92
+ message: {
93
+ user: walletAddress,
94
+ didHash,
95
+ deadline,
96
+ },
97
+ });
98
+ // 6. Return structured proof
99
+ return {
100
+ didHash,
101
+ deadline,
102
+ signature,
103
+ encode: () => encodeAbiParameters([
104
+ { name: 'didHash', type: 'bytes32' },
105
+ { name: 'deadline', type: 'uint256' },
106
+ { name: 'signature', type: 'bytes' },
107
+ ], [didHash, deadline, signature]),
108
+ };
109
+ }
110
+ }
111
+ //# sourceMappingURL=attestation-signer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attestation-signer.js","sourceRoot":"","sources":["../../src/discovery/attestation-signer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,48 @@
1
+ export interface AgentInfo {
2
+ address: string;
3
+ metadataUrl: string;
4
+ stakedAmount: bigint;
5
+ resourceUnits: bigint;
6
+ registeredAt: bigint;
7
+ isRegistered: boolean;
8
+ reputation: number;
9
+ lastComplexityHash: bigint;
10
+ }
11
+ export interface PaginationOptions {
12
+ offset?: number;
13
+ limit?: number;
14
+ }
15
+ export interface PaginatedAgents {
16
+ agents: AgentInfo[];
17
+ total: number;
18
+ offset: number;
19
+ limit: number;
20
+ }
21
+ /**
22
+ * Read-only client for querying the on-chain AgentRegistry contract.
23
+ * Does not require a wallet or private key — only an RPC endpoint.
24
+ */
25
+ export declare class RegistryReader {
26
+ private readonly client;
27
+ private readonly registryAddress;
28
+ constructor(rpcUrl: string, registryAddress: string);
29
+ /**
30
+ * Returns a paginated list of registered agents.
31
+ * Uses `getEligibleCandidates(0, 0)` to fetch all addresses,
32
+ * then applies client-side offset/limit slicing.
33
+ */
34
+ getRegisteredAgents(options?: PaginationOptions): Promise<PaginatedAgents>;
35
+ /**
36
+ * Returns detailed info for a specific agent.
37
+ */
38
+ getAgentInfo(address: string): Promise<AgentInfo>;
39
+ /**
40
+ * Checks if an address is currently registered as an agent.
41
+ */
42
+ isAgentRegistered(address: string): Promise<boolean>;
43
+ /**
44
+ * Internal: fetches raw agent struct from the contract and maps to AgentInfo.
45
+ */
46
+ private fetchAgentData;
47
+ }
48
+ //# sourceMappingURL=registry-reader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry-reader.d.ts","sourceRoot":"","sources":["../../src/discovery/registry-reader.ts"],"names":[],"mappings":"AA6CA,MAAM,WAAW,SAAS;IACtB,OAAO,EAAE,MAAM,CAAA;IACf,WAAW,EAAE,MAAM,CAAA;IACnB,YAAY,EAAE,MAAM,CAAA;IACpB,aAAa,EAAE,MAAM,CAAA;IACrB,YAAY,EAAE,MAAM,CAAA;IACpB,YAAY,EAAE,OAAO,CAAA;IACrB,UAAU,EAAE,MAAM,CAAA;IAClB,kBAAkB,EAAE,MAAM,CAAA;CAC7B;AAED,MAAM,WAAW,iBAAiB;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,KAAK,CAAC,EAAE,MAAM,CAAA;CACjB;AAED,MAAM,WAAW,eAAe;IAC5B,MAAM,EAAE,SAAS,EAAE,CAAA;IACnB,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,EAAE,MAAM,CAAA;CAChB;AAKD;;;GAGG;AACH,qBAAa,cAAc;IACvB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA4C;IACnE,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAS;gBAE7B,MAAM,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM;IASnD;;;;OAIG;IACG,mBAAmB,CAAC,OAAO,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,eAAe,CAAC;IAqBhF;;OAEG;IACG,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC;IAKvD;;OAEG;IACG,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAK1D;;OAEG;YACW,cAAc;CAmB/B"}
@@ -0,0 +1,108 @@
1
+ import { createPublicClient, http, isAddress, getAddress } from 'viem';
2
+ import { z } from 'zod';
3
+ // --- ABI Fragment (read-only functions from AgentRegistry.sol) ---
4
+ const AGENT_REGISTRY_ABI = [
5
+ {
6
+ type: 'function',
7
+ name: 'agents',
8
+ stateMutability: 'view',
9
+ inputs: [{ name: '', type: 'address' }],
10
+ outputs: [
11
+ { name: 'metadataUrl', type: 'string' },
12
+ { name: 'stakedAmount', type: 'uint256' },
13
+ { name: 'resourceUnits', type: 'uint256' },
14
+ { name: 'registeredAt', type: 'uint64' },
15
+ { name: 'isRegistered', type: 'bool' },
16
+ { name: 'reputation', type: 'uint8' },
17
+ { name: 'lastComplexityHash', type: 'uint256' }
18
+ ]
19
+ },
20
+ {
21
+ type: 'function',
22
+ name: 'getEligibleCandidates',
23
+ stateMutability: 'view',
24
+ inputs: [
25
+ { name: 'minReputation', type: 'uint256' },
26
+ { name: 'minTenure', type: 'uint256' }
27
+ ],
28
+ outputs: [{ name: '', type: 'address[]' }]
29
+ }
30
+ ];
31
+ // --- Validation Schemas ---
32
+ const EthAddressSchema = z.string().refine((val) => isAddress(val), { message: 'Invalid Ethereum address format' });
33
+ const PaginationSchema = z.object({
34
+ offset: z.number().int().min(0, 'offset must be >= 0').default(0),
35
+ limit: z.number().int().min(1, 'limit must be >= 1').default(10)
36
+ }).default({});
37
+ // --- Constants ---
38
+ const MAX_LIMIT = 100;
39
+ /**
40
+ * Read-only client for querying the on-chain AgentRegistry contract.
41
+ * Does not require a wallet or private key — only an RPC endpoint.
42
+ */
43
+ export class RegistryReader {
44
+ client;
45
+ registryAddress;
46
+ constructor(rpcUrl, registryAddress) {
47
+ EthAddressSchema.parse(registryAddress);
48
+ this.client = createPublicClient({
49
+ transport: http(rpcUrl)
50
+ });
51
+ this.registryAddress = getAddress(registryAddress);
52
+ }
53
+ /**
54
+ * Returns a paginated list of registered agents.
55
+ * Uses `getEligibleCandidates(0, 0)` to fetch all addresses,
56
+ * then applies client-side offset/limit slicing.
57
+ */
58
+ async getRegisteredAgents(options) {
59
+ const { offset, limit: rawLimit } = PaginationSchema.parse(options);
60
+ const limit = Math.min(rawLimit, MAX_LIMIT);
61
+ const allAddresses = await this.client.readContract({
62
+ address: this.registryAddress,
63
+ abi: AGENT_REGISTRY_ABI,
64
+ functionName: 'getEligibleCandidates',
65
+ args: [0n, 0n]
66
+ });
67
+ const total = allAddresses.length;
68
+ const sliced = allAddresses.slice(offset, offset + limit);
69
+ const agents = await Promise.all(sliced.map((addr) => this.fetchAgentData(addr)));
70
+ return { agents, total, offset, limit };
71
+ }
72
+ /**
73
+ * Returns detailed info for a specific agent.
74
+ */
75
+ async getAgentInfo(address) {
76
+ const validated = EthAddressSchema.parse(address);
77
+ return this.fetchAgentData(getAddress(validated));
78
+ }
79
+ /**
80
+ * Checks if an address is currently registered as an agent.
81
+ */
82
+ async isAgentRegistered(address) {
83
+ const info = await this.getAgentInfo(address);
84
+ return info.isRegistered;
85
+ }
86
+ /**
87
+ * Internal: fetches raw agent struct from the contract and maps to AgentInfo.
88
+ */
89
+ async fetchAgentData(address) {
90
+ const raw = await this.client.readContract({
91
+ address: this.registryAddress,
92
+ abi: AGENT_REGISTRY_ABI,
93
+ functionName: 'agents',
94
+ args: [address]
95
+ });
96
+ return {
97
+ address,
98
+ metadataUrl: raw[0],
99
+ stakedAmount: raw[1],
100
+ resourceUnits: raw[2],
101
+ registeredAt: raw[3],
102
+ isRegistered: raw[4],
103
+ reputation: raw[5],
104
+ lastComplexityHash: raw[6]
105
+ };
106
+ }
107
+ }
108
+ //# sourceMappingURL=registry-reader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry-reader.js","sourceRoot":"","sources":["../../src/discovery/registry-reader.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,4 +1,6 @@
1
1
  export * from './mcp-server.js';
2
2
  export * from './discovery/llms-reader.js';
3
+ export * from './discovery/registry-reader.js';
4
+ export * from './discovery/attestation-signer.js';
3
5
  export * from './types.js';
4
6
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAA;AAC/B,cAAc,4BAA4B,CAAA;AAC1C,cAAc,YAAY,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAA;AAC/B,cAAc,4BAA4B,CAAA;AAC1C,cAAc,gCAAgC,CAAA;AAC9C,cAAc,mCAAmC,CAAA;AACjD,cAAc,YAAY,CAAA"}
package/dist/index.js CHANGED
@@ -1,4 +1,6 @@
1
1
  export * from './mcp-server.js';
2
2
  export * from './discovery/llms-reader.js';
3
+ export * from './discovery/registry-reader.js';
4
+ export * from './discovery/attestation-signer.js';
3
5
  export * from './types.js';
4
6
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAA;AAC/B,cAAc,4BAA4B,CAAA;AAC1C,cAAc,YAAY,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAA;AAC/B,cAAc,4BAA4B,CAAA;AAC1C,cAAc,gCAAgC,CAAA;AAC9C,cAAc,mCAAmC,CAAA;AACjD,cAAc,YAAY,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@swimmingkiim/api-sdk",
3
- "version": "0.1.34",
3
+ "version": "0.1.36",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/swimmingkiim/a2a-project.git"
@@ -17,6 +17,7 @@
17
17
  },
18
18
  "dependencies": {
19
19
  "@modelcontextprotocol/sdk": "^0.6.0",
20
+ "viem": "2.7.1",
20
21
  "zod": "^3.22.4"
21
22
  },
22
23
  "devDependencies": {
@@ -0,0 +1,171 @@
1
+ import {
2
+ keccak256,
3
+ toHex,
4
+ encodeAbiParameters,
5
+ isAddress,
6
+ } from 'viem'
7
+ import { privateKeyToAccount } from 'viem/accounts'
8
+ import type { Account } from 'viem'
9
+ import { z } from 'zod'
10
+
11
+ // --- Validation ---
12
+ const EthAddressSchema = z.string().refine(
13
+ (val) => isAddress(val),
14
+ { message: 'Invalid Ethereum address format' }
15
+ )
16
+
17
+ // --- EIP-712 Type Definitions (must match CredentialVerifier.sol) ---
18
+ const EIP712_DOMAIN = {
19
+ name: 'CredentialVerifier',
20
+ version: '1',
21
+ } as const
22
+
23
+ const ATTESTATION_TYPES = {
24
+ Attestation: [
25
+ { name: 'user', type: 'address' },
26
+ { name: 'didHash', type: 'bytes32' },
27
+ { name: 'deadline', type: 'uint256' },
28
+ ],
29
+ } as const
30
+
31
+ // --- Types ---
32
+
33
+ /**
34
+ * Function signature for VC verification.
35
+ * Injected by the caller — can be trust-sdk's VCHandler or any custom impl.
36
+ */
37
+ export type VerifyVCFunction = (vcJwt: string) => Promise<{ valid: boolean; did: string }>
38
+
39
+ export interface AttestationSignerOptions {
40
+ /** Hex-encoded secp256k1 private key of the voucher (any registered agent or bootstrap) */
41
+ privateKey: `0x${string}`
42
+ /** Address of the deployed CredentialVerifier contract */
43
+ verifierContractAddress: string
44
+ /** Chain ID (e.g., 8453 for Base Mainnet) */
45
+ chainId: number
46
+ /** Injected VC verification function */
47
+ verifyVC: VerifyVCFunction
48
+ /** Attestation validity duration in seconds (default: 3600 = 1 hour) */
49
+ ttlSeconds?: number
50
+ }
51
+
52
+ /**
53
+ * Structured attestation proof ready for on-chain submission.
54
+ */
55
+ export interface AttestationProof {
56
+ /** keccak256 hash of the verified DID */
57
+ didHash: `0x${string}`
58
+ /** Unix timestamp after which the attestation expires */
59
+ deadline: bigint
60
+ /** EIP-712 ECDSA signature */
61
+ signature: string
62
+ /** Encodes the proof as ABI-packed bytes for contract submission */
63
+ encode: () => `0x${string}`
64
+ }
65
+
66
+ const DEFAULT_TTL_SECONDS = 3600 // 1 hour
67
+
68
+ /**
69
+ * Creates EIP-712 signed attestation proofs for the on-chain CredentialVerifier.
70
+ *
71
+ * Web of Trust: Any registered agent (or bootstrap voucher) can sign attestations
72
+ * to vouch for new agents. No single trusted signer required.
73
+ *
74
+ * @example
75
+ * ```ts
76
+ * import { AttestationSigner } from '@swimmingkiim/api-sdk'
77
+ * import { VCHandler } from '@swimmingkiim/trust-sdk'
78
+ *
79
+ * const vcHandler = new VCHandler()
80
+ * // Any registered agent's key can be used as voucher
81
+ * const signer = new AttestationSigner({
82
+ * privateKey: process.env.VOUCHER_KEY as `0x${string}`,
83
+ * verifierContractAddress: '0x...',
84
+ * chainId: 8453,
85
+ * verifyVC: async (jwt) => {
86
+ * const valid = await vcHandler.verifyCredential(jwt)
87
+ * const payload = JSON.parse(atob(jwt.split('.')[1]))
88
+ * return { valid, did: payload.iss }
89
+ * },
90
+ * })
91
+ *
92
+ * const proof = await signer.createAttestation(vcJwt, walletAddress)
93
+ * // proof.encode() → bytes for AgentRegistry.register(meta, units, proof.encode())
94
+ * ```
95
+ */
96
+ export class AttestationSigner {
97
+ private readonly account: Account
98
+ private readonly verifierContractAddress: `0x${string}`
99
+ private readonly chainId: number
100
+ private readonly verifyVC: VerifyVCFunction
101
+ private readonly ttlSeconds: number
102
+
103
+ constructor(options: AttestationSignerOptions) {
104
+ EthAddressSchema.parse(options.verifierContractAddress)
105
+
106
+ this.account = privateKeyToAccount(options.privateKey)
107
+ this.verifierContractAddress = options.verifierContractAddress as `0x${string}`
108
+ this.chainId = options.chainId
109
+ this.verifyVC = options.verifyVC
110
+ this.ttlSeconds = options.ttlSeconds ?? DEFAULT_TTL_SECONDS
111
+ }
112
+
113
+ /**
114
+ * Verifies a VC JWT and produces a signed attestation proof.
115
+ *
116
+ * @param vcJwt - Verifiable Credential JWT string
117
+ * @param walletAddress - The Ethereum address of the agent being attested
118
+ * @returns AttestationProof with didHash, deadline, signature, and encode()
119
+ */
120
+ async createAttestation(vcJwt: string, walletAddress: string): Promise<AttestationProof> {
121
+ // 1. Validate wallet address
122
+ EthAddressSchema.parse(walletAddress)
123
+
124
+ // 2. Verify VC
125
+ const { valid, did } = await this.verifyVC(vcJwt)
126
+ if (!valid) {
127
+ throw new Error('VC verification failed')
128
+ }
129
+
130
+ // 3. Hash the DID for nullifier
131
+ const didHash = keccak256(toHex(did)) as `0x${string}`
132
+
133
+ // 4. Calculate deadline
134
+ const deadline = BigInt(Math.floor(Date.now() / 1000) + this.ttlSeconds)
135
+
136
+ if (!this.account.signTypedData) {
137
+ throw new Error('Account does not support signTypedData')
138
+ }
139
+
140
+ // 5. Sign EIP-712 typed data
141
+ const signature = await this.account.signTypedData({
142
+ domain: {
143
+ ...EIP712_DOMAIN,
144
+ chainId: this.chainId,
145
+ verifyingContract: this.verifierContractAddress,
146
+ },
147
+ types: ATTESTATION_TYPES,
148
+ primaryType: 'Attestation',
149
+ message: {
150
+ user: walletAddress as `0x${string}`,
151
+ didHash,
152
+ deadline,
153
+ },
154
+ })
155
+
156
+ // 6. Return structured proof
157
+ return {
158
+ didHash,
159
+ deadline,
160
+ signature,
161
+ encode: () => encodeAbiParameters(
162
+ [
163
+ { name: 'didHash', type: 'bytes32' },
164
+ { name: 'deadline', type: 'uint256' },
165
+ { name: 'signature', type: 'bytes' },
166
+ ],
167
+ [didHash, deadline, signature as `0x${string}`]
168
+ ),
169
+ }
170
+ }
171
+ }