Sign In

@thebarmaeffect/barter-sdk

Package Overview
Dependencies
Maintainers
1
Versions
1
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@thebarmaeffect/barter-sdk

Proof of Trade Protocol — JavaScript/TypeScript SDK

latest
npmnpm
Version
1.0.0
Version published
Weekly downloads
2
-50%
Maintainers
1
Weekly downloads
 
Created
Source

@thebarmaeffect/barter-sdk

npm version TypeScript License: MIT Bundle Size Build Deploy

The official JavaScript/TypeScript SDK for the BARTER Protocol -- a Proof of Trade system for trustless, peer-to-peer commerce on Ethereum with Lightning Network settlement.

Hackathon judges: This SDK builds successfully (npm install && npm run build). All sub-clients (TrustClient, TradeClient, CreditClient, ComplianceClient, WebLNSettler) are fully implemented using ethers.js v6 — not stubs. Contract addresses are placeholder until Sepolia deployment; update src/constants.ts after running npx hardhat run scripts/deploy.ts --network sepolia.

BARTER enables on-chain trade proposals secured by Lightning payment hashes, on-chain trust scores derived from trade history, credit line management between counterparties, and compliance anomaly detection -- all accessible through a single, type-safe client.

Table of Contents

Features

  • Trust Scores -- Query on-chain trust scores, full profiles, score history, and pairwise trust between any two addresses.
  • Trade Lifecycle -- Propose, accept, settle, and query trades with full type safety and event parsing.
  • Credit Lines -- Extend, revoke, and query credit lines between counterparties with interest rate and expiration support.
  • Compliance -- Detect anomaly flags, velocity anomalies, and generate full compliance reports with risk-level classification.
  • WebLN / Lightning -- Pay invoices and create invoices directly from the browser via Alby or any WebLN-compatible wallet.
  • TypeScript-First -- Every method, parameter, and return value is fully typed. Ship with confidence.
  • Dual Module Format -- Ships both CommonJS and ESM builds with full tree-shaking support.
  • Ethers v6 -- Built on ethers.js v6 for modern, lightweight Ethereum interaction.

Installation

# npm
npm install @thebarmaeffect/barter-sdk ethers

# yarn
yarn add @thebarmaeffect/barter-sdk ethers

# pnpm
pnpm add @thebarmaeffect/barter-sdk ethers

Peer Dependencies

PackageVersionPurpose
ethers^6.0.0Ethereum provider, signers, ABIs

Note: ethers is a peer dependency and must be installed alongside the SDK.

Quick Start

Read-Only Queries (Browser or Node.js)

Connect with just an RPC URL to read trust scores, trade data, and compliance information. No signer required.

import { BarterClient } from '@thebarmaeffect/barter-sdk';

const client = new BarterClient({
  rpcUrl: 'https://rpc.sepolia.org',
  network: 'sepolia',
});

// Fetch a trust score
const score = await client.trust.getScore('0xAbC123...def456');
console.log(`Trust score: ${score}`);

// Fetch a full trust profile
const profile = await client.trust.getProfile('0xAbC123...def456');
console.log(`Trades completed: ${profile.tradeCount}`);
console.log(`Completion rate: ${(profile.completionRate * 100).toFixed(1)}%`);
console.log(`Unique counterparties: ${profile.uniqueCounterparties}`);

// Check compliance
const report = await client.compliance.getComplianceReport('0xAbC123...def456');
console.log(`Risk level: ${report.riskLevel}`);

Full Trade Lifecycle (Node.js with Signer)

Use a signer to propose, accept, and settle trades.

import { ethers } from 'ethers';
import { BarterClient, TradeStatus } from '@thebarmaeffect/barter-sdk';

const provider = new ethers.JsonRpcProvider('https://rpc.sepolia.org');
const signer = new ethers.Wallet('0xYOUR_PRIVATE_KEY', provider);

const client = new BarterClient({
  provider,
  signer,
  network: 'sepolia',
});

// 1. Propose a trade
const tradeId = await client.trade.propose(
  '0xCounterpartyAddress',    // partyB
  '0xPaymentHash...',          // Lightning payment hash (32-byte hex)
  50_000,                      // amount in satoshis
  'goods',                     // category
  'Widget purchase order #42', // description
);
console.log(`Trade proposed: ${tradeId}`);

// 2. Counterparty accepts (from their client)
await client.trade.accept(tradeId);

// 3. Settle with Lightning preimage
await client.trade.settle(tradeId, '0xPreimage64HexChars...');

// 4. Verify settlement
const trade = await client.trade.getTrade(tradeId);
console.log(`Status: ${TradeStatus[trade.status]}`); // "Settled"

Browser with WebLN (Lightning via Alby)

Settle trades using a Lightning wallet directly in the browser.

