@rhinestone/sdk 0.2.1 → 0.3.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.
Files changed (68) hide show
  1. package/README.md +4 -4
  2. package/dist/accounts/index.d.ts +15515 -4
  3. package/dist/accounts/index.d.ts.map +1 -1
  4. package/dist/accounts/index.js +69 -10
  5. package/dist/accounts/nexus.d.ts +15542 -32
  6. package/dist/accounts/nexus.d.ts.map +1 -1
  7. package/dist/accounts/nexus.js +86 -65
  8. package/dist/accounts/safe.d.ts +3 -1
  9. package/dist/accounts/safe.d.ts.map +1 -1
  10. package/dist/accounts/safe.js +8 -2
  11. package/dist/examples/abi/weth.d.ts +214 -0
  12. package/dist/examples/abi/weth.d.ts.map +1 -0
  13. package/dist/examples/abi/weth.js +279 -0
  14. package/dist/examples/cross-chain-ss.d.ts +1 -0
  15. package/dist/examples/cross-chain-ss.d.ts.map +1 -0
  16. package/dist/{example.js → examples/cross-chain-ss.js} +59 -22
  17. package/dist/examples/omni-account.d.ts +1 -0
  18. package/dist/examples/omni-account.d.ts.map +1 -0
  19. package/dist/examples/omni-account.js +169 -0
  20. package/dist/examples/smart-sessions.d.ts +1 -0
  21. package/dist/examples/smart-sessions.d.ts.map +1 -0
  22. package/dist/examples/smart-sessions.js +216 -0
  23. package/dist/execution/index.d.ts +28 -3
  24. package/dist/execution/index.d.ts.map +1 -1
  25. package/dist/execution/index.js +177 -47
  26. package/dist/execution/smart-session.d.ts +14 -0
  27. package/dist/execution/smart-session.d.ts.map +1 -0
  28. package/dist/execution/smart-session.js +83 -0
  29. package/dist/index.d.ts +15 -4
  30. package/dist/index.d.ts.map +1 -1
  31. package/dist/index.js +10 -10
  32. package/dist/modules/abi/smart-sessions.d.ts +42 -0
  33. package/dist/modules/abi/smart-sessions.d.ts.map +1 -0
  34. package/dist/modules/abi/smart-sessions.js +128 -0
  35. package/dist/modules/common.d.ts +16 -0
  36. package/dist/modules/common.d.ts.map +1 -0
  37. package/dist/modules/common.js +5 -0
  38. package/dist/modules/index.d.ts +7 -18
  39. package/dist/modules/index.d.ts.map +1 -1
  40. package/dist/modules/index.js +14 -119
  41. package/dist/modules/omni-account.d.ts +9 -0
  42. package/dist/modules/omni-account.d.ts.map +1 -0
  43. package/dist/modules/omni-account.js +7 -0
  44. package/dist/modules/validators.d.ts +31 -0
  45. package/dist/modules/validators.d.ts.map +1 -0
  46. package/dist/modules/validators.js +518 -0
  47. package/dist/orchestrator/client.d.ts +2 -5
  48. package/dist/orchestrator/client.d.ts.map +1 -1
  49. package/dist/orchestrator/consts.d.ts +3 -1
  50. package/dist/orchestrator/consts.d.ts.map +1 -1
  51. package/dist/orchestrator/consts.js +3 -1
  52. package/dist/orchestrator/index.d.ts +5 -3
  53. package/dist/orchestrator/index.d.ts.map +1 -1
  54. package/dist/orchestrator/index.js +5 -4
  55. package/dist/orchestrator/registry.d.ts +5 -0
  56. package/dist/orchestrator/registry.d.ts.map +1 -0
  57. package/dist/orchestrator/registry.js +187 -0
  58. package/dist/orchestrator/types.d.ts +39 -23
  59. package/dist/orchestrator/types.d.ts.map +1 -1
  60. package/dist/orchestrator/types.js +7 -6
  61. package/dist/orchestrator/utils.d.ts +8 -4
  62. package/dist/orchestrator/utils.d.ts.map +1 -1
  63. package/dist/orchestrator/utils.js +19 -5
  64. package/dist/types.d.ts +64 -4
  65. package/dist/types.d.ts.map +1 -1
  66. package/package.json +1 -1
  67. package/dist/example.d.ts +0 -1
  68. package/dist/example.d.ts.map +0 -1
