@flaunch/sdk 0.9.0-beta.2 → 0.9.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 CHANGED
@@ -23,13 +23,21 @@ _Note: Add this `llms-full.txt` file into Cursor IDE / LLMs to provide context a
23
23
  - [Installation](#installation)
24
24
  - [Quick Start](#quick-start)
25
25
  - [Usage](#usage)
26
- - [Read Operations](#read-operations-with-viem)
27
- - [Write Operations](#write-operations-with-viem--wagmi)
28
- - [Selling with Permit2](#selling-with-permit2)
26
+ - [Read Operations (with Viem)](#read-operations-with-viem)
27
+ - [Write Operations (with Viem + Wagmi)](#write-operations-with-viem--wagmi)
29
28
  - [Flaunching a Memecoin](#flaunching-a-memecoin)
30
- - [How to generate Base64Image from file upload](#how-to-generate-base64image-from-user-uploaded-file)
29
+ - [How to generate `base64Image` from User uploaded file](#how-to-generate-base64image-from-user-uploaded-file)
31
30
  - [Flaunch with Address Fee Splits](#flaunch-with-address-fee-splits)
31
+ - [Buying a Flaunch coin](#buying-a-flaunch-coin)
32
+ - [Selling with Permit2](#selling-with-permit2)
33
+ - [Swap using USDC or other tokens by passing `intermediatePoolKey`](#swap-using-usdc-or-other-tokens-by-passing-intermediatepoolkey)
32
34
  - [Advanced Integration: Revenue Sharing with RevenueManager](#advanced-integration-revenue-sharing-with-revenuemanager)
35
+ - [Bot Protection during Fair Launch via TrustedSigner](#bot-protection-during-fair-launch-via-trustedsigner)
36
+ - [Groups](#groups)
37
+ - [Importing External Coins into Flaunch](#importing-external-coins-into-flaunch)
38
+ - [Adding Liquidity to Imported (or flaunch) coins](#adding-liquidity-to-imported-or-flaunch-coins)
39
+ - [Import AND Add Liquidity calls in a single batch](#import-and-add-liquidity-calls-in-a-single-batch)
40
+ - [`createFlaunchCalldata`: alternative to `createFlaunch`](#createflaunchcalldata-alternative-to-createflaunch-that-returns-the-tx-call-object-with-to-data-and-value-instead-of-directly-broadcasting-the-tx-from-walletclient)
33
41
  - [All SDK functions](#all-sdk-functions)
34
42
  - [React Hooks](#react-hooks)
35
43
  - [Flaunch Docs](#flaunch-reference)
@@ -125,64 +133,6 @@ const flaunchWrite = useMemo(() => {
125
133
  walletClient,
126
134
  }) as ReadWriteFlaunchSDK;
127
135
  }, [publicClient, walletClient]);
128
-
129
- // Execute a buy transaction
130
- const buyTokens = async () => {
131
- const hash = await flaunchWrite.buyCoin({
132
- coinAddress,
133
- slippagePercent: 5,
134
- swapType: "EXACT_IN",
135
- amountIn: parseEther("0.1"),
136
- });
137
-
138
- // Wait for confirmation
139
- const receipt = await flaunchWrite.drift.waitForTransaction({ hash });
140
- console.log(receipt.status === "success" ? "Success" : "Failed");
141
- };
142
- ```
143
-
144
- ### Selling with Permit2
145
-
146
- Permit2 enables gasless token approvals. Here's how to implement token selling with Permit2:
147
-
148
- ```ts
149
- import { useSignTypedData } from "wagmi";
150
- import { parseEther, Hex } from "viem";
151
-
152
- const {
153
- signTypedData,
154
- status: sigStatus,
155
- error: sigError,
156
- data: signature,
157
- } = useSignTypedData();
158
-
159
- // Check allowance and permit if needed
160
- const { allowance } = await flaunchWrite.getPermit2AllowanceAndNonce(
161
- coinAddress
162
- );
163
-
164
- if (allowance < parseEther(coinAmount)) {
165
- const { typedData, permitSingle } = await flaunchWrite.getPermit2TypedData(
166
- coinAddress
167
- );
168
- signTypedData(typedData);
169
-
170
- // then call this when signature is not undefined
171
- const hash = await flaunchWrite.sellCoin({
172
- coinAddress,
173
- amountIn: parseEther(coinAmount),
174
- slippagePercent: 5,
175
- permitSingle,
176
- signature,
177
- });
178
- } else {
179
- // if already approved
180
- const hash = await flaunchWrite.sellCoin({
181
- coinAddress,
182
- amountIn: parseEther(coinAmount),
183
- slippagePercent: 5,
184
- });
185
- }
186
136
  ```
187
137
 
188
138
  ### Flaunching a Memecoin
@@ -209,11 +159,6 @@ const hash = await flaunchWrite.flaunchIPFS({
209
159
  twitterUrl: "https://x.com/example",
210
160
  telegramUrl: "https://t.me/example",
211
161
  },
212
- pinataConfig: {
213
- // Use one-time JWT for client-side uploads
214
- // Refer: https://www.pinata.cloud/blog/how-to-upload-to-ipfs-from-the-frontend-with-signed-jwts/
215
- jwt: pinataJWT,
216
- },
217
162
  });
218
163
  ```
219
164
 
@@ -264,9 +209,6 @@ await flaunchWrite.flaunchIPFSWithSplitManager({
264
209
  metadata: {
265
210
  base64Image: "...",
266
211
  },
267
- pinataConfig: {
268
- jwt: "...",
269
- },
270
212
  fairLaunchPercent: 40,
271
213
  fairLaunchDuration: 30 * 60, // 30 mins
272
214
  initialMarketCapUSD: 1_000,
@@ -287,6 +229,187 @@ await flaunchWrite.flaunchIPFSWithSplitManager({
287
229
  });
288
230
  ```
289
231
 
232
+ ### Buying a Flaunch coin
233
+
234
+ ```ts
235
+ // Execute the buy transaction
236
+ const buyTokens = async () => {
237
+ const hash = await flaunchWrite.buyCoin({
238
+ coinAddress,
239
+ slippagePercent: 5,
240
+ swapType: "EXACT_IN",
241
+ amountIn: parseEther("0.1"),
242
+ });
243
+
244
+ // Wait for confirmation
245
+ const receipt = await flaunchWrite.drift.waitForTransaction({ hash });
246
+ console.log(receipt.status === "success" ? "Success" : "Failed");
247
+ };
248
+ ```
249
+
250
+ ### Selling with Permit2
251
+
252
+ Permit2 enables gasless token approvals. Here's how to implement token selling with Permit2:
253
+
254
+ ```ts
255
+ import { useSignTypedData } from "wagmi";
256
+ import { parseEther, Hex } from "viem";
257
+
258
+ const {
259
+ signTypedData,
260
+ status: sigStatus,
261
+ error: sigError,
262
+ data: signature,
263
+ } = useSignTypedData();
264
+
265
+ // Check allowance and permit if needed
266
+ const { allowance } = await flaunchWrite.getPermit2AllowanceAndNonce(
267
+ coinAddress
268
+ );
269
+
270
+ if (allowance < parseEther(coinAmount)) {
271
+ const { typedData, permitSingle } = await flaunchWrite.getPermit2TypedData(
272
+ coinAddress
273
+ );
274
+ signTypedData(typedData);
275
+
276
+ // then call this when signature is not undefined
277
+ const hash = await flaunchWrite.sellCoin({
278
+ coinAddress,
279
+ amountIn: parseEther(coinAmount),
280
+ slippagePercent: 5,
281
+ permitSingle,
282
+ signature,
283
+ });
284
+ } else {
285
+ // if already approved
286
+ const hash = await flaunchWrite.sellCoin({
287
+ coinAddress,
288
+ amountIn: parseEther(coinAmount),
289
+ slippagePercent: 5,
290
+ });
291
+ }
292
+ ```
293
+
294
+ ### Swap using USDC or other tokens by passing `intermediatePoolKey`
295
+
296
+ An `intermediatePoolKey` can be specified for the swap, where one currency of the poolKey is required to be `ETH` and the other currency can be `USDC` or some other token for which you want to swap from or into.
297
+ With the addition of this intermediate pool key, the swap gets routed as: `USDC -> ETH -> flETH -> Coin`
298
+
299
+ 1. Buy Coin with USDC
300
+
301
+ ```ts
302
+ import { useSignTypedData } from "wagmi";
303
+ const {
304
+ signTypedData,
305
+ status: sigStatus,
306
+ error: sigError,
307
+ data: signature,
308
+ } = useSignTypedData();
309
+
310
+ // flaunch coins by default have infinite approval for Permit2
311
+ // this is required for external tokens like USDC
312
+ const usdcAllowanceToPermit2 = await flaunchWrite.getERC20AllowanceToPermit2(
313
+ usdcAddress
314
+ );
315
+ if (usdcAllowanceToPermit2 < amount) {
316
+ // 1. max approve tx for Permit2 address to spend USDC
317
+ await flaunchWrite.setERC20AllowanceToPermit2(usdcAddress, maxUint256);
318
+ }
319
+
320
+ const { allowance: usdcPermit2Allowance } =
321
+ await flaunchWrite.getPermit2AllowanceAndNonce(usdcAddress);
322
+ if (usdcPermit2Allowance < amount) {
323
+ // 2. sign permit2 signature to spend USDC for swap
324
+ const { typedData, permitSingle } = await flaunchWrite.getPermit2TypedData(
325
+ usdcAddress
326
+ );
327
+ signTypedData(typedData);
328
+ }
329
+
330
+ // 3. Buy flaunch coin with USDC
331
+ await flaunchWrite.buyCoin({
332
+ coinAddress: coin,
333
+ slippagePercent: 5,
334
+ swapType: "EXACT_IN",
335
+ amountIn: amount, // USDC amount
336
+ // poolKey to route USDC to ETH swap
337
+ intermediatePoolKey: {
338
+ currency0: zeroAddress,
339
+ currency1: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", // USDC
340
+ fee: 500,
341
+ tickSpacing: 10,
342
+ hooks: zeroAddress,
343
+ hookData: "0x",
344
+ },
345
+ permitSingle,
346
+ signature,
347
+ referrer: referrer,
348
+ });
349
+ ```
350
+
351
+ 2. Sell coin for USDC
352
+
353
+ ```ts
354
+ import { useSignTypedData } from "wagmi";
355
+ import { parseEther, Hex } from "viem";
356
+
357
+ const {
358
+ signTypedData,
359
+ status: sigStatus,
360
+ error: sigError,
361
+ data: signature,
362
+ } = useSignTypedData();
363
+
364
+ // Check allowance and permit if needed
365
+ const { allowance } = await flaunchWrite.getPermit2AllowanceAndNonce(
366
+ coinAddress
367
+ );
368
+
369
+ if (allowance < parseEther(coinAmount)) {
370
+ const { typedData, permitSingle } = await flaunchWrite.getPermit2TypedData(
371
+ coinAddress
372
+ );
373
+ signTypedData(typedData);
374
+
375
+ // then call this when signature is not undefined
376
+ const hash = await flaunchWrite.sellCoin({
377
+ coinAddress,
378
+ amountIn: parseEther(coinAmount),
379
+ slippagePercent: 5,
380
+ permitSingle,
381
+ signature,
382
+ // poolKey to route ETH to USDC swap
383
+ intermediatePoolKey: {
384
+ currency0: zeroAddress,
385
+ currency1: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", // USDC
386
+ fee: 500,
387
+ tickSpacing: 10,
388
+ hooks: zeroAddress,
389
+ hookData: "0x",
390
+ },
391
+ });
392
+ } else {
393
+ // if already approved
394
+ const hash = await flaunchWrite.sellCoin({
395
+ coinAddress,
396
+ amountIn: parseEther(coinAmount),
397
+ slippagePercent: 5,
398
+ // poolKey to route ETH to USDC swap
399
+ intermediatePoolKey: {
400
+ currency0: zeroAddress,
401
+ currency1: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", // USDC
402
+ fee: 500,
403
+ tickSpacing: 10,
404
+ hooks: zeroAddress,
405
+ hookData: "0x",
406
+ },
407
+ });
408
+ }
409
+ ```
410
+
411
+ 3. The quote functions `getSellQuoteExactInput`, `getBuyQuoteExactInput` and `getBuyQuoteExactOutput` also support passing optional `intermediatePoolKey`.
412
+
290
413
  ### Advanced Integration: Revenue Sharing with RevenueManager
291
414
 
292
415
  For platforms building on top of Flaunch, the `RevenueManager` contract enables sophisticated revenue-sharing models. It allows platforms to automatically take a protocol fee from the trading fees generated by memecoins launched through their integration.
@@ -311,9 +434,6 @@ await flaunchWrite.flaunchIPFSWithRevenueManager({
311
434
  metadata: {
312
435
  base64Image: "...",
313
436
  },
314
- pinataConfig: {
315
- jwt: "...",
316
- },
317
437
  fairLaunchPercent: 40,
318
438
  fairLaunchDuration: 30 * 60, // 30 mins
319
439
  initialMarketCapUSD: 1_000,
@@ -361,6 +481,444 @@ await flaunchWrite.revenueManagerCreatorClaimForTokens({
361
481
 
362
482
  Refer to the [RevenueManager Docs](https://docs.flaunch.gg/manager-types/revenuemanager) for detailed implementation guides and function references.
363
483
 
484
+ ### Bot Protection during Fair Launch via TrustedSigner
485
+
486
+ 1. The `flaunch` call can be modified to enable TrustedSigner. For coins where it's enabled in their fair launch period, the buy transactions revert if they don't include the hookData with the signature (unique to the coin & sender address).
487
+ It's upto your UI integration to use some captcha service or other sort of gating to allow the signature to be generated only for the selected users that are trying to buy the coin during it's fair launch.
488
+
489
+ You can also limit the amount of coins that can be bought in a single swap tx, or even set per wallet caps.
490
+
491
+ **Note:** If your have provided your custom `trustedFeeSigner`, then the signatures are expected to be signed by your address. The Flaunch UI won't be able to execute the swaps during fair launch in that case, as our UI won't have access to your keys.
492
+ But you may leave the `trustedFeeSigner` param `undefined`, then the swaps can go through our UI. But you won't be able to generate valid signatures on end, as you won't access to our signer address.
493
+
494
+ 1.1. Without Premine
495
+
496
+ ```ts
497
+ const hash = await flaunchWrite.flaunchIPFS({
498
+ name: "Test",
499
+ ...
500
+ trustedSignerSettings: {
501
+ enabled: true,
502
+ trustedFeeSigner: "0x..",
503
+ walletCap: parseEther("1000000"), // optional
504
+ txCap: parseEther("10000"), // optional
505
+ }
506
+ });
507
+ ```
508
+
509
+ 1.2. With Premine
510
+ Refer to '2.' below to understand how to generate the deadline and signature, that needs to be passed here.
511
+
512
+ ```ts
513
+ const hash = await flaunchWrite.flaunchIPFS({
514
+ name: "Test",
515
+ ...
516
+ premineAmount: 123..,
517
+ trustedSignerSettings: {
518
+ enabled: true,
519
+ trustedFeeSigner: "0x...",
520
+ walletCap: parseEther("1000000"), // optional
521
+ txCap: parseEther("10000"), // optional
522
+ premineSignedMessage: {
523
+ deadline: 1234..,
524
+ signature: "0xabc...",
525
+ }
526
+ }
527
+ });
528
+ ```
529
+
530
+ 2. Backend SDK to sign & generate hookData
531
+ As the signing happens via your secure privateKey, we have a separate `FlaunchBackend` exported from our SDK package that's intended to be run on your nodejs backend or API. The API can verify if the request is legit (post captcha verification), and then return the signed hookData to be used for the `buyCoin` transaction.
532
+
533
+ ```ts
534
+ import { FlaunchBackend } from "@flaunch/sdk";
535
+
536
+ const flaunchBackend = new FlaunchBackend(privateKeyHex, chain.id);
537
+
538
+ const { hookData, deadline, signature } =
539
+ await flaunchBackend.generateHookDataWithSignature({
540
+ userWallet,
541
+ coinAddress,
542
+ referrer: referrer || undefined, // Optional parameter
543
+ deadlineFromNowInSeconds: 10 * 60, // 10 minutes in seconds
544
+ });
545
+
546
+ // hookData would be passed to buyQuote and buyCoin functions
547
+ // signature and deadline useful for passing to the flaunch call with premine, via `trustedSignerSettings.premineSignedMessage` parameter
548
+ ```
549
+
550
+ 3. Check TrustedSigner status for a coin
551
+
552
+ ```ts
553
+ const {
554
+ isCurrentlyEnabled,
555
+ trustedSignerEnabled,
556
+ signer,
557
+ fairLaunchStartsAt,
558
+ fairLaunchEndsAt,
559
+ isFairLaunchActive,
560
+ } = await flaunchRead.trustedPoolKeySignerStatus(coinAddress);
561
+
562
+ // if `isCurrentlyEnabled` is true, then we need to sign & pass in the hookData for the swaps with the given `signer` address
563
+ ```
564
+
565
+ 4. Buy quotes with TrustedSigner
566
+
567
+ ```ts
568
+ const quote = await flaunchRead.getBuyQuoteExactInput({
569
+ coinAddress: coin,
570
+ amountIn: amount,
571
+ // when trusted signer is currently enabled:
572
+ hookData, // from the backend SDK
573
+ userWallet: address,
574
+ });
575
+ ```
576
+
577
+ 5. Buy coin transaction with TrustedSigner
578
+
579
+ ```ts
580
+ await flaunchWrite.buyCoin({
581
+ coinAddress: coin,
582
+ slippagePercent: 5,
583
+ swapType: "EXACT_IN",
584
+ referrer: referrer,
585
+ // when trusted signer is currently enabled:
586
+ hookData, // from the backend SDK
587
+ });
588
+ ```
589
+
590
+ ### Groups
591
+
592
+ The technical side of Groups is handled by the StakingManager. It allows the creator to deposit their flaunch memestream into the manager, and then a defined ERC20 token can be staked by the user to earn their share of the ETH rewards from the memestream.
593
+
594
+ 1. Deploy your instance of the staking manager
595
+
596
+ ```ts
597
+ import { Permissions } from "@flaunch/sdk";
598
+
599
+ const stakingManagerInstance = await flaunchWrite.deployStakingManager({
600
+ managerOwner: ...,
601
+ stakingToken: ..., // The ERC20 token to stake
602
+ minEscrowDuration: ..., // The minimum duration (in seconds) that the creator's memestream NFT would be locked for
603
+ minStakeDuration: ..., // The minimum duration (in seconds) that the user's tokens would be locked for
604
+ creatorSharePercent: ..., // The % share that a creator will earn from their token
605
+ ownerSharePercent: ..., // The % share that the manager owner will earn from their token
606
+ // The Permissions can be OPEN, CLOSED, or WHITELISTED
607
+ // OPEN = anyone can stake
608
+ // CLOSED = no one except the managerOwner can stake
609
+ // WHITELISTED = only whitelisted addresses can stake
610
+ permissions: Permissions.OPEN,
611
+ });
612
+ ```
613
+
614
+ 2. Setting permissions after a Group is deployed (can only be called by the manager owner)
615
+
616
+ ```ts
617
+ await flaunchWrite.treasuryManagerSetPermissions(
618
+ treasuryManagerAddress: stakingManagerInstance,
619
+ permissions: Permissions.CLOSED
620
+ );
621
+ ```
622
+
623
+ 3. Flaunch a new coin into your Group
624
+ 3.1. Flaunching into your staking manager instance
625
+
626
+ ```ts
627
+ const hash = await flaunchWrite.flaunchIPFS({
628
+ name: "Test",
629
+ ...
630
+ treasuryManagerParams: {
631
+ manager: stakingManagerInstance
632
+ }
633
+ });
634
+ ```
635
+
636
+ 3.2. Deploying a new staking manager instance, and flaunching a new coin into it in a single transaction
637
+
638
+ ```ts
639
+ import { StakingManagerAddress } from "@flaunch/sdk";
640
+
641
+ const hash = await flaunchWrite.flaunchIPFS({
642
+ name: "Test",
643
+ ...
644
+ treasuryManagerParams: {
645
+ manager: StakingManagerAddress[chain.id],
646
+ permissions: Permissions.CLOSED
647
+ }
648
+ });
649
+ ```
650
+
651
+ Note: the `treasuryManagerParams.permissions` value is ignored if the `treasuryManagerParams.manager` is your manager instance instead.
652
+
653
+ 4. Add an already flaunched coin to a group
654
+
655
+ ```ts
656
+ import { FlaunchVersion } from "@flaunch/sdk";
657
+
658
+ // first approve then deposit
659
+ const tokenId = 123;
660
+ const isApproved = await flaunchRead.isFlaunchTokenApprovedForAll(
661
+ FlaunchVersion.V1_1_1,
662
+ owner,
663
+ treasuryManagerAddress
664
+ );
665
+
666
+ if (!isApproved) {
667
+ await flaunchWrite.setFlaunchTokenApprovalForAll(
668
+ FlaunchVersion.V1_1_1,
669
+ treasuryManagerAddress,
670
+ true
671
+ );
672
+ }
673
+
674
+ await flaunchWrite.addToTreasuryManager(
675
+ treasuryManagerAddress,
676
+ FlaunchVersion.V1_1_1,
677
+ tokenId
678
+ );
679
+ ```
680
+
681
+ ### Importing External Coins into Flaunch
682
+
683
+ You can import external ERC20 coins launched on other platforms like Zora, Virtuals, etc. into Flaunch to utilize the power of our Uniswap V4 hooks!
684
+
685
+ 1.1. Import with coin's current price
686
+
687
+ ```ts
688
+ await flaunchWrite.importMemecoin({
689
+ coinAddress: "0x...", // ERC20 token contract address
690
+ creatorFeeAllocationPercent: 100, // Fee allocation to creator (0-100%)
691
+ initialPriceUSD: 1, // Starting price in USD
692
+ });
693
+ ```
694
+
695
+ 1.2. Import with coin's current market cap. For memecoins, market caps are more human readable so you can pass it as follows
696
+
697
+ ```ts
698
+ await flaunchWrite.importMemecoin({
699
+ coinAddress: "0x...", // ERC20 token contract address
700
+ creatorFeeAllocationPercent: 100, // Fee allocation to creator (0-100%)
701
+ initialMarketCapUSD: 10_000, // Starting market cap in USD
702
+ });
703
+ ```
704
+
705
+ **Note:** The Flaunch Version for imported coins is: `FlaunchVersion.ANY` where `import {FlaunchVersion} from "@flaunch/sdk"`
706
+
707
+ **⚠️ Note:** The term "MarketCap" used throughout simply means `current coin price * ERC20.totalSupply()`. Some coins might show it as FDV, make sure to verify so that the Pool is initialized at the right price, and the liquidity gets provided at the expected range.
708
+
709
+ 1.3. Verify if a memecoin is imported into Flaunch
710
+
711
+ ```ts
712
+ const isImported = await flaunchRead.isMemecoinImported(coinAddress);
713
+ ```
714
+
715
+ ### Adding Liquidity to Imported (or flaunch) coins
716
+
717
+ When an external coin is imported into Flaunch's Uniswap V4 hooks, it has no liquidity in the pool. We can add liquidity by using the functions below.
718
+
719
+ Note: for existing flaunch coins you can pass `version` param as `FlaunchVersion.V1_2`, if left blank then the SDK can determine it automatically, defaulting to `FlaunchVersion.ANY` for external coins
720
+
721
+ 1. Read call to calculate the Coin & ETH amounts required for providing liquidity, based on the liquidity range specified. The return values are useful for displaying on the UI, before sending the liquidity transaction.
722
+
723
+ 1.1. Full Range liquidity
724
+
725
+ ```ts
726
+ const result = await flaunchRead.calculateAddLiquidityAmounts({
727
+ coinAddress: "0x...", // Token contract address
728
+ // version = FlaunchVersion.ANY for imported coins as they use our {AnyPositionManager}
729
+ version: FlaunchVersion.ANY, // optional (auto determines Flaunch version if not provided, else defaults to ANY if not found)
730
+ liquidityMode: LiquidityMode.FULL_RANGE,
731
+ coinOrEthInputAmount: parseEther("1"), // Input amount in wei
732
+ inputToken: "coin", // "coin" or "eth" - which token amount is specified
733
+ minMarketCap: "0", // not needed for FULL_RANGE
734
+ maxMarketCap: "0", // not needed for FULL_RANGE
735
+ });
736
+ // Returns: { coinAmount, ethAmount, tickLower, tickUpper, currentTick }
737
+ ```
738
+
739
+ 1.2. Concentrated Range liquidity
740
+ 1.2.1. With Market Cap inputs
741
+
742
+ ```ts
743
+ const result = await flaunchRead.calculateAddLiquidityAmounts({
744
+ coinAddress: "0x...", // Token contract address
745
+ version: FlaunchVersion.ANY,
746
+ liquidityMode: LiquidityMode.CONCENTRATED,
747
+ coinOrEthInputAmount: parseEther("1"), // Input amount in wei
748
+ inputToken: "coin", // "coin" or "eth" - which token amount is specified
749
+ minMarketCap: "1000000", // $1M
750
+ maxMarketCap: "5000000", // $5M
751
+ });
752
+ // Returns: { coinAmount, ethAmount, tickLower, tickUpper, currentTick }
753
+ ```
754
+
755
+ 1.2.2. With Coin Price inputs
756
+
757
+ ```ts
758
+ const result = await flaunchRead.calculateAddLiquidityAmounts({
759
+ coinAddress: "0x...", // Token contract address
760
+ version: FlaunchVersion.ANY,
761
+ liquidityMode: LiquidityMode.CONCENTRATED,
762
+ coinOrEthInputAmount: parseEther("1"), // Input amount in wei
763
+ inputToken: "coin", // "coin" or "eth" - which token amount is specified
764
+ minPriceUSD: "1",
765
+ maxPriceUSD: "5",
766
+ });
767
+ // Returns: { coinAmount, ethAmount, tickLower, tickUpper, currentTick }
768
+ ```
769
+
770
+ 1.2.3. `checkSingleSidedAddLiquidity`: helper check function to detect which token input to hide during single-sided concentrated liquidity addition.
771
+
772
+ Based on the specified concentrated range, we can determine which token (memecoin or ETH) to hide on the UI, as the liquidity would be single-sided
773
+
774
+ ```ts
775
+ const { isSingleSided, shouldHideCoinInput, shouldHideETHInput } = await flaunchRead.checkSingleSidedAddLiquidity({
776
+ coinAddress,
777
+ liquidityMode: LiquidityMode.CONCENTRATED,
778
+ // Option 1: can pass market caps
779
+ minMarketCap: "1000000", // $1M
780
+ maxMarketCap: "5000000", // $5M
781
+ currentMarketCap: "1000000" // (optional) can be queried from the pool if not specified
782
+ // OR Option 2: or can pass price
783
+ minPriceUSD: "1",
784
+ maxPriceUSD: "5",
785
+ currentPriceUSD: 0.001, // (optional) can be queried from the pool if not specified
786
+ });
787
+ ```
788
+
789
+ 2. Add Liquidity Transactions
790
+ Adding liquidity is a multi-step process, but we have abstracted away all the complexities. With wallets supporting ERCs 5792 & 7702, users would only get one wallet popup to confirm the transactions. See code snippet below at 2.3. for the same
791
+
792
+ 2.1. With Market Cap inputs
793
+
794
+ ```ts
795
+ const addLiqCalls = await flaunchWrite.getAddLiquidityCalls({
796
+ coinAddress: "0x...", // Same parameters as calculateAddLiquidityAmounts
797
+ version: FlaunchVersion.ANY, // optional
798
+ liquidityMode: LiquidityMode.CONCENTRATED,
799
+ coinOrEthInputAmount: parseEther("1"),
800
+ inputToken: "coin",
801
+ minMarketCap: "1000000", // $1M
802
+ maxMarketCap: "5000000", // $5M
803
+ });
804
+ // Returns: CallWithDescription[] - Array of transaction calls with descriptions
805
+ ```
806
+
807
+ 2.2. With Coin Price inputs
808
+
809
+ ```ts
810
+ const addLiqCalls = await flaunchWrite.getAddLiquidityCalls({
811
+ coinAddress: "0x...", // Same parameters as calculateAddLiquidityAmounts
812
+ version: FlaunchVersion.ANY, // optional
813
+ liquidityMode: LiquidityMode.CONCENTRATED,
814
+ coinOrEthInputAmount: parseEther("1"),
815
+ inputToken: "coin",
816
+ minPriceUSD: "1",
817
+ maxPriceUSD: "5",
818
+ });
819
+ ```
820
+
821
+ 2.3. Sending the transactions as a single batch to the Wallet via ERC-5792 and wagmi
822
+
823
+ **Note:** if the user's connected wallet doesn't support ERC-5792 (can be checked via `useCapabilities`), then you can simply loop through the `addLiqCalls` array and use `useSendTransaction` to send the transactions individually. The calls have a description to show on the UI if they'd be sent sequentially.
824
+
825
+ ```ts
826
+ import { useSendCalls } from "wagmi";
827
+
828
+ const { sendCalls } = useSendCalls();
829
+
830
+ const calls = addLiqCalls.map((call) => ({
831
+ to: call.to as `0x${string}`,
832
+ value: call.value,
833
+ data: call.data as `0x${string}`,
834
+ }));
835
+
836
+ await sendCalls({ calls });
837
+ ```
838
+
839
+ ### Import AND Add Liquidity calls in a single batch
840
+
841
+ 1. This allows an external coin to be live on flaunch, and be tradeable instantly with the liquidity being provided in the same transaction batch.
842
+
843
+ 💡 Tip: To mimic the traditional flaunch liquidity curve, the coin creator can provide liquidity from current market cap to a higher market cap. This makes the liquidity addition to be single-sided, entirely being in their coin with no ETH required. As people buy into the pool and the price goes up, the liquidity position accumulates ETH while selling the coins from the position.
844
+
845
+ Note: As a flaunch liquidity provider, you won't accumulate the trading fees. The fees are only accumulated to the Creator or split based on the TreasuryManager used.
846
+
847
+ 1.1. With Market Cap inputs
848
+
849
+ ```ts
850
+ const importAndAddLiqCalls = await flaunchWrite.getImportAndAddLiquidityCalls({
851
+ coinAddress: "0x...", // ERC20 token contract address
852
+ creatorFeeAllocationPercent: 100, // Fee allocation to creator (0-100%)
853
+ initialMarketCapUSD: 10_000, // Starting market cap in USD
854
+ liquidityMode: LiquidityMode.CONCENTRATED,
855
+ coinOrEthInputAmount: parseEther("1"), // Input amount in wei
856
+ inputToken: "coin", // "coin" or "eth" - which token amount is specified
857
+ minMarketCap: "1000000", // $1M
858
+ maxMarketCap: "5000000", // $5M
859
+ });
860
+ // Returns: CallWithDescription[] - Array of transaction calls with descriptions
861
+
862
+ // === send these calls to user's wallet as a batch ===
863
+ import { useSendCalls } from "wagmi";
864
+
865
+ const { sendCalls } = useSendCalls();
866
+
867
+ const calls = importAndAddLiqCalls.map((call) => ({
868
+ to: call.to as `0x${string}`,
869
+ value: call.value,
870
+ data: call.data as `0x${string}`,
871
+ }));
872
+
873
+ await sendCalls({ calls });
874
+ ```
875
+
876
+ 1.2. With Coin Price inputs
877
+
878
+ ```ts
879
+ const importAndAddLiqCalls = await flaunchWrite.getImportAndAddLiquidityCalls({
880
+ coinAddress: "0x...", // ERC20 token contract address
881
+ creatorFeeAllocationPercent: 100, // Fee allocation to creator (0-100%)
882
+ initialPriceUSD: 1, // Starting price in USD
883
+ liquidityMode: LiquidityMode.CONCENTRATED,
884
+ coinOrEthInputAmount: parseEther("1"), // Input amount in wei
885
+ inputToken: "coin", // "coin" or "eth" - which token amount is specified
886
+ minPriceUSD: "1",
887
+ maxPriceUSD: "5",
888
+ });
889
+ ```
890
+
891
+ ### `createFlaunchCalldata`: alternative to `createFlaunch` that returns the tx call object with to, data, and value instead of directly broadcasting the tx from walletClient
892
+
893
+ To support custom signers that might not be compatible with our `walletClient` approach, or to enable account abstraction and batching on your wallet signer's end we have `createFlaunchCalldata` that returns the tx object, leaving the tx broadcasting to be flexible & handled on your end.
894
+
895
+ All the write calls must go via `parseCall` as shown below, read calls are made normally as before
896
+
897
+ ```ts
898
+ import { createFlaunchCalldata, parseCall } from "@flaunch/sdk";
899
+
900
+ // 1. Can create read-only SDK (similar to createFlaunch without walletClient)
901
+ const flaunchRead = createFlaunchCalldata({
902
+ publicClient,
903
+ });
904
+
905
+ // 2. Create read-write SDK for call generation
906
+ const flaunchCalldata = createFlaunchCalldata({
907
+ publicClient,
908
+ walletAddress,
909
+ });
910
+
911
+ const call = await parseCall(() =>
912
+ flaunchCalldata.setERC20AllowanceToPermit2(usdcAddress, maxUint256)
913
+ );
914
+
915
+ console.log("Call:", {
916
+ to: call.to,
917
+ value: call.value.toString(),
918
+ data: call.data,
919
+ });
920
+ ```
921
+
364
922
  ### All SDK functions
365
923
 
366
924
  For a list of all the functions in the SDK, refer to: [FlaunchSDK.ts](./src/sdk/FlaunchSDK.ts)