Get cost of deployment using newly published records

This commit is contained in:
Shreerang Kale 2025-07-24 11:02:24 +05:30
parent 7a912d03dd
commit 37051c5145
4 changed files with 42 additions and 40 deletions

View File

@ -4,10 +4,10 @@
# TODO: Use different RPC URL or use browser wallet # TODO: Use different RPC URL or use browser wallet
NEXT_PUBLIC_SOLANA_RPC_URL=https://skilled-prettiest-seed.solana-mainnet.quiknode.pro/eeecfebd04e345f69f1900cc3483cbbfea02a158 NEXT_PUBLIC_SOLANA_RPC_URL=https://skilled-prettiest-seed.solana-mainnet.quiknode.pro/eeecfebd04e345f69f1900cc3483cbbfea02a158
NEXT_PUBLIC_SOLANA_TOKEN_MINT_ADDRESS=71Jvq4Epe2FCJ7JFSF7jLXdNk1Wy4Bhqd9iL6bEFELvg NEXT_PUBLIC_SOLANA_TOKEN_MINT_ADDRESS=71Jvq4Epe2FCJ7JFSF7jLXdNk1Wy4Bhqd9iL6bEFELvg
NEXT_PUBLIC_SOLANA_TOKEN_SYMBOL=GOR
# Multisig address # Multisig address
NEXT_PUBLIC_SOLANA_TOKEN_RECIPIENT_ADDRESS=FFDx3SdAEeXrp6BTmStB4BDHpctGsaasZq4FFcowRobY NEXT_PUBLIC_SOLANA_TOKEN_RECIPIENT_ADDRESS=FFDx3SdAEeXrp6BTmStB4BDHpctGsaasZq4FFcowRobY
NEXT_PUBLIC_SOLANA_TOKEN_SYMBOL=GOR
# UI Configuration # UI Configuration
NEXT_PUBLIC_EXAMPLE_URL=https://git.vdb.to/cerc-io/test-progressive-web-app NEXT_PUBLIC_EXAMPLE_URL=https://git.vdb.to/cerc-io/test-progressive-web-app
@ -17,7 +17,8 @@ NEXT_PUBLIC_REGISTRY_CHAIN_ID=laconic-mainnet
NEXT_PUBLIC_REGISTRY_RPC_ENDPOINT=https://laconicd-mainnet-1.laconic.com NEXT_PUBLIC_REGISTRY_RPC_ENDPOINT=https://laconicd-mainnet-1.laconic.com
NEXT_PUBLIC_REGISTRY_GQL_ENDPOINT=https://laconicd-mainnet-1.laconic.com/graphql NEXT_PUBLIC_REGISTRY_GQL_ENDPOINT=https://laconicd-mainnet-1.laconic.com/graphql
NEXT_PUBLIC_REGISTRY_GAS_PRICE=0.001 NEXT_PUBLIC_REGISTRY_GAS_PRICE=0.001
NEXT_PUBLIC_PRICING_RECORD_LRN= NEXT_PUBLIC_ALNT_COST_LRN=
NEXT_PUBLIC_DEPLOYMENT_COST_LRN=
REGISTRY_BOND_ID= REGISTRY_BOND_ID=
REGISTRY_AUTHORITY= REGISTRY_AUTHORITY=
REGISTRY_USER_KEY= REGISTRY_USER_KEY=

View File

