@rhinestone/sdk 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +168 -0
- package/dist/example.d.ts +1 -0
- package/dist/example.d.ts.map +1 -0
- package/dist/example.js +129 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +20 -0
- package/dist/package.json +1 -0
- package/dist/services/account.d.ts +13 -0
- package/dist/services/account.d.ts.map +1 -0
- package/dist/services/account.js +127 -0
- package/dist/services/modules.d.ts +34 -0
- package/dist/services/modules.d.ts.map +1 -0
- package/dist/services/modules.js +174 -0
- package/dist/services/orchestrator/client.d.ts +30 -0
- package/dist/services/orchestrator/client.d.ts.map +1 -0
- package/dist/services/orchestrator/client.js +203 -0
- package/dist/services/orchestrator/consts.d.ts +6 -0
- package/dist/services/orchestrator/consts.d.ts.map +1 -0
- package/dist/services/orchestrator/consts.js +4 -0
- package/dist/services/orchestrator/error.d.ts +17 -0
- package/dist/services/orchestrator/error.d.ts.map +1 -0
- package/dist/services/orchestrator/error.js +25 -0
- package/dist/services/orchestrator/index.d.ts +8 -0
- package/dist/services/orchestrator/index.d.ts.map +1 -0
- package/dist/services/orchestrator/index.js +9 -0
- package/dist/services/orchestrator/types.d.ts +147 -0
- package/dist/services/orchestrator/types.d.ts.map +1 -0
- package/dist/services/orchestrator/types.js +6 -0
- package/dist/services/orchestrator/utils.d.ts +7 -0
- package/dist/services/orchestrator/utils.d.ts.map +1 -0
- package/dist/services/orchestrator/utils.js +196 -0
- package/dist/services/transaction.d.ts +6 -0
- package/dist/services/transaction.d.ts.map +1 -0
- package/dist/services/transaction.js +93 -0
- package/dist/types.d.ts +45 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +1 -0
- package/package.json +43 -0
package/README.md
ADDED
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
# Rhinestone SDK
|
|
2
|
+
|
|
3
|
+
End-to-end chain abstraction and modularity toolkit
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
### Installation
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install viem @rhinestone/sdk
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
pnpm install viem @rhinestone/sdk
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
yarn add viem @rhinestone/sdk
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
bun install viem @rhinestone/sdk
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
### Quick Start
|
|
26
|
+
|
|
27
|
+
You'll need a Rhinestone API key, as well as an existing account with some testnet tokens.
|
|
28
|
+
|
|
29
|
+
You can get some testnet USDC using a [Circle Faucet](https://faucet.circle.com). Make sure you have the testnet ETH on the source chain as well.
|
|
30
|
+
|
|
31
|
+
## Creating a Wallet
|
|
32
|
+
|
|
33
|
+
Let's create a single-owner Safe account:
|
|
34
|
+
|
|
35
|
+
```ts
|
|
36
|
+
import { generatePrivateKey, privateKeyToAccount } from 'viem/accounts'
|
|
37
|
+
import { baseSepolia, arbitrumSepolia, optimismSepolia } from 'viem/chains'
|
|
38
|
+
import {
|
|
39
|
+
Chain,
|
|
40
|
+
createPublicClient,
|
|
41
|
+
createWalletClient,
|
|
42
|
+
encodeFunctionData,
|
|
43
|
+
erc20Abi,
|
|
44
|
+
Hex,
|
|
45
|
+
http,
|
|
46
|
+
parseEther,
|
|
47
|
+
} from 'viem'
|
|
48
|
+
|
|
49
|
+
import { createRhinestoneAccount } from '@rhinestone/sdk'
|
|
50
|
+
|
|
51
|
+
const fundingPrivateKey = process.env.FUNDING_PRIVATE_KEY
|
|
52
|
+
if (!fundingPrivateKey) {
|
|
53
|
+
throw new Error('FUNDING_PRIVATE_KEY is not set')
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const rhinestoneApiKey = process.env.RHINESTONE_API_KEY
|
|
57
|
+
if (!rhinestoneApiKey) {
|
|
58
|
+
throw new Error('RHINESTONE_API_KEY is not set')
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const sourceChain = baseSepolia
|
|
62
|
+
const targetChain = arbitrumSepolia
|
|
63
|
+
|
|
64
|
+
const fundingAccount = privateKeyToAccount(fundingPrivateKey as Hex)
|
|
65
|
+
const publicClient = createPublicClient({
|
|
66
|
+
chain: sourceChain,
|
|
67
|
+
transport: http(),
|
|
68
|
+
})
|
|
69
|
+
const fundingClient = createWalletClient({
|
|
70
|
+
account: fundingAccount,
|
|
71
|
+
chain: sourceChain,
|
|
72
|
+
transport: http(),
|
|
73
|
+
})
|
|
74
|
+
|
|
75
|
+
// You can use an existing PK here
|
|
76
|
+
const privateKey = generatePrivateKey()
|
|
77
|
+
console.log('pk', privateKey)
|
|
78
|
+
const account = privateKeyToAccount(privateKey)
|
|
79
|
+
|
|
80
|
+
const rhinestoneAccount = await createRhinestoneAccount({
|
|
81
|
+
account: {
|
|
82
|
+
type: 'safe',
|
|
83
|
+
},
|
|
84
|
+
owners: {
|
|
85
|
+
type: 'ecdsa',
|
|
86
|
+
accounts: [account],
|
|
87
|
+
}
|
|
88
|
+
rhinestoneApiKey,
|
|
89
|
+
deployerAccount: fundingAccount,
|
|
90
|
+
})
|
|
91
|
+
const address = await rhinestoneAccount.getAddress(sourceChain)
|
|
92
|
+
console.log(address)
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## Funding the Account
|
|
96
|
+
|
|
97
|
+
We will send some tokens from the funding account to the Safe account.
|
|
98
|
+
|
|
99
|
+
```ts
|
|
100
|
+
const usdc = getTokenAddress(sourceChain)
|
|
101
|
+
const usdcTarget = getTokenAddress(targetChain)
|
|
102
|
+
const usdcAmount = 1n
|
|
103
|
+
|
|
104
|
+
const txHash = await fundingClient.sendTransaction({
|
|
105
|
+
to: address,
|
|
106
|
+
value: parseEther('0.001'),
|
|
107
|
+
})
|
|
108
|
+
await publicClient.waitForTransactionReceipt({ hash: txHash })
|
|
109
|
+
|
|
110
|
+
const txHash2 = await fundingClient.sendTransaction({
|
|
111
|
+
to: usdcSource,
|
|
112
|
+
data: encodeFunctionData({
|
|
113
|
+
abi: erc20Abi,
|
|
114
|
+
functionName: 'transfer',
|
|
115
|
+
args: [address, usdcAmount],
|
|
116
|
+
}),
|
|
117
|
+
})
|
|
118
|
+
await publicClient.waitForTransactionReceipt({ hash: txHash2 })
|
|
119
|
+
|
|
120
|
+
function getTokenAddress(chain: Chain) {
|
|
121
|
+
switch (chain.id) {
|
|
122
|
+
case baseSepolia.id:
|
|
123
|
+
return '0x036cbd53842c5426634e7929541ec2318f3dcf7e'
|
|
124
|
+
case arbitrumSepolia.id:
|
|
125
|
+
return '0x75faf114eafb1BDbe2F0316DF893fd58CE46AA4d'
|
|
126
|
+
case optimismSepolia.id:
|
|
127
|
+
return '0x5fd84259d66Cd46123540766Be93DFE6D43130D7'
|
|
128
|
+
default:
|
|
129
|
+
throw new Error('Unsupported chain')
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
## Sending a Cross-chain Transaction
|
|
135
|
+
|
|
136
|
+
Finally, let's make a cross-chain token transfer:
|
|
137
|
+
|
|
138
|
+
```ts
|
|
139
|
+
const bundleId = await rhinestoneAccount.sendTransactions({
|
|
140
|
+
sourceChain,
|
|
141
|
+
targetChain,
|
|
142
|
+
calls: [
|
|
143
|
+
{
|
|
144
|
+
to: usdcTarget,
|
|
145
|
+
value: 0n,
|
|
146
|
+
data: encodeFunctionData({
|
|
147
|
+
abi: erc20Abi,
|
|
148
|
+
functionName: 'transfer',
|
|
149
|
+
args: ['0xd8da6bf26964af9d7eed9e03e53415d37aa96045', usdcAmount],
|
|
150
|
+
}),
|
|
151
|
+
},
|
|
152
|
+
],
|
|
153
|
+
tokenRequests: [
|
|
154
|
+
{
|
|
155
|
+
address: usdcTarget,
|
|
156
|
+
amount: usdcAmount,
|
|
157
|
+
},
|
|
158
|
+
],
|
|
159
|
+
})
|
|
160
|
+
console.log('id', bundleId)
|
|
161
|
+
|
|
162
|
+
const bundleResult = await rhinestoneAccount.waitForExecution({ id: bundleId })
|
|
163
|
+
console.log('status', bundleResult.status)
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
## Contributing
|
|
167
|
+
|
|
168
|
+
For feature or change requests, feel free to open a PR, start a discussion or get in touch with us.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
//# sourceMappingURL=example.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"example.d.ts","sourceRoot":"","sources":["../example.ts"],"names":[],"mappings":""}
|
package/dist/example.js
ADDED
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// import { generatePrivateKey, privateKeyToAccount } from 'viem/accounts'
|
|
3
|
+
// import { baseSepolia, arbitrumSepolia, optimismSepolia } from 'viem/chains'
|
|
4
|
+
// import {
|
|
5
|
+
// Chain,
|
|
6
|
+
// createPublicClient,
|
|
7
|
+
// createWalletClient,
|
|
8
|
+
// encodeFunctionData,
|
|
9
|
+
// erc20Abi,
|
|
10
|
+
// Hex,
|
|
11
|
+
// http,
|
|
12
|
+
// parseEther,
|
|
13
|
+
// parseUnits,
|
|
14
|
+
// } from 'viem'
|
|
15
|
+
// import { createRhinestoneAccount } from './index'
|
|
16
|
+
// const fundingPrivateKey = process.env.FUNDING_PRIVATE_KEY
|
|
17
|
+
// if (!fundingPrivateKey) {
|
|
18
|
+
// throw new Error('FUNDING_PRIVATE_KEY is not set')
|
|
19
|
+
// }
|
|
20
|
+
// const rhinestoneApiKey = process.env.RHINESTONE_API_KEY
|
|
21
|
+
// if (!rhinestoneApiKey) {
|
|
22
|
+
// throw new Error('RHINESTONE_API_KEY is not set')
|
|
23
|
+
// }
|
|
24
|
+
// const sourceChain = baseSepolia
|
|
25
|
+
// const targetChain = arbitrumSepolia
|
|
26
|
+
// const usdc = getTokenAddress(sourceChain)
|
|
27
|
+
// const usdcTarget = getTokenAddress(targetChain)
|
|
28
|
+
// const usdcAmount = 1n
|
|
29
|
+
// const fundingAccount = privateKeyToAccount(fundingPrivateKey as Hex)
|
|
30
|
+
// const publicClient = createPublicClient({
|
|
31
|
+
// chain: sourceChain,
|
|
32
|
+
// transport: http(),
|
|
33
|
+
// })
|
|
34
|
+
// const fundingClient = createWalletClient({
|
|
35
|
+
// account: fundingAccount,
|
|
36
|
+
// chain: sourceChain,
|
|
37
|
+
// transport: http(),
|
|
38
|
+
// })
|
|
39
|
+
// console.log('new pks', [
|
|
40
|
+
// generatePrivateKey(),
|
|
41
|
+
// generatePrivateKey(),
|
|
42
|
+
// generatePrivateKey(),
|
|
43
|
+
// ])
|
|
44
|
+
// const privateKeyA =
|
|
45
|
+
// '0x04ba71050a787d8b50dbe6cfd35810276699a9eb6dae8c0ac48ccbf8d891324c'
|
|
46
|
+
// const accountA = privateKeyToAccount(privateKeyA)
|
|
47
|
+
// const privateKeyB =
|
|
48
|
+
// '0x921e8d0b257173f92791f47c14ecb84f0545a897a7b12f477a9fb743c1d2b2e3'
|
|
49
|
+
// const accountB = privateKeyToAccount(privateKeyB)
|
|
50
|
+
// const privateKeyC =
|
|
51
|
+
// '0xc55f1b744fcd9781d6a711fa8347dd41cf6fb662249aede85ed77e95bb2f3aa2'
|
|
52
|
+
// const accountC = privateKeyToAccount(privateKeyC)
|
|
53
|
+
// const rhinestoneAccount = await createRhinestoneAccount({
|
|
54
|
+
// account: {
|
|
55
|
+
// type: 'safe',
|
|
56
|
+
// },
|
|
57
|
+
// owners: {
|
|
58
|
+
// type: 'ecdsa',
|
|
59
|
+
// accounts: [accountA, accountB],
|
|
60
|
+
// },
|
|
61
|
+
// rhinestoneApiKey,
|
|
62
|
+
// deployerAccount: fundingAccount,
|
|
63
|
+
// })
|
|
64
|
+
// const address = await rhinestoneAccount.getAddress()
|
|
65
|
+
// console.log(address)
|
|
66
|
+
// // prefund
|
|
67
|
+
// const ethBalance = await publicClient.getBalance({
|
|
68
|
+
// address,
|
|
69
|
+
// })
|
|
70
|
+
// if (ethBalance < parseEther('0.001')) {
|
|
71
|
+
// const txHash = await fundingClient.sendTransaction({
|
|
72
|
+
// to: address,
|
|
73
|
+
// value: parseEther('0.001'),
|
|
74
|
+
// })
|
|
75
|
+
// await publicClient.waitForTransactionReceipt({ hash: txHash })
|
|
76
|
+
// }
|
|
77
|
+
// const usdcBalance = await publicClient.readContract({
|
|
78
|
+
// address: usdc,
|
|
79
|
+
// abi: erc20Abi,
|
|
80
|
+
// functionName: 'balanceOf',
|
|
81
|
+
// args: [address],
|
|
82
|
+
// })
|
|
83
|
+
// if (usdcBalance < usdcAmount) {
|
|
84
|
+
// const txHash2 = await fundingClient.sendTransaction({
|
|
85
|
+
// to: usdc,
|
|
86
|
+
// data: encodeFunctionData({
|
|
87
|
+
// abi: erc20Abi,
|
|
88
|
+
// functionName: 'transfer',
|
|
89
|
+
// args: [address, usdcAmount],
|
|
90
|
+
// }),
|
|
91
|
+
// })
|
|
92
|
+
// await publicClient.waitForTransactionReceipt({ hash: txHash2 })
|
|
93
|
+
// }
|
|
94
|
+
// const bundleId = await rhinestoneAccount.sendTransactions({
|
|
95
|
+
// sourceChain,
|
|
96
|
+
// targetChain,
|
|
97
|
+
// calls: [
|
|
98
|
+
// {
|
|
99
|
+
// to: usdcTarget,
|
|
100
|
+
// value: 0n,
|
|
101
|
+
// data: encodeFunctionData({
|
|
102
|
+
// abi: erc20Abi,
|
|
103
|
+
// functionName: 'transfer',
|
|
104
|
+
// args: ['0xd8da6bf26964af9d7eed9e03e53415d37aa96045', usdcAmount],
|
|
105
|
+
// }),
|
|
106
|
+
// },
|
|
107
|
+
// ],
|
|
108
|
+
// tokenRequests: [
|
|
109
|
+
// {
|
|
110
|
+
// address: usdcTarget,
|
|
111
|
+
// amount: usdcAmount,
|
|
112
|
+
// },
|
|
113
|
+
// ],
|
|
114
|
+
// })
|
|
115
|
+
// console.log('id', bundleId)
|
|
116
|
+
// const bundleResult = await rhinestoneAccount.waitForExecution({ id: bundleId })
|
|
117
|
+
// console.log('status', bundleResult.status)
|
|
118
|
+
// function getTokenAddress(chain: Chain) {
|
|
119
|
+
// switch (chain.id) {
|
|
120
|
+
// case baseSepolia.id:
|
|
121
|
+
// return '0x036cbd53842c5426634e7929541ec2318f3dcf7e'
|
|
122
|
+
// case arbitrumSepolia.id:
|
|
123
|
+
// return '0x75faf114eafb1BDbe2F0316DF893fd58CE46AA4d'
|
|
124
|
+
// case optimismSepolia.id:
|
|
125
|
+
// return '0x5fd84259d66Cd46123540766Be93DFE6D43130D7'
|
|
126
|
+
// default:
|
|
127
|
+
// throw new Error('Unsupported chain')
|
|
128
|
+
// }
|
|
129
|
+
// }
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { RhinestoneAccountConfig, Transaction } from './types';
|
|
2
|
+
declare function createRhinestoneAccount(config: RhinestoneAccountConfig): Promise<{
|
|
3
|
+
config: RhinestoneAccountConfig;
|
|
4
|
+
sendTransactions: (transaction: Transaction) => Promise<bigint>;
|
|
5
|
+
waitForExecution: ({ id }: {
|
|
6
|
+
id: bigint;
|
|
7
|
+
}) => Promise<import("./services/orchestrator").BundleResult>;
|
|
8
|
+
getAddress: () => Promise<`0x${string}`>;
|
|
9
|
+
}>;
|
|
10
|
+
export { createRhinestoneAccount };
|
|
11
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,uBAAuB,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AAO9D,iBAAe,uBAAuB,CAAC,MAAM,EAAE,uBAAuB;;oCACvB,WAAW;+BAIhB;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE;;GAcvD;AAED,OAAO,EAAE,uBAAuB,EAAE,CAAA"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { sendTransactions as sendTransactionsInternal, waitForExecution as waitForExecutionInternal, } from './services/transaction';
|
|
2
|
+
import { getAddress as getAddressInternal } from './services/account';
|
|
3
|
+
async function createRhinestoneAccount(config) {
|
|
4
|
+
const sendTransactions = async (transaction) => {
|
|
5
|
+
return await sendTransactionsInternal(config, transaction);
|
|
6
|
+
};
|
|
7
|
+
const waitForExecution = async ({ id }) => {
|
|
8
|
+
return await waitForExecutionInternal(config, id);
|
|
9
|
+
};
|
|
10
|
+
const getAddress = async () => {
|
|
11
|
+
return await getAddressInternal(config);
|
|
12
|
+
};
|
|
13
|
+
return {
|
|
14
|
+
config,
|
|
15
|
+
sendTransactions,
|
|
16
|
+
waitForExecution,
|
|
17
|
+
getAddress,
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
export { createRhinestoneAccount };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"type": "module","sideEffects":false}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Chain, Account } from 'viem';
|
|
2
|
+
import { RhinestoneAccountConfig } from '../types';
|
|
3
|
+
declare function getAddress(config: RhinestoneAccountConfig): Promise<`0x${string}`>;
|
|
4
|
+
declare function isDeployed(chain: Chain, config: RhinestoneAccountConfig): Promise<boolean>;
|
|
5
|
+
declare function deploy(deployer: Account, chain: Chain, config: RhinestoneAccountConfig): Promise<void>;
|
|
6
|
+
declare function getDeployArgs(config: RhinestoneAccountConfig): Promise<{
|
|
7
|
+
factory: `0x${string}`;
|
|
8
|
+
factoryData: `0x${string}`;
|
|
9
|
+
salt: `0x${string}`;
|
|
10
|
+
hashedInitcode: `0x${string}`;
|
|
11
|
+
}>;
|
|
12
|
+
export { getAddress, isDeployed, getDeployArgs, deploy };
|
|
13
|
+
//# sourceMappingURL=account.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"account.d.ts","sourceRoot":"","sources":["../../services/account.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,EAQL,OAAO,EAOR,MAAM,MAAM,CAAA;AAOb,OAAO,EAAE,uBAAuB,EAAE,MAAM,UAAU,CAAA;AAelD,iBAAe,UAAU,CAAC,MAAM,EAAE,uBAAuB,0BAUxD;AAED,iBAAe,UAAU,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,uBAAuB,oBAgBtE;AAED,iBAAe,MAAM,CACnB,QAAQ,EAAE,OAAO,EACjB,KAAK,EAAE,KAAK,EACZ,MAAM,EAAE,uBAAuB,iBAiBhC;AAED,iBAAe,aAAa,CAAC,MAAM,EAAE,uBAAuB;;;;;GA6F3D;AAED,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,EAAE,CAAA"}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { createPublicClient, http, encodeAbiParameters, encodeFunctionData, parseAbi, zeroAddress, createWalletClient, size, keccak256, encodePacked, slice, } from 'viem';
|
|
2
|
+
import { HOOK_ADDRESS, SAME_CHAIN_MODULE_ADDRESS, TARGET_MODULE_ADDRESS, } from './orchestrator';
|
|
3
|
+
import { getValidator, toOwners, SAFE_7579_LAUNCHPAD_ADDRESS, SAFE_7579_ADAPTER_ADDRESS, OMNI_ACCOUNT_MOCK_ATTESTER_ADDRESS, RHINESTONE_ATTESTER_ADDRESS, } from './modules';
|
|
4
|
+
const SAFE_SINGLETON_ADDRESS = '0x29fcb43b46531bca003ddc8fcb67ffe91900c762';
|
|
5
|
+
const SAFE_PROXY_FACTORY_ADDRESS = '0x4e1dcf7ad4e460cfd30791ccc4f9c8a4f820ec67';
|
|
6
|
+
async function getAddress(config) {
|
|
7
|
+
const { factory, salt, hashedInitcode } = await getDeployArgs(config);
|
|
8
|
+
const hash = keccak256(encodePacked(['bytes1', 'address', 'bytes32', 'bytes'], ['0xff', factory, salt, hashedInitcode]));
|
|
9
|
+
const address = slice(hash, 12, 32);
|
|
10
|
+
return address;
|
|
11
|
+
}
|
|
12
|
+
async function isDeployed(chain, config) {
|
|
13
|
+
const publicClient = createPublicClient({
|
|
14
|
+
chain: chain,
|
|
15
|
+
transport: http(),
|
|
16
|
+
});
|
|
17
|
+
const address = await getAddress(config);
|
|
18
|
+
const code = await publicClient.getCode({
|
|
19
|
+
address,
|
|
20
|
+
});
|
|
21
|
+
if (!code) {
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
if (code.startsWith('0xef0100') && code.length === 48) {
|
|
25
|
+
throw new Error('EIP-7702 accounts are not yet supported');
|
|
26
|
+
}
|
|
27
|
+
return size(code) > 0;
|
|
28
|
+
}
|
|
29
|
+
async function deploy(deployer, chain, config) {
|
|
30
|
+
const { factory, factoryData } = await getDeployArgs(config);
|
|
31
|
+
const publicClient = createPublicClient({
|
|
32
|
+
chain: chain,
|
|
33
|
+
transport: http(),
|
|
34
|
+
});
|
|
35
|
+
const client = createWalletClient({
|
|
36
|
+
account: deployer,
|
|
37
|
+
chain: chain,
|
|
38
|
+
transport: http(),
|
|
39
|
+
});
|
|
40
|
+
const tx = await client.sendTransaction({
|
|
41
|
+
to: factory,
|
|
42
|
+
data: factoryData,
|
|
43
|
+
});
|
|
44
|
+
await publicClient.waitForTransactionReceipt({ hash: tx });
|
|
45
|
+
}
|
|
46
|
+
async function getDeployArgs(config) {
|
|
47
|
+
switch (config.account.type) {
|
|
48
|
+
case 'safe': {
|
|
49
|
+
const owners = toOwners(config);
|
|
50
|
+
const initializer = encodeFunctionData({
|
|
51
|
+
abi: parseAbi([
|
|
52
|
+
'function setup(address[] calldata _owners,uint256 _threshold,address to,bytes calldata data,address fallbackHandler,address paymentToken,uint256 payment, address paymentReceiver) external',
|
|
53
|
+
]),
|
|
54
|
+
functionName: 'setup',
|
|
55
|
+
args: [
|
|
56
|
+
owners,
|
|
57
|
+
BigInt(1),
|
|
58
|
+
SAFE_7579_LAUNCHPAD_ADDRESS,
|
|
59
|
+
encodeFunctionData({
|
|
60
|
+
abi: parseAbi([
|
|
61
|
+
'struct ModuleInit {address module;bytes initData;}',
|
|
62
|
+
'function addSafe7579(address safe7579,ModuleInit[] calldata validators,ModuleInit[] calldata executors,ModuleInit[] calldata fallbacks, ModuleInit[] calldata hooks,address[] calldata attesters,uint8 threshold) external',
|
|
63
|
+
]),
|
|
64
|
+
functionName: 'addSafe7579',
|
|
65
|
+
args: [
|
|
66
|
+
SAFE_7579_ADAPTER_ADDRESS,
|
|
67
|
+
[
|
|
68
|
+
{
|
|
69
|
+
module: getValidator(config).address,
|
|
70
|
+
initData: getValidator(config).initData,
|
|
71
|
+
},
|
|
72
|
+
],
|
|
73
|
+
[
|
|
74
|
+
{
|
|
75
|
+
module: SAME_CHAIN_MODULE_ADDRESS,
|
|
76
|
+
initData: '0x',
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
module: TARGET_MODULE_ADDRESS,
|
|
80
|
+
initData: '0x',
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
module: HOOK_ADDRESS,
|
|
84
|
+
initData: '0x',
|
|
85
|
+
},
|
|
86
|
+
],
|
|
87
|
+
[
|
|
88
|
+
{
|
|
89
|
+
module: TARGET_MODULE_ADDRESS,
|
|
90
|
+
initData: encodeAbiParameters([
|
|
91
|
+
{ name: 'selector', type: 'bytes4' },
|
|
92
|
+
{ name: 'flags', type: 'bytes1' },
|
|
93
|
+
{ name: 'data', type: 'bytes' },
|
|
94
|
+
], ['0x3a5be8cb', '0x00', '0x']),
|
|
95
|
+
},
|
|
96
|
+
],
|
|
97
|
+
[],
|
|
98
|
+
[RHINESTONE_ATTESTER_ADDRESS, OMNI_ACCOUNT_MOCK_ATTESTER_ADDRESS],
|
|
99
|
+
1,
|
|
100
|
+
],
|
|
101
|
+
}),
|
|
102
|
+
SAFE_7579_ADAPTER_ADDRESS,
|
|
103
|
+
zeroAddress,
|
|
104
|
+
BigInt(0),
|
|
105
|
+
zeroAddress,
|
|
106
|
+
],
|
|
107
|
+
});
|
|
108
|
+
const saltNonce = 0n;
|
|
109
|
+
const factoryData = encodeFunctionData({
|
|
110
|
+
abi: parseAbi([
|
|
111
|
+
'function createProxyWithNonce(address singleton,bytes calldata initializer,uint256 saltNonce) external payable returns (address)',
|
|
112
|
+
]),
|
|
113
|
+
functionName: 'createProxyWithNonce',
|
|
114
|
+
args: [SAFE_SINGLETON_ADDRESS, initializer, saltNonce],
|
|
115
|
+
});
|
|
116
|
+
const salt = keccak256(encodePacked(['bytes32', 'uint256'], [keccak256(initializer), saltNonce]));
|
|
117
|
+
const hashedInitcode = '0xe298282cefe913ab5d282047161268a8222e4bd4ed106300c547894bbefd31ee';
|
|
118
|
+
return {
|
|
119
|
+
factory: SAFE_PROXY_FACTORY_ADDRESS,
|
|
120
|
+
factoryData,
|
|
121
|
+
salt,
|
|
122
|
+
hashedInitcode,
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
export { getAddress, isDeployed, getDeployArgs, deploy };
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { Address, Chain, Hex } from 'viem';
|
|
2
|
+
import { RhinestoneAccountConfig } from '../types';
|
|
3
|
+
type ModuleType = 'validator' | 'executor' | 'fallback' | 'hook';
|
|
4
|
+
interface Module {
|
|
5
|
+
address: Address;
|
|
6
|
+
initData: Hex;
|
|
7
|
+
deInitData: Hex;
|
|
8
|
+
additionalContext: Hex;
|
|
9
|
+
type: ModuleType;
|
|
10
|
+
}
|
|
11
|
+
interface WebAuthnData {
|
|
12
|
+
authenticatorData: Hex;
|
|
13
|
+
clientDataJSON: string;
|
|
14
|
+
typeIndex: number | bigint;
|
|
15
|
+
}
|
|
16
|
+
interface WebauthnValidatorSignature {
|
|
17
|
+
webauthn: WebAuthnData;
|
|
18
|
+
signature: WebauthnSignature | Hex | Uint8Array;
|
|
19
|
+
usePrecompiled?: boolean;
|
|
20
|
+
}
|
|
21
|
+
interface WebauthnSignature {
|
|
22
|
+
r: bigint;
|
|
23
|
+
s: bigint;
|
|
24
|
+
}
|
|
25
|
+
declare const SAFE_7579_LAUNCHPAD_ADDRESS: Address;
|
|
26
|
+
declare const SAFE_7579_ADAPTER_ADDRESS: Address;
|
|
27
|
+
declare const OMNI_ACCOUNT_MOCK_ATTESTER_ADDRESS: Address;
|
|
28
|
+
declare const RHINESTONE_ATTESTER_ADDRESS: Address;
|
|
29
|
+
declare function toOwners(config: RhinestoneAccountConfig): `0x${string}`[];
|
|
30
|
+
declare function getValidator(config: RhinestoneAccountConfig): Module;
|
|
31
|
+
export declare function getWebauthnValidatorSignature({ webauthn, signature, usePrecompiled, }: WebauthnValidatorSignature): `0x${string}`;
|
|
32
|
+
export declare function isRip7212SupportedNetwork(chain: Chain): boolean;
|
|
33
|
+
export { getValidator, toOwners, SAFE_7579_LAUNCHPAD_ADDRESS, SAFE_7579_ADAPTER_ADDRESS, OMNI_ACCOUNT_MOCK_ATTESTER_ADDRESS, RHINESTONE_ATTESTER_ADDRESS, };
|
|
34
|
+
//# sourceMappingURL=modules.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"modules.d.ts","sourceRoot":"","sources":["../../services/modules.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,OAAO,EAEP,KAAK,EAEL,GAAG,EAIJ,MAAM,MAAM,CAAA;AAYb,OAAO,EAAE,uBAAuB,EAAE,MAAM,UAAU,CAAA;AAElD,KAAK,UAAU,GAAG,WAAW,GAAG,UAAU,GAAG,UAAU,GAAG,MAAM,CAAA;AAEhE,UAAU,MAAM;IACd,OAAO,EAAE,OAAO,CAAA;IAChB,QAAQ,EAAE,GAAG,CAAA;IACb,UAAU,EAAE,GAAG,CAAA;IACf,iBAAiB,EAAE,GAAG,CAAA;IACtB,IAAI,EAAE,UAAU,CAAA;CACjB;AAcD,UAAU,YAAY;IACpB,iBAAiB,EAAE,GAAG,CAAA;IACtB,cAAc,EAAE,MAAM,CAAA;IACtB,SAAS,EAAE,MAAM,GAAG,MAAM,CAAA;CAC3B;AAED,UAAU,0BAA0B;IAClC,QAAQ,EAAE,YAAY,CAAA;IACtB,SAAS,EAAE,iBAAiB,GAAG,GAAG,GAAG,UAAU,CAAA;IAC/C,cAAc,CAAC,EAAE,OAAO,CAAA;CACzB;AAED,UAAU,iBAAiB;IACzB,CAAC,EAAE,MAAM,CAAA;IACT,CAAC,EAAE,MAAM,CAAA;CACV;AAED,QAAA,MAAM,2BAA2B,EAAE,OACW,CAAA;AAC9C,QAAA,MAAM,yBAAyB,EAAE,OACa,CAAA;AAE9C,QAAA,MAAM,kCAAkC,EAAE,OACI,CAAA;AAE9C,QAAA,MAAM,2BAA2B,EAAE,OACW,CAAA;AAS9C,iBAAS,QAAQ,CAAC,MAAM,EAAE,uBAAuB,mBAQhD;AAED,iBAAS,YAAY,CAAC,MAAM,EAAE,uBAAuB,UAcpD;AAkFD,wBAAgB,6BAA6B,CAAC,EAC5C,QAAQ,EACR,SAAS,EACT,cAAsB,GACvB,EAAE,0BAA0B,iBA6C5B;AAED,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,KAAK,WAarD;AA0BD,OAAO,EACL,YAAY,EACZ,QAAQ,EACR,2BAA2B,EAC3B,yBAAyB,EACzB,kCAAkC,EAClC,2BAA2B,GAC5B,CAAA"}
|