@cofhe/sdk 0.8.0 → 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/acps/acp.ts +25 -6
- package/acps/index.ts +20 -15
- package/acps/registry.ts +166 -8
- 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/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 +43 -6
- package/acps/utils.ts +15 -2
- package/acps/validation.ts +3 -1
- package/core/acps.ts +123 -74
- package/core/client.ts +33 -7
- package/core/clientTypes.ts +25 -7
- package/core/config.ts +8 -0
- package/core/decrypt/apiError.ts +4 -1
- package/core/decrypt/verifyDecryptResult.ts +4 -1
- package/core/encrypt/cofheMocksZkVerifySign.ts +19 -2
- package/core/test/acpDefaults.test.ts +108 -19
- package/core/test/acpStoreAccountCase.test.ts +80 -0
- package/core/test/acps.test.ts +38 -3
- package/core/test/apiError.test.ts +8 -0
- package/core/test/appKeyConfig.test.ts +94 -0
- package/core/test/config.test.ts +8 -0
- package/core/test/decryptBuilders.test.ts +110 -2
- package/core/test/incomingShares.test.ts +84 -0
- package/core/test/mocksEncryptRange.test.ts +90 -0
- package/core/test/utils.test.ts +128 -0
- package/core/test/verifyDecryptResult.test.ts +51 -0
- package/core/utils.ts +16 -9
- package/dist/acps.cjs +674 -33
- package/dist/acps.d.cts +367 -35
- package/dist/acps.d.ts +367 -35
- package/dist/acps.js +2 -2
- package/dist/chunk-6ZW76ZKB.js +228 -0
- package/dist/{chunk-UJYOBHYA.js → chunk-BQWHPIYU.js} +660 -198
- package/dist/{chunk-GGI7Y6AW.js → chunk-OL3DZN7A.js} +110 -269
- package/dist/chunk-XQ32JG3T.js +174 -0
- package/dist/{clientTypes-D3aIXmUp.d.cts → clientTypes-C0A9ji5O.d.cts} +61 -21
- package/dist/{clientTypes-5YPPR16m.d.ts → clientTypes-CcU5WvdV.d.ts} +61 -21
- package/dist/core.cjs +3239 -2731
- package/dist/core.d.cts +6 -3
- package/dist/core.d.ts +6 -3
- package/dist/core.js +4 -3
- package/dist/node.cjs +3046 -2538
- package/dist/node.d.cts +2 -2
- package/dist/node.d.ts +2 -2
- package/dist/node.js +18 -17
- package/dist/{onchain-utils-CUAK8glx.d.cts → onchain-utils-D9Z33IP7.d.cts} +136 -12
- package/dist/{onchain-utils-CUAK8glx.d.ts → onchain-utils-D9Z33IP7.d.ts} +136 -12
- package/dist/web.cjs +3074 -2573
- package/dist/web.d.cts +2 -2
- package/dist/web.d.ts +2 -2
- package/dist/web.js +4 -10
- package/dist/zkProve.worker.cjs +14 -7
- package/dist/zkProve.worker.js +2 -8
- package/node/index.ts +1 -10
- package/node/storage.ts +18 -7
- package/node/test/storage-permissions.test.ts +40 -0
- package/package.json +4 -4
- package/web/index.ts +1 -10
- package/web/test/threadPoolBenchHelper.ts +1 -7
- package/web/zkProve.worker.ts +1 -10
- package/dist/chunk-NMKMCAI3.js +0 -14
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'"
|
|
@@ -815,7 +825,210 @@ var getAclServedAddresses = async (publicClient, chainId) => {
|
|
|
815
825
|
return resolved;
|
|
816
826
|
};
|
|
817
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" };
|
|
1029
|
+
|
|
818
1030
|
// acps/acp.ts
|
|
1031
|
+
var sharedByName = (issuer) => `Shared by ${issuer.slice(0, 6)}\u2026${issuer.slice(-4)}`;
|
|
819
1032
|
var ACPUtils = {
|
|
820
1033
|
/**
|
|
821
1034
|
* Create a self acp for personal use
|
|
@@ -837,10 +1050,16 @@ var ACPUtils = {
|
|
|
837
1050
|
*/
|
|
838
1051
|
createSharing: (options) => {
|
|
839
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;
|
|
840
1058
|
const sealingPair = GenerateSealingKey();
|
|
841
1059
|
const acp = {
|
|
842
1060
|
hash: ACPUtils.getHash(validation),
|
|
843
1061
|
...validation,
|
|
1062
|
+
...metadata != null && { metadata },
|
|
844
1063
|
sealingPrivateKey: sealingPair.privateKey,
|
|
845
1064
|
sealingKey: sealingPair.publicKey,
|
|
846
1065
|
_signedDomain: void 0
|
|
@@ -848,9 +1067,10 @@ var ACPUtils = {
|
|
|
848
1067
|
return acp;
|
|
849
1068
|
},
|
|
850
1069
|
/**
|
|
851
|
-
* 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.
|
|
852
1072
|
*/
|
|
853
|
-
importShared: (options) => {
|
|
1073
|
+
importShared: (options, { name } = {}) => {
|
|
854
1074
|
let parsedOptions;
|
|
855
1075
|
if (typeof options === "string") {
|
|
856
1076
|
try {
|
|
@@ -871,6 +1091,7 @@ var ACPUtils = {
|
|
|
871
1091
|
const acp = {
|
|
872
1092
|
hash: ACPUtils.getHash(validation),
|
|
873
1093
|
...validation,
|
|
1094
|
+
name: name?.trim() || sharedByName(validation.issuer),
|
|
874
1095
|
sealingPrivateKey: sealingPair.privateKey,
|
|
875
1096
|
sealingKey: sealingPair.publicKey,
|
|
876
1097
|
_signedDomain: void 0
|
|
@@ -929,8 +1150,8 @@ var ACPUtils = {
|
|
|
929
1150
|
/**
|
|
930
1151
|
* Import and sign a shared acp in one operation from various input formats
|
|
931
1152
|
*/
|
|
932
|
-
importSharedAndSign: async (options, publicClient, walletClient) => {
|
|
933
|
-
const acp = ACPUtils.importShared(options);
|
|
1153
|
+
importSharedAndSign: async (options, publicClient, walletClient, importOptions = {}) => {
|
|
1154
|
+
const acp = ACPUtils.importShared(options, importOptions);
|
|
934
1155
|
return ACPUtils.sign(acp, publicClient, walletClient);
|
|
935
1156
|
},
|
|
936
1157
|
/**
|
|
@@ -959,7 +1180,8 @@ var ACPUtils = {
|
|
|
959
1180
|
issuerSignature: acp.issuerSignature,
|
|
960
1181
|
recipientSignature: acp.recipientSignature,
|
|
961
1182
|
_signedDomain: acp._signedDomain,
|
|
962
|
-
sealingPrivateKey: acp.sealingPrivateKey
|
|
1183
|
+
sealingPrivateKey: acp.sealingPrivateKey,
|
|
1184
|
+
...acp.metadata != null && { metadata: acp.metadata }
|
|
963
1185
|
};
|
|
964
1186
|
},
|
|
965
1187
|
/**
|
|
@@ -1033,7 +1255,7 @@ var ACPUtils = {
|
|
|
1033
1255
|
/**
|
|
1034
1256
|
* Export acp data for sharing (strips the private component).
|
|
1035
1257
|
* Fixed `SharedACP` shape — every field always present, aligned with
|
|
1036
|
-
* `ACPPublic` and the on-chain sharing payload.
|
|
1258
|
+
* `ACPPublic` and the on-chain sharing payload — plus `metadata` when the acp has labels.
|
|
1037
1259
|
*/
|
|
1038
1260
|
export: (acp) => {
|
|
1039
1261
|
if (acp.type !== "sharing") {
|
|
@@ -1047,7 +1269,6 @@ var ACPUtils = {
|
|
|
1047
1269
|
);
|
|
1048
1270
|
}
|
|
1049
1271
|
const shared = {
|
|
1050
|
-
name: acp.name,
|
|
1051
1272
|
type: acp.type,
|
|
1052
1273
|
issuer: acp.issuer,
|
|
1053
1274
|
expiration: acp.expiration,
|
|
@@ -1057,7 +1278,8 @@ var ACPUtils = {
|
|
|
1057
1278
|
scope: acp.scope,
|
|
1058
1279
|
contracts: acp.contracts,
|
|
1059
1280
|
handles: acp.handles,
|
|
1060
|
-
issuerSignature: acp.issuerSignature
|
|
1281
|
+
issuerSignature: acp.issuerSignature,
|
|
1282
|
+
...acp.metadata != null && acp.metadata !== "0x" && { metadata: acp.metadata }
|
|
1061
1283
|
};
|
|
1062
1284
|
return JSON.stringify(shared, void 0, 2);
|
|
1063
1285
|
},
|
|
@@ -1143,11 +1365,14 @@ var ACP_REVOKER_ABI = viem.parseAbi([
|
|
|
1143
1365
|
]);
|
|
1144
1366
|
var ACP_SHARE_REGISTRY_ABI = viem.parseAbi([
|
|
1145
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; }",
|
|
1146
|
-
"
|
|
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)",
|
|
1147
1370
|
"function removeShare(bytes32 shareId) external",
|
|
1148
|
-
"function sharesFor(address recipient) external view returns (
|
|
1149
|
-
"function getShare(bytes32 shareId) external view returns (
|
|
1150
|
-
"function isShareValid(bytes32 shareId) external view returns (bool)"
|
|
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)"
|
|
1151
1376
|
]);
|
|
1152
1377
|
var ACP_SHARE_TUPLE_ABI = [
|
|
1153
1378
|
{
|
|
@@ -1183,11 +1408,393 @@ var computeShareId = (acp) => {
|
|
|
1183
1408
|
return viem.keccak256(viem.encodeAbiParameters(ACP_SHARE_TUPLE_ABI, [p]));
|
|
1184
1409
|
};
|
|
1185
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
|
+
}
|
|
1462
|
+
}
|
|
1463
|
+
return result;
|
|
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));
|
|
1186
1786
|
var ACP_STORE_DEFAULTS = {
|
|
1187
1787
|
acps: {},
|
|
1188
1788
|
activeACPHash: {}
|
|
1189
1789
|
};
|
|
1190
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
|
+
};
|
|
1191
1798
|
var _acpStore = vanilla.createStore()(
|
|
1192
1799
|
middleware.persist(() => ACP_STORE_DEFAULTS, {
|
|
1193
1800
|
name: "cofhesdk-acps",
|
|
@@ -1196,12 +1803,23 @@ var _acpStore = vanilla.createStore()(
|
|
|
1196
1803
|
if (version < ACP_STORE_VERSION)
|
|
1197
1804
|
return ACP_STORE_DEFAULTS;
|
|
1198
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
|
+
};
|
|
1199
1817
|
}
|
|
1200
1818
|
})
|
|
1201
1819
|
);
|
|
1202
1820
|
var clearStaleStore = () => {
|
|
1203
1821
|
const state = _acpStore.getState();
|
|
1204
|
-
const hasExpectedStructure = state &&
|
|
1822
|
+
const hasExpectedStructure = isRecord(state) && isRecord(state.acps) && isRecord(state.activeACPHash);
|
|
1205
1823
|
if (hasExpectedStructure)
|
|
1206
1824
|
return;
|
|
1207
1825
|
_acpStore.setState({ acps: {}, activeACPHash: {} });
|
|
@@ -1210,7 +1828,8 @@ var getACP = (chainId, account, hash) => {
|
|
|
1210
1828
|
clearStaleStore();
|
|
1211
1829
|
if (chainId == null || account == null || hash == null)
|
|
1212
1830
|
return;
|
|
1213
|
-
const
|
|
1831
|
+
const accountACPs = _acpStore.getState().acps[chainId];
|
|
1832
|
+
const savedACP = accountACPs?.[resolveAccountKey(accountACPs, account)]?.[hash];
|
|
1214
1833
|
if (savedACP == null)
|
|
1215
1834
|
return;
|
|
1216
1835
|
return ACPUtils.deserialize(savedACP);
|
|
@@ -1219,14 +1838,16 @@ var getActiveACP = (chainId, account) => {
|
|
|
1219
1838
|
clearStaleStore();
|
|
1220
1839
|
if (chainId == null || account == null)
|
|
1221
1840
|
return;
|
|
1222
|
-
const
|
|
1841
|
+
const activeHashes = _acpStore.getState().activeACPHash[chainId];
|
|
1842
|
+
const activeACPHash = activeHashes?.[resolveAccountKey(activeHashes, account)];
|
|
1223
1843
|
return getACP(chainId, account, activeACPHash);
|
|
1224
1844
|
};
|
|
1225
1845
|
var getACPs = (chainId, account) => {
|
|
1226
1846
|
clearStaleStore();
|
|
1227
1847
|
if (chainId == null || account == null)
|
|
1228
1848
|
return {};
|
|
1229
|
-
|
|
1849
|
+
const accountACPs = _acpStore.getState().acps[chainId];
|
|
1850
|
+
return Object.entries(accountACPs?.[resolveAccountKey(accountACPs, account)] ?? {}).reduce(
|
|
1230
1851
|
(acc, [hash, acp]) => {
|
|
1231
1852
|
if (acp == void 0)
|
|
1232
1853
|
return acc;
|
|
@@ -1241,9 +1862,10 @@ var setACP = (chainId, account, acp) => {
|
|
|
1241
1862
|
immer.produce((state) => {
|
|
1242
1863
|
if (state.acps[chainId] == null)
|
|
1243
1864
|
state.acps[chainId] = {};
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
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);
|
|
1247
1869
|
})
|
|
1248
1870
|
);
|
|
1249
1871
|
};
|
|
@@ -1255,13 +1877,14 @@ var removeACP = (chainId, account, hash) => {
|
|
|
1255
1877
|
state.acps[chainId] = {};
|
|
1256
1878
|
if (state.activeACPHash[chainId] == null)
|
|
1257
1879
|
state.activeACPHash[chainId] = {};
|
|
1258
|
-
const accountACPs = state.acps[chainId][account];
|
|
1880
|
+
const accountACPs = state.acps[chainId][resolveAccountKey(state.acps[chainId], account)];
|
|
1259
1881
|
if (accountACPs == null)
|
|
1260
1882
|
return;
|
|
1261
1883
|
if (accountACPs[hash] == null)
|
|
1262
1884
|
return;
|
|
1263
|
-
|
|
1264
|
-
|
|
1885
|
+
const activeKey = resolveAccountKey(state.activeACPHash[chainId], account);
|
|
1886
|
+
if (state.activeACPHash[chainId][activeKey] === hash) {
|
|
1887
|
+
state.activeACPHash[chainId][activeKey] = void 0;
|
|
1265
1888
|
}
|
|
1266
1889
|
accountACPs[hash] = void 0;
|
|
1267
1890
|
})
|
|
@@ -1271,7 +1894,8 @@ var getActiveACPHash = (chainId, account) => {
|
|
|
1271
1894
|
clearStaleStore();
|
|
1272
1895
|
if (chainId == null || account == null)
|
|
1273
1896
|
return void 0;
|
|
1274
|
-
|
|
1897
|
+
const activeHashes = _acpStore.getState().activeACPHash[chainId];
|
|
1898
|
+
return activeHashes?.[resolveAccountKey(activeHashes, account)];
|
|
1275
1899
|
};
|
|
1276
1900
|
var setActiveACPHash = (chainId, account, hash) => {
|
|
1277
1901
|
clearStaleStore();
|
|
@@ -1279,7 +1903,7 @@ var setActiveACPHash = (chainId, account, hash) => {
|
|
|
1279
1903
|
immer.produce((state) => {
|
|
1280
1904
|
if (state.activeACPHash[chainId] == null)
|
|
1281
1905
|
state.activeACPHash[chainId] = {};
|
|
1282
|
-
state.activeACPHash[chainId][account] = hash;
|
|
1906
|
+
state.activeACPHash[chainId][resolveAccountKey(state.activeACPHash[chainId], account)] = hash;
|
|
1283
1907
|
})
|
|
1284
1908
|
);
|
|
1285
1909
|
};
|
|
@@ -1288,7 +1912,7 @@ var removeActiveACPHash = (chainId, account) => {
|
|
|
1288
1912
|
_acpStore.setState(
|
|
1289
1913
|
immer.produce((state) => {
|
|
1290
1914
|
if (state.activeACPHash[chainId])
|
|
1291
|
-
state.activeACPHash[chainId][account] = void 0;
|
|
1915
|
+
state.activeACPHash[chainId][resolveAccountKey(state.activeACPHash[chainId], account)] = void 0;
|
|
1292
1916
|
})
|
|
1293
1917
|
);
|
|
1294
1918
|
};
|
|
@@ -1315,15 +1939,18 @@ exports.ACP_REVOKER_ABI = ACP_REVOKER_ABI;
|
|
|
1315
1939
|
exports.ACP_SHARE_REGISTRY_ABI = ACP_SHARE_REGISTRY_ABI;
|
|
1316
1940
|
exports.ACP_SHARE_TUPLE_ABI = ACP_SHARE_TUPLE_ABI;
|
|
1317
1941
|
exports.ACP_STORE_DEFAULTS = ACP_STORE_DEFAULTS;
|
|
1942
|
+
exports.ERC7984_ABI = ERC7984_ABI;
|
|
1318
1943
|
exports.GenerateSealingKey = GenerateSealingKey;
|
|
1319
1944
|
exports.ImportACPOptionsValidator = ImportACPOptionsValidator;
|
|
1320
1945
|
exports.ImportACPValidator = ImportACPValidator;
|
|
1946
|
+
exports.SHARE_METADATA_VERSION = LAYOUT_VERSION;
|
|
1321
1947
|
exports.SelfACPOptionsValidator = SelfACPOptionsValidator;
|
|
1322
1948
|
exports.SelfACPValidator = SelfACPValidator;
|
|
1323
1949
|
exports.SharingACPOptionsValidator = SharingACPOptionsValidator;
|
|
1324
1950
|
exports.SharingACPValidator = SharingACPValidator;
|
|
1325
1951
|
exports.SignatureTypes = SignatureTypes;
|
|
1326
1952
|
exports.SignatureUtils = SignatureUtils;
|
|
1953
|
+
exports.UNLABELLED = UNLABELLED;
|
|
1327
1954
|
exports.ValidationUtils = ValidationUtils;
|
|
1328
1955
|
exports._acpStore = _acpStore;
|
|
1329
1956
|
exports.acpStore = acpStore;
|
|
@@ -1335,6 +1962,13 @@ exports.clearAclServedAddresses = clearAclServedAddresses;
|
|
|
1335
1962
|
exports.clearStaleStore = clearStaleStore;
|
|
1336
1963
|
exports.computeShareId = computeShareId;
|
|
1337
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;
|
|
1338
1972
|
exports.getACP = getACP;
|
|
1339
1973
|
exports.getACPs = getACPs;
|
|
1340
1974
|
exports.getAclAddress = getAclAddress;
|
|
@@ -1343,12 +1977,16 @@ exports.getActiveACP = getActiveACP;
|
|
|
1343
1977
|
exports.getActiveACPHash = getActiveACPHash;
|
|
1344
1978
|
exports.getSignatureTypesAndMessage = getSignatureTypesAndMessage;
|
|
1345
1979
|
exports.handlesSchema = handlesSchema;
|
|
1980
|
+
exports.readPostedShares = readPostedShares;
|
|
1981
|
+
exports.readShare = readShare;
|
|
1982
|
+
exports.readSharesFor = readSharesFor;
|
|
1346
1983
|
exports.removeACP = removeACP;
|
|
1347
1984
|
exports.removeActiveACPHash = removeActiveACPHash;
|
|
1348
1985
|
exports.resetStore = resetStore;
|
|
1349
1986
|
exports.seal = seal;
|
|
1350
1987
|
exports.setACP = setACP;
|
|
1351
1988
|
exports.setActiveACPHash = setActiveACPHash;
|
|
1989
|
+
exports.shareAppKey = shareAppKey;
|
|
1352
1990
|
exports.shareIdOfChainShare = shareIdOfChainShare;
|
|
1353
1991
|
exports.toChainShare = toChainShare;
|
|
1354
1992
|
exports.unsealWithPrivateKey = unsealWithPrivateKey;
|
|
@@ -1358,3 +1996,6 @@ exports.validateSelfACP = validateSelfACP;
|
|
|
1358
1996
|
exports.validateSelfACPOptions = validateSelfACPOptions;
|
|
1359
1997
|
exports.validateSharingACP = validateSharingACP;
|
|
1360
1998
|
exports.validateSharingACPOptions = validateSharingACPOptions;
|
|
1999
|
+
exports.verifyShareLabel = verifyShareLabel;
|
|
2000
|
+
exports.verifyShareLabels = verifyShareLabels;
|
|
2001
|
+
exports.viewFunctionLabel = viewFunctionLabel;
|