@cofhe/sdk 0.7.1 → 1.0.0-alpha.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.
Files changed (123) hide show
  1. package/CHANGELOG.md +35 -0
  2. package/acps/acp.ts +35 -7
  3. package/acps/index.ts +28 -12
  4. package/acps/onchain-utils.ts +188 -49
  5. package/acps/registry.ts +231 -0
  6. package/acps/sealing.ts +9 -3
  7. package/acps/share-metadata/appKey.ts +8 -0
  8. package/acps/share-metadata/decode.ts +120 -0
  9. package/acps/share-metadata/describe.ts +198 -0
  10. package/acps/share-metadata/encode.ts +147 -0
  11. package/acps/share-metadata/erc7984.ts +26 -0
  12. package/acps/share-metadata/index.ts +9 -0
  13. package/acps/share-metadata/layout.ts +69 -0
  14. package/acps/share-metadata/presets.ts +116 -0
  15. package/acps/share-metadata/schema.ts +47 -0
  16. package/acps/share-metadata/test/codec.test.ts +140 -0
  17. package/acps/share-metadata/test/describe.test.ts +112 -0
  18. package/acps/share-metadata/test/fixtures.ts +157 -0
  19. package/acps/share-metadata/test/live.test.ts +56 -0
  20. package/acps/share-metadata/test/presets.test.ts +119 -0
  21. package/acps/share-metadata/test/verify.test.ts +144 -0
  22. package/acps/share-metadata/verify.ts +155 -0
  23. package/acps/store.ts +48 -18
  24. package/acps/test/acp.test.ts +102 -7
  25. package/acps/test/localstorage.test.ts +28 -1
  26. package/acps/test/onchainAccessStatus.test.ts +116 -0
  27. package/acps/test/registry.test.ts +144 -0
  28. package/acps/test/sealing.test.ts +23 -0
  29. package/acps/test/store.test.ts +71 -0
  30. package/acps/test/utils.test.ts +63 -0
  31. package/acps/test/validation.test.ts +0 -4
  32. package/acps/types.ts +59 -6
  33. package/acps/utils.ts +15 -2
  34. package/acps/validation.ts +3 -1
  35. package/chains/chains/arbitrum.ts +14 -0
  36. package/chains/chains/ethereum.ts +14 -0
  37. package/chains/index.ts +5 -1
  38. package/chains/test/chains.test.ts +24 -3
  39. package/core/acps.ts +164 -207
  40. package/core/client.ts +44 -13
  41. package/core/clientTypes.ts +50 -7
  42. package/core/config.ts +33 -1
  43. package/core/consts.ts +14 -2
  44. package/core/decrypt/apiError.ts +4 -1
  45. package/core/decrypt/verifyDecryptResult.ts +8 -4
  46. package/core/encrypt/cofheMocksZkVerifySign.ts +19 -2
  47. package/core/encrypt/encryptInputsBuilder.ts +6 -0
  48. package/core/encrypt/zkPackProveVerify.ts +7 -1
  49. package/core/error.ts +1 -0
  50. package/core/fetchKeys.ts +2 -2
  51. package/core/index.ts +9 -1
  52. package/core/keyStore.ts +23 -10
  53. package/core/taskManager.ts +48 -0
  54. package/core/test/acpDefaults.test.ts +108 -19
  55. package/core/test/acpStoreAccountCase.test.ts +80 -0
  56. package/core/test/acps.test.ts +128 -3
  57. package/core/test/apiError.test.ts +8 -0
  58. package/core/test/appKeyConfig.test.ts +94 -0
  59. package/core/test/client.test.ts +41 -0
  60. package/core/test/config.test.ts +24 -0
  61. package/core/test/decrypt.test.ts +11 -4
  62. package/core/test/decryptBuilders.test.ts +110 -2
  63. package/core/test/encryptInputsBuilder.test.ts +1 -1
  64. package/core/test/fetchKeys.test.ts +23 -2
  65. package/core/test/incomingShares.test.ts +84 -0
  66. package/core/test/keyStore.test.ts +18 -6
  67. package/core/test/mocksEncryptRange.test.ts +90 -0
  68. package/core/test/taskManager.test.ts +57 -0
  69. package/core/test/utils.test.ts +128 -0
  70. package/core/test/verifyDecryptResult.test.ts +51 -0
  71. package/core/types.ts +8 -0
  72. package/core/utils.ts +16 -9
  73. package/dist/acps.cjs +984 -64
  74. package/dist/acps.d.cts +589 -10
  75. package/dist/acps.d.ts +589 -10
  76. package/dist/acps.js +2 -2
  77. package/dist/chains.cjs +26 -0
  78. package/dist/chains.d.cts +45 -1
  79. package/dist/chains.d.ts +45 -1
  80. package/dist/chains.js +1 -1
  81. package/dist/chunk-6ZW76ZKB.js +228 -0
  82. package/dist/chunk-BQWHPIYU.js +1828 -0
  83. package/dist/chunk-KSOV5B4B.js +50 -0
  84. package/dist/{chunk-43USWPEH.js → chunk-OL3DZN7A.js} +159 -523
  85. package/dist/{chunk-N6IDQRRU.js → chunk-UKQAJK4N.js} +25 -1
  86. package/dist/chunk-XQ32JG3T.js +174 -0
  87. package/dist/{clientTypes-CYZjFznO.d.cts → clientTypes-C0A9ji5O.d.cts} +132 -29
  88. package/dist/{clientTypes-BN3nbzYM.d.ts → clientTypes-CcU5WvdV.d.ts} +132 -29
  89. package/dist/core.cjs +3269 -2626
  90. package/dist/core.d.cts +32 -8
  91. package/dist/core.d.ts +32 -8
  92. package/dist/core.js +5 -4
  93. package/dist/node.cjs +3074 -2436
  94. package/dist/node.d.cts +2 -2
  95. package/dist/node.d.ts +2 -2
  96. package/dist/node.js +20 -19
  97. package/dist/{acp-Wi6isVQI.d.cts → onchain-utils-D9Z33IP7.d.cts} +166 -12
  98. package/dist/{acp-Wi6isVQI.d.ts → onchain-utils-D9Z33IP7.d.ts} +166 -12
  99. package/dist/web.cjs +3204 -2493
  100. package/dist/web.d.cts +49 -3
  101. package/dist/web.d.ts +49 -3
  102. package/dist/web.js +52 -27
  103. package/dist/zkProve.worker.cjs +79 -18
  104. package/dist/zkProve.worker.js +24 -24
  105. package/node/index.ts +1 -10
  106. package/node/storage.ts +20 -9
  107. package/node/test/inherited.test.ts +5 -1
  108. package/node/test/storage-memory-fallback.test.ts +47 -0
  109. package/node/test/storage-permissions.test.ts +40 -0
  110. package/package.json +3 -1
  111. package/web/index.ts +101 -36
  112. package/web/test/countingZkProveWorker.ts +31 -0
  113. package/web/test/inherited.web.test.ts +5 -1
  114. package/web/test/mainThreadPool.web.test.ts +174 -0
  115. package/web/test/threadPoolBenchHelper.ts +134 -0
  116. package/web/test/threadPoolOff.web.test.ts +17 -0
  117. package/web/test/threadPoolOn.web.test.ts +80 -0
  118. package/web/test/workerInitRace.web.test.ts +79 -0
  119. package/web/tfheThreadPool.ts +140 -0
  120. package/web/workerManager.ts +4 -2
  121. package/web/zkProve.worker.ts +42 -26
  122. package/dist/chunk-ESMZCFJY.js +0 -12
  123. package/dist/chunk-Q7CBWGQX.js +0 -1029
