@clayno-club/asset-flow 0.2.0 → 0.2.1
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 +115 -20
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -3202,6 +3202,90 @@ function parseSwapParticipants(swapEvent, assetId) {
|
|
|
3202
3202
|
toAddress: counterparty
|
|
3203
3203
|
};
|
|
3204
3204
|
}
|
|
3205
|
+
function parseListingSeller(event) {
|
|
3206
|
+
if (!event || typeof event.parsedJson !== "object" || event.parsedJson === null) {
|
|
3207
|
+
return null;
|
|
3208
|
+
}
|
|
3209
|
+
return getString(event.parsedJson.seller);
|
|
3210
|
+
}
|
|
3211
|
+
function getObjectChangeById(tx, objectId) {
|
|
3212
|
+
const matches = (tx.objectChanges ?? []).filter((change) => change.objectId === objectId);
|
|
3213
|
+
return matches[matches.length - 1] ?? null;
|
|
3214
|
+
}
|
|
3215
|
+
function resolveKioskOwnerAddress(tx, options = {}) {
|
|
3216
|
+
const ownerCapChanges = (tx.objectChanges ?? []).filter(
|
|
3217
|
+
(change) => getString(change.objectType)?.endsWith("::kiosk::KioskOwnerCap")
|
|
3218
|
+
);
|
|
3219
|
+
if (options.preferCreated) {
|
|
3220
|
+
const createdOwners = [
|
|
3221
|
+
...new Set(
|
|
3222
|
+
ownerCapChanges.filter((change) => change.type === "created").flatMap((change) => {
|
|
3223
|
+
const owner = normalizeOwnerRef(change.owner ?? change.recipient);
|
|
3224
|
+
return owner?.kind === "address" ? [owner.value] : [];
|
|
3225
|
+
})
|
|
3226
|
+
)
|
|
3227
|
+
];
|
|
3228
|
+
if (createdOwners.length === 1) {
|
|
3229
|
+
return createdOwners[0];
|
|
3230
|
+
}
|
|
3231
|
+
}
|
|
3232
|
+
const addressOwners = [
|
|
3233
|
+
...new Set(
|
|
3234
|
+
ownerCapChanges.flatMap((change) => {
|
|
3235
|
+
const owner = normalizeOwnerRef(change.owner ?? change.recipient);
|
|
3236
|
+
return owner?.kind === "address" ? [owner.value] : [];
|
|
3237
|
+
})
|
|
3238
|
+
)
|
|
3239
|
+
];
|
|
3240
|
+
return addressOwners.length === 1 ? addressOwners[0] : null;
|
|
3241
|
+
}
|
|
3242
|
+
function resolveAddressOwnerFromObjectChain(tx, rootObjectId) {
|
|
3243
|
+
const visited = /* @__PURE__ */ new Set();
|
|
3244
|
+
let currentObjectId = rootObjectId;
|
|
3245
|
+
while (currentObjectId && !visited.has(currentObjectId)) {
|
|
3246
|
+
visited.add(currentObjectId);
|
|
3247
|
+
const change = getObjectChangeById(tx, currentObjectId);
|
|
3248
|
+
if (!change) {
|
|
3249
|
+
return null;
|
|
3250
|
+
}
|
|
3251
|
+
if (getString(change.objectType)?.endsWith("::kiosk::Kiosk")) {
|
|
3252
|
+
return resolveKioskOwnerAddress(tx, {
|
|
3253
|
+
preferCreated: change.type === "created"
|
|
3254
|
+
});
|
|
3255
|
+
}
|
|
3256
|
+
const owner = normalizeOwnerRef(change.owner ?? change.recipient);
|
|
3257
|
+
if (!owner) {
|
|
3258
|
+
return null;
|
|
3259
|
+
}
|
|
3260
|
+
if (owner.kind === "address") {
|
|
3261
|
+
return owner.value;
|
|
3262
|
+
}
|
|
3263
|
+
if (owner.kind === "object") {
|
|
3264
|
+
currentObjectId = owner.value;
|
|
3265
|
+
continue;
|
|
3266
|
+
}
|
|
3267
|
+
if (owner.kind === "shared") {
|
|
3268
|
+
return resolveKioskOwnerAddress(tx);
|
|
3269
|
+
}
|
|
3270
|
+
return null;
|
|
3271
|
+
}
|
|
3272
|
+
return null;
|
|
3273
|
+
}
|
|
3274
|
+
function resolveNextBeneficialOwner(tx, ownerChange) {
|
|
3275
|
+
if (!ownerChange?.nextOwner) {
|
|
3276
|
+
return null;
|
|
3277
|
+
}
|
|
3278
|
+
if (ownerChange.nextOwner.kind === "address") {
|
|
3279
|
+
return ownerChange.nextOwner.value;
|
|
3280
|
+
}
|
|
3281
|
+
if (ownerChange.nextOwner.kind === "object") {
|
|
3282
|
+
return resolveAddressOwnerFromObjectChain(tx, ownerChange.nextOwner.value);
|
|
3283
|
+
}
|
|
3284
|
+
if (ownerChange.nextOwner.kind === "shared") {
|
|
3285
|
+
return resolveKioskOwnerAddress(tx);
|
|
3286
|
+
}
|
|
3287
|
+
return null;
|
|
3288
|
+
}
|
|
3205
3289
|
function sortTransactions(transactions) {
|
|
3206
3290
|
return [...transactions].sort((left, right) => {
|
|
3207
3291
|
const leftTime = Number(left.timestampMs ?? 0) || 0;
|
|
@@ -3237,20 +3321,20 @@ function buildFlow2(tx, timestamp, params) {
|
|
|
3237
3321
|
source: "sui",
|
|
3238
3322
|
fromAddress: params.fromAddress,
|
|
3239
3323
|
toAddress: params.toAddress,
|
|
3240
|
-
transferIndex: 0,
|
|
3324
|
+
transferIndex: params.transferIndex ?? 0,
|
|
3241
3325
|
tokenStandard: null,
|
|
3242
3326
|
derivedType: params.derivedType
|
|
3243
3327
|
};
|
|
3244
3328
|
}
|
|
3245
|
-
function
|
|
3329
|
+
function buildSuiFlows(tx, assetId, classification2, currentBeneficialOwner) {
|
|
3246
3330
|
if (classification2.materialization !== "PERSIST_FLOW") {
|
|
3247
|
-
return
|
|
3331
|
+
return [];
|
|
3248
3332
|
}
|
|
3249
3333
|
const timestamp = resolveTimestamp(tx);
|
|
3250
3334
|
const assetEvents = getAssetEvents(tx, assetId);
|
|
3251
3335
|
const ownerChange = getAssetOwnerChangeDetails(tx, assetId);
|
|
3252
3336
|
const sender = getString(tx.transaction?.data?.sender) ?? ownerChange?.sender ?? null;
|
|
3253
|
-
const addressOwner = ownerChange?.nextOwner?.kind === "address" ? ownerChange.nextOwner.value : null;
|
|
3337
|
+
const addressOwner = (ownerChange?.nextOwner?.kind === "address" ? ownerChange.nextOwner.value : null) ?? resolveNextBeneficialOwner(tx, ownerChange);
|
|
3254
3338
|
let fromAddress = null;
|
|
3255
3339
|
let toAddress = null;
|
|
3256
3340
|
switch (classification2.derivedType) {
|
|
@@ -3264,7 +3348,7 @@ function buildSuiFlow(tx, assetId, classification2, currentBeneficialOwner) {
|
|
|
3264
3348
|
TRADEPORT_KIOSK_BUY_EVENT_SUFFIX
|
|
3265
3349
|
]);
|
|
3266
3350
|
const sale = parseSaleParticipants(saleEvent);
|
|
3267
|
-
fromAddress = sale.seller ??
|
|
3351
|
+
fromAddress = currentBeneficialOwner ?? sale.seller ?? sender ?? null;
|
|
3268
3352
|
toAddress = sale.buyer ?? addressOwner ?? sender ?? null;
|
|
3269
3353
|
break;
|
|
3270
3354
|
}
|
|
@@ -3277,10 +3361,11 @@ function buildSuiFlow(tx, assetId, classification2, currentBeneficialOwner) {
|
|
|
3277
3361
|
}
|
|
3278
3362
|
case "TRANSFER":
|
|
3279
3363
|
fromAddress = currentBeneficialOwner ?? sender ?? null;
|
|
3280
|
-
toAddress = addressOwner ?? (ownerChange?.nextOwner?.kind === "object" ?
|
|
3364
|
+
toAddress = addressOwner ?? (ownerChange?.nextOwner?.kind === "object" ? sender ?? currentBeneficialOwner ?? null : sender ?? null);
|
|
3281
3365
|
break;
|
|
3282
3366
|
case "LIST": {
|
|
3283
|
-
const
|
|
3367
|
+
const listingEvent = findFirstEvent(assetEvents, [TRADEPORT_ADD_LISTING_EVENT_SUFFIX, KIOSK_LIST_EVENT_SUFFIX]);
|
|
3368
|
+
const owner = parseListingSeller(listingEvent) ?? currentBeneficialOwner ?? sender ?? addressOwner;
|
|
3284
3369
|
fromAddress = owner;
|
|
3285
3370
|
toAddress = owner;
|
|
3286
3371
|
break;
|
|
@@ -3288,7 +3373,12 @@ function buildSuiFlow(tx, assetId, classification2, currentBeneficialOwner) {
|
|
|
3288
3373
|
case "DELIST":
|
|
3289
3374
|
case "LOCK":
|
|
3290
3375
|
case "UNLOCK": {
|
|
3291
|
-
const
|
|
3376
|
+
const delistEvent = classification2.derivedType === "DELIST" ? findFirstEvent(assetEvents, [
|
|
3377
|
+
TRADEPORT_CANCEL_SIMPLE_EVENT_SUFFIX,
|
|
3378
|
+
TRADEPORT_REMOVE_LISTING_EVENT_SUFFIX,
|
|
3379
|
+
KIOSK_UNLIST_EVENT_SUFFIX
|
|
3380
|
+
]) : null;
|
|
3381
|
+
const owner = parseListingSeller(delistEvent) ?? addressOwner ?? sender ?? currentBeneficialOwner;
|
|
3292
3382
|
if (owner && currentBeneficialOwner && owner !== currentBeneficialOwner) {
|
|
3293
3383
|
fromAddress = currentBeneficialOwner;
|
|
3294
3384
|
toAddress = owner;
|
|
@@ -3300,13 +3390,15 @@ function buildSuiFlow(tx, assetId, classification2, currentBeneficialOwner) {
|
|
|
3300
3390
|
break;
|
|
3301
3391
|
}
|
|
3302
3392
|
default:
|
|
3303
|
-
return
|
|
3393
|
+
return [];
|
|
3304
3394
|
}
|
|
3305
|
-
return
|
|
3306
|
-
|
|
3307
|
-
|
|
3308
|
-
|
|
3309
|
-
|
|
3395
|
+
return [
|
|
3396
|
+
buildFlow2(tx, timestamp, {
|
|
3397
|
+
fromAddress,
|
|
3398
|
+
toAddress,
|
|
3399
|
+
derivedType: classification2.derivedType
|
|
3400
|
+
})
|
|
3401
|
+
];
|
|
3310
3402
|
}
|
|
3311
3403
|
function extractAssetFlows(transactions, assetId, classificationCache = /* @__PURE__ */ new Map()) {
|
|
3312
3404
|
const flows = [];
|
|
@@ -3314,14 +3406,17 @@ function extractAssetFlows(transactions, assetId, classificationCache = /* @__PU
|
|
|
3314
3406
|
for (const tx of sortTransactions(transactions)) {
|
|
3315
3407
|
const classification2 = classificationCache.get(tx.digest) ?? classifySuiTransactionForAsset(tx, assetId);
|
|
3316
3408
|
classificationCache.set(tx.digest, classification2);
|
|
3317
|
-
const
|
|
3318
|
-
if (
|
|
3409
|
+
const txFlows = buildSuiFlows(tx, assetId, classification2, currentBeneficialOwner);
|
|
3410
|
+
if (txFlows.length === 0) {
|
|
3319
3411
|
continue;
|
|
3320
3412
|
}
|
|
3321
|
-
|
|
3322
|
-
|
|
3323
|
-
|
|
3324
|
-
|
|
3413
|
+
txFlows.forEach((flow, index) => {
|
|
3414
|
+
flow.transferIndex = index;
|
|
3415
|
+
flows.push(flow);
|
|
3416
|
+
if (flow.toAddress && (flow.derivedType === "MINT" || flow.derivedType === "TRANSFER" || flow.derivedType === "SALE" || flow.derivedType === "SWAP" || flow.derivedType === "FORECLOSURE") && flow.toAddress !== currentBeneficialOwner) {
|
|
3417
|
+
currentBeneficialOwner = flow.toAddress;
|
|
3418
|
+
}
|
|
3419
|
+
});
|
|
3325
3420
|
}
|
|
3326
3421
|
return collapseRedundantCustodyFlows(canonicalizeMintFlows(flows));
|
|
3327
3422
|
}
|