@candledottv/agent-sdk 0.6.6 → 0.6.8

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 CHANGED
@@ -3318,6 +3318,795 @@ function describeRpcEndpoint(url) {
3318
3318
  }
3319
3319
  }
3320
3320
 
3321
+ // src/launch-definition.ts
3322
+ var LAUNCH_DEFINITION = {
3323
+ version: 1,
3324
+ wallet: {
3325
+ embeddedNames: [
3326
+ "embedded",
3327
+ "main"
3328
+ ],
3329
+ help: "The paying wallet: a TEE wallet name, or embedded (main) for the account's embedded wallet."
3330
+ },
3331
+ quoteDecimals: {
3332
+ sol: 9,
3333
+ usdc: 6,
3334
+ cndl: 6,
3335
+ eth: 18,
3336
+ usdg: 6
3337
+ },
3338
+ quoteChains: {
3339
+ sol: "solana",
3340
+ usdc: "solana",
3341
+ cndl: "solana",
3342
+ eth: "hood",
3343
+ usdg: "hood"
3344
+ },
3345
+ defaultQuote: {
3346
+ solana: "sol",
3347
+ hood: "eth"
3348
+ },
3349
+ buyLimits: {
3350
+ defaults: {
3351
+ sol: {
3352
+ env: "DEV_BUY_MAX_LAMPORTS",
3353
+ raw: "500000000",
3354
+ unit: "lamports"
3355
+ },
3356
+ usdc: {
3357
+ env: "DEV_BUY_MAX_USDC_RAW",
3358
+ raw: "500000000",
3359
+ unit: "USDC raw units"
3360
+ },
3361
+ cndl: {
3362
+ env: "DEV_BUY_MAX_CNDL_RAW",
3363
+ raw: "2000000000000",
3364
+ unit: "CNDL raw units"
3365
+ },
3366
+ eth: {
3367
+ env: "DEV_BUY_MAX_WEI",
3368
+ raw: "20000000000000000",
3369
+ unit: "wei"
3370
+ }
3371
+ },
3372
+ thresholdBps: 1000,
3373
+ presetThresholds: {
3374
+ "exp-a": {
3375
+ sol: "5000000000",
3376
+ cndl: "330000000000"
3377
+ },
3378
+ "exp-b": {
3379
+ sol: "5000000000",
3380
+ cndl: "330000000000"
3381
+ },
3382
+ "exp-c": {
3383
+ sol: "5000000000",
3384
+ cndl: "330000000000"
3385
+ }
3386
+ }
3387
+ },
3388
+ surfacesIntro: [
3389
+ "CLI: scripts and terminals. Agents always pass --json.",
3390
+ "MCP: chat agents (Claude, the connector). The same launch fields and results as the CLI's --json.",
3391
+ "SDK: code that embeds Candle."
3392
+ ],
3393
+ fields: [
3394
+ {
3395
+ key: "wallet",
3396
+ type: "string",
3397
+ help: "The paying wallet: a TEE wallet name, or embedded (main) for the account's embedded wallet.",
3398
+ required: true,
3399
+ surfaces: {
3400
+ cli: {
3401
+ flag: "--wallet",
3402
+ value: "<tee>|embedded"
3403
+ },
3404
+ mcp: {
3405
+ key: "wallet"
3406
+ },
3407
+ sdk: {
3408
+ key: "wallet"
3409
+ }
3410
+ }
3411
+ },
3412
+ {
3413
+ key: "clientLaunchId",
3414
+ type: "string",
3415
+ help: "An idempotency key of at most 128 characters; reuse it to recover the same launch.",
3416
+ range: {
3417
+ min: "1",
3418
+ max: "128",
3419
+ unit: "characters"
3420
+ },
3421
+ surfaces: {
3422
+ cli: {
3423
+ flag: "--client-trade-id",
3424
+ value: "<id>"
3425
+ },
3426
+ mcp: {
3427
+ key: "clientLaunchId"
3428
+ },
3429
+ sdk: {
3430
+ key: "clientLaunchId"
3431
+ }
3432
+ }
3433
+ },
3434
+ {
3435
+ key: "name",
3436
+ type: "string",
3437
+ help: "The token's name, at most 32 UTF-8 bytes.",
3438
+ required: true,
3439
+ range: {
3440
+ min: "1",
3441
+ max: "32",
3442
+ unit: "UTF-8 bytes"
3443
+ },
3444
+ surfaces: {
3445
+ cli: {
3446
+ flag: "--name",
3447
+ value: "<name>"
3448
+ },
3449
+ mcp: {
3450
+ key: "name"
3451
+ },
3452
+ sdk: {
3453
+ key: "name"
3454
+ }
3455
+ }
3456
+ },
3457
+ {
3458
+ key: "symbol",
3459
+ type: "string",
3460
+ help: "The token's ticker, at most 10 UTF-8 bytes.",
3461
+ required: true,
3462
+ range: {
3463
+ min: "1",
3464
+ max: "10",
3465
+ unit: "UTF-8 bytes"
3466
+ },
3467
+ surfaces: {
3468
+ cli: {
3469
+ flag: "--symbol",
3470
+ value: "<symbol>"
3471
+ },
3472
+ mcp: {
3473
+ key: "symbol"
3474
+ },
3475
+ sdk: {
3476
+ key: "symbol"
3477
+ }
3478
+ }
3479
+ },
3480
+ {
3481
+ key: "imageUrl",
3482
+ type: "url",
3483
+ help: "The roughly square token image at an https URL; --image <path> uploads a local file instead.",
3484
+ required: true,
3485
+ surfaces: {
3486
+ cli: {
3487
+ flag: "--image-url",
3488
+ value: "<https-url>"
3489
+ },
3490
+ mcp: {
3491
+ key: "imageUrl"
3492
+ },
3493
+ sdk: {
3494
+ key: "imageUrl"
3495
+ }
3496
+ }
3497
+ },
3498
+ {
3499
+ key: "bannerUrl",
3500
+ type: "url",
3501
+ help: "A wide banner at an https URL or a local file; uploads are public and permanent.",
3502
+ surfaces: {
3503
+ cli: {
3504
+ flag: "--banner",
3505
+ value: "<file|URL>"
3506
+ },
3507
+ mcp: {
3508
+ key: "bannerUrl"
3509
+ },
3510
+ sdk: {
3511
+ key: "bannerUrl"
3512
+ }
3513
+ }
3514
+ },
3515
+ {
3516
+ key: "description",
3517
+ type: "string",
3518
+ help: "The token's description, safe for on-chain JSON.",
3519
+ surfaces: {
3520
+ cli: {
3521
+ flag: "--description",
3522
+ value: "<text>"
3523
+ },
3524
+ mcp: {
3525
+ key: "description"
3526
+ },
3527
+ sdk: {
3528
+ key: "description"
3529
+ }
3530
+ }
3531
+ },
3532
+ {
3533
+ key: "socials.website",
3534
+ type: "url",
3535
+ help: "The token's website link as an absolute http(s) URL.",
3536
+ surfaces: {
3537
+ cli: {
3538
+ flag: "--website",
3539
+ value: "<url>"
3540
+ },
3541
+ mcp: {
3542
+ key: "socials.website"
3543
+ },
3544
+ sdk: {
3545
+ key: "socials.website"
3546
+ }
3547
+ }
3548
+ },
3549
+ {
3550
+ key: "socials.twitter",
3551
+ type: "url",
3552
+ help: "The token's X link as an absolute http(s) URL.",
3553
+ surfaces: {
3554
+ cli: {
3555
+ flag: "--x",
3556
+ value: "<url>"
3557
+ },
3558
+ mcp: {
3559
+ key: "socials.twitter"
3560
+ },
3561
+ sdk: {
3562
+ key: "socials.twitter"
3563
+ }
3564
+ }
3565
+ },
3566
+ {
3567
+ key: "socials.telegram",
3568
+ type: "url",
3569
+ help: "The token's telegram link as an absolute http(s) URL.",
3570
+ surfaces: {
3571
+ cli: {
3572
+ flag: "--telegram",
3573
+ value: "<url>"
3574
+ },
3575
+ mcp: {
3576
+ key: "socials.telegram"
3577
+ },
3578
+ sdk: {
3579
+ key: "socials.telegram"
3580
+ }
3581
+ }
3582
+ },
3583
+ {
3584
+ key: "socials.discord",
3585
+ type: "url",
3586
+ help: "The token's discord link as an absolute http(s) URL.",
3587
+ surfaces: {
3588
+ cli: {
3589
+ flag: "--discord",
3590
+ value: "<url>"
3591
+ },
3592
+ mcp: {
3593
+ key: "socials.discord"
3594
+ },
3595
+ sdk: {
3596
+ key: "socials.discord"
3597
+ }
3598
+ }
3599
+ },
3600
+ {
3601
+ key: "chain",
3602
+ type: "enum",
3603
+ values: [
3604
+ "solana",
3605
+ "hood"
3606
+ ],
3607
+ default: "solana",
3608
+ help: "The launch chain, inferred from the wallet, quote asset and dex version on the CLI.",
3609
+ surfaces: {
3610
+ cli: {
3611
+ derived: "wallet, --quote-asset and --dex-version"
3612
+ },
3613
+ mcp: {
3614
+ key: "chain"
3615
+ },
3616
+ sdk: {
3617
+ key: "chain"
3618
+ }
3619
+ }
3620
+ },
3621
+ {
3622
+ key: "quoteAsset",
3623
+ type: "enum",
3624
+ help: "The quote asset: sol, usdc or cndl on Solana; eth or usdg on Hood (defaults sol and eth).",
3625
+ values: [
3626
+ "sol",
3627
+ "usdc",
3628
+ "cndl",
3629
+ "eth",
3630
+ "usdg"
3631
+ ],
3632
+ surfaces: {
3633
+ cli: {
3634
+ flag: "--quote-asset",
3635
+ value: "sol|usdc|cndl|eth|usdg"
3636
+ },
3637
+ mcp: {
3638
+ key: "quoteAsset"
3639
+ },
3640
+ sdk: {
3641
+ key: "quoteAsset"
3642
+ }
3643
+ }
3644
+ },
3645
+ {
3646
+ key: "mode",
3647
+ type: "enum",
3648
+ help: "The curve mode: open or exclusive; test-open or test-exclusive need ENABLE_TEST_CURVES; exp-a, exp-b, exp-c and exp-custom are Solana sol/cndl only.",
3649
+ values: [
3650
+ "open",
3651
+ "exclusive",
3652
+ "test-open",
3653
+ "test-exclusive",
3654
+ "exp-a",
3655
+ "exp-b",
3656
+ "exp-c",
3657
+ "exp-custom"
3658
+ ],
3659
+ default: "open",
3660
+ surfaces: {
3661
+ cli: {
3662
+ flag: "--mode",
3663
+ value: "<mode>"
3664
+ },
3665
+ mcp: {
3666
+ key: "mode"
3667
+ },
3668
+ sdk: {
3669
+ key: "mode"
3670
+ }
3671
+ }
3672
+ },
3673
+ {
3674
+ key: "curve.virtualQuote",
3675
+ type: "decimal",
3676
+ help: "exp-custom's virtual quote, in whole quote units: 1 to 100 SOL or 66000 to 6600000 CNDL; requires --curve-g and EXP_CUSTOM_CURVES.",
3677
+ modes: [
3678
+ "exp-custom"
3679
+ ],
3680
+ chains: [
3681
+ "solana"
3682
+ ],
3683
+ requires: [
3684
+ "curve.threshold"
3685
+ ],
3686
+ range: {
3687
+ unit: "whole quote units",
3688
+ byQuote: {
3689
+ sol: {
3690
+ min: "1",
3691
+ max: "100"
3692
+ },
3693
+ cndl: {
3694
+ min: "66000",
3695
+ max: "6600000"
3696
+ }
3697
+ }
3698
+ },
3699
+ surfaces: {
3700
+ cli: {
3701
+ flag: "--curve-v",
3702
+ value: "<V>"
3703
+ },
3704
+ mcp: {
3705
+ key: "curve.virtualQuote"
3706
+ },
3707
+ sdk: {
3708
+ key: "curve.virtualQuote"
3709
+ }
3710
+ }
3711
+ },
3712
+ {
3713
+ key: "curve.threshold",
3714
+ type: "decimal",
3715
+ help: "exp-custom's graduation threshold, in whole quote units: 1 to 250 SOL or 66000 to 16500000 CNDL; requires --curve-v and EXP_CUSTOM_CURVES.",
3716
+ modes: [
3717
+ "exp-custom"
3718
+ ],
3719
+ chains: [
3720
+ "solana"
3721
+ ],
3722
+ requires: [
3723
+ "curve.virtualQuote"
3724
+ ],
3725
+ range: {
3726
+ unit: "whole quote units",
3727
+ byQuote: {
3728
+ sol: {
3729
+ min: "1",
3730
+ max: "250"
3731
+ },
3732
+ cndl: {
3733
+ min: "66000",
3734
+ max: "16500000"
3735
+ }
3736
+ }
3737
+ },
3738
+ surfaces: {
3739
+ cli: {
3740
+ flag: "--curve-g",
3741
+ value: "<G>"
3742
+ },
3743
+ mcp: {
3744
+ key: "curve.threshold"
3745
+ },
3746
+ sdk: {
3747
+ key: "curve.threshold"
3748
+ }
3749
+ }
3750
+ },
3751
+ {
3752
+ key: "creatorFeeBps",
3753
+ type: "enum",
3754
+ help: "An exp- mode's extra creator fee: 0, 100 or 200 bps on the curve and pool, paid to the creator in full.",
3755
+ values: [
3756
+ 0,
3757
+ 100,
3758
+ 200
3759
+ ],
3760
+ default: 0,
3761
+ surfaces: {
3762
+ cli: {
3763
+ flag: "--creator-fee-bps",
3764
+ value: "0|100|200"
3765
+ },
3766
+ mcp: {
3767
+ key: "creatorFeeBps"
3768
+ },
3769
+ sdk: {
3770
+ key: "creatorFeeBps"
3771
+ }
3772
+ }
3773
+ },
3774
+ {
3775
+ key: "stakerAllocationBps",
3776
+ type: "integer",
3777
+ help: "The staker allocation, 50 to 1000 bps; defaults to 50, or 500 on exp- curves.",
3778
+ range: {
3779
+ min: "50",
3780
+ max: "1000",
3781
+ unit: "bps"
3782
+ },
3783
+ default: 50,
3784
+ surfaces: {
3785
+ cli: {
3786
+ flag: "--staker-allocation-bps",
3787
+ value: "<bps>"
3788
+ },
3789
+ mcp: {
3790
+ key: "stakerAllocationBps"
3791
+ },
3792
+ sdk: {
3793
+ key: "stakerAllocationBps"
3794
+ }
3795
+ }
3796
+ },
3797
+ {
3798
+ key: "poolFee.tier",
3799
+ type: "enum",
3800
+ help: "Solana's graduated pool fee: 25, 50 or 100 bps (default 50), or the ending rate with --pool-fee-from.",
3801
+ values: [
3802
+ 25,
3803
+ 50,
3804
+ 100
3805
+ ],
3806
+ default: 50,
3807
+ chains: [
3808
+ "solana"
3809
+ ],
3810
+ surfaces: {
3811
+ cli: {
3812
+ flag: "--pool-fee",
3813
+ value: "25|50|100"
3814
+ },
3815
+ mcp: {
3816
+ key: "poolFee.tier"
3817
+ },
3818
+ sdk: {
3819
+ key: "poolFee.tier"
3820
+ }
3821
+ }
3822
+ },
3823
+ {
3824
+ key: "poolFee.startBps",
3825
+ type: "integer",
3826
+ help: "The falling pool fee's starting rate, at most 2500 bps; requires --pool-fee and --pool-fee-minutes.",
3827
+ range: {
3828
+ min: "25",
3829
+ max: "2500",
3830
+ unit: "bps"
3831
+ },
3832
+ chains: [
3833
+ "solana"
3834
+ ],
3835
+ requires: [
3836
+ "poolFee.tier",
3837
+ "poolFee.minutes"
3838
+ ],
3839
+ surfaces: {
3840
+ cli: {
3841
+ flag: "--pool-fee-from",
3842
+ value: "<bps>"
3843
+ },
3844
+ mcp: {
3845
+ key: "poolFee.startBps"
3846
+ },
3847
+ sdk: {
3848
+ key: "poolFee.startBps"
3849
+ }
3850
+ }
3851
+ },
3852
+ {
3853
+ key: "poolFee.minutes",
3854
+ type: "decimal",
3855
+ help: "The pool fee's fall time, at most 30 minutes; requires --pool-fee and --pool-fee-from.",
3856
+ wireType: "number",
3857
+ range: {
3858
+ min: "0.006666666666666667",
3859
+ max: "30",
3860
+ unit: "minutes"
3861
+ },
3862
+ chains: [
3863
+ "solana"
3864
+ ],
3865
+ requires: [
3866
+ "poolFee.tier",
3867
+ "poolFee.startBps"
3868
+ ],
3869
+ surfaces: {
3870
+ cli: {
3871
+ flag: "--pool-fee-minutes",
3872
+ value: "<min>"
3873
+ },
3874
+ mcp: {
3875
+ key: "poolFee.minutes"
3876
+ },
3877
+ sdk: {
3878
+ key: "poolFee.minutes"
3879
+ }
3880
+ }
3881
+ },
3882
+ {
3883
+ key: "poolFee.endBps",
3884
+ type: "enum",
3885
+ values: [
3886
+ 25,
3887
+ 50,
3888
+ 100
3889
+ ],
3890
+ chains: [
3891
+ "solana"
3892
+ ],
3893
+ help: "The falling fee's ending rate, taken from --pool-fee.",
3894
+ surfaces: {
3895
+ cli: {
3896
+ derived: "--pool-fee with --pool-fee-from"
3897
+ },
3898
+ mcp: {
3899
+ key: "poolFee.endBps"
3900
+ },
3901
+ sdk: {
3902
+ key: "poolFee.endBps"
3903
+ }
3904
+ }
3905
+ },
3906
+ {
3907
+ key: "poolOpen",
3908
+ type: "enum",
3909
+ help: "Solana preset pools: curve_price opens at the curve's last price and burns the rest; omitted uses curve_price when allocations fit graduation.maxStakerCarveBps, otherwise legacy; explicit curve_price above that limit is refused.",
3910
+ values: [
3911
+ "legacy",
3912
+ "curve_price"
3913
+ ],
3914
+ chains: [
3915
+ "solana"
3916
+ ],
3917
+ surfaces: {
3918
+ cli: {
3919
+ flag: "--pool-open",
3920
+ value: "legacy|curve_price"
3921
+ },
3922
+ mcp: {
3923
+ key: "poolOpen"
3924
+ },
3925
+ sdk: {
3926
+ key: "poolOpen"
3927
+ }
3928
+ }
3929
+ },
3930
+ {
3931
+ key: "expPoolShape",
3932
+ type: "enum",
3933
+ help: "Solana exp- pools: floor by default, or full_range to open across the whole price range.",
3934
+ values: [
3935
+ "floor",
3936
+ "full_range"
3937
+ ],
3938
+ default: "floor",
3939
+ chains: [
3940
+ "solana"
3941
+ ],
3942
+ surfaces: {
3943
+ cli: {
3944
+ flag: "--exp-pool-shape",
3945
+ value: "floor|full_range"
3946
+ },
3947
+ mcp: {
3948
+ key: "expPoolShape"
3949
+ },
3950
+ sdk: {
3951
+ key: "expPoolShape"
3952
+ }
3953
+ }
3954
+ },
3955
+ {
3956
+ key: "dexVersion",
3957
+ type: "enum",
3958
+ help: "Hood only, required there: the Uniswap version the curve graduates to.",
3959
+ values: [
3960
+ "v3",
3961
+ "v4"
3962
+ ],
3963
+ chains: [
3964
+ "hood"
3965
+ ],
3966
+ surfaces: {
3967
+ cli: {
3968
+ flag: "--dex-version",
3969
+ value: "v3|v4"
3970
+ },
3971
+ mcp: {
3972
+ key: "dexVersion"
3973
+ },
3974
+ sdk: {
3975
+ key: "dexVersion"
3976
+ }
3977
+ }
3978
+ },
3979
+ {
3980
+ key: "visibility",
3981
+ type: "enum",
3982
+ help: "The token's visibility: production, test, local or hidden; test keys require test or hidden.",
3983
+ values: [
3984
+ "production",
3985
+ "test",
3986
+ "local",
3987
+ "hidden"
3988
+ ],
3989
+ default: "production",
3990
+ surfaces: {
3991
+ cli: {
3992
+ flag: "--visibility",
3993
+ value: "production|test|local|hidden"
3994
+ },
3995
+ mcp: {
3996
+ key: "visibility"
3997
+ },
3998
+ sdk: {
3999
+ key: "visibility"
4000
+ }
4001
+ }
4002
+ },
4003
+ {
4004
+ key: "buy",
4005
+ type: "decimal",
4006
+ help: "An optional first buy in whole quote units; zero or empty means no buy, and the server applies dev-buy ceilings and TEE_LAUNCH_BUYS_ENABLED for TEE buys.",
4007
+ default: "0",
4008
+ range: {
4009
+ min: "0",
4010
+ unit: "whole quote units"
4011
+ },
4012
+ more: "Default raw caps (apps/api/src/lib/headless-validation.ts): DEV_BUY_MAX_LAMPORTS=500000000, DEV_BUY_MAX_USDC_RAW=500000000, DEV_BUY_MAX_CNDL_RAW=2000000000000, DEV_BUY_MAX_WEI=20000000000000000. On exp- curves the lower of the quote cap and 10% of G applies.",
4013
+ surfaces: {
4014
+ cli: {
4015
+ flag: "--buy",
4016
+ value: "<amount>"
4017
+ },
4018
+ mcp: {
4019
+ key: "buy"
4020
+ },
4021
+ sdk: {
4022
+ key: "buy"
4023
+ }
4024
+ }
4025
+ },
4026
+ {
4027
+ key: "dryRun",
4028
+ type: "boolean",
4029
+ help: "Print the launch preview without building, signing or recording a launch; local image uploads still become public and permanent.",
4030
+ default: false,
4031
+ surfaces: {
4032
+ cli: {
4033
+ flag: "--dry-run"
4034
+ },
4035
+ mcp: {
4036
+ key: "dryRun"
4037
+ },
4038
+ sdk: {
4039
+ key: "dryRun"
4040
+ }
4041
+ }
4042
+ }
4043
+ ]
4044
+ };
4045
+
4046
+ // src/launch-input.ts
4047
+ function embeddedLaunchWallet(wallet) {
4048
+ return wallet === undefined || typeof wallet === "string" && LAUNCH_DEFINITION.wallet.embeddedNames.includes(wallet);
4049
+ }
4050
+ function launchInputError(field, message, code = "VALIDATION_FAILED") {
4051
+ return new CandleApiError({ status: 400, code, field, message, retryable: false });
4052
+ }
4053
+ function validateLaunchInput(req) {
4054
+ if (req.buy !== undefined && req.buyAmount !== undefined)
4055
+ throw launchInputError("buy", "Pass buy or the deprecated buyAmount, never both.");
4056
+ if (req.wallet !== undefined && "linkedWalletId" in req)
4057
+ throw launchInputError("wallet", "Pass wallet without the legacy linkedWalletId field.");
4058
+ if (req.wallet !== undefined && typeof req.wallet !== "string" && (!req.wallet || typeof req.wallet.linkedWalletId !== "string" || !req.wallet.linkedWalletId || typeof req.wallet.privyWalletId !== "string" || !req.wallet.privyWalletId))
4059
+ throw launchInputError("wallet", "wallet needs linkedWalletId and privyWalletId.");
4060
+ if (req.buy !== undefined && (typeof req.buy !== "string" || req.buy.trim() !== "" && !/^\d+(\.\d+)?$/.test(req.buy)))
4061
+ throw launchInputError("buy", "buy must be a non-negative decimal string in whole quote units.");
4062
+ const keys = LAUNCH_DEFINITION.fields.filter((field) => field.key.startsWith("socials.")).map((field) => field.key.slice(8));
4063
+ if (req.socials !== undefined) {
4064
+ if (!req.socials || typeof req.socials !== "object" || Array.isArray(req.socials))
4065
+ throw launchInputError("socials", `socials accepts only ${keys.join(", ")}.`);
4066
+ for (const [key, value] of Object.entries(req.socials)) {
4067
+ if (!keys.includes(key))
4068
+ throw launchInputError("socials", `socials accepts only ${keys.join(", ")}.`);
4069
+ if (value === undefined)
4070
+ continue;
4071
+ try {
4072
+ if (typeof value !== "string")
4073
+ throw new Error;
4074
+ const url = new URL(value);
4075
+ if (!["http:", "https:"].includes(url.protocol))
4076
+ throw new Error;
4077
+ } catch {
4078
+ throw launchInputError(`socials.${key}`, `${key} must be an http(s) URL.`);
4079
+ }
4080
+ }
4081
+ }
4082
+ if (req.quoteAsset !== undefined || req.chain !== undefined || embeddedLaunchWallet(req.wallet))
4083
+ launchBody(req);
4084
+ }
4085
+ function launchBody(req, chain) {
4086
+ const { wallet: _wallet, buy, ...body } = req;
4087
+ if (chain !== undefined)
4088
+ body.chain = chain;
4089
+ const quote = body.quoteAsset ?? LAUNCH_DEFINITION.defaultQuote[body.chain ?? "solana"];
4090
+ const quoteChain = LAUNCH_DEFINITION.quoteChains[quote];
4091
+ if (!quoteChain)
4092
+ throw launchInputError("quoteAsset", "Unsupported launch quote asset.");
4093
+ if (body.chain !== undefined && body.chain !== quoteChain)
4094
+ throw launchInputError("quoteAsset", "The quote asset disagrees with the launch chain.", "CHAIN_MISMATCH");
4095
+ if (buy === undefined || buy.trim() === "" || /^0+(\.0+)?$/.test(buy))
4096
+ return body;
4097
+ const decimals = LAUNCH_DEFINITION.quoteDecimals[quote];
4098
+ const [whole = "0", fraction = ""] = buy.split(".");
4099
+ if (fraction.length > decimals)
4100
+ throw launchInputError("buy", `buy allows at most ${decimals} decimals for ${quote}.`);
4101
+ const raw = BigInt(whole) * 10n ** BigInt(decimals) + BigInt(fraction.padEnd(decimals, "0"));
4102
+ if (raw === 0n)
4103
+ return body;
4104
+ if (quoteChain === "solana" && raw > BigInt(Number.MAX_SAFE_INTEGER))
4105
+ throw launchInputError("buy", "buy exceeds the safe integer range for this quote asset.");
4106
+ body.buyAmount = quoteChain === "solana" ? Number(raw) : String(raw);
4107
+ return body;
4108
+ }
4109
+
3321
4110
  // src/perps-history.ts
