@swimmingkiim/api-sdk 0.1.35 → 0.1.37
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/dist/discovery/attestation-signer.d.ts +78 -0
- package/dist/discovery/attestation-signer.d.ts.map +1 -0
- package/dist/discovery/attestation-signer.js +111 -0
- package/dist/discovery/attestation-signer.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/quantum-client.d.ts +49 -0
- package/dist/quantum-client.d.ts.map +1 -0
- package/dist/quantum-client.js +127 -0
- package/dist/quantum-client.js.map +1 -0
- package/package.json +1 -1
- package/src/discovery/attestation-signer.ts +171 -0
- package/src/index.ts +2 -0
- package/src/quantum-client.ts +151 -0
- package/test/attestation-signer.test.ts +162 -0
- package/test/quantum-client.test.ts +101 -0
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -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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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
export * from './mcp-server.js';
|
|
2
2
|
export * from './discovery/llms-reader.js';
|
|
3
3
|
export * from './discovery/registry-reader.js';
|
|
4
|
+
export * from './discovery/attestation-signer.js';
|
|
5
|
+
export * from './quantum-client.js';
|
|
4
6
|
export * from './types.js';
|
|
5
7
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -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,gCAAgC,CAAA;AAC9C,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,qBAAqB,CAAA;AACnC,cAAc,YAAY,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
export * from './mcp-server.js';
|
|
2
2
|
export * from './discovery/llms-reader.js';
|
|
3
3
|
export * from './discovery/registry-reader.js';
|
|
4
|
+
export * from './discovery/attestation-signer.js';
|
|
5
|
+
export * from './quantum-client.js';
|
|
4
6
|
export * from './types.js';
|
|
5
7
|
//# 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,gCAAgC,CAAA;AAC9C,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,qBAAqB,CAAA;AACnC,cAAc,YAAY,CAAA"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { Address } from 'viem';
|
|
2
|
+
export interface QuantumClientOptions {
|
|
3
|
+
rpcUrl: string;
|
|
4
|
+
contractAddress: Address;
|
|
5
|
+
baseBackoffMs?: number;
|
|
6
|
+
maxBackoffMs?: number;
|
|
7
|
+
maxRetries?: number;
|
|
8
|
+
}
|
|
9
|
+
export declare class OverheatedError extends Error {
|
|
10
|
+
constructor(message: string);
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Client for interacting with the QuantumTaskBuffer smart contract.
|
|
14
|
+
* Implements V_AI (Self-Restraint) by structurally enforcing an exponential backoff
|
|
15
|
+
* when the macroscopic system is detected as 'overheated'.
|
|
16
|
+
*/
|
|
17
|
+
export declare class QuantumTaskClient {
|
|
18
|
+
private publicClient;
|
|
19
|
+
private contractAddress;
|
|
20
|
+
private baseBackoffMs;
|
|
21
|
+
private maxBackoffMs;
|
|
22
|
+
private maxRetries;
|
|
23
|
+
constructor(options: QuantumClientOptions);
|
|
24
|
+
/**
|
|
25
|
+
* Checks the thermodynamic state of the buffer.
|
|
26
|
+
* @returns boolean true if the system pending tasks exceed CRITICAL_MASS.
|
|
27
|
+
*/
|
|
28
|
+
isOverheated(): Promise<boolean>;
|
|
29
|
+
/**
|
|
30
|
+
* Sleep helper for backoff
|
|
31
|
+
*/
|
|
32
|
+
private sleep;
|
|
33
|
+
/**
|
|
34
|
+
* Prepares the `submitTask` transaction call data, enforcing V_AI (Thermodynamic Throttling).
|
|
35
|
+
* The agent SDK intrinsically checks the `isOverheated` state. If the system is overheated,
|
|
36
|
+
* the SDK *refuses* to generate the transaction and applies an exponential backoff.
|
|
37
|
+
*
|
|
38
|
+
* @param complexityHash The unique hash of the task logic to submit.
|
|
39
|
+
* @param metadataUri The URI (e.g. ipfs://...) pointing to the standard JSON metadata.
|
|
40
|
+
* @returns The call data object for use with the Paymaster or standard transaction execution.
|
|
41
|
+
* @throws OverheatedError if max retries are exceeded while the system remains overheated.
|
|
42
|
+
*/
|
|
43
|
+
enforceThrottleAndGetTaskCall(complexityHash: bigint, metadataUri: string): Promise<{
|
|
44
|
+
to: Address;
|
|
45
|
+
value: bigint;
|
|
46
|
+
data: string;
|
|
47
|
+
}>;
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=quantum-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"quantum-client.d.ts","sourceRoot":"","sources":["../src/quantum-client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAyC,OAAO,EAAgB,MAAM,MAAM,CAAC;AAoCpF,MAAM,WAAW,oBAAoB;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,eAAe,EAAE,OAAO,CAAC;IACzB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,qBAAa,eAAgB,SAAQ,KAAK;gBAC1B,OAAO,EAAE,MAAM;CAI9B;AAED;;;;GAIG;AACH,qBAAa,iBAAiB;IAC1B,OAAO,CAAC,YAAY,CAAe;IACnC,OAAO,CAAC,eAAe,CAAU;IACjC,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,UAAU,CAAS;gBAEf,OAAO,EAAE,oBAAoB;IAUzC;;;OAGG;IACG,YAAY,IAAI,OAAO,CAAC,OAAO,CAAC;IAetC;;OAEG;IACH,OAAO,CAAC,KAAK;IAIb;;;;;;;;;OASG;IACG,6BAA6B,CAAC,cAAc,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,EAAE,EAAE,OAAO,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;CAyC1I"}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { createPublicClient, http, getContract } from 'viem';
|
|
2
|
+
const QUANTUM_TASK_BUFFER_ABI = [
|
|
3
|
+
{
|
|
4
|
+
"inputs": [],
|
|
5
|
+
"name": "isOverheated",
|
|
6
|
+
"outputs": [
|
|
7
|
+
{
|
|
8
|
+
"internalType": "bool",
|
|
9
|
+
"name": "",
|
|
10
|
+
"type": "bool"
|
|
11
|
+
}
|
|
12
|
+
],
|
|
13
|
+
"stateMutability": "view",
|
|
14
|
+
"type": "function"
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
"inputs": [
|
|
18
|
+
{
|
|
19
|
+
"internalType": "uint256",
|
|
20
|
+
"name": "_complexityHash",
|
|
21
|
+
"type": "uint256"
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"internalType": "string",
|
|
25
|
+
"name": "_metadataUri",
|
|
26
|
+
"type": "string"
|
|
27
|
+
}
|
|
28
|
+
],
|
|
29
|
+
"name": "submitTask",
|
|
30
|
+
"outputs": [],
|
|
31
|
+
"stateMutability": "nonpayable",
|
|
32
|
+
"type": "function"
|
|
33
|
+
}
|
|
34
|
+
];
|
|
35
|
+
export class OverheatedError extends Error {
|
|
36
|
+
constructor(message) {
|
|
37
|
+
super(message);
|
|
38
|
+
this.name = 'OverheatedError';
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Client for interacting with the QuantumTaskBuffer smart contract.
|
|
43
|
+
* Implements V_AI (Self-Restraint) by structurally enforcing an exponential backoff
|
|
44
|
+
* when the macroscopic system is detected as 'overheated'.
|
|
45
|
+
*/
|
|
46
|
+
export class QuantumTaskClient {
|
|
47
|
+
publicClient;
|
|
48
|
+
contractAddress;
|
|
49
|
+
baseBackoffMs;
|
|
50
|
+
maxBackoffMs;
|
|
51
|
+
maxRetries;
|
|
52
|
+
constructor(options) {
|
|
53
|
+
this.publicClient = createPublicClient({
|
|
54
|
+
transport: http(options.rpcUrl),
|
|
55
|
+
});
|
|
56
|
+
this.contractAddress = options.contractAddress;
|
|
57
|
+
this.baseBackoffMs = options.baseBackoffMs || 30_000; // 30 seconds default
|
|
58
|
+
this.maxBackoffMs = options.maxBackoffMs || 600_000; // 10 mins default
|
|
59
|
+
this.maxRetries = options.maxRetries || 5;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Checks the thermodynamic state of the buffer.
|
|
63
|
+
* @returns boolean true if the system pending tasks exceed CRITICAL_MASS.
|
|
64
|
+
*/
|
|
65
|
+
async isOverheated() {
|
|
66
|
+
const contract = getContract({
|
|
67
|
+
address: this.contractAddress,
|
|
68
|
+
abi: QUANTUM_TASK_BUFFER_ABI,
|
|
69
|
+
client: this.publicClient
|
|
70
|
+
});
|
|
71
|
+
try {
|
|
72
|
+
return await contract.read.isOverheated();
|
|
73
|
+
}
|
|
74
|
+
catch (error) {
|
|
75
|
+
console.error("Failed to read isOverheated state from contract:", error);
|
|
76
|
+
throw new Error("Failed to check thermodynamic state. Assuming overheated for safety.");
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Sleep helper for backoff
|
|
81
|
+
*/
|
|
82
|
+
sleep(ms) {
|
|
83
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Prepares the `submitTask` transaction call data, enforcing V_AI (Thermodynamic Throttling).
|
|
87
|
+
* The agent SDK intrinsically checks the `isOverheated` state. If the system is overheated,
|
|
88
|
+
* the SDK *refuses* to generate the transaction and applies an exponential backoff.
|
|
89
|
+
*
|
|
90
|
+
* @param complexityHash The unique hash of the task logic to submit.
|
|
91
|
+
* @param metadataUri The URI (e.g. ipfs://...) pointing to the standard JSON metadata.
|
|
92
|
+
* @returns The call data object for use with the Paymaster or standard transaction execution.
|
|
93
|
+
* @throws OverheatedError if max retries are exceeded while the system remains overheated.
|
|
94
|
+
*/
|
|
95
|
+
async enforceThrottleAndGetTaskCall(complexityHash, metadataUri) {
|
|
96
|
+
let attempt = 0;
|
|
97
|
+
let currentBackoff = this.baseBackoffMs;
|
|
98
|
+
while (attempt < this.maxRetries) {
|
|
99
|
+
const overheated = await this.isOverheated();
|
|
100
|
+
if (!overheated) {
|
|
101
|
+
// System is safe, generate the transaction call data
|
|
102
|
+
// Note: the actual submission is usually done via Paymaster/UserOp,
|
|
103
|
+
// so we return the raw call data to be appended.
|
|
104
|
+
// Using generic approach to format call data for viem
|
|
105
|
+
const { encodeFunctionData } = await import('viem');
|
|
106
|
+
const encodedData = encodeFunctionData({
|
|
107
|
+
abi: QUANTUM_TASK_BUFFER_ABI,
|
|
108
|
+
functionName: 'submitTask',
|
|
109
|
+
args: [complexityHash, metadataUri]
|
|
110
|
+
});
|
|
111
|
+
return {
|
|
112
|
+
to: this.contractAddress,
|
|
113
|
+
value: 0n,
|
|
114
|
+
data: encodedData
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
console.warn(`[V_AI Throttling] System is OVERHEATED. Attempt ${attempt + 1}/${this.maxRetries}. Backing off for ${currentBackoff}ms...`);
|
|
118
|
+
await this.sleep(currentBackoff);
|
|
119
|
+
// Exponential backoff with jitter
|
|
120
|
+
attempt++;
|
|
121
|
+
const jitter = Math.random() * 0.2 + 0.9; // 0.9 - 1.1 multiplier
|
|
122
|
+
currentBackoff = Math.min(currentBackoff * 2 * jitter, this.maxBackoffMs);
|
|
123
|
+
}
|
|
124
|
+
throw new OverheatedError("System critically overheated. Task submission aborted after max retries to preserve macro-economic stability.");
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
//# sourceMappingURL=quantum-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"quantum-client.js","sourceRoot":"","sources":["../src/quantum-client.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -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
|
+
}
|
package/src/index.ts
CHANGED