Skip to content

Instantly share code, notes, and snippets.

@hydrogenbond007
Created September 9, 2025 14:43
Show Gist options
  • Select an option

  • Save hydrogenbond007/5a0123232f886026aa00dcc4ada36997 to your computer and use it in GitHub Desktop.

Select an option

Save hydrogenbond007/5a0123232f886026aa00dcc4ada36997 to your computer and use it in GitHub Desktop.
/**
* @file campUSD integration with Nucleus SDK
* @description Configuration and functions for bridging USDC <-> campUSD using Nucleus SDK
*/
import {
prepareDepositTransactionData,
prepareWithdrawTransactionData,
prepareApproveDepositToken,
prepareApproveWithdrawToken,
VaultKeys,
type VaultKey,
type DepositTransactionData,
type WithdrawTransactionData,
type ApproveDepositTokenTransactionData,
type ApproveWithdrawTokenTransactionData,
} from "@molecularlabs/nucleus-frontend";
import { Address } from "viem";
// campUSD Nucleus configuration
export const CAMPUSD_VAULT_KEY: VaultKey = VaultKeys.CAMPUSD;
// Chain IDs
export const ETHEREUM_CHAIN_ID = 1;
export const CAMP_CHAIN_ID = 484;
// USDC token symbol for Nucleus SDK
export const USDC_TOKEN_SYMBOL = "USDC";
/**
* Interface for campUSD parameters
*/
export interface CampUSDDepositParams {
userAddress: Address;
depositAmount: string; // Amount in USDC as string (e.g., "100.00")
slippage?: number; // Optional slippage (e.g., 0.01 for 1%)
}
export interface CampUSDWithdrawParams {
userAddress: Address;
withdrawAmount: string; // Amount in campUSD shares as string
slippage?: number; // Optional slippage (e.g., 0.01 for 1%)
}
/**
* Prepares transaction data for depositing USDC into campUSD vault
* This implements the deposit flow: USDC -> campUSD vault shares
*/
export async function prepareCampUSDDeposit(
params: CampUSDDepositParams,
): Promise<DepositTransactionData> {
return await prepareDepositTransactionData({
vaultKey: CAMPUSD_VAULT_KEY,
userAddress: params.userAddress,
depositTokenSymbol: USDC_TOKEN_SYMBOL,
depositAmount: params.depositAmount,
chainId: ETHEREUM_CHAIN_ID,
slippage: params.slippage,
});
}
/**
* Prepares transaction data for withdrawing from campUSD vault
* This implements the withdraw flow: campUSD vault shares -> USDC
*/
export async function prepareCampUSDWithdraw(
params: CampUSDWithdrawParams,
): Promise<WithdrawTransactionData> {
return await prepareWithdrawTransactionData({
vaultKey: CAMPUSD_VAULT_KEY,
userAddress: params.userAddress,
offerAmount: params.withdrawAmount,
wantTokenSymbol: USDC_TOKEN_SYMBOL, // Token symbol we want to receive (USDC on Ethereum)
chainId: CAMP_CHAIN_ID, // Withdrawal starts on Camp Network where user has campUSD
slippage: params.slippage,
});
}
/**
* Prepares approval transaction for USDC before deposit
* depositAmount is optional - if not provided, will approve maximum amount
*/
export async function prepareCampUSDDepositApproval(params: {
userAddress: Address;
depositAmount?: string; // Optional: specific amount to approve
}): Promise<ApproveDepositTokenTransactionData> {
return await prepareApproveDepositToken({
vaultKey: CAMPUSD_VAULT_KEY,
depositTokenSymbol: USDC_TOKEN_SYMBOL,
depositAmount: params.depositAmount, // Optional: will use max if not provided
chainId: ETHEREUM_CHAIN_ID,
});
}
/**
* Check if campUSD vault shares are approved for withdrawal
* This function should use Nucleus SDK display functions when available
*/
export async function isWithdrawalSpendApproved({
userAddress,
withdrawalAmount,
}: {
userAddress: Address;
withdrawalAmount: string;
}): Promise<{
isApproved: boolean;
allowance: string;
allowanceAsBigInt: string;
decimals: number;
error: Error | null;
}> {
try {
console.log(
"πŸ” Checking campUSD vault shares withdrawal approval for:",
userAddress,
"amount:",
withdrawalAmount,
);
// TODO: Use Nucleus SDK display functions when available
// This should be replaced with the actual SDK approval checking function
const isApproved = false; // Will be replaced with actual SDK call
const allowance = "0";
const decimals = 18; // campUSD vault shares use 18 decimals
console.log(
`βœ… campUSD vault shares allowance check: ${allowance} (required: ${withdrawalAmount}) - Approved: ${isApproved}`,
);
return {
isApproved,
allowance,
allowanceAsBigInt: allowance,
decimals,
error: null,
};
} catch (error) {
console.error("❌ Failed to check campUSD vault shares allowance:", error);
return {
isApproved: false,
allowance: "0",
allowanceAsBigInt: "0",
decimals: 18,
error:
error instanceof Error ? error : new Error("Failed to check allowance"),
};
}
}
/**
* Check if USDC is approved for deposit
* This function should use Nucleus SDK display functions when available
*/
export async function isDepositSpendApproved({
userAddress,
depositAmount,
}: {
userAddress: Address;
depositAmount: string;
}): Promise<{
isApproved: boolean;
allowance: string;
allowanceAsBigInt: string;
decimals: number;
error: Error | null;
}> {
try {
console.log(
"πŸ” Checking USDC deposit approval for:",
userAddress,
"amount:",
depositAmount,
);
// TODO: Use Nucleus SDK display functions when available
// This should be replaced with the actual SDK approval checking function
const isApproved = false; // Will be replaced with actual SDK call
const allowance = "0";
const decimals = 6; // USDC uses 6 decimals
console.log(
`βœ… USDC allowance check: ${allowance} (required: ${depositAmount}) - Approved: ${isApproved}`,
);
return {
isApproved,
allowance,
allowanceAsBigInt: allowance,
decimals,
error: null,
};
} catch (error) {
console.error("❌ Failed to check USDC allowance:", error);
return {
isApproved: false,
allowance: "0",
allowanceAsBigInt: "0",
decimals: 6,
error:
error instanceof Error ? error : new Error("Failed to check allowance"),
};
}
}
/**
* Prepares approval transaction for campUSD vault shares before withdrawal
* withdrawAmount is optional - if not provided, will approve maximum amount
*/
export async function prepareCampUSDWithdrawalApproval(params: {
userAddress: Address;
withdrawAmount?: string; // Optional: specific amount to approve
}): Promise<ApproveWithdrawTokenTransactionData> {
return await prepareApproveWithdrawToken({
vaultKey: CAMPUSD_VAULT_KEY,
withdrawAmount: params.withdrawAmount, // Optional: will use max if not provided
chainId: CAMP_CHAIN_ID, // Approval happens on Camp Network where campUSD vault shares exist
});
}
/**
* campUSD token configuration for bridge UI
*/
export const CAMPUSD_TOKEN_CONFIG = {
id: "campusd",
symbol: "campUSD",
name: "Camp USD",
icon: "/usdc.svg", // Using USDC icon since campUSD is backed by USDC
decimals: 18, // campUSD uses 18 decimals (standard for Nucleus vaults)
description: "USD-backed stablecoin vault token powered by Nucleus",
// Ethereum configuration (source chain for deposits)
ethereum: {
isNative: false,
// campUSD vault shares contract address on Ethereum will be provided by Nucleus SDK
contractAddress: undefined, // Will be fetched from Nucleus SDK
symbol: "campUSD",
name: "CampUSD",
depositToken: {
symbol: "USDC",
name: "USDC",
contractAddress: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48" as Address,
decimals: 6,
},
},
// Camp Network configuration (destination chain for deposits)
camp: {
isNative: false,
// campUSD vault shares contract address on Camp Network will be provided by Nucleus SDK
contractAddress: undefined, // Will be fetched from Nucleus SDK
symbol: "campUSD",
name: "CampUSD",
withdrawToken: {
symbol: "USDC",
name: "USDC",
// Note: For withdrawals, USDC would be received on Ethereum mainnet
contractAddress: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48" as Address,
decimals: 6,
},
},
} as const;
/**
* Helper function to get campUSD token configuration for a specific direction
*/
export function getCampUSDTokenConfig(
direction: "eth-to-camp" | "camp-to-eth",
) {
if (direction === "eth-to-camp") {
return {
source: CAMPUSD_TOKEN_CONFIG.ethereum,
destination: CAMPUSD_TOKEN_CONFIG.camp,
sourceChainId: ETHEREUM_CHAIN_ID,
destinationChainId: CAMP_CHAIN_ID,
};
} else {
return {
source: CAMPUSD_TOKEN_CONFIG.camp,
destination: CAMPUSD_TOKEN_CONFIG.ethereum,
sourceChainId: CAMP_CHAIN_ID,
destinationChainId: ETHEREUM_CHAIN_ID,
};
}
}
/**
* Type for campUSD bridge operations
*/
export type CampUSDBridgeDirection = "deposit" | "withdraw";
export type CampUSDBridgeOperation = {
direction: CampUSDBridgeDirection;
sourceChain: number;
destinationChain: number;
tokenSymbol: string;
vaultKey: VaultKey;
};
export const CAMPUSD_OPERATIONS: Record<
CampUSDBridgeDirection,
CampUSDBridgeOperation
> = {
deposit: {
direction: "deposit",
sourceChain: ETHEREUM_CHAIN_ID,
destinationChain: CAMP_CHAIN_ID,
tokenSymbol: USDC_TOKEN_SYMBOL,
vaultKey: CAMPUSD_VAULT_KEY,
},
withdraw: {
direction: "withdraw",
sourceChain: CAMP_CHAIN_ID,
destinationChain: ETHEREUM_CHAIN_ID,
tokenSymbol: USDC_TOKEN_SYMBOL,
vaultKey: CAMPUSD_VAULT_KEY,
},
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment