@interest-protocol/blast-migrators-sdk 0.1.2 → 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
package/src/reducer.ts CHANGED
@@ -1,562 +1,70 @@
1
- import type { NativeTransactionPosition } from "@interest-protocol/blast-core/events";
2
- import { normalizeNativeTransactionPosition } from "@interest-protocol/blast-core/events";
3
- import { requireU64 } from "@interest-protocol/blast-core/integers";
4
- import type { FeeSplit } from "@interest-protocol/blast-launchpad-sdk/allocation";
5
- import type { DecodedLaunchpadEvent } from "@interest-protocol/blast-launchpad-sdk/events";
6
- import type { LaunchpadEventProjection } from "@interest-protocol/blast-launchpad-sdk/reducer";
7
- import {
8
- createLaunchpadEventProjection,
9
- reduceLaunchpadEvent,
10
- } from "@interest-protocol/blast-launchpad-sdk/reducer";
11
- import {
12
- normalizeSuiAddress,
13
- normalizeSuiObjectId,
14
- toHex,
15
- } from "@mysten/sui/utils";
16
- import type { DecodedMigratorEvent, MigratorEventKind } from "./events.ts";
17
- import { migratorEventId, migratorEventSpecs } from "./events.ts";
1
+ import { suiEventId } from "@interest-protocol/blast-core/events";
2
+ import type { DecodedMigratorsEvent } from "./events.ts";
3
+ import type { BluefinPoolTier } from "./state.ts";
18
4
 
