-
Notifications
You must be signed in to change notification settings - Fork 431
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add script for adding gnosis safe delegates (#1032)
- Loading branch information
Showing
5 changed files
with
1,095 additions
and
20 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
import { LedgerSigner } from '@ethersproject/hardware-wallets'; | ||
// Due to TS funkiness, the following needs to be imported in order for this | ||
// code to build, but needs to be removed in order for the code to run. | ||
import '@ethersproject/hardware-wallets/thirdparty'; | ||
import { SafeDelegateConfig } from '@gnosis.pm/safe-service-client'; | ||
import yargs from 'yargs'; | ||
|
||
import { AllChains } from '@abacus-network/sdk'; | ||
|
||
import { getSafeDelegates, getSafeService } from '../src/utils/safe'; | ||
|
||
import { getCoreEnvironmentConfig, getEnvironment } from './utils'; | ||
|
||
function getArgs() { | ||
return yargs(process.argv.slice(2)) | ||
.describe('chain', 'chain of the validator to inspect') | ||
.choices('chain', AllChains) | ||
.demandOption('chain') | ||
.describe('action', 'add or remove') | ||
.choices('action', ['add', 'remove']) | ||
.demandOption('action') | ||
.describe('delegate', 'address of the delegate') | ||
.demandOption('delegate') | ||
.string('delegate') | ||
.describe('safe', 'address of the safe') | ||
.demandOption('safe') | ||
.string('safe').argv; | ||
} | ||
|
||
async function delegate() { | ||
const environment = await getEnvironment(); | ||
const config = getCoreEnvironmentConfig(environment); | ||
const { chain, delegate, safe, action } = await getArgs(); | ||
|
||
const multiProvider = await config.getMultiProvider(); | ||
const connection = multiProvider.getChainConnection(chain); | ||
|
||
const safeService = getSafeService(chain, connection); | ||
const delegates = await getSafeDelegates(safeService, safe); | ||
|
||
// Ledger Live derivation path, vary by changing the index i.e. | ||
// "m/44'/60'/{CHANGE_ME}'/0/0"; | ||
const path = "m/44'/60'/0'/0/0"; | ||
const signer = new LedgerSigner(undefined, 'hid', path); | ||
console.log('Connected to signer with address:', await signer.getAddress()); | ||
|
||
const delegateConfig: SafeDelegateConfig = { | ||
safe, | ||
delegate, | ||
signer, | ||
label: 'delegate', | ||
}; | ||
|
||
const baseDescription = `${delegate} as a delegate for ${chain} safe at address ${safe}`; | ||
if (action === 'add') { | ||
console.log(`Adding ${baseDescription}`); | ||
if (delegates.includes(delegate)) | ||
throw new Error(`${delegate} is already a delegate`); | ||
await safeService.addSafeDelegate(delegateConfig); | ||
} else if (action === 'remove') { | ||
console.log(`Removing ${baseDescription}`); | ||
if (!delegates.includes(delegate)) | ||
throw new Error(`${delegate} is not a delegate`); | ||
await safeService.removeSafeDelegate(delegateConfig); | ||
} else { | ||
throw new Error('unsupported action'); | ||
} | ||
} | ||
|
||
delegate().then(console.log).catch(console.error); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
import Safe from '@gnosis.pm/safe-core-sdk'; | ||
import EthersAdapter from '@gnosis.pm/safe-ethers-lib'; | ||
import SafeServiceClient from '@gnosis.pm/safe-service-client'; | ||
import { ethers } from 'ethers'; | ||
|
||
import { ChainConnection, ChainName, chainMetadata } from '@abacus-network/sdk'; | ||
|
||
export function getSafeService( | ||
chain: ChainName, | ||
connection: ChainConnection, | ||
): SafeServiceClient { | ||
const signer = connection.signer; | ||
if (!signer) throw new Error(`no signer found for ${chain}`); | ||
const ethAdapter = new EthersAdapter({ ethers, signer }); | ||
const txServiceUrl = chainMetadata[chain].gnosisSafeTransactionServiceUrl; | ||
if (!txServiceUrl) | ||
throw new Error(`must provide tx service url for ${chain}`); | ||
return new SafeServiceClient({ txServiceUrl, ethAdapter }); | ||
} | ||
|
||
export function getSafe( | ||
connection: ChainConnection, | ||
safeAddress: string, | ||
): Promise<Safe> { | ||
const signer = connection.signer; | ||
if (!signer) throw new Error(`no signer found`); | ||
const ethAdapter = new EthersAdapter({ ethers, signer }); | ||
return Safe.create({ | ||
ethAdapter, | ||
safeAddress: safeAddress, | ||
}); | ||
} | ||
|
||
export async function getSafeDelegates( | ||
service: SafeServiceClient, | ||
safe: string, | ||
) { | ||
const delegateResponse = await service.getSafeDelegates(safe); | ||
return delegateResponse.results.map((r) => r.delegate); | ||
} | ||
|
||
export async function canProposeSafeTransactions( | ||
proposer: string, | ||
chain: ChainName, | ||
connection: ChainConnection, | ||
safeAddress: string, | ||
): Promise<boolean> { | ||
const safeService = getSafeService(chain, connection); | ||
const safe = await getSafe(connection, safeAddress); | ||
const delegates = await getSafeDelegates(safeService, safeAddress); | ||
const owners = await safe.getOwners(); | ||
return delegates.includes(proposer) || owners.includes(proposer); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.