Skip to content

Commit

Permalink
chore: fix sessions
Browse files Browse the repository at this point in the history
  • Loading branch information
joepegler committed May 17, 2024
1 parent 26e1546 commit 6ba34bc
Show file tree
Hide file tree
Showing 6 changed files with 52 additions and 69 deletions.
5 changes: 3 additions & 2 deletions examples/CREATE_AND_USE_A_BATCH_SESSION.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,11 +116,12 @@ const nftMintTx: Transaction = {
}),
};

const txs = [transferTx, nftMintTx];
const txs = [nftMintTx, transferTx];
const correspondingIndexes = [1, 0]; // The order of the txs from the sessionBatch

const batchSessionParams = await getBatchSessionTxParams(
["ERC20", "ABI"],
txs,
correspondingIndexes,
session,
chain
);
Expand Down
4 changes: 2 additions & 2 deletions src/account/utils/Constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,8 @@ export const ERROR_MESSAGES = {
"'Amount' is required for withdrawal of native token without using a paymaster",
MISSING_RPC_URL:
"rpcUrl is required for PrivateKeyAccount signer type, please provide it in the config",
INVALID_SESSION_TYPES:
"Session types and transactions must be of the same length",
INVALID_SESSION_INDEXES:
"Session indexes and transactions must be of the same length and correspond to each other",
SIGNER_REQUIRED: "Signer is required for creating a smart account"
}

Expand Down
2 changes: 0 additions & 2 deletions src/modules/BatchedSessionRouterModule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -301,8 +301,6 @@ export class BatchedSessionRouterModule extends BaseValidationModule {
keccak256(leafDataHex)
)

console.log({ proof })

const sessionDataTuple: SessionDataTuple = [
BigInt(sessionSignerData.validUntil),
BigInt(sessionSignerData.validAfter),
Expand Down
25 changes: 10 additions & 15 deletions src/modules/sessions/batch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -183,31 +183,29 @@ export const createBatchSession = async (
}
}

