Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
41874f4
implemented the index barrel exports — ensure every public symbol is …
nafiuishaaq Aug 28, 2026
0cdf08d
implemented the index barrel exports — ensure every public symbol is …
nafiuishaaq Aug 28, 2026
14911a5
implemented the index barrel exports — ensure every public symbol is …
nafiuishaaq Aug 28, 2026
5a148c1
implemented the index barrel exports — ensure every public symbol is …
nafiuishaaq Aug 28, 2026
244010c
implemented the index barrel exports — ensure every public symbol is …
nafiuishaaq Aug 28, 2026
61c8ed0
implemented the index barrel exports — ensure every public symbol is …
nafiuishaaq Aug 28, 2026
c57d786
implemented the index barrel exports — ensure every public symbol is …
nafiuishaaq Aug 28, 2026
562b3b5
implemented the enforce consistent error throwing pattern — every mod…
nafiuishaaq Aug 28, 2026
2890185
implemented the enforce consistent error throwing pattern — every mod…
nafiuishaaq Aug 28, 2026
bc3516a
implemented the enforce consistent error throwing pattern — every mod…
nafiuishaaq Aug 28, 2026
f1ec6f5
implemented the enforce consistent error throwing pattern — every mod…
nafiuishaaq Aug 28, 2026
30a08b7
implemented the enforce consistent error throwing pattern — every mod…
nafiuishaaq Aug 28, 2026
33a933f
implemented the enforce consistent error throwing pattern — every mod…
nafiuishaaq Aug 28, 2026
c8541f2
implemented the enforce consistent error throwing pattern — every mod…
nafiuishaaq Aug 28, 2026
c54ada7
implemented the enforce consistent error throwing pattern — every mod…
nafiuishaaq Aug 28, 2026
c23734e
implemented the enforce consistent error throwing pattern — every mod…
nafiuishaaq Aug 28, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 21 additions & 8 deletions src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@
public readonly batch: BatchModule;

private server!: SorobanRpc.Server;
private readonly keypair: Keypair | undefined;
protected readonly keypair: Keypair | undefined;
private connected = false;

