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

Increase wallet provider method coverage #425

Merged
merged 2 commits into from
Dec 16, 2024
Merged
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
111 changes: 90 additions & 21 deletions background/services/internal-quai-provider/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ import { normalizeHexAddress } from "../../utils/addresses"
import TransactionService from "../transactions"
import { QuaiTransactionRequestWithAnnotation } from "../transactions/types"
import { ValidatedAddEthereumChainParameter } from "../provider-bridge/utils"
import { ProviderBridgeDatabase } from "../provider-bridge/db"

export type SwitchEthereumChainParameter = {
chainId: string
Expand Down Expand Up @@ -119,15 +120,17 @@ export default class InternalQuaiProviderService extends BaseService<Events> {
await initializeInternalQuaiDatabase(),
await chainService,
await transactionService,
await preferenceService
await preferenceService,
new ProviderBridgeDatabase()
)
}

private constructor(
private db: InternalQuaiProviderDatabase,
private chainService: ChainService,
private transactionsService: TransactionService,
private preferenceService: PreferenceService
private preferenceService: PreferenceService,
private providerBridgeDb: ProviderBridgeDatabase
) {
super()

Expand Down Expand Up @@ -279,13 +282,13 @@ export default class InternalQuaiProviderService extends BaseService<Events> {
)

case "quai_sendTransaction":
return this.sendTransaction(
params[0] as QuaiTransactionRequestWithAnnotation,
origin
).then((transactionResponse) => transactionResponse.hash)
case "eth_sendTransaction":
throw new Error(
"eth_sendTransaction is not supported. You must use quai_sendTransaction instead."
const request = params[0] as QuaiTransactionRequestWithAnnotation & {
maxFeePerGas?: string
maxPriorityFeePerGas?: string
}
return this.sendTransaction(request, origin).then(
(transactionResponse) => transactionResponse.hash
)

case "quai_sendRawTransaction":
Expand All @@ -299,10 +302,13 @@ export default class InternalQuaiProviderService extends BaseService<Events> {
)

case "quai_gasPrice":
case "eth_gasPrice":
return this.chainService.jsonRpcProvider
.getFeeData()
.then((feeData) => feeData.gasPrice)
case "quai_minerTip":
case "eth_minerTip":
case "eth_maxPriorityFeePerGas":
return this.chainService.jsonRpcProvider
.getFeeData()
.then((feeData) => feeData.minerTip)
Expand Down Expand Up @@ -435,8 +441,32 @@ export default class InternalQuaiProviderService extends BaseService<Events> {
return this.transactionsService.send(method, params)

// unsupported methods
case "net_peerCount":

case "wallet_requestPermissions":
case "wallet_getPermissions": {
const { address } = await this.preferenceService.getSelectedAccount()
const network = await this.getCurrentOrDefaultNetworkForOrigin(origin)

const permission = await this.providerBridgeDb.checkPermission(
origin,
address,
network.chainID
)

if (!permission) {
return []
}

// Format according to EIP-2255
return [
{
invoker: origin,
parentCapability: "eth_accounts",
caveats: [],
},
]
}
case "net_peerCount":
case "wallet_accountsChanged":
case "wallet_registerOnboarding":
default:
Expand Down Expand Up @@ -467,7 +497,11 @@ export default class InternalQuaiProviderService extends BaseService<Events> {
}

private async sendTransaction(
transactionRequest: QuaiTransactionRequestWithAnnotation,
transactionRequest: QuaiTransactionRequestWithAnnotation & {
gas?: string
maxFeePerGas?: string
maxPriorityFeePerGas?: string
},
origin: string
): Promise<QuaiTransactionResponse> {
const annotation =
Expand All @@ -492,19 +526,54 @@ export default class InternalQuaiProviderService extends BaseService<Events> {
await blockService.pollBlockPricesForNetwork({ network })
await blockService.pollLatestBlock(network)

const payload: QuaiTransactionRequestWithAnnotation & {
gas?: string
maxFeePerGas?: string
maxPriorityFeePerGas?: string
} = {
to,
from,
type: transactionRequest.type || 2,
chainId: network.chainID,
data: transactionRequest.data,
value: transactionRequest.value,
network,
annotation,
}

// Quai specific fields
if ("gasLimit" in transactionRequest) {
payload.gasLimit = transactionRequest.gasLimit
}

if ("gasPrice" in transactionRequest) {
payload.gasPrice = transactionRequest.gasPrice
}

if ("minerTip" in transactionRequest) {
payload.minerTip = transactionRequest.minerTip
}

// // Ethereum specific fields
if ("gas" in transactionRequest) {
payload.gasLimit = transactionRequest.gas
}

if ("maxFeePerGas" in transactionRequest) {
payload.gasPrice = transactionRequest.maxFeePerGas
}

if ("maxPriorityFeePerGas" in transactionRequest) {
payload.minerTip = transactionRequest.maxPriorityFeePerGas
}

if (typeof transactionRequest.value === "undefined") {
delete payload.value
}

return new Promise<QuaiTransactionResponse>((resolve, reject) => {
this.emitter.emit("transactionSendRequest", {
payload: {
to,
from,
type: transactionRequest.type,
chainId: network.chainID,
data: transactionRequest.data,
value: transactionRequest.value,
gasLimit: transactionRequest.gasLimit,
network,
annotation,
},
payload,
resolver: resolve,
rejecter: reject,
})
Expand Down
1 change: 1 addition & 0 deletions background/services/provider-bridge/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -568,6 +568,7 @@ export default class ProviderBridgeService extends BaseService<Events> {
showExtensionPopup(AllowedQueryParamPage.personalSignData)
)
case "quai_sendTransaction":
case "eth_sendTransaction":
// TODO check this checkPermissionSignTransaction function in future
checkPermissionSignTransaction(
(params[0] as QuaiTransactionRequest).chainId,
Expand Down
74 changes: 40 additions & 34 deletions src/window-provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ const PELAGUS_OBJECT_PROPERTY = "pelagus"
const ETHEREUM_OBJECT_PROPERTY = "ethereum"
const WALLET_ROUTER_OBJECT_PROPERTY = "walletRouter"

const DETECT_PROVIDER_INITIALIZATION_EVENT = "quai#initialized"
const DETECT_PROVIDER_INITIALIZATION_EVENT = "pelagus#initialized"

const pelagusWindowProvider: PelagusWindowProvider = new PelagusWindowProvider({
postMessage: (data: WindowRequestEvent) =>
Expand Down Expand Up @@ -78,43 +78,49 @@ let cachedWindowEthereumProxy: WindowEthereum
// default wallet is changed we are switching the underlying provider.
let cachedCurrentProvider: WalletProvider

Object.defineProperty(window, ETHEREUM_OBJECT_PROPERTY, {
get() {
if (!window.walletRouter) {
throw new Error(
`window.${WALLET_ROUTER_OBJECT_PROPERTY} is expected to be set to change the injected provider on window.${ETHEREUM_OBJECT_PROPERTY}.`
if (!window.ethereum) {
Object.defineProperty(window, ETHEREUM_OBJECT_PROPERTY, {
get() {
if (!window.walletRouter) {
throw new Error(
`window.${WALLET_ROUTER_OBJECT_PROPERTY} is expected to be set to change the injected provider on window.${ETHEREUM_OBJECT_PROPERTY}.`
)
}

if (
cachedWindowEthereumProxy &&
cachedCurrentProvider === window.walletRouter.currentProvider
)
}
return cachedWindowEthereumProxy

if (
cachedWindowEthereumProxy &&
cachedCurrentProvider === window.walletRouter.currentProvider
)
return cachedWindowEthereumProxy
cachedWindowEthereumProxy = new Proxy(
window.walletRouter.currentProvider,
{
get(target, prop, receiver) {
if (
window.walletRouter &&
!(prop in window.walletRouter.currentProvider) &&
prop in window.walletRouter
) {
// let's publish the api of `window.walletRoute` also on `window.ethereum` for better discoverability
// @ts-expect-error ts accepts symbols as index only from 4.4
return window.walletRouter[prop]
}

cachedWindowEthereumProxy = new Proxy(window.walletRouter.currentProvider, {
get(target, prop, receiver) {
if (
window.walletRouter &&
!(prop in window.walletRouter.currentProvider) &&
prop in window.walletRouter
) {
// let's publish the api of `window.walletRoute` also on `window.ethereum` for better discoverability
// @ts-expect-error ts accepts symbols as index only from 4.4
return window.walletRouter[prop]
return Reflect.get(target, prop, receiver)
},
}
)
cachedCurrentProvider = window.walletRouter.currentProvider

return Reflect.get(target, prop, receiver)
},
})
cachedCurrentProvider = window.walletRouter.currentProvider

return cachedWindowEthereumProxy
},
set(newProvider) {
window.walletRouter?.addProvider(newProvider)
},
configurable: true,
})
return cachedWindowEthereumProxy
},
set(newProvider) {
window.walletRouter?.addProvider(newProvider)
},
writable: true,
configurable: true,
})
}

window.dispatchEvent(new Event(DETECT_PROVIDER_INITIALIZATION_EVENT))