@vorionsys/basis 1.0.1
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/.env.example +22 -0
- package/AMOY-MIGRATION.md +188 -0
- package/DEPLOY-AMOY.md +368 -0
- package/DEPLOY-NOW.md +216 -0
- package/DEPLOYMENT.md +239 -0
- package/GET-WALLET.md +286 -0
- package/QUICK-WALLET-SETUP.md +268 -0
- package/README.md +195 -0
- package/artifacts/@openzeppelin/contracts/access/AccessControl.sol/AccessControl.dbg.json +4 -0
- package/artifacts/@openzeppelin/contracts/access/AccessControl.sol/AccessControl.json +236 -0
- package/artifacts/@openzeppelin/contracts/access/IAccessControl.sol/IAccessControl.dbg.json +4 -0
- package/artifacts/@openzeppelin/contracts/access/IAccessControl.sol/IAccessControl.json +204 -0
- package/artifacts/@openzeppelin/contracts/interfaces/IERC4906.sol/IERC4906.dbg.json +4 -0
- package/artifacts/@openzeppelin/contracts/interfaces/IERC4906.sol/IERC4906.json +328 -0
- package/artifacts/@openzeppelin/contracts/interfaces/draft-IERC6093.sol/IERC1155Errors.dbg.json +4 -0
- package/artifacts/@openzeppelin/contracts/interfaces/draft-IERC6093.sol/IERC1155Errors.json +113 -0
- package/artifacts/@openzeppelin/contracts/interfaces/draft-IERC6093.sol/IERC20Errors.dbg.json +4 -0
- package/artifacts/@openzeppelin/contracts/interfaces/draft-IERC6093.sol/IERC20Errors.json +97 -0
- package/artifacts/@openzeppelin/contracts/interfaces/draft-IERC6093.sol/IERC721Errors.dbg.json +4 -0
- package/artifacts/@openzeppelin/contracts/interfaces/draft-IERC6093.sol/IERC721Errors.json +114 -0
- package/artifacts/@openzeppelin/contracts/token/ERC721/ERC721.sol/ERC721.dbg.json +4 -0
- package/artifacts/@openzeppelin/contracts/token/ERC721/ERC721.sol/ERC721.json +444 -0
- package/artifacts/@openzeppelin/contracts/token/ERC721/IERC721.sol/IERC721.dbg.json +4 -0
- package/artifacts/@openzeppelin/contracts/token/ERC721/IERC721.sol/IERC721.json +296 -0
- package/artifacts/@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol/IERC721Receiver.dbg.json +4 -0
- package/artifacts/@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol/IERC721Receiver.json +45 -0
- package/artifacts/@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol/ERC721Enumerable.dbg.json +4 -0
- package/artifacts/@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol/ERC721Enumerable.json +521 -0
- package/artifacts/@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol/ERC721URIStorage.dbg.json +4 -0
- package/artifacts/@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol/ERC721URIStorage.json +476 -0
- package/artifacts/@openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable.sol/IERC721Enumerable.dbg.json +4 -0
- package/artifacts/@openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable.sol/IERC721Enumerable.json +352 -0
- package/artifacts/@openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol/IERC721Metadata.dbg.json +4 -0
- package/artifacts/@openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol/IERC721Metadata.json +341 -0
- package/artifacts/@openzeppelin/contracts/token/ERC721/utils/ERC721Utils.sol/ERC721Utils.dbg.json +4 -0
- package/artifacts/@openzeppelin/contracts/token/ERC721/utils/ERC721Utils.sol/ERC721Utils.json +10 -0
- package/artifacts/@openzeppelin/contracts/utils/Context.sol/Context.dbg.json +4 -0
- package/artifacts/@openzeppelin/contracts/utils/Context.sol/Context.json +10 -0
- package/artifacts/@openzeppelin/contracts/utils/Panic.sol/Panic.dbg.json +4 -0
- package/artifacts/@openzeppelin/contracts/utils/Panic.sol/Panic.json +10 -0
- package/artifacts/@openzeppelin/contracts/utils/Strings.sol/Strings.dbg.json +4 -0
- package/artifacts/@openzeppelin/contracts/utils/Strings.sol/Strings.json +37 -0
- package/artifacts/@openzeppelin/contracts/utils/introspection/ERC165.sol/ERC165.dbg.json +4 -0
- package/artifacts/@openzeppelin/contracts/utils/introspection/ERC165.sol/ERC165.json +30 -0
- package/artifacts/@openzeppelin/contracts/utils/introspection/IERC165.sol/IERC165.dbg.json +4 -0
- package/artifacts/@openzeppelin/contracts/utils/introspection/IERC165.sol/IERC165.json +30 -0
- package/artifacts/@openzeppelin/contracts/utils/math/Math.sol/Math.dbg.json +4 -0
- package/artifacts/@openzeppelin/contracts/utils/math/Math.sol/Math.json +10 -0
- package/artifacts/@openzeppelin/contracts/utils/math/SafeCast.sol/SafeCast.dbg.json +4 -0
- package/artifacts/@openzeppelin/contracts/utils/math/SafeCast.sol/SafeCast.json +65 -0
- package/artifacts/@openzeppelin/contracts/utils/math/SignedMath.sol/SignedMath.dbg.json +4 -0
- package/artifacts/@openzeppelin/contracts/utils/math/SignedMath.sol/SignedMath.json +10 -0
- package/artifacts/build-info/357d1bba4062d461f497f221490811a3.json +1 -0
- package/artifacts/contracts/AgentCard.sol/AgentCard.dbg.json +4 -0
- package/artifacts/contracts/AgentCard.sol/AgentCard.json +1430 -0
- package/build_errors.txt +0 -0
- package/build_output.txt +0 -0
- package/cache/solidity-files-cache.json +885 -0
- package/contracts/AgentCard.sol +478 -0
- package/contracts/deploy/01-deploy-agentcard.ts +66 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +12 -0
- package/dist/kya/accountability.d.ts.map +1 -0
- package/dist/kya/accountability.js +100 -0
- package/dist/kya/authorization.d.ts.map +1 -0
- package/dist/kya/authorization.js +258 -0
- package/dist/kya/behavior.d.ts.map +1 -0
- package/dist/kya/behavior.js +142 -0
- package/dist/kya/identity.d.ts.map +1 -0
- package/dist/kya/identity.js +187 -0
- package/dist/kya/index.d.ts.map +1 -0
- package/dist/kya/index.js +99 -0
- package/dist/kya/types.d.ts.map +1 -0
- package/dist/kya/types.js +5 -0
- package/dist/trust-1000-agents.test.d.ts.map +1 -0
- package/dist/trust-1000-agents.test.js +608 -0
- package/dist/trust-capabilities.d.ts.map +1 -0
- package/dist/trust-capabilities.js +478 -0
- package/dist/trust-factors.d.ts.map +1 -0
- package/dist/trust-factors.js +588 -0
- package/dist/trust-factors.test.d.ts.map +1 -0
- package/dist/trust-factors.test.js +179 -0
- package/dist/validation-gate.d.ts.map +1 -0
- package/dist/validation-gate.js +468 -0
- package/dist/validation-gate.test.d.ts.map +1 -0
- package/dist/validation-gate.test.js +419 -0
- package/hardhat.config.ts +55 -0
- package/package.json +57 -0
- package/scripts/certify-agent.ts +91 -0
- package/scripts/deploy-agentcard.ts +63 -0
- package/scripts/mint-agentcard.ts +87 -0
- package/specs/adversarial-sandbox-test-suite.md +1055 -0
- package/specs/kya-framework.md +910 -0
- package/specs/trust-factors-v2.md +437 -0
- package/src/index.ts +14 -0
- package/src/kya/accountability.ts +132 -0
- package/src/kya/authorization.ts +325 -0
- package/src/kya/behavior.ts +169 -0
- package/src/kya/identity.ts +224 -0
- package/src/kya/index.ts +125 -0
- package/src/kya/types.ts +242 -0
- package/src/trust-1000-agents.test.ts +745 -0
- package/src/trust-capabilities.ts +517 -0
- package/src/trust-factors.test.ts +241 -0
- package/src/trust-factors.ts +666 -0
- package/src/validation-gate.test.ts +531 -0
- package/src/validation-gate.ts +665 -0
- package/test-kya-simple.ts +258 -0
- package/test-kya.ts +245 -0
- package/tsconfig.json +14 -0
- package/typechain-types/@openzeppelin/contracts/access/AccessControl.ts +324 -0
- package/typechain-types/@openzeppelin/contracts/access/IAccessControl.ts +292 -0
- package/typechain-types/@openzeppelin/contracts/access/index.ts +5 -0
- package/typechain-types/@openzeppelin/contracts/index.ts +11 -0
- package/typechain-types/@openzeppelin/contracts/interfaces/IERC4906.ts +462 -0
- package/typechain-types/@openzeppelin/contracts/interfaces/draft-IERC6093.sol/IERC1155Errors.ts +69 -0
- package/typechain-types/@openzeppelin/contracts/interfaces/draft-IERC6093.sol/IERC20Errors.ts +69 -0
- package/typechain-types/@openzeppelin/contracts/interfaces/draft-IERC6093.sol/IERC721Errors.ts +69 -0
- package/typechain-types/@openzeppelin/contracts/interfaces/draft-IERC6093.sol/index.ts +6 -0
- package/typechain-types/@openzeppelin/contracts/interfaces/index.ts +6 -0
- package/typechain-types/@openzeppelin/contracts/token/ERC721/ERC721.ts +420 -0
- package/typechain-types/@openzeppelin/contracts/token/ERC721/IERC721.ts +393 -0
- package/typechain-types/@openzeppelin/contracts/token/ERC721/IERC721Receiver.ts +110 -0
- package/typechain-types/@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.ts +470 -0
- package/typechain-types/@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.ts +489 -0
- package/typechain-types/@openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable.ts +443 -0
- package/typechain-types/@openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.ts +420 -0
- package/typechain-types/@openzeppelin/contracts/token/ERC721/extensions/index.ts +7 -0
- package/typechain-types/@openzeppelin/contracts/token/ERC721/index.ts +8 -0
- package/typechain-types/@openzeppelin/contracts/token/index.ts +5 -0
- package/typechain-types/@openzeppelin/contracts/utils/Strings.ts +69 -0
- package/typechain-types/@openzeppelin/contracts/utils/index.ts +8 -0
- package/typechain-types/@openzeppelin/contracts/utils/introspection/ERC165.ts +94 -0
- package/typechain-types/@openzeppelin/contracts/utils/introspection/IERC165.ts +94 -0
- package/typechain-types/@openzeppelin/contracts/utils/introspection/index.ts +5 -0
- package/typechain-types/@openzeppelin/contracts/utils/math/SafeCast.ts +69 -0
- package/typechain-types/@openzeppelin/contracts/utils/math/index.ts +4 -0
- package/typechain-types/@openzeppelin/index.ts +5 -0
- package/typechain-types/common.ts +131 -0
- package/typechain-types/contracts/AgentCard.ts +1415 -0
- package/typechain-types/contracts/index.ts +4 -0
- package/typechain-types/factories/@openzeppelin/contracts/access/AccessControl__factory.ts +250 -0
- package/typechain-types/factories/@openzeppelin/contracts/access/IAccessControl__factory.ts +218 -0
- package/typechain-types/factories/@openzeppelin/contracts/access/index.ts +5 -0
- package/typechain-types/factories/@openzeppelin/contracts/index.ts +7 -0
- package/typechain-types/factories/@openzeppelin/contracts/interfaces/IERC4906__factory.ts +339 -0
- package/typechain-types/factories/@openzeppelin/contracts/interfaces/draft-IERC6093.sol/IERC1155Errors__factory.ts +127 -0
- package/typechain-types/factories/@openzeppelin/contracts/interfaces/draft-IERC6093.sol/IERC20Errors__factory.ts +111 -0
- package/typechain-types/factories/@openzeppelin/contracts/interfaces/draft-IERC6093.sol/IERC721Errors__factory.ts +128 -0
- package/typechain-types/factories/@openzeppelin/contracts/interfaces/draft-IERC6093.sol/index.ts +6 -0
- package/typechain-types/factories/@openzeppelin/contracts/interfaces/index.ts +5 -0
- package/typechain-types/factories/@openzeppelin/contracts/token/ERC721/ERC721__factory.ts +455 -0
- package/typechain-types/factories/@openzeppelin/contracts/token/ERC721/IERC721Receiver__factory.ts +59 -0
- package/typechain-types/factories/@openzeppelin/contracts/token/ERC721/IERC721__factory.ts +307 -0
- package/typechain-types/factories/@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable__factory.ts +535 -0
- package/typechain-types/factories/@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage__factory.ts +490 -0
- package/typechain-types/factories/@openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable__factory.ts +366 -0
- package/typechain-types/factories/@openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata__factory.ts +355 -0
- package/typechain-types/factories/@openzeppelin/contracts/token/ERC721/extensions/index.ts +7 -0
- package/typechain-types/factories/@openzeppelin/contracts/token/ERC721/index.ts +7 -0
- package/typechain-types/factories/@openzeppelin/contracts/token/index.ts +4 -0
- package/typechain-types/factories/@openzeppelin/contracts/utils/Strings__factory.ts +90 -0
- package/typechain-types/factories/@openzeppelin/contracts/utils/index.ts +6 -0
- package/typechain-types/factories/@openzeppelin/contracts/utils/introspection/ERC165__factory.ts +41 -0
- package/typechain-types/factories/@openzeppelin/contracts/utils/introspection/IERC165__factory.ts +41 -0
- package/typechain-types/factories/@openzeppelin/contracts/utils/introspection/index.ts +5 -0
- package/typechain-types/factories/@openzeppelin/contracts/utils/math/SafeCast__factory.ts +118 -0
- package/typechain-types/factories/@openzeppelin/contracts/utils/math/index.ts +4 -0
- package/typechain-types/factories/@openzeppelin/index.ts +4 -0
- package/typechain-types/factories/contracts/AgentCard__factory.ts +1480 -0
- package/typechain-types/factories/contracts/index.ts +4 -0
- package/typechain-types/factories/index.ts +5 -0
- package/typechain-types/index.ts +44 -0
- package/vitest.config.ts +8 -0
|
@@ -0,0 +1,419 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for BASIS Validation Gate
|
|
3
|
+
*/
|
|
4
|
+
import { describe, it, expect } from 'vitest';
|
|
5
|
+
import { validateAgent, isValidAgent, createValidationGate, strictValidationGate, productionValidationGate, GateDecision, ValidationSeverity, scoreToTier, } from './validation-gate';
|
|
6
|
+
import { TrustTier } from './trust-factors';
|
|
7
|
+
describe('ValidationGate', () => {
|
|
8
|
+
// =============================================================================
|
|
9
|
+
// BASIC VALIDATION TESTS
|
|
10
|
+
// =============================================================================
|
|
11
|
+
describe('validateAgent', () => {
|
|
12
|
+
it('should PASS a valid manifest', () => {
|
|
13
|
+
const manifest = {
|
|
14
|
+
agentId: 'a3i.acme-corp.invoice-bot:ABF-L3@1.0.0',
|
|
15
|
+
organization: 'acme-corp',
|
|
16
|
+
agentClass: 'invoice-bot',
|
|
17
|
+
domains: ['A', 'B', 'F'],
|
|
18
|
+
capabilityLevel: 3,
|
|
19
|
+
version: '1.0.0',
|
|
20
|
+
trustScore: 450,
|
|
21
|
+
};
|
|
22
|
+
const result = validateAgent(manifest);
|
|
23
|
+
expect(result.decision).toBe(GateDecision.PASS);
|
|
24
|
+
expect(result.valid).toBe(true);
|
|
25
|
+
expect(result.errors).toHaveLength(0);
|
|
26
|
+
});
|
|
27
|
+
it('should REJECT manifest missing required agentId', () => {
|
|
28
|
+
const manifest = {
|
|
29
|
+
organization: 'acme-corp',
|
|
30
|
+
trustScore: 450,
|
|
31
|
+
};
|
|
32
|
+
const result = validateAgent(manifest);
|
|
33
|
+
expect(result.decision).toBe(GateDecision.REJECT);
|
|
34
|
+
expect(result.valid).toBe(false);
|
|
35
|
+
expect(result.errors.length).toBeGreaterThan(0);
|
|
36
|
+
});
|
|
37
|
+
it('should include timing information', () => {
|
|
38
|
+
const manifest = {
|
|
39
|
+
agentId: 'test-agent',
|
|
40
|
+
trustScore: 500,
|
|
41
|
+
};
|
|
42
|
+
const result = validateAgent(manifest);
|
|
43
|
+
expect(result.validatedAt).toBeInstanceOf(Date);
|
|
44
|
+
expect(result.durationMs).toBeGreaterThanOrEqual(0);
|
|
45
|
+
});
|
|
46
|
+
it('should detect invalid CAR format', () => {
|
|
47
|
+
const manifest = {
|
|
48
|
+
agentId: 'invalid-format:missing-parts@1.0.0',
|
|
49
|
+
trustScore: 500,
|
|
50
|
+
};
|
|
51
|
+
const result = validateAgent(manifest);
|
|
52
|
+
const formatIssue = result.issues.find((i) => i.code === 'INVALID_CAR_FORMAT');
|
|
53
|
+
expect(formatIssue).toBeDefined();
|
|
54
|
+
});
|
|
55
|
+
it('should accept simple ID format with info note', () => {
|
|
56
|
+
const manifest = {
|
|
57
|
+
agentId: 'simple-agent-id',
|
|
58
|
+
trustScore: 500,
|
|
59
|
+
};
|
|
60
|
+
const result = validateAgent(manifest);
|
|
61
|
+
expect(result.valid).toBe(true);
|
|
62
|
+
const infoIssue = result.issues.find((i) => i.code === 'SIMPLE_ID_FORMAT');
|
|
63
|
+
expect(infoIssue).toBeDefined();
|
|
64
|
+
expect(infoIssue?.severity).toBe(ValidationSeverity.INFO);
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
// =============================================================================
|
|
68
|
+
// TRUST TIER VALIDATION
|
|
69
|
+
// =============================================================================
|
|
70
|
+
describe('trust tier validation', () => {
|
|
71
|
+
it('should calculate trust tier from score', () => {
|
|
72
|
+
// T0: 0-199
|
|
73
|
+
expect(scoreToTier(0)).toBe(TrustTier.T0_SANDBOX);
|
|
74
|
+
expect(scoreToTier(199)).toBe(TrustTier.T0_SANDBOX);
|
|
75
|
+
// T1: 200-349
|
|
76
|
+
expect(scoreToTier(200)).toBe(TrustTier.T1_OBSERVED);
|
|
77
|
+
expect(scoreToTier(349)).toBe(TrustTier.T1_OBSERVED);
|
|
78
|
+
// T2: 350-500
|
|
79
|
+
expect(scoreToTier(350)).toBe(TrustTier.T2_PROVISIONAL);
|
|
80
|
+
expect(scoreToTier(500)).toBe(TrustTier.T2_PROVISIONAL);
|
|
81
|
+
// T3: 501-649
|
|
82
|
+
expect(scoreToTier(501)).toBe(TrustTier.T3_MONITORED);
|
|
83
|
+
expect(scoreToTier(649)).toBe(TrustTier.T3_MONITORED);
|
|
84
|
+
// T4: 650-799
|
|
85
|
+
expect(scoreToTier(650)).toBe(TrustTier.T4_STANDARD);
|
|
86
|
+
expect(scoreToTier(799)).toBe(TrustTier.T4_STANDARD);
|
|
87
|
+
// T5: 800-875
|
|
88
|
+
expect(scoreToTier(800)).toBe(TrustTier.T5_TRUSTED);
|
|
89
|
+
expect(scoreToTier(875)).toBe(TrustTier.T5_TRUSTED);
|
|
90
|
+
// T6: 876-950
|
|
91
|
+
expect(scoreToTier(876)).toBe(TrustTier.T6_CERTIFIED);
|
|
92
|
+
expect(scoreToTier(950)).toBe(TrustTier.T6_CERTIFIED);
|
|
93
|
+
// T7: 951-1000
|
|
94
|
+
expect(scoreToTier(951)).toBe(TrustTier.T7_AUTONOMOUS);
|
|
95
|
+
expect(scoreToTier(1000)).toBe(TrustTier.T7_AUTONOMOUS);
|
|
96
|
+
});
|
|
97
|
+
it('should REJECT when trust tier is below minimum', () => {
|
|
98
|
+
const manifest = {
|
|
99
|
+
agentId: 'test-agent',
|
|
100
|
+
trustScore: 100, // T0
|
|
101
|
+
};
|
|
102
|
+
const result = validateAgent(manifest, undefined, {
|
|
103
|
+
minimumTrustTier: TrustTier.T3_MONITORED,
|
|
104
|
+
});
|
|
105
|
+
expect(result.decision).toBe(GateDecision.REJECT);
|
|
106
|
+
expect(result.errors.some((e) => e.code === 'INSUFFICIENT_TRUST_TIER')).toBe(true);
|
|
107
|
+
});
|
|
108
|
+
it('should PASS when trust tier meets minimum', () => {
|
|
109
|
+
const manifest = {
|
|
110
|
+
agentId: 'test-agent',
|
|
111
|
+
trustScore: 700, // T4 (650-799)
|
|
112
|
+
};
|
|
113
|
+
const result = validateAgent(manifest, undefined, {
|
|
114
|
+
minimumTrustTier: TrustTier.T3_MONITORED,
|
|
115
|
+
});
|
|
116
|
+
expect(result.decision).toBe(GateDecision.PASS);
|
|
117
|
+
expect(result.trustTier).toBe(TrustTier.T4_STANDARD);
|
|
118
|
+
});
|
|
119
|
+
it('should warn when trust score is missing', () => {
|
|
120
|
+
const manifest = {
|
|
121
|
+
agentId: 'test-agent',
|
|
122
|
+
};
|
|
123
|
+
const result = validateAgent(manifest);
|
|
124
|
+
expect(result.warnings.some((w) => w.code === 'MISSING_TRUST_SCORE')).toBe(true);
|
|
125
|
+
});
|
|
126
|
+
});
|
|
127
|
+
// =============================================================================
|
|
128
|
+
// PROFILE VALIDATION
|
|
129
|
+
// =============================================================================
|
|
130
|
+
describe('profile validation', () => {
|
|
131
|
+
const validProfile = {
|
|
132
|
+
agentId: 'a3i.acme-corp.invoice-bot:ABF-L3@1.0.0',
|
|
133
|
+
organization: 'acme-corp',
|
|
134
|
+
agentClass: 'invoice-bot',
|
|
135
|
+
approvedDomains: ['A', 'B', 'F'],
|
|
136
|
+
maxCapabilityLevel: 4,
|
|
137
|
+
approvedCapabilities: ['CAP-READ-PUBLIC', 'CAP-DB-READ', 'CAP-WRITE-APPROVED'],
|
|
138
|
+
trustScore: 500,
|
|
139
|
+
registeredAt: new Date('2024-01-01'),
|
|
140
|
+
};
|
|
141
|
+
it('should PASS when manifest matches profile', () => {
|
|
142
|
+
const manifest = {
|
|
143
|
+
agentId: 'a3i.acme-corp.invoice-bot:ABF-L3@1.0.0',
|
|
144
|
+
organization: 'acme-corp',
|
|
145
|
+
agentClass: 'invoice-bot',
|
|
146
|
+
domains: ['A', 'B'],
|
|
147
|
+
capabilityLevel: 3,
|
|
148
|
+
trustScore: 500,
|
|
149
|
+
};
|
|
150
|
+
const result = validateAgent(manifest, validProfile);
|
|
151
|
+
expect(result.decision).toBe(GateDecision.PASS);
|
|
152
|
+
expect(result.valid).toBe(true);
|
|
153
|
+
});
|
|
154
|
+
it('should REJECT when organization mismatches', () => {
|
|
155
|
+
const manifest = {
|
|
156
|
+
agentId: 'test-agent',
|
|
157
|
+
organization: 'evil-corp',
|
|
158
|
+
trustScore: 500,
|
|
159
|
+
};
|
|
160
|
+
const result = validateAgent(manifest, validProfile);
|
|
161
|
+
expect(result.decision).toBe(GateDecision.REJECT);
|
|
162
|
+
expect(result.errors.some((e) => e.code === 'ORG_MISMATCH')).toBe(true);
|
|
163
|
+
});
|
|
164
|
+
it('should REJECT when capability level exceeds maximum', () => {
|
|
165
|
+
const manifest = {
|
|
166
|
+
agentId: 'test-agent',
|
|
167
|
+
organization: 'acme-corp',
|
|
168
|
+
capabilityLevel: 7, // exceeds profile max of 4
|
|
169
|
+
trustScore: 500,
|
|
170
|
+
};
|
|
171
|
+
const result = validateAgent(manifest, validProfile);
|
|
172
|
+
expect(result.decision).toBe(GateDecision.REJECT);
|
|
173
|
+
expect(result.errors.some((e) => e.code === 'CAPABILITY_LEVEL_EXCEEDED')).toBe(true);
|
|
174
|
+
});
|
|
175
|
+
it('should REJECT unauthorized domains', () => {
|
|
176
|
+
const manifest = {
|
|
177
|
+
agentId: 'test-agent',
|
|
178
|
+
organization: 'acme-corp',
|
|
179
|
+
domains: ['A', 'B', 'S'], // S not approved
|
|
180
|
+
trustScore: 500,
|
|
181
|
+
};
|
|
182
|
+
const result = validateAgent(manifest, validProfile);
|
|
183
|
+
expect(result.decision).toBe(GateDecision.REJECT);
|
|
184
|
+
expect(result.errors.some((e) => e.code === 'UNAUTHORIZED_DOMAINS')).toBe(true);
|
|
185
|
+
});
|
|
186
|
+
it('should warn on unauthorized capabilities', () => {
|
|
187
|
+
const manifest = {
|
|
188
|
+
agentId: 'test-agent',
|
|
189
|
+
organization: 'acme-corp',
|
|
190
|
+
requestedCapabilities: ['CAP-READ-PUBLIC', 'CAP-SYSTEM-ADMIN-FULL'], // admin not approved
|
|
191
|
+
trustScore: 500,
|
|
192
|
+
};
|
|
193
|
+
const result = validateAgent(manifest, validProfile);
|
|
194
|
+
expect(result.warnings.some((w) => w.code === 'UNAUTHORIZED_CAPABILITIES')).toBe(true);
|
|
195
|
+
});
|
|
196
|
+
it('should REJECT when profile required but missing', () => {
|
|
197
|
+
const manifest = {
|
|
198
|
+
agentId: 'test-agent',
|
|
199
|
+
trustScore: 500,
|
|
200
|
+
};
|
|
201
|
+
const result = validateAgent(manifest, undefined, {
|
|
202
|
+
requireRegisteredProfile: true,
|
|
203
|
+
});
|
|
204
|
+
expect(result.decision).toBe(GateDecision.REJECT);
|
|
205
|
+
expect(result.errors.some((e) => e.code === 'PROFILE_NOT_FOUND')).toBe(true);
|
|
206
|
+
});
|
|
207
|
+
});
|
|
208
|
+
// =============================================================================
|
|
209
|
+
// CAPABILITY VALIDATION
|
|
210
|
+
// =============================================================================
|
|
211
|
+
describe('capability validation', () => {
|
|
212
|
+
it('should allow capabilities matching trust tier', () => {
|
|
213
|
+
const manifest = {
|
|
214
|
+
agentId: 'test-agent',
|
|
215
|
+
trustScore: 700, // T4_STANDARD (650-799)
|
|
216
|
+
requestedCapabilities: ['CAP-READ-PUBLIC', 'CAP-AGENT-COMMUNICATE'],
|
|
217
|
+
};
|
|
218
|
+
const result = validateAgent(manifest);
|
|
219
|
+
expect(result.allowedCapabilities).toContain('CAP-READ-PUBLIC');
|
|
220
|
+
expect(result.allowedCapabilities).toContain('CAP-AGENT-COMMUNICATE');
|
|
221
|
+
expect(result.deniedCapabilities).toBeUndefined();
|
|
222
|
+
});
|
|
223
|
+
it('should deny capabilities above trust tier', () => {
|
|
224
|
+
const manifest = {
|
|
225
|
+
agentId: 'test-agent',
|
|
226
|
+
trustScore: 100, // T0_SANDBOX
|
|
227
|
+
requestedCapabilities: ['CAP-READ-PUBLIC', 'CAP-AGENT-SPAWN'], // spawn requires T6
|
|
228
|
+
};
|
|
229
|
+
const result = validateAgent(manifest);
|
|
230
|
+
expect(result.allowedCapabilities).toContain('CAP-READ-PUBLIC');
|
|
231
|
+
expect(result.deniedCapabilities).toContain('CAP-AGENT-SPAWN');
|
|
232
|
+
});
|
|
233
|
+
it('should provide recommendations for denied capabilities', () => {
|
|
234
|
+
const manifest = {
|
|
235
|
+
agentId: 'test-agent',
|
|
236
|
+
trustScore: 100,
|
|
237
|
+
requestedCapabilities: ['CAP-AGENT-SPAWN'],
|
|
238
|
+
};
|
|
239
|
+
const result = validateAgent(manifest);
|
|
240
|
+
expect(result.recommendations).toBeDefined();
|
|
241
|
+
expect(result.recommendations?.some((r) => r.includes('trust score'))).toBe(true);
|
|
242
|
+
});
|
|
243
|
+
});
|
|
244
|
+
// =============================================================================
|
|
245
|
+
// REQUIRED DOMAINS
|
|
246
|
+
// =============================================================================
|
|
247
|
+
describe('required domains', () => {
|
|
248
|
+
it('should REJECT when required domains are missing', () => {
|
|
249
|
+
const manifest = {
|
|
250
|
+
agentId: 'test-agent',
|
|
251
|
+
domains: ['A', 'B'],
|
|
252
|
+
trustScore: 500,
|
|
253
|
+
};
|
|
254
|
+
const result = validateAgent(manifest, undefined, {
|
|
255
|
+
requiredDomains: ['A', 'F'], // F is missing
|
|
256
|
+
});
|
|
257
|
+
expect(result.decision).toBe(GateDecision.REJECT);
|
|
258
|
+
expect(result.errors.some((e) => e.code === 'MISSING_REQUIRED_DOMAINS')).toBe(true);
|
|
259
|
+
});
|
|
260
|
+
it('should PASS when all required domains present', () => {
|
|
261
|
+
const manifest = {
|
|
262
|
+
agentId: 'test-agent',
|
|
263
|
+
domains: ['A', 'B', 'F'],
|
|
264
|
+
trustScore: 500,
|
|
265
|
+
};
|
|
266
|
+
const result = validateAgent(manifest, undefined, {
|
|
267
|
+
requiredDomains: ['A', 'F'],
|
|
268
|
+
});
|
|
269
|
+
expect(result.decision).toBe(GateDecision.PASS);
|
|
270
|
+
});
|
|
271
|
+
});
|
|
272
|
+
// =============================================================================
|
|
273
|
+
// STRICT MODE
|
|
274
|
+
// =============================================================================
|
|
275
|
+
describe('strict mode', () => {
|
|
276
|
+
it('should REJECT on warnings in strict mode', () => {
|
|
277
|
+
const manifest = {
|
|
278
|
+
agentId: 'test-agent',
|
|
279
|
+
// No trust score - generates warning
|
|
280
|
+
};
|
|
281
|
+
const normalResult = validateAgent(manifest, undefined, { strict: false });
|
|
282
|
+
const strictResult = validateAgent(manifest, undefined, { strict: true });
|
|
283
|
+
expect(normalResult.decision).toBe(GateDecision.PASS);
|
|
284
|
+
expect(strictResult.decision).toBe(GateDecision.REJECT);
|
|
285
|
+
});
|
|
286
|
+
});
|
|
287
|
+
// =============================================================================
|
|
288
|
+
// CUSTOM VALIDATORS
|
|
289
|
+
// =============================================================================
|
|
290
|
+
describe('custom validators', () => {
|
|
291
|
+
it('should run custom validators', () => {
|
|
292
|
+
const manifest = {
|
|
293
|
+
agentId: 'test-agent',
|
|
294
|
+
trustScore: 500,
|
|
295
|
+
metadata: { version: '0.0.1' },
|
|
296
|
+
};
|
|
297
|
+
const customValidator = (m) => {
|
|
298
|
+
const issues = [];
|
|
299
|
+
if (m.metadata?.version === '0.0.1') {
|
|
300
|
+
issues.push({
|
|
301
|
+
code: 'UNSTABLE_VERSION',
|
|
302
|
+
message: 'Agent is using unstable version',
|
|
303
|
+
severity: ValidationSeverity.WARNING,
|
|
304
|
+
});
|
|
305
|
+
}
|
|
306
|
+
return issues;
|
|
307
|
+
};
|
|
308
|
+
const result = validateAgent(manifest, undefined, {
|
|
309
|
+
customValidators: [customValidator],
|
|
310
|
+
});
|
|
311
|
+
expect(result.warnings.some((w) => w.code === 'UNSTABLE_VERSION')).toBe(true);
|
|
312
|
+
});
|
|
313
|
+
it('should handle custom validator errors gracefully', () => {
|
|
314
|
+
const manifest = {
|
|
315
|
+
agentId: 'test-agent',
|
|
316
|
+
trustScore: 500,
|
|
317
|
+
};
|
|
318
|
+
const failingValidator = () => {
|
|
319
|
+
throw new Error('Validator crashed');
|
|
320
|
+
};
|
|
321
|
+
const result = validateAgent(manifest, undefined, {
|
|
322
|
+
customValidators: [failingValidator],
|
|
323
|
+
});
|
|
324
|
+
// Should not crash, just add a warning
|
|
325
|
+
expect(result.warnings.some((w) => w.code === 'CUSTOM_VALIDATOR_ERROR')).toBe(true);
|
|
326
|
+
});
|
|
327
|
+
});
|
|
328
|
+
// =============================================================================
|
|
329
|
+
// HELPER FUNCTIONS
|
|
330
|
+
// =============================================================================
|
|
331
|
+
describe('isValidAgent', () => {
|
|
332
|
+
it('should return true for valid agent', () => {
|
|
333
|
+
const manifest = {
|
|
334
|
+
agentId: 'test-agent',
|
|
335
|
+
trustScore: 500,
|
|
336
|
+
};
|
|
337
|
+
expect(isValidAgent(manifest)).toBe(true);
|
|
338
|
+
});
|
|
339
|
+
it('should return false for invalid agent', () => {
|
|
340
|
+
const manifest = {};
|
|
341
|
+
expect(isValidAgent(manifest)).toBe(false);
|
|
342
|
+
});
|
|
343
|
+
});
|
|
344
|
+
describe('createValidationGate', () => {
|
|
345
|
+
it('should create gate with preset options', () => {
|
|
346
|
+
const gate = createValidationGate({
|
|
347
|
+
minimumTrustTier: TrustTier.T3_MONITORED,
|
|
348
|
+
});
|
|
349
|
+
const lowTrustManifest = {
|
|
350
|
+
agentId: 'test-agent',
|
|
351
|
+
trustScore: 100,
|
|
352
|
+
};
|
|
353
|
+
const result = gate.validate(lowTrustManifest);
|
|
354
|
+
expect(result.decision).toBe(GateDecision.REJECT);
|
|
355
|
+
});
|
|
356
|
+
it('should allow option overrides', () => {
|
|
357
|
+
const gate = createValidationGate({
|
|
358
|
+
minimumTrustTier: TrustTier.T5_TRUSTED,
|
|
359
|
+
});
|
|
360
|
+
const manifest = {
|
|
361
|
+
agentId: 'test-agent',
|
|
362
|
+
trustScore: 700, // T4 (650-799)
|
|
363
|
+
};
|
|
364
|
+
// With default options, should fail (T4 < T5)
|
|
365
|
+
const result1 = gate.validate(manifest);
|
|
366
|
+
expect(result1.decision).toBe(GateDecision.REJECT);
|
|
367
|
+
// With override, should pass (T4 >= T3)
|
|
368
|
+
const result2 = gate.validate(manifest, undefined, {
|
|
369
|
+
minimumTrustTier: TrustTier.T3_MONITORED,
|
|
370
|
+
});
|
|
371
|
+
expect(result2.decision).toBe(GateDecision.PASS);
|
|
372
|
+
});
|
|
373
|
+
});
|
|
374
|
+
describe('preset gates', () => {
|
|
375
|
+
it('strictValidationGate should reject on warnings', () => {
|
|
376
|
+
const manifest = {
|
|
377
|
+
agentId: 'test-agent',
|
|
378
|
+
// Missing trustScore generates warning
|
|
379
|
+
};
|
|
380
|
+
expect(strictValidationGate.isValid(manifest)).toBe(false);
|
|
381
|
+
});
|
|
382
|
+
it('productionValidationGate should require profile', () => {
|
|
383
|
+
const manifest = {
|
|
384
|
+
agentId: 'test-agent',
|
|
385
|
+
trustScore: 500,
|
|
386
|
+
};
|
|
387
|
+
const result = productionValidationGate.validate(manifest);
|
|
388
|
+
expect(result.errors.some((e) => e.code === 'PROFILE_NOT_FOUND')).toBe(true);
|
|
389
|
+
});
|
|
390
|
+
});
|
|
391
|
+
// =============================================================================
|
|
392
|
+
// ESCALATION
|
|
393
|
+
// =============================================================================
|
|
394
|
+
describe('escalation', () => {
|
|
395
|
+
it('should ESCALATE when capability escalation allowed and denied caps exist', () => {
|
|
396
|
+
const manifest = {
|
|
397
|
+
agentId: 'test-agent',
|
|
398
|
+
trustScore: 100, // T0
|
|
399
|
+
requestedCapabilities: ['CAP-AGENT-SPAWN'], // Requires T6
|
|
400
|
+
};
|
|
401
|
+
const result = validateAgent(manifest, undefined, {
|
|
402
|
+
allowCapabilityEscalation: true,
|
|
403
|
+
});
|
|
404
|
+
expect(result.decision).toBe(GateDecision.ESCALATE);
|
|
405
|
+
});
|
|
406
|
+
it('should REJECT when capability escalation not allowed', () => {
|
|
407
|
+
const manifest = {
|
|
408
|
+
agentId: 'test-agent',
|
|
409
|
+
trustScore: 100,
|
|
410
|
+
requestedCapabilities: ['CAP-AGENT-SPAWN'],
|
|
411
|
+
};
|
|
412
|
+
const result = validateAgent(manifest, undefined, {
|
|
413
|
+
allowCapabilityEscalation: false,
|
|
414
|
+
});
|
|
415
|
+
expect(result.decision).toBe(GateDecision.REJECT);
|
|
416
|
+
});
|
|
417
|
+
});
|
|
418
|
+
});
|
|
419
|
+
//# sourceMappingURL=validation-gate.test.js.map
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { HardhatUserConfig } from 'hardhat/config';
|
|
2
|
+
import '@nomicfoundation/hardhat-ethers';
|
|
3
|
+
import * as dotenv from 'dotenv';
|
|
4
|
+
|
|
5
|
+
dotenv.config();
|
|
6
|
+
|
|
7
|
+
const config: HardhatUserConfig = {
|
|
8
|
+
solidity: {
|
|
9
|
+
version: '0.8.20',
|
|
10
|
+
settings: {
|
|
11
|
+
optimizer: {
|
|
12
|
+
enabled: true,
|
|
13
|
+
runs: 200,
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
|
|
18
|
+
networks: {
|
|
19
|
+
hardhat: {
|
|
20
|
+
chainId: 31337,
|
|
21
|
+
},
|
|
22
|
+
|
|
23
|
+
// Ethereum Sepolia Testnet (uses ETH)
|
|
24
|
+
sepolia: {
|
|
25
|
+
url: process.env.SEPOLIA_RPC_URL || 'https://ethereum-sepolia-rpc.publicnode.com',
|
|
26
|
+
accounts: process.env.PRIVATE_KEY && process.env.PRIVATE_KEY.startsWith('0x') && process.env.PRIVATE_KEY.length === 66 ? [process.env.PRIVATE_KEY] : [],
|
|
27
|
+
chainId: 11155111,
|
|
28
|
+
},
|
|
29
|
+
|
|
30
|
+
// Polygon Amoy Testnet
|
|
31
|
+
amoy: {
|
|
32
|
+
url: process.env.AMOY_RPC_URL || 'https://rpc-amoy.polygon.technology',
|
|
33
|
+
accounts: process.env.PRIVATE_KEY && process.env.PRIVATE_KEY.startsWith('0x') && process.env.PRIVATE_KEY.length === 66 ? [process.env.PRIVATE_KEY] : [],
|
|
34
|
+
chainId: 80002,
|
|
35
|
+
gasPrice: 30000000000, // 30 gwei
|
|
36
|
+
},
|
|
37
|
+
|
|
38
|
+
// Polygon Mainnet (uses POL token)
|
|
39
|
+
polygon: {
|
|
40
|
+
url: process.env.POLYGON_RPC_URL || 'https://polygon-rpc.com',
|
|
41
|
+
accounts: process.env.PRIVATE_KEY && process.env.PRIVATE_KEY.startsWith('0x') && process.env.PRIVATE_KEY.length === 66 ? [process.env.PRIVATE_KEY] : [],
|
|
42
|
+
chainId: 137,
|
|
43
|
+
gasPrice: 50000000000, // 50 gwei
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
|
|
47
|
+
paths: {
|
|
48
|
+
sources: './contracts',
|
|
49
|
+
tests: './test',
|
|
50
|
+
cache: './cache',
|
|
51
|
+
artifacts: './artifacts',
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
export default config;
|
package/package.json
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@vorionsys/basis",
|
|
3
|
+
"version": "1.0.1",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "Blockchain Agent Standard for Identity and Security (BASIS) - Open standard for AI agent governance",
|
|
6
|
+
"license": "Apache-2.0",
|
|
7
|
+
"publishConfig": {
|
|
8
|
+
"access": "public"
|
|
9
|
+
},
|
|
10
|
+
"main": "dist/index.js",
|
|
11
|
+
"types": "dist/index.d.ts",
|
|
12
|
+
"exports": {
|
|
13
|
+
".": {
|
|
14
|
+
"types": "./dist/index.d.ts",
|
|
15
|
+
"import": "./dist/index.js"
|
|
16
|
+
},
|
|
17
|
+
"./kya": {
|
|
18
|
+
"types": "./dist/kya/index.d.ts",
|
|
19
|
+
"import": "./dist/kya/index.js"
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
"scripts": {
|
|
23
|
+
"build": "tsc",
|
|
24
|
+
"test:trust": "vitest run src/trust-1000-agents.test.ts",
|
|
25
|
+
"test:trust:watch": "vitest src/trust-1000-agents.test.ts"
|
|
26
|
+
},
|
|
27
|
+
"dependencies": {
|
|
28
|
+
"@noble/ed25519": "^2.0.0",
|
|
29
|
+
"did-resolver": "^4.1.0",
|
|
30
|
+
"zod": "^3.22.4"
|
|
31
|
+
},
|
|
32
|
+
"devDependencies": {
|
|
33
|
+
"@types/node": "^20.10.6",
|
|
34
|
+
"typescript": "^5.3.3",
|
|
35
|
+
"vitest": "4.0.18"
|
|
36
|
+
},
|
|
37
|
+
"keywords": [
|
|
38
|
+
"vorion",
|
|
39
|
+
"basis",
|
|
40
|
+
"trust",
|
|
41
|
+
"ai",
|
|
42
|
+
"agent",
|
|
43
|
+
"governance",
|
|
44
|
+
"blockchain",
|
|
45
|
+
"identity"
|
|
46
|
+
],
|
|
47
|
+
"author": "Vorion <team@vorion.org>",
|
|
48
|
+
"repository": {
|
|
49
|
+
"type": "git",
|
|
50
|
+
"url": "https://github.com/voriongit/vorion.git",
|
|
51
|
+
"directory": "packages/basis"
|
|
52
|
+
},
|
|
53
|
+
"homepage": "https://vorion.org",
|
|
54
|
+
"engines": {
|
|
55
|
+
"node": ">=18.0.0"
|
|
56
|
+
}
|
|
57
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { ethers } from 'hardhat';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Certify CC Agent with AgentAnchor (T2: Standard tier, 350 trust score)
|
|
5
|
+
*/
|
|
6
|
+
async function main() {
|
|
7
|
+
const [deployer] = await ethers.getSigners();
|
|
8
|
+
|
|
9
|
+
console.log('Certifying agent with account:', deployer.address);
|
|
10
|
+
|
|
11
|
+
// Get deployed AgentCard contract
|
|
12
|
+
const AgentCard = await ethers.getContractFactory('AgentCard');
|
|
13
|
+
const agentCard = await AgentCard.attach(
|
|
14
|
+
process.env.AGENTCARD_ADDRESS || 'REPLACE_WITH_DEPLOYED_ADDRESS'
|
|
15
|
+
);
|
|
16
|
+
|
|
17
|
+
console.log('AgentCard contract:', await agentCard.getAddress());
|
|
18
|
+
|
|
19
|
+
const tokenId = 0; // First minted card (CC Agent)
|
|
20
|
+
|
|
21
|
+
// Check if account has CERTIFIER_ROLE
|
|
22
|
+
const CERTIFIER_ROLE = await agentCard.CERTIFIER_ROLE();
|
|
23
|
+
const hasCertifierRole = await agentCard.hasRole(CERTIFIER_ROLE, deployer.address);
|
|
24
|
+
|
|
25
|
+
if (!hasCertifierRole) {
|
|
26
|
+
console.error('ā Account does not have CERTIFIER_ROLE');
|
|
27
|
+
console.log('Granting CERTIFIER_ROLE to:', deployer.address);
|
|
28
|
+
|
|
29
|
+
const grantTx = await agentCard.grantRole(CERTIFIER_ROLE, deployer.address);
|
|
30
|
+
await grantTx.wait();
|
|
31
|
+
|
|
32
|
+
console.log('ā
CERTIFIER_ROLE granted');
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Certify with trust score 350 (T2: Standard)
|
|
36
|
+
const trustScore = 350;
|
|
37
|
+
const expiryTimestamp = Math.floor(Date.now() / 1000) + (365 * 24 * 60 * 60); // 1 year from now
|
|
38
|
+
|
|
39
|
+
console.log('\nCertifying agent:');
|
|
40
|
+
console.log('- Token ID:', tokenId);
|
|
41
|
+
console.log('- Trust Score:', trustScore);
|
|
42
|
+
console.log('- Tier: T2 (Standard)');
|
|
43
|
+
console.log('- Expires:', new Date(expiryTimestamp * 1000).toISOString());
|
|
44
|
+
|
|
45
|
+
const tx = await agentCard.certify(tokenId, trustScore, expiryTimestamp);
|
|
46
|
+
|
|
47
|
+
console.log('Certification transaction submitted:', tx.hash);
|
|
48
|
+
const receipt = await tx.wait();
|
|
49
|
+
|
|
50
|
+
// Get certification event
|
|
51
|
+
const certifyEvent = receipt?.logs?.find(
|
|
52
|
+
(log: any) => log.fragment?.name === 'AgentCertified'
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
if (certifyEvent) {
|
|
56
|
+
console.log('\nā
Agent certified successfully!');
|
|
57
|
+
console.log('Token ID:', certifyEvent.args?.tokenId.toString());
|
|
58
|
+
console.log('DID:', certifyEvent.args?.did);
|
|
59
|
+
console.log('Certifier:', certifyEvent.args?.certifier);
|
|
60
|
+
console.log('Trust Score:', certifyEvent.args?.trustScore.toString());
|
|
61
|
+
console.log('Tier:', certifyEvent.args?.tier); // Should be 2 (T2)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Query updated card
|
|
65
|
+
const card = await agentCard.getCard(tokenId);
|
|
66
|
+
|
|
67
|
+
console.log('\nš Updated AgentCard:');
|
|
68
|
+
console.log('-------------------');
|
|
69
|
+
console.log('DID:', card.did);
|
|
70
|
+
console.log('Name:', card.name);
|
|
71
|
+
console.log('Trust Score:', card.trustScore.toString());
|
|
72
|
+
console.log('Tier:', ['T0', 'T1', 'T2', 'T3', 'T4', 'T5'][card.tier]);
|
|
73
|
+
console.log('Certified:', card.certified);
|
|
74
|
+
console.log('Certifier:', card.certifier);
|
|
75
|
+
console.log('Certification Date:', new Date(Number(card.certificationDate) * 1000).toISOString());
|
|
76
|
+
console.log('Certification Expiry:', new Date(Number(card.certificationExpiry) * 1000).toISOString());
|
|
77
|
+
|
|
78
|
+
// Check if certified and valid
|
|
79
|
+
const isCertified = await agentCard.isCertified(tokenId);
|
|
80
|
+
console.log('\nIs Certified (not expired/revoked):', isCertified);
|
|
81
|
+
|
|
82
|
+
console.log('\nš View on PolygonScan:');
|
|
83
|
+
console.log(`https://mumbai.polygonscan.com/token/${await agentCard.getAddress()}?a=${tokenId}`);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
main()
|
|
87
|
+
.then(() => process.exit(0))
|
|
88
|
+
.catch((error) => {
|
|
89
|
+
console.error(error);
|
|
90
|
+
process.exit(1);
|
|
91
|
+
});
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { ethers } from 'hardhat';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Deploy AgentCard contract to network
|
|
5
|
+
*/
|
|
6
|
+
async function main() {
|
|
7
|
+
const [deployer] = await ethers.getSigners();
|
|
8
|
+
|
|
9
|
+
console.log('Deploying AgentCard with account:', deployer.address);
|
|
10
|
+
console.log('Account balance:', ethers.formatEther(await ethers.provider.getBalance(deployer.address)), 'MATIC');
|
|
11
|
+
|
|
12
|
+
// Deploy AgentCard
|
|
13
|
+
const AgentCard = await ethers.getContractFactory('AgentCard');
|
|
14
|
+
const agentCard = await AgentCard.deploy();
|
|
15
|
+
|
|
16
|
+
await agentCard.waitForDeployment();
|
|
17
|
+
|
|
18
|
+
const contractAddress = await agentCard.getAddress();
|
|
19
|
+
|
|
20
|
+
console.log('\nā
AgentCard deployed to:', contractAddress);
|
|
21
|
+
|
|
22
|
+
// Grant CERTIFIER_ROLE to deployer (for testing)
|
|
23
|
+
console.log('\nGranting CERTIFIER_ROLE to deployer...');
|
|
24
|
+
const CERTIFIER_ROLE = await agentCard.CERTIFIER_ROLE();
|
|
25
|
+
await agentCard.grantRole(CERTIFIER_ROLE, deployer.address);
|
|
26
|
+
|
|
27
|
+
console.log('ā
CERTIFIER_ROLE granted');
|
|
28
|
+
|
|
29
|
+
console.log('\nš Deployment Summary:');
|
|
30
|
+
console.log('=====================');
|
|
31
|
+
console.log('Contract Address:', contractAddress);
|
|
32
|
+
console.log('Deployer:', deployer.address);
|
|
33
|
+
console.log('Network:', (await ethers.provider.getNetwork()).name);
|
|
34
|
+
console.log('Chain ID:', (await ethers.provider.getNetwork()).chainId);
|
|
35
|
+
|
|
36
|
+
console.log('\nš View on Block Explorer:');
|
|
37
|
+
const chainId = (await ethers.provider.getNetwork()).chainId;
|
|
38
|
+
if (chainId === 11155111n) {
|
|
39
|
+
console.log(`https://sepolia.etherscan.io/address/${contractAddress}`);
|
|
40
|
+
} else if (chainId === 80002n) {
|
|
41
|
+
console.log(`https://amoy.polygonscan.com/address/${contractAddress}`);
|
|
42
|
+
} else if (chainId === 80001n) {
|
|
43
|
+
console.log(`https://mumbai.polygonscan.com/address/${contractAddress}`);
|
|
44
|
+
console.log('ā ļø WARNING: Mumbai testnet is deprecated. Use Amoy instead!');
|
|
45
|
+
} else if (chainId === 137n) {
|
|
46
|
+
console.log(`https://polygonscan.com/address/${contractAddress}`);
|
|
47
|
+
} else if (chainId === 1n) {
|
|
48
|
+
console.log(`https://etherscan.io/address/${contractAddress}`);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
console.log('\nš Next Steps:');
|
|
52
|
+
console.log('1. Save contract address:', contractAddress);
|
|
53
|
+
console.log('2. Verify contract: npx hardhat verify --network mumbai', contractAddress);
|
|
54
|
+
console.log('3. Mint AgentCard: npx hardhat run scripts/mint-agentcard.ts --network mumbai');
|
|
55
|
+
console.log('4. Certify agent: npx hardhat run scripts/certify-agent.ts --network mumbai');
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
main()
|
|
59
|
+
.then(() => process.exit(0))
|
|
60
|
+
.catch((error) => {
|
|
61
|
+
console.error(error);
|
|
62
|
+
process.exit(1);
|
|
63
|
+
});
|