Take deployment cost from published pricing record
This commit is contained in:
parent
cd409c38d8
commit
90eb55e9bc
11
.env.example
11
.env.example
@ -1,4 +1,4 @@
|
||||
# Client-side environment variables (must be prefixed with NEXT_PUBLIC_)
|
||||
# Client-side environment variables must be prefixed with NEXT_PUBLIC_
|
||||
|
||||
# Solana Token Payment Configuration
|
||||
# TODO: Use different RPC URL or use browser wallet
|
||||
@ -13,12 +13,11 @@ NEXT_PUBLIC_SOLANA_PAYMENT_AMOUNT_USD=5 # Payment amount in USD
|
||||
# UI Configuration
|
||||
NEXT_PUBLIC_EXAMPLE_URL=https://git.vdb.to/cerc-io/test-progressive-web-app
|
||||
|
||||
# Server-side environment variables
|
||||
|
||||
# Laconic Registry Configuration
|
||||
REGISTRY_CHAIN_ID=laconic-mainnet
|
||||
REGISTRY_RPC_ENDPOINT=https://laconicd-mainnet-1.laconic.com
|
||||
REGISTRY_GQL_ENDPOINT=https://laconicd-mainnet-1.laconic.com/graphql
|
||||
NEXT_PUBLIC_REGISTRY_CHAIN_ID=laconic-mainnet
|
||||
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_PRICING_RECORD_LRN=
|
||||
REGISTRY_GAS_PRICE=0.001
|
||||
REGISTRY_BOND_ID=
|
||||
REGISTRY_AUTHORITY=
|
||||
|
@ -82,9 +82,9 @@ NEXT_PUBLIC_EXAMPLE_URL=https://git.vdb.to/cerc-io/test-progressive-web-app
|
||||
|
||||
### Server-side Variables
|
||||
```bash
|
||||
REGISTRY_CHAIN_ID=laconic-mainnet
|
||||
REGISTRY_GQL_ENDPOINT=https://laconicd-mainnet-1.laconic.com/api
|
||||
REGISTRY_RPC_ENDPOINT=https://laconicd-mainnet-1.laconic.com
|
||||
NEXT_PUBLIC_REGISTRY_CHAIN_ID=laconic-mainnet
|
||||
NEXT_PUBLIC_REGISTRY_GQL_ENDPOINT=https://laconicd-mainnet-1.laconic.com/api
|
||||
NEXT_PUBLIC_REGISTRY_RPC_ENDPOINT=https://laconicd-mainnet-1.laconic.com
|
||||
REGISTRY_BOND_ID=<BOND_ID>
|
||||
REGISTRY_AUTHORITY=<AUTHORITY_NAME>
|
||||
REGISTRY_USER_KEY=<PRIVATE_KEY>
|
||||
|
@ -231,9 +231,9 @@ export async function POST(request: NextRequest) {
|
||||
|
||||
// Validate required environment variables for Solana payments
|
||||
const requiredEnvVars = [
|
||||
'REGISTRY_CHAIN_ID',
|
||||
'REGISTRY_GQL_ENDPOINT',
|
||||
'REGISTRY_RPC_ENDPOINT',
|
||||
'NEXT_PUBLIC_REGISTRY_CHAIN_ID',
|
||||
'NEXT_PUBLIC_REGISTRY_GQL_ENDPOINT',
|
||||
'NEXT_PUBLIC_REGISTRY_RPC_ENDPOINT',
|
||||
'REGISTRY_BOND_ID',
|
||||
'REGISTRY_AUTHORITY',
|
||||
'REGISTRY_USER_KEY', // This is the same as the prefilled account for LNT transfers
|
||||
|
@ -9,9 +9,28 @@ import { Connection } from '@solana/web3.js';
|
||||
import { sendSolanaTokenPayment } from '@/services/solana';
|
||||
import { getRequiredTokenInfo } from '@/services/jupiter-price';
|
||||
import { PaymentModalProps } from '@/types';
|
||||
import { getRegistry } from '@/config';
|
||||
|
||||
assert(process.env.NEXT_PUBLIC_SOLANA_RPC_URL, 'SOLANA_RPC_URL is required');
|
||||
assert(process.env.NEXT_PUBLIC_PRICING_RECORD_LRN, 'DEPLOYMENT_RECORD_LRN is required');
|
||||
|
||||
const SOLANA_RPC_URL = process.env.NEXT_PUBLIC_SOLANA_RPC_URL;
|
||||
const PRICING_RECORD_LRN = process.env.NEXT_PUBLIC_PRICING_RECORD_LRN;
|
||||
const SUPPORTED_CURRENCY = "USD";
|
||||
const VALID_PRICING_RECORD_TYPE = "webapp-deployment";
|
||||
|
||||
interface DeploymentCostInfo {
|
||||
amount: string;
|
||||
currency: string;
|
||||
}
|
||||
|
||||
interface PricingRecordAttributes {
|
||||
amount: string;
|
||||
currency: string;
|
||||
for: string;
|
||||
type: string;
|
||||
version: string;
|
||||
}
|
||||
|
||||
export default function PaymentModal({
|
||||
isOpen,
|
||||
@ -25,24 +44,56 @@ export default function PaymentModal({
|
||||
const [tokenAmount, setTokenAmount] = useState<number>(0);
|
||||
const [tokenDecimals, setTokenDecimals] = useState<number>(6); // Default fallback
|
||||
const [loadingPrice, setLoadingPrice] = useState(true);
|
||||
const [deploymentCostInfo, setDeploymentCostInfo] = useState<DeploymentCostInfo>();
|
||||
|
||||
const connection = useMemo(() => new Connection(SOLANA_RPC_URL), [])
|
||||
const connection = useMemo(() => new Connection(SOLANA_RPC_URL), []);
|
||||
|
||||
useEffect(() => {
|
||||
const registry = getRegistry();
|
||||
|
||||
const resolveDeploymentCostInfo = async () => {
|
||||
const result = await registry.resolveNames([PRICING_RECORD_LRN!])
|
||||
const PricingRecordAttributes: PricingRecordAttributes = result[0].attributes;
|
||||
|
||||
if (PricingRecordAttributes.type !== VALID_PRICING_RECORD_TYPE) {
|
||||
throw new Error(`Incorrect pricing record type: ${PricingRecordAttributes.type}. Please provide correct pricing record lrn`)
|
||||
}
|
||||
|
||||
if (PricingRecordAttributes.currency !== SUPPORTED_CURRENCY) {
|
||||
throw new Error(`Unsupported currency found in pricing record: ${PricingRecordAttributes.currency}`)
|
||||
}
|
||||
|
||||
setDeploymentCostInfo({
|
||||
amount: PricingRecordAttributes.amount,
|
||||
currency:PricingRecordAttributes.currency
|
||||
})
|
||||
}
|
||||
|
||||
resolveDeploymentCostInfo();
|
||||
}, []);
|
||||
|
||||
// Get configuration from environment variables
|
||||
const targetUsdAmount = parseFloat(process.env.NEXT_PUBLIC_SOLANA_PAYMENT_AMOUNT_USD!);
|
||||
const deploymentCost = useMemo(() => {
|
||||
if (!deploymentCostInfo) {
|
||||
return;
|
||||
}
|
||||
|
||||
return parseInt(deploymentCostInfo.amount, 10);
|
||||
}, [deploymentCostInfo])
|
||||
|
||||
const mintAddress = process.env.NEXT_PUBLIC_SOLANA_TOKEN_MINT_ADDRESS!;
|
||||
const recipientAddress = process.env.NEXT_PUBLIC_SOLANA_TOKEN_RECIPIENT_ADDRESS;
|
||||
|
||||
// Fetch token amount based on USD price
|
||||
useEffect(() => {
|
||||
if (!isOpen) return;
|
||||
if (!isOpen || !deploymentCost) return;
|
||||
|
||||
const fetchTokenAmount = async () => {
|
||||
setLoadingPrice(true);
|
||||
setError('');
|
||||
|
||||
try {
|
||||
const {requiredAmountInBaseUnits, decimals} = await getRequiredTokenInfo(targetUsdAmount, mintAddress)
|
||||
const {requiredAmountInBaseUnits, decimals} = await getRequiredTokenInfo(deploymentCost, mintAddress);
|
||||
setTokenAmount(requiredAmountInBaseUnits);
|
||||
setTokenDecimals(decimals);
|
||||
} catch (error) {
|
||||
@ -54,7 +105,7 @@ export default function PaymentModal({
|
||||
};
|
||||
|
||||
fetchTokenAmount();
|
||||
}, [isOpen, targetUsdAmount, mintAddress]);
|
||||
}, [isOpen, deploymentCost, mintAddress]);
|
||||
|
||||
const handlePayment = useCallback(async () => {
|
||||
if (tokenAmount === 0 || loadingPrice) {
|
||||
@ -117,7 +168,7 @@ export default function PaymentModal({
|
||||
<div className="relative">
|
||||
<input
|
||||
type="text"
|
||||
value={`$${targetUsdAmount}`}
|
||||
value={`$${deploymentCost}`}
|
||||
disabled={true}
|
||||
className="w-full p-3 pr-12 rounded-md"
|
||||
style={{
|
||||
|
@ -22,9 +22,9 @@ export const getRegistry = (): Registry => {
|
||||
export const getRegistryConfig = (): RegistryConfig => {
|
||||
// Validate required environment variables
|
||||
const requiredEnvVars = [
|
||||
'REGISTRY_CHAIN_ID',
|
||||
'REGISTRY_GQL_ENDPOINT',
|
||||
'REGISTRY_RPC_ENDPOINT',
|
||||
'NEXT_PUBLIC_REGISTRY_CHAIN_ID',
|
||||
'NEXT_PUBLIC_REGISTRY_GQL_ENDPOINT',
|
||||
'NEXT_PUBLIC_REGISTRY_RPC_ENDPOINT',
|
||||
'REGISTRY_BOND_ID',
|
||||
'REGISTRY_AUTHORITY',
|
||||
'REGISTRY_USER_KEY'
|
||||
@ -37,9 +37,9 @@ export const getRegistryConfig = (): RegistryConfig => {
|
||||
}
|
||||
|
||||
return {
|
||||
chainId: process.env.REGISTRY_CHAIN_ID!,
|
||||
rpcEndpoint: process.env.REGISTRY_RPC_ENDPOINT!,
|
||||
gqlEndpoint: process.env.REGISTRY_GQL_ENDPOINT!,
|
||||
chainId: process.env.NEXT_PUBLIC_REGISTRY_CHAIN_ID!,
|
||||
rpcEndpoint: process.env.NEXT_PUBLIC_REGISTRY_RPC_ENDPOINT!,
|
||||
gqlEndpoint: process.env.NEXT_PUBLIC_REGISTRY_GQL_ENDPOINT!,
|
||||
bondId: process.env.REGISTRY_BOND_ID!,
|
||||
authority: process.env.REGISTRY_AUTHORITY!,
|
||||
privateKey: process.env.REGISTRY_USER_KEY!,
|
||||
|
Loading…
Reference in New Issue
Block a user