Smart Contracts & Solidity

Chapter 7
Decentralized Application Integration

Advance Diploma in Blockchain
Smart Contracts & Solidity   •   Advance Diploma

Decentralized Application Integration

Introduction and Context

A decentralized application (dApp) is an application whose important business rules or state transitions are implemented by blockchain smart contracts. Unlike a conventional web application, a dApp usually combines four layers: a user interface, a wallet, blockchain contracts, and supporting off-chain infrastructure such as RPC providers, indexers and decentralized storage.

The integration problem is therefore broader than calling a function. A professional dApp must identify the correct contract and network, encode and decode calls through an ABI, distinguish read operations from signed transactions, manage wallet permissions, display transaction and event states, handle unreliable infrastructure, and protect users from misleading or irreversible actions.

A useful architectural principle is:

The blockchain is the authoritative source for contract state, while the front end is a coordinated interface for observing state and requesting authorized state transitions.

This chapter examines how these layers work together using common Web3 libraries and design practices. Examples use TypeScript-style pseudocode and concepts applicable to Ethereum-compatible networks.

Learning Objectives

By the end of this chapter, a learner should be able to:

  1. Explain the roles of wallets, providers, signers, ABIs, RPC endpoints and indexers.
  2. Connect a front end to a deployed Solidity contract safely.
  3. Distinguish read-only calls from transactions requiring signatures and gas.
  4. Implement transaction-status and event-handling workflows.
  5. Select suitable RPC, indexing and off-chain-storage strategies.
  6. Design usable, secure and resilient dApp interfaces.
  7. Evaluate an integration architecture through a practical case.

1. The dApp Integration Model

A typical interaction passes through the following sequence:

  1. The user opens a web or mobile interface.
  2. The application obtains a read-only RPC provider.
  3. The user connects a wallet, such as a browser wallet or mobile wallet.
  4. The wallet exposes an account and a signing interface.
  5. The front end constructs a contract call using the contract address and ABI.
  6. A read call is executed directly, or a transaction request is sent to the wallet.
  7. The wallet displays the transaction and the user approves or rejects it.
  8. The transaction is broadcast through an RPC endpoint.
  9. Validators or miners include it in a block.
  10. The application observes the receipt and emitted events, then refreshes its view.
Architecture of a decentralized application integration User interfaceReact / mobile Walletaccount + signer RPC providerread / broadcast Smart contractaddress + ABI Indexerqueries/events Storagemetadata/files
Architecture of a decentralized application integration
Figure: Architecture of a decentralized application integration

Figure: Principal components and information flows in a decentralized application.

The ABI is the formal interface between application code and a contract. It specifies function names, parameters, return types, mutability, and event definitions. The ABI does not contain the contract's source code or guarantee that an address contains the expected bytecode. Consequently, an application must treat the address, chain identifier and ABI as a versioned deployment configuration.

2. Providers, Wallets and Signers

Providers and RPC

An RPC provider is an interface through which software communicates with a blockchain node. Common read operations include retrieving blocks, balances, transaction data, contract state and logs. Write operations submit signed transactions for propagation.

A provider may be:

  • Public: convenient but potentially rate-limited and less predictable.
  • Managed: operated by a commercial infrastructure provider with monitoring and service-level features.
  • Self-hosted: offers greater control but requires operational expertise, synchronization and maintenance.

A robust application commonly uses more than one endpoint or a provider service with failover. It should verify the connected chain identifier rather than trusting a network name supplied by the interface.

Wallets and accounts

A wallet manages private keys and presents accounts to applications. The front end should request only the permissions it needs. Connecting an account is not the same as authorizing a transaction: a wallet may expose an address while still requiring approval for every signature.

A wallet can sign:

  • transactions that change blockchain state;
  • messages used for authentication or off-chain authorization;
  • typed structured data, often using EIP-712, for clearer signing semantics.

Private keys must never be placed in browser source code, local storage controlled by an untrusted application, or a server-side configuration file without a carefully designed custody model.

Signers

A signer is the software abstraction capable of authorizing a transaction or message. A provider can read state, but a signer is required for a user-approved state change. In ethers-style code, a provider may be connected to a signer supplied by a wallet:

const provider = new BrowserProvider(window.ethereum);
await provider.send("eth_requestAccounts", []);
const signer = await provider.getSigner();
const contract = new Contract(address, abi, signer);

The application should handle rejected connections, account changes, chain changes and wallets that do not implement every requested method.

