@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/README.md +397 -0
- package/dist/index.d.mts +1116 -0
- package/dist/index.d.ts +1116 -0
- package/dist/index.js +1220 -0
- package/dist/index.mjs +1165 -0
- package/package.json +56 -0
- package/src/.claude/settings.local.json +9 -0
- package/src/abi/ManiaFactoryUpgradeable.json +2183 -0
- package/src/abi.ts +268 -0
- package/src/bondingCurve.ts +319 -0
- package/src/constants.ts +72 -0
- package/src/index.ts +71 -0
- package/src/mania.ts +652 -0
- package/src/types.ts +238 -0
- package/src/utils.ts +154 -0
package/src/types.ts
ADDED
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
import type { Address, Hash } from "viem";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Bonding curve state for a token
|
|
5
|
+
*/
|
|
6
|
+
export interface BondingCurveState {
|
|
7
|
+
/** Virtual token reserves used in AMM calculation */
|
|
8
|
+
virtualTokenReserves: bigint;
|
|
9
|
+
/** Virtual ETH reserves used in AMM calculation */
|
|
10
|
+
virtualEthReserves: bigint;
|
|
11
|
+
/** Real token reserves available for purchase */
|
|
12
|
+
realTokenReserves: bigint;
|
|
13
|
+
/** Real ETH reserves collected from sales */
|
|
14
|
+
realEthReserves: bigint;
|
|
15
|
+
/** Total supply of the token */
|
|
16
|
+
tokenTotalSupply: bigint;
|
|
17
|
+
/** Whether the bonding curve has completed (reached migration threshold) */
|
|
18
|
+
complete: boolean;
|
|
19
|
+
/** Whether volume tracking is enabled for this token */
|
|
20
|
+
trackVolume: boolean;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Global protocol configuration
|
|
25
|
+
*/
|
|
26
|
+
export interface GlobalState {
|
|
27
|
+
/** Whether the protocol has been initialized */
|
|
28
|
+
initialized: boolean;
|
|
29
|
+
/** Protocol authority address */
|
|
30
|
+
authority: Address;
|
|
31
|
+
/** Fee recipient address */
|
|
32
|
+
feeRecipient: Address;
|
|
33
|
+
/** Initial virtual token reserves for new curves */
|
|
34
|
+
initialVirtualTokenReserves: bigint;
|
|
35
|
+
/** Initial virtual ETH reserves for new curves */
|
|
36
|
+
initialVirtualEthReserves: bigint;
|
|
37
|
+
/** Initial real token reserves for new curves */
|
|
38
|
+
initialRealTokenReserves: bigint;
|
|
39
|
+
/** Token total supply for new tokens */
|
|
40
|
+
tokenTotalSupply: bigint;
|
|
41
|
+
/** Fee basis points (1 bp = 0.01%) */
|
|
42
|
+
feeBasisPoints: bigint;
|
|
43
|
+
/** Withdraw authority address */
|
|
44
|
+
withdrawAuthority: Address;
|
|
45
|
+
/** Whether migration to Uniswap is enabled */
|
|
46
|
+
enableMigrate: boolean;
|
|
47
|
+
/** Fee charged for pool migration */
|
|
48
|
+
poolMigrationFee: bigint;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Parameters for setting global protocol configuration
|
|
53
|
+
*/
|
|
54
|
+
export interface SetParamsInput {
|
|
55
|
+
initialVirtualTokenReserves: bigint;
|
|
56
|
+
initialVirtualEthReserves: bigint;
|
|
57
|
+
initialRealTokenReserves: bigint;
|
|
58
|
+
tokenTotalSupply: bigint;
|
|
59
|
+
feeBasisPoints: bigint;
|
|
60
|
+
withdrawAuthority: Address;
|
|
61
|
+
enableMigrate: boolean;
|
|
62
|
+
poolMigrationFee: bigint;
|
|
63
|
+
feeRecipient: Address;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Token creation parameters
|
|
68
|
+
*/
|
|
69
|
+
export interface CreateTokenParams {
|
|
70
|
+
/** Token name */
|
|
71
|
+
name: string;
|
|
72
|
+
/** Token symbol */
|
|
73
|
+
symbol: string;
|
|
74
|
+
/** Token metadata URI (e.g., IPFS link) */
|
|
75
|
+
uri: string;
|
|
76
|
+
/** Creator address (receives creator fees) */
|
|
77
|
+
creator: Address;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Parameters for creating a token and buying in a single transaction
|
|
82
|
+
*/
|
|
83
|
+
export interface CreateAndBuyParams extends CreateTokenParams {
|
|
84
|
+
/** ETH amount to spend on initial buy */
|
|
85
|
+
buyAmountEth: bigint;
|
|
86
|
+
/** Minimum tokens to receive (slippage protection) */
|
|
87
|
+
minTokensOut: bigint;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Buy transaction parameters
|
|
92
|
+
*/
|
|
93
|
+
export interface BuyParams {
|
|
94
|
+
/** Token address to buy */
|
|
95
|
+
token: Address;
|
|
96
|
+
/** ETH amount to spend */
|
|
97
|
+
amountEth: bigint;
|
|
98
|
+
/** Minimum tokens to receive (slippage protection) */
|
|
99
|
+
minTokensOut: bigint;
|
|
100
|
+
/** Recipient address for tokens (defaults to sender) */
|
|
101
|
+
recipient?: Address;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Sell transaction parameters
|
|
106
|
+
*/
|
|
107
|
+
export interface SellParams {
|
|
108
|
+
/** Token address to sell */
|
|
109
|
+
token: Address;
|
|
110
|
+
/** Amount of tokens to sell */
|
|
111
|
+
amountTokens: bigint;
|
|
112
|
+
/** Minimum ETH to receive (slippage protection) */
|
|
113
|
+
minEthOut: bigint;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Migration parameters
|
|
118
|
+
*/
|
|
119
|
+
export interface MigrateParams {
|
|
120
|
+
/** Token address to migrate */
|
|
121
|
+
token: Address;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Quote result for buy operations
|
|
126
|
+
*/
|
|
127
|
+
export interface BuyQuote {
|
|
128
|
+
/** Tokens that would be received */
|
|
129
|
+
tokensOut: bigint;
|
|
130
|
+
/** Fee amount in ETH */
|
|
131
|
+
fee: bigint;
|
|
132
|
+
/** Net ETH after fees */
|
|
133
|
+
netEth: bigint;
|
|
134
|
+
/** Price per token in ETH */
|
|
135
|
+
pricePerToken: bigint;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Quote result for sell operations
|
|
140
|
+
*/
|
|
141
|
+
export interface SellQuote {
|
|
142
|
+
/** ETH that would be received (before fees) */
|
|
143
|
+
ethOutGross: bigint;
|
|
144
|
+
/** Fee amount in ETH */
|
|
145
|
+
fee: bigint;
|
|
146
|
+
/** Net ETH after fees */
|
|
147
|
+
ethOutNet: bigint;
|
|
148
|
+
/** Price per token in ETH */
|
|
149
|
+
pricePerToken: bigint;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Token information combining on-chain data
|
|
154
|
+
*/
|
|
155
|
+
export interface TokenInfo {
|
|
156
|
+
/** Token contract address */
|
|
157
|
+
address: Address;
|
|
158
|
+
/** Bonding curve state */
|
|
159
|
+
bondingCurve: BondingCurveState;
|
|
160
|
+
/** Current token price in ETH */
|
|
161
|
+
currentPrice: bigint;
|
|
162
|
+
/** Market cap in ETH */
|
|
163
|
+
marketCapEth: bigint;
|
|
164
|
+
/** Progress towards migration (0-100) */
|
|
165
|
+
migrationProgress: number;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Transaction result
|
|
170
|
+
*/
|
|
171
|
+
export interface TransactionResult {
|
|
172
|
+
/** Transaction hash */
|
|
173
|
+
hash: Hash;
|
|
174
|
+
/** Whether the transaction was successful */
|
|
175
|
+
success: boolean;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Event types emitted by the contract
|
|
180
|
+
*/
|
|
181
|
+
export interface CreateEvent {
|
|
182
|
+
name: string;
|
|
183
|
+
symbol: string;
|
|
184
|
+
uri: string;
|
|
185
|
+
mint: Address;
|
|
186
|
+
user: Address;
|
|
187
|
+
creator: Address;
|
|
188
|
+
timestamp: bigint;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
export interface TradeEvent {
|
|
192
|
+
mint: Address;
|
|
193
|
+
ethAmount: bigint;
|
|
194
|
+
tokenAmount: bigint;
|
|
195
|
+
isBuy: boolean;
|
|
196
|
+
user: Address;
|
|
197
|
+
timestamp: bigint;
|
|
198
|
+
virtualEthReserves: bigint;
|
|
199
|
+
virtualTokenReserves: bigint;
|
|
200
|
+
realEthReserves: bigint;
|
|
201
|
+
realTokenReserves: bigint;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
export interface CompleteEvent {
|
|
205
|
+
user: Address;
|
|
206
|
+
mint: Address;
|
|
207
|
+
timestamp: bigint;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
export interface MigrationEvent {
|
|
211
|
+
user: Address;
|
|
212
|
+
mint: Address;
|
|
213
|
+
mintAmount: bigint;
|
|
214
|
+
ethAmount: bigint;
|
|
215
|
+
poolMigrationFee: bigint;
|
|
216
|
+
timestamp: bigint;
|
|
217
|
+
pool: Address;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* SDK Configuration
|
|
222
|
+
*/
|
|
223
|
+
export interface ManiaSDKConfig {
|
|
224
|
+
/** ManiaFactory contract address */
|
|
225
|
+
factoryAddress: Address;
|
|
226
|
+
/** RPC URL or viem public client */
|
|
227
|
+
rpcUrl?: string;
|
|
228
|
+
/** Chain ID */
|
|
229
|
+
chainId?: number;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* Slippage configuration
|
|
234
|
+
*/
|
|
235
|
+
export interface SlippageConfig {
|
|
236
|
+
/** Slippage tolerance in basis points (e.g., 100 = 1%) */
|
|
237
|
+
slippageBps: number;
|
|
238
|
+
}
|
package/src/utils.ts
ADDED
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import { formatEther, parseEther, type Address } from "viem";
|
|
2
|
+
import { BPS_DENOMINATOR, MIGRATION_THRESHOLD } from "./constants.js";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Format a bigint wei value to a human-readable ETH string
|
|
6
|
+
*/
|
|
7
|
+
export function formatEthValue(wei: bigint, decimals: number = 4): string {
|
|
8
|
+
const ethValue = formatEther(wei);
|
|
9
|
+
const num = parseFloat(ethValue);
|
|
10
|
+
return num.toFixed(decimals);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Format a token amount to a human-readable string
|
|
15
|
+
*/
|
|
16
|
+
export function formatTokenAmount(amount: bigint, decimals: number = 2): string {
|
|
17
|
+
const ethValue = formatEther(amount);
|
|
18
|
+
const num = parseFloat(ethValue);
|
|
19
|
+
|
|
20
|
+
if (num >= 1_000_000_000) {
|
|
21
|
+
return (num / 1_000_000_000).toFixed(decimals) + "B";
|
|
22
|
+
}
|
|
23
|
+
if (num >= 1_000_000) {
|
|
24
|
+
return (num / 1_000_000).toFixed(decimals) + "M";
|
|
25
|
+
}
|
|
26
|
+
if (num >= 1_000) {
|
|
27
|
+
return (num / 1_000).toFixed(decimals) + "K";
|
|
28
|
+
}
|
|
29
|
+
return num.toFixed(decimals);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Parse an ETH string to wei
|
|
34
|
+
*/
|
|
35
|
+
export function parseEthValue(eth: string): bigint {
|
|
36
|
+
return parseEther(eth);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Calculate slippage-adjusted minimum amount
|
|
41
|
+
*/
|
|
42
|
+
export function calculateWithSlippage(amount: bigint, slippageBps: number): bigint {
|
|
43
|
+
const slippageMultiplier = BPS_DENOMINATOR - BigInt(slippageBps);
|
|
44
|
+
return (amount * slippageMultiplier) / BPS_DENOMINATOR;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Calculate percentage of migration threshold reached
|
|
49
|
+
*/
|
|
50
|
+
export function calculateMigrationProgress(realEthReserves: bigint): number {
|
|
51
|
+
if (realEthReserves >= MIGRATION_THRESHOLD) {
|
|
52
|
+
return 100;
|
|
53
|
+
}
|
|
54
|
+
return Number((realEthReserves * 10000n) / MIGRATION_THRESHOLD) / 100;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Format price with appropriate precision
|
|
59
|
+
*/
|
|
60
|
+
export function formatPrice(priceWei: bigint): string {
|
|
61
|
+
const price = Number(priceWei) / 1e18;
|
|
62
|
+
|
|
63
|
+
if (price < 0.000001) {
|
|
64
|
+
return price.toExponential(4);
|
|
65
|
+
}
|
|
66
|
+
if (price < 0.0001) {
|
|
67
|
+
return price.toFixed(8);
|
|
68
|
+
}
|
|
69
|
+
if (price < 0.01) {
|
|
70
|
+
return price.toFixed(6);
|
|
71
|
+
}
|
|
72
|
+
return price.toFixed(4);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Format market cap in ETH
|
|
77
|
+
*/
|
|
78
|
+
export function formatMarketCap(marketCapWei: bigint): string {
|
|
79
|
+
const ethValue = Number(formatEther(marketCapWei));
|
|
80
|
+
|
|
81
|
+
if (ethValue >= 1000) {
|
|
82
|
+
return (ethValue / 1000).toFixed(2) + "K ETH";
|
|
83
|
+
}
|
|
84
|
+
return ethValue.toFixed(2) + " ETH";
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Validate Ethereum address format
|
|
89
|
+
*/
|
|
90
|
+
export function isValidAddress(address: string): address is Address {
|
|
91
|
+
return /^0x[a-fA-F0-9]{40}$/.test(address);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Truncate address for display
|
|
96
|
+
*/
|
|
97
|
+
export function truncateAddress(address: Address, chars: number = 4): string {
|
|
98
|
+
const start = address.slice(0, chars + 2);
|
|
99
|
+
const end = address.slice(-chars);
|
|
100
|
+
return start + "..." + end;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Convert basis points to percentage
|
|
105
|
+
*/
|
|
106
|
+
export function bpsToPercent(bps: number | bigint): number {
|
|
107
|
+
return Number(bps) / 100;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Convert percentage to basis points
|
|
112
|
+
*/
|
|
113
|
+
export function percentToBps(percent: number): number {
|
|
114
|
+
return Math.round(percent * 100);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Calculate price impact as a percentage
|
|
119
|
+
*/
|
|
120
|
+
export function calculatePriceImpact(currentPrice: bigint, newPrice: bigint): number {
|
|
121
|
+
if (currentPrice === 0n) return 0;
|
|
122
|
+
return Number(((newPrice - currentPrice) * 10000n) / currentPrice) / 100;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Sleep utility for polling
|
|
127
|
+
*/
|
|
128
|
+
export function sleep(ms: number): Promise<void> {
|
|
129
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Retry a function with exponential backoff
|
|
134
|
+
*/
|
|
135
|
+
export async function withRetry<T>(
|
|
136
|
+
fn: () => Promise<T>,
|
|
137
|
+
maxRetries: number = 3,
|
|
138
|
+
baseDelayMs: number = 1000
|
|
139
|
+
): Promise<T> {
|
|
140
|
+
let lastError: Error | undefined;
|
|
141
|
+
|
|
142
|
+
for (let i = 0; i < maxRetries; i++) {
|
|
143
|
+
try {
|
|
144
|
+
return await fn();
|
|
145
|
+
} catch (error) {
|
|
146
|
+
lastError = error instanceof Error ? error : new Error(String(error));
|
|
147
|
+
if (i < maxRetries - 1) {
|
|
148
|
+
await sleep(baseDelayMs * Math.pow(2, i));
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
throw lastError;
|
|
154
|
+
}
|