@@ -0,0 +1,216 @@
1
+ "use strict";
2
+ // import { generatePrivateKey, privateKeyToAccount } from 'viem/accounts'
3
+ // import {
4
+ // baseSepolia,
5
+ // arbitrumSepolia,
6
+ // optimismSepolia,
7
+ // sepolia,
8
+ // } from 'viem/chains'
9
+ // import {
10
+ // Chain,
11
+ // createPublicClient,
12
+ // createWalletClient,
13
+ // encodeFunctionData,
14
+ // getAbiItem,
15
+ // Hex,
16
+ // http,
17
+ // parseEther,
18
+ // toFunctionSelector,
19
+ // } from 'viem'
20
+ // import { createRhinestoneAccount } from '../index'
21
+ // import { abi as wethAbi } from './abi/weth'
22
+ // import { Session } from '../types'
23
+ // const fundingPrivateKey = process.env.FUNDING_PRIVATE_KEY
24
+ // if (!fundingPrivateKey) {
25
+ // throw new Error('FUNDING_PRIVATE_KEY is not set')
26
+ // }
27
+ // const rhinestoneApiKey = process.env.RHINESTONE_API_KEY
28
+ // if (!rhinestoneApiKey) {
29
+ // throw new Error('RHINESTONE_API_KEY is not set')
30
+ // }
31
+ // const pimlicoApiKey = process.env.PIMLICO_API_KEY
32
+ // if (!pimlicoApiKey) {
33
+ // throw new Error('PIMLICO_API_KEY is not set')
34
+ // }
35
+ // const chain = optimismSepolia
36
+ // // const targetChain = arbitrumSepolia
37
+ // const wethAddress = getWethAddress(chain)
38
+ // const wethAmount = 1n
39
+ // const fundingAccount = privateKeyToAccount(fundingPrivateKey as Hex)
40
+ // console.log('fundingAccount', fundingAccount.address)
41
+ // const publicClient = createPublicClient({
42
+ // chain,
43
+ // transport: getTransport(chain),
44
+ // })
45
+ // const fundingClient = createWalletClient({
46
+ // account: fundingAccount,
47
+ // chain,
48
+ // transport: getTransport(chain),
49
+ // })
50
+ // const useNewKeys = true
51
+ // if (!useNewKeys) {
52
+ // console.log('new pks', [
53
+ // generatePrivateKey(),
54
+ // generatePrivateKey(),
55
+ // generatePrivateKey(),
56
+ // ])
57
+ // }
58
+ // const privateKeyA = useNewKeys
59
+ // ? generatePrivateKey()
60
+ // : '0xe48befb91c9741788c829da2b9ff5b4d64dd77a170c284d7cf10e9acf9e11175'
61
+ // const accountA = privateKeyToAccount(privateKeyA)
62
+ // const privateKeyB = useNewKeys
63
+ // ? generatePrivateKey()
64
+ // : '0xe076077b3c53583d0eefcad6b30929cc0dfd58e9a2566cf6a059e327ec62fdbe'
65
+ // const accountB = privateKeyToAccount(privateKeyB)
66
+ // const privateKeyC = useNewKeys
67
+ // ? generatePrivateKey()
68
+ // : '0x34afca21087883dba533ecf1d9d705dd2ab8a1933e98db704bb7d9ff83edcaa8'
69
+ // const accountC = privateKeyToAccount(privateKeyC)
70
+ // const session: Session = {
71
+ // owners: {
72
+ // type: 'ecdsa',
73
+ // accounts: [accountA],
74
+ // },
75
+ // actions: [
76
+ // {
77
+ // target: wethAddress,
78
+ // selector: toFunctionSelector(
79
+ // getAbiItem({
80
+ // abi: wethAbi,
81
+ // name: 'deposit',
82
+ // }),
83
+ // ),
84
+ // },
85
+ // {
86
+ // target: wethAddress,
87
+ // selector: toFunctionSelector(
88
+ // getAbiItem({
89
+ // abi: wethAbi,
90
+ // name: 'transfer',
91
+ // }),
92
+ // ),
93
+ // },
94
+ // ],
95
+ // }
96
+ // const session2: Session = {
97
+ // owners: {
98
+ // type: 'ecdsa',
99
+ // accounts: [accountA],
100
+ // },
101
+ // actions: [
102
+ // {
103
+ // target: wethAddress,
104
+ // selector: toFunctionSelector(
105
+ // getAbiItem({
106
+ // abi: wethAbi,
107
+ // name: 'deposit',
108
+ // }),
109
+ // ),
110
+ // },
111
+ // {
112
+ // target: wethAddress,
113
+ // selector: toFunctionSelector(
114
+ // getAbiItem({
115
+ // abi: wethAbi,
116
+ // name: 'transfer',
117
+ // }),
118
+ // ),
119
+ // policies: [
120
+ // {
121
+ // type: 'universal-action',
122
+ // rules: [
123
+ // {
124
+ // condition: 'equal',
125
+ // calldataOffset: 0n,
126
+ // referenceValue: '0xd8da6bf26964af9d7eed9e03e53415d37aa96045',
127
+ // },
128
+ // ],
129
+ // },
130
+ // ],
131
+ // },
132
+ // ],
133
+ // }
134
+ // const rhinestoneAccount = await createRhinestoneAccount({
135
+ // account: {
136
+ // type: 'nexus',
137
+ // },
138
+ // owners: {
139
+ // type: 'ecdsa',
140
+ // accounts: [accountA, accountB, accountC],
141
+ // threshold: 2,
142
+ // },
143
+ // sessions: [session],
144
+ // rhinestoneApiKey,
145
+ // deployerAccount: fundingAccount,
146
+ // bundler: {
147
+ // type: 'pimlico',
148
+ // apiKey: pimlicoApiKey,
149
+ // },
150
+ // })
151
+ // const address = await rhinestoneAccount.getAddress()
152
+ // console.log(address)
153
+ // // prefund
154
+ // const ethBalance = await publicClient.getBalance({
155
+ // address,
156
+ // })
157
+ // if (ethBalance < parseEther('0.001')) {
158
+ // const txHash = await fundingClient.sendTransaction({
159
+ // to: address,
160
+ // value: parseEther('0.001'),
161
+ // })
162
+ // await publicClient.waitForTransactionReceipt({ hash: txHash })
163
+ // }
164
+ // const transactionResult = await rhinestoneAccount.sendTransactions({
165
+ // chain,
166
+ // calls: [
167
+ // {
168
+ // to: wethAddress,
169
+ // value: 10n,
170
+ // data: encodeFunctionData({
171
+ // abi: wethAbi,
172
+ // functionName: 'deposit',
173
+ // }),
174
+ // },
175
+ // {
176
+ // to: wethAddress,
177
+ // data: encodeFunctionData({
178
+ // abi: wethAbi,
179
+ // functionName: 'transfer',
180
+ // args: ['0xd8da6bf26964af9d7eed9e03e53415d37aa96045', 1n],
181
+ // }),
182
+ // },
183
+ // ],
184
+ // tokenRequests: [
185
+ // {
186
+ // address: wethAddress,
187
+ // amount: 1n,
188
+ // },
189
+ // ],
190
+ // signers: {
191
+ // type: 'session',
192
+ // session: session2,
193
+ // },
194
+ // })
195
+ // const result = await rhinestoneAccount.waitForExecution(transactionResult)
196
+ // console.log('status', result)
197
+ // function getWethAddress(chain: Chain) {
198
+ // switch (chain.id) {
199
+ // case sepolia.id:
200
+ // return '0xfFf9976782d46CC05630D1f6eBAb18b2324d6B14'
201
+ // case baseSepolia.id:
202
+ // return '0x4200000000000000000000000000000000000006'
203
+ // case arbitrumSepolia.id:
204
+ // return '0x980B62Da83eFf3D4576C647993b0c1D7faf17c73'
205
+ // case optimismSepolia.id:
206
+ // return '0x4200000000000000000000000000000000000006'
207
+ // default:
208
+ // throw new Error('Unsupported chain')
209
+ // }
210
+ // }
211
+ // function getTransport(chain: Chain) {
212
+ // if (chain.id === sepolia.id) {
213
+ // return http('https://ethereum-sepolia-rpc.publicnode.com')
214
+ // }
215
+ // return http()
216
+ // }
@@ -1,6 +1,31 @@
1
+ import { Address, Chain, Hex } from 'viem';
1
2
  import { type BundleResult } from '../orchestrator';
