传统的gas定价模型(Txn Type===0)

import Web3 from 'web3';import { AbiItem } from 'web3-utils/types/index.d';import erc20 from '../abis/erc20.json';import { FeeMarketEIP1559Transaction as Tx } from '@ethereumjs/tx';import { Common, Chain, Hardfork } from '@ethereumjs/common';import config from '../constants/service.config';const webSocketProvider = (rpcUrl: string) => {  return new Web3.providers.HttpProvider(rpcUrl);};const provider = (rpcUrl: string = config.alchemyEthBaseUrl) => {  return new Web3(webSocketProvider(rpcUrl));};const transfer = async (  { ...rest }: any) => {  const {    privateKey,    contractAddress,    tokenAddress,    recipientAddress,    rpcUrl,    senderAddress,    amount,    ...args  } = rest;  const web3 = provider();  const { toHex, toWei, hexToNumber } = web3.utils;  const gasPrice = await web3.eth.getGasPrice();  try {    const nounce = await web3.eth.getTransactionCount(senderAddress, 'pending');    let rawTx = {};    if (['eth', 'matic'].includes(tokenAddress.toLowerCase())) {      // 以太坊主币      rawTx = {        to: recipientAddress,        value: toHex(toWei(String(amount))),      };    } else {      // 合乎erc20标准的代币      const contract = new web3.eth.Contract(erc20 as AbiItem[], tokenAddress, {        from: senderAddress,      });      const transferEvent = contract.methods.transfer(        recipientAddress,        toHex(toWei(String(amount)))      );      const limit = await transferEvent.estimateGas(); // gas limit      rawTx = {        to: tokenAddress,        gasLimit: toHex(Math.ceil(limit * 1.2)),        data: transferEvent.encodeABI(),      };    }    /**     * 组装交易数据:     * to:      *    如果是以太坊主币,to是收款人地址     *    如果是erc20代码,to是协定地址,收款人地址在合约办法:contrack.methods.transfer中定义     * value:     *    如果是以太坊主币,value是转账金额     *    如果是erc20代码,value是`toHex(0)`,转账金额在合约办法:contrack.methods.transfer中定义     * maxPriorityFeePerGas     *    Txn Type=2所必须,进步优先级,给予矿工的小费     * maxFeePerGas     *    Txn Type=2所必须,进步优先级,给予矿工小费的最大值    */    rawTx = {      from: senderAddress,      nonce: toHex(nounce),      gasLimit: toHex(21000), //"21000",       gasPrice: toHex(gasPrice),      value: '0x00', //"10000000",//'0x00',      ...rawTx,    };    /**     * 以太坊资源的通用实现类;     *    创立以太坊链和分叉的实例,实现EIP1559性能须要抉择London硬分叉     *    new Common({ chain: Chain.Mainnet, eips: [1559] })    */    const common = new Common({      chain: Chain.Goerli,      hardfork: Hardfork.London,    });    const unsignedTx = Tx.fromTxData(rawTx, { common });    const secretKey = Buffer.from(privateKey.slice(2), 'hex');    const signedTx = unsignedTx.sign(secretKey);    const serializedTx = signedTx.serialize();    const signedTransactionData = '0x' + serializedTx.toString('hex');    web3.eth      .sendSignedTransaction(signedTransactionData, async function (err, hash) {        if (!err) {          /**           * gasfee = `${web3.utils.fromWei(            (Number((rawTx as any).gasLimit) * Number(gasPrice)).toString()          )}${wallet.unit}`;          */          console.log('-----hash-------', hash);          const url = `https://goerli.etherscan.io/tx/${hash}`;          const accepted = `https://etherscan.io/api?module=localchk&action=txexist&txhash=${hash}`;          console.log('TX Link', url);          console.log('Accepted', accepted);        } else {          console.log('-----error', err);        }      })      .on('receipt', (receipt) => {        console.log('TX receipt', receipt);        //             blockHash: ""        // blockNumber:         // contractAddress: null        // cumulativeGasUsed:         // effectiveGasPrice:         // from: ""        // gasUsed: 21000        // logs: []        // logsBloom: ""        // status: true        // to: ""        // transactionHash: ""        // transactionIndex:         // type: "0x0"        const { gasUsed, status } = receipt;        /**         * gasfee = `${web3.utils.fromWei(          (gasUsed * Number(gasPrice)).toString()        )}${wallet.unit}`;        */      });  } catch (e) {    console.log(e);  }};

伦敦硬分叉EIP1559(Txn Type===2)

import Web3 from 'web3';import { AbiItem } from 'web3-utils/types/index.d';import erc20 from '../abis/erc20.json';import { FeeMarketEIP1559Transaction as Tx } from '@ethereumjs/tx';import { Common, Chain, Hardfork } from '@ethereumjs/common';import config from '../constants/service.config';const webSocketProvider = (rpcUrl: string) => {  return new Web3.providers.HttpProvider(rpcUrl);};const provider = (rpcUrl: string = config.alchemyEthBaseUrl) => {  return new Web3(webSocketProvider(rpcUrl));};const transfer = async (  { ...rest }: any) => {  const {    privateKey,    contractAddress,    tokenAddress,    recipientAddress,    rpcUrl,    senderAddress,    amount,    ...args  } = rest;  const web3 = provider();  const { toHex, toWei, hexToNumber } = web3.utils;  const gasPrice = await web3.eth.getGasPrice();  try {    const nounce = await web3.eth.getTransactionCount(senderAddress, 'pending');    let rawTx = {};    if (['eth', 'matic'].includes(tokenAddress.toLowerCase())) {      // 以太坊主币      rawTx = {        to: recipientAddress,        value: toHex(toWei(String(amount))),      };    } else {      // 合乎erc20标准的代币      const contract = new web3.eth.Contract(erc20 as AbiItem[], tokenAddress, {        from: senderAddress,      });      const transferEvent = contract.methods.transfer(        recipientAddress,        toHex(toWei(String(amount)))      );      const limit = await transferEvent.estimateGas(); // gas limit      rawTx = {        to: tokenAddress,        gasLimit: toHex(Math.ceil(limit * 1.2)),        data: transferEvent.encodeABI(),      };    }    // maxPriorityFeePerGas: Txn Type === 2所须要的字段    const maxPriorityFeePerGasRes = request.post(config.alchemyEthBaseUrl, {      id: 1,      jsonrpc: '2.0',      method: 'eth_maxPriorityFeePerGas',    });    const maxPriorityFeePerGas = ((await maxPriorityFeePerGasRes) as any)      .result;    const getBlockRes = web3.eth.getBlock('latest');    const baseFeePerGas = ((await getBlockRes) as any).baseFeePerGas - 1;    /**     * 组装交易数据:     * to:      *    如果是以太坊主币,to是收款人地址     *    如果是erc20代码,to是协定地址,收款人地址在合约办法:contrack.methods.transfer中定义     * value:     *    如果是以太坊主币,value是转账金额     *    如果是erc20代码,value是`toHex(0)`,转账金额在合约办法:contrack.methods.transfer中定义     * maxPriorityFeePerGas     *    Txn Type=2所必须,进步优先级,给予矿工的小费     * maxFeePerGas     *    Txn Type=2所必须,进步优先级,给予矿工小费的最大值    */    rawTx = {      from: senderAddress,      nonce: toHex(nounce),      gasLimit: toHex(21000), //"21000",      maxPriorityFeePerGas: maxPriorityFeePerGas,      maxFeePerGas: toHex(        2 * baseFeePerGas + hexToNumber(maxPriorityFeePerGas)      ),      value: '0x00', //"10000000",//'0x00',      ...rawTx,    };    /**     * 以太坊资源的通用实现类;     *    创立以太坊链和分叉的实例,实现EIP1559性能须要抉择London硬分叉     *    new Common({ chain: Chain.Mainnet, eips: [1559] })    */    const common = new Common({      chain: Chain.Goerli,      hardfork: Hardfork.London,    });    const unsignedTx = Tx.fromTxData(rawTx, { common });    const secretKey = Buffer.from(privateKey.slice(2), 'hex');    const signedTx = unsignedTx.sign(secretKey);    const serializedTx = signedTx.serialize();    const signedTransactionData = '0x' + serializedTx.toString('hex');    web3.eth      .sendSignedTransaction(signedTransactionData, async function (err, hash) {        if (!err) {          /**           * gasfee = `${web3.utils.fromWei(            (Number((rawTx as any).gasLimit) * Number(gasPrice)).toString()          )}${wallet.unit}`;          */          console.log('-----hash-------', hash);          const url = `https://goerli.etherscan.io/tx/${hash}`;          const accepted = `https://etherscan.io/api?module=localchk&action=txexist&txhash=${hash}`;          console.log('TX Link', url);          console.log('Accepted', accepted);        } else {          console.log('-----error', err);        }      })      .on('receipt', (receipt) => {        console.log('TX receipt', receipt);        // blockHash: ""        // blockNumber:         // contractAddress: null        // cumulativeGasUsed:         // effectiveGasPrice:         // from: ""        // gasUsed: 21000        // logs: []        // logsBloom: "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"        // status: true        // to: ""        // transactionHash: ""        // transactionIndex:         // type: "0x0"        const { gasUsed, status } = receipt;        /**         * gasfee = `${web3.utils.fromWei(          (gasUsed * Number(gasPrice)).toString()        )}${wallet.unit}`;        */      });  } catch (e) {    console.log(e);  }};

内部签名

import Web3 from 'web3';import { bufArrToArr, toBuffer, bigIntToHex, addHexPrefix } from '@ethereumjs/util'...// signatures是内部服务签名const { toHex, toWei, toDecimal } = web3.utils;const { r_hex: r, s_hex: s, recovery_id_hex } = signaturesconst chainId = unsignedTx.common.chainId()const v = chainId === undefined  ? BigInt(toDecimal(addHexPrefix(recovery_id_hex)) + 27)  : BigInt(toDecimal(addHexPrefix(recovery_id_hex)) + 35) + BigInt(chainId) * BigInt(2)const toSignTx = {  nonce: unsignedTx.nonce,  gasPrice: unsignedTx.gasPrice,  gasLimit: unsignedTx.gasLimit,  to: unsignedTx.to,  value: unsignedTx.value,  data: unsignedTx.data,  v,  r: addHexPrefix(r),  s: addHexPrefix(s),}const signedTx = Tx.fromTxData(toSignTx, { common })const serializeSignedTx = signedTx.serialize()const signedTxHex = addHexPrefix(serializeSignedTx.toString('hex'))web3.eth.sendSignedTransaction(signedTxHex, async function (err, hash) {    if (!err) {      console.log('-----hash-------', hash);      const url = `https://goerli.etherscan.io/tx/${hash}`;      const accepted = `https://etherscan.io/api?module=localchk&action=txexist&txhash=${hash}`;      console.log('TX Link', url);      console.log('Accepted', accepted);    } else {       console.log('-----error', err);    }})