Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: remove hardcoded gas, fix estimation, sdk improvements #193

Merged
merged 54 commits into from
Nov 20, 2024
Merged
Show file tree
Hide file tree
Changes from 52 commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
17daeb5
feat: store sessions offchain to reduce gas
ly0va Nov 1, 2024
d628d0c
feat: signer assertion and more events
ly0va Nov 1, 2024
82fc11d
chore: update abi
ly0va Nov 1, 2024
efd733a
fix: remove max_constraints
ly0va Nov 1, 2024
edb2472
chore: rename
ly0va Nov 1, 2024
8789160
Merge remote-tracking branch 'origin/main' into lyova-offchain-sessions
ly0va Nov 2, 2024
9c5db07
fix: update abi
ly0va Nov 2, 2024
3bce3f0
fix: gas estimation
ly0va Nov 2, 2024
109a2fb
chore: add more logs
ly0va Nov 2, 2024
56c4be3
Merge branch 'main' into lyova-offchain-sessions
ly0va Nov 11, 2024
077ec6e
chore: update sdk
ly0va Nov 11, 2024
9e5a417
feat: pass session in sdk
ly0va Nov 12, 2024
fbefbfe
fix: sdk bug
ly0va Nov 12, 2024
499c680
fix: remove hardcoded gas limits
ly0va Nov 12, 2024
89c631c
fix: leave hardcoded gas limit in sdk for now
ly0va Nov 12, 2024
5bb0d63
Merge branch 'main' into lyova-offchain-sessions
ly0va Nov 12, 2024
677fa53
Merge branch 'main' into lyova-offchain-sessions
JackHamer09 Nov 12, 2024
2bd1bb3
fix: session interface improvements
JackHamer09 Nov 12, 2024
c0578b3
fix: enable ci and fix docs
JackHamer09 Nov 12, 2024
4bc524d
fix: readme formatting
JackHamer09 Nov 12, 2024
13b4e07
fix: remove redundant workflow triggers
JackHamer09 Nov 12, 2024
f404b9e
fix: update contract addresses
JackHamer09 Nov 12, 2024
d09bd78
fix: update addresses
JackHamer09 Nov 12, 2024
6659e39
fix: popup communicator
JackHamer09 Nov 12, 2024
9ece621
Merge branch 'lyova-offchain-sessions' of https://github.com/matter-l…
JackHamer09 Nov 12, 2024
827512c
fix: e2e
JackHamer09 Nov 12, 2024
95c3af8
fix: move session defaults out of computed
JackHamer09 Nov 12, 2024
c7636ba
fix: rename fee to feeLimit
JackHamer09 Nov 13, 2024
fd4333c
fix: limit zero incorrect LimitType
JackHamer09 Nov 13, 2024
f2fb3fd
fix: remove session spec, which is copy of createSession from abi
JackHamer09 Nov 13, 2024
fcb0d79
fix: sdk build
JackHamer09 Nov 13, 2024
da9aa0d
fix: remove redundant bigint conversions
JackHamer09 Nov 13, 2024
c762d9d
fix: update interface to support specifying limit type
JackHamer09 Nov 13, 2024
c008cc0
fix: use unlimited default limit for calls constraints
JackHamer09 Nov 13, 2024
78d30d3
Merge pull request #164 from matter-labs/session-interface-improvements
ly0va Nov 13, 2024
ff882e5
Merge branch 'main' into lyova-offchain-sessions
JackHamer09 Nov 13, 2024
3499fe2
fix: pass custom signature during session transaction estimation
JackHamer09 Nov 13, 2024
580a529
fix: try fix estimation
JackHamer09 Nov 14, 2024
4092f84
Revert "fix: try fix estimation"
JackHamer09 Nov 14, 2024
94faafc
Revert "fix: pass custom signature during session transaction estimat…
JackHamer09 Nov 14, 2024
6e8aac5
Reapply "fix: pass custom signature during session transaction estima…
JackHamer09 Nov 14, 2024
a5f5123
Reapply "fix: try fix estimation"
JackHamer09 Nov 14, 2024
ad58810
Merge branch 'main' into fix-estimation
JackHamer09 Nov 14, 2024
59a4a02
fix: some more updates, getting closer to figure out the issue
JackHamer09 Nov 15, 2024
5403531
fix: estimation
JackHamer09 Nov 15, 2024
bf99429
fix: undo hardocde data and gasPerPubdata
JackHamer09 Nov 15, 2024
710edc3
fix: undo using gas price
JackHamer09 Nov 15, 2024
9311342
Merge branch 'main' of https://github.com/matter-labs/zksync-account-…
JackHamer09 Nov 18, 2024
d22aaf0
Merge branch 'main' into fix-estimation
JackHamer09 Nov 20, 2024
4ae8789
fix: sdk improvements
JackHamer09 Nov 20, 2024
f1d9726
Merge branch 'main' into fix-estimation
JackHamer09 Nov 20, 2024
cece0c8
fix: copy readme from root during deployment
JackHamer09 Nov 20, 2024
ae1a19d
fix: add separate readme for sdk
JackHamer09 Nov 20, 2024
d8c3f76
Merge branch 'main' into fix-estimation
JackHamer09 Nov 20, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion cspell-config/cspell-misc.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ Nuxt
nuxtjs
testid
vueuse
ethereum

