feat(vault): add user vault factory, non-custodial deposit/withdraw and session key UI
This commit is contained in:
@@ -9,9 +9,14 @@ interface Web3ContextType {
|
||||
chainId: number | null;
|
||||
isCorrectNetwork: boolean;
|
||||
wusdBalance: string;
|
||||
vaultAddress: string | null;
|
||||
isSessionActive: boolean;
|
||||
connectWallet: () => Promise<void>;
|
||||
switchNetwork: () => Promise<void>;
|
||||
refreshBalance: () => Promise<void>;
|
||||
depositToVault: (amount: string) => Promise<string>;
|
||||
withdrawFromVault: (amount: string) => Promise<string>;
|
||||
enableSessionKey: () => Promise<void>;
|
||||
getMarketContract: (address: string) => ethers.Contract | null;
|
||||
getCollateralContract: () => ethers.Contract | null;
|
||||
}
|
||||
@@ -23,9 +28,14 @@ const Web3Context = createContext<Web3ContextType>({
|
||||
chainId: null,
|
||||
isCorrectNetwork: false,
|
||||
wusdBalance: '0',
|
||||
vaultAddress: null,
|
||||
isSessionActive: false,
|
||||
connectWallet: async () => {},
|
||||
switchNetwork: async () => {},
|
||||
refreshBalance: async () => {},
|
||||
depositToVault: async () => '',
|
||||
withdrawFromVault: async () => '',
|
||||
enableSessionKey: async () => {},
|
||||
getMarketContract: () => null,
|
||||
getCollateralContract: () => null,
|
||||
});
|
||||
@@ -36,9 +46,23 @@ export const Web3Provider: React.FC<{ children: React.ReactNode }> = ({ children
|
||||
const [signer, setSigner] = useState<ethers.Signer | null>(null);
|
||||
const [chainId, setChainId] = useState<number | null>(null);
|
||||
const [wusdBalance, setWusdBalance] = useState<string>('0');
|
||||
const [vaultAddress, setVaultAddress] = useState<string | null>(null);
|
||||
const [isSessionActive, setIsSessionActive] = useState<boolean>(false);
|
||||
|
||||
const isCorrectNetwork = chainId === ROBINHOOD_TESTNET_CHAIN.id;
|
||||
|
||||
const predictUserVault = async (userAddr: string, prov: ethers.BrowserProvider) => {
|
||||
try {
|
||||
const factoryAddr = DEPLOYMENTS.robinhoodTestnet.contracts.vaultFactory;
|
||||
if (!factoryAddr) return;
|
||||
const factoryContract = new ethers.Contract(factoryAddr, ABIS.WTFVaultFactory, prov);
|
||||
const predicted = await factoryContract.predictVaultAddress(userAddr);
|
||||
setVaultAddress(predicted);
|
||||
} catch (e) {
|
||||
console.error('Failed to predict vault address:', e);
|
||||
}
|
||||
};
|
||||
|
||||
const refreshBalance = async () => {
|
||||
if (!account || !provider) return;
|
||||
try {
|
||||
@@ -73,10 +97,13 @@ export const Web3Provider: React.FC<{ children: React.ReactNode }> = ({ children
|
||||
(window as any).ethereum.on('accountsChanged', async (accs: string[]) => {
|
||||
if (accs.length > 0) {
|
||||
setAccount(accs[0]);
|
||||
setSigner(await browserProvider.getSigner());
|
||||
const currentSigner = await browserProvider.getSigner();
|
||||
setSigner(currentSigner);
|
||||
predictUserVault(accs[0], browserProvider);
|
||||
} else {
|
||||
setAccount(null);
|
||||
setSigner(null);
|
||||
setVaultAddress(null);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -157,6 +184,44 @@ export const Web3Provider: React.FC<{ children: React.ReactNode }> = ({ children
|
||||
);
|
||||
};
|
||||
|
||||
const depositToVault = async (amountStr: string): Promise<string> => {
|
||||
if (!signer || !account || !vaultAddress) throw new Error('Wallet/Vault not ready');
|
||||
const collateral = new ethers.Contract(
|
||||
DEPLOYMENTS.robinhoodTestnet.contracts.collateral,
|
||||
ABIS.MockERC20,
|
||||
signer
|
||||
);
|
||||
const amountWei = ethers.parseUnits(amountStr, 18);
|
||||
const tx = await collateral.transfer(vaultAddress, amountWei);
|
||||
await tx.wait();
|
||||
refreshBalance();
|
||||
return tx.hash;
|
||||
};
|
||||
|
||||
const withdrawFromVault = async (amountStr: string): Promise<string> => {
|
||||
if (!signer || !account || !vaultAddress) throw new Error('Wallet/Vault not ready');
|
||||
const vault = new ethers.Contract(vaultAddress, ABIS.WTFUserVault, signer);
|
||||
const amountWei = ethers.parseUnits(amountStr, 18);
|
||||
const tx = await vault.withdraw(
|
||||
DEPLOYMENTS.robinhoodTestnet.contracts.collateral,
|
||||
account,
|
||||
amountWei
|
||||
);
|
||||
await tx.wait();
|
||||
refreshBalance();
|
||||
return tx.hash;
|
||||
};
|
||||
|
||||
const enableSessionKey = async () => {
|
||||
if (!signer || !account || !vaultAddress) throw new Error('Wallet/Vault not ready');
|
||||
const vault = new ethers.Contract(vaultAddress, ABIS.WTFUserVault, signer);
|
||||
const relayerAdmin = DEPLOYMENTS.robinhoodTestnet.governance.admin;
|
||||
const duration = 24 * 3600; // 24 hours
|
||||
const tx = await vault.authorizeSession(relayerAdmin, duration);
|
||||
await tx.wait();
|
||||
setIsSessionActive(true);
|
||||
};
|
||||
|
||||
return (
|
||||
<Web3Context.Provider
|
||||
value={{
|
||||
@@ -166,9 +231,14 @@ export const Web3Provider: React.FC<{ children: React.ReactNode }> = ({ children
|
||||
chainId,
|
||||
isCorrectNetwork,
|
||||
wusdBalance,
|
||||
vaultAddress,
|
||||
isSessionActive,
|
||||
connectWallet,
|
||||
switchNetwork,
|
||||
refreshBalance,
|
||||
depositToVault,
|
||||
withdrawFromVault,
|
||||
enableSessionKey,
|
||||
getMarketContract,
|
||||
getCollateralContract,
|
||||
}}
|
||||
|
||||
@@ -1,9 +1,51 @@
|
||||
import React from 'react';
|
||||
import React, { useState } from 'react';
|
||||
import { useWeb3 } from '../../context/Web3Context';
|
||||
import { PieChart, Clock, ArrowUpRight, ArrowDownLeft, ShieldCheck, History } from 'lucide-react';
|
||||
import { PieChart, Clock, ArrowUpRight, ArrowDownLeft, ShieldCheck, History, KeyRound, ArrowRightLeft, Loader2, Check } from 'lucide-react';
|
||||
|
||||
export const PortfolioView: React.FC = () => {
|
||||
const { account, wusdBalance } = useWeb3();
|
||||
const { account, wusdBalance, vaultAddress, isSessionActive, depositToVault, withdrawFromVault, enableSessionKey } = useWeb3();
|
||||
const [depositAmount, setDepositAmount] = useState<string>('500');
|
||||
const [withdrawAmount, setWithdrawAmount] = useState<string>('100');
|
||||
const [loading, setLoading] = useState<boolean>(false);
|
||||
const [actionMsg, setActionMsg] = useState<string | null>(null);
|
||||
|
||||
const handleDeposit = async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
setActionMsg(null);
|
||||
const hash = await depositToVault(depositAmount);
|
||||
setActionMsg(`🎉 成功存入 ${depositAmount} WUSD 到专属非托管金库!Tx: ${hash.slice(0, 10)}...`);
|
||||
} catch (e: any) {
|
||||
alert(e.message || '充值失败');
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const handleWithdraw = async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
setActionMsg(null);
|
||||
const hash = await withdrawFromVault(withdrawAmount);
|
||||
setActionMsg(`🎉 成功从金库提现 ${withdrawAmount} WUSD 到钱包!Tx: ${hash.slice(0, 10)}...`);
|
||||
} catch (e: any) {
|
||||
alert(e.message || '提现失败');
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const handleEnableSession = async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
await enableSessionKey();
|
||||
setActionMsg('⚡ Session Key 免密连击授权成功!24小时内高频交易零弹窗!');
|
||||
} catch (e: any) {
|
||||
alert(e.message || '授权失败');
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const MOCK_POSITIONS = [
|
||||
{
|
||||
@@ -79,11 +121,95 @@ export const PortfolioView: React.FC = () => {
|
||||
</div>
|
||||
|
||||
<div className="bg-[#0f111d] border border-slate-800 rounded-2xl p-6 shadow-xl">
|
||||
<span className="text-xs text-slate-400 block font-medium">活跃预测头寸 (Active Positions)</span>
|
||||
<span className="text-2xl font-black font-mono text-slate-200 mt-1 block">2 个市场</span>
|
||||
<div className="text-xs text-slate-500 mt-2">持仓均基于不可变智能合约保护</div>
|
||||
<span className="text-xs text-slate-400 block font-medium">专属非托管智能金库 (AA User Vault)</span>
|
||||
<span className="text-xs font-mono text-slate-300 truncate block mt-1">
|
||||
{vaultAddress || '连接钱包后自动生成'}
|
||||
</span>
|
||||
<div className="flex items-center space-x-1 text-xs text-emerald-400 font-semibold mt-2">
|
||||
<ShieldCheck className="w-3.5 h-3.5" />
|
||||
<span>100% 资金链上非托管</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Non-Custodial Vault Operations Panel */}
|
||||
<div className="bg-[#0f111d] border border-cyan-900/30 rounded-2xl p-6 shadow-xl space-y-4">
|
||||
<div className="flex flex-col sm:flex-row items-start sm:items-center justify-between gap-3 border-b border-slate-800 pb-4">
|
||||
<div className="flex items-center space-x-3">
|
||||
<div className="p-2.5 bg-cyan-500/10 rounded-xl border border-cyan-500/20 text-cyan-400">
|
||||
<KeyRound className="w-5 h-5" />
|
||||
</div>
|
||||
<div>
|
||||
<h2 className="font-bold text-base text-white">非托管智能金库与免密连击管理 (AA Smart Vault)</h2>
|
||||
<p className="text-xs text-slate-400">平台无法转移你的资产,充值后可开启 Session Key 实现毫秒级 0 弹窗高频交易</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button
|
||||
onClick={handleEnableSession}
|
||||
disabled={loading || isSessionActive || !account}
|
||||
className={`px-4 py-2 rounded-xl text-xs font-bold transition-all flex items-center space-x-1.5 ${
|
||||
isSessionActive
|
||||
? 'bg-emerald-950/60 text-emerald-400 border border-emerald-800/50 cursor-default'
|
||||
: 'bg-gradient-to-r from-cyan-500 to-indigo-600 hover:from-cyan-400 hover:to-indigo-500 text-white shadow-md shadow-cyan-500/20'
|
||||
}`}
|
||||
>
|
||||
<KeyRound className="w-3.5 h-3.5" />
|
||||
<span>{isSessionActive ? '⚡ 免密 Session 已激活 (24H 有效)' : '开启免密连击交易 (Session Key)'}</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4 pt-2">
|
||||
{/* Deposit */}
|
||||
<div className="bg-slate-950/60 border border-slate-800 rounded-xl p-4 space-y-3">
|
||||
<span className="text-xs font-bold text-slate-300 block">充值到专属智能金库 (Deposit to Vault)</span>
|
||||
<div className="flex space-x-2">
|
||||
<input
|
||||
type="number"
|
||||
value={depositAmount}
|
||||
onChange={(e) => setDepositAmount(e.target.value)}
|
||||
placeholder="500"
|
||||
className="flex-1 bg-slate-900 border border-slate-700 rounded-lg px-3 py-2 text-xs font-mono text-slate-100 focus:outline-none focus:border-cyan-500"
|
||||
/>
|
||||
<button
|
||||
onClick={handleDeposit}
|
||||
disabled={loading || !account || !depositAmount}
|
||||
className="px-4 py-2 bg-cyan-600 hover:bg-cyan-500 text-white rounded-lg text-xs font-bold transition-colors disabled:opacity-50"
|
||||
>
|
||||
{loading ? <Loader2 className="w-3.5 h-3.5 animate-spin" /> : '立即充值'}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Withdraw */}
|
||||
<div className="bg-slate-950/60 border border-slate-800 rounded-xl p-4 space-y-3">
|
||||
<span className="text-xs font-bold text-slate-300 block">随时提现到 EOA 钱包 (Instant Withdraw)</span>
|
||||
<div className="flex space-x-2">
|
||||
<input
|
||||
type="number"
|
||||
value={withdrawAmount}
|
||||
onChange={(e) => setWithdrawAmount(e.target.value)}
|
||||
placeholder="100"
|
||||
className="flex-1 bg-slate-900 border border-slate-700 rounded-lg px-3 py-2 text-xs font-mono text-slate-100 focus:outline-none focus:border-cyan-500"
|
||||
/>
|
||||
<button
|
||||
onClick={handleWithdraw}
|
||||
disabled={loading || !account || !withdrawAmount}
|
||||
className="px-4 py-2 bg-slate-800 hover:bg-slate-700 text-slate-200 border border-slate-600 rounded-lg text-xs font-bold transition-colors disabled:opacity-50"
|
||||
>
|
||||
{loading ? <Loader2 className="w-3.5 h-3.5 animate-spin" /> : '提取本金'}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{actionMsg && (
|
||||
<div className="p-3 bg-emerald-950/30 border border-emerald-800/40 rounded-xl text-xs text-emerald-300 flex items-center space-x-2">
|
||||
<Check className="w-4 h-4 text-emerald-400" />
|
||||
<span>{actionMsg}</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Positions Table */}
|
||||
<div className="bg-[#0f111d] border border-slate-800 rounded-2xl p-6 shadow-xl space-y-4">
|
||||
|
||||
@@ -0,0 +1,294 @@
|
||||
[
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "_owner",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "constructor"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "address",
|
||||
"name": "token",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "address",
|
||||
"name": "from",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "uint256",
|
||||
"name": "amount",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "Deposited",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "address",
|
||||
"name": "target",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "uint256",
|
||||
"name": "value",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "bytes",
|
||||
"name": "data",
|
||||
"type": "bytes"
|
||||
}
|
||||
],
|
||||
"name": "Executed",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "address",
|
||||
"name": "sessionKey",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "uint256",
|
||||
"name": "expiry",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "SessionAuthorized",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "address",
|
||||
"name": "sessionKey",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "SessionRevoked",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "address",
|
||||
"name": "token",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "address",
|
||||
"name": "to",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "uint256",
|
||||
"name": "amount",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "Withdrawn",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "token",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "spender",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "amount",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "approveToken",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "sessionKey",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "duration",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "authorizeSession",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "target",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "value",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"internalType": "bytes",
|
||||
"name": "data",
|
||||
"type": "bytes"
|
||||
}
|
||||
],
|
||||
"name": "execute",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "bytes",
|
||||
"name": "",
|
||||
"type": "bytes"
|
||||
}
|
||||
],
|
||||
"stateMutability": "payable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "factory",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "isRelayer",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "bool",
|
||||
"name": "",
|
||||
"type": "bool"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "owner",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "sessionKey",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "revokeSession",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "sessionExpiry",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "token",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "to",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "amount",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "withdraw",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"stateMutability": "payable",
|
||||
"type": "receive"
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,103 @@
|
||||
[
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "address",
|
||||
"name": "user",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "address",
|
||||
"name": "vault",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "uint256",
|
||||
"name": "vaultIndex",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "VaultCreated",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "allVaults",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "user",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "getOrCreateVault",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "vault",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "getVault",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "user",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "predictVaultAddress",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
}
|
||||
]
|
||||
@@ -1,12 +1,16 @@
|
||||
import WTFControllerV2Abi from './abis/WTFControllerV2.json';
|
||||
import MockERC20Abi from './abis/MockERC20.json';
|
||||
import WTFMarketV2Abi from './abis/WTFMarketV2.json';
|
||||
import WTFVaultFactoryAbi from './abis/WTFVaultFactory.json';
|
||||
import WTFUserVaultAbi from './abis/WTFUserVault.json';
|
||||
import robinhoodTestnetDeployment from './robinhoodTestnet.json';
|
||||
|
||||
export const ABIS = {
|
||||
WTFControllerV2: WTFControllerV2Abi,
|
||||
MockERC20: MockERC20Abi,
|
||||
WTFMarketV2: WTFMarketV2Abi
|
||||
WTFMarketV2: WTFMarketV2Abi,
|
||||
WTFVaultFactory: WTFVaultFactoryAbi,
|
||||
WTFUserVault: WTFUserVaultAbi
|
||||
};
|
||||
|
||||
export const DEPLOYMENTS = {
|
||||
|
||||
@@ -7,7 +7,8 @@
|
||||
"collateral": "0xe776e957953EA69b7Eaa9d7d4098aBC076bDD5E7",
|
||||
"powerLDACurve": "0xF0E189974c413506098AFB6Bc6Bf4C6715fBf7B1",
|
||||
"controllerImplementation": "0x2Aeca49669e9E4E6CdCe46A1bc9bf136765A4f75",
|
||||
"controllerProxy": "0xc0E24E152771C588B21AEB654b30B1cBAf381c1a"
|
||||
"controllerProxy": "0xc0E24E152771C588B21AEB654b30B1cBAf381c1a",
|
||||
"vaultFactory": "0x89401e07296267c01017cA150D5Ec8883a78e0B2"
|
||||
},
|
||||
"governance": {
|
||||
"admin": "0x6cddF384792C77219fc25C454Cfe264757842830",
|
||||
|
||||
Reference in New Issue
Block a user