Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/main'
Browse files Browse the repository at this point in the history
  • Loading branch information
joaquim-verges committed Nov 13, 2024
2 parents 68fa560 + 3eb97c8 commit 7a6228e
Show file tree
Hide file tree
Showing 34 changed files with 1,462 additions and 272 deletions.
2 changes: 1 addition & 1 deletion .prettierrc
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@
"trailingComma": "all",
"singleQuote": true,
"printWidth": 80
}
}
8 changes: 8 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"editor.formatOnPaste": true,
"editor.formatOnSave": true,
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "always"
}
}
14 changes: 7 additions & 7 deletions eslint.config.mjs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import eslint from '@eslint/js';
import eslintPluginPrettier from 'eslint-plugin-prettier';
import eslintPluginSimpleImportSort from 'eslint-plugin-simple-import-sort';
import { createRequire } from "module"
import { createRequire } from 'module';
import tseslint from 'typescript-eslint';
const require = createRequire(import.meta.url)
const requireExtensions = require("eslint-plugin-require-extensions")
const require = createRequire(import.meta.url);
const requireExtensions = require('eslint-plugin-require-extensions');

export default tseslint.config(
eslint.configs.recommended,
Expand All @@ -13,8 +14,10 @@ export default tseslint.config(
plugins: {
'simple-import-sort': eslintPluginSimpleImportSort,
'require-extensions': requireExtensions,
prettier: eslintPluginPrettier,
},
rules: {
'prettier/prettier': 'error',
'require-extensions/require-extensions': 'error',
'@typescript-eslint/no-explicit-any': 'warn',
'@typescript-eslint/no-non-null-assertion': 'warn',
Expand All @@ -33,9 +36,6 @@ export default tseslint.config(
},
},
{
ignores: [
'node_modules/**',
'packages/**/dist/**'
],
ignores: ['node_modules/**', 'packages/**/dist/**'],
},
);
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
"@arethetypeswrong/cli": "^0.16.4",
"@types/eslint__js": "^8.42.3",
"eslint": "^9.10.0",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-prettier": "^5.2.1",
"eslint-plugin-require-extensions": "^0.1.3",
"eslint-plugin-simple-import-sort": "^12.1.1",
"husky": "^9.1.6",
Expand Down
2 changes: 1 addition & 1 deletion packages/agw-client/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@abstract-foundation/agw-client",
"description": "Abstract Global Wallet Client SDK",
"version": "0.0.1-beta.13",
"version": "0.0.1-beta.19",
"license": "MIT",
"repository": {
"type": "git",
Expand Down
35 changes: 22 additions & 13 deletions packages/agw-client/src/actions/prepareTransaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,11 @@ export type PrepareTransactionRequestRequest<
* @default ['blobVersionedHashes', 'chainId', 'fees', 'gas', 'nonce', 'type']
*/
parameters?: readonly PrepareTransactionRequestParameterType[] | undefined;

/**
* Whether the transaction is the first transaction of the account.
*/
isInitialTransaction?: boolean;
};

export type PrepareTransactionRequestParameters<
Expand All @@ -141,7 +146,9 @@ export type PrepareTransactionRequestParameters<
> = request &
GetAccountParameter<account, accountOverride, false> &
GetChainParameter<chain, chainOverride> &
GetTransactionRequestKzgParameter<request> & { chainId?: number | undefined };
GetTransactionRequestKzgParameter<request> & {
chainId?: number | undefined;
};

export type PrepareTransactionRequestReturnType<
chain extends ChainEIP712 | undefined = ChainEIP712 | undefined,
Expand Down Expand Up @@ -244,11 +251,14 @@ export type PrepareTransactionRequestErrorType =
* })
*/
export async function prepareTransactionRequest<
const request extends PrepareTransactionRequestRequest<chain, chainOverride>,
chain extends ChainEIP712 | undefined = ChainEIP712 | undefined,
account extends Account | undefined = Account | undefined,
accountOverride extends Account | Address | undefined = undefined,
chainOverride extends ChainEIP712 | undefined = ChainEIP712 | undefined,
const request extends PrepareTransactionRequestRequest<
chain,
chainOverride
> = PrepareTransactionRequestRequest<chain, chainOverride>,
>(
client: Client<Transport, ChainEIP712, Account>,
signerClient: WalletClient<Transport, ChainEIP712, Account>,
Expand All @@ -260,19 +270,17 @@ export async function prepareTransactionRequest<
accountOverride,
request
>,
isInitialTransaction: boolean,
): Promise<
PrepareTransactionRequestReturnType<
): Promise<PrepareTransactionRequestReturnType> {
const {
isInitialTransaction,
chain,
account,
chainOverride,
accountOverride,
request
>
> {
const { chain, gas, nonce, parameters = defaultParameters } = args;
gas,
nonce,
parameters = defaultParameters,
} = args;

const initiatorAccount = parseAccount(
isInitialTransaction ? signerClient.account : client.account,
(isInitialTransaction ?? false) ? signerClient.account : client.account,
);
const request = {
...args,
Expand Down Expand Up @@ -369,6 +377,7 @@ export async function prepareTransactionRequest<
assertRequest(request as AssertRequestParameters);

delete request.parameters;
delete request.isInitialTransaction;

return request as any;
}
35 changes: 34 additions & 1 deletion packages/agw-client/src/actions/sendPrivyTransaction.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import {
type Account,
type Client,
type Hex,
type SendTransactionRequest,
type SignMessageParameters,
type SignTypedDataParameters,
toHex,
type Transport,
} from 'viem';
Expand Down Expand Up @@ -35,6 +38,36 @@ export async function sendPrivyTransaction<
// eslint-disable-next-line @typescript-eslint/no-explicit-any
} as any,
{ retryCount: 0 },
)) as any;
)) as SignEip712TransactionReturnType;
return result;
}