2
3
  import { RhinestoneAccountConfig, Transaction } from '../types';
3
- declare function sendTransactions(config: RhinestoneAccountConfig, transaction: Transaction): Promise<bigint>;
4
- declare function waitForExecution(config: RhinestoneAccountConfig, id: bigint): Promise<BundleResult>;
5
- export { sendTransactions, waitForExecution };
4
+ type TransactionResult = {
5
+ type: 'userop';
6
+ hash: Hex;
7
+ sourceChain: Chain;
8
+ targetChain: Chain;
9
+ } | {
10
+ type: 'bundle';
11
+ id: bigint;
12
+ sourceChain: Chain;
13
+ targetChain: Chain;
14
+ };
15
+ declare function sendTransaction(config: RhinestoneAccountConfig, transaction: Transaction): Promise<TransactionResult>;
16
+ declare function waitForExecution(config: RhinestoneAccountConfig, result: TransactionResult): Promise<BundleResult | {
17
+ actualGasCost: bigint;
18
+ actualGasUsed: bigint;
19
+ entryPoint: Address;
20
+ logs: import("viem").Log<bigint, number, false>[];
21
+ nonce: bigint;
22
+ paymaster?: `0x${string}` | undefined;
23
+ reason?: string | undefined | undefined;
24
+ receipt: import("viem").TransactionReceipt<bigint, number, "success" | "reverted">;
25
+ sender: Address;
26
+ success: boolean;
27
+ userOpHash: import("viem").Hash;
28
+ }>;
29
+ export { sendTransaction, waitForExecution };
30
+ export type { TransactionResult };
6
31
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../execution/index.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,KAAK,YAAY,EAQlB,MAAM,iBAAiB,CAAA;AAaxB,OAAO,EAAE,uBAAuB,EAAE,WAAW,EAAY,MAAM,UAAU,CAAA;AAIzE,iBAAe,gBAAgB,CAC7B,MAAM,EAAE,uBAAuB,EAC/B,WAAW,EAAE,WAAW,mBA4DzB;AAED,iBAAe,gBAAgB,CAAC,MAAM,EAAE,uBAAuB,EAAE,EAAE,EAAE,MAAM,yBAe1E;AAkCD,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../execution/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,OAAO,EACP,KAAK,EAKL,GAAG,EAKJ,MAAM,MAAM,CAAA;AAMb,OAAO,EACL,KAAK,YAAY,EASlB,MAAM,iBAAiB,CAAA;AAYxB,OAAO,EACL,uBAAuB,EACvB,WAAW,EAKZ,MAAM,UAAU,CAAA;AAajB,KAAK,iBAAiB,GAClB;IACE,IAAI,EAAE,QAAQ,CAAA;IACd,IAAI,EAAE,GAAG,CAAA;IACT,WAAW,EAAE,KAAK,CAAA;IAClB,WAAW,EAAE,KAAK,CAAA;CACnB,GACD;IACE,IAAI,EAAE,QAAQ,CAAA;IACd,EAAE,EAAE,MAAM,CAAA;IACV,WAAW,EAAE,KAAK,CAAA;IAClB,WAAW,EAAE,KAAK,CAAA;CACnB,CAAA;AAEL,iBAAe,eAAe,CAC5B,MAAM,EAAE,uBAAuB,EAC/B,WAAW,EAAE,WAAW,8BAuBzB;AA8QD,iBAAe,gBAAgB,CAC7B,MAAM,EAAE,uBAAuB,EAC/B,MAAM,EAAE,iBAAiB;;;;;;;;;;;;GAgC1B;AAED,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,CAAA;AAC5C,YAAY,EAAE,iBAAiB,EAAE,CAAA"}
@@ -1,15 +1,151 @@
1
- import { concat, encodePacked } from 'viem';
2
- import { BUNDLE_STATUS_PENDING, BUNDLE_STATUS_FAILED, getOrchestrator, getOrderBundleHash, BUNDLE_STATUS_PARTIALLY_COMPLETED, } from '../orchestrator';
3
- import { getAddress, isDeployed, deploySource, deployTarget, getBundleInitCode, } from '../accounts';
4
- import { getValidator, getWebauthnValidatorSignature, isRip7212SupportedNetwork, } from '../modules';
1
+ import { createPublicClient, createWalletClient, encodeAbiParameters, encodePacked, http, keccak256, pad, toHex, } from 'viem';
2
+ import { entryPoint07Address, getUserOperationHash, } from 'viem/account-abstraction';
3
+ import { BUNDLE_STATUS_PENDING, BUNDLE_STATUS_FAILED, getOrchestrator, getOrderBundleHash, BUNDLE_STATUS_PARTIALLY_COMPLETED, getEmptyUserOp, } from '../orchestrator';
4
+ import { getAddress, isDeployed, deploySource, deployTarget, getBundleInitCode, sign, getSmartSessionSmartAccount, getDeployArgs, } from '../accounts';
5
+ import { getOwnerValidator } from '../modules';
6
+ import { getBundlerClient } from '../accounts/utils';
7
+ import { getSmartSessionValidator } from '../modules/validators';
8
+ import { getTokenBalanceSlot } from '../orchestrator';
9
+ import { enableSmartSession, getSessionSignature, hashErc7739, } from './smart-session';
5
10
  const POLLING_INTERVAL = 500;
