Build with Fairside
Decentralized membership-based coverage protocol. Integrate our REST API and smart contracts to offer wallet protection in your dApp.
Choose Your Integration Method
Integrate Fairside Protocol using our Web SDK for quick setup, or use the Direct API for full control.
Web SDK
Pre-built components and utilities for rapid integration. Handles authentication and contract interactions.
- Simplified API wrappers
- TypeScript support
- Purchase on Abstract chain
Direct API Integration
Full control with REST API and smart contract calls. For custom implementations.
- Purchase on multiple chains
- REST API for user management
- Direct smart contract calls
- Any language/framework
Referral Links
No code required. Share your referral link and earn ETH commissions on every purchase.
- Earn % on purchases
- Unique referral code
- Track signups & earnings
- Claim rewards in ETH
Two Payment Methods
Native Payment (Abstract Chain)
Your integration sends the transaction. Users pay directly on the Abstract network using ETH. You call the smart contract's purchaseMembership function and submit the transaction on behalf of the user.
- User signs transaction via their wallet
- Transaction sent to Abstract chain (Chain ID: 2741)
- Your integration handles contract interaction
- Immediate on-chain confirmation
Crypto Payment (NowPayments)
Fairside manages the transaction. Users pay with supported cryptocurrencies (BTC, USDT, USDC, etc.). They simply send tokens to a generated wallet address. Fairside handles the on-chain membership purchase automatically.
- User sends tokens to provided address
- Supports BTC, ETH, USDT, USDC, and more
- Fairside executes on-chain purchase
- No Abstract chain interaction required
API Endpoints
| Environment | Base URL |
|---|---|
| TestNet | https://api.test.fairside.dev/v1 |
| MainNet | https://api.fairside.io/v1 |
Contract Addresses (Abstract Chain)
Required only for Native Payment method. These are the FairSideNetwork contract addresses on Abstract chain.
| Environment | Chain ID | FairSideNetwork Contract | RPC URL |
|---|---|---|---|
| TestNet | 11124 | 0xCC484a76566e5cc6d4678D08c3214149f275A673 |
https://api.testnet.abs.xyz |
| MainNet | 2741 | 0x17aD4490A9181cf01F2Be059765d4f2d8Ee6d8a0 |
https://api.mainnet.abs.xyz |
Wallet-Based Auth Flow
Authenticate users by signing a message with their wallet. All API requests require an API key.
Request Auth Message
Generate a unique message for the user to sign
{
"walletAddress": "0xYourWalletAddress"
}
{
"authMessage": {
"nonce": "a1b2c3d4-e5f6-...",
"walletAddress": "0xYourWalletAddress",
"message": "Welcome to Fairside! ..."
}
}
The message field contains the full text to sign, including wallet address and nonce.
Sign Message
User signs the authMessage.message with their wallet
// Sign the message from the auth response
const signature = await signer.signMessage(authMessage.message);
Login & Get JWT
Submit signature with the nonce to receive authentication token
{
"walletAddress": "0xYourWalletAddress",
"nonce": "a1b2c3d4-e5f6-...",
"signature": "0xSignedMessageHash...",
"referralCode": "REFERRAL_CODE"
}
Required Headers
api-key
Your API key (required for all requests)
Authorization
Bearer token for authenticated endpoints
Coverage Management
Check coverage status, manage wallets, and handle membership operations through the API.
/membership/check-cover/{walletAddress}
Public
Check if a wallet has active coverage. No authentication required.
{
"statusCode": 200,
"hasCover": true,
"isActive": true,
"validFrom": "2024-01-01T00:00:00.000Z",
"validUntil": "2025-01-01T00:00:00.000Z",
"coverAmount": 5,
"coverID": 42,
"activeClaims": []
}
/membership/wallets
Auth Required
Retrieve the list of wallets covered under the user's membership.
/membership/add-wallet
Auth Required
Add additional wallets to an existing membership.
{
"walletAddresses": ["0xWallet1...", "0xWallet2..."],
"coverID": 42
}
/users/{walletAddress}
Auth Required
Retrieve the authenticated user's account information including membership details.
/users/terms/accept
Auth Required
Accept terms and conditions before purchasing membership.
/membership/top-up
Public
Record a top-up transaction after executing on-chain.
{
"coverID": 42,
"walletAddress": "0xWalletAddress...",
"coveredAmount": 2,
"transactionHash": "0xTransactionHash..."
}
Native Payment (Abstract Chain)
Purchase and manage memberships directly through the FairSideNetwork contract on Abstract chain. Your integration must send the transaction — users sign with their wallet, and you submit to the Abstract network.
purchaseMembership
payablefunction purchaseMembership(
uint256 costShareBenefit, // Amount in wei
address coverAddress, // Address to cover
uint256 membershipType // 0 for MainNet
) external payable
Purchase a new membership with the specified coverage amount.
estimateCost
viewfunction estimateCost(
uint256 costShareBenefit, // Amount in wei
uint256 accountDuration, // 0 for new membership
uint256 membershipTypeId // 0 for MainNet
) external view returns (uint256)
Calculate the required payment for a membership.
topupMembership
payablefunction topupMembership(
uint256 coverId,
uint256 costshareBenefit // Additional amount in wei
) external payable
Increase the coverage amount of an existing membership.
renewMembership
payablefunction renewMembership(
uint256 coverId,
uint256 costShareBenefit,
uint256 membershipTypeId
) external payable
Renew an expired or expiring membership.
getAccountMembership
viewfunction getAccountMembership(
address account
) external view returns (uint256[])
Get all cover IDs associated with an account.
getMembership
viewfunction getMembership(
uint256 coverId
) external view returns (Membership)
Get detailed membership information by cover ID.
Contract Events
NewMembership
event NewMembership(address indexed member, uint256 coverId, uint256 costshareBenefit, address indexed coverAddress, uint8 tokenType, uint256 membershipTypeId)
TopUpCover
event TopUpCover(address indexed member, uint256 coverId, uint256 costshareBenefit, uint8 tokenType)
RenewMembership
event RenewMembership(address indexed member, uint256 indexed coverId, uint256 costshareBenefit, uint8 tokenType)
Pay with Multiple Cryptocurrencies
Allow users to purchase memberships using Bitcoin, USDT, USDC, and other supported cryptocurrencies. Fairside handles the on-chain transaction — users simply send tokens to a generated wallet address on their preferred network.
Real-time Estimates
Get live exchange rates for supported cryptocurrencies. Shows exact amount needed in user's chosen currency.
Secure Payments
Time-limited payment windows, exact amount validation, and real-time transaction confirmation tracking.
Automatic Fulfillment
Once payment is confirmed, membership is automatically purchased on-chain via webhook processing.
/nowpayments/estimates
API Key Required
Get payment estimates for all supported cryptocurrencies based on coverage amount.
{
"coverAmount": 5
}
{
"coverAmount": 5,
"ethAmount": 0.0975,
"estimates": [
{
"currency": "btc",
"network": "btc",
"estimatedAmount": 0.00102345
},
{
"currency": "usdt",
"network": "eth",
"estimatedAmount": 195.50
},
{
"currency": "usdc",
"network": "eth",
"estimatedAmount": 195.45
}
]
}
/nowpayments/payments
Auth Required
Create a payment intention. Returns payment address and exact amount to send.
{
"coverAmount": 5,
"membershipTypeId": "0",
"paymentCurrency": "btc",
"paymentNetwork": "btc",
"paymentType": "new_purchase"
}
{
"paymentId": "550e8400-e29b-41d4-a716-446655440000",
"paymentAddress": "bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh",
"paymentAmount": 0.00102345,
"paymentCurrency": "btc",
"paymentNetwork": "btc",
"coverAmount": 5,
"coverCostAmount": 0.0975,
"expiresAt": "2024-01-15T12:30:00.000Z"
}
/nowpayments/payments/{paymentId}
Auth Required
Check the status of a payment. Poll this endpoint to track payment progress.
{
"paymentId": "550e8400-e29b-41d4-a716-446655440000",
"paymentStatus": "finished",
"membershipPurchaseStatus": "completed",
"membershipPurchaseTxHash": "0x1234...abcd",
"paymentCurrency": "btc",
"paymentNetwork": "btc",
"paymentAmount": 0.00102345,
"coverAmount": 5,
"coverCostAmount": 0.0975,
"createdAt": "2024-01-15T12:00:00.000Z",
"expiresAt": "2024-01-15T12:30:00.000Z"
}
/nowpayments/payments
Auth Required
List all payments for the authenticated user.
Payment Types
| Value | Description |
|---|---|
new_purchase |
New membership purchase |
topup |
Top-up existing membership coverage |
Payment Statuses
| Status | Description |
|---|---|
waiting |
Waiting for user to send payment |
confirming |
Payment received, waiting for confirmations |
confirmed |
Payment confirmed on blockchain |
finished |
Payment completed successfully |
partially_paid |
Partial amount received |
expired |
Payment window expired |
failed |
Payment failed |
Membership Purchase Statuses
| Status | Description |
|---|---|
pending |
Waiting for payment to complete |
completed |
Membership purchased on-chain |
failed |
On-chain purchase failed |
Crypto Payment Flow
Get Estimates
Fetch payment estimates for all supported cryptocurrencies
{ "coverAmount": 5 }
User Selects Currency
Display available currencies and let user choose their preferred payment method
Create Payment
Create payment intention with selected currency
{
"coverAmount": 5,
"membershipTypeId": "0",
"paymentCurrency": "btc",
"paymentNetwork": "btc",
"paymentType": "new_purchase"
}
Display Payment Details
Show user the payment address and exact amount to send. Include countdown timer for expiration.
Poll for Status
Poll payment status until completed or expired
// Poll every 5-10 seconds
// Stop when paymentStatus is "finished" or "expired"
Membership Created
When membershipPurchaseStatus is "completed", the membership has been purchased on-chain. The transaction hash is available in membershipPurchaseTxHash.
Supported Cryptocurrencies
The /nowpayments/estimates endpoint returns all currently supported currencies with their networks. Common options include:
BTC
Bitcoin (btc network)
ETH
Ethereum (eth network)
USDT
Tether
USDC
USD Coin
Earn with Referral Links
No integration required. Share your unique referral link and earn ETH commissions when users purchase memberships.
How It Works
Open Referral DashboardEvery Fairside user receives a unique referral code upon registration. Find it in your referral dashboard.
Share your referral link on social media, Discord, Telegram, or anywhere your audience is.
https://fairside.io?referralCode=YOUR_CODE
When users sign up and purchase memberships using your link, you earn a percentage of their purchase.
Track your earnings and claim your accumulated ETH rewards anytime from your dashboard.
What You Can Track
- Total signups from your link
- Users who purchased membership
- Total cover amount generated
- Total earnings in ETH
- Already claimed amount
- Claimable balance
Complete Integration Examples
Ready-to-use code examples for both payment methods: Native Payment (Abstract chain) and Crypto Payment (NowPayments).
import { ethers } from 'ethers';
const API_BASE_URL = 'https://api.fairside.io/v1';
const API_KEY = 'your-api-key';
const NETWORK_CONTRACT = '0x17aD4490A9181cf01F2Be059765d4f2d8Ee6d8a0';
// 1. Generate message to sign
const generateMessage = async (walletAddress) => {
const response = await fetch(`${API_BASE_URL}/auth/messages`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'api-key': API_KEY,
},
body: JSON.stringify({ walletAddress }),
});
return response.json();
};
// 2. Login with signed message
const login = async (walletAddress, nonce, signature) => {
const response = await fetch(`${API_BASE_URL}/auth/login`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'api-key': API_KEY,
},
body: JSON.stringify({ walletAddress, nonce, signature }),
});
const data = await response.json();
return data.jwtToken;
};
// 3. Accept terms
const acceptTerms = async (walletAddress, token) => {
await fetch(`${API_BASE_URL}/users/terms/accept`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'api-key': API_KEY,
'Authorization': `Bearer ${token}`,
},
body: JSON.stringify({ walletAddress }),
});
};
// 4. Check membership status
const checkMembership = async (walletAddress) => {
const response = await fetch(
`${API_BASE_URL}/membership/check-cover/${walletAddress}`,
{ headers: { 'api-key': API_KEY } }
);
return response.json();
};
// 5. Purchase membership on Abstract chain
const purchaseMembership = async (signer, coverAmount, coverAddress) => {
const networkContract = new ethers.Contract(
NETWORK_CONTRACT,
FairSideNetworkABI,
signer
);
const amountWei = ethers.parseEther(coverAmount.toString());
const fee = await networkContract.estimateCost(amountWei, 0, 0);
const tx = await networkContract.purchaseMembership(
amountWei,
coverAddress,
0, // MainNet membership type
{ value: fee }
);
return tx.wait();
};
// Main integration flow
async function main() {
const provider = new ethers.BrowserProvider(window.ethereum);
const signer = await provider.getSigner();
const walletAddress = await signer.getAddress();
// Auth flow
const { authMessage } = await generateMessage(walletAddress);
const signature = await signer.signMessage(authMessage.message);
const token = await login(walletAddress, authMessage.nonce, signature);
// Accept terms
await acceptTerms(walletAddress, token);
// Check if already has membership
const membershipStatus = await checkMembership(walletAddress);
if (membershipStatus.hasCover) {
console.log('Already has membership');
return;
}
// Purchase membership (5 ETH coverage)
const receipt = await purchaseMembership(signer, 5, walletAddress);
console.log('Membership purchased:', receipt.hash);
}
const API_BASE_URL = 'https://api.fairside.io/v1';
const API_KEY = 'your-api-key';
const POLLING_INTERVAL = 10000; // 10 seconds
// 1. Get payment estimates for all supported currencies
async function getPaymentEstimates(coverAmount) {
const response = await fetch(`${API_BASE_URL}/nowpayments/estimates`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'api-key': API_KEY,
},
body: JSON.stringify({ coverAmount }),
});
const data = await response.json();
// Returns: { coverAmount, ethAmount, estimates: [{ currency, network, estimatedAmount }] }
return data;
}
// 2. Create payment intention with selected currency
async function createPayment(token, params) {
const response = await fetch(`${API_BASE_URL}/nowpayments/payments`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'api-key': API_KEY,
'Authorization': `Bearer ${token}`,
},
body: JSON.stringify({
coverAmount: params.coverAmount,
membershipTypeId: '0', // MainNet
paymentCurrency: params.currency, // e.g., 'usdt', 'btc'
paymentNetwork: params.network, // e.g., 'erc20', 'bitcoin'
paymentType: 'new_purchase', // or 'topup'
}),
});
const data = await response.json();
// Returns: { paymentId, paymentAddress, paymentAmount, expiresAt, ... }
return data;
}
// 3. Poll payment status until complete
async function pollPaymentStatus(token, paymentId, onStatusUpdate) {
const checkStatus = async () => {
const response = await fetch(
`${API_BASE_URL}/nowpayments/payments/${paymentId}`,
{
headers: {
'api-key': API_KEY,
'Authorization': `Bearer ${token}`,
},
}
);
const status = await response.json();
onStatusUpdate(status);
// Payment statuses: waiting, confirming, confirmed, sending, finished, failed, expired
if (status.paymentStatus === 'finished') {
console.log('Payment complete! Tx:', status.membershipPurchaseTxHash);
return status;
}
if (status.paymentStatus === 'failed' || status.paymentStatus === 'expired') {
throw new Error(`Payment ${status.paymentStatus}`);
}
// Continue polling
await new Promise(resolve => setTimeout(resolve, POLLING_INTERVAL));
return checkStatus();
};
return checkStatus();
}
// Complete Crypto Payment Flow
async function purchaseWithCrypto(token, coverAmount, preferredCurrency = 'usdt') {
// Step 1: Get estimates
const estimates = await getPaymentEstimates(coverAmount);
console.log('Available currencies:', estimates.estimates);
// Step 2: Find preferred currency
const selected = estimates.estimates.find(
e => e.currency === preferredCurrency
);
if (!selected) {
throw new Error(`Currency ${preferredCurrency} not available`);
}
// Step 3: Create payment
const payment = await createPayment(token, {
coverAmount,
currency: selected.currency,
network: selected.network,
});
console.log('Send exactly', payment.paymentAmount, selected.currency);
console.log('To address:', payment.paymentAddress);
console.log('Expires at:', payment.expiresAt);
// Step 4: Poll until user sends payment and it's confirmed
// Fairside handles the on-chain membership purchase automatically
const finalStatus = await pollPaymentStatus(token, payment.paymentId, (status) => {
console.log('Status:', status.paymentStatus);
});
return finalStatus;
}
// Usage
purchaseWithCrypto(authToken, 5, 'usdt')
.then(status => console.log('Membership created:', status.membershipPurchaseTxHash))
.catch(err => console.error('Payment failed:', err));
import { ethers } from 'ethers';
const NETWORK_CONTRACT = '0x17aD4490A9181cf01F2Be059765d4f2d8Ee6d8a0';
// FairSideNetwork ABI (minimal)
const FairSideNetworkABI = [
'function purchaseMembership(uint256 costShareBenefit, address coverAddress, uint256 membershipType) external payable',
'function estimateCost(uint256 costShareBenefit, uint256 accountDuration, uint256 membershipTypeId) external view returns (uint256)',
'function getAccountMembership(address account) external view returns (uint256[])',
];
async function purchaseMembership(coverAmountETH) {
const provider = new ethers.BrowserProvider(window.ethereum);
const signer = await provider.getSigner();
const walletAddress = await signer.getAddress();
const networkContract = new ethers.Contract(
NETWORK_CONTRACT,
FairSideNetworkABI,
signer
);
// Check if user already has membership
const coverIds = await networkContract.getAccountMembership(walletAddress);
if (coverIds.length >= 1) {
throw new Error('User already has a membership');
}
// Calculate cost
const amountWei = ethers.parseEther(coverAmountETH.toString());
const fee = await networkContract.estimateCost(amountWei, 0, 0);
// Purchase
const tx = await networkContract.purchaseMembership(
amountWei,
walletAddress,
0, // MainNet type
{ value: fee }
);
const receipt = await tx.wait();
console.log('Transaction hash:', receipt.hash);
return receipt;
}
// Usage
purchaseMembership(5); // 5 ETH coverage
const API_BASE_URL = 'https://api.fairside.io/v1';
const API_KEY = 'your-api-key';
async function checkCoverageStatus(walletAddress) {
const response = await fetch(
`${API_BASE_URL}/membership/check-cover/${walletAddress}`,
{
headers: {
'api-key': API_KEY,
},
}
);
const data = await response.json();
return {
hasCoverage: data.hasCover,
isActive: data.isActive,
coverAmount: data.coverAmount,
validUntil: new Date(data.validUntil),
hasActiveClaims: data.activeClaims.length > 0,
};
}
// Usage
const status = await checkCoverageStatus('0x...');
if (status.hasCoverage && status.isActive) {
console.log(`Protected with ${status.coverAmount} ETH until ${status.validUntil}`);
} else if (status.hasCoverage && !status.isActive) {
console.log('Coverage expired - renewal needed');
} else {
console.log('No coverage - purchase needed');
}
Error Handling
API Errors
Contract Errors
"Only one cover allowed"
User already has active membership
"Capital pool not funded"
Protocol capital pool is empty
"Cover amount invalid"
Amount < 0.25 ETH or > 10 ETH
"Cannot top-up during claim"
Cover blocked due to ongoing claim
Ready to integrate?
Get your API key and start building wallet protection into your dApp.