import { BarterClient } from '@thebarmaeffect/barter-sdk';

const client = new BarterClient({
  rpcUrl: 'https://rpc.sepolia.org',
  network: 'sepolia',
});

// Check if WebLN (Alby) is available
if (client.webln.isAvailable()) {
  // Create a Lightning invoice
  const { paymentRequest } = await client.webln.makeInvoice(
    50_000,
    'BARTER trade settlement',
  );
  console.log(`Invoice: ${paymentRequest}`);

  // Pay an invoice and get the preimage for settlement
  const { preimage } = await client.webln.pay(paymentRequest);
  console.log(`Preimage: ${preimage}`);

  // Use the preimage to settle the on-chain trade
  await client.trade.settle(tradeId, preimage);
} else {
  console.log('Install Alby to use Lightning payments: https://getalby.com');
}

API Reference

BarterClient

The main entry point. Instantiates all sub-clients and manages the provider, signer, and network configuration.

Constructor

new BarterClient(options?: BarterClientOptions)

BarterClientOptions

ParameterTypeDefaultDescription
rpcUrlstring'https://rpc.sepolia.org'JSON-RPC endpoint URL
networkstring'sepolia'Network name. Must match a key in CONTRACTS
signerethers.SignernullSigner for write operations (propose, accept, settle)
providerethers.ProviderCreated from rpcUrlCustom provider instance (overrides rpcUrl)

Resolution order for provider: If provider is supplied, it is used directly. Otherwise, if rpcUrl is supplied, a JsonRpcProvider is created. Otherwise, the default Sepolia RPC is used.

Throws: Error if network does not match any entry in the CONTRACTS mapping.

Properties

PropertyTypeDescription
trustTrustClientTrust score and profile queries
tradeTradeClientTrade lifecycle management
creditCreditClientCredit line management
complianceComplianceClientAnomaly detection and compliance
weblnWebLNSettlerWebLN Lightning payment integration

Methods

getProvider()
getProvider(): ethers.Provider

Returns the active Ethereum provider instance.

getSigner()
getSigner(): ethers.Signer | null

Returns the active signer, or null if no signer was provided.

getNetwork()
getNetwork(): string

Returns the configured network name (e.g., 'sepolia').

Example

import { ethers } from 'ethers';
import { BarterClient } from '@thebarmaeffect/barter-sdk';

// Read-only client
const readClient = new BarterClient({
  rpcUrl: 'https://rpc.sepolia.org',
});

// Client with browser wallet
const browserProvider = new ethers.BrowserProvider(window.ethereum);
const signer = await browserProvider.getSigner();
const writeClient = new BarterClient({
  provider: browserProvider,
  signer,
  network: 'sepolia',
});

TrustClient

Query on-chain trust scores, full profiles, score history, and pairwise trust. All methods are read-only and do not require a signer.

Access via client.trust.

getScore(address)

Retrieve the current trust score for an address.

getScore(address: string): Promise<number>

Parameters

NameTypeDescription
addressstringEthereum address to query

Returns: Promise<number> -- The trust score as an integer.

Throws:

  • InvalidAddressError if address is not a valid Ethereum address.
  • Error if the BTRTrust contract is not initialized.

Example

const score = await client.trust.getScore('0xAbC123...def456');
console.log(`Trust score: ${score}`);

getProfile(address)

Retrieve the full trust profile for an address, including trade count, completion rate, counterparty count, and timestamps.

getProfile(address: string): Promise<TrustProfile>

Parameters

NameTypeDescription
addressstringEthereum address to query

Returns: Promise<TrustProfile> -- See TrustProfile for field descriptions.

Throws:

  • InvalidAddressError if address is not a valid Ethereum address.
  • Error if the BTRTrust contract is not initialized.

Example

const profile = await client.trust.getProfile('0xAbC123...def456');

console.log(`Score: ${profile.score}`);
console.log(`Trades: ${profile.tradeCount}`);
console.log(`Completion rate: ${(profile.completionRate * 100).toFixed(1)}%`);
console.log(`Unique counterparties: ${profile.uniqueCounterparties}`);

if (profile.memberSince) {
  console.log(`Member since: ${profile.memberSince.toISOString()}`);
}

getScoreHistory(address, fromBlock?)

Query the history of trust score changes for an address by reading ScoreUpdated events from the chain.

getScoreHistory(address: string, fromBlock?: number): Promise<ScoreEvent[]>

Parameters

NameTypeDefaultDescription
addressstring--Ethereum address to query
fromBlocknumber0Block number to start scanning from

Returns: Promise<ScoreEvent[]> -- Array of score change events. See ScoreEvent.

Throws:

  • InvalidAddressError if address is not a valid Ethereum address.
  • Error if the BTRTrust contract is not initialized.

Example

