Creating Transaction
Creating Templates Transaction Messages/Data
Using a Simple Flag:
--generate-only
Transaction templates form the foundation of blockchain development and automation in ENI. With the --generate-only
flag and Foundry's cast
tool, developers can create, analyze, and debug transactions in both native Cosmos and EVM environments. Understanding these tools unlocks powerful possibilities for building complex applications and development workflows.
Native Transaction Templates
The --generate-only
flag transforms any ENI CLI transaction command into a template generator, creating a complete transaction structure without broadcasting it. These templates serve as building blocks for applications, frontends, and automation tools.
Basic Usage Pattern
The general pattern follows this structure:
enid tx <module> <action> <parameters> --from <key> --generate-only
For example, a token transfer template:
enid tx bank send \
$(enid keys show sender -a) \
$(enid keys show recipient -a) \
1000000ueni \
--from sender \
--generate-only | jq
EVM Transaction Analysis
ENI's EVM compatibility introduces additional complexity when handling transactions. Let’s explore how to generate and analyze EVM transactions using ENI’s native tools and Foundry’s cast
command.
Generating an EVM Transaction Template
To generate an EVM transaction template, use the evm
module with --generate-only
. Here’s an example of registering an EVM pointer:
enid tx evm register-evm-pointer NATIVE \
factory/eni1ep3f207kt7julz9tjwxp2x8kluj0y9l6u0fume/gptw \
--gas-fee-cap=100000000000 \
--gas-limit=2500000 \
--evm-rpc=https://rpc.eniac.network \
--from tf \
--generate-only
This command returns a transaction hash, which you can further analyze using Foundry’s cast
tool.
Analyzing an EVM Transaction with Cast
Once you have the transaction hash, you can use Foundry’s cast
command to inspect transaction details:
cast tx 0x5010e6600e67f04a9bc3d3b670a7c2de380b180713d9a014a5dbd76b7e2190f1 \
--rpc-url=https://rpc.eniac.network
This provides detailed transaction information:
blockHash 0x4696d63a9a9ae88b03bcc94ccbd87f407e994b309d1dff9c0626de51ac57b76e
blockNumber 130076639
from 0xAa55a16dD4E73c48C968928983c2bcC98d913d96
transactionIndex 7
effectiveGasPrice 100000000000
accessList []
chainId 173
gasLimit 2500000
hash 0x5010e6600e67f04a9bc3d3b670a7c2de380b180713d9a014a5dbd76b7e2190f1
input 0xc31d960f0000...
maxFeePerGas 100000000000
maxPriorityFeePerGas 100000000000
nonce 3
r 0x92313277d1ffad9a18260303081671a2d40035016ac83740486dee916c964db7
s 0x158de03cac836b1fad26770274cffdb06b0809961811eb0b66aebfff95186417
to 0x000000000000000000000000000000000000100b
type 2
value 0
yParity 1
Understanding EVM Transaction Components
Let’s break down the key components of an EVM transaction:
input
: Encoded function call datamaxFeePerGas
: Maximum total fee per unit of gasmaxPriorityFeePerGas
: Maximum priority fee per unit of gasgasLimit
: Maximum gas allowed for the transactionto
: Target contract addresstype
: Transaction type (2 indicates an EIP-1559 transaction)
Practical Applications
Development Workflow
When developing applications that interact with native and EVM functionality:
async function analyzeTransaction(txHash) {
// First, get the native transaction details
const nativeTx = await fetch(`${eniRestEndpoint}/cosmos/tx/v1beta1/txs/${txHash}`).then((res) => res.json());
// If it's an EVM transaction, get EVM details
if (nativeTx.tx.body.messages[0]['@type'].includes('evm')) {
const evmTx = await fetch(`${evmRpcEndpoint}`, {
method: 'POST',
body: JSON.stringify({
jsonrpc: '2.0',
method: 'eth_getTransactionByHash',
params: [txHash],
id: 1
})
}).then((res) => res.json());
return {
native: nativeTx,
evm: evmTx
};
}
return { native: nativeTx };
}
Template Generation for Different Transaction Types
Generate templates for various transaction types:
# Native governance proposal
enid tx gov submit-proposal param-change proposal.json \
--from validator \
--generate-only > native_template.json
# EVM contract interaction
enid tx evm send-tx \
--evm-rpc=https://rpc.eniac.network \
--gas-limit=2500000 \
--from=mykey \
--generate-only > evm_template.json
Best Practices
Transaction Analysis
When analyzing transactions:
Always validate both the native and EVM aspects of a transaction
Use
cast
to decode input data when dealing with EVM transactionsTrack gas parameters on both layers
Monitor transaction status on both the native and EVM layers
Error Handling
Handle potential issues on both layers:
try {
// Check native transaction status
const nativeStatus = await checkNativeStatus(txHash);
// If native succeeds but EVM fails, investigate the EVM layer
if (nativeStatus.success) {
const evmStatus = await checkEvmStatus(txHash);
if (!evmStatus.success) {
const evmError = await cast.call(['tx', txHash, '--rpc-url', evmRpcUrl]);
console.error('EVM transaction failed:', evmError);
}
}
} catch (error) {
console.error('Transaction analysis failed:', error);
}
Security
Keep private keys secure and never include them in templates
Use
.env
files or other environment variables whenever possible when dealing with hardcoded wallet keys or mnemonics
Last updated