@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.
- package/CHANGELOG.md +35 -0
- package/acps/acp.ts +35 -7
- package/acps/index.ts +28 -12
- package/acps/onchain-utils.ts +188 -49
- package/acps/registry.ts +231 -0
- package/acps/sealing.ts +9 -3
- package/acps/share-metadata/appKey.ts +8 -0
- package/acps/share-metadata/decode.ts +120 -0
- package/acps/share-metadata/describe.ts +198 -0
- package/acps/share-metadata/encode.ts +147 -0
- package/acps/share-metadata/erc7984.ts +26 -0
- package/acps/share-metadata/index.ts +9 -0
- package/acps/share-metadata/layout.ts +69 -0
- package/acps/share-metadata/presets.ts +116 -0
- package/acps/share-metadata/schema.ts +47 -0
- package/acps/share-metadata/test/codec.test.ts +140 -0
- package/acps/share-metadata/test/describe.test.ts +112 -0
- package/acps/share-metadata/test/fixtures.ts +157 -0
- package/acps/share-metadata/test/live.test.ts +56 -0
- package/acps/share-metadata/test/presets.test.ts +119 -0
- package/acps/share-metadata/test/verify.test.ts +144 -0
- package/acps/share-metadata/verify.ts +155 -0
- package/acps/store.ts +48 -18
- package/acps/test/acp.test.ts +102 -7
- package/acps/test/localstorage.test.ts +28 -1
- package/acps/test/onchainAccessStatus.test.ts +116 -0
- package/acps/test/registry.test.ts +144 -0
- package/acps/test/sealing.test.ts +23 -0
- package/acps/test/store.test.ts +71 -0
- package/acps/test/utils.test.ts +63 -0
- package/acps/test/validation.test.ts +0 -4
- package/acps/types.ts +59 -6
- package/acps/utils.ts +15 -2
- package/acps/validation.ts +3 -1
- package/chains/chains/arbitrum.ts +14 -0
- package/chains/chains/ethereum.ts +14 -0
- package/chains/index.ts +5 -1
- package/chains/test/chains.test.ts +24 -3
- package/core/acps.ts +164 -207
- package/core/client.ts +44 -13
- package/core/clientTypes.ts +50 -7
- package/core/config.ts +33 -1
- package/core/consts.ts +14 -2
- package/core/decrypt/apiError.ts +4 -1
- package/core/decrypt/verifyDecryptResult.ts +8 -4
- package/core/encrypt/cofheMocksZkVerifySign.ts +19 -2
- package/core/encrypt/encryptInputsBuilder.ts +6 -0
- package/core/encrypt/zkPackProveVerify.ts +7 -1
- package/core/error.ts +1 -0
- package/core/fetchKeys.ts +2 -2
- package/core/index.ts +9 -1
- package/core/keyStore.ts +23 -10
- package/core/taskManager.ts +48 -0
- package/core/test/acpDefaults.test.ts +108 -19
- package/core/test/acpStoreAccountCase.test.ts +80 -0
- package/core/test/acps.test.ts +128 -3
- package/core/test/apiError.test.ts +8 -0
- package/core/test/appKeyConfig.test.ts +94 -0
- package/core/test/client.test.ts +41 -0
- package/core/test/config.test.ts +24 -0
- package/core/test/decrypt.test.ts +11 -4
- package/core/test/decryptBuilders.test.ts +110 -2
- package/core/test/encryptInputsBuilder.test.ts +1 -1
- package/core/test/fetchKeys.test.ts +23 -2
- package/core/test/incomingShares.test.ts +84 -0
- package/core/test/keyStore.test.ts +18 -6
- package/core/test/mocksEncryptRange.test.ts +90 -0
- package/core/test/taskManager.test.ts +57 -0
- package/core/test/utils.test.ts +128 -0
- package/core/test/verifyDecryptResult.test.ts +51 -0
- package/core/types.ts +8 -0
- package/core/utils.ts +16 -9
- package/dist/acps.cjs +984 -64
- package/dist/acps.d.cts +589 -10
- package/dist/acps.d.ts +589 -10
- package/dist/acps.js +2 -2
- package/dist/chains.cjs +26 -0
- package/dist/chains.d.cts +45 -1
- package/dist/chains.d.ts +45 -1
- package/dist/chains.js +1 -1
- package/dist/chunk-6ZW76ZKB.js +228 -0
- package/dist/chunk-BQWHPIYU.js +1828 -0
- package/dist/chunk-KSOV5B4B.js +50 -0
- package/dist/{chunk-43USWPEH.js → chunk-OL3DZN7A.js} +159 -523
- package/dist/{chunk-N6IDQRRU.js → chunk-UKQAJK4N.js} +25 -1
- package/dist/chunk-XQ32JG3T.js +174 -0
- package/dist/{clientTypes-CYZjFznO.d.cts → clientTypes-C0A9ji5O.d.cts} +132 -29
- package/dist/{clientTypes-BN3nbzYM.d.ts → clientTypes-CcU5WvdV.d.ts} +132 -29
- package/dist/core.cjs +3269 -2626
- package/dist/core.d.cts +32 -8
- package/dist/core.d.ts +32 -8
- package/dist/core.js +5 -4
- package/dist/node.cjs +3074 -2436
- package/dist/node.d.cts +2 -2
- package/dist/node.d.ts +2 -2
- package/dist/node.js +20 -19
- package/dist/{acp-Wi6isVQI.d.cts → onchain-utils-D9Z33IP7.d.cts} +166 -12
- package/dist/{acp-Wi6isVQI.d.ts → onchain-utils-D9Z33IP7.d.ts} +166 -12
- package/dist/web.cjs +3204 -2493
- package/dist/web.d.cts +49 -3
- package/dist/web.d.ts +49 -3
- package/dist/web.js +52 -27
- package/dist/zkProve.worker.cjs +79 -18
- package/dist/zkProve.worker.js +24 -24
- package/node/index.ts +1 -10
- package/node/storage.ts +20 -9
- package/node/test/inherited.test.ts +5 -1
- package/node/test/storage-memory-fallback.test.ts +47 -0
- package/node/test/storage-permissions.test.ts +40 -0
- package/package.json +3 -1
- package/web/index.ts +101 -36
- package/web/test/countingZkProveWorker.ts +31 -0
- package/web/test/inherited.web.test.ts +5 -1
- package/web/test/mainThreadPool.web.test.ts +174 -0
- package/web/test/threadPoolBenchHelper.ts +134 -0
- package/web/test/threadPoolOff.web.test.ts +17 -0
- package/web/test/threadPoolOn.web.test.ts +80 -0
- package/web/test/workerInitRace.web.test.ts +79 -0
- package/web/tfheThreadPool.ts +140 -0
- package/web/workerManager.ts +4 -2
- package/web/zkProve.worker.ts +42 -26
- package/dist/chunk-ESMZCFJY.js +0 -12
- package/dist/chunk-Q7CBWGQX.js +0 -1029
package/dist/acps.cjs
CHANGED
|
@@ -14,9 +14,14 @@ var nacl__default = /*#__PURE__*/_interopDefault(nacl);
|
|
|
14
14
|
// acps/acp.ts
|
|
15
15
|
|
|
16
16
|
// acps/utils.ts
|
|
17
|
+
var HEX_BODY_REGEX = /^[0-9a-fA-F]*$/;
|
|
17
18
|
var fromHexString = (hexString) => {
|
|
18
|
-
const
|
|
19
|
-
|
|
19
|
+
const body = hexString.replace(/^0x/, "");
|
|
20
|
+
if (!HEX_BODY_REGEX.test(body)) {
|
|
21
|
+
throw new Error("Invalid hex string: contains non-hexadecimal characters");
|
|
22
|
+
}
|
|
23
|
+
const padded = body.length % 2 === 1 ? `0${body}` : body;
|
|
24
|
+
const arr = padded.match(/.{1,2}/g);
|
|
20
25
|
if (!arr)
|
|
21
26
|
return new Uint8Array();
|
|
22
27
|
return new Uint8Array(arr.map((byte) => parseInt(byte, 16)));
|
|
@@ -73,7 +78,7 @@ var GenerateSealingKey = () => {
|
|
|
73
78
|
var seal = (value, publicKey) => {
|
|
74
79
|
isString(publicKey);
|
|
75
80
|
isBigIntOrNumber(value);
|
|
76
|
-
|
|
81
|
+
assertSealingKey(publicKey, "Public");
|
|
77
82
|
const ephemeralKeyPair = nacl__default.default.box.keyPair();
|
|
78
83
|
const nonce = nacl__default.default.randomBytes(nacl__default.default.box.nonceLength);
|
|
79
84
|
const encryptedMessage = nacl__default.default.box(toBeArray(value), nonce, fromHexString(publicKey), ephemeralKeyPair.secretKey);
|
|
@@ -84,7 +89,7 @@ var seal = (value, publicKey) => {
|
|
|
84
89
|
};
|
|
85
90
|
};
|
|
86
91
|
var unsealWithPrivateKey = (privateKey, parsedData) => {
|
|
87
|
-
|
|
92
|
+
assertSealingKey(privateKey, "Private");
|
|
88
93
|
const nonce = parsedData.nonce instanceof Uint8Array ? parsedData.nonce : new Uint8Array(parsedData.nonce);
|
|
89
94
|
const ephemPublicKey = parsedData.public_key instanceof Uint8Array ? parsedData.public_key : new Uint8Array(parsedData.public_key);
|
|
90
95
|
const dataToDecrypt = parsedData.data instanceof Uint8Array ? parsedData.data : new Uint8Array(parsedData.data);
|
|
@@ -94,11 +99,14 @@ var unsealWithPrivateKey = (privateKey, parsedData) => {
|
|
|
94
99
|
}
|
|
95
100
|
return toBigInt(decryptedMessage);
|
|
96
101
|
};
|
|
97
|
-
var
|
|
102
|
+
var assertSealingKey = (key, kind) => {
|
|
98
103
|
const bare = key.startsWith("0x") ? key.slice(2) : key;
|
|
99
104
|
if (bare.length !== KEY_HEX_LENGTH) {
|
|
100
105
|
throw new Error(`${kind} key must be of length ${KEY_HEX_LENGTH}`);
|
|
101
106
|
}
|
|
107
|
+
if (!/^[0-9a-fA-F]+$/.test(bare)) {
|
|
108
|
+
throw new Error(`${kind} key must contain only hex characters`);
|
|
109
|
+
}
|
|
102
110
|
};
|
|
103
111
|
var ACPScope = {
|
|
104
112
|
Global: 0,
|
|
@@ -151,7 +159,8 @@ var zACPWithDefaults = zod.z.object({
|
|
|
151
159
|
contracts: contractsSchema,
|
|
152
160
|
handles: handlesSchema,
|
|
153
161
|
issuerSignature: bytesSchema.optional().default("0x"),
|
|
154
|
-
recipientSignature: bytesSchema.optional().default("0x")
|
|
162
|
+
recipientSignature: bytesSchema.optional().default("0x"),
|
|
163
|
+
metadata: bytesSchema.optional()
|
|
155
164
|
});
|
|
156
165
|
var zACPWithSealingKeys = zACPWithDefaults.extend({
|
|
157
166
|
/** X25519 private key, 0x-prefixed 32-byte hex; never leaves the client */
|
|
@@ -222,7 +231,6 @@ var ImportACPOptionsValidator = zod.z.object({
|
|
|
222
231
|
type: zod.z.literal("recipient").optional().default("recipient"),
|
|
223
232
|
issuer: addressNotZeroSchema,
|
|
224
233
|
recipient: addressNotZeroSchema,
|
|
225
|
-
name: zod.z.string().optional().default("Unnamed ACP"),
|
|
226
234
|
expiration: zod.z.int(),
|
|
227
235
|
revokerData: zod.z.int().optional().default(0),
|
|
228
236
|
revokerContract: addressSchema.optional().default(viem.zeroAddress),
|
|
@@ -230,7 +238,9 @@ var ImportACPOptionsValidator = zod.z.object({
|
|
|
230
238
|
contracts: contractsSchema,
|
|
231
239
|
handles: handlesSchema,
|
|
232
240
|
issuerSignature: bytesNotEmptySchema,
|
|
233
|
-
recipientSignature: bytesSchema.optional().default("0x")
|
|
241
|
+
recipientSignature: bytesSchema.optional().default("0x"),
|
|
242
|
+
/** The share metadata (labels blob); `0x` means none and is dropped */
|
|
243
|
+
metadata: bytesSchema.optional().transform((val) => val === "0x" ? void 0 : val)
|
|
234
244
|
}).refine(...ExternalValidatorRefinement).transform(withDerivedScope).refine(...ScopeConsistencyRefinement);
|
|
235
245
|
var ImportACPValidator = zACPWithSealingKeys.refine((data) => data.type === "recipient", {
|
|
236
246
|
error: "Type must be 'recipient'"
|
|
@@ -398,15 +408,139 @@ var SignatureUtils = {
|
|
|
398
408
|
};
|
|
399
409
|
|
|
400
410
|
// core/consts.ts
|
|
401
|
-
var
|
|
411
|
+
var COFHE_ADDRESS_BOOK_ADDRESS = "0xC0F4e00E531a2B086492Ae3DCC1515038307196b";
|
|
412
|
+
var TASK_MANAGER_ID = 1n;
|
|
402
413
|
BigInt(1 << 30);
|
|
403
414
|
|
|
415
|
+
// core/error.ts
|
|
416
|
+
var CofheError = class _CofheError extends Error {
|
|
417
|
+
code;
|
|
418
|
+
cause;
|
|
419
|
+
hint;
|
|
420
|
+
context;
|
|
421
|
+
apiErrorCode;
|
|
422
|
+
constructor({ code, message, cause, hint, context, apiErrorCode }) {
|
|
423
|
+
const fullMessage = cause ? `${message} | Caused by: ${cause.message}` : message;
|
|
424
|
+
super(fullMessage);
|
|
425
|
+
this.name = "CofheError";
|
|
426
|
+
this.code = code;
|
|
427
|
+
this.cause = cause;
|
|
428
|
+
this.hint = hint;
|
|
429
|
+
this.context = context;
|
|
430
|
+
this.apiErrorCode = apiErrorCode;
|
|
431
|
+
if (Error.captureStackTrace) {
|
|
432
|
+
Error.captureStackTrace(this, _CofheError);
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
/**
|
|
436
|
+
* Creates a CofheError from an unknown error
|
|
437
|
+
* If the error is a CofheError, it is returned unchanged, else a new CofheError is created
|
|
438
|
+
* If a wrapperError is provided, it is used to create the new CofheError, else a default is used
|
|
439
|
+
*/
|
|
440
|
+
static fromError(error, wrapperError) {
|
|
441
|
+
if (isCofheError(error))
|
|
442
|
+
return error;
|
|
443
|
+
const cause = error instanceof Error ? error : new Error(`${error}`);
|
|
444
|
+
return new _CofheError({
|
|
445
|
+
code: wrapperError?.code ?? "INTERNAL_ERROR" /* InternalError */,
|
|
446
|
+
message: wrapperError?.message ?? "An internal error occurred",
|
|
447
|
+
hint: wrapperError?.hint,
|
|
448
|
+
context: wrapperError?.context,
|
|
449
|
+
apiErrorCode: wrapperError?.apiErrorCode,
|
|
450
|
+
cause
|
|
451
|
+
});
|
|
452
|
+
}
|
|
453
|
+
/**
|
|
454
|
+
* Serializes the error to JSON string with proper handling of Error objects
|
|
455
|
+
*/
|
|
456
|
+
serialize() {
|
|
457
|
+
return bigintSafeJsonStringify({
|
|
458
|
+
name: this.name,
|
|
459
|
+
code: this.code,
|
|
460
|
+
message: this.message,
|
|
461
|
+
hint: this.hint,
|
|
462
|
+
context: this.context,
|
|
463
|
+
apiErrorCode: this.apiErrorCode,
|
|
464
|
+
cause: this.cause ? {
|
|
465
|
+
name: this.cause.name,
|
|
466
|
+
message: this.cause.message,
|
|
467
|
+
stack: this.cause.stack
|
|
468
|
+
} : void 0,
|
|
469
|
+
stack: this.stack
|
|
470
|
+
});
|
|
471
|
+
}
|
|
472
|
+
/**
|
|
473
|
+
* Returns a human-readable string representation of the error
|
|
474
|
+
*/
|
|
475
|
+
toString() {
|
|
476
|
+
const codeSuffix = this.apiErrorCode ? ` (api: ${this.apiErrorCode})` : "";
|
|
477
|
+
const parts = [`${this.name} [${this.code}]${codeSuffix}: ${this.message}`];
|
|
478
|
+
if (this.hint) {
|
|
479
|
+
parts.push(`Hint: ${this.hint}`);
|
|
480
|
+
}
|
|
481
|
+
if (this.context && Object.keys(this.context).length > 0) {
|
|
482
|
+
parts.push(`Context: ${bigintSafeJsonStringify(this.context)}`);
|
|
483
|
+
}
|
|
484
|
+
if (this.stack) {
|
|
485
|
+
parts.push(`
|
|
486
|
+
Stack trace:`);
|
|
487
|
+
parts.push(this.stack);
|
|
488
|
+
}
|
|
489
|
+
if (this.cause) {
|
|
490
|
+
parts.push(`
|
|
491
|
+
Caused by: ${this.cause.name}: ${this.cause.message}`);
|
|
492
|
+
if (this.cause.stack) {
|
|
493
|
+
parts.push(this.cause.stack);
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
return parts.join("\n");
|
|
497
|
+
}
|
|
498
|
+
};
|
|
499
|
+
var bigintSafeJsonStringify = (value) => {
|
|
500
|
+
return JSON.stringify(value, (key, value2) => {
|
|
501
|
+
if (typeof value2 === "bigint") {
|
|
502
|
+
return `${value2}n`;
|
|
503
|
+
}
|
|
504
|
+
return value2;
|
|
505
|
+
});
|
|
506
|
+
};
|
|
507
|
+
var isCofheError = (error) => error instanceof CofheError;
|
|
508
|
+
|
|
509
|
+
// core/taskManager.ts
|
|
510
|
+
var ADDRESS_BOOK_ABI = viem.parseAbi([
|
|
511
|
+
"function getTm(uint256 id) view returns (address)",
|
|
512
|
+
"error TaskManagerNotSet(uint256 id)"
|
|
513
|
+
]);
|
|
514
|
+
var taskManagerAddressCache = /* @__PURE__ */ new Map();
|
|
515
|
+
var getTaskManagerAddress = async (publicClient, chainId) => {
|
|
516
|
+
const id = chainId ?? publicClient.chain?.id ?? await publicClient.getChainId();
|
|
517
|
+
const cached = taskManagerAddressCache.get(id);
|
|
518
|
+
if (cached != null)
|
|
519
|
+
return cached;
|
|
520
|
+
const pending = publicClient.readContract({
|
|
521
|
+
address: COFHE_ADDRESS_BOOK_ADDRESS,
|
|
522
|
+
abi: ADDRESS_BOOK_ABI,
|
|
523
|
+
functionName: "getTm",
|
|
524
|
+
args: [TASK_MANAGER_ID]
|
|
525
|
+
}).catch((error) => {
|
|
526
|
+
taskManagerAddressCache.delete(id);
|
|
527
|
+
throw CofheError.fromError(error, {
|
|
528
|
+
code: "TASK_MANAGER_UNRESOLVED" /* TaskManagerUnresolved */,
|
|
529
|
+
message: `Failed to resolve the Task Manager from the CoFHEAddressBook on chain ${id}`,
|
|
530
|
+
hint: "Ensure CoFHE is deployed on this chain. On a local hardhat / anvil chain, deploy the CoFHE mocks first.",
|
|
531
|
+
context: { chainId: id, addressBook: COFHE_ADDRESS_BOOK_ADDRESS, taskManagerId: TASK_MANAGER_ID }
|
|
532
|
+
});
|
|
533
|
+
});
|
|
534
|
+
taskManagerAddressCache.set(id, pending);
|
|
535
|
+
return pending;
|
|
536
|
+
};
|
|
537
|
+
|
|
404
538
|
// acps/onchain-utils.ts
|
|
405
539
|
var getAclAddress = async (publicClient) => {
|
|
406
540
|
const ACL_IFACE = "function acl() view returns (address)";
|
|
407
541
|
const aclAbi = viem.parseAbi([ACL_IFACE]);
|
|
408
542
|
return await publicClient.readContract({
|
|
409
|
-
address:
|
|
543
|
+
address: await getTaskManagerAddress(publicClient),
|
|
410
544
|
abi: aclAbi,
|
|
411
545
|
functionName: "acl"
|
|
412
546
|
});
|
|
@@ -433,6 +567,34 @@ var getAclEIP712Domain = async (publicClient) => {
|
|
|
433
567
|
verifyingContract
|
|
434
568
|
};
|
|
435
569
|
};
|
|
570
|
+
var toACPTuple = (acp) => ({
|
|
571
|
+
issuer: acp.issuer,
|
|
572
|
+
expiration: BigInt(acp.expiration),
|
|
573
|
+
recipient: acp.recipient,
|
|
574
|
+
revokerData: BigInt(acp.revokerData),
|
|
575
|
+
revokerContract: acp.revokerContract,
|
|
576
|
+
scope: acp.scope,
|
|
577
|
+
contracts: acp.contracts,
|
|
578
|
+
handles: acp.handles,
|
|
579
|
+
sealingKey: acp.sealingKey,
|
|
580
|
+
issuerSignature: acp.issuerSignature,
|
|
581
|
+
recipientSignature: acp.recipientSignature
|
|
582
|
+
});
|
|
583
|
+
function revertErrorName(err, abi) {
|
|
584
|
+
const walk = err?.walk;
|
|
585
|
+
if (typeof walk === "function") {
|
|
586
|
+
const revertError = walk.call(err, (e) => e?.name === "ContractFunctionRevertedError");
|
|
587
|
+
if (revertError)
|
|
588
|
+
return revertError.data?.errorName ?? "";
|
|
589
|
+
}
|
|
590
|
+
const customErrorName = extractCustomErrorFromDetails(err, abi);
|
|
591
|
+
if (customErrorName)
|
|
592
|
+
return customErrorName;
|
|
593
|
+
const hhDetailsData = extractReturnData(err);
|
|
594
|
+
if (hhDetailsData != null)
|
|
595
|
+
return viem.decodeErrorResult({ abi, data: hhDetailsData }).errorName;
|
|
596
|
+
return void 0;
|
|
597
|
+
}
|
|
436
598
|
var checkACPValidityOnChain = async (acp, publicClient) => {
|
|
437
599
|
const aclAddress = await getAclAddress(publicClient);
|
|
438
600
|
try {
|
|
@@ -440,43 +602,54 @@ var checkACPValidityOnChain = async (acp, publicClient) => {
|
|
|
440
602
|
address: aclAddress,
|
|
441
603
|
abi: checkACPValidityAbi,
|
|
442
604
|
functionName: "checkPermissionValidity",
|
|
443
|
-
args: [
|
|
444
|
-
{
|
|
445
|
-
issuer: acp.issuer,
|
|
446
|
-
expiration: BigInt(acp.expiration),
|
|
447
|
-
recipient: acp.recipient,
|
|
448
|
-
revokerData: BigInt(acp.revokerData),
|
|
449
|
-
revokerContract: acp.revokerContract,
|
|
450
|
-
scope: acp.scope,
|
|
451
|
-
contracts: acp.contracts,
|
|
452
|
-
handles: acp.handles,
|
|
453
|
-
sealingKey: acp.sealingKey,
|
|
454
|
-
issuerSignature: acp.issuerSignature,
|
|
455
|
-
recipientSignature: acp.recipientSignature
|
|
456
|
-
}
|
|
457
|
-
]
|
|
605
|
+
args: [toACPTuple(acp)]
|
|
458
606
|
});
|
|
459
607
|
return true;
|
|
460
608
|
} catch (err) {
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
609
|
+
const errorName = revertErrorName(err, checkACPValidityAbi);
|
|
610
|
+
if (errorName !== void 0)
|
|
611
|
+
throw new Error(errorName);
|
|
612
|
+
throw err;
|
|
613
|
+
}
|
|
614
|
+
};
|
|
615
|
+
var PERMISSION_ERROR_STATUS = {
|
|
616
|
+
PermissionInvalid_Expired: "expired",
|
|
617
|
+
PermissionInvalid_Disabled: "revoked",
|
|
618
|
+
PermissionInvalid_IssuerSignature: "invalid-issuer-signature",
|
|
619
|
+
PermissionInvalid_RecipientSignature: "invalid-recipient-signature"
|
|
620
|
+
};
|
|
621
|
+
var getACPAccessStatusOnChain = async (acp, publicClient, handle) => {
|
|
622
|
+
const aclAddress = await getAclAddress(publicClient);
|
|
623
|
+
try {
|
|
624
|
+
if (handle === void 0) {
|
|
625
|
+
await publicClient.simulateContract({
|
|
626
|
+
address: aclAddress,
|
|
627
|
+
abi: acpAccessAbi,
|
|
628
|
+
functionName: "checkPermissionValidity",
|
|
629
|
+
args: [toACPTuple(acp)]
|
|
477
630
|
});
|
|
478
|
-
|
|
631
|
+
return "valid";
|
|
479
632
|
}
|
|
633
|
+
const ctHash = BigInt(handle);
|
|
634
|
+
const allowed = await publicClient.readContract({
|
|
635
|
+
address: aclAddress,
|
|
636
|
+
abi: acpAccessAbi,
|
|
637
|
+
functionName: "isAllowedWithPermission",
|
|
638
|
+
args: [toACPTuple(acp), ctHash]
|
|
639
|
+
});
|
|
640
|
+
if (allowed)
|
|
641
|
+
return "allowed";
|
|
642
|
+
const issuerAllowed = await publicClient.readContract({
|
|
643
|
+
address: aclAddress,
|
|
644
|
+
abi: acpAccessAbi,
|
|
645
|
+
functionName: "isAllowed",
|
|
646
|
+
args: [ctHash, acp.issuer]
|
|
647
|
+
});
|
|
648
|
+
return issuerAllowed ? "out-of-scope" : "issuer-not-allowed";
|
|
649
|
+
} catch (err) {
|
|
650
|
+
const status = PERMISSION_ERROR_STATUS[revertErrorName(err, acpAccessAbi) ?? ""];
|
|
651
|
+
if (status)
|
|
652
|
+
return status;
|
|
480
653
|
throw err;
|
|
481
654
|
}
|
|
482
655
|
};
|
|
@@ -498,7 +671,8 @@ function extractCustomErrorFromDetails(err, abi) {
|
|
|
498
671
|
function extractReturnData(err) {
|
|
499
672
|
const anyErr = err;
|
|
500
673
|
const s = anyErr?.details ?? anyErr?.cause?.details ?? anyErr?.shortMessage ?? anyErr?.message ?? String(err);
|
|
501
|
-
|
|
674
|
+
const match = s.match(/return data:\s*(0x[a-fA-F0-9]+)/) ?? s.match(/custom error (0x[a-fA-F0-9]{8,})/);
|
|
675
|
+
return match?.[1];
|
|
502
676
|
}
|
|
503
677
|
var checkACPValidityAbi = [
|
|
504
678
|
{
|
|
@@ -598,8 +772,263 @@ var checkACPValidityAbi = [
|
|
|
598
772
|
inputs: []
|
|
599
773
|
}
|
|
600
774
|
];
|
|
775
|
+
var acpAccessAbi = [
|
|
776
|
+
...checkACPValidityAbi,
|
|
777
|
+
{
|
|
778
|
+
type: "function",
|
|
779
|
+
name: "isAllowedWithPermission",
|
|
780
|
+
inputs: [checkACPValidityAbi[0].inputs[0], { name: "handle", type: "uint256", internalType: "uint256" }],
|
|
781
|
+
outputs: [{ name: "", type: "bool", internalType: "bool" }],
|
|
782
|
+
stateMutability: "view"
|
|
783
|
+
},
|
|
784
|
+
{
|
|
785
|
+
type: "function",
|
|
786
|
+
name: "isAllowed",
|
|
787
|
+
inputs: [
|
|
788
|
+
{ name: "handle", type: "uint256", internalType: "uint256" },
|
|
789
|
+
{ name: "account", type: "address", internalType: "address" }
|
|
790
|
+
],
|
|
791
|
+
outputs: [{ name: "", type: "bool", internalType: "bool" }],
|
|
792
|
+
stateMutability: "view"
|
|
793
|
+
}
|
|
794
|
+
];
|
|
795
|
+
var ACL_SERVED_ADDRESSES_ABI = viem.parseAbi([
|
|
796
|
+
"function acl() view returns (address)",
|
|
797
|
+
"function defaultRevokerContract() view returns (address)",
|
|
798
|
+
"function shareRegistry() view returns (address)"
|
|
799
|
+
]);
|
|
800
|
+
var aclServedAddressesCache = /* @__PURE__ */ new Map();
|
|
801
|
+
var clearAclServedAddresses = () => aclServedAddressesCache.clear();
|
|
802
|
+
var getAclServedAddresses = async (publicClient, chainId) => {
|
|
803
|
+
const cached = aclServedAddressesCache.get(chainId);
|
|
804
|
+
if (cached != null)
|
|
805
|
+
return cached;
|
|
806
|
+
let aclAddress;
|
|
807
|
+
try {
|
|
808
|
+
aclAddress = await publicClient.readContract({
|
|
809
|
+
address: await getTaskManagerAddress(publicClient, chainId),
|
|
810
|
+
abi: ACL_SERVED_ADDRESSES_ABI,
|
|
811
|
+
functionName: "acl"
|
|
812
|
+
});
|
|
813
|
+
} catch {
|
|
814
|
+
return {};
|
|
815
|
+
}
|
|
816
|
+
const [defaultRevoker, shareRegistry] = await Promise.all([
|
|
817
|
+
publicClient.readContract({ address: aclAddress, abi: ACL_SERVED_ADDRESSES_ABI, functionName: "defaultRevokerContract" }).catch(() => void 0),
|
|
818
|
+
publicClient.readContract({ address: aclAddress, abi: ACL_SERVED_ADDRESSES_ABI, functionName: "shareRegistry" }).catch(() => void 0)
|
|
819
|
+
]);
|
|
820
|
+
const resolved = {
|
|
821
|
+
defaultRevoker: defaultRevoker != null && defaultRevoker !== viem.zeroAddress ? defaultRevoker : void 0,
|
|
822
|
+
shareRegistry: shareRegistry != null && shareRegistry !== viem.zeroAddress ? shareRegistry : void 0
|
|
823
|
+
};
|
|
824
|
+
aclServedAddressesCache.set(chainId, resolved);
|
|
825
|
+
return resolved;
|
|
826
|
+
};
|
|
827
|
+
|
|
828
|
+
// acps/share-metadata/layout.ts
|
|
829
|
+
var LAYOUT_VERSION = 3;
|
|
830
|
+
var ENTRY_KIND = {
|
|
831
|
+
stored: 0,
|
|
832
|
+
event: 1,
|
|
833
|
+
unlabelled: 255
|
|
834
|
+
};
|
|
835
|
+
var ARGS_CODE = {
|
|
836
|
+
none: 0,
|
|
837
|
+
issuer: 1,
|
|
838
|
+
explicit: 255
|
|
839
|
+
};
|
|
840
|
+
var ARG_TAG = {
|
|
841
|
+
word: 0,
|
|
842
|
+
issuer: 1
|
|
843
|
+
};
|
|
844
|
+
var APP_KEY_TAG = 1;
|
|
845
|
+
var BYTE_WIDTH = {
|
|
846
|
+
version: 1,
|
|
847
|
+
/** Length of a list, and a position in it: at most 255 of each per share. */
|
|
848
|
+
count: 1,
|
|
849
|
+
index: 1,
|
|
850
|
+
address: 20,
|
|
851
|
+
selector: 4,
|
|
852
|
+
/** uint32: 4.29 billion blocks. */
|
|
853
|
+
block: 4,
|
|
854
|
+
/** uint16: the position of a transaction within its block. */
|
|
855
|
+
txIndex: 2,
|
|
856
|
+
/** uint16: the block-wide position of a log (a busy block passes 255 logs). */
|
|
857
|
+
logIndex: 2,
|
|
858
|
+
kind: 1,
|
|
859
|
+
argsCode: 1,
|
|
860
|
+
returnWord: 1,
|
|
861
|
+
argTag: 1,
|
|
862
|
+
word: 32
|
|
863
|
+
};
|
|
864
|
+
|
|
865
|
+
// acps/share-metadata/encode.ts
|
|
866
|
+
var uint = (value, width) => viem.numberToHex(value, { size: width });
|
|
867
|
+
var BYTES_FIELD = {
|
|
868
|
+
contract: { width: BYTE_WIDTH.address, name: "a contract address" },
|
|
869
|
+
selector: { width: BYTE_WIDTH.selector, name: "a selector" },
|
|
870
|
+
viewCallArgument: { width: BYTE_WIDTH.word, name: "a view call argument" },
|
|
871
|
+
appKey: { width: BYTE_WIDTH.word, name: "an app key" }
|
|
872
|
+
};
|
|
873
|
+
var bytesField = (field, value) => {
|
|
874
|
+
const { width, name } = BYTES_FIELD[field];
|
|
875
|
+
if (!viem.isHex(value, { strict: true }) || viem.size(value) !== width) {
|
|
876
|
+
throw new Error(`share metadata: ${name} must be ${width} bytes`);
|
|
877
|
+
}
|
|
878
|
+
return value.toLowerCase();
|
|
879
|
+
};
|
|
880
|
+
var listOf = (keyOf, what) => {
|
|
881
|
+
const items = [];
|
|
882
|
+
const positions = /* @__PURE__ */ new Map();
|
|
883
|
+
const insert = (item) => {
|
|
884
|
+
const key = keyOf(item);
|
|
885
|
+
if (positions.has(key))
|
|
886
|
+
return;
|
|
887
|
+
positions.set(key, items.length);
|
|
888
|
+
items.push(item);
|
|
889
|
+
};
|
|
890
|
+
const positionOf = (item) => {
|
|
891
|
+
const position = positions.get(keyOf(item));
|
|
892
|
+
if (position === void 0)
|
|
893
|
+
throw new Error(`share metadata: ${what} ${keyOf(item)} was not collected`);
|
|
894
|
+
return position;
|
|
895
|
+
};
|
|
896
|
+
return { items, insert, positionOf };
|
|
897
|
+
};
|
|
898
|
+
var keyOfContract = (contract) => contract.toLowerCase();
|
|
899
|
+
var keyOfSelector = (selector) => selector.toLowerCase();
|
|
900
|
+
var keyOfTransaction = ({ block, txIndex }) => `${block}:${txIndex}`;
|
|
901
|
+
var transactionOf = ({ block, txIndex }) => ({ block, txIndex });
|
|
902
|
+
var encodeArg = (arg) => {
|
|
903
|
+
if (arg.type === "issuer")
|
|
904
|
+
return uint(ARG_TAG.issuer, BYTE_WIDTH.argTag);
|
|
905
|
+
return viem.concatHex([uint(ARG_TAG.word, BYTE_WIDTH.argTag), bytesField("viewCallArgument", arg.value)]);
|
|
906
|
+
};
|
|
907
|
+
var issuerWordOf = (issuer) => issuer == null ? void 0 : viem.padHex(issuer, { size: BYTE_WIDTH.word }).toLowerCase();
|
|
908
|
+
var asIssuer = (arg, issuerWord) => arg.type === "word" && issuerWord != null && arg.value.toLowerCase() === issuerWord ? { type: "issuer" } : arg;
|
|
909
|
+
var encodeArgs = ({ args: given, returnWord }, issuerWord) => {
|
|
910
|
+
const args = given.map((arg) => asIssuer(arg, issuerWord));
|
|
911
|
+
if (returnWord === 0 && args.length === 0)
|
|
912
|
+
return uint(ARGS_CODE.none, BYTE_WIDTH.argsCode);
|
|
913
|
+
if (returnWord === 0 && args.length === 1 && args[0].type === "issuer") {
|
|
914
|
+
return uint(ARGS_CODE.issuer, BYTE_WIDTH.argsCode);
|
|
915
|
+
}
|
|
916
|
+
return viem.concatHex([
|
|
917
|
+
uint(ARGS_CODE.explicit, BYTE_WIDTH.argsCode),
|
|
918
|
+
uint(returnWord, BYTE_WIDTH.returnWord),
|
|
919
|
+
uint(args.length, BYTE_WIDTH.count),
|
|
920
|
+
...args.map(encodeArg)
|
|
921
|
+
]);
|
|
922
|
+
};
|
|
923
|
+
var encodeShareMetadata = (labels, { issuer, appKey } = {}) => {
|
|
924
|
+
const issuerWord = issuerWordOf(issuer);
|
|
925
|
+
const contracts = listOf(keyOfContract, "contract");
|
|
926
|
+
const selectors = listOf(keyOfSelector, "selector");
|
|
927
|
+
const transactions = listOf(keyOfTransaction, "transaction");
|
|
928
|
+
for (const label of labels) {
|
|
929
|
+
if (label.kind === "unlabelled")
|
|
930
|
+
continue;
|
|
931
|
+
contracts.insert(label.contract);
|
|
932
|
+
selectors.insert(label.selector);
|
|
933
|
+
if (label.kind === "event")
|
|
934
|
+
transactions.insert(transactionOf(label));
|
|
935
|
+
}
|
|
936
|
+
const entries = labels.map((label) => {
|
|
937
|
+
switch (label.kind) {
|
|
938
|
+
case "stored":
|
|
939
|
+
return viem.concatHex([
|
|
940
|
+
uint(ENTRY_KIND.stored, BYTE_WIDTH.kind),
|
|
941
|
+
uint(contracts.positionOf(label.contract), BYTE_WIDTH.index),
|
|
942
|
+
uint(selectors.positionOf(label.selector), BYTE_WIDTH.index),
|
|
943
|
+
uint(label.block, BYTE_WIDTH.block),
|
|
944
|
+
encodeArgs(label, issuerWord)
|
|
945
|
+
]);
|
|
946
|
+
case "event":
|
|
947
|
+
return viem.concatHex([
|
|
948
|
+
uint(ENTRY_KIND.event, BYTE_WIDTH.kind),
|
|
949
|
+
uint(contracts.positionOf(label.contract), BYTE_WIDTH.index),
|
|
950
|
+
uint(transactions.positionOf(transactionOf(label)), BYTE_WIDTH.index),
|
|
951
|
+
uint(label.logIndex, BYTE_WIDTH.logIndex),
|
|
952
|
+
uint(selectors.positionOf(label.selector), BYTE_WIDTH.index)
|
|
953
|
+
]);
|
|
954
|
+
case "unlabelled":
|
|
955
|
+
return uint(ENTRY_KIND.unlabelled, BYTE_WIDTH.kind);
|
|
956
|
+
}
|
|
957
|
+
});
|
|
958
|
+
return viem.concatHex([
|
|
959
|
+
uint(LAYOUT_VERSION, BYTE_WIDTH.version),
|
|
960
|
+
uint(contracts.items.length, BYTE_WIDTH.count),
|
|
961
|
+
...contracts.items.map((contract) => bytesField("contract", contract)),
|
|
962
|
+
uint(selectors.items.length, BYTE_WIDTH.count),
|
|
963
|
+
...selectors.items.map((selector) => bytesField("selector", selector)),
|
|
964
|
+
uint(transactions.items.length, BYTE_WIDTH.count),
|
|
965
|
+
...transactions.items.map(
|
|
966
|
+
(tx) => viem.concatHex([uint(tx.block, BYTE_WIDTH.block), uint(tx.txIndex, BYTE_WIDTH.txIndex)])
|
|
967
|
+
),
|
|
968
|
+
...entries,
|
|
969
|
+
...appKey == null ? [] : [uint(APP_KEY_TAG, BYTE_WIDTH.count), bytesField("appKey", appKey)]
|
|
970
|
+
]);
|
|
971
|
+
};
|
|
972
|
+
var findViewFunction = (abi, name, arity) => {
|
|
973
|
+
const named = abi.filter((item) => item.type === "function" && item.name === name);
|
|
974
|
+
if (named.length === 0)
|
|
975
|
+
throw new Error(`share metadata: the ABI has no function ${name}`);
|
|
976
|
+
const fitting = named.filter((fn2) => fn2.inputs.length === arity);
|
|
977
|
+
if (fitting.length !== 1) {
|
|
978
|
+
throw new Error(
|
|
979
|
+
named.length === 1 ? `share metadata: ${name} takes ${named[0].inputs.length} arguments, ${arity} given` : `share metadata: no single overload of ${name} takes ${arity} arguments`
|
|
980
|
+
);
|
|
981
|
+
}
|
|
982
|
+
const [fn] = fitting;
|
|
983
|
+
if (fn.stateMutability !== "view" && fn.stateMutability !== "pure") {
|
|
984
|
+
throw new Error(`share metadata: ${name} is not a view function`);
|
|
985
|
+
}
|
|
986
|
+
return fn;
|
|
987
|
+
};
|
|
988
|
+
var encodeReadArg = (fn, index, value) => {
|
|
989
|
+
const input = fn.inputs[index];
|
|
990
|
+
const word = viem.encodeAbiParameters([input], [value]);
|
|
991
|
+
if (viem.size(word) !== BYTE_WIDTH.word) {
|
|
992
|
+
throw new Error(
|
|
993
|
+
`share metadata: argument ${index} of ${fn.name} is ${input.type}; only arguments of one static 32-byte word can be labelled`
|
|
994
|
+
);
|
|
995
|
+
}
|
|
996
|
+
return { type: "word", value: word };
|
|
997
|
+
};
|
|
998
|
+
var viewFunctionLabel = (options) => {
|
|
999
|
+
const { contract, block, returnWord = 0 } = options;
|
|
1000
|
+
const values = options.args ?? [];
|
|
1001
|
+
const fn = findViewFunction(options.abi, options.functionName, values.length);
|
|
1002
|
+
return {
|
|
1003
|
+
kind: "stored",
|
|
1004
|
+
contract,
|
|
1005
|
+
selector: viem.toFunctionSelector(fn),
|
|
1006
|
+
args: values.map((value, i) => encodeReadArg(fn, i, value)),
|
|
1007
|
+
returnWord,
|
|
1008
|
+
block
|
|
1009
|
+
};
|
|
1010
|
+
};
|
|
1011
|
+
var eventLogLabel = (log) => {
|
|
1012
|
+
const { address, blockNumber, transactionIndex, logIndex, topics } = log;
|
|
1013
|
+
const topic0 = topics[0];
|
|
1014
|
+
if (blockNumber == null || transactionIndex == null || logIndex == null) {
|
|
1015
|
+
throw new Error("share metadata: a pending log has no position to label");
|
|
1016
|
+
}
|
|
1017
|
+
if (topic0 == null || viem.size(topic0) !== 32)
|
|
1018
|
+
throw new Error("share metadata: an anonymous log has no event selector");
|
|
1019
|
+
return {
|
|
1020
|
+
kind: "event",
|
|
1021
|
+
contract: address,
|
|
1022
|
+
block: blockNumber,
|
|
1023
|
+
txIndex: transactionIndex,
|
|
1024
|
+
logIndex,
|
|
1025
|
+
selector: viem.sliceHex(topic0, 0, 4)
|
|
1026
|
+
};
|
|
1027
|
+
};
|
|
1028
|
+
var UNLABELLED = { kind: "unlabelled" };
|
|
601
1029
|
|
|
602
1030
|
// acps/acp.ts
|
|
1031
|
+
var sharedByName = (issuer) => `Shared by ${issuer.slice(0, 6)}\u2026${issuer.slice(-4)}`;
|
|
603
1032
|
var ACPUtils = {
|
|
604
1033
|
/**
|
|
605
1034
|
* Create a self acp for personal use
|
|
@@ -621,10 +1050,16 @@ var ACPUtils = {
|
|
|
621
1050
|
*/
|
|
622
1051
|
createSharing: (options) => {
|
|
623
1052
|
const validation = validateSharingACPOptions(options);
|
|
1053
|
+
const { labels, appKey } = options;
|
|
1054
|
+
if (labels != null && labels.length !== validation.handles.length) {
|
|
1055
|
+
throw new Error(`Cannot label a share of ${validation.handles.length} handles with ${labels.length} labels`);
|
|
1056
|
+
}
|
|
1057
|
+
const metadata = labels != null || appKey != null ? encodeShareMetadata(labels ?? validation.handles.map(() => UNLABELLED), { issuer: validation.issuer, appKey }) : void 0;
|
|
624
1058
|
const sealingPair = GenerateSealingKey();
|
|
625
1059
|
const acp = {
|
|
626
1060
|
hash: ACPUtils.getHash(validation),
|
|
627
1061
|
...validation,
|
|
1062
|
+
...metadata != null && { metadata },
|
|
628
1063
|
sealingPrivateKey: sealingPair.privateKey,
|
|
629
1064
|
sealingKey: sealingPair.publicKey,
|
|
630
1065
|
_signedDomain: void 0
|
|
@@ -632,9 +1067,10 @@ var ACPUtils = {
|
|
|
632
1067
|
return acp;
|
|
633
1068
|
},
|
|
634
1069
|
/**
|
|
635
|
-
* Import a shared acp from various input formats
|
|
1070
|
+
* Import a shared acp from various input formats. The acp is named `name`, or after its issuer
|
|
1071
|
+
* ("Shared by 0x1234…abcd"); a `name` in the share itself is ignored.
|
|
636
1072
|
*/
|
|
637
|
-
importShared: (options) => {
|
|
1073
|
+
importShared: (options, { name } = {}) => {
|
|
638
1074
|
let parsedOptions;
|
|
639
1075
|
if (typeof options === "string") {
|
|
640
1076
|
try {
|
|
@@ -655,6 +1091,7 @@ var ACPUtils = {
|
|
|
655
1091
|
const acp = {
|
|
656
1092
|
hash: ACPUtils.getHash(validation),
|
|
657
1093
|
...validation,
|
|
1094
|
+
name: name?.trim() || sharedByName(validation.issuer),
|
|
658
1095
|
sealingPrivateKey: sealingPair.privateKey,
|
|
659
1096
|
sealingKey: sealingPair.publicKey,
|
|
660
1097
|
_signedDomain: void 0
|
|
@@ -713,8 +1150,8 @@ var ACPUtils = {
|
|
|
713
1150
|
/**
|
|
714
1151
|
* Import and sign a shared acp in one operation from various input formats
|
|
715
1152
|
*/
|
|
716
|
-
importSharedAndSign: async (options, publicClient, walletClient) => {
|
|
717
|
-
const acp = ACPUtils.importShared(options);
|
|
1153
|
+
importSharedAndSign: async (options, publicClient, walletClient, importOptions = {}) => {
|
|
1154
|
+
const acp = ACPUtils.importShared(options, importOptions);
|
|
718
1155
|
return ACPUtils.sign(acp, publicClient, walletClient);
|
|
719
1156
|
},
|
|
720
1157
|
/**
|
|
@@ -743,7 +1180,8 @@ var ACPUtils = {
|
|
|
743
1180
|
issuerSignature: acp.issuerSignature,
|
|
744
1181
|
recipientSignature: acp.recipientSignature,
|
|
745
1182
|
_signedDomain: acp._signedDomain,
|
|
746
|
-
sealingPrivateKey: acp.sealingPrivateKey
|
|
1183
|
+
sealingPrivateKey: acp.sealingPrivateKey,
|
|
1184
|
+
...acp.metadata != null && { metadata: acp.metadata }
|
|
747
1185
|
};
|
|
748
1186
|
},
|
|
749
1187
|
/**
|
|
@@ -817,7 +1255,7 @@ var ACPUtils = {
|
|
|
817
1255
|
/**
|
|
818
1256
|
* Export acp data for sharing (strips the private component).
|
|
819
1257
|
* Fixed `SharedACP` shape — every field always present, aligned with
|
|
820
|
-
* `ACPPublic` and the on-chain sharing payload.
|
|
1258
|
+
* `ACPPublic` and the on-chain sharing payload — plus `metadata` when the acp has labels.
|
|
821
1259
|
*/
|
|
822
1260
|
export: (acp) => {
|
|
823
1261
|
if (acp.type !== "sharing") {
|
|
@@ -831,7 +1269,6 @@ var ACPUtils = {
|
|
|
831
1269
|
);
|
|
832
1270
|
}
|
|
833
1271
|
const shared = {
|
|
834
|
-
name: acp.name,
|
|
835
1272
|
type: acp.type,
|
|
836
1273
|
issuer: acp.issuer,
|
|
837
1274
|
expiration: acp.expiration,
|
|
@@ -841,7 +1278,8 @@ var ACPUtils = {
|
|
|
841
1278
|
scope: acp.scope,
|
|
842
1279
|
contracts: acp.contracts,
|
|
843
1280
|
handles: acp.handles,
|
|
844
|
-
issuerSignature: acp.issuerSignature
|
|
1281
|
+
issuerSignature: acp.issuerSignature,
|
|
1282
|
+
...acp.metadata != null && acp.metadata !== "0x" && { metadata: acp.metadata }
|
|
845
1283
|
};
|
|
846
1284
|
return JSON.stringify(shared, void 0, 2);
|
|
847
1285
|
},
|
|
@@ -911,13 +1349,452 @@ var ACPUtils = {
|
|
|
911
1349
|
checkValidityOnChain: async (acp, publicClient) => {
|
|
912
1350
|
const publicAcp = ACPUtils.getPublic(acp);
|
|
913
1351
|
return checkACPValidityOnChain(publicAcp, publicClient);
|
|
1352
|
+
},
|
|
1353
|
+
/**
|
|
1354
|
+
* The acp on-chain status as a value instead of a revert: 'valid' or why not, and given a
|
|
1355
|
+
* handle, whether the acp may read it (see `ACPAccessStatus`).
|
|
1356
|
+
*/
|
|
1357
|
+
checkAccessOnChain: async (acp, publicClient, handle) => {
|
|
1358
|
+
return getACPAccessStatusOnChain(ACPUtils.getPublic(acp), publicClient, handle);
|
|
1359
|
+
}
|
|
1360
|
+
};
|
|
1361
|
+
var ACP_REVOKER_ABI = viem.parseAbi([
|
|
1362
|
+
"function revokeSingle(uint256 id)",
|
|
1363
|
+
"function revokeAllExisting()",
|
|
1364
|
+
"function disabled(address issuer, uint256 id) view returns (bool)"
|
|
1365
|
+
]);
|
|
1366
|
+
var ACP_SHARE_REGISTRY_ABI = viem.parseAbi([
|
|
1367
|
+
"struct ACP { address issuer; uint64 expiration; address recipient; uint256 revokerData; address revokerContract; uint8 scope; address[] contracts; bytes32[] handles; bytes32 sealingKey; bytes issuerSignature; bytes recipientSignature; }",
|
|
1368
|
+
"struct ShareHeader { address issuer; uint64 expiration; address recipient; uint64 blockNumber; address revokerContract; uint256 revokerData; }",
|
|
1369
|
+
"function share(ACP calldata acp, bytes calldata metadata) external returns (bytes32)",
|
|
1370
|
+
"function removeShare(bytes32 shareId) external",
|
|
1371
|
+
"function sharesFor(address recipient) external view returns (bytes32[] shareIds, ShareHeader[] headers)",
|
|
1372
|
+
"function getShare(bytes32 shareId) external view returns (ShareHeader memory)",
|
|
1373
|
+
"function isShareValid(bytes32 shareId) external view returns (bool)",
|
|
1374
|
+
"event Shared(address indexed recipient, address indexed issuer, bytes32 indexed shareId, ACP acp, bytes metadata)",
|
|
1375
|
+
"event ShareRemoved(address indexed recipient, address indexed issuer, bytes32 indexed shareId)"
|
|
1376
|
+
]);
|
|
1377
|
+
var ACP_SHARE_TUPLE_ABI = [
|
|
1378
|
+
{
|
|
1379
|
+
type: "tuple",
|
|
1380
|
+
components: [
|
|
1381
|
+
{ name: "issuer", type: "address" },
|
|
1382
|
+
{ name: "expiration", type: "uint64" },
|
|
1383
|
+
{ name: "recipient", type: "address" },
|
|
1384
|
+
{ name: "revokerData", type: "uint256" },
|
|
1385
|
+
{ name: "revokerContract", type: "address" },
|
|
1386
|
+
{ name: "scope", type: "uint8" },
|
|
1387
|
+
{ name: "contracts", type: "address[]" },
|
|
1388
|
+
{ name: "handles", type: "bytes32[]" },
|
|
1389
|
+
{ name: "sealingKey", type: "bytes32" },
|
|
1390
|
+
{ name: "issuerSignature", type: "bytes" },
|
|
1391
|
+
{ name: "recipientSignature", type: "bytes" }
|
|
1392
|
+
]
|
|
1393
|
+
}
|
|
1394
|
+
];
|
|
1395
|
+
var ZERO_BYTES32 = `0x${"0".repeat(64)}`;
|
|
1396
|
+
var toChainShare = (acp) => {
|
|
1397
|
+
const pub = ACPUtils.getPublic(acp, true);
|
|
1398
|
+
return {
|
|
1399
|
+
...pub,
|
|
1400
|
+
expiration: BigInt(pub.expiration),
|
|
1401
|
+
revokerData: BigInt(pub.revokerData),
|
|
1402
|
+
sealingKey: ZERO_BYTES32,
|
|
1403
|
+
recipientSignature: "0x"
|
|
1404
|
+
};
|
|
1405
|
+
};
|
|
1406
|
+
var computeShareId = (acp) => {
|
|
1407
|
+
const p = toChainShare(acp);
|
|
1408
|
+
return viem.keccak256(viem.encodeAbiParameters(ACP_SHARE_TUPLE_ABI, [p]));
|
|
1409
|
+
};
|
|
1410
|
+
var shareIdOfChainShare = (share) => viem.keccak256(viem.encodeAbiParameters(ACP_SHARE_TUPLE_ABI, [share]));
|
|
1411
|
+
var messageOf = (error) => error instanceof Error ? error.message : String(error);
|
|
1412
|
+
var readPostedShares = async (publicClient, registry, headers) => {
|
|
1413
|
+
const idsByBlock = /* @__PURE__ */ new Map();
|
|
1414
|
+
for (const { shareId, header } of headers) {
|
|
1415
|
+
idsByBlock.set(header.blockNumber, [...idsByBlock.get(header.blockNumber) ?? [], shareId]);
|
|
1416
|
+
}
|
|
1417
|
+
const found = /* @__PURE__ */ new Map();
|
|
1418
|
+
await Promise.all(
|
|
1419
|
+
[...idsByBlock].map(async ([block, shareIds]) => {
|
|
1420
|
+
let logs;
|
|
1421
|
+
try {
|
|
1422
|
+
logs = await publicClient.getContractEvents({
|
|
1423
|
+
address: registry,
|
|
1424
|
+
abi: ACP_SHARE_REGISTRY_ABI,
|
|
1425
|
+
eventName: "Shared",
|
|
1426
|
+
args: { shareId: shareIds },
|
|
1427
|
+
fromBlock: block,
|
|
1428
|
+
toBlock: block,
|
|
1429
|
+
strict: true
|
|
1430
|
+
});
|
|
1431
|
+
} catch (error) {
|
|
1432
|
+
for (const shareId of shareIds) {
|
|
1433
|
+
found.set(shareId.toLowerCase(), {
|
|
1434
|
+
reason: `the Shared events of block ${block} could not be read: ${messageOf(error)}`
|
|
1435
|
+
});
|
|
1436
|
+
}
|
|
1437
|
+
return;
|
|
1438
|
+
}
|
|
1439
|
+
for (const { args } of logs) {
|
|
1440
|
+
const hashes = shareIdOfChainShare(args.acp).toLowerCase() === args.shareId.toLowerCase();
|
|
1441
|
+
found.set(
|
|
1442
|
+
args.shareId.toLowerCase(),
|
|
1443
|
+
hashes ? { share: args.acp, metadata: args.metadata } : { reason: "the payload in its Shared event does not hash to its id" }
|
|
1444
|
+
);
|
|
1445
|
+
}
|
|
1446
|
+
})
|
|
1447
|
+
);
|
|
1448
|
+
const result = { posted: [], unreadable: [] };
|
|
1449
|
+
for (const { shareId, header } of headers) {
|
|
1450
|
+
const entry = found.get(shareId.toLowerCase());
|
|
1451
|
+
if (entry == null) {
|
|
1452
|
+
result.unreadable.push({
|
|
1453
|
+
shareId,
|
|
1454
|
+
header,
|
|
1455
|
+
reason: `no Shared event in block ${header.blockNumber}, where the registry points`
|
|
1456
|
+
});
|
|
1457
|
+
} else if ("reason" in entry) {
|
|
1458
|
+
result.unreadable.push({ shareId, header, reason: entry.reason });
|
|
1459
|
+
} else {
|
|
1460
|
+
result.posted.push({ shareId, header, ...entry });
|
|
1461
|
+
}
|
|
914
1462
|
}
|
|
1463
|
+
return result;
|
|
915
1464
|
};
|
|
1465
|
+
var readSharesFor = async (publicClient, registry, recipient) => {
|
|
1466
|
+
const [shareIds, headers] = await publicClient.readContract({
|
|
1467
|
+
address: registry,
|
|
1468
|
+
abi: ACP_SHARE_REGISTRY_ABI,
|
|
1469
|
+
functionName: "sharesFor",
|
|
1470
|
+
args: [recipient]
|
|
1471
|
+
});
|
|
1472
|
+
return readPostedShares(
|
|
1473
|
+
publicClient,
|
|
1474
|
+
registry,
|
|
1475
|
+
shareIds.map((shareId, i) => ({ shareId, header: headers[i] }))
|
|
1476
|
+
);
|
|
1477
|
+
};
|
|
1478
|
+
var readShare = async (publicClient, registry, shareId) => {
|
|
1479
|
+
const header = await publicClient.readContract({
|
|
1480
|
+
address: registry,
|
|
1481
|
+
abi: ACP_SHARE_REGISTRY_ABI,
|
|
1482
|
+
functionName: "getShare",
|
|
1483
|
+
args: [shareId]
|
|
1484
|
+
});
|
|
1485
|
+
if (header.issuer === "0x0000000000000000000000000000000000000000")
|
|
1486
|
+
return null;
|
|
1487
|
+
const { posted, unreadable } = await readPostedShares(publicClient, registry, [{ shareId, header }]);
|
|
1488
|
+
if (unreadable.length > 0)
|
|
1489
|
+
throw new Error(`Share ${shareId}: ${unreadable[0].reason}`);
|
|
1490
|
+
return posted[0];
|
|
1491
|
+
};
|
|
1492
|
+
var readerOf = (blob) => {
|
|
1493
|
+
let offset = 0;
|
|
1494
|
+
const take = (width) => {
|
|
1495
|
+
if (offset + width > viem.size(blob))
|
|
1496
|
+
throw new Error("share metadata: the blob ends in the middle of a field");
|
|
1497
|
+
offset += width;
|
|
1498
|
+
return viem.sliceHex(blob, offset - width, offset);
|
|
1499
|
+
};
|
|
1500
|
+
return {
|
|
1501
|
+
take,
|
|
1502
|
+
takeNumber: (width) => viem.hexToNumber(take(width)),
|
|
1503
|
+
done: () => offset === viem.size(blob),
|
|
1504
|
+
remaining: () => viem.size(blob) - offset
|
|
1505
|
+
};
|
|
1506
|
+
};
|
|
1507
|
+
var takeList = (reader, takeItem) => Array.from({ length: reader.takeNumber(BYTE_WIDTH.count) }, takeItem);
|
|
1508
|
+
var takeFrom = (reader, list, what) => {
|
|
1509
|
+
const position = reader.takeNumber(BYTE_WIDTH.index);
|
|
1510
|
+
if (position >= list.length) {
|
|
1511
|
+
throw new Error(`share metadata: ${what} ${position} is outside the ${what} list`);
|
|
1512
|
+
}
|
|
1513
|
+
return list[position];
|
|
1514
|
+
};
|
|
1515
|
+
var decodeArg = (reader) => {
|
|
1516
|
+
const tag = reader.takeNumber(BYTE_WIDTH.argTag);
|
|
1517
|
+
if (tag === ARG_TAG.issuer)
|
|
1518
|
+
return { type: "issuer" };
|
|
1519
|
+
if (tag === ARG_TAG.word)
|
|
1520
|
+
return { type: "word", value: reader.take(BYTE_WIDTH.word) };
|
|
1521
|
+
throw new Error(`share metadata: unknown argument tag ${tag}`);
|
|
1522
|
+
};
|
|
1523
|
+
var decodeArgs = (reader) => {
|
|
1524
|
+
const code = reader.takeNumber(BYTE_WIDTH.argsCode);
|
|
1525
|
+
if (code === ARGS_CODE.none)
|
|
1526
|
+
return { args: [], returnWord: 0 };
|
|
1527
|
+
if (code === ARGS_CODE.issuer)
|
|
1528
|
+
return { args: [{ type: "issuer" }], returnWord: 0 };
|
|
1529
|
+
if (code !== ARGS_CODE.explicit)
|
|
1530
|
+
throw new Error(`share metadata: unknown args code ${code}`);
|
|
1531
|
+
const returnWord = reader.takeNumber(BYTE_WIDTH.returnWord);
|
|
1532
|
+
return { args: takeList(reader, () => decodeArg(reader)), returnWord };
|
|
1533
|
+
};
|
|
1534
|
+
var takeAppKey = (reader) => {
|
|
1535
|
+
if (reader.done())
|
|
1536
|
+
return void 0;
|
|
1537
|
+
const isKey = reader.remaining() === BYTE_WIDTH.count + BYTE_WIDTH.word && reader.takeNumber(BYTE_WIDTH.count) === APP_KEY_TAG;
|
|
1538
|
+
if (!isKey)
|
|
1539
|
+
throw new Error("share metadata: the blob has more entries than the share has ctHashes");
|
|
1540
|
+
return reader.take(BYTE_WIDTH.word);
|
|
1541
|
+
};
|
|
1542
|
+
var decodeShareMetadataFull = (blob, handles) => {
|
|
1543
|
+
const reader = readerOf(blob);
|
|
1544
|
+
const version = reader.takeNumber(BYTE_WIDTH.version);
|
|
1545
|
+
if (version !== LAYOUT_VERSION)
|
|
1546
|
+
throw new Error(`share metadata: unsupported version ${version}`);
|
|
1547
|
+
const contracts = takeList(reader, () => viem.getAddress(reader.take(BYTE_WIDTH.address)));
|
|
1548
|
+
const selectors = takeList(reader, () => reader.take(BYTE_WIDTH.selector));
|
|
1549
|
+
const transactions = takeList(reader, () => ({
|
|
1550
|
+
block: viem.hexToBigInt(reader.take(BYTE_WIDTH.block)),
|
|
1551
|
+
txIndex: reader.takeNumber(BYTE_WIDTH.txIndex)
|
|
1552
|
+
}));
|
|
1553
|
+
const labels = handles.map(() => {
|
|
1554
|
+
const kind = reader.takeNumber(BYTE_WIDTH.kind);
|
|
1555
|
+
switch (kind) {
|
|
1556
|
+
case ENTRY_KIND.stored: {
|
|
1557
|
+
const contract = takeFrom(reader, contracts, "contract");
|
|
1558
|
+
const selector = takeFrom(reader, selectors, "selector");
|
|
1559
|
+
const block = viem.hexToBigInt(reader.take(BYTE_WIDTH.block));
|
|
1560
|
+
return { kind: "stored", contract, selector, ...decodeArgs(reader), block };
|
|
1561
|
+
}
|
|
1562
|
+
case ENTRY_KIND.event: {
|
|
1563
|
+
const contract = takeFrom(reader, contracts, "contract");
|
|
1564
|
+
const { block, txIndex } = takeFrom(reader, transactions, "transaction");
|
|
1565
|
+
const logIndex = reader.takeNumber(BYTE_WIDTH.logIndex);
|
|
1566
|
+
const selector = takeFrom(reader, selectors, "selector");
|
|
1567
|
+
return { kind: "event", contract, block, txIndex, logIndex, selector };
|
|
1568
|
+
}
|
|
1569
|
+
case ENTRY_KIND.unlabelled:
|
|
1570
|
+
return { kind: "unlabelled" };
|
|
1571
|
+
default:
|
|
1572
|
+
throw new Error(`share metadata: unknown entry kind ${kind}`);
|
|
1573
|
+
}
|
|
1574
|
+
});
|
|
1575
|
+
const appKey = takeAppKey(reader);
|
|
1576
|
+
if (!reader.done())
|
|
1577
|
+
throw new Error("share metadata: the blob has more entries than the share has ctHashes");
|
|
1578
|
+
return { labels, appKey };
|
|
1579
|
+
};
|
|
1580
|
+
var decodeShareMetadata = (blob, handles) => decodeShareMetadataFull(blob, handles).labels;
|
|
1581
|
+
var decodeShareAppKey = (metadata, handles) => metadata == null || metadata === "0x" ? void 0 : decodeShareMetadataFull(metadata, handles).appKey;
|
|
1582
|
+
var sameWord = (a, b) => a.toLowerCase() === b.toLowerCase();
|
|
1583
|
+
var wordsOf = (data) => {
|
|
1584
|
+
const count = Math.floor(viem.size(data) / BYTE_WIDTH.word);
|
|
1585
|
+
return Array.from(
|
|
1586
|
+
{ length: count },
|
|
1587
|
+
(_, index) => viem.sliceHex(data, index * BYTE_WIDTH.word, (index + 1) * BYTE_WIDTH.word)
|
|
1588
|
+
);
|
|
1589
|
+
};
|
|
1590
|
+
var storedCallData = (label, issuer) => viem.concatHex([
|
|
1591
|
+
label.selector,
|
|
1592
|
+
...label.args.map((arg) => arg.type === "issuer" ? viem.padHex(issuer, { size: BYTE_WIDTH.word }) : arg.value)
|
|
1593
|
+
]);
|
|
1594
|
+
var checkStored = (label, handle, data) => {
|
|
1595
|
+
const found = data ? wordsOf(data)[label.returnWord] : void 0;
|
|
1596
|
+
return found && sameWord(found, handle) ? "verified" : "mismatch";
|
|
1597
|
+
};
|
|
1598
|
+
var checkEvent = (label, handle, logs) => {
|
|
1599
|
+
const log = logs.find((l) => l.logIndex === label.logIndex);
|
|
1600
|
+
if (log == null)
|
|
1601
|
+
return "mismatch";
|
|
1602
|
+
if (log.transactionIndex !== label.txIndex)
|
|
1603
|
+
return "mismatch";
|
|
1604
|
+
const topic0 = log.topics[0];
|
|
1605
|
+
if (topic0 == null || !topic0.toLowerCase().startsWith(label.selector.toLowerCase()))
|
|
1606
|
+
return "mismatch";
|
|
1607
|
+
const carried = [...log.topics.slice(1), ...wordsOf(log.data)].some((word) => word != null && sameWord(word, handle));
|
|
1608
|
+
return carried ? "verified" : "mismatch";
|
|
1609
|
+
};
|
|
1610
|
+
var callAt = async (publicClient, to, data, blockNumber) => (await publicClient.call({ to, data, blockNumber })).data;
|
|
1611
|
+
var logsAt = (publicClient, address, block) => publicClient.getLogs({ address, fromBlock: block, toBlock: block });
|
|
1612
|
+
var verifyShareLabel = async (label, handle, publicClient, issuer) => {
|
|
1613
|
+
try {
|
|
1614
|
+
switch (label.kind) {
|
|
1615
|
+
case "stored":
|
|
1616
|
+
return checkStored(
|
|
1617
|
+
label,
|
|
1618
|
+
handle,
|
|
1619
|
+
await callAt(publicClient, label.contract, storedCallData(label, issuer), label.block)
|
|
1620
|
+
);
|
|
1621
|
+
case "event":
|
|
1622
|
+
return checkEvent(label, handle, await logsAt(publicClient, label.contract, label.block));
|
|
1623
|
+
case "unlabelled":
|
|
1624
|
+
return "unverifiable";
|
|
1625
|
+
}
|
|
1626
|
+
} catch {
|
|
1627
|
+
return "unverifiable";
|
|
1628
|
+
}
|
|
1629
|
+
};
|
|
1630
|
+
var verifyShareLabels = async ({
|
|
1631
|
+
labels,
|
|
1632
|
+
handles,
|
|
1633
|
+
issuer,
|
|
1634
|
+
publicClient,
|
|
1635
|
+
verify = "all"
|
|
1636
|
+
}) => {
|
|
1637
|
+
if (labels.length !== handles.length) {
|
|
1638
|
+
throw new Error(`share metadata: ${labels.length} labels for ${handles.length} ctHashes`);
|
|
1639
|
+
}
|
|
1640
|
+
const requests = /* @__PURE__ */ new Map();
|
|
1641
|
+
const once = (key, request) => {
|
|
1642
|
+
if (!requests.has(key))
|
|
1643
|
+
requests.set(key, request());
|
|
1644
|
+
return requests.get(key);
|
|
1645
|
+
};
|
|
1646
|
+
return Promise.all(
|
|
1647
|
+
labels.map(async (label, i) => {
|
|
1648
|
+
const handle = handles[i];
|
|
1649
|
+
try {
|
|
1650
|
+
switch (label.kind) {
|
|
1651
|
+
case "stored": {
|
|
1652
|
+
if (verify !== "all")
|
|
1653
|
+
return "skipped";
|
|
1654
|
+
const data = storedCallData(label, issuer);
|
|
1655
|
+
const key = `call:${label.contract.toLowerCase()}:${label.block}:${data}`;
|
|
1656
|
+
return checkStored(
|
|
1657
|
+
label,
|
|
1658
|
+
handle,
|
|
1659
|
+
await once(key, () => callAt(publicClient, label.contract, data, label.block))
|
|
1660
|
+
);
|
|
1661
|
+
}
|
|
1662
|
+
case "event": {
|
|
1663
|
+
if (verify === "none")
|
|
1664
|
+
return "skipped";
|
|
1665
|
+
const key = `logs:${label.contract.toLowerCase()}:${label.block}`;
|
|
1666
|
+
return checkEvent(label, handle, await once(key, () => logsAt(publicClient, label.contract, label.block)));
|
|
1667
|
+
}
|
|
1668
|
+
case "unlabelled":
|
|
1669
|
+
return verify === "none" ? "skipped" : "unverifiable";
|
|
1670
|
+
}
|
|
1671
|
+
} catch {
|
|
1672
|
+
return "unverifiable";
|
|
1673
|
+
}
|
|
1674
|
+
})
|
|
1675
|
+
);
|
|
1676
|
+
};
|
|
1677
|
+
var abiOf = (abis, contract) => {
|
|
1678
|
+
const wanted = contract.toLowerCase();
|
|
1679
|
+
const key = Object.keys(abis).find((address) => address.toLowerCase() === wanted);
|
|
1680
|
+
return key ? abis[key] : void 0;
|
|
1681
|
+
};
|
|
1682
|
+
var paramOf = ({ name, type, ...rest }) => {
|
|
1683
|
+
const param = { type };
|
|
1684
|
+
if (name)
|
|
1685
|
+
param.name = name;
|
|
1686
|
+
if ("indexed" in rest && typeof rest.indexed === "boolean")
|
|
1687
|
+
param.indexed = rest.indexed;
|
|
1688
|
+
return param;
|
|
1689
|
+
};
|
|
1690
|
+
var findFunction = (abi, selector) => abi?.find(
|
|
1691
|
+
(item) => item.type === "function" && viem.toFunctionSelector(item).toLowerCase() === selector.toLowerCase()
|
|
1692
|
+
);
|
|
1693
|
+
var findEvent = (abi, selector) => abi?.find(
|
|
1694
|
+
(item) => item.type === "event" && viem.toEventSelector(item).toLowerCase().startsWith(selector.toLowerCase())
|
|
1695
|
+
);
|
|
1696
|
+
var decodeWord = (input, raw) => {
|
|
1697
|
+
if (input == null)
|
|
1698
|
+
return raw;
|
|
1699
|
+
try {
|
|
1700
|
+
return viem.decodeAbiParameters([input], raw)[0];
|
|
1701
|
+
} catch {
|
|
1702
|
+
return raw;
|
|
1703
|
+
}
|
|
1704
|
+
};
|
|
1705
|
+
var describeStored = (base, label, abis, issuer) => {
|
|
1706
|
+
const fn = findFunction(abiOf(abis, label.contract), label.selector);
|
|
1707
|
+
const args = label.args.map((arg, i) => {
|
|
1708
|
+
const input = fn?.inputs[i];
|
|
1709
|
+
const param = input ? paramOf(input) : { type: "bytes32" };
|
|
1710
|
+
if (arg.type === "issuer") {
|
|
1711
|
+
return {
|
|
1712
|
+
...param,
|
|
1713
|
+
isIssuer: true,
|
|
1714
|
+
raw: issuer ? viem.padHex(issuer, { size: 32 }) : void 0,
|
|
1715
|
+
value: issuer
|
|
1716
|
+
};
|
|
1717
|
+
}
|
|
1718
|
+
return { ...param, isIssuer: false, raw: arg.value, value: decodeWord(input, arg.value) };
|
|
1719
|
+
});
|
|
1720
|
+
const output = fn?.outputs[label.returnWord];
|
|
1721
|
+
return {
|
|
1722
|
+
...base,
|
|
1723
|
+
kind: "stored",
|
|
1724
|
+
label,
|
|
1725
|
+
contract: label.contract,
|
|
1726
|
+
block: label.block,
|
|
1727
|
+
selector: label.selector,
|
|
1728
|
+
function: fn ? { name: fn.name, signature: viem.toFunctionSignature(fn), inputs: fn.inputs.map(paramOf) } : null,
|
|
1729
|
+
args,
|
|
1730
|
+
output: output ? paramOf(output) : null
|
|
1731
|
+
};
|
|
1732
|
+
};
|
|
1733
|
+
var describeEvent = (base, label, abis) => {
|
|
1734
|
+
const event = findEvent(abiOf(abis, label.contract), label.selector);
|
|
1735
|
+
return {
|
|
1736
|
+
...base,
|
|
1737
|
+
kind: "event",
|
|
1738
|
+
label,
|
|
1739
|
+
contract: label.contract,
|
|
1740
|
+
block: label.block,
|
|
1741
|
+
txIndex: label.txIndex,
|
|
1742
|
+
logIndex: label.logIndex,
|
|
1743
|
+
selector: label.selector,
|
|
1744
|
+
event: event ? { name: event.name, signature: viem.toEventSignature(event), inputs: event.inputs.map(paramOf) } : null
|
|
1745
|
+
};
|
|
1746
|
+
};
|
|
1747
|
+
var describeShareLabels = (labels, handles, abis = {}, options = {}) => labels.map((label, index) => {
|
|
1748
|
+
const base = { index, handle: handles[index] };
|
|
1749
|
+
switch (label.kind) {
|
|
1750
|
+
case "stored":
|
|
1751
|
+
return describeStored(base, label, abis, options.issuer);
|
|
1752
|
+
case "event":
|
|
1753
|
+
return describeEvent(base, label, abis);
|
|
1754
|
+
case "unlabelled":
|
|
1755
|
+
return { ...base, kind: "unlabelled", label };
|
|
1756
|
+
}
|
|
1757
|
+
});
|
|
1758
|
+
var describeShareMetadata = (share, abis = {}) => {
|
|
1759
|
+
const { issuer, handles, metadata } = share;
|
|
1760
|
+
if (metadata == null || metadata === "0x")
|
|
1761
|
+
return null;
|
|
1762
|
+
return describeShareLabels(decodeShareMetadata(metadata, handles), handles, abis, { issuer });
|
|
1763
|
+
};
|
|
1764
|
+
|
|
1765
|
+
// acps/share-metadata/erc7984.ts
|
|
1766
|
+
var ERC7984_ABI = [
|
|
1767
|
+
{
|
|
1768
|
+
type: "function",
|
|
1769
|
+
name: "confidentialBalanceOf",
|
|
1770
|
+
stateMutability: "view",
|
|
1771
|
+
inputs: [{ name: "account", type: "address", internalType: "address" }],
|
|
1772
|
+
outputs: [{ name: "", type: "bytes32", internalType: "euint64" }]
|
|
1773
|
+
},
|
|
1774
|
+
{
|
|
1775
|
+
type: "event",
|
|
1776
|
+
name: "ConfidentialTransfer",
|
|
1777
|
+
anonymous: false,
|
|
1778
|
+
inputs: [
|
|
1779
|
+
{ name: "from", type: "address", indexed: true, internalType: "address" },
|
|
1780
|
+
{ name: "to", type: "address", indexed: true, internalType: "address" },
|
|
1781
|
+
{ name: "amount", type: "bytes32", indexed: true, internalType: "euint64" }
|
|
1782
|
+
]
|
|
1783
|
+
}
|
|
1784
|
+
];
|
|
1785
|
+
var shareAppKey = (app) => viem.keccak256(viem.stringToHex(app));
|
|
916
1786
|
var ACP_STORE_DEFAULTS = {
|
|
917
1787
|
acps: {},
|
|
918
1788
|
activeACPHash: {}
|
|
919
1789
|
};
|
|
920
1790
|
var ACP_STORE_VERSION = 3;
|
|
1791
|
+
var isRecord = (value) => value != null && typeof value === "object" && !Array.isArray(value);
|
|
1792
|
+
var resolveAccountKey = (records, account) => {
|
|
1793
|
+
if (records == null || account in records)
|
|
1794
|
+
return account;
|
|
1795
|
+
const lower = account.toLowerCase();
|
|
1796
|
+
return Object.keys(records).find((key) => key.toLowerCase() === lower) ?? account;
|
|
1797
|
+
};
|
|
921
1798
|
var _acpStore = vanilla.createStore()(
|
|
922
1799
|
middleware.persist(() => ACP_STORE_DEFAULTS, {
|
|
923
1800
|
name: "cofhesdk-acps",
|
|
@@ -926,12 +1803,23 @@ var _acpStore = vanilla.createStore()(
|
|
|
926
1803
|
if (version < ACP_STORE_VERSION)
|
|
927
1804
|
return ACP_STORE_DEFAULTS;
|
|
928
1805
|
return persistedState;
|
|
1806
|
+
},
|
|
1807
|
+
// Runs on every rehydrate, including a corrupt state saved at the current version that
|
|
1808
|
+
// `migrate` passes through unchanged. Consumers that read the raw snapshot (e.g. the React
|
|
1809
|
+
// hooks) never go through `clearStaleStore`, so the shape has to be fixed here.
|
|
1810
|
+
merge: (persistedState, currentState) => {
|
|
1811
|
+
const persisted = isRecord(persistedState) ? persistedState : {};
|
|
1812
|
+
return {
|
|
1813
|
+
...currentState,
|
|
1814
|
+
acps: isRecord(persisted.acps) ? persisted.acps : currentState.acps,
|
|
1815
|
+
activeACPHash: isRecord(persisted.activeACPHash) ? persisted.activeACPHash : currentState.activeACPHash
|
|
1816
|
+
};
|
|
929
1817
|
}
|
|
930
1818
|
})
|
|
931
1819
|
);
|
|
932
1820
|
var clearStaleStore = () => {
|
|
933
1821
|
const state = _acpStore.getState();
|
|
934
|
-
const hasExpectedStructure = state &&
|
|
1822
|
+
const hasExpectedStructure = isRecord(state) && isRecord(state.acps) && isRecord(state.activeACPHash);
|
|
935
1823
|
if (hasExpectedStructure)
|
|
936
1824
|
return;
|
|
937
1825
|
_acpStore.setState({ acps: {}, activeACPHash: {} });
|
|
@@ -940,7 +1828,8 @@ var getACP = (chainId, account, hash) => {
|
|
|
940
1828
|
clearStaleStore();
|
|
941
1829
|
if (chainId == null || account == null || hash == null)
|
|
942
1830
|
return;
|
|
943
|
-
const
|
|
1831
|
+
const accountACPs = _acpStore.getState().acps[chainId];
|
|
1832
|
+
const savedACP = accountACPs?.[resolveAccountKey(accountACPs, account)]?.[hash];
|
|
944
1833
|
if (savedACP == null)
|
|
945
1834
|
return;
|
|
946
1835
|
return ACPUtils.deserialize(savedACP);
|
|
@@ -949,14 +1838,16 @@ var getActiveACP = (chainId, account) => {
|
|
|
949
1838
|
clearStaleStore();
|
|
950
1839
|
if (chainId == null || account == null)
|
|
951
1840
|
return;
|
|
952
|
-
const
|
|
1841
|
+
const activeHashes = _acpStore.getState().activeACPHash[chainId];
|
|
1842
|
+
const activeACPHash = activeHashes?.[resolveAccountKey(activeHashes, account)];
|
|
953
1843
|
return getACP(chainId, account, activeACPHash);
|
|
954
1844
|
};
|
|
955
1845
|
var getACPs = (chainId, account) => {
|
|
956
1846
|
clearStaleStore();
|
|
957
1847
|
if (chainId == null || account == null)
|
|
958
1848
|
return {};
|
|
959
|
-
|
|
1849
|
+
const accountACPs = _acpStore.getState().acps[chainId];
|
|
1850
|
+
return Object.entries(accountACPs?.[resolveAccountKey(accountACPs, account)] ?? {}).reduce(
|
|
960
1851
|
(acc, [hash, acp]) => {
|
|
961
1852
|
if (acp == void 0)
|
|
962
1853
|
return acc;
|
|
@@ -971,9 +1862,10 @@ var setACP = (chainId, account, acp) => {
|
|
|
971
1862
|
immer.produce((state) => {
|
|
972
1863
|
if (state.acps[chainId] == null)
|
|
973
1864
|
state.acps[chainId] = {};
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
1865
|
+
const key = resolveAccountKey(state.acps[chainId], account);
|
|
1866
|
+
if (state.acps[chainId][key] == null)
|
|
1867
|
+
state.acps[chainId][key] = {};
|
|
1868
|
+
state.acps[chainId][key][acp.hash] = ACPUtils.serialize(acp);
|
|
977
1869
|
})
|
|
978
1870
|
);
|
|
979
1871
|
};
|
|
@@ -985,13 +1877,14 @@ var removeACP = (chainId, account, hash) => {
|
|
|
985
1877
|
state.acps[chainId] = {};
|
|
986
1878
|
if (state.activeACPHash[chainId] == null)
|
|
987
1879
|
state.activeACPHash[chainId] = {};
|
|
988
|
-
const accountACPs = state.acps[chainId][account];
|
|
1880
|
+
const accountACPs = state.acps[chainId][resolveAccountKey(state.acps[chainId], account)];
|
|
989
1881
|
if (accountACPs == null)
|
|
990
1882
|
return;
|
|
991
1883
|
if (accountACPs[hash] == null)
|
|
992
1884
|
return;
|
|
993
|
-
|
|
994
|
-
|
|
1885
|
+
const activeKey = resolveAccountKey(state.activeACPHash[chainId], account);
|
|
1886
|
+
if (state.activeACPHash[chainId][activeKey] === hash) {
|
|
1887
|
+
state.activeACPHash[chainId][activeKey] = void 0;
|
|
995
1888
|
}
|
|
996
1889
|
accountACPs[hash] = void 0;
|
|
997
1890
|
})
|
|
@@ -1001,7 +1894,8 @@ var getActiveACPHash = (chainId, account) => {
|
|
|
1001
1894
|
clearStaleStore();
|
|
1002
1895
|
if (chainId == null || account == null)
|
|
1003
1896
|
return void 0;
|
|
1004
|
-
|
|
1897
|
+
const activeHashes = _acpStore.getState().activeACPHash[chainId];
|
|
1898
|
+
return activeHashes?.[resolveAccountKey(activeHashes, account)];
|
|
1005
1899
|
};
|
|
1006
1900
|
var setActiveACPHash = (chainId, account, hash) => {
|
|
1007
1901
|
clearStaleStore();
|
|
@@ -1009,7 +1903,7 @@ var setActiveACPHash = (chainId, account, hash) => {
|
|
|
1009
1903
|
immer.produce((state) => {
|
|
1010
1904
|
if (state.activeACPHash[chainId] == null)
|
|
1011
1905
|
state.activeACPHash[chainId] = {};
|
|
1012
|
-
state.activeACPHash[chainId][account] = hash;
|
|
1906
|
+
state.activeACPHash[chainId][resolveAccountKey(state.activeACPHash[chainId], account)] = hash;
|
|
1013
1907
|
})
|
|
1014
1908
|
);
|
|
1015
1909
|
};
|
|
@@ -1018,7 +1912,7 @@ var removeActiveACPHash = (chainId, account) => {
|
|
|
1018
1912
|
_acpStore.setState(
|
|
1019
1913
|
immer.produce((state) => {
|
|
1020
1914
|
if (state.activeACPHash[chainId])
|
|
1021
|
-
state.activeACPHash[chainId][account] = void 0;
|
|
1915
|
+
state.activeACPHash[chainId][resolveAccountKey(state.activeACPHash[chainId], account)] = void 0;
|
|
1022
1916
|
})
|
|
1023
1917
|
);
|
|
1024
1918
|
};
|
|
@@ -1041,16 +1935,22 @@ var acpStore = {
|
|
|
1041
1935
|
|
|
1042
1936
|
exports.ACPScope = ACPScope;
|
|
1043
1937
|
exports.ACPUtils = ACPUtils;
|
|
1938
|
+
exports.ACP_REVOKER_ABI = ACP_REVOKER_ABI;
|
|
1939
|
+
exports.ACP_SHARE_REGISTRY_ABI = ACP_SHARE_REGISTRY_ABI;
|
|
1940
|
+
exports.ACP_SHARE_TUPLE_ABI = ACP_SHARE_TUPLE_ABI;
|
|
1044
1941
|
exports.ACP_STORE_DEFAULTS = ACP_STORE_DEFAULTS;
|
|
1942
|
+
exports.ERC7984_ABI = ERC7984_ABI;
|
|
1045
1943
|
exports.GenerateSealingKey = GenerateSealingKey;
|
|
1046
1944
|
exports.ImportACPOptionsValidator = ImportACPOptionsValidator;
|
|
1047
1945
|
exports.ImportACPValidator = ImportACPValidator;
|
|
1946
|
+
exports.SHARE_METADATA_VERSION = LAYOUT_VERSION;
|
|
1048
1947
|
exports.SelfACPOptionsValidator = SelfACPOptionsValidator;
|
|
1049
1948
|
exports.SelfACPValidator = SelfACPValidator;
|
|
1050
1949
|
exports.SharingACPOptionsValidator = SharingACPOptionsValidator;
|
|
1051
1950
|
exports.SharingACPValidator = SharingACPValidator;
|
|
1052
1951
|
exports.SignatureTypes = SignatureTypes;
|
|
1053
1952
|
exports.SignatureUtils = SignatureUtils;
|
|
1953
|
+
exports.UNLABELLED = UNLABELLED;
|
|
1054
1954
|
exports.ValidationUtils = ValidationUtils;
|
|
1055
1955
|
exports._acpStore = _acpStore;
|
|
1056
1956
|
exports.acpStore = acpStore;
|
|
@@ -1058,20 +1958,37 @@ exports.addressNotZeroSchema = addressNotZeroSchema;
|
|
|
1058
1958
|
exports.addressSchema = addressSchema;
|
|
1059
1959
|
exports.bytesNotEmptySchema = bytesNotEmptySchema;
|
|
1060
1960
|
exports.bytesSchema = bytesSchema;
|
|
1961
|
+
exports.clearAclServedAddresses = clearAclServedAddresses;
|
|
1061
1962
|
exports.clearStaleStore = clearStaleStore;
|
|
1963
|
+
exports.computeShareId = computeShareId;
|
|
1062
1964
|
exports.contractsSchema = contractsSchema;
|
|
1965
|
+
exports.decodeShareAppKey = decodeShareAppKey;
|
|
1966
|
+
exports.decodeShareMetadata = decodeShareMetadata;
|
|
1967
|
+
exports.decodeShareMetadataFull = decodeShareMetadataFull;
|
|
1968
|
+
exports.describeShareLabels = describeShareLabels;
|
|
1969
|
+
exports.describeShareMetadata = describeShareMetadata;
|
|
1970
|
+
exports.encodeShareMetadata = encodeShareMetadata;
|
|
1971
|
+
exports.eventLogLabel = eventLogLabel;
|
|
1063
1972
|
exports.getACP = getACP;
|
|
1064
1973
|
exports.getACPs = getACPs;
|
|
1974
|
+
exports.getAclAddress = getAclAddress;
|
|
1975
|
+
exports.getAclServedAddresses = getAclServedAddresses;
|
|
1065
1976
|
exports.getActiveACP = getActiveACP;
|
|
1066
1977
|
exports.getActiveACPHash = getActiveACPHash;
|
|
1067
1978
|
exports.getSignatureTypesAndMessage = getSignatureTypesAndMessage;
|
|
1068
1979
|
exports.handlesSchema = handlesSchema;
|
|
1980
|
+
exports.readPostedShares = readPostedShares;
|
|
1981
|
+
exports.readShare = readShare;
|
|
1982
|
+
exports.readSharesFor = readSharesFor;
|
|
1069
1983
|
exports.removeACP = removeACP;
|
|
1070
1984
|
exports.removeActiveACPHash = removeActiveACPHash;
|
|
1071
1985
|
exports.resetStore = resetStore;
|
|
1072
1986
|
exports.seal = seal;
|
|
1073
1987
|
exports.setACP = setACP;
|
|
1074
1988
|
exports.setActiveACPHash = setActiveACPHash;
|
|
1989
|
+
exports.shareAppKey = shareAppKey;
|
|
1990
|
+
exports.shareIdOfChainShare = shareIdOfChainShare;
|
|
1991
|
+
exports.toChainShare = toChainShare;
|
|
1075
1992
|
exports.unsealWithPrivateKey = unsealWithPrivateKey;
|
|
1076
1993
|
exports.validateImportACP = validateImportACP;
|
|
1077
1994
|
exports.validateImportACPOptions = validateImportACPOptions;
|
|
@@ -1079,3 +1996,6 @@ exports.validateSelfACP = validateSelfACP;
|
|
|
1079
1996
|
exports.validateSelfACPOptions = validateSelfACPOptions;
|
|
1080
1997
|
exports.validateSharingACP = validateSharingACP;
|
|
1081
1998
|
exports.validateSharingACPOptions = validateSharingACPOptions;
|
|
1999
|
+
exports.verifyShareLabel = verifyShareLabel;
|
|
2000
|
+
exports.verifyShareLabels = verifyShareLabels;
|
|
2001
|
+
exports.viewFunctionLabel = viewFunctionLabel;
|