permissionless 0.0.12 → 0.0.13
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/CHANGELOG.md +10 -0
- package/_cjs/accounts/index.js +9 -2
- package/_cjs/accounts/index.js.map +1 -1
- package/_cjs/accounts/privateKeyToSafeSmartAccount.js +24 -0
- package/_cjs/accounts/privateKeyToSafeSmartAccount.js.map +1 -0
- package/_cjs/accounts/privateKeyToSimpleSmartAccount.js +8 -160
- package/_cjs/accounts/privateKeyToSimpleSmartAccount.js.map +1 -1
- package/_cjs/accounts/signerToSafeSmartAccount.js +492 -0
- package/_cjs/accounts/signerToSafeSmartAccount.js.map +1 -0
- package/_cjs/accounts/signerToSimpleSmartAccount.js +190 -0
- package/_cjs/accounts/signerToSimpleSmartAccount.js.map +1 -0
- package/_cjs/accounts/types.js +20 -0
- package/_cjs/accounts/types.js.map +1 -1
- package/_cjs/actions/bundler/chainId.js.map +1 -1
- package/_cjs/actions/bundler/estimateUserOperationGas.js.map +1 -1
- package/_cjs/actions/bundler/getUserOperationByHash.js.map +1 -1
- package/_cjs/actions/bundler/getUserOperationReceipt.js.map +1 -1
- package/_cjs/actions/bundler/sendUserOperation.js.map +1 -1
- package/_cjs/actions/bundler/supportedEntryPoints.js.map +1 -1
- package/_cjs/actions/bundler/waitForUserOperationReceipt.js.map +1 -1
- package/_cjs/actions/smartAccount/prepareUserOperationRequest.js +3 -1
- package/_cjs/actions/smartAccount/prepareUserOperationRequest.js.map +1 -1
- package/_cjs/actions/smartAccount/sendTransaction.js +3 -2
- package/_cjs/actions/smartAccount/sendTransaction.js.map +1 -1
- package/_cjs/actions/smartAccount/sendTransactions.js +46 -0
- package/_cjs/actions/smartAccount/sendTransactions.js.map +1 -0
- package/_cjs/actions/smartAccount.js +3 -1
- package/_cjs/actions/smartAccount.js.map +1 -1
- package/_cjs/clients/decorators/smartAccount.js +5 -0
- package/_cjs/clients/decorators/smartAccount.js.map +1 -1
- package/_esm/accounts/index.js +6 -3
- package/_esm/accounts/index.js.map +1 -1
- package/_esm/accounts/privateKeyToSafeSmartAccount.js +26 -0
- package/_esm/accounts/privateKeyToSafeSmartAccount.js.map +1 -0
- package/_esm/accounts/privateKeyToSimpleSmartAccount.js +9 -160
- package/_esm/accounts/privateKeyToSimpleSmartAccount.js.map +1 -1
- package/_esm/accounts/signerToSafeSmartAccount.js +499 -0
- package/_esm/accounts/signerToSafeSmartAccount.js.map +1 -0
- package/_esm/accounts/signerToSimpleSmartAccount.js +191 -0
- package/_esm/accounts/signerToSimpleSmartAccount.js.map +1 -0
- package/_esm/accounts/types.js +18 -0
- package/_esm/accounts/types.js.map +1 -1
- package/_esm/actions/bundler/chainId.js.map +1 -1
- package/_esm/actions/bundler/estimateUserOperationGas.js.map +1 -1
- package/_esm/actions/bundler/getUserOperationByHash.js.map +1 -1
- package/_esm/actions/bundler/getUserOperationReceipt.js.map +1 -1
- package/_esm/actions/bundler/sendUserOperation.js.map +1 -1
- package/_esm/actions/bundler/supportedEntryPoints.js.map +1 -1
- package/_esm/actions/bundler/waitForUserOperationReceipt.js.map +1 -1
- package/_esm/actions/pimlico/getUserOperationGasPrice.js +1 -1
- package/_esm/actions/pimlico/getUserOperationStatus.js +1 -1
- package/_esm/actions/smartAccount/prepareUserOperationRequest.js +3 -1
- package/_esm/actions/smartAccount/prepareUserOperationRequest.js.map +1 -1
- package/_esm/actions/smartAccount/sendTransaction.js +3 -2
- package/_esm/actions/smartAccount/sendTransaction.js.map +1 -1
- package/_esm/actions/smartAccount/sendTransactions.js +90 -0
- package/_esm/actions/smartAccount/sendTransactions.js.map +1 -0
- package/_esm/actions/smartAccount.js +2 -1
- package/_esm/actions/smartAccount.js.map +1 -1
- package/_esm/actions/stackup/accounts.js +1 -1
- package/_esm/actions/stackup/sponsorUserOperation.js +1 -1
- package/_esm/clients/decorators/pimlico.js +1 -1
- package/_esm/clients/decorators/smartAccount.js +5 -0
- package/_esm/clients/decorators/smartAccount.js.map +1 -1
- package/_esm/clients/pimlico.js +1 -1
- package/_esm/clients/stackup.js +1 -1
- package/_types/accounts/index.d.ts +6 -3
- package/_types/accounts/index.d.ts.map +1 -1
- package/_types/accounts/privateKeyToSafeSmartAccount.d.ts +26 -0
- package/_types/accounts/privateKeyToSafeSmartAccount.d.ts.map +1 -0
- package/_types/accounts/privateKeyToSimpleSmartAccount.d.ts +5 -11
- package/_types/accounts/privateKeyToSimpleSmartAccount.d.ts.map +1 -1
- package/_types/accounts/signerToSafeSmartAccount.d.ts +28 -0
- package/_types/accounts/signerToSafeSmartAccount.d.ts.map +1 -0
- package/_types/accounts/signerToSimpleSmartAccount.d.ts +15 -0
- package/_types/accounts/signerToSimpleSmartAccount.d.ts.map +1 -0
- package/_types/accounts/types.d.ts +14 -3
- package/_types/accounts/types.d.ts.map +1 -1
- package/_types/actions/bundler/chainId.d.ts +3 -2
- package/_types/actions/bundler/chainId.d.ts.map +1 -1
- package/_types/actions/bundler/estimateUserOperationGas.d.ts +3 -3
- package/_types/actions/bundler/estimateUserOperationGas.d.ts.map +1 -1
- package/_types/actions/bundler/getUserOperationByHash.d.ts +3 -3
- package/_types/actions/bundler/getUserOperationByHash.d.ts.map +1 -1
- package/_types/actions/bundler/getUserOperationReceipt.d.ts +3 -3
- package/_types/actions/bundler/getUserOperationReceipt.d.ts.map +1 -1
- package/_types/actions/bundler/sendUserOperation.d.ts +3 -3
- package/_types/actions/bundler/sendUserOperation.d.ts.map +1 -1
- package/_types/actions/bundler/supportedEntryPoints.d.ts +3 -3
- package/_types/actions/bundler/supportedEntryPoints.d.ts.map +1 -1
- package/_types/actions/bundler/waitForUserOperationReceipt.d.ts +2 -3
- package/_types/actions/bundler/waitForUserOperationReceipt.d.ts.map +1 -1
- package/_types/actions/pimlico/getUserOperationGasPrice.d.ts +1 -1
- package/_types/actions/pimlico/getUserOperationStatus.d.ts +1 -1
- package/_types/actions/smartAccount/prepareUserOperationRequest.d.ts.map +1 -1
- package/_types/actions/smartAccount/sendTransaction.d.ts.map +1 -1
- package/_types/actions/smartAccount/sendTransactions.d.ts +63 -0
- package/_types/actions/smartAccount/sendTransactions.d.ts.map +1 -0
- package/_types/actions/smartAccount.d.ts +2 -1
- package/_types/actions/smartAccount.d.ts.map +1 -1
- package/_types/actions/stackup/accounts.d.ts +1 -1
- package/_types/actions/stackup/sponsorUserOperation.d.ts +1 -1
- package/_types/clients/createSmartAccountClient.d.ts +1 -0
- package/_types/clients/createSmartAccountClient.d.ts.map +1 -1
- package/_types/clients/decorators/bundler.d.ts +1 -1
- package/_types/clients/decorators/pimlico.d.ts +3 -3
- package/_types/clients/decorators/smartAccount.d.ts +51 -0
- package/_types/clients/decorators/smartAccount.d.ts.map +1 -1
- package/_types/clients/pimlico.d.ts +1 -1
- package/_types/clients/stackup.d.ts +1 -1
- package/_types/types/index.d.ts +1 -0
- package/_types/types/index.d.ts.map +1 -1
- package/accounts/index.ts +26 -7
- package/accounts/privateKeyToSafeSmartAccount.ts +73 -0
- package/accounts/privateKeyToSimpleSmartAccount.ts +15 -191
- package/accounts/signerToSafeSmartAccount.ts +775 -0
- package/accounts/signerToSimpleSmartAccount.ts +267 -0
- package/accounts/types.ts +43 -12
- package/actions/bundler/chainId.ts +9 -1
- package/actions/bundler/estimateUserOperationGas.ts +8 -3
- package/actions/bundler/getUserOperationByHash.ts +8 -3
- package/actions/bundler/getUserOperationReceipt.ts +16 -3
- package/actions/bundler/sendUserOperation.ts +8 -3
- package/actions/bundler/supportedEntryPoints.ts +8 -3
- package/actions/bundler/waitForUserOperationReceipt.ts +15 -4
- package/actions/pimlico/getUserOperationGasPrice.ts +1 -1
- package/actions/pimlico/getUserOperationStatus.ts +1 -1
- package/actions/smartAccount/prepareUserOperationRequest.ts +3 -1
- package/actions/smartAccount/sendTransaction.ts +3 -1
- package/actions/smartAccount/sendTransactions.ts +141 -0
- package/actions/smartAccount.ts +8 -1
- package/actions/stackup/accounts.ts +1 -1
- package/actions/stackup/sponsorUserOperation.ts +1 -1
- package/clients/decorators/bundler.ts +1 -1
- package/clients/decorators/pimlico.ts +3 -3
- package/clients/decorators/smartAccount.ts +61 -0
- package/clients/pimlico.ts +1 -1
- package/clients/stackup.ts +1 -1
- package/package.json +2 -2
- package/types/index.ts +5 -0
- package/tsconfig.build.tsbuildinfo +0 -1
|
@@ -1,169 +1,18 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { privateKeyToAccount
|
|
3
|
-
import {
|
|
4
|
-
import { getAccountNonce } from "../actions/public/getAccountNonce.js";
|
|
5
|
-
import { getSenderAddress } from "../actions/public/getSenderAddress.js";
|
|
6
|
-
import { getUserOperationHash } from "../utils/getUserOperationHash.js";
|
|
7
|
-
import {} from "./types.js";
|
|
8
|
-
export class SignTransactionNotSupportedBySmartAccount extends BaseError {
|
|
9
|
-
constructor({ docsPath } = {}) {
|
|
10
|
-
super([
|
|
11
|
-
"A smart account cannot sign or send transaction, it can only sign message or userOperation.",
|
|
12
|
-
"Please send user operation instead."
|
|
13
|
-
].join("\n"), {
|
|
14
|
-
docsPath,
|
|
15
|
-
docsSlug: "account"
|
|
16
|
-
});
|
|
17
|
-
Object.defineProperty(this, "name", {
|
|
18
|
-
enumerable: true,
|
|
19
|
-
configurable: true,
|
|
20
|
-
writable: true,
|
|
21
|
-
value: "SignTransactionNotSupportedBySmartAccount"
|
|
22
|
-
});
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
const getAccountInitCode = async (factoryAddress, owner, index = 0n) => {
|
|
26
|
-
if (!owner)
|
|
27
|
-
throw new Error("Owner account not found");
|
|
28
|
-
return concatHex([
|
|
29
|
-
factoryAddress,
|
|
30
|
-
encodeFunctionData({
|
|
31
|
-
abi: [
|
|
32
|
-
{
|
|
33
|
-
inputs: [
|
|
34
|
-
{
|
|
35
|
-
internalType: "address",
|
|
36
|
-
name: "owner",
|
|
37
|
-
type: "address"
|
|
38
|
-
},
|
|
39
|
-
{
|
|
40
|
-
internalType: "uint256",
|
|
41
|
-
name: "salt",
|
|
42
|
-
type: "uint256"
|
|
43
|
-
}
|
|
44
|
-
],
|
|
45
|
-
name: "createAccount",
|
|
46
|
-
outputs: [
|
|
47
|
-
{
|
|
48
|
-
internalType: "contract SimpleAccount",
|
|
49
|
-
name: "ret",
|
|
50
|
-
type: "address"
|
|
51
|
-
}
|
|
52
|
-
],
|
|
53
|
-
stateMutability: "nonpayable",
|
|
54
|
-
type: "function"
|
|
55
|
-
}
|
|
56
|
-
],
|
|
57
|
-
functionName: "createAccount",
|
|
58
|
-
args: [owner, index]
|
|
59
|
-
})
|
|
60
|
-
]);
|
|
61
|
-
};
|
|
62
|
-
const getAccountAddress = async ({ client, factoryAddress, entryPoint, owner }) => {
|
|
63
|
-
const initCode = await getAccountInitCode(factoryAddress, owner);
|
|
64
|
-
return getSenderAddress(client, {
|
|
65
|
-
initCode,
|
|
66
|
-
entryPoint
|
|
67
|
-
});
|
|
68
|
-
};
|
|
1
|
+
import {} from "viem";
|
|
2
|
+
import { privateKeyToAccount } from "viem/accounts";
|
|
3
|
+
import { signerToSimpleSmartAccount } from "./signerToSimpleSmartAccount.js";
|
|
69
4
|
/**
|
|
70
5
|
* @description Creates an Simple Account from a private key.
|
|
71
6
|
*
|
|
72
7
|
* @returns A Private Key Simple Account.
|
|
73
8
|
*/
|
|
74
|
-
export async function privateKeyToSimpleSmartAccount(client, { privateKey, factoryAddress, entryPoint }) {
|
|
9
|
+
export async function privateKeyToSimpleSmartAccount(client, { privateKey, factoryAddress, entryPoint, index = 0n }) {
|
|
75
10
|
const privateKeyAccount = privateKeyToAccount(privateKey);
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
owner: privateKeyAccount.address
|
|
82
|
-
}),
|
|
83
|
-
getChainId(client)
|
|
84
|
-
]);
|
|
85
|
-
if (!accountAddress)
|
|
86
|
-
throw new Error("Account address not found");
|
|
87
|
-
const account = toAccount({
|
|
88
|
-
address: accountAddress,
|
|
89
|
-
async signMessage({ message }) {
|
|
90
|
-
return privateKeyAccount.signMessage({ message });
|
|
91
|
-
},
|
|
92
|
-
async signTransaction(_, __) {
|
|
93
|
-
throw new SignTransactionNotSupportedBySmartAccount();
|
|
94
|
-
},
|
|
95
|
-
async signTypedData(typedData) {
|
|
96
|
-
return privateKeyAccount.signTypedData({ ...typedData, privateKey });
|
|
97
|
-
}
|
|
11
|
+
return signerToSimpleSmartAccount(client, {
|
|
12
|
+
signer: privateKeyAccount,
|
|
13
|
+
factoryAddress,
|
|
14
|
+
entryPoint,
|
|
15
|
+
index
|
|
98
16
|
});
|
|
99
|
-
return {
|
|
100
|
-
...account,
|
|
101
|
-
client: client,
|
|
102
|
-
publicKey: accountAddress,
|
|
103
|
-
entryPoint: entryPoint,
|
|
104
|
-
source: "privateKeySimpleSmartAccount",
|
|
105
|
-
async getNonce() {
|
|
106
|
-
return getAccountNonce(client, {
|
|
107
|
-
sender: accountAddress,
|
|
108
|
-
entryPoint: entryPoint
|
|
109
|
-
});
|
|
110
|
-
},
|
|
111
|
-
async signUserOperation(userOperation) {
|
|
112
|
-
return account.signMessage({
|
|
113
|
-
message: {
|
|
114
|
-
raw: getUserOperationHash({
|
|
115
|
-
userOperation,
|
|
116
|
-
entryPoint: entryPoint,
|
|
117
|
-
chainId: chainId
|
|
118
|
-
})
|
|
119
|
-
}
|
|
120
|
-
});
|
|
121
|
-
},
|
|
122
|
-
async getInitCode() {
|
|
123
|
-
const contractCode = await getBytecode(client, {
|
|
124
|
-
address: accountAddress
|
|
125
|
-
});
|
|
126
|
-
if ((contractCode?.length ?? 0) > 2)
|
|
127
|
-
return "0x";
|
|
128
|
-
return getAccountInitCode(factoryAddress, privateKeyAccount.address);
|
|
129
|
-
},
|
|
130
|
-
async encodeDeployCallData(_) {
|
|
131
|
-
throw new Error("Simple account doesn't support account deployment");
|
|
132
|
-
},
|
|
133
|
-
async encodeCallData({ to, value, data }) {
|
|
134
|
-
return encodeFunctionData({
|
|
135
|
-
abi: [
|
|
136
|
-
{
|
|
137
|
-
inputs: [
|
|
138
|
-
{
|
|
139
|
-
internalType: "address",
|
|
140
|
-
name: "dest",
|
|
141
|
-
type: "address"
|
|
142
|
-
},
|
|
143
|
-
{
|
|
144
|
-
internalType: "uint256",
|
|
145
|
-
name: "value",
|
|
146
|
-
type: "uint256"
|
|
147
|
-
},
|
|
148
|
-
{
|
|
149
|
-
internalType: "bytes",
|
|
150
|
-
name: "func",
|
|
151
|
-
type: "bytes"
|
|
152
|
-
}
|
|
153
|
-
],
|
|
154
|
-
name: "execute",
|
|
155
|
-
outputs: [],
|
|
156
|
-
stateMutability: "nonpayable",
|
|
157
|
-
type: "function"
|
|
158
|
-
}
|
|
159
|
-
],
|
|
160
|
-
functionName: "execute",
|
|
161
|
-
args: [to, value, data]
|
|
162
|
-
});
|
|
163
|
-
},
|
|
164
|
-
async getDummySignature() {
|
|
165
|
-
return "0xfffffffffffffffffffffffffffffff0000000000000000000000000000000007aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1c";
|
|
166
|
-
}
|
|
167
|
-
};
|
|
168
17
|
}
|
|
169
18
|
//# sourceMappingURL=privateKeyToSimpleSmartAccount.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"privateKeyToSimpleSmartAccount.js","sourceRoot":"","sources":["../../accounts/privateKeyToSimpleSmartAccount.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"privateKeyToSimpleSmartAccount.js","sourceRoot":"","sources":["../../accounts/privateKeyToSimpleSmartAccount.ts"],"names":[],"mappings":"AAAA,OAAO,EAMN,MAAM,MAAM,CAAA;AACb,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAA;AACnD,OAAO,EAEH,0BAA0B,EAC7B,MAAM,iCAAiC,CAAA;AAExC;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,8BAA8B,CAIhD,MAAkC,EAClC,EACI,UAAU,EACV,cAAc,EACd,UAAU,EACV,KAAK,GAAG,EAAE,EAMb;IAED,MAAM,iBAAiB,GAAG,mBAAmB,CAAC,UAAU,CAAC,CAAA;IAEzD,OAAO,0BAA0B,CAAC,MAAM,EAAE;QACtC,MAAM,EAAE,iBAAiB;QACzB,cAAc;QACd,UAAU;QACV,KAAK;KACR,CAAC,CAAA;AACN,CAAC"}
|
|
@@ -0,0 +1,499 @@
|
|
|
1
|
+
import { concatHex, encodeFunctionData, encodePacked, getContractAddress, hashMessage, hashTypedData, hexToBigInt, keccak256, toBytes, zeroAddress } from "viem";
|
|
2
|
+
import { toAccount } from "viem/accounts";
|
|
3
|
+
import { getBytecode, getChainId, readContract, signMessage, signTypedData } from "viem/actions";
|
|
4
|
+
import { getAccountNonce } from "../actions/public/getAccountNonce.js";
|
|
5
|
+
import { SignTransactionNotSupportedBySmartAccount } from "./types.js";
|
|
6
|
+
const EIP712_SAFE_OPERATION_TYPE = {
|
|
7
|
+
SafeOp: [
|
|
8
|
+
{ type: "address", name: "safe" },
|
|
9
|
+
{ type: "bytes", name: "callData" },
|
|
10
|
+
{ type: "uint256", name: "nonce" },
|
|
11
|
+
{ type: "uint256", name: "preVerificationGas" },
|
|
12
|
+
{ type: "uint256", name: "verificationGasLimit" },
|
|
13
|
+
{ type: "uint256", name: "callGasLimit" },
|
|
14
|
+
{ type: "uint256", name: "maxFeePerGas" },
|
|
15
|
+
{ type: "uint256", name: "maxPriorityFeePerGas" },
|
|
16
|
+
{ type: "address", name: "entryPoint" }
|
|
17
|
+
]
|
|
18
|
+
};
|
|
19
|
+
const SAFE_VERSION_TO_ADDRESSES_MAP = {
|
|
20
|
+
"1.4.1": {
|
|
21
|
+
ADD_MODULES_LIB_ADDRESS: "0x191EFDC03615B575922289DC339F4c70aC5C30Af",
|
|
22
|
+
SAFE_4337_MODULE_ADDRESS: "0x39E54Bb2b3Aa444b4B39DEe15De3b7809c36Fc38",
|
|
23
|
+
SAFE_PROXY_FACTORY_ADDRESS: "0x4e1DCf7AD4e460CfD30791CCC4F9c8a4f820ec67",
|
|
24
|
+
SAFE_SINGLETON_ADDRESS: "0x41675C099F32341bf84BFc5382aF534df5C7461a",
|
|
25
|
+
MULTI_SEND_ADDRESS: "0x38869bf66a61cF6bDB996A6aE40D5853Fd43B526",
|
|
26
|
+
MULTI_SEND_CALL_ONLY_ADDRESS: "0x9641d764fc13c8B624c04430C7356C1C7C8102e2"
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
const adjustVInSignature = (signingMethod, signature) => {
|
|
30
|
+
const ETHEREUM_V_VALUES = [0, 1, 27, 28];
|
|
31
|
+
const MIN_VALID_V_VALUE_FOR_SAFE_ECDSA = 27;
|
|
32
|
+
let signatureV = parseInt(signature.slice(-2), 16);
|
|
33
|
+
if (!ETHEREUM_V_VALUES.includes(signatureV)) {
|
|
34
|
+
throw new Error("Invalid signature");
|
|
35
|
+
}
|
|
36
|
+
if (signingMethod === "eth_sign") {
|
|
37
|
+
if (signatureV < MIN_VALID_V_VALUE_FOR_SAFE_ECDSA) {
|
|
38
|
+
signatureV += MIN_VALID_V_VALUE_FOR_SAFE_ECDSA;
|
|
39
|
+
}
|
|
40
|
+
signatureV += 4;
|
|
41
|
+
}
|
|
42
|
+
if (signingMethod === "eth_signTypedData") {
|
|
43
|
+
if (signatureV < MIN_VALID_V_VALUE_FOR_SAFE_ECDSA) {
|
|
44
|
+
signatureV += MIN_VALID_V_VALUE_FOR_SAFE_ECDSA;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return (signature.slice(0, -2) + signatureV.toString(16));
|
|
48
|
+
};
|
|
49
|
+
const generateSafeMessageMessage = (message) => {
|
|
50
|
+
const signableMessage = message;
|
|
51
|
+
if (typeof signableMessage === "string" || signableMessage.raw) {
|
|
52
|
+
return hashMessage(signableMessage);
|
|
53
|
+
}
|
|
54
|
+
return hashTypedData(message);
|
|
55
|
+
};
|
|
56
|
+
const encodeInternalTransaction = (tx) => {
|
|
57
|
+
const encoded = encodePacked(["uint8", "address", "uint256", "uint256", "bytes"], [
|
|
58
|
+
tx.operation,
|
|
59
|
+
tx.to,
|
|
60
|
+
tx.value,
|
|
61
|
+
BigInt(tx.data.slice(2).length / 2),
|
|
62
|
+
tx.data
|
|
63
|
+
]);
|
|
64
|
+
return encoded.slice(2);
|
|
65
|
+
};
|
|
66
|
+
const encodeMultiSend = (txs) => {
|
|
67
|
+
const data = `0x${txs
|
|
68
|
+
.map((tx) => encodeInternalTransaction(tx))
|
|
69
|
+
.join("")}`;
|
|
70
|
+
return encodeFunctionData({
|
|
71
|
+
abi: [
|
|
72
|
+
{
|
|
73
|
+
inputs: [
|
|
74
|
+
{
|
|
75
|
+
internalType: "bytes",
|
|
76
|
+
name: "transactions",
|
|
77
|
+
type: "bytes"
|
|
78
|
+
}
|
|
79
|
+
],
|
|
80
|
+
name: "multiSend",
|
|
81
|
+
outputs: [],
|
|
82
|
+
stateMutability: "payable",
|
|
83
|
+
type: "function"
|
|
84
|
+
}
|
|
85
|
+
],
|
|
86
|
+
functionName: "multiSend",
|
|
87
|
+
args: [data]
|
|
88
|
+
});
|
|
89
|
+
};
|
|
90
|
+
const getInitializerCode = async ({ owner, addModuleLibAddress, safe4337ModuleAddress, multiSendAddress, setupTransactions = [], safeModules = [] }) => {
|
|
91
|
+
const multiSendCallData = encodeMultiSend([
|
|
92
|
+
{
|
|
93
|
+
to: addModuleLibAddress,
|
|
94
|
+
data: encodeFunctionData({
|
|
95
|
+
abi: [
|
|
96
|
+
{
|
|
97
|
+
inputs: [
|
|
98
|
+
{
|
|
99
|
+
internalType: "address[]",
|
|
100
|
+
name: "modules",
|
|
101
|
+
type: "address[]"
|
|
102
|
+
}
|
|
103
|
+
],
|
|
104
|
+
name: "enableModules",
|
|
105
|
+
outputs: [],
|
|
106
|
+
stateMutability: "nonpayable",
|
|
107
|
+
type: "function"
|
|
108
|
+
}
|
|
109
|
+
],
|
|
110
|
+
functionName: "enableModules",
|
|
111
|
+
args: [[safe4337ModuleAddress, ...safeModules]]
|
|
112
|
+
}),
|
|
113
|
+
value: 0n,
|
|
114
|
+
operation: 1
|
|
115
|
+
},
|
|
116
|
+
...setupTransactions.map((tx) => ({ ...tx, operation: 0 }))
|
|
117
|
+
]);
|
|
118
|
+
return encodeFunctionData({
|
|
119
|
+
abi: [
|
|
120
|
+
{
|
|
121
|
+
inputs: [
|
|
122
|
+
{
|
|
123
|
+
internalType: "address[]",
|
|
124
|
+
name: "_owners",
|
|
125
|
+
type: "address[]"
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
internalType: "uint256",
|
|
129
|
+
name: "_threshold",
|
|
130
|
+
type: "uint256"
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
internalType: "address",
|
|
134
|
+
name: "to",
|
|
135
|
+
type: "address"
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
internalType: "bytes",
|
|
139
|
+
name: "data",
|
|
140
|
+
type: "bytes"
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
internalType: "address",
|
|
144
|
+
name: "fallbackHandler",
|
|
145
|
+
type: "address"
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
internalType: "address",
|
|
149
|
+
name: "paymentToken",
|
|
150
|
+
type: "address"
|
|
151
|
+
},
|
|
152
|
+
{
|
|
153
|
+
internalType: "uint256",
|
|
154
|
+
name: "payment",
|
|
155
|
+
type: "uint256"
|
|
156
|
+
},
|
|
157
|
+
{
|
|
158
|
+
internalType: "address payable",
|
|
159
|
+
name: "paymentReceiver",
|
|
160
|
+
type: "address"
|
|
161
|
+
}
|
|
162
|
+
],
|
|
163
|
+
name: "setup",
|
|
164
|
+
outputs: [],
|
|
165
|
+
stateMutability: "nonpayable",
|
|
166
|
+
type: "function"
|
|
167
|
+
}
|
|
168
|
+
],
|
|
169
|
+
functionName: "setup",
|
|
170
|
+
args: [
|
|
171
|
+
[owner],
|
|
172
|
+
1n,
|
|
173
|
+
multiSendAddress,
|
|
174
|
+
multiSendCallData,
|
|
175
|
+
safe4337ModuleAddress,
|
|
176
|
+
zeroAddress,
|
|
177
|
+
0n,
|
|
178
|
+
zeroAddress
|
|
179
|
+
]
|
|
180
|
+
});
|
|
181
|
+
};
|
|
182
|
+
const getAccountInitCode = async ({ owner, addModuleLibAddress, safe4337ModuleAddress, safeProxyFactoryAddress, safeSingletonAddress, multiSendAddress, saltNonce = 0n, setupTransactions = [], safeModules = [] }) => {
|
|
183
|
+
if (!owner)
|
|
184
|
+
throw new Error("Owner account not found");
|
|
185
|
+
const initializer = await getInitializerCode({
|
|
186
|
+
owner,
|
|
187
|
+
addModuleLibAddress,
|
|
188
|
+
safe4337ModuleAddress,
|
|
189
|
+
multiSendAddress,
|
|
190
|
+
setupTransactions,
|
|
191
|
+
safeModules
|
|
192
|
+
});
|
|
193
|
+
const initCodeCallData = encodeFunctionData({
|
|
194
|
+
abi: [
|
|
195
|
+
{
|
|
196
|
+
inputs: [
|
|
197
|
+
{
|
|
198
|
+
internalType: "address",
|
|
199
|
+
name: "_singleton",
|
|
200
|
+
type: "address"
|
|
201
|
+
},
|
|
202
|
+
{
|
|
203
|
+
internalType: "bytes",
|
|
204
|
+
name: "initializer",
|
|
205
|
+
type: "bytes"
|
|
206
|
+
},
|
|
207
|
+
{
|
|
208
|
+
internalType: "uint256",
|
|
209
|
+
name: "saltNonce",
|
|
210
|
+
type: "uint256"
|
|
211
|
+
}
|
|
212
|
+
],
|
|
213
|
+
name: "createProxyWithNonce",
|
|
214
|
+
outputs: [
|
|
215
|
+
{
|
|
216
|
+
internalType: "contract SafeProxy",
|
|
217
|
+
name: "proxy",
|
|
218
|
+
type: "address"
|
|
219
|
+
}
|
|
220
|
+
],
|
|
221
|
+
stateMutability: "nonpayable",
|
|
222
|
+
type: "function"
|
|
223
|
+
}
|
|
224
|
+
],
|
|
225
|
+
functionName: "createProxyWithNonce",
|
|
226
|
+
args: [safeSingletonAddress, initializer, saltNonce]
|
|
227
|
+
});
|
|
228
|
+
return concatHex([safeProxyFactoryAddress, initCodeCallData]);
|
|
229
|
+
};
|
|
230
|
+
const getAccountAddress = async ({ client, owner, addModuleLibAddress, safe4337ModuleAddress, safeProxyFactoryAddress, safeSingletonAddress, multiSendAddress, setupTransactions = [], safeModules = [], saltNonce = 0n }) => {
|
|
231
|
+
const proxyCreationCode = await readContract(client, {
|
|
232
|
+
abi: [
|
|
233
|
+
{
|
|
234
|
+
inputs: [],
|
|
235
|
+
name: "proxyCreationCode",
|
|
236
|
+
outputs: [
|
|
237
|
+
{
|
|
238
|
+
internalType: "bytes",
|
|
239
|
+
name: "",
|
|
240
|
+
type: "bytes"
|
|
241
|
+
}
|
|
242
|
+
],
|
|
243
|
+
stateMutability: "pure",
|
|
244
|
+
type: "function"
|
|
245
|
+
}
|
|
246
|
+
],
|
|
247
|
+
address: safeProxyFactoryAddress,
|
|
248
|
+
functionName: "proxyCreationCode"
|
|
249
|
+
});
|
|
250
|
+
const deploymentCode = encodePacked(["bytes", "uint256"], [proxyCreationCode, hexToBigInt(safeSingletonAddress)]);
|
|
251
|
+
const initializer = await getInitializerCode({
|
|
252
|
+
owner,
|
|
253
|
+
addModuleLibAddress,
|
|
254
|
+
safe4337ModuleAddress,
|
|
255
|
+
multiSendAddress,
|
|
256
|
+
setupTransactions,
|
|
257
|
+
safeModules
|
|
258
|
+
});
|
|
259
|
+
const salt = keccak256(encodePacked(["bytes32", "uint256"], [keccak256(encodePacked(["bytes"], [initializer])), saltNonce]));
|
|
260
|
+
return getContractAddress({
|
|
261
|
+
from: safeProxyFactoryAddress,
|
|
262
|
+
salt,
|
|
263
|
+
bytecode: deploymentCode,
|
|
264
|
+
opcode: "CREATE2"
|
|
265
|
+
});
|
|
266
|
+
};
|
|
267
|
+
const getDefaultAddresses = (safeVersion, { addModuleLibAddress: _addModuleLibAddress, safe4337ModuleAddress: _safe4337ModuleAddress, safeProxyFactoryAddress: _safeProxyFactoryAddress, safeSingletonAddress: _safeSingletonAddress, multiSendAddress: _multiSendAddress, multiSendCallOnlyAddress: _multiSendCallOnlyAddress }) => {
|
|
268
|
+
const addModuleLibAddress = _addModuleLibAddress ??
|
|
269
|
+
SAFE_VERSION_TO_ADDRESSES_MAP[safeVersion].ADD_MODULES_LIB_ADDRESS;
|
|
270
|
+
const safe4337ModuleAddress = _safe4337ModuleAddress ??
|
|
271
|
+
SAFE_VERSION_TO_ADDRESSES_MAP[safeVersion].SAFE_4337_MODULE_ADDRESS;
|
|
272
|
+
const safeProxyFactoryAddress = _safeProxyFactoryAddress ??
|
|
273
|
+
SAFE_VERSION_TO_ADDRESSES_MAP[safeVersion].SAFE_PROXY_FACTORY_ADDRESS;
|
|
274
|
+
const safeSingletonAddress = _safeSingletonAddress ??
|
|
275
|
+
SAFE_VERSION_TO_ADDRESSES_MAP[safeVersion].SAFE_SINGLETON_ADDRESS;
|
|
276
|
+
const multiSendAddress = _multiSendAddress ??
|
|
277
|
+
SAFE_VERSION_TO_ADDRESSES_MAP[safeVersion].MULTI_SEND_ADDRESS;
|
|
278
|
+
const multiSendCallOnlyAddress = _multiSendCallOnlyAddress ??
|
|
279
|
+
SAFE_VERSION_TO_ADDRESSES_MAP[safeVersion].MULTI_SEND_CALL_ONLY_ADDRESS;
|
|
280
|
+
return {
|
|
281
|
+
addModuleLibAddress,
|
|
282
|
+
safe4337ModuleAddress,
|
|
283
|
+
safeProxyFactoryAddress,
|
|
284
|
+
safeSingletonAddress,
|
|
285
|
+
multiSendAddress,
|
|
286
|
+
multiSendCallOnlyAddress
|
|
287
|
+
};
|
|
288
|
+
};
|
|
289
|
+
/**
|
|
290
|
+
* @description Creates an Simple Account from a private key.
|
|
291
|
+
*
|
|
292
|
+
* @returns A Private Key Simple Account.
|
|
293
|
+
*/
|
|
294
|
+
export async function signerToSafeSmartAccount(client, { signer, safeVersion, entryPoint, addModuleLibAddress: _addModuleLibAddress, safe4337ModuleAddress: _safe4337ModuleAddress, safeProxyFactoryAddress: _safeProxyFactoryAddress, safeSingletonAddress: _safeSingletonAddress, multiSendAddress: _multiSendAddress, multiSendCallOnlyAddress: _multiSendCallOnlyAddress, saltNonce = 0n, safeModules = [], setupTransactions = [] }) {
|
|
295
|
+
const chainId = await getChainId(client);
|
|
296
|
+
const viemSigner = signer.type === "local"
|
|
297
|
+
? {
|
|
298
|
+
...signer,
|
|
299
|
+
signTransaction: (_, __) => {
|
|
300
|
+
throw new SignTransactionNotSupportedBySmartAccount();
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
: signer;
|
|
304
|
+
const { addModuleLibAddress, safe4337ModuleAddress, safeProxyFactoryAddress, safeSingletonAddress, multiSendAddress, multiSendCallOnlyAddress } = getDefaultAddresses(safeVersion, {
|
|
305
|
+
addModuleLibAddress: _addModuleLibAddress,
|
|
306
|
+
safe4337ModuleAddress: _safe4337ModuleAddress,
|
|
307
|
+
safeProxyFactoryAddress: _safeProxyFactoryAddress,
|
|
308
|
+
safeSingletonAddress: _safeSingletonAddress,
|
|
309
|
+
multiSendAddress: _multiSendAddress,
|
|
310
|
+
multiSendCallOnlyAddress: _multiSendCallOnlyAddress
|
|
311
|
+
});
|
|
312
|
+
const accountAddress = await getAccountAddress({
|
|
313
|
+
client,
|
|
314
|
+
owner: viemSigner.address,
|
|
315
|
+
addModuleLibAddress,
|
|
316
|
+
safe4337ModuleAddress,
|
|
317
|
+
safeProxyFactoryAddress,
|
|
318
|
+
safeSingletonAddress,
|
|
319
|
+
multiSendAddress,
|
|
320
|
+
saltNonce,
|
|
321
|
+
setupTransactions,
|
|
322
|
+
safeModules
|
|
323
|
+
});
|
|
324
|
+
if (!accountAddress)
|
|
325
|
+
throw new Error("Account address not found");
|
|
326
|
+
const account = toAccount({
|
|
327
|
+
address: accountAddress,
|
|
328
|
+
async signMessage({ message }) {
|
|
329
|
+
const messageHash = hashTypedData({
|
|
330
|
+
domain: {
|
|
331
|
+
chainId: chainId,
|
|
332
|
+
verifyingContract: accountAddress
|
|
333
|
+
},
|
|
334
|
+
types: {
|
|
335
|
+
SafeMessage: [{ name: "message", type: "bytes" }]
|
|
336
|
+
},
|
|
337
|
+
primaryType: "SafeMessage",
|
|
338
|
+
message: {
|
|
339
|
+
message: generateSafeMessageMessage(message)
|
|
340
|
+
}
|
|
341
|
+
});
|
|
342
|
+
return adjustVInSignature("eth_sign", await signMessage(client, {
|
|
343
|
+
account: viemSigner,
|
|
344
|
+
message: {
|
|
345
|
+
raw: toBytes(messageHash)
|
|
346
|
+
}
|
|
347
|
+
}));
|
|
348
|
+
},
|
|
349
|
+
async signTransaction(_, __) {
|
|
350
|
+
throw new SignTransactionNotSupportedBySmartAccount();
|
|
351
|
+
},
|
|
352
|
+
async signTypedData(typedData) {
|
|
353
|
+
return adjustVInSignature("eth_signTypedData", await signTypedData(client, {
|
|
354
|
+
account: viemSigner,
|
|
355
|
+
domain: {
|
|
356
|
+
chainId: chainId,
|
|
357
|
+
verifyingContract: accountAddress
|
|
358
|
+
},
|
|
359
|
+
types: {
|
|
360
|
+
SafeMessage: [{ name: "message", type: "bytes" }]
|
|
361
|
+
},
|
|
362
|
+
primaryType: "SafeMessage",
|
|
363
|
+
message: {
|
|
364
|
+
message: generateSafeMessageMessage(typedData)
|
|
365
|
+
}
|
|
366
|
+
}));
|
|
367
|
+
}
|
|
368
|
+
});
|
|
369
|
+
return {
|
|
370
|
+
...account,
|
|
371
|
+
client: client,
|
|
372
|
+
publicKey: accountAddress,
|
|
373
|
+
entryPoint: entryPoint,
|
|
374
|
+
source: "SafeSmartAccount",
|
|
375
|
+
async getNonce() {
|
|
376
|
+
return getAccountNonce(client, {
|
|
377
|
+
sender: accountAddress,
|
|
378
|
+
entryPoint: entryPoint
|
|
379
|
+
});
|
|
380
|
+
},
|
|
381
|
+
async signUserOperation(userOperation) {
|
|
382
|
+
// const timestamps = 0n
|
|
383
|
+
const signatures = [
|
|
384
|
+
{
|
|
385
|
+
signer: viemSigner.address,
|
|
386
|
+
data: await signTypedData(client, {
|
|
387
|
+
account: viemSigner,
|
|
388
|
+
domain: {
|
|
389
|
+
chainId: chainId,
|
|
390
|
+
verifyingContract: safe4337ModuleAddress
|
|
391
|
+
},
|
|
392
|
+
types: EIP712_SAFE_OPERATION_TYPE,
|
|
393
|
+
primaryType: "SafeOp",
|
|
394
|
+
message: {
|
|
395
|
+
safe: accountAddress,
|
|
396
|
+
callData: userOperation.callData,
|
|
397
|
+
nonce: userOperation.nonce,
|
|
398
|
+
preVerificationGas: userOperation.preVerificationGas,
|
|
399
|
+
verificationGasLimit: userOperation.verificationGasLimit,
|
|
400
|
+
callGasLimit: userOperation.callGasLimit,
|
|
401
|
+
maxFeePerGas: userOperation.maxFeePerGas,
|
|
402
|
+
maxPriorityFeePerGas: userOperation.maxPriorityFeePerGas,
|
|
403
|
+
// signatureTimestamps: timestamps,
|
|
404
|
+
entryPoint: entryPoint
|
|
405
|
+
}
|
|
406
|
+
})
|
|
407
|
+
}
|
|
408
|
+
];
|
|
409
|
+
signatures.sort((left, right) => left.signer
|
|
410
|
+
.toLowerCase()
|
|
411
|
+
.localeCompare(right.signer.toLowerCase()));
|
|
412
|
+
let signatureBytes = "0x";
|
|
413
|
+
for (const sig of signatures) {
|
|
414
|
+
signatureBytes += sig.data.slice(2);
|
|
415
|
+
}
|
|
416
|
+
// const signatureWithTimestamps = encodePacked(
|
|
417
|
+
// ["uint96", "bytes"],
|
|
418
|
+
// [timestamps, signatureBytes]
|
|
419
|
+
// )
|
|
420
|
+
return signatureBytes;
|
|
421
|
+
},
|
|
422
|
+
async getInitCode() {
|
|
423
|
+
const contractCode = await getBytecode(client, {
|
|
424
|
+
address: accountAddress
|
|
425
|
+
});
|
|
426
|
+
if ((contractCode?.length ?? 0) > 2)
|
|
427
|
+
return "0x";
|
|
428
|
+
return getAccountInitCode({
|
|
429
|
+
owner: viemSigner.address,
|
|
430
|
+
addModuleLibAddress,
|
|
431
|
+
safe4337ModuleAddress,
|
|
432
|
+
safeProxyFactoryAddress,
|
|
433
|
+
safeSingletonAddress,
|
|
434
|
+
multiSendAddress,
|
|
435
|
+
saltNonce,
|
|
436
|
+
setupTransactions,
|
|
437
|
+
safeModules
|
|
438
|
+
});
|
|
439
|
+
},
|
|
440
|
+
async encodeDeployCallData(_) {
|
|
441
|
+
throw new Error("Safe account doesn't support account deployment");
|
|
442
|
+
},
|
|
443
|
+
async encodeCallData(args) {
|
|
444
|
+
let to;
|
|
445
|
+
let value;
|
|
446
|
+
let data;
|
|
447
|
+
if (Array.isArray(args)) {
|
|
448
|
+
const argsArray = args;
|
|
449
|
+
to = multiSendCallOnlyAddress;
|
|
450
|
+
value = 0n;
|
|
451
|
+
data = encodeMultiSend(argsArray.map((tx) => ({ ...tx, operation: 0 })));
|
|
452
|
+
}
|
|
453
|
+
else {
|
|
454
|
+
const singleTransaction = args;
|
|
455
|
+
to = singleTransaction.to;
|
|
456
|
+
data = singleTransaction.data;
|
|
457
|
+
value = singleTransaction.value;
|
|
458
|
+
}
|
|
459
|
+
return encodeFunctionData({
|
|
460
|
+
abi: [
|
|
461
|
+
{
|
|
462
|
+
inputs: [
|
|
463
|
+
{
|
|
464
|
+
internalType: "address",
|
|
465
|
+
name: "to",
|
|
466
|
+
type: "address"
|
|
467
|
+
},
|
|
468
|
+
{
|
|
469
|
+
internalType: "uint256",
|
|
470
|
+
name: "value",
|
|
471
|
+
type: "uint256"
|
|
472
|
+
},
|
|
473
|
+
{
|
|
474
|
+
internalType: "bytes",
|
|
475
|
+
name: "data",
|
|
476
|
+
type: "bytes"
|
|
477
|
+
},
|
|
478
|
+
{
|
|
479
|
+
internalType: "uint8",
|
|
480
|
+
name: "operation",
|
|
481
|
+
type: "uint8"
|
|
482
|
+
}
|
|
483
|
+
],
|
|
484
|
+
name: "executeUserOp",
|
|
485
|
+
outputs: [],
|
|
486
|
+
stateMutability: "nonpayable",
|
|
487
|
+
type: "function"
|
|
488
|
+
}
|
|
489
|
+
],
|
|
490
|
+
functionName: "executeUserOp",
|
|
491
|
+
args: [to, value, data, 0]
|
|
492
|
+
});
|
|
493
|
+
},
|
|
494
|
+
async getDummySignature() {
|
|
495
|
+
return "0xfffffffffffffffffffffffffffffff0000000000000000000000000000000007aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1c";
|
|
496
|
+
}
|
|
497
|
+
};
|
|
498
|
+
}
|
|
499
|
+
//# sourceMappingURL=signerToSafeSmartAccount.js.map
|