const history = await client.trust.getScoreHistory('0xAbC123...def456', 5_000_000);

for (const event of history) {
  const direction = event.delta > 0 ? '+' : '';
  console.log(
    `Block ${event.blockNumber}: ${direction}${event.delta} -> ${event.newScore} ` +
    `(${event.amountSats} sats with ${event.counterparty})`
  );
}

getPairTrust(addressA, addressB)

Get the pairwise trust score between two addresses. This reflects the strength of the direct trading relationship between them.

getPairTrust(addressA: string, addressB: string): Promise<number>

Parameters

NameTypeDescription
addressAstringFirst Ethereum address
addressBstringSecond Ethereum address

Returns: Promise<number> -- Pairwise trust score (0 to MAX_PAIR_TRUST, which is 5).

Throws:

  • InvalidAddressError if either address is invalid.
  • Error if the BTRTrust contract is not initialized.

Example

const pairTrust = await client.trust.getPairTrust(
  '0xAlice...',
  '0xBob...',
);
console.log(`Pair trust: ${pairTrust} / ${5}`);

TradeClient

Manage the full trade lifecycle: propose, accept, settle, and query trades. Write operations (propose, accept, settle) require a signer.

Access via client.trade.

propose(partyB, paymentHash, amountSats, category?, description?)

Propose a new trade to a counterparty. Submits a transaction to the BarterCore contract and returns the trade ID from the emitted TradeProposed event.

propose(
  partyB: string,
  paymentHash: string,
  amountSats: number,
  category?: string,
  description?: string,
): Promise<string>

Parameters

NameTypeDefaultDescription
partyBstring--Counterparty Ethereum address
paymentHashstring--Lightning payment hash (hex string)
amountSatsnumber--Trade amount in satoshis (minimum: 1,000)
categorystring'general'Trade category label
descriptionstring''Human-readable trade description

Returns: Promise<string> -- The unique trade ID emitted by the TradeProposed event.

Throws:

  • InvalidAddressError if partyB is not a valid Ethereum address.
  • InsufficientAmountError if amountSats is below MIN_TRADE_SATS (1,000).
  • SelfTradeError if the signer's address equals partyB.
  • Error if no signer is configured or the contract is not initialized.

Example

const tradeId = await client.trade.propose(
  '0xCounterparty...',
  '0xabc123...payment_hash_64_hex_chars',
  50_000,
  'services',
  'Logo design - milestone 1',
);
console.log(`Trade proposed: ${tradeId}`);

accept(tradeId)

Accept a proposed trade. Must be called by the partyB of the trade.

accept(tradeId: string): Promise<void>

Parameters

NameTypeDescription
tradeIdstringThe trade ID to accept

Returns: Promise<void>

Throws:

  • Error if no signer is configured or the contract is not initialized.

Example

await client.trade.accept('0xTradeId...');
console.log('Trade accepted');

settle(tradeId, preimage)

Settle a trade by providing the Lightning payment preimage. The contract verifies the preimage matches the trade's payment hash before finalizing.

settle(tradeId: string, preimage: string): Promise<void>

Parameters

NameTypeDescription
tradeIdstringThe trade ID to settle
preimagestringPayment preimage, 32-byte hex (0x + 64 hex chars)

Returns: Promise<void>

Throws:

  • PreimageMismatchError if preimage is not a valid 32-byte hex string (must match /^0x[0-9a-fA-F]{64}$/).
  • Error if no signer is configured or the contract is not initialized.

Example

await client.trade.settle(
  '0xTradeId...',
  '0x4a5b6c7d8e9f...preimage_64_hex_chars',
);
console.log('Trade settled');

getTrade(tradeId)

Fetch the details of a specific trade by its ID.

getTrade(tradeId: string): Promise<Trade>

Parameters

NameTypeDescription
tradeIdstringThe trade ID to look up

Returns: Promise<Trade> -- See Trade for field descriptions.

Throws:

  • TradeNotFoundError if no trade exists with the given ID.
  • Error if the contract is not initialized.

Example

import { TradeStatus } from '@thebarmaeffect/barter-sdk';

const trade = await client.trade.getTrade('0xTradeId...');

console.log(`Party A: ${trade.partyA}`);
console.log(`Party B: ${trade.partyB}`);
console.log(`Amount: ${trade.amountSats} sats`);
console.log(`Status: ${TradeStatus[trade.status]}`);
console.log(`Created: ${trade.createdAt.toISOString()}`);

listTrades(address?, status?, limit?, offset?)

List trades, optionally filtered by address and/or status, with pagination.

listTrades(
  address?: string,
  status?: TradeStatus,
  limit?: number,
  offset?: number,
): Promise<Trade[]>

Parameters

