@gotake/gotake-sdk
Version:
SDK for interacting with GoTake blockchain contracts
336 lines (335 loc) • 12.3 kB
JavaScript
;
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.PaymentUtils = void 0;
var ethers_1 = require("ethers");
var types_1 = require("../types");
/**
* Utility functions for payment processing
*/
var PaymentUtils = /** @class */ (function () {
function PaymentUtils() {
}
/**
* Validate payment parameters
* @param params Purchase parameters
* @returns Validation result with errors if any
*/
PaymentUtils.validatePurchaseParams = function (params) {
var errors = [];
// Validate content ID
if (!Number.isInteger(params.contentId) || params.contentId <= 0) {
errors.push('Content ID must be a positive integer');
}
// Validate payment method
if (!Object.values(types_1.PaymentMethod).includes(params.paymentMethod)) {
errors.push('Invalid payment method');
}
// Validate token address for ERC20 payments
if (params.paymentMethod === types_1.PaymentMethod.ERC20) {
if (!params.tokenAddress) {
errors.push('Token address is required for ERC20 payments');
}
else if (!this.isValidAddress(params.tokenAddress)) {
errors.push('Invalid token address format');
}
}
// Validate amount if provided
if (params.amount !== undefined) {
try {
var amount = ethers_1.BigNumber.from(params.amount);
if (amount.lte(0)) {
errors.push('Amount must be positive');
}
}
catch (_a) {
errors.push('Invalid amount format');
}
}
return {
isValid: errors.length === 0,
errors: errors
};
};
/**
* Check if address is valid Ethereum address
* @param address Address to check
* @returns True if address is valid
*/
PaymentUtils.isValidAddress = function (address) {
var ethers = require('ethers');
try {
return ethers.utils.isAddress(address);
}
catch (_a) {
return false;
}
};
/**
* Format payment method for display
* @param method Payment method
* @returns Formatted string
*/
PaymentUtils.formatPaymentMethod = function (method) {
switch (method) {
case types_1.PaymentMethod.ETH:
return 'Ethereum (ETH)';
case types_1.PaymentMethod.ERC20:
return 'ERC20 Token';
default:
return 'Unknown';
}
};
/**
* Get payment method icon/symbol
* @param method Payment method
* @returns Symbol string
*/
PaymentUtils.getPaymentMethodSymbol = function (method) {
switch (method) {
case types_1.PaymentMethod.ETH:
return 'ETH';
case types_1.PaymentMethod.ERC20:
return 'ERC20';
default:
return '?';
}
};
/**
* Calculate total cost including gas estimate
* @param price Content price
* @param gasEstimate Estimated gas cost
* @param paymentMethod Payment method
* @returns Total cost breakdown
*/
PaymentUtils.calculateTotalCost = function (price, gasEstimate, paymentMethod) {
var isETHPayment = paymentMethod === types_1.PaymentMethod.ETH;
return {
contentPrice: price,
gasCost: gasEstimate,
total: isETHPayment ? price.add(gasEstimate) : gasEstimate,
isETHPayment: isETHPayment
};
};
/**
* Format purchase result for display
* @param result Purchase result
* @returns Formatted result object
*/
PaymentUtils.formatPurchaseResult = function (result) {
return {
transactionHash: result.transactionHash,
shortHash: this.shortenHash(result.transactionHash),
contentId: result.contentId,
purchaseTime: this.formatTimestamp(result.purchaseTime),
viewCount: result.viewCount.toNumber(),
validUntil: this.formatTimestamp(result.validUntil),
gasUsed: result.gasUsed ? result.gasUsed.toString() : undefined
};
};
/**
* Shorten transaction hash for display
* @param hash Full transaction hash
* @returns Shortened hash
*/
PaymentUtils.shortenHash = function (hash) {
if (hash.length <= 10)
return hash;
return "".concat(hash.slice(0, 6), "...").concat(hash.slice(-4));
};
/**
* Format timestamp for display
* @param timestamp BigNumber timestamp
* @returns Formatted date string
*/
PaymentUtils.formatTimestamp = function (timestamp) {
var date = new Date(timestamp.toNumber() * 1000);
return date.toLocaleString();
};
/**
* Calculate percentage savings
* @param originalPrice Original price
* @param discountedPrice Discounted price
* @returns Savings percentage
*/
PaymentUtils.calculateSavings = function (originalPrice, discountedPrice) {
if (originalPrice.lte(0))
return 0;
var savings = originalPrice.sub(discountedPrice);
var percentage = savings.mul(10000).div(originalPrice).toNumber() / 100;
return Math.max(0, Math.min(100, percentage));
};
/**
* Compare payment costs across different methods
* @param costs Array of cost objects with method and price
* @returns Sorted costs with savings information
*/
PaymentUtils.comparePaymentCosts = function (costs) {
var _this = this;
// Calculate totals
var costsWithTotals = costs.map(function (cost) {
var gasEstimate = cost.gasEstimate || ethers_1.BigNumber.from(0);
var totalCost = _this.calculateTotalCost(cost.price, gasEstimate, cost.method);
return {
method: cost.method,
price: cost.price,
total: totalCost.total,
tokenSymbol: cost.tokenSymbol
};
});
// Sort by total cost
costsWithTotals.sort(function (a, b) {
if (a.total.lt(b.total))
return -1;
if (a.total.gt(b.total))
return 1;
return 0;
});
// Calculate savings and mark recommended
var cheapest = costsWithTotals[0];
return costsWithTotals.map(function (cost, index) { return (__assign(__assign({}, cost), { savings: cheapest.total.eq(cost.total) ? 0 :
_this.calculateSavings(cost.total, cheapest.total), isRecommended: index === 0 })); });
};
/**
* Generate payment summary text
* @param params Purchase parameters
* @param price Content price
* @returns Summary text
*/
PaymentUtils.generatePaymentSummary = function (params, price) {
var ethers = require('ethers');
var method = this.formatPaymentMethod(params.paymentMethod);
var priceStr = ethers.utils.formatEther(price);
var summary = "Purchase content ".concat(params.contentId, " for ").concat(priceStr, " ETH");
if (params.paymentMethod === types_1.PaymentMethod.ERC20 && params.tokenAddress) {
summary += " (paid with ".concat(params.tokenAddress, ")");
}
summary += " using ".concat(method);
return summary;
};
/**
* Estimate gas for purchase transaction
* @param paymentMethod Payment method
* @param hasApproval Whether token approval is needed (for ERC20)
* @returns Estimated gas units
*/
PaymentUtils.estimateGasUnits = function (paymentMethod, hasApproval) {
if (hasApproval === void 0) { hasApproval = true; }
switch (paymentMethod) {
case types_1.PaymentMethod.ETH:
return 65000; // Typical gas for ETH purchase
case types_1.PaymentMethod.ERC20:
// Add approval gas if needed
var approvalGas = hasApproval ? 0 : 46000;
var transferGas = 85000; // Typical gas for ERC20 purchase
return approvalGas + transferGas;
default:
return 100000; // Conservative estimate
}
};
/**
* Check if sufficient balance for purchase
* @param balance User's balance
* @param requiredAmount Required amount
* @param gasEstimate Gas cost estimate
* @param paymentMethod Payment method
* @returns Balance check result
*/
PaymentUtils.checkSufficientBalance = function (balance, requiredAmount, gasEstimate, paymentMethod) {
var totalRequired = paymentMethod === types_1.PaymentMethod.ETH ?
requiredAmount.add(gasEstimate) :
requiredAmount;
if (balance.gte(totalRequired)) {
return {
sufficient: true,
message: 'Sufficient balance'
};
}
var shortage = totalRequired.sub(balance);
var ethers = require('ethers');
var shortageStr = ethers.utils.formatEther(shortage);
return {
sufficient: false,
shortage: shortage,
message: "Insufficient balance. Need ".concat(shortageStr, " more ").concat(paymentMethod)
};
};
/**
* Generate transaction receipt URL for block explorer
* @param transactionHash Transaction hash
* @param networkId Network ID
* @returns Block explorer URL
*/
PaymentUtils.generateExplorerUrl = function (transactionHash, networkId) {
var baseUrls = {
1: 'https://etherscan.io/tx/',
5: 'https://goerli.etherscan.io/tx/',
11155111: 'https://sepolia.etherscan.io/tx/',
8453: 'https://basescan.org/tx/',
84531: 'https://goerli.basescan.org/tx/',
84532: 'https://sepolia.basescan.org/tx/'
};
var baseUrl = baseUrls[networkId];
return baseUrl ? "".concat(baseUrl).concat(transactionHash) : '#';
};
/**
* Parse error messages from failed transactions
* @param error Error object
* @returns User-friendly error message
*/
PaymentUtils.parseTransactionError = function (error) {
if (!error)
return 'Unknown error occurred';
var errorMessage = error.message || error.toString();
// Common error patterns
var patterns = [
{
pattern: /insufficient funds/i,
message: 'Insufficient funds to complete transaction'
},
{
pattern: /user rejected/i,
message: 'Transaction was rejected by user'
},
{
pattern: /gas too low/i,
message: 'Gas limit too low for transaction'
},
{
pattern: /nonce too low/i,
message: 'Transaction nonce error. Please try again'
},
{
pattern: /content not active/i,
message: 'Content is not available for purchase'
},
{
pattern: /already purchased/i,
message: 'Content has already been purchased'
},
{
pattern: /token not supported/i,
message: 'Payment token is not supported'
}
];
for (var _i = 0, patterns_1 = patterns; _i < patterns_1.length; _i++) {
var _a = patterns_1[_i], pattern = _a.pattern, message = _a.message;
if (pattern.test(errorMessage)) {
return message;
}
}
return 'Transaction failed. Please try again';
};
return PaymentUtils;
}());
exports.PaymentUtils = PaymentUtils;