Skip to content

Quickstart

Build a real-time payment application using RISE Chain's Shred API in under 15 minutes. This tutorial will demonstrate instant transaction confirmations and real-time balance updates.

What We'll Build

A simple payment application that:

  • Sends instant payments with immediate confirmation
  • Displays real-time balance updates
  • Shows live transaction history
  • Demonstrates shred subscriptions

Prerequisites

  • Node.js 16+ installed
  • Basic TypeScript/JavaScript knowledge
  • A code editor (VS Code recommended)
  • 5 minutes to spare

Project Setup

Create a New Project

mkdir rise-quickstart
cd rise-quickstart
npm init -y

Install Dependencies

npm install shreds viem dotenv
npm install -D typescript tsx @types/node

Configure TypeScript

Create tsconfig.json:

tsconfig.json
{
  "compilerOptions": {
    "target": "ES2020",
    "module": "ESNext",
    "moduleResolution": "bundler",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "resolveJsonModule": true
  }
}

Set Up Environment

Create .env:

.env
# RISE Testnet RPC endpoints
RISE_RPC_URL=https://testnet.riselabs.xyz
RISE_WS_URL=wss://testnet.riselabs.xyz
 
# Test wallet (has testnet tokens)
PRIVATE_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80

Build the Application

Create quickstart.ts:

quickstart.ts
import 'dotenv/config'
import { createWalletClient, createPublicClient, http, webSocket, parseEther, formatEther } from 'viem'
import { privateKeyToAccount } from 'viem/accounts'
import { riseTestnet } from 'viem/chains'
import { shredActions } from 'shreds/viem'
 
// Setup account from private key
const account = privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`)
console.log('Wallet address:', account.address)
 
// Create client and extend with shred actions
const client = createWalletClient({
  account,
  chain: riseTestnet,
  transport: http()
}).extend(shredActions)
 
// Recipient address
const recipient = '0x70997970C51812dc3A010C7d01b50e0d17dc79C8'
 
async function main() {
  console.log('[START] RISE Chain Quickstart\n')
  
  // Step 1: Check initial balances
  console.log('[INFO] Checking initial balances...')
  const senderBalance = await client.getBalance({ address: account.address })
  const recipientBalance = await client.getBalance({ address: recipient })
  
  console.log(`Sender: ${formatEther(senderBalance)} ETH`)
  console.log(`Recipient: ${formatEther(recipientBalance)} ETH\n`)
  
  // Step 2: Subscribe to shreds for real-time updates
  console.log('[SUBSCRIBE] Subscribing to real-time updates...\n')
  
  const unwatch = await client.watchShreds({
    onShred: (shred) => {
      console.log(`[SHRED] New shred detected!`)
      console.log(`   Index: ${shred.shredIndex}`)
      console.log(`   Transactions: ${shred.transactions.length}`)
      console.log(`   Timestamp: ${new Date(shred.blockTimestamp * 1000).toLocaleTimeString()}\n`)
    }
  })
  
  // Step 3: Send instant transaction
  console.log('[SEND] Sending 0.1 ETH with instant confirmation...')
  const startTime = Date.now()
  
  try {
    const receipt = await client.sendRawTransactionSync({
      to: recipient,
      value: parseEther('0.1'),
    })
    
    const confirmTime = Date.now() - startTime
    console.log(`[SUCCESS] Transaction confirmed in ${confirmTime}ms!`)
    console.log(`[RECEIPT] Transaction details:`)
    console.log(`   Block: ${receipt.blockNumber}`)
    console.log(`   Gas used: ${receipt.gasUsed}`)
    console.log(`   Status: ${receipt.status === 'success' ? 'Success' : 'Failed'}`)
    
    // Step 4: Check updated balances immediately
    console.log('[INFO] Checking updated balances...')
    const newSenderBalance = await client.getBalance({ address: account.address })
    const newRecipientBalance = await client.getBalance({ address: recipient })
    
    console.log(`Sender: ${formatEther(newSenderBalance)} ETH`)
    console.log(`Recipient: ${formatEther(newRecipientBalance)} ETH`)
    
  } catch (error) {
    console.error('[ERROR] Transaction failed:', error.message)
  }
  
  // Keep watching for a few seconds
  console.log('\n[WATCH] Watching for more shreds (10 seconds)...')
  
  setTimeout(() => {
    unwatch()
    console.log('\n[COMPLETE] Quickstart complete!')
    process.exit(0)
  }, 10000)
}
 
// Run the quickstart
main().catch(console.error)

Run the Application

Execute the quickstart:

npx tsx quickstart.ts

You should see output like:

[START] RISE Chain Quickstart
 
[INFO] Checking initial balances...
Sender: 10000.0 ETH
Recipient: 10000.0 ETH
 
[SUBSCRIBE] Subscribing to real-time updates...
 
[SEND] Sending 0.1 ETH with instant confirmation...
[SHRED] New shred detected!
   Index: 1234...
   Transactions: 1
   Timestamp: 2:34:56 PM
 
[SUCCESS] Transaction confirmed in 4ms!
[RECEIPT] Transaction details:
   Block: 1234567
   Gas used: 21000
   Status: Success
 
[INFO] Checking updated balances...
Sender: 9999.899... ETH
Recipient: 10000.1 ETH
 
[WATCH] Watching for more shreds (10 seconds)...

What Just Happened?

  1. Instant Confirmation: The transaction confirmed in ~4ms, not minutes
  2. Real-Time Updates: Balances reflected the change immediately
  3. Shred Subscription: We received the shred notification in real-time
  4. Full Compatibility: Standard viem methods worked seamlessly

Next Steps

Enhance the Application

Try these modifications:

  1. Batch Transactions: Send multiple transactions rapidly
  2. Event Monitoring: Watch for specific smart contract events
  3. Balance Streaming: Display continuously updating balances
  4. Error Recovery: Add retry logic for failed transactions

Example: Continuous Balance Monitor

balance-monitor.ts
async function monitorBalance(address: string) {
  let lastBalance = await publicClient.getBalance({ address })
  console.log(`Starting balance: ${formatEther(lastBalance)} ETH`)
  
  // Check every 100ms for changes
  setInterval(async () => {
    const balance = await publicClient.getBalance({ address })
    if (balance !== lastBalance) {
      const change = balance - lastBalance
      console.log(`Balance changed: ${formatEther(change)} ETH`)
      console.log(`New balance: ${formatEther(balance)} ETH`)
      lastBalance = balance
    }
  }, 100)
}

Deploy a Smart Contract

deploy-contract.ts
import { deployContract } from 'viem'
 
const hash = await deployContract(walletClient, {
  abi: contractAbi,
  bytecode: contractBytecode,
  args: [constructorArg1, constructorArg2],
})
 
// Contract is deployed instantly!
const receipt = await publicClient.getTransactionReceipt({ hash })
console.log('Contract address:', receipt.contractAddress)

Learn More

Get Help

Congratulations! You've built your first real-time blockchain application with RISE Chain. The instant confirmations and real-time updates open up entirely new possibilities for blockchain applications.