6
- async function sendTransactions(config, transaction) {
7
- const { sourceChain, targetChain, calls, tokenRequests } = transaction;
11
+ async function sendTransaction(config, transaction) {
12
+ if ('chain' in transaction) {
13
+ // Same-chain transaction
14
+ return await sendTransactionInternal(config, transaction.chain, transaction.chain, transaction.calls, transaction.tokenRequests, transaction.signers);
15
+ }
16
+ else {
17
+ // Cross-chain transaction
18
+ return await sendTransactionInternal(config, transaction.sourceChain, transaction.targetChain, transaction.calls, transaction.tokenRequests, transaction.signers);
19
+ }
20
+ }
21
+ async function sendTransactionInternal(config, sourceChain, targetChain, calls, tokenRequests, signers) {
8
22
  const isAccountDeployed = await isDeployed(sourceChain, config);
9
23
  if (!isAccountDeployed) {
10
- await deploySource(config.deployerAccount, sourceChain, config);
24
+ await deploySource(sourceChain, config);
25
+ }
26
+ const withSession = signers?.type === 'session' ? signers.session : null;
27
+ if (withSession) {
28
+ await enableSmartSession(sourceChain, config, withSession);
11
29
  }
12
30
  const accountAddress = await getAddress(config);
31
+ if (withSession) {
32
+ // Smart sessions require a UserOp flow
33
+ return await sendTransactionAsUserOp(config, sourceChain, targetChain, calls, tokenRequests, accountAddress, withSession);
34
+ }
35
+ else {
36
+ return await sendTransactionAsIntent(config, sourceChain, targetChain, calls, tokenRequests, accountAddress);
37
+ }
38
+ }
39
+ async function sendTransactionAsUserOp(config, sourceChain, targetChain, calls, tokenRequests, accountAddress, withSession) {
40
+ const publicClient = createPublicClient({
41
+ chain: sourceChain,
42
+ transport: http(),
43
+ });
44
+ const sessionAccount = await getSmartSessionSmartAccount(config, publicClient, sourceChain, withSession);
45
+ const bundlerClient = getBundlerClient(config, publicClient);
46
+ const targetPublicClient = createPublicClient({
47
+ chain: targetChain,
48
+ transport: http(),
49
+ });
50
+ const targetSessionAccount = await getSmartSessionSmartAccount(config, targetPublicClient, targetChain, withSession);
51
+ const targetBundlerClient = getBundlerClient(config, targetPublicClient);
52
+ if (sourceChain.id === targetChain.id) {
53
+ await enableSmartSession(targetChain, config, withSession);
54
+ const hash = await bundlerClient.sendUserOperation({
55
+ account: sessionAccount,
56
+ calls,
57
+ });
58
+ return {
59
+ type: 'userop',
60
+ hash,
61
+ sourceChain,
62
+ targetChain,
63
+ };
64
+ }
65
+ const metaIntent = {
66
+ targetChainId: targetChain.id,
67
+ tokenTransfers: tokenRequests.map((tokenRequest) => ({
68
+ tokenAddress: tokenRequest.address,
69
+ amount: tokenRequest.amount,
70
+ })),
71
+ targetAccount: accountAddress,
72
+ userOp: getEmptyUserOp(),
73
+ };
74
+ const orchestrator = getOrchestrator(config.rhinestoneApiKey);
75
+ const orderPath = await orchestrator.getOrderPath(metaIntent, accountAddress);
76
+ // Deploy the account on the target chain
77
+ const { factory, factoryData } = await getDeployArgs(config);
78
+ const deployerAccount = config.deployerAccount;
79
+ const targetWalletClient = createWalletClient({
80
+ chain: targetChain,
81
+ transport: http(),
82
+ });
83
+ const targetDeployTx = await targetWalletClient.sendTransaction({
84
+ account: deployerAccount,
85
+ to: factory,
86
+ data: factoryData,
87
+ });
88
+ await targetPublicClient.waitForTransactionReceipt({
89
+ hash: targetDeployTx,
90
+ });
91
+ await enableSmartSession(targetChain, config, withSession);
92
+ const userOp = await targetBundlerClient.prepareUserOperation({
93
+ account: targetSessionAccount,
94
+ calls: [...orderPath[0].injectedExecutions, ...calls],
95
+ stateOverride: [
96
+ ...tokenRequests.map((request) => {
97
+ const rootBalanceSlot = getTokenBalanceSlot(targetChain, request.address);
98
+ const balanceSlot = rootBalanceSlot
99
+ ? keccak256(encodeAbiParameters([{ type: 'address' }, { type: 'uint256' }], [accountAddress, rootBalanceSlot]))
100
+ : '0x';
101
+ return {
102
+ address: request.address,
103
+ stateDiff: [
104
+ {
105
+ slot: balanceSlot,
106
+ value: pad(toHex(request.amount)),
107
+ },
108
+ ],
109
+ };
110
+ }),
111
+ ],
112
+ });
113
+ userOp.signature = await targetSessionAccount.signUserOperation(userOp);
114
+ const userOpHash = getUserOperationHash({
115
+ userOperation: userOp,
116
+ chainId: targetChain.id,
117
+ entryPointAddress: entryPoint07Address,
118
+ entryPointVersion: '0.7',
119
+ });
120
+ orderPath[0].orderBundle.segments[0].witness.userOpHash = userOpHash;
121
+ const { hash, appDomainSeparator, contentsType, structHash, orderBundleHash, } = await hashErc7739(sourceChain, orderPath, accountAddress);
122
+ const signature = await sign(withSession.owners, targetChain, hash);
123
+ const sessionSignature = getSessionSignature(signature, appDomainSeparator, structHash, contentsType, withSession);
124
+ const smartSessionValidator = getSmartSessionValidator(config);
125
+ if (!smartSessionValidator) {
126
+ throw new Error('Smart session validator not available');
127
+ }
128
+ const packedSig = encodePacked(['address', 'bytes'], [smartSessionValidator.address, sessionSignature]);
129
+ const signedOrderBundle = {
130
+ ...orderPath[0].orderBundle,
131
+ originSignatures: Array(orderPath[0].orderBundle.segments.length).fill(packedSig),
132
+ targetSignature: packedSig,
133
+ };
134
+ await deployTarget(targetChain, config);
135
+ const bundleResults = await orchestrator.postSignedOrderBundle([
136
+ {
137
+ signedOrderBundle,
138
+ userOp,
139
+ },
140
+ ]);
141
+ return {
142
+ type: 'bundle',
143
+ id: bundleResults[0].bundleId,
144
+ sourceChain,
145
+ targetChain,
146
+ };
147
+ }
148
+ async function sendTransactionAsIntent(config, sourceChain, targetChain, calls, tokenRequests, accountAddress) {
13
149
  const metaIntent = {
14
150
  targetChainId: targetChain.id,
15
151
  tokenTransfers: tokenRequests.map((tokenRequest) => ({
@@ -31,7 +167,7 @@ async function sendTransactions(config, transaction) {
31
167
  ];
32
168
  const orderBundleHash = getOrderBundleHash(orderPath[0].orderBundle);
33
169
  const bundleSignature = await sign(config.owners, sourceChain, orderBundleHash);
34
- const validatorModule = getValidator(config);
170
+ const validatorModule = getOwnerValidator(config);
35
171
  const packedSig = encodePacked(['address', 'bytes'], [validatorModule.address, bundleSignature]);
36
172
  const signedOrderBundle = {
37
173
  ...orderPath[0].orderBundle,
@@ -46,47 +182,41 @@ async function sendTransactions(config, transaction) {
46
182
  initCode,
47
183
  },
48
184
  ]);
49
- return bundleResults[0].bundleId;
50
- }
51
- async function waitForExecution(config, id) {
52
- let bundleResult = null;
53
- while (bundleResult === null ||
54
- bundleResult.status === BUNDLE_STATUS_PENDING ||
55
- bundleResult.status === BUNDLE_STATUS_PARTIALLY_COMPLETED) {
56
- const orchestrator = getOrchestrator(config.rhinestoneApiKey);
57
- bundleResult = await orchestrator.getBundleStatus(id);
58
- await new Promise((resolve) => setTimeout(resolve, POLLING_INTERVAL));
59
- }
60
- if (bundleResult.status === BUNDLE_STATUS_FAILED) {
61
- throw new Error('Bundle failed');
62
- }
63
- return bundleResult;
185
+ return {
186
+ type: 'bundle',
187
+ id: bundleResults[0].bundleId,
188
+ sourceChain,
189
+ targetChain,
190
+ };
64
191
  }
65
- async function sign(validators, chain, hash) {
66
- switch (validators.type) {
67
- case 'ecdsa': {
68
- const signatures = await Promise.all(validators.accounts.map((account) => signEcdsa(account, hash)));
69
- return concat(signatures);
192
+ async function waitForExecution(config, result) {
193
+ switch (result.type) {
194
+ case 'bundle': {
195
+ let bundleResult = null;
196
+ while (bundleResult === null ||
197
+ bundleResult.status === BUNDLE_STATUS_PENDING ||
198
+ bundleResult.status === BUNDLE_STATUS_PARTIALLY_COMPLETED) {
199
+ const orchestrator = getOrchestrator(config.rhinestoneApiKey);
200
+ bundleResult = await orchestrator.getBundleStatus(result.id);
201
+ await new Promise((resolve) => setTimeout(resolve, POLLING_INTERVAL));
202
+ }
203
+ if (bundleResult.status === BUNDLE_STATUS_FAILED) {
204
+ throw new Error('Bundle failed');
205
+ }
206
+ return bundleResult;
70
207
  }
71
- case 'passkey': {
72
- return await signPasskey(validators.account, chain, hash);
208
+ case 'userop': {
209
+ const publicClient = createPublicClient({
210
+ chain: result.sourceChain,
211
+ transport: http(),
212
+ });
213
+ // It's a UserOp hash
214
+ const bundlerClient = getBundlerClient(config, publicClient);
215
+ const receipt = await bundlerClient.waitForUserOperationReceipt({
216
+ hash: result.hash,
217
+ });
218
+ return receipt;
73
219
  }
74
220
  }
75
221
  }
76
- async function signEcdsa(account, hash) {
77
- if (!account.signMessage) {
78
- throw new Error('Signing not supported for the account');
79
- }
80
- return await account.signMessage({ message: { raw: hash } });
81
- }
82
- async function signPasskey(account, chain, hash) {
83
- const { webauthn, signature } = await account.sign({ hash });
84
- const usePrecompiled = isRip7212SupportedNetwork(chain);
85
- const encodedSignature = getWebauthnValidatorSignature({
86
- webauthn,
87
- signature,
88
- usePrecompiled,
89
- });
90
- return encodedSignature;
91
- }
92
- export { sendTransactions, waitForExecution };
222
+ export { sendTransaction, waitForExecution };
@@ -0,0 +1,14 @@
1
+ import { Chain, Hex, Address } from 'viem';
2
+ import { RhinestoneAccountConfig, Session } from '../types';
3
+ import { OrderPath } from '../orchestrator';
4
+ declare function enableSmartSession(chain: Chain, config: RhinestoneAccountConfig, session: Session): Promise<void>;
5
+ declare function hashErc7739(sourceChain: Chain, orderPath: OrderPath, accountAddress: Address): Promise<{
6
+ hash: `0x${string}`;
7
+ appDomainSeparator: `0x${string}`;
8
+ contentsType: string;
9
+ structHash: `0x${string}`;
10
+ orderBundleHash: `0x${string}`;
11
+ }>;
12
+ declare function getSessionSignature(signature: Hex, appDomainSeparator: Hex, structHash: Hex, contentsType: string, withSession: Session): `0x${string}`;
13
+ export { enableSmartSession, hashErc7739, getSessionSignature };
14
+ //# sourceMappingURL=smart-session.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"smart-session.d.ts","sourceRoot":"","sources":["../../execution/smart-session.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,EAIL,GAAG,EAGH,OAAO,EACR,MAAM,MAAM,CAAA;AAWb,OAAO,EAAE,uBAAuB,EAAE,OAAO,EAAE,MAAM,UAAU,CAAA;AAC3D,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAM3C,iBAAe,kBAAkB,CAC/B,KAAK,EAAE,KAAK,EACZ,MAAM,EAAE,uBAAuB,EAC/B,OAAO,EAAE,OAAO,iBAyBjB;AAED,iBAAe,WAAW,CACxB,WAAW,EAAE,KAAK,EAClB,SAAS,EAAE,SAAS,EACpB,cAAc,EAAE,OAAO;;;;;;GAmExB;AAED,iBAAS,mBAAmB,CAC1B,SAAS,EAAE,GAAG,EACd,kBAAkB,EAAE,GAAG,EACvB,UAAU,EAAE,GAAG,EACf,YAAY,EAAE,MAAM,EACpB,WAAW,EAAE,OAAO,iBAkBrB;AAED,OAAO,EAAE,kBAAkB,EAAE,WAAW,EAAE,mBAAmB,EAAE,CAAA"}
@@ -0,0 +1,83 @@
1
+ import { http, createPublicClient, encodePacked, keccak256, encodeAbiParameters, } from 'viem';
2
+ import { getSmartAccount, getAddress } from '../accounts';
3
+ import { getBundlerClient } from '../accounts/utils';
4
+ import { getPermissionId, isSessionEnabled, getSessionAllowedERC7739Content, getAccountEIP712Domain, getEnableSessionCall, } from '../modules/validators';
5
+ import { getOrderBundleHash, hashMultichainCompactWithoutDomainSeparator, } from '../orchestrator/utils';
6
+ async function enableSmartSession(chain, config, session) {
7
+ const publicClient = createPublicClient({
8
+ chain,
9
+ transport: http(),
10
+ });
11
+ const address = await getAddress(config);
12
+ const isEnabled = await isSessionEnabled(publicClient, address, getPermissionId(session));
13
+ if (isEnabled) {
14
+ return;
15
+ }
16
+ const smartAccount = await getSmartAccount(config, publicClient, chain);
17
+ const bundlerClient = getBundlerClient(config, publicClient);
18
+ const enableSessionCall = await getEnableSessionCall(chain, session);
19
+ const opHash = await bundlerClient.sendUserOperation({
20
+ account: smartAccount,
21
+ calls: [enableSessionCall],
22
+ });
23
+ await bundlerClient.waitForUserOperationReceipt({
24
+ hash: opHash,
25
+ });
26
+ }
27
+ async function hashErc7739(sourceChain, orderPath, accountAddress) {
28
+ const publicClient = createPublicClient({
29
+ chain: sourceChain,
30
+ transport: http(),
31
+ });
32
+ const { appDomainSeparator, contentsType } = await getSessionAllowedERC7739Content(sourceChain);
33
+ const orderBundleHash = getOrderBundleHash(orderPath[0].orderBundle);
34
+ // Create hash following ERC-7739 TypedDataSign workflow
35
+ const typedDataSignTypehash = keccak256(encodePacked(['string'], [
36
+ 'TypedDataSign(MultichainCompact contents,string name,string version,uint256 chainId,address verifyingContract,bytes32 salt)'.concat(contentsType),
37
+ ]));
38
+ // Original struct hash
39
+ const structHash = hashMultichainCompactWithoutDomainSeparator(orderPath[0].orderBundle);
40
+ const { name, version, chainId, verifyingContract, salt } = await getAccountEIP712Domain(publicClient, accountAddress);
41
+ // Final hash according to ERC-7739
42
+ const hash = keccak256(encodePacked(['bytes2', 'bytes32', 'bytes32'], [
43
+ '0x1901',
44
+ appDomainSeparator,
45
+ keccak256(encodeAbiParameters([
46
+ { name: 'typedDataSignTypehash', type: 'bytes32' },
47
+ { name: 'structHash', type: 'bytes32' },
48
+ { name: 'name', type: 'bytes32' },
49
+ { name: 'version', type: 'bytes32' },
50
+ { name: 'chainId', type: 'uint256' },
51
+ { name: 'verifyingContract', type: 'address' },
52
+ { name: 'salt', type: 'bytes32' },
53
+ ], [
54
+ typedDataSignTypehash,
55
+ structHash,
56
+ keccak256(encodePacked(['string'], [name])),
57
+ keccak256(encodePacked(['string'], [version])),
58
+ BigInt(Number(chainId)),
59
+ verifyingContract,
60
+ salt,
61
+ ])),
62
+ ]));
63
+ return {
64
+ hash,
65
+ appDomainSeparator,
66
+ contentsType,
67
+ structHash,
68
+ orderBundleHash,
69
+ };
70
+ }
71
+ function getSessionSignature(signature, appDomainSeparator, structHash, contentsType, withSession) {
72
+ const erc7739Signature = encodePacked(['bytes', 'bytes32', 'bytes32', 'string', 'uint16'], [
73
+ signature,
74
+ appDomainSeparator,
75
+ structHash,
76
+ contentsType,
77
+ contentsType.length,
78
+ ]);
79
+ // Pack with permissionId for smart session
80
+ const wrappedSignature = encodePacked(['bytes32', 'bytes'], [getPermissionId(withSession), erc7739Signature]);
81
+ return wrappedSignature;
82
+ }
83
+ export { enableSmartSession, hashErc7739, getSessionSignature };
package/dist/index.d.ts CHANGED
@@ -1,10 +1,21 @@
1
1
  import { RhinestoneAccountConfig, Transaction } from './types';
2
+ import { type TransactionResult } from './execution';
2
3
  declare function createRhinestoneAccount(config: RhinestoneAccountConfig): Promise<{
3
4
  config: RhinestoneAccountConfig;
4
- sendTransactions: (transaction: Transaction) => Promise<bigint>;
5
- waitForExecution: ({ id }: {
6
- id: bigint;
7
- }) => Promise<import("./orchestrator").BundleResult>;
5
+ sendTransactions: (transaction: Transaction) => Promise<TransactionResult>;
6
+ waitForExecution: (result: TransactionResult) => Promise<import("./orchestrator").BundleResult | {
7
+ actualGasCost: bigint;
8
+ actualGasUsed: bigint;
9
+ entryPoint: import("abitype").Address;
10
+ logs: import("viem").Log<bigint, number, false>[];
11
+ nonce: bigint;
12
+ paymaster?: `0x${string}` | undefined;
13
+ reason?: string | undefined | undefined;
14
+ receipt: import("viem").TransactionReceipt<bigint, number, "success" | "reverted">;
15
+ sender: import("abitype").Address;
16
+ success: boolean;
17
+ userOpHash: import("viem").Hash;
18
+ }>;
8
19
  getAddress: () => Promise<`0x${string}`>;
9
20
  }>;
10
21
  export { createRhinestoneAccount };
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA,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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AAC9D,OAAO,EACL,KAAK,iBAAiB,EAGvB,MAAM,aAAa,CAAA;AAGpB,iBAAe,uBAAuB,CAAC,MAAM,EAAE,uBAAuB;;oCAC7B,WAAW;+BAIhB,iBAAiB;;;;;;;;;;;;;;GAcpD;AAED,OAAO,EAAE,uBAAuB,EAAE,CAAA"}
package/dist/index.js CHANGED
@@ -1,15 +1,15 @@
1
- import { sendTransactions as sendTransactionsInternal, waitForExecution as waitForExecutionInternal, } from './execution';
1
+ import { sendTransaction as sendTransactionInternal, waitForExecution as waitForExecutionInternal, } from './execution';
2
2
  import { getAddress as getAddressInternal } from './accounts';
3
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
- };
4
+ function sendTransactions(transaction) {
5
+ return sendTransactionInternal(config, transaction);
6
+ }
7
+ function waitForExecution(result) {
8
+ return waitForExecutionInternal(config, result);
9
+ }
10
+ function getAddress() {
11
+ return getAddressInternal(config);
12
+ }
13
13
  return {
14
14
  config,
15
15
  sendTransactions,