@charterlabs/rhinestone-sdk 0.0.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 +208 -0
- package/dist/accounts/index.d.ts +27 -0
- package/dist/accounts/index.d.ts.map +1 -0
- package/dist/accounts/index.js +289 -0
- package/dist/accounts/nexus.d.ts +20 -0
- package/dist/accounts/nexus.d.ts.map +1 -0
- package/dist/accounts/nexus.js +236 -0
- package/dist/accounts/safe.d.ts +17 -0
- package/dist/accounts/safe.d.ts.map +1 -0
- package/dist/accounts/safe.js +187 -0
- package/dist/accounts/utils.d.ts +27 -0
- package/dist/accounts/utils.d.ts.map +1 -0
- package/dist/accounts/utils.js +181 -0
- package/dist/execution/index.d.ts +33 -0
- package/dist/execution/index.d.ts.map +1 -0
- package/dist/execution/index.js +258 -0
- package/dist/execution/smart-session.d.ts +13 -0
- package/dist/execution/smart-session.d.ts.map +1 -0
- package/dist/execution/smart-session.js +85 -0
- package/dist/index.d.ts +34 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +67 -0
- package/dist/modules/abi/smart-sessions.d.ts +42 -0
- package/dist/modules/abi/smart-sessions.d.ts.map +1 -0
- package/dist/modules/abi/smart-sessions.js +131 -0
- package/dist/modules/common.d.ts +16 -0
- package/dist/modules/common.d.ts.map +1 -0
- package/dist/modules/common.js +11 -0
- package/dist/modules/index.d.ts +33 -0
- package/dist/modules/index.d.ts.map +1 -0
- package/dist/modules/index.js +153 -0
- package/dist/modules/omni-account.d.ts +9 -0
- package/dist/modules/omni-account.d.ts.map +1 -0
- package/dist/modules/omni-account.js +15 -0
- package/dist/modules/validators/core.d.ts +23 -0
- package/dist/modules/validators/core.d.ts.map +1 -0
- package/dist/modules/validators/core.js +118 -0
- package/dist/modules/validators/index.d.ts +4 -0
- package/dist/modules/validators/index.d.ts.map +1 -0
- package/dist/modules/validators/index.js +17 -0
- package/dist/modules/validators/smart-sessions.d.ts +29 -0
- package/dist/modules/validators/smart-sessions.d.ts.map +1 -0
- package/dist/modules/validators/smart-sessions.js +426 -0
- package/dist/orchestrator/client.d.ts +29 -0
- package/dist/orchestrator/client.d.ts.map +1 -0
- package/dist/orchestrator/client.js +250 -0
- package/dist/orchestrator/consts.d.ts +5 -0
- package/dist/orchestrator/consts.d.ts.map +1 -0
- package/dist/orchestrator/consts.js +9 -0
- package/dist/orchestrator/error.d.ts +18 -0
- package/dist/orchestrator/error.d.ts.map +1 -0
- package/dist/orchestrator/error.js +33 -0
- package/dist/orchestrator/index.d.ts +11 -0
- package/dist/orchestrator/index.d.ts.map +1 -0
- package/dist/orchestrator/index.js +40 -0
- package/dist/orchestrator/registry.d.ts +17 -0
- package/dist/orchestrator/registry.d.ts.map +1 -0
- package/dist/orchestrator/registry.js +358 -0
- package/dist/orchestrator/types.d.ts +221 -0
- package/dist/orchestrator/types.d.ts.map +1 -0
- package/dist/orchestrator/types.js +19 -0
- package/dist/orchestrator/utils.d.ts +29 -0
- package/dist/orchestrator/utils.d.ts.map +1 -0
- package/dist/orchestrator/utils.js +316 -0
- package/dist/types.d.ts +113 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/package.json +54 -0
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { type Address, type Chain, type Hex } from 'viem';
|
|
2
|
+
import type { BundleResult } from '../orchestrator';
|
|
3
|
+
import type { RhinestoneAccountConfig, Transaction } from '../types';
|
|
4
|
+
type TransactionResult = {
|
|
5
|
+
type: 'userop';
|
|
6
|
+
hash: Hex;
|
|
7
|
+
sourceChain: number;
|
|
8
|
+
targetChain: number;
|
|
9
|
+
} | {
|
|
10
|
+
type: 'bundle';
|
|
11
|
+
id: bigint;
|
|
12
|
+
sourceChain?: number;
|
|
13
|
+
targetChain: number;
|
|
14
|
+
};
|
|
15
|
+
declare function sendTransaction(config: RhinestoneAccountConfig, transaction: Transaction): Promise<TransactionResult>;
|
|
16
|
+
declare function waitForExecution(config: RhinestoneAccountConfig, result: TransactionResult, acceptsPreconfirmations: boolean): 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
|
+
declare function getMaxSpendableAmount(config: RhinestoneAccountConfig, chain: Chain, tokenAddress: Address, gasUnits: bigint): Promise<bigint>;
|
|
30
|
+
declare function getPortfolio(config: RhinestoneAccountConfig, onTestnets: boolean): Promise<import("../orchestrator").UserTokenBalance[]>;
|
|
31
|
+
export { sendTransaction, waitForExecution, getMaxSpendableAmount, getPortfolio, };
|
|
32
|
+
export type { TransactionResult };
|
|
33
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../execution/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,OAAO,EACZ,KAAK,KAAK,EAIV,KAAK,GAAG,EAMT,MAAM,MAAM,CAAA;AAmBb,OAAO,KAAK,EACV,YAAY,EAGb,MAAM,iBAAiB,CAAA;AAiBxB,OAAO,KAAK,EAEV,uBAAuB,EAIvB,WAAW,EACZ,MAAM,UAAU,CAAA;AASjB,KAAK,iBAAiB,GAClB;IACE,IAAI,EAAE,QAAQ,CAAA;IACd,IAAI,EAAE,GAAG,CAAA;IACT,WAAW,EAAE,MAAM,CAAA;IACnB,WAAW,EAAE,MAAM,CAAA;CACpB,GACD;IACE,IAAI,EAAE,QAAQ,CAAA;IACd,EAAE,EAAE,MAAM,CAAA;IACV,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,WAAW,EAAE,MAAM,CAAA;CACpB,CAAA;AAEL,iBAAe,eAAe,CAC5B,MAAM,EAAE,uBAAuB,EAC/B,WAAW,EAAE,WAAW,8BAyBzB;AA8RD,iBAAe,gBAAgB,CAC7B,MAAM,EAAE,uBAAuB,EAC/B,MAAM,EAAE,iBAAiB,EACzB,uBAAuB,EAAE,OAAO;;;;;;;;;;;;GAwCjC;AAED,iBAAe,qBAAqB,CAClC,MAAM,EAAE,uBAAuB,EAC/B,KAAK,EAAE,KAAK,EACZ,YAAY,EAAE,OAAO,EACrB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,MAAM,CAAC,CASjB;AAED,iBAAe,YAAY,CACzB,MAAM,EAAE,uBAAuB,EAC/B,UAAU,EAAE,OAAO,yDAMpB;AASD,OAAO,EACL,eAAe,EACf,gBAAgB,EAChB,qBAAqB,EACrB,YAAY,GACb,CAAA;AACD,YAAY,EAAE,iBAAiB,EAAE,CAAA"}
|
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.sendTransaction = sendTransaction;
|
|
4
|
+
exports.waitForExecution = waitForExecution;
|
|
5
|
+
exports.getMaxSpendableAmount = getMaxSpendableAmount;
|
|
6
|
+
exports.getPortfolio = getPortfolio;
|
|
7
|
+
const viem_1 = require("viem");
|
|
8
|
+
const account_abstraction_1 = require("viem/account-abstraction");
|
|
9
|
+
const chains_1 = require("viem/chains");
|
|
10
|
+
const accounts_1 = require("../accounts");
|
|
11
|
+
const utils_1 = require("../accounts/utils");
|
|
12
|
+
const modules_1 = require("../modules");
|
|
13
|
+
const validators_1 = require("../modules/validators");
|
|
14
|
+
const orchestrator_1 = require("../orchestrator");
|
|
15
|
+
const consts_1 = require("../orchestrator/consts");
|
|
16
|
+
const registry_1 = require("../orchestrator/registry");
|
|
17
|
+
const smart_session_1 = require("./smart-session");
|
|
18
|
+
const POLLING_INTERVAL = 500;
|
|
19
|
+
async function sendTransaction(config, transaction) {
|
|
20
|
+
if ('chain' in transaction) {
|
|
21
|
+
// Same-chain transaction
|
|
22
|
+
return await sendTransactionInternal(config, transaction.chain, transaction.chain, transaction.calls, transaction.gasLimit, transaction.tokenRequests, transaction.signers);
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
// Cross-chain transaction
|
|
26
|
+
return await sendTransactionInternal(config, transaction.sourceChain, transaction.targetChain, transaction.calls, transaction.gasLimit, transaction.tokenRequests, transaction.signers);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
async function sendTransactionInternal(config, sourceChain, targetChain, calls, gasLimit, initialTokenRequests, signers) {
|
|
30
|
+
if (sourceChain) {
|
|
31
|
+
const isAccountDeployed = await (0, accounts_1.isDeployed)(sourceChain, config);
|
|
32
|
+
if (!isAccountDeployed) {
|
|
33
|
+
await (0, accounts_1.deploySource)(sourceChain, config);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
const accountAddress = (0, accounts_1.getAddress)(config);
|
|
37
|
+
const withSession = signers?.type === 'session' ? signers.session : null;
|
|
38
|
+
// Across requires passing some value to repay the solvers
|
|
39
|
+
const tokenRequests = initialTokenRequests.length === 0
|
|
40
|
+
? [
|
|
41
|
+
{
|
|
42
|
+
address: viem_1.zeroAddress,
|
|
43
|
+
amount: 1n,
|
|
44
|
+
},
|
|
45
|
+
]
|
|
46
|
+
: initialTokenRequests;
|
|
47
|
+
if (withSession) {
|
|
48
|
+
if (!sourceChain) {
|
|
49
|
+
throw new Error(`Specifying source chain is required when using smart sessions`);
|
|
50
|
+
}
|
|
51
|
+
await (0, smart_session_1.enableSmartSession)(sourceChain, config, withSession);
|
|
52
|
+
// Smart sessions require a UserOp flow
|
|
53
|
+
return await sendTransactionAsUserOp(config, sourceChain, targetChain, calls, gasLimit, tokenRequests, accountAddress, withSession);
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
return await sendTransactionAsIntent(config, sourceChain, targetChain, calls, gasLimit, tokenRequests, accountAddress);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
async function sendTransactionAsUserOp(config, sourceChain, targetChain, calls, gasLimit, tokenRequests, accountAddress, withSession) {
|
|
60
|
+
const publicClient = (0, viem_1.createPublicClient)({
|
|
61
|
+
chain: sourceChain,
|
|
62
|
+
transport: (0, viem_1.http)(),
|
|
63
|
+
});
|
|
64
|
+
const sessionAccount = await (0, accounts_1.getSmartSessionSmartAccount)(config, publicClient, sourceChain, withSession);
|
|
65
|
+
const bundlerClient = (0, utils_1.getBundlerClient)(config, publicClient);
|
|
66
|
+
const targetPublicClient = (0, viem_1.createPublicClient)({
|
|
67
|
+
chain: targetChain,
|
|
68
|
+
transport: (0, viem_1.http)(),
|
|
69
|
+
});
|
|
70
|
+
const targetSessionAccount = await (0, accounts_1.getSmartSessionSmartAccount)(config, targetPublicClient, targetChain, withSession);
|
|
71
|
+
const targetBundlerClient = (0, utils_1.getBundlerClient)(config, targetPublicClient);
|
|
72
|
+
if (sourceChain.id === targetChain.id) {
|
|
73
|
+
await (0, smart_session_1.enableSmartSession)(targetChain, config, withSession);
|
|
74
|
+
const hash = await bundlerClient.sendUserOperation({
|
|
75
|
+
account: sessionAccount,
|
|
76
|
+
calls,
|
|
77
|
+
});
|
|
78
|
+
return {
|
|
79
|
+
type: 'userop',
|
|
80
|
+
hash,
|
|
81
|
+
sourceChain: sourceChain.id,
|
|
82
|
+
targetChain: targetChain.id,
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
const metaIntent = {
|
|
86
|
+
targetChainId: targetChain.id,
|
|
87
|
+
tokenTransfers: tokenRequests.map((tokenRequest) => ({
|
|
88
|
+
tokenAddress: tokenRequest.address,
|
|
89
|
+
amount: tokenRequest.amount,
|
|
90
|
+
})),
|
|
91
|
+
targetAccount: accountAddress,
|
|
92
|
+
targetGasUnits: gasLimit,
|
|
93
|
+
userOp: (0, orchestrator_1.getEmptyUserOp)(),
|
|
94
|
+
};
|
|
95
|
+
const orchestrator = getOrchestratorByChain(targetChain.id, config.rhinestoneApiKey);
|
|
96
|
+
const orderPath = await orchestrator.getOrderPath(metaIntent, accountAddress);
|
|
97
|
+
// Deploy the account on the target chain
|
|
98
|
+
await (0, accounts_1.deployTarget)(targetChain, config, true);
|
|
99
|
+
await (0, smart_session_1.enableSmartSession)(targetChain, config, withSession);
|
|
100
|
+
const userOp = await targetBundlerClient.prepareUserOperation({
|
|
101
|
+
account: targetSessionAccount,
|
|
102
|
+
calls: [...orderPath[0].injectedExecutions, ...calls],
|
|
103
|
+
stateOverride: [
|
|
104
|
+
...tokenRequests.map((request) => {
|
|
105
|
+
const rootBalanceSlot = (0, orchestrator_1.getTokenRootBalanceSlot)(targetChain, request.address);
|
|
106
|
+
const balanceSlot = rootBalanceSlot
|
|
107
|
+
? (0, viem_1.keccak256)((0, viem_1.encodeAbiParameters)([{ type: 'address' }, { type: 'uint256' }], [accountAddress, rootBalanceSlot]))
|
|
108
|
+
: '0x';
|
|
109
|
+
return {
|
|
110
|
+
address: request.address,
|
|
111
|
+
stateDiff: [
|
|
112
|
+
{
|
|
113
|
+
slot: balanceSlot,
|
|
114
|
+
value: (0, viem_1.pad)((0, viem_1.toHex)(request.amount)),
|
|
115
|
+
},
|
|
116
|
+
],
|
|
117
|
+
};
|
|
118
|
+
}),
|
|
119
|
+
],
|
|
120
|
+
});
|
|
121
|
+
userOp.signature = await targetSessionAccount.signUserOperation(userOp);
|
|
122
|
+
const userOpHash = (0, account_abstraction_1.getUserOperationHash)({
|
|
123
|
+
userOperation: userOp,
|
|
124
|
+
chainId: targetChain.id,
|
|
125
|
+
entryPointAddress: account_abstraction_1.entryPoint07Address,
|
|
126
|
+
entryPointVersion: '0.7',
|
|
127
|
+
});
|
|
128
|
+
orderPath[0].orderBundle.segments[0].witness.userOpHash = userOpHash;
|
|
129
|
+
const { hash, appDomainSeparator, contentsType, structHash } = await (0, smart_session_1.hashErc7739)(sourceChain, orderPath, accountAddress);
|
|
130
|
+
const signature = await (0, accounts_1.sign)(withSession.owners, targetChain, hash);
|
|
131
|
+
const sessionSignature = (0, smart_session_1.getSessionSignature)(signature, appDomainSeparator, structHash, contentsType, withSession);
|
|
132
|
+
const smartSessionValidator = (0, validators_1.getSmartSessionValidator)(config);
|
|
133
|
+
if (!smartSessionValidator) {
|
|
134
|
+
throw new Error('Smart session validator not available');
|
|
135
|
+
}
|
|
136
|
+
const packedSig = (0, viem_1.encodePacked)(['address', 'bytes'], [smartSessionValidator.address, sessionSignature]);
|
|
137
|
+
const signedOrderBundle = {
|
|
138
|
+
...orderPath[0].orderBundle,
|
|
139
|
+
originSignatures: Array(orderPath[0].orderBundle.segments.length).fill(packedSig),
|
|
140
|
+
targetSignature: packedSig,
|
|
141
|
+
};
|
|
142
|
+
const bundleResults = await orchestrator.postSignedOrderBundle([
|
|
143
|
+
{
|
|
144
|
+
signedOrderBundle,
|
|
145
|
+
userOp,
|
|
146
|
+
},
|
|
147
|
+
]);
|
|
148
|
+
return {
|
|
149
|
+
type: 'bundle',
|
|
150
|
+
id: bundleResults[0].bundleId,
|
|
151
|
+
sourceChain: sourceChain.id,
|
|
152
|
+
targetChain: targetChain.id,
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
async function sendTransactionAsIntent(config, sourceChain, targetChain, calls, gasLimit, tokenRequests, accountAddress) {
|
|
156
|
+
const accountAccessList = sourceChain
|
|
157
|
+
? {
|
|
158
|
+
chainIds: [sourceChain.id],
|
|
159
|
+
}
|
|
160
|
+
: undefined;
|
|
161
|
+
const metaIntent = {
|
|
162
|
+
targetChainId: targetChain.id,
|
|
163
|
+
tokenTransfers: tokenRequests.map((tokenRequest) => ({
|
|
164
|
+
tokenAddress: tokenRequest.address,
|
|
165
|
+
amount: tokenRequest.amount,
|
|
166
|
+
})),
|
|
167
|
+
targetAccount: accountAddress,
|
|
168
|
+
targetExecutions: calls.map((call) => ({
|
|
169
|
+
value: call.value ?? 0n,
|
|
170
|
+
to: call.to,
|
|
171
|
+
data: call.data ?? '0x',
|
|
172
|
+
})),
|
|
173
|
+
targetGasUnits: gasLimit,
|
|
174
|
+
accountAccessList,
|
|
175
|
+
};
|
|
176
|
+
const orchestrator = getOrchestratorByChain(targetChain.id, config.rhinestoneApiKey);
|
|
177
|
+
const orderPath = await orchestrator.getOrderPath(metaIntent, accountAddress);
|
|
178
|
+
orderPath[0].orderBundle.segments[0].witness.execs = [
|
|
179
|
+
...orderPath[0].injectedExecutions,
|
|
180
|
+
...metaIntent.targetExecutions,
|
|
181
|
+
];
|
|
182
|
+
const orderBundleHash = (0, orchestrator_1.getOrderBundleHash)(orderPath[0].orderBundle);
|
|
183
|
+
const bundleSignature = await (0, accounts_1.sign)(config.owners, sourceChain || targetChain, orderBundleHash);
|
|
184
|
+
const validatorModule = (0, modules_1.getOwnerValidator)(config);
|
|
185
|
+
const packedSig = (0, viem_1.encodePacked)(['address', 'bytes'], [validatorModule.address, bundleSignature]);
|
|
186
|
+
const signedOrderBundle = {
|
|
187
|
+
...orderPath[0].orderBundle,
|
|
188
|
+
originSignatures: Array(orderPath[0].orderBundle.segments.length).fill(packedSig),
|
|
189
|
+
targetSignature: packedSig,
|
|
190
|
+
};
|
|
191
|
+
await (0, accounts_1.deployTarget)(targetChain, config, false);
|
|
192
|
+
const initCode = (0, accounts_1.getBundleInitCode)(config);
|
|
193
|
+
const bundleResults = await orchestrator.postSignedOrderBundle([
|
|
194
|
+
{
|
|
195
|
+
signedOrderBundle,
|
|
196
|
+
initCode,
|
|
197
|
+
},
|
|
198
|
+
]);
|
|
199
|
+
return {
|
|
200
|
+
type: 'bundle',
|
|
201
|
+
id: bundleResults[0].bundleId,
|
|
202
|
+
sourceChain: sourceChain?.id,
|
|
203
|
+
targetChain: targetChain.id,
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
async function waitForExecution(config, result, acceptsPreconfirmations) {
|
|
207
|
+
const validStatuses = new Set([
|
|
208
|
+
orchestrator_1.BUNDLE_STATUS_FAILED,
|
|
209
|
+
orchestrator_1.BUNDLE_STATUS_COMPLETED,
|
|
210
|
+
orchestrator_1.BUNDLE_STATUS_FILLED,
|
|
211
|
+
]);
|
|
212
|
+
if (acceptsPreconfirmations) {
|
|
213
|
+
validStatuses.add(orchestrator_1.BUNDLE_STATUS_PRECONFIRMED);
|
|
214
|
+
}
|
|
215
|
+
switch (result.type) {
|
|
216
|
+
case 'bundle': {
|
|
217
|
+
let bundleResult = null;
|
|
218
|
+
while (bundleResult === null || !validStatuses.has(bundleResult.status)) {
|
|
219
|
+
const orchestrator = getOrchestratorByChain(result.targetChain, config.rhinestoneApiKey);
|
|
220
|
+
bundleResult = await orchestrator.getBundleStatus(result.id);
|
|
221
|
+
await new Promise((resolve) => setTimeout(resolve, POLLING_INTERVAL));
|
|
222
|
+
}
|
|
223
|
+
if (bundleResult.status === orchestrator_1.BUNDLE_STATUS_FAILED) {
|
|
224
|
+
throw new Error('Bundle failed');
|
|
225
|
+
}
|
|
226
|
+
return bundleResult;
|
|
227
|
+
}
|
|
228
|
+
case 'userop': {
|
|
229
|
+
const targetChain = (0, registry_1.getChainById)(result.targetChain);
|
|
230
|
+
const publicClient = (0, viem_1.createPublicClient)({
|
|
231
|
+
chain: targetChain,
|
|
232
|
+
transport: (0, viem_1.http)(),
|
|
233
|
+
});
|
|
234
|
+
const bundlerClient = (0, utils_1.getBundlerClient)(config, publicClient);
|
|
235
|
+
const receipt = await bundlerClient.waitForUserOperationReceipt({
|
|
236
|
+
hash: result.hash,
|
|
237
|
+
});
|
|
238
|
+
return receipt;
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
async function getMaxSpendableAmount(config, chain, tokenAddress, gasUnits) {
|
|
243
|
+
const address = (0, accounts_1.getAddress)(config);
|
|
244
|
+
const orchestrator = getOrchestratorByChain(chain.id, config.rhinestoneApiKey);
|
|
245
|
+
return orchestrator.getMaxTokenAmount(address, chain.id, tokenAddress, gasUnits);
|
|
246
|
+
}
|
|
247
|
+
async function getPortfolio(config, onTestnets) {
|
|
248
|
+
const address = (0, accounts_1.getAddress)(config);
|
|
249
|
+
const chainId = onTestnets ? chains_1.sepolia.id : chains_1.mainnet.id;
|
|
250
|
+
const orchestrator = getOrchestratorByChain(chainId, config.rhinestoneApiKey);
|
|
251
|
+
return orchestrator.getPortfolio(address);
|
|
252
|
+
}
|
|
253
|
+
function getOrchestratorByChain(chainId, apiKey) {
|
|
254
|
+
const orchestratorUrl = (0, registry_1.isTestnet)(chainId)
|
|
255
|
+
? consts_1.DEV_ORCHESTRATOR_URL
|
|
256
|
+
: consts_1.PROD_ORCHESTRATOR_URL;
|
|
257
|
+
return (0, orchestrator_1.getOrchestrator)(apiKey, orchestratorUrl);
|
|
258
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type Address, type Chain, type Hex } from 'viem';
|
|
2
|
+
import type { OrderPath } from '../orchestrator';
|
|
3
|
+
import type { RhinestoneAccountConfig, Session } from '../types';
|
|
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
|
+
}>;
|
|
11
|
+
declare function getSessionSignature(signature: Hex, appDomainSeparator: Hex, structHash: Hex, contentsType: string, withSession: Session): `0x${string}`;
|
|
12
|
+
export { enableSmartSession, hashErc7739, getSessionSignature };
|
|
13
|
+
//# 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,OAAO,EACZ,KAAK,KAAK,EAIV,KAAK,GAAG,EAGT,MAAM,MAAM,CAAA;AAWb,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAEhD,OAAO,KAAK,EAAE,uBAAuB,EAAE,OAAO,EAAE,MAAM,UAAU,CAAA;AAEhE,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;;;;;GAiExB;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,85 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.enableSmartSession = enableSmartSession;
|
|
4
|
+
exports.hashErc7739 = hashErc7739;
|
|
5
|
+
exports.getSessionSignature = getSessionSignature;
|
|
6
|
+
const viem_1 = require("viem");
|
|
7
|
+
const accounts_1 = require("../accounts");
|
|
8
|
+
const utils_1 = require("../accounts/utils");
|
|
9
|
+
const validators_1 = require("../modules/validators");
|
|
10
|
+
const utils_2 = require("../orchestrator/utils");
|
|
11
|
+
async function enableSmartSession(chain, config, session) {
|
|
12
|
+
const publicClient = (0, viem_1.createPublicClient)({
|
|
13
|
+
chain,
|
|
14
|
+
transport: (0, viem_1.http)(),
|
|
15
|
+
});
|
|
16
|
+
const address = (0, accounts_1.getAddress)(config);
|
|
17
|
+
const isEnabled = await (0, validators_1.isSessionEnabled)(publicClient, address, (0, validators_1.getPermissionId)(session));
|
|
18
|
+
if (isEnabled) {
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
const smartAccount = await (0, accounts_1.getSmartAccount)(config, publicClient, chain);
|
|
22
|
+
const bundlerClient = (0, utils_1.getBundlerClient)(config, publicClient);
|
|
23
|
+
const enableSessionCall = await (0, validators_1.getEnableSessionCall)(chain, session);
|
|
24
|
+
const opHash = await bundlerClient.sendUserOperation({
|
|
25
|
+
account: smartAccount,
|
|
26
|
+
calls: [enableSessionCall],
|
|
27
|
+
});
|
|
28
|
+
await bundlerClient.waitForUserOperationReceipt({
|
|
29
|
+
hash: opHash,
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
async function hashErc7739(sourceChain, orderPath, accountAddress) {
|
|
33
|
+
const publicClient = (0, viem_1.createPublicClient)({
|
|
34
|
+
chain: sourceChain,
|
|
35
|
+
transport: (0, viem_1.http)(),
|
|
36
|
+
});
|
|
37
|
+
const { appDomainSeparator, contentsType } = await (0, validators_1.getSessionAllowedERC7739Content)(sourceChain);
|
|
38
|
+
// Create hash following ERC-7739 TypedDataSign workflow
|
|
39
|
+
const typedDataSignTypehash = (0, viem_1.keccak256)((0, viem_1.encodePacked)(['string'], [
|
|
40
|
+
'TypedDataSign(MultichainCompact contents,string name,string version,uint256 chainId,address verifyingContract,bytes32 salt)'.concat(contentsType),
|
|
41
|
+
]));
|
|
42
|
+
// Original struct hash
|
|
43
|
+
const structHash = (0, utils_2.hashMultichainCompactWithoutDomainSeparator)(orderPath[0].orderBundle);
|
|
44
|
+
const { name, version, chainId, verifyingContract, salt } = await (0, validators_1.getAccountEIP712Domain)(publicClient, accountAddress);
|
|
45
|
+
// Final hash according to ERC-7739
|
|
46
|
+
const hash = (0, viem_1.keccak256)((0, viem_1.encodePacked)(['bytes2', 'bytes32', 'bytes32'], [
|
|
47
|
+
'0x1901',
|
|
48
|
+
appDomainSeparator,
|
|
49
|
+
(0, viem_1.keccak256)((0, viem_1.encodeAbiParameters)([
|
|
50
|
+
{ name: 'typedDataSignTypehash', type: 'bytes32' },
|
|
51
|
+
{ name: 'structHash', type: 'bytes32' },
|
|
52
|
+
{ name: 'name', type: 'bytes32' },
|
|
53
|
+
{ name: 'version', type: 'bytes32' },
|
|
54
|
+
{ name: 'chainId', type: 'uint256' },
|
|
55
|
+
{ name: 'verifyingContract', type: 'address' },
|
|
56
|
+
{ name: 'salt', type: 'bytes32' },
|
|
57
|
+
], [
|
|
58
|
+
typedDataSignTypehash,
|
|
59
|
+
structHash,
|
|
60
|
+
(0, viem_1.keccak256)((0, viem_1.encodePacked)(['string'], [name])),
|
|
61
|
+
(0, viem_1.keccak256)((0, viem_1.encodePacked)(['string'], [version])),
|
|
62
|
+
BigInt(Number(chainId)),
|
|
63
|
+
verifyingContract,
|
|
64
|
+
salt,
|
|
65
|
+
])),
|
|
66
|
+
]));
|
|
67
|
+
return {
|
|
68
|
+
hash,
|
|
69
|
+
appDomainSeparator,
|
|
70
|
+
contentsType,
|
|
71
|
+
structHash,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
function getSessionSignature(signature, appDomainSeparator, structHash, contentsType, withSession) {
|
|
75
|
+
const erc7739Signature = (0, viem_1.encodePacked)(['bytes', 'bytes32', 'bytes32', 'string', 'uint16'], [
|
|
76
|
+
signature,
|
|
77
|
+
appDomainSeparator,
|
|
78
|
+
structHash,
|
|
79
|
+
contentsType,
|
|
80
|
+
contentsType.length,
|
|
81
|
+
]);
|
|
82
|
+
// Pack with permissionId for smart session
|
|
83
|
+
const wrappedSignature = (0, viem_1.encodePacked)(['bytes32', 'bytes'], [(0, validators_1.getPermissionId)(withSession), erc7739Signature]);
|
|
84
|
+
return wrappedSignature;
|
|
85
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { Address, Chain } from 'viem';
|
|
2
|
+
import type { TransactionResult } from './execution';
|
|
3
|
+
import type { BundleStatus, MetaIntent, MultiChainCompact, PostOrderBundleResult, SignedMultiChainCompact } from './orchestrator';
|
|
4
|
+
import type { Call, Execution, RhinestoneAccountConfig, Session, Transaction } from './types';
|
|
5
|
+
/**
|
|
6
|
+
* Initialize a Rhinestone account
|
|
7
|
+
* Note: accounts are deployed onchain only when the first transaction is sent.
|
|
8
|
+
* @param config Account config (e.g. implementation vendor, owner signers, smart sessions)
|
|
9
|
+
* @returns account
|
|
10
|
+
*/
|
|
11
|
+
declare function createRhinestoneAccount(config: RhinestoneAccountConfig): Promise<{
|
|
12
|
+
config: RhinestoneAccountConfig;
|
|
13
|
+
sendTransaction: (transaction: Transaction) => Promise<TransactionResult>;
|
|
14
|
+
waitForExecution: (result: TransactionResult, acceptsPreconfirmations?: boolean) => Promise<import("./orchestrator").BundleResult | {
|
|
15
|
+
actualGasCost: bigint;
|
|
16
|
+
actualGasUsed: bigint;
|
|
17
|
+
entryPoint: Address;
|
|
18
|
+
logs: import("viem").Log<bigint, number, false>[];
|
|
19
|
+
nonce: bigint;
|
|
20
|
+
paymaster?: `0x${string}` | undefined;
|
|
21
|
+
reason?: string | undefined | undefined;
|
|
22
|
+
receipt: import("viem").TransactionReceipt<bigint, number, "success" | "reverted">;
|
|
23
|
+
sender: Address;
|
|
24
|
+
success: boolean;
|
|
25
|
+
userOpHash: import("viem").Hash;
|
|
26
|
+
}>;
|
|
27
|
+
getAddress: () => `0x${string}`;
|
|
28
|
+
getPortfolio: (onTestnets?: boolean) => Promise<import("./orchestrator").UserTokenBalance[]>;
|
|
29
|
+
getMaxSpendableAmount: (chain: Chain, tokenAddress: Address, gasUnits: bigint) => Promise<bigint>;
|
|
30
|
+
deploySource: (chain: Chain) => Promise<void>;
|
|
31
|
+
}>;
|
|
32
|
+
export { createRhinestoneAccount };
|
|
33
|
+
export type { BundleStatus, Session, Call, Execution, MetaIntent, MultiChainCompact, PostOrderBundleResult, SignedMultiChainCompact, };
|
|
34
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,MAAM,CAAA;AAE1C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AAOpD,OAAO,KAAK,EACV,YAAY,EACZ,UAAU,EACV,iBAAiB,EACjB,qBAAqB,EACrB,uBAAuB,EACxB,MAAM,gBAAgB,CAAA;AACvB,OAAO,KAAK,EACV,IAAI,EACJ,SAAS,EACT,uBAAuB,EACvB,OAAO,EACP,WAAW,EACZ,MAAM,SAAS,CAAA;AAEhB;;;;;GAKG;AACH,iBAAe,uBAAuB,CAAC,MAAM,EAAE,uBAAuB;;mCAM9B,WAAW;+BAWvC,iBAAiB;;;;;;;;;;;;;;;mCA+BlB,KAAK,gBACE,OAAO,YACX,MAAM;0BAKW,KAAK;GAanC;AAED,OAAO,EAAE,uBAAuB,EAAE,CAAA;AAClC,YAAY,EACV,YAAY,EACZ,OAAO,EACP,IAAI,EACJ,SAAS,EACT,UAAU,EACV,iBAAiB,EACjB,qBAAqB,EACrB,uBAAuB,GACxB,CAAA"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createRhinestoneAccount = createRhinestoneAccount;
|
|
4
|
+
const accounts_1 = require("./accounts");
|
|
5
|
+
const execution_1 = require("./execution");
|
|
6
|
+
/**
|
|
7
|
+
* Initialize a Rhinestone account
|
|
8
|
+
* Note: accounts are deployed onchain only when the first transaction is sent.
|
|
9
|
+
* @param config Account config (e.g. implementation vendor, owner signers, smart sessions)
|
|
10
|
+
* @returns account
|
|
11
|
+
*/
|
|
12
|
+
async function createRhinestoneAccount(config) {
|
|
13
|
+
/**
|
|
14
|
+
* Sign and send a transaction
|
|
15
|
+
* @param transaction Transaction to send
|
|
16
|
+
* @returns transaction result object (a bundle ID or a UserOp hash)
|
|
17
|
+
*/
|
|
18
|
+
function sendTransaction(transaction) {
|
|
19
|
+
return (0, execution_1.sendTransaction)(config, transaction);
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Wait for the transaction execution onchain
|
|
23
|
+
* @param result transaction result object
|
|
24
|
+
* @param acceptsPreconfirmations whether to accept preconfirmations from relayers before the transaction lands onchain (enabled by default)
|
|
25
|
+
* @returns bundle result or a UserOp receipt
|
|
26
|
+
*/
|
|
27
|
+
function waitForExecution(result, acceptsPreconfirmations = true) {
|
|
28
|
+
return (0, execution_1.waitForExecution)(config, result, acceptsPreconfirmations);
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Get account address
|
|
32
|
+
* @returns Address of the smart account
|
|
33
|
+
*/
|
|
34
|
+
function getAddress() {
|
|
35
|
+
return (0, accounts_1.getAddress)(config);
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Get account portfolio
|
|
39
|
+
* @param onTestnets Whether to query the testnet balances (default is `false`)
|
|
40
|
+
* @returns Account balances
|
|
41
|
+
*/
|
|
42
|
+
function getPortfolio(onTestnets = false) {
|
|
43
|
+
return (0, execution_1.getPortfolio)(config, onTestnets);
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Get the maximum spendable token amount on the target chain
|
|
47
|
+
* @param chain Target chain
|
|
48
|
+
* @param tokenAddress Token address (on the target chain)
|
|
49
|
+
* @param gasUnits Gas cost estimate for the transaction execution
|
|
50
|
+
* @returns Maximum spendable amount in absolute units
|
|
51
|
+
*/
|
|
52
|
+
function getMaxSpendableAmount(chain, tokenAddress, gasUnits) {
|
|
53
|
+
return (0, execution_1.getMaxSpendableAmount)(config, chain, tokenAddress, gasUnits);
|
|
54
|
+
}
|
|
55
|
+
function deploySource(chain) {
|
|
56
|
+
return (0, accounts_1.deploySource)(chain, config);
|
|
57
|
+
}
|
|
58
|
+
return {
|
|
59
|
+
config,
|
|
60
|
+
sendTransaction,
|
|
61
|
+
waitForExecution,
|
|
62
|
+
getAddress,
|
|
63
|
+
getPortfolio,
|
|
64
|
+
getMaxSpendableAmount,
|
|
65
|
+
deploySource,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
declare const enableSessionsAbi: {
|
|
2
|
+
type: string;
|
|
3
|
+
name: string;
|
|
4
|
+
inputs: {
|
|
5
|
+
name: string;
|
|
6
|
+
type: string;
|
|
7
|
+
internalType: string;
|
|
8
|
+
components: ({
|
|
9
|
+
name: string;
|
|
10
|
+
type: string;
|
|
11
|
+
internalType: string;
|
|
12
|
+
components?: undefined;
|
|
13
|
+
} | {
|
|
14
|
+
name: string;
|
|
15
|
+
type: string;
|
|
16
|
+
internalType: string;
|
|
17
|
+
components: ({
|
|
18
|
+
name: string;
|
|
19
|
+
type: string;
|
|
20
|
+
internalType: string;
|
|
21
|
+
components?: undefined;
|
|
22
|
+
} | {
|
|
23
|
+
name: string;
|
|
24
|
+
type: string;
|
|
25
|
+
internalType: string;
|
|
26
|
+
components: {
|
|
27
|
+
name: string;
|
|
28
|
+
type: string;
|
|
29
|
+
internalType: string;
|
|
30
|
+
}[];
|
|
31
|
+
})[];
|
|
32
|
+
})[];
|
|
33
|
+
}[];
|
|
34
|
+
outputs: {
|
|
35
|
+
name: string;
|
|
36
|
+
type: string;
|
|
37
|
+
internalType: string;
|
|
38
|
+
}[];
|
|
39
|
+
stateMutability: string;
|
|
40
|
+
}[];
|
|
41
|
+
export { enableSessionsAbi };
|
|
42
|
+
//# sourceMappingURL=smart-sessions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"smart-sessions.d.ts","sourceRoot":"","sources":["../../../modules/abi/smart-sessions.ts"],"names":[],"mappings":"AAAA,QAAA,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8HtB,CAAA;AAED,OAAO,EAAE,iBAAiB,EAAE,CAAA"}
|