Skip to content

Commit

Permalink
chore: formatting
Browse files Browse the repository at this point in the history
  • Loading branch information
kopy-kat committed Dec 30, 2024
1 parent 710ace8 commit 611cfd1
Show file tree
Hide file tree
Showing 58 changed files with 3,077 additions and 1,263 deletions.
8 changes: 4 additions & 4 deletions pages/automations/setup/validator-setup.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ For this guide, we will use permissionless.js but any other account SDK can be u

### Install the packages

First, install the required packages. We use the latest version of module sdk and automations sdk, permissionless ^0.2 and viem ^2.21.
First, install the required packages. We use the latest version of module sdk and automations sdk, permissionless ^0.2 and viem ^2.21.

```sh npm2yarn
npm i viem @rhinestone/module-sdk @rhinestone/automations-sdk permissionless
Expand Down Expand Up @@ -79,9 +79,9 @@ We are also going to add the initial validator. We will use this validator to bo

```typescript copy
const ownableValidator = getOwnableValidator({
owners: ["0x2DC2fb2f4F11DeE1d6a2054ffCBf102D09b62bE2", owner.address],
owners: ['0x2DC2fb2f4F11DeE1d6a2054ffCBf102D09b62bE2', owner.address],
threshold: 1,
});
})
```

### Create the Safe account
Expand All @@ -97,7 +97,7 @@ const safeAccount = await toSafeSmartAccount({
address: entryPoint07Address,
version: '0.7',
},
safe4337ModuleAddress: '0x7579EE8307284F293B1927136486880611F20002',
safe4337ModuleAddress: '0x7579EE8307284F293B1927136486880611F20002',
erc7579LaunchpadAddress: '0x7579011aB74c46090561ea277Ba79D510c6C00ff',
attesters: [
RHINESTONE_ATTESTER_ADDRESS, // Rhinestone Attester
Expand Down
253 changes: 125 additions & 128 deletions pages/automations/tutorial-1.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ You will need to set up the smart account, install the scheduled transfers modul

### Install the packages

First, install the required packages. We use the latest version of module sdk and automations sdk, permissionless ^0.2 and viem ^2.21.
First, install the required packages. We use the latest version of module sdk and automations sdk, permissionless ^0.2 and viem ^2.21.

```sh npm2yarn
npm i viem @rhinestone/module-sdk @rhinestone/automations-sdk permissionless
Expand All @@ -19,6 +19,24 @@ npm i viem @rhinestone/module-sdk @rhinestone/automations-sdk permissionless
### Import the required functions and constants

```typescript copy
import { createSmartAccountClient } from 'permissionless'
import { toSafeSmartAccount } from 'permissionless/accounts'
import { erc7579Actions } from 'permissionless/actions/erc7579'
import { createAutomationClient } from '@rhinestone/automations-sdk'
import { createPimlicoClient } from 'permissionless/clients/pimlico'
import { generatePrivateKey, privateKeyToAccount } from 'viem/accounts'
import {
createPaymasterClient,
entryPoint07Address,
} from 'viem/account-abstraction'
import {
Address,
Chain,
createPublicClient,
encodeFunctionData,
http,
parseAbi,
} from 'viem'
import {
RHINESTONE_ATTESTER_ADDRESS,
MOCK_ATTESTER_ADDRESS,
Expand All @@ -30,25 +48,7 @@ import {
encode1271Signature,
getAccount,
encode1271Hash,
} from "@rhinestone/module-sdk";
import { generatePrivateKey, privateKeyToAccount } from "viem/accounts";
import {
Address,
Chain,
createPublicClient,
encodeFunctionData,
http,
parseAbi,
} from "viem";
import { createSmartAccountClient } from "permissionless";
import { erc7579Actions } from "permissionless/actions/erc7579";
import { createPimlicoClient } from "permissionless/clients/pimlico";
import {
createPaymasterClient,
entryPoint07Address,
} from "viem/account-abstraction";
import { toSafeSmartAccount } from "permissionless/accounts";
import { createAutomationClient } from "@rhinestone/automations-sdk";
} from '@rhinestone/module-sdk'
```

### Create the clients
Expand Down Expand Up @@ -90,9 +90,9 @@ We are also going to add the initial validator. We will use this validator to bo

```typescript copy
const ownableValidator = getOwnableValidator({
owners: ["0x2DC2fb2f4F11DeE1d6a2054ffCBf102D09b62bE2", owner.address],
owners: ['0x2DC2fb2f4F11DeE1d6a2054ffCBf102D09b62bE2', owner.address],
threshold: 1,
});
})
```

