@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
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { CofheChainSchema, type CofheChain } from './types.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Defines and validates a CofheChain configuration
|
|
5
|
+
* @param chainConfig - The chain configuration object to validate
|
|
6
|
+
* @returns The validated chain configuration unchanged
|
|
7
|
+
* @throws {Error} If the chain configuration is invalid
|
|
8
|
+
*/
|
|
9
|
+
export function defineChain(chainConfig: CofheChain): CofheChain {
|
|
10
|
+
const result = CofheChainSchema.safeParse(chainConfig);
|
|
11
|
+
|
|
12
|
+
if (!result.success) {
|
|
13
|
+
const errorMessages = result.error.errors.map((err) => `${err.path.join('.')}: ${err.message}`);
|
|
14
|
+
throw new Error(`Invalid chain configuration: ${errorMessages.join(', ')}`);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
return result.data;
|
|
18
|
+
}
|
package/chains/index.ts
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
// Export types
|
|
2
|
+
export type { CofheChain, Environment } from './types.js';
|
|
3
|
+
|
|
4
|
+
// Import and export individual chains
|
|
5
|
+
import { sepolia } from './chains/sepolia.js';
|
|
6
|
+
import { arbSepolia } from './chains/arbSepolia.js';
|
|
7
|
+
import { baseSepolia } from './chains/baseSepolia.js';
|
|
8
|
+
import { hardhat } from './chains/hardhat.js';
|
|
9
|
+
|
|
10
|
+
export { sepolia, arbSepolia, baseSepolia, hardhat };
|
|
11
|
+
|
|
12
|
+
// Export all chains as a collection
|
|
13
|
+
export const chains = {
|
|
14
|
+
sepolia,
|
|
15
|
+
arbSepolia,
|
|
16
|
+
baseSepolia,
|
|
17
|
+
hardhat,
|
|
18
|
+
} as const;
|
|
19
|
+
|
|
20
|
+
// Import CofheChain type for helper functions
|
|
21
|
+
import type { CofheChain } from './types.js';
|
|
22
|
+
|
|
23
|
+
// Export chain by ID helper
|
|
24
|
+
export const getChainById = (chainId: number): CofheChain | undefined => {
|
|
25
|
+
return Object.values(chains).find((chain) => chain.id === chainId);
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
// Export chain by name helper
|
|
29
|
+
export const getChainByName = (name: string): CofheChain | undefined => {
|
|
30
|
+
return Object.values(chains).find(
|
|
31
|
+
(chain) => chain.name.toLowerCase() === name.toLowerCase() || chain.network.toLowerCase() === name.toLowerCase()
|
|
32
|
+
);
|
|
33
|
+
};
|
package/chains/types.ts
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Environment schema for @cofhe/sdk chains
|
|
5
|
+
*/
|
|
6
|
+
export const EnvironmentSchema = z.enum(['MOCK', 'TESTNET', 'MAINNET']);
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Zod schema for CofheChain validation
|
|
10
|
+
*/
|
|
11
|
+
export const CofheChainSchema = z.object({
|
|
12
|
+
/** Chain ID */
|
|
13
|
+
id: z.number().int().positive(),
|
|
14
|
+
/** Human-readable chain name */
|
|
15
|
+
name: z.string().min(1),
|
|
16
|
+
/** Network identifier */
|
|
17
|
+
network: z.string().min(1),
|
|
18
|
+
/** coFhe service URL */
|
|
19
|
+
coFheUrl: z.string().url(),
|
|
20
|
+
/** Verifier service URL */
|
|
21
|
+
verifierUrl: z.string().url(),
|
|
22
|
+
/** Threshold network service URL */
|
|
23
|
+
thresholdNetworkUrl: z.string().url(),
|
|
24
|
+
/** Environment type */
|
|
25
|
+
environment: EnvironmentSchema,
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Type inference from the schema
|
|
30
|
+
*/
|
|
31
|
+
export type CofheChain = z.infer<typeof CofheChainSchema>;
|
|
32
|
+
export type Environment = z.infer<typeof EnvironmentSchema>;
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { type PublicClient, type WalletClient } from 'viem';
|
|
2
|
+
import { type CofhesdkConfig } from './config.js';
|
|
3
|
+
import { CofhesdkError, CofhesdkErrorCode } from './error.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Base parameters that all builders need
|
|
7
|
+
*/
|
|
8
|
+
export type BaseBuilderParams = {
|
|
9
|
+
config: CofhesdkConfig | undefined;
|
|
10
|
+
publicClient: PublicClient | undefined;
|
|
11
|
+
walletClient: WalletClient | undefined;
|
|
12
|
+
|
|
13
|
+
chainId: number | undefined;
|
|
14
|
+
account: string | undefined;
|
|
15
|
+
|
|
16
|
+
requireConnected: (() => void) | undefined;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Abstract base class for builders that provides common functionality
|
|
21
|
+
* for working with clients, config, and chain IDs
|
|
22
|
+
*/
|
|
23
|
+
export abstract class BaseBuilder {
|
|
24
|
+
protected config: CofhesdkConfig | undefined;
|
|
25
|
+
protected publicClient: PublicClient | undefined;
|
|
26
|
+
protected walletClient: WalletClient | undefined;
|
|
27
|
+
|
|
28
|
+
protected chainId: number | undefined;
|
|
29
|
+
protected account: string | undefined;
|
|
30
|
+
|
|
31
|
+
protected requireConnected: (() => void) | undefined;
|
|
32
|
+
|
|
33
|
+
constructor(params: BaseBuilderParams) {
|
|
34
|
+
this.config = params.config;
|
|
35
|
+
this.publicClient = params.publicClient;
|
|
36
|
+
this.walletClient = params.walletClient;
|
|
37
|
+
|
|
38
|
+
this.chainId = params.chainId;
|
|
39
|
+
this.account = params.account;
|
|
40
|
+
|
|
41
|
+
this.requireConnected = params.requireConnected;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Gets the chain ID from the instance or fetches it from the public client
|
|
46
|
+
* @returns The chain ID
|
|
47
|
+
* @throws {CofhesdkError} If chainId is not set and publicClient is not available
|
|
48
|
+
*/
|
|
49
|
+
protected async getChainIdOrThrow(): Promise<number> {
|
|
50
|
+
if (this.chainId) return this.chainId;
|
|
51
|
+
|
|
52
|
+
throw new CofhesdkError({
|
|
53
|
+
code: CofhesdkErrorCode.ChainIdUninitialized,
|
|
54
|
+
message: 'Chain ID is not set',
|
|
55
|
+
hint: 'Ensure client.connect() has been called and awaited, or use setChainId(...) to set the chainId explicitly.',
|
|
56
|
+
context: {
|
|
57
|
+
chainId: this.chainId,
|
|
58
|
+
},
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Gets the account address from the instance or fetches it from the wallet client
|
|
64
|
+
* @returns The account address
|
|
65
|
+
* @throws {CofhesdkError} If account is not set and walletClient is not available
|
|
66
|
+
*/
|
|
67
|
+
protected async getAccountOrThrow(): Promise<string> {
|
|
68
|
+
if (this.account) return this.account;
|
|
69
|
+
|
|
70
|
+
throw new CofhesdkError({
|
|
71
|
+
code: CofhesdkErrorCode.AccountUninitialized,
|
|
72
|
+
message: 'Account is not set',
|
|
73
|
+
hint: 'Ensure client.connect() has been called and awaited, or use setAccount(...) to set the account explicitly.',
|
|
74
|
+
context: {
|
|
75
|
+
account: this.account,
|
|
76
|
+
},
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Gets the config or throws an error if not available
|
|
82
|
+
* @returns The config
|
|
83
|
+
* @throws {CofhesdkError} If config is not set
|
|
84
|
+
*/
|
|
85
|
+
protected getConfigOrThrow(): CofhesdkConfig {
|
|
86
|
+
if (this.config) return this.config;
|
|
87
|
+
throw new CofhesdkError({
|
|
88
|
+
code: CofhesdkErrorCode.MissingConfig,
|
|
89
|
+
message: 'Builder config is undefined',
|
|
90
|
+
hint: 'Ensure client has been created with a config.',
|
|
91
|
+
context: {
|
|
92
|
+
config: this.config,
|
|
93
|
+
},
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Gets the public client or throws an error if not available
|
|
99
|
+
* @returns The public client
|
|
100
|
+
* @throws {CofhesdkError} If publicClient is not set
|
|
101
|
+
*/
|
|
102
|
+
protected getPublicClientOrThrow(): PublicClient {
|
|
103
|
+
if (this.publicClient) return this.publicClient;
|
|
104
|
+
throw new CofhesdkError({
|
|
105
|
+
code: CofhesdkErrorCode.MissingPublicClient,
|
|
106
|
+
message: 'Public client not found',
|
|
107
|
+
hint: 'Ensure client.connect() has been called with a publicClient.',
|
|
108
|
+
context: {
|
|
109
|
+
publicClient: this.publicClient,
|
|
110
|
+
},
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Gets the wallet client or throws an error if not available
|
|
116
|
+
* @returns The wallet client
|
|
117
|
+
* @throws {CofhesdkError} If walletClient is not set
|
|
118
|
+
*/
|
|
119
|
+
protected getWalletClientOrThrow(): WalletClient {
|
|
120
|
+
if (this.walletClient) return this.walletClient;
|
|
121
|
+
throw new CofhesdkError({
|
|
122
|
+
code: CofhesdkErrorCode.MissingWalletClient,
|
|
123
|
+
message: 'Wallet client not found',
|
|
124
|
+
hint: 'Ensure client.connect() has been called with a walletClient.',
|
|
125
|
+
context: {
|
|
126
|
+
walletClient: this.walletClient,
|
|
127
|
+
},
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Requires the client to be connected
|
|
133
|
+
* @throws {CofhesdkError} If client is not connected
|
|
134
|
+
*/
|
|
135
|
+
protected requireConnectedOrThrow(): void {
|
|
136
|
+
if (this.requireConnected) this.requireConnected();
|
|
137
|
+
}
|
|
138
|
+
}
|
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
2
|
+
import { createCofhesdkClientBase } from './client.js';
|
|
3
|
+
import { type CofhesdkClient, type CofhesdkClientConnectionState } from './types.js';
|
|
4
|
+
import { createCofhesdkConfigBase } from './config.js';
|
|
5
|
+
import { CofhesdkErrorCode } from './error.js';
|
|
6
|
+
import { type PublicClient, type WalletClient } from 'viem';
|
|
7
|
+
import { EncryptInputsBuilder } from './encrypt/encryptInputsBuilder.js';
|
|
8
|
+
import { Encryptable } from './types.js';
|
|
9
|
+
|
|
10
|
+
// Mock dependencies
|
|
11
|
+
vi.mock('./keyStore', () => ({
|
|
12
|
+
createKeysStore: vi.fn(() => ({
|
|
13
|
+
rehydrateKeysStore: vi.fn().mockResolvedValue(undefined),
|
|
14
|
+
getFheKey: vi.fn(),
|
|
15
|
+
getCrs: vi.fn(),
|
|
16
|
+
setFheKey: vi.fn(),
|
|
17
|
+
setCrs: vi.fn(),
|
|
18
|
+
clearKeysStorage: vi.fn(),
|
|
19
|
+
store: {} as any,
|
|
20
|
+
})),
|
|
21
|
+
}));
|
|
22
|
+
|
|
23
|
+
vi.mock('./fetchKeys', () => ({
|
|
24
|
+
fetchMultichainKeys: vi.fn().mockResolvedValue(undefined),
|
|
25
|
+
}));
|
|
26
|
+
|
|
27
|
+
// Test helpers
|
|
28
|
+
const createMockPublicClient = (chainId = 11155111): PublicClient =>
|
|
29
|
+
({
|
|
30
|
+
getChainId: vi.fn().mockResolvedValue(chainId),
|
|
31
|
+
}) as any;
|
|
32
|
+
|
|
33
|
+
const createMockWalletClient = (addresses = ['0x1234567890123456789012345678901234567890']): WalletClient =>
|
|
34
|
+
({
|
|
35
|
+
getAddresses: vi.fn().mockResolvedValue(addresses),
|
|
36
|
+
}) as any;
|
|
37
|
+
|
|
38
|
+
const createTestClient = (): CofhesdkClient => {
|
|
39
|
+
const config = createCofhesdkConfigBase({ supportedChains: [] });
|
|
40
|
+
return createCofhesdkClientBase({
|
|
41
|
+
config,
|
|
42
|
+
zkBuilderAndCrsGenerator: {} as any,
|
|
43
|
+
tfhePublicKeyDeserializer: {} as any,
|
|
44
|
+
compactPkeCrsDeserializer: {} as any,
|
|
45
|
+
initTfhe: () => Promise.resolve(false),
|
|
46
|
+
});
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
describe('createCofhesdkClientBase', () => {
|
|
50
|
+
let client: CofhesdkClient;
|
|
51
|
+
|
|
52
|
+
beforeEach(() => {
|
|
53
|
+
client = createTestClient();
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
describe('initial state', () => {
|
|
57
|
+
it('should start disconnected', () => {
|
|
58
|
+
const snapshot = client.getSnapshot();
|
|
59
|
+
expect(snapshot.connected).toBe(false);
|
|
60
|
+
expect(snapshot.connecting).toBe(false);
|
|
61
|
+
expect(snapshot.connectError).toBe(undefined);
|
|
62
|
+
expect(snapshot.chainId).toBe(undefined);
|
|
63
|
+
expect(snapshot.account).toBe(undefined);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it('should expose convenience flags', () => {
|
|
67
|
+
expect(client.connected).toBe(false);
|
|
68
|
+
expect(client.connecting).toBe(false);
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
it('should expose config', () => {
|
|
72
|
+
expect(client.config).toBeDefined();
|
|
73
|
+
expect(client.config.supportedChains).toEqual([]);
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
describe('reactive state', () => {
|
|
78
|
+
it('should notify subscribers of state changes', async () => {
|
|
79
|
+
const states: CofhesdkClientConnectionState[] = [];
|
|
80
|
+
client.subscribe((snapshot) => states.push(snapshot));
|
|
81
|
+
|
|
82
|
+
const publicClient = createMockPublicClient();
|
|
83
|
+
const walletClient = createMockWalletClient();
|
|
84
|
+
await client.connect(publicClient, walletClient);
|
|
85
|
+
|
|
86
|
+
// Expect states[0] to be the connecting state
|
|
87
|
+
expect(states[0].connecting).toBe(true);
|
|
88
|
+
expect(states[0].connected).toBe(false);
|
|
89
|
+
expect(states[0].chainId).toBe(undefined);
|
|
90
|
+
expect(states[0].account).toBe(undefined);
|
|
91
|
+
|
|
92
|
+
// Expect states[1] to be the connected state
|
|
93
|
+
expect(states[1].connected).toBe(true);
|
|
94
|
+
expect(states[1].connecting).toBe(false);
|
|
95
|
+
expect(states[1].chainId).toBe(11155111);
|
|
96
|
+
expect(states[1].account).toBe('0x1234567890123456789012345678901234567890');
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
it('should stop notifications after unsubscribe', async () => {
|
|
100
|
+
const states: CofhesdkClientConnectionState[] = [];
|
|
101
|
+
const unsubscribe = client.subscribe((snapshot) => states.push(snapshot));
|
|
102
|
+
|
|
103
|
+
unsubscribe();
|
|
104
|
+
|
|
105
|
+
const publicClient = createMockPublicClient();
|
|
106
|
+
const walletClient = createMockWalletClient();
|
|
107
|
+
await client.connect(publicClient, walletClient);
|
|
108
|
+
|
|
109
|
+
// Should only have the initial notification
|
|
110
|
+
expect(states.length).toBe(0);
|
|
111
|
+
});
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
describe('connect', () => {
|
|
115
|
+
it('should successfully connect with valid clients', async () => {
|
|
116
|
+
const publicClient = createMockPublicClient(11155111);
|
|
117
|
+
const walletClient = createMockWalletClient(['0xabcd']);
|
|
118
|
+
|
|
119
|
+
const result = await client.connect(publicClient, walletClient);
|
|
120
|
+
|
|
121
|
+
expect(result.success).toBe(true);
|
|
122
|
+
expect(result.data).toBe(true);
|
|
123
|
+
|
|
124
|
+
expect(client.connected).toBe(true);
|
|
125
|
+
expect(client.connecting).toBe(false);
|
|
126
|
+
|
|
127
|
+
const snapshot = client.getSnapshot();
|
|
128
|
+
expect(snapshot.chainId).toBe(11155111);
|
|
129
|
+
expect(snapshot.account).toBe('0xabcd');
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
it('should set connecting state during connection', async () => {
|
|
133
|
+
const publicClient = createMockPublicClient();
|
|
134
|
+
const walletClient = createMockWalletClient();
|
|
135
|
+
|
|
136
|
+
const connectPromise = client.connect(publicClient, walletClient);
|
|
137
|
+
|
|
138
|
+
// Check mid-connection state
|
|
139
|
+
expect(client.connecting).toBe(true);
|
|
140
|
+
expect(client.connected).toBe(false);
|
|
141
|
+
|
|
142
|
+
await connectPromise;
|
|
143
|
+
|
|
144
|
+
expect(client.connecting).toBe(false);
|
|
145
|
+
expect(client.connected).toBe(true);
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
it('should return existing promise if already connecting', async () => {
|
|
149
|
+
const publicClient = createMockPublicClient();
|
|
150
|
+
const walletClient = createMockWalletClient();
|
|
151
|
+
|
|
152
|
+
const promise1 = client.connect(publicClient, walletClient);
|
|
153
|
+
const promise2 = client.connect(publicClient, walletClient);
|
|
154
|
+
|
|
155
|
+
expect(promise1).toStrictEqual(promise2);
|
|
156
|
+
|
|
157
|
+
await promise1;
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
it('should return immediately if already connected with same clients', async () => {
|
|
161
|
+
const publicClient = createMockPublicClient();
|
|
162
|
+
const walletClient = createMockWalletClient();
|
|
163
|
+
|
|
164
|
+
await client.connect(publicClient, walletClient);
|
|
165
|
+
const result = await client.connect(publicClient, walletClient);
|
|
166
|
+
|
|
167
|
+
expect(result.success).toBe(true);
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
it('should handle getChainId throwing an error', async () => {
|
|
171
|
+
const publicClient = createMockPublicClient();
|
|
172
|
+
const error = new Error('Network error');
|
|
173
|
+
publicClient.getChainId = vi.fn().mockRejectedValue(error);
|
|
174
|
+
const walletClient = createMockWalletClient();
|
|
175
|
+
|
|
176
|
+
const result = await client.connect(publicClient, walletClient);
|
|
177
|
+
|
|
178
|
+
expect(result.success).toBe(false);
|
|
179
|
+
expect(result.error?.code).toBe(CofhesdkErrorCode.PublicWalletGetChainIdFailed);
|
|
180
|
+
expect(result.error?.message).toBe('getting chain ID from public client failed | Caused by: Network error');
|
|
181
|
+
expect(result.error?.cause).toBe(error);
|
|
182
|
+
expect(client.connected).toBe(false);
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
it('should handle getChainId returning null', async () => {
|
|
186
|
+
const publicClient = createMockPublicClient();
|
|
187
|
+
publicClient.getChainId = vi.fn().mockResolvedValue(null);
|
|
188
|
+
const walletClient = createMockWalletClient();
|
|
189
|
+
|
|
190
|
+
const result = await client.connect(publicClient, walletClient);
|
|
191
|
+
|
|
192
|
+
expect(result.success).toBe(false);
|
|
193
|
+
expect(result.error?.code).toBe(CofhesdkErrorCode.PublicWalletGetChainIdFailed);
|
|
194
|
+
expect(result.error?.message).toBe('chain ID from public client is null');
|
|
195
|
+
expect(result.error?.cause).toBe(undefined);
|
|
196
|
+
expect(client.connected).toBe(false);
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
it('should handle getAddresses throwing an error', async () => {
|
|
200
|
+
const publicClient = createMockPublicClient();
|
|
201
|
+
const error = new Error('Network error');
|
|
202
|
+
const walletClient = createMockWalletClient();
|
|
203
|
+
walletClient.getAddresses = vi.fn().mockRejectedValue(error);
|
|
204
|
+
|
|
205
|
+
const result = await client.connect(publicClient, walletClient);
|
|
206
|
+
|
|
207
|
+
expect(result.success).toBe(false);
|
|
208
|
+
expect(result.error?.code).toBe(CofhesdkErrorCode.PublicWalletGetAddressesFailed);
|
|
209
|
+
expect(result.error?.message).toBe('getting address from wallet client failed | Caused by: Network error');
|
|
210
|
+
expect(result.error?.cause).toBe(error);
|
|
211
|
+
expect(client.connected).toBe(false);
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
it('should handle getAddresses returning an empty array', async () => {
|
|
215
|
+
const publicClient = createMockPublicClient();
|
|
216
|
+
const walletClient = createMockWalletClient([]);
|
|
217
|
+
|
|
218
|
+
const result = await client.connect(publicClient, walletClient);
|
|
219
|
+
|
|
220
|
+
expect(result.success).toBe(false);
|
|
221
|
+
expect(result.error?.code).toBe(CofhesdkErrorCode.PublicWalletGetAddressesFailed);
|
|
222
|
+
expect(result.error?.message).toBe('address from wallet client is null');
|
|
223
|
+
expect(result.error?.cause).toBe(undefined);
|
|
224
|
+
expect(client.connected).toBe(false);
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
it('should store error in state on failure', async () => {
|
|
228
|
+
const publicClient = createMockPublicClient();
|
|
229
|
+
const error = new Error('Network error');
|
|
230
|
+
publicClient.getChainId = vi.fn().mockRejectedValue(error);
|
|
231
|
+
const walletClient = createMockWalletClient();
|
|
232
|
+
|
|
233
|
+
const result = await client.connect(publicClient, walletClient);
|
|
234
|
+
|
|
235
|
+
expect(result.success).toBe(false);
|
|
236
|
+
const snapshot = client.getSnapshot();
|
|
237
|
+
expect(snapshot.connectError).toBeTruthy();
|
|
238
|
+
expect(snapshot.connected).toBe(false);
|
|
239
|
+
});
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
describe('encryptInputs', () => {
|
|
243
|
+
it('should throw if not connected', async () => {
|
|
244
|
+
const result = await client
|
|
245
|
+
.encryptInputs([Encryptable.uint8(1n), Encryptable.uint8(2n), Encryptable.uint8(3n)])
|
|
246
|
+
.encrypt();
|
|
247
|
+
expect(result.success).toBe(false);
|
|
248
|
+
expect(result.error?.code).toBe(CofhesdkErrorCode.NotConnected);
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
it('should create EncryptInputsBuilder when connected', async () => {
|
|
252
|
+
const publicClient = createMockPublicClient(123);
|
|
253
|
+
const walletClient = createMockWalletClient(['0xtest']);
|
|
254
|
+
|
|
255
|
+
await client.connect(publicClient, walletClient);
|
|
256
|
+
|
|
257
|
+
const builder = await client.encryptInputs([Encryptable.uint8(1n), Encryptable.uint8(2n), Encryptable.uint8(3n)]);
|
|
258
|
+
|
|
259
|
+
expect(builder).toBeDefined();
|
|
260
|
+
expect(builder).toBeInstanceOf(EncryptInputsBuilder);
|
|
261
|
+
expect(builder).toHaveProperty('encrypt');
|
|
262
|
+
expect(builder.getChainId()).toBe(123);
|
|
263
|
+
expect(builder.getAccount()).toBe('0xtest');
|
|
264
|
+
});
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
describe('initializationResults', () => {
|
|
268
|
+
it('should have keyFetchResult promise', () => {
|
|
269
|
+
expect(client.initializationResults.keyFetchResult).toBeInstanceOf(Promise);
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
it('should resolve keyFetchResult', async () => {
|
|
273
|
+
const result = await client.initializationResults.keyFetchResult;
|
|
274
|
+
expect(result.success).toBe(true);
|
|
275
|
+
});
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
describe('permits', () => {
|
|
279
|
+
it('should expose permits', () => {
|
|
280
|
+
expect(client.permits).toBeDefined();
|
|
281
|
+
expect(client.permits).toHaveProperty('getSnapshot');
|
|
282
|
+
expect(client.permits).toHaveProperty('subscribe');
|
|
283
|
+
expect(client.permits).toHaveProperty('createSelf');
|
|
284
|
+
expect(client.permits).toHaveProperty('createSharing');
|
|
285
|
+
expect(client.permits).toHaveProperty('importShared');
|
|
286
|
+
expect(client.permits).toHaveProperty('getHash');
|
|
287
|
+
expect(client.permits).toHaveProperty('serialize');
|
|
288
|
+
expect(client.permits).toHaveProperty('deserialize');
|
|
289
|
+
expect(client.permits).toHaveProperty('getPermit');
|
|
290
|
+
expect(client.permits).toHaveProperty('getPermits');
|
|
291
|
+
expect(client.permits).toHaveProperty('getActivePermit');
|
|
292
|
+
expect(client.permits).toHaveProperty('getActivePermitHash');
|
|
293
|
+
expect(client.permits).toHaveProperty('removePermit');
|
|
294
|
+
expect(client.permits).toHaveProperty('selectActivePermit');
|
|
295
|
+
expect(client.permits).toHaveProperty('removeActivePermit');
|
|
296
|
+
});
|
|
297
|
+
});
|
|
298
|
+
});
|