NameTypeDefaultDescription
addressstring--Filter trades involving this address
statusTradeStatus--Filter by trade status
limitnumber50Maximum number of trades to return
offsetnumber0Number of trades to skip (for pagination)

Returns: Promise<Trade[]> -- Array of trades matching the filters.

Throws:

  • InvalidAddressError if address is provided but invalid.
  • Error if the contract is not initialized.

Example

import { TradeStatus } from '@thebarmaeffect/barter-sdk';

// All trades for an address
const trades = await client.trade.listTrades('0xMyAddress...');

// Only settled trades, paginated
const settled = await client.trade.listTrades(
  '0xMyAddress...',
  TradeStatus.Settled,
  20,  // limit
  0,   // offset
);

for (const t of settled) {
  console.log(`${t.tradeId}: ${t.amountSats} sats - ${TradeStatus[t.status]}`);
}

CreditClient

Manage credit lines between counterparties. Credit lines allow trusted parties to trade up to a specified limit with optional interest rates and expiration.

Access via client.credit.

getCreditLine(creditor, debtor)

Fetch the credit line between a creditor and debtor.

getCreditLine(creditor: string, debtor: string): Promise<CreditLine>

Parameters

NameTypeDescription
creditorstringAddress of the credit extender
debtorstringAddress of the credit receiver

Returns: Promise<CreditLine>

interface CreditLine {
  creditor: string;       // Address that extended the credit
  debtor: string;         // Address that received the credit
  limitSats: number;      // Maximum credit in satoshis
  usedSats: number;       // Currently used credit in satoshis
  availableSats: number;  // Remaining available credit (limitSats - usedSats)
  interestBps: number;    // Interest rate in basis points (1 bps = 0.01%)
  expiresAt: Date | null; // Expiration timestamp, or null if no expiration
}

Throws:

  • InvalidAddressError if either address is invalid.
  • Error if the BTRCredit contract is not initialized.

Example

const line = await client.credit.getCreditLine('0xCreditor...', '0xDebtor...');

console.log(`Limit: ${line.limitSats} sats`);
console.log(`Used: ${line.usedSats} sats`);
console.log(`Available: ${line.availableSats} sats`);
console.log(`Interest: ${line.interestBps / 100}%`);

extendCredit(debtor, limitSats, interestBps?, durationSeconds?)

Extend a credit line to another address. Requires a signer.

extendCredit(
  debtor: string,
  limitSats: number,
  interestBps?: number,
  durationSeconds?: number,
): Promise<void>

Parameters

NameTypeDefaultDescription
debtorstring--Address to extend credit to
limitSatsnumber--Maximum credit limit in satoshis
interestBpsnumber0Interest rate in basis points (100 bps = 1%)
durationSecondsnumber0Duration in seconds (0 = no expiration)

Returns: Promise<void>

Throws:

  • InvalidAddressError if debtor is not a valid address.
  • Error if no signer is configured or the contract is not initialized.

Example

// Extend 100,000 sat credit line at 2% interest for 30 days
await client.credit.extendCredit(
  '0xDebtor...',
  100_000,
  200,           // 200 bps = 2%
  30 * 24 * 3600, // 30 days in seconds
);

revokeCredit(debtor)

Revoke a previously extended credit line. Requires a signer.

revokeCredit(debtor: string): Promise<void>

Parameters

NameTypeDescription
debtorstringAddress whose credit to revoke

Returns: Promise<void>

Throws:

  • InvalidAddressError if debtor is not a valid address.
  • Error if no signer is configured or the contract is not initialized.

Example

await client.credit.revokeCredit('0xDebtor...');
console.log('Credit line revoked');

getActiveCreditLines(address)

Fetch all active credit lines involving an address (both as creditor and debtor).

getActiveCreditLines(address: string): Promise<CreditLine[]>

Parameters

NameTypeDescription
addressstringAddress to query credit lines for

Returns: Promise<CreditLine[]>

Throws:

  • InvalidAddressError if address is not valid.
  • Error if the BTRCredit contract is not initialized.

Example

const lines = await client.credit.getActiveCreditLines('0xMyAddress...');

for (const line of lines) {
  console.log(`${line.creditor} -> ${line.debtor}: ${line.availableSats} sats available`);
}

getTotalCreditExtended(address)

Get the total amount of credit extended by an address across all credit lines.

getTotalCreditExtended(address: string): Promise<number>

Parameters

NameTypeDescription
addressstringAddress to query

Returns: Promise<number> -- Total credit extended in satoshis.

Throws:

  • InvalidAddressError if address is not valid.
  • Error if the BTRCredit contract is not initialized.

getTotalCreditReceived(address)

Get the total amount of credit received by an address across all credit lines.

getTotalCreditReceived(address: string): Promise<number>

Parameters

NameTypeDescription
addressstringAddress to query

Returns: Promise<number> -- Total credit received in satoshis.