### Create the Safe account
Expand All @@ -108,7 +108,7 @@ const safeAccount = await toSafeSmartAccount({
address: entryPoint07Address,
version: '0.7',
},
safe4337ModuleAddress: '0x7579EE8307284F293B1927136486880611F20002',
safe4337ModuleAddress: '0x7579EE8307284F293B1927136486880611F20002',
erc7579LaunchpadAddress: '0x7579011aB74c46090561ea277Ba79D510c6C00ff',
attesters: [
RHINESTONE_ATTESTER_ADDRESS, // Rhinestone Attester
Expand Down Expand Up @@ -149,157 +149,154 @@ First, we will create the scheduled transfer before adding this to both the modu
We will create a scheduled transfer to send 1 usdc every 60 seconds for two times and with the defined recipient address.

```typescript copy
const executeInterval = 60; // in seconds
const numberOfExecutions = 2;
const startDate = Date.now(); // UNIX timestamp
const executeInterval = 60 // in seconds
const numberOfExecutions = 2
const startDate = Date.now() // UNIX timestamp

const scheduledTransfer = {
startDate: startDate,
repeatEvery: executeInterval,
numberOfRepeats: numberOfExecutions,
token: {
token_address: "0x8034e69FAFEd6588cc36ff3400AFE5c049a3B92E" as Address, // Mock USDC
token_address: '0x8034e69FAFEd6588cc36ff3400AFE5c049a3B92E' as Address, // Mock USDC
decimals: 6,
},
amount: 1,
recipient: "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045" as Address,
};
recipient: '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045' as Address,
}
```

### Install the scheduled transfer module

Next, we will install the scheduled transfer module. This module will store all our scheduled transfers and make sure that they can only be executed when the scheduled is met.

```typescript copy
const executionData = getScheduledTransferData({
scheduledTransfer,
});

const scheduledTransfers = getScheduledTransfersExecutor({
executeInterval,
numberOfExecutions,
startDate,
executionData,
});
const executionData = getScheduledTransferData({
scheduledTransfer,
})

const opHash = await smartAccountClient.installModule(scheduledTransfers);
const scheduledTransfers = getScheduledTransfersExecutor({
executeInterval,
numberOfExecutions,
startDate,
executionData,
})

await pimlicoClient.waitForUserOperationReceipt({
hash: opHash,
});
const opHash = await smartAccountClient.installModule(scheduledTransfers)

await pimlicoClient.waitForUserOperationReceipt({
hash: opHash,
})
```

### Mint the mock tokens

In this tutorial, we use a Mock USDC token for demonstration purposes. We will now mint some tokens to the created smart account in order to be able to transfer them.

```typescript copy
await smartAccountClient.sendTransaction({
to: scheduledTransfer.token.token_address,
data: encodeFunctionData({
abi: parseAbi(["function mint(address to, uint256 amount) external"]),
functionName: "mint",
args: [safeAccount.address, BigInt(10)],
}),
});
await smartAccountClient.sendTransaction({
to: scheduledTransfer.token.token_address,
data: encodeFunctionData({
abi: parseAbi(['function mint(address to, uint256 amount) external']),
functionName: 'mint',
args: [safeAccount.address, BigInt(10)],
}),
})
```

### Get the automation client
### Get the automation client

Next, we will create the automation client using the Automations SDK. This client will be used to interact with the automations service.
Next, we will create the automation client using the Automations SDK. This client will be used to interact with the automations service.

To use this client, we will pass our api key as well as the validator we use, the account address and type and the network, in this case sepolia.
To use this client, we will pass our api key as well as the validator we use, the account address and type and the network, in this case sepolia.

```typescript copy
const automationClient = createAutomationClient({
account: safeAccount.address,
accountType: "SAFE",
apiKey: automationsApiKey,
accountInitCode: "0x",
network: 11155111,
validator: OWNABLE_VALIDATOR_ADDRESS,
});
```
```typescript copy
const automationClient = createAutomationClient({
account: safeAccount.address,
accountType: 'SAFE',
apiKey: automationsApiKey,
accountInitCode: '0x',
network: 11155111,
validator: OWNABLE_VALIDATOR_ADDRESS,
})
```

### Create the automation
### Create the automation

Next, we will create the automation on the automation service. This matches what is stored on the module and will allow the automation service to trigger the automations at the right times and with the required calldata.
Next, we will create the automation on the automation service. This matches what is stored on the module and will allow the automation service to trigger the automations at the right times and with the required calldata.

```typescript copy
const executeScheduledTranferAction = getExecuteScheduledTransferAction({
jobId: 0, // since this is our first automation on the module
});
```typescript copy
const executeScheduledTranferAction = getExecuteScheduledTransferAction({
jobId: 0, // since this is our first automation on the module
})

const actions = [
{
type: "static" as const,
target: executeScheduledTranferAction.target,
value: Number(executeScheduledTranferAction.value),
callData: executeScheduledTranferAction.callData,
},
];

const triggerData = {
cronExpression: "* * * * *",
startDate: startDate,
};

const automation = await automationClient.createAutomation({
type: "time-based",
data: {
trigger: {
triggerData,
},
actions,
maxNumberOfExecutions: numberOfExecutions,
const actions = [
{
type: 'static' as const,
target: executeScheduledTranferAction.target,
value: Number(executeScheduledTranferAction.value),
callData: executeScheduledTranferAction.callData,
},
]

const triggerData = {
cronExpression: '* * * * *',
startDate: startDate,
}

const automation = await automationClient.createAutomation({
type: 'time-based',
data: {
trigger: {
triggerData,
},
});
```
actions,
maxNumberOfExecutions: numberOfExecutions,
},
})
```

### Activate the automation
### Activate the automation

Our automation has now been created but is not active yet. The reason for this is that anyone could create an automation on behalf of other smart accounts. To prevent this, we require a signature from the smart account to verify that the owner actually wants to create this automation.
Our automation has now been created but is not active yet. The reason for this is that anyone could create an automation on behalf of other smart accounts. To prevent this, we require a signature from the smart account to verify that the owner actually wants to create this automation.

```typescript copy
```typescript copy
const account = getAccount({
address: safeAccount.address,
type: "safe",
});

const formattedHash = encode1271Hash({
account,
validator: OWNABLE_VALIDATOR_ADDRESS,
chainId: chain.id,
hash: automation.hash,
});

const signature = await owner.signMessage({
message: { raw: formattedHash },
});

const formattedSignature = encode1271Signature({
account,
validator: OWNABLE_VALIDATOR_ADDRESS,
signature,
});

await automationClient.signAutomation({
automationId: automation.id,
signature: formattedSignature,
});
address: safeAccount.address,
type: 'safe',
})

const formattedHash = encode1271Hash({
account,
validator: OWNABLE_VALIDATOR_ADDRESS,
chainId: chain.id,
hash: automation.hash,
})

const signature = await owner.signMessage({
message: { raw: formattedHash },
})

const formattedSignature = encode1271Signature({
account,
validator: OWNABLE_VALIDATOR_ADDRESS,
signature,
})

await automationClient.signAutomation({
automationId: automation.id,
signature: formattedSignature,
})
```

### Wait for the automations

Finally our automation is created and activated. We can now wait for them to happen, such as with a timeout. Then, we can query the logs to see all our executed automations.
Finally our automation is created and activated. We can now wait for them to happen, such as with a timeout. Then, we can query the logs to see all our executed automations.

```typescript copy
await new Promise((resolve) => setTimeout(resolve, 10000));
```typescript copy
await new Promise((resolve) => setTimeout(resolve, 10000))

const automationLogs = await automationClient.getAutomationLogs(
automation.id,
);
const automationLogs = await automationClient.getAutomationLogs(automation.id)
```

</Steps>
2 changes: 1 addition & 1 deletion pages/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ Modules are self-contained smart contracts that extend a smart account's feature

There are four types of modules today:

- **Validators:** Allow developers to modify how transactions are authenticated or what can be authorized against an account. This can unlock powerful features like session keys or quantum-proof signatures.
- **Validators:** Allow developers to modify how transactions are authenticated or what can be authorized against an account. This can unlock powerful features like session keys or quantum-proof signatures.
- **Executors:** Allow developers to create executions on an account with custom logic. This, for example, can unlock portfolio management products like a take profit or stop loss feature on a DeFi platform. [ZK Email](https://blog.rhinestone.wtf/private-email-recovery-with-zk-email-3405ce4d866e) is a novel example of how powerful and versatile an executor can be.
- **Hooks:** Allow developers to augment a smart account's execution flow by hooking in pre- or post-execution and enforcing conditions or any custom logic. A simple example is a spending limit.
- **Fallbacks:** Extend the account logic to add more functionality. For example, this can allow an account to be compatible with new module types in the future.
Expand Down
2 changes: 1 addition & 1 deletion pages/module-sdk/account-guides/safe.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ const safeAccount = await toSafeSmartAccount({
address: entryPoint07Address,
version: '0.7',
},
safe4337ModuleAddress: '0x7579EE8307284F293B1927136486880611F20002',
safe4337ModuleAddress: '0x7579EE8307284F293B1927136486880611F20002',
erc7579LaunchpadAddress: '0x7579011aB74c46090561ea277Ba79D510c6C00ff',
attesters: [
RHINESTONE_ATTESTER_ADDRESS, // Rhinestone Attester
Expand Down
2 changes: 1 addition & 1 deletion pages/module-sdk/account-sdks/permissionless.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ const safeAccount = await toSafeSmartAccount({
address: entryPoint07Address,
version: '0.7',
},
safe4337ModuleAddress: '0x7579EE8307284F293B1927136486880611F20002',
safe4337ModuleAddress: '0x7579EE8307284F293B1927136486880611F20002',
erc7579LaunchpadAddress: '0x7579011aB74c46090561ea277Ba79D510c6C00ff',
attesters: [
RHINESTONE_ATTESTER_ADDRESS, // Rhinestone Attester
Expand Down
Loading

0 comments on commit 611cfd1

Please sign in to comment.