3. ABI-Based Contract Interaction

A contract instance generally needs three items:

ItemPurposeTypical risk
AddressIdentifies the deployed contractWrong network or malicious address
ABIDefines encoding and decodingStale or incomplete interface
Provider or signerSupplies read or write capabilityUnexpected account or RPC endpoint

A read-only function such as balanceOf can be called without a signature. A state-changing function such as transfer produces a transaction and normally requires gas. Solidity's view and pure modifiers describe intended EVM behavior, but the practical front-end distinction is whether the call is executed locally through an RPC simulation or submitted as a transaction.

Example read operation:

const token = new Contract(tokenAddress, tokenAbi, provider);
const rawBalance = await token.balanceOf(account);

Blockchain numeric values should be treated as integers with explicit units. Token balances are commonly represented in the smallest denomination. If a token has d decimals and the raw integer balance is B, its display quantity is:

Q = B ÷ 10d

Here, B is an integer number of base units, d is the token's decimal precision, and Q is the human-readable quantity. This conversion is a display convention, not a change to the on-chain value. Applications should use arbitrary-precision integer types such as bigint, not JavaScript floating-point numbers, for raw token amounts.

Example transaction:

const token = new Contract(tokenAddress, tokenAbi, signer);
const amount = parseUnits("25.50", 6);
const tx = await token.transfer(recipient, amount);
showPending(tx.hash);
const receipt = await tx.wait();

The interface should validate the recipient address, amount, network and token before asking for a signature. It should not represent a transaction as successful merely because the wallet returned a hash.

Gas estimation and transaction preparation

A front end may request an estimated gas limit, but estimation is not a guarantee. Contract state can change between estimation and execution, and a transaction can still revert. Fee markets also change over time. The wallet should generally remain responsible for presenting current fee information, while the application explains the expected action and any protocol-specific limits.

A transaction can have several states: not started, awaiting wallet approval, submitted, pending, confirmed, reverted, replaced or dropped. These states should be visible and should not be collapsed into a single “success” flag.

4. Events, Logs and Application State

Solidity events create EVM logs. An event may be declared as follows:

event Deposit(address indexed account, uint256 amount);

The indexed qualifier places a value in a searchable topic. Non-indexed values remain in log data. Events are useful for discovering that an action occurred, but they are not a substitute for contract storage: contracts cannot generally read their own historical event logs as state.

A front end can listen for new events:

contract.on("Deposit", (account, amount, event) => {
  updateActivity({ account, amount, txHash: event.log.transactionHash });
});

Live subscriptions are useful for immediate feedback but are not sufficient for correctness. WebSocket connections can fail, a user can reload the page, and a chain can reorganize. A reliable application combines:

  1. an initial state query;
  2. event or block subscriptions where available;
  3. periodic reconciliation with confirmed contract state;
  4. a reorganization policy, such as waiting for a chosen number of confirmations for high-value actions.

A receipt indicates inclusion and execution result. A successful receipt means the transaction executed without reverting on the canonical chain observed by the provider; it does not imply that every off-chain indexer has already processed the event.

5. Indexing and Query Architecture

Direct RPC calls are suitable for current values and simple lookups. They become inefficient when the interface must answer historical questions such as “show all transfers involving this account,” especially when the contract has emitted many events.

An indexer consumes blocks and logs, decodes events, and stores queryable representations. It may expose a GraphQL or REST API. Some systems use a subgraph-like model; others use a custom database and ingestion service.

Important indexing concerns include:

  • Finality: whether data is provisional or sufficiently confirmed.
  • Idempotence: whether processing the same block twice produces the same result.
  • Reorganizations: whether records can be rolled back or marked non-final.
  • Schema evolution: how contract upgrades and new event versions are represented.
  • Provenance: whether each record retains block number, block hash, transaction hash and log index.

A useful event identity is often the tuple (chainId, transactionHash, logIndex), although an implementation should account for reorganization and replacement policies. Indexed data is a derived view, not an independent source of truth. Critical displays should be reconciled against the contract when appropriate.

6. Off-Chain Storage

Blockchains are expensive and deliberately constrained environments. Large documents, images and changing metadata are commonly stored off-chain, while the contract stores a content identifier, hash, or URI.

Possible choices include:

Storage approachStrengthLimitation
Centralized object storageFast, familiar operationsProvider dependency and mutable availability
Content-addressed decentralized storageIdentifier relates to contentPinning, retrieval and permanence require operational planning
Decentralized archival networksLong-term persistence modelCost and retrieval assumptions vary
Application databaseEfficient queries and access controlNot independently verifiable as blockchain state