package/dist/node.d.cts CHANGED
@@ -1,8 +1,8 @@
1
- import { C as CofheInputConfig, a as CofheConfig, b as CofheClient } from './clientTypes-CYZjFznO.cjs';
1
+ import { C as CofheInputConfig, a as CofheConfig, b as CofheClient } from './clientTypes-C0A9ji5O.cjs';
2
2
  import 'viem';
3
3
  import './types-C07FK-cL.cjs';
4
4
  import 'zod';
5
- import './acp-Wi6isVQI.cjs';
5
+ import './onchain-utils-D9Z33IP7.cjs';
6
6
  import 'zustand/vanilla';
7
7
 
8
8
  /**
package/dist/node.d.ts CHANGED
@@ -1,8 +1,8 @@
1
- import { C as CofheInputConfig, a as CofheConfig, b as CofheClient } from './clientTypes-BN3nbzYM.js';
1
+ import { C as CofheInputConfig, a as CofheConfig, b as CofheClient } from './clientTypes-CcU5WvdV.js';
2
2
  import 'viem';
3
3
  import './types-C07FK-cL.js';
4
4
  import 'zod';
5
- import './acp-Wi6isVQI.js';
5
+ import './onchain-utils-D9Z33IP7.js';
6
6
  import 'zustand/vanilla';
7
7
 
8
8
  /**
package/dist/node.js CHANGED
@@ -1,18 +1,25 @@
1
- import { createCofheConfigBase, createCofheClientBase } from './chunk-43USWPEH.js';
2
- import './chunk-N6IDQRRU.js';
3
- import './chunk-Q7CBWGQX.js';
4
- import { TFHE_RS_SAFE_SERIALIZATION_SIZE_LIMIT } from './chunk-ESMZCFJY.js';
1
+ import { createCofheConfigBase, createCofheClientBase } from './chunk-OL3DZN7A.js';
2
+ import './chunk-UKQAJK4N.js';
3
+ import './chunk-BQWHPIYU.js';
4
+ import { fromHexString } from './chunk-6ZW76ZKB.js';
5
+ import { TFHE_RS_SAFE_SERIALIZATION_SIZE_LIMIT } from './chunk-XQ32JG3T.js';
5
6
  import { promises } from 'fs';
6
7
  import { join } from 'path';
7
8
  import { init_panic_hook, ProvenCompactCiphertextList, CompactPkeCrs, TfheCompactPublicKey } from 'node-tfhe';
8
9
 
9
10
  var memoryStorage = {};
11
+ var getStorageDir = () => join(process.env.HOME || process.env.USERPROFILE || ".", ".cofhesdk");
12
+ var ensureStorageDir = async (storageDir) => {
13
+ await promises.mkdir(storageDir, { recursive: true, mode: 448 });
14
+ await promises.chmod(storageDir, 448).catch(() => {
15
+ });
16
+ };
10
17
  var createNodeStorage = () => {
11
18
  return {
12
19
  getItem: async (name) => {
13
20
  try {
14
- const storageDir = join(process.env.HOME || process.env.USERPROFILE || ".", ".cofhesdk");
15
- await promises.mkdir(storageDir, { recursive: true });
21
+ const storageDir = getStorageDir();
22
+ await ensureStorageDir(storageDir);
16
23
  const filePath = join(storageDir, `${name}.json`);
17
24
  const data = await promises.readFile(filePath, "utf8").catch(() => null);
18
25
  return data ? JSON.parse(data) : null;
@@ -23,19 +30,20 @@ var createNodeStorage = () => {
23
30
  },
24
31
  setItem: async (name, value) => {
25
32
  try {
26
- const storageDir = join(process.env.HOME || process.env.USERPROFILE || ".", ".cofhesdk");
27
- await promises.mkdir(storageDir, { recursive: true });
33
+ const storageDir = getStorageDir();
34
+ await ensureStorageDir(storageDir);
28
35
  const filePath = join(storageDir, `${name}.json`);
29
- await promises.writeFile(filePath, JSON.stringify(value));
36
+ await promises.writeFile(filePath, JSON.stringify(value), { mode: 384 });
37
+ await promises.chmod(filePath, 384).catch(() => {
38
+ });
30
39
  } catch (e) {
31
40
  console.warn("Node.js filesystem modules not available, falling back to memory storage" + e);
32
- memoryStorage[name] = JSON.stringify(value);
41
+ memoryStorage[name] = value;
33
42
  }
34
43
  },
35
44
  removeItem: async (name) => {
36
45
  try {
37
- const storageDir = join(process.env.HOME || process.env.USERPROFILE || ".", ".cofhesdk");
38
- const filePath = join(storageDir, `${name}.json`);
46
+ const filePath = join(getStorageDir(), `${name}.json`);
39
47
  await promises.unlink(filePath).catch(() => {
40
48
  });
41
49
  } catch (e) {
@@ -53,13 +61,6 @@ async function initTfhe() {
53
61
  tfheInitialized = true;
54
62
  return true;
55
63
  }
56
- var fromHexString = (hexString) => {
57
- const cleanString = hexString.length % 2 === 1 ? `0${hexString}` : hexString;
58
- const arr = cleanString.replace(/^0x/, "").match(/.{1,2}/g);
59
- if (!arr)
60
- return new Uint8Array();
61
- return new Uint8Array(arr.map((byte) => parseInt(byte, 16)));
62
- };
63
64
  var _deserializeTfhePublicKey = (buff) => {
64
65
  return TfheCompactPublicKey.safe_deserialize(fromHexString(buff), TFHE_RS_SAFE_SERIALIZATION_SIZE_LIMIT);
65
66
  };
@@ -1,4 +1,4 @@
1
- import { Hex, PublicClient, WalletClient } from 'viem';
1
+ import { Hex, Address, PublicClient, WalletClient } from 'viem';
2
2
 
3
3
  type EthEncryptedData = {
4
4
  data: Uint8Array;
@@ -35,6 +35,52 @@ declare const seal: (value: bigint | number, publicKey: string) => EthEncryptedD
35
35
  */
