@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,156 @@
1
+ import { describe, it, expect, beforeEach } from 'vitest';
2
+ import { parseEther, createPublicClient, createWalletClient, http, type PublicClient, type WalletClient } from 'viem';
3
+ import { privateKeyToAccount } from 'viem/accounts';
4
+ import { WagmiAdapter } from './wagmi.js';
5
+
6
+ describe('WagmiAdapter', () => {
7
+ const testRpcUrl = 'https://ethereum-sepolia.rpc.subquery.network/public';
8
+ const SEPOLIA_CHAIN_ID = 11155111;
9
+ let account: ReturnType<typeof privateKeyToAccount>;
10
+ let publicClient: PublicClient;
11
+ let walletClient: WalletClient;
12
+
13
+ beforeEach(() => {
14
+ // Create common setup for all tests - no chain needed
15
+ account = privateKeyToAccount(('0x' + '1'.repeat(64)) as `0x${string}`);
16
+
17
+ publicClient = createPublicClient({
18
+ transport: http(testRpcUrl),
19
+ });
20
+
21
+ walletClient = createWalletClient({
22
+ transport: http(testRpcUrl),
23
+ account,
24
+ });
25
+ });
26
+
27
+ it('should work with real Wagmi clients', async () => {
28
+ const result = await WagmiAdapter(walletClient, publicClient);
29
+
30
+ expect(result).toHaveProperty('publicClient');
31
+ expect(result).toHaveProperty('walletClient');
32
+ expect(result.publicClient).toBe(publicClient);
33
+ expect(result.walletClient).toBe(walletClient);
34
+ });
35
+
36
+ it('should throw error when wallet client is missing', async () => {
37
+ const mockPublicClient = {} as any;
38
+
39
+ await expect(async () => {
40
+ await WagmiAdapter(null as any, mockPublicClient);
41
+ }).rejects.toThrow('WalletClient is required');
42
+ });
43
+
44
+ it('should throw error when public client is missing', async () => {
45
+ const mockWalletClient = {} as any;
46
+
47
+ await expect(async () => {
48
+ await WagmiAdapter(mockWalletClient, null as any);
49
+ }).rejects.toThrow('PublicClient is required');
50
+ });
51
+
52
+ describe('Provider Functions', () => {
53
+ it('should support getChainId', async () => {
54
+ const { publicClient: resultPublic } = await WagmiAdapter(walletClient, publicClient);
55
+
56
+ const chainId = await resultPublic.getChainId();
57
+ expect(typeof chainId).toBe('number');
58
+ expect(chainId).toBe(SEPOLIA_CHAIN_ID);
59
+ }, 10000);
60
+
61
+ it('should support call (contract read)', async () => {
62
+ const { publicClient: resultPublic } = await WagmiAdapter(walletClient, publicClient);
63
+
64
+ // Test eth_call - get ETH balance of zero address
65
+ const balance = await resultPublic.getBalance({
66
+ address: '0x0000000000000000000000000000000000000000',
67
+ });
68
+ expect(typeof balance).toBe('bigint');
69
+ }, 10000);
70
+
71
+ it('should support request (raw RPC)', async () => {
72
+ const { publicClient: resultPublic } = await WagmiAdapter(walletClient, publicClient);
73
+
74
+ // Test raw RPC request
75
+ const blockNumber = (await resultPublic.request({
76
+ method: 'eth_blockNumber',
77
+ })) as string;
78
+ expect(typeof blockNumber).toBe('string');
79
+ expect(blockNumber.startsWith('0x')).toBe(true);
80
+ }, 10000);
81
+ });
82
+
83
+ describe('Signer Functions', () => {
84
+ it('should support getAddress', async () => {
85
+ const { walletClient: resultWallet } = await WagmiAdapter(walletClient, publicClient);
86
+
87
+ const addresses = await resultWallet.getAddresses();
88
+ expect(Array.isArray(addresses)).toBe(true);
89
+ // Should contain the account address
90
+ expect(addresses).toContain(account.address);
91
+ }, 10000);
92
+
93
+ it('should support signTypedData', async () => {
94
+ const { walletClient: resultWallet } = await WagmiAdapter(walletClient, publicClient);
95
+
96
+ const domain = {
97
+ name: 'Test',
98
+ version: '1',
99
+ chainId: SEPOLIA_CHAIN_ID, // Sepolia
100
+ verifyingContract: '0x0000000000000000000000000000000000000000' as const,
101
+ };
102
+
103
+ const types = {
104
+ Message: [{ name: 'content', type: 'string' }],
105
+ };
106
+
107
+ const message = { content: 'Hello World' };
108
+
109
+ const signature = await resultWallet.signTypedData({
110
+ domain,
111
+ types,
112
+ primaryType: 'Message',
113
+ message,
114
+ account: resultWallet.account!,
115
+ });
116
+
117
+ expect(typeof signature).toBe('string');
118
+ expect(signature.startsWith('0x')).toBe(true);
119
+ }, 10000);
120
+
121
+ it('should support sendTransaction', async () => {
122
+ const { publicClient: resultPublic, walletClient: resultWallet } = await WagmiAdapter(walletClient, publicClient);
123
+
124
+ // Try to send a transaction - this will fail due to insufficient funds
125
+ try {
126
+ console.log('estimating gas');
127
+ const gas = await resultPublic.estimateGas({
128
+ account: account.address,
129
+ to: '0x0000000000000000000000000000000000000000',
130
+ value: parseEther('0'),
131
+ });
132
+
133
+ console.log('sending transaction', account.address);
134
+ const hash = await resultWallet.sendTransaction({
135
+ to: '0x0000000000000000000000000000000000000000' as `0x${string}`,
136
+ value: parseEther('0'),
137
+ gas,
138
+ account: resultWallet.account!,
139
+ chain: resultWallet.chain,
140
+ });
141
+ console.log('transaction sent', hash);
142
+
143
+ // If it succeeds (shouldn't due to no funds), verify the format
144
+ expect(typeof hash).toBe('string');
145
+ expect(hash.startsWith('0x')).toBe(true);
146
+ expect(hash.length).toBe(66);
147
+ } catch (error: any) {
148
+ // Expected error: insufficient funds (good!)
149
+ const isInsufficientFunds = error.message.includes('insufficient funds') || error.message.includes('balance');
150
+
151
+ expect(isInsufficientFunds).toBe(true);
152
+ console.log('Expected error (insufficient funds):', error.message);
153
+ }
154
+ }, 10000);
155
+ });
156
+ });
@@ -0,0 +1,17 @@
1
+ import { type PublicClient, type WalletClient } from 'viem';
2
+
3
+ export async function WagmiAdapter(walletClient: WalletClient, publicClient: PublicClient) {
4
+ if (!walletClient) {
5
+ throw new Error('WalletClient is required');
6
+ }
7
+
8
+ if (!publicClient) {
9
+ throw new Error('PublicClient is required');
10
+ }
11
+
12
+ // Wagmi provides real viem clients, so we just pass them through
13
+ return {
14
+ publicClient,
15
+ walletClient,
16
+ };
17
+ }
@@ -0,0 +1,14 @@
1
+ import { defineChain } from '../defineChain.js';
2
+
3
+ /**
4
+ * Arbitrum Sepolia testnet chain configuration
5
+ */
6
+ export const arbSepolia = defineChain({
7
+ id: 421614,
8
+ name: 'Arbitrum Sepolia',
9
+ network: 'arb-sepolia',
10
+ coFheUrl: 'https://testnet-cofhe.fhenix.zone',
11
+ verifierUrl: 'https://testnet-cofhe-vrf.fhenix.zone',
12
+ thresholdNetworkUrl: 'https://testnet-cofhe-tn.fhenix.zone',
13
+ environment: 'TESTNET',
14
+ });
@@ -0,0 +1,14 @@
1
+ import { defineChain } from '../defineChain.js';
2
+
3
+ /**
4
+ * Base Sepolia testnet chain configuration
5
+ */
6
+ export const baseSepolia = defineChain({
7
+ id: 84532,
8
+ name: 'Base Sepolia',
9
+ network: 'base-sepolia',
10
+ coFheUrl: 'https://testnet-cofhe.fhenix.zone',
11
+ verifierUrl: 'https://testnet-cofhe-vrf.fhenix.zone',
12
+ thresholdNetworkUrl: 'https://testnet-cofhe-tn.fhenix.zone',
13
+ environment: 'TESTNET',
14
+ });
@@ -0,0 +1,15 @@
1
+ import { defineChain } from '../defineChain.js';
2
+
3
+ /**
4
+ * Hardhat local development chain configuration
5
+ */
6
+ export const hardhat = defineChain({
7
+ id: 31337,
8
+ name: 'Hardhat',
9
+ network: 'localhost',
10
+ // These are unused in the mock environment
11
+ coFheUrl: 'http://127.0.0.1:8448',
12
+ verifierUrl: 'http://127.0.0.1:3001',
13
+ thresholdNetworkUrl: 'http://127.0.0.1:3000',
14
+ environment: 'MOCK',
15
+ });
@@ -0,0 +1,14 @@
1
+ import { defineChain } from '../defineChain.js';
2
+
3
+ /**
4
+ * Localcofhe chain configuration
5
+ */
6
+ export const localcofhe = defineChain({
7
+ id: 420105,
8
+ name: 'Local Cofhe',
9
+ network: 'localhost',
10
+ coFheUrl: 'http://127.0.0.1:9448',
11
+ verifierUrl: 'http://127.0.0.1:3001',
12
+ thresholdNetworkUrl: 'http://127.0.0.1:3000',
13
+ environment: 'TESTNET',
14
+ });
@@ -0,0 +1,14 @@
1
+ import { defineChain } from '../defineChain.js';
2
+
3
+ /**
4
+ * Sepolia testnet chain configuration
5
+ */
6
+ export const sepolia = defineChain({
7
+ id: 11155111,
8
+ name: 'Sepolia',
9
+ network: 'sepolia',
10
+ coFheUrl: 'https://testnet-cofhe.fhenix.zone',
11
+ verifierUrl: 'https://testnet-cofhe-vrf.fhenix.zone',
12
+ thresholdNetworkUrl: 'https://testnet-cofhe-tn.fhenix.zone',
13
+ environment: 'TESTNET',
14
+ });
@@ -0,0 +1,50 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { sepolia, arbSepolia, baseSepolia, hardhat, chains, getChainById, getChainByName } from './index.js';
3
+
4
+ describe('Chains', () => {
5
+ it('should export all chains', () => {
6
+ expect(Object.keys(chains)).toHaveLength(5);
7
+ expect(chains).toHaveProperty('sepolia');
8
+ expect(chains).toHaveProperty('arbSepolia');
9
+ expect(chains).toHaveProperty('baseSepolia');
10
+ expect(chains).toHaveProperty('hardhat');
11
+ expect(chains).toHaveProperty('localcofhe');
12
+ });
13
+
14
+ it('should have correct chain configurations', () => {
15
+ expect(sepolia.id).toBe(11155111);
16
+ expect(sepolia.name).toBe('Sepolia');
17
+ expect(sepolia.environment).toBe('TESTNET');
18
+
19
+ expect(hardhat.id).toBe(31337);
20
+ expect(hardhat.name).toBe('Hardhat');
21
+ expect(hardhat.environment).toBe('MOCK');
22
+ });
23
+
24
+ it('should find chains by ID', () => {
25
+ expect(getChainById(11155111)).toBe(sepolia);
26
+ expect(getChainById(31337)).toBe(hardhat);
27
+ expect(getChainById(999999)).toBeUndefined();
28
+ });
29
+
30
+ it('should find chains by name', () => {
31
+ expect(getChainByName('sepolia')).toBe(sepolia);
32
+ expect(getChainByName('Sepolia')).toBe(sepolia);
33
+ expect(getChainByName('hardhat')).toBe(hardhat);
34
+ expect(getChainByName('nonexistent')).toBeUndefined();
35
+ });
36
+
37
+ it('should validate chain properties', () => {
38
+ const allChains = [sepolia, arbSepolia, baseSepolia, hardhat];
39
+
40
+ allChains.forEach((chain) => {
41
+ expect(typeof chain.id).toBe('number');
42
+ expect(typeof chain.name).toBe('string');
43
+ expect(typeof chain.network).toBe('string');
44
+ expect(typeof chain.coFheUrl).toBe('string');
45
+ expect(typeof chain.verifierUrl).toBe('string');
46
+ expect(typeof chain.thresholdNetworkUrl).toBe('string');
47
+ expect(['MOCK', 'TESTNET', 'MAINNET']).toContain(chain.environment);
48
+ });
49
+ });
50
+ });
@@ -0,0 +1,18 @@
1
+ import { CofheChainSchema, type CofheChain } from './types.js';
2
+ import { z } from 'zod';
3
+
4
+ /**
5
+ * Defines and validates a CofheChain configuration
6
+ * @param chainConfig - The chain configuration object to validate
7
+ * @returns The validated chain configuration unchanged
8
+ * @throws {Error} If the chain configuration is invalid
9
+ */
10
+ export function defineChain(chainConfig: CofheChain): CofheChain {
11
+ const result = CofheChainSchema.safeParse(chainConfig);
12
+
13
+ if (!result.success) {
14
+ throw new Error(`Invalid chain configuration: ${z.prettifyError(result.error)}`, { cause: result.error });
15
+ }
16
+
17
+ return result.data;
18
+ }
@@ -0,0 +1,35 @@
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
+ import { localcofhe } from './chains/localcofhe.js';
10
+
11
+ export { sepolia, arbSepolia, baseSepolia, hardhat, localcofhe };
12
+
13
+ // Export all chains as a collection
14
+ export const chains = {
15
+ sepolia,
16
+ arbSepolia,
17
+ baseSepolia,
18
+ hardhat,
19
+ localcofhe,
20
+ } as const;
21
+
22
+ // Import CofheChain type for helper functions
23
+ import type { CofheChain } from './types.js';
24
+
25
+ // Export chain by ID helper
26
+ export const getChainById = (chainId: number): CofheChain | undefined => {
27
+ return Object.values(chains).find((chain) => chain.id === chainId);
28
+ };
29
+
30
+ // Export chain by name helper
31
+ export const getChainByName = (name: string): CofheChain | undefined => {
32
+ return Object.values(chains).find(
33
+ (chain) => chain.name.toLowerCase() === name.toLowerCase() || chain.network.toLowerCase() === name.toLowerCase()
34
+ );
35
+ };
@@ -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.url(),
20
+ /** Verifier service URL */
21
+ verifierUrl: z.url(),
22
+ /** Threshold network service URL */
23
+ thresholdNetworkUrl: z.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,119 @@
1
+ import { type PublicClient, type WalletClient } from 'viem';
2
+ import { type CofheConfig } from './config.js';
3
+ import { CofheError, CofheErrorCode } from './error.js';
4
+
5
+ /**
6
+ * Base parameters that all builders need
7
+ */
8
+ export type BaseBuilderParams = {
9
+ config: CofheConfig | 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: CofheConfig;
25
+
26
+ protected publicClient: PublicClient | undefined;
27
+ protected walletClient: WalletClient | undefined;
28
+
29
+ protected chainId: number | undefined;
30
+ protected account: string | undefined;
31
+
32
+ constructor(params: BaseBuilderParams) {
33
+ // Check that config is provided
34
+ if (!params.config) {
35
+ throw new CofheError({
36
+ code: CofheErrorCode.MissingConfig,
37
+ message: 'Builder config is undefined',
38
+ hint: 'Ensure client has been created with a config.',
39
+ context: {
40
+ config: params.config,
41
+ },
42
+ });
43
+ }
44
+ this.config = params.config;
45
+
46
+ this.publicClient = params.publicClient;
47
+ this.walletClient = params.walletClient;
48
+
49
+ this.chainId = params.chainId;
50
+ this.account = params.account;
51
+
52
+ // Require the client to be connected if passed as param
53
+ params.requireConnected?.();
54
+ }
55
+
56
+ /**
57
+ * Asserts that this.chainId is populated
58
+ * @throws {CofheError} If chainId is not set
59
+ */
60
+ protected assertChainId(): asserts this is this & { chainId: number } {
61
+ if (this.chainId) return;
62
+ throw new CofheError({
63
+ code: CofheErrorCode.ChainIdUninitialized,
64
+ message: 'Chain ID is not set',
65
+ hint: 'Ensure client.connect() has been called and awaited, or use setChainId(...) to set the chainId explicitly.',
66
+ context: {
67
+ chainId: this.chainId,
68
+ },
69
+ });
70
+ }
71
+
72
+ /**
73
+ * Asserts that this.account is populated
74
+ * @throws {CofheError} If account is not set
75
+ */
76
+ protected assertAccount(): asserts this is this & { account: string } {
77
+ if (this.account) return;
78
+ throw new CofheError({
79
+ code: CofheErrorCode.AccountUninitialized,
80
+ message: 'Account is not set',
81
+ hint: 'Ensure client.connect() has been called and awaited, or use setAccount(...) to set the account explicitly.',
82
+ context: {
83
+ account: this.account,
84
+ },
85
+ });
86
+ }
87
+
88
+ /**
89
+ * Asserts that this.publicClient is populated
90
+ * @throws {CofheError} If publicClient is not set
91
+ */
92
+ protected assertPublicClient(): asserts this is this & { publicClient: PublicClient } {
93
+ if (this.publicClient) return;
94
+ throw new CofheError({
95
+ code: CofheErrorCode.MissingPublicClient,
96
+ message: 'Public client not found',
97
+ hint: 'Ensure client.connect() has been called with a publicClient.',
98
+ context: {
99
+ publicClient: this.publicClient,
100
+ },
101
+ });
102
+ }
103
+
104
+ /**
105
+ * Asserts that this.walletClient is populated
106
+ * @throws {CofheError} If walletClient is not set
107
+ */
108
+ protected assertWalletClient(): asserts this is this & { walletClient: WalletClient } {
109
+ if (this.walletClient) return;
110
+ throw new CofheError({
111
+ code: CofheErrorCode.MissingWalletClient,
112
+ message: 'Wallet client not found',
113
+ hint: 'Ensure client.connect() has been called with a walletClient.',
114
+ context: {
115
+ walletClient: this.walletClient,
116
+ },
117
+ });
118
+ }
119
+ }