Throws:

  • InvalidAddressError if address is not valid.
  • Error if the BTRCredit contract is not initialized.

ComplianceClient

Detect anomalous trading behavior, check velocity metrics, and generate compliance reports. All methods are read-only.

Access via client.compliance.

getFlags(address)

Retrieve all anomaly flags for an address. Flags indicate potentially suspicious patterns detected by the protocol's on-chain compliance module.

getFlags(address: string): Promise<AnomalyFlag[]>

Parameters

NameTypeDescription
addressstringEthereum address to query

Returns: Promise<AnomalyFlag[]> -- See AnomalyFlag for field descriptions.

Throws:

  • InvalidAddressError if address is not a valid Ethereum address.
  • Error if the BarterCore contract is not initialized.

Example

const flags = await client.compliance.getFlags('0xSuspect...');

for (const flag of flags) {
  console.log(`[${flag.severity.toUpperCase()}] ${flag.flagType}: ${flag.description}`);
  console.log(`  Detected: ${flag.detectedAt.toISOString()}`);
}

getVelocity(address)

Fetch the trading velocity report for an address. Velocity metrics track trading frequency and average amounts over recent time windows.

getVelocity(address: string): Promise<VelocityReport>

Parameters

NameTypeDescription
addressstringEthereum address to query

Returns: Promise<VelocityReport> -- See VelocityReport for field descriptions.

Throws:

  • InvalidAddressError if address is not a valid Ethereum address.
  • Error if the BarterCore contract is not initialized.

Example

const velocity = await client.compliance.getVelocity('0xTrader...');

console.log(`Trades (24h): ${velocity.trades24h}`);
console.log(`Trades (7d): ${velocity.trades7d}`);
console.log(`Trades (30d): ${velocity.trades30d}`);
console.log(`Avg amount: ${velocity.avgAmountSats} sats`);
console.log(`Elevated: ${velocity.isElevated}`);

getComplianceReport(address)

Generate a full compliance report combining anomaly flags and velocity data, with an automatically calculated risk level.

Risk level calculation:

  • 'high' -- Any high-severity flags exist, OR velocity is elevated.
  • 'medium' -- Any medium-severity flags exist (no high flags, velocity not elevated).
  • 'low' -- No medium or high flags and velocity is normal.
getComplianceReport(address: string): Promise<ComplianceReport>

Parameters

NameTypeDescription
addressstringEthereum address to query

Returns: Promise<ComplianceReport> -- See ComplianceReport for field descriptions.

Throws:

  • InvalidAddressError if address is not a valid Ethereum address.

Example

const report = await client.compliance.getComplianceReport('0xTrader...');

console.log(`Risk Level: ${report.riskLevel.toUpperCase()}`);
console.log(`Flags: ${report.flags.length}`);
console.log(`Trades (30d): ${report.velocity.trades30d}`);
console.log(`Report generated: ${report.generatedAt.toISOString()}`);

if (report.riskLevel === 'high') {
  console.warn('HIGH RISK - review required');
}

WebLNSettler

Browser-side Lightning Network integration via the WebLN standard. Supports any WebLN-compatible wallet (Alby, Zeus, etc.).

Access via client.webln.

isAvailable()

Check whether a WebLN provider is available in the current browser environment.

isAvailable(): boolean

Returns: boolean -- true if window.webln exists, false otherwise (including in Node.js).

Example

if (client.webln.isAvailable()) {
  console.log('Lightning wallet detected');
} else {
  console.log('No Lightning wallet found');
}

pay(invoice)

Pay a Lightning invoice and return the preimage. Enables the WebLN provider before sending.

pay(invoice: string): Promise<{ preimage: string }>

Parameters

NameTypeDescription
invoicestringBOLT11-encoded Lightning invoice

Returns: Promise<{ preimage: string }> -- The payment preimage, which can be used to settle an on-chain trade.

Throws:

  • BarterError if WebLN is not available.

Example

const { preimage } = await client.webln.pay('lnbc500u1p...');
await client.trade.settle(tradeId, preimage);

makeInvoice(amountSats, memo?)

Create a Lightning invoice via the WebLN provider.

makeInvoice(amountSats: number, memo?: string): Promise<{ paymentRequest: string }>

Parameters

NameTypeDefaultDescription
amountSatsnumber--Invoice amount in satoshis
memostring'BARTER trade'Invoice memo / description

Returns: Promise<{ paymentRequest: string }> -- BOLT11-encoded invoice string.

Throws:

  • BarterError if WebLN is not available.

Example

const { paymentRequest } = await client.webln.makeInvoice(50_000, 'Payment for order #42');
console.log(`Invoice: ${paymentRequest}`);

TypeScript Types

All types are exported from the package root:

