Skip to content
This repository has been archived by the owner on Nov 5, 2023. It is now read-only.

Dapp interaction with eth_sendTransaction rpc call #183

Merged
merged 2 commits into from
Apr 4, 2022
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
11 changes: 10 additions & 1 deletion extension/source/Controllers/Keyring/KeyringController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,12 @@ export default class KeyringController
return wallet.sign(tx);
}

async getNonce(address: string) {
const privKey = this._getPrivateKeyFor(address);
const wallet = await this._getBLSWallet(privKey);
return wallet.Nonce();
}

async _createAccountAndUpdate(privateKey: string): Promise<string> {
const address = await this._getContractWalletAddress(privateKey);

Expand All @@ -110,7 +116,10 @@ export default class KeyringController
}

private _getPrivateKeyFor(address: string): string {
const keyPair = this.state.wallets.find((x) => x.address === address);
const checksummedAddress = ethers.utils.getAddress(address);
const keyPair = this.state.wallets.find(
(x) => x.address === checksummedAddress,
);
if (!keyPair) throw new Error('key does not exist');
return keyPair.privateKey;
}
Expand Down
30 changes: 30 additions & 0 deletions extension/source/Controllers/Network/createEthMiddleware.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,44 @@ import {
JRPCRequest,
JRPCResponse,
} from '@toruslabs/openlogin-jrpc';
import { BigNumberish, BytesLike } from 'ethers';
import { PROVIDER_JRPC_METHODS } from '../../common/constants';

type TransactionFailure =
| { type: 'invalid-format'; description: string }
| { type: 'invalid-signature'; description: string }
| { type: 'duplicate-nonce'; description: string }
| { type: 'insufficient-reward'; description: string }
| { type: 'unpredictable-gas-limit'; description: string }
| { type: 'invalid-creation'; description: string };

export type SendTransactionParams = {
from: string;
to: string;
gas?: BigNumberish;
gasPrice?: BigNumberish;
value: BigNumberish;
data: BytesLike;
};

export interface IProviderHandlers {
version: string;
getAccounts: (req: JRPCRequest<unknown>) => Promise<string[]>;
requestAccounts: (req: JRPCRequest<unknown>) => Promise<string[]>;
getProviderState: (
req: JRPCRequest<unknown>,
) => Promise<{ accounts: string[]; chainId: string; isUnlocked: boolean }>;
submitBatch: (
req: JRPCRequest<SendTransactionParams>,
) => Promise<TransactionFailure[]>;
}

export function createWalletMiddleware({
version,
getAccounts,
requestAccounts,
getProviderState,
submitBatch,
}: IProviderHandlers): JRPCMiddleware<string, unknown> {
if (!getAccounts) {
throw new Error('opts.getAccounts is required');
Expand Down Expand Up @@ -63,6 +85,13 @@ export function createWalletMiddleware({
res.result = await getProviderState(req);
}

async function submitTransaction(
req: JRPCRequest<SendTransactionParams>,
res: JRPCResponse<unknown>,
): Promise<void> {
res.result = await submitBatch(req);
}

return createScaffoldMiddleware({
web3_clientVersion: `Quill/v${version}`,
// account lookups
Expand All @@ -72,5 +101,6 @@ export function createWalletMiddleware({
[PROVIDER_JRPC_METHODS.GET_PROVIDER_STATE]: createAsyncMiddleware(
getProviderStateFromController,
),
eth_sendTransaction: createAsyncMiddleware<any, any>(submitTransaction),
});
}
30 changes: 29 additions & 1 deletion extension/source/Controllers/QuillController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import type { Duplex } from 'readable-stream';

import { Runtime } from 'webextension-polyfill';
import { BigNumber } from 'ethers';
import { Aggregator } from 'bls-wallet-clients';
import {
createRandomId,
getDefaultProviderConfig,
Expand All @@ -29,7 +30,10 @@ import {
providerAsMiddleware,
SafeEventEmitterProvider,
} from './Network/INetworkController';
import { IProviderHandlers } from './Network/createEthMiddleware';
import {
IProviderHandlers,
SendTransactionParams,
} from './Network/createEthMiddleware';
import {
AddressPreferences,
PreferencesConfig,
Expand All @@ -53,6 +57,7 @@ import { createOriginMiddleware } from './Network/createOriginMiddleware';
import createTabIdMiddleware from './rpcHelpers/TabIdMiddleware';
import createMetaRPCHandler from './streamHelpers/MetaRPCHandler';
import { PROVIDER_NOTIFICATIONS } from '../common/constants';
import { AGGREGATOR_URL } from '../env';

export const DEFAULT_CONFIG = {
CurrencyControllerConfig: {
Expand Down Expand Up @@ -514,6 +519,29 @@ export default class QuillController extends BaseController<
isUnlocked: !!this.selectedAddress,
};
},

submitBatch: async (req: any) => {
const params: SendTransactionParams = req.params[0];

const nonce = await this.keyringController.getNonce(params.from);
const tx = {
nonce: nonce.toString(),
actions: [
{
ethValue: params.value.toString(),
contractAddress: params.to,
encodedFunction: params.data,
},
],
};

const bundle = await this.keyringController.signTransactions(
params.from,
tx,
);
const agg = new Aggregator(AGGREGATOR_URL);
return agg.add(bundle);
},
};
const providerProxy =
this.networkController.initializeProvider(providerHandlers);
Expand Down