This guide demonstrates how developers can interact with rollups from their code. We’ll cover connecting to the Elder testnet, preparing transactions, and sending them to the rollup.
Shib Alpha Layer provides seamless rollup interaction through the Elder testnet, enabling developers to connect, prepare transactions, and send them to rollups with instant confirmations.

Connect to Elder Testnet

The first step is to establish a connection to the Elder testnet. This involves signing a message with your Ethereum wallet to derive your Elder address and public key.

Basic Connection Setup

import { eth_getElderAccountInfoFromSignature } from 'elderjs'; 
import type { Signer } from 'ethers'; 

type ConnectParams = { 
  roll_id: number; 
  chain_id: bigint; 
  eth_rpc: string; 
  message?: string; 
}; 

const ELDER_testnet = process.env.ELDER_testnet;
const ELDER_REST_URL = process.env.ELDER_REST;
const ELDER_RPC_URL = process.env.ELDER_RPC;

let elder_address = '';
let elder_public_key = '';

async function connect(signer: Signer, params: ConnectParams) {
  const message = params.message || `Connect to Elder ${ELDER_testnet}`;

  const signature = await signer.signMessage(message);

  const { recoveredPublicKey, elderAddr } = await eth_getElderAccountInfoFromSignature(
    message,
    signature
  );

  elder_address = elderAddr;
  elder_public_key = recoveredPublicKey;

  return {
    roll_id: params.roll_id,
    chain_id: params.chain_id,
    eth_rpc: params.eth_rpc,
    eth_address: (await signer.getAddress()) as `0x${string}`,
    elder_address: elderAddr,
    elder_public_key: recoveredPublicKey,
    signer,
  };
}

Understanding the Connection Process

When connecting to the Elder testnet, the function:
  1. Signs a message using your Ethereum wallet
  2. Derives your Elder address and public key from the signature
  3. Returns connection details including both Ethereum and Elder addresses
The elder_address and elder_public_key are crucial as they’ll be used when building raw Elder transactions.

Prepare Ethereum Transaction Object

Before sending a transaction to the rollup, you need to prepare an Ethereum transaction object. This can be a PreparedTransactionRequest, PopulatedTransactionRequest, ContractTransaction, or any TransactionLike object.
// Example of preparing a transaction from a contract function
const tx = await didRegistry.connect(signer).getFunction("function_name").populateTransaction(
    ...args
);
You can prepare transactions for any contract interaction, token transfer, or other operations supported by the rollup.

Send Elder Transaction

Once you have prepared your transaction, you can send it to the Elder network using the following code:
import { ElderConfig, eth_broadcastTx, eth_getElderMsgAndFeeTxRaw } from 'elderjs';
import { TransactionLike } from 'ethers';

type BigNumberish = string | number | bigint;

const config = {
    rest: ELDER_REST_URL,
    rpc: ELDER_RPC_URL,
    chainName: ELDER_testnet,
    rollID: Number(ELDER_ROLL_ID),
    rollChainID: Number(ROLLUP_CHAIN_ID),
    eth_rpc: ROLLUP_ETH_RPC,
};

async function sendTransaction(
        tx: TransactionLike<string>,
        opts?: { gasLimit?: BigNumberish; value?: BigNumberish }
    ) {
        opts = {
            gasLimit: opts?.gasLimit || 10_000_000,
            value: opts?.value || parseEther('0'),
        };

        if (
            typeof elder_address === 'undefined' ||
            typeof elder_public_key === 'undefined' ||
            typeof config === 'undefined'
        )
            throw new Error('network not connected');

        let { tx_hash, rawTx } = await eth_getElderMsgAndFeeTxRaw(
            tx,
            elder_address,
            elder_public_key,
            opts.gasLimit!,
            opts.value!,
            config
        );
        let broadcastResult = await eth_broadcastTx(rawTx, config.rpc);

        return { tx_hash, result: broadcastResult };
    }

Using the sendTransaction Function

To send your prepared transaction to the rollup:
// Import parseEther if needed
import { parseEther } from 'ethers';

