@cofhe/sdk 0.0.0-alpha-20260409113701

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.
Files changed (132) hide show
  1. package/CHANGELOG.md +146 -0
  2. package/adapters/ethers5.test.ts +174 -0
  3. package/adapters/ethers5.ts +36 -0
  4. package/adapters/ethers6.test.ts +169 -0
  5. package/adapters/ethers6.ts +36 -0
  6. package/adapters/hardhat-node.ts +167 -0
  7. package/adapters/hardhat.hh2.test.ts +159 -0
  8. package/adapters/hardhat.ts +36 -0
  9. package/adapters/index.test.ts +20 -0
  10. package/adapters/index.ts +5 -0
  11. package/adapters/smartWallet.ts +99 -0
  12. package/adapters/test-utils.ts +53 -0
  13. package/adapters/types.ts +6 -0
  14. package/adapters/wagmi.test.ts +156 -0
  15. package/adapters/wagmi.ts +17 -0
  16. package/chains/chains/arbSepolia.ts +14 -0
  17. package/chains/chains/baseSepolia.ts +14 -0
  18. package/chains/chains/hardhat.ts +15 -0
  19. package/chains/chains/localcofhe.ts +14 -0
  20. package/chains/chains/sepolia.ts +14 -0
  21. package/chains/chains.test.ts +50 -0
  22. package/chains/defineChain.ts +18 -0
  23. package/chains/index.ts +35 -0
  24. package/chains/types.ts +32 -0
  25. package/core/baseBuilder.ts +119 -0
  26. package/core/client.test.ts +429 -0
  27. package/core/client.ts +341 -0
  28. package/core/clientTypes.ts +119 -0
  29. package/core/config.test.ts +242 -0
  30. package/core/config.ts +225 -0
  31. package/core/consts.ts +22 -0
  32. package/core/decrypt/MockThresholdNetworkAbi.ts +179 -0
  33. package/core/decrypt/cofheMocksDecryptForTx.ts +84 -0
  34. package/core/decrypt/cofheMocksDecryptForView.ts +48 -0
  35. package/core/decrypt/decryptForTxBuilder.ts +359 -0
  36. package/core/decrypt/decryptForViewBuilder.ts +332 -0
  37. package/core/decrypt/decryptUtils.ts +28 -0
  38. package/core/decrypt/pollCallbacks.test.ts +194 -0
  39. package/core/decrypt/polling.ts +14 -0
  40. package/core/decrypt/tnDecryptUtils.ts +65 -0
  41. package/core/decrypt/tnDecryptV1.ts +171 -0
  42. package/core/decrypt/tnDecryptV2.ts +365 -0
  43. package/core/decrypt/tnSealOutputV1.ts +59 -0
  44. package/core/decrypt/tnSealOutputV2.ts +324 -0
  45. package/core/decrypt/verifyDecryptResult.ts +52 -0
  46. package/core/encrypt/MockZkVerifierAbi.ts +106 -0
  47. package/core/encrypt/cofheMocksZkVerifySign.ts +281 -0
  48. package/core/encrypt/encryptInputsBuilder.test.ts +747 -0
  49. package/core/encrypt/encryptInputsBuilder.ts +583 -0
  50. package/core/encrypt/encryptUtils.ts +67 -0
  51. package/core/encrypt/zkPackProveVerify.ts +335 -0
  52. package/core/error.ts +168 -0
  53. package/core/fetchKeys.test.ts +195 -0
  54. package/core/fetchKeys.ts +144 -0
  55. package/core/index.ts +106 -0
  56. package/core/keyStore.test.ts +226 -0
  57. package/core/keyStore.ts +154 -0
  58. package/core/permits.test.ts +493 -0
  59. package/core/permits.ts +201 -0
  60. package/core/types.ts +419 -0
  61. package/core/utils.ts +130 -0
  62. package/dist/adapters.cjs +88 -0
  63. package/dist/adapters.d.cts +14576 -0
  64. package/dist/adapters.d.ts +14576 -0
  65. package/dist/adapters.js +83 -0
  66. package/dist/chains.cjs +111 -0
  67. package/dist/chains.d.cts +121 -0
  68. package/dist/chains.d.ts +121 -0
  69. package/dist/chains.js +1 -0
  70. package/dist/chunk-36FBWLUS.js +3310 -0
  71. package/dist/chunk-7HLGHV67.js +990 -0
  72. package/dist/chunk-TBLR7NNE.js +102 -0
  73. package/dist/clientTypes-AVSCBet7.d.cts +998 -0
  74. package/dist/clientTypes-flH1ju82.d.ts +998 -0
  75. package/dist/core.cjs +4362 -0
  76. package/dist/core.d.cts +138 -0
  77. package/dist/core.d.ts +138 -0
  78. package/dist/core.js +3 -0
  79. package/dist/node.cjs +4225 -0
  80. package/dist/node.d.cts +22 -0
  81. package/dist/node.d.ts +22 -0
  82. package/dist/node.js +91 -0
  83. package/dist/permit-jRirYqFt.d.cts +376 -0
  84. package/dist/permit-jRirYqFt.d.ts +376 -0
  85. package/dist/permits.cjs +1025 -0
  86. package/dist/permits.d.cts +353 -0
  87. package/dist/permits.d.ts +353 -0
  88. package/dist/permits.js +1 -0
  89. package/dist/types-YiAC4gig.d.cts +33 -0
  90. package/dist/types-YiAC4gig.d.ts +33 -0
  91. package/dist/web.cjs +4434 -0
  92. package/dist/web.d.cts +42 -0
  93. package/dist/web.d.ts +42 -0
  94. package/dist/web.js +256 -0
  95. package/dist/zkProve.worker.cjs +93 -0
  96. package/dist/zkProve.worker.d.cts +2 -0
  97. package/dist/zkProve.worker.d.ts +2 -0
  98. package/dist/zkProve.worker.js +91 -0
  99. package/node/client.test.ts +159 -0
  100. package/node/config.test.ts +68 -0
  101. package/node/encryptInputs.test.ts +155 -0
  102. package/node/index.ts +97 -0
  103. package/node/storage.ts +51 -0
  104. package/package.json +121 -0
  105. package/permits/index.ts +68 -0
  106. package/permits/localstorage.test.ts +113 -0
  107. package/permits/onchain-utils.ts +221 -0
  108. package/permits/permit.test.ts +534 -0
  109. package/permits/permit.ts +386 -0
  110. package/permits/sealing.test.ts +84 -0
  111. package/permits/sealing.ts +131 -0
  112. package/permits/signature.ts +79 -0
  113. package/permits/store.test.ts +88 -0
  114. package/permits/store.ts +156 -0
  115. package/permits/test-utils.ts +28 -0
  116. package/permits/types.ts +204 -0
  117. package/permits/utils.ts +58 -0
  118. package/permits/validation.test.ts +361 -0
  119. package/permits/validation.ts +327 -0
  120. package/web/client.web.test.ts +159 -0
  121. package/web/config.web.test.ts +69 -0
  122. package/web/const.ts +2 -0
  123. package/web/encryptInputs.web.test.ts +172 -0
  124. package/web/index.ts +166 -0
  125. package/web/storage.ts +49 -0
  126. package/web/worker.builder.web.test.ts +148 -0
  127. package/web/worker.config.web.test.ts +329 -0
  128. package/web/worker.output.web.test.ts +84 -0
  129. package/web/workerManager.test.ts +80 -0
  130. package/web/workerManager.ts +214 -0
  131. package/web/workerManager.web.test.ts +114 -0
  132. package/web/zkProve.worker.ts +133 -0
