-
Notifications
You must be signed in to change notification settings - Fork 4.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add Safe plugin with actions configuration for initializing a safe sm…
…art account
- Loading branch information
Showing
7 changed files
with
166 additions
and
91 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,23 @@ | ||
{ | ||
"name": "@elizaos/plugin-safe", | ||
"version": "0.1.0", | ||
"type": "module", | ||
"main": "dist/index.js", | ||
"module": "dist/index.js", | ||
"types": "dist/index.d.ts", | ||
"files": ["dist"], | ||
"dependencies": { | ||
"@elizaos/core": "workspace:*", | ||
"@safe-global/relay-kit": "^1.0.0" | ||
}, | ||
"devDependencies": { | ||
"@safe-global/api-kit": "^2.5.8", | ||
"@safe-global/protocol-kit": "5.2.1-alpha.0", | ||
"@safe-global/safe-core-sdk-types": "^5.1.0", | ||
"tsup": "^7.0.0", | ||
"typescript": "^5.0.0" | ||
}, | ||
"scripts": { | ||
"build": "tsup --format esm --dts" | ||
} | ||
} |
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,97 @@ | ||
|
||
|
||
|
||
|
||
// src/actions/createSafeAction.ts | ||
import { | ||
type Action, | ||
type HandlerCallback, | ||
type IAgentRuntime, | ||
type Memory, | ||
type State | ||
} from '@elizaos/core'; | ||
import Safe, { | ||
PredictedSafeProps, | ||
SafeAccountConfig, | ||
SafeDeploymentConfig | ||
} from '@safe-global/protocol-kit'; | ||
|
||
interface ExtendedSafeDeploymentConfig extends SafeDeploymentConfig { | ||
deploymentType?: 'canonical'; // or a union of acceptable values | ||
} | ||
|
||
const RPC_URL = 'https://rpc.ankr.com/eth_sepolia'; | ||
|
||
export const createSafeAction: Action = { | ||
name: "CREATE_SAFE_ACCOUNT", | ||
description: "Creates a new Safe smart account for the agent using the provided signer credentials.", | ||
similes: ["make a new safe smart account", "create a safe wallet", "set up a new safe account"], | ||
examples: [[ | ||
{ user: "{{user}}", content: { text: "create a new safe smart account" }} | ||
]], | ||
validate: async () => true, | ||
handler: async ( | ||
runtime: IAgentRuntime, | ||
message: Memory, | ||
state: State | undefined, | ||
options?: Record<string, unknown>, | ||
callback?: HandlerCallback | ||
): Promise<boolean> => { | ||
try { | ||
// Retrieve the signer credentials via runtime.getSetting (or process.env) | ||
const signerAddress: string | undefined = | ||
process.env.SIGNER_ADDRESS || runtime.getSetting("SIGNER_ADDRESS"); | ||
const signerPrivateKey: string | undefined = | ||
process.env.SIGNER_PRIVATE_KEY || runtime.getSetting("SIGNER_PRIVATE_KEY"); | ||
|
||
if (!signerAddress || !signerPrivateKey) { | ||
throw new Error("Missing SIGNER_ADDRESS or SIGNER_PRIVATE_KEY secrets."); | ||
} | ||
|
||
// Configure the safe account parameters | ||
const safeAccountConfig: SafeAccountConfig = { | ||
owners: [signerAddress], | ||
threshold: 1, | ||
// You can optionally provide additional parameters: | ||
// to: '0x...', data: '0x', fallbackHandler: '0x...', etc. | ||
}; | ||
|
||
// Optionally, configure deployment parameters | ||
const safeDeploymentConfig: ExtendedSafeDeploymentConfig = { | ||
saltNonce: '123', | ||
safeVersion: '1.4.1', | ||
deploymentType: 'canonical' | ||
}; | ||
|
||
// Build the predicted safe configuration | ||
const predictedSafe: PredictedSafeProps = { | ||
safeAccountConfig, | ||
safeDeploymentConfig // This property is optional | ||
}; | ||
|
||
// Initialize the new safe using the predictedSafe configuration | ||
// Note: Remove any 'safeAddress' parameter. Instead, pass 'predictedSafe'. | ||
const protocolKit = await (Safe as any).init({ | ||
provider: RPC_URL, | ||
signer: signerPrivateKey, // In production, create a proper signer instance (e.g., via ethers.js) | ||
predictedSafe, | ||
isL1SafeSingleton: true, | ||
// Optionally: contractNetworks, etc. | ||
}); | ||
|
||
// Optionally, get the computed safe address (if the API provides it) | ||
const safeAddress = protocolKit.getAddress ? await protocolKit.getAddress() : "unknown"; | ||
|
||
const resultMessage = `Safe smart account created successfully. Address: ${safeAddress}`; | ||
callback?.({ text: resultMessage, content: { safeAddress } }); | ||
return true; | ||
} catch (error) { | ||
const errorMessage = error instanceof Error ? error.message : String(error); | ||
callback?.({ text: `Error creating safe account: ${errorMessage}`, content: { error: errorMessage } }); | ||
return false; | ||
} | ||
}, | ||
}; | ||
|
||
export default createSafeAction; | ||
|
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 |
---|---|---|
@@ -1,91 +1,17 @@ | ||
import { Plugin, Runtime} from '@elizaos/core' | ||
import Safe from '@safe-global/protocol-kit' | ||
import SafeApiKit from '@safe-global/api-kit' | ||
import { MetaTransactionData } from '@safe-global/safe-core-sdk-types' | ||
|
||
// Import actions | ||
import { | ||
createSafeAction, | ||
deployNewSafeAction, | ||
proposeTransactionAction, | ||
executeTransactionAction, | ||
batchTransactionsAction, | ||
addOwnerAction, | ||
removeOwnerAction, | ||
changeThresholdAction | ||
} from './actions' | ||
|
||
// Import providers | ||
import { | ||
safeBalanceProvider, | ||
safeTransactionProvider, | ||
safeOwnerProvider, | ||
safeConfigProvider | ||
} from './providers' | ||
|
||
// Import evaluators | ||
import { | ||
transactionEvaluator, | ||
ownershipEvaluator | ||
} from './evaluators' | ||
|
||
export class SafePlugin implements Plugin { | ||
name = 'plugin-safe' | ||
runtime: Runtime | ||
safeSDK: Safe | ||
safeApi: SafeApiKit | ||
|
||
constructor(runtime: Runtime) { | ||
this.runtime = runtime | ||
this.initializeSafeSDK() | ||
this.initializeApiKit() | ||
|
||
// Register components | ||
this.registerActions() | ||
this.registerProviders() | ||
this.registerEvaluators() | ||
} | ||
|
||
private async initializeSafeSDK() { | ||
this.safeSDK = await Safe.create({ | ||
ethAdapter: this.runtime.ethAdapter, | ||
safeAddress: this.runtime.config.safeAddress | ||
}) | ||
} | ||
|
||
private initializeApiKit() { | ||
this.safeApi = new SafeApiKit({ | ||
txServiceUrl: this.runtime.config.safeApiUrl, | ||
ethAdapter: this.runtime.ethAdapter | ||
}) | ||
} | ||
|
||
private registerActions() { | ||
return [ | ||
createSafeAction, | ||
deployNewSafeAction, | ||
proposeTransactionAction, | ||
executeTransactionAction, | ||
batchTransactionsAction, | ||
addOwnerAction, | ||
removeOwnerAction, | ||
changeThresholdAction | ||
] | ||
} | ||
|
||
private registerProviders() { | ||
return [ | ||
safeBalanceProvider, | ||
safeTransactionProvider, | ||
safeOwnerProvider, | ||
safeConfigProvider | ||
] | ||
} | ||
|
||
private registerEvaluators() { | ||
return [ | ||
transactionEvaluator, | ||
ownershipEvaluator | ||
] | ||
} | ||
} | ||
// src/index.ts | ||
import { type Plugin } from '@elizaos/core'; | ||
import { createSafeAction } from './actions/createSafeAction'; | ||
|
||
console.log("Initializing Safe Plugin..."); | ||
|
||
export const safePlugin: Plugin = { | ||
name: 'Safe Protocol Integration', | ||
description: 'Plugin for integrating Safe protocol wallet functionality', | ||
providers: [], | ||
evaluators: [], | ||
services: [], | ||
actions: [createSafeAction] // add the action here | ||
}; | ||
|
||
export const pluginSafe = safePlugin; | ||
export default safePlugin; |
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,3 @@ | ||
// test-import.mjs | ||
import plugin from './dist/index.js'; | ||
console.log("Plugin loaded:", plugin); |
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,8 @@ | ||
{ | ||
"extends": "../../tsconfig.json", | ||
"compilerOptions": { | ||
"outDir": "./dist", | ||
"rootDir": "./src" | ||
}, | ||
"include": ["src/**/*"] | ||
} |
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,17 @@ | ||
import { defineConfig} from 'tsup' | ||
|
||
export default defineConfig({ | ||
entry: ['src/index.ts'], | ||
outDir: 'dist', | ||
sourcemap: true, | ||
clean: true, | ||
format: ['esm'], | ||
dts: true, | ||
external: [ | ||
'@elizaos/core', | ||
'@safe-global/protocol-kit', | ||
'@safe-global/api-kit', | ||
'@safe-global/safe-core-sdk-types', | ||
'@safe-global/relay-kit' | ||
] | ||
}) |