If a content hash h is stored on-chain, the application can retrieve a file and verify that its digest equals h. The security value depends on using a suitable cryptographic hash and verifying the exact bytes, not merely trusting a filename or URL. A URI is a locator or identifier; it is not automatically proof that content is authentic, available, or permanent.

Personal data requires special care. Public blockchains and many decentralized storage systems are difficult or impossible to erase. Developers should avoid putting unnecessary personal information on-chain and should consider encryption, key management, consent, retention and applicable data-protection law. Encryption does not remove all legal or operational responsibilities, because keys may be lost, compromised or linkable to individuals.

7. User Experience and Failure Design

Blockchain UX differs from ordinary web UX because actions may be delayed, irreversible and dependent on an external wallet. A mature interface should:

  • identify the active network and account clearly;
  • distinguish simulation, signature and broadcast stages;
  • show human-readable amounts and the underlying token precision;
  • explain why a signature is requested;
  • provide a transaction explorer link only for the correct network;
  • allow safe cancellation of local workflows, while explaining that broadcast transactions cannot usually be cancelled by the interface;
  • report rejected, reverted, underpriced, expired and unsupported-wallet states;
  • avoid pretending that an optimistic update is final;
  • preserve useful context after page reloads.

Optimistic and confirmed interfaces

An optimistic interface updates immediately after submission, improving responsiveness but risking inconsistency if the transaction fails. A confirmed interface waits for a receipt, improving accuracy but increasing perceived latency. A hybrid approach is often best: show the action as “pending,” display a provisional local result where harmless, and replace it with confirmed state after reconciliation.

Accessibility is also a decentralization concern. Users should not need to understand raw hexadecimal data to avoid serious mistakes. Interfaces should provide keyboard navigation, sufficient contrast, screen-reader labels, plain-language explanations and a non-wallet demonstration mode where feasible.

8. Security and Governance Considerations

Contract and address integrity

The front end should load deployment data from a controlled, versioned configuration. It should verify chain identifiers, reject unsupported networks and, where practical, compare deployed bytecode or verified deployment metadata. A user can be connected to a legitimate wallet but still be interacting with a counterfeit contract address.

Signature safety

Message signing can be abused when users cannot see what they are authorizing. Typed structured data can present fields such as domain, purpose, spender and deadline. Applications should use domain separation, short expirations and nonce management where applicable. A signature is not harmless merely because it does not pay gas; it may authorize a later transfer or permit.

Front-end supply chain

A smart contract may be immutable while its website is not. Compromised dependencies, DNS records, hosting accounts or update pipelines can substitute a malicious address or transaction. Use dependency review, reproducible builds, content-security controls, deployment approvals, monitoring and independent verification of release artifacts.

Privacy and compliance

Wallet addresses are pseudonymous identifiers, not guaranteed anonymity. Combining addresses with IP addresses, identity records or analytics can create personal-data profiles. Applications should minimize collection, publish clear disclosures, protect logs and consider jurisdiction-specific financial, consumer-protection, sanctions and data-protection requirements. Legal classification depends on the application, assets, users and jurisdiction; technical decentralization does not automatically remove regulatory duties.

9. Applied Case: Illustrative Community Grant dApp

Background

Consider a fictional community grant dApp in which members submit proposals and vote using a governance token. Proposal descriptions and supporting documents are stored off-chain. The contract records proposal identifiers, voting periods, vote totals and execution outcomes.

Problem

The first prototype directly queried the contract for every proposal on each page load. It displayed a successful message immediately after a wallet returned a transaction hash. Users sometimes saw stale vote totals, duplicate activity entries and misleading success messages after reverted transactions.

Analysis

The application had four architectural weaknesses:

  1. It lacked a historical query layer.
  2. It treated submission as confirmation.
  3. It did not preserve event provenance.
  4. It did not validate that the wallet's chain matched the deployment.

Approach and solution

The team introduced a deployment manifest containing chain ID, contract address, ABI version and metadata schema. A read-only provider loaded current proposal state. A signer was attached only after the user connected a wallet and selected the supported network.

The voting workflow became:

  1. Validate proposal ID, voting eligibility and active period through a read call.
  2. Present the action, token amount and target chain.
  3. Ask the wallet to simulate or estimate the transaction where supported.
  4. Mark the interface as awaiting approval.
  5. After broadcast, store the transaction hash locally and display “pending.”
  6. Wait for a receipt and inspect its status.
  7. Process VoteCast events through an idempotent indexer.
  8. Re-query the proposal after confirmation and display the block and transaction references.

