@safe-global/protocol-kit
Version:
SDK that facilitates the interaction with Safe Smart Accounts
1,337 lines (1,321 loc) • 176 kB
JavaScript
// test-utils/webauthnShim.ts
import { p256 } from "@noble/curves/p256";
import { ethers } from "ethers";
import CBOR from "cbor";
function base64UrlEncode(data) {
const buffer = typeof data === "string" ? Buffer.from(data.replace(/^0x/, ""), "hex") : Buffer.from(data);
return buffer.toString("base64url");
}
function userVerificationFlag(userVerification = "preferred") {
switch (userVerification) {
case "preferred":
return 1;
case "required":
return 4;
default:
throw new Error(`user verification requirement ${userVerification} not supported`);
}
}
function b2ab(buf) {
return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength);
}
function isEqualArray(a, b) {
if (a.length != b.length) return false;
for (let i = 0; i < a.length; i++) if (a[i] != b[i]) return false;
return true;
}
function encodeWebAuthnSigningMessage(clientData, authenticatorData) {
return ethers.getBytes(
ethers.concat([
authenticatorData,
ethers.sha256(ethers.toUtf8Bytes(JSON.stringify(clientData)))
])
);
}
var Credential = class {
constructor(rp, user, pk) {
this.rp = rp;
this.user = user;
this.pk = pk || p256.utils.normPrivateKeyToScalar(p256.utils.randomPrivateKey());
this.id = ethers.dataSlice(
ethers.keccak256(ethers.dataSlice(p256.getPublicKey(this.pk, false), 1)),
12
);
this.rawId = ethers.getBytes(this.id);
}
/**
* Computes the COSE encoded public key for this credential.
* See <https://datatracker.ietf.org/doc/html/rfc8152>.
*
* @returns Hex-encoded COSE-encoded public key
*/
cosePublicKey() {
const pubk = p256.getPublicKey(this.pk, false);
const x = pubk.subarray(1, 33);
const y = pubk.subarray(33, 65);
const key = /* @__PURE__ */ new Map();
key.set(-1, 1);
key.set(-2, b2ab(x));
key.set(-3, b2ab(y));
key.set(1, 2);
key.set(3, -7);
return ethers.hexlify(CBOR.encode(key));
}
};
var WebAuthnCredentials = class {
/**
* Creates a new instance of the WebAuthn credentials.
* @param privateKey The private key to use for the credentials. If not provided, a random key will be generated.
*/
constructor(privateKey) {
this.privateKey = privateKey;
this.credentials = [];
}
/**
* This is a shim for `navigator.credentials.create` method.
* See <https://w3c.github.io/webappsec-credential-management/#dom-credentialscontainer-create>.
*
* @param options The public key credential creation options.
* @returns A public key credential with an attestation response.
*/
create({
publicKey
}) {
if (!publicKey.pubKeyCredParams.some(({ alg }) => alg === -7)) {
throw new Error("unsupported signature algorithm(s)");
}
const credential = new Credential(publicKey.rp.id, publicKey.user.id, this.privateKey);
this.credentials.push(credential);
const clientData = {
type: "webauthn.create",
challenge: base64UrlEncode(publicKey.challenge),
origin: `https://${publicKey.rp.id}`
};
const attestationObject = {
authData: b2ab(
ethers.getBytes(
ethers.solidityPacked(
["bytes32", "uint8", "uint32", "bytes16", "uint16", "bytes", "bytes"],
[
ethers.sha256(ethers.toUtf8Bytes(publicKey.rp.id)),
64 + userVerificationFlag(publicKey.userVerification),
// flags = attested_data + user_present
0,
// signCount
`0x${"42".repeat(16)}`,
// aaguid
ethers.dataLength(credential.id),
credential.id,
credential.cosePublicKey()
]
)
)
),
fmt: "none",
attStmt: {}
};
return {
id: base64UrlEncode(credential.rawId),
rawId: credential.rawId.slice(),
response: {
clientDataJSON: b2ab(ethers.toUtf8Bytes(JSON.stringify(clientData))),
attestationObject: b2ab(CBOR.encode(attestationObject)),
getPublicKey: () => b2ab(p256.getPublicKey(credential.pk, false))
},
type: "public-key"
};
}
/**
* This is a shim for `navigator.credentials.get` method.
* See <https://w3c.github.io/webappsec-credential-management/#dom-credentialscontainer-get>.
*
* @param options The public key credential request options.
* @returns A public key credential with an assertion response.
*/
get({
publicKey
}) {
const credential = publicKey.allowCredentials.flatMap(({ id }) => this.credentials.filter((c) => isEqualArray(c.rawId, id))).at(0);
if (credential === void 0) {
throw new Error("credential not found");
}
const clientData = {
type: "webauthn.get",
challenge: base64UrlEncode(publicKey.challenge),
origin: `https://${credential.rp}`
};
const authenticatorData = ethers.solidityPacked(
["bytes32", "uint8", "uint32"],
[
ethers.sha256(ethers.toUtf8Bytes(credential.rp)),
userVerificationFlag(publicKey.userVerification),
// flags = user_present
0
// signCount
]
);
const message = encodeWebAuthnSigningMessage(clientData, authenticatorData);
const signature = p256.sign(message, credential.pk, {
lowS: false,
prehash: true
});
return {
id: base64UrlEncode(credential.rawId),
rawId: credential.rawId.slice(),
response: {
clientDataJSON: b2ab(ethers.toUtf8Bytes(JSON.stringify(clientData))),
authenticatorData: b2ab(ethers.getBytes(authenticatorData)),
signature: b2ab(signature.toDERRawBytes(false)),
userHandle: credential.user
},
type: "public-key"
};
}
};
// test-utils/passkeys.ts
import { keccak256 as keccak2563, toBytes as toBytes4 } from "viem";
// src/utils/types.ts
import { isHex, defineChain, etherUnits } from "viem";
import * as allChains from "viem/chains";
function asHash(hash) {
return hash;
}
function asHex(hex) {
return isHex(hex) ? hex : `0x${hex}`;
}
function getChainById(chainId) {
const chain = Object.values(allChains).find((chain2) => chain2.id === Number(chainId));
if (chain) {
return chain;
} else {
return defineChain({
id: Number(chainId),
name: "Custom",
nativeCurrency: {
decimals: etherUnits.wei,
name: "Ether",
symbol: "ETH"
},
rpcUrls: {
default: {
http: [],
webSocket: []
}
}
});
}
}
// src/utils/constants.ts
import { zeroAddress } from "viem";
var SENTINEL_ADDRESS = "0x0000000000000000000000000000000000000001";
// src/utils/address.ts
function sameString(str1, str2) {
return !!str1 && !!str2 && str1.toLowerCase() === str2.toLowerCase();
}
function isSentinelAddress(address) {
return sameString(address, SENTINEL_ADDRESS);
}
// src/utils/eip-3770/index.ts
import { isAddress } from "viem";
// src/utils/eip-3770/config.ts
var networks = [
{ chainId: 1n, shortName: "eth" },
{ chainId: 3n, shortName: "rop" },
{ chainId: 4n, shortName: "rin" },
{ chainId: 5n, shortName: "gor" },
{ chainId: 10n, shortName: "oeth" },
{ chainId: 11n, shortName: "meta" },
{ chainId: 12n, shortName: "kal" },
{ chainId: 14n, shortName: "flr" },
{ chainId: 16n, shortName: "cflr" },
{ chainId: 18n, shortName: "tst" },
{ chainId: 19n, shortName: "sgb" },
{ chainId: 25n, shortName: "cro" },
{ chainId: 28n, shortName: "bobarinkeby" },
{ chainId: 30n, shortName: "rsk" },
{ chainId: 31n, shortName: "trsk" },
{ chainId: 39n, shortName: "u2u" },
{ chainId: 40n, shortName: "telosevm" },
{ chainId: 41n, shortName: "telosevmtestnet" },
{ chainId: 42n, shortName: "lukso" },
{ chainId: 43n, shortName: "pangolin" },
{ chainId: 44n, shortName: "crab" },
{ chainId: 46n, shortName: "darwinia" },
{ chainId: 50n, shortName: "xdc" },
{ chainId: 51n, shortName: "txdc" },
{ chainId: 56n, shortName: "bnb" },
{ chainId: 57n, shortName: "sys" },
{ chainId: 61n, shortName: "etc" },
{ chainId: 63n, shortName: "metc" },
{ chainId: 69n, shortName: "okov" },
{ chainId: 71n, shortName: "cfxtest" },
{ chainId: 81n, shortName: "joc" },
{ chainId: 82n, shortName: "meter" },
{ chainId: 83n, shortName: "meter-test" },
{ chainId: 88n, shortName: "vic" },
{ chainId: 96n, shortName: "bkc" },
{ chainId: 97n, shortName: "bnbt" },
{ chainId: 98n, shortName: "six" },
{ chainId: 100n, shortName: "gno" },
{ chainId: 106n, shortName: "vlx" },
{ chainId: 108n, shortName: "tt" },
{ chainId: 109n, shortName: "shibariumecosystem" },
{ chainId: 111n, shortName: "etl" },
{ chainId: 114n, shortName: "c2flr" },
{ chainId: 122n, shortName: "fuse" },
{ chainId: 123n, shortName: "spark" },
{ chainId: 130n, shortName: "unichain" },
{ chainId: 133n, shortName: "HSKT" },
{ chainId: 137n, shortName: "matic" },
{ chainId: 143n, shortName: "mon" },
{ chainId: 146n, shortName: "sonic" },
{ chainId: 148n, shortName: "shimmerevm" },
{ chainId: 150n, shortName: "sixt" },
{ chainId: 151n, shortName: "rbn" },
{ chainId: 153n, shortName: "rbn-testnet" },
{ chainId: 155n, shortName: "tenet-testnet" },
{ chainId: 169n, shortName: "manta" },
{ chainId: 173n, shortName: "eni" },
{ chainId: 177n, shortName: "hsk" },
{ chainId: 179n, shortName: "abey" },
{ chainId: 181n, shortName: "water" },
{ chainId: 185n, shortName: "mint" },
{ chainId: 195n, shortName: "tokb" },
{ chainId: 196n, shortName: "okb" },
{ chainId: 204n, shortName: "opbnb" },
{ chainId: 228n, shortName: "fhe" },
{ chainId: 232n, shortName: "lens" },
{ chainId: 239n, shortName: "tacchain" },
{ chainId: 240n, shortName: "zkTCRO" },
{ chainId: 246n, shortName: "ewt" },
{ chainId: 250n, shortName: "ftm" },
{ chainId: 252n, shortName: "fraxtal" },
{ chainId: 255n, shortName: "kroma" },
{ chainId: 274n, shortName: "lachain" },
{ chainId: 280n, shortName: "zksync-goerli" },
{ chainId: 282n, shortName: "deprecated-zkTCRO" },
{ chainId: 288n, shortName: "boba" },
{ chainId: 291n, shortName: "orderly" },
{ chainId: 295n, shortName: "hedera-mainnet" },
{ chainId: 296n, shortName: "hedera-testnet" },
{ chainId: 300n, shortName: "zksync-sepolia" },
{ chainId: 314n, shortName: "filecoin" },
{ chainId: 321n, shortName: "kcs" },
{ chainId: 322n, shortName: "kcst" },
{ chainId: 324n, shortName: "zksync" },
{ chainId: 336n, shortName: "sdn" },
{ chainId: 338n, shortName: "tcro" },
{ chainId: 360n, shortName: "shape" },
{ chainId: 369n, shortName: "pls" },
{ chainId: 388n, shortName: "zkCRO" },
{ chainId: 418n, shortName: "latestnet" },
{ chainId: 420n, shortName: "ogor" },
{ chainId: 424n, shortName: "PGN" },
{ chainId: 466n, shortName: "appchain" },
{ chainId: 478n, shortName: "formnetwork" },
{ chainId: 480n, shortName: "wc" },
{ chainId: 530n, shortName: "pundiai" },
{ chainId: 545n, shortName: "flow-testnet" },
{ chainId: 570n, shortName: "sys-rollux" },
{ chainId: 588n, shortName: "metis-stardust" },
{ chainId: 592n, shortName: "astr" },
{ chainId: 595n, shortName: "maca" },
{ chainId: 599n, shortName: "metis-goerli" },
{ chainId: 648n, shortName: "ace" },
{ chainId: 686n, shortName: "kar" },
{ chainId: 690n, shortName: "redstone" },
{ chainId: 698n, shortName: "Matchain" },
{ chainId: 747n, shortName: "flow-mainnet" },
{ chainId: 756n, shortName: "capx-testnet" },
{ chainId: 757n, shortName: "capx" },
{ chainId: 787n, shortName: "aca" },
{ chainId: 841n, shortName: "tara" },
{ chainId: 842n, shortName: "taratest" },
{ chainId: 870n, shortName: "AMN" },
{ chainId: 919n, shortName: "modesep" },
{ chainId: 938n, shortName: "haust" },
{ chainId: 943n, shortName: "t4pls" },
{ chainId: 964n, shortName: "bittensor-evm-mainnet" },
{ chainId: 970n, shortName: "ccn" },
{ chainId: 988n, shortName: "stable" },
{ chainId: 995n, shortName: "5ire" },
{ chainId: 999n, shortName: "hyper_evm" },
{ chainId: 1001n, shortName: "kaia-kairos" },
{ chainId: 1008n, shortName: "eun" },
{ chainId: 1030n, shortName: "cfx" },
{ chainId: 1088n, shortName: "metis-andromeda" },
{ chainId: 1101n, shortName: "zkevm" },
{ chainId: 1111n, shortName: "wemix" },
{ chainId: 1112n, shortName: "twemix" },
{ chainId: 1114n, shortName: "tcore2" },
{ chainId: 1115n, shortName: "tcore" },
{ chainId: 1116n, shortName: "core" },
{ chainId: 1125n, shortName: "taker" },
{ chainId: 1135n, shortName: "lisk" },
{ chainId: 1230n, shortName: "UltronTestnet" },
{ chainId: 1231n, shortName: "UltronMainnet" },
{ chainId: 1284n, shortName: "mbeam" },
{ chainId: 1285n, shortName: "mriver" },
{ chainId: 1287n, shortName: "mbase" },
{ chainId: 1294n, shortName: "bobabeam" },
{ chainId: 1301n, shortName: "unichain-sep" },
{ chainId: 1315n, shortName: "story-aeneid" },
{ chainId: 1328n, shortName: "sei-testnet" },
{ chainId: 1329n, shortName: "sei" },
{ chainId: 1337n, shortName: "geth" },
{ chainId: 1424n, shortName: "perennial" },
{ chainId: 1439n, shortName: "injective-testnet" },
{ chainId: 1442n, shortName: "testnet-zkEVM-mango" },
{ chainId: 1480n, shortName: "vana" },
{ chainId: 1513n, shortName: "Story" },
{ chainId: 1514n, shortName: "sty" },
{ chainId: 1516n, shortName: "story-testnet" },
{ chainId: 1559n, shortName: "tenet" },
{ chainId: 1625n, shortName: "gravity" },
{ chainId: 1663n, shortName: "Gobi" },
{ chainId: 1672n, shortName: "pharos" },
{ chainId: 1729n, shortName: "reya" },
{ chainId: 1740n, shortName: "metall2-testnet" },
{ chainId: 1750n, shortName: "metall2" },
{ chainId: 1776n, shortName: "injective" },
{ chainId: 1807n, shortName: "rana" },
{ chainId: 1811n, shortName: "lif3-testnet" },
{ chainId: 1868n, shortName: "soneium" },
{ chainId: 1890n, shortName: "lightlink_phoenix" },
{ chainId: 1891n, shortName: "lightlink_pegasus" },
{ chainId: 1923n, shortName: "swellchain" },
{ chainId: 1924n, shortName: "swellchain-sep" },
{ chainId: 1946n, shortName: "soneium-minato" },
{ chainId: 1984n, shortName: "euntest" },
{ chainId: 1995n, shortName: "edxt" },
{ chainId: 1998n, shortName: "kyoto-testnet" },
{ chainId: 2000n, shortName: "dc" },
{ chainId: 2001n, shortName: "milkada" },
{ chainId: 2002n, shortName: "milkalgo" },
{ chainId: 2008n, shortName: "cloudwalk_testnet" },
{ chainId: 2019n, shortName: "pmint_test" },
{ chainId: 2020n, shortName: "pmint" },
{ chainId: 2021n, shortName: "edg" },
{ chainId: 2039n, shortName: "aleph" },
{ chainId: 2187n, shortName: "g7" },
{ chainId: 2192n, shortName: "snax" },
{ chainId: 2201n, shortName: "stable-testnet" },
{ chainId: 2221n, shortName: "tkava" },
{ chainId: 2222n, shortName: "kava" },
{ chainId: 2331n, shortName: "rss3-testnet" },
{ chainId: 2345n, shortName: "goat" },
{ chainId: 2358n, shortName: "kroma-sepolia" },
{ chainId: 2390n, shortName: "tacchain_2390-1" },
{ chainId: 2391n, shortName: "tacchain_2391-1" },
{ chainId: 2424n, shortName: "inevm-testnet" },
{ chainId: 2442n, shortName: "zkevm-testnet-cardona" },
{ chainId: 2522n, shortName: "fraxtal-testnet" },
{ chainId: 2741n, shortName: "abstract" },
{ chainId: 2787n, shortName: "creator-chain-mainnet" },
{ chainId: 2810n, shortName: "hmorph" },
{ chainId: 2818n, shortName: "morph" },
{ chainId: 2910n, shortName: "morph-hoodi-testnet" },
{ chainId: 3068n, shortName: "bfc" },
{ chainId: 3111n, shortName: "alpha" },
{ chainId: 3338n, shortName: "PEAQ" },
{ chainId: 3501n, shortName: "JFIN" },
{ chainId: 3636n, shortName: "BTNXt" },
{ chainId: 3637n, shortName: "BTNX" },
{ chainId: 3737n, shortName: "csb" },
{ chainId: 3776n, shortName: "astrzk" },
{ chainId: 4002n, shortName: "tftm" },
{ chainId: 4061n, shortName: "Nahmii3Mainnet" },
{ chainId: 4062n, shortName: "Nahmii3Testnet" },
{ chainId: 4078n, shortName: "muster" },
{ chainId: 4153n, shortName: "rise" },
{ chainId: 4157n, shortName: "crossfi-testnet" },
{ chainId: 4158n, shortName: "crossfi" },
{ chainId: 4162n, shortName: "SXR" },
{ chainId: 4202n, shortName: "lisksep" },
{ chainId: 4217n, shortName: "tempo" },
{ chainId: 4326n, shortName: "megaeth" },
{ chainId: 4337n, shortName: "beam" },
{ chainId: 4460n, shortName: "orderlyl2" },
{ chainId: 4488n, shortName: "HYDRA" },
{ chainId: 4509n, shortName: "SC" },
{ chainId: 4653n, shortName: "gold" },
{ chainId: 4661n, shortName: "appchaintestnet" },
{ chainId: 4689n, shortName: "iotex-mainnet" },
{ chainId: 4801n, shortName: "wcsep" },
{ chainId: 4918n, shortName: "txvm" },
{ chainId: 4919n, shortName: "xvm" },
{ chainId: 5000n, shortName: "mantle" },
{ chainId: 5001n, shortName: "mantle-testnet" },
{ chainId: 5003n, shortName: "mnt-sep" },
{ chainId: 5031n, shortName: "Somnia" },
{ chainId: 5115n, shortName: "citrea-testnet" },
{ chainId: 5165n, shortName: "ftn" },
{ chainId: 5330n, shortName: "sseed" },
{ chainId: 5464n, shortName: "saga" },
{ chainId: 5611n, shortName: "obnbt" },
{ chainId: 5700n, shortName: "tsys" },
{ chainId: 5851n, shortName: "OntologyTestnet" },
{ chainId: 5887n, shortName: "dukong" },
{ chainId: 5888n, shortName: "mantrachain" },
{ chainId: 6001n, shortName: "bouncebit-mainnet" },
{ chainId: 6102n, shortName: "cascadia" },
{ chainId: 6321n, shortName: "eaura" },
{ chainId: 6322n, shortName: "aura" },
{ chainId: 6342n, shortName: "megatest" },
{ chainId: 6398n, shortName: "connext-sepolia" },
{ chainId: 6688n, shortName: "iris" },
{ chainId: 6880n, shortName: "mtt-network" },
{ chainId: 6900n, shortName: "cataclysm-1" },
{ chainId: 6911n, shortName: "nibiru-testnet-2" },
{ chainId: 6942n, shortName: "laika" },
{ chainId: 7000n, shortName: "zetachain-mainnet" },
{ chainId: 7001n, shortName: "zetachain-testnet" },
{ chainId: 7070n, shortName: "planq" },
{ chainId: 7171n, shortName: "bitrock" },
{ chainId: 7200n, shortName: "xsat" },
{ chainId: 7208n, shortName: "nxra-mainnet" },
{ chainId: 7332n, shortName: "EON" },
{ chainId: 7336n, shortName: "pruvtestnet" },
{ chainId: 7337n, shortName: "pruvmainnet" },
{ chainId: 7341n, shortName: "shyft" },
{ chainId: 7560n, shortName: "cyeth" },
{ chainId: 7700n, shortName: "canto" },
{ chainId: 7771n, shortName: "tbitrock" },
{ chainId: 7897n, shortName: "arena-z" },
{ chainId: 7979n, shortName: "dos" },
{ chainId: 8008n, shortName: "polynomial" },
{ chainId: 8150n, shortName: "alpen" },
{ chainId: 8192n, shortName: "tqf" },
{ chainId: 8194n, shortName: "ttqf" },
{ chainId: 8217n, shortName: "kaia-mainnet" },
{ chainId: 8329n, shortName: "lrz" },
{ chainId: 8333n, shortName: "b3" },
{ chainId: 8408n, shortName: "zentest" },
{ chainId: 8453n, shortName: "base" },
{ chainId: 8700n, shortName: "ACN" },
{ chainId: 8765n, shortName: "ward" },
{ chainId: 8801n, shortName: "okto-testnet" },
{ chainId: 8822n, shortName: "iotaevm" },
{ chainId: 8844n, shortName: "THYDRA" },
{ chainId: 9000n, shortName: "evmos-testnet" },
{ chainId: 9001n, shortName: "evmos" },
{ chainId: 9069n, shortName: "AP3X" },
{ chainId: 9070n, shortName: "tAP3X" },
{ chainId: 9369n, shortName: "z" },
{ chainId: 9700n, shortName: "MainnetDev" },
{ chainId: 9728n, shortName: "boba-testnet" },
{ chainId: 9745n, shortName: "plasma" },
{ chainId: 9746n, shortName: "plasma-testnet" },
{ chainId: 10000n, shortName: "smartbch" },
{ chainId: 10001n, shortName: "smartbchtest" },
{ chainId: 10081n, shortName: "joct" },
{ chainId: 10143n, shortName: "mon-testnet" },
{ chainId: 10200n, shortName: "chi" },
{ chainId: 10242n, shortName: "aa" },
{ chainId: 10243n, shortName: "aat" },
{ chainId: 10849n, shortName: "lamina1" },
{ chainId: 10888n, shortName: "gameswift-chain-testnet" },
{ chainId: 11011n, shortName: "shapesep" },
{ chainId: 11111n, shortName: "WAGMI" },
{ chainId: 11124n, shortName: "abstract-sepolia" },
{ chainId: 11235n, shortName: "islm" },
{ chainId: 11417n, shortName: "anq-testnet" },
{ chainId: 11437n, shortName: "shyftt" },
{ chainId: 11501n, shortName: "bevm" },
{ chainId: 11503n, shortName: "bevm-test" },
{ chainId: 11820n, shortName: "artela-mainnet" },
{ chainId: 11891n, shortName: "Arianee" },
{ chainId: 12324n, shortName: "l3x" },
{ chainId: 12325n, shortName: "l3x-testnet" },
{ chainId: 12357n, shortName: "rei-testnet" },
{ chainId: 12553n, shortName: "rss3" },
{ chainId: 13337n, shortName: "beam-testnet" },
{ chainId: 13371n, shortName: "imx" },
{ chainId: 13441n, shortName: "bridgeless" },
{ chainId: 13473n, shortName: "imx-testnet" },
{ chainId: 13505n, shortName: "gravitysep" },
{ chainId: 13746n, shortName: "g7t" },
{ chainId: 14601n, shortName: "sonic-testnet" },
{ chainId: 14800n, shortName: "vana-moksha" },
{ chainId: 16661n, shortName: "0g" },
{ chainId: 17000n, shortName: "holesky" },
{ chainId: 17069n, shortName: "garnet" },
{ chainId: 17172n, shortName: "eclipse" },
{ chainId: 18231n, shortName: "unreal-old" },
{ chainId: 18233n, shortName: "unreal" },
{ chainId: 18880n, shortName: "expchain" },
{ chainId: 20994n, shortName: "fluent-testnet" },
{ chainId: 22776n, shortName: "mapo" },
{ chainId: 23294n, shortName: "sapphire" },
{ chainId: 23295n, shortName: "sapphire-testnet" },
{ chainId: 24101n, shortName: "incentiv" },
{ chainId: 25327n, shortName: "Everclear" },
{ chainId: 25363n, shortName: "fluent" },
{ chainId: 26888n, shortName: "tABCore" },
{ chainId: 28802n, shortName: "tcent" },
{ chainId: 28882n, shortName: "BobaSepolia" },
{ chainId: 28979n, shortName: "kimbonet-testnet" },
{ chainId: 30303n, shortName: "Ethiq" },
{ chainId: 31611n, shortName: "mezo-testnet" },
{ chainId: 31612n, shortName: "mezo" },
{ chainId: 32323n, shortName: "basedai" },
{ chainId: 32380n, shortName: "paix" },
{ chainId: 32769n, shortName: "zil" },
{ chainId: 32770n, shortName: "zq2-proto-mainnet" },
{ chainId: 33101n, shortName: "zil-testnet" },
{ chainId: 33111n, shortName: "curtis" },
{ chainId: 33139n, shortName: "apechain" },
{ chainId: 33401n, shortName: "slingshot" },
{ chainId: 34443n, shortName: "mode" },
{ chainId: 35441n, shortName: "q" },
{ chainId: 35443n, shortName: "q-testnet" },
{ chainId: 36888n, shortName: "abcore" },
{ chainId: 36900n, shortName: "adi" },
{ chainId: 37111n, shortName: "lens-sepolia" },
{ chainId: 41455n, shortName: "aleph-zero" },
{ chainId: 41923n, shortName: "edu-chain" },
{ chainId: 42161n, shortName: "arb1" },
{ chainId: 42170n, shortName: "arb-nova" },
{ chainId: 42220n, shortName: "celo" },
{ chainId: 42421n, shortName: "rwa" },
{ chainId: 42431n, shortName: "tempo-moderato" },
{ chainId: 42793n, shortName: "etlk" },
{ chainId: 43111n, shortName: "hemi" },
{ chainId: 43113n, shortName: "fuji" },
{ chainId: 43114n, shortName: "avax" },
{ chainId: 43288n, shortName: "boba-avax" },
{ chainId: 43419n, shortName: "gunz-mainnet" },
{ chainId: 44787n, shortName: "alfa" },
{ chainId: 45000n, shortName: "autobahnnetwork" },
{ chainId: 47763n, shortName: "neox-mainnet" },
{ chainId: 47805n, shortName: "rei" },
{ chainId: 48898n, shortName: "zircuit-garfield-testnet" },
{ chainId: 48899n, shortName: "zircuit-testnet" },
{ chainId: 48900n, shortName: "zircuit-mainnet" },
{ chainId: 49088n, shortName: "tbfc" },
{ chainId: 49321n, shortName: "Stork" },
{ chainId: 50104n, shortName: "sophon" },
{ chainId: 50312n, shortName: "SomniaTestnet" },
{ chainId: 52924n, shortName: "lazai" },
{ chainId: 53302n, shortName: "seedsep" },
{ chainId: 53456n, shortName: "birdlayer" },
{ chainId: 53457n, shortName: "dodochain" },
{ chainId: 54211n, shortName: "islmt" },
{ chainId: 55244n, shortName: "spn" },
{ chainId: 56288n, shortName: "boba-bnb" },
{ chainId: 57000n, shortName: "tsys-rollux" },
{ chainId: 57054n, shortName: "blaze" },
{ chainId: 57073n, shortName: "ink" },
{ chainId: 58008n, shortName: "sepPGN" },
{ chainId: 59140n, shortName: "linea-goerli" },
{ chainId: 59141n, shortName: "linea-sepolia" },
{ chainId: 59144n, shortName: "linea" },
{ chainId: 59902n, shortName: "metis-sepolia" },
{ chainId: 60808n, shortName: "bob" },
{ chainId: 61166n, shortName: "treasure" },
{ chainId: 66665n, shortName: "ceth" },
{ chainId: 71401n, shortName: "gw-testnet-v1" },
{ chainId: 71402n, shortName: "gw-mainnet-v1" },
{ chainId: 72080n, shortName: "nxra-testnet" },
{ chainId: 73799n, shortName: "vt" },
{ chainId: 80001n, shortName: "maticmum" },
{ chainId: 80002n, shortName: "polygonamoy" },
{ chainId: 80069n, shortName: "berachain-bepolia" },
{ chainId: 80084n, shortName: "berachainbArtio" },
{ chainId: 80085n, shortName: "berachainArtio" },
{ chainId: 80094n, shortName: "berachain" },
{ chainId: 81224n, shortName: "Codex" },
{ chainId: 81457n, shortName: "blastmainnet" },
{ chainId: 83291n, shortName: "lrz-testnet" },
{ chainId: 84531n, shortName: "basegor" },
{ chainId: 84532n, shortName: "basesep" },
{ chainId: 88811n, shortName: "unit0-mainnet" },
{ chainId: 88817n, shortName: "unit0-testnet" },
{ chainId: 88882n, shortName: "chzspicy" },
{ chainId: 88888n, shortName: "chiliz" },
{ chainId: 90001n, shortName: "dhobyghaut" },
{ chainId: 91342n, shortName: "giwasepolia" },
{ chainId: 97435n, shortName: "sling" },
{ chainId: 98864n, shortName: "plume-devnet" },
{ chainId: 98865n, shortName: "plume" },
{ chainId: 98866n, shortName: "plume-mainnet" },
{ chainId: 98867n, shortName: "plume-testnet" },
{ chainId: 98875n, shortName: "nil" },
{ chainId: 98985n, shortName: "superposition-testnet" },
{ chainId: 102030n, shortName: "ctc" },
{ chainId: 103454n, shortName: "masatest" },
{ chainId: 105105n, shortName: "stratis" },
{ chainId: 111188n, shortName: "re-al" },
{ chainId: 127823n, shortName: "etls" },
{ chainId: 128123n, shortName: "etlt" },
{ chainId: 167000n, shortName: "tko-mainnet" },
{ chainId: 167008n, shortName: "tko-katla" },
{ chainId: 167009n, shortName: "tko-hekla" },
{ chainId: 167013n, shortName: "tko-hoodi" },
{ chainId: 175188n, shortName: "lpy" },
{ chainId: 181228n, shortName: "hpp-sepolia" },
{ chainId: 190415n, shortName: "hpp-mainnet" },
{ chainId: 200101n, shortName: "milktada" },
{ chainId: 200202n, shortName: "milktalgo" },
{ chainId: 200810n, shortName: "btrt" },
{ chainId: 200901n, shortName: "btr" },
{ chainId: 205205n, shortName: "auroria" },
{ chainId: 210425n, shortName: "platon" },
{ chainId: 222888n, shortName: "mocat" },
{ chainId: 278701n, shortName: "creator-chain-testnet" },
{ chainId: 314159n, shortName: "filecoin-calibration" },
{ chainId: 325000n, shortName: "CampV2" },
{ chainId: 328527n, shortName: "nal" },
{ chainId: 333999n, shortName: "olympus" },
{ chainId: 369369n, shortName: "den-mainnet" },
{ chainId: 381931n, shortName: "metal" },
{ chainId: 421611n, shortName: "arb-rinkeby" },
{ chainId: 421613n, shortName: "arb-goerli" },
{ chainId: 421614n, shortName: "arb-sep" },
{ chainId: 444444n, shortName: "syndr" },
{ chainId: 490000n, shortName: "ATN" },
{ chainId: 511111n, shortName: "alpha-testnet" },
{ chainId: 534351n, shortName: "scr-sepolia" },
{ chainId: 534352n, shortName: "scr" },
{ chainId: 534353n, shortName: "scr-alpha" },
{ chainId: 543210n, shortName: "zero-network" },
{ chainId: 555666n, shortName: "eclipset" },
{ chainId: 560048n, shortName: "hoe" },
{ chainId: 622277n, shortName: "rth" },
{ chainId: 656476n, shortName: "open-campus-codex" },
{ chainId: 657468n, shortName: "ethereal-testnet" },
{ chainId: 660279n, shortName: "xai" },
{ chainId: 668668n, shortName: "cnw" },
{ chainId: 688688n, shortName: "pharos-testnet" },
{ chainId: 688689n, shortName: "pharos-atlantic" },
{ chainId: 695569n, shortName: "pyrope" },
{ chainId: 713715n, shortName: "sei-devnet" },
{ chainId: 743111n, shortName: "hemi-sep" },
{ chainId: 747474n, shortName: "katana" },
{ chainId: 763373n, shortName: "inksepolia" },
{ chainId: 763375n, shortName: "surge-testnet" },
{ chainId: 764984n, shortName: "lamina1test" },
{ chainId: 808813n, shortName: "bob-sepolia" },
{ chainId: 810180n, shortName: "zklink-nova" },
{ chainId: 839999n, shortName: "txsat" },
{ chainId: 853211n, shortName: "haqq-testethiq" },
{ chainId: 978657n, shortName: "treasure-ruby" },
{ chainId: 984122n, shortName: "forma" },
{ chainId: 1000101n, shortName: "xo" },
{ chainId: 1440000n, shortName: "xrplevm" },
{ chainId: 1449000n, shortName: "xrplevmtestnet" },
{ chainId: 1501869n, shortName: "water9" },
{ chainId: 2206132n, shortName: "platondev2" },
{ chainId: 2632500n, shortName: "coti" },
{ chainId: 3441006n, shortName: "mantaSepoliaTestnet" },
{ chainId: 4457845n, shortName: "zero-sepolia" },
{ chainId: 5042002n, shortName: "arc-testnet" },
{ chainId: 5064014n, shortName: "ethereal" },
{ chainId: 6038361n, shortName: "azkyt" },
{ chainId: 6281971n, shortName: "dogeos-chykyu" },
{ chainId: 6985385n, shortName: "hp" },
{ chainId: 7225878n, shortName: "saakuru" },
{ chainId: 7777777n, shortName: "zora" },
{ chainId: 9999999n, shortName: "fluence" },
{ chainId: 11142220n, shortName: "celo-sep" },
{ chainId: 11155111n, shortName: "sep" },
{ chainId: 11155420n, shortName: "opsep" },
{ chainId: 11155931n, shortName: "rise-testnet" },
{ chainId: 12227332n, shortName: "neox-t4" },
{ chainId: 13374202n, shortName: "ethereal-testnet-0" },
{ chainId: 13863860n, shortName: "sis" },
{ chainId: 20250407n, shortName: "platondev3" },
{ chainId: 21000000n, shortName: "corn" },
{ chainId: 52164803n, shortName: "fluence-testnet" },
{ chainId: 65100004n, shortName: "piccadilly-04" },
{ chainId: 94204209n, shortName: "polygon-blackberry" },
{ chainId: 111557560n, shortName: "cysep" },
{ chainId: 123420111n, shortName: "opcelestia-raspberry" },
{ chainId: 161221135n, shortName: "plume-testnet-legacy" },
{ chainId: 168587773n, shortName: "blastsepolia" },
{ chainId: 222000222n, shortName: "kanazawa" },
{ chainId: 245022926n, shortName: "neonevm-devnet" },
{ chainId: 245022934n, shortName: "neonevm-mainnet" },
{ chainId: 253368190n, shortName: "flame" },
{ chainId: 328527624n, shortName: "nalsep" },
{ chainId: 333000333n, shortName: "meld" },
{ chainId: 476462898n, shortName: "Skopje" },
{ chainId: 531050104n, shortName: "sophon-testnet" },
{ chainId: 531050204n, shortName: "sophon-os-testnet" },
{ chainId: 666666666n, shortName: "degen-chain" },
{ chainId: 888888888n, shortName: "ancient8" },
{ chainId: 994873017n, shortName: "lumia-mainnet" },
{ chainId: 999999999n, shortName: "zsep" },
{ chainId: 1313161554n, shortName: "aurora" },
{ chainId: 1313161555n, shortName: "aurora-testnet" },
{ chainId: 1417429182n, shortName: "zephyr" },
{ chainId: 1511670449n, shortName: "GPT" },
{ chainId: 1570754601n, shortName: "hst-test" },
{ chainId: 1660990954n, shortName: "sn-sepolia" },
{ chainId: 1666600000n, shortName: "hmy-s0" },
{ chainId: 1666700000n, shortName: "hmy-b-s0" },
{ chainId: 1952959480n, shortName: "lumiatestnet" },
{ chainId: 2030232745n, shortName: "lumia-beam-testnet" },
{ chainId: 3735928814n, shortName: "edent" },
{ chainId: 11297108099n, shortName: "tpalm" },
{ chainId: 11297108109n, shortName: "palm" },
{ chainId: 30143370385n, shortName: "BUB" },
{ chainId: 37714555429n, shortName: "xaitestnet" },
{ chainId: 88153591557n, shortName: "arb-blueberry" },
{ chainId: 123420000220n, shortName: "fluence-stage" },
{ chainId: 920637907288165n, shortName: "kkrt-starknet-sepolia" }
];
try {
if (process.env.TEST_NETWORK === "hardhat") {
networks.push({ shortName: "local", chainId: 31337n });
}
} catch {
}
// src/utils/eip-3770/index.ts
function parseEip3770Address(fullAddress) {
const parts = fullAddress.split(":");
const address = parts.length > 1 ? parts[1] : parts[0];
const prefix = parts.length > 1 ? parts[0] : "";
return { prefix, address };
}
function getEip3770NetworkPrefixFromChainId(chainId) {
const network = networks.find((network2) => chainId === network2.chainId);
if (!network) {
throw new Error("No network prefix supported for the current chainId");
}
return network.shortName;
}
function isValidEip3770NetworkPrefix(prefix) {
return networks.some(({ shortName }) => shortName === prefix);
}
function validateEip3770NetworkPrefix(prefix, currentChainId) {
const isCurrentNetworkPrefix = prefix === getEip3770NetworkPrefixFromChainId(currentChainId);
if (!isValidEip3770NetworkPrefix(prefix) || !isCurrentNetworkPrefix) {
throw new Error("The network prefix must match the current network");
}
}
function validateEthereumAddress(address) {
if (!isAddress(address)) {
throw new Error(`Invalid Ethereum address ${address}`);
}
}
function validateEip3770Address(fullAddress, currentChainId) {
const { address, prefix } = parseEip3770Address(fullAddress);
validateEthereumAddress(address);
if (prefix) {
validateEip3770NetworkPrefix(prefix, currentChainId);
}
return { address, prefix };
}
// src/utils/eip-712/index.ts
import { hashMessage as performMessageHash } from "viem";
import semverSatisfies from "semver/functions/satisfies.js";
// src/utils/eip-712/encode.ts
import {
keccak256,
concat,
encodeAbiParameters,
getTypesForEIP712Domain,
validateTypedData,
hashDomain,
toHex
} from "viem";
function encodeField({
types,
name,
type,
value
}) {
if (types[type] !== void 0) {
return [{ type: "bytes32" }, keccak256(encodeData({ data: value, primaryType: type, types }))];
}
if (type === "bytes") {
const prepend = value.length % 2 ? "0" : "";
value = `0x${prepend + value.slice(2)}`;
return [{ type: "bytes32" }, keccak256(value)];
}
if (type === "string") return [{ type: "bytes32" }, keccak256(toHex(value))];
if (type.lastIndexOf("]") === type.length - 1) {
const parsedType = type.slice(0, type.lastIndexOf("["));
const typeValuePairs = value.map(
(item) => encodeField({
name,
type: parsedType,
types,
value: item
})
);
return [
{ type: "bytes32" },
keccak256(
encodeAbiParameters(
typeValuePairs.map(([t]) => t),
typeValuePairs.map(([, v]) => v)
)
)
];
}
return [{ type }, value];
}
function findTypeDependencies({
primaryType: primaryType_,
types
}, results = /* @__PURE__ */ new Set()) {
const match = primaryType_.match(/^\w*/u);
const primaryType = match?.[0] || "";
if (results.has(primaryType) || types[primaryType] === void 0) {
return results;
}
results.add(primaryType);
for (const field of types[primaryType]) {
findTypeDependencies({ primaryType: field.type, types }, results);
}
return results;
}
function encodeType({
primaryType,
types
}) {
let result = "";
const unsortedDeps = findTypeDependencies({ primaryType, types });
unsortedDeps.delete(primaryType);
const deps = [primaryType, ...Array.from(unsortedDeps).sort()];
for (const type of deps) {
result += `${type}(${types[type].map(({ name, type: t }) => `${t} ${name}`).join(",")})`;
}
return result;
}
function hashType({
primaryType,
types
}) {
const encodedHashType = toHex(encodeType({ primaryType, types }));
return keccak256(encodedHashType);
}
function encodeData({
data,
primaryType,
types
}) {
const encodedTypes = [{ type: "bytes32" }];
const encodedValues = [hashType({ primaryType, types })];
for (const field of types[primaryType]) {
const [type, value] = encodeField({
types,
name: field.name,
type: field.type,
value: data[field.name]
});
encodedTypes.push(type);
encodedValues.push(value);
}
return encodeAbiParameters(encodedTypes, encodedValues);
}
function hashStruct({
data,
primaryType,
types
}) {
const encoded = encodeData({
data,
primaryType,
types
});
return keccak256(encoded);
}
function deducePrimaryType(types) {
return Object.keys(types)[0];
}
function hashTypedData(typedData) {
const data = encodeTypedData(typedData);
return keccak256(asHex(data));
}
function encodeTypedData(typedData) {
typedData.primaryType = !typedData?.primaryType ? deducePrimaryType(typedData.types) : typedData?.primaryType;
const { domain = {}, message, primaryType } = typedData;
const types = {
EIP712Domain: getTypesForEIP712Domain({ domain }),
...typedData.types
};
validateTypedData({
domain,
message,
primaryType,
types
});
const parts = ["0x1901"];
if (domain)
parts.push(
hashDomain({
domain,
types
})
);
if (primaryType !== "EIP712Domain")
parts.push(
hashStruct({
data: message,
primaryType,
types
})
);
return concat(parts);
}
// src/utils/eip-712/index.ts
var EQ_OR_GT_1_3_0 = ">=1.3.0";
var EIP712_DOMAIN_BEFORE_V130 = [
{
type: "address",
name: "verifyingContract"
}
];
var EIP712_DOMAIN = [
{
type: "uint256",
name: "chainId"
},
{
type: "address",
name: "verifyingContract"
}
];
function getEip712TxTypes(safeVersion) {
const eip712WithChainId = semverSatisfies(safeVersion, EQ_OR_GT_1_3_0);
return {
EIP712Domain: eip712WithChainId ? EIP712_DOMAIN : EIP712_DOMAIN_BEFORE_V130,
SafeTx: [
{ type: "address", name: "to" },
{ type: "uint256", name: "value" },
{ type: "bytes", name: "data" },
{ type: "uint8", name: "operation" },
{ type: "uint256", name: "safeTxGas" },
{ type: "uint256", name: "baseGas" },
{ type: "uint256", name: "gasPrice" },
{ type: "address", name: "gasToken" },
{ type: "address", name: "refundReceiver" },
{ type: "uint256", name: "nonce" }
]
};
}
function getEip712MessageTypes(safeVersion) {
const eip712WithChainId = semverSatisfies(safeVersion, EQ_OR_GT_1_3_0);
return {
EIP712Domain: eip712WithChainId ? EIP712_DOMAIN : EIP712_DOMAIN_BEFORE_V130,
SafeMessage: [{ type: "bytes", name: "message" }]
};
}
var hashTypedData2 = (typedData) => {
return hashTypedData(typedData);
};
var hashMessage = (message) => {
return performMessageHash(message);
};
var hashSafeMessage = (message) => {
return typeof message === "string" ? hashMessage(message) : hashTypedData2(message);
};
function generateTypedData({
safeAddress,
safeVersion,
chainId,
data
}) {
const isSafeTransactionDataType = data.hasOwnProperty("to");
const eip712WithChainId = semverSatisfies(safeVersion, EQ_OR_GT_1_3_0);
let typedData;
if (isSafeTransactionDataType) {
const txData = data;
typedData = {
types: getEip712TxTypes(safeVersion),
domain: {
verifyingContract: safeAddress
},
primaryType: "SafeTx",
message: {
...txData,
value: txData.value,
safeTxGas: txData.safeTxGas,
baseGas: txData.baseGas,
gasPrice: txData.gasPrice,
nonce: txData.nonce
}
};
} else {
const message = data;
typedData = {
types: getEip712MessageTypes(safeVersion),
domain: {
verifyingContract: safeAddress
},
primaryType: "SafeMessage",
message: { message: hashSafeMessage(message) }
};
}
if (eip712WithChainId) {
typedData.domain.chainId = Number(chainId);
}
return typedData;
}
// src/utils/safeVersions.ts
import semverSatisfies2 from "semver/functions/satisfies.js";
var SAFE_FEATURES_BY_VERSION = {
["SAFE_TX_GAS_OPTIONAL" /* SAFE_TX_GAS_OPTIONAL */]: ">=1.3.0",
["SAFE_TX_GUARDS" /* SAFE_TX_GUARDS */]: ">=1.3.0",
["SAFE_FALLBACK_HANDLER" /* SAFE_FALLBACK_HANDLER */]: ">=1.1.1",
["ETH_SIGN" /* ETH_SIGN */]: ">=1.1.0",
["ACCOUNT_ABSTRACTION" /* ACCOUNT_ABSTRACTION */]: ">=1.3.0",
["REQUIRED_TXGAS" /* REQUIRED_TXGAS */]: "<=1.2.0",
["SIMULATE_AND_REVERT" /* SIMULATE_AND_REVERT */]: ">=1.3.0",
["PASSKEY_SIGNER" /* PASSKEY_SIGNER */]: ">=1.3.0",
["SAFE_L2_CONTRACTS" /* SAFE_L2_CONTRACTS */]: ">=1.3.0",
["SAFE_MODULE_GUARD" /* SAFE_MODULE_GUARD */]: ">=1.5.0"
};
var hasSafeFeature = (feature, version) => {
if (!(feature in SAFE_FEATURES_BY_VERSION)) {
return false;
}
return semverSatisfies2(version, SAFE_FEATURES_BY_VERSION[feature]);
};
// src/utils/signatures/utils.ts
import { recoverAddress } from "viem";
import {
SigningMethod
} from "@safe-global/types-kit";
import semverSatisfies3 from "semver/functions/satisfies.js";
// src/utils/transactions/gas.ts
import { BaseError } from "viem";
import { OperationType } from "@safe-global/types-kit";
import semverSatisfies5 from "semver/functions/satisfies.js";
// src/contracts/BaseContract.ts
import {
encodeFunctionData
} from "viem";
import { estimateContractGas, getTransactionReceipt } from "viem/actions";
// src/contracts/config.ts
import {
getCompatibilityFallbackHandlerDeployments,
getCreateCallDeployments,
getExtensibleFallbackHandlerDeployments,
getMultiSendCallOnlyDeployments,
getMultiSendDeployments,
getProxyFactoryDeployments,
getSafeL2SingletonDeployments,
getSafeSingletonDeployments,
getSignMessageLibDeployments,
getSimulateTxAccessorDeployments
} from "@safe-global/safe-deployments";
import {
getSafeWebAuthnSignerFactoryDeployment,
getSafeWebAuthnShareSignerDeployment
} from "@safe-global/safe-modules-deployments";
var DEFAULT_SAFE_VERSION = "1.4.1";
var safeDeploymentsVersions = {
"1.5.0": {
safeSingletonVersion: "1.5.0",
safeSingletonL2Version: "1.5.0",
safeProxyFactoryVersion: "1.5.0",
compatibilityFallbackHandler: "1.5.0",
extensibleFallbackHandler: "1.5.0",
multiSendVersion: "1.5.0",
multiSendCallOnlyVersion: "1.5.0",
signMessageLibVersion: "1.5.0",
createCallVersion: "1.5.0",
simulateTxAccessorVersion: "1.5.0",
safeWebAuthnSignerFactoryVersion: "0.2.1",
safeWebAuthnSharedSignerVersion: "0.2.1"
},
"1.4.1": {
safeSingletonVersion: "1.4.1",
safeSingletonL2Version: "1.4.1",
safeProxyFactoryVersion: "1.4.1",
compatibilityFallbackHandler: "1.4.1",
multiSendVersion: "1.4.1",
multiSendCallOnlyVersion: "1.4.1",
signMessageLibVersion: "1.4.1",
createCallVersion: "1.4.1",
simulateTxAccessorVersion: "1.4.1",
safeWebAuthnSignerFactoryVersion: "0.2.1",
safeWebAuthnSharedSignerVersion: "0.2.1"
},
"1.3.0": {
safeSingletonVersion: "1.3.0",
safeSingletonL2Version: "1.3.0",
safeProxyFactoryVersion: "1.3.0",
compatibilityFallbackHandler: "1.3.0",
multiSendVersion: "1.3.0",
multiSendCallOnlyVersion: "1.3.0",
signMessageLibVersion: "1.3.0",
createCallVersion: "1.3.0",
simulateTxAccessorVersion: "1.3.0",
safeWebAuthnSignerFactoryVersion: "0.2.1",
safeWebAuthnSharedSignerVersion: "0.2.1"
},
"1.2.0": {
safeSingletonVersion: "1.2.0",
safeSingletonL2Version: void 0,
safeProxyFactoryVersion: "1.1.1",
compatibilityFallbackHandler: "1.3.0",
multiSendVersion: "1.1.1",
multiSendCallOnlyVersion: "1.3.0",
signMessageLibVersion: "1.3.0",
createCallVersion: "1.3.0",
safeWebAuthnSignerFactoryVersion: void 0,
safeWebAuthnSharedSignerVersion: void 0
},
"1.1.1": {
safeSingletonVersion: "1.1.1",
safeSingletonL2Version: void 0,
safeProxyFactoryVersion: "1.1.1",
compatibilityFallbackHandler: "1.3.0",
multiSendVersion: "1.1.1",
multiSendCallOnlyVersion: "1.3.0",
signMessageLibVersion: "1.3.0",
createCallVersion: "1.3.0",
safeWebAuthnSignerFactoryVersion: void 0,
safeWebAuthnSharedSignerVersion: void 0
},
"1.0.0": {
safeSingletonVersion: "1.0.0",
safeSingletonL2Version: void 0,
safeProxyFactoryVersion: "1.0.0",
compatibilityFallbackHandler: "1.3.0",
multiSendVersion: "1.1.1",
multiSendCallOnlyVersion: "1.3.0",
signMessageLibVersion: "1.3.0",
createCallVersion: "1.3.0",
safeWebAuthnSignerFactoryVersion: void 0,
safeWebAuthnSharedSignerVersion: void 0
}
};
var safeDeploymentsL1ChainIds = [
1n
// Ethereum Mainnet
];
var contractFunctions = {
safeSingletonVersion: getSafeSingletonDeployments,
safeSingletonL2Version: getSafeL2SingletonDeployments,
safeProxyFactoryVersion: getProxyFactoryDeployments,
compatibilityFallbackHandler: getCompatibilityFallbackHandlerDeployments,
extensibleFallbackHandler: getExtensibleFallbackHandlerDeployments,
multiSendVersion: getMultiSendDeployments,
multiSendCallOnlyVersion: getMultiSendCallOnlyDeployments,
signMessageLibVersion: getSignMessageLibDeployments,
createCallVersion: getCreateCallDeployments,
simulateTxAccessorVersion: getSimulateTxAccessorDeployments,
safeWebAuthnSignerFactoryVersion: getSafeWebAuthnSignerFactoryDeployment,
safeWebAuthnSharedSignerVersion: getSafeWebAuthnShareSignerDeployment
};
function getContractDeployment(safeVersion, chainId, contractName3) {
const contractVersion = safeDeploymentsVersions[safeVersion][contractName3];
const filters = {
version: contractVersion,
network: chainId.toString(),
released: true
};
const deployment = contractFunctions[contractName3](filters);
return deployment;
}
// src/contracts/BaseContract.ts
var BaseContract = class {
/**
* @constructor
* Constructs an instance of BaseContract.
*
* @param contractName - The contract name.
* @param chainId - The chain ID of the contract.
* @param safeProvider - An instance of SafeProvider.
* @param defaultAbi - The default ABI for the contract. It should be compatible with the specific version of the contract.
* @param safeVersion - The version of the Safe contract.
* @param customContractAddress - Optional custom address for the contract. If not provided, the address is derived from the Safe deployments based on the chainId and safeVersion.
* @param customContractAbi - Optional custom ABI for the contract. If not provided, the ABI is derived from the Safe deployments or the defaultAbi is used.
* @param deploymentType - Optional deployment type for the contract. If not provided, the first deployment retrieved from the safe-deployments array will be used.
*/
constructor(contractName3, chainId, safeProvider, defaultAbi, safeVersion, customContractAddress, customContractAbi, deploymentType) {
this.getAddress = () => {
return this.contractAddress;
};
this.encode = (functionToEncode, args) => {
const abi = this.contractAbi;
const functionName = functionToEncode;
const params = args;
return encodeFunctionData({
abi,
functionName,
args: params
});
};
this.estimateGas = async (functionToEstimate, args, options = {}) => {
const contractOptions = this.convertOptions(options);
const abi = this.contractAbi;
const params = args;
return estimateContractGas(this.runner, {
abi,
functionName: functionToEstimate,
address: this.getAddress(),
args: params,
...contractOptions
});
};
const deployment = getContractDeployment(safeVersion, chainId, contractName3);
const resolvedAddress = customContractAddress ?? this.#resolveAddress(
deployment?.networkAddresses[chainId.toString()],
deployment,
deploymentType
);
if (!resolvedAddress) {
throw new Error(`Invalid ${contractName3.replace("Version", "")} contract address`);
}
this.chainId = chainId;
this.contractName = contractName3;
this.safeVersion = safeVersion;
this.contractAddress = resolvedAddress;
this.contractAbi = customContractAbi || deployment?.abi || // this cast is required because abi is set as any[] in safe-deployments
defaultAbi;
this.runner = safeProvider.getExternalProvider();
this.safeProvider = safeProvider;
}
#resolveAddress(networkAddresses, deployment, deploymentType) {
if (!networkAddresses) {
return void 0;
}
if (deploymentType && deployment && "deployments" in deployment) {
const customDeploymentTypeAddress = deployment.deployments[deploymentType]?.address;
if (typeof networkAddresses === "string") {
return networkAddresses === customDeploymentTypeAddress ? customDeploymentTypeAddress : void 0;
}
return networkAddresses.find((address) => address === customDeploymentTypeAddress);
}
if (typeof networkAddresses === "string") {
return networkAddresses;
}
return networkAddresses[0];
}
async init() {
this.wallet = await this.safeProvider.getExternalSigner();
}
async getTransactionReceipt(hash) {
return getTransactionReceipt(this.runner, { hash });
}
/**
* Converts a type of TransactionOptions to a viem transaction type. The viem transaction type creates a clear distinction between the multiple transaction objects (e.g., post-London hard fork) and doesn't allow a union of fields.
* See: https://github.com/wevm/viem/blob/viem%402.18.0/src/types/fee.ts and https://github.com/wevm/viem/blob/603227e2588366914fb79a902d23fd9afc353cc6/src/types/transaction.ts#L200
*
* @param options - Transaction options as expected throughout safe sdk and propagated on the results.
*
* @returns Options object compatible with Viem
*/
convertOptions(options) {
const chain = this.getChain();
if (!chain) throw new Error("Invalid chainId");
const account = this.getWallet().account;
if (!account) throw new Error("Invalid signer");
const txOptions = convertTransactionOptions(options);
return { chain, ...txOptions, account };
}
getChain() {
return getChainById(this.chainId);
}
getWallet() {
if (!this.wallet) throw new Error("A signer must be set");
return this.wallet;
}
async write(