/** Cache for getCurrentLedger — { sequence, fetchedAt } */
Expand Down Expand Up @@ -337,7 +337,7 @@
if (rpcReachable) {
try {
await this.server.getContractData(
new Contract(this.config.contractId).getAddress().toScVal(),

Check failure on line 340 in src/client.ts

View workflow job for this annotation

GitHub Actions / Build, Lint, Test

Unsafe call of an `error` type typed value

Check failure on line 340 in src/client.ts

View workflow job for this annotation

GitHub Actions / Build, Lint, Test

Unsafe call of an `error` type typed value
);
contractFound = true;
} catch {
Expand Down Expand Up @@ -394,7 +394,10 @@
*/
async simulate(method: string, args: xdr.ScVal[]): Promise<SimulationResult> {
if (!this.connected) {
throw new Error('VeriTixClient: call connect() before simulate()');
throw new VeriTixError(
VeriTixErrorCode.ClientNotConnected,
'VeriTixClient: call connect() before simulate()'
);
}

try {
Expand Down Expand Up @@ -448,7 +451,10 @@
*/
async getCurrentLedger(): Promise<number> {
if (!this.connected || !this.server) {
throw new Error('VeriTixClient: call connect() before using module methods');
throw new VeriTixError(
VeriTixErrorCode.ClientNotConnected,
'VeriTixClient: call connect() before using module methods'
);
}
const now = Date.now();
if (
Expand All @@ -473,7 +479,10 @@
*/
async watchTransaction(hash: string, options?: WatchOptions): Promise<TransactionResult> {
if (!this.connected || !this.server) {
throw new Error('VeriTixClient: call connect() before using module methods');
throw new VeriTixError(
VeriTixErrorCode.ClientNotConnected,
'VeriTixClient: call connect() before using module methods'
);
}
const intervalMs = options?.intervalMs ?? 2_000;
const timeoutMs = options?.timeoutMs ?? 60_000;
Expand Down Expand Up @@ -502,9 +511,9 @@
);
}
// NOT_FOUND or PENDING — keep polling
setTimeout(poll, intervalMs);

Check failure on line 514 in src/client.ts

View workflow job for this annotation

GitHub Actions / Build, Lint, Test

Promise returned in function argument where a void return was expected
} catch {
setTimeout(poll, intervalMs);

Check failure on line 516 in src/client.ts

View workflow job for this annotation

GitHub Actions / Build, Lint, Test

Promise returned in function argument where a void return was expected
}
};
void poll();
Expand All @@ -518,7 +527,10 @@
*/
async getContractMetadata(): Promise<ContractMetadata> {
if (!this.connected || !this.server) {
throw new Error('VeriTixClient: call connect() before using module methods');
throw new VeriTixError(
VeriTixErrorCode.ClientNotConnected,
'VeriTixClient: call connect() before using module methods'
);
}
const [name, symbol, decimal, totalSupply] = await Promise.all([
this.token.name(),
Expand Down Expand Up @@ -595,12 +607,13 @@
return new Proxy({} as SorobanRpc.Server, {
get: (_target, prop) => {
if (!this.connected || !this.server) {
throw new Error(
`VeriTixClient: call connect() before using module methods (attempted access to server.${String(prop)})`,
throw new VeriTixError(
VeriTixErrorCode.ClientNotConnected,
`VeriTixClient: call connect() before using module methods (attempted access to server.${String(prop)})`
);
}
return (this.server as unknown as Record<string | symbol, unknown>)[prop];
},
});
}
}
}
49 changes: 48 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@
// Client
// ---------------------------------------------------------------------------
export { VeriTixClient } from './client';
export { VeriTixClientExtended } from './client-extended';
export { createSafeToJSON, createSafeInspect } from './client-security';
export { VeriTixSDK } from './namespace';
export { createFromFreighter } from './modules/freighter-factory';
// NOTE: WatchOptions was previously exported from './client' (deprecated).
// The canonical export is from './types/index' below.
// @deprecated importing WatchOptions from './client' — use './types/index' directly.
Expand All @@ -31,6 +35,7 @@ export type {
ContractMetadata,
EscrowRecord,
TicketEscrowParams,
BatchSettlementResult,
SplitRecord,
SplitRecipient,
DisputeRecord,
Expand All @@ -52,6 +57,13 @@ export { SplitterModule } from './modules/splitter';
export { RecurringModule } from './modules/recurring';
export { AdminModule } from './modules/admin';
export { BatchModule } from './modules/batch';
export { EventsService } from './modules/events-service';
export { EventDashboard } from './modules/events-dashboard';
export { EventGalleryService } from './modules/event-gallery.service';
export { RevenueAnalyticsModule } from './modules/analytics/revenue-analytics.service';
export { TicketAnalyticsModule } from './modules/analytics/ticket-analytics.service';
export { CollaboratorModule } from './modules/collaborator/collaborator.service';
export { TicketPurchaseModule } from './modules/ticket/ticket-purchase.service';

// Module param types
export type { MintParams, BurnParams, TransferParams, ApproveParams } from './modules/token';
Expand All @@ -60,6 +72,17 @@ export type { OpenDisputeParams, ResolveDisputeParams } from './modules/dispute'
export type { CreateSplitParams } from './modules/splitter';
export type { SetupRecurringParams } from './modules/recurring';
export type { BatchMintEntry, BatchTransferEntry } from './modules/batch';
// New module types
export type { Event, EventFilter } from './modules/events-service';
export type { DashboardMetrics } from './modules/events-dashboard';
export type { RevenuePeriod, TicketSale } from './modules/analytics/revenue-analytics.service';
export type { TicketPeriod, ExportFormat, TicketOrder } from './modules/analytics/ticket-analytics.service';
export type { Collaborator, CollaboratorUpdate } from './modules/collaborator/collaborator.service';
export type { BillingDetails, AddressDetails, PurchaseRequest, Receipt } from './modules/ticket/ticket-purchase.service';

// Module constants
export { TRANSACTION_CHARGE_RATE } from './modules/analytics/revenue-analytics.service';
export { MAX_COLLABORATORS_PER_EVENT } from './modules/collaborator/collaborator.service';

// ---------------------------------------------------------------------------
// Errors
Expand All @@ -83,6 +106,30 @@ export {
assertValidAddress,
} from './utils/network';

// ---------------------------------------------------------------------------
// ScVal conversion helpers
// ---------------------------------------------------------------------------
export {
addressToScVal,
bigintToScVal,
boolToScVal,
stringToScVal,
scValToString,
scValToBigint,
scValToBoolean,
scValToNumber,
} from './utils/scval';

// ---------------------------------------------------------------------------
// XDR struct parsers
// ---------------------------------------------------------------------------
export {
parseEscrowRecord,
parseSplitRecord,
parseDisputeRecord,
parseRecurringRecord,
} from './utils/parsers';

// ---------------------------------------------------------------------------
// Format helpers
// ---------------------------------------------------------------------------
Expand All @@ -96,4 +143,4 @@ export {
buildContractCall,
simulateTransaction,
submitTransaction,
} from './utils/transaction';
} from './utils/transaction';
20 changes: 14 additions & 6 deletions src/modules/collaborator/collaborator.service.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { VeriTixError, VeriTixErrorCode } from '../../utils/errors';

/** A person collaborating on an event. */
export interface Collaborator {
id: string;
Expand All @@ -19,12 +21,15 @@ export class CollaboratorModule {

public add(collaborator: Collaborator): Collaborator {
if (this.collaborators.has(collaborator.id)) {
throw new Error(`Collaborator ${collaborator.id} already exists.`);
throw new VeriTixError(
VeriTixErrorCode.CollaboratorAlreadyExists,
`Collaborator ${collaborator.id} already exists.`
);
}
if (this.listByEvent(collaborator.eventId).length >= MAX_COLLABORATORS_PER_EVENT) {
throw new Error(
`Event ${collaborator.eventId} already has the maximum of ` +
`${MAX_COLLABORATORS_PER_EVENT} collaborators.`,
throw new VeriTixError(
VeriTixErrorCode.MaxCollaboratorsReached,
`Event ${collaborator.eventId} already has the maximum of ${MAX_COLLABORATORS_PER_EVENT} collaborators.`
);
}
this.collaborators.set(collaborator.id, collaborator);
Expand All @@ -46,7 +51,10 @@ export class CollaboratorModule {
public update(id: string, changes: CollaboratorUpdate): Collaborator {
const existing = this.collaborators.get(id);
if (!existing) {
throw new Error(`Collaborator ${id} not found.`);
throw new VeriTixError(
VeriTixErrorCode.CollaboratorNotFound,
`Collaborator ${id} not found.`
);
}
const updated: Collaborator = { ...existing, ...changes };
this.collaborators.set(id, updated);
Expand All @@ -56,4 +64,4 @@ export class CollaboratorModule {
public remove(id: string): boolean {
return this.collaborators.delete(id);
}
}
}
10 changes: 8 additions & 2 deletions src/modules/freighter-factory.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
// Factory for creating VeriTixClient from Freighter wallet
import { VeriTixClient } from '../client';
import { VeriTixError, VeriTixErrorCode } from '../utils/errors';

export async function createFromFreighter(network: string = 'testnet') {
try {
const freighter = (window as any).freighter;
if (!freighter) {
throw new Error('Freighter wallet not found');
throw new VeriTixError(
VeriTixErrorCode.FreighterNotFound,
'Freighter wallet not found'
);
}
const publicKey = await freighter.getPublicKey();
return new VeriTixClient({
Expand All @@ -15,4 +21,4 @@ export async function createFromFreighter(network: string = 'testnet') {
console.error('Failed to connect to Freighter:', error);
throw error;
}
}
}
19 changes: 15 additions & 4 deletions src/modules/splitter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,10 @@ export class SplitterModule {
// TODO: implement
void this.config;
void this.server;
throw new Error('SplitterModule.getSplit: not implemented');
throw new VeriTixError(
VeriTixErrorCode.NotImplemented,
'SplitterModule.getSplit: not implemented'
);
}

/**
Expand Down Expand Up @@ -232,7 +235,10 @@ export class SplitterModule {
// TODO: build & submit contract call
void simulateTransaction;
void submitTransaction;
throw new Error('SplitterModule.createSplit: not implemented');
throw new VeriTixError(
VeriTixErrorCode.NotImplemented,
'SplitterModule.createSplit: not implemented'
);
}

/**
Expand Down Expand Up @@ -381,7 +387,12 @@ export class SplitterModule {
* ```
*/
async distribute(_id: bigint): Promise<TransactionResult> {
throw new Error('SplitterModule.distribute: not implemented');
void this.server;
void _id;
throw new VeriTixError(
VeriTixErrorCode.NotImplemented,
'SplitterModule.distribute: not implemented'
);
}

/**
Expand Down Expand Up @@ -415,4 +426,4 @@ export class SplitterModule {

return { distributed, failed };
}
}
}
15 changes: 10 additions & 5 deletions src/modules/ticket/ticket-purchase.service.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { VeriTixError, VeriTixErrorCode } from '../../utils/errors';

/** Billing contact captured at checkout. */
export interface BillingDetails {
fullName: string;
Expand Down Expand Up @@ -38,12 +40,15 @@ export class TicketPurchaseModule {
/** Confirms a purchase against remaining availability and stores a receipt. */
public purchase(orderId: string, request: PurchaseRequest, available: number): Receipt {
if (!Number.isInteger(request.quantity) || request.quantity < 1) {
throw new Error('Ticket quantity must be a positive integer.');
throw new VeriTixError(
VeriTixErrorCode.InvalidAmount,
'Ticket quantity must be a positive integer.'
);
}
if (request.quantity > available) {
throw new Error(
`Only ${available} ticket(s) remain for event ${request.eventId}; ` +
`${request.quantity} requested.`,
throw new VeriTixError(
VeriTixErrorCode.InsufficientBalance,
`Only ${available} ticket(s) remain for event ${request.eventId}; ${request.quantity} requested.`
);
}
const receipt: Receipt = {
Expand All @@ -60,4 +65,4 @@ export class TicketPurchaseModule {
public getReceipt(orderId: string): Receipt | undefined {
return this.receipts.get(orderId);
}
}
}
37 changes: 30 additions & 7 deletions src/modules/user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
*/

import { SorobanRpc, Keypair } from '@stellar/stellar-sdk';
import { VeriTixError, VeriTixErrorCode } from '../utils/errors';
import type { NetworkConfig, TransactionResult } from '../types/index';

/**
Expand Down Expand Up @@ -49,7 +50,10 @@ export class AdminModule {
void this.config;
void this.server;
void this.keypair;
throw new Error('AdminModule.setAdmin: not implemented');
throw new VeriTixError(
VeriTixErrorCode.NotImplemented,
'AdminModule.setAdmin: not implemented'
);
}

// -------------------------------------------------------------------------
Expand All @@ -66,7 +70,11 @@ export class AdminModule {
*/
async freeze(_address: string): Promise<TransactionResult> {
// TODO: implement
throw new Error('AdminModule.freeze: not implemented');
void _address;
throw new VeriTixError(
VeriTixErrorCode.NotImplemented,
'AdminModule.freeze: not implemented'
);
}

/**
Expand All @@ -78,7 +86,11 @@ export class AdminModule {
*/
async unfreeze(_address: string): Promise<TransactionResult> {
// TODO: implement
throw new Error('AdminModule.unfreeze: not implemented');
void _address;
throw new VeriTixError(
VeriTixErrorCode.NotImplemented,
'AdminModule.unfreeze: not implemented'
);
}

// -------------------------------------------------------------------------
Expand All @@ -96,7 +108,12 @@ export class AdminModule {
*/
async clawback(_from: string, _amount: bigint): Promise<TransactionResult> {
// TODO: implement
throw new Error('AdminModule.clawback: not implemented');
void _from;
void _amount;
throw new VeriTixError(
VeriTixErrorCode.NotImplemented,
'AdminModule.clawback: not implemented'
);
}

// -------------------------------------------------------------------------
Expand All @@ -112,7 +129,10 @@ export class AdminModule {
*/
async pause(): Promise<TransactionResult> {
// TODO: implement
throw new Error('AdminModule.pause: not implemented');
throw new VeriTixError(
VeriTixErrorCode.NotImplemented,
'AdminModule.pause: not implemented'
);
}

/**
Expand All @@ -123,6 +143,9 @@ export class AdminModule {
*/
async unpause(): Promise<TransactionResult> {
// TODO: implement
throw new Error('AdminModule.unpause: not implemented');
throw new VeriTixError(
VeriTixErrorCode.NotImplemented,
'AdminModule.unpause: not implemented'
);
}
}
}
Loading
Loading