@ -11,7 +11,7 @@ import { verifyUnusedSolanaPayment } from '@/utils/solana-verify';
import { transferLNTTokens } from '@/services/laconic-transfer'; import { transferLNTTokens } from '@/services/laconic-transfer';
import { getRegistry, getRegistryConfig } from '@/config'; import { getRegistry, getRegistryConfig } from '@/config';
import { getRequiredTokenInfo } from '@/services/jupiter-price'; import { getRequiredTokenInfo } from '@/services/jupiter-price';
import { resolvePricingRecordLrn } from '@/services/registry'; import { getCostOfDeployment } from '@/services/registry';
assert(process.env.NEXT_PUBLIC_SOLANA_RPC_URL, 'SOLANA_RPC_URL is required'); assert(process.env.NEXT_PUBLIC_SOLANA_RPC_URL, 'SOLANA_RPC_URL is required');
const SOLANA_RPC_URL = process.env.NEXT_PUBLIC_SOLANA_RPC_URL; const SOLANA_RPC_URL = process.env.NEXT_PUBLIC_SOLANA_RPC_URL;
@ -183,8 +183,7 @@ export async function POST(request: NextRequest) {
// Verify Solana payment // Verify Solana payment
console.log('Step 0: Verifying Solana token payment...'); console.log('Step 0: Verifying Solana token payment...');
const pricingRecordAttributes = await resolvePricingRecordLrn(); const targetUsdAmount = await getCostOfDeployment();
const targetUsdAmount = parseInt(pricingRecordAttributes.amount, 10);
const mintAddress = process.env.NEXT_PUBLIC_SOLANA_TOKEN_MINT_ADDRESS!; const mintAddress = process.env.NEXT_PUBLIC_SOLANA_TOKEN_MINT_ADDRESS!;
// Calculate expected token amount based on current price // Calculate expected token amount based on current price

View File

@ -9,16 +9,11 @@ import { Connection } from '@solana/web3.js';
import { sendSolanaTokenPayment } from '@/services/solana'; import { sendSolanaTokenPayment } from '@/services/solana';
import { getRequiredTokenInfo } from '@/services/jupiter-price'; import { getRequiredTokenInfo } from '@/services/jupiter-price';
import { PaymentModalProps } from '@/types'; import { PaymentModalProps } from '@/types';
import { resolvePricingRecordLrn } from '@/services/registry'; import { getCostOfDeployment } from '@/services/registry';
assert(process.env.NEXT_PUBLIC_SOLANA_RPC_URL, 'SOLANA_RPC_URL is required'); assert(process.env.NEXT_PUBLIC_SOLANA_RPC_URL, 'SOLANA_RPC_URL is required');
const SOLANA_RPC_URL = process.env.NEXT_PUBLIC_SOLANA_RPC_URL; const SOLANA_RPC_URL = process.env.NEXT_PUBLIC_SOLANA_RPC_URL;
interface DeploymentCostInfo {
amount: string;
currency: string;
}
export default function PaymentModal({ export default function PaymentModal({
isOpen, isOpen,
onClose, onClose,
@ -31,32 +26,20 @@ export default function PaymentModal({
const [tokenAmount, setTokenAmount] = useState<number>(0); const [tokenAmount, setTokenAmount] = useState<number>(0);
const [tokenDecimals, setTokenDecimals] = useState<number>(6); // Default fallback const [tokenDecimals, setTokenDecimals] = useState<number>(6); // Default fallback
const [loadingPrice, setLoadingPrice] = useState(true); const [loadingPrice, setLoadingPrice] = useState(true);
const [deploymentCostInfo, setDeploymentCostInfo] = useState<DeploymentCostInfo>(); const [deploymentCost, setDeploymentCost] = useState<number | null>(null);
const connection = useMemo(() => new Connection(SOLANA_RPC_URL), []); const connection = useMemo(() => new Connection(SOLANA_RPC_URL), []);
useEffect(() => { useEffect(() => {
const getDeploymentCostInfo = async () => { const getDeploymentCostInfo = async () => {
const pricingRecordAttributes = await resolvePricingRecordLrn(); const cost = await getCostOfDeployment();
setDeploymentCostInfo({ setDeploymentCost(cost);
amount: pricingRecordAttributes.amount,
currency:pricingRecordAttributes.currency
})
} }
getDeploymentCostInfo(); getDeploymentCostInfo();
}, []); }, []);
// Get configuration from environment variables
const deploymentCost = useMemo(() => {
if (!deploymentCostInfo) {
return;
}
return parseInt(deploymentCostInfo.amount, 10);
}, [deploymentCostInfo])
const mintAddress = process.env.NEXT_PUBLIC_SOLANA_TOKEN_MINT_ADDRESS!; const mintAddress = process.env.NEXT_PUBLIC_SOLANA_TOKEN_MINT_ADDRESS!;
const recipientAddress = process.env.NEXT_PUBLIC_SOLANA_TOKEN_RECIPIENT_ADDRESS; const recipientAddress = process.env.NEXT_PUBLIC_SOLANA_TOKEN_RECIPIENT_ADDRESS;

View File

@ -3,12 +3,13 @@ import assert from 'assert';
import { getRegistry } from '@/config'; import { getRegistry } from '@/config';
import { CreateRecordResponse, PricingRecordAttributes } from '../types'; import { CreateRecordResponse, PricingRecordAttributes } from '../types';
assert(process.env.NEXT_PUBLIC_PRICING_RECORD_LRN, 'DEPLOYMENT_RECORD_LRN is required'); assert(process.env.NEXT_PUBLIC_DEPLOYMENT_COST_LRN, 'DEPLOYMENT_RECORD_LRN is required');
const PRICING_RECORD_LRN = process.env.NEXT_PUBLIC_PRICING_RECORD_LRN; assert(process.env.NEXT_PUBLIC_ALNT_COST_LRN, 'DEPLOYMENT_RECORD_LRN is required');
const SUPPORTED_CURRENCY = "USD";
const VALID_PRICING_RECORD_FOR = "webapp-deployment";
const DEPLOYMENT_COST_LRN = process.env.NEXT_PUBLIC_DEPLOYMENT_COST_LRN;
const DEPLOYMENT = 'webapp-deployment';
const ALNT_COST_LRN = process.env.NEXT_PUBLIC_ALNT_COST_LRN;
const ALNT = 'alnt';
export const createApplicationDeploymentRequest = async ( export const createApplicationDeploymentRequest = async (
url: string, url: string,
@ -59,18 +60,36 @@ export const createApplicationDeploymentRequest = async (
} }
}; };
export const resolvePricingRecordLrn = async (): Promise<PricingRecordAttributes> => { const resolvePricingRecordLrns = async (lrns: string[]): Promise<PricingRecordAttributes[]> => {
const registry = getRegistry(); const registry = getRegistry();
const result = await registry.resolveNames([PRICING_RECORD_LRN]); const result = await registry.resolveNames(lrns);
const pricingRecordAttributes: PricingRecordAttributes = result[0].attributes; const pricingRecordsAttributes: PricingRecordAttributes[] = result.map((record: any) => {
return record.attributes
});
if (pricingRecordAttributes.for !== VALID_PRICING_RECORD_FOR) { return pricingRecordsAttributes;
throw new Error(`Incorrect pricing record type: ${pricingRecordAttributes.type}. Please provide correct pricing record lrn`) };
export const getCostOfDeployment = async (): Promise<number> => {
const resolvedRecords = await resolvePricingRecordLrns([ALNT_COST_LRN, DEPLOYMENT_COST_LRN]);
console.log('resolvedRecords:', resolvedRecords);
// Find the ALNT price record (USD per ALNT)
const alntPriceRecord = resolvedRecords.find(record => record.for === ALNT);
// Find the deployment cost record (ALNT cost for webapp-deployment)
const deploymentCostRecord = resolvedRecords.find(record => record.for === DEPLOYMENT);
if (!alntPriceRecord || !deploymentCostRecord) {
throw new Error('Required pricing records not found');
} }
if (pricingRecordAttributes.currency !== SUPPORTED_CURRENCY) { // Convert strings to numbers for calculation
throw new Error(`Unsupported currency found in pricing record: ${pricingRecordAttributes.currency}`) const alntPriceUsd = parseFloat(alntPriceRecord.amount); // USD per ALNT
} const deploymentCostAlnt = parseFloat(deploymentCostRecord.amount); // ALNT required
return pricingRecordAttributes; // Calculate deployment cost in USD: (ALNT required) * (USD per ALNT)
const deploymentCostUsd = deploymentCostAlnt * alntPriceUsd;
// Return with 6 decimal precision
return parseFloat(deploymentCostUsd.toFixed(6));
} }