aiia-vault-sdk 1.1.0 → 1.1.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.
@@ -34,6 +34,13 @@ export interface UserContribution {
34
34
  contributedToken: string;
35
35
  contributedAmount: number;
36
36
  }
37
+ /**
38
+ * SDK for interacting with the SeedRoundFundraiser smart contract
39
+ *
40
+ * @remarks
41
+ * This SDK provides methods to interact with the SeedRoundFundraiser contract,
42
+ * including contributing tokens, managing rounds, and handling whitelisted tokens.
43
+ */
37
44
  export declare class SeedRoundFundraiserSDK {
38
45
  name: string;
39
46
  private contract;
@@ -43,14 +50,138 @@ export declare class SeedRoundFundraiserSDK {
43
50
  private PRICE_PRECISION;
44
51
  private whitelistedTokensArray;
45
52
  private networkName;
53
+ /**
54
+ * Creates a new instance of the SeedRoundFundraiserSDK
55
+ *
56
+ * @param rpcUrls - Single RPC URL or array of RPC URLs for blockchain connection
57
+ * @param contractAddress - Optional contract address. If not provided, will be resolved from contracts.json
58
+ *
59
+ * @throws Will throw if no valid RPC providers are available
60
+ */
46
61
  constructor(rpcUrls: string | string[], contractAddress?: string);
62
+ /**
63
+ * Gets the network name from the RPC URL
64
+ *
65
+ * @param rpcUrl - The RPC URL to parse
66
+ * @returns The network name (e.g., 'sepolia', 'mainnet', 'base-sepolia')
67
+ * @private
68
+ */
47
69
  private getNetworkNameFromRpc;
70
+ /**
71
+ * Imports whitelisted tokens from configuration file
72
+ *
73
+ * @private
74
+ */
48
75
  private importWhitelistedTokens;
76
+ /**
77
+ * Gets detailed information about a whitelisted token
78
+ *
79
+ * @param tokenAddress - The address of the token to query
80
+ * @returns Token information including price, symbol, and contribution limits, or null if not whitelisted
81
+ *
82
+ * @example
83
+ * ```typescript
84
+ * const tokenInfo = await sdk.getWhitelistedTokenInfo("0x...");
85
+ * if (tokenInfo) {
86
+ * console.log(`Max contribution: ${tokenInfo.maxContribution} ${tokenInfo.symbol}`);
87
+ * }
88
+ * ```
89
+ */
49
90
  getWhitelistedTokenInfo(tokenAddress: string): Promise<WhitelistedTokenInfo | null>;
91
+ /**
92
+ * Gets information about all whitelisted tokens that are accepted for seed round participation.
93
+ *
94
+ * @remarks
95
+ * This function iterates through all whitelisted token addresses and fetches detailed information
96
+ * for each token that is actually whitelisted in the smart contract. The price and maxContribution
97
+ * values are calculated based on the current active round settings.
98
+ *
99
+ * @returns Promise<WhitelistedTokenInfo[]> Array of whitelisted token information with the following fields:
100
+ * - `address` (string): The token's contract address on the blockchain. For ETH, this will be the zero address (0x000...000)
101
+ * - `isWhitelisted` (boolean): Whether the token is currently whitelisted and accepted for contributions
102
+ * - `price` (number): Token price in USD with PRICE_PRECISION decimals (e.g., 1800.5 means 1 token = $1800.50)
103
+ * - `symbol` (string): Token symbol (e.g., "ETH", "USDC", "USDT")
104
+ * - `maxContribution` (number): Maximum amount of tokens a user can contribute in human-readable format,
105
+ * calculated as (maxFundPerAccount / tokenPrice)
106
+ * - `maxContributionRaw` (number): Maximum contribution amount adjusted with token decimals (maxContribution * 10^decimals),
107
+ * ready for contract interaction
108
+ * - `decimals` (number): Number of decimal places the token uses (e.g., 18 for ETH, 6 for USDC)
109
+ *
110
+ * @example
111
+ * ```typescript
112
+ * const sdk = new SeedRoundFundraiserSDK(rpcUrl);
113
+ * const whitelistedTokens = await sdk.getAllWhitelistedTokensInfo();
114
+ *
115
+ * // Example response:
116
+ * [
117
+ * {
118
+ * address: "0x0000000000000000000000000000000000000000",
119
+ * isWhitelisted: true,
120
+ * price: 1800.5, // 1 ETH = $1800.50
121
+ * symbol: "ETH",
122
+ * maxContribution: 5.55, // Can contribute up to 5.55 ETH
123
+ * maxContributionRaw: 5550000000000000000n, // 5.55 * 10^18
124
+ * decimals: 18
125
+ * },
126
+ * {
127
+ * address: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
128
+ * isWhitelisted: true,
129
+ * price: 1.0, // 1 USDC = $1.00
130
+ * symbol: "USDC",
131
+ * maxContribution: 10000, // Can contribute up to 10000 USDC
132
+ * maxContributionRaw: 10000000000, // 10000 * 10^6
133
+ * decimals: 6
134
+ * }
135
+ * ]
136
+ * ```
137
+ *
138
+ * @notice
139
+ * - Token prices are in USD with PRICE_PRECISION (1e18) decimals
140
+ * - maxContribution is calculated based on the current round's maxFundPerAccount
141
+ * - For new rounds or if no active round exists, maxContribution will be 0
142
+ * - ETH is represented with the zero address and always has 18 decimals
143
+ *
144
+ * @see {@link getWhitelistedTokenInfo} For getting information about a single token
145
+ * @see {@link WhitelistedTokenInfo} For the interface definition
146
+ */
50
147
  getAllWhitelistedTokensInfo(): Promise<WhitelistedTokenInfo[]>;
148
+ /**
149
+ * Gets a random provider from the available providers
150
+ *
151
+ * @returns An ethers Provider instance
152
+ * @private
153
+ */
51
154
  private getRandomProvider;
155
+ /**
156
+ * Gets a contract instance with a random provider
157
+ *
158
+ * @returns Contract instance
159
+ * @private
160
+ */
52
161
  private getContractWithRandomProvider;
162
+ /**
163
+ * Bootstraps the SDK by checking RPC health and removing inactive providers
164
+ *
165
+ * @throws Will throw if no active RPC providers are available
166
+ */
53
167
  bootstrap(): Promise<void>;
168
+ /**
169
+ * Signs and sends a transaction to the blockchain
170
+ *
171
+ * @param tx - The transaction to send
172
+ * @param wallet - The wallet or transaction sender
173
+ * @param callbacks - Optional callbacks for transaction lifecycle events
174
+ * @returns Transaction result and status
175
+ *
176
+ * @example
177
+ * ```typescript
178
+ * const tx = await sdk.buildContributeTx(0, ethers.ZeroAddress, 1.5);
179
+ * const result = await sdk.signAndSendTransaction(tx, wallet, {
180
+ * onSubmit: (txHash) => console.log(`Submitted: ${txHash}`),
181
+ * onFinally: (status) => console.log(`Completed: ${status.status}`)
182
+ * });
183
+ * ```
184
+ */
54
185
  signAndSendTransaction(tx: ethers.ContractTransaction, wallet: ethers.Wallet | SendTransactionMutateAsync<Config, any>, callbacks?: {
55
186
  onSubmit?: (tx: string) => void | Promise<void>;
56
187
  onFinally?: (status: {
@@ -72,20 +203,154 @@ export declare class SeedRoundFundraiserSDK {
72
203
  attempts: number;
73
204
  };
74
205
  }>;
206
+ /**
207
+ * Builds a transaction to add a token to the whitelist
208
+ *
209
+ * @param token - The token address to whitelist
210
+ * @param price - The price of the token in USD (with PRICE_PRECISION decimals)
211
+ * @returns Populated transaction
212
+ *
213
+ * @example
214
+ * ```typescript
215
+ * const tx = await sdk.buildAddWhitelistedTokenTx("0x...", 1800.5);
216
+ * ```
217
+ */
75
218
  buildAddWhitelistedTokenTx(token: string, price: number): Promise<ethers.ContractTransaction>;
219
+ /**
220
+ * Builds a transaction to update a whitelisted token's price
221
+ *
222
+ * @param token - The token address
223
+ * @param newPrice - The new price in USD (with PRICE_PRECISION decimals)
224
+ * @returns Populated transaction
225
+ */
76
226
  buildUpdateTokenPriceTx(token: string, newPrice: number): Promise<ethers.ContractTransaction>;
227
+ /**
228
+ * Builds a transaction to remove a token from the whitelist
229
+ *
230
+ * @param token - The token address to remove
231
+ * @returns Populated transaction
232
+ */
77
233
  buildRemoveWhitelistedTokenTx(token: string): Promise<ethers.ContractTransaction>;
234
+ /**
235
+ * Builds a transaction to create a new fundraising round
236
+ *
237
+ * @param startTime - Round start time (Unix timestamp)
238
+ * @param endTime - Round end time (Unix timestamp)
239
+ * @param targetFund - Target funding amount in USD (with PRICE_PRECISION decimals)
240
+ * @param totalAllocation - Total tokens to allocate
241
+ * @param maxFundPerAccount - Maximum funding per account in USD
242
+ * @returns Populated transaction
243
+ *
244
+ * @example
245
+ * ```typescript
246
+ * const now = Math.floor(Date.now() / 1000);
247
+ * const tx = await sdk.buildCreateRoundTx(
248
+ * now,
249
+ * now + 86400, // 24 hours
250
+ * 1000000, // $1M target
251
+ * 1000000, // 1M tokens
252
+ * 10000 // $10k max per account
253
+ * );
254
+ * ```
255
+ */
78
256
  buildCreateRoundTx(startTime: number, endTime: number, targetFund: number, totalAllocation: number, maxFundPerAccount: number): Promise<ethers.ContractTransaction>;
257
+ /**
258
+ * Builds a transaction to update an existing round's parameters
259
+ *
260
+ * @param roundId - The ID of the round to update
261
+ * @param startTime - New start time
262
+ * @param endTime - New end time
263
+ * @param targetFund - New target fund amount
264
+ * @param totalAllocation - New total token allocation
265
+ * @param maxFundPerAccount - New maximum funding per account
266
+ * @returns Populated transaction
267
+ */
79
268
  buildUpdateRoundTx(roundId: number, startTime: number, endTime: number, targetFund: number, totalAllocation: number, maxFundPerAccount: number): Promise<ethers.ContractTransaction>;
269
+ /**
270
+ * Builds a transaction to end a round
271
+ *
272
+ * @param roundId - The ID of the round to end
273
+ * @returns Populated transaction
274
+ */
80
275
  buildEndRoundTx(roundId: number): Promise<ethers.ContractTransaction>;
276
+ /**
277
+ * Builds a transaction to enable/disable token claiming for a round
278
+ *
279
+ * @param roundId - The round ID
280
+ * @param enabled - Whether to enable or disable claiming
281
+ * @returns Populated transaction
282
+ */
81
283
  buildSetClaimingEnabledTx(roundId: number, enabled: boolean): Promise<ethers.ContractTransaction>;
284
+ /**
285
+ * Builds a transaction to enable/disable refunds for a round
286
+ *
287
+ * @param roundId - The round ID
288
+ * @param enabled - Whether to enable or disable refunds
289
+ * @returns Populated transaction
290
+ */
82
291
  buildSetRefundEnabledTx(roundId: number, enabled: boolean): Promise<ethers.ContractTransaction>;
292
+ /**
293
+ * Builds a transaction to contribute to a round
294
+ *
295
+ * @param roundId - The ID of the round to contribute to
296
+ * @param token - The token address (use ethers.ZeroAddress for ETH)
297
+ * @param amount - Amount to contribute in human-readable format
298
+ * @returns Populated transaction
299
+ *
300
+ * @example
301
+ * ```typescript
302
+ * // Contribute 1.5 ETH
303
+ * const tx = await sdk.buildContributeTx(0, ethers.ZeroAddress, 1.5);
304
+ *
305
+ * // Contribute 1000 USDC
306
+ * const tx = await sdk.buildContributeTx(0, "0x...", 1000);
307
+ * ```
308
+ *
309
+ * @notice For ERC20 tokens, ensure you have approved the contract first
310
+ */
83
311
  buildContributeTx(roundId: number, token: string, amount: number): Promise<ethers.ContractTransaction>;
312
+ /**
313
+ * Builds a transaction to claim allocated tokens
314
+ *
315
+ * @returns Populated transaction for claiming tokens from all eligible rounds
316
+ */
84
317
  buildClaimTokensTx(): Promise<ethers.ContractTransaction>;
318
+ /**
319
+ * Builds a transaction to request a refund
320
+ *
321
+ * @returns Populated transaction for requesting refund from eligible rounds
322
+ */
85
323
  buildRefundTx(): Promise<ethers.ContractTransaction>;
324
+ /**
325
+ * Builds a transaction to withdraw accumulated funds
326
+ *
327
+ * @param token - The token address to withdraw
328
+ * @param amount - Amount to withdraw in human-readable format
329
+ * @returns Populated transaction
330
+ *
331
+ * @notice Only callable by contract owner
332
+ */
86
333
  buildWithdrawFundsTx(token: string, amount: number): Promise<ethers.ContractTransaction>;
334
+ /**
335
+ * Builds a transaction to claim tokens from a specific round
336
+ *
337
+ * @param roundId - The round ID to claim tokens from
338
+ * @returns Populated transaction
339
+ */
87
340
  buildClaimTokensByRoundIdTx(roundId: number): Promise<ethers.ContractTransaction>;
341
+ /**
342
+ * Gets information about a whitelisted token
343
+ *
344
+ * @param token - The token address
345
+ * @returns Token whitelist status and price
346
+ */
88
347
  getWhitelistedToken(token: string): Promise<WhitelistedToken>;
348
+ /**
349
+ * Gets configuration of a specific round
350
+ *
351
+ * @param roundId - The round ID to query
352
+ * @returns Round configuration including times, targets, and status
353
+ */
89
354
  getRound(roundId: number): Promise<RoundConfig>;
90
355
  getUserContribution(roundId: number, user: string): Promise<UserContribution>;
91
356
  getRoundRaisedFunds(roundId: number): Promise<number>;
@@ -101,9 +366,63 @@ export declare class SeedRoundFundraiserSDK {
101
366
  */
102
367
  getLatestRoundId(): Promise<number>;
103
368
  /**
104
- * Get comprehensive information about a specific round
105
- * @param roundId The ID of the round to get information for
106
- * @returns An object containing all information about the specified round
369
+ * Gets comprehensive information about a specific fundraising round
370
+ *
371
+ * @param roundId - The ID of the round to query (0-based index)
372
+ * @returns Detailed round information with the following fields:
373
+ * ```typescript
374
+ * {
375
+ * roundId: number; // The queried round ID
376
+ * config: { // Round configuration and current state
377
+ * startTime: number; // Unix timestamp when the round starts
378
+ * endTime: number; // Unix timestamp when the round ends
379
+ * targetFund: number; // Target funding amount in USD (with PRICE_PRECISION)
380
+ * totalAllocation: number;// Total project tokens to be distributed in this round
381
+ * maxFundPerAccount: number; // Maximum USD value one account can contribute
382
+ * exists: boolean; // Whether this round has been created
383
+ * ended: boolean; // Whether this round has been manually ended
384
+ * claimingEnabled: boolean; // Whether participants can claim their tokens
385
+ * refundEnabled: boolean; // Whether refunds are enabled for this round
386
+ * };
387
+ * raisedFunds: number; // Total USD value raised in this round
388
+ * participants: number; // Number of unique participants
389
+ * isActive: boolean; // Whether the round is currently active
390
+ * }
391
+ * ```
392
+ *
393
+ * @example
394
+ * ```typescript
395
+ * const roundInfo = await sdk.getRoundInfo(0);
396
+ *
397
+ * // Check if round is active and accepting contributions
398
+ * if (roundInfo.isActive) {
399
+ * console.log(`Round 0 is active!`);
400
+ * console.log(`Progress: $${roundInfo.raisedFunds}/$${roundInfo.config.targetFund}`);
401
+ * console.log(`Participants: ${roundInfo.participants}`);
402
+ * }
403
+ *
404
+ * // Check if tokens can be claimed
405
+ * if (roundInfo.config.claimingEnabled) {
406
+ * console.log('Token claiming is enabled for this round');
407
+ * }
408
+ * ```
409
+ *
410
+ * @notice
411
+ * - All USD values (targetFund, maxFundPerAccount, raisedFunds) use PRICE_PRECISION (1e18) decimals
412
+ * - totalAllocation is in project token's decimals (e.g., usually 18 decimals)
413
+ * - A round is considered active if:
414
+ * 1. It exists
415
+ * 2. Current time is between startTime and endTime
416
+ * 3. It hasn't been manually ended
417
+ * - Rounds are 0-indexed, so first round has ID 0
418
+ *
419
+ * @throws Will throw an error if:
420
+ * - roundId is negative
421
+ * - roundId is greater than or equal to total number of rounds
422
+ *
423
+ * @see {@link getRound} For getting just the round configuration
424
+ * @see {@link getRoundRaisedFunds} For getting just the raised funds
425
+ * @see {@link getRoundParticipants} For getting just the participant count
107
426
  */
108
427
  getRoundInfo(roundId: number): Promise<{
109
428
  roundId: number;
@@ -127,4 +446,72 @@ export declare class SeedRoundFundraiserSDK {
127
446
  getAllEvents(fromBlock: number, toBlock: number): Promise<ParsedSeedRoundFundraiserEventRaw[]>;
128
447
  streamEvents(fromBlock: number, onEvent: (event: ParsedSeedRoundFundraiserEvent) => Promise<void>, saveLatestBlock: (blockNumber: number) => Promise<void>, batchSize?: number, sleepTime?: number): Promise<void>;
129
448
  formatEventArgs: (event: ParsedSeedRoundFundraiserEventRaw) => ParsedSeedRoundFundraiserEvent;
449
+ /**
450
+ * Gets detailed information about a user's contribution in a specific round
451
+ *
452
+ * @param roundId - The ID of the round to query
453
+ * @param user - The user's address to check contribution
454
+ * @returns Detailed contribution information with the following fields:
455
+ * ```typescript
456
+ * {
457
+ * contribution: {
458
+ * fundAmount: number; // Total USD value of contribution (with PRICE_PRECISION)
459
+ * tokenAllocation: number; // Amount of project tokens allocated
460
+ * claimed: boolean; // Whether allocated tokens have been claimed
461
+ * refunded: boolean; // Whether contribution has been refunded
462
+ * contributedToken: string;// Address of token used for contribution
463
+ * contributedAmount: number;// Actual amount of tokens contributed
464
+ * };
465
+ * roundInfo: {
466
+ * exists: boolean; // Whether the round exists
467
+ * isActive: boolean; // Whether the round is currently active
468
+ * claimingEnabled: boolean;// Whether token claiming is enabled
469
+ * refundEnabled: boolean; // Whether refunds are enabled
470
+ * };
471
+ * tokenInfo?: { // Only present if contribution exists
472
+ * symbol: string; // Symbol of contributed token
473
+ * decimals: number; // Decimals of contributed token
474
+ * };
475
+ * }
476
+ * ```
477
+ *
478
+ * @example
479
+ * ```typescript
480
+ * const userContrib = await sdk.getUserRoundContribution(0, "0x...");
481
+ *
482
+ * if (userContrib.contribution.fundAmount > 0) {
483
+ * console.log(`Contributed: ${userContrib.contribution.contributedAmount} ${userContrib.tokenInfo?.symbol}`);
484
+ * console.log(`Value: $${userContrib.contribution.fundAmount}`);
485
+ * console.log(`Allocated: ${userContrib.contribution.tokenAllocation} tokens`);
486
+ *
487
+ * if (userContrib.roundInfo.claimingEnabled && !userContrib.contribution.claimed) {
488
+ * console.log('Tokens are ready to claim!');
489
+ * }
490
+ * }
491
+ * ```
492
+ *
493
+ * @notice
494
+ * - All USD values use PRICE_PRECISION (1e18) decimals
495
+ * - Token amounts are in their native decimals (e.g., 18 for ETH, 6 for USDC)
496
+ * - For ETH contributions, contributedToken will be the zero address
497
+ * - tokenInfo will be undefined if user hasn't contributed to the round
498
+ *
499
+ * @throws Will throw if:
500
+ * - roundId is invalid
501
+ * - user address is invalid
502
+ * - Contract call fails
503
+ */
504
+ getUserRoundContribution(roundId: number, user: string): Promise<{
505
+ contribution: UserContribution;
506
+ roundInfo: {
507
+ exists: boolean;
508
+ isActive: boolean;
509
+ claimingEnabled: boolean;
510
+ refundEnabled: boolean;
511
+ };
512
+ tokenInfo?: {
513
+ symbol: string;
514
+ decimals: number;
515
+ };
516
+ }>;
130
517
  }
@@ -1 +1 @@
1
- "use strict";var t=this&&this.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(exports,"__esModule",{value:!0}),exports.SeedRoundFundraiserSDK=void 0;const e=require("ethers"),n=t(require("./abis/SeedRoundFundraiser.json")),r=t(require("./contracts.json")),o=require("./utils"),a=t(require("./whitelist-tokens.json"));exports.SeedRoundFundraiserSDK=class{constructor(t,a){this.name="SeedRoundFundraiser",this.isBootstrapped=!1,this.PRICE_PRECISION=1e18,this.whitelistedTokensArray=[],this.formatEventArgs=t=>{const{eventName:e,args:n}=t;switch(e){case"TokenWhitelisted":return{...t,args:{...n,token:n.token.toLowerCase(),price:Number(n.price)/this.PRICE_PRECISION}};case"TokenPriceUpdated":return{...t,args:{...n,token:n.token.toLowerCase(),oldPrice:Number(n.oldPrice)/this.PRICE_PRECISION,newPrice:Number(n.newPrice)/this.PRICE_PRECISION}};case"TokenRemovedFromWhitelist":return{...t,args:{...n,token:n.token.toLowerCase()}};case"RoundCreated":case"RoundUpdated":return{...t,args:{...n,roundId:Number(n.roundId),startTime:Number(n.startTime),endTime:Number(n.endTime),targetFund:Number(n.targetFund)/this.PRICE_PRECISION,totalAllocation:Number(n.totalAllocation),maxFundPerAccount:Number(n.maxFundPerAccount)/this.PRICE_PRECISION}};case"RoundEnded":return{...t,args:{...n,roundId:Number(n.roundId),raisedFunds:Number(n.raisedFunds)/this.PRICE_PRECISION,participants:Number(n.participants)}};case"Contribution":return{...t,args:{...n,roundId:Number(n.roundId),contributor:n.contributor.toLowerCase(),token:n.token.toLowerCase(),amount:Number(n.amount),fundAmount:Number(n.fundAmount)/this.PRICE_PRECISION,tokenAllocation:Number(n.tokenAllocation)}};case"TokensClaimed":return{...t,args:{...n,roundId:Number(n.roundId),user:n.user.toLowerCase(),amount:Number(n.amount)}};case"ProjectTokenUpdated":return{...t,args:{...n,oldToken:n.oldToken.toLowerCase(),newToken:n.newToken.toLowerCase()}};case"ClaimingEnabledUpdated":case"RefundEnabledUpdated":return{...t,args:{...n,roundId:Number(n.roundId),enabled:n.enabled}};case"Refunded":return{...t,args:{...n,roundId:Number(n.roundId),user:n.user.toLowerCase(),token:n.token.toLowerCase(),amount:Number(n.amount)}};default:return t}};const s=Array.isArray(t)?t:[t];this.providers=s.map((t=>new e.ethers.JsonRpcProvider(t)));const i=(0,o.getRandomProvider)(this.providers);this.contractAddress=(0,o.resolveContractAddress)(s[0],this.name,r.default,a),this.contract=new e.ethers.Contract(this.contractAddress,n.default.abi,i),this.networkName=this.getNetworkNameFromRpc(s[0]),this.importWhitelistedTokens()}getNetworkNameFromRpc(t){const e=t.toLowerCase();return e.includes("sepolia.base")?"base-sepolia":e.includes("sepolia")?"sepolia":e.includes("mainnet")?"mainnet":e.includes("localhost")||e.includes("127.0.0.1")?"hardhat":"sepolia"}importWhitelistedTokens(){try{a.default[this.networkName]?(this.whitelistedTokensArray=a.default[this.networkName].map((t=>t.toLowerCase())),console.log(`Imported ${this.whitelistedTokensArray.length} whitelisted tokens for ${this.networkName} network`)):console.log(`No whitelisted tokens found for ${this.networkName} network`)}catch(t){console.error("Error importing whitelisted tokens:",t)}}async getWhitelistedTokenInfo(t){const n=t.toLowerCase();if(!this.whitelistedTokensArray.includes(n))return null;const r=await this.getWhitelistedToken(n);if(!r.isWhitelisted)return null;let a="ETH",s=18;n!==e.ethers.ZeroAddress&&([a,s]=await Promise.all([(0,o.getTokenSymbol)(n,this.getRandomProvider()),(0,o.getTokenDecimals)(n,this.getRandomProvider())]));const i=await this.getLatestRoundId();let d=0;if(i>=0){const t=await this.getRound(i);t.exists&&!t.ended&&(d=t.maxFundPerAccount/r.price)}return{address:n,isWhitelisted:r.isWhitelisted,price:r.price,symbol:a,maxContribution:d,maxContributionRaw:Math.floor(d*Math.pow(10,s)),decimals:s}}async getAllWhitelistedTokensInfo(){const t=[];for(const e of this.whitelistedTokensArray){const n=await this.getWhitelistedTokenInfo(e);n&&t.push(n)}return t}getRandomProvider(){return(0,o.getRandomProvider)(this.providers)}getContractWithRandomProvider(){return new e.ethers.Contract(this.contractAddress,n.default.abi,this.getRandomProvider())}async bootstrap(){if(this.isBootstrapped)return;const t=await Promise.all(this.providers.map(((t,e)=>(0,o.checkRpcHealth)(t,e))));if(this.providers=this.providers.filter(((e,n)=>t[n])),0===this.providers.length)throw new Error("No active RPC providers available");this.isBootstrapped=!0}async signAndSendTransaction(t,e,n={}){return(0,o.signAndSendTransaction)(t,e,(()=>this.getRandomProvider()),n,this.contract)}async buildAddWhitelistedTokenTx(t,e){const n=BigInt(Math.floor(e*this.PRICE_PRECISION));return await this.contract.addWhitelistedToken.populateTransaction(t,n)}async buildUpdateTokenPriceTx(t,e){const n=BigInt(Math.floor(e*this.PRICE_PRECISION));return await this.contract.updateTokenPrice.populateTransaction(t,n)}async buildRemoveWhitelistedTokenTx(t){return await this.contract.removeWhitelistedToken.populateTransaction(t)}async buildCreateRoundTx(t,e,n,r,a){const s=BigInt(Math.floor(n*this.PRICE_PRECISION)),i=BigInt(Math.floor(a*this.PRICE_PRECISION)),d=await(0,o.getTokenDecimals)(await this.getProjectToken(),this.getRandomProvider()),u=BigInt(Math.floor(r*Math.pow(10,d)));return await this.contract.createRound.populateTransaction(t,e,s,u,i)}async buildUpdateRoundTx(t,e,n,r,o,a){const s=BigInt(Math.floor(r*this.PRICE_PRECISION)),i=BigInt(Math.floor(a*this.PRICE_PRECISION));return await this.contract.updateRound.populateTransaction(t,e,n,s,o,i)}async buildEndRoundTx(t){return await this.contract.endRound.populateTransaction(t)}async buildSetClaimingEnabledTx(t,e){return await this.contract.setClaimingEnabled.populateTransaction(t,e)}async buildSetRefundEnabledTx(t,e){return await this.contract.setRefundEnabled.populateTransaction(t,e)}async buildContributeTx(t,n,r){let a=18;n!==e.ethers.ZeroAddress&&(a=await(0,o.getTokenDecimals)(n,this.getRandomProvider()));const s=e.ethers.parseUnits(r.toString(),a),i=await this.contract.contribute.populateTransaction(t,n,n===e.ethers.ZeroAddress?0:s);return n===e.ethers.ZeroAddress&&(i.value=s),i}async buildClaimTokensTx(){return await this.contract.claimTokens.populateTransaction()}async buildRefundTx(){return await this.contract.refund.populateTransaction()}async buildWithdrawFundsTx(t,e){const n=await(0,o.getTokenDecimals)(t,this.getRandomProvider()),r=BigInt(Math.floor(e*Math.pow(10,n)));return await this.contract.withdrawFunds.populateTransaction(t,r)}async buildClaimTokensByRoundIdTx(t){return await this.contract.claimTokensByRoundId.populateTransaction(t)}async getWhitelistedToken(t){const e=await this.contract.whitelistedTokens(t);return{isWhitelisted:e.isWhitelisted,price:Number(e.price)/this.PRICE_PRECISION}}async getRound(t){const e=await this.contract.rounds(t);return{startTime:Number(e.startTime),endTime:Number(e.endTime),targetFund:Number(e.targetFund)/this.PRICE_PRECISION,totalAllocation:Number(e.totalAllocation),maxFundPerAccount:Number(e.maxFundPerAccount)/this.PRICE_PRECISION,exists:e.exists,ended:e.ended,claimingEnabled:e.claimingEnabled,refundEnabled:e.refundEnabled}}async getUserContribution(t,e){const n=await this.contract.userContributions(t,e);return{fundAmount:Number(n.fundAmount)/this.PRICE_PRECISION,tokenAllocation:Number(n.tokenAllocation),claimed:n.claimed,refunded:n.refunded,contributedToken:n.contributedToken,contributedAmount:Number(n.contributedAmount)}}async getRoundRaisedFunds(t){const e=await this.contract.roundRaisedFunds(t);return Number(e)/this.PRICE_PRECISION}async getRoundParticipants(t){const e=await this.contract.roundParticipants(t);return Number(e)}async getUserParticipatedRound(t){const e=await this.contract.userParticipatedRound(t);return Number(e)}async getProjectToken(){return await this.contract.projectToken()}async getTotalRounds(){const t=await this.contract.totalRounds();return Number(t)}async getTotalRaisedFunds(){const t=await this.contract.totalRaisedFunds();return Number(t)/this.PRICE_PRECISION}async isRoundActive(t){return await this.contract.isRoundActive(t)}async getLatestRoundId(){const t=await this.getTotalRounds();return 0===t?-1:t-1}async getRoundInfo(t){const e=await this.getTotalRounds();if(t<0||t>=e)throw new Error(`Invalid round ID: ${t}`);return{roundId:t,config:await this.getRound(t),raisedFunds:await this.getRoundRaisedFunds(t),participants:await this.getRoundParticipants(t),isActive:await this.isRoundActive(t)}}async getUserTotalContribution(t){const e=await this.contract.getUserTotalContribution(t);return{totalFundAmount:Number(e.totalFundAmount)/this.PRICE_PRECISION,totalTokenAllocation:Number(e.totalTokenAllocation)}}async getTransactionStatus(t,e=10){return await(0,o.getTransactionStatus)(this.getRandomProvider(),t,e)}getContractAddress(){return this.contractAddress}async getAllEvents(t,e){return await this.bootstrap(),(0,o.getAllEvents)(this.contract,(()=>this.getRandomProvider()),(()=>this.getContractWithRandomProvider()),t,e)}async streamEvents(t,e,n,r=1e3,a=5e3){return await this.bootstrap(),(0,o.streamEvents)({getProvider:()=>this.getRandomProvider(),getAllEvents:(t,e)=>this.getAllEvents(t,e),formatEvent:t=>this.formatEventArgs(t),onEvent:e,saveLatestBlock:n,fromBlock:t,batchSize:r,sleepTime:a})}};
1
+ "use strict";var t=this&&this.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(exports,"__esModule",{value:!0}),exports.SeedRoundFundraiserSDK=void 0;const e=require("ethers"),n=t(require("./abis/SeedRoundFundraiser.json")),r=t(require("./contracts.json")),o=require("./utils"),a=t(require("./whitelist-tokens.json"));exports.SeedRoundFundraiserSDK=class{constructor(t,a){this.name="SeedRoundFundraiser",this.isBootstrapped=!1,this.PRICE_PRECISION=1e18,this.whitelistedTokensArray=[],this.formatEventArgs=t=>{const{eventName:e,args:n}=t;switch(e){case"TokenWhitelisted":return{...t,args:{...n,token:n.token.toLowerCase(),price:Number(n.price)/this.PRICE_PRECISION}};case"TokenPriceUpdated":return{...t,args:{...n,token:n.token.toLowerCase(),oldPrice:Number(n.oldPrice)/this.PRICE_PRECISION,newPrice:Number(n.newPrice)/this.PRICE_PRECISION}};case"TokenRemovedFromWhitelist":return{...t,args:{...n,token:n.token.toLowerCase()}};case"RoundCreated":case"RoundUpdated":return{...t,args:{...n,roundId:Number(n.roundId),startTime:Number(n.startTime),endTime:Number(n.endTime),targetFund:Number(n.targetFund)/this.PRICE_PRECISION,totalAllocation:Number(n.totalAllocation),maxFundPerAccount:Number(n.maxFundPerAccount)/this.PRICE_PRECISION}};case"RoundEnded":return{...t,args:{...n,roundId:Number(n.roundId),raisedFunds:Number(n.raisedFunds)/this.PRICE_PRECISION,participants:Number(n.participants)}};case"Contribution":return{...t,args:{...n,roundId:Number(n.roundId),contributor:n.contributor.toLowerCase(),token:n.token.toLowerCase(),amount:Number(n.amount),fundAmount:Number(n.fundAmount)/this.PRICE_PRECISION,tokenAllocation:Number(n.tokenAllocation)}};case"TokensClaimed":return{...t,args:{...n,roundId:Number(n.roundId),user:n.user.toLowerCase(),amount:Number(n.amount)}};case"ProjectTokenUpdated":return{...t,args:{...n,oldToken:n.oldToken.toLowerCase(),newToken:n.newToken.toLowerCase()}};case"ClaimingEnabledUpdated":case"RefundEnabledUpdated":return{...t,args:{...n,roundId:Number(n.roundId),enabled:n.enabled}};case"Refunded":return{...t,args:{...n,roundId:Number(n.roundId),user:n.user.toLowerCase(),token:n.token.toLowerCase(),amount:Number(n.amount)}};default:return t}};const i=Array.isArray(t)?t:[t];this.providers=i.map((t=>new e.ethers.JsonRpcProvider(t)));const s=(0,o.getRandomProvider)(this.providers);this.contractAddress=(0,o.resolveContractAddress)(i[0],this.name,r.default,a),this.contract=new e.ethers.Contract(this.contractAddress,n.default.abi,s),this.networkName=this.getNetworkNameFromRpc(i[0]),this.importWhitelistedTokens()}getNetworkNameFromRpc(t){const e=t.toLowerCase();return e.includes("sepolia.base")?"base-sepolia":e.includes("sepolia")?"sepolia":e.includes("mainnet")?"mainnet":e.includes("localhost")||e.includes("127.0.0.1")?"hardhat":"sepolia"}importWhitelistedTokens(){try{a.default[this.networkName]?(this.whitelistedTokensArray=a.default[this.networkName].map((t=>t.toLowerCase())),console.log(`Imported ${this.whitelistedTokensArray.length} whitelisted tokens for ${this.networkName} network`)):console.log(`No whitelisted tokens found for ${this.networkName} network`)}catch(t){console.error("Error importing whitelisted tokens:",t)}}async getWhitelistedTokenInfo(t){const n=t.toLowerCase();if(!this.whitelistedTokensArray.includes(n))return null;const r=await this.getWhitelistedToken(n);if(!r.isWhitelisted)return null;let a="ETH",i=18;n!==e.ethers.ZeroAddress&&([a,i]=await Promise.all([(0,o.getTokenSymbol)(n,this.getRandomProvider()),(0,o.getTokenDecimals)(n,this.getRandomProvider())]));const s=await this.getLatestRoundId();let d=0;if(s>=0){const t=await this.getRound(s);t.exists&&!t.ended&&(d=t.maxFundPerAccount/r.price)}return{address:n,isWhitelisted:r.isWhitelisted,price:r.price,symbol:a,maxContribution:d,maxContributionRaw:Math.floor(d*Math.pow(10,i)),decimals:i}}async getAllWhitelistedTokensInfo(){const t=[];for(const e of this.whitelistedTokensArray){const n=await this.getWhitelistedTokenInfo(e);n&&t.push(n)}return t}getRandomProvider(){return(0,o.getRandomProvider)(this.providers)}getContractWithRandomProvider(){return new e.ethers.Contract(this.contractAddress,n.default.abi,this.getRandomProvider())}async bootstrap(){if(this.isBootstrapped)return;const t=await Promise.all(this.providers.map(((t,e)=>(0,o.checkRpcHealth)(t,e))));if(this.providers=this.providers.filter(((e,n)=>t[n])),0===this.providers.length)throw new Error("No active RPC providers available");this.isBootstrapped=!0}async signAndSendTransaction(t,e,n={}){return(0,o.signAndSendTransaction)(t,e,(()=>this.getRandomProvider()),n,this.contract)}async buildAddWhitelistedTokenTx(t,e){const n=BigInt(Math.floor(e*this.PRICE_PRECISION));return await this.contract.addWhitelistedToken.populateTransaction(t,n)}async buildUpdateTokenPriceTx(t,e){const n=BigInt(Math.floor(e*this.PRICE_PRECISION));return await this.contract.updateTokenPrice.populateTransaction(t,n)}async buildRemoveWhitelistedTokenTx(t){return await this.contract.removeWhitelistedToken.populateTransaction(t)}async buildCreateRoundTx(t,e,n,r,a){const i=BigInt(Math.floor(n*this.PRICE_PRECISION)),s=BigInt(Math.floor(a*this.PRICE_PRECISION)),d=await(0,o.getTokenDecimals)(await this.getProjectToken(),this.getRandomProvider()),u=BigInt(Math.floor(r*Math.pow(10,d)));return await this.contract.createRound.populateTransaction(t,e,i,u,s)}async buildUpdateRoundTx(t,e,n,r,o,a){const i=BigInt(Math.floor(r*this.PRICE_PRECISION)),s=BigInt(Math.floor(a*this.PRICE_PRECISION));return await this.contract.updateRound.populateTransaction(t,e,n,i,o,s)}async buildEndRoundTx(t){return await this.contract.endRound.populateTransaction(t)}async buildSetClaimingEnabledTx(t,e){return await this.contract.setClaimingEnabled.populateTransaction(t,e)}async buildSetRefundEnabledTx(t,e){return await this.contract.setRefundEnabled.populateTransaction(t,e)}async buildContributeTx(t,n,r){let a=18;n!==e.ethers.ZeroAddress&&(a=await(0,o.getTokenDecimals)(n,this.getRandomProvider()));const i=e.ethers.parseUnits(r.toString(),a),s=await this.contract.contribute.populateTransaction(t,n,n===e.ethers.ZeroAddress?0:i);return n===e.ethers.ZeroAddress&&(s.value=i),s}async buildClaimTokensTx(){return await this.contract.claimTokens.populateTransaction()}async buildRefundTx(){return await this.contract.refund.populateTransaction()}async buildWithdrawFundsTx(t,e){const n=await(0,o.getTokenDecimals)(t,this.getRandomProvider()),r=BigInt(Math.floor(e*Math.pow(10,n)));return await this.contract.withdrawFunds.populateTransaction(t,r)}async buildClaimTokensByRoundIdTx(t){return await this.contract.claimTokensByRoundId.populateTransaction(t)}async getWhitelistedToken(t){const e=await this.contract.whitelistedTokens(t);return{isWhitelisted:e.isWhitelisted,price:Number(e.price)/this.PRICE_PRECISION}}async getRound(t){const e=await this.contract.rounds(t);return{startTime:Number(e.startTime),endTime:Number(e.endTime),targetFund:Number(e.targetFund)/this.PRICE_PRECISION,totalAllocation:Number(e.totalAllocation),maxFundPerAccount:Number(e.maxFundPerAccount)/this.PRICE_PRECISION,exists:e.exists,ended:e.ended,claimingEnabled:e.claimingEnabled,refundEnabled:e.refundEnabled}}async getUserContribution(t,e){const n=await this.contract.userContributions(t,e);return{fundAmount:Number(n.fundAmount)/this.PRICE_PRECISION,tokenAllocation:Number(n.tokenAllocation),claimed:n.claimed,refunded:n.refunded,contributedToken:n.contributedToken,contributedAmount:Number(n.contributedAmount)}}async getRoundRaisedFunds(t){const e=await this.contract.roundRaisedFunds(t);return Number(e)/this.PRICE_PRECISION}async getRoundParticipants(t){const e=await this.contract.roundParticipants(t);return Number(e)}async getUserParticipatedRound(t){const e=await this.contract.userParticipatedRound(t);return Number(e)}async getProjectToken(){return await this.contract.projectToken()}async getTotalRounds(){const t=await this.contract.totalRounds();return Number(t)}async getTotalRaisedFunds(){const t=await this.contract.totalRaisedFunds();return Number(t)/this.PRICE_PRECISION}async isRoundActive(t){return await this.contract.isRoundActive(t)}async getLatestRoundId(){const t=await this.getTotalRounds();return 0===t?-1:t-1}async getRoundInfo(t){const e=await this.getTotalRounds();if(t<0||t>=e)throw new Error(`Invalid round ID: ${t}`);return{roundId:t,config:await this.getRound(t),raisedFunds:await this.getRoundRaisedFunds(t),participants:await this.getRoundParticipants(t),isActive:await this.isRoundActive(t)}}async getUserTotalContribution(t){const e=await this.contract.getUserTotalContribution(t);return{totalFundAmount:Number(e.totalFundAmount)/this.PRICE_PRECISION,totalTokenAllocation:Number(e.totalTokenAllocation)}}async getTransactionStatus(t,e=10){return await(0,o.getTransactionStatus)(this.getRandomProvider(),t,e)}getContractAddress(){return this.contractAddress}async getAllEvents(t,e){return await this.bootstrap(),(0,o.getAllEvents)(this.contract,(()=>this.getRandomProvider()),(()=>this.getContractWithRandomProvider()),t,e)}async streamEvents(t,e,n,r=1e3,a=5e3){return await this.bootstrap(),(0,o.streamEvents)({getProvider:()=>this.getRandomProvider(),getAllEvents:(t,e)=>this.getAllEvents(t,e),formatEvent:t=>this.formatEventArgs(t),onEvent:e,saveLatestBlock:n,fromBlock:t,batchSize:r,sleepTime:a})}async getUserRoundContribution(t,n){const[r,a]=await Promise.all([this.contract.getUserRoundContribution(t,n),this.contract.rounds(t)]),i={fundAmount:Number(r.fundAmount)/this.PRICE_PRECISION,tokenAllocation:Number(r.tokenAllocation),claimed:r.claimed,refunded:r.refunded,contributedToken:r.contributedToken,contributedAmount:Number(r.contributedAmount)},s=Math.floor(Date.now()/1e3),d=a.exists&&!a.ended&&s>=Number(a.startTime)&&s<=Number(a.endTime),u={contribution:i,roundInfo:{exists:a.exists,isActive:d,claimingEnabled:a.claimingEnabled,refundEnabled:a.refundEnabled}};if(i.fundAmount>0){const t=i.contributedToken;let n="ETH",r=18;return t!==e.ethers.ZeroAddress&&([n,r]=await Promise.all([(0,o.getTokenSymbol)(t,this.getRandomProvider()),(0,o.getTokenDecimals)(t,this.getRandomProvider())])),{...u,tokenInfo:{symbol:n,decimals:r}}}return u}};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aiia-vault-sdk",
3
- "version": "1.1.0",
3
+ "version": "1.1.1",
4
4
  "description": "SDK for AIIA Vault Contract",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",