Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(protocol-kit): Add deployment functionality to Safe class + Viem #948

Closed
wants to merge 209 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
209 commits
Select commit Hold shift + click to select a range
061321e
Add passkey support
DaniSomoza May 8, 2024
55e24a6
update createAddOwnerTx to receive passkey param
DaniSomoza May 9, 2024
6702b3d
fix init issue in relay-kit
DaniSomoza May 9, 2024
a74b809
fix issue in BaseContract
DaniSomoza May 9, 2024
33fd454
PasskeyArgType type as Uppercase
DaniSomoza Jun 4, 2024
d20dc53
remove Safe Proxy Factory mentions in the SafeWebAuthnSignerFactoryCo…
DaniSomoza Jun 4, 2024
dac782f
fix getSafeWebAuthnSignerFactoryContract params
DaniSomoza Jun 4, 2024
f1ef57e
remove left-hand side condition
DaniSomoza Jun 4, 2024
a61e70c
Add support for passkeys to 4337
DaniSomoza May 16, 2024
a547b98
verificationGasLimit adjustment
DaniSomoza May 30, 2024
b2ac8df
Added createSafeProvider util function
DaniSomoza Jun 4, 2024
eff8ab5
added createSafeProvider in relay-kit
DaniSomoza Jun 4, 2024
3d524ef
use createSafeProvider in SafeFactory
DaniSomoza Jun 4, 2024
3aa0fdd
feat(protocol-kit): Tests for passkey (#838)
tmjssz Jun 5, 2024
06cdedf
fix isTypedDataSigner to return false if it is passkey signer
DaniSomoza Jun 5, 2024
f3cf8ab
Merge branch 'passkey-support' into passkey-4337-support
DaniSomoza Jun 5, 2024
694488b
refactor createSafeProvider into a static async init method in SafePr…
DaniSomoza Jun 5, 2024
94cb8a0
flatten signingMethod ifs
DaniSomoza Jun 5, 2024
dd0dddc
removed getSafeWebAuthnSignerFactoryContract from Contract Manager
DaniSomoza Jun 5, 2024
625b668
Merge branch 'development' into passkey-support
DaniSomoza Jun 5, 2024
801f8f2
fix types in SafeFactory signer param
DaniSomoza Jun 5, 2024
7ba2e47
updated docs
DaniSomoza Jun 5, 2024
378c03e
Add FIXME comment to use the production deployment packages instead o…
DaniSomoza Jun 5, 2024
70e09af
Add Passkeys as an experimental feature only available on the Sepolia…
DaniSomoza Jun 6, 2024
4977cf6
Merge pull request #841 from safe-global/passkey-4337-support
dasanra Jun 6, 2024
2e284eb
Set alpha.0 version
dasanra Jun 6, 2024
7d58f60
add version compatibility check for passkeys
DaniSomoza Jun 10, 2024
200c6b2
Merge branch 'development' into passkey-support
dasanra Jun 10, 2024
a4a45de
Merge branch 'development' into passkey-support
dasanra Jun 12, 2024
6cbd3f6
feat(protocol-kit): Restrict passkeys tests according to safe version…
leonardotc Jun 12, 2024
d5f32ec
feat(relay-kit): add dummy signature as a passkey signature (#857)
DaniSomoza Jun 12, 2024
61a1280
feat(relay-kit): Tests for using passkey with 4337 (#846)
tmjssz Jun 17, 2024
102c3b6
Update passkey type (#859)
DaniSomoza Jun 18, 2024
9ff82fc
Set alpha.1 version
dasanra Jun 19, 2024
a51e837
feat(protocol-kit): Tests for swap and remove passkey owners (#861)
leonardotc Jun 20, 2024
22354d2
relay-kit: Add viem dependency
tmjssz Jun 26, 2024
2666171
relay-kit: Migrate 4337 related components to viem
tmjssz Jun 26, 2024
b3d329e
playground: Use `generateTransferCallData` function from relay-kit in…
tmjssz Jun 26, 2024
e2be4ea
relay-kit: Fix hex string conversion for nonce
tmjssz Jun 26, 2024
6a5278c
relay-kit: Migrate 4337 bundler client to viem
tmjssz Jun 27, 2024
c040317
relay-kit: Remove `ethers` dependency
tmjssz Jun 27, 2024
7e0bd8e
fix(api-kit): Adjust e1e tests to 4337 bundler client changes
tmjssz Jul 2, 2024
e693167
fix(api-kit): e2e test
tmjssz Jul 2, 2024
92a62b7
Revert uses of `Hash`, `Hex` + `Address` types from viem in interfaces
tmjssz Jul 2, 2024
f554a93
api-kit: Migrate `signDelegate` to viem
tmjssz Jul 3, 2024
d008d4f
auth-kit: Migrate to viem
tmjssz Jul 3, 2024
56b294c
auth-kit: Rename file to `jest.setup.ts`
tmjssz Jul 3, 2024
da2b096
onramp-kit: Migrate to viem
tmjssz Jul 3, 2024
7704121
api-kit: Use WalletClient type with local account for `signDelegate` …
tmjssz Jul 4, 2024
bc494f5
api-kit: Improve Safe Delegates response types
tmjssz Jul 5, 2024
563ccce
api-kit: Fix `getSafeDelegates` e2e tests
tmjssz Jul 5, 2024
3dd6595
[Passkeys] Detect Shared Signer owner (#875)
DaniSomoza Jul 5, 2024
ee039ec
Merge branch 'development' into feat/viem-migration
tmjssz Jul 5, 2024
f1fc1f0
Merge branch 'development' into feat/viem-migration
tmjssz Jul 5, 2024
5129709
PR fixes
leonardotc Jul 9, 2024
8d32d23
remove SafeFactory
DaniSomoza Jul 9, 2024
1b91381
Merge branch 'development' into passkey-support
dasanra Jul 10, 2024
64cd846
Merge branch 'development' into passkey-support
dasanra Jul 10, 2024
1ba3833
add getSafeAddressFromDeploymentTx util fn
DaniSomoza Jul 10, 2024
d89831c
remove throw in getAddress
DaniSomoza Jul 10, 2024
8fbbded
Fix `safe-kit` reconnections
dasanra Jul 10, 2024
d214e9e
Add getProxyCreationEvent util fn
DaniSomoza Jul 10, 2024
2d56a2a
Add comment for TextEncoder polyfill
tmjssz Jul 10, 2024
8af26ef
Feat/viem migration tests (#894)
leonardotc Jul 11, 2024
de3ccc8
Fix onramp kit
leonardotc Jul 11, 2024
82d4512
Fix build
leonardotc Jul 11, 2024
4d91289
Api kit fixes
leonardotc Jul 12, 2024
4320cfa
Fix import
leonardotc Jul 12, 2024
65bda3a
Remove heap-size parameter
leonardotc Jul 12, 2024
e95fc3c
Remove ethers from onramp kit
leonardotc Jul 12, 2024
1fcc9eb
Add comment on global polyfill
leonardotc Jul 15, 2024
435ae4d
Change encode type conversion
leonardotc Jul 15, 2024
57f7219
Merge remote-tracking branch 'origin/development' into feat/viem-migr…
leonardotc Jul 15, 2024
6bc1f12
Fix build after merge
leonardotc Jul 15, 2024
ade9077
Merge remote-tracking branch 'origin/development' into feat/viem-migr…
leonardotc Jul 15, 2024
330f05c
api-kit: Move `viem` from devDependencies to dependencies
tmjssz Jul 15, 2024
eaca089
api-kit: Add `ethers` to devDependencies because it's still needed fo…
tmjssz Jul 15, 2024
ed70a38
api-kit: Fix import
tmjssz Jul 15, 2024
65127b4
api-kit: Fix tests for `addSafeOperation`
tmjssz Jul 15, 2024
4ff0dd8
api-kit: Fix e2e tests for `addSafeOperation`
tmjssz Jul 15, 2024
096ac25
api-kit: Add `@safe-global/relay-kit` to devDependencies because it's…
tmjssz Jul 15, 2024
a570ceb
api-kit: Fix `BrowserProvider` import
tmjssz Jul 15, 2024
f7cc1cd
Fix transaction encode test
leonardotc Jul 16, 2024
78979ed
Changed paymasterAndData
leonardotc Jul 16, 2024
9ae5384
Remove only on tests
leonardotc Jul 16, 2024
ec89e7a
api-kit: Fix `confirmSafeOperation` tests
tmjssz Jul 16, 2024
25e54f7
Fix (or maybe not) paymaster estimation on sponsored transaction
leonardotc Jul 16, 2024
8d29d3c
Merge remote-tracking branch 'origin/feat/viem-migration' into feat/v…
leonardotc Jul 16, 2024
a04a860
Fix gas estimation issue
leonardotc Jul 16, 2024
9e16f42
chore: remove deprecated ethereum utils lib (#884)
dasanra Jul 17, 2024
4f074f2
Remove ethers from safe-kit
leonardotc Jul 17, 2024
e926eba
Minor PR changes
leonardotc Jul 17, 2024
35c7cf6
Remove ethers dependency
leonardotc Jul 17, 2024
e966c67
Fix coverall file
leonardotc Jul 17, 2024
e553890
Re-add ethers but as dev deps
leonardotc Jul 17, 2024
93062e0
First clean up
leonardotc Jul 17, 2024
c5303af
Minor type changes and comments
leonardotc Jul 18, 2024
1adea41
Remove throws
leonardotc Jul 18, 2024
c2b2942
playground: Migrate scripts to viem
tmjssz Jul 18, 2024
32a6da4
Pre-pr changes
leonardotc Jul 18, 2024
47d4e1d
onramp-kit: Remove ethers from example app
tmjssz Jul 18, 2024
ee88653
Fix contracts
leonardotc Jul 19, 2024
6b0853c
Merge remote-tracking branch 'origin/development' into feat/viem-migr…
leonardotc Jul 19, 2024
3f0b7b5
Merge branch 'development' into feat/viem-migration
tmjssz Jul 19, 2024
1a52333
Add chain to the external signer
leonardotc Jul 22, 2024
e3ec4d8
Fix parsing of SafeTxGas estimation from viem error object
tmjssz Jul 22, 2024
a7c5bc1
relay-kit: Fix getNonce call in Safe4337Pack
tmjssz Jul 22, 2024
03907fd
Use different RPC endpoint
tmjssz Jul 22, 2024
17e149c
Merge branch 'development' into feat/viem-migration
tmjssz Jul 22, 2024
cc6589c
fix(api-kit): Fix confirmSafeOperation e2e test by making test transa…
tmjssz Jul 22, 2024
360d997
remove public schema from bundler
leonardotc Jul 23, 2024
3795719
refactor: Improve API Kit interoperability playground
tmjssz Jul 23, 2024
90157d0
refactor: Improve relay-kit playground scripts
tmjssz Jul 23, 2024
3000003
refactor: Fix wait for transaction being executed in api-kit playgrou…
tmjssz Jul 23, 2024
d20167c
refactor: Update playground scripts to use viem/accounts for private …
tmjssz Jul 23, 2024
dd6e775
refactor: Use `Account` type instead of LocalAccount in api-kit
tmjssz Jul 24, 2024
dca351a
Revert protocol kit playground
leonardotc Jul 24, 2024
124f931
refactor: Use `(await signer.getAddresses())[0]` instead of `signer.a…
tmjssz Jul 24, 2024
403e842
Fix wait for receipt in transaction result
leonardotc Jul 24, 2024
1d58ce8
Add comment for import from relay-kit dist folder
tmjssz Jul 24, 2024
3796ce4
Merge branch 'feat/viem-migration' of github.com:safe-global/safe-cor…
tmjssz Jul 24, 2024
4f9400e
refactor: Move `asBlockId` function to utils
tmjssz Jul 25, 2024
3648d94
refactor: Simplify SafeProvider constructor logic
tmjssz Jul 25, 2024
8e9391c
Add explanation for conversion
leonardotc Jul 25, 2024
0b940bb
Remove residual code
leonardotc Jul 26, 2024
128987f
Remove duplicate
leonardotc Jul 26, 2024
4475b88
Fix custom chain support
leonardotc Jul 26, 2024
8cd7e96
Depromisify getAddress
leonardotc Jul 26, 2024
658b9a8
Fix onramp
leonardotc Jul 26, 2024
00a292e
feat: Extend SafeProviders externalClient type (#928)
tmjssz Jul 30, 2024
af4a598
Merge branch 'development' into passkey-support
leonardotc Jul 30, 2024
4565be6
Fix build post-merge
leonardotc Jul 31, 2024
090bf04
Merge branch 'feat/viem-migration' into passkey-support-viem
leonardotc Jul 31, 2024
9853b12
chore: align api-kit tests
dasanra Aug 1, 2024
48d4902
fix: delegator address not checksummed
dasanra Aug 1, 2024
19d7910
Add further comments
leonardotc Aug 2, 2024
8aeb43b
Fix build
leonardotc Aug 2, 2024
8b5c2c5
Soft correction on passkey tests
leonardotc Aug 2, 2024
2dcb731
Fix overall address issue
leonardotc Aug 2, 2024
32e7893
Fix passkey ownership logic
leonardotc Aug 5, 2024
34ec5c4
Fix passkey deployment
leonardotc Aug 5, 2024
74f10e2
Fix getCode call
leonardotc Aug 5, 2024
2ba32fa
Fixed isSharedSignerPasskey usage
leonardotc Aug 5, 2024
4d60792
Fix a couple more tests on protocol kit
leonardotc Aug 6, 2024
a70cf83
Fix racing condition on modules test
leonardotc Aug 6, 2024
c91c8dc
Fix api kit
leonardotc Aug 6, 2024
7d3c11c
Add ethers to dev deps on api-kit
leonardotc Aug 6, 2024
5377c13
Update deployment information
leonardotc Aug 6, 2024
0296851
Fix pending deployment info
leonardotc Aug 6, 2024
e0a10ed
Fix test evaluation
leonardotc Aug 6, 2024
4f109ee
Fix passkey callee on non-paymaster test
leonardotc Aug 6, 2024
e0e9755
Fix sponsored transaction rates
leonardotc Aug 6, 2024
c682afa
Fix test amount to approve
leonardotc Aug 6, 2024
3295108
Change more estimations
leonardotc Aug 7, 2024
a9449b4
Update signature on signing test
leonardotc Aug 7, 2024
86871bd
Change base address type
leonardotc Aug 8, 2024
a8569e9
Possibly? fix passkey tests whole
leonardotc Aug 8, 2024
991317c
Checkout adjustEstimation
leonardotc Aug 8, 2024
701f7e3
Fix estimations
leonardotc Aug 8, 2024
eeeeb84
remove Viem dependency from @safe-global/safe-core-sdk-types
dasanra Aug 8, 2024
3d85ef2
Re-add from env
leonardotc Aug 8, 2024
4dc89f1
revert unnecessary Viem changes in api-kit playground
dasanra Aug 8, 2024
9d92313
fix: types in tests
dasanra Aug 9, 2024
aab6c6a
Swap private keys
leonardotc Aug 9, 2024
ff2e2dc
Restore fixture address
leonardotc Aug 9, 2024
03b1cb0
Update signatures with the rollback estimation values
leonardotc Aug 9, 2024
473367a
Merge branch 'feat/viem-migration' into added-deployment-safe-class
leonardotc Aug 9, 2024
1ba2989
Prepare passkeys release (#937)
DaniSomoza Aug 12, 2024
b875321
Merge branch 'development' into passkey-support
dasanra Aug 12, 2024
0597db8
Fix build
leonardotc Aug 12, 2024
5d7f329
Fix addresses and non-named event parameters
leonardotc Aug 12, 2024
eb1ce1a
fix(protocol-kit): build not finishing because of breaking change in …
dasanra Aug 12, 2024
ea8a753
Fix transaction type conversion
leonardotc Aug 12, 2024
36ef47f
Set alpha.2 version
dasanra Aug 12, 2024
13c8ef5
add comment to use external util
dasanra Aug 12, 2024
5490043
Merge remote-tracking branch 'origin/passkey-support' into passkey-su…
leonardotc Aug 13, 2024
55a5475
Merge remote-tracking branch 'origin/feat/viem-migration' into passke…
leonardotc Aug 13, 2024
00169e3
Fix build
leonardotc Aug 13, 2024
a875568
Fix some passkey tests
leonardotc Aug 14, 2024
cc08b4d
Remove only
leonardotc Aug 14, 2024
c31b351
Merge branch 'development' into passkey-support
dasanra Aug 14, 2024
2f11963
Fix the last tests
leonardotc Aug 14, 2024
46e2947
Remove timeout
leonardotc Aug 15, 2024
39702fb
Remove only
leonardotc Aug 15, 2024
e4d8e97
Fix 4337 test
leonardotc Aug 15, 2024
cfd46f6
Merge remote-tracking branch 'origin/passkey-support' into passkey-su…
leonardotc Aug 15, 2024
a789c5a
Merge branch 'passkey-support-viem' into added-deployment-safe-class-…
leonardotc Aug 19, 2024
569b074
Fix build
leonardotc Aug 19, 2024
d40e489
use contract addresses from safe-modules-deployments (#950)
DaniSomoza Aug 21, 2024
2081134
Merge branch 'development' into passkey-support
DaniSomoza Aug 22, 2024
d3da1e0
chore: remove bytecode from webauthn ABIs
dasanra Aug 22, 2024
1c22d9c
update passkeys contract names from v1_4_1 to v0.2.1 (#953)
DaniSomoza Aug 23, 2024
0c6f84b
Merge branch 'passkey-support' into rebase/passkey-support-viem
dasanra Aug 23, 2024
1e86e98
Merge branch 'passkey-support' into passkey-support-viem
dasanra Aug 23, 2024
6bfa278
Merge branch 'development' of https://github.com/safe-global/safe-cor…
yagopv Sep 10, 2024
c60c3a5
chore: remove alpha dependency
dasanra Sep 10, 2024
7f46683
Revert "chore: remove alpha dependency"
dasanra Sep 10, 2024
1917262
chore: remove alpha from package.json
dasanra Sep 10, 2024
0df4b6c
chore: remove unnecessary awaits
dasanra Sep 10, 2024
e868922
chore: cleanup api-kit tests
dasanra Sep 11, 2024
c391ee6
chore: cleanup unnecessary awaits
dasanra Sep 11, 2024
28cd737
fix: set ExternalClient instead of PublicClient type
dasanra Sep 11, 2024
d58f9ee
chore: fix wrong routes
dasanra Sep 11, 2024
ff2c0df
chore: fix some type casts and import routes
dasanra Sep 11, 2024
6b190db
fix: restore predictSafe util
dasanra Sep 11, 2024
1be83ac
fix: restore predictSafe tests
dasanra Sep 11, 2024
bf7a9f1
chore: add missing return type
dasanra Sep 11, 2024
053fecb
Merge branch 'passkey-support-viem' into added-deployment-safe-class-…
dasanra Sep 11, 2024
d2ef18f
Merge branch 'development' into added-deployment-safe-class-viem
dasanra Sep 11, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 7 additions & 16 deletions guides/integrating-the-safe-core-sdk.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,7 @@ const apiKit = new SafeApiKit({
### Initialize the Protocol Kit

```js
import Safe, { SafeFactory } from '@safe-global/protocol-kit'

const safeFactory = await SafeFactory.init({ provider, signer })
import Safe from '@safe-global/protocol-kit'

const protocolKit = await Safe.init({ provider, signer, safeAddress })
```
Expand All @@ -67,7 +65,6 @@ There are two versions of the Safe contracts: [Safe.sol](https://github.com/safe
By default `Safe.sol` will be only used on Ethereum Mainnet. For the rest of the networks where the Safe contracts are already deployed, the `SafeL2.sol` contract will be used unless you add the property `isL1SafeSingleton` to force the use of the `Safe.sol` contract.

```js
const safeFactory = await SafeFactory.init({ provider, signer, isL1SafeSingleton: true })

const protocolKit = await Safe.init({ provider, signer, safeAddress, isL1SafeSingleton: true })
```
Expand Down Expand Up @@ -102,21 +99,12 @@ const contractNetworks: ContractNetworksConfig = {
}
}

const safeFactory = await SafeFactory.init({ provider, signer, contractNetworks })

const protocolKit = await Safe.init({ provider, signer, safeAddress, contractNetworks })
```

The `SafeFactory` constructor also accepts the property `safeVersion` to specify the Safe contract version that will be deployed. This string can take the values `1.0.0`, `1.1.1`, `1.2.0`, `1.3.0` or `1.4.1`. If not specified, the `DEFAULT_SAFE_VERSION` value will be used.

```js
const safeVersion = 'X.Y.Z'
const safeFactory = await SafeFactory.init({ provider, signer, safeVersion })
```

## <a name="deploy-safe">3. Deploy a new Safe</a>

The Protocol Kit library allows the deployment of new Safes using the `safeFactory` instance we just created.
The Protocol Kit library allows the deployment of new Safes using the `deploy` method.

Here, for example, we can create a new Safe account with 3 owners and 2 required signatures.

Expand All @@ -128,10 +116,13 @@ const safeAccountConfig: SafeAccountConfig = {
threshold: 2,
// ... (optional params)
}
const protocolKit = await safeFactory.deploySafe({ safeAccountConfig })

const predictedSafe = await Safe.init({ provider, signer, predictSafe, contractNetworks })

const protocolKit = await predictedSafe.deploy()
```

Calling the method `deploySafe` will deploy the desired Safe and return a Protocol Kit initialized instance ready to be used. Check the [API Reference](https://github.com/safe-global/safe-core-sdk/tree/main/packages/protocol-kit#deploysafe) for more details on additional configuration parameters and callbacks.
Calling the method `deploy` will deploy the desired Safe and return a Protocol Kit initialized instance ready to be used. Check the [API Reference](https://github.com/safe-global/safe-core-sdk/tree/main/packages/protocol-kit#deploysafe) for more details on additional configuration parameters and callbacks.

## <a name="create-transaction">4. Create a transaction</a>

Expand Down
185 changes: 161 additions & 24 deletions packages/protocol-kit/src/Safe.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,10 @@ import {
encodeSetupCallData,
getChainSpecificDefaultSaltNonce,
getPredictedSafeAddressInitCode,
predictSafeAddress
getSafeAddressFromDeploymentTx,
predictSafeAddress,
validateSafeAccountConfig,
validateSafeDeploymentConfig
} from './contracts/utils'
import { DEFAULT_SAFE_VERSION } from './contracts/config'
import ContractManager from './managers/contractManager'
Expand Down Expand Up @@ -57,6 +60,7 @@ import {
generateSignature,
preimageSafeMessageHash,
preimageSafeTransactionHash,
toTransactionRequest,
adjustVInSignature
} from './utils'
import EthSafeTransaction from './utils/transactions/SafeTransaction'
Expand All @@ -79,7 +83,7 @@ import SafeMessage from './utils/messages/SafeMessage'
import semverSatisfies from 'semver/functions/satisfies'
import SafeProvider from './SafeProvider'
import { asHash, asHex } from './utils/types'
import { Hash, Hex } from 'viem'
import { Hash, Hex, WalletClient, Transport, Chain, Account } from 'viem'
import getPasskeyOwnerAddress from './utils/passkeys/getPasskeyOwnerAddress'
import createPasskeyDeploymentTransaction from './utils/passkeys/createPasskeyDeploymentTransaction'

Expand Down Expand Up @@ -264,13 +268,6 @@ class Safe {
*/
async getAddress(): Promise<string> {
if (this.#predictedSafe) {
const safeVersion = await this.getContractVersion()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is removed in several places but not sure why

if (!hasSafeFeature(SAFE_FEATURES.ACCOUNT_ABSTRACTION, safeVersion)) {
throw new Error(
'Account Abstraction functionality is not available for Safes with version lower than v1.3.0'
)
}

const chainId = await this.#safeProvider.getChainId()
return predictSafeAddress({
safeProvider: this.#safeProvider,
Expand Down Expand Up @@ -881,7 +878,7 @@ class Safe {
*/
async getOwnersWhoApprovedTx(txHash: string): Promise<string[]> {
if (!this.#contractManager.safeContract) {
throw new Error('Safe is not deployed')
return []
}

const owners = await this.getOwners()
Expand Down Expand Up @@ -912,6 +909,13 @@ class Safe {
fallbackHandlerAddress: string,
options?: SafeTransactionOptionalProps
): Promise<SafeTransaction> {
const safeVersion = await this.getContractVersion()
if (this.#predictedSafe && !hasSafeFeature(SAFE_FEATURES.ACCOUNT_ABSTRACTION, safeVersion)) {
throw new Error(
'Account Abstraction functionality is not available for Safes with version lower than v1.3.0'
)
}

const safeTransactionData = {
to: await this.getAddress(),
value: '0',
Expand All @@ -937,6 +941,13 @@ class Safe {
async createDisableFallbackHandlerTx(
options?: SafeTransactionOptionalProps
): Promise<SafeTransaction> {
const safeVersion = await this.getContractVersion()
if (this.#predictedSafe && !hasSafeFeature(SAFE_FEATURES.ACCOUNT_ABSTRACTION, safeVersion)) {
throw new Error(
'Account Abstraction functionality is not available for Safes with version lower than v1.3.0'
)
}

const safeTransactionData = {
to: await this.getAddress(),
value: '0',
Expand Down Expand Up @@ -1309,16 +1320,51 @@ class Safe {
? await this.toSafeTransactionType(safeTransaction)
: safeTransaction

const signedSafeTransaction = await this.#addPreValidatedSignature(transaction)

await this.#isReadyToExecute(signedSafeTransaction)

const value = BigInt(signedSafeTransaction.data.value)
if (value !== 0n) {
const balance = await this.getBalance()
if (value > balance) {
throw new Error('Not enough Ether funds')
}
}

const signerAddress = await this.#safeProvider.getSignerAddress()

const txResponse = await this.#contractManager.safeContract.execTransaction(
signedSafeTransaction,
{
from: signerAddress,
...options
}
)
return txResponse
}

/**
* Adds a PreValidatedSignature to the transaction if the threshold is not reached.
*
* @async
* @param {SafeTransaction} transaction - The transaction to add a signature to.
* @returns {Promise<SafeTransaction>} A promise that resolves to the signed transaction.
*/
async #addPreValidatedSignature(transaction: SafeTransaction): Promise<SafeTransaction> {
const signedSafeTransaction = await this.copyTransaction(transaction)

const txHash = await this.getTransactionHash(signedSafeTransaction)
const ownersWhoApprovedTx = await this.getOwnersWhoApprovedTx(txHash)

for (const owner of ownersWhoApprovedTx) {
signedSafeTransaction.addSignature(generatePreValidatedSignature(owner))
}

const owners = await this.getOwners()
const threshold = await this.getThreshold()
const signerAddress = await this.#safeProvider.getSignerAddress()

if (
threshold > signedSafeTransaction.signatures.size &&
signerAddress &&
Expand All @@ -1327,31 +1373,122 @@ class Safe {
signedSafeTransaction.addSignature(generatePreValidatedSignature(signerAddress))
}

if (threshold > signedSafeTransaction.signatures.size) {
const signaturesMissing = threshold - signedSafeTransaction.signatures.size
return signedSafeTransaction
}

/**
* Checks if the transaction has enough signatures to be executed.
*
* @async
* @param {SafeTransaction} transaction - The Safe transaction to check.
* @throws Will throw an error if the required number of signatures is not met.
*/
async #isReadyToExecute(transaction: SafeTransaction) {
const threshold = await this.getThreshold()

if (threshold > transaction.signatures.size) {
const signaturesMissing = threshold - transaction.signatures.size
throw new Error(
`There ${signaturesMissing > 1 ? 'are' : 'is'} ${signaturesMissing} signature${
signaturesMissing > 1 ? 's' : ''
} missing`
)
}
}

const value = BigInt(signedSafeTransaction.data.value)
if (value !== 0n) {
const balance = await this.getBalance()
if (value > balance) {
throw new Error('Not enough Ether funds')
}
/**
* Deploys a Safe and optionally executes a transaction in a batch
*
* @param safeTransaction - The Safe transaction to execute
* @param options - The Safe transaction execution options. Optional
* @throws "No signer provided"
* @throws "There are X signatures missing"
* @returns The new instance of the SDK with the Safe deployed
*/
async deploy(
safeTransaction?: SafeTransaction | SafeMultisigTransactionResponse,
options: TransactionOptions = {}
): Promise<Safe> {
const isSafeDeployed = await this.isSafeDeployed()

// if the safe is already deployed throws an error
if (isSafeDeployed) {
throw new Error('Safe already deployed')
}

const txResponse = await this.#contractManager.safeContract.execTransaction(
signedSafeTransaction,
{
if (!this.#predictedSafe) {
throw new Error('Predict Safe should be present')
}

const signer = (await this.#safeProvider.getExternalSigner()) as WalletClient<
Transport,
Chain,
Account
>

if (!signer) {
throw new Error('signer should be present')
}

validateSafeAccountConfig(this.#predictedSafe.safeAccountConfig)
validateSafeDeploymentConfig(this.#predictedSafe?.safeDeploymentConfig || {})

const signerAddress = (await this.#safeProvider.getSignerAddress()) || '0x'

let txReceipt

if (safeTransaction) {
const transaction = isSafeMultisigTransactionResponse(safeTransaction)
? await this.toSafeTransactionType(safeTransaction)
: safeTransaction

const signedSafeTransaction = await this.#addPreValidatedSignature(transaction)

await this.#isReadyToExecute(signedSafeTransaction)

// we add the Safe deployment to the batch
const deploymentBatch = await this.wrapSafeTransactionIntoDeploymentBatch(
signedSafeTransaction,
options
)

const tx = toTransactionRequest({
from: signerAddress,
...deploymentBatch,
...options
}
)
return txResponse
})

// await for the deployment
const hash = await signer.sendTransaction(tx)

txReceipt = await this.getSafeProvider()
.getExternalProvider()
.waitForTransactionReceipt({ hash })
} else {
// we create the deployment transaction
const safeDeploymentTransaction = await this.createSafeDeploymentTransaction(undefined, {
...options,
from: signerAddress
})

const hash = await signer.sendTransaction(toTransactionRequest(safeDeploymentTransaction))

txReceipt = await this.getSafeProvider()
.getExternalProvider()
.waitForTransactionReceipt({ hash })
}

const safeVersion = await this.getContractVersion()
const safeAddress = getSafeAddressFromDeploymentTx(txReceipt!, safeVersion)

const isSafeProxyContractDeployed = await this.#safeProvider.isContractDeployed(safeAddress)

if (!isSafeProxyContractDeployed) {
throw new Error('SafeProxy contract is not deployed on the current network')
}

// return a new instance of the SDK with the safe deployed
return this.connect({ signer: this.#safeProvider.signer, safeAddress })
}

/**
Expand Down
Loading
Loading