36
36
  declare const unsealWithPrivateKey: (privateKey: string, parsedData: EthEncryptedData) => bigint;
37
37
 
38
+ /**
39
+ * A label says where one ctHash of a SNAPSHOT share came from, as something the recipient can
40
+ * check against the chain. It speaks of contracts, selectors and positions in the chain only:
41
+ * it does not know what a token, a balance or a transfer is. A reader that recognises a selector
42
+ * can present the value accordingly (see `describeShareMetadata`). A share carries one label per
43
+ * ctHash, in the order of `acp.handles`, so the ctHashes themselves are never repeated.
44
+ */
45
+ /** One argument of a stored-value read: the share issuer, or a literal 32-byte ABI word. */
46
+ type ShareLabelReadArg = {
47
+ type: 'issuer';
48
+ } | {
49
+ type: 'word';
50
+ value: Hex;
51
+ };
52
+ /** A stored value: what a view function of a contract returned at a block. */
53
+ type StoredValueLabel = {
54
+ kind: 'stored';
55
+ contract: Address;
56
+ /** 4-byte selector of the view function. */
57
+ selector: Hex;
58
+ /** Static ABI types only: each argument is one 32-byte word. */
59
+ args: ShareLabelReadArg[];
60
+ /** Which 32-byte word of the return data is the ctHash (0 for a single return value). */
61
+ returnWord: number;
62
+ /** Block the value was read at (on Arbitrum: the L2 block number). */
63
+ block: bigint;
64
+ };
65
+ /** An event value: a value carried by one event (log) that a contract emitted. */
66
+ type EventValueLabel = {
67
+ kind: 'event';
68
+ contract: Address;
69
+ /** Block of the log (on Arbitrum: the L2 block number). */
70
+ block: bigint;
71
+ /** Index of the log's transaction within its block. */
72
+ txIndex: number;
73
+ /** Block-wide index of the log, as RPC nodes return it. */
74
+ logIndex: number;
75
+ /** First 4 bytes of the log's topic0: the event selector. */
76
+ selector: Hex;
77
+ };
78
+ /** The issuer chose not to say where the ctHash came from. */
79
+ type UnlabelledLabel = {
80
+ kind: 'unlabelled';
81
+ };
82
+ type ShareLabel = StoredValueLabel | EventValueLabel | UnlabelledLabel;
83
+
38
84
  /**
39
85
  * EIP712 related types
40
86
  */
@@ -76,6 +122,12 @@ interface ACPPrivate {
76
122
  * Never leaves the client.
77
123
  */
78
124
  sealingPrivateKey: Hex;
125
+ /**
126
+ * (sharing / recipient) The share metadata: the labels of its handles, a v3 blob
127
+ * (`decodeShareMetadata` / `describeShareMetadata`). Not signed; travels with the share, in the
128
+ * exported JSON or in the registry's `Shared` event. Absent when the share has none.
129
+ */
130
+ metadata?: Hex;
79
131
  /**
80
132
  * EIP712 domain used to sign this acp.
81
133
  * Should not be set manually, included in metadata as part of serialization flows.
@@ -211,37 +263,73 @@ type CreateSharingACPOptions = ACPScopeOptions & {
211
263
  expiration?: number;
212
264
  revokerData?: number;
213
265
  revokerContract?: string;
266
+ /**
267
+ * The labels of the handles, one per handle in order. Kept on the acp as `metadata`, then
268
+ * written into `export()` and posted by `shareOnChain`.
269
+ */
270
+ labels?: readonly ShareLabel[];
271
+ /**
272
+ * The key of the app the share is for (`shareAppKey(app)`), kept in `metadata` with the labels.
273
+ * A client configured with `acp: { app }` fills it in; a recipient client with the same `app`
274
+ * lists the share, one with another app does not.
275
+ */
276
+ appKey?: Hex;
214
277
  };
