@fairmint/canton-node-sdk
Version:
Canton Node SDK
300 lines • 13 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.EnvLoader = void 0;
const dotenv_1 = require("dotenv");
const path = __importStar(require("path"));
const fs = __importStar(require("fs"));
const errors_1 = require("../errors");
// Load environment variables with fallback to parent directory
const currentEnvPath = '.env';
const parentEnvPath = path.join('..', '.env');
// Try to load from current directory first
let result = (0, dotenv_1.config)({ path: currentEnvPath });
// If no .env file found in current directory, try parent directory
if (result.error && fs.existsSync(parentEnvPath)) {
result = (0, dotenv_1.config)({ path: parentEnvPath });
if (result.error) {
console.warn('Failed to load .env file from parent directory:', result.error.message);
}
}
/** Singleton class for managing environment variables and configuration */
class EnvLoader {
constructor(options = {}) {
this.env = process.env;
this.options = options;
}
static getInstance(options = {}) {
if (!EnvLoader.instance) {
EnvLoader.instance = new EnvLoader(options);
}
else if (options.currentNetwork || options.currentProvider) {
// Update existing instance with new options
EnvLoader.instance.options = { ...EnvLoader.instance.options, ...options };
}
return EnvLoader.instance;
}
static resetInstance() {
EnvLoader.instance = undefined;
}
/**
* Get configuration for a specific API type from environment variables
* @param apiType The API type to get configuration for
* @param options Optional network and provider to use instead of reading from env
* @returns ClientConfig with only the specified API configured
*/
static getConfig(apiType, options) {
const envLoader = EnvLoader.getInstance();
const network = options?.network || envLoader.getCurrentNetwork();
// For Lighthouse API, provider is optional
let provider;
let authUrl;
if (apiType === 'LIGHTHOUSE_API') {
// Lighthouse API doesn't require provider or auth URL
}
else {
provider = options?.provider || envLoader.getCurrentProvider();
authUrl = envLoader.getAuthUrl(network, provider);
}
// Get API-specific configuration
const apiConfig = envLoader.loadApiConfig(apiType, network, provider || undefined);
if (!apiConfig) {
if (apiType === 'LIGHTHOUSE_API') {
throw new errors_1.ConfigurationError(`Missing required environment variable for ${apiType}. ` +
`Required: CANTON_${network.toUpperCase()}_${apiType.toUpperCase()}_URI`);
}
else {
const providerStr = provider ? provider.toUpperCase() : 'PROVIDER';
throw new errors_1.ConfigurationError(`Missing required environment variables for ${apiType}. ` +
`Required: CANTON_${network.toUpperCase()}_${providerStr}_${apiType.toUpperCase()}_URI, ` +
`CANTON_${network.toUpperCase()}_${providerStr}_${apiType.toUpperCase()}_CLIENT_ID, ` +
`and either CLIENT_SECRET (for client_credentials) or USERNAME/PASSWORD (for password grant)`);
}
}
const config = {
network,
apis: {
[apiType]: apiConfig,
},
};
// Only add provider and authUrl if they exist
if (provider) {
config.provider = provider;
}
if (authUrl) {
config.authUrl = authUrl;
}
return config;
}
getNodeEnv() {
const value = this.env['NODE_ENV'] || 'development';
if (!['development', 'production', 'test'].includes(value)) {
throw new errors_1.ConfigurationError(`Invalid NODE_ENV: ${value}. Must be 'development', 'production', or 'test'`);
}
return value;
}
getCurrentNetwork() {
if (this.options.currentNetwork) {
return this.options.currentNetwork;
}
const value = this.env['CANTON_CURRENT_NETWORK']?.toLowerCase();
if (!value || !['devnet', 'testnet', 'mainnet'].includes(value)) {
throw new errors_1.ConfigurationError('Missing or invalid CANTON_CURRENT_NETWORK. Must be "devnet", "testnet", or "mainnet"');
}
return value;
}
getCurrentProvider() {
if (this.options.currentProvider) {
return this.options.currentProvider;
}
const value = this.env['CANTON_CURRENT_PROVIDER']?.toLowerCase();
if (!value) {
throw new errors_1.ConfigurationError('Missing or invalid CANTON_CURRENT_PROVIDER');
}
return value;
}
getApiUri(apiType, network, provider) {
const targetNetwork = network || this.getCurrentNetwork();
// Special case for APIs that don't require provider-specific configuration
if (apiType === 'LIGHTHOUSE_API') {
const envKey = `CANTON_${targetNetwork.toUpperCase()}_${apiType.toUpperCase()}_URI`;
const uri = this.env[envKey];
return uri;
}
const targetProvider = provider || this.getCurrentProvider();
const envKey = `CANTON_${targetNetwork.toUpperCase()}_${targetProvider.toUpperCase()}_${apiType.toUpperCase()}_URI`;
const uri = this.env[envKey];
return uri;
}
getApiClientId(apiType, network, provider) {
const targetNetwork = network || this.getCurrentNetwork();
const targetProvider = provider || this.getCurrentProvider();
const envKey = `CANTON_${targetNetwork.toUpperCase()}_${targetProvider.toUpperCase()}_${apiType.toUpperCase()}_CLIENT_ID`;
return this.env[envKey];
}
getApiClientSecret(apiType, network, provider) {
const targetNetwork = network || this.getCurrentNetwork();
const targetProvider = provider || this.getCurrentProvider();
const envKey = `CANTON_${targetNetwork.toUpperCase()}_${targetProvider.toUpperCase()}_${apiType.toUpperCase()}_CLIENT_SECRET`;
return this.env[envKey];
}
getApiUsername(apiType, network, provider) {
const targetNetwork = network || this.getCurrentNetwork();
const targetProvider = provider || this.getCurrentProvider();
const envKey = `CANTON_${targetNetwork.toUpperCase()}_${targetProvider.toUpperCase()}_${apiType.toUpperCase()}_USERNAME`;
return this.env[envKey];
}
getApiPassword(apiType, network, provider) {
const targetNetwork = network || this.getCurrentNetwork();
const targetProvider = provider || this.getCurrentProvider();
const envKey = `CANTON_${targetNetwork.toUpperCase()}_${targetProvider.toUpperCase()}_${apiType.toUpperCase()}_PASSWORD`;
return this.env[envKey];
}
getAuthUrl(network, provider) {
const targetNetwork = network || this.getCurrentNetwork();
const targetProvider = provider || this.getCurrentProvider();
const envKey = `CANTON_${targetNetwork.toUpperCase()}_${targetProvider.toUpperCase()}_AUTH_URL`;
const authUrl = this.env[envKey];
if (!authUrl) {
throw new errors_1.ConfigurationError(`Missing required environment variable: ${envKey}`);
}
return authUrl;
}
getPartyId(network, provider) {
const targetNetwork = network || this.getCurrentNetwork();
const targetProvider = provider || this.getCurrentProvider();
const envKey = `CANTON_${targetNetwork.toUpperCase()}_${targetProvider.toUpperCase()}_PARTY_ID`;
const partyId = this.env[envKey];
if (!partyId) {
throw new errors_1.ConfigurationError(`Missing required environment variable: ${envKey}`);
}
return partyId;
}
getUserId(network, provider) {
const targetNetwork = network || this.getCurrentNetwork();
const targetProvider = provider || this.getCurrentProvider();
const envKey = `CANTON_${targetNetwork.toUpperCase()}_${targetProvider.toUpperCase()}_USER_ID`;
return this.env[envKey];
}
getDatabaseUrl(network) {
const targetNetwork = network || this.getCurrentNetwork();
const envKey = `CANTON_${targetNetwork.toUpperCase()}_DATABASE_URL`;
const databaseUrl = this.env[envKey];
if (!databaseUrl) {
throw new errors_1.ConfigurationError(`Missing required environment variable: ${envKey}`);
}
return databaseUrl;
}
getManagedParties(network, provider) {
const targetNetwork = network || this.getCurrentNetwork();
const targetProvider = provider || this.getCurrentProvider();
const envKey = `CANTON_${targetNetwork.toUpperCase()}_${targetProvider.toUpperCase()}_MANAGED_PARTIES`;
const managedParties = this.env[envKey];
if (!managedParties) {
return [];
}
return managedParties.split(',').map(party => party.trim()).filter(party => party.length > 0);
}
loadApiConfig(apiType, network, provider) {
const apiUrl = this.getApiUri(apiType, network, provider);
// Special case for APIs that don't require authentication
if (apiType === 'LIGHTHOUSE_API') {
if (!apiUrl) {
return undefined;
}
const lighthouseConfig = {
apiUrl,
};
// Lighthouse API doesn't require party ID at client level
// Party ID will be provided in individual API calls
return lighthouseConfig;
}
if (!provider) {
return undefined; // Non-Lighthouse APIs require a provider
}
const clientId = this.getApiClientId(apiType, network, provider);
const clientSecret = this.getApiClientSecret(apiType, network, provider);
const username = this.getApiUsername(apiType, network, provider);
const password = this.getApiPassword(apiType, network, provider);
const partyId = this.getPartyId(network, provider);
const userId = this.getUserId(network, provider);
if (!apiUrl || !clientId) {
return undefined;
}
// Determine grant type based on available credentials
let grantType;
let auth;
if (clientSecret) {
// Use client_credentials if client secret is available
grantType = 'client_credentials';
auth = {
grantType,
clientId: clientId || '',
clientSecret,
};
}
else if (username && password) {
// Use password grant if username and password are available
grantType = 'password';
auth = {
grantType,
clientId: clientId || '',
username,
password,
};
}
else {
// Fallback to client_credentials without secret (some providers may not require it)
grantType = 'client_credentials';
auth = {
grantType,
clientId: clientId || '',
};
}
const apiConfig = {
apiUrl: apiUrl || '',
auth,
};
if (partyId) {
apiConfig.partyId = String(partyId);
}
if (userId) {
apiConfig.userId = String(userId);
}
return apiConfig;
}
}
exports.EnvLoader = EnvLoader;
//# sourceMappingURL=EnvLoader.js.map