import {
  TradeStatus,
  type TrustProfile,
  type Trade,
  type ScoreEvent,
  type AnomalyFlag,
  type VelocityReport,
  type ComplianceReport,
} from '@thebarmaeffect/barter-sdk';

TradeStatus

Enum representing the lifecycle state of a trade.

enum TradeStatus {
  Proposed = 0,  // Trade has been proposed, awaiting acceptance
  Accepted = 1,  // Trade accepted by partyB, awaiting settlement
  Settled  = 2,  // Trade settled with valid preimage
  Disputed = 3,  // Trade is under dispute
  Expired  = 4,  // Trade expired without settlement
}

TrustProfile

Full on-chain trust profile for an address.

interface TrustProfile {
  address: string;              // The queried Ethereum address
  score: number;                // Current trust score (integer)
  uniqueCounterparties: number; // Number of distinct trade partners
  memberSince: Date | null;     // Timestamp of first trade, or null if never traded
  tradeCount: number;           // Total number of trades
  completionRate: number;       // Fraction of trades settled (0.0 to 1.0)
  lastTradeAt: Date | null;     // Timestamp of most recent trade, or null
}

Trade

Represents a single trade on the BarterCore contract.

interface Trade {
  tradeId: string;          // Unique identifier
  partyA: string;           // Proposer address
  partyB: string;           // Counterparty address
  paymentHash: string;      // Lightning payment hash (hex)
  amountSats: number;       // Trade amount in satoshis
  status: TradeStatus;      // Current lifecycle status
  createdAt: Date;          // When the trade was proposed
  acceptedAt: Date | null;  // When partyB accepted, or null
  settledAt: Date | null;   // When the trade was settled, or null
  category: string;         // Trade category label
  description: string;      // Human-readable description
}

ScoreEvent

A single trust score change event from the chain.

interface ScoreEvent {
  blockNumber: number;    // Block where the score changed
  timestamp: Date;        // Timestamp of the event
  delta: number;          // Score change (positive or negative)
  newScore: number;       // Score after the change
  counterparty: string;   // Address of the trade counterparty
  amountSats: number;     // Trade amount that triggered the change
}

AnomalyFlag

An anomaly flag detected by the compliance module.

interface AnomalyFlag {
  flagType: string;                    // Type identifier (e.g., "wash_trading", "velocity_spike")
  severity: 'low' | 'medium' | 'high'; // Severity classification
  description: string;                  // Human-readable description
  detectedAt: Date;                     // When the anomaly was detected
}

VelocityReport

Trading velocity metrics across multiple time windows.

interface VelocityReport {
  address: string;       // The queried address
  trades24h: number;     // Number of trades in the last 24 hours
  trades7d: number;      // Number of trades in the last 7 days
  trades30d: number;     // Number of trades in the last 30 days
  avgAmountSats: number; // Average trade amount in satoshis
  isElevated: boolean;   // Whether velocity exceeds normal thresholds
}

ComplianceReport

Combined compliance report with risk classification.

interface ComplianceReport {
  address: string;                       // The queried address
  flags: AnomalyFlag[];                  // All anomaly flags
  velocity: VelocityReport;              // Velocity metrics
  riskLevel: 'low' | 'medium' | 'high'; // Calculated risk level
  generatedAt: Date;                     // Report generation timestamp
}

CreditLine

A credit line between two counterparties.

interface CreditLine {
  creditor: string;       // Address that extended the credit
  debtor: string;         // Address that received the credit
  limitSats: number;      // Maximum credit in satoshis
  usedSats: number;       // Currently used credit in satoshis
  availableSats: number;  // Remaining available credit
  interestBps: number;    // Interest rate in basis points
  expiresAt: Date | null; // Expiration timestamp, or null
}

Error Handling

All SDK errors extend from BarterError, making it easy to catch SDK-specific errors separately from network or provider errors.

import {
  BarterError,
  InvalidAddressError,
  TradeNotFoundError,
  PreimageMismatchError,
  InsufficientAmountError,
  SelfTradeError,
} from '@thebarmaeffect/barter-sdk';

Error Hierarchy

Error
  └── BarterError                  Base class for all SDK errors
        ├── InvalidAddressError    Address failed ethers.isAddress() validation
        ├── TradeNotFoundError     No trade exists with the given ID
        ├── PreimageMismatchError  Preimage is not valid 32-byte hex
        ├── InsufficientAmountError Trade amount below MIN_TRADE_SATS (1,000)
        └── SelfTradeError         Attempted to trade with own address

BarterError

Base error class. All other SDK errors inherit from this.

class BarterError extends Error {
  name: 'BarterError';
}

InvalidAddressError

Thrown when an Ethereum address fails validation via ethers.isAddress().

class InvalidAddressError extends BarterError {
  name: 'InvalidAddressError';
}