278
+ /** A share as exported (`SharedACP`) or read from the registry. A `name` in it is ignored. */
215
279
  type ImportSharedACPOptions = ACPScopeOptions & {
216
280
  type?: 'sharing';
217
281
  issuer: string;
218
282
  recipient: string;
219
283
  issuerSignature: string;
220
- name?: string;
221
284
  expiration: number;
222
285
  revokerData?: number;
223
286
  revokerContract?: string;
287
+ /** The share metadata (labels blob), kept on the recipient acp; `0x` or absent for none. */
288
+ metadata?: string;
224
289
  };
225
290
  /** An ACP is plain JSON-serializable data — the serialized form is the ACP itself. */
226
291
  type SerializedACP = ACP;
227
292
  /**
228
293
  * The share payload produced by `ACPUtils.export()` — the full public component
229
294
  * with `sealingKey`/`recipientSignature` left for the recipient to fill, plus
230
- * the display name and acp type. Fixed shape: every field is always present
295
+ * the acp type. The issuer's `name` is not exported: it is their own note, and the
296
+ * recipient names the share themselves. Fixed shape: every field is always present
231
297
  * (zero-values instead of omissions), so importers can parse a single schema.
232
- * Mirrors the on-chain sharing payload struct field-for-field.
298
+ * Mirrors the on-chain sharing payload struct field-for-field. The one optional
299
+ * field is `metadata`, the labels of the handles, present only when the share has them.
233
300
  */
234
301
  type SharedACP = Expand<Omit<ACPPublic, 'sealingKey' | 'recipientSignature'> & {
235
- name: string;
236
302
  type: 'sharing';
303
+ metadata?: Hex;
237
304
  }>;
305
+ /**
306
+ * An ACP on-chain status, as `client.acp.checkAccess` reports it instead of a revert.
307
+ * Without a handle: 'valid' or the reason it is not. With a handle, a valid ACP reports
308
+ * 'allowed', 'out-of-scope' (the ACP scope does not cover the handle) or
309
+ * 'issuer-not-allowed' (the issuer itself may not read the handle, so no ACP of theirs can).
310
+ */
311
+ type ACPAccessStatus = 'valid' | 'allowed' | 'out-of-scope' | 'issuer-not-allowed' | 'expired' | 'revoked' | 'invalid-issuer-signature' | 'invalid-recipient-signature';
238
312
  /**
239
313
  * A share read back from the on-chain ACPShareRegistry: the posted payload
240
- * (SharedACP minus the client-side name/type) plus its registry id.
314
+ * (SharedACP minus its type), its registry id, and the
315
+ * metadata blob posted with it (`0x` when none) — for a SNAPSHOT share, the
316
+ * labels of its handles (`decodeShareMetadata` / `describeShareMetadata`).
241
317
  */
