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

refactor(protocol-kit): Rename MasterCopy to singleton #532

Merged
merged 12 commits into from
Sep 14, 2023
10 changes: 5 additions & 5 deletions guides/integrating-the-safe-core-sdk.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,12 +66,12 @@ const safeSdk = await Safe.create({ ethAdapter, safeAddress })

There are two versions of the Safe contracts: [Safe.sol](https://github.com/safe-global/safe-contracts/blob/v1.4.1/contracts/Safe.sol) that does not trigger events in order to save gas and [SafeL2.sol](https://github.com/safe-global/safe-contracts/blob/v1.4.1/contracts/SafeL2.sol) that does, which is more appropriate for L2 networks.

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 `isL1SafeMasterCopy` to force the use of the `Safe.sol` contract.
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.create({ ethAdapter, isL1SafeMasterCopy: true })
const safeFactory = await SafeFactory.create({ ethAdapter, isL1SafeSingleton: true })

const safeSdk = await Safe.create({ ethAdapter, safeAddress, isL1SafeMasterCopy: true })
const safeSdk = await Safe.create({ ethAdapter, safeAddress, isL1SafeSingleton: true })
```

If the Safe contracts are not deployed to your current network, the property `contractNetworks` will be required to point to the addresses of the Safe contracts previously deployed by you.
Expand All @@ -82,15 +82,15 @@ import { ContractNetworksConfig } from '@safe-global/protocol-kit'
const chainId = await ethAdapter.getChainId()
const contractNetworks: ContractNetworksConfig = {
[chainId]: {
safeMasterCopyAddress: '<MASTER_COPY_ADDRESS>',
safeSingletonAddress: '<SINGLETON_ADDRESS>',
safeProxyFactoryAddress: '<PROXY_FACTORY_ADDRESS>',
multiSendAddress: '<MULTI_SEND_ADDRESS>',
multiSendCallOnlyAddress: '<MULTI_SEND_CALL_ONLY_ADDRESS>',
fallbackHandlerAddress: '<FALLBACK_HANDLER_ADDRESS>',
signMessageLibAddress: '<SIGN_MESSAGE_LIB_ADDRESS>',
createCallAddress: '<CREATE_CALL_ADDRESS>',
simulateTxAccessorAddress: '<SIMULATE_TX_ACCESSOR_ADDRESS>',
safeMasterCopyAbi: '<MASTER_COPY_ABI>', // Optional. Only needed with web3.js
safeSingletonAbi: '<SINGLETON_ABI>', // Optional. Only needed with web3.js
safeProxyFactoryAbi: '<PROXY_FACTORY_ABI>', // Optional. Only needed with web3.js
multiSendAbi: '<MULTI_SEND_ABI>', // Optional. Only needed with web3.js
multiSendCallOnlyAbi: '<MULTI_SEND_CALL_ONLY_ABI>', // Optional. Only needed with web3.js
Expand Down
6 changes: 3 additions & 3 deletions packages/api-kit/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,12 +69,12 @@ Returns the information and configuration of the service.
const serviceInfo: SafeServiceInfoResponse = await safeService.getServiceInfo()
```

### getServiceMasterCopiesInfo
### getServiceSingletonsInfo

Returns the list of Safe master copies.
Returns the list of Safe singleton copies.

```js
const masterCopies: MasterCopyResponse = await safeService.getServiceMasterCopiesInfo()
const singletons: SafeSingletonResponse = await safeService.getServiceSingletonsInfo()
```

### decodeData
Expand Down
8 changes: 4 additions & 4 deletions packages/api-kit/src/SafeApiKit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
AllTransactionsOptions,
DeleteSafeDelegateProps,
GetSafeDelegateProps,
MasterCopyResponse,
SafeSingletonResponse,
ModulesResponse,
OwnerResponse,
ProposeTransactionProps,
Expand Down Expand Up @@ -76,11 +76,11 @@
}

