provider.ts•2.62 kB
/**
* Starknet Provider Utilities
*/
import { RpcProvider, Contract } from 'starknet';
import type { ProviderConfig, StarknetNetwork } from '../types.js';
// Default RPC URLs
const DEFAULT_RPC_URLS = {
mainnet: 'https://starknet-mainnet.public.blastapi.io',
sepolia: 'https://starknet-sepolia.public.blastapi.io'
};
/**
* Create a configured Starknet RPC provider
*/
export function createProvider(config?: Partial<ProviderConfig>): RpcProvider {
const network = (process.env.STARKNET_NETWORK as StarknetNetwork) || config?.network || 'mainnet';
const nodeUrl = process.env.STARKNET_RPC_URL || config?.nodeUrl || DEFAULT_RPC_URLS[network];
return new RpcProvider({
nodeUrl
});
}
/**
* Get Chamber contract instance
*/
export async function getChamberContract(
provider: RpcProvider,
contractAddress: string,
abi: any
): Promise<any> {
return new Contract(abi, contractAddress, provider);
}
/**
* Validate Starknet address format
*/
export function isValidStarknetAddress(address: string): boolean {
// Starknet addresses start with 0x and are 64 hex characters (+ 0x prefix)
const addressRegex = /^0x[0-9a-fA-F]{1,64}$/;
return addressRegex.test(address);
}
import { CHAMBER_ADDR_MAINNET } from '@mistcash/config';
// Sepolia testnet address (fallback since not exported from config)
const CHAMBER_ADDR_SEPOLIA = '0x0';
/**
* Get the appropriate Chamber contract address based on configuration
* Priority:
* 1. CHAMBER_CONTRACT_ADDRESS env var (Custom/Madara)
* 2. Network default (Mainnet/Sepolia)
*/
export function getContractAddress(network: StarknetNetwork = 'mainnet'): string {
// 1. Check for custom override (e.g. for Madara/Appchains)
if (process.env.CHAMBER_CONTRACT_ADDRESS) {
return process.env.CHAMBER_CONTRACT_ADDRESS;
}
// 2. Return network default
return network === 'mainnet' ? CHAMBER_ADDR_MAINNET : CHAMBER_ADDR_SEPOLIA;
}
/**
* Retry helper with exponential backoff
*/
export async function retryWithBackoff<T>(
fn: () => Promise<T>,
maxRetries = 3,
baseDelay = 1000
): Promise<T> {
let lastError: Error;
for (let i = 0; i < maxRetries; i++) {
try {
return await fn();
} catch (error) {
lastError = error as Error;
if (i < maxRetries - 1) {
const delay = baseDelay * Math.pow(2, i);
await new Promise(resolve => setTimeout(resolve, delay));
}
}
}
throw lastError!;
}