The indexer stored chain ID, block number, block hash, transaction hash, log index, proposal ID, voter and vote weight. It marked recent records as provisional until the application's confirmation policy was met. The front end showed indexer data for history but used contract reads for critical current eligibility checks.

Proposal documents were stored using content-addressed identifiers. The contract stored the identifier and a metadata version. The interface verified retrieved content against the expected identifier and warned users when content was unavailable rather than silently displaying an empty document.

Outcome

The revised system reduced unnecessary RPC queries, made pending and failed actions understandable, and allowed historical activity to load quickly. It did not eliminate all risk: RPC outages, chain reorganizations, malicious proposals and unavailable off-chain files remained possible. The team therefore documented these limitations and provided links to contract addresses, source code and transaction evidence.

Learning points

The case illustrates that integration quality is determined not only by successful contract calls. Correct deployment configuration, explicit lifecycle states, event provenance, reconciliation and honest communication are equally important.

10. Contemporary Developments

Several developments are changing dApp integration:

  • Account abstraction: smart-contract accounts can support programmable validation, recovery and sponsored transactions, although wallet and infrastructure support remains uneven.
  • Layer-2 networks: lower fees and higher throughput introduce chain selection, bridging, sequencer and withdrawal considerations.
  • Wallet interoperability standards: common provider and signing interfaces reduce dependence on a single wallet implementation.
  • Zero-knowledge systems: privacy-preserving proofs can reduce disclosure, but applications must explain what is proven and what remains public.
  • AI-assisted interfaces: AI can help summarize proposals or explain transaction data, but it must not fabricate contract state. Critical values should be obtained from verified chain data, and AI-generated recommendations should remain distinguishable from authoritative protocol results.

These developments improve capability but increase integration complexity. A design should adopt them only when their trust, usability and operational requirements are understood.

Best-Practice Checklist

Before production release, verify that the application:

  1. Uses a versioned address, ABI and chain configuration.
  2. Separates read-only providers from signing capabilities.
  3. Validates chain ID, account and recipient data.
  4. Uses arbitrary-precision types for token values.
  5. Distinguishes wallet approval, submission, confirmation and failure.
  6. Reconciles events with contract state.
  7. Handles RPC, wallet, indexer and storage outages.
  8. Preserves event provenance and reorganization policy.
  9. Minimizes personal data and explains permanence.
  10. Audits front-end dependencies, deployment and signing flows.
  11. Provides accessible, comprehensible transaction explanations.
  12. Tests rejected signatures, reverted calls, account changes and network changes.

Chapter Summary

Decentralized application integration connects a user interface with wallets, RPC providers, smart contracts, indexers and off-chain storage. The ABI enables correct encoding and decoding, while the contract address and chain ID establish deployment identity. Providers support reading and broadcasting; signers authorize transactions and messages.

Read calls and state-changing transactions require different workflows. A transaction hash is evidence of submission, not successful execution. Receipts, events and reconciliation provide increasingly strong evidence, but applications must account for dropped transactions, provider failures and chain reorganizations. Indexers improve historical queries, while off-chain storage supports large content; neither replaces the blockchain as the authoritative source for contract state.

Professional dApps combine technical correctness with careful UX, security, privacy and governance. They explain signatures, display lifecycle states, protect keys, validate deployments, verify content identifiers and minimize irreversible mistakes. The central design principle is to make the boundary between user intent, wallet authorization, blockchain execution and derived off-chain views explicit.

Key Terms

ABI: Application Binary Interface describing contract functions, parameters, returns and events.

Account abstraction: A model that allows programmable account validation and transaction behavior.

Content identifier: A reference, often content-addressed, used to identify off-chain data.

Event: A Solidity declaration that produces searchable blockchain logs.

Finality: The degree of confidence that a blockchain record will not be reversed.

Gas: The computational resource consumed by EVM execution.

Indexer: Infrastructure that converts blocks and events into queryable data.

Log: An EVM record emitted during transaction execution.

Nonce: A sequence value used to order transactions or prevent signature replay, depending on context.

Off-chain storage: Data storage outside contract state, linked through identifiers or hashes.

Optimistic update: A provisional interface update made before confirmed execution.

Provider: A software interface to blockchain node and RPC services.

