@rhinestone/sdk 0.1.0 → 0.2.1
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 +4 -16
- package/dist/accounts/index.d.ts +24 -0
- package/dist/accounts/index.d.ts.map +1 -0
- package/dist/accounts/index.js +183 -0
- package/dist/accounts/nexus.d.ts +7771 -0
- package/dist/accounts/nexus.d.ts.map +1 -0
- package/dist/accounts/nexus.js +209 -0
- package/dist/accounts/safe.d.ts +13 -0
- package/dist/accounts/safe.d.ts.map +1 -0
- package/dist/accounts/safe.js +100 -0
- package/dist/accounts/utils.d.ts +27 -0
- package/dist/accounts/utils.d.ts.map +1 -0
- package/dist/accounts/utils.js +155 -0
- package/dist/example.js +32 -27
- package/dist/{services/transaction.d.ts → execution/index.d.ts} +2 -2
- package/dist/execution/index.d.ts.map +1 -0
- package/dist/{services/transaction.js → execution/index.js} +12 -13
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/{services/modules.d.ts → modules/index.d.ts} +18 -8
- package/dist/modules/index.d.ts.map +1 -0
- package/dist/{services/modules.js → modules/index.js} +75 -15
- package/dist/orchestrator/client.d.ts.map +1 -0
- package/dist/orchestrator/consts.d.ts +2 -0
- package/dist/orchestrator/consts.d.ts.map +1 -0
- package/dist/orchestrator/consts.js +1 -0
- package/dist/orchestrator/error.d.ts.map +1 -0
- package/dist/orchestrator/index.d.ts +7 -0
- package/dist/orchestrator/index.d.ts.map +1 -0
- package/dist/{services/orchestrator → orchestrator}/index.js +2 -2
- package/dist/orchestrator/types.d.ts.map +1 -0
- package/dist/orchestrator/utils.d.ts.map +1 -0
- package/dist/{services/orchestrator → orchestrator}/utils.js +1 -1
- package/dist/types.d.ts +8 -6
- package/dist/types.d.ts.map +1 -1
- package/package.json +3 -3
- package/dist/services/account.d.ts +0 -13
- package/dist/services/account.d.ts.map +0 -1
- package/dist/services/account.js +0 -127
- package/dist/services/modules.d.ts.map +0 -1
- package/dist/services/orchestrator/client.d.ts.map +0 -1
- package/dist/services/orchestrator/consts.d.ts +0 -6
- package/dist/services/orchestrator/consts.d.ts.map +0 -1
- package/dist/services/orchestrator/consts.js +0 -4
- package/dist/services/orchestrator/error.d.ts.map +0 -1
- package/dist/services/orchestrator/index.d.ts +0 -8
- package/dist/services/orchestrator/index.d.ts.map +0 -1
- package/dist/services/orchestrator/types.d.ts.map +0 -1
- package/dist/services/orchestrator/utils.d.ts.map +0 -1
- package/dist/services/transaction.d.ts.map +0 -1
- /package/dist/{services/orchestrator → orchestrator}/client.d.ts +0 -0
- /package/dist/{services/orchestrator → orchestrator}/client.js +0 -0
- /package/dist/{services/orchestrator → orchestrator}/error.d.ts +0 -0
- /package/dist/{services/orchestrator → orchestrator}/error.js +0 -0
- /package/dist/{services/orchestrator → orchestrator}/types.d.ts +0 -0
- /package/dist/{services/orchestrator → orchestrator}/types.js +0 -0
- /package/dist/{services/orchestrator → orchestrator}/utils.d.ts +0 -0
package/README.md
CHANGED
|
@@ -22,11 +22,9 @@ yarn add viem @rhinestone/sdk
|
|
|
22
22
|
bun install viem @rhinestone/sdk
|
|
23
23
|
```
|
|
24
24
|
|
|
25
|
-
###
|
|
25
|
+
### Quickstart
|
|
26
26
|
|
|
27
|
-
You'll need a Rhinestone API key, as well as an existing account with some testnet
|
|
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.
|
|
27
|
+
You'll need a Rhinestone API key, as well as an existing account with some testnet ETH on the source chain.
|
|
30
28
|
|
|
31
29
|
## Creating a Wallet
|
|
32
30
|
|
|
@@ -79,7 +77,7 @@ const account = privateKeyToAccount(privateKey)
|
|
|
79
77
|
|
|
80
78
|
const rhinestoneAccount = await createRhinestoneAccount({
|
|
81
79
|
account: {
|
|
82
|
-
type: '
|
|
80
|
+
type: 'nexus',
|
|
83
81
|
},
|
|
84
82
|
owners: {
|
|
85
83
|
type: 'ecdsa',
|
|
@@ -94,7 +92,7 @@ console.log(address)
|
|
|
94
92
|
|
|
95
93
|
## Funding the Account
|
|
96
94
|
|
|
97
|
-
We will send some
|
|
95
|
+
We will send some ETH from the funding account to the created Safe account. The Orchestrator will use some of that ETH to deploy the account on the target chain, as well as convert it to USDC for a transfer transaction.
|
|
98
96
|
|
|
99
97
|
```ts
|
|
100
98
|
const usdc = getTokenAddress(sourceChain)
|
|
@@ -107,16 +105,6 @@ const txHash = await fundingClient.sendTransaction({
|
|
|
107
105
|
})
|
|
108
106
|
await publicClient.waitForTransactionReceipt({ hash: txHash })
|
|
109
107
|
|
|
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
108
|
function getTokenAddress(chain: Chain) {
|
|
121
109
|
switch (chain.id) {
|
|
122
110
|
case baseSepolia.id:
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Account, Chain } from 'viem';
|
|
2
|
+
import { RhinestoneAccountConfig } from '../types';
|
|
3
|
+
declare function getDeployArgs(config: RhinestoneAccountConfig): Promise<{
|
|
4
|
+
factory: `0x${string}`;
|
|
5
|
+
factoryData: `0x${string}`;
|
|
6
|
+
salt: `0x${string}`;
|
|
7
|
+
hashedInitcode: `0x${string}`;
|
|
8
|
+
implementation: `0x${string}`;
|
|
9
|
+
initializationCallData: null;
|
|
10
|
+
} | {
|
|
11
|
+
factory: `0x${string}`;
|
|
12
|
+
factoryData: `0x${string}`;
|
|
13
|
+
salt: `0x${string}`;
|
|
14
|
+
hashedInitcode: `0x${string}`;
|
|
15
|
+
implementation: `0x${string}`;
|
|
16
|
+
initializationCallData: `0x${string}`;
|
|
17
|
+
}>;
|
|
18
|
+
declare function getAddress(config: RhinestoneAccountConfig): Promise<`0x${string}`>;
|
|
19
|
+
declare function isDeployed(chain: Chain, config: RhinestoneAccountConfig): Promise<boolean>;
|
|
20
|
+
declare function deploySource(deployer: Account, chain: Chain, config: RhinestoneAccountConfig): Promise<void>;
|
|
21
|
+
declare function deployTarget(chain: Chain, config: RhinestoneAccountConfig): Promise<void>;
|
|
22
|
+
declare function getBundleInitCode(config: RhinestoneAccountConfig): Promise<`0x${string}` | undefined>;
|
|
23
|
+
export { getDeployArgs, getBundleInitCode, getAddress, isDeployed, deploySource, deployTarget, };
|
|
24
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../accounts/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,OAAO,EACP,KAAK,EASN,MAAM,MAAM,CAAA;AAEb,OAAO,EAAE,uBAAuB,EAAE,MAAM,UAAU,CAAA;AAclD,iBAAe,aAAa,CAAC,MAAM,EAAE,uBAAuB;;;;;;;;;;;;;;GAS3D;AAED,iBAAe,UAAU,CAAC,MAAM,EAAE,uBAAuB,0BAgBxD;AAED,iBAAe,UAAU,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,uBAAuB,oBAiBtE;AAED,iBAAe,YAAY,CACzB,QAAQ,EAAE,OAAO,EACjB,KAAK,EAAE,KAAK,EACZ,MAAM,EAAE,uBAAuB,iBAOhC;AAED,iBAAe,YAAY,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,uBAAuB,iBAKxE;AAED,iBAAe,iBAAiB,CAAC,MAAM,EAAE,uBAAuB,sCAU/D;AA+ID,OAAO,EACL,aAAa,EACb,iBAAiB,EACjB,UAAU,EACV,UAAU,EACV,YAAY,EACZ,YAAY,GACb,CAAA"}
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
import { createPublicClient, http, createWalletClient, size, keccak256, encodePacked, slice, } from 'viem';
|
|
2
|
+
import { getDeployArgs as getSafeDeployArgs, get7702InitCalls as get7702SafeInitCalls, get7702SmartAccount as get7702SafeAccount, } from './safe';
|
|
3
|
+
import { getDeployArgs as getNexusDeployArgs, get7702InitCalls as get7702NexusInitCalls, get7702SmartAccount as get7702NexusAccount, } from './nexus';
|
|
4
|
+
import { getBundlerClient } from './utils';
|
|
5
|
+
async function getDeployArgs(config) {
|
|
6
|
+
switch (config.account.type) {
|
|
7
|
+
case 'safe': {
|
|
8
|
+
return getSafeDeployArgs(config);
|
|
9
|
+
}
|
|
10
|
+
case 'nexus': {
|
|
11
|
+
return getNexusDeployArgs(config);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
async function getAddress(config) {
|
|
16
|
+
if (is7702(config)) {
|
|
17
|
+
if (!config.eoa) {
|
|
18
|
+
throw new Error('EIP-7702 accounts must have an EOA account');
|
|
19
|
+
}
|
|
20
|
+
return config.eoa.address;
|
|
21
|
+
}
|
|
22
|
+
const { factory, salt, hashedInitcode } = await getDeployArgs(config);
|
|
23
|
+
const hash = keccak256(encodePacked(['bytes1', 'address', 'bytes32', 'bytes'], ['0xff', factory, salt, hashedInitcode]));
|
|
24
|
+
const address = slice(hash, 12, 32);
|
|
25
|
+
return address;
|
|
26
|
+
}
|
|
27
|
+
async function isDeployed(chain, config) {
|
|
28
|
+
const publicClient = createPublicClient({
|
|
29
|
+
chain: chain,
|
|
30
|
+
transport: http(),
|
|
31
|
+
});
|
|
32
|
+
const address = await getAddress(config);
|
|
33
|
+
const code = await publicClient.getCode({
|
|
34
|
+
address,
|
|
35
|
+
});
|
|
36
|
+
if (!code) {
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
if (code.startsWith('0xef0100') && code.length === 48) {
|
|
40
|
+
// Defensive check to ensure there's no storage conflict; can be lifted in the future
|
|
41
|
+
throw new Error('Existing EIP-7702 accounts are not yet supported');
|
|
42
|
+
}
|
|
43
|
+
return size(code) > 0;
|
|
44
|
+
}
|
|
45
|
+
async function deploySource(deployer, chain, config) {
|
|
46
|
+
if (is7702(config)) {
|
|
47
|
+
return deploy7702Self(chain, config);
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
return deployStandaloneSelf(deployer, chain, config);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
async function deployTarget(chain, config) {
|
|
54
|
+
if (is7702(config)) {
|
|
55
|
+
return deploy7702WithBundler(chain, config);
|
|
56
|
+
}
|
|
57
|
+
// No need to deploy manually outside of EIP-7702
|
|
58
|
+
}
|
|
59
|
+
async function getBundleInitCode(config) {
|
|
60
|
+
if (is7702(config)) {
|
|
61
|
+
return undefined;
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
const { factory, factoryData } = await getDeployArgs(config);
|
|
65
|
+
if (!factory || !factoryData) {
|
|
66
|
+
throw new Error('Factory args not available');
|
|
67
|
+
}
|
|
68
|
+
return encodePacked(['address', 'bytes'], [factory, factoryData]);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
async function deploy7702Self(chain, config) {
|
|
72
|
+
if (!config.eoa) {
|
|
73
|
+
throw new Error('EIP-7702 accounts must have an EOA account');
|
|
74
|
+
}
|
|
75
|
+
const { implementation, initializationCallData } = await getDeployArgs(config);
|
|
76
|
+
if (!initializationCallData) {
|
|
77
|
+
throw new Error(`Initialization call data not available for ${config.account.type}`);
|
|
78
|
+
}
|
|
79
|
+
const publicClient = createPublicClient({
|
|
80
|
+
chain,
|
|
81
|
+
transport: http(),
|
|
82
|
+
});
|
|
83
|
+
const accountClient = createWalletClient({
|
|
84
|
+
account: config.eoa,
|
|
85
|
+
chain,
|
|
86
|
+
transport: http(),
|
|
87
|
+
});
|
|
88
|
+
const authorization = await accountClient.signAuthorization({
|
|
89
|
+
contractAddress: implementation,
|
|
90
|
+
executor: 'self',
|
|
91
|
+
});
|
|
92
|
+
const hash = await accountClient.sendTransaction({
|
|
93
|
+
chain,
|
|
94
|
+
authorizationList: [authorization],
|
|
95
|
+
to: config.eoa.address,
|
|
96
|
+
data: initializationCallData,
|
|
97
|
+
});
|
|
98
|
+
await publicClient.waitForTransactionReceipt({ hash });
|
|
99
|
+
}
|
|
100
|
+
async function deployStandaloneSelf(deployer, chain, config) {
|
|
101
|
+
const { factory, factoryData } = await getDeployArgs(config);
|
|
102
|
+
const publicClient = createPublicClient({
|
|
103
|
+
chain: chain,
|
|
104
|
+
transport: http(),
|
|
105
|
+
});
|
|
106
|
+
const client = createWalletClient({
|
|
107
|
+
account: deployer,
|
|
108
|
+
chain: chain,
|
|
109
|
+
transport: http(),
|
|
110
|
+
});
|
|
111
|
+
const tx = await client.sendTransaction({
|
|
112
|
+
to: factory,
|
|
113
|
+
data: factoryData,
|
|
114
|
+
});
|
|
115
|
+
await publicClient.waitForTransactionReceipt({ hash: tx });
|
|
116
|
+
}
|
|
117
|
+
async function deploy7702WithBundler(chain, config) {
|
|
118
|
+
if (!config.eoa) {
|
|
119
|
+
throw new Error('EIP-7702 accounts must have an EOA account');
|
|
120
|
+
}
|
|
121
|
+
const { implementation } = await getDeployArgs(config);
|
|
122
|
+
const publicClient = createPublicClient({
|
|
123
|
+
chain,
|
|
124
|
+
transport: http(),
|
|
125
|
+
});
|
|
126
|
+
const accountClient = createWalletClient({
|
|
127
|
+
account: config.eoa,
|
|
128
|
+
chain,
|
|
129
|
+
transport: http(),
|
|
130
|
+
});
|
|
131
|
+
const bundlerClient = getBundlerClient(config, publicClient);
|
|
132
|
+
const fundingClient = createWalletClient({
|
|
133
|
+
account: config.deployerAccount,
|
|
134
|
+
chain,
|
|
135
|
+
transport: http(),
|
|
136
|
+
});
|
|
137
|
+
const authorization = await accountClient.signAuthorization({
|
|
138
|
+
contractAddress: implementation,
|
|
139
|
+
});
|
|
140
|
+
// Will be replaced by a bundler in the future
|
|
141
|
+
const authTxHash = await fundingClient.sendTransaction({
|
|
142
|
+
chain: publicClient.chain,
|
|
143
|
+
authorizationList: [authorization],
|
|
144
|
+
});
|
|
145
|
+
await publicClient.waitForTransactionReceipt({ hash: authTxHash });
|
|
146
|
+
// Init the account
|
|
147
|
+
const smartAccount = await get7702SmartAccount(config, publicClient);
|
|
148
|
+
const initCalls = await get7702InitCalls(config);
|
|
149
|
+
const opHash = await bundlerClient.sendUserOperation({
|
|
150
|
+
account: smartAccount,
|
|
151
|
+
calls: initCalls,
|
|
152
|
+
});
|
|
153
|
+
await bundlerClient.waitForUserOperationReceipt({
|
|
154
|
+
hash: opHash,
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
async function get7702InitCalls(config) {
|
|
158
|
+
switch (config.account.type) {
|
|
159
|
+
case 'safe': {
|
|
160
|
+
return get7702SafeInitCalls();
|
|
161
|
+
}
|
|
162
|
+
case 'nexus': {
|
|
163
|
+
return get7702NexusInitCalls(config);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
async function get7702SmartAccount(config, client) {
|
|
168
|
+
if (!config.eoa) {
|
|
169
|
+
throw new Error('EIP-7702 accounts must have an EOA account');
|
|
170
|
+
}
|
|
171
|
+
switch (config.account.type) {
|
|
172
|
+
case 'safe': {
|
|
173
|
+
return get7702SafeAccount();
|
|
174
|
+
}
|
|
175
|
+
case 'nexus': {
|
|
176
|
+
return get7702NexusAccount(config.eoa, client);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
function is7702(config) {
|
|
181
|
+
return config.eoa !== undefined;
|
|
182
|
+
}
|
|
183
|
+
export { getDeployArgs, getBundleInitCode, getAddress, isDeployed, deploySource, deployTarget, };
|