Skip to main content

Ethereum

November 11, 2022
Nahee Park
Software Engineer, DSRV

Prerequisites

The Ethereum part carries out the practice using ethers. Please prepare by installing the package.

Create Signed transaction

For a signed transaction, there are three essential steps.

  1. Create a raw transaction first.
  2. Make a raw transaction signature.
  3. Convert a raw transaction into a signed transaction by adding a signature.

1. getEthereumTx

Transaction and signature are needed. We first develop a getEtheriumTx function to generate raw transaction because it is necessary to have a raw transaction to receive a signature via kms.

getEthereumTx.ts
import { ethers, UnsignedTransaction } from 'ethers';
import { Account, CHAIN } from '@dsrv/kms/lib/types';
import { Ethereum } from '@dsrv/kms/lib/blockchains/ethereum';

interface RawTransaction {
unSignedTx: UnsignedTransaction;
serializedTx: string;
}

export const getEthereumTx = async (mnemonic: string): Promise<RawTransaction> => {
/* 1. get Account */
const account = Ethereum.getAccount({
mnemonic,
path: { type: CHAIN.ETHEREUM, account: 0, index: 0 },
});

/* 2. make raw transaction */
const provider = new ethers.providers.JsonRpcProvider(
'https://ethereum-goerli-rpc.allthatnode.com',
); //allthatnode rpc
const nonce = await provider.getTransactionCount(account.address);
const gasLimit = await provider.estimateGas({
value: '0x1',
to: account.address,
});
const transactionParameters = {
to: account.address, // send to yourself
value: ethers.utils.parseEther('0.0005'),
gasLimit: gasLimit.mul(10).toString(),
gasPrice: '0x07f9acf02',
type: 2,
nonce,
// goerli network
chainId: 5,
// EIP-1559; Type 2
maxPriorityFeePerGas: '0x07f9acf02',
maxFeePerGas: '0x07f9acf02',
};

return {
serializedTx: ethers.utils.serializeTransaction(transactionParameters),
unSignedTx: transactionParameters,
};
};

2. getEthereumSignature

We then develop a method called getEthereumSignature that produces a signature by using serializedTx as a factor in order to gain a signature for the transaction.

getEthereumSignature.ts
import { CHAIN } from '@dsrv/kms/lib/types';
import { Ethereum } from '@dsrv/kms/lib/blockchains/ethereum';

export const getEthereumSignature = (serializedTx: string): string => {
const { signature } = Ethereum.signTx(
{
mnemonic,
path: { type: CHAIN.ETHEREUM, account: 0, index: 0 },
},
serializedTx,
);

return signature;
};

3. createEthereumSignedTx

Finally, we develop the createEthereumSignedTx function, which takes an unsignedTx and a signature generated earlier and returns a signed transaction.

createEthereumSignedTx.ts
import { ethers, UnsignedTransaction } from 'ethers';

interface createEthereumSignedTxProps {
unSignedTx: UnsignedTransaction;
signature: string;
}

/* create singedTx by combining tx and signature */
export const createEthereumSignedTx = ({
unSignedTx,
signature,
}: createEthereumSignedTxProps): string => {
const signedTx = ethers.utils.serializeTransaction(unSignedTx, signature);
return signedTx;
};

Finally, you can construct a getEthereumSignedTx function that returns a signed transaction by combining the functions you made before, getEthereumTx, getEthereumSignature, and createEthereumSignedTx.

getEthereumSignedTx.ts
export const getEthereumSignedTx = async (mnemonic: string) => {
/* 1. get rawTransaction */
const { serializedTx, unSignedTx } = await getEthereumTx(mnemonic);
/* 2. get signature */
const ethereumSignature = getEthereumSignature(serializedTx);
/* 3. create singedTx by combining rawTransaction and signature */
const ethereumSignedTx = createEthereumSignedTx({
unSignedTx,
signature: ethereumSignature,
});

return ethereumSignedTx;
};

Send Signed transaction

You can transmit the transaction using a signed transaction you've prepared.

sendEthereumTransaction.ts
import { Transaction, providers } from 'ethers';

export const sendEthereumTransaction = async (serializedTx: string): Promise<Transaction> => {
const provider = new providers.JsonRpcProvider('https://ethereum-goerli-rpc.allthatnode.com');

const result = await provider.sendTransaction(serializedTx);
return result;
};
main.ts
const mnemonic = 'sample mnemonic';
const main = async () => {
const ethereumSignedTx = await getEthereumSignedTx(mnemonic);
const ethereumTxResult = await sendEthereumTransaction(ethereumSignedTx);
console.log('Ethereum Tx Result : ', ethereumTxResult);
};
main();

Examples

To complete the transaction, follow the steps outlined below. A faucet is required to transmit a transaction. You can request faucet through the FAUCET tab in the wallet.

danger

The loss of all cryptocurrency holdings is possible if mnemonic is revealed. To execute the following example, use a test or development mnemonic.

Live Editor
Result
Loading...