Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 3 additions & 1 deletion packages/mask/background/services/identity/persona/sign.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { timeout } from '@masknet/kit'
import { Signer } from '@masknet/web3-providers'
import type { ChainId } from '@masknet/web3-shared-evm'
import {
type PersonaIdentifier,
fromBase64URL,
Expand Down Expand Up @@ -43,12 +44,13 @@ export async function signWithPersona(
identifier?: ECKeyIdentifier,
origin?: string,
silent = false,
chainId?: ChainId,
): Promise<string> {
identifier = await getIdentifier(message.data, identifier, origin, silent)

// find the persona with the signer's identifier
const persona = (await queryPersonasWithPrivateKey()).find((x) => x.identifier === identifier)
if (!persona?.privateKey.d) throw new Error('Persona not found')

return Signer.sign(message, Buffer.from(fromBase64URL(persona.privateKey.d)))
return Signer.sign(message, Buffer.from(fromBase64URL(persona.privateKey.d)), chainId)
}
24 changes: 20 additions & 4 deletions packages/mask/background/services/wallet/services/send.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { JsonRpcRequest } from 'web3-types'
import { ECKeyIdentifier, SignType } from '@masknet/shared-base'
import { EVMRequestReadonly, EVMWeb3Readonly } from '@masknet/web3-providers'
import { EVMRequestReadonly, EVMWalletProviders, EVMWeb3Readonly } from '@masknet/web3-providers'
import {
ChainId,
createJsonRpcResponse,
Expand All @@ -25,13 +25,22 @@ export async function send(payload: JsonRpcRequest, options?: TransactionOptions
signableMessage,
signableTransaction,
} = PayloadEditor.fromPayload(payload, options)
const isTransactionSigningMethod =
payload.method === EthereumMethodType.eth_sendTransaction ||
payload.method === EthereumMethodType.MASK_REPLACE_TRANSACTION ||
payload.method === EthereumMethodType.eth_signTransaction
const providerChainId =
options?.providerType && isTransactionSigningMethod ?
EVMWalletProviders[options.providerType].subscription.chainId.getCurrentValue()
: undefined
const requestChainId = providerChainId ?? chainId
const identifier = ECKeyIdentifier.from(options?.identifier).unwrapOr(undefined)
const signTransaction = async (transaction: TransactionSerializable) => {
const message = { type: SignType.Transaction as const, data: transaction }
if (identifier) {
return signWithPersona(message, identifier)
return signWithPersona(message, identifier, undefined, false, providerChainId)
} else {
return signWithWallet(message, owner || from!)
return signWithWallet(message, owner || from!, providerChainId)
}
}
const signMessageOrTypedData = async (type: SignType.Message | SignType.TypedData, message: string) => {
Expand All @@ -47,12 +56,19 @@ export async function send(payload: JsonRpcRequest, options?: TransactionOptions
case EthereumMethodType.eth_sendTransaction:
case EthereumMethodType.MASK_REPLACE_TRANSACTION:
if (!signableTransaction) throw new Error('No transaction to be sent.')
if (
providerChainId !== undefined &&
signableTransaction.chainId !== undefined &&
signableTransaction.chainId !== providerChainId
) {
throw new Error('Chain ID mismatch.')
}

try {
return createJsonRpcResponse(
pid,
await EVMWeb3Readonly.sendSignedTransaction(await signTransaction(signableTransaction), {
chainId,
chainId: requestChainId,
providerURL,
}),
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { api } from '@dimensiondev/mask-wallet-core/proto'
import { Signer } from '@masknet/web3-providers'
import { ImportSource, toHex, type SignMessage, type Wallet } from '@masknet/shared-base'
import { HD_PATH_WITHOUT_INDEX_ETHEREUM } from '@masknet/web3-shared-base'
import type { ChainId } from '@masknet/web3-shared-evm'
import * as Mask from '../maskwallet/index.js'
import * as database from './database/index.js'
import * as password from './password.js'
Expand Down Expand Up @@ -247,8 +248,8 @@ export async function resetAllWallets() {
await database.resetAllWallets()
}

export async function signWithWallet(message: SignMessage, address: string) {
return Signer.sign(message, Buffer.from(toBytes(`0x${await exportPrivateKey(address)}`)))
export async function signWithWallet(message: SignMessage, address: string, chainId?: ChainId) {
return Signer.sign(message, Buffer.from(toBytes(`0x${await exportPrivateKey(address)}`)), chainId)
}

export async function exportMnemonicWords(address: string, unverifiedPassword?: string) {
Expand Down
19 changes: 17 additions & 2 deletions packages/web3-providers/src/Web3/EVM/apis/RequestAPI.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { EthereumMethodType, PayloadEditor, type RequestArguments } from '@masknet/web3-shared-evm'
import { EthereumMethodType, PayloadEditor, type ChainId, type RequestArguments } from '@masknet/web3-shared-evm'
import type { TransactionSerializable } from 'viem'
import { Composer } from './ComposerAPI.js'
import { evm } from '../../../Manager/registry.js'
import { ConnectionOptionsAPI } from './ConnectionOptionsAPI.js'
Expand All @@ -9,6 +10,12 @@ import type { EVMConnectionOptions } from '../types/index.js'
import { createWeb3FromProvider } from '../../../helpers/createWeb3FromProvider.js'
import { createWeb3ProviderFromRequest } from '../../../helpers/createWeb3ProviderFromRequest.js'

function assertTransactionChainId(transaction: TransactionSerializable | undefined, chainId: ChainId) {
if (!transaction) return
if (transaction.chainId !== undefined && transaction.chainId !== chainId)
throw new Error('Transaction chain id does not match current chain id.')
}

export class EVMRequestAPI extends EVMRequestReadonlyAPI {
static override Default = new EVMRequestAPI()
private Request = new EVMRequestReadonlyAPI(this.options)
Expand Down Expand Up @@ -46,7 +53,15 @@ export class EVMRequestAPI extends EVMRequestReadonlyAPI {
context.write(await this.Provider?.disconnect(options.providerType))
break
default: {
if (!PayloadEditor.fromPayload(context.request).readonly) {
const payloadEditor = PayloadEditor.fromPayload(context.request)
if (!payloadEditor.readonly) {
assertTransactionChainId(
payloadEditor.signableTransaction,
EVMWalletProviders[
options.providerType
].subscription.chainId.getCurrentValue(),
)

const web3Provider = EVMWalletProviders[
options.providerType
].createWeb3Provider({
Expand Down
10 changes: 5 additions & 5 deletions packages/web3-providers/src/Web3/EVM/apis/SignerAPI.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import defer * as _metamask_eth_sig_util from '@metamask/eth-sig-util'
import { signTransaction } from '@masknet/web3-shared-evm'
import { type ChainId, signTransaction } from '@masknet/web3-shared-evm'
import { type SignMessage, SignType, toHex } from '@masknet/shared-base'
import { unreachable } from '@masknet/kit'

export class Signer {
static async sign({ type, data }: SignMessage, key: Buffer<ArrayBuffer>): Promise<string> {
static async sign({ type, data }: SignMessage, key: Buffer<ArrayBuffer>, chainId?: ChainId): Promise<string> {
switch (type) {
case SignType.Message:
return _metamask_eth_sig_util.personalSign({
Expand All @@ -20,10 +20,10 @@ export class Signer {
case SignType.Transaction:
const transaction = data

const chainId = transaction.chainId
if (!chainId) throw new Error('Invalid chain id.')
const transactionChainId = transaction.chainId
if (!transactionChainId) throw new Error('Invalid chain id.')

const rawTransaction = await signTransaction(transaction, toHex(key))
const rawTransaction = await signTransaction(transaction, toHex(key), chainId)
if (!rawTransaction) throw new Error('Failed to sign transaction.')
return rawTransaction

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ export class Popups implements Middleware<ConnectionContext> {
arguments: context.requestArguments,
options: {
silent: context.silent,
providerType: context.providerType,
providerURL: context.providerURL,
gasOptionType: context.gasOptionType,
},
Expand Down
2 changes: 1 addition & 1 deletion packages/web3-providers/src/entry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export { RedPacket } from './RedPacket/index.js'
export { SnapshotSearch } from './Snapshot/index.js'
export { Snapshot } from './Snapshot/index.js'

export { MaskWalletProviderInstance as MaskWalletProvider } from './Web3/EVM/providers/index.js'
export { EVMWalletProviders, MaskWalletProviderInstance as MaskWalletProvider } from './Web3/EVM/providers/index.js'

// Web3
export { getConnection } from './Web3/Router/apis/getConnection.js'
Expand Down
4 changes: 3 additions & 1 deletion packages/web3-shared/evm/src/helpers/signTransaction.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { signTransaction as viem_signTransaction } from 'viem/accounts'
import type { Hex, TransactionSerializable } from 'viem'

export function signTransaction(transaction: TransactionSerializable, privateKey: Hex) {
export function signTransaction(transaction: TransactionSerializable, privateKey: Hex, chainId?: number) {
if (chainId !== undefined && transaction.chainId !== chainId)
throw new Error('Transaction chain id does not match current chain id.')
return viem_signTransaction({ privateKey, transaction })
}
2 changes: 2 additions & 0 deletions packages/web3-shared/evm/src/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,7 @@ export interface RequestOptions {
silent?: boolean
owner?: string
identifier?: string
providerType?: ProviderType
providerURL?: string
gasOptionType?: GasOptionType
maxFeePerGas?: string
Expand Down Expand Up @@ -428,6 +429,7 @@ export interface TransactionOptions {
chainId?: ChainId
owner?: string
identifier?: string
providerType?: ProviderType
providerURL?: string

// popups control
Expand Down
Loading