Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 3731184

Browse files
committedSep 9, 2024·
Refactor session registration / deployment
1 parent 0a28af1 commit 3731184

File tree

12 files changed

+343
-385
lines changed

12 files changed

+343
-385
lines changed
 

‎packages/account-wasm/pkg/account_wasm.d.ts

+18-30
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,5 @@
11
/* tslint:disable */
22
/* eslint-disable */
3-
export interface JsInvocationsDetails {
4-
nonce: Felt;
5-
maxFee: Felt;
6-
}
7-
83
export interface JsOutsideExecution {
94
caller: Felt;
105
executeBefore: number;
@@ -13,24 +8,29 @@ export interface JsOutsideExecution {
138
nonce: Felt;
149
}
1510

16-
export interface JsPolicy {
17-
target: string;
18-
method: string;
19-
}
11+
export type Felts = JsFelt[];
12+
13+
export type JsFelt = Felt;
2014

2115
export interface JsCall {
2216
contractAddress: Felt;
2317
entrypoint: string;
2418
calldata: Felt[];
2519
}
2620

27-
export interface JsEstimateFeeDetails {
21+
export interface JsInvocationsDetails {
2822
nonce: Felt;
23+
maxFee: Felt;
2924
}
3025

31-
export type Felts = JsFelt[];
26+
export interface JsPolicy {
27+
target: string;
28+
method: string;
29+
}
3230

33-
export type JsFelt = Felt;
31+
export interface JsEstimateFeeDetails {
32+
nonce: Felt;
33+
}
3434

3535
export interface JsSession {
3636
policies: JsPolicy[];
@@ -115,13 +115,6 @@ export class CartridgeAccount {
115115
*/
116116
sessionJson(): any;
117117
/**
118-
* @param {(JsPolicy)[]} policies
119-
* @param {bigint} expires_at
120-
* @param {any} external_account
121-
* @returns {any}
122-
*/
123-
static registerSessionCalldata(policies: (JsPolicy)[], expires_at: bigint, external_account: any): any;
124-
/**
125118
*/
126119
revokeSession(): void;
127120
/**
@@ -139,19 +132,14 @@ export class CartridgeAccount {
139132
*/
140133
delegateAccount(): Promise<JsFelt>;
141134
/**
142-
* @param {any} salt
143-
* @param {any} external_owner
144-
* @returns {any}
145-
*/
146-
static getUdcDeployedAddress(salt: any, external_owner: any): any;
147-
/**
148-
* @returns {any}
149-
*/
150-
static getAccountClassHash(): any;
151-
/**
135+
* @param {any} owner
136+
* @param {any} username
137+
* @param {bigint} initial_deposit
138+
* @param {(JsPolicy)[]} policies
139+
* @param {bigint} expires_at
152140
* @returns {any}
153141
*/
154-
static getUdcAddress(): any;
142+
static externalDeploymentCalls(owner: any, username: any, initial_deposit: bigint, policies: (JsPolicy)[], expires_at: bigint): any;
155143
}
156144
/**
157145
*/

‎packages/account-wasm/pkg/account_wasm.js

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
12
import * as wasm from "./account_wasm_bg.wasm";
23
import { __wbg_set_wasm } from "./account_wasm_bg.js";
34
__wbg_set_wasm(wasm);

‎packages/account-wasm/pkg/account_wasm_bg.js

+178-204
Large diffs are not rendered by default.
4.62 KB
Binary file not shown.
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/* tslint:disable */
22
/* eslint-disable */
33
export const memory: WebAssembly.Memory;
4-
export function __wbg_cartridgeaccount_free(a: number): void;
4+
export function __wbg_cartridgeaccount_free(a: number, b: number): void;
55
export function cartridgeaccount_new(a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number, j: number, k: number, l: number, m: number, n: number, o: number): void;
66
export function cartridgeaccount_ownerGuid(a: number): number;
77
export function cartridgeaccount_registerSession(a: number, b: number, c: number, d: number, e: number): number;
@@ -11,15 +11,12 @@ export function cartridgeaccount_execute(a: number, b: number, c: number, d: num
1111
export function cartridgeaccount_executeFromOutside(a: number, b: number, c: number, d: number): number;
1212
export function cartridgeaccount_hasSession(a: number, b: number, c: number, d: number): void;
1313
export function cartridgeaccount_sessionJson(a: number, b: number): void;
14-
export function cartridgeaccount_registerSessionCalldata(a: number, b: number, c: number, d: number, e: number): void;
1514
export function cartridgeaccount_revokeSession(a: number, b: number): void;
1615
export function cartridgeaccount_signMessage(a: number, b: number, c: number): number;
1716
export function cartridgeaccount_deploySelf(a: number, b: number): number;
1817
export function cartridgeaccount_delegateAccount(a: number): number;
19-
export function cartridgeaccount_getUdcDeployedAddress(a: number, b: number, c: number): void;
20-
export function cartridgeaccount_getAccountClassHash(): number;
21-
export function cartridgeaccount_getUdcAddress(): number;
22-
export function __wbg_cartridgesessionaccount_free(a: number): void;
18+
export function cartridgeaccount_externalDeploymentCalls(a: number, b: number, c: number, d: number, e: number, f: number, g: number): void;
19+
export function __wbg_cartridgesessionaccount_free(a: number, b: number): void;
2320
export function cartridgesessionaccount_new(a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number): void;
2421
export function cartridgesessionaccount_new_as_registered(a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number): void;
2522
export function cartridgesessionaccount_sign(a: number, b: number, c: number, d: number): number;
@@ -28,7 +25,7 @@ export function cartridgesessionaccount_execute_from_outside(a: number, b: numbe
2825
export function __wbindgen_malloc(a: number, b: number): number;
2926
export function __wbindgen_realloc(a: number, b: number, c: number, d: number): number;
3027
export const __wbindgen_export_2: WebAssembly.Table;
31-
export function _dyn_core__ops__function__FnMut__A____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__h3f3a3deef6344805(a: number, b: number, c: number): void;
28+
export function _dyn_core__ops__function__FnMut__A____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__ha5780fd1342283cf(a: number, b: number, c: number): void;
3229
export function __wbindgen_add_to_stack_pointer(a: number): number;
3330
export function __wbindgen_exn_store(a: number): void;
34-
export function wasm_bindgen__convert__closures__invoke2_mut__hbcb2218b5bd12b96(a: number, b: number, c: number, d: number): void;
31+
export function wasm_bindgen__convert__closures__invoke2_mut__h11630e69f33a5871(a: number, b: number, c: number, d: number): void;

‎packages/account-wasm/src/lib.rs

+74-44
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,11 @@ use account_sdk::account::session::hash::Session;
1313
use account_sdk::account::session::raw_session::RawSession;
1414
use account_sdk::account::session::SessionAccount;
1515
use account_sdk::account::{AccountHashAndCallsSigner, MessageSignerAccount};
16-
use account_sdk::constants::{ACCOUNT_CLASS_HASH, UDC_ADDRESS};
16+
use account_sdk::constants::{ACCOUNT_CLASS_HASH, ETH_CONTRACT_ADDRESS, UDC_ADDRESS};
1717
use account_sdk::controller::Controller;
1818
use account_sdk::provider::{CartridgeJsonRpcProvider, CartridgeProvider};
1919
use account_sdk::signers::webauthn::{CredentialID, WebauthnSigner};
20-
use account_sdk::signers::{HashSigner, Signer};
20+
use account_sdk::signers::{HashSigner, Signer, SignerTrait};
2121
use base64::engine::general_purpose;
2222
use base64::Engine;
2323
use cainome::cairo_serde::{CairoSerde, ContractAddress};
@@ -37,6 +37,7 @@ use types::session::JsSession;
3737
use types::{Felts, JsFelt};
3838
use url::Url;
3939
use wasm_bindgen::prelude::*;
40+
use web_sys::console;
4041

4142
use crate::errors::OperationError;
4243
use crate::types::invocation::JsInvocationsDetails;
@@ -256,28 +257,6 @@ impl CartridgeAccount {
256257
.map_or_else(|| Ok(JsValue::NULL), Ok)
257258
}
258259

259-
#[wasm_bindgen(js_name = registerSessionCalldata)]
260-
pub fn register_session_calldata(
261-
policies: Vec<JsPolicy>,
262-
expires_at: u64,
263-
external_account: JsValue,
264-
) -> Result<JsValue> {
265-
let methods = policies
266-
.into_iter()
267-
.map(TryFrom::try_from)
268-
.collect::<std::result::Result<Vec<_>, _>>()?;
269-
270-
let signer = SigningKey::from_random();
271-
let session = Session::new(methods, expires_at, &signer.signer())?;
272-
273-
let calldata = [
274-
<RawSession as CairoSerde>::cairo_serialize(&session.raw()),
275-
vec![from_value(external_account)?],
276-
]
277-
.concat();
278-
Ok(to_value(&calldata)?)
279-
}
280-
281260
#[wasm_bindgen(js_name = revokeSession)]
282261
pub fn revoke_session(&self) -> Result<()> {
283262
unimplemented!("Revoke Session not implemented");
@@ -324,39 +303,90 @@ impl CartridgeAccount {
324303
Ok(JsFelt(res))
325304
}
326305

327-
#[wasm_bindgen(js_name = getUdcDeployedAddress)]
328-
pub fn get_udc_deployed_address(salt: JsValue, external_owner: JsValue) -> Result<JsValue> {
329-
set_panic_hook();
330-
331-
let salt = from_value::<Felt>(salt)?;
332-
let external_owner = from_value::<ContractAddress>(external_owner)?;
306+
#[wasm_bindgen(js_name = externalDeploymentCalls)]
307+
pub fn external_deployment_calls(
308+
owner: JsValue,
309+
username: JsValue,
310+
initial_deposit: u64,
311+
policies: Vec<JsPolicy>,
312+
expires_at: u64,
313+
) -> Result<JsValue> {
314+
let mut js_calls: Vec<JsCall> = vec![];
315+
let salt = from_value::<Felt>(username)?;
316+
let owner = from_value::<ContractAddress>(owner)?;
333317

334318
let mut constructor_calldata =
335-
controller::Owner::cairo_serialize(&controller::Owner::Account(external_owner));
319+
controller::Owner::cairo_serialize(&controller::Owner::Account(owner));
336320
constructor_calldata.extend(Option::<AbigenSigner>::cairo_serialize(&None));
337321

338-
let res = get_udc_deployed_address(
322+
let address = get_udc_deployed_address(
339323
salt,
340324
ACCOUNT_CLASS_HASH,
341325
&UdcUniqueness::NotUnique,
342326
&constructor_calldata,
343327
);
344328

329+
let mut udc_deploy_calldata = vec![
330+
ACCOUNT_CLASS_HASH,
331+
salt,
332+
Felt::ZERO, // unique false
333+
];
334+
udc_deploy_calldata.push(constructor_calldata.len().into());
335+
udc_deploy_calldata.extend(constructor_calldata);
336+
337+
// Universal Deployer Contract calldata
338+
js_calls.push(JsCall {
339+
contract_address: UDC_ADDRESS,
340+
entrypoint: "deployContract".to_string(),
341+
calldata: udc_deploy_calldata,
342+
});
343+
344+
// Set Delegate account
345+
js_calls.push(JsCall {
346+
contract_address: address,
347+
entrypoint: "set_delegate_account".to_string(),
348+
calldata: vec![owner.into()],
349+
});
350+
351+
// Register new session
352+
let methods = policies
353+
.into_iter()
354+
.map(TryFrom::try_from)
355+
.collect::<std::result::Result<Vec<_>, _>>()?;
356+
let session_signer = SigningKey::from_random();
357+
let session = Session::new(methods, expires_at, &session_signer.signer())?;
358+
359+
js_calls.push(JsCall {
360+
contract_address: address,
361+
entrypoint: "register_session".to_string(),
362+
calldata: [
363+
<RawSession as CairoSerde>::cairo_serialize(&session.raw()),
364+
vec![owner.into()],
365+
]
366+
.concat(),
367+
});
368+
369+
// Transfer ETH calldata
370+
if initial_deposit > 0 {
371+
js_calls.push(JsCall {
372+
contract_address: ETH_CONTRACT_ADDRESS,
373+
entrypoint: "approve".to_string(),
374+
calldata: vec![address, initial_deposit.into(), Felt::ZERO],
375+
});
376+
377+
js_calls.push(JsCall {
378+
contract_address: ETH_CONTRACT_ADDRESS,
379+
entrypoint: "transfer".to_string(),
380+
calldata: vec![address, initial_deposit.into(), Felt::ZERO],
381+
});
382+
}
383+
345384
Ok(to_value(&JsDeployment {
346-
address: res,
347-
calldata: constructor_calldata,
385+
address: address,
386+
calls: js_calls,
387+
session_key: session_signer.secret_scalar(),
348388
})?)
349389
}
350-
351-
#[wasm_bindgen(js_name = getAccountClassHash)]
352-
pub fn get_account_class_hash() -> JsValue {
353-
to_value(&ACCOUNT_CLASS_HASH).unwrap()
354-
}
355-
356-
#[wasm_bindgen(js_name = getUdcAddress)]
357-
pub fn get_udc_address() -> JsValue {
358-
to_value(&UDC_ADDRESS).unwrap()
359-
}
360390
}
361391

362392
#[wasm_bindgen]

‎packages/account-wasm/src/types/call.rs

+10
Original file line numberDiff line numberDiff line change
@@ -45,3 +45,13 @@ impl TryFrom<JsCall> for types::Call {
4545
})
4646
}
4747
}
48+
49+
impl From<types::Call> for JsCall {
50+
fn from(value: types::Call) -> Self {
51+
JsCall {
52+
contract_address: value.to.into(),
53+
entrypoint: value.selector.to_string(),
54+
calldata: value.calldata,
55+
}
56+
}
57+
}

‎packages/account-wasm/src/types/deployment.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,14 @@ use serde_with::serde_as;
33
use starknet::core::serde::unsigned_field_element::UfeHex;
44
use starknet::core::types::Felt;
55

6+
use super::call::JsCall;
7+
68
#[serde_as]
79
#[derive(Clone, Debug, Deserialize, Serialize)]
810
#[serde(rename_all = "camelCase")]
911
pub struct JsDeployment {
1012
#[serde_as(as = "UfeHex")]
1113
pub address: Felt,
12-
13-
#[serde_as(as = "Vec<UfeHex>")]
14-
pub calldata: Vec<Felt>,
14+
pub calls: Vec<JsCall>,
15+
pub session_key: Felt,
1516
}

‎packages/account_sdk/src/constants.rs

+3
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,6 @@ pub const ACCOUNT_COMPILED_CLASS_HASH: Felt =
1212

1313
pub const ERC_20_COMPILED_CLASS_HASH: Felt =
1414
felt!("0x732654ca6baa90ff202d2fcc35fb39766eb34842a7e5ac6dbf7714af71f1dab");
15+
16+
pub const ETH_CONTRACT_ADDRESS: Felt =
17+
felt!("0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7");

‎packages/keychain/src/components/connect/Login.tsx

-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ import { ErrorAlert } from "components/ErrorAlert";
1313

1414
export function Login(props: LoginProps) {
1515
const theme = useControllerTheme();
16-
console.debug("login render");
1716

1817
return (
1918
<Container

‎packages/keychain/src/components/connect/Signup/Argent.tsx

+50-93
Original file line numberDiff line numberDiff line change
@@ -28,18 +28,12 @@ import {
2828
useProvider,
2929
voyager,
3030
} from "@starknet-react/core";
31-
import {
32-
CallData,
33-
RpcProvider,
34-
TypedData,
35-
cairo,
36-
num,
37-
shortString,
38-
} from "starknet";
39-
import { CheckIcon, CopyAddress, DotsIcon, PacmanIcon } from "@cartridge/ui";
31+
import { RpcProvider, TypedData, num, shortString } from "starknet";
32+
import { CheckIcon, DotsIcon, PacmanIcon } from "@cartridge/ui";
4033
import { useConnection } from "hooks/connection";
4134
import { useToast } from "hooks/toast";
4235
import {
36+
ETH_CONTRACT_ADDRESS,
4337
TokenInfo,
4438
fetchTokenInfo,
4539
getBalanceStr,
@@ -51,7 +45,10 @@ import {
5145
import { ErrorAlert } from "../../ErrorAlert";
5246
import { beginAccountSignup, finalizeAccountSignup } from "hooks/account";
5347
import base64url from "base64url";
54-
import { CartridgeAccount } from "@cartridge/account-wasm";
48+
import {
49+
CartridgeAccount,
50+
CartridgeSessionAccount,
51+
} from "@cartridge/account-wasm";
5552

5653
enum SignupState {
5754
CONNECT,
@@ -109,13 +106,11 @@ export function SignupArgent({ username }: { username: string }) {
109106
function SignupArgentInner({ username }: { username: string }) {
110107
const { account: extAccount } = useAccount();
111108
const { connectAsync, connectors, isPending: isConnecting } = useConnect();
112-
const { chainId, chainName, policies } = useConnection();
109+
const { chainId, chainName, policies, rpcUrl } = useConnection();
113110
const { isChecked, tokens, isFetching, isAllFunded } = useTokens();
114111
const [isDeploying, setIsDeploying] = useState(false);
115112
const [error, setError] = useState<Error>();
116113
const [state, setState] = useState<SignupState>(SignupState.CONNECT);
117-
const [controllerAddress, setControllerAddress] = useState("");
118-
const [controllerCalldata, setControllerCalldata] = useState([]);
119114

120115
const [title, setTitle] = useState("");
121116

@@ -152,17 +147,6 @@ function SignupArgentInner({ username }: { username: string }) {
152147
const typedData = registerTypedData(username, { low, high }, chainId);
153148
const sig = await extAccount.signMessage(typedData);
154149
await finalizeAccountSignup(extAccount.address, chainId, sig as string[]);
155-
156-
// set controller address & calldata
157-
const salt = shortString.encodeShortString(username);
158-
const { address, calldata } = CartridgeAccount.getUdcDeployedAddress(
159-
salt,
160-
extAccount.address,
161-
);
162-
163-
setControllerAddress(address);
164-
setControllerCalldata(calldata);
165-
166150
setState(SignupState.DEPLOY);
167151
} catch (e) {
168152
console.log(e);
@@ -173,83 +157,59 @@ function SignupArgentInner({ username }: { username: string }) {
173157
const onDeploy = useCallback(async () => {
174158
if (!extAccount) return;
175159

176-
const calls = tokens.flatMap((t) => {
177-
const amount = cairo.uint256(t.min);
178-
return [
179-
{
180-
contractAddress: t.address,
181-
entrypoint: "approve",
182-
calldata: CallData.compile({
183-
recipient: controllerAddress,
184-
amount,
185-
}),
186-
},
187-
{
188-
contractAddress: t.address,
189-
entrypoint: "transfer",
190-
calldata: CallData.compile({
191-
recipient: controllerAddress,
192-
amount,
193-
}),
194-
},
195-
];
196-
});
197-
198-
// deployContract
199-
const salt = shortString.encodeShortString(username);
200-
calls.push({
201-
contractAddress: CartridgeAccount.getUdcAddress(),
202-
entrypoint: "deployContract",
203-
calldata: CallData.compile({
204-
classHash: CartridgeAccount.getAccountClassHash(),
205-
salt,
206-
unique: false,
207-
calldata: controllerCalldata,
208-
}),
209-
});
210-
211-
// registerSession
212-
calls.push({
213-
contractAddress: controllerAddress,
214-
entrypoint: "register_session",
215-
calldata: CartridgeAccount.registerSessionCalldata(
160+
try {
161+
setIsDeploying(true);
162+
163+
const {
164+
address: controllerAddress,
165+
calls: deploymentCalls,
166+
sessionKey,
167+
} = CartridgeAccount.externalDeploymentCalls(
168+
extAccount.address,
169+
shortString.encodeShortString(username),
170+
100000000000000000n,
216171
policies.map((p) => {
217172
return { target: p.target, method: p.method };
218173
}),
219174
3000000000n,
220-
extAccount.address,
221-
),
222-
});
223-
224-
console.log(
225-
calls
226-
.map((call) => {
227-
return CallData.compile(call)
228-
.map((i) => `0x${BigInt(i).toString(16)}`)
229-
.join(" ");
230-
})
231-
.join(" / "),
232-
);
175+
);
233176

234-
try {
235-
setIsDeploying(true);
236-
const res = await extAccount.execute(calls);
177+
const res = await extAccount.execute(deploymentCalls);
237178
await extAccount.waitForTransaction(res.transaction_hash, {
238179
retryInterval: 1000,
239180
});
181+
182+
// Test session account
183+
const sessionAccount = CartridgeSessionAccount.new_as_registered(
184+
rpcUrl,
185+
sessionKey,
186+
controllerAddress,
187+
extAccount.address,
188+
chainId,
189+
{
190+
policies: policies.map((p) => {
191+
return { target: p.target, method: p.method };
192+
}),
193+
expiresAt: 3000000000,
194+
},
195+
);
196+
197+
const res2 = await sessionAccount.execute([
198+
{
199+
contractAddress: ETH_CONTRACT_ADDRESS,
200+
entrypoint: "transfer",
201+
calldata: [extAccount.address, "0x2386F26FC10000", "0"],
202+
},
203+
]);
204+
205+
console.log(res2);
240206
} catch (e) {
241207
console.log(e);
242208
setError(e);
209+
} finally {
210+
setIsDeploying(false);
243211
}
244-
setIsDeploying(false);
245-
}, [
246-
extAccount,
247-
controllerAddress,
248-
controllerCalldata,
249-
policies,
250-
tokens,
251-
username,
252-
]);
212+
}, [extAccount, policies, tokens, username]);
253213

254214
// const onCopy = useCallback(() => {
255215
// navigator.clipboard.writeText(controllerAddress);
@@ -283,9 +243,7 @@ function SignupArgentInner({ username }: { username: string }) {
283243
"Please connect your ArgentX wallet"}
284244
{state === SignupState.SIGN_MESSAGE &&
285245
"Sign message to create your controller"}
286-
{state === SignupState.DEPLOY && (
287-
<CopyAddress address={controllerAddress} />
288-
)}
246+
{state === SignupState.DEPLOY && <></>}
289247
</>
290248
}
291249
// TODO: Add line icons
@@ -407,7 +365,6 @@ function SignupArgentInner({ username }: { username: string }) {
407365
<Button
408366
colorScheme="colorful"
409367
onClick={() => {
410-
console.log("deploy");
411368
onDeploy();
412369
}}
413370
isLoading={isDeploying}

‎packages/keychain/src/components/connect/Signup/index.tsx

-2
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,6 @@ export function Signup({
5050
1000,
5151
);
5252

53-
console.debug("signup render");
54-
5553
// In order for Safari to open "Create Passkey" modal successfully, submit handler has to be async.
5654
// The workaround is to call async validation function every time when username input changes
5755
useEffect(() => {

0 commit comments

Comments
 (0)
Please sign in to comment.