19
- export type LpVaultEventProjection = {
20
- vaultId: string;
21
- /** The launch this vault completed, linked by Meme type in the product projection. */
22
- launchId: string | null;
23
- poolId: string;
24
- positionId: string;
25
- /** Separate full-range position Cetus auto-LP adds to; null until first use. */
26
- autoLpPositionId: string | null;
27
- venueType: string;
28
- memeType: string;
29
- quoteType: string;
30
- feeSplit: FeeSplit;
31
- creatorMeme: bigint;
32
- creatorQuote: bigint;
33
- autoLpMeme: bigint;
34
- autoLpQuote: bigint;
35
- rewardsMeme: bigint;
36
- rewardsQuote: bigint;
37
- /** Burn-share Quote waiting for a buyback. */
38
- burnQuote: bigint;
39
- /** Protocol migration residuals the venue returned. */
40
- protocolMemeResidual: bigint;
41
- protocolQuoteResidual: bigint;
42
- /** Liquidity of the migration position. */
43
- liquidity: bigint;
44
- nextRound: bigint;
45
- lastCheckpoint: bigint | null;
46
- /** Cumulative protocol LP-fee payouts. */
47
- protocolMemePaid: bigint;
48
- protocolQuotePaid: bigint;
49
- /** Blast's LP fees a partnered vault holds for its next partner claim. */
50
- protocolMemeHeld: bigint;
51
- protocolQuoteHeld: bigint;
52
- /** Cumulative cut of Blast's LP fees paid to the launch's partner. */
53
- partnerMemePaid: bigint;
54
- partnerQuotePaid: bigint;
55
- };
56
-
57
- export type HolderRewardRoundProjection = {
58
- roundId: string;
59
- vaultId: string;
60
- number: bigint;
61
- startCheckpoint: bigint;
62
- endCheckpoint: bigint;
63
- root: string;
64
- manifestDigest: string;
65
- leafCount: bigint;
66
- memeRemaining: bigint;
67
- quoteRemaining: bigint;
68
- paidIndexes: Readonly<Record<string, true>>;
69
- };
70
-
71
- export type LpFeePolicyProjection = {
72
- /** Default Meme/Quote shares, once a change is replayed; initialization sets zero/zero. */
73
- defaultShares: { memeBps: bigint; quoteBps: bigint };
74
- /** Original Meme type keyed pairs that override the defaults. */
75
- coinShares: Readonly<Record<string, { memeBps: bigint; quoteBps: bigint }>>;
76
- /** Protocol destination once redirected; initialization pays the publisher. */
77
- protocolDestination: string | null;
78
- };
79
-
80
- export type CetusPoolReservationProjection = {
81
- memeType: string;
5
+ /** A Meme's Cetus reservation: its `PoolCreationCap` and tick spacing. */
6
+ export type CetusReservation = {
82
7
  quoteType: string;
83
8
  poolCreationCapId: string;
84
9
  tickSpacing: number;
85
10
  };
86
11
 
87
- export type MigratorEventProjection = {
88
- appliedEventIds: Readonly<Record<string, true>>;
89
- eventCounts: Readonly<Record<MigratorEventKind, number>>;
90
- vaults: Readonly<Record<string, LpVaultEventProjection>>;
91
- rounds: Readonly<Record<string, HolderRewardRoundProjection>>;
92
- lpFeePolicy: LpFeePolicyProjection;
93
- /** Cetus pool-creation reservations, keyed by Meme type. */
94
- cetusPoolReservations: Readonly<
95
- Record<string, CetusPoolReservationProjection>
96
- >;
97
- };
98
-
99
- export type { NativeTransactionPosition } from "@interest-protocol/blast-core/events";
100
-
101
- export type PackagePublicationFact = {
102
- source: "transactionEffects";
103
- kind: "packagePublication";
104
- position: NativeTransactionPosition;
105
- packageId: string;
106
- createdObjectIds: readonly string[];
107
- };
108
-
109
- export type CreatorCapOwnershipFact = {
110
- source: "objectOwnership";
111
- kind: "creatorCapOwnership";
112
- checkpoint: bigint;
113
- creatorCapId: string;
114
- owner: string;
115
- };
116
-
117
- /** A coin a claim returned and where its transaction sent it. */
118
- export type ReturnedCoin = { objectId: string; recipient: string };
119
-
120
- /** The coins one claim returned: a launch protocol claim also returns Blast's SUI. */
121
- export type ReturnedCoinRecipientsFact = {
122
- source: "transactionEffects";
123
- kind: "returnedCoinRecipients";
124
- position: NativeTransactionPosition;
125
- memeCoin: ReturnedCoin;
126
- quoteCoin: ReturnedCoin;
127
- } & (
128
- | { claim: "launchCreatorFees" | "lpCreatorFees" | "lpProtocolFees" }
129
- | { claim: "launchProtocolFees"; suiCoin: ReturnedCoin }
130
- );
131
-
132
- export type NativeReconstructionFact =
133
- | PackagePublicationFact
134
- | CreatorCapOwnershipFact
135
- | ReturnedCoinRecipientsFact;
136
-
137
- export type NativeFactProjection = {
138
- appliedFactIds: Readonly<Record<string, true>>;
139
- packagePublications: Readonly<Record<string, PackagePublicationFact>>;
140
- creatorCapOwners: Readonly<
141
- Record<
142
- string,
143
- { source: "objectOwnership"; checkpoint: bigint; owner: string }
144
- >
145
- >;
146
- returnedCoinRecipients: Readonly<Record<string, ReturnedCoinRecipientsFact>>;
147
- };
12
+ /** A Meme's recorded Bluefin tier. */
13
+ export type BluefinReservation = BluefinPoolTier & { quoteType: string };
148
14
 
149
- export type LaunchpadProductProjection = {
150
- launchpad: LaunchpadEventProjection;
151
- migrators: MigratorEventProjection;
152
- native: NativeFactProjection;
15
+ /**
16
+ * The `VenueConfig` records rebuilt from `blast_migrators` events, by Meme
17
+ * type. Each venue keys its own records, so `cetus` and `bluefin` match
18
+ * `getCetusPoolTier`/`getCetusPoolCreationCapId` and `getBluefinPoolTier`
19
+ * once every event is applied.
20
+ */
21
+ export type VenueReservationProjection = {
22
+ appliedEventIds: Readonly<Record<string, true>>;
23
+ cetus: Readonly<Record<string, CetusReservation>>;
24
+ bluefin: Readonly<Record<string, BluefinReservation>>;
153
25
  };
154
26
 
155
- export type LaunchpadProductInput =
156
- | DecodedLaunchpadEvent
157
- | DecodedMigratorEvent
158
- | NativeReconstructionFact;
159
-
160
- export function createMigratorEventProjection(): MigratorEventProjection {
161
- return {
162
- appliedEventIds: {},
163
- eventCounts: Object.fromEntries(
164
- Object.keys(migratorEventSpecs).map((kind) => [kind, 0]),
165
- ) as Record<MigratorEventKind, number>,
166
- vaults: {},
167
- rounds: {},
168
- lpFeePolicy: {
169
- defaultShares: { memeBps: 0n, quoteBps: 0n },
170
- coinShares: {},
171
- protocolDestination: null,
172
- },
173
- cetusPoolReservations: {},
174
- };
175
- }
176
-
177
- export function createLaunchpadProductProjection(): LaunchpadProductProjection {
178
- return {
179
- launchpad: createLaunchpadEventProjection(),
180
- migrators: createMigratorEventProjection(),
181
- native: {
182
- appliedFactIds: {},
183
- packagePublications: {},
184
- creatorCapOwners: {},
185
- returnedCoinRecipients: {},
186
- },
187
- };
27
+ export function createVenueReservationProjection(): VenueReservationProjection {
28
+ return { appliedEventIds: {}, cetus: {}, bluefin: {} };
188
29
  }
189
30
 
190
- export function reduceMigratorEvent(
191
- state: MigratorEventProjection,
192
- event: DecodedMigratorEvent,
193
- ): MigratorEventProjection {
194
- const eventId = migratorEventId(event);
31
+ /** Applies one event once; replaying an applied event returns `state` unchanged. */
32
+ export function reduceVenueReservationEvent(
33
+ state: VenueReservationProjection,
34
+ event: DecodedMigratorsEvent,
35
+ ): VenueReservationProjection {
36
+ const eventId = suiEventId(event.position);
195
37
  if (state.appliedEventIds[eventId]) return state;
196
- const next: MigratorEventProjection = {
197
- ...state,
198
- appliedEventIds: { ...state.appliedEventIds, [eventId]: true },
199
- eventCounts: {
200
- ...state.eventCounts,
201
- [event.kind]: state.eventCounts[event.kind] + 1,
202
- },
38
+ const appliedEventIds = {
39
+ ...state.appliedEventIds,
40
+ [eventId]: true as const,
203
41
  };
204
-
205
42
  switch (event.kind) {
206
- case "VaultCreated": {
207
- const payload = event.payload;
208
- return {
209
- ...next,
210
- vaults: {
211
- ...state.vaults,
212
- [payload.vault_id]: {
213
- vaultId: payload.vault_id,
214
- launchId: null,
215
- poolId: payload.pool_id,
216
- positionId: payload.position_id,
217
- autoLpPositionId: null,
218
- venueType: payload.venue,
219
- memeType: payload.meme,
220
- quoteType: payload.quote,
221
- feeSplit: payload.fee_split,
222
- creatorMeme: 0n,
223
- creatorQuote: 0n,
224
- autoLpMeme: 0n,
225
- autoLpQuote: 0n,
226
- rewardsMeme: 0n,
227
- rewardsQuote: 0n,
228
- burnQuote: 0n,
229
- protocolMemeResidual: payload.residual_meme,
230
- protocolQuoteResidual: payload.residual_quote,
231
- liquidity: payload.liquidity,
232
- nextRound: 0n,
233
- lastCheckpoint: null,
234
- protocolMemePaid: 0n,
235
- protocolQuotePaid: 0n,
236
- protocolMemeHeld: 0n,
237
- protocolQuoteHeld: 0n,
238
- partnerMemePaid: 0n,
239
- partnerQuotePaid: 0n,
240
- },
241
- },
242
- };
243
- }
244
- case "FeesCollected": {
245
- const payload = event.payload;
246
- return updateVault(next, payload.vault_id, (vault) => ({
247
- ...vault,
248
- creatorMeme: vault.creatorMeme + payload.creator_meme,
249
- creatorQuote: vault.creatorQuote + payload.creator_quote,
250
- autoLpMeme: vault.autoLpMeme + payload.auto_lp_meme,
251
- autoLpQuote: vault.autoLpQuote + payload.auto_lp_quote,
252
- rewardsMeme: vault.rewardsMeme + payload.rewards_meme,
253
- rewardsQuote: vault.rewardsQuote + payload.rewards_quote,
254
- burnQuote: vault.burnQuote + payload.burn_quote,
255
- // A partnered vault holds Blast's share: no destination was paid.
256
- ...(payload.protocol_destination === null
257
- ? {
258
- protocolMemeHeld: vault.protocolMemeHeld + payload.protocol_meme,
259
- protocolQuoteHeld:
260
- vault.protocolQuoteHeld + payload.protocol_quote,
261
- }
262
- : {
263
- protocolMemePaid: vault.protocolMemePaid + payload.protocol_meme,
264
- protocolQuotePaid:
265
- vault.protocolQuotePaid + payload.protocol_quote,
266
- }),
267
- }));
268
- }
269
- case "ProtocolLpFeesClaimed": {
270
- const payload = event.payload;
271
- return updateVault(next, payload.vault_id, (vault) => ({
272
- ...vault,
273
- protocolMemeHeld: 0n,
274
- protocolQuoteHeld: 0n,
275
- protocolMemePaid: vault.protocolMemePaid + payload.protocol_meme,
276
- protocolQuotePaid: vault.protocolQuotePaid + payload.protocol_quote,
277
- partnerMemePaid: vault.partnerMemePaid + payload.partner_meme,
278
- partnerQuotePaid: vault.partnerQuotePaid + payload.partner_quote,
279
- }));
280
- }
281
- case "AutoLiquidityAdded": {
282
- const payload = event.payload;
283
- return updateVault(next, payload.vault_id, (vault) => ({
284
- ...vault,
285
- autoLpMeme: payload.meme_pending,
286
- autoLpQuote: payload.quote_pending,
287
- }));
288
- }
289
- case "BuybackBurned": {
290
- const payload = event.payload;
291
- return updateVault(next, payload.vault_id, (vault) => ({
292
- ...vault,
293
- burnQuote: payload.quote_pending,
294
- }));
295
- }
296
- case "AutoLpPositionOpened": {
297
- const payload = event.payload;
298
- return updateVault(next, payload.vault_id, (vault) => ({
299
- ...vault,
300
- autoLpPositionId: payload.position_id,
301
- }));
302
- }
303
- case "FeeSplitChanged": {
304
- const payload = event.payload;
305
- return updateVault(next, payload.vault_id, (vault) => ({
306
- ...vault,
307
- feeSplit: payload.new_fee_split,
308
- }));
309
- }
310
- case "CreatorFeesClaimed":
311
- return updateVault(next, event.payload.vault_id, (vault) => ({
312
- ...vault,
313
- creatorMeme: 0n,
314
- creatorQuote: 0n,
315
- }));
316
- case "ProtocolFeesClaimed":
317
- return updateVault(next, event.payload.vault_id, (vault) => ({
318
- ...vault,
319
- protocolMemeResidual: 0n,
320
- protocolQuoteResidual: 0n,
321
- }));
322
- case "RoundPublished": {
323
- const payload = event.payload;
324
- const updated = updateVault(next, payload.vault_id, (vault) => ({
325
- ...vault,
326
- rewardsMeme: payload.meme_unallocated,
327
- rewardsQuote: payload.quote_unallocated,
328
- nextRound: payload.number + 1n,
329
- lastCheckpoint: payload.end_checkpoint,
330
- }));
331
- return {
332
- ...updated,
333
- rounds: {
334
- ...state.rounds,
335
- [payload.round_id]: {
336
- roundId: payload.round_id,
337
- vaultId: payload.vault_id,
338
- number: payload.number,
339
- startCheckpoint: payload.start_checkpoint,
340
- endCheckpoint: payload.end_checkpoint,
341
- root: toHex(payload.root),
342
- manifestDigest: toHex(payload.manifest_digest),
343
- leafCount: payload.leaf_count,
344
- memeRemaining: payload.meme_amount,
345
- quoteRemaining: payload.quote_amount,
346
- paidIndexes: {},
347
- },
348
- },
349
- };
350
- }
351
- case "RewardPaid": {
352
- const payload = event.payload;
353
- const round = state.rounds[payload.round_id];
354
- if (!round) return next;
355
- return {
356
- ...next,
357
- rounds: {
358
- ...state.rounds,
359
- [payload.round_id]: {
360
- ...round,
361
- memeRemaining: payload.meme_remaining,
362
- quoteRemaining: payload.quote_remaining,
363
- paidIndexes: {
364
- ...round.paidIndexes,
365
- [payload.index.toString()]: true,
366
- },
367
- },
368
- },
369
- };
370
- }
371
- case "LpFeePolicyChanged": {
372
- const payload = event.payload;
373
- const pair =
374
- payload.new_meme_bps === null || payload.new_quote_bps === null
375
- ? null
376
- : { memeBps: payload.new_meme_bps, quoteBps: payload.new_quote_bps };
377
- if (payload.meme === null) {
378
- if (!pair) return next;
379
- return {
380
- ...next,
381
- lpFeePolicy: { ...state.lpFeePolicy, defaultShares: pair },
382
- };
383
- }
384
- const coinShares = { ...state.lpFeePolicy.coinShares };
385
- if (pair) coinShares[payload.meme] = pair;
386
- else delete coinShares[payload.meme];
387
- return { ...next, lpFeePolicy: { ...state.lpFeePolicy, coinShares } };
388
- }
389
- case "LpFeeDestinationChanged":
390
- return {
391
- ...next,
392
- lpFeePolicy: {
393
- ...state.lpFeePolicy,
394
- protocolDestination: event.payload.new_destination,
395
- },
396
- };
397
- case "CetusPoolReserved": {
398
- const payload = event.payload;
43
+ case "CetusPoolReserved":
399
44
  return {
400
- ...next,
401
- cetusPoolReservations: {
402
- ...state.cetusPoolReservations,
403
- [payload.meme]: {
404
- memeType: payload.meme,
405
- quoteType: payload.quote,
406
- poolCreationCapId: payload.pool_creation_cap_id,
407
- tickSpacing: payload.tick_spacing,
45
+ ...state,
46
+ appliedEventIds,
47
+ cetus: {
48
+ ...state.cetus,
49
+ [event.memeType]: {
50
+ quoteType: event.quoteType,
51
+ poolCreationCapId: event.payload.pool_creation_cap_id,
52
+ tickSpacing: event.payload.tick_spacing,
408
53
  },
409
54
  },
410
55
  };
411
- }
412
- }
413
- }
414
-
415
- export function reduceLaunchpadProductInput(
416
- state: LaunchpadProductProjection,
417
- input: LaunchpadProductInput,
418
- ): LaunchpadProductProjection {
419
- if (input.source === "launchpad") {
420
- const launchpad = reduceLaunchpadEvent(state.launchpad, input);
421
- return launchpad === state.launchpad ? state : { ...state, launchpad };
422
- }
423
- if (input.source === "migrators") {
424
- const migrators = reduceMigratorEvent(state.migrators, input);
425
- if (migrators === state.migrators) return state;
426
- if (input.kind !== "VaultCreated") return { ...state, migrators };
427
- return {
428
- ...state,
429
- migrators: linkVaultLaunch(migrators, state.launchpad, input.payload),
430
- };
431
- }
432
- const native = reduceNativeFact(state.native, input);
433
- return native === state.native ? state : { ...state, native };
434
- }
435
-
436
- function reduceNativeFact(
437
- state: NativeFactProjection,
438
- fact: NativeReconstructionFact,
439
- ): NativeFactProjection {
440
- const normalized = normalizeNativeFact(fact);
441
- const factId = nativeFactId(normalized);
442
- if (state.appliedFactIds[factId]) return state;
443
- const next = {
444
- ...state,
445
- appliedFactIds: { ...state.appliedFactIds, [factId]: true as const },
446
- };
447
-
448
- switch (normalized.kind) {
449
- case "packagePublication":
56
+ case "BluefinPoolTierRecorded":
450
57
  return {
451
- ...next,
452
- packagePublications: {
453
- ...state.packagePublications,
454
- [normalized.packageId]: normalized,
455
- },
456
- };
457
- case "creatorCapOwnership":
458
- return {
459
- ...next,
460
- creatorCapOwners: {
461
- ...state.creatorCapOwners,
462
- [normalized.creatorCapId]: {
463
- source: "objectOwnership",
464
- checkpoint: normalized.checkpoint,
465
- owner: normalized.owner,
58
+ ...state,
59
+ appliedEventIds,
60
+ bluefin: {
61
+ ...state.bluefin,
62
+ [event.memeType]: {
63
+ quoteType: event.quoteType,
64
+ tickSpacing: event.payload.tick_spacing,
65
+ feeRate: event.payload.fee_rate,
466
66
  },
467
67
  },
468
68
  };
469
- case "returnedCoinRecipients":
470
- return {
471
- ...next,
472
- returnedCoinRecipients: {
473
- ...state.returnedCoinRecipients,
474
- [factId]: normalized,
475
- },
476
- };
477
- }
478
- }
479
-
480
- /**
481
- * The migration transaction migrates the launch (`Migrated`) before it
482
- * attaches the vault (`VaultCreated`). One launch exists per Meme type, so the
483
- * launch of the vault's Meme type is the vault's launch.
484
- */
485
- function linkVaultLaunch(
486
- state: MigratorEventProjection,
487
- launchpad: LaunchpadEventProjection,
488
- payload: Extract<DecodedMigratorEvent, { kind: "VaultCreated" }>["payload"],
489
- ): MigratorEventProjection {
490
- const launch = Object.values(launchpad.launches).find(
491
- (candidate) =>
492
- candidate.memeType === payload.meme &&
493
- candidate.quoteType === payload.quote,
494
- );
495
- if (!launch) return state;
496
- return updateVault(state, payload.vault_id, (current) => ({
497
- ...current,
498
- launchId: launch.launchId,
499
- }));
500
- }
501
-
502
- function updateVault(
503
- state: MigratorEventProjection,
504
- vaultId: string,
505
- update: (vault: LpVaultEventProjection) => LpVaultEventProjection,
506
- ): MigratorEventProjection {
507
- const vault = state.vaults[vaultId];
508
- if (!vault) return state;
509
- return { ...state, vaults: { ...state.vaults, [vaultId]: update(vault) } };
510
- }
511
-
512
- function normalizeNativeFact(
513
- fact: NativeReconstructionFact,
514
- ): NativeReconstructionFact {
515
- if (fact.kind === "creatorCapOwnership") {
516
- requireU64("creator-cap ownership checkpoint", fact.checkpoint);
517
- return {
518
- ...fact,
519
- creatorCapId: normalizeSuiObjectId(fact.creatorCapId),
520
- owner: normalizeSuiAddress(fact.owner),
521
- };
522
- }
523
- const position = normalizeNativeTransactionPosition(
524
- fact.position,
525
- "native fact",
526
- );
527
- if (fact.kind === "packagePublication") {
528
- return {
529
- ...fact,
530
- position,
531
- packageId: normalizeSuiObjectId(fact.packageId),
532
- createdObjectIds: fact.createdObjectIds.map((id) =>
533
- normalizeSuiObjectId(id),
534
- ),
535
- };
536
- }
537
- const coins = {
538
- position,
539
- memeCoin: normalizeReturnedCoin(fact.memeCoin),
540
- quoteCoin: normalizeReturnedCoin(fact.quoteCoin),
541
- };
542
- return fact.claim === "launchProtocolFees"
543
- ? { ...fact, ...coins, suiCoin: normalizeReturnedCoin(fact.suiCoin) }
544
- : { ...fact, ...coins };
545
- }
546
-
547
- function normalizeReturnedCoin(coin: ReturnedCoin): ReturnedCoin {
548
- return {
549
- objectId: normalizeSuiObjectId(coin.objectId),
550
- recipient: normalizeSuiAddress(coin.recipient),
551
- };
552
- }
553
-
554
- function nativeFactId(fact: NativeReconstructionFact): string {
555
- if (fact.kind === "creatorCapOwnership") {
556
- return `${fact.checkpoint}:ownership:${fact.creatorCapId}`;
557
- }
558
- if (fact.kind === "returnedCoinRecipients") {
559
- return `${fact.position.transactionDigest}:${fact.kind}:${fact.memeCoin.objectId}:${fact.quoteCoin.objectId}`;
560
69
  }
561
- return `${fact.position.transactionDigest}:${fact.kind}:${fact.packageId}`;
562
70
  }