@jim4565/dapp-wrapper
v1.5.0
Published
An abstraction layer over the Incentiv dApp SDK for simplified dApp development
Maintainers
Readme
Incentiv dApp-Wrapper
A minimized, focused wrapper around the Incentiv dApp SDK for core blockchain interactions.
Features
- Core Blockchain Functions:
connect,getProvider,getSigner,getUserAddress,isConnected - Smart Contract Integration: Register contracts and call methods with simplified API
- Single Instance: One wrapper instance across your entire frontend application
- TypeScript Support: Full type safety with comprehensive interfaces
- Error Handling: Specific error codes and user-friendly messages
Installation
npm install @jim4565/dapp-wrapperPeer Dependencies
npm install @incentiv/dapp-sdk ethersQuick Start
Basic Setup
import { IncentivWrapper } from '@jim4565/dapp-wrapper';
// 1. Create wrapper (network configuration is built-in)
const wrapper = new IncentivWrapper();
// 2. Connect to wallet (triggers Incentiv Portal popup)
const userAddress = await wrapper.connect();
// 3. Register contracts (only way to add contracts)
wrapper.registerContract("SOLO", "0x1234...", yourABI);Perfect API Usage
// Your preferred API - exactly as you described!
// Directly call contract methods - transactions are sent automatically!
const receipt = await wrapper.getContract("SOLO").playGame(true);
// View/pure functions return values directly
const gameDetails = await wrapper.getContract("SOLO").getGameDetails(1);
const balance = await wrapper.getContract("SOLO").getBalance();
// State-changing functions return transaction receipt
const txReceipt = await wrapper.getContract("SOLO").deposit(100);
console.log('Transaction hash:', txReceipt.hash);
// Payable functions with ETH value (only works with payable functions!)
const gameReceipt = await wrapper.getContract("SOLO").playGame(true).withValue("0.1");
const depositReceipt = await wrapper.getContract("SOLO").deposit(100).withValue("3");
// Wait for confirmation
const confirmedReceipt = await txReceipt.wait();
console.log('Confirmed in block:', confirmedReceipt.blockNumber);
// Core functions
const provider = wrapper.getProvider();
const signer = wrapper.getSigner();
const address = wrapper.getUserAddress();
const connected = await wrapper.isConnected();Global Usage Pattern
Use one wrapper instance across your entire frontend:
// services/blockchain.ts
export class BlockchainService {
private static instance: IncentivWrapper;
static getInstance(): IncentivWrapper {
if (!BlockchainService.instance) {
BlockchainService.instance = new IncentivWrapper();
// Register contracts after creation
BlockchainService.instance.registerContracts([
{ name: "Game", address: "0x123...", abi: gameABI },
{ name: "Token", address: "0x456...", abi: tokenABI }
]);
}
return BlockchainService.instance;
}
}
// In any component
const wrapper = BlockchainService.getInstance();Wallet Connection
The wrapper provides multiple ways to connect to the Incentiv wallet:
Standard Connection
try {
const userAddress = await wrapper.connect();
console.log('Connected as:', userAddress);
} catch (error) {
if (error.code === 'USER_REJECTED') {
console.log('User rejected wallet connection');
}
}Alternative Connection Methods
// Force fresh connection (clears existing session)
const address = await wrapper.connectFresh();Connection Status
// Check if already connected
const isConnected = await wrapper.isConnected();
// Get current user address
const userAddress = wrapper.getUserAddress();
API Reference
Core Methods
connect(): Connect to wallet (triggers Incentiv Portal popup)connectFresh(): Force fresh wallet connectiongetProvider(): Get ethers providergetSigner(): Get current signergetUserAddress(): Get connected user addressisConnected(): Check connection statuscreateSigner(address): Create new signer instance
Contract Management
registerContract(name, address, abi): Register a single contractregisterContracts(contracts[]): Register multiple contractsgetRegisteredContracts(): Get list of all registered contract nameshasContract(name): Check if a contract is registeredgetContractAddress(name): Get contract address by namegetContractMethods(name): Get all function names for a contractgetContract(name): Get contract instance by name
Contract Access
Contracts are accessed through the getContract() method for better encapsulation:
// Get contract instance
const soloContract = wrapper.getContract("SOLO");
// Check if contract exists
if (!soloContract) {
console.log("Contract not found!");
return;
}
// Access contract properties
console.log(soloContract.address);
console.log(soloContract.abi);
// Direct method calls - automatically sends transactions or reads state
const txReceipt = await wrapper.getContract("SOLO").playGame(true);
console.log('Transaction sent:', txReceipt.hash);
// With ETH value for payable functions
const payableReceipt = await wrapper.getContract("SOLO").playGame(true).withValue("0.1");
console.log('Payable transaction sent:', payableReceipt.hash);
// Alternative: Store contract reference for multiple uses
const game = wrapper.getContract("SOLO");
const gameReceipt = await game.playGame(true);
const gameWithValue = await game.deposit(100).withValue("3");
const gameStatus = await game.getGameStatus(); // Returns value directly for view functionsValidation Rules
withValue() Usage
The withValue() method has strict validation rules:
// ✅ Correct usage - only on payable functions
const receipt = await wrapper.getContract("Game").deposit(100).withValue("1.0");
// ❌ This will throw an error - view functions cannot receive ETH
try {
await wrapper.getContract("Game").getBalance().withValue("1.0");
} catch (error) {
console.error(error.message);
// "Cannot use withValue() on function 'getBalance' with stateMutability 'view'. Only 'payable' functions accept ETH value."
}
// ❌ This will throw an error - nonpayable functions cannot receive ETH
try {
await wrapper.getContract("Game").updateSettings().withValue("1.0");
} catch (error) {
console.error(error.message);
// "Cannot use withValue() on function 'updateSettings' with stateMutability 'nonpayable'. Only 'payable' functions accept ETH value."
}
// ❌ This will throw an error - invalid ETH value
try {
await wrapper.getContract("Game").deposit(100).withValue("-1.0");
} catch (error) {
console.error(error.message);
// "Invalid ETH value '-1.0'. Value must be a positive number."
}Error Handling
try {
// Direct method call - automatically sends transaction
const result = await wrapper.getContract("Game").playGame(player, bet);
console.log('Game transaction:', result.hash);
// With ETH value for payable functions only
const payableResult = await wrapper.getContract("Game").deposit(100).withValue("1.5");
console.log('Payable transaction:', payableResult.hash);
// This will throw an error - withdraw is not payable!
// const errorResult = await wrapper.getContract("Game").withdraw().withValue("1.0");
// Wait for confirmation
const receipt = await result.wait();
console.log('Confirmed in block:', receipt.blockNumber);
} catch (error) {
if (error.code === 'WALLET_NOT_CONNECTED') {
// Handle not connected
} else if (error.code === 'USER_REJECTED') {
// Handle user rejection
} else if (error.code === 'INSUFFICIENT_FUNDS') {
// Handle insufficient funds
} else if (error.message.includes('Only \'payable\' functions')) {
// Handle incorrect withValue() usage
console.error('Cannot send ETH to non-payable function');
} else if (error.message.includes('Invalid ETH value')) {
// Handle invalid ETH value
console.error('ETH value must be a positive number');
}
}TypeScript Support
Full TypeScript support with interfaces:
import {
IncentivWrapper,
TransactionResponse
} from '@jim4565/dapp-wrapper';
// Simple creation - network is pre-configured
const wrapper = new IncentivWrapper();License
MIT License - see LICENSE file for details.
Support
- GitHub Issues: Repository Issues
- NPM Package: @jim4565/dapp-wrapper
