@interest-protocol/blast-migrators-sdk 0.1.1 → 0.2.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.
Files changed (46) hide show
  1. package/dist/aborts.d.ts +12 -0
  2. package/dist/aborts.d.ts.map +1 -0
  3. package/dist/aborts.js +21 -0
  4. package/dist/aborts.js.map +1 -0
  5. package/dist/client.d.ts +8 -11
  6. package/dist/client.d.ts.map +1 -1
  7. package/dist/client.js +12 -14
  8. package/dist/client.js.map +1 -1
  9. package/dist/events.d.ts +30 -160
  10. package/dist/events.d.ts.map +1 -1
  11. package/dist/events.js +33 -168
  12. package/dist/events.js.map +1 -1
  13. package/dist/index.d.ts +1 -3
  14. package/dist/index.d.ts.map +1 -1
  15. package/dist/index.js +1 -3
  16. package/dist/index.js.map +1 -1
  17. package/dist/reducer.d.ts +20 -132
  18. package/dist/reducer.d.ts.map +1 -1
  19. package/dist/reducer.js +28 -361
  20. package/dist/reducer.js.map +1 -1
  21. package/dist/state.d.ts +32 -152
  22. package/dist/state.d.ts.map +1 -1
  23. package/dist/state.js +61 -167
  24. package/dist/state.js.map +1 -1
  25. package/dist/transactions.d.ts +204 -259
  26. package/dist/transactions.d.ts.map +1 -1
  27. package/dist/transactions.js +347 -449
  28. package/dist/transactions.js.map +1 -1
  29. package/package.json +7 -10
  30. package/src/aborts.ts +24 -0
  31. package/src/client.ts +19 -34
  32. package/src/events.ts +54 -261
  33. package/src/index.ts +1 -3
  34. package/src/reducer.ts +46 -538
  35. package/src/state.ts +88 -282
  36. package/src/transactions.ts +569 -838
  37. package/dist/bluefin-pool.d.ts +0 -57
  38. package/dist/bluefin-pool.d.ts.map +0 -1
  39. package/dist/bluefin-pool.js +0 -102
  40. package/dist/bluefin-pool.js.map +0 -1
  41. package/dist/cetus-pool.d.ts +0 -44
  42. package/dist/cetus-pool.d.ts.map +0 -1
  43. package/dist/cetus-pool.js +0 -57
  44. package/dist/cetus-pool.js.map +0 -1
  45. package/src/bluefin-pool.ts +0 -180
  46. package/src/cetus-pool.ts +0 -107
@@ -1,45 +1,20 @@
1
- import type { CoinSourceOptions } from "@interest-protocol/blast-core/coins";
1
+ import { AdminCalls } from "@interest-protocol/blast-admin-sdk/transactions";
2
+ import { cetusMemeSide } from "@interest-protocol/blast-core/cetus";
2
3
  import { grossGasBudget } from "@interest-protocol/blast-core/gas";
3
4
  import {
4
5
  requirePositiveU64,
5
6
  requireU64,
7
+ requireU128,
6
8
  } from "@interest-protocol/blast-core/integers";
7
- import {
8
- deploymentObject,
9
- moveResults,
10
- } from "@interest-protocol/blast-core/ptb";
11
- import type {
12
- RewardManifest,
13
- RewardProof,
14
- } from "@interest-protocol/blast-core/rewards/allocations";
15
- import {
16
- MIGRATOR_REWARD_LEAF_DOMAIN,
17
- rewardAddress,
18
- rewardDigest,
19
- validateRewardManifest,
20
- } from "@interest-protocol/blast-core/rewards/allocations";
21
- import type {
22
- SharedObjectIdentity,
23
- SharedObjectReference,
24
- } from "@interest-protocol/blast-core/sui";
9
+ import { deploymentObject } from "@interest-protocol/blast-core/ptb";
10
+ import { coreRoleType } from "@interest-protocol/blast-core/roles";
11
+ import type { SharedObjectIdentity } from "@interest-protocol/blast-core/sui";
25
12
  import {
26
13
  normalizeSharedObjectIdentity,
27
- normalizeSharedObjectReference,
28
14
  normalizeSuiPackageReference,
29
15
  } from "@interest-protocol/blast-core/sui";
