Quickstart
Build your first realtime application in 15 minutes
Quickstart
Build a realtime payment application using RISE's Shred API in under 15 minutes. This tutorial will demonstrate instant transaction confirmations and realtime balance updates.
What We'll Build
A simple payment application that:
- Sends instant payments with immediate confirmation
- Displays realtime balance updates
- Shows live transaction history
- Demonstrates shred subscriptions
Prerequisites
- Node.js 16+ installed
- Basic TypeScript/JavaScript knowledge
- A code editor (VS Code recommended)
Project Setup
Create a New Project
mkdir rise-quickstart
cd rise-quickstart
npm init -yInstall Dependencies
npm install shreds viem dotenv
npm install -D typescript tsx @types/nodepnpm add shreds viem dotenv
pnpm add -D typescript tsx @types/nodeyarn add shreds viem dotenv
yarn add -D typescript tsx @types/nodebun add shreds viem dotenv
bun add -D typescript tsx @types/nodeConfigure TypeScript
Create tsconfig.json:
{
"compilerOptions": {
"target": "ES2020",
"module": "ESNext",
"moduleResolution": "bundler",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"resolveJsonModule": true
}
}Set Up Environment
Create .env:
# RISE Testnet RPC endpoints
RISE_RPC_URL=https://testnet.riselabs.xyz
RISE_WS_URL=wss://testnet.riselabs.xyz/ws
# Test wallet (has testnet tokens)
PRIVATE_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80This is a well-known test private key. Never use it for real funds!
Build the Application
Create 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(process.env.RISE_RPC_URL)
}).extend(shredActions)
// Recipient address
const recipient = '0x70997970C51812dc3A010C7d01b50e0d17dc79C8'
async function main() {
console.log('[START] RISE 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 realtime updates
console.log('[SUBSCRIBE] Subscribing to realtime updates...\n')
const wsClient = createPublicClient({
chain: riseTestnet,
transport: webSocket(process.env.RISE_WS_URL)
}).extend(shredActions)
const unwatch = wsClient.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(Number(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 hash = await client.sendTransactionSync({
to: recipient,
value: parseEther('0.1'),
})
const confirmTime = Date.now() - startTime
console.log(`[SUCCESS] Transaction confirmed in ${confirmTime}ms!`)
console.log(`[HASH] ${hash}\n`)
// 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.tsYou should see output like:
[START] RISE Quickstart
[INFO] Checking initial balances...
Sender: 10000.0 ETH
Recipient: 10000.0 ETH
[SUBSCRIBE] Subscribing to realtime 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!
[HASH] 0x...
[INFO] Checking updated balances...
Sender: 9999.899... ETH
Recipient: 10000.1 ETH
[WATCH] Watching for more shreds (10 seconds)...What Just Happened?
- Instant Confirmation: The transaction confirmed in ~4ms, not minutes
- Realtime Updates: Balances reflected the change immediately
- Shred Subscription: We received the shred notification in realtime
- Full Compatibility: Standard viem methods worked seamlessly
Next Steps
Enhance the Application
Try these modifications:
- Batch Transactions: Send multiple transactions rapidly
- Event Monitoring: Watch for specific smart contract events
- Balance Streaming: Display continuously updating balances
- Error Recovery: Add retry logic for failed transactions
Learn More
- API Methods - Core Shred API methods
- Watching Events - Realtime subscriptions