@metamask/delegation-toolkit
Version:
The Delegation Toolkit built on top of Viem - a library for interacting with DeleGator Smart Accounts
308 lines (302 loc) • 9.23 kB
JavaScript
import {
encode,
encode2,
encode3,
encode4,
encode5,
encodeProxyCreationCode
} from "./chunk-MOTJRLZE.mjs";
import {
createExecution,
encodeExecutionCalldatas
} from "./chunk-CPLIK3VF.mjs";
// src/constants.ts
var Implementation = /* @__PURE__ */ ((Implementation2) => {
Implementation2["MultiSig"] = "MultiSig";
Implementation2["Hybrid"] = "Hybrid";
Implementation2["Stateless7702"] = "Stateless7702";
return Implementation2;
})(Implementation || {});
// src/counterfactualAccountData.ts
import { getContractAddress, pad } from "viem";
var getCounterfactualAccountData = async ({
factory,
implementations,
implementation,
deployParams,
deploySalt
}) => {
let implementationAddress;
let initcode;
switch (implementation) {
case "Hybrid" /* Hybrid */: {
const [owner, keyIds, xValues, yValues] = deployParams;
if (!implementations.HybridDeleGatorImpl) {
throw new Error(
"HybridDeleGatorImpl address not provided in environment"
);
}
implementationAddress = implementations.HybridDeleGatorImpl;
const p256Owners = keyIds.map((keyId, index) => {
const xValue = xValues[index];
const yValue = yValues[index];
if (!xValue || !yValue) {
throw new Error(
`Missing X or Y value for keyId ${keyId} at index ${index}`
);
}
return {
keyId,
x: xValue,
y: yValue
};
});
initcode = encode({ eoaOwner: owner, p256Owners });
break;
}
case "MultiSig" /* MultiSig */: {
const [owners, threshold] = deployParams;
if (!implementations.MultiSigDeleGatorImpl) {
throw new Error(
"MultiSigDeleGatorImpl address not provided in environment"
);
}
implementationAddress = implementations.MultiSigDeleGatorImpl;
initcode = encode2({ owners, threshold });
break;
}
default:
throw new Error(`Implementation type '${implementation}' not supported`);
}
const salt = pad(deploySalt, { dir: "left", size: 32 });
const proxyCreationCode = encodeProxyCreationCode({
implementationAddress,
initcode
});
const address = getContractAddress({
bytecode: proxyCreationCode,
from: factory,
opcode: "CREATE2",
salt
});
const factoryData = encode3(proxyCreationCode, salt);
return {
factoryData,
address
};
};
// src/encodeCalls.ts
import { DelegationManager } from "@metamask/delegation-abis";
import { encodeFunctionData } from "viem";
var isDelegatedCall = (call) => {
return "permissionsContext" in call && "delegationManager" in call;
};
var processDelegatedCall = (call) => {
const {
permissionsContext,
delegationManager,
to: target,
value,
data: callData
} = call;
const callAsExecution = createExecution({ target, value, callData });
if (!permissionsContext) {
return callAsExecution;
}
const redeemCalldata = encodeFunctionData({
abi: DelegationManager.abi,
functionName: "redeemDelegations",
args: [
[permissionsContext],
["0x0000000000000000000000000000000000000000000000000000000000000000" /* SingleDefault */],
encodeExecutionCalldatas([[callAsExecution]])
]
});
return createExecution({
target: delegationManager,
callData: redeemCalldata
});
};
var encodeCalls = (calls) => {
if (calls.length === 1) {
const call = calls[0];
if (call && !isDelegatedCall(call)) {
const { to: target, value, data: callData } = call;
const execution = createExecution({ target, value, callData });
return encode4({ execution });
}
}
const executions = calls.map((call) => {
if (isDelegatedCall(call)) {
return processDelegatedCall(call);
}
const { to: target, value, data: callData } = call;
return createExecution({ target, value, callData });
});
const mode = calls.length === 1 ? "0x0000000000000000000000000000000000000000000000000000000000000000" /* SingleDefault */ : "0x0100000000000000000000000000000000000000000000000000000000000000" /* BatchDefault */;
return encode5({ mode, executions });
};
var encodeCallsForCaller = async (caller, calls) => {
if (calls.length === 1) {
const call = calls[0];
if (call && call.to === caller && !isDelegatedCall(call)) {
return call.data ?? "0x";
}
}
return encodeCalls(calls);
};
// src/webAuthn.ts
import {
parseAbiParameters,
encodeAbiParameters,
encodePacked,
keccak256,
concat
} from "viem";
import { parseSignature } from "webauthn-p256";
var FIELD_MODULUS = 115792089210356248762697446949407573529996955224135760342422259061068512044369n;
var MALLEABILITY_THRESHOLD = FIELD_MODULUS / 2n;
var SIGNATURE_ABI_PARAMS = parseAbiParameters(
"bytes32, uint256, uint256, bytes, bool, string, string, uint256"
);
var splitOnChallenge = (clientDataJson) => {
try {
const { challenge } = JSON.parse(clientDataJson);
if (challenge === void 0) {
throw new Error('No "challenge" found in the input string');
}
return clientDataJson.split(challenge);
} catch (error) {
throw new Error('No "challenge" found in the input string', {
cause: error
});
}
};
var getResponseTypeLocation = (clientDataJson) => {
try {
const typeIndex = clientDataJson.indexOf('"type":');
if (typeIndex === -1) {
throw new Error('No "type" found in the input string');
}
return BigInt(typeIndex);
} catch (error) {
throw new Error('No "type" found in the input string', {
cause: error
});
}
};
function encodeDeleGatorSignature(keyId, signature, clientDataJSON, authenticatorData) {
const keyIdHash = keccak256(encodePacked(["string"], [keyId]));
const parsedSignature = parseSignature(signature);
let { s } = parsedSignature;
while (s > MALLEABILITY_THRESHOLD) {
s = FIELD_MODULUS - s;
}
const { r } = parsedSignature;
const [clientDataComponent1, clientDataComponent2] = splitOnChallenge(clientDataJSON);
const { userVerified } = parseAuthenticatorFlags(authenticatorData);
const responseTypeLocation = getResponseTypeLocation(clientDataJSON);
const encodedSignature = encodeAbiParameters(SIGNATURE_ABI_PARAMS, [
keyIdHash,
r,
s,
authenticatorData,
userVerified,
clientDataComponent1,
clientDataComponent2,
responseTypeLocation
]);
return encodedSignature;
}
var AUTHENTICATOR_DATA_FLAGS_OFFSET = 32;
function parseAuthenticatorFlags(authenticatorData) {
const authenticatorDataBuffer = Buffer.from(
authenticatorData.slice(2),
"hex"
);
const flags = authenticatorDataBuffer.readUInt8(
AUTHENTICATOR_DATA_FLAGS_OFFSET
);
const bitMask = 1 << 2 /* UserVerified */;
return {
// eslint-disable-next-line no-bitwise
userVerified: (flags & bitMask) !== 0
};
}
var createDummyWebAuthnSignature = (keyId) => {
const rpIdHash = keccak256(encodePacked(["string"], ["AuthenticatorData"]));
const flags = "0x05";
const signCount = "0x00000000";
const authenticatorData = concat([rpIdHash, flags, signCount]);
const keyIdHash = keccak256(encodePacked(["string"], [keyId]));
const rs = 57896044605178124381348723474703786764998477612067880171211129530534256022184n;
const userVerification = true;
const clientDataPrefix = '{"type":"webauthn.get","challenge":"';
const clientDataSuffix = '","origin":"passkey-domain","crossOrigin":false}';
const responseTypeLocation = 1n;
const encodedSignature = encodeAbiParameters(SIGNATURE_ABI_PARAMS, [
keyIdHash,
rs,
rs,
authenticatorData,
userVerification,
clientDataPrefix,
clientDataSuffix,
responseTypeLocation
]);
return encodedSignature;
};
// src/userOp.ts
import { concat as concat2, encodeAbiParameters as encodeAbiParameters2, keccak256 as keccak2562, pad as pad2, toHex } from "viem";
import { toPackedUserOperation } from "viem/account-abstraction";
var SIGNABLE_USER_OP_TYPED_DATA = {
PackedUserOperation: [
{ name: "sender", type: "address" },
{ name: "nonce", type: "uint256" },
{ name: "initCode", type: "bytes" },
{ name: "callData", type: "bytes" },
{ name: "accountGasLimits", type: "bytes32" },
{ name: "preVerificationGas", type: "uint256" },
{ name: "gasFees", type: "bytes32" },
{ name: "paymasterAndData", type: "bytes" },
{ name: "entryPoint", type: "address" }
]
};
var signUserOperation = async ({
signer,
userOperation,
entryPoint,
chainId,
name,
address,
version = "1"
}) => {
const packedUserOp = toPackedUserOperation({
...userOperation,
signature: "0x"
});
return signer.signTypedData({
account: signer.account,
domain: {
chainId,
name,
version,
verifyingContract: address
},
types: SIGNABLE_USER_OP_TYPED_DATA,
primaryType: "PackedUserOperation",
message: { ...packedUserOp, entryPoint: entryPoint.address }
});
};
export {
Implementation,
getCounterfactualAccountData,
encodeCalls,
encodeCallsForCaller,
SIGNATURE_ABI_PARAMS,
encodeDeleGatorSignature,
createDummyWebAuthnSignature,
SIGNABLE_USER_OP_TYPED_DATA,
signUserOperation
};
//# sourceMappingURL=chunk-GODU24FS.mjs.map