forked from mito-systems/sol-mem-gen
Use big.js for handling decimals
This commit is contained in:
parent
cc64e6a035
commit
2e735c51dd
14
package-lock.json
generated
14
package-lock.json
generated
@ -12,6 +12,7 @@
|
||||
"@google/generative-ai": "^0.21.0",
|
||||
"@solana/spl-token": "^0.3.8",
|
||||
"@solana/web3.js": "^1.78.4",
|
||||
"big.js": "^6.2.2",
|
||||
"bn.js": "^5.2.0",
|
||||
"dotenv": "^16.4.7",
|
||||
"next": "13.5.4",
|
||||
@ -1501,6 +1502,19 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"node_modules/big.js": {
|
||||
"version": "6.2.2",
|
||||
"resolved": "https://registry.npmjs.org/big.js/-/big.js-6.2.2.tgz",
|
||||
"integrity": "sha512-y/ie+Faknx7sZA5MfGA2xKlu0GDv8RWrXGsmlteyJQ2lvoKv9GBK/fpRMc2qlSoBAgNxrixICFCBefIq8WCQpQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": "*"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/bigjs"
|
||||
}
|
||||
},
|
||||
"node_modules/bigint-buffer": {
|
||||
"version": "1.1.5",
|
||||
"resolved": "https://registry.npmjs.org/bigint-buffer/-/bigint-buffer-1.1.5.tgz",
|
||||
|
@ -13,6 +13,7 @@
|
||||
"@google/generative-ai": "^0.21.0",
|
||||
"@solana/spl-token": "^0.3.8",
|
||||
"@solana/web3.js": "^1.78.4",
|
||||
"big.js": "^6.2.2",
|
||||
"bn.js": "^5.2.0",
|
||||
"dotenv": "^16.4.7",
|
||||
"next": "13.5.4",
|
||||
|
@ -1,6 +1,7 @@
|
||||
import assert from "assert";
|
||||
import BN from "bn.js";
|
||||
import fetch from 'node-fetch';
|
||||
import Big from 'big.js';
|
||||
|
||||
assert(process.env.NEXT_PUBLIC_USDC_MINT, 'USDC_MINT is required');
|
||||
assert(process.env.NEXT_PUBLIC_MTM_TOKEN_MINT, 'MTM_TOKEN_MINT is required');
|
||||
@ -21,14 +22,15 @@ class QuotesService {
|
||||
}
|
||||
|
||||
const quoteResponse = await response.json();
|
||||
const priceFromAPI = Number(quoteResponse['data'][USDC_MINT]['price']).toFixed(6);
|
||||
const price = new BN(priceFromAPI.toString().replace('.', ''));
|
||||
|
||||
// Handle price with Big.js, then convert to BN
|
||||
const priceFromAPI = new Big(quoteResponse['data'][USDC_MINT]['price']).toFixed(6);
|
||||
const price = new BN(new Big(priceFromAPI).times(new Big(10).pow(6)).toString());
|
||||
|
||||
this.cachedQuotes.push(price);
|
||||
if (this.cachedQuotes.length > 3) {
|
||||
this.cachedQuotes.shift();
|
||||
}
|
||||
console.log('Cache updated: ', this.cachedQuotes);
|
||||
} catch (error) {
|
||||
console.error('Error fetching quotes:', error);
|
||||
}
|
||||
|
@ -1,6 +1,8 @@
|
||||
import { createServer } from 'http';
|
||||
import { parse } from 'url';
|
||||
import next from 'next';
|
||||
|
||||
// Reference: https://www.dotenv.org/docs/quickstart#initial-setup
|
||||
import dotenv from 'dotenv';
|
||||
dotenv.config();
|
||||
|
||||
@ -16,9 +18,9 @@ declare global {
|
||||
namespace NodeJS {
|
||||
interface Global {
|
||||
quotesService: typeof quotesService
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Look for a better way to use quotesService
|
||||
// Initialize global quotes service
|
||||
|
@ -48,13 +48,13 @@ export async function POST(req: NextRequest): Promise<NextResponse> {
|
||||
}
|
||||
|
||||
const quotes: BN[] = (global as any).quotesService.getQuotes();
|
||||
const priceMTMFor1USDC = quotes.reduce((min, quote) => quote.lt(min) ? quote : min, quotes[0]); // Take the minimum quote from the array
|
||||
const lowestQuote = quotes.reduce((minQuote, currentQuote) => BN.min(minQuote, currentQuote), quotes[0]);
|
||||
|
||||
const scale = new BN(100);
|
||||
const scaledCost = new BN(model.cost * 100);
|
||||
|
||||
const lowestQuote = scaledCost.mul(new BN(priceMTMFor1USDC)).div(scale);
|
||||
const isPaymentVerified = await verifyPayment(transactionSignature, lowestQuote);
|
||||
const tokenAmount = scaledCost.mul(new BN(lowestQuote)).div(scale);
|
||||
const isPaymentVerified = await verifyPayment(transactionSignature, tokenAmount);
|
||||
|
||||
if (!isPaymentVerified) {
|
||||
return NextResponse.json(
|
||||
|
@ -132,7 +132,6 @@ const Page: React.FC = (): React.ReactElement => {
|
||||
isWalletConnected={walletState.connected}
|
||||
onGenerate={handleFluxGeneration(
|
||||
model.modelId,
|
||||
// Calculate scaled cost directly in bn.js
|
||||
priceMTM
|
||||
)}
|
||||
priceMTM={priceMTM}
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
import React, { useState } from 'react'
|
||||
import BN from 'bn.js';
|
||||
import Big from 'big.js';
|
||||
|
||||
interface AIServiceCardProps {
|
||||
title: string
|
||||
@ -19,12 +20,12 @@ interface GenerationState {
|
||||
}
|
||||
|
||||
const formatBNWithDecimals = (value: BN, decimals: number): string => {
|
||||
const factor = new BN(10).pow(new BN(decimals));
|
||||
// Part before decimal point
|
||||
const quotient = value.div(factor);
|
||||
// Part after decimal point
|
||||
const remainder = value.mod(factor);
|
||||
return `${quotient.toString()}.${remainder.toString().padStart(decimals, '0')}`;
|
||||
if (value.isZero()) return '0.' + '0'.repeat(decimals); // Handle zero case
|
||||
|
||||
const bigValue = new Big(value.toString());
|
||||
const factor = new Big(10).pow(decimals);
|
||||
|
||||
return bigValue.div(factor).toFixed(decimals);
|
||||
}
|
||||
|
||||
const AIServiceCard: React.FC<AIServiceCardProps> = ({
|
||||
@ -64,6 +65,8 @@ const AIServiceCard: React.FC<AIServiceCardProps> = ({
|
||||
setTimeout(() => {
|
||||
window.location.reload();
|
||||
}, 3000);
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if (result.imageUrl) {
|
||||
@ -124,7 +127,7 @@ const AIServiceCard: React.FC<AIServiceCardProps> = ({
|
||||
|
||||
{generationState.error && (
|
||||
<div className="mt-4 bg-red-900/20 border border-red-500/20 text-red-400 px-4 py-3 rounded-xl text-center">
|
||||
{generationState.error}, reloading...
|
||||
{generationState.error}
|
||||
</div>
|
||||
)}
|
||||
|
||||
|
@ -51,7 +51,7 @@ export async function generateWithFlux(
|
||||
})
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error('Failed to generate image')
|
||||
throw new Error('Failed to generate image, reloading...')
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
|
@ -47,7 +47,7 @@ export async function markSignatureAsUsed(transactionSignature: string): Promise
|
||||
|
||||
export async function verifyPayment(
|
||||
transactionSignature: string,
|
||||
lowestQuote: BN,
|
||||
tokenAmount: BN,
|
||||
): Promise<boolean> {
|
||||
try {
|
||||
// Check if the signature is already used
|
||||
@ -74,8 +74,7 @@ export async function verifyPayment(
|
||||
|
||||
const transactionAmount = new BN(amount);
|
||||
|
||||
if (transactionAmount.gte(lowestQuote)) {
|
||||
console.log('Transaction amount is greater than minimum amount');
|
||||
if (transactionAmount.gte(tokenAmount)) {
|
||||
return true;
|
||||
}
|
||||
console.log('Transaction amount is less than minimum amount. Rejecting request');
|
||||
|
Loading…
Reference in New Issue
Block a user