@arcenpay/node 0.0.1 → 0.0.2
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/dist/_esm-H6IRXC3A.mjs +804 -0
- package/dist/_esm-HVKNJV5D.mjs +127 -0
- package/dist/chains-3R75GF4L.mjs +21 -0
- package/dist/{chunk-SKFD6TSD.mjs → chunk-5CPGRELK.mjs} +3 -25
- package/dist/chunk-E2J5KZ6E.mjs +41 -0
- package/dist/chunk-GY2HMODH.mjs +94 -0
- package/dist/chunk-XHLV6BIG.mjs +10224 -0
- package/dist/index.d.mts +9 -10
- package/dist/index.d.ts +9 -10
- package/dist/index.js +1328 -180
- package/dist/index.mjs +1218 -153
- package/dist/tableland-gyl7O0n6.d.mts +191 -0
- package/dist/tableland-gyl7O0n6.d.ts +191 -0
- package/dist/tableland.d.mts +1 -46
- package/dist/tableland.d.ts +1 -46
- package/dist/tableland.js +3 -1
- package/dist/tableland.mjs +2 -1
- package/package.json +6 -2
|
@@ -0,0 +1,804 @@
|
|
|
1
|
+
import {
|
|
2
|
+
DUMMY_ECDSA_SIG,
|
|
3
|
+
KERNEL_FEATURES,
|
|
4
|
+
KernelAccountAbi,
|
|
5
|
+
KernelFactoryStakerAbi,
|
|
6
|
+
KernelV3AccountAbi,
|
|
7
|
+
KernelV3InitAbi,
|
|
8
|
+
KernelV3_1AccountAbi,
|
|
9
|
+
KernelVersionToAddressesMap,
|
|
10
|
+
MAGIC_VALUE_SIG_REPLAYABLE,
|
|
11
|
+
VALIDATOR_MODE,
|
|
12
|
+
VALIDATOR_TYPE,
|
|
13
|
+
accountMetadata,
|
|
14
|
+
constants_exports,
|
|
15
|
+
createKernelAccountClient,
|
|
16
|
+
eip712WrapHash,
|
|
17
|
+
encodeCallData,
|
|
18
|
+
encodeCallData2,
|
|
19
|
+
encodeDeployCallData,
|
|
20
|
+
encodeDeployCallData2,
|
|
21
|
+
getAccountNonce,
|
|
22
|
+
getKernelImplementationAddress,
|
|
23
|
+
getPluginInstallCallData,
|
|
24
|
+
getSenderAddress,
|
|
25
|
+
hasKernelFeature,
|
|
26
|
+
isPluginInstalled,
|
|
27
|
+
satisfiesRange,
|
|
28
|
+
toKernelPluginManager,
|
|
29
|
+
toSigner,
|
|
30
|
+
validateKernelVersionWithEntryPoint
|
|
31
|
+
} from "./chunk-XHLV6BIG.mjs";
|
|
32
|
+
import "./chunk-E2J5KZ6E.mjs";
|
|
33
|
+
|
|
34
|
+
// ../../node_modules/@zerodev/ecdsa-validator/_esm/getAddress.js
|
|
35
|
+
import { concat, concatHex, encodeFunctionData, getContract, getContractAddress, isAddress, keccak256, toHex, zeroAddress as zeroAddress2 } from "viem";
|
|
36
|
+
|
|
37
|
+
// ../../node_modules/@zerodev/ecdsa-validator/_esm/toECDSAValidatorPlugin.js
|
|
38
|
+
import { zeroAddress } from "viem";
|
|
39
|
+
import { getUserOperationHash } from "viem/account-abstraction";
|
|
40
|
+
import { toAccount } from "viem/accounts";
|
|
41
|
+
import { getChainId, signMessage } from "viem/actions";
|
|
42
|
+
|
|
43
|
+
// ../../node_modules/@zerodev/ecdsa-validator/_esm/constants.js
|
|
44
|
+
var kernelVersionRangeToValidator = {
|
|
45
|
+
"0.0.2 - 0.2.4": "0xd9AB5096a832b9ce79914329DAEE236f8Eea0390",
|
|
46
|
+
"0.3.0": "0x8104e3Ad430EA6d354d013A6789fDFc71E671c43",
|
|
47
|
+
">=0.3.1": "0x845ADb2C711129d4f3966735eD98a9F09fC4cE57"
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
// ../../node_modules/@zerodev/ecdsa-validator/_esm/toECDSAValidatorPlugin.js
|
|
51
|
+
var getValidatorAddress = (entryPoint, kernelVersion, validatorAddress) => {
|
|
52
|
+
validateKernelVersionWithEntryPoint(entryPoint.version, kernelVersion);
|
|
53
|
+
const ecdsaValidatorAddress = Object.entries(kernelVersionRangeToValidator).find(([range]) => satisfiesRange(kernelVersion, range))?.[1];
|
|
54
|
+
if (!ecdsaValidatorAddress && !validatorAddress) {
|
|
55
|
+
throw new Error(`Validator not found for Kernel version: ${kernelVersion}`);
|
|
56
|
+
}
|
|
57
|
+
return validatorAddress ?? ecdsaValidatorAddress ?? zeroAddress;
|
|
58
|
+
};
|
|
59
|
+
async function signerToEcdsaValidator(client, { signer, entryPoint, kernelVersion, validatorAddress: _validatorAddress }) {
|
|
60
|
+
const validatorAddress = getValidatorAddress(entryPoint, kernelVersion, _validatorAddress);
|
|
61
|
+
const viemSigner = await toSigner({ signer });
|
|
62
|
+
const chainId = await getChainId(client);
|
|
63
|
+
const account = toAccount({
|
|
64
|
+
address: viemSigner.address,
|
|
65
|
+
async signMessage({ message }) {
|
|
66
|
+
return signMessage(client, { account: viemSigner, message });
|
|
67
|
+
},
|
|
68
|
+
async signTransaction(_, __) {
|
|
69
|
+
throw new Error("Smart account signer doesn't need to sign transactions");
|
|
70
|
+
},
|
|
71
|
+
async signTypedData(typedData) {
|
|
72
|
+
return viemSigner.signTypedData(typedData);
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
return {
|
|
76
|
+
...account,
|
|
77
|
+
supportedKernelVersions: kernelVersion,
|
|
78
|
+
validatorType: "SECONDARY",
|
|
79
|
+
address: validatorAddress,
|
|
80
|
+
source: "ECDSAValidator",
|
|
81
|
+
getIdentifier() {
|
|
82
|
+
return validatorAddress;
|
|
83
|
+
},
|
|
84
|
+
async getEnableData() {
|
|
85
|
+
return viemSigner.address;
|
|
86
|
+
},
|
|
87
|
+
async getNonceKey(_accountAddress, customNonceKey) {
|
|
88
|
+
if (customNonceKey) {
|
|
89
|
+
return customNonceKey;
|
|
90
|
+
}
|
|
91
|
+
return 0n;
|
|
92
|
+
},
|
|
93
|
+
// Sign a user operation
|
|
94
|
+
async signUserOperation(userOperation) {
|
|
95
|
+
const hash = getUserOperationHash({
|
|
96
|
+
userOperation: {
|
|
97
|
+
...userOperation,
|
|
98
|
+
signature: "0x"
|
|
99
|
+
},
|
|
100
|
+
entryPointAddress: entryPoint.address,
|
|
101
|
+
entryPointVersion: entryPoint.version,
|
|
102
|
+
chainId
|
|
103
|
+
});
|
|
104
|
+
const signature = await signMessage(client, {
|
|
105
|
+
account: viemSigner,
|
|
106
|
+
message: { raw: hash }
|
|
107
|
+
});
|
|
108
|
+
return signature;
|
|
109
|
+
},
|
|
110
|
+
// Get simple dummy signature
|
|
111
|
+
async getStubSignature() {
|
|
112
|
+
return "0xfffffffffffffffffffffffffffffff0000000000000000000000000000000007aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1c";
|
|
113
|
+
},
|
|
114
|
+
async isEnabled(_kernelAccountAddress, _selector) {
|
|
115
|
+
return false;
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// ../../node_modules/@zerodev/ecdsa-validator/_esm/getAddress.js
|
|
121
|
+
var getInitCodeHash = async (publicClient, entryPoint, kernelVersion) => {
|
|
122
|
+
validateKernelVersionWithEntryPoint(entryPoint.version, kernelVersion);
|
|
123
|
+
const addresses = constants_exports.KernelVersionToAddressesMap[kernelVersion];
|
|
124
|
+
if (entryPoint.version === "0.6") {
|
|
125
|
+
return await initCodeHashV0_6(publicClient, addresses.factoryAddress);
|
|
126
|
+
}
|
|
127
|
+
return initCodeHashV0_7(addresses.accountImplementationAddress);
|
|
128
|
+
};
|
|
129
|
+
var initCodeHashV0_6 = async (publicClient, factoryAddress) => {
|
|
130
|
+
const factoryContract = getContract({
|
|
131
|
+
address: factoryAddress,
|
|
132
|
+
abi: [
|
|
133
|
+
{
|
|
134
|
+
type: "function",
|
|
135
|
+
name: "initCodeHash",
|
|
136
|
+
inputs: [],
|
|
137
|
+
outputs: [
|
|
138
|
+
{
|
|
139
|
+
name: "result",
|
|
140
|
+
type: "bytes32",
|
|
141
|
+
internalType: "bytes32"
|
|
142
|
+
}
|
|
143
|
+
],
|
|
144
|
+
stateMutability: "view"
|
|
145
|
+
}
|
|
146
|
+
],
|
|
147
|
+
client: publicClient
|
|
148
|
+
});
|
|
149
|
+
return await factoryContract.read.initCodeHash();
|
|
150
|
+
};
|
|
151
|
+
var initCodeHashV0_7 = (implementationAddress) => {
|
|
152
|
+
if (!isAddress(implementationAddress)) {
|
|
153
|
+
throw new Error("Invalid implementation address");
|
|
154
|
+
}
|
|
155
|
+
const initCode = concatHex([
|
|
156
|
+
"0x603d3d8160223d3973",
|
|
157
|
+
implementationAddress,
|
|
158
|
+
"0x6009",
|
|
159
|
+
"0x5155f3363d3d373d3d363d7f360894a13ba1a3210667c828492db98dca3e2076",
|
|
160
|
+
"0xcc3735a920a3ca505d382bbc545af43d6000803e6038573d6000fd5b3d6000f3"
|
|
161
|
+
]);
|
|
162
|
+
const hash = keccak256(initCode);
|
|
163
|
+
return hash;
|
|
164
|
+
};
|
|
165
|
+
var generateSaltForV06 = (eoaAddress, index, validatorAddress) => {
|
|
166
|
+
const encodedIndex = toHex(index, { size: 32 });
|
|
167
|
+
const initData = encodeFunctionData({
|
|
168
|
+
abi: KernelAccountAbi,
|
|
169
|
+
functionName: "initialize",
|
|
170
|
+
args: [validatorAddress, eoaAddress]
|
|
171
|
+
});
|
|
172
|
+
const encodedSalt = concat([initData, encodedIndex]);
|
|
173
|
+
const salt = BigInt(keccak256(encodedSalt));
|
|
174
|
+
const mask = BigInt("0xffffffffffffffffffffffff");
|
|
175
|
+
const maskedSalt = toHex(salt & mask, { size: 32 });
|
|
176
|
+
return maskedSalt;
|
|
177
|
+
};
|
|
178
|
+
var generateSaltForV07 = (eoaAddress, index, hookAddress, hookData, validatorAddress, kernelVersion, initConfig) => {
|
|
179
|
+
const encodedIndex = toHex(index, { size: 32 });
|
|
180
|
+
let initData;
|
|
181
|
+
if (kernelVersion === "0.3.0") {
|
|
182
|
+
initData = encodeFunctionData({
|
|
183
|
+
abi: KernelV3InitAbi,
|
|
184
|
+
functionName: "initialize",
|
|
185
|
+
args: [
|
|
186
|
+
concatHex([
|
|
187
|
+
constants_exports.VALIDATOR_TYPE.SECONDARY,
|
|
188
|
+
validatorAddress
|
|
189
|
+
]),
|
|
190
|
+
hookAddress,
|
|
191
|
+
eoaAddress,
|
|
192
|
+
hookData
|
|
193
|
+
]
|
|
194
|
+
});
|
|
195
|
+
const packedData2 = concatHex([initData, encodedIndex]);
|
|
196
|
+
return keccak256(packedData2);
|
|
197
|
+
}
|
|
198
|
+
initData = encodeFunctionData({
|
|
199
|
+
abi: KernelV3_1AccountAbi,
|
|
200
|
+
functionName: "initialize",
|
|
201
|
+
args: [
|
|
202
|
+
concatHex([constants_exports.VALIDATOR_TYPE.SECONDARY, validatorAddress]),
|
|
203
|
+
hookAddress,
|
|
204
|
+
eoaAddress,
|
|
205
|
+
hookData,
|
|
206
|
+
initConfig
|
|
207
|
+
]
|
|
208
|
+
});
|
|
209
|
+
const packedData = concatHex([initData, encodedIndex]);
|
|
210
|
+
return keccak256(packedData);
|
|
211
|
+
};
|
|
212
|
+
async function getKernelAddressFromECDSA(params) {
|
|
213
|
+
validateKernelVersionWithEntryPoint(params.entryPoint.version, params.kernelVersion);
|
|
214
|
+
const kernelAddresses = constants_exports.KernelVersionToAddressesMap[params.kernelVersion];
|
|
215
|
+
const ecdsaValidatorAddress = getValidatorAddress(params.entryPoint, params.kernelVersion);
|
|
216
|
+
const bytecodeHash = await (async () => {
|
|
217
|
+
if ("initCodeHash" in params && params.initCodeHash) {
|
|
218
|
+
return params.initCodeHash;
|
|
219
|
+
}
|
|
220
|
+
if ("publicClient" in params && params.publicClient) {
|
|
221
|
+
return await getInitCodeHash(params.publicClient, params.entryPoint, params.kernelVersion);
|
|
222
|
+
}
|
|
223
|
+
throw new Error("Either initCodeHash or publicClient must be provided");
|
|
224
|
+
})();
|
|
225
|
+
let salt;
|
|
226
|
+
if (params.entryPoint.version === "0.6") {
|
|
227
|
+
salt = generateSaltForV06(params.eoaAddress, params.index, ecdsaValidatorAddress);
|
|
228
|
+
} else {
|
|
229
|
+
const hookAddress = "hookAddress" in params && params.hookAddress ? params.hookAddress : zeroAddress2;
|
|
230
|
+
const hookData = "hookData" in params && params.hookData ? params.hookData : "0x";
|
|
231
|
+
const initConfig = "initConfig" in params && params.initConfig ? params.initConfig : [];
|
|
232
|
+
salt = generateSaltForV07(params.eoaAddress, params.index, hookAddress, hookData, ecdsaValidatorAddress, params.kernelVersion, initConfig);
|
|
233
|
+
}
|
|
234
|
+
return getContractAddress({
|
|
235
|
+
bytecodeHash,
|
|
236
|
+
opcode: "CREATE2",
|
|
237
|
+
from: kernelAddresses.factoryAddress,
|
|
238
|
+
salt
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// ../../node_modules/@zerodev/ecdsa-validator/_esm/account/createEcdsaKernelMigrationAccount.js
|
|
243
|
+
import { concatHex as concatHex2, createNonceManager, encodeFunctionData as encodeFunctionData2, getTypesForEIP712Domain, hashMessage, hashTypedData, isAddressEqual, maxUint16, pad, toHex as toHex2, validateTypedData, zeroAddress as zeroAddress3 } from "viem";
|
|
244
|
+
import { entryPoint06Abi, entryPoint07Abi, entryPoint07Address, getUserOperationHash as getUserOperationHash2, toSmartAccount } from "viem/account-abstraction";
|
|
245
|
+
import { getChainId as getChainId2, signMessage as signMessage2 } from "viem/actions";
|
|
246
|
+
import { getAction } from "viem/utils";
|
|
247
|
+
var getKernelInitData = ({ entryPointVersion: _entryPointVersion, kernelVersion, validatorAddress, validatorData }) => {
|
|
248
|
+
const validatorId = concatHex2([VALIDATOR_TYPE.SECONDARY, validatorAddress]);
|
|
249
|
+
if (kernelVersion === "0.3.0") {
|
|
250
|
+
return encodeFunctionData2({
|
|
251
|
+
abi: KernelV3InitAbi,
|
|
252
|
+
functionName: "initialize",
|
|
253
|
+
args: [validatorId, zeroAddress3, validatorData, "0x"]
|
|
254
|
+
});
|
|
255
|
+
}
|
|
256
|
+
return encodeFunctionData2({
|
|
257
|
+
abi: KernelV3_1AccountAbi,
|
|
258
|
+
functionName: "initialize",
|
|
259
|
+
args: [validatorId, zeroAddress3, validatorData, "0x", []]
|
|
260
|
+
});
|
|
261
|
+
};
|
|
262
|
+
var getAccountInitCode = async ({ entryPointVersion, kernelVersion, validatorData, index, factoryAddress, validatorAddress }) => {
|
|
263
|
+
const initializationData = getKernelInitData({
|
|
264
|
+
entryPointVersion,
|
|
265
|
+
kernelVersion,
|
|
266
|
+
validatorAddress,
|
|
267
|
+
validatorData
|
|
268
|
+
});
|
|
269
|
+
return encodeFunctionData2({
|
|
270
|
+
abi: KernelFactoryStakerAbi,
|
|
271
|
+
functionName: "deployWithFactory",
|
|
272
|
+
args: [factoryAddress, initializationData, toHex2(index, { size: 32 })]
|
|
273
|
+
});
|
|
274
|
+
};
|
|
275
|
+
var isKernelUpgraded = async (client, accountAddress, toKernelVersion) => {
|
|
276
|
+
const kernelImplementation = await getKernelImplementationAddress(client, {
|
|
277
|
+
address: accountAddress
|
|
278
|
+
});
|
|
279
|
+
return isAddressEqual(kernelImplementation, KernelVersionToAddressesMap[toKernelVersion].accountImplementationAddress);
|
|
280
|
+
};
|
|
281
|
+
async function createEcdsaKernelMigrationAccount(client, { entryPoint, signer, index = 0n, address, migrationVersion, pluginMigrations }) {
|
|
282
|
+
if (entryPoint.version === "0.6") {
|
|
283
|
+
throw new Error("EntryPointV0.6 is not supported for migration");
|
|
284
|
+
}
|
|
285
|
+
validateKernelVersionWithEntryPoint(entryPoint.version, migrationVersion.from);
|
|
286
|
+
validateKernelVersionWithEntryPoint(entryPoint.version, migrationVersion.to);
|
|
287
|
+
const fromAddresses = KernelVersionToAddressesMap[migrationVersion.from];
|
|
288
|
+
const fromValidatorAddress = getValidatorAddress(entryPoint, migrationVersion.from);
|
|
289
|
+
const toValidatorAddress = getValidatorAddress(entryPoint, migrationVersion.to);
|
|
290
|
+
const viemSigner = await toSigner({ signer });
|
|
291
|
+
let chainId;
|
|
292
|
+
const getMemoizedChainId = async () => {
|
|
293
|
+
if (chainId)
|
|
294
|
+
return chainId;
|
|
295
|
+
chainId = client.chain ? client.chain.id : await getAction(client, getChainId2, "getChainId")({});
|
|
296
|
+
return chainId;
|
|
297
|
+
};
|
|
298
|
+
const generateInitCode = async () => {
|
|
299
|
+
return getAccountInitCode({
|
|
300
|
+
entryPointVersion: entryPoint.version,
|
|
301
|
+
factoryAddress: fromAddresses.factoryAddress,
|
|
302
|
+
index,
|
|
303
|
+
kernelVersion: migrationVersion.from,
|
|
304
|
+
validatorAddress: fromValidatorAddress,
|
|
305
|
+
validatorData: viemSigner.address
|
|
306
|
+
});
|
|
307
|
+
};
|
|
308
|
+
const getFactoryArgs = async () => {
|
|
309
|
+
return {
|
|
310
|
+
factory: fromAddresses.metaFactoryAddress ?? zeroAddress3,
|
|
311
|
+
factoryData: await generateInitCode()
|
|
312
|
+
};
|
|
313
|
+
};
|
|
314
|
+
let accountAddress = address ?? await (async () => {
|
|
315
|
+
const { factory, factoryData } = await getFactoryArgs();
|
|
316
|
+
return await getSenderAddress(client, {
|
|
317
|
+
factory,
|
|
318
|
+
factoryData,
|
|
319
|
+
entryPointAddress: entryPoint.address
|
|
320
|
+
});
|
|
321
|
+
})();
|
|
322
|
+
let kernelUpgraded = await isKernelUpgraded(client, accountAddress, migrationVersion.to);
|
|
323
|
+
const pluginCache = {
|
|
324
|
+
pendingPlugins: pluginMigrations || [],
|
|
325
|
+
allInstalled: false
|
|
326
|
+
};
|
|
327
|
+
const checkPluginInstallationStatus = async () => {
|
|
328
|
+
if (!pluginCache.pendingPlugins.length || pluginCache.allInstalled) {
|
|
329
|
+
pluginCache.allInstalled = true;
|
|
330
|
+
return;
|
|
331
|
+
}
|
|
332
|
+
const installationResults = await Promise.all(pluginCache.pendingPlugins.map((plugin) => isPluginInstalled(client, {
|
|
333
|
+
address: accountAddress,
|
|
334
|
+
plugin
|
|
335
|
+
})));
|
|
336
|
+
pluginCache.pendingPlugins = pluginCache.pendingPlugins.filter((_, index2) => !installationResults[index2]);
|
|
337
|
+
pluginCache.allInstalled = pluginCache.pendingPlugins.length === 0;
|
|
338
|
+
};
|
|
339
|
+
await checkPluginInstallationStatus();
|
|
340
|
+
const _entryPoint = {
|
|
341
|
+
address: entryPoint?.address ?? entryPoint07Address,
|
|
342
|
+
abi: (entryPoint?.version ?? "0.7") === "0.6" ? entryPoint06Abi : entryPoint07Abi,
|
|
343
|
+
version: entryPoint?.version ?? "0.7"
|
|
344
|
+
};
|
|
345
|
+
return toSmartAccount({
|
|
346
|
+
kernelVersion: migrationVersion.to,
|
|
347
|
+
kernelPluginManager: await toKernelPluginManager(client, {
|
|
348
|
+
entryPoint,
|
|
349
|
+
kernelVersion: migrationVersion.to,
|
|
350
|
+
chainId: await getMemoizedChainId(),
|
|
351
|
+
sudo: await signerToEcdsaValidator(client, {
|
|
352
|
+
entryPoint,
|
|
353
|
+
signer: viemSigner,
|
|
354
|
+
kernelVersion: migrationVersion.to,
|
|
355
|
+
validatorAddress: toValidatorAddress
|
|
356
|
+
})
|
|
357
|
+
}),
|
|
358
|
+
factoryAddress: (await getFactoryArgs()).factory,
|
|
359
|
+
generateInitCode,
|
|
360
|
+
accountImplementationAddress: KernelVersionToAddressesMap[migrationVersion.to].accountImplementationAddress,
|
|
361
|
+
encodeModuleInstallCallData: async () => {
|
|
362
|
+
throw new Error("Not implemented");
|
|
363
|
+
},
|
|
364
|
+
nonceKeyManager: createNonceManager({
|
|
365
|
+
source: { get: () => 0, set: () => {
|
|
366
|
+
} }
|
|
367
|
+
}),
|
|
368
|
+
client,
|
|
369
|
+
entryPoint: _entryPoint,
|
|
370
|
+
getFactoryArgs,
|
|
371
|
+
async getAddress() {
|
|
372
|
+
if (accountAddress)
|
|
373
|
+
return accountAddress;
|
|
374
|
+
const { factory, factoryData } = await getFactoryArgs();
|
|
375
|
+
accountAddress = await getSenderAddress(client, {
|
|
376
|
+
factory,
|
|
377
|
+
factoryData,
|
|
378
|
+
entryPointAddress: entryPoint.address
|
|
379
|
+
});
|
|
380
|
+
return accountAddress;
|
|
381
|
+
},
|
|
382
|
+
// Encode the deploy call data
|
|
383
|
+
async encodeDeployCallData(_tx) {
|
|
384
|
+
throw new Error("Not implemented");
|
|
385
|
+
},
|
|
386
|
+
async encodeCalls(calls, callType) {
|
|
387
|
+
await checkPluginInstallationStatus();
|
|
388
|
+
const pluginInstallCalls = [];
|
|
389
|
+
if (pluginCache.pendingPlugins.length > 0 && entryPoint.version === "0.7") {
|
|
390
|
+
for (const plugin of pluginCache.pendingPlugins) {
|
|
391
|
+
pluginInstallCalls.push(getPluginInstallCallData(accountAddress, plugin));
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
kernelUpgraded = kernelUpgraded || await isKernelUpgraded(client, accountAddress, migrationVersion.to);
|
|
395
|
+
let _calls = calls;
|
|
396
|
+
if (!kernelUpgraded) {
|
|
397
|
+
const implementation = KernelVersionToAddressesMap[migrationVersion.to].accountImplementationAddress;
|
|
398
|
+
const upgradeCall = {
|
|
399
|
+
to: accountAddress,
|
|
400
|
+
data: encodeFunctionData2({
|
|
401
|
+
abi: KernelV3AccountAbi,
|
|
402
|
+
functionName: "upgradeTo",
|
|
403
|
+
args: [implementation]
|
|
404
|
+
}),
|
|
405
|
+
value: 0n
|
|
406
|
+
};
|
|
407
|
+
if (!isAddressEqual(fromValidatorAddress, toValidatorAddress)) {
|
|
408
|
+
const rootValidatorId = concatHex2([
|
|
409
|
+
VALIDATOR_TYPE.SECONDARY,
|
|
410
|
+
pad(toValidatorAddress, {
|
|
411
|
+
size: 20,
|
|
412
|
+
dir: "right"
|
|
413
|
+
})
|
|
414
|
+
]);
|
|
415
|
+
const updateValidatorCall = {
|
|
416
|
+
to: accountAddress,
|
|
417
|
+
data: encodeFunctionData2({
|
|
418
|
+
abi: KernelV3_1AccountAbi,
|
|
419
|
+
functionName: "changeRootValidator",
|
|
420
|
+
args: [
|
|
421
|
+
rootValidatorId,
|
|
422
|
+
zeroAddress3,
|
|
423
|
+
viemSigner.address,
|
|
424
|
+
"0x"
|
|
425
|
+
]
|
|
426
|
+
}),
|
|
427
|
+
value: 0n
|
|
428
|
+
};
|
|
429
|
+
_calls = [
|
|
430
|
+
upgradeCall,
|
|
431
|
+
updateValidatorCall,
|
|
432
|
+
...pluginInstallCalls,
|
|
433
|
+
...calls
|
|
434
|
+
];
|
|
435
|
+
}
|
|
436
|
+
_calls = [upgradeCall, ...pluginInstallCalls, ...calls];
|
|
437
|
+
} else {
|
|
438
|
+
_calls = [...pluginInstallCalls, ...calls];
|
|
439
|
+
}
|
|
440
|
+
return encodeCallData2(_calls, callType);
|
|
441
|
+
},
|
|
442
|
+
async sign({ hash }) {
|
|
443
|
+
return this.signMessage({ message: hash });
|
|
444
|
+
},
|
|
445
|
+
async signMessage({ message, useReplayableSignature }) {
|
|
446
|
+
kernelUpgraded = kernelUpgraded || await isKernelUpgraded(client, accountAddress, migrationVersion.to);
|
|
447
|
+
const messageHash = hashMessage(message);
|
|
448
|
+
const version_ = kernelUpgraded ? migrationVersion.to : migrationVersion.from;
|
|
449
|
+
const version = version_ === "0.3.0" ? "0.3.0-beta" : version_;
|
|
450
|
+
const wrappedMessageHash = await eip712WrapHash(messageHash, {
|
|
451
|
+
name: "Kernel",
|
|
452
|
+
chainId,
|
|
453
|
+
version,
|
|
454
|
+
verifyingContract: accountAddress
|
|
455
|
+
}, useReplayableSignature);
|
|
456
|
+
let signature = await viemSigner.signMessage({
|
|
457
|
+
message: { raw: wrappedMessageHash }
|
|
458
|
+
});
|
|
459
|
+
if (!hasKernelFeature(KERNEL_FEATURES.ERC1271_WITH_VALIDATOR, version)) {
|
|
460
|
+
return signature;
|
|
461
|
+
}
|
|
462
|
+
if (useReplayableSignature && hasKernelFeature(KERNEL_FEATURES.ERC1271_REPLAYABLE, version)) {
|
|
463
|
+
signature = concatHex2([MAGIC_VALUE_SIG_REPLAYABLE, signature]);
|
|
464
|
+
}
|
|
465
|
+
return concatHex2([VALIDATOR_TYPE.SUDO, signature]);
|
|
466
|
+
},
|
|
467
|
+
async signTypedData(typedData) {
|
|
468
|
+
const { message, primaryType, types: _types, domain } = typedData;
|
|
469
|
+
const types = {
|
|
470
|
+
EIP712Domain: getTypesForEIP712Domain({
|
|
471
|
+
domain
|
|
472
|
+
}),
|
|
473
|
+
..._types
|
|
474
|
+
};
|
|
475
|
+
validateTypedData({
|
|
476
|
+
domain,
|
|
477
|
+
message,
|
|
478
|
+
primaryType,
|
|
479
|
+
types
|
|
480
|
+
});
|
|
481
|
+
const typedHash = hashTypedData(typedData);
|
|
482
|
+
kernelUpgraded = kernelUpgraded || await isKernelUpgraded(client, accountAddress, migrationVersion.to);
|
|
483
|
+
const version_ = kernelUpgraded ? migrationVersion.to : migrationVersion.from;
|
|
484
|
+
const version = version_ === "0.3.0" ? "0.3.0-beta" : version_;
|
|
485
|
+
const wrappedMessageHash = await eip712WrapHash(typedHash, {
|
|
486
|
+
name: "Kernel",
|
|
487
|
+
chainId,
|
|
488
|
+
version,
|
|
489
|
+
verifyingContract: accountAddress
|
|
490
|
+
});
|
|
491
|
+
const signature = await viemSigner.signMessage({
|
|
492
|
+
message: { raw: wrappedMessageHash }
|
|
493
|
+
});
|
|
494
|
+
if (!hasKernelFeature(KERNEL_FEATURES.ERC1271_WITH_VALIDATOR, version)) {
|
|
495
|
+
return signature;
|
|
496
|
+
}
|
|
497
|
+
return concatHex2([VALIDATOR_TYPE.SUDO, signature]);
|
|
498
|
+
},
|
|
499
|
+
// Get the nonce of the smart account
|
|
500
|
+
async getNonce(_args) {
|
|
501
|
+
const key = getNonceKeyWithEncoding(fromValidatorAddress, _args?.key);
|
|
502
|
+
return getAccountNonce(client, {
|
|
503
|
+
address: accountAddress,
|
|
504
|
+
entryPointAddress: entryPoint.address,
|
|
505
|
+
key
|
|
506
|
+
});
|
|
507
|
+
},
|
|
508
|
+
async getStubSignature() {
|
|
509
|
+
return DUMMY_ECDSA_SIG;
|
|
510
|
+
},
|
|
511
|
+
// Sign a user operation
|
|
512
|
+
async signUserOperation(parameters) {
|
|
513
|
+
const { chainId: chainId2 = await getMemoizedChainId(), ...userOperation } = parameters;
|
|
514
|
+
const hash = getUserOperationHash2({
|
|
515
|
+
userOperation: {
|
|
516
|
+
...userOperation,
|
|
517
|
+
sender: userOperation.sender ?? accountAddress,
|
|
518
|
+
signature: "0x"
|
|
519
|
+
},
|
|
520
|
+
entryPointAddress: entryPoint.address,
|
|
521
|
+
entryPointVersion: entryPoint.version,
|
|
522
|
+
chainId: chainId2
|
|
523
|
+
});
|
|
524
|
+
const signature = await signMessage2(client, {
|
|
525
|
+
account: viemSigner,
|
|
526
|
+
message: { raw: hash }
|
|
527
|
+
});
|
|
528
|
+
return signature;
|
|
529
|
+
}
|
|
530
|
+
});
|
|
531
|
+
}
|
|
532
|
+
var getNonceKeyWithEncoding = (validatorAddress, nonceKey = 0n) => {
|
|
533
|
+
if (nonceKey > maxUint16)
|
|
534
|
+
throw new Error("nonce key must be equal or less than 2 bytes(maxUint16) for Kernel version v0.7");
|
|
535
|
+
const validatorMode = VALIDATOR_MODE.DEFAULT;
|
|
536
|
+
const validatorType = VALIDATOR_TYPE.SUDO;
|
|
537
|
+
const encoding = pad(concatHex2([
|
|
538
|
+
validatorMode,
|
|
539
|
+
// 1 byte
|
|
540
|
+
validatorType,
|
|
541
|
+
// 1 byte
|
|
542
|
+
validatorAddress,
|
|
543
|
+
// 20 bytes
|
|
544
|
+
toHex2(nonceKey, { size: 2 })
|
|
545
|
+
// 2 byte
|
|
546
|
+
]), { size: 24 });
|
|
547
|
+
return BigInt(encoding);
|
|
548
|
+
};
|
|
549
|
+
|
|
550
|
+
// ../../node_modules/@zerodev/ecdsa-validator/_esm/clients/kernel7702AccountClient.js
|
|
551
|
+
import { prepareUserOperation as viemPrepareUserOperation } from "viem/account-abstraction";
|
|
552
|
+
function create7702KernelAccountClient(parameters) {
|
|
553
|
+
return createKernelAccountClient({
|
|
554
|
+
...parameters,
|
|
555
|
+
account: parameters.account,
|
|
556
|
+
userOperation: {
|
|
557
|
+
...parameters.userOperation,
|
|
558
|
+
prepareUserOperation: async (opClient, opArgs) => {
|
|
559
|
+
const authorization = opArgs.authorization || await parameters.account.signAuthorization();
|
|
560
|
+
const finalArgs = {
|
|
561
|
+
...opArgs,
|
|
562
|
+
authorization
|
|
563
|
+
};
|
|
564
|
+
return await viemPrepareUserOperation(opClient, finalArgs);
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
});
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
// ../../node_modules/@zerodev/ecdsa-validator/_esm/account/create7702KernelAccount.js
|
|
571
|
+
import { concatHex as concatHex3, createNonceManager as createNonceManager2, getTypesForEIP712Domain as getTypesForEIP712Domain2, hashMessage as hashMessage2, hashTypedData as hashTypedData2, isAddressEqual as isAddressEqual2, validateTypedData as validateTypedData2, zeroAddress as zeroAddress4 } from "viem";
|
|
572
|
+
import { entryPoint06Abi as entryPoint06Abi2, entryPoint07Abi as entryPoint07Abi2, entryPoint07Address as entryPoint07Address2, toSmartAccount as toSmartAccount2 } from "viem/account-abstraction";
|
|
573
|
+
import { getChainId as getChainId3, getCode, signAuthorization as signAuthorizationAction } from "viem/actions";
|
|
574
|
+
import { getAction as getAction2, verifyAuthorization } from "viem/utils";
|
|
575
|
+
var getDefaultAddresses = (entryPointVersion, kernelVersion, { accountImplementationAddress, factoryAddress, metaFactoryAddress }) => {
|
|
576
|
+
validateKernelVersionWithEntryPoint(entryPointVersion, kernelVersion);
|
|
577
|
+
const addresses = KernelVersionToAddressesMap[kernelVersion];
|
|
578
|
+
if (!addresses) {
|
|
579
|
+
throw new Error(`No addresses found for kernel version ${kernelVersion}`);
|
|
580
|
+
}
|
|
581
|
+
return {
|
|
582
|
+
accountImplementationAddress: accountImplementationAddress ?? addresses.accountImplementationAddress,
|
|
583
|
+
factoryAddress: factoryAddress ?? addresses.factoryAddress,
|
|
584
|
+
metaFactoryAddress: metaFactoryAddress ?? addresses.metaFactoryAddress ?? zeroAddress4
|
|
585
|
+
};
|
|
586
|
+
};
|
|
587
|
+
async function create7702KernelAccount(client, { signer, plugins, entryPoint, accountImplementationAddress: _accountImplementationAddress, kernelVersion, pluginMigrations, eip7702Auth }) {
|
|
588
|
+
const { accountImplementationAddress } = getDefaultAddresses(entryPoint.version, kernelVersion, {
|
|
589
|
+
accountImplementationAddress: _accountImplementationAddress,
|
|
590
|
+
factoryAddress: void 0,
|
|
591
|
+
metaFactoryAddress: void 0
|
|
592
|
+
});
|
|
593
|
+
let chainId;
|
|
594
|
+
let address;
|
|
595
|
+
if (typeof signer === "object" && signer !== null && "account" in signer) {
|
|
596
|
+
address = signer.account?.address;
|
|
597
|
+
}
|
|
598
|
+
const localAccount = await toSigner({ signer, address });
|
|
599
|
+
const accountAddress = localAccount.address;
|
|
600
|
+
const getMemoizedChainId = async () => {
|
|
601
|
+
if (chainId)
|
|
602
|
+
return chainId;
|
|
603
|
+
chainId = client.chain ? client.chain.id : await getAction2(client, getChainId3, "getChainId")({});
|
|
604
|
+
return chainId;
|
|
605
|
+
};
|
|
606
|
+
const kernelPluginManager = await toKernelPluginManager(client, {
|
|
607
|
+
sudo: await signerToEcdsaValidator(client, {
|
|
608
|
+
signer: localAccount,
|
|
609
|
+
entryPoint,
|
|
610
|
+
kernelVersion
|
|
611
|
+
}),
|
|
612
|
+
entryPoint,
|
|
613
|
+
kernelVersion,
|
|
614
|
+
chainId: await getMemoizedChainId()
|
|
615
|
+
});
|
|
616
|
+
const generateInitCode = async () => {
|
|
617
|
+
return "0x";
|
|
618
|
+
};
|
|
619
|
+
const getFactoryArgs = async () => {
|
|
620
|
+
return {
|
|
621
|
+
factory: void 0,
|
|
622
|
+
factoryData: void 0
|
|
623
|
+
};
|
|
624
|
+
};
|
|
625
|
+
const signAuthorization = async () => {
|
|
626
|
+
const code = await getCode(client, { address: accountAddress });
|
|
627
|
+
if (!code || code.length === 0 || !code.toLowerCase().startsWith(`0xef0100${accountImplementationAddress.slice(2).toLowerCase()}`)) {
|
|
628
|
+
if (eip7702Auth && !isAddressEqual2(eip7702Auth.address, accountImplementationAddress)) {
|
|
629
|
+
throw new Error("EIP-7702 authorization delegate address does not match account implementation address");
|
|
630
|
+
}
|
|
631
|
+
const auth = eip7702Auth ?? await signAuthorizationAction(client, {
|
|
632
|
+
account: localAccount,
|
|
633
|
+
address: accountImplementationAddress,
|
|
634
|
+
chainId: await getMemoizedChainId()
|
|
635
|
+
});
|
|
636
|
+
const verified = await verifyAuthorization({
|
|
637
|
+
authorization: auth,
|
|
638
|
+
address: accountAddress
|
|
639
|
+
});
|
|
640
|
+
if (!verified) {
|
|
641
|
+
throw new Error("Authorization verification failed");
|
|
642
|
+
}
|
|
643
|
+
return auth;
|
|
644
|
+
}
|
|
645
|
+
return void 0;
|
|
646
|
+
};
|
|
647
|
+
const _entryPoint = {
|
|
648
|
+
address: entryPoint?.address ?? entryPoint07Address2,
|
|
649
|
+
abi: (entryPoint?.version ?? "0.7") === "0.6" ? entryPoint06Abi2 : entryPoint07Abi2,
|
|
650
|
+
version: entryPoint?.version ?? "0.7"
|
|
651
|
+
};
|
|
652
|
+
const pluginCache = {
|
|
653
|
+
pendingPlugins: pluginMigrations || [],
|
|
654
|
+
allInstalled: false
|
|
655
|
+
};
|
|
656
|
+
const checkPluginInstallationStatus = async () => {
|
|
657
|
+
if (!pluginCache.pendingPlugins.length || pluginCache.allInstalled) {
|
|
658
|
+
pluginCache.allInstalled = true;
|
|
659
|
+
return;
|
|
660
|
+
}
|
|
661
|
+
const installationResults = await Promise.all(pluginCache.pendingPlugins.map((plugin) => isPluginInstalled(client, {
|
|
662
|
+
address: accountAddress,
|
|
663
|
+
plugin
|
|
664
|
+
})));
|
|
665
|
+
pluginCache.pendingPlugins = pluginCache.pendingPlugins.filter((_, index) => !installationResults[index]);
|
|
666
|
+
pluginCache.allInstalled = pluginCache.pendingPlugins.length === 0;
|
|
667
|
+
};
|
|
668
|
+
await checkPluginInstallationStatus();
|
|
669
|
+
return toSmartAccount2({
|
|
670
|
+
kernelVersion,
|
|
671
|
+
kernelPluginManager,
|
|
672
|
+
accountImplementationAddress,
|
|
673
|
+
factoryAddress: void 0,
|
|
674
|
+
generateInitCode,
|
|
675
|
+
encodeModuleInstallCallData: async () => {
|
|
676
|
+
return await kernelPluginManager.encodeModuleInstallCallData(accountAddress);
|
|
677
|
+
},
|
|
678
|
+
nonceKeyManager: createNonceManager2({
|
|
679
|
+
source: { get: () => 0, set: () => {
|
|
680
|
+
} }
|
|
681
|
+
}),
|
|
682
|
+
client,
|
|
683
|
+
entryPoint: _entryPoint,
|
|
684
|
+
getFactoryArgs,
|
|
685
|
+
async getAddress() {
|
|
686
|
+
return accountAddress;
|
|
687
|
+
},
|
|
688
|
+
signAuthorization,
|
|
689
|
+
// Encode the deploy call data
|
|
690
|
+
async encodeDeployCallData(_tx) {
|
|
691
|
+
if (entryPoint.version === "0.6") {
|
|
692
|
+
return encodeDeployCallData(_tx);
|
|
693
|
+
}
|
|
694
|
+
return encodeDeployCallData2(_tx);
|
|
695
|
+
},
|
|
696
|
+
async encodeCalls(calls, callType) {
|
|
697
|
+
await checkPluginInstallationStatus();
|
|
698
|
+
if (pluginCache.pendingPlugins.length > 0 && entryPoint.version === "0.7" && kernelPluginManager.activeValidatorMode === "sudo") {
|
|
699
|
+
const pluginInstallCalls = [];
|
|
700
|
+
for (const plugin of pluginCache.pendingPlugins) {
|
|
701
|
+
pluginInstallCalls.push(getPluginInstallCallData(accountAddress, plugin));
|
|
702
|
+
}
|
|
703
|
+
return encodeCallData2([...calls, ...pluginInstallCalls], callType, plugins?.hook ? true : void 0);
|
|
704
|
+
}
|
|
705
|
+
if (calls.length === 1 && (!callType || callType === "call") && calls[0].to.toLowerCase() === accountAddress.toLowerCase()) {
|
|
706
|
+
return calls[0].data ?? "0x";
|
|
707
|
+
}
|
|
708
|
+
if (entryPoint.version === "0.6") {
|
|
709
|
+
return encodeCallData(calls, callType);
|
|
710
|
+
}
|
|
711
|
+
if (plugins?.hook) {
|
|
712
|
+
return encodeCallData2(calls, callType, true);
|
|
713
|
+
}
|
|
714
|
+
return encodeCallData2(calls, callType);
|
|
715
|
+
},
|
|
716
|
+
async sign({ hash }) {
|
|
717
|
+
return this.signMessage({ message: hash });
|
|
718
|
+
},
|
|
719
|
+
async signMessage({ message, useReplayableSignature }) {
|
|
720
|
+
const messageHash = hashMessage2(message);
|
|
721
|
+
const { name, chainId: metadataChainId, version } = await accountMetadata(client, accountAddress, kernelVersion, chainId);
|
|
722
|
+
const wrappedMessageHash = await eip712WrapHash(messageHash, {
|
|
723
|
+
name,
|
|
724
|
+
chainId: Number(metadataChainId),
|
|
725
|
+
version,
|
|
726
|
+
verifyingContract: accountAddress
|
|
727
|
+
}, useReplayableSignature);
|
|
728
|
+
let signature = await kernelPluginManager.signMessage({
|
|
729
|
+
message: { raw: wrappedMessageHash }
|
|
730
|
+
});
|
|
731
|
+
if (!hasKernelFeature(KERNEL_FEATURES.ERC1271_WITH_VALIDATOR, version)) {
|
|
732
|
+
return signature;
|
|
733
|
+
}
|
|
734
|
+
if (useReplayableSignature && hasKernelFeature(KERNEL_FEATURES.ERC1271_REPLAYABLE, version)) {
|
|
735
|
+
signature = concatHex3([MAGIC_VALUE_SIG_REPLAYABLE, signature]);
|
|
736
|
+
}
|
|
737
|
+
return concatHex3([kernelPluginManager.getIdentifier(), signature]);
|
|
738
|
+
},
|
|
739
|
+
async signTypedData(typedData) {
|
|
740
|
+
const { message, primaryType, types: _types, domain } = typedData;
|
|
741
|
+
const types = {
|
|
742
|
+
EIP712Domain: getTypesForEIP712Domain2({
|
|
743
|
+
domain
|
|
744
|
+
}),
|
|
745
|
+
..._types
|
|
746
|
+
};
|
|
747
|
+
validateTypedData2({
|
|
748
|
+
domain,
|
|
749
|
+
message,
|
|
750
|
+
primaryType,
|
|
751
|
+
types
|
|
752
|
+
});
|
|
753
|
+
const typedHash = hashTypedData2(typedData);
|
|
754
|
+
const { name, chainId: metadataChainId, version } = await accountMetadata(client, accountAddress, kernelVersion, chainId);
|
|
755
|
+
const wrappedMessageHash = await eip712WrapHash(typedHash, {
|
|
756
|
+
name,
|
|
757
|
+
chainId: Number(metadataChainId),
|
|
758
|
+
version,
|
|
759
|
+
verifyingContract: accountAddress
|
|
760
|
+
});
|
|
761
|
+
const signature = await kernelPluginManager.signMessage({
|
|
762
|
+
message: { raw: wrappedMessageHash }
|
|
763
|
+
});
|
|
764
|
+
if (!hasKernelFeature(KERNEL_FEATURES.ERC1271_WITH_VALIDATOR, version)) {
|
|
765
|
+
return signature;
|
|
766
|
+
}
|
|
767
|
+
return concatHex3([kernelPluginManager.getIdentifier(), signature]);
|
|
768
|
+
},
|
|
769
|
+
// Get the nonce of the smart account
|
|
770
|
+
async getNonce(_args) {
|
|
771
|
+
const key = await kernelPluginManager.getNonceKey(accountAddress, _args?.key);
|
|
772
|
+
return getAccountNonce(client, {
|
|
773
|
+
address: accountAddress,
|
|
774
|
+
entryPointAddress: entryPoint.address,
|
|
775
|
+
key
|
|
776
|
+
});
|
|
777
|
+
},
|
|
778
|
+
async getStubSignature(userOperation) {
|
|
779
|
+
if (!userOperation) {
|
|
780
|
+
throw new Error("No user operation provided");
|
|
781
|
+
}
|
|
782
|
+
return kernelPluginManager.getStubSignature(userOperation);
|
|
783
|
+
},
|
|
784
|
+
// Sign a user operation
|
|
785
|
+
async signUserOperation(parameters) {
|
|
786
|
+
const { chainId: chainId2 = await getMemoizedChainId(), ...userOperation } = parameters;
|
|
787
|
+
return kernelPluginManager.signUserOperation({
|
|
788
|
+
...userOperation,
|
|
789
|
+
sender: userOperation.sender ?? await this.getAddress(),
|
|
790
|
+
chainId: chainId2
|
|
791
|
+
//authorization
|
|
792
|
+
});
|
|
793
|
+
}
|
|
794
|
+
});
|
|
795
|
+
}
|
|
796
|
+
export {
|
|
797
|
+
create7702KernelAccount,
|
|
798
|
+
create7702KernelAccountClient,
|
|
799
|
+
createEcdsaKernelMigrationAccount,
|
|
800
|
+
getKernelAddressFromECDSA,
|
|
801
|
+
getValidatorAddress,
|
|
802
|
+
kernelVersionRangeToValidator,
|
|
803
|
+
signerToEcdsaValidator
|
|
804
|
+
};
|