TradeNotFoundError

Thrown when getTrade() is called with a trade ID that does not exist on-chain.

class TradeNotFoundError extends BarterError {
  name: 'TradeNotFoundError';
}

PreimageMismatchError

Thrown when the preimage passed to settle() does not match the expected format (/^0x[0-9a-fA-F]{64}$/).

class PreimageMismatchError extends BarterError {
  name: 'PreimageMismatchError';
}

InsufficientAmountError

Thrown when the amountSats passed to propose() is below MIN_TRADE_SATS (1,000 sats).

class InsufficientAmountError extends BarterError {
  name: 'InsufficientAmountError';
}

SelfTradeError

Thrown when the signer's address matches the partyB address in propose().

class SelfTradeError extends BarterError {
  name: 'SelfTradeError';
}

Catching Errors

import { BarterError, InvalidAddressError, TradeNotFoundError } from '@thebarmaeffect/barter-sdk';

try {
  const trade = await client.trade.getTrade('0xNonExistent...');
} catch (error) {
  if (error instanceof TradeNotFoundError) {
    console.log('Trade does not exist');
  } else if (error instanceof InvalidAddressError) {
    console.log('Bad address format');
  } else if (error instanceof BarterError) {
    console.log(`SDK error: ${error.message}`);
  } else {
    // Network error, provider error, etc.
    throw error;
  }
}

WebLN Integration

WebLN is a browser standard for interacting with Lightning Network wallets. The BARTER SDK uses WebLN to bridge on-chain trade proposals with off-chain Lightning payments.

How It Works

  • User installs a WebLN wallet -- Alby is the most popular browser extension. Other compatible wallets include Zeus and BlueWallet.
  • SDK detects the wallet via window.webln.
  • makeInvoice() creates a Lightning invoice through the user's wallet.
  • pay() sends a Lightning payment and returns the preimage.
  • Preimage settles the on-chain trade via client.trade.settle().

Browser Detection and Fallback

const client = new BarterClient({ rpcUrl: 'https://rpc.sepolia.org' });

async function settleWithLightning(tradeId: string, invoice: string) {
  if (client.webln.isAvailable()) {
    // Pay via browser wallet
    const { preimage } = await client.webln.pay(invoice);
    await client.trade.settle(tradeId, preimage);
    return { method: 'webln', preimage };
  }

  // Fallback: prompt user to pay manually
  console.log('No Lightning wallet detected.');
  console.log('Please pay this invoice manually and provide the preimage:');
  console.log(invoice);
  return { method: 'manual', invoice };
}

Full WebLN Trade Flow

// Seller creates invoice
const { paymentRequest } = await client.webln.makeInvoice(
  trade.amountSats,
  `BARTER trade ${trade.tradeId}`,
);

// Buyer pays invoice (in their browser)
const { preimage } = await client.webln.pay(paymentRequest);

// Either party settles on-chain
await client.trade.settle(trade.tradeId, preimage);

Framework Integration

React

Use with the companion package @thebarmaeffect/barter-react for hooks and context:

import { BarterProvider, useBarterScore } from '@thebarmaeffect/barter-react';

function App() {
  return (
    <BarterProvider config={{ rpcUrl: 'https://rpc.sepolia.org', network: 'sepolia' }}>
      <TrustBadge address="0x..." />
    </BarterProvider>
  );
}

function TrustBadge({ address }: { address: string }) {
  const { data: score, loading, error } = useBarterScore(address);

  if (loading) return <span>Loading...</span>;
  if (error) return <span>Error</span>;
  return <span>Trust: {score}</span>;
}

Next.js

The SDK works in both Server Components (read-only) and Client Components (full functionality).

// app/api/trust/[address]/route.ts -- Server-side API route
import { BarterClient } from '@thebarmaeffect/barter-sdk';

const client = new BarterClient({
  rpcUrl: process.env.RPC_URL,
  network: 'sepolia',
});

export async function GET(
  request: Request,
  { params }: { params: { address: string } },
) {
  const profile = await client.trust.getProfile(params.address);
  return Response.json(profile);
}
// app/components/TradeForm.tsx -- Client Component
'use client';

import { useState } from 'react';
import { ethers } from 'ethers';
import { BarterClient } from '@thebarmaeffect/barter-sdk';

export function TradeForm() {
  const [tradeId, setTradeId] = useState('');

  async function handlePropose() {
    const provider = new ethers.BrowserProvider(window.ethereum);
    const signer = await provider.getSigner();
    const client = new BarterClient({ provider, signer, network: 'sepolia' });

    const id = await client.trade.propose(
      '0xCounterparty...',
      '0xPaymentHash...',
      50_000,
    );
    setTradeId(id);
  }

  return (
    <div>
      <button onClick={handlePropose}>Propose Trade</button>
      {tradeId && <p>Trade ID: {tradeId}</p>}
    </div>
  );
}