export async function sendPrivySignMessage(
client: Client<Transport, ChainEIP712, Account>,
parameters: Omit<SignMessageParameters, 'account'>,
): Promise<Hex> {
const result = (await client.request(
{
method: 'privy_signSmartWalletMessage',
params: [parameters.message],
// eslint-disable-next-line @typescript-eslint/no-explicit-any
} as any,
{ retryCount: 0 },
)) as Hex;
return result;
}

export async function sendPrivySignTypedData(
client: Client<Transport, ChainEIP712, Account>,
parameters: Omit<SignTypedDataParameters, 'account' | 'privateKey'>,
): Promise<Hex> {
const result = (await client.request(
{
method: 'privy_signSmartWalletTypedData',
params: [client.account.address, parameters],
// eslint-disable-next-line @typescript-eslint/no-explicit-any
} as any,
{ retryCount: 0 },
)) as Hex;
return result;
}
2 changes: 1 addition & 1 deletion packages/agw-client/src/actions/sendTransactionInternal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,8 @@ export async function sendTransactionInternal<
{
...parameters,
parameters: ['gas', 'nonce', 'fees'],
isInitialTransaction,
} as any,
isInitialTransaction,
);

let chainId: number | undefined;
Expand Down
40 changes: 40 additions & 0 deletions packages/agw-client/src/actions/signMessage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import {
type Account,
bytesToString,
type Client,
fromHex,
hashMessage,
type Hex,
type SignMessageParameters,
type Transport,
type WalletClient,
} from 'viem';
import type { ChainEIP712 } from 'viem/chains';

import { getAgwTypedSignature } from '../getAgwTypedSignature.js';
import { sendPrivySignMessage } from './sendPrivyTransaction.js';

export async function signMessage(
client: Client<Transport, ChainEIP712, Account>,
signerClient: WalletClient<Transport, ChainEIP712, Account>,
parameters: Omit<SignMessageParameters, 'account'>,
isPrivyCrossApp = false,
): Promise<Hex> {
if (isPrivyCrossApp) {
// We handle {message: {raw}} here because the message is expected to be a string
if (typeof parameters.message === 'object') {
if (parameters.message.raw instanceof Uint8Array) {
parameters.message = bytesToString(parameters.message.raw);
} else {
parameters.message = fromHex(parameters.message.raw, 'string');
}
}
return await sendPrivySignMessage(client, parameters);
}

return await getAgwTypedSignature({
client,
signer: signerClient,
messageHash: hashMessage(parameters.message),
});
}
14 changes: 11 additions & 3 deletions packages/agw-client/src/actions/signTransaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {
type AssertEip712RequestParameters,
} from '../eip712.js';
import { AccountNotFoundError } from '../errors/account.js';
import { transformHexValues } from '../utils.js';

const ALLOWED_CHAINS: number[] = [abstractTestnet.id];

Expand All @@ -42,9 +43,16 @@ export async function signTransaction<
} = args;
// TODO: open up typing to allow for eip712 transactions
transaction.type = 'eip712' as any;
transaction.value = transaction.value
? BigInt(transaction.value)
: (0n as any);
transformHexValues(transaction, [
'value',
'nonce',
'maxFeePerGas',
'maxPriorityFeePerGas',
'gas',
'value',
'chainId',
'gasPerPubdata',
]);

if (!account_)
throw new AccountNotFoundError({
Expand Down
50 changes: 50 additions & 0 deletions packages/agw-client/src/actions/signTypedData.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import {
type Account,
type Client,
encodeAbiParameters,
hashTypedData,
type Hex,
parseAbiParameters,
type Transport,
type WalletClient,
} from 'viem';
import type { SignTypedDataParameters } from 'viem/accounts';
import { signTypedData as viemSignTypedData } from 'viem/actions';
import type { ChainEIP712 } from 'viem/chains';

import { VALIDATOR_ADDRESS } from '../constants.js';
import { isEIP712Transaction } from '../eip712.js';
import { getAgwTypedSignature } from '../getAgwTypedSignature.js';
import { sendPrivySignTypedData } from './sendPrivyTransaction.js';

export async function signTypedData(
client: Client<Transport, ChainEIP712, Account>,
signerClient: WalletClient<Transport, ChainEIP712, Account>,
parameters: Omit<SignTypedDataParameters, 'account' | 'privateKey'>,
isPrivyCrossApp = false,
): Promise<Hex> {
if (isPrivyCrossApp) return await sendPrivySignTypedData(client, parameters);

// if the typed data is already a zkSync EIP712 transaction, don't try to transform it
// to an AGW typed signature, just pass it through to the signer.
if (
parameters.message &&
parameters.domain?.name === 'zkSync' &&
isEIP712Transaction(parameters.message)
) {
const rawSignature = await viemSignTypedData(signerClient, parameters);
// Match the expect signature format of the AGW smart account so the result can be
// directly used in eth_sendRawTransaction as the customSignature field
const signature = encodeAbiParameters(
parseAbiParameters(['bytes', 'address', 'bytes[]']),
[rawSignature, VALIDATOR_ADDRESS, []],
);
return signature;
}

return await getAgwTypedSignature({
client,
signer: signerClient,
messageHash: hashTypedData(parameters),
});
}
Loading

0 comments on commit 7a6228e

Please sign in to comment.