Wasm Precompile

Wasm Precompile Example

This example demonstrates how to use the Wasm precompile contract to interact with CosmWasm smart contracts.

Prerequisites

Before running this example, make sure you have:

  • Node.js v18 or later
  • Access to XPLA Chain testnet (Cube)
  • A deployed CosmWasm contract (or use the example contract address)

Setup

Install the required dependencies:

npm install @xpla/evm @xpla/xpla @interchainjs/cosmos @interchainjs/utils ethers bip39

Example Code

// examples/wasm-precompile.js
import { JsonRpcProvider, Wallet } from 'ethers';
import { createPrecompileWasm } from '@xpla/evm/precompiles';
import { fromBech32 } from '@interchainjs/encoding';
import { hexlify } from 'ethers';
import * as fs from 'fs';
import * as path from 'path';

async function wasmPrecompileExample() {
  console.log('=== Wasm Precompile Example ===\n');

  const RPC_URL = 'https://cube-evm-rpc.xpla.dev';
  const provider = new JsonRpcProvider(RPC_URL);

  // Generate wallet
  const mnemonic = 'abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about';
  const wallet = Wallet.fromPhrase(mnemonic);
  const userAddress = wallet.address;
  
  console.log(`User Address: ${userAddress}\n`);

  // Create wasm contract instance
  const wasmContract = createPrecompileWasm(provider);
  const wasmContractWithSigner = wasmContract.connect(wallet.connect(provider));

  try {
    // For this example, we'll assume a contract is already deployed
    // In a real scenario, you would first deploy the contract using CosmWasm
    
    // Example contract address
    const contractAddressBech32 = 'xpla1qw97zu0xazljpckxzf7wc5g3hevp7weefn40fw8z09ejzm2wz6ms7qverx';
    
    // Convert to EVM address format (last 20 bytes)
    const { data: contractAddressHex } = fromBech32(contractAddressBech32);
    const contractAddressHexString = hexlify(contractAddressHex.slice(12));
    
    console.log(`Contract Bech32: ${contractAddressBech32}`);
    console.log(`Contract EVM: ${contractAddressHexString}\n`);

    // Query contract state
    console.log('Querying contract state...');
    const queryData = new Uint8Array(Buffer.from('{"get_count": {}}'));
    
    const queryResponse = await wasmContract.smartContractState(contractAddressHexString, queryData);
    
    // Parse response
    const responseHex = queryResponse.startsWith('0x') ? queryResponse.slice(2) : queryResponse;
    const responseBytes = new Uint8Array(Buffer.from(responseHex, 'hex'));
    const responseText = new TextDecoder().decode(responseBytes);
    const responseData = JSON.parse(responseText);
    
    console.log(`Current Count: ${responseData.count}\n`);

    // Execute contract function
    console.log('Executing increment function...');
    const executeMsg = new Uint8Array(Buffer.from('{"increment": {}}'));
    
    const txResponse = await wasmContractWithSigner.executeContract(
      userAddress, 
      contractAddressHexString, 
      executeMsg, 
      []
    );
    
    console.log(`Transaction Hash: ${txResponse.hash}`);
    
    // Wait for transaction confirmation
    const txReceipt = await txResponse.wait();
    console.log(`Transaction confirmed in block: ${txReceipt.blockNumber}\n`);

    // Query updated state
    console.log('Querying updated contract state...');
    const updatedQueryResponse = await wasmContract.smartContractState(contractAddressHexString, queryData);
    
    const updatedResponseHex = updatedQueryResponse.startsWith('0x') ? updatedQueryResponse.slice(2) : updatedQueryResponse;
    const updatedResponseBytes = new Uint8Array(Buffer.from(updatedResponseHex, 'hex'));
    const updatedResponseText = new TextDecoder().decode(updatedResponseBytes);
    const updatedResponseData = JSON.parse(updatedResponseText);
    
    console.log(`Updated Count: ${updatedResponseData.count}`);
    console.log('✅ Wasm contract interaction completed successfully!');
    
  } catch (error) {
    console.error('❌ Wasm operation failed:', error);
  }
}

wasmPrecompileExample().catch(console.error);

Running the Example

node examples/wasm-precompile.js

Expected Output

=== Wasm Precompile Example ===

User Address: 0x123...

Contract Bech32: xpla1qw97zu0xazljpckxzf7wc5g3hevp7weefn40fw8z09ejzm2wz6ms7qverx
Contract EVM: 0xEC5111BE581F3B394CEAF4B8E27973216D4E16B7

Querying contract state...
Current Count: 5

Executing increment function...
Transaction Hash: 0xabc...
Transaction confirmed in block: 12347

Querying updated contract state...
Updated Count: 6
✅ Wasm contract interaction completed successfully!

Key Features

  • Contract Address Conversion: Convert between Bech32 and EVM address formats
  • State Queries: Query CosmWasm contract state using JSON messages
  • Contract Execution: Execute contract functions with proper message encoding
  • Response Parsing: Decode hex responses back to readable JSON

Common Operations

This example demonstrates:

  • Converting CosmWasm contract addresses to EVM format
  • Querying contract state with structured messages
  • Executing contract functions
  • Parsing binary responses from contract calls

Message Format

CosmWasm contracts expect messages in JSON format:

  • Query Messages: {"get_count": {}}, {"get_balance": {"address": "..."}}
  • Execute Messages: {"increment": {}}, {"transfer": {"to": "...", "amount": "..."}}