@cofhe/sdk 0.0.0-beta-20251027110729
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 +47 -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 +37 -0
- package/adapters/index.test.ts +25 -0
- package/adapters/index.ts +5 -0
- package/adapters/smartWallet.ts +91 -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/sepolia.ts +14 -0
- package/chains/chains.test.ts +49 -0
- package/chains/defineChain.ts +18 -0
- package/chains/index.ts +33 -0
- package/chains/types.ts +32 -0
- package/core/baseBuilder.ts +138 -0
- package/core/client.test.ts +298 -0
- package/core/client.ts +308 -0
- package/core/config.test.ts +224 -0
- package/core/config.ts +213 -0
- package/core/decrypt/MockQueryDecrypterAbi.ts +129 -0
- package/core/decrypt/cofheMocksSealOutput.ts +57 -0
- package/core/decrypt/decryptHandleBuilder.ts +281 -0
- package/core/decrypt/decryptUtils.ts +28 -0
- package/core/decrypt/tnSealOutput.ts +59 -0
- package/core/encrypt/MockZkVerifierAbi.ts +106 -0
- package/core/encrypt/cofheMocksZkVerifySign.ts +278 -0
- package/core/encrypt/encryptInputsBuilder.test.ts +735 -0
- package/core/encrypt/encryptInputsBuilder.ts +512 -0
- package/core/encrypt/encryptUtils.ts +64 -0
- package/core/encrypt/zkPackProveVerify.ts +273 -0
- package/core/error.ts +170 -0
- package/core/fetchKeys.test.ts +212 -0
- package/core/fetchKeys.ts +170 -0
- package/core/index.ts +77 -0
- package/core/keyStore.test.ts +226 -0
- package/core/keyStore.ts +127 -0
- package/core/permits.test.ts +242 -0
- package/core/permits.ts +136 -0
- package/core/result.test.ts +180 -0
- package/core/result.ts +67 -0
- package/core/test-utils.ts +45 -0
- package/core/types.ts +352 -0
- package/core/utils.ts +88 -0
- package/dist/adapters.cjs +88 -0
- package/dist/adapters.d.cts +14558 -0
- package/dist/adapters.d.ts +14558 -0
- package/dist/adapters.js +83 -0
- package/dist/chains.cjs +101 -0
- package/dist/chains.d.cts +99 -0
- package/dist/chains.d.ts +99 -0
- package/dist/chains.js +1 -0
- package/dist/chunk-GZCQQYVI.js +93 -0
- package/dist/chunk-KFGPTJ6X.js +2295 -0
- package/dist/chunk-LU7BMUUT.js +804 -0
- package/dist/core.cjs +3174 -0
- package/dist/core.d.cts +16 -0
- package/dist/core.d.ts +16 -0
- package/dist/core.js +3 -0
- package/dist/node.cjs +3090 -0
- package/dist/node.d.cts +22 -0
- package/dist/node.d.ts +22 -0
- package/dist/node.js +90 -0
- package/dist/permit-S9CnI6MF.d.cts +333 -0
- package/dist/permit-S9CnI6MF.d.ts +333 -0
- package/dist/permits.cjs +856 -0
- package/dist/permits.d.cts +1056 -0
- package/dist/permits.d.ts +1056 -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/types-PhwGgQvs.d.ts +953 -0
- package/dist/types-bB7wLj0q.d.cts +953 -0
- package/dist/web.cjs +3067 -0
- package/dist/web.d.cts +22 -0
- package/dist/web.d.ts +22 -0
- package/dist/web.js +64 -0
- package/node/client.test.ts +152 -0
- package/node/config.test.ts +68 -0
- package/node/encryptInputs.test.ts +175 -0
- package/node/index.ts +96 -0
- package/node/storage.ts +51 -0
- package/package.json +120 -0
- package/permits/index.ts +67 -0
- package/permits/localstorage.test.ts +118 -0
- package/permits/permit.test.ts +474 -0
- package/permits/permit.ts +396 -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 +168 -0
- package/permits/test-utils.ts +20 -0
- package/permits/types.ts +174 -0
- package/permits/utils.ts +63 -0
- package/permits/validation.test.ts +288 -0
- package/permits/validation.ts +349 -0
- package/web/client.web.test.ts +152 -0
- package/web/config.web.test.ts +71 -0
- package/web/encryptInputs.web.test.ts +195 -0
- package/web/index.ts +97 -0
- package/web/storage.ts +20 -0
package/core/client.ts
ADDED
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
/* eslint-disable no-unused-vars */
|
|
2
|
+
import type { CreateSelfPermitOptions, CreateSharingPermitOptions, ImportSharedPermitOptions } from '@/permits';
|
|
3
|
+
|
|
4
|
+
import { createStore } from 'zustand/vanilla';
|
|
5
|
+
import { type PublicClient, type WalletClient } from 'viem';
|
|
6
|
+
import { fetchMultichainKeys } from './fetchKeys.js';
|
|
7
|
+
import { CofhesdkError, CofhesdkErrorCode } from './error.js';
|
|
8
|
+
import { EncryptInputsBuilder } from './encrypt/encryptInputsBuilder.js';
|
|
9
|
+
import { type Result, ResultOk, resultWrapper } from './result.js';
|
|
10
|
+
import { createKeysStore } from './keyStore.js';
|
|
11
|
+
import { permits } from './permits.js';
|
|
12
|
+
import { DecryptHandlesBuilder } from './decrypt/decryptHandleBuilder.js';
|
|
13
|
+
import {
|
|
14
|
+
type CofhesdkClient,
|
|
15
|
+
type CofhesdkClientParams,
|
|
16
|
+
type CofhesdkClientConnectionState,
|
|
17
|
+
type EncryptableItem,
|
|
18
|
+
type FheTypes,
|
|
19
|
+
type CofhesdkClientPermits,
|
|
20
|
+
} from './types.js';
|
|
21
|
+
import { getPublicClientChainID, getWalletClientAccount } from './utils.js';
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Creates a CoFHE SDK client instance (base implementation)
|
|
25
|
+
* @param {CofhesdkClientParams} opts - Initialization options including config and platform-specific serializers
|
|
26
|
+
* @returns {CofhesdkClient} - The CoFHE SDK client instance
|
|
27
|
+
*/
|
|
28
|
+
export function createCofhesdkClientBase(opts: CofhesdkClientParams): CofhesdkClient {
|
|
29
|
+
// Create keysStorage instance using configured storage
|
|
30
|
+
const keysStorage = createKeysStore(opts.config.fheKeyStorage);
|
|
31
|
+
|
|
32
|
+
// refs captured in closure
|
|
33
|
+
let _publicClient: PublicClient | undefined = undefined;
|
|
34
|
+
let _walletClient: WalletClient | undefined = undefined;
|
|
35
|
+
|
|
36
|
+
// Zustand store for reactive state management
|
|
37
|
+
const connectStore = createStore<CofhesdkClientConnectionState>(() => ({
|
|
38
|
+
connected: false,
|
|
39
|
+
connecting: false,
|
|
40
|
+
connectError: undefined,
|
|
41
|
+
chainId: undefined,
|
|
42
|
+
account: undefined,
|
|
43
|
+
}));
|
|
44
|
+
|
|
45
|
+
// Helper to update state
|
|
46
|
+
const updateConnectState = (partial: Partial<CofhesdkClientConnectionState>) => {
|
|
47
|
+
connectStore.setState((state) => ({ ...state, ...partial }));
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
// single-flight + abortable warmup
|
|
51
|
+
let _connectPromise: Promise<Result<boolean>> | undefined = undefined;
|
|
52
|
+
|
|
53
|
+
// Called before any operation, throws of connection not yet established
|
|
54
|
+
const _requireConnected = () => {
|
|
55
|
+
const state = connectStore.getState();
|
|
56
|
+
const notConnected = !state.connected || !_publicClient || !_walletClient || !state.account || !state.chainId;
|
|
57
|
+
if (notConnected) {
|
|
58
|
+
throw new CofhesdkError({
|
|
59
|
+
code: CofhesdkErrorCode.NotConnected,
|
|
60
|
+
message: 'Client must be connected, account and chainId must be initialized',
|
|
61
|
+
hint: 'Ensure client.connect() has been called and awaited.',
|
|
62
|
+
context: {
|
|
63
|
+
connected: state.connected,
|
|
64
|
+
account: state.account,
|
|
65
|
+
chainId: state.chainId,
|
|
66
|
+
publicClient: _publicClient,
|
|
67
|
+
walletClient: _walletClient,
|
|
68
|
+
},
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
// INITIALIZATION
|
|
74
|
+
|
|
75
|
+
const keyFetchResult = resultWrapper(async () => {
|
|
76
|
+
// If configured, fetch keys for all supported chains
|
|
77
|
+
if (opts.config.fheKeysPrefetching === 'SUPPORTED_CHAINS') {
|
|
78
|
+
await fetchMultichainKeys(
|
|
79
|
+
opts.config,
|
|
80
|
+
0,
|
|
81
|
+
opts.tfhePublicKeyDeserializer,
|
|
82
|
+
opts.compactPkeCrsDeserializer,
|
|
83
|
+
keysStorage
|
|
84
|
+
);
|
|
85
|
+
return true;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return false;
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
// LIFECYCLE
|
|
92
|
+
|
|
93
|
+
async function connect(publicClient: PublicClient, walletClient: WalletClient) {
|
|
94
|
+
const state = connectStore.getState();
|
|
95
|
+
|
|
96
|
+
// Exit if already connected and clients are the same
|
|
97
|
+
if (state.connected && _publicClient === publicClient && _walletClient === walletClient) {
|
|
98
|
+
return Promise.resolve(ResultOk(true));
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Exit if already connecting
|
|
102
|
+
if (_connectPromise && _publicClient === publicClient && _walletClient === walletClient) {
|
|
103
|
+
return _connectPromise;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Set connecting state
|
|
107
|
+
updateConnectState({ connecting: true, connectError: null, connected: false });
|
|
108
|
+
|
|
109
|
+
_connectPromise = resultWrapper(
|
|
110
|
+
// try
|
|
111
|
+
async () => {
|
|
112
|
+
_publicClient = publicClient;
|
|
113
|
+
_walletClient = walletClient;
|
|
114
|
+
|
|
115
|
+
const chainId = await getPublicClientChainID(publicClient);
|
|
116
|
+
const account = await getWalletClientAccount(walletClient);
|
|
117
|
+
|
|
118
|
+
updateConnectState({ connecting: false, connected: true, chainId, account });
|
|
119
|
+
|
|
120
|
+
return true;
|
|
121
|
+
},
|
|
122
|
+
// catch
|
|
123
|
+
(e) => {
|
|
124
|
+
updateConnectState({ connecting: false, connected: false, connectError: e });
|
|
125
|
+
return false;
|
|
126
|
+
},
|
|
127
|
+
// finally
|
|
128
|
+
() => {
|
|
129
|
+
_connectPromise = undefined;
|
|
130
|
+
}
|
|
131
|
+
);
|
|
132
|
+
|
|
133
|
+
return _connectPromise;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// CLIENT OPERATIONS
|
|
137
|
+
|
|
138
|
+
function encryptInputs<T extends EncryptableItem[]>(inputs: [...T]): EncryptInputsBuilder<[...T]> {
|
|
139
|
+
const state = connectStore.getState();
|
|
140
|
+
|
|
141
|
+
return new EncryptInputsBuilder({
|
|
142
|
+
inputs,
|
|
143
|
+
account: state.account ?? undefined,
|
|
144
|
+
chainId: state.chainId ?? undefined,
|
|
145
|
+
|
|
146
|
+
config: opts.config,
|
|
147
|
+
publicClient: _publicClient ?? undefined,
|
|
148
|
+
walletClient: _walletClient ?? undefined,
|
|
149
|
+
zkvWalletClient: opts.config._internal?.zkvWalletClient,
|
|
150
|
+
|
|
151
|
+
tfhePublicKeyDeserializer: opts.tfhePublicKeyDeserializer,
|
|
152
|
+
compactPkeCrsDeserializer: opts.compactPkeCrsDeserializer,
|
|
153
|
+
zkBuilderAndCrsGenerator: opts.zkBuilderAndCrsGenerator,
|
|
154
|
+
initTfhe: opts.initTfhe,
|
|
155
|
+
|
|
156
|
+
keysStorage,
|
|
157
|
+
|
|
158
|
+
requireConnected: _requireConnected,
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
function decryptHandle<U extends FheTypes>(ctHash: bigint, utype: U): DecryptHandlesBuilder<U> {
|
|
163
|
+
const state = connectStore.getState();
|
|
164
|
+
|
|
165
|
+
return new DecryptHandlesBuilder({
|
|
166
|
+
ctHash,
|
|
167
|
+
utype,
|
|
168
|
+
chainId: state.chainId ?? undefined,
|
|
169
|
+
account: state.account ?? undefined,
|
|
170
|
+
|
|
171
|
+
config: opts.config,
|
|
172
|
+
publicClient: _publicClient ?? undefined,
|
|
173
|
+
walletClient: _walletClient ?? undefined,
|
|
174
|
+
|
|
175
|
+
requireConnected: _requireConnected,
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// PERMITS - Context-aware wrapper
|
|
180
|
+
|
|
181
|
+
const _getChainIdAndAccount = (chainId?: number, account?: string) => {
|
|
182
|
+
const state = connectStore.getState();
|
|
183
|
+
const _chainId = chainId ?? state.chainId;
|
|
184
|
+
const _account = account ?? state.account;
|
|
185
|
+
|
|
186
|
+
if (_chainId == null || _account == null) {
|
|
187
|
+
throw new CofhesdkError({
|
|
188
|
+
code: CofhesdkErrorCode.NotConnected,
|
|
189
|
+
message: 'ChainId or account not available.',
|
|
190
|
+
hint: 'Ensure client.connect() has been called, or provide chainId and account explicitly.',
|
|
191
|
+
context: {
|
|
192
|
+
chainId: _chainId,
|
|
193
|
+
account: _account,
|
|
194
|
+
},
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
return { chainId: _chainId, account: _account };
|
|
199
|
+
};
|
|
200
|
+
|
|
201
|
+
const clientPermits: CofhesdkClientPermits = {
|
|
202
|
+
// Pass through store access
|
|
203
|
+
getSnapshot: permits.getSnapshot,
|
|
204
|
+
subscribe: permits.subscribe,
|
|
205
|
+
|
|
206
|
+
// Creation methods (require connection)
|
|
207
|
+
createSelf: async (options: CreateSelfPermitOptions) =>
|
|
208
|
+
resultWrapper(async () => {
|
|
209
|
+
_requireConnected();
|
|
210
|
+
return permits.createSelf(options, _publicClient!, _walletClient!);
|
|
211
|
+
}),
|
|
212
|
+
|
|
213
|
+
createSharing: async (options: CreateSharingPermitOptions) =>
|
|
214
|
+
resultWrapper(async () => {
|
|
215
|
+
_requireConnected();
|
|
216
|
+
return permits.createSharing(options, _publicClient!, _walletClient!);
|
|
217
|
+
}),
|
|
218
|
+
|
|
219
|
+
importShared: async (options: ImportSharedPermitOptions | any | string) =>
|
|
220
|
+
resultWrapper(async () => {
|
|
221
|
+
_requireConnected();
|
|
222
|
+
return permits.importShared(options, _publicClient!, _walletClient!);
|
|
223
|
+
}),
|
|
224
|
+
|
|
225
|
+
// Retrieval methods (auto-fill chainId/account)
|
|
226
|
+
getPermit: async (hash: string, chainId?: number, account?: string) =>
|
|
227
|
+
resultWrapper(async () => {
|
|
228
|
+
const { chainId: _chainId, account: _account } = _getChainIdAndAccount(chainId, account);
|
|
229
|
+
return permits.getPermit(_chainId, _account, hash);
|
|
230
|
+
}),
|
|
231
|
+
|
|
232
|
+
getPermits: async (chainId?: number, account?: string) =>
|
|
233
|
+
resultWrapper(async () => {
|
|
234
|
+
const { chainId: _chainId, account: _account } = _getChainIdAndAccount(chainId, account);
|
|
235
|
+
return permits.getPermits(_chainId, _account);
|
|
236
|
+
}),
|
|
237
|
+
|
|
238
|
+
getActivePermit: async (chainId?: number, account?: string) =>
|
|
239
|
+
resultWrapper(async () => {
|
|
240
|
+
const { chainId: _chainId, account: _account } = _getChainIdAndAccount(chainId, account);
|
|
241
|
+
return permits.getActivePermit(_chainId, _account);
|
|
242
|
+
}),
|
|
243
|
+
|
|
244
|
+
getActivePermitHash: async (chainId?: number, account?: string) =>
|
|
245
|
+
resultWrapper(async () => {
|
|
246
|
+
const { chainId: _chainId, account: _account } = _getChainIdAndAccount(chainId, account);
|
|
247
|
+
return permits.getActivePermitHash(_chainId, _account);
|
|
248
|
+
}),
|
|
249
|
+
|
|
250
|
+
// Mutation methods (auto-fill chainId/account)
|
|
251
|
+
selectActivePermit: async (hash: string, chainId?: number, account?: string) =>
|
|
252
|
+
resultWrapper(async () => {
|
|
253
|
+
const { chainId: _chainId, account: _account } = _getChainIdAndAccount(chainId, account);
|
|
254
|
+
return permits.selectActivePermit(_chainId, _account, hash);
|
|
255
|
+
}),
|
|
256
|
+
|
|
257
|
+
removePermit: async (hash: string, chainId?: number, account?: string) =>
|
|
258
|
+
resultWrapper(async () => {
|
|
259
|
+
const { chainId: _chainId, account: _account } = _getChainIdAndAccount(chainId, account);
|
|
260
|
+
return permits.removePermit(_chainId, _account, hash);
|
|
261
|
+
}),
|
|
262
|
+
|
|
263
|
+
removeActivePermit: async (chainId?: number, account?: string) =>
|
|
264
|
+
resultWrapper(async () => {
|
|
265
|
+
const { chainId: _chainId, account: _account } = _getChainIdAndAccount(chainId, account);
|
|
266
|
+
return permits.removeActivePermit(_chainId, _account);
|
|
267
|
+
}),
|
|
268
|
+
|
|
269
|
+
// Utils (no context needed)
|
|
270
|
+
getHash: permits.getHash,
|
|
271
|
+
serialize: permits.serialize,
|
|
272
|
+
deserialize: permits.deserialize,
|
|
273
|
+
};
|
|
274
|
+
|
|
275
|
+
return {
|
|
276
|
+
// Zustand reactive accessors (don't export store directly to prevent mutation)
|
|
277
|
+
getSnapshot: connectStore.getState,
|
|
278
|
+
subscribe: connectStore.subscribe,
|
|
279
|
+
|
|
280
|
+
// initialization results
|
|
281
|
+
initializationResults: {
|
|
282
|
+
keyFetchResult,
|
|
283
|
+
},
|
|
284
|
+
|
|
285
|
+
// flags (read-only: reflect snapshot)
|
|
286
|
+
get connected() {
|
|
287
|
+
return connectStore.getState().connected;
|
|
288
|
+
},
|
|
289
|
+
get connecting() {
|
|
290
|
+
return connectStore.getState().connecting;
|
|
291
|
+
},
|
|
292
|
+
|
|
293
|
+
// config & platform-specific (read-only)
|
|
294
|
+
config: opts.config,
|
|
295
|
+
|
|
296
|
+
connect,
|
|
297
|
+
encryptInputs,
|
|
298
|
+
decryptHandle,
|
|
299
|
+
permits: clientPermits,
|
|
300
|
+
|
|
301
|
+
// Add SDK-specific methods below that require connection
|
|
302
|
+
// Example:
|
|
303
|
+
// async encryptData(data: unknown) {
|
|
304
|
+
// requireConnected();
|
|
305
|
+
// // Use _publicClient and _walletClient for implementation
|
|
306
|
+
// },
|
|
307
|
+
};
|
|
308
|
+
}
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
/* eslint-disable no-unused-vars */
|
|
2
|
+
import { sepolia, hardhat } from '@/chains';
|
|
3
|
+
|
|
4
|
+
import { describe, it, expect, vi } from 'vitest';
|
|
5
|
+
import {
|
|
6
|
+
createCofhesdkConfigBase,
|
|
7
|
+
getCofhesdkConfigItem,
|
|
8
|
+
type CofhesdkInputConfig,
|
|
9
|
+
getSupportedChainOrThrow,
|
|
10
|
+
getCoFheUrlOrThrow,
|
|
11
|
+
getZkVerifierUrlOrThrow,
|
|
12
|
+
getThresholdNetworkUrlOrThrow,
|
|
13
|
+
} from './config.js';
|
|
14
|
+
|
|
15
|
+
describe('createCofhesdkConfigBase', () => {
|
|
16
|
+
const validBaseConfig: CofhesdkInputConfig = {
|
|
17
|
+
supportedChains: [],
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const setNestedValue = (obj: any, path: string, value: any): void => {
|
|
21
|
+
const keys = path.split('.');
|
|
22
|
+
const lastKey = keys.pop()!;
|
|
23
|
+
const target = keys.reduce((acc, key) => {
|
|
24
|
+
if (!acc[key]) acc[key] = {};
|
|
25
|
+
return acc[key];
|
|
26
|
+
}, obj);
|
|
27
|
+
target[lastKey] = value;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
const getNestedValue = (obj: any, path: string): any => {
|
|
31
|
+
return path.split('.').reduce((acc, key) => acc?.[key], obj);
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
const expectInvalidConfigItem = (path: string, value: any, log = false): void => {
|
|
35
|
+
const config = { ...validBaseConfig };
|
|
36
|
+
setNestedValue(config, path, value);
|
|
37
|
+
if (log) {
|
|
38
|
+
console.log('expect config invalid', path, value, config);
|
|
39
|
+
try {
|
|
40
|
+
createCofhesdkConfigBase(config as CofhesdkInputConfig);
|
|
41
|
+
} catch (e) {
|
|
42
|
+
console.log('expect config invalid', path, value, config, e);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
expect(() => createCofhesdkConfigBase(config as CofhesdkInputConfig)).toThrow('Invalid cofhesdk configuration:');
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
const expectValidConfigItem = (path: string, value: any, expectedValue: any): void => {
|
|
49
|
+
const config = { ...validBaseConfig };
|
|
50
|
+
setNestedValue(config, path, value);
|
|
51
|
+
const result = createCofhesdkConfigBase(config);
|
|
52
|
+
expect(getNestedValue(result, path)).toEqual(expectedValue);
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
it('supportedChains', () => {
|
|
56
|
+
expectInvalidConfigItem('supportedChains', {});
|
|
57
|
+
expectInvalidConfigItem('supportedChains', 'not-an-array');
|
|
58
|
+
expectInvalidConfigItem('supportedChains', null);
|
|
59
|
+
expectInvalidConfigItem('supportedChains', undefined);
|
|
60
|
+
|
|
61
|
+
expectValidConfigItem('supportedChains', [sepolia], [sepolia]);
|
|
62
|
+
expectValidConfigItem('supportedChains', [sepolia, hardhat], [sepolia, hardhat]);
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it('fheKeysPrefetching', () => {
|
|
66
|
+
expectInvalidConfigItem('fheKeysPrefetching', 'invalid-option');
|
|
67
|
+
expectInvalidConfigItem('fheKeysPrefetching', 5);
|
|
68
|
+
|
|
69
|
+
expectValidConfigItem('fheKeysPrefetching', 'CONNECTED_CHAIN', 'CONNECTED_CHAIN');
|
|
70
|
+
expectValidConfigItem('fheKeysPrefetching', 'SUPPORTED_CHAINS', 'SUPPORTED_CHAINS');
|
|
71
|
+
expectValidConfigItem('fheKeysPrefetching', 'OFF', 'OFF');
|
|
72
|
+
expectValidConfigItem('fheKeysPrefetching', undefined, 'OFF');
|
|
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('should get config item', () => {
|
|
148
|
+
const config: CofhesdkInputConfig = {
|
|
149
|
+
supportedChains: [sepolia],
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
const result = createCofhesdkConfigBase(config);
|
|
153
|
+
|
|
154
|
+
const supportedChains = getCofhesdkConfigItem(result, 'supportedChains');
|
|
155
|
+
expect(supportedChains).toEqual(config.supportedChains);
|
|
156
|
+
});
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
describe('Config helper functions', () => {
|
|
160
|
+
const config = createCofhesdkConfigBase({
|
|
161
|
+
supportedChains: [sepolia, hardhat],
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
describe('getSupportedChainOrThrow', () => {
|
|
165
|
+
it('should return chain when found', () => {
|
|
166
|
+
expect(getSupportedChainOrThrow(config, sepolia.id)).toEqual(sepolia);
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
it('should throw UnsupportedChain error when not found', () => {
|
|
170
|
+
expect(() => getSupportedChainOrThrow(config, 999999)).toThrow();
|
|
171
|
+
});
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
describe('getCoFheUrlOrThrow', () => {
|
|
175
|
+
it('should return coFheUrl', () => {
|
|
176
|
+
expect(getCoFheUrlOrThrow(config, sepolia.id)).toBe(sepolia.coFheUrl);
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
it('should throw when chain not found', () => {
|
|
180
|
+
expect(() => getCoFheUrlOrThrow(config, 999999)).toThrow();
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
it('should throw MissingConfig when url not set', () => {
|
|
184
|
+
const configWithoutUrl = createCofhesdkConfigBase({
|
|
185
|
+
supportedChains: [{ ...sepolia, coFheUrl: undefined } as any],
|
|
186
|
+
});
|
|
187
|
+
expect(() => getCoFheUrlOrThrow(configWithoutUrl, sepolia.id)).toThrow();
|
|
188
|
+
});
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
describe('getZkVerifierUrlOrThrow', () => {
|
|
192
|
+
it('should return verifierUrl', () => {
|
|
193
|
+
expect(getZkVerifierUrlOrThrow(config, sepolia.id)).toBe(sepolia.verifierUrl);
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
it('should throw when chain not found', () => {
|
|
197
|
+
expect(() => getZkVerifierUrlOrThrow(config, 999999)).toThrow();
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
it('should throw ZkVerifierUrlUninitialized when url not set', () => {
|
|
201
|
+
const configWithoutUrl = createCofhesdkConfigBase({
|
|
202
|
+
supportedChains: [{ ...sepolia, verifierUrl: undefined } as any],
|
|
203
|
+
});
|
|
204
|
+
expect(() => getZkVerifierUrlOrThrow(configWithoutUrl, sepolia.id)).toThrow();
|
|
205
|
+
});
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
describe('getThresholdNetworkUrlOrThrow', () => {
|
|
209
|
+
it('should return thresholdNetworkUrl', () => {
|
|
210
|
+
expect(getThresholdNetworkUrlOrThrow(config, sepolia.id)).toBe(sepolia.thresholdNetworkUrl);
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
it('should throw when chain not found', () => {
|
|
214
|
+
expect(() => getThresholdNetworkUrlOrThrow(config, 999999)).toThrow();
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
it('should throw ThresholdNetworkUrlUninitialized when url not set', () => {
|
|
218
|
+
const configWithoutUrl = createCofhesdkConfigBase({
|
|
219
|
+
supportedChains: [{ ...sepolia, thresholdNetworkUrl: undefined } as any],
|
|
220
|
+
});
|
|
221
|
+
expect(() => getThresholdNetworkUrlOrThrow(configWithoutUrl, sepolia.id)).toThrow();
|
|
222
|
+
});
|
|
223
|
+
});
|
|
224
|
+
});
|