@safe-global/protocol-kit 2.0.1-alpha.0 → 3.0.0
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/README.md +7 -4
- package/dist/src/Safe.d.ts +57 -7
- package/dist/src/Safe.js +218 -35
- package/dist/src/Safe.js.map +1 -1
- package/dist/src/adapters/ethers/EthersAdapter.d.ts +2 -2
- package/dist/src/adapters/ethers/EthersAdapter.js +5 -3
- package/dist/src/adapters/ethers/EthersAdapter.js.map +1 -1
- package/dist/src/adapters/web3/Web3Adapter.d.ts +2 -2
- package/dist/src/adapters/web3/Web3Adapter.js +6 -5
- package/dist/src/adapters/web3/Web3Adapter.js.map +1 -1
- package/dist/src/index.d.ts +5 -3
- package/dist/src/index.js +17 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/types/index.d.ts +8 -0
- package/dist/src/types/index.js +9 -0
- package/dist/src/types/index.js.map +1 -1
- package/dist/src/utils/eip-3770/config.js +14 -1
- package/dist/src/utils/eip-3770/config.js.map +1 -1
- package/dist/src/utils/eip-712/index.d.ts +6 -9
- package/dist/src/utils/eip-712/index.js +57 -18
- package/dist/src/utils/eip-712/index.js.map +1 -1
- package/dist/src/utils/messages/SafeMessage.d.ts +10 -0
- package/dist/src/utils/messages/SafeMessage.js +20 -0
- package/dist/src/utils/messages/SafeMessage.js.map +1 -0
- package/dist/src/utils/signatures/SafeSignature.d.ts +3 -2
- package/dist/src/utils/signatures/SafeSignature.js +10 -2
- package/dist/src/utils/signatures/SafeSignature.js.map +1 -1
- package/dist/src/utils/signatures/utils.d.ts +11 -4
- package/dist/src/utils/signatures/utils.js +75 -7
- package/dist/src/utils/signatures/utils.js.map +1 -1
- package/dist/src/utils/transactions/SafeTransaction.d.ts +1 -0
- package/dist/src/utils/transactions/SafeTransaction.js +5 -10
- package/dist/src/utils/transactions/SafeTransaction.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +3 -5
package/README.md
CHANGED
|
@@ -627,7 +627,7 @@ const safeTransaction = await safeSdk.createTransaction({ transactions })
|
|
|
627
627
|
const txHash = await safeSdk.getTransactionHash(safeTransaction)
|
|
628
628
|
```
|
|
629
629
|
|
|
630
|
-
###
|
|
630
|
+
### signHash
|
|
631
631
|
|
|
632
632
|
Signs a hash using the current owner account.
|
|
633
633
|
|
|
@@ -639,7 +639,7 @@ const transactions: MetaTransactionData[] = [
|
|
|
639
639
|
]
|
|
640
640
|
const safeTransaction = await safeSdk.createTransaction({ transactions })
|
|
641
641
|
const txHash = await safeSdk.getTransactionHash(safeTransaction)
|
|
642
|
-
const signature = await safeSdk.
|
|
642
|
+
const signature = await safeSdk.signHash(txHash)
|
|
643
643
|
```
|
|
644
644
|
|
|
645
645
|
### signTypedData
|
|
@@ -673,11 +673,14 @@ const signedSafeTransaction = await safeSdk.signTransaction(safeTransaction)
|
|
|
673
673
|
Optionally, an additional parameter can be passed to specify a different way of signing:
|
|
674
674
|
|
|
675
675
|
```js
|
|
676
|
-
const signedSafeTransaction = await safeSdk.signTransaction(
|
|
676
|
+
const signedSafeTransaction = await safeSdk.signTransaction(
|
|
677
|
+
safeTransaction,
|
|
678
|
+
SigningMethod.ETH_SIGN_TYPED_DATA
|
|
679
|
+
)
|
|
677
680
|
```
|
|
678
681
|
|
|
679
682
|
```js
|
|
680
|
-
const signedSafeTransaction = await safeSdk.signTransaction(safeTransaction,
|
|
683
|
+
const signedSafeTransaction = await safeSdk.signTransaction(safeTransaction, SigningMethod.ETH_SIGN) // default option.
|
|
681
684
|
```
|
|
682
685
|
|
|
683
686
|
### approveTransactionHash
|
package/dist/src/Safe.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { EthAdapter, SafeMultisigTransactionResponse, SafeSignature, SafeTransaction, SafeVersion, TransactionOptions, TransactionResult, MetaTransactionData, Transaction } from '@safe-global/safe-core-sdk-types';
|
|
1
|
+
import { EthAdapter, SafeMultisigTransactionResponse, SafeSignature, SafeTransaction, SafeVersion, TransactionOptions, TransactionResult, MetaTransactionData, Transaction, EIP712TypedData } from '@safe-global/safe-core-sdk-types';
|
|
2
2
|
import ContractManager from './managers/contractManager';
|
|
3
|
-
import { AddOwnerTxParams, ConnectSafeConfig, CreateTransactionProps, RemoveOwnerTxParams, SafeConfig, SwapOwnerTxParams } from './types';
|
|
3
|
+
import { AddOwnerTxParams, ConnectSafeConfig, CreateTransactionProps, RemoveOwnerTxParams, SafeConfig, SigningMethodType, SwapOwnerTxParams } from './types';
|
|
4
4
|
import { SafeTransactionOptionalProps } from './utils/transactions/types';
|
|
5
|
+
import SafeMessage from './utils/messages/SafeMessage';
|
|
5
6
|
declare class Safe {
|
|
6
7
|
#private;
|
|
7
8
|
/**
|
|
@@ -163,7 +164,7 @@ declare class Safe {
|
|
|
163
164
|
* Returns the transaction hash of a Safe transaction.
|
|
164
165
|
*
|
|
165
166
|
* @param safeTransaction - The Safe transaction
|
|
166
|
-
* @returns The
|
|
167
|
+
* @returns The hash of the Safe transaction
|
|
167
168
|
*/
|
|
168
169
|
getTransactionHash(safeTransaction: SafeTransaction): Promise<string>;
|
|
169
170
|
/**
|
|
@@ -172,24 +173,47 @@ declare class Safe {
|
|
|
172
173
|
* @param hash - The hash to sign
|
|
173
174
|
* @returns The Safe signature
|
|
174
175
|
*/
|
|
175
|
-
|
|
176
|
+
signHash(hash: string): Promise<SafeSignature>;
|
|
177
|
+
/**
|
|
178
|
+
* Returns a Safe message ready to be signed by the owners.
|
|
179
|
+
*
|
|
180
|
+
* @param message - The message
|
|
181
|
+
* @returns The Safe message
|
|
182
|
+
*/
|
|
183
|
+
createMessage(message: string | EIP712TypedData): SafeMessage;
|
|
184
|
+
/**
|
|
185
|
+
* Returns the Safe message with a new signature
|
|
186
|
+
*
|
|
187
|
+
* @param message The message to be signed
|
|
188
|
+
* @param signingMethod The signature type
|
|
189
|
+
* @param preimageSafeAddress If the preimage is required, the address of the Safe that will be used to calculate the preimage.
|
|
190
|
+
* This field is mandatory for 1.4.1 contract versions Because the safe uses the old EIP-1271 interface which uses `bytes` instead of `bytes32` for the message
|
|
191
|
+
* we need to use the pre-image of the message to calculate the message hash
|
|
192
|
+
* https://github.com/safe-global/safe-contracts/blob/192c7dc67290940fcbc75165522bb86a37187069/test/core/Safe.Signatures.spec.ts#L229-L233
|
|
193
|
+
* @returns The signed Safe message
|
|
194
|
+
*/
|
|
195
|
+
signMessage(message: SafeMessage, signingMethod?: SigningMethodType, preimageSafeAddress?: string): Promise<SafeMessage>;
|
|
176
196
|
/**
|
|
177
197
|
* Signs a transaction according to the EIP-712 using the current signer account.
|
|
178
198
|
*
|
|
179
|
-
* @param
|
|
199
|
+
* @param eip712Data - The Safe Transaction or message hash to be signed
|
|
180
200
|
* @param methodVersion - EIP-712 version. Optional
|
|
181
201
|
* @returns The Safe signature
|
|
182
202
|
*/
|
|
183
|
-
signTypedData(
|
|
203
|
+
signTypedData(eip712Data: SafeTransaction | SafeMessage, methodVersion?: 'v3' | 'v4'): Promise<SafeSignature>;
|
|
184
204
|
/**
|
|
185
205
|
* Adds the signature of the current signer to the Safe transaction object.
|
|
186
206
|
*
|
|
187
207
|
* @param safeTransaction - The Safe transaction to be signed
|
|
188
208
|
* @param signingMethod - Method followed to sign a transaction. Optional. Default value is "eth_sign"
|
|
209
|
+
* @param preimageSafeAddress - If the preimage is required, the address of the Safe that will be used to calculate the preimage
|
|
210
|
+
* This field is mandatory for 1.3.0 and 1.4.1 contract versions Because the safe uses the old EIP-1271 interface which uses `bytes` instead of `bytes32` for the message
|
|
211
|
+
* we need to use the pre-image of the message to calculate the message hash
|
|
212
|
+
* https://github.com/safe-global/safe-contracts/blob/192c7dc67290940fcbc75165522bb86a37187069/test/core/Safe.Signatures.spec.ts#L229-L233
|
|
189
213
|
* @returns The signed Safe transaction
|
|
190
214
|
* @throws "Transactions can only be signed by Safe owners"
|
|
191
215
|
*/
|
|
192
|
-
signTransaction(safeTransaction: SafeTransaction | SafeMultisigTransactionResponse, signingMethod?:
|
|
216
|
+
signTransaction(safeTransaction: SafeTransaction | SafeMultisigTransactionResponse, signingMethod?: SigningMethodType, preimageSafeAddress?: string): Promise<SafeTransaction>;
|
|
193
217
|
/**
|
|
194
218
|
* Approves on-chain a hash using the current signer account.
|
|
195
219
|
*
|
|
@@ -389,5 +413,31 @@ declare class Safe {
|
|
|
389
413
|
*
|
|
390
414
|
*/
|
|
391
415
|
createTransactionBatch(transactions: MetaTransactionData[], transactionOptions?: TransactionOptions): Promise<Transaction>;
|
|
416
|
+
/**
|
|
417
|
+
* Get the fallback handler contract
|
|
418
|
+
*
|
|
419
|
+
* @returns The fallback Handler contract
|
|
420
|
+
*/
|
|
421
|
+
private getFallbackHandlerContract;
|
|
422
|
+
/**
|
|
423
|
+
* Call the CompatibilityFallbackHandler getMessageHash method
|
|
424
|
+
*
|
|
425
|
+
* @param messageHash The hash of the message
|
|
426
|
+
* @returns Returns the Safe message hash to be signed
|
|
427
|
+
* @link https://github.com/safe-global/safe-contracts/blob/8ffae95faa815acf86ec8b50021ebe9f96abde10/contracts/handler/CompatibilityFallbackHandler.sol#L26-L28
|
|
428
|
+
*/
|
|
429
|
+
getSafeMessageHash: (messageHash: string) => Promise<string>;
|
|
430
|
+
/**
|
|
431
|
+
* Call the CompatibilityFallbackHandler isValidSignature method
|
|
432
|
+
*
|
|
433
|
+
* @param messageHash The hash of the message
|
|
434
|
+
* @param signature The signature to be validated or '0x'. You can send as signature one of the following:
|
|
435
|
+
* 1) An array of SafeSignature. In this case the signatures are concatenated for validation (buildSignatureBytes())
|
|
436
|
+
* 2) The concatenated signatures as string
|
|
437
|
+
* 3) '0x' if you want to validate an onchain message (Approved hash)
|
|
438
|
+
* @returns A boolean indicating if the signature is valid
|
|
439
|
+
* @link https://github.com/safe-global/safe-contracts/blob/main/contracts/handler/CompatibilityFallbackHandler.sol
|
|
440
|
+
*/
|
|
441
|
+
isValidSignature: (messageHash: string, signature?: SafeSignature[] | string) => Promise<boolean>;
|
|
392
442
|
}
|
|
393
443
|
export default Safe;
|
package/dist/src/Safe.js
CHANGED
|
@@ -13,7 +13,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
|
|
|
13
13
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
14
14
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
15
15
|
};
|
|
16
|
-
var _Safe_predictedSafe, _Safe_ethAdapter, _Safe_contractManager, _Safe_ownerManager, _Safe_moduleManager, _Safe_guardManager, _Safe_fallbackHandlerManager;
|
|
16
|
+
var _Safe_predictedSafe, _Safe_ethAdapter, _Safe_contractManager, _Safe_ownerManager, _Safe_moduleManager, _Safe_guardManager, _Safe_fallbackHandlerManager, _Safe_MAGIC_VALUE, _Safe_MAGIC_VALUE_BYTES;
|
|
17
17
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
18
|
const safe_core_sdk_types_1 = require("@safe-global/safe-core-sdk-types");
|
|
19
19
|
const utils_1 = require("./contracts/utils");
|
|
@@ -23,12 +23,16 @@ const fallbackHandlerManager_1 = __importDefault(require("./managers/fallbackHan
|
|
|
23
23
|
const guardManager_1 = __importDefault(require("./managers/guardManager"));
|
|
24
24
|
const moduleManager_1 = __importDefault(require("./managers/moduleManager"));
|
|
25
25
|
const ownerManager_1 = __importDefault(require("./managers/ownerManager"));
|
|
26
|
+
const types_1 = require("./types");
|
|
26
27
|
const utils_2 = require("./utils");
|
|
27
|
-
const utils_3 = require("./utils/signatures/utils");
|
|
28
28
|
const SafeTransaction_1 = __importDefault(require("./utils/transactions/SafeTransaction"));
|
|
29
|
-
const
|
|
30
|
-
const
|
|
29
|
+
const utils_3 = require("./utils/transactions/utils");
|
|
30
|
+
const types_2 = require("./utils/types");
|
|
31
31
|
const safeDeploymentContracts_1 = require("./contracts/safeDeploymentContracts");
|
|
32
|
+
const SafeMessage_1 = __importDefault(require("./utils/messages/SafeMessage"));
|
|
33
|
+
const satisfies_1 = __importDefault(require("semver/functions/satisfies"));
|
|
34
|
+
const EQ_OR_GT_1_4_1 = '>=1.4.1';
|
|
35
|
+
const EQ_OR_GT_1_3_0 = '>=1.3.0';
|
|
32
36
|
class Safe {
|
|
33
37
|
constructor() {
|
|
34
38
|
_Safe_predictedSafe.set(this, void 0);
|
|
@@ -38,6 +42,75 @@ class Safe {
|
|
|
38
42
|
_Safe_moduleManager.set(this, void 0);
|
|
39
43
|
_Safe_guardManager.set(this, void 0);
|
|
40
44
|
_Safe_fallbackHandlerManager.set(this, void 0);
|
|
45
|
+
_Safe_MAGIC_VALUE.set(this, '0x1626ba7e');
|
|
46
|
+
_Safe_MAGIC_VALUE_BYTES.set(this, '0x20c13b0b'
|
|
47
|
+
/**
|
|
48
|
+
* Creates an instance of the Safe Core SDK.
|
|
49
|
+
* @param config - Ethers Safe configuration
|
|
50
|
+
* @returns The Safe Core SDK instance
|
|
51
|
+
* @throws "The SDK must be initialized with a safeAddress or a predictedSafe"
|
|
52
|
+
* @throws "SafeProxy contract is not deployed on the current network"
|
|
53
|
+
* @throws "MultiSend contract is not deployed on the current network"
|
|
54
|
+
* @throws "MultiSendCallOnly contract is not deployed on the current network"
|
|
55
|
+
*/
|
|
56
|
+
);
|
|
57
|
+
/**
|
|
58
|
+
* Call the CompatibilityFallbackHandler getMessageHash method
|
|
59
|
+
*
|
|
60
|
+
* @param messageHash The hash of the message
|
|
61
|
+
* @returns Returns the Safe message hash to be signed
|
|
62
|
+
* @link https://github.com/safe-global/safe-contracts/blob/8ffae95faa815acf86ec8b50021ebe9f96abde10/contracts/handler/CompatibilityFallbackHandler.sol#L26-L28
|
|
63
|
+
*/
|
|
64
|
+
this.getSafeMessageHash = async (messageHash) => {
|
|
65
|
+
const safeAddress = await this.getAddress();
|
|
66
|
+
const safeVersion = await this.getContractVersion();
|
|
67
|
+
const chainId = await this.getChainId();
|
|
68
|
+
return (0, utils_2.calculateSafeMessageHash)(safeAddress, messageHash, safeVersion, chainId);
|
|
69
|
+
};
|
|
70
|
+
/**
|
|
71
|
+
* Call the CompatibilityFallbackHandler isValidSignature method
|
|
72
|
+
*
|
|
73
|
+
* @param messageHash The hash of the message
|
|
74
|
+
* @param signature The signature to be validated or '0x'. You can send as signature one of the following:
|
|
75
|
+
* 1) An array of SafeSignature. In this case the signatures are concatenated for validation (buildSignatureBytes())
|
|
76
|
+
* 2) The concatenated signatures as string
|
|
77
|
+
* 3) '0x' if you want to validate an onchain message (Approved hash)
|
|
78
|
+
* @returns A boolean indicating if the signature is valid
|
|
79
|
+
* @link https://github.com/safe-global/safe-contracts/blob/main/contracts/handler/CompatibilityFallbackHandler.sol
|
|
80
|
+
*/
|
|
81
|
+
this.isValidSignature = async (messageHash, signature = '0x') => {
|
|
82
|
+
const safeAddress = await this.getAddress();
|
|
83
|
+
const fallbackHandler = await this.getFallbackHandlerContract();
|
|
84
|
+
const signatureToCheck = signature && Array.isArray(signature) ? (0, utils_2.buildSignatureBytes)(signature) : signature;
|
|
85
|
+
const data = fallbackHandler.encode('isValidSignature(bytes32,bytes)', [
|
|
86
|
+
messageHash,
|
|
87
|
+
signatureToCheck
|
|
88
|
+
]);
|
|
89
|
+
const bytesData = fallbackHandler.encode('isValidSignature(bytes,bytes)', [
|
|
90
|
+
messageHash,
|
|
91
|
+
signatureToCheck
|
|
92
|
+
]);
|
|
93
|
+
try {
|
|
94
|
+
const isValidSignatureResponse = await Promise.all([
|
|
95
|
+
__classPrivateFieldGet(this, _Safe_ethAdapter, "f").call({
|
|
96
|
+
from: safeAddress,
|
|
97
|
+
to: safeAddress,
|
|
98
|
+
data: data
|
|
99
|
+
}),
|
|
100
|
+
__classPrivateFieldGet(this, _Safe_ethAdapter, "f").call({
|
|
101
|
+
from: safeAddress,
|
|
102
|
+
to: safeAddress,
|
|
103
|
+
data: bytesData
|
|
104
|
+
})
|
|
105
|
+
]);
|
|
106
|
+
return (!!isValidSignatureResponse.length &&
|
|
107
|
+
(isValidSignatureResponse[0].slice(0, 10).toLowerCase() === __classPrivateFieldGet(this, _Safe_MAGIC_VALUE, "f") ||
|
|
108
|
+
isValidSignatureResponse[1].slice(0, 10).toLowerCase() === __classPrivateFieldGet(this, _Safe_MAGIC_VALUE_BYTES, "f")));
|
|
109
|
+
}
|
|
110
|
+
catch (error) {
|
|
111
|
+
return false;
|
|
112
|
+
}
|
|
113
|
+
};
|
|
41
114
|
}
|
|
42
115
|
/**
|
|
43
116
|
* Creates an instance of the Safe Core SDK.
|
|
@@ -64,7 +137,7 @@ class Safe {
|
|
|
64
137
|
async init(config) {
|
|
65
138
|
const { ethAdapter, isL1SafeSingleton, contractNetworks } = config;
|
|
66
139
|
__classPrivateFieldSet(this, _Safe_ethAdapter, ethAdapter, "f");
|
|
67
|
-
if ((0,
|
|
140
|
+
if ((0, types_2.isSafeConfigWithPredictedSafe)(config)) {
|
|
68
141
|
__classPrivateFieldSet(this, _Safe_predictedSafe, config.predictedSafe, "f");
|
|
69
142
|
__classPrivateFieldSet(this, _Safe_contractManager, await contractManager_1.default.create({
|
|
70
143
|
ethAdapter: __classPrivateFieldGet(this, _Safe_ethAdapter, "f"),
|
|
@@ -323,7 +396,7 @@ class Safe {
|
|
|
323
396
|
const multiSendContract = onlyCalls
|
|
324
397
|
? __classPrivateFieldGet(this, _Safe_contractManager, "f").multiSendCallOnlyContract
|
|
325
398
|
: __classPrivateFieldGet(this, _Safe_contractManager, "f").multiSendContract;
|
|
326
|
-
const multiSendData = (0,
|
|
399
|
+
const multiSendData = (0, utils_3.encodeMultiSendData)(transactions.map(utils_3.standardizeMetaTransactionData));
|
|
327
400
|
const multiSendTransaction = {
|
|
328
401
|
...options,
|
|
329
402
|
to: await multiSendContract.getAddress(),
|
|
@@ -337,7 +410,7 @@ class Safe {
|
|
|
337
410
|
newTransaction = { ...options, ...transactions[0] };
|
|
338
411
|
}
|
|
339
412
|
if (__classPrivateFieldGet(this, _Safe_predictedSafe, "f")) {
|
|
340
|
-
return new SafeTransaction_1.default(await (0,
|
|
413
|
+
return new SafeTransaction_1.default(await (0, utils_3.standardizeSafeTransactionData)({
|
|
341
414
|
predictedSafe: __classPrivateFieldGet(this, _Safe_predictedSafe, "f"),
|
|
342
415
|
ethAdapter: __classPrivateFieldGet(this, _Safe_ethAdapter, "f"),
|
|
343
416
|
tx: newTransaction,
|
|
@@ -347,7 +420,7 @@ class Safe {
|
|
|
347
420
|
if (!__classPrivateFieldGet(this, _Safe_contractManager, "f").safeContract) {
|
|
348
421
|
throw new Error('Safe is not deployed');
|
|
349
422
|
}
|
|
350
|
-
return new SafeTransaction_1.default(await (0,
|
|
423
|
+
return new SafeTransaction_1.default(await (0, utils_3.standardizeSafeTransactionData)({
|
|
351
424
|
safeContract: __classPrivateFieldGet(this, _Safe_contractManager, "f").safeContract,
|
|
352
425
|
ethAdapter: __classPrivateFieldGet(this, _Safe_ethAdapter, "f"),
|
|
353
426
|
tx: newTransaction,
|
|
@@ -399,15 +472,13 @@ class Safe {
|
|
|
399
472
|
* Returns the transaction hash of a Safe transaction.
|
|
400
473
|
*
|
|
401
474
|
* @param safeTransaction - The Safe transaction
|
|
402
|
-
* @returns The
|
|
475
|
+
* @returns The hash of the Safe transaction
|
|
403
476
|
*/
|
|
404
477
|
async getTransactionHash(safeTransaction) {
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
const txHash = await __classPrivateFieldGet(this, _Safe_contractManager, "f").safeContract.getTransactionHash(safeTransactionData);
|
|
410
|
-
return txHash;
|
|
478
|
+
const safeAddress = await this.getAddress();
|
|
479
|
+
const safeVersion = await this.getContractVersion();
|
|
480
|
+
const chainId = await this.getChainId();
|
|
481
|
+
return (0, utils_2.calculateSafeTransactionHash)(safeAddress, safeTransaction.data, safeVersion, chainId);
|
|
411
482
|
}
|
|
412
483
|
/**
|
|
413
484
|
* Signs a hash using the current signer account.
|
|
@@ -415,34 +486,109 @@ class Safe {
|
|
|
415
486
|
* @param hash - The hash to sign
|
|
416
487
|
* @returns The Safe signature
|
|
417
488
|
*/
|
|
418
|
-
async
|
|
419
|
-
|
|
489
|
+
async signHash(hash) {
|
|
490
|
+
const signature = await (0, utils_2.generateSignature)(__classPrivateFieldGet(this, _Safe_ethAdapter, "f"), hash);
|
|
491
|
+
return signature;
|
|
492
|
+
}
|
|
493
|
+
/**
|
|
494
|
+
* Returns a Safe message ready to be signed by the owners.
|
|
495
|
+
*
|
|
496
|
+
* @param message - The message
|
|
497
|
+
* @returns The Safe message
|
|
498
|
+
*/
|
|
499
|
+
createMessage(message) {
|
|
500
|
+
return new SafeMessage_1.default(message);
|
|
501
|
+
}
|
|
502
|
+
/**
|
|
503
|
+
* Returns the Safe message with a new signature
|
|
504
|
+
*
|
|
505
|
+
* @param message The message to be signed
|
|
506
|
+
* @param signingMethod The signature type
|
|
507
|
+
* @param preimageSafeAddress If the preimage is required, the address of the Safe that will be used to calculate the preimage.
|
|
508
|
+
* This field is mandatory for 1.4.1 contract versions Because the safe uses the old EIP-1271 interface which uses `bytes` instead of `bytes32` for the message
|
|
509
|
+
* we need to use the pre-image of the message to calculate the message hash
|
|
510
|
+
* https://github.com/safe-global/safe-contracts/blob/192c7dc67290940fcbc75165522bb86a37187069/test/core/Safe.Signatures.spec.ts#L229-L233
|
|
511
|
+
* @returns The signed Safe message
|
|
512
|
+
*/
|
|
513
|
+
async signMessage(message, signingMethod = types_1.SigningMethod.ETH_SIGN_TYPED_DATA_V4, preimageSafeAddress) {
|
|
514
|
+
const owners = await this.getOwners();
|
|
515
|
+
const signerAddress = await __classPrivateFieldGet(this, _Safe_ethAdapter, "f").getSignerAddress();
|
|
516
|
+
if (!signerAddress) {
|
|
517
|
+
throw new Error('EthAdapter must be initialized with a signer to use this method');
|
|
518
|
+
}
|
|
519
|
+
const addressIsOwner = owners.some((owner) => signerAddress && (0, utils_2.sameString)(owner, signerAddress));
|
|
520
|
+
if (!addressIsOwner) {
|
|
521
|
+
throw new Error('Messages can only be signed by Safe owners');
|
|
522
|
+
}
|
|
523
|
+
const safeVersion = await this.getContractVersion();
|
|
524
|
+
if (signingMethod === types_1.SigningMethod.SAFE_SIGNATURE &&
|
|
525
|
+
(0, satisfies_1.default)(safeVersion, EQ_OR_GT_1_4_1) &&
|
|
526
|
+
!preimageSafeAddress) {
|
|
527
|
+
throw new Error('The parent Safe account address is mandatory for contract signatures');
|
|
528
|
+
}
|
|
529
|
+
let signature;
|
|
530
|
+
if (signingMethod === types_1.SigningMethod.ETH_SIGN_TYPED_DATA_V4) {
|
|
531
|
+
signature = await this.signTypedData(message, 'v4');
|
|
532
|
+
}
|
|
533
|
+
else if (signingMethod === types_1.SigningMethod.ETH_SIGN_TYPED_DATA_V3) {
|
|
534
|
+
signature = await this.signTypedData(message, 'v3');
|
|
535
|
+
}
|
|
536
|
+
else if (signingMethod === types_1.SigningMethod.ETH_SIGN_TYPED_DATA) {
|
|
537
|
+
signature = await this.signTypedData(message, undefined);
|
|
538
|
+
}
|
|
539
|
+
else {
|
|
540
|
+
const chainId = await this.getChainId();
|
|
541
|
+
if (!(0, utils_2.hasSafeFeature)(utils_2.SAFE_FEATURES.ETH_SIGN, safeVersion)) {
|
|
542
|
+
throw new Error('eth_sign is only supported by Safes >= v1.1.0');
|
|
543
|
+
}
|
|
544
|
+
let safeMessageHash;
|
|
545
|
+
if (signingMethod === types_1.SigningMethod.SAFE_SIGNATURE &&
|
|
546
|
+
preimageSafeAddress &&
|
|
547
|
+
(0, satisfies_1.default)(safeVersion, EQ_OR_GT_1_4_1)) {
|
|
548
|
+
const messageHashData = (0, utils_2.preimageSafeMessageHash)(preimageSafeAddress, (0, utils_2.hashSafeMessage)(message.data), safeVersion, chainId);
|
|
549
|
+
safeMessageHash = await this.getSafeMessageHash(messageHashData);
|
|
550
|
+
}
|
|
551
|
+
else {
|
|
552
|
+
safeMessageHash = await this.getSafeMessageHash((0, utils_2.hashSafeMessage)(message.data));
|
|
553
|
+
}
|
|
554
|
+
signature = await this.signHash(safeMessageHash);
|
|
555
|
+
}
|
|
556
|
+
const signedSafeMessage = this.createMessage(message.data);
|
|
557
|
+
message.signatures.forEach((signature) => {
|
|
558
|
+
signedSafeMessage.addSignature(signature);
|
|
559
|
+
});
|
|
560
|
+
signedSafeMessage.addSignature(signature);
|
|
561
|
+
return signedSafeMessage;
|
|
420
562
|
}
|
|
421
563
|
/**
|
|
422
564
|
* Signs a transaction according to the EIP-712 using the current signer account.
|
|
423
565
|
*
|
|
424
|
-
* @param
|
|
566
|
+
* @param eip712Data - The Safe Transaction or message hash to be signed
|
|
425
567
|
* @param methodVersion - EIP-712 version. Optional
|
|
426
568
|
* @returns The Safe signature
|
|
427
569
|
*/
|
|
428
|
-
async signTypedData(
|
|
429
|
-
const
|
|
570
|
+
async signTypedData(eip712Data, methodVersion) {
|
|
571
|
+
const safeEIP712Args = {
|
|
430
572
|
safeAddress: await this.getAddress(),
|
|
431
573
|
safeVersion: await this.getContractVersion(),
|
|
432
574
|
chainId: await this.getEthAdapter().getChainId(),
|
|
433
|
-
|
|
575
|
+
data: eip712Data.data
|
|
434
576
|
};
|
|
435
|
-
return (0,
|
|
577
|
+
return (0, utils_2.generateEIP712Signature)(__classPrivateFieldGet(this, _Safe_ethAdapter, "f"), safeEIP712Args, methodVersion);
|
|
436
578
|
}
|
|
437
579
|
/**
|
|
438
580
|
* Adds the signature of the current signer to the Safe transaction object.
|
|
439
581
|
*
|
|
440
582
|
* @param safeTransaction - The Safe transaction to be signed
|
|
441
583
|
* @param signingMethod - Method followed to sign a transaction. Optional. Default value is "eth_sign"
|
|
584
|
+
* @param preimageSafeAddress - If the preimage is required, the address of the Safe that will be used to calculate the preimage
|
|
585
|
+
* This field is mandatory for 1.3.0 and 1.4.1 contract versions Because the safe uses the old EIP-1271 interface which uses `bytes` instead of `bytes32` for the message
|
|
586
|
+
* we need to use the pre-image of the message to calculate the message hash
|
|
587
|
+
* https://github.com/safe-global/safe-contracts/blob/192c7dc67290940fcbc75165522bb86a37187069/test/core/Safe.Signatures.spec.ts#L229-L233
|
|
442
588
|
* @returns The signed Safe transaction
|
|
443
589
|
* @throws "Transactions can only be signed by Safe owners"
|
|
444
590
|
*/
|
|
445
|
-
async signTransaction(safeTransaction, signingMethod =
|
|
591
|
+
async signTransaction(safeTransaction, signingMethod = types_1.SigningMethod.ETH_SIGN_TYPED_DATA_V4, preimageSafeAddress) {
|
|
446
592
|
const transaction = (0, utils_2.isSafeMultisigTransactionResponse)(safeTransaction)
|
|
447
593
|
? await this.toSafeTransactionType(safeTransaction)
|
|
448
594
|
: safeTransaction;
|
|
@@ -455,23 +601,42 @@ class Safe {
|
|
|
455
601
|
if (!addressIsOwner) {
|
|
456
602
|
throw new Error('Transactions can only be signed by Safe owners');
|
|
457
603
|
}
|
|
604
|
+
const safeVersion = await this.getContractVersion();
|
|
605
|
+
if (signingMethod === types_1.SigningMethod.SAFE_SIGNATURE &&
|
|
606
|
+
(0, satisfies_1.default)(safeVersion, EQ_OR_GT_1_3_0) &&
|
|
607
|
+
!preimageSafeAddress) {
|
|
608
|
+
throw new Error('The parent Safe account address is mandatory for contract signatures');
|
|
609
|
+
}
|
|
458
610
|
let signature;
|
|
459
|
-
if (signingMethod ===
|
|
611
|
+
if (signingMethod === types_1.SigningMethod.ETH_SIGN_TYPED_DATA_V4) {
|
|
460
612
|
signature = await this.signTypedData(transaction, 'v4');
|
|
461
613
|
}
|
|
462
|
-
else if (signingMethod ===
|
|
614
|
+
else if (signingMethod === types_1.SigningMethod.ETH_SIGN_TYPED_DATA_V3) {
|
|
463
615
|
signature = await this.signTypedData(transaction, 'v3');
|
|
464
616
|
}
|
|
465
|
-
else if (signingMethod ===
|
|
466
|
-
signature = await this.signTypedData(transaction);
|
|
617
|
+
else if (signingMethod === types_1.SigningMethod.ETH_SIGN_TYPED_DATA) {
|
|
618
|
+
signature = await this.signTypedData(transaction, undefined);
|
|
467
619
|
}
|
|
468
620
|
else {
|
|
469
621
|
const safeVersion = await this.getContractVersion();
|
|
622
|
+
const chainId = await this.getChainId();
|
|
470
623
|
if (!(0, utils_2.hasSafeFeature)(utils_2.SAFE_FEATURES.ETH_SIGN, safeVersion)) {
|
|
471
624
|
throw new Error('eth_sign is only supported by Safes >= v1.1.0');
|
|
472
625
|
}
|
|
473
|
-
|
|
474
|
-
|
|
626
|
+
let txHash;
|
|
627
|
+
// IMPORTANT: because the safe uses the old EIP-1271 interface which uses `bytes` instead of `bytes32` for the message
|
|
628
|
+
// we need to use the pre-image of the transaction hash to calculate the message hash
|
|
629
|
+
// https://github.com/safe-global/safe-contracts/blob/192c7dc67290940fcbc75165522bb86a37187069/test/core/Safe.Signatures.spec.ts#L229-L233
|
|
630
|
+
if (signingMethod === types_1.SigningMethod.SAFE_SIGNATURE &&
|
|
631
|
+
(0, satisfies_1.default)(safeVersion, EQ_OR_GT_1_3_0) &&
|
|
632
|
+
preimageSafeAddress) {
|
|
633
|
+
const txHashData = (0, utils_2.preimageSafeTransactionHash)(preimageSafeAddress, safeTransaction.data, safeVersion, chainId);
|
|
634
|
+
txHash = await this.getSafeMessageHash(txHashData);
|
|
635
|
+
}
|
|
636
|
+
else {
|
|
637
|
+
txHash = await this.getTransactionHash(transaction);
|
|
638
|
+
}
|
|
639
|
+
signature = await this.signHash(txHash);
|
|
475
640
|
}
|
|
476
641
|
const signedSafeTransaction = await this.copyTransaction(transaction);
|
|
477
642
|
signedSafeTransaction.addSignature(signature);
|
|
@@ -792,7 +957,7 @@ class Safe {
|
|
|
792
957
|
const txHash = await this.getTransactionHash(signedSafeTransaction);
|
|
793
958
|
const ownersWhoApprovedTx = await this.getOwnersWhoApprovedTx(txHash);
|
|
794
959
|
for (const owner of ownersWhoApprovedTx) {
|
|
795
|
-
signedSafeTransaction.addSignature((0,
|
|
960
|
+
signedSafeTransaction.addSignature((0, utils_2.generatePreValidatedSignature)(owner));
|
|
796
961
|
}
|
|
797
962
|
const owners = await this.getOwners();
|
|
798
963
|
const signerAddress = await __classPrivateFieldGet(this, _Safe_ethAdapter, "f").getSignerAddress();
|
|
@@ -800,7 +965,7 @@ class Safe {
|
|
|
800
965
|
throw new Error('EthAdapter must be initialized with a signer to use this method');
|
|
801
966
|
}
|
|
802
967
|
if (owners.includes(signerAddress)) {
|
|
803
|
-
signedSafeTransaction.addSignature((0,
|
|
968
|
+
signedSafeTransaction.addSignature((0, utils_2.generatePreValidatedSignature)(signerAddress));
|
|
804
969
|
}
|
|
805
970
|
const isTxValid = await __classPrivateFieldGet(this, _Safe_contractManager, "f").safeContract.isValidTransaction(signedSafeTransaction, {
|
|
806
971
|
from: signerAddress,
|
|
@@ -829,7 +994,7 @@ class Safe {
|
|
|
829
994
|
const txHash = await this.getTransactionHash(signedSafeTransaction);
|
|
830
995
|
const ownersWhoApprovedTx = await this.getOwnersWhoApprovedTx(txHash);
|
|
831
996
|
for (const owner of ownersWhoApprovedTx) {
|
|
832
|
-
signedSafeTransaction.addSignature((0,
|
|
997
|
+
signedSafeTransaction.addSignature((0, utils_2.generatePreValidatedSignature)(owner));
|
|
833
998
|
}
|
|
834
999
|
const owners = await this.getOwners();
|
|
835
1000
|
const threshold = await this.getThreshold();
|
|
@@ -837,7 +1002,7 @@ class Safe {
|
|
|
837
1002
|
if (threshold > signedSafeTransaction.signatures.size &&
|
|
838
1003
|
signerAddress &&
|
|
839
1004
|
owners.includes(signerAddress)) {
|
|
840
|
-
signedSafeTransaction.addSignature((0,
|
|
1005
|
+
signedSafeTransaction.addSignature((0, utils_2.generatePreValidatedSignature)(signerAddress));
|
|
841
1006
|
}
|
|
842
1007
|
if (threshold > signedSafeTransaction.signatures.size) {
|
|
843
1008
|
const signaturesMissing = threshold - signedSafeTransaction.signatures.size;
|
|
@@ -1013,7 +1178,7 @@ class Safe {
|
|
|
1013
1178
|
});
|
|
1014
1179
|
// multiSend method with the transactions encoded
|
|
1015
1180
|
const batchData = multiSendCallOnlyContract.encode('multiSend', [
|
|
1016
|
-
(0,
|
|
1181
|
+
(0, utils_3.encodeMultiSendData)(transactions) // encoded transactions
|
|
1017
1182
|
]);
|
|
1018
1183
|
const transactionBatch = {
|
|
1019
1184
|
...transactionOptions, // optional transaction options like from, gasLimit, gasPrice...
|
|
@@ -1023,7 +1188,25 @@ class Safe {
|
|
|
1023
1188
|
};
|
|
1024
1189
|
return transactionBatch;
|
|
1025
1190
|
}
|
|
1191
|
+
/**
|
|
1192
|
+
* Get the fallback handler contract
|
|
1193
|
+
*
|
|
1194
|
+
* @returns The fallback Handler contract
|
|
1195
|
+
*/
|
|
1196
|
+
async getFallbackHandlerContract() {
|
|
1197
|
+
if (!__classPrivateFieldGet(this, _Safe_contractManager, "f").safeContract) {
|
|
1198
|
+
throw new Error('Safe is not deployed');
|
|
1199
|
+
}
|
|
1200
|
+
const safeVersion = (await __classPrivateFieldGet(this, _Safe_contractManager, "f").safeContract.getVersion()) ?? config_1.DEFAULT_SAFE_VERSION;
|
|
1201
|
+
const chainId = await __classPrivateFieldGet(this, _Safe_ethAdapter, "f").getChainId();
|
|
1202
|
+
const compatibilityFallbackHandlerContract = await (0, safeDeploymentContracts_1.getCompatibilityFallbackHandlerContract)({
|
|
1203
|
+
ethAdapter: __classPrivateFieldGet(this, _Safe_ethAdapter, "f"),
|
|
1204
|
+
safeVersion,
|
|
1205
|
+
customContracts: __classPrivateFieldGet(this, _Safe_contractManager, "f").contractNetworks?.[chainId.toString()]
|
|
1206
|
+
});
|
|
1207
|
+
return compatibilityFallbackHandlerContract;
|
|
1208
|
+
}
|
|
1026
1209
|
}
|
|
1027
|
-
_Safe_predictedSafe = new WeakMap(), _Safe_ethAdapter = new WeakMap(), _Safe_contractManager = new WeakMap(), _Safe_ownerManager = new WeakMap(), _Safe_moduleManager = new WeakMap(), _Safe_guardManager = new WeakMap(), _Safe_fallbackHandlerManager = new WeakMap();
|
|
1210
|
+
_Safe_predictedSafe = new WeakMap(), _Safe_ethAdapter = new WeakMap(), _Safe_contractManager = new WeakMap(), _Safe_ownerManager = new WeakMap(), _Safe_moduleManager = new WeakMap(), _Safe_guardManager = new WeakMap(), _Safe_fallbackHandlerManager = new WeakMap(), _Safe_MAGIC_VALUE = new WeakMap(), _Safe_MAGIC_VALUE_BYTES = new WeakMap();
|
|
1028
1211
|
exports.default = Safe;
|
|
1029
1212
|
//# sourceMappingURL=Safe.js.map
|