Fix privy secrets
This commit is contained in:
@@ -8,13 +8,17 @@ namespace Managing.Application.Whitelist;
|
|||||||
public class WhitelistService : IWhitelistService
|
public class WhitelistService : IWhitelistService
|
||||||
{
|
{
|
||||||
private readonly IWhitelistRepository _whitelistRepository;
|
private readonly IWhitelistRepository _whitelistRepository;
|
||||||
|
private readonly IWebhookService _webhookService;
|
||||||
private readonly ILogger<WhitelistService> _logger;
|
private readonly ILogger<WhitelistService> _logger;
|
||||||
|
private const string AlertsChannel = "2676086723";
|
||||||
|
|
||||||
public WhitelistService(
|
public WhitelistService(
|
||||||
IWhitelistRepository whitelistRepository,
|
IWhitelistRepository whitelistRepository,
|
||||||
|
IWebhookService webhookService,
|
||||||
ILogger<WhitelistService> logger)
|
ILogger<WhitelistService> logger)
|
||||||
{
|
{
|
||||||
_whitelistRepository = whitelistRepository;
|
_whitelistRepository = whitelistRepository;
|
||||||
|
_webhookService = webhookService;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -58,9 +62,105 @@ public class WhitelistService : IWhitelistService
|
|||||||
_logger.LogInformation("Successfully updated {Count} account(s) to IsWhitelisted = {IsWhitelisted}",
|
_logger.LogInformation("Successfully updated {Count} account(s) to IsWhitelisted = {IsWhitelisted}",
|
||||||
updatedCount, isWhitelisted);
|
updatedCount, isWhitelisted);
|
||||||
|
|
||||||
|
// Send notification to Alert channel when users are whitelisted
|
||||||
|
if (isWhitelisted && updatedCount > 0)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await SendWhitelistNotificationAsync(idsList);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "Failed to send whitelist notification for account IDs: {AccountIds}",
|
||||||
|
string.Join(", ", idsList));
|
||||||
|
SentrySdk.CaptureException(ex);
|
||||||
|
// Don't throw - notification failure shouldn't fail the whitelist operation
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return updatedCount;
|
return updatedCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task SendWhitelistNotificationAsync(List<int> accountIds)
|
||||||
|
{
|
||||||
|
var accounts = new List<WhitelistAccount>();
|
||||||
|
|
||||||
|
// Fetch account details for the notification
|
||||||
|
foreach (var id in accountIds)
|
||||||
|
{
|
||||||
|
var account = await _whitelistRepository.GetByIdAsync(id);
|
||||||
|
if (account != null)
|
||||||
|
{
|
||||||
|
accounts.Add(account);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!accounts.Any())
|
||||||
|
{
|
||||||
|
_logger.LogWarning("No accounts found to send whitelist notification for IDs: {AccountIds}",
|
||||||
|
string.Join(", ", accountIds));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build notification message
|
||||||
|
var message = accounts.Count == 1
|
||||||
|
? BuildSingleAccountWhitelistMessage(accounts[0])
|
||||||
|
: BuildMultipleAccountsWhitelistMessage(accounts);
|
||||||
|
|
||||||
|
await _webhookService.SendMessage(message, AlertsChannel);
|
||||||
|
|
||||||
|
_logger.LogInformation("Sent whitelist notification to Alert channel for {Count} account(s)", accounts.Count);
|
||||||
|
}
|
||||||
|
|
||||||
|
private string BuildSingleAccountWhitelistMessage(WhitelistAccount account)
|
||||||
|
{
|
||||||
|
var message = $"✅ **User Whitelisted**\n" +
|
||||||
|
$"Account ID: `{account.Id}`\n" +
|
||||||
|
$"Privy ID: `{account.PrivyId}`\n" +
|
||||||
|
$"Embedded Wallet: `{account.EmbeddedWallet}`\n";
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(account.ExternalEthereumAccount))
|
||||||
|
{
|
||||||
|
message += $"External Ethereum: `{account.ExternalEthereumAccount}`\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(account.TwitterAccount))
|
||||||
|
{
|
||||||
|
message += $"Twitter: `{account.TwitterAccount}`\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
message += $"Time: {DateTime.UtcNow:yyyy-MM-dd HH:mm:ss} UTC";
|
||||||
|
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string BuildMultipleAccountsWhitelistMessage(List<WhitelistAccount> accounts)
|
||||||
|
{
|
||||||
|
var message = $"✅ **{accounts.Count} Users Whitelisted**\n\n";
|
||||||
|
|
||||||
|
foreach (var account in accounts)
|
||||||
|
{
|
||||||
|
message += $"• Account ID: `{account.Id}` | Privy ID: `{account.PrivyId}`\n";
|
||||||
|
message += $" Wallet: `{account.EmbeddedWallet}`\n";
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(account.ExternalEthereumAccount))
|
||||||
|
{
|
||||||
|
message += $" External Ethereum: `{account.ExternalEthereumAccount}`\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(account.TwitterAccount))
|
||||||
|
{
|
||||||
|
message += $" Twitter: `{account.TwitterAccount}`\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
message += "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
message += $"Time: {DateTime.UtcNow:yyyy-MM-dd HH:mm:ss} UTC";
|
||||||
|
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
public async Task<WhitelistAccount?> GetByIdAsync(int id)
|
public async Task<WhitelistAccount?> GetByIdAsync(int id)
|
||||||
{
|
{
|
||||||
return await _whitelistRepository.GetByIdAsync(id);
|
return await _whitelistRepository.GetByIdAsync(id);
|
||||||
@@ -85,7 +185,8 @@ public class WhitelistService : IWhitelistService
|
|||||||
string? externalEthereumAccount,
|
string? externalEthereumAccount,
|
||||||
string? twitterAccount)
|
string? twitterAccount)
|
||||||
{
|
{
|
||||||
_logger.LogInformation("Processing Privy webhook - PrivyId: {PrivyId}, Wallet: {Wallet}, ExternalEthereum: {ExternalEthereum}, Twitter: {Twitter}",
|
_logger.LogInformation(
|
||||||
|
"Processing Privy webhook - PrivyId: {PrivyId}, Wallet: {Wallet}, ExternalEthereum: {ExternalEthereum}, Twitter: {Twitter}",
|
||||||
privyUserId, walletAddress, externalEthereumAccount ?? "null", twitterAccount ?? "null");
|
privyUserId, walletAddress, externalEthereumAccount ?? "null", twitterAccount ?? "null");
|
||||||
|
|
||||||
// Convert Unix timestamp to UTC DateTime (PostgreSQL requires UTC)
|
// Convert Unix timestamp to UTC DateTime (PostgreSQL requires UTC)
|
||||||
@@ -93,7 +194,7 @@ public class WhitelistService : IWhitelistService
|
|||||||
|
|
||||||
// Check if account already exists
|
// Check if account already exists
|
||||||
var existing = await _whitelistRepository.GetByPrivyIdAsync(privyUserId) ??
|
var existing = await _whitelistRepository.GetByPrivyIdAsync(privyUserId) ??
|
||||||
await _whitelistRepository.GetByEmbeddedWalletAsync(walletAddress);
|
await _whitelistRepository.GetByEmbeddedWalletAsync(walletAddress);
|
||||||
|
|
||||||
var whitelistAccount = new WhitelistAccount
|
var whitelistAccount = new WhitelistAccount
|
||||||
{
|
{
|
||||||
@@ -120,4 +221,3 @@ public class WhitelistService : IWhitelistService
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -408,7 +408,7 @@ public static class ApiBootstrap
|
|||||||
|
|
||||||
|
|
||||||
services.AddTransient<IWeb3ProxyService, Web3ProxyService>();
|
services.AddTransient<IWeb3ProxyService, Web3ProxyService>();
|
||||||
services.AddTransient<IWebhookService, WebhookService>();
|
services.AddHttpClient<IWebhookService, WebhookService>();
|
||||||
services.AddTransient<IKaigenService, KaigenService>();
|
services.AddTransient<IKaigenService, KaigenService>();
|
||||||
services.AddTransient<IWhitelistService, WhitelistService>();
|
services.AddTransient<IWhitelistService, WhitelistService>();
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,28 @@ declare module 'fastify' {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Module-level cache for Privy secrets - accessible without Fastify instance
|
||||||
|
// This is populated ONCE at startup and never changed during runtime
|
||||||
|
let cachedPrivySecrets: {
|
||||||
|
appId: string
|
||||||
|
appSecret: string
|
||||||
|
authKey: string
|
||||||
|
} | null = null
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the cached Privy secrets (called once at startup)
|
||||||
|
*/
|
||||||
|
export function setCachedPrivySecrets(secrets: { appId: string; appSecret: string; authKey: string }) {
|
||||||
|
cachedPrivySecrets = secrets
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the cached Privy secrets (for use without Fastify instance)
|
||||||
|
*/
|
||||||
|
export function getCachedPrivySecrets(): { appId: string; appSecret: string; authKey: string } | null {
|
||||||
|
return cachedPrivySecrets
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads Privy secrets ONCE at application startup from Infisical (production) or env vars/files (non-production).
|
* Loads Privy secrets ONCE at application startup from Infisical (production) or env vars/files (non-production).
|
||||||
* Secrets are cached in memory via Fastify decorator and never reloaded during runtime.
|
* Secrets are cached in memory via Fastify decorator and never reloaded during runtime.
|
||||||
@@ -81,10 +103,32 @@ export default fp(async function (fastify) {
|
|||||||
const privyAppSecretSecret = allSecrets.secrets?.find(s => s.secretKey === 'PRIVY_APP_SECRET')
|
const privyAppSecretSecret = allSecrets.secrets?.find(s => s.secretKey === 'PRIVY_APP_SECRET')
|
||||||
const privyAuthKeySecret = allSecrets.secrets?.find(s => s.secretKey === 'PRIVY_AUTHORIZATION_KEY')
|
const privyAuthKeySecret = allSecrets.secrets?.find(s => s.secretKey === 'PRIVY_AUTHORIZATION_KEY')
|
||||||
|
|
||||||
|
// Log which secrets were found
|
||||||
|
fastify.log.info({
|
||||||
|
foundAppId: !!privyAppIdSecret,
|
||||||
|
foundAppSecret: !!privyAppSecretSecret,
|
||||||
|
foundAuthKey: !!privyAuthKeySecret,
|
||||||
|
allSecretKeys: allSecrets.secrets?.map(s => s.secretKey) || []
|
||||||
|
}, 'Checking for Privy secrets in Infisical response')
|
||||||
|
|
||||||
appId = privyAppIdSecret?.secretValue || process.env.PRIVY_APP_ID || ''
|
appId = privyAppIdSecret?.secretValue || process.env.PRIVY_APP_ID || ''
|
||||||
appSecret = privyAppSecretSecret?.secretValue || process.env.PRIVY_APP_SECRET || ''
|
appSecret = privyAppSecretSecret?.secretValue || process.env.PRIVY_APP_SECRET || ''
|
||||||
authKey = privyAuthKeySecret?.secretValue || process.env.PRIVY_AUTHORIZATION_KEY || ''
|
authKey = privyAuthKeySecret?.secretValue || process.env.PRIVY_AUTHORIZATION_KEY || ''
|
||||||
|
|
||||||
|
// Validate that we got the secrets
|
||||||
|
if (!appId || !appSecret || !authKey) {
|
||||||
|
fastify.log.error({
|
||||||
|
hasAppId: !!appId,
|
||||||
|
hasAppSecret: !!appSecret,
|
||||||
|
hasAuthKey: !!authKey,
|
||||||
|
fromInfisical: {
|
||||||
|
appId: !!privyAppIdSecret,
|
||||||
|
appSecret: !!privyAppSecretSecret,
|
||||||
|
authKey: !!privyAuthKeySecret
|
||||||
|
}
|
||||||
|
}, '⚠️ Privy secrets incomplete after loading from Infisical')
|
||||||
|
}
|
||||||
|
|
||||||
fastify.log.info({
|
fastify.log.info({
|
||||||
appId: !!appId,
|
appId: !!appId,
|
||||||
appSecret: !!appSecret,
|
appSecret: !!appSecret,
|
||||||
@@ -139,6 +183,13 @@ export default fp(async function (fastify) {
|
|||||||
nodeEnv: process.env.NODE_ENV
|
nodeEnv: process.env.NODE_ENV
|
||||||
}, '⚠️ WARNING: Privy secrets not fully resolved at plugin load - app will continue but Privy operations will fail')
|
}, '⚠️ WARNING: Privy secrets not fully resolved at plugin load - app will continue but Privy operations will fail')
|
||||||
|
|
||||||
|
// Store in module-level cache (even if empty, so getPrivyClient can detect the issue)
|
||||||
|
setCachedPrivySecrets({
|
||||||
|
appId: appId || '',
|
||||||
|
appSecret: appSecret || '',
|
||||||
|
authKey: authKey || ''
|
||||||
|
})
|
||||||
|
|
||||||
// Still decorate with empty strings so the app doesn't crash
|
// Still decorate with empty strings so the app doesn't crash
|
||||||
// The actual error will be thrown in getPrivyClient when it's used
|
// The actual error will be thrown in getPrivyClient when it's used
|
||||||
fastify.decorate('privySecrets', {
|
fastify.decorate('privySecrets', {
|
||||||
@@ -164,6 +215,13 @@ export default fp(async function (fastify) {
|
|||||||
return // Continue without throwing
|
return // Continue without throwing
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Store secrets in module-level cache (accessible without Fastify instance)
|
||||||
|
setCachedPrivySecrets({
|
||||||
|
appId,
|
||||||
|
appSecret,
|
||||||
|
authKey
|
||||||
|
})
|
||||||
|
|
||||||
// Decorate Fastify instance with secrets - these are cached in memory for the lifetime of the application
|
// Decorate Fastify instance with secrets - these are cached in memory for the lifetime of the application
|
||||||
// This decoration happens ONCE at startup, and secrets are reused from memory for all Privy client creations
|
// This decoration happens ONCE at startup, and secrets are reused from memory for all Privy client creations
|
||||||
fastify.decorate('privySecrets', {
|
fastify.decorate('privySecrets', {
|
||||||
@@ -176,7 +234,7 @@ export default fp(async function (fastify) {
|
|||||||
appId: appId.substring(0, 10) + '...',
|
appId: appId.substring(0, 10) + '...',
|
||||||
appSecret: appSecret.substring(0, 10) + '...',
|
appSecret: appSecret.substring(0, 10) + '...',
|
||||||
authKey: authKey.substring(0, 20) + '...',
|
authKey: authKey.substring(0, 20) + '...',
|
||||||
note: 'Secrets cached in memory - Infisical will not be called again during runtime'
|
note: 'Secrets cached in memory (module-level and Fastify decorator) - Infisical will not be called again during runtime'
|
||||||
}, '✅ Privy secrets loaded at startup and cached in memory')
|
}, '✅ Privy secrets loaded at startup and cached in memory')
|
||||||
}, {
|
}, {
|
||||||
name: 'privy-secrets',
|
name: 'privy-secrets',
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import {CONTRACTS} from '../../generated/gmxsdk/configs/contracts.js'
|
|||||||
import {getClientForAddress, getTokenDataFromTicker} from './gmx.js'
|
import {getClientForAddress, getTokenDataFromTicker} from './gmx.js'
|
||||||
import {Address} from 'viem'
|
import {Address} from 'viem'
|
||||||
import {Balance, Chain, Ticker} from '../../generated/ManagingApiTypes.js'
|
import {Balance, Chain, Ticker} from '../../generated/ManagingApiTypes.js'
|
||||||
|
import {getCachedPrivySecrets} from './privy-secrets.js'
|
||||||
|
|
||||||
// Load environment variables in non-production only
|
// Load environment variables in non-production only
|
||||||
if (process.env.NODE_ENV !== 'production') dotenv.config()
|
if (process.env.NODE_ENV !== 'production') dotenv.config()
|
||||||
@@ -59,16 +60,20 @@ declare module 'fastify' {
|
|||||||
*/
|
*/
|
||||||
export const getPrivyClient = (fastify?: FastifyInstance): PrivyClient => {
|
export const getPrivyClient = (fastify?: FastifyInstance): PrivyClient => {
|
||||||
// Read from cached secrets in memory (loaded once at startup):
|
// Read from cached secrets in memory (loaded once at startup):
|
||||||
// 1. Fastify decorator (populated by privy-secrets plugin at startup - Infisical in prod, env in dev)
|
// Priority order:
|
||||||
// 2. Fastify config (from env plugin)
|
// 1. Module-level cache (populated by privy-secrets plugin at startup - accessible without Fastify instance)
|
||||||
// 3. Environment variables (fallback)
|
// 2. Fastify decorator (populated by privy-secrets plugin at startup - Infisical in prod, env in dev)
|
||||||
// Note: In production, secrets come from Infisical and are cached in fastify.privySecrets at startup
|
// 3. Fastify config (from env plugin)
|
||||||
|
// 4. Environment variables (fallback)
|
||||||
|
// Note: In production, secrets come from Infisical and are cached in module-level variable and fastify.privySecrets at startup
|
||||||
|
|
||||||
|
// First, try module-level cache (works without Fastify instance)
|
||||||
|
const cachedSecrets = getCachedPrivySecrets()
|
||||||
const decorated = (fastify as any)?.privySecrets as { appId: string; appSecret: string; authKey: string } | undefined
|
const decorated = (fastify as any)?.privySecrets as { appId: string; appSecret: string; authKey: string } | undefined
|
||||||
|
|
||||||
const appId = decorated?.appId || fastify?.config?.PRIVY_APP_ID || process.env.PRIVY_APP_ID
|
const appId = cachedSecrets?.appId || decorated?.appId || fastify?.config?.PRIVY_APP_ID || process.env.PRIVY_APP_ID
|
||||||
const appSecret = decorated?.appSecret || fastify?.config?.PRIVY_APP_SECRET || process.env.PRIVY_APP_SECRET
|
const appSecret = cachedSecrets?.appSecret || decorated?.appSecret || fastify?.config?.PRIVY_APP_SECRET || process.env.PRIVY_APP_SECRET
|
||||||
const authKey = decorated?.authKey || fastify?.config?.PRIVY_AUTHORIZATION_KEY || process.env.PRIVY_AUTHORIZATION_KEY
|
const authKey = cachedSecrets?.authKey || decorated?.authKey || fastify?.config?.PRIVY_AUTHORIZATION_KEY || process.env.PRIVY_AUTHORIZATION_KEY
|
||||||
|
|
||||||
if (!appId || !appSecret || !authKey) {
|
if (!appId || !appSecret || !authKey) {
|
||||||
console.warn('Missing Privy environment variables:');
|
console.warn('Missing Privy environment variables:');
|
||||||
@@ -76,6 +81,7 @@ export const getPrivyClient = (fastify?: FastifyInstance): PrivyClient => {
|
|||||||
console.warn('PRIVY_APP_SECRET:', appSecret ? 'present' : 'missing');
|
console.warn('PRIVY_APP_SECRET:', appSecret ? 'present' : 'missing');
|
||||||
console.warn('PRIVY_AUTHORIZATION_KEY:', authKey ? 'present' : 'missing');
|
console.warn('PRIVY_AUTHORIZATION_KEY:', authKey ? 'present' : 'missing');
|
||||||
console.warn('NODE_ENV:', process.env.NODE_ENV);
|
console.warn('NODE_ENV:', process.env.NODE_ENV);
|
||||||
|
console.warn('Module-level cache available:', !!cachedSecrets);
|
||||||
console.warn('Fastify privySecrets decorated:', !!decorated);
|
console.warn('Fastify privySecrets decorated:', !!decorated);
|
||||||
console.warn('Fastify config available:', !!fastify?.config);
|
console.warn('Fastify config available:', !!fastify?.config);
|
||||||
|
|
||||||
@@ -108,8 +114,10 @@ export async function getAuthorizationSignature(
|
|||||||
fastify?: FastifyInstance
|
fastify?: FastifyInstance
|
||||||
) {
|
) {
|
||||||
// Get app ID from cached secrets (loaded once at startup) or env fallback
|
// Get app ID from cached secrets (loaded once at startup) or env fallback
|
||||||
|
// Priority: module-level cache > Fastify decorator > Fastify config > env vars
|
||||||
|
const cachedSecrets = getCachedPrivySecrets()
|
||||||
const decorated = (fastify as any)?.privySecrets as { appId: string; authKey: string } | undefined
|
const decorated = (fastify as any)?.privySecrets as { appId: string; authKey: string } | undefined
|
||||||
const appId = decorated?.appId || fastify?.config?.PRIVY_APP_ID || process.env.PRIVY_APP_ID || ''
|
const appId = cachedSecrets?.appId || decorated?.appId || fastify?.config?.PRIVY_APP_ID || process.env.PRIVY_APP_ID || ''
|
||||||
|
|
||||||
const payload = {
|
const payload = {
|
||||||
version: 1,
|
version: 1,
|
||||||
@@ -127,10 +135,12 @@ export async function getAuthorizationSignature(
|
|||||||
const serializedPayloadBuffer = Buffer.from(serializedPayload);
|
const serializedPayloadBuffer = Buffer.from(serializedPayload);
|
||||||
|
|
||||||
// Resolve authorization key from cached secrets (loaded once at startup from Infisical in production)
|
// Resolve authorization key from cached secrets (loaded once at startup from Infisical in production)
|
||||||
|
// Priority: module-level cache > Fastify decorator > Fastify config > file > env vars
|
||||||
let resolvedKey: string | undefined
|
let resolvedKey: string | undefined
|
||||||
|
|
||||||
// Try Fastify decorator first (secrets cached in memory from Infisical at startup in production)
|
if (cachedSecrets?.authKey) {
|
||||||
if (decorated?.authKey) {
|
resolvedKey = cachedSecrets.authKey
|
||||||
|
} else if (decorated?.authKey) {
|
||||||
resolvedKey = decorated.authKey
|
resolvedKey = decorated.authKey
|
||||||
} else if (fastify?.config?.PRIVY_AUTHORIZATION_KEY) {
|
} else if (fastify?.config?.PRIVY_AUTHORIZATION_KEY) {
|
||||||
resolvedKey = fastify.config.PRIVY_AUTHORIZATION_KEY
|
resolvedKey = fastify.config.PRIVY_AUTHORIZATION_KEY
|
||||||
@@ -176,11 +186,12 @@ export const makePrivyRequest = async <T>(
|
|||||||
): Promise<T> => {
|
): Promise<T> => {
|
||||||
try {
|
try {
|
||||||
// Resolve secrets from cached memory (loaded once at startup from Infisical in production)
|
// Resolve secrets from cached memory (loaded once at startup from Infisical in production)
|
||||||
|
// Priority: module-level cache > Fastify decorator > Fastify config > env vars
|
||||||
|
const cachedSecrets = getCachedPrivySecrets()
|
||||||
const decorated = (fastify as any)?.privySecrets as { appId: string; appSecret: string } | undefined
|
const decorated = (fastify as any)?.privySecrets as { appId: string; appSecret: string } | undefined
|
||||||
|
|
||||||
// Try Fastify decorator first (secrets cached in memory from Infisical at startup in production)
|
const appId = cachedSecrets?.appId || decorated?.appId || fastify?.config?.PRIVY_APP_ID || process.env.PRIVY_APP_ID || ''
|
||||||
const appId = decorated?.appId || fastify?.config?.PRIVY_APP_ID || process.env.PRIVY_APP_ID || ''
|
const appSecret = cachedSecrets?.appSecret || decorated?.appSecret || fastify?.config?.PRIVY_APP_SECRET || process.env.PRIVY_APP_SECRET || ''
|
||||||
const appSecret = decorated?.appSecret || fastify?.config?.PRIVY_APP_SECRET || process.env.PRIVY_APP_SECRET || ''
|
|
||||||
|
|
||||||
let headers: Record<string, string> = {
|
let headers: Record<string, string> = {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
|||||||
Reference in New Issue
Block a user