From 0b4d00c0cb44348bd41eb5aa8e2f5c1ba11b6e5d Mon Sep 17 00:00:00 2001 From: tomasklim Date: Wed, 9 Oct 2024 15:22:30 +0200 Subject: [PATCH] feat(connect): implement ethereum rpc call --- .../src/api/ethereum/api/ethereumCall.ts | 63 +++++++++++++++++++ .../connect/src/api/ethereum/api/index.ts | 1 + packages/connect/src/backend/Blockchain.ts | 4 ++ packages/connect/src/factory.ts | 2 + .../connect/src/types/api/ethereum/index.ts | 9 +++ .../connect/src/types/api/ethereumCall.ts | 6 ++ packages/connect/src/types/api/index.ts | 3 + 7 files changed, 88 insertions(+) create mode 100644 packages/connect/src/api/ethereum/api/ethereumCall.ts create mode 100644 packages/connect/src/types/api/ethereumCall.ts diff --git a/packages/connect/src/api/ethereum/api/ethereumCall.ts b/packages/connect/src/api/ethereum/api/ethereumCall.ts new file mode 100644 index 000000000000..c3c212ce2ad1 --- /dev/null +++ b/packages/connect/src/api/ethereum/api/ethereumCall.ts @@ -0,0 +1,63 @@ +import { AbstractMethod } from '../../../core/AbstractMethod'; +import { validateParams } from '../../common/paramsValidator'; +import { ERRORS } from '../../../constants'; +import { CoinInfo, EthereumCall as EthereumCallSchema } from '../../../types'; +import { initBlockchain, isBackendSupported } from '../../../backend/BlockchainLink'; +import { getCoinInfo } from '../../../data/coinInfo'; + +type Params = { + coinInfo: CoinInfo; + identity?: string; + request: EthereumCallSchema; +}; + +export default class EthereumCall extends AbstractMethod<'ethereumCall', Params> { + init() { + this.useDevice = false; + this.useUi = false; + + const { payload } = this; + + // validate incoming parameters + validateParams(payload, [ + { name: 'coin', type: 'string', required: true }, + { name: 'identity', type: 'string' }, + { name: 'from', type: 'string' }, + { name: 'to', type: 'string', required: true }, + { name: 'data', type: 'string', required: true }, + ]); + + const coinInfo = getCoinInfo(payload.coin); + + if (!coinInfo) { + throw ERRORS.TypedError('Method_UnknownCoin'); + } + // validate backend + isBackendSupported(coinInfo); + + this.params = { + coinInfo, + identity: payload.identity, + request: { + from: payload.from, + to: payload.to, + data: payload.data, + }, + }; + } + + get info() { + return 'Ethereum call'; + } + + async run() { + const backend = await initBlockchain( + this.params.coinInfo, + postMessage, + this.params.identity, + ); + const response = await backend.ethereumCall(this.params.request); + + return response; + } +} diff --git a/packages/connect/src/api/ethereum/api/index.ts b/packages/connect/src/api/ethereum/api/index.ts index dd05db5a77ec..6dcf5963f719 100644 --- a/packages/connect/src/api/ethereum/api/index.ts +++ b/packages/connect/src/api/ethereum/api/index.ts @@ -4,3 +4,4 @@ export { default as ethereumSignMessage } from './ethereumSignMessage'; export { default as ethereumSignTransaction } from './ethereumSignTransaction'; export { default as ethereumSignTypedData } from './ethereumSignTypedData'; export { default as ethereumVerifyMessage } from './ethereumVerifyMessage'; +export { default as ethereumCall } from './ethereumCall'; diff --git a/packages/connect/src/backend/Blockchain.ts b/packages/connect/src/backend/Blockchain.ts index a9a228110836..bfd35bf623a4 100644 --- a/packages/connect/src/backend/Blockchain.ts +++ b/packages/connect/src/backend/Blockchain.ts @@ -217,6 +217,10 @@ export class Blockchain { return this.link.getAccountUtxo(descriptor); } + ethereumCall(params: BlockchainLinkParams<'ethereumCall'>) { + return this.link.ethereumCall(params); + } + async estimateFee(request: Parameters[0]) { const { blocks } = request; // cache should be used if there is no specific data (ethereum case) and requested blocks are already cached/downloaded diff --git a/packages/connect/src/factory.ts b/packages/connect/src/factory.ts index 02c8f550a829..d48cd335f5f4 100644 --- a/packages/connect/src/factory.ts +++ b/packages/connect/src/factory.ts @@ -125,6 +125,8 @@ export const factory = ({ ethereumVerifyMessage: params => call({ ...params, method: 'ethereumVerifyMessage' }), + ethereumCall: params => call({ ...params, method: 'ethereumCall' }), + getAccountDescriptor: params => call({ ...params, method: 'getAccountDescriptor' }), getAccountInfo: params => call({ ...params, method: 'getAccountInfo' }), diff --git a/packages/connect/src/types/api/ethereum/index.ts b/packages/connect/src/types/api/ethereum/index.ts index 777a78055f44..8ed2439f4efc 100644 --- a/packages/connect/src/types/api/ethereum/index.ts +++ b/packages/connect/src/types/api/ethereum/index.ts @@ -159,3 +159,12 @@ export const EthereumVerifyMessage = Type.Object({ hex: Type.Optional(Type.Boolean()), signature: Type.String(), }); + +// ethereumCall + +export type EthereumCall = Static; +export const EthereumCall = Type.Object({ + from: Type.String(), + to: Type.String(), + data: Type.String(), +}); diff --git a/packages/connect/src/types/api/ethereumCall.ts b/packages/connect/src/types/api/ethereumCall.ts new file mode 100644 index 000000000000..c44e0ffb7f70 --- /dev/null +++ b/packages/connect/src/types/api/ethereumCall.ts @@ -0,0 +1,6 @@ +import type { CommonParamsWithCoin, Params, Response } from '../params'; +import type { EthereumCall } from './ethereum'; + +export declare function ethereumCall( + params: CommonParamsWithCoin & Params, +): Response<{ data: string }>; diff --git a/packages/connect/src/types/api/index.ts b/packages/connect/src/types/api/index.ts index 15f746b792e0..e3f1faaa6251 100644 --- a/packages/connect/src/types/api/index.ts +++ b/packages/connect/src/types/api/index.ts @@ -40,6 +40,7 @@ import { ethereumSignMessage } from './ethereumSignMessage'; import { ethereumSignTransaction } from './ethereumSignTransaction'; import { ethereumSignTypedData } from './ethereumSignTypedData'; import { ethereumVerifyMessage } from './ethereumVerifyMessage'; +import { ethereumCall } from './ethereumCall'; import { firmwareUpdate } from './firmwareUpdate'; import { getAccountDescriptor } from './getAccountDescriptor'; import { getAccountInfo } from './getAccountInfo'; @@ -217,6 +218,8 @@ export interface TrezorConnect { // https://connect.trezor.io/9/methods/ethereum/ethereumVerifyMessage/ ethereumVerifyMessage: typeof ethereumVerifyMessage; + ethereumCall: typeof ethereumCall; + // https://connect.trezor.io/9/methods/device/firmwareUpdate/ firmwareUpdate: typeof firmwareUpdate;