@interfold/sdk 0.13.0 → 0.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +51 -30
- package/dist/contracts/index.cjs +27 -12
- package/dist/contracts/index.cjs.map +1 -1
- package/dist/contracts/index.d.ts +2 -2
- package/dist/contracts/index.js +28 -12
- package/dist/contracts/index.js.map +1 -1
- package/dist/crypto/index.cjs.map +1 -1
- package/dist/crypto/index.js.map +1 -1
- package/dist/events/index.cjs +3 -0
- package/dist/events/index.cjs.map +1 -1
- package/dist/events/index.d.ts +24 -2
- package/dist/events/index.js +3 -0
- package/dist/events/index.js.map +1 -1
- package/dist/index.cjs +182 -17
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +37 -9
- package/dist/index.js +180 -17
- package/dist/index.js.map +1 -1
- package/dist/{types-Cwx_flfX.d.ts → types-BJe3EYvv.d.ts} +8 -1
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -49,7 +49,7 @@ const sdk = new InterfoldSDK({
|
|
|
49
49
|
feeToken: '0x...', // Your ERC-20 fee token address
|
|
50
50
|
},
|
|
51
51
|
chain: sepolia,
|
|
52
|
-
//
|
|
52
|
+
// Match the parameter set selected by the target E3.
|
|
53
53
|
thresholdBfvParamsPresetName: 'INSECURE_THRESHOLD_512',
|
|
54
54
|
})
|
|
55
55
|
|
|
@@ -95,7 +95,7 @@ const sdk = InterfoldSDK.create({
|
|
|
95
95
|
},
|
|
96
96
|
chain: sepolia,
|
|
97
97
|
privateKey: '0x...', // optional — omit for read-only
|
|
98
|
-
//
|
|
98
|
+
// Match the parameter set selected by the target E3.
|
|
99
99
|
thresholdBfvParamsPresetName: 'INSECURE_THRESHOLD_512',
|
|
100
100
|
})
|
|
101
101
|
```
|
|
@@ -355,7 +355,12 @@ await sdk.requestE3({
|
|
|
355
355
|
});
|
|
356
356
|
|
|
357
357
|
// Publish ciphertext output
|
|
358
|
-
await sdk.publishCiphertextOutput(e3Id
|
|
358
|
+
await sdk.publishCiphertextOutput(e3Id, {
|
|
359
|
+
contentHash,
|
|
360
|
+
ciphertextCommitment,
|
|
361
|
+
computeProof,
|
|
362
|
+
availabilityProof,
|
|
363
|
+
}, gasLimit);
|
|
359
364
|
|
|
360
365
|
// Read operations
|
|
361
366
|
const e3Data = await sdk.getE3(e3Id: bigint);
|
|
@@ -394,24 +399,41 @@ await sdk.startEventPolling();
|
|
|
394
399
|
sdk.stopEventPolling();
|
|
395
400
|
```
|
|
396
401
|
|
|
397
|
-
|
|
398
|
-
|
|
402
|
+
Committee public keys are emitted as `CommitteePublicKeyChunkPublished` events. Reassemble the
|
|
403
|
+
canonical chunk sequence, check its Keccak hash, and validate the decoded key against the event's
|
|
404
|
+
proven `pkCommitment` before using it for encryption:
|
|
399
405
|
|
|
400
406
|
```typescript
|
|
401
407
|
import { hexToBytes } from 'viem'
|
|
408
|
+
import { CommitteePublicKeyAssembler, RegistryEventType } from '@interfold/sdk'
|
|
409
|
+
|
|
410
|
+
const assembler = new CommitteePublicKeyAssembler()
|
|
411
|
+
|
|
412
|
+
await sdk.onInterfoldEvent(
|
|
413
|
+
RegistryEventType.COMMITTEE_PUBLIC_KEY_CHUNK_PUBLISHED,
|
|
414
|
+
async (event) => {
|
|
415
|
+
const assembled = assembler.add(event.data)
|
|
416
|
+
if (!assembled) return
|
|
417
|
+
|
|
418
|
+
if (
|
|
419
|
+
!(await sdk.validatePublicKeyCommitment(
|
|
420
|
+
assembled.publicKey,
|
|
421
|
+
hexToBytes(assembled.pkCommitment),
|
|
422
|
+
))
|
|
423
|
+
) {
|
|
424
|
+
throw new Error('Committee public-key commitment mismatch')
|
|
425
|
+
}
|
|
402
426
|
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
if (!(await sdk.validatePublicKeyCommitment(publicKey, expectedCommitment))) {
|
|
408
|
-
throw new Error('Committee public-key commitment mismatch')
|
|
409
|
-
}
|
|
410
|
-
|
|
411
|
-
// The key is now safe to pass to the encryption methods.
|
|
412
|
-
})
|
|
427
|
+
assembler.clear(assembled.e3Id)
|
|
428
|
+
// assembled.publicKey is now safe to pass to the encryption methods.
|
|
429
|
+
},
|
|
430
|
+
)
|
|
413
431
|
```
|
|
414
432
|
|
|
433
|
+
The assembler tracks at most 128 E3s by default. Pass a positive limit to the constructor if the
|
|
434
|
+
application needs a different memory bound. Evicted incomplete keys can be rebuilt by replaying
|
|
435
|
+
their chunk events.
|
|
436
|
+
|
|
415
437
|
#### Encryption
|
|
416
438
|
|
|
417
439
|
```typescript
|
|
@@ -468,21 +490,20 @@ interface SDKConfig {
|
|
|
468
490
|
`thresholdBfvParamsPresetName` selects the BFV parameter set used for encryption. It must match the
|
|
469
491
|
on-chain `paramSet` index registered in the Interfold contract:
|
|
470
492
|
|
|
471
|
-
| Preset name | On-chain `paramSet` index | Use case
|
|
472
|
-
| -------------------------- | ------------------------- |
|
|
473
|
-
| `'INSECURE_THRESHOLD_512'` | `0` |
|
|
474
|
-
| `'SECURE_THRESHOLD_8192'` | `1` | Production
|
|
475
|
-
|
|
476
|
-
| Network
|
|
477
|
-
|
|
|
478
|
-
| Local development
|
|
479
|
-
| Sepolia testnet
|
|
480
|
-
|
|
|
481
|
-
|
|
482
|
-
Use
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
[Proving](#proving-embedded-circuits-or-your-own)).
|
|
493
|
+
| Preset name | On-chain `paramSet` index | Use case |
|
|
494
|
+
| -------------------------- | ------------------------- | ------------------------------------------------------------------------ |
|
|
495
|
+
| `'INSECURE_THRESHOLD_512'` | `0` | Fast local or testnet work. This preset is not cryptographically secure. |
|
|
496
|
+
| `'SECURE_THRESHOLD_8192'` | `1` | Production-equivalent work with degree 8192 and three ciphertext moduli. |
|
|
497
|
+
|
|
498
|
+
| Network | Supported presets |
|
|
499
|
+
| ----------------- | -------------------------------------------------------- |
|
|
500
|
+
| Local development | `'INSECURE_THRESHOLD_512'` and `'SECURE_THRESHOLD_8192'` |
|
|
501
|
+
| Sepolia testnet | `'INSECURE_THRESHOLD_512'` and `'SECURE_THRESHOLD_8192'` |
|
|
502
|
+
| Ethereum mainnet | `'SECURE_THRESHOLD_8192'` only |
|
|
503
|
+
|
|
504
|
+
Use the preset that the target E3 selects. This package includes proof artifacts only for
|
|
505
|
+
`'INSECURE_THRESHOLD_512'`. For secure proof generation, use matching application artifacts such as
|
|
506
|
+
the `@crisp-e3/sdk/secure-8192` entry point, or compile your own artifacts.
|
|
486
507
|
|
|
487
508
|
### Proving: embedded circuits or your own
|
|
488
509
|
|
package/dist/contracts/index.cjs
CHANGED
|
@@ -43,6 +43,15 @@ var SDKError = class extends Error {
|
|
|
43
43
|
function isValidAddress(address) {
|
|
44
44
|
return /^0x[a-fA-F0-9]{40}$/.test(address);
|
|
45
45
|
}
|
|
46
|
+
function cryptoConfigIdForParamSet(paramSet) {
|
|
47
|
+
if (paramSet === 0) {
|
|
48
|
+
return "0x04f3677e73b0f5066d6caf5cbd92e3fb2e38338edaf5cfc971ab28f7b684da78";
|
|
49
|
+
}
|
|
50
|
+
if (paramSet === 1) {
|
|
51
|
+
return "0xd9c86e581f8291ffb5b63595600e8d096ed30b16e2e0a6634a76c22b1f58fb4e";
|
|
52
|
+
}
|
|
53
|
+
throw new SDKError(`Unsupported BFV parameter set: ${paramSet}`, "UNSUPPORTED_CRYPTO_CONFIG");
|
|
54
|
+
}
|
|
46
55
|
|
|
47
56
|
// src/contracts/types.ts
|
|
48
57
|
function validateCommitteeSize(value) {
|
|
@@ -172,11 +181,7 @@ var ContractClient = class _ContractClient {
|
|
|
172
181
|
}
|
|
173
182
|
const committeeSize = validateCommitteeSize(params.committeeSize);
|
|
174
183
|
const maxFee = params.maxFee ?? await this.getE3Quote(params);
|
|
175
|
-
const expectedCryptoConfigId =
|
|
176
|
-
address: this.contracts.interfold,
|
|
177
|
-
abi: import_types.Interfold__factory.abi,
|
|
178
|
-
functionName: "activeCryptoConfigId"
|
|
179
|
-
});
|
|
184
|
+
const expectedCryptoConfigId = cryptoConfigIdForParamSet(params.paramSet);
|
|
180
185
|
const { request } = await this.publicClient.simulateContract({
|
|
181
186
|
address: this.contracts.interfold,
|
|
182
187
|
abi: import_types.Interfold__factory.abi,
|
|
@@ -223,7 +228,7 @@ var ContractClient = class _ContractClient {
|
|
|
223
228
|
throw new SDKError(`Failed to cancel E3: ${error}`, "CANCEL_E3_FAILED");
|
|
224
229
|
}
|
|
225
230
|
}
|
|
226
|
-
async publishCiphertextOutput(e3Id,
|
|
231
|
+
async publishCiphertextOutput(e3Id, outputReference, gasLimit) {
|
|
227
232
|
if (!this.walletClient) {
|
|
228
233
|
throw new SDKError("Wallet client required for write operations", "NO_WALLET");
|
|
229
234
|
}
|
|
@@ -232,11 +237,25 @@ var ContractClient = class _ContractClient {
|
|
|
232
237
|
if (!account) {
|
|
233
238
|
throw new SDKError("No account connected", "NO_ACCOUNT");
|
|
234
239
|
}
|
|
240
|
+
const encodedOutputReference = (0, import_viem2.encodeAbiParameters)(
|
|
241
|
+
[
|
|
242
|
+
{
|
|
243
|
+
type: "tuple",
|
|
244
|
+
components: [
|
|
245
|
+
{ name: "contentHash", type: "bytes32" },
|
|
246
|
+
{ name: "ciphertextCommitment", type: "bytes32" },
|
|
247
|
+
{ name: "computeProof", type: "bytes" },
|
|
248
|
+
{ name: "availabilityProof", type: "bytes" }
|
|
249
|
+
]
|
|
250
|
+
}
|
|
251
|
+
],
|
|
252
|
+
[outputReference]
|
|
253
|
+
);
|
|
235
254
|
const { request } = await this.publicClient.simulateContract({
|
|
236
255
|
address: this.contracts.interfold,
|
|
237
256
|
abi: import_types.Interfold__factory.abi,
|
|
238
257
|
functionName: "publishCiphertextOutput",
|
|
239
|
-
args: [e3Id,
|
|
258
|
+
args: [e3Id, encodedOutputReference],
|
|
240
259
|
account,
|
|
241
260
|
gas: gasLimit
|
|
242
261
|
});
|
|
@@ -261,11 +280,7 @@ var ContractClient = class _ContractClient {
|
|
|
261
280
|
async getE3Quote(requestParams) {
|
|
262
281
|
try {
|
|
263
282
|
const committeeSize = validateCommitteeSize(requestParams.committeeSize);
|
|
264
|
-
const expectedCryptoConfigId =
|
|
265
|
-
address: this.contracts.interfold,
|
|
266
|
-
abi: import_types.Interfold__factory.abi,
|
|
267
|
-
functionName: "activeCryptoConfigId"
|
|
268
|
-
});
|
|
283
|
+
const expectedCryptoConfigId = cryptoConfigIdForParamSet(requestParams.paramSet);
|
|
269
284
|
return this.publicClient.readContract({
|
|
270
285
|
address: this.contracts.interfold,
|
|
271
286
|
abi: import_types.Interfold__factory.abi,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/contracts/index.ts","../../src/contracts/contract-client.ts","../../src/utils.ts","../../src/contracts/types.ts"],"sourcesContent":["// SPDX-License-Identifier: LGPL-3.0-only\n//\n// This file is provided WITHOUT ANY WARRANTY;\n// without even the implied warranty of MERCHANTABILITY\n// or FITNESS FOR A PARTICULAR PURPOSE.\n\nexport { ContractClient } from './contract-client'\nexport type { ContractClientConfig } from './contract-client'\nexport type { ContractAddresses, E3, E3RequestParams } from './types'\nexport { E3Stage, FailureReason } from './types'\n","// SPDX-License-Identifier: LGPL-3.0-only\n//\n// This file is provided WITHOUT ANY WARRANTY;\n// without even the implied warranty of MERCHANTABILITY\n// or FITNESS FOR A PARTICULAR PURPOSE.\n\nimport {\n type Abi,\n type Chain,\n type Hash,\n type PublicClient,\n type TransactionReceipt,\n type WalletClient,\n createPublicClient,\n createWalletClient,\n http,\n webSocket,\n} from 'viem'\nimport { privateKeyToAccount } from 'viem/accounts'\n\nimport { CiphernodeRegistryOwnable__factory, Interfold__factory, InterfoldToken__factory } from '@interfold/contracts/types'\nimport type { ContractAddresses, E3, E3RequestParams, E3Stage, FailureReason } from './types'\nimport { validateCommitteeSize } from './types'\nimport { SDKError, isValidAddress } from '../utils'\n\nexport interface ContractClientConfig {\n publicClient: PublicClient\n walletClient?: WalletClient\n contracts: ContractAddresses\n}\n\nexport class ContractClient {\n private publicClient: PublicClient\n private walletClient?: WalletClient\n private contracts: ContractAddresses\n private contractInfo: {\n interfold: { address: `0x${string}`; abi: Abi }\n ciphernodeRegistry: { address: `0x${string}`; abi: Abi }\n feeToken: { address: `0x${string}`; abi: Abi }\n }\n\n constructor(config: ContractClientConfig) {\n const { publicClient, walletClient, contracts } = config\n\n if (!isValidAddress(contracts.interfold)) {\n throw new SDKError('Invalid Interfold contract address', 'INVALID_ADDRESS')\n }\n if (!isValidAddress(contracts.ciphernodeRegistry)) {\n throw new SDKError('Invalid CiphernodeRegistry contract address', 'INVALID_ADDRESS')\n }\n if (!isValidAddress(contracts.feeToken)) {\n throw new SDKError('Invalid FeeToken contract address', 'INVALID_ADDRESS')\n }\n\n this.publicClient = publicClient\n this.walletClient = walletClient\n this.contracts = contracts\n\n this.contractInfo = {\n interfold: {\n address: contracts.interfold,\n abi: Interfold__factory.abi,\n },\n ciphernodeRegistry: {\n address: contracts.ciphernodeRegistry,\n abi: CiphernodeRegistryOwnable__factory.abi,\n },\n feeToken: {\n address: contracts.feeToken,\n abi: InterfoldToken__factory.abi,\n },\n }\n }\n\n public static create(options: {\n rpcUrl: string\n contracts: ContractAddresses\n privateKey?: `0x${string}`\n chain: Chain\n }): ContractClient {\n const isWebSocket = options.rpcUrl.startsWith('ws://') || options.rpcUrl.startsWith('wss://')\n const transport = isWebSocket\n ? webSocket(options.rpcUrl, {\n keepAlive: { interval: 30_000 },\n reconnect: { attempts: 5, delay: 2_000 },\n })\n : http(options.rpcUrl)\n\n const publicClient = createPublicClient({\n chain: options.chain,\n transport,\n }) as PublicClient\n\n let walletClient: WalletClient | undefined\n if (options.privateKey) {\n const account = privateKeyToAccount(options.privateKey)\n walletClient = createWalletClient({\n account,\n chain: options.chain,\n transport,\n })\n }\n\n return new ContractClient({ publicClient, walletClient, contracts: options.contracts })\n }\n\n public getPublicClient(): PublicClient {\n return this.publicClient\n }\n\n public async approveFeeToken(amount: bigint): Promise<Hash> {\n if (!this.walletClient) {\n throw new SDKError('Wallet client required for write operations', 'NO_WALLET')\n }\n\n try {\n const account = this.walletClient.account\n if (!account) {\n throw new SDKError('No account connected', 'NO_ACCOUNT')\n }\n\n const { request } = await this.publicClient.simulateContract({\n address: this.contracts.feeToken,\n abi: InterfoldToken__factory.abi,\n functionName: 'approve',\n args: [this.contracts.interfold, amount],\n account,\n })\n\n return await this.walletClient.writeContract(request)\n } catch (error) {\n throw new SDKError(`Failed to approve fee token: ${error}`, 'APPROVE_FEE_TOKEN_FAILED')\n }\n }\n\n public async requestE3(params: E3RequestParams): Promise<Hash> {\n if (!this.walletClient) {\n throw new SDKError('Wallet client required for write operations', 'NO_WALLET')\n }\n\n try {\n const account = this.walletClient.account\n if (!account) {\n throw new SDKError('No account connected', 'NO_ACCOUNT')\n }\n\n const committeeSize = validateCommitteeSize(params.committeeSize)\n const maxFee = params.maxFee ?? (await this.getE3Quote(params))\n const expectedCryptoConfigId = await this.publicClient.readContract({\n address: this.contracts.interfold,\n abi: Interfold__factory.abi,\n functionName: 'activeCryptoConfigId',\n })\n\n const { request } = await this.publicClient.simulateContract({\n address: this.contracts.interfold,\n abi: Interfold__factory.abi,\n functionName: 'request',\n args: [\n {\n committeeSize,\n inputWindow: params.inputWindow,\n e3Program: params.e3Program,\n paramSet: params.paramSet,\n computeProviderParams: params.computeProviderParams,\n customParams: params.customParams || '0x',\n expectedFeeToken: this.contracts.feeToken,\n expectedCryptoConfigId,\n maxFee,\n },\n ],\n account,\n gas: params.gasLimit,\n })\n\n return await this.walletClient.writeContract(request)\n } catch (error) {\n throw new SDKError(`Failed to request E3: ${error}`, 'REQUEST_E3_FAILED')\n }\n }\n\n public async cancelE3(e3Id: bigint): Promise<Hash> {\n if (!this.walletClient) {\n throw new SDKError('Wallet client required for write operations', 'NO_WALLET')\n }\n const account = this.walletClient.account\n if (!account) {\n throw new SDKError('No account connected', 'NO_ACCOUNT')\n }\n\n try {\n const { request } = await this.publicClient.simulateContract({\n address: this.contracts.interfold,\n abi: Interfold__factory.abi,\n functionName: 'cancelE3',\n args: [e3Id],\n account,\n })\n\n return await this.walletClient.writeContract(request)\n } catch (error) {\n throw new SDKError(`Failed to cancel E3: ${error}`, 'CANCEL_E3_FAILED')\n }\n }\n\n public async publishCiphertextOutput(\n e3Id: bigint,\n ciphertextOutput: `0x${string}`,\n ciphertextCommitment: `0x${string}`,\n proof: `0x${string}`,\n gasLimit?: bigint,\n ): Promise<Hash> {\n if (!this.walletClient) {\n throw new SDKError('Wallet client required for write operations', 'NO_WALLET')\n }\n\n try {\n const account = this.walletClient.account\n if (!account) {\n throw new SDKError('No account connected', 'NO_ACCOUNT')\n }\n\n const { request } = await this.publicClient.simulateContract({\n address: this.contracts.interfold,\n abi: Interfold__factory.abi,\n functionName: 'publishCiphertextOutput',\n args: [e3Id, ciphertextOutput, ciphertextCommitment, proof],\n account,\n gas: gasLimit,\n })\n\n return await this.walletClient.writeContract(request)\n } catch (error) {\n throw new SDKError(`Failed to publish ciphertext output: ${error}`, 'PUBLISH_CIPHERTEXT_OUTPUT_FAILED')\n }\n }\n\n public async getE3(e3Id: bigint): Promise<E3> {\n try {\n const result: E3 = await this.publicClient.readContract({\n address: this.contracts.interfold,\n abi: Interfold__factory.abi,\n functionName: 'getE3',\n args: [e3Id],\n })\n\n return result\n } catch (error) {\n throw new SDKError(`Failed to get E3: ${error}`, 'GET_E3_FAILED')\n }\n }\n\n public async getE3Quote(requestParams: E3RequestParams): Promise<bigint> {\n try {\n const committeeSize = validateCommitteeSize(requestParams.committeeSize)\n const expectedCryptoConfigId = await this.publicClient.readContract({\n address: this.contracts.interfold,\n abi: Interfold__factory.abi,\n functionName: 'activeCryptoConfigId',\n })\n\n return this.publicClient.readContract({\n address: this.contracts.interfold,\n abi: Interfold__factory.abi,\n functionName: 'getE3Quote',\n args: [\n {\n committeeSize,\n inputWindow: requestParams.inputWindow,\n e3Program: requestParams.e3Program,\n paramSet: requestParams.paramSet,\n computeProviderParams: requestParams.computeProviderParams,\n customParams: requestParams.customParams || '0x',\n expectedFeeToken: this.contracts.feeToken,\n expectedCryptoConfigId,\n maxFee: requestParams.maxFee ?? 0n,\n },\n ],\n })\n } catch (error) {\n throw new SDKError(`Failed to get E3 quote: ${error}`, 'GET_E3_QUOTE_FAILED')\n }\n }\n\n public async getFailureReason(e3Id: bigint): Promise<FailureReason> {\n try {\n return this.publicClient.readContract({\n address: this.contracts.interfold,\n abi: Interfold__factory.abi,\n functionName: 'getFailureReason',\n args: [e3Id],\n })\n } catch (error) {\n throw new SDKError(`Failed to get failure reason: ${error}`, 'GET_FAILURE_REASON_FAILED')\n }\n }\n\n public async getE3PublicKey(e3Id: bigint): Promise<`0x${string}`> {\n try {\n const result: `0x${string}` = await this.publicClient.readContract({\n address: this.contracts.ciphernodeRegistry,\n abi: CiphernodeRegistryOwnable__factory.abi,\n functionName: 'committeePublicKey',\n args: [e3Id],\n })\n\n return result\n } catch (error) {\n throw new SDKError(`Failed to get E3 public key: ${error}`, 'GET_E3_PUBLIC_KEY_FAILED')\n }\n }\n\n public async getE3Stage(e3Id: bigint): Promise<E3Stage> {\n try {\n return this.publicClient.readContract({\n address: this.contracts.interfold,\n abi: Interfold__factory.abi,\n functionName: 'getE3Stage',\n args: [e3Id],\n })\n } catch (error) {\n throw new SDKError(`Failed to get E3 stage: ${error}`, 'GET_E3_STAGE_FAILED')\n }\n }\n\n public async estimateGas(\n functionName: string,\n args: readonly unknown[],\n contractAddress: `0x${string}`,\n abi: Abi,\n value?: bigint,\n ): Promise<bigint> {\n if (!this.walletClient) {\n throw new SDKError('Wallet client required for gas estimation', 'NO_WALLET')\n }\n\n try {\n const account = this.walletClient.account\n if (!account) {\n throw new SDKError('No account connected', 'NO_ACCOUNT')\n }\n\n const estimateParams = {\n address: contractAddress,\n abi,\n functionName,\n args,\n account,\n ...(value !== undefined && { value }),\n }\n\n return await this.publicClient.estimateContractGas(estimateParams)\n } catch (error) {\n throw new SDKError(`Failed to estimate gas: ${error}`, 'GAS_ESTIMATION_FAILED')\n }\n }\n\n public async waitForTransaction(hash: Hash): Promise<TransactionReceipt> {\n try {\n return await this.publicClient.waitForTransactionReceipt({\n hash,\n confirmations: 1,\n })\n } catch (error) {\n throw new SDKError(`Failed to wait for transaction: ${error}`, 'TRANSACTION_WAIT_FAILED')\n }\n }\n}\n","// SPDX-License-Identifier: LGPL-3.0-only\n//\n// This file is provided WITHOUT ANY WARRANTY;\n// without even the implied warranty of MERCHANTABILITY\n// or FITNESS FOR A PARTICULAR PURPOSE.\n\nimport { type Address, type Hash, type Log, PublicClient, encodeAbiParameters } from 'viem'\nimport type { BfvParams } from './types'\n\nexport class SDKError extends Error {\n constructor(\n message: string,\n public readonly code?: string,\n ) {\n super(message)\n this.name = 'SDKError'\n }\n}\n\nexport function isValidAddress(address: string): address is Address {\n return /^0x[a-fA-F0-9]{40}$/.test(address)\n}\n\nexport function isValidHash(hash: string): hash is Hash {\n return /^0x[a-fA-F0-9]{64}$/.test(hash)\n}\n\nexport function formatEventName(contractName: string, eventName: string): string {\n return `${contractName}.${eventName}`\n}\n\nexport function parseEventData<T>(log: Log): T {\n return log.data as unknown as T\n}\n\n/**\n * Sleep for a specified number of milliseconds\n */\nexport const sleep = (ms: number): Promise<void> => {\n return new Promise((resolve) => setTimeout(resolve, ms))\n}\n\nexport function formatBigInt(value: bigint): string {\n return value.toString()\n}\n\nexport function parseBigInt(value: string): bigint {\n return BigInt(value)\n}\n\nexport function generateEventId(log: Log): string {\n return `${log.blockHash}-${log.logIndex}`\n}\n\n/**\n * Get the current timestamp in seconds\n * from onchain\n * @param publicClient - The public client to use\n */\nexport async function getCurrentTimestamp(publicClient: PublicClient): Promise<bigint> {\n const block = await publicClient.getBlock()\n return block.timestamp\n}\n\n// Compute provider parameters structure\nexport interface ComputeProviderParams {\n name: string\n parallel: boolean\n batch_size: number\n}\n\n// Default compute provider configuration\nexport const DEFAULT_COMPUTE_PROVIDER_PARAMS: ComputeProviderParams = {\n name: 'risc0',\n parallel: false,\n batch_size: 2,\n}\n\n// Default E3 configuration (`committeeSize` is `IInterfold.CommitteeSize`, not circuit N_PARTIES).\nexport const DEFAULT_E3_CONFIG = {\n committeeSize: 0, // CommitteeSize.Minimum\n duration: 1800, // 30 minutes in seconds\n payment_amount: '0', // 0 ETH in wei\n} as const\n\n/**\n * Encode BFV parameters for the smart contract\n * BFV (Brakerski-Fan-Vercauteren) is a type of fully homomorphic encryption\n */\nexport function encodeBfvParams(params: BfvParams): `0x${string}` {\n const { degree, plaintextModulus, moduli, error1Variance } = params\n\n if (error1Variance === undefined) {\n throw new SDKError(\n 'error1Variance is required in ProtocolParams. All BFV parameter sets must specify error1_variance.',\n 'MISSING_ERROR1_VARIANCE',\n )\n }\n\n return encodeAbiParameters(\n [\n {\n name: 'bfvParams',\n type: 'tuple',\n components: [\n { name: 'degree', type: 'uint256' },\n { name: 'plaintext_modulus', type: 'uint256' },\n { name: 'moduli', type: 'uint256[]' },\n { name: 'error1_variance', type: 'string' },\n ],\n },\n ],\n [\n {\n degree: BigInt(degree),\n plaintext_modulus: BigInt(plaintextModulus),\n moduli: [...moduli],\n error1_variance: error1Variance,\n },\n ],\n )\n}\n\n/**\n * Encode compute provider parameters for the smart contract'\n * If mock is true, the compute provider parameters will return 32 bytes of 0x00\n */\nexport function encodeComputeProviderParams(params: ComputeProviderParams, mock: boolean = false): `0x${string}` {\n if (mock) {\n return `0x${'00'.repeat(32)}` as `0x${string}`\n }\n\n const jsonString = JSON.stringify(params)\n const encoder = new TextEncoder()\n const bytes = encoder.encode(jsonString)\n\n return `0x${Array.from(bytes, (byte) => byte.toString(16).padStart(2, '0')).join('')}`\n}\n\n/**\n * Encode custom parameters for the smart contract.\n */\nexport function encodeCustomParams(params: Record<string, unknown>): `0x${string}` {\n const jsonString = JSON.stringify(params)\n const encoder = new TextEncoder()\n const bytes = encoder.encode(jsonString)\n\n return `0x${Array.from(bytes, (byte) => byte.toString(16).padStart(2, '0')).join('')}`\n}\n\n// inputWindow[0] is always larger than now and dkg deadline\nexport const inputWindowStartBuffer = 15n\n\n/**\n * Calculate start window for E3 request\n * @dev This function can be used for testing purposes, or for E3s which need to start as soon as possible.\n * @param publicClient - The public client to use\n * @param duration - The duration of the input window in seconds\n * @param startBuffer - Buffer in seconds added to current timestamp for input window start\n */\nexport async function calculateInputWindow(\n publicClient: PublicClient,\n duration: number = DEFAULT_E3_CONFIG.duration,\n startBuffer: bigint = inputWindowStartBuffer,\n): Promise<[bigint, bigint]> {\n const now = await getCurrentTimestamp(publicClient)\n return [BigInt(now) + startBuffer, BigInt(now) + startBuffer + BigInt(duration)]\n}\n\n/**\n * Decode plaintextOutput bytes to get the actual result number\n */\nexport function decodePlaintextOutput(plaintextOutput: string): number | null {\n try {\n // Remove '0x' prefix if present\n const hex = plaintextOutput.startsWith('0x') ? plaintextOutput.slice(2) : plaintextOutput\n\n // Convert hex to bytes\n const bytes = new Uint8Array(hex.match(/.{1,2}/g)?.map((byte) => parseInt(byte, 16)) || [])\n\n if (bytes.length < 8) {\n console.warn('Plaintext output too short for u64 decoding')\n return null\n }\n\n // Decode first u64 (8 bytes) as little-endian\n const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength)\n const result = view.getBigUint64(0, true) // true for little-endian\n\n return Number(result)\n } catch (error) {\n console.error('Failed to decode plaintext output:', error)\n return null\n }\n}\n\n// Helper function to convert proof bytes to field elements\nexport function proofToFields(proof: Uint8Array): string[] {\n const fields: string[] = []\n for (let i = 0; i < proof.length; i += 32) {\n const chunk = proof.slice(i, i + 32)\n fields.push('0x' + Buffer.from(chunk).toString('hex'))\n }\n return fields\n}\n","// SPDX-License-Identifier: LGPL-3.0-only\n//\n// This file is provided WITHOUT ANY WARRANTY;\n// without even the implied warranty of MERCHANTABILITY\n// or FITNESS FOR A PARTICULAR PURPOSE.\n\nimport { SDKError } from '../utils'\n\nexport interface ContractAddresses {\n interfold: `0x${string}`\n ciphernodeRegistry: `0x${string}`\n feeToken: `0x${string}`\n}\n\n/** On-chain `IInterfold.CommitteeSize`: Minimum (N=3), Micro (N=9), Small (N=19). */\nexport enum CommitteeSize {\n Minimum = 0,\n Micro = 1,\n Small = 2,\n}\n\n/** Fail fast on out-of-range committee sizes before they hit the contract. */\nexport function validateCommitteeSize(value: number | CommitteeSize): CommitteeSize {\n if (!Number.isInteger(value) || value < CommitteeSize.Minimum || value > CommitteeSize.Small) {\n throw new SDKError(\n `Invalid committeeSize ${value}. Use CommitteeSize.Minimum (0), CommitteeSize.Micro (1), or CommitteeSize.Small (2).`,\n 'INVALID_COMMITTEE_SIZE',\n )\n }\n return value\n}\n\nexport enum ParamSet {\n Insecure512 = 0,\n Secure8192 = 1,\n}\n\nexport interface E3 {\n seed: bigint\n committeeSize: number\n requestBlock: bigint\n inputWindow: readonly [bigint, bigint]\n encryptionSchemeId: string\n e3Program: string\n paramSet: number\n decryptionVerifier: string\n committeePublicKey: string\n ciphertextOutput: string\n ciphertextCommitment: string\n plaintextOutput: string\n}\n\nexport interface RequestParams {\n gasLimit?: bigint\n}\n\nexport interface E3RequestParams extends RequestParams {\n committeeSize: number\n inputWindow: readonly [bigint, bigint]\n e3Program: `0x${string}`\n paramSet: number\n computeProviderParams: `0x${string}`\n customParams?: `0x${string}`\n /** Maximum fee token amount accepted. Defaults to a fresh quote. */\n maxFee?: bigint\n}\n\nexport enum E3Stage {\n None,\n Requested,\n CommitteeFinalized,\n KeyPublished,\n CiphertextReady,\n Complete,\n Failed,\n}\n\nexport enum FailureReason {\n None,\n CommitteeFormationTimeout,\n InsufficientCommitteeMembers,\n DKGTimeout,\n DKGInvalidShares,\n NoInputsReceived,\n ComputeTimeout,\n ComputeProviderExpired,\n ComputeProviderFailed,\n RequesterCancelled,\n DecryptionTimeout,\n DecryptionInvalidShares,\n VerificationFailed,\n}\n"],"mappings":"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","names":["import_viem","E3Stage","FailureReason"]}
|
|
1
|
+
{"version":3,"sources":["../../src/contracts/index.ts","../../src/contracts/contract-client.ts","../../src/utils.ts","../../src/contracts/types.ts"],"sourcesContent":["// SPDX-License-Identifier: LGPL-3.0-only\n//\n// This file is provided WITHOUT ANY WARRANTY;\n// without even the implied warranty of MERCHANTABILITY\n// or FITNESS FOR A PARTICULAR PURPOSE.\n\nexport { ContractClient } from './contract-client'\nexport type { ContractClientConfig } from './contract-client'\nexport type { ContractAddresses, E3, E3RequestParams } from './types'\nexport { E3Stage, FailureReason } from './types'\n","// SPDX-License-Identifier: LGPL-3.0-only\n//\n// This file is provided WITHOUT ANY WARRANTY;\n// without even the implied warranty of MERCHANTABILITY\n// or FITNESS FOR A PARTICULAR PURPOSE.\n\nimport {\n encodeAbiParameters,\n type Abi,\n type Chain,\n type Hash,\n type PublicClient,\n type TransactionReceipt,\n type WalletClient,\n createPublicClient,\n createWalletClient,\n http,\n webSocket,\n} from 'viem'\nimport { privateKeyToAccount } from 'viem/accounts'\n\nimport { CiphernodeRegistryOwnable__factory, Interfold__factory, InterfoldToken__factory } from '@interfold/contracts/types'\nimport type { CiphertextOutputReference, ContractAddresses, E3, E3RequestParams, E3Stage, FailureReason } from './types'\nimport { validateCommitteeSize } from './types'\nimport { SDKError, cryptoConfigIdForParamSet, isValidAddress } from '../utils'\n\nexport interface ContractClientConfig {\n publicClient: PublicClient\n walletClient?: WalletClient\n contracts: ContractAddresses\n}\n\nexport class ContractClient {\n private publicClient: PublicClient\n private walletClient?: WalletClient\n private contracts: ContractAddresses\n private contractInfo: {\n interfold: { address: `0x${string}`; abi: Abi }\n ciphernodeRegistry: { address: `0x${string}`; abi: Abi }\n feeToken: { address: `0x${string}`; abi: Abi }\n }\n\n constructor(config: ContractClientConfig) {\n const { publicClient, walletClient, contracts } = config\n\n if (!isValidAddress(contracts.interfold)) {\n throw new SDKError('Invalid Interfold contract address', 'INVALID_ADDRESS')\n }\n if (!isValidAddress(contracts.ciphernodeRegistry)) {\n throw new SDKError('Invalid CiphernodeRegistry contract address', 'INVALID_ADDRESS')\n }\n if (!isValidAddress(contracts.feeToken)) {\n throw new SDKError('Invalid FeeToken contract address', 'INVALID_ADDRESS')\n }\n\n this.publicClient = publicClient\n this.walletClient = walletClient\n this.contracts = contracts\n\n this.contractInfo = {\n interfold: {\n address: contracts.interfold,\n abi: Interfold__factory.abi,\n },\n ciphernodeRegistry: {\n address: contracts.ciphernodeRegistry,\n abi: CiphernodeRegistryOwnable__factory.abi,\n },\n feeToken: {\n address: contracts.feeToken,\n abi: InterfoldToken__factory.abi,\n },\n }\n }\n\n public static create(options: {\n rpcUrl: string\n contracts: ContractAddresses\n privateKey?: `0x${string}`\n chain: Chain\n }): ContractClient {\n const isWebSocket = options.rpcUrl.startsWith('ws://') || options.rpcUrl.startsWith('wss://')\n const transport = isWebSocket\n ? webSocket(options.rpcUrl, {\n keepAlive: { interval: 30_000 },\n reconnect: { attempts: 5, delay: 2_000 },\n })\n : http(options.rpcUrl)\n\n const publicClient = createPublicClient({\n chain: options.chain,\n transport,\n }) as PublicClient\n\n let walletClient: WalletClient | undefined\n if (options.privateKey) {\n const account = privateKeyToAccount(options.privateKey)\n walletClient = createWalletClient({\n account,\n chain: options.chain,\n transport,\n })\n }\n\n return new ContractClient({ publicClient, walletClient, contracts: options.contracts })\n }\n\n public getPublicClient(): PublicClient {\n return this.publicClient\n }\n\n public async approveFeeToken(amount: bigint): Promise<Hash> {\n if (!this.walletClient) {\n throw new SDKError('Wallet client required for write operations', 'NO_WALLET')\n }\n\n try {\n const account = this.walletClient.account\n if (!account) {\n throw new SDKError('No account connected', 'NO_ACCOUNT')\n }\n\n const { request } = await this.publicClient.simulateContract({\n address: this.contracts.feeToken,\n abi: InterfoldToken__factory.abi,\n functionName: 'approve',\n args: [this.contracts.interfold, amount],\n account,\n })\n\n return await this.walletClient.writeContract(request)\n } catch (error) {\n throw new SDKError(`Failed to approve fee token: ${error}`, 'APPROVE_FEE_TOKEN_FAILED')\n }\n }\n\n public async requestE3(params: E3RequestParams): Promise<Hash> {\n if (!this.walletClient) {\n throw new SDKError('Wallet client required for write operations', 'NO_WALLET')\n }\n\n try {\n const account = this.walletClient.account\n if (!account) {\n throw new SDKError('No account connected', 'NO_ACCOUNT')\n }\n\n const committeeSize = validateCommitteeSize(params.committeeSize)\n const maxFee = params.maxFee ?? (await this.getE3Quote(params))\n const expectedCryptoConfigId = cryptoConfigIdForParamSet(params.paramSet)\n\n const { request } = await this.publicClient.simulateContract({\n address: this.contracts.interfold,\n abi: Interfold__factory.abi,\n functionName: 'request',\n args: [\n {\n committeeSize,\n inputWindow: params.inputWindow,\n e3Program: params.e3Program,\n paramSet: params.paramSet,\n computeProviderParams: params.computeProviderParams,\n customParams: params.customParams || '0x',\n expectedFeeToken: this.contracts.feeToken,\n expectedCryptoConfigId,\n maxFee,\n },\n ],\n account,\n gas: params.gasLimit,\n })\n\n return await this.walletClient.writeContract(request)\n } catch (error) {\n throw new SDKError(`Failed to request E3: ${error}`, 'REQUEST_E3_FAILED')\n }\n }\n\n public async cancelE3(e3Id: bigint): Promise<Hash> {\n if (!this.walletClient) {\n throw new SDKError('Wallet client required for write operations', 'NO_WALLET')\n }\n const account = this.walletClient.account\n if (!account) {\n throw new SDKError('No account connected', 'NO_ACCOUNT')\n }\n\n try {\n const { request } = await this.publicClient.simulateContract({\n address: this.contracts.interfold,\n abi: Interfold__factory.abi,\n functionName: 'cancelE3',\n args: [e3Id],\n account,\n })\n\n return await this.walletClient.writeContract(request)\n } catch (error) {\n throw new SDKError(`Failed to cancel E3: ${error}`, 'CANCEL_E3_FAILED')\n }\n }\n\n public async publishCiphertextOutput(e3Id: bigint, outputReference: CiphertextOutputReference, gasLimit?: bigint): Promise<Hash> {\n if (!this.walletClient) {\n throw new SDKError('Wallet client required for write operations', 'NO_WALLET')\n }\n\n try {\n const account = this.walletClient.account\n if (!account) {\n throw new SDKError('No account connected', 'NO_ACCOUNT')\n }\n\n const encodedOutputReference = encodeAbiParameters(\n [\n {\n type: 'tuple',\n components: [\n { name: 'contentHash', type: 'bytes32' },\n { name: 'ciphertextCommitment', type: 'bytes32' },\n { name: 'computeProof', type: 'bytes' },\n { name: 'availabilityProof', type: 'bytes' },\n ],\n },\n ],\n [outputReference],\n )\n\n const { request } = await this.publicClient.simulateContract({\n address: this.contracts.interfold,\n abi: Interfold__factory.abi,\n functionName: 'publishCiphertextOutput',\n args: [e3Id, encodedOutputReference],\n account,\n gas: gasLimit,\n })\n\n return await this.walletClient.writeContract(request)\n } catch (error) {\n throw new SDKError(`Failed to publish ciphertext output: ${error}`, 'PUBLISH_CIPHERTEXT_OUTPUT_FAILED')\n }\n }\n\n public async getE3(e3Id: bigint): Promise<E3> {\n try {\n const result: E3 = await this.publicClient.readContract({\n address: this.contracts.interfold,\n abi: Interfold__factory.abi,\n functionName: 'getE3',\n args: [e3Id],\n })\n\n return result\n } catch (error) {\n throw new SDKError(`Failed to get E3: ${error}`, 'GET_E3_FAILED')\n }\n }\n\n public async getE3Quote(requestParams: E3RequestParams): Promise<bigint> {\n try {\n const committeeSize = validateCommitteeSize(requestParams.committeeSize)\n const expectedCryptoConfigId = cryptoConfigIdForParamSet(requestParams.paramSet)\n\n return this.publicClient.readContract({\n address: this.contracts.interfold,\n abi: Interfold__factory.abi,\n functionName: 'getE3Quote',\n args: [\n {\n committeeSize,\n inputWindow: requestParams.inputWindow,\n e3Program: requestParams.e3Program,\n paramSet: requestParams.paramSet,\n computeProviderParams: requestParams.computeProviderParams,\n customParams: requestParams.customParams || '0x',\n expectedFeeToken: this.contracts.feeToken,\n expectedCryptoConfigId,\n maxFee: requestParams.maxFee ?? 0n,\n },\n ],\n })\n } catch (error) {\n throw new SDKError(`Failed to get E3 quote: ${error}`, 'GET_E3_QUOTE_FAILED')\n }\n }\n\n public async getFailureReason(e3Id: bigint): Promise<FailureReason> {\n try {\n return this.publicClient.readContract({\n address: this.contracts.interfold,\n abi: Interfold__factory.abi,\n functionName: 'getFailureReason',\n args: [e3Id],\n })\n } catch (error) {\n throw new SDKError(`Failed to get failure reason: ${error}`, 'GET_FAILURE_REASON_FAILED')\n }\n }\n\n public async getE3PublicKey(e3Id: bigint): Promise<`0x${string}`> {\n try {\n const result: `0x${string}` = await this.publicClient.readContract({\n address: this.contracts.ciphernodeRegistry,\n abi: CiphernodeRegistryOwnable__factory.abi,\n functionName: 'committeePublicKey',\n args: [e3Id],\n })\n\n return result\n } catch (error) {\n throw new SDKError(`Failed to get E3 public key: ${error}`, 'GET_E3_PUBLIC_KEY_FAILED')\n }\n }\n\n public async getE3Stage(e3Id: bigint): Promise<E3Stage> {\n try {\n return this.publicClient.readContract({\n address: this.contracts.interfold,\n abi: Interfold__factory.abi,\n functionName: 'getE3Stage',\n args: [e3Id],\n })\n } catch (error) {\n throw new SDKError(`Failed to get E3 stage: ${error}`, 'GET_E3_STAGE_FAILED')\n }\n }\n\n public async estimateGas(\n functionName: string,\n args: readonly unknown[],\n contractAddress: `0x${string}`,\n abi: Abi,\n value?: bigint,\n ): Promise<bigint> {\n if (!this.walletClient) {\n throw new SDKError('Wallet client required for gas estimation', 'NO_WALLET')\n }\n\n try {\n const account = this.walletClient.account\n if (!account) {\n throw new SDKError('No account connected', 'NO_ACCOUNT')\n }\n\n const estimateParams = {\n address: contractAddress,\n abi,\n functionName,\n args,\n account,\n ...(value !== undefined && { value }),\n }\n\n return await this.publicClient.estimateContractGas(estimateParams)\n } catch (error) {\n throw new SDKError(`Failed to estimate gas: ${error}`, 'GAS_ESTIMATION_FAILED')\n }\n }\n\n public async waitForTransaction(hash: Hash): Promise<TransactionReceipt> {\n try {\n return await this.publicClient.waitForTransactionReceipt({\n hash,\n confirmations: 1,\n })\n } catch (error) {\n throw new SDKError(`Failed to wait for transaction: ${error}`, 'TRANSACTION_WAIT_FAILED')\n }\n }\n}\n","// SPDX-License-Identifier: LGPL-3.0-only\n//\n// This file is provided WITHOUT ANY WARRANTY;\n// without even the implied warranty of MERCHANTABILITY\n// or FITNESS FOR A PARTICULAR PURPOSE.\n\nimport { type Address, type Hash, type Log, PublicClient, encodeAbiParameters } from 'viem'\nimport type { BfvParams } from './types'\n\nexport class SDKError extends Error {\n constructor(\n message: string,\n public readonly code?: string,\n ) {\n super(message)\n this.name = 'SDKError'\n }\n}\n\nexport function isValidAddress(address: string): address is Address {\n return /^0x[a-fA-F0-9]{40}$/.test(address)\n}\n\nexport function isValidHash(hash: string): hash is Hash {\n return /^0x[a-fA-F0-9]{64}$/.test(hash)\n}\n\nexport function formatEventName(contractName: string, eventName: string): string {\n return `${contractName}.${eventName}`\n}\n\nexport function parseEventData<T>(log: Log): T {\n return log.data as unknown as T\n}\n\n/**\n * Sleep for a specified number of milliseconds\n */\nexport const sleep = (ms: number): Promise<void> => {\n return new Promise((resolve) => setTimeout(resolve, ms))\n}\n\nexport function formatBigInt(value: bigint): string {\n return value.toString()\n}\n\nexport function parseBigInt(value: string): bigint {\n return BigInt(value)\n}\n\nexport function generateEventId(log: Log): string {\n return `${log.blockHash}-${log.logIndex}`\n}\n\n/**\n * Get the current timestamp in seconds\n * from onchain\n * @param publicClient - The public client to use\n */\nexport async function getCurrentTimestamp(publicClient: PublicClient): Promise<bigint> {\n const block = await publicClient.getBlock()\n return block.timestamp\n}\n\n// Compute provider parameters structure\nexport interface ComputeProviderParams {\n name: string\n parallel: boolean\n batch_size: number\n}\n\n// Default compute provider configuration\nexport const DEFAULT_COMPUTE_PROVIDER_PARAMS: ComputeProviderParams = {\n name: 'risc0',\n parallel: false,\n batch_size: 2,\n}\n\n// Default E3 configuration (`committeeSize` is `IInterfold.CommitteeSize`, not circuit N_PARTIES).\nexport const DEFAULT_E3_CONFIG = {\n committeeSize: 0, // CommitteeSize.Minimum\n duration: 1800, // 30 minutes in seconds\n payment_amount: '0', // 0 ETH in wei\n} as const\n\nexport function cryptoConfigIdForParamSet(paramSet: number): Hash {\n if (paramSet === 0) {\n return '0x04f3677e73b0f5066d6caf5cbd92e3fb2e38338edaf5cfc971ab28f7b684da78'\n }\n if (paramSet === 1) {\n return '0xd9c86e581f8291ffb5b63595600e8d096ed30b16e2e0a6634a76c22b1f58fb4e'\n }\n throw new SDKError(`Unsupported BFV parameter set: ${paramSet}`, 'UNSUPPORTED_CRYPTO_CONFIG')\n}\n\n/**\n * Encode BFV parameters for the smart contract\n * BFV (Brakerski-Fan-Vercauteren) is a type of fully homomorphic encryption\n */\nexport function encodeBfvParams(params: BfvParams): `0x${string}` {\n const { degree, plaintextModulus, moduli, error1Variance } = params\n\n if (error1Variance === undefined) {\n throw new SDKError(\n 'error1Variance is required in ProtocolParams. All BFV parameter sets must specify error1_variance.',\n 'MISSING_ERROR1_VARIANCE',\n )\n }\n\n return encodeAbiParameters(\n [\n {\n name: 'bfvParams',\n type: 'tuple',\n components: [\n { name: 'degree', type: 'uint256' },\n { name: 'plaintext_modulus', type: 'uint256' },\n { name: 'moduli', type: 'uint256[]' },\n { name: 'error1_variance', type: 'string' },\n ],\n },\n ],\n [\n {\n degree: BigInt(degree),\n plaintext_modulus: BigInt(plaintextModulus),\n moduli: [...moduli],\n error1_variance: error1Variance,\n },\n ],\n )\n}\n\n/**\n * Encode compute provider parameters for the smart contract'\n * If mock is true, the compute provider parameters will return 32 bytes of 0x00\n */\nexport function encodeComputeProviderParams(params: ComputeProviderParams, mock: boolean = false): `0x${string}` {\n if (mock) {\n return `0x${'00'.repeat(32)}` as `0x${string}`\n }\n\n const jsonString = JSON.stringify(params)\n const encoder = new TextEncoder()\n const bytes = encoder.encode(jsonString)\n\n return `0x${Array.from(bytes, (byte) => byte.toString(16).padStart(2, '0')).join('')}`\n}\n\n/**\n * Encode custom parameters for the smart contract.\n */\nexport function encodeCustomParams(params: Record<string, unknown>): `0x${string}` {\n const jsonString = JSON.stringify(params)\n const encoder = new TextEncoder()\n const bytes = encoder.encode(jsonString)\n\n return `0x${Array.from(bytes, (byte) => byte.toString(16).padStart(2, '0')).join('')}`\n}\n\n// inputWindow[0] is always larger than now and dkg deadline\nexport const inputWindowStartBuffer = 15n\n\n/**\n * Calculate start window for E3 request\n * @dev This function can be used for testing purposes, or for E3s which need to start as soon as possible.\n * @param publicClient - The public client to use\n * @param duration - The duration of the input window in seconds\n * @param startBuffer - Buffer in seconds added to current timestamp for input window start\n */\nexport async function calculateInputWindow(\n publicClient: PublicClient,\n duration: number = DEFAULT_E3_CONFIG.duration,\n startBuffer: bigint = inputWindowStartBuffer,\n): Promise<[bigint, bigint]> {\n const now = await getCurrentTimestamp(publicClient)\n return [BigInt(now) + startBuffer, BigInt(now) + startBuffer + BigInt(duration)]\n}\n\n/**\n * Decode plaintextOutput bytes to get the actual result number\n */\nexport function decodePlaintextOutput(plaintextOutput: string): number | null {\n try {\n // Remove '0x' prefix if present\n const hex = plaintextOutput.startsWith('0x') ? plaintextOutput.slice(2) : plaintextOutput\n\n // Convert hex to bytes\n const bytes = new Uint8Array(hex.match(/.{1,2}/g)?.map((byte) => parseInt(byte, 16)) || [])\n\n if (bytes.length < 8) {\n console.warn('Plaintext output too short for u64 decoding')\n return null\n }\n\n // Decode first u64 (8 bytes) as little-endian\n const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength)\n const result = view.getBigUint64(0, true) // true for little-endian\n\n return Number(result)\n } catch (error) {\n console.error('Failed to decode plaintext output:', error)\n return null\n }\n}\n\n// Helper function to convert proof bytes to field elements\nexport function proofToFields(proof: Uint8Array): string[] {\n const fields: string[] = []\n for (let i = 0; i < proof.length; i += 32) {\n const chunk = proof.slice(i, i + 32)\n fields.push('0x' + Buffer.from(chunk).toString('hex'))\n }\n return fields\n}\n","// SPDX-License-Identifier: LGPL-3.0-only\n//\n// This file is provided WITHOUT ANY WARRANTY;\n// without even the implied warranty of MERCHANTABILITY\n// or FITNESS FOR A PARTICULAR PURPOSE.\n\nimport { SDKError } from '../utils'\n\nexport interface ContractAddresses {\n interfold: `0x${string}`\n ciphernodeRegistry: `0x${string}`\n feeToken: `0x${string}`\n}\n\n/** On-chain `IInterfold.CommitteeSize`: Minimum (N=3), Micro (N=9), Small (N=19). */\nexport enum CommitteeSize {\n Minimum = 0,\n Micro = 1,\n Small = 2,\n}\n\n/** Fail fast on out-of-range committee sizes before they hit the contract. */\nexport function validateCommitteeSize(value: number | CommitteeSize): CommitteeSize {\n if (!Number.isInteger(value) || value < CommitteeSize.Minimum || value > CommitteeSize.Small) {\n throw new SDKError(\n `Invalid committeeSize ${value}. Use CommitteeSize.Minimum (0), CommitteeSize.Micro (1), or CommitteeSize.Small (2).`,\n 'INVALID_COMMITTEE_SIZE',\n )\n }\n return value\n}\n\nexport enum ParamSet {\n Insecure512 = 0,\n Secure8192 = 1,\n}\n\nexport interface E3 {\n seed: bigint\n committeeSize: number\n requestBlock: bigint\n inputWindow: readonly [bigint, bigint]\n encryptionSchemeId: string\n e3Program: string\n paramSet: number\n decryptionVerifier: string\n committeePublicKey: string\n ciphertextOutput: string\n ciphertextCommitment: string\n plaintextOutput: string\n}\n\nexport interface RequestParams {\n gasLimit?: bigint\n}\n\nexport interface E3RequestParams extends RequestParams {\n committeeSize: number\n inputWindow: readonly [bigint, bigint]\n e3Program: `0x${string}`\n paramSet: number\n computeProviderParams: `0x${string}`\n customParams?: `0x${string}`\n /** Maximum fee token amount accepted. Defaults to a fresh quote. */\n maxFee?: bigint\n}\n\n/** Proof-backed reference to an aggregate ciphertext published on the configured DA layer. */\nexport interface CiphertextOutputReference {\n contentHash: `0x${string}`\n ciphertextCommitment: `0x${string}`\n computeProof: `0x${string}`\n availabilityProof: `0x${string}`\n}\n\nexport enum E3Stage {\n None,\n Requested,\n CommitteeFinalized,\n KeyPublished,\n CiphertextReady,\n Complete,\n Failed,\n}\n\nexport enum FailureReason {\n None,\n CommitteeFormationTimeout,\n InsufficientCommitteeMembers,\n DKGTimeout,\n DKGInvalidShares,\n NoInputsReceived,\n ComputeTimeout,\n ComputeProviderExpired,\n ComputeProviderFailed,\n RequesterCancelled,\n DecryptionTimeout,\n DecryptionInvalidShares,\n VerificationFailed,\n}\n"],"mappings":"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","names":["import_viem","E3Stage","FailureReason"]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { PublicClient, WalletClient, Chain, Hash, Abi, TransactionReceipt } from 'viem';
|
|
2
|
-
import { C as ContractAddresses, E as E3RequestParams, a as E3, F as FailureReason,
|
|
2
|
+
import { C as ContractAddresses, E as E3RequestParams, a as CiphertextOutputReference, b as E3, F as FailureReason, c as E3Stage } from '../types-BJe3EYvv.js';
|
|
3
3
|
|
|
4
4
|
interface ContractClientConfig {
|
|
5
5
|
publicClient: PublicClient;
|
|
@@ -22,7 +22,7 @@ declare class ContractClient {
|
|
|
22
22
|
approveFeeToken(amount: bigint): Promise<Hash>;
|
|
23
23
|
requestE3(params: E3RequestParams): Promise<Hash>;
|
|
24
24
|
cancelE3(e3Id: bigint): Promise<Hash>;
|
|
25
|
-
publishCiphertextOutput(e3Id: bigint,
|
|
25
|
+
publishCiphertextOutput(e3Id: bigint, outputReference: CiphertextOutputReference, gasLimit?: bigint): Promise<Hash>;
|
|
26
26
|
getE3(e3Id: bigint): Promise<E3>;
|
|
27
27
|
getE3Quote(requestParams: E3RequestParams): Promise<bigint>;
|
|
28
28
|
getFailureReason(e3Id: bigint): Promise<FailureReason>;
|
package/dist/contracts/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// src/contracts/contract-client.ts
|
|
2
2
|
import {
|
|
3
|
+
encodeAbiParameters as encodeAbiParameters2,
|
|
3
4
|
createPublicClient,
|
|
4
5
|
createWalletClient,
|
|
5
6
|
http,
|
|
@@ -20,6 +21,15 @@ var SDKError = class extends Error {
|
|
|
20
21
|
function isValidAddress(address) {
|
|
21
22
|
return /^0x[a-fA-F0-9]{40}$/.test(address);
|
|
22
23
|
}
|
|
24
|
+
function cryptoConfigIdForParamSet(paramSet) {
|
|
25
|
+
if (paramSet === 0) {
|
|
26
|
+
return "0x04f3677e73b0f5066d6caf5cbd92e3fb2e38338edaf5cfc971ab28f7b684da78";
|
|
27
|
+
}
|
|
28
|
+
if (paramSet === 1) {
|
|
29
|
+
return "0xd9c86e581f8291ffb5b63595600e8d096ed30b16e2e0a6634a76c22b1f58fb4e";
|
|
30
|
+
}
|
|
31
|
+
throw new SDKError(`Unsupported BFV parameter set: ${paramSet}`, "UNSUPPORTED_CRYPTO_CONFIG");
|
|
32
|
+
}
|
|
23
33
|
|
|
24
34
|
// src/contracts/types.ts
|
|
25
35
|
function validateCommitteeSize(value) {
|
|
@@ -149,11 +159,7 @@ var ContractClient = class _ContractClient {
|
|
|
149
159
|
}
|
|
150
160
|
const committeeSize = validateCommitteeSize(params.committeeSize);
|
|
151
161
|
const maxFee = params.maxFee ?? await this.getE3Quote(params);
|
|
152
|
-
const expectedCryptoConfigId =
|
|
153
|
-
address: this.contracts.interfold,
|
|
154
|
-
abi: Interfold__factory.abi,
|
|
155
|
-
functionName: "activeCryptoConfigId"
|
|
156
|
-
});
|
|
162
|
+
const expectedCryptoConfigId = cryptoConfigIdForParamSet(params.paramSet);
|
|
157
163
|
const { request } = await this.publicClient.simulateContract({
|
|
158
164
|
address: this.contracts.interfold,
|
|
159
165
|
abi: Interfold__factory.abi,
|
|
@@ -200,7 +206,7 @@ var ContractClient = class _ContractClient {
|
|
|
200
206
|
throw new SDKError(`Failed to cancel E3: ${error}`, "CANCEL_E3_FAILED");
|
|
201
207
|
}
|
|
202
208
|
}
|
|
203
|
-
async publishCiphertextOutput(e3Id,
|
|
209
|
+
async publishCiphertextOutput(e3Id, outputReference, gasLimit) {
|
|
204
210
|
if (!this.walletClient) {
|
|
205
211
|
throw new SDKError("Wallet client required for write operations", "NO_WALLET");
|
|
206
212
|
}
|
|
@@ -209,11 +215,25 @@ var ContractClient = class _ContractClient {
|
|
|
209
215
|
if (!account) {
|
|
210
216
|
throw new SDKError("No account connected", "NO_ACCOUNT");
|
|
211
217
|
}
|
|
218
|
+
const encodedOutputReference = encodeAbiParameters2(
|
|
219
|
+
[
|
|
220
|
+
{
|
|
221
|
+
type: "tuple",
|
|
222
|
+
components: [
|
|
223
|
+
{ name: "contentHash", type: "bytes32" },
|
|
224
|
+
{ name: "ciphertextCommitment", type: "bytes32" },
|
|
225
|
+
{ name: "computeProof", type: "bytes" },
|
|
226
|
+
{ name: "availabilityProof", type: "bytes" }
|
|
227
|
+
]
|
|
228
|
+
}
|
|
229
|
+
],
|
|
230
|
+
[outputReference]
|
|
231
|
+
);
|
|
212
232
|
const { request } = await this.publicClient.simulateContract({
|
|
213
233
|
address: this.contracts.interfold,
|
|
214
234
|
abi: Interfold__factory.abi,
|
|
215
235
|
functionName: "publishCiphertextOutput",
|
|
216
|
-
args: [e3Id,
|
|
236
|
+
args: [e3Id, encodedOutputReference],
|
|
217
237
|
account,
|
|
218
238
|
gas: gasLimit
|
|
219
239
|
});
|
|
@@ -238,11 +258,7 @@ var ContractClient = class _ContractClient {
|
|
|
238
258
|
async getE3Quote(requestParams) {
|
|
239
259
|
try {
|
|
240
260
|
const committeeSize = validateCommitteeSize(requestParams.committeeSize);
|
|
241
|
-
const expectedCryptoConfigId =
|
|
242
|
-
address: this.contracts.interfold,
|
|
243
|
-
abi: Interfold__factory.abi,
|
|
244
|
-
functionName: "activeCryptoConfigId"
|
|
245
|
-
});
|
|
261
|
+
const expectedCryptoConfigId = cryptoConfigIdForParamSet(requestParams.paramSet);
|
|
246
262
|
return this.publicClient.readContract({
|
|
247
263
|
address: this.contracts.interfold,
|
|
248
264
|
abi: Interfold__factory.abi,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/contracts/contract-client.ts","../../src/utils.ts","../../src/contracts/types.ts"],"sourcesContent":["// SPDX-License-Identifier: LGPL-3.0-only\n//\n// This file is provided WITHOUT ANY WARRANTY;\n// without even the implied warranty of MERCHANTABILITY\n// or FITNESS FOR A PARTICULAR PURPOSE.\n\nimport {\n type Abi,\n type Chain,\n type Hash,\n type PublicClient,\n type TransactionReceipt,\n type WalletClient,\n createPublicClient,\n createWalletClient,\n http,\n webSocket,\n} from 'viem'\nimport { privateKeyToAccount } from 'viem/accounts'\n\nimport { CiphernodeRegistryOwnable__factory, Interfold__factory, InterfoldToken__factory } from '@interfold/contracts/types'\nimport type { ContractAddresses, E3, E3RequestParams, E3Stage, FailureReason } from './types'\nimport { validateCommitteeSize } from './types'\nimport { SDKError, isValidAddress } from '../utils'\n\nexport interface ContractClientConfig {\n publicClient: PublicClient\n walletClient?: WalletClient\n contracts: ContractAddresses\n}\n\nexport class ContractClient {\n private publicClient: PublicClient\n private walletClient?: WalletClient\n private contracts: ContractAddresses\n private contractInfo: {\n interfold: { address: `0x${string}`; abi: Abi }\n ciphernodeRegistry: { address: `0x${string}`; abi: Abi }\n feeToken: { address: `0x${string}`; abi: Abi }\n }\n\n constructor(config: ContractClientConfig) {\n const { publicClient, walletClient, contracts } = config\n\n if (!isValidAddress(contracts.interfold)) {\n throw new SDKError('Invalid Interfold contract address', 'INVALID_ADDRESS')\n }\n if (!isValidAddress(contracts.ciphernodeRegistry)) {\n throw new SDKError('Invalid CiphernodeRegistry contract address', 'INVALID_ADDRESS')\n }\n if (!isValidAddress(contracts.feeToken)) {\n throw new SDKError('Invalid FeeToken contract address', 'INVALID_ADDRESS')\n }\n\n this.publicClient = publicClient\n this.walletClient = walletClient\n this.contracts = contracts\n\n this.contractInfo = {\n interfold: {\n address: contracts.interfold,\n abi: Interfold__factory.abi,\n },\n ciphernodeRegistry: {\n address: contracts.ciphernodeRegistry,\n abi: CiphernodeRegistryOwnable__factory.abi,\n },\n feeToken: {\n address: contracts.feeToken,\n abi: InterfoldToken__factory.abi,\n },\n }\n }\n\n public static create(options: {\n rpcUrl: string\n contracts: ContractAddresses\n privateKey?: `0x${string}`\n chain: Chain\n }): ContractClient {\n const isWebSocket = options.rpcUrl.startsWith('ws://') || options.rpcUrl.startsWith('wss://')\n const transport = isWebSocket\n ? webSocket(options.rpcUrl, {\n keepAlive: { interval: 30_000 },\n reconnect: { attempts: 5, delay: 2_000 },\n })\n : http(options.rpcUrl)\n\n const publicClient = createPublicClient({\n chain: options.chain,\n transport,\n }) as PublicClient\n\n let walletClient: WalletClient | undefined\n if (options.privateKey) {\n const account = privateKeyToAccount(options.privateKey)\n walletClient = createWalletClient({\n account,\n chain: options.chain,\n transport,\n })\n }\n\n return new ContractClient({ publicClient, walletClient, contracts: options.contracts })\n }\n\n public getPublicClient(): PublicClient {\n return this.publicClient\n }\n\n public async approveFeeToken(amount: bigint): Promise<Hash> {\n if (!this.walletClient) {\n throw new SDKError('Wallet client required for write operations', 'NO_WALLET')\n }\n\n try {\n const account = this.walletClient.account\n if (!account) {\n throw new SDKError('No account connected', 'NO_ACCOUNT')\n }\n\n const { request } = await this.publicClient.simulateContract({\n address: this.contracts.feeToken,\n abi: InterfoldToken__factory.abi,\n functionName: 'approve',\n args: [this.contracts.interfold, amount],\n account,\n })\n\n return await this.walletClient.writeContract(request)\n } catch (error) {\n throw new SDKError(`Failed to approve fee token: ${error}`, 'APPROVE_FEE_TOKEN_FAILED')\n }\n }\n\n public async requestE3(params: E3RequestParams): Promise<Hash> {\n if (!this.walletClient) {\n throw new SDKError('Wallet client required for write operations', 'NO_WALLET')\n }\n\n try {\n const account = this.walletClient.account\n if (!account) {\n throw new SDKError('No account connected', 'NO_ACCOUNT')\n }\n\n const committeeSize = validateCommitteeSize(params.committeeSize)\n const maxFee = params.maxFee ?? (await this.getE3Quote(params))\n const expectedCryptoConfigId = await this.publicClient.readContract({\n address: this.contracts.interfold,\n abi: Interfold__factory.abi,\n functionName: 'activeCryptoConfigId',\n })\n\n const { request } = await this.publicClient.simulateContract({\n address: this.contracts.interfold,\n abi: Interfold__factory.abi,\n functionName: 'request',\n args: [\n {\n committeeSize,\n inputWindow: params.inputWindow,\n e3Program: params.e3Program,\n paramSet: params.paramSet,\n computeProviderParams: params.computeProviderParams,\n customParams: params.customParams || '0x',\n expectedFeeToken: this.contracts.feeToken,\n expectedCryptoConfigId,\n maxFee,\n },\n ],\n account,\n gas: params.gasLimit,\n })\n\n return await this.walletClient.writeContract(request)\n } catch (error) {\n throw new SDKError(`Failed to request E3: ${error}`, 'REQUEST_E3_FAILED')\n }\n }\n\n public async cancelE3(e3Id: bigint): Promise<Hash> {\n if (!this.walletClient) {\n throw new SDKError('Wallet client required for write operations', 'NO_WALLET')\n }\n const account = this.walletClient.account\n if (!account) {\n throw new SDKError('No account connected', 'NO_ACCOUNT')\n }\n\n try {\n const { request } = await this.publicClient.simulateContract({\n address: this.contracts.interfold,\n abi: Interfold__factory.abi,\n functionName: 'cancelE3',\n args: [e3Id],\n account,\n })\n\n return await this.walletClient.writeContract(request)\n } catch (error) {\n throw new SDKError(`Failed to cancel E3: ${error}`, 'CANCEL_E3_FAILED')\n }\n }\n\n public async publishCiphertextOutput(\n e3Id: bigint,\n ciphertextOutput: `0x${string}`,\n ciphertextCommitment: `0x${string}`,\n proof: `0x${string}`,\n gasLimit?: bigint,\n ): Promise<Hash> {\n if (!this.walletClient) {\n throw new SDKError('Wallet client required for write operations', 'NO_WALLET')\n }\n\n try {\n const account = this.walletClient.account\n if (!account) {\n throw new SDKError('No account connected', 'NO_ACCOUNT')\n }\n\n const { request } = await this.publicClient.simulateContract({\n address: this.contracts.interfold,\n abi: Interfold__factory.abi,\n functionName: 'publishCiphertextOutput',\n args: [e3Id, ciphertextOutput, ciphertextCommitment, proof],\n account,\n gas: gasLimit,\n })\n\n return await this.walletClient.writeContract(request)\n } catch (error) {\n throw new SDKError(`Failed to publish ciphertext output: ${error}`, 'PUBLISH_CIPHERTEXT_OUTPUT_FAILED')\n }\n }\n\n public async getE3(e3Id: bigint): Promise<E3> {\n try {\n const result: E3 = await this.publicClient.readContract({\n address: this.contracts.interfold,\n abi: Interfold__factory.abi,\n functionName: 'getE3',\n args: [e3Id],\n })\n\n return result\n } catch (error) {\n throw new SDKError(`Failed to get E3: ${error}`, 'GET_E3_FAILED')\n }\n }\n\n public async getE3Quote(requestParams: E3RequestParams): Promise<bigint> {\n try {\n const committeeSize = validateCommitteeSize(requestParams.committeeSize)\n const expectedCryptoConfigId = await this.publicClient.readContract({\n address: this.contracts.interfold,\n abi: Interfold__factory.abi,\n functionName: 'activeCryptoConfigId',\n })\n\n return this.publicClient.readContract({\n address: this.contracts.interfold,\n abi: Interfold__factory.abi,\n functionName: 'getE3Quote',\n args: [\n {\n committeeSize,\n inputWindow: requestParams.inputWindow,\n e3Program: requestParams.e3Program,\n paramSet: requestParams.paramSet,\n computeProviderParams: requestParams.computeProviderParams,\n customParams: requestParams.customParams || '0x',\n expectedFeeToken: this.contracts.feeToken,\n expectedCryptoConfigId,\n maxFee: requestParams.maxFee ?? 0n,\n },\n ],\n })\n } catch (error) {\n throw new SDKError(`Failed to get E3 quote: ${error}`, 'GET_E3_QUOTE_FAILED')\n }\n }\n\n public async getFailureReason(e3Id: bigint): Promise<FailureReason> {\n try {\n return this.publicClient.readContract({\n address: this.contracts.interfold,\n abi: Interfold__factory.abi,\n functionName: 'getFailureReason',\n args: [e3Id],\n })\n } catch (error) {\n throw new SDKError(`Failed to get failure reason: ${error}`, 'GET_FAILURE_REASON_FAILED')\n }\n }\n\n public async getE3PublicKey(e3Id: bigint): Promise<`0x${string}`> {\n try {\n const result: `0x${string}` = await this.publicClient.readContract({\n address: this.contracts.ciphernodeRegistry,\n abi: CiphernodeRegistryOwnable__factory.abi,\n functionName: 'committeePublicKey',\n args: [e3Id],\n })\n\n return result\n } catch (error) {\n throw new SDKError(`Failed to get E3 public key: ${error}`, 'GET_E3_PUBLIC_KEY_FAILED')\n }\n }\n\n public async getE3Stage(e3Id: bigint): Promise<E3Stage> {\n try {\n return this.publicClient.readContract({\n address: this.contracts.interfold,\n abi: Interfold__factory.abi,\n functionName: 'getE3Stage',\n args: [e3Id],\n })\n } catch (error) {\n throw new SDKError(`Failed to get E3 stage: ${error}`, 'GET_E3_STAGE_FAILED')\n }\n }\n\n public async estimateGas(\n functionName: string,\n args: readonly unknown[],\n contractAddress: `0x${string}`,\n abi: Abi,\n value?: bigint,\n ): Promise<bigint> {\n if (!this.walletClient) {\n throw new SDKError('Wallet client required for gas estimation', 'NO_WALLET')\n }\n\n try {\n const account = this.walletClient.account\n if (!account) {\n throw new SDKError('No account connected', 'NO_ACCOUNT')\n }\n\n const estimateParams = {\n address: contractAddress,\n abi,\n functionName,\n args,\n account,\n ...(value !== undefined && { value }),\n }\n\n return await this.publicClient.estimateContractGas(estimateParams)\n } catch (error) {\n throw new SDKError(`Failed to estimate gas: ${error}`, 'GAS_ESTIMATION_FAILED')\n }\n }\n\n public async waitForTransaction(hash: Hash): Promise<TransactionReceipt> {\n try {\n return await this.publicClient.waitForTransactionReceipt({\n hash,\n confirmations: 1,\n })\n } catch (error) {\n throw new SDKError(`Failed to wait for transaction: ${error}`, 'TRANSACTION_WAIT_FAILED')\n }\n }\n}\n","// SPDX-License-Identifier: LGPL-3.0-only\n//\n// This file is provided WITHOUT ANY WARRANTY;\n// without even the implied warranty of MERCHANTABILITY\n// or FITNESS FOR A PARTICULAR PURPOSE.\n\nimport { type Address, type Hash, type Log, PublicClient, encodeAbiParameters } from 'viem'\nimport type { BfvParams } from './types'\n\nexport class SDKError extends Error {\n constructor(\n message: string,\n public readonly code?: string,\n ) {\n super(message)\n this.name = 'SDKError'\n }\n}\n\nexport function isValidAddress(address: string): address is Address {\n return /^0x[a-fA-F0-9]{40}$/.test(address)\n}\n\nexport function isValidHash(hash: string): hash is Hash {\n return /^0x[a-fA-F0-9]{64}$/.test(hash)\n}\n\nexport function formatEventName(contractName: string, eventName: string): string {\n return `${contractName}.${eventName}`\n}\n\nexport function parseEventData<T>(log: Log): T {\n return log.data as unknown as T\n}\n\n/**\n * Sleep for a specified number of milliseconds\n */\nexport const sleep = (ms: number): Promise<void> => {\n return new Promise((resolve) => setTimeout(resolve, ms))\n}\n\nexport function formatBigInt(value: bigint): string {\n return value.toString()\n}\n\nexport function parseBigInt(value: string): bigint {\n return BigInt(value)\n}\n\nexport function generateEventId(log: Log): string {\n return `${log.blockHash}-${log.logIndex}`\n}\n\n/**\n * Get the current timestamp in seconds\n * from onchain\n * @param publicClient - The public client to use\n */\nexport async function getCurrentTimestamp(publicClient: PublicClient): Promise<bigint> {\n const block = await publicClient.getBlock()\n return block.timestamp\n}\n\n// Compute provider parameters structure\nexport interface ComputeProviderParams {\n name: string\n parallel: boolean\n batch_size: number\n}\n\n// Default compute provider configuration\nexport const DEFAULT_COMPUTE_PROVIDER_PARAMS: ComputeProviderParams = {\n name: 'risc0',\n parallel: false,\n batch_size: 2,\n}\n\n// Default E3 configuration (`committeeSize` is `IInterfold.CommitteeSize`, not circuit N_PARTIES).\nexport const DEFAULT_E3_CONFIG = {\n committeeSize: 0, // CommitteeSize.Minimum\n duration: 1800, // 30 minutes in seconds\n payment_amount: '0', // 0 ETH in wei\n} as const\n\n/**\n * Encode BFV parameters for the smart contract\n * BFV (Brakerski-Fan-Vercauteren) is a type of fully homomorphic encryption\n */\nexport function encodeBfvParams(params: BfvParams): `0x${string}` {\n const { degree, plaintextModulus, moduli, error1Variance } = params\n\n if (error1Variance === undefined) {\n throw new SDKError(\n 'error1Variance is required in ProtocolParams. All BFV parameter sets must specify error1_variance.',\n 'MISSING_ERROR1_VARIANCE',\n )\n }\n\n return encodeAbiParameters(\n [\n {\n name: 'bfvParams',\n type: 'tuple',\n components: [\n { name: 'degree', type: 'uint256' },\n { name: 'plaintext_modulus', type: 'uint256' },\n { name: 'moduli', type: 'uint256[]' },\n { name: 'error1_variance', type: 'string' },\n ],\n },\n ],\n [\n {\n degree: BigInt(degree),\n plaintext_modulus: BigInt(plaintextModulus),\n moduli: [...moduli],\n error1_variance: error1Variance,\n },\n ],\n )\n}\n\n/**\n * Encode compute provider parameters for the smart contract'\n * If mock is true, the compute provider parameters will return 32 bytes of 0x00\n */\nexport function encodeComputeProviderParams(params: ComputeProviderParams, mock: boolean = false): `0x${string}` {\n if (mock) {\n return `0x${'00'.repeat(32)}` as `0x${string}`\n }\n\n const jsonString = JSON.stringify(params)\n const encoder = new TextEncoder()\n const bytes = encoder.encode(jsonString)\n\n return `0x${Array.from(bytes, (byte) => byte.toString(16).padStart(2, '0')).join('')}`\n}\n\n/**\n * Encode custom parameters for the smart contract.\n */\nexport function encodeCustomParams(params: Record<string, unknown>): `0x${string}` {\n const jsonString = JSON.stringify(params)\n const encoder = new TextEncoder()\n const bytes = encoder.encode(jsonString)\n\n return `0x${Array.from(bytes, (byte) => byte.toString(16).padStart(2, '0')).join('')}`\n}\n\n// inputWindow[0] is always larger than now and dkg deadline\nexport const inputWindowStartBuffer = 15n\n\n/**\n * Calculate start window for E3 request\n * @dev This function can be used for testing purposes, or for E3s which need to start as soon as possible.\n * @param publicClient - The public client to use\n * @param duration - The duration of the input window in seconds\n * @param startBuffer - Buffer in seconds added to current timestamp for input window start\n */\nexport async function calculateInputWindow(\n publicClient: PublicClient,\n duration: number = DEFAULT_E3_CONFIG.duration,\n startBuffer: bigint = inputWindowStartBuffer,\n): Promise<[bigint, bigint]> {\n const now = await getCurrentTimestamp(publicClient)\n return [BigInt(now) + startBuffer, BigInt(now) + startBuffer + BigInt(duration)]\n}\n\n/**\n * Decode plaintextOutput bytes to get the actual result number\n */\nexport function decodePlaintextOutput(plaintextOutput: string): number | null {\n try {\n // Remove '0x' prefix if present\n const hex = plaintextOutput.startsWith('0x') ? plaintextOutput.slice(2) : plaintextOutput\n\n // Convert hex to bytes\n const bytes = new Uint8Array(hex.match(/.{1,2}/g)?.map((byte) => parseInt(byte, 16)) || [])\n\n if (bytes.length < 8) {\n console.warn('Plaintext output too short for u64 decoding')\n return null\n }\n\n // Decode first u64 (8 bytes) as little-endian\n const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength)\n const result = view.getBigUint64(0, true) // true for little-endian\n\n return Number(result)\n } catch (error) {\n console.error('Failed to decode plaintext output:', error)\n return null\n }\n}\n\n// Helper function to convert proof bytes to field elements\nexport function proofToFields(proof: Uint8Array): string[] {\n const fields: string[] = []\n for (let i = 0; i < proof.length; i += 32) {\n const chunk = proof.slice(i, i + 32)\n fields.push('0x' + Buffer.from(chunk).toString('hex'))\n }\n return fields\n}\n","// SPDX-License-Identifier: LGPL-3.0-only\n//\n// This file is provided WITHOUT ANY WARRANTY;\n// without even the implied warranty of MERCHANTABILITY\n// or FITNESS FOR A PARTICULAR PURPOSE.\n\nimport { SDKError } from '../utils'\n\nexport interface ContractAddresses {\n interfold: `0x${string}`\n ciphernodeRegistry: `0x${string}`\n feeToken: `0x${string}`\n}\n\n/** On-chain `IInterfold.CommitteeSize`: Minimum (N=3), Micro (N=9), Small (N=19). */\nexport enum CommitteeSize {\n Minimum = 0,\n Micro = 1,\n Small = 2,\n}\n\n/** Fail fast on out-of-range committee sizes before they hit the contract. */\nexport function validateCommitteeSize(value: number | CommitteeSize): CommitteeSize {\n if (!Number.isInteger(value) || value < CommitteeSize.Minimum || value > CommitteeSize.Small) {\n throw new SDKError(\n `Invalid committeeSize ${value}. Use CommitteeSize.Minimum (0), CommitteeSize.Micro (1), or CommitteeSize.Small (2).`,\n 'INVALID_COMMITTEE_SIZE',\n )\n }\n return value\n}\n\nexport enum ParamSet {\n Insecure512 = 0,\n Secure8192 = 1,\n}\n\nexport interface E3 {\n seed: bigint\n committeeSize: number\n requestBlock: bigint\n inputWindow: readonly [bigint, bigint]\n encryptionSchemeId: string\n e3Program: string\n paramSet: number\n decryptionVerifier: string\n committeePublicKey: string\n ciphertextOutput: string\n ciphertextCommitment: string\n plaintextOutput: string\n}\n\nexport interface RequestParams {\n gasLimit?: bigint\n}\n\nexport interface E3RequestParams extends RequestParams {\n committeeSize: number\n inputWindow: readonly [bigint, bigint]\n e3Program: `0x${string}`\n paramSet: number\n computeProviderParams: `0x${string}`\n customParams?: `0x${string}`\n /** Maximum fee token amount accepted. Defaults to a fresh quote. */\n maxFee?: bigint\n}\n\nexport enum E3Stage {\n None,\n Requested,\n CommitteeFinalized,\n KeyPublished,\n CiphertextReady,\n Complete,\n Failed,\n}\n\nexport enum FailureReason {\n None,\n CommitteeFormationTimeout,\n InsufficientCommitteeMembers,\n DKGTimeout,\n DKGInvalidShares,\n NoInputsReceived,\n ComputeTimeout,\n ComputeProviderExpired,\n ComputeProviderFailed,\n RequesterCancelled,\n DecryptionTimeout,\n DecryptionInvalidShares,\n VerificationFailed,\n}\n"],"mappings":"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","names":["E3Stage","FailureReason"]}
|
|
1
|
+
{"version":3,"sources":["../../src/contracts/contract-client.ts","../../src/utils.ts","../../src/contracts/types.ts"],"sourcesContent":["// SPDX-License-Identifier: LGPL-3.0-only\n//\n// This file is provided WITHOUT ANY WARRANTY;\n// without even the implied warranty of MERCHANTABILITY\n// or FITNESS FOR A PARTICULAR PURPOSE.\n\nimport {\n encodeAbiParameters,\n type Abi,\n type Chain,\n type Hash,\n type PublicClient,\n type TransactionReceipt,\n type WalletClient,\n createPublicClient,\n createWalletClient,\n http,\n webSocket,\n} from 'viem'\nimport { privateKeyToAccount } from 'viem/accounts'\n\nimport { CiphernodeRegistryOwnable__factory, Interfold__factory, InterfoldToken__factory } from '@interfold/contracts/types'\nimport type { CiphertextOutputReference, ContractAddresses, E3, E3RequestParams, E3Stage, FailureReason } from './types'\nimport { validateCommitteeSize } from './types'\nimport { SDKError, cryptoConfigIdForParamSet, isValidAddress } from '../utils'\n\nexport interface ContractClientConfig {\n publicClient: PublicClient\n walletClient?: WalletClient\n contracts: ContractAddresses\n}\n\nexport class ContractClient {\n private publicClient: PublicClient\n private walletClient?: WalletClient\n private contracts: ContractAddresses\n private contractInfo: {\n interfold: { address: `0x${string}`; abi: Abi }\n ciphernodeRegistry: { address: `0x${string}`; abi: Abi }\n feeToken: { address: `0x${string}`; abi: Abi }\n }\n\n constructor(config: ContractClientConfig) {\n const { publicClient, walletClient, contracts } = config\n\n if (!isValidAddress(contracts.interfold)) {\n throw new SDKError('Invalid Interfold contract address', 'INVALID_ADDRESS')\n }\n if (!isValidAddress(contracts.ciphernodeRegistry)) {\n throw new SDKError('Invalid CiphernodeRegistry contract address', 'INVALID_ADDRESS')\n }\n if (!isValidAddress(contracts.feeToken)) {\n throw new SDKError('Invalid FeeToken contract address', 'INVALID_ADDRESS')\n }\n\n this.publicClient = publicClient\n this.walletClient = walletClient\n this.contracts = contracts\n\n this.contractInfo = {\n interfold: {\n address: contracts.interfold,\n abi: Interfold__factory.abi,\n },\n ciphernodeRegistry: {\n address: contracts.ciphernodeRegistry,\n abi: CiphernodeRegistryOwnable__factory.abi,\n },\n feeToken: {\n address: contracts.feeToken,\n abi: InterfoldToken__factory.abi,\n },\n }\n }\n\n public static create(options: {\n rpcUrl: string\n contracts: ContractAddresses\n privateKey?: `0x${string}`\n chain: Chain\n }): ContractClient {\n const isWebSocket = options.rpcUrl.startsWith('ws://') || options.rpcUrl.startsWith('wss://')\n const transport = isWebSocket\n ? webSocket(options.rpcUrl, {\n keepAlive: { interval: 30_000 },\n reconnect: { attempts: 5, delay: 2_000 },\n })\n : http(options.rpcUrl)\n\n const publicClient = createPublicClient({\n chain: options.chain,\n transport,\n }) as PublicClient\n\n let walletClient: WalletClient | undefined\n if (options.privateKey) {\n const account = privateKeyToAccount(options.privateKey)\n walletClient = createWalletClient({\n account,\n chain: options.chain,\n transport,\n })\n }\n\n return new ContractClient({ publicClient, walletClient, contracts: options.contracts })\n }\n\n public getPublicClient(): PublicClient {\n return this.publicClient\n }\n\n public async approveFeeToken(amount: bigint): Promise<Hash> {\n if (!this.walletClient) {\n throw new SDKError('Wallet client required for write operations', 'NO_WALLET')\n }\n\n try {\n const account = this.walletClient.account\n if (!account) {\n throw new SDKError('No account connected', 'NO_ACCOUNT')\n }\n\n const { request } = await this.publicClient.simulateContract({\n address: this.contracts.feeToken,\n abi: InterfoldToken__factory.abi,\n functionName: 'approve',\n args: [this.contracts.interfold, amount],\n account,\n })\n\n return await this.walletClient.writeContract(request)\n } catch (error) {\n throw new SDKError(`Failed to approve fee token: ${error}`, 'APPROVE_FEE_TOKEN_FAILED')\n }\n }\n\n public async requestE3(params: E3RequestParams): Promise<Hash> {\n if (!this.walletClient) {\n throw new SDKError('Wallet client required for write operations', 'NO_WALLET')\n }\n\n try {\n const account = this.walletClient.account\n if (!account) {\n throw new SDKError('No account connected', 'NO_ACCOUNT')\n }\n\n const committeeSize = validateCommitteeSize(params.committeeSize)\n const maxFee = params.maxFee ?? (await this.getE3Quote(params))\n const expectedCryptoConfigId = cryptoConfigIdForParamSet(params.paramSet)\n\n const { request } = await this.publicClient.simulateContract({\n address: this.contracts.interfold,\n abi: Interfold__factory.abi,\n functionName: 'request',\n args: [\n {\n committeeSize,\n inputWindow: params.inputWindow,\n e3Program: params.e3Program,\n paramSet: params.paramSet,\n computeProviderParams: params.computeProviderParams,\n customParams: params.customParams || '0x',\n expectedFeeToken: this.contracts.feeToken,\n expectedCryptoConfigId,\n maxFee,\n },\n ],\n account,\n gas: params.gasLimit,\n })\n\n return await this.walletClient.writeContract(request)\n } catch (error) {\n throw new SDKError(`Failed to request E3: ${error}`, 'REQUEST_E3_FAILED')\n }\n }\n\n public async cancelE3(e3Id: bigint): Promise<Hash> {\n if (!this.walletClient) {\n throw new SDKError('Wallet client required for write operations', 'NO_WALLET')\n }\n const account = this.walletClient.account\n if (!account) {\n throw new SDKError('No account connected', 'NO_ACCOUNT')\n }\n\n try {\n const { request } = await this.publicClient.simulateContract({\n address: this.contracts.interfold,\n abi: Interfold__factory.abi,\n functionName: 'cancelE3',\n args: [e3Id],\n account,\n })\n\n return await this.walletClient.writeContract(request)\n } catch (error) {\n throw new SDKError(`Failed to cancel E3: ${error}`, 'CANCEL_E3_FAILED')\n }\n }\n\n public async publishCiphertextOutput(e3Id: bigint, outputReference: CiphertextOutputReference, gasLimit?: bigint): Promise<Hash> {\n if (!this.walletClient) {\n throw new SDKError('Wallet client required for write operations', 'NO_WALLET')\n }\n\n try {\n const account = this.walletClient.account\n if (!account) {\n throw new SDKError('No account connected', 'NO_ACCOUNT')\n }\n\n const encodedOutputReference = encodeAbiParameters(\n [\n {\n type: 'tuple',\n components: [\n { name: 'contentHash', type: 'bytes32' },\n { name: 'ciphertextCommitment', type: 'bytes32' },\n { name: 'computeProof', type: 'bytes' },\n { name: 'availabilityProof', type: 'bytes' },\n ],\n },\n ],\n [outputReference],\n )\n\n const { request } = await this.publicClient.simulateContract({\n address: this.contracts.interfold,\n abi: Interfold__factory.abi,\n functionName: 'publishCiphertextOutput',\n args: [e3Id, encodedOutputReference],\n account,\n gas: gasLimit,\n })\n\n return await this.walletClient.writeContract(request)\n } catch (error) {\n throw new SDKError(`Failed to publish ciphertext output: ${error}`, 'PUBLISH_CIPHERTEXT_OUTPUT_FAILED')\n }\n }\n\n public async getE3(e3Id: bigint): Promise<E3> {\n try {\n const result: E3 = await this.publicClient.readContract({\n address: this.contracts.interfold,\n abi: Interfold__factory.abi,\n functionName: 'getE3',\n args: [e3Id],\n })\n\n return result\n } catch (error) {\n throw new SDKError(`Failed to get E3: ${error}`, 'GET_E3_FAILED')\n }\n }\n\n public async getE3Quote(requestParams: E3RequestParams): Promise<bigint> {\n try {\n const committeeSize = validateCommitteeSize(requestParams.committeeSize)\n const expectedCryptoConfigId = cryptoConfigIdForParamSet(requestParams.paramSet)\n\n return this.publicClient.readContract({\n address: this.contracts.interfold,\n abi: Interfold__factory.abi,\n functionName: 'getE3Quote',\n args: [\n {\n committeeSize,\n inputWindow: requestParams.inputWindow,\n e3Program: requestParams.e3Program,\n paramSet: requestParams.paramSet,\n computeProviderParams: requestParams.computeProviderParams,\n customParams: requestParams.customParams || '0x',\n expectedFeeToken: this.contracts.feeToken,\n expectedCryptoConfigId,\n maxFee: requestParams.maxFee ?? 0n,\n },\n ],\n })\n } catch (error) {\n throw new SDKError(`Failed to get E3 quote: ${error}`, 'GET_E3_QUOTE_FAILED')\n }\n }\n\n public async getFailureReason(e3Id: bigint): Promise<FailureReason> {\n try {\n return this.publicClient.readContract({\n address: this.contracts.interfold,\n abi: Interfold__factory.abi,\n functionName: 'getFailureReason',\n args: [e3Id],\n })\n } catch (error) {\n throw new SDKError(`Failed to get failure reason: ${error}`, 'GET_FAILURE_REASON_FAILED')\n }\n }\n\n public async getE3PublicKey(e3Id: bigint): Promise<`0x${string}`> {\n try {\n const result: `0x${string}` = await this.publicClient.readContract({\n address: this.contracts.ciphernodeRegistry,\n abi: CiphernodeRegistryOwnable__factory.abi,\n functionName: 'committeePublicKey',\n args: [e3Id],\n })\n\n return result\n } catch (error) {\n throw new SDKError(`Failed to get E3 public key: ${error}`, 'GET_E3_PUBLIC_KEY_FAILED')\n }\n }\n\n public async getE3Stage(e3Id: bigint): Promise<E3Stage> {\n try {\n return this.publicClient.readContract({\n address: this.contracts.interfold,\n abi: Interfold__factory.abi,\n functionName: 'getE3Stage',\n args: [e3Id],\n })\n } catch (error) {\n throw new SDKError(`Failed to get E3 stage: ${error}`, 'GET_E3_STAGE_FAILED')\n }\n }\n\n public async estimateGas(\n functionName: string,\n args: readonly unknown[],\n contractAddress: `0x${string}`,\n abi: Abi,\n value?: bigint,\n ): Promise<bigint> {\n if (!this.walletClient) {\n throw new SDKError('Wallet client required for gas estimation', 'NO_WALLET')\n }\n\n try {\n const account = this.walletClient.account\n if (!account) {\n throw new SDKError('No account connected', 'NO_ACCOUNT')\n }\n\n const estimateParams = {\n address: contractAddress,\n abi,\n functionName,\n args,\n account,\n ...(value !== undefined && { value }),\n }\n\n return await this.publicClient.estimateContractGas(estimateParams)\n } catch (error) {\n throw new SDKError(`Failed to estimate gas: ${error}`, 'GAS_ESTIMATION_FAILED')\n }\n }\n\n public async waitForTransaction(hash: Hash): Promise<TransactionReceipt> {\n try {\n return await this.publicClient.waitForTransactionReceipt({\n hash,\n confirmations: 1,\n })\n } catch (error) {\n throw new SDKError(`Failed to wait for transaction: ${error}`, 'TRANSACTION_WAIT_FAILED')\n }\n }\n}\n","// SPDX-License-Identifier: LGPL-3.0-only\n//\n// This file is provided WITHOUT ANY WARRANTY;\n// without even the implied warranty of MERCHANTABILITY\n// or FITNESS FOR A PARTICULAR PURPOSE.\n\nimport { type Address, type Hash, type Log, PublicClient, encodeAbiParameters } from 'viem'\nimport type { BfvParams } from './types'\n\nexport class SDKError extends Error {\n constructor(\n message: string,\n public readonly code?: string,\n ) {\n super(message)\n this.name = 'SDKError'\n }\n}\n\nexport function isValidAddress(address: string): address is Address {\n return /^0x[a-fA-F0-9]{40}$/.test(address)\n}\n\nexport function isValidHash(hash: string): hash is Hash {\n return /^0x[a-fA-F0-9]{64}$/.test(hash)\n}\n\nexport function formatEventName(contractName: string, eventName: string): string {\n return `${contractName}.${eventName}`\n}\n\nexport function parseEventData<T>(log: Log): T {\n return log.data as unknown as T\n}\n\n/**\n * Sleep for a specified number of milliseconds\n */\nexport const sleep = (ms: number): Promise<void> => {\n return new Promise((resolve) => setTimeout(resolve, ms))\n}\n\nexport function formatBigInt(value: bigint): string {\n return value.toString()\n}\n\nexport function parseBigInt(value: string): bigint {\n return BigInt(value)\n}\n\nexport function generateEventId(log: Log): string {\n return `${log.blockHash}-${log.logIndex}`\n}\n\n/**\n * Get the current timestamp in seconds\n * from onchain\n * @param publicClient - The public client to use\n */\nexport async function getCurrentTimestamp(publicClient: PublicClient): Promise<bigint> {\n const block = await publicClient.getBlock()\n return block.timestamp\n}\n\n// Compute provider parameters structure\nexport interface ComputeProviderParams {\n name: string\n parallel: boolean\n batch_size: number\n}\n\n// Default compute provider configuration\nexport const DEFAULT_COMPUTE_PROVIDER_PARAMS: ComputeProviderParams = {\n name: 'risc0',\n parallel: false,\n batch_size: 2,\n}\n\n// Default E3 configuration (`committeeSize` is `IInterfold.CommitteeSize`, not circuit N_PARTIES).\nexport const DEFAULT_E3_CONFIG = {\n committeeSize: 0, // CommitteeSize.Minimum\n duration: 1800, // 30 minutes in seconds\n payment_amount: '0', // 0 ETH in wei\n} as const\n\nexport function cryptoConfigIdForParamSet(paramSet: number): Hash {\n if (paramSet === 0) {\n return '0x04f3677e73b0f5066d6caf5cbd92e3fb2e38338edaf5cfc971ab28f7b684da78'\n }\n if (paramSet === 1) {\n return '0xd9c86e581f8291ffb5b63595600e8d096ed30b16e2e0a6634a76c22b1f58fb4e'\n }\n throw new SDKError(`Unsupported BFV parameter set: ${paramSet}`, 'UNSUPPORTED_CRYPTO_CONFIG')\n}\n\n/**\n * Encode BFV parameters for the smart contract\n * BFV (Brakerski-Fan-Vercauteren) is a type of fully homomorphic encryption\n */\nexport function encodeBfvParams(params: BfvParams): `0x${string}` {\n const { degree, plaintextModulus, moduli, error1Variance } = params\n\n if (error1Variance === undefined) {\n throw new SDKError(\n 'error1Variance is required in ProtocolParams. All BFV parameter sets must specify error1_variance.',\n 'MISSING_ERROR1_VARIANCE',\n )\n }\n\n return encodeAbiParameters(\n [\n {\n name: 'bfvParams',\n type: 'tuple',\n components: [\n { name: 'degree', type: 'uint256' },\n { name: 'plaintext_modulus', type: 'uint256' },\n { name: 'moduli', type: 'uint256[]' },\n { name: 'error1_variance', type: 'string' },\n ],\n },\n ],\n [\n {\n degree: BigInt(degree),\n plaintext_modulus: BigInt(plaintextModulus),\n moduli: [...moduli],\n error1_variance: error1Variance,\n },\n ],\n )\n}\n\n/**\n * Encode compute provider parameters for the smart contract'\n * If mock is true, the compute provider parameters will return 32 bytes of 0x00\n */\nexport function encodeComputeProviderParams(params: ComputeProviderParams, mock: boolean = false): `0x${string}` {\n if (mock) {\n return `0x${'00'.repeat(32)}` as `0x${string}`\n }\n\n const jsonString = JSON.stringify(params)\n const encoder = new TextEncoder()\n const bytes = encoder.encode(jsonString)\n\n return `0x${Array.from(bytes, (byte) => byte.toString(16).padStart(2, '0')).join('')}`\n}\n\n/**\n * Encode custom parameters for the smart contract.\n */\nexport function encodeCustomParams(params: Record<string, unknown>): `0x${string}` {\n const jsonString = JSON.stringify(params)\n const encoder = new TextEncoder()\n const bytes = encoder.encode(jsonString)\n\n return `0x${Array.from(bytes, (byte) => byte.toString(16).padStart(2, '0')).join('')}`\n}\n\n// inputWindow[0] is always larger than now and dkg deadline\nexport const inputWindowStartBuffer = 15n\n\n/**\n * Calculate start window for E3 request\n * @dev This function can be used for testing purposes, or for E3s which need to start as soon as possible.\n * @param publicClient - The public client to use\n * @param duration - The duration of the input window in seconds\n * @param startBuffer - Buffer in seconds added to current timestamp for input window start\n */\nexport async function calculateInputWindow(\n publicClient: PublicClient,\n duration: number = DEFAULT_E3_CONFIG.duration,\n startBuffer: bigint = inputWindowStartBuffer,\n): Promise<[bigint, bigint]> {\n const now = await getCurrentTimestamp(publicClient)\n return [BigInt(now) + startBuffer, BigInt(now) + startBuffer + BigInt(duration)]\n}\n\n/**\n * Decode plaintextOutput bytes to get the actual result number\n */\nexport function decodePlaintextOutput(plaintextOutput: string): number | null {\n try {\n // Remove '0x' prefix if present\n const hex = plaintextOutput.startsWith('0x') ? plaintextOutput.slice(2) : plaintextOutput\n\n // Convert hex to bytes\n const bytes = new Uint8Array(hex.match(/.{1,2}/g)?.map((byte) => parseInt(byte, 16)) || [])\n\n if (bytes.length < 8) {\n console.warn('Plaintext output too short for u64 decoding')\n return null\n }\n\n // Decode first u64 (8 bytes) as little-endian\n const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength)\n const result = view.getBigUint64(0, true) // true for little-endian\n\n return Number(result)\n } catch (error) {\n console.error('Failed to decode plaintext output:', error)\n return null\n }\n}\n\n// Helper function to convert proof bytes to field elements\nexport function proofToFields(proof: Uint8Array): string[] {\n const fields: string[] = []\n for (let i = 0; i < proof.length; i += 32) {\n const chunk = proof.slice(i, i + 32)\n fields.push('0x' + Buffer.from(chunk).toString('hex'))\n }\n return fields\n}\n","// SPDX-License-Identifier: LGPL-3.0-only\n//\n// This file is provided WITHOUT ANY WARRANTY;\n// without even the implied warranty of MERCHANTABILITY\n// or FITNESS FOR A PARTICULAR PURPOSE.\n\nimport { SDKError } from '../utils'\n\nexport interface ContractAddresses {\n interfold: `0x${string}`\n ciphernodeRegistry: `0x${string}`\n feeToken: `0x${string}`\n}\n\n/** On-chain `IInterfold.CommitteeSize`: Minimum (N=3), Micro (N=9), Small (N=19). */\nexport enum CommitteeSize {\n Minimum = 0,\n Micro = 1,\n Small = 2,\n}\n\n/** Fail fast on out-of-range committee sizes before they hit the contract. */\nexport function validateCommitteeSize(value: number | CommitteeSize): CommitteeSize {\n if (!Number.isInteger(value) || value < CommitteeSize.Minimum || value > CommitteeSize.Small) {\n throw new SDKError(\n `Invalid committeeSize ${value}. Use CommitteeSize.Minimum (0), CommitteeSize.Micro (1), or CommitteeSize.Small (2).`,\n 'INVALID_COMMITTEE_SIZE',\n )\n }\n return value\n}\n\nexport enum ParamSet {\n Insecure512 = 0,\n Secure8192 = 1,\n}\n\nexport interface E3 {\n seed: bigint\n committeeSize: number\n requestBlock: bigint\n inputWindow: readonly [bigint, bigint]\n encryptionSchemeId: string\n e3Program: string\n paramSet: number\n decryptionVerifier: string\n committeePublicKey: string\n ciphertextOutput: string\n ciphertextCommitment: string\n plaintextOutput: string\n}\n\nexport interface RequestParams {\n gasLimit?: bigint\n}\n\nexport interface E3RequestParams extends RequestParams {\n committeeSize: number\n inputWindow: readonly [bigint, bigint]\n e3Program: `0x${string}`\n paramSet: number\n computeProviderParams: `0x${string}`\n customParams?: `0x${string}`\n /** Maximum fee token amount accepted. Defaults to a fresh quote. */\n maxFee?: bigint\n}\n\n/** Proof-backed reference to an aggregate ciphertext published on the configured DA layer. */\nexport interface CiphertextOutputReference {\n contentHash: `0x${string}`\n ciphertextCommitment: `0x${string}`\n computeProof: `0x${string}`\n availabilityProof: `0x${string}`\n}\n\nexport enum E3Stage {\n None,\n Requested,\n CommitteeFinalized,\n KeyPublished,\n CiphertextReady,\n Complete,\n Failed,\n}\n\nexport enum FailureReason {\n None,\n CommitteeFormationTimeout,\n InsufficientCommitteeMembers,\n DKGTimeout,\n DKGInvalidShares,\n NoInputsReceived,\n ComputeTimeout,\n ComputeProviderExpired,\n ComputeProviderFailed,\n RequesterCancelled,\n DecryptionTimeout,\n DecryptionInvalidShares,\n VerificationFailed,\n}\n"],"mappings":";AAMA;AAAA,EACE,uBAAAA;AAAA,EAOA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,2BAA2B;AAEpC,SAAS,oCAAoC,oBAAoB,+BAA+B;;;ACfhG,SAA0D,2BAA2B;AAG9E,IAAM,WAAN,cAAuB,MAAM;AAAA,EAClC,YACE,SACgB,MAChB;AACA,UAAM,OAAO;AAFG;AAGhB,SAAK,OAAO;AAAA,EACd;AACF;AAEO,SAAS,eAAe,SAAqC;AAClE,SAAO,sBAAsB,KAAK,OAAO;AAC3C;AAgEO,SAAS,0BAA0B,UAAwB;AAChE,MAAI,aAAa,GAAG;AAClB,WAAO;AAAA,EACT;AACA,MAAI,aAAa,GAAG;AAClB,WAAO;AAAA,EACT;AACA,QAAM,IAAI,SAAS,kCAAkC,QAAQ,IAAI,2BAA2B;AAC9F;;;ACvEO,SAAS,sBAAsB,OAA8C;AAClF,MAAI,CAAC,OAAO,UAAU,KAAK,KAAK,QAAQ,mBAAyB,QAAQ,eAAqB;AAC5F,UAAM,IAAI;AAAA,MACR,yBAAyB,KAAK;AAAA,MAC9B;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AA6CO,IAAK,UAAL,kBAAKC,aAAL;AACL,EAAAA,kBAAA;AACA,EAAAA,kBAAA;AACA,EAAAA,kBAAA;AACA,EAAAA,kBAAA;AACA,EAAAA,kBAAA;AACA,EAAAA,kBAAA;AACA,EAAAA,kBAAA;AAPU,SAAAA;AAAA,GAAA;AAUL,IAAK,gBAAL,kBAAKC,mBAAL;AACL,EAAAA,8BAAA;AACA,EAAAA,8BAAA;AACA,EAAAA,8BAAA;AACA,EAAAA,8BAAA;AACA,EAAAA,8BAAA;AACA,EAAAA,8BAAA;AACA,EAAAA,8BAAA;AACA,EAAAA,8BAAA;AACA,EAAAA,8BAAA;AACA,EAAAA,8BAAA;AACA,EAAAA,8BAAA;AACA,EAAAA,8BAAA;AACA,EAAAA,8BAAA;AAbU,SAAAA;AAAA,GAAA;;;AFrDL,IAAM,iBAAN,MAAM,gBAAe;AAAA,EAClB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAMR,YAAY,QAA8B;AACxC,UAAM,EAAE,cAAc,cAAc,UAAU,IAAI;AAElD,QAAI,CAAC,eAAe,UAAU,SAAS,GAAG;AACxC,YAAM,IAAI,SAAS,sCAAsC,iBAAiB;AAAA,IAC5E;AACA,QAAI,CAAC,eAAe,UAAU,kBAAkB,GAAG;AACjD,YAAM,IAAI,SAAS,+CAA+C,iBAAiB;AAAA,IACrF;AACA,QAAI,CAAC,eAAe,UAAU,QAAQ,GAAG;AACvC,YAAM,IAAI,SAAS,qCAAqC,iBAAiB;AAAA,IAC3E;AAEA,SAAK,eAAe;AACpB,SAAK,eAAe;AACpB,SAAK,YAAY;AAEjB,SAAK,eAAe;AAAA,MAClB,WAAW;AAAA,QACT,SAAS,UAAU;AAAA,QACnB,KAAK,mBAAmB;AAAA,MAC1B;AAAA,MACA,oBAAoB;AAAA,QAClB,SAAS,UAAU;AAAA,QACnB,KAAK,mCAAmC;AAAA,MAC1C;AAAA,MACA,UAAU;AAAA,QACR,SAAS,UAAU;AAAA,QACnB,KAAK,wBAAwB;AAAA,MAC/B;AAAA,IACF;AAAA,EACF;AAAA,EAEA,OAAc,OAAO,SAKF;AACjB,UAAM,cAAc,QAAQ,OAAO,WAAW,OAAO,KAAK,QAAQ,OAAO,WAAW,QAAQ;AAC5F,UAAM,YAAY,cACd,UAAU,QAAQ,QAAQ;AAAA,MACxB,WAAW,EAAE,UAAU,IAAO;AAAA,MAC9B,WAAW,EAAE,UAAU,GAAG,OAAO,IAAM;AAAA,IACzC,CAAC,IACD,KAAK,QAAQ,MAAM;AAEvB,UAAM,eAAe,mBAAmB;AAAA,MACtC,OAAO,QAAQ;AAAA,MACf;AAAA,IACF,CAAC;AAED,QAAI;AACJ,QAAI,QAAQ,YAAY;AACtB,YAAM,UAAU,oBAAoB,QAAQ,UAAU;AACtD,qBAAe,mBAAmB;AAAA,QAChC;AAAA,QACA,OAAO,QAAQ;AAAA,QACf;AAAA,MACF,CAAC;AAAA,IACH;AAEA,WAAO,IAAI,gBAAe,EAAE,cAAc,cAAc,WAAW,QAAQ,UAAU,CAAC;AAAA,EACxF;AAAA,EAEO,kBAAgC;AACrC,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,MAAa,gBAAgB,QAA+B;AAC1D,QAAI,CAAC,KAAK,cAAc;AACtB,YAAM,IAAI,SAAS,+CAA+C,WAAW;AAAA,IAC/E;AAEA,QAAI;AACF,YAAM,UAAU,KAAK,aAAa;AAClC,UAAI,CAAC,SAAS;AACZ,cAAM,IAAI,SAAS,wBAAwB,YAAY;AAAA,MACzD;AAEA,YAAM,EAAE,QAAQ,IAAI,MAAM,KAAK,aAAa,iBAAiB;AAAA,QAC3D,SAAS,KAAK,UAAU;AAAA,QACxB,KAAK,wBAAwB;AAAA,QAC7B,cAAc;AAAA,QACd,MAAM,CAAC,KAAK,UAAU,WAAW,MAAM;AAAA,QACvC;AAAA,MACF,CAAC;AAED,aAAO,MAAM,KAAK,aAAa,cAAc,OAAO;AAAA,IACtD,SAAS,OAAO;AACd,YAAM,IAAI,SAAS,gCAAgC,KAAK,IAAI,0BAA0B;AAAA,IACxF;AAAA,EACF;AAAA,EAEA,MAAa,UAAU,QAAwC;AAC7D,QAAI,CAAC,KAAK,cAAc;AACtB,YAAM,IAAI,SAAS,+CAA+C,WAAW;AAAA,IAC/E;AAEA,QAAI;AACF,YAAM,UAAU,KAAK,aAAa;AAClC,UAAI,CAAC,SAAS;AACZ,cAAM,IAAI,SAAS,wBAAwB,YAAY;AAAA,MACzD;AAEA,YAAM,gBAAgB,sBAAsB,OAAO,aAAa;AAChE,YAAM,SAAS,OAAO,UAAW,MAAM,KAAK,WAAW,MAAM;AAC7D,YAAM,yBAAyB,0BAA0B,OAAO,QAAQ;AAExE,YAAM,EAAE,QAAQ,IAAI,MAAM,KAAK,aAAa,iBAAiB;AAAA,QAC3D,SAAS,KAAK,UAAU;AAAA,QACxB,KAAK,mBAAmB;AAAA,QACxB,cAAc;AAAA,QACd,MAAM;AAAA,UACJ;AAAA,YACE;AAAA,YACA,aAAa,OAAO;AAAA,YACpB,WAAW,OAAO;AAAA,YAClB,UAAU,OAAO;AAAA,YACjB,uBAAuB,OAAO;AAAA,YAC9B,cAAc,OAAO,gBAAgB;AAAA,YACrC,kBAAkB,KAAK,UAAU;AAAA,YACjC;AAAA,YACA;AAAA,UACF;AAAA,QACF;AAAA,QACA;AAAA,QACA,KAAK,OAAO;AAAA,MACd,CAAC;AAED,aAAO,MAAM,KAAK,aAAa,cAAc,OAAO;AAAA,IACtD,SAAS,OAAO;AACd,YAAM,IAAI,SAAS,yBAAyB,KAAK,IAAI,mBAAmB;AAAA,IAC1E;AAAA,EACF;AAAA,EAEA,MAAa,SAAS,MAA6B;AACjD,QAAI,CAAC,KAAK,cAAc;AACtB,YAAM,IAAI,SAAS,+CAA+C,WAAW;AAAA,IAC/E;AACA,UAAM,UAAU,KAAK,aAAa;AAClC,QAAI,CAAC,SAAS;AACZ,YAAM,IAAI,SAAS,wBAAwB,YAAY;AAAA,IACzD;AAEA,QAAI;AACF,YAAM,EAAE,QAAQ,IAAI,MAAM,KAAK,aAAa,iBAAiB;AAAA,QAC3D,SAAS,KAAK,UAAU;AAAA,QACxB,KAAK,mBAAmB;AAAA,QACxB,cAAc;AAAA,QACd,MAAM,CAAC,IAAI;AAAA,QACX;AAAA,MACF,CAAC;AAED,aAAO,MAAM,KAAK,aAAa,cAAc,OAAO;AAAA,IACtD,SAAS,OAAO;AACd,YAAM,IAAI,SAAS,wBAAwB,KAAK,IAAI,kBAAkB;AAAA,IACxE;AAAA,EACF;AAAA,EAEA,MAAa,wBAAwB,MAAc,iBAA4C,UAAkC;AAC/H,QAAI,CAAC,KAAK,cAAc;AACtB,YAAM,IAAI,SAAS,+CAA+C,WAAW;AAAA,IAC/E;AAEA,QAAI;AACF,YAAM,UAAU,KAAK,aAAa;AAClC,UAAI,CAAC,SAAS;AACZ,cAAM,IAAI,SAAS,wBAAwB,YAAY;AAAA,MACzD;AAEA,YAAM,yBAAyBC;AAAA,QAC7B;AAAA,UACE;AAAA,YACE,MAAM;AAAA,YACN,YAAY;AAAA,cACV,EAAE,MAAM,eAAe,MAAM,UAAU;AAAA,cACvC,EAAE,MAAM,wBAAwB,MAAM,UAAU;AAAA,cAChD,EAAE,MAAM,gBAAgB,MAAM,QAAQ;AAAA,cACtC,EAAE,MAAM,qBAAqB,MAAM,QAAQ;AAAA,YAC7C;AAAA,UACF;AAAA,QACF;AAAA,QACA,CAAC,eAAe;AAAA,MAClB;AAEA,YAAM,EAAE,QAAQ,IAAI,MAAM,KAAK,aAAa,iBAAiB;AAAA,QAC3D,SAAS,KAAK,UAAU;AAAA,QACxB,KAAK,mBAAmB;AAAA,QACxB,cAAc;AAAA,QACd,MAAM,CAAC,MAAM,sBAAsB;AAAA,QACnC;AAAA,QACA,KAAK;AAAA,MACP,CAAC;AAED,aAAO,MAAM,KAAK,aAAa,cAAc,OAAO;AAAA,IACtD,SAAS,OAAO;AACd,YAAM,IAAI,SAAS,wCAAwC,KAAK,IAAI,kCAAkC;AAAA,IACxG;AAAA,EACF;AAAA,EAEA,MAAa,MAAM,MAA2B;AAC5C,QAAI;AACF,YAAM,SAAa,MAAM,KAAK,aAAa,aAAa;AAAA,QACtD,SAAS,KAAK,UAAU;AAAA,QACxB,KAAK,mBAAmB;AAAA,QACxB,cAAc;AAAA,QACd,MAAM,CAAC,IAAI;AAAA,MACb,CAAC;AAED,aAAO;AAAA,IACT,SAAS,OAAO;AACd,YAAM,IAAI,SAAS,qBAAqB,KAAK,IAAI,eAAe;AAAA,IAClE;AAAA,EACF;AAAA,EAEA,MAAa,WAAW,eAAiD;AACvE,QAAI;AACF,YAAM,gBAAgB,sBAAsB,cAAc,aAAa;AACvE,YAAM,yBAAyB,0BAA0B,cAAc,QAAQ;AAE/E,aAAO,KAAK,aAAa,aAAa;AAAA,QACpC,SAAS,KAAK,UAAU;AAAA,QACxB,KAAK,mBAAmB;AAAA,QACxB,cAAc;AAAA,QACd,MAAM;AAAA,UACJ;AAAA,YACE;AAAA,YACA,aAAa,cAAc;AAAA,YAC3B,WAAW,cAAc;AAAA,YACzB,UAAU,cAAc;AAAA,YACxB,uBAAuB,cAAc;AAAA,YACrC,cAAc,cAAc,gBAAgB;AAAA,YAC5C,kBAAkB,KAAK,UAAU;AAAA,YACjC;AAAA,YACA,QAAQ,cAAc,UAAU;AAAA,UAClC;AAAA,QACF;AAAA,MACF,CAAC;AAAA,IACH,SAAS,OAAO;AACd,YAAM,IAAI,SAAS,2BAA2B,KAAK,IAAI,qBAAqB;AAAA,IAC9E;AAAA,EACF;AAAA,EAEA,MAAa,iBAAiB,MAAsC;AAClE,QAAI;AACF,aAAO,KAAK,aAAa,aAAa;AAAA,QACpC,SAAS,KAAK,UAAU;AAAA,QACxB,KAAK,mBAAmB;AAAA,QACxB,cAAc;AAAA,QACd,MAAM,CAAC,IAAI;AAAA,MACb,CAAC;AAAA,IACH,SAAS,OAAO;AACd,YAAM,IAAI,SAAS,iCAAiC,KAAK,IAAI,2BAA2B;AAAA,IAC1F;AAAA,EACF;AAAA,EAEA,MAAa,eAAe,MAAsC;AAChE,QAAI;AACF,YAAM,SAAwB,MAAM,KAAK,aAAa,aAAa;AAAA,QACjE,SAAS,KAAK,UAAU;AAAA,QACxB,KAAK,mCAAmC;AAAA,QACxC,cAAc;AAAA,QACd,MAAM,CAAC,IAAI;AAAA,MACb,CAAC;AAED,aAAO;AAAA,IACT,SAAS,OAAO;AACd,YAAM,IAAI,SAAS,gCAAgC,KAAK,IAAI,0BAA0B;AAAA,IACxF;AAAA,EACF;AAAA,EAEA,MAAa,WAAW,MAAgC;AACtD,QAAI;AACF,aAAO,KAAK,aAAa,aAAa;AAAA,QACpC,SAAS,KAAK,UAAU;AAAA,QACxB,KAAK,mBAAmB;AAAA,QACxB,cAAc;AAAA,QACd,MAAM,CAAC,IAAI;AAAA,MACb,CAAC;AAAA,IACH,SAAS,OAAO;AACd,YAAM,IAAI,SAAS,2BAA2B,KAAK,IAAI,qBAAqB;AAAA,IAC9E;AAAA,EACF;AAAA,EAEA,MAAa,YACX,cACA,MACA,iBACA,KACA,OACiB;AACjB,QAAI,CAAC,KAAK,cAAc;AACtB,YAAM,IAAI,SAAS,6CAA6C,WAAW;AAAA,IAC7E;AAEA,QAAI;AACF,YAAM,UAAU,KAAK,aAAa;AAClC,UAAI,CAAC,SAAS;AACZ,cAAM,IAAI,SAAS,wBAAwB,YAAY;AAAA,MACzD;AAEA,YAAM,iBAAiB;AAAA,QACrB,SAAS;AAAA,QACT;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,GAAI,UAAU,UAAa,EAAE,MAAM;AAAA,MACrC;AAEA,aAAO,MAAM,KAAK,aAAa,oBAAoB,cAAc;AAAA,IACnE,SAAS,OAAO;AACd,YAAM,IAAI,SAAS,2BAA2B,KAAK,IAAI,uBAAuB;AAAA,IAChF;AAAA,EACF;AAAA,EAEA,MAAa,mBAAmB,MAAyC;AACvE,QAAI;AACF,aAAO,MAAM,KAAK,aAAa,0BAA0B;AAAA,QACvD;AAAA,QACA,eAAe;AAAA,MACjB,CAAC;AAAA,IACH,SAAS,OAAO;AACd,YAAM,IAAI,SAAS,mCAAmC,KAAK,IAAI,yBAAyB;AAAA,IAC1F;AAAA,EACF;AACF;","names":["encodeAbiParameters","E3Stage","FailureReason","encodeAbiParameters"]}
|