3322
4111
  var PERPS_HISTORY_INFO_URLS = {
3323
4112
  mainnet: "https://api.hyperliquid.xyz/info",
@@ -4126,12 +4915,54 @@ class CandleClient {
4126
4915
  }
4127
4916
  async dryRunLaunch(req) {
4128
4917
  this.requireKey("dryRunLaunch()");
4129
- return this.requestJson("POST", "/api/v1/launch/headless/dry-run", req);
4918
+ const { body, wallet } = await this.prepareLaunch(req);
4919
+ return wallet ? this.dryRunSelfLaunch({ ...body, linkedWalletId: wallet.linkedWalletId }) : this.requestJson("POST", "/api/v1/launch/headless/dry-run", body);
4920
+ }
4921
+ async prepareLaunch(req) {
4922
+ validateLaunchInput(req);
4923
+ let wallet;
4924
+ let chain = req.chain;
4925
+ if (typeof req.wallet === "object") {
4926
+ wallet = req.wallet;
4927
+ } else if (typeof req.wallet === "string" && !embeddedLaunchWallet(req.wallet)) {
4928
+ const rows = [];
4929
+ const cursors = new Set;
4930
+ let cursor;
4931
+ while (true) {
4932
+ const page = await this.requestJson("GET", `/api/v1/agent/wallets/trading${cursor ? `?cursor=${encodeURIComponent(cursor)}` : ""}`);
4933
+ rows.push(...page.page);
4934
+ if (page.isDone === true)
4935
+ break;
4936
+ if (!page.continueCursor || cursors.has(page.continueCursor))
4937
+ throw launchInputError("wallet", "Wallet discovery did not complete.");
4938
+ cursor = page.continueCursor;
4939
+ cursors.add(cursor);
4940
+ }
4941
+ const matches = rows.filter((row2) => row2.id === req.wallet || row2.label === req.wallet || (row2.chain === "evm" ? row2.address.toLowerCase() === String(req.wallet).toLowerCase() : row2.address === req.wallet));
4942
+ if (matches.length !== 1) {
4943
+ const choices = (matches.length ? matches : rows).map((row2) => `${row2.label ?? row2.id} (${row2.id}, ${row2.address})`).join("; ");
4944
+ throw launchInputError("wallet", `Name one TEE wallet by label, id or address. Matches: ${choices || "none"}.`, "TEE_WALLET_REQUIRED");
4945
+ }
4946
+ const row = matches[0];
4947
+ if (!row.privyWalletId)
4948
+ throw launchInputError("wallet", "The wallet has no signing identifier.", "SIGNER_UNAVAILABLE");
4949
+ const walletChain = row.chain === "solana" ? "solana" : row.chain === "evm" ? "hood" : undefined;
4950
+ if (!walletChain)
4951
+ throw launchInputError("wallet", "The wallet chain is unsupported.", "CHAIN_MISMATCH");
4952
+ if (chain !== undefined && chain !== walletChain)
4953
+ throw launchInputError("chain", "The launch chain disagrees with the named wallet.", "CHAIN_MISMATCH");
4954
+ chain = walletChain;
4955
+ wallet = { linkedWalletId: row.id, privyWalletId: row.privyWalletId };
4956
+ }
4957
+ return { body: launchBody(req, chain), wallet };
4130
4958
  }
4131
4959
  async launch(req) {
4132
4960
  this.requireKey("launch()");
4961
+ const prepared = await this.prepareLaunch(req);
4962
+ if (prepared.wallet)
4963
+ return this.selfLaunch({ ...prepared.body, ...prepared.wallet });
4133
4964
  const clientLaunchId = req.clientLaunchId ?? generateClientLaunchId();
4134
- const body = { ...req, clientLaunchId };
4965
+ const body = { ...prepared.body, clientLaunchId };
4135
4966
  return this.runOperation({ clientLaunchId }, "server-executed", async (op) => {
4136
4967
  let lastError;
4137
4968
  for (let attempt = 0;attempt <= this.maxRetries; attempt++) {
@@ -4151,8 +4982,11 @@ class CandleClient {
4151
4982
  }
4152
4983
  async launchAsync(req) {
4153
4984
  this.requireKey("launchAsync()");
4985
+ validateLaunchInput(req);
4986
+ if (!embeddedLaunchWallet(req.wallet))
4987
+ throw launchInputError("wallet", "launchAsync() supports embedded launches; use launch() for a TEE wallet.");
4154
4988
  const clientLaunchId = req.clientLaunchId ?? generateClientLaunchId();
4155
- const body = { ...req, clientLaunchId, async: true };
4989
+ const body = { ...launchBody(req), clientLaunchId, async: true };
4156
4990
  return this.runOperation({ clientLaunchId }, "server-executed", async (op) => {
4157
4991
  const accepted = await this.requestJson("POST", "/api/v1/launch/headless", body, op);
4158
4992
  return { ...accepted, clientLaunchId: accepted.clientLaunchId ?? clientLaunchId };
@@ -5655,7 +6489,7 @@ function generateClientLaunchId() {
5655
6489
  function generateClientTradeId() {
5656
6490
  return generateSdkId();
5657
6491
  }
5658
- var SDK_VERSION = "0.6.6";
6492
+ var SDK_VERSION = "0.6.8";
5659
6493
  var sdkUpdateWarned = false;
5660
6494
  function noteLatestSdkVersion(value) {
5661
6495
  if (sdkUpdateWarned || !value || !/^\d+\.\d+\.\d+$/.test(value))