Receipt: A record containing transaction execution and inclusion information.

Reorganization: A change in the observed canonical chain that can invalidate provisional records.

RPC: Remote Procedure Call interface for communicating with blockchain nodes.

Signer: A software component capable of authorizing transactions or messages.

Smart contract: Programmed blockchain logic that controls state and execution rules.

Transaction lifecycle: The stages from user approval through submission, confirmation or failure.

Wallet: Software or hardware that manages keys and interacts with blockchain accounts.

Review Questions

Short Answer Questions

  1. What is the purpose of an ABI in a dApp?
  2. Why is a signer needed for most state-changing contract functions?
  3. What information does an event log provide?
  4. Why should raw token amounts be represented with arbitrary-precision integers?
  5. What is the difference between a provider and an indexer?

Long Answer Questions

  1. Explain the complete lifecycle of a wallet-based transaction from user intent to confirmed contract state.
  2. Compare direct RPC querying with indexed historical data, including the limitations of each approach.
  3. Discuss how a dApp should use off-chain storage while preserving verifiability and respecting privacy.
  4. Explain the main security risks associated with contract addresses, signatures and front-end supply chains.
  5. Design a user-experience policy for pending, reverted, rejected and reorganized transactions.

Analytical / Application Questions

  1. A user sees a successful wallet transaction hash, but the contract state has not changed. Diagnose at least four possible causes and propose an interface response for each.
  2. Design an integration architecture for a tokenized document registry. Specify what belongs on-chain, what belongs off-chain, how documents are verified, and how historical records are indexed.
  3. Evaluate whether an optimistic balance update is appropriate for a high-value governance vote. Consider user expectations, reverts, finality, reorganization and reconciliation.

Multiple Choice Questions with Answers

Question 1

Which component is primarily responsible for encoding contract calls and decoding returned values?

A. ABI

B. Indexer

C. Wallet seed phrase

D. Block explorer

Correct Answer: A. ABI

Question 2

What is normally required to authorize a state-changing transaction from a user's account?

A. A read-only provider only

B. A signer connected to the user's wallet

C. An event listener only

D. An off-chain image store

Correct Answer: B. A signer connected to the user's wallet

Question 3

Why should a dApp not treat a returned transaction hash as proof of successful execution?

A. A hash cannot identify a transaction

B. A transaction may still be pending or may revert

C. Hashes are only used for off-chain files

D. Wallets never return hashes

Correct Answer: B. A transaction may still be pending or may revert

Question 4

If a token has 6 decimals and its raw balance is 25,500,000 base units, what display quantity is represented?

A. 0.0255 tokens

B. 2.55 tokens

C. 25.5 tokens

D. 255 tokens

Correct Answer: C. 25.5 tokens

Question 5

What is a principal advantage of an indexer?

A. It changes contract storage without gas

B. It provides efficient queries over historical events

C. It replaces the need for contract security

D. It stores users' private keys

Correct Answer: B. It provides efficient queries over historical events

Question 6

Which statement about off-chain storage is most accurate?

A. A URI automatically proves permanent availability

B. Off-chain data can be linked to an on-chain content identifier or hash

C. Off-chain data is always private

D. Large files should always be stored directly in contract state

Correct Answer: B. Off-chain data can be linked to an on-chain content identifier or hash

Question 7

What should an application do when the wallet is connected to an unsupported chain?

A. Silently submit the transaction to the deployment chain

B. Treat the network as valid if the account is correct

C. Clearly identify the mismatch and request a supported network

D. Replace the user's wallet

Correct Answer: C. Clearly identify the mismatch and request a supported network

Question 8

Why are event subscriptions alone insufficient for reliable application state?

A. Events cannot contain any data

B. Connections can fail and chains can reorganize

C. Events are never emitted by Solidity

D. Subscriptions automatically modify contract state

Correct Answer: B. Connections can fail and chains can reorganize

Question 9

Which practice best protects users from misleading signatures?

A. Hide all signing details

B. Use clear, structured signing data with purpose and expiry where appropriate

C. Request unlimited permissions for every action

D. Store private keys in front-end source code

Correct Answer: B. Use clear, structured signing data with purpose and expiry where appropriate

Question 10

Which value is especially important for preserving the provenance of an indexed event?

A. The user's screen resolution

B. The transaction hash and log index

C. The CSS framework version only

D. The browser's color scheme

Correct Answer: B. The transaction hash and log index

Smart Contracts & Solidity
Chapter 7 of 15