// examples/bank-demo
ctap
Expand All @@ -25,4 +26,3 @@ usdc
// examples/nft-quest
Fren
fren
trxn
8 changes: 5 additions & 3 deletions examples/demo-app/pages/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
</template>

<script lang="ts" setup>
import { disconnect, getBalance, watchAccount, sendTransaction, createConfig, connect, reconnect, type GetBalanceReturnType } from "@wagmi/core";
import { disconnect, getBalance, watchAccount, sendTransaction, createConfig, connect, reconnect, waitForTransactionReceipt, type GetBalanceReturnType } from "@wagmi/core";
import { zksyncSsoConnector } from "zksync-sso/connector";
import { zksyncInMemoryNode } from "@wagmi/core/chains";
import { createWalletClient, http, parseEther, type Address } from "viem";
Expand Down Expand Up @@ -142,15 +142,17 @@ const sendTokens = async () => {
errorMessage.value = "";
isSendingEth.value = true;
try {
await sendTransaction(wagmiConfig, {
const transactionHash = await sendTransaction(wagmiConfig, {
to: testTransferTarget,
value: parseEther("0.1"),
gas: 100_000_000n,
});

balance.value = await getBalance(wagmiConfig, {
address: address.value,
});

const receipt = await waitForTransactionReceipt(wagmiConfig, { hash: transactionHash });
if (receipt.status === "reverted") throw new Error("Transaction reverted");
} catch (error) {
// eslint-disable-next-line no-console
console.error("Transaction failed:", error);
Expand Down
17 changes: 2 additions & 15 deletions examples/nft-quest/composables/useMintNft.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { estimateGas, waitForTransactionReceipt, writeContract } from "@wagmi/core";
import { type Address, encodeFunctionData } from "viem";
import { waitForTransactionReceipt, writeContract } from "@wagmi/core";
import type { Address } from "viem";
import { getGeneralPaymasterInput } from "viem/zksync";

export const useMintNft = async (_address: MaybeRef<Address>) => {
Expand All @@ -10,24 +10,11 @@ export const useMintNft = async (_address: MaybeRef<Address>) => {
const { wagmiConfig } = storeToRefs(useConnectorStore());

const mintingForAddress = address.value;
const data = encodeFunctionData({
abi: nftAbi,
functionName: "mint",
args: [address.value],
});

const estimatedGas = await estimateGas(wagmiConfig.value, {
to: runtimeConfig.public.contracts.nft as Address,
chainId: runtimeConfig.public.chain.id,
data,
});

const transactionHash = await writeContract(wagmiConfig.value, {
address: runtimeConfig.public.contracts.nft as Address,
abi: nftAbi,
functionName: "mint",
args: [mintingForAddress],
gas: estimatedGas + (estimatedGas / 100n * 25n), // gas may be underestimated
paymaster: runtimeConfig.public.contracts.paymaster as Address,
paymasterInput: getGeneralPaymasterInput({ innerInput: "0x" }),
});
Expand Down
10 changes: 10 additions & 0 deletions examples/nft-quest/nuxt.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,4 +102,14 @@ export default defineNuxtConfig({
},
},
},

vite: {
css: {
preprocessorOptions: {
scss: {
api: "modern", // Fix warning: "The legacy JS API is deprecated and will be removed in Dart Sass 2.0.0"
},
},
},
},
});
10 changes: 10 additions & 0 deletions packages/auth-server/nuxt.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,4 +57,14 @@ export default defineNuxtConfig({
chainId: parseInt(process.env.NUXT_PUBLIC_DEFAULT_CHAIN_ID || "") || zksyncInMemoryNode.id,
},
},

vite: {
css: {
preprocessorOptions: {
scss: {
api: "modern", // Fix warning: "The legacy JS API is deprecated and will be removed in Dart Sass 2.0.0"
},
},
},
},
});
3 changes: 0 additions & 3 deletions packages/contracts/test/PasskeyModule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -220,9 +220,6 @@ async function rawVerify(
const hashedData = await toHash(concat([authDataBuffer, clientDataHash]));
const rs = unwrapEC2Signature(toBuffer(b64SignedChallange));
const publicKeys = await getPublicKey(publicKeyEs256Bytes);
/* console.log("externalSignature", ethers.hexlify(hashedData));
console.log("rs", ethers.hexlify(rs[0]), ethers.hexlify(rs[1]));
console.log("pubkey xy", publicKeys); */
return await passkeyValidator.rawVerify(hashedData, rs, publicKeys);
}

Expand Down
1 change: 0 additions & 1 deletion packages/contracts/test/SessionKeyTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,6 @@ describe("SessionKeyModule tests", function () {
await tester.sendTxSuccess({
to: sessionTarget,
value: parseEther("0.01"),
gasLimit: 10_000_000n,
});
expect(await provider.getBalance(sessionTarget))
.to.equal(parseEther("0.01"), "session target should have received the funds");
Expand Down
3 changes: 2 additions & 1 deletion packages/sdk/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ dist

node_modules
tsconfig*.tsbuildinfo
.DS_Store
.DS_Store
JackHamer09 marked this conversation as resolved.
Show resolved Hide resolved
README.md
19 changes: 13 additions & 6 deletions packages/sdk/prepare-package.mjs
Original file line number Diff line number Diff line change
@@ -1,20 +1,17 @@
import { promises as fs } from "fs";
import path from "path";

// Define the path to the package.json
const packageJsonPath = path.resolve("./package.json");
console.log(packageJsonPath);

// Get the version from environment variables
const version = process.env.INPUT_VERSION;
if (!version) {
console.error("Error: INPUT_VERSION is required.");
process.exit(1);
}

const packageJsonPath = path.resolve("./package.json");
const readmePath = path.resolve("../../README.md"); // copy readme into current path
JackHamer09 marked this conversation as resolved.
Show resolved Hide resolved

async function preparePackageJson() {
try {
// Read the existing package.json
const packageJsonData = await fs.readFile(packageJsonPath, "utf8");
const packageJson = JSON.parse(packageJsonData);

Expand All @@ -36,4 +33,14 @@ async function preparePackageJson() {
}
}

async function copyReadme() {
try {
await fs.copyFile(readmePath, path.resolve("./README.md"));
} catch (error) {
console.error("Error copying README.md:", error);
process.exit(1);
}
}

preparePackageJson();
copyReadme();
10 changes: 10 additions & 0 deletions packages/sdk/src/client-auth-server/Signer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ type Account = {
interface SignerInterface {
accounts: Address[];
chain: Chain;
getClient(parameters?: { chainId?: number }): ZksyncSsoSessionClient;
handshake(): Promise<Address[]>;
request<TMethod extends Method>(request: RequestArguments<TMethod>): Promise<ExtractReturnType<TMethod>>;
disconnect: () => Promise<void>;
Expand Down Expand Up @@ -83,6 +84,15 @@ export class Signer implements SignerInterface {
}
}

getClient(parameters?: { chainId?: number }) {
const chainId = parameters?.chainId || this.chain.id;
const chain = this.chains.find((e) => e.id === chainId);
if (!chain) throw new Error(`Chain with id ${chainId} is not supported`);

if (!this.walletClient) throw new Error("Wallet client is not created");
return this.walletClient;
}

private get account(): Account | null {
const account = this._account.get();
if (!account) return null;
Expand Down
4 changes: 4 additions & 0 deletions packages/sdk/src/client-auth-server/WalletProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ export class WalletProvider extends EventEmitter implements ProviderInterface {
return this.signer.accounts.length > 0;
}

public getClient(parameters?: { chainId?: number }) {
return this.signer.getClient(parameters);
}

public async request<M extends Method>(request: RequestArguments<M>): Promise<ExtractReturnType<M>> {
try {
switch (request.method) {
Expand Down
2 changes: 2 additions & 0 deletions packages/sdk/src/client-auth-server/interface.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { EventEmitter } from "eventemitter3";
import type { RpcSchema as RpcSchemaGeneric } from "viem";

import type { ZksyncSsoSessionClient } from "../client/index.js";
import type { ExtractParams, ExtractReturnType, Method, RpcSchema } from "./rpc.js";

export interface RequestArguments<M extends Method<TSchema>, TSchema extends RpcSchemaGeneric = RpcSchema> {
Expand All @@ -26,6 +27,7 @@ interface ProviderConnectInfo {
export interface ProviderInterface extends EventEmitter {
request<M extends Method>(args: RequestArguments<M>): Promise<ExtractReturnType<M>>;
disconnect(): Promise<void>;
getClient(parameters?: { chainId?: number }): Promise<ZksyncSsoSessionClient> | ZksyncSsoSessionClient;
on(event: "connect", listener: (info: ProviderConnectInfo) => void): this;
on(event: "disconnect", listener: (error: ProviderRpcError) => void): this;
on(event: "chainChanged", listener: (chainId: string) => void): this;
Expand Down
149 changes: 149 additions & 0 deletions packages/sdk/src/client/actions/sendEip712Transaction.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
import { type Account, assertRequest, type AssertRequestErrorType, type Chain, type Client, type ExactPartial, type Hash, type PublicActions, type RpcSchema, type SendTransactionRequest, type Transport, type WalletActions } from "viem";
import { parseAccount } from "viem/accounts";
import { prepareTransactionRequest, sendRawTransaction } from "viem/actions";
import { type ChainEIP712, type SendEip712TransactionParameters, type SendEip712TransactionReturnType, type SendTransactionParameters, zksync } from "viem/zksync";

import { InvalidEip712TransactionError, type InvalidEip712TransactionErrorType } from "../utils/assertEip712Transaction.js";
import { isEIP712Transaction } from "../utils/isEip712Transaction.js";

/**
* Creates, signs, and sends a new EIP712 transaction to the network.
*
* @param client - Client to use
* @param parameters - {@link SendEip712TransactionParameters}
* @returns The [Transaction](https://viem.sh/docs/glossary/terms#transaction) hash. {@link SendTransactionReturnType}
*
* @example
* import { createWalletClient, custom } from 'viem'
* import { zksync } from 'viem/chains'
* import { sendEip712Transaction } from 'viem/zksync'
*
* const client = createWalletClient({
* chain: zksync,
* transport: custom(window.ethereum),
* })
* const hash = await sendEip712Transaction(client, {
* account: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e',
* to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
* value: 1000000000000000000n,
* })
*
* @example
* // Account Hoisting
* import { createWalletClient, http } from 'viem'
* import { privateKeyToAccount } from 'viem/accounts'
* import { zksync } from 'viem/chains'
* import { sendEip712Transaction } from 'viem/zksync'
*
* const client = createWalletClient({
* account: privateKeyToAccount('0x…'),
* chain: zksync,
* transport: http(),
* })
*
* const hash = await sendEip712Transaction(client, {
* to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
* value: 1000000000000000000n,
* })
*/
export async function sendEip712Transaction<
chain extends ChainEIP712 | undefined,
account extends Account | undefined,
const request extends SendTransactionRequest<chain, chainOverride>,
chainOverride extends ChainEIP712 | undefined = undefined,
>(
client: Client<Transport, chain, account>,
parameters: SendEip712TransactionParameters<
chain,
account,
chainOverride,
request
>,
): Promise<SendEip712TransactionReturnType> {
const {
account: account_ = client.account,
chain = client.chain,
...rest
} = parameters;

if (!account_)
throw new Error("Account not found.");
const account = parseAccount(account_);

assertEip712Request(parameters);

const request = await getAction(
client,
prepareTransactionRequest,
"prepareTransactionRequest",
)({
account,
chain,
nonceManager: account.nonceManager,
...rest,
} as any);

const serializer = chain?.serializers?.transaction;
const serializedTransaction = (await account.signTransaction!(request, {
serializer,
})) as Hash;

return await getAction(
client,
sendRawTransaction,
"sendRawTransaction",
)({
serializedTransaction,
});
}

/**
* Retrieves and returns an action from the client (if exists), and falls
* back to the tree-shakable action.
*
* Useful for extracting overridden actions from a client (ie. if a consumer
* wants to override the `sendTransaction` implementation).
*/
export function getAction<
transport extends Transport,
chain extends Chain | undefined,
account extends Account | undefined,
rpcSchema extends RpcSchema | undefined,
extended extends { [key: string]: unknown },
client extends Client<transport, chain, account, rpcSchema, extended>,
parameters,
returnType,
>(
client: client,
actionFn: (_: any, parameters: parameters) => returnType,
// cspell:ignore minifiers
// Some minifiers drop `Function.prototype.name`, or replace it with short letters,
// meaning that `actionFn.name` will not always work. For that case, the consumer
// needs to pass the name explicitly.
name: keyof PublicActions | keyof WalletActions | (string & {}),
): (parameters: parameters) => returnType {
const action_implicit = client[actionFn.name];
if (typeof action_implicit === "function")
return action_implicit as (params: parameters) => returnType;

const action_explicit = client[name];
if (typeof action_explicit === "function")
return action_explicit as (params: parameters) => returnType;

return (params) => actionFn(client, params);
}

type AssertEip712RequestParameters = ExactPartial<
SendTransactionParameters<typeof zksync>
>;

/** @internal */
export type AssertEip712RequestErrorType =
| InvalidEip712TransactionErrorType
| AssertRequestErrorType;

export function assertEip712Request(args: AssertEip712RequestParameters) {
if (!isEIP712Transaction(args as any))
throw new InvalidEip712TransactionError();
assertRequest(args as any);
}
Loading
Loading