@@ -0,0 +1,68 @@
1
+ import { arbSepolia } from '@/chains';
2
+
3
+ import { describe, it, expect } from 'vitest';
4
+ import { createCofheConfig, createCofheClient } from './index.js';
5
+
6
+ describe('@cofhe/node - Config', () => {
7
+ describe('createCofheConfig', () => {
8
+ it('should automatically inject filesystem storage as default', () => {
9
+ const config = createCofheConfig({
10
+ supportedChains: [arbSepolia],
11
+ });
12
+
13
+ expect(config.fheKeyStorage).toBeDefined();
14
+ expect(config.fheKeyStorage).not.toBeNull();
15
+ expect(config.supportedChains).toEqual([arbSepolia]);
16
+ });
17
+
18
+ it('should allow overriding storage', async () => {
19
+ const customStorage = {
20
+ getItem: () => Promise.resolve(10),
21
+ setItem: () => Promise.resolve(),
22
+ removeItem: () => Promise.resolve(),
23
+ };
24
+ const config = createCofheConfig({
25
+ supportedChains: [arbSepolia],
26
+ fheKeyStorage: customStorage,
27
+ });
28
+
29
+ expect(await config.fheKeyStorage!.getItem('test')).toBe(10);
30
+ });
31
+
32
+ it('should allow null storage', () => {
33
+ const config = createCofheConfig({
34
+ supportedChains: [arbSepolia],
35
+ fheKeyStorage: null,
36
+ });
37
+
38
+ expect(config.fheKeyStorage).toBeNull();
39
+ });
40
+
41
+ it('should preserve all other config options', () => {
42
+ const config = createCofheConfig({
43
+ supportedChains: [arbSepolia],
44
+ mocks: {
45
+ decryptDelay: 0,
46
+ },
47
+ });
48
+
49
+ expect(config.supportedChains).toEqual([arbSepolia]);
50
+ expect(config.mocks.decryptDelay).toBe(0);
51
+ expect(config.fheKeyStorage).toBeDefined();
52
+ });
53
+ });
54
+
55
+ describe('createCofheClient with config', () => {
56
+ it('should create client with validated config', () => {
57
+ const config = createCofheConfig({
58
+ supportedChains: [arbSepolia],
59
+ });
60
+
61
+ const client = createCofheClient(config);
62
+
63
+ expect(client).toBeDefined();
64
+ expect(client.config).toBe(config);
65
+ expect(client.config.fheKeyStorage).toBeDefined();
66
+ });
67
+ });
68
+ });
@@ -0,0 +1,155 @@
1
+ import { Encryptable, FheTypes, type CofheClient, CofheErrorCode, CofheError } from '@/core';
2
+ import { arbSepolia as cofheArbSepolia } from '@/chains';
3
+
4
+ import { describe, it, expect, beforeAll, beforeEach } from 'vitest';
5
+ import type { PublicClient, WalletClient } from 'viem';
6
+ import { createPublicClient, createWalletClient, http } from 'viem';
7
+ import { privateKeyToAccount } from 'viem/accounts';
8
+ import { arbitrumSepolia as viemArbitrumSepolia } from 'viem/chains';
9
+ import { createCofheClient, createCofheConfig } from './index.js';
10
+
11
+ // Real test setup - using actual node-tfhe
12
+ const TEST_PRIVATE_KEY = '0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80';
13
+
14
+ describe('@cofhe/node - Encrypt Inputs', () => {
15
+ let cofheClient: CofheClient;
16
+ let publicClient: PublicClient;
17
+ let walletClient: WalletClient;
18
+
19
+ beforeAll(() => {
20
+ // Create real viem clients
21
+ publicClient = createPublicClient({
22
+ chain: viemArbitrumSepolia,
23
+ transport: http(),
24
+ });
25
+
26
+ const account = privateKeyToAccount(TEST_PRIVATE_KEY);
27
+ walletClient = createWalletClient({
28
+ chain: viemArbitrumSepolia,
29
+ transport: http(),
30
+ account,
31
+ });
32
+ });
33
+
34
+ beforeEach(() => {
35
+ const config = createCofheConfig({
36
+ supportedChains: [cofheArbSepolia],
37
+ });
38
+ cofheClient = createCofheClient(config);
39
+ });
40
+
41
+ describe('Real TFHE Initialization', () => {
42
+ it('should initialize node-tfhe on first encryption', async () => {
43
+ await cofheClient.connect(publicClient, walletClient);
44
+
45
+ // This will trigger real TFHE initialization
46
+ const encrypted = await cofheClient.encryptInputs([Encryptable.uint128(100n)]).execute();
47
+
48
+ // If we get here, TFHE was initialized successfully
49
+ expect(encrypted).toBeDefined();
50
+ }, 60000); // Longer timeout for real operations
51
+
52
+ it('should handle multiple encryptions without re-initializing', async () => {
53
+ await cofheClient.connect(publicClient, walletClient);
54
+
55
+ // First encryption
56
+ await cofheClient.encryptInputs([Encryptable.uint128(100n)]).execute();
57
+
58
+ // Second encryption should reuse initialization
59
+ await cofheClient.encryptInputs([Encryptable.uint64(50n)]).execute();
60
+ }, 120000);
61
+ });
62
+
63
+ describe('Real Encryption', () => {
64
+ it('should encrypt a bool with real TFHE', async () => {
65
+ await cofheClient.connect(publicClient, walletClient);
66
+
67
+ const encrypted = await cofheClient.encryptInputs([Encryptable.bool(true)]).execute();
68
+
69
+ expect(encrypted.length).toBe(1);
70
+ expect(encrypted[0].utype).toBe(FheTypes.Bool);
71
+ expect(encrypted[0].ctHash).toBeDefined();
72
+ expect(typeof encrypted[0].ctHash).toBe('bigint');
73
+ expect(encrypted[0].signature).toBeDefined();
74
+ expect(typeof encrypted[0].signature).toBe('string');
75
+ expect(encrypted[0].securityZone).toBe(0);
76
+ }, 60000);
77
+
78
+ it('should encrypt all supported types together', async () => {
79
+ await cofheClient.connect(publicClient, walletClient);
80
+
81
+ const inputs = [
82
+ Encryptable.bool(false),
83
+ Encryptable.uint8(1n),
84
+ Encryptable.uint16(2n),
85
+ Encryptable.uint32(3n),
86
+ Encryptable.uint64(4n),
87
+ Encryptable.uint128(5n),
88
+ Encryptable.address('0x742d35Cc6634C0532925a3b844D16faC4c175E99'),
89
+ ];
90
+
91
+ const encrypted = await cofheClient.encryptInputs(inputs).execute();
92
+
93
+ expect(encrypted.length).toBe(7);
94
+ // Verify each type
95
+ expect(encrypted[0].utype).toBe(FheTypes.Bool);
96
+ expect(encrypted[1].utype).toBe(FheTypes.Uint8);
97
+ expect(encrypted[2].utype).toBe(FheTypes.Uint16);
98
+ expect(encrypted[3].utype).toBe(FheTypes.Uint32);
99
+ expect(encrypted[4].utype).toBe(FheTypes.Uint64);
100
+ expect(encrypted[5].utype).toBe(FheTypes.Uint128);
101
+ expect(encrypted[6].utype).toBe(FheTypes.Uint160);
102
+ }, 90000); // Longer timeout for multiple encryptions
103
+ });
104
+
105
+ describe('Real Builder Pattern', () => {
106
+ it('should support chaining builder methods with real encryption', async () => {
107
+ await cofheClient.connect(publicClient, walletClient);
108
+
109
+ const snapshot = cofheClient.getSnapshot();
110
+ const encrypted = await cofheClient
111
+ .encryptInputs([Encryptable.uint128(100n)])
112
+ .setChainId(snapshot.chainId!)
113
+ .setAccount(snapshot.account!)
114
+ .setSecurityZone(0)
115
+ .execute();
116
+
117
+ expect(encrypted.length).toBe(1);
118
+ expect(encrypted[0].utype).toBe(FheTypes.Uint128);
119
+ }, 60000);
120
+ });
121
+
122
+ describe('Real Error Handling', () => {
123
+ it('should fail gracefully when not connected', async () => {
124
+ // Don't connect the client
125
+ try {
126
+ await cofheClient.encryptInputs([Encryptable.uint128(100n)]).execute();
127
+ } catch (error) {
128
+ expect(error).toBeInstanceOf(CofheError);
129
+ expect((error as CofheError).code).toBe(CofheErrorCode.NotConnected);
130
+ }
131
+ }, 30000);
132
+
133
+ it('should handle invalid CoFHE URL', async () => {
134
+ const badConfig = createCofheConfig({
135
+ supportedChains: [
136
+ {
137
+ ...cofheArbSepolia,
138
+ coFheUrl: 'http://invalid-cofhe-url.local',
139
+ verifierUrl: 'http://invalid-verifier-url.local',
140
+ },
141
+ ],
142
+ });
143
+
144
+ const badClient = createCofheClient(badConfig);
145
+ await badClient.connect(publicClient, walletClient);
146
+
147
+ try {
148
+ await badClient.encryptInputs([Encryptable.uint128(100n)]).execute();
149
+ } catch (error) {
150
+ expect(error).toBeInstanceOf(CofheError);
151
+ expect((error as CofheError).code).toBe(CofheErrorCode.ZkVerifyFailed);
152
+ }
153
+ }, 60000);
154
+ });
155
+ });
package/node/index.ts ADDED
@@ -0,0 +1,97 @@
1
+ // Node.js specific functionality only
2
+
3
+ import {
4
+ createCofheClientBase,
5
+ createCofheConfigBase,
6
+ type CofheClient,
7
+ type CofheConfig,
8
+ type CofheInputConfig,
9
+ type ZkBuilderAndCrsGenerator,
10
+ type FheKeyDeserializer,
11
+ } from '@/core';
12
+
13
+ // Import node-specific storage (internal use only)
14
+ import { createNodeStorage } from './storage.js';
15
+
16
+ // Import node-tfhe for Node.js
17
+ import { TfheCompactPublicKey, ProvenCompactCiphertextList, CompactPkeCrs, init_panic_hook } from 'node-tfhe';
18
+
19
+ /**
20
+ * Internal function to initialize TFHE for Node.js
21
+ * Called automatically on first encryption - users don't need to call this manually
22
+ * @returns true if TFHE was initialized, false if already initialized
23
+ */
24
+ let tfheInitialized = false;
25
+ async function initTfhe(): Promise<boolean> {
26
+ if (tfheInitialized) return false;
27
+ await init_panic_hook();
28
+ tfheInitialized = true;
29
+ return true;
30
+ }
31
+
32
+ /**
33
+ * Utility to convert the hex string key to a Uint8Array for use with tfhe
34
+ */
35
+ const fromHexString = (hexString: string): Uint8Array => {
36
+ const cleanString = hexString.length % 2 === 1 ? `0${hexString}` : hexString;
37
+ const arr = cleanString.replace(/^0x/, '').match(/.{1,2}/g);
38
+ if (!arr) return new Uint8Array();
39
+ return new Uint8Array(arr.map((byte) => parseInt(byte, 16)));
40
+ };
41
+
42
+ /**
43
+ * Serializer for TFHE public keys
44
+ * Validates that the buffer can be deserialized into a TfheCompactPublicKey
45
+ */
46
+ const tfhePublicKeyDeserializer: FheKeyDeserializer = (buff: string): void => {
47
+ TfheCompactPublicKey.deserialize(fromHexString(buff));
48
+ };
49
+
50
+ /**
51
+ * Serializer for Compact PKE CRS
52
+ * Validates that the buffer can be deserialized into ZkCompactPkePublicParams
53
+ */
54
+ const compactPkeCrsDeserializer: FheKeyDeserializer = (buff: string): void => {
55
+ CompactPkeCrs.deserialize(fromHexString(buff));
56
+ };
57
+
58
+ /**
59
+ * Creates a ZK builder and CRS from FHE public key and CRS buffers
60
+ * This is used internally by the SDK to create encrypted inputs
61
+ */
62
+ const zkBuilderAndCrsGenerator: ZkBuilderAndCrsGenerator = (fhe: string, crs: string) => {
63
+ const fhePublicKey = TfheCompactPublicKey.deserialize(fromHexString(fhe));
64
+ const zkBuilder = ProvenCompactCiphertextList.builder(fhePublicKey);
65
+ const zkCrs = CompactPkeCrs.deserialize(fromHexString(crs));
66
+
67
+ return { zkBuilder, zkCrs };
68
+ };
69
+
70
+ /**
71
+ * Creates a CoFHE configuration for Node.js with filesystem storage as default
72
+ * @param config - The CoFHE input configuration (fheKeyStorage will default to filesystem if not provided)
73
+ * @returns The CoFHE configuration with Node.js defaults applied
74
+ */
75
+ export function createCofheConfig(config: CofheInputConfig): CofheConfig {
76
+ return createCofheConfigBase({
77
+ environment: 'node',
78
+ ...config,
79
+ fheKeyStorage: config.fheKeyStorage === null ? null : config.fheKeyStorage ?? createNodeStorage(),
80
+ });
81
+ }
82
+
83
+ /**
84
+ * Creates a CoFHE client instance for Node.js with node-tfhe automatically configured
85
+ * TFHE will be initialized automatically on first encryption - no manual setup required
86
+ * @param config - The CoFHE configuration (use createCofheConfig to create with Node.js defaults)
87
+ * @returns The CoFHE client instance
88
+ */
89
+ export function createCofheClient(config: CofheConfig): CofheClient {
90
+ return createCofheClientBase({
91
+ config,
92
+ zkBuilderAndCrsGenerator,
93
+ tfhePublicKeyDeserializer,
94
+ compactPkeCrsDeserializer,
95
+ initTfhe,
96
+ });
97
+ }
@@ -0,0 +1,51 @@
1
+ /* eslint-disable turbo/no-undeclared-env-vars */
2
+
3
+ import type { IStorage } from '@/core';
4
+
5
+ import { promises as fs } from 'fs';
6
+ import { join } from 'path';
7
+
8
+ // Memory storage fallback
9
+ const memoryStorage: Record<string, string> = {};
10
+
11
+ /**
12
+ * Creates a node storage implementation using the filesystem
13
+ * @returns IStorage implementation for Node.js environments
14
+ */
15
+ export const createNodeStorage = (): IStorage => {
16
+ return {
17
+ getItem: async (name: string) => {
18
+ try {
19
+ const storageDir = join(process.env.HOME || process.env.USERPROFILE || '.', '.cofhesdk');
20
+ await fs.mkdir(storageDir, { recursive: true });
21
+ const filePath = join(storageDir, `${name}.json`);
22
+ const data = await fs.readFile(filePath, 'utf8').catch(() => null);
23
+ return data ? JSON.parse(data) : null;
24
+ } catch (e) {
25
+ console.warn('Node.js filesystem modules not available, falling back to memory storage' + e);
26
+ return memoryStorage[name] || null;
27
+ }
28
+ },
29
+ setItem: async (name: string, value: any) => {
30
+ try {
31
+ const storageDir = join(process.env.HOME || process.env.USERPROFILE || '.', '.cofhesdk');
32
+ await fs.mkdir(storageDir, { recursive: true });
33
+ const filePath = join(storageDir, `${name}.json`);
34
+ await fs.writeFile(filePath, JSON.stringify(value));
35
+ } catch (e) {
36
+ console.warn('Node.js filesystem modules not available, falling back to memory storage' + e);
37
+ memoryStorage[name] = JSON.stringify(value);
38
+ }
39
+ },
40
+ removeItem: async (name: string) => {
41
+ try {
42
+ const storageDir = join(process.env.HOME || process.env.USERPROFILE || '.', '.cofhesdk');
43
+ const filePath = join(storageDir, `${name}.json`);
44
+ await fs.unlink(filePath).catch(() => {});
45
+ } catch (e) {
46
+ console.warn('Node.js filesystem modules not available, falling back to memory storage' + e);
47
+ delete memoryStorage[name];
48
+ }
49
+ },
50
+ };
51
+ };
package/package.json ADDED
@@ -0,0 +1,121 @@
1
+ {
2
+ "name": "@cofhe/sdk",
3
+ "version": "0.0.0-alpha-20260409113701",
4
+ "type": "module",
5
+ "description": "SDK for Fhenix COFHE coprocessor interaction",
6
+ "main": "./dist/core.cjs",
7
+ "module": "./dist/core.js",
8
+ "types": "./dist/core.d.ts",
9
+ "browser": "./dist/web.js",
10
+ "exports": {
11
+ ".": {
12
+ "import": "./dist/core.js",
13
+ "require": "./dist/core.cjs",
14
+ "types": "./dist/core.d.ts"
15
+ },
16
+ "./adapters": {
17
+ "import": "./dist/adapters.js",
18
+ "require": "./dist/adapters.cjs",
19
+ "types": "./dist/adapters.d.ts"
20
+ },
21
+ "./chains": {
22
+ "import": "./dist/chains.js",
23
+ "require": "./dist/chains.cjs",
24
+ "types": "./dist/chains.d.ts"
25
+ },
26
+ "./permits": {
27
+ "import": "./dist/permits.js",
28
+ "require": "./dist/permits.cjs",
29
+ "types": "./dist/permits.d.ts"
30
+ },
31
+ "./node": {
32
+ "import": "./dist/node.js",
33
+ "require": "./dist/node.cjs",
34
+ "types": "./dist/node.d.ts"
35
+ },
36
+ "./web": {
37
+ "import": "./dist/web.js",
38
+ "require": "./dist/web.cjs",
39
+ "types": "./dist/web.d.ts"
40
+ }
41
+ },
42
+ "sideEffects": false,
43
+ "license": "MIT",
44
+ "repository": {
45
+ "type": "git",
46
+ "url": "https://github.com/FhenixProtocol/cofhesdk.git",
47
+ "directory": "packages/sdk"
48
+ },
49
+ "files": [
50
+ "dist/**",
51
+ "core/**",
52
+ "adapters/**",
53
+ "chains/**",
54
+ "permits/**",
55
+ "node/**",
56
+ "web/**",
57
+ "CHANGELOG.md"
58
+ ],
59
+ "dependencies": {
60
+ "iframe-shared-storage": "^1.0.34",
61
+ "immer": "^10.1.1",
62
+ "node-tfhe": "0.11.1",
63
+ "tfhe": "0.11.1",
64
+ "tweetnacl": "^1.0.3",
65
+ "viem": "^2.38.6",
66
+ "zod": "^4.0.0",
67
+ "zustand": "^5.0.1"
68
+ },
69
+ "peerDependencies": {
70
+ "@nomicfoundation/hardhat-ethers": "^3.0.0",
71
+ "@wagmi/core": "^2.0.0",
72
+ "ethers": "^5.0.0 || ^6.0.0",
73
+ "hardhat": "^2.0.0",
74
+ "viem": "^2.38.6"
75
+ },
76
+ "peerDependenciesMeta": {
77
+ "@wagmi/core": {
78
+ "optional": true
79
+ },
80
+ "ethers": {
81
+ "optional": true
82
+ },
83
+ "hardhat": {
84
+ "optional": true
85
+ },
86
+ "@nomicfoundation/hardhat-ethers": {
87
+ "optional": true
88
+ }
89
+ },
90
+ "devDependencies": {
91
+ "@nomicfoundation/hardhat-ethers": "^3.0.0",
92
+ "@types/node": "^20.0.0",
93
+ "@vitest/browser": "^3.0.0",
94
+ "@vitest/coverage-v8": "^3.0.0",
95
+ "eslint": "^8.57.0",
96
+ "ethers5": "npm:ethers@^5.7.2",
97
+ "ethers6": "npm:ethers@^6.13.0",
98
+ "happy-dom": "^15.0.0",
99
+ "hardhat": "^2.19.0",
100
+ "playwright": "^1.55.0",
101
+ "tsup": "^8.0.2",
102
+ "typescript": "5.5.4",
103
+ "vitest": "^3.0.0",
104
+ "@cofhe/eslint-config": "0.2.1",
105
+ "@cofhe/tsconfig": "0.1.2"
106
+ },
107
+ "publishConfig": {
108
+ "access": "public",
109
+ "registry": "https://registry.npmjs.org/"
110
+ },
111
+ "scripts": {
112
+ "build": "tsup",
113
+ "dev": "tsup --watch",
114
+ "lint": "eslint \"**/*.ts*\"",
115
+ "check:types": "tsc --noEmit",
116
+ "clean": "rm -rf .turbo && rm -rf node_modules && rm -rf dist",
117
+ "test": "vitest run",
118
+ "test:watch": "vitest",
119
+ "test:coverage": "vitest run --coverage"
120
+ }
121
+ }
@@ -0,0 +1,68 @@
1
+ // Core types
2
+ export type {
3
+ Permit,
4
+ CreateSelfPermitOptions as SelfPermitOptions,
5
+ CreateSharingPermitOptions as SharingPermitOptions,
6
+ ImportSharedPermitOptions as ImportPermitOptions,
7
+ SerializedPermit,
8
+ PermitMetadata,
9
+ Permission,
10
+ EIP712Domain,
11
+ EIP712Types,
12
+ EIP712Message,
13
+ ValidationResult,
14
+ PermitSignaturePrimaryType,
15
+ } from './types.js';
16
+
17
+ // Main utilities
18
+ export { PermitUtils } from './permit.js';
19
+
20
+ // Validation utilities
21
+ export {
22
+ // Self permit validators
23
+ SelfPermitOptionsValidator,
24
+ SelfPermitValidator,
25
+ validateSelfPermitOptions,
26
+ validateSelfPermit,
27
+ // Sharing permit validators
28
+ SharingPermitOptionsValidator,
29
+ SharingPermitValidator,
30
+ validateSharingPermitOptions,
31
+ validateSharingPermit,
32
+ // Import permit validators
33
+ ImportPermitOptionsValidator,
34
+ ImportPermitValidator,
35
+ validateImportPermitOptions,
36
+ validateImportPermit,
37
+ // Common utilities
38
+ ValidationUtils,
39
+ } from './validation.js';
40
+
41
+ // Signature utilities
42
+ export { SignatureUtils, getSignatureTypesAndMessage, SignatureTypes } from './signature.js';
43
+
44
+ // Storage utilities
45
+ export {
46
+ permitStore,
47
+ getPermit,
48
+ getActivePermit,
49
+ getPermits,
50
+ setPermit,
51
+ removePermit,
52
+ getActivePermitHash,
53
+ setActivePermitHash,
54
+ removeActivePermitHash,
55
+ clearStaleStore,
56
+ PERMIT_STORE_DEFAULTS,
57
+ } from './store.js';
58
+
59
+ // Sealing utilities
60
+ export { SealingKey, GenerateSealingKey } from './sealing.js';
61
+ export type { EthEncryptedData } from './sealing.js';
62
+
63
+ // Re-export everything for convenience
64
+ export * from './types.js';
65
+ export * from './permit.js';
66
+ export * from './validation.js';
67
+ export * from './signature.js';
68
+ export * from './store.js';
@@ -0,0 +1,113 @@
1
+ /**
2
+ * @vitest-environment happy-dom
3
+ */
4
+
5
+ import { describe, it, expect, beforeEach, afterEach } from 'vitest';
6
+ import {
7
+ getPermit,
8
+ setPermit,
9
+ removePermit,
10
+ getActivePermitHash,
11
+ setActivePermitHash,
12
+ PermitUtils,
13
+ permitStore,
14
+ } from './index.js';
15
+ import { createMockPermit } from './test-utils.js';
16
+
17
+ // Type declarations for happy-dom environment
18
+ declare const localStorage: {
19
+ clear: () => void;
20
+ getItem: (name: string) => string | null;
21
+ setItem: (name: string, value: string) => void;
22
+ };
23
+
24
+ describe('Permits localStorage Tests', () => {
25
+ const chainId = 1;
26
+ const account = '0x1234567890123456789012345678901234567890';
27
+
28
+ beforeEach(() => {
29
+ // Clear localStorage and reset store state
30
+ localStorage.clear();
31
+ permitStore.resetStore();
32
+ });
33
+
34
+ afterEach(() => {
35
+ // Clean up after each test
36
+ localStorage.clear();
37
+ permitStore.resetStore();
38
+ });
39
+
40
+ it('should persist permits to localStorage', async () => {
41
+ const permit = await createMockPermit();
42
+
43
+ setPermit(chainId, account, permit);
44
+
45
+ // Verify data is stored in localStorage
46
+ const storedData = localStorage.getItem('cofhesdk-permits');
47
+ expect(storedData).toBeDefined();
48
+
49
+ const parsedData = JSON.parse(storedData!);
50
+ expect(parsedData.state.permits[chainId][account][permit.hash]).toBeDefined();
51
+ });
52
+
53
+ it('should persist active permit hash to localStorage', async () => {
54
+ const permit = await createMockPermit();
55
+
56
+ setPermit(chainId, account, permit);
57
+ setActivePermitHash(chainId, account, permit.hash);
58
+
59
+ // Verify active permit hash is stored
60
+ const storedData = localStorage.getItem('cofhesdk-permits');
61
+ expect(storedData).toBeDefined();
62
+
63
+ const parsedData = JSON.parse(storedData!);
64
+ expect(parsedData.state.activePermitHash[chainId][account]).toBe(permit.hash);
65
+ });
66
+
67
+ it('should restore permits from localStorage', async () => {
68
+ const permit = await createMockPermit();
69
+
70
+ // Add permit to localStorage
71
+ setPermit(chainId, account, permit);
72
+ setActivePermitHash(chainId, account, permit.hash);
73
+ const serializedPermit = PermitUtils.serialize(permit);
74
+
75
+ // Verify data is restored
76
+ const retrievedPermit = getPermit(chainId, account, permit.hash);
77
+ expect(retrievedPermit).toBeDefined();
78
+ expect(PermitUtils.serialize(retrievedPermit!)).toEqual(serializedPermit);
79
+
80
+ const activeHash = getActivePermitHash(chainId, account);
81
+ expect(activeHash).toBe(permit.hash);
82
+ });
83
+
84
+ it('should handle corrupted localStorage data gracefully', () => {
85
+ // Set invalid JSON in localStorage
86
+ localStorage.setItem('cofhesdk-permits', 'invalid json');
87
+
88
+ // Store should handle this gracefully
89
+ expect(() => {
90
+ permitStore.store.getState();
91
+ }).not.toThrow();
92
+ });
93
+
94
+ it('should clean up localStorage when permits are removed', async () => {
95
+ const permit = await createMockPermit();
96
+
97
+ setPermit(chainId, account, permit);
98
+ setActivePermitHash(chainId, account, permit.hash);
99
+
100
+ // Verify data exists
101
+ let storedData = localStorage.getItem('cofhesdk-permits');
102
+ expect(storedData).toBeDefined();
103
+
104
+ // Remove permit
105
+ removePermit(chainId, account, permit.hash);
106
+
107
+ // Verify data is cleaned up
108
+ storedData = localStorage.getItem('cofhesdk-permits');
109
+ const parsedData = JSON.parse(storedData!);
110
+ expect(parsedData.state.permits[chainId][account][permit.hash]).toBeUndefined();
111
+ expect(parsedData.state.activePermitHash[chainId][account]).toBeUndefined();
112
+ });
113
+ });