Updates and complete methods here
Concept / method for associating a wallet address
any strange / unexplainable tx failures are very likely due to not having "associated"*
or "linked"*
the wallet yet
*
This is a term describing the act of making the wallet's pubkey known to the chain so that it can be confirmed that both addresses exist and can be safely used in interoperability functions.
export const associateAddr = async (signature: Hex, message: string, client: UsePublicClientReturnType) => {
if (!client) {
throw new Error('Failed to associate. Client is not defined.');
}
const { r, s } = secp256k1.Signature.fromCompact(signature.slice(2, 130));
const v = hexToNumber(`0x${signature.slice(130)}`);
const messageLength = Buffer.from(message, 'utf8').length;
const messageToSign = `\x19Ethereum Signed Message:\n${messageLength}${message}`;
const request: AssociateRequest = { r: numberToHex(r), s: numberToHex(s), v: numberToHex(v - 27), custom_message: messageToSign };
await client.request<AssociateRequestSchema>({ method: 'sei_associate', params: [request] });
};
You can easily extract the v/r/s from a signed message using the 'ethers' library:
const ethers = require('ethers');
// Example pre-signed transaction data (replace with your actual data)
const signedTxData = <raw_signed_message_here>;
// Remove '0x' prefix if present
const rawData = signedTxData.startsWith('0x') ? signedTxData.slice(2) : signedTxData;
// Extract v, r, s from the raw data
const v = parseInt(rawData.slice(-2), 16); // last byte
const r = '0x' + rawData.slice(0, 64); // first 32 bytes
const s = '0x' + rawData.slice(64, 128); // next 32 bytes
console.log('v:', v);
console.log('r:', r);
console.log('s:', s);
Using something like the example above, sign an empty bytes payload with the wallet to be 'associated', extract the v,r,s signature values and broadcast it using this EVM RPC method:
curl --request POST --url http://127.0.0.1:8545 --header 'accept: application/json' --header 'content-type: application/json' --data ' { "id": 1, "jsonrpc": "2.0", "method": "sei_associate", "params": [ { "r": "0x7c6d0be72bdff972210ce86783afbadeb3739101ac0e6b64b3fda64ddc7285ef", "s": "0x378f0312476380d690999480fba3b80bcb8912781974ccde9c298d7dd18c803c", "v": "0x1" } ] }
https://www.docs.sei.io/dev-advanced-concepts/evm-rpc-endpoints#sei_associate
check for 'associated' address for a given wallet, if exists
$ curl -X POST "$SEIEVM" -H "Content-Type: application/json" -d '{"jsonrpc":"2.0","method":"sei_getEVMAddress","params":["${bech32Address}"],"id":1}'
exp. result
{"jsonrpc":"2.0","id":1,"result":"0x..."}
$ curl -X POST "$SEIEVM" -H "Content-Type: application/json" -d '{"jsonrpc":"2.0","method":"sei_getSeiAddress","params":["${hexAddress}"],"id":1}'
exp. result
{"jsonrpc":"2.0","id":1,"result":"sei1..."}
Fetches Tendermint tx hash for corresponding EVM tx hash, or vice versa
curl "$SEIEVM" \
-X POST \
-H "Content-Type: application/json" \
--data '{"method":"sei_getCosmosTx","params":["<evm_tx_hash>"],"id":1,"jsonrpc":"2.0"}'
curl "$SEIEVM" \
-X POST \
-H "Content-Type: application/json" \
--data '{"method":"sei_getEvmTx","params":["<sei1_tx_hash>"],"id":1,"jsonrpc":"2.0"}'
hard-coded amounts
EVM - 100gwei
native - 0.02usei
EVM method
assuming the following parameters:
- from:
0x1234567890abcdef1234567890abcdef12345678
(sender's address) - to:
0xabcdef1234567890abcdef1234567890abcdef12
(recipient's address) - gas:
21000
(gas limit) - gasPrice:
5000000000
(gas price in Wei) - value:
1000000000000000000
(1 ETH in Wei) - input:
0x
(empty data for a simple ETH transfer) - block:
"latest"
(most recent block)
curl -X POST --data '{"jsonrpc":"2.0","method":"eth_estimateGas","params":[{"from": "0x1234567890abcdef1234567890abcdef12345678", "to": "0xabcdef1234567890abcdef1234567890abcdef12", "gas": "0x5208", "gasPrice": "0x12a05f200", "value": "0xde0b6b3a7640000", "input": "0x"}],"id":1}' -H "Content-Type: application/json" "$SEIEVM"
{
"id": 1,
"jsonrpc": "2.0",
"result": "0x5208" // Estimated gas in hex (21000)
}
Native/Cosmos method
- body: A string representing the transaction details to simulate. This includes the type of transaction, messages, signatures, fee, and any other required metadata formatted as a serialized string in Protobuf format.
import { getQueryClient } from '@sei-js/cosmjs'; // Import the getQueryClient method from sei-js
// Initialize the query client by connecting to the RPC endpoint of your choice
const queryClient = await getQueryClient("YOUR_RPC_URL");
// Destructure the simulation method from the transaction module
const { eCosmosTxV1Beta1Simulate } = queryClient.cosmos.tx.v1beta1;
// Define the parameters for the simulation
const params = {
body: "<Serialized_Transaction_Body>" // Replace with the actual serialized transaction body
};
// Call the simulate method and wait for the response
const response = await eCosmosTxV1Beta1Simulate(params);
// Log the response to see the simulation result
console.log(response);
-
Replace
"YOUR_RPC_URL"
with the actual RPC endpoint URL of the Cosmos SDK-compatible chain you are working with. -
Set the
body
field in theparams
object to the serialized transaction details (the Protobuf format string that represents your transaction). This should include all necessary transaction details like messages, signatures, and metadata. -
Execute the code and get the simulation result, which will include details such as the estimated gas required for the transaction. The response can be used to determine if the transaction will likely succeed or if adjustments are needed.
-
getQueryClient("YOUR_RPC_URL")
: This function creates a client instance connected to the provided Cosmos SDK RPC URL (YOUR_RPC_URL
). This client is required to query the network and simulate transactions. -
params
: This is the request object passed toeCosmosTxV1Beta1Simulate
. It must contain the serialized transaction data (in Protobuf format) as thebody
. This serialized string represents the transaction details you want to simulate.
The response
object returned from eCosmosTxV1Beta1Simulate
will include:
gas_info
: Information about the estimated gas usage.result
: The outcome of the simulation, including any logs
, errors, or other data relevant to the transaction.
Fetching specific Tendermint events from EVM client
In certain scenarios it's possible to prefix the Tendermint tx hash with 0x
and pull event logs from it as if it were an EVM tx. This is to save the trouble of separately querying the Tendermint RPC or indexing events from that environment.
The following query should return any relevant Cosmos >> EVM actions related to CW pointer or direct CW20/721 interactions from the EVM side
# tendermint hash
base_hash="a5443495286d4ec8fe83037220ad3b9b7cea02fed2a42d62cfded14403a654e4"
# hash to uppercase (if necessary) and prefix with '0x'
prefixed_hash="0x$(echo "$base_hash" | tr '[:lower:]' '[:upper:]')"
# curl request with formatted json output
curl --location --request POST "$SEIEVM" \
--header 'Content-Type: application/json' \
--data "{\"jsonrpc\": \"2.0\",\"method\": \"eth_getTransactionReceipt\",\"params\":[\"$prefixed_hash\"],\"id\":\"test\"}" | jq