30
- import type { FeeSplit } from "@interest-protocol/blast-launchpad-sdk/allocation";
31
- import type {
32
- BlastFunAdminRole,
33
- LaunchpadDeployment,
34
- LaunchSettings,
35
- LaunchTypes,
36
- PreShareBuyInput,
37
- } from "@interest-protocol/blast-launchpad-sdk/transactions";
38
- import {
39
- addLaunchCompletion,
40
- LaunchpadCalls,
41
- normalizeLaunchTypes,
42
- } from "@interest-protocol/blast-launchpad-sdk/transactions";
16
+ import type { VaultDeployment } from "@interest-protocol/blast-vault-sdk/transactions";
17
+ import { normalizeVaultDeployment } from "@interest-protocol/blast-vault-sdk/transactions";
43
18
  import type {
44
19
  TransactionArgument,
45
20
  TransactionObjectArgument,
@@ -47,189 +22,291 @@ import type {
47
22
  TransactionResult,
48
23
  } from "@mysten/sui/transactions";
49
24
  import { Transaction } from "@mysten/sui/transactions";
50
- import { normalizeStructTag, normalizeSuiAddress } from "@mysten/sui/utils";
51
- import type { MigratorVenue } from "./state.ts";
25
+ import { normalizeStructTag } from "@mysten/sui/utils";
52
26
 
53
27
  /**
54
- * The vault's partner, when `LpVaultState.partnerId` is set: the collection
55
- * then pays it and Blast the LP fees the vault held.
28
+ * The product-agnostic `blast_migrators` package: its shared
29
+ * `PackageVersion<BLAST_MIGRATORS>`, `PackageAdmin<BLAST_MIGRATORS>` and
30
+ * `venue_config::VenueConfig`, and the vault deployment (with core and admin)
31
+ * every venue call reads.
56
32
  */
57
- export type LpFeePartner = {
58
- partner?: SharedObjectReference<false> | null;
59
- };
60
-
61
33
  export type MigratorsDeployment = {
62
34
  packageId: string;
63
35
  originalPackageId: string;
64
- launchpad: LaunchpadDeployment;
65
- /** Migrators `blast_fun_migrators::PackageVersion` checked by every protected entry. */
66
- migratorsVersion: SharedObjectIdentity;
67
- /** Migrators `lp_fee_policy::LpFeePolicy` read by every LP-fee collection. */
68
- lpFeePolicy: SharedObjectIdentity;
69
- /** Migrators `venue_config::VenueConfig`, holding each Meme's Cetus `PoolCreationCap`. */
36
+ packageVersion: SharedObjectIdentity;
37
+ packageAdmin: SharedObjectIdentity;
70
38
  venueConfig: SharedObjectIdentity;
39
+ vault: VaultDeployment;
40
+ };
41
+
42
+ /** The venues `blast_migrators` defines, one module each. */
43
+ export const MIGRATOR_VENUES = ["bluefin", "cetus"] as const;
44
+ export type MigratorVenue = (typeof MIGRATOR_VENUES)[number];
45
+
46
+ /** `constants::bluefin_max_tick_spacing`: Bluefin pool creation's own bound. */
47
+ export const BLUEFIN_MAX_TICK_SPACING = 400;
48
+
49
+ /** `constants::bluefin_max_fee_rate`: Bluefin pool creation's own bound (1,000,000 is 100%). */
50
+ export const BLUEFIN_MAX_FEE_RATE = 20_000n;
51
+
52
+ export function normalizeMigratorsDeployment(
53
+ deployment: MigratorsDeployment,
54
+ ): MigratorsDeployment {
55
+ return {
56
+ ...normalizeSuiPackageReference("migrators", deployment),
57
+ packageVersion: normalizeSharedObjectIdentity(
58
+ "migrators.packageVersion",
59
+ deployment.packageVersion,
60
+ ),
61
+ packageAdmin: normalizeSharedObjectIdentity(
62
+ "migrators.packageAdmin",
63
+ deployment.packageAdmin,
64
+ ),
65
+ venueConfig: normalizeSharedObjectIdentity(
66
+ "migrators.venueConfig",
67
+ deployment.venueConfig,
68
+ ),
69
+ vault: normalizeVaultDeployment(deployment.vault),
70
+ };
71
+ }
72
+
73
+ /**
74
+ * `<migrators original>::<venue>::Venue`: the witness a venue seals tickets
75
+ * and redeems migrations under, and that a product and the vault registry
76
+ * admit.
77
+ */
78
+ export function venueWitnessType(
79
+ migrators: Pick<MigratorsDeployment, "originalPackageId">,
80
+ venue: MigratorVenue,
81
+ ): string {
82
+ if (!MIGRATOR_VENUES.includes(venue))
83
+ throw new TypeError(`unknown migrators venue ${String(venue)}`);
84
+ return normalizeStructTag(`${migrators.originalPackageId}::${venue}::Venue`);
85
+ }
86
+
87
+ /**
88
+ * The migrators venue a `Launch.venue` or `Presale.venue` `TypeName`
89
+ * (original-ID form) names, or null for any other venue.
90
+ */
91
+ export function venueOf(
92
+ migrators: Pick<MigratorsDeployment, "originalPackageId">,
93
+ typeName: string,
94
+ ): MigratorVenue | null {
95
+ const type = normalizeStructTag(typeName);
96
+ return (
97
+ MIGRATOR_VENUES.find(
98
+ (venue) => venueWitnessType(migrators, venue) === type,
99
+ ) ?? null
100
+ );
101
+ }
102
+
103
+ /** A vault's `Meme` and `Quote`; pass original (defining) type addresses. */
104
+ type PairTypes = { memeType: string; quoteType: string };
105
+
106
+ /** The Cetus `config::GlobalConfig` and LP Burn `lp_burn::BurnManager` fee routes read. */
107
+ type CetusFeeObjects = {
108
+ config: SharedObjectIdentity;
109
+ burnManager: SharedObjectIdentity;
71
110
  };
72
111
 
73
- import type { CetusMemeSide } from "@interest-protocol/blast-core/cetus";
112
+ /**
113
+ * One Cetus vault: `vault` is the `Vault<Meme, Quote>` and `pool` its own
114
+ * `Pool<CoinA, CoinB>`; `currency` is the Meme's Coin Registry
115
+ * `Currency<Meme>`, which the burn route burns through.
116
+ */
117
+ type CetusVaultInput = PairTypes & {
118
+ vault: SharedObjectIdentity;
119
+ currency: SharedObjectIdentity;
120
+ cetus: CetusFeeObjects;
121
+ pool: SharedObjectIdentity;
122
+ };
74
123
 
75
- export type { CetusMemeSide } from "@interest-protocol/blast-core/cetus";
124
+ /** One Bluefin vault: its `Vault<Meme, Quote>`, `Pool<Meme, Quote>` and `Currency<Meme>`. */
125
+ type BluefinVaultInput = PairTypes & {
126
+ vault: SharedObjectIdentity;
127
+ currency: SharedObjectIdentity;
128
+ bluefinConfig: SharedObjectIdentity;
129
+ pool: SharedObjectIdentity;
130
+ };
76
131
 
77
- /** The Cetus CLMM `config::GlobalConfig` every Cetus route reads. */
78
- export type CetusObjects = {
79
- /** Cetus CLMM `config::GlobalConfig`. */
80
- cetusConfig: SharedObjectReference<false>;
132
+ /** A Cetus vault's auto-LP compounding inputs: the vault, Cetus's config and the pool. */
133
+ type CetusCompoundInput = PairTypes & {
134
+ vault: SharedObjectIdentity;
135
+ cetus: { config: SharedObjectIdentity };
136
+ pool: SharedObjectIdentity;
81
137
  };
82
138
 
83
- /** Settings for starting a launch through an adapter in one transaction. */
84
- export type CreateLaunchOptions = LaunchTypes &
85
- LaunchSettings &
86
- CoinSourceOptions & {
87
- /** The `LaunchTicket<Meme>` the generated package's initializer transferred to its publisher. */
88
- ticket: TransactionObjectInput;
89
- /** The Meme `Currency<Meme>` in the Coin Registry, fixed at finalization. */
90
- memeCurrency: SharedObjectReference<true>;
91
- /** `LaunchConfig.creation_fee` in MIST, paid as an exact SUI coin. */
92
- creationFee: bigint;
93
- preShareBuy?: PreShareBuyInput;
94
- };
139
+ /** A Bluefin vault's auto-LP compounding inputs: the vault, Bluefin's config and the pool. */
140
+ type BluefinCompoundInput = PairTypes & {
141
+ vault: SharedObjectIdentity;
142
+ bluefinConfig: SharedObjectIdentity;
143
+ pool: SharedObjectIdentity;
144
+ };
95
145
 
96
- /** Maximum Merkle proof depth the holder-reward leaf count (65,536) allows. */
97
- export const MAX_HOLDER_REWARD_PROOF_DEPTH = 16;
146
+ /** A buyback's admin witness and swap bounds; `quoteIn` is atomic Quote. */
147
+ type BuybackInput = {
148
+ adminWitness: TransactionObjectInput;
149
+ quoteIn: bigint;
150
+ minMemeOut: bigint;
151
+ };
98
152
 
153
+ /**
154
+ * `blast_migrators` venue calls, in Move argument order; `&mut TxContext` is
155
+ * implicit and the `Clock` is `0x6`. The migrators and vault package
156
+ * versions, the `VenueConfig`, the `VaultRegistry` and the core treasury
157
+ * come from the deployment. `prepare*` return the `VenueTicket<Meme, Quote>`
158
+ * the product's `new` consumes; `migrate*` consume the product's
159
+ * `Migration<Meme, Quote>` in the same PTB. Cetus calls take
160
+ * `<Meme, Quote, CoinA, CoinB>` with the pool's coin order from
161
+ * `cetusMemeSide`, so pass original (defining) type addresses.
162
+ */
99
163
  export class MigratorCalls {
100
164
  readonly deployment: MigratorsDeployment;
101
- readonly launchpad: LaunchpadCalls;
165
+ /** `blast_migrators::BLAST_MIGRATORS`, the package's OTW. */
166
+ readonly otw: string;
102
167
 
103
168
  constructor(deployment: MigratorsDeployment) {
104
- this.launchpad = new LaunchpadCalls(deployment.launchpad);
105
- this.deployment = {
106
- ...normalizeSuiPackageReference("migrators", deployment),
107
- launchpad: this.launchpad.deployment,
108
- migratorsVersion: normalizeSharedObjectIdentity(
109
- "migratorsVersion",
110
- deployment.migratorsVersion,
111
- ),
112
- lpFeePolicy: normalizeSharedObjectIdentity(
113
- "lpFeePolicy",
114
- deployment.lpFeePolicy,
115
- ),
116
- venueConfig: normalizeSharedObjectIdentity(
117
- "venueConfig",
118
- deployment.venueConfig,
119
- ),
120
- };
121
- }
122
-
123
- /** The adapter witness type a launch stores as its `migration_witness`. */
124
- migrationWitnessType(venue: MigratorVenue): string {
125
- return normalizeStructTag(
126
- `${this.deployment.originalPackageId}::${venue}::Witness`,
169
+ this.deployment = normalizeMigratorsDeployment(deployment);
170
+ this.otw = normalizeStructTag(
171
+ `${this.deployment.originalPackageId}::blast_migrators::BLAST_MIGRATORS`,
127
172
  );
128
173
  }
129
174
 
130
- signIn(options: {
131
- adminCap: TransactionObjectInput;
132
- role: BlastFunAdminRole;
133
- }) {
134
- return this.launchpad.signIn(options);
135
- }
136
-
137
175
  /**
138
- * Starts a Cetus launch at `tickSpacing`: Cetus derives the fee rate, and the
139
- * Meme type's single `PoolCreationCap` is minted and reserved for the pair.
140
- * Returns the `LaunchInitializer`, which the same PTB must finalize.
176
+ * `cetus::prepare<Meme, Quote>(migrators_version, venue_config,
177
+ * cetus_config, pools, &mut sealed_treasury_cap, admission, tick_spacing)`:
178
+ * borrows the coin's sealed `TreasuryCap` with the product's `VenueAdmission`
179
+ * of this venue (`launch_config::venue_admission` or
180
+ * `creation_policy::venue_admission`, built earlier in the same PTB),
181
+ * reserves the Meme's Cetus pool and returns its `VenueTicket`.
141
182
  */
142
- newCetusLaunch(
143
- options: LaunchTypes &
144
- CetusObjects & {
145
- ticket: TransactionObjectInput;
146
- cetusPools: SharedObjectReference<true>;
147
- tickSpacing: number;
148
- },
149
- ) {
150
- const types = normalizeLaunchTypes(options);
183
+ prepareCetus(options: {
184
+ memeType: string;
185
+ quoteType: string;
186
+ cetus: { config: SharedObjectIdentity; pools: SharedObjectIdentity };
187
+ sealedTreasuryCap: TransactionObjectInput;
188
+ admission: TransactionArgument;
189
+ tickSpacing: number;
190
+ }): (tx: Transaction) => TransactionResult {
191
+ const types = pair(options);
151
192
  const tickSpacing = requireU32("tickSpacing", options.tickSpacing);
152
- return (tx: Transaction): TransactionResult =>
193
+ const cetus = {
194
+ config: normalizeSharedObjectIdentity(
195
+ "cetus.config",
196
+ options.cetus.config,
197
+ ),
198
+ pools: normalizeSharedObjectIdentity("cetus.pools", options.cetus.pools),
199
+ };
200
+ return (tx) =>
153
201
  tx.moveCall({
154
- target: `${this.deployment.packageId}::cetus::new`,
155
- typeArguments: [types.memeType, types.quoteType],
202
+ target: this.#target("cetus", "prepare"),
203
+ typeArguments: types,
156
204
  arguments: [
157
- tx.object(options.ticket),
158
205
  this.#migratorsVersion(tx),
159
- this.#launchpadVersion(tx),
160
- this.#launchConfig(tx),
161
206
  deploymentObject(tx, this.deployment.venueConfig, true),
162
- sharedObject(tx, "cetusConfig", options.cetusConfig, false),
163
- sharedObject(tx, "cetusPools", options.cetusPools, true),
207
+ deploymentObject(tx, cetus.config, false),
208
+ deploymentObject(tx, cetus.pools, true),
209
+ tx.object(options.sealedTreasuryCap),
210
+ options.admission,
164
211
  tx.pure.u32(tickSpacing),
165
212
  ],
166
213
  });
167
214
  }
168
215
 
169
216
  /**
170
- * Starts a Bluefin launch at the creator's tier (tick spacing 1-400, fee rate
171
- * 1-20,000, Bluefin's own bounds). Returns the `LaunchInitializer`.
217
+ * `bluefin::prepare<Meme, Quote>(migrators_version, venue_config,
218
+ * &sealed_treasury_cap, &currency, tick_spacing, fee_rate)`: records the
219
+ * Meme's Bluefin tier and returns its `VenueTicket`. The sealed cap only
220
+ * proves control of the coin; Bluefin reserves nothing, so it is never
221
+ * borrowed. Rejects a tier outside
222
+ * Bluefin's own bounds (`EInvalidTier`: tick spacing 1..=400, fee rate
223
+ * 1..=20,000); the contract also aborts with `ESymbolTooLong` when the
224
+ * Meme symbol exceeds 32 bytes.
172
225
  */
173
- newBluefinLaunch(
174
- options: LaunchTypes & {
175
- ticket: TransactionObjectInput;
176
- tickSpacing: number;
177
- feeRate: bigint;
178
- },
179
- ) {
180
- const types = normalizeLaunchTypes(options);
226
+ prepareBluefin(options: {
227
+ memeType: string;
228
+ quoteType: string;
229
+ sealedTreasuryCap: TransactionObjectInput;
230
+ currency: SharedObjectIdentity;
231
+ tickSpacing: number;
232
+ feeRate: bigint;
233
+ }): (tx: Transaction) => TransactionResult {
234
+ const types = pair(options);
181
235
  const tickSpacing = requireU32("tickSpacing", options.tickSpacing);
182
- requireU64("feeRate", options.feeRate);
183
- return (tx: Transaction): TransactionResult =>
236
+ const feeRate = requireU64("feeRate", options.feeRate);
237
+ if (
238
+ tickSpacing === 0 ||
239
+ tickSpacing > BLUEFIN_MAX_TICK_SPACING ||
240
+ feeRate === 0n ||
241
+ feeRate > BLUEFIN_MAX_FEE_RATE
242
+ ) {
243
+ throw new RangeError(
244
+ `a Bluefin tier needs a tick spacing in 1..=${BLUEFIN_MAX_TICK_SPACING} and a fee rate in 1..=${BLUEFIN_MAX_FEE_RATE}`,
245
+ );
246
+ }
247
+ const currency = normalizeSharedObjectIdentity(
248
+ "currency",
249
+ options.currency,
250
+ );
251
+ return (tx) =>
184
252
  tx.moveCall({
185
- target: `${this.deployment.packageId}::bluefin::new`,
186
- typeArguments: [types.memeType, types.quoteType],
253
+ target: this.#target("bluefin", "prepare"),
254
+ typeArguments: types,
187
255
  arguments: [
188
- tx.object(options.ticket),
189
256
  this.#migratorsVersion(tx),
190
- this.#launchpadVersion(tx),
191
- this.#launchConfig(tx),
257
+ deploymentObject(tx, this.deployment.venueConfig, true),
258
+ tx.object(options.sealedTreasuryCap),
259
+ deploymentObject(tx, currency, false),
192
260
  tx.pure.u32(tickSpacing),
193
- tx.pure.u64(options.feeRate),
261
+ tx.pure.u64(feeRate),
194
262
  ],
195
263
  });
196
264
  }
197
265
 
198
266
  /**
199
- * Migrates a MigrationReady Cetus launch: creates the pool with the reserved
200
- * capability, seeds full-range liquidity, and burns the position through
201
- * Cetus LP Burn. Anyone may call it.
267
+ * `cetus::migrate<Meme, Quote, CoinA, CoinB>(migration, migrators_version,
268
+ * venue_config, cetus_config, pools, burn_manager, registry, vault_version,
269
+ * treasury, clock)`; `CoinA`/`CoinB` follow `cetusMemeSide`. Cetus writes
270
+ * a clock-dependent amount of storage, so the PTB is budgeted at gross
271
+ * cost (`grossGasBudget`).
202
272
  */
203
- migrateCetus(
204
- options: LaunchTypes &
205
- CetusObjects & {
206
- memeSide: CetusMemeSide;
207
- launch: SharedObjectReference<true>;
208
- memeCurrency: SharedObjectReference<true>;
209
- cetusPools: SharedObjectReference<true>;
210
- /** Cetus LP Burn `lp_burn::BurnManager`. */
211
- burnManager: SharedObjectReference<true>;
212
- },
213
- ) {
214
- const types = normalizeLaunchTypes(options);
215
- const memeSide = normalizeMemeSide(options.memeSide);
216
- return (tx: Transaction): void => {
217
- // Cetus seeds a new pool's tick skip list from the clock, so its storage
218
- // differs between simulation and execution by up to 18 bytes, more than
219
- // the default budget's headroom: budget this transaction at gross cost.
273
+ migrateCetus(options: {
274
+ migration: TransactionArgument;
275
+ memeType: string;
276
+ quoteType: string;
277
+ cetus: {
278
+ config: SharedObjectIdentity;
279
+ pools: SharedObjectIdentity;
280
+ burnManager: SharedObjectIdentity;
281
+ };
282
+ }): (tx: Transaction) => void {
283
+ const typeArguments = cetusTypeArguments(options);
284
+ const cetus = {
285
+ config: normalizeSharedObjectIdentity(
286
+ "cetus.config",
287
+ options.cetus.config,
288
+ ),
289
+ pools: normalizeSharedObjectIdentity("cetus.pools", options.cetus.pools),
290
+ burnManager: normalizeSharedObjectIdentity(
291
+ "cetus.burnManager",
292
+ options.cetus.burnManager,
293
+ ),
294
+ };
295
+ return (tx) => {
220
296
  tx.addBuildPlugin(grossGasBudget());
221
297
  tx.moveCall({
222
- target: `${this.deployment.packageId}::cetus::migrate`,
223
- typeArguments: cetusTypeArguments(types, memeSide),
298
+ target: this.#target("cetus", "migrate"),
299
+ typeArguments,
224
300
  arguments: [
225
- sharedObject(tx, "launch", options.launch, true),
301
+ options.migration,
226
302
  this.#migratorsVersion(tx),
227
- this.#launchpadVersion(tx),
228
- sharedObject(tx, "memeCurrency", options.memeCurrency, true),
229
303
  deploymentObject(tx, this.deployment.venueConfig, false),
230
- sharedObject(tx, "cetusConfig", options.cetusConfig, false),
231
- sharedObject(tx, "cetusPools", options.cetusPools, true),
232
- sharedObject(tx, "burnManager", options.burnManager, true),
304
+ deploymentObject(tx, cetus.config, false),
305
+ deploymentObject(tx, cetus.pools, true),
306
+ deploymentObject(tx, cetus.burnManager, true),
307
+ deploymentObject(tx, this.deployment.vault.registry, true),
308
+ this.#vaultVersion(tx),
309
+ this.#treasury(tx),
233
310
  tx.object.clock(),
234
311
  ],
235
312
  });
@@ -237,31 +314,48 @@ export class MigratorCalls {
237
314
  }
238
315
 
239
316
  /**
240
- * Migrates a MigrationReady Bluefin launch into a new `Pool<Meme, Quote>`.
241
- * `creationFee` must be exactly Bluefin's configured SUI pool-creation fee.
317
+ * `bluefin::migrate<Meme, Quote>(migration, migrators_version,
318
+ * venue_config, currency, quote_currency, bluefin_config, registry,
319
+ * vault_version, treasury, creation_fee, clock)`; `creationFee` is a
320
+ * `Coin<SUI>` of Bluefin's pool creation fee.
242
321
  */
243
- migrateBluefin(
244
- options: LaunchTypes & {
245
- launch: SharedObjectReference<true>;
246
- memeCurrency: SharedObjectReference<true>;
247
- quoteCurrency: SharedObjectReference<false>;
248
- bluefinConfig: SharedObjectReference<true>;
249
- creationFee: TransactionObjectInput;
250
- },
251
- ) {
252
- const types = normalizeLaunchTypes(options);
253
- return (tx: Transaction): void => {
322
+ migrateBluefin(options: {
323
+ migration: TransactionArgument;
324
+ memeType: string;
325
+ quoteType: string;
326
+ currency: SharedObjectIdentity;
327
+ quoteCurrency: SharedObjectIdentity;
328
+ bluefinConfig: SharedObjectIdentity;
329
+ creationFee: TransactionArgument;
330
+ }): (tx: Transaction) => void {
331
+ const types = pair(options);
332
+ const currency = normalizeSharedObjectIdentity(
333
+ "currency",
334
+ options.currency,
335
+ );
336
+ const quoteCurrency = normalizeSharedObjectIdentity(
337
+ "quoteCurrency",
338
+ options.quoteCurrency,
339
+ );
340
+ const bluefinConfig = normalizeSharedObjectIdentity(
341
+ "bluefinConfig",
342
+ options.bluefinConfig,
343
+ );
344
+ return (tx) => {
254
345
  tx.moveCall({
255
- target: `${this.deployment.packageId}::bluefin::migrate`,
256
- typeArguments: [types.memeType, types.quoteType],
346
+ target: this.#target("bluefin", "migrate"),
347
+ typeArguments: types,
257
348
  arguments: [
258
- sharedObject(tx, "launch", options.launch, true),
349
+ options.migration,
259
350
  this.#migratorsVersion(tx),
260
- this.#launchpadVersion(tx),
261
- sharedObject(tx, "memeCurrency", options.memeCurrency, true),
262
- sharedObject(tx, "quoteCurrency", options.quoteCurrency, false),
263
- sharedObject(tx, "bluefinConfig", options.bluefinConfig, true),
264
- tx.object(options.creationFee),
351
+ deploymentObject(tx, this.deployment.venueConfig, false),
352
+ deploymentObject(tx, currency, false),
353
+ deploymentObject(tx, quoteCurrency, false),
354
+ deploymentObject(tx, bluefinConfig, true),
355
+ deploymentObject(tx, this.deployment.vault.registry, true),
356
+ this.#vaultVersion(tx),
357
+ this.#treasury(tx),
358
+ options.creationFee,
265
359
  tx.object.clock(),
266
360
  ],
267
361
  });
@@ -269,214 +363,119 @@ export class MigratorCalls {
269
363
  }
270
364
 
271
365
  /**
272
- * Collects the burned migration position's and the auto-LP position's fees,
273
- * pays Blast's live share, splits the rest, burns the burn share's Meme, and
274
- * adds the auto-LP share back. Anyone may call it.
366
+ * `cetus::collect_fees<Meme, Quote, CoinA, CoinB>(vault, migrators_version,
367
+ * vault_version, treasury, currency, cetus_config, burn_manager, pool)`:
368
+ * collects both positions' fees, splits them and burns the burn share's
369
+ * Meme; the auto-LP share waits in the vault for `compoundCetusAutoLp`.
370
+ * Anyone may call it.
275
371
  */
276
- collectCetusFees(
277
- options: LaunchTypes &
278
- CetusObjects & {
279
- memeSide: CetusMemeSide;
280
- vault: SharedObjectReference<true>;
281
- memeCurrency: SharedObjectReference<true>;
282
- burnManager: SharedObjectReference<false>;
283
- pool: SharedObjectReference<true>;
284
- },
285
- ) {
286
- const types = normalizeLaunchTypes(options);
287
- const memeSide = normalizeMemeSide(options.memeSide);
288
- return (tx: Transaction): void => {
289
- tx.moveCall({
290
- target: `${this.deployment.packageId}::cetus::collect_fees`,
291
- typeArguments: cetusTypeArguments(types, memeSide),
292
- arguments: [
293
- sharedObject(tx, "vault", options.vault, true),
294
- this.#migratorsVersion(tx),
295
- this.#lpFeePolicy(tx),
296
- sharedObject(tx, "memeCurrency", options.memeCurrency, true),
297
- sharedObject(tx, "cetusConfig", options.cetusConfig, false),
298
- sharedObject(tx, "burnManager", options.burnManager, false),
299
- sharedObject(tx, "pool", options.pool, true),
300
- tx.object.clock(),
301
- ],
302
- });
303
- };
372
+ collectCetusFees(options: CetusVaultInput): (tx: Transaction) => void {
373
+ return this.#cetusFees("collect_fees", options);
304
374
  }
305
375
 
306
- /** Collects, splits, burns, and adds auto-LP for a Bluefin vault. Anyone may call it. */
307
- collectBluefinFees(
308
- options: LaunchTypes & {
309
- vault: SharedObjectReference<true>;
310
- memeCurrency: SharedObjectReference<true>;
311
- bluefinConfig: SharedObjectReference<false>;
312
- pool: SharedObjectReference<true>;
313
- },
314
- ) {
315
- const types = normalizeLaunchTypes(options);
316
- return (tx: Transaction): void => {
317
- tx.moveCall({
318
- target: `${this.deployment.packageId}::bluefin::collect_fees`,
319
- typeArguments: [types.memeType, types.quoteType],
320
- arguments: [
321
- sharedObject(tx, "vault", options.vault, true),
322
- this.#migratorsVersion(tx),
323
- this.#lpFeePolicy(tx),
324
- sharedObject(tx, "memeCurrency", options.memeCurrency, true),
325
- sharedObject(tx, "bluefinConfig", options.bluefinConfig, false),
326
- sharedObject(tx, "pool", options.pool, true),
327
- tx.object.clock(),
328
- ],
329
- });
330
- };
376
+ /**
377
+ * `cetus::settle_and_apply_fee_split(..., pool, clock)`: `collectCetusFees`
378
+ * under the current split, then applies the ready scheduled split. Anyone
379
+ * may call it.
380
+ */
381
+ settleAndApplyCetusFeeSplit(
382
+ options: CetusVaultInput,
383
+ ): (tx: Transaction) => void {
384
+ return this.#cetusFees("settle_and_apply_fee_split", options);
331
385
  }
332
386
 
333
387
  /**
334
- * Settles the fees accrued under the current split, then commits `feeSplit`
335
- * as the vault's split. Only the launch's live `CurveFeeCap` authorizes it.
336
- * `launch` is read immutably by Move.
388
+ * `bluefin::collect_fees<Meme, Quote>(vault, migrators_version,
389
+ * vault_version, treasury, currency, bluefin_config, pool, clock)`: the
390
+ * auto-LP share waits in the vault for `compoundBluefinAutoLp`. Anyone may
391
+ * call it.
337
392
  */
338
- settleAndUpdateCetusFeeSplit(
339
- options: LaunchTypes &
340
- CetusObjects & {
341
- memeSide: CetusMemeSide;
342
- vault: SharedObjectReference<true>;
343
- launch: SharedObjectReference;
344
- curveFeeCap: TransactionObjectInput;
345
- memeCurrency: SharedObjectReference<true>;
346
- burnManager: SharedObjectReference<false>;
347
- pool: SharedObjectReference<true>;
348
- feeSplit: FeeSplit;
349
- },
350
- ) {
351
- const types = normalizeLaunchTypes(options);
352
- const memeSide = normalizeMemeSide(options.memeSide);
353
- const feeSplit = this.launchpad.feeSplit(options.feeSplit);
354
- return (tx: Transaction): void => {
355
- tx.moveCall({
356
- target: `${this.deployment.packageId}::cetus::settle_and_update_fee_split`,
357
- typeArguments: cetusTypeArguments(types, memeSide),
358
- arguments: [
359
- sharedObject(tx, "vault", options.vault, true),
360
- this.#migratorsVersion(tx),
361
- this.#lpFeePolicy(tx),
362
- sharedObject(tx, "launch", options.launch, options.launch.mutable),
363
- tx.object(options.curveFeeCap),
364
- sharedObject(tx, "memeCurrency", options.memeCurrency, true),
365
- sharedObject(tx, "cetusConfig", options.cetusConfig, false),
366
- sharedObject(tx, "burnManager", options.burnManager, false),
367
- sharedObject(tx, "pool", options.pool, true),
368
- tx.add(feeSplit),
369
- tx.object.clock(),
370
- ],
371
- });
372
- };
393
+ collectBluefinFees(options: BluefinVaultInput): (tx: Transaction) => void {
394
+ return this.#bluefinFees("collect_fees", options);
373
395
  }
374
396
 
375
- /** Bluefin counterpart of `settleAndUpdateCetusFeeSplit`. */
376
- settleAndUpdateBluefinFeeSplit(
377
- options: LaunchTypes & {
378
- vault: SharedObjectReference<true>;
379
- launch: SharedObjectReference;
380
- curveFeeCap: TransactionObjectInput;
381
- memeCurrency: SharedObjectReference<true>;
382
- bluefinConfig: SharedObjectReference<false>;
383
- pool: SharedObjectReference<true>;
384
- feeSplit: FeeSplit;
385
- },
386
- ) {
387
- const types = normalizeLaunchTypes(options);
388
- const feeSplit = this.launchpad.feeSplit(options.feeSplit);
389
- return (tx: Transaction): void => {
390
- tx.moveCall({
391
- target: `${this.deployment.packageId}::bluefin::settle_and_update_fee_split`,
392
- typeArguments: [types.memeType, types.quoteType],
393
- arguments: [
394
- sharedObject(tx, "vault", options.vault, true),
395
- this.#migratorsVersion(tx),
396
- this.#lpFeePolicy(tx),
397
- sharedObject(tx, "launch", options.launch, options.launch.mutable),
398
- tx.object(options.curveFeeCap),
399
- sharedObject(tx, "memeCurrency", options.memeCurrency, true),
400
- sharedObject(tx, "bluefinConfig", options.bluefinConfig, false),
401
- sharedObject(tx, "pool", options.pool, true),
402
- tx.add(feeSplit),
403
- tx.object.clock(),
404
- ],
405
- });
406
- };
397
+ /** `bluefin::settle_and_apply_fee_split`, same arguments as `collectBluefinFees`. */
398
+ settleAndApplyBluefinFeeSplit(
399
+ options: BluefinVaultInput,
400
+ ): (tx: Transaction) => void {
401
+ return this.#bluefinFees("settle_and_apply_fee_split", options);
407
402
  }
408
403
 
409
- /**
410
- * Swaps `quoteIn` atomic units of the vault's burn Quote for Meme in its
411
- * Cetus pool and burns it, under a `BuybackAdmin` witness. The contract
412
- * aborts with `EBuybackQuoteOutOfRange` when `quoteIn` exceeds the vault's
413
- * burn Quote, and unless the swap returns at least `minMemeOut`; set it from
414
- * an off-chain price, since anyone can move the pool's price within a
415
- * transaction. Unspent Quote waits for the next buyback.
404
+ /** Adds waiting auto-LP balances under AutoLpAdmin and keeper price bounds.
405
+ * The private entry consumes and re-shares the pool, so put it last in a PTB.
406
+ * Bounds are inclusive Q64.64 sqrt prices in venue pool coin order.
416
407
  */
417
- buybackAndBurnCetus(
418
- options: LaunchTypes &
419
- CetusObjects & {
420
- memeSide: CetusMemeSide;
421
- vault: SharedObjectReference<true>;
422
- adminWitness: TransactionObjectInput;
423
- memeCurrency: SharedObjectReference<true>;
424
- pool: SharedObjectReference<true>;
425
- quoteIn: bigint;
426
- minMemeOut: bigint;
408
+ compoundCetusAutoLp(
409
+ options: PairTypes &
410
+ AutoLpInput & {
411
+ vault: SharedObjectIdentity;
412
+ cetus: { config: SharedObjectIdentity };
413
+ pool: SharedObjectIdentity;
427
414
  },
428
- ) {
429
- const types = normalizeLaunchTypes(options);
430
- const memeSide = normalizeMemeSide(options.memeSide);
431
- const quoteIn = requirePositiveU64("quoteIn", options.quoteIn);
432
- const minMemeOut = requireU64("minMemeOut", options.minMemeOut);
433
- return (tx: Transaction): void => {
415
+ ): (tx: Transaction) => void {
416
+ const typeArguments = cetusTypeArguments(options);
417
+ const objects = {
418
+ vault: normalizeSharedObjectIdentity("vault", options.vault),
419
+ config: normalizeSharedObjectIdentity(
420
+ "cetus.config",
421
+ options.cetus.config,
422
+ ),
423
+ pool: normalizeSharedObjectIdentity("pool", options.pool),
424
+ };
425
+ const [min, max] = autoLpPriceBounds(options);
426
+ return (tx) => {
434
427
  tx.moveCall({
435
- target: `${this.deployment.packageId}::cetus::buyback_and_burn`,
436
- typeArguments: cetusTypeArguments(types, memeSide),
428
+ target: this.#target("cetus", "compound_auto_lp"),
429
+ typeArguments,
437
430
  arguments: [
438
- sharedObject(tx, "vault", options.vault, true),
431
+ deploymentObject(tx, objects.vault, true),
439
432
  this.#migratorsVersion(tx),
440
- tx.object(options.adminWitness),
441
- sharedObject(tx, "memeCurrency", options.memeCurrency, true),
442
- sharedObject(tx, "cetusConfig", options.cetusConfig, false),
443
- sharedObject(tx, "pool", options.pool, true),
444
- tx.pure.u64(quoteIn),
445
- tx.pure.u64(minMemeOut),
433
+ this.#vaultVersion(tx),
434
+ deploymentObject(tx, this.deployment.vault.admin.acl, false),
435
+ tx.object(options.adminCap),
436
+ deploymentObject(tx, objects.config, false),
437
+ deploymentObject(tx, objects.pool, true),
438
+ tx.pure.u128(min),
439
+ tx.pure.u128(max),
446
440
  tx.object.clock(),
447
441
  ],
448
442
  });
449
443
  };
450
444
  }
451
445
 
452
- /** Bluefin counterpart of `buybackAndBurnCetus`. */
453
- buybackAndBurnBluefin(
454
- options: LaunchTypes & {
455
- vault: SharedObjectReference<true>;
456
- adminWitness: TransactionObjectInput;
457
- memeCurrency: SharedObjectReference<true>;
458
- bluefinConfig: SharedObjectReference<false>;
459
- pool: SharedObjectReference<true>;
460
- quoteIn: bigint;
461
- minMemeOut: bigint;
462
- },
463
- ) {
464
- const types = normalizeLaunchTypes(options);
465
- const quoteIn = requirePositiveU64("quoteIn", options.quoteIn);
466
- const minMemeOut = requireU64("minMemeOut", options.minMemeOut);
467
- return (tx: Transaction): void => {
446
+ /** Bluefin's private AutoLpAdmin entry; see compoundCetusAutoLp. */
447
+ compoundBluefinAutoLp(
448
+ options: PairTypes &
449
+ AutoLpInput & {
450
+ vault: SharedObjectIdentity;
451
+ bluefinConfig: SharedObjectIdentity;
452
+ pool: SharedObjectIdentity;
453
+ },
454
+ ): (tx: Transaction) => void {
455
+ const types = pair(options);
456
+ const objects = {
457
+ vault: normalizeSharedObjectIdentity("vault", options.vault),
458
+ config: normalizeSharedObjectIdentity(
459
+ "bluefinConfig",
460
+ options.bluefinConfig,
461
+ ),
462
+ pool: normalizeSharedObjectIdentity("pool", options.pool),
463
+ };
464
+ const [min, max] = autoLpPriceBounds(options);
465
+ return (tx) => {
468
466
  tx.moveCall({
469
- target: `${this.deployment.packageId}::bluefin::buyback_and_burn`,
470
- typeArguments: [types.memeType, types.quoteType],
467
+ target: this.#target("bluefin", "compound_auto_lp"),
468
+ typeArguments: types,
471
469
  arguments: [
472
- sharedObject(tx, "vault", options.vault, true),
470
+ deploymentObject(tx, objects.vault, true),
473
471
  this.#migratorsVersion(tx),
474
- tx.object(options.adminWitness),
475
- sharedObject(tx, "memeCurrency", options.memeCurrency, true),
476
- sharedObject(tx, "bluefinConfig", options.bluefinConfig, false),
477
- sharedObject(tx, "pool", options.pool, true),
478
- tx.pure.u64(quoteIn),
479
- tx.pure.u64(minMemeOut),
472
+ this.#vaultVersion(tx),
473
+ deploymentObject(tx, this.deployment.vault.admin.acl, false),
474
+ tx.object(options.adminCap),
475
+ deploymentObject(tx, objects.config, false),
476
+ deploymentObject(tx, objects.pool, true),
477
+ tx.pure.u128(min),
478
+ tx.pure.u128(max),
480
479
  tx.object.clock(),
481
480
  ],
482
481
  });
@@ -484,580 +483,296 @@ export class MigratorCalls {
484
483
  }
485
484
 
486
485
  /**
487
- * Claims the creator's accrued LP fees with the launch's live `CurveFeeCap`.
488
- * `launch` is read immutably by Move.
486
+ * `cetus::buyback_and_burn<Meme, Quote, CoinA, CoinB>(vault,
487
+ * migrators_version, vault_version, admin_witness, currency, cetus_config,
488
+ * pool, quote_in, min_meme_out, clock)` under a `BuybackAdmin` witness.
489
+ * Swaps `quoteIn` of the vault's burn Quote and burns the Meme bought;
490
+ * aborts unless the swap returns at least `minMemeOut`, which the admin
491
+ * sets from an off-chain price.
489
492
  */
490
- claimCreatorFees(
491
- options: LaunchTypes & {
492
- vault: SharedObjectReference<true>;
493
- launch: SharedObjectReference;
494
- curveFeeCap: TransactionObjectInput;
495
- },
496
- ) {
497
- const types = normalizeLaunchTypes(options);
498
- return (tx: Transaction): TransactionResult =>
499
- tx.moveCall({
500
- target: `${this.deployment.packageId}::vault::claim_creator_fees`,
501
- typeArguments: [types.memeType, types.quoteType],
502
- arguments: [
503
- sharedObject(tx, "vault", options.vault, true),
504
- this.#migratorsVersion(tx),
505
- sharedObject(tx, "launch", options.launch, options.launch.mutable),
506
- tx.object(options.curveFeeCap),
507
- ],
508
- });
509
- }
510
-
511
- /**
512
- * `vault::claim_protocol_lp_fees_with_partner`: pays a partnered vault's held
513
- * Blast LP fees, the launch's partner its cut in force of each asset, rounded
514
- * down, and the `LpFeePolicy` destination the rest. Anyone may call it;
515
- * holding nothing pays nothing.
516
- */
517
- claimProtocolLpFeesWithPartner(
518
- options: LaunchTypes & {
519
- vault: SharedObjectReference<true>;
520
- partner: SharedObjectReference<false>;
521
- },
522
- ) {
523
- const types = normalizeLaunchTypes(options);
524
- return (tx: Transaction): void => {
525
- tx.moveCall({
526
- target: `${this.deployment.packageId}::vault::claim_protocol_lp_fees_with_partner`,
527
- typeArguments: [types.memeType, types.quoteType],
528
- arguments: [
529
- sharedObject(tx, "vault", options.vault, true),
530
- this.#migratorsVersion(tx),
531
- this.#lpFeePolicy(tx),
532
- sharedObject(tx, "partner", options.partner, false),
533
- tx.object.clock(),
534
- ],
535
- });
493
+ buybackAndBurnCetus(
494
+ options: PairTypes &
495
+ BuybackInput & {
496
+ vault: SharedObjectIdentity;
497
+ currency: SharedObjectIdentity;
498
+ cetus: { config: SharedObjectIdentity };
499
+ pool: SharedObjectIdentity;
500
+ },
501
+ ): (tx: Transaction) => void {
502
+ const typeArguments = cetusTypeArguments(options);
503
+ const objects = {
504
+ vault: normalizeSharedObjectIdentity("vault", options.vault),
505
+ currency: normalizeSharedObjectIdentity("currency", options.currency),
506
+ config: normalizeSharedObjectIdentity(
507
+ "cetus.config",
508
+ options.cetus.config,
509
+ ),
510
+ pool: normalizeSharedObjectIdentity("pool", options.pool),
536
511
  };
537
- }
538
-
539
- /** Claims the protocol-owned migration residuals under a `TreasuryAdmin` witness. */
540
- claimProtocolFees(
541
- options: LaunchTypes & {
542
- vault: SharedObjectReference<true>;
543
- adminWitness: TransactionObjectInput;
544
- },
545
- ) {
546
- const types = normalizeLaunchTypes(options);
547
- return (tx: Transaction): TransactionResult =>
512
+ const amounts = buybackAmounts(options);
513
+ return (tx) => {
548
514
  tx.moveCall({
549
- target: `${this.deployment.packageId}::vault::claim_protocol_fees`,
550
- typeArguments: [types.memeType, types.quoteType],
515
+ target: this.#target("cetus", "buyback_and_burn"),
516
+ typeArguments,
551
517
  arguments: [
552
- sharedObject(tx, "vault", options.vault, true),
518
+ deploymentObject(tx, objects.vault, true),
553
519
  this.#migratorsVersion(tx),
520
+ this.#vaultVersion(tx),
554
521
  tx.object(options.adminWitness),
522
+ deploymentObject(tx, objects.currency, true),
523
+ deploymentObject(tx, objects.config, false),
524
+ deploymentObject(tx, objects.pool, true),
525
+ tx.pure.u64(amounts.quoteIn),
526
+ tx.pure.u64(amounts.minMemeOut),
527
+ tx.object.clock(),
555
528
  ],
556
529
  });
557
- }
558
-
559
- /** Changes Blast's default Meme and Quote LP-fee shares for coins without their own pair (`FeeAdmin`). */
560
- setLpFeeDefaultShares(options: {
561
- adminWitness: TransactionObjectInput;
562
- memeBps: bigint;
563
- quoteBps: bigint;
564
- }) {
565
- return this.#lpFeePolicyAdmin("set_default_shares", [], options, (tx) => [
566
- tx.add(this.launchpad.bps(options.memeBps)),
567
- tx.add(this.launchpad.bps(options.quoteBps)),
568
- ]);
569
- }
570
-
571
- /** Sets Blast's LP-fee shares for one original Meme type (`FeeAdmin`). */
572
- setLpFeeCoinShares(options: {
573
- memeType: string;
574
- adminWitness: TransactionObjectInput;
575
- memeBps: bigint;
576
- quoteBps: bigint;
577
- }) {
578
- return this.#lpFeePolicyAdmin(
579
- "set_coin_shares",
580
- [normalizeStructTag(options.memeType)],
581
- options,
582
- (tx) => [
583
- tx.add(this.launchpad.bps(options.memeBps)),
584
- tx.add(this.launchpad.bps(options.quoteBps)),
585
- ],
586
- );
587
- }
588
-
589
- /** Removes one Meme type's own pair so its collections use the defaults again (`FeeAdmin`). */
590
- clearLpFeeCoinShares(options: {
591
- memeType: string;
592
- adminWitness: TransactionObjectInput;
593
- }) {
594
- return this.#lpFeePolicyAdmin(
595
- "clear_coin_shares",
596
- [normalizeStructTag(options.memeType)],
597
- options,
598
- () => [],
599
- );
600
- }
601
-
602
- /** Redirects every later protocol LP-fee payout (`TreasuryAdmin`). */
603
- setLpFeeProtocolDestination(options: {
604
- adminWitness: TransactionObjectInput;
605
- destination: string;
606
- }) {
607
- const destination = normalizeSuiAddress(options.destination);
608
- return this.#lpFeePolicyAdmin(
609
- "set_protocol_destination",
610
- [],
611
- options,
612
- (tx) => [tx.pure.address(destination)],
613
- );
530
+ };
614
531
  }
615
532
 
616
533
  /**
617
- * Publishes a holder-reward round from a validated manifest, reserving its
618
- * budget from the vault's rewards balance, and shares the `Round`
619
- * (`RewardsAdmin`).
534
+ * `bluefin::buyback_and_burn<Meme, Quote>(vault, migrators_version,
535
+ * vault_version, admin_witness, currency, bluefin_config, pool, quote_in,
536
+ * min_meme_out, clock)`; see `buybackAndBurnCetus`.
620
537
  */
621
- publishHolderRewardRound(
622
- options: LaunchTypes & {
623
- vault: SharedObjectReference<true>;
624
- adminWitness: TransactionObjectInput;
625
- manifest: RewardManifest;
626
- },
627
- ) {
628
- const types = normalizeLaunchTypes(options);
629
- const manifest = validateRewardManifest(
630
- options.manifest,
631
- MIGRATOR_REWARD_LEAF_DOMAIN,
632
- );
633
- if (
634
- rewardAddress(manifest.vaultId) !== rewardAddress(options.vault.objectId)
635
- ) {
636
- throw new TypeError("manifest belongs to another vault");
637
- }
638
- return (tx: Transaction): void => {
538
+ buybackAndBurnBluefin(
539
+ options: PairTypes &
540
+ BuybackInput & {
541
+ vault: SharedObjectIdentity;
542
+ currency: SharedObjectIdentity;
543
+ bluefinConfig: SharedObjectIdentity;
544
+ pool: SharedObjectIdentity;
545
+ },
546
+ ): (tx: Transaction) => void {
547
+ const types = pair(options);
548
+ const objects = {
549
+ vault: normalizeSharedObjectIdentity("vault", options.vault),
550
+ currency: normalizeSharedObjectIdentity("currency", options.currency),
551
+ config: normalizeSharedObjectIdentity(
552
+ "bluefinConfig",
553
+ options.bluefinConfig,
554
+ ),
555
+ pool: normalizeSharedObjectIdentity("pool", options.pool),
556
+ };
557
+ const amounts = buybackAmounts(options);
558
+ return (tx) => {
639
559
  tx.moveCall({
640
- target: `${this.deployment.packageId}::blast_holder_rewards::publish_round`,
641
- typeArguments: [types.memeType, types.quoteType],
560
+ target: this.#target("bluefin", "buyback_and_burn"),
561
+ typeArguments: types,
642
562
  arguments: [
643
- sharedObject(tx, "vault", options.vault, true),
563
+ deploymentObject(tx, objects.vault, true),
644
564
  this.#migratorsVersion(tx),
565
+ this.#vaultVersion(tx),
645
566
  tx.object(options.adminWitness),
646
- tx.pure.u64(manifest.number),
647
- tx.pure.u64(manifest.startCheckpoint),
648
- tx.pure.u64(manifest.endCheckpoint),
649
- tx.pure.vector("u8", rewardDigest(manifest.root)),
650
- tx.pure.vector("u8", rewardDigest(manifest.manifestDigest)),
651
- tx.pure.u64(manifest.allocations.length),
652
- tx.pure.u64(manifest.memeAmount),
653
- tx.pure.u64(manifest.quoteAmount),
567
+ deploymentObject(tx, objects.currency, true),
568
+ deploymentObject(tx, objects.config, false),
569
+ deploymentObject(tx, objects.pool, true),
570
+ tx.pure.u64(amounts.quoteIn),
571
+ tx.pure.u64(amounts.minMemeOut),
572
+ tx.object.clock(),
654
573
  ],
655
574
  });
656
575
  };
657
576
  }
658
577
 
659
- /** Relays one allocation's proof; the round pays its committed beneficiary. */
660
- claimHolderReward(
661
- options: LaunchTypes & {
662
- round: SharedObjectReference<true>;
663
- allocation: RewardProof;
664
- },
665
- ) {
666
- const types = normalizeLaunchTypes(options);
667
- const { allocation } = options;
668
- const index = requireU64("index", BigInt(allocation.index));
669
- const memeAmount = requireU64("memeAmount", BigInt(allocation.memeAmount));
670
- const quoteAmount = requireU64(
671
- "quoteAmount",
672
- BigInt(allocation.quoteAmount),
673
- );
674
- const beneficiary = rewardAddress(allocation.beneficiary);
675
- if (allocation.proof.length > MAX_HOLDER_REWARD_PROOF_DEPTH) {
676
- throw new RangeError(
677
- `proof exceeds ${MAX_HOLDER_REWARD_PROOF_DEPTH} siblings`,
678
- );
679
- }
680
- const proof = allocation.proof.map((sibling) =>
681
- Array.from(rewardDigest(sibling)),
682
- );
683
- return (tx: Transaction): void => {
578
+ #cetusFees(
579
+ name: "collect_fees" | "settle_and_apply_fee_split",
580
+ options: CetusVaultInput,
581
+ ): (tx: Transaction) => void {
582
+ const typeArguments = cetusTypeArguments(options);
583
+ const objects = {
584
+ vault: normalizeSharedObjectIdentity("vault", options.vault),
585
+ currency: normalizeSharedObjectIdentity("currency", options.currency),
586
+ config: normalizeSharedObjectIdentity(
587
+ "cetus.config",
588
+ options.cetus.config,
589
+ ),
590
+ burnManager: normalizeSharedObjectIdentity(
591
+ "cetus.burnManager",
592
+ options.cetus.burnManager,
593
+ ),
594
+ pool: normalizeSharedObjectIdentity("pool", options.pool),
595
+ };
596
+ return (tx) => {
684
597
  tx.moveCall({
685
- target: `${this.deployment.packageId}::blast_holder_rewards::claim`,
686
- typeArguments: [types.memeType, types.quoteType],
598
+ target: this.#target("cetus", name),
599
+ typeArguments,
687
600
  arguments: [
688
- sharedObject(tx, "round", options.round, true),
601
+ deploymentObject(tx, objects.vault, true),
689
602
  this.#migratorsVersion(tx),
690
- tx.pure.u64(index),
691
- tx.pure.address(beneficiary),
692
- tx.pure.u64(memeAmount),
693
- tx.pure.u64(quoteAmount),
694
- tx.pure.vector("vector<u8>", proof),
603
+ this.#vaultVersion(tx),
604
+ this.#treasury(tx),
605
+ deploymentObject(tx, objects.currency, true),
606
+ deploymentObject(tx, objects.config, false),
607
+ deploymentObject(tx, objects.burnManager, false),
608
+ deploymentObject(tx, objects.pool, true),
609
+ // Only the split's apply reads the clock.
610
+ ...(name === "settle_and_apply_fee_split" ? [tx.object.clock()] : []),
695
611
  ],
696
612
  });
697
613
  };
698
614
  }
699
615
 
700
- #lpFeePolicyAdmin(
701
- functionName: string,
702
- typeArguments: string[],
703
- options: { adminWitness: TransactionObjectInput },
704
- extra: (tx: Transaction) => TransactionArgument[],
705
- ) {
706
- return (tx: Transaction): void => {
616
+ #bluefinFees(
617
+ name: "collect_fees" | "settle_and_apply_fee_split",
618
+ options: BluefinVaultInput,
619
+ ): (tx: Transaction) => void {
620
+ const types = pair(options);
621
+ const objects = {
622
+ vault: normalizeSharedObjectIdentity("vault", options.vault),
623
+ currency: normalizeSharedObjectIdentity("currency", options.currency),
624
+ config: normalizeSharedObjectIdentity(
625
+ "bluefinConfig",
626
+ options.bluefinConfig,
627
+ ),
628
+ pool: normalizeSharedObjectIdentity("pool", options.pool),
629
+ };
630
+ return (tx) => {
707
631
  tx.moveCall({
708
- target: `${this.deployment.packageId}::lp_fee_policy::${functionName}`,
709
- typeArguments,
632
+ target: this.#target("bluefin", name),
633
+ typeArguments: types,
710
634
  arguments: [
711
- deploymentObject(tx, this.deployment.lpFeePolicy, true),
635
+ deploymentObject(tx, objects.vault, true),
712
636
  this.#migratorsVersion(tx),
713
- tx.object(options.adminWitness),
714
- ...extra(tx),
637
+ this.#vaultVersion(tx),
638
+ this.#treasury(tx),
639
+ deploymentObject(tx, objects.currency, true),
640
+ deploymentObject(tx, objects.config, false),
641
+ deploymentObject(tx, objects.pool, true),
642
+ tx.object.clock(),
715
643
  ],
716
644
  });
717
645
  };
718
646
  }
719
647
 
720
- #migratorsVersion(tx: Transaction): TransactionObjectArgument {
721
- return deploymentObject(tx, this.deployment.migratorsVersion, false);
648
+ #target(module: MigratorVenue, name: string): string {
649
+ return `${this.deployment.packageId}::${module}::${name}`;
722
650
  }
723
651
 
724
- #launchpadVersion(tx: Transaction): TransactionObjectArgument {
725
- return deploymentObject(
726
- tx,
727
- this.deployment.launchpad.packageVersion,
728
- false,
729
- );
652
+ #migratorsVersion(tx: Transaction): TransactionObjectArgument {
653
+ return deploymentObject(tx, this.deployment.packageVersion, false);
730
654
  }
731
655
 
732
- #launchConfig(tx: Transaction): TransactionObjectArgument {
733
- return deploymentObject(tx, this.deployment.launchpad.launchConfig, false);
656
+ #vaultVersion(tx: Transaction): TransactionObjectArgument {
657
+ return deploymentObject(tx, this.deployment.vault.packageVersion, false);
734
658
  }
735
659
 
736
- #lpFeePolicy(tx: Transaction): TransactionObjectArgument {
737
- return deploymentObject(tx, this.deployment.lpFeePolicy, false);
660
+ #treasury(tx: Transaction): TransactionObjectArgument {
661
+ return deploymentObject(tx, this.deployment.vault.core.treasury, false);
738
662
  }
739
663
  }
740
664
 
665
+ /**
666
+ * One-call PTBs for a migrated vault's venue routes: fee collection,
667
+ * settlement and auto-LP compounding (anyone) and buybacks (an `AdminCap` holding
668
+ * `blast_domain::BuybackAdmin`). Preparation and migration are composed
669
+ * with the product's own calls by the launchpad and presale packages.
670
+ */
741
671
  export class MigratorTransactions {
742
672
  readonly call: MigratorCalls;
743
- readonly #useGasCoin: boolean;
673
+ readonly admin: AdminCalls;
744
674
 
745
- constructor(
746
- deployment: MigratorsDeployment,
747
- options: CoinSourceOptions = {},
748
- ) {
675
+ constructor(deployment: MigratorsDeployment) {
749
676
  this.call = new MigratorCalls(deployment);
750
- this.#useGasCoin = options.useGasCoin ?? true;
677
+ this.admin = new AdminCalls(this.call.deployment.vault.admin);
751
678
  }
752
679
 
753
- /**
754
- * Starts, configures, finalizes, and shares a Cetus launch atomically, with
755
- * an optional purchase on the owned launch, routed to its recipient.
756
- */
757
- createCetusLaunch(
758
- options: CreateLaunchOptions &
759
- CetusObjects & {
760
- cetusPools: SharedObjectReference<true>;
761
- tickSpacing: number;
762
- },
763
- ): Transaction {
764
- const tx = new Transaction();
765
- const initializer = tx.add(this.call.newCetusLaunch(options));
766
- addLaunchCompletion(tx, this.call.launchpad, {
767
- ...options,
768
- initializer,
769
- currency: options.memeCurrency,
770
- useGasCoin: options.useGasCoin ?? this.#useGasCoin,
771
- });
772
- return tx;
773
- }
774
-
775
- /** Bluefin counterpart of `createCetusLaunch`. */
776
- createBluefinLaunch(
777
- options: CreateLaunchOptions & { tickSpacing: number; feeRate: bigint },
778
- ): Transaction {
779
- const tx = new Transaction();
780
- const initializer = tx.add(this.call.newBluefinLaunch(options));
781
- addLaunchCompletion(tx, this.call.launchpad, {
782
- ...options,
783
- initializer,
784
- currency: options.memeCurrency,
785
- useGasCoin: options.useGasCoin ?? this.#useGasCoin,
786
- });
787
- return tx;
680
+ collectCetusFees(options: CetusVaultInput): Transaction {
681
+ return single(this.call.collectCetusFees(options));
788
682
  }
789
683
 
790
- migrateCetus(
791
- options: Parameters<MigratorCalls["migrateCetus"]>[0],
792
- ): Transaction {
793
- const tx = new Transaction();
794
- tx.add(this.call.migrateCetus(options));
795
- return tx;
684
+ settleAndApplyCetusFeeSplit(options: CetusVaultInput): Transaction {
685
+ return single(this.call.settleAndApplyCetusFeeSplit(options));
796
686
  }
797
687
 
798
- /** Pays Bluefin's SUI pool-creation fee as an exact-balance coin. */
799
- migrateBluefin(
800
- options: Omit<
801
- Parameters<MigratorCalls["migrateBluefin"]>[0],
802
- "creationFee"
803
- > & {
804
- creationFee: bigint;
805
- } & CoinSourceOptions,
806
- ): Transaction {
807
- requireU64("creationFee", options.creationFee);
808
- const tx = new Transaction();
809
- const creationFee = tx.coin({
810
- type: "0x2::sui::SUI",
811
- balance: options.creationFee,
812
- useGasCoin: options.useGasCoin ?? this.#useGasCoin,
813
- });
814
- tx.add(this.call.migrateBluefin({ ...options, creationFee }));
815
- return tx;
688
+ collectBluefinFees(options: BluefinVaultInput): Transaction {
689
+ return single(this.call.collectBluefinFees(options));
816
690
  }
817
691
 
818
- /** Then pays the vault's partner when `partner` is given; see `claimProtocolLpFeesWithPartner`. */
819
- collectCetusFees(
820
- options: Parameters<MigratorCalls["collectCetusFees"]>[0] & LpFeePartner,
821
- ): Transaction {
822
- const tx = new Transaction();
823
- tx.add(this.call.collectCetusFees(options));
824
- return this.#claimProtocolLpFeesWithPartnerAfter(tx, options);
692
+ settleAndApplyBluefinFeeSplit(options: BluefinVaultInput): Transaction {
693
+ return single(this.call.settleAndApplyBluefinFeeSplit(options));
825
694
  }
826
695
 
827
- /** Then pays the vault's partner when `partner` is given; see `claimProtocolLpFeesWithPartner`. */
828
- collectBluefinFees(
829
- options: Parameters<MigratorCalls["collectBluefinFees"]>[0] & LpFeePartner,
696
+ compoundCetusAutoLp(
697
+ options: Parameters<MigratorCalls["compoundCetusAutoLp"]>[0],
830
698
  ): Transaction {
831
- const tx = new Transaction();
832
- tx.add(this.call.collectBluefinFees(options));
833
- return this.#claimProtocolLpFeesWithPartnerAfter(tx, options);
699
+ return single(this.call.compoundCetusAutoLp(options));
834
700
  }
835
701
 
836
- /** Pays a partnered vault's partner and Blast the LP fees its collections held. */
837
- claimProtocolLpFeesWithPartner(
838
- options: Parameters<MigratorCalls["claimProtocolLpFeesWithPartner"]>[0],
702
+ compoundBluefinAutoLp(
703
+ options: Parameters<MigratorCalls["compoundBluefinAutoLp"]>[0],
839
704
  ): Transaction {
840
- const tx = new Transaction();
841
- tx.add(this.call.claimProtocolLpFeesWithPartner(options));
842
- return tx;
843
- }
844
-
845
- settleAndUpdateCetusFeeSplit(
846
- options: Omit<
847
- Parameters<MigratorCalls["settleAndUpdateCetusFeeSplit"]>[0],
848
- "curveFeeCap"
849
- > & { curveFeeCapId: string },
850
- ): Transaction {
851
- const tx = new Transaction();
852
- tx.add(
853
- this.call.settleAndUpdateCetusFeeSplit({
854
- ...options,
855
- curveFeeCap: options.curveFeeCapId,
856
- }),
857
- );
858
- return tx;
859
- }
860
-
861
- settleAndUpdateBluefinFeeSplit(
862
- options: Omit<
863
- Parameters<MigratorCalls["settleAndUpdateBluefinFeeSplit"]>[0],
864
- "curveFeeCap"
865
- > & { curveFeeCapId: string },
866
- ): Transaction {
867
- const tx = new Transaction();
868
- tx.add(
869
- this.call.settleAndUpdateBluefinFeeSplit({
870
- ...options,
871
- curveFeeCap: options.curveFeeCapId,
872
- }),
873
- );
874
- return tx;
875
- }
876
-
877
- claimCreatorFees(
878
- options: LaunchTypes & {
879
- vault: SharedObjectReference<true>;
880
- launch: SharedObjectReference;
881
- curveFeeCapId: string;
882
- recipient: string;
883
- },
884
- ): Transaction {
885
- const tx = new Transaction();
886
- const result = tx.add(
887
- this.call.claimCreatorFees({
888
- ...options,
889
- curveFeeCap: options.curveFeeCapId,
890
- }),
891
- );
892
- tx.transferObjects(
893
- moveResults(result, 2),
894
- normalizeSuiAddress(options.recipient),
895
- );
896
- return tx;
897
- }
898
-
899
- claimProtocolFees(
900
- options: LaunchTypes & {
901
- vault: SharedObjectReference<true>;
902
- adminCapId: string;
903
- recipient: string;
904
- },
905
- ): Transaction {
906
- const tx = new Transaction();
907
- const adminWitness = tx.add(
908
- this.call.signIn({ adminCap: options.adminCapId, role: "TreasuryAdmin" }),
909
- );
910
- const result = tx.add(
911
- this.call.claimProtocolFees({ ...options, adminWitness }),
912
- );
913
- tx.transferObjects(
914
- moveResults(result, 2),
915
- normalizeSuiAddress(options.recipient),
916
- );
917
- return tx;
918
- }
919
-
920
- setLpFeeDefaultShares(options: {
921
- adminCapId: string;
922
- memeBps: bigint;
923
- quoteBps: bigint;
924
- }): Transaction {
925
- return this.#asAdmin(options.adminCapId, "FeeAdmin", (adminWitness) =>
926
- this.call.setLpFeeDefaultShares({ ...options, adminWitness }),
927
- );
928
- }
929
-
930
- setLpFeeCoinShares(options: {
931
- memeType: string;
932
- adminCapId: string;
933
- memeBps: bigint;
934
- quoteBps: bigint;
935
- }): Transaction {
936
- return this.#asAdmin(options.adminCapId, "FeeAdmin", (adminWitness) =>
937
- this.call.setLpFeeCoinShares({ ...options, adminWitness }),
938
- );
939
- }
940
-
941
- clearLpFeeCoinShares(options: {
942
- memeType: string;
943
- adminCapId: string;
944
- }): Transaction {
945
- return this.#asAdmin(options.adminCapId, "FeeAdmin", (adminWitness) =>
946
- this.call.clearLpFeeCoinShares({ ...options, adminWitness }),
947
- );
948
- }
949
-
950
- setLpFeeProtocolDestination(options: {
951
- adminCapId: string;
952
- destination: string;
953
- }): Transaction {
954
- return this.#asAdmin(options.adminCapId, "TreasuryAdmin", (adminWitness) =>
955
- this.call.setLpFeeProtocolDestination({ ...options, adminWitness }),
956
- );
705
+ return single(this.call.compoundBluefinAutoLp(options));
957
706
  }
958
707
 
708
+ /** Signs in as `BuybackAdmin` with `adminCapId`, then `buybackAndBurnCetus`. */
959
709
  buybackAndBurnCetus(
960
710
  options: Omit<
961
711
  Parameters<MigratorCalls["buybackAndBurnCetus"]>[0],
962
712
  "adminWitness"
963
713
  > & { adminCapId: string },
964
714
  ): Transaction {
965
- return this.#asAdmin(options.adminCapId, "BuybackAdmin", (adminWitness) =>
715
+ return this.#asBuybackAdmin(options.adminCapId, (adminWitness) =>
966
716
  this.call.buybackAndBurnCetus({ ...options, adminWitness }),
967
717
  );
968
718
  }
969
719
 
720
+ /** Signs in as `BuybackAdmin` with `adminCapId`, then `buybackAndBurnBluefin`. */
970
721
  buybackAndBurnBluefin(
971
722
  options: Omit<
972
723
  Parameters<MigratorCalls["buybackAndBurnBluefin"]>[0],
973
724
  "adminWitness"
974
725
  > & { adminCapId: string },
975
726
  ): Transaction {
976
- return this.#asAdmin(options.adminCapId, "BuybackAdmin", (adminWitness) =>
727
+ return this.#asBuybackAdmin(options.adminCapId, (adminWitness) =>
977
728
  this.call.buybackAndBurnBluefin({ ...options, adminWitness }),
978
729
  );
979
730
  }
980
731
 
981
- publishHolderRewardRound(
982
- options: Omit<
983
- Parameters<MigratorCalls["publishHolderRewardRound"]>[0],
984
- "adminWitness"
985
- > & { adminCapId: string },
986
- ): Transaction {
987
- return this.#asAdmin(options.adminCapId, "RewardsAdmin", (adminWitness) =>
988
- this.call.publishHolderRewardRound({ ...options, adminWitness }),
989
- );
990
- }
991
-
992
- /** Relays up to `allocations.length` proofs of one round in a single PTB. */
993
- claimHolderRewards(
994
- options: LaunchTypes & {
995
- round: SharedObjectReference<true>;
996
- allocations: readonly RewardProof[];
997
- },
998
- ): Transaction {
999
- const tx = new Transaction();
1000
- for (const allocation of options.allocations) {
1001
- tx.add(this.call.claimHolderReward({ ...options, allocation }));
1002
- }
1003
- return tx;
1004
- }
1005
-
1006
- #asAdmin(
732
+ #asBuybackAdmin(
1007
733
  adminCapId: string,
1008
- role: BlastFunAdminRole,
1009
734
  call: (
1010
735
  adminWitness: TransactionObjectArgument,
1011
736
  ) => (tx: Transaction) => void,
1012
737
  ): Transaction {
1013
738
  const tx = new Transaction();
1014
739
  const adminWitness = tx.add(
1015
- this.call.signIn({ adminCap: adminCapId, role }),
740
+ this.admin.signIn({
741
+ adminCap: adminCapId,
742
+ role: coreRoleType(this.call.deployment.vault.core, "BuybackAdmin"),
743
+ }),
1016
744
  );
1017
745
  tx.add(call(adminWitness));
1018
746
  return tx;
1019
747
  }
748
+ }
1020
749
 
1021
- #claimProtocolLpFeesWithPartnerAfter(
1022
- tx: Transaction,
1023
- options: LaunchTypes & {
1024
- vault: SharedObjectReference<true>;
1025
- } & LpFeePartner,
1026
- ): Transaction {
1027
- const { partner } = options;
1028
- if (partner)
1029
- tx.add(this.call.claimProtocolLpFeesWithPartner({ ...options, partner }));
1030
- return tx;
1031
- }
750
+ function single(step: (tx: Transaction) => void): Transaction {
751
+ const tx = new Transaction();
752
+ tx.add(step);
753
+ return tx;
1032
754
  }
1033
755
 
1034
- function sharedObject<const Mutable extends boolean>(
1035
- tx: Transaction,
1036
- name: string,
1037
- reference: SharedObjectReference<Mutable>,
1038
- mutable: Mutable,
1039
- ): TransactionObjectArgument {
1040
- return tx.sharedObjectRef(
1041
- normalizeSharedObjectReference(name, reference, mutable),
1042
- );
756
+ function pair(types: PairTypes): [string, string] {
757
+ return [
758
+ normalizeStructTag(types.memeType),
759
+ normalizeStructTag(types.quoteType),
760
+ ];
1043
761
  }
1044
762
 
1045
- /** `[Meme, Quote, CoinA, CoinB]`, the pool's coins in Cetus order. */
1046
- function cetusTypeArguments(
1047
- types: LaunchTypes,
1048
- memeSide: CetusMemeSide,
1049
- ): string[] {
1050
- const { memeType, quoteType } = types;
1051
- return memeSide === "a"
1052
- ? [memeType, quoteType, memeType, quoteType]
1053
- : [memeType, quoteType, quoteType, memeType];
763
+ /** `<Meme, Quote, CoinA, CoinB>`, with the pool's coin order from `cetusMemeSide`. */
764
+ function cetusTypeArguments(types: PairTypes): string[] {
765
+ const [meme, quote] = pair(types);
766
+ return cetusMemeSide(meme, quote) === "a"
767
+ ? [meme, quote, meme, quote]
768
+ : [meme, quote, quote, meme];
1054
769
  }
1055
770
 
1056
- function normalizeMemeSide(value: CetusMemeSide): CetusMemeSide {
1057
- if (value !== "a" && value !== "b") {
1058
- throw new RangeError("memeSide must be a or b");
1059
- }
1060
- return value;
771
+ function buybackAmounts(options: BuybackInput) {
772
+ return {
773
+ quoteIn: requirePositiveU64("quoteIn", options.quoteIn),
774
+ minMemeOut: requireU64("minMemeOut", options.minMemeOut),
775
+ };
1061
776
  }
1062
777
 
1063
778
  function requireU32(name: string, value: number): number {
@@ -1066,3 +781,19 @@ function requireU32(name: string, value: number): number {
1066
781
  }
1067
782
  return value;
1068
783
  }
784
+
785
+ /** Authority and inclusive pool-order Q64.64 bounds for a private auto-LP entry. */
786
+ export type AutoLpInput = {
787
+ adminCap: TransactionObjectInput;
788
+ minSqrtPrice: bigint;
789
+ maxSqrtPrice: bigint;
790
+ };
791
+
792
+ function autoLpPriceBounds(options: AutoLpInput): readonly [bigint, bigint] {
793
+ const min = requireU128("minSqrtPrice", options.minSqrtPrice);
794
+ const max = requireU128("maxSqrtPrice", options.maxSqrtPrice);
795
+ if (min === 0n || min > max) {
796
+ throw new RangeError("auto-LP needs 0 < minSqrtPrice <= maxSqrtPrice");
797
+ }
798
+ return [min, max];
799
+ }