@mania-labs/mania-sdk 1.0.0

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/index.js ADDED
@@ -0,0 +1,1220 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ BPS_DENOMINATOR: () => BPS_DENOMINATOR,
24
+ BondingCurve: () => BondingCurve,
25
+ CHAIN_CONFIGS: () => CHAIN_CONFIGS,
26
+ CREATOR_FEE_BASIS_POINTS: () => CREATOR_FEE_BASIS_POINTS,
27
+ DEFAULT_SLIPPAGE_BPS: () => DEFAULT_SLIPPAGE_BPS,
28
+ ERC20_ABI: () => ERC20_ABI,
29
+ MANIA_FACTORY_ABI: () => MANIA_FACTORY_ABI,
30
+ MAX_FEE_BASIS_POINTS: () => MAX_FEE_BASIS_POINTS,
31
+ MAX_MIGRATE_FEES: () => MAX_MIGRATE_FEES,
32
+ MIGRATION_THRESHOLD: () => MIGRATION_THRESHOLD,
33
+ ManiaSDK: () => ManiaSDK,
34
+ PROTOCOL_FEE_BASIS_POINTS: () => PROTOCOL_FEE_BASIS_POINTS,
35
+ TICK_LOWER: () => TICK_LOWER,
36
+ TICK_UPPER: () => TICK_UPPER,
37
+ TOKENS_FOR_LP: () => TOKENS_FOR_LP,
38
+ TOTAL_FEE_BASIS_POINTS: () => TOTAL_FEE_BASIS_POINTS,
39
+ UNISWAP_FEE_TIER: () => UNISWAP_FEE_TIER,
40
+ bpsToPercent: () => bpsToPercent,
41
+ calculateBuyAmount: () => calculateBuyAmount,
42
+ calculateMigrationProgress: () => calculateMigrationProgress,
43
+ calculatePriceImpact: () => calculatePriceImpact,
44
+ calculateSellAmount: () => calculateSellAmount,
45
+ calculateWithSlippage: () => calculateWithSlippage,
46
+ formatEthValue: () => formatEthValue,
47
+ formatMarketCap: () => formatMarketCap,
48
+ formatPrice: () => formatPrice,
49
+ formatTokenAmount: () => formatTokenAmount,
50
+ getChainConfig: () => getChainConfig,
51
+ isValidAddress: () => isValidAddress,
52
+ parseEthValue: () => parseEthValue,
53
+ percentToBps: () => percentToBps,
54
+ sleep: () => sleep,
55
+ truncateAddress: () => truncateAddress,
56
+ withRetry: () => withRetry
57
+ });
58
+ module.exports = __toCommonJS(index_exports);
59
+
60
+ // src/mania.ts
61
+ var import_viem = require("viem");
62
+ var import_accounts = require("viem/accounts");
63
+
64
+ // src/constants.ts
65
+ var PROTOCOL_FEE_BASIS_POINTS = 70n;
66
+ var CREATOR_FEE_BASIS_POINTS = 30n;
67
+ var TOTAL_FEE_BASIS_POINTS = PROTOCOL_FEE_BASIS_POINTS + CREATOR_FEE_BASIS_POINTS;
68
+ var MAX_FEE_BASIS_POINTS = 1000n;
69
+ var MIGRATION_THRESHOLD = 4000000000000000000n;
70
+ var TOKENS_FOR_LP = 206900000000000000000000000n;
71
+ var MAX_MIGRATE_FEES = 300000000000000n;
72
+ var UNISWAP_FEE_TIER = 3e3;
73
+ var TICK_LOWER = -887220;
74
+ var TICK_UPPER = 887220;
75
+ var DEFAULT_SLIPPAGE_BPS = 100;
76
+ var BPS_DENOMINATOR = 10000n;
77
+ var CHAIN_CONFIGS = {
78
+ // Mega Eth Testnet
79
+ 6543: {
80
+ chainId: 6543,
81
+ name: "Mega Eth Testnet",
82
+ factoryAddress: "0x0d593cE47EBA2d15a77ddbAc41BdE6d03CC9241b",
83
+ wethAddress: "0x4200000000000000000000000000000000000006",
84
+ nonfungiblePositionManager: "0xa204A97EF8Bd2E3198f19EB5a804680467BD85f5",
85
+ uniswapV3Factory: "0x619fb6C12c36b57a8bAb05e98F42C43745DCf69f",
86
+ blockExplorer: "https://megaeth-testnet-v2.blockscout.com"
87
+ }
88
+ };
89
+ function getChainConfig(chainId) {
90
+ return CHAIN_CONFIGS[chainId];
91
+ }
92
+
93
+ // src/bondingCurve.ts
94
+ var BondingCurve = class _BondingCurve {
95
+ state;
96
+ feeBasisPoints;
97
+ constructor(state, feeBasisPoints) {
98
+ this.state = state;
99
+ this.feeBasisPoints = feeBasisPoints;
100
+ }
101
+ /**
102
+ * Get the current bonding curve state
103
+ */
104
+ getState() {
105
+ return { ...this.state };
106
+ }
107
+ /**
108
+ * Check if the bonding curve is complete (reached migration threshold)
109
+ */
110
+ isComplete() {
111
+ return this.state.complete;
112
+ }
113
+ /**
114
+ * Check if the bonding curve has been migrated (all reserves are 0)
115
+ */
116
+ isMigrated() {
117
+ return this.state.realEthReserves === 0n && this.state.virtualEthReserves === 0n && this.state.realTokenReserves === 0n && this.state.virtualTokenReserves === 0n;
118
+ }
119
+ /**
120
+ * Get the current token price in ETH (wei per token)
121
+ *
122
+ * Price is calculated as: virtualEthReserves / virtualTokenReserves
123
+ */
124
+ getCurrentPrice() {
125
+ if (this.state.virtualTokenReserves === 0n) {
126
+ return 0n;
127
+ }
128
+ return this.state.virtualEthReserves * 10n ** 18n / this.state.virtualTokenReserves;
129
+ }
130
+ /**
131
+ * Get the market cap in ETH
132
+ *
133
+ * Market cap = current price * total supply
134
+ */
135
+ getMarketCapEth() {
136
+ const price = this.getCurrentPrice();
137
+ return price * this.state.tokenTotalSupply / 10n ** 18n;
138
+ }
139
+ /**
140
+ * Get the progress towards migration threshold (0-100)
141
+ */
142
+ getMigrationProgress() {
143
+ if (this.state.complete) {
144
+ return 100;
145
+ }
146
+ const progress = this.state.realEthReserves * 100n / MIGRATION_THRESHOLD;
147
+ return Number(progress);
148
+ }
149
+ /**
150
+ * Calculate ETH remaining until migration
151
+ */
152
+ getEthUntilMigration() {
153
+ if (this.state.realEthReserves >= MIGRATION_THRESHOLD) {
154
+ return 0n;
155
+ }
156
+ return MIGRATION_THRESHOLD - this.state.realEthReserves;
157
+ }
158
+ /**
159
+ * Get a quote for buying tokens with a specific ETH amount
160
+ *
161
+ * @param ethAmount - Amount of ETH to spend (in wei)
162
+ * @returns Quote with tokens out, fees, and price impact
163
+ */
164
+ getBuyQuote(ethAmount) {
165
+ const fee = ethAmount * this.feeBasisPoints / BPS_DENOMINATOR;
166
+ const netEth = ethAmount - fee;
167
+ const tokensOut = this.state.virtualTokenReserves * netEth / (this.state.virtualEthReserves + netEth);
168
+ const cappedTokensOut = tokensOut > this.state.realTokenReserves ? this.state.realTokenReserves : tokensOut;
169
+ const pricePerToken = cappedTokensOut > 0n ? netEth * 10n ** 18n / cappedTokensOut : 0n;
170
+ return {
171
+ tokensOut: cappedTokensOut,
172
+ fee,
173
+ netEth,
174
+ pricePerToken
175
+ };
176
+ }
177
+ /**
178
+ * Get a quote for selling tokens
179
+ *
180
+ * @param tokenAmount - Amount of tokens to sell
181
+ * @returns Quote with ETH out, fees, and price impact
182
+ */
183
+ getSellQuote(tokenAmount) {
184
+ const ethOutGross = tokenAmount * this.state.virtualEthReserves / (this.state.virtualTokenReserves + tokenAmount);
185
+ const fee = ethOutGross * this.feeBasisPoints / BPS_DENOMINATOR;
186
+ const ethOutNet = ethOutGross - fee;
187
+ const pricePerToken = tokenAmount > 0n ? ethOutNet * 10n ** 18n / tokenAmount : 0n;
188
+ return {
189
+ ethOutGross,
190
+ fee,
191
+ ethOutNet,
192
+ pricePerToken
193
+ };
194
+ }
195
+ /**
196
+ * Calculate minimum tokens out with slippage tolerance
197
+ *
198
+ * @param ethAmount - Amount of ETH to spend
199
+ * @param slippageBps - Slippage tolerance in basis points (e.g., 100 = 1%)
200
+ * @returns Minimum tokens to receive
201
+ */
202
+ calculateMinTokensOut(ethAmount, slippageBps) {
203
+ const quote = this.getBuyQuote(ethAmount);
204
+ const slippageMultiplier = BPS_DENOMINATOR - BigInt(slippageBps);
205
+ return quote.tokensOut * slippageMultiplier / BPS_DENOMINATOR;
206
+ }
207
+ /**
208
+ * Calculate minimum ETH out with slippage tolerance
209
+ *
210
+ * @param tokenAmount - Amount of tokens to sell
211
+ * @param slippageBps - Slippage tolerance in basis points (e.g., 100 = 1%)
212
+ * @returns Minimum ETH to receive
213
+ */
214
+ calculateMinEthOut(tokenAmount, slippageBps) {
215
+ const quote = this.getSellQuote(tokenAmount);
216
+ const slippageMultiplier = BPS_DENOMINATOR - BigInt(slippageBps);
217
+ return quote.ethOutNet * slippageMultiplier / BPS_DENOMINATOR;
218
+ }
219
+ /**
220
+ * Calculate price impact for a buy order
221
+ *
222
+ * @param ethAmount - Amount of ETH to spend
223
+ * @returns Price impact as a percentage (e.g., 2.5 = 2.5%)
224
+ */
225
+ calculateBuyPriceImpact(ethAmount) {
226
+ const currentPrice = this.getCurrentPrice();
227
+ if (currentPrice === 0n) return 0;
228
+ const quote = this.getBuyQuote(ethAmount);
229
+ if (quote.tokensOut === 0n) return 0;
230
+ const newVirtualEth = this.state.virtualEthReserves + quote.netEth;
231
+ const newVirtualTokens = this.state.virtualTokenReserves - quote.tokensOut;
232
+ const newPrice = newVirtualEth * 10n ** 18n / newVirtualTokens;
233
+ const impact = Number((newPrice - currentPrice) * 10000n / currentPrice) / 100;
234
+ return impact;
235
+ }
236
+ /**
237
+ * Calculate price impact for a sell order
238
+ *
239
+ * @param tokenAmount - Amount of tokens to sell
240
+ * @returns Price impact as a percentage (negative for sells)
241
+ */
242
+ calculateSellPriceImpact(tokenAmount) {
243
+ const currentPrice = this.getCurrentPrice();
244
+ if (currentPrice === 0n) return 0;
245
+ const quote = this.getSellQuote(tokenAmount);
246
+ const newVirtualEth = this.state.virtualEthReserves - quote.ethOutGross;
247
+ const newVirtualTokens = this.state.virtualTokenReserves + tokenAmount;
248
+ if (newVirtualTokens === 0n) return -100;
249
+ const newPrice = newVirtualEth * 10n ** 18n / newVirtualTokens;
250
+ const impact = Number((newPrice - currentPrice) * 10000n / currentPrice) / 100;
251
+ return impact;
252
+ }
253
+ /**
254
+ * Check if a buy would exceed the migration threshold
255
+ *
256
+ * @param ethAmount - Amount of ETH to spend
257
+ * @returns True if the buy would exceed threshold
258
+ */
259
+ wouldExceedMigrationThreshold(ethAmount) {
260
+ const fee = ethAmount * this.feeBasisPoints / BPS_DENOMINATOR;
261
+ const netEth = ethAmount - fee;
262
+ return this.state.realEthReserves + netEth > MIGRATION_THRESHOLD;
263
+ }
264
+ /**
265
+ * Calculate maximum ETH that can be spent before hitting migration threshold
266
+ *
267
+ * @returns Maximum ETH amount (in wei)
268
+ */
269
+ getMaxBuyAmount() {
270
+ if (this.state.complete) {
271
+ return 0n;
272
+ }
273
+ const remainingEth = MIGRATION_THRESHOLD - this.state.realEthReserves;
274
+ const maxEthWithFees = remainingEth * BPS_DENOMINATOR / (BPS_DENOMINATOR - this.feeBasisPoints);
275
+ return maxEthWithFees;
276
+ }
277
+ /**
278
+ * Update the internal state (used after trades)
279
+ */
280
+ updateState(newState) {
281
+ this.state = { ...newState };
282
+ }
283
+ /**
284
+ * Create a BondingCurve instance from raw contract data
285
+ */
286
+ static fromContractData(data, feeBasisPoints) {
287
+ const state = {
288
+ virtualTokenReserves: data[0],
289
+ virtualEthReserves: data[1],
290
+ realTokenReserves: data[2],
291
+ realEthReserves: data[3],
292
+ tokenTotalSupply: data[4],
293
+ complete: data[5],
294
+ trackVolume: data[6]
295
+ };
296
+ return new _BondingCurve(state, feeBasisPoints);
297
+ }
298
+ };
299
+ function calculateBuyAmount(virtualTokenReserves, virtualEthReserves, ethAmount, feeBasisPoints) {
300
+ const fee = ethAmount * feeBasisPoints / BPS_DENOMINATOR;
301
+ const netEth = ethAmount - fee;
302
+ return virtualTokenReserves * netEth / (virtualEthReserves + netEth);
303
+ }
304
+ function calculateSellAmount(virtualTokenReserves, virtualEthReserves, tokenAmount, feeBasisPoints) {
305
+ const ethOutGross = tokenAmount * virtualEthReserves / (virtualTokenReserves + tokenAmount);
306
+ const fee = ethOutGross * feeBasisPoints / BPS_DENOMINATOR;
307
+ return ethOutGross - fee;
308
+ }
309
+
310
+ // src/abi.ts
311
+ var MANIA_FACTORY_ABI = [
312
+ {
313
+ type: "function",
314
+ name: "bondingCurves",
315
+ inputs: [{ name: "mint", type: "address" }],
316
+ outputs: [
317
+ { name: "virtualTokenReserves", type: "uint256" },
318
+ { name: "virtualEthReserves", type: "uint64" },
319
+ { name: "realTokenReserves", type: "uint256" },
320
+ { name: "realEthReserves", type: "uint64" },
321
+ { name: "tokenTotalSupply", type: "uint256" },
322
+ { name: "complete", type: "bool" },
323
+ { name: "trackVolume", type: "bool" }
324
+ ],
325
+ stateMutability: "view"
326
+ },
327
+ {
328
+ type: "function",
329
+ name: "buy",
330
+ inputs: [
331
+ { name: "token", type: "address" },
332
+ { name: "minTokensOut", type: "uint256" },
333
+ { name: "recipient", type: "address" }
334
+ ],
335
+ outputs: [],
336
+ stateMutability: "payable"
337
+ },
338
+ {
339
+ type: "function",
340
+ name: "create",
341
+ inputs: [
342
+ { name: "name", type: "string" },
343
+ { name: "symbol", type: "string" },
344
+ { name: "uri", type: "string" },
345
+ { name: "creator", type: "address" }
346
+ ],
347
+ outputs: [{ name: "token", type: "address" }],
348
+ stateMutability: "nonpayable"
349
+ },
350
+ {
351
+ type: "function",
352
+ name: "createAndBuy",
353
+ inputs: [
354
+ { name: "name", type: "string" },
355
+ { name: "symbol", type: "string" },
356
+ { name: "uri", type: "string" },
357
+ { name: "creator", type: "address" },
358
+ { name: "minTokensOut", type: "uint256" }
359
+ ],
360
+ outputs: [{ name: "token", type: "address" }],
361
+ stateMutability: "payable"
362
+ },
363
+ {
364
+ type: "function",
365
+ name: "getBondingCurve",
366
+ inputs: [{ name: "token", type: "address" }],
367
+ outputs: [
368
+ {
369
+ name: "curve",
370
+ type: "tuple",
371
+ components: [
372
+ { name: "virtualTokenReserves", type: "uint256" },
373
+ { name: "virtualEthReserves", type: "uint64" },
374
+ { name: "realTokenReserves", type: "uint256" },
375
+ { name: "realEthReserves", type: "uint64" },
376
+ { name: "tokenTotalSupply", type: "uint256" },
377
+ { name: "complete", type: "bool" },
378
+ { name: "trackVolume", type: "bool" }
379
+ ]
380
+ }
381
+ ],
382
+ stateMutability: "view"
383
+ },
384
+ {
385
+ type: "function",
386
+ name: "getBuyQuote",
387
+ inputs: [
388
+ { name: "token", type: "address" },
389
+ { name: "ethAmount", type: "uint64" }
390
+ ],
391
+ outputs: [{ name: "tokenAmount", type: "uint256" }],
392
+ stateMutability: "view"
393
+ },
394
+ {
395
+ type: "function",
396
+ name: "getFee",
397
+ inputs: [{ name: "amount", type: "uint64" }],
398
+ outputs: [{ name: "fee", type: "uint128" }],
399
+ stateMutability: "view"
400
+ },
401
+ {
402
+ type: "function",
403
+ name: "getSellQuote",
404
+ inputs: [
405
+ { name: "token", type: "address" },
406
+ { name: "amount", type: "uint256" }
407
+ ],
408
+ outputs: [{ name: "ethOutput", type: "uint128" }],
409
+ stateMutability: "view"
410
+ },
411
+ {
412
+ type: "function",
413
+ name: "global",
414
+ inputs: [],
415
+ outputs: [
416
+ { name: "initialized", type: "bool" },
417
+ { name: "authority", type: "address" },
418
+ { name: "feeRecipient", type: "address" },
419
+ { name: "initialVirtualTokenReserves", type: "uint256" },
420
+ { name: "initialVirtualEthReserves", type: "uint64" },
421
+ { name: "initialRealTokenReserves", type: "uint256" },
422
+ { name: "tokenTotalSupply", type: "uint256" },
423
+ { name: "feeBasisPoints", type: "uint64" },
424
+ { name: "withdrawAuthority", type: "address" },
425
+ { name: "enableMigrate", type: "bool" },
426
+ { name: "poolMigrationFee", type: "uint64" }
427
+ ],
428
+ stateMutability: "view"
429
+ },
430
+ {
431
+ type: "function",
432
+ name: "migrate",
433
+ inputs: [{ name: "token", type: "address" }],
434
+ outputs: [],
435
+ stateMutability: "payable"
436
+ },
437
+ {
438
+ type: "function",
439
+ name: "sell",
440
+ inputs: [
441
+ { name: "token", type: "address" },
442
+ { name: "amount", type: "uint256" },
443
+ { name: "minEthOutput", type: "uint64" }
444
+ ],
445
+ outputs: [],
446
+ stateMutability: "nonpayable"
447
+ },
448
+ {
449
+ type: "function",
450
+ name: "userVolume",
451
+ inputs: [{ name: "user", type: "address" }],
452
+ outputs: [{ name: "volume", type: "uint256" }],
453
+ stateMutability: "view"
454
+ },
455
+ {
456
+ type: "event",
457
+ name: "CreateEvent",
458
+ inputs: [
459
+ { name: "name", type: "string", indexed: false },
460
+ { name: "symbol", type: "string", indexed: false },
461
+ { name: "uri", type: "string", indexed: false },
462
+ { name: "mint", type: "address", indexed: true },
463
+ { name: "user", type: "address", indexed: true },
464
+ { name: "creator", type: "address", indexed: true },
465
+ { name: "timestamp", type: "uint256", indexed: false }
466
+ ],
467
+ anonymous: false
468
+ },
469
+ {
470
+ type: "event",
471
+ name: "TradeEvent",
472
+ inputs: [
473
+ { name: "mint", type: "address", indexed: true },
474
+ { name: "ethAmount", type: "uint64", indexed: false },
475
+ { name: "tokenAmount", type: "uint256", indexed: false },
476
+ { name: "isBuy", type: "bool", indexed: false },
477
+ { name: "user", type: "address", indexed: true },
478
+ { name: "timestamp", type: "uint256", indexed: false },
479
+ { name: "virtualEthReserves", type: "uint64", indexed: false },
480
+ { name: "virtualTokenReserves", type: "uint256", indexed: false },
481
+ { name: "realEthReserves", type: "uint64", indexed: false },
482
+ { name: "realTokenReserves", type: "uint256", indexed: false }
483
+ ],
484
+ anonymous: false
485
+ },
486
+ {
487
+ type: "event",
488
+ name: "CompleteEvent",
489
+ inputs: [
490
+ { name: "user", type: "address", indexed: true },
491
+ { name: "mint", type: "address", indexed: true },
492
+ { name: "timestamp", type: "uint256", indexed: false }
493
+ ],
494
+ anonymous: false
495
+ },
496
+ {
497
+ type: "event",
498
+ name: "CompleteManiaAmmMigrationEvent",
499
+ inputs: [
500
+ { name: "user", type: "address", indexed: true },
501
+ { name: "mint", type: "address", indexed: true },
502
+ { name: "mintAmount", type: "uint256", indexed: false },
503
+ { name: "ethAmount", type: "uint64", indexed: false },
504
+ { name: "poolMigrationFee", type: "uint64", indexed: false },
505
+ { name: "timestamp", type: "uint256", indexed: false },
506
+ { name: "pool", type: "address", indexed: true }
507
+ ],
508
+ anonymous: false
509
+ }
510
+ ];
511
+ var ERC20_ABI = [
512
+ {
513
+ type: "function",
514
+ name: "name",
515
+ inputs: [],
516
+ outputs: [{ type: "string" }],
517
+ stateMutability: "view"
518
+ },
519
+ {
520
+ type: "function",
521
+ name: "symbol",
522
+ inputs: [],
523
+ outputs: [{ type: "string" }],
524
+ stateMutability: "view"
525
+ },
526
+ {
527
+ type: "function",
528
+ name: "decimals",
529
+ inputs: [],
530
+ outputs: [{ type: "uint8" }],
531
+ stateMutability: "view"
532
+ },
533
+ {
534
+ type: "function",
535
+ name: "totalSupply",
536
+ inputs: [],
537
+ outputs: [{ type: "uint256" }],
538
+ stateMutability: "view"
539
+ },
540
+ {
541
+ type: "function",
542
+ name: "balanceOf",
543
+ inputs: [{ name: "account", type: "address" }],
544
+ outputs: [{ type: "uint256" }],
545
+ stateMutability: "view"
546
+ },
547
+ {
548
+ type: "function",
549
+ name: "allowance",
550
+ inputs: [
551
+ { name: "owner", type: "address" },
552
+ { name: "spender", type: "address" }
553
+ ],
554
+ outputs: [{ type: "uint256" }],
555
+ stateMutability: "view"
556
+ },
557
+ {
558
+ type: "function",
559
+ name: "approve",
560
+ inputs: [
561
+ { name: "spender", type: "address" },
562
+ { name: "amount", type: "uint256" }
563
+ ],
564
+ outputs: [{ type: "bool" }],
565
+ stateMutability: "nonpayable"
566
+ },
567
+ {
568
+ type: "function",
569
+ name: "transfer",
570
+ inputs: [
571
+ { name: "to", type: "address" },
572
+ { name: "amount", type: "uint256" }
573
+ ],
574
+ outputs: [{ type: "bool" }],
575
+ stateMutability: "nonpayable"
576
+ }
577
+ ];
578
+
579
+ // src/mania.ts
580
+ var ManiaSDK = class _ManiaSDK {
581
+ publicClient;
582
+ walletClient = null;
583
+ factoryAddress;
584
+ chainId;
585
+ /**
586
+ * Create a new ManiaSDK instance
587
+ *
588
+ * @param config - SDK configuration
589
+ * @param config.factoryAddress - ManiaFactory contract address
590
+ * @param config.rpcUrl - RPC URL for the chain
591
+ * @param config.chainId - Chain ID (optional, will be fetched if not provided)
592
+ */
593
+ constructor(config) {
594
+ this.factoryAddress = config.factoryAddress;
595
+ this.chainId = config.chainId ?? 1;
596
+ this.publicClient = (0, import_viem.createPublicClient)({
597
+ transport: (0, import_viem.http)(config.rpcUrl)
598
+ });
599
+ }
600
+ /**
601
+ * Create SDK instance from chain ID using default configuration
602
+ *
603
+ * @param chainId - Chain ID
604
+ * @param rpcUrl - RPC URL (optional, uses public RPC if not provided)
605
+ * @returns ManiaSDK instance
606
+ */
607
+ static fromChainId(chainId, rpcUrl) {
608
+ const chainConfig = getChainConfig(chainId);
609
+ if (!chainConfig) {
610
+ throw new Error(`Unsupported chain ID: ${chainId}`);
611
+ }
612
+ return new _ManiaSDK({
613
+ factoryAddress: chainConfig.factoryAddress,
614
+ rpcUrl,
615
+ chainId
616
+ });
617
+ }
618
+ /**
619
+ * Connect a wallet for signing transactions
620
+ *
621
+ * @param privateKey - Private key (with or without 0x prefix)
622
+ * @param chain - Viem chain object
623
+ */
624
+ connectWallet(privateKey, chain) {
625
+ const account = (0, import_accounts.privateKeyToAccount)(
626
+ privateKey.startsWith("0x") ? privateKey : `0x${privateKey}`
627
+ );
628
+ this.walletClient = (0, import_viem.createWalletClient)({
629
+ account,
630
+ chain,
631
+ transport: (0, import_viem.http)()
632
+ });
633
+ }
634
+ /**
635
+ * Connect an existing wallet client
636
+ *
637
+ * @param walletClient - Viem wallet client
638
+ */
639
+ setWalletClient(walletClient) {
640
+ this.walletClient = walletClient;
641
+ }
642
+ /**
643
+ * Set a custom public client
644
+ *
645
+ * @param publicClient - Viem public client
646
+ */
647
+ setPublicClient(publicClient) {
648
+ this.publicClient = publicClient;
649
+ }
650
+ /**
651
+ * Get the connected wallet address
652
+ */
653
+ getWalletAddress() {
654
+ return this.walletClient?.account?.address;
655
+ }
656
+ // ========== READ METHODS ==========
657
+ /**
658
+ * Get global protocol configuration
659
+ */
660
+ async getGlobalState() {
661
+ const result = await this.publicClient.readContract({
662
+ address: this.factoryAddress,
663
+ abi: MANIA_FACTORY_ABI,
664
+ functionName: "global"
665
+ });
666
+ const [
667
+ initialized,
668
+ authority,
669
+ feeRecipient,
670
+ initialVirtualTokenReserves,
671
+ initialVirtualEthReserves,
672
+ initialRealTokenReserves,
673
+ tokenTotalSupply,
674
+ feeBasisPoints,
675
+ withdrawAuthority,
676
+ enableMigrate,
677
+ poolMigrationFee
678
+ ] = result;
679
+ return {
680
+ initialized,
681
+ authority,
682
+ feeRecipient,
683
+ initialVirtualTokenReserves,
684
+ initialVirtualEthReserves,
685
+ initialRealTokenReserves,
686
+ tokenTotalSupply,
687
+ feeBasisPoints,
688
+ withdrawAuthority,
689
+ enableMigrate,
690
+ poolMigrationFee
691
+ };
692
+ }
693
+ /**
694
+ * Get bonding curve state for a token
695
+ *
696
+ * @param token - Token address
697
+ */
698
+ async getBondingCurve(token) {
699
+ const result = await this.publicClient.readContract({
700
+ address: this.factoryAddress,
701
+ abi: MANIA_FACTORY_ABI,
702
+ functionName: "getBondingCurve",
703
+ args: [token]
704
+ });
705
+ const curve = result;
706
+ return {
707
+ virtualTokenReserves: curve.virtualTokenReserves,
708
+ virtualEthReserves: curve.virtualEthReserves,
709
+ realTokenReserves: curve.realTokenReserves,
710
+ realEthReserves: curve.realEthReserves,
711
+ tokenTotalSupply: curve.tokenTotalSupply,
712
+ complete: curve.complete,
713
+ trackVolume: curve.trackVolume
714
+ };
715
+ }
716
+ /**
717
+ * Get a BondingCurve instance for calculations
718
+ *
719
+ * @param token - Token address
720
+ */
721
+ async getBondingCurveInstance(token) {
722
+ const [curveState, globalState] = await Promise.all([
723
+ this.getBondingCurve(token),
724
+ this.getGlobalState()
725
+ ]);
726
+ return new BondingCurve(curveState, globalState.feeBasisPoints);
727
+ }
728
+ /**
729
+ * Get comprehensive token information
730
+ *
731
+ * @param token - Token address
732
+ */
733
+ async getTokenInfo(token) {
734
+ const curve = await this.getBondingCurveInstance(token);
735
+ const state = curve.getState();
736
+ return {
737
+ address: token,
738
+ bondingCurve: state,
739
+ currentPrice: curve.getCurrentPrice(),
740
+ marketCapEth: curve.getMarketCapEth(),
741
+ migrationProgress: curve.getMigrationProgress()
742
+ };
743
+ }
744
+ /**
745
+ * Get buy quote from contract
746
+ *
747
+ * @param token - Token address
748
+ * @param ethAmount - ETH amount in wei
749
+ */
750
+ async getBuyQuote(token, ethAmount) {
751
+ const result = await this.publicClient.readContract({
752
+ address: this.factoryAddress,
753
+ abi: MANIA_FACTORY_ABI,
754
+ functionName: "getBuyQuote",
755
+ args: [token, ethAmount]
756
+ });
757
+ return result;
758
+ }
759
+ /**
760
+ * Get sell quote from contract
761
+ *
762
+ * @param token - Token address
763
+ * @param tokenAmount - Token amount
764
+ */
765
+ async getSellQuote(token, tokenAmount) {
766
+ const result = await this.publicClient.readContract({
767
+ address: this.factoryAddress,
768
+ abi: MANIA_FACTORY_ABI,
769
+ functionName: "getSellQuote",
770
+ args: [token, tokenAmount]
771
+ });
772
+ return result;
773
+ }
774
+ /**
775
+ * Get fee for a given amount
776
+ *
777
+ * @param amount - Amount in wei
778
+ */
779
+ async getFee(amount) {
780
+ const result = await this.publicClient.readContract({
781
+ address: this.factoryAddress,
782
+ abi: MANIA_FACTORY_ABI,
783
+ functionName: "getFee",
784
+ args: [amount]
785
+ });
786
+ return result;
787
+ }
788
+ /**
789
+ * Get user volume
790
+ *
791
+ * @param user - User address
792
+ */
793
+ async getUserVolume(user) {
794
+ const result = await this.publicClient.readContract({
795
+ address: this.factoryAddress,
796
+ abi: MANIA_FACTORY_ABI,
797
+ functionName: "userVolume",
798
+ args: [user]
799
+ });
800
+ return result;
801
+ }
802
+ // ========== WRITE METHODS ==========
803
+ getConnectedWallet() {
804
+ if (!this.walletClient?.account) {
805
+ throw new Error("Wallet not connected. Call connectWallet() first.");
806
+ }
807
+ return this.walletClient;
808
+ }
809
+ /**
810
+ * Create a new token with bonding curve
811
+ *
812
+ * @param params - Token creation parameters
813
+ * @returns Transaction result with token address
814
+ */
815
+ async create(params) {
816
+ const wallet = this.getConnectedWallet();
817
+ const hash = await wallet.writeContract({
818
+ chain: null,
819
+ account: null,
820
+ address: this.factoryAddress,
821
+ abi: MANIA_FACTORY_ABI,
822
+ functionName: "create",
823
+ args: [params.name, params.symbol, params.uri, params.creator]
824
+ });
825
+ const receipt = await this.publicClient.waitForTransactionReceipt({ hash });
826
+ const logs = (0, import_viem.parseEventLogs)({
827
+ abi: MANIA_FACTORY_ABI,
828
+ logs: receipt.logs,
829
+ eventName: "CreateEvent"
830
+ });
831
+ const tokenAddress = logs[0]?.args?.mint;
832
+ return {
833
+ hash,
834
+ success: receipt.status === "success",
835
+ tokenAddress
836
+ };
837
+ }
838
+ /**
839
+ * Create a new token and buy in a single transaction
840
+ *
841
+ * @param params - Creation and buy parameters
842
+ * @returns Transaction result with token address
843
+ */
844
+ async createAndBuy(params) {
845
+ const wallet = this.getConnectedWallet();
846
+ const hash = await wallet.writeContract({
847
+ chain: null,
848
+ account: null,
849
+ address: this.factoryAddress,
850
+ abi: MANIA_FACTORY_ABI,
851
+ functionName: "createAndBuy",
852
+ args: [params.name, params.symbol, params.uri, params.creator, params.minTokensOut],
853
+ value: params.buyAmountEth
854
+ });
855
+ const receipt = await this.publicClient.waitForTransactionReceipt({ hash });
856
+ const logs = (0, import_viem.parseEventLogs)({
857
+ abi: MANIA_FACTORY_ABI,
858
+ logs: receipt.logs,
859
+ eventName: "CreateEvent"
860
+ });
861
+ const tokenAddress = logs[0]?.args?.mint;
862
+ return {
863
+ hash,
864
+ success: receipt.status === "success",
865
+ tokenAddress
866
+ };
867
+ }
868
+ /**
869
+ * Buy tokens from bonding curve
870
+ *
871
+ * @param params - Buy parameters
872
+ * @returns Transaction result
873
+ */
874
+ async buy(params) {
875
+ const wallet = this.getConnectedWallet();
876
+ const recipient = params.recipient ?? wallet.account.address;
877
+ const hash = await wallet.writeContract({
878
+ chain: null,
879
+ account: null,
880
+ address: this.factoryAddress,
881
+ abi: MANIA_FACTORY_ABI,
882
+ functionName: "buy",
883
+ args: [params.token, params.minTokensOut, recipient],
884
+ value: params.amountEth
885
+ });
886
+ const receipt = await this.publicClient.waitForTransactionReceipt({ hash });
887
+ return {
888
+ hash,
889
+ success: receipt.status === "success"
890
+ };
891
+ }
892
+ /**
893
+ * Buy tokens with automatic slippage calculation
894
+ *
895
+ * @param token - Token address
896
+ * @param ethAmount - ETH amount to spend
897
+ * @param slippageBps - Slippage tolerance in basis points (default: 100 = 1%)
898
+ */
899
+ async buyWithSlippage(token, ethAmount, slippageBps = DEFAULT_SLIPPAGE_BPS) {
900
+ const curve = await this.getBondingCurveInstance(token);
901
+ const minTokensOut = curve.calculateMinTokensOut(ethAmount, slippageBps);
902
+ return this.buy({
903
+ token,
904
+ amountEth: ethAmount,
905
+ minTokensOut
906
+ });
907
+ }
908
+ /**
909
+ * Sell tokens to bonding curve
910
+ *
911
+ * @param params - Sell parameters
912
+ * @returns Transaction result
913
+ */
914
+ async sell(params) {
915
+ const wallet = this.getConnectedWallet();
916
+ const hash = await wallet.writeContract({
917
+ chain: null,
918
+ account: null,
919
+ address: this.factoryAddress,
920
+ abi: MANIA_FACTORY_ABI,
921
+ functionName: "sell",
922
+ args: [params.token, params.amountTokens, params.minEthOut]
923
+ });
924
+ const receipt = await this.publicClient.waitForTransactionReceipt({ hash });
925
+ return {
926
+ hash,
927
+ success: receipt.status === "success"
928
+ };
929
+ }
930
+ /**
931
+ * Sell tokens with automatic slippage calculation
932
+ *
933
+ * @param token - Token address
934
+ * @param tokenAmount - Token amount to sell
935
+ * @param slippageBps - Slippage tolerance in basis points (default: 100 = 1%)
936
+ */
937
+ async sellWithSlippage(token, tokenAmount, slippageBps = DEFAULT_SLIPPAGE_BPS) {
938
+ const curve = await this.getBondingCurveInstance(token);
939
+ const minEthOut = curve.calculateMinEthOut(tokenAmount, slippageBps);
940
+ return this.sell({
941
+ token,
942
+ amountTokens: tokenAmount,
943
+ minEthOut
944
+ });
945
+ }
946
+ /**
947
+ * Migrate liquidity to Uniswap V3
948
+ *
949
+ * @param params - Migration parameters
950
+ * @returns Transaction result with pool address
951
+ */
952
+ async migrate(params) {
953
+ const wallet = this.getConnectedWallet();
954
+ const globalState = await this.getGlobalState();
955
+ const hash = await wallet.writeContract({
956
+ chain: null,
957
+ account: null,
958
+ address: this.factoryAddress,
959
+ abi: MANIA_FACTORY_ABI,
960
+ functionName: "migrate",
961
+ args: [params.token],
962
+ value: globalState.poolMigrationFee
963
+ });
964
+ const receipt = await this.publicClient.waitForTransactionReceipt({ hash });
965
+ const logs = (0, import_viem.parseEventLogs)({
966
+ abi: MANIA_FACTORY_ABI,
967
+ logs: receipt.logs,
968
+ eventName: "CompleteManiaAmmMigrationEvent"
969
+ });
970
+ const poolAddress = logs[0]?.args?.pool;
971
+ return {
972
+ hash,
973
+ success: receipt.status === "success",
974
+ poolAddress
975
+ };
976
+ }
977
+ // ========== EVENT WATCHING ==========
978
+ /**
979
+ * Watch for new token creation events
980
+ *
981
+ * @param callback - Callback function for each event
982
+ * @returns Unwatch function
983
+ */
984
+ watchCreateEvents(callback) {
985
+ return this.publicClient.watchContractEvent({
986
+ address: this.factoryAddress,
987
+ abi: MANIA_FACTORY_ABI,
988
+ eventName: "CreateEvent",
989
+ onLogs: (logs) => {
990
+ for (const log of logs) {
991
+ const args = log.args;
992
+ callback(args);
993
+ }
994
+ }
995
+ });
996
+ }
997
+ /**
998
+ * Watch for trade events on a specific token
999
+ *
1000
+ * @param token - Token address (optional, watches all if not provided)
1001
+ * @param callback - Callback function for each event
1002
+ * @returns Unwatch function
1003
+ */
1004
+ watchTradeEvents(token, callback) {
1005
+ return this.publicClient.watchContractEvent({
1006
+ address: this.factoryAddress,
1007
+ abi: MANIA_FACTORY_ABI,
1008
+ eventName: "TradeEvent",
1009
+ args: token ? { mint: token } : void 0,
1010
+ onLogs: (logs) => {
1011
+ for (const log of logs) {
1012
+ const args = log.args;
1013
+ callback(args);
1014
+ }
1015
+ }
1016
+ });
1017
+ }
1018
+ /**
1019
+ * Watch for bonding curve completion events
1020
+ *
1021
+ * @param callback - Callback function for each event
1022
+ * @returns Unwatch function
1023
+ */
1024
+ watchCompleteEvents(callback) {
1025
+ return this.publicClient.watchContractEvent({
1026
+ address: this.factoryAddress,
1027
+ abi: MANIA_FACTORY_ABI,
1028
+ eventName: "CompleteEvent",
1029
+ onLogs: (logs) => {
1030
+ for (const log of logs) {
1031
+ const args = log.args;
1032
+ callback(args);
1033
+ }
1034
+ }
1035
+ });
1036
+ }
1037
+ /**
1038
+ * Watch for migration events
1039
+ *
1040
+ * @param callback - Callback function for each event
1041
+ * @returns Unwatch function
1042
+ */
1043
+ watchMigrationEvents(callback) {
1044
+ return this.publicClient.watchContractEvent({
1045
+ address: this.factoryAddress,
1046
+ abi: MANIA_FACTORY_ABI,
1047
+ eventName: "CompleteManiaAmmMigrationEvent",
1048
+ onLogs: (logs) => {
1049
+ for (const log of logs) {
1050
+ const args = log.args;
1051
+ callback(args);
1052
+ }
1053
+ }
1054
+ });
1055
+ }
1056
+ // ========== UTILITY METHODS ==========
1057
+ /**
1058
+ * Check if a token's bonding curve is complete
1059
+ *
1060
+ * @param token - Token address
1061
+ */
1062
+ async isComplete(token) {
1063
+ const curve = await this.getBondingCurve(token);
1064
+ return curve.complete;
1065
+ }
1066
+ /**
1067
+ * Check if a token has been migrated
1068
+ *
1069
+ * @param token - Token address
1070
+ */
1071
+ async isMigrated(token) {
1072
+ const curve = await this.getBondingCurve(token);
1073
+ return curve.realEthReserves === 0n && curve.virtualEthReserves === 0n && curve.realTokenReserves === 0n && curve.virtualTokenReserves === 0n;
1074
+ }
1075
+ /**
1076
+ * Get the factory contract address
1077
+ */
1078
+ getFactoryAddress() {
1079
+ return this.factoryAddress;
1080
+ }
1081
+ /**
1082
+ * Get the public client
1083
+ */
1084
+ getPublicClient() {
1085
+ return this.publicClient;
1086
+ }
1087
+ /**
1088
+ * Get the wallet client
1089
+ */
1090
+ getWalletClient() {
1091
+ return this.walletClient;
1092
+ }
1093
+ };
1094
+
1095
+ // src/utils.ts
1096
+ var import_viem2 = require("viem");
1097
+ function formatEthValue(wei, decimals = 4) {
1098
+ const ethValue = (0, import_viem2.formatEther)(wei);
1099
+ const num = parseFloat(ethValue);
1100
+ return num.toFixed(decimals);
1101
+ }
1102
+ function formatTokenAmount(amount, decimals = 2) {
1103
+ const ethValue = (0, import_viem2.formatEther)(amount);
1104
+ const num = parseFloat(ethValue);
1105
+ if (num >= 1e9) {
1106
+ return (num / 1e9).toFixed(decimals) + "B";
1107
+ }
1108
+ if (num >= 1e6) {
1109
+ return (num / 1e6).toFixed(decimals) + "M";
1110
+ }
1111
+ if (num >= 1e3) {
1112
+ return (num / 1e3).toFixed(decimals) + "K";
1113
+ }
1114
+ return num.toFixed(decimals);
1115
+ }
1116
+ function parseEthValue(eth) {
1117
+ return (0, import_viem2.parseEther)(eth);
1118
+ }
1119
+ function calculateWithSlippage(amount, slippageBps) {
1120
+ const slippageMultiplier = BPS_DENOMINATOR - BigInt(slippageBps);
1121
+ return amount * slippageMultiplier / BPS_DENOMINATOR;
1122
+ }
1123
+ function calculateMigrationProgress(realEthReserves) {
1124
+ if (realEthReserves >= MIGRATION_THRESHOLD) {
1125
+ return 100;
1126
+ }
1127
+ return Number(realEthReserves * 10000n / MIGRATION_THRESHOLD) / 100;
1128
+ }
1129
+ function formatPrice(priceWei) {
1130
+ const price = Number(priceWei) / 1e18;
1131
+ if (price < 1e-6) {
1132
+ return price.toExponential(4);
1133
+ }
1134
+ if (price < 1e-4) {
1135
+ return price.toFixed(8);
1136
+ }
1137
+ if (price < 0.01) {
1138
+ return price.toFixed(6);
1139
+ }
1140
+ return price.toFixed(4);
1141
+ }
1142
+ function formatMarketCap(marketCapWei) {
1143
+ const ethValue = Number((0, import_viem2.formatEther)(marketCapWei));
1144
+ if (ethValue >= 1e3) {
1145
+ return (ethValue / 1e3).toFixed(2) + "K ETH";
1146
+ }
1147
+ return ethValue.toFixed(2) + " ETH";
1148
+ }
1149
+ function isValidAddress(address) {
1150
+ return /^0x[a-fA-F0-9]{40}$/.test(address);
1151
+ }
1152
+ function truncateAddress(address, chars = 4) {
1153
+ const start = address.slice(0, chars + 2);
1154
+ const end = address.slice(-chars);
1155
+ return start + "..." + end;
1156
+ }
1157
+ function bpsToPercent(bps) {
1158
+ return Number(bps) / 100;
1159
+ }
1160
+ function percentToBps(percent) {
1161
+ return Math.round(percent * 100);
1162
+ }
1163
+ function calculatePriceImpact(currentPrice, newPrice) {
1164
+ if (currentPrice === 0n) return 0;
1165
+ return Number((newPrice - currentPrice) * 10000n / currentPrice) / 100;
1166
+ }
1167
+ function sleep(ms) {
1168
+ return new Promise((resolve) => setTimeout(resolve, ms));
1169
+ }
1170
+ async function withRetry(fn, maxRetries = 3, baseDelayMs = 1e3) {
1171
+ let lastError;
1172
+ for (let i = 0; i < maxRetries; i++) {
1173
+ try {
1174
+ return await fn();
1175
+ } catch (error) {
1176
+ lastError = error instanceof Error ? error : new Error(String(error));
1177
+ if (i < maxRetries - 1) {
1178
+ await sleep(baseDelayMs * Math.pow(2, i));
1179
+ }
1180
+ }
1181
+ }
1182
+ throw lastError;
1183
+ }
1184
+ // Annotate the CommonJS export names for ESM import in node:
1185
+ 0 && (module.exports = {
1186
+ BPS_DENOMINATOR,
1187
+ BondingCurve,
1188
+ CHAIN_CONFIGS,
1189
+ CREATOR_FEE_BASIS_POINTS,
1190
+ DEFAULT_SLIPPAGE_BPS,
1191
+ ERC20_ABI,
1192
+ MANIA_FACTORY_ABI,
1193
+ MAX_FEE_BASIS_POINTS,
1194
+ MAX_MIGRATE_FEES,
1195
+ MIGRATION_THRESHOLD,
1196
+ ManiaSDK,
1197
+ PROTOCOL_FEE_BASIS_POINTS,
1198
+ TICK_LOWER,
1199
+ TICK_UPPER,
1200
+ TOKENS_FOR_LP,
1201
+ TOTAL_FEE_BASIS_POINTS,
1202
+ UNISWAP_FEE_TIER,
1203
+ bpsToPercent,
1204
+ calculateBuyAmount,
1205
+ calculateMigrationProgress,
1206
+ calculatePriceImpact,
1207
+ calculateSellAmount,
1208
+ calculateWithSlippage,
1209
+ formatEthValue,
1210
+ formatMarketCap,
1211
+ formatPrice,
1212
+ formatTokenAmount,
1213
+ getChainConfig,
1214
+ isValidAddress,
1215
+ parseEthValue,
1216
+ percentToBps,
1217
+ sleep,
1218
+ truncateAddress,
1219
+ withRetry
1220
+ });