aiia-vault-sdk 1.0.1

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.
Files changed (39) hide show
  1. package/SeedRoundFundraiser.ts +742 -0
  2. package/TradingVault.ts +863 -0
  3. package/abis/SeedRoundFundraiser.json +1519 -0
  4. package/abis/TradingVault.json +1647 -0
  5. package/common.ts +131 -0
  6. package/contracts/SeedRoundFundraiser.ts +1670 -0
  7. package/contracts/TradingVault.ts +1752 -0
  8. package/contracts/common.ts +131 -0
  9. package/contracts/factories/SeedRoundFundraiser__factory.ts +1495 -0
  10. package/contracts/factories/index.ts +4 -0
  11. package/contracts/index.ts +6 -0
  12. package/contracts.json +28 -0
  13. package/dist/SeedRoundFundraiser.d.ts +130 -0
  14. package/dist/SeedRoundFundraiser.js +445 -0
  15. package/dist/TradingVault.d.ts +175 -0
  16. package/dist/TradingVault.js +521 -0
  17. package/dist/abis/SeedRoundFundraiser.json +1519 -0
  18. package/dist/abis/TradingVault.json +1647 -0
  19. package/dist/common.d.ts +50 -0
  20. package/dist/common.js +2 -0
  21. package/dist/contracts/SeedRoundFundraiser.d.ts +936 -0
  22. package/dist/contracts/SeedRoundFundraiser.js +2 -0
  23. package/dist/contracts/TradingVault.d.ts +930 -0
  24. package/dist/contracts/TradingVault.js +2 -0
  25. package/dist/contracts.json +28 -0
  26. package/dist/index.d.ts +3 -0
  27. package/dist/index.js +19 -0
  28. package/dist/types.d.ts +291 -0
  29. package/dist/types.js +2 -0
  30. package/dist/utils.d.ts +95 -0
  31. package/dist/utils.js +370 -0
  32. package/dist/whitelist-tokens.json +14 -0
  33. package/index.ts +3 -0
  34. package/package.json +21 -0
  35. package/temp/aiia-vault-sdk-1.0.0.tgz +0 -0
  36. package/tsconfig.json +15 -0
  37. package/types.ts +301 -0
  38. package/utils.ts +576 -0
  39. package/whitelist-tokens.json +14 -0