// Send the transaction with optional parameters
const { result, tx_hash } = await sendTransaction(tx, {
    value: parseEther(amount),  // Amount of ETH to send with the transaction
    gasLimit: 1000000,          // Gas limit for the transaction
});

console.log(`Transaction sent with hash: ${tx_hash}`);
console.log('Transaction result:', result);
Transactions are confirmed in seconds with instant inclusion finalities, providing a seamless user experience.

Complete Example

Here’s how you might use these functions together in a complete workflow:
import { Wallet } from 'ethers';
import { eth_getElderAccountInfoFromSignature, eth_broadcastTx, eth_getElderMsgAndFeeTxRaw } from 'elderjs';

// Initialize your wallet with a private key
const wallet = new Wallet('your-private-key');

// Connect to Elder network
const connection = await connect(wallet, {
    roll_id: 1,
    chain_id: 1n,
    eth_rpc: 'https://your-eth-rpc-url',
});

// Prepare a transaction (example with a contract)
const contract = new Contract(contractAddress, contractABI, wallet);
const tx = await contract.getFunction("transfer").populateTransaction(
    recipientAddress,
    parseEther("0.1")
);

// Send the transaction
const { result, tx_hash } = await sendTransaction(tx, {
    gasLimit: 1000000,
});

console.log(`Transaction sent with hash: ${tx_hash}`);

Environment Variables

Make sure to set up the following environment variables for your application:
ELDER_testnet=your-testnet-name
ELDER_REST=https://your-elder-rest-url
ELDER_RPC=https://your-elder-rpc-url
ELDER_ROLL_ID=your-roll-id
ROLLUP_CHAIN_ID=your-rollup-chain-id
ROLLUP_ETH_RPC=https://your-rollup-eth-rpc
These variables are essential for configuring the connection to the Elder network and your specific rollup. Ensure they are properly set before attempting to connect.

Use with Viem

If you’re using Viem instead of Ethers, you can convert your Viem wallet client to an Ethers signer:
import { BrowserProvider } from 'ethers'; 
import type { Account, Chain, Client, Transport } from 'viem'; 

// Helper function to convert viem wallet client to ethers signer 
async function clientToSigner(client: Client<Transport, Chain, Account | undefined>) { 
    const { account, chain, transport } = client; 
    const network = { 
        chainId: chain.id, 
        name: chain.name, 
        ensAddress: chain.contracts?.ensRegistry?.address, 
    }; 
    const provider = new BrowserProvider(transport, network); 
    const signer = await provider.getSigner(account?.address); 
    return signer; 
} 

async function connectViem( 
        client: Client<Transport, Chain, Account | undefined>, 
        chain: Chain<undefined, { rollId?: number }> 
    ) { 
        if (typeof chain.custom?.rollId === 'number') 
            // connect is the ethers connect function from previous examples 
            return await connect(await clientToSigner(client), { 
                chain_id: BigInt(chain.id), 
                eth_rpc: chain.rpcUrls.default.http[0], 
                roll_id: chain.custom.rollId, 
            }); 
        return null; 
    }
This approach allows you to use your existing Viem setup while still leveraging the Elder.js functions that expect an Ethers signer.

Key Benefits of Rollup Interaction

Instant Confirmations

Transactions confirmed in seconds with instant inclusion finalities

Enhanced Interoperability

Seamless cross-chain operations with improved security

Single Account System

Use your existing wallet to interact with multiple rollups

Developer Friendly

Simple APIs and comprehensive documentation for easy integration

Next Steps

Now that you understand how to interact with your rollup, you can:
  • Develop smart contracts for your rollup
  • Create dApps that leverage the rollup’s capabilities
  • Integrate with existing Ethereum applications
  • Build cross-chain applications using the enhanced interoperability features

Interacting with rollups on Shib Alpha Layer provides instant confirmations, enhanced interoperability, and a unified account system that simplifies development. Join the ecosystem that’s bringing Web2 simplicity to Web3 innovation!