@kiroboio/fct-core
Version:
Kirobo.io FCT Core library
212 lines • 8.19 kB
JavaScript
import { TypedDataUtils } from "@metamask/eth-sig-util";
import { hexlify, id } from "ethers/lib/utils";
import { CALL_TYPE_MSG, EMPTY_HASH } from "../../../constants";
import { flows } from "../../../constants/flows";
import { EIP712 } from "../../classes";
export const EIP712Domain = [
{ name: "name", type: "string" },
{ name: "version", type: "string" },
{ name: "chainId", type: "uint256" },
{ name: "verifyingContract", type: "address" },
{ name: "salt", type: "bytes32" },
];
// Meta(string name,string app,string app_version,string builder,address builder_address,string domain)
export const Meta = [
{ name: "name", type: "string" },
{ name: "app", type: "string" },
{ name: "app_version", type: "string" },
{ name: "builder", type: "string" },
{ name: "builder_address", type: "address" },
{ name: "domain", type: "string" },
];
// Engine(bytes4 selector,bytes3 version,bytes3 random_id,bool eip712,string verifier,bool auth_enabled,bool dry_run)
export const Engine = [
{ name: "selector", type: "bytes4" },
{ name: "version", type: "bytes3" },
{ name: "random_id", type: "bytes3" },
{ name: "eip712", type: "bool" },
{ name: "verifier", type: "string" },
{ name: "auth_enabled", type: "bool" },
{ name: "dry_run", type: "bool" },
];
export const Limits = [
{ name: "valid_from", type: "uint40" },
{ name: "expires_at", type: "uint40" },
{ name: "gas_price_limit", type: "uint64" },
{ name: "purgeable", type: "bool" },
{ name: "blockable", type: "bool" },
];
export const Computed = [
{ name: "index", type: "uint256" },
{ name: "value_1", type: "uint256" },
{ name: "op_1", type: "string" },
{ name: "value_2", type: "uint256" },
{ name: "op_2", type: "string" },
{ name: "value_3", type: "uint256" },
{ name: "op_3", type: "string" },
{ name: "value_4", type: "uint256" },
{ name: "overflow_protection", type: "bool" },
];
export const Call = [
{ name: "call_index", type: "uint16" },
{ name: "payer_index", type: "uint16" },
{ name: "call_type", type: "string" },
{ name: "from", type: "address" },
{ name: "to", type: "address" },
{ name: "to_ens", type: "string" },
{ name: "value", type: "uint256" },
{ name: "gas_limit", type: "uint32" },
{ name: "permissions", type: "uint16" },
{ name: "validation", type: "uint16" },
{ name: "flow_control", type: "string" },
{ name: "returned_false_means_fail", type: "bool" },
{ name: "jump_on_success", type: "uint16" },
{ name: "jump_on_fail", type: "uint16" },
{ name: "method_interface", type: "string" },
];
export const Recurrency = [
{ name: "max_repeats", type: "uint16" },
{ name: "chill_time", type: "uint32" },
{ name: "accumetable", type: "bool" },
];
export const Multisig = [
{ name: "external_signers", type: "address[]" },
{ name: "minimum_approvals", type: "uint8" },
];
export const Validation = [
{ name: "index", type: "uint256" },
{ name: "value_1", type: "uint256" },
{ name: "op", type: "string" },
{ name: "value_2", type: "uint256" },
];
export class VersionBase {
FCT;
constructor(FCT) {
this.FCT = FCT;
}
EIP712Domain = EIP712Domain;
Meta = Meta;
Engine = Engine;
Limits = Limits;
Computed = Computed;
Call = Call;
Recurrency = Recurrency;
Multisig = Multisig;
Validation = Validation;
getMetaMessage(FCT) {
const FCTOptions = FCT.options;
return {
name: FCTOptions.name || "",
app: FCTOptions.app.name || "",
app_version: FCTOptions.app.version || "",
builder: FCTOptions.builder.name || "",
builder_address: FCTOptions.builder.address || "",
domain: FCTOptions.domain || "",
};
}
getEngineMessage(FCT) {
const FCTOptions = FCT.options;
return {
selector: this.batchMultiSigSelector,
version: FCT.version,
random_id: `0x${FCT.randomId}`,
eip712: true,
verifier: FCTOptions.verifier,
auth_enabled: FCTOptions.authEnabled,
dry_run: FCTOptions.dryRun,
};
}
getLimitsMessage(FCT) {
const FCTOptions = FCT.options;
return {
valid_from: FCTOptions.validFrom,
expires_at: FCTOptions.expiresAt,
gas_price_limit: FCTOptions.maxGasPrice,
purgeable: FCTOptions.purgeable,
blockable: FCTOptions.blockable,
};
}
exportFCT() {
const FCT = this.FCT;
if (!FCT) {
throw new Error("FCT is not defined, this should not happen");
}
if (FCT.calls.length === 0) {
throw new Error("No calls added to FCT");
}
const options = FCT.options;
const typedData = new EIP712(FCT).getTypedData();
return {
typedData,
typeHash: hexlify(TypedDataUtils.hashType(typedData.primaryType, typedData.types)),
sessionId: this.SessionId.asString(),
nameHash: id(options.name),
appHash: id(options.app.name),
appVersionHash: id(options.app.version),
builderHash: id(options.builder.name),
builderAddress: options.builder.address,
domainHash: id(options.domain),
verifierHash: id(options.verifier),
mcall: FCT.calls.map((call, index) => call.getAsMCall(typedData, index)),
externalSigners: options.multisig.externalSigners,
signatures: [FCT.utils.getAuthenticatorSignature()],
computed: FCT.computedAsData,
validations: FCT.validation.getForData(),
variables: [],
};
}
getCallAsMcall(call, typedData, index) {
const FCT = this.FCT;
if (!FCT) {
throw new Error("FCT is not defined, this should not happen");
}
const callFull = call.get();
return {
typeHash: hexlify(TypedDataUtils.hashType(`transaction${index + 1}`, typedData.types)),
ensHash: callFull.toENS ? id(callFull.toENS) : EMPTY_HASH,
functionSignature: call.getFunctionSignature(),
value: FCT.variables.getValue(callFull.value, "uint256", "0"),
callId: this.CallId.asString({
calls: FCT.calls,
validation: FCT.validation,
call,
callFull,
index,
payerIndex: call.options.payerIndex,
}),
from: FCT.variables.getValue(callFull.from, "address"),
to: FCT.variables.getValue(callFull.to, "address"),
data: call.getEncodedData(),
types: call.getTypesArray(),
typedHashes: call.getTypedHashes(index),
};
}
generateCallForEIP712Message(call, index) {
const FCT = this.FCT;
if (!FCT) {
throw new Error("FCT is not defined, this should not happen");
}
const callData = call.get();
const options = call.options;
const flow = flows[options.flow].text;
const { jumpOnSuccess, jumpOnFail } = call.getJumps(index);
return {
call_index: index + 1,
payer_index: typeof call.options.payerIndex === "number" ? call.options.payerIndex : index + 1,
call_type: CALL_TYPE_MSG[call.options.callType],
from: FCT.variables.getValue(callData.from, "address"),
to: FCT.variables.getValue(callData.to, "address"),
to_ens: callData.toENS || "",
value: FCT.variables.getValue(callData.value, "uint256", "0"),
gas_limit: options.gasLimit,
permissions: 0,
validation: call.options.validation ? FCT.validation.getIndex(call.options.validation) : 0,
flow_control: flow,
returned_false_means_fail: options.falseMeansFail,
jump_on_success: jumpOnSuccess,
jump_on_fail: jumpOnFail,
method_interface: call.getFunction(),
};
}
}
//# sourceMappingURL=VersionBase.js.map