@whitewall-os/sdk 0.1.0

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/src/client.ts ADDED
@@ -0,0 +1,260 @@
1
+ import {
2
+ createPublicClient,
3
+ http,
4
+ type Address,
5
+ type PublicClient,
6
+ type Transport,
7
+ type Chain,
8
+ type WatchEventReturnType,
9
+ zeroAddress,
10
+ } from "viem";
11
+ import { baseSepolia } from "viem/chains";
12
+ import {
13
+ humanVerifiedPolicyAbi,
14
+ identityRegistryAbi,
15
+ validationRegistryAbi,
16
+ whitewallConsumerAbi,
17
+ } from "./abis.js";
18
+ import { addresses, type ChainName, type WhitewallOSAddresses, type PolicyConfig } from "./addresses.js";
19
+ import type { AgentStatus, AccessGrantedEvent, ValidationSummary } from "./types.js";
20
+
21
+ const HUMAN_VERIFIED_TAG = "HUMAN_VERIFIED";
22
+
23
+ const chainMap: Record<ChainName, Chain> = {
24
+ baseSepolia,
25
+ };
26
+
27
+ export interface WhitewallOSConfig {
28
+ chain: ChainName;
29
+ rpcUrl?: string;
30
+ /** Pass your own viem PublicClient to skip internal client creation */
31
+ publicClient?: PublicClient<Transport, Chain>;
32
+ }
33
+
34
+ export class WhitewallOS {
35
+ private client: PublicClient<Transport, Chain>;
36
+ private addrs: WhitewallOSAddresses;
37
+ private policy: PolicyConfig | null = null;
38
+
39
+ private constructor(client: PublicClient<Transport, Chain>, addrs: WhitewallOSAddresses) {
40
+ this.client = client;
41
+ this.addrs = addrs;
42
+ }
43
+
44
+ /**
45
+ * Create and connect a WhitewallOS instance.
46
+ * Reads policy config from on-chain HumanVerifiedPolicy contract.
47
+ */
48
+ static async connect(config: WhitewallOSConfig): Promise<WhitewallOS> {
49
+ const addrs = addresses[config.chain];
50
+ const client =
51
+ config.publicClient ??
52
+ createPublicClient({
53
+ chain: chainMap[config.chain],
54
+ transport: http(config.rpcUrl),
55
+ });
56
+
57
+ const instance = new WhitewallOS(client, addrs);
58
+ await instance.loadPolicyConfig();
59
+ return instance;
60
+ }
61
+
62
+ /** Read policy configuration from the on-chain HumanVerifiedPolicy contract */
63
+ private async loadPolicyConfig(): Promise<void> {
64
+ const [identityRegistry, validationRegistry, worldIdValidator, requiredTier] =
65
+ await Promise.all([
66
+ this.client.readContract({
67
+ address: this.addrs.humanVerifiedPolicy,
68
+ abi: humanVerifiedPolicyAbi,
69
+ functionName: "getIdentityRegistry",
70
+ }),
71
+ this.client.readContract({
72
+ address: this.addrs.humanVerifiedPolicy,
73
+ abi: humanVerifiedPolicyAbi,
74
+ functionName: "getValidationRegistry",
75
+ }),
76
+ this.client.readContract({
77
+ address: this.addrs.humanVerifiedPolicy,
78
+ abi: humanVerifiedPolicyAbi,
79
+ functionName: "getWorldIdValidator",
80
+ }),
81
+ this.client.readContract({
82
+ address: this.addrs.humanVerifiedPolicy,
83
+ abi: humanVerifiedPolicyAbi,
84
+ functionName: "getRequiredTier",
85
+ }),
86
+ ]);
87
+
88
+ this.policy = { identityRegistry, validationRegistry, worldIdValidator, requiredTier };
89
+ }
90
+
91
+ private get policyConfig(): PolicyConfig {
92
+ if (!this.policy) throw new Error("WhitewallOS not connected. Use WhitewallOS.connect()");
93
+ return this.policy;
94
+ }
95
+
96
+ // ─── Core Read Methods ───
97
+
98
+ async isRegistered(agentId: bigint): Promise<boolean> {
99
+ try {
100
+ const owner = await this.client.readContract({
101
+ address: this.policyConfig.identityRegistry,
102
+ abi: identityRegistryAbi,
103
+ functionName: "ownerOf",
104
+ args: [agentId],
105
+ });
106
+ return owner !== zeroAddress;
107
+ } catch {
108
+ return false;
109
+ }
110
+ }
111
+
112
+ async isHumanVerified(agentId: bigint): Promise<boolean> {
113
+ const summary = await this.getValidationSummary(agentId);
114
+ return summary.count > 0n && summary.avgScore >= this.policyConfig.requiredTier;
115
+ }
116
+
117
+ async getOwner(agentId: bigint): Promise<Address> {
118
+ return this.client.readContract({
119
+ address: this.policyConfig.identityRegistry,
120
+ abi: identityRegistryAbi,
121
+ functionName: "ownerOf",
122
+ args: [agentId],
123
+ });
124
+ }
125
+
126
+ async getAgentWallet(agentId: bigint): Promise<Address> {
127
+ return this.client.readContract({
128
+ address: this.policyConfig.identityRegistry,
129
+ abi: identityRegistryAbi,
130
+ functionName: "getAgentWallet",
131
+ args: [agentId],
132
+ });
133
+ }
134
+
135
+ async getTokenURI(agentId: bigint): Promise<string> {
136
+ return this.client.readContract({
137
+ address: this.policyConfig.identityRegistry,
138
+ abi: identityRegistryAbi,
139
+ functionName: "tokenURI",
140
+ args: [agentId],
141
+ });
142
+ }
143
+
144
+ async getMetadata(agentId: bigint, key: string): Promise<`0x${string}`> {
145
+ return this.client.readContract({
146
+ address: this.policyConfig.identityRegistry,
147
+ abi: identityRegistryAbi,
148
+ functionName: "getMetadata",
149
+ args: [agentId, key],
150
+ });
151
+ }
152
+
153
+ // ─── Validation ───
154
+
155
+ async getValidationSummary(agentId: bigint): Promise<ValidationSummary> {
156
+ const [count, avgResponse] = await this.client.readContract({
157
+ address: this.policyConfig.validationRegistry,
158
+ abi: validationRegistryAbi,
159
+ functionName: "getSummary",
160
+ args: [agentId, [this.policyConfig.worldIdValidator], HUMAN_VERIFIED_TAG],
161
+ });
162
+ return { count: BigInt(count), avgScore: avgResponse };
163
+ }
164
+
165
+ async getAgentValidations(agentId: bigint): Promise<readonly `0x${string}`[]> {
166
+ return this.client.readContract({
167
+ address: this.policyConfig.validationRegistry,
168
+ abi: validationRegistryAbi,
169
+ functionName: "getAgentValidations",
170
+ args: [agentId],
171
+ });
172
+ }
173
+
174
+ // ─── Composite: Full Status ───
175
+
176
+ async getAgentStatus(agentId: bigint): Promise<AgentStatus> {
177
+ const registered = await this.isRegistered(agentId);
178
+ if (!registered) {
179
+ return {
180
+ isRegistered: false,
181
+ isHumanVerified: false,
182
+ tier: 0,
183
+ owner: zeroAddress,
184
+ agentWallet: zeroAddress,
185
+ validationCount: 0n,
186
+ };
187
+ }
188
+
189
+ const [owner, agentWallet, summary] = await Promise.all([
190
+ this.getOwner(agentId),
191
+ this.getAgentWallet(agentId),
192
+ this.getValidationSummary(agentId),
193
+ ]);
194
+
195
+ const isHumanVerified = summary.count > 0n && summary.avgScore >= this.policyConfig.requiredTier;
196
+ const tier = isHumanVerified ? this.policyConfig.requiredTier : 1;
197
+
198
+ return {
199
+ isRegistered: true,
200
+ isHumanVerified,
201
+ tier,
202
+ owner,
203
+ agentWallet,
204
+ validationCount: summary.count,
205
+ };
206
+ }
207
+
208
+ // ─── Event Watching ───
209
+
210
+ onAccessGranted(
211
+ callback: (event: AccessGrantedEvent) => void,
212
+ ): WatchEventReturnType {
213
+ return this.client.watchEvent({
214
+ address: this.addrs.whitewallConsumer,
215
+ event: whitewallConsumerAbi[0], // AccessGranted
216
+ onLogs: (logs) => {
217
+ for (const log of logs) {
218
+ callback({
219
+ agentId: (log as any).args.agentId,
220
+ accountableHuman: (log as any).args.accountableHuman,
221
+ tier: Number((log as any).args.tier),
222
+ blockNumber: log.blockNumber,
223
+ transactionHash: log.transactionHash,
224
+ });
225
+ }
226
+ },
227
+ });
228
+ }
229
+
230
+ onRegistered(
231
+ callback: (agentId: bigint, owner: Address) => void,
232
+ ): WatchEventReturnType {
233
+ return this.client.watchEvent({
234
+ address: this.policyConfig.identityRegistry,
235
+ event: identityRegistryAbi[5], // Registered event
236
+ onLogs: (logs) => {
237
+ for (const log of logs) {
238
+ callback(
239
+ (log as any).args.agentId,
240
+ (log as any).args.owner,
241
+ );
242
+ }
243
+ },
244
+ });
245
+ }
246
+
247
+ // ─── Utilities ───
248
+
249
+ getAddresses(): WhitewallOSAddresses {
250
+ return this.addrs;
251
+ }
252
+
253
+ getPolicyConfig(): PolicyConfig {
254
+ return this.policyConfig;
255
+ }
256
+
257
+ getPublicClient(): PublicClient<Transport, Chain> {
258
+ return this.client;
259
+ }
260
+ }
package/src/index.ts ADDED
@@ -0,0 +1,12 @@
1
+ export { WhitewallOS } from "./client.js";
2
+ export type { WhitewallOSConfig } from "./client.js";
3
+ export type { AgentStatus, AccessGrantedEvent, ValidationSummary } from "./types.js";
4
+ export type { ChainName, WhitewallOSAddresses, PolicyConfig } from "./addresses.js";
5
+ export { addresses } from "./addresses.js";
6
+ export {
7
+ humanVerifiedPolicyAbi,
8
+ identityRegistryAbi,
9
+ validationRegistryAbi,
10
+ whitewallConsumerAbi,
11
+ worldIdValidatorAbi,
12
+ } from "./abis.js";
package/src/types.ts ADDED
@@ -0,0 +1,23 @@
1
+ import type { Address } from "viem";
2
+
3
+ export interface AgentStatus {
4
+ isRegistered: boolean;
5
+ isHumanVerified: boolean;
6
+ tier: number;
7
+ owner: Address;
8
+ agentWallet: Address;
9
+ validationCount: bigint;
10
+ }
11
+
12
+ export interface AccessGrantedEvent {
13
+ agentId: bigint;
14
+ accountableHuman: Address;
15
+ tier: number;
16
+ blockNumber: bigint;
17
+ transactionHash: `0x${string}`;
18
+ }
19
+
20
+ export interface ValidationSummary {
21
+ count: bigint;
22
+ avgScore: number;
23
+ }