242
- type IncomingShare = Expand<Omit<SharedACP, 'name' | 'type'> & {
318
+ type IncomingShare = Expand<Omit<SharedACP, 'type' | 'metadata'> & {
243
319
  shareId: Hex;
320
+ metadata: Hex;
321
+ /** The key of the app the share was posted for (`shareAppKey(app)`), when it names one. */
322
+ appKey?: Hex;
244
323
  }>;
324
+ /**
325
+ * What the share label helpers read: the handles, their issuer and the metadata blob. An
326
+ * `IncomingShare` (on-chain route) and a sharing or recipient `ACP` (exported JSON route) both fit.
327
+ */
328
+ type LabelledShare = {
329
+ issuer: Hex;
330
+ handles: readonly Hex[];
331
+ metadata?: Hex;
332
+ };
245
333
  /**
246
334
  * A type representing the acp fields that are used to generate the hash
247
335
  */
@@ -274,9 +362,12 @@ declare const ACPUtils: {
274
362
  */
275
363
  createSharing: (options: CreateSharingACPOptions) => SharingACP;
276
364
  /**
277
- * Import a shared acp from various input formats
365
+ * Import a shared acp from various input formats. The acp is named `name`, or after its issuer
366
+ * ("Shared by 0x1234…abcd"); a `name` in the share itself is ignored.
278
367
  */
279
- importShared: (options: ImportSharedACPOptions | string) => RecipientACP;
368
+ importShared: (options: ImportSharedACPOptions | string, { name }?: {
369
+ name?: string;
370
+ }) => RecipientACP;
280
371
  /**
281
372
  * Sign an ACP with the provided wallet client
282
373
  */
@@ -292,7 +383,9 @@ declare const ACPUtils: {
292
383
  /**
293
384
  * Import and sign a shared acp in one operation from various input formats
294
385
  */
295
- importSharedAndSign: (options: ImportSharedACPOptions | string, publicClient: PublicClient, walletClient: WalletClient) => Promise<RecipientACP>;
386
+ importSharedAndSign: (options: ImportSharedACPOptions | string, publicClient: PublicClient, walletClient: WalletClient, importOptions?: {
387
+ name?: string;
388
+ }) => Promise<RecipientACP>;
296
389
  /**
297
390
  * Deserialize an ACP from serialized data
298
391
  */
@@ -317,6 +410,7 @@ declare const ACPUtils: {
317
410
  handles: `0x${string}`[];
318
411
  issuerSignature: `0x${string}`;
319
412
  recipientSignature: `0x${string}`;
413
+ metadata?: `0x${string}` | undefined;
320
414
  sealingPrivateKey?: string | undefined;
321
415
  sealingKey?: string | undefined;
322
416
  };
@@ -343,6 +437,7 @@ declare const ACPUtils: {
343
437
  handles: `0x${string}`[];
344
438
  issuerSignature: `0x${string}`;
345
439
  recipientSignature: `0x${string}`;
440
+ metadata?: `0x${string}` | undefined;
346
441
  sealingPrivateKey?: string | undefined;
347
442
  sealingKey?: string | undefined;
348
443
  };
@@ -358,7 +453,7 @@ declare const ACPUtils: {
358
453
  /**
359
454
  * Export acp data for sharing (strips the private component).
360
455
  * Fixed `SharedACP` shape — every field always present, aligned with
361
- * `ACPPublic` and the on-chain sharing payload.
456
+ * `ACPPublic` and the on-chain sharing payload — plus `metadata` when the acp has labels.
362
457
  */
363
458
  export: (acp: ACP) => string;
364
459
  /**
@@ -402,6 +497,65 @@ declare const ACPUtils: {
402
497
  * Check if acp passes the on-chain validation
403
498
  */
404
499
  checkValidityOnChain: (acp: ACP, publicClient: PublicClient) => Promise<boolean>;
500
+ /**
501
+ * The acp on-chain status as a value instead of a revert: 'valid' or why not, and given a
502
+ * handle, whether the acp may read it (see `ACPAccessStatus`).
503
+ */
504
+ checkAccessOnChain: (acp: ACP, publicClient: PublicClient, handle?: bigint | Hex) => Promise<ACPAccessStatus>;
405
505
  };
406
506
 
407
- export { type ACP as A, type CreateSelfACPOptions as C, type EIP712Types as E, GenerateSealingKey as G, type ImportSharedACPOptions as I, type RecipientACP as R, type SerializedACP as S, type ValidationResult as V, type ACPPublic as a, type ACPSignaturePrimaryType as b, type EIP712Message as c, type CreateSharingACPOptions as d, type ACPMetadata as e, type SharedACP as f, type IncomingShare as g, type EIP712Domain as h, ACPUtils as i, type SealingKeyPair as j, type EthEncryptedData as k, type EIP712Type as l, type ACPPrivate as m, type ACPType as n, type ACPOf as o, type SelfACP as p, type SharingACP as q, ACPScope as r, seal as s, type ACPScopeOptions as t, unsealWithPrivateKey as u, type ACPHashFields as v, type Expand as w };
507
+ /**
508
+ * - `verified`: the chain confirms the label.
509
+ * - `mismatch`: the chain contradicts it.
510
+ * - `unverifiable`: the chain could not be asked — an unlabelled ctHash, a node without the
511
+ * state of that block (a stored value needs an archive node once its block is old), or a
512
+ * failed request.
513
+ */
514
+ type LabelVerification = 'verified' | 'mismatch' | 'unverifiable';
515
+ /**
516
+ * How much of a share's labels a reader checks against the chain. Labels are the issuer's claim:
517
+ * - `all` (default): every label — one `getLogs` per contract and block, one call per stored value;
518
+ * - `events`: event values only, which any node can answer however old the block;
519
+ * - `none`: trust the labels as written, no requests (the issuer previewing their own share).
520
+ */
521
+ type ShareLabelVerifyMode = 'all' | 'events' | 'none';
522
+ /** A label's verification, or `skipped` when the verify mode leaves it unchecked. */
523
+ type ShareLabelCheck = LabelVerification | 'skipped';
524
+ /**
525
+ * Checks one label against the chain: does the ctHash really come from where the label says?
526
+ * `issuer` is the share issuer (`acp.issuer`), which an issuer argument of a stored value stands
527
+ * for. One request.
528
+ */
529
+ declare const verifyShareLabel: (label: ShareLabel, handle: Hex, publicClient: PublicClient, issuer: Address) => Promise<LabelVerification>;
530
+ /**
531
+ * Checks the labels of a share, index for index with `handles`, as far as `verify` says. Requests
532
+ * are shared: one `getLogs` per contract and block, however many values it carries, and one call
533
+ * per distinct stored read.
534
+ */
535
+ declare const verifyShareLabels: ({ labels, handles, issuer, publicClient, verify, }: {
536
+ labels: readonly ShareLabel[];
537
+ handles: readonly Hex[];
538
+ issuer: Address;
539
+ publicClient: PublicClient;
540
+ verify?: ShareLabelVerifyMode;
541
+ }) => Promise<ShareLabelCheck[]>;
542
+
543
+ declare const getAclAddress: (publicClient: PublicClient) => Promise<Hex>;
544
+ interface AclServedAddresses {
545
+ defaultRevoker?: Hex;
546
+ shareRegistry?: Hex;
547
+ }
548
+ /** Test hook: forget resolved addresses (e.g. between redeployments on one chainId). */
549
+ declare const clearAclServedAddresses: () => void;
550
+ /**
551
+ * The ACP infrastructure addresses the chain's ACL serves (CoFHEAddressBook ->
552
+ * TaskManager -> acl() -> getters). Zero addresses and pre-upgrade ACLs (getters absent -> revert)
553
+ * resolve to `undefined` — callers fall back to `acp.*` config.
554
+ *
555
+ * Resolutions are cached per chainId. A failure to reach the TaskManager (network
556
+ * error, no CoFHE deployment) is NOT cached, so a transient outage does not pin
557
+ * an empty result for the whole session.
558
+ */
559
+ declare const getAclServedAddresses: (publicClient: PublicClient, chainId: number) => Promise<AclServedAddresses>;
560
+
561
+ export { type ACP as A, type EIP712Type as B, type CreateSelfACPOptions as C, type ACPPrivate as D, type EventValueLabel as E, type ACPType as F, GenerateSealingKey as G, type ACPOf as H, type ImportSharedACPOptions as I, type SelfACP as J, type SharingACP as K, type LabelledShare as L, ACPScope as M, type ACPScopeOptions as N, type ACPAccessStatus as O, type ACPHashFields as P, type Expand as Q, type RecipientACP as R, type ShareLabel as S, type UnlabelledLabel as U, type ValidationResult as V, type StoredValueLabel as a, type ACPPublic as b, type ACPSignaturePrimaryType as c, type EIP712Types as d, type EIP712Message as e, type SerializedACP as f, type CreateSharingACPOptions as g, type ACPMetadata as h, type SharedACP as i, type IncomingShare as j, type EIP712Domain as k, ACPUtils as l, getAclAddress as m, getAclServedAddresses as n, clearAclServedAddresses as o, type AclServedAddresses as p, type SealingKeyPair as q, type EthEncryptedData as r, seal as s, type ShareLabelReadArg as t, unsealWithPrivateKey as u, type LabelVerification as v, type ShareLabelVerifyMode as w, type ShareLabelCheck as x, verifyShareLabel as y, verifyShareLabels as z };
@@ -1,4 +1,4 @@
1
- import { Hex, PublicClient, WalletClient } from 'viem';
1
+ import { Hex, Address, PublicClient, WalletClient } from 'viem';
2
2
 
3
3
  type EthEncryptedData = {
4
4
  data: Uint8Array;
@@ -35,6 +35,52 @@ declare const seal: (value: bigint | number, publicKey: string) => EthEncryptedD
35
35
  */
36
36
  declare const unsealWithPrivateKey: (privateKey: string, parsedData: EthEncryptedData) => bigint;
37
37
 
38
+ /**
39
+ * A label says where one ctHash of a SNAPSHOT share came from, as something the recipient can
40
+ * check against the chain. It speaks of contracts, selectors and positions in the chain only:
41
+ * it does not know what a token, a balance or a transfer is. A reader that recognises a selector
42
+ * can present the value accordingly (see `describeShareMetadata`). A share carries one label per
43
+ * ctHash, in the order of `acp.handles`, so the ctHashes themselves are never repeated.
44
+ */
45
+ /** One argument of a stored-value read: the share issuer, or a literal 32-byte ABI word. */
46
+ type ShareLabelReadArg = {
47
+ type: 'issuer';
48
+ } | {
49
+ type: 'word';
50
+ value: Hex;
51
+ };
52
+ /** A stored value: what a view function of a contract returned at a block. */
53
+ type StoredValueLabel = {
54
+ kind: 'stored';
55
+ contract: Address;
56
+ /** 4-byte selector of the view function. */
57
+ selector: Hex;
58
+ /** Static ABI types only: each argument is one 32-byte word. */
59
+ args: ShareLabelReadArg[];
60
+ /** Which 32-byte word of the return data is the ctHash (0 for a single return value). */
61
+ returnWord: number;
62
+ /** Block the value was read at (on Arbitrum: the L2 block number). */
63
+ block: bigint;
64
+ };
65
+ /** An event value: a value carried by one event (log) that a contract emitted. */
66
+ type EventValueLabel = {
67
+ kind: 'event';
68
+ contract: Address;
69
+ /** Block of the log (on Arbitrum: the L2 block number). */
70
+ block: bigint;
71
+ /** Index of the log's transaction within its block. */
72
+ txIndex: number;
73
+ /** Block-wide index of the log, as RPC nodes return it. */
74
+ logIndex: number;
75
+ /** First 4 bytes of the log's topic0: the event selector. */
76
+ selector: Hex;
77
+ };
78
+ /** The issuer chose not to say where the ctHash came from. */
79
+ type UnlabelledLabel = {
80
+ kind: 'unlabelled';
81
+ };
82
+ type ShareLabel = StoredValueLabel | EventValueLabel | UnlabelledLabel;
83
+
38
84
  /**
39
85
  * EIP712 related types
40
86
  */
@@ -76,6 +122,12 @@ interface ACPPrivate {
76
122
  * Never leaves the client.
77
123
  */
78
124
  sealingPrivateKey: Hex;
125
+ /**
126
+ * (sharing / recipient) The share metadata: the labels of its handles, a v3 blob
127
+ * (`decodeShareMetadata` / `describeShareMetadata`). Not signed; travels with the share, in the
128
+ * exported JSON or in the registry's `Shared` event. Absent when the share has none.
129
+ */
130
+ metadata?: Hex;
79
131
  /**
80
132
  * EIP712 domain used to sign this acp.
81
133
  * Should not be set manually, included in metadata as part of serialization flows.
@@ -211,37 +263,73 @@ type CreateSharingACPOptions = ACPScopeOptions & {
211
263
  expiration?: number;
212
264
  revokerData?: number;
213
265
  revokerContract?: string;
266
+ /**
267
+ * The labels of the handles, one per handle in order. Kept on the acp as `metadata`, then
268
+ * written into `export()` and posted by `shareOnChain`.
269
+ */
270
+ labels?: readonly ShareLabel[];
271
+ /**
272
+ * The key of the app the share is for (`shareAppKey(app)`), kept in `metadata` with the labels.
273
+ * A client configured with `acp: { app }` fills it in; a recipient client with the same `app`
274
+ * lists the share, one with another app does not.
275
+ */
276
+ appKey?: Hex;
214
277
  };
278
+ /** A share as exported (`SharedACP`) or read from the registry. A `name` in it is ignored. */
215
279
  type ImportSharedACPOptions = ACPScopeOptions & {
216
280
  type?: 'sharing';
217
281
  issuer: string;
218
282
  recipient: string;
219
283
  issuerSignature: string;
220
- name?: string;
221
284
  expiration: number;
222
285
  revokerData?: number;
223
286
  revokerContract?: string;
287
+ /** The share metadata (labels blob), kept on the recipient acp; `0x` or absent for none. */
288
+ metadata?: string;
224
289
  };
225
290
  /** An ACP is plain JSON-serializable data — the serialized form is the ACP itself. */
226
291
  type SerializedACP = ACP;
227
292
  /**
228
293
  * The share payload produced by `ACPUtils.export()` — the full public component
229
294
  * with `sealingKey`/`recipientSignature` left for the recipient to fill, plus
230
- * the display name and acp type. Fixed shape: every field is always present
295
+ * the acp type. The issuer's `name` is not exported: it is their own note, and the
296
+ * recipient names the share themselves. Fixed shape: every field is always present
231
297
  * (zero-values instead of omissions), so importers can parse a single schema.
232
- * Mirrors the on-chain sharing payload struct field-for-field.
298
+ * Mirrors the on-chain sharing payload struct field-for-field. The one optional
299
+ * field is `metadata`, the labels of the handles, present only when the share has them.
233
300
  */
234
301
  type SharedACP = Expand<Omit<ACPPublic, 'sealingKey' | 'recipientSignature'> & {
235
- name: string;
236
302
  type: 'sharing';
303
+ metadata?: Hex;
237
304
  }>;
305
+ /**
306
+ * An ACP on-chain status, as `client.acp.checkAccess` reports it instead of a revert.
307
+ * Without a handle: 'valid' or the reason it is not. With a handle, a valid ACP reports
308
+ * 'allowed', 'out-of-scope' (the ACP scope does not cover the handle) or
309
+ * 'issuer-not-allowed' (the issuer itself may not read the handle, so no ACP of theirs can).
310
+ */
311
+ type ACPAccessStatus = 'valid' | 'allowed' | 'out-of-scope' | 'issuer-not-allowed' | 'expired' | 'revoked' | 'invalid-issuer-signature' | 'invalid-recipient-signature';
238
312
  /**
239
313
  * A share read back from the on-chain ACPShareRegistry: the posted payload
240
- * (SharedACP minus the client-side name/type) plus its registry id.
314
+ * (SharedACP minus its type), its registry id, and the
315
+ * metadata blob posted with it (`0x` when none) — for a SNAPSHOT share, the
316
+ * labels of its handles (`decodeShareMetadata` / `describeShareMetadata`).
241
317
  */
242
- type IncomingShare = Expand<Omit<SharedACP, 'name' | 'type'> & {
318
+ type IncomingShare = Expand<Omit<SharedACP, 'type' | 'metadata'> & {
243
319
  shareId: Hex;
320
+ metadata: Hex;
321
+ /** The key of the app the share was posted for (`shareAppKey(app)`), when it names one. */
322
+ appKey?: Hex;
244
323
  }>;
324
+ /**
325
+ * What the share label helpers read: the handles, their issuer and the metadata blob. An
326
+ * `IncomingShare` (on-chain route) and a sharing or recipient `ACP` (exported JSON route) both fit.
327
+ */
328
+ type LabelledShare = {
329
+ issuer: Hex;
330
+ handles: readonly Hex[];
331
+ metadata?: Hex;
332
+ };
245
333
  /**
246
334
  * A type representing the acp fields that are used to generate the hash
247
335
  */
@@ -274,9 +362,12 @@ declare const ACPUtils: {
274
362
  */
275
363
  createSharing: (options: CreateSharingACPOptions) => SharingACP;
276
364
  /**
277
- * Import a shared acp from various input formats
365
+ * Import a shared acp from various input formats. The acp is named `name`, or after its issuer
366
+ * ("Shared by 0x1234…abcd"); a `name` in the share itself is ignored.
278
367
  */
279
- importShared: (options: ImportSharedACPOptions | string) => RecipientACP;
368
+ importShared: (options: ImportSharedACPOptions | string, { name }?: {
369
+ name?: string;
370
+ }) => RecipientACP;
280
371
  /**
281
372
  * Sign an ACP with the provided wallet client
282
373
  */
@@ -292,7 +383,9 @@ declare const ACPUtils: {
292
383
  /**
293
384
  * Import and sign a shared acp in one operation from various input formats
294
385
  */
295
- importSharedAndSign: (options: ImportSharedACPOptions | string, publicClient: PublicClient, walletClient: WalletClient) => Promise<RecipientACP>;
386
+ importSharedAndSign: (options: ImportSharedACPOptions | string, publicClient: PublicClient, walletClient: WalletClient, importOptions?: {
387
+ name?: string;
388
+ }) => Promise<RecipientACP>;
296
389
  /**
297
390
  * Deserialize an ACP from serialized data
298
391
  */
@@ -317,6 +410,7 @@ declare const ACPUtils: {
317
410
  handles: `0x${string}`[];
318
411
  issuerSignature: `0x${string}`;
319
412
  recipientSignature: `0x${string}`;
413
+ metadata?: `0x${string}` | undefined;
320
414
  sealingPrivateKey?: string | undefined;
321
415
  sealingKey?: string | undefined;
322
416
  };
@@ -343,6 +437,7 @@ declare const ACPUtils: {
343
437
  handles: `0x${string}`[];
344
438
  issuerSignature: `0x${string}`;
345
439
  recipientSignature: `0x${string}`;
440
+ metadata?: `0x${string}` | undefined;
346
441
  sealingPrivateKey?: string | undefined;
347
442
  sealingKey?: string | undefined;
348
443
  };
@@ -358,7 +453,7 @@ declare const ACPUtils: {
358
453
  /**
359
454
  * Export acp data for sharing (strips the private component).
360
455
  * Fixed `SharedACP` shape — every field always present, aligned with
361
- * `ACPPublic` and the on-chain sharing payload.
456
+ * `ACPPublic` and the on-chain sharing payload — plus `metadata` when the acp has labels.
362
457
  */
363
458
  export: (acp: ACP) => string;
364
459
  /**
@@ -402,6 +497,65 @@ declare const ACPUtils: {
402
497
  * Check if acp passes the on-chain validation
403
498
  */
404
499
  checkValidityOnChain: (acp: ACP, publicClient: PublicClient) => Promise<boolean>;
500
+ /**
501
+ * The acp on-chain status as a value instead of a revert: 'valid' or why not, and given a
502
+ * handle, whether the acp may read it (see `ACPAccessStatus`).
503
+ */
504
+ checkAccessOnChain: (acp: ACP, publicClient: PublicClient, handle?: bigint | Hex) => Promise<ACPAccessStatus>;
405
505
  };
406
506
 
407
- export { type ACP as A, type CreateSelfACPOptions as C, type EIP712Types as E, GenerateSealingKey as G, type ImportSharedACPOptions as I, type RecipientACP as R, type SerializedACP as S, type ValidationResult as V, type ACPPublic as a, type ACPSignaturePrimaryType as b, type EIP712Message as c, type CreateSharingACPOptions as d, type ACPMetadata as e, type SharedACP as f, type IncomingShare as g, type EIP712Domain as h, ACPUtils as i, type SealingKeyPair as j, type EthEncryptedData as k, type EIP712Type as l, type ACPPrivate as m, type ACPType as n, type ACPOf as o, type SelfACP as p, type SharingACP as q, ACPScope as r, seal as s, type ACPScopeOptions as t, unsealWithPrivateKey as u, type ACPHashFields as v, type Expand as w };
507
+ /**
508
+ * - `verified`: the chain confirms the label.
509
+ * - `mismatch`: the chain contradicts it.
510
+ * - `unverifiable`: the chain could not be asked — an unlabelled ctHash, a node without the
511
+ * state of that block (a stored value needs an archive node once its block is old), or a
512
+ * failed request.
513
+ */
514
+ type LabelVerification = 'verified' | 'mismatch' | 'unverifiable';
515
+ /**
516
+ * How much of a share's labels a reader checks against the chain. Labels are the issuer's claim:
517
+ * - `all` (default): every label — one `getLogs` per contract and block, one call per stored value;
518
+ * - `events`: event values only, which any node can answer however old the block;
519
+ * - `none`: trust the labels as written, no requests (the issuer previewing their own share).
520
+ */
521
+ type ShareLabelVerifyMode = 'all' | 'events' | 'none';
522
+ /** A label's verification, or `skipped` when the verify mode leaves it unchecked. */
523
+ type ShareLabelCheck = LabelVerification | 'skipped';
524
+ /**
525
+ * Checks one label against the chain: does the ctHash really come from where the label says?
526
+ * `issuer` is the share issuer (`acp.issuer`), which an issuer argument of a stored value stands
527
+ * for. One request.
528
+ */
529
+ declare const verifyShareLabel: (label: ShareLabel, handle: Hex, publicClient: PublicClient, issuer: Address) => Promise<LabelVerification>;
530
+ /**
531
+ * Checks the labels of a share, index for index with `handles`, as far as `verify` says. Requests
532
+ * are shared: one `getLogs` per contract and block, however many values it carries, and one call
533
+ * per distinct stored read.
534
+ */
535
+ declare const verifyShareLabels: ({ labels, handles, issuer, publicClient, verify, }: {
536
+ labels: readonly ShareLabel[];
537
+ handles: readonly Hex[];
538
+ issuer: Address;
539
+ publicClient: PublicClient;
540
+ verify?: ShareLabelVerifyMode;
541
+ }) => Promise<ShareLabelCheck[]>;
542
+
543
+ declare const getAclAddress: (publicClient: PublicClient) => Promise<Hex>;
544
+ interface AclServedAddresses {
545
+ defaultRevoker?: Hex;
546
+ shareRegistry?: Hex;
547
+ }
548
+ /** Test hook: forget resolved addresses (e.g. between redeployments on one chainId). */
549
+ declare const clearAclServedAddresses: () => void;
550
+ /**
551
+ * The ACP infrastructure addresses the chain's ACL serves (CoFHEAddressBook ->
552
+ * TaskManager -> acl() -> getters). Zero addresses and pre-upgrade ACLs (getters absent -> revert)
553
+ * resolve to `undefined` — callers fall back to `acp.*` config.
554
+ *
555
+ * Resolutions are cached per chainId. A failure to reach the TaskManager (network
556
+ * error, no CoFHE deployment) is NOT cached, so a transient outage does not pin
557
+ * an empty result for the whole session.
558
+ */
559
+ declare const getAclServedAddresses: (publicClient: PublicClient, chainId: number) => Promise<AclServedAddresses>;
560
+
561
+ export { type ACP as A, type EIP712Type as B, type CreateSelfACPOptions as C, type ACPPrivate as D, type EventValueLabel as E, type ACPType as F, GenerateSealingKey as G, type ACPOf as H, type ImportSharedACPOptions as I, type SelfACP as J, type SharingACP as K, type LabelledShare as L, ACPScope as M, type ACPScopeOptions as N, type ACPAccessStatus as O, type ACPHashFields as P, type Expand as Q, type RecipientACP as R, type ShareLabel as S, type UnlabelledLabel as U, type ValidationResult as V, type StoredValueLabel as a, type ACPPublic as b, type ACPSignaturePrimaryType as c, type EIP712Types as d, type EIP712Message as e, type SerializedACP as f, type CreateSharingACPOptions as g, type ACPMetadata as h, type SharedACP as i, type IncomingShare as j, type EIP712Domain as k, ACPUtils as l, getAclAddress as m, getAclServedAddresses as n, clearAclServedAddresses as o, type AclServedAddresses as p, type SealingKeyPair as q, type EthEncryptedData as r, seal as s, type ShareLabelReadArg as t, unsealWithPrivateKey as u, type LabelVerification as v, type ShareLabelVerifyMode as w, type ShareLabelCheck as x, verifyShareLabel as y, verifyShareLabels as z };