const types = ["ERC20", "ABI"] as const
export type BatchSessionParamsPayload = {
params: { batchSessionParams: SessionParams[] }
}
export type SessionValidationType = (typeof types)[number]
/**
* getBatchSessionTxParams
*
* Retrieves the transaction parameters for a batched session.
*
* @param sessionTypes - An array of session types.
* @param transactions - An array of {@link Transaction}s.
* @param correspondingIndexes - An array of indexes for the transactions corresponding to the relevant session
* @param session - {@link Session}.
* @param chain - The chain.
* @returns Promise<{@link BatchSessionParamsPayload}> - session parameters.
*
*/
export const getBatchSessionTxParams = async (
sessionValidationTypes: SessionValidationType[],
transactions: Transaction[],
correspondingIndexes: number[],
{ sessionIDInfo, sessionStorageClient }: Session,
chain: Chain
): Promise<BatchSessionParamsPayload> => {
if (sessionValidationTypes.length !== transactions.length) {
throw new Error(ERROR_MESSAGES.INVALID_SESSION_TYPES)
if (correspondingIndexes.length !== transactions.length) {
throw new Error(ERROR_MESSAGES.INVALID_SESSION_INDEXES)
}

const sessionSigner = await sessionStorageClient.getSignerBySession(
Expand All @@ -217,17 +215,14 @@ export const getBatchSessionTxParams = async (
chain
)

const batchSessionParams: SessionParams[] = sessionValidationTypes.map(
(sessionType, i): SessionParams => ({
sessionSigner,
sessionValidationModule: MODULE_ADDRESSES[sessionType],
sessionID: sessionIDInfo[i]
})
)

return {
params: {
batchSessionParams
batchSessionParams: correspondingIndexes.map(
(i): SessionParams => ({
sessionSigner,
sessionID: sessionIDInfo[i]
})
)
}
}
}
2 changes: 1 addition & 1 deletion tests/modules/read.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ describe("Modules:Read", () => {
const EXPECTED_SESSION_KEY_DATA =
"0x000000000000000000000000fa66e705cf2582cf56528386bb9dfca119767262000000000000000000000000747a4168db14f57871fa8cda8b5455d8c2a8e90a0000000000000000000000003079b249dfde4692d7844aa261f8cf7d927a0da50000000000000000000000000000000000000000000000000000000000989680"
const EXPECTED_ABI_SESSION_DATA =
"0xFA66E705cf2582cF56528386Bb9dFCA119767262747A4168DB14F57871fa8cda8B5455D8C2a8e90aa9059cbb0000000000000000000000000098968000020000000000000000000000000000003079B249DFDE4692D7844aA261f8cf7D927A0DA5000101989680"
"0xFA66E705cf2582cF56528386Bb9dFCA119767262747A4168DB14F57871fa8cda8B5455D8C2a8e90aa9059cbb0000000000000000000000000098968000020000000000000000000000000000003079B249DFDE4692D7844aA261f8cf7D927A0DA50001010000000000000000000000000000000000000000000000000000000000989680"
const sessionKeyEOA = "0xFA66E705cf2582cF56528386Bb9dFCA119767262"
const token = "0x747A4168DB14F57871fa8cda8B5455D8C2a8e90a"
const recipient = "0x3079B249DFDE4692D7844aA261f8cf7D927A0DA5"
Expand Down
83 changes: 36 additions & 47 deletions tests/modules/write.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ describe("Modules:Write", () => {
})

// User must be connected with a wallet to grant permissions
test.skip("should create a single session on behalf of a user", async () => {
test("should create a single session on behalf of a user", async () => {
const { sessionKeyAddress, sessionStorageClient } =
await createSessionKeyEOA(
smartAccountThree,
Expand Down Expand Up @@ -213,18 +213,18 @@ describe("Modules:Write", () => {
} = await wait()

// Save the sessionID for the next test
stores.single.sessionIDInfo = session.sessionIDInfo
stores.single = session

expect(success).toBe("true")
Logger.log("Tx Hash: ", transactionHash)
}, 50000)

// User no longer has to be connected,
// Only the reference to the relevant sessionID and the store from the previous step is needed to execute txs on the user's behalf
test.skip("should use the session to mint an NFT for the user", async () => {
test("should use the session to mint an NFT for the user", async () => {
// Setup
const session = stores.single
expect(stores.single.sessionIDInfo).toHaveLength(2) // Should have been set in the previous test
expect(stores.single.sessionIDInfo).toHaveLength(1) // Should have been set in the previous test

// Assume the real signer for userSmartAccountThree is no longer available (ie. user has logged out)
const smartAccountThreeWithSession = await createSessionSmartAccountClient(
Expand Down Expand Up @@ -274,7 +274,7 @@ describe("Modules:Write", () => {
})

// User must be connected with a wallet to grant permissions
test.skip("should create a batch session on behalf of a user", async () => {
test("should create a batch session on behalf of a user", async () => {
const { sessionKeyAddress, sessionStorageClient } =
await createSessionKeyEOA(
smartAccountFour,
Expand Down Expand Up @@ -333,21 +333,17 @@ describe("Modules:Write", () => {
expect(success).toBe("true")
stores.batch = session // Save the sessionID for the next test

expect(session.sessionIDInfo).toHaveLength(2)
// Save the sessionID for the next test
expect(session.sessionIDInfo).toHaveLength(2) // Save the sessionID for the next test

Logger.log("Tx Hash: ", transactionHash)
Logger.log("session: ", { session })
}, 50000)

// User no longer has to be connected,
// Only the reference to the relevant sessionID and the store from the previous step is needed to execute txs on the user's behalf
test.skip("should use the batch session to mint an NFT, and pay some token for the user", async () => {
// Setup
test("should use the batch session to mint an NFT, and pay some token for the user", async () => {
// Setup
const session = stores.batch
expect(session.sessionIDInfo).toHaveLength(2)
// Should have been set in the previous test

// Assume the real signer for userSmartAccountFour is no longer available (ie. user has logged out);
const smartAccountFourWithSession = await createSessionSmartAccountClient(
Expand Down Expand Up @@ -392,8 +388,8 @@ describe("Modules:Write", () => {
const txs = [transferTx, nftMintTx]

const batchSessionParams = await getBatchSessionTxParams(
["ERC20", "ABI"],
txs,
[0, 1],
session,
chain
)
Expand All @@ -414,7 +410,7 @@ describe("Modules:Write", () => {
expect(nftBalanceAfter - nftBalanceBefore).toBe(1n)
}, 50000)

test.skip("should use MultichainValidationModule to mint an NFT on two chains with sponsorship", async () => {
test("should use MultichainValidationModule to mint an NFT on two chains with sponsorship", async () => {
const nftAddress: Hex = "0x1758f42Af7026fBbB559Dc60EcE0De3ef81f665e"

const chainIdBase = 84532
Expand Down Expand Up @@ -532,7 +528,7 @@ describe("Modules:Write", () => {
expect(success2).toBe("true")
}, 50000)

test.skip("should use SessionValidationModule to send a user op", async () => {
test("should use SessionValidationModule to send a user op", async () => {
let sessionSigner: WalletClientSigner
const sessionKeyEOA = walletClient.account.address
const recipient = walletClientTwo.account.address
Expand Down Expand Up @@ -667,7 +663,7 @@ describe("Modules:Write", () => {
expect(maticBalanceAfter).toEqual(maticBalanceBefore)
}, 60000)

test.skip("should enable batched module", async () => {
test("should enable batched module", async () => {
const smartAccount = await createSmartAccountClient({
signer: walletClient,
bundlerUrl,
Expand All @@ -690,7 +686,7 @@ describe("Modules:Write", () => {
}
}, 50000)

test.skip("should use ABI SVM to allow transfer ownership of smart account", async () => {
test("should use ABI SVM to allow transfer ownership of smart account", async () => {
const smartAccount = await createSmartAccountClient({
chainId,
signer: walletClient,
Expand Down Expand Up @@ -860,36 +856,23 @@ describe("Modules:Write", () => {
new SessionMemoryStorage(smartAccountAddress)
)

const submitOrderAbi = parseAbi(["function submitOrder(uint256 _orderNum)"])

const submitCancelAbi = parseAbi([
"function submitCancel(uint256 _orderNum)"
])

const paddedOne = pad("0x1", { size: 32 })
const order = parseAbi(["function submitOrder(uint256 _orderNum)"])
const cancel = parseAbi(["function submitCancel(uint256 _orderNum)"])

// const testContract = getContract({
// address: DUMMY_CONTRACT_ADDRESS,
// abi: submitCancelAbi,
// client: { public: publicClient, wallet: walletClient }
// })

// const thash = await testContract.write.submitCancel([1n])

const allowedFunctionCalls: CreateSessionDataParams[] = [
const sessionBatch: CreateSessionDataParams[] = [
createABISessionDatum({
interval: {
validUntil: 0,
validAfter: 0
},
sessionKeyAddress,
contractAddress: DUMMY_CONTRACT_ADDRESS,
functionSelector: submitCancelAbi[0],
functionSelector: cancel[0],
rules: [
{
offset: 0,
condition: 0,
referenceValue: { raw: paddedOne }
referenceValue: BigInt(1)
}
],
valueLimit: 0n
Expand All @@ -901,12 +884,12 @@ describe("Modules:Write", () => {
},
sessionKeyAddress,
contractAddress: DUMMY_CONTRACT_ADDRESS,
functionSelector: submitOrderAbi[0],
functionSelector: order[0],
rules: [
{
offset: 0,
condition: 0,
referenceValue: { raw: paddedOne }
referenceValue: BigInt(1)
}
],
valueLimit: 0n
Expand All @@ -916,7 +899,7 @@ describe("Modules:Write", () => {
const { wait, session } = await createBatchSession(
smartAccount,
sessionStorageClient,
allowedFunctionCalls,
sessionBatch,
withSponsorship
)

Expand All @@ -925,6 +908,9 @@ describe("Modules:Write", () => {
success
} = await wait()

expect(success).toBe("true")
expect(transactionHash).toBeTruthy()

const smartAccountWithSession = await createSessionSmartAccountClient(
{
accountAddress: await smartAccount.getAccountAddress(), // Set the account address on behalf of the user
Expand All @@ -936,40 +922,43 @@ describe("Modules:Write", () => {
true
)

const submitOrderTx: Transaction = {
const submitCancelTx: Transaction = {
to: DUMMY_CONTRACT_ADDRESS,
data: encodeFunctionData({
abi: submitOrderAbi,
functionName: "submitOrder",
abi: cancel,
functionName: "submitCancel",
args: [BigInt(1)]
})
}
const submitCancelTx: Transaction = {

const submitOrderTx: Transaction = {
to: DUMMY_CONTRACT_ADDRESS,
data: encodeFunctionData({
abi: submitCancelAbi,
functionName: "submitCancel",
abi: order,
functionName: "submitOrder",
args: [BigInt(1)]
})
}

// const txs = [submitOrderTx, submitCancelTx]
const txs = [submitOrderTx, submitCancelTx]
const correspondingIndexes = [1, 0] // The order of the txs from the sessionBatch

const batchSessionParams = await getBatchSessionTxParams(
["ABI", "ABI"],
txs,
correspondingIndexes,
session,
chain
)

const { wait: waitForTx } = await smartAccountWithSession.sendTransaction(
txs,
{
...batchSessionParams
...batchSessionParams,
...withSponsorship
}
)

const receipt = await waitForTx()
const { success: txSuccess } = await waitForTx()
expect(txSuccess).toBe("true")
}, 60000)
})

0 comments on commit 6ba34bc

Please sign in to comment.