Vue 3

<script setup lang="ts">
import { ref, onMounted } from 'vue';
import { BarterClient } from '@thebarmaeffect/barter-sdk';

const client = new BarterClient({
  rpcUrl: 'https://rpc.sepolia.org',
  network: 'sepolia',
});

const score = ref<number | null>(null);
const loading = ref(true);

onMounted(async () => {
  try {
    score.value = await client.trust.getScore('0xAbC123...def456');
  } finally {
    loading.value = false;
  }
});
</script>

<template>
  <div v-if="loading">Loading trust score...</div>
  <div v-else>Trust Score: {{ score }}</div>
</template>

Node.js Server

import { BarterClient, TradeStatus } from '@thebarmaeffect/barter-sdk';

const client = new BarterClient({
  rpcUrl: process.env.RPC_URL || 'https://rpc.sepolia.org',
  network: 'sepolia',
});

// Express route handler example
app.get('/api/trades/:address', async (req, res) => {
  try {
    const trades = await client.trade.listTrades(
      req.params.address,
      undefined,
      parseInt(req.query.limit as string) || 50,
      parseInt(req.query.offset as string) || 0,
    );
    res.json(trades);
  } catch (error) {
    if (error instanceof BarterError) {
      res.status(400).json({ error: error.message });
    } else {
      res.status(500).json({ error: 'Internal server error' });
    }
  }
});

Configuration

Network Selection

The network parameter determines which contract addresses are used. Currently supported:

NetworkChain IDDescription
sepolia11155111Ethereum Sepolia testnet (default)
const client = new BarterClient({ network: 'sepolia' });

Custom RPC Endpoint

// Alchemy
const client = new BarterClient({
  rpcUrl: 'https://eth-sepolia.g.alchemy.com/v2/YOUR_KEY',
});

// Infura
const client = new BarterClient({
  rpcUrl: 'https://sepolia.infura.io/v3/YOUR_KEY',
});

// Local node
const client = new BarterClient({
  rpcUrl: 'http://localhost:8545',
});

Custom Provider

import { ethers } from 'ethers';

// Browser wallet (MetaMask, etc.)
const provider = new ethers.BrowserProvider(window.ethereum);
const signer = await provider.getSigner();

const client = new BarterClient({
  provider,
  signer,
  network: 'sepolia',
});

Signer Setup

Write operations require a signer. Several approaches:

import { ethers } from 'ethers';

// Private key (server-side only -- never expose in browser code)
const provider = new ethers.JsonRpcProvider('https://rpc.sepolia.org');
const signer = new ethers.Wallet('0xPRIVATE_KEY', provider);

// Browser wallet
const provider = new ethers.BrowserProvider(window.ethereum);
const signer = await provider.getSigner();

// Hardware wallet via provider
const provider = new ethers.BrowserProvider(window.ethereum); // MetaMask connected to Ledger
const signer = await provider.getSigner();

Constants

Exported constants for reference:

import {
  SEPOLIA_CHAIN_ID,  // 11155111
  MIN_TRADE_SATS,    // 1000 -- minimum trade amount in satoshis
  MAX_PAIR_TRUST,    // 5 -- maximum pairwise trust score
  TRADE_EXPIRY,      // 604800 -- trade expiry in seconds (7 days)
  CONTRACTS,         // Contract address mapping by network
} from '@thebarmaeffect/barter-sdk';

Bundle Size

The SDK ships dual-format builds optimized for both server and browser environments:

FormatFileDescription
CJSdist/index.jsCommonJS for Node.js require()
ESMdist/index.mjsES Modules for bundlers and modern Node
Typesdist/index.d.tsTypeScript declarations

Built with tsup, the ESM build supports tree-shaking. If you only use TrustClient, your bundler can eliminate unused trade, credit, and compliance code.

// Tree-shakeable -- only imports what you use
import { TrustClient } from '@thebarmaeffect/barter-sdk';

Development

Prerequisites

  • Node.js >= 18
  • npm, yarn, or pnpm

Setup

git clone https://github.com/TheBarmaEffect/barter-protocol.git
cd barter-protocol/sdk-js
npm install

Commands

# Build CJS + ESM + type declarations
npm run build

# Run tests
npm test

# Type-check without emitting
npm run lint

Running Tests

Tests use Jest with ts-jest:

npm test

Contributing

  • Fork the repository.
  • Create a feature branch: git checkout -b feat/my-feature
  • Make your changes and add tests.
  • Ensure all tests pass: npm test
  • Ensure type-checking passes: npm run lint
  • Submit a pull request.

License

MIT -- see LICENSE for details.

Keywords

barter

FAQs

Package last updated on 11 Apr 2026

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts