wgm-swap-components
Version:
A React component library for token swap interfaces
325 lines (324 loc) • 15.9 kB
JavaScript
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (g && (g = 0, op[0] && (_ = 0)), _) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
import { useState, useEffect } from 'react';
import { useAccount, useWriteContract, useSwitchChain, useBalance } from 'wagmi';
import { readContracts } from 'wagmi/actions';
import { formatUnits, parseUnits, erc20Abi } from 'viem';
import ROUTER_ABI from '../abis/abi.json';
import abi1514 from '../abis/0x1514000000000000000000000000000000000000.json';
import { ROUTER_ADDRESS, CHAIN_ID, IP_ADDRESS, WIP_ADDRESS, DEFAULT_DECIMALS } from '../constants';
var PoolType;
(function (PoolType) {
PoolType[PoolType["V2Pool"] = 0] = "V2Pool";
PoolType[PoolType["V3Pool"] = 1] = "V3Pool";
})(PoolType || (PoolType = {}));
var mapPoolType = function (type) {
if (type.includes('v2')) {
return PoolType.V2Pool;
}
return PoolType.V3Pool;
};
export function useWagmiIntegration(_a) {
var _this = this;
var _b = _a === void 0 ? {} : _a, token = _b.token, config = _b.config;
var _c = useAccount({ config: config }), address = _c.address, isConnected = _c.isConnected, chain = _c.chain;
var writeContractAsync = useWriteContract({ config: config }).writeContractAsync;
var switchChain = useSwitchChain({ config: config }).switchChain;
var _d = useState('0'), balance = _d[0], setBalance = _d[1];
var _e = useState(false), isLoading = _e[0], setIsLoading = _e[1];
// Get current chain ID from useAccount hook
var currentChainId = (chain === null || chain === void 0 ? void 0 : chain.id) || CHAIN_ID;
var isWrongNetwork = currentChainId !== CHAIN_ID;
// Use wagmi's useBalance hook directly like in exam
var _f = useBalance({
address: address || undefined,
token: (token === null || token === void 0 ? void 0 : token.address) === IP_ADDRESS ? undefined : token === null || token === void 0 ? void 0 : token.address,
config: config,
query: {
enabled: !!token && !!address && isConnected,
refetchInterval: 10000, // Refetch every 10 seconds
}
}), balanceData = _f.data, refetchBalance = _f.refetch;
// Update balance when data changes - following exam pattern
useEffect(function () {
if (!address) {
setBalance('0');
return;
}
if (balanceData) {
var formattedBalance = formatUnits(balanceData.value, Number(balanceData.decimals || DEFAULT_DECIMALS));
var balanceAsNumber = parseFloat(formattedBalance);
setBalance(balanceAsNumber.toFixed(6));
}
else {
setBalance('0.000000'); // Fallback to 0 with 6 decimals
}
}, [address, balanceData, token]);
// Switch to correct network
var switchToCorrectNetwork = function () { return __awaiter(_this, void 0, void 0, function () {
var error_1;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
_a.trys.push([0, 2, , 3]);
return [4 /*yield*/, switchChain({ chainId: CHAIN_ID })];
case 1:
_a.sent();
return [3 /*break*/, 3];
case 2:
error_1 = _a.sent();
console.error('Failed to switch network:', error_1);
return [3 /*break*/, 3];
case 3: return [2 /*return*/];
}
});
}); };
// Check token allowance
var checkAllowance = function (spenderAddress) { return __awaiter(_this, void 0, void 0, function () {
var allowanceData, error_2;
var _a;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
if (!token || !address)
return [2 /*return*/, '0'];
_b.label = 1;
case 1:
_b.trys.push([1, 3, , 4]);
// If no config provided, return '0' - app should handle this gracefully
if (!config) {
console.warn('No wagmi config provided to useWagmiIntegration');
return [2 /*return*/, '0'];
}
return [4 /*yield*/, readContracts(config, {
contracts: [
{
address: token.address,
abi: erc20Abi,
functionName: 'allowance',
args: [address, spenderAddress],
}
]
})];
case 2:
allowanceData = _b.sent();
if ((_a = allowanceData === null || allowanceData === void 0 ? void 0 : allowanceData[0]) === null || _a === void 0 ? void 0 : _a.result) {
return [2 /*return*/, formatUnits(allowanceData[0].result, token.decimals || DEFAULT_DECIMALS)];
}
return [2 /*return*/, '0'];
case 3:
error_2 = _b.sent();
console.error('Failed to check allowance:', error_2);
return [2 /*return*/, '0'];
case 4: return [2 /*return*/];
}
});
}); };
// Approve token spending
var approveToken = function (spenderAddress, amount) { return __awaiter(_this, void 0, void 0, function () {
var amountBigInt, hash, error_3;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
if (!token || !address)
return [2 /*return*/, false];
_a.label = 1;
case 1:
_a.trys.push([1, 3, 4, 5]);
setIsLoading(true);
amountBigInt = parseUnits(amount, token.decimals || DEFAULT_DECIMALS);
return [4 /*yield*/, writeContractAsync({
address: token.address,
abi: erc20Abi,
functionName: 'approve',
args: [spenderAddress, amountBigInt],
})];
case 2:
hash = _a.sent();
console.log('Approval transaction hash:', hash);
return [2 /*return*/, true];
case 3:
error_3 = _a.sent();
console.error('Failed to approve token:', error_3);
return [2 /*return*/, false];
case 4:
setIsLoading(false);
return [7 /*endfinally*/];
case 5: return [2 /*return*/];
}
});
}); };
// Execute token swap with quote data
var executeSwap = function (fromToken, toToken, amount, quoteData) { return __awaiter(_this, void 0, void 0, function () {
var deadline_1, slippage_1, allExecutionParams, hash, error_4;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
if (!address || !(quoteData === null || quoteData === void 0 ? void 0 : quoteData.route) || quoteData.route.length === 0)
return [2 /*return*/, null];
_a.label = 1;
case 1:
_a.trys.push([1, 3, 4, 5]);
setIsLoading(true);
deadline_1 = Math.floor(Date.now() / 1000) + 20 * 60;
slippage_1 = 0.5;
allExecutionParams = quoteData.route.map(function (path) {
var _a, _b, _c;
var swapRoutes = path.map(function (step) { return ({
routerAddress: step.routerAddress,
poolType: mapPoolType(step.type),
tokenIn: step.tokenIn.address,
tokenOut: step.tokenOut.address,
fee: step.fee || BigInt(0),
}); });
var amountInWithDecimals = BigInt(((_b = (_a = path[0]) === null || _a === void 0 ? void 0 : _a.amountIn) === null || _b === void 0 ? void 0 : _b.toString()) || '0');
var amountOutWithDecimals = BigInt(((_c = path[path.length - 1]) === null || _c === void 0 ? void 0 : _c.amountOut) || '0');
var amountOutMinimum = (amountOutWithDecimals * BigInt(10000 - slippage_1 * 100)) / BigInt(10000);
var totalPercent = path.reduce(function (acc, step) {
return acc - (typeof step.feeOnTransferToken === 'number' && step.feeOnTransferToken > 0 ? step.feeOnTransferToken : 0);
}, 100);
var finalAmountOutMinimum = (amountOutMinimum * BigInt(totalPercent)) / BigInt(100);
return {
swapRoutes: swapRoutes,
recipient: address,
deadline: deadline_1,
amountIn: amountInWithDecimals,
amountOutMinimum: finalAmountOutMinimum,
};
});
return [4 /*yield*/, writeContractAsync({
address: ROUTER_ADDRESS,
abi: ROUTER_ABI,
functionName: 'swapMultiroutes',
args: [allExecutionParams],
value: fromToken.address === IP_ADDRESS ? parseUnits(amount, fromToken.decimals || 18) : BigInt(0),
})];
case 2:
hash = _a.sent();
return [2 /*return*/, hash];
case 3:
error_4 = _a.sent();
console.error('Failed to execute swap:', error_4);
return [2 /*return*/, null];
case 4:
setIsLoading(false);
return [7 /*endfinally*/];
case 5: return [2 /*return*/];
}
});
}); };
// Wrap IP to WIP
var wrapIP = function (amount) { return __awaiter(_this, void 0, void 0, function () {
var amountBigInt, hash, error_5;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
if (!address)
return [2 /*return*/, null];
_a.label = 1;
case 1:
_a.trys.push([1, 3, 4, 5]);
setIsLoading(true);
amountBigInt = parseUnits(amount, 18);
return [4 /*yield*/, writeContractAsync({
address: WIP_ADDRESS,
abi: abi1514,
functionName: 'deposit',
value: amountBigInt,
})];
case 2:
hash = _a.sent();
return [2 /*return*/, hash];
case 3:
error_5 = _a.sent();
console.error('Failed to wrap IP:', error_5);
return [2 /*return*/, null];
case 4:
setIsLoading(false);
return [7 /*endfinally*/];
case 5: return [2 /*return*/];
}
});
}); };
// Unwrap WIP to IP
var unwrapWIP = function (amount) { return __awaiter(_this, void 0, void 0, function () {
var amountBigInt, hash, error_6;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
if (!address)
return [2 /*return*/, null];
_a.label = 1;
case 1:
_a.trys.push([1, 3, 4, 5]);
setIsLoading(true);
amountBigInt = parseUnits(amount, 18);
return [4 /*yield*/, writeContractAsync({
address: WIP_ADDRESS,
abi: abi1514,
functionName: 'withdraw',
args: [amountBigInt],
})];
case 2:
hash = _a.sent();
return [2 /*return*/, hash];
case 3:
error_6 = _a.sent();
console.error('Failed to unwrap WIP:', error_6);
return [2 /*return*/, null];
case 4:
setIsLoading(false);
return [7 /*endfinally*/];
case 5: return [2 /*return*/];
}
});
}); };
return {
balance: balance,
isLoading: isLoading,
isConnected: isConnected,
address: address,
chainId: currentChainId,
isWrongNetwork: isWrongNetwork,
switchToCorrectNetwork: switchToCorrectNetwork,
checkAllowance: checkAllowance,
approveToken: approveToken,
executeSwap: executeSwap,
wrapIP: wrapIP,
unwrapWIP: unwrapWIP,
};
}