@raac/rpc 1.1.0-beta.55 โ 1.1.0-beta.57
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/RPCLibrary.js +11 -0
- package/dist/oracles/houses/request.js +3 -13
- package/dist/oracles/houses/simulate.js +21 -0
- package/dist/oracles/prime-rate/config.js +3 -36
- package/dist/oracles/prime-rate/request.js +8 -11
- package/dist/oracles/prime-rate/simulate.js +25 -0
- package/dist/pools/lendingPool/getAdapterAddress.js +8 -10
- package/dist/pools/stabilityPool/getStabilityPoolInfo.js +0 -21
- package/dist/pools/stabilityPool/getWithdrawRequestInfo.js +3 -1
- package/dist/scripts/analyze_lending_positions.js +277 -0
- package/dist/scripts/analyze_transfers.js +247 -0
- package/dist/scripts/calculate_portfolio.js +167 -0
- package/dist/scripts/index.js +53 -45
- package/dist/scripts/run_analysis.js +115 -0
- package/dist/scripts/test_lending_analysis.js +105 -0
- package/dist/scripts/users.js +304 -0
- package/dist/types/RPCLibrary.d.ts +10 -0
- package/dist/types/oracles/houses/request.d.ts +2 -1
- package/dist/types/oracles/houses/simulate.d.ts +1 -0
- package/dist/types/oracles/prime-rate/config.d.ts +2 -1
- package/dist/types/oracles/prime-rate/request.d.ts +2 -1
- package/dist/types/oracles/prime-rate/simulate.d.ts +1 -0
- package/dist/types/pools/stabilityPool/getStabilityPoolInfo.d.ts +0 -1
- package/dist/types/pools/stabilityPool/getWithdrawRequestInfo.d.ts +1 -0
- package/dist/types/scripts/analyze_lending_positions.d.ts +1 -0
- package/dist/types/scripts/analyze_transfers.d.ts +1 -0
- package/dist/types/scripts/calculate_portfolio.d.ts +1 -0
- package/dist/types/scripts/run_analysis.d.ts +1 -0
- package/dist/types/scripts/test_lending_analysis.d.ts +1 -0
- package/dist/types/scripts/users.d.ts +1 -0
- package/package.json +2 -1
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const ethers_1 = require("ethers");
|
|
7
|
+
const chains_1 = __importDefault(require("../configs/chains"));
|
|
8
|
+
const RPCLibrary_1 = __importDefault(require("../RPCLibrary"));
|
|
9
|
+
const artifacts_1 = require("../utils/artifacts");
|
|
10
|
+
const chainId = 8453; // Base
|
|
11
|
+
const config = chains_1.default[chainId];
|
|
12
|
+
async function getProvider() {
|
|
13
|
+
return new ethers_1.ethers.JsonRpcProvider(config.rpcs[0]);
|
|
14
|
+
}
|
|
15
|
+
async function testLendingAnalysis() {
|
|
16
|
+
console.log("๐งช Testing Lending Position Analysis...");
|
|
17
|
+
console.log("=====================================");
|
|
18
|
+
try {
|
|
19
|
+
const provider = await getProvider();
|
|
20
|
+
const rpc = new RPCLibrary_1.default();
|
|
21
|
+
rpc.provider = provider;
|
|
22
|
+
rpc.chainId = chainId;
|
|
23
|
+
// Test 1: Get adapters
|
|
24
|
+
console.log("1. Testing adapter retrieval...");
|
|
25
|
+
const adapters = await rpc.pools.lendingPool.getAdapters(chainId, provider);
|
|
26
|
+
console.log(` Found ${adapters.adapters.length} adapters:`, adapters.adapters);
|
|
27
|
+
// Test 2: Test each adapter
|
|
28
|
+
for (const adapterAddress of adapters.adapters) {
|
|
29
|
+
console.log(`\n2. Testing adapter ${adapterAddress}...`);
|
|
30
|
+
try {
|
|
31
|
+
// Get adapter info
|
|
32
|
+
const adapterInfo = rpc.pools.lendingPool.getAdapterAddress(chainId, adapterAddress);
|
|
33
|
+
if (!adapterInfo) {
|
|
34
|
+
console.log(` โ Adapter not found in config`);
|
|
35
|
+
continue;
|
|
36
|
+
}
|
|
37
|
+
console.log(` โ
Adapter type: ${adapterInfo.type}`);
|
|
38
|
+
// Test event querying
|
|
39
|
+
if (adapterInfo.type === "ERC20") {
|
|
40
|
+
const erc20AdapterABI = (0, artifacts_1.getABI)("erc20assetadapter");
|
|
41
|
+
const erc20AdapterContract = new ethers_1.ethers.Contract(adapterInfo.address, erc20AdapterABI, provider);
|
|
42
|
+
const events = await erc20AdapterContract.queryFilter(erc20AdapterContract.filters.TokenDeposited(), "latest" // Only check latest block for testing
|
|
43
|
+
);
|
|
44
|
+
console.log(` โ
Found ${events.length} TokenDeposited events in latest block`);
|
|
45
|
+
}
|
|
46
|
+
else if (adapterInfo.type === "ERC721") {
|
|
47
|
+
const erc721AdapterABI = (0, artifacts_1.getABI)("erc721assetadapter");
|
|
48
|
+
const erc721AdapterContract = new ethers_1.ethers.Contract(adapterInfo.address, erc721AdapterABI, provider);
|
|
49
|
+
const events = await erc721AdapterContract.queryFilter(erc721AdapterContract.filters.NFTDeposited(), "latest" // Only check latest block for testing
|
|
50
|
+
);
|
|
51
|
+
console.log(` โ
Found ${events.length} NFTDeposited events in latest block`);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
catch (error) {
|
|
55
|
+
console.log(` โ Error testing adapter:`, error);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
// Test 3: Test lending pool contract
|
|
59
|
+
console.log("\n3. Testing lending pool contract...");
|
|
60
|
+
try {
|
|
61
|
+
const lendingPoolAddress = config.pools.lendingpool.contract;
|
|
62
|
+
const lendingPoolABI = (0, artifacts_1.getABI)("lendingpool");
|
|
63
|
+
const lendingPoolContract = new ethers_1.ethers.Contract(lendingPoolAddress, lendingPoolABI, provider);
|
|
64
|
+
// Test basic contract calls
|
|
65
|
+
const totalLiquidity = await lendingPoolContract.getTotalLiquidity();
|
|
66
|
+
console.log(` โ
Total liquidity: ${ethers_1.ethers.formatEther(totalLiquidity)}`);
|
|
67
|
+
const primeRate = await lendingPoolContract.getPrimeRate();
|
|
68
|
+
console.log(` โ
Prime rate: ${ethers_1.ethers.formatEther(primeRate)}`);
|
|
69
|
+
}
|
|
70
|
+
catch (error) {
|
|
71
|
+
console.log(` โ Error testing lending pool:`, error);
|
|
72
|
+
}
|
|
73
|
+
// Test 4: Test position view (if we have any positions)
|
|
74
|
+
console.log("\n4. Testing position view...");
|
|
75
|
+
try {
|
|
76
|
+
// Try to get position view for a test address (should fail gracefully if no position)
|
|
77
|
+
const testAddress = "0x0000000000000000000000000000000000000000";
|
|
78
|
+
const testData = new ethers_1.ethers.AbiCoder().encode(["uint256"], [0]);
|
|
79
|
+
if (adapters.adapters.length > 0) {
|
|
80
|
+
const testAdapter = adapters.adapters[0];
|
|
81
|
+
const lendingPoolAddress = config.pools.lendingpool.contract;
|
|
82
|
+
const lendingPoolABI = (0, artifacts_1.getABI)("lendingpool");
|
|
83
|
+
const lendingPoolContract = new ethers_1.ethers.Contract(lendingPoolAddress, lendingPoolABI, provider);
|
|
84
|
+
try {
|
|
85
|
+
await lendingPoolContract.getPositionView(testAdapter, testAddress, testData);
|
|
86
|
+
console.log(" โ Unexpected: Position view succeeded for zero address");
|
|
87
|
+
}
|
|
88
|
+
catch (error) {
|
|
89
|
+
console.log(" โ
Position view correctly failed for zero address (expected)");
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
catch (error) {
|
|
94
|
+
console.log(` โ Error testing position view:`, error);
|
|
95
|
+
}
|
|
96
|
+
console.log("\nโ
Test completed successfully!");
|
|
97
|
+
console.log("The analysis script should work correctly.");
|
|
98
|
+
}
|
|
99
|
+
catch (error) {
|
|
100
|
+
console.error("โ Test failed:", error);
|
|
101
|
+
throw error;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
// Run the test
|
|
105
|
+
testLendingAnalysis().catch(console.error);
|
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
const ethers_1 = require("ethers");
|
|
37
|
+
const fs = __importStar(require("fs"));
|
|
38
|
+
const RPC_URL = 'https://eth-sepolia.g.alchemy.com/v2/GRu4-s8cjabOCnh-3ZFzapF-MwUcURV_'; // Replace with actual RPC
|
|
39
|
+
const provider = new ethers_1.ethers.JsonRpcProvider(RPC_URL);
|
|
40
|
+
const TOKEN_CONTRACT_ADDRESS = '0xd39d5D3289B6B76D4d584a9cD58AED99442D29eb'; // ERC20 token contract
|
|
41
|
+
const NFT_CONTRACT_ADDRESS = '0x9f732c8082a660a89A55ec7551d90393572F5d42'; // Add your ERC721 contract address here
|
|
42
|
+
const ORACLE_CONTRACT_ADDRESS = '0x3a933ab12852a30c83dFDeAEf4a67b84241B0acc'; // Add your oracle contract address here
|
|
43
|
+
const R_TOKEN_ADDRESS = '0x3fea2bF12b686FfFD0321DA6CA6c762FA7C2121C';
|
|
44
|
+
const DE_TOKEN_ADDRESS = '0xdCB4C5aB4aE4873ec700C3EACD1f338547cE6117';
|
|
45
|
+
const IRAAC_TOKEN_ADDRESS = '0xc23b30B0fd654f51e6b833d3d550c320c0f32018';
|
|
46
|
+
// User to exclude from all calculations
|
|
47
|
+
const EXCLUDED_USER = '0x7FaE0737292cD3B7Dc9067AA30a67C42c205015c'.toLowerCase();
|
|
48
|
+
const START_BLOCK = 8718016;
|
|
49
|
+
const END_BLOCK = 'latest';
|
|
50
|
+
const BLOCK_RANGE_LIMIT = 500; // RPC limit for eth_getLogs
|
|
51
|
+
const ERC20_ABI = [
|
|
52
|
+
'event Transfer(address indexed from, address indexed to, uint256 value)',
|
|
53
|
+
'function balanceOf(address owner) view returns (uint256)'
|
|
54
|
+
];
|
|
55
|
+
const ERC721_ABI = [
|
|
56
|
+
'event Transfer(address indexed from, address indexed to, uint256 indexed tokenId)',
|
|
57
|
+
'function balanceOf(address owner) view returns (uint256)',
|
|
58
|
+
'function tokenOfOwnerByIndex(address owner, uint256 index) view returns (uint256)'
|
|
59
|
+
];
|
|
60
|
+
const ORACLE_ABI = [
|
|
61
|
+
'function getLatestPrice(uint256 id) view returns (uint256 price, uint256 timestamp)'
|
|
62
|
+
];
|
|
63
|
+
async function isEOA(address) {
|
|
64
|
+
const code = await provider.getCode(address);
|
|
65
|
+
return code === '0x';
|
|
66
|
+
}
|
|
67
|
+
async function getERC20Balance(tokenAddress, user) {
|
|
68
|
+
const token = new ethers_1.ethers.Contract(tokenAddress, ERC20_ABI, provider);
|
|
69
|
+
return await token.balanceOf(user);
|
|
70
|
+
}
|
|
71
|
+
async function getNFTBalance(nftContract, user) {
|
|
72
|
+
try {
|
|
73
|
+
return await nftContract.balanceOf(user);
|
|
74
|
+
}
|
|
75
|
+
catch (error) {
|
|
76
|
+
console.error(`Error getting NFT balance for ${user}:`, error);
|
|
77
|
+
return 0;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
async function getNFTTokenIds(nftContract, user) {
|
|
81
|
+
try {
|
|
82
|
+
const balance = await nftContract.balanceOf(user);
|
|
83
|
+
const tokenIds = [];
|
|
84
|
+
for (let i = 0; i < balance; i++) {
|
|
85
|
+
try {
|
|
86
|
+
const tokenId = await nftContract.tokenOfOwnerByIndex(user, i);
|
|
87
|
+
tokenIds.push(Number(tokenId));
|
|
88
|
+
}
|
|
89
|
+
catch (error) {
|
|
90
|
+
console.error(`Error getting token ID at index ${i} for user ${user}:`, error);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
return tokenIds;
|
|
94
|
+
}
|
|
95
|
+
catch (error) {
|
|
96
|
+
console.error(`Error getting NFT token IDs for ${user}:`, error);
|
|
97
|
+
return [];
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
async function getHousePrice(oracleContract, tokenId) {
|
|
101
|
+
try {
|
|
102
|
+
const [price, timestamp] = await oracleContract.getLatestPrice(tokenId);
|
|
103
|
+
return {
|
|
104
|
+
price: ethers_1.ethers.formatUnits(price, 18),
|
|
105
|
+
timestamp: new Date(Number(timestamp) * 1000).toISOString()
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
catch (error) {
|
|
109
|
+
console.error(`Error getting house price for token ID ${tokenId}:`, error);
|
|
110
|
+
return {
|
|
111
|
+
price: '0',
|
|
112
|
+
timestamp: 'N/A'
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
async function queryLogsInChunks(contract, filter, startBlock, endBlock) {
|
|
117
|
+
const logs = [];
|
|
118
|
+
let endBlockNumber;
|
|
119
|
+
if (typeof endBlock === 'string' && endBlock === 'latest') {
|
|
120
|
+
endBlockNumber = await provider.getBlockNumber();
|
|
121
|
+
}
|
|
122
|
+
else {
|
|
123
|
+
endBlockNumber = endBlock;
|
|
124
|
+
}
|
|
125
|
+
let currentBlock = startBlock;
|
|
126
|
+
while (currentBlock < endBlockNumber) {
|
|
127
|
+
const chunkEndBlock = Math.min(currentBlock + BLOCK_RANGE_LIMIT - 1, endBlockNumber);
|
|
128
|
+
console.log(`Querying logs from block ${currentBlock} to ${chunkEndBlock}...`);
|
|
129
|
+
try {
|
|
130
|
+
const chunkLogs = await contract.queryFilter(filter, currentBlock, chunkEndBlock);
|
|
131
|
+
logs.push(...chunkLogs);
|
|
132
|
+
console.log(`Found ${chunkLogs.length} logs in this chunk`);
|
|
133
|
+
}
|
|
134
|
+
catch (error) {
|
|
135
|
+
console.error(`Error querying logs from ${currentBlock} to ${chunkEndBlock}:`, error);
|
|
136
|
+
// If we hit an error, try with a smaller range
|
|
137
|
+
if (chunkEndBlock - currentBlock > 100) {
|
|
138
|
+
console.log('Retrying with smaller block range...');
|
|
139
|
+
const smallerEndBlock = Math.min(currentBlock + 100 - 1, endBlockNumber);
|
|
140
|
+
const smallerChunkLogs = await contract.queryFilter(filter, currentBlock, smallerEndBlock);
|
|
141
|
+
logs.push(...smallerChunkLogs);
|
|
142
|
+
console.log(`Found ${smallerChunkLogs.length} logs in smaller chunk`);
|
|
143
|
+
currentBlock = smallerEndBlock + 1;
|
|
144
|
+
}
|
|
145
|
+
else {
|
|
146
|
+
throw error;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
currentBlock = chunkEndBlock + 1;
|
|
150
|
+
}
|
|
151
|
+
return logs;
|
|
152
|
+
}
|
|
153
|
+
function arrayToCSV(data) {
|
|
154
|
+
if (data.length === 0)
|
|
155
|
+
return '';
|
|
156
|
+
const headers = Object.keys(data[0]);
|
|
157
|
+
const csvRows = [headers.join(',')];
|
|
158
|
+
for (const row of data) {
|
|
159
|
+
const values = headers.map(header => {
|
|
160
|
+
const value = row[header];
|
|
161
|
+
// Escape commas and quotes in CSV
|
|
162
|
+
if (typeof value === 'string' && (value.includes(',') || value.includes('"'))) {
|
|
163
|
+
return `"${value.replace(/"/g, '""')}"`;
|
|
164
|
+
}
|
|
165
|
+
return value;
|
|
166
|
+
});
|
|
167
|
+
csvRows.push(values.join(','));
|
|
168
|
+
}
|
|
169
|
+
return csvRows.join('\n');
|
|
170
|
+
}
|
|
171
|
+
async function main() {
|
|
172
|
+
// Check if NFT contract address is provided
|
|
173
|
+
if (!NFT_CONTRACT_ADDRESS) {
|
|
174
|
+
console.error('โ Please provide NFT_CONTRACT_ADDRESS in the script');
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
if (!ORACLE_CONTRACT_ADDRESS) {
|
|
178
|
+
console.error('โ Please provide ORACLE_CONTRACT_ADDRESS in the script');
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
const token = new ethers_1.ethers.Contract(TOKEN_CONTRACT_ADDRESS, ERC20_ABI, provider);
|
|
182
|
+
const nft = new ethers_1.ethers.Contract(NFT_CONTRACT_ADDRESS, ERC721_ABI, provider);
|
|
183
|
+
const oracle = new ethers_1.ethers.Contract(ORACLE_CONTRACT_ADDRESS, ORACLE_ABI, provider);
|
|
184
|
+
console.log('Querying token mint events...');
|
|
185
|
+
const mintEvents = await queryLogsInChunks(token, token.filters.Transfer(ethers_1.ethers.ZeroAddress), START_BLOCK, END_BLOCK);
|
|
186
|
+
// Track mint counts per user
|
|
187
|
+
const mintCounts = {};
|
|
188
|
+
const allMinters = new Set();
|
|
189
|
+
for (const event of mintEvents) {
|
|
190
|
+
const to = event?.args?.to;
|
|
191
|
+
if (to) {
|
|
192
|
+
const user = to.toLowerCase();
|
|
193
|
+
// Exclude the specified user
|
|
194
|
+
if (user === EXCLUDED_USER)
|
|
195
|
+
continue;
|
|
196
|
+
allMinters.add(user);
|
|
197
|
+
mintCounts[user] = (mintCounts[user] || 0) + 1;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
// Log users who minted multiple times
|
|
201
|
+
const multipleMinters = Object.entries(mintCounts).filter(([_, count]) => count > 1);
|
|
202
|
+
console.log(`\n=== USERS WHO MINTED MULTIPLE TIMES ===`);
|
|
203
|
+
console.log(`Found ${multipleMinters.length} users who minted multiple times:`);
|
|
204
|
+
for (const [user, count] of multipleMinters) {
|
|
205
|
+
console.log(`User: ${user} - Minted ${count} times`);
|
|
206
|
+
}
|
|
207
|
+
console.log('========================================\n');
|
|
208
|
+
console.log(`Found ${allMinters.size} unique minters total`);
|
|
209
|
+
console.log('Querying transfer events...');
|
|
210
|
+
const transferEvents = await queryLogsInChunks(token, token.filters.Transfer(), START_BLOCK, END_BLOCK);
|
|
211
|
+
const interactedWithEOA = new Set();
|
|
212
|
+
console.log('Checking EOA interactions...');
|
|
213
|
+
for (const event of transferEvents) {
|
|
214
|
+
const from = event?.args?.from?.toLowerCase();
|
|
215
|
+
const to = event?.args?.to?.toLowerCase();
|
|
216
|
+
// Skip if either from or to is the excluded user
|
|
217
|
+
if (from === EXCLUDED_USER || to === EXCLUDED_USER)
|
|
218
|
+
continue;
|
|
219
|
+
if (from && allMinters.has(from)) {
|
|
220
|
+
const isToEOA = await isEOA(to);
|
|
221
|
+
if (isToEOA)
|
|
222
|
+
interactedWithEOA.add(from);
|
|
223
|
+
}
|
|
224
|
+
if (to && allMinters.has(to)) {
|
|
225
|
+
const isFromEOA = await isEOA(from);
|
|
226
|
+
if (isFromEOA)
|
|
227
|
+
interactedWithEOA.add(to);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
const excludedUsers = [...allMinters].filter(x => !interactedWithEOA.has(x));
|
|
231
|
+
console.log(`Found ${excludedUsers.length} users who haven't interacted with EOAs`);
|
|
232
|
+
// Get balances for ALL users (not just excluded ones)
|
|
233
|
+
console.log('Getting token balances and NFT data for all users...');
|
|
234
|
+
const allUserData = [];
|
|
235
|
+
for (const user of [...allMinters]) {
|
|
236
|
+
const [rTokenBal, deTokenBal, iraacBal, nftBalance, tokenBal] = await Promise.all([
|
|
237
|
+
getERC20Balance(R_TOKEN_ADDRESS, user),
|
|
238
|
+
getERC20Balance(DE_TOKEN_ADDRESS, user),
|
|
239
|
+
getERC20Balance(IRAAC_TOKEN_ADDRESS, user),
|
|
240
|
+
getNFTBalance(nft, user),
|
|
241
|
+
getERC20Balance(TOKEN_CONTRACT_ADDRESS, user)
|
|
242
|
+
]);
|
|
243
|
+
// Get NFT token IDs and their prices
|
|
244
|
+
const nftTokenIds = await getNFTTokenIds(nft, user);
|
|
245
|
+
const nftData = [];
|
|
246
|
+
for (const tokenId of nftTokenIds) {
|
|
247
|
+
const housePrice = await getHousePrice(oracle, tokenId);
|
|
248
|
+
nftData.push({
|
|
249
|
+
tokenId: tokenId,
|
|
250
|
+
price: housePrice.price,
|
|
251
|
+
timestamp: housePrice.timestamp
|
|
252
|
+
});
|
|
253
|
+
}
|
|
254
|
+
const userData = {
|
|
255
|
+
address: user,
|
|
256
|
+
mintCount: mintCounts[user] || 0,
|
|
257
|
+
hasInteractedWithEOA: interactedWithEOA.has(user),
|
|
258
|
+
rTokenBalance: ethers_1.ethers.formatUnits(rTokenBal, 18),
|
|
259
|
+
deTokenBalance: ethers_1.ethers.formatUnits(deTokenBal, 18),
|
|
260
|
+
iraacBalance: ethers_1.ethers.formatUnits(iraacBal, 18),
|
|
261
|
+
tokenBalance: ethers_1.ethers.formatUnits(tokenBal, 18),
|
|
262
|
+
nftBalance: nftBalance,
|
|
263
|
+
nftTokenIds: nftTokenIds.join(';'),
|
|
264
|
+
nftData: JSON.stringify(nftData)
|
|
265
|
+
};
|
|
266
|
+
allUserData.push(userData);
|
|
267
|
+
console.log(`User: ${user}`);
|
|
268
|
+
console.log(` Mint Count: ${userData.mintCount}`);
|
|
269
|
+
console.log(` Interacted with EOA: ${userData.hasInteractedWithEOA}`);
|
|
270
|
+
console.log(` R Token: ${userData.rTokenBalance}`);
|
|
271
|
+
console.log(` DE Token: ${userData.deTokenBalance}`);
|
|
272
|
+
console.log(` iRAAC: ${userData.iraacBalance}`);
|
|
273
|
+
console.log(` Token Balance: ${userData.tokenBalance}`);
|
|
274
|
+
console.log(` NFT Balance: ${userData.nftBalance}`);
|
|
275
|
+
if (nftTokenIds.length > 0) {
|
|
276
|
+
console.log(` NFT Token IDs: ${nftTokenIds.join(', ')}`);
|
|
277
|
+
console.log(` NFT Prices:`);
|
|
278
|
+
for (const nft of nftData) {
|
|
279
|
+
console.log(` Token ID ${nft.tokenId}: ${nft.price} (${nft.timestamp})`);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
console.log('-----------------------------');
|
|
283
|
+
}
|
|
284
|
+
// Save to CSV file
|
|
285
|
+
const csvData = arrayToCSV(allUserData);
|
|
286
|
+
fs.writeFileSync('user_balances.csv', csvData);
|
|
287
|
+
console.log('โ
Saved all user data to user_balances.csv');
|
|
288
|
+
// Also save the multiple minters data separately
|
|
289
|
+
const multipleMintersData = multipleMinters.map(([user, count]) => ({
|
|
290
|
+
address: user,
|
|
291
|
+
mintCount: count,
|
|
292
|
+
rTokenBalance: allUserData.find(u => u.address === user)?.rTokenBalance || '0',
|
|
293
|
+
deTokenBalance: allUserData.find(u => u.address === user)?.deTokenBalance || '0',
|
|
294
|
+
iraacBalance: allUserData.find(u => u.address === user)?.iraacBalance || '0',
|
|
295
|
+
tokenBalance: allUserData.find(u => u.address === user)?.tokenBalance || '0',
|
|
296
|
+
nftBalance: allUserData.find(u => u.address === user)?.nftBalance || '0',
|
|
297
|
+
nftTokenIds: allUserData.find(u => u.address === user)?.nftTokenIds || '',
|
|
298
|
+
nftData: allUserData.find(u => u.address === user)?.nftData || '[]'
|
|
299
|
+
}));
|
|
300
|
+
const multipleMintersCSV = arrayToCSV(multipleMintersData);
|
|
301
|
+
fs.writeFileSync('multiple_minters.csv', multipleMintersCSV);
|
|
302
|
+
console.log('โ
Saved multiple minters data to multiple_minters.csv');
|
|
303
|
+
}
|
|
304
|
+
main().catch(console.error);
|
|
@@ -96,6 +96,8 @@ import { getWithdrawRequestInfo as getStabilityPoolWithdrawRequestInfo } from ".
|
|
|
96
96
|
import { requestWithdraw as requestStabilityPoolWithdraw } from "./pools/stabilityPool/requestWithdraw";
|
|
97
97
|
import { getABI } from "./utils/artifacts";
|
|
98
98
|
import { decodeErrorName, getErrorInfo, attachDecodedError, decodeErrorMessage, attachDecodedErrorMessage } from "./utils/errorDecoder";
|
|
99
|
+
import { request as requestPrimeRate } from "./oracles/prime-rate/request";
|
|
100
|
+
import { request as requestHousePrices } from "./oracles/houses/request";
|
|
99
101
|
declare class RPCLibrary {
|
|
100
102
|
signer: Signer | null;
|
|
101
103
|
isConnected: boolean;
|
|
@@ -120,6 +122,14 @@ declare class RPCLibrary {
|
|
|
120
122
|
};
|
|
121
123
|
rpcs: {};
|
|
122
124
|
};
|
|
125
|
+
oracles: {
|
|
126
|
+
primeRate: {
|
|
127
|
+
request: typeof requestPrimeRate;
|
|
128
|
+
};
|
|
129
|
+
housePrices: {
|
|
130
|
+
request: typeof requestHousePrices;
|
|
131
|
+
};
|
|
132
|
+
};
|
|
123
133
|
nfts: {
|
|
124
134
|
getBaseUri: typeof getBaseUri;
|
|
125
135
|
mint: typeof mintNFT;
|
|
@@ -1 +1,2 @@
|
|
|
1
|
-
|
|
1
|
+
import { Signer } from "ethers5";
|
|
2
|
+
export declare function request(chainId: number, houseId: string, signerV5: Signer): Promise<void>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function simulate(houseId: string): Promise<void>;
|
|
@@ -1 +1,2 @@
|
|
|
1
|
-
|
|
1
|
+
import { Signer } from "ethers5";
|
|
2
|
+
export declare function request(chainId: number, signerV5: Signer): Promise<void>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function simulate(): Promise<void>;
|
|
@@ -4,6 +4,7 @@ interface WithdrawRequestInfo {
|
|
|
4
4
|
amount: string;
|
|
5
5
|
readyAt: number;
|
|
6
6
|
expiresAt: number;
|
|
7
|
+
duration: number;
|
|
7
8
|
}
|
|
8
9
|
export declare function getWithdrawRequestInfo(chainId: ChainId, userAddress: string, provider: Provider): Promise<WithdrawRequestInfo | null>;
|
|
9
10
|
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@raac/rpc",
|
|
3
|
-
"version": "1.1.0-beta.
|
|
3
|
+
"version": "1.1.0-beta.57",
|
|
4
4
|
"description": "RPC Library for RAAC ",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/types/index.d.ts",
|
|
@@ -27,6 +27,7 @@
|
|
|
27
27
|
"license": "MIT",
|
|
28
28
|
"dependencies": {
|
|
29
29
|
"@chainlink/functions-toolkit": "^0.3.2",
|
|
30
|
+
"csv-parser": "^3.2.0",
|
|
30
31
|
"ethers": "^6.0.0",
|
|
31
32
|
"ethers5": "npm:ethers@5.7.2"
|
|
32
33
|
},
|