/**
* Returns the list of Safe master copies.
* Returns the list of Safe singleton copies.
*
* @returns The list of Safe master copies
* @returns The list of Safe singleton copies
*/
yagopv marked this conversation as resolved.
Show resolved Hide resolved
async getServiceMasterCopiesInfo(): Promise<MasterCopyResponse[]> {
async getServiceSingletonsInfo(): Promise<SafeSingletonResponse[]> {
return sendRequest({
url: `${this.#txServiceBaseUrl}/v1/about/master-copies`,
method: HttpMethod.Get
Expand All @@ -96,7 +96,7 @@
* @throws "Not Found"
* @throws "Ensure this field has at least 1 hexadecimal chars (not counting 0x)."
*/
async decodeData(data: string): Promise<any> {

Check warning on line 99 in packages/api-kit/src/SafeApiKit.ts

View workflow job for this annotation

GitHub Actions / eslint

Unexpected any. Specify a different type
if (data === '') {
throw new Error('Invalid data')
}
Expand Down Expand Up @@ -306,7 +306,7 @@
const totp = Math.floor(Date.now() / 1000 / 3600)
const data = delegate + totp
const signature = await signer.signMessage(data)
const body: any = {

Check warning on line 309 in packages/api-kit/src/SafeApiKit.ts

View workflow job for this annotation

GitHub Actions / eslint

Unexpected any. Specify a different type
safe: safeAddress ? this.#getEip3770Address(safeAddress).address : null,
delegate,
delegator,
Expand Down
6 changes: 3 additions & 3 deletions packages/api-kit/src/types/safeTransactionServiceTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export type SafeServiceInfoResponse = {
}
}

export type MasterCopyResponse = {
export type SafeSingletonResponse = {
address: string
version: string
deployer: string
Expand All @@ -35,7 +35,7 @@ export type SafeInfoResponse = {
readonly nonce: number
readonly threshold: number
readonly owners: string[]
readonly masterCopy: string
readonly singleton: string
readonly modules: string[]
readonly fallbackHandler: string
readonly guard: string
Expand All @@ -51,7 +51,7 @@ export type SafeCreationInfoResponse = {
readonly creator: string
readonly transactionHash: string
readonly factoryAddress: string
readonly masterCopy: string
readonly singleton: string
readonly setupData: string
readonly dataDecoded?: string
}
Expand Down
12 changes: 6 additions & 6 deletions packages/api-kit/tests/e2e/getServiceMastercopiesInfo.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,18 @@ import { getServiceClient } from '../utils/setupServiceClient'

let safeApiKit: SafeApiKit

describe('getServiceMasterCopiesInfo', () => {
describe('getServiceSingletonsInfo', () => {
before(async () => {
;({ safeApiKit } = await getServiceClient(
'0x4f3edf983ac636a65a842ce7c78d9aa706d3b113bce9c46f30d7d21715b23b1d'
))
})

it('should call getServiceMasterCopiesInfo', async () => {
const masterCopiesResponse = await safeApiKit.getServiceMasterCopiesInfo()
chai.expect(masterCopiesResponse.length).to.be.greaterThan(1)
masterCopiesResponse.map((masterCopy) => {
chai.expect(masterCopy.deployer).to.be.equal('Gnosis')
it('should call getServiceSingletonsInfo', async () => {
const singletonResponse = await safeApiKit.getServiceSingletonsInfo()
chai.expect(singletonResponse.length).to.be.greaterThan(1)
singletonResponse.map((singleton) => {
chai.expect(singleton.deployer).to.be.equal('Gnosis')
})
yagopv marked this conversation as resolved.
Show resolved Hide resolved
})
})
4 changes: 2 additions & 2 deletions packages/api-kit/tests/endpoint/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,9 @@ describe('Endpoint tests', () => {
})
})

it('getServiceMasterCopiesInfo', async () => {
it('getServiceSingletonsInfo', async () => {
await chai
.expect(safeApiKit.getServiceMasterCopiesInfo())
.expect(safeApiKit.getServiceSingletonsInfo())
.to.be.eventually.deep.equals({ data: { success: true } })
chai.expect(fetchData).to.have.been.calledWith({
url: `${txServiceBaseUrl}/v1/about/master-copies`,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ function Monerium() {
const safeSdk = await Safe.create({
ethAdapter: ethAdapter,
safeAddress: selectedSafe,
isL1SafeMasterCopy: true
isL1SafeSingleton: true
})

const pack = new MoneriumPack({
Expand Down
34 changes: 17 additions & 17 deletions packages/protocol-kit/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -163,14 +163,14 @@ import { SafeFactory } from '@safe-global/protocol-kit'
const safeFactory = await SafeFactory.create({ ethAdapter })
```

- The `isL1SafeMasterCopy` flag
- The `isL1SafeSingleton` flag

There are two versions of the Safe contracts: [Safe.sol](https://github.com/safe-global/safe-contracts/blob/v1.4.1/contracts/Safe.sol) that does not trigger events in order to save gas and [SafeL2.sol](https://github.com/safe-global/safe-contracts/blob/v1.4.1/contracts/SafeL2.sol) that does, which is more appropriate for L2 networks.

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 `isL1SafeMasterCopy` flag to force the use of the `Safe.sol` contract.
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 `isL1SafeSingleton` flag to force the use of the `Safe.sol` contract.

```js
const safeFactory = await SafeFactory.create({ ethAdapter, isL1SafeMasterCopy: true })
const safeFactory = await SafeFactory.create({ ethAdapter, isL1SafeSingleton: true })
```

- The `contractNetworks` property
Expand All @@ -183,15 +183,15 @@ const safeFactory = await SafeFactory.create({ ethAdapter })
const chainId = await ethAdapter.getChainId()
const contractNetworks: ContractNetworksConfig = {
[chainId]: {
safeMasterCopyAddress: '<MASTER_COPY_ADDRESS>',
safeSingletonAddress: '<SINGLETON_ADDRESS>',
safeProxyFactoryAddress: '<PROXY_FACTORY_ADDRESS>',
multiSendAddress: '<MULTI_SEND_ADDRESS>',
multiSendCallOnlyAddress: '<MULTI_SEND_CALL_ONLY_ADDRESS>',
fallbackHandlerAddress: '<FALLBACK_HANDLER_ADDRESS>',
signMessageLibAddress: '<SIGN_MESSAGE_LIB_ADDRESS>',
createCallAddress: '<CREATE_CALL_ADDRESS>',
simulateTxAccessorAddress: '<SIMULATE_TX_ACCESSOR_ADDRESS>',
safeMasterCopyAbi: '<MASTER_COPY_ABI>', // Optional. Only needed with web3.js
safeSingletonAbi: '<SINGLETON_ABI>', // Optional. Only needed with web3.js
safeProxyFactoryAbi: '<PROXY_FACTORY_ABI>', // Optional. Only needed with web3.js
multiSendAbi: '<MULTI_SEND_ABI>', // Optional. Only needed with web3.js
multiSendCallOnlyAbi: '<MULTI_SEND_CALL_ONLY_ABI>', // Optional. Only needed with web3.js
Expand All @@ -216,7 +216,7 @@ const safeFactory = await SafeFactory.create({ ethAdapter })

### deploySafe

Deploys a new Safe and returns an instance of the Protocol Kit connected to the deployed Safe. The address of the Master Copy, Safe contract version and the contract (`Safe.sol` or `SafeL2.sol`) of the deployed Safe will depend on the initialization of the `safeFactory` instance.
Deploys a new Safe and returns an instance of the Protocol Kit connected to the deployed Safe. The address of the Safe Singleton, Safe contract version and the contract (`Safe.sol` or `SafeL2.sol`) of the deployed Safe will depend on the initialization of the `safeFactory` instance.
yagopv marked this conversation as resolved.
Show resolved Hide resolved

```js
const safeAccountConfig: SafeAccountConfig = {
Expand Down Expand Up @@ -317,14 +317,14 @@ const predictedSafe: PredictedSafeProps = {
const safeSdk = await Safe.create({ ethAdapter, predictedSafe })
```

- The `isL1SafeMasterCopy` flag
- The `isL1SafeSingleton` flag

There are two versions of the Safe contracts: [Safe.sol](https://github.com/safe-global/safe-contracts/blob/v1.4.1/contracts/Safe.sol) that does not trigger events in order to save gas and [SafeL2.sol](https://github.com/safe-global/safe-contracts/blob/v1.4.1/contracts/SafeL2.sol) that does, which is more appropriate for L2 networks.

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 `isL1SafeMasterCopy` flag to force the use of the `Safe.sol` contract.
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 `isL1SafeSingleton` flag to force the use of the `Safe.sol` contract.

```js
const safeSdk = await Safe.create({ ethAdapter, safeAddress, isL1SafeMasterCopy: true })
const safeSdk = await Safe.create({ ethAdapter, safeAddress, isL1SafeSingleton: true })
```

- The `contractNetworks` property
Expand All @@ -337,15 +337,15 @@ const safeSdk = await Safe.create({ ethAdapter, predictedSafe })
const chainId = await ethAdapter.getChainId()
const contractNetworks: ContractNetworksConfig = {
[chainId]: {
safeMasterCopyAddress: '<MASTER_COPY_ADDRESS>',
safeSingletonAddress: '<SINGLETON_ADDRESS>',
safeProxyFactoryAddress: '<PROXY_FACTORY_ADDRESS>',
multiSendAddress: '<MULTI_SEND_ADDRESS>',
multiSendCallOnlyAddress: '<MULTI_SEND_CALL_ONLY_ADDRESS>',
fallbackHandlerAddress: '<FALLBACK_HANDLER_ADDRESS>',
signMessageLibAddress: '<SIGN_MESSAGE_LIB_ADDRESS>',
createCallAddress: '<CREATE_CALL_ADDRESS>',
simulateTxAccessorAddress: '<SIMULATE_TX_ACCESSOR_ADDRESS>',
safeMasterCopyAbi: '<MASTER_COPY_ABI>', // Optional. Only needed with web3.js
safeSingletonAbi: '<SINGLETON_ABI>', // Optional. Only needed with web3.js
safeProxyFactoryAbi: '<PROXY_FACTORY_ABI>', // Optional. Only needed with web3.js
multiSendAbi: '<MULTI_SEND_ABI>', // Optional. Only needed with web3.js
multiSendCallOnlyAbi: '<MULTI_SEND_CALL_ONLY_ABI>', // Optional. Only needed with web3.js
Expand Down Expand Up @@ -382,14 +382,14 @@ const predictedSafe: PredictedSafeProps = {
const safeSdk = await safeSdk.connect({ ethAdapter, predictedSafe })
```

- The `isL1SafeMasterCopy` flag
- The `isL1SafeSingleton` flag

There are two versions of the Safe contracts: [Safe.sol](https://github.com/safe-global/safe-contracts/blob/v1.4.1/contracts/Safe.sol) that does not trigger events in order to save gas and [SafeL2.sol](https://github.com/safe-global/safe-contracts/blob/v1.4.1/contracts/SafeL2.sol) that does, which is more appropriate for L2 networks.

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 `isL1SafeMasterCopy` flag to force the use of the `Safe.sol` contract.
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 `isL1SafeSingleton` flag to force the use of the `Safe.sol` contract.

```js
const safeSdk = await Safe.connect({ ethAdapter, safeAddress, isL1SafeMasterCopy: true })
const safeSdk = await Safe.connect({ ethAdapter, safeAddress, isL1SafeSingleton: true })
```

- The `contractNetworks` property
Expand All @@ -402,15 +402,15 @@ const safeSdk = await safeSdk.connect({ ethAdapter, predictedSafe })
const chainId = await ethAdapter.getChainId()
const contractNetworks: ContractNetworksConfig = {
[chainId]: {
safeMasterCopyAddress: '<MASTER_COPY_ADDRESS>',
safeSingletonAddress: '<SINGLETON_ADDRESS>',
safeProxyFactoryAddress: '<PROXY_FACTORY_ADDRESS>',
multiSendAddress: '<MULTI_SEND_ADDRESS>',
multiSendCallOnlyAddress: '<MULTI_SEND_CALL_ONLY_ADDRESS>',
fallbackHandlerAddress: '<FALLBACK_HANDLER_ADDRESS>',
signMessageLibAddress: '<SIGN_MESSAGE_LIB_ADDRESS>',
createCallAddress: '<CREATE_CALL_ADDRESS>',
simulateTxAccessorAddress: '<SIMULATE_TX_ACCESSOR_ADDRESS>',
safeMasterCopyAbi: '<MASTER_COPY_ABI>', // Optional. Only needed with web3.js
safeSingletonAbi: '<SINGLETON_ABI>', // Optional. Only needed with web3.js
safeProxyFactoryAbi: '<PROXY_FACTORY_ABI>', // Optional. Only needed with web3.js
multiSendAbi: '<MULTI_SEND_ABI>', // Optional. Only needed with web3.js
multiSendCallOnlyAbi: '<MULTI_SEND_CALL_ONLY_ABI>', // Optional. Only needed with web3.js
Expand All @@ -433,7 +433,7 @@ const safeAddress = await safeSdk.getAddress()

### getContractVersion

Returns the Safe Master Copy contract version.
Returns the Safe Singleton contract version.

```js
const contractVersion = await safeSdk.getContractVersion()
Expand Down
22 changes: 11 additions & 11 deletions packages/protocol-kit/src/Safe.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ class Safe {
* @throws "MultiSendCallOnly contract is not deployed on the current network"
*/
private async init(config: SafeConfig): Promise<void> {
const { ethAdapter, isL1SafeMasterCopy, contractNetworks } = config
const { ethAdapter, isL1SafeSingleton, contractNetworks } = config

this.#ethAdapter = ethAdapter

Expand All @@ -103,14 +103,14 @@ class Safe {
this.#contractManager = await ContractManager.create({
ethAdapter: this.#ethAdapter,
predictedSafe: this.#predictedSafe,
isL1SafeMasterCopy,
isL1SafeSingleton,
contractNetworks
})
} else {
this.#contractManager = await ContractManager.create({
ethAdapter: this.#ethAdapter,
safeAddress: config.safeAddress,
isL1SafeMasterCopy,
isL1SafeSingleton,
contractNetworks
})
}
Expand All @@ -133,10 +133,10 @@ class Safe {
* @throws "MultiSendCallOnly contract is not deployed on the current network"
*/
async connect(config: ConnectSafeConfig): Promise<Safe> {
const { ethAdapter, safeAddress, predictedSafe, isL1SafeMasterCopy, contractNetworks } = config
const { ethAdapter, safeAddress, predictedSafe, isL1SafeSingleton, contractNetworks } = config
const configProps: SafeConfigProps = {
ethAdapter: ethAdapter || this.#ethAdapter,
isL1SafeMasterCopy: isL1SafeMasterCopy || this.#contractManager.isL1SafeMasterCopy,
isL1SafeSingleton: isL1SafeSingleton || this.#contractManager.isL1SafeSingleton,
contractNetworks: contractNetworks || this.#contractManager.contractNetworks
}

Expand Down Expand Up @@ -248,9 +248,9 @@ class Safe {
}

/**
* Returns the Safe Master Copy contract version.
* Returns the Safe Singleton contract version.
*
* @returns The Safe Master Copy contract version
* @returns The Safe Singleton contract version
*/
async getContractVersion(): Promise<SafeVersion> {
if (this.#contractManager.safeContract) {
Expand Down Expand Up @@ -1031,12 +1031,12 @@ class Safe {
const safeVersion = await this.getContractVersion()
const chainId = await this.getChainId()
const customContracts = this.#contractManager.contractNetworks?.[chainId]
const isL1SafeMasterCopy = this.#contractManager.isL1SafeMasterCopy
const isL1SafeSingleton = this.#contractManager.isL1SafeSingleton

const safeSingletonContract = await getSafeContract({
ethAdapter: this.#ethAdapter,
safeVersion: safeVersion,
isL1SafeMasterCopy,
isL1SafeSingleton,
customContracts
})

Expand Down Expand Up @@ -1136,13 +1136,13 @@ class Safe {
const safeVersion = await this.getContractVersion()
const ethAdapter = this.#ethAdapter
const chainId = await ethAdapter.getChainId()
const isL1SafeMasterCopy = this.#contractManager.isL1SafeMasterCopy
const isL1SafeSingleton = this.#contractManager.isL1SafeSingleton
const customContracts = this.#contractManager.contractNetworks?.[chainId]

const safeSingletonContract = await getSafeContract({
ethAdapter: this.#ethAdapter,
safeVersion,
isL1SafeMasterCopy,
isL1SafeSingleton,
customContracts
})

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { Safe_proxy_factory as SafeProxyFactory_V1_4_1 } from '@safe-global/prot
import { SafeProxyFactoryContract } from '@safe-global/safe-core-sdk-types'

export interface CreateProxyProps {
safeMasterCopyAddress: string
safeSingletonAddress: string
initializer: string
saltNonce: string
options?: EthersTransactionOptions
Expand All @@ -33,7 +33,7 @@ class SafeProxyFactoryEthersContract implements SafeProxyFactoryContract {
}

async createProxy({
safeMasterCopyAddress,
safeSingletonAddress,
initializer,
saltNonce,
options,
Expand All @@ -44,14 +44,14 @@ class SafeProxyFactoryEthersContract implements SafeProxyFactoryContract {
if (options && !options.gasLimit) {
options.gasLimit = await this.estimateGas(
'createProxyWithNonce',
[safeMasterCopyAddress, initializer, saltNonce],
[safeSingletonAddress, initializer, saltNonce],
{
...options
}
)
}
const proxyAddress = this.contract
.createProxyWithNonce(safeMasterCopyAddress, initializer, saltNonce, options)
.createProxyWithNonce(safeSingletonAddress, initializer, saltNonce, options)
.then(async (txResponse) => {
if (callback) {
callback(txResponse.hash)
Expand Down
Loading
Loading