@cofhe/sdk 0.1.0 → 0.2.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/CHANGELOG.md +62 -0
- package/adapters/ethers5.test.ts +174 -0
- package/adapters/ethers5.ts +36 -0
- package/adapters/ethers6.test.ts +169 -0
- package/adapters/ethers6.ts +36 -0
- package/adapters/hardhat-node.ts +167 -0
- package/adapters/hardhat.hh2.test.ts +159 -0
- package/adapters/hardhat.ts +36 -0
- package/adapters/index.test.ts +20 -0
- package/adapters/index.ts +5 -0
- package/adapters/smartWallet.ts +99 -0
- package/adapters/test-utils.ts +53 -0
- package/adapters/types.ts +6 -0
- package/adapters/wagmi.test.ts +156 -0
- package/adapters/wagmi.ts +17 -0
- package/chains/chains/arbSepolia.ts +14 -0
- package/chains/chains/baseSepolia.ts +14 -0
- package/chains/chains/hardhat.ts +15 -0
- package/chains/chains/localcofhe.ts +14 -0
- package/chains/chains/sepolia.ts +14 -0
- package/chains/chains.test.ts +50 -0
- package/chains/defineChain.ts +18 -0
- package/chains/index.ts +35 -0
- package/chains/types.ts +32 -0
- package/core/baseBuilder.ts +119 -0
- package/core/client.test.ts +315 -0
- package/core/client.ts +292 -0
- package/core/clientTypes.ts +108 -0
- package/core/config.test.ts +235 -0
- package/core/config.ts +220 -0
- package/core/decrypt/MockQueryDecrypterAbi.ts +129 -0
- package/core/decrypt/cofheMocksSealOutput.ts +57 -0
- package/core/decrypt/decryptHandleBuilder.ts +287 -0
- package/core/decrypt/decryptUtils.ts +28 -0
- package/core/decrypt/tnSealOutputV1.ts +59 -0
- package/core/decrypt/tnSealOutputV2.ts +298 -0
- package/core/encrypt/MockZkVerifierAbi.ts +106 -0
- package/core/encrypt/cofheMocksZkVerifySign.ts +284 -0
- package/core/encrypt/encryptInputsBuilder.test.ts +751 -0
- package/core/encrypt/encryptInputsBuilder.ts +560 -0
- package/core/encrypt/encryptUtils.ts +67 -0
- package/core/encrypt/zkPackProveVerify.ts +335 -0
- package/core/error.ts +168 -0
- package/core/fetchKeys.test.ts +195 -0
- package/core/fetchKeys.ts +144 -0
- package/core/index.ts +89 -0
- package/core/keyStore.test.ts +226 -0
- package/core/keyStore.ts +154 -0
- package/core/permits.test.ts +494 -0
- package/core/permits.ts +200 -0
- package/core/types.ts +398 -0
- package/core/utils.ts +130 -0
- package/dist/adapters.cjs +88 -0
- package/dist/adapters.d.cts +14576 -0
- package/dist/adapters.d.ts +14576 -0
- package/dist/adapters.js +83 -0
- package/dist/chains.cjs +114 -0
- package/dist/chains.d.cts +121 -0
- package/dist/chains.d.ts +121 -0
- package/dist/chains.js +1 -0
- package/dist/chunk-UGBVZNRT.js +818 -0
- package/dist/chunk-WEAZ25JO.js +105 -0
- package/dist/chunk-WGCRJCBR.js +2523 -0
- package/dist/clientTypes-5_1nwtUe.d.cts +914 -0
- package/dist/clientTypes-Es7fyi65.d.ts +914 -0
- package/dist/core.cjs +3414 -0
- package/dist/core.d.cts +111 -0
- package/dist/core.d.ts +111 -0
- package/dist/core.js +3 -0
- package/dist/node.cjs +3286 -0
- package/dist/node.d.cts +22 -0
- package/dist/node.d.ts +22 -0
- package/dist/node.js +91 -0
- package/dist/permit-fUSe6KKq.d.cts +349 -0
- package/dist/permit-fUSe6KKq.d.ts +349 -0
- package/dist/permits.cjs +871 -0
- package/dist/permits.d.cts +1045 -0
- package/dist/permits.d.ts +1045 -0
- package/dist/permits.js +1 -0
- package/dist/types-KImPrEIe.d.cts +48 -0
- package/dist/types-KImPrEIe.d.ts +48 -0
- package/dist/web.cjs +3478 -0
- package/dist/web.d.cts +38 -0
- package/dist/web.d.ts +38 -0
- package/dist/web.js +240 -0
- package/dist/zkProve.worker.cjs +93 -0
- package/dist/zkProve.worker.d.cts +2 -0
- package/dist/zkProve.worker.d.ts +2 -0
- package/dist/zkProve.worker.js +91 -0
- package/node/client.test.ts +147 -0
- package/node/config.test.ts +68 -0
- package/node/encryptInputs.test.ts +155 -0
- package/node/index.ts +97 -0
- package/node/storage.ts +51 -0
- package/package.json +27 -15
- package/permits/index.ts +68 -0
- package/permits/localstorage.test.ts +117 -0
- package/permits/permit.test.ts +477 -0
- package/permits/permit.ts +405 -0
- package/permits/sealing.test.ts +84 -0
- package/permits/sealing.ts +131 -0
- package/permits/signature.ts +79 -0
- package/permits/store.test.ts +128 -0
- package/permits/store.ts +166 -0
- package/permits/test-utils.ts +20 -0
- package/permits/types.ts +191 -0
- package/permits/utils.ts +62 -0
- package/permits/validation.test.ts +288 -0
- package/permits/validation.ts +369 -0
- package/web/client.web.test.ts +147 -0
- package/web/config.web.test.ts +69 -0
- package/web/encryptInputs.web.test.ts +172 -0
- package/web/index.ts +161 -0
- package/web/storage.ts +34 -0
- package/web/worker.builder.web.test.ts +148 -0
- package/web/worker.config.web.test.ts +329 -0
- package/web/worker.output.web.test.ts +84 -0
- package/web/workerManager.test.ts +80 -0
- package/web/workerManager.ts +214 -0
- package/web/workerManager.web.test.ts +114 -0
- package/web/zkProve.worker.ts +133 -0
package/core/client.ts
ADDED
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
import type { CreateSelfPermitOptions, CreateSharingPermitOptions, ImportSharedPermitOptions } from '@/permits';
|
|
2
|
+
|
|
3
|
+
import { createStore } from 'zustand/vanilla';
|
|
4
|
+
import { type PublicClient, type WalletClient } from 'viem';
|
|
5
|
+
import { CofhesdkError, CofhesdkErrorCode } from './error.js';
|
|
6
|
+
import { EncryptInputsBuilder } from './encrypt/encryptInputsBuilder.js';
|
|
7
|
+
import { createKeysStore } from './keyStore.js';
|
|
8
|
+
import { permits } from './permits.js';
|
|
9
|
+
import { DecryptHandlesBuilder } from './decrypt/decryptHandleBuilder.js';
|
|
10
|
+
import { getPublicClientChainID, getWalletClientAccount } from './utils.js';
|
|
11
|
+
import type {
|
|
12
|
+
CofhesdkClientConnectionState,
|
|
13
|
+
CofhesdkClientParams,
|
|
14
|
+
CofhesdkClient,
|
|
15
|
+
CofhesdkClientPermits,
|
|
16
|
+
} from './clientTypes.js';
|
|
17
|
+
import type { EncryptableItem, FheTypes } from './types.js';
|
|
18
|
+
import type { CofhesdkConfig } from './config.js';
|
|
19
|
+
|
|
20
|
+
export const InitialConnectStore: CofhesdkClientConnectionState = {
|
|
21
|
+
connected: false,
|
|
22
|
+
connecting: false,
|
|
23
|
+
connectError: undefined,
|
|
24
|
+
chainId: undefined,
|
|
25
|
+
account: undefined,
|
|
26
|
+
publicClient: undefined,
|
|
27
|
+
walletClient: undefined,
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Creates a CoFHE SDK client instance (base implementation)
|
|
32
|
+
* @param {CofhesdkClientParams} opts - Initialization options including config and platform-specific serializers
|
|
33
|
+
* @returns {CofhesdkClient} - The CoFHE SDK client instance
|
|
34
|
+
*/
|
|
35
|
+
export function createCofhesdkClientBase<TConfig extends CofhesdkConfig>(
|
|
36
|
+
opts: CofhesdkClientParams<TConfig>
|
|
37
|
+
): CofhesdkClient<TConfig> {
|
|
38
|
+
// Create keysStorage instance using configured storage
|
|
39
|
+
const keysStorage = createKeysStore(opts.config.fheKeyStorage);
|
|
40
|
+
|
|
41
|
+
// Zustand store for reactive state management
|
|
42
|
+
|
|
43
|
+
const connectStore = createStore<CofhesdkClientConnectionState>(() => InitialConnectStore);
|
|
44
|
+
|
|
45
|
+
// Helper to update state
|
|
46
|
+
const updateConnectState = (partial: Partial<CofhesdkClientConnectionState>) => {
|
|
47
|
+
connectStore.setState((state) => ({ ...state, ...partial }));
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
// Called before any operation, throws of connection not yet established
|
|
51
|
+
const _requireConnected = () => {
|
|
52
|
+
const state = connectStore.getState();
|
|
53
|
+
const notConnected =
|
|
54
|
+
!state.connected || !state.account || !state.chainId || !state.publicClient || !state.walletClient;
|
|
55
|
+
if (notConnected) {
|
|
56
|
+
throw new CofhesdkError({
|
|
57
|
+
code: CofhesdkErrorCode.NotConnected,
|
|
58
|
+
message: 'Client must be connected, account and chainId must be initialized',
|
|
59
|
+
hint: 'Ensure client.connect() has been called and awaited.',
|
|
60
|
+
context: {
|
|
61
|
+
connected: state.connected,
|
|
62
|
+
account: state.account,
|
|
63
|
+
chainId: state.chainId,
|
|
64
|
+
publicClient: state.publicClient,
|
|
65
|
+
walletClient: state.walletClient,
|
|
66
|
+
},
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
// LIFECYCLE
|
|
72
|
+
|
|
73
|
+
async function connect(publicClient: PublicClient, walletClient: WalletClient) {
|
|
74
|
+
const state = connectStore.getState();
|
|
75
|
+
|
|
76
|
+
// Exit if already connected and clients are the same
|
|
77
|
+
if (state.connected && state.publicClient === publicClient && state.walletClient === walletClient) return;
|
|
78
|
+
|
|
79
|
+
// Set connecting state
|
|
80
|
+
updateConnectState({
|
|
81
|
+
...InitialConnectStore,
|
|
82
|
+
connecting: true,
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
// Fetch chainId and account
|
|
86
|
+
try {
|
|
87
|
+
const chainId = await getPublicClientChainID(publicClient);
|
|
88
|
+
const account = await getWalletClientAccount(walletClient);
|
|
89
|
+
updateConnectState({
|
|
90
|
+
connected: true,
|
|
91
|
+
connecting: false,
|
|
92
|
+
connectError: undefined,
|
|
93
|
+
chainId,
|
|
94
|
+
account,
|
|
95
|
+
publicClient,
|
|
96
|
+
walletClient,
|
|
97
|
+
});
|
|
98
|
+
} catch (e) {
|
|
99
|
+
updateConnectState({
|
|
100
|
+
...InitialConnectStore,
|
|
101
|
+
connectError: e,
|
|
102
|
+
});
|
|
103
|
+
throw e;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// CLIENT OPERATIONS
|
|
108
|
+
|
|
109
|
+
function encryptInputs<T extends EncryptableItem[]>(inputs: [...T]): EncryptInputsBuilder<[...T]> {
|
|
110
|
+
const state = connectStore.getState();
|
|
111
|
+
|
|
112
|
+
return new EncryptInputsBuilder({
|
|
113
|
+
inputs,
|
|
114
|
+
account: state.account ?? undefined,
|
|
115
|
+
chainId: state.chainId ?? undefined,
|
|
116
|
+
|
|
117
|
+
config: opts.config,
|
|
118
|
+
publicClient: state.publicClient ?? undefined,
|
|
119
|
+
walletClient: state.walletClient ?? undefined,
|
|
120
|
+
zkvWalletClient: opts.config._internal?.zkvWalletClient,
|
|
121
|
+
|
|
122
|
+
tfhePublicKeyDeserializer: opts.tfhePublicKeyDeserializer,
|
|
123
|
+
compactPkeCrsDeserializer: opts.compactPkeCrsDeserializer,
|
|
124
|
+
zkBuilderAndCrsGenerator: opts.zkBuilderAndCrsGenerator,
|
|
125
|
+
initTfhe: opts.initTfhe,
|
|
126
|
+
zkProveWorkerFn: opts.zkProveWorkerFn,
|
|
127
|
+
|
|
128
|
+
keysStorage,
|
|
129
|
+
|
|
130
|
+
requireConnected: _requireConnected,
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
function decryptHandle<U extends FheTypes>(ctHash: bigint, utype: U): DecryptHandlesBuilder<U> {
|
|
135
|
+
const state = connectStore.getState();
|
|
136
|
+
|
|
137
|
+
return new DecryptHandlesBuilder({
|
|
138
|
+
ctHash,
|
|
139
|
+
utype,
|
|
140
|
+
chainId: state.chainId ?? undefined,
|
|
141
|
+
account: state.account ?? undefined,
|
|
142
|
+
|
|
143
|
+
config: opts.config,
|
|
144
|
+
publicClient: state.publicClient ?? undefined,
|
|
145
|
+
walletClient: state.walletClient ?? undefined,
|
|
146
|
+
|
|
147
|
+
requireConnected: _requireConnected,
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// PERMITS - Context-aware wrapper
|
|
152
|
+
|
|
153
|
+
const _getChainIdAndAccount = (chainId?: number, account?: string) => {
|
|
154
|
+
const state = connectStore.getState();
|
|
155
|
+
const _chainId = chainId ?? state.chainId;
|
|
156
|
+
const _account = account ?? state.account;
|
|
157
|
+
|
|
158
|
+
if (_chainId == null || _account == null) {
|
|
159
|
+
throw new CofhesdkError({
|
|
160
|
+
code: CofhesdkErrorCode.NotConnected,
|
|
161
|
+
message: 'ChainId or account not available.',
|
|
162
|
+
hint: 'Ensure client.connect() has been called, or provide chainId and account explicitly.',
|
|
163
|
+
context: {
|
|
164
|
+
chainId: _chainId,
|
|
165
|
+
account: _account,
|
|
166
|
+
},
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
return { chainId: _chainId, account: _account };
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
const clientPermits: CofhesdkClientPermits = {
|
|
174
|
+
// Pass through store access
|
|
175
|
+
getSnapshot: permits.getSnapshot,
|
|
176
|
+
subscribe: permits.subscribe,
|
|
177
|
+
|
|
178
|
+
// Creation methods (require connection)
|
|
179
|
+
createSelf: async (
|
|
180
|
+
options: CreateSelfPermitOptions,
|
|
181
|
+
clients?: { publicClient: PublicClient; walletClient: WalletClient }
|
|
182
|
+
) => {
|
|
183
|
+
_requireConnected();
|
|
184
|
+
const { publicClient, walletClient } = clients ?? connectStore.getState();
|
|
185
|
+
return permits.createSelf(options, publicClient!, walletClient!);
|
|
186
|
+
},
|
|
187
|
+
|
|
188
|
+
createSharing: async (
|
|
189
|
+
options: CreateSharingPermitOptions,
|
|
190
|
+
clients?: { publicClient: PublicClient; walletClient: WalletClient }
|
|
191
|
+
) => {
|
|
192
|
+
_requireConnected();
|
|
193
|
+
const { publicClient, walletClient } = clients ?? connectStore.getState();
|
|
194
|
+
return permits.createSharing(options, publicClient!, walletClient!);
|
|
195
|
+
},
|
|
196
|
+
|
|
197
|
+
importShared: async (
|
|
198
|
+
options: ImportSharedPermitOptions | string,
|
|
199
|
+
clients?: { publicClient: PublicClient; walletClient: WalletClient }
|
|
200
|
+
) => {
|
|
201
|
+
_requireConnected();
|
|
202
|
+
const { publicClient, walletClient } = clients ?? connectStore.getState();
|
|
203
|
+
return permits.importShared(options, publicClient!, walletClient!);
|
|
204
|
+
},
|
|
205
|
+
|
|
206
|
+
// Get or create methods (require connection)
|
|
207
|
+
getOrCreateSelfPermit: async (chainId?: number, account?: string, options?: CreateSelfPermitOptions) => {
|
|
208
|
+
_requireConnected();
|
|
209
|
+
const { chainId: _chainId, account: _account } = _getChainIdAndAccount(chainId, account);
|
|
210
|
+
const { publicClient, walletClient } = connectStore.getState();
|
|
211
|
+
return permits.getOrCreateSelfPermit(publicClient!, walletClient!, _chainId, _account, options);
|
|
212
|
+
},
|
|
213
|
+
|
|
214
|
+
getOrCreateSharingPermit: async (options: CreateSharingPermitOptions, chainId?: number, account?: string) => {
|
|
215
|
+
_requireConnected();
|
|
216
|
+
const { chainId: _chainId, account: _account } = _getChainIdAndAccount(chainId, account);
|
|
217
|
+
const { publicClient, walletClient } = connectStore.getState();
|
|
218
|
+
return permits.getOrCreateSharingPermit(publicClient!, walletClient!, options, _chainId, _account);
|
|
219
|
+
},
|
|
220
|
+
|
|
221
|
+
// Retrieval methods (auto-fill chainId/account)
|
|
222
|
+
getPermit: async (hash: string, chainId?: number, account?: string) => {
|
|
223
|
+
const { chainId: _chainId, account: _account } = _getChainIdAndAccount(chainId, account);
|
|
224
|
+
return permits.getPermit(_chainId, _account, hash);
|
|
225
|
+
},
|
|
226
|
+
|
|
227
|
+
getPermits: async (chainId?: number, account?: string) => {
|
|
228
|
+
const { chainId: _chainId, account: _account } = _getChainIdAndAccount(chainId, account);
|
|
229
|
+
return permits.getPermits(_chainId, _account);
|
|
230
|
+
},
|
|
231
|
+
|
|
232
|
+
getActivePermit: async (chainId?: number, account?: string) => {
|
|
233
|
+
const { chainId: _chainId, account: _account } = _getChainIdAndAccount(chainId, account);
|
|
234
|
+
return permits.getActivePermit(_chainId, _account);
|
|
235
|
+
},
|
|
236
|
+
|
|
237
|
+
getActivePermitHash: async (chainId?: number, account?: string) => {
|
|
238
|
+
const { chainId: _chainId, account: _account } = _getChainIdAndAccount(chainId, account);
|
|
239
|
+
return permits.getActivePermitHash(_chainId, _account);
|
|
240
|
+
},
|
|
241
|
+
|
|
242
|
+
// Mutation methods (auto-fill chainId/account)
|
|
243
|
+
selectActivePermit: (hash: string, chainId?: number, account?: string) => {
|
|
244
|
+
const { chainId: _chainId, account: _account } = _getChainIdAndAccount(chainId, account);
|
|
245
|
+
return permits.selectActivePermit(_chainId, _account, hash);
|
|
246
|
+
},
|
|
247
|
+
|
|
248
|
+
removePermit: async (hash: string, chainId?: number, account?: string, force?: boolean) => {
|
|
249
|
+
const { chainId: _chainId, account: _account } = _getChainIdAndAccount(chainId, account);
|
|
250
|
+
return permits.removePermit(_chainId, _account, hash, force);
|
|
251
|
+
},
|
|
252
|
+
|
|
253
|
+
removeActivePermit: async (chainId?: number, account?: string) => {
|
|
254
|
+
const { chainId: _chainId, account: _account } = _getChainIdAndAccount(chainId, account);
|
|
255
|
+
return permits.removeActivePermit(_chainId, _account);
|
|
256
|
+
},
|
|
257
|
+
|
|
258
|
+
// Utils (no context needed)
|
|
259
|
+
getHash: permits.getHash,
|
|
260
|
+
serialize: permits.serialize,
|
|
261
|
+
deserialize: permits.deserialize,
|
|
262
|
+
};
|
|
263
|
+
|
|
264
|
+
return {
|
|
265
|
+
// Zustand reactive accessors (don't export store directly to prevent mutation)
|
|
266
|
+
getSnapshot: connectStore.getState,
|
|
267
|
+
subscribe: connectStore.subscribe,
|
|
268
|
+
|
|
269
|
+
// flags (read-only: reflect snapshot)
|
|
270
|
+
get connected() {
|
|
271
|
+
return connectStore.getState().connected;
|
|
272
|
+
},
|
|
273
|
+
get connecting() {
|
|
274
|
+
return connectStore.getState().connecting;
|
|
275
|
+
},
|
|
276
|
+
|
|
277
|
+
// config & platform-specific (read-only)
|
|
278
|
+
config: opts.config,
|
|
279
|
+
|
|
280
|
+
connect,
|
|
281
|
+
encryptInputs,
|
|
282
|
+
decryptHandle,
|
|
283
|
+
permits: clientPermits,
|
|
284
|
+
|
|
285
|
+
// Add SDK-specific methods below that require connection
|
|
286
|
+
// Example:
|
|
287
|
+
// async encryptData(data: unknown) {
|
|
288
|
+
// requireConnected();
|
|
289
|
+
// // Use state.publicClient and state.walletClient for implementation
|
|
290
|
+
// },
|
|
291
|
+
};
|
|
292
|
+
}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
// TODO: Extract client types to its own file, keep this one as primitives
|
|
2
|
+
import { type PublicClient, type WalletClient } from 'viem';
|
|
3
|
+
import { type CofhesdkConfig, type CofhesdkEnvironment } from './config.js';
|
|
4
|
+
import { type DecryptHandlesBuilder } from './decrypt/decryptHandleBuilder.js';
|
|
5
|
+
import { type EncryptInputsBuilder } from './encrypt/encryptInputsBuilder.js';
|
|
6
|
+
import { type ZkBuilderAndCrsGenerator, type ZkProveWorkerFunction } from './encrypt/zkPackProveVerify.js';
|
|
7
|
+
import { type FheKeyDeserializer } from './fetchKeys.js';
|
|
8
|
+
import { permits } from './permits.js';
|
|
9
|
+
import type { EncryptableItem, FheTypes, TfheInitializer } from './types.js';
|
|
10
|
+
import type { PermitUtils } from 'permits/permit.js';
|
|
11
|
+
import type {
|
|
12
|
+
CreateSelfPermitOptions,
|
|
13
|
+
Permit,
|
|
14
|
+
CreateSharingPermitOptions,
|
|
15
|
+
ImportSharedPermitOptions,
|
|
16
|
+
SharingPermit,
|
|
17
|
+
RecipientPermit,
|
|
18
|
+
SelfPermit,
|
|
19
|
+
} from 'permits/types.js';
|
|
20
|
+
|
|
21
|
+
// CLIENT
|
|
22
|
+
|
|
23
|
+
export type CofhesdkClient<TConfig extends CofhesdkConfig = CofhesdkConfig> = {
|
|
24
|
+
// --- state access ---
|
|
25
|
+
getSnapshot(): CofhesdkClientConnectionState;
|
|
26
|
+
subscribe(listener: Listener): () => void;
|
|
27
|
+
|
|
28
|
+
// --- convenience flags (read-only) ---
|
|
29
|
+
readonly connected: boolean;
|
|
30
|
+
readonly connecting: boolean;
|
|
31
|
+
|
|
32
|
+
// --- config & platform-specific ---
|
|
33
|
+
readonly config: TConfig;
|
|
34
|
+
|
|
35
|
+
connect(publicClient: PublicClient, walletClient: WalletClient): Promise<void>;
|
|
36
|
+
/**
|
|
37
|
+
* Types docstring
|
|
38
|
+
*/
|
|
39
|
+
encryptInputs<T extends EncryptableItem[]>(inputs: [...T]): EncryptInputsBuilder<[...T]>;
|
|
40
|
+
decryptHandle<U extends FheTypes>(ctHash: bigint, utype: U): DecryptHandlesBuilder<U>;
|
|
41
|
+
permits: CofhesdkClientPermits;
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
export type CofhesdkClientConnectionState = {
|
|
45
|
+
connected: boolean;
|
|
46
|
+
connecting: boolean;
|
|
47
|
+
connectError: unknown | undefined;
|
|
48
|
+
chainId: number | undefined;
|
|
49
|
+
account: `0x${string}` | undefined;
|
|
50
|
+
publicClient: PublicClient | undefined;
|
|
51
|
+
walletClient: WalletClient | undefined;
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
type Listener = (snapshot: CofhesdkClientConnectionState) => void;
|
|
55
|
+
|
|
56
|
+
export type CofhesdkClientPermitsClients = {
|
|
57
|
+
publicClient: PublicClient;
|
|
58
|
+
walletClient: WalletClient;
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
export type CofhesdkClientPermits = {
|
|
62
|
+
getSnapshot: typeof permits.getSnapshot;
|
|
63
|
+
subscribe: typeof permits.subscribe;
|
|
64
|
+
|
|
65
|
+
// Creation methods (require connection, no params)
|
|
66
|
+
createSelf: (options: CreateSelfPermitOptions, clients?: CofhesdkClientPermitsClients) => Promise<SelfPermit>;
|
|
67
|
+
createSharing: (
|
|
68
|
+
options: CreateSharingPermitOptions,
|
|
69
|
+
clients?: CofhesdkClientPermitsClients
|
|
70
|
+
) => Promise<SharingPermit>;
|
|
71
|
+
importShared: (
|
|
72
|
+
options: ImportSharedPermitOptions | string,
|
|
73
|
+
clients?: CofhesdkClientPermitsClients
|
|
74
|
+
) => Promise<RecipientPermit>;
|
|
75
|
+
|
|
76
|
+
// Retrieval methods (chainId/account optional)
|
|
77
|
+
getPermit: (hash: string, chainId?: number, account?: string) => Promise<Permit | undefined>;
|
|
78
|
+
getPermits: (chainId?: number, account?: string) => Promise<Record<string, Permit>>;
|
|
79
|
+
getActivePermit: (chainId?: number, account?: string) => Promise<Permit | undefined>;
|
|
80
|
+
getActivePermitHash: (chainId?: number, account?: string) => Promise<string | undefined>;
|
|
81
|
+
|
|
82
|
+
// Get or create methods (get active or create new, chainId/account optional)
|
|
83
|
+
getOrCreateSelfPermit: (chainId?: number, account?: string, options?: CreateSelfPermitOptions) => Promise<Permit>;
|
|
84
|
+
getOrCreateSharingPermit: (
|
|
85
|
+
options: CreateSharingPermitOptions,
|
|
86
|
+
chainId?: number,
|
|
87
|
+
account?: string
|
|
88
|
+
) => Promise<Permit>;
|
|
89
|
+
|
|
90
|
+
// Mutation methods (chainId/account optional)
|
|
91
|
+
selectActivePermit: (hash: string, chainId?: number, account?: string) => void;
|
|
92
|
+
removePermit: (hash: string, chainId?: number, account?: string, force?: boolean) => void;
|
|
93
|
+
removeActivePermit: (chainId?: number, account?: string) => void;
|
|
94
|
+
|
|
95
|
+
// Utils
|
|
96
|
+
getHash: typeof PermitUtils.getHash;
|
|
97
|
+
serialize: typeof PermitUtils.serialize;
|
|
98
|
+
deserialize: typeof PermitUtils.deserialize;
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
export type CofhesdkClientParams<TConfig extends CofhesdkConfig> = {
|
|
102
|
+
config: TConfig;
|
|
103
|
+
zkBuilderAndCrsGenerator: ZkBuilderAndCrsGenerator;
|
|
104
|
+
tfhePublicKeyDeserializer: FheKeyDeserializer;
|
|
105
|
+
compactPkeCrsDeserializer: FheKeyDeserializer;
|
|
106
|
+
initTfhe: TfheInitializer;
|
|
107
|
+
zkProveWorkerFn?: ZkProveWorkerFunction;
|
|
108
|
+
};
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
import { sepolia, hardhat } from '@/chains';
|
|
2
|
+
|
|
3
|
+
import { describe, it, expect, vi } from 'vitest';
|
|
4
|
+
import {
|
|
5
|
+
createCofhesdkConfigBase,
|
|
6
|
+
getCofhesdkConfigItem,
|
|
7
|
+
type CofhesdkInputConfig,
|
|
8
|
+
getSupportedChainOrThrow,
|
|
9
|
+
getCoFheUrlOrThrow,
|
|
10
|
+
getZkVerifierUrlOrThrow,
|
|
11
|
+
getThresholdNetworkUrlOrThrow,
|
|
12
|
+
} from './config.js';
|
|
13
|
+
|
|
14
|
+
describe('createCofhesdkConfigBase', () => {
|
|
15
|
+
const validBaseConfig: CofhesdkInputConfig = {
|
|
16
|
+
supportedChains: [],
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
const setNestedValue = (obj: any, path: string, value: any): void => {
|
|
20
|
+
const keys = path.split('.');
|
|
21
|
+
const lastKey = keys.pop()!;
|
|
22
|
+
const target = keys.reduce((acc, key) => {
|
|
23
|
+
if (!acc[key]) acc[key] = {};
|
|
24
|
+
return acc[key];
|
|
25
|
+
}, obj);
|
|
26
|
+
target[lastKey] = value;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
const getNestedValue = (obj: any, path: string): any => {
|
|
30
|
+
return path.split('.').reduce((acc, key) => acc?.[key], obj);
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const expectInvalidConfigItem = (path: string, value: any, log = false): void => {
|
|
34
|
+
const config = { ...validBaseConfig };
|
|
35
|
+
setNestedValue(config, path, value);
|
|
36
|
+
if (log) {
|
|
37
|
+
console.log('expect config invalid', path, value, config);
|
|
38
|
+
try {
|
|
39
|
+
createCofhesdkConfigBase(config as CofhesdkInputConfig);
|
|
40
|
+
} catch (e) {
|
|
41
|
+
console.log('expect config invalid', path, value, config, e);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
expect(() => createCofhesdkConfigBase(config as CofhesdkInputConfig)).toThrow('Invalid cofhesdk configuration:');
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
const expectValidConfigItem = (path: string, value: any, expectedValue: any): void => {
|
|
48
|
+
const config = { ...validBaseConfig };
|
|
49
|
+
setNestedValue(config, path, value);
|
|
50
|
+
const result = createCofhesdkConfigBase(config);
|
|
51
|
+
expect(getNestedValue(result, path)).toEqual(expectedValue);
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
it('environment', () => {
|
|
55
|
+
expectInvalidConfigItem('environment', 'not-a-valid-environment');
|
|
56
|
+
expectInvalidConfigItem('environment', 123);
|
|
57
|
+
expectInvalidConfigItem('environment', {});
|
|
58
|
+
|
|
59
|
+
expectValidConfigItem('environment', 'node', 'node');
|
|
60
|
+
expectValidConfigItem('environment', 'hardhat', 'hardhat');
|
|
61
|
+
expectValidConfigItem('environment', 'web', 'web');
|
|
62
|
+
expectValidConfigItem('environment', 'react', 'react');
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it('supportedChains', () => {
|
|
66
|
+
expectInvalidConfigItem('supportedChains', {});
|
|
67
|
+
expectInvalidConfigItem('supportedChains', 'not-an-array');
|
|
68
|
+
expectInvalidConfigItem('supportedChains', null);
|
|
69
|
+
expectInvalidConfigItem('supportedChains', undefined);
|
|
70
|
+
|
|
71
|
+
expectValidConfigItem('supportedChains', [sepolia], [sepolia]);
|
|
72
|
+
expectValidConfigItem('supportedChains', [sepolia, hardhat], [sepolia, hardhat]);
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
it('permitGeneration', () => {
|
|
76
|
+
expectInvalidConfigItem('permitGeneration', 'not-a-boolean');
|
|
77
|
+
expectInvalidConfigItem('permitGeneration', null);
|
|
78
|
+
|
|
79
|
+
expectValidConfigItem('permitGeneration', 'ON_CONNECT', 'ON_CONNECT');
|
|
80
|
+
expectValidConfigItem('permitGeneration', 'ON_DECRYPT_HANDLES', 'ON_DECRYPT_HANDLES');
|
|
81
|
+
expectValidConfigItem('permitGeneration', 'MANUAL', 'MANUAL');
|
|
82
|
+
expectValidConfigItem('permitGeneration', undefined, 'ON_CONNECT');
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
it('defaultPermitExpiration', () => {
|
|
86
|
+
expectInvalidConfigItem('defaultPermitExpiration', 'not-a-number');
|
|
87
|
+
expectInvalidConfigItem('defaultPermitExpiration', null);
|
|
88
|
+
|
|
89
|
+
expectValidConfigItem('defaultPermitExpiration', 5, 5);
|
|
90
|
+
expectValidConfigItem('defaultPermitExpiration', undefined, 60 * 60 * 24 * 30);
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
it('fheKeyStorage', async () => {
|
|
94
|
+
expectInvalidConfigItem('fheKeyStorage', 'not-an-object');
|
|
95
|
+
|
|
96
|
+
expectValidConfigItem('fheKeyStorage', undefined, null);
|
|
97
|
+
expectValidConfigItem('fheKeyStorage', null, null);
|
|
98
|
+
|
|
99
|
+
let getItemCalled = false;
|
|
100
|
+
let setItemCalled = false;
|
|
101
|
+
let removeItemCalled = false;
|
|
102
|
+
|
|
103
|
+
const fakeStorage = {
|
|
104
|
+
getItem: (name: string) => {
|
|
105
|
+
getItemCalled = true;
|
|
106
|
+
return Promise.resolve(null);
|
|
107
|
+
},
|
|
108
|
+
setItem: (name: string, value: any) => {
|
|
109
|
+
setItemCalled = true;
|
|
110
|
+
return Promise.resolve();
|
|
111
|
+
},
|
|
112
|
+
removeItem: (name: string) => {
|
|
113
|
+
removeItemCalled = true;
|
|
114
|
+
return Promise.resolve();
|
|
115
|
+
},
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
const config = { ...validBaseConfig, fheKeyStorage: fakeStorage };
|
|
119
|
+
const result = createCofhesdkConfigBase(config);
|
|
120
|
+
|
|
121
|
+
expect(result.fheKeyStorage).not.toBeNull();
|
|
122
|
+
await result.fheKeyStorage!.getItem('test');
|
|
123
|
+
await result.fheKeyStorage!.setItem('test', 'test');
|
|
124
|
+
await result.fheKeyStorage!.removeItem('test');
|
|
125
|
+
|
|
126
|
+
expect(getItemCalled).toBe(true);
|
|
127
|
+
expect(setItemCalled).toBe(true);
|
|
128
|
+
expect(removeItemCalled).toBe(true);
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
it('mocks', () => {
|
|
132
|
+
expectInvalidConfigItem('mocks', 'not-an-object');
|
|
133
|
+
expectInvalidConfigItem('mocks', null);
|
|
134
|
+
|
|
135
|
+
expectValidConfigItem('mocks', { sealOutputDelay: 1000 }, { sealOutputDelay: 1000 });
|
|
136
|
+
expectValidConfigItem('mocks', undefined, { sealOutputDelay: 0 });
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
it('mocks.sealOutputDelay', () => {
|
|
140
|
+
expectInvalidConfigItem('mocks.sealOutputDelay', 'not-a-number');
|
|
141
|
+
expectInvalidConfigItem('mocks.sealOutputDelay', null);
|
|
142
|
+
|
|
143
|
+
expectValidConfigItem('mocks.sealOutputDelay', undefined, 0);
|
|
144
|
+
expectValidConfigItem('mocks.sealOutputDelay', 1000, 1000);
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
it('useWorkers', () => {
|
|
148
|
+
expectInvalidConfigItem('useWorkers', 'not-a-boolean');
|
|
149
|
+
expectInvalidConfigItem('useWorkers', null);
|
|
150
|
+
expectInvalidConfigItem('useWorkers', 123);
|
|
151
|
+
expectInvalidConfigItem('useWorkers', {});
|
|
152
|
+
|
|
153
|
+
expectValidConfigItem('useWorkers', true, true);
|
|
154
|
+
expectValidConfigItem('useWorkers', false, false);
|
|
155
|
+
expectValidConfigItem('useWorkers', undefined, true); // defaults to true
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
it('should get config item', () => {
|
|
159
|
+
const config: CofhesdkInputConfig = {
|
|
160
|
+
supportedChains: [sepolia],
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
const result = createCofhesdkConfigBase(config);
|
|
164
|
+
|
|
165
|
+
const supportedChains = getCofhesdkConfigItem(result, 'supportedChains');
|
|
166
|
+
expect(supportedChains).toEqual(config.supportedChains);
|
|
167
|
+
});
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
describe('Config helper functions', () => {
|
|
171
|
+
const config = createCofhesdkConfigBase({
|
|
172
|
+
supportedChains: [sepolia, hardhat],
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
describe('getSupportedChainOrThrow', () => {
|
|
176
|
+
it('should return chain when found', () => {
|
|
177
|
+
expect(getSupportedChainOrThrow(config, sepolia.id)).toEqual(sepolia);
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
it('should throw UnsupportedChain error when not found', () => {
|
|
181
|
+
expect(() => getSupportedChainOrThrow(config, 999999)).toThrow();
|
|
182
|
+
});
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
describe('getCoFheUrlOrThrow', () => {
|
|
186
|
+
it('should return coFheUrl', () => {
|
|
187
|
+
expect(getCoFheUrlOrThrow(config, sepolia.id)).toBe(sepolia.coFheUrl);
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
it('should throw when chain not found', () => {
|
|
191
|
+
expect(() => getCoFheUrlOrThrow(config, 999999)).toThrow();
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
it('should throw MissingConfig when url not set', () => {
|
|
195
|
+
const configWithoutUrl = createCofhesdkConfigBase({
|
|
196
|
+
supportedChains: [{ ...sepolia, coFheUrl: undefined } as any],
|
|
197
|
+
});
|
|
198
|
+
expect(() => getCoFheUrlOrThrow(configWithoutUrl, sepolia.id)).toThrow();
|
|
199
|
+
});
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
describe('getZkVerifierUrlOrThrow', () => {
|
|
203
|
+
it('should return verifierUrl', () => {
|
|
204
|
+
expect(getZkVerifierUrlOrThrow(config, sepolia.id)).toBe(sepolia.verifierUrl);
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
it('should throw when chain not found', () => {
|
|
208
|
+
expect(() => getZkVerifierUrlOrThrow(config, 999999)).toThrow();
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
it('should throw ZkVerifierUrlUninitialized when url not set', () => {
|
|
212
|
+
const configWithoutUrl = createCofhesdkConfigBase({
|
|
213
|
+
supportedChains: [{ ...sepolia, verifierUrl: undefined } as any],
|
|
214
|
+
});
|
|
215
|
+
expect(() => getZkVerifierUrlOrThrow(configWithoutUrl, sepolia.id)).toThrow();
|
|
216
|
+
});
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
describe('getThresholdNetworkUrlOrThrow', () => {
|
|
220
|
+
it('should return thresholdNetworkUrl', () => {
|
|
221
|
+
expect(getThresholdNetworkUrlOrThrow(config, sepolia.id)).toBe(sepolia.thresholdNetworkUrl);
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
it('should throw when chain not found', () => {
|
|
225
|
+
expect(() => getThresholdNetworkUrlOrThrow(config, 999999)).toThrow();
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
it('should throw ThresholdNetworkUrlUninitialized when url not set', () => {
|
|
229
|
+
const configWithoutUrl = createCofhesdkConfigBase({
|
|
230
|
+
supportedChains: [{ ...sepolia, thresholdNetworkUrl: undefined } as any],
|
|
231
|
+
});
|
|
232
|
+
expect(() => getThresholdNetworkUrlOrThrow(configWithoutUrl, sepolia.id)).toThrow();
|
|
233
|
+
});
|
|
234
|
+
});
|
|
235
|
+
});
|