package/dist/utils.js ADDED
@@ -0,0 +1,370 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.signAndSendTransaction = exports.streamEvents = exports.getAllEvents = exports.resolveContractAddress = exports.getRewardWeight = exports.buildApproveERC20Tx = exports.getTokenAllowance = exports.getTokenSymbol = exports.getTokenDecimals = exports.getTransactionStatus = exports.checkRpcHealth = exports.getRandomProvider = exports.sleep = exports.LOG_PREFIXES = void 0;
4
+ const ethers_1 = require("ethers");
5
+ // Debug log prefixes with colors
6
+ exports.LOG_PREFIXES = {
7
+ INFO: "\x1b[36m[STREAM-INFO]\x1b[0m", // Cyan
8
+ BLOCK: "\x1b[33m[STREAM-BLOCK]\x1b[0m", // Yellow
9
+ EVENT: "\x1b[32m[STREAM-EVENT]\x1b[0m", // Green
10
+ ERROR: "\x1b[31m[STREAM-ERROR]\x1b[0m", // Red
11
+ SAVE: "\x1b[35m[STREAM-SAVE]\x1b[0m", // Magenta
12
+ DEBUG: "\x1b[34m[STREAM-DEBUG]\x1b[0m", // Blue
13
+ };
14
+ const sleep = async (ms) => {
15
+ return new Promise((resolve) => setTimeout(resolve, ms));
16
+ };
17
+ exports.sleep = sleep;
18
+ const getRandomProvider = (providers) => {
19
+ return providers[Math.floor(Math.random() * providers.length)];
20
+ };
21
+ exports.getRandomProvider = getRandomProvider;
22
+ const checkRpcHealth = async (provider, index = 0) => {
23
+ try {
24
+ // Try to get the latest block number with a timeout of 5 seconds
25
+ const timeoutPromise = new Promise((_, reject) => {
26
+ setTimeout(() => reject(new Error("RPC request timeout")), 5000);
27
+ });
28
+ await Promise.race([provider.getBlockNumber(), timeoutPromise]);
29
+ return true;
30
+ }
31
+ catch (error) {
32
+ console.error(`${exports.LOG_PREFIXES.ERROR} RPC health check failed:`, error, index);
33
+ return false;
34
+ }
35
+ };
36
+ exports.checkRpcHealth = checkRpcHealth;
37
+ const getTransactionStatus = async (provider, txHash, maxRetries = 10) => {
38
+ let attempts = 0;
39
+ let waitTime = 1000; // Start with 1 second
40
+ while (attempts < maxRetries) {
41
+ try {
42
+ const receipt = await provider.getTransactionReceipt(txHash);
43
+ if (!receipt) {
44
+ attempts++;
45
+ if (attempts === maxRetries) {
46
+ return {
47
+ hash: txHash,
48
+ status: null,
49
+ confirmations: 0,
50
+ isCompleted: false,
51
+ attempts,
52
+ };
53
+ }
54
+ // Exponential backoff: 1s, 2s, 4s, 8s, 16s
55
+ await (0, exports.sleep)(waitTime);
56
+ waitTime *= 2;
57
+ continue;
58
+ }
59
+ const confirmations = Number((await receipt.confirmations()) || 0);
60
+ return {
61
+ hash: receipt.hash,
62
+ status: receipt.status === 1,
63
+ confirmations,
64
+ isCompleted: true,
65
+ attempts: attempts + 1,
66
+ };
67
+ }
68
+ catch (error) {
69
+ throw new Error(`Failed to get transaction status: ${error.message}`);
70
+ }
71
+ }
72
+ // This should never be reached due to the return in the if(!receipt) block
73
+ throw new Error("Failed to get transaction status after maximum retries");
74
+ };
75
+ exports.getTransactionStatus = getTransactionStatus;
76
+ const getTokenDecimals = async (tokenAddress, provider) => {
77
+ const tokenContract = new ethers_1.ethers.Contract(tokenAddress, ["function decimals() view returns (uint8)"], provider);
78
+ return Number(await tokenContract.decimals());
79
+ };
80
+ exports.getTokenDecimals = getTokenDecimals;
81
+ const getTokenSymbol = async (tokenAddress, provider) => {
82
+ const tokenContract = new ethers_1.ethers.Contract(tokenAddress, ["function symbol() view returns (string)"], provider);
83
+ return await tokenContract.symbol();
84
+ };
85
+ exports.getTokenSymbol = getTokenSymbol;
86
+ const getTokenAllowance = async (tokenAddress, owner, spender, provider) => {
87
+ // If the token is ETH (zero address), return max bigint value
88
+ if (tokenAddress === ethers_1.ethers.ZeroAddress ||
89
+ tokenAddress.toLowerCase() === ethers_1.ethers.ZeroAddress) {
90
+ // Max bigint value (2^256 - 1)
91
+ return BigInt("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
92
+ }
93
+ const tokenContract = new ethers_1.ethers.Contract(tokenAddress, [
94
+ "function allowance(address owner, address spender) view returns (uint256)",
95
+ ], provider);
96
+ return await tokenContract.allowance(owner, spender);
97
+ };
98
+ exports.getTokenAllowance = getTokenAllowance;
99
+ const buildApproveERC20Tx = async (tokenAddress, spender, amount, provider) => {
100
+ const tokenContract = new ethers_1.ethers.Contract(tokenAddress, ["function approve(address spender, uint256 amount) returns (bool)"], provider);
101
+ return await tokenContract.approve.populateTransaction(spender, amount);
102
+ };
103
+ exports.buildApproveERC20Tx = buildApproveERC20Tx;
104
+ const getRewardWeight = (duration, configs) => {
105
+ let maxWeight = 0;
106
+ // Sort configs by duration to ensure correct weight calculation
107
+ const sortedConfigs = [...configs].sort((a, b) => a.duration - b.duration);
108
+ for (const config of sortedConfigs) {
109
+ if (duration >= config.duration) {
110
+ maxWeight = config.weight;
111
+ }
112
+ }
113
+ return maxWeight;
114
+ };
115
+ exports.getRewardWeight = getRewardWeight;
116
+ const resolveContractAddress = (rpcUrl, contractName, contracts, providedAddress) => {
117
+ if (providedAddress) {
118
+ return providedAddress;
119
+ }
120
+ const rpcLower = rpcUrl.toLowerCase();
121
+ if (["testnet", "sepolia", "goerli"].some((network) => rpcLower.includes(network))) {
122
+ if (rpcLower.includes("sepolia.base")) {
123
+ return contracts?.["base-sepolia"]?.[contractName];
124
+ }
125
+ else if (rpcLower.includes("sepolia")) {
126
+ return contracts?.sepolia?.[contractName];
127
+ }
128
+ else if (rpcLower.includes("goerli")) {
129
+ return contracts?.goerli?.[contractName];
130
+ }
131
+ throw new Error("Unsupported testnet network");
132
+ }
133
+ return contracts?.mainnet?.[contractName];
134
+ };
135
+ exports.resolveContractAddress = resolveContractAddress;
136
+ /**
137
+ * Generic function to get all events from a contract within a block range
138
+ * @param contract The ethers contract instance
139
+ * @param getRandomProvider Function to get a random provider
140
+ * @param fromBlock Starting block number
141
+ * @param toBlock Ending block number
142
+ * @returns Array of parsed events with timestamps
143
+ */
144
+ const getAllEvents = async (contract, getRandomProvider, getContractWithRandomProvider, fromBlock, toBlock) => {
145
+ // Get all event names from the contract interface
146
+ const eventNames = [];
147
+ contract.interface.forEachEvent((event) => {
148
+ eventNames.push(event.name);
149
+ });
150
+ // Create filter for each event type
151
+ const eventPromises = eventNames.map(async (eventName) => {
152
+ // Create a new contract instance with a random provider for each query
153
+ const randomContract = getContractWithRandomProvider();
154
+ const filter = randomContract.filters[eventName]();
155
+ const events = await randomContract.queryFilter(filter, fromBlock, toBlock);
156
+ // Parse each event into a more readable format
157
+ return events.map((event) => {
158
+ const parsedLog = contract.interface.parseLog({
159
+ topics: event.topics,
160
+ data: event.data,
161
+ });
162
+ return {
163
+ eventName,
164
+ blockNumber: event.blockNumber,
165
+ transactionHash: event.transactionHash,
166
+ args: parsedLog?.args.toObject(),
167
+ timestamp: null, // Will be populated below
168
+ };
169
+ });
170
+ });
171
+ // Wait for all event queries to complete
172
+ const allEvents = (await Promise.all(eventPromises)).flat();
173
+ // Sort events by block number
174
+ allEvents.sort((a, b) => a.blockNumber - b.blockNumber);
175
+ // Get block timestamps in batches to improve performance
176
+ const uniqueBlocks = [...new Set(allEvents.map((e) => e.blockNumber))];
177
+ const blockPromises = uniqueBlocks.map((blockNumber) => getRandomProvider().getBlock(blockNumber));
178
+ const blocks = await Promise.all(blockPromises);
179
+ // Create a map of block numbers to timestamps
180
+ const blockTimestamps = new Map(blocks.map((block) => [block.number, block.timestamp]));
181
+ // Add timestamps to events
182
+ return allEvents.map((event) => ({
183
+ eventName: event.eventName,
184
+ blockNumber: event.blockNumber,
185
+ transactionHash: event.transactionHash,
186
+ args: Object.fromEntries(Object.entries(event.args || {}).filter(([key]) => isNaN(Number(key)))),
187
+ timestamp: blockTimestamps.get(event.blockNumber) ?? null,
188
+ }));
189
+ };
190
+ exports.getAllEvents = getAllEvents;
191
+ /**
192
+ * Generic function to stream blockchain events
193
+ * @param getProvider Function to get a provider
194
+ * @param getAllEvents Function to get events for a block range
195
+ * @param formatEvent Function to format raw events
196
+ * @param onEvent Callback for each processed event
197
+ * @param saveLatestBlock Function to save the latest processed block
198
+ * @param fromBlock Starting block number
199
+ * @param batchSize Number of blocks to process in each batch
200
+ * @param sleepTime Time to wait between iterations when caught up
201
+ */
202
+ const streamEvents = async ({ getProvider, getAllEvents, formatEvent, onEvent, saveLatestBlock, fromBlock, batchSize = 1000, sleepTime = 5000, }) => {
203
+ const debugEnabled = process.env.DEBUG_STREAM_EVENTS === "1";
204
+ let currentBlock = fromBlock;
205
+ if (debugEnabled) {
206
+ console.log(`${exports.LOG_PREFIXES.INFO} StreamEvents Debug Mode Enabled`);
207
+ console.log(`${exports.LOG_PREFIXES.INFO} Initial fromBlock: ${currentBlock}`);
208
+ console.log(`${exports.LOG_PREFIXES.INFO} Batch size: ${batchSize}`);
209
+ console.log(`${exports.LOG_PREFIXES.INFO} Sleep time: ${sleepTime}ms`);
210
+ }
211
+ while (true) {
212
+ try {
213
+ // Get the latest block number
214
+ const latestBlock = await getProvider().getBlockNumber();
215
+ if (debugEnabled) {
216
+ console.log(`${exports.LOG_PREFIXES.BLOCK} Latest block: ${latestBlock}`);
217
+ }
218
+ // Calculate toBlock as min(fromBlock + batchSize, latestBlock)
219
+ const toBlock = Math.min(currentBlock + batchSize, latestBlock);
220
+ if (debugEnabled) {
221
+ console.log(`${exports.LOG_PREFIXES.BLOCK} Processing blocks from ${currentBlock} to ${toBlock}`);
222
+ }
223
+ // If we've caught up to the latest block, wait before next iteration
224
+ if (currentBlock >= latestBlock) {
225
+ if (debugEnabled) {
226
+ console.log(`${exports.LOG_PREFIXES.DEBUG} Caught up to latest block, waiting ${sleepTime}ms...`);
227
+ }
228
+ await (0, exports.sleep)(sleepTime);
229
+ continue;
230
+ }
231
+ // Get events for the current batch
232
+ const events = await getAllEvents(currentBlock, toBlock);
233
+ if (debugEnabled && events.length > 0) {
234
+ const eventTypes = events.reduce((acc, event) => {
235
+ const eventName = event.eventName || "Unknown";
236
+ acc[eventName] = (acc[eventName] || 0) + 1;
237
+ return acc;
238
+ }, {});
239
+ console.log(`${exports.LOG_PREFIXES.EVENT} Found ${events.length} events:`);
240
+ Object.entries(eventTypes).forEach(([eventName, count]) => {
241
+ console.log(`${exports.LOG_PREFIXES.EVENT} - ${eventName}: ${count}`);
242
+ });
243
+ }
244
+ // Process each event
245
+ for (const event of events) {
246
+ if (debugEnabled) {
247
+ console.log(`${exports.LOG_PREFIXES.EVENT} Processing: ${event.eventName || "Event"}`);
248
+ }
249
+ await onEvent(formatEvent(event));
250
+ }
251
+ // Save the latest processed block
252
+ await saveLatestBlock(toBlock);
253
+ if (debugEnabled) {
254
+ console.log(`${exports.LOG_PREFIXES.SAVE} Saved latest block: ${toBlock}`);
255
+ }
256
+ // Update fromBlock for next iteration
257
+ currentBlock = toBlock + 1;
258
+ }
259
+ catch (error) {
260
+ if (debugEnabled) {
261
+ console.error(`${exports.LOG_PREFIXES.ERROR} Error in streamEvents:`, error);
262
+ console.error(`${exports.LOG_PREFIXES.ERROR} Stack trace:`, error instanceof Error ? error.stack : "");
263
+ }
264
+ else {
265
+ console.error(`${exports.LOG_PREFIXES.ERROR} Error in streamEvents:`, error);
266
+ }
267
+ await (0, exports.sleep)(1000); // Wait before retrying on error
268
+ }
269
+ }
270
+ };
271
+ exports.streamEvents = streamEvents;
272
+ /**
273
+ * Generic function to sign and send a transaction
274
+ * @param tx The transaction to send
275
+ * @param wallet The wallet or sendTransaction function to use
276
+ * @param getRandomProvider Function to get a random provider
277
+ * @param contract Optional contract instance
278
+ * @param callbacks Optional callbacks for transaction events
279
+ * @returns Transaction result with status
280
+ */
281
+ const signAndSendTransaction = async (tx, wallet, getRandomProvider, { onSubmit, onFinally, onError, } = {}, contract) => {
282
+ try {
283
+ // Prepare the transaction
284
+ const transaction = {
285
+ ...tx,
286
+ };
287
+ // Sign and send the transaction
288
+ let txHash;
289
+ // Check if wallet is an object with the expected Wallet methods
290
+ if (typeof wallet === "object" &&
291
+ wallet !== null &&
292
+ "sendTransaction" in wallet) {
293
+ const connectedWallet = wallet.connect(getRandomProvider());
294
+ const signedTx = await connectedWallet.sendTransaction(transaction);
295
+ txHash = signedTx.hash;
296
+ }
297
+ else {
298
+ // Assume it's a SendTransactionMutateAsync function
299
+ txHash = await wallet(transaction);
300
+ }
301
+ // Call onSubmit callback if provided
302
+ if (onSubmit) {
303
+ await onSubmit(txHash);
304
+ }
305
+ // Check transaction status
306
+ const status = await (0, exports.getTransactionStatus)(getRandomProvider(), txHash);
307
+ // Add new error handling
308
+ if (status.status === null) {
309
+ throw new Error("Transaction may not be minted on-chain yet or has failed. Please check the blockchain explorer.");
310
+ }
311
+ if (status.status === false) {
312
+ throw new Error("Transaction failed. Please check the blockchain explorer for details.");
313
+ }
314
+ // Call onFinally callback if provided
315
+ if (onFinally) {
316
+ await onFinally({ ...status, txHash });
317
+ }
318
+ return {
319
+ transaction: {
320
+ hash: txHash,
321
+ },
322
+ status,
323
+ };
324
+ }
325
+ catch (error) {
326
+ // Try to decode the error if contract is provided
327
+ if (contract && error) {
328
+ try {
329
+ // Handle custom errors from estimateGas or other pre-transaction errors
330
+ if (error.code === "CALL_EXCEPTION" && error.data) {
331
+ // The error.data contains the custom error selector (first 4 bytes of the error signature hash)
332
+ const errorSelector = error.data;
333
+ // Try to find matching error in the contract interface
334
+ for (const errorFragment of Object.values(contract.interface.fragments).filter((fragment) => fragment.type === "error")) {
335
+ if ("name" in errorFragment) {
336
+ // Calculate the selector for this error
337
+ const errorDef = contract.interface.getError(errorFragment.name);
338
+ if (errorDef && errorDef.selector) {
339
+ const calculatedSelector = errorDef.selector;
340
+ if (calculatedSelector === errorSelector) {
341
+ // Found matching error!
342
+ const errorName = errorFragment.name;
343
+ const errorArgs = error.errorArgs || [];
344
+ const enhancedError = new Error(`Transaction failed with custom error: ${errorName}(${errorArgs.join(", ")})`);
345
+ // Preserve original error properties
346
+ Object.assign(enhancedError, error);
347
+ if (onError) {
348
+ await onError(enhancedError);
349
+ }
350
+ throw enhancedError;
351
+ }
352
+ }
353
+ }
354
+ }
355
+ // If we couldn't match the selector to a known error
356
+ console.log(`${exports.LOG_PREFIXES.DEBUG} Unknown custom error with selector: ${errorSelector}`);
357
+ }
358
+ }
359
+ catch (decodeError) {
360
+ console.error(`${exports.LOG_PREFIXES.ERROR} Error decoding transaction error:`, decodeError);
361
+ }
362
+ }
363
+ // Call onError callback if provided
364
+ if (onError) {
365
+ await onError(error instanceof Error ? error : new Error(String(error)));
366
+ }
367
+ throw error; // Re-throw the error after handling
368
+ }
369
+ };
370
+ exports.signAndSendTransaction = signAndSendTransaction;
@@ -0,0 +1,14 @@
1
+ {
2
+ "sepolia": [
3
+ "0x1234567890123456789012345678901234567890",
4
+ "0xabcdefabcdefabcdefabcdefabcdefabcdefabcd",
5
+ "0x0000000000000000000000000000000000000000",
6
+ "0x09F827Fa3307cF467F51782722A5e3f43a2598dc",
7
+ "0xC82AE9c8b25F5b48ac200efd3e86Ca372AE1AD91"
8
+ ],
9
+ "base-sepolia": [
10
+ "0x0000000000000000000000000000000000000000",
11
+ "0xa5Ef2328aa2F6F231D15cdcF48503974D0938eD4",
12
+ "0x08a2d38807B1D345b6c1642f8030a29DC2Cc7223"
13
+ ]
14
+ }
package/index.ts ADDED
@@ -0,0 +1,3 @@
1
+ export * from "./TradingVault";
2
+ export * from "./SeedRoundFundraiser";
3
+ export * from "./types";
package/package.json ADDED
@@ -0,0 +1,21 @@
1
+ {
2
+ "name": "aiia-vault-sdk",
3
+ "version": "1.0.1",
4
+ "description": "SDK for AIIA Vault Contract",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "scripts": {
8
+ "build": "tsc",
9
+ "clean": "rm -rf dist",
10
+ "prebuild": "npm run clean"
11
+ },
12
+ "dependencies": {
13
+ "ethers": "^6.0.0",
14
+ "wagmi": "^2.14.6",
15
+ "@wagmi/core": "^2.16.3"
16
+ },
17
+ "devDependencies": {
18
+ "typescript": "^5.0.0",
19
+ "@types/node": "^20.0.0"
20
+ }
21
+ }
Binary file
package/tsconfig.json ADDED
@@ -0,0 +1,15 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "es2020",
4
+ "module": "commonjs",
5
+ "declaration": true,
6
+ "outDir": "./dist",
7
+ "esModuleInterop": true,
8
+ "forceConsistentCasingInFileNames": true,
9
+ "strict": true,
10
+ "skipLibCheck": true,
11
+ "resolveJsonModule": true
12
+ },
13
+ "include": ["*.ts"],
14
+ "exclude": ["node_modules", "dist"]
15
+ }